From 57ba96e291a055f69dbfd4ae9f1ae2390e36986e Mon Sep 17 00:00:00 2001 From: Roman Moravcik Date: Thu, 23 Jun 2011 13:51:54 +0200 Subject: [PATCH] Added gst-plugins-base-subtitles0.10-0.10.34 for Meego Harmattan 1.2 --- gst-plugins-base-subtitles0.10/.gitignore | 51 + gst-plugins-base-subtitles0.10/.gitmodules | 3 + gst-plugins-base-subtitles0.10/AUTHORS | 23 + gst-plugins-base-subtitles0.10/Android.mk | 125 + gst-plugins-base-subtitles0.10/COPYING | 340 + gst-plugins-base-subtitles0.10/COPYING.LIB | 481 + gst-plugins-base-subtitles0.10/ChangeLog |49339 ++++++++++++++++++++ gst-plugins-base-subtitles0.10/INSTALL | 182 + gst-plugins-base-subtitles0.10/LICENSE_readme | 137 + gst-plugins-base-subtitles0.10/MAINTAINERS | 13 + gst-plugins-base-subtitles0.10/Makefile.am | 84 + gst-plugins-base-subtitles0.10/NEWS | 2233 + gst-plugins-base-subtitles0.10/README | 247 + gst-plugins-base-subtitles0.10/RELEASE | 90 + gst-plugins-base-subtitles0.10/REQUIREMENTS | 105 + gst-plugins-base-subtitles0.10/android/NOTICE | 481 + gst-plugins-base-subtitles0.10/android/alsa.mk | 50 + gst-plugins-base-subtitles0.10/android/app.mk | 43 + .../android/app_plugin.mk | 34 + gst-plugins-base-subtitles0.10/android/audio.mk | 63 + .../android/audioconvert.mk | 40 + .../android/audioresample.mk | 38 + .../android/audiotestsrc.mk | 35 + .../android/decodebin.mk | 35 + .../android/decodebin2.mk | 37 + .../android/ffmpegcolorspace.mk | 40 + gst-plugins-base-subtitles0.10/android/gdp.mk | 36 + .../android/interfaces.mk | 70 + .../android/netbuffer.mk | 38 + gst-plugins-base-subtitles0.10/android/pbutils.mk | 68 + gst-plugins-base-subtitles0.10/android/playbin.mk | 45 + gst-plugins-base-subtitles0.10/android/queue2.mk | 35 + gst-plugins-base-subtitles0.10/android/riff.mk | 45 + gst-plugins-base-subtitles0.10/android/rtp.mk | 48 + gst-plugins-base-subtitles0.10/android/rtsp.mk | 58 + gst-plugins-base-subtitles0.10/android/sdp.mk | 38 + gst-plugins-base-subtitles0.10/android/tag.mk | 46 + gst-plugins-base-subtitles0.10/android/tcp.mk | 42 + .../android/typefindfunctions.mk | 34 + gst-plugins-base-subtitles0.10/android/video.mk | 47 + .../android/videoscale.mk | 40 + .../android/videotestsrc.mk | 38 + gst-plugins-base-subtitles0.10/autogen.sh | 104 + gst-plugins-base-subtitles0.10/common/.gitignore | 3 + gst-plugins-base-subtitles0.10/common/ChangeLog | 1712 + gst-plugins-base-subtitles0.10/common/Makefile.am | 22 + gst-plugins-base-subtitles0.10/common/c-to-xml.py | 34 + .../common/check-exports | 72 + gst-plugins-base-subtitles0.10/common/check.mak | 181 + .../common/coverage/coverage-report-entry.pl | 69 + .../common/coverage/coverage-report.pl | 125 + .../common/coverage/coverage-report.xsl | 235 + .../common/coverage/lcov.mak | 43 + gst-plugins-base-subtitles0.10/common/cruft.mak | 56 + .../common/download-translations | 152 + .../common/extract-release-date-from-doap-file | 32 + .../common/gen-changelog.py | 99 + .../common/gettext.patch | 12 + gst-plugins-base-subtitles0.10/common/glib-gen.mak | 44 + .../common/gst-autogen.sh | 376 + .../common/gst-glib-gen.mak | 45 + gst-plugins-base-subtitles0.10/common/gst-indent | 49 + gst-plugins-base-subtitles0.10/common/gst.supp | 3929 ++ .../common/gstdoc-scangobj | 1571 + .../common/gtk-doc-plugins.mak | 379 + gst-plugins-base-subtitles0.10/common/gtk-doc.mak | 234 + .../common/hooks/post-receive.hook | 290 + .../common/hooks/pre-commit.hook | 77 + .../common/hooks/pre-receive.hook | 95 + .../common/m4/.gitignore | 23 + .../common/m4/Makefile.am | 42 + gst-plugins-base-subtitles0.10/common/m4/README | 3 + .../common/m4/as-ac-expand.m4 | 43 + .../common/m4/as-auto-alt.m4 | 50 + .../common/m4/as-compiler-flag.m4 | 64 + .../common/m4/as-compiler.m4 | 44 + .../common/m4/as-docbook.m4 | 66 + .../common/m4/as-gcc-inline-assembly.m4 | 52 + .../common/m4/as-libtool-tags.m4 | 83 + .../common/m4/as-libtool.m4 | 45 + .../common/m4/as-objc.m4 | 56 + .../common/m4/as-python.m4 | 152 + .../common/m4/as-scrub-include.m4 | 36 + .../common/m4/as-version.m4 | 75 + .../common/m4/ax_create_stdint_h.m4 | 734 + gst-plugins-base-subtitles0.10/common/m4/check.m4 | 181 + .../common/m4/glib-gettext.m4 | 432 + .../common/m4/gst-arch.m4 | 141 + .../common/m4/gst-args.m4 | 330 + .../common/m4/gst-check.m4 | 262 + .../common/m4/gst-debuginfo.m4 | 46 + .../common/m4/gst-default.m4 | 120 + .../common/m4/gst-doc.m4 | 148 + .../common/m4/gst-dowhile.m4 | 24 + .../common/m4/gst-error.m4 | 213 + .../common/m4/gst-feature.m4 | 283 + .../common/m4/gst-function.m4 | 63 + .../common/m4/gst-gettext.m4 | 21 + .../common/m4/gst-glib2.m4 | 73 + .../common/m4/gst-libxml2.m4 | 52 + .../common/m4/gst-package-release-datetime.m4 | 89 + .../common/m4/gst-parser.m4 | 55 + .../common/m4/gst-platform.m4 | 67 + .../common/m4/gst-plugin-docs.m4 | 21 + .../common/m4/gst-plugindir.m4 | 17 + .../common/m4/gst-valgrind.m4 | 35 + .../common/m4/gst-x11.m4 | 70 + gst-plugins-base-subtitles0.10/common/m4/gst.m4 | 31 + .../common/m4/gtk-doc.m4 | 42 + .../common/m4/introspection.m4 | 88 + gst-plugins-base-subtitles0.10/common/m4/orc.m4 | 68 + gst-plugins-base-subtitles0.10/common/m4/pkg.m4 | 157 + .../common/mangle-tmpl.py | 163 + gst-plugins-base-subtitles0.10/common/orc.mak | 76 + .../common/parallel-subdirs.mak | 13 + gst-plugins-base-subtitles0.10/common/plugins.xsl | 209 + gst-plugins-base-subtitles0.10/common/po.mak | 4 + gst-plugins-base-subtitles0.10/common/release.mak | 25 + .../common/scangobj-merge.py | 280 + .../common/update-common | 65 + .../common/upload-doc.mak | 66 + gst-plugins-base-subtitles0.10/common/win32.mak | 72 + gst-plugins-base-subtitles0.10/configure.ac | 1080 + .../debian/HACKING.Debian | 91 + .../debian/README.Debian | 64 + gst-plugins-base-subtitles0.10/debian/TODO.Debian | 18 + gst-plugins-base-subtitles0.10/debian/api | 8 + gst-plugins-base-subtitles0.10/debian/changelog | 2458 + gst-plugins-base-subtitles0.10/debian/compat | 1 + gst-plugins-base-subtitles0.10/debian/control | 46 + gst-plugins-base-subtitles0.10/debian/control.in | 46 + gst-plugins-base-subtitles0.10/debian/copyright | 31 + .../debian/gstreamer-alsa.install | 1 + .../debian/gstreamer-plugins-base-apps.install | 2 + .../debian/gstreamer-plugins-base-apps.manpages | 1 + .../debian/gstreamer-plugins-base-doc.install | 1 + .../debian/gstreamer-plugins-base-extra.install | 6 + .../gstreamer-plugins-base-subtitles.install | 2 + .../debian/gstreamer-plugins-base.install | 18 + .../debian/gstreamer-x.install | 2 + .../gstreamer0.10-plugins-base-tests.install | 49 + .../debian/libgstreamer-plugins-base-dev.install | 3 + .../debian/libgstreamer-plugins-base.install | 13 + gst-plugins-base-subtitles0.10/debian/maint | 13 + ...-GstTagReader-interface-to-allow-fine-tun.patch | 494 + ...ke-uridecodebin-and-decodebin2-implement-.patch | 133 + ...add-tagreadbin-element-for-fast-and-easy-.patch | 2467 + ...ding-add-gst-tagread-test-app-to-examples.patch | 357 + ...don-t-try-to-guess-codec-tag-from-NULL-ca.patch | 25 + ...-add-loop-N-command-line-option-to-tagrea.patch | 64 + ...avoid-deadlock-on-state-change-PAUSED_TO_.patch | 51 + ...ounding-of-source-width-in-gstvideosink.c.patch | 24 + ...ind-optimize-MP3-and-MPEG_SYS-typefinding.patch | 100 + ...-add-network-queue-support-adding-nw-queu.patch | 423 + .../patches/0011-Startup-benchmarking-test.patch | 296 + ...c-sink-Change-default-latency-time-to-40m.patch | 39 + .../0013-Install-gst-tagread-example-program.patch | 19 + ...timized-version-of-uyvy_to_rgb24-function.patch | 161 + ...timized-version-of-uyvy422_to_yuv420p-fun.patch | 180 + ...-workaround-for-hangs-with-ID3-tagged-m4a.patch | 29 + ...-extend-workaround-to-ID3-tagged-ASF-WAV-.patch | 42 + ...fix-unknown-codec-tag-missing-after-first.patch | 29 + ...-add-disable-colorkey-property-Maemo-spec.patch | 167 + ...-Add-property-for-the-XV_STACKING-port-at.patch | 115 + ...021-Fix-libgstpbutils-libgstvideo-linking.patch | 58 + ...tag-xmp-Write-the-same-tag-to-all-schemas.patch | 117 + .../patches/0023-tag-xmp-Fixing-schema-maps.patch | 39 + ...4-tag-xmp-Add-struct-xmp-tag-type-support.patch | 556 + ...g-xmp-Add-support-for-reading-struct-tags.patch | 194 + ...26-tag-xmp-Add-Iptc4xmpExt-schema-support.patch | 64 + ...ts-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch | 59 + .../0028-uridecodebin-remove-some-dead-code.patch | 61 + ...n-use-bitrate-to-configure-streaming-buff.patch | 202 + .../debian/patches/series | 29 + gst-plugins-base-subtitles0.10/debian/rules | 198 + gst-plugins-base-subtitles0.10/debian/watch | 2 + gst-plugins-base-subtitles0.10/docs/.gitignore | 1 + gst-plugins-base-subtitles0.10/docs/Makefile.am | 18 + .../docs/design/Makefile.am | 11 + .../docs/design/design-audiosinks.txt | 138 + .../docs/design/design-decodebin.txt | 205 + .../docs/design/design-encoding.txt | 571 + .../docs/design/design-orc-integration.txt | 204 + .../docs/design/draft-keyframe-force.txt | 91 + .../docs/design/draft-va.txt | 111 + .../docs/design/part-interlaced-video.txt | 99 + .../docs/design/part-playbin2.txt | 69 + .../docs/libs/.gitignore | 21 + .../docs/libs/Makefile.am | 106 + .../docs/libs/compiling.sgml | 48 + .../docs/libs/gst-plugins-base-libs-docs.sgml | 240 + .../docs/libs/gst-plugins-base-libs-sections.txt | 2250 + .../docs/libs/gst-plugins-base-libs.types | 72 + .../docs/plugins/.gitignore | 25 + .../docs/plugins/Makefile.am | 152 + .../plugins/gst-plugins-base-plugins-docs.sgml | 113 + .../plugins/gst-plugins-base-plugins-overrides.txt | 30 + .../plugins/gst-plugins-base-plugins-sections.txt | 826 + .../docs/plugins/gst-plugins-base-plugins.args | 3490 ++ .../plugins/gst-plugins-base-plugins.hierarchy | 133 + .../plugins/gst-plugins-base-plugins.interfaces | 30 + .../plugins/gst-plugins-base-plugins.prerequisites | 9 + .../docs/plugins/gst-plugins-base-plugins.signals | 507 + .../docs/plugins/gst-plugins-base-plugins.types | 1 + .../docs/plugins/inspect.stamp | 1 + .../docs/plugins/inspect/plugin-adder.xml | 34 + .../docs/plugins/inspect/plugin-alsa.xml | 52 + .../docs/plugins/inspect/plugin-app.xml | 43 + .../docs/plugins/inspect/plugin-audioconvert.xml | 34 + .../docs/plugins/inspect/plugin-audiorate.xml | 34 + .../docs/plugins/inspect/plugin-audioresample.xml | 34 + .../docs/plugins/inspect/plugin-audiotestsrc.xml | 28 + .../docs/plugins/inspect/plugin-cdparanoia.xml | 28 + .../docs/plugins/inspect/plugin-decodebin.xml | 34 + .../docs/plugins/inspect/plugin-encoding.xml | 46 + .../plugins/inspect/plugin-ffmpegcolorspace.xml | 34 + .../docs/plugins/inspect/plugin-gdp.xml | 55 + .../docs/plugins/inspect/plugin-gio.xml | 73 + .../docs/plugins/inspect/plugin-gnomevfs.xml | 43 + .../docs/plugins/inspect/plugin-libvisual.xml | 181 + .../docs/plugins/inspect/plugin-ogg.xml | 160 + .../docs/plugins/inspect/plugin-pango.xml | 103 + .../docs/plugins/inspect/plugin-playback.xml | 97 + .../docs/plugins/inspect/plugin-subparse.xml | 55 + .../docs/plugins/inspect/plugin-tcp.xml | 88 + .../docs/plugins/inspect/plugin-theora.xml | 76 + .../plugins/inspect/plugin-typefindfunctions.xml | 13 + .../docs/plugins/inspect/plugin-uridecodebin.xml | 49 + .../docs/plugins/inspect/plugin-video4linux.xml | 28 + .../docs/plugins/inspect/plugin-videorate.xml | 34 + .../docs/plugins/inspect/plugin-videoscale.xml | 34 + .../docs/plugins/inspect/plugin-videotestsrc.xml | 28 + .../docs/plugins/inspect/plugin-volume.xml | 34 + .../docs/plugins/inspect/plugin-vorbis.xml | 97 + .../docs/plugins/inspect/plugin-ximagesink.xml | 28 + .../docs/plugins/inspect/plugin-xvimagesink.xml | 28 + .../docs/random/ChangeLog-0.8 |15589 +++++++ gst-plugins-base-subtitles0.10/docs/random/LICENSE | 18 + .../docs/version.entities.in | 2 + gst-plugins-base-subtitles0.10/ext/Makefile.am | 85 + .../ext/alsa/Makefile.am | 36 + gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.c | 571 + gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.h | 60 + .../ext/alsa/gstalsadeviceprobe.c | 210 + .../ext/alsa/gstalsadeviceprobe.h | 33 + .../ext/alsa/gstalsamixer.c | 957 + .../ext/alsa/gstalsamixer.h | 217 + .../ext/alsa/gstalsamixerelement.c | 244 + .../ext/alsa/gstalsamixerelement.h | 61 + .../ext/alsa/gstalsamixeroptions.c | 109 + .../ext/alsa/gstalsamixeroptions.h | 62 + .../ext/alsa/gstalsamixertrack.c | 355 + .../ext/alsa/gstalsamixertrack.h | 79 + .../ext/alsa/gstalsaplugin.c | 91 + .../ext/alsa/gstalsasink.c | 954 + .../ext/alsa/gstalsasink.h | 86 + .../ext/alsa/gstalsasrc.c | 859 + .../ext/alsa/gstalsasrc.h | 86 + .../ext/cdparanoia/Makefile.am | 17 + .../ext/cdparanoia/gstcdparanoiasrc.c | 541 + .../ext/cdparanoia/gstcdparanoiasrc.h | 100 + gst-plugins-base-subtitles0.10/ext/gio/Makefile.am | 29 + gst-plugins-base-subtitles0.10/ext/gio/gstgio.c | 259 + gst-plugins-base-subtitles0.10/ext/gio/gstgio.h | 42 + .../ext/gio/gstgiobasesink.c | 347 + .../ext/gio/gstgiobasesink.h | 71 + .../ext/gio/gstgiobasesrc.c | 447 + .../ext/gio/gstgiobasesrc.h | 72 + .../ext/gio/gstgiosink.c | 319 + .../ext/gio/gstgiosink.h | 68 + gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.c | 339 + gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.h | 68 + .../ext/gio/gstgiostreamsink.c | 198 + .../ext/gio/gstgiostreamsink.h | 68 + .../ext/gio/gstgiostreamsrc.c | 191 + .../ext/gio/gstgiostreamsrc.h | 68 + .../ext/gnomevfs/Makefile.am | 21 + .../ext/gnomevfs/gstgnomevfs.c | 143 + .../ext/gnomevfs/gstgnomevfs.h | 38 + .../ext/gnomevfs/gstgnomevfssink.c | 628 + .../ext/gnomevfs/gstgnomevfssink.h | 84 + .../ext/gnomevfs/gstgnomevfssrc.c | 895 + .../ext/gnomevfs/gstgnomevfssrc.h | 87 + .../ext/gnomevfs/gstgnomevfsuri.c | 90 + .../ext/gnomevfs/gstgnomevfsuri.h | 32 + .../ext/libvisual/Makefile.am | 8 + .../ext/libvisual/visual.c | 1027 + gst-plugins-base-subtitles0.10/ext/ogg/Makefile.am | 45 + gst-plugins-base-subtitles0.10/ext/ogg/README | 366 + .../ext/ogg/dirac_parse.c | 498 + .../ext/ogg/dirac_parse.h | 178 + gst-plugins-base-subtitles0.10/ext/ogg/gstogg.c | 46 + gst-plugins-base-subtitles0.10/ext/ogg/gstogg.h | 31 + .../ext/ogg/gstoggaviparse.c | 476 + .../ext/ogg/gstoggdemux.c | 3683 ++ .../ext/ogg/gstoggdemux.h | 178 + gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.c | 1805 + gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.h | 144 + .../ext/ogg/gstoggparse.c | 758 + .../ext/ogg/gstoggstream.c | 2108 + .../ext/ogg/gstoggstream.h | 139 + .../ext/ogg/gstogmparse.c | 965 + .../ext/ogg/vorbis_parse.c | 240 + .../ext/ogg/vorbis_parse.h | 30 + .../ext/pango/Makefile.am | 30 + .../ext/pango/gstclockoverlay.c | 248 + .../ext/pango/gstclockoverlay.h | 81 + .../ext/pango/gsttextoverlay.c | 2752 ++ .../ext/pango/gsttextoverlay.h | 171 + .../ext/pango/gsttextrender.c | 705 + .../ext/pango/gsttextrender.h | 104 + .../ext/pango/gsttimeoverlay.c | 153 + .../ext/pango/gsttimeoverlay.h | 61 + .../ext/theora/Makefile.am | 21 + .../ext/theora/gsttheora.c | 52 + .../ext/theora/gsttheoradec.c | 1601 + .../ext/theora/gsttheoradec.h | 120 + .../ext/theora/gsttheoraenc.c | 1565 + .../ext/theora/gsttheoraenc.h | 140 + .../ext/theora/gsttheoraparse.c | 936 + .../ext/theora/gsttheoraparse.h | 87 + .../ext/vorbis/Makefile.am | 60 + gst-plugins-base-subtitles0.10/ext/vorbis/README | 16 + .../ext/vorbis/gstivorbisdec.c | 47 + .../ext/vorbis/gstvorbis.c | 73 + .../ext/vorbis/gstvorbiscommon.c | 75 + .../ext/vorbis/gstvorbiscommon.h | 28 + .../ext/vorbis/gstvorbisdec.c | 1301 + .../ext/vorbis/gstvorbisdec.h | 96 + .../ext/vorbis/gstvorbisdeclib.c | 252 + .../ext/vorbis/gstvorbisdeclib.h | 164 + .../ext/vorbis/gstvorbisenc.c | 1427 + .../ext/vorbis/gstvorbisenc.h | 101 + .../ext/vorbis/gstvorbisparse.c | 670 + .../ext/vorbis/gstvorbisparse.h | 82 + .../ext/vorbis/gstvorbistag.c | 142 + .../ext/vorbis/gstvorbistag.h | 63 + .../gst-libs/Makefile.am | 1 + .../gst-libs/ext/.gitignore | 1 + .../gst-libs/ext/Makefile.am | 2 + .../gst-libs/gst/Makefile.am | 44 + .../gst-libs/gst/app/.gitignore | 2 + .../gst-libs/gst/app/Makefile.am | 99 + .../gst-libs/gst/app/gstapp-marshal.list | 5 + .../gst-libs/gst/app/gstappbuffer.c | 108 + .../gst-libs/gst/app/gstappbuffer.h | 64 + .../gst-libs/gst/app/gstappsink.c | 1443 + .../gst-libs/gst/app/gstappsink.h | 141 + .../gst-libs/gst/app/gstappsrc.c | 1689 + .../gst-libs/gst/app/gstappsrc.h | 153 + .../gst-libs/gst/audio/.gitignore | 4 + .../gst-libs/gst/audio/Makefile.am | 132 + .../gst-libs/gst/audio/TODO | 15 + .../gst-libs/gst/audio/audio.c | 435 + .../gst-libs/gst/audio/audio.def | 5 + .../gst-libs/gst/audio/audio.h | 185 + .../gst-libs/gst/audio/audio.vcproj | 153 + .../gst-libs/gst/audio/audiofilter.vcproj | 144 + .../gst-libs/gst/audio/gstaudioclock.c | 314 + .../gst-libs/gst/audio/gstaudioclock.h | 108 + .../gst-libs/gst/audio/gstaudiofilter.c | 205 + .../gst-libs/gst/audio/gstaudiofilter.h | 96 + .../gst-libs/gst/audio/gstaudiosink.c | 619 + .../gst-libs/gst/audio/gstaudiosink.h | 102 + .../gst-libs/gst/audio/gstaudiosrc.c | 532 + .../gst-libs/gst/audio/gstaudiosrc.h | 99 + .../gst-libs/gst/audio/gstbaseaudiosink.c | 2015 + .../gst-libs/gst/audio/gstbaseaudiosink.h | 177 + .../gst-libs/gst/audio/gstbaseaudiosrc.c | 1158 + .../gst-libs/gst/audio/gstbaseaudiosrc.h | 146 + .../gst-libs/gst/audio/gstringbuffer.c | 2060 + .../gst-libs/gst/audio/gstringbuffer.h | 408 + .../gst-libs/gst/audio/mixerutils.c | 246 + .../gst-libs/gst/audio/mixerutils.h | 50 + .../gst-libs/gst/audio/multichannel.c | 742 + .../gst-libs/gst/audio/multichannel.h | 115 + .../gst-libs/gst/audio/testchannels.c | 49 + .../gst-libs/gst/cdda/Makefile.am | 70 + .../gst-libs/gst/cdda/gstcddabasesrc.c | 1665 + .../gst-libs/gst/cdda/gstcddabasesrc.h | 157 + .../gst-libs/gst/fft/Makefile.am | 103 + .../gst-libs/gst/fft/_kiss_fft_guts_f32.h | 112 + .../gst-libs/gst/fft/_kiss_fft_guts_f64.h | 112 + .../gst-libs/gst/fft/_kiss_fft_guts_s16.h | 135 + .../gst-libs/gst/fft/_kiss_fft_guts_s32.h | 136 + .../gst-libs/gst/fft/gstfft.c | 54 + .../gst-libs/gst/fft/gstfft.h | 49 + .../gst-libs/gst/fft/gstfftf32.c | 208 + .../gst-libs/gst/fft/gstfftf32.h | 75 + .../gst-libs/gst/fft/gstfftf64.c | 208 + .../gst-libs/gst/fft/gstfftf64.h | 75 + .../gst-libs/gst/fft/gstffts16.c | 208 + .../gst-libs/gst/fft/gstffts16.h | 74 + .../gst-libs/gst/fft/gstffts32.c | 207 + .../gst-libs/gst/fft/gstffts32.h | 75 + .../gst-libs/gst/fft/kiss_fft_f32.c | 472 + .../gst-libs/gst/fft/kiss_fft_f32.h | 103 + .../gst-libs/gst/fft/kiss_fft_f64.c | 472 + .../gst-libs/gst/fft/kiss_fft_f64.h | 103 + .../gst-libs/gst/fft/kiss_fft_s16.c | 472 + .../gst-libs/gst/fft/kiss_fft_s16.h | 106 + .../gst-libs/gst/fft/kiss_fft_s32.c | 472 + .../gst-libs/gst/fft/kiss_fft_s32.h | 107 + .../gst-libs/gst/fft/kiss_fftr_f32.c | 169 + .../gst-libs/gst/fft/kiss_fftr_f32.h | 46 + .../gst-libs/gst/fft/kiss_fftr_f64.c | 170 + .../gst-libs/gst/fft/kiss_fftr_f64.h | 46 + .../gst-libs/gst/fft/kiss_fftr_s16.c | 170 + .../gst-libs/gst/fft/kiss_fftr_s16.h | 46 + .../gst-libs/gst/fft/kiss_fftr_s32.c | 170 + .../gst-libs/gst/fft/kiss_fftr_s32.h | 46 + .../gst-libs/gst/fft/kiss_version | 4 + .../gst-libs/gst/floatcast/Makefile.am | 2 + .../gst-libs/gst/floatcast/floatcast.h | 102 + .../gst-libs/gst/gettext.h | 69 + .../gst-libs/gst/gst-i18n-plugin.h | 37 + .../gst-libs/gst/interfaces/.gitignore | 5 + .../gst-libs/gst/interfaces/Makefile.am | 137 + .../gst-libs/gst/interfaces/colorbalance.c | 224 + .../gst-libs/gst/interfaces/colorbalance.h | 112 + .../gst-libs/gst/interfaces/colorbalancechannel.c | 124 + .../gst-libs/gst/interfaces/colorbalancechannel.h | 75 + .../gst/interfaces/interfaces-marshal.list | 5 + .../gst-libs/gst/interfaces/mixer.c | 872 + .../gst-libs/gst/interfaces/mixer.h | 231 + .../gst-libs/gst/interfaces/mixeroptions.c | 146 + .../gst-libs/gst/interfaces/mixeroptions.h | 91 + .../gst-libs/gst/interfaces/mixertrack.c | 288 + .../gst-libs/gst/interfaces/mixertrack.h | 134 + .../gst-libs/gst/interfaces/navigation.c | 848 + .../gst-libs/gst/interfaces/navigation.h | 257 + .../gst-libs/gst/interfaces/propertyprobe.c | 378 + .../gst-libs/gst/interfaces/propertyprobe.h | 115 + .../gst-libs/gst/interfaces/streamvolume.c | 225 + .../gst-libs/gst/interfaces/streamvolume.h | 87 + .../gst-libs/gst/interfaces/tuner.c | 574 + .../gst-libs/gst/interfaces/tuner.h | 128 + .../gst-libs/gst/interfaces/tunerchannel.c | 148 + .../gst-libs/gst/interfaces/tunerchannel.h | 113 + .../gst-libs/gst/interfaces/tunernorm.c | 111 + .../gst-libs/gst/interfaces/tunernorm.h | 67 + .../gst-libs/gst/interfaces/videoorientation.c | 270 + .../gst-libs/gst/interfaces/videoorientation.h | 94 + .../gst-libs/gst/interfaces/xoverlay.c | 567 + .../gst-libs/gst/interfaces/xoverlay.h | 121 + .../gst-libs/gst/netbuffer/Makefile.am | 69 + .../gst-libs/gst/netbuffer/README | 9 + .../gst-libs/gst/netbuffer/gstnetbuffer.c | 423 + .../gst-libs/gst/netbuffer/gstnetbuffer.h | 129 + .../gst-libs/gst/pbutils/.gitignore | 4 + .../gst-libs/gst/pbutils/Makefile.am | 136 + .../gst-libs/gst/pbutils/codec-utils.c | 767 + .../gst-libs/gst/pbutils/codec-utils.h | 63 + .../gst-libs/gst/pbutils/descriptions.c | 1013 + .../gst-libs/gst/pbutils/descriptions.h | 58 + .../gst-libs/gst/pbutils/encoding-profile.c | 966 + .../gst-libs/gst/pbutils/encoding-profile.h | 187 + .../gst-libs/gst/pbutils/encoding-target.c | 1201 + .../gst-libs/gst/pbutils/encoding-target.h | 147 + .../gst-libs/gst/pbutils/gstdiscoverer-types.c | 983 + .../gst-libs/gst/pbutils/gstdiscoverer.c | 1525 + .../gst-libs/gst/pbutils/gstdiscoverer.h | 266 + .../gst-libs/gst/pbutils/gstpluginsbaseversion.c | 78 + .../gst/pbutils/gstpluginsbaseversion.h.in | 86 + .../gst-libs/gst/pbutils/install-plugins.c | 783 + .../gst-libs/gst/pbutils/install-plugins.h | 144 + .../gst-libs/gst/pbutils/missing-plugins.c | 802 + .../gst-libs/gst/pbutils/missing-plugins.h | 77 + .../gst-libs/gst/pbutils/pbutils-marshal.list | 2 + .../gst-libs/gst/pbutils/pbutils-private.h | 86 + .../gst-libs/gst/pbutils/pbutils.c | 108 + .../gst-libs/gst/pbutils/pbutils.h | 42 + .../gst-libs/gst/riff/Makefile.am | 92 + .../gst-libs/gst/riff/riff-ids.h | 517 + .../gst-libs/gst/riff/riff-media.c | 1911 + .../gst-libs/gst/riff/riff-media.h | 65 + .../gst-libs/gst/riff/riff-read.c | 749 + .../gst-libs/gst/riff/riff-read.h | 87 + .../gst-libs/gst/riff/riff.c | 48 + .../gst-libs/gst/riff/riff.def | 27 + .../gst-libs/gst/riff/riff.vcproj | 158 + .../gst-libs/gst/rtp/Makefile.am | 85 + .../gst-libs/gst/rtp/README | 66 + .../gst-libs/gst/rtp/gstbasertpaudiopayload.c | 992 + .../gst-libs/gst/rtp/gstbasertpaudiopayload.h | 98 + .../gst-libs/gst/rtp/gstbasertpdepayload.c | 806 + .../gst-libs/gst/rtp/gstbasertpdepayload.h | 141 + .../gst-libs/gst/rtp/gstbasertppayload.c | 1069 + .../gst-libs/gst/rtp/gstbasertppayload.h | 162 + .../gst-libs/gst/rtp/gstrtcpbuffer.c | 2031 + .../gst-libs/gst/rtp/gstrtcpbuffer.h | 286 + .../gst-libs/gst/rtp/gstrtpbuffer.c | 2059 + .../gst-libs/gst/rtp/gstrtpbuffer.h | 166 + .../gst-libs/gst/rtp/gstrtppayloads.c | 229 + .../gst-libs/gst/rtp/gstrtppayloads.h | 193 + .../gst-libs/gst/rtsp/.gitignore | 4 + .../gst-libs/gst/rtsp/Makefile.am | 120 + .../gst-libs/gst/rtsp/gstrtsp-marshal.list | 2 + .../gst-libs/gst/rtsp/gstrtsp.h | 27 + .../gst-libs/gst/rtsp/gstrtspbase64.c | 91 + .../gst-libs/gst/rtsp/gstrtspbase64.h | 37 + .../gst-libs/gst/rtsp/gstrtspconnection.c | 3668 ++ .../gst-libs/gst/rtsp/gstrtspconnection.h | 209 + .../gst-libs/gst/rtsp/gstrtspdefs.c | 505 + .../gst-libs/gst/rtsp/gstrtspdefs.h | 397 + .../gst-libs/gst/rtsp/gstrtspextension.c | 224 + .../gst-libs/gst/rtsp/gstrtspextension.h | 97 + .../gst-libs/gst/rtsp/gstrtspmessage.c | 842 + .../gst-libs/gst/rtsp/gstrtspmessage.h | 187 + .../gst-libs/gst/rtsp/gstrtsprange.c | 272 + .../gst-libs/gst/rtsp/gstrtsprange.h | 121 + .../gst-libs/gst/rtsp/gstrtsptransport.c | 717 + .../gst-libs/gst/rtsp/gstrtsptransport.h | 174 + .../gst-libs/gst/rtsp/gstrtspurl.c | 416 + .../gst-libs/gst/rtsp/gstrtspurl.h | 103 + .../gst-libs/gst/sdp/Makefile.am | 71 + .../gst-libs/gst/sdp/gstsdp.h | 58 + .../gst-libs/gst/sdp/gstsdpmessage.c | 2241 + .../gst-libs/gst/sdp/gstsdpmessage.h | 423 + .../gst-libs/gst/tag/Makefile.am | 96 + .../gst-libs/gst/tag/gstexiftag.c | 2655 ++ .../gst-libs/gst/tag/gstid3tag.c | 487 + .../gst-libs/gst/tag/gsttagdemux.c | 1535 + .../gst-libs/gst/tag/gsttagdemux.h | 144 + .../gst-libs/gst/tag/gsttageditingprivate.c | 468 + .../gst-libs/gst/tag/gsttageditingprivate.h | 75 + .../gst-libs/gst/tag/gstvorbistag.c | 793 + .../gst-libs/gst/tag/gstxmptag.c | 1684 + .../gst-libs/gst/tag/lang-tables.dat | 447 + .../gst-libs/gst/tag/lang.c | 494 + .../gst-libs/gst/tag/mklangtables.c | 239 + .../gst-libs/gst/tag/tag.h | 549 + .../gst-libs/gst/tag/tags.c | 634 + .../gst-libs/gst/tag/xmpwriter.c | 322 + .../gst-libs/gst/tag/xmpwriter.h | 68 + .../gst-libs/gst/video/.gitignore | 2 + .../gst-libs/gst/video/Makefile.am | 98 + .../gst-libs/gst/video/convertframe.c | 700 + .../gst-libs/gst/video/gstvideofilter.c | 124 + .../gst-libs/gst/video/gstvideofilter.h | 58 + .../gst-libs/gst/video/gstvideosink.c | 288 + .../gst-libs/gst/video/gstvideosink.h | 132 + .../gst-libs/gst/video/video.c | 2295 + .../gst-libs/gst/video/video.h | 501 + .../gst-libs/gst/video/video.vcproj | 150 + .../gst-plugins-base.doap | 417 + .../gst-plugins-base.spec.in | 275 + gst-plugins-base-subtitles0.10/gst/Makefile.am | 4 + .../gst/adder/.gitignore | 7 + .../gst/adder/Makefile.am | 31 + .../gst/adder/adder.vcproj | 148 + .../gst/adder/gstadder.c | 1312 + .../gst/adder/gstadder.h | 110 + .../gst/adder/gstadderorc-dist.c | 835 + .../gst/adder/gstadderorc-dist.h | 85 + .../gst/adder/gstadderorc.orc | 52 + gst-plugins-base-subtitles0.10/gst/app/Makefile.am | 21 + gst-plugins-base-subtitles0.10/gst/app/gstapp.c | 42 + .../gst/audioconvert/.gitignore | 1 + .../gst/audioconvert/Makefile.am | 51 + .../gst/audioconvert/audioconvert.c | 796 + .../gst/audioconvert/audioconvert.h | 146 + .../gst/audioconvert/audioconvert.vcproj | 154 + .../gst/audioconvert/channelmixtest.c | 95 + .../gst/audioconvert/gstaudioconvert.c | 1176 + .../gst/audioconvert/gstaudioconvert.h | 60 + .../gst/audioconvert/gstaudioconvertorc-dist.c | 6828 +++ .../gst/audioconvert/gstaudioconvertorc-dist.h | 132 + .../gst/audioconvert/gstaudioconvertorc.orc | 593 + .../gst/audioconvert/gstaudioquantize.c | 503 + .../gst/audioconvert/gstaudioquantize.h | 34 + .../gst/audioconvert/gstchannelmix.c | 742 + .../gst/audioconvert/gstchannelmix.h | 56 + .../gst/audioconvert/gstfastrandom.h | 90 + .../gst/audioconvert/plugin.c | 51 + .../gst/audioconvert/plugin.h | 35 + .../gst/audiorate/Makefile.am | 23 + .../gst/audiorate/audiorate.vcproj | 145 + .../gst/audiorate/gstaudiorate.c | 877 + .../gst/audiorate/gstaudiorate.h | 83 + .../gst/audioresample/Makefile.am | 57 + .../gst/audioresample/README | 347 + .../gst/audioresample/arch.h | 265 + .../gst/audioresample/fixed_arm4.h | 148 + .../gst/audioresample/fixed_arm5e.h | 178 + .../gst/audioresample/fixed_bfin.h | 176 + .../gst/audioresample/fixed_debug.h | 487 + .../gst/audioresample/fixed_generic.h | 106 + .../gst/audioresample/gstaudioresample.c | 1604 + .../gst/audioresample/gstaudioresample.h | 95 + .../gst/audioresample/resample.c | 1354 + .../gst/audioresample/resample_sse.h | 128 + .../gst/audioresample/speex_resampler.h | 367 + .../gst/audioresample/speex_resampler_double.c | 25 + .../gst/audioresample/speex_resampler_float.c | 24 + .../gst/audioresample/speex_resampler_int.c | 24 + .../gst/audioresample/speex_resampler_wrapper.h | 168 + .../gst/audiotestsrc/Makefile.am | 23 + .../gst/audiotestsrc/gstaudiotestsrc.c | 1238 + .../gst/audiotestsrc/gstaudiotestsrc.h | 144 + .../gst/encoding/.gitignore | 1 + .../gst/encoding/Makefile.am | 53 + .../gst/encoding/gstencode-marshal.list | 1 + .../gst/encoding/gstencodebin.c | 1796 + .../gst/encoding/gstencodebin.h | 39 + .../gst/encoding/gstsmartencoder.c | 701 + .../gst/encoding/gstsmartencoder.h | 71 + .../gst/encoding/gststreamcombiner.c | 276 + .../gst/encoding/gststreamcombiner.h | 60 + .../gst/encoding/gststreamsplitter.c | 435 + .../gst/encoding/gststreamsplitter.h | 62 + .../gst/ffmpegcolorspace/Makefile.am | 37 + .../gst/ffmpegcolorspace/avcodec.h | 285 + .../gst/ffmpegcolorspace/dsputil.c | 45 + .../gst/ffmpegcolorspace/dsputil.h | 39 + .../gst/ffmpegcolorspace/ffmpegcolorspace.vcproj | 181 + .../gst/ffmpegcolorspace/gstffmpegcodecmap.c | 1016 + .../gst/ffmpegcolorspace/gstffmpegcodecmap.h | 58 + .../gst/ffmpegcolorspace/gstffmpegcolorspace.c | 517 + .../gst/ffmpegcolorspace/gstffmpegcolorspace.h | 63 + .../gst/ffmpegcolorspace/imgconvert.c | 4126 ++ .../gst/ffmpegcolorspace/imgconvert_template.h | 2188 + .../gst/ffmpegcolorspace/mem.c | 125 + .../gst/ffmpegcolorspace/utils.c | 159 + gst-plugins-base-subtitles0.10/gst/gdp/Makefile.am | 29 + gst-plugins-base-subtitles0.10/gst/gdp/README | 22 + gst-plugins-base-subtitles0.10/gst/gdp/gstgdp.c | 46 + .../gst/gdp/gstgdpdepay.c | 478 + .../gst/gdp/gstgdpdepay.h | 82 + gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.c | 898 + gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.h | 81 + .../gst/playback/.gitignore | 3 + .../gst/playback/Makefile.am | 107 + gst-plugins-base-subtitles0.10/gst/playback/README | 91 + .../gst/playback/gstdecodebin.c | 2059 + .../gst/playback/gstdecodebin2.c | 3738 ++ .../gst/playback/gstplay-enum.c | 81 + .../gst/playback/gstplay-enum.h | 80 + .../gst/playback/gstplay-marshal.list | 10 + .../gst/playback/gstplayback.c | 67 + .../gst/playback/gstplayback.h | 31 + .../gst/playback/gstplaybasebin.c | 2811 ++ .../gst/playback/gstplaybasebin.h | 126 + .../gst/playback/gstplaybin.c | 1990 + .../gst/playback/gstplaybin2.c | 3786 ++ .../gst/playback/gstplaysink.c | 3431 ++ .../gst/playback/gstplaysink.h | 113 + .../gst/playback/gstrawcaps.h | 42 + .../gst/playback/gststreaminfo.c | 402 + .../gst/playback/gststreaminfo.h | 86 + .../gst/playback/gststreamselector.c | 749 + .../gst/playback/gststreamselector.h | 62 + .../gst/playback/gststreamsynchronizer.c | 986 + .../gst/playback/gststreamsynchronizer.h | 67 + .../gst/playback/gstsubtitleoverlay.c | 2140 + .../gst/playback/gstsubtitleoverlay.h | 129 + .../gst/playback/gsturidecodebin.c | 2467 + .../gst/subparse/Makefile.am | 33 + .../gst/subparse/gstssaparse.c | 381 + .../gst/subparse/gstssaparse.h | 57 + .../gst/subparse/gstsubparse.c | 1886 + .../gst/subparse/gstsubparse.h | 120 + .../gst/subparse/mpl2parse.c | 107 + .../gst/subparse/mpl2parse.h | 32 + .../gst/subparse/qttextparse.c | 453 + .../gst/subparse/qttextparse.h | 36 + .../gst/subparse/samiparse.c | 474 + .../gst/subparse/samiparse.h | 38 + .../gst/subparse/tmplayerparse.c | 154 + .../gst/subparse/tmplayerparse.h | 32 + gst-plugins-base-subtitles0.10/gst/tcp/.gitignore | 5 + gst-plugins-base-subtitles0.10/gst/tcp/Makefile.am | 56 + gst-plugins-base-subtitles0.10/gst/tcp/README | 53 + .../gst/tcp/gstmultifdsink.c | 3016 ++ .../gst/tcp/gstmultifdsink.h | 288 + .../gst/tcp/gsttcp-marshal.list | 5 + gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.c | 569 + gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.h | 76 + .../gst/tcp/gsttcpclientsink.c | 460 + .../gst/tcp/gsttcpclientsink.h | 91 + .../gst/tcp/gsttcpclientsrc.c | 441 + .../gst/tcp/gsttcpclientsrc.h | 83 + .../gst/tcp/gsttcpplugin.c | 63 + .../gst/tcp/gsttcpplugin.h | 40 + .../gst/tcp/gsttcpserversink.c | 378 + .../gst/tcp/gsttcpserversink.h | 90 + .../gst/tcp/gsttcpserversrc.c | 483 + .../gst/tcp/gsttcpserversrc.h | 89 + gst-plugins-base-subtitles0.10/gst/tcp/tcp.vcproj | 160 + .../gst/typefind/Makefile.am | 26 + .../gst/typefind/gsttypefindfunctions.c | 4545 ++ .../gst/typefind/typefindfunctions.vcproj | 145 + .../gst/videorate/Makefile.am | 23 + .../gst/videorate/gstvideorate.c | 1024 + .../gst/videorate/gstvideorate.h | 85 + .../gst/videorate/videorate.vcproj | 145 + .../gst/videoscale/.gitignore | 7 + .../gst/videoscale/Makefile.am | 42 + .../gst/videoscale/README | 5 + .../gst/videoscale/gstvideoscale.c | 1339 + .../gst/videoscale/gstvideoscale.h | 97 + .../gst/videoscale/gstvideoscaleorc-dist.c | 2264 + .../gst/videoscale/gstvideoscaleorc-dist.h | 93 + .../gst/videoscale/gstvideoscaleorc.orc | 199 + .../gst/videoscale/videoscale.vcproj | 154 + .../gst/videoscale/vs_4tap.c | 1451 + .../gst/videoscale/vs_4tap.h | 99 + .../gst/videoscale/vs_fill_borders.c | 422 + .../gst/videoscale/vs_fill_borders.h | 44 + .../gst/videoscale/vs_image.c | 1155 + .../gst/videoscale/vs_image.h | 98 + .../gst/videoscale/vs_scanline.c | 781 + .../gst/videoscale/vs_scanline.h | 79 + .../gst/videotestsrc/.gitignore | 1 + .../gst/videotestsrc/Makefile.am | 37 + .../gst/videotestsrc/generate_sine_table.c | 43 + .../gst/videotestsrc/gstvideotestsrc.c | 955 + .../gst/videotestsrc/gstvideotestsrc.h | 190 + .../gst/videotestsrc/gstvideotestsrcorc-dist.c | 482 + .../gst/videotestsrc/gstvideotestsrcorc-dist.h | 82 + .../gst/videotestsrc/gstvideotestsrcorc.orc | 31 + .../gst/videotestsrc/videotestsrc.c | 2593 + .../gst/videotestsrc/videotestsrc.h | 148 + .../gst/videotestsrc/videotestsrc.vcproj | 154 + .../gst/volume/.gitignore | 1 + .../gst/volume/Makefile.am | 34 + .../gst/volume/gstvolume.c | 1048 + .../gst/volume/gstvolume.h | 88 + .../gst/volume/gstvolumeorc-dist.c | 2721 ++ .../gst/volume/gstvolumeorc-dist.h | 96 + .../gst/volume/gstvolumeorc.orc | 180 + .../gst/volume/volume.vcproj | 148 + .../pkgconfig/.gitignore | 1 + .../pkgconfig/Makefile.am | 69 + .../pkgconfig/gstreamer-app-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-app.pc.in | 16 + .../pkgconfig/gstreamer-audio-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-audio.pc.in | 16 + .../pkgconfig/gstreamer-cdda-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-cdda.pc.in | 16 + .../pkgconfig/gstreamer-fft-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-fft.pc.in | 16 + .../gstreamer-floatcast-uninstalled.pc.in | 14 + .../pkgconfig/gstreamer-floatcast.pc.in | 16 + .../gstreamer-interfaces-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-interfaces.pc.in | 16 + .../gstreamer-netbuffer-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-netbuffer.pc.in | 16 + .../pkgconfig/gstreamer-pbutils-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-pbutils.pc.in | 16 + .../gstreamer-plugins-base-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-plugins-base.pc.in | 14 + .../pkgconfig/gstreamer-riff-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-riff.pc.in | 16 + .../pkgconfig/gstreamer-rtp-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-rtp.pc.in | 16 + .../pkgconfig/gstreamer-rtsp-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-rtsp.pc.in | 16 + .../pkgconfig/gstreamer-sdp-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-sdp.pc.in | 16 + .../pkgconfig/gstreamer-tag-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-tag.pc.in | 16 + .../pkgconfig/gstreamer-video-uninstalled.pc.in | 16 + .../pkgconfig/gstreamer-video.pc.in | 16 + gst-plugins-base-subtitles0.10/po/.gitignore | 17 + gst-plugins-base-subtitles0.10/po/LINGUAS | 1 + gst-plugins-base-subtitles0.10/po/Makevars | 47 + gst-plugins-base-subtitles0.10/po/POTFILES.in | 23 + gst-plugins-base-subtitles0.10/po/af.po | 734 + gst-plugins-base-subtitles0.10/po/az.po | 735 + gst-plugins-base-subtitles0.10/po/bg.po | 610 + gst-plugins-base-subtitles0.10/po/ca.po | 613 + gst-plugins-base-subtitles0.10/po/cs.po | 613 + gst-plugins-base-subtitles0.10/po/da.po | 649 + gst-plugins-base-subtitles0.10/po/de.po | 645 + gst-plugins-base-subtitles0.10/po/el.po | 625 + gst-plugins-base-subtitles0.10/po/en_GB.po | 740 + gst-plugins-base-subtitles0.10/po/es.po | 637 + gst-plugins-base-subtitles0.10/po/eu.po | 612 + gst-plugins-base-subtitles0.10/po/fi.po | 643 + gst-plugins-base-subtitles0.10/po/fr.po | 627 + gst-plugins-base-subtitles0.10/po/gl.po | 612 + gst-plugins-base-subtitles0.10/po/hu.po | 610 + gst-plugins-base-subtitles0.10/po/id.po | 628 + gst-plugins-base-subtitles0.10/po/it.po | 629 + gst-plugins-base-subtitles0.10/po/ja.po | 621 + gst-plugins-base-subtitles0.10/po/lt.po | 639 + gst-plugins-base-subtitles0.10/po/lv.po | 626 + gst-plugins-base-subtitles0.10/po/nb.po | 600 + gst-plugins-base-subtitles0.10/po/nl.po | 615 + gst-plugins-base-subtitles0.10/po/or.po | 757 + gst-plugins-base-subtitles0.10/po/pl.po | 611 + gst-plugins-base-subtitles0.10/po/pt_BR.po | 645 + gst-plugins-base-subtitles0.10/po/ro.po | 606 + gst-plugins-base-subtitles0.10/po/ru.po | 623 + gst-plugins-base-subtitles0.10/po/sk.po | 643 + gst-plugins-base-subtitles0.10/po/sl.po | 637 + gst-plugins-base-subtitles0.10/po/sq.po | 756 + gst-plugins-base-subtitles0.10/po/sr.po | 736 + gst-plugins-base-subtitles0.10/po/sv.po | 1776 + gst-plugins-base-subtitles0.10/po/tr.po | 627 + gst-plugins-base-subtitles0.10/po/uk.po | 637 + gst-plugins-base-subtitles0.10/po/vi.po | 607 + gst-plugins-base-subtitles0.10/po/zh_CN.po | 613 + gst-plugins-base-subtitles0.10/sys/Makefile.am | 29 + gst-plugins-base-subtitles0.10/sys/v4l/.gitignore | 2 + gst-plugins-base-subtitles0.10/sys/v4l/Makefile.am | 41 + gst-plugins-base-subtitles0.10/sys/v4l/README | 35 + gst-plugins-base-subtitles0.10/sys/v4l/TODO | 44 + gst-plugins-base-subtitles0.10/sys/v4l/gstv4l.c | 67 + .../sys/v4l/gstv4lcolorbalance.c | 150 + .../sys/v4l/gstv4lcolorbalance.h | 59 + .../sys/v4l/gstv4lelement.c | 552 + .../sys/v4l/gstv4lelement.h | 116 + .../sys/v4l/gstv4ljpegsrc.c | 293 + .../sys/v4l/gstv4ljpegsrc.h | 57 + .../sys/v4l/gstv4lmjpegsink.c | 431 + .../sys/v4l/gstv4lmjpegsink.h | 97 + .../sys/v4l/gstv4lmjpegsrc.c | 868 + .../sys/v4l/gstv4lmjpegsrc.h | 116 + gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.c | 727 + gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.h | 108 + .../sys/v4l/gstv4ltuner.c | 328 + .../sys/v4l/gstv4ltuner.h | 84 + .../sys/v4l/gstv4lxoverlay.c | 246 + .../sys/v4l/gstv4lxoverlay.h | 40 + gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.c | 724 + gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.h | 154 + .../sys/v4l/v4lmjpegsink_calls.c | 525 + .../sys/v4l/v4lmjpegsink_calls.h | 62 + .../sys/v4l/v4lmjpegsrc_calls.c | 577 + .../sys/v4l/v4lmjpegsrc_calls.h | 66 + .../sys/v4l/v4lsrc_calls.c | 764 + .../sys/v4l/v4lsrc_calls.h | 58 + .../sys/v4l/videodev_mjpeg.h | 123 + .../sys/ximage/Makefile.am | 14 + gst-plugins-base-subtitles0.10/sys/ximage/ximage.c | 47 + .../sys/ximage/ximagesink.c | 2508 + .../sys/ximage/ximagesink.h | 234 + .../sys/xvimage/Makefile.am | 15 + .../sys/xvimage/xvimagesink.c | 3784 ++ .../sys/xvimage/xvimagesink.h | 303 + gst-plugins-base-subtitles0.10/tests/Makefile.am | 28 + .../tests/check/.gitignore | 1 + .../tests/check/Makefile.am | 529 + .../tests/check/elements/.gitignore | 29 + .../tests/check/elements/adder.c | 874 + .../tests/check/elements/alsa.c | 134 + .../tests/check/elements/appsink.c | 423 + .../tests/check/elements/appsrc.c | 188 + .../tests/check/elements/audioconvert.c | 1742 + .../tests/check/elements/audiorate.c | 470 + .../tests/check/elements/audioresample.c | 926 + .../tests/check/elements/audiotestsrc.c | 128 + .../tests/check/elements/decodebin.c | 200 + .../tests/check/elements/decodebin2.c | 203 + .../tests/check/elements/encodebin.c | 902 + .../tests/check/elements/ffmpegcolorspace.c | 439 + .../tests/check/elements/gdpdepay.c | 413 + .../tests/check/elements/gdppay.c | 566 + .../tests/check/elements/gnomevfssink.c | 319 + .../tests/check/elements/libvisual.c | 118 + .../tests/check/elements/multifdsink.c | 867 + .../tests/check/elements/playbin.c | 650 + .../tests/check/elements/playbin2.c | 754 + .../tests/check/elements/subparse.c | 719 + .../tests/check/elements/textoverlay.c | 751 + .../tests/check/elements/videorate.c | 797 + .../tests/check/elements/videoscale.c | 866 + .../tests/check/elements/videotestsrc.c | 428 + .../tests/check/elements/volume.c | 1525 + .../tests/check/elements/vorbisdec.c | 339 + .../tests/check/elements/vorbistag.c | 409 + .../tests/check/generic/.gitignore | 3 + .../tests/check/generic/clock-selection.c | 72 + .../tests/check/generic/states.c | 222 + .../tests/check/gst-plugins-base.supp | 389 + .../tests/check/gst/.gitignore | 2 + .../tests/check/gst/typefindfunctions.c | 391 + .../tests/check/libs/.gitignore | 18 + .../tests/check/libs/audio.c | 559 + .../tests/check/libs/cddabasesrc.c | 515 + .../tests/check/libs/discoverer.c | 94 + .../tests/check/libs/fft.c | 563 + .../tests/check/libs/gstlibscpp.cc | 139 + .../tests/check/libs/libsabi.c | 122 + .../tests/check/libs/mixer.c | 243 + .../tests/check/libs/navigation.c | 353 + .../tests/check/libs/netbuffer.c | 96 + .../tests/check/libs/pbutils.c | 750 + .../tests/check/libs/profile.c | 621 + .../tests/check/libs/rtp.c | 767 + .../tests/check/libs/rtsp.c | 153 + .../tests/check/libs/struct_i386.h | 100 + .../tests/check/libs/struct_i386_osx.h | 100 + .../tests/check/libs/struct_x86_64.h | 100 + .../tests/check/libs/tag.c | 1656 + .../tests/check/libs/video.c | 770 + .../tests/check/libs/xmpwriter.c | 275 + .../tests/check/pipelines/.gitignore | 10 + .../tests/check/pipelines/basetime.c | 158 + .../check/pipelines/capsfilter-renegotiation.c | 172 + .../tests/check/pipelines/gio.c | 181 + .../tests/check/pipelines/oggmux.c | 432 + .../tests/check/pipelines/simple-launch-lines.c | 240 + .../tests/check/pipelines/streamheader.c | 256 + .../tests/check/pipelines/theoraenc.c | 463 + .../tests/check/pipelines/vorbisdec.c | 118 + .../tests/check/pipelines/vorbisenc.c | 410 + .../tests/check/tests.xml | 160 + .../tests/examples/Makefile.am | 15 + .../tests/examples/app/.gitignore | 6 + .../tests/examples/app/Makefile.am | 32 + .../tests/examples/app/appsink-src.c | 192 + .../tests/examples/app/appsrc-ra.c | 224 + .../tests/examples/app/appsrc-seekable.c | 229 + .../tests/examples/app/appsrc-stream.c | 249 + .../tests/examples/app/appsrc-stream2.c | 219 + .../tests/examples/app/appsrc_ex.c | 95 + .../tests/examples/dynamic/.gitignore | 5 + .../tests/examples/dynamic/Makefile.am | 21 + .../tests/examples/dynamic/addstream.c | 253 + .../tests/examples/dynamic/codec-select.c | 298 + .../tests/examples/dynamic/sprinkle.c | 264 + .../tests/examples/dynamic/sprinkle2.c | 288 + .../tests/examples/dynamic/sprinkle3.c | 301 + .../tests/examples/encoding/.gitignore | 1 + .../tests/examples/encoding/Makefile.am | 12 + .../tests/examples/encoding/encoding.c | 512 + .../tests/examples/encoding/gstcapslist.c | 285 + .../tests/examples/encoding/gstcapslist.h | 35 + .../tests/examples/gio/.gitignore | 1 + .../tests/examples/gio/Makefile.am | 8 + .../tests/examples/gio/giosrc-mounting.c | 127 + .../tests/examples/overlay/.gitignore | 5 + .../tests/examples/overlay/Makefile.am | 47 + .../tests/examples/overlay/gtk-xoverlay.c | 149 + .../tests/examples/overlay/qt-xoverlay.cpp | 130 + .../tests/examples/overlay/qtgv-xoverlay.cpp | 128 + .../tests/examples/overlay/qtgv-xoverlay.h | 45 + .../tests/examples/playrec/.gitignore | 1 + .../tests/examples/playrec/Makefile.am | 4 + .../tests/examples/playrec/playrec.c | 166 + .../tests/examples/seek/.gitignore | 5 + .../tests/examples/seek/Makefile.am | 17 + .../tests/examples/seek/jsseek.c | 3056 ++ .../tests/examples/seek/scrubby.c | 568 + .../tests/examples/seek/seek.c | 2996 ++ .../tests/examples/seek/stepping.c | 124 + .../tests/examples/seek/stepping2.c | 142 + .../tests/examples/snapshot/.gitignore | 2 + .../tests/examples/snapshot/Makefile.am | 10 + .../tests/examples/snapshot/snapshot.c | 151 + .../tests/examples/v4l/.gitignore | 1 + .../tests/examples/v4l/Makefile.am | 10 + .../tests/examples/v4l/probe.c | 85 + .../tests/examples/volume/.gitignore | 1 + .../tests/examples/volume/Makefile.am | 6 + .../tests/examples/volume/volume.c | 172 + .../tests/files/623663.mts | Bin 0 -> 4000 bytes .../tests/files/Makefile.am | 4 + .../tests/files/hls.m3u8 | 15 + .../tests/files/partialframe.mjpeg | Bin 0 -> 1600 bytes .../tests/icles/.gitignore | 12 + .../tests/icles/Makefile.am | 82 + .../tests/icles/audio-trickplay.c | 264 + .../tests/icles/input-selector-test.c | 162 + .../tests/icles/output-selector-test.c | 173 + .../tests/icles/playback/.gitignore | 8 + .../tests/icles/playback/Makefile.am | 26 + .../tests/icles/playback/decodetest.c | 169 + .../tests/icles/playback/test.c | 193 + .../tests/icles/playback/test2.c | 43 + .../tests/icles/playback/test3.c | 128 + .../tests/icles/playback/test4.c | 99 + .../tests/icles/playback/test5.c | 132 + .../tests/icles/playback/test6.c | 164 + .../tests/icles/playback/test7.c | 179 + .../tests/icles/playbin-text.c | 178 + .../tests/icles/position-formats.c | 149 + .../tests/icles/stress-playbin.c | 157 + .../tests/icles/stress-xoverlay.c | 247 + .../tests/icles/test-box.c | 144 + .../tests/icles/test-colorkey.c | 284 + .../tests/icles/test-scale.c | 164 + .../tests/icles/test-textoverlay.c | 125 + .../tests/icles/test-xoverlay.c | 247 + .../tests/old/Makefile.am | 26 + .../tests/old/examples/Makefile.am | 15 + .../tests/old/examples/capsfilter/Makefile.am | 6 + .../tests/old/examples/capsfilter/capsfilter1.c | 87 + .../tests/old/examples/gob/Makefile.am | 19 + .../tests/old/examples/gob/gst-identity2.gob | 139 + .../tests/old/examples/indexing/.gitignore | 1 + .../tests/old/examples/indexing/Makefile.am | 7 + .../tests/old/examples/indexing/indexmpeg.c | 321 + .../tests/old/examples/seek/.gitignore | 6 + .../tests/old/examples/seek/Makefile.am | 7 + .../tests/old/examples/seek/cdparanoia.c | 215 + .../tests/old/examples/seek/cdplayer.c | 292 + .../tests/old/examples/seek/chained.c | 107 + .../tests/old/examples/stats/Makefile.am | 6 + .../tests/old/examples/stats/mp2ogg.c | 102 + .../tests/old/examples/switch/.gitignore | 1 + .../tests/old/examples/switch/Makefile.am | 7 + .../tests/old/examples/switch/switcher.c | 104 + .../tests/old/testsuite/alsa/.gitignore | 3 + .../tests/old/testsuite/alsa/Makefile.am | 13 + .../tests/old/testsuite/alsa/formats.c | 184 + .../tests/old/testsuite/alsa/sinesrc.c | 351 + .../tests/old/testsuite/alsa/sinesrc.h | 89 + .../tests/old/testsuite/alsa/srcstate.c | 95 + .../tests/old/testsuite/alsa/state.c | 108 + .../tests/old/testsuite/embed/Makefile.am | 7 + .../tests/old/testsuite/embed/embed.c | 54 + .../tests/old/testsuite/gst-lint | 571 + gst-plugins-base-subtitles0.10/tools/.gitignore | 5 + gst-plugins-base-subtitles0.10/tools/Makefile.am | 49 + .../tools/README.filterstamp | 24 + .../tools/filterstamp.sh | 57 + .../tools/gst-discoverer.c | 499 + .../tools/gst-launch-ext.1.in | 42 + .../tools/gst-visualise.1.in | 32 + gst-plugins-base-subtitles0.10/win32/MANIFEST | 84 + .../win32/common/audio-enumtypes.c | 173 + .../win32/common/audio-enumtypes.h | 29 + .../win32/common/gstrtsp-enumtypes.c | 389 + .../win32/common/gstrtsp-enumtypes.h | 35 + .../win32/common/interfaces-enumtypes.c | 274 + .../win32/common/interfaces-enumtypes.h | 49 + .../win32/common/libgstapp.def | 34 + .../win32/common/libgstaudio.def | 75 + .../win32/common/libgstcdda.def | 4 + .../win32/common/libgstinterfaces.def | 122 + .../win32/common/libgstnetbuffer.def | 12 + .../win32/common/libgstpbutils.def | 137 + .../win32/common/libgstriff.def | 16 + .../win32/common/libgstrtp.def | 136 + .../win32/common/libgstrtsp.def | 112 + .../win32/common/libgstsdp.def | 78 + .../win32/common/libgsttag.def | 41 + .../win32/common/libgstvideo.def | 36 + .../win32/common/multichannel-enumtypes.c | 53 + .../win32/common/multichannel-enumtypes.h | 19 + .../win32/common/pbutils-enumtypes.c | 70 + .../win32/common/pbutils-enumtypes.h | 23 + .../win32/common/video-enumtypes.c | 65 + .../win32/common/video-enumtypes.h | 19 + .../win32/vs6/grammar.dsp | 424 + .../win32/vs6/gst_plugins_base.dsw | 440 + .../win32/vs6/libgstadder.dsp | 123 + .../win32/vs6/libgstaudio.dsp | 207 + .../win32/vs6/libgstaudioconvert.dsp | 151 + .../win32/vs6/libgstaudiorate.dsp | 119 + .../win32/vs6/libgstaudioresample.dsp | 163 + .../win32/vs6/libgstaudioscale.dsp | 125 + .../win32/vs6/libgstaudiotestsrc.dsp | 123 + .../win32/vs6/libgstcdda.dsp | 143 + .../win32/vs6/libgstdecodebin.dsp | 123 + .../win32/vs6/libgstdecodebin2.dsp | 135 + .../win32/vs6/libgstdirectsound.dsp | 125 + .../win32/vs6/libgstffmpegcolorspace.dsp | 163 + .../win32/vs6/libgstfft.dsp | 167 + .../win32/vs6/libgstgdp.dsp | 127 + .../win32/vs6/libgstinterfaces.dsp | 223 + .../win32/vs6/libgstnetbuffer.dsp | 127 + .../win32/vs6/libgstogg.dsp | 139 + .../win32/vs6/libgstpbutils.dsp | 139 + .../win32/vs6/libgstplaybin.dsp | 151 + .../win32/vs6/libgstriff.dsp | 143 + .../win32/vs6/libgstrtp.dsp | 155 + .../win32/vs6/libgstrtsp.dsp | 195 + .../win32/vs6/libgstsdp.dsp | 123 + .../win32/vs6/libgstsinesrc.dsp | 121 + .../win32/vs6/libgstsubparse.dsp | 123 + .../win32/vs6/libgsttag.dsp | 139 + .../win32/vs6/libgsttheora.dsp | 131 + .../win32/vs6/libgsttypefindfunctions.dsp | 119 + .../win32/vs6/libgstvideo.dsp | 143 + .../win32/vs6/libgstvideorate.dsp | 119 + .../win32/vs6/libgstvideoscale.dsp | 143 + .../win32/vs6/libgstvideotestsrc.dsp | 131 + .../win32/vs6/libgstvolume.dsp | 119 + .../win32/vs6/libgstvorbis.dsp | 147 + .../win32/vs7/gst-plugins-base.sln | 199 + .../win32/vs7/libgstadder.vcproj | 142 + .../win32/vs7/libgstaudio.vcproj | 183 + .../win32/vs7/libgstaudioconvert.vcproj | 151 + .../win32/vs7/libgstaudiorate.vcproj | 142 + .../win32/vs7/libgstaudioresample.vcproj | 163 + .../win32/vs7/libgstaudiotestsrc.vcproj | 142 + .../win32/vs7/libgstdecodebin.vcproj | 169 + .../win32/vs7/libgstffmpegcolorspace.vcproj | 160 + .../win32/vs7/libgstinterfaces.vcproj | 206 + .../win32/vs7/libgstogg.vcproj | 154 + .../win32/vs7/libgstplaybin.vcproj | 178 + .../win32/vs7/libgstriff.vcproj | 153 + .../win32/vs7/libgstsubparse.vcproj | 134 + .../win32/vs7/libgsttag.vcproj | 150 + .../win32/vs7/libgsttcp.vcproj | 160 + .../win32/vs7/libgsttheora.vcproj | 148 + .../win32/vs7/libgsttypefind.vcproj | 142 + .../win32/vs7/libgstvideo.vcproj | 150 + .../win32/vs7/libgstvideorate.vcproj | 142 + .../win32/vs7/libgstvideoscale.vcproj | 148 + .../win32/vs7/libgstvideotestsrc.vcproj | 145 + .../win32/vs7/libgstvolume.vcproj | 142 + .../win32/vs7/libgstvorbis.vcproj | 151 + .../win32/vs8/gst-plugins-base.sln | 177 + .../win32/vs8/libgstadder.vcproj | 206 + .../win32/vs8/libgstaudio.vcproj | 254 + .../win32/vs8/libgstaudioconvert.vcproj | 218 + .../win32/vs8/libgstaudiorate.vcproj | 206 + .../win32/vs8/libgstaudioresample.vcproj | 230 + .../win32/vs8/libgstaudiotestsrc.vcproj | 206 + .../win32/vs8/libgstdecodebin.vcproj | 212 + .../win32/vs8/libgstffmpegcolorspace.vcproj | 230 + .../win32/vs8/libgstinterfaces.vcproj | 264 + .../win32/vs8/libgstogg.vcproj | 226 + .../win32/vs8/libgstplaybin.vcproj | 224 + .../win32/vs8/libgstriff.vcproj | 222 + .../win32/vs8/libgstsubparse.vcproj | 200 + .../win32/vs8/libgsttag.vcproj | 222 + .../win32/vs8/libgsttcp.vcproj | 232 + .../win32/vs8/libgsttheora.vcproj | 218 + .../win32/vs8/libgsttypefind.vcproj | 206 + .../win32/vs8/libgstvideo.vcproj | 218 + .../win32/vs8/libgstvideorate.vcproj | 206 + .../win32/vs8/libgstvideoscale.vcproj | 218 + .../win32/vs8/libgstvideotestsrc.vcproj | 210 + .../win32/vs8/libgstvolume.vcproj | 206 + .../win32/vs8/libgstvorbis.vcproj | 222 + 1132 files changed, 420618 insertions(+) create mode 100644 gst-plugins-base-subtitles0.10/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/.gitmodules create mode 100644 gst-plugins-base-subtitles0.10/AUTHORS create mode 100644 gst-plugins-base-subtitles0.10/Android.mk create mode 100644 gst-plugins-base-subtitles0.10/COPYING create mode 100644 gst-plugins-base-subtitles0.10/COPYING.LIB create mode 100644 gst-plugins-base-subtitles0.10/ChangeLog create mode 100644 gst-plugins-base-subtitles0.10/INSTALL create mode 100644 gst-plugins-base-subtitles0.10/LICENSE_readme create mode 100644 gst-plugins-base-subtitles0.10/MAINTAINERS create mode 100644 gst-plugins-base-subtitles0.10/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/NEWS create mode 100644 gst-plugins-base-subtitles0.10/README create mode 100644 gst-plugins-base-subtitles0.10/RELEASE create mode 100644 gst-plugins-base-subtitles0.10/REQUIREMENTS create mode 100644 gst-plugins-base-subtitles0.10/android/NOTICE create mode 100644 gst-plugins-base-subtitles0.10/android/alsa.mk create mode 100644 gst-plugins-base-subtitles0.10/android/app.mk create mode 100644 gst-plugins-base-subtitles0.10/android/app_plugin.mk create mode 100644 gst-plugins-base-subtitles0.10/android/audio.mk create mode 100644 gst-plugins-base-subtitles0.10/android/audioconvert.mk create mode 100644 gst-plugins-base-subtitles0.10/android/audioresample.mk create mode 100644 gst-plugins-base-subtitles0.10/android/audiotestsrc.mk create mode 100644 gst-plugins-base-subtitles0.10/android/decodebin.mk create mode 100644 gst-plugins-base-subtitles0.10/android/decodebin2.mk create mode 100644 gst-plugins-base-subtitles0.10/android/ffmpegcolorspace.mk create mode 100644 gst-plugins-base-subtitles0.10/android/gdp.mk create mode 100644 gst-plugins-base-subtitles0.10/android/interfaces.mk create mode 100644 gst-plugins-base-subtitles0.10/android/netbuffer.mk create mode 100644 gst-plugins-base-subtitles0.10/android/pbutils.mk create mode 100644 gst-plugins-base-subtitles0.10/android/playbin.mk create mode 100644 gst-plugins-base-subtitles0.10/android/queue2.mk create mode 100644 gst-plugins-base-subtitles0.10/android/riff.mk create mode 100644 gst-plugins-base-subtitles0.10/android/rtp.mk create mode 100644 gst-plugins-base-subtitles0.10/android/rtsp.mk create mode 100644 gst-plugins-base-subtitles0.10/android/sdp.mk create mode 100644 gst-plugins-base-subtitles0.10/android/tag.mk create mode 100644 gst-plugins-base-subtitles0.10/android/tcp.mk create mode 100644 gst-plugins-base-subtitles0.10/android/typefindfunctions.mk create mode 100644 gst-plugins-base-subtitles0.10/android/video.mk create mode 100644 gst-plugins-base-subtitles0.10/android/videoscale.mk create mode 100644 gst-plugins-base-subtitles0.10/android/videotestsrc.mk create mode 100755 gst-plugins-base-subtitles0.10/autogen.sh create mode 100644 gst-plugins-base-subtitles0.10/common/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/common/ChangeLog create mode 100644 gst-plugins-base-subtitles0.10/common/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/common/c-to-xml.py create mode 100755 gst-plugins-base-subtitles0.10/common/check-exports create mode 100644 gst-plugins-base-subtitles0.10/common/check.mak create mode 100644 gst-plugins-base-subtitles0.10/common/coverage/coverage-report-entry.pl create mode 100644 gst-plugins-base-subtitles0.10/common/coverage/coverage-report.pl create mode 100644 gst-plugins-base-subtitles0.10/common/coverage/coverage-report.xsl create mode 100644 gst-plugins-base-subtitles0.10/common/coverage/lcov.mak create mode 100644 gst-plugins-base-subtitles0.10/common/cruft.mak create mode 100755 gst-plugins-base-subtitles0.10/common/download-translations create mode 100755 gst-plugins-base-subtitles0.10/common/extract-release-date-from-doap-file create mode 100644 gst-plugins-base-subtitles0.10/common/gen-changelog.py create mode 100644 gst-plugins-base-subtitles0.10/common/gettext.patch create mode 100644 gst-plugins-base-subtitles0.10/common/glib-gen.mak create mode 100644 gst-plugins-base-subtitles0.10/common/gst-autogen.sh create mode 100644 gst-plugins-base-subtitles0.10/common/gst-glib-gen.mak create mode 100755 gst-plugins-base-subtitles0.10/common/gst-indent create mode 100644 gst-plugins-base-subtitles0.10/common/gst.supp create mode 100755 gst-plugins-base-subtitles0.10/common/gstdoc-scangobj create mode 100644 gst-plugins-base-subtitles0.10/common/gtk-doc-plugins.mak create mode 100644 gst-plugins-base-subtitles0.10/common/gtk-doc.mak create mode 100755 gst-plugins-base-subtitles0.10/common/hooks/post-receive.hook create mode 100755 gst-plugins-base-subtitles0.10/common/hooks/pre-commit.hook create mode 100644 gst-plugins-base-subtitles0.10/common/hooks/pre-receive.hook create mode 100644 gst-plugins-base-subtitles0.10/common/m4/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/common/m4/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/common/m4/README create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-ac-expand.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-auto-alt.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-compiler-flag.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-compiler.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-docbook.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-gcc-inline-assembly.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-libtool-tags.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-libtool.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-objc.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-python.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-scrub-include.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/as-version.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/ax_create_stdint_h.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/check.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/glib-gettext.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-arch.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-args.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-check.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-debuginfo.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-default.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-doc.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-dowhile.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-error.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-feature.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-function.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-gettext.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-glib2.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-libxml2.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-package-release-datetime.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-parser.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-platform.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-plugin-docs.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-plugindir.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-valgrind.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst-x11.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gst.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/gtk-doc.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/introspection.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/orc.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/m4/pkg.m4 create mode 100644 gst-plugins-base-subtitles0.10/common/mangle-tmpl.py create mode 100644 gst-plugins-base-subtitles0.10/common/orc.mak create mode 100644 gst-plugins-base-subtitles0.10/common/parallel-subdirs.mak create mode 100644 gst-plugins-base-subtitles0.10/common/plugins.xsl create mode 100644 gst-plugins-base-subtitles0.10/common/po.mak create mode 100644 gst-plugins-base-subtitles0.10/common/release.mak create mode 100755 gst-plugins-base-subtitles0.10/common/scangobj-merge.py create mode 100755 gst-plugins-base-subtitles0.10/common/update-common create mode 100644 gst-plugins-base-subtitles0.10/common/upload-doc.mak create mode 100644 gst-plugins-base-subtitles0.10/common/win32.mak create mode 100644 gst-plugins-base-subtitles0.10/configure.ac create mode 100644 gst-plugins-base-subtitles0.10/debian/HACKING.Debian create mode 100644 gst-plugins-base-subtitles0.10/debian/README.Debian create mode 100644 gst-plugins-base-subtitles0.10/debian/TODO.Debian create mode 100644 gst-plugins-base-subtitles0.10/debian/api create mode 100644 gst-plugins-base-subtitles0.10/debian/changelog create mode 100644 gst-plugins-base-subtitles0.10/debian/compat create mode 100644 gst-plugins-base-subtitles0.10/debian/control create mode 100644 gst-plugins-base-subtitles0.10/debian/control.in create mode 100644 gst-plugins-base-subtitles0.10/debian/copyright create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-alsa.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.manpages create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-doc.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-extra.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-subtitles.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer-x.install create mode 100644 gst-plugins-base-subtitles0.10/debian/gstreamer0.10-plugins-base-tests.install create mode 100644 gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base-dev.install create mode 100644 gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base.install create mode 100755 gst-plugins-base-subtitles0.10/debian/maint create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0001-tag-add-new-GstTagReader-interface-to-allow-fine-tun.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0002-playback-make-uridecodebin-and-decodebin2-implement-.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0003-tagreading-add-tagreadbin-element-for-fast-and-easy-.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0004-tagreading-add-gst-tagread-test-app-to-examples.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0005-tagreadbin-don-t-try-to-guess-codec-tag-from-NULL-ca.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0006-gst-tagread-add-loop-N-command-line-option-to-tagrea.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0007-tagreadbin-avoid-deadlock-on-state-change-PAUSED_TO_.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0008-Fix-rounding-of-source-width-in-gstvideosink.c.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0009-typefind-optimize-MP3-and-MPEG_SYS-typefinding.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0011-Startup-benchmarking-test.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0012-baseaudiosrc-sink-Change-default-latency-time-to-40m.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0013-Install-gst-tagread-example-program.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0014-NEON-optimized-version-of-uyvy_to_rgb24-function.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0015-ARM-NEON-optimized-version-of-uyvy422_to_yuv420p-fun.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0016-typefinding-workaround-for-hangs-with-ID3-tagged-m4a.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0017-typefinding-extend-workaround-to-ID3-tagged-ASF-WAV-.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0018-tagreading-fix-unknown-codec-tag-missing-after-first.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0019-xvimagesink-add-disable-colorkey-property-Maemo-spec.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0020-xvimagesink-Add-property-for-the-XV_STACKING-port-at.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0021-Fix-libgstpbutils-libgstvideo-linking.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0022-tag-xmp-Write-the-same-tag-to-all-schemas.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0023-tag-xmp-Fixing-schema-maps.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0024-tag-xmp-Add-struct-xmp-tag-type-support.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0025-tag-xmp-Add-support-for-reading-struct-tags.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0026-tag-xmp-Add-Iptc4xmpExt-schema-support.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0027-tests-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0028-uridecodebin-remove-some-dead-code.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/0029-uridecodebin-use-bitrate-to-configure-streaming-buff.patch create mode 100644 gst-plugins-base-subtitles0.10/debian/patches/series create mode 100755 gst-plugins-base-subtitles0.10/debian/rules create mode 100644 gst-plugins-base-subtitles0.10/debian/watch create mode 100644 gst-plugins-base-subtitles0.10/docs/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/docs/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/docs/design/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/docs/design/design-audiosinks.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/design-decodebin.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/design-encoding.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/design-orc-integration.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/draft-keyframe-force.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/draft-va.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/part-interlaced-video.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/design/part-playbin2.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/compiling.sgml create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-docs.sgml create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-overrides.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-sections.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs.types create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-docs.sgml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-overrides.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-sections.txt create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.args create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.hierarchy create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.interfaces create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.prerequisites create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.signals create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.types create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect-build.stamp create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect.stamp create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-adder.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-alsa.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-app.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioconvert.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiorate.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioresample.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiotestsrc.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-cdparanoia.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-decodebin.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-encoding.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ffmpegcolorspace.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gdp.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gio.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gnomevfs.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-libvisual.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ogg.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-pango.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-playback.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-subparse.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-tcp.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-theora.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-typefindfunctions.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-uridecodebin.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-video4linux.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videorate.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videoscale.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videotestsrc.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-volume.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-vorbis.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ximagesink.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-xvimagesink.xml create mode 100644 gst-plugins-base-subtitles0.10/docs/plugins/scanobj-build.stamp create mode 100644 gst-plugins-base-subtitles0.10/docs/random/ChangeLog-0.8 create mode 100644 gst-plugins-base-subtitles0.10/docs/random/LICENSE create mode 100644 gst-plugins-base-subtitles0.10/docs/version.entities.in create mode 100644 gst-plugins-base-subtitles0.10/ext/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsaplugin.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.h create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/cdparanoia/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgio.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgio.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.c create mode 100644 gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.h create mode 100644 gst-plugins-base-subtitles0.10/ext/libvisual/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/libvisual/visual.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/README create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.h create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstogg.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstogg.h create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggaviparse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.h create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.h create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggparse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.h create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/gstogmparse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.h create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.c create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.h create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheora.c create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.c create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.h create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/README create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstivorbisdec.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbis.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.h create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.c create mode 100644 gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/ext/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/ext/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstapp-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/TODO create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.def create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audiofilter.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/audio/testchannels.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f64.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s16.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_version create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/floatcast.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/gettext.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/gst-i18n-plugin.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/interfaces-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/README create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer-types.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.h.in create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-private.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-ids.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.def create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/README create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdp.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstexiftag.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstid3tag.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstvorbistag.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstxmptag.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang-tables.dat create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/mklangtables.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tag.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tags.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/convertframe.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.c create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.h create mode 100644 gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst-plugins-base.doap create mode 100644 gst-plugins-base-subtitles0.10/gst-plugins-base.spec.in create mode 100644 gst-plugins-base-subtitles0.10/gst/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/adder.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/gstadder.c create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/gstadder.h create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.c create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.h create mode 100644 gst-plugins-base-subtitles0.10/gst/adder/gstadderorc.orc create mode 100644 gst-plugins-base-subtitles0.10/gst/app/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/app/gstapp.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/channelmixtest.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc.orc create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/gstfastrandom.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audiorate/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/audiorate/audiorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/README create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/arch.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm4.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm5e.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/fixed_bfin.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/fixed_debug.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/fixed_generic.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/resample.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/resample_sse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_double.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_float.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_int.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_wrapper.h create mode 100644 gst-plugins-base-subtitles0.10/gst/audiotestsrc/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gstencode-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.h create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.c create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.h create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.c create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.h create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.c create mode 100644 gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/avcodec.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.c create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/ffmpegcolorspace.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.c create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.c create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert_template.h create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/mem.c create mode 100644 gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/utils.c create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/README create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/gstgdp.c create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.c create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.h create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.c create mode 100644 gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/README create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin2.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplay-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplayback.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplayback.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaybin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaybin2.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstrawcaps.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/gst/playback/gsturidecodebin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/samiparse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/samiparse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.c create mode 100644 gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/README create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcp-marshal.list create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst/tcp/tcp.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/typefind/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/typefind/gsttypefindfunctions.c create mode 100644 gst-plugins-base-subtitles0.10/gst/typefind/typefindfunctions.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/videorate/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videorate/videorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/README create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc.orc create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/videoscale.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/generate_sine_table.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc.orc create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.c create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.h create mode 100644 gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.vcproj create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/gstvolume.c create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/gstvolume.h create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.c create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.h create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc.orc create mode 100644 gst-plugins-base-subtitles0.10/gst/volume/volume.vcproj create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video-uninstalled.pc.in create mode 100644 gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video.pc.in create mode 100644 gst-plugins-base-subtitles0.10/po/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/po/LINGUAS create mode 100644 gst-plugins-base-subtitles0.10/po/Makevars create mode 100644 gst-plugins-base-subtitles0.10/po/POTFILES.in create mode 100644 gst-plugins-base-subtitles0.10/po/af.po create mode 100644 gst-plugins-base-subtitles0.10/po/az.po create mode 100644 gst-plugins-base-subtitles0.10/po/bg.po create mode 100644 gst-plugins-base-subtitles0.10/po/ca.po create mode 100644 gst-plugins-base-subtitles0.10/po/cs.po create mode 100644 gst-plugins-base-subtitles0.10/po/da.po create mode 100644 gst-plugins-base-subtitles0.10/po/de.po create mode 100644 gst-plugins-base-subtitles0.10/po/el.po create mode 100644 gst-plugins-base-subtitles0.10/po/en_GB.po create mode 100644 gst-plugins-base-subtitles0.10/po/es.po create mode 100644 gst-plugins-base-subtitles0.10/po/eu.po create mode 100644 gst-plugins-base-subtitles0.10/po/fi.po create mode 100644 gst-plugins-base-subtitles0.10/po/fr.po create mode 100644 gst-plugins-base-subtitles0.10/po/gl.po create mode 100644 gst-plugins-base-subtitles0.10/po/hu.po create mode 100644 gst-plugins-base-subtitles0.10/po/id.po create mode 100644 gst-plugins-base-subtitles0.10/po/it.po create mode 100644 gst-plugins-base-subtitles0.10/po/ja.po create mode 100644 gst-plugins-base-subtitles0.10/po/lt.po create mode 100644 gst-plugins-base-subtitles0.10/po/lv.po create mode 100644 gst-plugins-base-subtitles0.10/po/nb.po create mode 100644 gst-plugins-base-subtitles0.10/po/nl.po create mode 100644 gst-plugins-base-subtitles0.10/po/or.po create mode 100644 gst-plugins-base-subtitles0.10/po/pl.po create mode 100644 gst-plugins-base-subtitles0.10/po/pt_BR.po create mode 100644 gst-plugins-base-subtitles0.10/po/ro.po create mode 100644 gst-plugins-base-subtitles0.10/po/ru.po create mode 100644 gst-plugins-base-subtitles0.10/po/sk.po create mode 100644 gst-plugins-base-subtitles0.10/po/sl.po create mode 100644 gst-plugins-base-subtitles0.10/po/sq.po create mode 100644 gst-plugins-base-subtitles0.10/po/sr.po create mode 100644 gst-plugins-base-subtitles0.10/po/sv.po create mode 100644 gst-plugins-base-subtitles0.10/po/tr.po create mode 100644 gst-plugins-base-subtitles0.10/po/uk.po create mode 100644 gst-plugins-base-subtitles0.10/po/vi.po create mode 100644 gst-plugins-base-subtitles0.10/po/zh_CN.po create mode 100644 gst-plugins-base-subtitles0.10/sys/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/README create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/TODO create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4l.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.c create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.h create mode 100644 gst-plugins-base-subtitles0.10/sys/v4l/videodev_mjpeg.h create mode 100644 gst-plugins-base-subtitles0.10/sys/ximage/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/sys/ximage/ximage.c create mode 100644 gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.c create mode 100644 gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.h create mode 100644 gst-plugins-base-subtitles0.10/sys/xvimage/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.c create mode 100644 gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.h create mode 100644 gst-plugins-base-subtitles0.10/tests/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/check/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/adder.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/alsa.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/appsink.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/appsrc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/audioconvert.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/audiorate.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/audioresample.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/audiotestsrc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/decodebin.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/decodebin2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/encodebin.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/ffmpegcolorspace.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/gdpdepay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/gdppay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/gnomevfssink.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/libvisual.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/multifdsink.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/playbin.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/playbin2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/subparse.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/textoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/videorate.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/videoscale.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/videotestsrc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/volume.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/vorbisdec.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/elements/vorbistag.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/generic/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/generic/clock-selection.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/generic/states.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/gst-plugins-base.supp create mode 100644 gst-plugins-base-subtitles0.10/tests/check/gst/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/gst/typefindfunctions.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/audio.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/cddabasesrc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/discoverer.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/fft.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/gstlibscpp.cc create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/libsabi.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/mixer.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/navigation.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/netbuffer.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/pbutils.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/profile.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/rtp.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/rtsp.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386.h create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386_osx.h create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/struct_x86_64.h create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/tag.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/video.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/libs/xmpwriter.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/basetime.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/capsfilter-renegotiation.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/gio.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/oggmux.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/simple-launch-lines.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/streamheader.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/theoraenc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/vorbisdec.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/pipelines/vorbisenc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/check/tests.xml create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsink-src.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-ra.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-seekable.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/app/appsrc_ex.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/addstream.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/codec-select.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle3.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/encoding/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/encoding/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/encoding/encoding.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.h create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/gio/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/gio/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/gio/giosrc-mounting.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/gtk-xoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/qt-xoverlay.cpp create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.cpp create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.h create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/playrec/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/playrec/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/playrec/playrec.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/jsseek.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/scrubby.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/seek.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/stepping.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/seek/stepping2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/snapshot/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/snapshot/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/snapshot/snapshot.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/v4l/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/v4l/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/v4l/probe.c create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/volume/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/volume/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/examples/volume/volume.c create mode 100644 gst-plugins-base-subtitles0.10/tests/files/623663.mts create mode 100644 gst-plugins-base-subtitles0.10/tests/files/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/files/hls.m3u8 create mode 100644 gst-plugins-base-subtitles0.10/tests/files/partialframe.mjpeg create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/audio-trickplay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/input-selector-test.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/output-selector-test.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/decodetest.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test2.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test3.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test4.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test5.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test6.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playback/test7.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/playbin-text.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/position-formats.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/stress-playbin.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/stress-xoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/test-box.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/test-colorkey.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/test-scale.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/test-textoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/icles/test-xoverlay.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/capsfilter1.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/gob/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/gob/gst-identity2.gob create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/indexing/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/indexing/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/indexing/indexmpeg.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/seek/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/seek/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdparanoia.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdplayer.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/seek/chained.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/stats/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/stats/mp2ogg.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/switch/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/switch/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/examples/switch/switcher.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/formats.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.h create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/srcstate.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/state.c create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/embed.c create mode 100755 gst-plugins-base-subtitles0.10/tests/old/testsuite/gst-lint create mode 100644 gst-plugins-base-subtitles0.10/tools/.gitignore create mode 100644 gst-plugins-base-subtitles0.10/tools/Makefile.am create mode 100644 gst-plugins-base-subtitles0.10/tools/README.filterstamp create mode 100755 gst-plugins-base-subtitles0.10/tools/filterstamp.sh create mode 100644 gst-plugins-base-subtitles0.10/tools/gst-discoverer.c create mode 100644 gst-plugins-base-subtitles0.10/tools/gst-launch-ext.1.in create mode 100644 gst-plugins-base-subtitles0.10/tools/gst-visualise.1.in create mode 100644 gst-plugins-base-subtitles0.10/win32/MANIFEST create mode 100644 gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstapp.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstaudio.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstcdda.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstinterfaces.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstnetbuffer.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstpbutils.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstriff.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstrtp.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstrtsp.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstsdp.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgsttag.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/libgstvideo.def create mode 100644 gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.c create mode 100644 gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.h create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/grammar.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/gst_plugins_base.dsw create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstadder.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudio.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioconvert.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiorate.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioresample.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioscale.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiotestsrc.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstcdda.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin2.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstdirectsound.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstffmpegcolorspace.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstfft.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstgdp.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstinterfaces.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstnetbuffer.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstogg.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstpbutils.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstplaybin.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstriff.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstrtp.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstrtsp.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstsdp.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstsinesrc.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstsubparse.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgsttag.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgsttheora.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgsttypefindfunctions.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvideo.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvideorate.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvideoscale.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvideotestsrc.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvolume.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs6/libgstvorbis.dsp create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/gst-plugins-base.sln create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstadder.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstaudio.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioconvert.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioresample.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiotestsrc.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstdecodebin.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstffmpegcolorspace.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstinterfaces.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstogg.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstplaybin.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstriff.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstsubparse.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgsttag.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgsttcp.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgsttheora.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgsttypefind.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvideo.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvideorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvideoscale.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvideotestsrc.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvolume.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs7/libgstvorbis.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/gst-plugins-base.sln create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstadder.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstaudio.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioconvert.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioresample.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiotestsrc.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstdecodebin.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstffmpegcolorspace.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstinterfaces.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstogg.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstplaybin.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstriff.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstsubparse.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgsttag.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgsttcp.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgsttheora.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgsttypefind.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvideo.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvideorate.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvideoscale.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvideotestsrc.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvolume.vcproj create mode 100644 gst-plugins-base-subtitles0.10/win32/vs8/libgstvorbis.vcproj diff --git a/gst-plugins-base-subtitles0.10/.gitignore b/gst-plugins-base-subtitles0.10/.gitignore new file mode 100644 index 0000000..005392e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/.gitignore @@ -0,0 +1,51 @@ +aclocal.m4 +autom4te.cache +config.h* +config.h.in +config.log +config.status +config.guess +config.sub +config.rpath +configure +gst-plugins-base.spec +gstreamer-libs-uninstalled*.pc +gstreamer-libs*.pc +gstreamer-play-uninstalled*.pc +gstreamer-play*.pc +libtool +stamp-h +stamp-h.in +stamp-h1 +gst-element-check-*.m4 +ltmain.sh +missing +mkinstalldirs +compile +install-sh +depcomp +autoregen.sh +ABOUT-NLS +_stdint.h + +gst-plugins-base-*.tar* + +.deps +.libs +*.lo +*.la +*.o +*~ +*.bak +/m4 +Makefile.in +Makefile +*.gir +*.typelib + +gst-libs/gst/pbutils/gstpluginsbaseversion.h +gst-libs/gst/tag/mklangtables + +tmp-orc.c +gst*orc.h +tests/check/orc diff --git a/gst-plugins-base-subtitles0.10/.gitmodules b/gst-plugins-base-subtitles0.10/.gitmodules new file mode 100644 index 0000000..1ba590b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/.gitmodules @@ -0,0 +1,3 @@ +[submodule "common"] + path = common + url = git://anongit.freedesktop.org/gstreamer/common diff --git a/gst-plugins-base-subtitles0.10/AUTHORS b/gst-plugins-base-subtitles0.10/AUTHORS new file mode 100644 index 0000000..1a394ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/AUTHORS @@ -0,0 +1,23 @@ +Erik Walthinsen +Matt Howell +Brent Bradburn +Wim Taymans +Richard Boulton +Zaheer Abbas Merali +David I. Lehn +Chris Emerson +Jens Thiele +Thomas Nyberg +Bastien Nocera +Christian Fredrik Kalager Schaller +Thomas Vander Stichele +Andy Wingo +Cameron Hutchison +David Schleef +Benjamin Otte +Ronald Bultje +Julien MOUTTE +Jan Schmidt +Arwed v. Merkatz +Tim-Philipp Müller +Mark Borgerding (kissfft, used in libgstfft) diff --git a/gst-plugins-base-subtitles0.10/Android.mk b/gst-plugins-base-subtitles0.10/Android.mk new file mode 100644 index 0000000..b3d345b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/Android.mk @@ -0,0 +1,125 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +GST_PLUGINS_BASE_TOP := $(LOCAL_PATH) + +GST_PLUGINS_BASE_BUILT_SOURCES := \ + pkgconfig/gstreamer-app-0.10.pc \ + pkgconfig/gstreamer-audio-0.10.pc \ + pkgconfig/gstreamer-cdda-0.10.pc \ + pkgconfig/gstreamer-fft-0.10.pc \ + pkgconfig/gstreamer-floatcast-0.10.pc \ + pkgconfig/gstreamer-interfaces-0.10.pc \ + pkgconfig/gstreamer-netbuffer-0.10.pc \ + pkgconfig/gstreamer-pbutils-0.10.pc \ + pkgconfig/gstreamer-plugins-base-0.10.pc \ + pkgconfig/gstreamer-riff-0.10.pc \ + pkgconfig/gstreamer-rtp-0.10.pc \ + pkgconfig/gstreamer-rtsp-0.10.pc \ + pkgconfig/gstreamer-sdp-0.10.pc \ + pkgconfig/gstreamer-tag-0.10.pc \ + pkgconfig/gstreamer-video-0.10.pc \ + pkgconfig/gstreamer-app-0.10-uninstalled.pc \ + pkgconfig/gstreamer-audio-0.10-uninstalled.pc \ + pkgconfig/gstreamer-cdda-0.10-uninstalled.pc \ + pkgconfig/gstreamer-fft-0.10-uninstalled.pc \ + pkgconfig/gstreamer-floatcast-0.10-uninstalled.pc \ + pkgconfig/gstreamer-interfaces-0.10-uninstalled.pc \ + pkgconfig/gstreamer-netbuffer-0.10-uninstalled.pc \ + pkgconfig/gstreamer-pbutils-0.10-uninstalled.pc \ + pkgconfig/gstreamer-plugins-base-0.10-uninstalled.pc \ + pkgconfig/gstreamer-riff-0.10-uninstalled.pc \ + pkgconfig/gstreamer-rtp-0.10-uninstalled.pc \ + pkgconfig/gstreamer-rtsp-0.10-uninstalled.pc \ + pkgconfig/gstreamer-sdp-0.10-uninstalled.pc \ + pkgconfig/gstreamer-tag-0.10-uninstalled.pc \ + pkgconfig/gstreamer-video-0.10-uninstalled.pc \ + gst-libs/gst/interfaces/Android.mk \ + gst-libs/gst/tag/Android.mk \ + gst-libs/gst/audio/Android.mk \ + gst-libs/gst/video/Android.mk \ + gst-libs/gst/riff/Android.mk \ + gst-libs/gst/pbutils/Android.mk \ + gst-libs/gst/rtp/Android.mk \ + gst-libs/gst/rtsp/Android.mk \ + gst-libs/gst/netbuffer/Android.mk \ + gst-libs/gst/sdp/Android.mk \ + gst-libs/gst/app/Android.mk \ + gst-libs/gst/fft/Android.mk \ + gst/playback/Android.mk \ + gst/typefind/Android.mk \ + gst/app/Android.mk \ + gst/gdp/Android.mk \ + gst/tcp/Android.mk \ + gst/audioconvert/Android.mk \ + gst/audioresample/Android.mk \ + gst/audiotestsrc/Android.mk \ + gst/videotestsrc/Android.mk \ + gst/videoscale/Android.mk \ + gst/ffmpegcolorspace/Android.mk \ + gst/videorate/Android.mk \ + gst/encoding/Android.mk \ + gst/adder/Android.mk \ + gst/audiorate/Android.mk \ + gst/volume/Android.mk \ + tools/Android.mk \ + ext/vorbis/Android.mk \ + ext/ogg/Android.mk + +GST_PLUGINS_BASE_BUILT_SOURCES := $(patsubst %, $(abspath $(GST_PLUGINS_BASE_TOP))/%, $(GST_PLUGINS_BASE_BUILT_SOURCES)) + + +.PHONY: gst-plugins-base-configure +gst-plugins-base-configure: + cd $(GST_PLUGINS_BASE_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=/ \ + IVORBIS_CFLAGS="-I$(TOP)/external/tremolo -DTREMOR" \ + IVORBIS_LIBS="-lvorbisidec" \ + $(abspath $(GST_PLUGINS_BASE_TOP))/$(CONFIGURE) --host=arm-linux-androideabi \ + --prefix=/system --disable-orc --disable-gio --enable-ivorbis \ + --disable-valgrind --disable-gtk-doc && \ + for file in $(GST_PLUGINS_BASE_BUILT_SOURCES); do \ + rm -f $$file && \ + make -C $$(dirname $$file) $$(basename $$file) ; \ + done + +CONFIGURE_TARGETS += gst-plugins-base-configure + +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/interfaces/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/fft/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/tag/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/audio/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/video/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/riff/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/pbutils/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/rtp/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/rtsp/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/netbuffer/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/sdp/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst-libs/gst/app/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/playback/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/typefind/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/app/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/gdp/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/tcp/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/audioconvert/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/audioresample/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/audiotestsrc/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/videotestsrc/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/videoscale/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/ffmpegcolorspace/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/videorate/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/encoding/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/adder/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/audiorate/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/gst/volume/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/ext/ogg/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/ext/vorbis/Android.mk +-include $(GST_PLUGINS_BASE_TOP)/tools/Android.mk diff --git a/gst-plugins-base-subtitles0.10/COPYING b/gst-plugins-base-subtitles0.10/COPYING new file mode 100644 index 0000000..60549be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +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 give any other recipients of the Program a copy of this License +along with the Program. + +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 Program or any portion +of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, 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 executable. However, as a +special exception, the source code 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. + +If distribution of executable or 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 counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program 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. + + 5. 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 Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program 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 to +this License. + + 7. 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 Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program 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 Program. + +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. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program 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. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 Program +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 Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, 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 + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), 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 Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. 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. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/gst-plugins-base-subtitles0.10/COPYING.LIB b/gst-plugins-base-subtitles0.10/COPYING.LIB new file mode 100644 index 0000000..eb685a5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/COPYING.LIB @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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 + + Appendix: 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. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! diff --git a/gst-plugins-base-subtitles0.10/ChangeLog b/gst-plugins-base-subtitles0.10/ChangeLog new file mode 100644 index 0000000..883a765 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ChangeLog @@ -0,0 +1,49339 @@ +=== release 0.10.34 === + +2011-05-14 Tim-Philipp Müller + + * configure.ac: + releasing 0.10.34, "Lemmings" + +=== release 0.10.33 === + +2011-05-10 09:32:11 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.33 + Highlights: + - support for 16-bit-per-component video formats + - playbin2 fixes and improvements for custom and non-raw sinks + - oggmux muxes based on running time now + - many other fixes and improvements + +2011-04-30 17:35:54 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * po/da.po: + * po/de.po: + * po/fr.po: + * po/uk.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.32.4 pre-release + +2011-04-30 17:21:28 +0100 Tim-Philipp Müller + + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/volume/gstvolumeorc-dist.c: + gst: update orc-generated disted C backup code to orc 0.4.14 + +2011-04-27 12:09:33 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * po/bg.po: + * po/nl.po: + * po/pl.po: + * po/ru.po: + * po/sl.po: + * po/tr.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.32.3 pre-release + +2011-04-24 18:45:40 -0700 David Schleef + + * gst/videoscale/vs_image.c: + videoscale: Fix off-by-one error in previous commit + Fix for 7c0b702e. It helps to get your j+1's right. + +2011-04-24 18:16:20 -0700 David Schleef + + * gst/videoscale/vs_image.c: + videoscale: Fix ARGB bilinear scaling + Fixes #648548. Orc generates bad code for + gst_videoscale_orc_resample_merge_bilinear_u32, so we'll use the + slightly slower two-stage process. I'd fix Orc, but it's hard to + get excited about fixing a feature that I'm planning to deprecate + and replace. + +2011-04-23 13:42:23 -0700 David Schleef + + * gst/videoscale/vs_image.c: + videoscale: hack to fix invalid reads in linear + https://bugzilla.gnome.org/show_bug.cgi?id=633837 + +2011-04-23 12:46:09 -0700 David Schleef + + * gst/videoscale/vs_4tap.c: + videoscale: protect 4tap from out-of-bounds reads + https://bugzilla.gnome.org/show_bug.cgi?id=633837 + +2011-04-24 14:03:12 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c3cafe1 to 46dfcea + +2011-04-23 12:44:50 -0700 David Schleef + + * gst/videoscale/gstvideoscale.c: + videoscale: use simpler scaling method for small images + https://bugzilla.gnome.org/show_bug.cgi?id=633837 + +2011-04-14 09:32:19 +0200 Marc Plano-Lesay + + * gst/audioresample/gstaudioresample.c: + audioresample: fix unused-but-set-variable warnings with gcc 4.6 + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-22 13:55:20 +0200 Víctor Manuel Jáquez Leal + + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + tag: exif: register common tags from tag library + Exif uses tags like image-vertical-ppi or image-horizontal-ppi which are + registered in gst_tag_register_musicbrainz_tags(), but neither GstExifReader + nor GstExifWriter register them. + https://bugzilla.gnome.org/show_bug.cgi?id=648459 + +2011-04-24 12:16:47 +0100 Tim-Philipp Müller + + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tag: update some FIXMEs for 0.11 + +2011-04-21 14:11:49 +0100 Tim-Philipp Müller + + * tests/check/elements/videoscale.c: + tests: add unit test for basetransform/videoscale negotiation regression + Turn Rene's test pipeline into a unit test. + https://bugzilla.gnome.org/show_bug.cgi?id=648220 + +2010-11-25 17:01:53 +0100 Håvard Graff + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: make sure to not start if the may_start flag is FALSE + Fixes #635784 + +2011-04-18 11:24:57 +0200 Sebastian Dröge + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: If NULL caps are passed to buffer_alloc() do fallback allocation + Fixes bug #647857. + +2011-04-18 10:19:52 +0200 Sebastian Dröge + + * tests/check/pipelines/oggmux.c: + oggmux: Remove bus GSource to prevent a valgrind warning + +2011-04-18 09:16:35 +0200 Sebastian Dröge + + * tests/check/pipelines/gio.c: + gio: Remove the bus GSource from the main context + Prevents a valgrind warning about possibly leaked memory, + see bug #647763. + +2011-04-17 19:33:04 +0100 Tim-Philipp Müller + + * gst-libs/gst/sdp/Makefile.am: + sdp: remove gst_init() for g-i scanner here again as well to avoid problems with -Wl,--as-needed + +2011-04-17 17:59:40 +0100 Tim-Philipp Müller + + * gst-libs/gst/fft/Makefile.am: + fft: remove gst_init() for g-i scanner again + libgstfft doesn't actually use any symbols from libgstreamer, so when + compiling with -Wl,--as-needed it won't even link to it, which can + cause failures with older versions of g-i that ignore the --pkg + arguments. + Should fix PPA build failure on Ubuntu Maverick + +2011-04-16 16:31:57 +0200 Sebastian Dröge + + * ext/pango/gsttextoverlay.c: + textoverlay: Always hold the class-global pango mutex when using pango API + +2011-04-16 16:23:47 +0200 Sebastian Dröge + + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttimeoverlay.c: + {time,clock}overlay: Hold the class-global pango mutex when changing the pango context + +2011-04-16 16:21:39 +0200 Sebastian Dröge + + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttimeoverlay.c: + {clock,time}overlay: Only set the global pango context options once in class_init + Instead of doing it over and over again when instantiating a new instance. + +2011-04-16 16:18:40 +0200 Sebastian Dröge + + * ext/pango/gsttextoverlay.c: + pango: Create a new pango context for every subclass + timeoverlay/clockoverlay are setting some global options + on the context that shouldn't be used for the generic textoverlay. + +2011-04-16 16:03:56 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/video-enumtypes.c: + 0.10.32.2 pre-release + +2011-04-16 15:58:21 +0100 Tim-Philipp Müller + + * gst/adder/gstadderorc-dist.c: + * gst/adder/gstadderorc-dist.h: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.h: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + gst: update disted orc backup code + +2011-04-16 15:50:05 +0100 Tim-Philipp Müller + + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + docs: update documentation + +2011-04-16 15:42:04 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/sk.po: + * po/sl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2011-03-31 17:56:00 +0000 Thibault Saunier + + * Android.mk: + * configure.ac: + * ext/vorbis/Makefile.am: + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisdec.h: + * ext/vorbis/gstvorbisdeclib.h: + vorbis: add support for using tremolo on android + Tremolo is an ARM-optimised version of xiph's tremor library. + +2011-04-15 13:36:39 +0100 Vincent Penquerc'h + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggmux: prefer headers from caps to determine stream type + Ogg mandates the first header packet must determine a stream's type. + However, some streams (such as VP8) do not include such a header + when muxed in other containers, and thus do not include this header + as a buffer, but only in caps. We thus use headers from caps when + available to determine a new stream's type. + https://bugzilla.gnome.org/show_bug.cgi?id=647856 + +2011-04-16 11:00:31 +0100 Tim-Philipp Müller + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + libs: gobject-introspection scanner doesn't need to scan or update plugin info + Make sure the scanner doesn't load or introspect or check any plugins, + (especially not outside the build directory). + +2011-04-15 21:09:00 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: list libs/struct*h files explicitly in Makefile.am + Hopefully makes the gentoo buildbot happy again. + +2011-04-15 11:11:52 +0200 Mark Nauwelaerts + + * gst/playback/gstplaybin2.c: + playbin2: avoid foregoing READY_TO_NULL when appropriate + +2011-04-14 22:13:21 +0200 Mark Nauwelaerts + + * gst/playback/gstplaybin2.c: + playbin2: ensure proper PAUSED_TO_READY cleanup + ... since going async to PAUSED might fail, and never making it to PAUSED + subsequently skips going down to READY. + Fixes #647781. + +2011-04-14 12:42:20 -0700 David Schleef + + * gst-libs/gst/video/video.c: + Revert "video: Remove the extensive checkings from switch" + This reverts commit 500d14c35c656890686574e1c041fb556df17056. + +2011-04-14 13:15:08 +0200 Sebastian Dröge + + * tests/check/elements/encodebin.c: + encodebin: Unref encoding profiles after usage in the test + +2011-04-14 12:55:00 +0200 Sebastian Dröge + + * tests/check/elements/encodebin.c: + encodebin: Release pads after setting the state to NULL in the unit test + See bug #647756. + +2011-04-14 12:23:10 +0200 Sebastian Dröge + + * gst/encoding/gstencodebin.c: + encodebin: Set all elements to NULL and remove them from the bin when removing a source group + +2011-04-14 00:26:34 +0300 Sreerenj Balachandran + + * gst-libs/gst/video/video.c: + video: Remove the extensive checkings from switch + The default case handles them already + +2011-04-13 23:17:34 -0300 Thiago Santos + + * tests/check/libs/tag.c: + tests: tag: Fix typo + +2011-04-13 23:17:14 -0300 Thiago Santos + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds mapping for GST_TAG_CAPTURING_EXPOSURE_COMPENSATION + Adds mapping for GST_TAG_CAPTURING_EXPOSURE_COMPENSATION for xmp + library. + Includes unit tests. + +2011-04-13 23:16:02 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds mapping for GST_TAG_CAPTURING_EXPOSURE_COMPENSATION + Adds mapping for GST_TAG_CAPTURING_EXPOSURE_COMPENSATION for exif + library. + Includes unit tests. + +2011-04-13 23:13:59 -0300 Thiago Santos + + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tag: Adds GST_TAG_CAPTURING_EXPOSURE_COMPENSATION + Adds a new tag for indicating the used exposure compensation + level in EV used when capturing an image. + API: GST_TAG_CAPTURING_EXPOSURE_COMPENSATION + +2011-04-14 00:24:26 +0100 Tim-Philipp Müller + + * tests/examples/encoding/gstcapslist.c: + * tests/examples/gio/giosrc-mounting.c: + * tests/examples/playrec/playrec.c: + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + tests: fix unused-but-set-variable warnings with gcc 4.6 + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-13 23:57:56 +0100 Tim-Philipp Müller + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggstream.c: + ogg: fix unused-but-set-variable warnings with gcc 4.6 + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-13 23:19:07 +0100 Tim-Philipp Müller + + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: fix unused-but-set-variable warnings with gcc 4.6 + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-13 22:59:03 +0100 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: fix unused-but-set-variable warning with gcc 4.6 + We don't compare the bitrates of consecutive mp3 frames on purpose + here. + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-13 09:10:52 +0100 Tim-Philipp Müller + + * gst-libs/gst/video/video.h: + docs: fix typo in video format docs + +2011-04-12 12:41:06 +0100 Tim-Philipp Müller + + * ext/ogg/gstoggmux.c: + oggmux: fix uninitialised variable usage and element leak + gcc on OSX complains about ret being used uninitialized in + this function, and it is right. Don't leak element ref + when returning early because newsegment event is not in + TIME format. + +2011-04-12 12:20:43 +0100 Tim-Philipp Müller + + * gst/tcp/gstmultifdsink.c: + multifdsink: do check return values of fcntl() and fstat() + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-09 19:15:23 +0200 Marc Plano-Lesay + + * gst/playback/gstplaybasebin.c: + * gst/subparse/tmplayerparse.c: + * gst/tcp/gstmultifdsink.c: + * gst/videoscale/vs_image.c: + fix unused-but-set-variable warnings with gcc 4.6 + https://bugzilla.gnome.org/show_bug.cgi?id=647294 + +2011-04-06 22:57:41 +0300 Sreerenj Balachandran + + * gst-libs/gst/rtsp/gstrtsptransport.c: + rtsptranport: ensure valid int result when parsing ranges + Specifically, make sure that the return value of strtol is falling in + between the range of G_MININT and G_MAXINT. + Fixes #646952. + +2011-04-06 16:27:54 +0100 Bastien Nocera + + * gst-libs/gst/pbutils/encoding-target.c: + encoding-profile: fix unused-but-set-variable warnings with gcc 4.6 + Top-level profiles don't have restrictions, only stream profiles, + so no need to serialise that here. + https://bugzilla.gnome.org/show_bug.cgi?id=646925 + +2011-04-11 14:29:35 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: dist all struct_*.h files for libs ABI test + Should fix distcheck on x86_64. + +2011-04-11 15:02:38 +0200 Mark Nauwelaerts + + * gst/videorate/gstvideorate.c: + videorate: empty caps have no structure to pick + +2011-04-11 10:06:53 +0100 Tim-Philipp Müller + + * gst-libs/gst/tag/gstid3tag.c: + tag: fix typo in ID3 genres + psychadelic -> psychedelic. Spotted by Sébastien Wilmet. + https://bugzilla.gnome.org/show_bug.cgi?id=647399 + +2011-01-27 17:28:51 +0100 Alessandro Decina + + * Android.mk: + * android/alsa.mk: + * android/app.mk: + * android/app_plugin.mk: + * android/audio.mk: + * android/audioconvert.mk: + * android/audioresample.mk: + * android/audiotestsrc.mk: + * android/decodebin.mk: + * android/decodebin2.mk: + * android/ffmpegcolorspace.mk: + * android/gdp.mk: + * android/gst-libs/gst/app/gstapp-marshal.c: + * android/gst-libs/gst/app/gstapp-marshal.h: + * android/gst-libs/gst/audio/audio-enumtypes.c: + * android/gst-libs/gst/audio/audio-enumtypes.h: + * android/gst-libs/gst/interfaces/interfaces-enumtypes.c: + * android/gst-libs/gst/interfaces/interfaces-enumtypes.h: + * android/gst-libs/gst/interfaces/interfaces-marshal.c: + * android/gst-libs/gst/interfaces/interfaces-marshal.h: + * android/gst-libs/gst/pbutils/pbutils-enumtypes.c: + * android/gst-libs/gst/pbutils/pbutils-enumtypes.h: + * android/gst-libs/gst/rtsp/gstrtsp-enumtypes.c: + * android/gst-libs/gst/rtsp/gstrtsp-enumtypes.h: + * android/gst-libs/gst/rtsp/gstrtsp-marshal.c: + * android/gst-libs/gst/rtsp/gstrtsp-marshal.h: + * android/gst-libs/gst/video/video-enumtypes.c: + * android/gst-libs/gst/video/video-enumtypes.h: + * android/gst/playback/gstplay-marshal.c: + * android/gst/playback/gstplay-marshal.h: + * android/gst/tcp/gsttcp-enumtypes.c: + * android/gst/tcp/gsttcp-enumtypes.h: + * android/gst/tcp/gsttcp-marshal.c: + * android/gst/tcp/gsttcp-marshal.h: + * android/interfaces.mk: + * android/netbuffer.mk: + * android/pbutils.mk: + * android/playbin.mk: + * android/queue2.mk: + * android/riff.mk: + * android/rtp.mk: + * android/rtsp.mk: + * android/sdp.mk: + * android/tag.mk: + * android/tcp.mk: + * android/typefindfunctions.mk: + * android/video.mk: + * android/videoscale.mk: + * android/videotestsrc.mk: + * ext/ogg/Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + * gst/adder/Makefile.am: + * gst/app/Makefile.am: + * gst/audioconvert/Makefile.am: + * gst/audiorate/Makefile.am: + * gst/audioresample/Makefile.am: + * gst/audiotestsrc/Makefile.am: + * gst/encoding/Makefile.am: + * gst/ffmpegcolorspace/Makefile.am: + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/gdp/Makefile.am: + * gst/playback/Makefile.am: + * gst/tcp/Makefile.am: + * gst/typefind/Makefile.am: + * gst/videorate/Makefile.am: + * gst/videoscale/Makefile.am: + * gst/videotestsrc/Makefile.am: + * gst/volume/Makefile.am: + * tools/Makefile.am: + android: make it ready for androgenizer + Remove the android/ top dir + Fixe the Makefile.am to be androgenized + To build gstreamer for android we are now using androgenizer which generates the + needed Android.mk files. + Androgenizer can be found here: + http://git.collabora.co.uk/?p=user/derek/androgenizer.git + +2011-04-09 02:01:08 +0100 Christian Fredrik Kalager Schaller + + * gst-plugins-base.spec.in: + Add new header file to spec file + +2011-04-08 15:10:02 +0200 Sebastian Dröge + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertppayload.c: + rtp: Unref events if the parent element disappeared or has no event handler implemented + +2011-01-06 18:20:58 +0100 Ole André Vadla Ravnås + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertppayload.c: + rtp: fix pad callbacks so they handle when parent goes away + 1) We need to lock and get a strong ref to the parent, if still there. + 2) If it has gone away, we need to handle that gracefully. + This is necessary in order to safely modify a running pipeline. Has been + observed when a streaming thread is doing a buffer_alloc() while an + application thread sends an event on a pad further downstream, and from + within a pad probe (holding STREAM_LOCK) carries out the pipeline plumbing + while the streaming thread has its buffer_alloc() in progress. + +2011-03-20 08:59:33 +0100 Havard Graff + + * gst/audioresample/gstaudioresample.c: + audioresample: Make src query MT-safe + It is possible that the element might be going down while the event arrives + +2011-04-08 15:00:58 +0200 Sebastian Dröge + + * ext/vorbis/gstvorbisdec.c: + vorbisdec: Unref events if the parent element disappeared + +2011-03-21 16:03:16 +0100 Havard Graff + + * ext/vorbis/gstvorbisdec.c: + vorbisdec: make upstream queries and events MT-safe + +2011-04-06 16:25:37 +0100 Bastien Nocera + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtp: Remove unused variables + https://bugzilla.gnome.org/show_bug.cgi?id=646924 + +2011-04-07 10:06:53 +0200 Sebastian Dröge + + * gst-libs/gst/video/video.c: + video: Fix creation of grayscale caps + The endianness was not set correctly before. + Fixes bug #646923. + +2011-04-06 16:11:02 +0200 Robert Swain + + * docs/design/part-interlaced-video.txt: + docs: Update interlaced video design document + The RFF flag is to be reused for buffers in the telecine state to + indicate that the buffer contains only unneeded repeated fields that are + present in other buffers and as such this buffer can be dropped. + +2011-03-25 16:59:51 +0100 Mark Nauwelaerts + + * ext/theora/gsttheoraenc.c: + theoraenc: refactor multipass file writing + +2011-02-08 14:02:20 +0100 Mark Nauwelaerts + + * gst/audioresample/gstaudioresample.c: + audioresample: minor simplification + ... which avoids crashing in the off-chance that structure == NULL. + +2011-04-05 18:14:49 +0300 Stefan Kost + + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/discoverer.c: + tests: add basic unit tests for discoverer + +2010-08-24 13:14:33 +0200 Pascal Buhler + + * gst-libs/gst/rtp/gstrtcpbuffer.c: + rtcpbuffer: Round to next 32bit word, not current 32bit word at end of SDES chunk + +2011-04-05 11:32:52 +0300 Stefan Kost + + * sys/xvimage/xvimagesink.c: + xvimagesink: don't paint the window black when going to NULL + Leave dealing with the appearance of the window when we are not playing to the + applications. We anyway want to go to NULL as quickly as possible. + Fixes #635800 + +2011-04-04 16:00:30 -0700 David Schleef + + * gst-libs/gst/video/video.c: + * tests/check/libs/video.c: + video: Fix YUV9 and YVU9 again + +2011-04-04 23:41:16 +0100 Tim-Philipp Müller + + * gst-libs/gst/tag/gstvorbistag.c: + tag: fix compiler warning on OSX + gstvorbistag.c: In function 'gst_tag_list_from_vorbiscomment_buffer': + gstvorbistag.c:371: warning: 'data' may be used uninitialized in this function + +2011-04-04 23:23:37 +0100 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + tests: ignore xmpwriter unit test binary + +2011-04-04 17:21:45 +0200 Haakon Sporsheim + + * gst-libs/gst/tag/gstexiftag.c: + tag: use gst/math-compat.h header. + https://bugzilla.gnome.org/show_bug.cgi?id=646744 + +2011-04-04 17:23:53 +0200 Haakon Sporsheim + + * gst-libs/gst/tag/xmpwriter.c: + tag: Remove constness to silence MS compiler. + https://bugzilla.gnome.org/show_bug.cgi?id=646744 + +2011-04-04 17:23:13 +0200 Haakon Sporsheim + + * gst-libs/gst/tag/gstxmptag.c: + tag: Explicit cast to GThreadFunc to silence MS compiler. + https://bugzilla.gnome.org/show_bug.cgi?id=646744 + +2011-04-04 15:56:50 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 1ccbe09 to c3cafe1 + +2011-03-11 10:41:11 +0100 Trond Andersen + + * gst-libs/gst/rtp/gstrtcpbuffer.c: + rtcpbuffer: fix invalid read in validation of padding in rtcp packet + +2011-02-23 10:55:12 +0100 Stian Johansen + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: Add src object lock around call to ringbuffer parse caps. + A race was observed between query() and setcaps() where the latter would + change the ringbuffer spec while the former was performing operations + based this data. + +2011-01-22 23:09:32 +0100 Havard Graff + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: protect against ringbuffer disappearing while in a query + Observed a case where the src went to null-state during the query, + hence the spec pointer was no longer valid, and + gst_util_unit64_scale_int crashed (assertion `denom > 0´failed) + Add locking to make sure the ringbuffer can't disappear. + +2011-02-08 18:27:43 +0100 Havard Graff + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: don't allow aligning behind the read-segment + Given a large enough drift-tolerance, one could end up in a situation + where one would keep aligning the written buffers behind the current + read-segment position. The result for the reader would be complete + silence, possible preceded by very choppy audio. + By checking the available headroom, one can determine if there is + room to do alignment, or if one should resort to a resync instead to get + the pointers back on track. + Also refactor the alignment-logic out of the render function for cleaner + code. + +2011-04-01 13:55:26 -0700 David Schleef + + * gst/encoding/Makefile.am: + * gst/playback/Makefile.am: + Remove setting of plugindir from Makefiles + +2011-03-23 23:10:51 -0700 David Schleef + + * gst-libs/gst/video/video.c: + * tests/check/libs/video.c: + video: Fix height calculation for YUV9/YVU9 + +2011-04-01 15:34:30 +0200 Josep Torra + + * ext/ogg/gstoggmux.c: + oggmux: fix warning building in mac os x + +2011-04-01 15:33:42 +0200 Josep Torra + + * ext/pango/gsttextoverlay.c: + textoverlay: fix comparison is always false due to limited range of data type + Perform calculation in a temp var with enough room as there's guarantee that + ret will be able to hold the result for example in _blit_AYUV. + +2011-04-01 12:52:05 +0200 Sebastian Dröge + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Write GST_TAG_IMAGE and GST_TAG_PREVIEW_IMAGE as METADATA_BLOCK_PICTURE + This is the official, standardized way of embedding images into + vorbiscomments now. + +2011-04-01 12:28:28 +0200 Sebastian Dröge + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Add support for METADATA_BLOCK_PICTURE tags + This is the official, standardized way of embedding pictures + inside vorbiscomments now. Parsing code taken from flacparse + and slightly changed. + Fixes bug #635669. + +2011-04-01 12:09:44 +0200 Sebastian Dröge + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Use g_base64_decode_inplace() + Instead of using the GLib base64 decoding functions manually to + do inplace base64 decoding. This makes the code easier to understand. + +2011-04-01 11:00:38 +0200 Sebastian Dröge + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + oggmux: Store the segment directly inside the pad + Also initialize it always in TIME format. We require TIME segments + in oggmux anyway and drop newsegment events in other formats and + assume an open-ended segment starting at 0. + +2011-04-01 10:57:08 +0200 Sebastian Dröge + + * ext/ogg/gstoggmux.c: + oggmux: Reset the segment on flush-stop events and when going back to READY + +2011-03-03 08:45:15 -0300 Thiago Santos + + * ext/ogg/gstoggmux.c: + oggmux: Use running time instead of timestamps + Theora and vorbis use running time (which is correct) for calculating + the granulepos for their ogg packets. Oggmux, however, used + timestamps to order the received buffers. + This patch makes it use the running time to compare buffer times + and also to timestamp pushed buffers. + Some bits of the code still use timestamps, but they are only + used to calculate durations, so it should be fine. + https://bugzilla.gnome.org/show_bug.cgi?id=643775 + +2011-02-16 16:07:49 -0300 Thiago Santos + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + oggmux: Keep track of pad's segments + https://bugzilla.gnome.org/show_bug.cgi?id=643775 + +2011-04-01 10:39:31 +0200 Sebastian Dröge + + * ext/pango/gsttextoverlay.c: + textoverlay: Add support for xBGR and RGBx + Now all RGB variants are supported. + +2011-01-17 21:12:18 -0700 Lane Brooks + + * ext/pango/gsttextoverlay.c: + textoverlay: Added support for ARGB and other RGB alpha variants + +2011-01-11 10:34:33 -0700 Lane Brooks + + * ext/pango/gsttextoverlay.c: + textoverlay: converted AYUV to use 'A OVER B' alpha compositing + 'A OVER B' compositing is explained at + http://en.wikipedia.org/wiki/Alpha_compositing. + Previously, overlaying text on a transparent background image left the + text overlay also transparent. This pipeline shows such an example: + gst-launch videotestsrc pattern=white ! video/x-raw-yuv,format=\(fourcc\)AYUV ! alpha alpha=0.0 ! textoverlay text=Testing auto-resize=False font-desc=60px ! videomixer ! ffmpegcolorspace ! autovideosink + With this patch, text is composited "OVER" the background image and + thus is visible regardless of the alpha of the background image. The + overlay in the above pipeline works after applying this patch. + +2011-03-28 22:00:25 +0200 Mark Nauwelaerts + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosink.h: + baseaudiosink: arrange for running clock when rendering eos + Commit ba2e500bd992d8ad7db0da923801964964835967 ensured to provide + a running clock when EOS had finished rendering. However, + other measures are needed (and were in place before) to ensure a + running clock when EOS still needs rendering (i.e. waiting). + So, specifically, re-introduce eos_rendering removed in aforementioned commit, + this time as a public variable so subclasses can be aware of the situation. + Fixes (part of) #645961. + API: GstBaseAudioSink:eos_rendering + +2011-03-31 12:37:32 +0200 Edward Hervey + + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_i386_osx.h: + tests: Fixes libsabi for MacOSX/32bit. + GStaticRecMutex is 60bytes on macosx/32bit (As opposed to 40). + Fixes #644996 + +2011-03-31 10:38:43 +0200 Sebastian Dröge + + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_x86_64.h: + libsabi: Add structure sizes for x86-64 + +2011-03-09 11:51:14 +0000 Tim-Philipp Müller + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + libs: make sure gobject-introspection scanner calls gst_init() + Cherry-picked from 0.11, since it's the right thing to do (we + now silently rely on various _get_type() working without + gst_init() having been called). + +2011-03-30 20:57:32 +0100 Tim-Philipp Müller + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + libs: replace 0.10 with @GST_MAJORMINOR@ in Makefile.am + For easier cherry-picking/merging later. + +2011-03-30 15:47:38 +0100 Tim-Philipp Müller + + * tests/check/gst/typefindfunctions.c: + * tests/files/Makefile.am: + * tests/files/hls.m3u8: + tests: add typefind test for application/x-hls + To make sure we don't break detection when we add typefinding + for normal m3u8 playlists. + +2011-03-30 15:44:45 +0100 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: rename type playlist/m3u8 to application/x-hls + We should keep playlist/m3u8 available for normal m3u8 playlists, + which we we'll likely support some day. Also, we probably don't + want this handled like other playlists, so application/* seems + more appropriate in this case, even if it's really just a playlist. + +2011-03-30 09:18:00 +0200 Sebastian Dröge + + * gst/typefind/gsttypefindfunctions.c: + typefind: Fix comment typo and add a link the the HTTP live streaming spec + +2011-03-30 09:12:25 +0200 Sebastian Dröge + + * gst/typefind/gsttypefindfunctions.c: + typefind: Use the DataScanCtx for the m3u8 typefinder + +2011-02-14 19:05:09 +0100 Andoni Morales Alastruey + + * gst/typefind/gsttypefindfunctions.c: + typefind: add m3u8 playlists + +2011-03-21 15:34:09 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/libs/xmpwriter.c: + tagxmpwriter: Add check tests + https://bugzilla.gnome.org/show_bug.cgi?id=645167 + +2011-03-17 15:42:28 -0300 Thiago Santos + + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gstxmptag.c: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/xmpwriter.c: + * gst-libs/gst/tag/xmpwriter.h: + * win32/common/libgsttag.def: + tagxmpwriter: Adds a new GstTagXmpWriter interface + The GstTagXmpWriter interface is to be implemented on elements that + provide xmp serialization. It allows users to select which + xmp schemas should be used on serialization. + API: GstTagXmpWriter + https://bugzilla.gnome.org/show_bug.cgi?id=645167 + +2011-03-18 09:28:23 -0300 Thiago Santos + + * gst-libs/gst/tag/gstxmptag.c: + * gst-libs/gst/tag/tag.h: + * win32/common/libgsttag.def: + tag: xmp: Add function to list the available schemas + Adds a function to list the available schemas in our xmp lib + https://bugzilla.gnome.org/show_bug.cgi?id=645167 + +2011-03-29 15:41:33 +0200 Sebastian Dröge + + * tests/check/elements/encodebin.c: + encodebin: Requesting a pad again now gives a g_return_val_if_fail() + Before the behaviour was undefined and implemented differently by elements, + now core checks for this (and other problems) and returns NULL and an assertion. + +2011-03-26 19:36:50 +0000 Tim-Philipp Müller + + * ext/ogg/gstoggparse.c: + oggparse: fix list iteration code + Not that it really matters, but let's fix it before someone + notices and makes fun of us. + +2011-03-26 12:01:05 +0000 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + tests: ignore new libsabi test binary + +2011-03-26 11:59:54 +0000 Tim-Philipp Müller + + * ext/ogg/gstoggparse.c: + oggparse: make sure buffer metadata is writable before setting caps on buffers + +2011-03-25 22:14:44 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 193b717 to 1ccbe09 + +2011-03-25 14:55:52 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From b77e2bf to 193b717 + +2011-03-25 11:06:35 +0200 Stefan Kost + + * docs/plugins/Makefile.am: + docs: do xrefs for non installed books too + Get the xrefs from the builddir for the books in the same package. This fixes + the cross references if one does not have the docs already installed. + +2011-02-25 16:46:29 +0100 Robert Swain + + * docs/design/part-interlaced-video.txt: + docs: Add an interlaced video design document + +2011-03-25 09:29:38 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From d8814b6 to b77e2bf + +2011-03-25 09:03:13 +0100 Sebastian Dröge + + * common: + Automatic update of common submodule + From 6aaa286 to d8814b6 + +2011-03-24 18:48:59 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 6aec6b9 to 6aaa286 + +2011-03-24 14:22:00 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + playsink: Update comment about why an audio queue is needed + +2011-03-24 14:21:01 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + Revert "playsink: Only add a queue before the audio sink if visualizations are enabled" + This reverts commit df886c0622257bb8635e5bd0fc7fc3da20bfc3be. + +2011-03-24 14:03:31 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + playsink: Only add a queue before the audio sink if visualizations are enabled + The queue is not needed otherwise and will add some delay to track + switches. + +2011-03-23 12:42:04 -0300 Thiago Santos + + * tests/check/libs/video.c: + tests: video: Uncommenting test + Pushed a commented test by accident, uncommenting it. + +2011-03-23 12:02:42 -0300 Thiago Santos + + * win32/common/libgstvideo.def: + video: adds missing function to win32 def + +2011-03-23 12:02:35 -0300 Thiago Santos + + * gst-libs/gst/video/video.c: + video: Getting component offsets without dimensions is fine if it is not YUV + This fixes a regression that an assertion would happen if + gst_video_get_component_offset would be called with width or + height as 0. + Calling it with 0 is fine if the format isn't yuv and this + was already being used in some other places of video.c + +2011-03-23 11:13:57 -0300 Thiago Santos + + * tests/check/libs/video.c: + tests: video: Add a test for checking rgb caps creation + This new test for checking rgb caps creation exposes a regression + +2011-03-15 14:45:03 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + playsink: Remember automatically created sinks for future reconfigures + Also allow reuse of sink elements in error cases. + +2011-03-16 15:27:51 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Check if an already existing sink supports the non-raw format too + Before we were assuming that a sink will always support all non-raw formats + in a single stream. + +2011-03-10 19:04:51 +0530 Arun Raghavan + + * gst/playback/gstplaybin2.c: + playbin2: Check if an element accepts requisite caps before selecting + In addition to ensuring that an element we want to select in + autoplug-select can enter the READY state, we also now check if it can + accept the caps we wish to plug it for. This is handy for sinks that + need to perform a probe to figure out whether they can actually handle a + given format. + +2011-03-16 15:56:34 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Set sinks to READY before checking if it accept caps + Fixes bug #642732. + +2011-03-16 15:56:34 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Always prefer the custom set sink and also set it back to NULL in all cases. + +2011-03-17 13:47:10 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Only consider the audio/video sinks in autoplug_continue for the normal uridecodebin + Considering them for the subtitle uridecodebin will add audio/video + streams that might be in a file used as subtitle file. + +2011-03-22 11:59:40 -0700 David Schleef + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add gst_video_format_new_template_caps() + +2011-02-24 08:42:34 -0300 Thiago Santos + + * gst/videoscale/gstvideoscale.c: + videoscale: Fix assertion on caps fixation + When fixating caps, from_par should always be initialized + with a fixed value. + In case the fixation is from src to sink pad it was setting + the from par (srcpad par) to a fraction range, this patch initializes + it to 1/1, based on the assumption that missing PAR is 1/1. + https://bugzilla.gnome.org/show_bug.cgi?id=641952 + +2011-03-22 12:44:49 +0100 Luis de Bethencourt + + * configure.ac: + configure.ac: redundant use of AC_MSG_RESULT() + cleaned the redundant use of AC_MSG_RESULT() in configure.ac + +2011-03-18 19:34:57 +0100 Luis de Bethencourt + + * autogen.sh: + autogen: wingo signed comment + +2011-03-21 19:22:30 +0100 Fraxinas + + * gst-libs/gst/pbutils/encoding-profile.c: + encoding-profile: Fix syntax in Example: Creating a profile + https://bugzilla.gnome.org/show_bug.cgi?id=645437 + +2011-03-21 18:33:03 -0300 Thiago Santos + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Add missing schema creation + tiff schema entries were being added to the previous + schema (xap) because a new one wasn't being created + for it. + +2011-03-17 21:50:15 -0400 Olivier Crête + + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtpbuffer: Off-by-one error when creating RTP header extensions with a two-byte header + +2011-03-16 15:38:31 +0200 Mart Raudsepp + + * ext/pango/gsttextoverlay.h: + textoverlay: Clean up alignment docs a bit and remove horiz top alignment enum + +2011-02-07 09:13:39 +0200 Mart Raudsepp + + * tests/check/Makefile.am: + check: Really fix the linking order of libs/tag + Follow-up to commit 5f5c52c, which only fixed the CFLAGS order. + Fix the linker order as well. + +2011-03-16 10:19:42 +0000 Tim-Philipp Müller + + * gst/playback/gsturidecodebin.c: + uridecodebin: post proper error message if decodebin2/typefind elements are missing + Post better error messages in case typefind/decodebin2 are missing or + could not be loaded for some reason (e.g. because they inadvertently + got blacklisted). + https://bugzilla.gnome.org/show_bug.cgi?id=644892 + +2011-03-15 19:47:11 +0100 Blaise Gassend + + * ext/alsa/gstalsamixer.c: + alsamixer: Store return values of poll functions in a signed integer + Negative return values are used for errors and storing + them in an unsigned integer will make it impossible to + detect the errors. + Fixes bug #644845. + +2011-03-14 19:42:49 +0100 Sebastian Dröge + + * ext/ogg/gstoggmux.c: + oggmux: Increase the seen header packets count when seeing a header packet + This fixes muxing of Speex content and possibly other formats where the + header detection works by counting the packets. + Fixes bug #644745. + +2011-03-14 18:35:27 +0000 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefinding: add depth and endianness to DTS caps + https://bugzilla.gnome.org/show_bug.cgi?id=644208 + +2011-03-14 11:14:04 +0200 Stefan Kost + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: use a class wide mutex to work around pango reentrance issues + Pango is not reentrant. Use a class wide mutex to protect pange use in + gst_text_overlay_render_pangocairo(). This works reliable in contrast to the + hack in my previous commit. + Fixes Bug #412678 + +2011-03-14 11:12:53 +0200 Stefan Kost + + * ext/pango/gsttextoverlay.c: + Revert "textoverlay: add a hack to init the pango engine" + This reverts commit fee3266056b522cdd34e606b5682553d35eec5a1. + +2011-03-14 10:09:35 +0200 Stefan Kost + + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybin2.c: + plaback: trim trailing whitespace + +2011-03-14 10:05:34 +0200 Stefan Kost + + * gst/playback/gstdecodebin2.c: + decodebin2: reflow configuring new multiqueue instance + Use a single g_object_set to configure the new multiqueue instance. Also don't + needlessly set "use-buffering" if it is the default. + +2011-03-04 14:52:01 +0200 Stefan Kost + + * ext/pango/gsttextoverlay.c: + textoverlay: drop trailing whitespaces + +2011-03-04 14:52:28 +0200 Stefan Kost + + * ext/pango/gsttextoverlay.c: + textoverlay: add a hack to init the pango engine + Layout a single char to pre-create all resources. + +2011-03-12 17:51:41 +0000 Tim-Philipp Müller + + * configure.ac: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/gstlibscpp.cc: + tests: add libscpp unit test to make sure g++ likes our library headers + +2011-03-10 14:22:38 -0300 Thiago Santos + + * tests/check/elements/encodebin.c: + tests: encodebin: Add reuse test case + Adds a test case to check if encodebin can be reused + https://bugzilla.gnome.org/show_bug.cgi?id=644416 + +2011-03-10 14:38:47 -0300 Thiago Santos + + * gst/encoding/gstencodebin.c: + encodebin: Tear down old profiles when setting new ones + In NULL/READY, we should be able to switch profiles on encodebin, + this patch makes it tear down old profiles when new ones are set + if in NULL/READY states + https://bugzilla.gnome.org/show_bug.cgi?id=644416 + +2010-10-22 14:01:26 +0200 Andoni Morales Alastruey + + * gst/tcp/gstmultifdsink.c: + multifdsink: disconnect inactive clients in the select loop too + Clients are usually disconnected in the streaming thread if their inactivity + is bigger than the timeout. If no new buffers are to be rendered in the sink, + these clients will never be disconnected and for that reason it should be + handled in the select() loop too. + +2010-11-03 14:37:07 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Don't wait for subtitle streams to preroll + Subtitle streams being parse can cause the pipeline to wait indefinitely + to PREROLL. This makes subtitle streams got to PAUSED even if no data is + available. This should not be a cause for concern as we don't expect to + get much data for subtitle streams other than language tags from the + container. + https://bugzilla.gnome.org/show_bug.cgi?id=632291 + +2011-03-03 19:14:38 +0100 Mark Nauwelaerts + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: start ringbuffer upon going to PLAYING and already EOS + ... otherwise we may end up without running clock in PLAYING. + Fixes #636886. + +2011-03-04 14:39:45 +0200 Stefan Kost + + * gst/playback/gstplaybin2.c: + playbin2: set several properties in one go + g_object_set is a varargs function. Save 7 g_obvject_calls (and the overhead of + them) by using it accordingly. + +2011-03-02 15:38:01 +0000 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: fix compiler warning on 32-bit systems + Mark 64-bit interger constant as such to avoid warnings such as: + gsttypefindfunctions.c:2152: error: integer constant is too large for ‘long’ type + +2011-02-28 18:52:47 +0100 Mark Nauwelaerts + + * configure.ac: + configure.ac: export plugin description more platform independent + Fixes #642504. + +2011-02-28 18:32:33 +0100 Mark Nauwelaerts + + * common: + Automatic update of common submodule + From 1de7f6a to 6aec6b9 + +2011-02-28 10:10:22 +0200 Stefan Kost + + * tests/check/Makefile.am: + * tests/check/libs/libsabi.c: + * tests/check/libs/struct_i386.h: + tests: add ABI test suite for libs + +2011-02-27 09:32:55 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Only prevent to autoplug the same parser multiple times for the same chain + Parsers are the only element class that are not changing the data and + could lead to an infinite loop. Other element classes like demuxers, + e.g. id3demux, can be used multiple times in a row and sometimes are. + +2011-02-26 23:43:39 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Break the double-factory checking loop immediately if the factory was used already + +2011-02-26 23:39:03 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't use the same element multiple times in the same chain + This is going to lead to an infinite loop of this element and can easily + happen with parsers that accept their own src caps on the sinkpad. + +2011-02-26 23:20:42 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Improve detection of raw caps in expose-all-streams=false mode + Previously we only checked against the raw caps but we should also + check against the return value of autoplug-continue. Additionally fix + a thread-safety issue with accessing the raw caps. + +2011-02-25 19:37:07 -0800 David Schleef + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add support for r210 + +2011-01-03 11:41:56 +0100 Robert Swain + + * gst-libs/gst/video/video.h: + gstvideo: Add GST_VIDEO_BUFFER_PROGRESSIVE flag + Maps to GST_BUFFER_FLAG_MEDIA4. The purpose is to explicitly indicate + whether a telecined buffer is progressive or not without having to make + assumptions based on previous buffers. + +2011-02-24 20:59:48 +0100 Sebastian Dröge + + * tests/check/elements/encodebin.c: + encodebin: Fix double unref in unit test + +2011-02-22 14:54:55 +0000 Tim-Philipp Müller + + * tests/check/elements/playbin2.c: + checks: add a simple unit test for the source-setup signal + +2011-02-22 12:56:48 +0000 Tim-Philipp Müller + + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playbin2, uridecodebin: add "source-setup" signal + Add "source-setup" signal for convenience and discoverability. No need + to figure out "notify::source", look up the notify callback signature, + then do an g_object_get() to get the source element.. + https://bugzilla.gnome.org/show_bug.cgi?id=626152 + +2011-02-24 16:22:53 +0100 Sebastian Dröge + + * ext/ogg/gstoggmux.c: + oggmux: Don't handle GstCollectData as GstObject, use the pad instead + +2011-02-24 16:02:50 +0100 Sebastian Dröge + + * tests/check/elements/encodebin.c: + encodebin: Fix memory leaks related to request pads + Request pads have to be released by the caller and must be + unreffed after releasing them. + +2011-02-24 15:55:00 +0100 Sebastian Dröge + + * gst/encoding/gstencodebin.c: + encodebin: Return a new reference of the pad for the "request-pad" signal + The GObject signal code assumes that the signal handlers return a + new reference or copy. Fixes bug #641927. + +2011-02-21 20:34:41 -0800 Leo Singer + + * gst/adder/gstadder.c: + adder: Fill in offset_end field of outgoing buffers + ... rather than leave it as GST_BUFFER_OFFSET_NONE + Fix bug #642942. + +2011-02-23 14:31:13 +0100 Mark Nauwelaerts + + * gst/playback/gstplaysink.c: + playsink: release all chains when going to NULL + Also fixes #642466. + +2011-02-23 14:29:03 +0100 Mark Nauwelaerts + + * gst/playback/gstplaysink.c: + playsink: undo state change side effect on error way out + ... to avoid subsequent cleanup disposing an element not in NULL state. + +2011-02-23 10:32:08 +0100 Mark Nauwelaerts + + * gst/playback/gstplaysink.c: + playsink: avoid crashing on the way out when needed chain missing + +2011-02-22 15:26:14 +0000 Tim-Philipp Müller + + * win32/common/libgstvideo.def: + win32: update .def file for new libgstvideo API + +2011-02-22 16:41:54 +0200 Stefan Kost + + * tools/gst-discoverer.c: + discoverer: handle desc==NULL + It would otherwise be printed as (null) and mess up indentation (no \n). + +2011-02-08 12:42:32 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Chain dispose() up to parent class + +2011-02-07 13:04:55 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Keep a ref for the async timeout callback + This makes sure we maintain a ref on the discoverer object while the + async timeout callback is alive to prevent a potential crash if the + object is freed while the callback is pending. + https://bugzilla.gnome.org/show_bug.cgi?id=641706 + +2011-02-07 13:57:39 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Use g_signal_connect_object instead of g_signal_connect + We want to make sure the discoverer object passed to the various + callbacks doesn't become invalid if a callback is pending and the object + is free'd in the mean time. + https://bugzilla.gnome.org/show_bug.cgi?id=641706 + +2011-02-10 03:22:42 +1100 Parthasarathi Susarla + + * gst/typefind/gsttypefindfunctions.c: + typefinding: detect raw h.263 + https://bugzilla.gnome.org/show_bug.cgi?id=623846 + +2011-02-21 15:58:16 +0200 Teemu Katajisto + + * gst-libs/gst/pbutils/encoding-target.c: + pbutils: encoding-target: fix error checking in target file loading + https://bugzilla.gnome.org/show_bug.cgi?id=642949 + +2011-02-21 17:55:04 +0000 Tim-Philipp Müller + + * tests/check/elements/videoscale.c: + tests: fix videoscale test by ignoring newly-added 64-bit formats + They probably fail because ffmpegcolorspace can't handle those formats. + +2011-02-21 18:01:04 +0100 Benjamin Otte + + * gst-libs/gst/sdp/Makefile.am: + sdp: Fix copy/paste error in inrospection part of Makefile + +2011-02-21 18:00:36 +0100 Benjamin Otte + + * gst-libs/gst/tag/Makefile.am: + tag: Fix copy/paste error in inrospection part of Makefile + +2011-02-21 18:00:02 +0100 Benjamin Otte + + * gst-libs/gst/rtsp/Makefile.am: + rtsp: Fix copy/paste error in inrospection part of Makefile + +2011-02-21 12:40:36 +0100 Mark Nauwelaerts + + * gst/audiorate/gstaudiorate.c: + * gst/audiorate/gstaudiorate.h: + audiorate: add skip-to-first property + API: GstAudioRate::skip-to-first + +2011-02-21 12:27:17 +0100 Mark Nauwelaerts + + * gst/videorate/gstvideorate.c: + videorate: fix skip-to-first ts setup + ... such as avoiding arithmetic mixing counts and ts, although latter + would typically be 0 so far. + +2011-02-21 12:04:09 +0100 Edward Hervey + + * ext/ogg/gstoggmux.c: + * gst/adder/gstadder.c: + Revert "oggmux,adder: Check if collectpads has been freed" + This reverts commit 6d150873e8b4c23d694b0351570de323b1576d76. + Depends on a core commit that was reverted. + +2011-02-20 23:49:54 -0800 David Schleef + + * ext/ogg/gstoggmux.c: + * gst/adder/gstadder.c: + oggmux,adder: Check if collectpads has been freed + Core now calls release_pad in finalize, which is usually after + the collectpads has been unreffed. + +2011-02-19 18:50:37 -0800 David Schleef + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + * gst/videoscale/vs_fill_borders.c: + * gst/videoscale/vs_fill_borders.h: + * gst/videoscale/vs_image.c: + * gst/videoscale/vs_image.h: + * gst/videoscale/vs_scanline.c: + * gst/videoscale/vs_scanline.h: + videoscale: Add 16-bit-channel support + +2011-02-19 16:41:43 -0800 David Schleef + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add 16-bit-per-channel formats + +2011-02-19 12:03:17 -0800 David Schleef + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add ARGB64 and AYUV64 + 16-bit per channel formats. + +2011-02-18 16:26:59 -0800 David Schleef + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add gst_video_format_get_component_depth() + +2011-02-18 13:27:23 -0800 Leo Singer + + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/audiotestsrc/gstaudiotestsrc.h: + audiotestsrc: each element gets its own instance of GRand, if needed + As a result, pipelines that contain multiple instances of audiotestsrc + with the 'wave' property set to 'white-noise', 'pink-noise', or + 'gaussian-noise' will run much faster, since they won't be competing + for access to the global, lock-protected instance of GRand. + Fixes bug #642720. + +2011-02-18 17:26:53 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: If a sink claims to support ANY caps assume that it only supports the usual raw formats + This should be changed again in 0.11, if a sink really claims to support ANY + caps it should support everything or provide correct caps. + +2011-02-17 18:11:10 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + encodebin: Add a audioconverter after the audio resampler. + This allows handling non-native-endianness conversion properly. + +2011-02-18 14:04:38 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Use gst_pad_accept_caps() instead of intersecting with the getcaps caps + This might be faster and more accurate in some cases to detect if a + sink supports a format and autoplugging can be stopped. + +2011-02-18 12:06:30 +0100 Sebastian Dröge + + * gst/playback/gsturidecodebin.c: + uridecodebin: Add default handler for autoplug-select + uridecodebin proxies this signal and only the first signal handler + will ever be called from decodebin2, which is uridecodebin's proxy + signal handler. + +2011-02-18 12:02:07 +0100 Sebastian Dröge + + * gst/playback/gsturidecodebin.c: + uridecodebin: Return NULL from the default autoplug-sort handler + ...instead of copying the array. Returning NULL will result + in the original factories array to be used and prevents a useless + array copy in most use cases. + +2011-02-18 12:01:05 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Return NULL from the default autoplug-sort handler + ...instead of copying the array. Returning NULL will result + in the original factories array to be used and prevents a useless + array copy in most use cases. + +2011-02-18 12:00:34 +0100 Sebastian Dröge + + * gst/playback/gsturidecodebin.c: + uridecodebin: Update autoplug-* signal docs from decodebin2 + uridecodebin proxies these signals. + +2011-02-18 11:58:44 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Update documentation of the autoplug-* signals + Add notes about the behaviour if multiple signal handlers are connected. + For most autoplug-* signals only the first signal handler will ever + be invoked. + Also add to the autoplug-sort docs that the signal handler can return NULL + to specify that the order should change and other handlers get the chance + to sort the array. + +2011-02-18 11:57:12 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Keep the original factory list if the sort signal handlers returned NULL + +2011-02-16 20:14:25 +0900 tskd2@yahoo.co.jp + + * gst/playback/gsturidecodebin.c: + uridecodebin: expose "autoplug-sort" signal + It is a proxy of the decodebin2's one, and was missing + in the previous code. + See bug #642433. + +2011-02-18 10:57:40 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Use a recursive mutex for the playbin lock + This lock is taken when activating a group, which could result in + calling the autoplug-continue callback, which also needs this lock + to access the sinks. + See bug #642174. + +2011-02-18 09:36:34 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Disconnect signal handlers when removing a failed element + This prevents crashes later if one of the signals is emitted after the + element was removed from decodebin2 already, which can happen in discoverer. + +2011-02-15 19:23:48 -0800 David Schleef + + * gst/typefind/gsttypefindfunctions.c: + typefind: Fix mpeg TS detection + +2011-02-04 17:36:40 -0800 David Schleef + + * ext/theora/gsttheoraenc.c: + theoraenc: move debug category init earlier + +2011-02-03 22:41:23 -0800 David Schleef + + * ext/ogg/gstoggparse.c: + * ext/ogg/gstoggstream.h: + oggparse: better detection of delta unit flag + +2011-01-15 18:21:28 -0800 David Schleef + + * ext/theora/gsttheoraenc.c: + theoraenc: Set speed level while running + +2011-01-13 15:12:53 -0800 Ralph Giles + + * ext/theora/gsttheoraenc.c: + Set the theoraenc speed-level property from libtheora's defaults. + The speed-level property, which allows callers to trade of encoding + quality for speed in the libtheora api, has a version-dependent + maximum and default values. Instead of hardcoding the acceptable + range for the theoraenc element's presentation of this setting, + we query the library directly at class initialization time and + set the maximum and default values from that. If the query fails, + we fall back to the previous default setting. + To keep the values reported by gst-inspect (which I'm told use + the spec values from the class) with those available on an\ + instantiated element, we remove to setting of enc->speed_level + from the initializer and instead pass G_PARAM_CONSTRUCT to + the property spec flags, asking g_object to set this property + when theoraenc objects are constructed. + NB in theory the maximum speed-level could depend on the actual + video caps. If later versions of libtheoraenc do this, a second + call will need to be made from theora_enc_reset to update the + property, since this function is mostly useful for realtime + adjustment of performance while the pipeline is running. + +2011-02-16 11:57:31 +0200 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: don't leak parent tags + +2011-02-16 11:56:16 +0200 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: improve logging (and reindent) + Add more logging for the tag merging and use the _OBJECT flavour more. + +2011-02-15 17:46:22 +0100 Sebastian Dröge + + * gst/playback/gstplaybin2.c: + playbin2: Optimize autoplug-continue handler a bit + Don't build merge the caps of all sinks but check them one-by-one + until one supports the caps. Also get reffed caps from the sinkpads + instead of a writable copy and add debug output if a sink claims to + support ANY caps. + +2011-02-15 17:24:28 +0100 Akihiro Tsukada + + * gst/playback/gstplaybin2.c: + playbin2: Fix handling of non-raw custom sinks + When autoplugging elements in decodebin2, check if + the caps are supported by one of the sink before + continuing autoplugging. + Fixes bug #642174. + +2011-02-15 17:01:13 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't leak elements that fail to go to PAUSED after being autoplugged + Fixes bug #642381. + +2011-02-13 14:42:14 +0000 Sjoerd Simons + + * ext/theora/gsttheoraenc.c: + theoraenc: Don't reset the video quality setting the bitrate + libtheora has two encoding modes, CBR, where it tries to hit a target + bitrate and VBR where it tries to achieve a target quality. + Internally if the target bitrate is set to anything other then 0 the + encoding-mode is CBR. + This means that the gstreamer element can leave the video_quality + setting alone as long as the user is tweaking the bitrate. Which has the + nice side-effect that if the user explicitely sets the bitrate to 0 + (which is actually the default), the quality value doesn't get reset and + one ends up encoding VBR at quality-level 0... + +2011-02-09 12:45:23 +0100 Andoni Morales Alastruey + + * gst/gdp/gstgdppay.c: + gdppay: ensure buffer's metadata is writable before setting caps + +2011-02-14 12:52:59 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From f94d739 to 1de7f6a + +2011-02-10 23:44:43 +0000 Tim-Philipp Müller + + * gst-plugins-base.doap: + doap: update mailing list location + +2011-02-08 23:58:56 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Use nominal bitrate if bitrate tag is unavailable + If the bitrate tag is unavailable, this falls back to the nominal + bitrate tag instead, if that is present. + https://bugzilla.gnome.org/show_bug.cgi?id=641860 + +2011-02-08 12:31:34 +0200 Stefan Kost + + * gst/playback/gstdecodebin2.c: + decodebin2: caps can be NULL + Don't use and unref NULL caps. + +2011-02-02 16:49:04 +0100 Mark Nauwelaerts + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: also push cached events downstream when operating in pull mode + Otherwise, having 2 tagdemux in a row followed by an element operating in + pull mode will make the second tagdemux implictly eat the first tagdemux' + tag event(s). + Fixes (part of) #641047. + +2011-01-21 18:10:29 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggmux.c: + oggmux: ensure serialnos are unique + We do that by checking a newly generated one is not already used in + an existing stream, and doing it again if it is. + https://bugzilla.gnome.org/show_bug.cgi?id=640211 + +2011-02-02 17:30:15 +0000 Tim-Philipp Müller + + * ext/ogg/gstoggmux.c: + oggmux: free stream map caps when done + +2011-02-02 17:23:43 +0000 Tim-Philipp Müller + + * ext/ogg/gstoggmux.c: + oggmux: keep IN_CAPS flag check for header buffers as fallback + In case the ogg mapper doesn't handle all the accepted input formats + (although it really should). Saves us error handling for that case + though. Also log caps properly. + https://bugzilla.gnome.org/show_bug.cgi?id=629196 + +2011-01-21 16:05:46 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + oggmux: use oggstream for less brittleness in recognizing headers + Using the IN_CAPS flag for this is brittle, and will fail if either + vorbisparse or vorbistag (which is itself based on vorbisparse) is + inserted between oggdemux and oggmux. Possibly other elements too + (eg, theoraparse, etc). + Using oggstream ensures we Get It Right More Often Than Not. + https://bugzilla.gnome.org/show_bug.cgi?id=629196 + +2011-02-02 15:33:36 +0100 Mark Nauwelaerts + + * gst/playback/gsturidecodebin.c: + uridecodebin: fix copy-and-paste typo in property docs + +2011-01-21 10:56:00 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + oggmux: do not skip a pageno at start + Discontinuities are automatically signalled by oggdemux at the start + of a new stream. When oggmux is yet to output actual data pages, + do not signal these discontinuities in the ogg stream. + This patch may miss some actual discontinuities at the very start of + a stream, but avoids the spurious missing pages when encoding happens + normally. + A better fix might involve finding a way to distinguish between actual + data discontinuities and discontinuities merely marking the start of + a new stream. + Fixes an issue with ogg page numbering (would skip a number for no + reason, which then looks like a packet was lost somewhere) when + re-muxing an ogg stream, e.g. when re-tagging in rhythmbox. + https://bugzilla.gnome.org/show_bug.cgi?id=629196 + +2011-02-01 15:57:14 +0000 Tim-Philipp Müller + + * ext/theora/gsttheoraenc.c: + theoraenc: clean up property descriptions + Remove "This property requires libtheora version >= 1.1" qualifiers + from property descriptions. They aren't needed any longer now that + we require libtheora >= 1.1. + +2010-08-19 22:31:07 +0300 Sreerenj Balachandran + + * configure.ac: + * gst-libs/gst/tag/gstid3tag.c: + id3tag: map the ID3v2 TENC frame to GST_TAG_ENCODED_BY + https://bugzilla.gnome.org/show_bug.cgi?id=627268 + +2011-01-29 20:43:08 +0100 Mark Nauwelaerts + + * gst/tcp/gsttcpserversink.c: + tcp: use socklen_t where appropriate rather than specific type + In particular, fixes Cygwin build where socklen_t is defined as int + in line with native win32 api definition. + +2011-01-29 19:40:23 +0100 Mark Nauwelaerts + + * gst-libs/gst/tag/gstxmptag.c: + xmptag: cast argument to isdigit to int + ... as that is the specification and fixes compilation on Cygwin: + gstxmptaag.c: In function 'read_one_tag': + gstxmptag.c:1015: error: array subscript has type 'char' + +2011-01-31 18:06:18 +0000 Tim-Philipp Müller + + * gst-libs/gst/app/gstappsink.c: + * tests/check/elements/appsink.c: + appsink: add buffer fallback in case the application doesn't handle buffer lists + We shouldn't assume the application handles buffer lists, for + ease-of-use reasons and for backwards compatibility reasons. + +2011-01-26 10:32:32 +0800 Cai Yuanqing + + * gst-libs/gst/app/gstappsink.c: + appsink: send new-buffer-list signal + Send new-buffer-list signal when emit-signals is TRUE + https://bugzilla.gnome.org/show_bug.cgi?id=640607 + +2011-01-20 16:25:42 +0100 Wim Taymans + + * gst/playback/gsturidecodebin.c: + uridecodebin: also add https to buffer protocols + HTTPS also needs buffering. + +2011-01-30 15:40:53 +0200 Felipe Contreras + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: trivial cleanups + It seems these stuff was neglected from commmit d8942e2. + Signed-off-by: Felipe Contreras + +2011-01-27 15:26:25 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + win32: fix DEFAULT_AUDIOSINK, should be direct*sound*sink + https://bugzilla.gnome.org/show_bug.cgi?id=640705 + +2011-01-27 12:32:35 +0100 Philippe Normand + + * gst/typefind/gsttypefindfunctions.c: + typefinding: register H264 typefinder with H264 caps + https://bugzilla.gnome.org/show_bug.cgi?id=640709 + +2011-01-26 12:16:58 -0300 Thiago Santos + + * gst/encoding/gststreamsplitter.c: + streamsplitter: release pending events refs + Unref pending events when disposing the streamsplitter. + Also refactor a little to replace a for with a g_list_foreach + +2011-01-26 15:42:48 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: don't run encodebin test if vorbis or theora plugins aren't available + +2011-01-26 09:07:26 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for degas images + +2011-01-26 09:06:10 +0000 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefinding: use image/x-icon as media type for ICON files + That's what we've been using so far (e.g. gdkpixbufdec). + +2011-01-18 10:20:29 +0200 Stefan Kost + + * tests/examples/snapshot/snapshot.c: + snapshot: use a keyframe seek + One would usualy get good quality snapshots quickly. The exact seek position + does not really matter. + +2011-01-17 23:13:29 +0200 Stefan Kost + + * tests/examples/snapshot/snapshot.c: + snapshot: add a newline to the usage and error output + +2011-01-25 18:03:23 +0200 Stefan Kost + + * gst/playback/gstdecodebin2.c: + decodebin2: add comment and whitespace trimming + +2011-01-12 14:03:12 +0200 Stefan Kost + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for x-annodex + +2011-01-25 13:39:25 +0000 Vincent Penquerc'h + + * gst/typefind/gsttypefindfunctions.c: + typefind: add typefinder for DEGAS images + This fixes at least one DEGAS image from being misdetected as DTS audio. + https://bugzilla.gnome.org/show_bug.cgi?id=625129 + +2011-01-21 14:56:28 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggmux.c: + oggmux: cleanup + Remove a pointless string concatentation, and fix an off-by-one in + packetno in a log. + https://bugzilla.gnome.org/show_bug.cgi?id=640189 + +2011-01-24 11:45:21 +0000 Vincent Penquerc'h + + * gst/typefind/gsttypefindfunctions.c: + typefind: add detection for windows icon files to get them out of the way + Some of them can otherwise be misdetected for MPEG audio. + https://bugzilla.gnome.org/show_bug.cgi?id=620364 + +2011-01-17 15:11:15 +0200 Sreerenj Balachandran + + * ext/ogg/gstoggdemux.c: + oggdemux: Remove dead code + +2011-01-11 15:10:42 +0800 Yang Xichuan + + * ext/ogg/gstoggparse.c: + oggparse: Make gst_ogg_parse_submit_buffer() safe + By not passing zero-sized buffers to ogg_sync_buffer() + and checking the return values of libogg functions. + Fixes bug #639136. + +2011-01-11 18:18:34 +0100 Lane Brooks + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: Add support for vertical center alignment + Fixes bug #639159. + +2011-01-24 15:21:10 -0300 Thiago Santos + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Move static variable to local function + Variable was being written to and could cause crashes + if multiple elements were parsing xmp at the same time. + Moving it to local scope solves the problem. + +2011-01-24 18:27:30 +0100 Edward Hervey + + * gst-libs/gst/riff/riff-media.c: + riff: Add support for video/x-camstudio + +2011-01-24 00:00:27 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + Back to development + +=== release 0.10.32 === + +2011-01-21 10:50:06 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.32 + +2011-01-18 10:45:01 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.31.4 pre-releases + +2011-01-18 10:44:01 +0000 Tim-Philipp Müller + + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + docs: update docs + +2011-01-18 10:40:29 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/encoding-target.c: + * tests/check/libs/profile.c: + encoding-target: change keyfile header to 'GStreamer Encoding Target' + which is more in line with other files such as .desktop files. + +2011-01-18 01:06:50 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/encoding-target.c: + pbutils: don't assume LC_MESSAGES is always defined, also check for ENABLE_NLS + Should fix build with mingw32 build bot again. + +2011-01-18 00:09:37 +0000 Tim-Philipp Müller + + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/app/gstappsrc.h: + * win32/common/libgstapp.def: + app: export gst_app_stream_type_get_type() + API: gst_app_stream_type_get_type() + API: GST_TYPE_APP_STREAM_TYPE + https://bugzilla.gnome.org/show_bug.cgi?id=639747 + +2011-01-17 23:59:48 +0000 Tim-Philipp Müller + + * gst-libs/gst/app/gstappbuffer.c: + app: make GstAppBuffer get_type() function thread-safe + +2011-01-18 01:09:53 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Drop new stream tags once preroll is done + This makes sure we do not touch the stream taglist once the pipeline has + been prerolled. Adding of stream tags happens in the pad event probe + which runs in a different thread from discoverer stream processing, so + modifying the tag list while discoverer might be processing it can + sometimes cause a crash. + https://bugzilla.gnome.org/show_bug.cgi?id=639778 + +2011-01-17 15:30:08 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Validate timeouts before processing them + This avoids a race where the timeout callback is scheduled to run but we + get sufficient information to finish discovery before actually getting + around to executing the callback. See the documentation of + g_source_is_destroyed() for more details. + https://bugzilla.gnome.org/show_bug.cgi?id=639730 + +2011-01-18 00:08:32 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Make sure we call _stop() before being freed + This ensures that everything is properly cleaned up before the + GstDiscoverer object is freed. Specifically, it makes sure that we've + removed the async timeout callback before freeing the object to avoid a + potential crash later on. + https://bugzilla.gnome.org/show_bug.cgi?id=639755 + +2011-01-16 14:55:46 -0800 David Schleef + + * gst/gdp/gstgdppay.c: + gdppay: make newsegment buffer metadata writable + +2011-01-16 16:46:22 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/encoding-target.c: + pbutils: save localised strings properly when writing encoding targets to a file + Use LC_MESSAGES rather than LC_ALL. Save/load description as untranslated string + when using an English language locale. Strip locale information to the language, + so we don't save keys like description[fr_FR.UTF-8]=... + https://bugzilla.gnome.org/show_bug.cgi?id=638860 + +2011-01-13 13:59:41 +0000 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefinding: set framed=false on DTS caps + +2011-01-12 17:51:43 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-target.c: + docs: add some more Since: markers for new encoding-profile API + +2011-01-12 15:51:52 +0000 Tim-Philipp Müller + + * configure.ac: + configure: require gobject-introspection >= 0.9.12 + Earlier versions don't honour the -L/--library-path option, + which we need. See commit 4d0ccdad in gobject-introspection git. + Should "fix" build on lucid/maverick build bots. + +2011-01-11 19:19:50 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.31.3 pre-release + +2011-01-11 18:59:39 +0000 Tim-Philipp Müller + + * po/da.po: + * po/gl.po: + * po/pt_BR.po: + po: update translations + +2011-01-11 14:41:53 +0000 Bastien Nocera + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + examples: allow building with newer GTK+ + GtkFunction is gone, and there's no update policies for + GtkRanges any more (but the default was continuous anyway, + so no need to set it to that mode explicitly). + https://bugzilla.gnome.org/show_bug.cgi?id=639215 + +2011-01-11 14:59:38 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/Makefile.am: + gobject-introspection: pass --library-path as well to make it find the right libgstreamer + Makes things work again properly in uninstalled setups (and + presumably in installed setups where GStreamer is installed + into a non-standard prefix). Requires fixes from core git. + https://bugzilla.gnome.org/show_bug.cgi?id=639039 + +2011-01-11 14:52:51 +0000 Byeong-ryeol Kim + + * gst-libs/gst/pbutils/Makefile.am: + gobject-introspection: fix issue when gold linker is used + Need to pass libgstreamer-0.10 explicitly to linker, since we're + calling gst_init(), which in turn is needed because the encoding + target get_type() function calls gst_value_register(). + https://bugzilla.gnome.org/show_bug.cgi?id=639039 + +2011-01-11 15:49:54 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From e572c87 to f94d739 + +2011-01-10 16:35:44 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From ccbaa85 to e572c87 + +2011-01-10 14:53:04 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 46445ad to ccbaa85 + +2011-01-10 15:55:26 +0800 Yang Xichuan + + * ext/ogg/gstoggdemux.c: + oggdemux: remove outdated comment + https://bugzilla.gnome.org/show_bug.cgi?id=639121 + +2011-01-08 02:16:19 +0000 Koop Mast + + * configure.ac: + configure: fix bash-ism + https://bugzilla.gnome.org/show_bug.cgi?id=638961 + +2011-01-08 02:10:03 +0000 Tim-Philipp Müller + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + gobject-introspection: use same PKG_CONFIG_PATH for g-ir-compiler as for g-ir-scanner + Make sure to use the PKG_CONFIG_PATH set at configure time instead of + just relying on an env-var set one. This makes sure both g-ir-compiler + and g-ir-scanner use the same PKG_CONFIG_PATH for determining include + paths etc. + +2011-01-08 01:12:02 +0000 Tim-Philipp Müller + + * pkgconfig/gstreamer-app-uninstalled.pc.in: + * pkgconfig/gstreamer-app.pc.in: + * pkgconfig/gstreamer-audio-uninstalled.pc.in: + * pkgconfig/gstreamer-audio.pc.in: + * pkgconfig/gstreamer-cdda-uninstalled.pc.in: + * pkgconfig/gstreamer-cdda.pc.in: + * pkgconfig/gstreamer-fft-uninstalled.pc.in: + * pkgconfig/gstreamer-fft.pc.in: + * pkgconfig/gstreamer-floatcast.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-interfaces.pc.in: + * pkgconfig/gstreamer-netbuffer-uninstalled.pc.in: + * pkgconfig/gstreamer-netbuffer.pc.in: + * pkgconfig/gstreamer-pbutils-uninstalled.pc.in: + * pkgconfig/gstreamer-pbutils.pc.in: + * pkgconfig/gstreamer-riff-uninstalled.pc.in: + * pkgconfig/gstreamer-riff.pc.in: + * pkgconfig/gstreamer-rtp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtp.pc.in: + * pkgconfig/gstreamer-rtsp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp.pc.in: + * pkgconfig/gstreamer-sdp-uninstalled.pc.in: + * pkgconfig/gstreamer-sdp.pc.in: + * pkgconfig/gstreamer-tag-uninstalled.pc.in: + * pkgconfig/gstreamer-tag.pc.in: + * pkgconfig/gstreamer-video-uninstalled.pc.in: + * pkgconfig/gstreamer-video.pc.in: + pkg-config: add girdir and typelibdir variables to .pc files + We need them when building gir and typelib files for + libraries that depend on these, such as gst-rtsp-server + for example, in an uninstalled setup. + +2011-01-07 12:50:07 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/pbutils-enumtypes.c: + * win32/common/video-enumtypes.c: + 0.10.31.2 pre-release + +2011-01-07 13:04:11 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + * gst/encoding/gstencodebin.h: + encodebin: Add missing-plugin support + https://bugzilla.gnome.org/show_bug.cgi?id=638903 + +2011-01-07 12:51:11 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + encodebin: Extend documentation + https://bugzilla.gnome.org/show_bug.cgi?id=638901 + +2011-01-07 00:43:07 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: never disable g_assert() and cast checks for the unit tests + The unit tests are riddled with g_assert() and friends, sometimes + containing functional code like set_state() calls in them even + (looking at you, pipeline/capsfilter-renegotiation). Make sure we + don't disable assert and cast checks for the unit tests even if + this has been specified for the rest of the code base, e.g. via + --disable-glib-asserts. + +2011-01-06 23:17:12 +0000 Tim-Philipp Müller + + * win32/common/libgstpbutils.def: + win32: udpate pbutils .def file for API change + +2011-01-06 23:13:53 +0000 Tim-Philipp Müller + + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + docs: update docs + +2011-01-06 23:13:35 +0000 Tim-Philipp Müller + + * po/fi.po: + * po/ru.po: + po: update translations + +2011-01-06 23:08:34 +0000 Tim-Philipp Müller + + * ext/pango/gsttextoverlay.c: + textoverlay: make text property controllable too + Because we can, and because it's the most interesting one + to control really, after xpos/ypos. + +2011-01-06 23:01:20 +0000 Lane Brooks + + * ext/pango/Makefile.am: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: make some properties controllable + https://bugzilla.gnome.org/show_bug.cgi?id=638859 + +2011-01-06 20:37:50 +0000 Tim-Philipp Müller + + * tests/check/libs/.gitignore: + tests: ignore new rtsp test binary + +2011-01-05 15:54:15 -0800 David Schleef + + * ext/ogg/gstoggdemux.c: + oggdemux: ignore header pages when looking for keyframe + This was causing keyframe_granule to be set to 0 for all streams + when seeking to the beginning of the stream, i.e., at the + beginning of playback. Fixes #619778. + +2010-12-29 15:27:44 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggstream.c: + oggstream: when the last keyframe position is not known, do not use -1 + Instead, use either 0 or 1, depending on bitstream version, which give + the correct result for streams which aren't cut off at start. + This allows that function to not return negative granpos. + https://bugzilla.gnome.org/show_bug.cgi?id=638276 + +2011-01-06 17:57:41 +0000 christian schaller + + * gst-plugins-base.spec.in: + Update spec file with discoverer and encodebinchanges + +2011-01-05 15:53:09 +0530 Arun Raghavan + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + discoverer: Documentation updates + Some cosmetic changes and expands on some bits of the documentation to + make it more newbie-friendly. + +2011-01-06 13:08:53 +0100 Robert Swain + + * gst/videorate/gstvideorate.c: + * gst/videorate/gstvideorate.h: + videorate: Fix behaviour for frame rate cap changes + The outgoing buffer timestamp is calculated by scaling an output buffer + count by the src pad frame rate caps. If these caps change, we need to + reset the count and work from a new base timestamp. The new output + buffer timestamp is then the count scaled by the new caps values added + onto the base timestamp. + +2011-01-06 08:47:04 +0100 Edward Hervey + + * tools/gst-discoverer.c: + tools: Improve pretty-printing of tags + Avoids escaping strings for nothing and printing out useless buffer contents. + +2011-01-06 08:46:42 +0100 Edward Hervey + + * tools/gst-discoverer.c: + tools: don't leak the GMainLoop + +2011-01-06 00:28:39 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/encoding-target.c: + pbutils: config.h include should come before all other includes + +2011-01-05 22:02:35 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-profile.h: + * gst/encoding/gstencodebin.c: + * tests/check/libs/profile.c: + * tests/examples/encoding/encoding.c: + encoding: encoding_profile_get_output_caps => _get_input_caps + Makes more sense name-wise + +2011-01-05 20:40:39 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: Add various new symbols + +2011-01-05 01:50:34 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-target.c: + encoding-profile: Minor documentation updates + +2011-01-03 19:07:45 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-profile.c: + encoding-profile: Give a better usage example + +2011-01-03 18:52:00 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + * tests/check/libs/profile.c: + * win32/common/libgstpbutils.def: + encoding-target: Fixup loading/saving methods + +2011-01-03 18:51:22 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + encoding-target: more docs cleanups + +2011-01-03 16:07:49 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-target.c: + * tests/check/libs/profile.c: + encoding-target: Change target suffix to .gep + Along with a bunch of other internal cleanups + +2011-01-03 13:21:26 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + encoding-target: Add more docs regarding categories + +2011-01-03 13:20:19 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + * tests/check/libs/profile.c: + * win32/common/libgstpbutils.def: + encoding-target: Add API for list all categories and targets + API: gst_encoding_list_available_categories + API: gst_encoding_list_all_targets + +2010-12-22 18:18:00 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-profile.h: + * tests/check/libs/profile.c: + * win32/common/libgstpbutils.def: + encoding-profile: Add convenience method to find a profile + API: gst_encoding_profile_find + +2010-12-22 18:16:33 +0100 Edward Hervey + + * configure.ac: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + * tests/check/libs/profile.c: + encoding-target: Implement save/load feature + Fixes #637735 + +2010-12-22 11:41:41 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + * tests/check/libs/profile.c: + * win32/common/libgstpbutils.def: + encoding-target: Add method to get a profile by name + API: gst_encoding_target_get_profile + +2011-01-05 19:30:50 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + encodebin: Convert to new GstElementClass::request_new_pad_full vmethod + +2011-01-05 15:31:09 +0100 Edward Hervey + + * gst-libs/gst/pbutils/pbutils.h: + pbutils: Don't forget to include the encoding headers + +2011-01-05 12:02:02 +0100 Edward Hervey + + * gst-libs/gst/video/video.c: + video: Fix uninitialized variables + reported by macosx gcc + +2010-12-07 14:59:46 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/codec-utils.c: + codec-utils: Minor documentation changes + +2011-01-02 15:48:47 -0800 David Schleef + + * gst/typefind/gsttypefindfunctions.c: + typefind: Add stream-format to h264 caps + +2011-01-02 17:21:54 +0000 Tim-Philipp Müller + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: default to enable-last-buffer=FALSE for audio sinks + There isn't really any good reason to get the last buffer from an + audio sink, so don't make the sink keep it around unnecessarily. + +2010-12-31 12:14:22 +0000 Tim-Philipp Müller + + * configure.ac: + * gst/playback/Makefile.am: + * gst/playback/gstinputselector.c: + * gst/playback/gstinputselector.h: + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybin2.c: + playbin2: use input-selector from core instead of internal copy + +2010-12-31 01:24:50 +0000 Tim-Philipp Müller + + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + tests: add input-selector-test and output-selector-test + Moved from gst-plugins-bad into -base, becasue it uses videotestsrc + and other elements from -base, so it can't be in core. + +2010-11-24 12:22:01 +0200 Stefan Kost + + * tests/icles/output-selector-test.c: + output-selector-test: don't hardcode videosinks and use more colorspace conv. + Use autovideosink instead of hardcoded sinks. Use an additional colorspace + converter between videotestsrc and timeoverlay. + +2009-10-27 11:51:05 -0700 Michael Smith + + * tests/icles/output-selector-test.c: + tests: Remove executable bits from non-executable files. + +2009-02-24 16:33:51 +0100 Sebastian Dröge + + * tests/icles/input-selector-test.c: + tests: move examples directory to tests/examples as in every other GStreamer module + +2008-06-19 13:18:24 +0000 Stefan Kost + + tests: Use BOILERPLATE macro and update output-selector test to the latest api changes. + Original commit message from CVS: + * gst/selector/gstoutputselector.c: + * tests/icles/output-selector-test.c: + Use BOILERPLATE macro and update test to the latest api changes. + +2008-02-07 13:48:20 +0000 Stefan Kost + + tests/icles/output-selector-test.c: Add a fixme comment. + Original commit message from CVS: + * gst/multifile/gstmultifilesink.c: + Add a fixme comment. + * gst/selector/gstoutputselector.c: + Fix same leak as in input-selector. + * tests/icles/output-selector-test.c: + Improve the test. + +2008-01-29 07:38:31 +0000 Stefan Kost + + Replace the switch plugin with the selector plugin. Add output-selector as the opposite of input-selector (was switc... + Original commit message from CVS: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.interfaces: + * docs/plugins/gst-plugins-bad-plugins.signals: + * docs/plugins/inspect/plugin-metadata.xml: + * docs/plugins/inspect/plugin-selector.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-switch.xml: + * gst/selector/.cvsignore: + * gst/selector/Makefile.am: + * gst/selector/gstinputselector.c: + * gst/selector/gstinputselector.h: + * gst/selector/gstoutputselector.c: + * gst/selector/gstoutputselector.h: + * gst/selector/gstselector-marshal.list: + * gst/selector/gstselector.c: + * gst/selector/selector.vcproj: + * gst/switch/.cvsignore: + * gst/switch/Makefile.am: + * gst/switch/gstswitch-marshal.list: + * gst/switch/gstswitch.c: + * gst/switch/gstswitch.h: + * gst/switch/switch.vcproj: + * tests/icles/.cvsignore: + * tests/icles/Makefile.am: + * tests/icles/output-selector-test.c: + Replace the switch plugin with the selector plugin. Add output- + selector as the opposite of input-selectoo (was switch). Add a test + for output-selector. Add docs for the elements. The vcproj needs + update. Fixes #500142. + +2010-12-30 18:08:05 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + baseaudiopay: fix timestamps on buffer lists + Fix the outgoing timestamps and RTP timestamps on outgoing buffers when using + buffer lists. + +2010-12-29 22:36:41 +0000 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefinding: assume EBML files without doctype are matroska + https://bugzilla.gnome.org/show_bug.cgi?id=638019 + +2010-12-29 12:53:36 +0100 Wim Taymans + + * gst/tcp/gstmultifdsink.c: + multifdsink: only keep last valid timestamp + Fixes #634397 + +2010-10-13 17:09:13 +0200 Andoni Morales Alastruey + + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + multifdsink: add first and last buffer's timestamp to the stats + +2010-12-29 11:51:42 +0000 Tim-Philipp Müller + + * ext/ogg/gstoggstream.c: + ogg: fix typo in comment + +2010-12-28 17:39:58 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggstream.c: + oggstream: fix interpretation of Theora granule position + The offset part of the granpos is not a sign of the newer encoding. + Use the version number instead. + This fixes the criticals thrown by theoraparse, and (at last) the + remaining part of #553244. + +2010-11-25 17:01:04 +0100 Havard Graff + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: protect against ringbuffer disappearing while in a query + Observed a case where the sink went to null-state during the query, + hence the ringbuffer-pointer was NULL, causing a crash. + Moving the ringbuffer-check code until after the query, and hold the + lock during the check and while using the spec-values. It should not matter + to the query wether the ringbuffer is present or not, and it actually + gets a time bit more time to get the ringbuffer set up in this case! + Fixes #635231 + +2010-12-28 19:39:18 +0100 Wim Taymans + + * ext/ogg/gstoggdemux.c: + oggdemux: handle pads that are not added yet + Don't try to stream data on pads that are not added yet. This happens while we + discover the different streams. + +2010-12-28 11:41:49 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basedepay: fix refcounting issue + Make sure that when _make_writable() returns a new buffer, we actually push that + one instead of the old one. + +2010-12-25 15:22:42 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggstream.c: + oggstream: implement tag extraction for Kate streams + This will mainly allow Totem to know the language of those streams, + so the subtitle selection menu gets properly filled out. + https://bugzilla.gnome.org/show_bug.cgi?id=638005 + +2010-12-26 17:29:38 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for DVB subtitle caps + +2010-12-23 17:18:17 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggdemux.c: + oggdemux: set headers on caps + This will allow switching from one stream to another without having to send + the headers for the new stream again. + https://bugzilla.gnome.org/show_bug.cgi?id=637927 + +2010-12-22 15:29:56 -0800 David Schleef + + * ext/ogg/gstoggstream.c: + oggstream: Fix parsing of theora size + +2010-12-22 19:06:56 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggdemux.c: + oggdemux: Don't use gst_pad_alloc_buffer() + allocate buffers using gst_buffer_new_and_alloc() instead of + gst_pad_alloc_buffer_and_set_caps(), as the first one will + cause the pad to block, and we don't want that since that will + prevent subsequent pads from being fed if a block occurs at + start, when all pads must be fed for playback to start. + This fixes autoplugging of the tiger element and other things. + https://bugzilla.gnome.org/show_bug.cgi?id=637822 + +2010-12-22 18:12:14 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + encodebin: Also use "Formatter"s for container formats + +2010-12-22 18:19:48 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-target.c: + encoding-target: Fix typo + +2010-12-22 10:32:03 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Fix unitialized data warning + Fixes a valgrind warning on jifmux tests on -bad caused by + unitialized bytes. + Fixes #637758 + +2010-12-22 13:56:12 +0100 Alessandro Decina + + * gst/encoding/gstencodebin.c: + encodebin: minor fix in error handling. + Don't call gst_bin_remove (bin, ). + +2010-12-21 18:51:29 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/install-plugins.c: + * gst-libs/gst/pbutils/missing-plugins.c: + pbutils: More gtk-doc annotations + +2010-12-21 10:26:40 +0000 Vincent Penquerc'h + + * gst/playback/gstplaybin2.c: + playbin2: delay stream-changed messages + https://bugzilla.gnome.org/show_bug.cgi?id=637586 + +2010-12-21 16:33:50 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-target.c: + * tests/check/libs/profile.c: + encoding-target: Ensure target names and categories are valid + +2010-12-21 15:11:10 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpdepayload.h: + depay: update some docs + +2010-12-21 15:02:18 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + rtpdepayloade: add support for getting events + Add support for intercepting sink events in the depayloader by adding a new + vmethod. + +2010-12-21 13:37:41 +0100 Wim Taymans + + * ext/vorbis/gstvorbisdec.c: + vorbisdec: keep timestamps when no decoded output + Keep track of the timestamps even when we didn't generate decodable output. + +2010-12-21 13:19:38 +0100 Wim Taymans + + * ext/vorbis/gstvorbisdec.c: + vorbisdec: avoid using invalid timestamps + +2010-12-21 10:41:27 +0100 Wim Taymans + + * tests/examples/seek/seek.c: + seek: don't pause for live buffering messages + +2010-12-20 18:29:15 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppay: use RTP base time when invalid timestamps + When we have an invalid running-time (because we clipped, for example) use the + RTP base time for timestamping instead of generating wrong RTP timestamps. + +2010-12-20 18:28:14 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertppayload.c: + rtppayload: copy applied rate to segment + Use set_segment_full to copy all segment values to the segment structure. + +2010-12-21 13:09:34 +0100 Edward Hervey + + * tests/check/elements/encodebin.c: + * tests/check/libs/profile.c: + tests: Update container-less profile checks + +2010-12-21 13:08:15 +0100 Edward Hervey + + * gst-libs/gst/pbutils/encoding-profile.c: + encoding-profile: Add guard against profiles without format + +2010-12-21 13:07:27 +0100 Edward Hervey + + * gst/encoding/gstencodebin.c: + encodebin: Fix usage of non-container profiles + +2010-12-17 16:10:53 +0100 Edward Hervey + + * docs/plugins/inspect/plugin-videoscale.xml: + docs: Update for videoscale class changes + +2010-12-20 17:46:48 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 169462a to 46445ad + +2010-12-19 13:41:22 +0100 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer.c: + gstdiscoverer: Don't leak tags + +2010-12-19 13:22:23 +0100 Edward Hervey + + * tools/gst-discoverer.c: + gst-discoverer: show global tags by default + +2010-12-19 09:53:08 +0100 Sebastian Dröge + + * tests/check/libs/rtsp.c: + rtsp: Fix memory leaks in the gst_rtsp_url_decode_path_components() unit tests + +2010-12-18 20:47:00 +0100 Sebastian Dröge + + * tests/examples/encoding/Makefile.am: + examples: Fix encodebin example CFLAGS and LDFLAGS + Previously it would only succeed to link if a new enough + libgstpbutils-0.10 was installed in the default library + search path. + +2010-12-17 14:16:18 +0000 Vincent Penquerc'h + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + ogg: implement packet duration query for kate streams + https://bugzilla.gnome.org/show_bug.cgi?id=637519 + +2010-12-17 19:06:27 -0600 Rob Clark + + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-profile.h: + * gst/encoding/gstencodebin.c: + fix compile errors on macosx + with i686-apple-darwin10-gcc-4.2.1: + encoding-profile.h:134: warning: type qualifiers ignored on function return type + encoding-profile.c:240: warning: type qualifiers ignored on function return type + gstencodebin.c: In function 'next_unused_stream_profile': + gstencodebin.c:454: warning: format '%d' expects type 'int', but argument 8 has type 'GType' + gstencodebin.c:464: warning: format '%d' expects type 'int', but argument 8 has type 'GType' + +2010-12-17 00:49:26 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + audioresample: corrected buffer duration calculation to account for nonzero initial timestamp + Since we calculate timestamps by: + timestamp = t0 + (out samples) / (out rate) + and durations by: + duration = ((out samples) + (processed samples)) / (out rate) - timestamp + if t0 is nonzero, this would simplify to + duration = t0 + (processed samples) / (out rate). + This duration is too large by the amount t0. We should have done: + duration = t0 + ((out samples) + (processed samples)) / (out rate) - timestamp + so that + duration = (processed samples) / (out rate). + +2010-12-16 20:40:33 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.h: + audioresample: changed num_gap_samples, num_nongap_samples from guint32 to guint64 so that gaps of greater than or equal to 2^32 samples do not cause integer overflow + +2010-12-16 20:38:31 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + audioresample: push half a history length, instead of a full history length, at end-of-stream so that output segment and input segment have same duration + +2010-12-16 20:34:13 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + audioresample: renamed count_gap, count_nongap to more descriptive num_gap_samples, num_nongap_samples + +2010-12-16 20:32:07 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + audioresample: replaced void* with gpointer + +2010-12-16 20:30:24 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + audioresample: initial filter transient discarded; unit tests passing + +2010-12-16 20:09:58 -0800 Leo Singer + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + * gst/audioresample/resample.c: + * gst/audioresample/speex_resampler.h: + * gst/audioresample/speex_resampler_wrapper.h: + Revert "Revert "audioresample: Add GAP flag support"" + This reverts commit 35c76b3409dde7f2dcc8232388a47a1b99b661a7. + Conflicts: + gst/audioresample/gstaudioresample.c + gst/audioresample/gstaudioresample.h + +2010-12-16 10:26:43 +0000 Vincent Penquerc'h + + * ext/pango/gsttextoverlay.c: + timeoverlay: add missing break + https://bugzilla.gnome.org/show_bug.cgi?id=637377 + +2010-12-16 10:11:43 +0100 Sebastian Dröge + + * gst/videoscale/gstvideoscale.c: + videoscale: Change classification to Filter/Converter/Video/Scaler + +2010-12-15 23:47:29 +0200 Stefan Kost + + * win32/common/libgstrtsp.def: + win32: update the def file with the new rtsp api + +2010-12-15 17:51:36 +0100 Andy Wingo + + add gst_rtsp_url_decode_path_components + * gst-libs/gst/rtsp/gstrtspurl.h: + * gst-libs/gst/rtsp/gstrtspurl.c (gst_rtsp_url_decode_path_components): + New public function, returns a strv of uri-decoded path components. + * tests/check/Makefile.am: + * tests/check/libs/rtsp.c: Add tests. + +2010-12-15 16:35:43 +0100 Wim Taymans + + * win32/common/libgstrtp.def: + win32: update defs file + +2010-12-15 16:30:55 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtpbuffer: relax arrangement for RTP bufferlists + Don't assume there are exactly 2 buffers but allow cases where the header and + payload are in 1 buffer or where the payload is in more buffers. + +2010-12-15 14:55:34 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 20742ae to 169462a + +2010-12-15 12:58:47 +0100 Wim Taymans + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + basedepay: add support for buffer lists in the depayloader + Add support for buffer lists in the depayloader. + +2010-09-13 10:08:47 +0200 Edward Hervey + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/encoding/.gitignore: + * tests/examples/encoding/Makefile.am: + * tests/examples/encoding/encoding.c: + * tests/examples/encoding/gstcapslist.c: + * tests/examples/encoding/gstcapslist.h: + examples: encoding example + Along with gstcapslist + +2010-08-13 17:36:38 +0200 Edward Hervey + + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-encoding.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * gst/encoding/.gitignore: + * gst/encoding/Makefile.am: + * gst/encoding/gstencode-marshal.list: + * gst/encoding/gstencodebin.c: + * gst/encoding/gstencodebin.h: + * gst/encoding/gstsmartencoder.c: + * gst/encoding/gstsmartencoder.h: + * gst/encoding/gststreamcombiner.c: + * gst/encoding/gststreamcombiner.h: + * gst/encoding/gststreamsplitter.c: + * gst/encoding/gststreamsplitter.h: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/encodebin.c: + gst: New encoding plugin + https://bugzilla.gnome.org/show_bug.cgi?id=627476 + +2010-08-13 17:27:52 +0200 Edward Hervey + + * docs/design/Makefile.am: + * docs/design/design-encoding.txt: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/encoding-profile.c: + * gst-libs/gst/pbutils/encoding-profile.h: + * gst-libs/gst/pbutils/encoding-target.c: + * gst-libs/gst/pbutils/encoding-target.h: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/profile.c: + * win32/common/libgstpbutils.def: + pbutils: New Profile library + https://bugzilla.gnome.org/show_bug.cgi?id=627476 + +2010-12-15 12:21:05 +0200 Stefan Kost + + * configure.ac: + configure: use the -Bsymbolic-functions linker flag if supported + This feature turns intra library calls into direct function calls and thus makes + them a little faster. The downside is that this causes problems for e.g. + LD_PRELOAD based tools. Thus add a configure option to turn it off. + +2010-12-14 00:16:13 -0800 David Schleef + + * gst/typefind/gsttypefindfunctions.c: + typefind: Add check for yuv4mpeg + +2010-12-13 18:05:41 +0200 Stefan Kost + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: spell out two more container formats + +2010-12-13 16:20:23 +0200 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + * gst-libs/gst/pbutils/pbutils-private.h: + * tools/gst-discoverer.c: + * win32/common/libgstpbutils.def: + discoverer: query seekability + Besides the duration we can also query the seekability of a stream. Use the new + API in the gst-discoverer tool. + API: gst_discoverer_info_get_seekable + +2010-12-13 16:23:04 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 011bcc8 to 20742ae + +2010-12-13 13:04:40 +0100 Mark Nauwelaerts + + * tests/check/elements/audioresample.c: + tests: audioresample: adjust unit test to relaxed discont checking + +2010-12-13 12:34:58 +0200 Stefan Kost + + * docs/Makefile.am: + * docs/design/Makefile.am: + make: move the design doc also on the Makefile.am level (for dist) + +2010-12-13 10:05:00 +0100 Mark Nauwelaerts + + * gst/audioresample/gstaudioresample.c: + audioresample: relax discont checking slightly + +2010-12-13 09:56:04 +0100 Mark Nauwelaerts + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + audioresample: provide as much valid output ts and offset as valid input + ... by independently tracking time and offset, rather than having no offset + leading to no output ts. + +2010-12-13 10:41:24 +0200 Stefan Kost + + * gst/typefind/gsttypefindfunctions.c: + typefinders: name "aac" typefinder "audio/aac" + This is in sync how we call the others. + +2010-12-13 09:58:53 +0200 Stefan Kost + + * docs/design-audiosinks.txt: + * docs/design/design-audiosinks.txt: + docs: move design doc to design folder + +2010-12-11 19:33:33 +0200 Zeeshan Ali (Khattak) + + * gst/videotestsrc/generate_sine_table.c: + videotestsrc: Add a missing return statement + +2010-12-11 17:18:49 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Deprecate new-decoded-pad and removed-decoded-pad signals + They're really the same as pad-added and pad-removed from GstElement + and it doesn't make sense to have two signals for the same thing. + +2010-12-11 17:14:36 +0100 Sebastian Dröge + + * gst/playback/gstdecodebin2.c: + decodebin2: Emit "remove-decoded-pad" signal when pads are removed from decodebin2 + Fixes bug #636198. + +2010-12-10 18:57:56 +0100 Wim Taymans + + * gst-libs/gst/app/gstappsink.c: + appsink: unset flushing flag when starting + When we start again after being stopped, clear the flushing flag or else + it will always be TRUE. + Fixes #636769 + +2010-12-09 16:57:35 +0100 Edward Hervey + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add/Fix some media descriptions + Fixes #623413 + +2010-12-09 08:40:25 +0100 Gavin Stark + + * sys/xvimage/xvimagesink.c: + xvimagesink: Use gst_caps_can_intersect() instead of gst_caps_intersect() + Fixes a memory leak and bug #636827. + +2010-12-08 12:55:24 +0100 Mark Nauwelaerts + + * gst/typefind/gsttypefindfunctions.c: + typefinding: improve iso media typefinding + ... by also considering compatible brands rather than only aiming at major brand + (of which there are a seemingly ever expanding great many). + +2010-12-08 12:28:32 +0200 Stefan Kost + + * tests/check/libs/pbutils.c: + tests: remove superflous ';' and reindent + +2010-12-08 12:09:45 +0200 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/rtp/gstrtpbuffer.c: + docs: fix wrong use of Since: keyword + +2010-12-07 20:28:37 +0200 René Stadler + + * tests/check/gst/typefindfunctions.c: + tests: add AC-3, E-AC-3 typefind tests + +2010-12-03 17:33:40 +0200 René Stadler + + * gst/typefind/gsttypefindfunctions.c: + typefind: ignore AC-3 BSIDs 9, 10 and >16 + These are reserved for future extensions which will not be backwards + compatible to E-AC-3. + +2010-12-03 16:54:21 +0200 René Stadler + + * gst/typefind/gsttypefindfunctions.c: + typefind: accept consecutive AC-3 frames of different sizes + This is perfectly valid and occurs in particular when there are + (in)dependent substreams present. + +2010-12-03 16:22:32 +0200 René Stadler + + * gst/typefind/gsttypefindfunctions.c: + typefind: remove useless masking in (E-)AC-3 typefinders + +2010-12-03 16:14:15 +0200 René Stadler + + * gst/typefind/gsttypefindfunctions.c: + typefind: stop scanning after suggesting E-AC-3 caps + +2010-12-03 18:08:58 +0200 René Stadler + + * gst/typefind/gsttypefindfunctions.c: + typefind: fix E-AC-3 frame size parsing + Frame size is given in words; it is already multiplied by two where + needed, so the left shift is superfluous. This extra multiplication + caused the code to inspect the third packet instead of the second, + which would fail for files where the second packet has a size + different from the first. + +2010-12-07 17:35:14 +0100 Edward Hervey + + * gst-libs/gst/rtsp/gstrtsptransport.h: + rtsp: Move around the typedefs to make GIR happy + Otherwise it will generate they symbols as _GstRTSP* (with the leading + underscore). + +2010-12-04 14:48:46 +0000 Tim-Philipp Müller + + * tests/examples/app/appsrc-ra.c: + * tests/examples/app/appsrc-seekable.c: + * tests/examples/app/appsrc-stream.c: + * tests/examples/app/appsrc-stream2.c: + tests: use GLib 2.22 API unconditionally + +2010-12-04 14:45:58 +0000 Tim-Philipp Müller + + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/tag/lang.c: + * gst-libs/gst/tag/mklangtables.c: + * gst-libs/gst/video/convertframe.c: + libs: use GLib 2.22 API unconditionally + +2010-12-03 17:41:18 +0100 Benjamin Gaignard + + * Android.mk: + * android/NOTICE: + * android/alsa.mk: + * android/app.mk: + * android/app_plugin.mk: + * android/audio.mk: + * android/audioconvert.mk: + * android/decodebin.mk: + * android/decodebin2.mk: + * android/gdp.mk: + * android/gst-libs/gst/app/gstapp-marshal.c: + * android/gst-libs/gst/app/gstapp-marshal.h: + * android/gst-libs/gst/audio/audio-enumtypes.c: + * android/gst-libs/gst/audio/audio-enumtypes.h: + * android/gst-libs/gst/interfaces/interfaces-enumtypes.c: + * android/gst-libs/gst/interfaces/interfaces-enumtypes.h: + * android/gst-libs/gst/interfaces/interfaces-marshal.c: + * android/gst-libs/gst/interfaces/interfaces-marshal.h: + * android/gst-libs/gst/pbutils/pbutils-enumtypes.c: + * android/gst-libs/gst/pbutils/pbutils-enumtypes.h: + * android/gst-libs/gst/rtsp/gstrtsp-enumtypes.c: + * android/gst-libs/gst/rtsp/gstrtsp-enumtypes.h: + * android/gst-libs/gst/rtsp/gstrtsp-marshal.c: + * android/gst-libs/gst/rtsp/gstrtsp-marshal.h: + * android/gst-libs/gst/video/video-enumtypes.c: + * android/gst-libs/gst/video/video-enumtypes.h: + * android/gst/playback/gstplay-marshal.c: + * android/gst/playback/gstplay-marshal.h: + * android/gst/tcp/gsttcp-enumtypes.c: + * android/gst/tcp/gsttcp-enumtypes.h: + * android/gst/tcp/gsttcp-marshal.c: + * android/gst/tcp/gsttcp-marshal.h: + * android/interfaces.mk: + * android/netbuffer.mk: + * android/pbutils.mk: + * android/playbin.mk: + * android/queue2.mk: + * android/riff.mk: + * android/rtp.mk: + * android/rtsp.mk: + * android/sdp.mk: + * android/tag.mk: + * android/tcp.mk: + * android/typefindfunctions.mk: + * android/video.mk: + Add build system for Android + +2010-12-03 15:46:07 +0100 Wim Taymans + + * win32/common/libgstvideo.def: + defs: add new symbol + +2010-10-27 13:49:41 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggstream.c: + oggstream: additional tag extraction + ... supporting theora, flac, speex, celt. + Fixes #629349. + +2010-10-27 12:08:25 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggstream: use separate tag extraction vfunction + +2010-10-27 11:58:53 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggstream.c: + oggstream: refactor vorbis comment tag extraction + +2010-10-27 11:16:15 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggdemux.c: + oggdemux: plug some oggstream leaks + +2010-10-27 10:59:03 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggstream: streamline tag extraction and prevent some leaks + +2010-10-27 10:58:16 +0200 Mark Nauwelaerts + + * ext/ogg/gstoggdemux.c: + oggdemux: send stream tags after newsegment and global tags + +2010-09-14 23:08:51 +0300 Sreerenj Balachandran + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: perform more (vorbis comment header) tag extractions + In particular, move comment header parsing to gstoggstrem.c. + Thanks to Felipe Contreras. + Fixes #629349 (partially). + +2010-10-27 10:20:15 +0200 Mark Nauwelaerts + + * gst-libs/gst/riff/riff-ids.h: + riff: document omitted field in _gst_riff_strf_auds + (aka WAVEFORMATEX) + +2010-10-10 17:15:53 -0700 David Schleef + + * ext/ogg/gstoggstream.c: + oggstream: fix incorrect warning on skeleton headers + +2010-11-20 19:02:50 -0800 David Schleef + + * ext/ogg/gstoggparse.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggparse: Set DELTA_UNIT on buffers + +2010-12-03 00:01:06 +0000 Tim-Philipp Müller + + * tests/check/libs/video.c: + tests: fix video library unit test and skip non-working YUV9/YVU9 parts for now + +2010-12-02 23:49:31 +0000 Tim-Philipp Müller + + * gst-libs/gst/video/video.c: + video: add missing break statement for the GST_VIDEO_FORMAT_RGB8_PALETTED case + +2010-11-15 22:02:07 +0200 Evan Broder + + * tools/gst-visualise-m.m: + gst-visualise: trim unused perl dependency + Remove an unused perl module. Fixes #634522. + +2010-11-01 23:07:12 +0200 Stefan Kost + + * gst/playback/gstplaybin2.c: + playbin2: add some logging for failure case + +2010-11-01 23:06:21 +0200 Stefan Kost + + * gst/playback/gstinputselector.c: + inputselector: log times in human readable form + +2010-11-01 22:44:16 +0200 Stefan Kost + + * gst/playback/gstinputselector.c: + inputselector: more G_PARAM_STATIC_STRINGS use + +2010-11-01 22:42:23 +0200 Stefan Kost + + * gst/playback/gstinputselector.c: + inputselector: move reoccuring logs to LOG and remove a double info + Less debug spew in DEBUG category. No need to log pad again if we use + GST_LOG_OBJECT(pad,...). + +2010-12-02 19:11:37 +0100 Edward Hervey + + * gst-libs/gst/rtsp/Makefile.am: + libgstrtsp: Fix typo in .pc to use for GIR + +2010-12-02 15:16:25 +0100 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + docs: Add a whole bunch of symbols that were unused to the proper sections + +2010-11-10 11:02:27 +0100 Wim Taymans + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: only parse TTL for IP4 addresses + Only IP4 addresses can have a TTL in the address. + +2010-11-10 10:53:41 +0100 Wim Taymans + + * gst-libs/gst/sdp/gstsdpmessage.c: + * gst-libs/gst/sdp/gstsdpmessage.h: + * win32/common/libgstsdp.def: + sdp: add method to check for multicast addresses + Expose a previously internal method to check for multicast addresses. + See #634093 + +2010-11-03 11:13:08 +0100 Sebastian Dröge + + * gst-libs/gst/pbutils/gstpluginsbaseversion.h.in: + pbutils: Take nano version into account in GST_CHECK_PLUGINS_BASE_VERSION() + If the nano is > 0 the current version should be handled the same as + micro + 1. + +2010-11-03 09:51:40 +0100 Sebastian Dröge + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add YUV9, YVU9 and IYU1 video formats + API: GST_VIDEO_FORMAT_YUV9: planar 4:1:0 YUV + API: GST_VIDEO_FORMAT_YVU9: planar 4:1:0 YUV (chroma planes swapped) + API: GST_VIDEO_FORMAT_IYU1: packed 4:1:1 YUV (Cr-Y0-Y1-Cb-Y2-Y3) + +2010-11-02 11:57:09 +0100 Sebastian Dröge + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add 8-bit paletted RGB + API: Add GST_VIDEO_FORMAT_RGB8_PALETTED + API: Add GST_VIDEO_CAPS_RGB8_PALETTED + API: Add gst_video_parse_caps_palette() + +2010-10-31 19:17:28 +0100 Sebastian Dröge + + * ext/gnomevfs/gstgnomevfssrc.c: + gnomevfssrc: Remove dead assignment + +2010-10-31 19:14:27 +0100 Sebastian Dröge + + * gst/tcp/gsttcp.c: + tcp: Remove dead assignment + +2010-10-31 19:11:53 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + playsink: gen_video_chain() always returns a bin, no need to check for that + +2010-10-31 19:08:32 +0100 Sebastian Dröge + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: If we get EOS for an unknown stream just do nothing + instead of dereferencing NULL pointers. This can happen if the stream + was just removed from the streamsynchronizer in a bad time. + +2010-10-31 19:06:00 +0100 Sebastian Dröge + + * gst/playback/gstplaysink.c: + playsink: gen_video_deinterlace_chain() always returns a bin, no need to check that + +2010-10-31 19:01:49 +0100 Sebastian Dröge + + * sys/v4l/v4l_calls.c: + v4l: If no video tuner is the requested one don't read unitialized data + +2010-10-25 14:13:16 +0100 Sebastian Dröge + + * sys/ximage/ximagesink.c: + ximagesink: Add docs for the new property + Including Since markers + +2010-10-25 14:11:01 +0100 Sebastian Dröge + + * sys/xvimage/xvimagesink.c: + xvimagesink: Add docs for the new property + Including Since markers + +2010-10-25 14:09:39 +0100 Sebastian Dröge + + * sys/xvimage/xvimagesink.c: + xvimagesink: Use PROP_ instead of ARG_ for the property enums + +2010-10-25 14:09:20 +0100 Andrea Sebastianutti + + * sys/xvimage/xvimagesink.c: + xvimagesink: Add read-only properties window-width and window-height + +2010-10-25 14:08:43 +0100 Andrea Sebastianutti + + * sys/ximage/ximagesink.c: + ximagsink: Add read-only properties window-width and window-height + +2010-10-17 14:26:23 +0200 Sebastian Dröge + + * gst-libs/gst/video/video.c: + video: Return correct component width/height for A420 + +2010-12-02 00:15:25 +0000 Tim-Philipp Müller + + * configure.ac: + Bump GLib requirement to >= 2.22 + See http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement + +2010-12-02 00:12:51 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + Back to development + +=== release 0.10.31 === + +2010-11-30 19:25:44 +0000 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.31 + +2010-11-24 17:34:21 +0200 Stefan Kost + + * gst/playback/gsturidecodebin.c: + uridecodebin: disconnect signal handlers before disposing + +2010-11-22 00:54:35 +0000 Tim-Philipp Müller + + * gst/playback/gstdecodebin2.c: + docs: improve decodebin2 docs a little + Mention that new pads may be created even after no-more-pads. + https://bugzilla.gnome.org/show_bug.cgi?id=634584 + +2010-11-20 15:45:49 -0800 Evan Nemerson + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introspection: Add information on exported packages to GIRs + https://bugzilla.gnome.org/show_bug.cgi?id=635392 + +2010-11-18 04:51:56 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + discoverer: Minor documentation fix + docs: Minor discoverer documentation fix + +2010-11-18 00:36:14 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.30.5 pre-release + +2010-11-18 00:35:53 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/ca.po: + * po/es.po: + * po/hu.po: + * po/sk.po: + * po/tr.po: + po: update translations + +2010-11-18 00:33:22 +0000 Tim-Philipp Müller + + * gst/playback/gstdecodebin.c: + decodebin: fix one more pad template ref leak + +2010-11-17 10:14:59 +0200 Harri Mähönen + + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gsturidecodebin.c: + *decodebin*: don't leak pad templates set on ghostpads + https://bugzilla.gnome.org/show_bug.cgi?id=635067 + +2010-11-17 01:01:03 +0000 Tim-Philipp Müller + + * gst/playback/gststreamsynchronizer.c: + playbin2: disable streamsynchronizer magic for this release + Some things aren't quite right yet and cause problems (0-sized buffers + with PREROLL flag set cause crashes in elements that don't expect those; + getting pipeline back to preroll/playing again when audio/video streams + have different lengths and a seek past the end of one of the stream + happens doesn't always work, etc.). Needs further investigation in the + next cycle. + https://bugzilla.gnome.org/show_bug.cgi?id=633700 + https://bugzilla.gnome.org/show_bug.cgi?id=634699 + +2010-11-08 09:27:52 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Fix a gtk-doc gobject-introspection annotation + gst_discoverer_discover_uri() expects the caller to unref the returned + GstDiscovererInfo object. The corresponding gtk-doc annotation was not + updated to reflect this. + +2010-11-08 09:26:27 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + * tools/gst-discoverer.c: + discoverer: Fix argument type to _container_info_get_streams() + No reason for gst_discoverer_container_info_get_streams() to not take a + GstDiscovererContainerInfo as its argument. + +2010-11-05 20:47:41 +0000 Tim-Philipp Müller + + * configure.ac: + configure: add --with-gtk option and default to Gtk+ 2.0 while the 3.0 API is still in flux + https://bugzilla.gnome.org/show_bug.cgi?id=634014 + +2010-11-03 10:35:35 +0100 Sebastian Dröge + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix IYU1 support + Fix conversions to IYU1, they allocated infinite amounts of memory before + because no conversion to IYU1 was actually implemented and it was running + into an infinite loop trying to find suitable intermediate formats. + Also fix the stride and sizes used for IYU1. + +2010-11-02 12:29:05 +0000 Tim-Philipp Müller + + * tests/check/libs/rtp.c: + tests: fix invalid free and buffer list leak in rtp library unit test + +2010-11-02 12:03:21 +0000 Tim-Philipp Müller + + * tests/check/libs/tag.c: + tests: fix leak in tag library unit test + +2010-11-02 12:01:03 +0000 Tim-Philipp Müller + + * gst-libs/gst/tag/gstexiftag.c: + tag: fix leak when parsing undefined EXIF tag into tag list + gst_buffer_set_data() does not set GST_BUFFER_MALLOCDATA, but + the code assumes the buffer takes ownership of the memory + allocated earlier. + +2010-11-02 11:57:02 +0000 Tim-Philipp Müller + + * gst-libs/gst/tag/gstexiftag.c: + tag: fix GstDateTime leak when converting exif tag to tag list + +2010-11-01 17:00:38 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.30.4 pre-release + +2010-11-01 16:59:59 +0000 Tim-Philipp Müller + + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/fr.po: + * po/ja.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/sl.po: + po: update translations + +2010-10-30 16:07:59 +0100 Tim-Philipp Müller + + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: update docs for discoverer API changes as well + +2010-10-30 16:03:18 +0100 Matthias Clasen + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + examples: update some more code for new Gtk+ API, with fallback for older Gtk+ versions + Move code to new Gtk+ 3.x / 2.9x API. We have defines in place + already that make this code work fine on older Gtk+ 2.x. + https://bugzilla.gnome.org/show_bug.cgi?id=632653 + +2010-10-28 15:13:45 +0200 Sebastian Dröge + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + seek: Define the new combobox API to the old functions if using older GTK + https://bugzilla.gnome.org/show_bug.cgi?id=632653 + +2010-10-30 15:31:52 +0100 Tim-Philipp Müller + + * win32/common/libgstutils.def: + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstutils.dsp: + win32: remove unused libgstutils stuff + Cruft from before the lib was renamed to pbutils + +2010-10-28 18:51:08 +0300 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + * tools/gst-discoverer.c: + * win32/common/libgstpbutils.def: + discoverer: rename boolean getters for consistency + Rename _get_is_image() to _is_image() and _get_interlaced() to _is_interlaced(). + https://bugzilla.gnome.org/show_bug.cgi?id=633311 + +2010-10-30 12:24:05 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/pbutils-private.h: + pbutils: remove padding from now-private GstDiscovererInfo structure + +2010-10-30 12:03:39 +0100 Tim-Philipp Müller + + * Makefile.am: + * tools/.gitignore: + * tools/Makefile.am: + tools: rename gst-discoverer binary to gst-discoverer-0.10 + We're not providing a wrapper like we do for the tools in core, + since wrappers are confusing (e.g. for debugging purposes), + mostly pointless (since the API is likely to change between + major versions), and cause packaging issues when packages for + two different major versions are to be installed in parallel. + https://bugzilla.gnome.org/show_bug.cgi?id=633023 + +2010-10-30 11:41:23 +0100 Tim-Philipp Müller + + * tools/gst-discoverer.c: + tools: update gst-discoverer tool for last-minute API change + https://bugzilla.gnome.org/show_bug.cgi?id=633311 + +2010-10-29 14:17:44 +0100 Wim Taymans + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: calculate better timeout value + We want to send the keealive message a little earlier than the timeout value + specifies. Scale this based on the value of the timeout instead of just assuming + 5 seconds. + +2010-10-29 14:24:54 +0200 Thijs Vermeir + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: don't let the rtsp connection timeout + Because we should act before the rtsp server does a timeout, we + reduce the timeout-time with 5 seconds, this should be safe to always + keep te rtsp connection alive. + https://bugzilla.gnome.org/show_bug.cgi?id=633455 + +2010-10-28 15:55:12 +0200 Sebastian Dröge + + * tests/check/Makefile.am: + * tests/check/elements/videoscale.c: + videoscale: Add unit test for working reverse negotiation + See bug #633147. + +2010-10-29 11:48:18 +0100 Wim Taymans + + * ext/ogg/gstoggdemux.c: + oggdemux: fix wrong flowreturn handling + Oggdemux will currently try to pad alloc a buffer from the peer when it is + reading the header files. This is a relic from the time where we had an internal + parser and needs to be removed at some point in time. + The problem is that when there is no peer pad yet (which is normal when + collecting headers) we should still continue to parse all the packets of a + page instead of erroring out on NOT_LINKED. + Fixes #632167 + +2010-10-29 11:47:53 +0100 Wim Taymans + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + ogg: add some more debug statements + +2010-10-26 16:41:28 +0100 Jan Schmidt + + * gst/playback/gstplaysink.c: + playsink: Fix subpicture overlay when deinterlacing disabled. + Fix a bug when reconfiguring the playsink where the subpicture + stream is broken by attempting to connect it through + streamsynchroniser and second time. + +2010-10-28 17:38:29 +0300 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + discoverer: use const in most of the getters + +2010-10-28 03:09:10 +0300 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + discoverer: use specific types in getters + Use GstDiscoverer{Audio,Video}Info in getters like + gst_discoverer_{audio,video}_info_get_*(). This avoids the casts in the macros, + help language bindings and is more correct. + +2010-10-28 11:56:06 +0200 Sebastian Dröge + + * docs/libs/gst-plugins-base-libs-docs.sgml: + discoverer: Move documentation to the correct section + And don't mention the (not existing) libgstdiscovery. + https://bugzilla.gnome.org/show_bug.cgi?id=633336 + +2010-10-27 13:16:37 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From 7bbd708 to 011bcc8 + +2010-10-24 16:09:26 +0200 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Get pad caps if we can't get negotiated caps + Better provide something than nothing + https://bugzilla.gnome.org/show_bug.cgi?id=632988 + +2010-10-24 15:38:30 +0200 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + discoverer: Don't ref a NULL caps + https://bugzilla.gnome.org/show_bug.cgi?id=632988 + +2010-09-24 16:02:42 +0200 Edward Hervey + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't add non prerolled stream to topology + If a final stream didn't preroll, don't add it to the topology since + it doesn't give any information at all. + https://bugzilla.gnome.org/show_bug.cgi?id=632988 + +2010-10-24 16:17:09 +0200 Edward Hervey + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Description for RealAudio container format + +2010-10-24 15:38:42 +0200 Edward Hervey + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for VP6 alpha and ASS subtitle + +2010-10-22 17:44:08 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.30.3 pre-release + +2010-10-20 11:01:59 +0200 Sebastian Dröge + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + seek: The new combo box text API is available since 2.23.0 and 2.91.1 + Only use it conditionally. + +2010-10-20 11:01:14 +0200 Matthias Clasen + + * tests/examples/seek/jsseek.c: + seek: Don't use deprecated combo box text API + Fixes bug #632653. + +2010-10-21 12:24:19 +0200 Mark Nauwelaerts + + * gst/playback/gsturidecodebin.c: + uridecodebin: workaround internal decodebin2 failing state change + Fixes #632656. + +2010-10-21 13:38:01 +0100 Tim-Philipp Müller + + * tests/examples/overlay/gtk-xoverlay.c: + * tests/icles/test-colorkey.c: + * tests/icles/test-xoverlay.c: + tests: don't use deprecated gtk_widget_hide_all() + gtk_widget_hide_all() has been deprecated in gtk+ 2.x and + removed in 2.9x master. Just use gtk_widget_hide() instead. + +2010-10-21 13:07:34 +0100 Tim-Philipp Müller + + * tools/Makefile.am: + tools: fix linking problems caused by accidentally linking against installed pbutils/gstvideo libs + Fixes build errors in jhbuild: + /foo/build/gst-plugins-base/gst-libs/gst/video/.libs/libgstvideo-0.10.so: undefined reference to `gst_element_factory_list_get_elements' + ../gst-libs/gst/pbutils/.libs/libgstpbutils-0.10.so: undefined reference to `gst_element_link_pads_full' + /foo/build/gst-plugins-base/gst-libs/gst/video/.libs/libgstvideo-0.10.so: undefined reference to `gst_element_factory_list_filter' + ../gst-libs/gst/pbutils/.libs/libgstpbutils-0.10.so: undefined reference to `gst_pad_link_full' + /foo/build/gst-plugins-base/gst-libs/gst/video/.libs/libgstvideo-0.10.so: undefined reference to `gst_plugin_feature_list_debug' + +2010-10-19 00:07:47 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/pbutils-marshal.list: + * gst-libs/gst/rtsp/gstrtsp-marshal.list: + libs: touch marshal.list files to force rebuild after Makefile.am changes + Force regeneration of marshal.[ch] files after prefix changes in + Makefile.am, to avoid build errors for those of us who don't + habitually make clean first. + +2010-10-16 01:08:38 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/pbutils-enumtypes.c: + * win32/common/pbutils-enumtypes.h: + * win32/common/video-enumtypes.c: + 0.10.30.2 pre-release + +2010-10-16 01:07:16 +0100 Tim-Philipp Müller + + * po/LINGUAS: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/sk.po: + * po/sl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2010-10-08 17:24:07 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + * tests/check/libs/tag.c: + tag: Adds GST_TAG_CAPTURING_SOURCE + Adds a tag to indicate the source/device used for the capture. + Already maps it in exif and adds tests. + API: GST_TAG_CAPTURING_SOURCE + https://bugzilla.gnome.org/show_bug.cgi?id=631773 + +2010-10-08 15:51:28 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + * tests/check/libs/tag.c: + tag: Adds GST_TAG_CAPTURING_METERING_MODE + Adds a tag to inform what mode was used by a camera to calculate + the picture capturing exposure + Also adds mapping to exif and tests + API: GST_TAG_CAPTURING_METERING_MODE + https://bugzilla.gnome.org/show_bug.cgi?id=631773 + +2010-10-08 15:14:22 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + * tests/check/libs/tag.c: + tag: Adds GST_TAG_CAPTURING_SHARPNESS + Adds new tag for tagging sharpness processing used + when capturing an image. Also maps it in the exif + tags. + Tests included. + API: GST_TAG_CAPTURING_SHARPNESS + https://bugzilla.gnome.org/show_bug.cgi?id=631773 + +2010-10-15 23:54:40 +0100 Tim-Philipp Müller + + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtspextension.c: + * win32/common/libgstrtsp.def: + rtsp: don't export marshaller function + Make sure the marshaller function isn't exported. As it was + never in a public header file, this should be fine. + +2010-10-15 21:22:35 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/Makefile.am: + pbutils: fix distcheck + Apparently noinst implies dist. + +2010-10-15 11:23:02 -0700 David Schleef + + * tests/check/Makefile.am: + tests: Don't dist generated orc code + +2010-10-15 11:22:45 -0700 David Schleef + + * gst/videoscale/gstvideoscaleorc-dist.c: + Update generated orc code + +2010-10-15 19:18:12 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/pbutils.h: + * win32/common/libgstpbutils.def: + pbutils: make marshaller private + There's no reason to make the marshaller public API. Don't install + pbutils-marshal.h header file and use prefix that makes sure the + symbol doesn't get exported. + +2010-10-15 19:14:49 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/Makefile.am: + pbutils: use fewer variables in Makefile.am to make things clearer + Also fix typo in DISTCLEANFILES. + +2010-10-15 17:59:26 +0100 Tim-Philipp Müller + + * configure.ac: + configure: bump Orc requirement to 0.4.11 + Has fixes for volume, among other things. + +2010-10-15 17:23:44 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/gstdiscoverer.c: + docs: improve gst_discoverer_new() docs a bit + +2010-10-15 16:43:41 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: private structs need to padding + +2010-10-15 11:26:50 +0200 Sebastian Dröge + + * gst-libs/gst/video/video.c: + video: Fix stupid copy&paste error in last commit + +2010-10-13 22:51:12 +0200 Sebastian Dröge + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add support for A420 + +2010-10-13 20:45:28 +0200 Sebastian Dröge + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: API: Add A420 video format + This is planar 4:2:0 YUV plus non-subsampled alpha plane. + +2010-10-14 12:31:39 -0700 David Schleef + + * common: + Automatic update of common submodule + From 5a668bf to 7bbd708 + +2010-10-14 16:36:30 +0100 Tim-Philipp Müller + + * gst/typefind/gsttypefindfunctions.c: + typefinding: fix ADTS caps stream-format detail + Field should be "stream-format", not "stream-type". + +2010-07-08 15:22:08 +0200 Andrzej K. Haczewski + + * gst/typefind/gsttypefindfunctions.c: + typefinding: extend AAC typefinder to detect LOAS streams + Extend AAC typefinder to recognize LOAS stream as specified by + ISO/IEC 14496-3:2009. + https://bugzilla.gnome.org/show_bug.cgi?id=623918 + +2010-10-13 23:26:35 +0300 Stefan Kost + + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gsturidecodebin.c: + *decodebin*: set pad-templates on ghostpads + This makes calling gst_pad_get_pad_template() work. + +2010-10-12 21:23:03 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: Update with latest datetime from core + Updates datetime functions to latest APIs in core + +2010-10-13 16:12:38 +0300 Stefan Kost + + * ext/theora/gsttheoraparse.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + * gst-libs/gst/interfaces/mixertrack.c: + * gst/audioresample/gstaudioresample.c: + * gst/playback/gstinputselector.c: + * gst/playback/gstplaybasebin.c: + * gst/playback/gsturidecodebin.c: + * gst/subparse/gstsubparse.c: + various: add a missing G_PARAM_STATIC_STRINGS flag to object properties + +2010-10-13 13:05:12 +0100 Tim-Philipp Müller + + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + decodebin2: declare decodebin2 stable, deprecate the old decodebin + https://bugzilla.gnome.org/show_bug.cgi?id=624949 + +2010-10-13 12:55:31 +0100 Tim-Philipp Müller + + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + playbin2: declare stable, deprecate the old playbin + https://bugzilla.gnome.org/show_bug.cgi?id=624949 + +2010-10-12 16:03:36 +0200 Wim Taymans + + * ext/ogg/gstoggdemux.c: + oggdemux: only keep last valid granulepos + Only keep the last valid granulepos we see when scanning the last + pages. It is possible that the last page that we inspect has a -1 granulepos, in + which case we want to keep the previous valid time instead. + Fixes #631703 + +2010-10-10 15:22:52 -0700 David Schleef + + * ext/ogg/gstoggdemux.c: + oggdemux: Fix check for last page + +2010-10-10 15:22:04 -0700 David Schleef + + * ext/ogg/gstoggdemux.c: + oggdemux: change checks from is_skeleton to is_sparse + +2010-10-10 15:17:31 -0700 David Schleef + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: move is_sparse into stream map + +2010-10-11 18:06:18 -0300 Thiago Santos + + * tests/check/Makefile.am: + tests: vorbis: adds missing lib + Adds missing lib to vorbis check tests makefile + +2010-10-11 14:30:02 +0200 Sebastian Dröge + + * gst/playback/gsturidecodebin.c: + uridecodebin: Set GST_ELEMENT_IS_SOURCE flag + uridecodebin behaves like a source, let's mark it as a source + +2010-10-10 00:52:13 +0100 Tim-Philipp Müller + + * ext/theora/gsttheoradec.c: + theoradec: expose telemetry properties only if libtheora was compiled with --enable-telemetry + Since this is just a debugging feature and libtheora will usually not be + compiled with that option enabled, we should maybe just hide these properties, + since they won't work anyway, and avoid confusing warnings. + Also rename properties to make them less cryptic. + https://bugzilla.gnome.org/show_bug.cgi?id=628488 + +2010-10-09 23:49:35 +0100 Alexey Fisher + + * ext/theora/gsttheoradec.c: + * ext/theora/gsttheoradec.h: + theoradec: add properties to enable debugging telemetry overlay + The theora decoder can overlay debugging information on the output + video. This functionality is only available if libtheora has been + compiled with --enable-telemetry. For more details see: + http://people.xiph.org/~xiphmont/demo/theora/demo2.html + Based on original patch by Michael Smith + https://bugzilla.gnome.org/show_bug.cgi?id=628488 + +2010-10-10 18:35:54 +0200 Sebastian Dröge + + * sys/xvimage/xvimagesink.c: + xvimagesink: Make sure that the caps for upstream negotiation are simple caps + Fixes bug #631774. + +2010-10-09 14:17:57 +0100 Vincent Penquerc'h + + * tests/examples/app/appsrc-ra.c: + * tests/examples/app/appsrc-seekable.c: + * tests/examples/app/appsrc-stream.c: + * tests/examples/app/appsrc-stream2.c: + examples: g_mapped_file_unref exists already since GLib 2.21.3 + +2010-10-07 19:32:56 +0200 Guillaume Emont + + * ext/ogg/gstoggdemux.c: + oggdemux: fix seeking with negative rate with skeleton + Files with a skeleton, or other files with a stream that ends before the end of + the chain would start playing from the end of the chain when trying to seek with + a negative rate at a position between the end of any stream and the end of the + chain. + This is due to the loop in _do_seek() assuming that pages will be encountered + for all streams shortly after the place where we want to seek, as found by + do_binary_search(). + In the first iteration of the loop, stream ends are now checked against the + time of the current page. + +2010-10-07 18:53:35 +0100 Zaheer Abbas Merali + + * gst/tcp/gstmultifdsink.c: + multifdsink: gdp protocol is deprecated. People should use gdppay instead. + +2010-10-08 12:43:28 -0700 David Schleef + + * common: + Automatic update of common submodule + From c4a8adc to 5a668bf + +2010-09-28 12:17:41 +0200 Edward Hervey + + * docs/libs/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/descriptions.c: + * gst-libs/gst/pbutils/gstdiscoverer-private.h: + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/missing-plugins.c: + * gst-libs/gst/pbutils/pbutils-private.h: + pbutils: rename gstdiscoverer-private.h to pbutils-private.h + +2010-09-28 12:15:22 +0200 Edward Hervey + + * gst-libs/gst/pbutils/descriptions.c: + * gst-libs/gst/pbutils/gstdiscoverer-private.h: + * gst-libs/gst/pbutils/missing-plugins.c: + pbutils: Use copy_and_clean_caps for description methods + This allows the various _get_*_description() methods to be more + forgiving with the provided caps. + +2010-10-08 12:51:43 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 5e3c9bf to c4a8adc + +2010-10-08 11:23:33 +0100 Tim-Philipp Müller + + * gst-libs/gst/rtsp/gstrtspextension.c: + * gst-libs/gst/rtsp/gstrtsptransport.c: + * gst-libs/gst/rtsp/gstrtspurl.c: + rtsp: make public _get_type() functions thread-safe + +2010-10-08 10:29:04 +0100 Tim-Philipp Müller + + * gst-libs/gst/rtsp/gstrtspurl.c: + rtspurl: minor clean-up + Merge and const-ify two arrays that should be one. + +2010-10-08 10:06:07 +0100 Tim-Philipp Müller + + * gst-libs/gst/rtsp/gstrtsptransport.c: + rtsp: fix enum value name in enums that are public API + https://bugzilla.gnome.org/show_bug.cgi?id=629746 + +2010-10-08 09:48:50 +0100 Tim-Philipp Müller + + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + audio: make public get_type() functions thread-safe + +2010-10-08 09:45:30 +0100 Tim-Philipp Müller + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + audio: fix enum value name in enums that are public API + So run-time bindings can introspect the names correctly (we abuse this + field as description field only in elements, not for public API + (where the description belongs into the gtk-doc chunk). + https://bugzilla.gnome.org/show_bug.cgi?id=629746 + +2010-10-08 12:30:33 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc-dist.c: + volume: Regenerate generated orc C code again with an orc fix for loading double parameters + +2010-10-08 11:50:43 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + volume: Update generated orc sources + +2010-10-08 11:49:09 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Fix unit test failure for the controlled processing functions + Going over integer arithmetic will lead to minimal rounding errors, + leading to +/-1 changes for volume==1.0. Implement the controlled + processing with floating point arithmetic, which was already done + for the C versions anyway. + +2010-10-08 09:10:41 +0200 Sebastian Dröge + + * configure.ac: + configure: Require orc 0.4.10 + +2010-10-07 23:54:57 +0200 Sebastian Dröge + + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + audioconvert: Update generated orc files + +2010-10-07 23:54:25 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc.orc: + volume: Update for orc changes + double parameters are declared with .doubleparam now. + +2010-10-03 11:21:20 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + volume: Update generated orc sources + +2010-10-03 12:00:42 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc.orc: + volume: Fix controlled processing via orc + +2010-10-03 11:24:29 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + volume: Actually enable usage of the orc optimized functions + +2010-10-03 11:20:37 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Implement int32 processing with orc + +2010-10-01 12:21:52 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Implement controlled processing for int16/1-2ch and int8/1,2,4ch with orc + +2010-10-01 11:13:01 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Implement controlled processing for f64/1ch and f32/1-2ch in orc + +2010-10-01 11:00:54 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Convert parts of the controlled processing to orc + +2010-10-01 10:44:37 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Implement f64 scaling with orc + This requires orc 0.4.10 + +2010-10-01 10:38:38 +0200 Sebastian Dröge + + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/gstaudioconvertorc.orc: + audioconvert: Implement remaining conversion functions from/to doubles to orc + This requires orc 0.4.10 + +2010-10-07 20:54:32 +0100 Tim-Philipp Müller + + * gst/audiorate/gstaudiorate.c: + audiorate: use g_object_notify_by_pspec() if possible + Use g_object_notify_by_pspec() when building against GLib >= 2.26. + This avoids the pspec lookup which takes the global paramspec pool lock. + +2010-10-07 20:37:10 +0100 Tim-Philipp Müller + + * gst/videorate/gstvideorate.c: + videorate: use g_object_notify_by_pspec() if possible + Use g_object_notify_by_pspec() when building against GLib >= 2.26. + This avoids the pspec lookup which takes the global paramspec pool lock. + +2010-10-04 10:01:19 -0300 Thiago Santos + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: Do not advance segment starts beyond stop times + Advance stop times too when they are getting higher than the + stop time of segments, avoiding assertions. + The stop time has to be advanced too so that running time keep in sync + for gapless mode. + https://bugzilla.gnome.org/show_bug.cgi?id=631312 + +2010-10-06 16:19:49 -0300 Thiago Santos + + * tests/check/libs/rtp.c: + tests: rtp: No need to unref buffer from bufferlist + Buffers obtained from buffer list iterators don't need to + be unreffed. + Test was failing due to this. + +2010-10-04 11:22:45 +0200 Mark Nauwelaerts + + * ext/vorbis/gstvorbisdec.c: + vorbisdec: reverse playback; decode pending buffers upon EOS + +2010-10-05 19:15:47 +0100 Tim-Philipp Müller + + * gst/videoscale/vs_4tap.c: + videoscale: use math-compat.h here as well + Hopefully the powers that be don't mind the gst/glib include here + too much. + +2010-10-05 19:13:43 +0100 Tim-Philipp Müller + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: include new math-compat.h header for rint() on MSVC + Should fix compilation with Visual Studio 2008. + https://bugzilla.gnome.org/show_bug.cgi?id=630802 + +2010-10-05 17:19:28 +0200 Wim Taymans + + * win32/common/libgstrtp.def: + win32: update def file with new RTP methods + +2010-10-05 17:13:09 +0200 Wim Taymans + + * tests/check/libs/rtp.c: + check: fix rtp checks + Fix the checks for the extension support in RTP. + +2010-10-05 16:36:24 +0200 Wim Taymans + + * tests/examples/seek/seek.c: + seek: fix position reporting + +2010-08-26 12:34:11 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + * gst-libs/gst/rtp/gstrtcpbuffer.h: + rtcpbuffer: Add function to manipulation the data in RTCP feedback packets + Add methods to get/set the length of the Feedback Control Information (FCI) as + well as getting a pointer to the FCI itself. + +2010-08-23 16:41:44 -0400 Olivier Crête + + * tests/check/libs/rtp.c: + tests: Test the manipulations of bufferlists containing RFC 5285 header extensions + +2010-08-23 14:24:21 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add function to transform a GstBuffer into a GstBufferList + Add a new function called gst_rtp_buffer_list_from_buffer() that takes + a GstBuffer containing a RTP packets and spits out a GstBufferList + containing two buffers, one with the header and the other with the payload. + +2010-08-22 19:44:38 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add functions to add RFC 5285 header extensions to GstBufferLists + Add functions to add header extensions to buffer lists, these functions only modify + the header part of the buffer lists, so the data is not copied. + +2010-08-22 17:22:21 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add function to read RFC 5285 header extensions from GstBufferLists + +2010-08-20 15:30:08 -0400 Olivier Crête + + * tests/check/libs/rtp.c: + tests: Add test for RTP header extension functions + +2010-08-20 17:13:06 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add function to add RTP header extensions with a two bytes header + +2010-08-20 12:54:38 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add function to append RFC 5285 one byte header extensions + +2010-08-19 16:26:18 -0400 Olivier Crête + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + rtpbuffer: Add function to parse RFC 5285 header extensions + RFC 5285 describes a generic method to add multiple header extensions to RTP packets. + These functions parse these headers and return them, both for the one-byte header and the + two bytes headers. + +2010-10-05 12:05:38 +0200 Wim Taymans + + * ext/libvisual/visual.c: + libvisual: only drop frames that are really too old + Also take the frame duration into account so that we don't drop frames that are + partially past the estimated QoS time. + +2010-10-05 12:01:25 +0200 Wim Taymans + + * ext/libvisual/visual.c: + libvisual: add latency query + Add our own latency to the latency query reply from upstream. + +2010-10-05 12:00:28 +0200 Wim Taymans + + * ext/libvisual/visual.c: + libvisual: add some defines + Add some defines for width/height/fps and a define for the minimum amount of + samples we need to buffer. + +2010-10-04 15:48:51 +0530 Arun Raghavan + + * tools/gst-discoverer.c: + gst-discoverer: The 'ready' signal was renamed to 'finished' + +2010-10-04 17:27:00 +0200 Wim Taymans + + * ext/theora/gsttheoraparse.c: + parse: Don't error on discont + We don't need to error out when we detect a discontinuity. + +2010-10-04 17:08:43 +0200 Wim Taymans + + * ext/theora/gsttheoraparse.c: + theoraparse: set caps on streamheader too + +2010-10-04 13:07:14 +0530 Arun Raghavan + + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + build: Fix include path order for gir generation + This makes sure that the built girs are picked up over installed girs + where this is currently the case. + +2010-10-01 14:52:15 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/codec-utils.c: + codec utils: populate mpeg4 caps "level" field with level, not profile + Call the right function to get the level. Also add some more debug + logging. + +2010-10-01 10:47:08 +0200 Sebastian Dröge + + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + volume: Update generated orc files + +2010-10-01 10:42:27 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + volume: Improve f32 scaling by using only a single array + Passing the same array as dest and src is invalid anyway because + they're maked with the restrict qualifier. + +2010-09-30 15:19:02 +0100 Tim-Philipp Müller + + * gst-libs/gst/pbutils/codec-utils.c: + pbutils: include config.h in codec utils + +2010-09-30 00:19:29 +0100 Tim-Philipp Müller + + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/codec-utils.c: + docs: add new codec utils API to docs + +2010-05-01 01:03:18 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/codec-utils.c: + * gst-libs/gst/pbutils/codec-utils.h: + * win32/common/libgstpbutils.def: + pbutils: Add MPEG-4 Video profile/level extraction + This adds code to translate the profile_and_level indication from the + MPEG-4 video (ISO/IEC 14496-2) headers to a string profile/level. The + mappings are taken from the spec and Wireshark's code, and might need to + be expanded on. + https://bugzilla.gnome.org/show_bug.cgi?id=617314 + API: gst_codec_utils_mpeg4video_get_profile() + API: gst_codec_utils_mpeg4video_get_level() + API: gst_codec_utils_mpeg4video_caps_set_level_and_profile() + +2010-04-30 20:50:09 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/codec-utils.c: + * gst-libs/gst/pbutils/codec-utils.h: + pbutils: add H.264 profile/level extraction functions to codec utils + This adds code to parse the first few bytes of H.264 sequence parameter + set in order to extract the profile and level as const strings. This + code was originally in both qtdemux and matroskademux. + https://bugzilla.gnome.org/show_bug.cgi?id=617314 + API: gst_codec_utils_h264_get_level() + API: gst_codec_utils_h264_get_profile() + API: gst_codec_utils_h264_caps_set_level_and_profile() + +2010-04-30 15:12:04 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/codec-utils.c: + * gst-libs/gst/pbutils/codec-utils.h: + * gst/typefind/gsttypefindfunctions.c: + * win32/common/libgstpbutils.def: + pbutils: add AAC profile detection to codec utils + This moves AAC profile detection to pbutils, and uses this in + typefindfunctions. This will also be used in qtdemux. + https://bugzilla.gnome.org/show_bug.cgi?id=617314 + API: gst_codec_utils_aac_get_profile() + API: codec_utils_aac_caps_set_level_and_profile() + +2010-04-30 13:41:17 +0530 Arun Raghavan + + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/codec-utils.c: + * gst-libs/gst/pbutils/codec-utils.h: + * gst-libs/gst/pbutils/pbutils.h: + * gst/typefind/Makefile.am: + * gst/typefind/gstaacutil.c: + * gst/typefind/gstaacutil.h: + * gst/typefind/gsttypefindfunctions.c: + * win32/common/libgstpbutils.def: + pbutils: add codec-specific utility functions for AAC + This allows us to add generic codec-specific functionality, like + extracting profile/level data from headers, without having to duplicate + code across demuxers and typefindfunctions. + As a starting point, this moves over AAC level extraction code from + typefindfunctions, so it can be reused in qtdemux, etc. + https://bugzilla.gnome.org/show_bug.cgi?id=617314 + API: gst_codec_utils_aac_get_sample_rate_from_index() + API: gst_codec_utils_aac_get_level() + +2010-09-30 13:12:30 +0300 René Stadler + + * gst-libs/gst/tag/tags.c: + tags: fix unused function warning with debug disabled + +2010-09-30 12:59:46 +0300 René Stadler + + * gst-libs/gst/tag/tags.c: + tags: fix illegal use of internal debug category function + From gstinfo.h: + /* do not use this function, use the GST_DEBUG_CATEGORY_INIT macro */ + GstDebugCategory *_gst_debug_category_new (const gchar * name, + And more importantly: + #pragma GCC poison _gst_debug_category_new + So this commit fixes --disable-gst-debug builds. + +2010-09-29 18:57:50 +0200 Edward Hervey + + * tools/gst-discoverer.c: + gst-discoverer: Print out topology if available. + If we have some unhandled streams, we can still print out the remaining + topology. + +2010-09-29 18:54:28 +0200 Edward Hervey + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't post async-done when not needed + Where it was previously located, we would get async-done for the first + unknown-type, even if other valid streams would appear afterwards. + decode_bin_expose() will take care of posting async-done when the group + is exposed. + But we still want to post it in case the typefinding returned an unknown + type, in which case we will post it after posting an error. + These two changes ensure we do as much as possible before posting async-done. + +2010-09-29 16:53:21 +0200 Thijs Vermeir + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basertpdepay: ensure metadata is writable + +2010-09-29 13:29:20 +0200 Edward Hervey + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add descriptions for more codecs + +2010-09-29 12:33:44 +0200 Edward Hervey + + * tests/examples/seek/seek.c: + seek: Fix debug statement argument type + +2010-09-28 09:30:57 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tools/Makefile.am: + More makefile Fixes + Removing some not needed lines added in the last makefile + fixes commit (previous commit). + Also adds some more makefile files to check tests + +2010-06-17 14:32:22 +0300 René Stadler + + * sys/xvimage/xvimagesink.c: + xvimagesink: allow render rectangle coordinates to be negative + Useful for cropped zooming. + +2010-06-17 14:33:44 +0300 René Stadler + + * gst-libs/gst/interfaces/xoverlay.c: + xoverlay: allow render rectangle coordinates to be negative + This is useful for cropped zooming of the overlay. + +2010-09-28 15:15:57 +0300 René Stadler + + * gst-libs/gst/interfaces/xoverlay.c: + xoverlay: fix endless loop in deprecated method + +2010-09-28 08:46:25 -0300 Thiago Santos + + * tests/examples/app/Makefile.am: + * tools/Makefile.am: + Fixing Makefiles + Adds some missing lines to makefiles + +2010-09-27 18:14:50 +0100 Tim-Philipp Müller + + * gst-libs/gst/tag/tags.c: + tags: add debug category for tags utility functions + +2010-09-27 14:36:17 +0100 Tim-Philipp Müller + + * gst-libs/gst/tag/tags.c: + tags: try ISO-8859-1 as second fallback in case WINDOWS-1252 is not supported + Better safe than sorry. Some embedded systems may use crippled iconv + implementations or not support WINDOWS-1252 for other reasons. + https://bugzilla.gnome.org/show_bug.cgi?id=630471 + +2010-09-23 23:53:48 +0300 Sreerenj Balachandran + + * gst-libs/gst/tag/tags.c: + tags: when converting freeform strings try Windows-1252 as fallback instead of ISO-8859-1 + Windows-1252 is a superset of ISO-8859-1, which uses some space + allocated to control characters for additional printable characters. + https://bugzilla.gnome.org/show_bug.cgi?id=630471 + +2010-09-24 21:30:20 -0700 David Schleef + + * ext/theora/gsttheoraenc.c: + theoraenc: ptalarbvorm speed level goes to 3 + +2010-09-24 16:31:37 +0200 Vladimir + + * tests/examples/seek/seek.c: + seek: Add #define for seekbar granularity + Fixes #630496 + +2010-09-24 14:03:45 +0100 Tim-Philipp Müller + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/audio-enumtypes.c: + * win32/common/audio-enumtypes.h: + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/gstrtsp-enumtypes.h: + * win32/common/interfaces-enumtypes.c: + * win32/common/interfaces-enumtypes.h: + * win32/common/pbutils-enumtypes.c: + * win32/common/pbutils-enumtypes.h: + * win32/common/video-enumtypes.c: + * win32/common/video-enumtypes.h: + win32: define GST_PACKAGE_RELEASE_DATETIME in win32 config.h as well + Also update enums. + +2010-09-24 00:25:20 +0100 Tim-Philipp Müller + + * tests/check/elements/.gitignore: + .gitignore: ignore new appsrc unit test + +2010-09-24 13:09:28 +0200 Wim Taymans + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: add Since markers + Fixes #630443 + +2010-07-30 13:54:42 +0200 Havard Graff + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosink.h: + * win32/common/libgstaudio.def: + baseaudiosink: Added getter and setter for drift tolerance. + +2010-09-24 12:54:47 +0200 Wim Taymans + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: subtract the render_delay from our latency + The latency reported by the base class includes the render_delay, which we don't + want to include when we start slaving our clocks. + See #630441 + +2010-09-23 23:57:50 +0200 Sebastian Dröge + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: Use G_DEFINE_ABSTRACT_TYPE instead of manual GObject boilerplate code + This also makes the _get_type() function threadsafe. + Fixes bug #630440. + +2010-09-23 10:16:07 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tags: exif: Add mapping for _HORIZONTAL_ERROR + Maps GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR to the + GPSHPositionError tag in exif. + Tests included. + +2010-09-22 14:10:18 -0300 Thiago Santos + + * gst-libs/gst/app/gstappsrc.c: + * tests/check/Makefile.am: + * tests/check/elements/appsrc.c: + appsrc: Do not override buffer caps if appsrc caps is null + Make appsrc not set caps on buffers when its own caps is NULL. + This avoids calling make_metadata_writable on all buffers and + prevents losing buffer caps in case we are not replacing it + with something meaningful. + https://bugzilla.gnome.org/show_bug.cgi?id=630353 + +2010-09-21 18:57:42 -0400 Olivier Crête + + * ext/theora/gsttheoraenc.c: + * ext/theora/gsttheoraenc.h: + theoraenc: Make the bitrate/quality dynamically modifiable + https://bugzilla.gnome.org/show_bug.cgi?id=630303 + +2010-09-22 12:35:59 +0200 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer.c: + * tools/gst-discoverer.c: + discoverer: Fixup DiscovererResult handling + This was a leftover from the changes from a flag to an enum + +2010-09-22 12:10:24 +0200 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: We don't need the signals from the queues + +2010-09-22 01:50:21 -0700 David Schleef + + * gst-libs/gst/Makefile.am: + gst-libs: build pbutils after video + Because pbutils now depends on video. + +2010-09-21 18:33:36 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From aa0d1d0 to 5e3c9bf + +2010-09-20 21:04:48 +0300 Stefan Kost + + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + discoverer: fix docs + While the doc parser allows for certain variation, it is a good idea to not + use random characters here and there, but try to stick to the little markup + syntax there is. + +2010-09-20 16:45:32 +0200 Edward Hervey + + * gst-libs/gst/pbutils/gstdiscoverer.c: + discoverer: Fix debug statement. + Fixes build on macosx + +2010-09-20 16:28:52 +0200 Edward Hervey + + * gst/volume/gstvolumeorc-dist.c: + volume: orc fixup for loading float arguments + This is only used with DISABLE_ORC. + +2010-09-20 11:24:10 +0200 Edward Hervey + + * tools/.gitignore: + * tools/Makefile.am: + * tools/gst-discoverer.c: + tools: Standalone tool for discovering media file properties + Fixes #625944 + +2010-09-20 11:23:36 +0200 Edward Hervey + + * win32/common/libgstpbutils.def: + win32: Update with symbols from GstDiscoverer + Fixes #625944 + +2010-09-20 11:23:17 +0200 Edward Hervey + + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + docs: Documentation for new pbutils GstDiscoverer + Fixes #625944 + +2010-09-20 11:22:32 +0200 Edward Hervey + + * gst-libs/gst/Makefile.am: + * gst-libs/gst/pbutils/.gitignore: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/gstdiscoverer-private.h: + * gst-libs/gst/pbutils/gstdiscoverer-types.c: + * gst-libs/gst/pbutils/gstdiscoverer.c: + * gst-libs/gst/pbutils/gstdiscoverer.h: + * gst-libs/gst/pbutils/pbutils-marshal.list: + * gst-libs/gst/pbutils/pbutils.h: + pbutils: New Discoverer utility + Fixes #625944 + +2010-09-20 11:13:56 +0200 Sebastian Dröge + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add mp3 to the apetag extensions + +2010-09-18 13:15:08 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix regression in ball pattern + Was painting using two different methods. + +2010-09-17 11:46:05 +0200 Sebastian Dröge + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: Fix ACCEPTABLE_CHAR() macro to work with signed and unsigned chars + +2010-09-17 11:44:29 +0200 Sebastian Dröge + + * gst-libs/gst/sdp/gstsdpmessage.c: + Revert "sdp: Remove useless check in macro" + This reverts commit e6a041b69fd21c42651d98cf8a3064e43cecc51c. + It's not a useless check, the signedness of "char" and "gchar" is + defined by the ABI. + +2010-09-17 10:43:04 +0200 Edward Hervey + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: Remove useless check in macro + A signed char is always < 128. Fixes a warning on macosx build. + +2010-09-16 18:03:23 -0700 David Schleef + + * gst/adder/gstadderorc-dist.c: + * gst/adder/gstadderorc-dist.h: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.h: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + orc: update generated files to fix MSVC compile issues + +2010-09-16 17:56:31 -0700 David Schleef + + * gst/videoscale/gstvideoscaleorc.orc: + videoscale: Don't use broken orc feature + +2010-09-16 19:30:59 +0200 Wim Taymans + + * gst-libs/gst/interfaces/xoverlay.c: + xoverlay: G_GUINTPTR_FORMAT is since 2.22 + Don't rely on too new symbols, we only depend on 2.20. + +2010-09-16 15:01:59 +0200 Wim Taymans + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/playrec/.gitignore: + * tests/examples/playrec/Makefile.am: + * tests/examples/playrec/playrec.c: + examples: add synchronized playback and capture example + Add an example that demonstrates synchronized playback and capture. + +2010-09-16 17:15:32 +0200 Thijs Vermeir + + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Fix indentation + +2010-09-16 17:14:20 +0200 Thijs Vermeir + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: add bar pattern + Simple bar with foreground color on the background color + +2010-09-16 15:07:15 +0200 Thijs Vermeir + + * tests/check/elements/videotestsrc.c: + tests: use gst-check API in videotestsrc + use gst_check_drop_buffers in videotestsrc to + clear the global buffers list. + +2010-09-16 14:55:55 +0200 Thijs Vermeir + + * tests/check/elements/videotestsrc.c: + tests: Fix unit test of videotestsrc + Use UYVY for unit tests, it's exactly the same as Y422. + (which is currently disabled in videotestsrc) + +2010-09-15 15:13:15 +0100 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update for new strings + +2010-09-15 15:12:26 +0100 Tim-Philipp Müller + + * gst-libs/gst/video/video.h: + docs: add Since: comment to docs for new GST_VIDEO_FORMAT_UYVP + +2010-09-14 11:20:42 -0400 Tristan Matthews + + * ext/gnomevfs/gstgnomevfssrc.c: + gnomevfsrc: set GST_PARAM_MUTABLE_READY flag on the "handle" property + Fixes #629672 + +2010-09-15 15:19:04 +0200 Thijs Vermeir + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: fix segfault on negative horizontal-speed + +2010-09-15 14:15:13 +0200 Edward Hervey + + * gst/playback/gstdecodebin2.c: + decodebin2: Actually dispose the unused ghostpads + +2010-09-15 11:28:29 +0200 Sebastian Dröge + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + * gst/audioresample/resample.c: + * gst/audioresample/speex_resampler.h: + * gst/audioresample/speex_resampler_wrapper.h: + Revert "audioresample: Add GAP flag support" + This reverts commit 129af0d8e6a74e8edef3e77c3626616b674b7cc1. + This shouldn't be committed at all, it isn't ready and apparently + was in the wrong branch locally. + +2010-09-15 11:26:48 +0200 Sebastian Dröge + + * gst-libs/gst/video/convertframe.c: + * gst-libs/gst/video/video.h: + * tests/check/libs/video.c: + video: Add a destroy notify parameter to gst_video_convert_frame_async() + Binding generators apparently need this as they can't really know + that the callback is guaranteed to be called exactly once and that + the user_data can be freed at the end of it. + +2010-09-14 12:00:39 +0200 Leo Singer + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + * gst/audioresample/resample.c: + * gst/audioresample/speex_resampler.h: + * gst/audioresample/speex_resampler_wrapper.h: + audioresample: Add GAP flag support + Fixes bug #586570. + +2010-09-05 15:17:47 -0700 David Schleef + + * gst-libs/gst/interfaces/xoverlay.c: + * gst-libs/gst/interfaces/xoverlay.h: + * sys/v4l/gstv4lxoverlay.c: + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + * tests/examples/overlay/gtk-xoverlay.c: + * tests/examples/overlay/qt-xoverlay.cpp: + * tests/examples/overlay/qtgv-xoverlay.cpp: + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + * tests/icles/stress-xoverlay.c: + * tests/icles/test-colorkey.c: + * tests/icles/test-xoverlay.c: + * win32/common/libgstinterfaces.def: + xoverlay: Add guintptr versions of functions + And deprecate the gulong versions. This is to support platforms + where sizeof(unsigned long) < sizeof(void *). Fixes #627565. + API: Add gst_x_overlay_set_window_handle() + API: Deprecate: gst_x_overlay_set_xwindow_id() + API: Add gst_x_overlay_got_window_handle() + API: Deprecate: gst_x_overlay_got_xwindow_id() + API: Add GstXOverlay::set_window_handle() + API: Deprecate: GstXOverlay::set_xwindow_id() + +2010-09-14 12:31:58 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add UYVP + +2010-09-12 20:36:19 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Various improvements + Replace moving-color-bars pattern with smpte100, and change + moving-speed to horizontal-speed. Default is now 0. Add + a rotation stage to pattern building. + Allocate a temporary scanline for building images. Remove + unused code. Disable several patterns that we're unable to + test and probably never used. Add other variants of bayer + sampling. Convert some patterns to use videotestsrc_blend_line. + +2010-09-10 18:10:40 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: clean up blink pattern + +2010-09-10 15:57:54 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Clean up the RGB code + +2010-09-10 14:40:44 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Convert to intermediate AYUV/ARGB + Scanlines are generated into AYUV/ARGB, then converted to the + various formats. + +2010-09-10 12:48:30 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: rearrange code to work on scanlines + +2010-09-10 12:03:07 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix recent breakage of smpte75 pattern + +2010-09-01 15:18:31 +0200 Thijs Vermeir + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: add moving color bars pattern + This pattern is moving the color bars with a given + speed. Negative speed is inverting the moving direction. + https://bugzilla.gnome.org/show_bug.cgi?id=628500 + +2010-06-14 15:42:09 -0700 David Schleef + + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videoscale/vs_image.c: + * gst/videoscale/vs_scanline.c: + videoscale: refactor using more Orc code + Convert downsampling to Orc. Convert horizontal linear scaling + to Orc. Combine horizontal and vertical scaling into one pass. + +2010-09-12 19:34:28 -0700 David Schleef + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add UYVP, 10-bit 4:2:2 + +2010-09-14 08:41:43 +0200 Sebastian Dröge + + * docs/libs/gst-plugins-base-libs-sections.txt: + video: Add gst_video_convert_frame_async() to the docs + +2010-09-14 08:40:52 +0200 Sebastian Dröge + + * win32/common/libgstvideo.def: + win32: Add gst_video_convert_frame() and gst_video_convert_frame_async() to the .def files + +2010-09-14 08:40:07 +0200 Sebastian Dröge + + * tests/check/libs/video.c: + video: Add unit test for gst_video_convert_frame_async() + +2010-09-14 08:39:20 +0200 Sebastian Dröge + + * gst-libs/gst/video/convertframe.c: + * gst-libs/gst/video/video.h: + video: Add async variant of the convert frame function + API: gst_video_convert_frame_async() + +2010-09-12 16:53:59 +0200 Sebastian Dröge + + * tests/check/libs/video.c: + video: Add a simple unit test for the new convert_frame API + Unfortunately this can't test the encoding because there's no + image encoder in base. + +2010-09-12 16:51:52 +0200 Sebastian Dröge + + * gst-libs/gst/video/convertframe.c: + video: Strip framerate from the target caps + There will always be only a single output buffer and if the + target caps have a different framerate than the input there + will be a negotiation error during conversion. + +2010-09-12 16:36:15 +0200 Sebastian Dröge + + * gst-libs/gst/video/convertframe.c: + video: Refactor convert_frame a bit and fix some minor memory leaks in error cases + +2010-09-09 14:11:52 +0200 Edward Hervey + + * gst/playback/Makefile.am: + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + * gst/playback/gstscreenshot.c: + * gst/playback/gstscreenshot.h: + playback: Switch to using gst_video_convert_frame + https://bugzilla.gnome.org/show_bug.cgi?id=629157 + +2010-09-09 13:44:54 +0200 Edward Hervey + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/convertframe.c: + * gst-libs/gst/video/video.h: + video: Add new method for converting a video frame + https://bugzilla.gnome.org/show_bug.cgi?id=629157 + +2010-09-13 10:02:44 +0200 Mark Nauwelaerts + + * gst/playback/gstdecodebin2.c: + decodebin2: prevent another race with shutdown state change + +2010-09-11 14:55:01 +0200 Sebastian Dröge + + * win32/common/libgstsdp.def: + win32: Add new SDP symbols to the .def files + +2010-09-10 18:42:16 +0200 Wim Taymans + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: remove leftover g_print + +2010-09-10 17:55:46 +0200 Wim Taymans + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/sdp/gstsdpmessage.c: + * gst-libs/gst/sdp/gstsdpmessage.h: + sdp: add methods to convert between uri and message + Add methods to convert between uri and sdpmessages, loosly based on + http://tools.ietf.org/html/draft-fujikawa-sdp-url-01 + API: GstSDPMessage::gst_sdp_message_parse_uri + API: GstSDPMessage::gst_sdp_message_as_uri + +2010-09-10 10:40:52 +0200 Thijs Vermeir + + * tests/check/elements/videotestsrc.c: + tests: videotestsrc change the pattern property for the tests + +2010-09-10 08:42:37 +0200 Sebastian Dröge + + * gst/adder/gstadderorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/volume/gstvolumeorc-dist.c: + orc: Fix generated source files + +2010-09-09 20:45:38 +0100 Tim-Philipp Müller + + * tests/examples/seek/seek.c: + tests: fix passing of URIs containing '*' and '?' to the seek example + Only do wildcard expansion (why?!) on things that look like local + file paths. Fixes passing of URIs containing '*' and '?' (see #629212). + +2010-09-09 21:51:18 +0300 Stefan Kost + + * tests/check/Makefile.am: + * tests/check/generic/states.c: + tests: allow running state tests for all elements + Now one can use GST_NO_STATE_IGNORE_ELEMENTS=1 make generic/states.check + to try elements that would normaly be skipped. + +2010-09-09 11:12:56 +0200 Sebastian Dröge + + * gst/adder/gstadder.c: + adder: Do debug category initialization in plugin_init again + +2010-09-09 10:59:13 +0200 Sebastian Dröge + + * gst/adder/gstadderorc-dist.c: + * gst/adder/gstadderorc-dist.h: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.h: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + orc: Update generated source files everywhere + +2010-09-09 10:57:41 +0200 Sebastian Dröge + + * gst/adder/gstadder.c: + * gst/adder/gstadderorc.orc: + * gst/audioconvert/gstaudioconvertorc.orc: + * gst/audioconvert/plugin.c: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrcorc.orc: + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + Revert "Revert "Use init functions for Orc code"" + This reverts commit 93aa13639d74449dc68296427e5dbcfe8aca5f51. + Everything should work now after regenerating the disted source files. + +2010-09-07 19:04:23 +0200 Edward Hervey + + * win32/common/libgstaudio.def: + win32: Add new symbol to libgstaudio + +2010-09-07 18:09:12 +0200 Wim Taymans + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudio: avoid taking extra ref on sink/src + Don't take an extra ref on the sink and source because that creates a reference + cycle. Instead, use the invalidate method of the clock when the sink and source + are freed. This way, we don't call into the time function anymore after the + objects are disposed. + +2010-09-07 18:06:27 +0200 Wim Taymans + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstaudioclock.h: + audioclock: add a function to invalidate the clock + Add a function to invalidate the time function of a clock. Useful for when the + function becomes invalid. + +2010-09-07 16:26:56 +0200 Edward Hervey + + * tests/check/Makefile.am: + check: Fix linking order of libs/tag + +2010-09-07 16:26:30 +0200 Edward Hervey + + * tests/check/gst-plugins-base.supp: + check: Make fontconfig leak suppression more generic + +2010-09-07 08:46:15 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds mappings for new image ppi tags + Adds mappings for GST_TAG_IMAGE_HORIZONTAL/VERTICAL_PPI into + our exif lib + Tests included. + Fixes #626570 + +2010-09-07 08:22:27 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tags: Add GST_TAG_IMAGE_HORIZONTAL/VERTICAL_PPI tags + Adds new tags for representing the intended PPI of images/videos + API: GST_TAG_IMAGE_HORIZONTAL_PPI + API: GST_TAG_IMAGE_VERTICAL_PPI + Fixes #626570 + +2010-09-07 11:41:52 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c2e10bf to aa0d1d0 + +2010-09-06 18:17:10 +0100 Tim-Philipp Müller + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + rtp: improve basertpdepayload's error message when no input caps were set + This is pretty much an FAQ, so try to make the error message a bit + more helpful. Also, don't tell people to file a bug in bugzilla + about this (which is what happens if the default error message for + CORE_NEGOTIATION is used). + +2010-09-06 13:14:00 +0200 Wim Taymans + + * gst-libs/gst/rtp/gstbasertppayload.c: + rtppayload: notify of first timestamp/seqnum + Notify of the first timestamp/seqnum pushed out by the payloader. + Fixes #612264 + +2010-09-06 11:53:35 +0200 Edward Hervey + + * gst/videotestsrc/.gitignore: + videotestsrc: .gitignore new generate_sine_table + +2010-09-06 11:44:17 +0300 Stefan Kost + + * gst/playback/gstinputselector.c: + * gst/playback/gstinputselector.h: + * gst/playback/gstplaybin2.c: + playback: ref the selector pad class inside input-selector + Minimizes the delta to original element in -bad and allows us to keep the + type static. + +2010-09-05 20:57:48 -0700 David Schleef + + * gst/videotestsrc/Makefile.am: + * gst/videotestsrc/generate_sine_table.c: + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Use static sine table + +2010-09-05 20:35:13 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Add foreground/background-color properties + Replace solid-color property with foreground-color and add + background-color. Pull some common code out of each of the + pattern generating functions. Fix many of the patterns to + use foreground-color/background-color instead of white/black. + Generated images are indentical to previously if foreground-color + and background-color are left as default. + API: GstVideoTestSrc::foreground-color + API: GstVideoTestSrc::background-color + +2010-09-05 18:58:03 -0700 David Schleef + + * common: + Automatic update of common submodule + From d3d9acf to c2e10bf + +2010-09-05 17:04:31 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: deprecate colorspec property + Fixes: #616392. + +2010-09-05 12:57:36 +0200 Sebastian Dröge + + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc.orc: + audioconvert: Simplify float->s32 conversion + orc 0.4.7 is doing saturated conversion from floats to integers + and it's not necessary to do this manually anymore. + +2010-09-05 12:14:55 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ca1c867 to d3d9acf + +2010-09-05 12:12:43 +0200 Sebastian Dröge + + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + audioconvert: Update disted orc files + +2010-09-05 12:09:19 +0200 Sebastian Dröge + + * gst/volume/gstvolume.c: + volume: Enable float processing with orc again + +2010-09-05 12:08:44 +0200 Sebastian Dröge + + * configure.ac: + configure: Require orc 0.4.8.1 for the volume test + +2010-08-26 19:16:18 +0200 Sebastian Dröge + + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/gstaudioconvertorc.orc: + audioconvert: Use the ORC double support + +2010-09-04 09:06:08 +0200 Leo Singer + + * gst-libs/gst/tag/gstexiftag.c: + exiftag: Fix compiler warnings with old gcc versions + Old gcc complains about possibly uninitialized variables which + are always initialized before usage in reality. Fixes bug #628747. + +2010-08-06 11:53:38 +0200 Edward Hervey + + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstfactorylists.c: + * gst/playback/gstfactorylists.h: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playback: Switch to gstfactorylist from core + https://bugzilla.gnome.org/show_bug.cgi?id=626181 + +2010-09-02 12:57:42 +0300 Stefan Kost + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: fix typo in property description + +2010-09-01 17:52:31 +0200 Sebastian Dröge + + * ext/pango/gsttextoverlay.c: + textoverlay: Add support for AYUV + +2010-09-01 11:37:37 +0200 Sebastian Dröge + + * gst/audiorate/gstaudiorate.c: + audiorate: Fill segment until the end on EOS + +2010-09-01 11:33:12 +0200 Sebastian Dröge + + * gst/videorate/gstvideorate.c: + videorate: Fill the segment on EOS or at least produce enough frames to use the complete buffer duration + Fixes bug #628400. + +2010-09-01 11:22:25 +0200 Sebastian Dröge + + * gst/videorate/gstvideorate.c: + videorate: Don't ignore flow returns when filling the previous segment during NEWSEGMENT handling + +2010-09-01 11:11:47 +0200 Philippe Normand + + * tests/examples/seek/seek.c: + seek: allow seeking behind the currently downloaded position. + +2010-09-01 10:06:09 +0300 Stefan Kost + + * gst/adder/gstadder.c: + adder: use GST_BOILERPALTE macro + +2010-08-31 10:09:51 +0200 Edward Hervey + + * gst/playback/gstplaysink.c: + playback: Set queues silent property to TRUE + We don't use the queue signals within playsink. + +2010-08-30 14:59:22 -0500 Rob Clark + + * ext/pango/gsttextoverlay.c: + textoverlay: fix Cb/Cr inversion for colored text overlays + In case of odd values for xpos or ypos, the division by two in CbCr + plane would result in an off-by-one error, which in the case of NV12, + NV21, or UYVY would cause inversion of blue and red colors. (And + would be not so easily noticed for I420 as it would just cause the + chroma to be offset slightly from the luma.) + This patch also fixes a silly typo from the earlier patch which + added NV12 support that broke UYVY support. + +2010-08-30 15:50:26 +0200 Sebastian Dröge + + * ext/ogg/gstoggdemux.c: + oggdemux: Don't reset the pad when pushing resulted in NOT_LINKED + The pad might be linked later and after resetting it it will + only work after resetting all of oggdemux. + +2010-08-27 20:45:19 +0200 Sebastian Dröge + + * gst/playback/gsturidecodebin.c: + uridecodebin: Only enable progressive downloading if the upstream duration in bytes is known + Otherwise we might try to enable it for live streams, where this would + cause playback to fail completely. + Fixes bug #628028. + +2010-08-27 17:23:46 +0200 Sebastian Dröge + + * ext/ogg/gstoggaviparse.c: + * ext/ogg/gstoggdemux.c: + oggdemux: Don't use GST_FLOW_IS_FATAL() + And while we're at it, handle WRONG_STATE as error too + in oggdemux and WRONG_STATE and NOT_LINKED in oggaviparse. + +2010-08-27 11:49:47 +0200 Wim Taymans + + * gst/adder/gstadder.c: + * gst/adder/gstadderorc.orc: + * gst/audioconvert/gstaudioconvertorc.orc: + * gst/audioconvert/plugin.c: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrcorc.orc: + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + Revert "Use init functions for Orc code" + This reverts commit b2051090b43f82b23bb01826f09053479bbd7874. + Fixes the build again until someone pushes the regenerated .c/.h + files too. + +2010-08-22 23:01:19 -0700 David Schleef + + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: clean up code + Merge various color structures into one. + +2010-08-22 22:16:45 -0700 David Schleef + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Add ball pattern + +2010-08-19 15:43:09 -0700 David Schleef + + * gst/adder/gstadder.c: + * gst/adder/gstadderorc.orc: + * gst/audioconvert/gstaudioconvertorc.orc: + * gst/audioconvert/plugin.c: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrcorc.orc: + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc.orc: + Use init functions for Orc code + +2010-08-26 15:17:20 +0300 Stefan Kost + + * gst/volume/gstvolume.c: + volume: make the orc usage for float conditional again + See bug #628009. The tests still fail in the orc code (which we just don't call + now). + +2010-08-25 12:19:05 +0200 Thijs Vermeir + + * gst-libs/gst/riff/riff-media.c: + riff: add support for 2vuy + It is the apple alternative for Microsofts UYVY. + (http://ntta.szm.com/Tutors/FourCC.htm) + Only use the UYVY for the caps to enable support in other + gstreamer elements. + https://bugzilla.gnome.org/show_bug.cgi?id=627924 + +2010-08-25 19:01:57 +0300 Stefan Kost + + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + * gst/volume/gstvolumeorc.orc: + volume: enable ORC for float in volume + +2010-08-25 11:19:31 -0300 Thiago Santos + + * configure.ac: + * gst-libs/gst/tag/gstexiftag.c: + configure: Add check for log2 + Adds check for log2 and only use it in exif library if it is + available. + +2010-08-25 15:32:41 +0200 Sebastian Dröge + + * gst-libs/gst/tag/Makefile.am: + tag: Link to $(LIBM) for pow(), log2() and friends + +2010-08-25 08:41:52 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Move some tags to their correct IFDs + Put some tags in their correct IFDs + +2010-08-20 16:39:08 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Always write FlashPixVersion tag + FlashPixVersion is mandatory and constant. Write it always. + +2010-08-20 15:59:22 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds flash tags mapping + Adds a mapping for GST_TAG_CAPTURING_FLASH_FIRED/_MODE to + the exif Flash tag. + Tests included. + +2010-08-19 15:47:18 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + * win32/common/libgsttag.def: + tag: exif: More photography mappings + Adds mappings from: + GST_TAG_CAPTURING_EXPOSURE_PROGRAM -> ExposureProgram + GST_TAG_CAPTURING_EXPOSURE_MODE -> ExposureMode + GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE -> SceneCaptureType + GST_TAG_CAPTURING_GAIN_ADJUSTMENT -> GainControl + GST_TAG_CAPTURING_WHITE_BALANCE -> WhiteBalance + GST_TAG_CAPTURING_CONTRAST -> Constrast + GST_TAG_CAPTURING_SATURATION -> Saturation + Also renames gst_tag_image_orientation_from_exif_value and + gst_tag_image_orientation_to_exif_value to remove the 'gst' + prefix and not including in the win32 defs. + Tests included. + +2010-08-19 09:39:39 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Add macros for the exif ids + Use macros for exif ids to avoid having those numbers spread + all over the code. + +2010-08-17 15:56:34 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds photography tags mappings + Adds the following mappings for the exif helper: + * GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO -> DigitalZoomRatio + * GST_TAG_CAPTURING_FOCAL_LENGTH -> FocalLength + * GST_TAG_CAPTURING_SHUTTER_SPEED -> ExposureTime, ShutterSpeedValue + * GST_TAG_CAPTURING_FOCAL_RATIO -> FNumber, ApertureValue + * GST_TAG_CAPTURING_ISO_SPEED -> ISOSpeed, PhotographicSensitivity + Tests included. + +2010-08-17 15:05:32 -0300 Thiago Santos + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds mapping for GST_TAG_APPLICATION_DATA + Adds mapping for GST_TAG_APPLICATION_DATA to the exif + 'maker-note' tag. + +2010-08-20 14:54:23 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tag: Adds GST_TAG_CAPTURE_FLASH_FIRED/_MODE + Adds a new tag for informing if flash was used while + capturing an image and the flash mode selected by the + user during this capture + API: GST_TAG_CAPTURING_FLASH_FIRED + API: GST_TAG_CAPTURING_FLASH_MODE + https://bugzilla.gnome.org/show_bug.cgi?id=626651 + +2010-08-17 07:21:20 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tag: More photography related tags + API: GST_TAG_CAPTURING_EXPOSURE_PROGRAM + API: GST_TAG_CAPTURING_EXPOSURE_MODE + API: GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE + API: GST_TAG_CAPTURING_GAIN_ADJUSTMENT + API: GST_TAG_CAPTURING_WHITE_BALANCE + API: GST_TAG_CAPTURING_CONTRAST + API: GST_TAG_CAPTURING_SATURATION + Fixes #626651 + +2010-08-17 06:47:52 -0300 Thiago Santos + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + tag: Adds some basic photography tags + Adds the following basic photography tags. + API: GST_TAG_CAPTURING_SHUTTER_SPEED + API: GST_TAG_CAPTURING_FOCAL_RATIO + API: GST_TAG_CAPTURING_FOCAL_LENGTH + API: GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO + API: GST_TAG_CAPTURING_ISO_SPEED + Fixes #626651 + +2010-08-24 15:06:31 +0200 Sebastian Dröge + + * configure.ac: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + audioconvert: Require ORC 0.4.7 for the loadl/storel opcodes + And update disted files to allow compilation with no or too old ORC. + +2010-08-24 11:39:09 +0200 Alessandro Decina + + * gst/adder/gstadder.c: + adder: Make sure FLUSH_STOP is always sent after a flushing seek. + Send FLUSH_STOP right after forwarding the seek event upstream if necessary. + This makes sure that adder->srcpad is not left flushing if seeking fails or if + upstream is blocked. + The same fix was already applied to videomixer in 49b2a946. + +2010-08-24 11:11:49 +0200 Sebastian Dröge + + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/gstaudioconvertorc.orc: + audioconvert: Use ORC for the float<->int32 conversion + This should speed up standard Vorbis encoding and decoding pipelines a bit. + Thanks to David Schleef for the assistance to get the ORC code right + and explaining everything. + +2010-08-24 10:12:53 +0200 Sebastian Dröge + + * ext/pango/gsttextoverlay.c: + textoverlay: Support NV21 too and minor cleanups + +2010-08-24 10:03:04 +0200 Sebastian Dröge + + * gst-libs/gst/video/video.c: + video: Fix component width for NV12/NV21 + Both have width/2 as component width for the chroma planes. + +2010-08-24 09:51:46 +0200 Sebastian Dröge + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix NV21 rendering + Using the same as for NV12 will result in wrong colors and crashes. + +2010-08-23 18:51:18 -0400 Chris Shoemaker + + * ext/pango/gstclockoverlay.c: + * ext/pango/gstclockoverlay.h: + clockoverlay: only rerender text if time string has changed + The textoverlay element will rerender the text string whenever + overlay sets the 'need_render' flag to TRUE. Previously, we + lazily set the flag to TRUE every time the time string was requested. + Now, we save a copy of the previously given string, and only set + 'need_render' to TRUE if the string has changed. + In my tests with a 30fps video stream, and a time string including + a seconds field, this change reduced the CPU usage of the clockoverlay + element from 60% to 5%. + Fixes bug #627780. + +2010-08-23 13:59:38 -0500 Rob Clark + + * ext/pango/gsttextoverlay.c: + textoverlay: add NV12 support + Fixes bug #627768. + +2010-08-20 12:03:44 +0200 Sebastian Dröge + + * gst/videorate/gstvideorate.c: + videorate: Mark duplicated frames with the GAP flag + We currently don't use the GAP flag for video and the docs say + that this is for buffers, that have been created to fill a gap + and contains neutral data. For video this is the previous frame. + This information can be used by encoders to encode the duplicated + frames more efficiently. See bug #627459. + +2010-08-19 18:51:25 +0200 Sebastian Dröge + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Add back support for 8 bit paletted RGB + This was removed by 3a00a97fd2b4015e93cdcabaa75da406aa599570 + while making the pad template caps more compact. + Fixes bug #626629. + +2010-08-18 16:45:37 +0200 Wim Taymans + + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + alsasrc/sink: add property to get the card name + fixes #627203 + +2010-08-18 16:42:13 +0200 Wim Taymans + + * ext/alsa/gstalsa.c: + * ext/alsa/gstalsa.h: + alsa: add method to retrieve the card name + Reuse an existing method to retrieve the card name. + +2010-08-18 12:34:07 +0200 American Dynamics + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basertpdepay: don't clear the discont flag too early + Set the discont flag when we receive a DISCONT buffer and only clear the discont + state when we pushed out a DISCONT buffer. + Fixes #626869 + +2010-08-14 19:08:53 +0100 Tim-Philipp Müller + + * gst-libs/gst/app/gstappsink.c: + docs: fix typo in appsink docs so function gets cross-referenced properly + +2010-08-14 19:02:44 +0100 Tim-Philipp Müller + + * common: + * configure.ac: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + build: use new AG_GST_PKG_CONFIG_PATH m4 macro from common + Sets up a GST_PKG_CONFIG_PATH variable for use in Makefile.am + (avoids trailing ':' in PKG_CONFIG_PATH used). + +2010-08-14 18:36:55 +0100 Tim-Philipp Müller + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introspection: set PKG_CONFIG_PATH so that our in-tree libs come first when calling scanner + When calling gobject-introspection scanner, make sure our own + freshly-built libs within the source tree (well, build dir) come + first in the PKG_CONFIG_PATH. May or may not help to make sure + that it doesn't pick up older external plugins-base libs (or + .gir files) from outside the source tree / build directory as + dependencies of the introspected lib instead of using the + stuff we just built in a sibling directory. + https://bugzilla.gnome.org/show_bug.cgi?id=623698 + +2010-08-06 17:16:27 +0200 Edward Hervey + + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playback: Delay usage of GstFactoryList + By delaying it to when it's actually needed, we speed things up a bit + since some elements might have been added/removed in between. + https://bugzilla.gnome.org/show_bug.cgi?id=626718 + +2010-06-17 09:10:11 +0200 Robert Swain + + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playbin2: uridecodebin: add property to configure ring buffer size + +2010-08-13 17:23:46 +0300 Stefan Kost + + * common: + Automatic update of common submodule + From 3e8db1d to ec60217 + +2010-08-13 13:59:08 +0300 Stefan Kost + + * docs/plugins/gst-plugins-base-plugins-sections.txt: + plugin-docs: the tag should come right after <FILE>. + Fixes missing plugin entries. If the object name, e.g. GstGIOSrc came before the + title, we ended up with differnt section_id in the generated docbook. + +2010-08-12 18:14:38 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: fix the classification. + Change "Src" into "Source" (we use that elsewhere). I did not keept "Src" as it + is quite unlikely that someone plugs appsrc by searching the registry by classification. + +2010-08-12 15:26:08 +0300 Stefan Kost <ensonic@users.sf.net> + + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + alsa: remove 'dir' out variable + Alsa seems to expect that we initialize it. Remove the variable and pass NULL + as we actually don't use it. In alsasink also #ifdef one section that is + grabing diagnostics to be disabled, when logging is disabled (the code was + using the out parameter as well). + Fixes #626125 + +2010-08-12 11:46:11 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: remove chroma-site and color-matrix fields from RGB caps + +2010-08-11 12:49:40 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: prevent deadlock with _chain when deactivating pad + Fixes #626581. + +2010-08-12 12:50:27 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/Makefile.am: + playback: bad bad editor, readd missing line to fix the build + +2010-08-12 12:08:35 +0300 Stefan Kost <ensonic@users.sf.net> + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/playback/.gitignore: + * tests/examples/playback/Makefile.am: + * tests/examples/playback/decodetest.c: + * tests/examples/playback/test.c: + * tests/examples/playback/test2.c: + * tests/examples/playback/test3.c: + * tests/examples/playback/test4.c: + * tests/examples/playback/test5.c: + * tests/examples/playback/test6.c: + * tests/examples/playback/test7.c: + * tests/icles/Makefile.am: + * tests/icles/playback/.gitignore: + * tests/icles/playback/Makefile.am: + * tests/icles/playback/decodetest.c: + * tests/icles/playback/test.c: + * tests/icles/playback/test2.c: + * tests/icles/playback/test3.c: + * tests/icles/playback/test4.c: + * tests/icles/playback/test5.c: + * tests/icles/playback/test6.c: + * tests/icles/playback/test7.c: + tests/playback: due to popular demand mv them from examples to icles + The tests are toys and not reference demos. + +2010-08-12 10:02:56 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: send preroll buffer when delaying preroll eos + That is, if eos is received which will not be forwarded, and the stream + has not yet seen any data, then send a buffer to preroll downstream + (which might otherwise be accomplished by the eos event). + +2010-08-12 10:01:03 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: remove some heuristic in chain configuration code + .. since queues are now inserted unconditionally. + +2010-08-11 10:27:35 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + playbin2/playsink: update subtitle handling for streamsynchronizer + Streamsynchronizer excepts to see stream-changed msg for all streams, but to + arrange for this, video and subtitle streams need to be decoupled by means + of queues (due to pad blocks that may occur). + Fixes #626463. + +2010-08-10 13:06:32 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: always have a queue in chain head to aid streamsynchronizer + Specifically, as the latter may have one thread pushing EOS to several streams, + that needs to be decoupled into various thread to prevent preroll hanging + problems. + +2010-08-10 11:28:43 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: drop lock when pushing eos downstream + ... to prevent deadlock (e.g. upon seek) when downstream waits in preroll. + +2010-08-10 11:19:59 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: clear stream eos state on FLUSH and new stream + +2010-08-10 11:19:22 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: set READY sinks to NULL before freeing chain upon failure + +2010-08-12 10:49:59 +0300 Stefan Kost <ensonic@users.sf.net> + + * configure.ac: + * gst/playback/.gitignore: + * gst/playback/Makefile.am: + * gst/playback/decodetest.c: + * gst/playback/test.c: + * gst/playback/test2.c: + * gst/playback/test3.c: + * gst/playback/test4.c: + * gst/playback/test5.c: + * gst/playback/test6.c: + * gst/playback/test7.c: + * tests/examples/Makefile.am: + * tests/examples/playback/.gitignore: + * tests/examples/playback/Makefile.am: + * tests/examples/playback/decodetest.c: + * tests/examples/playback/test.c: + * tests/examples/playback/test2.c: + * tests/examples/playback/test3.c: + * tests/examples/playback/test4.c: + * tests/examples/playback/test5.c: + * tests/examples/playback/test6.c: + * tests/examples/playback/test7.c: + playback: move tests from plugin-dir to tests/examples/playback + +2010-08-11 18:08:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * sys/xvimage/xvimagesink.c: + xvimagesink: Suggest caps with different width/height if bufferalloc is called with impossible width/height + +2010-08-11 17:16:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: Add some debug output to the videoscale negotiation test + +2010-08-11 17:03:11 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Only set the PAR if the caps already had a PAR + Otherwise we're producing different caps and basetransform thinks that it + can't passthrough buffer allocations, etc. + In 0.11 all video caps really should have the PAR set... + +2010-08-11 17:00:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * sys/xvimage/xvimagesink.c: + xvimagesink: It's not a bad thing if the preferred video format needs less bytes per frame + +2010-08-11 08:47:57 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tags: exif: Fix bug in inner ifd parsing + Do not use the result of inner ifd's parsing to increment + the current tag index. The reasons are: + 1) The function returns a boolean. + 2) The inner ifd's tags are in a separate table, so they shouldn't + interfere with its parent ifd table parsing. + +2010-08-11 08:03:44 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Put ExifVersion in the correct IFD + ExifVersion is from the 'exif' ifd, not the 0th ifd. + +2010-08-10 19:50:42 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Refactor functions declaration + Use some macros to declare serialization/deserialization + functions prototypes. + +2010-08-10 19:30:11 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Add another DateTime mapping + datetimes can also be represented by the 0x132 tag. Map it, too. + +2010-08-10 11:29:22 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Fix bug on image-orientation parsing + Do not skip one extra tag when parsing image-orientation tags. + +2010-08-10 10:57:17 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From bd2054b to 3e8db1d + +2010-08-10 11:52:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + exiftag: Compare with G_MAXUINT16 instead of -1 + Fixes a compiler warning on the OS X buildbot. + +2010-08-09 18:04:08 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + xmp: exif: Adds GST_TAG_APPLICATION_NAME mappings + adds xmp and exif helper library mappings for GST_TAG_APPLICATION_NAME + tag. + +2010-08-04 13:01:21 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Write ExifVersion tag + Write ExifVersion tag unconditionally when creating exif + buffers. Might help other applications parsing of this data. + +2010-08-04 13:02:52 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/libs/tag.c: + tests: tag: Test to try to serialize multiple exif tags + Adds a new test for exif data that tries serializing data + from multiple ifd tables and check if it works. + +2010-08-09 17:25:07 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tags: exif: Fix inner tags offset rewriting + Fixes a bug that made exif helper lib fail to rewrite inner ifd tags + offsets when there were more than 1 inner ifd. + +2010-07-22 17:29:57 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: configurable text color and position + Rather than only left, right, top, etc, allow for horizontal and vertical + positioning on a scale from 0 to 1. + Also cater for configuring rendered text color. + Fixes #624920. + API: GstTextOverlay:xpos + API: GstTextOverlay:ypos + API: GstTextOverlay:color + +2010-07-21 14:20:03 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: add solid-color pattern + ... which generalizes the current listing of white, black, etc. + In particular, also allow specifying alpha channel, and modify + some structures and pattern filling to cater for alpha value as well. + Fixes #624919. + API: GstVideoTestSrc:solid-color + +2010-08-08 17:42:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: static forward declarations are forbidden by the C standard + ...and actually cause compiler errors on VC++. Change it to an extern + forward declaration and non-static definition. + +2010-08-05 13:56:29 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From 2004d03 to bd2054b + +2010-08-04 19:24:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + configure: Check if the compiler supports ISO C89 or C99 and which parameters are required + This first checks what is required for ISO C99 support and sets the relevant + compiler parameters and if no C99 compiler is found, it checks for a + C89 compiler. This enables us to check for and use C89/C99 functions + that gcc hides from us without the correct compiler parameters. + +2010-08-04 15:18:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosink/baseaudiosrc: Post CLOCK-LOST/CLOCK-PROVIDE when going to/from READY + Otherwise the clocks are redistributed every time the pipeline + goes to PAUSED, which is quite expensive. + +2010-08-03 15:03:27 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Make xmp lib aware for the different tag types + Makes the xmp helper lib aware that the tags can be simple, + sequences or bags (there is still struct and alt, but those + aren't handled yet). Adding this info makes serialization + and deserialization more consistent. + +2010-08-02 09:56:21 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + xmp: Add a new layer of indirection (GstXmpSchema) + Instead of storing all tags in a single hashtable, store them + grouped by schema in a GstXmpSchema, and add those to the toplevel + hashtable. + +2010-08-03 14:37:05 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Make bag tags deserialization work correctly + If we find a bag of tags of type string in the xmp packet, we + should concat them, this is not the ideal approach, but at + least works for now as we don't know what type of tag it + is (simple, structure, seq, alt or bag) + +2010-08-04 21:44:22 +1000 Jan Schmidt <thaytan@noraisin.net> + + * tests/examples/seek/seek.c: + examples/seek: Don't unpause on clock-lost unless playing + If the pipeline is paused by the user, don't pause/unpause + on clock-lost. + +2010-07-02 12:10:16 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: improve debugging + +2010-07-02 12:09:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.h: + ringbuffer: whitespace fixes + +2010-06-28 10:53:57 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: use more efficient way of getting caps + When inspecting the caps of a pad, try to get the pad _CAPS first before calling + the getcaps function. + +2010-08-02 11:06:00 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/pipelines/oggmux.c: + oggmux: Fix test build when theora and vorbis aren't available + Ifdef properly to avoid build failures + +2010-08-01 06:50:13 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Detect avc1 ftyp as video/quicktime + Detects avc1 ftyp as video/quicktime (iso variant) + +2010-07-27 11:25:12 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: removing useless locking + Everything in the xmp helper lib is initiallized once and on a thread + safe way, and after that there are only reads going on, no more + writing. Based on that, drop the locking. + +2010-06-20 23:53:38 +1000 Jan Schmidt <thaytan@noraisin.net> + + * tests/examples/seek/jsseek.c: + jsseek: Set joystick io encoding to 'NULL' + Fix problems with newer glib reporting bad encodings on the binary + data emerging from the joystick device fd. + +2010-07-26 20:25:55 +0200 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: fix printf format compiler warnings + Make OSX build bot happy. + +2010-07-26 18:23:33 +0200 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: initialize datetime variable in xmp tag parsing code + Fixes (correct) compiler warning on the OSX build bot. + +2010-07-26 17:48:14 +0200 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: require core from git + For GstDateTime stuff used in libgsttag. + +2010-07-26 17:04:02 +0200 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + * configure.ac: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/gstpluginsbaseversion.c: + * gst-libs/gst/pbutils/gstpluginsbaseversion.h.in: + * gst-libs/gst/pbutils/pbutils.h: + * tests/check/libs/pbutils.c: + * win32/common/libgstpbutils.def: + pbutils: add compile time and runtime version checks for gst-plugins-base + So people can check what version of the gst-plugins-base libs they're + building against or linked against. + API: GST_PLUGINS_BASE_VERSION_MAJOR + API: GST_PLUGINS_BASE_VERSION_MINOR + API: GST_PLUGINS_BASE_VERSION_MICRO + API: GST_PLUGINS_BASE_VERSION_NANO + API: GST_CHECK_PLUGINS_BASE_VERSION + API: gst_plugins_base_version() + API: gst_plugins_base_version_string() + +2010-06-30 16:36:14 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Map GST_TAG_DATE_TIME + Adds mapping to the exif helper library for GST_TAG_DATE_TIME. + Tests included. + https://bugzilla.gnome.org/show_bug.cgi?id=594504 + +2010-06-23 12:02:24 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Maps GST_TAG_DATE_TIME + Adds mapping for GST_TAG_DATE_TIME. + Tests included. + https://bugzilla.gnome.org/show_bug.cgi?id=594504 + +2010-07-26 16:05:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: Fixate the pixel-aspect-ratio if necessary + +2010-07-24 18:17:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: Delay EOS events until all streams are EOS + This fixes a race condition in playbin2's gapless mode, where the + EOS of other streams might arrive in the sinks before the last stream + ends and the switch to the new track happens. The EOS sinks won't + accept any new data then and playback stops. + To prevent this, delay all EOS events until all streams are EOS + and advance the sinks of the EOS streams by filler newsegment + events if necessary. + Fixes bug #625118. + +2010-06-01 23:43:45 +0530 Arun Raghavan <arun.raghavan@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: export 3gp profile in caps + This reads the 3gp profile from the major/compatible brands and puts + this as a 'profile' field in caps. This can be used by demuxers to + decide whether they can handle this stream or not. Also needed for + DLNA. + https://bugzilla.gnome.org/show_bug.cgi?id=620291 + +2010-07-24 11:48:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + * tests/icles/test-colorkey.c: + * tests/icles/test-xoverlay.c: + examples: Use cairo instead of to-be-deprecated GDK API + Fixes bug #625001. + +2010-07-24 09:22:28 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + * configure.ac: + configure: set release date/time + Use the new AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO macro. + +2010-07-20 12:08:52 +0530 Parthasarathi Susarla <partha.susarla@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: detect enhanced AC-3 + https://bugzilla.gnome.org/show_bug.cgi?id=623846 + +2010-07-22 09:13:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + * gst/playback/gststreamsynchronizer.h: + streamsynchronizer: Fix another deadlock when going PAUSED->READY while streams are waiting for the GCond + +2010-07-20 21:05:45 +0200 Edward Hervey <bilboed@bilboed.com> + + playsink: Switch to faster pad linking methods + Logic for choice of GST_PAD_LINK_CHECK_* is as follows: + * Where return of pad_link wasn't checked before : NOTHING + * Where linking is between known compatible elements : NOTHING + * All other cases : TEMPLATE_CAPS + Slashes down playsink reconfigure by up to 50% cpu time. + +2010-07-19 15:58:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * gst/playback/gstscreenshot.c: + playsink: Set add-borders=true on the videoscale instances + This makes sure that we always keep the display aspect ratio and + add black borders if necessary, which is usually something you want + for viewing a video. + +2010-07-19 15:44:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Rename borders property to add-borders + +2010-07-19 09:39:28 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + videoscale: update disted orc files for latest changes + +2010-07-17 20:24:18 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/Makefile.am: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videoscale/vs_fill_borders.c: + * gst/videoscale/vs_fill_borders.h: + * gst/videoscale/vs_image.h: + videoscale: Add support for adding black borders to keep the DAR if necessary + Fixes bug #617506. + +2010-07-18 15:08:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_scanline.c: + videoscale: Fix linear scaling of UYVY scanlines + Fixes bug #624656. + +2010-07-17 19:57:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Fix caps fixating if the height is fixed but the width isn't + +2010-07-16 20:41:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + videoscale: Remove interlaced scaling again + This behaviour was not preferred and caused visible image quality + degradations. The real solution would be, to apply a real + deinterlacing filter before scaling the frames. + Fixes bug #615471. + +2010-07-16 19:06:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Add helper method for filling the VSImage struct + +2010-07-18 11:43:00 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/files/Makefile.am: + tests: don't forget to dist test file for typefinding unit test + +2010-07-18 11:38:19 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/gst/typefindfunctions.c: + * tests/files/623663.mts: + tests: add unit test for mpeg-ts typefinding bug + See #623663. + +2010-07-18 11:24:46 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: make mpeg-ts typefinder scan more data + We only look for packets with payload, but it appears there may be packets without, + which makes it harder to find the N packets with payload in a row that we need in + order to typefind this successfully, so scan some more data than necessary in the + optimistic scenario. Alternatively we could change IS_MPEGTS_HEADER(). + Fixes #623663. + +2010-07-16 18:51:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * gst/playback/gststreamsynchronizer.c: + playsink/streamsynchronizer: Remove and deactivate pads after calling the change_state function of the parent class + Fixes some deadlocks. + +2010-07-16 18:25:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gststreamsynchronizer.c: + streamsynchronizer: Drop DISCONT flag on first buffer for new streams + Also reset stream state when going back to READY and on flush-stop. + +2010-07-11 14:44:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/Makefile.am: + * gst/playback/gstplaysink.c: + * gst/playback/gststreamsynchronizer.c: + * gst/playback/gststreamsynchronizer.h: + * gst/playback/test7.c: + playsink: Fix gapless playback in many non-simple scenarios + Before gapless playback failed when switching between audio-only, + video-only and audio-video files, when choosing different clocks + and when the different streams had different durations. + This is now handled by a helper element, which keeps track of the + running times of all streams and synchronizes them. + Fixes bug #602437. + +2010-07-11 14:43:52 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Remove QOS event adjustments for gapless playback mode + +2010-07-09 17:15:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: Post clock-provide and clock-lost messages when going from/to PLAYING + +2010-07-09 17:15:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: Post clock-provide and clock-lost messages when going from/to PLAYING + +2010-07-08 16:11:12 +0200 Philip Jägenstedt <philipj@opera.com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: only associate .webm with WebM + .weba (audio) and .webv (video) were speculation on my part before + the public launch. As of yet no decision has been made on the + file extension for audio-only WebM, and I'm pretty sure there will + never be one for video-only. + Fixes bug #623837. + +2010-07-08 09:54:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: Use new gst_audio_clock_new_full() + +2010-07-08 09:54:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: Use new gst_audio_clock_new_full() + +2010-07-08 08:32:22 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstaudioclock.h: + * win32/common/libgstaudio.def: + audioclock: API: Add gst_audio_clock_new_full() with a GDestroyNotify for the user_data + Elements usually use their own instance as instance data but the + clock can have a longer lifetime than their elements and the clock + doesn't own a reference of the element. + Fixes bug #623807. + +2010-07-04 20:29:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/Makefile.am: + * ext/theora/gsttheoraenc.c: + * ext/theora/gsttheoraenc.h: + theoraenc: Implement two pass encoding + Fixes bug #621349. + +2010-07-04 20:14:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * ext/theora/gsttheoraenc.c: + configure: Require libtheora >= 1.1 + It's more than a year old at the time of the next -base release, + has many encoder and decoder improvements and gets us rid of a lot + of #ifdefs + +2010-07-04 20:08:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/gsttheoradec.c: + * ext/theora/gsttheoraenc.c: + theora: Use PROP_ instead of ARG_ for property enum values + +2010-05-04 12:09:57 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: use proper error message code for failing state change + +2010-07-16 11:24:21 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + Back to development + +=== release 0.10.30 === + +2010-07-15 01:20:54 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.30 + +2010-07-15 00:32:09 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/cs.po: + * po/lv.po: + po: update translations + +2010-07-14 12:59:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Disconnect and destroy uridecodebins when going from READY to NULL + Fixes spurious errors that happen after an error and playing a working + stream afterwards or signals that are emitted for non-active groups. + Fixes bug #624266. + +2010-07-08 14:51:08 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/design/Makefile.am: + docs: dist more of the gst-plugin-base design docs + +2010-07-07 00:35:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.29.4 pre-release + +2010-07-07 00:24:42 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/LINGUAS: + * po/es.po: + * po/fr.po: + * po/it.po: + * po/nl.po: + * po/pt_BR.po: + * po/sl.po: + * po/sv.po: + po: update translations + +2010-07-06 09:47:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + Revert "playbin2: Don't put "raw" subtitle types in the raw caps for decodebin2" + This reverts commit 9d7538247ff1bf9841b53eeb71ddc47f2c662415. + If the DVD subpicture caps are not part of the raw caps, uridecodebin + doesn't qualify resindvdbin as raw source and plugs decodebins, which + causes broken DVD playback because of bugs elsewhere. + This change was originally added to only expose supported, raw subtitles, + e.g. if the subtitle sink did not support DVD subpictures but a converter + to some supported format exists. It's not very important right now because + we have nothing (that is autoplugged) to convert from plaintext/pango-markup + or DVD subpictures to something else. + Fixes bug #623583. + +2010-07-04 17:27:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Use correct Y offset for YVYU -> RGB conversions + Fixes bug #623530. + +2010-07-04 17:26:03 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Use correct Y offset for the YUY2 -> RGB conversions + Fixes bug #623530. + +2010-07-04 14:55:50 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/plugins/inspect/plugin-ogg.xml: + docs: update ogg introspection info after riff fourcc addition + +2010-07-02 20:09:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix conversion of packed 4:2:2 YUV to 8 bit grayscale + The last pixel wasn't written before for odd widths. + Fixes bug #623418. + +2010-07-02 14:56:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Fix conversion of packed 4:2:2 YUV to RGB + The last pixel wasn't written before. + Fixes bug #623384. + +2010-07-02 13:59:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix invalid memory accesses with odd widths/heights during subsampling + Fixes bug #623375. + +2010-07-01 21:21:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: If setup of the source element fails in READY->PAUSED deactive the current group + Otherwise the uridecodebin will be still a child of playbin2 and + its signals will still be connected. In future state changes this + will then emit unrelated signals that will confuse playbin2 or, + even worse, cause crashes and assertions. + Fixes bug #623318. + +2010-06-30 21:20:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: add FLV4 fourcc and map it to video/x-vp6-flash + Fixes #623176. + +2010-06-30 15:13:10 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/netbuffer/gstnetbuffer.c: + netbuffer: declare with G_DEFINE_TYPE for type safety + Fixes #623233. + +2010-06-24 16:55:57 +0200 Fredrik Söderquist <fs@opera.com> + + * ext/ogg/gstoggdemux.c: + oggdemux: Handle errors from _get_next_page in _do_seek. + If the source element failed here, oggdemux would crash. + Fixes #623218. + +2010-06-30 11:00:45 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: keep things sorted alphabetically + On special request. Because it's important, apparently. + +2010-06-29 18:48:15 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.29.3 pre-release + +2010-06-29 18:46:18 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: fix --disable-external + +2010-06-28 15:43:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * autogen.sh: + * configure.ac: + Bump automake requirement to 1.10 + For maintainability reasons and $(builddir). + Fixes #622944. + +2010-06-27 10:43:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/jsseek.c: + * tests/examples/seek/seek.c: + examples: Remove some #if GTK_CHECK_VERSION(2,12,0) + We depend on GTK+ >= 2.14 already. + +2010-06-26 21:28:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/Makefile.am: + videotestsrc: Explicitely link with $(LIBM) + +2010-06-26 21:27:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/Makefile.am: + videoscale: Explicitely link with $(LIBM) + +2010-06-26 18:19:56 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/video-enumtypes.c: + 0.10.29.2 pre-release + +2010-06-26 18:19:33 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/adder/gstadderorc-dist.c: + * gst/adder/gstadderorc-dist.h: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.h: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + gst: update orc files + +2010-06-26 18:19:16 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2010-06-26 17:55:12 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Properly clean DecodeChain after errors. + If an error happens, the PAUSED state will never be reached. If an + application re-uses decodebin2 (like totem) where one would normally + set to READY between each file, the cleanup that normally happens in + the PAUSED=>READY codepath will never be called, resulting in the + following file to re-use the previous demuxer/decoder/... + https://bugzilla.gnome.org/show_bug.cgi?id=622807 + +2010-06-26 12:39:34 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/design/design-orc-integration.txt: + docs: fix a few typos + +2010-06-26 12:03:54 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/videoscale.c: + checks: simplify GstBus usage in videoscale unit test + There's no need to run a main loop, add a bus watch and deal with + helper structs here just to wait for an EOS message. + +2010-06-26 11:38:56 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/videoscale.c: + checks: speed up videoscale unit test a little + Use new gst_element_link_pads_full() function to link elements, + and disable all checks when linking (don't try this at home). + Down to 18s from 3m20s. Scary. + +2010-06-25 17:18:34 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: check for ringbuffer state first + Check for the state of the ringbuffer before doing the checks of the other + buffer properties, when we're not started, we don't care about those values. + +2010-06-24 13:30:59 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Use a more concise pad template + Speeds up caps nego 2 fold + https://bugzilla.gnome.org/show_bug.cgi?id=622696 + +2010-06-24 15:31:31 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/icles/audio-trickplay.c: + tests: make audio-trickplay test compile when the gst debugging system is disabled + Fixes unused variable warning in that case. + +2010-06-24 15:13:31 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/gst/typefindfunctions.c: + tests: add test that runs all typefinders over random data + +2010-06-06 12:31:35 +0530 Arun Raghavan <arun.raghavan@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: Mark ISO 14496-14 files as video/quicktime + These are currently being marked as audio/x-m4a which is incorrect. + https://bugzilla.gnome.org/show_bug.cgi?id=620720 + +2010-06-24 13:42:20 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + .gitignore: add temporary orc test directory + +2010-06-24 13:30:50 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/Makefile.am: + tests: add plugin loading whitelist to test environment + Only want to load core/-base plugins here. + +2010-06-24 15:09:04 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From 73ff93a to a519571 + +2010-06-24 08:41:42 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gsttageditingprivate.c: + tag: Fix printf format string + Use %s for strings, not %d. + +2010-06-24 12:06:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_scanline.c: + videoscale: Fix resampling of ARGB scanlines + Previously we would read behind the end of the source lines. + +2010-06-16 14:08:05 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds GST_TAG_IMAGE_ORIENTATION mapping + Adds GST_TAG_IMAGE_ORIENTATION mapping to xmp helper lib. + Tests included. + +2010-06-16 11:19:37 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/gsttageditingprivate.c: + * gst-libs/gst/tag/gsttageditingprivate.h: + * tests/check/libs/tag.c: + * win32/common/libgsttag.def: + tag: exif: Adds mapping for GST_TAG_IMAGE_ORIENTATION + Adds GST_TAG_IMAGE_ORIENTATION to the exif helper lib mapped tags. + Tests included. + +2010-06-23 12:10:32 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: clear ts-offset pointer + We need to clear the pointer to our ts-offset element when we destroy the video + chain elements to make sure nobody derefs it to invalid memory afterwards. + +2010-06-23 10:16:07 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaysink.c: + playsink: Reset ts_offset field when freeing chain + Otherwise we would end up with a bogus ->audiochain->ts_offset field + which would cause segfaults/assertions when trying to modify the + 'ts-offset' property in update_av_offset(). + Was easy to trigger when using a list of audio+video files mixed with + video-only files in totem. + +2010-06-18 16:37:14 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/check/elements/adder.c: + * tests/check/elements/appsink.c: + * tests/check/elements/audiotestsrc.c: + * tests/check/elements/gdpdepay.c: + * tests/check/elements/gdppay.c: + * tests/check/elements/multifdsink.c: + * tests/check/elements/videotestsrc.c: + * tests/check/elements/vorbisdec.c: + tests: use our own macros for the tests main function + +2010-06-18 14:17:30 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstvorbistag.c: + tag: Use gst_tag_list_peek_string_index in vorbistag + Use _peek_string_index instead of _get_string_index to avoid + a string copy + +2010-06-14 12:27:02 +0200 Philippe Normand <pnormand@igalia.com> + + * sys/ximage/ximagesink.c: + * sys/ximage/ximagesink.h: + ximagesink: Ask pad peer to accept new caps once only + In buffer_alloc, if the buffer caps are new, call + gst_pad_peer_accept_caps once only, it's useless to call it in the + cases where we know it will always fail. + Fixes bug #621190 + +2010-06-17 17:07:39 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add YUY2/YVYU to all RGB formats conversions + +2010-06-17 16:57:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix Y42B to YUY2/YVYU/UYVY conversion for odd widths + +2010-06-17 16:54:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix YUY2/YVYU/UYVY to Y42B conversion for odd widths + +2010-06-17 16:06:53 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + docs: update introspected plugin docs for gstdoc-scangobj and other changes + Update common for latest gstdoc-scangobj and inspect xml files for + escaping and pad template order changes. Update other gtk-doc files + for API additions and object hierarchy changes. + +2010-06-16 19:15:20 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: improve autoplugging + Use the pad caps when they are available to continue the autoplugging. If the + pad caps are set, they are fixed and then we can directly continue autoplugging. + +2010-06-15 16:49:17 +0200 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From 9339ccc to 35617c2 + +2010-06-15 16:53:49 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From 5adb1ca to 9339ccc + +2010-06-15 16:34:54 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From 57c89b7 to 5adb1ca + +2010-06-15 15:32:34 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From c804988 to 57c89b7 + +2010-06-15 13:09:37 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/check/elements/audioresample.c: + Revert "audioresample: set pads as negotiable" + This reverts commit 5f74f3a82eb54f9a9517f99dffbe45ce4d474870. + +2010-06-15 13:09:29 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/check/elements/audioconvert.c: + Revert "audioconvert: set pads negotiable" + This reverts commit bbd7dee8f604bd0373a82e6e5cc3eec8313806ac. + +2010-06-14 15:19:32 -0700 David Schleef <ds@schleef.org> + + * gst/videoscale/vs_scanline.c: + videoscale: Fix black horizontal line in image + +2010-06-14 15:05:16 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Init char variable for gps coordinates + Initialize char variable for gps coordinates deserialization to 0 + to identify when it couldn't be parsed/found and error out. + Fixes #621509 + +2010-06-14 18:10:52 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/check/elements/audioconvert.c: + audioconvert: set pads negotiable + +2010-06-14 17:48:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/check/elements/audioresample.c: + audioresample: set pads as negotiable + +2010-06-14 16:25:46 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Revert accidental downgrade of common revision. + +2010-06-14 16:07:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: And only expect a single buffer in the unit test + +2010-06-14 16:02:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: Only convert one buffer instead of five + Should make the unit test a lot faster. + +2010-06-14 14:13:32 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Fix unitialized variables + yay macosx compilers :( + +2010-06-14 14:13:16 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/video/video.c: + video: Fix unitialized variable. + yay macosx compilers :( + +2010-06-14 13:27:01 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Use Quarks for structure name/field checking + +2010-06-14 13:26:02 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Speed up _remove_format_info + Instead of copying full caps, use the fact that the provided caps only have + one structure and only copy around structures. + +2010-06-14 13:24:06 +0200 Edward Hervey <bilboed@bilboed.com> + + * common: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Transfer structures instead of copying them + Avoids many expensive structure copies + +2010-06-14 13:20:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + configure: Use GLIB_EXTRA_CFLAGS + +2010-06-14 13:02:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 7a0fdf5 to c804988 + +2010-06-14 11:31:09 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 6da3bab to 7a0fdf5 + +2010-06-14 11:20:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/jsseek.c: + jsseek: Don't use deprecated GLib API + Fixes once again bug #605100. + +2010-06-14 11:16:45 +0200 Prahal <prahal at yahoo.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: use accumulator for autoplug-sort + Use an accumulator for the autoplug-sort signal so that we can stop the emission + when a signal handler produced a valid result. This avoids the object handler + to overwrite the results from user signals. + Fixes #621161 + +2010-06-14 11:11:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: activate_chain must not be called with a NULL chain + It will crash later and shouldn't really happen anyway unless + something is really wrong. + +2010-06-14 11:08:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gnomevfs/gstgnomevfssrc.c: + gnomevfssrc: Fix possible NULL pointer dereference + It's always an error if gst_buffer_try_new_and_alloc() returns NULL + +2010-06-14 11:03:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Return FALSE from the seek handler if no seek callback was set + +2010-06-14 09:53:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiostreamsrc.c: + giostreamsrc: Fix copy&paste error in the docs + +2010-06-14 00:33:04 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: fix debug message printf format some more + Just cast the pointer diff, so it works everywhere without + warnings. Can't use %tu, because that modifier is C99. Warning + was: "format '%li' expects type 'long int', but argument 8 has + type 'int'". + +2010-06-13 22:17:18 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: Add ffmpegcolorspace after videotestsrc for the unit test + +2010-06-13 20:57:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: ...and add Y16 case for the linear scaling + +2010-06-13 20:38:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Add Y16 case for 4-tap scaling + +2010-06-13 18:27:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/Makefile.am: + tests: Fix linking of the tags test + +2010-06-13 08:20:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.h: + video: Re-add (but deprecated) GST_VIDEO_{RED,GREEN,BLUE}_MASK_1[56] + +2010-06-12 21:04:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Use correct variables for debug output + +2010-06-12 16:51:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix Y16 from/to GRAY8 conversion + +2010-06-12 16:31:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Don't crash when doing gray YUV to GRAY conversion + +2010-06-12 16:23:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + videoscale: Update disted orc files + +2010-06-12 16:16:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Allow video/webm for progressive downloading + +2010-06-12 13:59:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Add support for more gray formats + +2010-06-01 16:45:34 +0000 Martin Bisson <martin.bisson@gmail.com> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video.{c,h}: Fix an endianness bug fix. + This commit makes sure the endianness is ok for RGB/BGR 15/16 formats. + +2010-06-01 14:42:54 +0000 Martin Bisson <martin.bisson@gmail.com> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video.{c,h}: Add support for RGB and BGR with 15 and 16 bits. + +2010-06-12 13:35:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + videoscale: Use libgstvideo for caps parsing, etc + +2010-06-12 13:04:43 +0200 Philippe Normand <phil@base-art.net> + + * ext/ogg/gstoggstream.c: + oggdemux: Fix format string compiler warning on OS X + +2010-06-12 13:00:26 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Use GST_VIDEO_CAPS_GRAY{8,16} + +2010-06-12 12:57:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videoscale/vs_scanline.c: + videoscale: Implement linear merging of Y16 scanlines with orc + +2010-06-12 08:26:27 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 733fca9 to 6da3bab + +2010-06-11 22:16:26 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * ext/cdparanoia/Makefile.am: + cdparanoia: check for cdparanoia with pkg-config first + cdparanoia now has a .pc file in post-0.10.2 SVN, so use + that to check for cdparanoia before we try all the other + checks. Besides being generally nicer, this may help with + correctly detecting cdparanoia on OSX some day (see #609918). + +2010-06-11 12:34:24 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: look for dts frames at non-zero offsets too + Scan a bit into the data when checking for dts frames instead + of expecting the frame sync to be right at the start of the + data. This is needed for some dts-disguised-as-pcm-in-wav files. + See #413942. + +2010-06-10 18:12:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: add typefinder for dts audio + +2010-06-11 15:23:14 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/tag/gstexiftag.c: + gstexiftag: Fix unitialized variables + I hate thee macosx + +2010-06-11 08:47:27 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/tag/gstexiftag.c: + gstexiftag: Fix debug statements + +2010-06-11 08:47:17 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/tag/gstexiftag.c: + exiftag: Fix unitialized variable + +2010-06-10 20:45:42 +0300 Stefan Kost <ensonic@users.sf.net> + + * win32/common/libgsttag.def: + win32: update def file + +2010-06-10 20:36:32 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/tag/tag.h: + docs: fix gtk-doc warnings + Variable names in function prototypes in the headers should match the doc- + comment. + +2010-06-10 08:47:17 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: If the text-sink claims to support ANY caps assume it only support raw plaintext subtitles + Fixes bug #621071. + +2010-06-10 08:46:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/icles/playbin-text.c: + icles: Only accept plain subtitles in the playbin-text icles test + +2010-06-09 22:34:24 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add support for VP6F (On2 VP6 Flash variant) + +2010-06-09 12:35:40 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + Use the Orc m4 macro + +2010-06-09 12:40:00 -0700 David Schleef <ds@schleef.org> + + * common: + Automatic update of common submodule + From fad145b to 733fca9 + +2010-06-09 12:33:51 -0700 David Schleef <ds@schleef.org> + + * common: + Automatic update of common submodule + From 47683c1 to fad145b + +2010-06-09 15:58:32 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + tag: exif: Refactor byte-order handling + Only check for valid byte-order values when creating the + exif readers and writers + +2010-05-10 14:01:46 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstexiftag.c: + * tests/check/libs/tag.c: + tag: exif: Adds new geo-location tag mappings + Adds mappings for: + GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION + GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION + GST_TAG_GEO_LOCATION_MOVEMENT_SPEED + GST_TAG_GEO_LOCATION_ELEVATION + Does some refactoring in the code to reduce number of parameters + passed to functions + Tests included. + +2010-04-04 22:25:24 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/libs/tag.c: + tests: tag: Adds unit tests for exif helper lib + Adds some simple unit tests for exif helper lib functions + Fixes #614872 + +2010-04-03 23:02:57 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gstexiftag.c: + * gst-libs/gst/tag/tag.h: + * win32/common/libgsttag.def: + tag: Adds basic exif tags support + Adds exif helper lib functions to parse exif buffers from/to + taglists. Exif is tipically used in jpeg images, but it can + also be embedded into TIFF, AVI and WAV formats. + Adds a couple function to handle exif in tiff header structures, that is how + exif is embedded in jpeg and (obviously) in tiff. + API: gst_tag_list_to_exif_buffer + API: gst_tag_list_to_exif_buffer_with_tiff_header + API: gst_tag_list_from_exif_buffer + API: gst_tag_list_from_exif_buffer_with_tiff_header + Fixes #614872 + +2010-06-09 17:02:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Handle SEEKING query in push mode too + +2010-06-09 16:38:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Update the total time from the Skeleton 4 indexes + Fixes bug #620939, see bug #607945. + +2010-06-09 16:33:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: Implement latest version of the Skeleton 4.0 spec + Fixes bug #620939. + +2010-06-09 16:59:10 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/volume/gstvolume.c: + volume: make the orc codes available for testing. + Add a USE_ORC define for now and switch 'this' to 'self'. Having orc enabled + passes the test suite and various manual gst-launch pipelines. + +2010-06-08 13:34:46 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + .gitignore: add orc-related temp files + +2010-06-08 13:26:53 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * gst/audioresample/Makefile.am: + * gst/audioresample/gstaudioresample.c: + Fix build if orc is not installed + Orc is not a hard requirement. Things should still compile and + work without orc, but slow fallback code may be used in this + case. Fix up configure to not error out if orc is not installed + and wrap use of orc profiling in audioresample in #ifdefs. + Fixes #620136 some more. + +2010-06-08 13:11:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Implement correct parsing of Skeleton 4.0 index packets + +2010-06-08 12:01:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: Add parsing of Skeleton 4.0 indexes + +2010-06-08 11:40:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Parse segment length and content offset from fishead + And print them for debugging purposes. Not sure if we can do anything useful + with this information. + +2010-06-08 11:31:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: Parse Skeleton stream major/minor version + +2010-06-08 11:26:26 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Use binary search for searching in the index + +2010-06-08 11:02:08 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/libs/video.c: + video: Fix unit test, the Y800 checks were not used before and were not working + +2010-06-08 11:01:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + video: Return TRUE in gst_video_format_is_gray() for Y800 and Y16 + +2010-06-08 00:33:31 -0700 David Schleef <ds@schleef.org> + + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + audioconvert, videotestsrc: Update generated Orc code + Fixes compile errors with initialization of unions. + +2010-06-08 00:32:36 -0700 David Schleef <ds@schleef.org> + + * REQUIREMENTS: + requirements: change liboil to Orc + +2010-06-06 23:50:05 -0700 David Schleef <ds@schleef.org> + + * gst/audioresample/Makefile.am: + * gst/audioresample/gstaudioresample.c: + audioresample: convert from liboil to orc + +2010-06-06 23:48:35 -0700 David Schleef <ds@schleef.org> + + * tests/check/Makefile.am: + tests: Add orc tests + +2010-06-06 23:48:15 -0700 David Schleef <ds@schleef.org> + + * gst/volume/Makefile.am: + * gst/volume/gstvolume.c: + * gst/volume/gstvolumeorc-dist.c: + * gst/volume/gstvolumeorc-dist.h: + * gst/volume/gstvolumeorc.orc: + volume: convert from liboil to orc + +2010-06-06 23:47:53 -0700 David Schleef <ds@schleef.org> + + * gst/videotestsrc/Makefile.am: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.c: + * gst/videotestsrc/gstvideotestsrcorc-dist.h: + * gst/videotestsrc/gstvideotestsrcorc.orc: + * gst/videotestsrc/videotestsrc.c: + videotestsrc: convert from liboil to orc + +2010-06-06 23:47:16 -0700 David Schleef <ds@schleef.org> + + * gst/videoscale/Makefile.am: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscaleorc-dist.c: + * gst/videoscale/gstvideoscaleorc-dist.h: + * gst/videoscale/gstvideoscaleorc.orc: + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + * gst/videoscale/vs_image.h: + * gst/videoscale/vs_scanline.c: + * gst/videoscale/vs_scanline.h: + videoscale: convert from liboil to orc + +2010-06-06 23:46:41 -0700 David Schleef <ds@schleef.org> + + * gst/audioconvert/Makefile.am: + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/gstaudioconvertorc-dist.c: + * gst/audioconvert/gstaudioconvertorc-dist.h: + * gst/audioconvert/gstaudioconvertorc.orc: + audioconvert: convert from liboil to orc + +2010-06-06 23:45:58 -0700 David Schleef <ds@schleef.org> + + * gst/adder/Makefile.am: + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + * gst/adder/gstadderorc-dist.c: + * gst/adder/gstadderorc-dist.h: + * gst/adder/gstadderorc.orc: + adder: convert from liboil to orc + +2010-06-06 23:45:10 -0700 David Schleef <ds@schleef.org> + + * docs/design/Makefile.am: + * docs/design/design-orc-integration.txt: + docs: Add notes about Orc integration + +2010-06-06 23:34:39 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + configure: convert liboil check to orc + +2010-06-08 07:34:08 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + oggmux: Start a new page for every CMML buffer + +2010-06-07 14:38:42 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: add av-offset property + Add av-offset property to control the audio and video sync offset. This can be + used to to manually correct badly synced streams. + See #620529 + +2010-06-07 08:31:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + ffmpegcolorspace: Map "Y8 " and "GREY" to "Y800" and add it to the template caps + +2010-06-07 08:17:13 +0200 Martin Bisson <martin.bisson@gmail.com> + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add support for Y800 and Y16 + Fixes bug #620441. + +2010-06-07 08:16:01 +0200 Martin Bisson <martin.bisson@gmail.com> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add support for Y800 and Y16 + Fixes bug #620441. + +2010-06-06 16:46:55 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: fix log function printf format issue + +2010-06-05 18:14:38 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: stop jpeg typefinding once we found a SOF marker + +2010-06-05 18:05:40 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/gst/typefindfunctions.c: + tests: fix memory leak in unit test + +2010-05-19 15:40:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: improve jpeg typefinder + Make jpeg typefinder check more than just the first two bytes + plus Exif or JFIF marker. This allows us to report MAXIMUM + probability in cases where there's no Exif or JFIF marker, + making typefinding stop early. Also extract width and height, + because we can. + +2010-06-05 17:22:17 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * tests/Makefile.am: + * tests/check/Makefile.am: + * tests/check/gst/typefindfunctions.c: + * tests/files/Makefile.am: + * tests/files/partialframe.mjpeg: + tests: add small unit test for AC3 vs. JPEG typefinding issue + +2010-06-05 16:58:50 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: fix AC-3 typefinding so that it actually checks for a second frame + Fix typo that made the AC-3 typefinder not actually check for a + second frame, but rather compare the sync point found to itself, + which resulted in the AC-3 typefinder reporting an overly optimistic + MAXIMUM or VERY_LIKELY probability when it found a possible frame + sync. + +2010-06-05 12:27:12 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstscreenshot.c: + playbin2: improve screenshot code + Use appsrc and appsink in the screenshot code to make things nicer. + +2010-06-05 11:28:17 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: fix documentation string + +2010-06-05 11:05:22 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: add convert-frame action signal + Add a convert-frame action signal. + Fixes #620279 + +2010-06-05 11:02:24 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstscreenshot.c: + * gst/playback/gstscreenshot.h: + playbin2: move marshaller to screenshot + Move the marshaller for the convert_frame signal to the screenshot file in + preparation for moving it to playsink. + See #620279 + +2010-06-05 10:42:56 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: move convert_frame to playsink + Move the convert_frame function to playsink and make it part of the API. This is + in preparation to add the convert_frame signal to playsink. + See #620279 + +2010-06-05 10:31:03 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: add property to get the last frame + Add a property to get the last video frame. + See #620279 + +2010-06-04 19:30:14 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Handle raw streams we don't want. + If a file contains raw streams (not requiring a decoder) that we do + not want (expose-all-streams == FALSE), we would previously consider + those of unknown-type (missing a decoder) ... whereas in fact it was just + because they don't need decoders. + This only applies if expose-all-streams is FALSE. + +2010-06-03 13:44:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + Revert "baseaudiosink: Allocate and free the clock in NULL->READY and reverse" + This reverts commit cea2644ed86097aadedc9e8731e78a22ffc6246b. + Many audio sink assume that they can create a clock in + the instance init function and it will be there forever + and not be cleared by the state change functions. + +2010-06-02 12:19:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: Allocate and free the clock in NULL->READY and reverse + +2010-06-01 23:49:07 -0700 David Schleef <ds@schleef.org> + + * common: + Automatic update of common submodule + From 17f89e5 to 47683c1 + +2010-06-01 22:54:33 -0700 David Schleef <ds@schleef.org> + + * common: + Automatic update of common submodule + From fd7ca04 to 17f89e5 + +2010-06-01 13:00:22 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * tests/examples/overlay/Makefile.am: + examples: get the right Qt moc binary to use via pkg-config + Should make us do the right thing in cases where both Qt3 and Qt4 + are installed. + Fixes #620211. + +2010-05-31 19:28:45 +1000 Jonathan Matthew <jonathan@d14n.org> + + * ext/gio/gstgiobasesink.c: + gio: map GIO NO_SPACE error to NO_SPACE_LEFT + Fixes bug #620140. + +2010-05-28 08:27:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * gst-libs/gst/interfaces/streamvolume.c: + configure: Remove (now) useless check for cbrt + +2009-12-02 22:16:22 -0800 David Schleef <ds@schleef.org> + + * gst-libs/gst/interfaces/streamvolume.c: + interfaces: Use pow() instead of cbrt() for MSVC + +2010-05-26 11:54:51 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 357b0db to fd7ca04 + +2010-05-26 08:51:09 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/audiorate/gstaudiorate.c: + audiorate: Fix buffer offset_end when within tolerance. + This fixes issues if we then have downstream elements that operate + on offset/offset_end. + And add the expected timestamp in the debug logs + +2010-05-24 11:27:36 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/fft/kiss_fft_f32.c: + * gst-libs/gst/fft/kiss_fft_f32.h: + * gst-libs/gst/fft/kiss_fft_f64.c: + * gst-libs/gst/fft/kiss_fft_f64.h: + * gst-libs/gst/fft/kiss_fft_s16.c: + * gst-libs/gst/fft/kiss_fft_s16.h: + * gst-libs/gst/fft/kiss_fft_s32.c: + * gst-libs/gst/fft/kiss_fft_s32.h: + * gst-libs/gst/fft/kiss_fftr_f32.c: + * gst-libs/gst/fft/kiss_fftr_f64.c: + * gst-libs/gst/fft/kiss_fftr_s16.c: + * gst-libs/gst/fft/kiss_fftr_s32.c: + fft: Merge kissfft 1.2.8 + This reduces memory footprint for the FFT and adds + OpenMP support (but we don't use it). + +2010-05-22 10:05:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: Fixate interlaced, chroma-site and color-matrix fields if necessary + +2010-05-22 10:02:46 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * gst/videorate/gstvideorate.c: + videorate: Use new string fixation function from core + +2010-05-22 09:48:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: Fixate color-matrix and chroma-site fields if necessary + +2010-05-22 09:39:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: Fixate the interlaced field if necessary + Fixes bug #619310. + +2010-05-22 08:55:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add IVF typefinder + +2010-05-21 18:16:07 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: pass object to logging functions, use GST_DEBUG_FUNCPTR + +2010-05-20 15:14:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add basic descriptions for new WebM and VP8 types + +2010-05-20 14:21:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Fix sizes again, this time for real + +2010-05-20 13:58:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + oggdemux: Fix size checks + +2010-05-20 10:19:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + oggdemux: Drop all other Ogg VP8 header packets and make VP8 mapping check a bit more strict + +2010-05-20 08:52:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + ogg: Some more minor adjustments for the VP8 Ogg mapping + +2010-05-19 21:35:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + ogg: Update to the latest VP8 mapping + +2010-05-10 05:53:22 +0200 Philip Jägenstedt <philipj@opera.com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Detect WebM as video/webm + Refactor matroska_type_find into ebml_check_header and a new + matroska_type_find and webm_type_find. + +2010-05-14 13:31:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Fix granulepos->key granule calculation for Dirac + +2010-05-14 11:02:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Add support for mapping specific granulepos to key granule mapping + +2010-05-05 13:59:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + ogg: Implement Ogg VP8 mapping + +2010-04-27 15:24:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: Add support for On2 VP8 + +2010-05-19 16:17:19 +0200 Alessandro Decina <alessandro.decina@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: fix a typo introduced by 9d753824. + video/x-raw-float => audio/x-raw-float. Fixes #619090. + +2010-05-18 08:45:52 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't put "raw" subtitle types in the raw caps for decodebin2 + We handle them from the autoplug-continue signal, where the caps supported + by the subtitle sink or overlay are known already. + +2010-05-15 21:15:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + configure: Use = instead of == in shell scripts for equality checks + +2010-05-14 18:23:11 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 4d67bd6 to 357b0db + +2010-05-14 17:24:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Always take the object lock when accessing the caps + Fixes bug #618625. + +2010-05-14 17:17:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Don't fail if subtitles are used but only audio is available and no visualizations + Instead simply disable displaying of the subtitles for now, as was + intended by that part of code... + Fixes bug #610866. + +2010-05-14 17:13:17 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Fix deadlock caused from an additional lock instead of unlock + Also improve debug output for the playsink lock. + +2010-05-13 12:16:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Use passthrough mode if width and height are not changed + It doesn't matter if the PAR changes or not, processing of every pixel + is only necessary when the width or height changes. + +2010-05-13 12:03:07 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: relax width and height constraints + Increase the acceptable video sizes from [16,4096] to [1, MAX]. + See #618392 + +2010-05-13 08:05:09 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + video: Use simple fraction multiplication functions instead of going through GValues + +2010-05-10 17:09:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: Add a unit test for checking if the negotiation works as expected + +2010-05-10 17:09:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Try harder to keep the DAR if possible + Fixes bug #371108. + +2010-05-10 15:13:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Log PAR and DAR of input and output caps when setting caps + +2010-05-10 14:52:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Set input width/height if the output caps don't have any width or height + +2010-05-10 13:01:44 +0200 Andoni Morales <ylatuya@gmail.com> + + * gst/videoscale/gstvideoscale.c: + videoscale: Try to keep DAR when scaling + Fixes bug #371108. + +2010-05-10 19:09:28 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + basertpaudiopayload: Add extra frame for non-complete frame lengths + Some payloaders like rtpg729pay can add a shorter frame at the end of a + RTP packet. We need to count it like a full frame for timestamps. + https://bugzilla.gnome.org/show_bug.cgi?id=618324 + +2010-05-10 18:53:29 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + basertpaudiopayload: Set duration on buffers + Set the duration of the buffers from their size + +2010-05-11 16:12:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: Fixate PAR to 1/1 if possible + +2010-05-11 10:07:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + configure: Check for GTK+ 3.0 and if it's not available for GTK+ 2.0 + +2010-05-10 12:44:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * sys/ximage/ximagesink.c: + ximagesink: Check if the X context is allocated before using it + It should be allocated at these places already or the state changes + would have failed... but better add an additional check here. + +2010-05-10 12:28:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * sys/ximage/ximagesink.c: + ximagesink: Post an error message on the bus if no supported pixmap formats can be found + Might fix bug #615851. + +2010-05-07 19:49:57 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace : whooops + +2010-05-07 19:21:13 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: more minor cleanups + +2010-05-07 17:16:28 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: speedup caps transformation + * don't re-create our possible caps every single time, just use the + template caps. + * don't intersect the caps against the template, basetransform has already + done that for us. + 62% speedup of _transform_caps() (instruction calls, measured with callgrind) + +2010-05-07 12:19:25 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add the 'expose-all-streams' property from decodebin2 + API: expose-all-streams + https://bugzilla.gnome.org/show_bug.cgi?id=617868 + +2010-05-06 18:50:51 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Add a property to not expose/decode all streams + API : expose-all-streams + If disabled: + * only the streams that CAN be decoded and match the final caps will have a + decoder plugged in and be exposed. + * the streams that COULD HAVE BEEN decoded but do not match the finals caps + will not have a decoder plugged in and will not be exposed. + If no decoder is available to decode a certain stream, then the missing element + message will still be emitted regardless of the value of the property. + https://bugzilla.gnome.org/show_bug.cgi?id=617868 + +2010-05-06 17:47:12 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: rename are_raw_caps to are_final_caps, correct comment + https://bugzilla.gnome.org/show_bug.cgi?id=617868 + +2010-05-07 17:16:37 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/sdp/gstsdpmessage.h: + sdpmessage: add new TIAS bandwidth modifier + Add TIAS modifier as specified in RFC 3890. + Do some whitespace fixes. + +2010-05-07 00:10:22 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/audioconvert/audioconvert.c: + audioconvert: disambigue comment due to popular demand + Write "target depth" instead of "our depth" or previous ambigous "out depth". + +2010-05-06 15:40:34 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: disconnect signals in some more cleanup cases + +2010-05-06 13:10:54 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: don't seek when no current chain + Avoid a crash when we try to seek when there is no current chain. + +2010-05-06 12:21:38 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: ignore the skeleton start time + Ignore the skeleton start time as it is usually wrong for live streams + and we have the needed logic to calculate it anyway. + +2010-05-06 12:06:09 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: wait for headers before exposing chains + Wait until we have all the stream headers before we start exposing the streams + of a chain. + +2010-05-06 10:56:21 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: use index to estimate bitrate + When we have an index, use it to much more accurately estimate the total stream + bitrate. + +2010-05-06 11:34:53 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/rtsp/gstrtsptransport.h: + docs: be more firendly to gtk-doc limitted parsing capabilities + +2010-05-06 09:42:02 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspmessage.c: + * gst-libs/gst/rtsp/gstrtsprange.c: + * gst-libs/gst/rtsp/gstrtsptransport.c: + * gst-libs/gst/rtsp/gstrtspurl.c: + docs: fix wrong doc markup + +2010-05-06 09:17:33 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/videoscale/gstvideoscale.c: + videoscale: use can_intersect to avoid a caps copy + +2010-05-06 09:14:25 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/videorate/gstvideorate.c: + videorate: trucate own caps, instead of copying and using the first only + We got the caps from an intersect, it is our own, hence we can truncate it. + Besides gst-indent has chooses to line-up all caps in one line again :/. + +2010-05-06 09:12:32 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstdecodebin.c: + decodebin: use can_intersect to avoid a caps copy + +2010-05-06 09:11:17 +0300 Stefan Kost <ensonic@users.sf.net> + + * ext/libvisual/visual.c: + libvisual: trucate own caps, instead of copying and using the first only + We got the caps from an intersect, it is our own, hence we can truncate it. + +2010-05-06 08:20:10 +0300 Stefan Kost <ensonic@users.sf.net> + + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisdec.h: + * ext/vorbis/gstvorbisdeclib.c: + * ext/vorbis/gstvorbisdeclib.h: + vorbis: have a copy_sample func as a func pointer + Make some more variants for copy_sample funcs and use them via function pointer. + +2010-05-06 08:16:45 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/audioconvert/audioconvert.c: + audioconvert: fix typo in comment + +2010-05-06 08:15:16 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: use gst_caps_can_intersect() more + In place where we just need to know whether caps intersect, we can use this + quicker function. + +2010-04-15 13:09:45 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + * tests/icles/position-formats.c: + examples: add a test for difference position formats + The test runs position and duration queries on the pipeline in all formats. + +2010-04-15 13:08:39 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/audio-trickplay.c: + example: update status (adder is fixed now) + +2010-04-15 13:08:01 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/playbin-text.c: + example: make app static + +2010-05-05 13:25:02 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: printf format fixes + +2010-05-04 15:32:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: weekday and month names in RTSP date string should be in C locale + Create date string using C locale weekday and month names. + Fixes #617636. + +2010-05-04 17:54:01 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add all qtdemux types to downloadable types + Add all the media types that qtdemux can handle to the list of downloadable + types. + +2010-05-04 17:38:50 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: handle corrupt indexes + Make sure we handle and receover from corrupt indexes. + +2010-05-04 15:47:29 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix EOS check + +2010-05-04 13:51:07 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: avoild division by 0 + +2010-05-04 13:50:46 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: cleanup unused defines + +2010-05-04 13:36:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: use the index in push mode when we can + When seeking in push mode, try to use the index first before we use the bitrate + estimation. + +2010-05-04 13:05:51 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: use skeleton duration when possible + +2010-05-04 13:02:19 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggstream: parse duration from 3.3 skeleton + +2010-03-02 11:16:39 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: more index parsing work + +2010-03-01 13:50:32 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: clean up fishead/fisbone parsing + Remove some redundant code for parsing fishead streams. Actually use the data we + parsed (mostly start_time). + +2010-05-04 11:19:39 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: implement seek in push mode + Refactor start time collection code. + When we receive a flush_stop, resync to the new start time and push out a new + segment event. + +2010-05-03 16:52:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: make event handling better + Explicitly handle FLUSH events and resync on FLUSH_STOP. + Make send_event return a boolean. + Use more performant send_event function to forward events. + +2010-04-30 18:37:17 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: implement seeking in pushmode + Convert seek requests to bytes using the bitrate and forward them upstream. Does + not quite work because the flushing and resyncing is not implemented yet. + +2010-04-30 18:03:37 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: refactor for seeking in pushmode + refactor the code a little to prepare for seeking in push mode + +2010-05-03 12:46:34 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds new geo-location mappings + Adds GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, + GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION and + GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION to xmp + mappings. + Tests included. + +2010-04-26 22:08:41 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds xmp mappings for device tags + Adds xmp mappings for GST_TAG_DEVICE_MANUFACTURER and + GST_TAG_DEVICE_MODEL. Also adds tests for it. + +2010-04-30 19:56:14 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspbase64.c: + * gst-libs/gst/rtsp/gstrtspbase64.h: + rtsp: deprecate remaining base64 function now that we depend on GLib 2.20 + API: deprecate gst_rtsp_base64_decode_ip(), use g_base64_decode_inplace() instead + +2010-04-30 19:37:33 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basertpdepayload: ensure writable metadata + +2010-04-30 17:41:05 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: use bitrate to estimate length in pushmode + Parse the bitrate from the various streams. + Use the bitrate and the upstream length in bytes to estimate the total stream + duration in push mode. + +2010-04-30 14:07:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * ext/gio/gstgiobasesrc.c: + Bump GLib requirement to 2.20 + See http://gstreamer.freedesktop.org/wiki/ReleasePlanning/GLibRequirement + +2010-04-30 13:36:59 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: forward duration query duration during group switch if no cached duration + ... such as during first group setup. + Fixes #616396. + +2010-04-02 16:37:21 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: only EOS when all streams are EOS + +2010-04-02 16:36:53 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix debug message + +2010-04-30 08:45:43 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/audio-trickplay.c: + test: fix copy and paste error of variable name + +2010-04-18 20:46:37 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: only accept seek-types none and set + Previously we were also acting on cur and end, but treating them like none. + +2010-04-14 23:31:20 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + adder: rework timestamping + Adder was using always incrementing timestamps. Seeking was done by setting the + position in the newsegment event. This was failing when doing segmented seeks + with rate<0.0, as offset (and thus timestamp) would go below 0. + Now we take both cur and end from the seek event. We construct newsegment events + depending including cur and end from the seek event. We set position to the + start of the segment. Timestamp is set to start or end of segment depending on + rate. Offset is recalculated. + +2010-04-26 17:30:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Add support for deinterlacing + This is disabled by default and can be enabled with the + deinterlace flag. + Fixes bug #547603. + +2010-04-26 11:12:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplay-enum.c: + * gst/playback/gstplay-enum.h: + playbin2: Add flag for enabling/disabling automatic deinterlacing + +2010-04-26 11:11:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplay-enum.c: + playbin: Use g_once_init_{enter,leave} instead of GOnce for enum/flag registration + +2010-04-23 17:01:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/Makefile.am: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.h: + ffmpegcolorspace: Use GST_BOILERPLATE and use GstVideoFilter as base class + This gives automatic QoS handling. + +2010-04-23 16:24:11 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Correctly reconfigure the video chain when switching from a subtitle to a non-subtitle file + Fixes bug #616422. + +2010-04-23 16:08:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: If a text sink is provided, let subtitle parsing be done by decodebin2 if required + This way subtitle sinks only get buffers in the format that they + understand, i.e. raw parsed text in most cases. + Fixes bug #614942. + +2010-04-23 15:30:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Set subtitle encoding on the decodebins again + +2010-04-23 15:22:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: API: Add GST_VIDEO_FORMAT_v308 for packed 4:4:4 YUV + +2010-04-23 15:14:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + videoscale: Some random cleanup + +2010-04-23 15:06:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Add support for Y444, Y42B and Y41B + +2010-04-23 14:42:50 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Reorder template caps by the amount of information contained in the color formats + +2010-04-22 15:46:17 -0400 Joshua M. Doe <joshua.doe@us.army.mil> + + * gst/videorate/gstvideorate.c: + videorate: add support for video/x-raw-gray + +2010-04-29 15:05:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/inspect/plugin-decodebin2.xml: + * docs/plugins/inspect/plugin-playbin.xml: + docs: remove references to and introspection data of plugins that no longer exist + Some plugins (decodebin2, playbin) have been renamed or merged + into different plugins (uridecodebin, playback). + +2010-04-29 15:02:39 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + Back to development. + +=== release 0.10.29 === + +2010-04-28 02:16:58 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.29 + +2010-04-28 01:34:24 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2010-04-25 23:14:35 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.28.3 pre-release + +2010-04-20 17:20:43 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-plugins-base.doap: + doap: update repository info from cvs->git and maintainers + +2010-04-23 14:39:46 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From fc85867 to 4d67bd6 + +2010-04-22 20:58:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Fix Y41B->Y444 conversion + ...which is the intermediate conversion for conversion to all + other formats. + Fixes bug #616545. + +2010-04-16 20:03:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: Don't leak the input buffer in error cases + Fixes bug #615572. + +2010-03-29 12:53:11 +0300 Stefan Kost <ensonic@users.sf.net> + + * ext/ogg/gstoggmux.c: + docs: fix typo in link name + +2010-04-15 12:59:53 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: gracefully handle ximagesink>xwindow == NULL + Expose could be called before we have set the xwindow. Handle this gracefully + like we do in image_put. + Fixes #615789 + +2010-04-15 11:44:49 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + ximagesink: refactor _update_geometry() + Refactor like in xvimagesink. Remove the extra parameter and adjust the assert check. + +2010-04-15 07:18:05 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * configure.ac: + configure: Drop -Wcast-align + Commit message copied from core's commit from Benjamin Otte: + 246f5dba96a5b50bb74621af67b30942cca72af5 + Apparently gcc warns that GstMiniObject is not castable to + GstEvent/Message/Buffer due to them containing 64bit variables, even + though ARM hackers claim that those only need 4byte alignment. And as + long as gcc behaves that way, this warning is not very useful. + So we'll remove the warning until this problem is fixed. + Fixes #615698 + +2010-04-14 14:13:25 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * gst-libs/gst/tag/lang-tables.dat: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/video-enumtypes.c: + 0.10.28.2 pre-release + +2010-04-14 13:50:21 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translations + +2010-04-13 16:20:10 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: init geometry when setting new xid + Don't rely on expose event to query geomentry after new xid is set. + Fixes #615647. + +2010-04-14 13:43:44 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/audioconvert/Makefile.am: + * tests/examples/app/Makefile.am: + * tests/examples/dynamic/Makefile.am: + * tests/examples/gio/Makefile.am: + * tests/examples/volume/Makefile.am: + * tests/old/examples/switch/Makefile.am: + build: use LDADD instead of LDFLAGS to specify libs to link to when building executables + Use foo_LDADD instead of foo_LDFLAGS to specify the libraries to link to. + This should make sure arguments are passed to the linker in the right + order, and makes LDFLAGS usable again. + Based on initial patch by Brian Cameron <brian.cameron@oracle.com> + Fixes #615697. + +2010-04-12 14:02:34 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: add channels and rate to ADTS caps if we can + +2010-04-12 13:33:18 +0100 Arun Raghavan <arun.raghavan@collabora.co.uk> + + * gst/typefind/Makefile.am: + * gst/typefind/gstaacutil.c: + * gst/typefind/gstaacutil.h: + * gst/typefind/gsttypefindfunctions.c: + typefinding: add AAC level to ADTS caps + This adds code to calculate the level for a given AAC stream and export + it in the stream caps. For AAC LC streams, the level is calculated + according to the definition under the AAC Profile. For other streams, + the definition under the Main Profile is used. + HE-AAC support is still to be done, and is dependent on detecting the + presence of SBR and PS in the stream. + Level is added as a field of type string because that's the way it's + done in H.264 caps as well. There are only a few possible levels, so + not using a numerical type is not too painful in this case, and + consistency is nice. + Fixes #613589. + +2010-03-10 13:32:53 +0000 Arun Raghavan <arun.raghavan@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: add AAC profile to ADTS caps + This looks at the AAC profile for ADTS streams and adds the profile as a + string in the corresponding caps. + Profile is the actual profile, base-profile denotes the minimum codec + requirements to decode this stream. In this case they're always the + same, but they may differ e.g. in case of certain HE-AAC streams that + can be partially decoded by LC decoders (with loss of quality of course) + if no suitable HE-AAC decoder is available. + Fixes #612312. + +2010-04-11 22:58:15 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: add support for negative playback rates + Decrement sample counter when playing backwards. Set proper segment when playing + backwards (0..cur instead or cur..-1). Add more logging and fix a format string. + +2010-03-26 19:00:47 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiopayload: use ptime-multiple + Based on patch by Olivier Crête <olivier.crete@collabora.co.uk> + Fixes #613248 + +2010-04-09 16:06:05 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + audiopayload: add property to control packet duration + Add a property to specify that the amount of data in a packet should be a + multiple of ptime-multiple. + See #613248 + +2010-04-09 11:20:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 218568f to fc85867 + +2010-04-08 17:49:02 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/Makefile.am: + * gst/playback/Makefile.am: + * gst/playback/gstplayback.h: + playback, ogg: dist new gstplayback.h and gstogg.h + +2010-04-09 08:23:33 +0200 Thomas Green <thomasgr33n@googlemail.com> + + * gst/playback/gstplaybin.c: + playbin: Only unref the volume element on dispose and when a new audio sink is set + Unreffing it whenever the sinks are removed will make the volume + element unavailable after a playbin reuse because it is only + recreated if the audio sink has changed. + Fixes bug #614288. + +2010-04-08 07:39:08 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Be sure that metadata is writable before setting caps + Call gst_buffer_make_metadata_writable before attempting + to set caps on the buffer. + +2010-04-08 12:21:50 +0200 Edward Hervey <bilboed@bilboed.com> + + * ext/gio/gstgio.c: + * ext/gnomevfs/gstgnomevfs.c: + ext: Invert rank of gio and gnomevfs elements + +2010-04-08 01:26:09 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + alsa: don't pass non-constant strings as printf format strings + Fixes 'format not a string literal and no format arguments' compiler + warning when compiling with -DGST_DISABLE_PRINTF_EXTENSION. + +2010-04-07 20:21:14 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/video/video.h: + docs: add gtk-doc chunks with Since: tags for new GST_VIDEO_CAPS_GRAY* API + +2010-04-07 19:07:29 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * autogen.sh: + * configure.ac: + build: bump autoconf requirement to 2.60 for gobject-introspection.m4 + Require autoconf 2.60 (which was released in June 2006). + Fixes #600718. + +2010-04-07 17:25:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + video: Fix parsing of 8-bit grayscale caps + +2010-04-07 17:21:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/video/video.h: + video: API: Add GST_VIDEO_CAPS_GRAY{8,16} + +2010-04-07 17:08:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + video: API: Add gst_video_format_is_gray() to the docs + +2010-04-07 17:07:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * win32/common/libgstvideo.def: + video: Add new symbol to the exported symbols list + +2010-04-07 17:06:36 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add support for 8-bit and 16-bit grayscale formats + +2010-04-06 10:55:42 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtspconnection: Handle closed POST socket in tunneling + Catch more socket errors. + Rework how sockets are managed in the GSource, wake up the maincontext instead + of adding/removing the sockets from the source. + Add callback for when the tunnel connection is lost. Some clients (Quicktime + Player) close the POST connection in tunneled mode and reopen the socket when + needed. + See #612915 + +2010-04-04 21:24:44 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + configure: fix cdparanoia check + Linking with libcdda_paranoia.so requires also linking with + libcdda_interface.so. + +2010-04-04 18:00:23 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/libs/tag.c: + tests: tag: Refactor a bit + Refactor xmp tags unit tests and remove an useless assertion. + This will make easier to add unit tests to serialize/deserialize + taglists. + +2010-04-04 21:18:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + alsa: Ignore errors when unpreparing or closing the device + Errors could happen here when the device was removed already + or when something is broken anyway. If errors happen here and + they're propagated, the element can't shutdown cleanly. + Fixes bug #614545. + +2010-04-04 20:55:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/alsa/gstalsamixer.c: + alsamixer: Detect errors from device polling, stop the task and post an error message + Partially fixes bug #614545. + +2010-04-04 12:13:02 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * tests/examples/seek/Makefile.am: + examples: build silly joystick seek example only on linux + jsseek depends on linux headers and should therefore only be built + on linux. + Fixes #614764. + +2010-04-03 22:49:11 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: swap timestamps in forward and reverse mode. + In reverse mode we want use the next next timestamp (and not the other way + around). Fixes the tests again. Also readd a log line that was dropped with + previous commit. + +2010-04-03 14:03:45 +0100 Vincent Untz <vuntz@gnome.org> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + libs: point gobject-introspection scanner to .la files + Point g-ir-scanner to the .la file of our library, which hopefully + makes it find the right dependencies in all cases (ie. our locally + built libgstreamer and not the system-installed one). This is also + how it's done in Gtk+ and how it's documented in the wiki, see + http://live.gnome.org/GObjectIntrospection/AutotoolsIntegration + Fixes #603710. + +2010-04-02 21:01:25 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/audiotestsrc/gstaudiotestsrc.h: + audiotestsrc: implement reverse playback + Support playback at negative rates. When having a GstController assigned, the + element will produce time dependend output. + +2010-04-02 20:56:19 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/audio-trickplay.c: + tests: extend audio-trickplay test app + Tell status in top comment. Use debug logging instead of print to be able to + see timing issue in debug log viewer. Add more commandline flags. Test reverse + playback. + +2010-04-02 18:56:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: Only use embed_xid if HAVE_X is defined + Fixes bug #614622. + +2010-04-01 19:13:22 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/check/pipelines/basetime.c: + tests/basetime: Don't run test with osxaudiosrc + libcheck runs the actual tests in a forked process and that makes the guys + in Cupertino really sad. + +2010-04-01 18:51:17 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/check/pipelines/capsfilter-renegotiation.c: + tests: Unref the bus once we're done with it + +2010-04-01 16:49:37 +0200 Edward Hervey <bilboed@bilboed.com> + + * common: + common: Update for new suppressions + +2010-04-01 13:55:15 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaysink.c: + gstplaysink: Remove unused variable. + The value of klass is never used + +2010-04-01 13:53:37 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Removing dead assignment. + The value of group is overwritten a few lines below before being used. + +2010-04-01 13:51:13 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: Remove unused variable + +2010-04-01 13:48:42 +0200 Edward Hervey <bilboed@bilboed.com> + + * ext/gnomevfs/gstgnomevfssink.c: + gstgnomevfssink: Return the proper GstFlowReturn. + We were always returning GST_FLOW_OK previously even if we encountered errors. + +2010-03-30 23:44:51 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + gst-libs: more gobject-introspection fixes + Use right .pc file variable for compiler includes this time: + g-ir-compiler wants the girdirs not the typelibdirs as includes. + +2010-03-30 20:21:28 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/seek/jsseek.c: + examples: fix printf format warning in jsseek example + Yes, I know about G_GSIZE_FORMAT. + +2010-03-30 19:56:56 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + gst-libs: fix up gobject-introspection some more + Use new girdir and typlibdir from core .pc files, so we can figure + out the right includes to pass to the gobject-introspection tools, + whether core is installed in the same prefix as gobject-introspection + or in a different prefix or uninstalled. This also keeps us from adding + bogus paths to the includes that only work if core is uninstalled. + Also add some missing includes/pkgs where needed. + +2010-03-30 19:29:48 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/Makefile.am: + Our RIFF library depends on both the audio and tag libraries + Update rules in Makefile.am accordingly. + +2010-03-30 15:10:42 +0200 Robert Swain <robert.swain@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Fix aduio_raw_sink typo + +2009-11-28 21:03:44 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/examples/seek/.gitignore: + * tests/examples/seek/Makefile.am: + * tests/examples/seek/jsseek.c: + examples: Add a silly joystick based shuttle example + +2010-03-29 20:07:52 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoraenc.c: + theoraenc: 0-length packets are delta units + +2010-03-29 10:47:31 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/Makefile.am: + gst-libs: build independent sub-directories in parallel if make -jN is used + Build those libraries that don't depend on any other gst-plugins-base + libraries in parallel if make -jN is used. + +2010-03-29 00:22:20 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + * ext/Makefile.am: + * gst/Makefile.am: + * sys/Makefile.am: + * tests/examples/Makefile.am: + build: build plugin and example directories in parallel if make -jN is used + We know our plugins and examples are independent of each other, so may + just as well build them in parallel. Makes the output a bit messy, but + that shouldn't be a problem and can easily be avoided with make -j1. + +2010-03-28 21:50:58 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/Makefile.am: + gst-libs: specify dependencies in Makefile.am to make them explicit + +2010-03-24 09:59:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/xoverlay.c: + * gst-libs/gst/interfaces/xoverlay.h: + * sys/xvimage/xvimagesink.c: + * tests/icles/test-xoverlay.c: + xoverlay: change new set_render_rectangle() vfunc to take four arguments so we don't depend on libgstvideo + Don't make libgstinterfaces (and thus libgstaudio etc.) indirectly depend + on libgstvideo by using the GstVideoRectangle helper structure in the API, + which causes undesirable dependencies, esp. with the gobject-introspection + (people will point and laugh at us if they find out that libgstaudio + depends on libgstvideo). Instead, pass the x, y, width and height parameters + directly to the function. + Re-fixes #610249. + +2010-03-25 18:45:48 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: we can handle avi in download mode too + Add avi to the whitelisted types that can be used for download buffering. + +2010-03-26 15:57:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: Provide packet duration function for old FLAC mapping too + Fixes bug #613809. + +2010-03-18 22:12:40 +0000 Damien Lespiau <damien.lespiau@intel.com> + + * autogen.sh: + autogen.sh: Don't call configure with --enable-plugin-docs + configure gives a nice warning: + configure: WARNING: unrecognized options: --enable-plugin-docs + and indeed, I could not find anything in the configure.ac or the m4 + macros that would allow enabling that option. Remove it then. + +2010-03-24 23:04:43 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Do not remove tag from list twice + There was a but when parsing the tags that removed two tags + from the list when only one was parsed + +2010-03-24 14:43:21 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Add some comments + Just adds some comments explaining some stuff about the + (de)serialization functions. Add myself to the copyright list too. + +2010-03-24 10:18:13 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds _USER_RATING mapping for xmp + Adds a new mapping for _USER_RATING on xmp helper lib + and also adds tests for it + +2010-03-23 09:32:40 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Add Elevation tag mapping + Adds a mapping to the _ELEVATION tag, this is a different + mapping as it has to be mapped into exif:GPSAltitude and + exif:GPSAltitudeRef at the same time. So we needed to refactor + a little more to be able to deserialize it properly. + Now, when parsing a xmp buffer into a taglist all tags are + added to a list before being parsed so that when one of the + altitude tags are found the deserialization function can search + for its complementary tag to do the correct parsing + Fixes #613690 + +2010-03-23 09:48:19 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Fix off by one + Avoid ignoring single char tags, like exif:GPSAltitudeRef + Fixes #613690 + +2010-03-22 15:18:28 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + * tests/check/libs/tag.c: + tag: xmp: Adds mappings for LATITUDE and LONGITUDE + Adds the mappings for those tags and tests + for tags serialization. + Fixes #613690 + +2010-03-22 22:03:09 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Refactor buffer parsing + When parsing the xmp buffer into the gst taglist store the + found tags into a list to be parsed only after finding all + tags on the buffer. This allows the parser function to search + this list for complimentary tags that should be parsed together + Fixes #613690 + +2010-03-20 11:17:38 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tag: xmp: Refactor mappings storage + This commit is only refactoring, no fetaures added. + Do not store tags in flexible arrays as it doesn't allow us + to use nested flexible arrays. This is going to be needed in the + following commits to map gst tags that are stored into + 2 separate tags in xmp (Not that they are alternatives, but + they are complementary). + For example, GST_TAG_ELEVATION is represented in the exif + schema with 2 fields: the absolute altitude and an integer + to indicate if it is above or below sea level. + The previous mappings storage wouldn't allow us to + express it. + Also store a serialization and a deserialization function + for each xmp tag as some of them require some non-trivial + convertion to its string form. + Fixes #613690 + +2010-03-24 18:51:42 +0100 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From 55cd514 to c1d07dd + +2010-03-24 18:55:25 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: parse more info from the buffering query + Parse more info from the buffering query and log this as debug info. + +2010-03-24 12:10:38 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtsptransport.c: + rtsptransport: ignore unparsable ranges + Ignore unparsable port ranges instead of erroring out. + Fixes #613591 + +2010-03-23 18:36:26 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * win32/common/libgstrtsp.def: + win32: Add new gst_rtsp_lower_trans_get_type() symbol to the symbol lists + +2010-03-23 11:01:17 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: add some more fourcc for MPEG-4 video + +2010-03-22 09:15:28 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: require core git + +2010-03-22 08:38:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * pkgconfig/gstreamer-fft-uninstalled.pc.in: + * pkgconfig/gstreamer-fft.pc.in: + pkgconfig: Add @LIBM@ to the FFT pkg-config files + +2010-03-22 08:35:57 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * pkgconfig/gstreamer-app-uninstalled.pc.in: + * pkgconfig/gstreamer-audio-uninstalled.pc.in: + * pkgconfig/gstreamer-cdda-uninstalled.pc.in: + * pkgconfig/gstreamer-fft-uninstalled.pc.in: + * pkgconfig/gstreamer-floatcast-uninstalled.pc.in: + * pkgconfig/gstreamer-floatcast.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-netbuffer-uninstalled.pc.in: + * pkgconfig/gstreamer-pbutils-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-riff-uninstalled.pc.in: + * pkgconfig/gstreamer-rtp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp-uninstalled.pc.in: + * pkgconfig/gstreamer-sdp-uninstalled.pc.in: + * pkgconfig/gstreamer-tag-uninstalled.pc.in: + * pkgconfig/gstreamer-video-uninstalled.pc.in: + pkgconfig: Fix include and library paths for the uninstalled pc files + +2010-03-20 13:42:32 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/gio/gstgiobasesrc.c: + gio: add cast to avoid compiler warning with old GLib versions + g_file_input_stream_query_info() had char * instead of const char * + as attribute argument before 2.20. + Fixes #613387, spotted by tetsuyayasuda@gmail.com + +2010-03-20 12:55:36 +0000 Torsten Schönfeld <kaffeetisch@gmx.de> + + * gst-libs/gst/interfaces/xoverlay.c: + docs: add Since: tags to gst_x_overlay_handle_event() docs + Fixes #613403. + +2010-03-19 22:33:58 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + Constify some strings in the API + Needed by plugins-good + +2010-03-19 16:41:54 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Only set color-matrix and chroma-site for relevant formats + The color-matrix only makes sense for colorful formats, i.e. not Y800 + and the chroma-site only for non-4:4:4(:4) formats. + +2010-03-19 15:37:04 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/gsttheoradec.c: + * ext/theora/gsttheoradec.h: + theoradec: add QoS messages to the decoder + Post QoS messages when we drop a frame because of QoS. + +2010-03-19 15:00:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtsptransport.c: + * gst-libs/gst/rtsp/gstrtsptransport.h: + rtsp: add GType for transport flags + Make a method to register the transport flags as a GType. + +2010-03-19 01:00:36 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/cdparanoia/Makefile.am: + * ext/gio/Makefile.am: + * ext/gnomevfs/Makefile.am: + * ext/libvisual/Makefile.am: + * ext/ogg/Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/video/Makefile.am: + * gst/ffmpegcolorspace/Makefile.am: + * gst/tcp/Makefile.am: + * gst/videotestsrc/Makefile.am: + * sys/v4l/Makefile.am: + * tests/examples/app/Makefile.am: + * tests/examples/overlay/Makefile.am: + * tests/icles/Makefile.am: + build: Makefile.am fixes + Mostly just add missing $(GST_BASE_CFLAGS), but also fix up order + of flags (see docs/random/moving-plugins). + +2010-03-19 00:46:56 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/pipelines/.gitignore: + .gitignore: ignore new unit test binary + +2010-03-17 23:57:31 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure.ac: -Wmissing-prototypes and -Wnested-externs are not valid for C++ + Fixes building Qt-based overlay examples in combination with -Werror. + +2010-03-17 16:32:35 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure.ac: wrap overly long warning flag lines + +2010-03-17 19:24:27 -0300 Reuben Dowle <reube.dowle@navico.com> + + * sys/ximage/ximagesink.c: + ximagesink: Fix caps leak + Unref caps when peer doesn't accept caps + Fixes #613198 + +2010-03-17 08:13:59 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/Makefile.am: + * tests/check/pipelines/capsfilter-renegotiation.c: + tests: capsfilter-renegotiation: Adds a new unit test + Adds a new test for checking that capsfilter 'caps' property + changes cause caps renegotiation on the pipeline. + +2010-03-17 16:46:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_scanline.c: + videoscale: Use correct boundary checks for YUY2/UYVY + Fixes bug #613093. + +2010-03-17 16:39:13 +0100 Peter Kjellerstedt <peter.kjellerstedt@axis.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + rtsp: Further clean up of gst_rtsp_strresult() + Since we no longer use an array of error messages, there is no reason + to clamp the error code, which allows us to simplify the code some more + and also to actually report the correct error code for unknown errors. + +2010-03-17 15:41:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + volume: Remove useless cast + It's not necessary anymore after latest core change to GstValueArray. + +2010-03-17 12:08:30 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + Add more warning flags + The warnings are: + -Wcast-align + -Winit-self + -Wmissing-include-dirs + -Waddress + -Waggregate-return + -Wno-multichar + -Wnested-externs + No code needed to be fixed. + +2010-03-17 11:14:29 +0100 Benjamin Otte <otte@redhat.com> + + * gst/audioconvert/gstfastrandom.h: + Fix for -Wold-style-definition + I didn't add the flag to configure because libvisual ships headers that + trigger this warning. + +2010-03-17 10:53:21 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + * ext/pango/gstclockoverlay.h: + * gst/subparse/mpl2parse.c: + Add -Wformat-nonliteral -Wformat-security + And fix the resulting compile failures. + I'm sorry about the patch necessary to gstclockoverlay.h but after + talking to Tim we decided we can live with it. + +2010-03-17 10:51:57 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + rtsp: Refactor gst_rtsp_strresult + 2 goals in the refactoring: + - Put the error messages closer to their enum values, so that it's easy + to see which error belongs to which value. + - Make gcc not complain with -Wformat-nonliteral + +2010-03-17 10:47:07 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/tag/gstxmptag.c: + xmp: Refactor code + I initially looked here because I wanted compiles to not fail with + -Wformat-nonliteral but ended up refactoring the code to make it look + nicer. + As I lack a large collection of XMP tagged files, I only did rough + testing of the code. The testsuite passes though. + +2010-03-16 20:05:43 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * m4/Makefile.am: + * m4/a52.m4: + * m4/aalib.m4: + * m4/as-arts.m4: + * m4/as-ffmpeg.m4: + * m4/as-liblame.m4: + * m4/as-slurp-ffmpeg.m4: + * m4/esd.m4: + * m4/gconf-2.m4: + * m4/glib.m4: + * m4/gst-artsc.m4: + * m4/gst-matroska.m4: + * m4/gst-sdl.m4: + * m4/gst-shout2.m4: + * m4/gst-sid.m4: + * m4/gtk.m4: + * m4/libfame.m4: + * m4/libmikmod.m4: + m4: remove some unused .m4 files + +2010-03-16 18:31:15 +0100 Benjamin Otte <otte@redhat.com> + + * ext/alsa/gstalsaplugin.c: + * ext/ogg/gstoggdemux.c: + More ENABLE_NLS fixes + +2010-03-16 18:06:16 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/gettext.h: + Fix for ENABLE_NLS being undefined for -Wundef + +2010-03-15 22:49:53 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + * ext/libvisual/visual.c: + * ext/theora/gsttheoraenc.c: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/cdda/gstcddabasesrc.c: + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspurl.c: + * gst-libs/gst/tag/tags.c: + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + * gst/subparse/gstsubparse.c: + * gst/subparse/samiparse.c: + * gst/typefind/gsttypefindfunctions.c: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + * gst/volume/gstvolume.c: + * sys/v4l/gstv4lelement.c: + * sys/xvimage/xvimagesink.c: + * tests/check/elements/audioconvert.c: + * tests/check/elements/gdpdepay.c: + * tests/check/elements/playbin.c: + * tests/check/elements/playbin2.c: + * tests/check/elements/videorate.c: + * tests/check/libs/pbutils.c: + * tests/check/libs/video.c: + * tests/check/pipelines/simple-launch-lines.c: + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + * tests/icles/stress-playbin.c: + Add -Wwrite-strings to configure + Fixes for the code included + +2010-03-16 15:45:23 +0100 Benjamin Otte <otte@redhat.com> + + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsamixerelement.c: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + * ext/cdparanoia/gstcdparanoiasrc.c: + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/libvisual/visual.c: + * ext/ogg/gstoggaviparse.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: + * ext/ogg/gstogmparse.c: + * ext/theora/gsttheoradec.c: + * ext/theora/gsttheoraenc.c: + * ext/theora/gsttheoraparse.c: + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisdeclib.h: + * ext/vorbis/gstvorbisenc.c: + * ext/vorbis/gstvorbisparse.c: + * ext/vorbis/gstvorbistag.c: + * gst-libs/gst/sdp/gstsdpmessage.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/audiorate/gstaudiorate.c: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstinputselector.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gststreamselector.c: + * gst/playback/gsturidecodebin.c: + * gst/subparse/gstssaparse.c: + * gst/subparse/gstsubparse.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + * gst/videorate/gstvideorate.c: + * gst/videoscale/gstvideoscale.c: + * gst/videotestsrc/gstvideotestsrc.c: + * sys/v4l/gstv4ljpegsrc.c: + * sys/v4l/gstv4lmjpegsink.c: + * sys/v4l/gstv4lmjpegsrc.c: + * sys/v4l/gstv4lsrc.c: + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + * tests/check/elements/audioconvert.c: + * tests/check/elements/playbin.c: + * tests/check/elements/playbin2.c: + * tests/check/elements/textoverlay.c: + * tests/check/libs/cddabasesrc.c: + * tests/check/libs/pbutils.c: + * tests/old/testsuite/alsa/formats.c: + * tests/old/testsuite/alsa/sinesrc.c: + gst_element_class_set_details => gst_element_class_set_details_simple + Also change my email from the old university one to the current one. + +2010-03-15 22:17:56 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + Add -Wundef flag + +2010-03-16 16:15:39 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: allow for more ipv6 addresses + Use hints in getaddrinfo() so that we can also resolve ipv6 addresses. + +2010-03-11 14:52:09 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: arrange for a running ringbuffer/clock for _wait_eos + Fixes #612223. + +2010-03-16 01:08:48 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/videorate.c: + tests: fix videorate test + Fix up videorate test for latest videotestsrc changes: just check for + the important bits in the negotiated caps, not for exact equality with + our filter caps. Also don't leak the videorate element in the test. + +2010-03-15 12:54:32 -0500 Rob Clark <rob@ti.com> + + * gst-libs/gst/riff/riff-media.c: + riff: add mapping for On2 VP7 fourccs + Fixes #612968. + +2010-03-15 12:54:01 -0500 Rob Clark <rob@ti.com> + + * gst-libs/gst/riff/riff-media.c: + riff: add mapping for On2 VP62 fourcc + See #612968. + +2010-03-15 23:46:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/audio.h: + * gst-libs/gst/audio/multichannel.c: + * gst-libs/gst/audio/multichannel.h: + * gst-libs/gst/interfaces/propertyprobe.c: + * gst-libs/gst/interfaces/tuner.c: + * gst-libs/gst/pbutils/install-plugins.c: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtsp/gstrtsptransport.h: + docs: more helper libraries docs fixes + Quieten gtk-doc a bit more. + +2010-03-15 23:47:23 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspextension.c: + docs: add GstRTSPExtension to docs + Add minimal docs for GstRTSPExtension so people know it exists. + +2010-03-15 18:45:13 +0000 David Hoyt <dhoyt@llnl.gov> + + * gst/typefind/gsttypefindfunctions.c: + typefind: use g_ascii_strncasecmp() instead of strncasecmp() + g_ascii_strncasecmp() is more portable and likely more robust as + well (with random binary data as input). + Fixes #612845. + +2010-03-15 13:39:58 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + docs: fix typo in gst_tag_list_from_xmp_buffer() docs chunk + +2010-03-15 13:32:58 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/navigation.c: + * gst-libs/gst/interfaces/xoverlay.c: + * gst-libs/gst/interfaces/xoverlay.h: + docs: fix up interfaces library docs to make gtk-doc happy + +2010-03-15 13:24:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: add new libgstvideo API to documentation + +2010-03-15 13:19:09 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/common/libgstinterfaces.def: + * win32/common/libgstvideo.def: + win32: add recently added API to .def files + Also add API markers to make life easier for the release manager: + API: gst_x_overlay_set_render_rectangle() + API: gst_video_parse_caps_color_matrix() + API: gst_video_parse_caps_chroma_site() + +2010-03-15 13:14:54 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: use C comments instead of C++-style comments + +2010-03-15 13:10:23 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: use g_value_set_static_string() for string constants + +2010-03-15 14:26:28 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Avoid g_object_set() on NULL if a text sink is used + Fixes bug #611702. + +2010-03-15 14:10:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: Correctly escape brackets in DKS regex + Fixes bug #612783. + +2010-03-15 11:36:22 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: make timeout usec more accurate + Adjust the returned usec from the elapsed time so it represents the remaining + timeout. + +2010-03-15 11:41:35 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/check/elements/videorate.c: + tests: update videorate test for videotestsrc changes + Add color-matrix to the caps we are comparing. Add logging og the caps in the + test. + +2010-03-15 01:35:15 -0700 David Schleef <ds@schleef.org> + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: add chroma-zone-plate pattern + pattern=chroma-zone-plate is pattern similar to zone-plate, + but in the chroma channels instead of luma. + +2010-03-15 01:34:09 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoradec.c: + theoradec: add chroma-site to caps + +2010-03-15 01:33:36 -0700 David Schleef <ds@schleef.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: add chroma-site to caps + +2010-03-15 01:31:20 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: add gst_video_parse_caps_chroma_site() + +2010-03-14 19:10:16 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoradec.c: + theoradec: add color-matrix to caps + +2010-03-14 16:17:46 -0700 David Schleef <ds@schleef.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add color-matrix to template caps + +2010-03-14 22:14:19 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/overlay/gtk-xoverlay.c: + * tests/examples/seek/seek.c: + * tests/icles/test-colorkey.c: + * tests/icles/test-xoverlay.c: + tests: make Gtk+ test programs compile with -DGSEAL_ENABLE + Fixes #612552, at least for now. + +2010-03-14 22:13:25 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * Makefile.am: + build: add cruft alert for common/shave* leftovers to top-level Makefile.am + +2010-03-14 13:11:53 -0700 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + oggdemux: Don't drop zero-sized packets + Zero-sized packets have relevence to Theora. + +2010-03-12 15:47:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + volume: Revert rounding behaviour changes when using controlled volume properties + Now the controlled and non-controlled code paths are all having + exactly the same rounding behaviour and the unit tests pass again. + +2010-03-12 15:44:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + volume: Only allocate a mute value array if a control source exists for the mute property + +2010-03-12 13:55:55 +0100 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From e272f71 to 55cd514 + +2010-03-10 10:50:32 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst-libs/gst/tag/gstxmptag.c: + tags: Add new mapping to XMP helpers + Adds geotagging mappings to XMP helpers + Fixes #609539 + +2010-03-11 20:16:44 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/interfaces/Makefile.am: + Don't have 2 include dirs + Seems to have been accidentally introduced in + 7269bc26d0a4bf44bd77a039fb54777625ef5f39. + +2010-03-11 16:35:10 +0100 Edward Hervey <bilboed@bilboed.com> + + * tests/icles/audio-trickplay.c: + tests: Fix another unitialized variable + +2010-03-11 16:09:26 +0100 Edward Hervey <bilboed@bilboed.com> + + * tests/icles/audio-trickplay.c: + tests: Fix unitialized variable. + +2010-03-11 15:38:18 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + * ext/ogg/gstoggdemux.c: + * ext/theora/gsttheoraparse.c: + * ext/vorbis/gstvorbistag.c: + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioquantize.h: + * gst/audioconvert/gstchannelmix.h: + * gst/playback/gstplaysink.c: + Add -Wredundant-decls to warning flags + ... and fix all the warnings that flag throws. + +2010-03-11 13:32:14 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + * ext/ogg/Makefile.am: + * ext/ogg/gstogg.c: + * ext/ogg/gstogg.h: + * ext/ogg/gstoggaviparse.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + * ext/ogg/gstoggparse.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstogmparse.c: + * ext/ogg/vorbis_parse.c: + * ext/ogg/vorbis_parse.h: + * ext/theora/gsttheoradec.h: + * ext/theora/gsttheoraenc.h: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/riff/riff.c: + * gst-libs/gst/rtsp/gstrtspbase64.c: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/tag/lang.c: + * gst/ffmpegcolorspace/Makefile.am: + * gst/ffmpegcolorspace/gstffmpeg.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/gdp/gstgdpdepay.h: + * gst/gdp/gstgdppay.h: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplayback.c: + * gst/playback/gstplayback.h: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + * gst/videorate/gstvideorate.h: + * tests/check/elements/appsink.c: + * tests/check/elements/audiorate.c: + * tests/check/elements/audioresample.c: + * tests/check/libs/cddabasesrc.c: + * tests/check/libs/mixer.c: + * tests/check/libs/navigation.c: + * tests/examples/gio/giosrc-mounting.c: + Add -Wmissing-declarations -Wmissing-prototypes to warning flags + Includes all the fixes necessary to make stuff compile again. + +2010-03-11 12:49:02 +0100 Benjamin Otte <otte@redhat.com> + + * ext/gio/gstgiobasesink.c: + gio: Remove unused function + +2010-03-11 11:14:35 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/vorbis/gstvorbisparse.c: + vorbisparse: make sure header buffer metadata is writable before modifying it + Fixes unit test failures with core git. + +2010-03-11 12:18:00 +0100 Benjamin Otte <otte@redhat.com> + + * tests/check/elements/multifdsink.c: + check: Ref buffers after setting caps on them + Reffing makes metadata unwritable, so we need to set the caps before. + +2010-03-11 12:04:32 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + Add WARNING_CXXFLAGS where ERROR_CXXFLAGS are + This matches the previous commit doing the same for CFLAGS in response + to the common/ module changes. + +2010-03-11 12:04:37 +0100 Edward Hervey <bilboed@bilboed.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2010-03-11 10:38:53 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/icles/test-xoverlay.c: + tests: don't use Gtk+ 2.18 API for no good reason + The rest of the code directly uses widget->allocation as well, so no point + in using the new API in other places. + +2010-03-11 11:20:48 +0100 Benjamin Otte <otte@redhat.com> + + * common: + Automatic update of common submodule + From df8a7c8 to e272f71 + +2010-03-11 10:55:21 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/interfaces/xoverlay.c: + xvoverlay: correct version number in docs + +2010-02-26 13:56:21 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + * tests/icles/audio-trickplay.c: + tests: add a test for trickplay in audio synthesis graphs + Right now this mostly demonstatest what not works. That is seeking with + start-type = NONE to only update the rate and playing backwards. Also + it shows that non-flushing seeks tend to lockup adder. Separate unit tests + for the issues follow. + +2010-02-08 17:20:35 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gstxmptag.c: + * gst-libs/gst/tag/tag.h: + * tests/check/libs/tag.c: + * win32/common/libgsttag.def: + tags: add basic xmp metadata support + XMP metadata can be embedded in many media container formats. Implement own + parser and formatter that can be used to convert between an xpacket and a + GstTagList. Add unit tests. + +2010-02-19 14:38:36 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + * tests/icles/test-xoverlay.c: + example: add an example for xoverlay::set_render_rectangle() + This add a new example which animates a target recangle for the video. + +2010-02-19 14:46:43 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + xvimagesink: implement set_render_rectangle + Previously we hardcoded the target rectangle passes to Xv(Shm)PutImage. Extend + the implementation to use a full rectangle and don't assume 0,0 for top,left. + +2010-02-17 15:00:13 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/xoverlay.c: + * gst-libs/gst/interfaces/xoverlay.h: + xoverlay: add new vmethod ::set_render_rectangle() + Add set_render_rectangle() vmethod to the interface to better support windowless + toolkits (e.g. qt graphicsview or video on canvas in general). Right now we + always fill the widget to 100%. With the patch we can use a rectangular target + region. Fixes #610249. + API: GstXOverlay::set_render_rectangle() + +2010-02-16 12:06:08 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: take new size from event thread and do not poll for every frame + We can update the geometry in ConfigureNotify (unless we disable event- + handling). If event handling is disabled, one should use _expose() to trigger a + redraw and update the geometry. + +2010-03-10 21:51:59 +0100 Benjamin Otte <otte@redhat.com> + + * common: + Automatic update of common submodule + From 9720a7d to df8a7c8 + +2010-03-10 21:01:20 +0100 Benjamin Otte <otte@redhat.com> + + * configure.ac: + Update for recent changes to common submodule + This just replaces every "$ERROR_CFLAGS" usage with a usage of + "$WARNING_CFLAGS $ERROR_CFLAGS" to get the same functionality as + previously. + Actually using that separation will happen later. + +2010-03-10 20:43:46 +0100 Benjamin Otte <otte@redhat.com> + + * common: + Automatic update of common submodule + From 0b6e072 to 9720a7d + +2010-03-10 16:09:45 +0100 Benjamin Otte <otte@redhat.com> + + * common: + Automatic update of common submodule + From 7cc5eb4 to 0b6e072 + +2010-03-10 14:36:34 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: do not cache FLUSH_START/_STOP events + ... and similarly so for serialized events. + +2010-03-10 14:34:57 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: provide correct error message if configured audio/video sink fails + +2010-03-10 10:22:47 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/vorbis/gstvorbisdec.h: + vorbisdec: remove unused field + +2010-02-02 11:34:10 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * tests/check/pipelines/vorbisdec.c: + tests: enable strict discontinuity checking on vorbisdec pipeline + Closes #423086. + +2010-03-10 01:09:31 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 7aa65b5 to 7cc5eb4 + +2010-03-10 01:07:09 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/video/video.c: + docs: fix Returns: for gst_video_parse_caps_color_matrix() + +2010-03-10 00:46:34 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update for changed string + +2010-03-10 00:42:15 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/videorate.c: + tests: fix typo in videorate unit test pipeline description + Two consecutive ! ! leave a 'Link without source' error in the debug log. + +2010-03-10 00:41:13 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/videorate.c: + tests: don't use deprecated functions in videorate unit test + +2010-03-10 00:29:21 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/common/libgstvideo.def: + win32: add new API to libgstvideo.def + +2010-03-09 15:39:55 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggmux.c: + oggmux: Don't flush after every frame for theora + +2010-03-09 21:26:58 +0000 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 44ecce7 to 7aa65b5 + +2010-03-09 13:05:23 -0800 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add color-matrix handling to caps + +2010-01-30 22:55:01 -0800 David Schleef <ds@schleef.org> + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: Add color-matrix to caps + +2010-02-26 16:25:59 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + * pkgconfig/Makefile.am: + * tests/examples/overlay/Makefile.am: + * tools/Makefile.am: + build: Make some more rules silent if requested + +2010-02-26 15:40:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + configure: Use automake 1.11 silent rules instead of shave if available + This makes sure that we use something that is still maintained and + also brings back libtool 1.5 support. + +2010-02-23 19:12:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Don't fail if there are subtitles and audio but no video + Change playbin2 to not error out if there are subtitles and audio + but no video. If visualizations are enabled the subtitles are rendered on top + of the visualization stream, otherwise the subtitles are not linked at all and + only the audio is played (and a warning message is posted). + If there are only subtitles but neither audio nor video an error message is + still posted. + Fixes bug #610866. + +2010-02-17 19:18:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + * gst/volume/gstvolume.h: + volume: If a controller is used, use sample accurate property values + Fixes bug #609801. + +2010-03-09 19:17:04 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/video/video.c: + gstvideo: Fix typos in comments + +2010-03-09 17:32:25 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/_stdint.h: + * win32/common/config.h: + Back to development + +=== release 0.10.28 === + +2010-03-08 23:20:43 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.28 + +2010-03-08 23:19:57 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2010-03-08 21:57:03 +0100 Benjamin Otte <otte@redhat.com> + + * ext/theora/gsttheoraenc.c: + theora: Fix SIGFPE when using 0/1 framerate + libtheora crashes with a 0 framerate, so let's forbid it. + https://bugzilla.redhat.com/show_bug.cgi?id=571289 + +2010-03-08 14:50:25 +0000 David Schleef <ds@schleef.org> + + * ext/ogg/dirac_parse.c: + oggdemux: fix dirac header parsing + Fixes #611900. + +2010-03-08 14:46:17 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/overlay/Makefile.am: + examples: make sure to dist qtgv-xoverlay.h header file + This time for real. + Fixes #610832. + +2010-03-08 12:11:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basedepay: clarify some documentation + +2010-03-08 11:25:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/alsa/gstalsasrc.c: + alsasrc: return right number of bytes that we wrote + +2010-03-08 11:20:51 +0100 Dake Gu <gudake@gmail.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: fix handling of x-server-ip-address + Fix handling of x-server-ip-address. + +2010-03-02 11:25:31 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/design/draft-keyframe-force.txt: + docs: update keyframe force event + Add field to send all headers. + +=== release 0.10.27 === + +2010-03-06 00:09:29 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.27 + +2010-03-06 00:08:23 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2010-03-05 15:58:44 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: first check for QtGui >= 4.6, only then for >= 4.0 + If we first check for >= 4.0 the second check for >= 4.6 will just + short-cut since we are using the same prefix for the variables for + both checks, and they've already been set previously. So the examples + requiring >= 4.6 were built even in the >= 4.0 case. + +2010-03-03 20:18:16 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.26.4 pre-release + +2010-03-03 20:17:31 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/ja.po: + po: update translations + +2010-03-03 20:15:44 +0000 Josep Torra Valles <n770galaxy@gmail.com> + + * gst/playback/gstplaysink.c: + playsink: avoid g_object_set() on NULL pointers + There may not be an overlay element if a text-sink is set. + Fixes #611702. + +2010-03-01 12:17:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: mark skeleton streams correctly + Mark skeleton streams because we need to ignore them for calculating the + duration of the stream. + Fixes #611227 + +2010-02-24 01:10:09 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * po/nl.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.26.3 pre-release + +2010-02-23 16:57:53 +0100 Götz Waschk <waschk@mandriva.org> + + * tests/examples/overlay/Makefile.am: + examples: Dist header file for the Qt graphics view example + Fixes bug #610832. + +2010-02-23 11:41:20 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: use the chain begin_time instead of our counter + We update the passed begintime argument to narrow our search region in the + binary search. This means that it does not always contain the chain begin time + after a couple of bisects. Use the real chain->begin_time to bring the + granuletime to the time in the chain instead. + Fixes #610005 + +2010-02-19 18:24:40 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * tests/check/elements/videorate.c: + videorate: tests: New unit tests for upstream caps nego + Adds unit tests that check videorate's upstream caps + negotiation works properly (put passthrough caps + first) + Fixes #608025 + +2010-01-27 15:07:47 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: Improve upstream negotiation + Put peer pad caps preferred framerates first, indicating + they are videorate's first choices, removing an unnecessary + conversion. + Fixes #608025 + +2010-02-21 19:52:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + playbin2, playsink, subtitleoverlay: Set subtitle encoding properly + For this add subtitle encoding properties to playsink and subtitleoverlay + and update the values in the containing elements. + Also update the font description in textoverlay or the used renderer + element if it is changed during playback. + Fixes bug #610310. + +2010-02-22 13:01:19 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/examples/overlay/gtk-xoverlay.c: + * tests/examples/overlay/qt-xoverlay.cpp: + * tests/examples/overlay/qtgv-xoverlay.cpp: + examples: also add sink detection and set title to qt examples + Also set a title in the qt examples like it is now done in the gtk example. + Fix the newly added find_video_sink in the gtk example and add similar function + to the qt examples. + +2010-02-19 14:40:43 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/examples/overlay/.gitignore: + gitignore: ignore files in new example directroy + +2010-02-17 14:59:33 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/video/Makefile.am: + make: fix copy and paste error in git rules (audio<->video) + +2010-02-19 17:44:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Ghost the video sinkpad if a text sinkpad is available + Only don't ghost it if no visualizations are need and if + no text is needed and no textchain was created yet. + Fixes bug #610379. + +2010-02-19 00:22:13 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.26.2 pre-release + +2010-02-19 00:20:02 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translation files + +2010-02-19 00:17:51 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/overlay/.gitignore: + Ignore new overlay examples + +2010-02-18 23:47:35 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/overlay/gtk-xoverlay.c: + examples: don't hard-code xvimagesink for Gtk+ GstXOverlay example + Try to find a working videosink, don't hardcode xvimagesink. Also + add some borders to window and give it a title so that it's clear + that this is really a Gtk+ window and not a window created by the + videosink. + +2010-02-18 11:42:55 -0800 David Schleef <ds@schleef.org> + + * gst/tcp/gsttcp.c: + tcp(client/server)src: Fix handling of closed sockets + The peer closing the socket should cause an EOS, instead of + silently doing nothing. This changes the behavior to be + more like fdsrc. Fixes: #610386 + +2010-02-18 12:42:53 +0000 Patrick Radizi <patrick.radizi@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: make sure not to dereference NULL username or password + Fixes #610268. + +2010-02-17 21:22:54 -0800 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoradec.c: + theoradec: Fix chroma copying for 4:2:2 + Fix mixup of height/width, causing only half the chroma lines to + be copied when outputting buffers. Fixes: #610329. + +2010-02-16 15:43:26 +0200 Stefan Kost <ensonic@users.sf.net> + + * configure.ac: + * gst-libs/gst/interfaces/xoverlay.c: + * tests/examples/Makefile.am: + * tests/examples/overlay/Makefile.am: + * tests/examples/overlay/gtk-xoverlay.c: + * tests/examples/overlay/qt-xoverlay.cpp: + * tests/examples/overlay/qtgv-xoverlay.cpp: + * tests/examples/overlay/qtgv-xoverlay.h: + examples: add video overlay examples for gtk, qt and qt graphics view + Add simple videotestsrc ! xvimagesink examples using gtk and qt. This patch also + adds all boilerplate to configure for using c++. The qt based examples are + optional like their gtk counterparts. + +2010-02-16 17:20:01 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/compiling.sgml: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: cleanup library docs + Correct name of included files. Remove files that are not used anymore. Add many + new api entries to their sections. + +2010-02-15 11:11:04 +0200 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/test-colorkey.c: + test-colorkey: remove the XInitThreads() + We don't do this is any other example, this should be done for us in gdk it if + would be needed. + +2010-02-16 10:09:54 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: use same message string for missing elements as in playbin + Use the same translated message string for missing core elements as + playbin uses, which is a bit nicer and also indicates that there is + something wrong with the user's GStreamer installation (which arguably + is the case if elements like typefind or queue2 are missing). + +2010-02-08 13:54:57 +0200 Kaj-Michael Lang <milang@tal.org> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Handle stm module format + Fixes #609314. + +2010-02-15 12:10:10 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/vorbis/gstivorbisdec.c: + ivorbisdec: set rank to SECONDARY + +2010-02-15 12:09:53 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * configure.ac: + * ext/Makefile.am: + * ext/vorbis/Makefile.am: + * ext/vorbis/gstivorbisdec.c: + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisdec.h: + * ext/vorbis/gstvorbisdeclib.c: + * ext/vorbis/gstvorbisdeclib.h: + vorbisdec: also support ivorbis tremor decoder + ... which only needs a bit of refactoring and extracting to support + the minor difference in (i)vorbis interface. + Fixes #609063. + +2010-02-03 14:37:43 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisdec.h: + vorbisdec: reduce some hard-coding + ... such as assuming float all over, and base src caps on template caps. + +2010-02-15 10:23:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/playbin.c: + playbin: Fix the primary-decoder-missing test with USE_DECODEBIN2 + +2010-02-15 09:04:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggparse.c: + oggparse: Fix another format string compiler warning + +2010-02-15 08:56:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Fix format string compiler warnings + +2010-02-15 08:48:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Post a missing element message and an error message if no uridecodebin can be found + +2010-02-15 08:46:26 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Post missing element messages if a core plugin is missing + And post a warning in cases where we can still continue to work + or an error when the missing element is fatal. + +2010-02-15 08:28:24 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/playbin2.c: + playbin2: Enable all unit tests + They're all working and valgrind clean now. + +2010-02-15 08:26:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: First post a missing-plugin message, then emit the unkown-type signal + This makes sure that there *always* is a missing plugin message in the bus + before any errors or warning messages. + +2010-02-15 08:20:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Missing decoder errors should be STREAM CODEC_NOT_FOUND + and not CORE MISSING_PLUGIN. + +2010-02-15 08:18:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Free the subtitle URI + +2010-02-15 08:06:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Post missing plugin messages if a required element can't be created + Especially if no suitable URI source can be found. + +2010-02-15 06:50:29 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/.gitignore: + tests: Add decodebin2 test to .gitignore + +2010-02-15 01:18:55 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Set ghostpad targets to NULL when freeing a decode chain + Otherwise the ghostpad will still be linked to the peer and there + will still be a reference kept, leading to nothing being unlinked + and destroyed until decodebin2 is finalized. + This fixes reuse of decodebin2 if a raw stream is connected to + its sinkpad. + +2010-02-15 01:17:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/Makefile.am: + * tests/check/elements/decodebin2.c: + decodebin2: Add simple unit test, mainly a copy of the decodebin unit test + The only difference between the two unit tests right now is, + that the decodebin2 test resets the element to READY before trying + to reuse it instead of NULL. decodebin2 guarantees to be reusable + without going back to NULL. + +2010-02-15 00:11:17 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: theora PAR of 0:N, N:0 or 0:0 is allowed and maps to 1:1 + See #609252. + +2010-02-14 23:16:32 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 96dc793 to 44ecce7 + +2010-02-14 23:10:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/Makefile.am: + playbin2: Enable playbin2 unit test + It now contains a single working unit test and can be enabled. + The other more useful unit tests still need fixing. + +2010-02-14 22:16:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/playbin.c: + playbin: Fix indention in the unit test + +2010-02-13 01:08:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + volume: Replace this variables by self + +2010-02-12 19:43:13 +0100 Josep Torra Valles <n770galaxy@gmail.com> + + * gst/playback/gstplaysink.c: + playsink: Reset the sink's state to NULL before unreffing it unless it's the same instance again + This makes sure that we don't destroy the last reference before the + element gets back to NULL state. Fixes assertion failures if a playbin2 + instance is reused but different sinks are automatically chosen because + of different caps. + +2010-02-12 18:00:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: fix Since tag + +2010-02-12 14:19:33 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/riff/riff-read.c: + riff: treat JUNQ chunks like JUNK chunks + +2010-02-12 14:29:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Update basesrc segment duration and post duration messages from the streaming thread + +2010-02-11 14:10:02 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/tag/tags.c: + tags: improve docs about determining the encoding + +2010-02-11 14:09:05 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/tag/gstvorbistag.c: + comment: fix wrong header comment + +2010-02-01 13:50:14 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/riff/riff-ids.h: + riff: add a variant of the JUNK tag that several adobe products produce + JUNQ has same semantics as JUNK. + +2010-02-01 19:01:33 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: add min-percent property + Emit need-data when the amount of data in the internal queue drops below + min-percent. + Fixes #608309 + +2010-02-01 18:56:34 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: cleanups + Avoid some typechecks. + Avoid dereferencing appsrc->priv all the time. + +2010-02-01 18:55:39 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsink.c: + appsink: cleanups + Avoid some typecasting. + Avoid dereferencing appsink->priv all the time. + +2010-02-01 15:09:56 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: avoid some typecasts + +2010-01-29 16:34:44 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: ignore \n and \r as the first line + Be more forgiving for bad servers and ignore \r and \n when we are looking for + the response/request line. + See #608417 + +2010-02-10 16:05:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: fail gracefully on bad Content-Length headers + Be careful when allocating the amount of bytes specified in the Content-Length + because it can be an insanely huge value. Try to allocate the memory but fail + gracefully with a nice error when the allocation failed. + +2010-02-10 10:12:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add conversions from all ARGB formats to AYUV and back + +2010-02-09 17:39:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Update segment duration and post a duration message if the duration changes + Fixes bug #609423. + +2010-02-11 10:56:17 +0100 Benjamin Otte <otte@redhat.com> + + * tests/examples/seek/Makefile.am: + build: link to libm in examples that use it + This fixes build failure in Fedora 13. + +2010-02-11 01:11:30 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * MAINTAINERS: + Update MAINTAINERS, add myself + +2010-02-11 23:57:38 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: back to development + Slushy freeze remains in effect. + +=== release 0.10.26 === + +2010-02-10 20:17:36 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.26 + +2010-02-10 20:16:37 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2010-02-08 11:21:35 +0100 Benjamin M. Schwartz <bens@alum.mit.edu> + + * ext/theora/gsttheoradec.c: + theoradec: PARs of 0:x, x:0 and 0:0 are all allowed and map to 1:1 + Fixes #609252. + +2010-01-24 12:31:04 +0000 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> + + * ext/ogg/gstoggstream.c: + oggdemux: use the default granpos functions for kate streams + Set timestamps on kate packets. See bug #600929. + +2010-02-05 01:18:43 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.25.3 pre-release + +2010-02-04 18:52:59 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/bg.po: + po: update translations + +2010-02-04 18:32:48 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + Revert "playbin2: Only allow to set the URIs in states <= READY or from an about-to-finish signal handler" + This reverts commit 7335ce5d3e03c126a417a721571cb6f3af136ecf. + Support abusing the uri property to configure the next uri to play + outside of the about-to-finish handler for the time being after all. + We also shouldn't use thread private structures for this, since it + should be possible to block the thread that emitted about-to-finish + while the main thread sets the uri property. See #607226. + +2010-02-02 10:18:05 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Don't leak allocated buffers + This can happen if the combined flow return is not OK although the + allocation succeeded or if the packet in question is a BOS and we're + not going to push headers. + Fixes bug #608699. + +2010-02-01 11:44:34 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: clean up decodebin properties + When reusing a decodebin2 element, clear the properties we might have changed, + to their default values or else we might end up with old configuration. + Fixes #608484 + +2010-01-29 13:56:05 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: when no uri is set, post an error message + When no uri is set, don't just return STATE_CHANGE_FAILURE from the + state change function, but actually post an error message. + +2010-01-30 15:18:13 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 15d47a6 to 96dc793 + +2010-01-28 17:12:34 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: don't hold object lock when calling peer elements + Do not hold the object lock while we call methods on peer elements as this can + lead to deadlocks. + Fixes #608179 + +2010-01-27 01:12:49 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + 0.10.25.2 pre-release + +2010-01-27 01:07:55 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/interfaces-enumtypes.c: + * win32/common/interfaces-enumtypes.h: + * win32/common/pbutils-enumtypes.c: + * win32/common/video-enumtypes.c: + win32: update generated files for non-autotools win32 builds + +2010-01-27 00:56:00 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translation files + +2010-01-27 00:41:24 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosrc.c: + audiosrc: add gratuitious FIXME for use of generic G_TYPE_POINTER type + +2010-01-26 16:47:40 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't skip an element when getting the topology + Fixes #608167 + +2010-01-24 14:41:44 +0000 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> + + * ext/ogg/gstoggdemux.c: + oggdemux: sparse streams aren't timed by end time, and their duration isn't implicit + Fixes timestamps and durations on Kate subtitle streams. + See http://www.xiph.org/ogg/doc/ogg-multiplex.html section 'start-time and + end-time positioning' for some more details, and bug #600929. + +2010-01-23 20:15:08 +0000 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> + + * ext/ogg/gstoggstream.c: + oggdemux: properly set up the media type for kate streams + See #600929. + +2010-01-25 18:57:52 +0100 Julien Moutte <julien@fluendo.com> + + * gst/playback/gstsubtitleoverlay.c: + subtitleoverlay: relax caps template on sink pads + Allow any caps on sink pad templates as we could do passthrough with non raw + video caps. + +2010-01-25 15:14:56 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.h: + oggdemux: use right type for the serialno + Use a consistent type for the serialno to avoid problems when comparing between + signed and unsigned variants. + Fixes #607926 + +2010-01-25 14:00:52 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: don't push headers twice + Don't push the stream headers twice but only in the activation of a chain. + Fixes #607929 + +2010-01-25 13:18:18 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-base + +2010-01-25 12:31:24 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: rename a variable + Rename the 'seekable' variable to 'pullmode'. We might be able to seek in push + mode too eventually. + +2010-01-25 12:22:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + Revert "inputselector: Protect g_object_notify() with the object's mutex" + This reverts commit a37426c41c80fd21e5017fea01a786c05bcd9661, it's + causing deadlocks with playbin2. + +2010-01-24 20:55:26 +0100 Kipp Cannon <kcannon@ligo.caltech.edu> + + * gst/playback/gstinputselector.c: + inputselector: Protect g_object_notify() with the object's mutex + This works around the thread unsafety of g_object_notify() + Fixes bug #607513. + +2010-01-24 20:46:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add typefinder for ISO MP4 files + Fixes bug #607848. + +2010-01-24 13:29:07 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix crash when freeing headers + Use _ogg_packet_free() instead of gst_mini_object_unref in one more + place now that the header list contains ogg packets and not buffers. + file: Stephen_Fry-Happy_Birthday_GNU-nq_600px_425kbit.ogv + +2010-01-24 08:57:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Strip trailing \0 for subtitle OGM streams + Fixes bug #607870. + +2010-01-23 22:09:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Correctly set DELTA_UNIT flag for OGM streams + +2010-01-23 22:05:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Don't strip all 0-bytes from the end of OGM packets + This fixes broken packets pushed downstream by oggdemux for + MPEG4 streams for example. + +2010-01-23 22:03:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Extract tags from OGM text streams and don't push them downstream + +2010-01-23 14:46:19 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Store header/queued packets as ogg_packet and use normal peer chaining functions to pass them downstream + +2010-01-23 15:25:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: optimise AC-3 typefinder a bit + Make AC-3 typefinder use the DataScanCtx stuff so we don't have to + do gst_type_find_peek() in the inner loop all the time. Also return + when we've suggested AC3 caps, instead of continuing with the loop. + +2010-01-23 14:31:15 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + Revert "typefind: Reduce number of calls to gst_type_find_peek." + This reverts commit c661bfaa991c58f1fbd9fbc0dae90b8b2c27f92b. + This breaks AC-3 typefinding for all cases where the first frame + is at an offset > 0. + +2010-01-23 15:35:05 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for Zip Block Motion Video + +2010-01-23 15:34:54 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add mapping for Zip Block Motion Video + +2010-01-23 15:26:37 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: YUNV is a fourcc which is also used for YUY2 raw video + +2010-01-23 15:13:45 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: vp61 and VP61 are also valid On2 VP6 fourcc + +2010-01-23 15:10:45 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add mapping for On2 VP5 + +2010-01-23 15:04:35 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add mapping for Sigma-Designs MPEG4 + It's actually a xvid-compatible stream. both xviddec and ffmpeg handle it. + +2010-01-23 14:35:28 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for LOCO Lossless codec + +2010-01-23 14:35:16 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add mapping for LOCO Lossless codec + +2010-01-23 14:08:39 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add support for YV12 / Uncompressed packed YVU 4:2:2 + +2010-01-23 13:50:26 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for Autodesk Animator codec + +2010-01-23 13:50:09 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add mapping for Autodesk Animator Codec + +2010-01-23 13:20:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: ...and set caps on queued packet buffers too + +2010-01-23 13:19:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Set caps on header buffers + +2010-01-22 16:23:43 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: handle raw sources about-to-finish signals + When we are dealing with a source that produces raw audio/video, we don't use a + decodebin2 to decode the data and we thus don't have the drained/about-to-finish + signal emited. To fix this, we add a padprobe on the source pads and emit the + drained signal ourselves. This then makes playbin2 emit the about-to-finish + signal for raw sources such as cdda:// + Fixes #607116 + +2010-01-22 16:15:54 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/typefind/gsttypefindfunctions.c: + typefind: include stdio.h for sscanf + +2010-01-22 01:49:38 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: add PNM typefinder + Add PNM typefinder, so we can remove the one that's in the PNM plugin + in -bad (which btw uses different/wrong media types that don't match + the ones used by gdkpixbufdec) and people don't make fun of us for + loading image decoders when typefinding and playing back audio files. + +2010-01-21 19:31:23 +0100 Thijs Vermeir <thijsvermeir@gmail.com> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: rename performance category + rename the performance category to ffmpegcolorspace_performance + as there is already a global GST_CAT_PERFORMANCE in core + +2010-01-21 17:32:33 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: keep track of added pads + Keep track of the pads we added and removed. + Remove some unused fields. + Don't add pads for which we don't have caps. + +2010-01-21 17:31:13 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: don't call NULL setup functions + If we find a known mapper but it doesn't have a setup function, simply skip it + instead of crashing. + +2010-01-21 17:30:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggstream: avoid division by 0 on bad annodex streams + +2010-01-21 13:47:01 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for y4m container + +2010-01-19 14:31:34 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppayload: ptime/maxptime should be unsigned + https://bugzilla.gnome.org/show_bug.cgi?id=607403 + +2010-01-18 21:16:32 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + basertppayload: ptime should be in nanoseconds + https://bugzilla.gnome.org/show_bug.cgi?id=607403 + +2010-01-20 00:53:20 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 14cec89 to 15d47a6 + +2010-01-19 13:33:06 -0800 David Schleef <ds@schleef.org> + + * gst/typefind/gsttypefindfunctions.c: + typefind: rewrite h.264 detection + Make detection simpler: check for NALs, check that they make + sense, and report how certain we are that it's a raw H.264 stream. + Fixes: #583376. + +2010-01-18 14:33:30 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppayload: Reject empty caps + https://bugzilla.gnome.org/show_bug.cgi?id=607353 + +2010-01-19 08:39:14 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: No need to subtract begin time + Last stop is already based on the chain start and there is no need + to subtract the chain start as it may lead to a negative overflow. + This was causing seeking issues when the target chain was not + the first one (that has chain start = 0) + Fixes #606382 + +2010-01-19 09:25:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/audio.h: + audio: Use rounding scaling functions for GST_CLOCK_TIME_TO_FRAMES and _FRAMES_TO_CLOCK_TIME + Fixes bug #607381. + +2010-01-18 15:22:52 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: granulepos is relative to its chain + When performing seeks, the granulepos should be offset by + its chain start time to avoid using wrong values to + update segment's last_stop. A sample file is indicated on + bug #606382 + +2010-01-18 17:57:16 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for MXF container format + +2010-01-18 10:07:30 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: re-use iterator callback to avoid code duplication + +2010-01-18 02:08:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: when looking for sink properties, make sure they have the right type + We don't want to end up setting values on elements where the property is of + a different type than we expect. Can't transform the value either, since we + can't really make assumptions about the scale and transform function. + Fixes crashes when using playbin2 with apexsink (#606949). + +2010-01-18 09:30:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Only allow to set the URIs in states <= READY or from an about-to-finish signal handler + Changing the URIs in a state > READY results in unexpected behaviour, + i.e. the new URIs are only used after the current track has finished. + Fixes bug #607226. + +2010-01-15 19:52:29 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: sprinkle some more locking + ... to avoid races and ensure some data structure consistency. + See also #574289. + +2010-01-14 18:26:03 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: mind blocked pads when shutting down + Fix regression in shutdown deadlock handling now that the + target of a ghostpad is blocked instead of ghostpad itself. + See also #574293. + +2010-01-14 13:36:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Fix disabling of subtitles if subtitles were used before + In this case the video still goes through the text chain and + subtitles are still going in there, in case subtitles are + enabled again. This makes sure that re-enabling subtitles + happens instantly. + Fixes hanging video when disabling subtitles, caused by an + unliked video pad. + +2010-01-14 10:43:59 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: fix pad ref leak + +2010-01-12 21:42:59 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * docs/plugins/Makefile.am: + docs: fix out-of-source build + +2009-04-29 11:50:03 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * tests/icles/stress-playbin.c: + stress-playbin: fix error return check + +2010-01-14 10:10:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/Makefile.am: + * ext/theora/gsttheora.c: + * ext/theora/gsttheoradec.c: + * ext/theora/gsttheoraenc.c: + * ext/theora/gsttheoraparse.c: + * ext/theora/theora.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/theora/theoraparse.c: + theora: Rename source files to have the same name as the headers + +2010-01-14 10:07:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/vorbis/Makefile.am: + * ext/vorbis/gstvorbis.c: + * ext/vorbis/gstvorbisdec.c: + * ext/vorbis/gstvorbisenc.c: + * ext/vorbis/gstvorbisparse.c: + * ext/vorbis/gstvorbistag.c: + * ext/vorbis/vorbis.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisparse.c: + * ext/vorbis/vorbistag.c: + vorbis: Rename source files to have the same name as the headers + +2010-01-14 10:05:35 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/vorbis/Makefile.am: + * ext/vorbis/gstvorbiscommon.c: + * ext/vorbis/gstvorbiscommon.h: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + vorbis: Move channel layout definitions into a single separate file + ...instead of having two copies. + +2010-01-14 08:19:55 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + vorbis: Add official 6.1 and 7.1 channel mappings + These are in the Vorbis spec since 2010-01-13. Fixes bug #606926. + +2010-01-13 23:05:45 +0100 Benjamin Otte <otte@redhat.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + rtsp: Don't define h_error ourselves + It's included from netdb.h and that header might define it differently, + which can lead to build failures. + +2010-01-13 17:36:05 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: mp4 video is not parsed + +2010-01-13 12:49:20 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Add aac stream-format to caps + Also add the aac stream-format field on the caps when + detecting it. + +2010-01-13 09:39:54 +0100 Brijesh Singh <brijesh.ksingh@gmail.com> + + * gst/playback/gstplaysink.c: + playsink: Fix handling of the native audio/video flags + Fixes bug #606687. + +2010-01-12 16:35:50 +0100 Edward Hervey <bilboed@bilboed.com> + + * ext/ogg/gstoggdemux.c: + oggdemux: Fix unitialized variable. + If the package isn't handled, gracefully return GST_FLOW_OK. + +2010-01-10 23:50:02 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/xoverlay.c: + docs: flesh out GtkXOverlay docs some more and add example for Gtk+ >= 2.18 + Explain why the whole bus sync handler mess is needed. Add section about + how to use GstXOverlay in connection with Gtk+ and mention the Gtk+ API + break issue and how to work around it (see #601809). + +2010-01-10 21:18:04 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/netbuffer/gstnetbuffer.c: + docs: minor netbuffer documentation fix + +2010-01-10 20:41:53 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update translated strings + Queue2 moved into core, so remove its strings. + +2010-01-08 16:57:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.h: + oggdemux: push headers when activating chains + Keep a list of headers for each stream of a chain. When a chain is activated, + push the headers before pushing the data so that decoders can sync. + Fix seeking in chains, take the chain start time into account when comparing + timestamps. + See #606382 + +2010-01-07 15:26:57 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/lang-tables.c: + * gst-libs/gst/tag/lang-tables.dat: + * gst-libs/gst/tag/lang.c: + tag: fix up disting of lang-tables.c more correctly + lang-tables.c is included by lang.c and not really a proper source + file that should be compiled into its own object, so rename it to + lang-tables.dat and put it into EXTRA_DIST instead to ensure it + gets disted. + +2010-01-07 13:50:03 +0000 Christian Schaller <christian.schaller@collabora.co.uk> + + * gst-libs/gst/tag/Makefile.am: + * gst-plugins-base.spec.in: + Add missing source file for tagger to Makefile and update spec file + +2010-01-06 18:30:57 -0800 Mark Yen <mook@songbirdnest.com> + + * gst-libs/gst/riff/riff-media.c: + riff-media: handle 32 bit raw RGB video. + +2010-01-06 13:57:51 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: decide flac header packet by content rather than count + +2010-01-06 13:56:26 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: reset header packet count at bos page + +2010-01-06 13:39:14 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiopayload: add support for buffer-lists + +2010-01-06 11:33:03 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-base + +2010-01-05 17:17:58 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Ignore zero framerate + https://bugzilla.gnome.org/show_bug.cgi?id=606163 + +2009-12-29 18:45:32 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + basertpaudiopayload: Respect ptime if it is given + If the ptime is given in the caps, respect it and force the minimum + and maximum sizes to be exactly the requested ptime. + https://bugzilla.gnome.org/show_bug.cgi?id=606050 + +2009-12-29 18:36:29 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + rtpbasepayload: Store ptime from caps + https://bugzilla.gnome.org/show_bug.cgi?id=606050 + +2009-12-02 19:40:58 +0530 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppayload: Accept maxptime from caps + https://bugzilla.gnome.org/show_bug.cgi?id=606050 + +2010-01-05 14:11:06 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + oggdemux: enhance flac packet duration calculation + +2010-01-05 10:38:41 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-base + +2010-01-04 09:49:25 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/seek/seek.c: + * tests/icles/test-colorkey.c: + examples: use Gtk+-2.18 API conditionally + so the seek example and colorkey test work with older Gtk+ versions + as well. + Fixes #605960. + +2009-12-29 00:53:53 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/icles/test-colorkey.c: + tests: fix colorkey test up for Gtk+ >= 2.18 + Make test-colorkey work with newer versions of Gtk+. + See #601809. + +2009-12-29 00:40:27 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/seek/seek.c: + examples: make seek example work with Gtk+ >= 2.18 + Gtk+ broke API slightly with the introduction of + client-side windows in Gtk+ 2.18. Fix up seek + example to work with newer Gtk+ versions. + Fixes #601809. + +2009-12-26 23:29:24 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/icles/stress-xoverlay.c: + tests: fix warning and memory leak in stress-overlay test + Not all messages have structures and we need to unref messages + when returning GST_BUS_DROP in the sync bus handler. + +2009-12-26 18:46:50 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: correctly eat empty and dummy buffers + +2009-12-24 19:56:55 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: be a lot smarter with buffer management + Detect EOS faster. + Try to reuse one of the input buffer as the output buffer. This usually works + and avoids an allocation and a memcpy. + Be smarter with GAP buffers so that they don't get mixed or cleared at all. Also + try to use a GAP buffer as the output buffer when all input buffers are GAP + buffers. + +2009-12-24 16:30:23 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/Makefile.am: + * gst/adder/gstadder.c: + * tests/check/elements/adder.c: + adder: use collectpads clipping function + Install a clipping function in the collectpads and use the audio clipping helper + function to perform clipping to the segment boundaries. + Fixes #590265 + +2009-12-24 13:58:52 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: fix juvenile comment + +2009-12-23 21:24:48 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: fix typo in debug message + +2009-12-23 18:18:03 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: avoid some type checks + +2009-12-23 17:08:27 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: avoid leaking selector request pads + +2009-12-23 15:46:25 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: avoid leaking queue and typefind + Don't leak the queue and typefind elements that we might link after the + source element. + +2009-12-23 15:43:52 +0100 Jonathan Matthew <jonathan@d14n.org> + + * gst/playback/gsturidecodebin.c: + uridecodebin: don't name the queue + There is no reason to name the queue. + Fixes #605219 + +2009-12-23 15:30:50 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstrtp.def: + defs: update defs with new symbols + +2009-12-22 20:15:28 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + * gst-libs/gst/rtp/gstrtcpbuffer.h: + rtcpbuffer: add helper functions for SDES types + Add functions to convert SDES names to their types and back. Will be used later + to set SDES items using a GstStructure. + See #595265 + +2009-12-21 19:12:02 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * common: + Automatic update of common submodule + From 47cb23a to 14cec89 + +2009-12-21 18:45:58 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: add Since marker for the new tolerance property + +2009-12-21 07:57:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/lang.c: + docs: use 'Returns: xyz' rather than 'Returns xyz' to make gtk-doc happy + +2009-12-21 07:50:26 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/examples/app/appsrc-ra.c: + * tests/examples/app/appsrc-seekable.c: + * tests/examples/app/appsrc-stream.c: + * tests/examples/app/appsrc-stream2.c: + tests: don't use deprecated GLib API g_mapped_file_free + Fixes #605100. + +2009-12-20 17:34:46 -0800 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theoraenc: Add encoder controls for libtheora 1.1 + Added drop-frames, cap-overflow, cap-underflow, and rate-buffer. + +2009-12-19 21:40:44 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: increase default drift tolerance to fix glitches with WMA + Increase default drift tolerance to 40ms to avoid glitches with decoders + or formats where there's a lot of timestamp jitter for some reason or + another (in this case: asf/wma), at least until we implement timestamp + smoothing. + +2009-12-16 11:43:27 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: add some debugging + +2009-12-15 18:41:38 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + * gst/audiorate/gstaudiorate.h: + audiorate: add a tolerance property + It may not be uncommon for the input timestamps to experience some jitter + around the 'perfect time'. As such, instead of regularly adding and dropping + samples, optionally allow for some tolerance in a more relaxed approach. + API: GstAudioRate:tolerance + +2009-12-15 19:50:56 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * gst/audiorate/gstaudiorate.c: + audiorate: add documentation + +2009-12-15 16:52:44 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/Makefile.am: + * gst/audiorate/gstaudiorate.c: + * gst/audiorate/gstaudiorate.h: + audiorate: use separate header file + +2009-12-14 21:17:57 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: set DISCONT when resyncing (e.g. newsegment) + +2009-12-14 18:47:27 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: also fill up segments if possible + +2009-12-15 19:29:29 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: fix segment handling + Do not compare a media (buffer) time to a (bogus) running time + (or their offset equivalents). + +2009-12-15 19:22:45 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/audiorate/gstaudiorate.c: + audiorate: properly report truncated samples as dropped samples + +2009-12-13 18:43:56 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/lang.c: + docs: mention that gst_tag_get_language_name() may return NULL + +2009-12-13 18:42:11 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/libs/tag.c: + checks: some more testing for the new language code functions + +2009-12-12 18:58:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/interfaces/mixeroptions.c: + * gst-libs/gst/interfaces/mixertrack.c: + docs: misc. mixer docs improvements + +2009-12-12 18:16:39 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + docs: add short descriptions for API reference contents page + +2009-12-12 17:43:26 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/lang-tables.c: + * gst-libs/gst/tag/mklangtables.c: + tag: make internal language names table static + +2009-12-12 17:41:44 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/lang.c: + * gst-libs/gst/tag/mklangtables.c: + tag: don't use GLib 2.22 API + g_mapped_file_unref() was introduced in GLib 2.22, but we depend + only on GLib 2.18, so use g_mapped_file_free() when compiling + against older GLib versions until we bump the GLib dependency. + +2009-12-11 23:59:54 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + * configure.ac: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/lang-tables.c: + * gst-libs/gst/tag/lang.c: + * gst-libs/gst/tag/mklangtables.c: + * gst-libs/gst/tag/tag.h: + * tests/check/libs/tag.c: + * win32/common/libgsttag.def: + tag: add some utility functions for language codes and tags + Add some utility functions for language tags and ISO-639 + codes. These are useful for both GUIs and elements. The + iso-codes package is used for language name translations + if available. + API: gst_tag_get_language_codes() + API: gst_tag_get_language_name() + API: gst_tag_get_language_code() + API: gst_tag_get_language_code_iso_639_1() + API: gst_tag_get_language_code_iso_639_2B() + API: gst_tag_get_language_code_iso_639_2T() + +2009-12-11 12:02:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: ogm video has constant packet duration + +2009-12-10 22:47:53 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggstream.c: + oggdemux: implement old fLaC mapping + +2009-12-10 17:53:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/tcp/gsttcpclientsrc.c: + tcpclientsrc: unset flushing state too + When unlocking, we set the flushing state on the fdset. Implement unlock_stop so + that we can use it to unset the flushing state again. + Fixes #577326 + +2009-12-10 16:09:09 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: remove redundant fields + +2009-12-09 19:03:16 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/vorbis/gstvorbisdec.h: + * ext/vorbis/vorbisdec.c: + vorbisdec: adapt to new oggdemux + Remove all granulepos hacks and simply use the timestamps from the new oggdemux + like any other decoder. + +2009-12-09 19:04:18 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/vorbis/vorbisdec.c: + vorbisdec: fix peer query + +2009-12-09 17:24:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: fix query + +2009-12-09 16:55:52 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: small cleanups + +2009-12-09 16:38:43 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/vorbis/vorbisdec.c: + vorbisdec: use gst_pad_peer_query() + +2009-12-09 12:10:35 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: fix video when subtitles disabled + When we have a source with subtitles but they were disabled with the flags, + still ghostpad the video pad instead of leaving it unlinked. + +2009-12-09 09:47:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Only flush downstream on seeks for flushing seeks + +2009-12-09 09:35:14 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Proxy buffer allocation on the video sinkpad to the srcpad + +2009-12-08 17:30:39 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: update slider only 25 times a second + don't update the slider a 100 times a second, it's likely higher than the screen + framerate and just wastes cpu. + +2009-12-08 17:23:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: + theora: remove granulepos hacks + Remove the granulepos hacking now that oggdemux outputs timestamps like any + other demuxer. + +2009-12-08 13:40:18 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Fix stream-changed message list iteration + When iterating the list and removing the current element, first + get the next element and then remove the current one and not + the other way around. + +2009-12-07 18:49:43 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: improve keyframe seeking + Improve keyframe seeking. + Fix reverse playback. + +2009-12-07 15:42:05 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: implement keyframe seeking + Implement keyframe seeking in oggdemux by doing the double seek trick. First + seek to the required position, then read pages for all streams to grab the + granulepos (to know the timing of the keyframe) of each stream, then seek back + to the first keyframe. + +2009-12-07 09:13:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Some minor cleanup + +2009-12-06 18:05:15 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Reset stream segments on FLUSH_STOP and don't adjust QoS events for non-time segments + +2009-12-04 16:35:09 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix timestamps after seek + After a seek, discard all packets before the packet with the granulepos on it so + that the output buffers contain valid timestamps. + Reorder some code so that we check the timestamps before allocating and pushing + an output buffer. + Do more checks on valid packets in ogm mode. + +2009-12-04 15:39:59 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: add comment + +2009-12-04 14:01:11 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: don't do math with invalid granulepos + When the current granulepos is unknown and set to -1, don't try to add durations + to it. + +2009-12-04 13:14:57 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: guard against wrong granulepos + Clamp the initial granulepos to 0 instead of going negative for some badly muxed + ogg files. + +2009-12-04 12:26:47 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: don't fail on bogus granulepos + Do some additional checks on the granulpos timestamp before using it for + calculating the duration because oggdemux generates wrong granulepos now. + Fixes seeking somewhat again. + +2009-12-03 20:05:29 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: reimplement OGM support + OGM demuxing no longer requires helper elements. It's done internally + in oggdemux. Vorbis comments are still not handled because I don't + have anything to test with. + +2009-12-03 17:02:11 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggstream.c: + oggdemux: fix for I-frame-only theora + +2009-12-03 01:16:17 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: log when ogg mapper doesn't accept the setup header packet + +2009-12-02 02:08:46 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: extract width, height and PAR from theora header and add to caps + +2009-12-03 23:43:08 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggstream.c: + ogg: extract number of channels from FLAC, speex and vorbis headers + Because we can. + +2009-12-03 22:14:34 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaybin2.c: + build: fix build with debug logging disabled. + +2009-12-03 21:07:49 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + ogg: more print fixes + gstoggstream.c:419: error: format ‘%lld’ expects type ‘long long int’, but argument 8 has type ‘gint64’ + gstoggdemux.c:2253: error: format ‘%lld’ expects type ‘long long int’, but argument 8 has type ‘GstClockTime’ + gstoggdemux.c:2333: error: format ‘%lld’ expects type ‘long long int’, but argument 8 has type ‘GstClockTime’ + +2009-12-03 16:57:48 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * ext/ogg/gstoggparse.c: + * ext/ogg/gstoggstream.c: + ogg: Fixing some printf format strings + Fixes some printf format strings to make it build on mac. + +2009-12-03 18:08:49 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstfactorylists.c: + * gst/playback/gstfactorylists.h: + * gst/playback/gstplaybin2.c: + playbin2: don't iterate the factory lists in non-debug mode + When debugging is disabled, we won't see anything printed anyway. + +2009-12-02 23:55:55 -0800 David Schleef <ds@schleef.org> + + * gst/videoscale/vs_4tap.c: + Build fix for MSVC + +2009-12-02 23:27:55 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/subparse/qttextparse.c: + build: add missing includes for sprintf and atoi + +2009-12-01 16:42:42 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + * gst/subparse/qttextparse.c: + subparse: Add support for some tags of qttext + Currently supporting timescale, timestamps, font, size, + textColor, backColor, plain, bold and italic + Fixes #603357 + +2009-12-01 13:13:24 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: + * gst/subparse/gstsubparse.h: + * gst/subparse/qttextparse.c: + * gst/subparse/qttextparse.h: + subparse: add qttext support + Adds basic support for qttext subtitles, still lacks markup tags + to make it prettier, but the plain text already works. + Implemented according to: + http://www.apple.com/quicktime/tutorials/texttracks.html + http://www.apple.com/quicktime/tutorials/textdescriptors.html + Fixes #603357 + +2009-12-01 13:22:57 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: conditionally cleanup sami context + Only cleanup sami context if we are parsing sami subtitles, + otherwise we might have crashes. + +2009-12-01 13:19:35 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: Add missing caps to sink caps template + Some caps were missing from the sink caps template when + xml was disabled + +2009-12-01 15:06:10 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 87bf428 to 47cb23a + +2009-12-01 14:14:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From da4c75c to 87bf428 + +2009-11-30 10:22:15 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + subtitleoverlay: Fix some pad refcount issues + Fixes bug #603345. + +2009-11-27 18:54:57 +0100 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From 53a2485 to da4c75c + +2009-11-25 17:04:41 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: handle theora streams with 0 keyoffset + +2009-11-25 16:53:26 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + oggdemux: Handle unknown streams + +2009-11-26 14:30:33 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + Revert "textoverlay: First draw outline text and then the real text" + This reverts commit 60aa09d28c1f9fd29b56876d7ac6c0366d6cef4d. + First drawing the real text and then the outline produces ugly + text in lower resolutions. The outline line width needs to be somehow + changed relative to the resolution. Fixes bug #602924. + +2009-11-26 10:30:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiofilter.c: + audiofilter: Use G_DEFINE_ABSTRACT_TYPE_WITH_CODE + ...and fix code style a bit. + +2009-11-26 10:31:00 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiofilter.h: + audiofilter: Add _CAST variants of the cast macros + +2009-11-25 10:26:16 -0600 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + audiosink: add adjustement when slaving + Our calibration against the pipeline clock is done with the adjusted + ringbuffer time, so take the adjustement into account. Fixes some audio dropouts + when reusing audio sinks after switching clocks and slaving methods in a + pipeline. + +2009-11-25 16:17:13 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Prefer transforming alpha formats to alpha formats and the other way around + Fixes bug #602834 and #350748. + +2009-11-25 00:46:55 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + oggdemux: Reset last_granule during seeking + Fix case where we would reconstruct the wrong granulepos for + outgoing streams immediately after a seek. + +2009-11-24 22:08:09 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + oggdemux: Fix timestamp generation for theora + Timestamp generation was broken by the last commit for formats + with a non-zero granule shift. Also keep track of the last keyframe + so that we can regenerate granulepos for theora. + +2009-11-24 21:22:03 -0800 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + * ext/ogg/vorbis_parse.c: + oggdemux: Fix vorbis parsing + Add a granule to granulepos conversion function. Fix the duration + function for vorbis. Handle timestamps on header packets differently + and be more careful about calculating OFFSET and OFFSET_END. After + this change, timestamps for vorbis don't exactly match up with the + timestamps that vorbisparse outputs, but it's unclear if vorbisparse + is actually correct and it would add a lot more code to make oggdemux + match vorbisparse. Fixes #602790. + +2009-11-19 19:28:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Transform QoS events to be meaningful for upstream elements + This is necessary because the sinks don't notice the group switches + and the decoders/demuxers have a different running time than the + sinks. + Fixes bug #537050. + +2009-11-21 22:05:34 +0100 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + ogg: Fix generation of timestamps and durations + After changing some internal functions, I forgot to update + the code that puts the values on the buffers. + +2009-08-29 10:51:48 -0700 David Schleef <ds@schleef.org> + + * ext/ogg/Makefile.am: + * ext/ogg/dirac_parse.c: + * ext/ogg/dirac_parse.h: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggparse.c: + * ext/ogg/gstoggstream.c: + * ext/ogg/gstoggstream.h: + * ext/ogg/vorbis_parse.c: + ogg: Add ogg stream parsing + Adds code that parses headers of various formats encapsulated in + Ogg in order to calculate timestamps and durations of each buffer. + Removes the creation of helper decoder elements to do this calculation + via conversion queries. + Fixes: #344013, #568014. + +2009-09-04 00:11:38 -0700 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggmux.c: + oggmux: don't overwrite object properties + +2009-11-21 17:54:49 +0200 Stefan Kost <ensonic@users.sf.net> + + * ext/theora/theoradec.c: + debug: also cast packet.packetno to gint64 in debug log + We do this already for granulepos to handle ogg_int64_t mismatches. + +2009-11-21 17:47:26 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + debug: fix format string that was missing a var + +2009-10-10 00:32:04 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + * tests/check/elements/adder.c: + adder: make events succeed, if they succed on atleast one pad + +2009-11-19 14:51:33 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: error when all streams have no buffers + In some cases (all buffers dropped by a parser) a decodebin2 + chain might receive an EOS before it gets enough data to + expose a decoded pad. In the case that no streams can expose + a pad we should error out instead of hang. + Fixes #542758 + +2009-11-19 12:23:08 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Fix stupid bug introduced in last commit + +2009-11-19 12:10:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Aggregate the stream-changed message by looking at the seqnum + Just counting how many messages were sent and how many were received + is not good enough because they might've been duplicated (e.g. by the + visualization audio tee). Comparing the sequence numbers should give + better results in that case. + +2009-11-19 10:05:28 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Ignore async state changes of the uridecodebins + Otherwise the async state change from READY->PAUSED of the + uridecodebins will take playbin2 from PLAYING->PAUSED again + during gapless group switches. + Fixes bug #602000. + +2009-11-19 10:30:06 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Automatic update of common submodule + From 0702fe1 to 53a2485 + +2009-11-18 14:50:28 -0300 Thiago Santos <thiago.sousa.santos@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: set to buffer less on no-more-pads + When a decodebin2 receives no-more-pads of a group it + can set that group's multiqueue buffering thresholds to + 'playing' buffering method, avoiding that it buffers + too long and cause problems when using with queue2. + See the associated bug for details. + Fixes #600787 + +2009-11-18 17:09:28 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: fix initial calibration + When we are calibrating the internal clock against the external clock take into + account the time offset applied to our internal clock because we will subtract + that in the render_function again. + +2009-11-18 09:22:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't handle DURATION queries during group switches + During a group switch return the cached duration of the old group + because the old group still didn't finish playback. If we have no + cached duration return FALSE. + Fixes bug #585969. + +2009-11-15 19:36:21 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Post a stream-changed message after activating a group + This is useful to detect when playbin2 has really switched to the next + group after about-to-finish for example. + Fixes bug #584987. + +2009-11-18 12:27:19 +0000 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/libgstvideo.def: + win32: Add new still-frame API to the defs + Add gst_video_event_new_still_frame() and + gst_video_event_parse_still_frame() functions to the win32 defs files + +2009-11-18 12:37:44 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: fix 'uninitialized' compiler warning + +2009-11-18 10:14:41 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: bump core requirement to 0.10.25.1 + We depend on new API that's only in git so far. + +2009-11-15 17:34:37 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + * tests/check/libs/video.c: + video: Add functions to create/parse still frame events. + Add a new video event to mark the start or end of a still-frame + sequence, and a parser function to identify and extract info from + such events. + API: gst_video_event_new_still_frame() + API: gst_video_event_parse_still_frame() + Fixes: #601942 + +2009-11-17 16:39:09 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: make sure we always go to PAUSED async + Set the need_async_start flag before going to PAUSED so that we always post the + ASYNC_START message, even after reusing playsink. + +2009-11-17 16:37:57 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: make sure we remain a sink + When we remove our elements, we could lose our sink flag. Make sure we remain a + sink by setting the flag again after removing elements. + +2009-11-16 22:47:54 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/audioconvert/gstaudioconvert.c: + audioconvert: remove unused array + +2009-11-16 09:57:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: Use new double->fraction transformation function from core + +2009-11-14 14:05:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Make subtitle error handling more robust and ignore late errors too + Make sure, to only "simulate" subtitle no-more-pads if it was still + pending and also handle errors in the subtitle pipeline as warnings + after the subtitles prerolled. + Don't set the suburidecodebin to READY after errors, handle_message + will usually be called from the streaming thread and doing that + from there is obviously not a good idea. + +2009-11-14 13:21:15 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Handle errors from subtitle elements as warning and go into passthrough mode + +2009-11-13 12:47:55 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't leak the GError and debug string when parsing error messages + +2009-11-13 11:16:44 +0100 Sreerenj B <bsreerenj@gmail.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: avoid crashing on SIGPIPE + Use send() instead of write() so that we can pass the MSG_NOSIGNAL flags to + avoid crashing with SIGPIPE when the remote end is not listening to us anymore. + Fixes #601772 + +2009-11-11 17:35:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Improve subtitle passthrough in uridecodebin + Now the caps property isn't set anymore for the subtitle caps + but instead in the autoplug-continue signal it is detected + if the caps belong to a supported subtitle stream. + This makes automatic use of newly installed plugins. + +2009-11-11 17:08:47 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + subtitleoverlay: Only recreate factory caps if necessary and cache them + +2009-11-10 18:27:15 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Only update the factory list when the registry has changed + Also don't free the list every time we go to NULL. + +2009-11-08 15:04:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + subtitleoverlay: Use gst_pad_get_caps_reffed() + +2009-11-07 21:38:10 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + playbin2/playsink: Use new "silent" property instead of unlinking + This makes sure that subtitleoverlay still gets segment updates and + everything to pass on downstream. Without this segment problems happen. + +2009-11-07 21:10:27 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Update segments after pushing the events downstream + This makes sure that we don't apply segments twice downstream. Also + always send our newsegment events downstream. + +2009-11-07 21:09:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Add silent property to disable subtitles + This tries to disable subtitles in the overlay or renderer + and if that's not possible it goes into passthrough mode. + +2009-11-07 11:46:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Set the video framerate on parsers if possible + Fixes bug #599649. + +2009-11-07 11:31:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + * gst/subparse/gstsubparse.h: + subparse: Make fps a GstFraction typed property and use it properly + +2009-11-07 11:08:19 +0100 Iago Toral <itoral@igalia.com> + + * gst/subparse/gstsubparse.c: + * gst/subparse/gstsubparse.h: + subparse: Add property for the video framerate + +2009-11-06 12:51:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Handle external subtitles better + First of all, make sure that suburidecodebin never + errors out because of not-linked in case external subtitles + are used but then subtitles are disabled. + And then make sure that external subtitles always start from + the correct position and are not racing until EOS if they + get unselected and selected again. + +2009-11-04 17:29:07 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Flush the subtitles before switching to a new subtitle stream + This makes sure that all currently shown subtitles disappear + and new ones can be shown as soon as possible. + +2009-11-03 12:47:55 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Set subtitle caps as raw caps for the uridecodebins + This will make sure that no subparse is ever plugged and subtitleoverlay, + that subpicture streams are handled the same was as subtitles and that + subtitle renderers are used if available. + Fixes bugs #595123, #570753, #591662, #591706. + +2009-11-03 12:33:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2/playsink: Remove everything related to subpicture streams + These will soon be handled the same way as subtitle streams. + +2009-11-02 15:50:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Add a queue before subtitleoverlay + This will improve playback, and the same thing is done + for subpicture streams too. + +2009-11-02 15:05:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Use subtitleoverlay for subtitles + +2009-11-02 07:43:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + subtitleoverlay: Add to the docs + +2009-10-13 16:48:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/Makefile.am: + * gst/playback/gstplayback.c: + * gst/playback/gstsubtitleoverlay.c: + * gst/playback/gstsubtitleoverlay.h: + subtitleoverlay: Add new element for generic subtitle overlaying + This autopluggs the required elements for parsing and rendering + different subtitle formats on a video stream. + Fixes bug #600370. + +2009-11-11 19:32:01 -0500 Olivier Crête <olivier.crete@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: Keep timestamp from incoming buffer if it is valid + Fixes bug #601627. + +2009-11-11 14:00:26 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playback: Update factories list on every access if the registry has changed + This makes application's simpler because the element doesn't need to + go to NULL first to make use of newly installed plugins. + Fixes bug #601480. + +2009-11-10 18:13:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playback: When going from NULL->READY check if the registry has new features + This makes it possible to use newly installed plugins after going back + to NULL instead of requiring a new instance. + Fixes bug #599266. + +2009-11-10 13:55:26 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Clear the EOS state on a seek. + Allow seeking back into the stream after it hits EOS. + +2009-11-10 12:21:50 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audioresample/README: + * gst/audioresample/arch.h: + * gst/audioresample/fixed_arm4.h: + * gst/audioresample/fixed_arm5e.h: + * gst/audioresample/fixed_bfin.h: + * gst/audioresample/fixed_debug.h: + * gst/audioresample/resample.c: + * gst/audioresample/resample_sse.h: + * gst/audioresample/speex_resampler.h: + audioresample: Update speex resampler to latest GIT + +2009-11-10 00:48:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: assign chain->mute before using it + Fixes GObject warnings when starting totem. + +2009-10-28 22:10:33 -0700 David Schleef <ds@schleef.org> + + * ext/theora/theoradec.c: + theora: Fix alignment of frames when converting + Fix logic inversion in calculating the offset in the theora + frame when copying to a GStreamer frame. + +2009-11-09 19:58:20 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstfactorylists.c: + playback: Fix the order in strcmp that I broke in previous commit. + +2009-11-09 19:16:21 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Reduce number of calls to gst_type_find_peek. + Shaves off a couple percents off typefinding + +2009-11-09 17:49:51 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstfactorylists.c: + playback: Avoid expensive API calls in tight loop. + We know we're dealing with GstPluginFeature. + +2009-11-09 18:11:42 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/libs/cddabasesrc.c: + cddabasesrc: Add unit test for property settings + Also includes a regression test for bug #601104. + +2009-11-09 18:04:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + cddabasesrc: Never return a negative track number in get_uri() + +2009-11-09 18:03:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + cddabasesrc: Don't set the track to 1 every time a device is set + Fixes bug #601104. + +2009-11-08 11:27:10 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: Remove useless variables and fix a uninitialized variable compiler warnings + +2009-11-06 17:01:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Add property to disable/enable posting of stream-topology messages + Most people don't need this messages and generating them is quite + expensive. + +2009-11-06 15:12:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Protect subtitle elements and subtitle encoding by a new mutex + Using the object lock here can and will lead to deadlocks because + of deep-notifies of property changes: the deep-notify handler will + get the parent of objects, which will take the object lock again. + Fixes bug #600479. + +2009-11-06 13:13:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: Make sure that running_time->timestamp calculation never becomes negative + +2009-11-06 13:25:05 +0200 Mart Raudsepp <leio@gentoo.org> + + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + examples: Correct casting of g_signal* funcs first arguments + This completes the deprecated GTK API fix in commits 81a0a986 and + 79adfa54 - unlike gtk_signal_connect and co, g_signal_connect and + co take a gpointer, not a GtkObject. + +2009-11-06 12:25:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Improve all-raw-caps detection for pads + +2009-11-06 12:19:47 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + basesrc: fix startup position in the ringbuffer + When we start and we need to produce the first sample, go to the next sample + that will be written into the ringbuffer instead of trying to go to sample 0. + We relied on rather small ringbuffer sizes to correctly go to the current + sample, which breaks whith large buffers. + Fixes #600945 + +2009-11-06 11:26:14 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: Use the start time (i.e. timestamp) as the last stop + Using the end time makes it impossible to replace buffers, which is + a big problem for subtitles that could have very long durations. + +2009-11-06 12:08:19 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Synchronize video/text based on the running time + Instead of simply using the buffer timestamps. + +2009-11-06 09:30:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Clip text buffers to the text segment and reset segments properly + +2009-11-06 09:01:34 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: Put the video segment into the instance struct instead of allocating it separately + +2009-11-06 09:05:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Check if text timestamp/duration is valid before clipping + +2009-11-05 23:33:42 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: printf format fix + +2009-11-05 15:42:09 +0100 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst/gdp/gstgdpdepay.c: + gdpdepay: Clear adapter on flush and state change + Fixes #600469 + +2009-11-05 13:12:19 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: use _get_caps_reffed() + +2009-11-05 13:00:27 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + pad: rename new api from _refed to _reffed. + Due to popular demand rename the new api as we still can. + +2009-11-04 18:57:07 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playbin2: avoid copying caps + Use get_caps_refed() when we can. + +2009-11-04 18:31:09 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: use new getcaps function to avoid copies + Use the gst_pad_get_caps_refed() to avoid some caps copy functions. + +2009-11-04 17:50:11 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: use faster element_link_pads + Use the faster gst_element_link_pads because we know for sure the sinkpad name + and we don't need to have the function search for a suitable pad anymore. + +2009-11-04 16:16:31 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: make drift tolerance configurable + Add drift-tolerance property (defaulting to 20ms) to handle resync after clock + drift or timestamp drift instead of relying on the latency-time value for clock + drift and 500ms for timestamp drift. + Remove warning about discont timestamp and simply resync. The warning is in some + cases not correct and is triggered more frequently now that we lower the + tolerance value. + +2009-11-04 10:52:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Return NOT_LINKED for unselected text pads from a demuxer + We want to return NOT_LINKED for unselected pads but only for pads + from the normal uridecodebin. This makes sure that subtitle streams + are not raced past audio/video from decodebin2's multiqueue. + For pads from suburidecodebin OK should always be returned, otherwise + it will most likely stop with an error. + +2009-11-04 08:20:59 +0100 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstinputselector.c: + inputselector: also add inline to the proto to fix the build + Merged from gst-plugins-bad, e1e9be6dbe1bd0df0543f2a72dcf9cc6d644dd78. + +2009-11-03 12:01:16 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Initialize caps property with the default raw caps + +2009-11-03 11:48:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstrawcaps.h: + decodebin2: Use static caps for the default raw caps and put them into a separate header + This way we can use the same default raw caps everywhere. + +2009-11-03 08:26:37 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: First draw outline text and then the real text + Improves the output a bit because no parts of the outline are + overwritten again. + +2009-10-31 14:02:40 +0100 Josep Torra Valles <n770galaxy@gmail.com> + + * gst/playback/gstplaybin.c: + playbin: Make sure to keep a reference on the volume element + Fixes null pointer dereferences under certain circumstances. + Fixes bug #595401. + +2009-10-31 09:47:54 +0100 Edward Hervey <bilboed@bilboed.com> + + * po/POTFILES.in: + po: queue2 has moved to core + +2009-10-30 09:24:30 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Reset {mute,volume}-changed flags after setting the volume + These flags are there to make sure that the volume is set, if there + is no volume element yet. + +2009-10-30 09:24:03 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: If notify::{volume,mute} is triggered by the volume element, update our internal state + +2009-10-29 14:30:31 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Proxy notify::volume and notify::mute from the volume/mute elements (or sinks) + Fixes bug #600027. + +2009-10-29 14:19:09 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Proxy notify::volume and notify::mute from the playsink to playbin2 + +2009-10-29 11:37:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/plugins/inspect/plugin-queue2.xml: + queue2: Remove inspect file + +2009-10-29 11:29:46 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/Makefile.am: + * gst/playback/gstqueue2.c: + queue2: Remove from gst-plugins-base + This is now in coreplugins. + +2009-10-28 11:29:36 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + docs: include more indexes + +2009-10-28 11:13:20 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + docs: turn entities into xi:includes + This is faster to process and easier to maintain. Its also less 80s. + +2009-10-28 10:17:43 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtp: dump packets which we reject + +2009-10-28 01:01:35 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/pipelines/.gitignore: + .gitignore: ignore basetime unit test binary + +2009-10-28 00:59:35 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst/adder/gstadder.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstinputselector.c: + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstqueue2.c: + * gst/playback/gststreaminfo.c: + * gst/playback/gststreamselector.c: + * gst/subparse/gstssaparse.c: + Remove GST_DEBUG_FUNCPTR where they're pointless + There's not much point in using GST_DEBUG_FUNCPTR with GObject + virtual functions such as get_property, set_propery, finalize and + dispose, since they'll never be used by anyone anyway. Saves a + few bytes and possibly a sixteenth of a polar bear. + +2009-10-27 15:23:00 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstqueue2.c: + queue2: add custom acceptcaps function + +2009-10-27 15:22:22 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: implement low/high watermark property + +2009-10-23 14:56:11 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: add checkbox to enable buffering + +2009-10-23 14:54:47 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: don't use 2 buffering elements + Only use the multiqueue buffering when we don't have a stream (and thus are + using queue2 to do the buffering already). + +2009-10-23 14:34:42 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplay-enum.c: + * gst/playback/gstplay-enum.h: + * gst/playback/gstplaybin2.c: + playbin2: add flag to enable decodebin buffering + Add a flag that enables buffering in decodebin. + +2009-10-23 14:32:29 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: buffering is implemented now + +2009-10-23 14:30:52 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: buffering is implemented now + +2009-10-23 14:09:17 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: configure use-buffering on multiqueue + +2009-10-23 13:58:25 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: use 0 for max buffer size + +2009-10-23 13:53:21 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: set some reasonable defaults + +2009-10-23 13:44:12 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: set buffering properties on decodebin2 + Propagate the buffering properties on decodebin2 but only if we are not already + doing download buffering. + +2009-10-23 11:52:09 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add use-buffering property + Add a use-buffering property that will perform buffering on the parsed or + demuxed media. + +2009-10-23 11:31:47 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: refactor queue size configuration. + Refactor the queue size configuration into a new method. + Use the same queue values for buffering as for preroll. + +2009-10-23 11:08:50 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: move error path down + +2009-10-23 11:02:40 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: implement max queue size properties + +2009-10-23 10:42:23 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: add properties for buffering + Add properties that can be used to configure the multiqueue buffers and + buffering methods + +2009-10-24 13:19:08 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/examples/app/Makefile.am: + * tests/examples/seek/Makefile.am: + * tests/examples/v4l/Makefile.am: + examples: fix linking order. + the uninstalled wrapper would create a LD_LIBRARY_PATH with system-wide + path before the local ones... resulting in the example applications picking + up the system-wide libraries and not the (potentially modified) uninstalled + libraries + +2009-10-24 13:08:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't destroy the suburidecodebin on errors + It can still be reused + +2009-10-24 13:07:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: If setting the state of the suburidecodebin fails just warn, don't error out + +2009-10-24 12:12:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't set uridecodebin states to NULL before reusing them + This makes sure that the internal decodebin2 and everything else can + be reused without reinstantiation. + +2009-10-18 17:28:22 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Store unused decodebin2 instances for further usage. + This allows faster re-use of uridecodebin. + https://bugzilla.gnome.org/show_bug.cgi?id=599471 + +2009-10-23 17:49:15 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoraparse.h: + * ext/theora/theoraparse.c: + theora: Convert theoraparse to libtheora 1.0 API + +2009-10-21 12:38:59 +0300 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + rtpaudiopayload: Only sent exact multiple of the frame size + Also align the maximum size with the frame size, not only the minimum + +2009-10-22 09:12:03 -0300 Thiago Santos <thiagoss@embedded.ufcg.edu.br> + + * gst/audiorate/gstaudiorate.c: + audiorate: move debug calculation into debug macro + Remove in_duration and move its calculation to + GST_LOG_OBJECT macro. This way it will only be calculated + if we have debug enabled. + +2009-10-22 09:06:02 -0300 Thiago Santos <thiagoss@embedded.ufcg.edu.br> + + * gst/audiorate/gstaudiorate.c: + audiorate: Removing unused variable + The in_stop variable was never read. Removing it. + +2009-10-22 08:40:01 -0300 Thiago Santos <thiagoss@embedded.ufcg.edu.br> + + * gst/audiorate/gstaudiorate.c: + audiorate: be more accurate on offset math + Replace gst_util_uint64_scale_int for its rounding version + to improve accuracy and avoid inserting samples where + they aren't needed. + Fixes #499181 + +2009-10-22 10:17:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Optimize a bit more + ...and add a FIXME for bug #598695 and explain + what we should do once Pango supports user fonts. + +2009-10-22 10:02:11 +0200 Iago Toral <itoral@igalia.com> + + * gst/subparse/gstsubparse.c: + * gst/subparse/gstsubparse.h: + * tests/check/elements/subparse.c: + subparse: Add support for DKS subtitle format + Fixes bug #598936. + +2009-10-22 09:31:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Do shading as first operation + +2009-10-22 09:08:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Only use a single cairo surface for drawing + ... and comment/optimize what is going on here a bit better. + +2009-10-21 16:24:29 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: set output caps before pushing + Set the output caps on the srcpad before pushing the buffer because else core + will do a rather expensive check to see if we can actually accept those caps on + the srcpad. + +2009-10-21 15:58:11 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstinputselector.c: + inputselector: install an acceptcaps function + Install a custom acceptcaps function instead of using the default expensive + check. We accept whatever downstream accepts so we pass along the acceptcaps + call to the downstream peer. + +2009-10-21 20:35:17 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: fix typo in previous mxf typefinder change + +2009-10-21 20:44:33 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: speed up mxf_type_find over 300 times for worst case scenarios + * memcmp is expensive and was being abused, reduce calling it by checking + the first byte. + * iterating one byte at at time over 64 kbites introduces a certain overhead, + therefore we now do it in chunks of 1024 bytes + And I do mean over 300 times. The average instruction call per mxf_type_find + was previously 785685 and it's now down to 2458 :) + +2009-10-20 17:13:39 -0400 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstfactorylists.c: + decodebin2: avoid type checks + +2009-10-20 09:00:28 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + gst/decodebin2: Ensure we get fixed caps for topology message + There are some corner cases (like with dvdemux amongst others) where + the caps won't be negotiated, but the pad has fixed caps. + +2009-10-20 08:52:36 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + gst/decodebin2: Don't expose chains if we're shutting down. + This avoids adding flushing pads to ourself + +2009-10-17 21:16:57 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * ext/pango/gsttextoverlay.c: + pango: bump pango requirement to stable version and remove ifdefs + Bump pango requirement from an ancient development version to an + ancient stable version. + +2009-10-17 21:11:10 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/.gitignore: + .gitignore: update after files got renamed + +2009-10-16 10:54:31 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppayload: small comment fix + +2009-10-16 10:50:35 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtp/gstbasertppayload.c: + rtp: Correct timestamping of buffers when buffer_lists are used + The timestamping of buffers when buffer_lists are used failed if + a buffer did not have both a timestamp and an offset. + +2009-10-16 10:56:56 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtsp-marshal.list: + * gst-libs/gst/rtsp/gstrtspextension.c: + * gst-libs/gst/rtsp/rtsp-marshal.list: + * gst-libs/gst/video/Makefile.am: + * gst/playback/Makefile.am: + * gst/tcp/Makefile.am: + build: fix previous commit to fully accomodate the glib-gen.mak changes + I also renamed glib_enum_prefix to glib_gen_prefix as we also use that for the + marshallers. Also rename the rtsp-marshal.list to work with the unified prefix. + +2009-10-16 10:18:45 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/video/Makefile.am: + * gst/playback/Makefile.am: + * gst/tcp/Makefile.am: + build: use gst-glib-gen.mak to fix the glib build rules. Fixes #598114 + The build rules in glib-gen.mak were using pattern rules in a non save way. + +2009-10-16 10:14:36 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From 85d1530 to 0702fe1 + +2009-09-10 11:39:18 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoradec.c: + theora: Make theoradec use gstvideo for image conversion + Vastly simplifies code. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-10 09:36:31 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoradec.c: + theora: Don't always round to even width/height + Previously, the code always rounded to even sizes. Now it only ensures + that pic_x and pic_y are multiples of 2 if the output format requires + it. + Also inlcudes fixes to take pic_x/y into account properly when copying + the buffer. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-10 00:00:44 +0200 Benjamin Otte <otte@gnome.org> + + * configure.ac: + theora: Don't check for theora.pc anymore + THe new APIs from theoradec and theoraenc are used now. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-07-31 14:59:03 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: + theora: Convert theoradec to libtheora 1.0 API + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 23:44:36 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/Makefile.am: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Port encoder to new Theora API + Includes ripping out the old buffer copy code to fill up to frame size. + This is not necesary with the new encoder. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 21:59:31 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Disable sharpness property + It's ignored by libtheora + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 21:57:08 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Disable noise-sensitivity property + It is ignored by libtheora + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 21:50:57 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Disable keyframe-mindistance property + It's ignored by the current Theora library + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 21:48:08 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Disable keyframe_threshold property + It's ignored by the current theora encoder + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-09 20:26:47 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Get rid of "quick" property + The proeprty is not used by libtheora at all + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-08 15:12:23 +0200 Benjamin Otte <otte@gnome.org> + + * configure.ac: + * ext/theora/theoraenc.c: + theora: remove support for outdated granulepos hack + This is in preparation to switching to switching to the new Theora API + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-08 13:23:04 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Ignore border property + Always make the video use black as padding color. + The output will be identical to previous versions. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-09-08 13:18:26 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theora: Ignore the center property, always set video to top left + This is not a necessary property, the output will be identical no matter + what. + https://bugzilla.gnome.org/show_bug.cgi?id=594729 + +2009-10-15 16:34:28 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/Makevars: + po: Don't create backup .po files + As well as preventing creation of useless backup files, it works + around a bug in gettext 0.17 on OS/X + +2009-10-15 13:13:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Post a element message on the bus with the stream topology + Fixes bug #598533. + +2009-10-15 13:01:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Store the "endcaps" of a chain + This are the caps that either resulted in a deadend if + no plugin for them could be found or raw caps. + +2009-10-15 11:38:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Store for every chain, which pad resulted in its creation + +2009-10-15 10:28:39 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/pipelines/basetime.c: + check: Don't fail the basetime test when no audiosrc is available + On OS/X the DEFAULT_AUDIOSRC is not going to be available, because + it isn't in gst-plugins-base. Just defer the test, instead of + failing it. + +2009-10-14 10:41:03 +0200 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From a3e3ce4 to 85d1530 + +2009-10-14 08:36:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Use gst_object_has_ancestor() instead of our own implementation of it + +2009-10-13 19:14:41 +0300 Tommi Myöhänen <ext-tommi.1.myohanen@nokia.com> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: fix timestamp comparission, Fixes #597407 + +2009-10-13 13:52:02 +0300 Tommi Myöhänen <ext-tommi.1.myohanen@nokia.com> + + * tests/check/Makefile.am: + * tests/check/pipelines/basetime.c: + tests: new test for baseaudiosrc base_time comparison + This test reveals a bug in comparison operation between timestamp and + GstElement's base_time in GstBaseAudioSrc. + +2009-10-08 19:55:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Don't stop completely on initialization errors from subtitle elements + Instead disable the subtitles and play the other parts of the stream. + Fixes bug #587704. + +2009-10-13 16:50:37 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Ignore no-more-pads from non-demuxer elements + instead of printing an error that no corresponding group could + be found. no-more-pads from non-demuxer elements doesn't give + any additional information because there can only be a single srcpad. + Fixes bug #598288. + +2009-10-12 21:30:15 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/audioconvert/gstaudioconvert.c: + audioconvert: track active conversion in perf log + +2009-10-12 15:48:46 +0200 Patrick Radizi <patrick.radizi at axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: handle socket errors + gstrtspconnection.c:gst_rtsp_connection_receive() can hang when an error occured + on a socekt. Fix this problem by checking for error on 'other' socket after poll + return. + Fixes #596159 + +2009-10-06 14:08:48 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudioclock.c: + audioclock: whitespace fixes + +2009-10-06 14:07:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: avoid confusing error + +2009-10-09 22:00:45 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + vorbis: fixes warings in macosx snow leopard + +2009-10-09 18:52:12 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/theora/theoradec.c: + * ext/theora/theoraparse.c: + theora: fixes warnings on macosx snow leopard + +2009-10-09 16:56:29 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: + ogg: fixes warnings on macosx snow leopard + +2009-10-09 16:19:17 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix a warning in macosx + +2009-10-08 14:16:44 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/tag/tags.c: + tag: use BOM to recognize UTF-16/32 encoding and convert accordingly + +2009-10-09 15:11:16 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/gst-plugins-base.supp: + check: Add valgrind suppressions for ALSA and fontconfig bits on Jaunty. + +2009-10-09 15:32:45 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/gnomevfs/gstgnomevfssrc.c: + audioconvert: change the format instead of cast as ensonic asked + +2009-10-09 15:29:15 +0200 Josep Torra <n770galaxy@gmail.com> + + * gst/audioconvert/gstchannelmix.c: + audioconvert: fixes warning: format not a string literal and no format arguments + redo of valid part of my previous revert. + +2009-10-09 15:19:42 +0200 Josep Torra <n770galaxy@gmail.com> + + * common: + * gst/audioconvert/gstchannelmix.c: + Revert "audioconvert: fixes warning: format not a string literal and no format arguments" + Revert this commit as unintentionally I've changed common. + This reverts commit 49ea0138223ec5f9e53780635cbcc70f33778667. + +2009-10-09 14:28:42 +0200 Josep Torra <n770galaxy@gmail.com> + + * ext/gnomevfs/gstgnomevfssrc.c: + gnomevfssrc: fixes warnings in macosx + warning: format '%llu' expects type 'long long unsigned int', but argument 8 has type 'GnomeVFSFileOffset' + warning: format '%lld' expects type 'long long int', but argument 9 has type 'guint64' + +2009-10-09 14:23:36 +0200 Josep Torra <n770galaxy@gmail.com> + + * gst/videorate/gstvideorate.c: + videorate: fix warning in macosx + +2009-10-09 14:20:47 +0200 Josep Torra <n770galaxy@gmail.com> + + * gst/audiorate/gstaudiorate.c: + audiorate: fix warning in macosx + +2009-10-09 14:14:15 +0200 Josep Torra <n770galaxy@gmail.com> + + * common: + * gst/audioconvert/gstchannelmix.c: + audioconvert: fixes warning: format not a string literal and no format arguments + +2009-10-09 14:07:24 +0200 Josep Torra <n770galaxy@gmail.com> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + * gst-libs/gst/audio/gstringbuffer.c: + audio: fix warnings building on macosx + +2009-10-08 18:08:22 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: chwck formats just once per _chain() + +2009-10-08 17:49:39 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: add perf-log-category and log suboptimal operation + Log if we use an intermediate colorspace for conversion. + +2009-10-08 10:59:36 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From 19fa4f3 to a3e3ce4 + +2009-10-08 00:17:21 +0100 Jan Schmidt <jan.schmidt@sun.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Fix type-punning warning + +2009-09-26 12:56:36 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Chains with an exposed endpad are complete too + This allows partial group changes, i.e. demuxer2 in the example below + goes EOS but has a next group and audio2 stays the same. + /-- >demuxer2---->video + demuxer--- \--->audio1 + \--->audio2 + +2009-09-26 12:47:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Use the iterate internal links function instead of string magic to get multiqueue srcpads + +2009-09-24 14:56:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Don't post missing plugin messages twice + decodebin2 already posts them after emitting the unknown-type signal, + there's no need to post another one. + +2009-09-26 12:17:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Rewrite autoplugging and how groups of pads are exposed + This now keeps track of everything that is going on, creates + a tree of chains and groups to allow "demuxer after demuxer" scenarios + and allows chained Oggs with multiple streams (needs oggdemux or playbin2 fixes). + Also document everything in detail and give a general overview of what + decodebin2 is doing at the top of the sources. + Fixes bug #596183, #563828 and #591677. + +2009-10-07 17:45:33 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + ximagesink: only start event thread if needed + The event thread is doing 20 wakeups per second to poll the events. If one + runs ximagesink with handle-events=false and handle-expose=false then we can + avoid the extra thread. + +2009-10-07 16:56:28 +0200 Edward Hervey <bilboed@bilboed.com> + + * ext/theora/theoraenc.c: + theoraenc: Make the default quality property 48. + This guarantees that people who use theoraenc without modifying any + properties will end up with a reasonably good quality output. + 48 is also the default of the encoder_example application shipped with + libtheora. + +2009-10-07 11:48:37 +0200 Benjamin Otte <otte@gnome.org> + + * tests/check/libs/video.c: + tests/check/libs/video.c: Update strides for Y41B + +2009-10-07 10:32:17 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: we can use GLib 2.18 API unconditionally now + +2009-10-07 10:13:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: bump GLib requirement to 2.18 + Bump required GLib version as per the release planning docs. + +2009-10-05 00:33:32 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/tuner.c: + docs: clarify GstTuner docs in two places + +2009-09-25 15:32:18 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * sys/v4l/gstv4lelement.c: + v4l: fix compiler warning + Fix 'variable may be used uninitialized' compiler warning (which is + true in theory, but can't actually ever happen, since we always + call the function with check=FALSE). + Fixes #596313. + +2009-10-07 11:56:35 +0300 Stefan Kost <ensonic@users.sf.net> + + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstogmparse.c: + * gst/subparse/gstsubparse.c: + * gst/subparse/mpl2parse.c: + * gst/subparse/tmplayerparse.c: + build: sprintf, sscanf need stdio.h + +2009-09-15 15:26:06 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: only start event thread if needed + The event thread is doing 20 wakeups per second to poll the events. If one runs + xvimagesink with handle-events=false and handle-expose=false then we can avoid + the extra thread. + +2009-10-07 09:58:27 +0200 Benjamin Otte <otte@gnome.org> + + * gst-libs/gst/video/video.h: + Update Since tags for NV12/NV21 + They are added in 0.10.26 now, not 0.10.25 + +2009-09-23 15:31:50 +0200 Benjamin Otte <otte@gnome.org> + + * gst/videotestsrc/videotestsrc.c: + [videotestsrc] Make checkers-8 pattern create 8x8 instead of 16x16 tiles + +2009-09-23 11:03:57 +0200 Benjamin Otte <otte@gnome.org> + + * gst/ffmpegcolorspace/imgconvert_template.h: + [ffmpegcolorspace] Fix NV12 and NV21 with odd width and height + +2009-09-23 10:25:02 +0200 Benjamin Otte <otte@gnome.org> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + Add NV12 and NV21 formats + +2009-09-21 18:49:42 +0200 Benjamin Otte <otte@gnome.org> + + * gst-libs/gst/video/video.c: + [video] Fix Y41B + Chroma components should be aligned on 4byte boundaries. + https://bugzilla.gnome.org/show_bug.cgi?id=595849 + +2009-09-21 18:49:06 +0200 Benjamin Otte <otte@gnome.org> + + * gst/videotestsrc/videotestsrc.c: + [videotestsrc] Fix Y41B + Chroma components should be aligned on 4byte boundaries. + https://bugzilla.gnome.org/show_bug.cgi?id=595849 + +2009-10-07 07:28:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * gst-libs/gst/interfaces/streamvolume.c: + streamvolume: Define cbrt() if it's not available + Fixes build on Win32, bug #597537. + +2009-09-24 16:05:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstfactorylists.c: + factorylist: Use gst_caps_can_intersect() instead of _intersect() + This is faster and results in less allocations. + +2009-09-26 12:10:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't set the external ghostpads blocked but only their targets + Pad blocks should never be done on external pads as outside elements + might want to use their own pad blocks on them and this will lead to + conflicts and deadlocks. + +2009-09-26 12:04:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Only use the object lock for protecting the subtitle elements + Using the decodebin lock will result in deadlocks if the subtitle encoding + is accessed from a pad-added handler. + +2009-09-26 18:11:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Improve debugging of pad blocks + +2009-09-23 16:07:36 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + playbin2/playsink: Use gst_object_ref_sink() instead of calling both separately + +2009-10-06 19:59:11 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + configure: Add an 'else' to pangocairo check + Otherwise it exits if it fails. + +2009-10-06 19:35:50 -0700 David Schleef <ds@schleef.org> + + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: add pattern with out-of-gamut colors + Adds a pattern with out-of-gamut colors in a checkerboard + pattern with in-gamut neighbors. Useful for checking YCbCr->RGB + color matrixing. Correct matrixing and clamping will cause the + checkerboard pattern to be invisible. + +2009-10-06 19:17:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: use CLOSE_SOCKET() instead of close() + Use CLOSE_SOCKET instead of directly calling close() because it does the right + thing for windows. + Fixes #597539 + +2009-10-01 14:19:41 +0200 Robert Swain <robert swain gmail com> + + * gst/audioresample/gstaudioresample.c: + audioresample: fix printf variable type + Change printf variable type from %lu to %" G_GUINT64_FORMAT " as it + should be for guint64. + Fixes #596981 + +2009-09-30 23:22:35 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + ffmpegcolorspace: Use the ffmpegcolorspace debug category + Move gstffmpegcodecmap debug to the ffmpegcolorspace category + +2009-09-22 11:58:26 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/gdp/gstgdppay.c: + gdppay: Don't repeat tags buffers for every new segment + Only send a tag buffer when one is received, not after every new segment + event/update. + +2009-09-28 20:25:35 -0700 David Schleef <ds@schleef.org> + + * gst/typefind/gsttypefindfunctions.c: + typefind: detect 'ftypqt ' as video/quicktime + +2009-10-06 19:47:00 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + back to development -> 0.10.25.1 + +=== release 0.10.25 === + +2009-10-05 13:56:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + Release 0.10.25 + +2009-10-05 13:49:10 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2009-10-01 17:17:55 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.24.4 pre-release + +2009-10-01 10:37:38 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + pango: Unpremultiply Cairo's ARGB to match GStreamers ARGB + +2009-09-28 22:06:11 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: make the lock recursive for now + Fixes #583255 + +2009-09-28 21:54:03 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: fix the vis property getter + +2009-09-30 18:06:56 +0100 Christian F.K. Schaller <christian.schaller@collabora.co.uk> + + * gst-plugins-base.spec.in: + Add missing file to spec file + +2009-09-17 16:57:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + * tests/check/libs/cddabasesrc.c: + cddabasesrc: Fix string leaks in the unit test and a leak in cddabasesrc + +2009-09-17 23:42:52 +1000 Jonathan Matthew <jonathan@d14n.org> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + * tests/check/libs/cddabasesrc.c: + cddabasesrc: ignore URI fragments that look like device paths + Rhythmbox uses cdda:// URIs of the form cdda://track#device, which + worked before the fix for bug #321532. + Also adds a check for negative track numbers and some unit tests for URI + parsing. + Fixes bug #595454. + +2009-09-17 01:20:45 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.24.3 pre-release + +2009-09-15 15:23:49 -0700 Michael Smith <msmith@songbirdnest.com> + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: don't ever return NULL in list of strings. + +2009-09-14 12:18:33 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaysink.c: + playsink: Expose mute,volume,vis-plugin and font-desc properties + https://bugzilla.gnome.org/show_bug.cgi?id=594623 + +2009-09-09 12:42:04 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaysink.c: + GstPlaySink: Expose 'reconfigure' as an action signal. + +2009-09-09 11:17:28 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaysink.c: + GstPlaySink: Expose flags as a gobject property. + +2009-09-08 11:35:20 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplayback.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playback: Register playsink as an element. + This allows using playsink from outside the playback plugin. + Add code to be able to request the sink pads using standard GStreamer API. + TODO : expose GObject properties/signals. + +2009-09-12 14:55:06 +0300 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs.types: + docs: add new gst_stream_volume_get_type to types file + This is needs to get Gobject features to show up in the docs. + +2009-09-12 15:48:11 -0700 David Schleef <ds@schleef.org> + + * ext/ogg/gstoggdemux.c: + oggdemux: Fix duration calculation for truncated files + If the last page of a stream has a granulepos of -1, that is, + it doesn't complete a packet, we need to continue to search + for the last granulepos. + +2009-09-12 14:01:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introspection: Build pkgconfig before all libraries and set PKG_CONFIG_PATH + This way g-ir-scanner can find the gstreamer-*-0.10 pkg-config files. + +2009-09-12 02:23:07 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ext/theora/theoraenc.c: + theoraenc: Fix a string leak in _getcaps() + +2009-09-11 23:49:11 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/LINGUAS: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.24.2 pre-release + +2009-09-11 21:44:18 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/audioresample.c: + check: Improve audioresample test + Make the audioresample test work with CK_FORK=no, and + turn a g_print into a GST_INFO. + +2009-09-11 22:09:06 +0200 Benjamin Otte <otte@gnome.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix crashes with even widths + The fix for green lines introduced by commit + 35fdfcc6258c66ba462a4330a35deffb0f2b501d caused invalid memory accesses + for even widths. This patch fixes it. + +2009-09-11 15:11:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Implement GstStreamVolume interface + +2009-09-11 15:04:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/volume/gstvolume.c: + * gst/volume/gstvolume.h: + * tests/check/Makefile.am: + * tests/check/elements/volume.c: + volume: Implement GstStreamVolume interface + +2009-09-11 14:54:17 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/streamvolume.c: + * gst-libs/gst/interfaces/streamvolume.h: + * gst/playback/Makefile.am: + * win32/common/libgstinterfaces.def: + interfaces: API: Add GstStreamVolume interface + Fixes bug #567660. + +2009-09-11 12:20:10 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: properly fix the HTTP manual mode + When we're not parsing HTTP, return EPARSE when we get an HTTP + message. + +2009-09-11 10:16:15 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/mixertrack.h: + mixertrack: add READONLY and WRITEONLY flags + Should really have been READABLE and WRITABLE, but those are hard to + add whilst maintaining backwards compatibility. See #343615. + API: GST_MIXER_TRACK_READONLY + API: GST_MIXER_TRACK_WRITEONLY + +2009-09-11 10:02:54 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: fix build against core that has debugging disabled + The macro is called GST_DISABLE_GST_DEBUG, not GST_DISABLE_DEBUG. + +2009-09-11 07:38:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + videorate: Add Since marker for the new skip-to-first property + +2009-09-11 07:36:10 +0200 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + * gst/videorate/gstvideorate.h: + videorate: Make videorate work with a live source + Add a property that makes videorate skip to the first buffer it + receives instead of padding the stream from segment start to the + first real buffer. + Fixes bug #567928. + +2009-09-11 07:20:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/fft/gstfft.h: + * gst-libs/gst/fft/gstfftf32.h: + * gst-libs/gst/fft/gstfftf64.h: + * gst-libs/gst/fft/gstffts16.h: + * gst-libs/gst/fft/gstffts32.h: + fft: Mark one function as const and add notes that the structs should be private in 0.11 + +2009-09-10 22:28:19 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: add human readable format names when logging + Add string array with human readable names for format and type to be used in log + statements. + +2009-09-10 18:19:36 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppay: don't print RTP timestamps as clocktime + Don't try to print the RTP timestamp as a GstClockTime, it's just a guint32. + Fixes #594757 + +2009-09-10 16:55:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + playbin(2): Document that the volume property uses a linear scale + Fixes bug #571610. + +2009-09-10 14:04:53 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: don't return EPARSE + Don't blindly return EPARSE when http mode is disabled. + Restore old http mode after temporarily setting it to TRUE. + +2009-09-10 12:38:16 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: add ugly backward compat hack + Check for pulsesink < 0.10.17 because it includes code that is now included in + baseaudiosink. Disable that code in baseaudiosink to be compatible with the + older version. + +2009-09-10 10:56:29 +0200 Benjamin Otte <otte@gnome.org> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Handle YVU9/YUV9 conversion with odd widths + A green border could be visible when converting to Y444 or RGB, because + the last chroma samples weren't copied correctly + +2009-09-10 10:43:37 +0200 Benjamin Otte <otte@gnome.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix YVU9 and YUV9 + - Buffer sizes were computed different from ffmpegcolorspace + - Green bar on right size for widths not divisable by 4 + +2009-09-10 10:08:28 +0200 Benjamin Otte <otte@gnome.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix image for odd widths in some formats + videotestsrc rounds chroma down. This causes it to omit the last chroma + value completely for odd widths when the chroma is downsampled. + This patch special cases the last pixel to not be rounded down. + +2009-09-10 10:02:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: Handle kate and cmml as sparse streams too + +2009-09-10 10:00:16 +0200 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: Better handling of sparse streams by sending segment updates + Fixes bug #397419. + +2009-09-10 09:43:28 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gsturidecodebin.c: + docs: tell a biit more about uri-decodebin and buffering + +2009-09-09 18:24:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: take clock time in setcaps + Take the time of the clock so that the last_time field is set. This is important + for sinks that restart their internal ringbuffer after a caps change and need to + know the last know position. + +2009-09-09 18:24:15 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudioclock.c: + audioclock: add some more debug + +2009-09-09 16:44:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/theoraenc.c: + theoraenc: Print a debug message with supported formats + +2009-09-07 17:29:38 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Check supported input formats in getcaps function + We want to fail early when an older libtheora release is used that does + not support Y444 or Y42B formats, so use a getcaps function that does + this. + +2009-09-04 21:37:04 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Implement support in theoraenc for Y444 and Y42B + Fixes bug #594165. + +2009-09-04 20:23:52 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Refactor the buffer copy code + +2009-09-04 16:59:49 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Split yuv_buffer creation into its own function + +2009-09-04 16:49:08 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Split out buffer resize in its own function + +2009-09-04 14:06:09 +0200 Benjamin Otte <otte@gnome.org> + + * ext/theora/theoraenc.c: + theora: Add assertions that functions don't fail + Some functions in libtheora can return an error, but that error cannot + ever happen inside theoraenc. In those cases assert that it doesn't. + +2009-09-09 16:21:57 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: make stop state configurable + Make it easy to experiment with different stop states (NULL and READY) + +2009-09-09 16:19:32 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: correct for clock reset + When going to NULL, we reset the ringbuffer so that it starts beck from 0. We + also make sure that the clock is updated with the elapsed time so that it + alsways increments even when the ringbuffer goes back to 0. When this happened + we need to adjust the sample position for the reset ringbuffer. + Fixes #594136 + +2009-09-09 16:17:02 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.h: + baseaudiosink: whitespace fixes + +2009-09-09 16:16:40 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: add more debug + +2009-09-09 10:25:33 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/interfaces/colorbalance.h: + * gst-libs/gst/interfaces/mixer.h: + whitespace fixes + +2009-09-08 17:59:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/video/gstvideosink.c: + * gst-libs/gst/video/gstvideosink.h: + videosink: add "show-preroll-frame" property + Add a property to disable rendering of video frames during preroll. This + will only work for videosinks that use the new ::show_frame() vfunc instead + of overriding basesink's preroll and render vfuncs directly. + API: GstVideoSink:show-preroll-frame + +2009-09-08 17:43:26 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + ximagesink, xvimagesink: use new GstVideoSink::show_frame() vfunc + +2009-09-08 18:19:19 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/video/gstvideosink.c: + * gst-libs/gst/video/gstvideosink.h: + video: add GstVideoSinkClass::show_frame() + Add ::show_frame() vfunc which maps to basesink's ::preroll and ::render + vfuncs and add some gtk-doc chunks. + API: GstVideoSinkClass::show_frame() + +2009-09-08 16:00:47 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/interfaces/navigation.c: + navigation: don't do stuff inside g_return_val_if_fail() statements + Or it will all fall apart if someone compiles with -DG_DISABLE_ASSERT. + +2009-08-31 20:24:22 +0200 Havard Graff <havard.graff@tandberg.com> + + * gst-libs/gst/interfaces/navigation.c: + navigation: Fix compiler warning with MSVC + Fixes bug #594275. + +2009-08-31 20:31:56 +0200 Havard Graff <havard.graff@tandberg.com> + + * gst-libs/gst/rtp/gstbasertpdepayload.c: + basertpdepayload: fix event forwarding + +2009-08-31 20:36:37 +0200 Havard Graff <havard.graff@tandberg.com> + + * gst-libs/gst/rtp/gstrtcpbuffer.c: + rtcpbuffer: add missing break in handling of GST_RTCP_TYPE_PSFB + Fixes #594258 + +2009-09-08 13:02:46 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + fix whitespace + +2009-09-08 12:59:20 +0200 Håvard Graff <havard.graff@tandberg.com> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: improve slave skew resync + The old one did the mistake of not actually advancing the ringbuffer, it just + adjusted the segbase, introducing the whole lenght of the ringbuffer as an + extra delay in the pipeline. + Also make sure that the resync can never go back in time, producing the same + timestamps that has already been produced, as this can cause severe problems + for sinks and other synching mechanisms. + Fixes #594256 + +2009-09-07 17:13:12 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: disable typefinder for headerless flac + Disable headerless flac typefinder as long as it happily typefinds anything + including /dev/urandom as flac and as long as it's not particularly useful + given that such streams don't really exist in the wild. + Also fix up some comments so that gtk-doc doesn't complain about them. + +2009-09-06 15:21:43 +0300 René Stadler <mail@renestadler.de> + + * sys/ximage/ximagesink.c: + ximagesink: fix small memory leak when setting window title + +2009-09-06 01:42:42 +0300 René Stadler <mail@renestadler.de> + + * sys/xvimage/xvimagesink.c: + xvimagesink: fix small memory leak when setting window title + +2009-09-05 13:55:27 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * .gitignore: + introspection: Add *.gir and *.typelib to .gitignore + +2009-09-05 13:46:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introduction: Fix out-of-tree build + +2009-09-05 13:13:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/rtsp/Makefile.am: + rtsp: Fix introspection build by ordering sources/headers in dependency order + +2009-09-05 13:09:17 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/Makefile.am: + audio: Remove debug echo + +2009-09-05 13:08:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/Makefile.am: + audio: Fix build of introspection data by using dependency order for the headers/sources + +2009-09-05 12:31:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introspection: Strip Gst prefix from all types/functions + +2009-09-05 11:49:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/netbuffer/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/video/Makefile.am: + introspection: Fix build if gir-repository is not installed + +2009-09-05 11:37:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/Makefile.am: + video: Add gobject-introspection support + +2009-09-05 11:35:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/tag/Makefile.am: + tag: Add gobject-introspection support + +2009-09-05 11:34:11 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/sdp/Makefile.am: + sdp: Add gobject-introspection support + +2009-09-05 11:31:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/pbutils/Makefile.am: + libs: Add nodist headers and sources to the introspection files + +2009-09-05 11:28:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/rtsp/Makefile.am: + rtsp: Add gobject-introspection support + +2009-09-05 11:25:42 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/rtp/Makefile.am: + rtp: Add gobject-introspection support + +2009-09-05 11:23:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/riff/Makefile.am: + riff: Add gobject-introspection support + +2009-09-05 11:20:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/pbutils/Makefile.am: + pbutils: Add gobject-introspection support + +2009-09-05 11:17:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/netbuffer/Makefile.am: + netbuffer: Add gobject-introspection support + +2009-09-05 11:15:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/Makefile.am: + interfaces: Add gobject-introspection support + +2009-09-05 11:04:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/fft/Makefile.am: + fft: Add gobject-introspection support + +2009-09-05 11:01:44 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/cdda/Makefile.am: + cdda: Add gobject-introspection support + This is disabled for now until gobject-introspection is fixed + +2009-09-05 10:50:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/audio/Makefile.am: + audio: Add gobject-introspection support + +2009-09-05 10:40:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * gst-libs/gst/app/Makefile.am: + app: Add gobject-introspection support + +2009-09-05 10:20:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 00a859e to 19fa4f3 + +2009-09-04 15:48:06 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: fix midi typefinding + We already have a audio/midi typefinder so don't override it with the midi in + RIFF typefinder or else we fail to detect plain midi files. + +2009-09-04 11:29:55 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: do buffering for more uris + Add ssh://, ftp://, sftp://, myth:// to the list of uris that require + buffering. + Fixes #594020 + +2009-09-04 07:36:10 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add typefinder for Midi inside RIFF + This is a standard Midi file format that should be supported by + all Midi decoders and also has the mimetype audio/mid according to + the Midi specification homepage. + Fixes bug #594094. + +2009-09-03 18:53:19 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: add some debugging + +2009-09-03 17:53:47 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: handle gaps + Add various conversion functions between time<->bytes<->rtptime that will be + used later on. + Refactor the min/max packet length code so that it can be used for both + sample/frame based payloaders. Cache the returned values. + code cleanups. + When we discover a DISCONT buffer, make the outgoing RTP timestamps have the + same gap as the GStreamer timestamps gap. + +2009-09-03 14:13:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: fix frame duration calculations + Fix the calculation of the frame duration and rtp timestamps. + Add some debugging + +2009-09-03 14:13:12 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + rtppay: add some debugging + +2009-09-02 19:49:57 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: use offsets for RTP timestamps + Have a custom sample/frame function to generate an offset that the base class + will use for generating RTP timestamps. This results in perfect RTP timestamps + on the output buffers. + Refactor setting metadata on output buffers. + Add some more functionality to _flush(). + Handle DISCONT on the input buffers and set the marker bit and DISCONT flag on + the next outgoing buffer. + Flush the pending data on EOS. + +2009-09-02 13:13:54 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: move function around + +2009-09-02 13:12:28 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: fix sample duration calculation + +2009-09-02 12:24:22 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppay: more refactoring + Unify the sample/frame buffer handling code by making the functions plugable. + +2009-09-02 12:03:27 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + audiortppayload: refactor some more + Refactor getting the packet min/max size and alignment code. + Refactor converting bytes to time. + change some variable to something shorter. + +2009-09-02 10:46:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + * win32/common/libgstrtp.def: + audiortppayload: refactor and cleanup + Always use the adapter when we need to fragment the incomming buffer. Use more + modern adapter functions to avoid malloc and memcpy. The overall result is that + the code looks cleaner while it should be equally fast and in some case avoid a + memcpy and malloc. + Use the adapter timestamping functions for more precise timestamps in case of + weird disconts. + Cache some values instead of recalculating them. + Add gst_base_rtp_audio_payload_flush() to flush a certain amount of bytes from + the internal adapter. + API: GstBaseRTPAudioPayload::gst_base_rtp_audio_payload_flush() + +2009-09-03 16:56:55 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + Update common + +2009-09-03 11:29:23 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppay: add property to disable perfect RTP time + Add a property to disable the generation of perfect RTP timestamps. By default + it is active. + API: GstBaseRTPPayload::perfect-rtptime + +2009-09-02 19:47:26 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + basertppay: allow subclasses to influence RTP time + Allow subclasses to use the OFFSET field on RTP buffers to influence the way in + which RTP timestamps are generated. Usually timestamps are created from the + GStreamer timestamps on the buffer, which could result in imperfect RTP + timestamps. + +2009-09-02 19:44:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.h: + basertppay: add macro to cast + +2009-09-01 18:26:52 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiopayload: code cleanups + +2009-09-01 18:08:14 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + audiortppayload: don't check adapter + the adapter is never NULL so we don't need to check it. + Use _scale functions to avoid overflows. + +2009-09-03 00:14:02 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * gst/typefind/Makefile.am: + * gst/typefind/gsttypefindfunctions.c: + typefinding: move gio-based xdg mime typefinder from -bad to -base + Its purposes is mainly to avoid false positives (e.g. mp3 typefinder + reporting a 20% probability and somesuch). Won't be registered if + the gio plugin has been disabled via ./configure --disable-gio. + +2009-09-01 15:06:51 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: GstAdapter is not a GstObject and should be freed with g_object_unref + +2009-09-01 15:02:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * sys/v4l/v4lsrc_calls.c: + v4lsrc: fix timestamping for when we do not have a clock yet + Should fix #559049. + +2009-09-01 14:30:41 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * sys/v4l/v4lsrc_calls.c: + v4lsrc: don't log not-yet-initialised integer value + +2009-09-01 14:28:48 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * sys/v4l/v4lsrc_calls.c: + v4lsrc: avoid unnecessary run-time type checks in custom buffer finalize + And reflow code to be more indent friendly. + +2009-09-01 10:39:52 +0200 Jonas Holmberg <jonas.holmberg@axis.com> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + basertppayload: Make instance init faster by not reading /dev/urandom 3 times + ... which is the default seed when creating a new GRand. Because + GLib in older versions used buffered IO this would take a lot of time. + Instead use the global GRand for getting random numbers and keep the + three instance GRand for backward compatibility with a simple seed. + Fixes bug #593284. + +2009-08-31 22:48:01 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: improve caps filter functionality. Fixes #590146. + Also use the capsfilter if there is no src-peer as the caps constrain what + we can do. Don't create any_caps as a default, as we check for NULL to skip the + filtering. This is a (small) performance regression as we always intersect + otherwise. + +2009-08-31 11:10:55 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Post missing plugin messages before any error messages + +2009-08-28 19:06:57 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + cddabasesrc: safely handle the indexes + +2009-08-28 19:06:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstrtsp.def: + def: add new rtsp symbols + +2009-08-28 14:08:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.h: + basertppayload: whitespace fixes. + +2009-08-27 18:59:49 +0200 Marc-André Lureau <mlureau@flumotion.com> + + * gst/gdp/gstgdppay.c: + Bug 593035 - set IN_CAPS for streamheader buffer + +2009-08-26 16:56:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + * gst/playback/gststreamselector.c: + playbin: The internally linked pad of the selector might be NULL in some cases + +2009-08-26 16:45:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + * gst/playback/gststreamselector.c: + playbin: Fix iterate internal linked pads functions for the stream selectors + This now used the new gst_iterator_new_single() function and as a side effect + fixes bug #592864. + +2009-08-26 09:08:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-read.c: + riff: Add support for AVF files + AVF is valid RIFF but has AVF0 has first fourcc instead of RIFF. + Fixes bug #593117. + +2009-08-26 09:08:12 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Detect AVF files as RIFF files too + AVF is valid RIFF but has AVF0 as first fourcc instead of RIFF. + Partially fixes bug #593117. + +2009-08-21 11:51:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/audioresample.c: + audioresample: Add unit test for checking for timestamp drifts + This also checks for perfect timestamping and offsetting. + +2009-08-21 10:11:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audioresample/gstaudioresample.c: + audioresample: Fix drain processing + In case we have to convert internally don't process output length input samples + but history length input samples. + +2009-08-21 10:02:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/audioresample.c: + audioresample: Improve debugging a bit in the unit test + +2009-08-21 10:00:49 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audioresample/gstaudioresample.c: + audioresample: On the first buffer we need discont handling + Otherwise we won't get upstream timestamps and everything and all + output buffers would have -1 timestamps. + +2009-08-21 08:23:39 +0400 Руслан Ижбулатов <lrn1986@gmail.com> + + * configure.ac: + * gst/subparse/gstsubparse.c: + subparse: Remove dependency on regex.h as it's not used anyway + Fixes bug #592544. + +2009-08-21 06:58:31 +0200 Kipp Cannon <kcannon@ligo.caltech.edu> + + * gst/audioresample/gstaudioresample.c: + audioresample: Fix buffer overflow when pushing the drain + +2009-08-21 06:57:58 +0200 Kipp Cannon <kcannon@ligo.caltech.edu> + + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + audioresample: Fix timestamp drift + Fixes bug #591934. + +2009-08-24 11:34:35 -0700 David Schleef <ds@schleef.org> + + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstogmparse.c: + * ext/pango/gsttextrender.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/playback/gstinputselector.c: + * gst/playback/gststreamselector.c: + * gst/subparse/gstsubparse.c: + * sys/v4l/gstv4lmjpegsink.c: + * sys/v4l/gstv4lmjpegsrc.c: + * sys/v4l/gstv4lsrc.c: + Remove Ronald Bultje from Authors field + Replaced with "GStreamer maintainers + <gstreamer-devel@lists.sourceforge.net>" or just removed, + depending on the number of other authors. + +2009-08-24 15:06:28 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: fix refcounting of _get_sink() + g_value_set_object() increases the refcount of the sink, which is not needed + because the object should already be refcounted. Make sure this is always the + case and use g_value_take_object(). + Fixes: #592884 + +2009-08-24 14:39:16 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + rtsp: Mark Transport as supporting multiple values. + +2009-08-24 13:58:17 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.h: + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtspmessage.h: + rtsp: Added missing Since tags. + +2009-08-24 13:27:55 +0200 Eero Nurkkala <ext-eero.nurkkala at nokia.com> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: Improve audiosink startup performance + When we start the ringbuffer, immediatly continue processing samples if the + writer prepared some for us. + Fixes #545807 + +2009-08-17 11:53:43 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Added new API for sending using GstRTSPWatch. + The new API to send messages using GstRTSPWatch will first try to send the + message immediately. Then, if that failed (or the message was not sent + fully), it will queue the remaining message for later delivery. This avoids + unnecessary context switches, and makes it possible to keep track of + whether the connection is blocked (the unblocking of the connection is + indicated by the reception of the message_sent signal). + This also deprecates the old API (gst_rtsp_watch_queue_data() and + gst_rtsp_watch_queue_message().) + API: gst_rtsp_watch_write_data() + API: gst_rtsp_watch_send_message() + +2009-08-17 11:46:32 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Made gst_rtsp_watch_queue_data() thread safe. + +2009-06-17 15:37:53 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Added gst_rtsp_connection_set_http_mode(). + With gst_rtsp_connection_set_http_mode() it is possible to tell the + connection whether to allow HTTP messages to be supported. By enabling HTTP + support the automatic HTTP tunnel support will also be disabled. + API: gst_rtsp_connection_set_http_mode() + +2009-06-16 19:35:23 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Allow gst_rtsp_connection_do_tunnel() to just setup decoding context. + If the second connection passed to gst_rtsp_connection_do_tunnel() is NULL + then just setup the base64 decoding context for the first connection. + +2009-06-16 19:04:54 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Write as much as possible in gst_rtsp_source_dispatch(). + Try to write as much as possible if there are multiple messages queued. + +2009-06-16 18:38:02 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Add error_full callback to GstRTSPWatchFuncs. + The error_full callback is similar to the error callback, but allows for + better error handling. For read errors a partial message is provided to + help an RTSP server generate a more correct error response, and for write + errors the write queue id of the failed message is returned. + +2009-08-17 18:29:17 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Made read_line() support LWS. + Rewrote read_line() to support LWS (Line White Space), the method used by + RTSP (and HTTP) to break long lines. Also added support for \r and \n as + line endings (in addition to the official \r\n). + +2009-08-20 14:12:50 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: Do not split headers which should not be split. + From RFC 2068 section 4.2: "Multiple message-header fields with the same + field-name may be present in a message if and only if the entire + field-value for that header field is defined as a comma-separated list + [i.e., #(values)]." This means that we should not split other headers which + may contain a comma, e.g., Range and Date. + +2009-08-20 14:12:09 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Parse WWW-Authenticate headers correctly. + Due to the odd syntax for WWW-Authenticate (and Proxy-Authenticate) which + allows commas both to separate between multiple challenges, and within the + challenges themself, we need to take some extra care to split these headers + correctly. + +2009-06-17 21:46:27 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Improve parse_line(). + Make parse_line() handle keys with multiple values on one line correctly. + +2009-06-17 23:15:23 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Rewrote setup_tunneling(). + Rewrote setup_tunneling() to use normal GstRTSPMessages instead of hard + coded strings and duplicates of the message parsing code. + +2009-08-24 10:20:16 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: Rewrote gen_tunnel_reply(). + Rewrote gen_tunnel_reply() to generate a normal GstRTSPMessage rather + than a hard coded string. + +2009-08-24 10:19:35 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Ignore the Content-Length for POST requests. + The Content-Length for POST requests with an x-sessioncookie header should + be ignored as the length is bogus and only there to fool proxies. + +2009-06-17 20:52:48 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Normalize lines (remove extra whitespace) before parsing. + +2009-06-10 13:11:31 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Made parse_string() return a result. + This will catch parsing errors when a too long string is received. + +2009-06-10 11:43:31 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Improved parsing of messages. + Do not abort message parsing as soon as there is an error. Instead parse + as much as possible to allow a server to return as meaningful an error as + possible. + +2009-06-09 17:54:20 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtspmessage.c: + * gst-libs/gst/rtsp/gstrtspmessage.h: + rtsp: Added support for HTTP messages + +2009-06-09 16:22:17 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Added gst_rtsp_connection_create_from_fd(). + API: gst_rtsp_connection_create_from_fd() + +2009-06-09 15:27:17 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Add initial buffer support. + The initial buffer contains data for a connection which should be used + before starting to actually read anything from the socket. + +2009-08-24 13:15:06 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsink.c: + appsink: don't block in paused + When we are asked to unlock we should either leave the render function or call + the wait_preroll method to release the stream lock. + Fixes #592657 + +2009-08-24 13:06:36 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: fix includes for appsrc/appsink + +2009-08-24 11:24:27 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: Add support for the Authentication-Info header. + The Authentication-Info header is defined in RFC 2617 (Digest Access + Authentication). + +2009-08-20 13:11:07 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + * tests/check/pipelines/oggmux.c: + oggmux: don't drop the streamheader field from the output caps + Revert previous 'fix' for bug #588717 and fix it properly, whilst + maintaining the streamheader field on the output caps. Also make + sure we don't leak header buffers we couldn't push when downstream + is unlinked. Add unit test for the presence of the streamheader + field on the output caps and for the issue from bug #588717. + +2009-08-18 21:45:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstinputselector.c: + * gst/playback/gststreamselector.c: + streamselector/inputselector: Use iterate internal links instead of deprecated get internal links + +2009-08-19 09:31:51 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Avoid duplicated headers. + Remove any existing Session and Date headers before adding new ones + when sending a request. This may happen if the user of this code reuses + a request (rtspsrc does this when resending after authorization fails). + +2009-08-18 16:49:58 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Corrected the HTTP digest authorization computation. + Do not use sizeof() on an array passed as an argument to a function and + expect to get anything but the size of a pointer. As a result only the + first 4 (or 8) bytes of the response buffer were initialized to 0 in + auth_digest_compute_response() which caused it to return a string which + was not NUL-terminated... + +2009-08-18 11:15:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: Also send SEEK events directly to a subpicture sink + +2009-08-18 08:39:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: If a custom text sink is used, send events to it too + Before, SEEK events would be sent to the video sink, which wouldn't + be linked in any way to the subtitle part of the pipeline and + subparse would never see the SEEK event. This would then seek + the audio/video but the subtitles would continue from the old + position instead. + Fixes bug #591664. + +2009-08-18 08:20:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Make missing plugins emit a warning message, not an error message + The problem with an error message is, that it will stop playback completely + while it could be that only a audio decoder plugin is missing and the video + could be played with the available plugins. + See bug #591677. + +2009-08-13 17:42:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Post a correct error message for unknown types + Before we had STREAM/WRONG_TYPE but it's really CORE/MISSING_PLUGIN + because a plugin is missing and nothing else is wrong. + Also make it an error instead of a warning. + Really fixes bug #591677. + +2009-08-13 15:48:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Post a missing plugin message additional to the error message on unknown types + Fixes bug #591677. + +2009-08-13 10:59:35 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + playbin2: fix error message string + Fixes #591577. + +2009-08-05 15:38:32 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst-libs/gst/riff/riff-read.c: + riff: align API doc of gst_riff_parse_chunk with reality + +2009-08-05 15:36:30 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: avoid assertion failure on empty/NULL caps + +2009-08-12 12:09:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Also detect SVG by the <svg> starting tag + Not all SVG images have the DOCTYPE specified. + +2009-08-10 20:18:24 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: don't use GLib-2.18 function + g_checksum_reset() was added only in GLib 2.18, but we still require + only 2.16, so work around that if we only have 2.16. Fixes #591357. + +2009-08-10 15:40:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/pipelines/streamheader.c: + streamheader: Fix caps leak in the vorbisenc unit test + +2009-08-10 14:14:30 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/pipelines/streamheader.c: + checks: fix stream header unit test hanging in gst_task_cleanup_all() + Set pipelines to NULL state and unref when done. + +2009-08-10 10:17:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/md5.c: + * gst-libs/gst/rtsp/md5.h: + rtsp: Use GLib's GChecksum instead of our own MD5 implementation + +2009-08-10 03:46:39 +0300 Mart Raudsepp <leio@gentoo.org> + + * gst-libs/gst/interfaces/navigation.c: + navigation: Fix doc blurb typo for gst_navigation_send_key_event + +2009-08-09 12:13:16 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: Allow . instead of , as millisecond delimiter in srt subtitles + Fixes bug #591207. + +2009-08-08 17:51:10 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosrc.c: + * gst/playback/gstinputselector.c: + * gst/playback/gststreamselector.c: + Revert inlines that cause compiler warnings and are not needed anyway + +2009-08-08 15:54:57 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/interfaces/propertyprobe.c: + * gst-libs/gst/riff/riff-media.c: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/video/gstvideofilter.c: + * gst-libs/gst/video/gstvideosink.c: + gst-libs: Remove dead assignments and resulting unused variables. + +2009-08-08 15:54:41 +0200 Edward Hervey <bilboed@bilboed.com> + + * ext/alsa/gstalsadeviceprobe.c: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstoggaviparse.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/pango/gsttextrender.c: + * ext/vorbis/vorbisenc.c: + ext: Remove dead assignments and resulting unused variables. + +2009-08-08 15:54:02 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/adder/gstadder.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/audioresample/gstaudioresample.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstfactorylists.c: + * gst/playback/gstinputselector.c: + * gst/playback/gstplaysink.c: + * gst/playback/gststreamselector.c: + * gst/tcp/gsttcpclientsink.c: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/vs_image.c: + * gst/videotestsrc/gstvideotestsrc.c: + gst: Remove dead assignments and resulting unused variables + +2009-08-07 13:05:42 +0200 Josep Torra <n770galaxy@gmail.com> + + * docs/design/draft-va.txt: + docs: add draft for generic introduction of video acceleration APIs idea + +2009-08-07 08:53:44 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: + Revert "theora: Convert theoradec to libtheora 1.0 API" + This reverts commit f1e142ac9dcfb754d85357b9077d5aee48559dd9. + Temporarily revert until we have a workaround for debian/ubuntu + packaging failure (see http://bugs.debian.org/528710). + +2009-08-07 09:32:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add typefinders for many game sound console formats supported by gme + These are AY, GBS, GYM, KSS, SAP and VGM. SPC and NSF already had typefinders. + +2009-07-16 11:29:20 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + oggmux: fix warning when we're not linked downstream and error out properly + Fix caps warning when there's no element linked downstream, and pass + not-linked flow return value correctly up the chain, so we error out + correctly. Fixes #588717. + +2009-07-31 14:59:03 -0700 David Schleef <ds@schleef.org> + + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: + theora: Convert theoradec to libtheora 1.0 API + +2009-08-06 20:47:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Fix blitting of text over the output buffer and cairo painting + +2009-08-06 09:13:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Fix endianness problems (i.e. make it work again on big endian architectures) + +2009-07-31 14:27:28 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/icles/test-colorkey.c: + colorkey-test: fix xsync error + +2009-07-06 23:06:50 +0300 Siarhei Siamashka <siarhei.siamashka@nokia.com> + + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: support for direct conversion from uyvy422 to rgb formats + +2009-07-14 12:33:29 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaysink.c: + playbin2: smarter sink selection. Fixes #588523 + Don't do fallbacks if application specified a sink element. When doing the + fallback use configured default elements instead of hardcoded linux only + elements. Improve error messages accordingly. + +2009-08-06 12:18:36 +0200 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstqueue2.c: + queue2: post error message when pausing task if so appropriate + If a downstream element returns an error while upstream has already + put all data into queue2 (including EOS), upstream will no longer + chain into queue2, so it is up to queue2 to perform some + EOS handling / message posting in such cases. See #589991. + +2009-08-06 12:58:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: change default slave method + Set the default slave method to the much better skew slaving algortihm. + +2009-08-06 12:01:10 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: make buffer writable + Make the input buffer writable before changing its contents. + +2009-08-06 09:55:42 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: fix postscript typefinder probability + Two bytes for a rare format hardly warrants MAXIMUM typefinding + probability, POSSIBLE seems more appropriate. + +2009-08-04 14:55:06 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + pango: Send queries from the srcpad directly to the video sinkpad + +2009-08-04 14:32:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + subparse: Implement POSITION query + +2009-08-04 14:29:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + * gst/subparse/samiparse.c: + subparse: Implement SEEKING query + +2009-08-04 14:14:53 +0200 John Millikin <jmillikin@gmail.com> + + * configure.ac: + * gst-libs/gst/tag/gstid3tag.c: + * gst-libs/gst/tag/gstvorbistag.c: + tag: Add support for ALBUM_ARTIST tag in vorbiscomments and ID3v2 tags + Require latest core for this. + Fixes bug #590430. + +2009-08-04 12:46:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + pango: Add support for xRGB and BGRx formats + +2009-08-04 12:22:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + pango: Fix endianness issues from the pangocairo switch + cairo's ARGB is in native endianness, i.e. ARGB on big endian architectures + and BGRA on little endian architectures. + +2009-08-04 12:11:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + pango: Re-add shading support which was dropped by a previous patch + +2009-08-04 11:58:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * ext/pango/gsttextoverlay.c: + pango: Check if pangocairo supports vertical rendering and fix properties + +2009-08-04 11:45:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Use PROP_X instead of ARG_X consistently + +2009-08-04 11:42:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/pango/gsttimeoverlay.c: + pango: Some minor cleanup + +2009-08-04 11:36:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + pango: Check for pangocairo instead of pangoft2 + +2009-08-04 11:35:10 +0200 Young-Ho Cha <ganadist@chollian.net> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + * ext/pango/gsttextrender.c: + * ext/pango/gsttextrender.h: + pango: Use pango-cairo instead of pango-ft2 + pango-cairo will always use the native font rendering backend + of the platform and provides better results. + Fixes bug #340887. + +2009-08-04 10:35:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add SVG typefinder + +2009-08-04 10:29:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Add postscript typefinder + +2009-07-30 15:08:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Use static caps again for MPEG4 typefinding + +2009-07-30 15:05:28 +0200 Arnout Vandecappelle <arnout@mind.be> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Implement better & more flexible MPEG4 typefinding + This detects more MPEG4 streams as MPEG4. + Fixes bug #556537. + +2009-07-30 14:04:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + cddabasesrc: Allow to specify the device name in the URI + The allowed URI scheme is now: + cdda://(device#)?track + Also allow every combination of uppercase and lowercase + characters for the protocol part. + Fixes bug #321532. + +2009-07-30 12:37:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Restrict width/height to 2^15 - 1 + Otherwise integer overflows will happen, resulting in segmentation faults. + Fixes bug #590243. + +2009-07-29 14:55:04 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Fix indention of template header + +2009-07-29 14:10:35 +0200 Philip Jägenstedt <philipj@opera.com> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: Clarify documentation about caps and linkage + Fixes bug #589095. + +2009-07-29 07:42:05 +0200 Benjamin Gaignard <benjamin@gaignard.net> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Fix typefinding of SDP files + Fixes bug #589574. + +2009-07-28 20:50:06 +0200 Kipp Cannon <kcannon@ligo.caltech.edu> + + * gst/audioresample/gstaudioresample.c: + audioresample: Take the output offsets from the input if possible + Fixes bug #588915. + +2009-07-28 15:54:14 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Make sure to allocate enough memory for the temporary buffer + and fix scaling of odd-height interlaced video. + +2009-07-28 15:18:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Fix interlaced scaling for I420 + ...and some other minor mistakes in the previous change. + +2009-07-28 14:12:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.h: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Include interlacing information in the AVPicture + This later allows to handle interlaced AVPicture different than + progressive ones which is needed for horizontally subsampled YUV + formats, see bug #589242. + +2009-07-28 13:55:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + videoscale: Add support for interlaced content + videoscale is not mixing content of two seperate fields anymore + and does scaling on every field separately. + Fixes bug #588761. + +2009-08-06 01:44:24 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + back to development -> 0.10.24.1 + +2009-08-05 02:03:44 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst-plugins-base.doap: + Add 0.10.24 release to the doap file + +=== release 0.10.24 === + +2009-08-05 00:56:58 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Release 0.10.24 + +2009-08-05 00:38:40 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2009-08-01 17:26:23 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + * tests/check/gst/typefindfunctions.c: + typefinding: fix detection of fLaC id packet in broken flac-in-ogg + There are flac-in-ogg files without the usual flac packet framing + and these files just have a 4-byte fLaC ID packet as first packet. + We need to recognise the type just from these four bytes if we + want oggdemux to recognise these streams correctly. + +2009-07-30 14:40:50 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/LINGUAS: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/lv.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.24.5 pre-release + +2009-07-29 14:15:53 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiofilter.c: + audiofilter: Don't assert on slightly different caps + Plugins should not assert on incompatible caps, caps negotiation will + fail anyway. + +2009-07-30 13:42:21 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: reset pending flush-stop flag in state_changed. (mostly) Fixes #590146. + +2009-07-30 09:28:20 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: bump Gtk+ requirement of GUI examples from 2.12 to 2.14 + The gio mount example needs GtkMountOperation, which is new in 2.14. + +2009-07-27 10:29:27 +0100 Balachandran C <balachandran_c@rediffmail.com> + + * ext/alsa/gstalsasrc.c: + alsasrc: set alsasrc->handle back to NULL when closing device + Fixes crashes in gst_alsa_find_device_name() when probing or + reading the device-name property (e.g. when doing a dot-file + dump). Fixes #589797. + +2009-07-24 19:26:40 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gststreamselector.c: + playbin: rename GType of stream selector pad to avoid clash with input-selector from -bad + Rename the GType of the pads of playbin's internal stream selector + element so they don't use the same type name as input-selector's + pads. Fixes #589622. + +2009-07-24 13:39:55 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.23.4 pre-release + +2009-07-24 13:46:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/examples/v4l/.gitignore: + ignores: Ignore v4l probing example binary + +2009-07-24 09:35:38 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefind: recognise Kate spu subtitles as well + Recognise spu-subtitles, SUB and K-SPU as valid categories for + Kate subtitles as well. + +2009-07-24 00:42:16 +0300 Stefan Kost <ensonic@users.sf.net> + + * common: + Automatic update of common submodule + From fedaaee to 94f95e3 + +2009-07-22 14:21:43 +0100 Christian Schaller <christian.schaller@collabora.co.uk> + + * gst-plugins-base.spec.in: + Update spec file with latest changes + +2009-07-20 17:28:20 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * win32/common/_stdint.h: + * win32/common/audio-enumtypes.c: + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/interfaces-enumtypes.c: + * win32/common/video-enumtypes.c: + 0.10.23.3 pre-release + +2009-07-20 12:51:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: call send_event directly + We can't call gst_element_send_event() from a streaming thread as it gets the + state lock. Instead call the send_event method directly until we have a nice API + for this in basesrc. + Fixes #588746 + +2009-07-03 04:42:24 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosink.c: + audiosink: Add stream-status messages + Fixes #587695 + +2009-07-03 04:41:05 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosrc.c: + audiosrc: Add stream-status messages + See #587695 + +2009-07-20 10:53:11 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/adder/gstadder.c: + gstadder: Don't forget to free pending events on flush/dispose. + Fixes #588747 + +2009-07-12 10:08:12 +0200 Edward Hervey <bilboed@bilboed.com> + + * tests/check/elements/adder.c: + tests/adder: Add stream consistency checking. Fixes #588748 + +2009-07-12 10:07:34 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: Make sure tags are properly serialized. Fixes #588746 + We do this by letting the basesrc base class handle the tags. + +2009-07-13 09:28:54 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + adder: Collect incoming tag events and send them after newsegment. Fixes #588747 + +2009-07-16 09:32:46 +0200 Edward Hervey <bilboed@bilboed.com> + + * ext/vorbis/vorbisdec.c: + vorbisdec: Check for empty tag strings. Fixes #588724 + +2009-07-14 17:03:35 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstqueue2.c: + queue2: fix leak and improve buffering + Keep track of the max requested position and compare this to the write position + in the temp file to get the current amount of buffered data. + Fix memleak of all incomming buffers. + Fixes #588551 + +2009-07-15 17:40:14 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/Makefile.am: + * gst/playback/gstinputselector.c: + * gst/playback/gstinputselector.h: + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybin2.c: + playbin2: use private copy of input-selector + We shouldn't really depend on elements from -bad for stream + selection in playbin2, so use a private copy of input-selector + until the selector plugin is ready to be moved to -base or -good. + Fixes #586356. + +2009-07-15 17:26:32 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstinputselector.c: + * gst/playback/gstinputselector.h: + playback: add private copy of the input-selector from gst-plugins-bad + Not hooked up yet though. See #586356. + +2009-07-14 19:00:36 +0200 Filippo Argiolas <filippo.argiolas@gmail.com> + + * tests/examples/v4l/Makefile.am: + examples: fix v4l probe example build + Fixes bug #588550. + +2009-07-14 19:00:10 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.23.2 pre-release + +2009-07-14 16:24:10 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/LINGUAS: + * po/tr.po: + Add Turkish translations + +2009-07-14 15:31:13 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/adder.c: + adder: One more attempt to fix the adder test + Give up and discard and recreate the alsasrc after checking it can + be opened, due to some strange crash inside alsa when we don't. + +2009-07-14 15:06:41 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/adder.c: + adder: Perform get_state() in the unit test + Wait for the alsasrc to return to NULL after setting it to PAUSED for + testing, otherwise it leads to segfaults later on. + +2009-07-14 14:39:32 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/adder.c: + adder: Don't fail when alsasrc is unavailable + Make the liveadder test succeed silently when it can't be completed + either because alsasrc is unavailable, or because the device is + inaccessible. + +2009-07-13 22:51:48 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + * gst/typefind/gsttypefindfunctions.c: + typefinding: use subtitle/x-kate for Kate subtitle streams and application/x-kate for the rest + Differentiate subtitle streams and lyrics/cracktastic/complex streams via + the category string in the headers. This seems like a useful distinction + to make, and also seems more future-proof. See #525743. + +2009-02-21 13:18:10 +0000 Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> + + * ext/ogg/gstoggmux.c: + oggmux: add Kate caps to the list of accepted types + See #525743. + +2009-07-13 21:56:46 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gsturidecodebin.c: + uridecodebin: treat uri-schemas incasesensitive + Treat uri-schemas incasesensitive. This is mandated in rfc2396 section 3.1. + Fixes not showing buffering messages e.g. for HTTP://... + +2009-07-13 21:54:47 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/interfaces/navigation.c: + navigation: simplify docs + Make short-desc short - its used in the toc. Strip uneeded markup. + +2009-07-13 18:31:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/libgstnetbuffer.def: + * win32/common/libgstvideo.def: + win32: Fix exports + Remove methods from video base classes that have moved to -bad. + Add gst_netaddress_to_string + +2009-07-13 17:56:58 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/examples/gio/.gitignore: + ignores: ignore the giosrc-mounting example binary + +2009-07-13 17:54:40 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/interfaces/navigation.c: + navigation: Add some partial documentation + Add a general documentation blurb for the GstNavigation functionality. + Still lacks some example code and detail on how to implement it. + +2009-07-13 17:52:39 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for Siren codec and make two descriptions non-translatable + +2009-07-13 12:23:20 -0400 Olivier Crête <olivier.crete@collabora.co.uk> + + * common: + Automatic update of common submodule + From 5845b63 to fedaaee + +2009-07-13 18:21:49 +0200 Elliott Sales de Andrade <quantum.analyst at gmail.com> + + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: + riff: add siren to the RIFF parser + Add siren7 caps to the RIFF parser. + +2009-07-13 14:55:59 +0200 Filippo Argiolas <filippo.argiolas@gmail.com> + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/v4l/Makefile.am: + * tests/examples/v4l/probe.c: + v4lsrc: add a simple test case for device probing + +2009-07-03 11:38:01 +0200 Filippo Argiolas <filippo.argiolas@gmail.com> + + * configure.ac: + * sys/v4l/Makefile.am: + * sys/v4l/gstv4lelement.c: + v4lsrc: optional support for device probing with gudev + Enumerate v4l devices using gudev if available. + Fixes bug #583640. + +2009-07-10 23:24:36 +0100 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: add since tags to docs + +2009-07-10 21:29:51 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: don't automatically start pipeline in DB + Keep the pipeline paused when we detect download buffering. The user has to + manually start the pipeline for now because we can't estimate when the buffering + will finish or when we have underrun. + +2009-07-10 21:01:39 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstqueue2.c: + queue2: flush differently, avoiding deadlocks + Don't flush the file by closing and opening it but instead use g_freopen. This + avoids a deadlock in shutdown because we emit the temp-location property change + with the wrong lock held. + +2009-07-10 20:25:43 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: add a checkbox for progressive download + +2009-07-10 20:24:14 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: Fix template construction + Fix the construction of the temporary filename construction as the application + name can be NULL and we don't want a separator between the prgname and the + template. + +2009-07-10 20:04:33 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplay-enum.c: + * gst/playback/gstplay-enum.h: + * gst/playback/gstplaybin2.c: + playbin2: add support for progressive download + Add a new playbin2 flag (initially disabled) to enable progressive download + buffering in uridecodebin. + +2009-07-10 19:59:30 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add download property + Add a download property that will attempt to configure queue2 into progressive + download buffering. + Make sure we only enable download buffering for quicktime and flv formats. + +2009-07-10 19:49:46 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstqueue2.c: + queue2: add temp-template property + Add a new temp-template property so that queue2 can securely allocate a + temporary filename. Deprecate the temp-location property for setting the + location but still use it to notify the allocated temp file. + +2009-07-10 20:06:28 +0100 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + adder: add a caps-property to avoid to need to plug a capsfilter afterwards + Adder can only handle one common format accross the pads. Thus one needed to add + a capsfilter afterwards and manage the caps. Now one can simply set the caps on + the property. + +2009-07-10 18:59:05 +0100 Stefan Kost <ensonic@users.sf.net> + + * tests/check/elements/adder.c: + adder: skip live-seek text if we have no audiosrc, add new test + The seek-test needs a real audiosrc. Also add a test that checks that adder is + reusable. Finaly handle warnings as warnings to fix a assertion. + +2009-07-10 19:16:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosink.c: + gio: Also post a "not-mounted" message from giosink + +2009-07-10 17:15:48 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/gio/giosrc-mounting.c: + gio: Remove workaround for playbin2 bug in the sample application + The playbin2 bug was #588078. + +2009-07-10 17:08:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: Make it possible for READY->PAUSED to succeed after it failed the first time + If READY->PAUSED failed in the source element we would've swapped + the current and next group already. To allow READY->PAUSED to succeed + after the first failure we have to swap the current and next group + back again. This also ensure that we're again in the same state + as before the failed state change and not at the next group. + This was especially a problem for playbin2 pipelines that use the + new mounting support in giosrc as the source would fail for READY->PAUSED + the first time, the application mounts the location and then tries + to go READY->PAUSED again (and this time it would succeed). + Fixes bug #588078. + +2009-07-10 11:42:51 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/gio/Makefile.am: + * tests/examples/gio/giosrc-mounting.c: + gio: Add example application that shows how to handle the "not-mounted" message + +2009-07-10 11:24:57 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + gio: Remove the experimental status from the GIO plugin + Fixes bug #510417. + +2009-07-10 11:24:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + gio: Add documentation for the new "not-mounted" and "file-exists" messages + +2009-07-09 13:45:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesrc.c: + gio: Make sure that we have the correct stream position when starting + +2009-07-08 17:24:19 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesink.c: + gio: Make sure to flush the output stream if it shouldn't be closed + Otherwise there might still be unwritten data after the element + has stopped. + +2009-07-08 17:19:29 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesink.c: + * ext/gio/gstgiobasesink.h: + * ext/gio/gstgiobasesrc.c: + * ext/gio/gstgiobasesrc.h: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + gio: Don't close the GIO streams for the giostream{src,sink} elements + This makes it possible to do something useful with the streams + after the element has stopped. Fixes bug #587896. + +2009-07-08 17:19:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/pipelines/gio.c: + gio: Try to reuse the pipeline with the same stream objects + +2009-07-08 17:02:54 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesink.c: + * ext/gio/gstgiobasesrc.c: + gio: Improve the error message if a stream is already closed before usage + +2009-07-08 16:55:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosink.c: + gio: Post a custom file-exists message on the bus if the file already exists + An application can handle this message, remove the file in question + and restart the pipeline again without showing an error. + This fixes bug #529300. + +2009-07-08 16:54:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosrc.c: + gio: Use OPEN_READ instead of NOT_FOUND if a location is not mounted + +2009-07-08 16:50:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosink.c: + gio: Use OPEN_WRITE instead of OPEN_READ as error category in giosink + +2009-07-08 15:52:35 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiosrc.c: + gio: Post a custom "not-mounted" message on the bus + This allows applications to mount the GFile if possible and restart + the pipeline instead of simply giving an error. + +2009-07-08 15:08:32 +0200 Philip Jägenstedt <philipj@opera.com> + + * gst/audioconvert/gstchannelmix.c: + audioconvert: Fix compilation when debugging is disabled + Fixes bug #587980. + +2009-07-07 20:23:23 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesink.c: + * ext/gio/gstgiobasesink.h: + * ext/gio/gstgiobasesrc.h: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosink.h: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsink.h: + gio: Add vfunc for requesting the stream for the sinks too + +2009-07-07 20:21:36 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesink.c: + * ext/gio/gstgiobasesink.h: + * ext/gio/gstgiobasesrc.c: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsrc.c: + gio: Some more random cleanup + +2009-07-07 20:20:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgio.c: + * ext/gio/gstgiobasesink.c: + * ext/gio/gstgiobasesrc.c: + * ext/gio/gstgiobasesrc.h: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + * ext/gio/gstgiosrc.h: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsrc.c: + * ext/gio/gstgiostreamsrc.h: + gio: Update my mail address and copyright + +2009-07-07 20:18:00 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/gio/gstgiobasesrc.c: + * ext/gio/gstgiobasesrc.h: + * ext/gio/gstgiosrc.c: + * ext/gio/gstgiostreamsrc.c: + * ext/gio/gstgiostreamsrc.h: + gio: General clean up and simplification + The GInputStreams are now requested by a vfunc from + the subclasses instead of relying that the subclass + sets it until it's needed. + This might also fix bug #587896. + +2009-07-06 22:31:12 +0100 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: keep sending newsegments after seeking + Adder sends with timestamps from 0 upwards. After seeking we need to send + new-segments to get correct positions-queries. + +2009-07-06 20:44:00 +0100 Stefan Kost <ensonic@users.sf.net> + + * tests/check/elements/adder.c: + adder: make test more robust + Add audioconverts to the live-seeking test to make it negotiate. + +2009-06-30 17:19:50 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: use core performance log category + +2009-07-05 21:29:40 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/adder/gstadder.c: + adder: Call set_flushing(TRUE) for flushing seeks *when* the streaming is stopped. + This ensures that collectpads' cookie is properly updated so that when the streaming + threads will restart and be checking for the flushing status of all pads there will + be no inconsistent state. + +2009-07-05 18:01:38 +0200 Hans-Peter Nilsson <hp@gcc.gnu.org> + + * ext/pango/gstclockoverlay.c: + pango: Call tzset() before localtime_r() + POSIX and your local friendly ctime(3) manual entry says that localtime_r isn't + required to set the state variables that define the current timezone. Indeed, + glibc (at least 2.9) doesn't do this for subsequent calls. The effect is that + if the system timezone is changed for a running program between two calls to + gst_clock_overlay_render_time, it won't be noticed. For glibc, changing the + timezone equals /etc/localtime being modified. + Fixes bug #587676. + +2009-07-01 17:33:14 -0700 David Schleef <ds@schleef.org> + + * ext/Makefile.am: + build: remove spurious schroedinger reference + +2009-07-01 10:25:43 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + * ext/Makefile.am: + * ext/schroedinger/Makefile.am: + * ext/schroedinger/gstschro.c: + * ext/schroedinger/gstschrodec.c: + * ext/schroedinger/gstschroenc.c: + * ext/schroedinger/gstschroparse.c: + * ext/schroedinger/gstschroutils.c: + * ext/schroedinger/gstschroutils.h: + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/gstbasevideocodec.c: + * gst-libs/gst/video/gstbasevideocodec.h: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideodecoder.h: + * gst-libs/gst/video/gstbasevideoencoder.c: + * gst-libs/gst/video/gstbasevideoencoder.h: + * gst-libs/gst/video/gstbasevideoparse.c: + * gst-libs/gst/video/gstbasevideoparse.h: + * gst-libs/gst/video/gstbasevideoutils.c: + * gst-libs/gst/video/gstbasevideoutils.h: + basevideo: send basevideo back to remedial school + Move basevideo classes and schroedinger plugin to -bad. + +2009-07-01 12:54:21 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/netbuffer/gstnetbuffer.h: + netaddress: add constant for max len + +2009-07-01 12:48:38 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/netbuffer/gstnetbuffer.c: + * gst-libs/gst/netbuffer/gstnetbuffer.h: + netbuffer: add gst_netaddress_to_string + Add function to serialize a net address to a string. + API: GstNetAddress::gst_netaddress_to_string() + +2009-06-30 18:44:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: make fd:// uri use buffering too + fd:// usually operate in push mode only and are thus suitable for buffering. + +2009-06-30 14:46:38 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaybin2.c: + * gst/volume/gstvolume.c: + volume: include "1.0=100%" in property description + +2009-06-30 14:45:51 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaysink.c: + playsink: remove unused property defs + +2009-06-29 17:11:50 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/multichannel.c: + multichannel: rewrite the new doc comment a bit + Its part of the audio lib. + +2009-06-29 14:34:02 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaysink.c: + playsink: Avoid a segfault when the video sink fails to start + Don't attempt to display the subpictures and segfault when the + video sink failed to start (and hence the videochain is NULL). + +2009-06-29 15:14:07 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/audio/gstringbuffer.h: + ringbuffer: add vmethod to clear the ringbuffer + Add a vmethod so that subclasses can be notified when they should clear the data + in the ringbuffer. + +2009-06-29 14:00:14 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/riff/riff-media.c: + riff-media: Fix the fourcc caps property for VC-1/WMVA + The caps property for carrying fourccs is 'format', not 'fourcc' + +2009-06-29 12:20:52 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: include in.h for FreeBSD compat + Fixes #586920 + +2009-06-29 12:20:20 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstapp.def: + defs: add defs for new appsink buffer-list method + +2009-06-29 12:14:43 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsink.h: + appsink: add docs and signals + Add docs for the new callback. + Add signals for the new buffer-list support. + +2009-06-29 10:24:36 +0200 Branko Subasic <branko@lnxbranko2.se.axis.com> + + * tests/check/elements/appsink.c: + Added unit tests for buffer list support in appsink. + +2009-06-17 11:12:08 +0200 Branko Subasic <branko@lnxbranko2.se.axis.com> + + * gst-libs/gst/app/gstappsink.c: + Added buffer list support. + +2009-06-17 09:23:11 +0200 Branko Subasic <branko@lnxbranko2.se.axis.com> + + * gst-libs/gst/app/gstappsink.h: + Added buffer list support. + +2009-06-29 09:36:27 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: Include winsock2.h after defining WINVER. + Similar to bug #587080. + +2009-06-29 09:31:40 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Moved a comment. + +2009-06-27 23:23:02 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/audio/multichannel.c: + docs: add basic section docs for multichannel and relocate the ones for audio + Add section docs for multichannel, so that it has a short desc in the toc too. + Move the section docs in adio up, so that the follow the copyright like + elsewhere. + +2009-06-26 21:11:45 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/v4l/gstv4lelement.c: + * sys/v4l/gstv4lsrc.c: + v4l: open/close device in ready. + Simillar change like in v4l2src. This allows probing feature in paused, where + streaming is noit yet started. + +2009-06-10 17:05:22 +0300 René Stadler <rene.stadler@nokia.com> + + * gst/playback/gstplaysink.c: + playbin2: fix initial volume handling also when reusing the element + This is a follow-up to commit 452988, making it work correctly when the audio + chain is reused. + +2009-06-26 21:48:58 +0400 Руслан Ижбулатов <lrn1986@gmail.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Define WINVER before including any win headers + Fixes bug #587080. + +2009-06-27 00:50:54 +0300 René Stadler <mail@renestadler.de> + + * gst-libs/gst/riff/riff-read.c: + riff: prevent crash if rounded up tag size exceeds data size + When rounding up `tsize' exceeds the remaining buffer size, `size' underflows + and an invalid read past the buffer data follows. + +2009-06-26 15:17:21 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/gstbasevideocodec.c: + basevideocodec: By default don't allow caps changes on the srcpad + This fixed playback of Dirac files with schrodec when upstream wants + a different width/height, basevideocodec accepts this and then + pushes buffers with new caps but content of the old caps. + In the best case this will just result in wrong unit size and a + failure in basestransform elements. + +2009-06-26 14:11:21 +0100 Jan Schmidt <thaytan@noraisin.net> + + * autogen.sh: + autogen.sh: Use printf instead of 'echo -n'. Check for automake-1.1[01] + Check for more automake command variants. Use printf instead of 'echo -n' + for portability + +2009-06-26 13:41:38 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From f810030 to 5845b63 + +2009-06-26 13:14:02 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstscreenshot.c: + screenshot: don't leak message + +2009-06-25 12:04:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: lower the h264 typefinder's probability + A NEARLY_CERTAIN is absolutely not warranted given the kind + of things it checks for. Even a LIKELY is probably not entirely + appropriate. + +2009-06-24 15:13:56 +0100 Jan Schmidt <jan.schmidt@sun.com> + + * common: + Automatic update of common submodule + From f3bb51b to f810030 + +2009-06-24 09:48:41 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for multipart + So we get slightly nicer error messages when multipartdemux is missing. + +2009-06-23 18:07:31 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: only unflush when we flushed before + Ass suggested by Stefan Kost: + Keep track of when the sinkpad was set to flushing and unflush the pad when an + upstream flushing seek failed. + +2009-06-23 15:10:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: fix leak when the source fails to change state + +2009-06-23 12:40:56 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/subparse/gstssaparse.c: + ssaparse: avoid leaking all buffers + +2009-06-22 22:18:03 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/check/elements/adder.c: + adder: test seek handling in adder + This tests seeking on an adder that has a normal and a live source connected. + Wheter the current behavior is the desired one needs to be discussed still + (see #586033) + +2009-06-22 16:17:10 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: pass the xwindow along to not look at the yet unset var. + When we call this from xwindow_new, x(v)imagesink->xwindow is not yet set. + +2009-06-22 11:40:33 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + x(v)imagesink: catch tags and show title in own window + Refactor the code that sets the window title. Catch tag-events and use title + metadata for the window title. + +2009-06-21 19:42:15 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: Name gaussian noise "gaussian-noise" instead of just "gaussian" + Also make all the function arrays constant. + +2009-06-21 12:27:37 +0200 Kipp Cannon <kcannon@ligo.caltech.edu> + + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/audiotestsrc/gstaudiotestsrc.h: + audiotestsrc: Add support for generating gaussian white noise + This patch adds support for stationary white Gaussian noise. + The Box-Muller algorithm is used to generate pairs of independent + normally-distributed random numbers. + Fixes bug #586519. + +2009-06-20 23:46:28 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Fix NV12 and NV21 transformations + Fix some stride problems, fix the nv12 to nv21 direct transformation, + and implement a direct conversion to yuv444 to save CPU. + +2009-06-20 22:36:21 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Fix NV12 painting for odd strides/heights + +2009-06-19 22:16:43 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/cdparanoia/gstcdparanoiasrc.c: + cdparanoia: run-time license is LGPL now that we require cdparanoia 0.10.2 + cdparanoia has an LGPL v2.1 license since 0.10.1 and we now require 0.10.2. + Finally fixes #531035. + +2009-06-19 21:25:54 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/cdparanoia/gstcdparanoiasrc.c: + cdparanoia: try to guess a good cache size if it's set to -1 + Try to guess from the paranoia-mode setting whether playback or + ripping is wanted, and use a smaller cache size if we're likely + to be doing playback, to avoid a long startup delay. Since this + was the value used in older cdparanoia versions, it should be + fine in any case. See #586331. + +2009-06-19 11:27:40 +1000 Jonathan Matthew <jonathan@d14n.org> + + * configure.ac: + * ext/cdparanoia/gstcdparanoiasrc.c: + * ext/cdparanoia/gstcdparanoiasrc.h: + cdparanoia: expose cache size setting + This setting was added in cdparanoia 10.2. The default value is good + for audio extraction, but lower values (previous versions of cdparanoia + used 150) are better for realtime playback. + Fixes #586331. + +2009-06-19 17:43:03 +0100 Christian Schaller <christian.schaller@collabora.co.uk> + + * gst-plugins-base.spec.in: + Make build of schro plugin conditional + +2009-06-19 15:52:34 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + * win32/common/libgstrtp.def: + basertppayload: add support for bufferlists + Based on patch from Ognyan Tonchev. + See #585559 + +2009-06-19 15:33:04 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtpbuffer: use new convenience functions + New core convenience functions makes the list getters and setters trivial. + Maybe even too trivial... + +2009-06-18 19:07:22 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstrtp.def: + defs: add new symbol to win32 defs file + Based on patches by Ognyan Tonchev. + See #585559 + +2009-06-18 19:04:52 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtp: cleanups, add _list_get_seq() too + Clean up the docs a little. + Add missing _list_get_seq method. + Add new symbols to the docs + +2009-06-18 18:47:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + * win32/common/libgstrtp.def: + rtp: cleanups + Add Since tags to docs + Move some code around + Add win32 symbols + +2009-06-18 17:46:01 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + * tests/check/libs/rtp.c: + rtp: add bufferlist support + +2009-06-18 18:03:40 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + rtp: pass data to macros instead of GstBuffer + +2009-06-18 17:42:10 +0100 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/libgstrtsp.def: + win32: Add gst_rtsp_watch_queue_data() to the exports + Fix the tests by exporting the new symbol from the win32 dlls + +2009-06-18 18:13:22 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: appname might be NULL + Don't set title if appname is unknown. + +2009-06-18 17:58:06 +0300 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: set window title from application name + +2009-06-09 19:14:00 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspurl.c: + rtsp: Made the parsing of the RTSP URL scheme more generic. + +2009-06-15 13:58:26 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Added gst_rtsp_watch_queue_data(). + gst_rtsp_watch_queue_data() is similar to gst_rtsp_watch_queue_message() + but allows for queuing any data block for writing (much like + gst_rtsp_connection_write() vs. gst_rtsp_connection_send().) + API: gst_rtsp_watch_queue_data() + +2009-06-09 16:37:09 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Only extract the session ID from RTSP responses. + +2009-06-09 19:06:57 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspurl.c: + rtsp: Added support for parsing IPv6 addresses in RTSP URLs. + +2009-06-09 14:31:18 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Use getaddrinfo() to support both IPv4 and IPv6. + +2009-06-17 15:37:53 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Improved base64 decoding in fill_bytes(). + The base64 decoding in fill_bytes() expected the size of the read data to + be evenly divisible by four (which is true for the base64 encoded data + itself). This did not, however, take whitespace (especially line breaks) + into account and would fail the decoding if any whitespace was present. + +2009-06-17 14:00:23 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + audiosrc: fix get_offset + When we need to jump to the most recently captured sample, jump to where the + next sample will be written instead of to some old data. + Fixes #581460 + +2009-06-17 13:18:18 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + audiosink: free the ringbuffer when going to NULL + Unparent and free the ringbuffer when going to NULL, like we do with the + audiosrc element. We can do this now because we correctly manage the time + jumping back to 0. + +2009-06-17 13:17:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + audio: correctly handle short read/writes + +2009-05-05 15:37:54 +0300 René Stadler <rene.stadler@nokia.com> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: add some extra logging for buffer timestamps + +2009-06-17 11:22:51 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: more seeking fixes. + When a seek failed upstream, make sure the adder sinkpad is set unflushing again + so that streaming can continue. + We only have a pending segment when we flushed. + Set the flush_stop_pending flag inside the appropriate locks and before we + attempt to perform the upstream seek. + Add some more comments. + Use the right lock to protect the flags in flush_stop. + See #585708 + +2009-06-17 07:24:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: Free iterator after removing all groups + +2009-06-16 19:38:17 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/gstvideofilter.c: + videofilter: Add a default get_unit_size function + This returns the correct values for all formats that are handled by + GstVideoFormat and makes all the custom get_unit_size functions in + many elements unnecessary. + +2009-06-16 18:57:20 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: add Timestamp header field + fixes #585994 + +2009-06-16 18:15:06 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: set smarter target state on uridecodebin + Set the target state of the newly added uridecodebins to somthing else that + PAUSED so that we keep their state in sync with the playsink state. + Fixes #585268 + +2009-06-16 18:13:53 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: set the sink flag on the element + +2009-06-16 18:09:43 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add debug message + +2009-06-16 14:05:04 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + audiosink, audiosrc: do the class_ref()s in the right class_init functions + Spotted by Philip Jägenstedt. Hopefully fixes #585970 for real. + +2009-06-15 15:39:09 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + audiosink,audiosrc: ref the audio ring buffer class and type in class_init + Hack around thread-safety issues in GObject and our racy _get_type() + functions (we could easily fix the _get_type() functions, but we still + need to hack around the GObject class races until we require a newer + GLib version, I think). + +2009-06-15 12:57:39 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + audiosrc: return FALSE when receiving a SEEK event + When receiving a seek event, return FALSE as we don't implement seeking. + +2009-06-15 11:06:25 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/seek.c: + Don't use deprecated GTK API + Fixes bug #585758. + +2009-06-15 11:40:00 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: send flush_stop when seeking failed + At least do the fix to sent the flush_stop when seeking failed to ensure we + keep no pads flushing. before it was send when the seeking worked which is just + plain wrong and was not the intention. + +2009-06-12 15:17:14 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Use a more consistent naming of GstRTSPRec variables. + +2009-06-12 15:11:05 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Call message_sent() callback for all sent messages. + Previously the messages_sent() callback was only called for messages + which had a CSeq, which excluded all data messages. Instead of using the + CSeq as ID, use a simple index counter. + +2009-06-14 22:13:41 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/theora/theoradec.c: + * ext/vorbis/vorbisdec.c: + oggdemux: post/send tags with the container-format tag + For this to work properly, theoradec and vorbisdec need to put + tag events received from upstream into the pending_events list + so they get pushed out after any newsegment event, not before. + +2009-06-14 20:30:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + * tests/old/examples/seek/cdplayer.c: + Don't use deprecated GTK API + Fixes bug #585758. + +2009-06-12 16:31:00 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/adder/gstadder.c: + adder: send flush-stop earlier + When no flush-stop has been sent by upstream, we have to send one ourselves to + continue playback. Do this as soon as the collect function is called instead of + after we possibly pushed segment events (that got then flushed out) + +2009-06-12 13:55:33 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: add shuttle controls + +2009-06-12 13:55:02 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/stepping2.c: + example: fix compile + +2009-06-12 13:52:25 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/Makefile.am: + examples: build the stepping2 example + +2009-06-12 13:52:02 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: update for new step API + +2009-06-12 13:22:47 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: do reverse seeks more accurate + For reverse seeking with the accurate flag set, try to be more precise by + seeking a little bit after the requested position. + +2009-06-11 22:32:28 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/ogg/gstogmparse.c: + * gst/subparse/gstssaparse.c: + * gst/subparse/gstssaparse.h: + * gst/subparse/gstsubparse.c: + * gst/subparse/gstsubparse.h: + subparse, ogmparse: post tags with GST_TAG_SUBTITLE_CODEC + Make subtitle parsers post a taglist with codec tags, so the application + knows what kind of subtitle a subtitle stream is. Fixes #576552. + +2009-06-11 19:12:51 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + ringbuffer: handle border cases in resampler + +2009-06-11 13:28:20 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + docs: Update common. Use upload-doc.mak instead of upload.mak + +2009-06-11 12:39:19 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + docs: fix typo + +2009-06-11 12:17:16 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: reset accum when dropping samples + When we are resampling and we drop samples because we paused, reset the accum + counter because it's now invalid. + +2009-06-11 11:16:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/video/gstbasevideodecoder.h: + docs: Fix a couple of warnings from the docs build. + +2009-06-10 21:36:19 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/testchannels.c: + Don't include config.h multiple times when build audio testchannel app. + Fixes build problem on win32 (#585075). + +2009-06-10 16:56:51 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + playbin2/uridecodebin: Fix connection-speed propagation + uridecodebin expects the passed connection-speed value in kbps, so we + need to divide the value stored in bps by 1000. Also, lower the upper + limit on the properties to the value that we can actually store in our + internal guint (which is plenty high enough) + +2009-06-10 14:37:36 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/subparse/gstsubparse.c: + * tests/check/elements/subparse.c: + subparse: recognise more subrip timestamp variants + Be even less restrictive in what we accept for .srt timestamps when + typefinding and parsing subrip subtitles and add a unit test for + the 'new' format. Fixes #585197. + +2009-06-09 22:00:53 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtsptransport.h: + rtsp: add some more docs + +2009-06-09 18:24:55 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: Avoid a compiler warning. + +2009-06-09 18:23:28 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: Updated documentation for GstRTSPResult. + Moved GST_RTSP_ELAST to be last in the documentation to match the actual + enum values. + +2009-05-20 17:30:23 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * autogen.sh: + autogen: remove -Wno-portability from here + as it is in configure.ac now. + +2009-06-09 16:28:20 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Plug a memory leak. + Free memory related to any partially read and/or written RTSP messages. + +2009-06-09 12:09:15 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: no need to cause discont when clipping + Remove the discont-when-clipping hack now that basesink provides us with + correctly clipped samples when stepping. + +2009-06-08 17:26:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + audiosink: don't align when we clip + Don't align samples when they were clipped. Not entirely correct but better than + nothing for now. + +2009-06-08 16:41:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/.gitignore: + * tests/examples/seek/stepping2.c: + examples: add stepping example in PLAYING + Add stepping example in PLAYING, audio is a bit distorted because basesink does + not provide good clipping info yet. + +2009-06-08 10:25:00 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: Add description for hdv/aux-* formats. + +2009-06-07 22:20:33 +0400 LRN <lrn1986@gmail.com> + + * ext/schroedinger/Makefile.am: + Added libgstbase to schro's LIBADD + Fixes #585079 + +2009-06-06 02:15:05 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/gstid3tag.c: + libgsttag: don't extract genres from empty ID3v1 tags + If we don't have any other info, don't try to interpret the + genre field. In particular we don't want to interpret a genre + of 0 as 'Blues' if no other fields are set and the entire tag + is just empty. + +2009-06-05 18:13:25 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: make sure varargs are of right type + Explicitly cast the variables to g_object_set to their right types. + +2009-06-05 16:49:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: increase stream probing queues + When we are probing for streams, we want to set the queue size in such a way + that we can scan a maximum amount of data without consuming too much memory. + Therefore, remove the time limit on the queue and only stop scanning after 2MB + of data. + See #584104. + +2009-06-05 14:06:17 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Fixed a typo. + +2009-06-05 14:05:54 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Remove an unused variable. + +2009-06-05 13:59:14 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Removed duplicate initialization of conn->writefd. + +2009-06-05 13:55:08 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Use #defined status codes. + +2009-06-05 13:53:29 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Correct gen_tunnel_reply(). + Prevent gen_tunnel_reply() from generating an incomplete response + in case an error response code is given. + +2009-06-05 10:57:44 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/video-enumtypes.c: + configure: remove AC_C_INLINE which is not needed and causes problems with MSVC + See #584835. Also update win32 files while we're at it. + +2009-06-04 08:57:24 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: API: Add {audio,video,text}-tags-changed signals + Fixes bug #584686. + +2009-06-03 20:42:39 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/vorbis/vorbisdec.c: + vorbisdec: don't put invalid bitrate values into the taglist + Bitrates are stored as 32-bit signed integers in the vorbis + identification headers, but seem to be read incorrectly, + namely as unsigned 32-bit integers, into the vorbis structure + members which are of type long, which makes our check for + values <= 0 fail with files that put -1 in there for unset + values. + +2009-06-03 15:52:54 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/.gitignore: + ignore: add new stepping app to ignore + +2009-06-03 15:31:27 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/Makefile.am: + * tests/examples/seek/stepping.c: + examples: add stepping example. + Add an example of using playbin2 and frame stepping to simulate variable rate + playback based on a sine wave. + +2009-06-03 12:45:08 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.h: + playbin2: also set custom text and subp sinks + Set the custom subpicture and text sinks along with the custom audio and video + sinks when needed. + Fix a little docs blurb too. + +2009-06-02 12:10:39 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: add G_LIKELY because we can + +2009-06-02 09:53:05 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: Fix caps for ogg typefinder. + +2009-05-29 11:10:07 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + docs: remove some cruft from -sections.txt file + +2009-06-01 11:31:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * tests/examples/seek/seek.c: + add framestepping to playbin2 and seek + +2009-06-01 09:59:22 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Avoid compiler warnings with -Wextra. + +2009-06-01 09:58:27 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: Include gst/gstconfig.h to make sure GST_PADDING is defined. + +2009-06-01 09:43:04 +0200 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/sdp/gstsdpmessage.c: + sdp: Remove an unused variable. + +2009-05-30 14:17:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add a lot more conversions from/to 16 bit grayscale + +2009-05-29 00:09:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaybin2.c: + playbin2: Have playbin recognise PGS subpicture streams + Recognise PGS subpicture streams and connect them to the SPU pad + in playsink. Unfortunately this fails badly with negotiation errors + if the SPU is not recent enough to support the stream. I'm not sure + how to add format negotiation in yet. + +2009-05-21 23:11:29 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstdecodebin2.c: + * gst/playback/gsturidecodebin.c: + decodebin/uridecodebin: Recognise subpicture/x-pgs pads and output them. + +2009-05-28 20:37:59 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix volume handling for audio sinks without "volume" property + When using an audio sink without a "volume" property, volume control + would only work for the first song. For the next song, we'd try to + re-use the existing audio chain, but inadvertently set chain->volume + to NULL instead of to the existing volume element. + +2009-05-28 17:05:55 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: cosmetic change to avoid unnecessary line breaks + Looks nicer and works around gst-indent silliness. + +2009-05-28 17:21:35 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: don't lose the ref to the volume element + Only release the ref to the volume element when it is controled by a sink. For + software volume we never have to fear that it will change. + +2009-05-28 15:21:42 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + playbin2: actually use configured audio/video sinks + playbin2 inadvertently used autoaudiosink and autovideosink up to now, + since it would overwrite the sinks configured via the "audio-sink" + and "video-sink" properties with the stream-specific group sinks when + configuring the outputs. Those are usually NULL however, so that would + overwrite the configured sinks with NULL which makes playbin2 then + default to the auto sinks. Fix this by keeping a reference to each + configured sink in playbin2 and setting up the right sinks depending + on whether there is a stream-specific sink or not. + Fixes #584020. + +2009-05-27 17:37:38 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/examples/seek/seek.c: + seek: add volume label and sync with sink volume + Look at the volume and have the pulsemixer open at same time. Unfortunately + playbin2 does not emit notify on volume right, so this polls for now. + +2009-05-27 18:12:10 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: remove leftover elements + Remove all of the elements inside decodebin2 when goint to READY and NULL. + Makes decodebin2 reusable. + Fixes #583750 + +2009-05-27 15:36:51 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2; release refs to volume/mute properties + Release the refs to the volume and mute property elemens before setting the + child elements to READY or NULL. + Fixes #583318 + +2009-05-27 12:10:05 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/gdp/gstgdppay.c: + gdppay: set caps on outgoing buffers + Set caps on outgoing buffers because NULL caps confuse basetransform. + Fixes #583867 + +2009-05-27 11:08:37 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/netbuffer/gstnetbuffer.c: + netbuffer: also note the order of IP4 addresses + IP4 addresses are also stored in network byte order. Make a note of this in the + docs. + +2009-05-26 22:43:34 +0200 Alessandro Decina <alessandro.d@gmail.com> + + * ext/theora/theoraparse.c: + theoraparse: fix assertions in make_granulepos when using the new theora granulepos mapping. Fixes #583903. + +2009-05-26 11:13:35 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Revert "rtspconnection: don't use GLib-2.16 API, we require only 2.14" + This reverts commit 418760cf740332c12c3fd9cf3244af134fa9534b. + We now require GLib 2.16. + +2009-05-26 15:18:09 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + Update common + +2009-05-26 15:37:18 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/netbuffer/gstnetbuffer.c: + netbuffer: document that the port is network order + Document the fact that we store the port number in network order in + GstNetAddress and that the caller should byteswap appropriately. + +2009-05-26 15:23:45 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + * gst/videoscale/vs_image.c: + * gst/videoscale/vs_image.h: + * gst/videoscale/vs_scanline.c: + * gst/videoscale/vs_scanline.h: + videoscale: Add support for 16 bit grayscale in native endianness + +2009-05-26 14:58:28 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Add support for 16 bit grayscale in little/big endian + +2009-05-26 14:38:43 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + videotestsrc: Add support for 16 bit grayscale in native endianness + +2009-01-21 12:33:59 +0100 Andy Wingo <wingo@oblong.net> + + add can-activate-pull property to baseaudiosink + * gst-libs/gst/audio/gstbaseaudiosink.c: Add can-activate-pull property + to baseaudiosink. + +2009-05-26 13:14:07 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: fix boundary case for seeking. + When we have exactly 0 bytes left to search, make sure we stop instead of going + into an infinite loop. + +2009-05-26 11:11:03 +0200 Bastien Nocera <hadess at hadess.net> + + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/cdda/gstcddabasesrc.c: + * gst-libs/gst/cdda/sha1.c: + * gst-libs/gst/cdda/sha1.h: + cddabasesrc: Remove copy of sha1 digest + Remove our copy of sha1 digest now that we depend on glib 2.16. + Fixes #536313 + +2009-05-25 17:54:01 +0100 Christian Schaller <christian.schaller@collabora.co.uk> + + * gst-plugins-base.spec.in: + Update spec file + +2009-05-23 00:33:04 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideoparse.c: + * gst-libs/gst/video/gstbasevideoutils.c: + * gst-libs/gst/video/gstbasevideoutils.h: + * win32/common/libgstvideo.def: + video: don't expose internal gst_adapter_get_buffer() helper function + If it's really needed it should go into GstAdapter in core. + +2009-05-22 21:29:51 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/gstbasevideodecoder.c: + basevideo: Fix memleak + +2009-05-22 21:27:58 -0700 David Schleef <ds@schleef.org> + + * ext/schroedinger/gstschrodec.c: + * ext/schroedinger/gstschroparse.c: + schro: Fix usage of adapter_masked_scan_uint32 + Because *somebody* changed the API without telling me. + +2009-05-22 21:25:06 -0700 David Schleef <ds@schleef.org> + + * ext/schroedinger/gstschro.c: + schro: Change package name to GST_PACKAGE_NAME + +2009-05-22 17:34:10 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/gstbasevideoencoder.c: + basevideo: Add preset interface to encoder + +2009-05-22 17:31:14 -0700 David Schleef <ds@schleef.org> + + * gst/audioresample/gstaudioresample.c: + Run liboil benchmark multiple times + The statistics function requires multiple runs, otherwise + it causes a divide by zero error. + +2009-05-22 19:36:06 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * m4/gst-fionread.m4: + m4: fix 'suspicious cache value' warning for gst-fionread.m4 + .. here as well (should really be moved to common, but I'm too lazy). + +2009-05-22 17:41:50 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/vorbis/vorbisdec.c: + vorbisdec: detect and report errors better + Check the return values of a couple more libvorbis functions and post an error + when something is wrong instead of continuing and crashing. + +2009-05-22 15:49:14 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaysink.c: + playbin2: fix initial volume and mute handling + Use two flags to remember volume/mute changes at times when we don't have the + audiochain yet (e.g. construction). Only set values when they were actualy + changed. This makes pulseaudio's stream restore functional. + +2009-05-22 10:19:51 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From d3a8fab to 888e0a2 + +2009-05-22 09:03:22 +0100 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/libgstvideo.def: + win32: Remove gst_adapter_masked_scan_uint32 from the exports + +2009-05-21 10:48:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + audiosink: improve debug message + +2009-05-19 18:10:55 -0700 Michael Smith <msmith@songbirdnest.com> + + * gst-libs/gst/tag/gstid3tag.c: + gstid3tag: Don't extract a track number unless present. + In ID3v1, a track number is present only if byte 125 is null AND + byte 126 is non-null. If the track number is not present, don't add + a track number tag with value 0. + +2009-05-20 00:48:40 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/video/gstbasevideoutils.c: + * gst-libs/gst/video/gstbasevideoutils.h: + videoutils: remove adapter methods + Remove adapter methods now that they are in core. + +2009-05-20 00:42:29 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstvideo.def: + defs: add new symbols + +2009-05-19 17:47:34 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + autogen: pass -Wno-portability to automake to suppress warnings + GNU make is needed. + +2009-05-19 02:28:20 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/.gitignore: + gitignore: remove bogus *.sgml wildcard - these files are tracked in git + +2009-05-19 18:41:58 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/tcp/gsttcpclientsrc.c: + tcpclientsrc: this is not a live source + Don't mark us as a live source because we are not. + +2009-05-19 18:41:02 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: only send flush_stop when seek failed + This is still not the ultimate fix. Added some comment to explain the troubles. + +2009-05-19 17:17:37 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + audiosink: return the return value of wait_preroll + Return the value that _wait_preroll() returned instead of always WRONG_STATE. + +2009-05-19 16:45:56 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + adder: send flush_stop to match flush_start + Adder was relying that something else sends a flush stop. When using adder with + a livesource it was not getting a flush_stop and thus all pads downstream where + keept flushing. Mark a pending flush_stop and send it when we are working on + the new segment back in the streaming thread. + +2009-05-19 16:02:44 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/examples/seek/seek.c: + seek: ui improvements + Repaint the window black on expose, as this looks nicer when resizing or using + the expander. Also show time after slider, as this saves a whole line (nice on + small displays). + +2009-04-29 18:36:17 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstdecodebin.c: + decodebin: use iterators instead of list + The list api is deprecated. Use threadsafe iterators instead. + +2009-05-19 15:35:54 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: configure caps on decodebin2 + Implement the caps property by setting the configured caps on new decodebin2 + objects. + Fixes #582749 + +2009-05-19 15:34:38 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: avoid some _caps_ref in some cases + Only mess with the caps refcount when we configure different caps. + +2009-05-19 15:27:12 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: fix potential caps leak + Free the user-configured caps in finalize. + +2009-05-19 15:20:27 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: add queue after cdda:// + Add a queue2 after the raw output pads of certain sources such as those for uris + like cdda:// + No tuning of the queue is done yet as the defaults seem to work fine for me. + Fixes #582528 + +2009-05-19 12:45:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: don't loop when at EOS + When we try to read the last page, don't try to read past the upper boundary, as + this might cause endless loops. + See #582942 + +2009-05-19 11:20:19 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/audioresample/gstaudioresample.c: + audioresample: Don't drain remaining buffers after a flush. + If we were resetted (due to a flush), we can not drain the remaining + buffers since they would be pushed before a valid new newsegment event. + +2009-05-18 22:29:07 -0700 Michael Smith <msmith@syncword.(none)> + + * ext/theora/theoradec.c: + theoradec: for 4:2:2, use Y42B (planar) rather than a packed format. + +2009-05-19 01:13:34 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: add more logging and return value checking + +2009-05-19 01:11:45 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: handle the return value from iterator_fold + +2009-05-19 01:03:44 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: use the pad in logging as objects + Helps to differenciate between source and sinks pads. + +2009-04-21 22:54:19 +0300 Stefan Kost <ensonic@users.sf.net> + + * tests/examples/seek/seek.c: + seek: use parser for mp3 and rename variable + +2009-05-18 11:08:56 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: add playbin2 options in expander + Add the playbin2 stream selection options inside an expander to preserve some + space on screen. + +2009-02-10 15:29:10 -0800 David Schleef <ds@schleef.org> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add support for v210 and v216 formats + +2009-05-15 16:21:15 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/gstbasevideocodec.c: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideoencoder.c: + * gst-libs/gst/video/gstbasevideoparse.c: + video: remove // comments + +2009-05-15 16:18:18 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add Y444, v210, v216 formats + +2009-05-15 16:12:37 -0700 David Schleef <ds@schleef.org> + + * configure.ac: + * ext/Makefile.am: + * ext/schroedinger/Makefile.am: + * ext/schroedinger/gstschro.c: + * ext/schroedinger/gstschrodec.c: + * ext/schroedinger/gstschroenc.c: + * ext/schroedinger/gstschroparse.c: + * ext/schroedinger/gstschroutils.c: + * ext/schroedinger/gstschroutils.h: + schro: Move schro plugin from Schroedinger + Previous history is in Schroedinger. Depends on, and is an example + of using, GstBaseVideo* base classes. + Code was reindented, and an #ifdef HAVE_ENCODER removed. + +2009-05-15 10:23:08 -0700 David Schleef <ds@schleef.org> + + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/gstbasevideocodec.c: + * gst-libs/gst/video/gstbasevideocodec.h: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideodecoder.h: + * gst-libs/gst/video/gstbasevideoencoder.c: + * gst-libs/gst/video/gstbasevideoencoder.h: + * gst-libs/gst/video/gstbasevideoparse.c: + * gst-libs/gst/video/gstbasevideoparse.h: + * gst-libs/gst/video/gstbasevideoutils.c: + * gst-libs/gst/video/gstbasevideoutils.h: + video: Copy BaseVideo classes from Schroedinger + +2009-05-15 23:05:45 +0200 Arnout Vandecappelle <arnout@mind.be> + + * gst/tcp/gstmultifdsink.c: + multifdsink: add num-fds property + multifdsink::num-fds + +2009-05-15 20:36:29 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add descriptions for 3GP, JPEG 2000 and Motion JPEG 2000 + +2009-05-14 11:44:27 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/vorbis/vorbisenc.c: + vorbisenc: Implement Preset interface + +2009-05-14 11:43:07 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/theoraenc.c: + theoraenc: Implement Preset interface + +2009-05-14 11:41:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + oggmux: Implement Preset interface + +2009-05-14 21:37:22 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaysink.c: + playbin2: Fix cdda:// playback + Don't send async-start when the playsink has already been configured + before changing state. + +2009-05-14 01:31:48 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: require core CVS for gst_adapter_prev_timestamp() + which is used in the libvisual plugin. + +2009-04-22 18:34:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * AUTHORS: + AUTHORS: fix my email + +2009-04-22 18:35:40 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudioclock.c: + audioclock: make our internal time monotonic + Make the internal time increase monotonically. + +2009-05-13 19:27:54 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/libvisual/visual.c: + visual: remove next_ts variable + We can remove the next_ts variable as we don't use it anymore. + +2009-05-13 19:24:15 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/libvisual/visual.c: + visual: use new adapter timestamp code + Use the new adapter timestamp tracking code to make things easier and produce + vastly better output timestamps. + +2009-05-13 01:35:07 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * po/Makevars: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: avoid conflicts of local *.po files with files in git + Make it so that filenames and line numbers are only stored in the *.pot file + (which is not in git), but not in the individual *.po files. This information + is hardly useful for translators in our case, and it should avoid the constant + conflicts of local *.po files with the ones in git which are caused by the + source files changing and the line numbers being updated. This commit might + cause one last merge conflict for you, which you can work around with + "git checkout po/*.po" before merging or pulling. After that there should + (hopefully) not be any more local modifications of these files (unless + someone committed additions or changes to translated strings and the + *.po files haven't been updated yet, that is). + +2009-05-12 23:51:08 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * tests/check/elements/.gitignore: + * tests/check/elements/audioresample.c: + tests: fix audioresample unit test on big endian architectures + Don't hardcode endianness=1234 in the filtercaps, it will cause + pad link failures which will result in the test timing out. + +2009-05-12 17:18:37 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: fix broken enum nick - it should have a hyphen + The enum nick should be 'sine-table', not 'sine table'. Technically this is + an API/ABI change I guess, but anyone who was using this and didn't report + it deserves this. + +2009-05-01 01:04:48 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/audiotestsrc/gstaudiotestsrc.c: + audiotestsrc: seek to the requested byte offset, not the expected byte offset + +2009-05-01 01:03:06 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/audiotestsrc/gstaudiotestsrc.h: + audiotestsrc: support more than just one channel + +2009-05-12 15:52:41 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/propertyprobe.h: + propertyprobe: Fix typo in the docs + +2009-05-12 12:17:55 +0100 Christian Schaller <christian.schaller@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + * ext/theora/theora.c: + * ext/vorbis/vorbis.c: + Add ranks to the Oggmuxer, Vorbis encoder and Theora encoder + +2009-04-30 16:37:38 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + * gst/videorate/gstvideorate.h: + videorate: handle invalid timestamps better + Handle buffers with -1 timestamps better by keeping track of the en time of the + previous buffer and assuming the -1 timestamp buffer goes right after the + previous one. + when we have two buffers that are equally good, output the oldest buffer once to + minimize latency. + don't try to calculate latency when the input framerate is unknown. + +2009-04-28 11:37:14 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggmux.c: + oggmux: small debug statement in DISCONT + +2009-04-28 11:24:19 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + oggdemux: fix abuse of ogg API, handle broken oggs + When we feed the ogg sync layer, we need to feed it contiguous data even if the + sync layer did not consume all of it yet. This makes sure that it always finds + the next page even for more corrupted files. Use a different read_offset for + this purpose. since we now keep track of the sync layer, we don't have to reset + after finding a start of a page. + Add some more debug info for the error paths. + Only reset the sync layer when we perform a seek operation. + Avoid failure when the next chain has no bos pages but instead simply ignore it. + when we receive unknown page serial numbers mid stream, don't fail but post a + warning and hope that we get back on track later. + Fixes #579642 + +2009-04-30 16:41:51 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: make subpictures a raw output format + Subpictures are a raw format, we want those pads exposed so that playbin2 can do + the subpicture mixing. + +2009-04-27 10:15:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + rtpdepay: add some more comments + +2009-04-17 10:54:31 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudioclock.c: + audioclock: make sure values are ever increasing + +2009-05-05 17:17:00 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: make fallback identity silent + Set the signal-handoffs to FALSE and silent to TRUE for the fallback identity + element so that it consumes less CPU. + +2009-04-17 10:57:16 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + playbin2: handle custom audiosinks differently + Keep track of the autoplugged custom sinks and configure them in the playsink + element when we have collected all streams. + Also make sure that we only select one custom sink. + When unreffing the internal sink, we don't need to change the state to NULL. + +2009-05-12 10:36:25 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: unify custom sink get/set functions + Use one function to set/get all of the different sink types. + cleanup up the subpicture chain too. + Allow setting a custom subpicture sink. + +2009-05-11 18:29:34 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/tunernorm.h: + interfaces: Seperate some more struct definitions from typedefs + +2009-05-11 15:48:56 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/navigation.h: + * gst-libs/gst/interfaces/videoorientation.h: + * gst-libs/gst/interfaces/xoverlay.h: + interfaces: Seperate some more struct definitions from typedefs + +2009-05-10 17:28:53 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * win32/common/libgstinterfaces.def: + Add new functions to win32 exports + +2009-05-10 17:28:05 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + Add new functions to the docs + +2009-05-10 17:25:58 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/interfaces/mixer.h: + interfaces: API: Add gst_mixer_get_mixer_type() + This is a convenience function that returns the mixer_type + of the interface struct. + +2009-05-10 17:25:31 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/colorbalance.c: + interfaces: Add docs for gst_color_balance_get_balance_type() + +2009-05-10 11:17:19 +0200 Marc-Andre Lureau <marcandre.lureau@gmail.com> + + * autogen.sh: + Run libtoolize before aclocal + This unbreaks the build in some cases. Fixes bug #582021 + +2009-05-07 17:38:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Correctly initialize the background for ARGB too + +2009-05-07 16:59:32 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + * ext/pango/gsttextrender.h: + textrender: Use libgstvideo functions to create caps + Also check if downstream wants ARGB always when we get + new caps. + +2009-05-07 16:52:02 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Don't always use ARGB if downstream supports it but take it's preference + +2009-05-07 16:48:08 +0200 Kapil Agrawal <kapil@mediamagictechnologies.com> + + * ext/pango/gsttextrender.c: + * ext/pango/gsttextrender.h: + textrender: Add support for ARGB and alignment properties + Fixes bug #581571. + +2009-05-07 16:42:20 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextrender.c: + textrender: Add ; after GST_BOILERPLATE to fix indention + +2009-05-07 15:10:30 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Use text/uri-list as mimetype instead of ---> for URI lists + +2009-05-07 14:59:36 +0200 Arnout Vandecappelle <arnout@mind.be> + + * gst/typefind/gsttypefindfunctions.c: + typefindfunctions: made mp3_type_find less aggressive + mp3_type_find could suggest already when only a single valid header + was found, if it ran out of data before the end of the next frame. + Therefore, ignore the last found frame if it was incomplete. + Fixes bug #579692. + +2009-05-07 14:48:29 +0200 John Millikin <jmillikin@gmail.com> + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Store cover art in vorbiscomments + Fixes bug #513373. + +2009-05-07 06:14:18 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/colorbalance.c: + * gst-libs/gst/interfaces/colorbalance.h: + interfaces: API: Add gst_color_balance_get_balance_type() + This is a convenience function that returns the balance_type + of the interface struct. + +2009-05-06 17:59:13 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/interfaces/colorbalance.h: + * gst-libs/gst/interfaces/colorbalancechannel.h: + * gst-libs/gst/interfaces/tuner.h: + * gst-libs/gst/interfaces/tunerchannel.h: + interfaces: Separate struct definitions from typedefs + +2009-05-06 14:03:01 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * pkgconfig/gstreamer-app-uninstalled.pc.in: + Fix libdir for uninstalled gstreamer-app library + +2009-05-12 01:59:01 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/descriptions.c: + pbutils: add description for APE tag caps + +2009-05-12 01:35:27 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: bump core requirement to last release + as that's more likely to be true than that we need + only 0.21.1. + +2009-05-12 01:21:57 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * common: + * configure.ac: + configure: rename CVS -> git in a couple of places + +2009-05-12 01:17:53 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + configure: bump GLib requirement to GLib >= 2.16 + as per the New Regime (see wiki). + +2009-05-01 00:09:15 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: cache events from upstream and re-send them once we have a source pad + Makes sure tags don't get dropped when we have multiple tag demuxers in a row. + Fixes #580318. + +2009-05-07 14:07:44 -0700 Michael Smith <msmith@songbirdnest.com> + + * gst-libs/gst/riff/riff-media.c: + riff: support UYVY raw 4:2:2 in riff. + +2009-05-11 21:20:07 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + Back to development -> 0.10.23.1 + +2009-04-27 22:42:55 -0700 Michael Smith <msmith@syncword.(none)> + + * ext/theora/theoradec.c: + theoradec: fix buffer overrun on 422 decode. + +2009-04-27 21:39:01 -0700 Michael Smith <msmith@syncword.(none)> + + * ext/theora/theoradec.c: + theoradec: 444 support. + +2009-04-27 21:30:04 -0700 Michael Smith <msmith@syncword.(none)> + + * ext/theora/theoradec.c: + theoradec: handle 422 images (as YUY2). + +2009-04-27 21:01:51 -0700 Michael Smith <msmith@syncword.(none)> + + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: + theoradec: rearrange code in preparation for 422 and 444 support. + +=== release 0.10.23 === + +2009-05-10 23:57:01 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/_stdint.h: + * win32/common/config.h: + Release 0.10.23 + +2009-05-10 23:56:05 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + +2009-05-08 20:32:20 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.22.6 pre-release + +2009-05-08 13:09:32 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix resume after pause + Don't ignore the state change of the children, they might be doing an ASYNC + state change. + +2009-05-08 11:05:41 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + 0.10.22.5 pre-release + +2009-05-07 22:01:01 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcp-marshal.list: + multifdsink: fix signature of the add-full signal + The second parameter is a GstSyncMethod enum, not a boolean. + +2009-05-07 15:19:05 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: initialize variable too + +2009-05-07 14:28:30 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: make playsink go ASYNC to PAUSED + Make playsink go async to the PAUSED state instead of relying on uridecodebin + for async behaviour in playbin. This solves some problems (mainly with DVD) + where the pipeline would go to PLAYING before preroll completed, failing to + select the audiosink clock. + Fixes #581727 + +2009-05-06 16:09:52 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.22.4 pre-release + +2009-05-06 13:19:34 +0100 Zaheer Merali <zaheerabbas@merali.org> + + * ext/theora/theoraenc.c: + * ext/vorbis/vorbisenc.c: + vorbisenc, theoraenc: Ensure gp is computed consistently + clip to segment + With vorbisenc, compute the granulepos with running time and clip incoming + buffers to segment. + With theoraenc, drop out of segment buffers. + +2009-05-01 16:47:53 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst/audioresample/gstaudioresample.c: + audioresample: Fix buffer size transformations + When calculating the input/output buffer sizes in the transform_size function, + take the number of channels into account, so we don't end up calculating + a buffer size that only contains a partial number of audio frames. + Also, when going from output size to input size, round down rather than + up, so as to calculate the minimum number of samples that *might* yield + a buffer of the intended destination size. + Fixes: #580470 and #580952 + +2009-04-29 16:45:27 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ext/vorbis/gstvorbisenc.h: + * ext/vorbis/vorbisenc.c: + vorbisenc: Ensure output buffers fall within the segment + Add the start position of the first segment to the running time + used to generate buffer timestamps in vorbisenc. This avoids generating + buffers which fall outside the initial segment. The element segment + handling requires more extensive fixing, but this at least prevents + regressions. Fixes: #580020 + +2009-04-29 11:18:42 +0200 Andy Wingo <wingo@oblong.net> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + Revert "add can-activate-pull property to baseaudiosink" + This reverts commit c4074a2ee4f1e6cac734a145bf675bbb16fac985. + +2009-04-29 11:18:33 +0200 Andy Wingo <wingo@oblong.net> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + Revert "[baseaudiosink] add docs for can-activate-pull" + This reverts commit 416ce16f26b39c76ab35e1ef6a75dc41ec69f75b. + +2009-04-28 18:48:33 +0200 Andy Wingo <wingo@oblong.net> + + [baseaudiosink] add docs for can-activate-pull + * gst-libs/gst/audio/gstbaseaudiosink.c: Add documentation for + can-activate-pull. + +2009-01-21 12:33:59 +0100 Andy Wingo <wingo@oblong.net> + + add can-activate-pull property to baseaudiosink + * gst-libs/gst/audio/gstbaseaudiosink.c: Add can-activate-pull property + to baseaudiosink. + +2009-04-28 11:32:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/videorate/gstvideorate.c: + * gst/videorate/gstvideorate.h: + videorate: clear discont on duplicated buffers + When videorate duplicates a buffer with a DISCONT flag, it copies the discont on + the first pushed buffer but fails to clear it for subsequent buffers. This + causes theoraenc!oggmux and possibly other elements to consider this a discont + stream. + Fix videorate to produce discont as the first buffer and after a flushing seek. + Fixes #580271. + +2009-04-24 18:13:00 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/Makefile.am: + check: Disable the playbin2 for this release, as it is a bit racy. + Disable the test, as per the discussion in #580120. Needs re-enabling + after the release, when playbin2 is fixed. + +2009-04-23 08:41:19 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: Don't reduce max-size-time of exposed groups. Fixes #579912 + The 2s limit is way too small for a lot of files (which have an interleave + in time of between 3 and 5s). Instead, leave it to the initial 5s value + and reduce the other limits (allowing us to stay memory-efficient). + +2009-04-21 21:06:59 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * win32/common/_stdint.h: + * win32/common/config.h: + 0.10.22.3 pre-release + +2009-04-21 20:41:23 +0100 René Stadler <mail@renestadler.de> + + * gst/audioresample/gstaudioresample.c: + audioresample: Fix unused variable in compilation with --disable-gst-debug + Fixes: #579668 + +2009-04-21 22:12:28 +0100 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From b3941ea to 6ab11d1 + +2009-04-21 20:57:34 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybasebin.c: + playbin: only use raw_decoding_mode when it's true + First check the pad caps if they are raw before setting the raw_decoding_mode to + TRUE. Fixes playback of transport streams and other streams that require large + queues. + Fixes #579734 + +2009-04-19 18:15:28 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/cdda/gstcddabasesrc.c: + * tests/check/libs/cddabasesrc.c: + cddabasesrc: fix posting of discid tags after MERGE_MODE_REPLACE_ALL changes in core + Don't use REPLACE_ALL merge mode when that's not really what we want, + as now that REPLACE_ALL actually does what it's supposed to do in + core, we drop tags we wanted to keep, such as the various disc id + tags. Add unit test for this as well. Fixes #579463. + +2009-04-17 10:34:54 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: don't use GLib-2.16 API, we require only 2.14 + Fixes #579267. + +2009-04-17 10:55:08 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: don't unparent the ringbuffer + when going to NULL, don't unparent the ringbuffer because we don't support going + back to 0 very well yet. + Fixes #579203 + +2009-04-17 10:53:10 +0200 Olivier Crete <tester at tester.ca> + + * gst-libs/gst/rtp/gstrtcpbuffer.c: + RTCP: don't fail when retrieving invalid PT + We can't meaningfully assert on valid packet types so just return the type as it + is. Update the comments to reflect this. + Fixes #579192. + +2009-04-16 12:12:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/app/gstappsink.h: + * gst-libs/gst/app/gstappsrc.h: + app: add trivial cast macros + Add trivial cast macros for appsrc and appsink. Mark them as being since 0.10.23 + and add the macros to the standard macros in the docs. + Fixes #579130 + +2009-04-16 12:09:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + pkgconfig: add the app/ directory to Libs + Add the appsrc/appsink directory to the Libs in the uninstalled + pkgconfig file so that one can build against it. + Fixes #579129 + +2009-04-15 22:59:31 +0100 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + 0.10.22.2 pre-release + +2009-04-15 22:56:15 +0100 Jan Schmidt <thaytan@noraisin.net> + + * ChangeLog: + ChangeLog: regenerate changelog with the gen-changelog script + +2009-04-16 00:41:13 +0100 Jan Schmidt <thaytan@noraisin.net> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: Update po files from TP + +2009-04-16 00:40:59 +0100 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/interfaces-enumtypes.c: + * win32/common/interfaces-enumtypes.h: + * win32/common/video-enumtypes.c: + win32: Update win32 build files + +2009-04-16 00:31:55 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/libs/video.c: + check: Add GST_VIDEO_FORMAT_YVYU to the test so it passes. + +2009-04-16 00:31:00 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/playbin2.c: + check: Fix the input uri in playbin2 test. + Don't try and use a random file in wim's home directory as a test input + +2009-04-15 15:35:59 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.h: + video: Fix typo in the docs + +2009-04-15 14:53:47 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add support for YVYU YUV colorspace + +2009-04-15 00:17:51 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + * gst-libs/gst/fft/gstfft.c: + docs: fix hyperlink and move fft attribution to the right place + +2009-04-15 00:02:39 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + log: use G_GUINT64_FORMAT instead of llu + +2009-04-14 18:31:52 +0200 Josep Torra <n770galaxy at gmail.com> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + RTSP: add missing headers for WMS RTSP + Add missing headers related to Windows Media RTSP extension. + Fixes #578942 + +2009-04-14 18:16:37 +0200 Olivier Crete <tester at tester.ca> + + * docs/design/draft-keyframe-force.txt: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theoraenc: implement upstream keyframe force + Implement handling of upstream keyframe forcing. + Update the design documents too. + Fixes #578656 + +2009-04-14 17:31:31 +0200 Olivier Crete <tester at tester.ca> + + * ext/theora/theoraenc.c: + theoraenc: factor out keyframe forcing + See #578656 + +2009-04-14 17:01:51 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * AUTHORS: + * gst-libs/gst/fft/gstfft.c: + Give credit to Mark Borgerding (kissfft author) + and add myself to AUTHORS as well. Fixes #575638. + +2009-04-14 17:04:06 +0200 Jan Urbanski <j.urbanski at students.mimuw.edu.pl> + + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + multifdsink: add property to resend streamheaders + Adds a new property in multifdsink, resend-streamheader. + If this property is false, the multifdsink will not send the streamheader if + there's already one set for a particular client. + There are some formats in which every stream needs to start with a certain + blob, but you can't inject this blob at leisure. If the producer wants to + change the blob in question and sets in as the streamheader on the outgoing + buffers' caps, new clients of multifdsink will get the new streamheader, but + old clients will break, because they'll see the blob in the middle of the + stream. + The property is true by default, so existing code will not see any difference. + Fixes #578118. + +2009-04-14 16:53:33 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + multifdsink: add property to handle client write + Add a property to disable listening to client writes. This property is usefull + when other code will deal with reading from the client socket. + API: GstMultiFdSink::handle-read property + +2009-04-14 16:45:20 +0200 Johann Prieur <johann.prieur at gmail.com> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + * gst-libs/gst/rtp/gstrtcpbuffer.h: + * win32/common/libgstrtp.def: + RTCP: add beginnings of Feedback messages + Add the beginnings of parsing and constructing Feedback messages. + Fixes #577610. + +2009-04-14 13:51:41 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: clear the target + Clear the target of our ghostpads before we remove the pad from the element. + This to make sure that the internal pad is not left linked to whatever pad we + were ghosted to. This should only be a problem when we leak the ghostpads. + Also release our subpicture pads. + Fixes #577288. + +2009-04-14 12:10:30 +0100 Hannes Bistry <hannesb@gmx.net> + + * sys/ximage/ximagesink.c: + ximagesink: fix mouse pointer offsets in navigation event if window is smaller than the image + Fixes #570768. + +2009-04-14 13:16:14 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + baseaudiosrc: adjust the internal timestamp + Adjust the internal timestamp before comparing it against the adjusted clock + time. + Fixes #578506 + +2009-04-14 13:12:59 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: use new clock time methods + Use the unadjusted internal clock times to calculate the internal/external + offset when calibrating the clock. + When going to NULL, unparent and free the ringbuffer, like we do in the source + element. + See #578506 + +2009-04-14 13:08:52 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstaudioclock.h: + * win32/common/libgstaudio.def: + audioclock: add methods for the internal offset + Add two methods for getting the unadjusted time of the clock and one for + adjusting an internal time. We will need these methods for correctly handling + the time after a gst_audio_clock_reset(). + Add a debug category and some debug lines to the audio clock. + API: gst_audio_clock_get_time() + API: gst_audio_clock_adjust() + API: GST_AUDIO_CLOCK_CAST() + +2009-04-14 11:34:49 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: fix up the debugs and warnings + Use _OBJECT variants because we can. Go over some log statements and put them in + the right category. + Fixes #567740. + +2009-04-12 22:26:33 +0200 Luca Ognibene <luca.ognibene at gmail.com> + + * gst/tcp/gstmultifdsink.c: + multifdsink: fix error in sync-method + Multifdsink did not handle sync-method=latest-keyframe correctly when the + soft-limit is set to -1 (unlimited). + Fixes #578583. + +2009-04-10 21:49:45 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: use the internal clock time + We can't assume that the internal clock time is the same as the function we + installed on our provided clock because somebody might have changed it. + +2009-04-10 14:12:53 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: handle clock-lost messages + When we receive a clock-lost message we need to pause and play to select a new + clock. + +2009-04-10 13:44:40 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/check/Makefile.am: + * tests/check/elements/playbin2.c: + check: add a unit test for playbin2 + Add unit test for playbin2 and include the refcount test in #577794. + +2009-04-10 13:42:56 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix refcounting of visualisations + See #577794. + +2009-04-10 13:27:41 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playsink: fix refcounting of custom elements + Sink the custom sinks, let other elements we create be sunken by the bin we add + them to. + Fixes #577794. + +2009-04-10 12:27:53 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/check/elements/appsink.c: + check: fix appsink test + Fix the appsink test now that the method signature changed. + +2009-04-10 12:26:16 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: handle missing input-selector + Gracefully degrade and disable stream selection when input-selector is + missing. + +2009-04-09 23:46:17 +0200 Martin Samuelsson <martin.samuelsson at axis.com> + + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsink.h: + appsink: make callbacks return GstFlowReturn + Make the new_buffer and new_preroll callbacks return a GstFlowReturn so that + errors can be reported properly. + Fixes #577827. + +2009-04-09 18:04:44 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/audio/gstringbuffer.h: + ringbuffer: allow for custom commit functions + Allow subclasses to override the commit method. + +2009-04-08 18:04:22 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + baseaudiosink: fix a small glitch after pause + After we pause the stream and interrupt the writeout to the ringbuffer, also adjust + the amount of output samples we consumed. We can't do this reliably with the + current API when we are doing trick modes but we can do the right thing for + normal playback. + +2009-04-08 16:43:27 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaysink.c: + playbin2: better error message on sink failure + If we could create the sinks, but the don't work, don't send the missing plugin + message and report that the state-changed failed. + +2009-04-07 22:38:29 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstaudiofilter.c: + audiofilter: don't leak pad-template + gst_element_class_add_pad_template() does not take ownership. + +2009-04-04 21:18:38 +0300 Felipe Contreras <felipe.contreras@gmail.com> + + * common: + Automatic update of common submodule + From d0ea89e to b3941ea + +2009-04-04 16:28:14 +0200 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/interfaces/navigation.c: + * sys/v4l/v4lsrc_calls.c: + navigation/v4l: Don't use g_return_val_if_fail for computed/used values. + +2009-03-22 09:46:37 +0100 Edward Hervey <bilboed@bilboed.com> + + * ext/theora/theoradec.c: + theoradec: return GST_CLOCK_TIME_NONE for negative framecounts. + This fixes most seeking issues when used with gnonlin. + Fixes #543591 + +2009-04-04 14:53:42 +0200 Edward Hervey <bilboed@bilboed.com> + + * common: + Automatic update of common submodule + From f8b3d91 to d0ea89e + +2009-04-03 10:51:42 -0700 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + playbin2: don't leak selector when getting current stream numbers. + +2009-04-02 22:28:55 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: use fully qualified urls when using a proxy + Use a fully qualified url when specifying the url for tunneled requests through + a proxy. + See #573173 + +2009-03-31 00:54:30 +0100 Jan Schmidt <thaytan@noraisin.net> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/navigation.c: + * gst-libs/gst/interfaces/navigation.h: + * tests/check/Makefile.am: + * tests/check/libs/.gitignore: + * tests/check/libs/navigation.c: + * win32/common/libgstinterfaces.def: + navigation: Extend the navigation interface + Add support for a set of standard commands that can be queried and executed to + support applications like DVD. Add query construction and parsing functions. + Add new messages that can be sent on the bus to provide notifications related + to commands, multiangle changes, and button highlight activity. + Add some helper functions to parse the existing GstNavigation events that + elements might receive. + Document it all and add unit tests. + +2009-02-04 17:03:07 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybasebin.h: + playbin: Add simple 'raw decoding mode'. + Raw decoding mode removes almost all buffering in video and audio queues + when a source providing already decoded video/audio is detected, on the + possibly bogus assumption that such a source should provide sufficient + internal queueing. Fixes playback on some DVDs, and improves it + on all. + +2009-04-02 09:27:07 +0100 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/elements/.gitignore: + ignores: Ignore the videoscale check binary + +2009-04-02 12:13:57 +0100 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/libgstrtsp.def: + win32: Add gst_rtsp_connection_set_proxy to the win32 exports + +2009-04-02 10:42:19 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * ext/alsa/gstalsamixer.c: + alsamixer: don't forget to release locks in a few places + Might fix #576585. + +2009-04-02 11:10:12 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + videoscale: Don't read over line ends when taking the last Cr or Cb + +2009-04-02 10:52:06 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + videoscale: Don't write to few pixels and don't mix Cr and Cb + Fixes bug #577054. + +2009-04-01 15:15:57 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/audioresample/gstaudioresample.c: + * tests/check/elements/audioresample.c: + audioresample: fix negotiation so that upstream can actually fixate to downstream's rate + If one side has a preference for a particular sample rate or set of sample rates, we + should honour this in the caps we advertise and transform to and from, so that elements + actually know about the other side's sample rate preference and can negotiate to it + if supported. Also add unit test for this. + +2009-03-26 19:34:23 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + docs: add a blurb about redirect messages to playbin2 docs + +2009-04-01 09:03:35 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: fix little typo in the comments + +2009-03-31 17:52:44 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: make gst_rtsp_watch_queue_message() thread-safe + People might queue messages from a thread other than the thread in which + the main context which this watch is attached is iterated from, so use + a GAsyncQueue instead of a GList, so g_list_append() doesn't trample + over list nodes just freed in the other thread. This just fixes issues + I've had with gst-rtsp-server. We might need more locking in various + places here. + +2009-03-31 18:13:19 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: clear the entire builder structure + And use structure instead of variable with sizeof when + clearing the rtsp message structure, for clarity. + +2009-03-31 17:56:24 +0100 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + docs: fix typo in gst_rtsp_message_unset() API docs + +2009-03-31 19:00:00 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: add support for proxies + Add suport for proxy servers. Currently only used for tunneled HTTP + connections without authentication. + +2009-03-31 18:57:08 +0200 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + Revert "rtsp: reset whole message (was sizeof pointer instead of sizeof type)" + This reverts commit 79de0b8d67df6fbbe79455adc2e06858295f5c03. + +2009-03-26 18:54:56 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: use xcontext->depth instead of bits in attr.max_value for colorkey + According to the drivers in http://cgit.freedesktop.org/xorg/driver/ we should + format the colorkey depending on xcontext->depth. This is what they will use to + interprete the value. The max_value in turn is usualy a constant regardless of + the depth. + +2009-03-31 12:22:14 +0300 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: reset whole message (was sizeof pointer instead of sizeof type) + +2009-03-31 00:56:18 +0100 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/interfaces/mixer.c: + doc: Fix a typo in the GstMixer docs + +2009-03-29 12:01:33 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_scanline.c: + videoscale: Fix linear scaling for one byte components + Fixes bug #577054. + +2009-03-29 11:53:40 +0200 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + videoscale: Fix 4tap scaling of YUYV and friends + +2009-03-28 16:08:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_image.c: + * gst/videoscale/vs_scanline.c: + * gst/videoscale/vs_scanline.h: + videoscale: Rewrite YUYV (and friends) scaling and don't read/write over line ends + Partially fixes bug #577054, there's just one issue left now. + +2009-03-28 12:48:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/elements/videoscale.c: + videoscale: Add some more unit tests + +2009-03-28 11:51:01 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Use bilinear instead of 4tap scaling for heights < 4 + Partially fixes bug #577054. + +2009-03-28 11:45:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_scanline.c: + videoscale: Don't read after the end of a line when lineary scaling YUYV/UYVY/RGB/RGBA + This case is for upscaling a frame with width=1 + Partially fixes bug #577054. + +2009-03-28 11:27:56 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_scanline.c: + videoscale: Don't read after the end of a line when lineary scaling YUYV/UYVY + Partially fixes bug #577054. + +2009-03-28 10:40:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/gstvideotestsrc.c: + videotestsrc: Initialize buffer memory with zeroes + This prevents valgrind warnings when accessing the "x" parts + of xRGB and friends in other elements that handle (and can handle) + xRGB like ARGB (for example videoscale). + +2009-03-28 10:25:12 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/Makefile.am: + * tests/check/elements/videoscale.c: + videoscale: Add a lot of unit tests + +2009-03-28 10:06:24 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videocale: Add support for video/x-raw-gray with bpp=depth=8 + +2009-03-28 10:01:00 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add support for generating video/x-raw-gray with bpp=depth=8 + +2009-03-28 09:43:23 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + ffmpegcolorspace: video/x-raw-gray is the same as the YUV Y800 format + +2009-03-27 19:12:49 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + videoscale: Take the next luma value instead of every second next when scaling UYVY and friends + +2009-03-27 19:09:47 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Add support for v308 YUV colorspace + +2009-03-27 13:15:11 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + videoscale: Add my copyright to the 4tap scalers + +2009-03-27 13:14:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/gstvideoscale.c: + videoscale: Enable 4-tap scaling for all supported formats + +2009-03-27 13:14:00 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + videoscale: Implement 4-tap scaling for RGB565 and RGB555 + +2009-03-27 10:47:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + videoscale: Implement 4-tap scaling for UYVY + +2009-03-27 09:33:58 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + videoscale: Implement 4-tap scaling for YUY2 and YVYU + +2009-03-26 22:14:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + videoscale: Implement 4-tap scaling for RGB and BGR + +2009-03-26 22:08:26 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + videoscale: Implement 4-tap scaling for RGBA and other 4 byte formats + +2009-03-26 11:02:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/pango/gsttextoverlay.c: + textoverlay: Fix drawing of UYVY text borders + +2009-03-26 10:36:27 +0100 Zeeshan Ali <zeeshan.ali@nokia.com> + + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + textoverlay: Add support for UYVY colorspace + Fixes bug #378094. + +2009-03-25 19:01:45 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: do some more cleanup + Free the groups when we go to READY. + Allow for NO_PREROLL elements. + +2009-03-25 16:37:28 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: start CSeq counting from 1 instead of 0 + Start counting from 1 instead of 0 as this is what most other clients + seem to do. + +2009-03-25 16:35:22 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: add ETag and If-Match headers + Add new headers, we need them for RealMedia support. + +2009-03-25 14:16:25 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: scale the colorkey components in case of 16bit visuals + Use a default that won't be scales to 0,0,0 + +2009-03-25 11:27:44 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/audio/gstbaseaudiosrc.c: + audiosrc: improve 'Dropped n samples' warning message + +2009-03-24 19:41:06 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/app/appsrc-ra.c: + * tests/examples/app/appsrc-seekable.c: + examples: use new method to set flags + Use the new core method for setting object enum properties by name. + +2009-03-24 18:29:28 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: add more support for subpictures + +2009-03-24 17:12:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: first support for subpictures + Add beginnings of subpicture support. + +2009-03-24 15:26:57 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: print tags from the different tracks + +2009-03-24 12:22:37 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: blacklist subpictures for now + Blacklist the subpictures until we add support for them. + Add some small debug info. + See #576408. + +2009-03-24 12:19:30 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: expose more media types + Expose more media types from a raw source, such as the subpicture and various + text pads. + Small cleanups and add some more debugging. + See #576408. + +2009-03-24 10:42:04 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: rescan audio sinks for volume/mute + Rescan the audio sinks for the mute and volume properties. + fixes #576180. + +2009-03-23 19:40:18 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix reuse of the video chains + When reusing playbin with visualisations, reset the async property on the video + sink because some sinks might dynamically recreate their sinks. + Fixes #576188 + +2009-03-23 17:37:48 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: allow dynamic swtiching of subtitles + When we have the textpad configured, enable and disable the subtitles by setting + the silent flag on the overlay element instead of trying to remove elements. + See #576187 + +2009-03-23 16:59:36 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/playbin-text.c: + tests: print some more info in the text example + Print both the position and the running_time when the subtitle becomes available + in the application. + +2009-03-23 16:04:27 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix dynamic switching of visualisations + Fix the switching of visualisations by requesting and releasing the tee request + pads on demand. + See #576187. + +2009-03-23 16:19:11 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/tcp/README: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + docs: add examples for tcp elements, also use correct section name. Fixes #564139 + Updated the examples in the README to actually work. Add them to api docs. Tests + the api-docs and fix the section names to make the docs actualy show up. + The example for "tcpserversrc" needs review (might be an element bug). + +2009-03-17 09:14:02 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/videoscale/gstvideoscale.c: + indent: fix damange that gst-indent did some time ago + +2009-03-23 15:27:27 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: fix linking order + Link after doing the state change and unlink before shutting down. Makes the + window for causing races in toggling the visualisations smaller. + See #576187. + +2009-03-23 12:26:05 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + uridecodebin: reset counter + reset the number of pending dynamic operations back to 0 when we reuse + uridecodebin. + Fixes #576190 + +2009-03-23 11:38:53 +0100 Edward Hervey <bilboed@bilboed.com> + + * ext/theora/theoradec.c: + theoradec: Use GST_CLOCK_TIME_NONE for invalid positions. Fixes #543591 + The problem was that previously we didn't check whether _theora_granule_frame + returned a negative framecount or not, resulting in bogus timestamps. + +2009-03-21 09:46:28 +0100 René Stadler <mail@renestadler.de> + + * ext/vorbis/vorbisenc.c: + vorbisenc: Set caps on non-header ouput buffers. + Fixes #576142. + +2009-03-20 16:13:06 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/seek/seek.c: + seek: Add some more debug + Add some more info about the selected streams. + +2009-03-20 15:47:47 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: a pad starts out being not drained. + Mark a new pad as not drained until we get EOS on it. + +2009-03-20 14:17:19 +0100 LRN <lrn1986 at gmail dot com> + + * gst/playback/gstqueue2.c: + win32: fix seeking in large files + Fix Seeking in large files by using the 64-bit seek functions. + Fixes #576019 + +2009-03-19 20:31:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: recover from failing to add a pad + When we cannot add a pad to the decodebin2 for some reason, print a warning but + continue adding the remaining pads. + +2009-03-19 19:35:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: more cleanups and docs. + Add some more comments and use g_list_prepend(). + +2009-03-19 19:19:38 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: refactoring and race fixes + Refactor some code so that we can take the right locks and in the right order. + Fixes quite a bit of races already. + +2009-03-19 19:03:25 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: remove the group cond + cleanups + Remove the group GCond that we used for waiting for groups to finish because we + use pad blocking on the selectors and counters instead for waiting for the + groups to complete. + remove the obsolete about_to_finish variable set while emiting the + about-to-finish signal and fix some old comments. + We don't need to take the playbin lock when querying the uridecodebin. + +2009-03-18 10:45:50 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/playbin-text.c: + icles: print better error and warning messages + -- + +2009-03-17 22:53:44 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspbase64.c: + * gst-libs/gst/rtsp/gstrtspbase64.h: + rtsp: Use GLib base64 functions and deprecate gst_rtsp_base64_encode + This also fixes another instance of CVE-2008-4316. + +2009-03-17 19:53:44 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: report -1 for duration in push mode + In push mode we must return TRUE from the duration query with a value of -1 + meaning that we know that we don't know the duration. + +2009-03-17 19:09:02 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: add extra dynamic ref for demuxers + When we make a group connected to a demuxer, keep an extra dynamic refcount for + the group which is only decremented when no_more_pads or a multiqueue overrun is + detected. This way we avoid a race between exposing the group while more dynamic + refs are added from new pads. + Fixes #575588. + +2009-03-17 15:39:23 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2: sync state of the sink correctly + Sync the state of the newly added chains to the state of the parent sink element + to avoid lost async-start messages. Fixes cdda:// async-done message storm. + +2009-03-17 11:54:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: return NOT_LINKED for unselected streams + When streams are not selected in the selector, return NOT_LINKED so that + upstream elements can skip decoding. Only do this for audio and video pads + because for text streams the overhead is smaller and they could come from + external files. + +2009-03-17 11:51:58 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin: set custom text sink properties + Set the custom sink async=FALSE to not make it participate in preroll because we + are dealing with sparse streams. + Try to set sync=TRUE on the custom text sink. + +2009-03-17 11:30:58 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/playbin-text.c: + example: use appsink instead of fakesink + Use appsink instead of fakesink to get the subtitles. + Make things more pretty. + +2009-03-17 11:24:00 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + * tests/icles/playbin-text.c: + examples: add example of intercepting subtitles + Add an example of how to install a custom sink for receiving subtitles in + playbin2. + +2009-03-17 11:03:57 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/check/elements/appsink.c: + tests: fix include in the appsink test + Fix dist by doing the right include. + +2009-03-16 16:42:18 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: don't try to set invalid stream numbers + Fix a problem with setting the stream numbers because we check for the wrong + range. + See #575239. + +2009-03-16 16:16:30 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: release the shutdown lock + Release the shutdown lock when we wait for other groups to complete or else we + have a deadlock when the other group completes and tries to grab the shutdown + lock. + Fixes #575550. + +2009-03-16 15:31:44 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/app/appsrc-ra.c: + * tests/examples/app/appsrc-seekable.c: + * tests/examples/app/appsrc-stream.c: + * tests/examples/app/appsrc-stream2.c: + examples: fix g_object_set() value type. + Make sure we cast the length value as a gint64 to the vararg g_object_set() just + incase sizeof(gsize) != sizeof(gint64). + +2009-03-15 19:57:36 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: make flac typefinder return lower probability for frame headers + The flac frame header typefinder overstates the likelihood of a match, leading + to false positives with e.g. aac streams and PDF files. Reduce probabilty + returned from LIKELY to POSSIBLE for the frame header matchin code. + Fixes #574939. + +2009-03-11 12:59:05 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: improve image/bmp typefinder + Detect more variations and also bail out in more cases where the values + don't make sense. Furthermore, add width/height and bpp to the caps, + because we can. + +2009-03-13 15:22:42 +0000 Jan Schmidt <thaytan@noraisin.net> + + * tests/check/Makefile.am: + check: Ignore alsamixer in the states test too + +2009-03-13 15:22:11 +0000 Jan Schmidt <thaytan@noraisin.net> + + * sys/v4l/v4l_calls.c: + v4lsrc: Fix some valgrind warnings about leaked memory and uninitialised data. + +2009-03-13 16:19:41 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: fix resolving of hostnames + We were returning a pointer to a stack variable with the resolved hostname, + which doesn't work. + return a copy of the resolved ip address instead. + Fixes #575256. + +2009-03-13 15:29:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/vorbis/vorbisparse.c: + vorbisparse: be smarter when queueing headers + Look at the first buffer byte to see if a buffer is a header instead of counting + packets. + +2009-03-13 15:27:51 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/gsttheoraparse.h: + * ext/theora/theoraparse.c: + theoraparse: be smarter when queuing headers + Look at the first byte of the buffer data (if we can) to decide if the packet is + a header packet or not instead of counting packets. + +2009-03-13 15:26:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/ogg/gstoggdemux.c: + oggdemux: add some debug info + Add some debug info to log when the seek worked. + +2009-03-13 15:14:37 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + appsrc: release lock in _eos flushing case + Release the mutex when we are flushing in gst_app_src_end_of_stream() + Fixes #574964. + +2009-03-13 11:49:10 +0000 Jan Schmidt <thaytan@noraisin.net> + + * ext/vorbis/vorbisdec.c: + vorbisdec: Avoid an unnecessary memory allocation in vorbiscomment handling. + +2009-03-13 11:48:28 +0000 Jan Schmidt <thaytan@noraisin.net> + + * ext/theora/theoradec.c: + theoradec: Avoid an unnecessary memory allocation in vorbiscomment handling. + +2009-03-12 18:27:25 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + playbin2: fix raw elements like cdda:// + Fix a fixme with a one liner and make cd playback work again. + +2009-03-12 17:47:41 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playbin2: improve subtitle handling + Add property to playbin2 to configure a custom sink that receives the raw + subtitle buffers instead of using a textoverlay. + Improve the property finding code to make it more usable. + Use property find code to find async properties in custom sinks that are bins. + Improve text overlay code to gracefully handle missing elements. + +2009-02-24 15:58:42 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/tag/gstvorbistag.c: + vorbistag: Protect memory allocation calculation from overflow. + Patch by: Tomas Hoger <thoger@redhat.com> Fixes CVE-2009-0586 + +2009-03-12 11:34:20 +0000 Jan Urbanski <jurbanski@flumotion.com> + + * gst-plugins-base.spec.in: + Spec: fix up deps + +2009-03-11 18:45:59 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: fix parsing of the timeout parameter + -- + +2009-03-11 16:20:20 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: fix g_return condition + when parsing a data message, we require a data message. + +2009-03-11 13:33:33 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + typefinding: flac typefinder fixes + Use scan context for initial peek as well. Peek 6 bytes in the initial + peek rather than 5 bytes, to match the length of the memcmp we're doing + on that data later. Return immediately when we found caps from looking + at the beginning of the data - no point in continuing to scan the next + 64kB for something matching a frame header. + +2009-03-11 14:08:10 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: free the right string. + Free the key value before we remove the header item from the array. The item we + retrieved from the array is only valid until we remove it from the array. + +2009-03-11 14:07:05 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: keep track of amount of decoded bytes + Keep track of the actual amount of decoded bytes, which can be less than 3 when + we decode the last bits of a base64 message. + +2009-03-10 21:00:26 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: log details in getcaps like in setcaps + +2009-03-10 13:11:09 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/MANIFEST: + win32: update MANIFEST, fixing 'make dist' + +2009-03-09 23:12:00 +0000 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From 7032163 to f8b3d91 + +2009-03-09 16:19:40 +0100 Jonathan Matthew <notverysmart at gmail dot com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: add photoshop typefind functions + Add photoshop typefind functions. + Fixes #574516. + +2009-03-09 15:46:21 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + decodebin2: only remove pads that were added + Flag pads that were added so that we can see if we need to remove them later or + not. + +2009-03-09 13:53:41 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtsptransport.c: + rtsp: only add ports when not using TCP + Only add the port numbers in the transport string when we are using udp or + multicast. + +2009-03-09 13:53:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + rtsp: use gstreamer dump mem + -- + +2009-03-09 13:51:48 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: use glib base64 encoder + -- + +2009-03-06 19:28:37 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + Unblock blocked ghostpads when shutting down. Fixes #574293. + +2009-03-09 10:03:13 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + Riff: Add mapping for Fraps video codec. + Found through insanity testrun. Confirmed mapping in libavformat. + +2009-03-09 09:07:13 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + riff: Add the 'DVR ' mapping for mpeg2video. + Found this in 3 files from the insanity suite and mapping is also present + in libavformat. + +2009-03-09 09:06:40 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Use the proper data pointer instead of poking random memory. + +2009-03-08 18:17:48 +0100 LRN <lrn1986@gmail.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: fix compilation on windows. + Remove unused variable when building for windows. + Fixes #574443. + +2009-03-08 12:03:22 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From ffa738d to 7032163 + +2009-03-08 11:19:00 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 3f13e4e to ffa738d + +2009-03-07 11:44:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 3c7456b to 3f13e4e + +2009-03-07 10:44:43 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * common: + Automatic update of common submodule + From 57c83f2 to 3c7456b + +2009-03-06 19:02:58 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + theoradec: parse and use codec_data in the caps + Parse the codec_data in the caps and use this as the headers. + Fixes #574169. + +2009-03-06 18:53:17 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: add theora mapping + Add theora mappings. See #574169. + +2009-03-06 16:31:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + * win32/common/libgstrtsp.def: + rtsp: Add methods for getting the read/write fds + API:gst_rtsp_connection_get_readfd() + API:gst_rtsp_connection_get_writefd() + +2009-03-06 10:35:01 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * Makefile.am: + * win32/common/audio-enumtypes.c: + win32: indent copied *-enumtypes.c files in make win32-update + +2009-03-06 10:35:56 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/MANIFEST: + win32: update MANIFEST + +2009-03-06 10:30:28 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * configure.ac: + * win32/common/config.h: + win32: fix configure logic for GST_INSTALL_PLUGINS_HELPER define + +2009-03-06 10:05:11 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * win32/common/_stdint.h: + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/interfaces-enumtypes.c: + * win32/common/multichannel-enumtypes.c: + * win32/common/pbutils-enumtypes.c: + * win32/common/video-enumtypes.c: + * win32/common/video-enumtypes.h: + win32: update windows files via make win32-update + Updates win32 files using the new system/hook, and defines HAVE_PROCESS_H, + which fixes the build of pbutils on windows (#574319). + +2009-03-06 10:03:31 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + gitignore: ignore more + +2009-03-06 10:37:38 +0100 Julien Moutte <julien@fluendo.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Fix build on Mac OS X + +2009-03-05 15:42:23 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstdecodebin2.c: + decodebin2: don't stay connected to notify::caps after negotiation + Disconnect the notify::caps signal in our callback (it'll be re-added + if we're not, in fact, finished getting complete caps). Ensures that + caps changes mid-stream (e.g. from an mp3 that changes from + stereo->mono mid-file) don't cause us to try to add a new pad. + +2009-03-05 13:48:37 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtsprange.c: + rtsp: fix parsing of 'now-' ranges. + -- + +2009-03-05 12:43:02 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/dynamic/.gitignore: + * tests/examples/dynamic/Makefile.am: + * tests/examples/dynamic/sprinkle.c: + * tests/examples/dynamic/sprinkle2.c: + * tests/examples/dynamic/sprinkle3.c: + examples: add some more sprinkle examples + Add some more sprinle examples and add some more comments. + See #574160. + +2009-03-05 11:57:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/plugins/gst-plugins-base-plugins-sections.txt: + docs: add appsrc symbols to standard section + -- + +2009-03-05 12:27:16 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/adder/gstadder.c: + adder: add variants for unsigned to fix warnings for unneeded check + For unsigned int out+in can't be < 0. + +2009-03-05 10:58:12 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/subparse/gstsubparse.c: + subparse: use the right variable in debug log, encoding is not yet initialized + +2009-03-05 10:51:25 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/v4l/v4l_calls.c: + v4l: add a fixme for broken code, that someone who has a v4l tuner device should fix + +2009-03-05 10:39:33 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/audioresample/gstaudioresample.c: + audioresample: add missing break in event handling, remove dead code + +2009-03-04 16:24:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: do some more cleanup in _close + Do som more cleanup in gst_rtsp_connection_close() so that it's back into the + unconnected state as it was allocated. + +2009-03-04 16:11:20 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: fix the memory management of the url + Constify the url parameter in _create. + Make a copy of the url stored in the connection. + Free the url when the connection is freed. + +2009-03-04 12:21:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + * win32/common/libgstrtsp.def: + RTSP: Add support for server tunneling + Save the tunnelid in the connection. Add a method to retrieve the tunnelid so + that a server can store and match the id against other tunnel requests. + Fix the URI in the tunnel requests so that they contain the absolute uri and the + query string if any instead of just the hostname. + Transparently base64 decode the input stream when tunneling. + Add method to set the connection ip address so that it can be included in the + tunnel response. + Add method to connect the two tunnel requests. + Add two callbacks for the async mode to notify a tunnel start and tunnel + complete event. + Add method to reset the watch after the connection has been tunneled. + Various little refactoring to make more stuff reusable. + API: RTSP::gst_rtsp_connection_set_ip() + API: RTSP::gst_rtsp_connection_get_tunnelid() + API: RTSP::gst_rtsp_connection_do_tunnel() + API: RTSP::gst_rtsp_watch_reset() + +2009-03-04 12:18:00 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + rtsp: add new defines for tunneling + Add two more result codes for tunneling support. + +2009-03-04 12:12:06 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.h: + rtsp: remove , from last enum member + Remove , from last enum member to improve compatibility with other compilers. + +2009-02-28 15:23:20 -0800 LRN <lrn1986@gmail.com> + + * gst/subparse/gstsubparse.c: + subparse: Convert regex code to GRegex code + Fixes: #572993. Patch author prefers to use an alias, contact + ds if you actually need a real name. + Signed-off-by: David Schleef <ds@schleef.org> + +2009-03-02 16:13:33 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: remove debugging g_message + -- + +2009-03-02 16:03:49 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + * win32/common/libgstrtsp.def: + RTSP: add support for Quicktime tunneled RTSP + Add support for tunneling RTSP over HTTP. + Fix documentation some more. + See also #573173. + API: RTSP:gst_rtsp_connection_is_tunneled() + API: RTSP:gst_rtsp_connection_set_tunneled() + +2009-03-02 15:48:56 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtsptransport.h: + * gst-libs/gst/rtsp/gstrtspurl.c: + RTSP: parse rtsph uris as RTSP tunneled over HTTP + Add transport define for RTSP tunneled over HTTP. + Parse rtsph:// uris as tunneled HTTP over TCP. + API: GstRTSPLowerTrans::GST_RTSP_LOWER_TRANS_HTTP + See also #573173. + +2009-03-02 12:48:18 +0100 Edward Hervey <bilboed@bilboed.com> + + * win32/common/libgstrtsp.def: + win32: Add gst_rtsp_connection_get_url definition + No, I'm not wim's buildslave, seriously. + +2009-03-02 10:58:49 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + rtsp: add _get_url method and separate sockets + Add gst_rtsp_connection_get_url() method. + Reserve space for 2 sockets, one for reading and one for writing. Use socket + pointers to select the read and write sockets. This should allow us to implement + tunneling over HTTP soon. + API: RTSP::gst_rtsp_connection_get_url() + +2009-03-01 18:31:17 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/app/gstapp-marshal.list: + app: force automatic rebuild of gstapp-marshal.[ch] after previous change + The previous change to appsrc/appsink requires people to 'make clean' + to get the marshallers rebuilt (causing a build failure otherwise). + Change some lines in the .list file around to force a rebuild of + these files automatically. + +2009-02-28 11:07:04 -0800 David Schleef <ds@schleef.org> + + * configure.ac: + Bump glib requirement to 2.14 + +2009-02-28 19:37:53 +0100 LRN <lrn1986@gmail.com> + + * ext/gio/gstgiobasesink.c: + gio: Use correct format modifier for size_t + Fixes bug #573528. + +2009-02-28 19:35:33 +0100 LRN <lrn1986@gmail.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: Use correct types for some functions on Win32 + Fixes bug #573529. + +2009-02-28 13:11:59 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtspconnection: Fix warning about using unitialized value. + +2009-02-28 12:41:28 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: + riff: Add more codec mappings. + This comes mostly from a review of ffmpeg/libavformat/riff.c + +2009-02-27 11:14:25 +0200 Stefan Kost <ensonic@users.sf.net> + + * ext/alsa/gstalsa.c: + alsa: release pcminfo after the strdup + +2009-02-26 17:38:47 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/rtsp/gstrtsprange.c: + rtsprange: don't leak the range in case of parsing error. + Free the gstRTSPTimeRange if we don't return it. Also simplify + gst_rtsp_range_free() as it is valid to pass NULL to g_free(). + +2009-02-26 16:47:39 +0200 Stefan Kost <ensonic@users.sf.net> + + * ext/alsa/gstalsa.c: + alsa: cleanup name lookup. + We can break, once we have a name to make sure, we won't read it ever twice. + +2009-02-26 16:09:03 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/subparse/gstsubparse.c: + subparse: don't leak line, if flushing + +2009-02-26 16:03:39 +0200 Stefan Kost <ensonic@users.sf.net> + + * ext/gio/gstgiosink.c: + giosink: reflow error handling to not leak uri + +2009-02-26 15:53:10 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: remove unused code/variables + +2009-02-26 12:10:47 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + ximagesink: use GST_FLOW_NOT_NEGOTIATED for partial caps + +2009-02-26 16:44:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/app/gstappsrc.h: + * win32/common/libgstapp.def: + app: add callbacks to appsrc, cleanups + Add a uri handler to appsink. + don't emit signals when we have installed callbacks on appsink. + Add callbacks to appsrc to replace the signals. + Add property to disable callbacks in appsrc, default to TRUE for backwards + compatibility but disable when callbacks are installed. + API: GstAppSrc::emit-signals + API: GstAppSrc::gst_app_src_set_emit_signals() + API: GstAppSrc::gst_app_src_get_emit_signals() + API: GstAppSrc::gst_app_src_set_callbacks() + +2009-02-26 11:42:44 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/app/gstappsink.h: + * tests/check/elements/appsink.c: + Appsink: add padding for callbacks + docs + Add some padding to the callbacks structure just to be safe. + Remove the now invisible marshaller methods from the docs. + Fix a comment in the unit test. + +2009-02-26 09:52:59 +0100 Edward Hervey <bilboed@bilboed.com> + + * win32/common/libgstapp.def: + win32: Add new libgstapp symbol + +2009-02-26 10:07:21 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/plugins/gst-plugins-base-plugins-sections.txt: + docs: clean section.txt file. + Add appsrc/sink symbols to private, as they are covered in the libs docs. + +2009-02-26 10:06:23 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaybasebin.c: + docs: fix random text after since: tag. Also fix class name to make the docs actual appear. + +2009-02-26 09:56:16 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst/playback/gstplaybin2.c: + docs: playbin2 has no stream-info + +2009-02-26 09:53:03 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/video/video.h: + docs: fix newly added interlace constants and plug holes in video format docs + +2009-02-26 09:35:43 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/audio/gstaudiofilter.c: + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + docs: don't put random stuff in tags. + Tags like Since: or Returns: can only be followed by more tags. gtk-doc has no + tag to append text again to the documentation body. + +2009-02-06 11:10:15 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/ximage/ximagesink.c: + ximagsink: do not access uninitialized height variable. + Exit like in xvimagesink, if we have partial caps. + +2009-02-25 20:26:05 -0800 David Schleef <ds@schleef.org> + + * Makefile.am: + * configure.ac: + * win32/common/config.h.in: + Change how win32/common/config.h is updated + Generate win32/common/config.h-new directly from config.h.in, + using shell variables in configure and some hard-coded information. + Change top-level makefile so that 'make win32-update' copies the + generated file to win32/common/config.h, which we keep in source + control. It's kept in source control so that the git tree is + buildable from VS. + This change is similar to the one recently applied to GStreamer, + except that it adds a few -base specific defines. + +2009-02-25 19:40:43 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * win32/common/libgstapp.def: + app: add win32 .def file and only export functions we want exported + Add a .def file for win32 builds (and make check-exports). + Fix LDFLAGS in Makefile.am, so the usual export regexps are used (fixes #573165). + Make sure private marshaller functions aren't exported by prefixing them with __gst; + also rename gst_app_marshal_OBJECT__VOID to _BUFFER__VOID, make it static and add + a comment why we're not using glib-genmarshal for this one. + +2009-02-25 17:08:24 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/examples/dynamic/.gitignore: + * tests/examples/dynamic/Makefile.am: + * tests/examples/dynamic/sprinkle.c: + sprinkle: Add another example app + Add an example app that dynamically adds and removes audiotestsrc elements from + adder. + +2009-02-25 16:25:33 +0100 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Fixed a typo. + +2009-02-25 11:31:02 +0100 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst/tcp/gstmultifdsink.c: + rtsp, multifdsink: Unify the use of union gst_sockaddr. + +2009-02-25 14:22:35 +0000 Jan Schmidt <thaytan@noraisin.net> + + * common: + * configure.ac: + build: Update shave init statement for changes in common. Bump common. + +2009-02-25 13:16:32 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + xvimageink: protect buffer_alloc from shutdown + Use the pool_lock in the buffer_alloc function to detect shutdown. Avoids + crashes when the sink is shutdown. + +2009-02-25 12:43:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin: use flushing pads instead of fakesink + Use the flushing pads on playsink to terminate on shutdown instead of plugging + fakesinks. this should be a little cheaper. + +2009-02-25 12:42:20 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaysink.c: + * gst/playback/gstplaysink.h: + playsink: Add FLUSHING pad type + Make it possible to request a flushing pad from the playsink. We can eventually + use these flushing pads to quickly terminate the dataflow when we are shutting + down. + +2009-02-25 11:31:52 +0000 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From 9cf8c9b to a6ce5c6 + +2009-02-25 09:52:38 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/riff/riff-media.c: + riff: add fourcc for mpeg2-in-avi (as produced by mencoder) + Fixes: #565777 + +2009-02-25 12:07:43 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/stress-playbin.c: + stress-playbin: print the current uri + Print the current uri so that we can more easily see what uri caused a crash or + error. + +2009-02-25 11:07:20 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * tests/icles/stress-playbin.c: + Print the errors more clearly + Print some more verbose messages when dealing with errors. + +2009-02-25 10:08:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + Release the group lock when setting states + Release the group lock while we perform the state changes on the uridecodebins + because that might trigger callbacks that we need to handle with the group lock + taken. Avoids a possible deadly embrace in some id3/flac files. + Fixes #567396. + +2009-02-25 10:05:38 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + Combine finding and creating groups + Combine the search for the current group and optionally creating one into one + function so that we can avoid taking the lock multiple times. + +2009-02-25 08:22:00 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst/playback/gstplaybin2.c: + Playbin2: Don't leave unused parameters in debug statements. + Fixes build on macosx + +2009-02-24 10:33:05 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + Riff: Add fourcc for mpeg1-in-avi (as produced by mencoder) + +2009-02-24 18:43:45 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + Add some G_UNLIKELY because we can + Add a G_UNLIKELY when checking the shutdown variable. + +2009-02-24 17:23:58 +0000 Garret D'Amore <garrett.damore@sun.com> + + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/interfaces/mixertrack.h: + mixer interface: Add flags to enhance mixer interfaces + This patch adds a few flags to the mixer and mixerctrl interface to + better support OSSv4 (and potentially other backends). + Patch By: Garret D'Amore <garrett.damore@sun.com> + Signed-Off-By: Jan Schmidt <jan.schmidt@sun.com> + API: GST_MIXER_FLAG_HAS_WHITELIST, GST_MIXER_FLAG_GROUPING, + API: GST_MIXER_TRACK_NO_RECORD, GST_MIXER_TRACK_NO_MUTE, + API: GST_MIXER_TRACK_WHITELIST + +2009-02-24 17:03:08 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst/tcp/gstmultifdsink.c: + multifdsink: Fix strict aliasing error using a union + +2009-02-24 16:49:40 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + rtsp: Fix a strict aliasing warning + Fix strict aliasing warnings from casting a sockaddr_storage and + using it as a sockaddr_in6. Use a union instead. + +2009-02-24 16:08:49 +0000 Jan Schmidt <thaytan@noraisin.net> + + * docs/libs/.gitignore: + * docs/libs/tmpl/.gitignore: + * docs/plugins/.gitignore: + * docs/plugins/tmpl/.gitignore: + Remove .gitignore files from the docs tmpl dirs, that are killed by make clean. + +2009-02-24 14:36:39 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * docs/plugins/Makefile.am: + * ext/vorbis/Makefile.am: + * ext/vorbis/gstvorbisdec.h: + * ext/vorbis/gstvorbisenc.h: + * ext/vorbis/gstvorbisparse.h: + * ext/vorbis/gstvorbistag.h: + * ext/vorbis/vorbis.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisdec.h: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisenc.h: + * ext/vorbis/vorbisparse.c: + * ext/vorbis/vorbisparse.h: + * ext/vorbis/vorbistag.c: + * ext/vorbis/vorbistag.h: + vorbis: Rename vorbis*.h to gstvorbis*.h to prevent name conflicts + +2009-02-24 14:06:38 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Add conversion from/to YVYU colorspace + Fixes bug #572872. + +2009-02-24 13:42:01 +0100 Jonas Danielsson <jonas.danielsson@axis.com> + + * gst/ffmpegcolorspace/imgconvert.c: + ffmpegcolorspace: Add direct UYVY->GRAY8 conversion + The conversion from UYVY to RGB24 and then to GRAY8 + is quite slow. Fixes bug #569655. + +2009-02-19 17:16:51 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaybin2.c: + playbin2: fix deadlock when shutting down. Fixes #572577. + +2009-02-19 17:15:18 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * tests/icles/stress-playbin.c: + stress-playbin: make more flexible, e.g. also useful for playbin2 + +2009-02-24 12:11:00 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Match WSAStartup and WSACleanup correctly + Don't randomly call WSAStartup and WSACleanup but instead call the startup when + we create a connection and cleanup when we free it again. Because the internal + datastructure is refcounted, this should not cause any refcounting leaks when + the connection is managed correctly. + Fixes #562794. + +2009-02-18 11:59:58 +0100 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst/playback/gstplaysink.c: + playbin2/playsink: Set audiotee to PAUSED state in all cases. Fixes #565105. + +2009-02-23 10:57:42 -0800 David Flynn <davidf@rd.bbc.co.uk> + + * pkgconfig/gstreamer-app-uninstalled.pc.in: + * pkgconfig/gstreamer-audio-uninstalled.pc.in: + * pkgconfig/gstreamer-cdda-uninstalled.pc.in: + * pkgconfig/gstreamer-fft-uninstalled.pc.in: + * pkgconfig/gstreamer-floatcast-uninstalled.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-netbuffer-uninstalled.pc.in: + * pkgconfig/gstreamer-pbutils-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-riff-uninstalled.pc.in: + * pkgconfig/gstreamer-rtp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp-uninstalled.pc.in: + * pkgconfig/gstreamer-sdp-uninstalled.pc.in: + * pkgconfig/gstreamer-tag-uninstalled.pc.in: + * pkgconfig/gstreamer-video-uninstalled.pc.in: + Add srcdir to includes for out-of-source builds + When you use gstreamer uninstalled and build outside + the source tree, the includes need to be specified for + both the source tree and the build tree. + Signed-off-by: David Schleef <ds@schleef.org> + +2009-02-22 17:23:52 +0000 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Use shave for the build output + +2009-02-23 12:17:07 +0100 Edward Hervey <bilboed@bilboed.com> + + * win32/common/libgstrtsp.def: + win32: Add new symbol to libgstrtsp.def + +2009-02-23 10:57:08 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspextension.c: + * gst-libs/gst/rtsp/gstrtspextension.h: + Add method for handling server requests + Add a receive_request so that extensions can react to server requests. + +2009-02-22 19:20:40 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * tests/check/libs/netbuffer.c: + Correctly cast to GstBuffer * before passing to gst_buffer_(copy|unref) + +2009-02-22 19:19:04 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * ext/theora/theoraparse.c: + theoraparse: Use the correct unref functions + +2009-02-22 19:18:41 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + x(v)imagesink: Correctly cast to GstBuffer * before passing to gst_buffer_unref() + +2009-02-22 19:12:00 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: Unref the actual buffer instead of the memory address of the buffer + +2009-02-22 15:47:53 +0000 Jan Schmidt <thaytan@noraisin.net> + + * common: + Automatic update of common submodule + From 5d7c9cc to 9cf8c9b + +2009-02-22 14:49:29 +0100 Edward Hervey <bilboed@bilboed.com> + + * win32/common/libgstrtsp.def: + * win32/common/libgstvideo.def: + win32/common: Update .def files for recent API addition + +2009-02-22 13:43:35 +0100 Edward Hervey <bilboed@bilboed.com> + + * tests/check/libs/rtp.c: + tests: Fix indentation + +2009-02-22 13:42:33 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/video/video.c: + libs/video: Fix gst_video_format_new_caps* functions. + Only add a 'interlaced=True' property to caps *IF* it is interlaced, else + don't add anything. + +2009-02-21 11:13:36 -0800 David Schleef <ds@schleef.org> + + * common: + Automatic update of common submodule + From 80c627d to 5d7c9cc + +2009-02-20 17:26:40 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + Improve key/value parsing + Improve header field parsing by keeping a ref to the key/value instead of + copying it into a local variable. + +2009-02-20 12:35:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Add trailing \0 to message length + We always put a trailing 0 at the end of the message body. Reflect this fact in + the length of the message. + +2009-02-20 09:50:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Don't parse headers for data messages + Don't try to parse the headers on a data message because they don't have + headers. + +2009-02-19 12:18:29 -0800 Benjamin M. Schwartz <bens@alum.mit.edu> + + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + theoraenc: Add property for speed level control + Add property "speed-level" to control the amount of motion searching + the encoder does. This is only available in libtheora >= 1.0 and + will silently fail with earlier libraries. Fixes: #572275. + Signed-off-by: David Schleef <ds@schleef.org> + +2009-02-19 17:40:45 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Fix 'Since' tags + +2009-01-26 10:30:53 +0100 Edward Hervey <bilboed@bilboed.com> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + video: Add flags for interlaced video along with convenience methods for interlaced caps. + These three flags allow all know combinations of interlaced formats. They should + only be used when the caps contain 'interlaced=True'. + Fixes #163577 (yes, it's a 4 year old bug). + +2009-02-19 15:51:52 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + Make RTSPConnection opaque and rename RTSPChannel + Make the RTSPConnection object opaque so that we can extend it in the future. + Rename GstRTSPChannel to GstRTSPWatch to avoid confusing with the RTSP channels. + +2009-01-26 10:31:14 +0100 Edward Hervey <bilboed@bilboed.com> + + * gst-libs/gst/riff/riff-media.c: + Add some more mappings for h264 in riff + +2009-02-19 10:49:56 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstrtsp.def: + Add new RTSP symbols to def files + Add the new RTSP symbols to the windows def file. + +2009-02-19 10:44:31 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsink.h: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/appsink.c: + Add method to install callbacks on appsink + Based on pacth by Martin Samuelsson <martin dot samuelsson at axis dot com> + Fixes #571299. + Add gst_app_sink_set_callbacks() to install a set of callbacks. This is a more + performant alternative to connecting to the signals. + Add a unit test for appsink. + Clean up some of the appsink docs. + API: GstAppSink::gst_app_sink_set_callbacks() + +2009-02-18 18:46:35 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + Add RTSP accept method + Add a method to accept a connection on a socket and create a GstRTSPConnection + for it. + API: gst_rtsp_connection_accept() + +2009-02-18 17:42:59 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspconnection.h: + Add RTSP channel object for async io + Add a GstRTSPChannel object that wraps a GSource around the RTSP connection so + that the connection can be monitored from a maincontext. This allows us to + operate in ASYNC mode, which is handy when building a server. + Rework the old code to use the async code under the hood. + API: gst_rtsp_channel_new() + API: gst_rtsp_channel_unref() + API: gst_rtsp_channel_attach() + API: gst_rtsp_channel_queue_message() + +2009-02-15 07:30:17 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/audioresample/gstaudioresample.c: + audioresample: Add locking to protect the resampling context + When setting the quality/filter-length while PLAYING the + resampling context will be destroyed and created again in + some cases, which will cause crashes in the transform function + if it's called at that time. + +2009-02-13 10:10:25 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/videotestsrc/videotestsrc.c: + ffmpegcolorspace/videotestsrc: Use v308 instead of V308 + +2009-02-12 19:02:59 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + ffmpegcolorspace: Add support for packed 4:4:4 YUV (format=V308) + Only conversions from/to are implemented, which + gives (indirect) support for all possible conversions. + Partially fixes bug #571147. + +2009-02-12 18:17:53 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add support for packed 4:4:4 YUV (format=V308) + Partially fixes bug #571147. + +2009-02-12 09:18:20 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/tag/gsttagdemux.c: + tagdemux: don't abort when downstream pulls a buffer of size 0 + Pulling a 0-sized buffer is allowed, and we should handle this correctly instead of + aborting. Fixes #571009 (wma file with ID3v2 tag). + +2009-02-11 16:39:55 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/riff/riff-read.c: + riff: error out on nonsensical chunk sizes instead of aborting + When encountering a nonsensical chunk size such as (guint)-1, error out cleanly instead of + continuing and trying to g_memdup() 4GB of data that doesn't exist, which will either abort + in g_malloc() or crash. + Fixes #553295, crash with fuzzed AVI file. + +2009-02-11 16:39:06 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * .gitignore: + Make git ignore backup files. + +2009-02-10 20:38:58 -0800 Michael Smith <msmith@syncword.(none)> + + * gst/playback/gstplaybin2.c: + Revert "Remove pad-removed handlers after setting the decodebins to NULL." + This reverts commit b36d8f3e119f9edc5993c08025614ee32642972e. + This brought back some deadlocks. A small leak is better, for now. Need to + figure out a way to fix the leak properly. + +2009-02-10 17:16:07 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + playbin2: Fix segfault on notify after group change. + If our group has been switched, then we get a selector active-pad + notification, we don't need to notify. + +2009-02-10 17:10:33 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaysink.c: + playbin2: Look for volume/mute properties recursively in audio element. + Rather than only checking for volume property on the audio sink + directly, recursively look for it on sinks within it (if it's a bin). + Allows use of sink-as-volume-control where the application has supplied + an audio-sink bin that includes a real audio sink internally. + +2009-02-10 18:29:22 +0000 Christian Schaller <cschalle@crazyhorse.localdomain> + + * gst-plugins-base.spec.in: + Update spec file with latest additions and changes, most noteably the move of appsrc appsink into -base + +2009-02-10 17:39:45 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * gst/videotestsrc/videotestsrc.c: + videotestsrc: Add support for Y444 (planar 4:4:4 YUV) + Partially fixes bug #571147. + +2009-02-10 17:37:06 +0100 Peter Kjellerstedt <pkj@axis.com> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + gstrtspmessage: Minor documentation correction. + Corrected documentation about what needs to be freed after calling + gst_rtsp_message_new(), gst_rtsp_message_new_request(), + gst_rtsp_message_new_response() and gst_rtsp_message_new_data(). + +2009-02-10 11:00:12 +0100 Antoine Tremblay <hexa00@gmail.com> + + * ext/alsa/gstalsamixer.c: + alsamixer: Fix race condition that made alsamixer not working properly + This is due to race conditions between functions that + modified the mixer like set_volume and + snd_mixer_handle_events since the handle_events + can now be called at any time. + Fixed by adding locking around any snd_mixer call + since even read functions can modify the mixer stucture, since + alsa likes to clear it's values before reading new ones. + The favorite race condition seemed to be that set_volume + called read_elem (in alsalib) that reset the volumes to + 0 and then read them with read_x_volume. This read looped + on each channel and as the race condition occured the + channels value could be anything , most of the time + it was 0. Thus no value was read or only the value of + one channel was and the volume was reset to 0. + Fixes bug #478512. + +2009-02-09 12:02:21 +0100 Edward Hervey <bilboed@bilboed.com> + + * common: + Bump revision to use for common submodule. + +2009-02-05 15:47:00 +0200 Stefan Kost <ensonic@users.sf.net> + + * sys/xvimage/xvimagesink.c: + xvimagesink: do not call _xwindow_clear on ready->paused. + Calling clear at that transition does things like stopping xvideo (which is not + running at that time) and also clearing anything what the application might have drawn. + This breaks handle-expose and autopaint-colorkey features. + +2009-02-04 17:03:52 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtsprange.c: + * gst-libs/gst/rtsp/gstrtsprange.h: + RTSPRange: Add method to serialize ranges + Add gst_rtsp_range_to_string() to serialize a GstRTSPRange to a string that can + be used by a server. + API: GstRTSPRange::gst_rtsp_range_to_string() + +2009-02-04 13:16:48 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspurl.c: + * gst-libs/gst/rtsp/gstrtspurl.h: + GstRTSPUrl: Add some const to methods + Add const to the methods that do not modify the object. + +2009-02-04 13:53:30 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/playback/gstplaysink.c: + playbin2: implement GST_PLAY_FLAG_NATIVE_{AUDIO,VIDEO} + The flags where present but actually not been taken into account. + +2009-02-04 12:06:38 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/audioresample/gstaudioresample.c: + audioresample: Add a proper deprecation comment and also drop G_PARAM_CONSTRUCT. + The comment will ensure that is is marked properly in the docs and the + GParamSpecflag was causing a duplicated initialisation of the same value. + +2009-02-04 11:18:31 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspconnection.c: + Add more g_return_if_fail() calls + Check that we have a valid file descriptor before entering certain functions in + order to avoid undesirable situations. + Add some more debugging in the connect method. + +2009-02-04 10:31:21 +0200 Stefan Kost <ensonic@users.sf.net> + + * configure.ac: + * gst/audioresample/Makefile.am: + * gst/audioresample/gstaudioresample.c: + audioresample: Only pull in liboil if its actualy used. + Liboil still has quite significant startup overhead especialy on embedded + platforms. In audioresample it was only used for the profiling timer. + +2009-02-03 15:26:08 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst/typefind/gsttypefindfunctions.c: + typefind: Make the flac check more tight to not mistace some aac files for flac. Fixes #570356. + Add comments about the flac format. Tighten the check to not allow values that + refer to headers. + +2009-02-03 10:52:15 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * win32/common/libgstrtsp.def: + Add new methods + Add new methods to the windows def file. + +2009-02-02 17:25:21 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + * gst-libs/gst/pbutils/install-plugins.c: + * tests/check/libs/pbutils.c: + pbutils: remove duplicate detail strings when calling the external codec installer + It doesn't make sense to ask installers for the same codec or element twice, so filter out duplicate requests before calling the external helper script and make the unit test check this works right. Fixes #567636. + +2009-02-02 18:05:42 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosink.h: + Add a FIXME 0.11. Make the log message a bit more detailed and add comments. + +2009-02-02 15:43:03 +0200 Stefan Kost <ensonic@users.sf.net> + + * configure.ac: + * gst/audioresample/gstaudioresample.c: + Allow to configure the resampler function for integer to skip the benchmarking. Fix releasing the intger resampler in benchmark. + +2009-02-02 13:30:42 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * sys/ximage/ximagesink.c: + Fix buffer_alloc in ximagesink + Remove some useless debug info that reported wrong image sizes. + When upstream does not accept out suggested size, fall back to allocating an + image of the requested width/height instead of the currently configured size. + The problem is that an image is reused from the pool because the width/height + match but the caps on the new buffer are the requested caps with possibly + different height/width resulting in errors. + +2009-02-02 12:54:31 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gstdecodebin2.c: + * gst/playback/gsturidecodebin.c: + Fix documentation for autoplug-select + fix the documentation strings for the autoplug-select signal. + Fixes #570142. + +2009-02-02 10:09:07 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspmessage.c: + Fix string leak in rtspmessage + when we remove a header field from a message we must free the value associated + with the key to avoid a memory leak. + +2009-01-31 18:45:47 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/libs/gst-plugins-base-libs-docs.sgml: + Its "Base Library" and not just "Library". + +2009-01-31 18:44:32 +0200 Stefan Kost <ensonic@users.sf.net> + + * gst-libs/gst/audio/gstaudiofilter.c: + Link to the class, as we can't link to the members yet. + +2009-01-30 17:48:23 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Remove pad-removed handlers after setting the decodebins to NULL. + They do needed cleanup; without this we leak selector requestpads. + +2009-01-30 17:47:07 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Unref selector request pad even if we no longer have a selector. + During destruction, we won't have a selector any more, but we still need + to unref the pad to avoid leaking it. + +2009-01-30 15:23:23 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Unref source in playbin2's finalize method + +2009-01-30 12:04:01 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaysink.c: + Fix more leaks of pads and elements in gstplaysink. + Don't keep extra references to volume and mute elements; we don't need + to do so. + Ensure we unref pads that we have references to, and release request + pads. + +2009-01-30 11:04:37 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaysink.c: + Avoid leaking all playsinks. Fix some internal leaks. + Playsink was holding references to itself. Don't do that, it's not cool. + Also, free all chains in dispose. + +2009-01-30 10:54:12 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Unref peer request pad after releasing it, since we hold a reference. + +2009-01-30 10:52:52 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Fix caps leak in playbin2. + +2009-01-30 10:51:11 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Unref active pad from selector when finding active stream. + +2009-01-30 10:49:55 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gstplaybin2.c: + Free uris when finalizing playbin2 instance. + +2009-01-30 10:38:17 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/playback/gsturidecodebin.c: + Unref pads when iterating over them in analyse_source. + Fixes leak of source's srcpad when using uridecodebin. + +2009-01-30 22:22:07 +0200 Stefan Kost <ensonic@users.sf.net> + + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + Add releaseinfo with online url. + +2009-01-30 17:58:15 +0000 Jan Schmidt <jan.schmidt@sun.com> + + * gst/playback/gstplaybasebin.c: + Fix compilation warning on Forte + +2009-01-30 17:16:39 +0000 Jan Schmidt <jan.schmidt@sun.com> + + * gst/adder/gstadder.c: + Don't do void pointer arithmetic. + +2009-01-30 17:25:51 +0000 Jan Schmidt <thaytan@noraisin.net> + + * common: + Bump common + +2009-01-30 08:50:53 +0100 Edward Hervey <bilboed@bilboed.com> + + * autogen.sh: + * common: + Use a symbolic link for the pre-commit client-side hook + +2009-01-30 08:12:42 +0100 Edward Hervey <bilboed@bilboed.com> + + * .gitignore: + Add more files/directories to ignore + +2009-01-29 14:00:30 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + fix some typos + Fix some typos in the doc string of the new + gst_rtsp_options_as_string() method. + +2009-01-29 11:55:10 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspconnection.c: + * gst-libs/gst/rtsp/gstrtspmessage.c: + * gst-libs/gst/rtsp/gstrtspmessage.h: + Add new RTSP message method to set header + Add gst_rtsp_message_take_header() that takes ownership of the passed header + value. This allows us to avoid an allocations and memory copy in some + situations. + API: GstRTSPMessage::gst_rtsp_message_take_header() + +2009-01-29 11:51:23 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * docs/libs/gst-plugins-base-libs-sections.txt: + Add new method to docs + Add the new gst_rtsp_options_as_text() method to the docs. + +2009-01-28 11:48:01 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtsp/gstrtspdefs.c: + * gst-libs/gst/rtsp/gstrtspdefs.h: + Add method to serialize RTSP options + Add gst_rtsp_options_as_text() method to serialize a set of RTSP options to a + string. + API: GstRTSP::gst_rtsp_options_as_text() + +2009-01-26 17:59:37 -0800 Michael Smith <msmith@songbirdnest.com> + + * gst/typefind/gsttypefindfunctions.c: + Ensure we have sufficient data when using data scan contexts. + Fixes crashes typefinding things that look like they might contain AAC + data (but probably aren't actually AAC). + +2009-01-26 23:32:09 +0000 Jan Schmidt <thaytan@noraisin.net> + + * ext/gio/Makefile.am: + Fix include order for gio plugin + +2009-01-23 23:59:48 +0000 Jan Schmidt <thaytan@noraisin.net> + + * win32/common/config.h: + Update win32 config.h for 0.10.22.1 dev cycle + +2009-01-23 23:16:11 +0000 Jan Schmidt <thaytan@noraisin.net> + + * .gitignore: + * docs/libs/.gitignore: + * gst-libs/gst/audio/.gitignore: + * gst-libs/gst/video/.gitignore: + * po/.gitignore: + * tests/examples/dynamic/.gitignore: + Extend and clean up git ignores + +2009-01-23 12:31:06 +0100 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst/audioresample/Makefile.am: + * gst/audioresample/README: + * gst/audioresample/arch.h: + * gst/audioresample/buffer.c: + * gst/audioresample/buffer.h: + * gst/audioresample/debug.c: + * gst/audioresample/debug.h: + * gst/audioresample/fixed_arm4.h: + * gst/audioresample/fixed_arm5e.h: + * gst/audioresample/fixed_bfin.h: + * gst/audioresample/fixed_debug.h: + * gst/audioresample/fixed_generic.h: + * gst/audioresample/functable.c: + * gst/audioresample/functable.h: + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + * gst/audioresample/resample.c: + * gst/audioresample/resample.h: + * gst/audioresample/resample_chunk.c: + * gst/audioresample/resample_functable.c: + * gst/audioresample/resample_ref.c: + * gst/audioresample/resample_sse.h: + * gst/audioresample/speex_resampler.h: + * gst/audioresample/speex_resampler_double.c: + * gst/audioresample/speex_resampler_float.c: + * gst/audioresample/speex_resampler_int.c: + * gst/audioresample/speex_resampler_wrapper.h: + * gst/speexresample/Makefile.am: + * gst/speexresample/README: + * gst/speexresample/arch.h: + * gst/speexresample/fixed_arm4.h: + * gst/speexresample/fixed_arm5e.h: + * gst/speexresample/fixed_bfin.h: + * gst/speexresample/fixed_debug.h: + * gst/speexresample/fixed_generic.h: + * gst/speexresample/gstspeexresample.c: + * gst/speexresample/gstspeexresample.h: + * gst/speexresample/resample.c: + * gst/speexresample/resample_sse.h: + * gst/speexresample/speex_resampler.h: + * gst/speexresample/speex_resampler_double.c: + * gst/speexresample/speex_resampler_float.c: + * gst/speexresample/speex_resampler_int.c: + * gst/speexresample/speex_resampler_wrapper.h: + * gst/typefind/gsttypefindfunctions.c: + * tests/check/Makefile.am: + * tests/check/elements/audioresample.c: + * tests/check/elements/speexresample.c: + Rename files and types from speexresample to audioresample + Rename files and types from speexresample to audioresample + to finish the move and to prevent any confusion. + +2009-01-23 11:44:53 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * sys/xvimage/xvimagesink.c: + Add some more debugging to the Xv strides + Add some more debugging to the strides as they are received from the server and + the expected strides. + +2009-01-23 11:40:26 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/typefind/gsttypefindfunctions.c: + Add typefind function for gsm + Because core now supports typefindfactories without a typefind function we can + register a factory fo GSM that will --if all else fails-- assume the file is a + GSM file based on the registered extension. + Fixes #566661. + +2009-01-23 11:37:45 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst/playback/gsturidecodebin.c: + Use more performant link function + We can use gst_element_link_pads() instead of the more generic + gst_element_link() function because we know the pads. This saves some cycles + because the more generic function needs to search for possible compatible caps + etc. + +2009-01-23 11:33:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: + Add more codec ids for RIFF formats + Handle codec ID for various other AAC formats. + Sync the list of possible codec ids with that of ffmpeg. + Fixes #567255 + +2009-01-23 11:27:16 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/theora/theoradec.c: + Use rounded values for image strides and sizes + Round up the height before calculating the expected size and + strides of the output image. + +2009-01-23 11:23:09 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * ext/alsa/gstalsasink.c: + Improve debug message + Improve the debug message when alsa returns an error. + +2009-01-23 11:07:05 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/app/gstappsrc.c: + Reset queued_bytes counter when flushing + Set the amount of queued bytes in the internal queue back to 0 when we clear the + queue. + Fixes #567982 + +2009-01-23 10:19:27 +0100 Benjamin Gaignard <benjamin@gaignard.net> + + * gst/typefind/gsttypefindfunctions.c: + Add typefinder for Mobile XMF. Fixes bug #568707. + +2009-01-23 10:00:11 +0100 Brian Cameron <brian.cameron@sun.com> + + * configure.ac: + Fix linking on Solaris. Fixes bug #568482. + Check for nsl and socket libraries and add them to + LIBS if they're found. They're needed for socket() + and gethostbyname() on Solaris. + +2009-01-22 22:09:47 +0000 Jan Schmidt <thaytan@noraisin.net> + + * gst/playback/gstplaybasebin.c: + Fix use-after-unref problem noticed by Josep Torra Valles, and run gst-indent + +2009-01-22 17:46:59 +0200 Stefan Kost <ensonic@users.sf.net> + + * common: + Update common snapshot. + +2009-01-22 13:47:24 +0100 Sebastian Dröge <slomo@circular-chaos.org> + + * common: + Fix pre-commit hook + +2009-01-22 13:12:02 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + Merge branch 'master' of ssh://git.freedesktop.org/git/gstreamer/gst-plugins-base + +2009-01-22 10:14:28 +0100 Sebastian Dröge <slomo@circular-chaos.org> + + * gst-libs/gst/fft/gstfftf32.c: + * gst-libs/gst/fft/gstfftf64.c: + * gst-libs/gst/fft/gstffts16.c: + * gst-libs/gst/fft/gstffts32.c: + Reduce the number of allocations for creating FFT contexts + Reduce the number of allocations from 2 to 1 for every FFT + context by allocating enough memory for the FFT context + and passing parts of it to the kissfft allocation functions. + +2009-01-22 11:32:56 +0000 Jan Schmidt <thaytan@noraisin.net> + + * configure.ac: + Back to devel -> 0.10.22.1 + +2009-01-22 05:57:53 +0100 Edward Hervey <bilboed@bilboed.com> + + * autogen.sh: + * common: + Install and use pre-commit indentation hook from common + +2009-01-21 13:09:29 +0100 Wim Taymans <wim.taymans@collabora.co.uk> + + * gst-libs/gst/rtp/gstrtpbuffer.c: + * tests/check/libs/rtp.c: + Avoid overflows in the padding checks by doing the check slightly differently. Add a unit test to check for correct behaviour. + +2009-01-21 04:31:32 +0100 Edward Hervey <bilboed@bilboed.com> + + * autogen.sh: + autogen.sh : Use git submodule + +=== release 0.10.22 === + +2009-01-19 23:10:50 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * po/LINGUAS: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + * win32/common/config.h: + Release 0.10.22 + Original commit message from CVS: + Release 0.10.22 + +2009-01-19 22:01:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2009-01-16 11:44:04 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/fft/: Use correct struct alignment everywhere to prevent unaligned memory accesses, resulting in SIGBUS ... + Original commit message from CVS: + * gst-libs/gst/fft/_kiss_fft_guts_f32.h: + * gst-libs/gst/fft/_kiss_fft_guts_f64.h: + * gst-libs/gst/fft/_kiss_fft_guts_s16.h: + * gst-libs/gst/fft/_kiss_fft_guts_s32.h: + * gst-libs/gst/fft/kiss_fftr_f32.c: (kiss_fftr_f32_alloc): + * gst-libs/gst/fft/kiss_fftr_f64.c: (kiss_fftr_f64_alloc): + * gst-libs/gst/fft/kiss_fftr_s16.c: (kiss_fftr_s16_alloc): + * gst-libs/gst/fft/kiss_fftr_s32.c: (kiss_fftr_s32_alloc): + Use correct struct alignment everywhere to prevent unaligned + memory accesses, resulting in SIGBUS on sparc and probably others. + Fixes bug #500833. + +2009-01-16 11:40:02 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/tag/gsttagdemux.c: Forward unknown events upstream to allow latency configuration. + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: (gst_tag_demux_srcpad_event): + Forward unknown events upstream to allow latency configuration. + Fixes bug #567960. + +2009-01-13 14:47:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Provide the right arguments to a debug line. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (groups_set_locked_state): + Provide the right arguments to a debug line. + +2009-01-13 06:51:54 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Don't reset the colorkey when element is reused. Fixes #567511. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Don't reset the colorkey when element is reused. Fixes #567511. + +2009-01-09 23:42:22 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: 0.10.21.3 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.21.3 pre-release + +2009-01-09 23:13:17 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/app/gstappsink.c: Store the returned signal id in the right slot when registering the pull-buffer signal. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: + Store the returned signal id in the right slot when + registering the pull-buffer signal. + Fixes #567168 + Spotted by: Thomas Vander Stichele <thomas at apestaart dot org> + +2009-01-09 17:17:50 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixer.c: Small docs addition to clarify that one really mustn't free the constant GList retur... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixer.c: + Small docs addition to clarify that one really mustn't free + the constant GList returned (#566812). + +2009-01-08 17:18:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add GType for GstRTSPUrl and expose a copy function because we can. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspurl.c: (register_rtsp_url_type), + (gst_rtsp_url_get_type), (gst_rtsp_url_copy): + * gst-libs/gst/rtsp/gstrtspurl.h: + * win32/common/libgstrtsp.def: + Add GType for GstRTSPUrl and expose a copy function because we can. + API: gst_rtsp_url_copy() + Fixes #567027. + +2009-01-07 18:36:04 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add plugin dependency for the GIO and GVfs modules. + Original commit message from CVS: + * configure.ac: + * ext/gio/gstgio.c: (plugin_init): + Add plugin dependency for the GIO and GVfs modules. + Fixes bug #566876. + +2009-01-07 18:32:33 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add plugin dependency for the gnomevfs modules. + Original commit message from CVS: + * configure.ac: + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + Add plugin dependency for the gnomevfs modules. + Fixes bug #566875. + +2009-01-07 18:30:52 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstcdda.def: Add new symbol to the list of exported symbols. + Original commit message from CVS: + * win32/common/libgstcdda.def: + Add new symbol to the list of exported symbols. + +2009-01-07 13:52:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Fix some comments and docs. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_set_uri), (gst_play_bin_set_suburi), + (no_more_pads_cb), (drained_cb), (group_set_locked_state_unlocked), + (activate_group), (deactivate_group), (groups_set_locked_state), + (gst_play_bin_change_state): + Fix some comments and docs. + Post an error message when we fail to link the selector to the sink. + Remove pushing of EOS, this seems unneeded. + Lock the state of deactivated groups so that they don't accidentally + reactivate when the playbin2 state changes. + Reuse uridecodebins. + Unlock and relock state of groups when playbin goes to NULL. + Fixes #566654. + Fixes #566341. + * gst/playback/gsturidecodebin.c: (pad_removed_cb), (type_found): + Only do something in the pad removed callback when we are dealing with + our sourcepads because the sinkpads don't have a ghostpad. + +2009-01-07 10:50:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/cdda/gstcddabasesrc.*: Make the GType of GstCDDABaseSrcMode public for bindings. + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + * gst-libs/gst/cdda/gstcddabasesrc.h: + Make the GType of GstCDDABaseSrcMode public for bindings. + Fixes bug #566837. + +2009-01-06 18:03:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + Use new core API to make registry re-scan the plugin whenever visualisations are added or removed (see #350477). + Original commit message from CVS: + * configure.ac: + * ext/libvisual/visual.c: (plugin_init): + Use new core API to make registry re-scan the plugin + whenever visualisations are added or removed (see #350477). + +2009-01-06 17:30:31 +0000 José Alburquerque <jaalburqu@svn.gnome.org> + + gst-libs/gst/audio/gstaudioclock.*: Make gst_audio_clock_new use const gchar* to ease the wrapping of + Original commit message from CVS: + Patch by: José Alburquerque <jaalburqu svn gnome org> + * gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_new): + * gst-libs/gst/audio/gstaudioclock.h: + Make gst_audio_clock_new use const gchar* to ease the wrapping of + C++ bindings. Fixes #566723. + +2009-01-06 12:16:18 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add pkg-config files for libgstapp. Fixes bug #566761. + Original commit message from CVS: + * configure.ac: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-app-uninstalled.pc.in: + * pkgconfig/gstreamer-app.pc.in: + Add pkg-config files for libgstapp. Fixes bug #566761. + +2009-01-06 11:10:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/app/: Make debug categories static. Use _element_class_set_details_simple(). + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsink.h: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/app/gstappsrc.h: + Make debug categories static. Use _element_class_set_details_simple(). + +2009-01-06 10:56:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/app/: Move private data into a private instance struct. Add padding to instance and class structures exp... + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (_GstAppSinkPrivate), + (gst_app_sink_class_init), (gst_app_sink_init), + (gst_app_sink_dispose), (gst_app_sink_finalize), + (gst_app_sink_unlock_start), (gst_app_sink_unlock_stop), + (gst_app_sink_flush_unlocked), (gst_app_sink_start), + (gst_app_sink_stop), (gst_app_sink_event), (gst_app_sink_preroll), + (gst_app_sink_render), (gst_app_sink_getcaps), + (gst_app_sink_set_caps), (gst_app_sink_get_caps), + (gst_app_sink_is_eos), (gst_app_sink_set_emit_signals), + (gst_app_sink_get_emit_signals), (gst_app_sink_set_max_buffers), + (gst_app_sink_get_max_buffers), (gst_app_sink_set_drop), + (gst_app_sink_get_drop), (gst_app_sink_pull_preroll), + (gst_app_sink_pull_buffer):: + * gst-libs/gst/app/gstappsink.h: (GstAppSinkPrivate), (_GstAppSink):: + * gst-libs/gst/app/gstappsrc.c: (_GstAppSrcPrivate), + (gst_app_src_class_init), (gst_app_src_init), + (gst_app_src_flush_queued), (gst_app_src_dispose), + (gst_app_src_finalize), (gst_app_src_set_property), + (gst_app_src_get_property), (gst_app_src_unlock), + (gst_app_src_unlock_stop), (gst_app_src_start), (gst_app_src_stop), + (gst_app_src_is_seekable), (gst_app_src_check_get_range), + (gst_app_src_query), (gst_app_src_do_seek), (gst_app_src_create), + (gst_app_src_set_caps), (gst_app_src_get_caps), + (gst_app_src_set_size), (gst_app_src_get_size), + (gst_app_src_set_stream_type), (gst_app_src_get_stream_type), + (gst_app_src_set_max_bytes), (gst_app_src_get_max_bytes), + (gst_app_src_set_latencies), (gst_app_src_set_latency), + (gst_app_src_get_latency), (gst_app_src_push_buffer_full), + (gst_app_src_push_buffer_action), (gst_app_src_end_of_stream):: + * gst-libs/gst/app/gstappsrc.h: (GstAppSrcPrivate):: + Move private data into a private instance struct. Add padding to + instance and class structures exposed in public headers. Add + Since markers to the gtk-doc blurbs (#566750). + +2009-01-06 10:50:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/app/appsrc_ex.c: Some comments. + Original commit message from CVS: + * tests/examples/app/appsrc_ex.c: (main): + Some comments. + When pulling a buffer we can get NULL when the element is EOS, don't try + to unref this NULL buffer. + +2009-01-06 10:16:16 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/video/: Fix up build flags and include statement for the new generated enumtypes files, to fix dist. + Original commit message from CVS: + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/video.h: + Fix up build flags and include statement for the new generated + enumtypes files, to fix dist. + +2009-01-05 23:04:57 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Move AppSrc/AppSink from gst-plugins-bad. Fixes #564421 + Original commit message from CVS: + * configure.ac: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-app.xml: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * tests/examples/Makefile.am: + * tests/examples/app/Makefile.am: + Move AppSrc/AppSink from gst-plugins-bad. Fixes #564421 + +2009-01-05 17:13:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Avoid holding the OBJECT_LOCK when calling ringbuffer functions that take the ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_change_state): + Avoid holding the OBJECT_LOCK when calling ringbuffer functions that + take the ringbuffer lock because rinbuffer lock > OBJECT_LOCK. We can do + this because the async_play method is deprecated and usually not called + anymore. + +2009-01-05 12:18:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Disconnect signal handlers before destroying a previous decodebin so that we don't end up... + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (notify_source_cb), (activate_group): + Disconnect signal handlers before destroying a previous decodebin so + that we don't end up causing deadlocks. Fixes #566586. + +2009-01-05 10:59:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiotestsrc/gstaudiotestsrc.*: Add property to control pull/push based scheduling. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_class_init), (gst_audio_test_src_init), + (gst_audio_test_src_check_get_range), + (gst_audio_test_src_set_property), + (gst_audio_test_src_get_property): + * gst/audiotestsrc/gstaudiotestsrc.h: + Add property to control pull/push based scheduling. + +2009-01-02 15:04:13 +0000 Alessandro Decina <alessandro.d@gmail.com> + + Make the seek and colorkey examples depend on gtk+-x11 as they use + Original commit message from CVS: + * configure.ac: + * tests/examples/seek/Makefile.am: + * tests/icles/Makefile.am: + Make the seek and colorkey examples depend on gtk+-x11 as they use + GDK_WINDOW_XID. + Fixes the build with gtk+-quartz. + +2008-12-31 16:04:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + win32/common/: Add new exports to win32 files. + Original commit message from CVS: + * win32/common/libgstaudio.def: + * win32/common/libgsttag.def: + * win32/common/libgstvideo.def: + Add new exports to win32 files. + +2008-12-31 13:31:55 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/tag/gsttagdemux.*: Add GType for GstTagDemuxResult enum. + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: (gst_tag_demux_result_get_type): + * gst-libs/gst/tag/gsttagdemux.h: + Add GType for GstTagDemuxResult enum. + +2008-12-31 13:01:30 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/video/: Add glib-mkenum for GstVideoFormat enum GTYPE auto-generation. + Original commit message from CVS: + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/video.h: + Add glib-mkenum for GstVideoFormat enum GTYPE auto-generation. + This will help bindings to use it. + +2008-12-31 11:20:26 +0000 Edward Hervey <bilboed@bilboed.com> + + Switch glib-mkenum for gst-libs/gst/audio from multichannel- to audio- in order to wrap all enums declarations of tha... + Original commit message from CVS: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/audio/multichannel.h: + * gst-libs/gst/audio/testchannels.c: + * win32/MANIFEST: + * win32/common/audio-enumtypes.c: + (gst_audio_channel_position_get_type), + (gst_ring_buffer_state_get_type), + (gst_ring_buffer_seg_state_get_type), + (gst_buffer_format_type_get_type), (gst_buffer_format_get_type): + * win32/common/audio-enumtypes.h: + * win32/common/multichannel-enumtypes.c: + * win32/common/multichannel-enumtypes.h: + * win32/vs6/grammar.dsp: + * win32/vs6/libgstaudio.dsp: + * win32/vs7/libgstaudio.vcproj: + * win32/vs8/libgstaudio.vcproj: + Switch glib-mkenum for gst-libs/gst/audio from multichannel- to + audio- in order to wrap all enums declarations of that library. + This modification should not matter since that header file is not a + public header (it will be included by public headers). + Modify win32 crap^Wfiles accordingly. + +2008-12-30 17:55:07 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/audio/: Complete Sebastien's commit from the 13th by exporting the _slave_method_get_type() methods. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.h: + * gst-libs/gst/audio/gstbaseaudiosink.h: + Complete Sebastien's commit from the 13th by exporting the + _slave_method_get_type() methods. + +2008-12-29 16:45:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsrc.*: Add properties and methods to configure and retrieve the min and max latencies. + Original commit message from CVS: + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_init), (gst_app_src_set_property), + (gst_app_src_get_property), (gst_app_src_query), + (gst_app_src_set_latencies), (gst_app_src_set_latency), + (gst_app_src_get_latency), (gst_app_src_push_buffer_full): + * gst-libs/gst/app/gstappsrc.h: + Add properties and methods to configure and retrieve the min and max + latencies. + +2008-12-20 17:38:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/: Implement URI query. Fixes bug #562949. + Original commit message from CVS: + * ext/gio/gstgiobasesink.c: (gst_gio_base_sink_query): + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_class_init), + (gst_gio_base_src_query): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_query): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init), + (gst_gnome_vfs_src_query): + Implement URI query. Fixes bug #562949. + +2008-12-20 12:48:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Add some debug info. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (no_more_pads_cb): + Add some debug info. + * gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain), + (gst_play_sink_reconfigure), (gst_play_sink_request_pad), + (gst_play_sink_release_pad): + Add some more debug info. + Reconfigure the audio chain when we switch between raw and encoded audio + in gapless playback. + +2008-12-20 12:45:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Pause the write thread before deactivating and releasing the ringbuffer to avo... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_setcaps): + Pause the write thread before deactivating and releasing the ringbuffer + to avoid a deadlock when we do gapless playback with different sample + rates in playbin2. Fixes #564929. + +2008-12-19 13:03:00 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Make GstAudioSrcSlaveMethod get_type() function non-static as it's public now. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + Make GstAudioSrcSlaveMethod get_type() function non-static + as it's public now. + * win32/common/libgstaudio.def: + * win32/common/libgstnetbuffer.def: + Add some missing functions to the list of exported symbols. + +2008-12-18 12:37:33 +0000 Andrew Feren <acferen@yahoo.com> + + gst-libs/gst/netbuffer/gstnetbuffer.*: Make gst_netaddress_get_ip4_address fail for v6 addresses. + Original commit message from CVS: + Patch by: Andrew Feren <acferen at yahoo dot com> + * gst-libs/gst/netbuffer/gstnetbuffer.c: + (gst_netaddress_get_ip4_address), (gst_netaddress_get_ip6_address), + (gst_netaddress_get_address_bytes), + (gst_netaddress_set_address_bytes): + * gst-libs/gst/netbuffer/gstnetbuffer.h: + Make gst_netaddress_get_ip4_address fail for v6 addresses. + Make gst_netaddress_get_ip6_address either fail or return the v4 + address as a transitional v6 address. + Add two convenience functions: + API: gst_netaddress_get_address_bytes() + API: gst_netaddress_set_address_bytes() + Fixes #564896. + +2008-12-17 13:51:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add appsrc and appsink documentation. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init): + Add appsrc and appsink documentation. + +2008-12-17 08:51:34 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/: Cleanup variable names to make the adder-loop easier to understand. + Original commit message from CVS: + * gst/adder/Makefile.am: + * gst/adder/gstadder.c: + Cleanup variable names to make the adder-loop easier to understand. + Also try to use liboil to spee it up, but ifdef it out as it does not + make any change for me (Intel pentim M (sse,sse2) please try on other + systems). + +2008-12-16 20:16:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add minimal docs to make the remaining tcp elements show up. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversrc.c: + Add minimal docs to make the remaining tcp elements show up. + Fixes #564139. + +2008-12-15 12:02:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/: Fix example to unref after emiting the push-buffer action. + Original commit message from CVS: + * examples/app/appsrc-ra.c: (feed_data): + * examples/app/appsrc-seekable.c: (feed_data): + * examples/app/appsrc-stream.c: (read_data): + * examples/app/appsrc-stream2.c: (feed_data): + Fix example to unref after emiting the push-buffer action. + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_push_buffer_full), (gst_app_src_push_buffer), + (gst_app_src_push_buffer_action): + Don't take the ref on the buffer in push-buffer action because it's too + awkward for bindings. Fixes #564482. + +2008-12-13 19:32:13 +0000 Tim-Philipp Müller <tim@centricular.net> + + win32/common/config.h: Update to CVS version. + Original commit message from CVS: + * win32/common/config.h: + Update to CVS version. + * win32/common/config.h.in: + Hardcode path to plugin install helper exe, just like we hardcode + the paths in core. Removes another source of VCS conflicts for + people hacking gst-plugins-base on systems with autotools. + +2008-12-13 16:21:12 +0000 Edward Hervey <bilboed@bilboed.com> + + m4/Makefile.am: And a couple more .m4 that don't exist anymore with gettext 0.17 + Original commit message from CVS: + * m4/Makefile.am: + And a couple more .m4 that don't exist anymore with gettext 0.17 + +2008-12-13 12:41:56 +0000 Edward Hervey <bilboed@bilboed.com> + + m4/Makefile.am: inttypes.m4 hasn't been available since gettext-0.15, and since we now require gettext >= 0.17 ... we... + Original commit message from CVS: + * m4/Makefile.am: + inttypes.m4 hasn't been available since gettext-0.15, and since we now + require gettext >= 0.17 ... we can remove it from the list of files to + dist. + +2008-12-13 06:57:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/: API: Add GST_TYPE_BASE_AUDIO_(SRC|SINK)_SLAVE_METHOD to the public API. This is needed for the C... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_slave_method_get_type), + (gst_base_audio_sink_class_init): + * gst-libs/gst/audio/gstbaseaudiosink.h: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_slave_method_get_type), + (gst_base_audio_src_class_init): + * gst-libs/gst/audio/gstbaseaudiosrc.h: + API: Add GST_TYPE_BASE_AUDIO_(SRC|SINK)_SLAVE_METHOD to the + public API. This is needed for the C++ bindings to be able + to use this base classes. Fixes bug #564200, #564206. + +2008-12-12 19:41:28 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/cdda/gstcddabasesrc.c: Remove erroneous gst_buffer_ref(). + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_handle_event): + Remove erroneous gst_buffer_ref(). + * tests/check/libs/rtp.c: (GST_START_TEST): + Don't forget to unref the buffer once you're done with it. + +2008-12-12 13:06:48 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/: XRef to GstXOverlay. + Original commit message from CVS: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + XRef to GstXOverlay. + +2008-12-12 10:54:45 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gsturidecodebin.c: Free the factory array when finalizing. + Original commit message from CVS: + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_finalize): + Free the factory array when finalizing. + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_base_init): + Use a GstStaticPadTemplate since the src pad caps are fixed. + +2008-12-12 07:17:21 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisenc.c: Make vorbisenc's pad template behave like vorbisdec's. Fixes a leak with pad templates. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_base_init), + (gst_vorbis_enc_init): + Make vorbisenc's pad template behave like vorbisdec's. Fixes a leak with + pad templates. + +2008-12-12 07:15:22 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Add mapping for VP6 in avi/riff. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add mapping for VP6 in avi/riff. + +2008-12-11 15:49:12 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/subparse/samiparse.c: Some versions of libxml seem to be very picky as to strict formatting of the input and neve... + Original commit message from CVS: + * gst/subparse/samiparse.c: (sami_context_push_state), + (sami_context_pop_state), (start_sami_element), (end_sami_element): + Some versions of libxml seem to be very picky as to strict formatting + of the input and never 'close' the final </body> tag. + In order to fix that bad behaviour, we trigger the flushing of + remaining data on both </body> and </sami>. + Fixes #557365 + +2008-12-11 12:32:03 +0000 Guillaume Emont <guillaume@fluendo.com> + + gst/typefind/gsttypefindfunctions.c: Add typefinders for MS Word files and OS X .DS_Store files to prevent them to be... + Original commit message from CVS: + Patch by: Guillaume Emont <guillaume at fluendo dot com> + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add typefinders for MS Word files and OS X .DS_Store files to + prevent them to be recognized as MPEG files. Fixes bug #564098. + +2008-12-11 11:04:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Add some more debug info. + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gen_audio_chain), + (gst_play_sink_reconfigure): + Add some more debug info. + Fix linking of just an encoded sink. + Handle failure to create a sink chain more gracefully than crashing. + +2008-12-11 10:33:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/pipelines/theoraenc.c: Pushing 10 buffers is enough to run the test. + Original commit message from CVS: + * tests/check/pipelines/theoraenc.c: (GST_START_TEST): + Pushing 10 buffers is enough to run the test. + +2008-12-11 10:28:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Hook up the SKIP seek flag. + Original commit message from CVS: + * tests/examples/seek/seek.c: (do_seek), (stop_cb), + (skip_toggle_cb), (rate_spinbutton_changed_cb), (msg_segment_done), + (main): + Hook up the SKIP seek flag. + +2008-12-10 18:43:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Error out with a missing-plugin error when the input-selector was not found. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (pad_added_cb): + Error out with a missing-plugin error when the input-selector was not + found. + * gst/playback/gstplaysink.c: (gst_play_sink_reconfigure): + Indentation. + +2008-12-10 17:39:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Use G_DEFINE_TYPE. + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gst_play_sink_dispose), (gst_play_sink_finalize), (try_element), + (gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure), + (gst_play_sink_send_event), (gst_play_sink_change_state): + Use G_DEFINE_TYPE. + Try to set the selected sink to READY before using it. This will allow + for detection of incompatible formats sooner. + Don't cause a fatal error when conversion elements are missing but post + a missing-element message and a warning instead because things might + still link and run fine. + Simplyfy the construction of audio and video sink chains. + +2008-12-10 14:55:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Use G_DEFINE_TYPE for the OggPad to get some threadsafe type init from glib. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_class_init), + (gst_ogg_pad_dispose), (gst_ogg_pad_finalize): + Use G_DEFINE_TYPE for the OggPad to get some threadsafe type + init from glib. + +2008-12-10 08:19:13 +0000 Luis Menina <liberforce@freeside.fr> + + gst/: Include glib.h instead of a specific GLib header. Including single + Original commit message from CVS: + Patch by: Luis Menina <liberforce at freeside dot fr> + * gst-libs/gst/floatcast/floatcast.h: + * gst/typefind/gsttypefindfunctions.c: + Include glib.h instead of a specific GLib header. Including single + GLib headers is deprecated. Fixes bug #563904. + +2008-12-09 18:30:10 +0000 Julien Moutte <julien@moutte.net> + + gst-libs/gst/riff/riff-media.c: Support higher max audio rates for some formats (WAV, Vorbis, LPCM). + Original commit message from CVS: + 2008-12-09 Julien Moutte <julien@fluendo.com> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Support higher max audio rates for some formats (WAV, Vorbis, LPCM). + +2008-12-09 17:21:37 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-read.c: Fix handling of odd chunks in riff metadata. + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: + Fix handling of odd chunks in riff metadata. + +2008-12-08 18:44:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/volume/gstvolume.c: Use new basetransform vmethod to reconfigure the dynamic properties and any pending volume/mu... + Original commit message from CVS: + * gst/volume/gstvolume.c: (gst_volume_class_init), + (volume_before_transform), (volume_transform_ip): + Use new basetransform vmethod to reconfigure the dynamic properties and + any pending volume/mute changes. Fixes #563508. + +2008-12-08 18:12:18 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: First check for "theoraenc theoradec" and if that failed check for "theora >= 1.0alpha5". The former ap... + Original commit message from CVS: + * configure.ac: + First check for "theoraenc theoradec" and if that failed check + for "theora >= 1.0alpha5". The former appeared in 1.0beta3 and + deprecate the latter. Also linking on Windows fails with just "theora" + and the version check would fail for the release candidates. + Fixes bug #563718. + +2008-12-08 15:25:13 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/: Add basic docs to decodebin and link to decodebin from decodebin2. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + Add basic docs to decodebin and link to decodebin from decodebin2. + +2008-12-08 12:08:32 +0000 Olivier Crete <tester@tester.ca> + + gst-libs/gst/rtp/gstrtcpbuffer.*: Implement gst_rtcp_packet_remove(). Fixes #563174. + Original commit message from CVS: + Patch by: Olivier Crete <tester at tester ca> + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_packet_remove): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Implement gst_rtcp_packet_remove(). Fixes #563174. + * tests/check/libs/rtp.c: (GST_START_TEST), (rtp_suite): + Add unit test for some RTCP functions. + +2008-12-04 20:09:19 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Apparently AC_CONFIG_MACRO_DIR breaks when using more than one macro directory, reverting last change. + Original commit message from CVS: + * configure.ac: + Apparently AC_CONFIG_MACRO_DIR breaks when using more + than one macro directory, reverting last change. + +2008-12-04 19:47:12 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Set AC_CONFIG_MACRO_DIR to common/m4 to point autoconf to our M4 macros. + Original commit message from CVS: + * configure.ac: + Set AC_CONFIG_MACRO_DIR to common/m4 to point autoconf to + our M4 macros. + +2008-12-03 17:47:44 +0000 Edward Hervey <bilboed@bilboed.com> + + sys/: Clear all flags on buffers returned from the image pool. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_buffer_alloc): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_buffer_alloc): + Clear all flags on buffers returned from the image pool. + Fixes #563143 + +2008-12-01 19:36:35 +0000 이문형 <iwings@gmail.com> + + gst-libs/gst/app/gstappsrc.c: Don't forget to release the lock again if we bail out because some pad is flushing or w... + Original commit message from CVS: + Patch by: 이문형 <iwings at gmail dot com> + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_push_buffer): + Don't forget to release the lock again if we bail out because some + pad is flushing or we've reached EOS, otherwise things will lock up + next time _push_buffer() is called (#562802). + +2008-11-29 13:31:47 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Require gettext 0.17 because older versions don't mix with libtool 2.2. At build time an older gettext version will s... + Original commit message from CVS: + Patch by: Cygwin Ports maintainer + <yselkowitz at users dot sourceforge dot net> + * autogen.sh: + * configure.ac: + Require gettext 0.17 because older versions don't mix with libtool + 2.2. At build time an older gettext version will still work. + Fixes bug #556091. + +2008-11-28 13:30:36 +0000 Christian Schaller <uraeus@gnome.org> + + * ChangeLog: + * gst/speexresample/Makefile.am: + fix build + Original commit message from CVS: + fix build + +2008-11-28 09:44:12 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Update documentation of speexresample for the new element name. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-videorate.xml: + * gst/speexresample/gstspeexresample.c: + Update documentation of speexresample for the new element name. + +2008-11-28 09:04:46 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/README: Update README with the latest diff between the Speex resampler and our copy. + Original commit message from CVS: + * gst/speexresample/README: + Update README with the latest diff between the Speex resampler + and our copy. + +2008-11-28 08:37:50 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Update the debug category from speex_resample to audioresample. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: (plugin_init): + Update the debug category from speex_resample to audioresample. + +2008-11-27 19:13:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Remove audioresample files. + Original commit message from CVS: + * gst/audioresample/Makefile.am: + * gst/audioresample/buffer.c: + * gst/audioresample/buffer.h: + * gst/audioresample/debug.c: + * gst/audioresample/debug.h: + * gst/audioresample/functable.c: + * gst/audioresample/functable.h: + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/gstaudioresample.h: + * gst/audioresample/resample.c: + * gst/audioresample/resample.h: + * gst/audioresample/resample_chunk.c: + * gst/audioresample/resample_functable.c: + * gst/audioresample/resample_ref.c: + * tests/check/elements/audioresample.c: + Remove audioresample files. + +2008-11-27 17:04:07 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + docs/plugins/inspect/plugin-audioresample.xml: Regenerated for library filename change. + Original commit message from CVS: + * docs/plugins/inspect/plugin-audioresample.xml: + Regenerated for library filename change. + +2008-11-27 16:57:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Rename the moved speexresample to audioresample, integrate into the build system and remove the old audioresample fro... + Original commit message from CVS: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst/speexresample/gstspeexresample.c: (plugin_init): + * gst/speexresample/Makefile.am: + * tests/check/Makefile.am: + * tests/check/elements/speexresample.c: (setup_speexresample), + (GST_START_TEST), (test_pipeline): + Rename the moved speexresample to audioresample, integrate into the + build system and remove the old audioresample from the build system. + Fixes bug #558124, #385061, #346218, #116051. + +2008-11-27 16:47:41 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Avoid nasty int overflows after about 12 hours and 25 minutes when these code p... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_get_offset), (gst_base_audio_src_create): + Avoid nasty int overflows after about 12 hours and 25 minutes when these + code paths are triggered. + A free beer to Håvard Graff for finding this! + +2008-11-27 11:16:44 +0000 이문형 <iwings@gmail.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: A successful gst_poll_wait() doesn't always mean successful connect() on + Original commit message from CVS: + Patch by: 이문형 <iwings at gmail dot com> + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect): + A successful gst_poll_wait() doesn't always mean successful connect() on + Windows. We should check errors by calling gst_poll_fd_has_error(). + See #561924. + +2008-11-25 16:37:50 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/elements/speexresample.c: Make unit test again faster to prevent timeouts with valgrind. + Original commit message from CVS: + * tests/check/elements/speexresample.c: (test_pipeline): + Make unit test again faster to prevent timeouts with valgrind. + +2008-11-25 15:33:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.c: Fix typo in the docs. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + Fix typo in the docs. + +2008-11-25 15:28:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: If no stream was found before receiving EOS, post an error message. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_sink_event): + If no stream was found before receiving EOS, post an error message. + Fixes #561924. + +2008-11-25 15:14:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/: Parse segment events. + Original commit message from CVS: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: (gst_theora_enc_init), + (theora_buffer_from_packet), (theora_push_packet), + (theora_enc_sink_event), (theora_enc_is_discontinuous), + (theora_enc_chain): + Parse segment events. + Pass incomming buffer timestamps to outgoing buffers. + Use the running_time to construct the granulepos. + Fixes #562163. + +2008-11-25 11:00:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Fix buffer-duration property. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (activate_group): + Fix buffer-duration property. + +2008-11-25 10:32:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Really fix audiosink drain handling by keeping track of the running_time of th... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain), (gst_base_audio_sink_event), + (gst_base_audio_sink_sync_latency), (gst_base_audio_sink_render), + (gst_base_audio_sink_change_state): + Really fix audiosink drain handling by keeping track of the running_time + of the last sample. + +2008-11-24 20:25:24 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstplaybin2.c: Add notification of current stream. Add ability to configure buffer sizes. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: + Add notification of current stream. Add ability to configure buffer + sizes. + * gst/playback/gsturidecodebin.c: + Add ability to configure buffer sizes for streaming mode. + Bug #561734. + +2008-11-24 20:11:52 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/gstbaseaudiosink.c: Time is already in running_time. Remove base_time handling. Fixes audiosinks n... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + Time is already in running_time. Remove base_time handling. Fixes + audiosinks not draining and thus chopping some audio in the end. + +2008-11-24 19:18:59 +0000 David Schleef <ds@schleef.org> + + ext/ogg/gstoggmux.*: If we're muxing a dirac stream, flush the page after every picture. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + If we're muxing a dirac stream, flush the page after every picture. + +2008-11-24 12:56:54 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/gstbaseaudiosink.c: Add one log message to check for audio_drained. Sync one log message with the ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + Add one log message to check for audio_drained. Sync one log message + with the condition. Send EOS after draining audio in pull mode. + +2008-11-24 12:07:10 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/: Use gst_buffer_try_new_and_alloc() and fail properly if the allocation failed. This prevents abort() if downstr... + Original commit message from CVS: + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_create): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_create): + Use gst_buffer_try_new_and_alloc() and fail properly if the + allocation failed. This prevents abort() if downstream elements + request an insane amount of memory. + +2008-11-24 12:03:11 +0000 Jon Trowbridge <trow@ximian.com> + + gst/volume/gstvolume.*: Cleanup volume, define and use default values. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_update_volume), (gst_volume_set_volume), + (gst_volume_get_volume), (gst_volume_set_mute), + (gst_volume_class_init), (gst_volume_init), + (volume_process_double), (volume_process_float), + (volume_process_int32), (volume_process_int32_clamp), + (volume_process_int24), (volume_process_int24_clamp), + (volume_process_int16), (volume_process_int16_clamp), + (volume_process_int8), (volume_process_int8_clamp), (volume_setup), + (volume_transform_ip), (volume_set_property), + (volume_get_property): + * gst/volume/gstvolume.h: + Cleanup volume, define and use default values. + Recalculate new volume and mute setup before processing. Fixes #561789. + * tests/check/elements/volume.c: (GST_START_TEST), (volume_suite): + Add controller unit test. Patch by: Jonathan Matthew + Fix bogus test that messed with basetransform's internal state. + +2008-11-22 15:02:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/elements/speexresample.c: Make the unit test a bit faster to prevent timeouts, especially with valgrind. + Original commit message from CVS: + * tests/check/elements/speexresample.c: (GST_START_TEST): + Make the unit test a bit faster to prevent timeouts, especially + with valgrind. + +2008-11-22 14:44:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videorate/gstvideorate.c: Add jpeg and png image media types to the caps. Fixes #561436. + Original commit message from CVS: + * gst/videorate/gstvideorate.c: + Add jpeg and png image media types to the caps. Fixes #561436. + +2008-11-22 14:31:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Don't post an error when we can't configure the volume but post a warning instead. Fixes ... + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gen_audio_chain): + Don't post an error when we can't configure the volume but post a + warning instead. Fixes #561780. + +2008-11-21 20:32:56 +0000 Jonathan Rosser <jonathan.rosser@rd.bbc.co.uk> + + gst/videotestsrc/: Add a zone plate pattern generator based on BBC R&D Report 1978/23 (yeah *that* 1978). Try 'video... + Original commit message from CVS: + Patch by: Jonathan Rosser <jonathan.rosser@rd.bbc.co.uk> + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + Add a zone plate pattern generator based on BBC R&D Report + 1978/23 (yeah *that* 1978). Try 'videotestsrc pattern=zone-plate + kx2=20 ky2=20 kt=1'. + +2008-11-21 15:45:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Add a "filter-length" property that maps to the quality values for compatibilty... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_class_init), (gst_speex_resample_set_property), + (gst_speex_resample_get_property): + Add a "filter-length" property that maps to the quality values + for compatibilty with audioresample. + +2008-11-21 00:04:48 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstdecodebin2.c: Fix random fat-fingering making this not compile. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + Fix random fat-fingering making this not compile. + +2008-11-20 22:11:38 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstdecodebin2.c: If the top-level type of the stream is plain text, don't try to decode it, matching beh... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + If the top-level type of the stream is plain text, don't try to decode + it, matching behaviour of decodebin. + * gst/playback/gstplaysink.c: + If we fail to generate a text chain (e.g. due to missing optional + plugins), don't crash. + +2008-11-20 22:06:05 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/rtsp/gstrtspdefs.c: Fix win32 build. Oops. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspdefs.c: + Fix win32 build. Oops. + +2008-11-20 21:40:49 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/rtsp/gstrtspdefs.c: Use WSAGetLastError() rather than errno/h_errno on win32. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspdefs.c: + Use WSAGetLastError() rather than errno/h_errno on win32. + +2008-11-20 21:20:27 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/riff/riff-media.c: Support WMA Lossless properly. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: + Support WMA Lossless properly. + +2008-11-19 00:24:44 +0000 David Schleef <ds@schleef.org> + + gst/videotestsrc/: Add "colorspec" property, specifying whether to generate BT.601 or BT.709 video. This only affect... + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + Add "colorspec" property, specifying whether to generate BT.601 + or BT.709 video. This only affects YCbCr values, not RGB, since + if you're generating a 709 test pattern, presumably you want + 709 RGB primaries, not 601. Also add "smpte75" pattern, which + uses 75% colors instead of 100%, since this is often more useful + for testing (and also follows the SMPTE EG-1 guideline). + +2008-11-18 18:08:42 +0000 Alessandro Decina <alessandro.d@gmail.com> + + gst/playback/gstdecodebin.c: Add a "sink-caps" property to decodebin like it's done for decodebin2. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: + Add a "sink-caps" property to decodebin like it's done for decodebin2. + Fixes #560380. + +2008-11-14 21:44:33 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/audioresample/gstaudioresample.c: Guard against a NULL dereference I somehow encountered - with a FLUSH_STOP arri... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + Guard against a NULL dereference I somehow encountered - + with a FLUSH_STOP arriving either before basetransform _start(), + or after _stop(). + * gst/typefind/gsttypefindfunctions.c: + Make sure we never jump backwards when typefinding corrupt mov files. + +2008-11-14 21:39:09 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/propertyprobe.c: Fix random type causing a docs warning. + Original commit message from CVS: + * gst-libs/gst/interfaces/propertyprobe.c: + Fix random type causing a docs warning. + +2008-11-14 15:40:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/v4l/gstv4l.c: Give it a minimal rank for autovideosrc. + Original commit message from CVS: + * sys/v4l/gstv4l.c: + Give it a minimal rank for autovideosrc. + +2008-11-13 21:11:13 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + gst/typefind/gsttypefindfunctions.c: Improve typefinding of ISO JPEG2000 mime types. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (jp2_type_find), + (plugin_init): + Improve typefinding of ISO JPEG2000 mime types. + +2008-11-13 18:18:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/xvimage/xvimagesink.*: Avoid typechecking when we do trivial casts. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_finalize), + (gst_xvimagesink_xvimage_put), (gst_xvimagesink_setcaps), + (gst_xvimagesink_show_frame), (gst_xvimagesink_buffer_alloc): + * sys/xvimage/xvimagesink.h: + Avoid typechecking when we do trivial casts. + Move error handling out of the main program flow. + Sneak in the display-region caps property, not completely correct yet. + Cache the width/height in buffer_alloc instead of parsing it from the + caps all the time. + +2008-11-13 17:27:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: don't try to unlink the selector sinkpad when we don't have it yet. This can happen if an... + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (deactivate_group): + don't try to unlink the selector sinkpad when we don't have it yet. This + can happen if an error occured before the group was complete. + +2008-11-13 15:37:40 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.c: Avoid expensive type checks we already did as part of the _validate() function that ... + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_validate_data), + (gst_rtp_buffer_set_packet_len), (gst_rtp_buffer_get_packet_len), + (gst_rtp_buffer_get_header_len), (gst_rtp_buffer_get_version), + (gst_rtp_buffer_set_version), (gst_rtp_buffer_get_padding), + (gst_rtp_buffer_set_padding), (gst_rtp_buffer_pad_to), + (gst_rtp_buffer_get_extension), (gst_rtp_buffer_set_extension), + (gst_rtp_buffer_get_extension_data), + (gst_rtp_buffer_set_extension_data), (gst_rtp_buffer_get_ssrc), + (gst_rtp_buffer_set_ssrc), (gst_rtp_buffer_get_csrc_count), + (gst_rtp_buffer_get_csrc), (gst_rtp_buffer_set_csrc), + (gst_rtp_buffer_get_marker), (gst_rtp_buffer_set_marker), + (gst_rtp_buffer_get_payload_type), + (gst_rtp_buffer_set_payload_type), (gst_rtp_buffer_get_seq), + (gst_rtp_buffer_set_seq), (gst_rtp_buffer_get_timestamp), + (gst_rtp_buffer_set_timestamp), + (gst_rtp_buffer_get_payload_subbuffer), + (gst_rtp_buffer_get_payload_len), (gst_rtp_buffer_get_payload): + Avoid expensive type checks we already did as part of the + _validate() function that should be called first. + +2008-11-11 16:40:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Fix some cases where a newsegment event was not sent. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: (create_segment_event), + (gst_base_rtp_depayload_push_full), + (gst_base_rtp_depayload_set_gst_timestamp): + Fix some cases where a newsegment event was not sent. + +2008-11-11 15:52:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Catch state change errors and stop from the uridecodebin elements instead of trying to co... + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (activate_group): + Catch state change errors and stop from the uridecodebin elements + instead of trying to continue in vain. + +2008-11-10 14:53:45 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/: Wim, you're a bad boy. You don't want people to contact you or what? + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsrc.c: + * gst/h264parse/gsth264parse.c: + Wim, you're a bad boy. You don't want people to contact you or what? + +2008-11-10 14:22:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Use gst_base_sink_do_preroll() to wait for PLAYING and before waiting for the ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_sync_latency), (gst_base_audio_sink_render), + (gst_base_audio_sink_callback): + Use gst_base_sink_do_preroll() to wait for PLAYING and before waiting + for the latency to expire, fixes #559567. + +2008-11-10 13:55:08 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/adder/gstadder.c: Change author string after seeing output of gst-inspector. + Original commit message from CVS: + * gst/adder/gstadder.c: + Change author string after seeing output of gst-inspector. + +2008-11-10 10:33:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Don't try to do crazy things when we only have a text pad without a video pad. Fixes #559... + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gst_play_sink_reconfigure): + Don't try to do crazy things when we only have a text pad without a + video pad. Fixes #559478. + +2008-11-07 17:35:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsrc.*: Add is-live property. + Original commit message from CVS: + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_init), (gst_app_src_set_property), + (gst_app_src_get_property), (gst_app_src_push_buffer): + * gst-libs/gst/app/gstappsrc.h: + Add is-live property. + Add some more docs. + +2008-11-06 12:14:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: Fix case where we don't have a range for the rates or channels as is the case with tr... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Fix case where we don't have a range for the rates or channels as is the + case with truespeech. + +2008-11-05 19:18:25 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/volume/gstvolume.*: Keep negotiated state in a separate variable. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_update_real_volume), + (gst_volume_set_volume), (gst_volume_get_volume), + (gst_volume_set_mute), (gst_volume_init), (volume_setup), + (volume_transform_ip), (volume_update_mute), + (volume_update_volume), (volume_get_property): + * gst/volume/gstvolume.h: + Keep negotiated state in a separate variable. + Protect the volume and mute properties with the object lock. + Protect modifying the transform with the transform lock. + +2008-11-05 12:20:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Only convert caps to string when debug is enabled. + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps): + Only convert caps to string when debug is enabled. + +2008-11-04 18:17:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/: Copy seqnum. + Original commit message from CVS: + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_init), + (gst_theora_dec_reset), (theora_dec_src_event), + (theora_dec_sink_event), (theora_handle_type_packet): + Copy seqnum. + Keep events in a pending list, like vorbisdec, instead of trying + to construct a segment event ourselves. + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_reset), + (vorbis_dec_src_event), (vorbis_dec_sink_event): + * ext/vorbis/vorbisdec.h: + Copy seqnum. + +2008-11-04 17:24:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.*: Copy seqnums around to track playback segments and messages. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_handle_page), + (gst_ogg_demux_loop): + * ext/ogg/gstoggdemux.h: + Copy seqnums around to track playback segments and messages. + +2008-11-04 12:42:18 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Don't install static libs for plugins. Fixes #550851 for -bad. + Original commit message from CVS: + * ext/alsaspdif/Makefile.am: + * ext/amrwb/Makefile.am: + * ext/apexsink/Makefile.am: + * ext/arts/Makefile.am: + * ext/artsd/Makefile.am: + * ext/audiofile/Makefile.am: + * ext/audioresample/Makefile.am: + * ext/bz2/Makefile.am: + * ext/cdaudio/Makefile.am: + * ext/celt/Makefile.am: + * ext/dc1394/Makefile.am: + * ext/dirac/Makefile.am: + * ext/directfb/Makefile.am: + * ext/divx/Makefile.am: + * ext/dts/Makefile.am: + * ext/faac/Makefile.am: + * ext/faad/Makefile.am: + * ext/gsm/Makefile.am: + * ext/hermes/Makefile.am: + * ext/ivorbis/Makefile.am: + * ext/jack/Makefile.am: + * ext/jp2k/Makefile.am: + * ext/ladspa/Makefile.am: + * ext/lcs/Makefile.am: + * ext/libfame/Makefile.am: + * ext/libmms/Makefile.am: + * ext/metadata/Makefile.am: + * ext/mpeg2enc/Makefile.am: + * ext/mplex/Makefile.am: + * ext/musepack/Makefile.am: + * ext/musicbrainz/Makefile.am: + * ext/mythtv/Makefile.am: + * ext/nas/Makefile.am: + * ext/neon/Makefile.am: + * ext/ofa/Makefile.am: + * ext/polyp/Makefile.am: + * ext/resindvd/Makefile.am: + * ext/sdl/Makefile.am: + * ext/shout/Makefile.am: + * ext/snapshot/Makefile.am: + * ext/sndfile/Makefile.am: + * ext/soundtouch/Makefile.am: + * ext/spc/Makefile.am: + * ext/swfdec/Makefile.am: + * ext/tarkin/Makefile.am: + * ext/theora/Makefile.am: + * ext/timidity/Makefile.am: + * ext/twolame/Makefile.am: + * ext/x264/Makefile.am: + * ext/xine/Makefile.am: + * ext/xvid/Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/dshow/Makefile.am: + * gst/aiffparse/Makefile.am: + * gst/app/Makefile.am: + * gst/audiobuffer/Makefile.am: + * gst/bayer/Makefile.am: + * gst/cdxaparse/Makefile.am: + * gst/chart/Makefile.am: + * gst/colorspace/Makefile.am: + * gst/dccp/Makefile.am: + * gst/deinterlace/Makefile.am: + * gst/deinterlace2/Makefile.am: + * gst/dvdspu/Makefile.am: + * gst/festival/Makefile.am: + * gst/filter/Makefile.am: + * gst/flacparse/Makefile.am: + * gst/flv/Makefile.am: + * gst/games/Makefile.am: + * gst/h264parse/Makefile.am: + * gst/librfb/Makefile.am: + * gst/mixmatrix/Makefile.am: + * gst/modplug/Makefile.am: + * gst/mpeg1sys/Makefile.am: + * gst/mpeg4videoparse/Makefile.am: + * gst/mpegdemux/Makefile.am: + * gst/mpegtsmux/Makefile.am: + * gst/mpegvideoparse/Makefile.am: + * gst/mve/Makefile.am: + * gst/nsf/Makefile.am: + * gst/nuvdemux/Makefile.am: + * gst/overlay/Makefile.am: + * gst/passthrough/Makefile.am: + * gst/pcapparse/Makefile.am: + * gst/playondemand/Makefile.am: + * gst/rawparse/Makefile.am: + * gst/real/Makefile.am: + * gst/rtjpeg/Makefile.am: + * gst/rtpmanager/Makefile.am: + * gst/scaletempo/Makefile.am: + * gst/sdp/Makefile.am: + * gst/selector/Makefile.am: + * gst/smooth/Makefile.am: + * gst/smoothwave/Makefile.am: + * gst/speed/Makefile.am: + * gst/speexresample/Makefile.am: + * gst/stereo/Makefile.am: + * gst/subenc/Makefile.am: + * gst/tta/Makefile.am: + * gst/vbidec/Makefile.am: + * gst/videodrop/Makefile.am: + * gst/videosignal/Makefile.am: + * gst/virtualdub/Makefile.am: + * gst/vmnc/Makefile.am: + * gst/y4m/Makefile.am: + * sys/acmenc/Makefile.am: + * sys/cdrom/Makefile.am: + * sys/dshowdecwrapper/Makefile.am: + * sys/dshowsrcwrapper/Makefile.am: + * sys/dvb/Makefile.am: + * sys/dxr3/Makefile.am: + * sys/fbdev/Makefile.am: + * sys/oss4/Makefile.am: + * sys/qcam/Makefile.am: + * sys/qtwrapper/Makefile.am: + * sys/vcd/Makefile.am: + * sys/wininet/Makefile.am: + * win32/common/config.h: + Don't install static libs for plugins. Fixes #550851 for -bad. + +2008-11-03 15:30:14 +0000 Matthias Kretz <kretz@kde.org> + + ext/alsa/gstalsasink.c: Make all access non-blocking so that we can better handle unplugging of usb devices. Fixes #5... + Original commit message from CVS: + Based on patch by: Matthias Kretz <kretz at kde dot org> + * ext/alsa/gstalsasink.c: (gst_alsasink_open), + (gst_alsasink_prepare), (gst_alsasink_unprepare), + (gst_alsasink_write): + Make all access non-blocking so that we can better handle unplugging + of usb devices. Fixes #559111 + +2008-11-03 10:49:24 +0000 Damien Lespiau <damien.lespiau@gmail.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Make the next call to poll not depend on previous calls to poll with or withou... + Original commit message from CVS: + Patch by: Damien Lespiau <damien.lespiau gmail com> + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_write): + Make the next call to poll not depend on previous calls to poll with or + without reading from the active descriptor. Fixes #544293. + +2008-11-03 08:55:49 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Add TODO at the top of the file for enabling SSE/ARM specific optimizations and... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_convert_buffer): + Add TODO at the top of the file for enabling SSE/ARM specific + optimizations and choosing the fastest implementation at runtime. + Add g_assert_not_reached() at two places that should really never + be reached. + +2008-11-02 09:19:24 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Fix format string and arguments. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_check_discont): + Fix format string and arguments. + * gst/speexresample/resample_sse.h: + Add missing file. + +2008-11-01 19:38:36 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/: Add missing headers to Makefile.am. + Original commit message from CVS: + * gst/speexresample/Makefile.am: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_base_init), (gst_speex_resample_get_funcs), + (gst_speex_resample_convert_buffer), (_benchmark_int_float), + (_benchmark_int_int), (_benchmark_integer_resampling), + (plugin_init): + * gst/speexresample/gstspeexresample.h: + * gst/speexresample/resample.c: + * gst/speexresample/speex_resampler_double.c: + * gst/speexresample/speex_resampler_float.c: + * gst/speexresample/speex_resampler_int.c: + * gst/speexresample/speex_resampler_wrapper.h: + Add missing headers to Makefile.am. + Update copyright, years and my mail address. + Benchmark the integer resampling implementation against the + float implementation and use the faster one for 8/16 bit integer + input. On most recent systems the floating point version is faster. + +2008-10-31 09:49:57 +0000 Nick Haddad <nick@haddads.net> + + gst-libs/gst/riff/: Add support for other fourcc codes that are commonly used for 'uncompressed RGB', including 'RGB ... + Original commit message from CVS: + Patch by: Nick Haddad <nick at haddads dot net> + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add support for other fourcc codes that are commonly used for + 'uncompressed RGB', including 'RGB ', 'RAW ', and 0. + Fixes #558553. + +2008-10-30 14:55:43 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: The length for the buffer conversion function is the number of audio frames, i.... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_convert_buffer): + The length for the buffer conversion function is the number of + audio frames, i.e. we need to multiply it by the number of channels + to get the number of values. Also spotted by the unit test after + running in valgrind. + +2008-10-30 14:46:31 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/elements/speexresample.c: Add pipeline unit tests for testing all supported formats with up/downsampling ... + Original commit message from CVS: + * tests/check/elements/speexresample.c: (element_message_cb), + (eos_message_cb), (test_pipeline), (GST_START_TEST), + (speexresample_suite): + Add pipeline unit tests for testing all supported formats with + up/downsampling and different in/outrates. + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_push_drain), (gst_speex_resample_process): + * gst/speexresample/speex_resampler_wrapper.h: + Fix bugs identified by the testsuite. + +2008-10-30 13:44:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/: Add support for int8, int24 and int32 input by converting internally to/from int16 or double. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: (gst_speex_resample_stop), + (gst_speex_resample_get_funcs), + (gst_speex_resample_transform_size), + (gst_speex_resample_convert_buffer), + (gst_speex_resample_push_drain), (gst_speex_resample_process): + * gst/speexresample/gstspeexresample.h: + * gst/speexresample/speex_resampler_wrapper.h: + Add support for int8, int24 and int32 input by converting internally + to/from int16 or double. + +2008-10-30 12:43:44 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add support for double samples as input and refactor the usage of the different compilation flavors of the speex resa... + Original commit message from CVS: + * gst/speexresample/Makefile.am: + * gst/speexresample/arch.h: + * gst/speexresample/gstspeexresample.c: (gst_speex_resample_stop), + (gst_speex_resample_get_unit_size), (gst_speex_resample_get_funcs), + (gst_speex_resample_init_state), (gst_speex_resample_update_state), + (gst_speex_resample_reset_state), (gst_speex_resample_parse_caps), + (_gcd), (gst_speex_resample_transform_size), + (gst_speex_resample_set_caps), (gst_speex_resample_push_drain), + (gst_speex_resample_process), (gst_speex_resample_transform), + (gst_speex_resample_query), (gst_speex_resample_set_property): + * gst/speexresample/gstspeexresample.h: + * gst/speexresample/resample.c: + * gst/speexresample/speex_resampler.h: + * gst/speexresample/speex_resampler_double.c: + * gst/speexresample/speex_resampler_wrapper.h: + * tests/check/elements/speexresample.c: (setup_speexresample), + (test_perfect_stream_instance), (GST_START_TEST), + (test_discont_stream_instance): + Add support for double samples as input and refactor the usage + of the different compilation flavors of the speex resampler. + +2008-10-30 11:43:12 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioresample/gstaudioresample.c: Return the result of parent_class->event(). + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + Return the result of parent_class->event(). + +2008-10-29 17:02:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.c: Fix the docs. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_class_init): + Fix the docs. + +2008-10-29 12:11:20 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.*: Rewrite timestamp tracking to make it more robust and guarantee a continous str... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: (gst_speex_resample_start), + (gst_speex_resample_get_unit_size), + (gst_speex_resample_push_drain), (gst_speex_resample_event), + (gst_speex_resample_check_discont), (gst_speex_resample_process), + (gst_speex_resample_transform): + * gst/speexresample/gstspeexresample.h: + Rewrite timestamp tracking to make it more robust and guarantee + a continous stream. + * tests/check/Makefile.am: + * tests/check/elements/speexresample.c: (setup_speexresample), + (cleanup_speexresample), (fail_unless_perfect_stream), + (test_perfect_stream_instance), (GST_START_TEST), + (test_discont_stream_instance), (live_switch_alloc_only_48000), + (live_switch_get_sink_caps), (live_switch_push), + (speexresample_suite): + Add unit tests for speexresample based on the audioresample unit tests. + +2008-10-28 19:30:33 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.*: Some random cleanup, add G_LIKELY and friends, use GST_DEBUG_OBJECT instead of ... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_get_unit_size), + (gst_speex_resample_fixate_caps), (gst_speex_resample_init_state), + (gst_speex_resample_update_state), (gst_speex_resample_parse_caps), + (gst_speex_resample_transform_size), (gst_speex_resample_set_caps), + (gst_speex_resample_push_drain), (gst_speex_resample_event), + (gst_speex_resample_check_discont), (gst_speex_fix_output_buffer), + (gst_speex_resample_process), (gst_speex_resample_transform), + (gst_speex_resample_query), (gst_speex_resample_set_property): + * gst/speexresample/gstspeexresample.h: + Some random cleanup, add G_LIKELY and friends, use GST_DEBUG_OBJECT + instead of GST_DEBUG, ... + +2008-10-28 16:28:45 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Fixate to the nearest supported rate instead of the first one. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_class_init), (gst_speex_resample_fixate_caps), + (gst_speex_resample_process): + Fixate to the nearest supported rate instead of the first one. + +2008-10-28 16:25:00 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioresample/gstaudioresample.c: Fixate the rate to the nearest supported rate instead of the first one. Fixes b... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + (gst_audioresample_class_init), (audioresample_fixate_caps): + Fixate the rate to the nearest supported rate instead of + the first one. Fixes bug #549510. + +2008-10-28 11:46:28 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/: Update Speex resampler with latest version from Speex GIT. + Original commit message from CVS: + * gst/speexresample/README: + * gst/speexresample/arch.h: + * gst/speexresample/fixed_arm4.h: + * gst/speexresample/fixed_arm5e.h: + * gst/speexresample/fixed_bfin.h: + * gst/speexresample/fixed_debug.h: + * gst/speexresample/fixed_generic.h: + * gst/speexresample/resample.c: (compute_func), (main), (sinc), + (cubic_coef), (resampler_basic_direct_single), + (resampler_basic_direct_double), + (resampler_basic_interpolate_single), + (resampler_basic_interpolate_double), (update_filter), + (speex_resampler_init_frac), (speex_resampler_process_native), + (speex_resampler_magic), (speex_resampler_process_float), + (speex_resampler_process_int), + (speex_resampler_process_interleaved_float), + (speex_resampler_process_interleaved_int), + (speex_resampler_set_rate_frac), (speex_resampler_skip_zeros), + (speex_resampler_reset_mem): + * gst/speexresample/speex_resampler.h: + Update Speex resampler with latest version from Speex GIT. + +2008-10-27 14:57:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + win32/common/libgstaudio.def: Add new symbols. + Original commit message from CVS: + * win32/common/libgstaudio.def: + Add new symbols. + +2008-10-23 09:57:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Attempt to make obfuscated code clearer. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_identification_packet): + Attempt to make obfuscated code clearer. + +2008-10-23 07:11:23 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Move float endianness conversion macros to core. Second part of bug ##555196. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/floatcast/floatcast.h: + Move float endianness conversion macros to core. Second part of + bug ##555196. + +2008-10-22 12:29:30 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/: Don't mark as gtk-doc docs as they aren't public. + Original commit message from CVS: + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.h: + Don't mark as gtk-doc docs as they aren't public. + +2008-10-22 12:25:02 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Allow setting colorkey if possible. Implement property probe interface for optional X features (autopaint-colorkey, d... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + * tests/icles/Makefile.am: + * tests/icles/test-colorkey.c: + Allow setting colorkey if possible. Implement property probe interface + for optional X features (autopaint-colorkey, double-buffer and + colorkey). Fixes #554533 + +2008-10-22 12:01:32 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/tag/tags.c: Remove useless buffer size assignment. It already has this value. + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (gst_tag_image_data_to_image_buffer): + Remove useless buffer size assignment. It already has this value. + +2008-10-20 15:35:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Implement a separate activate functions to start monitoring the segments or, in pu... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: + (gst_audioringbuffer_class_init), (gst_audioringbuffer_acquire), + (gst_audioringbuffer_activate), (gst_audioringbuffer_release), + (gst_audioringbuffer_stop): + Implement a separate activate functions to start monitoring the segments + or, in pull mode, pulling in data. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_init), (gst_base_audio_sink_dispose), + (gst_base_audio_sink_query_pad), (gst_base_audio_sink_query), + (gst_base_audio_sink_setcaps), (gst_base_audio_sink_callback), + (gst_base_audio_sink_activate_pull), + (gst_base_audio_sink_async_play), + (gst_base_audio_sink_change_state): + Implement pad and element convert query function. + Activate the ringbuffer. + Use the segment last_stop value as the offset to pull. + Use new basesink _do_preroll() method to preroll in the pulling thread. + Take appropriate locking in the pulling thread. + * gst-libs/gst/audio/gstringbuffer.h: + Update some docs. + +2008-10-20 14:08:52 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Improve MXF typefinding a bit by searching for a header partition pack instead o... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mxf_type_find): + Improve MXF typefinding a bit by searching for a header partition + pack instead of just a general partition pack and checking more + bytes for valid values. + +2008-10-20 13:45:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/icles/.cvsignore: update ignore file. + Original commit message from CVS: + * tests/icles/.cvsignore: + update ignore file. + * tests/icles/Makefile.am: + * tests/icles/test-box.c: (make_pipeline), (main): + Add another interactive command line experimentation suite for + dynamically boxing/cropping/saling an input video. + +2008-10-17 13:19:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add methods to more accuratly control the pulling thread of a ringbuffer. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_convert), + (gst_ring_buffer_activate), (gst_ring_buffer_is_active): + * gst-libs/gst/audio/gstringbuffer.h: + Add methods to more accuratly control the pulling thread of a + ringbuffer. + Add format conversion helper code to the ringbuffer. + API: GstRingBuffer:gst_ring_buffer_activate() + API: GstRingBuffer:gst_ring_buffer_is_active() + API: GstRingBuffer:gst_ring_buffer_convert() + +2008-10-16 15:44:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Signal thread startup earlier so that we can immediatly go into pull mode when we ... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func), + (gst_audioringbuffer_acquire), (gst_audioringbuffer_release), + (gst_audioringbuffer_stop): + Signal thread startup earlier so that we can immediatly go into pull + mode when we have to and block on preroll. + +2008-10-16 15:38:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: In pull mode we want the callback to prepull a buffer we can preroll on even when... + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_prepare_read): + In pull mode we want the callback to prepull a buffer we can preroll on + even when we are not yet playing. + +2008-10-16 15:07:00 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Don't install static libs for plugins. Fixes #550851 for base. + Original commit message from CVS: + * ext/alsa/Makefile.am: + * ext/cdparanoia/Makefile.am: + * ext/gio/Makefile.am: + * ext/gnomevfs/Makefile.am: + * ext/libvisual/Makefile.am: + * ext/ogg/Makefile.am: + * ext/pango/Makefile.am: + * ext/theora/Makefile.am: + * ext/vorbis/Makefile.am: + * gst/adder/Makefile.am: + * gst/audioconvert/Makefile.am: + * gst/audiorate/Makefile.am: + * gst/audioresample/Makefile.am: + * gst/audiotestsrc/Makefile.am: + * gst/ffmpegcolorspace/Makefile.am: + * gst/gdp/Makefile.am: + * gst/playback/Makefile.am: + * gst/subparse/Makefile.am: + * gst/tcp/Makefile.am: + * gst/typefind/Makefile.am: + * gst/videorate/Makefile.am: + * gst/videoscale/Makefile.am: + * gst/videotestsrc/Makefile.am: + * gst/volume/Makefile.am: + * sys/v4l/Makefile.am: + * sys/ximage/Makefile.am: + * sys/xvimage/Makefile.am: + Don't install static libs for plugins. Fixes #550851 for base. + +2008-10-16 13:50:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiotestsrc/gstaudiotestsrc.c: Set the default blocksize to -1 because we will then use the configured samplespe... + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_init): + Set the default blocksize to -1 because we will then use the configured + samplesperbuffer to create our output buffer. + +2008-10-15 15:28:41 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Add mappping for the KMVC (Karl Morton's Video) Codec. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add mappping for the KMVC (Karl Morton's Video) Codec. + +2008-10-15 14:25:50 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Don't forget to advance the offset of what we're matching against, else we end u... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (flac_type_find): + Don't forget to advance the offset of what we're matching against, else + we end up in a forever loop. + +2008-10-15 11:25:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/subparse/gstsubparse.c: Improve typefinding a bit. If we don't have a Unicode charset try GST_SUBTITLE_ENCODING a... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (gst_subparse_type_find): + Improve typefinding a bit. If we don't have a Unicode charset + try GST_SUBTITLE_ENCODING and otherwise try ISO-8859-15. + +2008-10-14 11:13:59 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/theora/theoradec.c: Fix build on macosx. + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_decode_buffer): + Fix build on macosx. + +2008-10-13 11:36:13 +0000 Robin Stocker <robin@nibor.org> + + ext/theora/: Parse input caps and make the PAR override the encoded PAR when specified by a container. Fixes #555699. + Original commit message from CVS: + Based on patch by: Robin Stocker <robin at nibor dot org> + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_init), + (theora_dec_setcaps), (theora_handle_type_packet), + (theora_dec_decode_buffer), (theora_dec_change_state): + Parse input caps and make the PAR override the encoded PAR when + specified by a container. Fixes #555699. + +2008-10-13 09:16:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Add some more G_LIKELY + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_change_state): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Add some more G_LIKELY + Fail when the setcaps function was not called. + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_set_outcaps): + Propagate return value of setcaps. + +2008-10-13 08:58:29 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/subparse/: Add support for UTF16/UTF32 subtitles as long as the first bytes of the first buffer contain the BOM. ... + Original commit message from CVS: + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (gst_sub_parse_class_init), (gst_sub_parse_init), + (gst_convert_to_utf8), (detect_encoding), (convert_encoding), + (get_next_line), (gst_sub_parse_data_format_autodetect), + (feed_textbuf), (handle_buffer), (gst_sub_parse_change_state), + (gst_subparse_type_find): + * gst/subparse/gstsubparse.h: + Add support for UTF16/UTF32 subtitles as long as the first bytes of + the first buffer contain the BOM. This also adds support for other + encodings that allow NUL bytes via the encoding property. + Fixes bugs #552237 and #456788. + +2008-10-13 08:15:13 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/tag/tags.c: Don't drop the last byte of image tags if they're not an URI list. + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (gst_tag_image_data_to_image_buffer): + Don't drop the last byte of image tags if they're not an URI list. + Fixes bug #556066. + +2008-10-13 08:00:55 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: For looking at the 4th byte we have to get 4 bytes of course and not 3. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (flac_type_find): + For looking at the 4th byte we have to get 4 bytes of course + and not 3. + +2008-10-13 07:52:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Improve FLAC-without-headers typefinding by looking at most of the frame header ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (flac_type_find): + Improve FLAC-without-headers typefinding by looking at most of the + frame header and checking if invalid values are used. Should prevent + quite some false positives compared to the old version which only + check if the first 14 bits are set. + +2008-10-11 16:27:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Don't assert on caps==NULL. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Don't assert on caps==NULL. + +2008-10-10 17:13:40 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add support for subtitle files with UTF-8 BOM at the beginning by simple stripping it from the first line before pass... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect), (handle_buffer), + (gst_sub_parse_change_state): + * gst/subparse/gstsubparse.h: + * tests/check/elements/subparse.c: (GST_START_TEST): + Add support for subtitle files with UTF-8 BOM at the beginning + by simple stripping it from the first line before passing it + to any parsing code. Fixes bug #555257 and playback of files + created by Gnome Subtitles. + +2008-10-10 15:45:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiotestsrc/gstaudiotestsrc.*: Define the default property values in the usual place. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_class_init), (gst_audio_test_src_init), + (gst_audio_test_src_src_fixate), (gst_audio_test_src_setcaps), + (gst_audio_test_src_start), (gst_audio_test_src_stop), + (gst_audio_test_src_do_seek), (gst_audio_test_src_check_get_range), + (gst_audio_test_src_create): + * gst/audiotestsrc/gstaudiotestsrc.h: + Define the default property values in the usual place. + Implement start/stop to reset values correctly. + Calculate the sample size only once when we negotiate. + Rename some values to make more sense. + Keep track of our byte range. + Add support for pull based scheduling. Disabled for now until we have + the whole stack working. + Set the BUFFER_OFFSET correctly. + +2008-10-10 15:32:10 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Make the detection of the used subtitle a bit less strict for srt subtitles. Fixes bug #555607. + Original commit message from CVS: + Based on a patch by: xavierb at gmail dot com + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect): + * tests/check/elements/subparse.c: (GST_START_TEST): + Make the detection of the used subtitle a bit less strict + for srt subtitles. Fixes bug #555607. + +2008-10-10 15:21:38 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/vorbis/vorbisenc.c: Fix discontinuity detection which was broken by last commit. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: + (gst_vorbis_enc_buffer_check_discontinuous): + Fix discontinuity detection which was broken by last commit. + +2008-10-09 11:18:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Require core CVS for ghostpad API additions used by decodebin2. + Original commit message from CVS: + * configure.ac:: + Require core CVS for ghostpad API additions used by decodebin2. + +2008-10-08 15:30:33 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Fix debug statements (space between '%' and actual format). + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Fix debug statements (space between '%' and actual format). + +2008-10-08 14:44:04 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Remove bogus assert, the decodepad could have been created inside an already existing g... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_pad_activate): + Remove bogus assert, the decodepad could have been created inside an + already existing group. + +2008-10-08 14:01:42 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + changelog + Original commit message from CVS: + changelog + +2008-10-08 14:00:07 +0000 Andy Wingo <wingo@pobox.com> + + gst/playback/gstdecodebin2.c (expose_pad): Fix typo: unset target instead of setting it. + Original commit message from CVS: + 2008-10-08 Andy Wingo <wingo@pobox.com> + * gst/playback/gstdecodebin2.c (expose_pad): Fix typo: unset + target instead of setting it. + (gst_decode_pad_activate, gst_decode_pad_unblock): This is now the + API for a decode pad. The bugfix is that we set the group in + activate(), not when the pad was created because it might be NULL + then. + (gst_decode_group_control_source_pad, gst_decode_group_expose): + Update to use the API. + +2008-10-08 12:49:40 +0000 Andy Wingo <wingo@pobox.com> + + gst/playback/gstdecodebin2.c (struct _GstDecodePad): Change to be a subclass of GstGhostPad. + Original commit message from CVS: + 2008-10-08 Andy Wingo <wingo@pobox.com> + * gst/playback/gstdecodebin2.c (struct _GstDecodePad): Change to + be a subclass of GstGhostPad. + (analyze_new_pad): So, when emitting the signals that determine + how we do autoplugging, already create the ghost pad and use it as + the pad in the signal arguments. This allows applications to make + a connection between the pad passed in e.g. autoplug-continue, and + the pad passed in new-decoded-pad. + (connect_pad, expose_pad): Update to receive the ghosted decode + pad in the args, retargetting it as necessary if we have to plug + the target pad through a multiqueue. + (gst_decode_group_control_source_pad): Adapt to receive an + already-ghosted pad that just needs activation, blocking, and + drain notification. + (sort_end_pads): Adapt for decode pads actually being pads. + (gst_decode_group_expose): Adapt for decode pads actually being + pads. Rewrite the decode pad names so they appear in order. Adds a + new error case if we couldn't set the name. + (gst_decode_group_free, gst_decode_group_hide): Adapt cleanup + logic. + (gst_decode_pad_set_blocked, gst_decode_pad_add_drained_check): + New API for the decode pad, needed because we shouldn't do these + things inside gst_decode_pad_new(), but after. + (gst_decode_pad_new): Change to actually make the real pad, and + delay the blocking/drainage bits. + +2008-10-08 12:12:01 +0000 Daniel Drake <dsd@laptop.org> + + ext/ogg/gstoggmux.c: Unref all buffers when clearing collectpads. Fixes bug #546955. + Original commit message from CVS: + Patch by: Daniel Drake <dsd at laptop dot org> + * ext/ogg/gstoggmux.c: (gst_ogg_mux_clear_collectpads): + Unref all buffers when clearing collectpads. Fixes bug #546955. + +2008-10-08 12:08:01 +0000 Klaas <klaas@rivercrew.net> + + ext/vorbis/vorbisenc.*: Keep track of the upstream segments and use the running time on that segment instead of the b... + Original commit message from CVS: + Based on a patch by: Klaas <klaas at rivercrew dot net> + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_sink_event), + (gst_vorbis_enc_buffer_check_discontinuous), + (gst_vorbis_enc_chain), (gst_vorbis_enc_change_state): + * ext/vorbis/vorbisenc.h: + Keep track of the upstream segments and use the running time on that + segment instead of the buffer timestamp everywhere. Fixes bug #525807. + +2008-10-08 11:50:50 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/audioconvert.c: Prevent overflows with big buffer when calculating the size of the intermediate buff... + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (audio_convert_convert): + Prevent overflows with big buffer when calculating the size of + the intermediate buffer by using gst_util_uint64_scale() instead of + plain arithmetics. Fixes bug #552801. + +2008-10-08 10:49:15 +0000 Pavel Zeldin <pzeldin@gmail.com> + + ext/pango/gstclockoverlay.*: API: Add ability to specify format for date/time display by adding a "time-format" prope... + Original commit message from CVS: + Patch by: Pavel Zeldin <pzeldin at gmail dot com> + * ext/pango/gstclockoverlay.c: (gst_clock_overlay_render_time), + (gst_clock_overlay_class_init), (gst_clock_overlay_finalize), + (gst_clock_overlay_init), (gst_clock_overlay_set_property), + (gst_clock_overlay_get_property): + * ext/pango/gstclockoverlay.h: + API: Add ability to specify format for date/time display by + adding a "time-format" property. + Fixes bug #554879. + +2008-10-08 09:22:26 +0000 Jan Gerber <j@oil21.org> + + gst-libs/gst/riff/riff-media.c: Add FFV1 fourcc to support playback of FFMPEG lossless video in AVI. Fixes bug #555319. + Original commit message from CVS: + Patch by: Jan Gerber <j at oil21 dot org> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add FFV1 fourcc to support playback of FFMPEG lossless video + in AVI. Fixes bug #555319. + +2008-10-08 09:12:36 +0000 Håvard Graff <havard.graff@tandberg.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Implement skew clock slaving. Fixes #552559. + Original commit message from CVS: + Patch by: Håvard Graff <havard dot graff at tandberg dot com> + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Implement skew clock slaving. Fixes #552559. + +2008-10-08 09:10:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/: Fix include of config.h + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + * gst-libs/gst/audio/testchannels.c: + Fix include of config.h + +2008-10-06 16:36:20 +0000 Tero Saarni <tero.saarni@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.c: Fix parsing of the c= field containing multicast addresses. + Original commit message from CVS: + Based on Patch by: Tero Saarni <tero dot saarni at gmail dot com> + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_parse_line), + (print_media), (gst_sdp_message_dump): + Fix parsing of the c= field containing multicast addresses. + Fixes #552199. + Add the connection info to the session or streams. + Fix parsing of the bandwidth. + Add debugging for the connections and bandwidths for a media. + Add debugging for the bandwidth of the session. + +2008-10-06 16:31:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Configure the next seqnum and timestamp in the state change so that they can be... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_change_state): + Configure the next seqnum and timestamp in the state change so that they + can be queried soon after. + +2008-10-06 16:29:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Improve debugging of the rtptime. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain): + Improve debugging of the rtptime. + +2008-10-05 11:33:47 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to development -> 0.10.21.1 + Original commit message from CVS: + * configure.ac: + Back to development -> 0.10.21.1 + +2008-10-05 08:18:31 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + * ChangeLog: + ChangeLog surgery + Original commit message from CVS: + ChangeLog surgery + +2008-10-05 08:11:53 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for MXF. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mxf_type_find), + (plugin_init): + Add typefinder for MXF. + +2008-10-05 08:10:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for MXF. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mxf_type_find), + (plugin_init): + Add typefinder for MXF. + +2008-10-03 15:19:40 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/icles/Makefile.am: Only build test-colorkey if GTK+ is available. + Original commit message from CVS: + * tests/icles/Makefile.am: + Only build test-colorkey if GTK+ is available. + +=== release 0.10.21 === + +2008-10-03 00:03:05 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/config.h: + Release 0.10.21 + Original commit message from CVS: + Release 0.10.21 + +2008-10-02 23:44:45 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-09-28 22:58:18 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: 0.10.20.4 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.20.4 pre-release + +2008-09-25 10:46:00 +0000 ogg.k.ogg.k <ogg.k.ogg.k@googlemail.com> + + ext/theora/theoraparse.c: Set the BOS flag on the BOS packet. Fixes #553244. + Original commit message from CVS: + Patch by: ogg.k.ogg.k <ogg dot k dot ogg dot k at googlemail dot com> + * ext/theora/theoraparse.c: (theora_parse_set_streamheader): + Set the BOS flag on the BOS packet. Fixes #553244. + +2008-09-23 17:48:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspmessage.c: Fix the g_return_val_if_fail() statements. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspmessage.c: + (gst_rtsp_message_parse_request), + (gst_rtsp_message_parse_response): + Fix the g_return_val_if_fail() statements. + +2008-09-22 17:44:14 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/tag/gsttagdemux.c: Fail to activate if there's insufficient data in the file to be usable, preventing an... + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: + Fail to activate if there's insufficient data in the file to be usable, + preventing an assertion fail later. Fixes #552960 + +2008-09-16 15:36:56 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Commit stuff that should have gone in last week when I made the pre-releases: + Original commit message from CVS: + Commit stuff that should have gone in last week when I made the pre-releases: + 2008-09-10 Jan Schmidt <jan.schmidt@sun.com> + * configure.ac: + 0.10.20.2 pre-release + * po/LINGUAS: + * po/id.po: + * po/pt_BR.po: + New translations. + +2008-09-15 15:11:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: Recognise Kate subtitle streams (#550582). + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: + * gst/typefind/gsttypefindfunctions.c: + Recognise Kate subtitle streams (#550582). + +2008-09-13 11:04:02 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/audio.h: Remove trailing comma from enum list, which causes problems with -pendantic (#550729). + Original commit message from CVS: + * gst-libs/gst/audio/audio.h: (GST_AUDIO_FIELD_SIGNED): + Remove trailing comma from enum list, which causes problems + with -pendantic (#550729). + +2008-09-05 19:04:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/propertyprobe.c: More sanity checks for our second-favourite interface. + Original commit message from CVS: + * gst-libs/gst/interfaces/propertyprobe.c: + (gst_property_probe_get_properties), + (gst_property_probe_get_property), + (gst_property_probe_probe_property), + (gst_property_probe_probe_property_name), + (gst_property_probe_needs_probe), + (gst_property_probe_needs_probe_name), + (gst_property_probe_get_values), + (gst_property_probe_get_values_name), + (gst_property_probe_probe_and_get_values), + (gst_property_probe_probe_and_get_values_name): + More sanity checks for our second-favourite interface. + +2008-09-05 14:12:01 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/interfaces/propertyprobe.c: Check for NULL pointer, in the hope that this fixes #532864. + Original commit message from CVS: + * gst-libs/gst/interfaces/propertyprobe.c: + Check for NULL pointer, in the hope that this fixes #532864. + +2008-09-05 10:24:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/xvimage/xvimagesink.c: No really, the next release is 0.10.21 (fix Since: tags in docs). + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_class_init): + No really, the next release is 0.10.21 (fix Since: tags in docs). + +2008-09-04 16:25:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosrc.c: Disable a code path that is now called but causes a deadlock for some reason and is... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosrc.c: (gst_audioringbuffer_stop): + Disable a code path that is now called but causes a deadlock for some + reason and is unneeded. + +2008-09-04 13:46:52 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.*: Add a "draw-border" property that can be set to false to disable drawing borders. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + Add a "draw-border" property that can be set to false to disable + drawing borders. + * tests/icles/test-colorkey.c: + * tests/icles/Makefile.am: + Add new test application for the colorkey handling. + +2008-09-03 14:00:06 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Use a decent caps for TrueSpeech instead of a ffmpeg-specific one. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Use a decent caps for TrueSpeech instead of a ffmpeg-specific one. + This will also be fixed for upcoming gst-ffmpeg release so that once + this release of -base is out, it will work with the latest gst-ffmpeg + release. + +2008-09-03 13:27:20 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Add Truespeech mapping for RIFF formats (AVI/WAV). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Add Truespeech mapping for RIFF formats (AVI/WAV). + Fixes #550656 + +2008-09-03 12:23:44 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + gst/typefind/gsttypefindfunctions.c: Typefind video/mj2 and image/jp2 ISO JPEG2000 mime types. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Typefind video/mj2 and image/jp2 ISO JPEG2000 mime types. + Fixes #550638. + +2008-09-03 10:12:04 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Rework last change, so that we build subparse, but just disable the sami parse functionality, if we're configured to ... + Original commit message from CVS: + * configure.ac: + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: + * gst/subparse/samiparse.c: + * tests/check/elements/subparse.c: + Rework last change, so that we build subparse, but just disable the + sami parse functionality, if we're configured to not use xml. In the + tests only the sami test is disabled now. + +2008-09-02 15:07:09 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Disable subparse when xml is disabled. It woundn't work anyway. Fixes test runs. + Original commit message from CVS: + * configure.ac: + Disable subparse when xml is disabled. It woundn't work anyway. Fixes + test runs. + +2008-09-02 09:33:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + po/POTFILES.in: Add some more files with strings for translation. + Original commit message from CVS: + * po/POTFILES.in: + Add some more files with strings for translation. + +2008-09-02 06:37:04 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Use new geo location tags from core. Fixes #481169 + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: + * tests/check/libs/tag.c: + Use new geo location tags from core. Fixes #481169 + +2008-09-01 16:05:45 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/elements/audioresample.c: Now that GstBaseTransform is 'fixed' ... remove cruft from tests. + Original commit message from CVS: + * tests/check/elements/audioresample.c: (setup_audioresample), + (fail_unless_perfect_stream), (test_perfect_stream_instance), + (test_discont_stream_instance): + Now that GstBaseTransform is 'fixed' ... remove cruft from tests. + Add debugging for coherence. + +2008-08-30 15:55:06 +0000 Jonathan Matthew <notverysmart@gmail.com> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for PDF documents (which is nice to have, since it's a common for... + Original commit message from CVS: + Patch by: Jonathan Matthew <notverysmart gmail com> + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add typefinder for PDF documents (which is nice to have, since it's a + common format, but also helps prevent false positives). Fixes #549814. + +2008-08-27 15:30:16 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Fix nasty race where multiple decodebins could start pushing data before we manage to con... + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (selector_blocked), (pad_added_cb), + (no_more_pads_cb): + Fix nasty race where multiple decodebins could start pushing data before + we manage to configure the sinks, resulting in not-linked errors in + typical RTSP streaming cases. + +2008-08-26 17:24:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Since we now call stop, we trigger this code path that causes a deadlock is appare... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_stop): + Since we now call stop, we trigger this code path that causes a deadlock + is apparently not needed. + +2008-08-26 15:45:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Also allow the case where the ringbuffer was paused when we try to stop it so tha... + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_start), + (gst_ring_buffer_stop): + Also allow the case where the ringbuffer was paused when we try to stop + it so that the basesrc stop function is still called. + +2008-08-23 15:25:44 +0000 Mike Ruprecht <cmaiku@gmail.com> + + sys/v4l/gstv4lelement.c: Reprobe devices again instead of taking a cached list as new devices could've been plugged i... + Original commit message from CVS: + Patch by: Mike Ruprecht <cmaiku at gmail dot com> + * sys/v4l/gstv4lelement.c: (gst_v4l_class_probe_devices): + Reprobe devices again instead of taking a cached list as new + devices could've been plugged in. Fixes bug #549062. + +2008-08-23 15:19:59 +0000 Alessandro Dessina <alessandro@nnva.org> + + ext/ogg/gstoggdemux.c: Don't add pads and activate them for skeleton streams. These are already handled inside oggdem... + Original commit message from CVS: + Patch by: Alessandro Dessina <alessandro nnva org> + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_activate_chain): + Don't add pads and activate them for skeleton streams. These are already + handled inside oggdemux. Fixes bug #537599. + +2008-08-22 15:54:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Reset variable so that query and convert fail after going back to + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_change_state): + Reset variable so that query and convert fail after going back to + READY. Fixes #548898. + +2008-08-22 07:24:13 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/vorbis/vorbisenc.c: If a buffer arrives with a timestamp before the timestamp+duration of the previous buffer cli... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_chain): + If a buffer arrives with a timestamp before the timestamp+duration + of the previous buffer clip it instead of dropping it completely. + Slight improvement for the unfixable bug #548913. + +2008-08-21 14:19:21 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/vorbis/vorbisdec.c: Take the current timestamp instead of timestamp+duration for the offset. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + Take the current timestamp instead of timestamp+duration for the offset. + This offset will later be used for calculating the timestamp and + otherwise vorbisdec will interpolate timestamps wrong if upstream + only sends timestamps and no granulepos. + +2008-08-21 11:20:36 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Don't crash when having no visualisations. + Original commit message from CVS: + * tests/examples/seek/seek.c: + Don't crash when having no visualisations. + +2008-08-16 20:57:27 +0000 David Schleef <ds@schleef.org> + + gst/typefind/gsttypefindfunctions.c: DV typefinding. Remove check for a bit that is 0 in IEC 61384, but not SMPTE 314M. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: DV typefinding. Remove + check for a bit that is 0 in IEC 61384, but not SMPTE 314M. + Fixes #548065. + +2008-08-15 07:24:38 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/pbutils/missing-plugins.c: When cleaning up the caps fields also remove "depth" for the same reason we r... + Original commit message from CVS: + * gst-libs/gst/pbutils/missing-plugins.c: (copy_and_clean_caps): + When cleaning up the caps fields also remove "depth" for the same + reason we remove "width". + +2008-08-14 17:14:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/descriptions.c: Add Lead H.264 here as well. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (format_info_get_desc): + Add Lead H.264 here as well. + +2008-08-14 15:17:31 +0000 Julien Moutte <julien@moutte.net> + + gst-libs/gst/riff/riff-media.c: Add Lead H.264 variant. + Original commit message from CVS: + 2008-08-14 Julien Moutte <julien@fluendo.com> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): Add Lead H.264 variant. + +2008-08-13 09:17:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: When not slaved to another clock also subtract the base_time from our internal ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + When not slaved to another clock also subtract the base_time from our + internal clock time to get the running time. + +2008-08-13 00:59:07 +0000 David Schleef <ds@schleef.org> + + ext/theora/theoraenc.c: Remove the 2000 kbit limit to bitrate, since it has no basis in libtheora. + Original commit message from CVS: + * ext/theora/theoraenc.c: Remove the 2000 kbit limit to bitrate, + since it has no basis in libtheora. + +2008-08-12 06:31:49 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/interfaces/propertyprobe.h: Remove double "interface" from doc-string. + Original commit message from CVS: + * gst-libs/gst/interfaces/propertyprobe.h: + Remove double "interface" from doc-string. + * gst-libs/gst/interfaces/xoverlay.h: + Document interface. + * gst-libs/gst/riff/riff.c: + Add basic doc blobs. + +2008-08-11 15:05:35 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/Makefile.am: Don't try to build that example anymore. + Original commit message from CVS: + * gst-libs/gst/audio/Makefile.am: + Don't try to build that example anymore. + +2008-08-11 14:51:58 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/: Move audiofiltertemplate to gst-template. + Original commit message from CVS: + * gst-libs/gst/audio/.cvsignore: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + * gst-libs/gst/audio/make_filter: + Move audiofiltertemplate to gst-template. + +2008-08-11 09:20:33 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + More docs and shuffling. What can we do with the hundreds of #defines. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudiosrc.h: + More docs and shuffling. What can we do with the hundreds of #defines. + +2008-08-11 08:34:56 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/: Reducing number of dundocumented symbols. + Original commit message from CVS: + * gst-libs/gst/audio/audio.h: + * gst-libs/gst/audio/gstaudiofilter.h: + * gst-libs/gst/audio/gstringbuffer.h: + * gst-libs/gst/interfaces/propertyprobe.h: + * gst-libs/gst/tag/gsttagdemux.h: + Reducing number of dundocumented symbols. + +2008-08-11 07:16:30 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/audio.c: Fix doc comment syntax. + Original commit message from CVS: + * gst-libs/gst/audio/audio.c: + Fix doc comment syntax. + * gst-libs/gst/interfaces/propertyprobe.c: + Add more doc-comments and a FIXME: for the signal. + +2008-08-07 16:11:14 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/ogg/gstoggmux.*: Don't pretend to support NEWSEGMENT events, instead override the + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_sink_event), + (gst_ogg_mux_request_new_pad): + * ext/ogg/gstoggmux.h: + Don't pretend to support NEWSEGMENT events, instead override the + GstCollectPads event function to return FALSE on NEWSEGMENT events + and do the normal work for other events. + This prevents elements like flacenc to seek to the start and rewrite + some data which then results in a broken Ogg packet. + +2008-08-07 15:58:58 +0000 Frederic Crozat <fcrozat@mandriva.org> + + Make sure gettext returns translations in UTF-8 encoding rather than in the current locale encoding (#546822). + Original commit message from CVS: + Patch by: Frederic Crozat <fcrozat@mandriva.org> + * ext/alsa/gstalsaplugin.c: (plugin_init): + * ext/cdparanoia/gstcdparanoiasrc.c: (plugin_init): + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_plugin_init): + * gst-libs/gst/audio/gstbaseaudiosrc.c: (_do_init): + * gst-libs/gst/pbutils/pbutils.c: (gst_pb_utils_init): + * gst-libs/gst/tag/tags.c: (gst_tag_register_tags_internal): + * gst/playback/gstdecodebin.c: (plugin_init): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_plugin_init): + * gst/playback/gstplayback.c: (plugin_init): + * gst/playback/gstqueue2.c: (plugin_init): + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_plugin_init): + * sys/v4l/gstv4l.c: (plugin_init): + Make sure gettext returns translations in UTF-8 encoding rather + than in the current locale encoding (#546822). + +2008-08-06 13:12:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/pbutils/descriptions.c: Add audio/x-qdm for qtdemux. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: + Add audio/x-qdm for qtdemux. + +2008-08-05 15:38:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/vorbis/vorbisdec.c: Do not leak old taglist. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: + Do not leak old taglist. + +2008-08-04 12:35:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/icles/test-scale.c: Include <stdlib.h> for atoi(). + Original commit message from CVS: + * tests/icles/test-scale.c: + Include <stdlib.h> for atoi(). + +2008-08-04 09:11:08 +0000 Andy Wingo <wingo@pobox.com> + + gst/audiotestsrc/gstaudiotestsrc.c: Very crucial and important documentation fix. + Original commit message from CVS: + 2008-08-04 Andy Wingo <wingo@pobox.com> + * gst/audiotestsrc/gstaudiotestsrc.c: Very crucial and important + documentation fix. + +2008-08-01 13:06:59 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/gstadder.c: Cleanup lots of empty lines that came from gst-indent going havoc before I added the INDENT_ON/... + Original commit message from CVS: + * gst/adder/gstadder.c: + Cleanup lots of empty lines that came from gst-indent going havoc + before I added the INDENT_ON/OFF marker some time agao. + +2008-08-01 11:55:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Bump requirement to latest core and use new tag for riff formats. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/riff/riff-read.c: + Bump requirement to latest core and use new tag for riff formats. + Needed for #520694. + +2008-08-01 11:14:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/dynamic/: Add example app that dynamically switches between 3 'encoders'. + Original commit message from CVS: + * tests/examples/dynamic/Makefile.am: + * tests/examples/dynamic/codec-select.c: (make_encoder), + (make_pipeline), (do_switch), (my_bus_callback), (main): + Add example app that dynamically switches between 3 'encoders'. + +2008-07-31 13:06:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Add some more comments. + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gst_play_sink_set_vis_plugin): + Add some more comments. + +2008-07-31 12:58:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videotestsrc/gstvideotestsrc.c: Discard buffers of the wrong size after renegotiation, this is perfectly possible... + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_getcaps), + (gst_video_test_src_create): + Discard buffers of the wrong size after renegotiation, this is perfectly + possible with things like capsfilter that could suggest caps changes + upstream without knowing the size of the buffer. + +2008-07-31 11:39:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/icles/: Add dynamic rescaling tests for the new basetransform. + Original commit message from CVS: + * tests/icles/.cvsignore: + * tests/icles/Makefile.am: + * tests/icles/test-scale.c: (make_pipeline), (main): + Add dynamic rescaling tests for the new basetransform. + +2008-07-30 19:51:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/Makefile.am: Dist recently-added gstfastrandom.h. + Original commit message from CVS: + * gst/audioconvert/Makefile.am: + Dist recently-added gstfastrandom.h. + +2008-07-30 15:29:44 +0000 Edward Hervey <bilboed@bilboed.com> + + sys/xvimage/xvimagesink.c: Fix a "may be used uninitialized in this function" which weirdly only appears on macosx (?). + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + Fix a "may be used uninitialized in this function" which weirdly only + appears on macosx (?). + +2008-07-30 09:02:31 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-ids.h: Adding acid chunk for tempo and loop information. + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + Adding acid chunk for tempo and loop information. + +2008-07-29 13:01:13 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/Makefile.am: floor() needs linking to $(LIBM). + Original commit message from CVS: + * sys/xvimage/Makefile.am: + floor() needs linking to $(LIBM). + +2008-07-29 12:35:54 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/gnomevfs/gstgnomevfssrc.c: Aggregate short reads and add some comments and debug logging. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: + Aggregate short reads and add some comments and debug logging. + Fixes #537380 + +2008-07-29 10:26:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstplaybasebin.c: Fix property doc markup (its not a signal). + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + Fix property doc markup (its not a signal). + * sys/xvimage/xvimagesink.c: + Add since tag for new proeprties (also add sice tags fro the last two + other additions). + +2008-07-29 08:59:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.*: Add autofill/colorkey properties. Fixes #538656. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + Add autofill/colorkey properties. Fixes #538656. + +2008-07-29 01:58:05 +0000 David Schleef <ds@schleef.org> + + sys/xvimage/xvimagesink.c: Fix rounding errors when converting colorbalance values between hardware and object proper... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Fix rounding errors when converting colorbalance values + between hardware and object property ranges. Partial + fix for #537889, however, there still seems to be a small + drift problem that could be totem's fault. + +2008-07-28 15:34:13 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/ogg/gstoggdemux.c: Don't use GST_CLOCK_TIME_NONE as start of NEWSEGMENT events. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain_peer), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_handle_page): + Don't use GST_CLOCK_TIME_NONE as start of NEWSEGMENT events. + This fixes a critical warning. + +2008-07-28 13:12:51 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/ogg/gstoggmux.c: Allow muxing of CELT into Ogg streams. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + Allow muxing of CELT into Ogg streams. + +2008-07-28 12:47:06 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add simple typefinder for the CELT codec (www.celt-codec.org). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (celt_type_find), + (plugin_init): + Add simple typefinder for the CELT codec (www.celt-codec.org). + +2008-07-27 11:12:41 +0000 Jan Gerber <j@oil21.org> + + ext/ogg/gstoggdemux.c: Fix calculation of the start time from skeleton streams. + Original commit message from CVS: + Patch by: Jan Gerber <j at oil21 dot org> + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_parse_skeleton_fisbone): + Fix calculation of the start time from skeleton streams. + Fixes bug #530068. + +2008-07-24 13:19:26 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Use 64 bit constant GST_CLOCK_TIME_NONE instead of plain -1. + Original commit message from CVS: + * tests/examples/seek/seek.c: + Use 64 bit constant GST_CLOCK_TIME_NONE instead of plain -1. + +2008-07-23 18:34:19 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/: Implement a linear congruential generator as pseudo random number generator for the dither noise. ... + Original commit message from CVS: + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioquantize.c: + (gst_audio_quantize_setup_dither), + (gst_audio_quantize_free_dither): + * gst/audioconvert/gstfastrandom.h: + Implement a linear congruential generator as pseudo random number + generator for the dither noise. This is about 2 times faster than + using GLib's mersenne twister. Also this uses only integer math for + generating integers while GLib internally uses floating point math. + +2008-07-23 18:27:15 +0000 Michael Smith <msmith@xiph.org> + + configure.ac: Remove AC_ISC_POSIX; it breaks on some systems and is not needed. + Original commit message from CVS: + * configure.ac: + Remove AC_ISC_POSIX; it breaks on some systems and is not needed. + +2008-07-23 13:17:31 +0000 Damien Lespiau <damien.lespiau@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.c: Use GST_STR_NULL to avoid crashes with libcs that don't like NULL strings in printf... + Original commit message from CVS: + Patch by: Damien Lespiau <damien.lespiau gmail com> + * gst-libs/gst/sdp/gstsdpmessage.c: (print_media): + Use GST_STR_NULL to avoid crashes with libcs that don't + like NULL strings in printf args (such as the win32 one). + Fixes #544306. + +2008-07-17 14:21:30 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/xvimage/xvimagesink.c: Oops - set the size of the image used for probing back to 1x1, for consistency with ximage... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls): + Oops - set the size of the image used for probing back to 1x1, for + consistency with ximagesink + +2008-07-17 13:57:33 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: it's not legal to ask the + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new): + Apparently on Solaris and OS/X (at least), it's not legal to ask the + X server to attach to a shared memory segment after we've deleted it, + with the result that MIT-SHM is disabled. Instead, remove it only after + X succeeds in attaching too. + +2008-07-17 02:30:24 +0000 David Schleef <ds@schleef.org> + + gst/audiotestsrc/gstaudiotestsrc.*: Add 'ticks', a 1/30 second sine wave pulse every second. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/audiotestsrc/gstaudiotestsrc.h: + Add 'ticks', a 1/30 second sine wave pulse every second. + +2008-07-15 22:43:16 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/video/video.c: Revert ABI change. + Original commit message from CVS: + * gst-libs/gst/video/video.c: Revert ABI change. + +2008-07-15 13:05:04 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Make it impossible to have NULL caps at the point where we set framerate and other th... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Make it impossible to have NULL caps at the point where we set + framerate and other things. Also don't return immediately for "3ivd" + video and let framerate, etc be set. Might fix bug #542508. + +2008-07-14 17:06:26 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + gst-libs/gst/video/video.c: Video format can also be conveniently determined from (many) non-fixed caps. + Original commit message from CVS: + * gst-libs/gst/video/video.c: (gst_video_format_parse_caps): + Video format can also be conveniently determined from (many) + non-fixed caps. + +2008-07-14 08:18:58 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/: First stab at integrating DVD subpicture overlay into playbin. Successfully plugs and plays, but the q... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: + * gst/playback/gststreamselector.c: + First stab at integrating DVD subpicture overlay into + playbin. Successfully plugs and plays, but the queues need + shrinking - 3 seconds of video is too much buffering. + +2008-07-11 18:06:33 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/gstaudioconvert.c: Remove now obsolete note in the docs. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + Remove now obsolete note in the docs. + +2008-07-11 06:10:24 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Cleanup Plugin docs. Link to signals and properties. Fix sub-section titles. Drop mentining that all our example pipe... + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-overrides.txt: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsrc.c: + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/pango/gsttimeoverlay.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/theora/theoraparse.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisparse.c: + * ext/vorbis/vorbistag.c: + * gst/adder/gstadder.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/audioresample/gstaudioresample.c: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gstqueue2.c: + * gst/playback/gsturidecodebin.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpserversink.c: + * gst/videorate/gstvideorate.c: + * gst/videoscale/gstvideoscale.c: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/volume/gstvolume.c: + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + Cleanup Plugin docs. Link to signals and properties. Fix sub-section + titles. Drop mentining that all our example pipelines are "simple" + pipelines. + +2008-07-10 21:06:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Cleanup Plugin docs. Link to signals and properties. Fix sub-section titles. Drop mentining that all our example pipe... + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-overrides.txt: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsrc.c: + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/pango/gsttimeoverlay.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/theora/theoraparse.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisparse.c: + * ext/vorbis/vorbistag.c: + * gst/adder/gstadder.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/audioresample/gstaudioresample.c: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gstqueue2.c: + * gst/playback/gsturidecodebin.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpserversink.c: + * gst/videorate/gstvideorate.c: + * gst/videoscale/gstvideoscale.c: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/volume/gstvolume.c: + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + Cleanup Plugin docs. Link to signals and properties. Fix sub-section + titles. Drop mentining that all our example pipelines are "simple" + pipelines. + +2008-07-07 17:25:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/examples/seek/Makefile.am: Fix out of tree build by adding all required CFLAGS. + Original commit message from CVS: + * tests/examples/seek/Makefile.am: + Fix out of tree build by adding all required CFLAGS. + +2008-07-07 09:55:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/playback/gstdecodebin.c: And ref the pad before returning it again when linking to the queue failed. Otherwise we... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (add_raw_queue): + And ref the pad before returning it again when linking to the queue + failed. Otherwise we will unref the pad twice later and things break. + +2008-07-07 09:48:45 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/playback/gstdecodebin.c: If linking the raw pad with a queue fails, try it without a queue instead of failing com... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (add_raw_queue): + If linking the raw pad with a queue fails, try it without a queue + instead of failing completely. This should never happen. + +2008-07-06 23:22:12 +0000 Evgeniy Stepanov <eugeni.stepanov@gmail.com> + + gst/playback/gstdecodebin.c: Add a queue after a demuxer if the demuxer outputs raw data. This was done before only f... + Original commit message from CVS: + Patch by: Evgeniy Stepanov <eugeni dot stepanov at gmail dot com> + * gst/playback/gstdecodebin.c: (add_raw_queue), (close_pad_link): + Add a queue after a demuxer if the demuxer outputs raw data. This was + done before only for non-raw data but is required in this case too. + Fixes bug #540215. + decodebin2 doesn't have this issue because all streams of a group + go through multiqueue. + +2008-07-03 09:12:49 +0000 Damien Lespiau <damien.lespiau@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.c: Makes libgstsdp compile with mingw32 by defining the right WINVER so that getaddrin... + Original commit message from CVS: + Patch by: Damien Lespiau <damien dot lespiau at gmail dot com> + * gst-libs/gst/sdp/gstsdpmessage.c: + Makes libgstsdp compile with mingw32 by defining the right WINVER so + that getaddrinfo() can be used. Fixes #541358. + +2008-07-01 13:22:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videotestsrc/gstvideotestsrc.*: Cleanups, use default property values as defines. + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_class_init), (gst_video_test_src_init), + (gst_video_test_src_set_property), + (gst_video_test_src_get_property), (gst_video_test_src_create): + * gst/videotestsrc/gstvideotestsrc.h: + Cleanups, use default property values as defines. + Add property to enable/disable peer buffer allocation. + +2008-06-30 09:46:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/: Enable unit tests on PPC again as the bugs are now fixed. + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (gdpdepay_suite): + * tests/check/pipelines/streamheader.c: (streamheader_suite): + Enable unit tests on PPC again as the bugs are now fixed. + +2008-06-30 09:20:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/: Add support for ADPCM IMA DK3 and DK4 variant in RIFF containers. + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Add support for ADPCM IMA DK3 and DK4 variant in RIFF containers. + Fixes bug #540351. + +2008-06-30 08:29:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/ffmpegcolorspace/: Only set/get on the PAL8 format, ffmpegcolorspace doesn't support it on other formats. Also ad... + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_get_unit_size): + Only set/get on the PAL8 format, ffmpegcolorspace doesn't support + it on other formats. Also adjust the unit size only for that format + to not include the palette. Fixes bug #540497. + +2008-06-29 13:45:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/gstadder.c: Use GST_DEBUG_FUNCPTR and remove some extra vlnak lines. + Original commit message from CVS: + * gst/adder/gstadder.c: + Use GST_DEBUG_FUNCPTR and remove some extra vlnak lines. + +2008-06-27 07:55:40 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ChangeLog: ChangeLog surgery. + Original commit message from CVS: + * ChangeLog: + ChangeLog surgery. + * tests/examples/seek/seek.c: + Move variable into ifdef too. + +2008-06-27 07:42:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Include config.h and check if we have X. Fixes: #540334. + Original commit message from CVS: + * tests/examples/seek/seek.c: + Include config.h and check if we have X. Fixes: #540334. + +2008-06-26 06:03:38 +0000 Sam Morris <sam@robots.org.to.uk> + + gst-libs/gst/interfaces/mixertrack.c: API: Add "index" property to GstMixerTrack to differantiate between multiple mi... + Original commit message from CVS: + Patch by: Sam Morris <sam at robots dot org to uk> + * gst-libs/gst/interfaces/mixertrack.c: + (gst_mixer_track_class_init), (gst_mixer_track_get_property), + (gst_mixer_track_set_property): + API: Add "index" property to GstMixerTrack to differantiate between + multiple mixer tracks with the same label. + * ext/alsa/gstalsamixeroptions.c: (gst_alsa_mixer_options_new): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + Set the "index" property of GstMixerTrack to the index given by ALSA. + Fixes bug #528299. + +2008-06-25 13:15:50 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/: Remove libgstvideo usage. Use gtk_get_option_group instead of gtk_init(). + Original commit message from CVS: + * tests/examples/seek/Makefile.am: + * tests/examples/seek/seek.c: + Remove libgstvideo usage. Use gtk_get_option_group instead of + gtk_init(). + +2008-06-24 16:27:35 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/Makefile.am: Name the test registry format neutral. + Original commit message from CVS: + * tests/check/Makefile.am: + Name the test registry format neutral. + +2008-06-24 16:22:45 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstqueue2.c: Do not double notify. Remove the unsued return value. + Original commit message from CVS: + * gst/playback/gstqueue2.c: + Do not double notify. Remove the unsued return value. + +2008-06-24 16:15:26 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/alsa/gstalsamixer.c: Also consider "speaker" as a name for master volume. If that doesn't help look for the first... + Original commit message from CVS: + * ext/alsa/gstalsamixer.c: + Also consider "speaker" as a name for master volume. If that doesn't + help look for the first non-mono volume control that also has a + playback switch. + +2008-06-24 16:10:50 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ChangeLog: Forgot to save the ChangeLog :/ + Original commit message from CVS: + * ChangeLog: + Forgot to save the ChangeLog :/ + +2008-06-24 16:05:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/: Embedd the xwindow. + Original commit message from CVS: + * tests/examples/seek/Makefile.am: + * tests/examples/seek/seek.c: + Embedd the xwindow. + +2008-06-24 01:14:40 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/ximage/ximagesink.h: When the caps change, make sure to re-draw borders in force-aspect-ratio=true mode. + Original commit message from CVS: + * sys/ximage/ximagesink.c (gst_ximagesink_ximage_put), + (gst_ximagesink_setcaps): + * sys/ximage/ximagesink.h: + When the caps change, make sure to re-draw borders in + force-aspect-ratio=true mode. + * sys/xvimage/xvimagesink.c (gst_xvimagesink_xvimage_put): + Don't clear the border_draw flag until we actually draw the border. + * tests/check/Makefile.am: + Ignore alsasink/src during the states test too, so it doesn't fail + when running without access to the sound device. + +2008-06-22 18:35:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Fix crasher when playing a parse-launch line the 2nd time. + Original commit message from CVS: + * tests/examples/seek/seek.c: + Fix crasher when playing a parse-launch line the 2nd time. + +2008-06-21 18:56:08 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/pipelines/oggmux.c: Properly ifdef tests to fix compilation. + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: + Properly ifdef tests to fix compilation. + +2008-06-21 10:25:59 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + break long lines + Original commit message from CVS: + break long lines + +2008-06-20 18:24:24 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/: Add get-video-pad, get-audio-pad, get-text-pad action signals to playbin2. This allows the user to get... + Original commit message from CVS: + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybin2.c: + Add get-video-pad, get-audio-pad, get-text-pad action signals to + playbin2. This allows the user to get to the selector's sinkpads, and + thus inspect a range of things - caps, tags, etc. + +2008-06-20 17:27:03 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstplaybin2.c: Use a different constant for the convert-frame signal id. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: + Use a different constant for the convert-frame signal id. + Fixes #537009. + +2008-06-20 17:18:55 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/: Fix a whole bunch of typos in comments and log statements. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: + * gst/playback/gstplaysink.c: + Fix a whole bunch of typos in comments and log statements. + +2008-06-20 17:02:48 +0000 Michael Smith <msmith@xiph.org> + + sys/xvimage/xvimagesink.c: Don't set colour balance values on the Xv port if the user hasn't changed them (via proper... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Don't set colour balance values on the Xv port if the user hasn't + changed them (via properties or the interface). Avoids accumulating + rounding errors for the common case. + Partial fix for bug #537889. + +2008-06-20 16:56:18 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstdecodebin2.c: Ensure decodebin2 emits 'drained' signal once, and only once, when all pads are drained. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + Ensure decodebin2 emits 'drained' signal once, and only once, when all + pads are drained. + +2008-06-20 16:12:50 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/README: + apparently it's an error to specify nc -l -p 3000 - though the short usage does not make it very clear that you can d... + Original commit message from CVS: + apparently it's an error to specify nc -l -p 3000 - though the short usage + does not make it very clear that you can drop the host arg with -l + +2008-06-20 09:25:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisenc.c: Report the encoder latency. Fixes #538232. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_get_latency), + (gst_vorbis_enc_src_query), (gst_vorbis_enc_chain): + Report the encoder latency. Fixes #538232. + +2008-06-20 09:19:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Implement the source property, emit notify when it changes in the underlying uridecodebin. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_get_property), + (notify_source), (activate_group): + Implement the source property, emit notify when it changes in the + underlying uridecodebin. + +2008-06-20 09:14:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Free and clear the seek element list so that we don't use invalid references when seeking... + Original commit message from CVS: + * tests/examples/seek/seek.c: (stop_cb): + Free and clear the seek element list so that we don't use invalid + references when seeking after recreating a gst-launch line. + +2008-06-20 09:09:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Report latency even if we are not live instead of hiding it. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_query), (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_render): + Report latency even if we are not live instead of hiding it. + Take ts-offset and render-delay of the basesink into account when + scheduling samples. + Rework the clipping code so that we can take the various offsets into + account and still do correct clipping. + +2008-06-20 08:52:21 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Bump verion back to devel -> 0.10.20.1 + Original commit message from CVS: + * configure.ac: + Bump verion back to devel -> 0.10.20.1 + +2008-06-20 08:47:14 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/tag/tags.c: Don't increase the size of non-string image buffers by one as this might in theory confuse d... + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (gst_tag_image_data_to_image_buffer): + Don't increase the size of non-string image buffers by one as this + might in theory confuse decoders. Still increase it by one for string + image buffers to append '\0'. + +2008-06-20 08:45:13 +0000 Antoine Tremblay <hexa00@gmail.com> + + gst/gdp/gstgdppay.c: Fix a buffer memleak and remove a confusing and wrong debug output. + Original commit message from CVS: + Patch by: Antoine Tremblay <hexa00 at gmail dot com> + * gst/gdp/gstgdppay.c: (gst_gdp_pay_reset): + Fix a buffer memleak and remove a confusing and wrong debug output. + Fixes bug #538663. + +2008-06-19 11:25:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/appsink-src.c: Don't use a buffer after unreffing it. + Original commit message from CVS: + * examples/app/appsink-src.c: (on_new_buffer_from_source): + Don't use a buffer after unreffing it. + +=== release 0.10.20 === + +2008-06-18 14:36:28 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * po/LINGUAS: + * win32/common/config.h: + Release 0.10.20 + Original commit message from CVS: + Release 0.10.20 + +2008-06-18 14:32:12 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/fr.po: + * po/hu.po: + * po/it.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/ru.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-06-18 06:31:11 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix gtk-doc warnings. Also don't misuse api-doc comments for normal comments. + Original commit message from CVS: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * examples/app/appsrc-ra.c: + * examples/app/appsrc-seekable.c: + * examples/app/appsrc-stream.c: + * examples/app/appsrc-stream2.c: + * ext/directfb/dfbvideosink.h: + * ext/metadata/gstbasemetadata.c: + * ext/metadata/gstbasemetadata.h: + * ext/metadata/metadata.c: + * ext/metadata/metadataexif.c: + * ext/theora/theoradec.h: + * gst/deinterlace2/gstdeinterlace2.h: + * gst/deinterlace2/tvtime/speedy.c: + * gst/deinterlace2/tvtime/speedy.h: + * gst/deinterlace2/tvtime/vfir.c: + Fix gtk-doc warnings. Also don't misuse api-doc comments for normal + comments. + +2008-06-16 14:11:36 +0000 Andy Wingo <wingo@pobox.com> + + * gst-libs/gst/app/gstappsrc.c: + gst-libs/gst/app/gstappsrc.c (gst_app_src_set_max_bytes) + Original commit message from CVS: + 2008-06-16 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/app/gstappsrc.c (gst_app_src_set_max_bytes) + (gst_app_src_get_max_bytes, gst_app_src_push_buffer): Use + G_GUINT64_FORMAT. Avoid overflow in get_max_bytes(). + +2008-06-16 07:30:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Final round of doc updates. + Original commit message from CVS: + * gst/rtpmanager/gstrtpjitterbuffer.c: + * gst/speed/gstspeed.c: + * gst/speexresample/gstspeexresample.c: + * gst/videosignal/gstvideoanalyse.c: + * gst/videosignal/gstvideodetect.c: + * gst/videosignal/gstvideomark.c: + * sys/dvb/gstdvbsrc.c: + * sys/oss4/oss4-mixer.c: + * sys/oss4/oss4-sink.c: + * sys/oss4/oss4-source.c: + * sys/wininet/gstwininetsrc.c: + Final round of doc updates. + +2008-06-13 11:59:21 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/plugins/: docs/plugins/inspect/plugin-mythtv.xml + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.interfaces: + * docs/plugins/gst-plugins-bad-plugins.prerequisites: + * docs/plugins/gst-plugins-bad-plugins.signals: + * docs/plugins/inspect/plugin-alsaspdif.xml: + * docs/plugins/inspect/plugin-amrwb.xml: + * docs/plugins/inspect/plugin-app.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-cdaudio.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-dvb.xml: + * docs/plugins/inspect/plugin-dvdspu.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-fbdevsink.xml: + * docs/plugins/inspect/plugin-festival.xml: + * docs/plugins/inspect/plugin-filter.xml: + * docs/plugins/inspect/plugin-flvdemux.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstinterlace.xml: + * docs/plugins/inspect/plugin-gstrtpmanager.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-interleave.xml: + * docs/plugins/inspect/plugin-jack.xml: + * docs/plugins/inspect/plugin-ladspa.xml: + * docs/plugins/inspect/plugin-metadata.xml: + * docs/plugins/inspect/plugin-mms.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-mpeg4videoparse.xml: + * docs/plugins/inspect/plugin-mpegtsparse.xml: + * docs/plugins/inspect/plugin-mpegvideoparse.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-mve.xml: + * docs/plugins/inspect/plugin-mythtv.xml + * docs/plugins/inspect/plugin-nas.xml: + * docs/plugins/inspect/plugin-neon.xml: + * docs/plugins/inspect/plugin-nsfdec.xml: + * docs/plugins/inspect/plugin-nuvdemux.xml: + * docs/plugins/inspect/plugin-oss4.xml + * docs/plugins/inspect/plugin-rawparse.xml: + * docs/plugins/inspect/plugin-real.xml: + * docs/plugins/inspect/plugin-replaygain.xml: + * docs/plugins/inspect/plugin-rfbsrc.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-sdp.xml: + * docs/plugins/inspect/plugin-selector.xml: + * docs/plugins/inspect/plugin-sndfile.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-spcdec.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-speexresample.xml: + * docs/plugins/inspect/plugin-stereo.xml: + * docs/plugins/inspect/plugin-subenc.xml + * docs/plugins/inspect/plugin-timidity.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-vcdsrc.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-vmnc.xml: + * docs/plugins/inspect/plugin-wildmidi.xml: + * docs/plugins/inspect/plugin-x264.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * docs/plugins/inspect/plugin-y4menc.xml: + * ext/amrwb/gstamrwbdec.c: + * ext/amrwb/gstamrwbenc.c: + * ext/amrwb/gstamrwbparse.c: + * ext/dc1394/gstdc1394.c: + * ext/directfb/dfbvideosink.c: + * ext/ivorbis/vorbisdec.c: + * ext/jack/gstjackaudiosink.c: + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/mplex/gstmplex.cc: + * ext/musicbrainz/gsttrm.c: + * ext/mythtv/gstmythtvsrc.c: + * ext/theora/theoradec.c: + * ext/timidity/gsttimidity.c: + * ext/timidity/gstwildmidi.c: + * gst-libs/gst/app/gstappsink.c: + * gst/deinterlace/gstdeinterlace.c: + * gst/dvdspu/gstdvdspu.c: + * gst/festival/gstfestival.c: + * gst/freeze/gstfreeze.c: + * gst/interleave/deinterleave.c: + * gst/interleave/interleave.c: + * gst/modplug/gstmodplug.cc: + * gst/nuvdemux/gstnuvdemux.c: + Add missing elements to docs. Fix doc-markup: use convinience syntax + for examples (produces valid docbook), add several refsec2 when we + have several titles. Fix some types. + +2008-06-12 15:47:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/: Add beefed up example app from bug #413418. It now also uses appsink instead of fakesink for more ulti... + Original commit message from CVS: + * examples/app/.cvsignore: + * examples/app/Makefile.am: + * examples/app/appsink-src.c: (on_new_buffer_from_source), + (on_source_message), (on_sink_message), (main): + Add beefed up example app from bug #413418. It now also uses appsink + instead of fakesink for more ultimate coolness. + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_init), (gst_app_src_set_property), + (gst_app_src_get_property), (gst_app_src_unlock), + (gst_app_src_unlock_stop), (gst_app_src_create), + (gst_app_src_set_max_bytes), (gst_app_src_push_buffer), + (gst_app_src_end_of_stream): + * gst-libs/gst/app/gstappsrc.h: + Add block property to allow push based implementation to block when we + fill up the appsrc queues. + Emit the enough-data signal while releasing our lock. + +2008-06-12 14:50:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + examples/app/.cvsignore: Ignore more. + Original commit message from CVS: + * examples/app/.cvsignore: + Ignore more. + +2008-06-12 14:49:15 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Do not use short_description in section docs for elements. We extract them from element details and there will be war... + Original commit message from CVS: + * ext/dc1394/gstdc1394.c: + * ext/ivorbis/vorbisdec.c: + * ext/jack/gstjackaudiosink.c: + * ext/metadata/gstmetadatademux.c: + * ext/mythtv/gstmythtvsrc.c: + * ext/theora/theoradec.c: + * gst-libs/gst/app/gstappsink.c: + * gst/bayer/gstbayer2rgb.c: + * gst/deinterlace/gstdeinterlace.c: + * gst/rawparse/gstaudioparse.c: + * gst/rawparse/gstvideoparse.c: + * gst/rtpmanager/gstrtpbin.c: + * gst/rtpmanager/gstrtpclient.c: + * gst/rtpmanager/gstrtpjitterbuffer.c: + * gst/rtpmanager/gstrtpptdemux.c: + * gst/rtpmanager/gstrtpsession.c: + * gst/rtpmanager/gstrtpssrcdemux.c: + * gst/selector/gstinputselector.c: + * gst/selector/gstoutputselector.c: + * gst/videosignal/gstvideoanalyse.c: + * gst/videosignal/gstvideodetect.c: + * gst/videosignal/gstvideomark.c: + * sys/oss4/oss4-mixer.c: + * sys/oss4/oss4-sink.c: + * sys/oss4/oss4-source.c: + Do not use short_description in section docs for elements. We extract + them from element details and there will be warnings if they differ. + Also fixing up the ChangeLog order. + +2008-06-11 21:17:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: 0.10.19.3 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.19.3 pre-release + +2008-06-11 20:13:00 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/rtsp/gstrtspconnection.c: Fix build on win32. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + Fix build on win32. + Patch By: David Schleef <ds@schleef.org> + Fixes: #536874 + +2008-06-11 09:35:51 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgiobasesrc.*: Try to read the requested number of bytes, even if the first read returns less than requeste... + Original commit message from CVS: + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_finalize), + (gst_gio_base_src_create): + * ext/gio/gstgiobasesrc.h: + Try to read the requested number of bytes, even if the first + read returns less than requested, until nothing is read anymore + or we have the requested amount of bytes. This fixes playback of + files via Samba as Samba only allows to read 64k at once. + Implement a caching algorithm that makes sure that we read at + least 4k of data every time. Some elements will try to read a few + bytes, then seek, read again a few bytes and so on and this is + painfully slow as every operation has to go over DBus if GVfs is + used as backend. + Fixes bug #536849 and #536848. + * ext/gio/gstgiosrc.c: (gst_gio_src_class_init), + (gst_gio_src_check_get_range): + Override check_get_range() to blacklist http/https URIs + and whitelist file URIs. More to be added on demand. + +2008-06-06 16:50:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/: Added 3 more example application for using appsrc in random-access mode, pull-mode streaming and pull ... + Original commit message from CVS: + * examples/app/Makefile.am: + * examples/app/appsrc-ra.c: (feed_data), (seek_data), + (found_source), (bus_message), (main): + * examples/app/appsrc-seekable.c: (feed_data), (seek_data), + (found_source), (bus_message), (main): + * examples/app/appsrc-stream2.c: (feed_data), (found_source), + (bus_message), (main): + Added 3 more example application for using appsrc in random-access mode, + pull-mode streaming and pull mode seekable. + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_start), (gst_app_src_do_get_size), + (gst_app_src_create): + * gst-libs/gst/app/gstappsrc.h: + Make stream-type property writable. + Unset flushing when starting so that we reuse appsrc. + Inform basesrc about the configured size. + Emit seek-data signal when we are going to a different offset in + random-access mode. + +2008-06-06 14:19:54 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/appsrc-stream.c: Use deep-notify until we can depend on a playbin2 with support for the source property. + Original commit message from CVS: + * examples/app/appsrc-stream.c: (found_source), (main): + Use deep-notify until we can depend on a playbin2 with support for the + source property. + +2008-06-05 16:38:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/: Added an example on how to use appsrc in playbin in streaming mode from an mmapped file. + Original commit message from CVS: + * examples/app/.cvsignore: + * examples/app/Makefile.am: + * examples/app/appsrc-stream.c: (read_data), (start_feed), + (stop_feed), (found_source), (bus_message), (main): + Added an example on how to use appsrc in playbin in streaming mode from + an mmapped file. + * examples/app/appsrc_ex.c: (main): + Set pipeline to NULL to free queued buffers. + * gst-libs/gst/app/gstapp-marshal.list: + * gst-libs/gst/app/gstappsrc.c: (stream_type_get_type), (_do_init), + (gst_app_src_class_init), (gst_app_src_init), + (gst_app_src_flush_queued), (gst_app_src_dispose), + (gst_app_src_set_property), (gst_app_src_get_property), + (gst_app_src_unlock), (gst_app_src_unlock_stop), + (gst_app_src_start), (gst_app_src_stop), (gst_app_src_is_seekable), + (gst_app_src_check_get_range), (gst_app_src_do_seek), + (gst_app_src_create), (gst_app_src_set_stream_type), + (gst_app_src_get_stream_type), (gst_app_src_set_max_bytes), + (gst_app_src_get_max_bytes), (gst_app_src_push_buffer), + (gst_app_src_end_of_stream), (gst_app_src_uri_get_type), + (gst_app_src_uri_get_protocols), (gst_app_src_uri_get_uri), + (gst_app_src_uri_set_uri), (gst_app_src_uri_handler_init): + * gst-libs/gst/app/gstappsrc.h: + Measure max queue size in bytes instead. + Add support for 3 modes of operation, streaming, seekable and + random-access, making basesrc handle the scheduling modes for each. + Add appsrc:// uri handler so that automatic plugging can be done from + playbin2 or uridecodebin, for example. + Added support for custom segment formats. + Add support for push and pull based operations from the application. + Expand the methods so that errors can be detected. + Flush the queued buffers on seeks and when shutting down. + Add signals to inform the app that a seek must happen. + +2008-06-05 09:47:23 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: 0.10.19.2 pre-release + Original commit message from CVS: + * configure.ac: + 0.10.19.2 pre-release + +2008-06-04 21:48:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + win32/common/: Add new API functions to the dll exports + Original commit message from CVS: + * win32/common/libgstrtsp.def: + * win32/common/libgsttag.def: + Add new API functions to the dll exports + +2008-06-04 17:42:38 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstplaybasebin.c: Disconnect signals from decodebins we created before we remove it from playbin, to avo... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + Disconnect signals from decodebins we created before we remove it from + playbin, to avoid crashes if the decodebin is eventually disposed after + the playbin itself (possible if the app takes a reference on the + decodebin). + Fixes #536521. + +2008-06-04 17:12:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Bunch of small clean-ups: use gst_type_find_suggest_simple(); don't copy caps fo... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (aac_type_find), + (mp3_type_find), (musepack_type_find), (MULTIPART_MAX_HEADER_SIZE), + (mpeg_sys_type_find), (mpeg_ts_type_find), (mpeg4_video_type_find), + (h264_video_type_find), (mpeg_video_stream_type_find), + (dv_type_find), (mmsh_type_find): + Bunch of small clean-ups: use gst_type_find_suggest_simple(); don't + copy caps for no good reason (this may be desirable to make it easier + to detect leaks, but then it should probably be done for all caps + in the typefinder somewhere). + +2008-06-04 16:06:49 +0000 Peter Kjellerstedt <pkj@axis.com> + + tests/check/Makefile.am: Do not try to run the check tests for subparse unless it has been built. + Original commit message from CVS: + * tests/check/Makefile.am: + Do not try to run the check tests for subparse unless it has been + built. + +2008-06-04 16:00:26 +0000 Peter Kjellerstedt <pkj@axis.com> + + tests/check/pipelines/streamheader.c: Do not try to run a test which requires vorbisenc unless we have actually built... + Original commit message from CVS: + * tests/check/pipelines/streamheader.c: (buffer_probe_cb), + (test_multifdsink_gdp_vorbisenc), (streamheader_suite): + Do not try to run a test which requires vorbisenc unless we have + actually built it. + +2008-06-04 11:53:53 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst-libs/gst/rtsp/gstrtspconnection.*: Add a couple of missing argument guards. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_set_auth), (gst_rtsp_connection_set_auth_param), + (gst_rtsp_connection_clear_auth_params), + (gst_rtsp_connection_set_qos_dscp), (gst_rtsp_connection_get_ip): + * gst-libs/gst/rtsp/gstrtspconnection.h: + Add a couple of missing argument guards. + Add a way of setting the DSCP for an RTSP connection. + Add an accessor method for the ip member of GstRTSPConnection as all + members are supposed to be private. + +2008-06-04 11:33:23 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst/tcp/gstmultifdsink.c: Fixed accidental use of IPv4 options for all IPv6 addresses. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (setup_dscp_client): + Fixed accidental use of IPv4 options for all IPv6 addresses. + +2008-06-04 10:18:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixertrack.h: Document mixer track flags. + Original commit message from CVS: + * gst-libs/gst/interfaces/mixertrack.h: + Document mixer track flags. + +2008-06-04 05:58:38 +0000 Antoine Tremblay <hexa00@gmail.com> + + gst/gdp/gstgdppay.c: Don't set caps on the buffers that contain a copy of the buffer including the caps of them resul... + Original commit message from CVS: + Patch by: Antoine Tremblay <hexa00 at gmail dot com> + * gst/gdp/gstgdppay.c: (gst_gdp_pay_reset_streamheader): + Don't set caps on the buffers that contain a copy of the buffer + including the caps of them resulting in an always increasing refcount + of the caps and insanely large caps. Instead include a buffer without + caps in the new caps. Fixes bug #536475. + +2008-06-04 05:44:06 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/videoscale/gstvideoscale.c: Transform a given PAR to a range on the struct with the generic height/width instead ... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps): + Transform a given PAR to a range on the struct with the generic + height/width instead of the struct with the possibly restricted + height/width. + +2008-06-04 04:24:27 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/videoscale/gstvideoscale.c: Prefer the given format if it contains something stricter than [1,MAX] for height or ... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps): + Prefer the given format if it contains something stricter than [1,MAX] + for height or width and only put a structure that requires rescaling + as second. This makes it possible to use videoscale in pipelines where + the source can actually produce the wanted height/width but usually + selects a different one from the requested. + +2008-06-03 20:01:58 +0000 John Millikin <jmillikin@gmail.com> + + gst-libs/gst/tag/gstvorbistag.c: Retrieve COVERART tags from vorbis comments (#512333) + Original commit message from CVS: + Based on patch by: John Millikin <jmillikin gmail com> + * gst-libs/gst/tag/gstvorbistag.c: (tag_matches), (gst_vorbis_tag_add), + (gst_vorbis_tag_add_coverart): + Retrieve COVERART tags from vorbis comments (#512333) + +2008-06-03 19:44:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/: Don't forget to add new enum value here too (should probably use glib-mkenums here...). + Original commit message from CVS: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: (register_tag_image_type_enum): + Don't forget to add new enum value here too (should probably use + glib-mkenums here...). + +2008-06-03 19:29:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/: API: add gst_tag_image_data_to_image_buffer() + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: (gst_tag_list_add_id3_image): + * gst-libs/gst/tag/tag.h: (GST_TAG_IMAGE_TYPE_NONE), + * gst-libs/gst/tag/tags.c: (register_tag_image_type_enum), + (gst_tag_image_type_get_type), (gst_tag_image_type_is_valid), + (gst_tag_image_data_to_image_buffer): + Add two utility functions to avoid code duplication (#512333): + API: add gst_tag_image_data_to_image_buffer() + API: add gst_tag_list_add_id3_image() + +2008-06-03 08:54:29 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstaudio.def: Add gst_audio_check_channel_positions() to the exported symbols. + Original commit message from CVS: + * win32/common/libgstaudio.def: + Add gst_audio_check_channel_positions() to the exported symbols. + +2008-06-03 08:48:32 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + API: Make gst_audio_check_channel_positions() public. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions): + * gst-libs/gst/audio/multichannel.h: + API: Make gst_audio_check_channel_positions() public. + * tests/check/libs/audio.c: (GST_START_TEST): + Add some simple checks for gst_audio_check_channel_positions(). + +2008-06-02 20:09:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/v4l/v4l_calls.c: minrange and maxrange are scaled according to the frequency multiplier. + Original commit message from CVS: + * sys/v4l/v4l_calls.c: (gst_v4l_get_chan_names): + minrange and maxrange are scaled according to the frequency + multiplier. + +2008-06-02 18:37:02 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/: Use gstvideo functions to calculate strides and plane offsets. Fixes rendering issue ('ghost' images of t... + Original commit message from CVS: + * ext/pango/Makefile.am: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_shade_y), + (gst_text_overlay_blit_yuv420), (gst_text_overlay_push_frame): + Use gstvideo functions to calculate strides and plane offsets. Fixes + rendering issue ('ghost' images of the text on the chroma planes) + with widths or heights that are not multiples of 8 (#506659 and + probably also #485729). + * tests/icles/test-textoverlay.c: (show_text), (test_textoverlay), + (main): + Test with odd height/width too. + +2008-06-02 12:20:35 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: When using gst_element_iterate_pads() one has to unref every pad after usage. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_query_duration), + (gst_adder_query_latency): + When using gst_element_iterate_pads() one has to unref every pad + after usage. + +2008-05-31 19:57:57 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Add a gtk-doc chunk for the new properties to have a Since: indication. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init): + Add a gtk-doc chunk for the new properties to have a Since: indication. + +2008-05-31 19:50:59 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * ChangeLog: + ChangeLog surgery, mark API change + Original commit message from CVS: + ChangeLog surgery, mark API change + +2008-05-31 18:10:47 +0000 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Provide readable actual-buffer-time and actual-latency-time properties that ref... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init), (gst_base_audio_src_dispose), + (gst_base_audio_src_get_property), (gst_base_audio_src_setcaps), + (gst_base_audio_src_change_state): + Provide readable actual-buffer-time and actual-latency-time properties + that reflect the configured ringbuffer values. Fixes #524724. + +2008-05-30 15:29:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Simply converting the running time into an RTP timestamp by scaling it based on... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push), + (gst_basertppayload_change_state): + Simply converting the running time into an RTP timestamp by scaling it + based on the clock-rate is good enough for making an RTP timestamp. This + has the added benefit that we can later on expose a property with the + RTP timestamp of running time 0, as is needed for RTSP servers to + generate the response of the PLAY request. + +2008-05-30 08:42:17 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Allow up to 11 positioned channels now that audioconvert can handle this but add ... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (structure_has_fixed_channel_positions), + (gst_audio_convert_transform_caps): + Allow up to 11 positioned channels now that audioconvert can handle + this but add no default positions for > 8 channels. + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Add some unit tests for the above change: Test conversion of + 11 positioned channels to stereo and the other way around, test + conversion of 15 unpositioned channels in different ways. + +2008-05-29 19:45:40 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstaudio.def: Add gst_audio_clock_reset to the list of exported symbols. + Original commit message from CVS: + * win32/common/libgstaudio.def: + Add gst_audio_clock_reset to the list of exported symbols. + +2008-05-29 19:37:47 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/elements/vorbisdec.c: Remove wrong_channels_identification_header unit test as we now support 7 (and more... + Original commit message from CVS: + * tests/check/elements/vorbisdec.c: (vorbisdec_suite): + Remove wrong_channels_identification_header unit test as we now + support 7 (and more channels). + +2008-05-29 12:17:16 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstchannelmix.c: If mixing left or right to center (or the other way around) only take the complete ... + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: + (gst_channel_mix_fill_one_other): + If mixing left or right to center (or the other way around) only take + the complete value if we don't already have the original position in + the source. + +2008-05-29 11:34:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/multichannel.c: Allow rear center together with rear left/right and other previously conflicting c... + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions), + (gst_audio_set_structure_channel_positions_list), + (gst_audio_fixate_channel_positions): + Allow rear center together with rear left/right and other previously + conflicting channel positions. The reason why they weren't allowed + was the channel mixing implementation in audioconvert. + Also take this into account when fixing channel layouts. + Allow setting channel positions for 1/2 channels when using + gst_audio_set_structure_channel_position(). + * gst/audioconvert/gstchannelmix.c: + (gst_channel_mix_fill_compatible), (gst_channel_mix_detect_pos), + (gst_channel_mix_fill_one_other), (gst_channel_mix_fill_others), + (gst_channel_mix_fill_special), (gst_channel_mix_fill_matrix): + Major rewrite of the channel mixing. + We now allow previously conflicting channel positions to appear + together (rear center and rear left/right for example). + Fixes bug #533817. + Rework the way channels are mixed together to take more possible + channel positions into account, properly mix from/to side channels + and don't assume that either center, left&right or nothing of a + specific position is available anymore. + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Adjust unit tests with non-standard 1/2 channel layouts to the more + correct new behaviour. + Add a unit test for 5.1->Stereo downmixing. + +2008-05-29 07:02:50 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/vorbis/: Add sane defaults for the 7 and 8 channel layouts as those are undefined in the Vorbis spec. Use NONE ch... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_identification_packet): + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_generate_sink_caps): + Add sane defaults for the 7 and 8 channel layouts as those are + undefined in the Vorbis spec. Use NONE channel layouts when decoding + more than 8 channels instead of erroring out. Fixes bug #535356. + +2008-05-28 16:10:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add theoraparse to the docs and fix some docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/theora/theoraparse.c: + Add theoraparse to the docs and fix some docs. + +2008-05-28 15:48:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/cdda/gstcddabasesrc.c: Fix EOS condition and track addition check, the track.end sector is included in t... + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_add_track), (gst_cdda_base_src_create): + Fix EOS condition and track addition check, the track.end sector is + included in the track. Fixes #533265. + +2008-05-28 14:49:24 +0000 Mark Nauwelaerts <manauw@skynet.be> + + gst/videorate/gstvideorate.*: React (more) to NEWSEGMENT + Original commit message from CVS: + Patch by: Mark Nauwelaerts <manauw at skynet be> + * gst/videorate/gstvideorate.c: (gst_video_rate_reset), + (gst_video_rate_flush_prev), (gst_video_rate_event), + (gst_video_rate_chain): + * gst/videorate/gstvideorate.h: + React (more) to NEWSEGMENT + Small adjustment in timestamp calculation to prevent mismatches + Fixes #435633. + +2008-05-28 11:31:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/examples/seek/seek.c: Initialise error to NULL as we should. + Original commit message from CVS: + * tests/examples/seek/seek.c: (make_parselaunch_pipeline): + Initialise error to NULL as we should. + +2008-05-28 08:14:47 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: Implement latency query. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_query_duration), + (gst_adder_query_latency), (gst_adder_query): + Implement latency query. + +2008-05-27 18:10:00 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: Correctly resync the iterator if gst_iterator_next() returns + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_query_duration): + Correctly resync the iterator if gst_iterator_next() returns + GST_ITERATOR_RESYNC. + +2008-05-27 17:14:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + win32/vs6/libgstpbutils.dsp: Add pbutils-enumtypes.c to sources (#518037). + Original commit message from CVS: + * win32/vs6/libgstpbutils.dsp: + Add pbutils-enumtypes.c to sources (#518037). + +2008-05-27 16:20:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudioclock.*: Add method to inform the clock that the time starts from 0 again. We use this inf... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_init), + (gst_audio_clock_reset), (gst_audio_clock_get_internal_time): + * gst-libs/gst/audio/gstaudioclock.h: + Add method to inform the clock that the time starts from 0 again. We use + this info to calculate a clock offset so that the time we report in + internal_time is monotonically increasing, as required by the clock base + class. Fixes #521761. + API: GstAudioClock::gst_audio_clock_reset() + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_change_state): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create), (gst_base_audio_src_change_state): + Reset reported time when we (re)create the ringbuffer. + +2008-05-27 16:11:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsamixertrack.c: Make sure playback volumes aren't accidentally overwritten by capture volumes if an als... + Original commit message from CVS: + * ext/alsa/gstalsamixertrack.c: + (gst_alsa_mixer_track_update_alsa_capabilities): + Make sure playback volumes aren't accidentally overwritten by + capture volumes if an alsa mixer track has both playback and + capture capabilities: we create two GstMixerTracks in that + case, so make sure we query only the alsa capabilities that + refer to the type of GstMixerTrack we created from the dual + capability alsa element. Should fix issues with Audigy2 sound + cards (#518082). + +2008-05-27 10:57:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/oggmux.c: Don't use deprecated function. + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: (test_pipeline): + Don't use deprecated function. + +2008-05-27 10:35:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Check for NULL cases and log them, creating ghostpads can, for example, fail when the p... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + (gst_decode_group_control_source_pad), (gst_decode_group_expose): + Check for NULL cases and log them, creating ghostpads can, for example, + fail when the pad returns wrong caps. + * gst/playback/gstplaybin2.c: (perform_eos): + When pushing out the EOS event, collect the return value and warn when + something failed. + +2008-05-26 17:18:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: Add support for DVCPRO. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add support for DVCPRO. + +2008-05-26 10:29:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videoscale/gstvideoscale.c: Change default scaling method from nearest-neighbour to bilinear. + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (DEFAULT_PROP_METHOD): + Change default scaling method from nearest-neighbour to bilinear. + +2008-05-26 10:26:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/video.c: More checks. + Original commit message from CVS: + * tests/check/libs/video.c: + More checks. + +2008-05-25 20:51:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + Limit duration to a maximum of five seconds for tmplayer format where we can guess the duration only from the timesta... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (parser_state_init), + (gst_sub_parse_format_autodetect), (handle_buffer): + * gst/subparse/gstsubparse.h: + * tests/check/elements/subparse.c: (test_tmplayer_style3b): + Limit duration to a maximum of five seconds for tmplayer format where + we can guess the duration only from the timestamp of the next line of + text. We don't want to show a text for eternities just because nothing + else is being said for a while. + +2008-05-23 14:14:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Check sequence numbers, mark input buffers with a discont flag for the subcla... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_handle_sink_event), + (gst_base_rtp_depayload_push_full), + (gst_base_rtp_depayload_change_state): + Check sequence numbers, mark input buffers with a discont flag for the + subclass when we detected a gap, drop duplicate buffers. We do this + because one can use the element without a jitterbuffer in front and we + don't want to feed the subclasses invalid or reordered data. + Do an error when the subclass did not provide a process function instead + of crashing. + Some other small cleanups. + +2008-05-22 22:35:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/videotestsrc.c: May just as well use the precalculated uvstride here. + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: (paint_hline_NV12_NV21): + May just as well use the precalculated uvstride here. + +2008-05-22 22:09:16 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Add some documentation comments, and some new headers to be scanned. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-overrides.txt: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * ext/cdparanoia/gstcdparanoiasrc.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggdemux.h: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioconvert.h: + * gst/gdp/gstgdpdepay.h: + * gst/gdp/gstgdppay.h: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: + * gst/playback/gsturidecodebin.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp.h: + Add some documentation comments, and some new headers to be scanned. + Rename some internal enum declarations (audioconvert's DitherType and + NoiseShapingType, GstUnitType from the TCP elements) to match the + documented GObject type names so that the docs pick them up. + Name the playbin2 docs markups properly so they get picked up. They'll + need renaming back when/if playbin2 becomes playbin. + 100% symbol coverage for the plugin docs, booya. + +2008-05-22 18:30:15 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + gst/videotestsrc/videotestsrc.c: Fix generation of NV12/NV21 frames. Fixes bug #532454. + Original commit message from CVS: + Patch by: Thijs Vermeir <thijsvermeir@gmail.com> + * gst/videotestsrc/videotestsrc.c: (paint_hline_NV12_NV21): + Fix generation of NV12/NV21 frames. Fixes bug #532454. + +2008-05-22 11:59:33 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/playback/gstdecodebin.c: Lock the fakesink before setting the state to NULL and removing it from the bin so that ... + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon dot net> + * gst/playback/gstdecodebin.c: (remove_fakesink): + Lock the fakesink before setting the state to NULL and removing it from + the bin so that a concurrent state change cannot interfere. + Fixes #534331. + +2008-05-21 17:09:42 +0000 Felipe Contreras <felipe.contreras@nokia.com> + + docs/Makefile.am: Fix installing plugin documentation when gtk-doc is disabled. + Original commit message from CVS: + * docs/Makefile.am: + Fix installing plugin documentation when gtk-doc is disabled. + +2008-05-21 17:01:16 +0000 Felipe Contreras <felipe.contreras@nokia.com> + + gst-libs/gst/rtsp/Makefile.am: Distribute, don't install md5.h + Original commit message from CVS: + * gst-libs/gst/rtsp/Makefile.am: + Distribute, don't install md5.h + +2008-05-21 16:47:58 +0000 Julien Moutte <julien@moutte.net> + + gst/tcp/gstmultifdsink.c: Use IPPROTO_IP instead of SOL_IP, works on more platforms. + Original commit message from CVS: + 2008-05-21 Julien Moutte <julien@fluendo.com> + * gst/tcp/gstmultifdsink.c: (setup_dscp_client): Use IPPROTO_IP + instead of SOL_IP, works on more platforms. + * gst/typefind/gsttypefindfunctions.c: (aac_type_find): Fix printf + arguments. + +2008-05-21 16:44:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + Some debug and comment fixes. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_show_frame): + Some debug and comment fixes. + * tests/examples/dynamic/addstream.c: (main): + Fix , to ; + +2008-05-21 16:36:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + Don't use bad gst_element_get_pad(). + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_typefind): + * gst/playback/decodetest.c: (new_decoded_pad_cb): + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (try_to_link_1), (elem_is_dynamic), (close_link), (type_found), + (cleanup_decodebin): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_init), + (connect_element), (gst_decode_group_control_demuxer_pad): + * gst/playback/gstplaybasebin.c: (queue_remove_probe), + (queue_out_of_data), (gen_preroll_element), (preroll_unlinked), + (mute_group_type): + * gst/playback/gstplaybin.c: (gst_play_bin_vis_blocked), + (gst_play_bin_set_property), (handoff), (gen_video_element), + (gen_text_element), (gen_audio_element), (gen_vis_element), + (remove_sinks), (add_sink), (setup_sinks): + * gst/playback/gstplaybin2.c: (pad_added_cb), (no_more_pads_cb): + * gst/playback/gstplaysink.c: (gst_play_sink_get_video_sink), + (gst_play_sink_get_audio_sink), (gst_play_sink_vis_unblocked), + (gst_play_sink_vis_blocked), (gst_play_sink_set_vis_plugin), + (gst_play_sink_get_vis_plugin), (gst_play_sink_set_mute), + (gen_video_chain), (gen_text_chain), (gen_audio_chain), + (gen_vis_chain), (gst_play_sink_reconfigure), + (gst_play_sink_set_font_desc), (gst_play_sink_get_font_desc), + (gst_play_sink_request_pad): + * gst/playback/gsturidecodebin.c: (type_found), (setup_source): + * gst/playback/test.c: (gen_video_element), (gen_audio_element), + (cb_newpad): + * gst/playback/test6.c: (new_decoded_pad_cb): + * tests/check/elements/audioconvert.c: (GST_START_TEST): + * tests/check/elements/audiorate.c: (test_injector_chain), + (do_perfect_stream_test): + * tests/check/elements/ffmpegcolorspace.c: (GST_START_TEST): + * tests/check/elements/gdpdepay.c: (GST_START_TEST): + * tests/check/elements/gnomevfssink.c: + * tests/check/elements/textoverlay.c: + (notgst_check_setup_src_pad2), (notgst_check_teardown_src_pad2): + * tests/check/elements/videotestsrc.c: (GST_START_TEST): + * tests/check/libs/cddabasesrc.c: (GST_START_TEST): + * tests/check/pipelines/oggmux.c: (test_pipeline): + * tests/check/pipelines/streamheader.c: (GST_START_TEST): + * tests/check/pipelines/theoraenc.c: (GST_START_TEST): + * tests/check/pipelines/vorbisenc.c: (GST_START_TEST): + * tests/examples/seek/scrubby.c: (make_wav_pipeline): + * tests/examples/seek/seek.c: (make_mod_pipeline), + (make_dv_pipeline), (make_wav_pipeline), (make_flac_pipeline), + (make_sid_pipeline), (make_parse_pipeline), (make_vorbis_pipeline), + (make_theora_pipeline), (make_vorbis_theora_pipeline), + (make_avi_msmpeg4v3_mp3_pipeline), (make_mp3_pipeline), + (make_avi_pipeline), (make_mpeg_pipeline), (make_mpegnt_pipeline), + (update_fill), (msg_buffering): + Don't use bad gst_element_get_pad(). + +2008-05-21 14:35:41 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-media.c: Fix wrong method name in docs. Fix calculation of strf fields for broken mulaw/alaw. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: + Fix wrong method name in docs. Fix calculation of strf fields for + broken mulaw/alaw. + * gst-libs/gst/riff/riff-read.c: + Whitespace fix and removing double ';'. + +2008-05-21 11:52:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/design/part-playbin2.txt: Add some leftover doc. + Original commit message from CVS: + * docs/design/part-playbin2.txt: + Add some leftover doc. + +2008-05-21 11:36:37 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstchannelmix.c: Fix copy & paste error in last commit. + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_others): + Fix copy & paste error in last commit. + +2008-05-21 11:30:58 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstchannelmix.c: Add support for mixing GST_AUDIO_CHANNEL_POSITION_SIDE_* from/to other channel posi... + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_others): + Add support for mixing GST_AUDIO_CHANNEL_POSITION_SIDE_* from/to + other channel positions when source has SIDE channels and dest doesn't + or the other way around. + +2008-05-21 11:29:25 +0000 Henrik Eriksson <henriken@axis.com> + + gst/tcp/gstmultifdsink.*: Add support for DSCP QOS. Fixes #469933. + Original commit message from CVS: + Patch by: Henrik Eriksson <henriken at axis dot com> + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_init), (setup_dscp_client), (setup_dscp), + (gst_multi_fd_sink_add_full), (gst_multi_fd_sink_set_property), + (gst_multi_fd_sink_get_property): + * gst/tcp/gstmultifdsink.h: + Add support for DSCP QOS. Fixes #469933. + +2008-05-21 07:46:02 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/elements/audioconvert.c: Add another test that checks if conversion between standard 1 and 2 channel layo... + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Add another test that checks if conversion between standard 1 and 2 + channel layouts with and without positions set is working. + +2008-05-21 07:39:56 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/multichannel.c: Allow non-standard 2 channel layouts. + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions): + Allow non-standard 2 channel layouts. + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Add some tests for converting and remapping non-standard 1 and 2 + channel layouts. + +2008-05-21 07:28:04 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstchannelmix.c: Prevent division by zero if the channel mix matrix contains only zeroes. + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: + (gst_channel_mix_fill_normalize): + Prevent division by zero if the channel mix matrix contains only + zeroes. + +2008-05-21 06:45:22 +0000 Antoine Tremblay <hexa00@gmail.com> + + gst/gdp/gstgdppay.c: Close a buffer memory leak. Fixes bug #534071. + Original commit message from CVS: + Patch by: Antoine Tremblay <hexa00 at gmail dot com> + * gst/gdp/gstgdppay.c: (gst_gdp_pay_chain): + Close a buffer memory leak. Fixes bug #534071. + +2008-05-21 06:39:20 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/rtsp/gstrtsptransport.h: Make the GstRTSPTransport struct members public as there are no setters/getters... + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtsptransport.h: + Make the GstRTSPTransport struct members public as there are no + setters/getters and it's supposed to be changed directly. + Fixes bug #533087. + +2008-05-21 05:48:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: Adder also doesn't support audio/x-raw-int with width!=depth so don't claim this on the pad tem... + Original commit message from CVS: + * gst/adder/gstadder.c: + Adder also doesn't support audio/x-raw-int with width!=depth so don't + claim this on the pad template caps. + +2008-05-20 16:26:53 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: We can only use our optimal calibration if we prerolled before the latency exp... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_sync_latency): + We can only use our optimal calibration if we prerolled before the + latency expired. + +2008-05-20 14:35:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Require core CVS for GstBaseSrc buffer caps setting magic. + Original commit message from CVS: + * configure.ac: + Require core CVS for GstBaseSrc buffer caps setting magic. + +2008-05-20 12:26:32 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Fix logic in last commit. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_fixate_channels): + Fix logic in last commit. + +2008-05-20 12:15:34 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Passthrough the channel positions if the number of output channels is the same as... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_fixate_channels): + Passthrough the channel positions if the number of output channels is + the same as the number of input channels, the input had a channel + layout and downstream requests no special one. We did this already for + > 2 channels but now it's also done for 1 channel. Fixes bug #533617. + +2008-05-20 11:13:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/gnomevfs/gstgnomevfssrc.*: Set the ICY caps on the srcpad from where they get picked up by the base class now and... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_init), + (gst_gnome_vfs_src_finalize), + (gst_gnome_vfs_src_received_headers_callback), + (gst_gnome_vfs_src_create), (gst_gnome_vfs_src_stop): + * ext/gnomevfs/gstgnomevfssrc.h: + Set the ICY caps on the srcpad from where they get picked up by the base + class now and set on the outgoing buffers. + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new): + BaseSrc now sets the caps on outgoing buffers automatically. + +2008-05-20 11:09:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Change the way in which the ringbuffer is started when dealing with a slaved c... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_resample_slaving), + (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_sync_latency), (gst_base_audio_sink_render), + (gst_base_audio_sink_async_play), + (gst_base_audio_sink_change_state): + Change the way in which the ringbuffer is started when dealing with a + slaved clock and latency. We now sync to the clock until we reach + upstream latency before starting the ringbuffer. This has the effect + that we can accurately align the master and slave clocks and let the + rate correction code take care of the initial drift or rounding errors + instead of leaving them uncorrected with the old approach. + +2008-05-20 08:12:19 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Correctly set the default channel positions when converting to 8 channels. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_fixate_channels): + Correctly set the default channel positions when converting to 8 + channels. + +2008-05-19 16:13:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Error out if we don't have the required version of core. + Original commit message from CVS: + * configure.ac: + Error out if we don't have the required version of core. + +2008-05-19 15:59:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Use data scan helper in aac typefinder and stop scanning for headers when we've ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (aac_type_find): + Use data scan helper in aac typefinder and stop scanning + for headers when we've found a type. Also fix potential invalid + memory access when calculating the frame length. + +2008-05-19 14:09:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Don't modify scan context when we return FALSE in ensure_data, so it's possible ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (data_scan_ctx_ensure_data), + (mpeg_sys_is_valid_pack): + Don't modify scan context when we return FALSE in ensure_data, so + it's possible to continue scanning, and we don't end up with a NULL + data pointer and a positive size, which might bite us the next time + we're called. Small constification. + +2008-05-16 21:12:02 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: Adder doesn't support 24 bit samples so don't claim it supports them in the pad template caps. + Original commit message from CVS: + * gst/adder/gstadder.c: + Adder doesn't support 24 bit samples so don't claim it supports them + in the pad template caps. + +2008-05-14 20:28:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Validate the RTP packet before further processing it. It's just too dangerous... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain): + Validate the RTP packet before further processing it. It's just too + dangerous to accept random packets and people are not forced to use a + jitterbuffer or session manager to filter out the bad packets. + * gst-libs/gst/rtp/gstrtpbuffer.c: + (gst_rtp_buffer_set_extension_data), + (gst_rtp_buffer_get_payload_subbuffer): + Small cleanups. + When setting extension data in a buffer that is too small, we fail and + we should not set the extension bit. + Change GST_WARNINGS into g_warning because they really are + programming errors. + * tests/check/libs/rtp.c: (GST_START_TEST): + Catch the g_warnings now in the unit tests and that fact that failing to + set extension data left the extension bit untouched. + +2008-05-14 13:57:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioresample/gstaudioresample.c: Revert previous change which made basetransform handle buffer_alloc and which b... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init): + Revert previous change which made basetransform handle buffer_alloc + and which breaks things badly in the non-passthrough case since it + returned buffers with a different (ie. sometimes smaller) size than + the size requested. + +2008-05-14 13:43:12 +0000 Bernard B <b-gnome@largestprime.net> + + gst-libs/gst/rtp/gstrtpbuffer.c: Fix seqnum compare function for bordercase values and fix the docs again. Fixes #533... + Original commit message from CVS: + Patch by: Bernard B <b-gnome at largestprime dot net> + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_compare_seqnum): + Fix seqnum compare function for bordercase values and fix the docs + again. Fixes #533075. + * tests/check/libs/rtp.c: (GST_START_TEST), (rtp_suite): + Add a testcase for seqnum compare function. + +2008-05-14 10:58:52 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/adder/gstadder.c: Correctly declare the supported endianness on the pad templates and check for correct endiannes... + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_setcaps), + (gst_adder_class_init): + Correctly declare the supported endianness on the pad templates + and check for correct endianness in the set caps function. Adder + only supports native endianness. + Also use gst_element_class_set_details_simple(). + +2008-05-14 09:12:10 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Better debug logging in port value handling. Merging separate port value loops into one. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Better debug logging in port value handling. Merging separate port + value loops into one. + +2008-05-13 16:02:19 +0000 Hannes Bistry <hannesb@gmx.de> + + gst/tcp/: Fix regression in clientsrc because we did not add the fd to the poll set anymore. Fixes #532364. + Original commit message from CVS: + Patch by: Hannes Bistry <hannesb at gmx dot de> + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_start): + * gst/tcp/gsttcpserversink.c: + (gst_tcp_server_sink_handle_server_read), + (gst_tcp_server_sink_handle_wait), (gst_tcp_server_sink_init_send): + Fix regression in clientsrc because we did not add the fd to the poll + set anymore. Fixes #532364. + Do some cleanups here and there. + +2008-05-13 13:04:24 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/playback/: Use correct marshallers. GstCaps are a boxed type and no GObject subclass. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init): + * gst/playback/gstplay-marshal.list: + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init): + Use correct marshallers. GstCaps are a boxed type and no GObject + subclass. + +2008-05-13 11:37:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstrtsp.def: Add gst_rtsp_connection_(set|clear)_auth_param() to the exported symbols. + Original commit message from CVS: + * win32/common/libgstrtsp.def: + Add gst_rtsp_connection_(set|clear)_auth_param() to the exported + symbols. + +2008-05-13 10:59:49 +0000 Sjoerd Simons <sjoerd@luon.net> + + tests/check/elements/audioresample.c: Add unit test for the latest basetransform negotiation changes. + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon dot net> + * tests/check/elements/audioresample.c: + (live_switch_alloc_only_48000), (live_switch_get_sink_caps), + (live_switch_push), (GST_START_TEST): + Add unit test for the latest basetransform negotiation changes. + See bug #526768. + +2008-05-13 09:14:44 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/ffmpegcolorspace/imgconvert.c: Fix nv12<->nv21 conversion if stride is larger than width. + Original commit message from CVS: + * gst/ffmpegcolorspace/imgconvert.c: (nv12_to_nv21): + Fix nv12<->nv21 conversion if stride is larger than width. + +2008-05-13 07:28:21 +0000 j^ <j@oil21.org> + + ext/ogg/gstoggdemux.*: Parse presentation time from skeleton streams and use it as offset for the timestamps. Fixes b... + Original commit message from CVS: + Patch by: j^ <j at oil21 dot org> + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_parse_skeleton_fishead), + (gst_ogg_pad_parse_skeleton_fisbone): + * ext/ogg/gstoggdemux.h: + Parse presentation time from skeleton streams and use it as offset + for the timestamps. Fixes bug #530068. + +2008-05-12 08:45:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Revert previous patch that attempted to more accurately calculate the initial ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render), (gst_base_audio_sink_async_play): + Revert previous patch that attempted to more accurately calculate the + initial offset between master and slave clock. The best thing we can do + in general is take the time of both clocks as the diff since we don't + know when the actual preroll happened. + +2008-05-11 19:52:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/install-plugins.c: Fix docs: type and missing word. + Original commit message from CVS: + * gst-libs/gst/pbutils/install-plugins.c: + Fix docs: type and missing word. + +2008-05-10 20:16:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Don't do lots of 4-byte peeks, but use the 'new' data scan helper for this inste... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (h264_video_type_find): + Don't do lots of 4-byte peeks, but use the 'new' data scan helper + for this instead; don't check if we've found enough markers after + each and every step, it's enough to do that only if we've actually + found a new marker. + Embed a G_UNLIKELY into the IS_MPEG_HEADER macro. + +2008-05-10 18:19:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Move scan helper thingy to the beginning of the file so we can use it in other t... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + (DATA_SCAN_CTX_CHUNK_SIZE), (DataScanCtx), (data_scan_ctx_advance), + (data_scan_ctx_ensure_data), (GST_MPEGVID_TYPEFIND_TRY_SYNC), + (mpeg_video_stream_type_find): + Move scan helper thingy to the beginning of the file so we can use + it in other typefind functions. Rename it to something more + generic. Also improve handling of things towards the end of the + typefind data: peek as much as we can if we know the size of the + data, rather than just min_size. + +2008-05-09 21:42:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Document the GstTuner and GstColorBalance interfaces, and some other random API functions that needed it. 70% symbol ... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/colorbalance.c: + * gst-libs/gst/interfaces/colorbalance.h: + * gst-libs/gst/interfaces/colorbalancechannel.c: + * gst-libs/gst/interfaces/colorbalancechannel.h: + * gst-libs/gst/interfaces/tuner.c: + * gst-libs/gst/interfaces/tunerchannel.c: + * gst-libs/gst/interfaces/tunerchannel.h: + * gst-libs/gst/interfaces/tunernorm.c: + * gst-libs/gst/interfaces/tunernorm.h: + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + Document the GstTuner and GstColorBalance interfaces, and some + other random API functions that needed it. 70% symbol coverage, woo. + +2008-05-09 16:38:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Choose to allocate one less segment but require one additional segment as latency. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_acquire): + Choose to allocate one less segment but require one additional segment + as latency. + * gst-libs/gst/audio/gstaudiosrc.c: (gst_audioringbuffer_acquire): + No need to increment the number of segments in the source. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_time), (clock_convert_external), + (gst_base_audio_sink_resample_slaving), + (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_none_slaving), (gst_base_audio_sink_render), + (gst_base_audio_sink_async_play): + Remove adding latency when returning the internal time while subtracting + it again when we use the value a little later. + When calculating the end timestamp, we are making a rounding error + with the current algorithm. Ensure that we don't accumulate these + rounding errors when aligning samples by not resampling at all if we + don't need to. Fixes #419351. + Make the initial calibration of the clock slaving a little more + predictable and accurate. Also handle the case where we don't do + clock slaving. + +2008-05-09 08:34:52 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/ffmpegcolorspace/: Add conversions from/to NV12 and NV21 and conversions between those two formats. Fixes bug #53... + Original commit message from CVS: + Based on a patch by: + Björn Benderius <bjoern dot benderius at axis dot com> + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (nv12_to_nv21): + * gst/ffmpegcolorspace/imgconvert_template.h: + Add conversions from/to NV12 and NV21 and conversions between those + two formats. Fixes bug #532166. + +2008-05-08 17:35:44 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Abort the h264 typefinding as soon as _peek() doesn't return anything, which hap... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (h264_video_type_find): + Abort the h264 typefinding as soon as _peek() doesn't return anything, + which happens for example with files smaller than 128kb. + +2008-05-08 14:46:27 +0000 Wouter Cloetens <zombie@e2big.org> + + gst-libs/gst/rtsp/: Add Digest authorization support for RTSP connections. See #532065. + Original commit message from CVS: + Patch by: Wouter Cloetens <zombie at e2big dot org> + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_create), (md5_digest_to_hex_string), + (auth_digest_compute_hex_urp), (auth_digest_compute_response), + (add_auth_header), (gst_rtsp_connection_free), + (gst_rtsp_connection_set_auth), (str_case_hash), (str_case_equal), + (gst_rtsp_connection_set_auth_param), + (gst_rtsp_connection_clear_auth_params): + * gst-libs/gst/rtsp/gstrtspconnection.h: + Add Digest authorization support for RTSP connections. See #532065. + * gst-libs/gst/rtsp/md5.c: + * gst-libs/gst/rtsp/md5.h: + Yeap, another md5 implementation until we can depend on a glib that has + support for it. + +2008-05-08 06:20:42 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/audioresample/gstaudioresample.c: Let audioresample use the buffer allocation of basetransform instead of it's ow... + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon dot net> + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init): + Let audioresample use the buffer allocation of basetransform instead + of it's own stuff. + * tests/check/elements/audioresample.c: (alloc_only_48000), + (GST_START_TEST), (audioresample_suite): + Add unit test for the recent basetransform bugfix, where upstream + changes caps to something that can't be passed through anymore. + +2008-05-07 19:50:27 +0000 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + + win32/common/config.h.in: Don't define GST_FUNCTION, if GLib supports MSVC we'd much rather use the real thing than h... + Original commit message from CVS: + * win32/common/config.h.in: + Don't define GST_FUNCTION, if GLib supports MSVC we'd much rather + use the real thing than having "???" unconditionally. + +2008-05-07 15:47:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Report the latency with the new seglatency parameter. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_query): + Report the latency with the new seglatency parameter. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_debug_spec_buff), (gst_ring_buffer_parse_caps), + (gst_ring_buffer_acquire): + * gst-libs/gst/audio/gstringbuffer.h: + Add new field to the ringbufferspec to specify the expected latency + between the underlying device read/write pointer, this is needed + when writing sinks that sit a little closer to the hardware. + Add some more docs for other fields. + +2008-05-07 10:38:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/: Add marshal.list, make it compile and add to cvsignore. + Original commit message from CVS: + * gst-libs/gst/app/.cvsignore: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/app/gstapp-marshal.list: + Add marshal.list, make it compile and add to cvsignore. + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_dispose), + (gst_app_sink_stop): + Small cleanups. + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_class_init), + (gst_app_src_init), (gst_app_src_set_property), + (gst_app_src_get_property), (gst_app_src_unlock), + (gst_app_src_unlock_stop), (gst_app_src_start), (gst_app_src_stop), + (gst_app_src_create), (gst_app_src_set_caps), + (gst_app_src_get_caps), (gst_app_src_set_size), + (gst_app_src_get_size), (gst_app_src_set_seekable), + (gst_app_src_get_seekable), (gst_app_src_set_max_buffers), + (gst_app_src_get_max_buffers), (gst_app_src_push_buffer), + (gst_app_src_end_of_stream): + * gst-libs/gst/app/gstappsrc.h: + Beat appsrc in shape, add signals and actions. + Add some docs. + Add properties for caps, size, seekability and max-buffers. + Fix unlock/stop code. + +2008-05-06 12:35:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/volume/gstvolume.c: Return NOT_NEGOTIATED if we didn't set a process function yet for some reason instead of cras... + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_transform_ip): + Return NOT_NEGOTIATED if we didn't set a process function yet for some + reason instead of crashing later. Might fix bug #509125. + +2008-05-06 12:12:16 +0000 Tim-Philipp Müller <tim.muller@collabora.co.uk> + + gst/audioconvert/: Add support for more than 8 channels and NONE channel layouts. For more than 8 channels no channel... + Original commit message from CVS: + Based on a patch by: Tim-Philipp Müller <tim.muller at collabora co uk> + * gst/audioconvert/audioconvert.c: (audio_convert_prepare_context): + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_parse_caps), + (structure_has_fixed_channel_positions), + (gst_audio_convert_transform_caps): + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_matrix): + Add support for more than 8 channels and NONE channel layouts. For + more than 8 channels no channel conversion is supported yet, only + format conversions are supported. Fixes bug #398033. + * tests/check/elements/audioconvert.c: (verify_convert), + (GST_START_TEST), (audioconvert_suite): + Add some unit tests by Tim for checking the NONE channel layouts + and more than 8 channels and add some more unit tests for channel + conversions. + +2008-05-06 10:16:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: When autoplugging fails, set the element back to NULL before unreffing it. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (connect_pad): + When autoplugging fails, set the element back to NULL before + unreffing it. + +2008-05-06 09:59:43 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstaudio.def: Add gst_base_audio_src_[sg]et_slave_method() to the exported symbols. + Original commit message from CVS: + * win32/common/libgstaudio.def: + Add gst_base_audio_src_[sg]et_slave_method() to the exported + symbols. + +2008-05-05 12:33:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/subparse/samiparse.c: Remove trailing, leading and double whitespaces. + Original commit message from CVS: + * gst/subparse/samiparse.c: (handle_start_sync), + (end_sami_element), (characters_sami): + Remove trailing, leading and double whitespaces. + Correctly timestamp buffers and output the last buffer too. + * tests/check/elements/subparse.c: (GST_START_TEST), + (subparse_suite): + Add a simple unit test for SAMI parsing. + +2008-05-05 11:14:48 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: Only output characters inside the "sync" elements. There could be other elements like "styl... + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian dot net> + * gst/subparse/samiparse.c: (handle_start_sync), + (start_sami_element), (end_sami_element), (characters_sami), + (sami_context_reset): + Only output characters inside the "sync" elements. There could be + other elements like "style" that have some content but should + not be printed. Fixes bug #467911. + +2008-05-05 10:27:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.*: Start some docs. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_class_init), + (gst_app_sink_init), (gst_app_sink_set_property), + (gst_app_sink_get_property), (gst_app_sink_unlock_start), + (gst_app_sink_unlock_stop), (gst_app_sink_flush_unlocked), + (gst_app_sink_start), (gst_app_sink_stop), (gst_app_sink_event), + (gst_app_sink_preroll), (gst_app_sink_render), + (gst_app_sink_set_caps), (gst_app_sink_set_drop), + (gst_app_sink_get_drop): + * gst-libs/gst/app/gstappsink.h: + Start some docs. + Add property to drop buffers when the queue is filled + Fix unlocking and flushing when the queues are filled. + +2008-05-05 10:03:51 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/playback/: Allow setting -1 as current-audio to mute the current audio stream, similar to what is done for subtit... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (set_audio_mute), + (set_active_source): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (playbin_set_audio_mute): + Allow setting -1 as current-audio to mute the current audio stream, + similar to what is done for subtitles. Fixes bug #342294. + +2008-05-05 07:41:03 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/pbutils/descriptions.c: It's SorensOn and not SorensEn. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (formats): + It's SorensOn and not SorensEn. + +2008-05-04 15:23:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/descriptions.c: Fix description of video/x-flash-video. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (formats): + Fix description of video/x-flash-video. + +2008-05-04 15:02:20 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Remove some unused code. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func): + * gst-libs/gst/audio/gstaudiosrc.c: (audioringbuffer_thread_func): + * gst/tcp/gsttcp.c: (gst_tcp_socket_write): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_get_fps_list): + Remove some unused code. + * gst/audioconvert/gstaudioquantize.c: + (gst_audio_quantize_free_noise_shaping): + Don't return before freeing the noise shaping history. + +2008-05-03 16:00:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/subparse.c: Add unit test for the tmplayer variant from bug #530962. + Original commit message from CVS: + * tests/check/elements/subparse.c: (do_test), + (test_tmplayer_style3b), (subparse_suite): + Add unit test for the tmplayer variant from bug #530962. + +2008-05-03 15:45:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/: Fix parsing of tmplayer subtitle variant where every single line contains text and there isn't an empt... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (handle_buffer), + (gst_sub_parse_sink_event): + * gst/subparse/tmplayerparse.c: (tmplayer_process_buffer), + (tmplayer_parse_line): + Fix parsing of tmplayer subtitle variant where every single line contains + text and there isn't an empty line after each line to determine the + duration (#530962). Improve EOS handling for tmplayer subtitles a bit by + making sure that we push out the last line of text without a duration if + there's still text left in the buffer at the end. + +2008-05-03 15:39:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Fix detection of discontinuities based on the buffer offset (doesn't work so well if no b... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (feed_textbuf): + Fix detection of discontinuities based on the buffer offset (doesn't work + so well if no buffer offset is set) and also check for the DISCONT buffer + flag. This keeps the parser state from being reset after each buffer in + the unit test. + +2008-05-03 12:09:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Further fine-tuning: don't absolutely require sequence or GOP headers but adjust... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg_video_stream_type_find): + Further fine-tuning: don't absolutely require sequence or GOP headers + (as introduced in the previous commit), but adjust the typefind + probabilities returned accordingly if we don't see them. Also make sure + picture header and first slice are somewhat close to each other (which + is not perfect but still better than requiring a fixed offset or having + no limit at all). + +2008-05-02 12:13:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Rename the setcaps/getcaps function internally to make it clear that they are c... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_init), + (gst_basertppayload_sink_setcaps), + (gst_basertppayload_sink_getcaps): + Rename the setcaps/getcaps function internally to make it clear that + they are called for the sink pad. + +2008-05-02 12:11:07 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Catch packet-lost events from the jitterbuffer and convert them into a vmetho... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_class_init), + (gst_base_rtp_depayload_handle_sink_event), (create_segment_event), + (gst_base_rtp_depayload_packet_lost), + (gst_base_rtp_depayload_set_gst_timestamp): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Catch packet-lost events from the jitterbuffer and convert them into a + vmethod call (lost-packet) so that depayloaders can do something smart. + Also add a default packet-lost function that sends out a segment update + to the decoders. + +2008-05-02 11:13:05 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/: Also include config.h when relying on defines from it. Fixes the build. Its been a please to serve :) + Original commit message from CVS: + * gst/playback/test4.c: + * gst/playback/test5.c: + * gst/playback/test6.c: + * gst/playback/test7.c: + Also include config.h when relying on defines from it. Fixes the + build. Its been a please to serve :) + +2008-05-02 10:54:51 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + * ChangeLog: + * gst/videotestsrc/videotestsrc.c: + Add support for NV12 and NV21 in videotestsrc + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c (paint_setup_NV12), + (paint_setup_NV21), (paint_hline_NV12_NV21): + Add support for NV12 and NV21 in videotestsrc + +2008-05-02 10:02:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/videoscale/: Support 1x1 images as input and output as for example the BBC HQ new streams have 1x1 GIFs in the pl... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/vs_4tap.c: (vs_image_scale_4tap_Y): + * gst/videoscale/vs_image.c: (vs_image_scale_nearest_RGBA), + (vs_image_scale_linear_RGBA), (vs_image_scale_nearest_RGB), + (vs_image_scale_linear_RGB), (vs_image_scale_nearest_YUYV), + (vs_image_scale_linear_YUYV), (vs_image_scale_nearest_UYVY), + (vs_image_scale_linear_UYVY), (vs_image_scale_nearest_Y), + (vs_image_scale_linear_Y), (vs_image_scale_nearest_RGB565), + (vs_image_scale_linear_RGB565), (vs_image_scale_nearest_RGB555), + (vs_image_scale_linear_RGB555): + Support 1x1 images as input and output as for example the BBC HQ new + streams have 1x1 GIFs in the playlists for some reason. + +2008-05-01 19:11:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: If we can't activate one of the decoders we plugged in (such as, say, musepackdec) for s... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (free_pad_probe_for_element), + (try_to_link_1): + If we can't activate one of the decoders we plugged in (such as, + say, musepackdec) for some reason (it might not support push mode, + for example), remove any pad probes that close_pad_link() might + have set up. This makes sure we later don't try to remove a probe + for a pad that doesn't exist any longer, and avoids nast warnings + and probably other things too. + +2008-04-30 20:54:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Rework mpeg video stream typefinding a bit more: make sure sequence, + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + (mpeg_video_stream_ctx_ensure_data), (mpeg_video_stream_type_find), + (plugin_init): + Rework mpeg video stream typefinding a bit more: make sure sequence, + GOP, picture and slice headers appear in the order they should and + that we've in fact at least had one of each; fix picture header + detection; decouple picture and slice header check - don't assume + they're at a fixed offset, there may be extra data in between. Also, + announce varying degrees of probability depending on what we found + exactly (multiple pictures, at least one picture, just sequence and + GOP headers). Finally, in _ensure_data(), take into account that we + might be typefinding smaller amounts of data, such as the first + buffer of a stream, so fall back to the minimum size needed as long + as that's available, instead of erroring out if there's less than + 2kB of data. Fixes #526173. Conveniently also doesn't recognise the + fuzzed file from #399342 as valid. + +2008-04-30 17:06:45 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Cool kids don't divide by zero. + Original commit message from CVS: + * ext/theora/theoradec.c: + Cool kids don't divide by zero. + Treat PAR of x:0 as 1:1. + Fixes #530719. + +2008-04-30 14:37:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Refactor a bit: use context structure to track parsing offset and size of availa... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (MpegVideoStreamCtx), + (mpeg_video_stream_ctx_advance), (mpeg_video_stream_ctx_ensure_data), + (mpeg_video_stream_type_find): + Refactor a bit: use context structure to track parsing offset and size of + available data and make the code a bit clearer. Fixes bad memory access + in #356937. + +2008-04-28 22:18:49 +0000 Michael Smith <msmith@xiph.org> + + gst/: Include stdlib.h and unistd.h only if the appropriate HAVE_*_H macro is defined. + Original commit message from CVS: + * gst/playback/test4.c: + * gst/playback/test5.c: + * gst/playback/test6.c: + * gst/tcp/gstmultifdsink.c: + Include stdlib.h and unistd.h only if the appropriate HAVE_*_H macro + is defined. + +2008-04-28 08:51:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.h: Clarify some docs. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.h: + Clarify some docs. + * gst-libs/gst/audio/gstbaseaudiosrc.c: (slave_method_get_type), + (gst_base_audio_src_class_init), (gst_base_audio_src_init), + (gst_base_audio_src_set_slave_method), + (gst_base_audio_src_get_slave_method), + (gst_base_audio_src_set_property), + (gst_base_audio_src_get_property), (gst_base_audio_src_create): + * gst-libs/gst/audio/gstbaseaudiosrc.h: + Add property and methods for selecting the clock slave method in the + source, like in the sink. + We only implement "none" and "re-timestamp" for now. + API: gst_base_audio_src_set_slave_method() + API: gst_base_audio_src_get_slave_method() + +2008-04-25 18:18:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.*: Add more docs. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_class_init), + (gst_app_sink_init), (gst_app_sink_set_property), + (gst_app_sink_get_property), (gst_app_sink_event), + (gst_app_sink_preroll), (gst_app_sink_render), + (gst_app_sink_set_emit_signals), (gst_app_sink_get_emit_signals), + (gst_app_sink_set_max_buffers), (gst_app_sink_get_max_buffers), + (gst_app_sink_pull_buffer): + * gst-libs/gst/app/gstappsink.h: + Add more docs. + Add signals for when preroll and render buffers are available. + Add property to control signal emission. + Add property to control the max queue size. + +2008-04-25 07:37:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.c: Fix the docs about the seqnum compare function, it returns a difference. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + Fix the docs about the seqnum compare function, it returns a difference. + +2008-04-24 09:27:35 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/alsa/gstalsadeviceprobe.c: Don't return before freeing up the allocated structures. + Original commit message from CVS: + * ext/alsa/gstalsadeviceprobe.c: + (gst_alsa_get_device_list): Don't return before freeing up + the allocated structures. + +2008-04-24 08:19:35 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstplaybin.c: Remove obsolete streaminfo code and fix a leak. Fixes #529546 + Original commit message from CVS: + * gst/playback/gstplaybin.c: + Remove obsolete streaminfo code and fix a leak. Fixes #529546 + +2008-04-23 13:50:34 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/ogg/gstoggdemux.c: Revert the event part, that should not go in. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: + Revert the event part, that should not go in. + +2008-04-23 13:45:29 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/ogg/gstoggdemux.c: Don't leak GstPluginFeatures when filtering. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: + Don't leak GstPluginFeatures when filtering. + +2008-04-23 08:58:42 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Add some logging for cases when grabbing the xv failed. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Add some logging for cases when grabbing the xv failed. + +2008-04-22 06:18:04 +0000 David Schleef <ds@schleef.org> + + ext/ogg/gstoggmux.c: Update Ogg/Dirac muxing. Removes the weird "KW-DIRAC" bos packet. Should conform to what we cu... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + Update Ogg/Dirac muxing. Removes the weird "KW-DIRAC" bos + packet. Should conform to what we currently think is the + final Ogg/Dirac muxing spec. + +2008-04-22 06:13:43 +0000 David Schleef <ds@schleef.org> + + sys/xvimage/xvimagesink.c: Fix typo that causes the overlay keying color to bright green on a 16-bit display. Dark g... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Fix typo that causes the overlay keying color to bright green + on a 16-bit display. Dark grey good. Bright green bad. + +2008-04-21 13:47:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/gnomevfs/gstgnomevfsuri.c: Add FIXME comment about using uri-list for source and sink. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfsuri.c: + Add FIXME comment about using uri-list for source and sink. + +2008-04-20 11:42:37 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/ogg/gstogmparse.c: GST_TYPE_FRACTION contains gints so correctly cast gint64 arguments to vaargs functions to gin... + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_stream_header): + GST_TYPE_FRACTION contains gints so correctly cast gint64 arguments to + vaargs functions to gint. Otherwise the fractions will get 0 set + instead of the correct value on big endian systems. Fixes bug #529018. + +2008-04-20 10:17:23 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gnomevfs/: Get the list of supported URI schemes in a threadsafe way and use the same list for the source and sink. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.c: + (gst_gnome_vfs_sink_uri_get_protocols): + * ext/gnomevfs/gstgnomevfssrc.c: + (gst_gnome_vfs_src_uri_get_protocols): + * ext/gnomevfs/gstgnomevfsuri.c: (_internal_get_supported_uris), + (gst_gnomevfs_get_supported_uris): + Get the list of supported URI schemes in a threadsafe way and use the + same list for the source and sink. + +2008-04-20 10:11:54 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Don't generate a new supported protocols list on each call but cache it. It's supposed to be static... + Original commit message from CVS: + * ext/gio/gstgio.c: (_internal_get_supported_protocols), + (gst_gio_get_supported_protocols): + Don't generate a new supported protocols list on each call but cache + it. It's supposed to be static anyway, this way we only leak it once + per process. + * ext/gio/gstgiosink.c: (gst_gio_sink_base_init), + (gst_gio_sink_class_init), (gst_gio_sink_finalize), + (gst_gio_sink_set_property), (gst_gio_sink_get_property), + (gst_gio_sink_start): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.c: (gst_gio_src_base_init), + (gst_gio_src_class_init), (gst_gio_src_finalize), + (gst_gio_src_set_property), (gst_gio_src_get_property), + (gst_gio_src_start): + * ext/gio/gstgiosrc.h: + API: Add "file" properties where one can set a GFile as source/destination. + Add locking to the properties and use gst_element_class_set_details_simple() + instead of a static GstElementDetails struct. + +2008-04-19 20:06:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add "mpp" and "mp+" as possible extensions for MusePack files. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (musepack_type_find), + (plugin_init): + Add "mpp" and "mp+" as possible extensions for MusePack files. + Add typefinding for MusePack StreamVersion 8 files and include the + stream version in the caps. + +2008-04-19 16:33:24 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/rtp/gstrtppayloads.c: Use g_ascii_strcasecmp() instead of the deprecated g_strcasecmp(). + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtppayloads.c: + (gst_rtp_payload_info_for_name): + Use g_ascii_strcasecmp() instead of the deprecated g_strcasecmp(). + +2008-04-18 17:10:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Bump Gtk+ requirement to 2.12.0 for gtk_range_set_fill_level (NB: this only affects compilation of some... + Original commit message from CVS: + * configure.ac: + Bump Gtk+ requirement to 2.12.0 for gtk_range_set_fill_level + (NB: this only affects compilation of some of the examples). + Remove some configure.ac cruft that's not needed any longer. + +2008-04-18 14:54:01 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/gdp/gstgdpdepay.c: Don't validate the payload if there isn't any. + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain): + Don't validate the payload if there isn't any. + Fixes #525915 + +2008-04-17 07:33:46 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/gstringbuffer.c: Use g_atomic_int_set() instead of gst_atomic_int_set(). + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_may_start): + Use g_atomic_int_set() instead of gst_atomic_int_set(). + +2008-04-17 07:29:28 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Return NULL instead of a gchar * array with one NULL element if we don't get any supported URI sche... + Original commit message from CVS: + * ext/gio/gstgio.c: (gst_gio_get_supported_protocols): + Return NULL instead of a gchar * array with one NULL element if we + don't get any supported URI schemes from GIO. + +2008-04-15 19:06:00 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audiotestsrc/gstaudiotestsrc.c: Remove cpp style commented old code. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + Remove cpp style commented old code. + +2008-04-15 19:02:10 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstdecodebin2.c: Fix signal docs. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + Fix signal docs. + +2008-04-14 17:58:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Fix textoverlay unit test again by making the supposed default value for the wait-text pr... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init), + (gst_text_overlay_init): + Fix textoverlay unit test again by making the supposed default + value for the wait-text property the actual default value. + Also fix Since: tag for new property. + +2008-04-11 17:13:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/video/video.c: Add guards to these functions to ensure sane input values. + Original commit message from CVS: + * gst-libs/gst/video/video.c: (gst_video_format_new_caps), + (gst_video_format_to_fourcc), (gst_video_format_get_row_stride), + (gst_video_format_get_pixel_stride), + (gst_video_format_get_component_width), + (gst_video_format_get_component_height), + (gst_video_format_get_component_offset), (gst_video_format_get_size), + (gst_video_format_convert): + Add guards to these functions to ensure sane input values. + * tests/check/libs/video.c: + Fix unit test not to create caps with width=0 and height=0. + +2008-04-11 01:25:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/design/draft-keyframe-force.txt: Fix typo. + Original commit message from CVS: + * docs/design/draft-keyframe-force.txt: + Fix typo. + * gst/playback/gstqueue2.c: (update_buffering), + (gst_queue_handle_src_query): + Set buffering mode in the messages. + Set buffering percent in the query. + * tests/examples/seek/seek.c: (update_fill), (msg_state_changed), + (do_stream_buffering), (do_download_buffering), (msg_buffering): + Do some more fancy things based on the buffering method in use. + +2008-04-09 21:42:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add basic download reports to seek using the new buffering API. + Original commit message from CVS: + * tests/examples/seek/seek.c: (update_fill), (set_update_fill), + (play_cb), (pause_cb), (stop_cb), (msg_state_changed), + (msg_buffering), (main): + Add basic download reports to seek using the new buffering API. + +2008-04-09 21:40:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Include extra buffering stats in the buffering message. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (update_buffering), + (gst_queue_close_temp_location_file), (gst_queue_handle_src_query), + (gst_queue_src_checkgetrange_function): + Include extra buffering stats in the buffering message. + Implement BUFFERING query. + * gst/playback/gsturidecodebin.c: (do_async_start), + (do_async_done), (type_found), (setup_streaming), (setup_source), + (gst_uri_decode_bin_change_state): + Only add decodebin2 when the type is found in streaming mode. + Make uridecodebin async to PAUSED even when we don't have decodebin2 + added yet. + +2008-04-09 08:38:19 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Filter cdda from the supported URI schemes. We can't support musicbrainz tags and everything else o... + Original commit message from CVS: + * ext/gio/gstgio.c: (gst_gio_get_supported_protocols): + Filter cdda from the supported URI schemes. We can't support + musicbrainz tags and everything else one expects from a cdda source + with GIO. Fixes bug #526794. + +2008-04-07 22:37:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * sys/xvimage/xvimagesink.c: + Fix calculation of 'expected size' for YV12 buffers. + Original commit message from CVS: + 2008-04-07 Jan Schmidt <jan.schmidt@sun.com> + * sys/xvimage/xvimagesink.c (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_buffer_alloc): + Fix calculation of 'expected size' for YV12 buffers. + Be a little more verbose in the debug output for buffer-alloc'ed + buffers which turn out to have the wrong size. + +2008-04-07 22:26:50 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + Fix calculation of 'expected size' for YV12 buffers. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_buffer_alloc): + Fix calculation of 'expected size' for YV12 buffers. + Be a little more verbose in the debug output for buffer-alloc'ed + buffers which turn out to have the wrong size. + +2008-04-07 10:50:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + Merge other changes from 0.10.19 release branch. + Original commit message from CVS: + * NEWS: + * RELEASE: + * gst-plugins-base.doap: + Merge other changes from 0.10.19 release branch. + +2008-04-06 20:16:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: Work around missing bits of thread-safety on older GLibs some more to avoid assertions when starting up multipl... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init): + * gst/playback/gstplayback.c: (plugin_init): + * gst/volume/gstvolume.c: (plugin_init): + Work around missing bits of thread-safety on older GLibs some + more to avoid assertions when starting up multiple playbin + objects concurrently (see #512382). + +2008-04-06 17:19:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/missing-plugins.c: Remove some more fields. + Original commit message from CVS: + * gst-libs/gst/pbutils/missing-plugins.c: (copy_and_clean_caps): + Remove some more fields. + +2008-04-06 08:56:07 +0000 Damien Lespiau <damien.lespiau@gmail.com> + + configure.ac: Actually build dlls when cross-compiling with mingw32. + Original commit message from CVS: + Patch by: Damien Lespiau <damien dot lespiau at gmail dot com> + * configure.ac: + Actually build dlls when cross-compiling with mingw32. + Fixes bug #526247. + +2008-04-03 23:01:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Bump version to 0.10.19.1 after the unplanned 0.10.19 release. + Original commit message from CVS: + * configure.ac: + Bump version to 0.10.19.1 after the unplanned 0.10.19 release. + +2008-04-03 16:10:53 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add statusbar. + Original commit message from CVS: + * tests/examples/seek/seek.c: (play_cb), (pause_cb), (stop_cb), + (msg_buffering), (connect_bus_signals), (main): + Add statusbar. + Add buffering support with feedback in the statusbar. + +2008-04-03 15:58:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggmux.c: Fix sample pipeline description. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + Fix sample pipeline description. + +2008-04-03 14:58:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/plugins/: Add playbin, playbin2, decodebin, decodebin2, uridecodebin and oggmux + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-overrides.txt: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + Add playbin, playbin2, decodebin, decodebin2, uridecodebin and oggmux + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Update introspection data. + * ext/ogg/gstoggmux.c: + Document oggmux. + * gst/playback/gstdecodebin2.c: + Don't use gtk-doc style comment start for private stuff, but make it + formatted like this for consistency. + +2008-04-03 12:16:04 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Remove fakesink hack, we can now implement this more elegantly. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (gst_decode_bin_dispose), + (gst_decode_bin_set_sink_caps), (gst_decode_bin_get_sink_caps), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (analyze_new_pad), (connect_pad), (expose_pad), + (gst_decode_group_new), (gst_decode_group_control_demuxer_pad), + (gst_decode_group_expose), (gst_decode_group_free), + (do_async_start), (do_async_done), (gst_decode_bin_change_state): + Remove fakesink hack, we can now implement this more elegantly. + Added property to bypass typefinding. + Removed underrun callback and demuxer pad probe, we now use the srcpad + probe to expose groups. + API::sink-caps property + * gst/playback/gstplaybin2.c: (no_more_pads_cb): + Guard against multiple emissions of the no_more_pads signal, which + happens when we are dealing with chained oggs. + * gst/playback/gsturidecodebin.c: (remove_decoders), + (make_decoder), (type_found), (setup_streaming), (source_new_pad), + (setup_source): + For streams, use our own typefind element and plug our queue after it. + We will need this to determine the type of buffering to use for the + queue soon. + +2008-04-03 10:37:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Guard against over and underflows because of clock slaving. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_skew_slaving), (gst_base_audio_sink_render): + Guard against over and underflows because of clock slaving. + When we are using our own clock, still compensate for any calibrations + that we might have done to our clock. + +2008-04-03 10:22:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Don't try to do anything fancy with the return code from pushing an event, it does not have e... + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_handle_type_packet), + (theora_dec_chain): + Don't try to do anything fancy with the return code from pushing an + event, it does not have enough information to turn it into a + GST_FLOW_ERROR. + +2008-04-03 10:19:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Add small debug line. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_reset), + (gst_ogg_demux_chain_elem_pad): + Add small debug line. + Pass return code from the internal decoder instead of the too generic + GST_FLOW_ERROR. + +2008-04-03 06:39:27 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/cdda/: Use GLib's base64 implementation instead of our own. + Original commit message from CVS: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/cdda/base64.c: + * gst-libs/gst/cdda/base64.h: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cddabasesrc_calculate_musicbrainz_discid): + Use GLib's base64 implementation instead of our own. + +2008-04-02 15:41:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Refix oggdemux, we only have a problem if we failed to find a chain and we are not EOF. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_activate_chain), + (gst_ogg_demux_read_chain): + Refix oggdemux, we only have a problem if we failed to find a chain and + we are not EOF. + +2008-04-02 15:07:01 +0000 Victor STINNER <victor.stinner@haypocalc.com> + + ext/ogg/gstoggdemux.c: When we fail to find a BOS page and we and up with no chain, error out properly instead of seg... + Original commit message from CVS: + Patch by: Victor STINNER <victor dot stinner at haypocalc dot com> + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_activate_chain), + (gst_ogg_demux_read_chain): + When we fail to find a BOS page and we and up with no chain, error out + properly instead of segfaulting. Fixes #525665. + +2008-04-02 14:58:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: The new-pad-group sequence is add-pads, no-more-pads, add-pads, no-more-pads... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_activate_chain), + (gst_ogg_demux_read_chain), (gst_ogg_demux_handle_page): + The new-pad-group sequence is add-pads, no-more-pads, add-pads, + no-more-pads... + +2008-04-02 11:08:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Update the estimated input data when we push out a buffer. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (update_out_rates), + (gst_queue_open_temp_location_file), + (gst_queue_close_temp_location_file), (gst_queue_handle_src_event), + (gst_queue_handle_src_query), (gst_queue_set_property): + Update the estimated input data when we push out a buffer. + Add some debug info about the temp file. + Only forward src events when we are not using a temp file. + Don't block the duration query, we need to find something better. + Don't leak the temp filename. + +2008-04-01 14:01:14 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Require GLib 2.12 and liboil 0.3.14. + Original commit message from CVS: + * configure.ac: + Require GLib 2.12 and liboil 0.3.14. + * gst/volume/gstvolume.c: (volume_process_double): + Unconditionally use liboil 0.3.14 function. + +2008-03-31 16:08:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: ms-gsm can have arbitrarty sample rates. See #481354. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + ms-gsm can have arbitrarty sample rates. See #481354. + +2008-03-28 16:22:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: MP4S is generic MPEG-4, not a microsoft variant. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + MP4S is generic MPEG-4, not a microsoft variant. + +2008-03-27 15:26:38 +0000 Michael Smith <msmith@xiph.org> + + gst/gdp/gstgdpdepay.c: Check the body CRC (if set) when depayloading. + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain): + Check the body CRC (if set) when depayloading. + Fixes #522401. + +2008-03-24 17:45:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Fix Since: version for new property. + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init): + Fix Since: version for new property. + +2008-03-24 16:40:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Don't error when poll_wait returns EAGAIN. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect), (gst_rtsp_connection_write), + (gst_rtsp_connection_read_internal), (gst_rtsp_connection_poll): + Don't error when poll_wait returns EAGAIN. + +2008-03-24 14:08:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: The queue is never filled when there are no buffers in the queue at all. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_is_filled): + The queue is never filled when there are no buffers in the queue at all. + Fixes #523993. + +2008-03-24 12:26:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Update some docs. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (init_group), (free_group), (gst_play_bin_init), + (gst_play_bin_finalize), (gst_play_bin_set_uri), + (gst_play_bin_set_suburi), (gst_play_bin_get_video_tags), + (gst_play_bin_get_audio_tags), (gst_play_bin_get_text_tags), + (gst_play_bin_set_current_video_stream), + (gst_play_bin_set_current_audio_stream), + (gst_play_bin_set_current_text_stream), + (gst_play_bin_set_encoding), (gst_play_bin_set_property), + (gst_play_bin_get_property), (pad_added_cb), (pad_removed_cb), + (no_more_pads_cb), (perform_eos), (autoplug_select_cb), + (activate_group), (deactivate_group), (setup_next_source), + (save_current_group), (gst_play_bin_change_state): + Update some docs. + Add new locks and conds to protect pipeline creation and group + switching. + Implement the sub-uri property. + Keep track of pending uridecodebin creation and configure the output + pipeline after all streams are configured. + Propagate subtitle encoding to the uridecodebins. + Implement getting the video/audio/visualisation elements. + Use input-selector for stream switching. + If we are asked to do visualisation, prefer to autoplug raw sinks + instead of sinks that accept encoded data. + +2008-03-24 12:15:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.*: Add methods to get audio/video/vis elements. + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gst_play_sink_init), (gst_play_sink_dispose), + (gst_play_sink_set_video_sink), (gst_play_sink_get_video_sink), + (gst_play_sink_set_audio_sink), (gst_play_sink_get_audio_sink), + (gst_play_sink_vis_unblocked), (gst_play_sink_vis_blocked), + (gst_play_sink_set_vis_plugin), (gst_play_sink_get_vis_plugin), + (gst_play_sink_set_volume), (gst_play_sink_get_volume), + (gst_play_sink_set_mute), (gen_video_chain), (gen_text_chain), + (gen_audio_chain), (gen_vis_chain), (gst_play_sink_reconfigure), + (gst_play_sink_set_font_desc), (gst_play_sink_get_font_desc), + (gst_play_sink_send_event_to_sink), (gst_play_sink_change_state): + * gst/playback/gstplaysink.h: + Add methods to get audio/video/vis elements. + Add methods to set the font description for the overlay. + Remove properties, we're using this element with its methods only. + Add support for subtitles. + Rearrange the locking a bit to not use the object lock for protecting + the pipeline construction. + Try to use the volume and mute property on the sink when its available. + Implement the mute option with volume when the sink does not have a mute + property. + Only add volume element when the sink has no volume property. + Only do visualisations with raw audio pads. + +2008-03-24 12:03:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/pango/gsttextoverlay.*: Add property to configure waiting for text on the textpad or not, with the default behavi... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init), + (gst_text_overlay_init), (gst_text_overlay_set_property), + (gst_text_overlay_get_property), (gst_text_overlay_src_event), + (gst_text_overlay_text_event), (gst_text_overlay_video_event), + (gst_text_overlay_text_chain), (gst_text_overlay_video_chain), + (gst_text_overlay_change_state): + * ext/pango/gsttextoverlay.h: + Add property to configure waiting for text on the textpad or not, with + the default behaviour being the old one (always wait for text before + rendering the video). This default behaviour is usually not the best one + because the text stream can very sparse and could require queueing a lot + of video. + Fix the flushing and EOS handing so that we don't mix up their meaning. + +2008-03-24 11:54:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gsturidecodebin.c: Add a readonly source property and notify. + Original commit message from CVS: + * gst/playback/gsturidecodebin.c: + (gst_uri_decode_bin_autoplug_factories), + (gst_uri_decode_bin_class_init), (gst_uri_decode_bin_init), + (gst_uri_decode_bin_finalize), (gst_uri_decode_bin_set_encoding), + (gst_uri_decode_bin_set_property), + (gst_uri_decode_bin_get_property), (no_more_pads_full), + (new_decoded_pad_cb), (gen_source_element), (remove_decoders), + (proxy_autoplug_factories_signal), (make_decoder), + (source_new_pad), (setup_source): + Add a readonly source property and notify. + Add new lock for protecting the construction of the pipeline. + Keep track of the decodebins we plugged. + Correctly proxy the autoplug signal so that it actually continues. + Proxy subtitle-encoding to the decodebins. + +2008-03-24 11:46:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Rearrange some buttons in playbin2 and make some other boxes insensitive when needed. + Original commit message from CVS: + * tests/examples/seek/seek.c: (audio_toggle_cb), (video_toggle_cb), + (text_toggle_cb), (update_streams), (main): + Rearrange some buttons in playbin2 and make some other boxes insensitive + when needed. + Add language codes to subtitle selection boxes when we gind the right + tags for the streams. + +2008-03-24 11:36:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Protect caps property with the object lock. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_dispose), + (gst_decode_bin_set_caps), (gst_decode_bin_get_caps), + (gst_decode_bin_set_subs_encoding), + (gst_decode_bin_get_subs_encoding), + (gst_decode_bin_autoplug_factories), (connect_pad), (are_raw_caps), + (deactivate_free_recursive): + Protect caps property with the object lock. + Protect encoding property with the object lock. + Keep list of elements we added that have the subtitle-encoding property. + Distribute the subtitle-encoding to all of the elements when it + changes. + +2008-03-24 11:24:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Small debug improvement. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (gst_audioringbuffer_release): + Small debug improvement. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + Fix bug in determining the sample start/stop position, we want to base + this decision on the fact that we are going forwards or backwards, not + slower or faster. This fixes some ugly resync warnings when playing at + very slow speeds. + +2008-03-23 13:41:28 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Correctly set the supported URI schemes and don't leave some schemes in the middle or at the start ... + Original commit message from CVS: + * ext/gio/gstgio.c: (gst_gio_get_supported_protocols): + Correctly set the supported URI schemes and don't leave + some schemes in the middle or at the start at NULL. + +2008-03-23 13:12:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/gdpdepay.c: Make test compile without unused function/variable warnings on PPC. + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: + Make test compile without unused function/variable warnings on PPC. + +2008-03-22 15:00:53 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Use G_PARAM_STATIC_STRINGS everywhere for GParamSpecs that use static strings (i.e. all). This gives us less memory u... + Original commit message from CVS: + * configure.ac: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_class_init): + * ext/alsa/gstalsasink.c: (gst_alsasink_class_init): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_class_init): + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_src_class_init): + * ext/gio/gstgiosink.c: (gst_gio_sink_class_init): + * ext/gio/gstgiosrc.c: (gst_gio_src_class_init): + * ext/gio/gstgiostreamsink.c: (gst_gio_stream_sink_class_init): + * ext/gio/gstgiostreamsrc.c: (gst_gio_stream_src_class_init): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_class_init): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init): + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init): + * ext/pango/gsttextrender.c: (gst_text_render_class_init): + * ext/theora/theoradec.c: (gst_theora_dec_class_init): + * ext/theora/theoraenc.c: (gst_theora_enc_class_init): + * ext/theora/theoraparse.c: (gst_theora_parse_class_init): + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_class_init): + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + (gst_audio_filter_template_class_init): + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init): + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_class_init): + * gst-libs/gst/interfaces/mixertrack.c: + (gst_mixer_track_class_init): + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_class_init): + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_class_init): + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_class_init): + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_class_init): + * gst/audioresample/gstaudioresample.c: + (gst_audioresample_class_init): + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_class_init): + * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (preroll_unlinked): + * gst/playback/gstplaybin.c: (gst_play_bin_class_init): + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init): + * gst/playback/gstplaysink.c: (gst_play_sink_class_init): + * gst/playback/gstqueue2.c: (gst_queue_class_init): + * gst/playback/gststreaminfo.c: (gst_stream_info_class_init): + * gst/playback/gststreamselector.c: (gst_selector_pad_class_init), + (gst_stream_selector_class_init): + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init): + * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init): + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_class_init): + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_class_init): + * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_class_init): + * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_class_init): + * gst/videorate/gstvideorate.c: (gst_video_rate_class_init): + * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init): + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_class_init): + * gst/volume/gstvolume.c: (gst_volume_class_init): + * sys/v4l/gstv4lelement.c: (gst_v4lelement_class_init): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init): + * sys/ximage/ximagesink.c: (gst_ximagesink_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_class_init): + Use G_PARAM_STATIC_STRINGS everywhere for GParamSpecs that use + static strings (i.e. all). This gives us less memory usage, + fewer allocations and thus less memory defragmentation. Depend + on core CVS for this. Fixes bug #523806. + +2008-03-22 14:13:55 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Filter http and https protocols. GIO/GVfs handles them but it's impossible to implement iradio/icec... + Original commit message from CVS: + * ext/gio/gstgio.c: (gst_gio_get_supported_protocols): + Filter http and https protocols. GIO/GVfs handles them but it's + impossible to implement iradio/icecast with it. Better use + souphttpsrc or something else for this. + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_get_size): + If getting the file informations by a query fails try it with the + seek-to-end trick too. + +2008-03-21 16:46:33 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/volume/gstvolume.c: memset buffers to zero if we get a GAP buffer. We usually see a buffer as one unit so let's h... + Original commit message from CVS: + * gst/volume/gstvolume.c: (gst_volume_interface_supported), + (gst_volume_base_init), (gst_volume_class_init), + (volume_process_double), (volume_process_float), + (volume_transform_ip), (plugin_init): + memset buffers to zero if we get a GAP buffer. We usually see a + buffer as one unit so let's handle it as one and don't care about + volume changes while processing one buffer. + Also clean up some stuff a bit. + +2008-03-21 15:58:44 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Make audioconvert GAP-aware by outputting silence buffers when the input has the ... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init), + (gst_audio_convert_create_silence_buffer), + (gst_audio_convert_transform): + Make audioconvert GAP-aware by outputting silence buffers when the + input has the GAP flag set. This is up to 8x faster. + Based on a patch by Stefan Kost. Fixes bug #517813. + +2008-03-21 15:54:54 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/volume/gstvolume.c: Use oil_scalarmultiply_f64_ns() for double processing when it's available at compile time. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_process_double): + Use oil_scalarmultiply_f64_ns() for double processing when it's + available at compile time. + +2008-03-21 13:27:47 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Fix lrint/lrintf checks to actually work. These functions are in libm on Linux at least so try to link ... + Original commit message from CVS: + * configure.ac: + Fix lrint/lrintf checks to actually work. These functions are + in libm on Linux at least so try to link to it. + +2008-03-21 00:36:20 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to development - 0.10.18.1 + Original commit message from CVS: + * configure.ac: + Back to development - 0.10.18.1 + +=== release 0.10.18 === + +2008-03-21 00:26:03 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * po/LINGUAS: + * win32/common/config.h: + Release 0.10.18 + Original commit message from CVS: + Release 0.10.18 + +2008-03-21 00:16:37 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/hu.po: + * po/it.po: + * po/lt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/sk.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-03-18 12:19:43 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + 0.10.17.4 pre-release + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + 0.10.17.4 pre-release + +2008-03-18 11:20:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.c: Use GST_STR_NULL when trying to print strings that could be NULL because this might... + Original commit message from CVS: + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_message_dump): + Use GST_STR_NULL when trying to print strings that could be NULL because + this might crash on some platforms. See #520808. + +2008-03-18 11:10:12 +0000 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Generic Windows fixes that makes libgstrtsp work on Windows when coupled with ... + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect), (gst_rtsp_connection_write), + (read_line), (gst_rtsp_connection_read_internal): + Generic Windows fixes that makes libgstrtsp work on Windows when + coupled with the new GstPoll API. See #520808. + +2008-03-17 22:06:56 +0000 Milosz Derezynski <internalerror@gmail.com> + + ext/gio/gstgiobasesrc.c: If seeking to a new position succeeds don't simply return from create() without creating a b... + Original commit message from CVS: + Patch by: Milosz Derezynski <internalerror at gmail dot com> + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_create): + If seeking to a new position succeeds don't simply return from + create() without creating a buffer. Do this only in the case + seeking to the new position fails. Fixes bug #523054. + +2008-03-17 10:32:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/video/video.c: Fix gst_video_format_parse_caps() for RGB caps with alpha channel (#522635). + Original commit message from CVS: + * gst-libs/gst/video/video.c: (gst_video_format_parse_caps), + (gst_video_format_from_rgba32_masks): + Fix gst_video_format_parse_caps() for RGB caps with alpha channel + (#522635). + * tests/check/libs/video.c: (test_parse_caps_rgb), (video_suite): + Add unit test for the RGB caps parsing and creation, checking for + internal consistency of the new API and consistency of the API with + the old GST_VIDEO_CAPS_* defines. + +2008-03-14 18:42:35 +0000 David Schleef <ds@schleef.org> + + gst/videotestsrc/videotestsrc.c: Oops, revert last change because -base is in freeze. + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: Oops, revert last change + because -base is in freeze. + +2008-03-14 17:33:09 +0000 William M. Brack <wbrack@mmm.hk> + + gst/videotestsrc/videotestsrc.c: Fix Bayer pattern generation. + Original commit message from CVS: + Patch by: William M. Brack + * gst/videotestsrc/videotestsrc.c: Fix Bayer pattern generation. + +2008-03-14 09:54:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gststreamselector.*: Revert change that caused regression until a real fix is found. + Original commit message from CVS: + * gst/playback/gststreamselector.c: (gst_selector_pad_event), + (gst_selector_pad_chain): + * gst/playback/gststreamselector.h: + Revert change that caused regression until a real fix is found. + Fixes #522203. + +2008-03-12 12:39:13 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/audio/gstringbuffer.*: Rename recently added buffer types to make more sense. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_parse_caps): + * gst-libs/gst/audio/gstringbuffer.h: + Rename recently added buffer types to make more sense. + * ext/alsa/gstalsasink.c: (alsasink_parse_spec), + (gst_alsasink_write): + Adapt for above API changes. + Fixes bug #520523. + +2008-03-11 13:23:55 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + win32/common/libgstnetbuffer.def: Add new symbol gst_netaddress_equal. Fixes bug #521743. + Original commit message from CVS: + * win32/common/libgstnetbuffer.def: + Add new symbol gst_netaddress_equal. Fixes bug #521743. + +2008-03-11 00:25:13 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + 0.10.17.3 pre-release + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + 0.10.17.3 pre-release + +2008-03-10 17:19:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Fix duration when no clock was provided. Fixes #520300. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Fix duration when no clock was provided. Fixes #520300. + +2008-03-07 18:17:44 +0000 Olivier Crete <tester@tester.ca> + + Add trivial function to compare GstNetAddress. See #520626. + Original commit message from CVS: + Patch by: Olivier Crete <tester at tester ca> + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/netbuffer/gstnetbuffer.c: (gst_netaddress_equal): + * gst-libs/gst/netbuffer/gstnetbuffer.h: + Add trivial function to compare GstNetAddress. See #520626. + API: GstNetBuffer::gst_netaddress_equal + +2008-03-07 16:10:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.c: Update mode property docs, it's deprecated now. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + Update mode property docs, it's deprecated now. + +2008-03-07 15:48:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/: Remove GstPollMode from gstpoll constructor. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_create): + * gst/tcp/gstmultifdsink.c: (gst_fdset_mode_get_type), + (gst_multi_fd_sink_class_init), (gst_multi_fd_sink_start): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_start): + * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_start): + Remove GstPollMode from gstpoll constructor. + +2008-03-04 00:26:46 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + 0.10.17.2 pre-release + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + 0.10.17.2 pre-release + +2008-03-03 23:59:45 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/Makefile.am: GST_PLUGINS_ALL correctly lists subparse and tcp now, don't distclean them twice + Original commit message from CVS: + * gst/Makefile.am: + GST_PLUGINS_ALL correctly lists subparse and tcp now, don't distclean + them twice + * win32/common/libgstinterfaces.def: + * win32/common/libgstrtp.def: + Add new API to the defs + +2008-03-03 16:11:50 +0000 Mersad Jelacic <mersad@axis.com> + + gst-libs/gst/rtp/gstbasertpaudiopayload.*: API: add gst_base_rtp_audio_payload_set_samplebits_options() to make it po... + Original commit message from CVS: + Patch by: Mersad Jelacic <mersad at axis dot com> + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + API: add gst_base_rtp_audio_payload_set_samplebits_options() to make it + possible to specify the sample size in bits. (#509637) + +2008-03-03 13:59:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/mixer.c: Add a few simple checks for the new message types. + Original commit message from CVS: + * tests/check/libs/mixer.c: + Add a few simple checks for the new message types. + +2008-03-03 13:56:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add gst_mixer_options_list_changed(), gst_mixer_mixer_changed() and gst_mixer_message_parse_options_list_changed... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/interfaces/mixer.c: (gst_mixer_option_changed), + (gst_mixer_options_list_changed), (gst_mixer_mixer_changed), + (gst_mixer_message_get_type), + (gst_mixer_message_parse_option_changed), + (gst_mixer_message_parse_options_list_changed): + * gst-libs/gst/interfaces/mixer.h: (GstMixerType), + (GST_MIXER_MESSAGE_OPTION_CHANGED), + (GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED), + (GST_MIXER_MESSAGE_MIXER_CHANGED): + API: add gst_mixer_options_list_changed(), gst_mixer_mixer_changed() + and gst_mixer_message_parse_options_list_changed(). Fixes #519916. + +2008-03-03 13:50:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixeroptions.*: API: add GstMixerOptions::get_values vfunc (#519906) + Original commit message from CVS: + * gst-libs/gst/interfaces/mixeroptions.c: (gst_mixer_options_init), + (gst_mixer_options_get_values): + * gst-libs/gst/interfaces/mixeroptions.h: + (GST_MIXER_OPTIONS_GET_CLASS), (GstMixerOptionsClass), + (_GstMixerOptions), (_GstMixerOptionsClass): + API: add GstMixerOptions::get_values vfunc (#519906) + +2008-03-03 12:01:15 +0000 Peter Kjellerstedt <pkj@axis.com> + + configure.ac: Use AG_GST_CHECK_PLUGIN and AG_GST_DISABLE_PLUGIN to simplify which plug-ins are included/excluded. (#4... + Original commit message from CVS: + * configure.ac: + Use AG_GST_CHECK_PLUGIN and AG_GST_DISABLE_PLUGIN to simplify which + plug-ins are included/excluded. (#498222) + +2008-03-03 06:22:39 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for IMelody files, using audio/x-imelody. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add typefinder for IMelody files, using audio/x-imelody. + See bug #519516. + +2008-03-03 06:04:31 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Correct all relevant warnings found by the sparse semantic code analyzer. This include marking several symbols static... + Original commit message from CVS: + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_get_type): + * ext/alsa/gstalsasink.c: (set_hwparams): + * ext/alsa/gstalsasrc.c: (set_hwparams): + * ext/gio/gstgio.c: (gst_gio_uri_handler_get_uri): + * ext/ogg/gstoggmux.h: + * ext/ogg/gstogmparse.c: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/fft/kiss_fft_f64.c: (kiss_fft_f64_alloc): + * gst-libs/gst/pbutils/missing-plugins.c: + (gst_missing_uri_sink_message_new), + (gst_missing_element_message_new), + (gst_missing_decoder_message_new), + (gst_missing_encoder_message_new): + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + (gst_rtcp_packet_bye_get_reason): + * gst/audioconvert/gstaudioconvert.c: + * gst/audioresample/gstaudioresample.c: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/playback/test.c: (gen_video_element), (gen_audio_element): + * gst/typefind/gsttypefindfunctions.c: + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + * sys/v4l/gstv4lelement.c: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get_any_caps): + * sys/v4l/v4l_calls.c: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_capture_init), + (gst_v4lsrc_try_capture): + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new): + * tests/check/elements/audioconvert.c: + * tests/check/elements/audioresample.c: + (fail_unless_perfect_stream): + * tests/check/elements/audiotestsrc.c: (setup_audiotestsrc): + * tests/check/elements/decodebin.c: + * tests/check/elements/gdpdepay.c: (setup_gdpdepay), + (setup_gdpdepay_streamheader): + * tests/check/elements/gdppay.c: (setup_gdppay), (GST_START_TEST), + (setup_gdppay_streamheader): + * tests/check/elements/gnomevfssink.c: (setup_gnomevfssink): + * tests/check/elements/multifdsink.c: (setup_multifdsink): + * tests/check/elements/textoverlay.c: + * tests/check/elements/videorate.c: (setup_videorate): + * tests/check/elements/videotestsrc.c: (setup_videotestsrc): + * tests/check/elements/volume.c: (setup_volume): + * tests/check/elements/vorbisdec.c: (setup_vorbisdec): + * tests/check/elements/vorbistag.c: + * tests/check/generic/clock-selection.c: + * tests/check/generic/states.c: (setup), (teardown): + * tests/check/libs/cddabasesrc.c: + * tests/check/libs/video.c: + * tests/check/pipelines/gio.c: + * tests/check/pipelines/oggmux.c: + * tests/check/pipelines/simple-launch-lines.c: + (simple_launch_lines_suite): + * tests/check/pipelines/streamheader.c: + * tests/check/pipelines/theoraenc.c: + * tests/check/pipelines/vorbisdec.c: + * tests/check/pipelines/vorbisenc.c: + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: (query_positions_elems), + (query_positions_pads): + * tests/icles/stress-xoverlay.c: (myclock): + Correct all relevant warnings found by the sparse semantic code + analyzer. This include marking several symbols static, using + NULL instead of 0 for pointers and using "foo (void)" instead + of "foo ()" for declarations. + * win32/common/libgstrtp.def: + Add gst_rtp_buffer_set_extension_data to the symbol definition file. + +2008-03-02 18:43:15 +0000 José Alburquerque <jaalburqu@svn.gnome.org> + + gst/playback/gstplaybin2.c: Make the function signature of the _get_*_tags() functions match the signature of the vfu... + Original commit message from CVS: + Patch by: José Alburquerque <jaalburqu svn gnome org> + * gst/playback/gstplaybin2.c: + Make the function signature of the _get_*_tags() functions match + the signature of the vfuncs they implement, ie. return a + GstTagList rather than a GstStructure, which is more correct, + even if one is typedef'ed to the other (#518940). + +2008-03-02 18:32:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/rtsp/gstrtspconnection.c: Don't include unix headers unconditionally (fixes #518037). + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + Don't include unix headers unconditionally (fixes #518037). + +2008-03-02 18:24:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/video.c: Add unit test that makes sure that the strides, offsets and sizes returned for the various ... + Original commit message from CVS: + * tests/check/libs/video.c: (paintinfo), (paintinfo_struct), + (fourcc_list_struct), (fourcc_list), (fourcc_get_size), + (paint_setup_I420), (paint_setup_YV12), (paint_setup_AYUV), + (paint_setup_YUY2), (paint_setup_UYVY), (paint_setup_YVYU), + (paint_setup_IYU2), (paint_setup_Y41B), (paint_setup_Y42B), + (paint_setup_Y800), (paint_setup_YVU9), (paint_setup_YUV9), + (gst_video_format_is_packed), (video_format_is_packed): + Add unit test that makes sure that the strides, offsets and + sizes returned for the various YUV formats by the new video API + match the old reference implementation in videotestsrc. + +2008-03-02 18:20:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/video/video.*: API: add GST_VIDEO_FORMAT_Y41B and GST_VIDEO_FORMAT_Y42B. + Original commit message from CVS: + * gst-libs/gst/video/video.c: (gst_video_calculate_display_ratio), + (gst_video_format_from_fourcc), (gst_video_format_to_fourcc), + (gst_video_format_is_rgb), (gst_video_format_is_yuv), + (gst_video_format_has_alpha), (gst_video_format_get_row_stride), + (gst_video_format_get_pixel_stride), + (gst_video_format_get_component_width), + (gst_video_format_get_component_height), + (gst_video_format_get_component_offset), (gst_video_format_get_size): + * gst-libs/gst/video/video.h: (GST_VIDEO_FORMAT_Y41B), + (GST_VIDEO_FORMAT_Y42B): + API: add GST_VIDEO_FORMAT_Y41B and GST_VIDEO_FORMAT_Y42B. + +2008-03-02 18:07:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/video/video.c: YV12 is I420 with swapped components 1 and 2, so the offset of component 1 for I420 shoul... + Original commit message from CVS: + * gst-libs/gst/video/video.c: (gst_video_format_get_component_offset): + YV12 is I420 with swapped components 1 and 2, so the offset of + component 1 for I420 should be the offset for component 2 for YV12 + and vice versa. + +2008-02-29 21:48:00 +0000 Rene Stadler <mail@renestadler.de> + + sys/v4l/gstv4lelement.c: Add missing semicolon to fix indentation. + Original commit message from CVS: + * sys/v4l/gstv4lelement.c: + Add missing semicolon to fix indentation. + +2008-02-29 18:44:36 +0000 Julien Moutte <julien@moutte.net> + + ext/alsa/gstalsa.c: Probe for IEC958 pcm to detect if we can do SPDIF output. + Original commit message from CVS: + 2008-02-29 Julien Moutte <julien@fluendo.com> + * ext/alsa/gstalsa.c: (gst_alsa_open_iec958_pcm), + (gst_alsa_probe_supported_formats): Probe for IEC958 pcm to + detect + if we can do SPDIF output. + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (set_hwparams), (alsasink_parse_spec), + (gst_alsasink_prepare), (gst_alsasink_close), + (gst_alsasink_write): + * ext/alsa/gstalsasink.h: Initial support for SPDIF. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_parse_caps): + * gst-libs/gst/audio/gstringbuffer.h: Add non linear buffer + types + to support AC3, EC3 and IEC958 buffers. + +2008-02-29 17:59:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixer.c: De-cruft and fix message type assertions (NULL is not a really valid mixer message t... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixer.c: (GST_MIXER_MESSAGE_HAS_TYPE), + (gst_mixer_message_parse_mute_toggled), + (gst_mixer_message_parse_record_toggled), + (gst_mixer_message_parse_volume_changed), + (gst_mixer_message_parse_option_changed): + De-cruft and fix message type assertions (NULL is not a really + valid mixer message type string). + +2008-02-29 14:52:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: When negotiating, actually start from a format that we can support instead of from the too ge... + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_vis_src_negotiate): + When negotiating, actually start from a format that we can support + instead of from the too generic template. + +2008-02-29 12:26:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Enable vis setting. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_set_property): + Enable vis setting. + * gst/playback/gstplaysink.c: (gst_play_sink_init), + (gst_play_sink_dispose), (gst_play_sink_vis_unblocked), + (gst_play_sink_vis_blocked), (gst_play_sink_set_vis_plugin), + (gen_vis_chain): + Implement vis switching while playing. + +2008-02-29 00:04:57 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/riff/riff-media.c: Add Dirac mapping + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: Add Dirac mapping + +2008-02-28 10:54:14 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst/tcp/: Removed fdset and stress test, they are now known as GstPoll in core. + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst/tcp/Makefile.am: + * gst/tcp/fdsetstress.c: + * gst/tcp/gstfdset.c: + * gst/tcp/gstfdset.h: + Removed fdset and stress test, they are now known as GstPoll in + core. + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_add_full), (gst_multi_fd_sink_remove), + (gst_multi_fd_sink_clear), (gst_multi_fd_sink_remove_client_link), + (gst_multi_fd_sink_handle_client_write), + (gst_multi_fd_sink_queue_buffer), + (gst_multi_fd_sink_handle_clients), (gst_multi_fd_sink_start), + (gst_multi_fd_sink_stop): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp.c: (gst_tcp_socket_read), (gst_tcp_socket_close), + (gst_tcp_read_buffer), (gst_tcp_gdp_read_buffer), + (gst_tcp_gdp_read_caps): + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_init), + (gst_tcp_client_sink_setcaps), (gst_tcp_client_sink_render), + (gst_tcp_client_sink_start), (gst_tcp_client_sink_stop): + * gst/tcp/gsttcpclientsink.h: + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_init), + (gst_tcp_client_src_create), (gst_tcp_client_src_start), + (gst_tcp_client_src_stop), (gst_tcp_client_src_unlock): + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_handle_wait), + (gst_tcp_server_sink_init_send), (gst_tcp_server_sink_close): + * gst/tcp/gsttcpserversink.h: + * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_init), + (gst_tcp_server_src_create), (gst_tcp_server_src_start), + (gst_tcp_server_src_stop), (gst_tcp_server_src_unlock): + * gst/tcp/gsttcpserversrc.h: + Port to GstPoll. See #505417. + +2008-02-28 09:54:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + * ChangeLog: + Patch Changelog a bit to give credit and refer to the relevant bug. + Original commit message from CVS: + Patch Changelog a bit to give credit and refer to the + relevant bug. + +2008-02-28 09:50:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspconnection.*: Use GstPoll for the rtsp connection. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_create), (gst_rtsp_connection_connect), + (gst_rtsp_connection_write), (gst_rtsp_connection_read_internal), + (gst_rtsp_connection_receive), (gst_rtsp_connection_close), + (gst_rtsp_connection_free), (gst_rtsp_connection_poll), + (gst_rtsp_connection_flush): + * gst-libs/gst/rtsp/gstrtspconnection.h: + Use GstPoll for the rtsp connection. + +2008-02-27 12:19:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add combo box for visualisations, populate it with a factory list of all visualisation pl... + Original commit message from CVS: + * tests/examples/seek/seek.c: (vis_toggle_cb), (filter_features), + (init_visualization_features), (vis_combo_cb), (shot_cb), (main): + Add combo box for visualisations, populate it with a factory list + of all visualisation plugins, configure vis plugin instance in + playbin2. + +2008-02-27 10:55:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/libs/rtp.c: Add check for RTP buffer defaults, padding and marker bit API. + Original commit message from CVS: + * tests/check/libs/rtp.c: (GST_START_TEST): + Add check for RTP buffer defaults, padding and marker bit API. + +2008-02-27 10:42:08 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/cdda/sha1.c: Use memcpy() instead of upcasting a byte array to long *. This fixes an unaligned memory ac... + Original commit message from CVS: + * gst-libs/gst/cdda/sha1.c: (sha_transform): + Use memcpy() instead of upcasting a byte array to long *. This + fixes an unaligned memory access, resulting in SIGBUS on IA64. + This should be ported to GCheckSum once we can use GLib 2.16. + Partially fixes bug #500833. + +2008-02-27 10:23:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gsttagdemux.c: Push tag event after the newsegment event. Log the pointer of the buffer we're actual... + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: (gst_tag_demux_chain): + Push tag event after the newsegment event. Log the pointer of + the buffer we're actually going to push rather than the buffer + we're feeding to _make_metadata_writable(). + +2008-02-25 07:21:33 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Comment smoke typefinder for now. The smokedec plugin needs one frame per buffer... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Comment smoke typefinder for now. The smokedec plugin needs one + frame per buffer but we have no parser yet, thus it simply crashes + in most situations. + +2008-02-25 06:48:14 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for the smoke video codec. Copied from the jpeg plugin. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add typefinder for the smoke video codec. Copied from the jpeg plugin. + +2008-02-25 06:29:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/typefind/gsttypefindfunctions.c: Add midi typefinder, copied from the timidity plugin. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mid_type_find), + (plugin_init): + Add midi typefinder, copied from the timidity plugin. + +2008-02-23 09:51:26 +0000 Tomasz Sałaciński <tsalacinski@gmail.com> + + Forward slashes at the beginning and end of a line also signify italics (Fixes: #518162). + Original commit message from CVS: + Based on patch by: Tomasz Sałaciński <tsalacinski gmail com> + * gst/subparse/gstsubparse.c: (parse_mdvdsub): + * tests/check/elements/subparse.c: (test_microdvd_with_italics), + (subparse_suite): + Forward slashes at the beginning and end of a line also signify + italics (Fixes: #518162). + +2008-02-22 06:38:08 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/gst-plugins-base.supp: Add a suppression for a cached value in GIO that wasn't moved while moving gio fro... + Original commit message from CVS: + * tests/check/gst-plugins-base.supp: + Add a suppression for a cached value in GIO that wasn't moved + while moving gio from -bad to -base. + +2008-02-22 05:27:24 +0000 Brian Cameron <brian.cameron@sun.com> + + configure.ac: Don't hardcode -Wall and -Werror for configure checks, this fails with non-GCC compilers. Fixes bug #51... + Original commit message from CVS: + Patch by: Brian Cameron <brian dot cameron at sun dot com> + * configure.ac: + Don't hardcode -Wall and -Werror for configure checks, this fails + with non-GCC compilers. Fixes bug #517991. + +2008-02-21 08:05:10 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audiotestsrc/gstaudiotestsrc.c: Mark buffers as GAP,if volume is 0.0 and fix the previous logic. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + Mark buffers as GAP,if volume is 0.0 and fix the previous logic. + +2008-02-20 15:37:36 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gnomevfs/gstgnomevfssink.c: Return FALSE when seeking for a new segment fails instead of silently ignoring the fa... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.c: + (gst_gnome_vfs_sink_handle_event): + Return FALSE when seeking for a new segment fails instead + of silently ignoring the failure and appending every buffer + that comes for the new segment. + +2008-02-20 11:52:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Recursively search the sink element for a last-frame property so that we can also find th... + Original commit message from CVS: + * gst/playback/gstplaysink.c: (find_property), + (gst_play_sink_find_property), (gen_video_chain), + (gst_play_sink_reconfigure), (gst_play_sink_get_last_frame): + Recursively search the sink element for a last-frame property so that we + can also find the property in autovideosink and friends that don't + always proxy the internal sink properties. + +2008-02-19 20:42:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: Fix confusing terminology in docs and code: structure fields are 'fields' and not ... + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME), + (gst_audio_get_channel_positions), (gst_audio_set_channel_positions), + (gst_audio_set_structure_channel_positions_list), + (add_list_to_struct), (gst_audio_set_caps_channel_positions_list), + (gst_audio_fixate_channel_positions): + Fix confusing terminology in docs and code: structure fields are + 'fields' and not 'properties'. + +2008-02-19 20:36:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: Give more useful warning messages if one of the channel layout enums passed to us ... + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions), (add_list_to_struct): + Give more useful warning messages if one of the channel + layout enums passed to us is invalid and if the "channels" + field in the caps has a GType we don't expect. + +2008-02-19 20:22:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: Fix typo in docs blurb. + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + Fix typo in docs blurb. + +2008-02-19 16:16:55 +0000 Josep Torra Valles <josep@fluendo.com> + + gst/typefind/gsttypefindfunctions.c: Increase the MPEG PS typefind lookup to fix typefinding on HD clips. + Original commit message from CVS: + 2008-02-19 Julien Moutte <julien@fluendo.com> + Patch by: Josep Torra Valles <josep@fluendo.com> + * gst/typefind/gsttypefindfunctions.c: Increase the MPEG PS + typefind lookup to fix typefinding on HD clips. + +2008-02-19 15:50:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstscreenshot.*: Fix up copyright (I rewrote the GStreamer-0.10 code for this from scratch back in the d... + Original commit message from CVS: + * gst/playback/gstscreenshot.c: + * gst/playback/gstscreenshot.h: + Fix up copyright (I rewrote the GStreamer-0.10 code for + this from scratch back in the days). + +2008-02-19 15:02:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Add screenshot conversion code from totem. + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstscreenshot.c: (feed_fakesrc), (save_result), + (create_element), (gst_play_frame_conv_convert): + * gst/playback/gstscreenshot.h: + Add screenshot conversion code from totem. + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybin2.c: (gst_play_marshal_BUFFER__BOXED), + (gst_play_bin_class_init), (gst_play_bin_convert_frame), + (gst_play_bin_get_property), (no_more_pads_cb), (activate_group): + Implement frame property to get a color-unconverted snapshot. + Implement convert-frame action signal to get a converted snapshot image. + Configure connection speed in uridecodebin. + Document some more properties. + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure), + (gst_play_sink_get_last_frame): + * gst/playback/gstplaysink.h: + Use last-buffer property of the video sink to get a video snapshot. + * tests/examples/seek/seek.c: (shot_cb), (main): + Add snapshot button for playbin2 and use the frame property to save the + frame as a png in the current directory. + +2008-02-19 11:45:56 +0000 Josep Torra Valles <josep@fluendo.com> + + gst/typefind/gsttypefindfunctions.c: Add typefinding support for h264 elementary streams. + Original commit message from CVS: + Patch by: Josep Torra Valles <josep at fluendo dot com> + * gst/typefind/gsttypefindfunctions.c: (h264_video_type_find), + (plugin_init): + Add typefinding support for h264 elementary streams. + Fixes bug #517420. + +2008-02-18 13:51:34 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Require CVS of core for new API in collectpads. + Original commit message from CVS: + * configure.ac: + Require CVS of core for new API in collectpads. + * gst/adder/gstadder.c: + Use new API to make adder sparse stream aware. + +2008-02-18 11:54:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Get the object data correct so that we can remove our channels correctly. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (pad_added_cb), (pad_removed_cb), + (no_more_pads_cb): + Get the object data correct so that we can remove our channels + correctly. + * gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain), + (gen_vis_chain), (gst_play_sink_reconfigure), + (gst_play_sink_request_pad): + Add option to disable async behaviour in the sinks when possible. This + makes it possible to avoid an audio queue when dealing with + visualisations. + Add option to add a queue for the audio path. + * tests/examples/seek/seek.c: (clear_streams), (update_streams), + (main): + Disable the vis checkbox to match the defaults of playbin2. + Only get the stream info when we need to. + +2008-02-17 05:15:45 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Don't use async operations as they require a running main loop. + Original commit message from CVS: + * ext/gio/gstgiobasesink.c: (gst_gio_base_sink_stop), + (gst_gio_base_sink_set_stream): + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_stop), + (gst_gio_base_src_set_stream): + * ext/gio/gstgiosink.c: (gst_gio_sink_start): + * ext/gio/gstgiosrc.c: (gst_gio_src_start): + Don't use async operations as they require a running main loop. + This makes us block again when closing streams and unable + to mount the enclosing volume of an URI if it isn't yet. + +2008-02-15 18:38:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaysink.c: Move tee in front of the audio and vis pipelines. + Original commit message from CVS: + * gst/playback/gstplaysink.c: (gst_play_sink_set_mute), + (gst_play_sink_get_mute), (gen_video_chain), (gen_audio_chain), + (gen_vis_chain), (gst_play_sink_reconfigure), + (gst_play_sink_request_pad): + Move tee in front of the audio and vis pipelines. + Add queue for audio for now. + Add visualisation support. + * tests/examples/seek/seek.c: (main): + Visualisation is by default disabled. + +2008-02-15 11:58:06 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Improve debugging a bit. + Original commit message from CVS: + * ext/gio/gstgiobasesink.c: (close_stream_cb): + * ext/gio/gstgiobasesrc.c: (close_stream_cb): + Improve debugging a bit. + * ext/gio/gstgiosink.c: (mount_cb), (gst_gio_sink_start): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.c: (mount_cb), (gst_gio_src_start): + * ext/gio/gstgiosrc.h: + Try to mount the enclosing volume of a GFile if it isn't mounted + yet. This requires us to wait for an async operation to finish, done + with an nested GMainLoop. Authentication is not supported yet, will + come later. + +2008-02-14 18:24:42 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Add mute property. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (pad_added_cb), (pad_removed_cb), (no_more_pads_cb): + * gst/playback/gstplaysink.c: (gst_play_sink_set_mute), + (gst_play_sink_get_mute), (gen_audio_chain): + * gst/playback/gstplaysink.h: + Add mute property. + * gst/playback/gststreamselector.c: (gst_selector_pad_event), + (gst_selector_pad_chain): + * gst/playback/gststreamselector.h: + Make sure we forward the event only once. + * tests/examples/seek/seek.c: (stop_cb), (mute_toggle_cb), (main): + Add and implement the mute button for playbin2. + +2008-02-13 14:34:55 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + ext/alsa/gstalsasink.c: Add some more debug info. + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * ext/alsa/gstalsasink.c: (set_hwparams), (gst_alsasink_delay): + Add some more debug info. + Make sure we never return a negative delay. Fixes #516246. + +2008-02-12 20:09:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsasink.c: Revert patch that makes the sink hold the object lock when calling snd_pcm_delay(), since it ... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_delay): + Revert patch that makes the sink hold the object lock when + calling snd_pcm_delay(), since it breaks playback for me. + +2008-02-12 19:50:36 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Add some seek flags when changing rate. + Original commit message from CVS: + 2008-02-12 Julien Moutte <julien@fluendo.com> + * tests/examples/seek/seek.c: (rate_spinbutton_changed_cb): Add + some seek flags when changing rate. + +2008-02-12 14:51:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Fix potential leaks. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_handle_frame_based_buffer), + (gst_base_rtp_audio_payload_handle_sample_based_buffer): + Fix potential leaks. + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_chain): + Fix leak when there is no function configured. + +2008-02-12 11:36:27 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + sys/v4l/v4lsrc_calls.c: Correctly chain up the finalize method. + Original commit message from CVS: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_class_init), + (gst_v4lsrc_buffer_finalize): + Correctly chain up the finalize method. + +2008-02-12 09:24:11 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Add documentation and example code for giostreamsink/giostreamsrc. + Original commit message from CVS: + * ext/gio/gstgiostreamsink.c: + * ext/gio/gstgiostreamsrc.c: + Add documentation and example code for giostreamsink/giostreamsrc. + * tests/check/pipelines/gio.c: (GST_START_TEST): + Ask the GMemoryOutputStream for the data instead of assuming that + the pointer to the data stayed the same. It could've been realloc'ed. + +2008-02-12 08:55:57 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Make the documentation of giosink/giosrc complete, large parts are based on the gnomevfssink/gnomevfssrc docs. + Original commit message from CVS: + * ext/gio/gstgiosink.c: + * ext/gio/gstgiosrc.c: + Make the documentation of giosink/giosrc complete, large parts + are based on the gnomevfssink/gnomevfssrc docs. + +2008-02-12 08:13:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + docs/plugins/: Add the GIO documentation again and while at that run make update. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playback.xml: + * docs/plugins/inspect/plugin-queue2.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-uridecodebin.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + Add the GIO documentation again and while at that run make update. + +2008-02-11 20:23:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/: Don't use snd_pcm_sw_params_set_xfer_align() if we're compiling against libasound >= 1.0.16, since it's be... + Original commit message from CVS: + * ext/alsa/gstalsa.h: (GST_CHECK_ALSA_VERSION): + * ext/alsa/gstalsasink.c: (set_swparams): + * ext/alsa/gstalsasrc.c: (set_swparams), (gst_alsasrc_open): + Don't use snd_pcm_sw_params_set_xfer_align() if we're compiling + against libasound >= 1.0.16, since it's been deprecated in + 0.10.16, and alignment is always 1 then, apparently. (#512899) + +2008-02-11 18:31:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Handle case where we can't create the volume element a bit better (#514307). + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_audio_element): + * gst/playback/gstplaysink.c: (gen_audio_chain): + Handle case where we can't create the volume element a bit + better (#514307). + +2008-02-11 18:02:13 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/: Add support for https protocol. Fixes #510229. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_check_get_range): + * ext/gnomevfs/gstgnomevfsuri.c: (gst_gnomevfs_get_supported_uris): + Add support for https protocol. Fixes #510229. + +2008-02-11 17:03:18 +0000 Alan Peevers <peeves@pacbell.net> + + ext/alsa/gstalsasink.c: Take appropriate lock when calling alsa methods. + Original commit message from CVS: + 2008-02-11 Julien Moutte <julien@fluendo.com> + Patch by: Alan Peevers <peeves@pacbell.net> + * ext/alsa/gstalsasink.c: (gst_alsasink_delay): Take appropriate + lock when calling alsa methods. + +2008-02-11 13:03:13 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Bump rank of jpeg and png typefinders, which will return maximum probability in ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + Bump rank of jpeg and png typefinders, which will return maximum + probability in the most common cases (thus short-circuiting more + expensive typefinders like the mp3 one for these two quite common + image types). + +2008-02-11 09:48:03 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/theora/theoraparse.c: Fix long description of the theora parser to be more verbose than just the type name. + Original commit message from CVS: + * ext/theora/theoraparse.c: + Fix long description of the theora parser to be more verbose than just + the type name. + +2008-02-11 06:47:50 +0000 Branko Čibej <brane@xbc.nu> + + sys/xvimage/xvimagesink.c: Fix build of xvimagesink if we don't have XShm, e.g. on Mac OS X. + Original commit message from CVS: + Patch by: Branko Čibej <brane at xbc dot nu> + * sys/xvimage/xvimagesink.c: + Fix build of xvimagesink if we don't have XShm, e.g. on Mac OS X. + Fixes bug #515654. + +2008-02-09 10:41:36 +0000 Zaheer Abbas Merali <zaheerabbas@merali.org> + + gst/playback/gstplaybasebin.c: Set is_dynamic as True if there are elements with both request and sometimes src pad t... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + Set is_dynamic as True if there are elements with both request + and sometimes src pad templates instead of breaking out when it + finds the first pad template that is a src. + +2008-02-08 18:17:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add some stream switching and volume gui for playbin2. + Original commit message from CVS: + * tests/examples/seek/seek.c: (stop_cb), (clear_streams), + (update_streams), (video_combo_cb), (audio_combo_cb), + (text_combo_cb), (volume_spinbutton_changed_cb), (main): + Add some stream switching and volume gui for playbin2. + +2008-02-08 17:47:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplay-marshal.list: Added marshal for streamselector Tags. + Original commit message from CVS: + * gst/playback/gstplay-marshal.list: + Added marshal for streamselector Tags. + * gst/playback/gstplaybasebin.c: (set_active_source): + Streamselector now selects pads based on the pad object instead of its + name. + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (init_group), (gst_play_bin_init), (get_group), (get_tags), + (gst_play_bin_get_video_tags), (gst_play_bin_get_audio_tags), + (gst_play_bin_get_text_tags), + (gst_play_bin_set_current_video_stream), + (gst_play_bin_set_current_audio_stream), + (gst_play_bin_set_current_text_stream), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (pad_added_cb), (pad_removed_cb), (autoplug_select_cb): + Remove option to mute streams with the current-a/v/t property, we have + this functionality in the flags. + Add signals to notify when the number of A/V/T channels changed. + Add action signals to get tags for the A/V/T streams. + Implement setting the current A/V/T stream. + Rearrange some things to simplify stream selection. + Implement volume. + * gst/playback/gstplaysink.c: (gst_play_sink_set_volume), + (gst_play_sink_get_volume), (gst_play_sink_set_property), + (gst_play_sink_get_property), (gen_video_chain), (gen_audio_chain), + (activate_vis), (gst_play_sink_reconfigure): + * gst/playback/gstplaysink.h: + Add and implement volume setting methods. + * gst/playback/gststreamselector.c: (gst_selector_pad_class_init), + (gst_selector_pad_finalize), (gst_selector_pad_get_property), + (gst_selector_pad_event), (gst_stream_selector_class_init), + (gst_stream_selector_init), (gst_stream_selector_finalize), + (gst_stream_selector_set_property), + (gst_stream_selector_get_property), + (gst_stream_selector_get_linked_pad), + (gst_stream_selector_request_new_pad): + * gst/playback/gststreamselector.h: + Add pad properties for tags and status of pads. + Keep tags on pads. + Make active pad selection based on pad object instead of name. + +2008-02-08 16:10:25 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Revert last change as we now check in gtk-doc.m4 for sed. + Original commit message from CVS: + * configure.ac: + Revert last change as we now check in gtk-doc.m4 for sed. + +2008-02-08 14:54:30 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Find and subst SED when building the docs. + Original commit message from CVS: + * configure.ac: + Find and subst SED when building the docs. + +2008-02-08 14:34:41 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Make sure bus signals are reconnected when pressing STOP and then PLAY again for a parse ... + Original commit message from CVS: + 2008-02-08 Julien Moutte <julien@fluendo.com> + * tests/examples/seek/seek.c: (stop_cb), (connect_bus_signals), + (main): Make sure bus signals are reconnected when pressing STOP + and then PLAY again for a parse launch pipeline. Fix a ref leak + on the bus. + * win32/common/config.h: Updated. + +2008-02-08 00:57:21 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Make DISABLE_DEPRECATED defined *only* during CVS, not during pre-releases or releases. + Original commit message from CVS: + * configure.ac: + Make DISABLE_DEPRECATED defined *only* during CVS, not during + pre-releases or releases. + +2008-02-08 00:45:56 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Subst GIO_LDFLAGS to avoid undefined Makefile var error Zaheer is reporting + Original commit message from CVS: + * configure.ac: + * ext/gio/Makefile.am: + Subst GIO_LDFLAGS to avoid undefined Makefile var error Zaheer is + reporting + +2008-02-07 23:40:30 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + docs/plugins/Makefile.am: Add the headers which need scanning for the GIO plugin. The rest of the docs still need mig... + Original commit message from CVS: + * docs/plugins/Makefile.am: + Add the headers which need scanning for the GIO plugin. The rest of + the docs still need migrating. + +2008-02-07 23:22:23 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Add gio in a few more places. + Original commit message from CVS: + * ext/Makefile.am: + * tests/check/Makefile.am: + * tests/check/pipelines/.cvsignore: + Add gio in a few more places. + +2008-02-07 23:18:43 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Move gio plugin from -bad and mark as experimental. + Original commit message from CVS: + * configure.ac: + * ext/Makefile.am: + * tests/check/Makefile.am: + Move gio plugin from -bad and mark as experimental. + +2008-02-07 22:39:00 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/: Comment out a couple of other things which break the build when + Original commit message from CVS: + * gst-libs/gst/interfaces/mixeroptions.c: + * gst-libs/gst/interfaces/mixertrack.c: + Comment out a couple of other things which break the build when + GST_DISABLE_DEPRECATED isn't on but -Werror is. + +2008-02-07 18:28:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Fix pbutils header. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + Fix pbutils header. + +2008-02-07 18:07:41 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + commit spec file update which includes all the split .pc files + Original commit message from CVS: + commit spec file update which includes all the split .pc files + +2008-02-07 12:17:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspmessage.c: Fix compiler warning. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspmessage.c: (gst_rtsp_message_unset): + Fix compiler warning. + +2008-02-07 11:00:45 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst-libs/gst/sdp/gstsdpmessage.c: Clear the addrinfo struct using memset. Fixes #514937. + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst-libs/gst/sdp/gstsdpmessage.c: (is_multicast_address): + Clear the addrinfo struct using memset. Fixes #514937. + +2008-02-06 15:07:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstfdset.h: Remove unused field to same some memory. + Original commit message from CVS: + * gst/tcp/gstfdset.h: + Remove unused field to same some memory. + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + Mark action signals as such. + +2008-02-06 13:35:58 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Increment granulepos for new-bitstream versions appropriately. + Original commit message from CVS: + * ext/theora/theoradec.c: (_theora_granule_frame), + (_inc_granulepos): + Increment granulepos for new-bitstream versions appropriately. + Fixes #514623. + +2008-02-04 11:51:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Remove obsolete stream_time reset after flushing seek, core does that automatically now. + Original commit message from CVS: + * tests/examples/seek/seek.c: (do_seek), + (rate_spinbutton_changed_cb), (update_streams), (main): + Remove obsolete stream_time reset after flushing seek, core does that + automatically now. + Improve accuracy of speed spinbutton. + Only do playbin2 stuff when we actually use it. + +2008-02-02 17:29:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Revert previous change of the test environment's GST_PLUGIN_PATH. + Original commit message from CVS: + * tests/check/Makefile.am: + Revert previous change of the test environment's GST_PLUGIN_PATH. + The problem is not with the plugins, but with element factories + and only occurs if elements are split out from existing plugins + or if plugins change name (see #512740). + +2008-02-02 15:32:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Fix the tests environment's GST_PLUGIN_PATH: we want the directory with the core's plugins f... + Original commit message from CVS: + * tests/check/Makefile.am: + Fix the tests environment's GST_PLUGIN_PATH: we want the directory + with the core's plugins first and our local build directories last, + since we might be building against an installed core, and that + core's plugin directory may contain older or other versions of + our own -base plugins, but we really do want to test our local + ones (if there are multiple plugins or element factories with the + same name, those inspected last will trump those read in earlier). + Fixes #512740 for the most part. + +2008-02-02 07:13:15 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Use gmtime_r if available as gmtime is not MT-safe. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/rtsp/gstrtspconnection.c: (add_date_header): + Use gmtime_r if available as gmtime is not MT-safe. + Fixes bug #511810. + +2008-02-02 06:52:41 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/rtsp/gstrtspconnection.c: Cast glong to time_t as time_t might have a different type on other platforms,... + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: (add_date_header): + Cast glong to time_t as time_t might have a different type on + other platforms, like FreeBSD, and we get a compiler warning + otherwise. Fixes bug #511825. + +2008-02-01 16:44:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Remove stream-info, we going for something easier. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (get_group), (get_n_pads), (gst_play_bin_get_property), + (pad_added_cb), (no_more_pads_cb), (perform_eos), + (autoplug_select_cb), (deactivate_group): + Remove stream-info, we going for something easier. + Refactor getting the current group. + Implement getting the number of audio/video/text streams. + * gst/playback/gststreamselector.c: + (gst_stream_selector_class_init), (gst_stream_selector_init), + (gst_stream_selector_get_property), + (gst_stream_selector_request_new_pad), + (gst_stream_selector_release_pad): + * gst/playback/gststreamselector.h: + Add property for number of pads. + * tests/examples/seek/seek.c: (set_scale), (update_flag), + (vis_toggle_cb), (audio_toggle_cb), (video_toggle_cb), + (text_toggle_cb), (update_streams), (msg_async_done), + (msg_state_changed), (main): + Block slider callback when updating the slider position. + Add gui elements for controlling playbin2. + Add callback for async_done that updates position/duration. + +2008-02-01 12:56:59 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/plugins/: First round of plugin docs cleansups. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + First round of plugin docs cleansups. + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Regenerate. + * ext/ogg/Makefile.am: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggmux.h: + Add header for oggmux. the c-file needs a doc blob still. + +2008-02-01 11:09:16 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + Add gst_rtp_buffer_set_extension_data() + Original commit message from CVS: + Patch by: Thijs Vermeir <thijsvermeir at gmail dot com> + * gst-libs/gst/rtp/gstrtpbuffer.c: + (gst_rtp_buffer_set_extension_data): + * gst-libs/gst/rtp/gstrtpbuffer.h: + * tests/check/libs/rtp.c: (GST_START_TEST), (rtp_suite): + Add gst_rtp_buffer_set_extension_data() + Add a unit test for this addition. Fixes #511478. + API: GstRTPBuffer:gst_rtp_buffer_set_extension_data() + +2008-01-31 17:18:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.c: Really clean up the queue instead of just unreffing all buffers in it. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_dispose): + Really clean up the queue instead of just unreffing all buffers + in it. + * gst-libs/gst/app/gstappsrc.c: (gst_app_src_base_init), + (gst_app_src_class_init), (gst_app_src_init), + (gst_app_src_dispose), (gst_app_src_finalize): + Fix dispose/finalize. + +2008-01-30 15:34:25 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Use async variants of the close stream functions to prevent blocking for a long time there and add some mor... + Original commit message from CVS: + * ext/gio/gstgiobasesink.c: (close_stream_cb), + (gst_gio_base_sink_stop), (gst_gio_base_sink_event), + (gst_gio_base_sink_render), (gst_gio_base_sink_set_stream): + * ext/gio/gstgiobasesrc.c: (close_stream_cb), + (gst_gio_base_src_stop), (gst_gio_base_src_create), + (gst_gio_base_src_set_stream): + Use async variants of the close stream functions to prevent blocking + for a long time there and add some more sanity checks for a correct + stream. + +2008-01-30 14:42:14 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.17 === + +2008-01-30 14:19:05 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/config.h: + Release 0.10.17 + Original commit message from CVS: + Release 0.10.17 + +2008-01-30 13:45:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/: Also remove the conditional registration of the signals that disappeared with the ABI chang... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixeroptions.c: + * gst-libs/gst/interfaces/mixertrack.c: + Also remove the conditional registration of the signals + that disappeared with the ABI change in 0.10.14 + +2008-01-30 12:28:59 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Revert patch to gstrtspconnection.c for brown paper bag release of -base. Re-o... + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + Revert patch to gstrtspconnection.c for brown paper bag + release of -base. Re-opens: #511825 + +2008-01-30 12:20:42 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/: Change the way these deprecated function pointers are removed so that the compiled ABI is u... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixeroptions.h: + * gst-libs/gst/interfaces/mixertrack.h: + Change the way these deprecated function pointers are removed + so that the compiled ABI is unconditionally smaller. This + sets in stone an ABI break that actually occurred when the + things were deprecated in 0.10.14, which seems to be the best + fix as the only known users are oss-mixer and sunaudio-mixer in + gst-plugins-good. + Fixes: #513018 + +2008-01-30 12:19:02 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/: Change the way these deprecated function pointers are removed so that the compiled ABI is u... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixeroptions.h: + * gst-libs/gst/interfaces/mixertrack.h: + Change the way these deprecated function pointers are removed + so that the compiled ABI is unconditionally smaller. This + sets in stone an ABI break that actually occurred when the + things were deprecated in 0.10.14, which seems to be the best + fix as the only known users are oss-mixer and sunaudio-mixer in + gst-plugins-good. + +2008-01-30 11:43:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + win32/common/libgstpbutils.def: Export the two new _get_type() functions which are needed by the python bindings. + Original commit message from CVS: + * win32/common/libgstpbutils.def: + Export the two new _get_type() functions which are needed + by the python bindings. + +2008-01-29 09:59:03 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/rtsp/gstrtspconnection.c: Cast glong to time_t as time_t might have a different type on other platforms,... + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: (add_date_header): + Cast glong to time_t as time_t might have a different type on + other platforms, like FreeBSD, and we get a compiler warning + otherwise. Fixes bug #511825. + +2008-01-29 09:47:12 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/gstaudiofilter.c: Initialize the GstRingerBuffer class to get it's debug category initialized. gst... + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiofilter.c: + (gst_audio_filter_class_init): + Initialize the GstRingerBuffer class to get it's debug category + initialized. gst_ring_buffer_parse_caps() uses the ringbuffer debug + category and otherwise we get some g_critical(). Fixes bug #512334. + +2008-01-28 23:35:21 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.16 === + +2008-01-28 23:31:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.prerequisites: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/config.h: + Release 0.10.16 + Original commit message from CVS: + Release 0.10.16 + +2008-01-28 22:15:47 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * common: + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2008-01-22 15:37:49 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.c: Fix typos and wrong extension check. Fixes #511274. + Original commit message from CVS: + Patch by: Thijs Vermeir <thijsvermeir at gmail dot com> + * gst-libs/gst/rtp/gstrtpbuffer.c: + (gst_rtp_buffer_get_extension_data): + Fix typos and wrong extension check. Fixes #511274. + +2008-01-18 00:03:18 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + po/sk.po: Oops - add new sk.po mentioned in the LINGUAS I just committed + Original commit message from CVS: + * po/sk.po: + Oops - add new sk.po mentioned in the LINGUAS I just committed + +2008-01-17 22:31:25 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + po/LINGUAS: Add ca translation to the disted list. + Original commit message from CVS: + * po/LINGUAS: + Add ca translation to the disted list. + * win32/vs6/libgstsdp.dsp: + Convert line endings to CRLF + +2008-01-17 21:58:53 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/MANIFEST: Add win32/vs6/libgstrtsp.dsp to MANIFEST + Original commit message from CVS: + * win32/MANIFEST: + Add win32/vs6/libgstrtsp.dsp to MANIFEST + +2008-01-16 05:40:48 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Update for API changes in GIO and require GIO 2.15.2 for this. + Original commit message from CVS: + * configure.ac: + * tests/check/pipelines/gio.c: (GST_START_TEST): + Update for API changes in GIO and require GIO 2.15.2 for this. + +2008-01-14 22:20:12 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + win32/common/: Add new API declarations + Original commit message from CVS: + * win32/common/libgstsdp.def: + * win32/common/libgstvideo.def: + Add new API declarations + +2008-01-14 17:00:03 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/theora/: Take a 2nd stab at handling libtheora granulepos changes in the decoder and parser by inspecting the bit... + Original commit message from CVS: + * ext/theora/gsttheoradec.h: + * ext/theora/gsttheoraparse.h: + * ext/theora/theoradec.c: + * ext/theora/theoraparse.c: + Take a 2nd stab at handling libtheora granulepos changes in the decoder + and parser by inspecting the bitstream version of the incoming data. + +2008-01-14 13:11:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Provide one pkg-config file for every gst-plugins-base library. + Original commit message from CVS: + * configure.ac: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-audio-uninstalled.pc.in: + * pkgconfig/gstreamer-audio.pc.in: + * pkgconfig/gstreamer-cdda-uninstalled.pc.in: + * pkgconfig/gstreamer-cdda.pc.in: + * pkgconfig/gstreamer-fft-uninstalled.pc.in: + * pkgconfig/gstreamer-fft.pc.in: + * pkgconfig/gstreamer-floatcast-uninstalled.pc.in: + * pkgconfig/gstreamer-floatcast.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-interfaces.pc.in: + * pkgconfig/gstreamer-netbuffer-uninstalled.pc.in: + * pkgconfig/gstreamer-netbuffer.pc.in: + * pkgconfig/gstreamer-pbutils-uninstalled.pc.in: + * pkgconfig/gstreamer-pbutils.pc.in: + * pkgconfig/gstreamer-riff-uninstalled.pc.in: + * pkgconfig/gstreamer-riff.pc.in: + * pkgconfig/gstreamer-rtp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtp.pc.in: + * pkgconfig/gstreamer-rtsp-uninstalled.pc.in: + * pkgconfig/gstreamer-rtsp.pc.in: + * pkgconfig/gstreamer-sdp-uninstalled.pc.in: + * pkgconfig/gstreamer-sdp.pc.in: + * pkgconfig/gstreamer-tag-uninstalled.pc.in: + * pkgconfig/gstreamer-tag.pc.in: + * pkgconfig/gstreamer-video-uninstalled.pc.in: + * pkgconfig/gstreamer-video.pc.in: + Provide one pkg-config file for every gst-plugins-base library. + This makes linking to those libraries much more intuitive and + provides standard pkg-config behaviour for them. Fixes bug #499697. + +2008-01-14 01:19:34 +0000 David Schleef <ds@schleef.org> + + gst/videoscale/vs_4tap.c: Fix valgrind error on 4tap scaling method. + Original commit message from CVS: + * gst/videoscale/vs_4tap.c: + Fix valgrind error on 4tap scaling method. + +2008-01-13 21:40:45 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/sdp/gstsdpmessage.c: Include Winsock2.h for VS6 and use a different way initialize hints structure so it... + Original commit message from CVS: + * gst-libs/gst/sdp/gstsdpmessage.c: (is_multicast_address): + Include Winsock2.h for VS6 and use a different way initialize + hints structure so it can build with VS6. + * win32/MANIFEST: + * win32/vs6/libgstsdp.dsp: + * win32/common/libgstsdp.def: + Add new files for libgstsdp. + * win32/vs6/grammar.dsp: + Copy pbutils-enumtypes* from win32/common to pbutils sources folder. + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstdecodebin.dsp: + * win32/vs6/libgstdecodebin2.dsp: + * win32/vs6/libgstplaybin.dsp: + * win32/vs6/libgstvolume.dsp: + Add new dependencies to the link list. + +2008-01-13 17:24:49 +0000 Julien Moutte <julien@moutte.net> + + win32/common/: Update/Add generated files in the win32 build directory. + Original commit message from CVS: + 2008-01-13 Julien Moutte <julien@fluendo.com> + * win32/common/config.h: + * win32/common/gstrtsp-enumtypes.c: (gst_rtsp_result_get_type), + (gst_rtsp_event_get_type), (gst_rtsp_family_get_type), + (gst_rtsp_state_get_type), (gst_rtsp_version_get_type), + (gst_rtsp_method_get_type), (gst_rtsp_auth_method_get_type), + (gst_rtsp_header_field_get_type), + (gst_rtsp_status_code_get_type): + * win32/common/interfaces-enumtypes.c: + (gst_color_balance_type_get_type), (gst_mixer_type_get_type), + (gst_mixer_message_type_get_type), (gst_mixer_flags_get_type), + (gst_mixer_track_flags_get_type), + (gst_tuner_channel_flags_get_type): + * win32/common/multichannel-enumtypes.c: + (gst_audio_channel_position_get_type): + * win32/common/pbutils-enumtypes.c: + (gst_install_plugins_return_get_type): + * win32/common/pbutils-enumtypes.h: Update/Add generated files + in the win32 build directory. + +2008-01-12 23:24:02 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/Makefile.am: Fix CFLAGS to also pull in the gstcheck cflags from AM_CFLAGS. + Original commit message from CVS: + * tests/check/Makefile.am: + Fix CFLAGS to also pull in the gstcheck cflags from AM_CFLAGS. + * tests/check/elements/audiorate.c: (do_perfect_stream_test): + * tests/check/elements/playbin.c: + * tests/check/libs/mixer.c: (test_element_interface_supported), + (gst_implements_interface_init): + * tests/check/libs/rtp.c: (GST_START_TEST): + Fix various assignment type mismatches. + +2008-01-12 23:08:28 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Add test to see if hstrerror is available or if we need libresolv (Solaris) for it, then use it in libgstrtsp. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/rtsp/Makefile.am: + Add test to see if hstrerror is available or if we need libresolv + (Solaris) for it, then use it in libgstrtsp. + +2008-01-12 14:54:51 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/tag/Makefile.am: Fix include path order + Original commit message from CVS: + * gst-libs/gst/tag/Makefile.am: + Fix include path order + +2008-01-11 17:15:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + * gst-libs/gst/pbutils/.gitignore: + Ignore more and make buildbot happy + Original commit message from CVS: + Ignore more and make buildbot happy + +2008-01-11 16:18:10 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/pbutils/install-plugins.*: Add GBoxed GType for GstInstallPluginsContext, this eases the wrapping for bi... + Original commit message from CVS: + * gst-libs/gst/pbutils/install-plugins.c: + (gst_install_plugins_context_copy), + (gst_install_plugins_context_get_type): + * gst-libs/gst/pbutils/install-plugins.h: + Add GBoxed GType for GstInstallPluginsContext, this eases the wrapping + for bindings. + +2008-01-11 15:48:11 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Adapt for post-alpha meaning of granulepos, when we have a newer version of libtheora. + Original commit message from CVS: + * ext/theora/theoradec.c: (gst_theora_dec_class_init), + (_theora_granule_frame), (_theora_granule_start_time), + (theora_dec_sink_convert), (theora_dec_decode_buffer): + Adapt for post-alpha meaning of granulepos, when we + have a newer version of libtheora. + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_get_ogg_packet_end_time), (theora_enc_sink_event), + (theora_enc_is_discontinuous), (theora_enc_chain): + Likewise. + * tests/check/Makefile.am: + Link libtheora into theoraenc test so we can check which version of + libtheora we're testing against. + * tests/check/pipelines/theoraenc.c: (check_libtheora), + (check_buffer_granulepos), + (check_buffer_granulepos_from_starttime), (GST_START_TEST), + (theoraenc_suite): + Adapt tests to check the values that are now defined for theora; make + the tests backwards-adapt the passed values if we're running against an + old libtheora. + Fixes #497964 + +2008-01-10 17:55:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/: Ref audio clock class from a thread-safe context to make sure however unlikely that may be in pr... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init): + Ref audio clock class from a thread-safe context to make sure + we're not bit by GObjects lack of thread-safety here (#349410), + however unlikely that may be in practice. + +2008-01-10 12:22:46 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + autogen.sh: Add -Wno-portability to the automake parameters to stop warnings about GNU make extensions being used. We... + Original commit message from CVS: + * autogen.sh: + Add -Wno-portability to the automake parameters to stop warnings + about GNU make extensions being used. We require GNU make in almost + every Makefile anyway. + * configure.ac: + Use AM_PROG_CC_C_O as a compiler that accepts both -c and -o + at the same time is required for per target flags. + +2008-01-08 21:10:02 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gsttagdemux.c: Post an error message if we can't pull as many bytes as we need for the tag. This mak... + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: (gst_tag_demux_pull_start_tag): + Post an error message if we can't pull as many bytes as we need + for the tag. This makes sure the user gets to see a proper error + message if a file with a partial ID3 tag is fed to decodebin, and + not a 'no ID3 tag demuxer' error, which would be confusing + (see #508138). + +2008-01-08 20:59:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/descriptions.c: Add description strings for ID3, APE, and ICY tags. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (formats): + Add description strings for ID3, APE, and ICY tags. + +2008-01-08 20:48:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: Make sure we error out correctly if we can't activate one of the elements we've added. ... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (try_to_link_1): + Make sure we error out correctly if we can't activate one of + the elements we've added. Fixes #508138. + +2008-01-07 13:59:43 +0000 Bastien Nocera <hadess@hadess.net> + + ext/alsa/gstalsamixer.c: Use snd_mixer_selem_set_{playback|capture}_volume_all() if the volume is the same for all ch... + Original commit message from CVS: + Patch by: Bastien Nocera <hadess at hadess net> + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume), + (check_if_volumes_are_the_same), (gst_alsa_mixer_set_volume): + Use snd_mixer_selem_set_{playback|capture}_volume_all() if + the volume is the same for all channels. This works around + some problem in alsa that leaves us with inconsistent state + for some reason (#486840). + +2008-01-07 13:19:50 +0000 Jerone Young <jerone@gmail.com> + + ext/alsa/gstalsamixer.c: If there's no mixer track by the name of 'Master' or 'Front', check if there's one called 'P... + Original commit message from CVS: + Patch by: Jerone Young <jerone at gmail com> + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_find_master_mixer): + If there's no mixer track by the name of 'Master' or 'Front', + check if there's one called 'PCM' before trying the generic + fallback logic (fixes #506928, where we pick 'Mic' as master + track for the AD1984 card in a Thinkpad T61/X61 laptop). + +2008-01-07 11:40:04 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplay-enum.*: Add enums for configuration flags. + Original commit message from CVS: + * gst/playback/gstplay-enum.c: + (register_gst_autoplug_select_result), + (gst_autoplug_select_result_get_type), (register_gst_play_flags), + (gst_play_flags_get_type): + * gst/playback/gstplay-enum.h: + Add enums for configuration flags. + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (init_group), (gst_play_bin_init), (gst_play_bin_set_property), + (gst_play_bin_get_property), (no_more_pads_cb), + (autoplug_select_cb), (gst_play_bin_change_state): + Merge mode with flags. + Add more property getters/setters, defaults and docs. + Add properties to get number of audio/video/text streams. + Create sink object in _init so that we can always rely on it being + there. + * gst/playback/gstplaysink.c: (gst_play_sink_init), + (gen_video_chain), (gen_audio_chain), (gen_vis_chain), + (activate_vis), (gst_play_sink_reconfigure), + (gst_play_sink_set_flags), (gst_play_sink_get_flags), + (gst_play_sink_change_state): + * gst/playback/gstplaysink.h: + Use flags to configure the sink pipelines. + Add tee before audio pipeline so that we can use it for visualisations. + Start working on integrating visualisations. + Remove mode, we can do everything with the flags now. + Add method to configue the sink pipeline. + +2008-01-06 16:36:32 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Update to GMemoryInputStream API changes in GLib SVN and require gio-2.0 >= 2.15.1 for this. Fixes bug #507584. + Original commit message from CVS: + * configure.ac: + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_get_size): + * tests/check/pipelines/gio.c: (free_input), (GST_START_TEST): + Update to GMemoryInputStream API changes in GLib SVN and require + gio-2.0 >= 2.15.1 for this. Fixes bug #507584. + We can also report the duration for every GSeekable, not only + GFileInputStream and GMemoryInputStream. + +2008-01-06 14:39:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/theoraenc.c: Turn these functions into macros so we can see right away where the failure occured. + Original commit message from CVS: + * tests/check/pipelines/theoraenc.c: (check_buffer_is_header), + (check_buffer_timestamp), (check_buffer_duration): + Turn these functions into macros so we can see right away + where the failure occured. + +2008-01-05 22:25:05 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.c: Add debugging information to understand how X calculates the stride for XvImages. + Original commit message from CVS: + 2008-01-05 Julien Moutte <julien@fluendo.com> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new): Add + debugging information to understand how X calculates the stride + for XvImages. + +2008-01-03 20:33:58 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/volume/: Use GstAudioFilter as base class for the volume element instead of plain GstBaseTransform. + Original commit message from CVS: + * gst/volume/Makefile.am: + * gst/volume/gstvolume.c: (volume_choose_func), + (gst_volume_base_init), (gst_volume_class_init), (gst_volume_init), + (volume_setup): + * gst/volume/gstvolume.h: + Use GstAudioFilter as base class for the volume element instead of + plain GstBaseTransform. + +2008-01-03 07:17:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/gstaudiofilter.c: Don't set element details for the abstract GstAudioFilter class. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audio_filter_get_type): + Don't set element details for the abstract GstAudioFilter class. + +2008-01-02 12:09:48 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/gstaudiofilter.c: Implement get_unit_size() vmethod of GstBaseTransform. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiofilter.c: + (gst_audio_filter_class_init), (gst_audio_filter_get_unit_size): + Implement get_unit_size() vmethod of GstBaseTransform. + +2008-01-01 12:53:48 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/pbutils/: Use glib-enum generator to have a proper enum GType for + Original commit message from CVS: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/pbutils.h: + Use glib-enum generator to have a proper enum GType for + GST_TYPE_INSTALL_PLUGINS_RETURN so we can easily wrap it in bindings. + +2008-01-01 01:21:47 +0000 David Schleef <ds@schleef.org> + + tests/check/: Reenable theoraenc test, which fails on the buildbot but not locally. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/pipelines/theoraenc.c: + Reenable theoraenc test, which fails on the buildbot but + not locally. + +2007-12-31 21:31:01 +0000 David Schleef <ds@schleef.org> + + docs/: Add *-undeclared.txt to fix buildbot. + Original commit message from CVS: + * docs/libs/.cvsignore: + * docs/plugins/.cvsignore: + Add *-undeclared.txt to fix buildbot. + +2007-12-31 20:45:28 +0000 David Schleef <ds@schleef.org> + + tests/check/Makefile.am: Second attempt at disabling theoraenc test long enough to get buildbot to compile -base. + Original commit message from CVS: + * tests/check/Makefile.am: + Second attempt at disabling theoraenc test long enough to + get buildbot to compile -base. + +2007-12-31 20:21:20 +0000 David Schleef <ds@schleef.org> + + tests/check/pipelines/theoraenc.c: Disable theoraenc test long enough to get the buildbot to compile a recent -base. + Original commit message from CVS: + * tests/check/pipelines/theoraenc.c: + Disable theoraenc test long enough to get the buildbot to + compile a recent -base. + +2007-12-31 13:17:29 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Make sure we reset the slider value to 0.0 without racing against a possible g_idle that ... + Original commit message from CVS: + * tests/examples/seek/seek.c: (stop_cb): + Make sure we reset the slider value to 0.0 without racing against a + possible g_idle that sets it to something else. + +2007-12-31 00:32:53 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + sys/ximage/ximagesink.c: fix typo + Original commit message from CVS: + * sys/ximage/ximagesink.c: + fix typo + +2007-12-30 19:21:16 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspdefs.*: Add Location header so that we can start implementing redirects. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspdefs.c: (rtsp_init_status): + * gst-libs/gst/rtsp/gstrtspdefs.h: + Add Location header so that we can start implementing redirects. + See #506025. + +2007-12-29 20:55:39 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + gst/subparse/gstssaparse.c: combine if's + Original commit message from CVS: + * gst/subparse/gstssaparse.c: + combine if's + +2007-12-29 19:23:59 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + gst/subparse/gstssaparse.c: remove duplicate log message + Original commit message from CVS: + * gst/subparse/gstssaparse.c: + remove duplicate log message + +2007-12-29 17:29:17 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Update to latest API changes in GLib/GIO and require at least gio-2.0 2.15.0 for this. + Original commit message from CVS: + * configure.ac: + * ext/gio/gstgio.c: + * ext/gio/gstgio.h: + * ext/gio/gstgiobasesink.h: + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_get_size): + * ext/gio/gstgiobasesrc.h: + * ext/gio/gstgiosink.c: (gst_gio_sink_start): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.h: + * ext/gio/gstgiostreamsink.h: + * ext/gio/gstgiostreamsrc.h: + * tests/check/pipelines/gio.c: + Update to latest API changes in GLib/GIO and require at least + gio-2.0 2.15.0 for this. + * ext/gio/Makefile.am: + Add GST_PLUGIN_LDFLAGS to LDFLAGS. + +2007-12-29 16:23:23 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/libvisual/visual.c: Fix 'xyz may be used uninitialized' compiler warnings caused by broken g_assert_not_reached()... + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_chain): + Fix 'xyz may be used uninitialized' compiler warnings caused + by broken g_assert_not_reached() macro in GLib-2.15.x and don't + abort() in any case but properly report the error. + +2007-12-28 09:00:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin2.c: Code cleanups. + Original commit message from CVS: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_finalize), (gst_play_bin_set_uri), + (gst_play_bin_set_suburi), (gst_play_bin_set_property), + (gst_play_bin_get_property), (pad_removed_cb), (drained_cb), + (autoplug_select_cb), (activate_group), (deactivate_group), + (setup_next_source), (save_current_group), + (gst_play_bin_change_state): + Code cleanups. + Remove next-uri, we can use the uri property just fine. + Fix some crasher. + Unref uridecodebin when switching. + Fix going to READY. + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gst_play_sink_init), (gst_play_sink_dispose), + (gst_play_sink_finalize), (gst_play_sink_vis_unblocked), + (gst_play_sink_vis_blocked), (gst_play_sink_set_video_sink), + (gst_play_sink_set_audio_sink), (gst_play_sink_set_vis_plugin), + (gst_play_sink_set_property), (gst_play_sink_get_property), + (gen_video_chain), (gen_text_element), (gen_audio_chain), + (gen_vis_element), (gst_play_sink_get_mode), + (gst_play_sink_set_mode), (gst_play_sink_set_flags), + (gst_play_sink_get_flags), (gst_play_sink_request_pad), + (gst_play_sink_release_pad), (gst_play_sink_send_event_to_sink), + (gst_play_sink_change_state): + * gst/playback/gstplaysink.h: + Add some locking to make things threadsafe. + * gst/playback/test7.c: (about_to_finish_cb): + Fix test. + +2007-12-22 12:06:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videoscale/gstvideoscale.c: Don't claim to be able to handle/transform caps that can't really be handled by the c... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_set_property), + (gst_video_scale_get_property), (gst_video_scale_transform_caps), + (gst_video_scale_transform): + Don't claim to be able to handle/transform caps that can't really + be handled by the currently selected scaling method (here: RGB or + packed YUV with 4-tap method). Also add locking to method property. + * tests/check/pipelines/simple-launch-lines.c: (setup_pipeline), + (test_basetransform_based): + Some test pipelines for the above (not entirely valgrind clean yet + apparently). + +2007-12-22 05:19:00 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/video/video.*: Add additional RGBA and RGB-24 video formats. + Original commit message from CVS: + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + Add additional RGBA and RGB-24 video formats. + +2007-12-21 22:46:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Don't use GST_PLUGIN_DEFINE_STATIC, it's not portable and will be deprecated in the future (see #498924). + Original commit message from CVS: + * tests/check/elements/playbin.c: (test_sink_usage_video_only_stream), + (test_suburi_error_unknowntype), (test_suburi_error_invalidfile), + (test_suburi_error_wrongproto), (test_missing_primary_decoder): + * tests/check/libs/cddabasesrc.c: (GST_START_TEST), (GST_START_TEST), + (cddabasesrc_suite): + Don't use GST_PLUGIN_DEFINE_STATIC, it's not portable and will be + deprecated in the future (see #498924). + +2007-12-21 22:26:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreamselector.c: Don't leak event. + Original commit message from CVS: + * gst/playback/gststreamselector.c: (gst_selector_pad_event): + Don't leak event. + +2007-12-20 19:43:25 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + gst-libs/gst/riff/riff-read.c: Use GST_ROUND_UP_2 macro + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: + Use GST_ROUND_UP_2 macro + +2007-12-20 17:13:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/.cvsignore: Ignore more. + Original commit message from CVS: + * gst/playback/.cvsignore: + Ignore more. + +2007-12-20 10:41:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + Make switching off of subtitles work. To avoid all kind of problems with unlinking of the subtitle input, we just kee... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init): + * gst/playback/gstplaybasebin.c: (set_subtitles_visible), + (set_active_source): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (setup_sinks), (playbin_set_subtitles_visible): + Make switching off of subtitles work. To avoid all kind of + problems with unlinking of the subtitle input, we just keep + the subtitle inputs linked as they are and tell textoverlay + not to render them. Fixes #373011. + Other subtitle switching issues (esp. when there are both + external and in-stream subtitles) remain. They'll be solved + in playbin2. + +2007-12-18 16:21:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gststreamselector.c: Init the pad segment too. + Original commit message from CVS: + * gst/playback/gststreamselector.c: (gst_selector_pad_init): + Init the pad segment too. + +2007-12-18 15:56:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Improve debug output. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func), + (gst_audioringbuffer_open_device), + (gst_audioringbuffer_close_device), (gst_audioringbuffer_acquire), + (gst_audioringbuffer_release), (gst_audioringbuffer_start), + (gst_audioringbuffer_pause), (gst_audioringbuffer_stop), + (gst_audio_sink_create_ringbuffer): + Improve debug output. + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_start), + (gst_ring_buffer_pause), (gst_ring_buffer_delay): + Prevent some functions from doing things and failing when the + ringbuffer is not yet acquired. + +2007-12-18 15:32:49 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/interfaces/interfaces.h: Also remove interfaces.h from CVS as it is not needed anymore. + Original commit message from CVS: + * gst-libs/gst/interfaces/interfaces.h: + Also remove interfaces.h from CVS as it is not needed anymore. + +2007-12-18 15:20:12 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/interfaces/Makefile.am: interfaces.h is not used anymore so remove it from the build process. + Original commit message from CVS: + * gst-libs/gst/interfaces/Makefile.am: + interfaces.h is not used anymore so remove it from the build + process. + +2007-12-18 01:01:23 +0000 David Schleef <ds@schleef.org> + + gst/videotestsrc/gstvideotestsrc.*: Add a "blink" pattern. Turn on the pain. Apologies. It's useful for testing ve... + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + Add a "blink" pattern. Turn on the pain. Apologies. It's useful + for testing vertical refresh synchronization. + +2007-12-18 00:13:26 +0000 David Schleef <ds@schleef.org> + + Add new GstVideFormat enum and write a bunch of helper functions based around it. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/video/video.c: + * gst-libs/gst/video/video.h: + Add new GstVideFormat enum and write a bunch of helper functions + based around it. + +2007-12-17 23:41:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + Makefile.am: Use new common/win32.mak. + Original commit message from CVS: + * Makefile.am: + Use new common/win32.mak. + +2007-12-17 16:44:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Add debug info. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create), (gst_base_audio_src_change_state): + Add debug info. + When going from PLAYING to PAUSED, pause the ringbuffer before calling + the parent state change function, just like the audiosink, because the + parent waits for the element to finish its processing before completing + the state change. This makes going to PAUSED a lot snappier. + When going from READY to PAUSED, don't allow the ringbuffer to start + yet. + +2007-12-17 00:01:00 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Yet another fix for broken software that produce files with an empty blockalign field... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Yet another fix for broken software that produce files with an empty + blockalign field. Instead of completely failing, make a second attempt + at guessing the width/depth by looking at strf->size. + +2007-12-16 23:52:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/: Turn a few g_assert_not_reached() into g_return_val_if_reached() to avoid compiler warnings (#503930). + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_do_seek), + (gst_cdda_base_src_handle_track_seek), (gst_cdda_base_src_create): + * gst-libs/gst/pbutils/install-plugins.c: + (gst_install_plugins_spawn_child), (gst_install_plugins_supported): + * gst-libs/gst/pbutils/missing-plugins.c: + (gst_missing_plugin_message_get_installer_detail), + (gst_missing_encoder_installer_detail_new): + * gst-libs/gst/rtsp/gstrtspconnection.c: (gst_rtsp_connection_send): + * gst-libs/gst/rtsp/gstrtspmessage.c: (gst_rtsp_message_unset): + Turn a few g_assert_not_reached() into g_return_val_if_reached() to + avoid compiler warnings (#503930). + +2007-12-16 23:46:16 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Be apologetic of software that use the 'jpeg' instead of 'JPEG' FOURCC for jpeg video... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Be apologetic of software that use the 'jpeg' instead of 'JPEG' FOURCC + for jpeg video streams. + Add the 'avc1'/'AVC1' fourcc mapping for h264, same software-comment as + for the above modification. + +2007-12-15 17:27:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/xoverlay.c: More guards (we don't want klass to end up being NULL). + Original commit message from CVS: + * gst-libs/gst/interfaces/xoverlay.c: (gst_x_overlay_expose), + (gst_x_overlay_handle_events): + More guards (we don't want klass to end up being NULL). + +2007-12-15 03:40:34 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Use new gst_base_transform_set_gap_aware() function as volume correctly handles GST_BUFFER_FLAG_GAP. Require core 0.1... + Original commit message from CVS: + * configure.ac: + * gst/volume/gstvolume.c: (gst_volume_init): + Use new gst_base_transform_set_gap_aware() function as volume + correctly handles GST_BUFFER_FLAG_GAP. Require core 0.10.15.1 + for this. + +2007-12-14 19:06:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Don't go to READY on EOS as this avoids testing of seeking and restarting after EOS, use ... + Original commit message from CVS: + * tests/examples/seek/seek.c: (msg_segment_done), (main): + Don't go to READY on EOS as this avoids testing of seeking and + restarting after EOS, use the stop button when you want to READY. + Don't try to do a flushing seek in segment-done, it does not make + sense to use this for gapless playback and is not needed. + +2007-12-14 18:46:12 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Use separate timers for input and output rates. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_init), (gst_queue_finalize), + (reset_rate_timer), (update_in_rates), (update_out_rates), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue), + (gst_queue_chain), (gst_queue_loop): + Use separate timers for input and output rates. + Pause measuring the output rate when we block for more data. + See #503262. + +2007-12-14 16:23:06 +0000 Christian Schaller <uraeus@gnome.org> + + * gst/speexresample/Makefile.am: + update spec file and add two missing files for disting + Original commit message from CVS: + update spec file and add two missing files for disting + +2007-12-14 09:24:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Pause the timer to measure the input rate when we block because the queue is filled. See #5... + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_chain): + Pause the timer to measure the input rate when we block because the + queue is filled. See #503262. + +2007-12-13 15:54:00 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Close control sockets. Fixes #503440. + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_free): + Close control sockets. Fixes #503440. + +2007-12-13 12:31:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Expose the right pad in the right place with the right element. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (analyze_new_pad), (connect_pad): + Expose the right pad in the right place with the right element. + +2007-12-13 11:40:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/descriptions.c: Add description for 'private' dts caps (who come up with that name?). + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (formats): + Add description for 'private' dts caps (who come up with that name?). + +2007-12-13 10:10:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + Makefile.am: Add check-exports target and run it with 'make check'. + Original commit message from CVS: + * Makefile.am: + Add check-exports target and run it with 'make check'. + * configure.ac: + Be stricter about what we export in our libraries: change regexp so that + we only export _gst_foo(), but not __gst_foo(). + * gst-libs/gst/cdda/base64.h: (rfc822_binary): + * gst-libs/gst/cdda/sha1.h: (sha_init), (sha_update), (sha_final): + Change internal functions to __gst_foo so they dont' get exported. + * win32/common/libgstaudio.def: + Add missing symbols. + +2007-12-11 21:18:57 +0000 David Schleef <ds@schleef.org> + + * ChangeLog: + ChangeLog: remove conflict markers + Original commit message from CVS: + ChangeLog: remove conflict markers + +2007-12-11 17:14:13 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/: Use gst_tag_freeform_string_to_utf8() here, which also takes into account any character sets specified... + Original commit message from CVS: + * ext/gnomevfs/Makefile.am: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_unicodify): + Use gst_tag_freeform_string_to_utf8() here, which also takes + into account any character sets specified by the user via + environment variables. + +2007-12-10 15:21:41 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audioconvert/Makefile.am: Also link to libm. + Original commit message from CVS: + * gst/audioconvert/Makefile.am: + Also link to libm. + +2007-12-10 15:13:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: No need for floating point operations here. avoids having to link against the math li... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + No need for floating point operations here. avoids having to link + against the math library too. + +2007-12-10 11:16:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add one or two missing formats. Generate ADPCM description dynamically depending on layout/format. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (formats), + (format_info_get_desc): + * tests/check/libs/pbutils.c: (GST_START_TEST), (caps_strings), + (GST_START_TEST): + Add one or two missing formats. Generate ADPCM description + dynamically depending on layout/format. + +2007-12-09 04:28:38 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Don't define GST_DISABLE_DEPRECATED for releases. Fixes #498181. + Original commit message from CVS: + * configure.ac: + Don't define GST_DISABLE_DEPRECATED for releases. Fixes #498181. + +2007-12-08 18:38:39 +0000 Robin Stocker <robin.stocker@gmx.ch> + + gst/subparse/gstsubparse.c: Some .srt files start with chunk number 0 and not chunk number 1, recognise and accept th... + Original commit message from CVS: + Patch by: Robin Stocker <robin dot stocker at gmx dot ch> + * gst/subparse/gstsubparse.c: (gst_sub_parse_data_format_autodetect): + Some .srt files start with chunk number 0 and not chunk number 1, + recognise and accept those as well (fixes #502497). + * tests/check/elements/subparse.c: (srt_input), (srt_input0), + (test_src): + Add unit test for the above. + +2007-12-06 12:08:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplay-enum.*: Add missing files. + Original commit message from CVS: + * gst/playback/gstplay-enum.c: + (register_gst_autoplug_select_result), + (gst_autoplug_select_result_get_type): + * gst/playback/gstplay-enum.h: + Add missing files. + +2007-12-05 17:11:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/Makefile.am: Group decodebin2 and uridecodebin into the same plugin so that they can share the GEnumType. + Original commit message from CVS: + * gst/playback/Makefile.am: + Group decodebin2 and uridecodebin into the same plugin so that they + can share the GEnumType. + * gst/playback/gstdecodebin2.c: (_gst_array_accumulator), + (_gst_select_accumulator), (gst_decode_bin_class_init), + (gst_decode_bin_init), (gst_decode_bin_autoplug_sort), + (gst_decode_bin_autoplug_select), (gst_decode_bin_autoplug_add), + (analyze_new_pad), (connect_pad), (gst_decode_bin_plugin_init): + Add signal to sort factories instead of the more awkward autoplug-select + signal. + Modify autoplug_select so that we can try, skip or expose the + autopluggin of an element on a pad. + * gst/playback/gstfactorylists.c: (compare_ranks), + (decoders_filter), (sinks_filter), (gst_factory_list_is_type), + (element_filter), (gst_factory_list_get_elements), + (gst_factory_list_debug), (gst_factory_list_filter): + * gst/playback/gstfactorylists.h: + Simplify the API, allow getting elements based on mask. + * gst/playback/gstplay-marshal.list: + Add some more marshallers. + * gst/playback/gstplaybin2.c: (init_group), (gst_play_bin_init), + (gst_play_bin_finalize), (pad_removed_cb), (autoplug_factories_cb), + (autoplug_select_cb), (activate_group): + Add support for managing non-raw sinks by providing a custom element and + sink list to decodebin2. + Try to plug non-raw sinks when decodebin2 using autoplug-select of + decodebin2. + * gst/playback/gstplaysink.c: (gen_video_chain), (gen_audio_chain), + (gst_play_sink_set_mode), (gst_play_sink_request_pad): + * gst/playback/gstplaysink.h: + Add support for raw and non-raw sinks. + Add support to force sinks selected by playbin2. + Don't plug raw converters for non-raw sinks. + * gst/playback/gsturidecodebin.c: (_gst_array_accumulator), + (_gst_select_accumulator), (gst_uri_decode_bin_class_init), + (proxy_autoplug_select_signal), (gst_uri_decode_bin_plugin_init), + (plugin_init): + Use right accumulators. + Proxy new signal. + +2007-12-03 13:47:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Use runnning time as the base time instead of the timestamp. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push): + Use runnning time as the base time instead of the timestamp. + Spotted by Saur on IRC. + +2007-12-03 11:32:30 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Add 'WVC1' codec mapping for Windows Media VC-1 video codec. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add 'WVC1' codec mapping for Windows Media VC-1 video codec. + +2007-12-03 10:58:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: If we find a new serial number but it does not contain a BOS page, make sure we initialize the... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_bisect_forward_serialno), + (gst_ogg_demux_read_chain): + If we find a new serial number but it does not contain a BOS page, make + sure we initialize the chain to NULL because else we will try to scan it + and crash. Fixes #500763 + +2007-11-30 17:47:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Refactor some common code to filter factories and check caps compat. + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstfactorylists.c: (compare_ranks), (print_feature), + (get_feature_array), (decoders_filter), (sinks_filter), + (gst_factory_list_get_decoders), (gst_factory_list_get_sinks), + (gst_factory_list_filter): + * gst/playback/gstfactorylists.h: + Refactor some common code to filter factories and check caps compat. + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (gst_decode_bin_dispose), + (gst_decode_bin_autoplug_continue), + (gst_decode_bin_autoplug_factories), + (gst_decode_bin_autoplug_select), (analyze_new_pad), + (find_compatibles): + * gst/playback/gstplaybin.c: + * gst/playback/gstplaybin2.c: (gst_play_bin_class_init), + (gst_play_bin_init), (gst_play_bin_finalize), + (autoplug_factories_cb), (activate_group): + * gst/playback/gstqueue2.c: + * gst/playback/gsturidecodebin.c: (proxy_unknown_type_signal), + (proxy_autoplug_continue_signal), + (proxy_autoplug_factories_signal), (proxy_autoplug_select_signal), + (proxy_drained_signal): + Add some more debug info and use factor filtering code. + +2007-11-26 13:19:46 +0000 Julien Moutte <julien@moutte.net> + + configure.ac: Add QuickTime Wrapper plug-in. + Original commit message from CVS: + 2007-11-26 Julien Moutte <julien@fluendo.com> + * configure.ac: Add QuickTime Wrapper plug-in. + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_push_drain), (gst_speex_resample_process): Fix + build on Mac OS X Leopard. Incorrect printf format arguments. + * sys/Makefile.am: + * sys/qtwrapper/Makefile.am: + * sys/qtwrapper/audiodecoders.c: + (qtwrapper_audio_decoder_base_init), + (qtwrapper_audio_decoder_class_init), + (qtwrapper_audio_decoder_init), + (clear_AudioStreamBasicDescription), (fill_indesc_mp3), + (fill_indesc_aac), (fill_indesc_samr), (fill_indesc_generic), + (make_samr_magic_cookie), (open_decoder), + (qtwrapper_audio_decoder_sink_setcaps), (process_buffer_cb), + (qtwrapper_audio_decoder_chain), + (qtwrapper_audio_decoder_sink_event), + (qtwrapper_audio_decoders_register): + * sys/qtwrapper/codecmapping.c: (audio_caps_from_string), + (fourcc_to_caps): + * sys/qtwrapper/codecmapping.h: + * sys/qtwrapper/imagedescription.c: (image_description_for_avc1), + (image_description_for_mp4v), (image_description_from_stsd_buffer), + (image_description_from_codec_data): + * sys/qtwrapper/imagedescription.h: + * sys/qtwrapper/qtutils.c: (get_name_info_from_component), + (get_output_info_from_component), (dump_avcc_atom), + (dump_image_description), (dump_codec_decompress_params), + (addSInt32ToDictionary), (dump_cvpixel_buffer), + (DestroyAudioBufferList), (AllocateAudioBufferList): + * sys/qtwrapper/qtutils.h: + * sys/qtwrapper/qtwrapper.c: (plugin_init): + * sys/qtwrapper/qtwrapper.h: + * sys/qtwrapper/videodecoders.c: + (qtwrapper_video_decoder_base_init), + (qtwrapper_video_decoder_class_init), + (qtwrapper_video_decoder_init), (qtwrapper_video_decoder_finalize), + (fill_image_description), (new_image_description), (close_decoder), + (open_decoder), (qtwrapper_video_decoder_sink_setcaps), + (decompressCb), (qtwrapper_video_decoder_chain), + (qtwrapper_video_decoder_sink_event), + (qtwrapper_video_decoders_register): Initial import of QuickTime + wrapper jointly developped by Songbird authors (Pioneers of the + Inevitable) and Fluendo. + +2007-11-26 12:25:55 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/: Add GAP-flag support. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/volume/gstvolume.c: + * gst/volume/gstvolume.h: + Add GAP-flag support. + +2007-11-26 08:43:25 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/: Update speex resampler to latest SVN. We're now down to only the changes noted in README again. + Original commit message from CVS: + * gst/speexresample/README: + * gst/speexresample/arch.h: + * gst/speexresample/resample.c: (resampler_basic_direct_single), + (resampler_basic_direct_double), + (resampler_basic_interpolate_single), + (resampler_basic_interpolate_double), + (speex_resampler_process_native), (speex_resampler_process_float), + (speex_resampler_process_int), + (speex_resampler_process_interleaved_float), + (speex_resampler_process_interleaved_int), + (speex_resampler_get_input_latency), + (speex_resampler_get_output_latency): + * gst/speexresample/speex_resampler.h: + Update speex resampler to latest SVN. We're now down to only the + changes noted in README again. + * gst/speexresample/speex_resampler_wrapper.h: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_push_drain), (gst_speex_resample_query): + Adjust to API changes. + +2007-11-24 15:02:01 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Increase the range of the rate selector as I would like to test QOS behavior at higher fo... + Original commit message from CVS: + 2007-11-24 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (main): Increase the range of the + rate selector as I would like to test QOS behavior at higher + forward and reverse playback speed like say 64x. + +2007-11-23 10:21:31 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Only post the latency message if we have a resampler state already. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_update_state): + Only post the latency message if we have a resampler state already. + +2007-11-23 10:21:11 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioresample/gstaudioresample.c: Implement latency query. + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init), + (audioresample_query), (audioresample_query_type), + (gst_audioresample_set_property): + Implement latency query. + +2007-11-23 10:01:33 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Also post GST_MESSAGE_LATENCY if the latency changes. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_update_state): + Also post GST_MESSAGE_LATENCY if the latency changes. + +2007-11-23 08:48:50 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/: Add functions to push the remaining samples and to get the latency of the resampler. These will g... + Original commit message from CVS: + * gst/speexresample/resample.c: (speex_resampler_get_latency), + (speex_resampler_drain_float), (speex_resampler_drain_int), + (speex_resampler_drain_interleaved_float), + (speex_resampler_drain_interleaved_int): + * gst/speexresample/speex_resampler.h: + * gst/speexresample/speex_resampler_wrapper.h: + Add functions to push the remaining samples and to get the latency + of the resampler. These will get added to Speex SVN in this or a + slightly changed form at some point too and should get merged then + again. + * gst/speexresample/gstspeexresample.c: (gst_speex_resample_init), + (gst_speex_resample_init_state), + (gst_speex_resample_transform_size), + (gst_speex_resample_push_drain), (gst_speex_resample_event), + (gst_speex_fix_output_buffer), (gst_speex_resample_process), + (gst_speex_resample_query), (gst_speex_resample_query_type): + Drop the prepending zeroes and output the remaining samples on EOS. + Also properly implement the latency query for this. speexresample + should be completely ready for production use now. + +2007-11-21 18:02:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Our EOS time contains the base_time, _wait_eos() expects a running_time so we ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain): + Our EOS time contains the base_time, _wait_eos() expects a running_time + so we have to subtract the base_time again before calling the function. + This fixes an EOS regression where the base_time was added twice and EOS + took longer and longer in certain situations. + Fixes #498767. + +2007-11-21 13:04:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + Expose methods for some object properties so that subclasses can more easily configure them. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstbaseaudiosink.c: (slave_method_get_type), + (gst_base_audio_sink_set_provide_clock), + (gst_base_audio_sink_get_provide_clock), + (gst_base_audio_sink_set_slave_method), + (gst_base_audio_sink_get_slave_method), + (gst_base_audio_sink_set_property), + (gst_base_audio_sink_get_property), (gst_base_audio_sink_drain), + (gst_base_audio_sink_none_slaving), + (gst_base_audio_sink_handle_slaving): + * gst-libs/gst/audio/gstbaseaudiosink.h: + Expose methods for some object properties so that subclasses can more + easily configure them. + Added slave method none, that completely disables slaving to the + internal clock. + API: gst_base_audio_sink_set_provide_clock() + API: gst_base_audio_sink_get_provide_clock() + API: gst_base_audio_sink_set_slave_method() + API: gst_base_audio_sink_get_slave_method() + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_set_provide_clock), + (gst_base_audio_src_get_provide_clock), + (gst_base_audio_src_set_property), + (gst_base_audio_src_get_property), (gst_base_audio_src_create): + * gst-libs/gst/audio/gstbaseaudiosrc.h: + Expose methods for some object properties so that subclasses can more + easily configure them. + API: gst_base_audio_src_set_provide_clock() + API: gst_base_audio_src_get_provide_clock() + +2007-11-21 10:18:56 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/README: Add README explaining where the resampling code was taken from and which changes were done. + Original commit message from CVS: + * gst/speexresample/README: + Add README explaining where the resampling code was taken from + and which changes were done. + * gst/speexresample/resample.c: (speex_alloc), (speex_realloc), + (speex_free): + Use g_malloc() and friends instead of malloc() to achieve higher + portability and define the functions inline. + * gst/speexresample/speex_resampler.h: + Add back some useless preprocessor stuff to keep the diff between + our version and the one from the Speex SVN repository lower. + +2007-11-20 20:23:25 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: Some small cleanup and addition of a TODO item. + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_fix_output_buffer), (gst_speex_resample_transform): + Some small cleanup and addition of a TODO item. + +2007-11-20 12:56:00 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/Makefile.am: Add missing file. + Original commit message from CVS: + * gst/speexresample/Makefile.am: + Add missing file. + +2007-11-20 07:53:56 +0000 Joe Peterson <lavajoe@gentoo.org> + + gst-libs/gst/sdp/gstsdpmessage.c: Fix compilation on FreeBSD (Gentoo). Fixes #498228. + Original commit message from CVS: + Patch by: Joe Peterson <lavajoe at gentoo dot org> + * gst-libs/gst/sdp/gstsdpmessage.c: + Fix compilation on FreeBSD (Gentoo). Fixes #498228. + +2007-11-20 07:47:27 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add speexresample to the docs and while at that do a make update. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.signals: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-equalizer.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-filter.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstrtpmanager.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-nsfdec.xml: + * docs/plugins/inspect/plugin-replaygain.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-spcdec.xml: + * docs/plugins/inspect/plugin-spectrum.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-xingheader.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * gst/speexresample/gstspeexresample.h: + Add speexresample to the docs and while at that do a make update. + +2007-11-20 07:30:30 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/speexresample/gstspeexresample.c: If the resampler gives less output samples than expected adjust the output buff... + Original commit message from CVS: + * gst/speexresample/gstspeexresample.c: + (gst_speex_fix_output_buffer), (gst_speex_resample_process): + If the resampler gives less output samples than expected + adjust the output buffer and print a warning. + +2007-11-20 07:02:45 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add resample element based on the Speex resampling algorithm. + Original commit message from CVS: + * configure.ac: + * gst/speexresample/arch.h: + * gst/speexresample/fixed_generic.h: + * gst/speexresample/gstspeexresample.c: + (gst_speex_resample_base_init), (gst_speex_resample_class_init), + (gst_speex_resample_init), (gst_speex_resample_start), + (gst_speex_resample_stop), (gst_speex_resample_get_unit_size), + (gst_speex_resample_transform_caps), + (gst_speex_resample_init_state), (gst_speex_resample_update_state), + (gst_speex_resample_reset_state), (gst_speex_resample_parse_caps), + (gst_speex_resample_transform_size), (gst_speex_resample_set_caps), + (gst_speex_resample_event), (gst_speex_resample_check_discont), + (gst_speex_resample_process), (gst_speex_resample_transform), + (gst_speex_resample_set_property), + (gst_speex_resample_get_property), (plugin_init): + * gst/speexresample/gstspeexresample.h: + * gst/speexresample/resample.c: (speex_alloc), (speex_realloc), + (speex_free), (compute_func), (main), (sinc), (cubic_coef), + (resampler_basic_direct_single), (resampler_basic_direct_double), + (resampler_basic_interpolate_single), + (resampler_basic_interpolate_double), (update_filter), + (speex_resampler_init), (speex_resampler_init_frac), + (speex_resampler_destroy), (speex_resampler_process_native), + (speex_resampler_process_float), (speex_resampler_process_int), + (speex_resampler_process_interleaved_float), + (speex_resampler_process_interleaved_int), + (speex_resampler_set_rate), (speex_resampler_get_rate), + (speex_resampler_set_rate_frac), (speex_resampler_get_ratio), + (speex_resampler_set_quality), (speex_resampler_get_quality), + (speex_resampler_set_input_stride), + (speex_resampler_get_input_stride), + (speex_resampler_set_output_stride), + (speex_resampler_get_output_stride), (speex_resampler_skip_zeros), + (speex_resampler_reset_mem), (speex_resampler_strerror): + * gst/speexresample/speex_resampler.h: + * gst/speexresample/speex_resampler_float.c: + * gst/speexresample/speex_resampler_int.c: + * gst/speexresample/speex_resampler_wrapper.h: + Add resample element based on the Speex resampling algorithm. + +2007-11-19 12:30:22 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + tests/check/libs/fft.c: Fix scaling to really have dB instead of something else. + Original commit message from CVS: + * tests/check/libs/fft.c: (GST_START_TEST): + Fix scaling to really have dB instead of something else. + +2007-11-19 12:08:16 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: There's a nice macro to check + Original commit message from CVS: + 2007-11-19 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (main): There's a nice macro to + check + GTK version, use it. + +2007-11-19 11:59:20 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Try to support stable version of GTK. + Original commit message from CVS: + 2007-11-19 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (main): Try to support stable version + of GTK. + +2007-11-17 15:25:15 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/: Fix the build + little README update. + Original commit message from CVS: + * gst/playback/README: + * gst/playback/test7.c: + Fix the build + little README update. + +2007-11-16 16:02:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add playbin2 seek pipeline. + Original commit message from CVS: + * tests/examples/seek/seek.c: (make_playerbin2_pipeline), (main): + Add playbin2 seek pipeline. + +2007-11-16 15:44:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Add playbin2. + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstplayback.c: (plugin_init): + * gst/playback/test7.c: (update_scale), (warning_cb), (error_cb), + (eos_cb), (about_to_finish_cb), (main): + Add playbin2. + Added gapless playback example. + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_plugin_init): + * gst/playback/gstqueue2.c: + * gst/playback/test.c: + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init), + (pad_removed_cb): + * gst/playback/gststreaminfo.h: + Change email. + * gst/playback/gstplaybin2.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (init_group), (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_set_uri), + (gst_play_bin_set_suburi), (gst_play_bin_set_property), + (gst_play_bin_get_property), (gst_play_bin_handle_message), + (pad_added_cb), (pad_removed_cb), (no_more_pads_cb), (perform_eos), + (drained_cb), (unlink_group), (activate_group), + (setup_next_source), (gst_play_bin_change_state), + (gst_play_bin2_plugin_init): + Added raw first version of playbin2. Does chained oggs and gapless + playback fine. No support for raw sinks yet. No visualisations or + subtitles yet. + * gst/playback/gstplaysink.c: (gst_play_sink_get_type), + (gst_play_sink_class_init), (gst_play_sink_init), + (gst_play_sink_dispose), (gst_play_sink_vis_unblocked), + (gst_play_sink_vis_blocked), (gst_play_sink_set_video_sink), + (gst_play_sink_set_audio_sink), (gst_play_sink_set_vis_plugin), + (gst_play_sink_set_property), (gst_play_sink_get_property), + (post_missing_element_message), (free_chain), (add_chain), + (activate_chain), (gen_video_chain), (gen_text_element), + (gen_audio_chain), (gen_vis_element), (gst_play_sink_get_mode), + (gst_play_sink_set_mode), (gst_play_sink_request_pad), + (gst_play_sink_release_pad), (gst_play_sink_send_event_to_sink), + (gst_play_sink_send_event), (gst_play_sink_change_state): + * gst/playback/gstplaysink.h: + Added Element that abstracts the sinks and their pipelines for playbin2. + +2007-11-16 15:05:07 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gststreamselector.*: Improve streamselector, make it select and unselect the current pad more intelligen... + Original commit message from CVS: + * gst/playback/gststreamselector.c: (gst_selector_pad_get_type), + (gst_selector_pad_class_init), (gst_selector_pad_init), + (gst_selector_pad_finalize), (gst_selector_pad_reset), + (gst_selector_pad_get_linked_pads), (gst_selector_pad_event), + (gst_selector_pad_getcaps), (gst_selector_pad_bufferalloc), + (gst_selector_pad_chain), (gst_stream_selector_get_type), + (gst_stream_selector_base_init), (gst_stream_selector_class_init), + (gst_stream_selector_init), (gst_stream_selector_set_property), + (gst_stream_selector_get_linked_pad), + (gst_stream_selector_getcaps), + (gst_stream_selector_is_active_sinkpad), + (gst_stream_selector_activate_sinkpad), + (gst_stream_selector_get_linked_pads), + (gst_stream_selector_request_new_pad), + (gst_stream_selector_release_pad): + * gst/playback/gststreamselector.h: + Improve streamselector, make it select and unselect the current pad more + intelligently. + Subclass GstPad for the sinkpads of the selector. + Handle segments more correctly. + Fix caps negotiation. + Implement release_pad. + +2007-11-16 12:51:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Add drained signal fired when decodebin finishes decoding the data. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), + (gst_decode_group_check_if_drained), (source_pad_event_probe), + (remove_fakesink): + Add drained signal fired when decodebin finishes decoding the data. + Remove deprecated STATE_DIRTY message. + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init), + (unknown_type_cb), (new_decoded_pad_cb), (pad_removed_cb), + (analyse_source), (proxy_drained_signal), (make_decoder), + (source_new_pad), (value_list_append_structure_list), + (handle_redirect_message), (handle_message): + Proxy the new drained signal. + Handle pad removed from decodebin. + Handle redirect messages by sorting multiple redirections based on the + connection speed. + +2007-11-16 11:22:09 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + gst-libs/gst/rtsp/gstrtspmessage.c: Fix leaking headers. Fixes #496761. + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * gst-libs/gst/rtsp/gstrtspmessage.c: (gst_rtsp_message_unset): + Fix leaking headers. Fixes #496761. + +2007-11-16 11:16:58 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + sys/: Don't leak the PAR on errors. Fixes #496731. + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), + (gst_ximagesink_change_state): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get): + Don't leak the PAR on errors. Fixes #496731. + +2007-11-16 10:14:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstid3tag.c: Add mapping for audio cd discid tags, so we can extract them from tags as well (see #34... + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: (user_tag_matches), + (gst_tag_from_id3_user_tag): + Add mapping for audio cd discid tags, so we can extract + them from tags as well (see #347848). Also compare identifiers + in ID3v2 TXXX frames in a case-insensitive way to increase + compatibility when reading tags (discid vs. DiscID vs. DiscId). + +2007-11-16 01:21:40 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-plugins-base.doap: Oops, fix the release name. + Original commit message from CVS: + * gst-plugins-base.doap: + Oops, fix the release name. + +2007-11-16 00:44:58 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-plugins-base.doap: Add 0.10.15 release + Original commit message from CVS: + * gst-plugins-base.doap: + Add 0.10.15 release + +2007-11-16 00:24:55 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.15 === + +2007-11-16 00:14:33 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: releasing 0.10.15, "No need to argue" + Original commit message from CVS: + === release 0.10.15 === + 2007-11-15 Jan Schmidt <jan.schmidt@sun.com> + * configure.ac: + releasing 0.10.15, "No need to argue" + +2007-11-16 00:04:24 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/en_GB.po: + * po/es.po: + * po/fi.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-11-15 21:40:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + win32/vs6/libgstfft.dsp: Convert line endings to DOS. + Original commit message from CVS: + * win32/vs6/libgstfft.dsp: + Convert line endings to DOS. + +2007-11-15 21:14:04 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/: Add a project file for fft plugin and remove socket based plugin which don't build from the workspace.* win32... + Original commit message from CVS: + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstfft.dsp: + * win32/MANIFEST: + Add a project file for fft plugin and remove socket + based plugin which don't build from the workspace.* win32/vs6/libgstaudio.dsp: + * win32/vs6/libgstrtp.dsp: + * win32/vs6/libgsttag.dsp: + Convert line endings back to DOS. + Fixes #496724 + +2007-11-14 12:27:13 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + win32/vs6/: Convert line endings back to DOS + Original commit message from CVS: + * win32/vs6/libgstinterfaces.dsp: + * win32/vs6/libgstrtsp.dsp: + Convert line endings back to DOS + +2007-11-14 11:08:48 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/fft/: Don't include malloc.h which doesn't exist on Mac OSX. + Original commit message from CVS: + * gst-libs/gst/fft/kiss_fft_f32.h: + * gst-libs/gst/fft/kiss_fft_f64.h: + * gst-libs/gst/fft/kiss_fft_s16.h: + * gst-libs/gst/fft/kiss_fft_s32.h: + Don't include malloc.h which doesn't exist on Mac OSX. + Instead, pull in glib.h and use g_malloc/g_free for + consistency. Fixes: #496548 + +2007-11-09 15:54:45 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstdecodebin2.c: Dont leak ghostpad. Fixes #475451. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + Dont leak ghostpad. Fixes #475451. + +2007-11-09 12:21:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + Update some more docs and comments. + Original commit message from CVS: + * docs/design/design-decodebin.txt: + * gst/playback/gstdecodebin2.c: (analyze_new_pad): + Update some more docs and comments. + +2007-11-07 16:47:32 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Require GIO >= 0.1.2 and adjust unit test for an API change. + Original commit message from CVS: + * configure.ac: + * tests/check/pipelines/gio.c: (GST_START_TEST): + Require GIO >= 0.1.2 and adjust unit test for an API change. + +2007-11-07 15:18:54 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.h: Add macro to check if a stream supports seeking. + Original commit message from CVS: + * ext/gio/gstgio.h: + Add macro to check if a stream supports seeking. + * ext/gio/Makefile.am: + * ext/gio/gstgiobasesink.c: (gst_gio_base_sink_base_init), + (gst_gio_base_sink_class_init), (gst_gio_base_sink_init), + (gst_gio_base_sink_finalize), (gst_gio_base_sink_start), + (gst_gio_base_sink_stop), (gst_gio_base_sink_unlock), + (gst_gio_base_sink_unlock_stop), (gst_gio_base_sink_event), + (gst_gio_base_sink_render), (gst_gio_base_sink_query), + (gst_gio_base_sink_set_stream): + * ext/gio/gstgiobasesink.h: + * ext/gio/gstgiobasesrc.c: (gst_gio_base_src_base_init), + (gst_gio_base_src_class_init), (gst_gio_base_src_init), + (gst_gio_base_src_finalize), (gst_gio_base_src_start), + (gst_gio_base_src_stop), (gst_gio_base_src_get_size), + (gst_gio_base_src_is_seekable), (gst_gio_base_src_unlock), + (gst_gio_base_src_unlock_stop), (gst_gio_base_src_check_get_range), + (gst_gio_base_src_create), (gst_gio_base_src_set_stream): + * ext/gio/gstgiobasesrc.h: + Refactor common GIO functions to GstGioBaseSink and GstGioBaseSrc + base classes that only require a GInputStream or GOutputStream to + work. + * ext/gio/gstgiosink.c: (gst_gio_sink_base_init), + (gst_gio_sink_class_init), (gst_gio_sink_init), + (gst_gio_sink_finalize), (gst_gio_sink_start): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.c: (gst_gio_src_base_init), + (gst_gio_src_class_init), (gst_gio_src_init), + (gst_gio_src_finalize), (gst_gio_src_start): + * ext/gio/gstgiosrc.h: + Use the newly created base classes here. + * ext/gio/gstgio.c: (plugin_init): + * ext/gio/gstgiostreamsink.c: (gst_gio_stream_sink_base_init), + (gst_gio_stream_sink_class_init), (gst_gio_stream_sink_init), + (gst_gio_stream_sink_finalize), (gst_gio_stream_sink_set_property), + (gst_gio_stream_sink_get_property): + * ext/gio/gstgiostreamsink.h: + * ext/gio/gstgiostreamsrc.c: (gst_gio_stream_src_base_init), + (gst_gio_stream_src_class_init), (gst_gio_stream_src_init), + (gst_gio_stream_src_finalize), (gst_gio_stream_src_set_property), + (gst_gio_stream_src_get_property): + * ext/gio/gstgiostreamsrc.h: + Implement GstGioStreamSink and GstGioStreamSrc that have a property + to set the GInputStream/GOutputStream that should be used. + * tests/check/Makefile.am: + * tests/check/pipelines/.cvsignore: + * tests/check/pipelines/gio.c: (message_handler), (GST_START_TEST), + (gio_testsuite), (main): + Add unit test for giostreamsrc and giostreamsink. + +2007-11-07 11:48:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Remove nowadays unnecessary workaround for a crash. + Original commit message from CVS: + * ext/gio/gstgio.c: (plugin_init): + Remove nowadays unnecessary workaround for a crash. + * ext/gio/gstgiosink.c: (gst_gio_sink_finalize), + (gst_gio_sink_start), (gst_gio_sink_stop), + (gst_gio_sink_unlock_stop): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.c: (gst_gio_src_finalize), (gst_gio_src_start), + (gst_gio_src_stop), (gst_gio_src_unlock_stop): + * ext/gio/gstgiosrc.h: + Make the finalize function safer, clean up everything that could stay + around. + Reset the cancellable instead of creating a new one after cancelling + some operation. + Don't store the GFile in the element, it's only necessary for creating + the streams. + +2007-11-06 23:35:39 +0000 Sebastien Moutte <sebastien@moutte.net> + + gst-libs/gst/rtp/: Fix some C99-isms and and a missing function that some versions of + Original commit message from CVS: + Patch by: Sebastien Moutte <sebastien moutte net> + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_ntp_to_unix), + (gst_rtcp_unix_to_ntp): + * gst-libs/gst/rtp/gstrtppayloads.c: (gst_rtp_payload_info_for_name): + Fix some C99-isms and and a missing function that some versions of + MSVC don't like too much (#494346). + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstaudio.dsp: + * win32/vs6/libgstrtp.dsp: + * win32/vs6/libgsttag.dsp: + Update vs6 projects files (#494346). + +2007-11-06 16:38:49 +0000 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + + win32/common/: More missing symbols to export (fixes #493986). + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + * win32/common/libgstaudio.def: + * win32/common/libgstcdda.def: + * win32/common/libgstinterfaces.def: + * win32/common/libgstnetbuffer.def: + * win32/common/libgstpbutils.def: + * win32/common/libgstrtp.def: + * win32/common/libgstrtsp.def: + * win32/common/libgsttag.def: + * win32/common/libgstvideo.def: + More missing symbols to export (fixes #493986). + +2007-11-06 11:58:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Remove the magnitude and phase calculation functions as these have very special use cases and can't even be used for ... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/fft/gstfftf32.c: + * gst-libs/gst/fft/gstfftf32.h: + * gst-libs/gst/fft/gstfftf64.c: + * gst-libs/gst/fft/gstfftf64.h: + * gst-libs/gst/fft/gstffts16.c: + * gst-libs/gst/fft/gstffts16.h: + * gst-libs/gst/fft/gstffts32.c: + * gst-libs/gst/fft/gstffts32.h: + * tests/check/libs/fft.c: (GST_START_TEST): + Remove the magnitude and phase calculation functions as these have + very special use cases and can't even be used for the spectrum + element. Also adjust the docs to mention some properties of the used + FFT implemention, i.e. how the values are scaled. Fixes #492098. + +2007-11-06 11:09:30 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Avoid crash when there are external subtitles (fixes #491722). + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (queue_threshold_reached), + (finish_source): + Avoid crash when there are external subtitles (fixes #491722). + +2007-11-03 10:39:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/: 'Could not open resource for writing' is not an acceptable even less so when we're trying to open it to re... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_open): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_open): + 'Could not open resource for writing' is not an acceptable + error message when we can't open the audio device (see #492334), + even less so when we're trying to open it to record something. + +2007-11-02 21:03:01 +0000 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + + win32/common/libgstrtp.def: Add some more missing symbols (#492813). + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + * win32/common/libgstrtp.def: + Add some more missing symbols (#492813). + +2007-11-02 14:59:06 +0000 Thijs Vermeir <thijsvermeir@gmail.com> + + tests/check/elements/audioconvert.c: Add check to make sure that the out caps have a channel layout set on them where... + Original commit message from CVS: + Patch by: Thijs Vermeir <thijsvermeir@gmail.com> + * tests/check/elements/audioconvert.c: (verify_convert): + Add check to make sure that the out caps have a channel layout + set on them where they should have one. + +2007-11-01 13:28:59 +0000 Vincent Torri <vtorri@univ-evry.fr> + + gst-libs/gst/fft/: Include our own _stdint.h instead of sys/types.h, makes MingW happy (#492306). + Original commit message from CVS: + Patch by: Vincent Torri <vtorri at univ-evry dot fr> + * gst-libs/gst/fft/kiss_fft_s16.h: (KISS_FFT_S16_MALLOC): + * gst-libs/gst/fft/kiss_fft_s32.h: (KISS_FFT_S32_MALLOC): + Include our own _stdint.h instead of sys/types.h, makes MingW happy + (#492306). + * gst-libs/gst/rtsp/gstrtspconnection.c: (gst_rtsp_connection_create): + Use _pipe directly, GLib doesn't have a pipe() macro any longer + (it disappeared in GLib 2.14.0) (#492306). + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/sdp/gstsdpmessage.c: + Fix includes and LIBS for win32/Mingw (#492306). + * tests/examples/dynamic/addstream.c (pause_play_stream): + Use more portable g_usleep() instead of sleep() (#492306). + +2007-11-01 12:51:57 +0000 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + + gst-libs/gst/audio/gstringbuffer.c: Return NULL instead of an enum that happens to be 0, fixes warning on MSVC (#4921... + Original commit message from CVS: + Patch by: Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.com> + * gst-libs/gst/audio/gstringbuffer.c: (build_linear_format), + (gst_ring_buffer_parse_caps): + Return NULL instead of an enum that happens to be 0, fixes warning + on MSVC (#492114). + * gst-libs/gst/audio/gstringbuffer.h: + No trailing commas in enum list (for gcc-2.9x). + * gst/videotestsrc/videotestsrc.c: (random_char): + Make information loss explicit instead of implicitly truncating to + eight bits via the return value. Fixes runtime error on MSVC when + using the debug CRT (#492114). + * win32/common/config.h.in: + Fix a bunch of '#undef FOO bar', which MSVC doesn't like (#492114). + * win32/common/libgstinterfaces.def: + * win32/common/libgstrtp.def: + Export a few more symbols (#492114). + +2007-11-01 08:06:13 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/audio.*: Readd the deprecation guards, but preserve compilability. + Original commit message from CVS: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/audio/audio.h: + Readd the deprecation guards, but preserve compilability. + +2007-10-31 17:54:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/gstaudioconvert.c: Preserve channel layout when fixating the number of channels in the output caps, ... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (find_suitable_channel_layout), + (gst_audio_convert_fixate_channels), (gst_audio_convert_fixate_caps): + Preserve channel layout when fixating the number of channels in the + output caps, or make sure there's a suitable channel position layout + set on the caps if required. Fixes #430677. + +2007-10-31 17:32:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/decodebin.c: Make sure the pipeline really operates in push mode as it should in this case. + Original commit message from CVS: + * tests/check/elements/decodebin.c: (test_text_plain_streams): + Make sure the pipeline really operates in push mode as it should + in this case. + +2007-10-31 15:30:15 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/audio.h: Don't guard deprecated enum with #ifndef DISABLE_DEPRECATED, or compilation with DISABLE_... + Original commit message from CVS: + * gst-libs/gst/audio/audio.h: + Don't guard deprecated enum with #ifndef DISABLE_DEPRECATED, or + compilation with DISABLE_DEPRECATED and without REMOVE_DEPRECATED + (ie. normal cvs builds) will fail. + +2007-10-31 12:47:41 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tell gtk-doc about the deprecation guard. Apply more doc fixes. + Original commit message from CVS: + * docs/libs/Makefile.am: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/audio/audio.h: + * gst-libs/gst/interfaces/mixer.c: + tell gtk-doc about the deprecation guard. Apply more doc fixes. + +2007-10-31 12:30:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/audio.c: Add simple unit test to make sure GstValue intersection of channel layouts works the way I ... + Original commit message from CVS: + * tests/check/libs/audio.c: (init_value_to_channel_layout), + (test_channel_layout_value_intersect), (audio_suite): + Add simple unit test to make sure GstValue intersection + of channel layouts works the way I think it does. + +2007-10-30 20:32:14 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix the docs according to what gtk-doc complained about. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudiofilter.h: + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + * gst-libs/gst/sdp/gstsdpmessage.c: + Fix the docs according to what gtk-doc complained about. + +2007-10-30 19:46:02 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/icles/stress-playbin.c: Fix the build. + Original commit message from CVS: + * tests/icles/stress-playbin.c: + Fix the build. + +2007-10-30 15:54:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Post nice/more useful error message if we don't have a decoder for the primary type. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (close_pad_link), (type_found): + * gst/playback/gstdecodebin2.c: (analyze_new_pad): + Post nice/more useful error message if we don't have a decoder for + the primary type. + +2007-10-30 15:07:58 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Be a bit more useful, unblock the pads after we fired the no-more-pads signal so that w... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_group_expose): + Be a bit more useful, unblock the pads after we fired the no-more-pads + signal so that we can use the signal to inspect and connect all pads + without having to keep extra state outside of decodebin. + +2007-10-30 15:00:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gsturidecodebin.c: Implement default signal handler so that we return TRUE when nothing is connected. + Original commit message from CVS: + * gst/playback/gsturidecodebin.c: + (gst_uri_decode_bin_autoplug_continue), + (gst_uri_decode_bin_class_init), (no_more_pads_full): + Implement default signal handler so that we return TRUE when nothing is + connected. + +2007-10-28 11:53:36 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Use the ALSA channel layout as default for wav files without channel layout informati... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: + (gst_riff_wavext_add_channel_layout), + (gst_riff_wave_add_default_channel_layout), + (gst_riff_wavext_get_default_channel_mask), + (gst_riff_create_audio_caps): + Use the ALSA channel layout as default for wav files without channel + layout information. This fixes playback of chan-id.wav on 5.1 systems + for example. Also refactor the channel layout setting a bit and add + more default channel orders. Fixes #489010. + +2007-10-28 11:46:48 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + * ChangeLog: + Use the ALSA channel layout as default for wav files without channel layout information. This fixes playback of chan-... + Original commit message from CVS: + (gst_riff_wavext_add_channel_layout), + (gst_riff_wave_add_default_channel_layout), + (gst_riff_wavext_get_default_channel_mask), + (gst_riff_create_audio_caps): + Use the ALSA channel layout as default for wav files without channel + layout information. This fixes playback of chan-id.wav on 5.1 systems + for example. Also refactor the channel layout setting a bit and add + more default channel orders. Fixes #489010. + +2007-10-26 18:57:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/tag.c: GST_TAG_MUSICBRAINZ_SORTNAME is deprecated and we compile with + Original commit message from CVS: + * tests/check/libs/tag.c: (test_musicbrainz_tag_registration): + GST_TAG_MUSICBRAINZ_SORTNAME is deprecated and we compile with + -DGST_DISABLE_DEPRECATED, so use new GST_TAG_ARTIST_SORTNAME + instead. + +2007-10-26 12:07:14 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update spec file + Original commit message from CVS: + update spec file + +2007-10-25 17:36:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Move subtitle encoding property to decodebin2 so that it can set the property value on ... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), + (gst_decode_bin_dispose), (gst_decode_bin_set_caps), + (gst_decode_bin_set_subs_encoding), + (gst_decode_bin_get_subs_encoding), (gst_decode_bin_set_property), + (gst_decode_bin_get_property), (analyze_new_pad): + Move subtitle encoding property to decodebin2 so that it can set the + property value on all elements that it autoplugs and that require it. + Make caps refcounting more consistent in get/set. + * gst/playback/gsturidecodebin.c: (_gst_boolean_accumulator), + (gst_uri_decode_bin_class_init), (gst_uri_decode_bin_init), + (gst_uri_decode_bin_finalize), (gst_uri_decode_bin_set_property), + (gst_uri_decode_bin_get_property), (proxy_unknown_type_signal), + (proxy_autoplug_continue_signal), + (proxy_autoplug_factories_signal), (proxy_autoplug_select_signal), + (make_decoder): + Proxy properties and relevant signals from the internal decodebin. + Make properties MT safe. + +2007-10-25 15:10:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/: Deprecate GST_TAG_MUSICBRAINZ_SORTNAME, replaced by the newly-added + Original commit message from CVS: + * gst-libs/gst/tag/tag.h: (GST_TAG_MUSICBRAINZ_SORTNAME): + * gst-libs/gst/tag/tags.c: + Deprecate GST_TAG_MUSICBRAINZ_SORTNAME, replaced by the newly-added + GST_TAG_ARTIST_SORTNAME (in an API and ABI compatible way). + * gst-libs/gst/tag/gstid3tag.c: (tag_matches): + Map ID3v2 TSOP, TSOA and TSOT frames to new SORTNAME tags (#414539). + * gst-libs/gst/tag/gstvorbistag.c: (tag_matches), + (gst_tag_to_vorbis_comments): + Map new SORTNAME tags (these tags aren't even semi-official, so I'm + just mapping everything I found in the wild) (#414539). + +2007-10-24 11:07:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Remove the autoplug-sort signal and replace it with a binding friendly autoplug-select signal. + Original commit message from CVS: + Inspired by patch of: René Stadler <mail at renestadler dot de> + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init), + (gst_decode_bin_autoplug_continue), + (gst_decode_bin_autoplug_factories), + (gst_decode_bin_autoplug_select), (analyze_new_pad), (connect_pad), + (find_compatibles): + * gst/playback/gstplay-marshal.list: + Remove the autoplug-sort signal and replace it with a binding friendly + autoplug-select signal. + Add an autoplug-factories signal that can be used to generate a list of + factories to try to autoplug. + Add the GstPad to the autoplugging signal args as it might be needed to + make a good factory selection. + Fix up the marshallers for this. Fixes #407282. + +2007-10-23 14:23:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gsttagdemux.c: Don't abort with an assertion if we receive a seek event with a start type of NONE (s... + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: + Don't abort with an assertion if we receive a seek event with + a start type of NONE (see launchpad bug #155878). + +2007-10-22 10:21:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/: Make sure that before we clean up the X resources, we shutdown and join the event thread. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_event_thread), + (gst_ximagesink_xcontext_get), (gst_ximagesink_xcontext_clear), + (gst_ximagesink_change_state), (gst_ximagesink_reset): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_event_thread), + (gst_xvimagesink_xcontext_get), (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_change_state), (gst_xvimagesink_reset): + Make sure that before we clean up the X resources, we shutdown and join + the event thread. + Also make sure the event thread does not shut down immediatly after + startup because the running variable is not yet correctly set. + Fixes #378770. + +2007-10-16 16:48:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Make the window for a race in typefind and shutting down smaller until we figure out the... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (new_pad), (type_found): + Make the window for a race in typefind and shutting down smaller until + we figure out the right locking here. Avoids #485753 usually. + * gst/playback/gstdecodebin2.c: (type_found), (pad_added_group_cb): + Remove unneeded lock causing a race in typefind and shutting down. + Fixes #485753. + * gst/playback/gstplaybin.c: (gst_play_bin_change_state): + Also remove sinks when going to NULL because we might not complete the + state change to PAUSED, causing the PAUSED->READY state change not to + happen. + +2007-10-16 15:33:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Also explicitly release the ringbuffer when going to NULL because it is requir... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain), (gst_base_audio_sink_change_state): + Also explicitly release the ringbuffer when going to NULL because it + is required in the setcaps function, before the state change to PAUSED + completes. + +2007-10-16 14:58:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/icles/: Does what it says on the tin. + Original commit message from CVS: + * tests/icles/.cvsignore: + * tests/icles/Makefile.am: + * tests/icles/stress-playbin.c: + Does what it says on the tin. + +2007-10-15 11:38:39 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Fix queue negotiation. See #486758. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_init), (gst_queue_push_one): + Fix queue negotiation. See #486758. + +2007-10-12 10:52:18 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Actual code change to go along with: + Original commit message from CVS: + Actual code change to go along with: + 2007-10-12 Jan Schmidt <Jan.Schmidt@sun.com> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_decorate), + (gst_xvimagesink_xwindow_new), + (gst_xvimagesink_update_colorbalance), + (gst_xvimagesink_handle_xevents), (gst_xvimagesink_xcontext_get): + Fix handling of some of the X atoms. If the last parameter is True, + XInternAtom won't create the atom if it doesn't exist, and therefore + might return None. This causes X errors on Xv implementations that + don't provide the colour balance attributes. + +2007-10-12 10:37:09 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + Remove stray character from the changelog. + Original commit message from CVS: + Remove stray character from the changelog. + +2007-10-12 10:33:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + I'm too lazy to comment this + Original commit message from CVS: + *** empty log message *** + +2007-10-11 18:24:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + Extract vorbis comment LICENSE tags correctly. + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: + * tests/check/libs/tag.c: + Extract vorbis comment LICENSE tags correctly. + +2007-10-11 16:12:21 +0000 Jason Kivlighn <jkivlighn@gmail.com> + + Map ID3v2 WCOP frame to GST_TAG_COPYRIGHT_URI (#447000). + Original commit message from CVS: + Patch by: Jason Kivlighn <jkivlighn gmail com> + * gst-libs/gst/tag/gstid3tag.c: + * tests/check/libs/tag.c: + Map ID3v2 WCOP frame to GST_TAG_COPYRIGHT_URI (#447000). + +2007-10-10 17:01:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gsttagdemux.c: Don't error out when a buggy downstream element doesn't handle the newsegment event w... + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: + Don't error out when a buggy downstream element doesn't + handle the newsegment event we send properly (especially + not without posting a meaningful error message on the + bus). See bug #471370 and launchpad bug #136264. + +2007-10-10 15:36:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Use new basesink method to make our EOS drain interruptable. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain): + Use new basesink method to make our EOS drain interruptable. + +2007-10-10 09:37:09 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtp/gstrtppayloads.c: Fix silly search-replace oversight. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtppayloads.c: + Fix silly search-replace oversight. + +2007-10-09 09:57:17 +0000 Laurent Glayal <spglegle@yahoo.fr> + + gst-libs/gst/rtp/gstbasertppayload.c: Fix caps memleak. Fixes #484989. + Original commit message from CVS: + Patch by: Laurent Glayal <spglegle at yahoo dot fr> + * gst-libs/gst/rtp/gstbasertppayload.c: (copy_fixed), + (gst_basertppayload_set_outcaps): + Fix caps memleak. Fixes #484989. + +2007-10-08 18:04:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Fix debug output. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), (gst_base_rtp_depayload_chain): + Fix debug output. + +2007-10-08 18:02:53 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Also handle the case where there is no clock set on the audio source, like in t... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Also handle the case where there is no clock set on the audio source, + like in the unit tests. + +2007-10-08 17:40:17 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtp/gstrtppayloads.c: Use unsigned G_MAXUINT8 instead of -1 to initialise a guint8 to avoid compiler war... + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtppayloads.c: + Use unsigned G_MAXUINT8 instead of -1 to initialise a guint8 + to avoid compiler warnings + +2007-10-08 17:12:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Don't disconnect the have_type signal because we never reconnect it later on. Instead keep a variable ... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (type_found), + (gst_decode_bin_change_state): + * gst/playback/gstdecodebin2.c: (type_found), + (gst_decode_bin_change_state): + Don't disconnect the have_type signal because we never reconnect it + later on. Instead keep a variable to see if we already detected a type. + +2007-10-08 10:47:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Unlink the signal handler when we found the type, we're not going to do anything sensible with more ty... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (add_fakesink), (type_found): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_init), + (type_found): + Unlink the signal handler when we found the type, we're not going to do + anything sensible with more type_found signals anyway. + +2007-10-08 06:07:22 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgio.c: Use GIO function to get a list of supported URI schemes instead of hard coding something. + Original commit message from CVS: + * ext/gio/gstgio.c: (gst_gio_get_supported_protocols): + Use GIO function to get a list of supported URI schemes instead of + hard coding something. + +2007-10-06 16:49:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gsttagdemux.c: Don't leak caps. + Original commit message from CVS: + * gst-libs/gst/tag/gsttagdemux.c: + Don't leak caps. + +2007-10-06 15:04:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/: API: add GstTagDemux base class for simple tag demuxers. + Original commit message from CVS: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gsttagdemux.c: + * gst-libs/gst/tag/gsttagdemux.h: + API: add GstTagDemux base class for simple tag demuxers. + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + Add GstTagDemux to docs. + +2007-10-05 07:49:25 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/rtp/gstrtpbuffer.c: Fix bug introduced with last commit which inverted the logic and caused all buffers ... + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + (gst_rtp_buffer_get_payload_subbuffer): + Fix bug introduced with last commit which inverted the logic and + caused all buffers to be dropped. Fixes #483620. + Thanks to Laurent Glayal <spglegle at yahoo dot fr> for noticing. + +2007-10-04 06:50:53 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/rtp/gstrtpbuffer.c: with regular return and warning. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + Replace g_return_if_val (as it could be disabled), with regular return + and warning. + +2007-10-03 14:51:59 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/pipelines/simple-launch-lines.c: Print message name and not just number. + Original commit message from CVS: + * tests/check/pipelines/simple-launch-lines.c: + Print message name and not just number. + +2007-10-02 11:11:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: When slaved to the clock, don't try to align a sample with the previous one wh... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_async_play): + When slaved to the clock, don't try to align a sample with the previous + one when going to PLAYING again. + +2007-10-02 09:04:03 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/snapshot/snapshot.c: Fix the build. + Original commit message from CVS: + * tests/examples/snapshot/snapshot.c: + Fix the build. + +2007-10-02 07:43:57 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/gstgiosink.c: Update to API changes in GIO. + Original commit message from CVS: + * ext/gio/gstgiosink.c: (gst_gio_sink_start): + Update to API changes in GIO. + +2007-10-01 16:33:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.h: Add RFC 3556 bandwidth modifiers. + Original commit message from CVS: + * gst-libs/gst/sdp/gstsdpmessage.h: + Add RFC 3556 bandwidth modifiers. + +2007-10-01 13:37:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + Update documentation. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtppayloads.c: + Update documentation. + +2007-10-01 13:22:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/: Added new file and header to deal with payload info. + Original commit message from CVS: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtp/gstrtppayloads.c: (gst_rtp_payload_info_for_pt), + (gst_rtp_payload_info_for_name): + * gst-libs/gst/rtp/gstrtppayloads.h: + Added new file and header to deal with payload info. + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_validate_data), + (gst_rtp_buffer_default_clock_rate): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Payload specific stuff is move to new headers. + Implement _default_clock rate using the new payload function. + * gst-libs/gst/sdp/gstsdpmessage.c: (is_multicast_address), + (gst_sdp_parse_line): + * gst-libs/gst/sdp/gstsdpmessage.h: + Add some more comments. + +2007-10-01 10:22:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/typefind/gsttypefindfunctions.c: Add typefind function for application/sdp. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (utf8_type_find), + (sdp_check_header), (sdp_type_find), (plugin_init): + Add typefind function for application/sdp. + Remove some old dirac typefind code that was ifdeffed out. + +2007-09-29 12:04:02 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/common/libgstaudio.def: Add new exported functions. + Original commit message from CVS: + * win32/common/libgstaudio.def: + Add new exported functions. + * win32/vs6/grammar.dsp: + Add autogeneration and copy of some autegenerated files from win32/common + for rtsp library. + * win32/vs6/libgstaudioconvert.dsp: + Add gstaudioquantize.c to the build. + * win32/vs6/libgstinterfaces.dsp: + Add videoorientation.c to the build. + * win32/vs6/libgstriff.dsp: + Add libgsttag to the link libraries list. + * win32/vs6/libgstvolume.dsp: + Add liboil to the link. + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstrtsp.dsp: + * win32/common/libgstrtsp.def: + Add files to build libgstrtsp library. + +2007-09-29 07:01:55 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/gio/: Some minor cleanup and allow setting the location only when the element is not playing or paused. + Original commit message from CVS: + * ext/gio/gstgiosink.c: (gst_gio_sink_base_init), + (gst_gio_sink_set_property), (gst_gio_sink_render): + * ext/gio/gstgiosrc.c: (gst_gio_src_base_init), + (gst_gio_src_set_property): + Some minor cleanup and allow setting the location only when the + element is not playing or paused. + +2007-09-26 15:14:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/snapshot/snapshot.c: Print error when pipeline failed to construct. + Original commit message from CVS: + * tests/examples/snapshot/snapshot.c: (main): + Print error when pipeline failed to construct. + +2007-09-25 19:06:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add mappings for the new GST_TAG_COMPOSER for vorbis comments and ID3v2 tags. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/tag/gstid3tag.c: + * gst-libs/gst/tag/gstvorbistag.c: + Add mappings for the new GST_TAG_COMPOSER for vorbis comments + and ID3v2 tags. + +2007-09-25 11:54:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/floatcast/floatcast.h: Don't include config.h in an installed public header, this might break compilatio... + Original commit message from CVS: + * gst-libs/gst/floatcast/floatcast.h: + Don't include config.h in an installed public header, this + might break compilation of applications that don't have such + a header and doesn't necessarily do what it's supposed to do + anyway (ie. check for the lrint/lrintf defines) (#442065). + Add docs for the various macros and document how this header + has to be used (link against libm, etc.); add a few FIXMEs; + include math.h for non-c99 code path. Based on patch by + Jan Schmidt. + +2007-09-25 07:50:59 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + configure.ac: Use AG_GST_ARG_WITH_PLUGINS and AG_GST_ARG_ENABLE_EXTERNAL instead of duplicating these macros in confi... + Original commit message from CVS: + * configure.ac: + Use AG_GST_ARG_WITH_PLUGINS and AG_GST_ARG_ENABLE_EXTERNAL instead + of duplicating these macros in configure.ac. + +2007-09-22 17:58:22 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/: Updated translations to 0.10.14 + Original commit message from CVS: + * po/hu.po: + * po/sv.po: + * po/uk.po: + Updated translations to 0.10.14 + +2007-09-22 17:57:08 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * po/LINGUAS: + add languages + Original commit message from CVS: + add languages + +2007-09-22 17:56:28 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/pl.po: Added Polish translation. + Original commit message from CVS: + translated by: Jakub Bogusz <qboosh@pld-linux.org> + * po/pl.po: + Added Polish translation. + +2007-09-22 17:55:37 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/fi.po: Added Finnish translation. + Original commit message from CVS: + translated by: Ilkka Tuohela <hile@iki.fi> + * po/fi.po: + Added Finnish translation. + +2007-09-22 17:54:50 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/es.po: Added Spanish translation. + Original commit message from CVS: + translated by: Jorge González González <aloriel@gmail.com> + * po/es.po: + Added Spanish translation. + +2007-09-22 17:53:59 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/da.po: Added Danish translation. + Original commit message from CVS: + translated by: Mogens Jaeger <mogens@jaeger.tf> + * po/da.po: + Added Danish translation. + +2007-09-22 17:52:56 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/zh_CN.po: Added Chinese (simplified) translation. + Original commit message from CVS: + translated by: Funda Wang <fundawang@linux.net.cn> + * po/zh_CN.po: + Added Chinese (simplified) translation. + +2007-09-22 17:51:45 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/bg.po: Added Bulgarian translation. + Original commit message from CVS: + translated by: Alexander Shopov <ash@contact.bg> + * po/bg.po: + Added Bulgarian translation. + +2007-09-21 18:00:24 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + docs/plugins/gst-plugins-bad-plugins.hierarchy: Update hierarchy. + Original commit message from CVS: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + Update hierarchy. + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.h: + Mark private fields of the instance structs private. + +2007-09-21 17:31:05 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + docs/plugins/: Add the GIO plugin to the docs and do a make update while doing that. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.signals: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-dfbvideosink.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-equalizer.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-filter.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-gio.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstrtpmanager.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-nsfdec.xml: + * docs/plugins/inspect/plugin-replaygain.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-spcdec.xml: + * docs/plugins/inspect/plugin-spectrum.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-xingheader.xml: + * docs/plugins/inspect/plugin-xvid.xml: + Add the GIO plugin to the docs and do a make update + while doing that. + * ext/gio/gstgiosrc.c: (gst_gio_src_start): + Fix a small memleak. + +2007-09-21 17:07:56 +0000 René Stadler <mail@renestadler.de> + + Add a GIO/GVFS plugin with source and sink elements. This will only be enabled when --enable-experimental is given to... + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler dot de> + * configure.ac: + * ext/Makefile.am: + * ext/gio/Makefile.am: + * ext/gio/gstgio.c: (gst_gio_error), (gst_gio_seek), + (gst_gio_get_supported_protocols), + (gst_gio_uri_handler_get_type_sink), + (gst_gio_uri_handler_get_type_src), + (gst_gio_uri_handler_get_protocols), (gst_gio_uri_handler_get_uri), + (gst_gio_uri_handler_set_uri), (gst_gio_uri_handler_init), + (gst_gio_uri_handler_do_init), (plugin_init): + * ext/gio/gstgio.h: + * ext/gio/gstgiosink.c: (gst_gio_sink_base_init), + (gst_gio_sink_class_init), (gst_gio_sink_init), + (gst_gio_sink_finalize), (gst_gio_sink_set_property), + (gst_gio_sink_get_property), (gst_gio_sink_start), + (gst_gio_sink_stop), (gst_gio_sink_unlock), + (gst_gio_sink_unlock_stop), (gst_gio_sink_event), + (gst_gio_sink_render), (gst_gio_sink_query): + * ext/gio/gstgiosink.h: + * ext/gio/gstgiosrc.c: (gst_gio_src_base_init), + (gst_gio_src_class_init), (gst_gio_src_init), + (gst_gio_src_finalize), (gst_gio_src_set_property), + (gst_gio_src_get_property), (gst_gio_src_start), + (gst_gio_src_stop), (gst_gio_src_get_size), + (gst_gio_src_is_seekable), (gst_gio_src_unlock), + (gst_gio_src_unlock_stop), (gst_gio_src_check_get_range), + (gst_gio_src_create): + * ext/gio/gstgiosrc.h: + Add a GIO/GVFS plugin with source and sink elements. This will + only be enabled when --enable-experimental is given to configure + for now as the GIO API is not stable yet. Fixes #476916. + +2007-09-21 14:37:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Fix compilation wrt printf arguments. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_push_one): + Fix compilation wrt printf arguments. + +2007-09-20 17:38:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + examples/app/appsrc_ex.c: Fix compilation after changing the name of a method. + Original commit message from CVS: + * examples/app/appsrc_ex.c: (main): + Fix compilation after changing the name of a method. + +2007-09-20 14:09:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add simple snapshot example program using appsink. + Original commit message from CVS: + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/snapshot/.cvsignore: + * tests/examples/snapshot/Makefile.am: + * tests/examples/snapshot/snapshot.c: (main): + Add simple snapshot example program using appsink. + +2007-09-20 13:59:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.*: Add properties, signals and actions to access the element even without linking to the ... + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_marshal_OBJECT__VOID), + (gst_app_sink_class_init), (gst_app_sink_init), + (gst_app_sink_dispose), (gst_app_sink_finalize), + (gst_app_sink_set_property), (gst_app_sink_get_property), + (gst_app_sink_flush_unlocked), (gst_app_sink_start), + (gst_app_sink_event), (gst_app_sink_getcaps), + (gst_app_sink_set_caps), (gst_app_sink_get_caps), + (gst_app_sink_is_eos), (gst_app_sink_pull_preroll), + (gst_app_sink_pull_buffer): + * gst-libs/gst/app/gstappsink.h: + Add properties, signals and actions to access the element even without + linking to the library. + Fix some method names and signatures. + +2007-09-20 10:37:02 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/generic/states.c: Improved state change unit test. + Original commit message from CVS: + * tests/check/generic/states.c: + Improved state change unit test. + +2007-09-19 18:16:58 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Ignore registries in any format. + Original commit message from CVS: + * docs/plugins/.cvsignore: + * tests/check/.cvsignore: + Ignore registries in any format. + +2007-09-19 16:09:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Only copy timestamp on outgoing packets if the depayloader did not set one. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_set_gst_timestamp): + Only copy timestamp on outgoing packets if the depayloader did not set + one. + Also copy duration on outgoing packets. + +2007-09-19 15:55:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Fix compilation because of missing %d in printf. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: (copy_fixed), + (gst_basertppayload_set_outcaps): + Fix compilation because of missing %d in printf. + When fixating caps, fixate what we can and throw away all remaining + unfixed caps, subclasses should do something smart if they need to. + +2007-09-19 12:04:21 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/gnomevfs/gstgnomevfssrc.c: Improve debug logs a bit and be more verbose if things go wrong. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: + Improve debug logs a bit and be more verbose if things go wrong. + +2007-09-17 17:24:55 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Fix a bunch of compile warnings shown with Forte. + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init), + (gst_text_overlay_set_property): + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_ntp_to_unix), + (gst_rtcp_unix_to_ntp): + * gst-libs/gst/rtsp/gstrtspmessage.c: (gst_rtsp_message_get_type): + * gst/playback/gstqueue2.c: + * tests/examples/seek/seek.c: (set_scale): + Fix a bunch of compile warnings shown with Forte. + * gst/audiorate/gstaudiorate.c: + Always pull in config.h before including any system headers. + +2007-09-17 16:22:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Also fix #476514 for queue2. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (update_buffering), + (gst_queue_locked_flush), (gst_queue_locked_enqueue), + (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_push_one), (gst_queue_sink_activate_push), + (gst_queue_src_activate_push), (gst_queue_src_activate_pull): + Also fix #476514 for queue2. + +2007-09-16 19:31:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Remove code to deal with RTP to GST time conversion, we now just copy the GST... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_init), (gst_base_rtp_depayload_setcaps), + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_handle_sink_event), + (gst_base_rtp_depayload_push_full), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_change_state): + Remove code to deal with RTP to GST time conversion, we now just copy + the GST timestamp we receive to the outgoing buffers. + Handle segment and flushes correctly. + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push): + When we have no valid input timestamp, use the previous rtp timestamp on + the outgoing RTP packet instead of the RTP base time. + +2007-09-16 01:56:21 +0000 David Schleef <ds@schleef.org> + + ext/alsa/: Change alsa alloca's to malloc to fix warnings on gcc-4.2. + Original commit message from CVS: + * ext/alsa/gstalsa.c: + * ext/alsa/gstalsadeviceprobe.c: + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: + Change alsa alloca's to malloc to fix warnings on gcc-4.2. + +2007-09-15 18:41:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Add some debug info when negotiating caps. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_set_outcaps), (gst_basertppayload_push): + Add some debug info when negotiating caps. + +2007-09-15 00:29:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.c: A buffer with an empty payload is also a valid buffer. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_validate_data): + A buffer with an empty payload is also a valid buffer. + +2007-09-14 20:52:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Make sure we start our RTP timestamp from the random base RTP timestamp even if... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_event), + (gst_basertppayload_set_outcaps), (gst_basertppayload_push), + (gst_basertppayload_change_state): + Make sure we start our RTP timestamp from the random base RTP + timestamp even if the buffer timestamp starts from some random value. + +2007-09-14 16:56:16 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add simple exmple app to demonstrate starting and pausing live and non-live bins in a PLAYING pipeline. + Original commit message from CVS: + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/dynamic/.cvsignore: + * tests/examples/dynamic/Makefile.am: + * tests/examples/dynamic/addstream.c: (create_stream), + (pause_play_stream), (message_received), (eos_message_received), + (perform_step), (main): + Add simple exmple app to demonstrate starting and pausing live and + non-live bins in a PLAYING pipeline. + +2007-09-14 10:42:00 +0000 Julien Moutte <julien@moutte.net> + + gst/typefind/gsttypefindfunctions.c: Add some typefind for QCP files (RFC #3625) + Original commit message from CVS: + 2007-09-14 Julien MOUTTE <julien@moutte.net> + * gst/typefind/gsttypefindfunctions.c: (plugin_init): Add some + typefind for QCP files (RFC #3625) + +2007-09-13 22:52:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Disable pull mode scheduling, we're not ready for it yet and it subtly breaks ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_init): + Disable pull mode scheduling, we're not ready for it yet and it subtly + breaks a lot of things. + +2007-09-12 17:35:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/libvisual.c: Test all libvisual plugins, not just the first one; this reproduces bug #450336 qui... + Original commit message from CVS: + * tests/check/elements/libvisual.c: + Test all libvisual plugins, not just the first one; this reproduces + bug #450336 quite easily. Looks like a problem with the 'jess' + visualisation. + +2007-09-12 17:15:12 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add basic libvisual test case in an attempt to reproduce bug #450336. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/libvisual.c: + Add basic libvisual test case in an attempt to reproduce bug #450336. + Doesn't reproduce that bug, but some other crasher instead (invalid + free), at least with make elements/libvisual.forever and the bumscope + plugin on x86-64/gutsy. Leaving test disabled for now. + +2007-09-12 08:38:21 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst/: Printf format fixes (#476128). + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst-libs/gst/app/gstappsink.c: + * gst/flv/gstflvdemux.c: + * gst/flv/gstflvparse.c: + * gst/interleave/deinterleave.c: + * gst/switch/gstswitch.c: + Printf format fixes (#476128). + +2007-09-11 19:07:57 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + gst-libs/gst/rtsp/gstrtspconnection.c: Make sure we can not cancel in the middle of receiving a message. + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_read_internal), (gst_rtsp_connection_read), + (read_body), (gst_rtsp_connection_receive): + Make sure we can not cancel in the middle of receiving a message. + Fixes #475731. + +2007-09-11 11:29:12 +0000 Josep Torra Valles <josep@fluendo.com> + + gst/playback/gstplaybasebin.c: Increase upper limit for audio queue a bit; fixes preroll problem with playbin and dec... + Original commit message from CVS: + Patch by: Josep Torra Valles <josep@fluendo.com> + * gst/playback/gstplaybasebin.c: + Increase upper limit for audio queue a bit; fixes preroll problem + with playbin and decodebin2 when playing a quicktime trailer with + multichannel audio via http (#464666). + +2007-09-10 22:10:54 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.*: Allow othe clocks than the internal clock to be used for the pipeline. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init), (gst_base_audio_src_init), + (gst_base_audio_src_provide_clock), + (gst_base_audio_src_set_property), + (gst_base_audio_src_get_property), (gst_base_audio_src_create): + * gst-libs/gst/audio/gstbaseaudiosrc.h: + Allow othe clocks than the internal clock to be used for the pipeline. + Add property to disable clock provide. + API: GstBaseAudioSrc::provide-clock + +2007-09-10 12:05:34 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gstdecodebin2.c: Don't leak request pads. Fixes #475395. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + Don't leak request pads. Fixes #475395. + +2007-09-09 10:25:43 +0000 René Stadler <mail@renestadler.de> + + sys/: Correctly chain up finalize with the parent class to prevent memory leaks. Fixes #474880. + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler dot de> + * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), + (gst_ximage_buffer_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimage_buffer_class_init): + Correctly chain up finalize with the parent class to prevent + memory leaks. Fixes #474880. + +2007-09-09 04:08:48 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Revert the latest change: floating point samples are allowed to have any value, not only values in the range [-1,1]. ... + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_choose_func): + * tests/check/elements/volume.c: (GST_START_TEST): + Revert the latest change: floating point samples are allowed to + have any value, not only values in the range [-1,1]. Thanks to Andy + Wingo for noticing. + Also fix processing of int32 samples with volumes > 4 by making the + unity value smaller which prevents overflows. + +2007-09-07 17:37:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + Fix gst_rtp_buffer_set_csrc() and enable csrc-related unit test checks. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * tests/check/libs/rtp.c: + Fix gst_rtp_buffer_set_csrc() and enable csrc-related unit test checks. + +2007-09-07 16:46:05 +0000 Haakon Sporsheim <haakon.sporsheim@tandberg.com> + + gst-libs/gst/rtp/gstrtpbuffer.c: Fix up GstRTPHeader helper struct so that compilers will not under any circumstances... + Original commit message from CVS: + Based on patch by: Haakon Sporsheim <haakon.sporsheim at tandberg com> + * gst-libs/gst/rtp/gstrtpbuffer.c: + Fix up GstRTPHeader helper struct so that compilers will not under + any circumstances add padding in between our fields, as currently + happens with MSVC on win32, because that would lead to us sending + out RTP payloads with broken RTP headers (#471194). + Fix assertion guards for gst_rtp_buffer_get_csrc() and _set_csrc(). + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/rtp.c: + Add some simple unit tests for GstRTPBuffer. Some are disabled + because the code tested still needs fixing (set_csrc() does not work). + +2007-09-07 15:05:24 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update spec file to include latest RTSP libraries and headers and more + Original commit message from CVS: + update spec file to include latest RTSP libraries and headers and more + +2007-09-07 12:41:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + win32/: Add rtsp enumtypes (#474384) and update others. + Original commit message from CVS: + * win32/MANIFEST: + * win32/common/gstrtsp-enumtypes.c: + * win32/common/gstrtsp-enumtypes.h: + * win32/common/interfaces-enumtypes.c: + * win32/common/interfaces-enumtypes.h: + * win32/common/multichannel-enumtypes.c: + Add rtsp enumtypes (#474384) and update others. + +2007-09-06 20:31:50 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Fix configure check for HAVE_LIBXML_HTML. + Original commit message from CVS: + * configure.ac: + Fix configure check for HAVE_LIBXML_HTML. + +2007-09-06 12:14:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/.cvsignore: Ignore more, in case the build bots work again one day. + Original commit message from CVS: + * tests/check/libs/.cvsignore: + Ignore more, in case the build bots work again one day. + +2007-09-06 07:00:36 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + Add libgstfft, a FFT library based on Kiss FFT which is + Original commit message from CVS: + Reviewed by: Stefan Kost <ensonic@users.sf.net> + * configure.ac: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/fft/Makefile.am: + * gst-libs/gst/fft/_kiss_fft_guts_f32.h: + * gst-libs/gst/fft/_kiss_fft_guts_f64.h: + * gst-libs/gst/fft/_kiss_fft_guts_s16.h: + * gst-libs/gst/fft/_kiss_fft_guts_s32.h: + * gst-libs/gst/fft/gstfft.c: (gst_fft_next_fast_length): + * gst-libs/gst/fft/gstfft.h: + * gst-libs/gst/fft/gstfftf32.c: (gst_fft_f32_new), + (gst_fft_f32_fft), (gst_fft_f32_inverse_fft), (gst_fft_f32_free), + (gst_fft_f32_window), (gst_fft_f32_magnitude), (gst_fft_f32_phase): + * gst-libs/gst/fft/gstfftf32.h: + * gst-libs/gst/fft/gstfftf64.c: (gst_fft_f64_new), + (gst_fft_f64_fft), (gst_fft_f64_inverse_fft), (gst_fft_f64_free), + (gst_fft_f64_window), (gst_fft_f64_magnitude), (gst_fft_f64_phase): + * gst-libs/gst/fft/gstfftf64.h: + * gst-libs/gst/fft/gstffts16.c: (gst_fft_s16_new), + (gst_fft_s16_fft), (gst_fft_s16_inverse_fft), (gst_fft_s16_free), + (gst_fft_s16_window), (gst_fft_s16_magnitude), (gst_fft_s16_phase): + * gst-libs/gst/fft/gstffts16.h: + * gst-libs/gst/fft/gstffts32.c: (gst_fft_s32_new), + (gst_fft_s32_fft), (gst_fft_s32_inverse_fft), (gst_fft_s32_free), + (gst_fft_s32_window), (gst_fft_s32_magnitude), (gst_fft_s32_phase): + * gst-libs/gst/fft/gstffts32.h: + * gst-libs/gst/fft/kiss_fft_f32.c: (kf_bfly2), (kf_bfly4), + (kf_bfly3), (kf_bfly5), (kf_bfly_generic), (kf_work), (kf_factor), + (kiss_fft_f32_alloc), (kiss_fft_f32_stride), (kiss_fft_f32), + (kiss_fft_f32_cleanup), (kiss_fft_f32_next_fast_size): + * gst-libs/gst/fft/kiss_fft_f32.h: + * gst-libs/gst/fft/kiss_fft_f64.c: (kf_bfly2), (kf_bfly4), + (kf_bfly3), (kf_bfly5), (kf_bfly_generic), (kf_work), (kf_factor), + (kiss_fft_f64_alloc), (kiss_fft_f64_stride), (kiss_fft_f64), + (kiss_fft_f64_cleanup), (kiss_fft_f64_next_fast_size): + * gst-libs/gst/fft/kiss_fft_f64.h: + * gst-libs/gst/fft/kiss_fft_s16.c: (kf_bfly2), (kf_bfly4), + (kf_bfly3), (kf_bfly5), (kf_bfly_generic), (kf_work), (kf_factor), + (kiss_fft_s16_alloc), (kiss_fft_s16_stride), (kiss_fft_s16), + (kiss_fft_s16_cleanup), (kiss_fft_s16_next_fast_size): + * gst-libs/gst/fft/kiss_fft_s16.h: + * gst-libs/gst/fft/kiss_fft_s32.c: (kf_bfly2), (kf_bfly4), + (kf_bfly3), (kf_bfly5), (kf_bfly_generic), (kf_work), (kf_factor), + (kiss_fft_s32_alloc), (kiss_fft_s32_stride), (kiss_fft_s32), + (kiss_fft_s32_cleanup), (kiss_fft_s32_next_fast_size): + * gst-libs/gst/fft/kiss_fft_s32.h: + * gst-libs/gst/fft/kiss_fftr_f32.c: (kiss_fftr_f32_alloc), + (kiss_fftr_f32), (kiss_fftri_f32): + * gst-libs/gst/fft/kiss_fftr_f32.h: + * gst-libs/gst/fft/kiss_fftr_f64.c: (kiss_fftr_f64_alloc), + (kiss_fftr_f64), (kiss_fftri_f64): + * gst-libs/gst/fft/kiss_fftr_f64.h: + * gst-libs/gst/fft/kiss_fftr_s16.c: (kiss_fftr_s16_alloc), + (kiss_fftr_s16), (kiss_fftri_s16): + * gst-libs/gst/fft/kiss_fftr_s16.h: + * gst-libs/gst/fft/kiss_fftr_s32.c: (kiss_fftr_s32_alloc), + (kiss_fftr_s32), (kiss_fftri_s32): + * gst-libs/gst/fft/kiss_fftr_s32.h: + * gst-libs/gst/fft/kiss_version: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + Add libgstfft, a FFT library based on Kiss FFT which is + BSD licensed. Supported sample formats are int16, int32, + float and double. For those formats a real FFT and IFFT + can be done, different windowing functions can be applied + and functions for extracting the magnitude and phase exist. + Fixes #468619. + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + Integrate libgstfft into the docs. + * tests/check/Makefile.am: + * tests/check/libs/fft.c: (GST_START_TEST), (fft_suite), (main): + Add unit tests for libgstfft, currently only testing the FFT. + Unit tests for IFFT will follow soon. + +2007-09-05 23:07:40 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst-libs/gst/sdp/gstsdpmessage.*: Separate INIT_ARRAY() and related macros into two versions, one for structures and ... + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_time_init), + (gst_sdp_message_init), (gst_sdp_message_uninit), + (is_multicast_address), (gst_sdp_message_as_text), + (gst_sdp_message_get_origin), (gst_sdp_message_set_connection), + (gst_sdp_message_get_connection), (gst_sdp_message_add_bandwidth), + (gst_sdp_message_add_time), (gst_sdp_message_add_zone), + (gst_sdp_message_get_key), (gst_sdp_message_get_attribute_val_n), + (gst_sdp_message_get_attribute_val), (gst_sdp_message_add_media), + (gst_sdp_media_init), (gst_sdp_media_uninit), + (gst_sdp_media_as_text), (gst_sdp_media_set_port_info), + (gst_sdp_media_connections_len), (gst_sdp_media_add_connection), + (gst_sdp_media_bandwidths_len), (gst_sdp_media_get_bandwidth), + (gst_sdp_media_add_bandwidth), (gst_sdp_media_attributes_len), + (gst_sdp_parse_line), (print_media), (gst_sdp_message_dump): + * gst-libs/gst/sdp/gstsdpmessage.h: + Separate INIT_ARRAY() and related macros into two versions, one for + structures and one for pointers (e.g., INIT_ARRAY() and + INIT_PTR_ARRAY()). This fixes a segmentation error on freeing the + lists of emails and phone numbers. + Add missing const as appropriate. + Change all gint to guint since they all actually represent unsigned + values. + Do not use time as a variable name as it shadows the global time(). + Add gst_sdp_message_as_text() and gst_sdp_media_as_text(). + Actually implement gst_sdp_message_add_time(). + Make gst_sdp_message_add_time() take repeat times as an argument. + Store repeat times in GstSDPTime as a GArray rather than as gchar**. + Corrected the definition of gst_sdp_media_get_bandwidth() (was + misspelled as badwidth). + gst-indented and a little clean up. Fixes #471067. + +2007-09-05 21:20:12 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/volume/gstvolume.c: Correctly clamp float/double samples in the [-1.0,1.0] range to prevent weird effects. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_process_double), (volume_process_double_clamp), + (volume_process_float_clamp): + Correctly clamp float/double samples in the [-1.0,1.0] range to + prevent weird effects. + * tests/check/elements/volume.c: (GST_START_TEST), (volume_suite): + Add unit tests for all samples types that had none before. + +2007-09-05 14:09:15 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/rtp/gstrtpbuffer.c: Need to include stdlib.h for abs() here too. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + Need to include stdlib.h for abs() here too. + +2007-09-05 14:01:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreaminfo.c: Fix build. + Original commit message from CVS: + * gst/playback/gststreaminfo.c: + Fix build. + +2007-09-05 10:32:09 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/gststreaminfo.c: Clean up some half-disabled code and comment. + Original commit message from CVS: + * gst/playback/gststreaminfo.c: + Clean up some half-disabled code and comment. + +2007-09-04 16:18:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Return FALSE from the event handler to let the parent class handle the event. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_payload_audio_handle_event): + Return FALSE from the event handler to let the parent class handle the + event. + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), (gst_base_rtp_depayload_push_full): + Mark outgoing buffers as DISCONT if the incomming buffer was DISCONT. + * gst-libs/gst/rtp/gstbasertppayload.c: + Bump the MTU to 1400. + +2007-09-04 01:50:55 +0000 Johan Dahlin <johan@gnome.org> + + gst/typefind/gsttypefindfunctions.c (plugin_init): Add an audio/x-nsf typefind function for the nsfdec element. + Original commit message from CVS: + 2007-09-03 Johan Dahlin <jdahlin@async.com.br> + * gst/typefind/gsttypefindfunctions.c (plugin_init): + Add an audio/x-nsf typefind function for the nsfdec element. + +2007-09-03 20:46:38 +0000 Renato Filho <renato.filho@indt.org.br> + + gst/playback/gstplaybasebin.c: Included "myth://" on stream_uris list for enable buffering to mythtv files + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + Included "myth://" on stream_uris list for enable buffering to mythtv files + +2007-09-03 19:31:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + Fix parsing of RB blocks. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_packet_get_rb), + (gst_rtcp_packet_sdes_copy_entry), (gst_rtcp_ntp_to_unix), + (gst_rtcp_unix_to_ntp): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Fix parsing of RB blocks. + Fix docs. + Added helper functions to convert to/from UNIX and NTP time. + API: gst_rtcp_ntp_to_unix() + API: gst_rtcp_unix_to_ntp() + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_validate_data), + (gst_rtp_buffer_get_header_len), + (gst_rtp_buffer_get_extension_data), + (gst_rtp_buffer_get_payload_subbuffer), + (gst_rtp_buffer_get_payload_len), (gst_rtp_buffer_get_payload), + (gst_rtp_buffer_ext_timestamp): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Fix some more docs. + Implement handling of packets with extensions. + Fix padding check in _validate(). + Added function to get extension data. + API: gst_rtp_buffer_get_header_len() + API: gst_rtp_buffer_get_extension_data() + +2007-09-03 19:19:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Add some more docs for the queue-delay property and fix a typo in a comment. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_class_init), + (gst_base_rtp_depayload_set_gst_timestamp): + Add some more docs for the queue-delay property and fix a typo in a + comment. + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push): + Fix typo. + +2007-09-03 19:17:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: When skew slaving, try to hover around the middle of a segment so that we at m... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_skew_slaving), (gst_base_audio_sink_render), + (gst_base_audio_sink_change_state): + When skew slaving, try to hover around the middle of a segment so that + we at most drift by half a segment. + If we are aligning in the oposite direction of the clock skew, we don't + have to resync. + +2007-08-31 21:07:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Be less silly with the segment start, just apply the clock-base to the timest... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), + (gst_base_rtp_depayload_set_gst_timestamp): + Be less silly with the segment start, just apply the clock-base to the + timestamp. + +2007-08-31 15:58:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Deprecate the queue handling thread thing and remove the code. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_class_init), + (gst_base_rtp_depayload_finalize), + (gst_base_rtp_depayload_setcaps), (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_handle_sink_event), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_change_state): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Deprecate the queue handling thread thing and remove the code. + Use new method to calculate the extended timestamp. + +2007-08-31 15:21:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.c: Use g_strndup which does exactly what we want. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + (gst_rtcp_packet_sdes_copy_entry): + Use g_strndup which does exactly what we want. + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_compare_seqnum), + (gst_rtp_buffer_ext_timestamp): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Add helper function to compare seqnums. + Add helper function to calculate extended timestamps. + API: gst_rtp_buffer_compare_seqnum() + API: gst_rtp_buffer_ext_timestamp() + +2007-08-30 21:59:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.*: Fix and document SDES item data function. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + (gst_rtcp_packet_sdes_get_entry), + (gst_rtcp_packet_sdes_copy_entry): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Fix and document SDES item data function. + Add new function that makes a proper copy of SDES item data. + API: gst_rtcp_packet_sdes_copy_entry() + +2007-08-30 07:29:55 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + The tcp and subparse plugins are under gst, but not totaly free of dependencies. Handle selection inconfigure.ac, so ... + Original commit message from CVS: + * configure.ac: + * gst/Makefile.am: + The tcp and subparse plugins are under gst, but not totaly free of + dependencies. Handle selection inconfigure.ac, so that they show up + on the final list of what is build and what is not. Maybe they should + better be moved to ext. + +2007-08-30 06:58:46 +0000 Daniel Díaz <yosoy@danieldiaz.org> + + Check if libxml provides HTML parser which subparse needs. + Original commit message from CVS: + Patch by: Daniel Díaz <yosoy@danieldiaz.org> + * configure.ac: + * gst/Makefile.am: + Check if libxml provides HTML parser which subparse needs. + Fixes #451970. + +2007-08-29 14:22:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsa.c: Fix typo and compilation on big endian systems. + Original commit message from CVS: + * ext/alsa/gstalsa.c: + Fix typo and compilation on big endian systems. + +2007-08-29 12:16:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstssaparse.c: Convert SSA newline codes into actual newline characters (#470766). + Original commit message from CVS: + * gst/subparse/gstssaparse.c: + Convert SSA newline codes into actual newline characters (#470766). + +2007-08-28 14:58:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: also add gst_install_plugins_supported() while we're at it (see #470456). + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/install-plugins.c: + * gst-libs/gst/pbutils/install-plugins.h: + * tests/check/libs/pbutils.c: + API: also add gst_install_plugins_supported() while we're at it + (see #470456). + +2007-08-28 14:23:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add gst_missing_*_installer_detail_new() convenience API so that applications that know exactly what they're mis... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/pbutils/missing-plugins.c: + * gst-libs/gst/pbutils/missing-plugins.h: + * tests/check/libs/pbutils.c: + API: add gst_missing_*_installer_detail_new() convenience API so + that applications that know exactly what they're missing can request + installer detail strings for those items directly instead of having + to first create a dummy missing-plugin message and then get the + installer detail string from that. Fixes #470456. + +2007-08-27 11:59:56 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: We need to set up delayed-linking whenever the caps are non-fixed, not just when there a... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (close_pad_link): + We need to set up delayed-linking whenever the caps are non-fixed, + not just when there are multiple types - use gst_pad_is_fixed() + to test. + +2007-08-26 14:14:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/missing-plugins.c: Add missing separator in PID fallback case. + Original commit message from CVS: + * gst-libs/gst/pbutils/missing-plugins.c: + (gst_missing_plugin_message_get_installer_detail): + Add missing separator in PID fallback case. + +2007-08-24 15:28:33 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/alsa/Makefile.am: There is no GST_PLUGINS_BASE_LIBS defined. + Original commit message from CVS: + * ext/alsa/Makefile.am: + There is no GST_PLUGINS_BASE_LIBS defined. + * ext/alsa/gstalsa.c: + * ext/alsa/gstalsasink.c: (gst_alsasink_delay): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_delay): + Add support for ALSA 24-bit formats. + snd_pcm_delay can return an error code, especially + during XRUNS. In that case, the best we can do is assume + delay = 0. + * gst/audioconvert/Makefile.am: + Add flags from -base before any more-remote dependencies. + +2007-08-23 20:45:45 +0000 Davyd <davyd@madeley.id.au> + + gst/volume/gstvolume.*: Add support for int32, int24 and int8 to the volume element. + Original commit message from CVS: + Based on a patch by: Davyd <davyd at madeley dot id dot au> + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_update_real_volume), (gst_volume_set_volume), + (gst_volume_init), (volume_process_int32), + (volume_process_int32_clamp), (volume_process_int24), + (volume_process_int24_clamp), (volume_process_int16), + (volume_process_int16_clamp), (volume_process_int8), + (volume_process_int8_clamp), (volume_update_volume), (plugin_init): + * gst/volume/gstvolume.h: + Add support for int32, int24 and int8 to the volume element. + Fixes #445529. + +2007-08-23 12:37:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/examples/Makefile.am: Fix even more. + Original commit message from CVS: + * tests/examples/Makefile.am: + Fix even more. + +2007-08-23 10:58:42 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Revert unwanted commit. many thanks to moap. I want a fix for https://thomas.apestaart.org/moap/trac/ticket/239 + Original commit message from CVS: + * configure.ac: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/gnomevfs/gstgnomevfssrc.h: + * gst-libs/gst/Makefile.am: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + * sys/v4l/v4lsrc_calls.c: + * tests/examples/Makefile.am: + * win32/common/config.h: + Revert unwanted commit. many thanks to moap. I want a fix for + https://thomas.apestaart.org/moap/trac/ticket/239 + +2007-08-23 08:33:43 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + * ChangeLog: + * configure.ac: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/gnomevfs/gstgnomevfssrc.h: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/audio/gstaudiofilter.h: + * gst/typefind/gsttypefindfunctions.c: + * gst/volume/gstvolume.c: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + * sys/v4l/v4lsrc_calls.c: + * tests/examples/Makefile.am: + * win32/common/config.h: + Original commit message from CVS: reviewed by: <delete if not using a buddy> patch by: <delete if not someone else's patch> * configure.ac: * docs/libs/Makefile.am: * docs/libs/gst-plugins-base-libs-docs.sgml: * docs/libs/gst-plugins-base-libs-sections.txt: * ext/gnomevfs/gstgnomevfssrc.c: * ext/gnomevfs/gstgnomevfssrc.h: * gst-libs/gst/Makefile.am: * gst-libs/gst/audio/gstaudiofilter.h: * gst/typefind/gsttypefindfunctions.c: * gst/volume/gstvolume.c: * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: * pkgconfig/gstreamer-plugins-base.pc.in: * sys/v4l/v4lsrc_calls.c: * tests/examples/Makefile.am: * win32/common/config.h: + +2007-08-22 15:29:04 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/audio.c: Clarify the docs a little. + Original commit message from CVS: + * gst-libs/gst/audio/audio.c: + Clarify the docs a little. + +2007-08-22 11:20:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/volume/gstvolume.c: Enable liboil for float and add more details about problems with int16. + Original commit message from CVS: + * gst/volume/gstvolume.c: + Enable liboil for float and add more details about problems with + int16. + +2007-08-21 15:43:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/v4l/gstv4lsrc.c: Fix RGB24 masks as spotted by _ke (Daniel G. Siegel) on IRC. + Original commit message from CVS: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_palette_to_caps): + Fix RGB24 masks as spotted by _ke (Daniel G. Siegel) on IRC. + +2007-08-21 12:08:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: When calculating the first timestamp of the buffers, don't go below 0 and clip the samples be... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_push_forward): + When calculating the first timestamp of the buffers, don't go below 0 + and clip the samples because the offset was on the eos page. + Fixes #466717. + +2007-08-21 11:42:39 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Also submit the eos page when trying to find the first timestamp. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_read_chain), + (gst_ogg_demux_collect_chain_info): + Also submit the eos page when trying to find the first timestamp. + See #466717. + +2007-08-17 15:24:43 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/audio/audio.h: Use gst_util_uint64_scale() instead of doing the math with double for GST_FRAMES_TO_CLOCK... + Original commit message from CVS: + * gst-libs/gst/audio/audio.h: + Use gst_util_uint64_scale() instead of doing the math + with double for GST_FRAMES_TO_CLOCK_TIME() and + GST_CLOCK_TIME_TO_FRAMES(). For large timestamps this + prevents rounding errors. Fixes #467667. + +2007-08-17 13:42:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspconnection.*: Small cleanups. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect), (gst_rtsp_connection_write), + (gst_rtsp_connection_read), (gst_rtsp_connection_poll): + * gst-libs/gst/rtsp/gstrtspconnection.h: + Small cleanups. + On shutdown, don't read the control socket yet. + Set timeout value correctly in all cases. + Add function to check if the server accepts reads or writes. + API: gst_rtsp_connection_poll() + * gst-libs/gst/rtsp/gstrtspdefs.h: + Fix compilation with -pedantic. + Add enum for _poll. + +2007-08-16 17:11:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.c: Override the preroll vmethod instead of overriding the render method twice. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_class_init): + Override the preroll vmethod instead of overriding the render method + twice. + +2007-08-16 16:06:21 +0000 Olivier Crete <tester@tester.ca> + + gst-libs/gst/rtp/gstbasertppayload.*: Add getcaps vfunc to basertppayload. See #465146. + Original commit message from CVS: + Patch by: Olivier Crete <tester at tester ca> + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_init), + (gst_basertppayload_getcaps): + * gst-libs/gst/rtp/gstbasertppayload.h: + Add getcaps vfunc to basertppayload. See #465146. + +2007-08-16 11:20:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Only post buffering messages when we are a stream. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (queue_threshold_reached): + Only post buffering messages when we are a stream. + +2007-08-15 17:05:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/: Small docs fix and addition. + Original commit message from CVS: + * gst-libs/gst/pbutils/install-plugins.c: + * gst-libs/gst/pbutils/missing-plugins.c: + Small docs fix and addition. + +2007-08-14 17:47:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.c: Don't use new API. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_flush_unlocked): + Don't use new API. + +2007-08-14 17:38:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/app/gstappsink.*: Make love to appsink. + Original commit message from CVS: + * gst-libs/gst/app/gstappsink.c: (gst_app_sink_base_init), + (gst_app_sink_class_init), (gst_app_sink_dispose), + (gst_app_sink_flush_unlocked), (gst_app_sink_start), + (gst_app_sink_stop), (gst_app_sink_event), (gst_app_sink_preroll), + (gst_app_sink_render), (gst_app_sink_get_caps), + (gst_app_sink_set_caps), (gst_app_sink_end_of_stream), + (gst_app_sink_pull_preroll), (gst_app_sink_pull_buffer): + * gst-libs/gst/app/gstappsink.h: + Make love to appsink. + Make it support pulling of the preroll buffer. + Add docs and debug statements. + Fix some races wrt to EOS handling and stopping. + Implement getcaps. + Implement FLUSHING. + API: gst_app_sink_pull_preroll() + +2007-08-13 15:37:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/icles/: Add a dumb little test for textoverlay alignments. + Original commit message from CVS: + * tests/icles/.cvsignore: + * tests/icles/Makefile.am: + * tests/icles/test-textoverlay.c: + Add a dumb little test for textoverlay alignments. + +2007-08-13 15:26:54 +0000 Dan Williams <dcbw@redhat.com> + + ext/pango/gsttextoverlay.*: API: add "line-alignment" property (#459334). Add gtk-doc blurb for "silent" property so ... + Original commit message from CVS: + Patch by: Dan Williams <dcbw redhat com> + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + API: add "line-alignment" property (#459334). Add gtk-doc blurb for + "silent" property so there's a Since tag in the API reference. + +2007-08-13 11:21:00 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + fix ... by: lines + Original commit message from CVS: + fix ... by: lines + +2007-08-12 16:30:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.*: Improve caps negotiation so that downstream elements can confiure certain RTP p... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_set_outcaps): + * gst-libs/gst/rtp/gstbasertppayload.h: + Improve caps negotiation so that downstream elements can confiure + certain RTP properties by fixing them on the caps. See #465146. + Add docs. + +2007-08-11 12:39:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + Mark as deprecated some macros which were presumably meant to be private API and accidentally exposed in the public h... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Mark as deprecated some macros which were presumably meant to be + private API and accidentally exposed in the public header file. + Also actually _init() lock (only works at the moment because the + struct is zeroed out when created and the initial values in the + mutex struct are zeroes too). (#459585) + +2007-08-10 17:35:52 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/Makefile.am: Remove cruft and do some cleanups. + Original commit message from CVS: + * docs/libs/Makefile.am: + Remove cruft and do some cleanups. + * docs/libs/gst-plugins-base-libs-docs.sgml: + Prepare for comming gtkdoc features (rebase against online docs). + +2007-08-10 13:55:44 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: Debug output fixes. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + Debug output fixes. + * tests/check/elements/audiorate.c: (do_perfect_stream_test), + (GST_START_TEST): + Change the number of buffers used; 500 is too many and leads to + timeouts. + +2007-08-10 10:08:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: Printf format fixes (#465028). + Original commit message from CVS: + * gst/playback/gstqueue2.c: + * gst/videorate/gstvideorate.c: + Printf format fixes (#465028). + +2007-08-09 15:44:02 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: If we have a large (> 1 second) discontinuity, push a series of smaller buffers rather ... + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + If we have a large (> 1 second) discontinuity, push a series of + smaller buffers rather than a single very large buffer. Avoids + unreasonably large single buffer allocations when encountering a + large gap. + * tests/check/elements/audiorate.c: (GST_START_TEST), + (audiorate_suite): + Add a test for this. + +2007-08-09 12:06:43 +0000 Josep Torra Valles <josep@fluendo.com> + + gst/playback/gstplaybasebin.c: Fixes: #465015 + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (group_commit), + (queue_remove_probe), (queue_threshold_reached): + Patch by: Josep Torra Valles <josep@fluendo.com> + Fixes: #465015 + Make sure we remove the check_queues buffer probe from the + correct queue to avoid racily going back to "buffering 99%" when + buffering is actually complete. + Also, fix the spelling of Josep's surname in the ChangeLog. + +2007-08-09 11:37:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/ogg/gstoggmux.c: Do not leak oggmux instance. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + Do not leak oggmux instance. + * ext/vorbis/vorbisenc.c: + Also log values. + +2007-08-09 10:51:55 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/: Updated translations. + Original commit message from CVS: + * po/hu.po: + * po/it.po: + * po/nl.po: + * po/uk.po: + * po/vi.po: + Updated translations. + +2007-08-08 16:07:21 +0000 Yang Hong <hongyang@redflag-linux.com> + + ext/pango/gsttextoverlay.*: Add 'silent' property to GstTimeOverlay. Fixes #462979 + Original commit message from CVS: + patch by: Yang Hong <hongyang@redflag-linux.com> + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextoverlay.h: + Add 'silent' property to GstTimeOverlay. Fixes #462979 + +2007-08-08 15:05:22 +0000 Josep Torre Valles <josep@fluendo.com> + + Add connection-speed property. Fixes #464690. + Original commit message from CVS: + Patch by: Josep Torre Valles <josep@fluendo.com> + * docs/plugins/gst-plugins-base-plugins.args: + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_class_init), + (gst_uri_decode_bin_init), (gst_uri_decode_bin_set_property), + (gst_uri_decode_bin_get_property), (gen_source_element): + Add connection-speed property. Fixes #464690. + +2007-08-07 15:13:46 +0000 Damien Lespiau <damien.lespiau@gmail.com> + + Fix compilation on windows. Fixes #464320. + Original commit message from CVS: + Patch by: Damien Lespiau <damien dot lespiau at gmail dot com> + * configure.ac: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect): + Fix compilation on windows. Fixes #464320. + +2007-08-07 14:14:54 +0000 Josep Torre Valles <josep@fluendo.com> + + gst/playback/: Move connection-speed property from playbin to playbasebin so that we can also configure it in source ... + Original commit message from CVS: + Patch by: Josep Torre Valles <josep@fluendo.com> + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (queue_threshold_reached), + (gen_source_element), (setup_substreams), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property), + (gst_play_base_bin_get_streaminfo_value_array): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (gst_play_bin_handle_redirect_message): + Move connection-speed property from playbin to playbasebin so that we + can also configure it in source elements that have the connection-speed + property. Fixes #464028. + Add some debug info here and there. + +2007-08-06 16:42:22 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audiotestsrc/gstaudiotestsrc.c: Properly respond to conversion queries. Fixes #464079. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_query): + Properly respond to conversion queries. Fixes #464079. + +2007-08-03 19:53:11 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audiotestsrc/gstaudiotestsrc.*: Add float/double and int32 support to audiotestsrc. Fixes #460422. + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_init), + (gst_audio_test_src_src_fixate), (gst_audio_test_src_setcaps), + (gst_audio_test_src_init_sine_table), + (gst_audio_test_src_change_wave), (gst_audio_test_src_create): + * gst/audiotestsrc/gstaudiotestsrc.h: + Add float/double and int32 support to audiotestsrc. Fixes #460422. + Also set the default volume to the default value specified in the + GParamSpec. + +2007-08-03 19:40:14 +0000 Jens Granseuer <jensgr@gmx.net> + + gst/audioconvert/gstaudioquantize.c: Fix C89 incompatibilities and spelling of explanations. Fixes #463215. + Original commit message from CVS: + Patch by: Jens Granseuer <jensgr at gmx dot net> + * gst/audioconvert/gstaudioquantize.c: + Fix C89 incompatibilities and spelling of explanations. Fixes #463215. + +2007-08-03 15:44:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtsptransport.c: Add rdt manager for rdt transport. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtsptransport.c: (gst_rtsp_transport_parse): + Add rdt manager for rdt transport. + Fix parsing of RDT transport. + +2007-08-03 14:43:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.14 === + +2007-08-03 14:41:46 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-decodebin2.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/config.h: + Release 0.10.14 + Original commit message from CVS: + Release 0.10.14 + +2007-08-03 14:24:08 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-07-27 17:37:19 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/libs/audio.c: Fix the test to reflect the behaviour of gst_audio_clip_buffer. + Original commit message from CVS: + * tests/check/libs/audio.c: (GST_START_TEST): + Fix the test to reflect the behaviour of gst_audio_clip_buffer. + +2007-07-27 17:10:47 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/audio/audio.c: When clipping a buffer with no timestamp, assume it is within the segment without warnings. + Original commit message from CVS: + * gst-libs/gst/audio/audio.c: + When clipping a buffer with no timestamp, assume it is + within the segment without warnings. + Fixes: #460978 + +2007-07-27 11:16:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtsp/gstrtspextension.c: Fire the signal on the object, not the interface. + Original commit message from CVS: + * gst-libs/gst/rtsp/gstrtspextension.c: (gst_rtsp_extension_send): + Fire the signal on the object, not the interface. + +2007-07-27 09:17:19 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtsp/.cvsignore: Ber. Don't include the full path, idiot. + Original commit message from CVS: + * gst-libs/gst/rtsp/.cvsignore: + Ber. Don't include the full path, idiot. + +2007-07-27 08:29:29 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtsp/.cvsignore: Ignore generated files. + Original commit message from CVS: + * gst-libs/gst/rtsp/.cvsignore: + Ignore generated files. + +2007-07-26 19:57:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/: Move the rtspextension.h interface into gstrtspextension.h as part of libgstrtsp instead of libgstinte... + Original commit message from CVS: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/interfaces-marshal.list: + * gst-libs/gst/interfaces/rtspextension.c: + * gst-libs/gst/interfaces/rtspextension.h: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtsp.h: + * gst-libs/gst/rtsp/gstrtspextension.c: + (gst_rtsp_extension_get_type), (gst_rtsp_extension_iface_init), + (gst_rtsp_extension_detect_server), + (gst_rtsp_extension_before_send), (gst_rtsp_extension_after_send), + (gst_rtsp_extension_parse_sdp), (gst_rtsp_extension_setup_media), + (gst_rtsp_extension_configure_stream), + (gst_rtsp_extension_get_transports), + (gst_rtsp_extension_stream_select), (gst_rtsp_extension_send): + * gst-libs/gst/rtsp/gstrtspextension.h: + * gst-libs/gst/rtsp/rtsp-marshal.list: + Move the rtspextension.h interface into gstrtspextension.h + as part of libgstrtsp instead of libgstinterfaces, because it's + only for use within plugins, not applications. + Add stuff to do the enum & marshal generation needed in libgstrtsp now. + Use the GST_TYPE_RTSP_RESULT enum type for the return value of the + signal that the GstRTSPExtension interface emits, since G_TYPE_ENUM + is abstract. + +2007-07-26 15:48:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/interfaces/: Fix marshaller for the send signal. + Original commit message from CVS: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/interfaces-marshal.list: + * gst-libs/gst/interfaces/rtspextension.c: + (gst_rtsp_extension_iface_init), + (gst_rtsp_extension_stream_select), (gst_rtsp_extension_send): + * gst-libs/gst/interfaces/rtspextension.h: + Fix marshaller for the send signal. + Add URL to stream selection interface method. + +2007-07-26 15:35:43 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/riff/Makefile.am: Pull in our dependencies from -base before those from outside. + Original commit message from CVS: + * gst-libs/gst/riff/Makefile.am: + Pull in our dependencies from -base before those from outside. + +2007-07-26 14:33:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + API: gst_rtsp_base64_decode_ip() + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspbase64.c: (gst_rtsp_base64_decode_ip): + * gst-libs/gst/rtsp/gstrtspbase64.h: + API: gst_rtsp_base64_decode_ip() + Added function to decode Base64 in-place. + +2007-07-26 14:08:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/libs/.cvsignore: Ignore the mixer test binary. + Original commit message from CVS: + * tests/check/libs/.cvsignore: + Ignore the mixer test binary. + +2007-07-26 10:00:37 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/vorbis/vorbisdec.c: Gratuitous comment change to trigger a rebuild on the buildbots. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_push_forward): + Gratuitous comment change to trigger a rebuild on the buildbots. + +2007-07-25 18:20:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/sdp/gstsdpmessage.*: Constify args where we can. + Original commit message from CVS: + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_media_get_media), + (gst_sdp_media_get_port), (gst_sdp_media_get_num_ports), + (gst_sdp_media_get_proto), (gst_sdp_media_formats_len), + (gst_sdp_media_get_format), (gst_sdp_media_get_information), + (gst_sdp_media_connections_len), (gst_sdp_media_get_connection), + (gst_sdp_media_bandwidths_len), (gst_sdp_media_get_badwidth), + (gst_sdp_media_get_key), (gst_sdp_media_attributes_len), + (gst_sdp_media_get_attribute), (gst_sdp_media_get_attribute_val_n), + (gst_sdp_media_get_attribute_val): + * gst-libs/gst/sdp/gstsdpmessage.h: + Constify args where we can. + +2007-07-25 18:18:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/interfaces/: Move interface for RTSP extensions from -good to here. + Original commit message from CVS: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/rtspextension.c: + (gst_rtsp_extension_get_type), (gst_rtsp_extension_iface_init), + (gst_rtsp_extension_detect_server), + (gst_rtsp_extension_before_send), (gst_rtsp_extension_after_send), + (gst_rtsp_extension_parse_sdp), (gst_rtsp_extension_setup_media), + (gst_rtsp_extension_configure_stream), + (gst_rtsp_extension_get_transports), + (gst_rtsp_extension_stream_select), (gst_rtsp_extension_send): + * gst-libs/gst/interfaces/rtspextension.h: + Move interface for RTSP extensions from -good to here. + Added helper methods to invoke interface methods. + +2007-07-25 11:22:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + Fix some more RTSP docs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtspmessage.c: (key_value_foreach), + (gst_rtsp_message_get_type), (gst_rtsp_message_parse_request), + (gst_rtsp_message_init_response), + (gst_rtsp_message_parse_response), (gst_rtsp_message_new_data), + (gst_rtsp_message_parse_data), (gst_rtsp_message_add_header), + (gst_rtsp_message_remove_header), (gst_rtsp_message_get_header), + (gst_rtsp_message_append_headers), (gst_rtsp_message_set_body), + (gst_rtsp_message_get_body), (dump_key_value): + * gst-libs/gst/rtsp/gstrtspmessage.h: + * gst-libs/gst/rtsp/gstrtsprange.c: (parse_npt_time), + (parse_npt_range), (parse_clock_range), (parse_smpte_range), + (gst_rtsp_range_parse): + * gst-libs/gst/rtsp/gstrtsprange.h: + * gst-libs/gst/rtsp/gstrtsptransport.c: + * gst-libs/gst/rtsp/gstrtspurl.c: + Fix some more RTSP docs. + Add some missing methods for dealing with messages. + +2007-07-24 19:19:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + Added beginnings of RTSP documentation. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtsp/gstrtspbase64.c: (gst_rtsp_base64_encode): + * gst-libs/gst/rtsp/gstrtspbase64.h: + * gst-libs/gst/rtsp/gstrtspconnection.c: + (gst_rtsp_connection_connect), (add_auth_header), + (gst_rtsp_connection_write), (gst_rtsp_connection_send), + (read_body), (gst_rtsp_connection_receive), + (gst_rtsp_connection_next_timeout), + (gst_rtsp_connection_reset_timeout), + (gst_rtsp_connection_set_auth): + * gst-libs/gst/rtsp/gstrtspconnection.h: + * gst-libs/gst/rtsp/gstrtspdefs.c: (rtsp_init_status): + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtspmessage.h: + * gst-libs/gst/rtsp/gstrtsprange.c: (parse_npt_time), + (parse_npt_range), (parse_clock_range), (parse_smpte_range), + (gst_rtsp_range_parse): + * gst-libs/gst/rtsp/gstrtspurl.h: + Added beginnings of RTSP documentation. + +2007-07-24 17:37:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + Document the SDP library. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/sdp/gstsdp.h: + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_message_set_origin), + (gst_sdp_message_set_connection), (gst_sdp_message_add_bandwidth), + (gst_sdp_message_add_time), (gst_sdp_message_add_zone), + (gst_sdp_message_set_key), (gst_sdp_message_get_attribute_val_n), + (gst_sdp_message_get_attribute_val), + (gst_sdp_message_add_attribute), (gst_sdp_media_new), + (gst_sdp_media_init), (gst_sdp_media_uninit), (gst_sdp_media_free), + (gst_sdp_media_get_media), (gst_sdp_media_set_media), + (gst_sdp_media_get_port), (gst_sdp_media_get_num_ports), + (gst_sdp_media_set_port_info), (gst_sdp_media_get_proto), + (gst_sdp_media_set_proto), (gst_sdp_media_formats_len), + (gst_sdp_media_get_format), (gst_sdp_media_add_format), + (gst_sdp_media_get_information), (gst_sdp_media_set_information), + (gst_sdp_media_connections_len), (gst_sdp_media_get_connection), + (gst_sdp_media_add_connection), (gst_sdp_media_bandwidths_len), + (gst_sdp_media_get_badwidth), (gst_sdp_media_add_bandwidth), + (gst_sdp_media_set_key), (gst_sdp_media_get_key), + (gst_sdp_media_attributes_len), (gst_sdp_media_add_attribute), + (gst_sdp_media_get_attribute_val_n), + (gst_sdp_media_get_attribute_val), (gst_sdp_message_parse_buffer), + (print_media), (gst_sdp_message_dump): + * gst-libs/gst/sdp/gstsdpmessage.h: + Document the SDP library. + Add some of the missing SDPMedia methods. + +2007-07-24 11:52:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + Move SDP and RTSP from helper objects in -good to a reusable library. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/rtsp/Makefile.am: + * gst-libs/gst/rtsp/gstrtspbase64.c: (gst_rtsp_base64_encode): + * gst-libs/gst/rtsp/gstrtspbase64.h: + * gst-libs/gst/rtsp/gstrtspconnection.c: (inet_aton), + (gst_rtsp_connection_create), (gst_rtsp_connection_connect), + (add_auth_header), (add_date_header), (gst_rtsp_connection_write), + (gst_rtsp_connection_send), (read_line), (read_string), (read_key), + (parse_response_status), (parse_request_line), (parse_line), + (gst_rtsp_connection_read), (read_body), + (gst_rtsp_connection_receive), (gst_rtsp_connection_close), + (gst_rtsp_connection_free), (gst_rtsp_connection_next_timeout), + (gst_rtsp_connection_reset_timeout), (gst_rtsp_connection_flush), + (gst_rtsp_connection_set_auth): + * gst-libs/gst/rtsp/gstrtspconnection.h: + * gst-libs/gst/rtsp/gstrtspdefs.c: (rtsp_init_status), + (gst_rtsp_strresult), (gst_rtsp_method_as_text), + (gst_rtsp_version_as_text), (gst_rtsp_header_as_text), + (gst_rtsp_status_as_text), (gst_rtsp_find_header_field), + (gst_rtsp_find_method): + * gst-libs/gst/rtsp/gstrtspdefs.h: + * gst-libs/gst/rtsp/gstrtspmessage.c: (key_value_foreach), + (gst_rtsp_message_new), (gst_rtsp_message_init), + (gst_rtsp_message_new_request), (gst_rtsp_message_init_request), + (gst_rtsp_message_new_response), (gst_rtsp_message_init_response), + (gst_rtsp_message_init_data), (gst_rtsp_message_unset), + (gst_rtsp_message_free), (gst_rtsp_message_add_header), + (gst_rtsp_message_remove_header), (gst_rtsp_message_get_header), + (gst_rtsp_message_append_headers), (gst_rtsp_message_set_body), + (gst_rtsp_message_take_body), (gst_rtsp_message_get_body), + (gst_rtsp_message_steal_body), (dump_mem), (dump_key_value), + (gst_rtsp_message_dump): + * gst-libs/gst/rtsp/gstrtspmessage.h: + * gst-libs/gst/rtsp/gstrtsprange.c: (parse_npt_time), + (parse_npt_range), (parse_clock_range), (parse_smpte_range), + (gst_rtsp_range_parse), (gst_rtsp_range_free): + * gst-libs/gst/rtsp/gstrtsprange.h: + * gst-libs/gst/rtsp/gstrtsptransport.c: (gst_rtsp_transport_new), + (gst_rtsp_transport_init), (gst_rtsp_transport_get_mime), + (gst_rtsp_transport_get_manager), (parse_mode), (parse_range), + (range_as_text), (rtsp_transport_mode_as_text), + (rtsp_transport_profile_as_text), (rtsp_transport_ltrans_as_text), + (gst_rtsp_transport_parse), (gst_rtsp_transport_as_text), + (gst_rtsp_transport_free): + * gst-libs/gst/rtsp/gstrtsptransport.h: + * gst-libs/gst/rtsp/gstrtspurl.c: (gst_rtsp_url_parse), + (gst_rtsp_url_free), (gst_rtsp_url_set_port), + (gst_rtsp_url_get_port), (gst_rtsp_url_get_request_uri): + * gst-libs/gst/rtsp/gstrtspurl.h: + * gst-libs/gst/sdp/Makefile.am: + * gst-libs/gst/sdp/gstsdp.h: + * gst-libs/gst/sdp/gstsdpmessage.c: (gst_sdp_origin_init), + (gst_sdp_connection_init), (gst_sdp_bandwidth_init), + (gst_sdp_time_init), (gst_sdp_zone_init), (gst_sdp_key_init), + (gst_sdp_attribute_init), (gst_sdp_message_new), + (gst_sdp_message_init), (gst_sdp_message_uninit), + (gst_sdp_message_free), (gst_sdp_media_new), (gst_sdp_media_init), + (gst_sdp_media_uninit), (gst_sdp_media_free), + (gst_sdp_message_set_origin), (gst_sdp_message_get_origin), + (gst_sdp_message_set_connection), (gst_sdp_message_get_connection), + (gst_sdp_message_add_bandwidth), (gst_sdp_message_add_time), + (gst_sdp_message_add_zone), (gst_sdp_message_set_key), + (gst_sdp_message_get_key), (gst_sdp_message_get_attribute_val_n), + (gst_sdp_message_get_attribute_val), + (gst_sdp_message_add_attribute), (gst_sdp_message_add_media), + (gst_sdp_media_add_attribute), (gst_sdp_media_add_bandwidth), + (gst_sdp_media_add_format), (gst_sdp_media_get_attribute), + (gst_sdp_media_get_attribute_val_n), + (gst_sdp_media_get_attribute_val), (gst_sdp_media_get_format), + (read_string), (read_string_del), (gst_sdp_parse_line), + (gst_sdp_message_parse_buffer), (print_media), + (gst_sdp_message_dump): + * gst-libs/gst/sdp/gstsdpmessage.h: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + Move SDP and RTSP from helper objects in -good to a reusable library. + Use a proper gst_ namespace. + +2007-07-23 18:42:22 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/vorbis/vorbisdec.c: Use the new buffer clipping function from gstaudio here. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_push_forward), + (vorbis_dec_flush_decode): + Use the new buffer clipping function from gstaudio here. + +2007-07-23 18:26:09 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + API: Add buffer clipping function for raw audio buffers. Fixes #456656. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/audio.c: (gst_audio_buffer_clip): + * gst-libs/gst/audio/audio.h: + * tests/check/libs/audio.c: (GST_START_TEST), (audio_suite): + API: Add buffer clipping function for raw audio buffers. Fixes #456656. + Also add deprecation guards for gst_audio_structure_set_int() to the + header. + +2007-07-23 14:45:16 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Cleanup the docs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + Cleanup the docs. + +2007-07-23 11:18:35 +0000 Dan Williams <dcbw@redhat.com> + + gst/playback/gstplaybasebin.c: Don't return NULL when querying the stream info value array but instead return an empt... + Original commit message from CVS: + Patch by: Dan Williams <dcbw at redhat dot com> + * gst/playback/gstplaybasebin.c: + (gst_play_base_bin_get_streaminfo_value_array): + Don't return NULL when querying the stream info value array but instead + return an empty array. Fixes #459204. + +2007-07-23 10:41:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gsturidecodebin.c: Init debug category before using it. + Original commit message from CVS: + * gst/playback/gsturidecodebin.c: + Init debug category before using it. + +2007-07-21 09:56:09 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/interfaces/mixer.h: Add padding vars in place of the signal pointers when building with DISABLE_DEPRECAT... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixer.h: + Add padding vars in place of the signal pointers + when building with DISABLE_DEPRECATED so that the + interface structure doesn't change size. + +2007-07-21 09:21:12 +0000 Marc-Andre Lureau <marcandre.lureau@gmail.com> + + Fixes: #152864 + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsamixer.h: + * ext/alsa/gstalsamixerelement.c: + * ext/alsa/gstalsamixertrack.c: + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/interfaces/mixeroptions.c: + * gst-libs/gst/interfaces/mixeroptions.h: + * gst-libs/gst/interfaces/mixertrack.c: + * gst-libs/gst/interfaces/mixertrack.h: + * tests/check/Makefile.am: + * tests/check/libs/mixer.c: + Patch By: Marc-Andre Lureau <marcandre.lureau@gmail.com> + Fixes: #152864 + Add support for notifying mixer changes on the message bus, and + implement it in alsamixer. + API: gst_mixer_get_mixer_flags + API: gst_mixer_message_parse_mute_toggled + API: gst_mixer_message_parse_record_toggled + API: gst_mixer_message_parse_volume_changed + API: gst_mixer_message_parse_option_changed + API: GstMixerMessageType + API: GstMixerFlags + +2007-07-20 16:09:03 +0000 Michael Smith <msmith@xiph.org> + + sys/xvimage/xvimagesink.c: xcontext->im_format is only for testing XShm support (as the header file comments document... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_get_xv_support), (gst_xvimagesink_setcaps): + xcontext->im_format is only for testing XShm support (as the header + file comments document). Use xvimage->im_format for everything else. + Avoids spurious warnings on buffer allocation before setcaps. + +2007-07-20 07:22:15 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/: We should use $(LIBM). + Original commit message from CVS: + * tests/examples/volume/Makefile.am: + * tests/icles/Makefile.am: + We should use $(LIBM). + +2007-07-20 06:13:21 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/icles/Makefile.am: This needs -lm. + Original commit message from CVS: + * tests/icles/Makefile.am: + This needs -lm. + +2007-07-18 07:35:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add stdlib include (free, atoi, exit). + Original commit message from CVS: + * examples/app/appsrc_ex.c: + * examples/switch/switcher.c: + * ext/neon/gstneonhttpsrc.c: + * ext/timidity/gstwildmidi.c: + * ext/x264/gstx264enc.c: + * gst/mve/mveaudioenc.c: (mve_compress_audio): + * gst/rtpmanager/gstrtpclient.c: + * gst/rtpmanager/gstrtpjitterbuffer.c: + * gst/spectrum/demo-audiotest.c: + * gst/spectrum/demo-osssrc.c: + * sys/dvb/gstdvbsrc.c: + Add stdlib include (free, atoi, exit). + +2007-07-16 10:10:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.c: Don't break ABI, restore previous ranges. Keep the default random selection of ... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_class_init), (gst_basertppayload_init), + (gst_basertppayload_set_property), + (gst_basertppayload_get_property): + Don't break ABI, restore previous ranges. Keep the default random + selection of timestamp and seqnum offset but as soon as the app sets a + specific value, use that one. + +2007-07-14 18:33:15 +0000 Bastien Nocera <hadess@hadess.net> + + sys/xvimage/xvimagesink.*: Add option to turn off double-buffering for debugging purposes. + Original commit message from CVS: + Patch by: Bastien Nocera <hadess at hadess dot net> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + Add option to turn off double-buffering for debugging purposes. + Fixes #437169. + +2007-07-14 18:20:41 +0000 Jorn Baayen <jorn@openedhand.com> + + sys/: add 'handle-expose' property. Useful for video widgets which may want to be in control of Expose behaviour. Fix... + Original commit message from CVS: + Patch by: Jorn Baayen <jorn at openedhand dot com> + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents), + (gst_ximagesink_set_property), (gst_ximagesink_get_property), + (gst_ximagesink_init), (gst_ximagesink_class_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + add 'handle-expose' property. Useful for video widgets which may want to + be in control of Expose behaviour. Fixes #380625 + +2007-07-14 17:23:42 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertppayload.*: Fix ranges of rtp payloader properties so that the full range can be used in ad... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_class_init), (gst_basertppayload_init), + (gst_basertppayload_event), (gst_basertppayload_push), + (gst_basertppayload_set_property), + (gst_basertppayload_get_property), + (gst_basertppayload_change_state): + * gst-libs/gst/rtp/gstbasertppayload.h: + Fix ranges of rtp payloader properties so that the full range can be + used in addition to -1 (random). + Fix wrong seqnum reporting in caps. + Fixes #420326. + +2007-07-13 18:12:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videorate/gstvideorate.c: Use boilerplate. + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_init), + (gst_video_rate_query): + Use boilerplate. + Add latency query, might not be perfect yet but already works a lot + better. Fixes #442557. + +2007-07-13 16:05:17 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/xvimage/xvimagesink.*: After a caps change, redraw our borders to avoid garbage left there when the image format ... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_setcaps): + * sys/xvimage/xvimagesink.h: + After a caps change, redraw our borders to avoid garbage left there + when the image format changes to a smaller size, like 16:9 -> 4:3 + Also, hold the flow_lock a bit longer in the set_caps while we're + fiddling with the xcontext. + +2007-07-13 16:02:23 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Remove bogus check for libcheck, since we check for gstreamer-check and it pulls in the required info from there, and... + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * tests/Makefile.am: + Remove bogus check for libcheck, since we check for + gstreamer-check and it pulls in the required info from there, and we + weren't actually _using_ the information for libcheck ourselves + anyway. + +2007-07-13 15:52:02 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Fix the r_mask test for RGBA32 on little-endian. + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_caps_to_pixfmt): + Fix the r_mask test for RGBA32 on little-endian. + Fix a stupid typo that would have obviously broken + compilation on big-endian, if anyone was testing. + +2007-07-12 15:02:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videotestsrc/videotestsrc.*: Add alpha to the color struct. + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: (paint_hline_AYUV), + (paint_hline_str4): + * gst/videotestsrc/videotestsrc.h: + Add alpha to the color struct. + Use a default alpha value of 255 instead of 128. + +2007-07-12 12:01:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Clear the dynamic pads counter when starting a new uri. This makes reusing playbin wor... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (no_more_pads_full), + (setup_source): + Clear the dynamic pads counter when starting a new uri. This makes + reusing playbin work again. + Fixes #454264. + +2007-07-12 11:13:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Use pkg-config to locate check. + Original commit message from CVS: + * configure.ac: + Use pkg-config to locate check. + +2007-07-11 23:12:12 +0000 Tim-Philipp Müller <tim@centricular.net> + + Fix 'make check' build against core CVS. + Original commit message from CVS: + * configure.ac: + * tests/check/elements/volume.c: (GST_START_TEST): + Fix 'make check' build against core CVS. + +2007-07-10 20:46:41 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/: Make gtk-doc happy. + Original commit message from CVS: + * gst-libs/gst/interfaces/propertyprobe.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/tag/gstvorbistag.c: + Make gtk-doc happy. + +2007-07-08 13:07:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstbaseaudiosink.c: Quick hack to make audiosinks stop at EOS when operating in pull-mode; needs t... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_callback): + Quick hack to make audiosinks stop at EOS when operating in + pull-mode; needs to be fixed properly some day. + +2007-07-06 18:19:39 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Fix location of includes in the docs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + Fix location of includes in the docs. + +2007-07-06 11:40:45 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/ffmpegcolorspace/: Add 2 new pixel formats - ABGR32 and ARGB32, which are reflections of the existing BGRA32 and ... + Original commit message from CVS: + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (img_convert), + (img_get_alpha_info): + Add 2 new pixel formats - ABGR32 and ARGB32, which are reflections + of the existing BGRA32 and RGBA32 formats with the alpha at the other + end of the word. Partially fixes #451908 + +2007-07-05 08:43:30 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/: Simplify --extra-dir as gtkdoc scans recursively. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Simplify --extra-dir as gtkdoc scans recursively. + +2007-07-03 11:52:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.c: Make getcaps more robust by not using the proxycaps function. This makes sure that we don't end... + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_sink_getcaps), + (gst_adder_request_new_pad): + Make getcaps more robust by not using the proxycaps function. This makes + sure that we don't end up recursively calling getcaps upstream. + See #316248. + +2007-06-29 17:21:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audioconvert/audioconvert.c: Include math.h to fix compilation. + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: + Include math.h to fix compilation. + +2007-06-29 14:47:42 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Add a mapping for YUV format "IYU1", which is a 4:1:1 packed pixel format, ... + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt): + Add a mapping for YUV format "IYU1", which is a 4:1:1 packed pixel + format, as produced by some dc1394 cameras like the iSight. + See http://www.fourcc.org/yuv.php#IYU1 + +2007-06-28 20:37:58 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/: Implement dithering and noise shaping in audioconvert. By default now + Original commit message from CVS: + * gst/audioconvert/Makefile.am: + * gst/audioconvert/audioconvert.c: (audio_convert_get_func_index), + (check_default), (audio_convert_prepare_context), + (audio_convert_clean_context), (audio_convert_convert): + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_dithering_get_type), + (gst_audio_convert_ns_get_type), (gst_audio_convert_class_init), + (gst_audio_convert_init), (gst_audio_convert_set_caps), + (gst_audio_convert_set_property), (gst_audio_convert_get_property): + * gst/audioconvert/gstaudioconvert.h: + * gst/audioconvert/gstaudioquantize.c: + (gst_audio_quantize_setup_noise_shaping), + (gst_audio_quantize_free_noise_shaping), + (gst_audio_quantize_setup_dither), + (gst_audio_quantize_free_dither), + (gst_audio_quantize_setup_quantize_func), + (gst_audio_quantize_setup), (gst_audio_quantize_free): + * gst/audioconvert/gstaudioquantize.h: + Implement dithering and noise shaping in audioconvert. By default now + TPDF dithering (and no noise shaping) will be used when converting + from a higher bit depth to 20 bit depth or smaller, otherwise + everything will be as it is now. + For the last audioconvert in a pipeline it would make sense to + use some kind of noise shaping, enabling it by default for all + conversions would give undesired results though. Fixes #360246. + * tests/check/elements/audioconvert.c: (setup_audioconvert), + (GST_START_TEST): + Adjust unit test for the new audioconvert. + +2007-06-28 11:06:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Use other metrics as well when estimating the buffer level. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (apply_segment), (update_buffering): + Use other metrics as well when estimating the buffer level. + +2007-06-28 10:21:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Small debug improvement. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (make_decoder), (setup_source): + Small debug improvement. + * gst/playback/gstqueue2.c: (apply_segment), (update_buffering), + (plugin_init): + Tweak the rate estimation period. + When calculating the buffer filledness in rate estimation mode, don't + mix it with other metrics. + +2007-06-28 09:46:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: When creating the groups, allow for a 5 second, unlimited buffers preroll phase after w... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_group_new), + (gst_decode_group_expose), (gst_decode_group_free), (add_fakesink): + When creating the groups, allow for a 5 second, unlimited buffers + preroll phase after which we expose the group. + When the group is exposed, use a small number of buffers up to a 2 + second limit. Also disconnect the overrun signal from multiqueue when we + exposed the group because it is not needed anymore. + +2007-06-27 22:30:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/tags.c: Don't pass trailing zeroes in fixed-size string arrays in ID3v1 tags to utf8-validate; fixes... + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (gst_tag_freeform_string_to_utf8): + Don't pass trailing zeroes in fixed-size string arrays in ID3v1 tags + to utf8-validate; fixes recognition of ID3v1 tags in UTF-8 encoding + (#451707); also, output some debugging info when dealing with + freeform strings. + * tests/check/libs/tag.c: (GST_START_TEST), (tag_suite): + Add unit test for the above. + +2007-06-27 12:55:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/descriptions.c: Add description for Windows Media RTP caps. + Original commit message from CVS: + * gst-libs/gst/pbutils/descriptions.c: (caps_are_rtp_caps): + Add description for Windows Media RTP caps. + * gst-libs/gst/pbutils/missing-plugins.c: (copy_and_clean_caps): + Remove RTP fields that don't define the format from caps. + +2007-06-27 10:14:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/vorbis/vorbisdec.c: Skip empty buffers, but not empty header buffers. That way the original vorbisdec unit test s... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_decode_buffer): + Skip empty buffers, but not empty header buffers. That way the original + vorbisdec unit test still passes (#451145); also, take into account + that those empty packets might carry a granulepos. + * tests/check/Makefile.am: + * tests/check/elements/vorbisdec.c: + (_create_codebook_header_buffer), (_create_audio_buffer), + (GST_START_TEST), (vorbisdec_suite): + Add unit test that sends an empty packet. + +2007-06-27 09:49:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Don't error out on 0-sized packets, just emit a warning because this is not a fatal error. Fi... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_decode_buffer): + Don't error out on 0-sized packets, just emit a warning because this is + not a fatal error. Fixes #451145. + +2007-06-25 12:43:01 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/plugins/: Update docs with caps info. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-decodebin2.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Update docs with caps info. + +2007-06-25 12:04:15 +0000 Tim-Philipp Müller <tim@centricular.net> + + po/POTFILES.in: Add more files with translatable strings (#450875). + Original commit message from CVS: + * po/POTFILES.in: + Add more files with translatable strings (#450875). + +2007-06-23 14:44:07 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/ogg/gstoggdemux.c: The chain should be freed if we error out here, else it will leak. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_find_chains): + The chain should be freed if we error out here, else it will leak. + * gst/playback/gstdecodebin.c: (disconnect_unlinked_signals), + (cleanup_decodebin): + Don't forget to *properly* remove the signals, else it will leak. + +2007-06-22 14:25:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + MAINTAINERS: Updating all the maintainers files + Original commit message from CVS: + * MAINTAINERS: + Updating all the maintainers files + +2007-06-21 08:34:46 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Destroy and recreate parse-launch based pipeline after stop to be able to play again. Reo... + Original commit message from CVS: + * tests/examples/seek/seek.c: (update_scale), (play_cb), (stop_cb), + (main): + Destroy and recreate parse-launch based pipeline after stop to be able + to play again. Reorder some code and add more comments. + +2007-06-20 11:09:03 +0000 Wim Taymans <wim@fluendo.com> + + gst/playback/gstdecodebin2.c: When handling a delayed-caps notification case, mark the group as dynamic so that the n... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (analyze_new_pad): + When handling a delayed-caps notification case, mark + the group as dynamic so that the nbdynamic count is + incremented and decremented correctly. Fixes: #449156 + Patch by: Wim Taymans <wim@fluendo.com> + +2007-06-19 19:13:04 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst-libs/gst/audio/gstbaseaudiosink.c: + * win32/common/config.h: + gst-libs/gst/audio/gstbaseaudiosink.c + Original commit message from CVS: + 2007-06-19 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_init): Enable pull-mode operation. + +2007-06-19 09:34:35 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/riff/riff-media.c: Change minimum rate back to 1000 to allow low-sample-rate wav files to play back. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Change minimum rate back to 1000 to allow low-sample-rate wav files + to play back. + +2007-06-17 17:27:09 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/vi.po: Update translations. + Original commit message from CVS: + * po/vi.po: + Update translations. + +2007-06-16 03:42:14 +0000 David Schleef <ds@schleef.org> + + gst/playback/gstqueue2.c: Fix compile error from ignored return value. + Original commit message from CVS: + * gst/playback/gstqueue2.c: + Fix compile error from ignored return value. + +2007-06-15 15:23:36 +0000 Michael Smith <msmith@xiph.org> + + gst/videoscale/vs_4tap.c: Update tmpbuf for all neccesary rows, not just one, as is required when downscaling. + Original commit message from CVS: + * gst/videoscale/vs_4tap.c: (vs_image_scale_4tap_Y): + Update tmpbuf for all neccesary rows, not just one, as is required + when downscaling. + Fixes #402076. + +2007-06-15 11:15:28 +0000 Michael Smith <msmith@xiph.org> + + tests/check/pipelines/oggmux.c: Add a test that ensures we set DELTA_UNIT on all non-header, non-video buffers, if we... + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: (validate_ogg_page), (is_video), + (eos_buffer_probe): + Add a test that ensures we set DELTA_UNIT on all non-header, + non-video buffers, if we have a video stream. + * ext/ogg/gstoggmux.c: (gst_ogg_mux_queue_pads), + (gst_ogg_mux_process_best_pad): + Move setting delta_pad to earlier, where we inspect all pads, so + that leading audio pages don't get DELTA_UNIT unset if they come + before the first DELTA_UNIT from video pages. Fixes the newly-added + test. Fixes #385527. + +2007-06-14 19:53:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/streamheader.c: Disable test_multifdsink_gdp_vorbisenc() on ppc64 since it fails on the p5-ppc6... + Original commit message from CVS: + * tests/check/pipelines/streamheader.c: (streamheader_suite): + Disable test_multifdsink_gdp_vorbisenc() on ppc64 since it + fails on the p5-ppc64 build bot and the failure looks like it is due + to the same issue as #348114, ie. a compiler bug. + +2007-06-13 18:20:57 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstqueue2.c: Fix build on MacOSX. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_create_read): + Fix build on MacOSX. + +2007-06-13 09:01:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Fix compilation on mingw. Fixes #446972. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_read_chain): + Fix compilation on mingw. Fixes #446972. + +2007-06-12 08:38:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Fix a division by zero when the max percent is <= 0. Fixes #446572. also update the bufferi... + Original commit message from CVS: + Patches by: Thiago Sousa Santos <thiagossantos at gmail dot com> + * gst/playback/gstqueue2.c: (update_buffering), + (gst_queue_locked_enqueue): + Fix a division by zero when the max percent is <= 0. Fixes #446572. + also update the buffering status when receiving events. Fixes #446551. + +2007-06-11 11:32:26 +0000 Thiago Sousa Santos <thiagossantos@gmail.com> + + gst/playback/gstqueue2.c: Wait for preroll before attempting to forward a duration query upstream. + Original commit message from CVS: + Based on patch by: Thiago Sousa Santos <thiagossantos at gmail dot com> + * gst/playback/gstqueue2.c: (gst_queue_peer_query), + (gst_queue_handle_src_query): + Wait for preroll before attempting to forward a duration query upstream. + Fixes #445505. + +2007-06-07 21:08:38 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Use G_GINT64_CONSTANT macro for int64 constant. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_set_gst_timestamp): + Use G_GINT64_CONSTANT macro for int64 constant. + * win32/common/libgstinterfaces.def: + * win32/common/libgsttag.def: + Add new exported functions. + +2007-06-07 14:25:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggmux.c: The BOS page of the first Dirac video stream needs to come before the BOS page of any Vorbis str... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_send_headers): + The BOS page of the first Dirac video stream needs to come before + the BOS page of any Vorbis streams or other audio streams, just like + it is with Theora. + +2007-06-07 09:11:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Fix compilation. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_get_range): + Fix compilation. + +2007-06-06 13:36:26 +0000 Thiago Sousa Santos <thiagossantos@gmail.com> + + gst/playback/gstqueue2.c: Add pull based scheduling and fix some deadlocks. Fixes #444523. + Original commit message from CVS: + Patch by: Thiago Sousa Santos <thiagossantos at gmail dot com> + * gst/playback/gstqueue2.c: (gst_queue_init), + (gst_queue_handle_sink_event), (gst_queue_chain), + (gst_queue_get_range), (gst_queue_src_checkgetrange_function), + (gst_queue_sink_activate_push), (gst_queue_src_activate_push), + (gst_queue_src_activate_pull): + Add pull based scheduling and fix some deadlocks. Fixes #444523. + Does not yet completely work because duration queries upstream won't + block yet. + +2007-06-06 09:08:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + Some more fseeko checks. + Original commit message from CVS: + * configure.ac: + * gst/playback/gstqueue2.c: (gst_queue_create_read): + Some more fseeko checks. + +2007-06-06 08:01:42 +0000 Wim Taymans <wim.taymans@gmail.com> + + configure.ac: check for large file support. + Original commit message from CVS: + * configure.ac: + check for large file support. + +2007-06-05 21:36:11 +0000 Sven Arvidsson <sa@whiz.se> + + gst/subparse/gstsubparse.*: Add support for SubViewer version 1 and 2 subtitles. Fixes #394061. + Original commit message from CVS: + Based on a patch by Sven Arvidsson <sa at whiz dot se>: + * gst/subparse/gstsubparse.c: (parse_subrip), + (subviewer_unescape_newlines), (parse_subviewer), + (gst_sub_parse_data_format_autodetect), + (gst_sub_parse_format_autodetect), (gst_subparse_type_find): + * gst/subparse/gstsubparse.h: + Add support for SubViewer version 1 and 2 subtitles. Fixes #394061. + * tests/check/elements/subparse.c: (GST_START_TEST), + (subparse_suite): + Add a unit test for both SubViewer formats. + +2007-06-05 17:08:04 +0000 Michael Smith <msmith@xiph.org> + + gst/audiotestsrc/gstaudiotestsrc.c: Don't overflow intermediate values when seeking to large time values in audiotest... + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_do_seek): + Don't overflow intermediate values when seeking to large time values + in audiotestsrc. + +2007-06-05 17:02:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Include stdio to define fseeko. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_have_data), + (gst_queue_create_read), (gst_queue_read_item_from_file), + (gst_queue_open_temp_location_file), (gst_queue_locked_enqueue): + Include stdio to define fseeko. + +2007-06-05 16:37:09 +0000 Edward Hervey <edward@fluendo.com> + + sys/v4l/gstv4lsrc.c: Make v4lsrc output segments in GST_FORMAT_TIME. Fixes #442553. + Original commit message from CVS: + Patch by: Edward Hervey <edward@fluendo.com> + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_init), (gst_v4lsrc_fixate), + (gst_v4lsrc_query): + Make v4lsrc output segments in GST_FORMAT_TIME. Fixes #442553. + +2007-06-05 16:20:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/: Use gst_tag_utf8_from_freeform_string() from libgsttag instead of our own implementation. + Original commit message from CVS: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/riff/riff-read.c: (gst_riff_parse_info): + Use gst_tag_utf8_from_freeform_string() from libgsttag instead of + our own implementation. + +2007-06-05 16:19:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Handle timestamp wraparound. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_change_state): + Handle timestamp wraparound. + +2007-06-05 16:17:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gsturidecodebin.c: Make sure we name srcpads uniquely even when using different internal decodebins. + Original commit message from CVS: + * gst/playback/gsturidecodebin.c: (no_more_pads_full), + (new_decoded_pad), (remove_pads), (make_decoder), (setup_source), + (gst_uri_decode_bin_change_state): + Make sure we name srcpads uniquely even when using different internal + decodebins. + Signal no-more-pads when no more dynamic elements exist. + Remove pads on cleanup. + +2007-06-05 16:14:23 +0000 Thiago Sousa Santos <thiagossantos@gmail.com> + + gst/playback/gstqueue2.c: Add support for filebased buffering. Fixes #441264. + Original commit message from CVS: + Based on patch by: Thiago Sousa Santos <thiagossantos at gmail dot com> + * gst/playback/gstqueue2.c: (gst_queue_class_init), + (gst_queue_init), (gst_queue_finalize), + (gst_queue_write_buffer_to_file), (gst_queue_have_data), + (gst_queue_create_read), (gst_queue_read_item_from_file), + (gst_queue_open_temp_location_file), + (gst_queue_close_temp_location_file), (gst_queue_locked_flush), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue), + (gst_queue_is_empty), (gst_queue_is_filled), + (gst_queue_change_state), (gst_queue_set_temp_location), + (gst_queue_set_property): + Add support for filebased buffering. Fixes #441264. + +2007-06-05 16:05:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Add support for delayed caps fixation when autoplugging. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_factory_filter), + (analyze_new_pad), (connect_pad), (expose_pad), (caps_notify_cb), + (caps_notify_group_cb), (gst_decode_group_new), + (gst_decode_group_free): + Add support for delayed caps fixation when autoplugging. + Optimize cases where a multiqueue is not needed/wanted, like right after + anything that is not a demuxer. + +2007-06-05 16:02:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: consideratly speedup ogg chain detection by not trying to find a base timestamp for skeleton s... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_parse_skeleton_fisbone), + (gst_ogg_pad_submit_packet), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_read_chain), (gst_ogg_demux_collect_chain_info): + consideratly speedup ogg chain detection by not trying to find a base + timestamp for skeleton streams. + +2007-06-05 16:00:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.*: Add support for remuve_flush. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_client_status_get_type), + (gst_multi_fd_sink_class_init), (gst_multi_fd_sink_add_full), + (gst_multi_fd_sink_remove_flush), + (gst_multi_fd_sink_remove_client_link), + (gst_multi_fd_sink_handle_client_write), + (gst_multi_fd_sink_handle_clients): + * gst/tcp/gstmultifdsink.h: + Add support for remuve_flush. + +2007-06-05 15:59:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add draft design for forcing keyframes in encoders and implement in theoraenc. + Original commit message from CVS: + * docs/design/draft-keyframe-force.txt: + * ext/theora/theoraenc.c: (theora_enc_sink_event), + (theora_enc_chain): + Add draft design for forcing keyframes in encoders and implement in + theoraenc. + +2007-06-05 13:22:18 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.13 === + +2007-06-05 12:50:24 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-decodebin2.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * gst-plugins-base.doap: + * win32/common/config.h: + * win32/vs6/grammar.dsp: + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstadder.dsp: + * win32/vs6/libgstaudio.dsp: + * win32/vs6/libgstaudioconvert.dsp: + * win32/vs6/libgstaudiorate.dsp: + * win32/vs6/libgstaudioresample.dsp: + * win32/vs6/libgstaudioscale.dsp: + * win32/vs6/libgstaudiotestsrc.dsp: + * win32/vs6/libgstcdda.dsp: + * win32/vs6/libgstdecodebin.dsp: + * win32/vs6/libgstdecodebin2.dsp: + * win32/vs6/libgstdirectsound.dsp: + * win32/vs6/libgstffmpegcolorspace.dsp: + * win32/vs6/libgstgdp.dsp: + * win32/vs6/libgstinterfaces.dsp: + * win32/vs6/libgstnetbuffer.dsp: + * win32/vs6/libgstogg.dsp: + * win32/vs6/libgstpbutils.dsp: + * win32/vs6/libgstplaybin.dsp: + * win32/vs6/libgstriff.dsp: + * win32/vs6/libgstrtp.dsp: + * win32/vs6/libgstsinesrc.dsp: + * win32/vs6/libgstsubparse.dsp: + * win32/vs6/libgsttag.dsp: + * win32/vs6/libgsttheora.dsp: + * win32/vs6/libgsttypefindfunctions.dsp: + * win32/vs6/libgstutils.dsp: + * win32/vs6/libgstvideo.dsp: + * win32/vs6/libgstvideorate.dsp: + * win32/vs6/libgstvideoscale.dsp: + * win32/vs6/libgstvideotestsrc.dsp: + * win32/vs6/libgstvolume.dsp: + * win32/vs6/libgstvorbis.dsp: + Release 0.10.13 "What's going on?" + Original commit message from CVS: + Release 0.10.13 "What's going on?" + +2007-06-05 12:32:03 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-05-31 17:08:58 +0000 Wim Taymans <wim@fluendo.com> + + gst-libs/gst/riff/riff-media.c: In riff, the depth is stored in the size field but it just means that the least signi... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + In riff, the depth is stored in the size field but it just means that + the least significant bits are cleared. We can therefore just play + the sample as if it had a depth == width. Fixes: #440997 + Patch by: Wim Taymans <wim@fluendo.com> + Patch by: Sebastian Dröge <slomo@circular-chaos.org> + +2007-05-31 16:36:22 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/floatcast/floatcast.h: Define inline when needed on win32 builds. Fixes: #441295 + Original commit message from CVS: + * gst-libs/gst/floatcast/floatcast.h: + Define inline when needed on win32 builds. Fixes: #441295 + +2007-05-29 13:38:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Stop buffering when the group is commited because the queues filled up. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (queue_overrun), + (no_more_pads_full): + Stop buffering when the group is commited because the queues filled up. + Fixes #442024. + +2007-05-25 10:07:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Revert commits towards #152864 made so far. We'll pick it up again after the 0.10.13 release. + Original commit message from CVS: + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_ensure_track_list), + (gst_alsa_mixer_free), (gst_alsa_mixer_update), + (gst_alsa_mixer_get_volume), (gst_alsa_mixer_set_volume), + (gst_alsa_mixer_set_mute), (gst_alsa_mixer_set_record), + (gst_alsa_mixer_set_option), (gst_alsa_mixer_get_option): + * ext/alsa/gstalsamixer.h: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_interface_supported), + (gst_alsa_mixer_element_finalize), (gst_alsa_mixer_element_init), + (gst_alsa_mixer_element_set_property), + (gst_alsa_mixer_element_get_property), + (gst_alsa_mixer_element_change_state): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_update): + * gst-libs/gst/interfaces/mixer.c: (gst_mixer_volume_changed), + (gst_mixer_option_changed): + * gst-libs/gst/interfaces/mixer.h: + Revert commits towards #152864 made so far. We'll pick it up again + after the 0.10.13 release. + +2007-05-24 16:22:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: After an interrupt (PAUSED/flush) assume that the next sample should not be al... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + After an interrupt (PAUSED/flush) assume that the next sample should not + be aligned to the previous sample. Fixes #417992. + +2007-05-24 15:16:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Don't add channels and rate fields to the template caps for audio/x-dts, as wavparse ... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Don't add channels and rate fields to the template caps for + audio/x-dts, as wavparse might not always be able to set them, + which would then lead to 'caps are not a real subset of the + template caps' warnings. + +2007-05-24 11:15:32 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybasebin.c: Handle unknown or invalid pads without crashing, as might occur if a media file like a... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (new_decoded_pad_full): + Handle unknown or invalid pads without crashing, as might occur if + a media file like an mp3 is specified as a subtitle file. + Fixes: #410039 + +2007-05-24 10:19:54 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybin.c: Block the subtitle bin output queue before ghosting it and linking, then unblock after. Th... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (add_sink), (dummy_blocked_cb), + (setup_sinks): + Block the subtitle bin output queue before ghosting it and linking, + then unblock after. This avoids spurious not-linked errors caused + by the queue starting up (because it gets linked when it is ghosted). + Fixes: #350299 + +2007-05-23 15:54:28 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/elements/playbin.c: Use /dev/zero instead of /dev/urandom to produce an invalid subtitle file. Avoids flu... + Original commit message from CVS: + * tests/check/elements/playbin.c: (test_suburi_error_unknowntype): + Use /dev/zero instead of /dev/urandom to produce an invalid subtitle + file. Avoids flukes where the input gets typefound to some valid but + useless type. + +2007-05-22 15:45:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add unit test for gnomevfssink seeking and position reporting for file:// URIs. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/gnomevfssink.c: (setup_gnomevfssink), + (cleanup_gnomevfssink), (GST_START_TEST), (gnomevfssink_suite): + Add unit test for gnomevfssink seeking and position reporting for + file:// URIs. + +2007-05-22 15:30:26 +0000 Mark Nauwelaerts <manauw@skynet.be> + + ext/gnomevfs/gstgnomevfssink.*: see #412648. + Original commit message from CVS: + Patch by: Mark Nauwelaerts <manauw at skynet be> + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_init), + (gst_gnome_vfs_sink_open_file), (gst_gnome_vfs_sink_handle_event), + (gst_gnome_vfs_sink_query), (gst_gnome_vfs_sink_render): + * ext/gnomevfs/gstgnomevfssink.h: + Fix position reporting, especially after a seek (from upstream), + see #412648. + +2007-05-22 15:04:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/cdparanoia/gstcdparanoiasrc.c: Repair umlaut. + Original commit message from CVS: + * ext/cdparanoia/gstcdparanoiasrc.c: + Repair umlaut. + +2007-05-22 11:40:31 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/riff/riff-media.c: Specify the full valid range for MP3 samplerates. Fixes a regression caused by extra ... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Specify the full valid range for MP3 samplerates. Fixes a regression + caused by extra header checks since the last release. + +2007-05-21 15:32:42 +0000 Mike Smith <msmith@xiph.org> + + sys/: Fix a locking-order bug I introduced with my changes the other day. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): + Fix a locking-order bug I introduced with my changes the other day. + Patch by Mike Smith. + +2007-05-21 15:24:21 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Don't look inside 0-length packets (which indicate duplicated frames) + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_handle_data_packet): + Don't look inside 0-length packets (which indicate duplicated + frames) + +2007-05-21 10:25:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + Small cleanups. + Original commit message from CVS: + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_src_read_sector): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Small cleanups. + * ext/theora/theoradec.c: (theora_dec_sink_event): + Fix typo. + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_set_gst_timestamp): + Add some FIXME + * gst/playback/gstdecodebin.c: (queue_underrun_cb): + And some debug info when a FIXME path is hit. + +2007-05-21 09:45:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Some cleanups, remove minptime property as it is now in the parent class. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_class_init), + (gst_base_rtp_audio_payload_init), + (gst_base_rtp_audio_payload_finalize), + (gst_base_rtp_audio_payload_handle_frame_based_buffer), + (gst_base_rtp_audio_payload_handle_sample_based_buffer), + (gst_base_rtp_payload_audio_handle_event): + Some cleanups, remove minptime property as it is now in the parent + class. + Override parent class event function. + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_class_init), (gst_basertppayload_init), + (gst_basertppayload_event), (gst_basertppayload_set_property), + (gst_basertppayload_get_property): + * gst-libs/gst/rtp/gstbasertppayload.h: + Add min-ptime property. + Add handle-event vmethod. Fixes #415001. + +2007-05-18 17:10:03 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update spec + Original commit message from CVS: + update spec + +2007-05-18 15:23:43 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/audio/gstbaseaudiosink.c + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_change_state): + Fix typo in comment. + * gst/playback/gstdecodebin.c (gst_decode_bin_class_init, + free_dynamics, pad_probe, close_pad_link, try_to_link_1, + get_our_ghost_pad, remove_element_chain, queue_underrun_cb, + close_link): + * gst/playback/gstplaybin.c (gst_play_bin_set_property, + gen_audio_element, remove_sinks, gst_play_bin_send_event_to_sink): + Remove trailing whitespaces in comments. + * gst/volume/Makefile.am: + Fix tabs. + +2007-05-18 15:10:08 +0000 Marc-Andre Lureau <marcandre.lureau@gmail.com> + + * ChangeLog: + * gst-libs/gst/interfaces/mixer.h: + gst-libs/gst/interfaces/mixer.h (mixer_type, option_changed, set_option, get_option, _gst_reserved): + Original commit message from CVS: + patch by: Marc-Andre Lureau <marcandre.lureau@gmail.com> + * gst-libs/gst/interfaces/mixer.h (mixer_type, option_changed, + set_option, get_option, _gst_reserved): + Revert reordering functions (keep ABI). + +2007-05-17 17:35:46 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: When we create our own window, indicate that we handle the + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_put), + (gst_ximagesink_xwindow_new), (gst_ximagesink_handle_xevents), + (gst_ximagesink_show_frame): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_xwindow_new), (gst_xvimagesink_handle_xevents), + (gst_xvimagesink_show_frame): + When we create our own window, indicate that we handle the + WM_DELETE client message from the window manager, so that it won't + kill our window (and our app) along with it. Handle ClientMessage, + post an error on the bus, and close the window. Further buffers + arriving will result in a FlowError because the window has been + destroyed. + Fixes: #393975 + Clean up the X event handling loop and make them the same for + both xvimagesink and ximagesink while I'm at it. + +2007-05-17 16:27:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin2.c: Make decodebin2 autoplug depayloaders too. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_factory_filter): + Make decodebin2 autoplug depayloaders too. + * gst/playback/gsturidecodebin.c: (source_new_pad): + Set the newly created decoder in a usable state when autoplugging a + dynamic source such as RTSP. + +2007-05-17 16:11:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreaminfo.c: Ignore video-codec tag for audio streams and ignore audio-codec tags for video streams.... + Original commit message from CVS: + * gst/playback/gststreaminfo.c: (cb_probe): + Ignore video-codec tag for audio streams and ignore audio-codec tags + for video streams. Should make codec name collection a bit more + robust against sloppy demuxers that send tag events containing both + tags down each pad. + +2007-05-17 15:22:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: Tweak the buffering thresholds a little. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (update_rates): + Tweak the buffering thresholds a little. + Update the buffer size with the previously calculate rate instead of + only when we calculate a new rate so that we get smoother buffering + updates. + * gst/playback/Makefile.am: + * gst/playback/gsturidecodebin.c: (gst_uri_decode_bin_base_init), + (gst_uri_decode_bin_class_init), (gst_uri_decode_bin_init), + (gst_uri_decode_bin_finalize), (gst_uri_decode_bin_set_property), + (gst_uri_decode_bin_get_property), (unknown_type), + (add_element_stream), (no_more_pads_full), (no_more_pads), + (source_no_more_pads), (new_decoded_pad), (array_has_value), + (gen_source_element), (has_all_raw_caps), (analyse_source), + (remove_decoders), (make_decoder), (remove_source), + (source_new_pad), (setup_source), (decoder_query_init), + (decoder_query_duration_fold), (decoder_query_duration_done), + (decoder_query_position_fold), (decoder_query_position_done), + (decoder_query_latency_fold), (decoder_query_latency_done), + (decoder_query_seeking_fold), (decoder_query_seeking_done), + (decoder_query_generic_fold), (gst_uri_decode_bin_query), + (gst_uri_decode_bin_change_state), (plugin_init): + New element that intergrates a source, optional buffering element and + decodebin. + +2007-05-17 14:17:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Bump libtheora requirement to 1.0alpha5 for the pixformat check (also has a .pc file, so we don't need ... + Original commit message from CVS: + * configure.ac: + Bump libtheora requirement to 1.0alpha5 for the pixformat check + (also has a .pc file, so we don't need the fallback check any + longer). Fixes #438840. + +2007-05-17 13:36:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstqueue2.c: fix build. + Original commit message from CVS: + * gst/playback/gstqueue2.c: (gst_queue_get_type), + (gst_queue_class_init), (gst_queue_finalize), (update_time_level), + (apply_segment), (apply_buffer), (update_buffering), + (reset_rate_timer), (update_rates), (gst_queue_locked_flush), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue), + (gst_queue_handle_sink_event), (gst_queue_is_filled), + (gst_queue_chain), (gst_queue_push_one), (gst_queue_loop), + (plugin_init): + fix build. + +2007-05-17 11:57:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: On our way to playbin2 this is the new network queue that does buffering all by itself using high and ... + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstqueue2.c: (gst_queue_get_type), + (gst_queue_class_init), (gst_queue_init), (gst_queue_finalize), + (gst_queue_getcaps), (gst_queue_bufferalloc), + (gst_queue_acceptcaps), (update_time_level), (apply_segment), + (apply_buffer), (update_buffering), (reset_rate_timer), + (update_rates), (gst_queue_locked_flush), + (gst_queue_locked_enqueue), (gst_queue_locked_dequeue), + (gst_queue_handle_sink_event), (gst_queue_is_empty), + (gst_queue_is_filled), (gst_queue_chain), (gst_queue_push_one), + (gst_queue_loop), (gst_queue_handle_src_event), + (gst_queue_handle_src_query), (gst_queue_sink_activate_push), + (gst_queue_src_activate_push), (gst_queue_change_state), + (gst_queue_set_property), (gst_queue_get_property), (plugin_init): + On our way to playbin2 this is the new network queue that does buffering + all by itself using high and low watermarks. It can also measure up and + downstream bandwidth to optimally size the queue. + +2007-05-17 11:16:14 +0000 Michael Smith <msmith@xiph.org> + + gst/: Use the segment->last_stop value to calculate the next timestamp to generate after a seek; not the segment->sta... + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_do_seek): + * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_do_seek): + Use the segment->last_stop value to calculate the next timestamp to + generate after a seek; not the segment->start value. + +2007-05-15 20:14:06 +0000 David Schleef <ds@schleef.org> + + docs/Makefile.am: Install docs even when --disable-gtk-doc is disabled. This matches the behavior of gtk+. Fixes #3... + Original commit message from CVS: + * docs/Makefile.am: Install docs even when --disable-gtk-doc + is disabled. This matches the behavior of gtk+. Fixes #349099. + +2007-05-15 17:11:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Some more chained streaming ogg timestamp fixes. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_handle_page): + Some more chained streaming ogg timestamp fixes. + +2007-05-15 16:46:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Add some FIXMEs. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_handle_page): + Add some FIXMEs. + Fix chain start/stop segment handling based on patch by + <ahalda at cs dot mcgill dot ca> see #320984. + +2007-05-15 15:33:54 +0000 Michael Smith <msmith@xiph.org> + + configure.ac: We don't require a C++ compiler. So don't require one. + Original commit message from CVS: + * configure.ac: + We don't require a C++ compiler. So don't require one. + +2007-05-15 15:29:17 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + * ChangeLog: + * ext/alsa/gstalsamixer.c: + ext/alsa/gstalsamixer.c (source, n_poll_fds, poll_fds, gst_alsa_mixer_check, gst_alsa_mixer_dispatch, gst_alsa_mixer_... + Original commit message from CVS: + * ext/alsa/gstalsamixer.c (source, n_poll_fds, poll_fds, + gst_alsa_mixer_check, gst_alsa_mixer_dispatch, + gst_alsa_mixer_finalize, gst_alsa_mixer_handle_source_callback, + gst_alsa_mixer_handle_callback, gst_alsa_mixer_elem_handle_callback, + gst_alsa_mixer_ensure_track_list, gst_alsa_mixer_update_option, + gst_alsa_mixer_update_track): + Apply some of the cleanup Tim suggested in #152864 afterwards. + +2007-05-15 14:01:26 +0000 Marc-Andre Lureau <marcandre.lureau@gmail.com> + + ext/alsa/gstalsamixer.c (main_context, GstAlsaMixerWatch, _GstAlsaMixerWatch, source, n_poll_fds, poll_fds, gst_alsa_... + Original commit message from CVS: + patch by: Marc-Andre Lureau <marcandre.lureau@gmail.com> + * ext/alsa/gstalsamixer.c (main_context, GstAlsaMixerWatch, + _GstAlsaMixerWatch, source, n_poll_fds, poll_fds, + gst_alsa_mixer_watch_funcs, gst_alsa_mixer_prepare, + gst_alsa_mixer_check, gst_alsa_mixer_dispatch, + gst_alsa_mixer_finalize, gst_alsa_mixer_find_master_mixer, + gst_alsa_mixer_handle_source_callback, + gst_alsa_mixer_handle_callback, gst_alsa_mixer_elem_handle_callback, + gst_alsa_mixer_ensure_track_list, gst_alsa_mixer_free, + gst_alsa_mixer_get_volume, gst_alsa_mixer_set_volume, + gst_alsa_mixer_set_mute, gst_alsa_mixer_set_record, + gst_alsa_mixer_get_option, gst_alsa_mixer_update_option, + gst_alsa_mixer_update_track, _gst_alsa_mixer_set_interface): + * ext/alsa/gstalsamixer.h (handle_source, interface, dir): + * ext/alsa/gstalsamixerelement.c (gst_alsa_mixer_element_details, + gst_alsa_mixer_element_interface_supported, + gst_alsa_mixer_element_finalize, gst_alsa_mixer_element_init, + gst_alsa_mixer_element_set_property, + gst_alsa_mixer_element_get_property, + gst_alsa_mixer_element_change_state): + * ext/alsa/gstalsamixertrack.c (gst_alsa_mixer_track_update): + * gst-libs/gst/interfaces/mixer.c (gst_mixer_volume_changed, + gst_mixer_option_changed): + * gst-libs/gst/interfaces/mixer.h (set_option, get_option, + volume_changed, option_changed, _gst_reserved): + Implement notification for alsamixer. Fixes #152864 + +2007-05-15 03:53:11 +0000 David Schleef <ds@schleef.org> + + gst/videotestsrc/videotestsrc.*: Add support for video/x-raw-bayer. + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + Add support for video/x-raw-bayer. + +2007-05-13 01:06:19 +0000 David Schleef <ds@schleef.org> + + sys/xvimage/xvimagesink.c: Add some sanity checking for the XVImage size returned by X. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: + Add some sanity checking for the XVImage size returned by X. + Related to #377400. + +2007-05-12 16:18:39 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Parse and use additional caps fields as described in updated application/x-rt... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), + (gst_base_rtp_depayload_set_gst_timestamp): + Parse and use additional caps fields as described in updated + application/x-rtp caps spec. + +2007-05-12 16:16:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: If there is a stream in a chain without any data packets, ignore the stream in the total lengt... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_collect_chain_info): + If there is a stream in a chain without any data packets, ignore the + stream in the total length calculations. Might be related to #436820. + +2007-05-11 17:33:43 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/typefind/gsttypefindfunctions.c: Consolidate and re-work our mpeg system stream detection to probe more packets a... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg_sys_is_valid_pack), + (mpeg_sys_is_valid_pes), (mpeg_sys_is_valid_sys), + (mpeg_sys_type_find), (mpeg_ts_type_find), (mpeg4_video_type_find), + (mpeg_video_type_find), (mpeg_video_stream_type_find), + (plugin_init): + Consolidate and re-work our mpeg system stream detection to probe + more packets and produce a higher confidence result. Fixes a + regression caused by lowering the typefind probability last year + - related to bug #397810. Remove the redundant MPEG-1 specific + typefind function, as the new one detects both MPEG-1 & MPEG-2 + happily. + Also cleanup the MPEG elementary and MPEG-TS detection functions a + little. + Tested against my media test directory, with some improvements and + no regressions. + +2007-05-10 15:28:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Connect to the new queue "pushing" signal instead of the broken "running" one. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (fill_buffer), (check_queue), + (queue_out_of_data): + Connect to the new queue "pushing" signal instead of the broken + "running" one. + +2007-05-09 21:17:40 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Move variable declaration before the first instruction. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_handle_frame_based_buffer): + Move variable declaration before the first instruction. + * gst/videotestsrc/videotestsrc.c: + Define M_PI if it's not defined yet. + * win32/common/libgstrtp.def: + Add new exported functions. + +2007-05-09 11:54:32 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: gst_pad_push_event() does not return a GstFlowReturn! + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_handle_type_packet): + gst_pad_push_event() does not return a GstFlowReturn! + +2007-05-09 11:25:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/: Some small cosmetic changes. + Original commit message from CVS: + * tests/examples/seek/scrubby.c: (stop_cb), (main): + * tests/examples/seek/seek.c: (do_seek): + Some small cosmetic changes. + +2007-05-08 19:24:01 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + * ChangeLog: + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + gst/adder/gstadder.c (gst_adder_src_event, gst_adder_collected, gst_adder_change_state): gst/adder/gstadder.h (bps, o... + Original commit message from CVS: + * gst/adder/gstadder.c (gst_adder_src_event, gst_adder_collected, + gst_adder_change_state): + * gst/adder/gstadder.h (bps, offset, collect_event, segment, + segment_pending, segment_position, segment_rate): + Handle playback-rate on adder. + +2007-05-07 11:43:31 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/: Don't push events (newsegment, tags) before initialising the decoder. + Original commit message from CVS: + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_reset), + (theora_dec_sink_event), (theora_handle_comment_packet), + (theora_handle_type_packet), (theora_dec_change_state): + Don't push events (newsegment, tags) before initialising the + decoder. + This is neccesary for seeking to work correctly in gnonlin. + +2007-05-04 13:10:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/: gst/audiotestsrc/gstaudiotestsrc.c + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst/adder/gstadder.c: + * gst/audiotestsrc/gstaudiotestsrc.c + (gst_audio_test_src_create_white_noise): + * gst/videotestsrc/gstvideotestsrc.c: + * gst/volume/gstvolume.c (VOLUME_UNITY_INT16, + VOLUME_UNITY_INT16_BIT_SHIFT, VOLUME_MAX_DOUBLE, + volume_sink_template, volume_src_template, gst_volume_init, + volume_process_double, volume_process_int16, + volume_process_int16_clamp): + Doc fixes and formatting. + +2007-05-04 12:41:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Minimal check for volume's GstController usability; also another test for #422295. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/volume.c: (GST_START_TEST), (volume_suite): + Minimal check for volume's GstController usability; also another + test for #422295. + +2007-05-04 09:06:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: Fix it so that it (a) makes sense and (b) doesn't break everything cdda-related i... + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_add_track): + Fix it so that it (a) makes sense and (b) doesn't break + everything cdda-related including the unit test. + +2007-05-04 08:46:59 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: Fix build when disabling asserts. + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_add_track): + Fix build when disabling asserts. + +2007-05-03 16:29:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/ximage/ximagesink.c: When XShm is not available, we might get row strides that are not rounded up to multiples of... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new): + When XShm is not available, we might get row strides that are not + rounded up to multiples of four; this is bad, because virtually + every RGB-processing element in GStreamer assumes rowstrides are + rounded up to multiples of four, so let's allocate at least enough + memory to avoid crashes in this case. The image will still be + displayed distorted though if this happens, so that still needs + fixing (maybe by allocating a bigger image with an 'even' width + and then clipping it appropriately when rendering - something for + Xlib aficionados in any case). + +2007-05-03 13:16:21 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: If a buffer doesn't have a timestamp, assume it's contiguous with the previous buffer, ... + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + If a buffer doesn't have a timestamp, assume it's contiguous with + the previous buffer, and synthesise timestamps appropriately. + +2007-05-03 11:24:00 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/elements/videorate.c: Set buffer timestamp to a valid value in order to test the buffer really does stay ... + Original commit message from CVS: + * tests/check/elements/videorate.c: (GST_START_TEST): + Set buffer timestamp to a valid value in order to test the buffer + really does stay in videorate. + +2007-05-03 10:47:22 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/videorate/gstvideorate.c: There is no sensible way to handle incoming buffers which don't have a valid timestamp.... + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_chain): + There is no sensible way to handle incoming buffers which don't have a + valid timestamp. We therefore discard them and wait for the next one. + +2007-05-01 18:45:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Better error message for text files. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (type_found), (plugin_init): + * gst/playback/gstdecodebin2.c: (plugin_init): + Better error message for text files. + +2007-04-29 14:38:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.c: Fix offset bug in generation RR packets. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_packet_add_rb): + Fix offset bug in generation RR packets. + +2007-04-27 15:33:46 +0000 Julien Moutte <julien@moutte.net> + + ext/theora/theoradec.c: Calculate buffer duration correctly to generate a perfect stream (#433888). + Original commit message from CVS: + 2007-04-27 Julien MOUTTE <julien@moutte.net> + * ext/theora/theoradec.c: (_theora_granule_time), + (theora_dec_push_forward), (theora_handle_data_packet), + (theora_dec_decode_buffer): Calculate buffer duration correctly + to generate a perfect stream (#433888). + * gst/audioresample/gstaudioresample.c: + (audioresample_check_discont): Glib provides ABS. + +2007-04-27 15:01:40 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.*: Fix RB block parsing and writing. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_packet_get_rb), + (gst_rtcp_packet_add_rb), (gst_rtcp_packet_sdes_add_item), + (gst_rtcp_packet_sdes_add_entry), (gst_rtcp_packet_bye_add_ssrc), + (gst_rtcp_packet_bye_add_ssrcs), (get_reason_offset), + (gst_rtcp_packet_bye_set_reason): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Fix RB block parsing and writing. + Add support for constructing BYE packets. + +2007-04-25 08:54:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + When posting a warning message because samples were dropped, post something more intelligible than he default error m... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: (_do_init), + (gst_base_audio_src_create): + * po/POTFILES.in: + When posting a warning message because samples were dropped, post + something more intelligible than he default error message for clock + errors which is just confusing in this context (#432984). + +2007-04-25 08:10:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtcpbuffer.*: Implement code to write SR, RR and SDES packets. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtcpbuffer.c: (gst_rtcp_buffer_new), + (gst_rtcp_buffer_end), (gst_rtcp_buffer_get_packet_count), + (read_packet_header), (gst_rtcp_packet_move_to_next), + (gst_rtcp_buffer_add_packet), (gst_rtcp_packet_sr_set_sender_info), + (gst_rtcp_packet_rr_set_ssrc), (gst_rtcp_packet_add_rb), + (gst_rtcp_packet_sdes_get_item_count), + (gst_rtcp_packet_sdes_first_item), + (gst_rtcp_packet_sdes_next_item), (gst_rtcp_packet_sdes_get_ssrc), + (gst_rtcp_packet_sdes_first_entry), + (gst_rtcp_packet_sdes_next_entry), + (gst_rtcp_packet_sdes_get_entry), (gst_rtcp_packet_sdes_add_item), + (gst_rtcp_packet_sdes_add_entry): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Implement code to write SR, RR and SDES packets. + +2007-04-24 20:45:24 +0000 Christian Kirbach <Christian.Kirbach@googlemail.com> + + sys/ximage/ximagesink.c: Fix build if XShm is not available (#432362). + Original commit message from CVS: + Patch by: Christian Kirbach <Christian dot Kirbach at googlemail com> + * sys/ximage/ximagesink.c: + Fix build if XShm is not available (#432362). + +2007-04-24 18:58:25 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/gstaudioconvert.c: Initalize the AudioConvertCtx with zeroes, otherwise it will contain pointers to ... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init): + Initalize the AudioConvertCtx with zeroes, otherwise it will contain + pointers to random memory which are passed to g_free() when + audio_convert_prepare_context() is called the first time. + +2007-04-24 15:00:07 +0000 Dan Williams <dcbw@redhat.com> + + gst/videorate/gstvideorate.c: Don't leak incoming buffer if gst_pad_push() returns a non-OK flow. Fixes #432755. + Original commit message from CVS: + Patch by: Dan Williams <dcbw redhat com> + * gst/videorate/gstvideorate.c: (gst_video_rate_chain): + Don't leak incoming buffer if gst_pad_push() returns a + non-OK flow. Fixes #432755. + * tests/check/elements/videorate.c: (GST_START_TEST), + (videorate_suite): + Unit test for the above by Yours Truly. + +2007-04-23 20:04:28 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/gstadder.c: Fix non-flushing segmented seeks, Fixes #340060 for me + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_setcaps), (gst_adder_src_event), + (gst_adder_sink_event), (gst_adder_collected): + Fix non-flushing segmented seeks, Fixes #340060 for me + +2007-04-21 15:29:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery: add API keyword + Original commit message from CVS: + ChangeLog surgery: add API keyword + +2007-04-21 15:25:22 +0000 Olivier Crete <tester@tester.ca> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Chain up to parent class in dispose function; get rid of unnecessary 'dipo... + Original commit message from CVS: + Patch by: Olivier Crete <tester at tester ca> + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_class_init), + (gst_base_rtp_audio_payload_init), + (gst_base_rtp_audio_payload_dispose): + Chain up to parent class in dispose function; get rid of + unnecessary 'diposed' flag in private structure (#415001). + +2007-04-21 15:10:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + Some minor docs fixes and additions; also add missing 'Since' bits. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs.types: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_class_init): + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertppayload.c: + Some minor docs fixes and additions; also add missing 'Since' bits. + +2007-04-21 14:40:45 +0000 Zeeshan Ali <zeenix@gmail.com> + + gst-libs/gst/rtp/gstbasertpaudiopayload.*: The recently-added gst_base_rtp_audio_payload_push() should take an object... + Original commit message from CVS: + Patch by: Zeeshan Ali <zeenix gmail com> + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_handle_frame_based_buffer), + (gst_base_rtp_audio_payload_handle_sample_based_buffer), + (gst_base_rtp_audio_payload_push): + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + The recently-added gst_base_rtp_audio_payload_push() should take an + object of type GstBaseRTPAudioPayload as first argument (#431672). + +2007-04-21 14:14:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioresample/gstaudioresample.c: Make more functions static, just because we can. + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + Make more functions static, just because we can. + +2007-04-21 13:54:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/audioresample.c: Add unit test for audioresample shutdown crasher (#420106). + Original commit message from CVS: + * tests/check/elements/audioresample.c: + Add unit test for audioresample shutdown crasher (#420106). + +2007-04-20 10:42:24 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/subparse/: Use GST_DISABLE_XML here + Original commit message from CVS: + * gst/subparse/gstsubparse.c: + * gst/subparse/samiparse.c: + Use GST_DISABLE_XML here + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_xwindow_new), (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_navigation_send_event): + * sys/xvimage/xvimagesink.h: + Include stdlib.h when using atoi. + * tests/check/elements/playbin.c: (playbin_suite): + Use GST_DISABLE_REGISTRY here + +2007-04-19 16:58:53 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/: Track initialisation state; don't try to use encoder state if we're not initialised (it'll segfault). + Original commit message from CVS: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: (theora_enc_sink_setcaps), + (theora_enc_sink_event), (theora_enc_change_state): + Track initialisation state; don't try to use encoder state if we're + not initialised (it'll segfault). + +2007-04-18 11:06:42 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/pipelines/.cvsignore: Fix build. + Original commit message from CVS: + * tests/check/pipelines/.cvsignore: + Fix build. + +2007-04-17 10:56:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/app/Makefile.am: Fix CFLAGS and hopefully #430594. + Original commit message from CVS: + * gst/app/Makefile.am: + Fix CFLAGS and hopefully #430594. + +2007-04-17 02:53:16 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Allow random depths between 1 and 32 instead of only multiplies of 8. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Allow random depths between 1 and 32 instead of only multiplies of 8. + +2007-04-17 02:04:21 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Set the maximum number of channels for PCM and float in the correct place to have it ... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Set the maximum number of channels for PCM and float in the correct + place to have it also used when creating the template caps. + +2007-04-17 01:56:07 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Correctly support 4, 6 and 8 channels with normal PCM and float wav files. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Correctly support 4, 6 and 8 channels with normal PCM and float + wav files. + Fix the depth and signedness calculation in extensible wav files and + also handle 1, 2, 4, 6, 8 channels here when a file without channel + mask is found. + Add support for float, alaw and mulaw in extensible wav files. + This allows correct playback of all but 5 files from + http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/Samples.html + (gst_riff_create_audio_template_caps): + Add voxware and float formats to the template caps. + +2007-04-16 22:20:03 +0000 Vincent Torri <vtorri@univ-evry.fr> + + ext/pango/gstclockoverlay.c: Fix unused variable warning if HAVE_LOCALTIME_R is undefinied + Original commit message from CVS: + Patch by: Vincent Torri <vtorri at univ-evry dot fr> + * ext/pango/gstclockoverlay.c: (gst_clock_overlay_render_time): + Fix unused variable warning if HAVE_LOCALTIME_R is undefinied + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + * gst/audioresample/gstaudioresample.c: (audioresample_do_output): + Use the correct format strings for integer formats. + +2007-04-16 21:44:34 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst-plugins-base.doap: + fix release date + Original commit message from CVS: + fix release date + +2007-04-16 21:42:13 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst-plugins-base.doap: + fix release date + Original commit message from CVS: + fix release date + +2007-04-15 14:35:53 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/theora/theoraenc.c (theora_buffer_from_packet, theora_enc_chain): Don't use pad_alloc_buffer_and_set_caps to crea... + Original commit message from CVS: + * ext/theora/theoraenc.c (theora_buffer_from_packet, theora_enc_chain): + Don't use pad_alloc_buffer_and_set_caps to create a small header + packet, or, worse, to create a big temporary video buffer using the + src pad. + +2007-04-14 12:34:55 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/gdp/gstgdppay.c (gst_gdp_pay_chain): tests/check/pipelines/streamheader.c (tag_event_probe_cb, + Original commit message from CVS: + * gst/gdp/gstgdppay.c (gst_gdp_pay_chain): + * tests/check/pipelines/streamheader.c (tag_event_probe_cb, + GST_START_TEST, buffer_probe_cb, GST_START_TEST): + Fix a bug where serialized IN_CAPS buffers needed to be set IN_CAPS. + +2007-04-13 22:10:58 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + add debug + Original commit message from CVS: + add debug + +2007-04-13 21:55:31 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * tests/check/pipelines/streamheader.c: + tests/check/pipelines/streamheader.c (tag_event_probe_cb, + Original commit message from CVS: + * tests/check/pipelines/streamheader.c (tag_event_probe_cb, + GST_START_TEST, n_in_caps, buffer_probe_cb, GST_START_TEST, + streamheader_suite): + Add another test set up for failure + +2007-04-13 21:09:04 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + * gst/gdp/gstgdpdepay.c: + debug changes + Original commit message from CVS: + debug changes + +2007-04-13 21:08:11 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/Makefile.am: tests/check/pipelines/streamheader.c (n_tags, tag_event_probe_cb, + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/pipelines/streamheader.c (n_tags, tag_event_probe_cb, + GST_START_TEST, streamheader_suite, main): + Add a test for the streamheader bug Wim fixed. + +2007-04-13 11:42:34 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/theora/theoradec.c: Fix misleading comment. + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_sink_event): + Fix misleading comment. + +2007-04-13 06:17:45 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-media.c: More sanity checks for the header fields. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + More sanity checks for the header fields. + +2007-04-12 16:36:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/tags.c: Try encodings from all environment variables, not just those in the first environment variab... + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (gst_tag_freeform_string_to_utf8): + Try encodings from all environment variables, not just those in the + first environment variable that is set. + +2007-04-12 15:00:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videorate/gstvideorate.c: Add some debug. + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_setcaps), + (gst_video_rate_chain): + Add some debug. + * tests/check/elements/videorate.c: (GST_START_TEST), + (videorate_suite): + Added check for videorate changing caps handling. Closes #421834. + +2007-04-12 12:57:33 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisdec.c: Use scale functions to avoid overflow when calculating duration of vorbis buffers. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + Use scale functions to avoid overflow when calculating duration of + vorbis buffers. + +2007-04-12 12:19:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add gst_tag_freeform_string_to_utf8() (#405072). + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: (gst_tag_freeform_string_to_utf8): + API: add gst_tag_freeform_string_to_utf8() (#405072). + * gst-libs/gst/tag/gstid3tag.c: (gst_tag_extract_id3v1_string): + Use gst_tag_freeform_string_to_utf8() here. + +2007-04-12 10:38:03 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + log tweaking + Original commit message from CVS: + log tweaking + +2007-04-12 10:03:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/gdp/gstgdppay.c: Make sure we set the IN_CAPS flag correctly. + Original commit message from CVS: + * gst/gdp/gstgdppay.c: (gst_gdp_pay_chain), + (gst_gdp_pay_sink_event): + Make sure we set the IN_CAPS flag correctly. + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_render): + Get the IN_CAPS flag before we call functions that mess with the flags. + +2007-04-10 20:37:05 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * gst/gdp/gstgdppay.c: + gst/gdp/gstgdppay.c (gst_gdp_pay_reset_streamheader, gst_gdp_pay_chain, gst_gdp_pay_sink_event): + Original commit message from CVS: + * gst/gdp/gstgdppay.c (gst_gdp_pay_reset_streamheader, + gst_gdp_pay_chain, gst_gdp_pay_sink_event): + Only stamp buffers with offset/offset_end right before they get + pushed. This ensures offset continuity, which was not the case + before as shown by + gst-launch -v -m audiotestsrc num-buffers=10 ! audioconvert ! vorbisenc ! gdppay ! identity check-imperfect-offset=TRUE ! fakesink silent=TRUE + +2007-04-10 20:25:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + adding debugging + Original commit message from CVS: + adding debugging + +2007-04-10 11:23:18 +0000 Christian Schaller <uraeus@gnome.org> + + * common: + * gst-plugins-base.spec.in: + update spec file for RTP changes + Original commit message from CVS: + update spec file for RTP changes + +2007-04-06 12:58:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin.c: Activate sync in playbin, we are ready to handle it for live streams. + Original commit message from CVS: + * gst/playback/gstplaybin.c: (add_sink), + (gst_play_bin_change_state): + Activate sync in playbin, we are ready to handle it for live streams. + +2007-04-06 09:56:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/playbin.c: Add small test for stream-info-value-array code paths. + Original commit message from CVS: + * tests/check/elements/playbin.c: + (test_sink_usage_video_only_stream), (playbin_suite): + Add small test for stream-info-value-array code paths. + +2007-04-05 15:44:40 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Don't try to create invalid calibration parameters by making the internal time... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_skew_slaving): + Don't try to create invalid calibration parameters by making the + internal time go backwards, instead make external time go forward. + +2007-04-05 10:27:06 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + gst/playback/gstplaybasebin.c: Fix leak in add_stream(), when g_value_set_object() increases the refcount of streamin... + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * gst/playback/gstplaybasebin.c: (add_stream): + Fix leak in add_stream(), when g_value_set_object() increases the + refcount of streaminfo object. Fixes #426250. + +2007-04-04 02:45:03 +0000 David Schleef <ds@schleef.org> + + gst/videotestsrc/: Add a test pattern called "circular", which has concentric rings with varying radial frequency. T... + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + Add a test pattern called "circular", which has concentric + rings with varying radial frequency. The main purpose of this + pattern is to test fidelity loss in a filter or scaler element. + Notably, this pattern is scale invariant, and is optimally viewed + with a width (and height) of 400. + +2007-04-03 11:10:52 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + gst/playback/gstdecodebin2.c: Decodebin2 doesn't unref pads it obtains in some occasions: + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * gst/playback/gstdecodebin2.c: (connect_pad), (expose_pad), + (deactivate_free_recursive): + Decodebin2 doesn't unref pads it obtains in some occasions: + - multiqueue src pads, when either connecting further or exposing + - sink pads of new autoplugged elements + - peer pads when recursively freeing elements + Fixes #425455. + +2007-03-30 17:05:23 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: Add audio/x-raw-float support, now that audioconvert support non-native endianness fl... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Add audio/x-raw-float support, now that audioconvert support + non-native endianness floats. + +2007-03-30 15:00:49 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/libs/gst-plugins-base-libs-docs.sgml: gstreamer-plugins-base.pc doesn't exist, it's gstreamer-plugins-base-0.10.pc. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + gstreamer-plugins-base.pc doesn't exist, it's + gstreamer-plugins-base-0.10.pc. + +2007-03-29 18:42:34 +0000 René Stadler <mail@renestadler.de> + + with some minor changes + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler dot de> + with some minor changes + * gst-libs/gst/floatcast/floatcast.h: + Use more efficient float endianness conversion functions that don't + involve 2 function calls per value. + * gst/audioconvert/audioconvert.c: (audio_convert_get_func_index), + (check_default), (audio_convert_prepare_context): + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_parse_caps), (make_lossless_changes): + Support non-native endianness floats as input and output. + Fixes #339838. + * tests/check/elements/audioconvert.c: (verify_convert), + (GST_START_TEST): + Add unit tests for the non-native endianness float conversions. + +2007-03-29 16:23:53 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Add Private structure. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_base_init), + (gst_base_rtp_depayload_class_init), (gst_base_rtp_depayload_init), + (gst_base_rtp_depayload_setcaps), (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_change_state), + (gst_base_rtp_depayload_set_property), + (gst_base_rtp_depayload_get_property): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Add Private structure. + Bring element code to 2007. + Parse clock-base caps param and use it when generating the + newsegment. + Reset variables before going to PAUSED. + Fix some docs. + +2007-03-29 16:20:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + Add RTCP docs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_get_adapter): + Add RTCP docs. + Fix some more docs. + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtp/gstrtcpbuffer.c: + (gst_rtcp_buffer_new_take_data), (gst_rtcp_buffer_new_copy_data), + (gst_rtcp_buffer_validate_data), (gst_rtcp_buffer_validate), + (gst_rtcp_buffer_get_packet_count), (read_packet_header), + (gst_rtcp_buffer_get_first_packet), (gst_rtcp_packet_move_to_next), + (gst_rtcp_buffer_add_packet), (gst_rtcp_packet_remove), + (gst_rtcp_packet_get_padding), (gst_rtcp_packet_get_type), + (gst_rtcp_packet_get_count), (gst_rtcp_packet_get_length), + (gst_rtcp_packet_sr_get_sender_info), + (gst_rtcp_packet_sr_set_sender_info), + (gst_rtcp_packet_rr_get_ssrc), (gst_rtcp_packet_rr_set_ssrc), + (gst_rtcp_packet_get_rb_count), (gst_rtcp_packet_get_rb), + (gst_rtcp_packet_add_rb), (gst_rtcp_packet_set_rb), + (gst_rtcp_packet_sdes_get_chunk_count), + (gst_rtcp_packet_sdes_first_chunk), + (gst_rtcp_packet_sdes_next_chunk), (gst_rtcp_packet_sdes_get_ssrc), + (gst_rtcp_packet_sdes_first_item), + (gst_rtcp_packet_sdes_next_item), (gst_rtcp_packet_sdes_get_item), + (gst_rtcp_packet_bye_get_ssrc_count), + (gst_rtcp_packet_bye_get_nth_ssrc), (gst_rtcp_packet_bye_add_ssrc), + (gst_rtcp_packet_bye_add_ssrcs), (get_reason_offset), + (gst_rtcp_packet_bye_get_reason_len), + (gst_rtcp_packet_bye_get_reason), (gst_rtcp_packet_bye_set_reason): + * gst-libs/gst/rtp/gstrtcpbuffer.h: + Add new helper object for parsing and creating RTCP messages. + +2007-03-29 12:07:02 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst-libs/gst/riff/riff-media.c: PCM samples with width=8 must be always unsigned, no matter what depth they have. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + PCM samples with width=8 must be always unsigned, no matter what + depth they have. + +2007-03-29 11:24:47 +0000 Andy Wingo <wingo@pobox.com> + + gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): Make perfect offsets also, not just timestamps. + Original commit message from CVS: + 2007-03-29 Andy Wingo <wingo@pobox.com> + * gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): Make + perfect offsets also, not just timestamps. + * tests/check/elements/videorate.c (test_more): Test that given + any incoming offsets, that videorate produces perfect offsets. + +2007-03-29 10:19:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-ids.h: Add some more RIFF formats. + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + Add some more RIFF formats. + +2007-03-29 10:17:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.*: Fix fixed payload names and docs. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.c: + (gst_rtp_buffer_default_clock_rate): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Fix fixed payload names and docs. + Added method to get the default clock rates of fixed payload types. + API: GstRTPBuffer::gst_rtp_buffer_default_clock_rate() + +2007-03-28 15:24:40 +0000 Zaheer Abbas Merali <zaheerabbas@merali.org> + + tests/check/pipelines/.cvsignore: Add new vorbisdec test to cvsignore. + Original commit message from CVS: + * tests/check/pipelines/.cvsignore: + Add new vorbisdec test to cvsignore. + +2007-03-28 14:50:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.*: Store private stuff in GstBaseAudioSinkPrivate. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: (slave_method_get_type), + (gst_base_audio_sink_class_init), (gst_base_audio_sink_init), + (gst_base_audio_sink_query), (gst_base_audio_sink_get_time), + (gst_base_audio_sink_set_property), + (gst_base_audio_sink_get_property), (gst_base_audio_sink_event), + (clock_convert_external), (gst_base_audio_sink_resample_slaving), + (gst_base_audio_sink_skew_slaving), + (gst_base_audio_sink_handle_slaving), (gst_base_audio_sink_render), + (gst_base_audio_sink_async_play): + * gst-libs/gst/audio/gstbaseaudiosink.h: + Store private stuff in GstBaseAudioSinkPrivate. + Add configurable clock slaving modes property. + API:: GstBaseAudioSink::slave-method property + Some more latency reporting tweaks. + Added skew based clock slaving correction and make it the default until + the resampling method is more robust. + +2007-03-27 12:44:14 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + gst/audioconvert/audioconvert.c: Add docs to the integer pack functions and implement proper rounding. Before we had ... + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: + Add docs to the integer pack functions and implement proper + rounding. Before we had rounding towards negative infinity, i.e. + always the smaller number was taken. Now we use natural rounding, + i.e. rounding to the nearest integer and to the one with the largest + absolute value for X.5. The old rounding introduced some minor + distortions. Fixes #420079 + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Fix one unit test that assumed the old rounding and added unit tests + for checking signed/unsigned int16 <-> signed/unsigned int16 with + depth 8, one for signed int16 <-> unsigned int16 and one for the new + rounding from signed int32 to signed/unsigned int16. + +2007-03-27 11:31:17 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/gstaudioconvert.c: Fix typo in debug line introduced recently, as pointed out on irc. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (strip_width_64), + (gst_audio_convert_transform_caps): + Fix typo in debug line introduced recently, as pointed out on irc. + +2007-03-27 10:17:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + Make sure we parse floating-point numbers in vorbis comments correctly with either '.' or ',' as separator, no matter... + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + * tests/check/libs/tag.c: (GST_START_TEST): + Make sure we parse floating-point numbers in vorbis comments + correctly with either '.' or ',' as separator, no matter what + the current locale is. Add unit test for this too. + +2007-03-27 09:37:42 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/pipelines/vorbisdec.c: + commit new file + Original commit message from CVS: + commit new file + +2007-03-26 22:38:19 +0000 René Stadler <mail@renestadler.de> + + gst-libs/gst/tag/gstvorbistag.c: When writing out floating-point numbers to vorbis comment tags, always use the same ... + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler de> + * gst-libs/gst/tag/gstvorbistag.c: (gst_tag_to_vorbis_comments): + When writing out floating-point numbers to vorbis comment tags, always + use the same character as separator no matter what the current locale is + (fixes #423051). + * tests/check/libs/tag.c: (GST_START_TEST): + Add unit tests for replaygain tags in vorbis comments (closes #423055). + +2007-03-26 20:56:35 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/vorbis/vorbisdec.c (vorbis_dec_push_forward, vorbis_handle_data_packet): + Original commit message from CVS: + * ext/vorbis/vorbisdec.c (vorbis_dec_push_forward, + vorbis_handle_data_packet): + Correctly set DURATION to generate a timestamp-continuous stream. + One bug left at the end; see + ihttp://bugzilla.gnome.org/show_bug.cgi?id=423086 + * tests/check/Makefile.am: + * tests/check/pipelines/vorbisenc.c (GST_START_TEST): + Add a test to check this. Without the above patch this test fails. + +2007-03-26 11:44:07 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/rtp/Makefile.am: The base audio payloader uses GstAdapter - we need GST_BASE_LIBS. + Original commit message from CVS: + * gst-libs/gst/rtp/Makefile.am: + The base audio payloader uses GstAdapter - we need GST_BASE_LIBS. + +2007-03-23 15:43:24 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update spec file + Original commit message from CVS: + update spec file + +2007-03-23 12:32:33 +0000 Michael Smith <msmith@xiph.org> + + gst/videorate/gstvideorate.c: If videorate changes caps, we can no longer use the old buffer (which may have a differ... + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_setcaps), + (gst_video_rate_reset), (gst_video_rate_chain): + If videorate changes caps, we can no longer use the old buffer + (which may have a different size, incompatible with our caps). + So don't do that; just duplicate the new frame more times. + +2007-03-22 17:43:52 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybin.c: Remove playbin's override of the set_clock vmethod. It's irrelevant after Wim's commit on ... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init): + Remove playbin's override of the set_clock vmethod. It's irrelevant + after Wim's commit on the 19th. + +2007-03-22 14:37:08 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst-libs/gst/app/Makefile.am: Use GST_ALL_LDFLAGS, which actually exists, but maybe David can confirm that was what h... + Original commit message from CVS: + * gst-libs/gst/app/Makefile.am: + Use GST_ALL_LDFLAGS, which actually exists, but maybe David + can confirm that was what he wanted. + +2007-03-22 09:26:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/gnomevfs/gstgnomevfssrc.*: Don't cache file sizes. Fixes #341078. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_get_size), + (gst_gnome_vfs_src_start), (gst_gnome_vfs_src_stop): + * ext/gnomevfs/gstgnomevfssrc.h: + Don't cache file sizes. Fixes #341078. + +2007-03-21 11:03:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Use GST_PTR_FORMAT to log caps. + Original commit message from CVS: + * gst/playback/gstplaybin.c: (add_sink): + Use GST_PTR_FORMAT to log caps. + +2007-03-21 10:23:11 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: Special-case some more colour names that pango doesn't handle by default. Fixes #420578. + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/subparse/samiparse.c: (handle_start_font): + Special-case some more colour names that pango doesn't handle by + default. Fixes #420578. + +2007-03-20 11:49:55 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.c: If we get a zero-sized input buffer, don't pass it to libvorbis, as that marks EOS internally... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_chain): + If we get a zero-sized input buffer, don't pass it to libvorbis, as + that marks EOS internally. After that, libvorbis will buffer all + input data, and encode none of it, eventually leading to memory + exhaustion. + +2007-03-19 10:52:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Don't post STATE_DIRTY anymore. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (remove_fakesink): + Don't post STATE_DIRTY anymore. + * gst/playback/gstplaybin.c: (add_sink), (gst_play_bin_send_event), + (gst_play_bin_change_state): + Remove stream_time reset in seek handling, core does that now. + Disable clocking for live pipelines by forcing a NULL clock to the + complete pipeline, core is too smart now for our previous hack. + We can always autoplug in PAUSED now. + +2007-03-18 03:14:01 +0000 David Schleef <ds@schleef.org> + + REQUIREMENTS: Update this file, change the formatting to make it more consistent, plus more machine readable. + Original commit message from CVS: + * REQUIREMENTS: Update this file, change the formatting to make + it more consistent, plus more machine readable. + +2007-03-16 17:29:09 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/gstaudioconvert.c: Previous fix was too simplistic, and broke the tests. Use a better approach; only... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes), + (strip_width_64), (append_with_other_format): + Previous fix was too simplistic, and broke the tests. Use a better + approach; only strip 64 from widths for integer audio. + +2007-03-16 16:42:23 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/gstaudioconvert.c: We don't support 64 bit integer audio, so don't try to claim we can. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes), + (gst_audio_convert_transform_caps): + We don't support 64 bit integer audio, so don't try to claim we can. + Stops us producing caps don't match our template caps. + Update comments. + +2007-03-15 10:52:21 +0000 Michael Smith <msmith@xiph.org> + + gst/audioresample/gstaudioresample.c: Don't trigger discontinuities for very small imperfections; a filter flush will... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + (audioresample_check_discont), (audioresample_transform): + Don't trigger discontinuities for very small imperfections; a filter + flush will sound bad, and many plugins have rounding errors leading + to these. + +2007-03-14 21:11:18 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpaudiopayload.*: olivier.crete@collabora.co.uk. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + Add min-ptime property to RTP base audio payloader. Patch by + olivier.crete@collabora.co.uk. + Fixes #415001 + Indentation/whitespace/documentation fixes. + +2007-03-14 17:16:30 +0000 Julien Moutte <julien@moutte.net> + + gst/audioresample/gstaudioresample.c: Handle discontinuous streams. + Original commit message from CVS: + 2007-03-14 Julien MOUTTE <julien@moutte.net> + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init), + (audioresample_transform_size), (audioresample_do_output), + (audioresample_transform), (audioresample_pushthrough): Handle + discontinuous streams. + * gst/audioresample/gstaudioresample.h: + * tests/check/elements/audioresample.c: + (test_discont_stream_instance), (GST_START_TEST), + (audioresample_suite): Add a test for discontinuous streams. + * win32/common/config.h: Updated. + +2007-03-14 15:16:23 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + po/: Update translations from translation project. + Original commit message from CVS: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update translations from translation project. + +2007-03-14 15:05:32 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/gstgdpdepay.c: + add buffer logging + Original commit message from CVS: + add buffer logging + +2007-03-14 14:48:12 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/audioresample/: Since I really am not interested in a debug line for each sample being processed, move the librar... + Original commit message from CVS: + * gst/audioresample/debug.h: + * gst/audioresample/resample.c: (resample_init): + Since I really am not interested in a debug line for each sample + being processed, move the library's debugging to its own category, + libaudioresample + +2007-03-14 14:09:21 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/audioresample/gstaudioresample.c: + add debugging and reformat docs + Original commit message from CVS: + add debugging and reformat docs + +2007-03-12 23:29:07 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Since the plugin doesn't support anything other than 4:2:0 right now, post an error and fail ... + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_handle_type_packet): + Since the plugin doesn't support anything other than 4:2:0 right + now, post an error and fail if we get something else. Won't matter + until libtheora supports the other pixel formats, but hopefully + that'll be soon... + +2007-03-12 15:50:35 +0000 Alex Lancaster <alexlan@fedoraproject.org> + + * ChangeLog: + I'm too lazy to comment this + Original commit message from CVS: + Mention Patch by: Alex Lancaster in a recent commit. + +2007-03-12 11:47:42 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + examples/app/.cvsignore: The buildbot demands .cvsignore files, and I comply. + Original commit message from CVS: + * examples/app/.cvsignore: + The buildbot demands .cvsignore files, and I comply. + +2007-03-11 00:48:26 +0000 David Schleef <ds@schleef.org> + + Add appsrc/appsink example. + Original commit message from CVS: + * configure.ac: + * examples/Makefile.am: + * examples/app/Makefile.am: + * examples/app/appsrc_ex.c: + Add appsrc/appsink example. + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/app/gstapp.c: + * gst-libs/gst/app/gstappsink.c: + * gst-libs/gst/app/gstappsink.h: + * gst/app/gstapp.c: + Add appsink. + +2007-03-10 15:59:33 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/audio/gstbaseaudiosink.c: Use gst_guint64_to_gdouble for conversion. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c:(gst_base_audio_sink_render): + Use gst_guint64_to_gdouble for conversion. + * win32/MANIFEST: + Add new files to the win32 MANIFEST. + * win32/common/libgstaudio.def: + * win32/common/libgstpbutils.def: + Add new exported functions. + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstdecodebin.dsp: + * win32/vs6/libgstplaybin.dsp: + Change the link to libgstpbutils.lib. + * win32/vs6/libgstdecodebin2.dsp: + Add a new project for decodebin2. + * win32/vs6/libgstpbutils.dsp: + Add a new project for pbutils. + +2007-03-10 12:18:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Also accept partial dates with only year and month, like 1999-12-00 (fixes #410396 e... + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + Also accept partial dates with only year and month, + like 1999-12-00 (fixes #410396 even more). + * tests/check/libs/tag.c: (GST_START_TEST): + Add unit test for the above. + +2007-03-10 11:21:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/subparse.c: Add unit test for MPL2 subtitle format (#413799). + Original commit message from CVS: + * tests/check/elements/subparse.c: (GST_START_TEST), + (subparse_suite): + Add unit test for MPL2 subtitle format (#413799). + +2007-03-10 11:17:52 +0000 Kamil Pawlowski <kamilpe@gmail.com> + + gst/subparse/: Add support for MPL2 subtitle format (#413799). + Original commit message from CVS: + Patch by: Kamil Pawlowski <kamilpe gmail com> + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect), + (gst_sub_parse_format_autodetect), (gst_sub_parse_sink_event), + (gst_subparse_type_find): + * gst/subparse/gstsubparse.h: + * gst/subparse/mpl2parse.c: (mpl2_parse_line), (parse_mpl2): + * gst/subparse/mpl2parse.h: + Add support for MPL2 subtitle format (#413799). + +2007-03-09 17:33:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: We require core CVS for the new buffer metadata copy functions. + Original commit message from CVS: + * configure.ac: + We require core CVS for the new buffer metadata copy functions. + +2007-03-09 16:51:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/tag/gstid3tag.c: Add read support for GST_TAG_MUSICBRAINZ_SORTNAME (TSOP) tag. + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Add read support for GST_TAG_MUSICBRAINZ_SORTNAME (TSOP) tag. + Fixes #414496. + +2007-03-09 16:46:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: Improve adapter usage and comments. + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_sink_setcaps), + (gst_vis_src_negotiate), (get_buffer), (gst_visual_chain): + Improve adapter usage and comments. + +2007-03-09 16:38:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + Use new metadata copy function. + Original commit message from CVS: + * ext/pango/gsttextrender.c: (gst_text_render_chain): + * ext/vorbis/vorbistag.c: (gst_vorbis_tag_parse_packet): + * gst-libs/gst/netbuffer/gstnetbuffer.c: (gst_netbuffer_copy): + Use new metadata copy function. + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_transform): + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform): + Basetransform copied the metadata for us. + +2007-03-09 16:28:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Some more logging. Only accept newsegment events in TIME format and send a WARNING messag... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_text_event), + (gst_text_overlay_video_event): + Some more logging. Only accept newsegment events in TIME format and + send a WARNING message if they are not in TIME format. + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (gst_sub_parse_init), (gst_sub_parse_src_event), (handle_buffer), + (gst_sub_parse_chain), (gst_sub_parse_sink_event): + * gst/subparse/gstsubparse.h: + No need to allocate GstSegment structure dynamically, just put it + into the instance structure; ignore newsegment events in BYTE + format and in particular don't let it overwrite our saved TIME + segment from the last seek. + +2007-03-09 13:05:04 +0000 Michael Smith <msmith@xiph.org> + + gst/typefind/gsttypefindfunctions.c: Replace AC3 typefinder with one that isn't terrible, and actually works usefully. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (ac3_type_find): + Replace AC3 typefinder with one that isn't terrible, and actually + works usefully. + +2007-03-09 12:22:53 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/audioconvert/gstaudioconvert.c: fix error category and translatable string + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_transform): + fix error category and translatable string + +2007-03-09 11:23:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + pkgconfig/: Fix up utils => pbutils here too. + Original commit message from CVS: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + Fix up utils => pbutils here too. + +2007-03-09 10:49:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Break out of loop in chain function as soon as possible if we get a non-OK flow return. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (handle_buffer): + Break out of loop in chain function as soon as possible if we get + a non-OK flow return. + +2007-03-08 18:26:07 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/elements/alsa.c: Unref the mixer if the state change fails too (if the alsa devices are inaccessible, for... + Original commit message from CVS: + * tests/check/elements/alsa.c: (GST_START_TEST): + Unref the mixer if the state change fails too (if the + alsa devices are inaccessible, for example) + +2007-03-08 17:49:46 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/Makefile.am: Don't test libvisual elements in the states check, because libvisual seems to leak internally. + Original commit message from CVS: + * tests/check/Makefile.am: + Don't test libvisual elements in the states check, because libvisual + seems to leak internally. + Re-enable the alsa and states tests now that there's new suppressions + in gst.supp. + * tests/check/elements/alsa.c: (GST_START_TEST): + Don't leak the alsamixer we instantiated. + +2007-03-08 15:22:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: Move some cleanup stuff from the state change handler into a _reset() function that can be called from _finaliz... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_clear), + (gst_ximagesink_change_state), (gst_ximagesink_reset), + (gst_ximagesink_finalize): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_change_state), + (gst_xvimagesink_reset), (gst_xvimagesink_finalize): + Move some cleanup stuff from the state change handler into a _reset() + function that can be called from _finalize(). This ensures that things + get freed even if (for some reason) the NULL->READY state transition + fails in the parent class. + Even if a parent state change fails, process our downward state change + logic instead of bailing out early. + Free the correct xcontext pointer in ximagesink's xcontext_clear. + +2007-03-08 12:53:51 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/alsa/gstalsasink.c: Extra log line. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_open): + Extra log line. + * ext/pango/gstclockoverlay.c: (gst_clock_overlay_init): + * ext/pango/gsttimeoverlay.c: (gst_time_overlay_init): + Use pango_font_description_set_family_static instead of + pango_font_description_set_family to save a string copy (it was + leaking due to the strdup anyway) + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_finalize): + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_finalize): + * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_finalize): + * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_finalize): + Chain up in finalize. + +2007-03-07 18:50:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixertrack.c: API: add "untranslated-label" property which should be set by implementations a... + Original commit message from CVS: + * gst-libs/gst/interfaces/mixertrack.c: + (gst_mixer_track_class_init), (gst_mixer_track_get_property), + (gst_mixer_track_set_property): + API: add "untranslated-label" property which should be set by + implementations at construct time (#414645). + * ext/alsa/gstalsamixeroptions.c: (gst_alsa_mixer_options_new): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + Set "untranslated-label" when constructing mixer track objects. + * tests/check/elements/alsa.c: (GST_START_TEST), (alsa_suite): + Unit test to check the above. + +2007-03-07 17:15:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Fix confusing debug message. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_read_chain): + Fix confusing debug message. + +2007-03-07 17:12:54 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-plugins-base.doap: update doap file with new version + Original commit message from CVS: + * gst-plugins-base.doap: + update doap file with new version + +2007-03-07 17:05:21 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + update docs + Original commit message from CVS: + update docs + +2007-03-07 16:56:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.12 === + +2007-03-07 16:46:51 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-decodebin2.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/config.h: + Release 0.10.12 + Original commit message from CVS: + Release 0.10.12 + +2007-03-07 15:35:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * common: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/de.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2007-03-06 12:31:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Bump version to 0.10.11.4 pre-release + Original commit message from CVS: + * configure.ac: + Bump version to 0.10.11.4 pre-release + +2007-03-06 12:10:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Fix regression that made GStreamer skip the first samples of audio. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_async_play): + Fix regression that made GStreamer skip the first samples of audio. + Fixes #414684. + +2007-03-05 11:21:13 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Bump version to 0.10.11.3 pre-release + Original commit message from CVS: + * configure.ac: + Bump version to 0.10.11.3 pre-release + +2007-03-05 09:35:29 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + po/POTFILES.in: Update paths for the rename from utils to pbutils to fix the build. + Original commit message from CVS: + * po/POTFILES.in: + Update paths for the rename from utils to pbutils to fix the build. + +2007-03-05 09:27:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/pbutils/Makefile.am: Change directory to install headers in from gst/utils to gst/pbutils as well. + Original commit message from CVS: + * gst-libs/gst/pbutils/Makefile.am: + Change directory to install headers in from gst/utils to gst/pbutils + as well. + +2007-03-04 23:41:51 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/libs/.gitignore: + moap ignore + Original commit message from CVS: + moap ignore + +2007-03-04 23:41:04 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * win32/common/config.h: + * win32/common/libgstutils.def: + update defs + Original commit message from CVS: + update defs + +2007-03-04 23:39:51 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + rename utils to pbutils + Original commit message from CVS: + * configure.ac: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/pbutils/Makefile.am: + * gst-libs/gst/pbutils/descriptions.c: + (gst_pb_utils_get_source_description), + (gst_pb_utils_get_sink_description), + (gst_pb_utils_get_decoder_description), + (gst_pb_utils_get_encoder_description), + (gst_pb_utils_get_element_description), + (gst_pb_utils_add_codec_description_to_tag_list), + (gst_pb_utils_get_codec_description), (gst_pb_utils_list_all): + * gst-libs/gst/pbutils/descriptions.h: + * gst-libs/gst/pbutils/install-plugins.c: + * gst-libs/gst/pbutils/install-plugins.h: + * gst-libs/gst/pbutils/missing-plugins.c: + (gst_missing_uri_source_message_new), + (gst_missing_uri_sink_message_new), + (gst_missing_element_message_new), + (gst_missing_decoder_message_new), + (gst_missing_encoder_message_new), + (gst_missing_plugin_message_get_description): + * gst-libs/gst/pbutils/missing-plugins.h: + * gst-libs/gst/pbutils/pbutils.c: (gst_pb_utils_init): + * gst-libs/gst/pbutils/pbutils.h: + * gst-libs/gst/utils/Makefile.am: + * gst-libs/gst/utils/base-utils.c: + * gst-libs/gst/utils/base-utils.h: + * gst-libs/gst/utils/descriptions.c: + * gst-libs/gst/utils/descriptions.h: + * gst-libs/gst/utils/install-plugins.c: + * gst-libs/gst/utils/install-plugins.h: + * gst-libs/gst/utils/missing-plugins.c: + * gst-libs/gst/utils/missing-plugins.h: + * gst-plugins-base.spec.in: + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin.c: + * gst/playback/gstdecodebin2.c: + * gst/playback/gstplaybasebin.c: (setup_subtitle), + (gen_source_element): + * gst/playback/gstplaybin.c: (plugin_init): + * tests/check/Makefile.am: + * tests/check/libs/pbutils.c: (GST_START_TEST), + (test_pb_utils_install_plugins_do_callout), (libgstpbutils_suite): + * tests/check/libs/utils.c: + rename utils to pbutils + +2007-03-03 10:23:03 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/app/Makefile.am: Install the headers. + Original commit message from CVS: + * gst-libs/gst/app/Makefile.am: + Install the headers. + +2007-03-03 10:10:30 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/app/: Add GstAppBuffer that includes a callback and closure for proper handling of data chunks. + Original commit message from CVS: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/app/gstappbuffer.c: + * gst-libs/gst/app/gstappbuffer.h: + * gst-libs/gst/app/gstappsrc.c: + Add GstAppBuffer that includes a callback and closure for + proper handling of data chunks. + +2007-03-03 09:06:06 +0000 David Schleef <ds@schleef.org> + + gst-libs/gst/app/gstappsrc.*: Hacking to address issues in 413418. + Original commit message from CVS: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/app/gstappsrc.h: + Hacking to address issues in 413418. + +2007-03-03 08:16:57 +0000 David Schleef <ds@schleef.org> + + Move the app library to gst-libs/gst/app (duh!) + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * ext/Makefile.am: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/app/Makefile.am: + * gst-libs/gst/app/gstapp.c: + * gst-libs/gst/app/gstappsrc.c: + * gst-libs/gst/app/gstappsrc.h: + * gst/app/Makefile.am: + * gst/app/gstapp.c: + * gst/app/gstappsrc.c: + * gst/app/gstappsrc.h: + Move the app library to gst-libs/gst/app (duh!) + +2007-03-02 12:59:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Add documentation for decodebin2 that indicates that the API is still unstable. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/inspect/plugin-decodebin2.xml: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_class_init): + Add documentation for decodebin2 that indicates that the API + is still unstable. + +2007-03-01 18:50:00 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Update to 0.10.11.2 (0.10.12 pre-release) + Original commit message from CVS: + * configure.ac: + Update to 0.10.11.2 (0.10.12 pre-release) + +2007-03-01 17:29:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: base time is irrelevant here. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_async_play): + base time is irrelevant here. + +2007-03-01 17:01:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/: Improve debugging. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func): + * gst-libs/gst/audio/gstaudiosrc.c: (audioringbuffer_thread_func): + Improve debugging. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_query), (gst_base_audio_sink_event), + (gst_base_audio_sink_render), (gst_base_audio_sink_async_play): + Improve latency and clock slaving calculations. + Improve slave clock calibration. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_commit_full): + When we are asked to render N sample to 0 bytes, return N. + +2007-03-01 16:48:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.*: Remove unused dispose function. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_class_init), + (gst_alsasink_write), (gst_alsasink_reset): + * ext/alsa/gstalsasink.h: + Remove unused dispose function. + Rename lock to not interfere with alsasrc lock. + * ext/alsa/gstalsasrc.c: (gst_alsasrc_finalize), + (gst_alsasrc_class_init), (gst_alsasrc_init), (set_swparams), + (gst_alsasrc_read), (gst_alsasrc_reset): + * ext/alsa/gstalsasrc.h: + Implement finalize function. + Use lock to protect alsa access. + Implement _reset. + Fine tune sw params. + +2007-03-01 10:20:59 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * configure.ac: + typo + Original commit message from CVS: + typo + +2007-02-28 19:27:28 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: Convert to new AG_GST style. + Original commit message from CVS: + * configure.ac: + Convert to new AG_GST style. + +2007-02-28 15:17:20 +0000 Ed Catmur <ed@catmur.co.uk> + + gst/playback/gstplaybin.c: Fix race condition when rapidly switching visualisations in playbin. + Original commit message from CVS: + Patch by: Ed Catmur <ed at catmur dot co dot uk> + * gst/playback/gstplaybin.c: (gst_play_bin_vis_unblocked), + (gst_play_bin_vis_blocked), (gst_play_bin_set_property): + Fix race condition when rapidly switching visualisations in playbin. + Fixes #401029. + +2007-02-28 15:11:59 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/Makefile.am: Include local stuff before system installed things in LDFLAGS and + Original commit message from CVS: + * tests/check/Makefile.am: + Include local stuff before system installed things in LDFLAGS and + CFLAGS. + +2007-02-28 15:10:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Improve debugging. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_sink_activate): + Improve debugging. + +2007-02-28 15:05:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/v4l/: Fix duration and timestamping, taking latency into account. + Original commit message from CVS: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init), + (gst_v4lsrc_fixate), (gst_v4lsrc_query): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_buffer_new): + Fix duration and timestamping, taking latency into account. + Implement latency query. + +2007-02-28 15:02:25 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudioclock.c: Fix clock name. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_init), + (gst_audio_clock_new): + Fix clock name. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_init), (gst_base_audio_sink_query): + * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_init), + (gst_base_audio_src_query), (gst_base_audio_src_get_offset), + (gst_base_audio_src_create): + Improve latency query code. + Use proper clock names. + +2007-02-28 12:57:46 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/generic/states.c: + plug test leak + Original commit message from CVS: + plug test leak + +2007-02-28 12:44:53 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/generic/states.c: Copy the states.c test from core again + Original commit message from CVS: + * tests/check/generic/states.c: (GST_START_TEST): + Copy the states.c test from core again + * tests/check/Makefile.am: + ignore cdio and cdparanoiasrc + +2007-02-28 12:08:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/audioconvert.c: Also make valgrind happy and avoid copying data in some cases. + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float), (double), (float_hq), + (double_hq), (audio_convert_get_func_index), (check_default), + (audio_convert_prepare_context), (audio_convert_convert): + Also make valgrind happy and avoid copying data in some cases. + +2007-02-28 11:58:16 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/generic/states.c: + use a macro + Original commit message from CVS: + use a macro + +2007-02-28 11:47:45 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Don't run inplace if that overwrites source data as we go. Add more tests. Fixes #339837 even more. + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float), (double), (float_hq), + (double_hq), (audio_convert_get_func_index), + (audio_convert_prepare_context), (audio_convert_convert): + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_class_init), (gst_audio_convert_get_unit_size), + (gst_audio_convert_transform_caps): + * tests/check/elements/audioconvert.c: (GST_START_TEST), + (audioconvert_suite): + Don't run inplace if that overwrites source data as we go. Add more + tests. Fixes #339837 even more. + +2007-02-27 18:45:37 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Fix various seeking bugs (Slider was not updating when doing a non flushing seek, Reverse... + Original commit message from CVS: + 2007-02-27 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (do_seek), (set_update_scale), + (msg_segment_done): Fix various seeking bugs (Slider was not + updating when doing a non flushing seek, Reverse playback + on segment seek was wrong). + +2007-02-26 21:01:03 +0000 David Schleef <ds@schleef.org> + + Add a new plugin/library to make it easy for apps to shove data into a pipeline. + Original commit message from CVS: + * configure.ac: + * gst/app/Makefile.am: + * gst/app/gstapp.c: + * gst/app/gstappsrc.c: + * gst/app/gstappsrc.h: + Add a new plugin/library to make it easy for apps to shove + data into a pipeline. + +2007-02-26 11:48:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: When we stop scrubbing, don't leave the pipeline PLAYING when we requested a PAUSED state. + Original commit message from CVS: + * tests/examples/seek/seek.c: (stop_seek): + When we stop scrubbing, don't leave the pipeline PLAYING when we + requested a PAUSED state. + +2007-02-25 23:51:03 +0000 René Stadler <mail@renestadler.de> + + gst-libs/gst/tag/gstvorbistag.c: Parse date strings in vorbis comments that have an invalid (zero) month or day (#410... + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler de> + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + Parse date strings in vorbis comments that have an invalid (zero) + month or day (#410396). + * tests/check/libs/tag.c: (GST_START_TEST): + Test case for the above. + +2007-02-24 20:12:49 +0000 Loïc Minier <lool+gnome@via.ecp.fr> + + Fix compilation with LDFLAGS='-Wl,-z,defs' (#410963). + Original commit message from CVS: + Patch by: Loïc Minier <lool+gnome at via ecp fr> + * configure.ac: + * ext/alsa/Makefile.am: + * gst/audiotestsrc/Makefile.am: + Fix compilation with LDFLAGS='-Wl,-z,defs' (#410963). + +2007-02-23 18:49:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Improve docs: point out that the application needs to assist playbin with buffering. + Original commit message from CVS: + * gst/playback/gstplaybin.c: + Improve docs: point out that the application needs to assist playbin + with buffering. + +2007-02-23 13:10:50 +0000 Tim-Philipp Müller <tim@centricular.net> + + Change GStreamer marker prefix in detail string from 'gstreamer.net' to just 'gstreamer'. Document the caps string co... + Original commit message from CVS: + * gst-libs/gst/utils/install-plugins.c: + * gst-libs/gst/utils/missing-plugins.c: + * tests/check/libs/utils.c: (missing_msg_check_getters): + Change GStreamer marker prefix in detail string from 'gstreamer.net' + to just 'gstreamer'. Document the caps string component of the + decoder/encoder detail a bit better, since not everyone will be + familiar with the GStreamer media type/caps system (but they better + enjoy nested itemized lists). + +2007-02-22 12:57:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/netbuffer/gstnetbuffer.c: Fix copying of GstNetBuffer (would crash before, or at least lead to invalid m... + Original commit message from CVS: + * gst-libs/gst/netbuffer/gstnetbuffer.c: + (notgst_buffer_copy_fields_in_place), (gst_netbuffer_copy): + Fix copying of GstNetBuffer (would crash before, or at least lead to + invalid memory access, #410772), for now by copying the GstBuffer copy + code from the core over here so we can copy the GstBuffer fields on a + provided buffer instance (of type GstNetBuffer in this case). Would be + better to fix this with some support by the core though (and in the long + run change the broken GstBuffer/GstMiniObject copy semantics, #393099). + * tests/check/Makefile.am: + Enable unit test for GstNetBuffer. + +2007-02-22 11:04:10 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst-libs/gst/audio/gstbaseaudiosink.c: + gst-libs/gst/audio/gstbaseaudiosink.c + Original commit message from CVS: + 2007-02-22 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_init): Disable pull-mode activation until we + figure out how to make audio sinks go to PLAYING. + +2007-02-22 09:04:37 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add float as an intermediate format, as well as float mixing. Enable test that was failing before. Fixes #339837 + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float), (double), (float_hq), + (double_hq), (audio_convert_get_func_index), + (audio_convert_prepare_context), (audio_convert_convert): + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_setup_matrix), + (gst_channel_mix_mix_int), (gst_channel_mix_mix_float): + * gst/audioconvert/gstchannelmix.h: + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Add float as an intermediate format, as well as float mixing. Enable + test that was failing before. Fixes #339837 + +2007-02-21 16:12:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/examples/seek/seek.c: Undo the previous commit: -1 as a stop time implies that the stop time is the end of file... + Original commit message from CVS: + * tests/examples/seek/seek.c: (do_seek): + Undo the previous commit: -1 as a stop time implies that the stop + time is the end of file, clearing any previously configured segment. + +2007-02-21 15:36:26 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/examples/seek/seek.c: Don't SEEK_SET with a stop time of -1, use SEEK_NONE instead. + Original commit message from CVS: + * tests/examples/seek/seek.c: (do_seek): + Don't SEEK_SET with a stop time of -1, use SEEK_NONE instead. + +2007-02-21 13:55:54 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/volume/gstvolume.c: Unbreak volume, value remains gint. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_process_int16), + (volume_process_int16_clamp), (volume_set_caps): + Unbreak volume, value remains gint. + +2007-02-21 13:08:51 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/volume/gstvolume.*: Extend float audio support (double) and some int->uint cleanups. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_update_real_volume), (gst_volume_set_volume), + (gst_volume_init), (volume_process_double), (volume_process_float), + (volume_process_int16), (volume_process_int16_clamp), + (volume_set_caps), (volume_transform_ip), (volume_update_volume): + * gst/volume/gstvolume.h: + Extend float audio support (double) and some int->uint cleanups. + +2007-02-20 15:44:32 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin2.c: Don't free groups from the streaming threads. Just put them aside and free them in disp... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_dispose), + (multi_queue_underrun_cb), (gst_decode_group_check_if_drained), + (sort_end_pads), (gst_decode_group_expose), + (gst_decode_group_hide): + Don't free groups from the streaming threads. Just put them aside and + free them in dispose. + +2007-02-20 11:20:52 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin2.c: Handle dynamic pads within groups. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (connect_element), + (pad_added_group_cb), (gst_decode_group_check_if_blocked), + (sort_end_pads), (gst_decode_group_expose): + Handle dynamic pads within groups. + Sort pads before exposing them in order to make playbin happy. + There still is a race with the multiqueue filling up. This should be + solved separately. + Fixes #398721 + +2007-02-18 21:02:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/utils/: Some more docs (and descriptions for two subtitle formats). + Original commit message from CVS: + * gst-libs/gst/utils/base-utils.c: + * gst-libs/gst/utils/descriptions.c: + * gst-libs/gst/utils/install-plugins.c: + * gst-libs/gst/utils/missing-plugins.c: + Some more docs (and descriptions for two subtitle formats). + +2007-02-16 10:19:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/audio.c: Fix documentation. + Original commit message from CVS: + * gst-libs/gst/audio/audio.c: + Fix documentation. + +2007-02-16 10:15:46 +0000 Yves Lefebvre <ivanohe@abacom.com> + + gst/videorate/gstvideorate.c: Don't leak caps. Fixes #408278. + Original commit message from CVS: + Patch by: Yves Lefebvre <ivanohe abacom com> + * gst/videorate/gstvideorate.c: (gst_video_rate_setcaps): + Don't leak caps. Fixes #408278. + +2007-02-15 15:17:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + More docs coverage and some ChangeLog surgery (add missing names) + Original commit message from CVS: + * ext/cdparanoia/gstcdparanoiasrc.h: + * ext/ogg/gstoggdemux.h: + * gst-libs/gst/audio/audio.c: (gst_audio_frame_byte_size), + (gst_audio_frame_length), (gst_audio_duration_from_pad_buffer), + (gst_audio_is_buffer_framed), (gst_audio_structure_set_int): + * gst-libs/gst/audio/audio.h: + * gst-libs/gst/audio/gstaudiofilter.h: + * gst-libs/gst/interfaces/videoorientation.h: + * gst/adder/gstadder.h: + More docs coverage and some ChangeLog surgery (add missing names) + +2007-02-15 12:07:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/: Small constifications. + Original commit message from CVS: + * sys/ximage/ximagesink.c: + (gst_ximagesink_calculate_pixel_aspect_ratio): + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio): + Small constifications. + +2007-02-15 12:06:25 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Answer latency query. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init), (gst_base_audio_sink_query), + (gst_base_audio_sink_render), (gst_base_audio_sink_callback), + (gst_base_audio_sink_async_play), + (gst_base_audio_sink_change_state): + Answer latency query. + Use configured latency when syncing. + Fix clock slaving. + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init), (gst_base_audio_src_dispose), + (gst_base_audio_src_query), (gst_base_audio_src_change_state): + Fix possible memleak. + Implement latency query. + Small cleanups. + +2007-02-15 11:59:41 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.c: Ignore errors in reset, these are not fatal. They also grab the element lock which is already... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_reset): + Ignore errors in reset, these are not fatal. They also grab the element + lock which is already taking when this function is called. Fixes + #405451. + +2007-02-13 13:50:56 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + add header file for easy codec install + Original commit message from CVS: + add header file for easy codec install + +2007-02-13 10:24:13 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + configure.ac: Remove 'tests/examples/xerror/Makefile' from output files again. + Original commit message from CVS: + * configure.ac: + Remove 'tests/examples/xerror/Makefile' from output files again. + +2007-02-13 09:12:11 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Also crossref against gst-plugins-base-libs. + Original commit message from CVS: + * configure.ac: + * docs/plugins/Makefile.am: + Also crossref against gst-plugins-base-libs. + +2007-02-12 20:42:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add crossreferences to glib/gobject/gstream docs. + Original commit message from CVS: + * configure.ac: + * docs/libs/Makefile.am: + * docs/plugins/Makefile.am: + Add crossreferences to glib/gobject/gstream docs. + * gst-libs/gst/audio/audio.h: + Source formatting. + * gst/audiotestsrc/gstaudiotestsrc.c: (plugin_init): + Add own debug category. + +2007-02-12 11:01:04 +0000 René Stadler <mail@renestadler.de> + + gst-libs/gst/tag/gstvorbistag.c: Add vorbis/FLAC-tag mapping for new GST_TAG_REFERENCE_LEVEL (#403597). + Original commit message from CVS: + Patch by: René Stadler <mail at renestadler de> + * gst-libs/gst/tag/gstvorbistag.c: + Add vorbis/FLAC-tag mapping for new GST_TAG_REFERENCE_LEVEL + (#403597). + +2007-02-12 10:33:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: When we have external subtitles and wait for the subtitle decodebin to get up and runn... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source): + When we have external subtitles and wait for the subtitle decodebin + to get up and running, we set up a (sync) bus handler for the + subtitle decodebin, so we can stop waiting when it posts an error + message. However, we should do that before we set the subtitle + decodebin's state to playing, otherwise things are racy and we might + miss error messages posted before we had a chance to set up the bus. + This should finally fix totem hanging on .txt pseudo-subtitle files. + +2007-02-10 19:27:48 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Use gst_gdouble_to_guint64 for conversions. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c:(gst_base_rtp_audio_payload_handle_frame_based_buffer): + Use gst_gdouble_to_guint64 for conversions. + * win32/common/config.h.in: + Add a define for GST_INSTALL_PLUGINS_HELPER + * win32/common/libgstaudio.def: + * win32/common/libgstcdda.def: + * win32/common/libgstnetbuffer.def: + * win32/common/libgstrtp.def: + * win32/common/libgutils.def: + Add new exported functions. + * win32/vs6/gst_plugins_base.dsw: + * win32/vs6/libgstdecodebin.dsp: + * win32/vs6/libgstnetbuffer.dsp: + * win32/vs6/libgstplaybin.dsp: + * win32/vs6/libgstrtp.dsp: + * win32/vs6/libgstvorbis.dsp: + * win32/vs6/libgstcdda.dsp: + * win32/vs6/libgstgdp.dsp: + * win32/vs6/libgstutils.dsp: + Update and add new project files. + +2007-02-10 18:19:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: For SubRip (.srt) subtitles, ignore all markup tags we don't handle (like font tags, for ... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (subrip_remove_unhandled_tag), + (subrip_remove_unhandled_tags), (parse_subrip): + For SubRip (.srt) subtitles, ignore all markup tags we don't + handle (like font tags, for example). + * tests/check/elements/subparse.c: + Add test for this. + +2007-02-09 13:28:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery + Original commit message from CVS: + ChangeLog surgery + +2007-02-09 13:16:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Don't error out if there is no fakesink in the READY to NULL state change, since when decodebin is re-... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (add_fakesink), + (gst_decode_bin_change_state): + * gst/playback/gstdecodebin2.c: (add_fakesink), + (gst_decode_bin_change_state): + Don't error out if there is no fakesink in the READY to NULL state + change, since when decodebin is re-used, we're only adding the + fakesink element in READY to PAUSED. + * tests/check/elements/decodebin.c: + (new_decoded_pad_plug_fakesink_cb), (GST_START_TEST), + (decodebin_suite): + Minimal unit test to make sure we can use the same decodebin + instance twice (at least with audiotestsrc input). + +2007-02-09 09:58:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsa.c: Try to get devic-name from device string first, and from handle only as fallback (seems to yield ... + Original commit message from CVS: + * ext/alsa/gstalsa.c: (gst_alsa_find_device_name): + Try to get devic-name from device string first, and from handle only + as fallback (seems to yield better results and is more robust + against buggy probing code on the application side). + +2007-02-08 15:43:26 +0000 Julien Puydt <julien.puydt@laposte.net> + + ext/alsa/: Improve device-name detection a bit, especially in the case where the device is not actually open (#405020... + Original commit message from CVS: + Based on patch by: Julien Puydt <julien.puydt at laposte net> + * ext/alsa/gstalsa.c: (gst_alsa_find_device_name_no_handle), + (gst_alsa_find_device_name): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsasink_get_property): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_get_property): + Improve device-name detection a bit, especially in the case where + the device is not actually open (#405020, #405024). Move common code + into gstalsa.c instead of duplicating it. + +2007-02-07 13:05:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/gstaudioconvert.c: Fix up docs chunk so that gtk-doc doesn't complain, and fix typo. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + Fix up docs chunk so that gtk-doc doesn't complain, and fix typo. + +2007-02-06 17:47:32 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.*: Implement PropertyProbe Interface for XVAdaptors so that one can choose the adaptor to use... + Original commit message from CVS: + 2007-02-06 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents), + (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_interface_supported), + (gst_xvimagesink_probe_get_properties), + (gst_xvimagesink_probe_probe_property), + (gst_xvimagesink_probe_needs_probe), + (gst_xvimagesink_probe_get_values), + (gst_xvimagesink_property_probe_interface_init), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init), + (gst_xvimagesink_get_type): + * sys/xvimage/xvimagesink.h: Implement PropertyProbe Interface + for XVAdaptors so that one can choose the adaptor to use with + gstreamer-properties. + +2007-02-06 14:00:31 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/gstaudioconvert.c: Also mention that a conversion from double to float is suboptimal still. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + Also mention that a conversion from double to float is suboptimal still. + +2007-02-06 09:42:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstaudiofilter.c: Clear our formats structure and free the caps contained in it when shutting down. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiofilter.c: + (gst_audio_filter_class_init), (gst_audio_filter_change_state): + Clear our formats structure and free the caps contained in it when + shutting down. + +2007-02-05 18:39:51 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst-libs/gst/audio/gstbaseaudiosink.c: + gst-libs/gst/audio/gstbaseaudiosink.c + Original commit message from CVS: + 2007-02-05 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_callback): Update basesink->offset so that we + pull monotonically increasing offsets instead of, um, seeking back + to 0 each time. Fixes alsasrc ! alsasink! + +2007-02-05 11:44:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videoscale/gstvideoscale.c: A width and height of 1 makes us crash, so increase minimum size to 2x2 pixels until ... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: + A width and height of 1 makes us crash, so increase minimum size to + 2x2 pixels until someone feels like fixing this (#404512). + +2007-02-04 16:23:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/oggmux.c: Add small test to make sure request pads are cleaned up properly even if oggmux never... + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: (GST_START_TEST), (oggmux_suite): + Add small test to make sure request pads are cleaned up properly + even if oggmux never changes state out of NULL. + +2007-02-04 14:11:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/utils.c: Fix unit test. Turns out things work much better when you + Original commit message from CVS: + * tests/check/libs/utils.c: (GST_START_TEST): + Fix unit test. Turns out things work much better when you + NULL-terminate string arrays. Should make p5 build bot happy again. + +2007-02-03 23:28:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/: Oops, forgot to commit fixed-up example. + Original commit message from CVS: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + (gst_audio_filter_template_base_init), + (gst_audio_filter_template_class_init), + (gst_audio_filter_template_init), + (gst_audio_filter_template_set_property), + (gst_audio_filter_template_get_property), + (gst_audio_filter_template_setup), + (gst_audio_filter_template_filter), + (gst_audio_filter_template_filter_inplace), (plugin_init): + Oops, forgot to commit fixed-up example. + +2007-02-03 20:19:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + Port GstAudioFilter to 0.10. This change technically breaks but seems justifiable on the grounds that the base class ... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audio_filter_get_type), + (gst_audio_filter_class_init), (gst_audio_filter_init), + (gst_audio_filter_set_caps), + (gst_audio_filter_class_add_pad_templates): + * gst-libs/gst/audio/gstaudiofilter.h: + Port GstAudioFilter to 0.10. This change technically breaks + API and ABI (and thus also every library developer's heart), + but seems justifiable on the grounds that the base class was + completely unusable before (ie. would crash immediately when + actually used). Fixes #403963 (and eventually also #403572). + Also document all of this a bit. + +2007-02-03 14:26:54 +0000 Tim-Philipp Müller <tim@centricular.net> + + Lowering log level to see why things fail on the p5 build bot; fix some typos in unit test messages. + Original commit message from CVS: + * gst-libs/gst/utils/install-plugins.c: + (gst_install_plugins_spawn_child): + * tests/check/libs/utils.c: + (test_base_utils_install_plugins_do_callout): + Lowering log level to see why things fail on the p5 build bot; + fix some typos in unit test messages. + +2007-02-03 13:59:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/utils.c: Don't hard-code temp directory for test helper; use GLib functions to write out file and do... + Original commit message from CVS: + * tests/check/libs/utils.c: + (test_base_utils_install_plugins_do_callout): + Don't hard-code temp directory for test helper; use GLib functions + to write out file and do error checking etc. + +2007-02-02 20:42:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/utils/: API: add API for applications to initiate installation of missing plugins, ie. gst_install_plugi... + Original commit message from CVS: + * gst-libs/gst/utils/Makefile.am: + * gst-libs/gst/utils/base-utils.h: + * gst-libs/gst/utils/install-plugins.c: + (gst_install_plugins_context_set_xid), + (gst_install_plugins_context_new), + (gst_install_plugins_context_free), + (gst_install_plugins_get_helper), + (gst_install_plugins_spawn_child), + (gst_install_plugins_return_from_status), + (gst_install_plugins_installer_exited), + (gst_install_plugins_async), (gst_install_plugins_sync), + (gst_install_plugins_return_get_name), + (gst_install_plugins_installation_in_progress): + * gst-libs/gst/utils/install-plugins.h: + API: add API for applications to initiate installation of missing + plugins, ie. gst_install_plugins_async() primarily. + Based on libgimme-codec by Ryan Lortie. + * configure.ac: + Add --with-install-plugins-helper configure option so distros can specify + the path of the helper script or program to call when plugin installation + is requested (distros: please do any argument munging in this helper + script instead of patching GStreamer to pass arguments differently + to another program directly). + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + Build and document new API. + * tests/check/libs/utils.c: (result_cb), + (test_base_utils_install_plugins_do_callout), (GST_START_TEST), + (libgstbaseutils_suite): + Some simple checks for the new API. + +2007-02-02 14:44:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/audioconvert.c: Add small test for 32bit float <=> 64bit float conversion (works only one way so... + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (test_float_conversion): + Add small test for 32bit float <=> 64bit float conversion (works + only one way so far, 32=>64 produces structured noise). + +2007-02-02 11:21:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/gstaudioconvert.c: We don't support floats with a width of 40, 48 or 56 bits. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (set_structure_widths_32_and_64), (make_lossless_changes): + We don't support floats with a width of 40, 48 or 56 bits. + +2007-02-02 09:48:53 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/: Support for 64-bit float audio in audioconvert (#339837) + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float), (double), + (audio_convert_get_func_index): + * gst/audioconvert/gstaudioconvert.c: (set_structure_widths), + (make_lossless_changes): + Support for 64-bit float audio in audioconvert (#339837) + +2007-02-01 18:50:08 +0000 Holger Wansing <linux@wansing-online.de> + + po/: Add German translation (#352069). + Original commit message from CVS: + Patch by: Holger Wansing <linux wansing-online de> + * po/LINGUAS: + * po/de.po: + Add German translation (#352069). + +2007-02-01 17:52:39 +0000 Sebastian Dröge <slomo@circular-chaos.org> + + ext/ogg/gstoggmux.c: Use newly added GstCollectPads API to free the allocated resources in the GstOggPad structures (... + Original commit message from CVS: + reviewed by: Wim Taymans <wim@fluendo.com> + * ext/ogg/gstoggmux.c: (gst_ogg_mux_ogg_pad_destroy_notify), + (gst_ogg_mux_request_new_pad), (gst_ogg_mux_release_pad): + Use newly added GstCollectPads API to free the allocated resources in + the GstOggPad structures (#402393). + +2007-01-31 15:58:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybin.c: Add audioresample+audioconvert in front of the visualisation element, so that elements lik... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_vis_element): + Add audioresample+audioconvert in front of the visualisation + element, so that elements like libvisual 0.4 that don't support all + samplerates can work. + Fixes: #402505 + +2007-01-30 19:19:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Take some locks and make a copy of the streaminfo value array we maintain while holdin... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_property), + (gst_play_base_bin_get_streaminfo_value_array): + Take some locks and make a copy of the streaminfo value array we + maintain while holding the lock, so that the application can + retrieve the stream-info as a value array in a thread-safe way. + +2007-01-30 11:29:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audioconvert/gstaudioconvert.c: Don't fail on 0 sized buffers. Fixes #396835. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + Don't fail on 0 sized buffers. Fixes #396835. + +2007-01-29 21:13:07 +0000 David Schleef <ds@schleef.org> + + gst/typefind/gsttypefindfunctions.c: Detect BBCD as video/x-dirac, so we can play raw dirac streams. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + Detect BBCD as video/x-dirac, so we can play raw dirac + streams. + +2007-01-29 18:14:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/theora/theoraenc.c: Check return value of theora_encode_header(), or we might try to allocate a random number of ... + Original commit message from CVS: + * ext/theora/theoraenc.c: (theora_enc_chain): + Check return value of theora_encode_header(), or we might try to + allocate a random number of bytes. theora_encode_header() can fail + if libtheora has been compiled with encoding support disabled. + Fixes #398110. + +2007-01-29 10:53:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/gst/.cvsignore: Do as buildbot says. + Original commit message from CVS: + * tests/check/gst/.cvsignore: + Do as buildbot says. + +2007-01-29 10:25:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: Fix strides in libvisual. Gst uses X strides. + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_src_setcaps): + Fix strides in libvisual. Gst uses X strides. + Inspired by: <ed at catmur dot co dot uk> and + <tim at centricular dot net> + Fixes #401118. + +2007-01-27 13:32:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.*: Properly propagate streaming errors when we are scanning the file for chains so that we don't ... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_submit_buffer), + (gst_ogg_demux_get_data), (gst_ogg_demux_get_next_page), + (gst_ogg_demux_get_prev_page), (gst_ogg_demux_do_seek), + (gst_ogg_demux_perform_seek), + (gst_ogg_demux_bisect_forward_serialno), + (gst_ogg_demux_read_chain), (gst_ogg_demux_read_end_chain), + (gst_ogg_demux_find_chains), (gst_ogg_demux_handle_page), + (gst_ogg_demux_chain), (gst_ogg_demux_combine_flows), + (gst_ogg_demux_loop_reverse), (gst_ogg_demux_loop): + * ext/ogg/gstoggdemux.h: + Properly propagate streaming errors when we are scanning the file for + chains so that we don't crash when shut down. Might fix some crashers + when quickly switching oggs in RB such as #332503 and #378436. + +2007-01-26 12:44:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Map a gnome-vfs HOST_NOT_FOUND error into a GStreamer NOT_FOUND error code as well. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_start): + Map a gnome-vfs HOST_NOT_FOUND error into a GStreamer NOT_FOUND + error code as well. + +2007-01-25 16:02:41 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Don't try to disconnect a signal from a finalized object. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (remove_source): + Don't try to disconnect a signal from a finalized object. + +2007-01-25 14:29:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin2.c: Cast lock macro parameters to make sure we're actually accessing the lock member at the... + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_dispose): + Cast lock macro parameters to make sure we're actually accessing the + lock member at the right class level. Free list itself in _dispose() + as well and NULL it in case dispose gets called multiple times. + +2007-01-25 14:02:37 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin2.c: Free GstDecodeGroups no longer used. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: + (gst_decode_bin_dispose),(gst_decode_bin_finalize): + Free GstDecodeGroups no longer used. + (gst_decode_group_expose): + Don't unlock too many times ! + (deactivate_free_recursive): + Free iterator once we're done with it. + Fix for recursively deactivating elements (stop at ghostpads). + +2007-01-25 12:24:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Fix up caps on the frame buffer before we save it and potentially make it accessible to ot... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (handoff): + Fix up caps on the frame buffer before we save it and potentially + make it accessible to other threads via g_object_get; also use + gst_buffer_replace() instead of gst_mini_object_replace(). + +2007-01-25 12:06:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Make getting the current frame thread-safe. + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gst_play_bin_get_property): + Make getting the current frame thread-safe. + +2007-01-25 11:48:10 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin2.c: Set queues to bigger sizes to cope with HD contents. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_finalize), + (gst_decode_group_new), (gst_decode_group_free): + Set queues to bigger sizes to cope with HD contents. + Fix some mutex freeing and add comment about MT safe methods. + +2007-01-24 12:51:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Don't unnecessarily ref (and then leak) upstream events if the text pad is not linked. Fi... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_src_event), + (gst_text_overlay_text_event): + Don't unnecessarily ref (and then leak) upstream events if the text + pad is not linked. Fixes #399948. + * tests/check/gst-plugins-base.supp: + Add suppression for pango on edgy/x86 for textoverlay test. + +2007-01-24 12:10:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstrtpbuffer.h: Add some more fixed payloads. + Original commit message from CVS: + * gst-libs/gst/rtp/gstrtpbuffer.h: + Add some more fixed payloads. + +2007-01-23 18:39:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggdemux.c: Error out properly if we get an error from libogg while reading the + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_read_chain): + Error out properly if we get an error from libogg while reading the + BOS page(s). Fixes crash parsing 'fuzzed' ogg file (#399340). + +2007-01-23 17:49:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin2.c: Don't leak mutex. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_finalize): + Don't leak mutex. + * tests/check/elements/playbin.c: + (test_sink_usage_video_only_stream), + (test_suburi_error_unknowntype), (test_suburi_error_invalidfile), + (test_suburi_error_wrongproto), (test_missing_urisource_handler), + (test_missing_suburisource_handler), + (test_missing_primary_decoder), (playbin_suite): + Run all tests once with decodebin and once with decodebin2. + One test does not pass yet with decodebin2. + +2007-01-23 14:30:28 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/ogg/gstoggmux.c: Fix the cases where oggmux doesn't properly figure out that all sinkpads have gone EOS, and ther... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (all_pads_eos), (gst_ogg_mux_collected): + Fix the cases where oggmux doesn't properly figure out that all + sinkpads have gone EOS, and therefore doesn't push out the remaining + buffers and the final EOS event. + Fixes #363379 + +2007-01-23 13:19:19 +0000 Julien Moutte <julien@moutte.net> + + sys/: Don't lock on navigation event push, just on keysym to string. + Original commit message from CVS: + 2007-01-23 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): + Don't lock on navigation event push, just on keysym to string. + Fixes #397673 again. + +2007-01-22 17:37:38 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin2.c: Cleanups. + Original commit message from CVS: + * gst/playback/gstdecodebin2.c: (gst_decode_group_new), + (get_current_group), (group_demuxer_event_probe), + (gst_decode_group_expose), (deactivate_free_recursive), + (gst_decode_group_free): + Cleanups. + Don't forget to emit 'no-more-pads' once a group is exposed. + Cleanup elements from a DecodeGroup once we remove it. + Protect call to gst_decode_group_expose() with the decodebin lock. + +2007-01-22 13:16:42 +0000 Julien Moutte <julien@moutte.net> + + sys/: Looking at Xorg code i can't figure out if that XKeysymToString function is thread sensible or not. Lock it jus... + Original commit message from CVS: + 2007-01-22 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): + Looking at Xorg code i can't figure out if that XKeysymToString + function is thread sensible or not. Lock it just in case as + recommended by Radek Doulik <rodo at ximian dot com>. + +2007-01-22 13:10:13 +0000 Julien Moutte <julien@moutte.net> + + sys/: Lock that X Call as well. Fixes #397673. + Original commit message from CVS: + 2007-01-22 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): + Lock that X Call as well. Fixes #397673. + +2007-01-22 12:03:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Don't go into an endless loop if the file starts with 00 00 01 2X, like quicktim... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg4_video_type_find): + Don't go into an endless loop if the file starts with 00 00 01 2X, + like quicktime redirect files might. Fixes #396042. + * tests/check/Makefile.am: + * tests/check/gst/.cvsignore: + * tests/check/gst/typefindfunctions.c: (GST_START_TEST), + (typefindfunctions_suite): + Add unit test for the above. + +2007-01-22 10:27:26 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: On second thought, use "depth" field rather than "bpp" field. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + On second thought, use "depth" field rather than "bpp" field. + +2007-01-22 09:23:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Camtasia caps apparently need a bpp field (#398875). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Camtasia caps apparently need a bpp field (#398875). + +2007-01-19 19:09:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Attempt at a better error message in case we don't have the required + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_subtitle), + (gen_source_element), (gst_play_base_bin_change_state): + Attempt at a better error message in case we don't have the required + URI handler installed; post missing-plugin message also when we're + missing an URI handler for the subtitle URI; clean up properly also + when an error occurs and we never made it to PAUSED state. + * tests/check/elements/playbin.c: (GST_START_TEST), + (playbin_suite): + Check that we're also getting a missing-plugin messsage for a + missing subtitle URI handler (and clean up properly). + +2007-01-19 18:47:30 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Plug a few reference leaks. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (analyse_source), (setup_source): + Plug a few reference leaks. + +2007-01-19 12:23:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Lower probability a bit if the marker isn't right at the start, to decrease the ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find): + Lower probability a bit if the marker isn't right at the start, + to decrease the chance of false positives. + +2007-01-19 11:31:50 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Small mpeg2 system stream typefinding improvement: make typefinder probe a bit i... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find): + Small mpeg2 system stream typefinding improvement: make typefinder + probe a bit into the stream instead of just looking for a marker + at the beginning. Fixes #397810. + +2007-01-18 16:23:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/gstchannelmix.c: Remove compatibility cruft for prehistoric GLib versions. + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: + Remove compatibility cruft for prehistoric GLib versions. + +2007-01-17 16:11:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Let decodebin be the element to post missing-plugin messages for missing decoders (rather than playbin... + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin.c: (close_pad_link): + * gst/playback/gstdecodebin2.c: (analyze_new_pad): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_handle_message_func), (unknown_type): + Let decodebin be the element to post missing-plugin messages for + missing decoders (rather than playbin); make playbin implement + GstBin::handle_message so we can suppress missing-plugin messages + for types we're not handling on purpose (don't want to bring up an + installer in those cases). + +2007-01-16 19:37:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: Fix potentially unaligned access (#397207). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + * gst-libs/gst/tag/gstvorbistag.c: + (gst_tag_list_to_vorbiscomment_buffer): + * gst/typefind/gsttypefindfunctions.c: (vorbis_type_find): + Fix potentially unaligned access (#397207). + +2007-01-16 12:17:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/examples/seek/seek.c: Allow to toggle looping while it plays. Fix callback prototype. Clean up code a bit more.... + Original commit message from CVS: + * tests/examples/seek/seek.c: (set_scale), (update_scale), + (do_seek), (stop_seek), (pause_cb), (stop_cb), (loop_toggle_cb), + (rate_spinbutton_changed_cb), (msg_eos), (msg_segment_done), + (main): + Allow to toggle looping while it plays. Fix callback prototype. Clean + up code a bit more. Add copyright header. + +2007-01-16 11:41:58 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Red and blue mask was swapped (spotted by Dan Williams). + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + Red and blue mask was swapped (spotted by Dan Williams). + +2007-01-15 13:58:58 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/tag/: Use new beats-per-minute tag from core. + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + * gst-libs/gst/tag/gstvorbistag.c: + Use new beats-per-minute tag from core. + +2007-01-15 11:30:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + po/POTFILES.in: Add new files with translatable strings, so they actually make it into the template file one day. + Original commit message from CVS: + * po/POTFILES.in: + Add new files with translatable strings, so they actually make it + into the template file one day. + +2007-01-12 21:19:35 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + gst-libs/gst/audio/gstbaseaudiosink.c + Original commit message from CVS: + 2007-01-12 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_fixate): Implement, stolen from baseaudiosrc. + (gst_base_audio_sink_activate_pull): Remove the handwavey nego + stuff, as the base class handles this now. Actually tell the ring + buffer to start. + (gst_base_audio_sink_callback): Cast the ring buffer correctly. + How did this work before? Maybe I'm not as awesome a programmer as + I think. + * gst-libs/gst/audio/gstbaseaudiosrc.c + (gst_base_audio_src_fixate): Rework as a basesrc vmethod instead + of a pad function. + +2007-01-12 18:08:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/utils/missing-plugins.c: Remove more fields so that the application can better blacklist formats that ha... + Original commit message from CVS: + * gst-libs/gst/utils/missing-plugins.c: (copy_and_clean_caps): + Remove more fields so that the application can better blacklist + formats that have been tried before. + +2007-01-12 17:43:40 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + add latest files + Original commit message from CVS: + add latest files + +2007-01-12 12:47:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/mixerutils.h: Add G_BEGIN_DECLS and G_END_DECLS guards so these helpers can be used when compiling... + Original commit message from CVS: + * gst-libs/gst/audio/mixerutils.h: + Add G_BEGIN_DECLS and G_END_DECLS guards so these helpers can be + used when compiling with c++ compilers as well. + +2007-01-12 09:45:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Fix comment. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + Fix comment. + +2007-01-11 13:12:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Post missing-plugin messages also when we error out because converters, textoverlay or aut... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (post_missing_element_message), + (gen_video_element), (gen_text_element), (gen_audio_element), + (gen_vis_element): + Post missing-plugin messages also when we error out because + converters, textoverlay or auto*sinks are missing (#161922). + +2007-01-10 16:08:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Fix the case where we try to ref a NULL element when we delay a link because of unfixed caps. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (dynamic_add), (close_pad_link), + (is_demuxer_element), (new_caps): + * gst/playback/gstplaybasebin.c: (source_new_pad): + Fix the case where we try to ref a NULL element when we delay a link + because of unfixed caps. + Set the state of autoplugged decodebins to PAUSED. + RTSP now works in playbin, we can remove it from the blacklist. + +2007-01-09 14:33:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Post missing-plugin messages on the bus for missing sources and missing decoders/demuxers/depayloaders... + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstplaybasebin.c: (string_arr_has_str), + (unknown_type), (setup_subtitle), (gen_source_element): + * gst/playback/gstplaybin.c: (plugin_init): + Post missing-plugin messages on the bus for missing sources and + missing decoders/demuxers/depayloaders; fix error code used when + we're missing an URI handler source; for media types that we are not + handling on purpose at the moment, don't print "don't know how to + handle xyz" messages to the terminal or post missing-plugin + messages on the bus. + * tests/check/elements/playbin.c: (create_playbin), + (GST_START_TEST), (gst_codec_src_uri_get_type), + (gst_codec_src_uri_get_protocols), (gst_codec_src_uri_get_uri), + (gst_codec_src_uri_set_uri), (gst_codec_src_uri_handler_init), + (gst_codec_src_init_type), (gst_codec_src_base_init), + (gst_codec_src_create), (gst_codec_src_class_init), + (gst_codec_src_init), (plugin_init), (playbin_suite): + Add some tests for the missing-plugin stuff. + +2007-01-09 14:20:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add new libgstbaseutils library with functions + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/utils/Makefile.am: + * gst-libs/gst/utils/base-utils.c: (gst_base_utils_init): + * gst-libs/gst/utils/base-utils.h: + * gst-libs/gst/utils/descriptions.c: (format_info_get_desc), + (find_format_info), (caps_are_rtp_caps), + (gst_base_utils_get_source_description), + (gst_base_utils_get_sink_description), + (gst_base_utils_get_decoder_description), + (gst_base_utils_get_encoder_description), + (gst_base_utils_get_element_description), + (gst_base_utils_add_codec_description_to_tag_list), + (gst_base_utils_get_codec_description), (gst_base_utils_list_all): + * gst-libs/gst/utils/descriptions.h: + * gst-libs/gst/utils/missing-plugins.c: + (missing_structure_get_type), (copy_and_clean_caps), + (gst_missing_uri_source_message_new), + (gst_missing_uri_sink_message_new), + (gst_missing_element_message_new), + (gst_missing_decoder_message_new), + (gst_missing_encoder_message_new), + (missing_structure_get_string_detail), + (missing_structure_get_caps_detail), + (gst_missing_plugin_message_get_installer_detail), + (gst_missing_plugin_message_get_description), + (gst_is_missing_plugin_message): + * gst-libs/gst/utils/missing-plugins.h: + API: add new libgstbaseutils library with functions + - to create and parse missing-plugins messages + - that provide (translated) descriptions for caps/decoders/sources/etc. + Closes #392393. + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + Add new lib. + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + Generate docs for new lib and API. + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/utils.c: (missing_msg_check_getters), + (GST_START_TEST), (libgstbaseutils_suite): + Add some basic unit tests. + +2007-01-09 13:35:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/Makefile.am: Dist gstoggdemux.h to fix 'make distcheck'. + Original commit message from CVS: + * ext/ogg/Makefile.am: + Dist gstoggdemux.h to fix 'make distcheck'. + * sys/v4l/Makefile.am: + Fix 'make distcheck' even more. + +2007-01-09 12:30:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + Added docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/ogg/gstoggdemux.c: (gst_ogg_page_copy), (gst_ogg_page_free), + (gst_ogg_pad_query_types), (gst_ogg_pad_submit_page), + (gst_ogg_chain_reset), (gst_ogg_chain_new_stream), + (gst_ogg_demux_perform_seek): + * ext/ogg/gstoggdemux.h: + Added docs. + Add some more comments. + Small cleanups. + +2007-01-09 11:15:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + Small documentation updates/fixes + Original commit message from CVS: + * ext/theora/theoradec.c: + * ext/vorbis/vorbisdec.c: + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_commit_full): + * gst-libs/gst/audio/gstringbuffer.h: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/tag/gstvorbistag.c: + Small documentation updates/fixes + +2007-01-09 10:37:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Require core CVS HEAD for Andy's basesrc/sink API additions. + Original commit message from CVS: + * configure.ac: + Require core CVS HEAD for Andy's basesrc/sink API additions. + +2007-01-08 14:01:23 +0000 Günter Thelen <daedalus.inc@gmx.net> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for flac-in-ogg in conformance with the ogg-mapping on flac.sf.ne... + Original commit message from CVS: + Patch by: Günter Thelen <daedalus dot inc at gmx net> + * gst/typefind/gsttypefindfunctions.c: (flac_type_find), + (plugin_init): + Add typefinder for flac-in-ogg in conformance with the ogg-mapping + on flac.sf.net (there appear to be other versions of the first + ogg page in the wild) (#391365). + +2007-01-08 13:32:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Check if localtime_r() is available. + Original commit message from CVS: + * configure.ac: + Check if localtime_r() is available. + * ext/pango/gstclockoverlay.c: (gst_clock_overlay_render_time): + If localtime_r() is not available, fall back to localtime(). Should + fix build on MingW (#393310). + +2007-01-08 12:30:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.*: Remove spurious 1000 subtrahend when calculating the timestamp from the frame number and ... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (parse_mdvdsub): + * gst/subparse/gstsubparse.h: + Remove spurious 1000 subtrahend when calculating the timestamp from + the frame number and the frame rate . Also, use the frames/second + value specified in the first line of the file, if one is specified + there. Should fix #357503. + * tests/check/elements/subparse.c: (do_test), + (test_tmplayer_do_test), (test_microdvd_do_test), (GST_START_TEST), + (subparse_suite): + Add some basic unit tests for the microdvd subtitle format. + +2007-01-07 21:53:38 +0000 Young-Ho Cha <ganadist@chollian.net> + + sys/xvimage/xvimagesink.c: Fixes : #390076. + Original commit message from CVS: + 2007-01-07 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimage_buffer_finalize), (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_xvimage_put), + (gst_lookup_xv_port_from_adaptor), + (gst_xvimagesink_get_xv_support), (gst_xvimagesink_setcaps), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_set_event_handling), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + Patch by : Young-Ho Cha <ganadist at chollian dot net> + Fixes : #390076. + Add an adaptor property to select a specific XV adaptor. + * sys/xvimage/xvimagesink.h: + +2007-01-07 18:50:13 +0000 Julien Moutte <julien@moutte.net> + + sys/: Use flow_lock much more to protect every access to xwindow. + Original commit message from CVS: + 2007-01-07 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), + (gst_ximagesink_handle_xerror), (gst_ximagesink_ximage_new), + (gst_ximagesink_ximage_destroy), (gst_ximagesink_ximage_put), + (gst_ximagesink_handle_xevents), (gst_ximagesink_setcaps), + (gst_ximagesink_change_state), (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_expose), (gst_ximagesink_set_event_handling): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimage_buffer_finalize), (gst_xvimagesink_handle_xerror), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_handle_xevents), (gst_xvimagesink_setcaps), + (gst_xvimagesink_change_state), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_expose), (gst_xvimagesink_set_event_handling): + Use flow_lock much more to protect every access to xwindow. + Try to catch erros while creating images in case some drivers + are + just generating an XError when the requested image is too big. + Should fix : #354698, #384008, #384060. + * tests/icles/stress-xoverlay.c: (cycle_window), + (create_window): + Implement some stress testing of setting window xid. + +2007-01-07 10:33:55 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/common/libgsaudio.def: Add new exported function. + Original commit message from CVS: + * win32/common/libgsaudio.def: + Add new exported function. + * win32/common/libgstogg.dsp: + Add gstoggaviparse.c to the build. + * win32/common/libgstvideoscale.dsp: + Add vs_4tap.c to the build. + * win32/common/libgstvorbis.dsp: + Add vorbistag.c to the build. + +2007-01-06 17:28:40 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst-libs/gst/audio/gstbaseaudiosink.c: + gst-libs/gst/audio/gstbaseaudiosink.c (gst_base_audio_sink_class_init) + Original commit message from CVS: + 2007-01-06 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstbaseaudiosink.c + (gst_base_audio_sink_class_init) + (gst_base_audio_sink_init): + (gst_base_audio_sink_activate_pull): Add an activate_pull function + to baseaudiosink, and tell basesink that we can work in pull mode. + This way the ring buffer thread drives the pipeline directly, if + pull mode is possible. There is some lingering nastiness regarding + capsnego, however. + (gst_base_audio_sink_callback): Implement the callback to pull + data. This interface is a bit light, though -- it should get a + GstFlowReturn return value at least. + +2007-01-05 19:43:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + Printf format and missing argument fixes. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_stream_out): + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + * gst/playback/gstdecodebin2.c: + (gst_decode_group_check_if_blocked): + Printf format and missing argument fixes. + +2007-01-05 18:57:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/ogg/gstogmparse.c: Activate pads before adding them to the element. + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_stream_header), + (gst_ogm_parse_change_state): + Activate pads before adding them to the element. + +2007-01-05 16:02:50 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/examples/seek/: Call g_thread_init() first thing in main() (see #391278). + Original commit message from CVS: + * tests/examples/seek/scrubby.c: (main): + * tests/examples/seek/seek.c: (main): + Call g_thread_init() first thing in main() (see #391278). + +2007-01-05 12:19:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add test for GstNetBuffer + gst_buffer_copy(). Disabled for the time being, since it's broken, see #393... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/netbuffer.c: (GST_START_TEST), + (netbuffer_suite): + Add test for GstNetBuffer + gst_buffer_copy(). Disabled + for the time being, since it's broken, see #393099. + +2007-01-05 12:13:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Update to use GST_PLUGINS_BASE_CFLAGS as well. + Original commit message from CVS: + * tests/check/Makefile.am: + Update to use GST_PLUGINS_BASE_CFLAGS as well. + +2007-01-04 12:49:48 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: split out GST_CFLAGS into GST_PLUGINS_BASE_CFLAGS and GST_CFLAGS so that GST_BASE_CFLAGS can go inbetwe... + Original commit message from CVS: + * configure.ac: + split out GST_CFLAGS into GST_PLUGINS_BASE_CFLAGS and GST_CFLAGS + so that GST_BASE_CFLAGS can go inbetween them, making sure + we use uninstalled gst-libs headers + * docs/libs/Makefile.am: + * ext/alsa/Makefile.am: + * ext/cdparanoia/Makefile.am: + * ext/gnomevfs/Makefile.am: + * ext/libvisual/Makefile.am: + * ext/ogg/Makefile.am: + * ext/theora/Makefile.am: + * ext/vorbis/Makefile.am: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/tag/Makefile.am: + * gst/adder/Makefile.am: + * gst/audioconvert/Makefile.am: + * gst/audiorate/Makefile.am: + * gst/audioresample/Makefile.am: + * gst/playback/Makefile.am: + * gst/tcp/Makefile.am: + * gst/videoscale/Makefile.am: + * gst/volume/Makefile.am: + * sys/ximage/Makefile.am: + * sys/xvimage/Makefile.am: + * tests/icles/Makefile.am: + adapt + +2007-01-04 11:30:53 +0000 Julien Moutte <julien@moutte.net> + + Add a method to the XOverlay interface to allow disabling of event handling in x[v]imagesink elements. This will let ... + Original commit message from CVS: + 2007-01-04 Julien MOUTTE <julien@moutte.net> + * gst-libs/gst/interfaces/xoverlay.c: + (gst_x_overlay_handle_events): + * gst-libs/gst/interfaces/xoverlay.h: + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new), + (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_set_event_handling), + (gst_ximagesink_xoverlay_init), (gst_ximagesink_set_property), + (gst_ximagesink_get_property), (gst_ximagesink_init), + (gst_ximagesink_class_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_new), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_set_event_handling), + (gst_xvimagesink_xoverlay_init), (gst_xvimagesink_set_property), + (gst_xvimagesink_get_property), (gst_xvimagesink_init), + (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + * tests/icles/stress-xoverlay.c: (toggle_events), + (create_window): + Add a method to the XOverlay interface to allow disabling of + event handling in x[v]imagesink elements. This will let X events + propagate to parent windows which can be usefull in some cases. + Be carefull that the application is then responsible of pushing + navigation events and expose events to the video sink. + Fixes: #387138. + +2007-01-03 15:45:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add vorbistag <=> GStreamer tag mapping for GST_TAG_LOCATION (fixes #392070). + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: + * tests/check/libs/tag.c: (GST_START_TEST): + Add vorbistag <=> GStreamer tag mapping for GST_TAG_LOCATION + (fixes #392070). + +2007-01-01 18:59:49 +0000 Tim-Philipp Müller <tim@centricular.net> + + Dist design docs. + Original commit message from CVS: + * configure.ac: + * docs/Makefile.am: + * docs/design/Makefile.am: + Dist design docs. + +2006-12-27 17:15:35 +0000 Julien Moutte <julien@moutte.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Fix a documentation typo. Fixes: #390063. + Original commit message from CVS: + 2006-12-27 Julien MOUTTE <julien@moutte.net> + * docs/libs/gst-plugins-base-libs-sections.txt: Fix a + documentation + typo. Fixes: #390063. + +2006-12-27 12:08:13 +0000 Julien Moutte <julien@moutte.net> + + sys/: Plug a caps leak. + Original commit message from CVS: + 2006-12-27 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_setcaps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_setcaps): Plug a + caps leak. + * win32/common/config.h: Updated. + +2006-12-22 12:10:18 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/: Fix the dp tests, but activating the pads for the streamheader tests too and cleaning up condi... + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (cleanup_gdpdepay), + (setup_gdpdepay_streamheader): + * tests/check/elements/gdppay.c: (cleanup_gdppay), + (setup_gdppay_streamheader): + Fix the dp tests, but activating the pads for the streamheader tests + too and cleaning up conditionaly + +2006-12-22 11:09:34 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/ffmpegcolorspace/: Add 2 new caps arrangements, for 24-bit RGB and BGR in 32-bits, but at the other end of the wo... + Original commit message from CVS: + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (img_convert), + (img_get_alpha_info): + Add 2 new caps arrangements, for 24-bit RGB and BGR in 32-bits, but at the + other end of the word. Fixes: #387073. + Add some inconsequential branch hints in a couple of places. + +2006-12-21 12:30:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: The "signed" field in raw audio caps is of boolean type, trying to extract ... + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_caps_to_smpfmt): + The "signed" field in raw audio caps is of boolean type, trying to + extract the value with _get_int() will fail (fix to keep in sync with + the copy in gst-ffmpeg) + +2006-12-21 08:12:26 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/: consistent pad (de)activation + Original commit message from CVS: + * tests/check/elements/audioresample.c: (cleanup_audioresample): + * tests/check/elements/audiotestsrc.c: (cleanup_audiotestsrc): + * tests/check/elements/gdpdepay.c: (setup_gdpdepay), + (cleanup_gdpdepay): + * tests/check/elements/gdppay.c: (setup_gdppay), (cleanup_gdppay): + * tests/check/elements/subparse.c: (teardown_subparse): + * tests/check/elements/textoverlay.c: (cleanup_textoverlay): + * tests/check/elements/videorate.c: (cleanup_videorate): + * tests/check/elements/videotestsrc.c: (cleanup_videotestsrc): + * tests/check/elements/volume.c: (cleanup_volume): + * tests/check/elements/vorbisdec.c: (setup_vorbisdec), + (cleanup_vorbisdec): + * tests/check/elements/vorbistag.c: (setup_vorbistag), + (cleanup_vorbistag): + consistent pad (de)activation + +2006-12-20 10:29:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Forgot to register the extensions. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Forgot to register the extensions. + +2006-12-20 09:25:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for VIVO files (my christmas present to the 90s). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (vivo_type_find), + (plugin_init): + Add typefinder for VIVO files (my christmas present to the 90s). + +2006-12-16 13:59:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: Special-case the text/plain media type: we only want to recognise it as a 'raw' decoded ... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (type_found): + Special-case the text/plain media type: we only want to recognise it + as a 'raw' decoded media type if it comes from a demuxer or subtitle + parser, but not if the entire stream is of text/plain type. If the + entire stream is text/plain, we should just error out. + This fixes playback of audio files with lyrics in totem. Totem can't + distinguish between text files and subtitle files and passes any + .txt file with the same basename as the main file to playbin as + suburi, and playbin will then throw a 'subtitle found, but no video + stream' error, which isn't entirely helpful. See #380342. + Also, with this change we'll show a slightly more correct error + message in case totem passes a playlist file to us (although a + custom error message wording instead of the default text would + probably not be a bad idea either). + Same problem also needs to be fixed for playbin+decodebin2. + * tests/check/Makefile.am: + * tests/check/elements/decodebin.c: (src_handoff_cb), + (decodebin_new_decoded_pad_cb), (GST_START_TEST), + (decodebin_suite): + Add simple unit test for decodebin for the above. + +2006-12-16 12:22:57 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Refuse to change state to READY when we failed to create any of the required elements in our instance ... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_change_state): + * gst/playback/gstdecodebin2.c: (gst_decode_bin_change_state): + Refuse to change state to READY when we failed to create any of the + required elements in our instance init function. + +2006-12-15 10:52:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Small docs fixes/updates. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + Small docs fixes/updates. + * gst-libs/gst/video/gstvideosink.h: + Remove nonfunctional GST_VIDEO_SINK_CLOCK macro which is a leftover + from the 0.9 days (GST_BASE_SINK_CLOCK, which it points to, was + removed from the base sink API between 0.9.6 and 0.9.7). + API: add GST_VIDEO_SINK_CAST and use it for the height/width + accessor macros, so we don't do a runtime GObject type check every + time we use them. + +2006-12-15 00:20:37 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + add doap file + Original commit message from CVS: + * Makefile.am: + * gst-plugins-base.doap: + * gst-plugins-base.spec.in: + add doap file + +2006-12-09 15:12:38 +0000 Jens Granseuer <jensgr@gmx.net> + + Declare variables at the beginning of a block. Fixes #383195. + Original commit message from CVS: + Patch by: Jens Granseuer <jensgr at gmx net> + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_create): + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_handle_frame_based_buffer), + (gst_base_rtp_audio_payload_handle_sample_based_buffer): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_fixate): + Declare variables at the beginning of a block. Fixes #383195. + +2006-12-07 02:38:41 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Bump version nano - back to CVS. + Original commit message from CVS: + * configure.ac: + Bump version nano - back to CVS. + +=== release 0.10.11 === + +2006-12-07 02:30:38 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: releasing 0.10.11, "Dumb things" + Original commit message from CVS: + === release 0.10.11 === + 2006-12-06 Jan Schmidt <thaytan@mad.scientist.com> + * configure.ac: + releasing 0.10.11, "Dumb things" + +2006-12-05 12:44:00 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: Handle the case where an element has multiple pads with unfixed caps as well as still po... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (find_dynamic), (dynamic_add), + (close_pad_link), (elem_is_dynamic), (unlinked), (close_link): + Handle the case where an element has multiple pads with + unfixed caps as well as still possibly producing more dynamic + pads by storing each case as a distinct entry in the dynamic list. + Fixes #38223 again. + +2006-12-04 13:02:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Fix #382223, add more dynamic caps handling. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (close_pad_link): + Fix #382223, add more dynamic caps handling. + +2006-12-01 11:35:57 +0000 Zaheer Abbas Merali <zaheerabbas@merali.org> + + * po/.gitignore: + Ignore all pot files + Original commit message from CVS: + Ignore all pot files + +2006-12-01 10:36:50 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: Delete bad debug code. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + Delete bad debug code. + Fixes #381219 + +2006-12-01 10:27:54 +0000 Sergey Scobich <sergey.scobich@gmail.com> + + Fix compilation on win32 under VS8 + Original commit message from CVS: + * gst/videoscale/vs_4tap.c: + * win32/MANIFEST: + * win32/common/config.h: + * win32/vs8/libgstvideoscale.vcproj: + Fix compilation on win32 under VS8 + Patch by: Sergey Scobich <sergey dot scobich at gmail dot com> + Partially fixes #381175 + +2006-11-30 23:46:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-11-30 12:50:42 +0000 Michael Smith <msmith@xiph.org> + + tests/check/pipelines/theoraenc.c: It would be very bad if, after a discont buffer, we thought every single following... + Original commit message from CVS: + * tests/check/pipelines/theoraenc.c: (check_buffer_granulepos), + (GST_START_TEST): + It would be very bad if, after a discont buffer, we thought every + single following buffer was also discont. So, add to the test to + ensure that this isn't the case. + * ext/theora/theoraenc.c: (theora_enc_is_discontinuous): + ... it was the case. So fix it. + +2006-11-28 16:43:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Improve debug. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (check_queue_event): + Improve debug. + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps): + Fix width and height range from 16 - 4096 to 1 - MAXINT, just like the + padtemplate caps. Refixes #357577. + +2006-11-28 16:21:27 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Add event probe to see when EOS is in a queue and we can disable the underrun signals.... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (check_queue_event), + (queue_threshold_reached), (queue_out_of_data), + (gen_preroll_element): + Add event probe to see when EOS is in a queue and we can disable the + underrun signals. Fixes #357577. + +2006-11-28 14:40:39 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/: New decodebin2 element. + Original commit message from CVS: + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin2.c: (gst_decode_bin_get_type), + (_gst_boolean_accumulator), (gst_decode_bin_class_init), + (gst_decode_bin_factory_filter), (compare_ranks), (print_feature), + (gst_decode_bin_init), (gst_decode_bin_dispose), + (gst_decode_bin_finalize), (gst_decode_bin_set_property), + (gst_decode_bin_get_property), (gst_decode_bin_set_caps), + (gst_decode_bin_get_caps), (gst_decode_bin_autoplug_continue), + (gst_decode_bin_autoplug_sort), (analyze_new_pad), (connect_pad), + (connect_element), (expose_pad), (type_found), + (pad_added_group_cb), (pad_removed_group_cb), + (no_more_pads_group_cb), (pad_added_cb), (pad_removed_cb), + (no_more_pads_cb), (find_compatibles), (is_demuxer_element), + (are_raw_caps), (multi_queue_overrun_cb), + (multi_queue_underrun_cb), (gst_decode_group_new), + (get_current_group), (group_demuxer_event_probe), + (gst_decode_group_control_demuxer_pad), + (gst_decode_group_control_source_pad), + (gst_decode_group_check_if_blocked), + (gst_decode_group_check_if_drained), (gst_decode_group_expose), + (gst_decode_group_hide), (gst_decode_group_free), + (gst_decode_group_set_complete), (source_pad_blocked_cb), + (source_pad_event_probe), (gst_decode_pad_new), (add_fakesink), + (remove_fakesink), (find_sink_pad), (gst_decode_bin_change_state), + (plugin_init): + New decodebin2 element. + Closes #370092 + * gst/playback/gstplay-marshal.list: + Added marshallers for new signals in decodebin2 + * gst/playback/gstplaybasebin.c: (setup_subtitle), (make_decoder): + Use decodebin2 if *and only if* the USE_DECODEBIN2 environment variable + is set. + +2006-11-28 10:45:40 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Disable rtsp:// uris for the release, it's not good enough yet. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source), + (gst_play_base_bin_change_state): + Disable rtsp:// uris for the release, it's not good enough yet. + Remove unused var. + +2006-11-26 16:39:41 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Implement reverse playback. + Original commit message from CVS: + * ext/theora/theoradec.c: (gst_theora_dec_reset), + (theora_dec_push_forward), (theora_dec_push_reverse), + (theora_handle_data_packet), (theora_dec_decode_buffer), + (theora_dec_flush_decode), (theora_dec_chain_reverse), + (theora_dec_chain_forward), (theora_dec_chain): + Implement reverse playback. + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_reset), + (vorbis_dec_decode_buffer), (vorbis_dec_flush_decode), + (vorbis_dec_chain_forward): + Clear buffers used for reverse playback in _reset. + No need to set the eos flag, we clip samples using the segment. + +2006-11-24 15:40:58 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Some cleanups. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_page_copy), (gst_ogg_page_free), + (gst_ogg_pad_init), (gst_ogg_pad_dispose), (gst_ogg_pad_reset), + (gst_ogg_pad_stream_out), (gst_ogg_pad_submit_page), + (gst_ogg_chain_reset), (gst_ogg_demux_perform_seek): + Some cleanups. + Handle continued pages in reverse mode. + +2006-11-24 15:39:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Small cleanups. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_push_forward), + (vorbis_handle_data_packet), (vorbis_dec_decode_buffer), + (vorbis_dec_flush_decode): + Small cleanups. + Don't try to add invalid timestamps. + Clipping will unref the buffer. + +2006-11-24 08:56:10 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/: remove obsolete _factory_init protos + Original commit message from CVS: + * gst/adder/gstadder.h: + * gst/audiotestsrc/gstaudiotestsrc.h: + remove obsolete _factory_init protos + +2006-11-24 08:35:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: Fix spacing in debug message. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_buffer_alloc): + Fix spacing in debug message. + +2006-11-23 11:07:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Don't just ignore return values from _pad_push(). + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_page), + (gst_ogg_demux_chain): + Don't just ignore return values from _pad_push(). + Small debug improvements. + +2006-11-23 11:02:11 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggmux.c: If our incoming buffer is marked as DISCONT, then increment the page number (so that the discont... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_process_best_pad): + If our incoming buffer is marked as DISCONT, then increment the page + number (so that the discontinuity is marked in the final ogg + bitstream) and flush the previous page. + +2006-11-22 14:34:03 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/: Mark discontinuities of > 3/4 of a frame, reinit encoder. + Original commit message from CVS: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: (gst_theora_enc_init), + (theora_enc_reset), (theora_enc_clear), (theora_enc_sink_setcaps), + (theora_buffer_from_packet), (theora_enc_is_discontinuous), + (theora_enc_chain), (theora_enc_change_state): + Mark discontinuities of > 3/4 of a frame, reinit encoder. + * tests/check/pipelines/theoraenc.c: (check_buffer_granulepos), + (GST_START_TEST), (theoraenc_suite): + Enable discontinuity test, fix it. + +2006-11-21 18:39:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.*: Some textoverlay fixes: for one, in the video chain function, actually wait for a text bu... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init), + (gst_text_overlay_text_pad_unlink), (gst_text_overlay_text_event), + (gst_text_overlay_video_event), (gst_text_overlay_pop_text), + (gst_text_overlay_text_chain), (gst_text_overlay_video_chain), + (gst_text_overlay_change_state): + * ext/pango/gsttextoverlay.h: + Some textoverlay fixes: for one, in the video chain function, + actually wait for a text buffer to come in if there is none at the + moment and there should be one; also, deal more gracefully with + incoming buffers that do not have a timestamp or duration; discard + text buffer when not needed any longer. Fixes #341681. + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/textoverlay.c: + (notgst_check_setup_src_pad2), (notgst_check_teardown_src_pad2), + (setup_textoverlay), (buffer_is_all_black), (create_black_buffer), + (create_text_buffer), (cleanup_textoverlay), (GST_START_TEST), + (test_video_waits_for_text_send_text_newsegment_thread), + (test_video_waits_for_text_shutdown_element), + (test_render_continuity_push_video_buffers_thread), + (textoverlay_suite): + Add some unit tests for textoverlay. + +2006-11-21 09:29:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Avoid integer underflow when the found probability for mp3 is smaller than the '... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset): + Avoid integer underflow when the found probability for mp3 is + smaller than the 'penalty' we subtract if there's not a clean + mp3 header sync at offset 0. + +2006-11-21 08:17:16 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/gst-plugins-base-libs-sections.txt: Add some new symbols to the docs + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + Add some new symbols to the docs + +2006-11-20 16:44:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Enable ffmpegcolorspace test now that the RGBA32 issue is fixed (for now not for valgrinding though, si... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/ffmpegcolorspace.c: + (ffmpegcolorspace_suite): + Enable ffmpegcolorspace test now that the RGBA32 issue is fixed + (for now not for valgrinding though, since it takes too long). + +2006-11-20 15:01:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Fix RGBA32 caps. Fixes #357038. + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps): + Fix RGBA32 caps. Fixes #357038. + +2006-11-20 12:20:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixertrack.h: Add FIXME so we can add some padding here in 0.11 + Original commit message from CVS: + * gst-libs/gst/interfaces/mixertrack.h: + Add FIXME so we can add some padding here in 0.11 + +2006-11-19 17:07:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/rtp/gstbasertpaudiopayload.h: Fix GstBaseRTPAudioPayload structure so the whole GObject inheritance busi... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + Fix GstBaseRTPAudioPayload structure so the whole GObject + inheritance business actually works (parent class instance structure + must always come first in the derived class instance structure). + +2006-11-16 14:35:30 +0000 Tim-Philipp Müller <tim@centricular.net> + + Make sure our checks and the videotestsrc plugin link against the local uninstalled gst libs and not any installed gs... + Original commit message from CVS: + * gst/videotestsrc/Makefile.am: + * tests/check/Makefile.am: + Make sure our checks and the videotestsrc plugin link against the + local uninstalled gst libs and not any installed gst libs that + might happen to exist as well. + * tests/check/elements/adder.c: (message_received), + (test_event_message_received), (test_play_twice_message_received): + * tests/check/elements/ffmpegcolorspace.c: (GST_START_TEST): + Fix compiler warnings when compiling against core with disabled + debugging system. + +2006-11-16 12:55:08 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: Fix audiorate, so that it accurately sets offsets and timestamps. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_reset), + (gst_audio_rate_sink_event), (gst_audio_rate_chain): + Fix audiorate, so that it accurately sets offsets and timestamps. + Doesn't change the fundamental algorithmic decisions; so should be + safe. + * tests/check/Makefile.am: + Enable audiorate test now that it passes. + +2006-11-15 10:05:33 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: clear xv when going to NULL, remove // commented non-existant proto + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_change_state): + clear xv when going to NULL, remove // commented non-existant proto + * tests/examples/seek/seek.c: (main): + add missing tooltip description for scrub and play_scrub + +2006-11-14 23:34:19 +0000 David Schleef <ds@schleef.org> + + configure.ac: Bump liboil requirement to 0.3.8. + Original commit message from CVS: + * configure.ac: + Bump liboil requirement to 0.3.8. + * gst-libs/gst/riff/riff-media.c: + Add Dirac fourcc. + * gst/videoscale/vs_image.h: + * gst/videoscale/vs_scanline.h: + Use liboil's stdint.h. + * gst/videotestsrc/videotestsrc.c: + Remove liboil related ifdef's, since they aren't needed now, and + won't work with future versions. + +2006-11-14 23:08:38 +0000 David Schleef <ds@schleef.org> + + gst/videoscale/: Add a 4-tap image scaler. Theoretically looks much prettier. + Original commit message from CVS: + * gst/videoscale/Makefile.am: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/gstvideoscale.h: + * gst/videoscale/vs_4tap.c: + * gst/videoscale/vs_4tap.h: + * gst/videoscale/vs_image.c: + * gst/videoscale/vs_image.h: + * gst/videoscale/vs_scanline.c: + * gst/videoscale/vs_scanline.h: + Add a 4-tap image scaler. Theoretically looks much prettier. + The tap calculation could use some improvement. + +2006-11-14 11:54:14 +0000 Jan David Mol <j.j.d.mol@tudelft.nl> + + Various gsize and gssize printf fixes. Fixes #372507. + Original commit message from CVS: + Patch by: Jan David Mol <j dot j dot d dot mol at tudelft dot nl> + * gst-libs/gst/riff/riff-read.c: (gst_riff_parse_strf_auds), + (gst_riff_parse_strf_iavs): + * gst/subparse/gstsubparse.c: (convert_encoding): + * gst/tcp/gstmultifdsink.c: + (gst_multi_fd_sink_handle_client_write): + * gst/tcp/gsttcp.c: (gst_tcp_socket_write), (gst_tcp_socket_read), + (gst_tcp_read_buffer), (gst_tcp_gdp_read_caps), + (gst_tcp_gdp_write_buffer), (gst_tcp_gdp_write_caps): + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_render): + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new): + Various gsize and gssize printf fixes. Fixes #372507. + +2006-11-13 18:14:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.*: First stab at vorbis reverse playback. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_sink_event), + (vorbis_dec_push_forward), (vorbis_dec_push_reverse), + (vorbis_handle_data_packet), (vorbis_dec_decode_buffer), + (vorbis_dec_flush_decode), (vorbis_dec_chain_reverse), + (vorbis_dec_chain_forward), (vorbis_dec_chain): + * ext/vorbis/vorbisdec.h: + First stab at vorbis reverse playback. + +2006-11-13 17:30:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.*: Make the clock sync code more accurate wrt resampling and playback at differen... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_event), (gst_base_audio_sink_render): + * gst-libs/gst/audio/gstbaseaudiosink.h: + Make the clock sync code more accurate wrt resampling and playback + at different rates. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_commit_full), (gst_ring_buffer_commit): + * gst-libs/gst/audio/gstringbuffer.h: + Use better algorithm to interpolate sample rates. + +2006-11-13 15:31:01 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggdemux.c: Improve a debug line slightly. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_page): + Improve a debug line slightly. + * ext/ogg/gstogmparse.c: (gst_ogm_parse_plugin_init): + Call gst_riff_init() in plugin_init, to avoid getting errors from + the debug system (unrelated changes to another plugin made this turn + up; not sure why). + +2006-11-10 19:20:21 +0000 Sergey Scobich <sergery.scobich@gmail.com> + + win32/common/libgsttag.def: Add missing symbol (#366492). + Original commit message from CVS: + Patch by: Sergey Scobich <sergery.scobich at gmail com> + * win32/common/libgsttag.def: + Add missing symbol (#366492). + +2006-11-10 00:52:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreamselector.c: Don't unref a NULL pad. + Original commit message from CVS: + * gst/playback/gststreamselector.c: (gst_stream_selector_dispose): + Don't unref a NULL pad. + +2006-11-09 00:50:00 +0000 Christian Schaller <uraeus@gnome.org> + + ext/ogg/gstoggdemux.c: Implement first stab at reverse playback. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_page), + (gst_ogg_demux_get_prev_page), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_handle_page), (gst_ogg_demux_chain), + (gst_ogg_demux_loop_forward), (gst_ogg_demux_loop_reverse), + (gst_ogg_demux_loop): + Implement first stab at reverse playback. + +2006-11-07 07:22:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-media.c: add h263/h264 variants to the caps, Fixes #363118 + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + add h263/h264 variants to the caps, Fixes #363118 + +2006-11-06 18:24:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/: Use g_strerror instead of strerror so we get UTF-8. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func): + * gst-libs/gst/audio/gstaudiosrc.c: (audioringbuffer_thread_func): + Use g_strerror instead of strerror so we get UTF-8. + +2006-11-04 07:25:58 +0000 David Schleef <ds@schleef.org> + + ext/ogg/: Add/remove KW-DIRAC header here, since it is ogg-specific. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + Add/remove KW-DIRAC header here, since it is ogg-specific. + +2006-11-03 15:44:31 +0000 Michael Smith <msmith@xiph.org> + + gst/typefind/gsttypefindfunctions.c: Recognise more mpeg4 elementary video streams. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg4_video_type_find): + Recognise more mpeg4 elementary video streams. + +2006-11-02 17:26:03 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Lower the probability of mp3 typefinding functions if we don't find a valid mp3 ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset): + Lower the probability of mp3 typefinding functions if we don't find a + valid mp3 header at the start of the file. + Closes #369482 + +2006-11-02 15:06:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/: Document and partially implement an algorithm for doing reverse playback of theora video. + Original commit message from CVS: + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_init), + (theora_dec_sink_event), (theora_dec_chain_forward), + (theora_dec_flush_decode), (theora_dec_chain_reverse), + (theora_dec_chain): + Document and partially implement an algorithm for doing reverse playback + of theora video. + +2006-11-02 14:18:45 +0000 Sergey Scobich <sergey.scobich@gmail.com> + + win32/: Misc. VS8 build fixes: fix syntax in config.h, add missing entries to libgsttag.def; add missing dependencies... + Original commit message from CVS: + Patch by: Sergey Scobich <sergey.scobich at gmail com> + * win32/common/config.h: + * win32/common/interfaces-enumtypes.c: + * win32/common/libgsttag.def: + * win32/vs8/gst-plugins-base.sln: + * win32/vs8/libgstaudioresample.vcproj: + * win32/vs8/libgstinterfaces.vcproj: + * win32/vs8/libgstogg.vcproj: + * win32/vs8/libgstriff.vcproj: + * win32/vs8/libgsttag.vcproj: + * win32/vs8/libgsttheora.vcproj: + * win32/vs8/libgstvideoscale.vcproj: + * win32/vs8/libgstvorbis.vcproj: + Misc. VS8 build fixes: fix syntax in config.h, add missing entries + to libgsttag.def; add missing dependencies for some vs8 projects; + re-arrange placement of .def files in vs8 projects (#366334). + +2006-11-01 14:08:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstogg.c: Remove unused variable. + Original commit message from CVS: + * ext/ogg/gstogg.c: + Remove unused variable. + * ext/ogg/gstoggdemux.c: + Fix Wim's surname in plugin description. + +2006-10-31 15:05:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-plugins-base.spec.in: spec new .h file. Fixes #368310. + Original commit message from CVS: + * gst-plugins-base.spec.in: + spec new .h file. Fixes #368310. + +2006-10-31 14:19:07 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.*: Make using the remove or clear signals threadsafe. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_add_full), + (gst_multi_fd_sink_remove), (gst_multi_fd_sink_clear), + (gst_multi_fd_sink_get_stats), + (gst_multi_fd_sink_remove_client_link), + (gst_multi_fd_sink_queue_buffer), + (gst_multi_fd_sink_handle_clients): + * gst/tcp/gstmultifdsink.h: + Make using the remove or clear signals threadsafe. + Make calling get-stats with an invalid fd not segfault. + Fixes 368273. + +2006-10-31 10:49:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/: Fix and activate base audio payloader. + Original commit message from CVS: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + (gst_base_rtp_audio_payload_init): + Fix and activate base audio payloader. + +2006-10-28 17:22:57 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for QuickTime Image Files (see #366156). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (qtif_type_find), + (plugin_init): + Add typefinder for QuickTime Image Files (see #366156). + +2006-10-28 16:00:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioresample/gstaudioresample.c: Another typo fix (#366212). + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init): + Another typo fix (#366212). + +2006-10-27 17:13:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/volume/gstvolume.c: Use stream time to synchronize volume property instead of rather random timestamps. This is n... + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_transform_ip): + Use stream time to synchronize volume property instead of rather random + timestamps. This is needed when gnonlin does its time shifting. + +2006-10-27 16:46:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + * ChangeLog: + I'm too lazy to comment this + Original commit message from CVS: + *** empty log message *** + +2006-10-27 16:45:30 +0000 Mark Nauwelaerts <manauw@skynet.be> + + ext/ogg/gstoggmux.c: Remove the pad from the element in release_pad. + Original commit message from CVS: + Patch by: Mark Nauwelaerts <manauw at skynet dot be> + * ext/ogg/gstoggmux.c: (gst_ogg_mux_release_pad): + Remove the pad from the element in release_pad. + +2006-10-27 11:57:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/: Explicitly create our custom buffer classes at a thread-safe location as well, since g_type_class_ref() doesn't... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_get_type): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_type): + Explicitly create our custom buffer classes at a thread-safe + location as well, since g_type_class_ref() doesn't seem to be + entirely thread-safe either (#365501; also see #349410). + +2006-10-26 10:49:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-read.c: If strings in INFO chunk are not UTF-8, do something similar to what we do for ID3v1 t... + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: (freeform_string_to_utf8), + (gst_riff_parse_info): + If strings in INFO chunk are not UTF-8, do something similar to + what we do for ID3v1 tags: check a number of environment variables + (GST_AVI_TAG_ENCODING, GST_RIFF_TAG_ENCODING, GST_TAG_ENCODING) for + character sets to try, otherwise try the current locale and/or fall + back on ISO-8859-1. Fixes #360552. + +2006-10-23 12:46:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/: Add a bunch of exciting new checkers patterns. + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_pattern_get_type), + (gst_video_test_src_set_pattern): + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: (gst_video_test_src_checkers1), + (gst_video_test_src_checkers2), (gst_video_test_src_checkers4), + (gst_video_test_src_checkers8): + * gst/videotestsrc/videotestsrc.h: + Add a bunch of exciting new checkers patterns. + +2006-10-23 12:06:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/: Add support for TMPlayer-type subtitles (#362845). + Original commit message from CVS: + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect), + (gst_sub_parse_format_autodetect), (handle_buffer), + (gst_sub_parse_chain), (gst_subparse_type_find), (plugin_init): + * gst/subparse/gstsubparse.h: + * gst/subparse/tmplayerparse.c: (tmplayer_parse_line), + (parse_tmplayer): + * gst/subparse/tmplayerparse.h: + Add support for TMPlayer-type subtitles (#362845). + * tests/check/elements/subparse.c: (test_tmplayer_do_test), + (GST_START_TEST), (subparse_suite): + Add some basic unit tests for the above. + +2006-10-23 11:47:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/audiorate.c: More tests for audiorate: inject buffers to check behaviour when buffers overlap. + Original commit message from CVS: + * tests/check/elements/audiorate.c: (test_injector_base_init), + (test_injector_class_init), (test_injector_chain), + (test_injector_init), (probe_cb), (do_perfect_stream_test), + (GST_START_TEST), (audiorate_suite): + More tests for audiorate: inject buffers to check behaviour when + buffers overlap. + +2006-10-21 16:39:54 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add some basic unit tests for audiorate. Disabled at the moment since it doesn't pass yet (see bug #363... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/audiorate.c: (probe_cb), (got_buf), + (do_perfect_stream_test), (GST_START_TEST), (audiorate_suite): + Add some basic unit tests for audiorate. Disabled at the moment + since it doesn't pass yet (see bug #363119). + +2006-10-20 17:02:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Add missing closing tags for markup and fix broken markup, otherwise pango won't render a... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (subrip_fix_up_markup), + (parse_subrip), (handle_buffer): + Add missing closing tags for markup and fix broken markup, + otherwise pango won't render anything (fixes #357531). Also, + make sure the text we send out is always NUL-terminated + (better safe than sorry etc.). + * tests/check/elements/subparse.c: (test_srt_do_test), + (test_srt): + Some more tests for .srt incl. tests for the above stuff. + +2006-10-20 13:56:55 +0000 Stefan Kost <ensonic@users.sf.net> + + sys/: Try to redraw borders only when needed. Apparently this consumes resources on small devices... :-O (#363607) + Original commit message from CVS: + 2006-10-20 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_put): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put): + Patch by: Stefan Kost <ensonic@users.sf.net> + Try to redraw borders only when needed. Apparently this consumes + resources on small devices... :-O (#363607) + +2006-10-20 13:54:19 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.c: If caps change, then update the client's idea of the caps so that we don't end up re-sendin... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: + (gst_multi_fd_sink_client_queue_buffer): + If caps change, then update the client's idea of the caps so that we + don't end up re-sending streamheaders for every single buffer after + the caps change. + +2006-10-20 12:31:02 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggparse.c: Set caps on pushed buffers; fix up refcounting of caps objects. + Original commit message from CVS: + * ext/ogg/gstoggparse.c: (gst_ogg_parse_dispose), + (gst_ogg_parse_append_header), (gst_ogg_parse_chain): + Set caps on pushed buffers; fix up refcounting of caps objects. + +2006-10-19 14:09:30 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Typefind mmsh header data packet to application/x-mmsh (#362625). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mmsh_type_find), + (plugin_init): + Typefind mmsh header data packet to application/x-mmsh (#362625). + +2006-10-19 09:17:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add very simple unit test for subparse. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/subparse.c: (buffer_from_static_string), + (setup_subparse), (teardown_subparse), (test_srt_do_test), + (GST_START_TEST), (subparse_suite): + Add very simple unit test for subparse. + +2006-10-19 09:00:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Strip trailing newlines from subtitle text output. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (strip_trailing_newlines), + (parse_subrip): + Strip trailing newlines from subtitle text output. + +2006-10-18 18:40:12 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Fix memleak; clear subparse->textbuf n state change function. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (gst_sub_parse_change_state): + Fix memleak; clear subparse->textbuf n state change function. + +2006-10-18 15:13:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Don't require subrip (.srt) files to start with a chunk number of 1. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect): + Don't require subrip (.srt) files to start with a chunk number of 1. + +2006-10-18 13:42:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.*: Extract rate from the NEWSEGMENT event. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_event), (gst_base_audio_sink_render): + * gst-libs/gst/audio/gstbaseaudiosink.h: + Extract rate from the NEWSEGMENT event. + Use commit_full to also take rate adjustment into account when writing + samples to the ringbuffer. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_commit_full), (gst_ring_buffer_commit), + (gst_ring_buffer_read): + * gst-libs/gst/audio/gstringbuffer.h: + Added _commit_full() to also take rate into account. + Use simple interpolation algorithm to resample audio. + API: gst_ring_buffer_commit_full() + * tests/examples/seek/scrubby.c: (speed_cb), (do_seek): + * tests/examples/seek/seek.c: (segment_done): + Don't try to seek with 0.0 rate, just pause instead. + Remove bogus debug line. + +2006-10-18 12:57:54 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Catch async errors when starting up the subtitle bin, so we can stop waiting and conti... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (subbin_startup_sync_msg), + (setup_source): + Catch async errors when starting up the subtitle bin, so we can + stop waiting and continue with the main film instead of hanging + forever. Fixes #339366. + * tests/check/elements/playbin.c: (playbin_suite): + Enable unit test for the above. + +2006-10-18 09:53:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Some small and basic unit tests for playbin; not very useful yet, but at least a start. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/playbin.c: (GST_START_TEST), + (gst_red_video_src_uri_get_type), + (gst_red_video_src_uri_get_protocols), + (gst_red_video_src_uri_get_uri), (gst_red_video_src_uri_set_uri), + (gst_red_video_src_uri_handler_init), + (gst_red_video_src_init_type), (gst_red_video_src_base_init), + (gst_red_video_src_create), (gst_red_video_src_class_init), + (gst_red_video_src_init), (plugin_init), (playbin_suite): + Some small and basic unit tests for playbin; not very useful yet, + but at least a start. + +2006-10-18 09:46:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: The old pad activation spiel. + Original commit message from CVS: + * gst/playback/gstplaybin.c: (setup_sinks): + The old pad activation spiel. + +2006-10-18 09:31:49 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Don't hang forever if the subbin already fails to start up in the state change to PAUS... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source): + Don't hang forever if the subbin already fails to start up in + the state change to PAUSED (#339366). + +2006-10-17 17:17:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/tuner.c: Fix some function guards, add some more function guards. + Original commit message from CVS: + * gst-libs/gst/interfaces/tuner.c: (gst_tuner_list_channels), + (gst_tuner_set_channel), (gst_tuner_get_channel), + (gst_tuner_list_norms), (gst_tuner_set_norm), (gst_tuner_get_norm), + (gst_tuner_set_frequency), (gst_tuner_get_frequency), + (gst_tuner_signal_strength), (gst_tuner_find_norm_by_name), + (gst_tuner_find_channel_by_name): + Fix some function guards, add some more function guards. + +2006-10-17 11:34:32 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: Don't return a pad from get_our_ghost_pad unless it is actually the one we want. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (get_our_ghost_pad), + (remove_element_chain): + Don't return a pad from get_our_ghost_pad unless it is actually the + one we want. + Change a cast in remove_element_chain slightly. + +2006-10-13 15:20:29 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Segment seeking needs to use the rate and set stop to -1. + Original commit message from CVS: + 2006-10-13 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (do_seek), (start_seek), + (rate_spinbutton_changed_cb), (segment_done), + (msg_state_changed): + Segment seeking needs to use the rate and set stop to -1. + +2006-10-13 14:15:42 +0000 Ville Syrjala <ville.syrjala@movial.fi> + + gst-libs/gst/audio/gstbaseaudiosink.c: Don't crash when ringbuffer is not yet created. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_setcaps): + Don't crash when ringbuffer is not yet created. + Patch by: Ville Syrjala <ville dot syrjala at movial dot fi> + Fixes #361634. + * gst/playback/gstplaybasebin.c: (new_decoded_pad_full): + * gst/playback/gststreamselector.c: + (gst_stream_selector_request_new_pad): + Activate pads befre adding them to running elements. + +2006-10-13 11:25:10 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Stop the scale updater when we start grabing the slider. Don't wait for the pipeline to b... + Original commit message from CVS: + 2006-10-13 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (do_seek), (start_seek), + (rate_spinbutton_changed_cb), (msg_state_changed): Stop the + scale + updater when we start grabing the slider. Don't wait for the + pipeline to be PAUSED. + +2006-10-13 08:57:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/mixer.c: Guard mixer interface functions against bogus arguments. + Original commit message from CVS: + * gst-libs/gst/interfaces/mixer.c: (gst_mixer_list_tracks), + (gst_mixer_set_volume), (gst_mixer_get_volume), + (gst_mixer_set_mute), (gst_mixer_set_option), + (gst_mixer_get_option), (gst_mixer_mute_toggled), + (gst_mixer_record_toggled), (gst_mixer_volume_changed), + (gst_mixer_option_changed): + Guard mixer interface functions against bogus arguments. + +2006-10-12 19:39:07 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: Use state-changed messages to trigger start/stop of scale update timer. Indeed the scale ... + Original commit message from CVS: + 2006-10-12 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (do_seek), (start_seek), + (stop_seek), + (play_cb), (pause_cb), (stop_cb), + (rate_spinbutton_changed_cb), + (msg_state_changed), (main): Use state-changed messages to + trigger + start/stop of scale update timer. Indeed the scale slider was + jumping here and there because the update timer was activated + before seek completed. This fixes instant applying of rate + changes + by pressing the spinbutton like a crazy man ! + +2006-10-12 19:09:06 +0000 Sebastien Cote <sebas642@yahoo.ca> + + gst-libs/gst/rtp/gstbasertppayload.c: Fix two small memory leaks (#361456). + Original commit message from CVS: + Patch by: Sebastien Cote <sebas642 at yahoo.ca> + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_init), + (gst_basertppayload_finalize): + Fix two small memory leaks (#361456). + +2006-10-10 18:56:01 +0000 Julien Moutte <julien@moutte.net> + + tests/examples/seek/seek.c: When changing spinbutton we try to change the rate on the fly. + Original commit message from CVS: + 2006-10-10 Julien MOUTTE <julien@moutte.net> + * tests/examples/seek/seek.c: (do_seek), + (rate_spinbutton_changed_cb): When changing spinbutton we try + to change the rate on the fly. + +2006-10-10 16:50:06 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/: Add WMS caps. + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Add WMS caps. + +2006-10-10 12:49:03 +0000 Josep Torre Valles <josep@fluendo.com> + + ext/gnomevfs/: Fix URI interface implementation return type. + Original commit message from CVS: + 2006-10-10 Zaheer Abbas Merali <zaheerabbas at merali dot org> + Patch by: Josep Torre Valles <josep@fluendo.com> + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + Fix URI interface implementation return type. + * ext/pango/gsttextoverlay.c: (gst_text_overlay_set_property): + Fix what looks like a copy/paste issue when assigning values. + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + (gst_audio_filter_template_get_type): + Cast to prevent Forte warnings. + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_create): + Fix URI interface implementation return type. + gst_pad_query_position requires a signed integer pointer as + 3rd parameter, GstClockTime is unsigned. + * gst/audioconvert/audioconvert.c: + Fix integer overflow when treated as signed. + * gst/audioresample/resample.c: (resample_add_input_data): + Cast to prevent warnings on Forte. + * gst/ffmpegcolorspace/imgconvert.c: (build_rgb_palette): + Fix integer overflow when treated as signed. + * gst/ffmpegcolorspace/imgconvert_template.h: + Fix integer overflow when treated as signed. RGBA_OUT shifts bits. + * gst/playback/gstdecodebin.c: (queue_filled_cb), + (cleanup_decodebin): + Who initialises a guint to -1! + Cast function pointers to prevent warnings on Forte. + * gst/playback/gstplaybasebin.c: (queue_deadlock_check), + (queue_threshold_reached): + Cast function pointers correctly to prevent warnings on Forte. + * gst/playback/gststreaminfo.c: (gst_stream_info_dispose): + Cast function pointers correctly to prevent warnings on Forte. + * gst/subparse/gstssaparse.c: (gst_ssa_parse_setcaps): + Obvious change to unsigned, 0xEF > max signed char. + * gst/tcp/gstmultifdsink.c: (get_buffers_max), (count_burst_unit): + GstClockTime is unsigned, initialise correctly. + * gst/tcp/gsttcp.c: (gst_tcp_socket_write): + Cast so pointer arithemetic doesn't cause warnings on Forte. + * gst/videorate/gstvideorate.c: + Use correct return value. + * tests/examples/seek/scrubby.c: + GstClockTime is unsigned, initialise correctly. + +2006-10-10 11:20:03 +0000 Ferenc Gerlits <fgerlits@gmail.com> + + gst/typefind/gsttypefindfunctions.c: Recognise XML files and XML-like files shorter than 256 bytes as well (fixes #35... + Original commit message from CVS: + Patch by: Ferenc Gerlits <fgerlits at gmail com> + * gst/typefind/gsttypefindfunctions.c: + Recognise XML files and XML-like files shorter than 256 bytes as + well (fixes #359237). + +2006-10-09 15:01:30 +0000 Edgard Lima <edgard.lima@indt.org.br> + + * ChangeLog: + * common: + * gst/typefind/gsttypefindfunctions.c: + Added typefind functions to video/x-nuv media. + Original commit message from CVS: + Added typefind functions to video/x-nuv media. + +2006-10-08 16:59:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/xoverlay.c: Some more guards against invalid input. + Original commit message from CVS: + * gst-libs/gst/interfaces/xoverlay.c: + (gst_x_overlay_set_xwindow_id), (gst_x_overlay_expose): + Some more guards against invalid input. + +2006-10-07 18:35:39 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Useless goto. + Original commit message from CVS: + 2006-10-07 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_text_event): + Useless goto. + * tests/examples/seek/seek.c: (do_seek), + (rate_spinbutton_changed_cb), (main): Add a rate spinbutton in + seek example to experiment with rates != 1.0 (reverse playback + !) + +2006-10-06 19:20:53 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/interfaces/xoverlay.c: Unref message in doc-example (spotted by Robert McQueen) + Original commit message from CVS: + * gst-libs/gst/interfaces/xoverlay.c: + Unref message in doc-example (spotted by Robert McQueen) + +2006-10-06 17:04:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/typefind/gsttypefindfunctions.c: printf fix. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset), + (mpeg1_parse_header), (mpeg1_sys_type_find): + printf fix. + +2006-10-06 14:37:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/: Activate dynamic pads before adding them to the element. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (close_pad_link): + * gst/playback/gstplaybasebin.c: (new_decoded_pad_full): + Activate dynamic pads before adding them to the element. + +2006-10-06 14:04:53 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/floatcast/floatcast.h: Fix obviously-bogus macros; use the correct types. + Original commit message from CVS: + * gst-libs/gst/floatcast/floatcast.h: + Fix obviously-bogus macros; use the correct types. + +2006-10-06 13:34:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Also call parent state change function to activate pads. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_change_state): + Also call parent state change function to activate pads. + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset), + (mpeg1_parse_header), (mpeg1_sys_type_find): + Add some more debug info in mpeg typefinding. + +2006-10-06 12:57:10 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoradec.c: Zero byte theora packets are valid and well-defined; don't warn on them. + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_chain): + Zero byte theora packets are valid and well-defined; don't warn on + them. + +2006-10-06 10:04:14 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gstmultifdsink.c: API: add dropped_buffers to the get-stats GValueArray + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_get_stats), (find_limits), + (gst_multi_fd_sink_queue_buffer): + API: add dropped_buffers to the get-stats GValueArray + +2006-10-05 15:55:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + Printf format fixes. + Original commit message from CVS: + * ext/alsa/gstalsadeviceprobe.c: + (gst_alsa_device_property_probe_get_values): + * ext/alsa/gstalsasink.c: (set_hwparams): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain_elem_pad), + (gst_ogg_chain_new_stream), (gst_ogg_demux_read_chain): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_send_headers), + (gst_ogg_mux_process_best_pad): + * ext/ogg/gstoggparse.c: (gst_ogg_parse_new_stream), + (gst_ogg_parse_chain): + * ext/ogg/gstogmparse.c: (gst_ogm_parse_stream_header): + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_setup), + (gst_vorbis_enc_buffer_check_discontinuous): + * ext/vorbis/vorbisparse.c: (vorbis_parse_src_query): + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_handle_track_seek): + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_push_full): + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push): + * gst/audioresample/resample.c: (resample_input_pushthrough): + * gst/playback/gstplaybasebin.c: (queue_out_of_data): + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_handle_clients): + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset), + (wavpack_type_find): + * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_create): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimagesink_check_xshm_calls), (gst_xvimagesink_xvimage_new): + * tests/check/elements/volume.c: (GST_START_TEST): + Printf format fixes. + +2006-10-04 13:18:57 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gsttcp.c: Fix a simple mistake (see the docs) + Original commit message from CVS: + * gst/tcp/gsttcp.c: (gst_tcp_gdp_read_caps): + Fix a simple mistake (see the docs) + Fixes #359580 + +2006-10-04 13:15:36 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * win32/common/config.h: + bump version + Original commit message from CVS: + bump version + +2006-10-03 12:11:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/plugins/: Add vorbistag element to docs; update version numbers to 0.10.10.1. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Add vorbistag element to docs; update version numbers to 0.10.10.1. + +2006-10-03 11:51:48 +0000 James Doc Livingston <doclivingston@gmail.com> + + ext/vorbis/: Add new vorbistag element which derives from vorbisparse and is essentially the same as well, only that ... + Original commit message from CVS: + Patch by: James "Doc" Livingston <doclivingston at gmail com> + * ext/vorbis/Makefile.am: + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisparse.c: (gst_vorbis_parse_class_init), + (vorbis_parse_parse_packet), (vorbis_parse_chain): + * ext/vorbis/vorbisparse.h: + * ext/vorbis/vorbistag.c: (gst_vorbis_tag_base_init), + (gst_vorbis_tag_class_init), (gst_vorbis_tag_init), + (gst_vorbis_tag_parse_packet): + * ext/vorbis/vorbistag.h: + Add new vorbistag element which derives from vorbisparse + and is essentially the same as well, only that it implements + the GstTagSetter interface and can modify the stream's + vorbiscomment on the fly (#335635). + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/vorbistag.c: (setup_vorbistag), + (cleanup_vorbistag), (buffer_probe), (start_pipeline), + (get_buffer), (stop_pipeline), (_create_codebook_header_buffer), + (_create_audio_buffer), (GST_START_TEST), (vorbistag_suite): + Add unit test for new vorbistag element. + +2006-10-03 10:36:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/vorbis/vorbisparse.c: Set BOS flag in packet structure to fix 'jump depends on unitialized value' errors in valgr... + Original commit message from CVS: + * ext/vorbis/vorbisparse.c: (gst_vorbis_parse_init), + (vorbis_parse_push_headers), (vorbis_parse_chain): + Set BOS flag in packet structure to fix 'jump depends + on unitialized value' errors in valgrind; various minor + clean-ups. + +2006-09-30 15:30:07 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: Fix typo in a debug statement. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (close_pad_link): + Fix typo in a debug statement. + * gst/playback/gstplaybasebin.c: (probe_triggered), + (new_decoded_pad_full), (new_decoded_pad), (subs_new_decoded_pad), + (gen_source_element), (source_new_pad), (analyse_source), + (setup_source): + When handling no_more_pads in new_decoded_pad, make sure to treat + subtitle pads correctly. Fixes playback with subtitle files. + Move a recurring message to LOG level. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + The maximum value for the Xv colorkey on this Radeon is 0xFFFFFFFF, + which ends up as -1 when cast to an int. Make the logic handle the + max value as an unsigned mask and only change the colorkey when it's + a value we recognise. + +2006-09-30 00:14:20 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Removed empty * between paragraphs + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + Removed empty * between paragraphs + +2006-09-29 23:50:53 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/: Moved some documentation into .c file + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/README: + Moved some documentation into .c file + +2006-09-29 17:35:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Fix compilation. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (no_more_pads): + Fix compilation. + +2006-09-29 16:04:05 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Remove g_print + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (new_caps): + Remove g_print + * gst/playback/gstplaybin.c: + Add some docs. + +2006-09-29 15:16:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Re-enable cddabasesrc test to see if it works again now. + Original commit message from CVS: + * tests/check/Makefile.am: + Re-enable cddabasesrc test to see if it works again + now. + +2006-09-29 13:46:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Handle invalid URIs a bit more gracefully. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_subtitle), + (gen_source_element): + Handle invalid URIs a bit more gracefully. + +2006-09-29 12:54:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/oggmux.c: Remove obsolete comment. + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: + Remove obsolete comment. + +2006-09-29 10:43:05 +0000 James Doc Livingston <doclivingston@gmail.com> + + ext/ogg/gstoggmux.c: Commit patch from James "Doc" Livingston, adds proper EOS handling in oggmux. GStreamer can, for... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_request_new_pad), + (gst_ogg_mux_release_pad), (gst_ogg_mux_push_buffer), + (gst_ogg_mux_compare_pads), (gst_ogg_mux_queue_pads), + (gst_ogg_mux_send_headers), (gst_ogg_mux_process_best_pad), + (gst_ogg_mux_collected): + Commit patch from James "Doc" Livingston, adds proper EOS handling + in oggmux. GStreamer can, for the first time ever, create a valid + Ogg file! Yay! + * tests/check/pipelines/oggmux.c: (check_chain_final_state), + (oggmux_suite): + Reenable tests now that they pass. + +2006-09-29 08:20:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.c: Stop reading commands when EOF (we read 0) as well. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_handle_clients): + Stop reading commands when EOF (we read 0) as well. + +2006-09-28 15:29:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Implement delayed caps linking needed for element with a lot of different caps on the sr... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (dynamic_create), (dynamic_free), + (close_pad_link), (dynamic_remove), (no_more_pads), (new_caps), + (find_dynamic), (unlinked), (close_link): + Implement delayed caps linking needed for element with a lot of + different caps on the src pads that get fixed at runtime. + Improve management of dynamic elements. + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_init), + (group_destroy), (group_commit), (check_queue), (queue_overrun), + (gen_preroll_element), (remove_groups), (unknown_type), + (add_element_stream), (no_more_pads_full), (no_more_pads), + (sub_no_more_pads), (source_no_more_pads), (preroll_unlinked), + (new_decoded_pad), (setup_subtitle), (array_has_value), + (gen_source_element), (source_new_pad), (has_all_raw_caps), + (analyse_source), (remove_decoders), (make_decoder), + (remove_source), (setup_source), (finish_source), (prepare_output), + (gst_play_base_bin_change_state): + * gst/playback/gstplaybasebin.h: + Use more _CAST instead of full type checking casts. + Small cleanups, plug some leaks. + Handle dynamic sources. + Add some helper functions to create lists of strings used for + blacklisting and other stuff. + Refactor some code dealing with analysing the source. + Re-enable sources without pads (like cd:// or other selfcontained + elements). + +2006-09-28 15:08:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: When we have a timestamp, we can still perform clipping. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + When we have a timestamp, we can still perform clipping. + When we have no clock, we must play the sample ASAP. + +2006-09-28 11:46:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiorate/gstaudiorate.c: Set caps on outgoing buffers. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + Set caps on outgoing buffers. + * gst/videorate/gstvideorate.c: (gst_video_rate_flush_prev), + (gst_video_rate_event), (gst_video_rate_chain): + * gst/videorate/gstvideorate.h: + Fix videorate some more. Fixes #357977 + +2006-09-28 11:34:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/adder.c: Don't set timeout to 6 seconds when we're running in valgrind ... (and how is 6 seconds... + Original commit message from CVS: + * tests/check/elements/adder.c: (adder_suite): + Don't set timeout to 6 seconds when we're running + in valgrind ... (and how is 6 seconds longer than + the default anyway?) + +2006-09-28 10:49:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiorate/gstaudiorate.c: Keep sink and src segment to keep track of time and support more input formats. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_reset), + (gst_audio_rate_sink_event), (gst_audio_rate_convert), + (gst_audio_rate_convert_segments), (gst_audio_rate_chain): + Keep sink and src segment to keep track of time and support more + input formats. + Fix bogus next_offset and run_time calculation, don't understand how + this could have worked before. Fixes #357976. + Remove some unneeded vars. + +2006-09-28 09:41:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Only remove visualisation from visbin if there is a visbin (or: don't throw warnings when ... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (remove_sinks): + Only remove visualisation from visbin if there is a visbin (or: + don't throw warnings when closing totem without playing a file). + +2006-09-27 13:52:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Add some more info in a WARNING. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + Add some more info in a WARNING. + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_create): + Handle PAUSE in create function, use new -core addition to + wait for playing. Fixes pausing and resuming capture from an + audiosrc. + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_commit), + (gst_ring_buffer_read): + Constify some more. + Caller supports interrupted reads now. + +2006-09-27 13:29:49 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + add new header file to spec + Original commit message from CVS: + add new header file to spec + +2006-09-27 12:55:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Another attempt to make the gen64 buildbot happy. + Original commit message from CVS: + * tests/check/Makefile.am: + Another attempt to make the gen64 buildbot happy. + +2006-09-27 11:58:17 +0000 Jonathan Matthew <jonathan@kaolin.wh9.net> + + ext/libvisual/visual.c: Libvisual plugin was not passing audio data to libvisual 0.4.0 correctly. Fixes #357800 + Original commit message from CVS: + Patch by: Jonathan Matthew <jonathan@kaolin.wh9.net> + * ext/libvisual/visual.c: (gst_visual_clear_actors), + (gst_visual_chain), (gst_visual_change_state): + Libvisual plugin was not passing audio data to libvisual 0.4.0 + correctly. Fixes #357800 + +2006-09-27 11:31:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/simple-launch-lines.c: Add timeout to _get_state() so we see which pipeline it is that causes t... + Original commit message from CVS: + * tests/check/pipelines/simple-launch-lines.c: (run_pipeline): + Add timeout to _get_state() so we see which pipeline it is + that causes trouble on the gen64 build bot. + +2006-09-27 11:06:54 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: the source pad always uses fixed caps. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_init), (gst_base_rtp_depayload_push_full), + (gst_base_rtp_depayload_push_ts), (gst_base_rtp_depayload_process), + (gst_base_rtp_depayload_set_gst_timestamp): + the source pad always uses fixed caps. + +2006-09-27 11:05:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + Added docs for the audio libs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/gstaudioclock.c: + * gst-libs/gst/audio/gstaudioclock.h: + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosink.h: + * gst-libs/gst/audio/gstaudiosrc.c: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + * gst-libs/gst/audio/gstbaseaudiosink.h: + * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_init): + * gst-libs/gst/audio/gstbaseaudiosrc.h: + * gst-libs/gst/audio/gstringbuffer.h: + Added docs for the audio libs. + +2006-09-27 10:59:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Temporarily disable test that fails on the bots for unknown reasons. + Original commit message from CVS: + * tests/check/Makefile.am: + Temporarily disable test that fails on the bots for unknown reasons. + +2006-09-27 00:13:29 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpaudiopayload.*: Moved AudioCodecType into priv + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + Moved AudioCodecType into priv + Renamed all gst_basertpaudiopayload to gst_base_rtp_audio_payload prefixes + +2006-09-25 15:47:25 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Cleanups and small leak fixes. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter), + (add_fakesink), (remove_fakesink), (pad_probe), (close_pad_link), + (is_demuxer_element), (try_to_link_1), (get_our_ghost_pad), + (new_pad): + Cleanups and small leak fixes. + Added Depayloaders to valid list of autopluggable elements. + +2006-09-25 13:24:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin.c: Detect NO_PREROLL state change returns and disable clock distribution to the sinks so that... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (gst_play_bin_vis_blocked), (gst_play_bin_set_property), + (gen_video_element), (gen_text_element), (gen_audio_element), + (gen_vis_element), (remove_sinks), (add_sink), (setup_sinks), + (gst_play_bin_set_clock_func), (gst_play_bin_change_state): + Detect NO_PREROLL state change returns and disable clock distribution to + the sinks so that sync is disabled. + Avoid some type checking and do simple casts instead. + Small cleanups, fix some FIXMEs. + Be more robust when linking user specified elements, catch an report + errors. Fixes #357404. + Fix some leaks in the error paths. + +2006-09-25 12:55:04 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + * ChangeLog: + ChangeLog surgery for missing bug-number + Original commit message from CVS: + ChangeLog surgery for missing bug-number + +2006-09-25 11:28:15 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst/playback/test.c: Fix compilation with uClibc and -Werror (#357591). + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst/playback/test.c: + Fix compilation with uClibc and -Werror (#357591). + +2006-09-25 10:21:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Parse dates that are followed by a time as well (#357532). + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + Parse dates that are followed by a time as well (#357532). + * tests/check/libs/tag.c: (test_vorbis_tags): + Add unit test for this. + +2006-09-23 15:24:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: A few array const-ifications. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes), + (gst_audio_convert_transform_caps): + * gst/videotestsrc/videotestsrc.c: (gst_video_test_src_unicolor): + * gst/videotestsrc/videotestsrc.h: + A few array const-ifications. + +2006-09-23 15:02:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: See if this makes the build bots happy. + Original commit message from CVS: + * tests/check/Makefile.am: + See if this makes the build bots happy. + * tests/check/libs/cddabasesrc.c: + UTF8-ise my name. + +2006-09-23 14:30:53 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: More case-insensitivity for certain tags; recognise entities with decimal codes as special ... + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian dot net> + * gst/subparse/samiparse.c: (handle_start_font), + (fix_invalid_entities): + More case-insensitivity for certain tags; recognise entities with + decimal codes as special entities as well (#357330). + +2006-09-23 13:32:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/Makefile.am: Need to build tag directory before cdda. + Original commit message from CVS: + * gst-libs/gst/Makefile.am: + Need to build tag directory before cdda. + +2006-09-23 13:21:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + Move GST_TAG_CDDA_* tags into libgsttag and make libgstcddabasesrc depend on libgsttag. This is required so we can ex... + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_base_init): + * gst-libs/gst/cdda/gstcddabasesrc.h: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: (gst_tag_register_tags_internal), + (gst_tag_register_musicbrainz_tags): + Move GST_TAG_CDDA_* tags into libgsttag and make libgstcddabasesrc + depend on libgsttag. This is required so we can extract/read tags like + DISCID without depending on libgstcddabasesrc (which used to register + them). + * gst-libs/gst/tag/gstvorbistag.c: + Add vorbiscomment mapping for CDDB_DISCID and MUSICBRAINZ_DISCID + tags (also see #347848). + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_metadata_set1): + Log vorbis comments we are actually writing. Const-ify array. + +2006-09-23 08:53:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Improve buffering a bit by avoiding a deadlock because we cannot assume the underrun i... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gen_preroll_element): + Improve buffering a bit by avoiding a deadlock because we cannot assume + the underrun is always called. + +2006-09-23 08:51:14 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst-libs/gst/riff/: Added MPEG-4 AAC and id and caps. Fixes #357289 + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian dot net> + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Added MPEG-4 AAC and id and caps. Fixes #357289 + Added WMA9 Lossless id. + +2006-09-22 14:50:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Fix misleading docs addition. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: + Fix misleading docs addition. + * tests/check/elements/videotestsrc.c: (check_rgb_buf): + Get rid of compiler warning the right way. + +2006-09-22 14:13:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Small cleanups. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_finalize), + (gst_base_rtp_depayload_setcaps), (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_push_full), + (gst_base_rtp_depayload_push_ts), (gst_base_rtp_depayload_push), + (gst_base_rtp_depayload_process), + (gst_base_rtp_depayload_set_gst_timestamp), + (gst_base_rtp_depayload_queue_release): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Small cleanups. + Fix some leaks. + Refactored the process method and added methods to push from the process + vmethod. + Use _scale functions. + API: gst_base_rtp_depayload_push_ts + API: gst_base_rtp_depayload_push + * gst-libs/gst/rtp/gstbasertppayload.c: (gst_basertppayload_push): + timestamps are uint. + +2006-09-22 11:59:00 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/interfaces/xoverlay.c: Remove unused statement from doc example. + Original commit message from CVS: + * gst-libs/gst/interfaces/xoverlay.c: + Remove unused statement from doc example. + +2006-09-22 09:52:21 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/videorate/gstvideorate.c: + update docs + Original commit message from CVS: + update docs + +2006-09-21 13:49:47 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/interfaces/videoorientation.c: Add since tags to new API docs, ChangeLog surgery (forgot API keyword in ... + Original commit message from CVS: + * gst-libs/gst/interfaces/videoorientation.c: + (gst_video_orientation_iface_init), + (gst_video_orientation_get_hflip), + (gst_video_orientation_get_vflip), + (gst_video_orientation_get_hcenter), + (gst_video_orientation_get_vcenter), + (gst_video_orientation_set_hflip), + (gst_video_orientation_set_vflip), + (gst_video_orientation_set_hcenter), + (gst_video_orientation_set_vcenter): + Add since tags to new API docs, ChangeLog surgery (forgot API keyword + in ChangeLog) + +2006-09-21 09:27:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: but disable for now since it doesn't pass (something wrong with + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/.cvsignore: + * tests/check/elements/ffmpegcolorspace.c: (rgb_format_to_caps), + (create_rgb_conversions), (rgb_conversion_free), + (right_shift_colour), (fix_expected_colour), (check_rgb_buf), + (got_buf_cb), (GST_START_TEST), (ffmpegcolorspace_suite): + Add unit test for ffmpegcolorspace (RGB <=> RGB only so far), + but disable for now since it doesn't pass (something wrong with + RGBA somewhere). + +2006-09-21 07:01:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Refactor handling of overrun detection. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (group_commit), + (queue_deadlock_check), (queue_overrun), (queue_threshold_reached), + (queue_out_of_data), (gen_preroll_element), + (preroll_remove_overrun), (probe_triggered): + Refactor handling of overrun detection. + Separate handling of group completion and deadlock detection when doing + network buffering. This should fix some deadlocks that were not detected + because the group was completed. + Add more comments, improve debugging. + +2006-09-21 05:31:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/: Some more compilation fixes. + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (GST_START_TEST): + * tests/check/libs/audio.c: + Some more compilation fixes. + +2006-09-21 05:12:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Early morning compilation fix. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_samples_done), (gst_ring_buffer_commit), + (gst_ring_buffer_read): + Early morning compilation fix. + +2006-09-20 18:09:43 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + bump nano + Original commit message from CVS: + bump nano + +2006-09-20 17:04:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/: Fix some warnings. + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (GST_START_TEST): + * tests/check/elements/multifdsink.c: (GST_START_TEST): + * tests/check/elements/videorate.c: (GST_START_TEST): + * tests/check/libs/cddabasesrc.c: (GST_START_TEST): + * tests/check/pipelines/oggmux.c: (eos_buffer_probe): + Fix some warnings. + +2006-09-20 10:59:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: change colorkey behaviour back according to #354773 comment 6/7 + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_get_times): + change colorkey behaviour back according to #354773 comment 6/7 + +2006-09-20 10:42:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery: remove junk + Original commit message from CVS: + ChangeLog surgery: remove junk + +2006-09-19 11:31:06 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.*: Implement stubbed out properties unit-type, units-soft-max, units-max, to allow specifying ... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_sync_method_get_type), + (gst_multi_fd_sink_class_init), (get_buffers_max), (find_limits), + (gst_multi_fd_sink_recover_client), + (gst_multi_fd_sink_queue_buffer), (gst_multi_fd_sink_set_property), + (gst_multi_fd_sink_get_property): + * gst/tcp/gstmultifdsink.h: + Implement stubbed out properties unit-type, units-soft-max, + units-max, to allow specifying maximum sizes in units other than + buffers. + Fixes #355935 + +2006-09-19 10:23:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-media.c: Reorder the audio formats a bit for clarity. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Reorder the audio formats a bit for clarity. + Detect and create caps for MSGSM and MSN (WAV49). + Fixes #356596. + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimagesink_check_xshm_calls), (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_get_xv_support), (gst_xvimagesink_show_frame): + Small cleanups, move error handling out of normal flow for clarity. + +2006-09-18 15:59:39 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add new interface to control video orientation (fixes #354908) + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs.types: + * gst-libs/gst/interfaces/Makefile.am: + * gst-libs/gst/interfaces/videoorientation.c: + (gst_video_orientation_get_type), + (gst_video_orientation_iface_init), + (gst_video_orientation_get_hflip), + (gst_video_orientation_get_vflip), + (gst_video_orientation_get_hcenter), + (gst_video_orientation_get_vcenter), + (gst_video_orientation_set_hflip), + (gst_video_orientation_set_vflip), + (gst_video_orientation_set_hcenter), + (gst_video_orientation_set_vcenter): + * gst-libs/gst/interfaces/videoorientation.h: + Add new interface to control video orientation (fixes #354908) + +2006-09-18 15:48:01 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/videotestsrc/gstvideotestsrc.c: Use G_UNLIKELY in _create and log one more detail. + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + Use G_UNLIKELY in _create and log one more detail. + (gst_video_test_src_get_times), (gst_video_test_src_create): + * sys/ximage/ximagesink.c: (gst_ximagesink_get_times): + Use gst_util_uint64_scale_int in _get_times(). + +2006-09-18 15:00:51 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support) + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support) + Give better warning message (add object and detail). + +2006-09-18 14:42:03 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + sys/xvimage/xvimagesink.c: xvimage assumed that XV_COLORKEY can be set in RGB888 format (fixes #354773), use gst_util... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_get_times): + xvimage assumed that XV_COLORKEY can be set in RGB888 format (fixes + #354773), use gst_util_uint64_scale_int in _get_times() + +2006-09-18 14:21:45 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggmux.c: Timestamps are unsigned; comparision against GST_CLOCK_TIME_NONE was always true, leading to dro... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_push_buffer): + Timestamps are unsigned; comparision against GST_CLOCK_TIME_NONE was + always true, leading to dropping all timestamps. + +2006-09-18 11:40:14 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/libvisual/visual.c: update to work also with libvisual 0.4 API + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_vis_src_negotiate), + (gst_visual_chain), (gst_visual_change_state): + update to work also with libvisual 0.4 API + * tools/gst-launch-ext.1.in: + * tools/gst-visualise.1.in: + remove references to old man-pages + * tests/examples/seek/seek.c: (main): + add real meadi-buttons, add tool-tips for the seek-options, arrange + seek options in a table + +2006-09-18 10:57:28 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggmux.c: Don't generate out-of-order timestamps from oggmux, instead clamp output timestamps to be >= the... + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_clear), + (gst_ogg_mux_push_buffer): + Don't generate out-of-order timestamps from oggmux, instead clamp + output timestamps to be >= the previously output ts. + Fixes #355595 + +2006-09-18 10:18:22 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.c: Updates, fixes, and typo corrections for multifdsink. No functional changes. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_sync_method_get_type), + (gst_multi_fd_sink_class_init): + Updates, fixes, and typo corrections for multifdsink. No functional + changes. + +2006-09-17 21:58:06 +0000 Michael Smith <msmith@xiph.org> + + gst/typefind/gsttypefindfunctions.c: Don't crash on truncated files - check that we got an 8 byte buffer before tryin... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (ogganx_type_find): + Don't crash on truncated files - check that we got an 8 byte buffer + before trying to memcmp it. + +2006-09-17 20:32:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Make stream-switching appear instant to the application (ie. make sure that a g_object... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (get_active_source): + Make stream-switching appear instant to the application + (ie. make sure that a g_object_get on 'current-foo' returns + the stream previously set with g_object_set(). Totem needs + this to update stream-related meta-info (like audio-codec) + correctly when switching streams. + +2006-09-17 20:14:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsamixer.c: Try harder to guess which mixer track is the master mixer track (instead of just taking the ... + Original commit message from CVS: + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_find_master_mixer), + (gst_alsa_mixer_ensure_track_list): + Try harder to guess which mixer track is the master mixer + track (instead of just taking the first one that has a pvolume). + Fixes #342228. + +2006-09-17 11:24:21 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/gstaudioconvert.c: Get structure-name just once. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (set_structure_widths), + (gst_audio_convert_transform_caps): + Get structure-name just once. + +2006-09-16 22:30:50 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/: Fix big batch of compiler warnings. + Original commit message from CVS: + * tests/check/elements/audioresample.c: (GST_START_TEST): + * tests/check/elements/videotestsrc.c: (check_rgb_buf): + * tests/check/elements/volume.c: (GST_START_TEST): + * tests/check/elements/vorbisdec.c: (GST_START_TEST): + * tests/check/pipelines/oggmux.c: (validate_ogg_page), (eos_watch), + (test_pipeline), (GST_START_TEST): + * tests/check/pipelines/theoraenc.c: (GST_START_TEST): + * tests/check/pipelines/vorbisenc.c: (GST_START_TEST): + Fix big batch of compiler warnings. + +2006-09-16 21:54:48 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/gnomevfs/gstgnomevfssrc.c: Add docs about icydemux usage in connection with gnomevfssrc + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: + Add docs about icydemux usage in connection with gnomevfssrc + * ext/libvisual/visual.c: + * ext/ogg/gstoggaviparse.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosrc.c: + * gst/audiorate/gstaudiorate.c: + More G_OBJECT macro fixing. + * gst/audiotestsrc/gstaudiotestsrc.h: + Fix wrong info in header due to copy & paste + +2006-09-15 14:53:44 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/: Do the delay calculation in the source/sink base classes as this is specific for the capture/pla... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_time), (gst_base_audio_sink_callback): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_get_time), (gst_base_audio_src_fixate), + (gst_base_audio_src_get_times), (gst_base_audio_src_get_offset), + (gst_base_audio_src_create), (gst_base_audio_src_change_state): + Do the delay calculation in the source/sink base classes as this is + specific for the capture/playback mode. + Try to fixate a bit better, like round depth up to a multiple of 8 + bigger than width. + Handle underruns correctly by marking DISCONT on buffers and adjusting + timestamps to handle the gap. + Set offset/offset_end correctly on buffers. + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_pause), + (gst_ring_buffer_samples_done), (gst_ring_buffer_commit), + (gst_ring_buffer_read): + Remove resync and underrun recovery from the ringbuffer. + Fix ringbuffer read code on under/overrun. + +2006-09-15 11:17:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.*: Don't use a 0 low watermark when buffering, it is catching starvation way too late. In... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (fill_buffer), (check_queue), + (queue_threshold_reached), (gst_play_base_bin_set_property), + (gst_play_base_bin_get_property): + * gst/playback/gstplaybasebin.h: + Don't use a 0 low watermark when buffering, it is catching starvation + way too late. Instead, use a 3 second queue with 30 and 95 + percent low/high watermarks. + Added queue-min-threshold property to configure low watermark. + Use new _buffering message API. + Make queue_threshold variable big enough to store a uint64 time value. + API: playbin::queue-min-threshold property. + +2006-09-15 09:13:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + configure.ac: We require 0.10.10.1 now because of _wait_preroll(). + Original commit message from CVS: + * configure.ac: + We require 0.10.10.1 now because of _wait_preroll(). + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + Use gst_base_sink_wait_preroll(). + +2006-09-15 09:09:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/: Use DEBUG_OBJECT more. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (xrun_recovery), (gst_alsasink_write): + * ext/alsa/gstalsasrc.c: (xrun_recovery), (gst_alsasrc_read): + Use DEBUG_OBJECT more. + +=== release 0.10.10 === + +2006-09-14 20:09:19 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * common: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gdp.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * ext/theora/theoraparse.c: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst/playback/gstplaybin.c: + * tests/check/Makefile.am: + * win32/common/config.h: + releasing 0.10.10 + Original commit message from CVS: + releasing 0.10.10 + +2006-09-09 16:08:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + * win32/common/config.h: + second prerelease + Original commit message from CVS: + second prerelease + +2006-09-07 19:01:23 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + update bug in changelog + Original commit message from CVS: + update bug in changelog + +2006-09-07 19:00:33 +0000 Michael Smith <msmith@fluendo.com> + + Fix implementation of sync-method 'next-keyframe' + Original commit message from CVS: + patch by: Michael Smith <msmith at fluendo dot com> + * gst/tcp/gstmultifdsink.c: (is_sync_frame), + (gst_multi_fd_sink_client_queue_buffer), + (gst_multi_fd_sink_new_client): + * tests/check/elements/multifdsink.c: (GST_START_TEST), + (multifdsink_suite): + Fix implementation of sync-method 'next-keyframe' + +2006-09-07 15:00:08 +0000 Wim Taymans <wim@fluendo.com> + + ext/gnomevfs/gstgnomevfssrc.c: This patch removes the RANDOM flag that was incorrectly introduced with revision 1.91.... + Original commit message from CVS: + patch by: Wim Taymans <wim at fluendo dot com> + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_start): + This patch removes the RANDOM flag that was incorrectly introduced with + revision 1.91. Fixes #354590 + +2006-09-07 14:56:47 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + * win32/common/config.h: + first prerelease + Original commit message from CVS: + first prerelease + +2006-09-07 14:56:31 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + update po files + Original commit message from CVS: + update po files + +2006-09-05 09:12:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Random variation in Makefile line to see if it makes the gen64-base-full bot any happier. + Original commit message from CVS: + * tests/check/Makefile.am: + Random variation in Makefile line to see if it makes the + gen64-base-full bot any happier. + +2006-09-04 19:04:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/pipelines/oggmux.c: Disable test that fails at the moment (killed after timeout). + Original commit message from CVS: + * tests/check/pipelines/oggmux.c: (oggmux_suite): + Disable test that fails at the moment (killed after timeout). + +2006-09-04 18:19:06 +0000 James Livingston <doclivingston@gmail.com> + + tests/check/: Add simple unit test for oggmux from #337026 with checking for the + Original commit message from CVS: + Patch by: James Livingston <doclivingston at gmail.com> + * tests/check/Makefile.am: + * tests/check/pipelines/.cvsignore: + * tests/check/pipelines/oggmux.c: (get_page_codec), + (check_chain_final_state), (fail_if_audio), (validate_ogg_page), + (eos_buffer_probe), (start_pipeline), (stop_pipeline), (eos_watch), + (test_pipeline), (test_vorbis), (test_theora), (test_vorbis_theora), + (test_theora_vorbis), (oggmux_suite): + Add simple unit test for oggmux from #337026 with checking for the + EOS flags disabled for the time being. + +2006-09-04 09:13:01 +0000 Alessandro Dessina <alessandro@nnva.org> + + ext/ogg/gstoggmux.c: Add cmml caps to oggmux. Fixes #353912 + Original commit message from CVS: + patch by: Alessandro Dessina <alessandro nnva org> + * ext/ogg/gstoggmux.c: + Add cmml caps to oggmux. Fixes #353912 + +2006-09-02 13:20:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/videotestsrc.c: Returning a return value often helps. In this case, we don't need the return val... + Original commit message from CVS: + * tests/check/elements/videotestsrc.c: (check_rgb_buf): + Returning a return value often helps. In this case, we + don't need the return value anyway, so just get rid of it. + Should make build bots much happier. + +2006-09-02 12:59:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/videotestsrc.*: Add support for AYUV and the various RGBA formats. Initialise fields of paintinfo st... + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: (paintinfo_find_by_structure), + (paint_get_structure), (gst_video_test_src_get_size), + (gst_video_test_src_smpte), (gst_video_test_src_snow), + (gst_video_test_src_unicolor), (paint_setup_AYUV), + (paint_hline_AYUV), (paint_setup_ARGB8888), (paint_setup_ABGR8888), + (paint_setup_RGBA8888), (paint_setup_BGRA8888), (paint_hline_str4): + * gst/videotestsrc/videotestsrc.h: + Add support for AYUV and the various RGBA formats. Initialise + fields of paintinfo structs allocated on the stack. + * tests/check/elements/videotestsrc.c: (right_shift_colour), + (fix_expected_colour), (check_rgb_buf), (got_buf_cb), + (GST_START_TEST), (videotestsrc_suite): + Add unit tests for videotestsrc's RGB output. + +2006-09-01 16:12:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/: Add more uni-colour patterns ("white", "red", "green", and "blue"). + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_pattern_get_type), + (gst_video_test_src_set_pattern): + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: (gst_video_test_src_unicolor), + (gst_video_test_src_black), (gst_video_test_src_white), + (gst_video_test_src_red), (gst_video_test_src_green), + (gst_video_test_src_blue): + * gst/videotestsrc/videotestsrc.h: + Add more uni-colour patterns ("white", "red", "green", and "blue"). + +2006-09-01 10:07:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/videotestsrc.c: Fix stride for YVYU, should be word-aligned (#353658). + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.c: (paint_setup_YVYU): + Fix stride for YVYU, should be word-aligned (#353658). + +2006-08-31 14:37:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/adder/gstadder.c: Fix build. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_src_event): + Fix build. + +2006-08-31 12:39:17 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/adder/gstadder.*: Remember the start position asked in the incoming seeks, so we can output GST_EVENT_NEW_SEGMENT... + Original commit message from CVS: + * gst/adder/gstadder.c: (forward_event_func), + (gst_adder_src_event), (gst_adder_collected), + (gst_adder_change_state): + * gst/adder/gstadder.h: + Remember the start position asked in the incoming seeks, so we can + output GST_EVENT_NEW_SEGMENT with a correct position value (instead + of assuming it will always be 0). + +2006-08-31 12:31:00 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/ogg/gstoggdemux.c: Send the GST_EVENT_NEW_SEGMENT from the streaming thread. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_init), + (gst_ogg_demux_finalize), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_loop): + Send the GST_EVENT_NEW_SEGMENT from the streaming thread. + +2006-08-30 17:22:27 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/ffmpegcolorspace/gstffmpegcolorspace.c: Return FALSE instead of returning a random false unit size when the forma... + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_get_unit_size): + Return FALSE instead of returning a random false unit + size when the format isn't known/supported (even if + this shouldn't happen under normal circumstances). + +2006-08-29 15:23:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Try harder to get the size from a uri by using _info_uri() when _info_from_handle() do... + Original commit message from CVS: + Patch by: Tim-Philipp Müller <tim at centricular dot net> + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_create), + (gst_gnome_vfs_src_start): + Try harder to get the size from a uri by using _info_uri() when + _info_from_handle() does not give us enough info. + Also follow symlinks when getting the size. + Partially Fixes #332864. + +2006-08-29 11:50:51 +0000 Viktor Peters <viktor.peters@gmail.com> + + ext/alsa/: Improve and fix mixer track handling, in particular better handling of alsa's pvolume/pswitch/cvolume/cswi... + Original commit message from CVS: + Patch by: Viktor Peters <viktor dot peters at gmail dot com> + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_ensure_track_list), + (gst_alsa_mixer_update), (gst_alsa_mixer_get_volume), + (gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute), + (gst_alsa_mixer_set_record): + * ext/alsa/gstalsamixertrack.c: + (gst_alsa_mixer_track_update_alsa_capabilities), + (alsa_track_has_cap), (gst_alsa_mixer_track_new), + (gst_alsa_mixer_track_update): + * ext/alsa/gstalsamixertrack.h: + Improve and fix mixer track handling, in particular better handling + of alsa's pvolume/pswitch/cvolume/cswitch capabilities; create separate + track objects for tracks that have both capture and playback volume + (and label them differently as well so they're not mistakenly + assumed to be duplicates); classify mixer tracks that only affect + the audible volume of something (rather than the capture volume) + as playback tracks. Redefine/fix meaning of RECORD and MUTE flags + for capture tracks to correspond to alsa-pswitch alsa-cswitch + (following the meaning documented in the mixer interface header + file); add support for alsa's exclusive cswitch groups; update/sync + state/flags better if mixer settings are changed by another + application. Fixes #336075. + +2006-08-29 10:58:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Improve docs: add section about BUFFERING messages sent by playbin. + Original commit message from CVS: + * gst/playback/gstplaybin.c: + Improve docs: add section about BUFFERING messages sent by playbin. + +2006-08-29 10:51:12 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.c: Ignore explicit DISCONT marked on buffers (which is often spurious, particularly when using m... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_push_buffer), + (gst_vorbis_enc_buffer_check_discontinuous), + (gst_vorbis_enc_chain): + Ignore explicit DISCONT marked on buffers (which is often spurious, + particularly when using multiple segments), in favour of solely + using the timestamps/durations. + +2006-08-29 10:32:34 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/audiorate/gstaudiorate.c: Don't rely on incoming buffers offset anymore, since it is completely broken when using... + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain): + Don't rely on incoming buffers offset anymore, since it is completely + broken when using multiple segments. + Instead convert the incoming buffers timestamp to running time, and + then convert that value to the offsets. + Also inform GstSegment of the last outputted stop position, which is + needed if we received several segments with an unknown stop value. + +2006-08-29 08:03:05 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/vorbis/vorbisenc.c: fix buffer unreffing on a header push failure + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_chain): + fix buffer unreffing on a header push failure + +2006-08-28 16:17:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiorate/gstaudiorate.c: Make the metadata of the buffer writable before changing its flags. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_sink_event), + (gst_audio_rate_chain): + Make the metadata of the buffer writable before changing its + flags. + +2006-08-28 16:09:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + * ChangeLog: + Fix changelog with bugzilla bug it fixed. + Original commit message from CVS: + Fix changelog with bugzilla bug it fixed. + +2006-08-28 16:08:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audiorate/gstaudiorate.c: Fix audiorate some more. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_reset), + (gst_audio_rate_setcaps), (gst_audio_rate_init), + (gst_audio_rate_sink_event), (gst_audio_rate_src_event), + (gst_audio_rate_chain), (gst_audio_rate_change_state): + Fix audiorate some more. + Reset and resync counters on flush and READY. + Handle the DISCONT flag correctly. + Use GstSegment to track position. + Fail when not negotiated. + +2006-08-25 16:48:28 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.c: Fix spelling. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_render): + Fix spelling. + Remove accidently included debug line. + +2006-08-25 16:39:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.c: Small cleanups. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_render): + Small cleanups. + If a buffer is received with no caps, make the buffer metadata + writable and set the caps, making sure that we don't screw up the + refcounts. + +2006-08-25 16:19:55 +0000 Michael Smith <msmith@xiph.org> + + gst/gdp/gstgdppay.c: Fix memory leaks and misleading debug messages, add a couple of comments. + Original commit message from CVS: + * gst/gdp/gstgdppay.c: (gst_gdp_pay_reset), + (gst_gdp_pay_reset_streamheader), (gst_gdp_pay_chain): + Fix memory leaks and misleading debug messages, add a couple of + comments. + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_get_stats), + (gst_multi_fd_sink_render): + Do not use gst_buffer_make_writable() in a basesink render method, + as it may incorrectly unref the buffer. Instead, use convoluted + dance to avoid copying the buffer except when we need to. + +2006-08-25 09:54:56 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.c: Allow very small discontinuities in the timestamps. These we can't do anything useful with an... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: + (gst_vorbis_enc_buffer_check_discontinuous): + Allow very small discontinuities in the timestamps. These we can't + do anything useful with anyway (because vorbis's timestamps have + only sample granularity), and are commonly produced by elements with + minor bugs. Allow up to 1/2 a sample out. + Fixes #351742. + +2006-08-24 11:18:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add a checkbox to enable play scrubbing. Makes it possible to disable normal scrubbing. + Original commit message from CVS: + * tests/examples/seek/seek.c: (seek_cb), (start_seek), (stop_seek), + (play_scrub_toggle_cb), (main): + Add a checkbox to enable play scrubbing. Makes it possible to disable + normal scrubbing. + +2006-08-23 19:37:50 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/.cvsignore: make buildbot happy + Original commit message from CVS: + * tests/check/elements/.cvsignore: + make buildbot happy + +2006-08-23 16:43:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstogmparse.c: Refactor ogm parse, do better input checking, misc. clean-ups. + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_audio_parse_base_init), + (gst_ogm_video_parse_base_init), (gst_ogm_text_parse_base_init), + (gst_ogm_parse_class_init), (gst_ogm_parse_dispose), + (gst_ogm_parse_init), (gst_ogm_audio_parse_init), + (gst_ogm_video_parse_init), (gst_ogm_text_parse_init), + (gst_ogm_parse_stream_header), (gst_ogm_parse_comment_packet), + (gst_ogm_text_parse_strip_trailing_zeroes), + (gst_ogm_parse_data_packet), (gst_ogm_parse_chain), + (gst_ogm_parse_sink_event), (gst_ogm_parse_change_state): + Refactor ogm parse, do better input checking, misc. clean-ups. + Cache incoming events and push them once the source pad has + been created. Don't pass unterminated strings to sscanf(). + Strip trailing zeroes from subtitle text output, since they + are not valid UTF-8. Don't push vorbiscomment packets on + the subtitle text pad. Output perfect streams if possible. + +2006-08-23 15:27:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/libs/cddabasesrc.c: Waits for tasks to settle down so that we clean up correctly for valgrind. + Original commit message from CVS: + * tests/check/libs/cddabasesrc.c: (GST_START_TEST): + Waits for tasks to settle down so that we clean up correctly for + valgrind. + +2006-08-23 15:11:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/libs/tag.c: Unit test fixes: \377 is more likely to fit into 8 bits than \777; actually return return val... + Original commit message from CVS: + * tests/check/libs/tag.c: (GST_START_TEST), (taglists_are_equal): + Unit test fixes: \377 is more likely to fit into 8 bits than \777; + actually return return value in taglists_are_equal. + +2006-08-23 12:14:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstogmparse.c: Fix crash due to broken bitstream parsing on x86-64: can't make any assumptions about sizeof(s... + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): + Fix crash due to broken bitstream parsing on x86-64: can't make + any assumptions about sizeof(struct) due to alignment/packing + differences on different architectures. Fixes #351790. + +2006-08-22 16:31:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/riff/riff-read.c: Protect public functions against bad input. + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_chunk), + (gst_riff_parse_chunk), (gst_riff_parse_file_header), + (gst_riff_parse_strh), (gst_riff_parse_strf_vids), + (gst_riff_parse_strf_auds), (gst_riff_parse_strf_iavs), + (gst_riff_parse_info): + Protect public functions against bad input. + Do some cleanups. + Fix documentation. + +2006-08-22 15:50:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/: Add voxware audio IDs (even if we can't play it) (#351795). + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Add voxware audio IDs (even if we can't play it) (#351795). + +2006-08-22 15:11:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Const-ify some arrays and use G_N_ELEMENTS instead of wasting oodles of RAM on termin... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_template_caps), + (gst_riff_create_audio_template_caps), + (gst_riff_create_iavs_template_caps): + Const-ify some arrays and use G_N_ELEMENTS instead + of wasting oodles of RAM on terminator bits. + +2006-08-22 08:27:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + And the same for _to_vorbiscomment_buffer(): allow id_data_len == 0 for speex. + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: + (gst_tag_list_to_vorbiscomment_buffer): + * tests/check/libs/tag.c: (GST_START_TEST): + And the same for _to_vorbiscomment_buffer(): allow + id_data_len == 0 for speex. + +2006-08-21 19:04:14 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/README: + adding a README + Original commit message from CVS: + adding a README + +2006-08-21 19:01:41 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + Move GDP plugin to -base from -bad. Closes #347783. + Original commit message from CVS: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/inspect/plugin-gdp.xml: + * gst/gdp/Makefile.am: + * tests/check/Makefile.am: + Move GDP plugin to -base from -bad. Closes #347783. + +2006-08-21 18:34:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Allow id_data_len == 0 (needed for vorbis comments in Speex files). + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: + (gst_tag_list_from_vorbiscomment_buffer): + Allow id_data_len == 0 (needed for vorbis comments in Speex files). + Also add some checks to make sure we don't memcmp() beyond the end of + vorbiscomment buffer if the ID to check for is larger than the buffer. + * tests/check/libs/tag.c: (GST_START_TEST): + Some more tests for gst_tag_list_from_vorbiscomment_buffer(). + +2006-08-21 16:39:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/vorbis/vorbisenc.c: Use vorbis comment utility functions from libgsttag instead of re-inventing the wheel (partia... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_metadata_set1), + (gst_vorbis_enc_set_metadata): + Use vorbis comment utility functions from libgsttag + instead of re-inventing the wheel (partially fixes #347091). + +2006-08-21 11:42:12 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/elements/audioconvert.c: Fix leaks. Wait for state transitions that might happen ASYNC, as well as some t... + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (GST_START_TEST): + Fix leaks. Wait for state transitions that might happen ASYNC, as well + as some that won't. + +2006-08-21 10:32:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/libs/: Don't try to GObject scan the netbuffer as it's not a GObject. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + Don't try to GObject scan the netbuffer as it's not a GObject. + Fixes #351308. + * gst-libs/gst/netbuffer/gstnetbuffer.c: + * gst-libs/gst/netbuffer/gstnetbuffer.h: + Document GstNetBuffer. + +2006-08-21 08:54:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/audioconvert.c: Add testcase for caps-size-explosion + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (GST_START_TEST), + (audioconvert_suite): + Add testcase for caps-size-explosion + +2006-08-20 13:05:44 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audioconvert/gstaudioconvert.c: Lower debug, use g_assert in _get_unit_size + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_get_unit_size), (set_structure_widths): + Lower debug, use g_assert in _get_unit_size + * gst/audioresample/gstaudioresample.c: + (audioresample_get_unit_size): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_get_unit_size): + * gst/videoscale/gstvideoscale.c: (gst_video_scale_get_unit_size): + use g_assert in _get_unit_size + +2006-08-18 21:21:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery: fix bug number + Original commit message from CVS: + ChangeLog surgery: fix bug number + +2006-08-18 16:43:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + Document GstRTPBuffer. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_set_packet_len), + (gst_rtp_buffer_pad_to), (gst_rtp_buffer_get_payload_subbuffer), + (gst_rtp_buffer_get_payload_buffer): + * gst-libs/gst/rtp/gstrtpbuffer.h: + Document GstRTPBuffer. + Added function to efficiently strip payload headers. + API: gst_rtp_buffer_get_payload_subbuffer() + +2006-08-17 16:52:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Serialise unknown vorbis comments into GST_TAG_EXTENDED_COMMENT tags and deserialise... + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add), + (gst_tag_to_vorbis_comments): + Serialise unknown vorbis comments into GST_TAG_EXTENDED_COMMENT + tags and deserialise them properly as well (#351768). + Add some more gtk-doc blurbs and also some g_return_if_fail(). + * tests/check/libs/tag.c: (GST_START_TEST), + (back_to_vorbis_comments), (taglists_are_equal), (tag_suite): + More tests. + +2006-08-17 15:43:40 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/: Added ogg-in-avi parser element. Fixes #140139. + Original commit message from CVS: + * ext/ogg/Makefile.am: + * ext/ogg/gstogg.c: (plugin_init): + * ext/ogg/gstoggaviparse.c: (gst_ogg_avi_parse_get_type), + (gst_ogg_avi_parse_base_init), (gst_ogg_avi_parse_class_init), + (gst_ogg_avi_parse_init), (gst_ogg_avi_parse_finalize), + (gst_ogg_avi_parse_setcaps), (gst_ogg_avi_parse_event), + (gst_ogg_avi_parse_push_packet), (gst_ogg_avi_parse_chain), + (gst_ogg_avi_parse_change_state), (gst_ogg_avi_parse_plugin_init): + Added ogg-in-avi parser element. Fixes #140139. + * ext/ogg/gstoggmux.c: (gst_ogg_mux_buffer_from_page): + Fixed a bug in oggdemux debug code. + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Recognise Ogg in the AVI extensible wave format. + +2006-08-17 10:00:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: Make buffer durations add up (duration should be next_ts-ts for perfect streams).... + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_create): + Make buffer durations add up (duration should be next_ts-ts for + perfect streams). Fixes CD ripping to Ogg/Vorbis with vorbisenc + from CVS. + * tests/check/libs/cddabasesrc.c: (gst_cd_foo_src_close), + (test_buffer_timestamps), (cddabasesrc_suite): + Add unit test for the above. + * tests/check/Makefile.am: + Don't know why cddabasesrc test was in VALGRIND_TO_FIX, remove + to see what happens. + +2006-08-16 11:38:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/: Avoid setting and using a NULL device name. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_set_property), + (gst_alsasink_open): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_set_property), + (gst_alsasrc_open): + Avoid setting and using a NULL device name. + Print more info when we fail to open a device. + +2006-08-16 11:28:57 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add gst_tag_parse_extended_comment() (#351426). + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: (gst_tag_parse_extended_comment): + API: add gst_tag_parse_extended_comment() (#351426). + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/tag.c: (GST_START_TEST), (tag_suite), (main): + Add unit test for gst_tag_parse_extended_comment(). + +2006-08-15 19:20:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/: Fix leak (#351502). + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_get_property): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_property): + Fix leak (#351502). + +2006-08-15 17:21:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + Document playbin. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * gst/playback/gstplaybin.c: + Document playbin. + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + Update to CVS version. + +2006-08-14 17:54:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Add "connection-speed" property; re-order redirect messages with multiple redirect locatio... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (value_list_append_structure_list), + (gst_play_bin_handle_redirect_message), + (gst_play_bin_handle_message): + Add "connection-speed" property; re-order redirect messages with + multiple redirect locations depending on the minimum bitrate if + that information is available and a connection speed is set + (#350399). + +2006-08-14 11:41:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Update max volume to the same value that the volume element uses. + Original commit message from CVS: + * gst/playback/gstplaybin.c: + Update max volume to the same value that the volume element uses. + +2006-08-14 10:50:15 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsamixer.c: Less uglyness.. + Original commit message from CVS: + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_open): + Less uglyness.. + +2006-08-14 10:49:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Add some more debug info. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_submit_buffer), + (gst_ogg_demux_get_next_page), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_read_chain), (gst_ogg_demux_loop): + Add some more debug info. + Don't crash when a seek failed. + Actually return the result of the seek instead of TRUE. + Ignore multiple BOS pages with the same serial so that we don't create + the same stream multiple times. + Post an error when we fail to do the initial seek. + +2006-08-13 14:34:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsa.c: Small code cleanup. + Original commit message from CVS: + * ext/alsa/gstalsa.c: (gst_alsa_detect_rates), + (gst_alsa_detect_channels), (gst_alsa_probe_supported_formats): + Small code cleanup. + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_open), + (gst_alsa_mixer_new): + Remove hack that always set the device to hw:0*. + Properly find the card name for whatever device was configured. + Do some better debugging. + Fixes #350784. + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_set_property), + (gst_alsa_mixer_element_change_state): + Cleanups. + Handle setting of a NULL device name better. + +2006-08-11 15:53:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.c: Don't clip float values. Fixes #350900. + Original commit message from CVS: + * gst/adder/gstadder.c: + Don't clip float values. Fixes #350900. + +2006-08-11 15:33:17 +0000 Andy Wingo <wingo@pobox.com> + + gst/tcp/gsttcp.c: Really fix the build? + Original commit message from CVS: + 2006-08-11 Andy Wingo <wingo@pobox.com> + * gst/tcp/gsttcp.c: Really fix the build? + +2006-08-11 15:29:56 +0000 Andy Wingo <wingo@pobox.com> + + gst/tcp/gsttcp.h: For now, always disable deprecation here -- fixes the build. + Original commit message from CVS: + 2006-08-11 Andy Wingo <wingo@pobox.com> + * gst/tcp/gsttcp.h: For now, always disable deprecation here -- + fixes the build. + +2006-08-10 13:01:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/gstaudioconvert.c: Float caps shouldn't have a "signed" field. + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes): + Float caps shouldn't have a "signed" field. + +2006-08-10 08:56:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggdemux.c: Implement SEEKING query in its most basic form, so that we can at least check if we're seekabl... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query): + Implement SEEKING query in its most basic form, so that we can + at least check if we're seekable or not (#350655). + +2006-08-09 14:42:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: The checks here are not even close to anything that would justify MAXIMUM probab... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find): + The checks here are not even close to anything that would + justify MAXIMUM probability, lowering to POSSIBLE until someone + fixes the checks (case at hand: quicktime redirection files + might start with 00 00 01 XX and pass the checks here just + fine, see #350399). + +2006-08-08 13:57:29 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/elements/gdpdepay.c: I forgot to include the file containing the #define :) + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (gdpdepay_suite): + I forgot to include the file containing the #define :) + Now includes "config.h" + +2006-08-08 13:45:44 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/elements/gdpdepay.c: Ignore test known to fail on PPC64. See #348114. + Original commit message from CVS: + * tests/check/elements/gdpdepay.c: (gdpdepay_suite): + Ignore test known to fail on PPC64. See #348114. + +2006-08-08 08:41:13 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/typefind/gsttypefindfunctions.c: Better detection for multipart/x-mixed-replace: accept leading whitespaces befor... + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon net> + * gst/typefind/gsttypefindfunctions.c: (multipart_type_find): + Better detection for multipart/x-mixed-replace: accept leading + whitespaces before the boundary marker as well (as our very own + multipartmux used to produce) (#349068). + +2006-08-07 08:26:03 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst-libs/gst/riff/: Detect DTS audio streams (#350157). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + Detect DTS audio streams (#350157). + +2006-08-05 17:08:05 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/gsttheoraparse.h: ext/theora/theoraparse.c (gst_theora_parse_class_init) (theora_parse_dispose, theora_par... + Original commit message from CVS: + 2006-08-05 Andy Wingo <wingo@pobox.com> + * ext/theora/gsttheoraparse.h: + * ext/theora/theoraparse.c (gst_theora_parse_class_init) + (theora_parse_dispose, theora_parse_set_property) + (theora_parse_get_property, theora_parse_munge_granulepos) + (theora_parse_push_buffer, theora_parse_change_state): Add a + property 'synchronization-points' to fix badly synchronized oggs. + +2006-08-04 13:20:23 +0000 Zaheer Abbas Merali <zaheerabbas@merali.org> + + gst/gdp/gstgdpdepay.c: Fix event parsing by gdpdepay. Fixes #349916. + Original commit message from CVS: + 2006-08-04 Zaheer Abbas Merali <zaheerabbas at merali dot org> + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain): + Fix event parsing by gdpdepay. Fixes #349916. + +2006-08-03 15:04:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add a few tests for the channel position stuff in libgstaudio. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/libs/.cvsignore: + * tests/check/libs/audio.c: (structure_contains_channel_positions), + (fixed_caps_have_channel_positions), (GST_START_TEST), + (audio_suite), (main): + Add a few tests for the channel position stuff in libgstaudio. + +2006-08-03 14:16:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/: Add support for cards that (only) do more than 8 channels, like the Delta 44 (#345188). + Original commit message from CVS: + * ext/alsa/gstalsa.c: (caps_add_channel_configuration), + (gst_alsa_detect_channels): + * ext/alsa/gstalsasink.c: + Add support for cards that (only) do more than 8 channels, + like the Delta 44 (#345188). + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions): + * gst-libs/gst/audio/multichannel.h: + API: add GST_AUDIO_CHANNEL_POSITION_NONE, which stands for an + unspecified channel position and cannot be combined with any + of the other audio channel positions; adjust position layout + checks accordingly (#345188). + +2006-08-03 11:15:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Recognise ancient RealAudio files (see #349779). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Recognise ancient RealAudio files (see #349779). + +2006-08-03 09:01:25 +0000 Jens Granseuer <jensgr@gmx.net> + + gst/typefind/gsttypefindfunctions.c: Add typefinder for Interplay's MVE format (#348973). + Original commit message from CVS: + Patch by: Jens Granseuer <jensgr at gmx net> + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add typefinder for Interplay's MVE format (#348973). + +2006-08-02 17:03:29 +0000 Marcel Moreaux <marcelm@luon.net> + + gst-libs/gst/rtp/gstbasertpdepayload.*: Handle RTP sequence number rollover. + Original commit message from CVS: + Patch by: Marcel Moreaux <marcelm at luon dot net> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_add_to_queue): + * gst-libs/gst/rtp/gstbasertpdepayload.h: + Handle RTP sequence number rollover. + Disable jitterbuffer by default. + +2006-08-02 16:56:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/gdp/gstgdpdepay.c: Disable seeking. + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_init), + (gst_gdp_depay_finalize), (gst_gdp_depay_sink_event), + (gst_gdp_depay_src_event), (gst_gdp_depay_chain), + (gst_gdp_depay_change_state): + Disable seeking. + Small cleanups. + Clear adapter on disconts. + Clear caps when going to READY instead of NULL + * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init), + (gst_gdp_pay_init), (gst_gdp_pay_finalize), (gst_gdp_pay_reset), + (gst_gdp_buffer_from_caps), (gst_gdp_pay_buffer_from_buffer), + (gst_gdp_buffer_from_event), (gst_gdp_pay_reset_streamheader), + (gst_gdp_queue_buffer), (gst_gdp_pay_chain), + (gst_gdp_pay_sink_event), (gst_gdp_pay_src_event), + (gst_gdp_pay_change_state): + * gst/gdp/gstgdppay.h: + Reset payloader when going to READY. + Fix leaked buffers in ->queue on push errors. + Disable seeking. + Code cleanups. + Create packetizer in _init, free in _finalize. + +2006-07-31 08:48:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/gdp/gstgdpdepay.c: Consume all events except EOS because we generate events from the gdp payload instead. Fixes #... + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_init), + (gst_gdp_depay_sink_event), (gst_gdp_depay_chain): + Consume all events except EOS because we generate events from + the gdp payload instead. Fixes #349204 + +2006-07-28 17:17:24 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/audioresample/gstaudioresample.c: Don't leak references to the incoming caps. Clean them up when stopping. + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: (audioresample_stop), + (audioresample_set_caps): + Don't leak references to the incoming caps. Clean them up when + stopping. + * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init), + (gst_video_scale_finalize): + Don't leak our temporary pixel buffer. + * tests/check/Makefile.am: + * tests/check/pipelines/simple-launch-lines.c: (run_pipeline), + (GST_START_TEST), (simple_launch_lines_suite): + Fix leaks and re-enable the test for valgrind checking. + +2006-07-28 16:39:31 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/typefind/gsttypefindfunctions.c: Add typefind function for multipart/x-mixed-replace (#348916). + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon net> + * gst/typefind/gsttypefindfunctions.c: (multipart_type_find), + (plugin_init): + Add typefind function for multipart/x-mixed-replace (#348916). + +2006-07-28 14:14:58 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.c: Fix leak in duration query. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_setcaps), + (gst_adder_query_duration): + Fix leak in duration query. + Reflow some docs and notes. + +2006-07-28 13:42:48 +0000 Michael Smith <msmith@xiph.org> + + tests/check/pipelines/vorbisenc.c: Enable Andy's extra vorbisenc test, now that it passes. Also fix one aspect of it. + Original commit message from CVS: + * tests/check/pipelines/vorbisenc.c: (GST_START_TEST), + (vorbisenc_suite): + Enable Andy's extra vorbisenc test, now that it passes. Also fix one + aspect of it. + +2006-07-28 12:48:21 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.*: Handle discontinuities in the input vorbis stream correctly, so that the output is properly t... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_generate_sink_caps), + (gst_vorbis_enc_sink_getcaps), (gst_vorbis_enc_buffer_from_packet), + (gst_vorbis_enc_push_buffer), + (gst_vorbis_enc_buffer_check_discontinuous), + (gst_vorbis_enc_chain), (gst_vorbis_enc_change_state): + * ext/vorbis/vorbisenc.h: + Handle discontinuities in the input vorbis stream correctly, + so that the output is properly timestamped (and has good granulepos + values). Needs some oggmux fixes too. + +2006-07-27 10:52:52 +0000 Kai Vehmanen <kv2004@eca.cx> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Don't send multiple newsegments with different formats. + Original commit message from CVS: + patch by: Kai Vehmanen <kv2004 eca cx> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_handle_sink_event), + (gst_base_rtp_depayload_change_state): + Don't send multiple newsegments with different formats. + Fixes #348677. + +2006-07-26 15:20:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Make seeking in ogg more accurate again by doing the more correct granuletime to stream time c... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_internal_chain), + (gst_ogg_demux_do_seek), (gst_ogg_demux_read_chain): + Make seeking in ogg more accurate again by doing the more correct + granuletime to stream time conversion. + +2006-07-26 10:59:35 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gstmultifdsink.c: debug a little more understandably do not use goto as a substitute for break, especially if... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_add_full), + (gst_multi_fd_sink_new_client): + debug a little more understandably + do not use goto as a substitute for break, especially if + break is also being used + +2006-07-26 10:55:13 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gsttcp.c: + move a recurring normal event to LOG, where it should be + Original commit message from CVS: + move a recurring normal event to LOG, where it should be + +2006-07-26 10:54:13 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/vorbis/vorbisdec.c: + tweak debug output + Original commit message from CVS: + tweak debug output + +2006-07-26 10:52:05 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/gdp/gstgdpdepay.c: proxying get/set caps is the wrong thing to do, since we really do change caps quite fundament... + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_init): + proxying get/set caps is the wrong thing to do, since we really + do change caps quite fundamentally + * tests/check/elements/gdpdepay.c: + * tests/check/elements/gdppay.c: + remove declaration of buffers, it's already done in gstcheck.h + +2006-07-26 10:31:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Remove GLib-2.6 compatibility cruft. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_property): + * gst/playback/gstplaybin.c: (gst_play_bin_get_property): + Remove GLib-2.6 compatibility cruft. + +2006-07-24 16:47:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Don't try to align a sample to an unknown value. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + Don't try to align a sample to an unknown value. + +2006-07-24 15:14:17 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: When the audio clock is slaved to another clock, never try to align samples bu... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_provide_clock), (gst_base_audio_sink_render): + When the audio clock is slaved to another clock, never try to align + samples but trust the rate interpolation algorithm. + +2006-07-24 14:34:42 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.c: Don't try to calculate silence samples, base class does this much better now. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (set_hwparams), (gst_alsasink_prepare): + Don't try to calculate silence samples, base class does this much + better now. + * gst-libs/gst/audio/gstringbuffer.c: (build_linear_format), + (gst_ring_buffer_debug_spec_caps), (gst_ring_buffer_parse_caps), + (gst_ring_buffer_acquire): + Calculate silence samples correctly. + * gst-libs/gst/audio/gstringbuffer.h: + Add _CAST macro. + +2006-07-22 17:01:12 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Limit search for the first markup tag to the first few kB of the file. If we don... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (xml_check_first_element): + Limit search for the first markup tag to the first few kB of + the file. If we don't find one there, it's highly unlikely that + this is an XML(-ish) file. + +2006-07-21 17:04:06 +0000 Andy Wingo <wingo@pobox.com> + + tests/check/pipelines/theoraenc.c (test_discontinuity): Similar test to the one in vorbisenc. Also commented out. + Original commit message from CVS: + 2006-07-21 Andy Wingo <wingo@pobox.com> + * tests/check/pipelines/theoraenc.c (test_discontinuity): Similar + test to the one in vorbisenc. Also commented out. + +2006-07-21 16:54:19 +0000 Andy Wingo <wingo@pobox.com> + + tests/check/pipelines/vorbisenc.c: New test, commented out until Mike lands some elite vorbisenc patches. + Original commit message from CVS: + 2006-07-21 Andy Wingo <wingo@pobox.com> + * tests/check/pipelines/vorbisenc.c: + (test_discontinuity): New test, commented out until Mike lands + some elite vorbisenc patches. + +2006-07-21 15:59:24 +0000 Andy Wingo <wingo@pobox.com> + + tests/check/pipelines/: Port to bufferstraw. + Original commit message from CVS: + 2006-07-21 Andy Wingo <wingo@pobox.com> + * tests/check/pipelines/vorbisenc.c: + * tests/check/pipelines/theoraenc.c: Port to bufferstraw. + Bufferstraw was actually factored out of these tests. Now we share + code yay. + +2006-07-21 11:03:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Better clipping. + Original commit message from CVS: + * ext/theora/theoradec.c: (clip_buffer): + Better clipping. + +2006-07-21 10:43:54 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Fix leak. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: (audioringbuffer_thread_func), + (gst_audioringbuffer_finalize), (gst_audioringbuffer_acquire), + (gst_audioringbuffer_release), (gst_audioringbuffer_stop): + Fix leak. + Avoid type casting when we can. + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_dispose): + Fix mem leak. + +2006-07-20 16:57:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsamixerelement.c: Make state change fail if the specified device can't be opened for some reason. + Original commit message from CVS: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_change_state): + Make state change fail if the specified device can't be opened + for some reason. + +2006-07-20 10:42:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/test.c: Example of a small audio/video player using decodebin. + Original commit message from CVS: + * gst/playback/test.c: (gen_video_element), (gen_audio_element), + (cb_newpad), (main): + Example of a small audio/video player using decodebin. + +2006-07-20 05:56:48 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/riff-ids.h: Add 'fact' chunk id + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + Add 'fact' chunk id + +2006-07-19 18:20:43 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Don't assert when not negotiated but post a meaningfull error message. Fixes ... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_chain), + (gst_base_rtp_depayload_change_state): + Don't assert when not negotiated but post a meaningfull + error message. Fixes #347918. + * gst-libs/gst/rtp/gstbasertppayload.c: + Add comment about better default MTU size. + * gst-libs/gst/rtp/gstrtpbuffer.c: (gst_rtp_buffer_validate_data): + Small cleanups, start docs. + +2006-07-19 14:46:36 +0000 Martin Szulecki <compiz@sukimashita.com> + + sys/v4l/gstv4lelement.c: If "device-name" is requested and the device is not open, try to temporarily open it to obta... + Original commit message from CVS: + Patch by: Martin Szulecki + * sys/v4l/gstv4lelement.c: (gst_v4lelement_get_property): + If "device-name" is requested and the device is not + open, try to temporarily open it to obtain this + information (#342494). + +2006-07-19 12:25:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstid3tag.c: Add TSSE <=> GST_TAG_ENCODER mapping (see #347898). + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Add TSSE <=> GST_TAG_ENCODER mapping (see #347898). + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/gstvorbistag.c: + Some more random const-ifications. + +2006-07-18 19:48:48 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst-libs/gst/riff/: add comment what those 16 bytes in struct _gst_riff_strh according to one avi-dumper are + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_template_caps): + Add more FOURCCs (sort list to make stuff easier to find), + add comment what those 16 bytes in struct _gst_riff_strh according to + one avi-dumper are + +2006-07-17 14:17:45 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/gdp/: remove parent_class setting, BOILERPLATE does this fix typo in comment + Original commit message from CVS: + 2006-07-17 Thomas Vander Stichele <thomas at apestaart dot org> + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_class_init): + * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init), + remove parent_class setting, BOILERPLATE does this + (gst_gdp_pay_reset_streamheader): + fix typo in comment + +2006-07-17 13:48:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: Const-ify two arrays. + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions), + (gst_audio_fixate_channel_positions): + Const-ify two arrays. + +2006-07-17 12:33:42 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsa.c: Fix typo, so that alsasink also advertises 8 channels if that's supported (tags: can, worms, open... + Original commit message from CVS: + * ext/alsa/gstalsa.c: (caps_add_channel_configuration): + Fix typo, so that alsasink also advertises 8 channels + if that's supported (tags: can, worms, open, alsa, ph34r). + +2006-07-17 12:01:04 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: *sigh*, when is the compiler going to warn when the comments are out-of-sync with the code.. R... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_internal_chain), + (gst_ogg_pad_submit_packet), (gst_ogg_demux_read_chain): + *sigh*, when is the compiler going to warn when the comments + are out-of-sync with the code.. Refix case of busted theora + headers with 0 granule pos. + +2006-07-14 17:56:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Fix 99% cpu load by waiting for absolute times on the clock. Fixes #347300. + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_wait), + (gst_base_rtp_depayload_change_state), + (gst_base_rtp_depayload_set_property), + (gst_base_rtp_depayload_get_property): + Fix 99% cpu load by waiting for absolute times on the + clock. Fixes #347300. + +2006-07-14 17:07:08 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/gsttheoraparse.h: ext/theora/theoraparse.c (theora_parse_drain_event_queue) (theora_parse_push_headers, th... + Original commit message from CVS: + 2006-07-14 Andy Wingo <wingo@pobox.com> + * ext/theora/gsttheoraparse.h: + * ext/theora/theoraparse.c (theora_parse_drain_event_queue) + (theora_parse_push_headers, theora_parse_clear_queue) + (theora_parse_drain_queue_prematurely, ) + (theora_parse_sink_event, theora_parse_change_state): Queue events + until we initialized our state, like in vorbisparse. + +2006-07-14 16:45:17 +0000 Iain * <iaingnome@gmail.com> + + ext/vorbis/vorbisparse.h: ext/vorbis/vorbisparse.c (vorbis_parse_drain_event_queue) (vorbis_parse_push_headers, vorbi... + Original commit message from CVS: + 2006-07-14 Andy Wingo <wingo@pobox.com> + * ext/vorbis/vorbisparse.h: + * ext/vorbis/vorbisparse.c (vorbis_parse_drain_event_queue) + (vorbis_parse_push_headers, vorbis_parse_clear_queue) + (vorbis_parse_drain_queue_prematurely, ) + (vorbis_parse_sink_event, vorbis_parse_change_state): Queue events + until we have initialized our state. Fixes seeking after an + initial pad block. + 2006-07-14 Andy Wingo <wingo@pobox.com> + Patch by: Iain * <iaingnome@gmail.com> + * ext/ogg/gstoggdemux.c (gst_ogg_demux_finalize): Fix memleak. + +2006-07-14 15:52:39 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Bump nano back to CVS + Original commit message from CVS: + * configure.ac: + Bump nano back to CVS + +=== release 0.10.9 === + +2006-07-14 15:51:24 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: releasing 0.10.9, "I walk the line" + Original commit message from CVS: + 2006-07-13 Jan Schmidt <thaytan@mad.scientist.com> + * configure.ac: + releasing 0.10.9, "I walk the line" + +2006-07-14 14:12:40 +0000 Michael Smith <msmith@xiph.org> + + tests/check/pipelines/vorbisenc.c: Move a g_cond_signal to earlier to avoid sometimes deadlocking (commonly happens w... + Original commit message from CVS: + * tests/check/pipelines/vorbisenc.c: (stop_pipeline): + Move a g_cond_signal to earlier to avoid sometimes deadlocking + (commonly happens when running this test under valgrind) when trying + to remove the buffer probe. + +2006-07-14 10:34:36 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/Makefile.am: + build as a plugin, not a lib + Original commit message from CVS: + build as a plugin, not a lib + +2006-07-13 16:43:22 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/xvimage/xvimagesink.c: Fix missing g_unlock from the previous commit + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new): + Fix missing g_unlock from the previous commit + +2006-07-13 16:34:04 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: Implement a locking order to ensure we always take the object lock before the x_lock and never vice-versa. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_change_state): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_change_state): + Implement a locking order to ensure we always take the object lock + before the x_lock and never vice-versa. + +2006-07-13 15:25:58 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + docs/plugins/: add more plugins and elements to docs + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + add more plugins and elements to docs + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain): + fix segfaults due to wrong g_free + add example + * gst/gdp/gstgdppay.c: + add example + +2006-07-13 14:38:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: Fix a caps leak when linking (#347304) + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (find_compatibles): + Fix a caps leak when linking (#347304) + * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), + (gst_ximagesink_ximage_destroy), (gst_ximagesink_xcontext_clear), + (gst_ximagesink_change_state): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimage_buffer_finalize), (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_xcontext_clear), (gst_xvimagesink_change_state): + Don't leak shared memory resources. Use the object lock to protect + against the xcontext disappearing while returning a buffer from the + pipeline. (#347304) + +2006-07-12 14:20:43 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisdec.c: gst_tag_list_merge() returns a new object. Take that into account when using it. This avoids ... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_finalize), + (vorbis_handle_comment_packet): + gst_tag_list_merge() returns a new object. Take that into account when + using it. This avoids memleak. + Revert previous commit which is not needed. + +2006-07-12 13:30:20 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisdec.c: Reset the decoder in finalize so that all fields get cleared. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_finalize): + Reset the decoder in finalize so that all fields get cleared. + +2006-07-12 13:24:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Don't try to post an error message when setting the clock fails as this can hap... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_set_clock), + (gst_base_audio_src_check_get_range), (gst_base_audio_src_create): + Don't try to post an error message when setting the clock fails + as this can happen when adding an element to a bin which will then + deadlock. Fixes #347296. + +2006-07-12 13:04:15 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisdec.c: Post tag messages on the bus even if we're not initialized. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_reset), + (vorbis_dec_sink_event), (vorbis_handle_comment_packet), + (vorbis_handle_type_packet): + Post tag messages on the bus even if we're not initialized. + If we're not initialized, we still postpone the event pushing of tags. + +2006-07-12 11:28:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + Revert last two changes that broke the freeze. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (set_hwparams), (gst_alsasink_prepare): + * gst-libs/gst/audio/gstringbuffer.c: (build_linear_format), + (gst_ring_buffer_debug_spec_caps), (gst_ring_buffer_parse_caps): + Revert last two changes that broke the freeze. + +2006-07-12 10:59:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.c: basesink calculates silence sample correctly for us. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (set_hwparams), (gst_alsasink_prepare): + basesink calculates silence sample correctly for us. + +2006-07-12 10:58:42 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Calculate correct silence samples so we don't fill our ringbuffer with noise. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (build_linear_format), + (gst_ring_buffer_debug_spec_caps), (gst_ring_buffer_parse_caps): + Calculate correct silence samples so we don't fill our ringbuffer + with noise. + +2006-07-12 10:37:18 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisdec.*: Delay sending events (newsegment, tags) until the decoder is properly initialized. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), + (gst_vorbis_dec_reset), (vorbis_dec_sink_event), + (vorbis_handle_comment_packet), (vorbis_handle_type_packet): + * ext/vorbis/vorbisdec.h: + Delay sending events (newsegment, tags) until the decoder is properly + initialized. + Fixes #347295 + +2006-07-11 22:40:13 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-07-11 21:04:16 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/elements/audioconvert.c: Patch from #347221 adding a test for audioconvert channel remappings. + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (get_float_mc_caps), + (get_int_mc_caps), (GST_START_TEST), (audioconvert_suite): + Patch from #347221 adding a test for audioconvert + channel remappings. + +2006-07-11 12:03:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstssaparse.c: Don't include the terminating NUL in the buffer size, it's only there for extra paranoia ... + Original commit message from CVS: + * gst/subparse/gstssaparse.c: (gst_ssa_parse_base_init), + (gst_ssa_parse_parse_line): + Don't include the terminating NUL in the buffer size, + it's only there for extra paranoia (would add random + '*' characters at the end of each subtitle since the + terminator itself is not valid UTF-8 technically). + Also fix indenting after boilerplate macro. + +2006-07-10 14:59:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: Also emit 'unknown-type' signal (which should really be called unhandled-type) if we fou... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (close_pad_link): + Also emit 'unknown-type' signal (which should really be + called unhandled-type) if we found potential decoders/demuxers + in the registry but none of them worked in the end (as in the + case where the plugins don't exist any longer but are still + listed in the registry). Fixes #329798. + +2006-07-08 13:48:58 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * ext/theora/theoraparse.c: + theoraparse.c (theora_parse_push_buffer) + Original commit message from CVS: + 2006-07-08 Andy Wingo <wingo@pobox.com> + * theoraparse.c (theora_parse_push_buffer) + (theora_parse_drain_queue_prematurely, theora_parse_drain_queue): + Add some more debugging. Fix granulepos reconstruction in the face + of discontinuities. + +2006-07-06 15:54:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Use gobject_class instead of G_OBJECT_CLASS (klass) + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init), + (gst_base_audio_sink_provide_clock): + Use gobject_class instead of G_OBJECT_CLASS (klass) + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init), (gst_base_audio_src_init), + (gst_base_audio_src_set_clock), (gst_base_audio_src_provide_clock), + (gst_base_audio_src_get_time), + (gst_base_audio_src_check_get_range), (gst_base_audio_src_create), + (gst_base_audio_src_create_ringbuffer): + Fix latency and buffer-time constants and properties ala basesink. + Implement pull based scheduling. Fixes #346527. + Set default blocksize in GstBaseSrc to 0, we default to pushing out + one segment. + Refuse slaving to another clock instead of silently not working. + Only provide a clock when we are actually able to do so. + Various small cleanups and compiler hints. + +2006-07-06 13:23:07 +0000 Lutz Mueller <lutz@topfrose.de> + + gst/typefind/gsttypefindfunctions.c: Add typefinding for text/html (#346581). + Original commit message from CVS: + Patch by: Lutz Mueller <lutz at topfrose de> + * gst/typefind/gsttypefindfunctions.c: (html_type_find), + (plugin_init): + Add typefinding for text/html (#346581). + +2006-07-06 13:12:02 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Fix SMIL typefinding, make xml_check_first_element() more useful. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (utf8_type_find), + (xml_check_first_element), (xml_type_find), (smil_type_find): + Fix SMIL typefinding, make xml_check_first_element() more + useful. + +2006-07-06 13:04:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.*: Protect list of elements with a subtitle-encoding property and the subtitle encoding m... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_init), + (gst_play_base_bin_finalize), (decodebin_element_added_cb), + (decodebin_element_removed_cb), (gst_play_base_bin_set_property): + * gst/playback/gstplaybasebin.h: + Protect list of elements with a subtitle-encoding property and + the subtitle encoding member itself with a lock of their own + instead of using the object lock. This prevents a dead-lock in + the element-remove callback in some circumstances when shutting + down playbin. + +2006-07-05 20:11:13 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/common/libgsttag.def: Export some new functions. + Original commit message from CVS: + * win32/common/libgsttag.def: + Export some new functions. + * win32/vs6/libgstogg.dsp: + Add a link to libgsttag-0.10.lib. + +2006-07-04 16:50:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsamixertrack.c: Some const-ification. + Original commit message from CVS: + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + Some const-ification. + +2006-07-04 14:06:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.c: Improve checking if we are dealing with a stream. Added some more uris that need buffe... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (is_stream), (gen_source_element): + Improve checking if we are dealing with a stream. Added some + more uris that need buffering. + +2006-07-03 10:43:31 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/vorbis/vorbisdec.c: Remove unused variable. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_do_clip): + Remove unused variable. + +2006-07-02 21:48:51 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + Makefile.am: include lcov.mak + Original commit message from CVS: + * Makefile.am: + include lcov.mak + * configure.ac: + add GCOV_LIBS to GST_LIBS + +2006-07-02 11:08:58 +0000 Michael Sheldon <webmaster@mikeasoft.com> + + ext/alsa/gstalsasrc.c: Add 32 bps to template caps and increase channels range from [1,2] to [1,MAX]. See #346326. + Original commit message from CVS: + Patch by: Michael Sheldon <webmaster at mikeasoft com> + * ext/alsa/gstalsasrc.c: + Add 32 bps to template caps and increase channels range + from [1,2] to [1,MAX]. See #346326. + +2006-06-30 12:04:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Recognise 'WMVA' video codec fourcc (#345879). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Recognise 'WMVA' video codec fourcc (#345879). + +2006-06-29 12:21:06 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: Fixed nasty memory leak + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + Fixed nasty memory leak + +2006-06-26 13:19:33 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gsttcp.c: fix logging + Original commit message from CVS: + * gst/tcp/gsttcp.c: (gst_tcp_read_buffer), + (gst_tcp_gdp_read_buffer), (gst_tcp_gdp_read_caps): + fix logging + +2006-06-23 16:45:50 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: Protect remove_fakesink using a mutex, so that we don't try and remove the fakesink simu... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (gst_decode_bin_finalize), (add_fakesink), + (remove_fakesink), (pad_probe), (gst_decode_bin_change_state): + Protect remove_fakesink using a mutex, so that we don't try and + remove the fakesink simultaneously from multiple threads. + When going from READY to PAUSED, restore the fakesink, so that + it is there when decodebin gets reused. + +2006-06-23 09:53:09 +0000 Tim-Philipp Müller <tim@centricular.net> + + Use GST_DEBUG_CATEGORY_STATIC where possible (#342503). + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + * gst/videorate/gstvideorate.c: + * gst/videotestsrc/gstvideotestsrc.c: + * sys/v4l/gstv4ljpegsrc.c: + * sys/v4l/gstv4lmjpegsink.c: + * sys/v4l/gstv4lsrc.c: + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + Use GST_DEBUG_CATEGORY_STATIC where possible (#342503). + +2006-06-23 09:09:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + Use GST_DEBUG_CATEGORY_STATIC where possible (#342503) and fix one GObject boilerplate macro. + Original commit message from CVS: + * ext/directfb/dfbvideosink.c: + * ext/gsm/gstgsmdec.c: + * ext/gsm/gstgsmenc.c: + * ext/libmms/gstmms.c: + * ext/neon/gstneonhttpsrc.c: + * ext/theora/theoradec.c: + * gst/freeze/gstfreeze.c: + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.c: + * sys/glsink/glimagesink.c: + Use GST_DEBUG_CATEGORY_STATIC where possible (#342503) + and fix one GObject boilerplate macro. + +2006-06-22 12:13:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/tags.c: Second field in GEnumValue shouldn't be a description, but a stringified version of the enum... + Original commit message from CVS: + * gst-libs/gst/tag/tags.c: (register_tag_image_type_enum): + Second field in GEnumValue shouldn't be a description, + but a stringified version of the enum value. + +2006-06-22 12:03:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/ximage/ximagesink.c: Avoid type checking in buffer casts. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), + (gst_ximage_buffer_free), (gst_ximagesink_ximage_put), + (gst_ximagesink_setcaps), (gst_ximagesink_buffer_alloc): + Avoid type checking in buffer casts. + Avoid caps copy in buffer_alloc when we can. + Use pad_peer_accept. + +2006-06-22 11:01:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/tag.h: Oops, make that 'Since: 0.10.9'. + Original commit message from CVS: + * gst-libs/gst/tag/tag.h: + Oops, make that 'Since: 0.10.9'. + +2006-06-22 10:55:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + API: add GstTagImageType enum to describe images contained in image tags (#345641). + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: (register_tag_image_type_enum), + (gst_tag_image_type_get_type): + API: add GstTagImageType enum to describe images contained + in image tags (#345641). + +2006-06-22 10:31:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/tcp/gstmultifdsink.c: Fix warnings with gst-inspect: "buffers-min" property should be of G_TYPE_INT and not G_TYP... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + Fix warnings with gst-inspect: "buffers-min" property + should be of G_TYPE_INT and not G_TYPE_INT64. Also fix + typo in property description. + +2006-06-22 10:10:51 +0000 Cody Russell <bratsche@gnome.org> + + gst/: Avoid unnecessary class cast check in class_init functions (#337747). + Original commit message from CVS: + Patch by: Cody Russell <bratsche at gnome org> + * gst/audioresample/gstaudioresample.c: + (gst_audioresample_class_init): + * gst/playback/gststreamselector.c: + (gst_stream_selector_class_init): + * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init): + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_class_init): + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_class_init): + * gst/tcp/gsttcpserversink.c: (gst_tcp_server_sink_class_init): + * gst/tcp/gsttcpserversrc.c: (gst_tcp_server_src_class_init): + * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init): + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_class_init): + * gst/volume/gstvolume.c: (gst_volume_class_init): + Avoid unnecessary class cast check in class_init + functions (#337747). + +2006-06-21 18:39:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: g_markup_escape_text() REALLY doesn't like non-UTF8 input and doesn't validate its input ... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_make_utf8), + (gst_text_overlay_video_chain): + g_markup_escape_text() REALLY doesn't like non-UTF8 input + and doesn't validate its input either (and neither did + textoverlay it seems). Let's do that then and fix #345206. + +2006-06-19 17:12:57 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.*: Added shiny new burst-on-connect methods. + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_sync_method_get_type), + (gst_unit_type_get_type), (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_init), (gst_multi_fd_sink_add_full), + (gst_multi_fd_sink_add), (gst_multi_fd_sink_handle_client_read), + (find_syncframe), (find_limits), (assign_value), + (count_burst_unit), (gst_multi_fd_sink_new_client), + (gst_multi_fd_sink_handle_client_write), + (gst_multi_fd_sink_queue_buffer), (gst_multi_fd_sink_render), + (gst_multi_fd_sink_set_property), (gst_multi_fd_sink_get_property), + (gst_multi_fd_sink_change_state): + * gst/tcp/gstmultifdsink.h: + Added shiny new burst-on-connect methods. + Add properties to control the minimal amount of data queued. + Small cleanups. + API: bytes-min property + API: time-min property + API: buffers-min property + API: burst-unit property + API: burst-value property + API: add-full signal + * gst/tcp/gsttcp-marshal.list: + Added new marshaller code for the new signal. + * tests/check/elements/multifdsink.c: (GST_START_TEST), + (multifdsink_suite): + Added testcases for new burst methods. + +2006-06-19 11:35:47 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update for latest changes + Original commit message from CVS: + update for latest changes + +2006-06-19 09:57:50 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/theora/theoradec.c: Implement clipping for accurate seeking. + Original commit message from CVS: + * ext/theora/theoradec.c: (clip_buffer), (theora_dec_push): + Implement clipping for accurate seeking. + Closes #345225 + +2006-06-19 09:08:05 +0000 Philip Jaegenstedt <philip@lysator.liu.se> + + gst/videoscale/gstvideoscale.c: Make videoscale support RGBA, ARGB, BGRA and ABGR. Fixes #345131 + Original commit message from CVS: + Patch by: Philip Jaegenstedt <philip at lysator dot liu dot se> + * gst/videoscale/gstvideoscale.c: (gst_video_scale_prepare_size), + (gst_video_scale_transform): + Make videoscale support RGBA, ARGB, BGRA and ABGR. Fixes #345131 + +2006-06-17 14:18:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery + Original commit message from CVS: + ChangeLog surgery + +2006-06-17 14:13:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Fix --disable-extern (can't set conditionals conditionally, #343602). + Original commit message from CVS: + * configure.ac: + Fix --disable-extern (can't set conditionals conditionally, + #343602). + +2006-06-16 15:43:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/audioresample.c: Add test case for bug #342789 fixed below. + Original commit message from CVS: + * tests/check/elements/audioresample.c: (test_reuse), + (audioresample_suite): + Add test case for bug #342789 fixed below. + +2006-06-16 15:17:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioresample/gstaudioresample.c: Implement GstBaseTransform::start and ::stop so that audioresample can clear it... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + (gst_audioresample_class_init), (gst_audioresample_init), + (audioresample_start), (audioresample_stop), + (gst_audioresample_set_property), (gst_audioresample_get_property): + Implement GstBaseTransform::start and ::stop so that audioresample + can clear its internal state properly and be reused insted of + causing non-negotiated errors with playbin under some circumstances + (#342789). + * tests/check/elements/audioresample.c: (setup_audioresample), + (cleanup_audioresample): + Need to set element state here so that ::start and ::stop are + called. + +2006-06-16 13:59:29 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst-libs/gst/riff/riff-read.c: Parse extra data better, apparently it's right behind the normal strf header size. Fix... + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian dot net> + * gst-libs/gst/riff/riff-read.c: (gst_riff_parse_strf_vids): + Parse extra data better, apparently it's right behind + the normal strf header size. Fixes #343500. + +2006-06-16 11:04:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.c: If we fail to set the buffer_time and period_time alsa parameters, post a warning and leave a... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (set_hwparams): + If we fail to set the buffer_time and period_time alsa + parameters, post a warning and leave alsa select a + default instead of failing. Fixes #342085 + +2006-06-16 10:30:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery (it wouldn't have crashed, just shown bogus values) + Original commit message from CVS: + ChangeLog surgery (it wouldn't have crashed, just shown bogus values) + +2006-06-16 10:20:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + Remove GST_CDDA_TAG_TRACK_TAGS again, it is #ifdef 0'ed out in the header file and shouldn't be listed in the docs. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/cdda/gstcddabasesrc.h: + Remove GST_CDDA_TAG_TRACK_TAGS again, it is #ifdef 0'ed + out in the header file and shouldn't be listed in the docs. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_chunk): + Fix it so that it doesn't crash in the debug statement. + +2006-06-16 10:02:25 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/: add remaining symbols into correct setions + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + add remaining symbols into correct setions + * gst-libs/gst/audio/gstringbuffer.c: + fix incomplete docs + * gst-libs/gst/audio/gstringbuffer.h: + comment out not yet implemented function + * gst-libs/gst/floatcast/floatcast.h: + * gst-libs/gst/netbuffer/gstnetbuffer.c: + add short descriptions + * gst-libs/gst/interfaces/propertyprobe.c: + fix return value docs + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_chunk): + simplify debug logging + * gst-libs/gst/riff/riff-read.h: + sync function prototype and docs + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + remove left over symbol + +2006-06-16 09:56:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + Use GST_PLUGIN_DOCS macro in configure.ac, add + Original commit message from CVS: + * autogen.sh: + * configure.ac: + * docs/Makefile.am: + Use GST_PLUGIN_DOCS macro in configure.ac, add + --enable-plugin-docs default to autogen.sh and use + ENABLE_PLUGIN_DOCS conditional in Makefile.am (#344039). + +2006-06-15 15:27:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Combine GstFlowReturn from the source pads to give a meaningfull result to the upstream peer o... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain_peer), + (gst_ogg_demux_activate_chain), (gst_ogg_demux_combine_flows), + (gst_ogg_demux_loop): + Combine GstFlowReturn from the source pads to give a + meaningfull result to the upstream peer or to stop the + processing task in case of errors. + +2006-06-14 14:49:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreaminfo.c: Try GST_TAG_CODEC as fallback when extracting the codec name; more debug info. + Original commit message from CVS: + * gst/playback/gststreaminfo.c: (cb_probe): + Try GST_TAG_CODEC as fallback when extracting the + codec name; more debug info. + +2006-06-14 14:34:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/: Extract language tags from ogm subtitle streams, so that the subtitle menu choices are labelled correctly in + Original commit message from CVS: + * ext/ogg/Makefile.am: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): + Extract language tags from ogm subtitle streams, so that + the subtitle menu choices are labelled correctly in + Totem (fixes #344708). + +2006-06-14 09:13:54 +0000 Alessandro Decina <alessandro@nnva.org> + + ext/ogg/gstoggmux.c: Fix various leaks. Fixes #343699. + Original commit message from CVS: + Patch by: Alessandro Decina <alessandro at nnva dot org> + * ext/ogg/gstoggmux.c: (gst_ogg_mux_get_type), (gst_ogg_mux_clear), + (gst_ogg_mux_release_pad), (gst_ogg_mux_get_headers), + (gst_ogg_mux_set_header_on_caps), (gst_ogg_mux_init_collectpads), + (gst_ogg_mux_clear_collectpads), (gst_ogg_mux_change_state): + Fix various leaks. Fixes #343699. + Add x-smoke mime type. + +2006-06-14 08:17:45 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-ids.h: Add IDs for 'bext' chunks (see #343837). + Original commit message from CVS: + * gst-libs/gst/riff/riff-ids.h: + Add IDs for 'bext' chunks (see #343837). + +2006-06-12 12:44:38 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: Honour font face tags in SAMI subtitles (#344503). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/subparse/samiparse.c: (sami_context_pop_state), + (handle_start_font), (end_sami_element): + Honour font face tags in SAMI subtitles (#344503). + +2006-06-11 20:41:56 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + po/POTFILES.in: add missing files containing translatable strings + Original commit message from CVS: + * po/POTFILES.in: + add missing files containing translatable strings + +2006-06-11 19:55:32 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/tmpl/.cvsignore: we don't want those *.sgml files in CVS either + Original commit message from CVS: + * docs/libs/tmpl/.cvsignore: + we don't want those *.sgml files in CVS either + +2006-06-11 19:44:49 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ignore more + Original commit message from CVS: + * docs/libs/.cvsignore: + * tests/check/elements/.cvsignore: + * tests/check/libs/.cvsignore: + ignore more + +2006-06-11 18:33:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/Makefile.am: also commiting the changed Makefile.am (added more libs to the doc-build) + Original commit message from CVS: + * docs/libs/Makefile.am: + also commiting the changed Makefile.am (added more libs to the + doc-build) + +2006-06-11 17:08:26 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + docs/libs/: first batch of reordering things, add index & hierarchy + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + first batch of reordering things, add index & hierarchy + +2006-06-11 14:08:54 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * ext/alsa/Makefile.am: + * ext/cdparanoia/Makefile.am: + * ext/gnomevfs/Makefile.am: + * ext/libvisual/Makefile.am: + * ext/ogg/Makefile.am: + * ext/pango/Makefile.am: + * ext/theora/Makefile.am: + * ext/vorbis/Makefile.am: + * sys/v4l/Makefile.am: + * sys/ximage/Makefile.am: + * sys/xvimage/Makefile.am: + further clean up build + Original commit message from CVS: + further clean up build + +2006-06-11 12:14:18 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: use GST_PKG_CHECK_MODULES, cleans up output + Original commit message from CVS: + * configure.ac: + use GST_PKG_CHECK_MODULES, cleans up output + +2006-06-11 12:10:55 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * win32/common/config.h: + update to cvs + Original commit message from CVS: + update to cvs + +2006-06-10 18:52:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfsuri.c: Add support for burn:// URIs (#343385); const-ify things a bit, use G_N_ELEMENTS inste... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfsuri.c: (gst_gnomevfs_get_supported_uris): + Add support for burn:// URIs (#343385); const-ify things a bit, + use G_N_ELEMENTS instead of hard-coded array size. + +2006-06-10 18:25:07 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: Fix up broken entities before passing them to libxml *sigh*. (#343303). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/subparse/samiparse.c: (fix_invalid_entities), (parse_sami): + Fix up broken entities before passing them to libxml *sigh*. + (#343303). + +2006-06-09 18:52:35 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + back to trunk + Original commit message from CVS: + back to trunk + +=== release 0.10.8 === + +2006-06-09 18:49:26 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/config.h: + releasing 0.10.8 + Original commit message from CVS: + releasing 0.10.8 + +2006-06-07 11:04:09 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + 0.10.7.2 prerelease + Original commit message from CVS: + * configure.ac: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * win32/common/config.h: + 0.10.7.2 prerelease + +2006-06-07 11:03:03 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + move last template doc snippets to source code and delete them + Original commit message from CVS: + * docs/libs/tmpl/gstaudio.sgml: + * docs/libs/tmpl/gstcolorbalance.sgml: + * docs/libs/tmpl/gstmixer.sgml: + * docs/libs/tmpl/gstringbuffer.sgml: + * docs/libs/tmpl/gsttuner.sgml: + * docs/libs/tmpl/gstxoverlay.sgml: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/audio/gstringbuffer.c: + * gst-libs/gst/interfaces/colorbalance.c: + * gst-libs/gst/interfaces/mixer.c: + * gst-libs/gst/interfaces/tuner.c: + * gst-libs/gst/interfaces/xoverlay.c: + move last template doc snippets to source code and delete them + +2006-06-06 16:26:59 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/gstgdppay.c: + adapt to new api + Original commit message from CVS: + adapt to new api + +2006-06-06 14:39:15 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: enable building of GDP elements + Original commit message from CVS: + * configure.ac: + enable building of GDP elements + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain): + * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init), + (gst_gdp_pay_init), (gst_gdp_buffer_from_caps), + (gst_gdp_pay_buffer_from_buffer), (gst_gdp_buffer_from_event), + (gst_gdp_pay_reset_streamheader), (gst_gdp_pay_sink_event), + (gst_gdp_pay_set_property), (gst_gdp_pay_get_property), + (gst_gdp_pay_change_state): + * gst/gdp/gstgdppay.h: + add version 1.0 + +2006-06-06 11:13:18 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoraparse.c: Mark DELTA_UNIT on non-keyframes. + Original commit message from CVS: + * ext/theora/theoraparse.c: (theora_parse_drain_queue_prematurely), + (theora_parse_drain_queue): + Mark DELTA_UNIT on non-keyframes. + +2006-06-03 21:06:49 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/audio/: Document better the fact that latency_time and buffer_time are values stored in microseconds, an... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init), (gst_base_audio_sink_setcaps): + * gst-libs/gst/audio/gstbaseaudiosink.h: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_parse_caps), + (gst_ring_buffer_samples_done): + * gst-libs/gst/audio/gstringbuffer.h: + Document better the fact that latency_time and buffer_time are values + stored in microseconds, and not the usual GStreamer nanoseconds. + Change the variables (compatibly) that store them from GstClockTime + to guint64 to make it more clear that they're not storing clock times. + Also, remove the bogus property description that says the user can + specify -1 to get the default value, since that's never been the case. + When computing the default segment size for the ring buffer, make it + an integer number of samples. + When the sub-class indicates a delay greater than the number of + samples we've written return 0 from the audio sink get_time method. + +2006-06-02 17:01:02 +0000 Michael Smith <msmith@xiph.org> + + tests/check/: Don't busy-wait in tests; this was causing test timeouts very frequently when running under valgrind. + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (set_channel_positions), + (get_float_mc_caps), (get_int_mc_caps): + * tests/check/elements/audioresample.c: + * tests/check/elements/audiotestsrc.c: (GST_START_TEST): + * tests/check/elements/videorate.c: + * tests/check/elements/videotestsrc.c: (GST_START_TEST): + * tests/check/elements/volume.c: + * tests/check/elements/vorbisdec.c: + * tests/check/pipelines/vorbisenc.c: (GST_START_TEST): + Don't busy-wait in tests; this was causing test timeouts very + frequently when running under valgrind. + +2006-06-02 16:45:59 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/gdp/gstgdpdepay.c: + * gst/gdp/gstgdppay.h: + small fixes + Original commit message from CVS: + small fixes + +2006-06-02 16:35:12 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + fail_if_can_read is racy + Original commit message from CVS: + fail_if_can_read is racy + +2006-06-02 16:26:54 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/: make multifdsink properly deal with streamheader: + Original commit message from CVS: + * gst/tcp/README: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_init), + (gst_multi_fd_sink_remove_client_link), + (gst_multi_fd_sink_client_queue_caps), + (gst_multi_fd_sink_client_queue_buffer), + (gst_multi_fd_sink_handle_client_write), + (gst_multi_fd_sink_render): + * gst/tcp/gstmultifdsink.h: + make multifdsink properly deal with streamheader: + - streamheader is taken from caps + - buffers marked with IN_CAPS are not sent + - streamheaders are sent, on connection, from the caps of the + buffer where the client gets positioned to + - further streamheader changes are done every time the client + will receive a buffer with different caps + * tests/check/elements/multifdsink.c: (GST_START_TEST), + (gst_multifdsink_create_streamheader): + add tests for this + +2006-06-02 15:06:59 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisdec.c: Reinstate limit on channel count. Vorbis does not define the meaning of > 6 channels, so they... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_identification_packet): + Reinstate limit on channel count. Vorbis does not define the meaning + of > 6 channels, so they're just independent channels. Gstreamer + currently has no mechanism to represent N independent channels. + +2006-06-02 14:23:34 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisdec.c: Don't arbitrarily restrict channel counts and rate in vorbis. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_handle_identification_packet): + Don't arbitrarily restrict channel counts and rate in vorbis. + In terms of effects likely on real-world files, this fixes 96kHz + playback of vorbis. + +2006-06-02 14:19:18 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/audioconvert.c: More correct float->int conversion. + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float): + More correct float->int conversion. + +2006-06-02 14:07:42 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggdemux.c: Don't accidently send GST_CLOCK_TIME_NONE as a new segment start value. Fixes g-critical on tr... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_perform_seek): + Don't accidently send GST_CLOCK_TIME_NONE as a new segment start + value. Fixes g-critical on trying to play back ogg containing + unknown codec. + +2006-06-02 10:34:12 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybasebin.*: Make the subtitle detection work from any thread so we don't deadlock. Fixes #343397. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (group_create), (group_commit), + (setup_source): + * gst/playback/gstplaybasebin.h: + Make the subtitle detection work from any thread so we don't + deadlock. Fixes #343397. + +2006-06-02 10:28:32 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/gdp/gstgdppay.c: add crc-header and crc-payload properties don't error out on some things that are recoverable + Original commit message from CVS: + * gst/gdp/gstgdppay.c: (gst_gdp_pay_class_init), + (gst_gdp_pay_init), (gst_gdp_buffer_from_caps), + (gst_gdp_pay_buffer_from_buffer), (gst_gdp_buffer_from_event), + (gst_gdp_pay_reset_streamheader), (gst_gdp_pay_chain), + (gst_gdp_pay_sink_event), (gst_gdp_pay_set_property), + (gst_gdp_pay_get_property): + add crc-header and crc-payload properties + don't error out on some things that are recoverable + * tests/check/elements/gdppay.c: (GST_START_TEST), (gdppay_suite): + add test for crc + +2006-06-02 09:17:07 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gsttcp.c: + show type number when packet is of the wrong type + Original commit message from CVS: + show type number when packet is of the wrong type + +2006-06-01 23:04:32 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/volume/Makefile.am: Seriously, it's not *that* hard to get compilation right. Even a drunk can do it ! Add LIBOI... + Original commit message from CVS: + * gst/volume/Makefile.am: + Seriously, it's not *that* hard to get compilation right. Even + a drunk can do it ! Add LIBOIL CFLAGS and LIBS + +2006-06-01 22:00:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix more gobject macros: obj<->klass, GstXXX<->GstXXXClass + Original commit message from CVS: + * ext/alsaspdif/alsaspdifsink.h: + * ext/amrwb/gstamrwbdec.h: + * ext/amrwb/gstamrwbenc.h: + * ext/amrwb/gstamrwbparse.h: + * ext/arts/gst_arts.h: + * ext/artsd/gstartsdsink.h: + * ext/audiofile/gstafparse.h: + * ext/audiofile/gstafsink.h: + * ext/audiofile/gstafsrc.h: + * ext/audioresample/gstaudioresample.h: + * ext/bz2/gstbz2dec.h: + * ext/bz2/gstbz2enc.h: + * ext/dirac/gstdiracdec.h: + * ext/directfb/dfbvideosink.h: + * ext/divx/gstdivxdec.h: + * ext/divx/gstdivxenc.h: + * ext/dts/gstdtsdec.h: + * ext/faac/gstfaac.h: + * ext/gsm/gstgsmdec.h: + * ext/gsm/gstgsmenc.h: + * ext/ivorbis/vorbisenc.h: + * ext/libfame/gstlibfame.h: + * ext/nas/nassink.h: + * ext/neon/gstneonhttpsrc.h: + * ext/polyp/polypsink.h: + * ext/sdl/sdlaudiosink.h: + * ext/sdl/sdlvideosink.h: + * ext/shout/gstshout.h: + * ext/snapshot/gstsnapshot.h: + * ext/sndfile/gstsf.h: + * ext/swfdec/gstswfdec.h: + * ext/tarkin/gsttarkindec.h: + * ext/tarkin/gsttarkinenc.h: + * ext/theora/theoradec.h: + * ext/wavpack/gstwavpackdec.h: + * ext/wavpack/gstwavpackparse.h: + * ext/xine/gstxine.h: + * ext/xvid/gstxviddec.h: + * ext/xvid/gstxvidenc.h: + * gst/cdxaparse/gstcdxaparse.h: + * gst/cdxaparse/gstcdxastrip.h: + * gst/colorspace/gstcolorspace.h: + * gst/festival/gstfestival.h: + * gst/freeze/gstfreeze.h: + * gst/gdp/gstgdpdepay.h: + * gst/gdp/gstgdppay.h: + * gst/modplug/gstmodplug.h: + * gst/mpeg1sys/gstmpeg1systemencode.h: + * gst/mpeg1videoparse/gstmp1videoparse.h: + * gst/mpeg2sub/gstmpeg2subt.h: + * gst/mpegaudioparse/gstmpegaudioparse.h: + * gst/multifilesink/gstmultifilesink.h: + * gst/overlay/gstoverlay.h: + * gst/playondemand/gstplayondemand.h: + * gst/qtdemux/qtdemux.h: + * gst/rtjpeg/gstrtjpegdec.h: + * gst/rtjpeg/gstrtjpegenc.h: + * gst/smooth/gstsmooth.h: + * gst/smoothwave/gstsmoothwave.h: + * gst/spectrum/gstspectrum.h: + * gst/speed/gstspeed.h: + * gst/stereo/gststereo.h: + * gst/switch/gstswitch.h: + * gst/tta/gstttadec.h: + * gst/tta/gstttaparse.h: + * gst/videodrop/gstvideodrop.h: + * gst/xingheader/gstxingmux.h: + * sys/directdraw/gstdirectdrawsink.h: + * sys/directsound/gstdirectsoundsink.h: + * sys/dxr3/dxr3audiosink.h: + * sys/dxr3/dxr3spusink.h: + * sys/dxr3/dxr3videosink.h: + * sys/qcam/gstqcamsrc.h: + * sys/vcd/vcdsrc.h: + Fix more gobject macros: obj<->klass, GstXXX<->GstXXXClass + +2006-06-01 20:39:30 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/volume/gstvolume.*: rewrite the passthrough check, split _int16 and _int16_clamp, fix another property desc., rem... + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_choose_func), + (volume_update_real_volume), (gst_volume_class_init), + (gst_volume_init), (volume_process_float), (volume_process_int16), + (volume_process_int16_clamp), (volume_set_caps), + (volume_transform_ip), (plugin_init): + * gst/volume/gstvolume.h: + rewrite the passthrough check, split _int16 and _int16_clamp, fix + another property desc., remove unused param from process function + * tests/check/elements/volume.c: (volume_suite): + reactivate the passthrough test + +2006-06-01 19:19:51 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix more gobject macros: obj<->klass, GstXXX<->GstXXXClass + Original commit message from CVS: + * ext/alsa/gstalsamixerelement.h: + * ext/alsa/gstalsamixeroptions.h: + * ext/alsa/gstalsamixertrack.h: + * ext/gnomevfs/gstgnomevfssink.h: + * ext/gnomevfs/gstgnomevfssrc.h: + * ext/theora/gsttheoradec.h: + * ext/theora/gsttheoraenc.h: + * ext/theora/gsttheoraparse.h: + * ext/vorbis/vorbisparse.h: + * gst-libs/gst/audio/gstaudioclock.h: + * gst-libs/gst/audio/gstaudiofilter.h: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + * gst/audioconvert/gstaudioconvert.h: + * gst/audioresample/gstaudioresample.h: + * gst/audiotestsrc/gstaudiotestsrc.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.h: + * gst/playback/gststreamselector.h: + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpclientsink.h: + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpserversink.h: + * gst/tcp/gsttcpserversrc.h: + * gst/videorate/gstvideorate.h: + * gst/videoscale/gstvideoscale.h: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/volume/gstvolume.h: + * sys/v4l/gstv4ljpegsrc.h: + * sys/v4l/gstv4lmjpegsink.h: + * sys/v4l/gstv4lmjpegsrc.h: + * sys/v4l/gstv4lsrc.h: + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.h: + * tests/old/testsuite/alsa/sinesrc.h: + Fix more gobject macros: obj<->klass, GstXXX<->GstXXXClass + +2006-05-31 16:56:45 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + remove wrong commit + Original commit message from CVS: + remove wrong commit + +2006-05-31 16:21:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: Handle DISCONT. + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_reset), + (gst_visual_sink_setcaps), (gst_visual_sink_event), + (gst_visual_src_event), (get_buffer), (gst_visual_chain): + Handle DISCONT. + Use running time before doing QoS. + Handle mono too. + +2006-05-31 14:17:30 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + docs/libs/Makefile.am: set a magic variable to indicate we know the docs are incomplete + Original commit message from CVS: + * docs/libs/Makefile.am: + set a magic variable to indicate we know the docs are incomplete + +2006-05-30 20:33:59 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/common/libgstvideo.def: export gst_video_calculate_display_ratio + Original commit message from CVS: + * win32/common/libgstvideo.def: + export gst_video_calculate_display_ratio + * win32/vs6/libgstvideoscale.dsp: + add link to libgstvideo-0.10.lib + +2006-05-30 19:00:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Throw a more comprehensible error for rtsp:// URIs (rather than erroring out with a ne... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gen_source_element): + Throw a more comprehensible error for rtsp:// URIs (rather + than erroring out with a negotiation error later on) until + we fix playbin to handle rtspsrc etc. + +2006-05-30 16:09:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/pango/gsttextoverlay.c: Added some FIXMEs. + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_src_event), + (gst_text_overlay_text_event): + Added some FIXMEs. + +2006-05-30 16:07:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.*: Implement release_request_pad. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_class_init), (gst_adder_init), + (gst_adder_request_new_pad), (gst_adder_release_pad): + * gst/adder/gstadder.h: + Implement release_request_pad. + Make padcounter atomic. + * tests/check/elements/adder.c: (GST_START_TEST), (adder_suite): + Added check for release_pad in adder. + +2006-05-30 16:04:14 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Fix build again. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_chain_new_stream): + Fix build again. + +2006-05-30 14:59:24 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/ogg/gstoggdemux.c: add more debugging clean up printf formats for granulepos and serialno + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_typefind), + (gst_ogg_demux_chain_elem_pad), (gst_ogg_demux_queue_data), + (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), + (gst_ogg_pad_submit_page), (gst_ogg_chain_new_stream), + (gst_ogg_demux_seek), (gst_ogg_demux_get_data), + (gst_ogg_demux_get_next_page), (gst_ogg_demux_do_seek), + (gst_ogg_demux_bisect_forward_serialno), + (gst_ogg_demux_read_chain), (gst_ogg_demux_find_chains), + (gst_ogg_demux_chain), (gst_ogg_demux_loop), (gst_ogg_print): + add more debugging + clean up printf formats for granulepos and serialno + +2006-05-30 14:31:43 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + * tests/check/generic/states.c: + properly fail if we can't make an element + Original commit message from CVS: + properly fail if we can't make an element + +2006-05-30 13:22:58 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.*: Multi-channel caps negotiation, so we can do proper multichannel vorbis encoding, negotiated ... + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (raw_caps_factory), + (gst_vorbis_enc_class_init), (gst_vorbis_enc_dispose), + (gst_vorbis_enc_generate_sink_caps), (gst_vorbis_enc_sink_getcaps), + (gst_vorbis_enc_init), (gst_vorbis_enc_buffer_from_header_packet), + (gst_vorbis_enc_chain), (gst_vorbis_enc_change_state): + * ext/vorbis/vorbisenc.h: + Multi-channel caps negotiation, so we can do proper multichannel + vorbis encoding, negotiated through audioconvert. + +2006-05-30 11:45:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/elements/adder.c: Added check to show that #339935 is fixed with ongoing adder and collectpads fixes. + Original commit message from CVS: + * tests/check/elements/adder.c: (test_event_message_received), + (test_play_twice_message_received), (GST_START_TEST), + (adder_suite): + Added check to show that #339935 is fixed with ongoing + adder and collectpads fixes. + +2006-05-29 17:19:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.c: Don't leak pad name. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_request_new_pad): + Don't leak pad name. + +2006-05-29 15:49:53 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.c: Fix adder seeking. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_query_duration), + (forward_event_func), (forward_event), (gst_adder_src_event): + Fix adder seeking. + Make query/seeking code threadsafe. + * tests/check/Makefile.am: + * tests/check/elements/adder.c: (test_event_message_received), + (GST_START_TEST), (test_play_twice_message_received): + Fix adder test case. + +2006-05-29 13:21:00 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/playback/gstplaybasebin.*: Add 'subtitle-encoding' property to playbin, so applications can force a subtitle enco... + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (gst_play_base_bin_dispose), + (set_encoding_element), (decodebin_element_added_cb), + (decodebin_element_removed_cb), (setup_subtitle), (setup_source), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property): + * gst/playback/gstplaybasebin.h: + Add 'subtitle-encoding' property to playbin, so applications can + force a subtitle encoding for non-UTF8 subtitles (#342268). + * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init), + (gst_sub_parse_set_property): + Rename recently-added 'encoding' property to 'subtitle-encoding' + (so it can be proxied by playbin/decodebin in a generic way + with less danger of false positives). + +2006-05-29 11:04:48 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/gstaudioconvert.c: Patch from #341562: give more specific audio caps in get_caps, so that basetransf... + Original commit message from CVS: + * gst/audioconvert/gstaudioconvert.c: (make_lossless_changes), + (append_with_other_format), (set_structure_widths), + (gst_audio_convert_transform_caps): + Patch from #341562: give more specific audio caps in get_caps, so + that basetransform can make better decisions on what caps to + negotiate. + +2006-05-28 20:04:12 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/volume.c: make it compile again + Original commit message from CVS: + * tests/check/elements/volume.c: + make it compile again + +2006-05-28 19:56:25 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/volume.c: disable test until #343196 gets resolved + Original commit message from CVS: + * tests/check/elements/volume.c: (volume_suite): + disable test until #343196 gets resolved + +2006-05-28 19:42:27 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/gstadder.c: Make it easier to copy&paste + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_get_type): + Make it easier to copy&paste + * gst/volume/Makefile.am: + * gst/volume/gstvolume.c: (volume_update_real_volume), + (gst_volume_set_volume), (gst_volume_set_mute), + (gst_volume_class_init), (volume_process_int16), (volume_set_caps), + (volume_transform_ip), (volume_update_mute), + (volume_update_volume): + * gst/volume/gstvolume.h: + Add own debug category, move duplicate code to helper function, fix + property texts, add more comments and prepare ffor liboil-goodness + * tests/check/Makefile.am: + * tests/check/elements/volume.c: (GST_START_TEST), (volume_suite): + add test for mute and passtrough case, be a bit more verbose to track + failure + * tests/check/generic/states.c: (GST_START_TEST): + catch elements that fail to instantiate + +2006-05-28 09:37:18 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/pipelines/: Comment out tests using parse_launch() if core was built without parsing capabilities. + Original commit message from CVS: + * tests/check/pipelines/simple-launch-lines.c: + * tests/check/pipelines/theoraenc.c: + * tests/check/pipelines/vorbisenc.c: + Comment out tests using parse_launch() if core was built without + parsing capabilities. + +2006-05-27 13:34:03 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/check/Makefile.am: Extra bonus points for whoever explains to ensonic that you are meant to test unit tests tho... + Original commit message from CVS: + * tests/check/Makefile.am: + Extra bonus points for whoever explains to ensonic that you are meant + to test unit tests thoroughly before commiting them, especially if + you know it's going to break. + De-activated element/adder tests. + +2006-05-27 13:09:16 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Marking caps conversion issues as GST_WARNING is way too verbose, + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_smpfmt_to_caps): + Marking caps conversion issues as GST_WARNING is way too verbose, + Moving them to GST_LOG. + +2006-05-27 11:26:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + README: Replace current README (containing the release notes from some 0.9.x version) with a proper README taken from... + Original commit message from CVS: + * README: + Replace current README (containing the release notes from + some 0.9.x version) with a proper README taken from the core. + +2006-05-26 15:52:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Small cleanups. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query), + (vorbis_dec_src_event), (vorbis_dec_sink_event), (vorbis_do_clip), + (vorbis_dec_push), (vorbis_handle_data_packet), (vorbis_dec_chain), + (vorbis_dec_change_state): + Small cleanups. + Add some FIXMEs + Clip output samples to segment boundaries. + +2006-05-26 11:17:57 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/ximage/ximagesink.c: Improve the errors produced on bad output, including some human readable description strings. + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_xcontext_get), (gst_ximagesink_show_frame): + Improve the errors produced on bad output, including some human + readable description strings. + Handle the (theoretical for ximagesink) case where the XServer + has a different idea about the size required for a particular + frame and gives us too small a memory allocation. + +2006-05-26 10:18:41 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + Mention bugs fixed by previous commit + Original commit message from CVS: + Mention bugs fixed by previous commit + +2006-05-26 09:40:35 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/xvimage/xvimagesink.c: Improve the errors produced on bad output, including some human readable description strings. + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_get_xv_support), (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_get_format_from_caps), (gst_xvimagesink_setcaps), + (gst_xvimagesink_show_frame), (gst_xvimagesink_buffer_alloc): + Improve the errors produced on bad output, including some human + readable description strings. + Handle RGB Xv formats properly by transforming them into our + big-endian caps description. + Use gst_caps_truncate to ensure that we never try and choose a + non-fixed caps in buffer_alloc. + Handle the case where the XServer has a different idea about the size + required for a particular frame and gives us too small a memory + allocation. + Use -1 to indicate 'no image format', because 0 is a valid XServer + image format number. + Put RGB Xv formats at the end of the caps, so that we always prefer + YUV format frames. + Iterate the available Xv Encodings to determine the maximum width and + height, and then return that in our caps. + +2006-05-25 16:50:17 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstdecodebin.c: When there is only one unfinished pad and it receives an event that doesn't match our re... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (remove_fakesink), (pad_probe): + When there is only one unfinished pad and it receives an event that + doesn't match our requirements, we need to set alldone=FALSE so that + the fakesink is not removed yet. + +2006-05-25 09:32:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggdemux.c: Use gst_type_find_helper_for_buffer() to find the type of stream from the first packet. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_typefind): + Use gst_type_find_helper_for_buffer() to find the type + of stream from the first packet. + * configure.ac: + Bump requirements to core CVS (needed for vorbis + typefinding to work). + +2006-05-24 08:34:53 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Added the 'prfl' atom type which MQV (no, it's not a typo) files contain. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): + Added the 'prfl' atom type which MQV (no, it's not a typo) files contain. + Else they play perfectly fine with qtdemux. + +2006-05-23 20:38:56 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + make more debug catagories static + Original commit message from CVS: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/theora/theoraparse.c: (gst_theora_parse_class_init): + * gst/audiorate/gstaudiorate.c: + make more debug catagories static + * tests/check/Makefile.am: + * tests/check/elements/adder.c: (message_received), + (test_event_message_received), (GST_START_TEST), + (test_play_twice_message_received), (adder_suite): + added test case for using element twice, extra bonus points for anyone + who can make these test run reliably + +2006-05-23 15:18:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/theora/theoradec.c: Make work with time-stamped input buffers that do not have a granulepos in BUFFER_OFFSET_END ... + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_chain): + Make work with time-stamped input buffers that do not + have a granulepos in BUFFER_OFFSET_END (like theora + buffers coming from matroskademux). Fixes #342448. + +2006-05-22 15:53:07 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/gdp/: Handle error cases when calling functions do downwards state change after parent's change_state + Original commit message from CVS: + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_chain), + (gst_gdp_depay_change_state): + * gst/gdp/gstgdpdepay.h: + * gst/gdp/gstgdppay.c: (gst_gdp_pay_reset_streamheader), + (gst_gdp_pay_chain), (gst_gdp_pay_sink_event), + (gst_gdp_pay_change_state): + * gst/gdp/gstgdppay.h: + Handle error cases when calling functions + do downwards state change after parent's change_state + * tests/check/elements/gdpdepay.c: (GST_START_TEST): + * tests/check/elements/gdppay.c: (GST_START_TEST): + clean up more + +2006-05-22 13:25:52 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + adding GDP payloader and depayloader. Build integration will follow later when the GDP issues for core are sorted out. + Original commit message from CVS: + * gst/gdp/Makefile.am: + * gst/gdp/gstgdp.c: (plugin_init): + * gst/gdp/gstgdpdepay.c: (gst_gdp_depay_base_init), + (gst_gdp_depay_class_init), (gst_gdp_depay_init), + (gst_gdp_depay_finalize), (gst_gdp_depay_chain), + (gst_gdp_depay_change_state), (gst_gdp_depay_plugin_init): + * gst/gdp/gstgdpdepay.h: + * gst/gdp/gstgdppay.c: (gst_gdp_pay_base_init), + (gst_gdp_pay_class_init), (gst_gdp_pay_init), + (gst_gdp_pay_dispose), (gst_gdp_stamp_buffer), + (gst_gdp_buffer_from_caps), (gst_gdp_pay_buffer_from_buffer), + (gst_gdp_buffer_from_event), (gst_gdp_pay_reset_streamheader), + (gst_gdp_queue_buffer), (gst_gdp_pay_chain), + (gst_gdp_pay_sink_event), (gst_gdp_pay_change_state), + (gst_gdp_pay_plugin_init): + * gst/gdp/gstgdppay.h: + * tests/check/Makefile.am: + * tests/check/elements/gdpdepay.c: (setup_gdpdepay), + (cleanup_gdpdepay), (gdpdepay_push_per_byte), (GST_START_TEST), + (setup_gdpdepay_streamheader), (gdpdepay_suite), (main): + * tests/check/elements/gdppay.c: (setup_gdppay), (cleanup_gdppay), + (GST_START_TEST), (setup_gdppay_streamheader), (gdppay_suite), + (main): + adding GDP payloader and depayloader. Build integration will + follow later when the GDP issues for core are sorted out. + +2006-05-22 11:42:03 +0000 Peter Kjellerstedt <pkj@axis.com> + + gst/tcp/Makefile.am: fdstresstest doesn't need Gtk+, fix compilation if gtk is not available (#342566). + Original commit message from CVS: + Patch by: Peter Kjellerstedt <pkj at axis com> + * gst/tcp/Makefile.am: + fdstresstest doesn't need Gtk+, fix compilation if + gtk is not available (#342566). + +2006-05-19 17:57:56 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpaudiopayload.c: 80 line columns + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + 80 line columns + Removed redundant floor() + +2006-05-19 15:00:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-read.c: On second thought, just skip JUNK chunks automatically, so the caller doesn't have to ... + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_chunk): + On second thought, just skip JUNK chunks automatically, so + the caller doesn't have to handle this. Fixes #342345. + Also, return GST_FLOW_UNEXPECTED if we get a short read, + not GST_FLOW_ERROR. + +2006-05-19 13:37:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-read.c: Don't bail out on JUNK chunks with a size of 0 (would try to pull_range 0 bytes before... + Original commit message from CVS: + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_chunk): + Don't bail out on JUNK chunks with a size of 0 (would try to + pull_range 0 bytes before, which sources don't like too much). + See #342345. + +2006-05-19 13:02:46 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Use the gstutil scaling function to preserve 64 bits while calculating output width and height from the display-aspec... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_fixate_caps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_setcaps): + Use the gstutil scaling function to preserve 64 bits while calculating + output width and height from the display-aspect-ratio. (A continuation + of #341542) + +2006-05-19 11:50:17 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/xvimage/xvimagesink.*: When performing buffer allocations, remember the caps and image format we return so that i... + Original commit message from CVS: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_buffer_alloc): + * sys/xvimage/xvimagesink.h: + When performing buffer allocations, remember the caps and image format + we return so that if the same caps are asked for next time we can + return them immediately without doing any caps intersections. + +2006-05-18 23:00:02 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/README: Some new documentation + Original commit message from CVS: + 2006-05-18 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + * gst-libs/gst/rtp/README: + Some new documentation + * gst-libs/gst/rtp/gstrtpbuffer.h: + Added GST_RTP_PAYLOAD_DYNAMIC_STRING for use by children + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + New RTP audio base payloader class. Supports frame or sample based codecs. + Not enabled in Makefile.am until approved. + +2006-05-18 20:30:26 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/elements/alsa.c: Fix test case: don't try to free NULL GValueArray when there are no devices. + Original commit message from CVS: + * tests/check/elements/alsa.c: (test_device_property_probe): + Fix test case: don't try to free NULL GValueArray when there + are no devices. + +2006-05-18 19:21:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/: Add simple test that runs a device property probe on alsasrc, alsasink and alsamixer. Disable valgrind ... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/alsa.c: (test_device_property_probe), + (alsa_suite), (main): + Add simple test that runs a device property probe on alsasrc, + alsasink and alsamixer. Disable valgrind check for now (too + many leaks in libasound, and valgrind ignored my suppressions + additions). + +2006-05-18 17:19:39 +0000 Martin Szulecki <gnomebugzilla@sukimashita.com> + + ext/alsa/: Clean up and simplify alsa device probing. Make it actually work for multiple classes. Don't cache results... + Original commit message from CVS: + * ext/alsa/gstalsadeviceprobe.c: (gst_alsa_get_device_list), + (gst_alsa_device_property_probe_probe_property), + (gst_alsa_device_property_probe_needs_probe), + (gst_alsa_device_property_probe_get_values), + (gst_alsa_type_add_device_property_probe_interface): + * ext/alsa/gstalsadeviceprobe.h: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_init_interfaces): + * ext/alsa/gstalsamixerelement.h: + Clean up and simplify alsa device probing. Make it actually work + for multiple classes. Don't cache results any longer. + * ext/alsa/gstalsasink.c: (gst_alsasink_init_interfaces), + (gst_alsasink_init): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_dispose), + (gst_alsasrc_interface_supported), (gst_implements_interface_init), + (gst_alsasrc_init_interfaces), (gst_alsasrc_set_property): + Make alsasink and alsasrc implement the GstPropertyProbe interface + for device probing (#342181). + Patch by: Martin Szulecki <gnomebugzilla at sukimashita com> + +2006-05-18 10:05:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/samiparse.c: Don't ignore return value of strtol (++compiler_happiness). + Original commit message from CVS: + * gst/subparse/samiparse.c: (handle_start_font): + Don't ignore return value of strtol (++compiler_happiness). + +2006-05-17 17:49:10 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/gstsubparse.*: Add 'encoding' property (#341681). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist chollian net> + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (gst_sub_parse_class_init), (gst_sub_parse_init), + (gst_sub_parse_set_property), (gst_sub_parse_get_property), + (convert_encoding): + * gst/subparse/gstsubparse.h: + Add 'encoding' property (#341681). + * gst/subparse/samiparse.c: (characters_sami): + Output is pango markup, so we need to escape text + between tags (#342143). + +2006-05-16 17:34:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: It's okay to have caps with channels=1 and a channel position different from GST_A... + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions): + It's okay to have caps with channels=1 and a channel position + different from GST_AUDIO_CHANNEL_POSITION_FRONT_MONO + (deinterleavers might want to keep the position in the caps, + so that they can be re-interleaved again properly later). + Leave check for unexpected 2-channel layouts intact for now. + +2006-05-16 16:28:10 +0000 Zaheer Abbas Merali <zaheerabbas@merali.org> + + gst/tcp/gsttcp.c: Return GST_FLOW_UNEXPECTED when we have an eos on the socket so basesrc can do its job correctly. + Original commit message from CVS: + 2006-05-16 Zaheer Abbas Merali <zaheerabbas at merali dot org> + * gst/tcp/gsttcp.c: (gst_tcp_socket_read): + Return GST_FLOW_UNEXPECTED when we have an eos on the socket so + basesrc can do its job correctly. + +2006-05-16 15:52:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/: Refactor and improve caps probing code: probe signedness when we probe the supported formats/widths; set e... + Original commit message from CVS: + * ext/alsa/Makefile.am: + * ext/alsa/gstalsa.c: (gst_alsa_detect_rates), + (gst_alsa_detect_formats), (get_channel_free_structure), + (caps_add_channel_configuration), (gst_alsa_detect_channels), + (gst_alsa_probe_supported_formats): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsasink_getcaps): + Refactor and improve caps probing code: probe signedness + when we probe the supported formats/widths; set endianness + to the one we actually probed for (ie. cpu endianness). + * ext/alsa/gstalsasrc.c: (gst_alsasrc_init), (gst_alsasrc_getcaps), + (gst_alsasrc_close): + * ext/alsa/gstalsasrc.h: + Implement caps probing for alsasrc. + +2006-05-15 17:42:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Cleanups, add some G_LIKELY. + Original commit message from CVS: + * ext/theora/theoradec.c: (gst_theora_dec_reset), + (theora_dec_src_query), (theora_dec_src_event), + (theora_dec_sink_event), (theora_handle_comment_packet), + (theora_handle_data_packet), (theora_dec_change_state): + Cleanups, add some G_LIKELY. + Use segment helpers instead of our own wrong code. + Clear queued buffers on seek and READY. + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_reset), + (vorbis_dec_convert), (vorbis_dec_src_query), + (vorbis_dec_src_event), (vorbis_dec_sink_event), + (vorbis_handle_comment_packet), (vorbis_dec_push), + (vorbis_handle_data_packet), (vorbis_dec_chain), + (vorbis_dec_change_state): + * ext/vorbis/vorbisdec.h: + Remove old useless packetno variable. + Do position query properly. + Add some G_LIKELY. + Do cleanup of queued buffers in new helper function + and use it. + +2006-05-15 17:17:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsasink.c: Query supported sample rates. Fixes #341732. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_getcaps): + Query supported sample rates. Fixes #341732. + +2006-05-15 17:01:02 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gstdecodebin.c: Make decodebin reusable when going from PAUSE_TO_READY and then back to PAUSED. + Original commit message from CVS: + 2006-05-15 Julien MOUTTE <julien@moutte.net> + * gst/playback/gstdecodebin.c: (cleanup_decodebin), + (gst_decode_bin_change_state): Make decodebin reusable + when going from PAUSE_TO_READY and then back to PAUSED. + Fixes #331678. + +2006-05-15 16:49:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Cleanups. Use refcounting and DEBUG_OBJECT. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_get_query_types), + (vorbis_dec_convert), (vorbis_dec_src_query), + (vorbis_dec_sink_query), (vorbis_dec_src_event), + (vorbis_dec_sink_event), (vorbis_handle_identification_packet), + (vorbis_dec_clean_queued), (vorbis_dec_push), + (vorbis_handle_data_packet), (vorbis_dec_change_state): + Cleanups. Use refcounting and DEBUG_OBJECT. + Reset segment on flush, use code methods instead of our + own wrong version. + Fix potential memleak. + +2006-05-15 16:46:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsasink.*: Don't leak allocated snd_output_t structure if there's more than one alsasink instance at a t... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_finalise), + (gst_alsasink_init): + * ext/alsa/gstalsasink.h: + Don't leak allocated snd_output_t structure if there's + more than one alsasink instance at a time (#341873). + Also fix GObject macros in header file. + +2006-05-15 15:31:30 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Don't use libxml functions in the typefinding code. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect): + Don't use libxml functions in the typefinding code. + +2006-05-15 15:01:08 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Fix seeking performance in the case where a non-header packet has a 0 granulepos (busted theor... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet): + Fix seeking performance in the case where a non-header + packet has a 0 granulepos (busted theora case). + Fixes #341719 + +2006-05-15 14:19:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Improve SAMI typefinding: handle case where there are whitespaces or newlines in front of... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: + (gst_sub_parse_data_format_autodetect): + Improve SAMI typefinding: handle case where there are + whitespaces or newlines in front of the first <SAMI> + tag (#169936). + +2006-05-15 12:18:13 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Build video4linux plugin even if there's no XVIDEO, just without implementing the GstXOverlay interface... + Original commit message from CVS: + * configure.ac: + Build video4linux plugin even if there's no XVIDEO, just + without implementing the GstXOverlay interface (#334002). + +2006-05-15 10:17:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add tentative support for libvisual-0.4 (#336881). + Original commit message from CVS: + * configure.ac: + * ext/libvisual/visual.c: (gst_visual_actor_plugin_is_gl), + (plugin_init): + Add tentative support for libvisual-0.4 (#336881). + +2006-05-15 09:41:03 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/samiparse.c: Need to map "silver" colour explicitly (#169936). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/subparse/samiparse.c: (handle_start_font): + Need to map "silver" colour explicitly (#169936). + +2006-05-15 09:14:35 +0000 Young-Ho Cha <ganadist@chollian.net> + + gst/subparse/: Add support for SAMI subtitles (#169936). + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (parser_state_dispose), (gst_sub_parse_data_format_autodetect), + (gst_sub_parse_format_autodetect), (feed_textbuf), + (gst_subparse_type_find), (plugin_init): + * gst/subparse/gstsubparse.h: + * gst/subparse/samiparse.c: + * gst/subparse/samiparse.h: + Add support for SAMI subtitles (#169936). + +2006-05-14 21:18:58 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * win32/common/config.h: + update config.h + Original commit message from CVS: + update config.h + +2006-05-14 21:18:16 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/README: + fix mistakes in README + Original commit message from CVS: + fix mistakes in README + +2006-05-14 18:15:17 +0000 Michael Smith <msmith@xiph.org> + + gst/audioconvert/gstchannelmix.c: Fix #341696: crash when mixing L+R+C to mono or stereo. + Original commit message from CVS: + * gst/audioconvert/gstchannelmix.c: (gst_channel_mix_fill_others): + Fix #341696: crash when mixing L+R+C to mono or stereo. + * tests/check/Makefile.am: + * tests/check/elements/audioconvert.c: (set_channel_positions), + (get_float_mc_caps), (get_int_mc_caps), (GST_START_TEST), + (audioconvert_suite): + Add test for the above, including some generic framework bits for + testing multichannel things. + +2006-05-14 16:05:47 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * configure.ac: + Back to CVS + Original commit message from CVS: + Back to CVS + +=== release 0.10.7 === + +2006-05-14 16:00:57 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: releasing 0.10.7, "Leave the gun" + Original commit message from CVS: + 2006-05-14 Jan Schmidt <thaytan@mad.scientist.com> + * configure.ac: + releasing 0.10.7, "Leave the gun" + +2006-05-14 15:55:16 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * common: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-05-12 22:22:37 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Fix the build. + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_fixate_caps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_setcaps): + Fix the build. + +2006-05-12 21:30:00 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Fix integer overflow problem with pixel-aspect-ratio calculations in videoscale and xvimagesink (#341542) + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/video/video.c: (gst_video_calculate_display_ratio): + * gst-libs/gst/video/video.h: + * gst/videoscale/Makefile.am: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_fixate_caps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_setcaps): + * tests/check/Makefile.am: + * tests/check/libs/video.c: (GST_START_TEST), (video_suite), + (main): + Fix integer overflow problem with pixel-aspect-ratio calculations + in videoscale and xvimagesink (#341542) + +2006-05-12 16:56:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstid3tag.c: Map GST_IMAGE_TAG to and from ID2v2 APIC frames (#341557). + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Map GST_IMAGE_TAG to and from ID2v2 APIC frames (#341557). + +2006-05-12 10:39:08 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/MANIFEST: update win32 files listing + Original commit message from CVS: + * win32/MANIFEST: + update win32 files listing + +2006-05-11 21:47:01 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + disable failing check on gentoo64 + Original commit message from CVS: + disable failing check on gentoo64 + +2006-05-11 21:35:44 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + disable failing check on gentoo64 + Original commit message from CVS: + disable failing check on gentoo64 + +2006-05-11 21:20:20 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + macros show the correct line + Original commit message from CVS: + macros show the correct line + +2006-05-11 21:04:08 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + macros show the correct line + Original commit message from CVS: + macros show the correct line + +2006-05-11 21:01:05 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/playback/gstplaybasebin.*: API: GstPlayBaseBin::stream-info-value-array property use a more bindings-friendly way... + Original commit message from CVS: + 2006-05-11 Thomas Vander Stichele <thomas at apestaart dot org> + patch by: Sjoerd Simons (sjoerd@luon.net) + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (group_create), (group_destroy), (add_stream), + (gst_play_base_bin_get_property), + (gst_play_base_bin_get_streaminfo_value_array): + * gst/playback/gstplaybasebin.h: + API: GstPlayBaseBin::stream-info-value-array property + use a more bindings-friendly way of exposing streaminfo + using a GValueArray. Tested in ipython. + Closes #341114 + +2006-05-11 19:44:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + fix some type warnings + Original commit message from CVS: + fix some type warnings + +2006-05-11 19:38:22 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Also catch queue underruns but don't do anything yet. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (try_to_link_1), (queue_enlarge), + (queue_underrun_cb), (queue_filled_cb): + Also catch queue underruns but don't do anything yet. + Refactor and comment queue enlarging code a bit. + * gst/playback/gstplaybasebin.c: (queue_overrun), + (queue_threshold_reached), (queue_out_of_data), + (gen_preroll_element): + If a queue over/underruns check that we don't create nasty + deadlocks when the min-threshold is not reached but the + max-bytes is. In those cases disable max-bytes when we + know that the queue is fed timed data. + Add more comments. + +2006-05-11 18:06:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Make playbin automatically plug an 'audioresample' element before the audio sink as well. ... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_audio_element): + Make playbin automatically plug an 'audioresample' + element before the audio sink as well. This solves + problems with sinks that only accept a very specific + sample rate, like esdsink (e.g. #340379). + +2006-05-11 16:04:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Make http sources send special headers so that we receive icecast metadata if the http... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gen_source_element): + Make http sources send special headers so that we receive + icecast metadata if the http stream is an icecast stream + (otherwise the server will just ignore them). This also + means that from now on users will need the 'icydemux' + element from gst-plugins-good installed if they want to + listen to icecast radio streams. (#341432, #333657). + +2006-05-11 12:34:53 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + more commenting + Original commit message from CVS: + more commenting + +2006-05-11 11:40:39 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gstmultifdsink.c: remove stupid example from docs - it should come with a simple + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_remove_client_link), + (gst_multi_fd_sink_new_client), (gst_multi_fd_sink_stop): + remove stupid example from docs - it should come with a simple + C program instead. + Clean up/fix docs + * tests/check/elements/multifdsink.c: (wait_bytes_served), + (fail_if_can_read), (GST_START_TEST), + (gst_multifdsink_create_streamheader), (multifdsink_suite): + add a test for changing streamheader which exposes a bug in + multifdsink + +2006-05-11 10:33:46 +0000 Michael Smith <msmith@xiph.org> + + ext/gnomevfs/gstgnomevfssrc.*: Don't set icy-caps unless we have a sane interval value. Move interval to a local vari... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_init), + (gst_gnome_vfs_src_received_headers_callback): + * ext/gnomevfs/gstgnomevfssrc.h: + Don't set icy-caps unless we have a sane interval value. Move + interval to a local variable; we never use it outside this function. + +2006-05-11 10:14:20 +0000 Wim Taymans <wim.taymans@gmail.com> + + sys/: Register special buffer types along with the objects so that they are not registered at runtime from N differen... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_get_type): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_type): + Register special buffer types along with the objects so + that they are not registered at runtime from N different + streaming threads since they are not threadsafe. + +2006-05-10 18:31:27 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/multifdsink.c: + set caps and plug leaks + Original commit message from CVS: + set caps and plug leaks + +2006-05-10 18:16:23 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/elements/multifdsink.c: add two more tests, one doing streamheader + Original commit message from CVS: + * tests/check/elements/multifdsink.c: (wait_bytes_served), + (GST_START_TEST), (fail_unless_read), (multifdsink_suite): + add two more tests, one doing streamheader + +2006-05-10 16:34:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/tcp/gstmultifdsink.c: clean up the bufqueue when shutting down + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_stop): + clean up the bufqueue when shutting down + * tests/check/Makefile.am: + * tests/check/elements/multifdsink.c: (setup_multifdsink), + (cleanup_multifdsink), (GST_START_TEST), (multifdsink_suite), + (main): + add a test for the leak that was just fixed + +2006-05-10 15:16:33 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + DEBUG_FUNCPTR'ing + Original commit message from CVS: + DEBUG_FUNCPTR'ing + +2006-05-10 15:14:30 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + whitespace fixes + Original commit message from CVS: + whitespace fixes + +2006-05-10 11:54:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.*: Updated some docs. Added comments and FIXMEs all over the place. + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_setcaps), + (gst_adder_query_duration), (gst_adder_query), (forward_event), + (gst_adder_src_event), (gst_adder_sink_event), + (gst_adder_class_init), (gst_adder_finalize), + (gst_adder_request_new_pad), (gst_adder_collected): + * gst/adder/gstadder.h: + Updated some docs. Added comments and FIXMEs all over the place. + Improve debugging info. + Fix leak on finalize by not calling the parent. + Implement duration query. + Make event forwarding threadsafe. + Correctly send NEWSEGMENT at start and after flush. + Handle EOS correctly. + Post error when not negotiated. + * tests/check/elements/adder.c: (GST_START_TEST): + Added FIXME in the test. + +2006-05-09 19:24:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + Const-ify GEnumValue and GFlagsValue arrays. Use + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_valign_get_type), + (gst_text_overlay_halign_get_type), + (gst_text_overlay_wrap_mode_get_type): + * ext/theora/theoradec.c: (theora_handle_type_packet), + (theora_handle_data_packet): + * ext/theora/theoraenc.c: (gst_border_mode_get_type), + (theora_enc_sink_setcaps), (theora_enc_chain): + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_mode_get_type): + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audiostestsrc_wave_get_type): + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type): + * gst/tcp/gstfdset.c: (gst_fdset_mode_get_type): + * gst/tcp/gstmultifdsink.c: (gst_recover_policy_get_type), + (gst_sync_method_get_type), (gst_unit_type_get_type), + (gst_client_status_get_type): + * gst/videoscale/gstvideoscale.c: + (gst_video_scale_method_get_type): + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_pattern_get_type): + * gst/videotestsrc/videotestsrc.c: (paint_setup_I420), + (paint_setup_YV12), (paint_setup_YUY2), (paint_setup_UYVY), + (paint_setup_YVYU), (paint_setup_IYU2), (paint_setup_Y41B), + (paint_setup_Y42B), (paint_setup_Y800), (paint_setup_YVU9), + (paint_setup_YUV9), (paint_setup_RGB888), (paint_setup_BGR888), + (paint_setup_RGB565), (paint_setup_xRGB1555): + Const-ify GEnumValue and GFlagsValue arrays. Use + GST_ROUND_UP_* macros instead of home-made ones. + +2006-05-09 17:40:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Require core CVS for the new newsegment stuff. + Original commit message from CVS: + * configure.ac: + Require core CVS for the new newsegment stuff. + +2006-05-09 17:30:48 +0000 Sjoerd Simons <sjoerd@luon.net> + + gst/tcp/gstmultifdsink.c: Register nick for enum value (#341160). + Original commit message from CVS: + Patch by: Sjoerd Simons <sjoerd at luon net> + * gst/tcp/gstmultifdsink.c: (gst_client_status_get_type): + Register nick for enum value (#341160). + +2006-05-09 16:46:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/typefind/gsttypefindfunctions.c: backout typefind patch #340375 + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (m4a_type_find), + (plugin_init): + backout typefind patch #340375 + * tests/check/elements/adder.c: (message_received), + (GST_START_TEST), (adder_suite): + redo, signal-handling of test + +2006-05-09 16:14:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/adder/gstadder.*: Remove bogus segment merging and forwarding, we don't care about timestamps anyway and we just ... + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_request_new_pad), + (gst_adder_collected): + * gst/adder/gstadder.h: + Remove bogus segment merging and forwarding, we don't + care about timestamps anyway and we just produce a + continuous stream. + Also create a nice NEWSEGMENT event when we start. + Use _scale_int some more. + +2006-05-09 11:59:13 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/icles/stress-xoverlay.c: Fix if core was built without parsing support. + Original commit message from CVS: + * tests/icles/stress-xoverlay.c: + Fix if core was built without parsing support. + +2006-05-09 11:37:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Add SEDG (Samsung MPEG-4) fourcc. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add SEDG (Samsung MPEG-4) fourcc. + +2006-05-09 11:31:47 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/examples/volume/volume.c: Fox if core was built without parsing support. + Original commit message from CVS: + * tests/examples/volume/volume.c: + Fox if core was built without parsing support. + * tests/examples/seek/seek.c: + Disable the parse_launch example if core was built without parsing + support. + +2006-05-09 11:21:24 +0000 Edward Hervey <bilboed@bilboed.com> + + tests/examples/seek/seek.c: Disable the parse_launch example if core was built without parsing support. + Original commit message from CVS: + * tests/examples/seek/seek.c: + Disable the parse_launch example if core was built without parsing + support. + +2006-05-08 15:51:15 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * docs/libs/tmpl/gstcolorbalance.sgml: + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst/tcp/gstmultifdsink.c: + * gst/videoscale/gstvideoscale.c: + doc reparagraphing and DEBUG_FUNCPTRing + Original commit message from CVS: + doc reparagraphing and DEBUG_FUNCPTRing + +2006-05-08 11:51:43 +0000 Edward Hervey <bilboed@bilboed.com> + + autogen.sh: libtoolize on Darwin/MacOSX is called glibtoolize + Original commit message from CVS: + * autogen.sh: (CONFIGURE_DEF_OPT): + libtoolize on Darwin/MacOSX is called glibtoolize + +2006-05-07 17:39:04 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/: Disable the adder test, until the build-slaves posses the kindness to either like it or to give valid r... + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/elements/adder.c: (event_loop), (GST_START_TEST): + Disable the adder test, until the build-slaves posses the kindness to + either like it or to give valid reason for not doing so + +2006-05-07 17:25:56 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + tests/check/elements/adder.c: Shuffle NULL state change around and raise timeout more + Original commit message from CVS: + * tests/check/elements/adder.c: (event_loop), (GST_START_TEST), + (adder_suite): + Shuffle NULL state change around and raise timeout more + +2006-05-07 17:07:03 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/typefind/gsttypefindfunctions.c: Add typefind to distinguish between "audio/x-m4a" and new type "video/mp4". Fixe... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp4_find_box), + (mp4_type_find), (plugin_init): + Add typefind to distinguish between "audio/x-m4a" and new type + "video/mp4". Fixes #340375 + * tests/check/elements/adder.c: (adder_suite): + Raise timeout to make buildbot happy + +2006-05-07 16:39:36 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add sink-event handling to adder. It tries to merge incomming newsegment-events. Added test to check if segment_done ... + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_sink_event), + (gst_adder_request_new_pad), (gst_adder_change_state): + * gst/adder/gstadder.h: + * tests/check/Makefile.am: + * tests/check/elements/adder.c: (event_loop), (GST_START_TEST), + (adder_suite), (main): + Add sink-event handling to adder. It tries to merge incomming + newsegment-events. Added test to check if segment_done is comming + through. + +2006-05-05 16:34:15 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * ext/theora/theoraparse.c: + * ext/vorbis/vorbisparse.c: + ext/theora/theoraparse.c (gst_theora_parse_init) ext/vorbis/vorbisparse.c (gst_vorbis_parse_init) + Original commit message from CVS: + 2006-05-05 Andy Wingo <wingo@pobox.com> + * ext/theora/theoraparse.c (gst_theora_parse_init) + (theora_parse_src_convert, theora_parse_src_query): + * ext/vorbis/vorbisparse.c (gst_vorbis_parse_init) + (vorbis_parse_convert, vorbis_parse_src_query): Add convert and + query functions on the source pads of the theora and vorbis parse + elements. Fixes position querying when doing a remux. + +2006-05-05 13:46:37 +0000 Michael Smith <msmith@xiph.org> + + ext/theora/theoraparse.c: Fix flushing. + Original commit message from CVS: + * ext/theora/theoraparse.c: (parse_granulepos), + (theora_parse_drain_queue_prematurely), + (theora_parse_queue_buffer), (theora_parse_sink_event): + Fix flushing. + Fix invalid granulepos outputs when starting with a non-keyframe. + +2006-05-05 12:37:35 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/typefind/gsttypefindfunctions.c: Rearrange MPEG system stream detection, fixing some memleaks in the process. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find), + (mpeg1_sys_type_find), (ogganx_type_find), (sw_data_destroy): + Rearrange MPEG system stream detection, fixing some memleaks in the + process. + Constify the data for STARTS_WITH and RIFF helper handlers. Make sure + they clean up their data correctly. + Remove unused ogganx caps and move the 'is_annodex' check to inside + the 'is_ogg' if statement. + +2006-05-05 11:33:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstdecodebin.c: Properly remove ghostpads. Fixes #340392 + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (cleanup_decodebin): + Properly remove ghostpads. Fixes #340392 + +2006-05-04 18:43:58 +0000 David Schleef <ds@schleef.org> + + gst/typefind/gsttypefindfunctions.c: + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + +2006-05-03 16:32:19 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/typefind/gsttypefindfunctions.c: When typefinding an MP3 in push-based mode, don't penalise the probability down ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset), + (mpeg_ts_probe_headers), (mpeg_ts_type_find): + When typefinding an MP3 in push-based mode, don't penalise the + probability down to 74% when we found 5 valid frames just because we + can't peek the end of the file. + Make the probability for detecting MPEG Transport Streams based on the + number of sequential headers we successfully detected. + +2006-05-03 15:52:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Still produce an error when we receive an empty packet. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_sink_event), + (vorbis_dec_push), (vorbis_dec_chain): + Still produce an error when we receive an empty packet. + +2006-05-03 15:34:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Mark buffers with DISCONT after seek and after activating new chains. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain_peer), + (gst_ogg_chain_mark_discont), (gst_ogg_chain_new_stream), + (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek): + Mark buffers with DISCONT after seek and after activating new + chains. + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_reset), + (theora_get_query_types), (theora_dec_sink_event), + (theora_dec_push), (theora_handle_data_packet), (theora_dec_chain), + (theora_dec_change_state): + Fix frame counter. + Detect and mark DISCONT buffers. + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query), + (vorbis_dec_sink_event), (vorbis_dec_push), (vorbis_dec_chain), + (vorbis_dec_change_state): + * ext/vorbis/vorbisdec.h: + Use GstSegment. + Detect and mark DISCONT buffers. + Don't crash on 0 sized buffers. + +2006-05-03 08:58:13 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/volume/gstvolume.c: Increase "volume" property to 10.0. Fixes #340369. + Original commit message from CVS: + * gst/volume/gstvolume.c: (volume_funcfind), (volume_set_caps), + (volume_transform_ip): + Increase "volume" property to 10.0. Fixes #340369. + Set the process function to NULL when capsnego fails so that + we properly error out. + +2006-05-02 18:15:25 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/playback/: free cpas using gst_caps_unref, don't leak caps-strings + Original commit message from CVS: + * gst/playback/gstplaybin.c: (add_sink): + * gst/playback/test.c: (main): + * gst/playback/test5.c: (dump_element_stats): + * gst/playback/test6.c: (main): + free cpas using gst_caps_unref, don't leak caps-strings + +2006-05-02 06:33:54 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst-libs/gst/rtp/gstbasertppayload.c: + some RTP debug + Original commit message from CVS: + some RTP debug + +2006-05-01 19:08:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Refine musepack typefinding a bit. Return MAXIMUM probability when we detect str... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (musepack_type_find), + (plugin_init): + Refine musepack typefinding a bit. Return MAXIMUM + probability when we detect stream version 7 to make + sure the mpeg audio typefinder doesn't trump us. + +2006-04-29 16:25:58 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Protect against unexpected NULL strf_data buffer. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Protect against unexpected NULL strf_data buffer. + +2006-04-29 13:09:52 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/elements/audioconvert.c: interpret the out[] buffer in the order the bytes are actually put in, which is ... + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (verify_convert), + (GST_START_TEST): + interpret the out[] buffer in the order the bytes are actually + put in, which is LITTLE_ENDIAN, not BYTE_ORDER. + Other tests should use BYTE_ORDER since the array is filled in + with actual values + +2006-04-29 12:10:52 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/elements/audioconvert.c: + dump expected data when audioconvert test fails + Original commit message from CVS: + dump expected data when audioconvert test fails + +2006-04-29 11:55:09 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/elements/audioconvert.c: when a test fails, give an indication of which it is + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (verify_convert), + (GST_START_TEST): + when a test fails, give an indication of which it is + +2006-04-29 09:48:16 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + * ext/theora/theoraenc.c: + add another include + Original commit message from CVS: + add another include + +2006-04-29 01:24:31 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/subparse/gstssaparse.c: + atoi() needs stdlib.h + Original commit message from CVS: + atoi() needs stdlib.h + +2006-04-29 01:18:05 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/playback/test4.c: + * gst/playback/test5.c: + * gst/playback/test6.c: + exit needs stdlib.h + Original commit message from CVS: + exit needs stdlib.h + +2006-04-29 01:10:34 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst-libs/gst/cdda/gstcddabasesrc.c: compile fix; strtol() needs <stdlib.h> + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + compile fix; strtol() needs <stdlib.h> + +2006-04-29 01:04:51 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * common: + * docs/Makefile.am: + * docs/libs/Makefile.am: + * docs/libs/tmpl/gstcolorbalance.sgml: + * docs/plugins/Makefile.am: + * docs/upload.mak: + use common upload.mak + Original commit message from CVS: + use common upload.mak + +2006-04-28 19:46:37 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + make GstElementDetails const + Original commit message from CVS: + * ext/alsa/gstalsamixerelement.c: + * ext/alsa/gstalsasrc.c: + * ext/cdparanoia/gstcdparanoiasrc.c: + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: + * ext/ogg/gstogmparse.c: + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/pango/gsttimeoverlay.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * gst-libs/gst/audio/gstaudiofilter.c: + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/audiorate/gstaudiorate.c: + * gst/audioresample/gstaudioresample.c: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/playback/gstdecodebin.c: + * gst/playback/gstplaybin.c: + * gst/playback/gststreamselector.c: + * gst/subparse/gstsubparse.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + * gst/videorate/gstvideorate.c: + * gst/videoscale/gstvideoscale.c: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/volume/gstvolume.c: + * sys/v4l/gstv4ljpegsrc.c: + * sys/v4l/gstv4lmjpegsink.c: + * sys/v4l/gstv4lmjpegsrc.c: + * sys/v4l/gstv4lsrc.c: + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + * tests/check/libs/cddabasesrc.c: + make GstElementDetails const + +2006-04-28 19:17:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/adder/gstadder.c: send events from src-pad to all sink-pads fixes #338657 + Original commit message from CVS: + * gst/adder/gstadder.c: (gst_adder_setcaps), (gst_adder_src_event), + (gst_adder_init): + send events from src-pad to all sink-pads fixes #338657 + +2006-04-28 19:08:34 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/alsa/gstalsasink.c: query witdh capabilities from alsa, fixes #338919 + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_getcaps), + (alsasink_parse_spec): + query witdh capabilities from alsa, fixes #338919 + +2006-04-28 15:31:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/tcp/gstmultifdsink.*: Fix race condition in multifdsink that can lead to spurious duplicate clients. this patch a... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init), + (gst_multi_fd_sink_remove_client_link): + * gst/tcp/gstmultifdsink.h: + Fix race condition in multifdsink that can lead to spurious + duplicate clients. this patch adds a new signal that is fired when + multifdsink has removed all references to the fd. + Fixes #339574. + Updated documentation. + API: client-fd-removed signal added + +2006-04-28 15:24:00 +0000 Michael Smith <msmith@xiph.org> + + gst/tcp/gstmultifdsink.c: When asking g_value_array_new to prealloc elements, we may as well ask for the right number... + Original commit message from CVS: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_get_stats): + When asking g_value_array_new to prealloc elements, we may as well + ask for the right number of elements. + +2006-04-28 15:08:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: patch to make timestamp checking more tollerant to rounding errors given that ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain), (gst_base_audio_sink_event), + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + patch to make timestamp checking more tollerant to rounding + errors given that real discontinuities are to be marked on + buffers. Fixes some asf files and #338778. + Also avoid some crashers when we receive an event in the + NULL state. + +2006-04-28 15:01:58 +0000 Michael Smith <msmith@xiph.org> + + ext/gnomevfs/gstgnomevfssrc.*: Remove ICY handling (mostly) from gnomevfssrc, in favour of proper shared support with... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init), + (gst_gnome_vfs_src_init), (gst_gnome_vfs_src_finalize), + (gst_gnome_vfs_src_get_property), + (gst_gnome_vfs_src_send_additional_headers_callback), + (gst_gnome_vfs_src_received_headers_callback), + (gst_gnome_vfs_src_create), (gst_gnome_vfs_src_start), + (gst_gnome_vfs_src_stop): + * ext/gnomevfs/gstgnomevfssrc.h: + Remove ICY handling (mostly) from gnomevfssrc, in favour of + proper shared support within icydemux. + +2006-04-28 14:49:22 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/videorate/gstvideorate.c: fix up docs fix a leak when no caps negotiated fix counting of input frames + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_reset), + (gst_video_rate_swap_prev), (gst_video_rate_chain): + fix up docs + fix a leak when no caps negotiated + fix counting of input frames + * tests/check/elements/.cvsignore: + * tests/check/elements/videorate.c: (assert_videorate_stats), + (GST_START_TEST), (videorate_suite): + add tests for these + +2006-04-28 14:48:11 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Check arguments passed to public functions instead of crashing. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_set_callback), (gst_ring_buffer_acquire), + (gst_ring_buffer_release), (gst_ring_buffer_is_acquired), + (gst_ring_buffer_set_flushing), (gst_ring_buffer_start), + (gst_ring_buffer_pause), (gst_ring_buffer_stop), + (gst_ring_buffer_delay), (gst_ring_buffer_samples_done), + (gst_ring_buffer_set_sample), (gst_ring_buffer_clear_all), + (gst_ring_buffer_commit), (gst_ring_buffer_read), + (gst_ring_buffer_prepare_read), (gst_ring_buffer_advance), + (gst_ring_buffer_clear), (gst_ring_buffer_may_start): + Check arguments passed to public functions instead of + crashing. + +2006-04-28 14:37:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: GstBaseAudioSrc must be live or it does not work. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_init), + (gst_base_audio_src_get_time), (gst_base_audio_src_create): + GstBaseAudioSrc must be live or it does not work. + * gst-libs/gst/audio/gstaudiosrc.c: (gst_audio_src_init): + Don't set live to TRUE as this is the default in the parentclass. + +2006-04-28 14:37:12 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * win32/common/config.h: + update config.h + Original commit message from CVS: + update config.h + +2006-04-28 14:33:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videoscale/gstvideoscale.c: Videoscale doesn't pass on pixel-aspect ratio. Handle all fixation cases better. Fixe... + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: (gst_video_scale_transform_caps), + (gst_video_scale_fixate_caps), (gst_video_scale_src_event): + Videoscale doesn't pass on pixel-aspect ratio. Handle all + fixation cases better. Fixes #338991 + +2006-04-28 14:24:38 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videotestsrc/gstvideotestsrc.c: Handle 0/1 framerate correctly Fixes #331901. + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_create): + Handle 0/1 framerate correctly Fixes #331901. + +2006-04-28 14:22:16 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/check/elements/audioconvert.c: Added check for correct clipping when doing float samples in audioconvert. + Original commit message from CVS: + * tests/check/elements/audioconvert.c: (get_float_caps), + (GST_START_TEST), (audioconvert_suite): + Added check for correct clipping when doing float samples + in audioconvert. + +2006-04-28 14:19:49 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videorate/gstvideorate.c: Print more debugging info. + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_event), + (gst_video_rate_chain): + Print more debugging info. + +2006-04-28 14:17:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audioresample/gstaudioresample.c: Add support for other formats audioresample can handle such as 32 bits in and f... + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: (gst_audioresample_init), + (resample_set_state_from_caps): + Add support for other formats audioresample can handle such as + 32 bits in and float and 64 bits float. Fixes #301759 + +2006-04-28 14:12:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/audioconvert/audioconvert.c: correctly clip float samples > 1.0. Fixes #338718 + Original commit message from CVS: + * gst/audioconvert/audioconvert.c: (float): + correctly clip float samples > 1.0. Fixes #338718 + +2006-04-28 13:35:34 +0000 Young-Ho Cha <ganadist@chollian.net> + + ext/pango/gsttextoverlay.c: Don't strip newlines from the text. Also, center lines within multi-line paragraphs (#339... + Original commit message from CVS: + Patch by: Young-Ho Cha <ganadist at chollian net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init), + (gst_text_overlay_render_text): + Don't strip newlines from the text. Also, center lines + within multi-line paragraphs (#339405). + +2006-04-28 12:15:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Fix wavpack typefinding to work in more cases (don't peek for chunks of multiple... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (wavpack_type_find): + Fix wavpack typefinding to work in more cases (don't peek + for chunks of multiple hundred kBs at once, but process + things step-by-step in smaller units). Fixes #339786. + +2006-04-28 10:58:41 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.6 === + +2006-04-28 10:53:40 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * docs/upload.mak: + releasing 0.10.6 + Original commit message from CVS: + releasing 0.10.6 + +2006-04-28 10:42:57 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * win32/MANIFEST: + * win32/common/config.h: + dist more win32 files + Original commit message from CVS: + dist more win32 files + +2006-04-28 10:41:57 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-04-27 00:19:29 +0000 David Schleef <ds@schleef.org> + + gst/videoscale/gstvideoscale.c: Add call to oil_init(). + Original commit message from CVS: + * gst/videoscale/gstvideoscale.c: Add call to oil_init(). + Fixes #338897. + +2006-04-26 17:20:31 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + * win32/common/config.h: + new prerelease + Original commit message from CVS: + new prerelease + +2006-04-26 17:17:39 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: make sure correct newsegments are sent, so that the decoder and the demuxer agree on timestamp... + Original commit message from CVS: + 2006-04-26 Thomas Vander Stichele <thomas at apestaart dot org> + patch by: Wim Taymans + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet), + (gst_ogg_demux_perform_seek): + make sure correct newsegments are sent, so that the decoder + and the demuxer agree on timestamps. Fixes playback of a lot + of Ogg files that do not start from 0. Fixes #339833. + +2006-04-26 16:44:20 +0000 Edward Hervey <edward@fluendo.com> + + Fix an infinite loop if frames are passed in with wrongly ordered timestamps. Fixes #339013. + Original commit message from CVS: + Patch by: Edward Hervey <edward@fluendo.com> + * gst/videorate/gstvideorate.c: (gst_video_rate_chain): + * tests/check/Makefile.am: + * tests/check/elements/videorate.c: (assert_videorate_stats), + (setup_videorate), (cleanup_videorate), (GST_START_TEST), + (videorate_suite), (main): + Fix an infinite loop if frames are passed in with wrongly ordered + timestamps. Fixes #339013. + +2006-04-26 13:55:14 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + * win32/common/config.h: + prerelease + Original commit message from CVS: + prerelease + +2006-04-22 21:25:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: fix typefinding on some ISO files. Fixes #339212. + Original commit message from CVS: + Patch by: Tim-Philipp Müller <tim at centricular dot net> + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): + fix typefinding on some ISO files. Fixes #339212. + +2006-04-22 21:19:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: add another H264 fourcc. Fixes #339047. + Original commit message from CVS: + Patch by: Tim-Philipp Müller <tim at centricular dot net> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + add another H264 fourcc. Fixes #339047. + +2006-04-22 21:12:52 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gststreamselector.c: Restore old StreamSelector behaviour. + Original commit message from CVS: + Patch by: Jan Schmidt + * gst/playback/gststreamselector.c: + (gst_stream_selector_bufferalloc): + Restore old StreamSelector behaviour. + Fixes #338419. + +2006-04-13 09:26:27 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * gst-libs/gst/rtp/Makefile.am: + * gst-libs/gst/rtp/gstrtpbuffer.h: + reverting rtp patches to fix freeze break on -base as explained on the list + Original commit message from CVS: + reverting rtp patches to fix freeze break on -base as explained on the list + +2006-04-13 03:55:12 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstrtpbuffer.h: Added GST_RTP_PAYLOAD_DYNAMIC_STRING for use by children + Original commit message from CVS: + 2006-04-12 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + * gst-libs/gst/rtp/gstrtpbuffer.h: + Added GST_RTP_PAYLOAD_DYNAMIC_STRING for use by children + * gst-libs/gst/rtp/gstbasertpaudiopayload.c: + * gst-libs/gst/rtp/gstbasertpaudiopayload.h: + New RTP audio base payloader class. Supports frame or sample based codecs + +2006-04-12 11:04:53 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + update libtool versioning + Original commit message from CVS: + update libtool versioning + +2006-04-12 10:58:00 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + * win32/common/config.h: + prerelease + Original commit message from CVS: + prerelease + +2006-04-11 17:31:29 +0000 Antoine Tremblay <hexa00@gmail.com> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Fix some memory leaks: on finalize, free buffers left in the queue before des... + Original commit message from CVS: + Patch by: Antoine Tremblay <hexa00 at gmail dot com> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_finalize), (gst_base_rtp_depayload_push): + Fix some memory leaks: on finalize, free buffers left in the queue + before destroying the queue; in _push(), unref rtp_buf even if + the process vfunc returned a NULL buffer as output buffer (#337548); + demote some recuring debug messages to LOG level. + +2006-04-11 15:01:51 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + fix version number macro + Original commit message from CVS: + fix version number macro + +2006-04-11 14:42:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: More cleanups. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query), + (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), + (gst_ogg_chain_free), (gst_ogg_demux_sink_event), + (gst_ogg_demux_loop): + More cleanups. + Respect segment stop when emiting EOS or SEGMENT_DONE. + Fixes (#337945). + +2006-04-11 10:45:32 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gststreamselector.c: Don't leak pad name. + Original commit message from CVS: + * gst/playback/gststreamselector.c: + (gst_stream_selector_get_property): + Don't leak pad name. + +2006-04-11 09:42:52 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + Mention bug #336617 closed by recent commit + Original commit message from CVS: + Mention bug #336617 closed by recent commit + +2006-04-10 20:32:46 +0000 Michael Smith <msmith@xiph.org> + + tests/check/: so that FC4 buildslaves can pass. + Original commit message from CVS: + * tests/check/Makefile.am: + * tests/check/gst-plugins-base.supp: + Suppress an old libtheora bug (fixed in more recent versions), so + that FC4 buildslaves can pass. + +2006-04-10 19:13:30 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Don't leak events. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query), + (gst_ogg_demux_receive_event), (gst_ogg_pad_event), + (gst_ogg_demux_init), (gst_ogg_demux_finalize), + (gst_ogg_demux_sink_event), (gst_ogg_demux_get_data), + (gst_ogg_demux_loop): + Don't leak events. + Remember what error we got when finding chains, if we + were shutdown, that would not be an error. + +2006-04-10 17:05:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Starting the ringbuffer when we did not acquire it can cause a deadlock, is po... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_event): + Starting the ringbuffer when we did not acquire it can cause + a deadlock, is pointless and causes nasty things for + subclasses. + Fixes gst-launch audiotestsrc num-buffers=0 ! alsasink. + +2006-04-10 15:17:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Add some more debugging. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_src_query), + (gst_ogg_demux_receive_event), (gst_ogg_pad_event), + (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), + (gst_ogg_demux_submit_buffer), (gst_ogg_demux_get_data), + (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_activate_chain), (gst_ogg_demux_perform_seek), + (gst_ogg_demux_bisect_forward_serialno), + (gst_ogg_demux_find_chains), (gst_ogg_demux_chain): + Add some more debugging. + +2006-04-10 14:52:10 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * ext/theora/theoraenc.c: + fix width of docs + Original commit message from CVS: + fix width of docs + +2006-04-10 10:29:21 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Some more debug info. + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_src_event), + (theora_handle_data_packet): + Some more debug info. + * tests/examples/seek/seek.c: (start_seek), (main): + Print element messages too. + +2006-04-09 17:14:22 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst/audioresample/debug.h: replace debug macros with variable number of parameters by a simple alias to gstreamer sta... + Original commit message from CVS: + * gst/audioresample/debug.h: + replace debug macros with variable number of parameters + by a simple alias to gstreamer standard debug macros + (#define RESAMPLE_ERROR GST_ERROR, __VA_ARGS__ is not + supported by MSVC 6.0 and 7.1) + * gst/audioresample/resample.h: + define M_PI and rint for WIN32 + * win32/common/libgstaudio.def: + * win32/common/libgstriff.def: + * win32/common/libgsttag.def: + * win32/common/libgstvideo.def: + add new exported functions + * win32/vs6: + update project files + +2006-04-08 21:02:53 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix #337365 (g_type_class_ref <-> g_type_class_peek_parent) + Original commit message from CVS: + * ext/alsa/gstalsamixeroptions.c: + (gst_alsa_mixer_options_class_init): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_class_init): + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_class_init): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init): + * ext/ogg/gstoggparse.c: (gst_ogg_parse_class_init): + * gst-libs/gst/audio/gstaudioclock.c: (gst_audio_clock_class_init): + * gst-libs/gst/audio/gstaudiofilter.c: + (gst_audio_filter_class_init): + * gst-libs/gst/audio/gstaudiosink.c: + (gst_audioringbuffer_class_init): + * gst-libs/gst/audio/gstaudiosrc.c: + (gst_audioringbuffer_class_init): + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_class_init): + * gst-libs/gst/interfaces/colorbalancechannel.c: + (gst_color_balance_channel_class_init): + * gst-libs/gst/interfaces/mixeroptions.c: + (gst_mixer_options_class_init): + * gst-libs/gst/interfaces/mixertrack.c: + (gst_mixer_track_class_init): + * gst-libs/gst/interfaces/tunerchannel.c: + (gst_tuner_channel_class_init): + * gst-libs/gst/interfaces/tunernorm.c: (gst_tuner_norm_class_init): + * gst-libs/gst/netbuffer/gstnetbuffer.c: + (gst_netbuffer_class_init): + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_class_init): + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init): + * gst/playback/gstplaybin.c: (gst_play_bin_class_init): + * gst/playback/gststreaminfo.c: (gst_stream_info_class_init): + * gst/playback/gststreamselector.c: + (gst_stream_selector_class_init): + * gst/subparse/gstsubparse.c: (gst_sub_parse_class_init): + * gst/tcp/gsttcpclientsink.c: (gst_tcp_client_sink_class_init): + * sys/v4l/gstv4lcolorbalance.c: + (gst_v4l_color_balance_channel_class_init): + * sys/v4l/gstv4ljpegsrc.c: (gst_v4ljpegsrc_class_init): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): + * sys/v4l/gstv4ltuner.c: (gst_v4l_tuner_channel_class_init), + (gst_v4l_tuner_norm_class_init): + * sys/ximage/ximagesink.c: (gst_ximagesink_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_class_init): + * tests/old/testsuite/alsa/sinesrc.c: (sinesrc_class_init): + Fix #337365 (g_type_class_ref <-> g_type_class_peek_parent) + +2006-04-08 18:09:17 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Fix broken GObject macros + Original commit message from CVS: + * ext/pango/gsttextrender.h: + * gst-libs/gst/audio/gstaudiosink.h: + * gst-libs/gst/audio/gstaudiosrc.h: + * gst-libs/gst/audio/gstbaseaudiosink.h: + * gst-libs/gst/audio/gstbaseaudiosrc.h: + * gst-libs/gst/audio/gstringbuffer.h: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + * gst-libs/gst/rtp/gstbasertppayload.h: + * gst-libs/gst/video/gstvideofilter.h: + * gst-libs/gst/video/gstvideosink.h: + * gst/playback/gstplaybasebin.h: + * gst/tcp/gstmultifdsink.h: + * sys/v4l/gstv4lelement.h: + Fix broken GObject macros + +2006-04-08 16:21:15 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/alsa/gstalsasink.c: More debug to trace why my USB headset is not working with gst + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (set_hwparams), (alsasink_parse_spec): + More debug to trace why my USB headset is not working with gst + +2006-04-07 17:18:11 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybasebin.c: Clean up our group elements properly in the case where it never got committed - it sti... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (group_destroy): + Clean up our group elements properly in the case where it never + got committed - it still got added unconditionally to the bin. + +2006-04-07 15:14:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Unref unhandled events. + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_dec_sink_event), + (theora_handle_data_packet), (theora_dec_chain): + Unref unhandled events. + Protect against empty buffers. + Perform QoS on running time. + +2006-04-07 13:24:54 +0000 Michael Smith <msmith@xiph.org> + + ext/vorbis/vorbisenc.c: Remove leaks from vorbisenc. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_set_header_on_caps), + (gst_vorbis_enc_chain): + Remove leaks from vorbisenc. + Mostly minor changes, the only significant one is that now the + buffers we set as 'streamheader' on the caps are copies of the + original buffers, to avoid circular refcounting problems. + +2006-04-07 09:51:35 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybasebin.c: Don't remove our mute-probe if someone else already did so. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (mute_stream), (setup_substreams): + Don't remove our mute-probe if someone else already did so. + Don't set a 2nd one if there is already one pending on the pad. + * gst/playback/gstplaybin.c: (gst_play_bin_send_event_to_sink), + (do_playbin_seek): + When a seek fails, ensure that playbin is still set back to playing. + * gst/typefind/gsttypefindfunctions.c: (mpeg_ts_probe_headers), + (mpeg_ts_type_find), (plugin_init): + Add a typefind function for mpeg-ts streams. + +2006-04-06 11:40:45 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * gst/audiotestsrc/gstaudiotestsrc.c: + * gst/videorate/gstvideorate.c: + gst/videorate/gstvideorate.c (gst_video_rate_reset) + Original commit message from CVS: + 2006-04-06 Andy Wingo <wingo@pobox.com> + * gst/videorate/gstvideorate.c (gst_video_rate_reset) + (gst_video_rate_init): Caps-related parameters should not be reset + by a flush -- move their inits to the instance init function. + (gst_video_rate_flush_prev): Don't complain if gst_pad_push + is not OK, just return the result. + * gst/audiotestsrc/gstaudiotestsrc.c + (gst_audio_test_src_class_init) + (gst_audio_test_src_get_times): Re-enable is-live=true, as was + broken by Stefan's commit on 24 March. + +2006-04-06 10:50:14 +0000 Andy Wingo <wingo@pobox.com> + + ext/ogg/gstoggmux.c (gst_ogg_mux_push_buffer): Set caps on buffers being pushed out. Fixes oggmux ! multifdsink. + Original commit message from CVS: + 2006-04-06 Andy Wingo <wingo@pobox.com> + * ext/ogg/gstoggmux.c (gst_ogg_mux_push_buffer): Set caps on + buffers being pushed out. Fixes oggmux ! multifdsink. + +2006-04-05 13:05:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/vorbis/: Remove left-over 0.8 cruft; use GST_DEBUG_FUNCPTR; make vorbisenc adhere to the official nomenclature; u... + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_class_init), + (gst_vorbis_dec_init), (vorbis_dec_finalize): + * ext/vorbis/vorbisdec.h: + * ext/vorbis/vorbisenc.c: (gst_vorbis_enc_add_interfaces), + (gst_vorbis_enc_base_init), (gst_vorbis_enc_class_init), + (gst_vorbis_enc_sink_setcaps), (gst_vorbis_enc_convert_src), + (gst_vorbis_enc_convert_sink), (gst_vorbis_enc_get_query_types), + (gst_vorbis_enc_src_query), (gst_vorbis_enc_sink_query), + (gst_vorbis_enc_init), (gst_vorbis_enc_get_tag_value), + (gst_vorbis_enc_metadata_set1), (gst_vorbis_enc_set_metadata), + (gst_vorbis_enc_setup), (gst_vorbis_enc_clear), + (gst_vorbis_enc_buffer_from_packet), + (gst_vorbis_enc_buffer_from_header_packet), + (gst_vorbis_enc_push_buffer), (gst_vorbis_enc_push_packet), + (gst_vorbis_enc_set_header_on_caps), (gst_vorbis_enc_sink_event), + (gst_vorbis_enc_chain), (gst_vorbis_enc_output_buffers), + (gst_vorbis_enc_get_property), (gst_vorbis_enc_set_property), + (gst_vorbis_enc_change_state): + * ext/vorbis/vorbisenc.h: + Remove left-over 0.8 cruft; use GST_DEBUG_FUNCPTR; make + vorbisenc adhere to the official nomenclature; use boilerplate + macro. + +2006-04-04 11:20:24 +0000 Andy Wingo <wingo@pobox.com> + + gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): Whoops, fix bug introduced. Bad hacker! + Original commit message from CVS: + 2006-04-04 Andy Wingo <wingo@pobox.com> + * gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): + Whoops, fix bug introduced. Bad hacker! + +2006-04-04 11:15:00 +0000 Andy Wingo <wingo@pobox.com> + + gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): Properly handle the case where you get EOS before any buffe... + Original commit message from CVS: + 2006-04-04 Andy Wingo <wingo@pobox.com> + * gst/videorate/gstvideorate.c (gst_video_rate_flush_prev): + Properly handle the case where you get EOS before any buffers are + received. Use gst_buffer_make_metadata_writable where appropriate. + +2006-04-04 10:16:46 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/theoradec.c (theora_handle_data_packet): This value is often negative -- make it signed so as not to wrap ... + Original commit message from CVS: + 2006-04-04 Andy Wingo <wingo@pobox.com> + * ext/theora/theoradec.c (theora_handle_data_packet): This value + is often negative -- make it signed so as not to wrap around. + Fixes segfaults introduced on 9 March. + +2006-04-03 16:43:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/: Don't try to store a gdouble in a gboolean. + Original commit message from CVS: + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (theora_dec_src_event): + Don't try to store a gdouble in a gboolean. + Small cleanups. + +2006-04-03 12:55:18 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggmux.c: Oggmux sucks. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_queue_pads): + Oggmux sucks. + Make it suck slightly less by writing out the final page. + Still can't encode a vorbis-in-ogg file correctly, though. + +2006-04-03 08:49:06 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/theoraparse.c (theora_parse_drain_queue): Um, remove a g_print. + Original commit message from CVS: + 2006-04-03 Andy Wingo <wingo@pobox.com> + * ext/theora/theoraparse.c (theora_parse_drain_queue): Um, remove + a g_print. + +2006-04-03 08:32:21 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/theora.c (plugin_init): Register theoraparse. + Original commit message from CVS: + 2006-04-03 Andy Wingo <wingo@pobox.com> + * ext/theora/theora.c (plugin_init): Register theoraparse. + * ext/theora/gsttheoraparse.h: + * ext/theora/theoraparse.c: New files implementing a theora + parser. Now we can properly remux ogg/theora+vorbis, yay. + +2006-04-03 08:28:58 +0000 Andy Wingo <wingo@pobox.com> + + ext/vorbis/vorbisparse.c: Add some docs and a copyright. + Original commit message from CVS: + 2006-04-03 Andy Wingo <wingo@pobox.com> + * ext/vorbis/vorbisparse.c: Add some docs and a copyright. + +2006-04-01 15:34:38 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * configure.ac: + don't use AS_LIBTOOL_TAGS, it doesn't work + Original commit message from CVS: + don't use AS_LIBTOOL_TAGS, it doesn't work + +2006-04-01 11:41:13 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * ext/pango/gsttextoverlay.c: + * sys/v4l/gstv4lsrc.c: + remove BT8x8 from description, works for more devices + Original commit message from CVS: + remove BT8x8 from description, works for more devices + +2006-04-01 11:21:30 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/audiotestsrc/gstaudiotestsrc.c: Fixed the sample pipeline (see #323798) + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + Fixed the sample pipeline (see #323798) + +2006-04-01 09:50:34 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + use AS_VERSION and AS_NANO more cleanups + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + * win32/common/config.h.in: + use AS_VERSION and AS_NANO + more cleanups + +2006-03-31 17:08:41 +0000 Andy Wingo <wingo@pobox.com> + + ext/vorbis/vorbisparse.c (vorbis_parse_sink_event): Fix uninitialized variable return that would happen. + Original commit message from CVS: + 2006-03-31 Andy Wingo <wingo@pobox.com> + * ext/vorbis/vorbisparse.c (vorbis_parse_sink_event): Fix + uninitialized variable return that would happen. + +2006-03-31 16:57:47 +0000 Andy Wingo <wingo@pobox.com> + + ext/vorbis/vorbisparse.c (vorbis_parse_drain_queue): Fix uninitialized variable return that would never happen. + Original commit message from CVS: + 2006-03-31 Andy Wingo <wingo@pobox.com> + * ext/vorbis/vorbisparse.c (vorbis_parse_drain_queue): Fix + uninitialized variable return that would never happen. + +2006-03-31 16:43:43 +0000 Andy Wingo <wingo@pobox.com> + + ext/vorbis/vorbisparse.c (gst_vorbis_parse_init) + Original commit message from CVS: + 2006-03-31 Andy Wingo <wingo@pobox.com> + * ext/vorbis/vorbisparse.c (gst_vorbis_parse_init) + (vorbis_parse_sink_event): Add an event function to flush our + state on a seek, and to drain buffers on a premature EOS. + (vorbis_parse_push_headers, vorbis_parse_clear_queue) + (vorbis_parse_push_buffer, vorbis_parse_drain_queue_prematurely) + (vorbis_parse_chain, vorbis_parse_queue_buffer) + (vorbis_parse_drain_queue): Queue up buffers until we can set + their timestamps and granulepos values. + * ext/vorbis/vorbisparse.h: Include the vorbis decoder headers, + and keep track of data needed for deriving granulepos and + timestamps for buffers. + +2006-03-30 11:05:25 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + expose pluginsdir so gonlin can use it for tests + Original commit message from CVS: + expose pluginsdir so gonlin can use it for tests + +2006-03-30 10:03:56 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-base.pc.in: + add ccda to libraries + Original commit message from CVS: + add ccda to libraries + +2006-03-29 14:00:08 +0000 j^ <j@bootlab.org> + + better/unified long descriptions + Original commit message from CVS: + Patch by: j^ <j at bootlab dot org> + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_class_init): + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasrc.c: (gst_alsasrc_class_init): + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: + * ext/pango/gstclockoverlay.c: + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/pango/gsttimeoverlay.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * gst/audioconvert/gstaudioconvert.c: + * gst/subparse/gstsubparse.c: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + better/unified long descriptions + Fixes #336477 + +2006-03-29 13:54:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Don't let double and tripple clicks mess up our state. + Original commit message from CVS: + * tests/examples/seek/seek.c: (end_scrub), (seek_cb), (start_seek), + (stop_seek): + Don't let double and tripple clicks mess up our state. + +2006-03-28 13:13:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybin.c: Error out gracefully when we can't create any of the usual conversion elements for some re... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_text_element), (gen_audio_element), (gen_vis_element): + Error out gracefully when we can't create any of the usual + conversion elements for some reason. Also, don't try to + create an audioscale (sic) element that's not used anyway. + +2006-03-28 10:21:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Don't post RESOURCE_NOT_FOUND error when we can't find a source element for a particul... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source): + Don't post RESOURCE_NOT_FOUND error when we can't find a source + element for a particular protocol, that's confusing for users. + Instead, post a RESOURCE_FAILED error, so that our own error + message is actually shown in totem etc. (#336303). + +2006-03-27 16:36:46 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + ext/gnomevfs/gstgnomevfssrc.c: Fix some minor memory leaks (#336194). + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_finalize), + (gst_gnome_vfs_src_get_icy_metadata): + Fix some minor memory leaks (#336194). + +2006-03-27 16:15:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/: Make gnomevfssink accept filenames as well as URIs for the "location" property, just like gnomevfssrc ... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfs.c: + (gst_gnome_vfs_location_to_uri_string): + * ext/gnomevfs/gstgnomevfs.h: + * ext/gnomevfs/gstgnomevfssink.c: + (gst_gnome_vfs_sink_set_property): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_set_property): + Make gnomevfssink accept filenames as well as URIs for the + "location" property, just like gnomevfssrc does (and + filesrc/filesink do) (#336190). + +2006-03-24 20:35:34 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/check/generic/clock-selection.c: set to NULL before unreffing, fixes a valgrind leak. + Original commit message from CVS: + * tests/check/generic/clock-selection.c: (GST_START_TEST): + set to NULL before unreffing, fixes a valgrind leak. + Why was this not triggering the error that an object needs to + be NULL before unreffing ? + * win32/common/config.h: + update + +2006-03-24 17:57:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.*: Text subtitle files may or may not be UTF-8. If it's not, we don't really want to see '?'... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (convert_encoding), + (gst_sub_parse_change_state): + * gst/subparse/gstsubparse.h: + Text subtitle files may or may not be UTF-8. If it's not, we + don't really want to see '?' characters in place of non-ASCII + characters like accented characters. So let's assume the input + is UTF-8 until we come across text that is clearly not. If it's + not UTF-8, we don't really know what it is, so try the following: + (a) see whether the GST_SUBTITLE_ENCODING environment variable + is set; if not, check (b) if the current locale encoding is + non-UTF-8 and use that if it is, or (c) assume ISO-8859-15 if + the current locale encoding is UTF-8 and the environment variable + was not set to any particular encoding. Not perfect, but better + than nothing (and better than before, I think) (fixes #172848). + +2006-03-24 17:39:45 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * docs/plugins/tmpl/.gitignore: + * tests/check/libs/.gitignore: + * tests/check/pipelines/.gitignore: + * tests/examples/volume/.gitignore: + ignore more + Original commit message from CVS: + ignore more + +2006-03-24 17:26:54 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: update core requirement to 0.10.4.1 because of async_playback vmethod on GstBaseSink + Original commit message from CVS: + 2006-03-24 Thomas Vander Stichele <thomas at apestaart dot org> + * configure.ac: + update core requirement to 0.10.4.1 because of async_playback + vmethod on GstBaseSink + +2006-03-24 17:11:53 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + use DEBUG_FUNCPTR for collectpads + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_init): + * gst/adder/gstadder.c: (gst_adder_init): + use DEBUG_FUNCPTR for collectpads + +2006-03-24 14:11:20 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * Makefile.am: + don't go through check-torture if no check installed + Original commit message from CVS: + don't go through check-torture if no check installed + +2006-03-24 10:42:11 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + Add docs for adder, use GST_ELEMENT_DETAILS macro, define GstElementDetails at the top + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/cdparanoia/gstcdparanoiasrc.c: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_base_init), + (gst_gnome_vfs_sink_class_init): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_base_init): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_base_init): + * ext/ogg/gstoggmux.c: + * ext/ogg/gstoggparse.c: (gst_ogg_parse_base_init): + * ext/ogg/gstogmparse.c: (gst_ogm_audio_parse_base_init), + (gst_ogm_video_parse_base_init), (gst_ogm_text_parse_base_init): + * ext/pango/gsttextoverlay.c: + * ext/pango/gsttextrender.c: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisenc.c: + * gst-libs/gst/audio/gstaudiofilter.c: + (gst_audio_filter_base_init): + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + (gst_audio_filter_template_base_init): + * gst/adder/gstadder.c: (gst_adder_get_type): + * gst/adder/gstadder.h: + * gst/audioconvert/gstaudioconvert.c: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audiostestsrc_wave_get_type), (gst_audio_test_src_class_init), + (gst_audio_test_src_create): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + * gst/playback/gstdecodebin.c: + * gst/playback/gstplaybin.c: + * gst/playback/gststreamselector.c: + (gst_stream_selector_base_init): + * gst/subparse/gstsubparse.c: (gst_sub_parse_base_init): + * gst/volume/gstvolume.c: + * sys/v4l/gstv4lmjpegsink.c: + * sys/v4l/gstv4lmjpegsrc.c: + * tests/check/libs/cddabasesrc.c: + * tests/old/examples/gob/gst-identity2.gob: + Add docs for adder, use GST_ELEMENT_DETAILS macro, + define GstElementDetails at the top + +2006-03-23 21:48:18 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/common/libgstinterfaces.def: Add a lot of export functions for gst-python + Original commit message from CVS: + * win32/common/libgstinterfaces.def: + Add a lot of export functions for gst-python + * win32/common/libgstinterfaces.dsp: + Add a missing include folder in the project configuration + +2006-03-23 16:58:03 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: Fix audio sources, forgot to make the ringbuffer startable... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_get_time), (gst_base_audio_src_create), + (gst_base_audio_src_change_state): + Fix audio sources, forgot to make the ringbuffer + startable... + +2006-03-23 16:29:58 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosrc.c: unparent instead of unref the ringbuffer. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_get_time), (gst_base_audio_src_create), + (gst_base_audio_src_change_state): + unparent instead of unref the ringbuffer. + +2006-03-23 16:24:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Implement new async_play vmethod to start slaving and allow playback start in ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init), (gst_base_audio_sink_async_play), + (gst_base_audio_sink_do_play), (gst_base_audio_sink_change_state): + Implement new async_play vmethod to start slaving and allow + playback start in case of async PLAY state changes. + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init): + Enable QoS with new method in base class. + +2006-03-23 11:18:19 +0000 Julien MOUTTE <julien@moutte.net> + + gst/videotestsrc/gstvideotestsrc.c: Partially handle 0 framerate, only EOS after the first frame is missing. + Original commit message from CVS: + Patch by: Julien MOUTTE <julien at moutte dot net> + * gst/videotestsrc/gstvideotestsrc.c: (gst_video_test_src_query), + (gst_video_test_src_do_seek), (gst_video_test_src_create): + Partially handle 0 framerate, only EOS after the first frame + is missing. + +2006-03-23 09:38:59 +0000 Fabrizio Gennari <fabrizio.ge@tiscali.it> + + gst/: Patch for support of YVU9 AVI files (#334822) + Original commit message from CVS: + Patch by: Fabrizio Gennari <fabrizio dot ge at tiscali dot it> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: + Patch for support of YVU9 AVI files (#334822) + +2006-03-22 15:29:25 +0000 Edward Hervey <bilboed@bilboed.com> + + docs/design/design-decodebin.txt: Added design document for new decodebin text/x-pango-markup is also a default targe... + Original commit message from CVS: + * docs/design/design-decodebin.txt: + Added design document for new decodebin + (Target Caps): text/x-pango-markup is also a default target caps. + +2006-03-22 15:11:47 +0000 Edward Hervey <bilboed@bilboed.com> + + docs/design/design-decodebin.txt: Added design document for new decodebin + Original commit message from CVS: + * docs/design/design-decodebin.txt: + Added design document for new decodebin + +2006-03-22 12:33:09 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Since we _parent the ringbuffer, we also need to _unparent instead of a plain ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_dispose): + Since we _parent the ringbuffer, we also need to + _unparent instead of a plain _unref. + +2006-03-22 12:28:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/seek.c: Add scrub checkbox. + Original commit message from CVS: + * tests/examples/seek/seek.c: (end_scrub), (do_seek), (seek_cb), + (stop_seek), (scrub_toggle_cb), (main): + Add scrub checkbox. + +2006-03-21 17:47:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstoggparse.c: Fix very inefficient usage of linked lists (#335365). + Original commit message from CVS: + * ext/ogg/gstoggparse.c: (gst_ogg_parse_find_stream), + (gst_ogg_parse_chain): + Fix very inefficient usage of linked lists (#335365). + +2006-03-21 14:26:01 +0000 Edward Hervey <bilboed@bilboed.com> + + gcc 4.1 unreferenced pointer fixes. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_dispose): + * gst/playback/gstplaybin.c: (handoff): + * gst/playback/gststreamselector.c: + (gst_stream_selector_set_property): + gcc 4.1 unreferenced pointer fixes. + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_put): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put): + gst_buffer_ref() now takes a GstBuffer*. + +2006-03-20 18:09:41 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.c: Fix a memleak reported by Jan Schmidt. + Original commit message from CVS: + 2006-03-20 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_get_format_from_caps): Fix a memleak reported + by Jan Schmidt. + +2006-03-19 11:37:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Can't do tag preferences via probability, as tags would then lose against types ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (id3v2_type_find), + (id3v1_type_find), (apetag_type_find), (plugin_init): + Can't do tag preferences via probability, as tags would then + lose against types that are recognised with MAXIMUM probability + (like .wav); so let all tag typefinders return MAXIMUM themselves + and order them via the rank. Split ID3v1 and ID3v2 typefinders so + that we can prefer APE to ID3v1 (fixes #335028). + +2006-03-17 17:48:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/: Only start playback if we are playing. should fix #330748. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_change_state): + * gst-libs/gst/audio/gstringbuffer.c: (wait_segment), + (gst_ring_buffer_may_start): + * gst-libs/gst/audio/gstringbuffer.h: + Only start playback if we are playing. + should fix #330748. + +2006-03-17 13:11:45 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Revert accidental commits to these files. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_getcaps): + * win32/common/config.h: + Revert accidental commits to these files. + +2006-03-16 20:01:03 +0000 Michal Benes <michal.benes@xeris.cz> + + tests/Makefile.am: Don't try to build tests in tests/icles if we don't have X (#323852) + Original commit message from CVS: + Patch by: Michal Benes <michal dot benes at xeris dot cz> + * tests/Makefile.am: + Don't try to build tests in tests/icles if we + don't have X (#323852) + +2006-03-16 13:08:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstid3tag.c: Add TXXX frame identifiers for replaygain stuff as used by some taggers (see #323721). + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Add TXXX frame identifiers for replaygain stuff as used + by some taggers (see #323721). + +2006-03-16 10:22:27 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gststreamselector.c: Preserve the existing buggy streamselector behaviour by performing a fallback buffe... + Original commit message from CVS: + * gst/playback/gststreamselector.c: + (gst_stream_selector_set_property), + (gst_stream_selector_bufferalloc): + Preserve the existing buggy streamselector behaviour by performing + a fallback buffer allocation when downstream isn't linked yet. + This should really be fixed in playbin by blocking pads until it's + linked them. + Also, use gst_pad_alloc_buffer instead of + gst_pad_alloc_buffer_and_set. + +2006-03-15 22:40:08 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstid3tag.c: Don't crash on unknown ID3v2 TXXX frames. + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Don't crash on unknown ID3v2 TXXX frames. + +2006-03-15 17:59:05 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/alsa/gstalsasink.c: Chain up to the parent finalize method. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_finalise): + Chain up to the parent finalize method. + Add 32-bit sample size to the template caps. + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add the fourcc that the VMWare codec uses. + * gst/playback/gststreamselector.c: + (gst_stream_selector_set_property), + (gst_stream_selector_bufferalloc), + (gst_stream_selector_request_new_pad): + For the active pad, forward buffer-alloc requests, otherwise + return GST_FLOW_NOT_LINKED. This also prevents xvimagesink + having to memcpy every frame when used by playbin. + * gst/tcp/gstmultifdsink.c: + (gst_multi_fd_sink_handle_client_write): + Get negotiated caps from the sink pad, rather than the sink + pad's peer. + +2006-03-15 17:11:34 +0000 Tommi Myöhänen <ext-tommi.myohanen@nokia.com> + + ext/gnomevfs/gstgnomevfssrc.c: Don't forget to set src->callbacks_pushed to FALSE again when popping them, otherwise ... + Original commit message from CVS: + Patch by: Tommi Myöhänen <ext-tommi dot myohanen at nokia dot com> + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_pop_callbacks): + Don't forget to set src->callbacks_pushed to FALSE again when + popping them, otherwise re-activation in a different mode won't + work (#334620). + +2006-03-15 11:30:29 +0000 Sebastien Moutte <sebastien@moutte.net> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Replace __VA_ARGS__ caps creation macros with varargs functions. looks nice... + Original commit message from CVS: + Patch by: Sebastien Moutte <sebastien moutte net> + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: (gst_ff_vid_caps_new), + (gst_ff_aud_caps_new), (gst_ffmpeg_pixfmt_to_caps), + (gst_ffmpeg_smpfmt_to_caps): + Replace __VA_ARGS__ caps creation macros with varargs functions. + Makes things compile on MSVC (#320765), looks nicer, and we can + tell the compiler to check for the NULL terminator. + +2006-03-14 15:13:04 +0000 Fabrizio Gennari <fabrizio.ge@tiscali.it> + + gst-libs/gst/riff/riff-media.c: Make sure the buffer we copy into is really always big enough, this time for real (#3... + Original commit message from CVS: + Patch by: Fabrizio Gennari <fabrizio dot ge at tiscali dot it> + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Make sure the buffer we copy into is really always big + enough, this time for real (#333488). + +2006-03-14 13:16:49 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Add support for 24bpp DIB (#305279). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add support for 24bpp DIB (#305279). + +2006-03-14 11:11:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/: Re-enable QoS after the release. + Original commit message from CVS: + * gst-libs/gst/video/gstvideofilter.c: (gst_video_filter_init): + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: (gst_ffmpegcsp_init): + * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init), + (gst_video_scale_init), (gst_video_scale_src_event): + Re-enable QoS after the release. + Rework videoscale to use the base class src_event handler. + +2006-03-14 09:51:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: back to CVS. + Original commit message from CVS: + * configure.ac: + back to CVS. + +=== release 0.10.5 === + +2006-03-13 19:50:04 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/config.h: + releasing 0.10.5 + Original commit message from CVS: + releasing 0.10.5 + +2006-03-13 17:28:23 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-03-13 11:17:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/plugins/Makefile.am: Part of previous cdparanoiasrc docs fixes, forgot to commit. + Original commit message from CVS: + * docs/plugins/Makefile.am: + Part of previous cdparanoiasrc docs fixes, forgot to commit. + +2006-03-12 14:56:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/plugins/: Add cdparanoiasrc to docs. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + Add cdparanoiasrc to docs. + * gst-libs/gst/cdda/gstcddabasesrc.c: + More GstCddaBaseSrc docs. + +2006-03-12 13:47:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add new API to libgsttag: gst_tag_from_id3_user_tag(). + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstid3tag.c: (gst_tag_from_id3_user_tag): + * gst-libs/gst/tag/tag.h: + Add new API to libgsttag: gst_tag_from_id3_user_tag(). + +2006-03-11 19:47:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: NULL-terminate array of mpeg4 video file extensions. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + NULL-terminate array of mpeg4 video file extensions. + Fixes crash on PPC (#334226). + +2006-03-11 16:40:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: gnome_vfs_uri_is_local() alone is not a good indicator whether we can operate in pull-... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: + (gst_gnome_vfs_src_check_get_range): + gnome_vfs_uri_is_local() alone is not a good indicator + whether we can operate in pull-mode with a specific URI, + as it returns FALSE for file:// URIs that point to an + NFS-mounted path. Be more conservative here: whitelist + local files, blacklist http URIs and use the old + mechanism for anything else (fixes #334216). + +2006-03-10 19:15:34 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + configure.ac: back to trunk + Original commit message from CVS: + * configure.ac: + back to trunk + +=== release 0.10.4 === + +2006-03-10 19:05:13 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * docs/upload.mak: + * win32/common/config.h: + releasing 0.10.4 + Original commit message from CVS: + releasing 0.10.4 + +2006-03-10 12:37:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/video/gstvideosink.c: Disable max-lateness by setting it to -1 for now, so that we can bed QoS stuff in ... + Original commit message from CVS: + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init): + Disable max-lateness by setting it to -1 for now, so that + we can bed QoS stuff in thoroughly between now and the next + release. + +2006-03-10 11:09:23 +0000 Fabrizio <fabrizio.ge@tiscali.it> + + gst-libs/gst/riff/riff-media.c: Make sure we don't read beyond the palette buffer in case of + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Make sure we don't read beyond the palette buffer in case of + broken or manipulated files (#333488, patch by: Fabrizio + Gennari) + +2006-03-10 10:44:02 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Fix for variable not initialized. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset): + Fix for variable not initialized. + +2006-03-09 19:02:32 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + * docs/libs/tmpl/gstringbuffer.sgml: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + * win32/common/config.h: + prereleasing + Original commit message from CVS: + prereleasing + +2006-03-09 17:58:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: Small cleanups. + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_get_type), + (gst_visual_src_setcaps), (gst_vis_src_negotiate), + (gst_visual_chain): + Small cleanups. + * ext/theora/gsttheoradec.h: + * ext/theora/theoradec.c: (gst_theora_dec_init), + (gst_theora_dec_reset), (_theora_granule_time), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_dec_src_query), (theora_dec_src_event), + (theora_dec_sink_event), (theora_handle_comment_packet), + (theora_handle_header_packet), (theora_dec_push), + (theora_handle_data_packet), (theora_dec_chain), + (theora_dec_change_state): + Add simple QoS. + +2006-03-09 17:50:59 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/gnomevfs/gstgnomevfssrc.c: Some cleanups. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (audiocast_init), + (audiocast_register_listener), (gst_gnome_vfs_src_start): + Some cleanups. + +2006-03-09 17:45:39 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Don't try to activate NULL chains. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_activate_chain): + Don't try to activate NULL chains. + +2006-03-09 16:30:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Fix invalid memory access to region before peek'd data (#332964). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset): + Fix invalid memory access to region before peek'd data (#332964). + +2006-03-09 15:05:03 +0000 Christophe Fergeau <teuf@gnome.org> + + closes #333510. + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init): + * ext/pango/gsttextrender.c: (gst_text_render_init): + * gst/adder/gstadder.c: (gst_adder_init): + Don't leak padtemplates, patch by Christophe Fergeau, + closes #333510. + +2006-03-09 12:56:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Fix invalid memory access: make sure string passed to regexec() is NUL-termianted. + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (gst_subparse_type_find): + Fix invalid memory access: make sure string passed to + regexec() is NUL-termianted. + +2006-03-09 12:37:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Refactor mpeg/audio typefinding to make it more maintainable and easier to fine-... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find_at_offset), + (mp3_type_find): + Refactor mpeg/audio typefinding to make it more maintainable + and easier to fine-tune. Make probing into middle of the file + work properly (fixes #333900, also see #152688). + +2006-03-09 11:10:03 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Remove part from previous commit that was bogus: g_utf8_validate() does in fact ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + (utf8_type_find_have_valid_utf8_at_offset): + Remove part from previous commit that was bogus: + g_utf8_validate() does in fact not accept embedded + zeroes, so we don't need to check for those (thanks + to Mike for the hint). + +2006-03-08 17:11:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Make plain/text typefinder more conservative: firstly, check for embedded zeroes... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: + (utf8_type_find_count_embedded_zeroes), + (utf8_type_find_have_valid_utf8_at_offset), (utf8_type_find): + Make plain/text typefinder more conservative: firstly, check + for embedded zeroes, which are perfectly valid UTF-8 characters, + but also a fairly good sign that something is not a plain text + file; secondly, probe into the middle of the file if possible. + If we can't probe into the middle, limit the probability value + to be returned to TYPE_FIND_POSSIBLE (see #333900). + +2006-03-08 11:34:45 +0000 Michael Smith <msmith@xiph.org> + + gst/typefind/gsttypefindfunctions.c: Make typefind function name for mpeg4 video unique. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Make typefind function name for mpeg4 video unique. + +2006-03-08 09:53:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/libvisual/visual.c: Cleanups, post nice errors. + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_init), + (gst_visual_clear_actors), (gst_visual_dispose), + (gst_visual_reset), (gst_visual_src_setcaps), + (gst_visual_sink_setcaps), (gst_vis_src_negotiate), + (gst_visual_sink_event), (gst_visual_src_event), (get_buffer), + (gst_visual_chain), (gst_visual_change_state): + Cleanups, post nice errors. + Handle sink and src events. + Implement simple QoS. + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init): + Use new basesink methods to configure max-lateness. + Small doc update. + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_transform_caps), (gst_ffmpegcsp_set_caps): + Debug statement cleanups. + * gst/volume/gstvolume.c: (gst_volume_class_init): + Simple cleanup. + +2006-03-08 09:50:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Revert API/ABI break from March 1. Keep 'halign' and 'valign' as string type properties, ... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_class_init), + (gst_text_overlay_init), (gst_text_overlay_set_property), + (gst_text_overlay_get_property): + Revert API/ABI break from March 1. Keep 'halign' and 'valign' + as string type properties, but mark them deprecated. Add + 'halignment' and 'valignment' properties that use enums + instead of strings. + +2006-03-08 09:37:12 +0000 Fabrizio <fabrizio.ge@tiscali.it> + + gst-libs/gst/riff/riff-media.c: Allow palettes with less than 256 colours in AVI files + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Allow palettes with less than 256 colours in AVI files + (#333488, patch by: Fabrizio Gennari). + +2006-03-07 21:56:09 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Fix wrong EOS handling on text pad. We were releasing the queued text buffer when we shou... + Original commit message from CVS: + 2006-03-07 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_text_event), + (gst_text_overlay_video_event): Fix wrong EOS handling on text + pad. We were releasing the queued text buffer when we should keep + it until video pad gets EOS or discard the text buffer because it's + too old. That was eating the last subtitle buffer. Add some more + debug. + +2006-03-07 17:28:36 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Fix invalid memory access (we can't access a buffer after it's been pushed downstream wit... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_render_text), + (gst_text_overlay_video_chain): + Fix invalid memory access (we can't access a buffer after it's been + pushed downstream without taking a reference); fix memory leak (if + there's no text to render, bail out before allocating stuff). + +2006-03-07 15:08:15 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.*: If input is plain text, escape it before passing it to pango_layout_set_markup(). + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init), + (gst_text_overlay_setcaps_txt), (gst_text_overlay_video_chain): + * ext/pango/gsttextoverlay.h: + If input is plain text, escape it before passing it to + pango_layout_set_markup(). + +2006-03-07 13:01:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstaudiofilter.c: Don't ignore flow return from gst_pad_push(). + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audio_filter_chain): + Don't ignore flow return from gst_pad_push(). + +2006-03-07 12:49:03 +0000 Christophe Fergeau <teuf@gnome.org> + + Don't leak references returned by gst_pad_get_parent() + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_getcaps), + (gst_visual_src_setcaps), (gst_visual_sink_setcaps): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_sinkconnect): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_convert_src), + (gst_vorbisenc_convert_sink): + * gst-libs/gst/audio/audio.c: (gst_audio_frame_byte_size), + (gst_audio_duration_from_pad_buffer): + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audio_filter_link), + (gst_audio_filter_chain): + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps): + * gst-libs/gst/video/video.c: (gst_video_frame_rate), + (gst_video_get_size): + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_setcaps): + Don't leak references returned by gst_pad_get_parent() + (#333663, based on patch by: Christophe Fergeau). + +2006-03-06 20:52:25 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/gnomevfs/gstgnomevfssink.c: change location param details + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_class_init): + change location param details + * gst/volume/gstvolume.c: (plugin_init): + correct plugin description + +2006-03-06 20:07:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Override GstBaseSrc::check_get_range() in order to avoid opening the resource just to ... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_class_init), + (gst_gnome_vfs_src_check_get_range): + Override GstBaseSrc::check_get_range() in order to avoid opening + the resource just to check whether we can operate in pull-mode or + not - we can predict that pretty well from the URI alone. Should + fix problems with last.fm (#331690). (Requires latest core CVS). + +2006-03-06 16:18:51 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/video/gstvideosink.c: Throw away frames that are later than 20 ms. + Original commit message from CVS: + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_init), + (gst_video_sink_class_init): + Throw away frames that are later than 20 ms. + +2006-03-06 14:14:47 +0000 Fabrizio <fabrizio.ge@tiscali.it> + + gst-libs/gst/riff/riff-media.c: + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Set depth on WMA caps (#333545, patch by: Fabrizio Gennari). + +2006-03-05 23:39:50 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/ogg/gstoggmux.c: put Theora BOS pages before others. This hardcodes the Ogg/Theora I profile, but hey. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: (gst_ogg_mux_buffer_from_page), + (gst_ogg_mux_send_headers), (gst_ogg_mux_collected): + put Theora BOS pages before others. This hardcodes + the Ogg/Theora I profile, but hey. + +2006-03-05 23:06:22 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + changed more than 5 lines + Original commit message from CVS: + changed more than 5 lines + +2006-03-05 22:57:58 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ogg muxing of vorbis and theora now has pages ordered correctly again, even with delays. + Original commit message from CVS: + ogg muxing of vorbis and theora now has pages ordered correctly again, + even with delays. + * ext/ogg/README: + updated with some examples + * ext/theora/theoraenc.c: (granulepos_to_timestamp), + (granulepos_add), (theora_buffer_from_packet): + * ext/vorbis/vorbisenc.c: (granulepos_to_timestamp_offset), + (granulepos_to_timestamp), (gst_vorbisenc_buffer_from_packet), + (gst_vorbisenc_chain): + implement strategy from ext/ogg/README + * ext/ogg/gstoggmux.c: (gst_ogg_mux_buffer_from_page), + (gst_ogg_mux_push_buffer), (gst_ogg_mux_dequeue_page), + (gst_ogg_mux_pad_queue_page), (gst_ogg_mux_compare_pads), + (gst_ogg_mux_queue_pads), (gst_ogg_mux_collected): + Fix muxer so that oggz-validate is happy with all streams; + except for no eos mark, and the BOS page ordering + * tests/check/pipelines/theoraenc.c: (check_buffer_is_header), + (check_buffer_granulepos): + * tests/check/pipelines/vorbisenc.c: (check_buffer_granulepos): + update tests to check for OFFSET being set as requested + fixed type of granulepos, it's not a ClockTime + +2006-03-05 21:34:23 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.c: Check that the xvimage we are creating has a correct size before returning it. (#3... + Original commit message from CVS: + 2006-03-05 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_show_frame), (gst_xvimagesink_buffer_alloc): + Check that the xvimage we are creating has a correct size before returning it. (#314897) + +2006-03-05 13:44:05 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Give id3 and ape tag typefinders a rank slightly higher than PRIMARY to ensure t... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Give id3 and ape tag typefinders a rank slightly higher + than PRIMARY to ensure they're always run before any of + the other typefinders (in particular wav and mp3) (#324186). + +2006-03-05 13:08:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Add support for '3IVD' fourcc (#333403). + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add support for '3IVD' fourcc (#333403). + +2006-03-04 14:35:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + configure.ac: Bump requirements to GStreamer CVS for the new error enum. + Original commit message from CVS: + * configure.ac: + Bump requirements to GStreamer CVS for the new error enum. + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_render): + Emit new GST_RESOURCE_ERROR_NO_SPACE_LEFT when there's no + space left on the device (fixes #333352). + +2006-03-03 23:53:50 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/vs6: add a project file for libgstvolume update the workspace + Original commit message from CVS: + * win32/vs6: + add a project file for libgstvolume + update the workspace + +2006-03-03 15:26:57 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/README: + * ext/ogg/gstoggmux.c: + debug updates + Original commit message from CVS: + debug updates + +2006-03-03 15:22:02 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + Fix for http://bugzilla.gnome.org/show_bug.cgi?id=333254 + Original commit message from CVS: + 2006-03-03 Thomas Vander Stichele <thomas at apestaart dot org> + * ext/theora/theoraenc.c: (theora_set_header_on_caps): + * tests/check/pipelines/theoraenc.c: (check_buffer_is_header), + (GST_START_TEST): + Fix for http://bugzilla.gnome.org/show_bug.cgi?id=333254 + Set IN_CAPS on header buffers + +2006-03-02 18:23:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/plugins/: Add audioresample to docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + Add audioresample to docs. + * gst/audioconvert/gstaudioconvert.c: + Add revision date. + * gst/audioresample/gstaudioresample.c: + (gst_audioresample_base_init), (gst_audioresample_class_init), + (gst_audioresample_init), (gst_audioresample_dispose), + (audioresample_get_unit_size), (audioresample_transform_caps), + (resample_set_state_from_caps), (audioresample_transform_size), + (audioresample_set_caps), (audioresample_event), + (audioresample_do_output), (audioresample_transform), + (audioresample_pushthrough), (gst_audioresample_set_property), + (gst_audioresample_get_property), (plugin_init): + * gst/audioresample/gstaudioresample.h: + Added docs. + Small code cleanups. + +2006-03-02 18:12:33 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/videorate/Makefile.am: + fix wim's commit + Original commit message from CVS: + fix wim's commit + +2006-03-02 17:48:40 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + debug using the actual GstPad, that allows us to see the serialno in the padname + Original commit message from CVS: + debug using the actual GstPad, that allows us to see the serialno in the padname + +2006-03-02 17:46:36 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/plugins/: Added videoscale to docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + Added videoscale to docs. + * gst/videorate/gstvideorate.c: (gst_video_rate_flush_prev), + (gst_video_rate_swap_prev), (gst_video_rate_event), + (gst_video_rate_chain): + Fix typo in docs. + * gst/videoscale/gstvideoscale.c: (gst_video_scale_class_init), + (gst_video_scale_init), (gst_video_scale_prepare_size), + (gst_video_scale_set_caps), (gst_video_scale_get_unit_size), + (gst_video_scale_fixate_caps), (gst_video_scale_transform): + * gst/videoscale/gstvideoscale.h: + Added docs, examples. + Some code cleanups. + Post errors instead of g_warning. + +2006-03-02 17:30:57 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + clean up debug messages + Original commit message from CVS: + clean up debug messages + +2006-03-02 17:15:38 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + extra debugging from older version, makes it easier to compare + Original commit message from CVS: + extra debugging from older version, makes it easier to compare + +2006-03-02 17:04:55 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ext/ogg/gstoggmux.c: + some space cleanup and debug fixes + Original commit message from CVS: + some space cleanup and debug fixes + +2006-03-02 16:47:34 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/: Added some more docs to libs and plugins. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + Added some more docs to libs and plugins. + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_prepare_read), (gst_ring_buffer_clear): + * gst-libs/gst/audio/gstringbuffer.h: + Document ringbuffer some more. + * gst/videorate/gstvideorate.c: (gst_video_rate_class_init), + (gst_video_rate_setcaps), (gst_video_rate_reset), + (gst_video_rate_init), (gst_video_rate_flush_prev), + (gst_video_rate_swap_prev), (gst_video_rate_event), + (gst_video_rate_chain), (gst_video_rate_change_state): + * gst/videorate/gstvideorate.h: + Fix videorate to use segments. + Make it work with 0/1 framerates (closes #331903) + Handle EOS correctly. + Added docs. + +2006-03-02 13:13:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstogmparse.c: In state change function, first chain up to parent class, then handle downwards state change s... + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_class_init), + (gst_ogm_audio_parse_init), (gst_ogm_video_parse_init), + (gst_ogm_text_parse_init), (gst_ogm_parse_change_state): + In state change function, first chain up to parent class, + then handle downwards state change stuff. Remove some + commented out cruft from 0.8 code. + +2006-03-02 12:35:59 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/ogg/gstogmparse.c: Don't remove/re-add source pad if the new caps are the same as the old caps anyway (#333042). ... + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_audio_parse_init), + (gst_ogm_video_parse_init), (gst_ogm_text_parse_init), + (gst_ogm_parse_sink_convert), (gst_ogm_parse_sink_query), + (gst_ogm_parse_chain): + Don't remove/re-add source pad if the new caps are the same as + the old caps anyway (#333042). When removing source pad, don't + unref it afterwards - we didn't ref it when adding. Sprinkle some + GST_DEBUG_FUNCPTR goodness here and there. Don't leak references + after using gst_pad_get_parent(). Return downstream flow return + value in chain function. + +2006-03-02 11:28:23 +0000 Wim Taymans <wim.taymans@gmail.com> + + docs/plugins/: Fix hierarchy, added some more elements to the docs. + Original commit message from CVS: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.interfaces: + * docs/plugins/gst-plugins-base-plugins.signals: + Fix hierarchy, added some more elements to the docs. + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_get_type): + * gst/ffmpegcolorspace/gstffmpegcolorspace.h: + Fix docs for ffmpegcolorspace. + +2006-03-01 19:24:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Some typefinding fine-tuning: + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (id3_type_find), + (apetag_type_find), (ape_type_find), (plugin_init): + Some typefinding fine-tuning: + - rank ID3/APE tags in order of preference via probabilities, so that + ID3v2 > APEv2 > APEv1 > ID3v1. + - three or four bytes don't really justify MAXIMUM probability, + change those to 'very likely' (musepack and monkeysaudio). + +2006-03-01 18:25:18 +0000 Wim Taymans <wim.taymans@gmail.com> + + Added alsa docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/alsa/gstalsamixer.c: + * ext/alsa/gstalsamixer.h: + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_class_init), (gst_alsa_mixer_element_init): + * ext/alsa/gstalsamixerelement.h: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasink.h: + * ext/alsa/gstalsasrc.c: (gst_alsasrc_class_init), + (gst_alsasrc_init): + * ext/alsa/gstalsasrc.h: + Added alsa docs. + Small code cleanups. + +2006-03-01 17:52:45 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/Makefile.am: Dist new header too, + Original commit message from CVS: + * ext/theora/Makefile.am: + Dist new header too, + +2006-03-01 17:39:28 +0000 Wim Taymans <wim.taymans@gmail.com> + + Fix some more docs. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/gnomevfs/gstgnomevfssink.h: + * ext/gnomevfs/gstgnomevfssrc.h: + * ext/vorbis/vorbisdec.c: (vorbis_handle_data_packet): + * ext/vorbis/vorbisdec.h: + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_convert_sink): + * ext/vorbis/vorbisenc.h: + * ext/vorbis/vorbisparse.c: (vorbis_parse_set_header_on_caps), + (vorbis_parse_chain), (vorbis_parse_change_state): + * ext/vorbis/vorbisparse.h: + * gst/audioconvert/gstaudioconvert.h: + * gst/tcp/gsttcpserversink.h: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/volume/gstvolume.c: + * gst/volume/gstvolume.h: + Fix some more docs. + Added docs for vorbisdec and vorbisparse. + Fix vorbisparse. + +2006-03-01 16:24:37 +0000 Wim Taymans <wim.taymans@gmail.com> + + Updated/added documentation. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * ext/pango/gstclockoverlay.h: + * ext/pango/gsttextoverlay.h: + * ext/pango/gsttextrender.h: + * ext/pango/gsttimeoverlay.h: + * ext/theora/gsttheoradec.h: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * gst/audioconvert/gstaudioconvert.h: + * gst/audiotestsrc/gstaudiotestsrc.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.h: + * gst/tcp/gstmultifdsink.c: (gst_multi_fd_sink_class_init): + * gst/tcp/gstmultifdsink.h: + Updated/added documentation. + * ext/pango/gsttextoverlay.c: (gst_text_overlay_valign_get_type), + (gst_text_overlay_halign_get_type), + (gst_text_overlay_wrap_mode_get_type), + (gst_text_overlay_base_init), (gst_text_overlay_class_init), + (gst_text_overlay_init), (gst_text_overlay_set_property), + (gst_text_overlay_get_property): + Fix up properties to be enums instead of string to make bindings, + introspection and automatic GUI creation possible. + Add getters for the properties. + +2006-02-28 21:21:07 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst/audiotestsrc/gstaudiotestsrc.c: added defines of M_PI and M_PI_2 + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + added defines of M_PI and M_PI_2 + * gst/ffmpegcolorspace/avcodec.h: + removed #include "stdint.h" for win32 as _stdint.h is + autogenerated to win32/common + * win32/common/libgstaudio.def: + * win32/common/libgsttag.def: + added some exports + * win32/vs6: + some project files bugs corrected + * win32/vs7: + project files are reset to the default vs7 configuration + (they link to msvcr71.dll using default optimizations) + +2006-02-28 19:08:12 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/gnomevfs/gstgnomevfssink.c: Fix some docs. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_class_init): + Fix some docs. + +2006-02-28 13:52:04 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/alsa/gstalsasrc.c: Set proper class on the ElementDetails: + Original commit message from CVS: + * ext/alsa/gstalsasrc.c: + Set proper class on the ElementDetails: + Source/Audio instead of Src/Audio + +2006-02-28 12:19:11 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/videoscale/vs_scanline.c: Revert optimization in videoscale. It should go in liboil and have an appropriate liboi... + Original commit message from CVS: + * gst/videoscale/vs_scanline.c: + (vs_scanline_resample_nearest_RGBA): + Revert optimization in videoscale. It should go in liboil and have + an appropriate liboil function. + +2006-02-28 11:06:24 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Don't try to provide a clock in the NULL state. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_provide_clock): + Don't try to provide a clock in the NULL state. + +2006-02-28 11:04:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/ogg/gstoggdemux.c: Use GstSegment infrastructure to remove duplicated code and handle more seek cases correctly. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_receive_event), + (gst_ogg_pad_event), (gst_ogg_pad_internal_chain), + (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), + (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_activate_chain), (gst_ogg_demux_do_seek), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_collect_info), + (gst_ogg_demux_find_chains), (gst_ogg_demux_chain), + (gst_ogg_demux_loop), (gst_ogg_demux_change_state): + Use GstSegment infrastructure to remove duplicated code + and handle more seek cases correctly. + +2006-02-28 10:39:19 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/ffmpegcolorspace/gstffmpegcolorspace.c: Don't ignore return code from ffmpeg convert function. + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_transform): + Don't ignore return code from ffmpeg convert function. + * gst/ffmpegcolorspace/imgconvert.c: (img_convert): + Split out some long statements to ease debugging. + +2006-02-27 12:08:22 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/libvisual/visual.c: Don't use gst_pad_use_fixed_caps, because it prevents downstream from being able to renegotia... + Original commit message from CVS: + * ext/libvisual/visual.c: (gst_visual_init), + (gst_vis_src_negotiate), (get_buffer), (plugin_init): + Don't use gst_pad_use_fixed_caps, because it prevents downstream from + being able to renegotiate the size. Instead, use the negotiation + algorithm from the goom plugin to pick an initial output caps. + Also, allow theoretical libvisual plugins that might support non-GL + output even if they also do GL. + +2006-02-26 21:05:46 +0000 Julien Moutte <julien@moutte.net> + + ext/libvisual/visual.c: Load only non GL plugins. Fix some memleaks and possible negotiation issues. + Original commit message from CVS: + 2006-02-26 Julien MOUTTE <julien@moutte.net> + * ext/libvisual/visual.c: (gst_visual_init), + (gst_visual_src_setcaps), (get_buffer), (gst_visual_chain), + (plugin_init): Load only non GL plugins. Fix some memleaks and + possible negotiation issues. + +2006-02-24 23:19:44 +0000 Julien Moutte <julien@moutte.net> + + gst-libs/gst/tag/tag.h: Adding Annodex tags here. + Original commit message from CVS: + 2006-02-25 Julien MOUTTE <julien@moutte.net> + * gst-libs/gst/tag/tag.h: Adding Annodex tags here. + +2006-02-24 18:55:27 +0000 Michael Smith <msmith@xiph.org> + + gst/typefind/gsttypefindfunctions.c: Fix CMML type find function to not require a specific minor version of the CMML ... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mpeg4_video_type_find), + (cmml_type_find), (plugin_init): + Fix CMML type find function to not require a specific minor version + of the CMML header. + Add an MPEG4 video elementary stream typefind function. + +2006-02-24 17:31:53 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggdemux.c: Annodex support in ogg demuxer. Doesn't do very much without the other annodex patches (to come). + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_parse_skeleton_fishead), + (gst_ogg_pad_parse_skeleton_fisbone), (gst_ogg_pad_query_convert), + (gst_ogg_demux_chain_peer), (gst_ogg_pad_submit_packet), + (gst_ogg_demux_perform_seek), (gst_ogg_demux_read_chain), + (gst_ogg_demux_read_end_chain), (gst_ogg_demux_collect_chain_info), + (gst_ogg_demux_change_state), (gst_annodex_granule_to_time): + Annodex support in ogg demuxer. Doesn't do very much without the + other annodex patches (to come). + +2006-02-24 16:21:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Pick up palette for MS video v1 (#327028, patch by: + Fabrizio Gennari <fabrizio dot get at tiscali dot it>) + +2006-02-24 13:54:04 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/ffmpegcolorspace/gstffmpegcolorspace.c: The 'palette_data' field from incoming RGB caps shouldn't be proxied on o... + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_caps_remove_format_info), + (gst_ffmpegcsp_get_unit_size): + The 'palette_data' field from incoming RGB caps shouldn't be + proxied on outgoing YUV caps; also, restrict unit size + adjustment in case of paletted data only to the unit that + actually has a palette. Fixes #330711. + +2006-02-24 12:18:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/ffmpegcolorspace/gstffmpegcolorspace.c: Plug some memory leaks. + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_transform_caps), (gst_ffmpegcsp_set_caps), + (gst_ffmpegcsp_finalize), (gst_ffmpegcsp_class_init), + (gst_ffmpegcsp_get_unit_size): + Plug some memory leaks. + +2006-02-24 10:18:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + sys/: Add some _CFLAGS and _LIBS that seem to be missing and/or required for Cygwin (see #317048). + Original commit message from CVS: + * sys/ximage/Makefile.am: + * sys/xvimage/Makefile.am: + Add some _CFLAGS and _LIBS that seem to be missing + and/or required for Cygwin (see #317048). + +2006-02-24 00:07:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + * ChangeLog: + ChangeLog surgery: use UTF-8 encoding in stead of ISO-8859-15 + Original commit message from CVS: + ChangeLog surgery: use UTF-8 encoding in stead of ISO-8859-15 + +2006-02-22 18:46:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasrc.c: Fix description as pointed out by caugier. + Original commit message from CVS: + * ext/alsa/gstalsasrc.c: + Fix description as pointed out by caugier. + +2006-02-22 10:29:22 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Better 3gp typefinding. + Original commit message from CVS: + Reviewed by : Edward Hervey <edward@fluendo.com> + * gst/typefind/gsttypefindfunctions.c: (q3gp_type_find), + (qt_type_find): + Better 3gp typefinding. + +2006-02-21 12:16:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Don't send EOS event here, the base class will send one for us. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_create): + Don't send EOS event here, the base class will send one for us. + * gst/playback/gstplaybasebin.c: (prepare_output): + Subpictures without video stream aren't allowed either. + * gst/subparse/gstsubparse.c: (gst_subparse_type_find): + Fix debug statement copy'n'paste-o. + +2006-02-21 12:05:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsamixer.c: Fix issues with mixer keeping state when muting/unmuting and when changing the volume whilst... + Original commit message from CVS: + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume): + Fix issues with mixer keeping state when muting/unmuting + and when changing the volume whilst muted (see #331763 + and #331765). + +2006-02-20 18:27:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Set right caps given that we send escaped text. Also, honour <i></i>, <b></b> and <u></u>... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (subrip_unescape_formatting), + (parse_subrip), (gst_sub_parse_format_autodetect): + Set right caps given that we send escaped text. Also, + honour <i></i>, <b></b> and <u></u> markers that can be found + in .srt files (fixes #310202). + +2006-02-20 16:21:14 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/mixerutils.c: Make order in which elements are tried more determinable. + Original commit message from CVS: + * gst-libs/gst/audio/mixerutils.c: + (element_factory_rank_compare_func): + Make order in which elements are tried more determinable. + +2006-02-20 15:57:51 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gstdecodebin.c: Make decodebin reusable by fixing remove_element_chain first and then introduce a cleane... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (get_our_ghost_pad), + (remove_element_chain), (cleanup_decodebin), + (gst_decode_bin_change_state): Make decodebin reusable by + fixing remove_element_chain first and then introduce a + cleaner in state change to ->NULL. (Closes #331678) + ------------------------------------------------------ + +2006-02-19 14:32:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/gnomevfs/gstgnomevfssink.c: use 0666 mask when creating files so umask gets applied correctly. Fixes #331295. + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_open_file): + use 0666 mask when creating files so umask gets applied + correctly. Fixes #331295. + +2006-02-19 14:16:16 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/: Add very basic parser for SSA subtitle streams (as often found in matroska files). + Original commit message from CVS: + * gst/subparse/Makefile.am: + * gst/subparse/gstssaparse.c: (gst_ssa_parse_base_init), + (gst_ssa_parse_dispose), (gst_ssa_parse_init), + (gst_ssa_parse_class_init), (gst_ssa_parse_src_event), + (gst_ssa_parse_sink_event), (gst_ssa_parse_setcaps), + (gst_ssa_parse_remove_override_codes), (gst_ssa_parse_parse_line), + (gst_ssa_parse_chain), (gst_ssa_parse_change_state): + * gst/subparse/gstssaparse.h: + * gst/subparse/gstsubparse.c: (plugin_init): + Add very basic parser for SSA subtitle streams (as often + found in matroska files). + +2006-02-19 14:09:40 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: That should be text/x-pango-markup, not text/x-pango-layout. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (mimetype_is_raw): + That should be text/x-pango-markup, not text/x-pango-layout. + +2006-02-19 12:41:03 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Polishing. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_finalize): + Polishing. + +2006-02-19 12:05:23 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Fix state change deadlock. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_base_init), + (gst_text_overlay_finalize), (gst_text_overlay_init), + (gst_text_overlay_setcaps), (gst_text_overlay_src_event), + (gst_text_overlay_render_text), + (gst_text_overlay_text_pad_link), + (gst_text_overlay_text_event), (gst_text_overlay_video_event), + (gst_text_overlay_pop_text), (gst_text_overlay_text_chain), + (gst_text_overlay_video_chain), (gst_text_overlay_change_state): + Fix state change deadlock. + +2006-02-19 11:56:28 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.*: Fix seeking both for muxed formats and subtitles files. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_base_init), + (gst_text_overlay_finalize), (gst_text_overlay_init), + (gst_text_overlay_setcaps), (gst_text_overlay_src_event), + (gst_text_overlay_render_text), + (gst_text_overlay_text_pad_link), + (gst_text_overlay_text_event), (gst_text_overlay_video_event), + (gst_text_overlay_pop_text), (gst_text_overlay_text_chain), + (gst_text_overlay_video_chain), (gst_text_overlay_change_state): + * ext/pango/gsttextoverlay.h: Fix seeking both for muxed formats + and subtitles files. + +2006-02-19 00:40:38 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gstdecodebin.c: pango layout should be considered as row. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE <julien@moutte.net> + * gst/playback/gstdecodebin.c: (mimetype_is_raw): pango layout + should be considered as row. + +2006-02-19 00:25:16 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gststreaminfo.*: Introduce language informations. + Original commit message from CVS: + 2006-02-19 Julien MOUTTE <julien@moutte.net> + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), + (cb_probe): + * gst/playback/gststreaminfo.h: Introduce language informations. + +2006-02-18 22:41:31 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: Set shared memory segments to be deleted as soon as we have attached, that way they get cleaned up automaticall... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_destroy): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimagesink_check_xshm_calls), (gst_xvimagesink_xvimage_new): + Set shared memory segments to be deleted as soon as we have attached, + that way they get cleaned up automatically if we crash. + +2006-02-18 19:53:48 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/: Those functions are called with lock held. + Original commit message from CVS: + 2006-02-18 Julien MOUTTE <julien@moutte.net> + * ext/pango/gstclockoverlay.c: (gst_clock_overlay_get_text): + * ext/pango/gsttimeoverlay.c: (gst_time_overlay_get_text): Those + functions are called with lock held. + +2006-02-18 19:51:47 +0000 Julien Moutte <julien@moutte.net> + + * ChangeLog: + Forgot Changelog. + Original commit message from CVS: + Forgot Changelog. + +2006-02-18 19:10:35 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Refactoring of textoverlay without collectpads. This now supports sparse subtitles coming... + Original commit message from CVS: + 2006-02-18 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_base_init), + (gst_text_overlay_finalize), (gst_text_overlay_init), + (gst_text_overlay_setcaps), (gst_text_overlay_src_event), + (gst_text_overlay_render_text), + (gst_text_overlay_text_pad_link), + (gst_text_overlay_text_pad_unlink), + (gst_text_overlay_text_event), + (gst_text_overlay_video_event), (gst_text_overlay_pop_text), + (gst_text_overlay_text_chain), (gst_text_overlay_video_chain), + (gst_text_overlay_change_state): Refactoring of textoverlay + without collectpads. This now supports sparse subtitles coming + from a demuxer instead of a sub file. Seeking is still broken + though. Need to discuss with wtay some more on how to handle + seeking correctly. + * ext/pango/gsttextoverlay.h: + * gst/playback/gstplaybin.c: (setup_sinks): Support linking with + subtitles coming from the demuxer. + +2006-02-17 19:31:12 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisenc.c: Use some more scaling functions. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_convert_src), + (gst_vorbisenc_convert_sink): + Use some more scaling functions. + +2006-02-17 16:12:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/cdparanoia/gstcdparanoiasrc.*: Add back 'transport-error' and 'uncorrected-error' signals and make them actually ... + Original commit message from CVS: + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_src_class_init), (gst_cd_paranoia_dummy_callback), + (gst_cd_paranoia_paranoia_callback), + (gst_cd_paranoia_src_signal_is_being_watched), + (gst_cd_paranoia_src_read_sector): + * ext/cdparanoia/gstcdparanoiasrc.h: + Add back 'transport-error' and 'uncorrected-error' signals and + make them actually be fired when bad stuff happens (#319340). + +2006-02-17 14:07:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Small cleanups. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_get_type), + (gst_ring_buffer_open_device), (gst_ring_buffer_close_device), + (gst_ring_buffer_device_is_open), (gst_ring_buffer_acquire), + (gst_ring_buffer_release), (gst_ring_buffer_set_flushing), + (gst_ring_buffer_start), (gst_ring_buffer_pause_unlocked), + (gst_ring_buffer_pause), (gst_ring_buffer_stop), + (gst_ring_buffer_delay), (gst_ring_buffer_samples_done), + (gst_ring_buffer_set_sample), (gst_ring_buffer_clear_all), + (gst_ring_buffer_commit), (gst_ring_buffer_prepare_read), + (gst_ring_buffer_clear): + Small cleanups. + Added some G_LIKELY. + +2006-02-17 10:15:52 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/TODO: Update TODO + Original commit message from CVS: + * gst-libs/gst/audio/TODO: + Update TODO + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_offset): + When trying to play samples ASAP and we don't have a + previous sample, try to play at position 0 instead of + an invalid position. + +2006-02-17 09:24:56 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.c: Also release lock when we get an error in _reset(); fix an error message. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_open), + (gst_alsasink_reset): + Also release lock when we get an error in _reset(); + fix an error message. + +2006-02-16 21:01:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/gstalsasink.*: Add support for more than 2 channels (#326720). + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_class_init), + (gst_alsasink_init), (get_channel_free_structure), + (caps_add_channel_configuration), (gst_alsasink_getcaps), + (gst_alsasink_close): + * ext/alsa/gstalsasink.h: + Add support for more than 2 channels (#326720). + +2006-02-16 20:19:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/riff/riff-media.c: Set codec_name for WAVEFORMATEX as well. When we have 'normal PCM' with 4 or 6 channe... + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Set codec_name for WAVEFORMATEX as well. When we have 'normal PCM' + with 4 or 6 channels, assume a default channel layout to make things + work (not sure there's anything else we can do in those cases). + +2006-02-16 19:18:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: Minor docs fix. + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + Minor docs fix. + * gst-libs/gst/riff/Makefile.am: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: + (gst_riff_wavext_add_channel_layout), (gst_riff_create_audio_caps): + Add support for WAVEFORMATEX, eg. PCM audio with more than two + channels and a channel layout map. + +2006-02-16 17:06:46 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/videoscale/vs_scanline.c: C-level optimization of the RGBA nearest neighbour function. + Original commit message from CVS: + Reviewed by Edward Hervey <edward@fluendo.com> + * gst/videoscale/vs_scanline.c: (vs_scanline_resample_nearest_RGBA): + C-level optimization of the RGBA nearest neighbour function. + Eventually this might end up in liboil with vectorized versions. + +2006-02-16 11:44:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/multichannel.c: When we have more than 2 channels, but no channel layout is specified in the caps,... + Original commit message from CVS: + * gst-libs/gst/audio/multichannel.c: + (gst_audio_get_channel_positions): + When we have more than 2 channels, but no channel layout is + specified in the caps, return some default channel layout + to the caller and warn about about a possibly buggy element + (could be buggy filtercaps as well of course) (#317038). + +2006-02-16 09:29:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: Add gst-libs/gst/cdda to list of lib search paths. + Original commit message from CVS: + * pkgconfig/gstreamer-plugins-base-uninstalled.pc.in: + Add gst-libs/gst/cdda to list of lib search paths. + +2006-02-15 12:20:47 +0000 Andy Wingo <wingo@pobox.com> + + ext/ogg/gstoggmux.c (gst_ogg_mux_collected): When updating timestamp, update timestamp_end as well. Fixes a bugaboo. ... + Original commit message from CVS: + 2006-02-15 Andy Wingo <wingo@pobox.com> + * ext/ogg/gstoggmux.c (gst_ogg_mux_collected): When updating + timestamp, update timestamp_end as well. Fixes a bugaboo. I hope + to the Lord Jesus that I do not have to touch the ogg muxer ever + again. + +2006-02-15 12:07:57 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: quicktime movie files can also contain 'uuid' atoms. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): + quicktime movie files can also contain 'uuid' atoms. + +2006-02-14 18:52:52 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/audioconvert/plugin.c: Register the GstAudioChannelPosition enum type with the type system in the plugin_init fun... + Original commit message from CVS: + * gst/audioconvert/plugin.c: (plugin_init): + Register the GstAudioChannelPosition enum type with the type + system in the plugin_init function, so that it is known before + any element actually makes use of multi-channel stuff. This is + required for example if one wants to be able to deserialise/use + a caps string with channel positions before any pipeline has + been setup and started, like with gst-launch. + +2006-02-14 13:45:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstringbuffer.c: Add some compiler G_(UN_)LIKELY help. + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: + (gst_ring_buffer_pause_unlocked), (gst_ring_buffer_delay), + (gst_ring_buffer_samples_done), (wait_segment), + (gst_ring_buffer_commit), (gst_ring_buffer_clear): + Add some compiler G_(UN_)LIKELY help. + SIGNAL the ringbuffer waiters when going to PAUSED as well to + make sure they can exit their functions. Should fix #330748 + +2006-02-13 20:49:07 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + Windows does not have long long; copy the generated _stdint.h + Original commit message from CVS: + * Makefile.am: + * configure.ac: + * win32/MANIFEST: + * win32/common/_stdint.h: + Windows does not have long long; copy the generated _stdint.h + * win32/common/interfaces-enumtypes.c: + (gst_color_balance_type_get_type), (gst_mixer_type_get_type), + (gst_mixer_track_flags_get_type), + (gst_tuner_channel_flags_get_type): + * win32/common/multichannel-enumtypes.c: + (gst_audio_channel_position_get_type): + update + +2006-02-13 18:49:02 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Always sync on first sample we receive when starting. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_time), (gst_base_audio_sink_preroll), + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + Always sync on first sample we receive when starting. + +2006-02-13 15:59:48 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/playback/gstplaybin.c: Update vis bin docs. + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_vis_element): + Update vis bin docs. + Move queue after tee so we don't queue video buffers but + audio samples instead. Fixes problems where the video queue + is filled and the audio queue empty. + +2006-02-13 15:17:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: No need to push an EOS event here, GstBaseSrc will do that for us when we return ... + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_create): + No need to push an EOS event here, GstBaseSrc will do that for us + when we return FLOW_UNEXPECTED. + +2006-02-12 14:54:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Use scale functions when possible. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_get_time), (gst_base_audio_sink_setcaps), + (gst_base_audio_sink_drain), (gst_base_audio_sink_preroll), + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + Use scale functions when possible. + Fix error messages. + Free clockid when after waiting for EOS. + Use G_(UN_)LIKLY when it makes sense. + Fix sample clipping bug found by Arwed v. Merkatz fixes #330789. + +2006-02-12 14:26:55 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstplaybasebin.c: Remove stray semi-colon (fixes #330888). + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (prepare_output): + Remove stray semi-colon (fixes #330888). + +2006-02-11 23:35:55 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + sys/: Fix up the XShm call testing so that we catch errors, and don't cause new ones by attempting to detach from a s... + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls): + Fix up the XShm call testing so that we catch errors, and don't + cause new ones by attempting to detach from a segment we failed + to attach to. Fixes #312439. + +2006-02-10 11:29:55 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/typefind/gsttypefindfunctions.c: Added flv file typefind (video/x-flv). + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Added flv file typefind (video/x-flv). + +2006-02-10 10:53:33 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Added FLV1 <==> 'video/x-flash-video,flvversion=1' conversion. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Added FLV1 <==> 'video/x-flash-video,flvversion=1' conversion. + Also added the caps to the default set of riff video caps. + +2006-02-09 19:05:23 +0000 Andy Wingo <wingo@pobox.com> + + ext/ogg/gstoggmux.c (GstOggPad): Keep track of both the start time and the end time of the last packet in the page. + Original commit message from CVS: + 2006-02-09 Andy Wingo <wingo@pobox.com> + * ext/ogg/gstoggmux.c (GstOggPad): Keep track of both the start + time and the end time of the last packet in the page. + (gst_ogg_mux_pad_queue_page): In addition to setting the timestamp + on the pages in our queue, set the duration as well. Reflow a + debug statement. + (gst_ogg_mux_collected): Keep track of GstOggPad->timestamp_end. + Fixes bad muxing order. + +2006-02-09 17:04:18 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst-libs/gst/rtp/gstbasertppayload.c: update seqnum before setting it on the packet; this makes sure that the timesta... + Original commit message from CVS: + * gst-libs/gst/rtp/gstbasertppayload.c: + (gst_basertppayload_setcaps), (gst_basertppayload_push): + update seqnum before setting it on the packet; this makes sure + that the timestamp and seqnum properties match after pushing + a buffer + +2006-02-09 12:16:35 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + changelog foo + Original commit message from CVS: + changelog foo + +2006-02-09 11:46:03 +0000 Andy Wingo <wingo@pobox.com> + + * gst-libs/gst/audio/gstringbuffer.c: + * win32/common/config.h: + kapowpowpow + Original commit message from CVS: + kapowpowpow + +2006-02-09 11:36:18 +0000 Andy Wingo <wingo@pobox.com> + + gst-libs/gst/audio/gstringbuffer.c + Original commit message from CVS: + 2006-02-09 Andy Wingo <wingo@pobox.com> + * gst-libs/gst/audio/gstringbuffer.c + (gst_ring_buffer_samples_done): Cast to guint64, fixes an integer + overflow after 13.5 hours of recording. Kapow! + * ext/alsa/gstalsasrc.c (gst_alsasrc_delay): Clamp the delay to + the buffer size -- we don't care about underrun/overrun reporting + right now, just need to return a useful value. + +2006-02-09 11:21:33 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Back to CVS + Original commit message from CVS: + * configure.ac: + Back to CVS + +=== release 0.10.3 === + +2006-02-09 11:18:22 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + * win32/common/config.h: + Releasing 0.10.3 + Original commit message from CVS: + Releasing 0.10.3 + +2006-02-08 18:37:38 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + configure.ac: Drat. Bump libtool version number for new API. + Original commit message from CVS: + * configure.ac: + Drat. Bump libtool version number for new API. + Prelease 0.10.2.3 (of 0.10.3) + +2006-02-08 15:57:53 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + 0.10.2.2 prerelease (of 0.10.3). + Original commit message from CVS: + * configure.ac: + * win32/common/config.h: + 0.10.2.2 prerelease (of 0.10.3). + +2006-02-08 15:50:08 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/tcp/gsttcpclientsrc.c: Revert Andy's newsegment change pending a more correct fix. + Original commit message from CVS: + * gst/tcp/gsttcpclientsrc.c: (gst_tcp_client_src_create): + Revert Andy's newsegment change pending a more correct + fix. + +2006-02-08 12:46:14 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + Update .po files + Original commit message from CVS: + Update .po files + +2006-02-08 11:04:09 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst/tcp/gstmultifdsink.c: + doc fixes + Original commit message from CVS: + doc fixes + +2006-02-08 09:20:23 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst/typefind/gsttypefindfunctions.c: detect more files as 3gp group and reorder the iso file formats + Original commit message from CVS: + : + * gst/typefind/gsttypefindfunctions.c: (q3gp_type_find), + (qt_type_find), (plugin_init): + detect more files as 3gp + group and reorder the iso file formats + +2006-02-07 18:32:00 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/vorbis/vorbis.c: Register musicbrainz tags, so apps don't have to. + Original commit message from CVS: + * ext/vorbis/vorbis.c: (plugin_init): + Register musicbrainz tags, so apps don't have to. + +2006-02-07 17:44:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Make sure we called gst_tag_register_musicbrainz_tags() before possibly mapping a vo... + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_tag_from_vorbis_tag), + (gst_tag_to_vorbis_tag): + Make sure we called gst_tag_register_musicbrainz_tags() + before possibly mapping a vorbiscomment string from/to a + musicbrainz tag. + +2006-02-07 16:16:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: In case we can't find the required number of consecutive mpeg audio frames to po... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find): + In case we can't find the required number of consecutive + mpeg audio frames to positively identify an MPEG audio + stream, check if there's at least a valid mpeg audio + frame right at offset 0 and if so suggest mpeg/audio + caps with a very low probability (#153004). + +2006-02-07 15:52:26 +0000 Andy Wingo <wingo@pobox.com> + + gst/tcp/gsttcpclientsrc.c (gst_tcp_client_src_create): Switch to a TIME segment if we get timestamped buffers. Requir... + Original commit message from CVS: + 2006-02-07 Andy Wingo <wingo@pobox.com> + * gst/tcp/gsttcpclientsrc.c (gst_tcp_client_src_create): Switch to + a TIME segment if we get timestamped buffers. Requires recent + fixes in core to work properly. + +2006-02-07 14:57:46 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Don't print the URI as part of the error message, it makes error dialogs look rather u... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (prepare_output): + Don't print the URI as part of the error message, it + makes error dialogs look rather ugly, especially if + the URI is very long or has characters in it that + need escaping. + +2006-02-07 13:11:31 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Error out if we have only text or subtitles, but nothing else. Also error out if we ha... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (prepare_output): + Error out if we have only text or subtitles, but nothing + else. Also error out if we have subtitles but no video + stream. + +2006-02-07 11:44:39 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssrc.c: Treat GNOME_VFS_RESULT_EOF as EOS, not as error (#329194). + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_create): + Treat GNOME_VFS_RESULT_EOF as EOS, not as error (#329194). + Post an error message on the bus when we encounter an + error, which will hopefully be more meaningful than the + 'Internal Flow Error' message users get to see if we + just return GST_FLOW_ERROR. + +2006-02-07 11:28:04 +0000 Andy Wingo <wingo@pobox.com> + + configure.ac (GST_MAJORMINOR): Update core version req to 0.10.2.2, for the collectpads API addition (#330244). + Original commit message from CVS: + 2006-02-07 Andy Wingo <wingo@pobox.com> + * configure.ac (GST_MAJORMINOR): Update core version req to + 0.10.2.2, for the collectpads API addition (#330244). + +2006-02-06 19:09:26 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfs.c: Return FALSE from plugin_init() when GnomeVFS can't be initialised for some reason (#3284... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + Return FALSE from plugin_init() when GnomeVFS can't + be initialised for some reason (#328423). + +2006-02-06 13:26:54 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Stick to seeking theory until i find the bug. + Original commit message from CVS: + 2006-02-06 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_src_event): + Stick to seeking theory until i find the bug. + * gst/subparse/gstsubparse.c: (parse_subrip): Fix debug. + +2006-02-06 12:38:48 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Make theoraenc and the tests leak free. Like, really. + Original commit message from CVS: + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_finalize), (theora_enc_sink_setcaps), + (theora_set_header_on_caps), (theora_enc_chain), + (theora_enc_change_state): + * tests/check/pipelines/theoraenc.c: (GST_START_TEST): + Make theoraenc and the tests leak free. Like, really. + +2006-02-05 23:31:05 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + Add a finalize method to ensure we clean up state even if someone omitted the state change back to NULL. + Original commit message from CVS: + (theora_enc_finalize), (theora_enc_sink_setcaps): + Add a finalize method to ensure we clean up state even if + someone omitted the state change back to NULL. + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_metadata_set1), + (gst_vorbisenc_chain): + Free some more leaked bits. + * tests/check/pipelines/theoraenc.c: (start_pipeline), + (stop_pipeline): + Wait for state changes to happen if they're ASYNC. + This ought to teach those fancy pants buildbots a lesson. + +2006-02-05 22:47:41 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/tag/gstid3tag.c: Add mapping for ID3 International Standard Recording Code tag "TSRC" + Original commit message from CVS: + * gst-libs/gst/tag/gstid3tag.c: + Add mapping for ID3 International Standard Recording Code + tag "TSRC" + +2006-02-05 22:44:55 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/vorbis/vorbisenc.c: Don't leak tag names. + Original commit message from CVS: + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_metadata_set1): + Don't leak tag names. + +2006-02-05 18:22:01 +0000 Tim-Philipp Müller <tim@centricular.net> + + Split libgsttag docs into multiple sections. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstid3tag.c: + * gst-libs/gst/tag/gstvorbistag.c: + * gst-libs/gst/tag/tags.c: + Split libgsttag docs into multiple sections. + +2006-02-05 18:01:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add libgsttag to the docs. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/tag/gstid3tag.c: (gst_tag_from_id3_tag): + * gst-libs/gst/tag/gstvorbistag.c: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + Add libgsttag to the docs. + +2006-02-05 17:21:23 +0000 Julien Moutte <julien@moutte.net> + + ext/pango/gsttextoverlay.c: Fix clockoverlay. + Original commit message from CVS: + 2006-02-05 Julien MOUTTE <julien@moutte.net> + * ext/pango/gsttextoverlay.c: (gst_text_overlay_finalize), + (gst_text_overlay_init), (gst_text_overlay_src_event), + (gst_text_overlay_collected): Fix clockoverlay. + +2006-02-05 17:15:17 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/libs/compiling.sgml: Fix typo: it's pkg-config, not pkg-gconfig + Original commit message from CVS: + * docs/libs/compiling.sgml: + Fix typo: it's pkg-config, not pkg-gconfig + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/tmpl/gstgconf.sgml: + There is no libgstgconf in 0.10, remove it + from the docs. + +2006-02-05 16:03:48 +0000 Julien Moutte <julien@moutte.net> + + docs/libs/tmpl/gstcolorbalance.sgml: Updated. + Original commit message from CVS: + 2006-02-05 Julien MOUTTE <julien@moutte.net> + * docs/libs/tmpl/gstcolorbalance.sgml: Updated. + * ext/pango/gsttextoverlay.c: (gst_text_overlay_init), + (gst_text_overlay_src_event), (gst_text_overlay_collected): + * gst/subparse/gstsubparse.c: (gst_sub_parse_dispose), + (gst_sub_parse_class_init), (gst_sub_parse_init), + (gst_sub_parse_src_event), (parse_mdvdsub), (parse_subrip), + (parse_mpsub), (parser_state_init), (handle_buffer), + (gst_sub_parse_chain), (gst_sub_parse_sink_event), + (plugin_init): + * gst/subparse/gstsubparse.h: Introduce seeking code. + +2006-02-05 15:14:06 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/gstvorbistag.c: Add comment about LANGUAGE tag inconsistency (we want + Original commit message from CVS: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + Add comment about LANGUAGE tag inconsistency (we want + ISO-639-1, but extract three-letter identifiers?) + * po/POTFILES.in: + Add two translatable files. + +2006-02-05 14:59:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/tag/: Forward-port some tags stuff from the 0.8 branch. This is mostly the addition of musicbrainz tags ... + Original commit message from CVS: + * gst-libs/gst/tag/Makefile.am: + * gst-libs/gst/tag/gstvorbistag.c: (gst_vorbis_tag_add): + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/tag/tags.c: + (gst_tag_register_musicbrainz_tags_internal), + (gst_tag_register_musicbrainz_tags): + Forward-port some tags stuff from the 0.8 branch. This is + mostly the addition of musicbrainz tags and their mapping + to vorbistags, and a vorbistag mapping of the language tag. + +2006-02-05 12:06:25 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gstplaybin.c: Fix broken code refactoring. + Original commit message from CVS: + 2006-02-05 Julien MOUTTE <julien@moutte.net> + * gst/playback/gstplaybin.c: (gen_text_element): Fix broken code + refactoring. + +2006-02-05 03:05:41 +0000 David Schleef <ds@schleef.org> + + Add Dirac typefinding and add dirac format to oggmux. + Original commit message from CVS: + * ext/ogg/gstoggmux.c: + * gst/typefind/gsttypefindfunctions.c: + Add Dirac typefinding and add dirac format to oggmux. + +2006-02-04 07:49:03 +0000 Michael Smith <msmith@xiph.org> + + * configure.ac: + Improve error message for liboil missingness. + Original commit message from CVS: + Improve error message for liboil missingness. + +2006-02-03 19:23:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: Don't put essential function call into g_return_*() macro, otherwise it'll all be replac... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (try_to_link_1): + Don't put essential function call into + g_return_*() macro, otherwise it'll all be + replaced by NOOPs when compiling with + G_DISABLE_CHECKS defined. + +2006-02-03 17:45:44 +0000 Edgard Lima <edgard.lima@indt.org.br> + + * ChangeLog: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggparse.c: + * gst/tcp/gsttcpserversink.c: + * sys/v4l/v4lsrc_calls.c: + * sys/v4l/v4lsrc_calls.h: + Just make it compile with --disable-gst-debug. + Original commit message from CVS: + Just make it compile with --disable-gst-debug. + +2006-02-03 12:51:47 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/alsa/gstalsasink.*: Add lock to protect alsa calls. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_finalise), + (gst_alsasink_class_init), (gst_alsasink_init), + (gst_alsasink_write), (gst_alsasink_reset): + * ext/alsa/gstalsasink.h: + Add lock to protect alsa calls. + Implement reset to flush samples ASAP, does not work + with dmix though. + +2006-02-02 18:18:31 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Ugh.. getting late I guess... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_provide_clock): + Ugh.. getting late I guess... + +2006-02-02 18:13:26 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Don't try to provide a clock when we are not negotiated since we might not be ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_provide_clock), + (gst_base_audio_sink_set_property), + (gst_base_audio_sink_get_property), (gst_base_audio_sink_render): + Don't try to provide a clock when we are not negotiated since + we might not be able to make it run. + +2006-02-02 17:51:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstdecodebin.c: Unlinking two source pads is ... hard. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (try_to_link_1): + Unlinking two source pads is ... hard. + +2006-02-02 12:14:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/TODO: Updated. + Original commit message from CVS: + * gst-libs/gst/audio/TODO: + Updated. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_drain), (gst_base_audio_sink_event): + On EOS, wait till the last sample is played before posting EOS. + +2006-02-02 08:53:27 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * tests/check/pipelines/theoraenc.c: + comment on my understanding + Original commit message from CVS: + comment on my understanding + +2006-02-02 08:47:42 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * common: + * tests/check/pipelines/theoraenc.c: + reformat to fit 80 chars + Original commit message from CVS: + reformat to fit 80 chars + +2006-02-02 00:04:37 +0000 Kai Vehmanen <kv2004@eca.cx> + + gst-libs/gst/rtp/gstbasertpdepayload.c: setting queue_delay to zero. Also avoid thread being started if queue_delay i... + Original commit message from CVS: + 2006-02-01 Philippe Kalaf <burger at speedy dot org> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + Patch by Kai Vehmanen : Adds ability to enable newsegment bypass by + setting queue_delay to zero. Also avoid thread being started if + queue_delay is zero. + +2006-02-01 14:51:29 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/test6.c: Make test work again by connecting fakesinks to each decoded pad, which makes the pipeline wait... + Original commit message from CVS: + * gst/playback/test6.c: (new_decoded_pad_cb), (show_error), (main): + Make test work again by connecting fakesinks to each decoded pad, + which makes the pipeline wait until each fakesink has a buffer + queued before going to PAUSED state. At that point we know the + decodebin pads are negotiated. + +2006-02-01 11:59:47 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/: Pass unhandled queries to the parent class's query function. + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: (gst_cdda_base_src_query), + (gst_cdda_base_src_handle_event): + * gst/audiotestsrc/gstaudiotestsrc.c: (gst_audio_test_src_query): + Pass unhandled queries to the parent class's query function. + +2006-02-01 11:56:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + Pass unhandled queries upstream instead of just dropping them (#326447). Also, fix supported query types list for som... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_query_types), + (gst_ogg_pad_src_query): + * ext/ogg/gstogmparse.c: (gst_ogm_parse_sink_query): + * ext/theora/theoradec.c: (theora_dec_src_query), + (theora_dec_sink_query): + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query), + (vorbis_dec_sink_query): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_src_query), + (gst_vorbisenc_sink_query): + * gst/adder/gstadder.c: (gst_adder_query): + Pass unhandled queries upstream instead of just + dropping them (#326447). Also, fix supported + query types list for some elements. + +2006-02-01 09:58:15 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Fix typefinding for audio/x-au, audio/x-paris and audio/iLBC-sh. We cannot use t... + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (au_type_find), + (paris_type_find), (ilbc_type_find), (plugin_init): + Fix typefinding for audio/x-au, audio/x-paris and + audio/iLBC-sh. We cannot use the START_WITH macros + here, because there can only be one typefind factory + with the same name (caps), so the second one would + replace the first one and the first one would never + be called when doing typefinding (see #161712). + +2006-01-31 19:25:10 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/vorbis/vorbisdec.c: Use scale_int when we can, add some more scaling. + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_convert), + (vorbis_handle_header_packet), (vorbis_dec_push), + (vorbis_handle_data_packet): + Use scale_int when we can, add some more scaling. + Check packettype before parsing it. + +2006-01-31 17:44:35 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Call right _scale functions. + Original commit message from CVS: + * ext/theora/theoradec.c: (_theora_granule_time), + (theora_dec_src_convert), (theora_dec_sink_convert): + Call right _scale functions. + Use parameter instead of some other random value. + +2006-01-31 17:27:00 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/theora/theoradec.c: Use higher precision timestamps calculation. + Original commit message from CVS: + * ext/theora/theoradec.c: (_theora_granule_frame), + (_theora_granule_time), (_inc_granulepos), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_handle_type_packet), (theora_handle_data_packet), + (theora_dec_chain): + Use higher precision timestamps calculation. + Convert some other conversions to _scale. + +2006-01-31 17:19:09 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/: initialize gst_controller before using + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_create_sine_table), (plugin_init): + * gst/volume/gstvolume.c: (plugin_init): + initialize gst_controller before using + +2006-01-31 16:26:57 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + tests/check/pipelines/: Define constant using G_GINT64_CONSTANT to avoid errors when passing it around - otherwise it... + Original commit message from CVS: + * tests/check/pipelines/theoraenc.c: + * tests/check/pipelines/vorbisenc.c: + Define constant using G_GINT64_CONSTANT to avoid errors when + passing it around - otherwise it gets truncated to 32 bits. + Fixes failing tests. + +2006-01-31 15:36:13 +0000 Andy Wingo <wingo@pobox.com> + + sys/v4l/gstv4lsrc.c (gst_v4lsrc_set_caps): Don't segfault if the caps being set doesn't have a framerate value. Basic... + Original commit message from CVS: + 2006-01-31 Andy Wingo <wingo@pobox.com> + * sys/v4l/gstv4lsrc.c (gst_v4lsrc_set_caps): Don't segfault if the + caps being set doesn't have a framerate value. Basically a stopgap + measure. + * ext/ogg/gstoggmux.c (GST_BUFFER_END_TIME): New macro. Not + technically correct enough to put into core though. + (gst_ogg_mux_dequeue_page): Use END_TIME instead of TIMESTAMP + + DURATION. Fixes theoraenc ! oggmux. + * sys/v4l/gstv4lsrc.c (gst_v4lsrc_fixate): Fixate to the nearest + fraction, not double. + +2006-01-31 12:23:35 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update with latest files + Original commit message from CVS: + update with latest files + +2006-01-30 23:42:54 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/vs7: add vs7 project files created by Sergey Scobich + Original commit message from CVS: + * win32/vs7: + add vs7 project files created by Sergey Scobich + +2006-01-30 22:18:53 +0000 Sébastien Moutte <sebastien@moutte.net> + + win32/vs8: add vs8 project files created by Sergey Scobich + Original commit message from CVS: + * win32/vs8: + add vs8 project files created by Sergey Scobich + +2006-01-30 19:22:22 +0000 Andy Wingo <wingo@pobox.com> + + ext/ogg/gstoggmux.c (gst_ogg_mux_dequeue_page): Compare timestamp + duration, not just timestamp -- ogg pages should ... + Original commit message from CVS: + 2006-01-30 Andy Wingo <wingo@pobox.com> + * ext/ogg/gstoggmux.c (gst_ogg_mux_dequeue_page): Compare + timestamp + duration, not just timestamp -- ogg pages should be + ordered by stop time. Necessary fix given the change in vorbis + timestamps. + +2006-01-30 19:21:07 +0000 Andy Wingo <wingo@pobox.com> + + * ChangeLog: + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: + * tests/check/pipelines/theoraenc.c: + ext/theora/theoraenc.c (theora_enc_sink_setcaps) + Original commit message from CVS: + 2006-01-30 Andy Wingo <wingo@pobox.com> + * ext/theora/theoraenc.c (theora_enc_sink_setcaps) + (gst_theora_enc_init): Pull the granule shift out of the encoder. + (granulepos_add): New function, handles the messiness of adjusting + granulepos values. + (theora_buffer_from_packet): + (theora_enc_chain): + (theora_enc_sink_event): Use granulepos_add, not +. + * tests/check/pipelines/theoraenc.c + (check_buffer_granulepos_from_starttime): Just check the frame + count, not the actual granulepos -- we can't dictate to the + encoder when it should be placing keyframes. + +2006-01-30 18:17:19 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/gnomevfs/gstgnomevfssrc.c: SERVICE_NOT_AVAILABLE happens for example when you're trying to play an http:// stream... + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_start): + SERVICE_NOT_AVAILABLE happens for example when you're trying to + play an http:// stream from a server that's not serving + +2006-01-30 17:08:11 +0000 Andy Wingo <wingo@pobox.com> + + tests/check/pipelines/: Totally remove the UINT64_CONSTANT macro, doesn't appear to be needed or available. + Original commit message from CVS: + 2006-01-30 Andy Wingo <wingo@pobox.com> + * tests/check/pipelines/vorbisenc.c (TIMESTAMP_OFFSET): + * tests/check/pipelines/theoraenc.c (TIMESTAMP_OFFSET): Totally + remove the UINT64_CONSTANT macro, doesn't appear to be needed or + available. + +2006-01-30 17:01:54 +0000 Andy Wingo <wingo@pobox.com> + + ext/theora/: Same changes as were done to vorbisenc, although theoraenc was timestamping correctly. Added handling of... + Original commit message from CVS: + 2006-01-30 Andy Wingo <wingo@pobox.com> + * ext/theora/gsttheoraenc.h: + * ext/theora/theoraenc.c: Same changes as were done to vorbisenc, + although theoraenc was timestamping correctly. Added handling of + streams that start with nonzero timestamps. + * tests/check/Makefile.am: + * tests/check/pipelines/theoraenc.c: New file, basically does same + tests as vorbisenc. + * tests/check/pipelines/vorbisenc.c: I claim these bugs. + +2006-01-30 16:19:33 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstaudiosink.c: Implement pause that does not wait for completion. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosink.c: + (gst_audioringbuffer_class_init), (gst_audioringbuffer_release), + (gst_audioringbuffer_pause): + Implement pause that does not wait for completion. + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + Don't drop buffers when going to PAUSED but perform preroll on + remaining samples now that core base class supports this. + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_release), + (gst_ring_buffer_pause_unlocked), (gst_ring_buffer_stop), + (gst_ring_buffer_commit): + Pause should not signal waiters. + Implement return value of _commit correctly. + +2006-01-30 15:01:28 +0000 Andy Wingo <wingo@pobox.com> + + tests/check/Makefile.am (check_vorbis): Add pipelines/vorbisenc. + Original commit message from CVS: + 2006-01-30 Andy Wingo <wingo@pobox.com> + * tests/check/Makefile.am (check_vorbis): Add pipelines/vorbisenc. + * ext/vorbis/vorbisenc.c (gst_vorbisenc_buffer_from_packet): Logic + updated to timestamp from the first sample, not the last. + (gst_vorbisenc_buffer_from_header_packet): New function, takes + special care of granulepos and timestamp for header packets. + (gst_vorbisenc_chain): Reflow, fix some leaks, and handle the case + when the first buffer has a nonzero timestamp. + * ext/vorbis/vorbisenc.h (GstVorbisEnc.granulepos_offset) + (GstVorbisEnc.subgranule_offset): New members. Take care of the + case when the first audio buffer we get has a nonzero timestamp. + (GstVorbisEnc.next_ts): Renamed from prev_ts, because now we + properly timestamp vorbis buffers with the time of the first + sample, not the last. + * ext/vorbis/vorbisenc.c (granulepos_to_clocktime): Renamed from + vorbis_granule_time_copy -- now it takes the granule/subgranule + offset into account. + * tests/check/pipelines/vorbisenc.c: New test for correctness of + timestamps, durations, and granulepos on buffers produced by + vorbisenc. + +2006-01-30 14:42:28 +0000 Eric Jonas <jonas@mit.edu> + + gst/ffmpegcolorspace/gstffmpegcodecmap.c: Patch from Eric Jonas to support conversions to/from UYVY (Fixes: #324626) + Original commit message from CVS: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt): + Patch from Eric Jonas to support conversions to/from UYVY + (Fixes: #324626) + +2006-01-30 08:11:14 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/: Implement subtitles. + Original commit message from CVS: + 2006-01-30 Julien MOUTTE <julien@moutte.net> + * gst/playback/gstplaybasebin.c: (group_commit), + (queue_overrun), + (setup_subtitle), (setup_source), (set_active_source): + * gst/playback/gstplaybin.c: (gst_play_bin_dispose), + (gen_text_element), (gen_audio_element), (gen_vis_element), + (remove_sinks), (add_sink), (setup_sinks): Implement subtitles. + +2006-01-29 19:13:39 +0000 Sébastien Moutte <sebastien@moutte.net> + + gst-libs/gst/audio/audio.h: (GST_CLOCK_TIME_TO_FRAMES) + Original commit message from CVS: + * gst-libs/gst/audio/audio.h: (GST_CLOCK_TIME_TO_FRAMES) + * gst-libs/gst/audio/gstbaseaudiosink.c: (gst_base_audio_sink_render) + use of gst_guint64_to_gdouble to be compliant with vs6 + * gst/playback/gstdecodebin.c: (try_to_link_1) + * gst/videorate/videorate.c: (gst_video_rate_blank_data) + use of G_GINT64_CONSTANT for int64 constants + * win32/common/libgstinterfaces.def: + export some symbols (gst_mixer_get_type,gst_mixer_track_get_type) + * win32/vs6: + update and add new project files + +2006-01-29 18:21:12 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + add a win32-update rule like in core, and copy over enumtypes files + Original commit message from CVS: + * Makefile.am: + * win32/MANIFEST: + * win32/common/interfaces-enumtypes.c: + (gst_color_balance_type_get_type), (gst_mixer_type_get_type), + (gst_mixer_track_flags_get_type), + (gst_tuner_channel_flags_get_type): + * win32/common/interfaces-enumtypes.h: + * win32/common/multichannel-enumtypes.c: + (gst_audio_channel_position_get_type): + * win32/common/multichannel-enumtypes.h: + add a win32-update rule like in core, and copy over enumtypes files + +2006-01-29 18:07:51 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + generate win32/common/config.h + Original commit message from CVS: + generate win32/common/config.h + +2006-01-29 18:05:42 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + win32/: add config files just like in core + Original commit message from CVS: + * win32/MANIFEST: + * win32/common/config.h: + * win32/common/config.h.in: + add config files just like in core + +2006-01-28 18:22:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/alsa/: Update all error messages. All of them should either use the default translated message, or actually prov... + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_init), (set_hwparams), + (set_swparams), (gst_alsasink_prepare), (gst_alsasink_unprepare), + (gst_alsasink_close), (gst_alsasink_write), (gst_alsasink_reset): + * ext/alsa/gstalsasrc.c: (gst_alsasrc_init), (set_hwparams), + (set_swparams), (gst_alsasrc_open), (gst_alsasrc_prepare), + (gst_alsasrc_unprepare), (gst_alsasrc_read): + Update all error messages. All of them should either use + the default translated message, or actually provide a + translatable string. + Make the string for channel count problems meaningful. + +2006-01-28 18:19:18 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstringbuffer.c: Make gcc-4.1 happy (part of #327357). + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (build_linear_format): + Make gcc-4.1 happy (part of #327357). + +2006-01-28 16:35:47 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + sys/v4l/v4l_calls.c: check for and throw RESOURCE_BUSY + Original commit message from CVS: + * sys/v4l/v4l_calls.c: (gst_v4l_open): + check for and throw RESOURCE_BUSY + +2006-01-28 02:13:14 +0000 David Schleef <ds@schleef.org> + + gst/videoscale/vs_scanline.c: Oops, *that's* why I never checked in this change -- it requires liboil features not in... + Original commit message from CVS: + * gst/videoscale/vs_scanline.c: Oops, *that's* why I never + checked in this change -- it requires liboil features not + in 0.3.6. Revert parts. + +2006-01-27 23:40:19 +0000 David Schleef <ds@schleef.org> + + update liboil requirement to 0.3.6 + Original commit message from CVS: + * REQUIREMENTS: + * configure.ac: update liboil requirement to 0.3.6 + * gst/videoscale/Makefile.am: + * gst/videoscale/vs_scanline.c: liboilify + +2006-01-27 17:00:09 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/libvisual/visual.c: When pad_alloc returns a GstFlowReturn other than GST_FLOW_OK, make sure it is passed upstream. + Original commit message from CVS: + * ext/libvisual/visual.c: (get_buffer): + When pad_alloc returns a GstFlowReturn other + than GST_FLOW_OK, make sure it is passed upstream. + +2006-01-27 01:36:01 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/alsa/gstalsasink.c: Free the device name string. + Original commit message from CVS: + * ext/alsa/gstalsasink.c: (gst_alsasink_finalise), + (gst_alsasink_class_init): + Free the device name string. + * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init), + (gst_ogg_mux_request_new_pad), (gst_ogg_mux_release_pad), + (gst_ogg_mux_handle_src_event), (gst_ogg_mux_clear_collectpads): + Don't remove a pad from the collectpads structure until it + is released - it's a request pad, and may receive data again + if the element gets moved back to PLAYING state. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + Ensure we turn on double buffering on the Xv port, and + set the colour key to something dark and mysterious that + isn't black. + +2006-01-27 01:06:29 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/: - a library should not call setlocale. see Libraries node in gettext manual + Original commit message from CVS: + * ext/alsa/gstalsaplugin.c: (plugin_init): + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_src_base_init), (plugin_init): + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_plugin_init): + - a library should not call setlocale. see Libraries node in + gettext manual + - make sure all plugins that use translation do bindtextdomain + to point to the localedir + * gst/playback/gstplaybin.c: (gen_vis_element), (add_sink), + (setup_sinks), (plugin_init): + all this, and check for NULL when creating sinks + +2006-01-26 23:21:31 +0000 Julien Moutte <julien@moutte.net> + + gst/subparse/gstsubparse.c: Make typefinding of subtitles work again. + Original commit message from CVS: + 2006-01-27 Julien MOUTTE <julien@moutte.net> + * gst/subparse/gstsubparse.c: (gst_subparse_type_find), + (plugin_init): Make typefinding of subtitles work again. + +2006-01-26 20:40:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/typefind/gsttypefindfunctions.c: Backport a bunch of typefinding fixes from the 0.8 branch. + Original commit message from CVS: + * gst/typefind/gsttypefindfunctions.c: (aac_type_find), + (mp3_type_frame_length_from_header), (mp3_type_find), + (wavpack_type_find), (m4a_type_find), (ircam_type_find), + (plugin_init): + Backport a bunch of typefinding fixes from the 0.8 branch. + Also, improve wavpack typefinding: if we can't peek the + entire wavpack block, try to parse the bits we can get and + see if we find what we're looking for in those. + +2006-01-26 19:17:38 +0000 Julien Moutte <julien@moutte.net> + + sys/: Handle some more cases of pixel aspect ratio. + Original commit message from CVS: + 2006-01-26 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: + (gst_ximagesink_calculate_pixel_aspect_ratio): + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio): Handle some + more cases of pixel aspect ratio. + +2006-01-26 13:09:24 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin.c: Also consider the flush-start and tag events as unblockers for the pad probes. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (pad_probe): + Also consider the flush-start and tag events as unblockers + for the pad probes. + +2006-01-26 12:32:58 +0000 Julien Moutte <julien@moutte.net> + + gst/playback/gstplaybin.c: On the fly visualisation switch, works disabling, enabling as well but it won't be able to... + Original commit message from CVS: + 2006-01-26 Julien MOUTTE <julien@moutte.net> + * gst/playback/gstplaybin.c: (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_vis_unblocked), + (gst_play_bin_vis_blocked), (gst_play_bin_set_property): + On the fly visualisation switch, works disabling, enabling as + well but it won't be able to enable vis in a playbin that was + created with no visualisation. + +2006-01-25 10:50:32 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Undo previous commit, it breaks resume after pause. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render), (gst_base_audio_sink_change_state): + Undo previous commit, it breaks resume after pause. + +2006-01-25 09:27:01 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Improve debugging. + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_setcaps), (gst_base_audio_sink_event), + (gst_base_audio_sink_preroll), (gst_base_audio_sink_render): + Improve debugging. + Post error when caps cannot be parsed. + Resync on discontinuity in the stream. + Clip samples to segment boundaries. + return WRONG_STATE sooner when we are flushing. + * gst-libs/gst/audio/gstbaseaudiosrc.c: (gst_base_audio_src_init), + (gst_base_audio_src_get_time), (gst_base_audio_src_create): + Make audiosrc operate in TIME. + Set TIMESTAMP and DURATION on buffers. + +2006-01-24 21:55:21 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/examples/seek/seek.c: Output tag messages as well. + Original commit message from CVS: + * tests/examples/seek/seek.c: (main): + Output tag messages as well. + +2006-01-23 15:05:24 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/playback/gstdecodebin.c: Replace GstPadBlockCallback with pad probes that detect first buffer AND eos before remo... + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (free_pad_probes), (remove_fakesink), (pad_probe), + (close_pad_link), (gst_decode_bin_change_state): + Replace GstPadBlockCallback with pad probes that detect + first buffer AND eos before removing fakesink. + Fixes hang with demuxers doing EOS while pre-rolling. + Solves #328279 + +2006-01-23 10:10:36 +0000 Jens Granseuer <jensgr@gmx.net> + + GCC 2.95 fixes (#328263). + Original commit message from CVS: + 2006-01-23 Andy Wingo <wingo@pobox.com> + * ext/alsa/gstalsasink.c: + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_setcaps), + (gst_base_rtp_depayload_add_to_queue), + (gst_base_rtp_depayload_queue_release): GCC 2.95 fixes (#328263). + Patch by: Jens Granseuer <jensgr at gmx dot net> + +2006-01-22 17:24:02 +0000 Julien Moutte <julien@moutte.net> + + sys/: Playbin keeps some ref to some frames. We might get a frame destroyed after changing state to + Original commit message from CVS: + 2006-01-22 Julien MOUTTE <julien@moutte.net> + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_destroy): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_destroy), + (gst_xvimagesink_buffer_alloc): Playbin keeps some ref to some + frames. We might get a frame destroyed after changing state to + NULL, adding a safety check on xcontext. + +2006-01-22 14:50:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/interfaces/xoverlay.c: Fix prepare-xwindow-id code example in the docs - we need to ignore all messages ... + Original commit message from CVS: + * gst-libs/gst/interfaces/xoverlay.c: + Fix prepare-xwindow-id code example in the docs - we need to + ignore all messages that aren't element messages as well. + +2006-01-21 22:40:03 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.c: I think one day i'll completely undestand how caps negotiation is supposed to work. This r... + Original commit message from CVS: + 2006-01-21 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_buffer_alloc): + I think one day i'll completely undestand how caps negotiation + is supposed to work. This refactoring handles buffer_alloc + called with caps we can't handle. We definitely don't want a + set_caps with those caps, so we define and allocate a buffer + we would like to receive. + +2006-01-20 19:10:26 +0000 Christian Schaller <uraeus@gnome.org> + + * autogen.sh: + * common: + up automake requirement to 1.7 + Original commit message from CVS: + up automake requirement to 1.7 + +2006-01-19 10:59:51 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Free iterator when done. + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source): + Free iterator when done. + +2006-01-17 11:43:49 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst-libs/gst/audio/gstbaseaudiosink.c: Fix playback of non-synchronised streams by assuming a rate of 1.0 instead of ... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_render): + Fix playback of non-synchronised streams by assuming a rate + of 1.0 instead of a random one. + Makes this work again: + gst-launch filesrc location=raw_audio.file ! 'audio/x-raw-int, + endianness=(int)4321, signed=(boolean)true, width=(int)16, + depth=(int)16, rate=(int)44100, channels=(int)2' ! audioconvert ! + audioresample ! alsasink + +2006-01-16 21:01:29 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.2 === + +2006-01-16 20:59:32 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-cdparanoia.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + releasing 0.10.2 + Original commit message from CVS: + releasing 0.10.2 + +2006-01-16 16:38:15 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/: Comment out broken code that connects to the state-changed signal. + Original commit message from CVS: + * gst/playback/gststreaminfo.c: (gst_stream_info_set_mute): + * gst/playback/gststreamselector.c: + (gst_stream_selector_set_property): + Comment out broken code that connects to the state-changed signal. + At this point, changing current stream selection is broken, but + stuff like gst-launch playbin current-audio=1 works and filters + to the chosen stream. + +2006-01-16 15:31:14 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/vorbis/vorbisdec.c: Fix #327216 (null dereference in vorbisdec) + Original commit message from CVS: + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query): + Fix #327216 (null dereference in vorbisdec) + +2006-01-16 15:19:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/theora/theoradec.c: Post taglist actually on bus instead of just freeing it (fixes #327114 and totem bug #327080). + Original commit message from CVS: + * ext/theora/theoradec.c: (theora_handle_comment_packet): + Post taglist actually on bus instead of just freeing it + (fixes #327114 and totem bug #327080). + * ext/vorbis/vorbisdec.c: (vorbis_handle_comment_packet): + Use gst_element_found_tags_for_pad(), so that the tags + are sent downstream as an event as well. + +2006-01-15 10:06:40 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + sys/: move all regularly occurring messages to GST_LOG level add some more object logs + Original commit message from CVS: + * sys/ximage/ximagesink.c: (gst_ximage_buffer_finalize), + (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_put), + (gst_ximagesink_buffer_alloc): + * sys/xvimage/xvimagesink.c: (gst_xvimage_buffer_finalize), + (gst_xvimagesink_xvimage_put), (gst_xvimagesink_show_frame), + (gst_xvimagesink_buffer_alloc): + move all regularly occurring messages to GST_LOG level + add some more object logs + +2006-01-14 22:59:49 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + prerelease + Original commit message from CVS: + prerelease + +2006-01-14 20:46:25 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + ext/ogg/gstoggmux.c: fix a silly segfault + Original commit message from CVS: + 2006-01-14 Thomas Vander Stichele <thomas at apestaart dot org> + * ext/ogg/gstoggmux.c: (gst_ogg_mux_collected): + fix a silly segfault + +2006-01-14 12:52:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add docs for mixerutils stuff. + Original commit message from CVS: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * gst-libs/gst/audio/mixerutils.c: + * gst-libs/gst/audio/mixerutils.h: + Add docs for mixerutils stuff. + +2006-01-13 17:17:07 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/gstplaybasebin.c: Fix playback for sources that emit raw audio or raw video streams (e.g.: cd audio sour... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (setup_source): + Fix playback for sources that emit raw audio or + raw video streams (e.g.: cd audio sources) (#325984). + +2006-01-13 16:45:50 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst-libs/gst/audio/mixerutils.c: actually save the element we create + Original commit message from CVS: + * gst-libs/gst/audio/mixerutils.c: + (gst_audio_mixer_filter_do_filter): + actually save the element we create + +2006-01-13 16:17:50 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + remove version suffix + Original commit message from CVS: + remove version suffix + +2006-01-12 14:56:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: No need to post a tag message on the bus when seeking within the same track, only... + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_handle_track_seek): + No need to post a tag message on the bus when seeking + within the same track, only post it when the current + track changes. + +2006-01-11 18:30:25 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/: Reenable stream selection. These mechanisms need a complete overhaul in the face of 0.8->0.10 changes ... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (group_destroy), + (probe_triggered), (new_decoded_pad), (mute_group_type), + (set_active_source): + * gst/playback/gststreaminfo.c: (gst_stream_info_set_mute): + * gst/playback/gststreamselector.c: + (gst_stream_selector_base_init), + (gst_stream_selector_set_property), + (gst_stream_selector_request_new_pad): + Reenable stream selection. These mechanisms need a complete overhaul + in the face of 0.8->0.10 changes though. + +2006-01-11 18:03:24 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/ogg/gstoggdemux.c: Change the pad template to src_%d to match the pads that are created from it. decodebin needs ... + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: + Change the pad template to src_%d to match the pads that + are created from it. decodebin needs this information in order + to decide that oggdemux is capable of producing multiple pads + (and hence needs queues inserted). + * ext/ogg/gstoggmux.c: (gst_ogg_mux_queue_pads), + (gst_ogg_mux_collected): + Make debug output more useful by using GST_PTR_FORMAT. + +2006-01-11 17:38:35 +0000 Christian Schaller <uraeus@gnome.org> + + * gst-plugins-base.spec.in: + update spec.in file + Original commit message from CVS: + update spec.in file + +2006-01-11 15:11:20 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstringbuffer.c: Set depth and width for alaw/mulaw (fixes #326601). + Original commit message from CVS: + Reviewed by: Tim-Philipp Müller <tim at centricular dot net> + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_parse_caps): + Set depth and width for alaw/mulaw (fixes #326601). + +2006-01-10 23:58:36 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + tests/icles/Makefile.am: don't build the tests if we don't have the libs + Original commit message from CVS: + * tests/icles/Makefile.am: + don't build the tests if we don't have the libs + +2006-01-10 18:06:56 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/cdparanoia/gstcdparanoiasrc.c: Don't try to free NULL pointers. + Original commit message from CVS: + * ext/cdparanoia/gstcdparanoiasrc.c: (gst_cd_paranoia_src_close), + (gst_cd_paranoia_paranoia_callback): + Don't try to free NULL pointers. + +2006-01-10 15:47:48 +0000 Edward Hervey <bilboed@bilboed.com> + + gst/audiorate/gstaudiorate.c: Add debugging category. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_chain), + (gst_audio_rate_change_state), (plugin_init): + Add debugging category. + Fix type issues. + Add case for incoming buffers without valid offset/offset_end. + +2006-01-10 12:25:59 +0000 Michael Smith <msmith@xiph.org> + + gst-libs/gst/audio/gstaudiosrc.c: Don't leak GCond in audio sources. + Original commit message from CVS: + * gst-libs/gst/audio/gstaudiosrc.c: (gst_audioringbuffer_dispose): + Don't leak GCond in audio sources. + +2006-01-10 11:49:28 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + gst/playback/gstplaybin.c: Don't leak an autoaudiosink/alsasink when we generate a new audio element. (old code, I gu... + Original commit message from CVS: + * gst/playback/gstplaybin.c: (gen_audio_element): + Don't leak an autoaudiosink/alsasink when we generate + a new audio element. (old code, I guess) + +2006-01-10 11:04:21 +0000 Michael Smith <msmith@xiph.org> + + gst/audiorate/gstaudiorate.c: Support float audio in audiorate. + Original commit message from CVS: + * gst/audiorate/gstaudiorate.c: (gst_audio_rate_setcaps): + Support float audio in audiorate. + Use width rather than depth for selecting sample width. + +2006-01-10 10:06:53 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/videotestsrc.h: Use GLib types here (that way we don't have to include the generated _stdint.h heade... + Original commit message from CVS: + * gst/videotestsrc/videotestsrc.h: + Use GLib types here (that way we don't have to include the + generated _stdint.h header, which makes life easier for win32 + folks that don't use autotools for the build) (#325990, patch + by: Sergey Scobich). + +2006-01-10 09:38:44 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstringbuffer.*: Name (private) union, makes Forte compiler happy (this time for real) (#324900). + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_init), + (gst_ring_buffer_set_flushing), (gst_ring_buffer_start), + (gst_ring_buffer_pause), (wait_segment): + * gst-libs/gst/audio/gstringbuffer.h: + Name (private) union, makes Forte compiler happy (this time + for real) (#324900). + +2006-01-09 10:52:33 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/Makefile.am: Link against libgstinterfaces, needed for mixer and property probe stuff. + Original commit message from CVS: + * gst-libs/gst/audio/Makefile.am: + Link against libgstinterfaces, needed for mixer + and property probe stuff. + +2006-01-09 10:46:52 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/Makefile.am: + Original commit message from CVS: + * gst-libs/gst/Makefile.am: + +2006-01-09 09:38:34 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/: Add gst_audio_default_registry_mixer_filter() utility function. + Original commit message from CVS: + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/audio/mixerutils.c: + (gst_audio_mixer_filter_do_filter), + (gst_audio_mixer_filter_check_element), + (gst_audio_mixer_filter_probe_feature), + (element_factory_rank_compare_func), + (gst_audio_default_registry_mixer_filter): + * gst-libs/gst/audio/mixerutils.h: + Add gst_audio_default_registry_mixer_filter() utility + function. + +2006-01-03 17:33:16 +0000 Michael Smith <msmith@xiph.org> + + gst/audioresample/resample.h: As before, but for o_buf + Original commit message from CVS: + * gst/audioresample/resample.h: + As before, but for o_buf + +2006-01-03 17:27:13 +0000 Michael Smith <msmith@xiph.org> + + gst/audioresample/resample.h: Declare struct _ResampleState.buffer as unsigned char *, not void *, since we do arithm... + Original commit message from CVS: + * gst/audioresample/resample.h: + Declare struct _ResampleState.buffer as unsigned char *, not void *, + since we do arithmetic on it. + +2006-01-02 23:37:38 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/audio/gstringbuffer.*: Sun's Forte compiler doesn't seem to like anonymous structs, so use same setup as... + Original commit message from CVS: + * gst-libs/gst/audio/gstringbuffer.c: (gst_ring_buffer_init), + (gst_ring_buffer_set_flushing), (gst_ring_buffer_start), + (gst_ring_buffer_pause), (wait_segment): + * gst-libs/gst/audio/gstringbuffer.h: + Sun's Forte compiler doesn't seem to like anonymous structs, + so use same setup as in GstBaseSrc (fixes #324900). + +2005-12-30 14:54:06 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + move old example to tests/examples/volume/volune.c + Original commit message from CVS: + * configure.ac: + * gst/volume/Makefile.am: + * gst/volume/demo.c: + move old example to tests/examples/volume/volune.c + * tests/examples/Makefile.am: + * tests/examples/seek/seek.c: (main): + change window-close event from "delete-event" to "destroy" + * tests/examples/volume/Makefile.am: + * tests/examples/volume/volume.c: (value_changed_callback), + (setup_gui), (message_received), (eos_message_received), (main): + fix event handling and bus usage + +2005-12-29 20:37:23 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audiotestsrc/gstaudiotestsrc.*: update to basesrc changes, implement segmented seeking and eos handling, add a 's... + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audiostestsrc_wave_get_type), (gst_audio_test_src_class_init), + (gst_audio_test_src_init), (gst_audio_test_src_src_fixate), + (gst_audio_test_src_query), (gst_audio_test_src_create_sine), + (gst_audio_test_src_create_square), + (gst_audio_test_src_create_saw), + (gst_audio_test_src_create_triangle), + (gst_audio_test_src_create_silence), + (gst_audio_test_src_create_white_noise), + (gst_audio_test_src_create_pink_noise), + (gst_audio_test_src_init_sine_table), + (gst_audio_test_src_create_sine_table), + (gst_audio_test_src_change_wave), + (gst_audio_test_src_change_volume), (gst_audio_test_src_do_seek), + (gst_audio_test_src_create), (gst_audio_test_src_set_property): + * gst/audiotestsrc/gstaudiotestsrc.h: + update to basesrc changes, implement segmented seeking and eos handling, + add a 'sine-tab' waveform for performance critical playback + +2005-12-29 16:17:55 +0000 Tim-Philipp Müller <tim@centricular.net> + + po/POTFILES.in: ... and this time the other modified file that I missed last time. + Original commit message from CVS: + * po/POTFILES.in: + ... and this time the other modified file that I missed last time. + +2005-12-29 14:31:49 +0000 Michael Smith <msmith@xiph.org> + + gst/playback/gstdecodebin.c: Fix non-C89 variable declaration not at the start of a block. Should help some compilers. + Original commit message from CVS: + * gst/playback/gstdecodebin.c: (new_pad): + Fix non-C89 variable declaration not at the start of a block. Should + help some compilers. + +2005-12-29 12:43:22 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: And now fix 'make distcheck' (builddir != srcdir) + Original commit message from CVS: + * tests/check/Makefile.am: + And now fix 'make distcheck' (builddir != srcdir) + +2005-12-29 12:22:24 +0000 Tim-Philipp Müller <tim@centricular.net> + + New cdparanoiasrc element based on cddabasesrc; enable cdparanoia plugin again (there are still fixes required to pla... + Original commit message from CVS: + * configure.ac: + * ext/cdparanoia/Makefile.am: + * ext/cdparanoia/gstcdparanoia.c: + * ext/cdparanoia/gstcdparanoia.h: + * ext/cdparanoia/gstcdparanoiasrc.c: + (gst_cd_paranoia_mode_get_type), (gst_cd_paranoia_src_base_init), + (gst_cd_paranoia_src_init), (gst_cd_paranoia_src_class_init), + (gst_cd_paranoia_src_open), (gst_cd_paranoia_src_close), + (gst_cd_paranoia_paranoia_callback), + (gst_cd_paranoia_src_read_sector), (gst_cd_paranoia_src_finalize), + (gst_cd_paranoia_src_set_property), + (gst_cd_paranoia_src_get_property), (plugin_init): + * ext/cdparanoia/gstcdparanoiasrc.h: + New cdparanoiasrc element based on cddabasesrc; enable cdparanoia + plugin again (there are still fixes required to playbin to make + cdda:// uris work there). + +2005-12-29 12:13:57 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/Makefile.am: Fix test case compilation. + Original commit message from CVS: + * tests/check/Makefile.am: + Fix test case compilation. + +2005-12-29 11:49:11 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst-libs/gst/cdda/gstcddabasesrc.c: An integer is not a string. Fix access to uninitialised variable. + Original commit message from CVS: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_update_duration), + (gst_cdda_base_src_calculate_cddb_id): + An integer is not a string. Fix access to uninitialised variable. + * tests/check/Makefile.am: + Add cddabasesrc unit test; also actually enable the vorbis test. + * tests/check/generic/states.c: + Blacklist new cd audio elements as well. + * tests/check/libs/cddabasesrc.c: + Unit test for GstCddaBaseSrc (discid calculation mostly). + +2005-12-28 18:19:25 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/libs/: Add docs for libgstcdda/GstCddaBaseSrc. + Original commit message from CVS: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-base-libs-docs.sgml: + * docs/libs/gst-plugins-base-libs-sections.txt: + * docs/libs/gst-plugins-base-libs.types: + Add docs for libgstcdda/GstCddaBaseSrc. + * gst-libs/gst/interfaces/mixertrack.h: + Do one struct member per line with a semicolon at the end, that way + even gtk-doc might parse it without complaining. + +2005-12-28 18:06:50 +0000 Tim-Philipp Müller <tim@centricular.net> + + Add new libgstcdda with GstCddaBaseSrc class. + Original commit message from CVS: + * configure.ac: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/cdda/Makefile.am: + * gst-libs/gst/cdda/base64.c: + * gst-libs/gst/cdda/base64.h: + * gst-libs/gst/cdda/gstcddabasesrc.c: + (gst_cdda_base_src_mode_get_type), (gst_cdda_base_src_base_init), + (gst_cdda_base_src_class_init), (gst_cdda_base_src_init), + (gst_cdda_base_src_finalize), (gst_cdda_base_src_set_property), + (gst_cdda_base_src_get_property), + (gst_cdda_base_src_get_track_from_sector), + (gst_cdda_base_src_get_query_types), (gst_cdda_base_src_convert), + (gst_cdda_base_src_query), (gst_cdda_base_src_is_seekable), + (gst_cdda_base_src_do_seek), (gst_cdda_base_src_handle_track_seek), + (gst_cdda_base_src_handle_event), (gst_cdda_base_src_uri_get_type), + (gst_cdda_base_src_uri_get_protocols), + (gst_cdda_base_src_uri_get_uri), (gst_cdda_base_src_uri_set_uri), + (gst_cdda_base_src_uri_handler_init), + (gst_cdda_base_src_setup_interfaces), + (gst_cdda_base_src_add_track), (gst_cdda_base_src_update_duration), + (cddb_sum), (gst_cddabasesrc_calculate_musicbrainz_discid), + (lba_to_msf), (gst_cdda_base_src_calculate_cddb_id), + (gst_cdda_base_src_add_tags), + (gst_cdda_base_src_add_index_associations), + (gst_cdda_base_src_set_index), (gst_cdda_base_src_get_index), + (gst_cdda_base_src_track_sort_func), (gst_cdda_base_src_start), + (gst_cdda_base_src_clear_tracks), (gst_cdda_base_src_stop), + (gst_cdda_base_src_create): + * gst-libs/gst/cdda/gstcddabasesrc.h: + * gst-libs/gst/cdda/sha1.c: + * gst-libs/gst/cdda/sha1.h: + Add new libgstcdda with GstCddaBaseSrc class. + +2005-12-28 14:59:41 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/gstgnomevfssink.h: Use GstBaseSinkClass as parent_class member for class struct, not + Original commit message from CVS: + * ext/gnomevfs/gstgnomevfssink.h: + Use GstBaseSinkClass as parent_class member for class struct, not + GstBaseSink. + +2005-12-27 22:29:43 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/videotestsrc/gstvideotestsrc.c: Add start method to reset running time and number of frames sent + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_class_init), (gst_video_test_src_start): + Add start method to reset running time and number of frames sent + when starting up (fixes #324696; patch by: Michal Benes). + +2005-12-27 21:58:28 +0000 Tim-Philipp Müller <tim@centricular.net> + + docs/plugins/: Add docs stuff for gnomevfssrc and gnomevfssink. + Original commit message from CVS: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-base-plugins-docs.sgml: + * docs/plugins/gst-plugins-base-plugins-sections.txt: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.hierarchy: + * docs/plugins/gst-plugins-base-plugins.signals: + Add docs stuff for gnomevfssrc and gnomevfssink. + * ext/gnomevfs/gstgnomevfssrc.c: + Fix example pipeline in gtk-doc blurb. + +2005-12-27 21:42:23 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/gnomevfs/: Port gnomevfssink; add gtk-doc blurb. + Original commit message from CVS: + * ext/gnomevfs/Makefile.am: + * ext/gnomevfs/gstgnomevfs.c: (gst_gnome_vfs_uri_get_type), + (gst_gnome_vfs_handle_copy), (gst_gnome_vfs_handle_free), + (gst_gnome_vfs_handle_get_type), (plugin_init): + * ext/gnomevfs/gstgnomevfs.h: + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnome_vfs_sink_do_init), + (gst_gnome_vfs_sink_base_init), (gst_gnome_vfs_sink_class_init), + (gst_gnome_vfs_sink_finalize), (gst_gnome_vfs_sink_init), + (gst_gnome_vfs_sink_set_property), + (gst_gnome_vfs_sink_get_property), (gst_gnome_vfs_sink_open_file), + (gst_gnome_vfs_sink_close_file), (gst_gnome_vfs_sink_start), + (gst_gnome_vfs_sink_stop), (gst_gnome_vfs_sink_handle_event), + (gst_gnome_vfs_sink_query), (gst_gnome_vfs_sink_render), + (gst_gnome_vfs_sink_uri_get_type), + (gst_gnome_vfs_sink_uri_get_protocols), + (gst_gnome_vfs_sink_uri_get_uri), (gst_gnome_vfs_sink_uri_set_uri), + (gst_gnome_vfs_sink_uri_handler_init): + * ext/gnomevfs/gstgnomevfssink.h: + Port gnomevfssink; add gtk-doc blurb. + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnome_vfs_src_get_type), + (gst_gnome_vfs_src_base_init), (gst_gnome_vfs_src_class_init), + (gst_gnome_vfs_src_init), (gst_gnome_vfs_src_finalize), + (gst_gnome_vfs_src_uri_get_type), + (gst_gnome_vfs_src_uri_get_protocols), + (gst_gnome_vfs_src_uri_get_uri), (gst_gnome_vfs_src_uri_set_uri), + (gst_gnome_vfs_src_uri_handler_init), + (gst_gnome_vfs_src_set_property), (gst_gnome_vfs_src_get_property), + (gst_gnome_vfs_src_unicodify), (audiocast_thread_run), + (gst_gnome_vfs_src_send_additional_headers_callback), + (gst_gnome_vfs_src_received_headers_callback), + (gst_gnome_vfs_src_push_callbacks), + (gst_gnome_vfs_src_pop_callbacks), + (gst_gnome_vfs_src_get_icy_metadata), (gst_gnome_vfs_src_create), + (gst_gnome_vfs_src_is_seekable), (gst_gnome_vfs_src_get_size), + (gst_gnome_vfs_src_start), (gst_gnome_vfs_src_stop): + * ext/gnomevfs/gstgnomevfssrc.h: + s/gst_gnomevfssrc/gst_gnome_vfs_src/; move header stuff to header + file; add gtk-doc blurb with example pipelines. + +2005-12-23 18:16:22 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.1 === + +2005-12-23 18:08:39 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/libs/tmpl/gstcolorbalance.sgml: + * docs/plugins/gst-plugins-base-plugins.args: + * docs/plugins/gst-plugins-base-plugins.signals: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + releasing 0.10.1 + Original commit message from CVS: + releasing 0.10.1 + +2005-12-21 20:59:52 +0000 Edgard Lima <edgard.lima@indt.org.br> + + * ChangeLog: + * gst/typefind/gsttypefindfunctions.c: + iLBC30 and iLBC20 added to typefind. + Original commit message from CVS: + iLBC30 and iLBC20 added to typefind. + +2005-12-20 15:57:06 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * configure.ac: + * docs/libs/tmpl/gstcolorbalance.sgml: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + * po/vi.po: + prereleasing + Original commit message from CVS: + prereleasing + +2005-12-20 12:24:29 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + stop making fun of older compilers + Original commit message from CVS: + stop making fun of older compilers + +2005-12-20 12:00:26 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + gst-libs/gst/audio/: update strings, values are in microseconds change the default sink buffer time to something that... + Original commit message from CVS: + * gst-libs/gst/audio/gstbaseaudiosink.c: + (gst_base_audio_sink_class_init): + * gst-libs/gst/audio/gstbaseaudiosrc.c: + (gst_base_audio_src_class_init): + update strings, values are in microseconds + change the default sink buffer time to something that is smaller + (to help software volume mixing have a slightly lower delay) but + still be acceptable on Wim's laptop + +2005-12-20 10:13:05 +0000 Edward Hervey <bilboed@bilboed.com> + + gst-libs/gst/riff/riff-media.c: Made a quack, forgot to add DUCK to the riff video template. + Original commit message from CVS: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_template_caps): + Made a quack, forgot to add DUCK to the riff video template. + +2005-12-19 15:00:38 +0000 Edward Hervey <bilboed@bilboed.com> + + ext/ogg/gstogmparse.c: Make sure pads are initialized correctly. + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_text_parse_base_init), + (gst_ogm_parse_init), (gst_ogm_audio_parse_init), + (gst_ogm_video_parse_init), (gst_ogm_text_parse_init), + (gst_ogm_parse_chain): + Make sure pads are initialized correctly. + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add a whole bunch of FOURCC <=> MimeType. + Extend the riff video pad template to support the newly added fourcc. + +2005-12-18 15:04:21 +0000 Jan Schmidt <thaytan@mad.scientist.com> + + ext/ogg/gstoggdemux.c: Extra debug output when activating/deactivating chains. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_deactivate_current_chain), + (gst_ogg_demux_activate_chain): + Extra debug output when activating/deactivating chains. + * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter), + (is_demuxer_element), (try_to_link_1), (remove_element_chain), + (unlinked): + Remove a queue from our list when it becomes unlinked. + Don't add queues to elements in class 'Demux' if they + can only produce one pad + +2005-12-18 10:54:33 +0000 Julien Moutte <julien@moutte.net> + + gst-libs/gst/video/gstvideosink.c: Add a debug category. + Original commit message from CVS: + 2005-12-18 Julien MOUTTE <julien@moutte.net> + * gst-libs/gst/video/gstvideosink.c: (gst_video_sink_base_init), + (gst_video_sink_get_type): Add a debug category. + +2005-12-18 00:56:07 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpdepayload.c: Handle downstream newsegment by sending our own newsegment before the next bu... + Original commit message from CVS: + 2005-12-17 Philippe Khalaf <burger@speedy.org> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_init), (gst_base_rtp_depayload_handle_sink_event): + Handle downstream newsegment by sending our own newsegment before the + next buffer to be released. (#323900) + +2005-12-18 00:41:10 +0000 Philippe Kalaf <philippe.kalaf@collabora.co.uk> + + gst-libs/gst/rtp/gstbasertpdepayload.c: add queue delay to new segment as well (as opposed to just the first buffer).... + Original commit message from CVS: + 2005-12-17 Philippe Khalaf <burger@speedy.org> + * gst-libs/gst/rtp/gstbasertpdepayload.c: + (gst_base_rtp_depayload_set_gst_timestamp): + add queue delay to new segment as well (as opposed to just the first + buffer). (bug #322347) + +2005-12-16 22:00:07 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + ext/libvisual/visual.c: change some char* into char[] + Original commit message from CVS: + * ext/libvisual/visual.c: (make_valid_name): + change some char* into char[] + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_class_init), (gst_audio_test_src_do_seek), + (gst_audio_test_src_create): + * gst/audiotestsrc/gstaudiotestsrc.h: + prepare to handle EOS and SEGMENT_DONE + +2005-12-16 12:32:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + tests/check/generic/states.c: Blacklist cdparanoia element in state test. + Original commit message from CVS: + * tests/check/generic/states.c: (GST_START_TEST): + Blacklist cdparanoia element in state test. + +2005-12-16 11:25:51 +0000 Benjamin Pineau <ben.pineau@gmail.com> + + gst/tcp/: Add <string.h> includes for memset and FD_ZERO (fixes #323878; + Original commit message from CVS: + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + Add <string.h> includes for memset and FD_ZERO (fixes #323878; + patch by: Benjamin Pineau). + +2005-12-15 14:43:38 +0000 Michael Smith <msmith@xiph.org> + + gst/videorate/gstvideorate.c: Fix timestamping for videorate when the first buffer it sees has a non-zero timestamp. ... + Original commit message from CVS: + * gst/videorate/gstvideorate.c: (gst_video_rate_blank_data), + (gst_video_rate_chain): + Fix timestamping for videorate when the first buffer it sees has a + non-zero timestamp. Fix some misleading debug output. + +2005-12-15 10:30:14 +0000 Michael Smith <msmith@xiph.org> + + gst/audioresample/gstaudioresample.c: Don't leak all input buffers to audioresample. + Original commit message from CVS: + * gst/audioresample/gstaudioresample.c: + Don't leak all input buffers to audioresample. + +2005-12-15 10:15:10 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/pango/gsttextoverlay.c: Don't operate on empty text buffers. Strip newlines and tabs only from the end of the tex... + Original commit message from CVS: + * ext/pango/gsttextoverlay.c: (gst_text_overlay_collected): + Don't operate on empty text buffers. Strip newlines and + tabs only from the end of the text, but leave them intact + in the middle. Fix typo in gtk-doc description. + +2005-12-15 09:48:19 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Make sure the video frame buffer we return to apps via the "frame" property always has caps set on it.... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: + * gst/playback/gstplaybin.c: (handoff): + Make sure the video frame buffer we return to apps via the + "frame" property always has caps set on it. Modify + _gst_gvalue_set_object() macro to handle NULL objects + gracefully too. + +2005-12-14 20:42:11 +0000 Stefan Kost <ensonic@users.sourceforge.net> + + gst/audiotestsrc/gstaudiotestsrc.*: Adjust to some recent api changes and add wtays new cool seeking capabillities + Original commit message from CVS: + * gst/audiotestsrc/gstaudiotestsrc.c: + (gst_audio_test_src_class_init), (gst_audio_test_src_init), + (gst_audio_test_src_setcaps), (gst_audio_test_src_src_query), + (gst_audio_test_src_do_seek), (gst_audio_test_src_is_seekable), + (gst_audio_test_src_create): + * gst/audiotestsrc/gstaudiotestsrc.h: + Adjust to some recent api changes and add wtays new cool seeking + capabillities + +2005-12-14 17:58:48 +0000 Tim-Philipp Müller <tim@centricular.net> + + ext/alsa/: Helper functions to add device probing via the GstPropertyProbe interface to a class. + Original commit message from CVS: + * ext/alsa/Makefile.am: + * ext/alsa/gstalsadeviceprobe.c: + * ext/alsa/gstalsadeviceprobe.h: + Helper functions to add device probing via the GstPropertyProbe + interface to a class. + * ext/alsa/gstalsamixer.h: + Comment out GST_ALSA_MIXER, it returns a struct that's not + used. + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_open): + Add some debug info. + * ext/alsa/gstalsamixerelement.c: + (gst_alsa_mixer_element_interface_supported), + (gst_implements_interface_init), + (gst_alsa_mixer_element_init_interfaces), + (gst_alsa_mixer_element_class_init), + (gst_alsa_mixer_element_finalize), (gst_alsa_mixer_element_init), + (gst_alsa_mixer_element_set_property), + (gst_alsa_mixer_element_get_property), + (gst_alsa_mixer_element_change_state): + * ext/alsa/gstalsamixerelement.h: + Add 'device' and 'device-name' properties. Add GstPropertyProbe + for device handling (gnome-volume-control will need that). + +2005-12-12 20:31:24 +0000 Christian Schaller <uraeus@gnome.org> + + * ChangeLog: + * ext/Makefile.am: + * gst-plugins-base.spec.in: + updates to activate cdparanoia plugin + Original commit message from CVS: + updates to activate cdparanoia plugin + +2005-12-12 19:13:09 +0000 Michael Smith <msmith@xiph.org> + + ext/ogg/gstoggdemux.c: Use the correct function to free list of typefind factories. + Original commit message from CVS: + * ext/ogg/gstoggdemux.c: (gst_ogg_type_find): + Use the correct function to free list of typefind factories. + +2005-12-12 15:09:55 +0000 Wim Taymans <wim.taymans@gmail.com> + + gst/videotestsrc/gstvideotestsrc.*: Implement seeking in videotestsrc. + Original commit message from CVS: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_video_test_src_class_init), (gst_video_test_src_init), + (gst_video_test_src_parse_caps), (gst_video_test_src_query), + (gst_video_test_src_do_seek), (gst_video_test_src_is_seekable), + (gst_video_test_src_create): + * gst/videotestsrc/gstvideotestsrc.h: + Implement seeking in videotestsrc. + Small cleanups. + +2005-12-12 15:06:46 +0000 Wim Taymans <wim.taymans@gmail.com> + + ext/cdparanoia/: Partially ported cdparanoia now that basesrc can support a plugin like this.. + Original commit message from CVS: + * ext/cdparanoia/Makefile.am: + * ext/cdparanoia/gstcdparanoia.c: (gst_paranoia_mode_get_type), + (gst_paranoia_endian_get_type), (_do_init), + (cdparanoia_class_init), (cdparanoia_init), + (cdparanoia_set_property), (cdparanoia_get_property), + (cdparanoia_do_seek), (cdparanoia_is_seekable), + (cdparanoia_create), (cdparanoia_start), (cdparanoia_stop), + (cdparanoia_convert), (cdparanoia_get_query_types), + (cdparanoia_query), (cdparanoia_set_index), + (cdparanoia_uri_set_uri): + * ext/cdparanoia/gstcdparanoia.h: + Partially ported cdparanoia now that basesrc can support a + plugin like this.. + +2005-12-12 13:03:50 +0000 Wim Taymans <wim.taymans@gmail.com> + + tests/examples/seek/scrubby.c: Set higher priority for bus events so they don't get reordered with gtk gui events. + Original commit message from CVS: + * tests/examples/seek/scrubby.c: (main): + Set higher priority for bus events so they don't get reordered with + gtk gui events. + * tests/examples/seek/seek.c: (do_seek), (start_seek), (stop_seek), + (flush_toggle_cb), (main): + Added checkbox do disable flushing seeks. + Disable scrubbing when doing non flushing seeks. + +2005-12-12 09:52:37 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/subparse/gstsubparse.c: Implement some sort of event handling that doesn't rely on g_return_if_fail; make sure we... + Original commit message from CVS: + * gst/subparse/gstsubparse.c: (gst_sub_parse_init), + (gst_sub_parse_do_seek), (gst_sub_parse_src_event), (parse_subrip), + (parser_state_init), (handle_buffer), (gst_sub_parse_chain), + (gst_sub_parse_sink_event), (gst_sub_parse_change_state): + Implement some sort of event handling that doesn't rely on + g_return_if_fail; make sure we always push the last chunk of an + .srt out when we receive an EOS; use gst_pad_alloc_buffer; fix + state change function; remove some old cruft. Seeking is still + rather unlikely to work though. + * tools/.cvsignore: + Ignore more. + +2005-12-11 22:26:08 +0000 Julien Moutte <julien@moutte.net> + + sys/xvimage/xvimagesink.c: Fixed a leak of the current image reference when cleaning up. + Original commit message from CVS: + 2005-12-11 Julien MOUTTE <julien@moutte.net> + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_change_state): + Fixed a leak of the current image reference when cleaning up. + Thanks to Arwed von Merkatz (alley_cat) for pointing it out. + +2005-12-09 10:23:42 +0000 Michael Smith <msmith@xiph.org> + + tools/: Remove gst-launch-ext. It doesn't work, and is no longer particularly useful. + Original commit message from CVS: + * tools/Makefile.am: + * tools/gst-launch-ext-m.m: + Remove gst-launch-ext. It doesn't work, and is no longer + particularly useful. + +2005-12-08 18:53:57 +0000 Luca Ognibene <luogni@tin.it> + + ext/ogg/gstogmparse.c: don't pass random values to ogmparse convert function. + Original commit message from CVS: + * ext/ogg/gstogmparse.c: (gst_ogm_parse_sink_query): + don't pass random values to ogmparse convert function. + Make seeking possible in the exile1.ogm file. + +2005-12-07 18:51:35 +0000 Tim-Philipp Müller <tim@centricular.net> + + gst/playback/: Work around refcount problem with g_value_set_object() that occur if the core has been compiled agains... + Original commit message from CVS: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_property): + * gst/playback/gstplaybin.c: (gst_play_bin_get_property): + Work around refcount problem with g_value_set_object() that occur + if the core has been compiled against GLib-2.6 (g_value_set_object() + will only g_object_ref() the element, but the caller will + gst_object_unref() it and bad things will happen due to the way + GstObjects are refcounted in the GLib-2.6 case). Fixes problems with + totem for people on FC4 using Thomas's 0.10 RPMs. + +2005-12-07 11:34:37 +0000 Edward Hervey <bilboed@bilboed.com> + + Time to welcome ogm to 0.10 :) + Original commit message from CVS: + Time to welcome ogm to 0.10 :) + * ext/ogg/gstoggdemux.c: (internal_element_pad_added_cb), + (gst_ogg_pad_typefind): + Oggdemux can now properly typefind elements with dynamic pads. + * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): + Properly set caps on src pad, and set caps on outgoing buffers. + +2005-12-06 19:42:02 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * ext/alsa/gstalsamixer.h: + * ext/alsa/gstalsamixerelement.h: + * ext/alsa/gstalsamixeroptions.h: + * ext/alsa/gstalsamixertrack.h: + * ext/alsa/gstalsasink.c: + * ext/alsa/gstalsasink.h: + * ext/alsa/gstalsasrc.c: + * ext/alsa/gstalsasrc.h: + * ext/cdparanoia/gstcdparanoia.h: + * ext/gnomevfs/gstgnomevfsuri.h: + * ext/ogg/gstoggdemux.c: + * ext/ogg/gstoggmux.c: + * ext/pango/gsttextoverlay.h: + * ext/theora/theoradec.c: + * ext/theora/theoraenc.c: + * ext/vorbis/vorbisdec.h: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisenc.h: + * ext/vorbis/vorbisparse.h: + * gst-libs/gst/audio/gstaudioclock.h: + * gst-libs/gst/audio/gstaudiosink.c: + * gst-libs/gst/audio/gstaudiosink.h: + * gst-libs/gst/audio/gstaudiosrc.c: + * gst-libs/gst/audio/gstaudiosrc.h: + * gst-libs/gst/audio/gstbaseaudiosink.c: + * gst-libs/gst/audio/gstbaseaudiosink.h: + * gst-libs/gst/audio/gstbaseaudiosrc.c: + * gst-libs/gst/audio/gstbaseaudiosrc.h: + * gst-libs/gst/audio/gstringbuffer.h: + * gst-libs/gst/audio/multichannel.h: + * gst-libs/gst/floatcast/floatcast.h: + * gst-libs/gst/interfaces/colorbalance.c: + * gst-libs/gst/interfaces/colorbalance.h: + * gst-libs/gst/interfaces/colorbalancechannel.h: + * gst-libs/gst/interfaces/mixer.h: + * gst-libs/gst/interfaces/mixeroptions.h: + * gst-libs/gst/interfaces/mixertrack.h: + * gst-libs/gst/interfaces/navigation.h: + * gst-libs/gst/interfaces/propertyprobe.h: + * gst-libs/gst/interfaces/tuner.h: + * gst-libs/gst/interfaces/tunerchannel.h: + * gst-libs/gst/interfaces/tunernorm.h: + * gst-libs/gst/interfaces/xoverlay.h: + * gst-libs/gst/netbuffer/gstnetbuffer.h: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/riff/riff-media.h: + * gst-libs/gst/riff/riff-read.h: + * gst-libs/gst/rtp/gstbasertpdepayload.h: + * gst-libs/gst/rtp/gstbasertppayload.c: + * gst-libs/gst/rtp/gstbasertppayload.h: + * gst-libs/gst/rtp/gstrtpbuffer.c: + * gst-libs/gst/rtp/gstrtpbuffer.h: + * gst-libs/gst/tag/gsttageditingprivate.h: + * gst-libs/gst/tag/gstvorbistag.c: + * gst-libs/gst/tag/tag.h: + * gst-libs/gst/video/video.h: + * gst/adder/gstadder.c: + * gst/adder/gstadder.h: + * gst/audioconvert/audioconvert.c: + * gst/audioconvert/audioconvert.h: + * gst/audioconvert/gstaudioconvert.c: + * gst/audioconvert/gstchannelmix.c: + * gst/audioconvert/gstchannelmix.h: + * gst/audiorate/gstaudiorate.c: + * gst/audioresample/buffer.h: + * gst/audioresample/functable.h: + * gst/audioresample/gstaudioresample.c: + * gst/audioresample/resample.h: + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/ffmpegcolorspace/imgconvert.c: + * gst/ffmpegcolorspace/imgconvert_template.h: + * gst/playback/gstdecodebin.c: + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: + * gst/playback/gststreaminfo.h: + * gst/tcp/gstfdset.c: + * gst/tcp/gstfdset.h: + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpplugin.h: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + * gst/typefind/gsttypefindfunctions.c: + * gst/videorate/gstvideorate.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.h: + * sys/v4l/gstv4lcolorbalance.h: + * sys/v4l/gstv4ltuner.h: + * sys/v4l/gstv4lxoverlay.h: + * sys/v4l/v4l_calls.h: + * sys/v4l/videodev_mjpeg.h: + * tests/check/elements/audioconvert.c: + * tests/check/elements/audioresample.c: + * tests/check/elements/audiotestsrc.c: + * tests/check/elements/videotestsrc.c: + * tests/check/elements/volume.c: + * tests/examples/seek/scrubby.c: + * tests/examples/seek/seek.c: + expand tabs + Original commit message from CVS: + expand tabs + +2005-12-06 19:28:24 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * docs/libs/tmpl/gstaudio.sgml: + * docs/libs/tmpl/gstcolorbalance.sgml: + * docs/libs/tmpl/gstgconf.sgml: + * docs/libs/tmpl/gstmixer.sgml: + * docs/libs/tmpl/gstringbuffer.sgml: + * docs/libs/tmpl/gsttuner.sgml: + * docs/libs/tmpl/gstxoverlay.sgml: + put back stability level + Original commit message from CVS: + put back stability level + +2005-12-05 18:11:49 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * configure.ac: + back to HEAD + Original commit message from CVS: + back to HEAD + +=== release 0.10.0 === + +2005-12-05 18:02:48 +0000 Thomas Vander Stichele <thomas@apestaart.org> + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * docs/libs/tmpl/gstcolorbalance.sgml: + * docs/plugins/inspect/plugin-adder.xml: + * docs/plugins/inspect/plugin-alsa.xml: + * docs/plugins/inspect/plugin-audioconvert.xml: + * docs/plugins/inspect/plugin-audiorate.xml: + * docs/plugins/inspect/plugin-audioresample.xml: + * docs/plugins/inspect/plugin-audiotestsrc.xml: + * docs/plugins/inspect/plugin-decodebin.xml: + * docs/plugins/inspect/plugin-ffmpegcolorspace.xml: + * docs/plugins/inspect/plugin-gnomevfs.xml: + * docs/plugins/inspect/plugin-libvisual.xml: + * docs/plugins/inspect/plugin-ogg.xml: + * docs/plugins/inspect/plugin-pango.xml: + * docs/plugins/inspect/plugin-playbin.xml: + * docs/plugins/inspect/plugin-subparse.xml: + * docs/plugins/inspect/plugin-tcp.xml: + * docs/plugins/inspect/plugin-theora.xml: + * docs/plugins/inspect/plugin-typefindfunctions.xml: + * docs/plugins/inspect/plugin-video4linux.xml: + * docs/plugins/inspect/plugin-videorate.xml: + * docs/plugins/inspect/plugin-videoscale.xml: + * docs/plugins/inspect/plugin-videotestsrc.xml: + * docs/plugins/inspect/plugin-volume.xml: + * docs/plugins/inspect/plugin-vorbis.xml: + * docs/plugins/inspect/plugin-ximagesink.xml: + * docs/plugins/inspect/plugin-xvimagesink.xml: + releasing 0.10.0 + Original commit message from CVS: + releasing 0.10.0 + diff --git a/gst-plugins-base-subtitles0.10/INSTALL b/gst-plugins-base-subtitles0.10/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/gst-plugins-base-subtitles0.10/LICENSE_readme b/gst-plugins-base-subtitles0.10/LICENSE_readme new file mode 100644 index 0000000..67fd312 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/LICENSE_readme @@ -0,0 +1,137 @@ + +Disclaimer: The GStreamer team makes a real effort to make sure that +the information in this file is as up-to-date and accurate as possible. +However, this file may contain errors and omissions. Some dependant +libraries change their licensing from version-to-version and some of +the libraries listed here as LGPL were under the GPL license in +older releases. Distributions which include GStreamer are responsible +for ensuring that plugins are used in accordance with licensing terms +and other laws. + +GStreamer is developed under the terms of the LGPL (see LICENSE file for details). +Some of our plugins however rely on libraries which are available under other +licenses. This means that if you are using an application which has a non-GPL +compatible license, for instance a closed-source application with GStreamer +you have to make sure not to use GPL linked or derived plugins. When using +GPL linked plugins GStreamer is for all practical reasons under the GPL itself. + +The plugins which use a GPL library are as follows: + +a52dec liba52 (http://liba52.sourceforge.net/) +aasink aalib (http://sourceforge.net/projects/aa-project/) +cdparanoia libcdparanoia (http://www.xiph.org/paranoia/) +dtsdec libdts (http://www.videolan.org/dtsdec.html) +dvdnavsrc libdvdnav (http://dvd.sourceforge.net/) +dxr3 (http://dxr3.sourceforge.net/) +icecastsend libshout (http://www.icecast.org) +mad libmad (http://www.mars.org/home/rob/proj/mpeg/) +mpeg2dec libmpeg2 (http://libmpeg2.sourceforge.net/) +mpeg2enc libmpeg2enc (http://mjpeg.sourceforge.net/) +mplex libmplex (http://mjpeg.sourceforge.net/) +siddec libsidplay 1.36 (http://www.geocities.com/SiliconValley/Lakes/5147/sidplay/, + http://sourceforge.net/projects/sidplay2/) +trm libmusicbrainz (http://www.musicbrainz.org/) +xine libxine (http://xinehq.de/) +xvid libxvidcore (http://www.xvid.org/) + +Plugins derived from GPL code are as follows: + +dvdreadsrc libdvdread (http://www.dtek.chalmers.se/groups/dvd/) +jack libjack (http://jackit.sourceforge.net/) + Note libjack is LGPL, but plugin is GPL. +monoscope None (Algorithm by Ralph Loader, Joerg Walter, + Richard Boulton, and Andy Lo A Foe) +rtjpeg None (Erik Walthinsen's algorithm) +rtp None (http://www.linphone.org/ortp/) +synaesthesia (http://www.logarithmic.net/pfh/synaesthesia) +system_encode None (Algorithm by Chrisoph Moar, Wim Tayman's and + Erik Walthinsen) +vbidec None (Algorithm by Billy Biggs, Doug Bell, + Erik Walthinsen and David I. Lehn) + +Plugins which use a LGPL library are as follows: + +alsa alsa (http://alsa-project.org/) +artsdsink aRts (http://arts-project.org/) +cacasink libcaca (http://sam.zoy.org/projects/libcaca/) +colorspacelcs libcolorspace +dvdec libdv (http://libdv.sourceforge.net/) +esdmon,esdsink libesd (ftp.gnome.org/pub/GNOME/stable/sources/esound/) +faac libfaac (http://www.audiocoding.com/modules/mydownloads/) +fameenc libfame (http://fame.sourceforge.net/) +ffmpeg ffmpeg (http://ffmpeg.sourceforge.net/) +gdkpixbuf GTK+ (http://www.gtk.org/) +gnomevfs gnome-vfs (ftp.gnome.org//pub/GNOME/stable/sources/gnome-vfs/) +gst_arts aRts (http://arts-project.org/) +gst1394 libraw1394 (http://www.linux1394.org/) +gstaf libaudiofile (http://www.68k.org/~michael/audiofile/) +gstsf libsndfile (http://www.mega-nerd.com/libsndfile/) +hermescolorspace Hermes (http://www.clanlib.org/hermes/) +kio KDE (http://www.kde.org/) +ladspa (http://www.ladspa.org/) +lame libmp3lame (http://lame.sourceforge.net/) +libvisual libvisual (http://libvisual.sourceforge.net/) +matroska (http://www.matroska.org/) +mikmod libmikmod (http://mikmod.raphnet.net/) +ossaudio (http://www.opensound.com/) +qcamsrc +rfbenc librfb +sdlvideosink libsdl (http://www.libsdl.org/) +shout2send libshout2 (http://www.icecast.org) +smoothwave +swfdec (http://swfdec.sourceforge.net/) +tarkin (http://svn.xiph.org/trunk/tarkin/) +textoverlay pango (http://www.pango.org/) +dirac (http://www.bbc.co.uk/rd/projects/dirac/) +effectv (Our ports was relicensed)(http://effectv.sourceforge.net/) +musepack (http://www.musepack.net/) + +Plugins which use a BSD covered library are as follows: + +ogg libogg/libvorbis (http://www.xiph.org/ogg/vorbis/) +vorbis libogg/libvorbis (http://www.xiph.org/ogg/vorbis/) +gsttheora libtheora (http://www.theora.org/) +speex (http://www.speex.org/) +flac libFLAC (http://flac.sourceforge.net/) + +Plugins based on libraries with other free licenses: + +ximagesink libXv +xvimagesink libXv + - license: MIT X11 / X Consortium license + +gsm libgsm + - license MIT license http://kbs.cs.tu-berlin.de/~jutta/toast.html + +festival (http://www.cstr.ed.ac.uk/projects/festival/) + - license: http://www.cstr.ed.ac.uk/projects/festival/freecopyright.shtml + +jpeg (http://www.ijg.org/) + - license: IJG license + +nas (http://radscan.com/nas.html) + - license: NAS license + +snapshot libpng (http://www.libpng.org/pub/png/) + - license: PNG license + +mngdec/mngenc libmng (http://gjuyn.xs4all.nl/libmng) + - license PNG license + +Plugins using non-free libraries: +divxdec, divxenc (http://www.divx.com/) +osxaudio (http://www.apple.com/macosx/) +sunaudiosink (http://www.sun.com/) + +Unsure: + +faad libfaad (http://www.audiocoding.com/) +faad's license depends on its major version : + - for FAAD1 : it is LGPL + - for FAAD2 : it is GPL +look at these pages for more information on licenses : +http://www.audiocoding.com/modules/wiki/?page=FAAD2 +http://www.audiocoding.com/modules/wiki/?page=FAAC + +by default, GStreamer faad plugin would compile against FAAD2 if available. +it falls back to FAAD1 if not. diff --git a/gst-plugins-base-subtitles0.10/MAINTAINERS b/gst-plugins-base-subtitles0.10/MAINTAINERS new file mode 100644 index 0000000..2412862 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/MAINTAINERS @@ -0,0 +1,13 @@ +GStreamer is currently maintained by the consensus of a number +of people, including, but not limited to: + + David Schleef <ds@schleef.org> + Jan Schmidt <thaytan@noraisin.net> + Wim Taymans <wim.taymans@gmail.com> + Tim-Philipp Müller <tim centricular net> + +Maintainer-related issues should be addressed to: + + gstreamer-devel@lists.sourceforge.net + + diff --git a/gst-plugins-base-subtitles0.10/Makefile.am b/gst-plugins-base-subtitles0.10/Makefile.am new file mode 100644 index 0000000..19e3c2b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/Makefile.am @@ -0,0 +1,84 @@ +DISTCHECK_CONFIGURE_FLAGS=--enable-gtk-doc + +if BUILD_EXTERNAL +SUBDIRS_EXT = ext +else +SUBDIRS_EXT = +endif + +SUBDIRS = \ + pkgconfig \ + gst-libs \ + gst sys $(SUBDIRS_EXT) \ + tools \ + tests \ + docs \ + po \ + common \ + m4 + +DIST_SUBDIRS = \ + pkgconfig \ + docs \ + gst-libs \ + gst sys ext \ + tools \ + tests \ + po \ + common \ + m4 + +# include before EXTRA_DIST for win32 assignment +include $(top_srcdir)/common/win32.mak + +EXTRA_DIST = \ + gst-plugins-base.spec depcomp \ + AUTHORS COPYING COPYING.LIB NEWS README RELEASE REQUIREMENTS \ + ChangeLog gst-plugins-base.doap autogen.sh $(win32) + +DISTCLEANFILES = _stdint.h + +ACLOCAL_AMFLAGS = -I m4 -I common/m4 + +include $(top_srcdir)/common/release.mak +include $(top_srcdir)/common/po.mak + +check-valgrind: + cd tests/check && make check-valgrind + +if HAVE_GST_CHECK +check-torture: + cd tests/check && make torture +else +check-torture: + true +endif + +WIN32_COPY = \ + $(top_builddir)/gst-libs/gst/*/*-enumtypes.[ch] \ + $(top_builddir)/_stdint.h + +win32-update: + for f in $(WIN32_COPY); do cp -v $$f win32/common; done; \ + for f in win32/common/*-enumtypes.c; do \ + echo "Indenting $$f"; \ + gst-indent $$f; gst-indent $$f; \ + done + cp -v $(top_builddir)/win32/common/config.h-new \ + $(top_srcdir)/win32/common/config.h + +include $(top_srcdir)/common/coverage/lcov.mak + +check: check-exports + +# cruft: plugins that have been merged or moved or renamed + +CRUFT_FILES = \ + $(top_builddir)/common/shave \ + $(top_builddir)/common/shave-libtool \ + $(top_builddir)/tools/gst-discoverer + + +include $(top_srcdir)/common/cruft.mak + +all-local: check-cruft diff --git a/gst-plugins-base-subtitles0.10/NEWS b/gst-plugins-base-subtitles0.10/NEWS new file mode 100644 index 0000000..617438f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/NEWS @@ -0,0 +1,2233 @@ +This is GStreamer Base Plug-ins 0.10.34, "Lemmings" + +Changes since 0.10.33: + + * None: this release is identical to 0.10.33 and just done to keep core/base + versions in sync + +Changes since 0.10.32: + + * audioringbuffer: make sure to not start if the may_start flag is FALSE + * baseaudiosink: arrange for running clock when rendering eos + * baseaudiosink: don't allow aligning behind the read-segment + * baseaudiosink: start ringbuffer upon going to PLAYING and already EOS + * riff: Add support for video/x-camstudio + * rtcpbuffer: fix invalid read in validation of padding in rtcp packet + * rtcpbuffer: Round to next 32bit word, not current 32bit word at end of SDES chunk + * rtpbuffer: Off-by-one error when creating RTP header extensions with a two-byte header + * rtsptransport: ensure valid int result when parsing ranges + * tag: map the ID3v2 TENC frame to GST_TAG_ENCODED_BY + * tag: add GST_TAG_CAPTURING_EXPOSURE_COMPENSATION incl. EXIF/XMP mappings + * tag: add a new GstTagXmpWriter interface to select XMP schemas to be used + * tagdemux: also push cached events downstream when operating in pull mode + * video: add GST_VIDEO_BUFFER_PROGRESSIVE flag + * video: add ARGB64 and AYUV64 (16 bits per channel) formats + * video: add r210 (10 bits per channel) format + * video: add gst_video_format_get_component_depth() and _new_template_caps() + * video: fix creation of grayscale caps and height calculation for YUV9/YVU9 + * appsink: emit "new-buffer-list" signal for buffer lists if handled by app + * audiorate: add "skip-to-first" property + * decodebin2: don't use the same parser element multiple times in the same chain + * decodebin2: improve detection of raw caps in expose-all-streams=false mode + * discoverer: don't wait for subtitle streams to preroll; leak fixes + * discoverer: use nominal bitrate if bitrate tag is unavailable + * encodebin: add an audioconvert after the audio resampler + * encodebin: fix refcounting issues and leaks related to request pads + * encodebin: return a new reference of the pad for the "request-pad" signal + * encodebin: set all elements to NULL and remove them from the bin when removing a source group + * encodebin: tear down old profiles when setting new ones + * multifdsink: disconnect inactive clients in the select loop too + * oggmux: prefer headers from caps to determine stream type (for VP8) + * oggmux: fix issue with ogg page numbering and discont flag handling + * oggmux: ensure stream serial numbers are unique + * oggmux: use running time for muxing instead of timestamps + * oggparse: better detection of delta unit flag + * playbin2, uridecodebin: add "source-setup" signal + * playbin2: always prefer the custom set sink and also set it back to NULL in all cases + * playbin2: check if an already existing sink supports the non-raw format too + * playbin2: fix handling of non-raw custom sinks + * playbin2: if a sink claims to support ANY caps assume that it only supports the usual raw formats + * playbin2: only consider the audio/video sinks in autoplug_continue for the normal uridecodebin + * playbin2: use gst_pad_accept_caps() instead of intersecting with the getcaps caps + * playbin2: set sinks to READY before checking if it accept caps + * textoverlay: add support for ARGB and other RGB alpha variants, and xBGR and RGBx + * textoverlay: add support for vertical center alignment + * textoverlay: converted AYUV to use 'A OVER B' alpha compositing + * textoverlay: use a class wide mutex to work around pango reentrance issues + * theoraenc: don't reset the video quality when setting the bitrate + * theoraenc: allow adjustment of the speed level while running + * theoraenc: set speed-level property defaults from libtheora's defaults + * typefinding: MPEG-TS detection fixes + * typefinding: detect HTTP live streaming m3u8 playlists + * typefinding: detect windows icon files and DEGAS images (to avoid false positives) + * typefinding: detect raw h.263 + * typefinding: add depth and endianness fields to DTS caps + * uridecodebin: Add default handler for autoplug-select + * uridecodebin: add https:// to protocols for which to enable buffering + * uridecodebin: expose "autoplug-sort" signal + * uridecodebin: post proper error message if decodebin2/typefind elements are missing + * uridecodebin: Return NULL from the default autoplug-sort handler + * videorate: fix "skip-to-first" timestamp setup + * videoscale: add 16-bit-channel support (ARGB64, AYUV64), fix ARGB bilinear scaling + * videotestsrc: add 16-bit-per-channel support (ARGB64, AYUV64) + * vorbis: add support for using tremolo on android + * vorbistag: Add support for METADATA_BLOCK_PICTURE tags + * vorbistag: Write GST_TAG_IMAGE and GST_TAG_PREVIEW_IMAGE as METADATA_BLOCK_PICTURE + * win32: fix DEFAULT_AUDIOSINK, should be direct*sound*sink + * xvimagesink: don't paint the window black when going to NULL + +Bugs fixed since 0.10.32: + + * 618516 : [typefinding] need raw H.263 typefinder + * 619778 : oggdemux: fails on zero-length pages with Patent_Absurdity_HD_3540kbit.ogv + * 633837 : videoscale: invalid reads after conversion to orc linear scaling + * 412678 : random segfaults or memory corruptions with multiple textoverlays (pango not reentrant) + * 620364 : [typefinding] .ico file detected as AAC + * 625129 : typefinding: file incorrectly detected as audio/x-dts + * 626152 : [playbin2] add " source-setup " signal + * 627268 : [tag] add GST_TAG_ENCODED_BY and map id3v2 TENC frame + * 629196 : oggmux: re-tagging an Ogg Vorbis file may corrupt audio data + * 632291 : discoverer: sparse tracks cause prerolling to hang till timeout + * 632889 : [multifdsink] [PATCH] Disconnect inactive clients in the select loop too + * 635669 : [vorbistag] Support METADATA_BLOCK_PICTURE for Vorbis cover art + * 635784 : ringbuffer: make sure to not start if the may_start flag is FALSE + * 635800 : xvimagesink flashes black when going from READY_TO_NULL + * 636886 : baseaudiosink: no running clock when eos leads to hang in PLAYING + * 639136 : [oggparse]code is not safe when using libogg fuctions + * 639159 : [textoverloay] Add vertical center alignment option + * 639237 : textoverlay: patch to use " A OVER B " alpha compositing + * 639744 : [oggdemux] Removing dead code: + * 640189 : oggmux: cleanup + * 640211 : oggmux: ensure serialnos are unique + * 640607 : appsink never sends " new-buffer-list " signal + * 640709 : [typefindfunctions] h264 typefinder registered with MPEG_VIDEO_CAPS + * 640804 : checks: encodebin test fails if theora or vorbis plugins are not available + * 641706 : discoverer: Keep references on discoverer objects for callbacks + * 641860 : discoverer: Use nominal bitrate if bitrate tag is unavailable + * 641917 : [gdppay] Ensure buffer's medata is writeable before setting it + * 641927 : [encodebin] refcount issue with the " request-pad " signal + * 641952 : [videoscale] assertion on fixate_caps + * 642174 : Playbin2 cannot work with non-raw custom sinks + * 642232 : theoraenc sets Video quality to zero when explicitely setting the bitrate to 0 + * 642274 : [playbin2] arbitrary audio-sink is chosen even though explicitely having set a custom audio-sink bin + * 642381 : potential memleak in decodebin2 + * 642466 : playbin2: after replacing a video sink with the pipeline in NULL state I still get the old one + * 642720 : audiotestsrc: pipelines with multiple instances with wave=gaussian-noise, white-noise, or pink-noise are very slow + * 642942 : adder: offset_end field of outgoing buffers is set to GST_BUFFER_OFFSET_NONE + * 642949 : pbutils: encoding-target: chaining error object in loading target from file may cause crash if there is no error + * 643775 : [oggmux] use running time instead of timestamps + * 644416 : [encodebin] Cannot be reused + * 644745 : [oggmux] Fails to mux Speex content, doesn't preroll + * 644845 : [alsa] Comparison of unsigned int < 0 always false in gstalsamixer.c + * 644996 : libsABI check doesn't depend only on architecture + * 645167 : [xmp] Add a new XmpConfig interface + * 645437 : encoding-profile: Fix syntax in Example: Creating a profile + * 646570 : baseaudiosink: don't allow aligning behind the read-segment + * 646572 : baseaudiosrc: protect against ringbuffer disappearing while in a query + * 646573 : baseaudiosrc: Add src object lock around call to ringbuffer parse caps + * 646575 : rtcpbuffer: Round to next 32bit word, not current 32bit word at end of SDES chunk + * 646576 : rtcpbuffer: fix invalid read in validation of padding in rtcp packet + * 646923 : video: Remove unused variable + * 646924 : rtp: Remove unused variables + * 646925 : encoding-profile: Remove unused variables + * 646952 : Fix the strlol return type mismatch : + * 647399 : Bad typo in ID3 tags: psychadelic - > psychedelic + * 647721 : Remove excessive checking for video.c + * 647781 : [playbin2] missing shutdown steps and inconsistent error behaviour + * 647856 : [oggmux] Assumes that the first buffer can be used to detect the stream type + * 647857 : [xvimagesink/ximagesink] Handle NULL caps in buffer_alloc() + * 647942 : [pango] Use different Pango contexts for the different subclasses + * 647943 : [pango] Class global pango mutex not always used + * 648459 : tag: exif: register common tags from tag library + * 648466 : Ogg to LPCM transcoding fails + * 648548 : videoscale broken with orc 0.4.13 + * 642667 : [playbin2] autoplug-factories code does not do what it claims to do + * 642732 : [playbin2] sinks set to READY after activating groups causes bad autoplug-continue decisions + * 646744 : libgsttag: Minor issues building gst-plugins-base with MS compiler + * 647294 : gst-plugins-base doesn't compile with GCC 4.6 + +API additions since 0.10.32: + + * gst_tag_list_to_xmp_buffer_full() + * gst_tag_xmp_list_schemas() + * gst_tag_xmp_writer_add_all_schemas() + * gst_tag_xmp_writer_add_schema() + * gst_tag_xmp_writer_get_type() + * gst_tag_xmp_writer_has_schema() + * gst_tag_xmp_writer_remove_all_schemas() + * gst_tag_xmp_writer_remove_schema() + * gst_tag_xmp_writer_tag_list_to_xmp_buffer() + * GST_TAG_CAPTURING_EXPOSURE_COMPENSATION + * gst_video_format_get_component_depth() + * gst_video_format_new_template_caps() + +Changes since 0.10.31: + + * GLib requirement is now >= 2.22, gobject-introspection >= 0.9.12 + * New encodebin element + * New encoding profile and encoding targets API in pbutils + * audioresample: corrected buffer duration calculation to account for nonzero initial timestamp + * audioresample: provide as much valid output ts and offset as valid input + * audioresample: push half a history length, instead of a full history length, at end-of-stream + so that output segment and input segment have same duration + * decodebin2: deprecate new-decoded-pad and removed-decoded-pad signals (use "pad-added" and "pad-removed" instead) + * multifdsink: add first and last buffer's timestamp to the stats; only keep last valid timestamp + * oggdemux: extract more tags (vorbis comment headers, Kate) + * oggdemux: ignore header pages when looking for keyframe; set headers on caps + * oggdemux: fix interpretation of Theora granule position and parsing of Theora size + * oggparse: Set DELTA_UNIT on buffers + * playbin2: delay stream-changed messages, fixing KATE subtitle recognition + * textoverlay: make text, xpos, ypos, color, and silent properties controllable + * typefinding: (E)AC-3 and ISO typefinder improvements; add yuv4mpeg typefinder + * typefinding: add "stream-format" to h264 caps, and framed=false to DTS caps + * typefinding: assume EBML files without doctype are matroska + * videorate: fix behaviour for frame rate cap changes + * vorbisdec: avoid using invalid timestamps; keep timestamps when no decoded output + * ximagesink, xvimagesink: add read-only window-width and window-height properties + * baseaudiopay: fix timestamps on buffer lists + * baseaudiosink: protect against ringbuffer disappearing while in a query + * basedepay: add support for buffer lists in the depayloader + * basertppay: use RTP base time when invalid timestamps + * rtpbuffer: relax arrangement for RTP bufferlists + * rtpdepayloader: add support for getting events + * rtppayload: copy applied rate to segment + * sdp: add method to check for multicast addresses + * sdp: only parse TTL for IP4 addresses + * video: add 8-bit paletted RGB, YUV9, YVU9 and IYU1 video formats + * video: return correct component width/height for A420 + +Bugs fixed since 0.10.31: + + * 619778 : oggdemux: fails on zero-length pages with Patent_Absurdity_HD_3540kbit.ogv + * 586570 : Add GAP Flag support to audioresample + * 623413 : pbutils: Add/Fix some media descriptions + * 627476 : New profile library and encoding plugin + * 629349 : [oggdemux] extract stream tags for tagreadbin and transcoding + * 632667 : [ximagesink] added read-only properties window-width and window-height + * 634397 : [multifdsink] [PATCH] Add the timestamp of the first and last buffer to the stats + * 634522 : gst-visualize-m.m imports but doesn't use File::Basename + * 635231 : baseaudiosink: protect against ringbuffer disappearing while in a query + * 636198 : decodebin2: " removed-decoded-pad " signal never fired + * 636769 : [appsink] Flushing property is never reset + * 636827 : Usage of gst_caps_interset where gst_caps_can_intersect was intended? + * 637324 : oggdemux: unable to demux Ogg files with Skeleton in push mode + * 637377 : timeoverlay: add missing break + * 637519 : ogg: implement packet duration query for kate streams + * 637586 : playbin2 fails to recognize subtitle caps from katedec + * 637735 : [encoding-profile] automatic load/save support and registry + * 637758 : [exiftag] Generates buffers with uninitialized data during taglist- > exif buffer serialization + * 637822 : oggdemux: allocate buffers using gst_buffer_new_and_alloc + * 637927 : oggdemux: set headers on caps + * 638200 : [oggdemux] fails to playback video file + * 638276 : oggstream: when the last keyframe position is not known, do not use -1 + * 638859 : textoverlay: make misc. properties controllable + * 638901 : [encodebin] proper element documentation + * 638903 : [encodebin] missing-plugin support + * 638961 : Small configure bashism 0.10.31.2 + * 639039 : gobject-introspection: GstPbutils gir scanner fails to link with gold linker + * 639121 : oggdemux: outdated comment for gst_ogg_demux_submit_buffer() + * 639215 : examples: Allow building with newer GTK+ + * 639730 : discoverer: Validate timeouts before processing them + * 639755 : discoverer: Clean up callbacks in dispose() + * 639778 : discoverer: Drop new stream tags once preroll is done + * 639790 : [gdp] Fix metadata g_warning + * 639747 : Please export GST_TYPE_APP_STREAM_TYPE + * 553244 : theoraparse doesn't work at all (throws criticals and asserts) + + +API added since 0.10.31: + + * gst_app_stream_type_get_type() + * gst_discoverer_info_get_seekable() + * gst_encoding_audio_profile_get_type() + * gst_encoding_audio_profile_new() + * gst_encoding_container_profile_add_profile() + * gst_encoding_container_profile_contains_profile() + * gst_encoding_container_profile_get_profiles() + * gst_encoding_container_profile_get_type() + * gst_encoding_container_profile_new() + * gst_encoding_list_all_targets() + * gst_encoding_list_available_categories() + * gst_encoding_profile_find() + * gst_encoding_profile_get_description() + * gst_encoding_profile_get_format() + * gst_encoding_profile_get_input_caps() + * gst_encoding_profile_get_name() + * gst_encoding_profile_get_presence() + * gst_encoding_profile_get_preset() + * gst_encoding_profile_get_restriction() + * gst_encoding_profile_get_type() + * gst_encoding_profile_get_type_nick() + * gst_encoding_profile_is_equal() + * gst_encoding_profile_set_description() + * gst_encoding_profile_set_format() + * gst_encoding_profile_set_name() + * gst_encoding_profile_set_presence() + * gst_encoding_profile_set_preset() + * gst_encoding_profile_set_restriction() + * gst_encoding_target_add_profile() + * gst_encoding_target_get_category() + * gst_encoding_target_get_description() + * gst_encoding_target_get_name() + * gst_encoding_target_get_profile() + * gst_encoding_target_get_profiles() + * gst_encoding_target_get_type() + * gst_encoding_target_load() + * gst_encoding_target_load_from_file() + * gst_encoding_target_new() + * gst_encoding_target_save() + * gst_encoding_target_save_to_file() + * gst_encoding_video_profile_get_pass() + * gst_encoding_video_profile_get_type() + * gst_encoding_video_profile_get_variableframerate() + * gst_encoding_video_profile_new() + * gst_encoding_video_profile_set_pass() + * gst_encoding_video_profile_set_variableframerate() + * gst_base_rtp_depayload_push_list() + * gst_rtsp_url_decode_path_components() + * gst_sdp_address_is_multicast() + * gst_video_parse_caps_palette() + +Changes since 0.10.30: + + * adder: Make sure FLUSH_STOP is always sent after a flushing seek + * alsasrc, alsasink: add "card-name" property to get the card name in addition to the device name + * appsrc: don't override buffer caps if appsrc caps are NULL; fix element classification + * audioclock: add a function to invalidate the clock + * audioconvert: optimise remaining conversion code paths with Orc as well + * baseaudiosink,baseaudiosrc: post clock-provide and clock-lost messages when going from/to READY to/from PAUSED + * baseaudiosink: subtract the render_delay from our latency + * decodebin2: don't add non prerolled stream to topology + * ffmpegcolorspace: add support for A420 and fix support for 8 bit paletted RGB and IYU1 + * gnomevfsrc: set GST_PARAM_MUTABLE_READY flag on the "handle" property + * libvisual: add latency query; only drop frames that are really too old + * multifdsink: gdp protocol is deprecated. People should use gdppay instead + * oggdemux: fix seeking with negative rate with skeleton; fix wrong flowreturn handling + * pbutils: AAC profile and level detection utility functions + * pbutils: H.264 and MPEG-4 profile and level extraction utility functions + * pbutils: new GstDiscoverer utility API for extracting metadata and tags + * playbin2, decodebin2: declare stable, deprecate the old playbin/decodebin + * playbin2, uridecodebin: add property to configure ring buffer size + * rtcpbuffer: add function to manipulation the data in RTCP feedback packets + * rtpbuffer: add functions to add RFC 5285 header extensions to GstBufferLists + * rtpbuffer: add function to add RTP header extensions with a two bytes header + * rtpbuffer: add function to append RFC 5285 one byte header extensions + * rtpbuffer: add function to parse RFC 5285 header extensions + * rtpbuffer: add function to read RFC 5285 header extensions from GstBufferLists + * rtpbuffer: add function to transform a GstBuffer into a GstBufferList + * rtsp: improve rtsp timeout calculation and handling + * sdp: add methods to convert between uri and message + * tags: try ISO-8859-1 as second fallback in case WINDOWS-1252 is not supported + * tags: add many more photography/capture tags + * tags: EXIF and XMP tag handling improvements + * textoverlay: add support for NV12, NV21 and AYUV; configurable text color and position + * theoradec: expose telemetry properties only if libtheora was compiled with --enable-telemetry + * theoraenc: add support for two-pass encoding; allow change of bitrate and quality on-the-fly + * tools: standalone gst-discoverer-0.10 tool for discovering media file properties + * typefinding: detect avc1 ftyp as video/quicktime + * typefinding: export 3gp profile in caps + * typefinding: detect enhanced AC-3 + * typefinding: extend AAC typefinder to detect LOAS streams + * typefinding: fix ADTS caps stream-format detail + * typefinding: more reliable mpeg-ts typefinding + * uridecodebin: Only enable progressive downloading if the upstream duration in bytes is known + * video: add gst_video_convert_frame*() utility functions + * videorate: fixate the pixel-aspect-ratio if necessary + * videorate: mark duplicated frames with the GAP flag + * videoscale: add support for adding black borders to keep the DAR if necessary ("add-borders" property) + * videoscale: Fix caps fixating if the height is fixed but the width isn't + * videoscale: only set the PAR if the caps already had a PAR + * videoscale: refactor using more Orc code + * videotestsrc: new patterns: solid-color, ball, bar and smpte100 + * videotestsrc: add "foreground-color" and "background-color" properties, deprecate "colorspec" property + * videotestsrc: add support for UYVP format, fix NV21 rendering + * volume: use Orc to optimise many code paths + * vorbisdec: decode pending buffers upon EOS when doing reverse playback + * xoverlay: add set_window_handle() with guintptr argument, deprecate set_xwindow_id() which doesn't work on some platforms + * xoverlay: allow render rectangle coordinates to be negative + +Bugs fixed since 0.10.30: + + * 628028 : [uridecodebin] Don't enable progressive downloading for live streams + * 623846 : typefinding: add support for " enhanced ac3 " (eac3) + * 602437 : [playbin2] [gapless] Completely broken when switching between files with audio/video only + * 612264 : Notification needed when the first buffer is pushed by the basertppayloader + * 615471 : [videoscale] Interlaced handling makes output worse than no interlaced handling at all + * 616392 : videotestsrc colorspec=0/1 does not affect color-matrix in caps + * 617314 : pbutils: Add codec-specific utility functions for AAC, H.264, MPEG-4 video + * 617506 : [videoscale] Add support for adding black borders if necessary to keep the DAR + * 620291 : typefindfunctions: Export 3gp profile in caps + * 623663 : [typefinding] mpeg-ts file detected as audio/mpeg + * 623807 : [audioclock] Add gst_audio_clock_new_full() with GDestroyNotify for the user_data + * 623837 : typefind: only associate .webm with WebM + * 623918 : [typefind] Extend AAC typefinder to detect LOAS stream + * 624598 : [adder] crash in orc_sse_set_mxcsr() + * 624656 : [videoscale] UYVY scaling broken, introduces green lines + * 624919 : [videotestsrc] add solid color pattern + * 624920 : [textoverlay] configurable text color and position + * 624949 : [playbin2] declare playbin2 stable + * 625001 : [examples] Don't use GdkDraw/GdkGC + * 625118 : [playbin2] Race condition with EOS events in gapless mode + * 625944 : [pbutils] GstDiscoverer - API to discover metadata and stream information + * 626125 : [alsa] Conditional jump or move depends on uninitialised value(s) + * 626570 : [tag] Add resolution tags + * 626581 : [playbin2] regression: occasional deadlocks in streamsynchronizer + * 626621 : [playbin2] streamsynchronizer regressions + * 626629 : [ffmpegcolorspace] doesn't handle palettes any longer + * 626718 : playback: Delay usage of GstFactoryList + * 627203 : [alsa] alsasrc and alsasink should expose card name via property + * 627297 : [regression] build-failure + * 627565 : [xoverlay][win64] gulong can't hold a HANDLE + * 627768 : add NV12 support to textoverlay + * 627780 : GstClockOverlay re-renders string even if it hasn't changed, resulting in very high CPU usage. + * 627924 : riff: add support for 2vuy + * 628009 : [volume] Float processing with orc broken + * 628400 : [videorate] does not generate buffers to fill the duration of the last frame + * 628500 : videotestsrc: add moving color bars pattern + * 628747 : gst-plugins-base: unable to build because of compiler warning in libggsttag + * 629157 : Move video frame conversion from playback plugin to libgstvideo + * 629672 : gnomevfsrsrc: " handle " property should also have the GST_PARAM_MUTABLE_READY flag + * 629848 : build problem with current gtk+: implicit declaration of function 'gdk_draw_rectangle', GtkStyle' has no member named 'black_gc' + * 630303 : theoraenc: Make the bitrate/quality dynamically modifiable + * 630353 : [appsrc] Avoid losing buffers' caps + * 630440 : ringbuffer: use g_once for type-init + * 630443 : baseaudiosink: Add getter and setter for drift tolerance + * 630471 : [tag] ligatures " Œ " and " œ " are not supported in freeform strings + * 630496 : seek example: add new #define to set seek bar graininess + * 630802 : videotestsrc.c doesn't compile in Visual Studio 2008 + * 631128 : Add methods to manipulate RFC 5285 header extensions + * 631312 : [streamsynchronizer] Advancing segments too much + * 631633 : [oggdemux] fix seeking with negative rate with skeleton + * 631703 : [oggdemux] sintel ogv delay when playing + * 631756 : Fix build with glib 2.21.3 + * 631773 : [tags] Add new exif tags: sharpness, metering mode, file/capturing source + * 631774 : [xvimagesink] sets non-simple caps on pad_alloced buffer + * 632167 : [oggdemux] doesn't parse/push all headers in pull mode + * 632653 : [seek] Don't use deprecated combo box API + * 632656 : [uridecodebin] internal decodebin2 might fail to reach PLAYING in streaming case + * 632789 : [PATCH] tests/icles/: adapted test-colorkey.c and test-xoverlay.c to deprecation of gtk_widget_hide_all + * 632809 : [regression] build failure in 0.10.30.2 in tools/ + * 632988 : [discoverer] gst_caps_ref() critical for substreams of unknown streams + * 633023 : [discoverer] Add versionized gst-discoverer tool + * 633203 : Regression: streamsynchroniser + disabled deinterlacing = no DVD menu highlights/subtitles + * 633311 : discoverer: use specific types in getters, rename some boolean getters + * 633336 : [discoverer] Move documentation into the correct section + * 633455 : [rtsp] don't let the rtsp connection timeout + * 634014 : GTK+3 is a moving target, lets not compile against it by default. + * 634584 : decodebin2 docs should mention that " new-decoded-pad " signal may be emitted after " no-more-pads " + * 635067 : [*decodebin*] pad template leaked + * 635392 : Missing information on exported packages from GIRs + * 621349 : [theoraenc] Implement two-pass encoding + * 628488 : [theoradec] add properties to enable telemetry overlay + * 629746 : Enumerations have incorrect names of enum values (GEnumValue.value_name) + * 626869 : The RTP depayloader is sometimes sending partial frames down the pipeline without the DISCONT bit set + +API added since 0.10.30: + + * gst_audio_clock_invalidate() + * gst_audio_clock_new_full() + * gst_base_audio_sink_get_drift_tolerance() + * gst_base_audio_sink_set_drift_tolerance() + * gst_x_overlay_got_window_handle() + * gst_x_overlay_set_window_handle() + * GstXOverlay::set_window_handle() + * gst_codec_utils_aac_caps_set_level_and_profile() + * gst_codec_utils_aac_get_level() + * gst_codec_utils_aac_get_profile() + * gst_codec_utils_aac_get_sample_rate_from_index() + * gst_codec_utils_h264_caps_set_level_and_profile() + * gst_codec_utils_h264_get_level() + * gst_codec_utils_h264_get_profile() + * gst_codec_utils_mpeg4video_caps_set_level_and_profile() + * gst_codec_utils_mpeg4video_get_level() + * gst_codec_utils_mpeg4video_get_profile() + * gst_discoverer_audio_info_get_bitrate() + * gst_discoverer_audio_info_get_channels() + * gst_discoverer_audio_info_get_depth() + * gst_discoverer_audio_info_get_max_bitrate() + * gst_discoverer_audio_info_get_sample_rate() + * gst_discoverer_audio_info_get_type() + * gst_discoverer_container_info_get_streams() + * gst_discoverer_container_info_get_type() + * gst_discoverer_discover_uri() + * gst_discoverer_discover_uri_async() + * gst_discoverer_get_type() + * gst_discoverer_info_copy() + * gst_discoverer_info_get_audio_streams() + * gst_discoverer_info_get_container_streams() + * gst_discoverer_info_get_duration() + * gst_discoverer_info_get_misc() + * gst_discoverer_info_get_result() + * gst_discoverer_info_get_stream_info() + * gst_discoverer_info_get_stream_list() + * gst_discoverer_info_get_streams() + * gst_discoverer_info_get_tags() + * gst_discoverer_info_get_type() + * gst_discoverer_info_get_uri() + * gst_discoverer_info_get_video_streams() + * gst_discoverer_new() + * gst_discoverer_result_get_type() + * gst_discoverer_start() + * gst_discoverer_stop() + * gst_discoverer_stream_info_get_caps() + * gst_discoverer_stream_info_get_misc() + * gst_discoverer_stream_info_get_next() + * gst_discoverer_stream_info_get_previous() + * gst_discoverer_stream_info_get_stream_type_nick() + * gst_discoverer_stream_info_get_tags() + * gst_discoverer_stream_info_get_type() + * gst_discoverer_stream_info_list_free() + * gst_discoverer_video_info_get_bitrate() + * gst_discoverer_video_info_get_depth() + * gst_discoverer_video_info_get_framerate_denom() + * gst_discoverer_video_info_get_framerate_num() + * gst_discoverer_video_info_get_height() + * gst_discoverer_video_info_get_max_bitrate() + * gst_discoverer_video_info_get_par_denom() + * gst_discoverer_video_info_get_par_num() + * gst_discoverer_video_info_get_type() + * gst_discoverer_video_info_get_width() + * gst_discoverer_video_info_is_image() + * gst_discoverer_video_info_is_interlaced() + * GST_PLUGINS_BASE_VERSION_MAJOR + * GST_PLUGINS_BASE_VERSION_MINOR + * GST_PLUGINS_BASE_VERSION_MICRO + * GST_PLUGINS_BASE_VERSION_NANO + * GST_CHECK_PLUGINS_BASE_VERSION + * gst_plugins_base_version() + * gst_plugins_base_version_string() + * gst_rtcp_packet_fb_get_fci() + * gst_rtcp_packet_fb_get_fci_length() + * gst_rtcp_packet_fb_set_fci_length() + * gst_rtp_buffer_add_extension_onebyte_header() + * gst_rtp_buffer_add_extension_twobytes_header() + * gst_rtp_buffer_get_extension_onebyte_header() + * gst_rtp_buffer_get_extension_twobytes_header() + * gst_rtp_buffer_list_add_extension_onebyte_header() + * gst_rtp_buffer_list_add_extension_twobytes_header() + * gst_rtp_buffer_list_from_buffer() + * gst_rtp_buffer_list_get_extension_onebyte_header() + * gst_rtp_buffer_list_get_extension_twobytes_header() + * gst_sdp_message_as_uri() + * gst_sdp_message_parse_uri() + * GST_TAG_CAPTURING_SOURCE + * GST_TAG_CAPTURING_METERING_MODE + * GST_TAG_CAPTURING_SHARPNESS + * GST_TAG_IMAGE_HORIZONTAL_PPI + * GST_TAG_IMAGE_VERTICAL_PPI + * GST_TAG_CAPTURING_FLASH_FIRED + * GST_TAG_CAPTURING_FLASH_MODE + * GST_TAG_CAPTURING_EXPOSURE_PROGRAM + * GST_TAG_CAPTURING_EXPOSURE_MODE + * GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE + * GST_TAG_CAPTURING_GAIN_ADJUSTMENT + * GST_TAG_CAPTURING_WHITE_BALANCE + * GST_TAG_CAPTURING_CONTRAST + * GST_TAG_CAPTURING_SATURATION + * GST_TAG_CAPTURING_SHUTTER_SPEED + * GST_TAG_CAPTURING_FOCAL_RATIO + * GST_TAG_CAPTURING_FOCAL_LENGTH + * GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO + * GST_TAG_CAPTURING_ISO_SPEED + * GST_VIDEO_FORMAT_UYVP + * GST_VIDEO_FORMAT_A420 + * gst_video_convert_frame() + * gst_video_convert_frame_async() + * GstTextOverlay:xpos + * GstTextOverlay:ypos + * GstTextOverlay:color + * GstVideoTestSrc:solid-color + * GstVideoTestSrc::foreground-color + * GstVideoTestSrc::background-color + +API deprecated since 0.10.30: + + * gst_x_overlay_set_xwindow_id() + * gst_x_overlay_got_xwindow_id() + * GstXOverlay::set_xwindow_id() + +Changes since 0.10.29: + + * Use Orc (Optimized Inner Loops Runtime Compiler) for SIMD and + other optimisations, and remove liboil dependency. The main goal + for this release was to make the transition from liboil to liborc. + Performance improvements should not be expected and will be the + focus of future versions. liborc is an optional dependency for + the time being, to make it possible to test and develop the very + latest GStreamer versions on systems that don't have orc yet. + However, without orc slow unoptimised backup code will be used + for many performance critical code paths. Distributors are urged + to package and ship the latest version of liborc and compile + GStreamer modules with --enable-orc. Please do not distribute + GStreamer packages that are not orc enabled. More information on + the orc integration can be found in the docs/design/ directory. + * basertpaudiopayload: Set duration on buffers; add extra frame for non-complete frame lengths + * riff: add mappings for On2 VP8 and VP6F (On2 VP6 Flash variant) + * video: Add support for RGB/BGR with 15 and 16 bits, and Y800 and Y16 + * xmp/exif tags: add mappings for new tags (device, geo location, image orientation) + * adder, audioconvert, audioresample, volume: convert from liboil to orc + * adder: rework timestamping; only accept seek-types SEEK_NONE and SEEK_SET + * decodebin2: add "expose-all-streams" property to not expose/decode all streams + * decodebin2: use accumulator for autoplug-sort + * ffmpegcolorspace: add YUY2/YVYU to all RGB formats conversions + * ffmpegcolorspace: fix conversion of packed 4:2:2 YUV to RGB and 8 bit grayscale + * ffmpegcolorspace: fix Y16 from/to GRAY8 conversion + * ffmpegcolorspace: fix Y42B from/to YUY2/YVYU/UYVY conversion for odd widths + * ffmpegcolorspace: Map "Y8 " and "GREY" to "Y800" and add it to the template caps + * ffmpegcolorspace: negotiation speed-ups + * oggdemux: implement seeking and duration estimates when operating in push mode (http etc.) + * oggdemux: parse Skeleton index packets for better seeking in push mode + * oggdemux: fix granulepos->key granule calculation for Dirac video + * oggdemux: fix EOS flow aggregation: only EOS when all streams are EOS + * oggmux: Start a new page for every CMML buffer + * ogg: Implement Ogg VP8 mapping + * playbin2: add "av-offset" property to adjust audio/video sync + * playbin2: add flag for enabling/disabling automatic deinterlacing + * playbin2: fix race when querying duration right after preroll, by forwarding duration + query duration during group switch if no cached duration exists + * playbin2: if a text sink is provided, let subtitle parsing be done by decodebin2 if required + * playbin2: set the subtitle encoding on the decodebins again + * playsink: also expose "convert-frame" action signal and "frame" property in playsink + * playsink: reconfigure the video chain correctly when switching from a subtitle to a non-subtitle file + * playsink: Don't fail if subtitles are used but only audio is available and no visualizations + * typefinding: add WebM typefinder (was in -good before) + * typefinding: add IVF and dts typefinders, improve AC-3 and jpeg typefinding + * typefinding: detect ISO 14496-14 files as video/quicktime not audio/x-m4a + * uridecodebin: add all qtdemux types to downloadable types + * uridecodebin: add the 'expose-all-streams' property from decodebin2 + * uridecodebin: Allow video/webm for progressive downloading + * videorate, videotestsrc: fixate color-matrix, chroma-site and interlaced fields if necessary + * videoscale: Try to keep DAR when scaling + * videoscale: Add support for Y444, Y42B and Y41B and more gray formats + * videoscale: Fix resampling of ARGB scanlines + * videoscale: Try harder to keep the DAR if possible + * videoscale: Use passthrough mode if width and height are not changed + +Bugs fixed since 0.10.29: + + * 621428 : [playbin2] ghostpad with arbitrary getcaps func leads to not working srt subtitles + * 371108 : videoscale sucks at basic mathematics when it comes to PAR + * 512740 : unit test failures if compiling against installed core with installed plugins-base also present + * 605100 : GNOME Goal: Remove deprecated glib symbols + * 610866 : [playbin2] Don't fail if there are subtitles and audio but no video + * 614872 : [tag] Add basic exif support + * 614942 : playbin2: " text-sink " is supposed to handle raw subtitle data? + * 615783 : reworked timestamping in adder + * 616396 : [playbin2] might fail a duration query immediately following PAUSED state + * 616422 : playsink might not handle reconfiguring after a text enabled file correctly + * 616557 : [videorate] Add support for video/x-raw-gray + * 617636 : [rtsp] uses unicode characters in date string + * 617855 : [oggdemux] Fails to play LAC2010 videos + * 617868 : [decodebin2] Option to not expose/decode all streams + * 618324 : rtp payloader don't put the duration on their output buffers + * 618392 : [avi-demux] Gstreamer does not support 1x1 or 1xN avi files + * 618625 : lock priv mutex in appsrc when setting caps + * 619090 : [uridecodebin] caps negociation fail + * 619102 : [PATCH] WebM typefinder + * 619310 : [videorate] negotiation issue, tries to set unfixed caps on pad + * 619396 : gstreamer does not seek http streams of Ogg Vorbis and Flac audio files. + * 620136 : Orc integration + * 620140 : [gio] report out-of-space errors + * 620211 : gst-plugins-base gets confused by dual-QT system + * 620279 : [playsink] expose 'frame' property and move 'convert-frame' action from playbin2 + * 620342 : [baseaudiosink] Allocate and free the clock in state changes + * 620412 : [video] Incomplete support for 15 and 16 bit RGB and BGR formats + * 620441 : [video] Add support for Y800 and Y16 formats + * 620500 : totem won't do progressive download for flv videos + * 620720 : typefinding: Mark ISO 14496-14 files as video/quicktime + * 620939 : [oggdemux] No support for Skeleton 4.0 streams + * 621071 : [playbin2] no playback with fakesink instead of appsink as text-sink + * 621161 : autoplug-sort default callback is run last - overwrite user supplied callback result + * 621190 : video sink drops buffers if it's preceded by ffmpegcolorspace, videoscale and a capsfilter + * 621509 : [xmptag] Uses uninitialized variable + * 621572 : [videoscale] Adds horizontal green lines in bilinear mode + * 622696 : ffmpegcolorspace: Speed up caps nego by using simpler caps + * 622807 : [decodebin2] Doesn't recover properly after an error + * 622944 : Require automake 1.9 or newer for $(builddir) + * 623003 : Major problems with calls to gst_util_uint64_scale() + * 623176 : riff: matroska file with FLV4 FOURCC fails to play + * 623218 : oggdemux: Handle errors from _get_next_page in _do_seek. + * 623233 : GstNetBuffer initialization isn't thread safe. + * 623318 : [playbin2] If source setup fails the old uridecodebin is kept and breaks future playback + * 623375 : [ffmpegcolorspace] Invalid memory accesses with odd widths/height during subsampling + * 623384 : [ffmpegcolorspace] Doesn't write last pixel for odd widths in packed 4:2:2 YUV- > RGB conversion + * 623418 : [ffmpegcolorspace] Fix packed 4:2:2 YUV to 8 bit grayscale conversion for odd widths + * 623530 : [ffmpegcolorspace] Stripy pattern with videotestsrc ! ffmpegcolorspace ! ximagesink + * 623583 : [playbin2] regression: DVD playback broken + * 624266 : [playbin2] Internal uridecodebin are not properly removed in READY= > NULL + * 547603 : [playbin2] add deinterlacing support + +API added since 0.10.29: + + * GST_VIDEO_FORMAT_v308 + * GST_VIDEO_FORMAT_Y800 + * GST_VIDEO_FORMAT_Y16 + * GST_VIDEO_FORMAT_RGB16 + * GST_VIDEO_FORMAT_BGR16 + * GST_VIDEO_FORMAT_RGB15 + * GST_VIDEO_FORMAT_BGR15 + * gst_tag_image_orientation_to_exif_value () + * gst_tag_image_orientation_from_exif_value () + * gst_tag_list_to_exif_buffer () + * gst_tag_list_to_exif_buffer_with_tiff_header () + * gst_tag_list_from_exif_buffer () + * gst_tag_list_from_exif_buffer_with_tiff_header () + +Changes since 0.10.28: + + * video: add support for color-matrix and chroma-site fields in video caps and selected elements + * video: Add support for 8-bit and 16-bit grayscale formats + * typefinding: add AAC profile, level, channels and rate to ADTS caps + * tags: add basic xmp metadata support + * gio, gnomevfs: invert ranks of gio and gnomevfs elements: gio is prefered now, gnomevfs has been deprecated + * riff: add mapping for On2 VP62 and VP7 and add some more MPEG4 fourccs + * playsink: Don't fail if there are subtitles and audio but no video + * oggdemux: map old FLAC mapping correctly + * alsa: handle disappearing of sound device whilst in use more gracefully + * playbin: Only unref the volume element on dispose and when a new audio sink is set + * build: build plugin, example and libs directories in parallel if make -jN is used + * uridecodebin/playbin2: we can handle avi in download mode too + * rtsp: handle closed POST socket in tunneling, ignore unparsable ranges, allow for more ipv6 addresses + * audiopayload: add property to control packet duration + +Bugs fixed since 0.10.28: + + * 615647 : xvimagesink could miss initial expose + * 423086 : vorbisdec introduces timestamp discontinuity at the end + * 601315 : [uridecodebin] No download buffering for AVI files + * 609539 : xmp metadata support in tag library + * 609801 : [volume] Use sample accurate property values if a controller is used + * 610248 : don't poll geometry for every frame + * 610249 : [xoverlay] add set_render_rectangle() methods + * 610866 : [playbin2] Don't fail if there are subtitles and audio but no video + * 611702 : playbin2: Warning: g_object_set: assertion `G_IS_OBJECT (object)' failed with custom text sink + * 612223 : [base(audio)sink] hangs in _wait_eos + * 612312 : typefind: Post AAC profile in caps + * 612552 : Examples and tests don't compile with -DGSEAL_ENABLE + * 612783 : Warning when compiling gstsubparse.c with MSVC + * 612845 : [typefindfunctions] crash in strncasecmp() on windows + * 612968 : Add On2 VP62 and VP7 support in riff-media + * 613093 : Improper boundary condition handling in videoscale. + * 613198 : ximagesink memory leak + * 613248 : [audiopayload] add property to control packet duration + * 613281 : [PATCH] autogen.sh: Don't call configure with --enable-plugin-docs + * 613387 : [gio] compiler warning with GLib 2.18, breaks build with -Werror + * 613403 : docs: gst_x_overlay_handle_events() lacks Since: tag + * 613589 : typefind: Export AAC level in caps + * 613591 : rtspsrc doesn't parse negative port numbers + * 613690 : [xmp] refactoring to 1-n tag mappings + * 613809 : [oggdemux] flac: file does not play locally + * 614288 : Setting playbin volume has no effect the second time around + * 614545 : gstalsasrc mixer task spins 100% CPU when USB sound card is removed + * 614622 : Trying to compile and it blows up at seek + * 614764 : Compile breaks on Mac OS 10.5.8 on new jsseek example + * 615572 : Buffer Leak in audiorate during fill process + * 615697 : Problems with Makefile + * 615789 : [ximagesink] gst_ximagesink_xwindow_update_geometry: assertion `xwindow != NULL' failed + * 616545 : [ffmpegcolorspace] Crashes when converting Y41B with some width/height combinations + +API added since 0.10.28: + + * gst_x_overlay_set_render_rectangle() + * gst_tag_list_from_xmp_buffer() + * gst_tag_list_to_xmp_buffer() + * gst_video_format_is_gray() + * gst_video_parse_caps_chroma_site() + * gst_video_parse_caps_color_matrix() + * GST_VIDEO_CAPS_GRAY8 + * GST_VIDEO_CAPS_GRAY16 + * GST_TYPE_RTSP_LOWER_TRANS + * gst_rtsp_lower_trans_get_type() + +Changes since 0.10.27: + + * Ogg/Dirac fixes + * build: really dist qtgv-xoverlay.h header file needed by overlay examples this time + * rtspconnection: fix handling of x-server-ip-address + * alsasrc fixes + +Bugs fixed since 0.10.27: + + * 610832 : qtgv-xoverlay.h header file missing in the tarball + * 611900 : [oggdemux] Incorrect parsing of Dirac headers + +Changes since 0.10.26: + + * playbin2,decodebin2: lots of fixes for missing plugin installation + * playbin2, playsink, subtitleoverlay: Set subtitle encoding properly + * videorate: Improve upstream negotiation + * oggdemux: use the chain begin_time instead of our counter + * oggdemux: mark skeleton streams correctly + * oggdemux: theora PAR of 0:N, N:0 or 0:0 is allowed and maps to 1:1 + * typefinding: detect stm module format + * ffmpegcolorspace: add conversions from all ARGB formats to AYUV and back + * theoradec: Fix chroma copying for 4:2:2 + * tcpclientsrc,tcpserversrc: Fix handling of closed sockets + * examples,build: dist header file for the Qt graphics view example + * playsink: Reset the sink's state to NULL before unreffing it unless it's the same instance again + * rtspconnection: make sure not to dereference NULL username or password + * appsrc: Update segment duration and post a duration message if the duration changes + * vorbisdec: also support ivorbis tremor decoder + * rtsp: fail gracefully on bad Content-Length headers + * rtsp: ignore \n and \r as the first line + +Bugs fixed since 0.10.26: + + * 610449 : codec autodetection does not always work + * 608025 : [videorate] fails at upstream negotiation + * 608309 : [appsrc] Should request new data before the queue is empty + * 608417 : rtspsrc problem with \n and \r as first line + * 609063 : [vorbisdec] also support integer vorbis decoder (tremor) library implementation + * 609314 : typefind: Typefind does not handle .stm module format + * 609423 : [appsrc] gst_app_src_set_size() should update duration and post a duration message + * 610005 : [oggdemux] regression: bad seek granularity + * 610268 : [rtsp] NULL pointer reference in gstrtspconnection + * 610310 : [playbin2] Subtitle encoding property has no effect + * 610329 : [theoradec] doesn't copy all chroma lines for 4:2:2 + * 610379 : [playbin2] doesn't play if text flag is unset and media has text subtitles + * 610386 : [tcpserversrc] Doesn't send EOS when socket is closed + * 610672 : overlay examples are now inconsistent and broken + * 610832 : missing header file in the tarball + * 611225 : [oggdemux] doesn't preroll big_buck_bunny_427x240.indexed.ogg in push mode + * 611227 : [oggdemux] no duration or seeking in local big_buck_bunny_427x240.indexed.ogg in pull mode + * 604131 : Totem can no longer open Matroska files that hold ASS subtitles + +API added since 0.10.26: + + * appsrc::min-percent property + * GST_RIFF_TAG_JUNQ + +Changes since 0.10.25: + + * playbin2: make about-to-finish signal work for raw sources (e.g. audio CDs) + * playbin2: fix handling of the native audio/video flags + * playbin2: add flag to enable decodebin buffering + * playbin2: make subtitle error handling more robust and ignore late errors + * playbin2: improve subtitle passthrough in uridecodebin + * playbin2: new subtitleoverlay element for generic subtitle overlaying + * playbin2: proxy notify::volume and notify::mute from the volume/mute + elements (or audio sink) + * playbin2: don't stop completely on initialization errors from subtitle + elements; instead disable the subtitles and play the other + parts of the stream + * decodebin2: rewrite autoplugging and how groups of pads are exposed + * uridecodebin: add use-buffering property that will perform buffering on + parsed or demuxed media. + * GstXOverlay: flesh out docs and add example for use with Gtk+ >= 2.18 + * libgsttag: add utility functions for ISO-639 language codes and tags + * oggdemux: use internal granulepos<->timestamp mapper and make oggdemux + more like a 'normal' demuxer that outputs timestamps + * oggdemux: seeking improvements + * subparse: add qttext support + * ffmpegcolorspace: prefer transforming alpha formats to alpha formats + and the other way around + * libgstvideo: add functions to create/parse still frame events. + * theoraenc: make the default quality property 48. + * videotestsrc: add pattern with out-of-gamut colors + * theora: port to 'new' theora 1.0 API; make misc. existing properties + have no effect (quick, keyframe-mindistance, noise-sensitivity, + sharpness, keyframe_threshold); those either never worked or + aren't needed/provided/useful any longer with the newer API + * typefinding: misc. performance improvements and fixes + * baseaudiosink: make drift tolerance configurable + +Bugs fixed since 0.10.25: + + * 507131 : GStreamer does not play short ogg sounds + * 583376 : [typefind] Detects MP3 as h264 + * 344013 : [oggdemux] use parsers to suck less + * 598114 : build overwrites interfaces/interfaces-enumtypes.h with wrong enumtypes + * 344706 : [playbin] problem changing subtitles and language + * 350748 : [ffmpegcolorspace] ffmpeg colorspace should prefer RGBA over RGB + * 499181 : audiorate inserting samples (due to rounding errors ?) + * 524771 : Can't seek in YouTube videos + * 537050 : [playbin2] QOS event problems + * 542758 : [playbin2] Hangs in PLAYING forever if caps are not a subset of pad template caps + * 549254 : [playbin/decodebin] Doesn't handle pads that are added much later than the other(s) correctly + * 563828 : [decodebin2] Complains about loops in the graph when demuxer output requires another demuxer + * 568014 : oggdemux/theoradec doesn't play last video frame + * 570753 : [playbin] Support subtitle renderers additional to subtitle parsers + * 574289 : [decodebin2] race in state change to PAUSED + * 577326 : tcpclientsrc stops working if set to PLAYING, PAUSED and PLAYING again + * 579394 : [playbin2] deadlock with wavpack files: type_found - > analyze_new_pad - > no_more_pads + * 584441 : [playbin2] if suburi preroll fails with error, playback should continue + * 584987 : [playbin2] [gapless] Fire a track-changed message on track change. + * 585681 : Subtitle selector doesn't work + * 585969 : [playbin2] [gapless] Position/Duration information mismatch on track change + * 587704 : " GstDecodeBin2: This appears to be a text file " error when playing files from a samba share + * 591625 : [alsasrc] odd timestamping on start + * 591662 : [playbin2] can't handle both text subtitles and subpictures + * 591677 : Easy codec installation is not working + * 591706 : [playbin2] Support of files with subtitle subpicture streams + * 594729 : theora: Convert to libtheora 1.0 API + * 595123 : [playbin2] Should hide the difference between subtitles and subpictures + * 595401 : gobject assertion and null access to volume instance in playbin + * 595427 : avoid x event thread if not needed + * 595849 : Fix Y41B strides in videotestsrc and gstvideo + * 596159 : rtspsrc hangs when connecting over http tunneled rtsp + * 596694 : [typefind] Detects quicktime as mp3 + * 596774 : Speed up subtitle display after seek/switch + * 596981 : [audioresample] Compilation failure due to warning about use of %lu for guint64 variable + * 597537 : [streamvolume.c]The cube root function is not defined in Microsoft's CRT + * 597539 : [gststrpconnection.c] 'close' is not defined in Microsoft's CRT + * 597786 : [tag] enhance gst_tag_freeform_string_to_utf8 to handle 16-bit Unicode + * 598288 : [decodebin2] Plays a wav file but issues an error + * 598533 : [decodebin2] Post element message with the stream topology on the bus + * 598936 : DKS subtitle format + * 599105 : [baseaudiosink] Remove pulsesink < 0.10.17 hack after gst-plugins-good release + * 599154 : RtpAudioPayload can send out buffers that are not exact multiple of the frame size + * 599266 : Requires restart after installing codecs + * 599471 : uridecodebin: Store unused decodebin2 instances for further usage. + * 599649 : Support for frame-based subtitles using playbin2 and subparse + * 600027 : [playbin2,playsink] Should notify about volume/mute changes + * 600370 : [subtitleoverlay] New element to overlay video with subtitles in every supported format + * 600469 : gdpdepay: Clear adapter on flush and state change + * 600479 : Deadlock when playing movie with subtitles + * 600726 : [queue2] implement buffering-left argument to buffer messages + * 600787 : playbin2 has a problem with Ogg stream with " info " + * 600945 : silence buffers at start reusing pulsesrc + * 600948 : [uridecodebin] Improve all raw caps detection on pads + * 601104 : [cddabasesrc] always plays first track if device is specified + * 601627 : theoradec breaks timestamps + * 601772 : gst-rtsp-server crashing : bug fixed + * 601809 : seek example doesn't work with csw + * 601942 : Add a still-frame event to libgstvideo + * 602000 : [playbin2] [gapless] Does state change PLAYING- > PAUSED- > PLAYING while it should stay in PLAYING + * 602225 : Can't play another movie after using subtitles + * 602790 : New oggdemux parsers break theora/vorbis playback + * 602834 : [ffmpegcolorspace] does un-necessary conversion from RGB to ARGB + * 602924 : Text subtitle rendering regression + * 602954 : [oggdemux] can't get first chain on ogg/theora stream + * 603345 : [playbin2] textoverlay refcount issues in git + * 603357 : [subparse] support for QTtext + * 605100 : GNOME Goal: Remove deprecated glib symbols + * 605219 : Freezes nearly always when switching Audio CDs + * 605960 : new examples require GTK 2.18 + * 606050 : Implement ptime support + * 606163 : textoverlay: Ignore zero framerate + * 606687 : playbin2: can't see video after setting native flags + * 606744 : Totem fails to play video file: " Can't display both text subtitles and subpictures. " + * 606926 : Vorbis: Implement Proper Channel Orderings for 6.1 and 7.1 Configurations + * 607116 : [playbin2] no 'about-to-finish' signal with audio CDs + * 607226 : Disallow setting the playbin uri property in state > = PAUSED + * 607381 : GST_FRAMES_TO_CLOCK_TIME() GST_CLOCK_TIME_TO_FRAMES() should round result + * 607403 : rtpaudiopayload: ptime is in milli-seconds, convert to nanosecs + * 607569 : Playing a chained ogg stream from HTTP pauses or freezes between songs + * 607652 : segfault with an ogg annodex file + * 607848 : typefind wrong classifies mp4 file as mp3 + * 607870 : [oggdemux] OGM parsing broken + * 607926 : [oggdemux] regression with certain chained ogg stream + * 607929 : [oggdemux] regression: headers pushed twice at the beginnign of each stream + * 608167 : [decodebin2] Doesn't push out full topology + * 608179 : caps filter appearing after adder results in deadlock + * 608446 : [playbin2] post an error message if no URI is set + * 608484 : [playbin2] problem with redirect and reset to READY + * 608699 : [oggdemux] memory leak while demuxing + * 609252 : [theoradec] Doesn't handle unknown pixel aspect ratio properly + * 596078 : Playbin2 takes ref of audio-/video-sink parameter + * 596183 : decodebin2: Rewrite autoplugging and how groups of pads are handled + * 601480 : [playback] Update factory lists not only after going back to NULL + * 596313 : gstv4lelement.c:168: error: ‘client’ may be used uninitialized in this function + * 606949 : [playbin2] verify type of volume property before using it + +API added since 0.10.25: + + * gst_rtcp_sdes_name_to_type() + * gst_rtcp_sdes_type_to_name() + * gst_tag_get_language_name() + * gst_tag_get_language_codes() + * gst_tag_get_language_code_iso_639_1() + * gst_tag_get_language_code_iso_639_2B() + * gst_tag_get_language_code_iso_639_2T() + * gst_video_event_new_still_frame() + * gst_video_event_parse_still_frame() + +Changes since 0.10.24: + + * Add per-stream volume controls + * Theora 1.0 and Y444 and Y42B format support + * Improve audio capture timing + * GObject introspection support + * Improve audio output startup + * RTSP improvements + * Use pango-cairo instead of pangoft2 + * Allow cdda://(device#)?track URI scheme in cddabasesrc + * Support interlaced content in videoscale and ffmpegcolorspacee + * Many other bug fixes and improvements + +Bugs fixed since 0.10.24: + + * 595401 : gobject assertion and null access to volume instance in playbin + * 563828 : [decodebin2] Complains about loops in the graph when demuxer output requires another demuxer + * 591677 : Easy codec installation is not working + * 588523 : smarter sink selection in playbin2 + * 590146 : adder regressions + * 321532 : [cddabasesrc] Support device setting in cdda:// URI + * 340887 : add pangocairo textoverlay plugin. + * 397419 : [oggdemux] ogm video with subtitles stuck on first frame + * 556537 : [PATCH] typefind: more flexible MPEG4 start code recognition + * 559049 : gstcheck.c:76:F:general:test_state_changes_* failure: GST_IS_CLOCK(clock) assertion fails + * 567660 : [API] need a stream volume interface for sinks that do volume control + * 567928 : Make videorate work with a live source + * 571610 : [playbin] Scale of volume property is not documented + * 583255 : [playbin2] deadlock when disabling visualisations + * 586180 : RTSP improvements + * 588717 : [oggmux] gst_caps_unref() warning if not linked downstream + * 588761 : [videoscale] Needs special support for interlaced content + * 588915 : audioresample's output offset counter's initialization could maybe be improved + * 589095 : [appsrc] clarify documentation on caps and linkage + * 589574 : [typefind] incorrect sdp file detection + * 590243 : [videoscale] Claims to support MAX width/height + * 590425 : Slaved alsasrc clock with slave-method=re-timestamp not usable for RTP audio + * 590856 : [decodebin2] triggers assertion failure on NULL caps + * 591207 : totem does display the following subtitle srt file. + * 591357 : gst-plugins-base git won't build due to warning in gstrtspconnection.c + * 591577 : [playbin2] Incorrect error message string + * 591664 : [playbin2] after seeking, srt subtitles don't resync correctly + * 591934 : timestamp drift in audioresample + * 592544 : Remove regex.h check + * 592657 : [appsink] Blocks after entering on pause state + * 592864 : deadlocks from recent inputselector/streamselector change + * 592884 : [playbin2] g_object_get increases refcount by 2 and therefore leaves memleak + * 593035 : gdp doesn't preserve fields of the buffers put into the caps' streamheader + * 593284 : basertppayloader takes time in instance init + * 594020 : Totem don't play videos from ssh remote host + * 594094 : Playback Error playing Midi file + * 594136 : [alsasink] Regression from 0.10.23 -- element reuse doesn't work + * 594165 : [theoraenc] Implement support for new formats + * 594256 : improved slave-skew resynch mechanism + * 594258 : missing break in rtcpbuffer + * 594275 : Add cast to navigation to fix compiler warning + * 594623 : Expose playsink as a fully-fledged element + * 594732 : parse error + * 594757 : build fails due to warning in gstbasertppayload.c + * 594993 : [introspection] pkg-config file madness + * 594994 : [streamvolume] Add get_type function to the documentation + * 595454 : [cddabasesrc] uri format change breaks rhythmbox + * 545807 : [baseaudiosink] audible crack when starting the pipeline + +API added since 0.10.24: + + * gst_rtsp_connection_create_from_fd() + * gst_rtsp_connection_set_http_mode() + * gst_rtsp_watch_write_data() + * gst_rtsp_watch_send_message() + * GstBaseRTPPayload::perfect-rtptime + * GstBaseRTPAudioPayload::gst_base_rtp_audio_payload_flush() + * GstVideoSinkClass::show_frame() + * GstVideoSink:show-preroll-frame + * GST_MIXER_TRACK_READONLY + * GST_MIXER_TRACK_WRITEONLY + * GstStreamVolume interface + +Changes since 0.10.23: + + * Recognise Kate subpicture subtitles + * Support progressive download in playbin2 + * GIO improvements + * Add buffer-list support in appsink + * Add gaussian-noise mode to audiotestsrc + * bump cdparanoia req to 0.10.2 and improve caching + * Improve audio source base class + * Add frame-by-frame stepping and examples + * Extend stream-probing in decodebin2 + * Many RTSP improvements + * support for PGS subpictures + * adder improvements + * Add Y444, v210, v216 formats + * implement preset interface in vorbisenc, theoraenc, oggmux + * Improve libvisual visualisation timestamp tracking + * playbin2 enhancements: custom audiosink, subpictures, cdda + * Improvements in textrender + * Support raw YUV 4:2:2 and SIREN in RIFF + * Add 4:2:2 and 4:4:4 support to theoradec + * Many other bug-fixes and improvements + +Bugs fixed since 0.10.23: + + * 510417 : [gio] make non-experimental + * 513373 : [PATCH] [gstvorbistag] Preserve cover art in Ogg/Vorbis tags + * 529300 : [giosink] [PATCH] Allow overwrite + * 531035 : [cdparanoia] Should depend on LGPL'd version of the libra... + * 567997 : [patch] add allow-pull-scheduling property to audio sinks + * 576552 : [subparse] post GST_TAG_SUBTITLE_CODEC tags + * 577637 : [playbin2] expose temp-location property + * 579692 : mp3_type_find is over-optimistic + * 580318 : [tagdemux] drops tag events from upstream + * 581460 : [baseaudiosrc] Reusing audio source leads to null timesta... + * 581571 : ARGB and alignment added to textrender + * 582021 : autogen: libtoolize must be called before aclocal + * 582749 : uridecodebin caps property not implemented yet + * 582819 : multifdsink: add num-fds property + * 583867 : gdpdepay + identity cause failed assertions + * 584020 : [playbin2] inadvertently resets configured audio/video sinks + * 584686 : [playbin2] Need {audio,video,text}-tags-changed signals + * 585197 : [subparse] fails to detect subrip subtitles with fewer th... + * 585758 : Remove deprecated GTK+ symbols + * 585970 : gst_audioringbuffer_get_type is not thread safe + * 585994 : gst-rtsp-message doesn't support " Timestamp " filed + * 586331 : [cdparanoia] expose cd cache size parameter + * 586356 : [playbin2] use private copy of input-selector as long as ... + * 586519 : white Gaussian noise would be useful in audiotestsrc + * 587080 : rtsp fails to compile - doesn't see some ws2tcpip functions + * 587278 : Support for GstBufferList in appsink + * 587676 : Call tzset() before localtime_r(), in e.g. gst-plugins-ba... + * 587695 : Patches to add stream-status messages audio elements + * 587896 : " No stream given yet " error from giostreamsrc + * 587980 : gstchannelmix.c: protect debug code with GST_DISABLE_GST_... + * 588078 : [playbin2] Fails to go to READY again after an error + * 588205 : Pipeline with giostreamsrc will not enter playing state + * 588550 : build failure in git, missing gstinterfaces-0.10 + * 588551 : queue2: download buffering fixes + * 588724 : [vorbisdec] empty encoder string causes GStreamer + * 588746 : [audiotestsrc] Make sure tags are properly serialized in ... + * 588747 : [adder] Serialize incoming in-band events (tags) in the d... + * 588748 : [adder] Check dataflow consistency in unit tests + * 589075 : [playbin2] changing volume doesn't work after stream rest... + * 589581 : typefinder: recognise more Kate subtitle categories + * 589622 : Cannot use both playbin and input-selector + * 589663 : gstreamer asserts in gstaudiofilter + * 589797 : alsasrc does not set GstAlsaSrc- > handle to NULL after snd... + * 590470 : [typefinding] certain flac-in-ogg files not detected any ... + * 536313 : [cdda] Remove sha1 copy once we depend on glib-2.16 + * 579642 : [oggdemux] handle broken ogg/vorbis files better + * 582528 : playbin2 Audio CD playback broken since + * 583318 : Assertion from within playbin2 + * 585079 : undefined references to gst_adapter_* functions in schro + * 585708 : [adder] Wrong handling of flushing seeks + * 588218 : Siren in .wav support + * 586920 : rtsp: needs < netinet/in.h > on FreeBSD + +API added since 0.10.23: + + * GstNetAddress::gst_netaddress_to_string() + * Add gst_rtsp_watch_queue_data() + * playbin2: Add {audio,video,text}-tags-changed signals + * Add gst_color_balance_get_balance_type() + * Add gst_mixer_get_mixer_type() + +Changes since 0.10.22: + + * New navigation API to support DVD playback + * playbin2 improvements + * RTSP extensions to allow extra headers and options + * Replace audioresampler with speexresample based code + * Support interlacing flags in the gstvideo library + * Support new RIFF formats + * Improve typefinding + * Support more frame formats in videoscale + * Many other bug-fixes and improvements + +Bugs fixed since 0.10.22: + + * 577637 : [playbin2] expose temp-location property + * 580120 : [playbin2] unit test fails + * 478512 : [alsamixer] volume control slider not working + * 574962 : rhythmbox crash in flac_type_find + * 564139 : Documentation of TCP plugins + * 577436 : xvimagesink should use xcontext- > depth and not count bits... + * 350311 : [playbin2] support for subpicture subtitles + * 378094 : Enable pango elements to handle UYVY + * 543591 : Gnonlin can not play theora streams + * 553295 : [riff] fuzzed AVI file causes segfault + * 565105 : Gstreamer does not change from READY back to PAUSED in sa... + * 565777 : [riff] unrecognised video fourcc 0x10000002 for mpeg2 in avi + * 566661 : [typefind] Fall back to file extension using uri query + * 567255 : [riff] doesn't detect codec_id 0x706d as AAC (amongst other) + * 567636 : [pbutils] Missing plugins code shouldn't ask for the same... + * 567740 : bogus warning in decodebin2? + * 568482 : linking problems in gst-plugins-base + * 569655 : [ffmpegcolorspace] Add UYVY422 to GRAY8 conversion function + * 570142 : Documentation is broken for uridecodebin + * 570356 : aac typefinder failure + * 570768 : [ximagesink] wrong mouse pointer position if output windo... + * 570832 : Add flags to enhance mixer interfaces + * 571009 : [tagdemux] WMA file with id3v2 tag causes assertion to fail + * 571147 : [ffmpegcolorspace/videotestsrc] Add support for packed/pl... + * 572577 : [playbin2] deadlock on shutdown + * 572872 : [ffmpegcolorspace] Add YVYU colorspace + * 572993 : [subparse] broken libregex dependency on Windows + * 573165 : Generate additional export files for gstreamer app plugin + * 573528 : Wrong format modifier in gstgiobasesink.c + * 573529 : In gstrtspconnection.c some functions are called with wro... + * 574293 : [decodebin2] deadlock on shutdown + * 574319 : Missing HAVE_PROCESS_H in win32/common/config.h + * 574447 : gstadder.c: line 904: error C2036: 'gpointer' : unknown size + * 574939 : [typefinding] flac typefinder mis-typefinds PDFs as flac ... + * 575550 : srt subtitle file keeps playbin2 from playing + * 575638 : kissfft copyright + * 575649 : [oggdemux] duration query in time format returns true wit... + * 576019 : On Windows queue2 can't write files longer than 2-4 GiB, ... + * 576142 : [vorbisenc] Non-header output buffers have NULL caps + * 576180 : [playbin2] Uses unref'd audiosink volume if using gconfau... + * 576586 : [alsamixer] gnome-sound-properties freeze + * 577054 : [videoscale] Not valgrind clean + * 577709 : Review new navigation API + * 577827 : [appsink] Have appsink new_buffer-callback return GstFlow... + * 578583 : [PATCH] multifdsink doesn't handle sync-method=latest-key... + * 578656 : Implement upstream GstForceKeyUnit events in theoraenc + * 579129 : pkgconfig: appsrc/appsink can not be linked to uninstalled + * 579130 : app: expose trivial type macros + * 579192 : gst_rtcp_packet_get_type should not assert on packet content + * 579203 : baseaudiosink: unparenting the ringbuffer in NULL causes ... + * 579267 : [rtspconnection] g_async_queue_new_full() is GLib-2.16 AP... + * 579463 : [cddabasesrc] [cdparanoiasrc] no longer emits discid + * 579668 : audioresample fails to build with --disable-gst-debug + * 579734 : [playbin] raw_decoding_mode seems to be set unconditionally + * 579912 : [decodebin2] multiqueue is too small in time (interleave ... + * 580470 : [audioresample] causes pipelines to go out of sync and be... + * 580952 : [audioresample] bad quality/pops compared to plughw + * 581727 : [playbin2] make playsink go to PAUSED async + * 569682 : playbin2 leaks request pad from input selector + * 580020 : [vorbisenc] causes buffers to be out of segment if new se... + * 562794 : rtspsrc fails to create a socket on Win32 sometimes. + * 567396 : playbin2: DECODE_BIN_LOCK occasionally called twice withi... + * 567982 : " queued_bytes " field isn't updated while flushing the que... + * 571299 : [appsink] Handoff callback API + * 574443 : rtsp win32 - forgotten variable + * 574516 : [typefind] add typefinder for photoshop .psd files + * 574964 : gst_app_src_end_of_stream(), mutex on error return + * 575256 : rtspsrc fails to resolve hostnames + * 575588 : decodebin2 deadlock + * 576187 : [playbin2] Stalls video sink when disabling subtitles in ... + * 576188 : [playbin2] Reusing a playbin2 instance with visualization... + * 576190 : [playbin2] Deadlock when reusing playbin2 after an error + * 577288 : " Internal playbin error " when seeking to the end of files + * 577610 : RTCP feedback messages support in GstRTCPPacket + * 577794 : [playbin2] leaks elements set through properties + * 578118 : [multifdsink] add option to not resend the streamheader w... + * 578506 : Pipeline with alsasrc and alsasink cannot change state ba... + * 578942 : Missing RTSP headers related to Windows Media extension. + * 580271 : videorate: fails to clear discont flag on duplicated buffers + * 580649 : uridecodebin: bug on documentation published in website + +API added since 0.10.22: + + * GstRTSP::gst_rtsp_options_as_text() + * GstRTSPMessage::gst_rtsp_message_take_header() + * GstRTSPRange::gst_rtsp_range_to_string() + * New Navigation interface commands, queries and messages + * gst_rtsp_channel_new() + * gst_rtsp_channel_unref() + * gst_rtsp_channel_attach() + * gst_rtsp_channel_queue_message() + * gst_rtsp_connection_accept() + * GstAppSink::gst_app_sink_set_callbacks() + * GST_VIDEO_FORMAT_YVYU,GST_VIDEO_BUFFER_TFF,GST_VIDEO_BUFFER_RFF,GST_VIDEO_BUFFER_ONEFIELD + * GST_MIXER_FLAG_HAS_WHITELIST,GST_MIXER_FLAG_GROUPING,GST_MIXER_TRACK_NO_RECORD,GST_MIXER_TRACK_NO_MUTE,GST_MIXER_TRACK_WHITELIST + * GstAppSrc::emit-signals + * GstAppSrc::gst_app_src_set_emit_signals() + * GstAppSrc::gst_app_src_get_emit_signals() + * GstAppSrc::gst_app_src_set_callbacks() + * RTSP::gst_rtsp_connection_get_url() + * GstRTSPLowerTrans::GST_RTSP_LOWER_TRANS_HTTP + * RTSP:gst_rtsp_connection_set_tunneled() + * RTSP:gst_rtsp_connection_is_tunneled() + * RTSP::gst_rtsp_connection_set_ip() + * RTSP::gst_rtsp_connection_get_tunnelid() + * RTSP::gst_rtsp_connection_do_tunnel() + * RTSP::gst_rtsp_watch_reset() + +IMPORTANT NOTES + +1) Please note that decodebin2 and playbin2 API included in this release is +still considered unstable and WILL change in future releases. At this stage, +only developers or early adopters should consider using decodebin2 or playbin2 +API embodied in their signals and properties. + +Changes since 0.10.21: + + * Require gettext 0.17 + * Replace audioresample with speexresample from -bad + * Support new formats in RIFF: uncompressed RGB, WMA lossless, VP6 + * Move libgstapp and elements from -bad + * Support color-key setting and probing for Xv properties + * Improve typefinding for various formats + * Extend audio sinks for pull-mode operation + * Support for more subtitle formats + * More development on decode2bin and playbin2 + * RTP and SDP fixes + * Many bug fixes and improvements + +Bugs fixed since 0.10.21: + + * 562163 : theoraenc likely ignoring segments + * 562258 : rtspsrc element takes long time to error out if the addre... + * 561789 : [volume] deadlocks with a controller attached + * 554533 : [xvimagesink] allow setting colorkey if possible + * 567511 : colorkey in xvimagesink gets reset when element is reused + * 116051 : libresample doesn't handle > factor of 2 rate conversion + * 346218 : [audioresample] doesn't do anti aliasing + * 385061 : [audioresample?] investigate high CPU usage + * 456788 : [subparse] can't handle UTF-16 charset encoded subtitle. + * 525807 : [vorbisenc] vorbisenc has problems with a gnlsource that ... + * 546955 : gstoggmux EOS handling issue + * 549417 : [audioresample] unit test fails on 64bit linux + * 549510 : audioresample doesn't negotiate ideal caps + * 552237 : UTF-16 srt confuses gstreamer, misdetected as mp3 + * 552559 : Implementation of SLAVE_SKEW in baseaudiosrc + * 552569 : audioresample producing strange sized buffers + * 552801 : audioconvert can overflow with big audio buffers + * 554879 : Add ability to specify format for date/time display in Gs... + * 555257 : Doesn't display srt subtitles saved with BOM + * 555319 : add FFV1 fourcc to riff-media + * 555607 : subrip subtitles typefind too strict + * 555699 : [PATCH] theoradec: prefer container's pixel aspect ratio ... + * 556025 : build failure in tests/icles + * 556066 : Last byte of FLAC image buffer chopped off + * 557365 : subparse check fails + * 558124 : [PLUGIN-MOVE] Move speexresample as audioresample2 to -base + * 559111 : ALSA sink hangs on USB audio device unplug while playing + * 559478 : does not play windows media streams correctly + * 559567 : `gst_base_audio_sink_sync_latency' should call `gst_base_... + * 561436 : videorate element add image/jpeg to caps template + * 561734 : playbin2 additions + * 561780 : Playbin2 should work without volume too + * 561924 : oggdemux hangs when given corrupt input via non-seekable ... + * 562270 : build without gdk fails + * 563143 : ximagesink/xvimagesink : _alloc_buffer returns non-clean ... + * 563174 : Implement gst_rtcp_packet_remove + * 563508 : [rgvolume] Unit test fails with passthrough assertions + * 563718 : Theora check out of date + * 563904 : GNOME Goal: Clean up GLib and GTK+ includes + +API added since 0.10.21: + + * clockoverlay::time-format + * GstRingBuffer:gst_ring_buffer_activate() + * GstRingBuffer:gst_ring_buffer_is_active() + * GstRingBuffer:gst_ring_buffer_convert() + * Add GST_TYPE_BASE_AUDIO_(SRC|SINK)_SLAVE_METHOD to the public API + * gst_netaddress_get_address_bytes() + * gst_netaddress_set_address_bytes() + +Changes since 0.10.20: + + * Continue playbin2 development + * Ogg improvements - CELT support, skeleton fixes + * DVD subpicture support + * Improved audio dithering random number generator + * xvimagesink/ximagesink fixes + * Vorbis encoding and decoding fixes + * Recognise Kate subtitle streams + * Many bug-fixes and enhancements + +Bugs fixed since 0.10.20: + + * 537380 : [gnomevfssrc] Doesn't handle short reads properly + * 538656 : xvimagesink support for autofill/colorkey property + * 540334 : Build fails without X in tests/examples/seek + * 528299 : Multiple GstMixerTracks with the same label cause problem... + * 530068 : Ogg Streams with Skeleton and Granulepos > 0 do not work(... + * 537009 : playbin2 silly typo breaks signals + * 537045 : decodebin2 sometimes emits 'drained' multiple times + * 537599 : [oggdemux] skeleton streams not skipped in ogg + * 537889 : [xvimagesink] colorbalance is bad + * 538232 : vorbisenc/vorbisdec don't work with a live source + * 538663 : gdppay memleak in gst_gdp_pay_reset + * 540215 : decodebin does not insert a queue for raw data type + * 540351 : [avidemux] Doesn't know about Duck DK4 ADPCM + * 540497 : ffmpegcolorspace is returning wrong size + * 541358 : cross mingw32 gcc: getaddrinfo is not in ws2_32.dll befor... + * 544306 : rtspsrc debug=1 segfaults with some libc + * 548898 : GStreamer-CRITICAL errors on seeking beyond stream borders + * 548913 : vorbisenc being picky about rounding errors in timestamps + * 549062 : Video devices aren't updated on subsequent probing. + * 549814 : [typefind] add application/pdf typefinder + * 550582 : [oggdemux] KATE streams not recognised + * 550638 : [typefind] Recognize some jpeg2k file types + * 550656 : recognize TrueSpeech in wavparse + * 550729 : gst-plugins-base won't compile with " -pedantic " option + * 552960 : tagdemux asserts and aborts on truncated files + * 553244 : theoraparse doesn't work at all (throws criticals and ass... + +API added since 0.10.20: + + * Add "index" property to GstMixerTrack to differantiate between + multiple mixer tracks with the same label. + +Changes since 0.10.19: + + * RTP improvements + * Support digest auth for RTSP + * Additional documentation + * Support DSCP QoS in multifdsink + * Add NV12/NV21 video buffer layouts + * Video scaling now bilinear by default + * Support more than 8 channels in audio conversions + * Channel mapping fixes for audioconvert + * Improve tmplayer and sami subtitle support + * Support 1x1 pixel buffers for videoscale + * Typefinding improvements for MPEG2, musepack + * Ogg/Dirac mapping updated in oggmux + * Fixes in ogg demuxing + * audiosink synchronisation and slaving fixes + * Support muting of the audio in playbin by selecting -1 as the audio stream + * Work done on playbin2 and uridecodebin + * Improvements in the experimental GIO plugin + * decodebin fixes + * Handle GAP buffers in some places + * Various other leak and bug-fixes + +Bugs fixed since 0.10.20: + + * 526794 : [giosrc] totem doesn't work with some gvfs backends + * 510417 : [PLUGIN-MOVE] Move gio to gst-plugins-base + * 509125 : crash in CD Player: - playing CD - lowering/... + * 517813 : [audioconvert] make gap aware + * 302798 : [playbin] add mute property + * 342294 : Setting playbin property current-audio=-1 also stops the ... + * 398033 : [audioconvert] support more than 8 channels + * 419351 : [avi/a52dec] AV synchronization problems + * 467911 : [subparse] sami parser update + * 469933 : multifdsink IPv6 and diffserv TOS/TC markup + * 506659 : [textoverlay] rendering error when using non-standard widths + * 512333 : [gstvorbistag] Retrieve Ogg/Vorbis cover art as image met... + * 512382 : [playbin] race condition when pausing/playing multiple in... + * 518037 : pbutils-enumtypes.c is not included in win32/vs6/libgstpb... + * 521761 : gstaudioclock frozen the clock value until reaches latest... + * 522401 : gdpdepay doesn't validate payload CRCs + * 523993 : playbin2 blocks after a while when listening to a radio s... + * 524724 : [PATCH] [baseaudiosrc] buffer-time and latency-time do no... + * 525665 : Crash on Ogg/Vorbis with chain=NULL + * 525915 : [streamheader] Unit test fails with " gst_adapter_peek: as... + * 526173 : [typefinding] fails to detect mpeg video stream whereas m... + * 529018 : gst_ogm_parse_stream_header creates fraction value with w... + * 529500 : [videotestsrc] support for NV12 and NV21 + * 529546 : [Playbin] Memory leak in streaminfo handling + * 530068 : Ogg Streams with Skeleton and Granulepos > 0 do not work(... + * 530531 : [typefinding] bad read in mpeg_video_stream_type_find + * 530719 : gst_video_calculate_display_ratio fails when playing Ogg ... + * 530962 : [subparse] parses only every second line of TMPlayer subt... + * 532454 : [NV12/NV21] videotestsrc and ffmpegcolorspace don't play ... + * 533087 : GstRTSPTransport kept opaque in docs + * 533817 : [audioconvert] Can't use default 7 channel layout / only ... + * 534071 : Gdppay memleak + * 534331 : race in decodebin when changing states while the internal... + * 535356 : vorbisdec doesn't support 8 channels + * 536475 : gdppay memleak and possible crash + * 536521 : Refcounting errors in playbin + * 536874 : Build failure on windows + * 532166 : [ffmpegcolorspace] support NV12 format + * 533617 : [audioconvert] Produces silence when converting 1/2 chann... + * 536848 : [giosrc] Doesn't handle short reads properly + * 536849 : [giosrc] Very slow doing any playback + * 518082 : [alsamixer] playback volumes overwritten by capture volum... + * 435633 : [PATCH] videorate not (fully) segment aware; causes frame... + * 532364 : tcpclientsrc broken in 0.10.19 + * 533075 : gst_rtp_buffer_compare_seqnum doesn't do what it says + * 533265 : [cddabasesrc] Sound Juicer cut a sector when ripping a track + +API additions since 0.10.20: + + * decodebin2::sink-caps property + * giosrc::file property + * giosink::file property + * gst_base_audio_src_set_slave_method() + * gst_base_audio_src_get_slave_method() + * GstAudioClock::gst_audio_clock_reset() + * GstBaseAudioSrc:actual-buffer-time property + * GstBaseAudioSrc:actual-latency-time property + * gst_audio_check_channel_positions() + * add gst_tag_image_data_to_image_buffer() + * add gst_tag_list_add_id3_image() + * add GST_TAG_IMAGE_TYPE_NONE enum value + +Changes since 0.10.18: + + * Handle EAGAIN when polling sockets in rtspconnection + +Changes since 0.10.17: + + * Experimental GIO plugin + * Continued playbin2 development + * RTP fixes + * Better network element support on Windows + * Various other bug-fixes and improvements + +Bugs fixed since 0.10.17: + + * 509637 : [API] [basertpaudiopayload] add _set_samplebits_options() + * 510229 : [gnomevfssrc] HTTPS support + * 511478 : [rtpbuffer] add gst_rtp_buffer_set_extension_data function + * 511810 : [RTSP] Uses MT-unsafe gmtime() function + * 512899 : [alsa] gstalsasink.c:527: warning: 'snd_pcm_sw_params_set... + * 513167 : Fix compiler warning due to disabled signals in mixertrac... + * 514307 : [playbin] warning in nautilus, volume element can't be cr... + * 514623 : Ogg Theora video slow + * 514937 : Correct initialization of hints in is_multicast_address() + * 515654 : xvimagesink doesn't build with --disable-xshm + * 516246 : [alsasink] handle negative delay from snd_pcm_delay + * 517420 : typefind: add h264 elementary stream discovery + * 517991 : problems with configure file depending on GCC compiler + * 518039 : libgstrtsp MSVC 6.0 compile error + * 518162 : [subparse] handle italic text starting with " / " with Micr... + * 518940 : [playbin2] make _get_*_tags() match vfuncs prototype in c... + * 519906 : [API] add GstMixerOptions::get_values vfunc + * 519916 : [API] add mixer-changed and options-list-changed messages + * 520523 : [API] Unreviewed changes to ringbuffer API + * 521743 : libgstnetbuffer.def exports not up to date + * 522625 : [video] gst_video_format_parse_caps() broken for RGBA for... + * 523054 : gstbasesrc crashes when called from typefind helpers + * 511825 : [RTSP] compiler warning on FreeBSD + * 520300 : [alsasrc] provide-clock=false messes up buffer durations + +API added since 0.10.17: + + * GstRTPBuffer:gst_rtp_buffer_set_extension_data() + * add GST_VIDEO_FORMAT_Y41B and GST_VIDEO_FORMAT_Y42B. + * add GstMixerOptions::get_values vfunc (#519906) + * add gst_mixer_options_list_changed(), gst_mixer_mixer_changed() and + gst_mixer_message_parse_options_list_changed(). Fixes #519916. + * gst_base_rtp_audio_payload_set_samplebits_options() + * GstNetBuffer::gst_netaddress_equal + +Changes since 0.10.16: + + * Work-around ABI breakage due to unfortunate use of the + GST_DISABLE_DEPRECATED macro + * Export 2 missing functions needed for bindings in the win32 build + * Initialise the GstRingBuffer GType from a thread-safe context + +Bugs fixed since 0.10.16: + + * 511825 : [RTSP] compiler warning on FreeBSD + * 513018 : crash in Volume Control: I typed my password at t... + * 512334 : g_critical() when using GstAudioFilter & GST_DEBUG + +Changes since 0.10.15: + + * Handle newer Theora granule-pos semantics + * Introducing first alpha version playbin2 - the upcoming successor to + playbin + * Fixes in playbin handling of stream-switching + * New API for uniform handling of raw-video format buffers. + * Improvements for RTSP/RTP handling + * RIFF lib additions for VC-1 and AVC1 fourccs + * Many other bug-fixes and improvements + +Bugs fixed since 0.10.15: + + * 506132 : Review of changes in video/video.h + * 320984 : [oggdemux] cannot handle multiple chains + * 373011 : [playbin] throws error when switching off subtitles + * 436756 : Intermittent crashes in Pidgin in audioclock g_type_class... + * 462740 : [streamselector] patch to improve default stream selection + * 486840 : [alsamixer] use _all variants when setting the mixer + * 497964 : theoraenc test fails + * 498228 : gst-plugins-base-0.10.15 does not compile on FreeBSD (Gen... + * 499697 : Provide better pkg-config files + * 502497 : [subparse] SubRip subtitles starting from 0 not recognised + * 503440 : The control sockets used by gstrtspconnection.c are never... + * 503930 : [cdda] warning: 'eos' may be used uninitialized in this f... + * 506928 : [alsamixer] add " PCM " as master fall back for cards that ... + * 508138 : [decodebin] does not error out if pad activation fails + * 509762 : missing file in win32/MANIFEST + * 511274 : gst_rtp_buffer_get_extension_data is returning FALSE when... + * 496731 : [PATCH] xvimagesink leaks memory if initialization fails + * 496761 : [PATCH] RTSP message leaks memory when uninitialized + * 500763 : SIGSEGV while playing ogg audio file + +API additions since 0.10.15: + + * New GstVideoFormat API and helper functions in libgstvideo + * gst_base_audio_sink_set_provide_clock() + * gst_base_audio_sink_get_provide_clock() + * gst_base_audio_sink_set_slave_method() + * gst_base_audio_sink_get_slave_method() + * gst_base_audio_src_set_provide_clock() + * gst_base_audio_src_get_provide_clock() + +Changes since 0.10.14: + + * RTP/RTSP/RTCP/SDP support improved + * New FFT support library libgstfft, based on Kiss FFT + * New formats supported in volume and audiotestsrc + * Fixes in audiorate and videorate + * Audio capture fixes + * Playbin and decodebin fixes + * New tagdemux base class for ID3/APE style tag readers + * Fix a nasty crash in the X sinks on shutdown + * New tags supported + * Add support for multichannel WAV files. + * Preserve channel layout information when up/down-mixing. + * Many bug-fixes and improvements + +Bugs fixed since 0.10.14: + + * 475395 : decodebin2 leaks request-pads + * 475451 : [decodebin2] leaks ghostpad + * 378770 : [xvimagesink] race condition in event thread? + * 407282 : [decodebin2] autoplug-sort signal has GList ** parameter + * 430677 : [audioconvert] does not preserve channel positions when f... + * 442654 : [volume] controller bypassed by default + * 445529 : [volume] support for 24/32-bit audio/x-raw-int + * 446766 : return code for gst_base_rtp_payload_audio_handle_event() + * 451970 : Subparse requires HTML parser + * 453650 : [audiobasesrc] two alsasrcs do not work in one pipeline + * 459334 : [textoverlay] expose pango line alignment property + * 459585 : [basertpdepayload] api without namespace + * 460422 : [audiotestsrc] Add support for float and double output + * 462805 : [alsa] compilation fails with gcc 4.2 + * 462979 : Add 'silent' property to GstTimeOverlay + * 463215 : [audioconvert] compile errors + * 464320 : [PATCH] gst-plugins-base-0.14 does not build for win32 + * 464666 : [playbin] QT trailer hangs in preroll with decodebin2 + * 464690 : Add connection-speed property to uridecodebin element + * 465015 : [playbin] Not removed probes causes deadlocks in streamin... + * 465028 : some warnings with mingw + * 467667 : GST_FRAMES_TO_CLOCK_TIME() and GST_CLOCK_TIME_TO_FRAMES()... + * 468129 : [basertpaudiopayload] event handler returns the wrong value + * 468619 : New library gstfft: FFT library for integer and float typ... + * 470456 : [API] add gst_missing_*_installer_detail_new() + * 470766 : [ssaparse] line breaks in SSA subtitle parser + * 471067 : Make the SDP code useable for generating SDP descriptions + * 471194 : [rtpbuffer] RTP headers are wrong for win32 + * 473097 : [baseaudiosink] gstreamer-properties hangs when testing s... + * 474384 : gstrtsp-enumtypes.c and .h needed for win32 + * 474880 : [xvimagesink] [ximagesink] leaking buffer caps reference + * 475731 : rtspconnection is able to read incomplete messages + * 483620 : All Rtp buffers are discarded -- gst_rtp_buffer_get_payl... + * 484989 : memleak, not unrefed caps for gstbasertppayload.c + * 489010 : Please change default channel order for WAVE_EXT-less .wa... + * 491722 : [playbin] regression: crash with external subtitles + * 492098 : [GstFFT] Broken scaling + * 492114 : Build issues on Windows/MSVC + * 492306 : compilation errors with MinGW + * 492813 : Missing symbols in libgstrtp.def + * 493986 : Build issues on Windows (missing symbols) + * 494346 : pre-release vs6 patch + * 496548 : Including malloc.h breaks macos build + * 496724 : DSW file references non-existent DSP files + * 464079 : audiotestsrc doesn't respond to conversion queries properly + * 442065 : floatcast.h includes config.h and might break other apps + * 466717 : gst_event_new_new_segment_full:assertion `start < = stop' ... + * 485753 : Decodebin2 deadlocks when nulling pipeline during typefind + * 464028 : Move connection-speed from playbin to playbasebin + +API added since 0.10.14: + + * GstTagDemux base class for simple tag demuxers + * GstBaseAudioSrc::provide-clock property + * gst_rtcp_ntp_to_unix() + * gst_rtcp_unix_to_ntp() + * gst_rtp_buffer_get_header_len() + * gst_rtp_buffer_get_extension_data() + * gst_rtp_buffer_compare_seqnum() + * gst_rtp_buffer_ext_timestamp() + * gst_rtcp_packet_sdes_copy_entry() + * gst_install_plugins_supported() + * gst_missing_*_installer_detail_new() convenience API + * gst_rtsp_connection_poll() + * GstTextOverlay::line-alignment property + +Changes since 0.10.13: + + * Audio dither and noise-shaping when reducing bit-depth + * RTSP and SDP helper libraries added + * Experimental buffering element "queue2" now supports pull-mode + and file-based buffering. + * Support for more 32-bit video pixel layouts + * Various fixes and improvements + +Bugs fixed since 0.10.13: + + * 380625 : [x*imagesink] add 'handle-expose' property + * 385527 : oggmux sometimes gets DELTA flag on output wrong near start + * 402076 : videoscale 4-tap method broken for downscaling + * 437169 : [xvimagesink] add property to disable Xv double-buffering + * 441264 : queue2 support to do buffering on a file + * 442553 : [v4lsrc] doesn't output segments in GST_FORMAT_TIME + * 442557 : [videorate] doesn't handle latency queries + * 442944 : Audiotestsrc can overflow on seeks + * 444523 : [queue2] Pull mode support + * 444630 : Compilation error with fsseko (from gstqueue2.c) -- unabl... + * 445505 : [queue2] It does not work in pull mode with oggdemux + * 446551 : [queue2] Buffering is not working properly if it is set t... + * 446572 : [queue2] Division by zero + * 446972 : warning when compiling gstoggdemux.c + * 449156 : Regression in CVS for decodebin2 + * 450875 : Missing files in po/POTFILES.in + * 451707 : [tag] UTF-8 in ID3v1 tag not correctly decoded + * 451908 : [ffmpegcolorspace] regression: doesn't accept GST_VIDEO_C... + * 454264 : Playbin fails to " play " image url after a movie url + * 456656 : [API] Addition of audio buffer clipping function to gstaudio + * 460978 : gst_audio_buffer_clip outputs warnings + * 152864 : [PATCH] GstAlsaMixer doesn't support signals + * 360246 : [audioconvert] Optionally apply dithering + * 394061 : Add support for Subviewer subtitles + * 420326 : Base payloader class has wrong property types and ranges + * 451145 : [vorbisdec] errors out on 0-sized packets + * 459204 : [PATCH] [playbin] gst_play_base_bin_get_streaminfo_value_... + +API added since 0.10.13: + + * RTSP and SDP libraries added + * gst_rtsp_base64_decode_ip + * Add buffer clipping function gst_audio_buffer_clip for raw audio + buffers. Fixes #456656. + * gst_mixer_get_mixer_flags + * gst_mixer_message_parse_mute_toggled + * gst_mixer_message_parse_record_toggled + * gst_mixer_message_parse_volume_changed + * gst_mixer_message_parse_option_changed + * GstMixerMessageType + * GstMixerFlags + +Changes since 0.10.12: + * Many fixes and improvements + * RTP and RTCP support improved + +Bugs fixed since 0.10.12: + + * 339838 : [audioconvert] support floats with non-native endianness + * 393975 : closing x/xvimagesink window crashes gst-launch + * 405072 : [API] add gst_tag_freeform_string_to_utf8() + * 413799 : [subparse] add support for MPL2 format + * 414645 : GstMixerTrack should make untranslated label available + * 420079 : [audioconvert] Uses biased rounding which results in dist... + * 420578 : [subparse] add more colour map in sami parser + * 421834 : videorate breaks on dimension changes + * 423051 : Vorbis tags of type double use locale-dependent formatting + * 423055 : Verify ReplayGain vorbistag processing in libs/tag testsuite + * 425455 : Decodebin2 leaks pads + * 426250 : GstPlayBaseBin leaks streaminfo objects + * 428187 : Rtp base depayloader class doesn't send new_segment after... + * 431672 : gst_base_rtp_audio_payload_push() should take object of i... + * 432362 : [ximagesink] doesn't build if XShm is not available + * 432755 : [videorate] leaks buffer if flow != OK + * 432984 : [baseaudiosrc] misleading warning message when dropping s... + * 433888 : [theoradec] does not generate a perfect stream + * 436562 : Theoradec doesn't work well with gnonlin + * 438840 : [theoradec] does not compile with old version of libtheora + * 440997 : [gstriff] Doesn't handle width!=depth files with audio/x-... + * 441295 : audioconvert doesn't build on VS6 + * 442024 : regression in playbin buffering + * 350299 : [playbin] " Internal data flow error " opening movie with s... + * 410039 : totem crashed with SIGSEGV in new_decoded_pad_full() + * 340842 : do latency calculation for live sources + * 341078 : RB does not play beyond initially downloaded podcast file + * 414496 : [id3demux, id3v2mux] Add support for GST_TAG_MUSICBRAINZ_... + +API additions since 0.10.12: + + * add gst_tag_freeform_string_to_utf8() + * GstRTPBuffer::gst_rtp_buffer_default_clock_rate() + * GstBaseAudioSink::slave-method property + * add "min-ptime" property to RTP base audio payloader + * gst_base_rtp_audio_payload_push() + * gst_base_rtp_audio_payload_get_adapter() + * GstMixerTrack::untranslated-label property + +Changes since 0.10.11: + + * New API for on-demand plugin installation + * Xv thread-safety and configuration enhancements + * decodebin2 improvements + * Support more raw audio format conversions + * Improvements in Ogg support + * AudioFilter base class ported to 0.10 + * Fixes for subtitles + * Latency/live-playback support for Alsa + * Lots of bug fixes and improvements + +Bugs fixed since 0.10.11: + + * 398721 : No video in .ogm files with decodebin2 + * 339837 : [audioconvert] support for 64-bit float audio + * 341524 : [decodebin] can't handle decoders with always src pads wi... + * 352069 : Add de.po German translation + * 363379 : [oggmux] doesn't detect EOS on all sinkpads + * 378436 : [oggdemux] rhythmbox crash on fast clicking on rating in ... + * 380342 : Totem does not play mp3 files when lyrics are present + * 383195 : [cddabasesrc,basertpaudiopayload] compile errors with gcc... + * 383198 : totem crashed to gst_xvimagesink_update_colorbalance + * 384008 : [xvimagesink] accesses - > xwindow outside locks + * 384060 : gst_xoverlay_set_xwindow_id() causing lockups with x(v)im... + * 387138 : x input events processing in sinks with xoverlay interfac... + * 390063 : Documentation typo + * 390076 : add xv adaptor and port properties in xvimagesink element. + * 391365 : [oggdemux] internal stream error on OggFlac + * 392070 : [vorbis] GST_TAG_LOCATION not mapped + * 392393 : [API] add libgstbaseutils library for missing plugins mes... + * 396042 : mpeg4 video typefinder loops endlessly on quicktime redirect + * 396835 : audioconvert/audioresample combination causing buffer of ... + * 397673 : [patch] XIOError caught in x[v]imagesink.c + * 397810 : [typefinding] .vob file: could not determine type of stream + * 398110 : [theoraenc] GLib failed to allocate 3080991032 bytes on g... + * 399340 : Crash in the oggdemux plugin when trying to play a specia... + * 401029 : [playbin] rapidly changing visualisation freezes + * 401072 : Move libgimme-codec helper functions to GStreamer + * 402505 : visualisations don't work for some samplerates + * 407811 : decodebin2 hang on HD clip + * 409683 : Crash with Decodebin2 + * 410396 : not reading " DATE " tags from Flac files + * 410963 : Fails to build with -z defs + * 357503 : [suparse] wrong timing with microdvd subtitles + * 393310 : [pango] localtime_r does not exist in MinGW + * 397207 : Test failure w/ HP-UX 11.11 & native compiler + * 399948 : [textoverlay] leaks upstream events if textpad unlinked + * 403963 : GstAudioFilter base class broken + * 404512 : [videoscale] floating point exception on 1x1 video + * 405020 : [alsa] probing the device-name doesn't seem to work corre... + * 408278 : [videorate] memory leak + * 410772 : Crash copying a GstNetBuffer + * 401118 : [visual] error if width not a multiple of 4 + * 405451 : [alsasink] deadlocks when disconnecting USB Sounddevice + +API additions since 0.10.11: + + * GstAudioFilter + * GST_VIDEO_SINK_CAST() + * gst_pb_utils_add_codec_description_to_tag_list() + * gst_pb_utils_get_codec_description() + * gst_pb_utils_get_source_description() + * gst_pb_utils_get_sink_description() + * gst_pb_utils_get_decoder_description() + * gst_pb_utils_get_encoder_description() + * gst_pb_utils_get_element_description() + * gst_pb_utils_init() + * gst_install_plugins_context_new() + * gst_install_plugins_context_set_xid() + * gst_install_plugins_context_free() + * gst_install_plugins_async() + * gst_install_plugins_sync() + * gst_install_plugins_return_get_name() + * gst_install_plugins_installation_in_progress() + * gst_missing_uri_source_message_new() + * gst_missing_uri_sink_message_new + * gst_missing_element_message_new + * gst_missing_decoder_message_new + * gst_missing_encoder_message_new + * gst_missing_plugin_message_get_installer_detail + * gst_missing_plugin_message_get_description + * gst_is_missing_plugin_message + +Bugs fixed since 0.10.10: + + * 360552 : [riff] [avi] extracts non-UTF8 metadata + * 365501 : [x/xvimagesink] race condition when creating first image ... + * 339366 : [playbin] hangs if suburi file type cannot be determined + * 355914 : libvisual causes xvimagesink: assertion `GST_CAPS_REFCOU... + * 363118 : gst_riff_create_video_caps() should also store variant in... + * 363607 : xvimagesink xwindow_draw_border() slowness + * 336301 : [playbin] can't handle RTSP source + * 337026 : oggmux doesn't set EOS properly + * 337031 : vorbisdec outputs too much data + * 340049 : New BaseRTPAudioPayloader class to -base + * 348264 : Theora encoding, Ogg muxing don't handle discontinuities + * 354773 : xvimage assumes that XV_COLORKEY can be set in RGB888 format + * 355917 : libvisual plugin is broken + * 355935 : multifdsink doesn't allow setting maximums (soft, hard) i... + * 357038 : [ffmpegcolorspace] RGBA handling broken + * 357215 : [playbin] buffering notification not quite right yet + * 357289 : [riff] riff parser can't detect aac audio stream + * 357404 : [playbin] Linking can fail silently + * 357531 : [subparse] problem if markup is not closed + * 357577 : [playbin] regression: buffering still images broken + * 357591 : Avoid compiler warning with uclibc and -Werror + * 357613 : XvStopVideo in xvimagesink + * 357800 : [libvisual] doesn't pass audio data to libvisual 0.4.0 co... + * 359580 : tcpserversink and dataprotocol assert for multipart streams + * 361095 : Fixes compiling with forte: warning clean up (part 3) + * 361456 : [basertppayload] Memory leak + * 361634 : sink- > ringbuffer NULL in BaseAudioSink's setcaps() + * 361984 : [subparse] doesn't accept .srt file that doesn't start wi... + * 366334 : [PATCH] Windows vs8 fixes + * 368273 : Using the remove signal on multifdsink is not threadsafe + * 368310 : include file gstbasertpaudiopayload.h not included for r... + * 369482 : [typefind] MPEG system streams get recognized as mp3 files + * 370092 : [PATCH] Decodebin v2 : Implementation + * 377183 : regression: no eos when playing ogg vorbis files + * 381219 : bad debugging code left in audiorate + * 382223 : [decodebin] more delayed linking + * 382269 : Typefind detects mpeg video clip as audio/mpeg + * 335635 : Add an Ogg/Vorbis retagging element + * 341681 : [textoverlay] flickering with continuously timestamped text + * 342228 : [alsa] Recognize " Front " as a Master channel + * 357330 : [subparse] some sami parser minor but enhanced patch + * 357532 : [gsttag] vorbistag doesn't handle dates that include time... + * 359237 : [typefinding] doesn't recognize XML files shorter than 25... + * 362845 : [subparse] add support for tmplayer format + * 357977 : [videorate] new segment start is not respected + * 364812 : [PATCH] oggmux release pad does not remove pad + * 364856 : pngenc stride problems + * 372507 : Mac build fixes + +API added since 0.10.10: + + * playbin::queue-min-threshold property. + * GstVideoOrientation interface + * gst_base_rtp_depayload_push_ts + * gst_base_rtp_depayload_push + * Add dropped_buffers to multifdsink's get-stats GValueArray + * gst_ring_buffer_commit_full + +Changes since 0.10.9: + + * New elements: gdppay, gdpdepay + +Bugs fixed since 0.10.9: + + * 343787 : The adder cannot handle when multiple elements tries to l... + * 336075 : ALSA emu10k1 mixer tracks are wrongly classified as playb... + * 349105 : crash with playbin and resizing screen + * 342494 : [v4l] Query " device-name " even if device is not open + * 342680 : [adder] seeking with multiple ogg files fails to work + * 345188 : [alsa] can't handle more than 8 channels + * 347091 : converting vorbis comments to GstTagLists is lossy + * 348157 : Changed " Change Device " menu behaviour in gnome-volume-co... + * 348916 : [typefind] add multipart/x-mixed-replace typefinder + * 350157 : [riff] riff parser can't detect dts audio stream + * 350655 : [oggdemux] should process seeking queries + * 350900 : [adder] should not clamp floating point values + * 351426 : API: add gst_tag_parse_extended_comment + * 351502 : g_value_set_string leaks + * 351742 : [vorbisenc] discontinuity detection too sensitive, might ... + * 353658 : [videotestsrc] doesn't round strides correctly for YVYU + * 354594 : multifdsink doesn't work reliably with sync-method = 'nex... + * 351790 : [ogmparse] crash parsing video stream on x86-64 + * 140139 : [avidemux] can't play broken avi with ogg (not vorbis) au... + * 347783 : [PLUGIN-MOVE] GDP elements should be moved + * 347918 : Internal data flow error in udpsrc + * 349656 : jitterbuffer in GstBaseRtp fails to handle rtp seqnum rol... + * 350784 : element alsamixer doesn't respect asoundrc + * 351308 : [netbuffer] build fails with gkt-doc critical warnings + * 353234 : audiorate preserves DISCONT on buffers + * 353912 : Add cmml caps to oggmux + +API added since 0.10.9: + + * gst_rtp_buffer_get_payload_subbuffer() + * gst_tag_parse_extended_comment() + * GstPlayBin::connection-speed + * GstTheoraParse::synchronization-points + * GST_AUDIO_CHANNEL_POSITION_NONE + +Changes since 0.10.8: + + * Parallel installability with 0.8.x series + * Threadsafe design and API + * Subtitle fixes + * Support for images in tags + * Playback improvements + * Gnomevfssrc now supports burn:// uris + * Videoscale now supports more RGBA formats + * Multifdsink improvements + * Testsuite can now generate coverage information + +Bugs fixed since 0.10.8: + + * 347296 : Problems with clocks on alsasrc hangs the application + * 347295 : [vorbisdec] Pushes before being initialized + * 329798 : [playbin] doesn't always give correct error message for m... + * 342085 : [alsasink] doesn't set buffer-time correctly + * 342789 : [audioresample] doesn't clear state when stopped, causing... + * 343303 : [subparse] workaround for bad entities in sami parser + * 343385 : [gnomevfs] add support for burn:// URIs + * 343500 : [riff] gst_riff_parse_strf_vids() can't parse extra data. + * 343699 : oggmux leaks + * 344503 : [subparse] parse font face property in sami parser. + * 345131 : [PATCH] videoscale support for 32-bit RGB-formats + * 345206 : [textoverlay] crash with non-UTF8 input + * 345225 : [theoradec] Clipping for exact seeking + * 345641 : [API] [libgsttag] add enums for image tag type + * 345879 : [riff] won't play a .wmv file with WMVA video stream + * 346581 : [typefinding] recognise text/html + * 347221 : [audioconvert] channel remapping does not work right + * 347304 : Massive leaks with xvimagesink + * 346527 : alsasrc get_range does not respect requested size + +Changes since 0.10.7: + + * alsasink probing fixes + * xvimagesink error reporting fixes + * subtitle fixes + * adder fixes + * vorbis multichannel fixes + * multifdsink streamheader fixes + +Bugs fixed since 0.10.7: + + * 169936 : [subparse] support for SAMI subtitles + * 315312 : Gstreamer Xv uses RGB instead of YUV. + * 334002 : video4linux shouldn't depend on X in configure script + * 336881 : [libvisual] additional support for libvisual-0.4 + * 337544 : [xvimagesink] Internal Error when image is too large + * 339520 : [subparse] add " encoding " property + * 340909 : [alsasink] can't enable spdif output + * 341542 : some users have an assertion failed: (GST_VIDEO_SINK_WIDT... + * 341562 : audioconvert doesn't list formats in order of preference + * 341696 : audioconvert crashes if converting from a format with no ... + * 341719 : bisection algorithm in ogg doesn't bisect in some cases + * 341732 : [alsasink] doesn't query supported sample rates + * 341873 : [alsasink] minor memory leak, uses unprotected static var... + * 342143 : [subparse] sami parser needs to escape characters + * 342181 : [alsa] add property probe interface to alsasink and alsasrc + * 342268 : [playbin] add 'subtitle-encoding' property + * 342345 : [riff] Elephant's Dream AVI does not play, JUNK chunk bef... + * 342566 : Building without GTK+ fails + * 343397 : H.264/AAC movie deadlocks with totem in gstreamer code, p... + * 339935 : [adder] dead-locks when adding sink pads in PAUSED state + +Changes since 0.10.6: + + * typefind improvements + * bug-fixes in textoverlay, audioconvert, videotestsrc, + multifdsink and audio source/sink base classes + * Ice-cast metadata support has moved from gnomevfssrc to the + icydemux element in gst-plugins-good + * audioresample now supports floating point samples + * Adder element fixes. + * Fixes for network playback and audio resampling in playbin + +Bugs fixed since 0.10.6: + + * 340060 : [adder] handle newsegment events properly + * 340375 : [API 0.11] [patch] typefind to differentiate between mp4 ... + * 339405 : [textoverlay] can't display '\n' character + * 338657 : [patch] adder should send events from src-pad to all sink... + * 338919 : [patch] alsasink should also query witdh capabilities fro... + * 301759 : [audioresample] float audio support (for OSX audio sinks) + * 331901 : [videotestsrc] framerate=0/1 gives assertion error + * 333657 : Replacing icy demuxing in gnomevfssrc + * 336339 : [audioresample] should support width != 16 + * 338718 : [patch] [audioconvert] correctly clip float samples > 1.0 + * 338778 : [patch] Bad audio with ASX files + * 338991 : [patch] Videoscale doesn't pass on pixel-aspect ratio + * 339574 : [patch] Race condition in multifdsink can lead to spuriou... + * 339786 : [typefinding] wavpack typefinding doesn't always work + * 340369 : [volume element] " volume " property range insufficient + * 340379 : [playbin] doesn't insert audioresample, causes problems w... + * 340392 : Problem with internal-decodebin + * 341160 : [multifdsink] client_status enum has an uninitialized nick + * 341182 : Accessing playbin's streaminfo property from high languag... + * 341432 : [playbin] automatically get icecast metadata requiring ic... + * 341542 : some users have an assertion failed: (GST_VIDEO_SINK_WIDT... + * 341557 : Map GST_TAG_IMAGE < = > ID3v2 APIC tag + +API added since 0.10.6: + + * client-fd-removed signal added to multifdsink + * stream-info-value-array property added to playbin + * gst_video_calculate_display_ratio() in libgstvideo + +Changes since 0.10.5: + + * QoS in sinks and transform elements + * Needs GStreamer 0.10.5 for new GstBaseSink::async_playback() vmethod + * added theoraparse element + +Bugs fixed since 0.10.5: + + * 313136 : [playbin] hang while playing truncated ogg file + * 172848 : [subparse] subtitles with special chars are displayed as ... + * 305279 : [riff] uncompressed AVIs with 24bpp don't work + * 320765 : [ffmpegcolorspace] make win32+msvc compliant, don't use _... + * 323852 : Disable tests/icles on platforms that do not have X + * 325653 : build errors compiling audioresample on win32(vs7) + * 327357 : gst-plugins-base fails to compile with GCC 4.1 + * 334620 : [gnomevfssrc] fails to connect to icecast streaming servers + * 334822 : [ffmpegcolorspace] YVU9 support + * 335028 : [typefinding] ID3 v1 tag is not recognized with mp3-in-wa... + * 335365 : inefficient use of GList in gst-plugins-base + * 336190 : [gnomevfssink] should accept non-URI filenames as " location " + * 336194 : [gnomevfssrc] some minor memory leaks + * 336477 : plugins need better/univied descriptions + * 336617 : Unable to recognise MPEG TS stream + * 337548 : Memory leaks in basertpdepayload + * 337945 : [oggdemux] segment stop position ignored + * 338419 : Regression in the handling of files with multiple audio/s... + * 338897 : Videoscale crashes as part of DVD to Ogg transcoding + * 339013 : [videorate] Goes into an infinite loop + * 339047 : [riff] handle H264 fourcc in addition to h264 + * 339212 : ISO file typefinding regression + * 330748 : deadlock in base audio sink on playing- > paused state change + +Bugs fixed since 0.10.4: + + * 334216 : [gnomevfssrc] won't open some media on NFS mounts any longer + * 334226 : typefindfunctions plugin crashes on PPC on registration + +Changes since 0.10.3: + + * (Experimental) QoS support + * oggmuxer now creates 100% valid streams for Theora, Vorbis and Speex + * documentation updates + * better support for subtitles (seeking) + +Bugs fixed since 0.10.3: + + * 310202 : [subtitles] < i > < /i > tags and others should be supported i... + * 312439 : XVideo output doesn't work on remote displays (probably r... + * 321271 : audio output is truncated at EOS + * 321650 : Can't decode this ogm file + * 325732 : [oggdemux] problem when seeking to time less than 4s with... + * 325972 : [typefinding] doesn't recognise this mp3 + * 326720 : [alsasink] doesn't support more than 2 channels anymore + * 330711 : [ffmpegcolorspace] problems with palettized RGB (fencount... + * 330789 : gstbaseaudiosink causes noise on seeking + * 330888 : Fix build with gcc 2.95 (again) + * 331295 : gnomevfssink doesn't respect umask when creating files + * 331526 : 3GP type detection is too simple + * 331678 : Decodebin is not reusable within a single pipeline (as in... + * 331690 : playbin won't play my last.fm stream + * 331763 : [alsamixer] unmute sets the volume to 100% + * 331765 : [alsamixer] mixer applet slider doesn't want to move from... + * 331903 : [videorate] doesnt handle input caps of framerate=0/1 sanely + * 332778 : [ogmparse] " Already an existing pad " WARNING + * 332964 : random crashes in mp3_type_find + * 333254 : theora encoder does not set IN_CAPS flag properly + * 333352 : [gnomevfssink] reports disk full as generic error + * 333488 : Allow for palette < 256 colours in AVI files + * 333510 : [PATCH] Fix gst_pad_new_from_template (gst_static_pad_tem... + * 333545 : [riff] set depth on wma caps to make asfdemux and pitfdll... + * 333663 : [patch] unref the result of gst_pad_get_parent + * 333900 : [typefind] cannot play a particular mp3 file + * 334112 : variable not initialized + * 334129 : Disable frame dropping for now + * 317038 : use default channel layout if none is specified in multic... + * 319340 : [cdparanoia] uncorrected-error signal never fired + +API added since 0.10.3: + + * GstTextOverlay::halignment + * GstTextOverlay::valignment + +Changes since 0.10.2: + + * typefind improvements + * Ogg decoding and encoding fixes + * Improved audio and video sink classes + * Bug and leak fixes + * Improved video scaling + * On-the-fly visualisation switching + * Subtitle support + +Bugs fixed since 0.10.2: + + * 330244 : gsttextoverlay.c:895: 'struct _GstCollectData' has no mem... + * 324000 : [playbin] post error or message on unknown input + * 153004 : [typefind] can't identify mp3 file with one single mpeg f... + * 323874 : [playbin] leaks sinks and threads when using gconfaudiosink + * 324626 : ffmpegcolorspace support for fourcc " UYVY " + * 326447 : check that all elements in -base pass queries they can't ... + * 328263 : Fix build with gcc 2.95 + * 328279 : [decodebin] timeout issue when pre-rolling + * 329326 : Fix oggmux removing pads from collect pads + +Changes since 0.10.1: + + * ported gnomevfssink, cdparanoia + * New library and base class: GstCddaBaseSrc + * ported mixerutils.h + * added 'sine-tab' waveform to audiotestsrc + * added float audio to audiorate + +Bugs fixed since 0.10.1: + + * 324216 : [cdparanoia] missing patches from 0.8 + * 324696 : [videotestsrc] does not start counting the time from zero... + * 324900 : Problem compiling gst-plugins-base with Forte + * 325984 : [playbin] cannot handle sources that produce raw audio/video + * 325990 : patch videotestsrc for using glib types + * 326601 : GstRingBuffer crashes with alaw/mulaw caps + * 327114 : [theoradec] should post tags on the bus + * 327216 : vorbisdec segfaults on certain queries + +API added since 0.10.1: + + * added libgstcddabase + * added mixerutils.h + +Changes since 0.10.0: + + * Parallel installability with 0.8.x series + * Threadsafe design and API + * removed gst-launch-ext + * Ported: ogmparse + * Fixes for: subparse, xvimagesink, audioresample, videorate, decodebin + +Bugs fixed since 0.10.0: + + * 322347 : GstBaseRtpDepayload timestamps are wring + * 323900 : Basertpdepayloader lets NEWSEGMENT events through unfiltered + * 323878 : missing < string.h > inclusion (for memset & FD_ZERO) + +API added since 0.10.0: + + * GstAlsaMixer::device + * GstAlsaMixer::device-name + +Bugs fixed since 0.9.7: + + * 319172 : gstreamer-plugins-base-0.9.pc doesn't export linking flags + * 323017 : While(1) loop with sleep(0) in basertpdepayload.c + +Changes since 0.9.6: + + * Parallel installability with 0.8.x series + * Threadsafe design and API + * ximagesink and xvimagesink updates and interactive test + * added pango + * rename net to netbuffer library + * rtp element renaming + * stream selector fixes + +Bugs fixed since 0.9.6: + + * 319618 : [decodebin] some ogg videos don't play + * 320644 : RTP packetizer does't set the packet timestamps correctly + * 322388 : xvimagesink force-aspect-ratio=True always displays squar... + * 322704 : oggdemux typefind list leak + +Changes since 0.9.5: + + * Parallel installability with 0.8.x series + * Threadsafe design and API + * lots of leak fixes + * flicker-free and rewritten X sinks + * fractional framerates + * removed sinesrc, replaced by audiotestsrc + +Bugs fixed since 0.9.5: + + * 316442 : playbin should use autoaudiosink/autovideosink by default + * 318353 : [ffmpegcolorspace] forward-port fixes from 0.8 branch + * 320200 : vorbisenc: min-bitrate and max-bitrate are 1/1000 bps rat... + * 321164 : gstringbuffer stops working under load + * 321426 : ximage plugin should be renamed to ximagesink + * 321446 : sinesrc should be dropped in favour of audiotestsrc + * 321451 : GstRtpBuffer: no way to create a sub buffer with only the... + * 321816 : [API] xoverlay API to post prepare-xwindow-id message + * 321894 : vorbisenc doesn't compile + * 322117 : Rename libgsttagedit to libgsttag + +Changes since 0.9.4: + + * video caps now use a good range for framerate and w/h + * oggdemux/oggmux improvements + * playbin improvements + +Bugs fixed since 0.9.4: + + * 319110 : [PATCH] oggdemux chain finding is slow + * 320058 : playbin of a jpeg over http does not work + * 320923 : [volume] doesn't build on Solaris + * 321011 : gstbasertpdepayload doesn't send the " new segment " event ... + +Changes since 0.9.3: + + * New element: audiotestsrc + * typefind improvements + * buffer-frames removed + +Changes since 0.9.2: + + * RTP base classes + +Bugs fixed since 0.9.2: + + * 313251 : ximagesink unused functions + * 315159 : audioconvert lost 24 bit conversions in the rewrite + diff --git a/gst-plugins-base-subtitles0.10/README b/gst-plugins-base-subtitles0.10/README new file mode 100644 index 0000000..908386d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/README @@ -0,0 +1,247 @@ +WHAT IT IS +---------- + +This is GStreamer, a framework for streaming media. + +WHERE TO START +-------------- + +We have a website at +http://gstreamer.freedesktop.org/ + +You should start by going through our FAQ at +http://gstreamer.freedesktop.org/data/doc/gstreamer/head/faq/html/ + +There is more documentation; go to +http://gstreamer.freedesktop.org/documentation + +You can subscribe to our mailing lists; see the website for details. + +We track bugs in GNOME's bugzilla; see the website for details. + +You can join us on IRC - #gstreamer on irc.freenode.org + +GStreamer 0.10 series +--------------------- + +Starring + + GSTREAMER + +The core around which all other modules revolve. Base functionality and +libraries, some essential elements, documentation, and testing. + + BASE + +A well-groomed and well-maintained collection of GStreamer plug-ins and +elements, spanning the range of possible types of elements one would want +to write for GStreamer. + +And introducing, for the first time ever, on the development screen ... + + THE GOOD + + --- "Such ingratitude. After all the times I've saved your life." + +A collection of plug-ins you'd want to have right next to you on the +battlefield. Shooting sharp and making no mistakes, these plug-ins have it +all: good looks, good code, and good licensing. Documented and dressed up +in tests. If you're looking for a role model to base your own plug-in on, +here it is. + +If you find a plot hole or a badly lip-synced line of code in them, +let us know - it is a matter of honour for us to ensure Blondie doesn't look +like he's been walking 100 miles through the desert without water. + + THE UGLY + + --- "When you have to shoot, shoot. Don't talk." + +There are times when the world needs a color between black and white. +Quality code to match the good's, but two-timing, backstabbing and ready to +sell your freedom down the river. These plug-ins might have a patent noose +around their neck, or a lock-up license, or any other problem that makes you +think twice about shipping them. + +We don't call them ugly because we like them less. Does a mother love her +son less because he's not as pretty as the other ones ? No - she commends +him on his great personality. These plug-ins are the life of the party. +And we'll still step in and set them straight if you report any unacceptable +behaviour - because there are two kinds of people in the world, my friend: +those with a rope around their neck and the people who do the cutting. + + THE BAD + + --- "That an accusation?" + +No perfectly groomed moustache or any amount of fine clothing is going to +cover up the truth - these plug-ins are Bad with a capital B. +They look fine on the outside, and might even appear to get the job done, but +at the end of the day they're a black sheep. Without a golden-haired angel +to watch over them, they'll probably land in an unmarked grave at the final +showdown. + +Don't bug us about their quality - exercise your Free Software rights, +patch up the offender and send us the patch on the fastest steed you can +steal from the Confederates. Because you see, in this world, there's two +kinds of people, my friend: those with loaded guns and those who dig. +You dig. + +The Lowdown +----------- + + --- "I've never seen so many plug-ins wasted so badly." + +GStreamer Plug-ins has grown so big that it's hard to separate the wheat from +the chaff. Also, distributors have brought up issues about the legal status +of some of the plug-ins we ship. To remedy this, we've divided the previous +set of available plug-ins into four modules: + +- gst-plugins-base: a small and fixed set of plug-ins, covering a wide range + of possible types of elements; these are continuously kept up-to-date + with any core changes during the development series. + + - We believe distributors can safely ship these plug-ins. + - People writing elements should base their code on these elements. + - These elements come with examples, documentation, and regression tests. + +- gst-plugins-good: a set of plug-ins that we consider to have good quality + code, correct functionality, our preferred license (LGPL for the plug-in + code, LGPL or LGPL-compatible for the supporting library). + + - We believe distributors can safely ship these plug-ins. + - People writing elements should base their code on these elements. + +- gst-plugins-ugly: a set of plug-ins that have good quality and correct + functionality, but distributing them might pose problems. The license + on either the plug-ins or the supporting libraries might not be how we'd + like. The code might be widely known to present patent problems. + + - Distributors should check if they want/can ship these plug-ins. + - People writing elements should base their code on these elements. + +- gst-plugins-bad: a set of plug-ins that aren't up to par compared to the + rest. They might be close to being good quality, but they're missing + something - be it a good code review, some documentation, a set of tests, + a real live maintainer, or some actual wide use. + If the blanks are filled in they might be upgraded to become part of + either gst-plugins-good or gst-plugins-ugly, depending on the other factors. + + - If the plug-ins break, you can't complain - instead, you can fix the + problem and send us a patch, or bribe someone into fixing them for you. + - New contributors can start here for things to work on. + +PLATFORMS +--------- + +- Linux is of course fully supported +- FreeBSD is reported to work; other BSD's should work too +- Solaris is reported to work; a specific sunaudiosink plugin has been written +- MacOSX is reported to work; specific audio and video sinks have been written +- Windows support is experimental but improving. Output sinks have been + written but are not yet included in the code. We support + - MSys/MingW builds + - Microsoft Visual Studio 6 builds (see win32/README.txt) + +INSTALLING FROM PACKAGES +------------------------ + +You should always prefer installing from packages first. GStreamer is +well-maintained for a number of distributions, including Fedora, Debian, +Ubuntu, Mandrake, Gentoo, ... + +Only in cases where you: +- want to hack on GStreamer +- want to verify that a bug has been fixed +- do not have a sane distribution +should you choose to build from source tarballs or CVS. + +Find more information about the various packages at +http://gstreamer.freedesktop.org/download/ + +COMPILING FROM SOURCE TARBALLS +------------------------------ + +- again, make sure that you really need to install from source ! + If GStreamer is one of your first projects ever that you build from source, + consider taking on an easier project. + +- check output of ./configure --help to see if any options apply to you +- run + ./configure + make + + to build GStreamer. +- if you want to install it (not required, but what you usually want to do), run + make install + +- try out a simple test: + gst-launch -v fakesrc num_buffers=5 ! fakesink + (If you didn't install GStreamer, prefix gst-launch with tools/) + + If it outputs a bunch of messages from fakesrc and fakesink, everything is + ok. + + If it did not work, keep in mind that you might need to adjust the + PATH and/or LD_LIBRARY_PATH environment variables to make the system + find GStreamer in the prefix where you installed (by default that is /usr/local). + +- After this, you're ready to install gst-plugins, which will provide the + functionality you're probably looking for by now, so go on and read + that README. + +COMPILING FROM CVS +------------------ + +When building from CVS sources, you will need to run autogen.sh to generate +the build system files. + +You will need a set of additional tools typical for building from CVS, +including: +- autoconf +- automake +- libtool + +autogen.sh will check for recent enough versions and complain if you don't have +them. You can also specify specific versions of automake and autoconf with +--with-automake and --with-autoconf + +Check autogen.sh options by running autogen.sh --help + +autogen.sh can pass on arguments to configure - you just need to separate them +from autogen.sh with -- between the two. +prefix has been added to autogen.sh but will be passed on to configure because +some build scripts like that. + +When you have done this once, you can use autoregen.sh to re-autogen with +the last passed options as a handy shortcut. Use it. + +After the autogen.sh stage, you can follow the directions listed in +"COMPILING FROM SOURCE" + +You can also run your whole cvs stack uninstalled. The script in +the gstreamer module /docs/faq/gst-uninstalled) is helpful in setting +up your environment for this. + +PLUG-IN DEPENDENCIES AND LICENSES +--------------------------------- + +GStreamer is developed under the terms of the LGPL (see LICENSE file for +details). Some of our plug-ins however rely on libraries which are available +under other licenses. This means that if you are distributing an application +which has a non-GPL compatible license (for instance a closed-source +application) with GStreamer, you have to make sure not to distribute GPL-linked +plug-ins. + +When using GPL-linked plug-ins, GStreamer is for all practical reasons +under the GPL itself. + +HISTORY +------- + +The fundamental design comes from the video pipeline at Oregon Graduate +Institute, as well as some ideas from DirectMedia. It's based on plug-ins that +will provide the various codec and other functionality. The interface +hopefully is generic enough for various companies (ahem, Apple) to release +binary codecs for Linux, until such time as they get a clue and release the +source. diff --git a/gst-plugins-base-subtitles0.10/RELEASE b/gst-plugins-base-subtitles0.10/RELEASE new file mode 100644 index 0000000..18ef504 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/RELEASE @@ -0,0 +1,90 @@ + +Release notes for GStreamer Base Plug-ins 0.10.34 "Lemmings" + + + +The GStreamer team is proud to announce a new release +in the 0.10.x stable series of the +GStreamer Base Plug-ins. + + +The 0.10.x series is a stable series targeted at end users. +It is not API or ABI compatible with the stable 0.8.x series. +It is, however, parallel installable with the 0.8.x series. + + + +This module contains a set of reference plugins, base classes for other +plugins, and helper libraries. + +This module is kept up-to-date together with the core developments. Element +writers should look at the elements in this module as a reference for +their development. + +This module contains elements for, among others: + + device plugins: x(v)imagesink, alsa, v4lsrc, cdparanoia + containers: ogg + codecs: vorbis, theora + text: textoverlay, subparse + sources: audiotestsrc, videotestsrc, gnomevfssrc, giosrc + network: tcp + typefind functions + audio processing: audioconvert, adder, audiorate, audioresample, volume + visualisation: libvisual + video processing: ffmpegcolorspace + aggregate elements: uridecodebin, playbin2, decodebin2, decodebin, playbin, encodebin + libraries: app, audio, cdda, fft, interfaces, netbuffer, pbutils, riff, rtp, rtsp, sdp, tag, video + + +Other modules containing plug-ins are: + + +gst-plugins-good +contains a set of well-supported plug-ins under our preferred license +gst-plugins-ugly +contains a set of well-supported plug-ins, but might pose problems for + distributors +gst-plugins-bad +contains a set of less supported plug-ins that haven't passed the + rigorous quality testing we expect + + + + + +Features of this release + + * This release is identical to 0.10.33 (to keep core/base versions in sync) +There were no bugs fixed in this release + + +Download + +You can find source releases of gst-plugins-base in the download directory: +http://gstreamer.freedesktop.org/src/gst-plugins-base/ + +GStreamer Homepage + +More details can be found on the project's website: +http://gstreamer.freedesktop.org/ + +Support and Bugs + +We use GNOME's bugzilla for bug reports and feature requests: +http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer + +Developers + +GStreamer is stored in Git, hosted at git.freedesktop.org, and can be cloned from there. +Interested developers of the core library, plug-ins, and applications should +subscribe to the gstreamer-devel list. If there is sufficient interest we +will create more lists as necessary. + + +Applications + +Contributors to this release + + * Tim-Philipp Müller +  \ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/REQUIREMENTS b/gst-plugins-base-subtitles0.10/REQUIREMENTS new file mode 100644 index 0000000..e620fc6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/REQUIREMENTS @@ -0,0 +1,105 @@ +GStreamer uses a *large* array of tools and libraries, most of which are +optional. We have attempted to make sure that any code that depends on +optional libraries doesn't get built unless you have those libraries. If +you find this not to be the case, please, let us know by filing a bug +report at http://bugzilla.gnome.org/. + + +Required tools: +=============== + +An extra set of tools is required if you wish to build GStreamer out of +CVS (using autogen.sh): + +autoconf 2.52 or better +automake 1.5 +gettext 0.11.5 +libtool v1.4 or better +pkgconfig 0.9.0 or better (http://www.freedesktop.org/software/pkgconfig/) + +Required libraries: +=================== + +The core GStreamer libraries. See the gstreamer/ module in GStreamer cvs, or +the version that corresponds to this plugin release. + +Package: GStreamer +Version: 0.10.11.2 +Recommended: 0.10.latest +URL: http://gstreamer.freedesktop.org/ +DebianPackage: libgstreamer0.10-dev +Notes: The required version is updated frequently, so the version + listed in this file is often wrong. If you are compiling from CVS, + the required version is often the latest GStreamer CVS. + + +Optional libraries: +=================== + +This file lists supporting libraries for which gst-plugins-base contains +plugins, as well as their minimum version. You can find the corresponding +plugins in ext/(library) + +Package: Orc +Version: >= 0.4.5 +Recommended: 0.4.latest +URL: http://code.entropywave.com/orc +DebianPackage: liborc-0.4-dev + +Package: GTK+ +Version: >= 2.0 +Recommended: >= 2.2 +URL: http://www.gtk.org/ +DebianPackage: libgtk2.0-dev +Notes: Required by several examples + +Package: Xlib +Plugins: xvimagesink, ximagesink, v4l (v4lsrc), ximagesrc +DebianPackage: libx11-dev libxv-dev libxt-dev + +Package: Alsa +Version: >= 0.9.1 +Plugins: alsa (alsasrc, alsasink) +URL: http://www.alsa-project.org/ +DebianPackage: libasound2-dev + +Package: CDParanoia +Plugins: cdparanoia +URL: http://xiph.org/paranoia/ +DebianPackage: libcdparanoia0-dev + +Package: GnomeVFS +Version: >= 2.0 (2.4?) +Plugins: gnomevfs (gnomevfssrc) +URL: http://www.gnome.org/ +DebianPackage: libgnomevfs2-dev + +Package: libvisual +Version: >= 0.2.0 +Recommended: 0.4.0 +Plugins: libvisual +URL: http://localhost.nl/~synap/libvisual-wiki/index.php/Main_Page +DebianPackage: libvisual0.4-dev + +Package: Ogg +Version: >= 1.0 +Plugins: ogg (oggdemux, oggmux) +URL: http://xiph.org/ogg/ +DebianPackage: libogg-dev + +Package: Pango +Plugins: pango +DebianPackage: libpango1.0-dev +URL: http://www.pango.org/ + +Package: Theora +Plugins: theora (theoradec, theoraenc) +URL: http://www.theora.org/ +DebianPackage: libtheora-dev + +Package: Vorbis +Plugins: vorbis (vorbisdec, vorbisenc) +DebianPackage: libvorbis-dev +URL: http://www.vorbis.com/ + + diff --git a/gst-plugins-base-subtitles0.10/android/NOTICE b/gst-plugins-base-subtitles0.10/android/NOTICE new file mode 100644 index 0000000..eb685a5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/NOTICE @@ -0,0 +1,481 @@ + GNU LIBRARY GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, 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 library GPL. It is + numbered 2 because it goes with version 2 of the ordinary GPL.] + + 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 Library General Public License, applies to some +specially designated Free Software Foundation software, and to any +other libraries whose authors decide to use it. You can use it for +your libraries, too. + + When we speak of free software, we are referring to freedom, 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 or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the 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 a program 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. + + Our method of protecting your rights has two steps: (1) copyright +the library, and (2) offer you this license which gives you legal +permission to copy, distribute and/or modify the library. + + Also, for each distributor's protection, we want to make certain +that everyone understands that there is no warranty for this free +library. If the library is modified by someone else and passed on, we +want its recipients to know that what they have is not the original +version, so that any problems introduced by others will not reflect on +the original authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that companies distributing free +software will individually obtain patent licenses, thus in effect +transforming the program into proprietary software. To prevent this, +we have made it clear that any patent must be licensed for everyone's +free use or not licensed at all. + + Most GNU software, including some libraries, is covered by the ordinary +GNU General Public License, which was designed for utility programs. This +license, the GNU Library General Public License, applies to certain +designated libraries. This license is quite different from the ordinary +one; be sure to read it in full, and don't assume that anything in it is +the same as in the ordinary license. + + The reason we have a separate public license for some libraries is that +they blur the distinction we usually make between modifying or adding to a +program and simply using it. Linking a program with a library, without +changing the library, is in some sense simply using the library, and is +analogous to running a utility program or application program. However, in +a textual and legal sense, the linked executable is a combined work, a +derivative of the original library, and the ordinary General Public License +treats it as such. + + Because of this blurred distinction, using the ordinary General +Public License for libraries did not effectively promote software +sharing, because most developers did not use the libraries. We +concluded that weaker conditions might promote sharing better. + + However, unrestricted linking of non-free programs would deprive the +users of those programs of all benefit from the free status of the +libraries themselves. This Library General Public License is intended to +permit developers of non-free programs to use free libraries, while +preserving your freedom as a user of such programs to change the free +libraries that are incorporated in them. (We have not seen how to achieve +this as regards changes in header files, but we have achieved it as regards +changes in the actual functions of the Library.) The hope is that this +will lead to faster development of free libraries. + + 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, while the latter only +works together with the library. + + Note that it is possible for a library to be covered by the ordinary +General Public License rather than by this special one. + + GNU LIBRARY GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library which +contains a notice placed by the copyright holder or other authorized +party saying it may be distributed under the terms of this Library +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 compile 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) 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. + + c) 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. + + d) 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 source code 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 to +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 Library 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 + + Appendix: 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 Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +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/gst-plugins-base-subtitles0.10/android/alsa.mk b/gst-plugins-base-subtitles0.10/android/alsa.mk new file mode 100644 index 0000000..c67a1df --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/alsa.mk @@ -0,0 +1,50 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +alsa_LOCAL_SRC_FILES:= \ + ext/alsa/gstalsadeviceprobe.c \ + ext/alsa/gstalsamixer.c \ + ext/alsa/gstalsamixerelement.c \ + ext/alsa/gstalsamixertrack.c \ + ext/alsa/gstalsamixeroptions.c \ + ext/alsa/gstalsaplugin.c \ + ext/alsa/gstalsasink.c \ + ext/alsa/gstalsasrc.c \ + ext/alsa/gstalsa.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(alsa_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libdl \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstinterfaces-0.10 \ + libgstaudio-0.10 + +LOCAL_MODULE:= libgstalsa + +LOCAL_WHOLE_STATIC_LIBRARIES := libasound + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 + + +$(TARGET_OUT)/lib/libgstalsa.so: + +ALL_PREBUILT += $(TARGET_OUT)/lib/libgstalsa.so + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/app.mk b/gst-plugins-base-subtitles0.10/android/app.mk new file mode 100644 index 0000000..88dfb7d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/app.mk @@ -0,0 +1,43 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_app_COPY_HEADERS_TO := gstreamer-0.10/gst/app +gst_app_COPY_HEADERS := \ + ../gst-libs/gst/app/gstappbuffer.h \ + ../gst-libs/gst/app/gstappsink.h \ + ../gst-libs/gst/app/gstappsrc.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +app_LOCAL_SRC_FILES_BASE:= \ + gst-libs/gst/app/gstappsrc.c \ + gst-libs/gst/app/gstappbuffer.c \ + gst-libs/gst/app/gstappsink.c \ + gst-libs/gst/app/gstapp-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(app_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstapp-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_app_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_app_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/app_plugin.mk b/gst-plugins-base-subtitles0.10/android/app_plugin.mk new file mode 100644 index 0000000..8e067fc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/app_plugin.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +app_plugin_LOCAL_SRC_FILES:= \ + gst/app/gstapp.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(app_plugin_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstapp-0.10 + +LOCAL_MODULE:= libgstapp + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/audio.mk b/gst-plugins-base-subtitles0.10/android/audio.mk new file mode 100644 index 0000000..fa24286 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/audio.mk @@ -0,0 +1,63 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_audio_COPY_HEADERS_TO := gstreamer-0.10/gst/audio +gst_audio_COPY_HEADERS_BASE := \ + gst-libs/gst/audio/audio.h \ + gst-libs/gst/audio/gstaudioclock.h \ + gst-libs/gst/audio/gstaudiofilter.h \ + gst-libs/gst/audio/gstaudiosink.h \ + gst-libs/gst/audio/gstaudiosrc.h \ + gst-libs/gst/audio/gstbaseaudiosink.h \ + gst-libs/gst/audio/gstbaseaudiosrc.h \ + gst-libs/gst/audio/gstringbuffer.h \ + gst-libs/gst/audio/mixerutils.h \ + gst-libs/gst/audio/multichannel.h \ + gst-libs/gst/audio/audio-enumtypes.h + +gst_audio_COPY_HEADERS := $(addprefix ../,$(gst_audio_COPY_HEADERS_BASE)) \ + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +# TODO: mixerutils.c is removed, because it depends on gst-lib/gst/interface. +# We need add it later +audio_LOCAL_SRC_FILES_BASE:= \ + gst-libs/gst/audio/audio.c \ + gst-libs/gst/audio/gstaudioclock.c \ + gst-libs/gst/audio/mixerutils.c \ + gst-libs/gst/audio/multichannel.c \ + gst-libs/gst/audio/gstaudiofilter.c \ + gst-libs/gst/audio/gstaudiosink.c \ + gst-libs/gst/audio/gstaudiosrc.c \ + gst-libs/gst/audio/gstbaseaudiosink.c \ + gst-libs/gst/audio/gstbaseaudiosrc.c \ + gst-libs/gst/audio/gstringbuffer.c \ + gst-libs/gst/audio/audio-enumtypes.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(audio_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstinterfaces-0.10 + +LOCAL_MODULE:= libgstaudio-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_audio_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_audio_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/audioconvert.mk b/gst-plugins-base-subtitles0.10/android/audioconvert.mk new file mode 100644 index 0000000..015f39c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/audioconvert.mk @@ -0,0 +1,40 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +audioconvert_LOCAL_SRC_FILES:= \ + gst/audioconvert/gstaudioconvert.c \ + gst/audioconvert/audioconvert.c \ + gst/audioconvert/gstaudioconvertorc-dist.c \ + gst/audioconvert/gstchannelmix.c \ + gst/audioconvert/gstaudioquantize.c \ + gst/audioconvert/plugin.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(audioconvert_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstaudio-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstaudioconvert + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/audioresample.mk b/gst-plugins-base-subtitles0.10/android/audioresample.mk new file mode 100644 index 0000000..8421511 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/audioresample.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +audioresample_LOCAL_SRC_FILES:= \ + gst/audioresample/gstaudioresample.c \ + gst/audioresample/resample.c \ + gst/audioresample/speex_resampler_float.c \ + gst/audioresample/speex_resampler_double.c + +audioresample_C_INCLUDES := $(LOCAL_PATH)/ \ + +LOCAL_SRC_FILES := $(addprefix ../,$(audioresample_LOCAL_SRC_FILES)) +LOCAL_C_INCLUDES := $(audioresample_C_INCLUDES) + +LOCAL_SHARED_LIBRARIES := \ + libgstaudio-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstaudioresample + +LOCAL_CFLAGS := -DFLOATING_POINT -DOUTSIDE_SPEEX -DRANDOM_PREFIX=gst -DDISABLE_ORC -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +LOCAL_PRELINK_MODULE := false + +#It's a gstreamer plugin so it should be installed in /lib/gstreamer-0.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/audiotestsrc.mk b/gst-plugins-base-subtitles0.10/android/audiotestsrc.mk new file mode 100644 index 0000000..06a76c3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/audiotestsrc.mk @@ -0,0 +1,35 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +audiotestsrc_LOCAL_SRC_FILES:= \ + gst/audiotestsrc/gstaudiotestsrc.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(audiotestsrc_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstcontroller-0.10 \ + libgstaudio-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstaudiotestsrc + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/decodebin.mk b/gst-plugins-base-subtitles0.10/android/decodebin.mk new file mode 100644 index 0000000..2d20164 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/decodebin.mk @@ -0,0 +1,35 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +decodebin_LOCAL_SRC_FILES_BASE:= \ + gst/playback/gstdecodebin.c \ + gst/playback/gstplay-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(decodebin_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstdecodebin + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/decodebin2.mk b/gst-plugins-base-subtitles0.10/android/decodebin2.mk new file mode 100644 index 0000000..30f0ace --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/decodebin2.mk @@ -0,0 +1,37 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +decodebin2_LOCAL_SRC_FILES_BASE:= \ + gst/playback/gstdecodebin2.c \ + gst/playback/gsturidecodebin.c \ + gst/playback/gstplay-enum.c \ + gst/playback/gstplay-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(decodebin2_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstdecodebin2 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/ffmpegcolorspace.mk b/gst-plugins-base-subtitles0.10/android/ffmpegcolorspace.mk new file mode 100644 index 0000000..c197a64 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/ffmpegcolorspace.mk @@ -0,0 +1,40 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +ffmpegcolorspace_LOCAL_SRC_FILES:= \ + gst/ffmpegcolorspace/gstffmpegcolorspace.c \ + gst/ffmpegcolorspace/gstffmpegcodecmap.c \ + gst/ffmpegcolorspace/dsputil.c \ + gst/ffmpegcolorspace/imgconvert.c \ + gst/ffmpegcolorspace/mem.c \ + gst/ffmpegcolorspace/utils.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(ffmpegcolorspace_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstvideo-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstffmpegcolorspace + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/gdp.mk b/gst-plugins-base-subtitles0.10/android/gdp.mk new file mode 100644 index 0000000..156bf28 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/gdp.mk @@ -0,0 +1,36 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +gdp_LOCAL_SRC_FILES:= \ + gst/gdp/gstgdp.c \ + gst/gdp/gstgdppay.c \ + gst/gdp/gstgdpdepay.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(gdp_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstdataprotocol-0.10 + +LOCAL_MODULE:= libgstgdp + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/interfaces.mk b/gst-plugins-base-subtitles0.10/android/interfaces.mk new file mode 100644 index 0000000..61564b3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/interfaces.mk @@ -0,0 +1,70 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_interfaces_COPY_HEADERS_TO := gstreamer-0.10/gst/interfaces +gst_interfaces_COPY_HEADERS_BASE := \ + gst-libs/gst/interfaces/colorbalance.h \ + gst-libs/gst/interfaces/colorbalancechannel.h \ + gst-libs/gst/interfaces/mixer.h \ + gst-libs/gst/interfaces/mixeroptions.h \ + gst-libs/gst/interfaces/mixertrack.h \ + gst-libs/gst/interfaces/navigation.h \ + gst-libs/gst/interfaces/propertyprobe.h \ + gst-libs/gst/interfaces/streamvolume.h \ + gst-libs/gst/interfaces/tuner.h \ + gst-libs/gst/interfaces/tunerchannel.h \ + gst-libs/gst/interfaces/tunernorm.h \ + gst-libs/gst/interfaces/videoorientation.h \ + gst-libs/gst/interfaces/xoverlay.h \ + gst-libs/gst/interfaces/interfaces-enumtypes.h + +gst_interfaces_COPY_HEADERS := $(addprefix ../,$(gst_interfaces_COPY_HEADERS_BASE)) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +interfaces_LOCAL_SRC_FILES_BASE:= \ + gst-libs/gst/interfaces/colorbalance.c \ + gst-libs/gst/interfaces/colorbalancechannel.c \ + gst-libs/gst/interfaces/mixer.c \ + gst-libs/gst/interfaces/mixeroptions.c \ + gst-libs/gst/interfaces/mixertrack.c \ + gst-libs/gst/interfaces/navigation.c \ + gst-libs/gst/interfaces/propertyprobe.c \ + gst-libs/gst/interfaces/streamvolume.c \ + gst-libs/gst/interfaces/tuner.c \ + gst-libs/gst/interfaces/tunernorm.c \ + gst-libs/gst/interfaces/tunerchannel.c \ + gst-libs/gst/interfaces/videoorientation.c \ + gst-libs/gst/interfaces/xoverlay.c \ + gst-libs/gst/interfaces/interfaces-marshal.c \ + gst-libs/gst/interfaces/interfaces-enumtypes.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(interfaces_LOCAL_SRC_FILES_BASE)) \ + $(addprefix ../android/,$(interfaces_LOCAL_SRC_FILES_ANDROID)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstinterfaces-0.10 + + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_interfaces_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_interfaces_COPY_HEADERS) + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/netbuffer.mk b/gst-plugins-base-subtitles0.10/android/netbuffer.mk new file mode 100644 index 0000000..fd904bd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/netbuffer.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_netbuffer_COPY_HEADERS_TO := gstreamer-0.10/gst/netbuffer +gst_netbuffer_COPY_HEADERS := \ + ../gst-libs/gst/netbuffer/gstnetbuffer.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +netbuffer_LOCAL_SRC_FILES:= \ + gst-libs/gst/netbuffer/gstnetbuffer.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(netbuffer_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstnetbuffer-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_netbuffer_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_netbuffer_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/pbutils.mk b/gst-plugins-base-subtitles0.10/android/pbutils.mk new file mode 100644 index 0000000..a9aebac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/pbutils.mk @@ -0,0 +1,68 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +GST_PBUTILS_DIR := gst-libs/gst/pbutils/ + +gst_pbutils_COPY_HEADERS_TO := gstreamer-0.10/gst/pbutils +gst_pbutils_COPY_HEADERS_BASE := \ + gst-libs/gst/pbutils/descriptions.h \ + gst-libs/gst/pbutils/install-plugins.h \ + gst-libs/gst/pbutils/missing-plugins.h \ + gst-libs/gst/pbutils/pbutils.h \ + gst-libs/gst/pbutils/pbutils-enumtypes.h + +gst_pbutils_COPY_HEADERS := $(addprefix ../,$(gst_pbutils_COPY_HEADERS_BASE)) + + + + +LOCAL_ARM_MODE := arm + +BUILT_SOURCES = \ + pbutils-enumtypes.c \ + pbutils-enumtypes.h \ + pbutils-marshal.c \ + pbutils-marshal.h + +LOCAL_SRC_FILES := \ + gstpluginsbaseversion.c \ + pbutils.c \ + codec-utils.c \ + descriptions.c \ + encoding-profile.c \ + encoding-target.c \ + install-plugins.c \ + missing-plugins.c \ + gstdiscoverer.c \ + gstdiscoverer-types.c \ + pbutils-enumtypes.c \ + pbutils-marshal.c + +LOCAL_SRC_FILES := $(addprefix ../$(GST_PBUTILS_DIR),$(LOCAL_SRC_FILES)) + +$(BUILT_SOURCES): + make -C $(GST_PLUGINS_BASE_TOP)/$(GST_PBUTILS_DIR) $@ + + +LOCAL_SHARED_LIBRARIES := \ + libgstvideo-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstpbutils-0.10 +LOCAL_CFLAGS := -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_pbutils_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_pbutils_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/playbin.mk b/gst-plugins-base-subtitles0.10/android/playbin.mk new file mode 100644 index 0000000..e792429 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/playbin.mk @@ -0,0 +1,45 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm +playbin_LOCAL_SRC_FILES_BASE:= \ + gst/playback/gstplayback.c \ + gst/playback/gstplaybin.c \ + gst/playback/gstplaybin2.c \ + gst/playback/gstplaysink.c \ + gst/playback/gstplaybasebin.c \ + gst/playback/gstplay-enum.c \ + gst/playback/gststreaminfo.c \ + gst/playback/gststreamselector.c \ + gst/playback/gstsubtitleoverlay.c \ + gst/playback/gststreamsynchronizer.c \ + gst/playback/gstplay-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(playbin_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 \ + libgstinterfaces-0.10 \ + libgstvideo-0.10 + +LOCAL_MODULE:= libgstplaybin + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/queue2.mk b/gst-plugins-base-subtitles0.10/android/queue2.mk new file mode 100644 index 0000000..6c5fcd4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/queue2.mk @@ -0,0 +1,35 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +queue2_LOCAL_SRC_FILES_BASE:= \ + gst/playback/gstqueue2.c \ + gst/playback/gstplay-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(queue2_LOCAL_SRC_FILES_BASE)) + + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstqueue2 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/riff.mk b/gst-plugins-base-subtitles0.10/android/riff.mk new file mode 100644 index 0000000..759bdad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/riff.mk @@ -0,0 +1,45 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_riffs_COPY_HEADERS_TO := gstreamer-0.10/gst/riff +gst_riffs_COPY_HEADERS := \ + ../gst-libs/gst/riff/riff-ids.h \ + ../gst-libs/gst/riff/riff-media.h \ + ../gst-libs/gst/riff/riff-read.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +riff_LOCAL_SRC_FILES:= \ + gst-libs/gst/riff/riff.c \ + gst-libs/gst/riff/riff-media.c \ + gst-libs/gst/riff/riff-read.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(riff_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgsttag-0.10 \ + libgstaudio-0.10 + + +LOCAL_MODULE:= libgstriff-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_riffs_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_riffs_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/rtp.mk b/gst-plugins-base-subtitles0.10/android/rtp.mk new file mode 100644 index 0000000..7ad0071 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/rtp.mk @@ -0,0 +1,48 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_rtp_COPY_HEADERS_TO := gstreamer-0.10/gst/rtp +gst_rtp_COPY_HEADERS := \ + ../gst-libs/gst/rtp/gstbasertpaudiopayload.h \ + ../gst-libs/gst/rtp/gstbasertpdepayload.h \ + ../gst-libs/gst/rtp/gstbasertppayload.h \ + ../gst-libs/gst/rtp/gstrtcpbuffer.h \ + ../gst-libs/gst/rtp/gstrtpbuffer.h \ + ../gst-libs/gst/rtp/gstrtppayloads.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +rtp_LOCAL_SRC_FILES:= \ + gst-libs/gst/rtp/gstrtpbuffer.c \ + gst-libs/gst/rtp/gstrtcpbuffer.c \ + gst-libs/gst/rtp/gstrtppayloads.c \ + gst-libs/gst/rtp/gstbasertpaudiopayload.c \ + gst-libs/gst/rtp/gstbasertppayload.c \ + gst-libs/gst/rtp/gstbasertpdepayload.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(rtp_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libdl \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstrtp-0.10 +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_rtp_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_rtp_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/rtsp.mk b/gst-plugins-base-subtitles0.10/android/rtsp.mk new file mode 100644 index 0000000..fdc07b9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/rtsp.mk @@ -0,0 +1,58 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_rtsp_COPY_HEADERS_TO := gstreamer-0.10/gst/rtsp +gst_rtsp_COPY_HEADERS_BASE := \ + gst-libs/gst/rtsp/gstrtspbase64.h \ + gst-libs/gst/rtsp/gstrtspdefs.h \ + gst-libs/gst/rtsp/gstrtspconnection.h \ + gst-libs/gst/rtsp/gstrtspextension.h \ + gst-libs/gst/rtsp/gstrtspmessage.h \ + gst-libs/gst/rtsp/gstrtsprange.h \ + gst-libs/gst/rtsp/gstrtsptransport.h \ + gst-libs/gst/rtsp/gstrtspurl.h \ + gst-libs/gst/rtsp/gstrtsp-enumtypes.h + +gst_rtsp_COPY_HEADERS := $(addprefix ../,$(gst_rtsp_COPY_HEADERS_BASE)) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +rtsp_LOCAL_SRC_FILES_BASE:= \ + gst-libs/gst/rtsp/gstrtspbase64.c \ + gst-libs/gst/rtsp/gstrtspdefs.c \ + gst-libs/gst/rtsp/gstrtspconnection.c \ + gst-libs/gst/rtsp/gstrtspextension.c \ + gst-libs/gst/rtsp/gstrtspmessage.c \ + gst-libs/gst/rtsp/gstrtsprange.c \ + gst-libs/gst/rtsp/gstrtsptransport.c \ + gst-libs/gst/rtsp/gstrtspurl.c \ + gst-libs/gst/rtsp/gstrtsp-marshal.c \ + gst-libs/gst/rtsp/gstrtsp-enumtypes.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(rtsp_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstrtsp-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DINET_ADDRSTRLEN=16 -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + + +LOCAL_COPY_HEADERS_TO := $(gst_rtsp_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_rtsp_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/sdp.mk b/gst-plugins-base-subtitles0.10/android/sdp.mk new file mode 100644 index 0000000..b83002c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/sdp.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_sdp_COPY_HEADERS_TO := gstreamer-0.10/gst/sdp +gst_sdp_COPY_HEADERS := \ + ../gst-libs/gst/sdp/gstsdp.h \ + ../gst-libs/gst/sdp/gstsdpmessage.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +sdp_LOCAL_SRC_FILES:= \ + gst-libs/gst/sdp/gstsdpmessage.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(sdp_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstsdp-0.10 +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_sdp_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_sdp_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/tag.mk b/gst-plugins-base-subtitles0.10/android/tag.mk new file mode 100644 index 0000000..e4eaee6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/tag.mk @@ -0,0 +1,46 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_tag_COPY_HEADERS_TO := gstreamer-0.10/gst/tag +gst_tag_COPY_HEADERS := \ + ../gst-libs/gst/tag/gsttagdemux.h \ + ../gst-libs/gst/tag/tag.h + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +tag_LOCAL_SRC_FILES:= \ + gst-libs/gst/tag/gstvorbistag.c \ + gst-libs/gst/tag/gstid3tag.c \ + gst-libs/gst/tag/gstxmptag.c \ + gst-libs/gst/tag/gsttageditingprivate.c \ + gst-libs/gst/tag/tags.c \ + gst-libs/gst/tag/lang.c \ + gst-libs/gst/tag/gsttagdemux.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(tag_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgsttag-0.10 + + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_tag_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_tag_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/tcp.mk b/gst-plugins-base-subtitles0.10/android/tcp.mk new file mode 100644 index 0000000..28f1dca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/tcp.mk @@ -0,0 +1,42 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +tcp_LOCAL_SRC_FILES_BASE:= \ + gst/tcp/gsttcpplugin.c \ + gst/tcp/gsttcp.c \ + gst/tcp/gstmultifdsink.c \ + gst/tcp/gsttcpclientsrc.c \ + gst/tcp/gsttcpclientsink.c \ + gst/tcp/gsttcpserversrc.c \ + gst/tcp/gsttcpserversink.c \ + gst/tcp/gsttcp-enumtypes.c \ + gst/tcp/gsttcp-marshal.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(tcp_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstdataprotocol-0.10 + +LOCAL_MODULE:= libgsttcp + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/typefindfunctions.mk b/gst-plugins-base-subtitles0.10/android/typefindfunctions.mk new file mode 100644 index 0000000..2650e2b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/typefindfunctions.mk @@ -0,0 +1,34 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +typefindfunctions_LOCAL_SRC_FILES:= \ + gst/typefind/gsttypefindfunctions.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(typefindfunctions_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libgstpbutils-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgsttypefindfunctions + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/video.mk b/gst-plugins-base-subtitles0.10/android/video.mk new file mode 100644 index 0000000..fdfb6a2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/video.mk @@ -0,0 +1,47 @@ +LOCAL_PATH:= $(call my-dir) +#---------------------------------------- +# include +gst_video_COPY_HEADERS_TO := gstreamer-0.10/gst/video +gst_video_COPY_HEADERS_BASE := \ + gst-libs/gst/video/gstvideofilter.h \ + gst-libs/gst/video/gstvideosink.h \ + gst-libs/gst/video/video.h \ + gst-libs/gst/video/video-enumtypes.h + +gst_video_COPY_HEADERS := $(addprefix ../,$(gst_video_COPY_HEADERS_BASE)) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +video_LOCAL_SRC_FILES_BASE:= \ + gst-libs/gst/video/video.c \ + gst-libs/gst/video/gstvideosink.c \ + gst-libs/gst/video/gstvideofilter.c \ + gst-libs/gst/video/convertframe.c \ + gst-libs/gst/video/video-enumtypes.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(video_LOCAL_SRC_FILES_BASE)) + +LOCAL_SHARED_LIBRARIES := \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstvideo-0.10 + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# define LOCAL_PRELINK_MODULE to false to not use pre-link map +# +LOCAL_PRELINK_MODULE := false + +LOCAL_COPY_HEADERS_TO := $(gst_video_COPY_HEADERS_TO) +LOCAL_COPY_HEADERS := $(gst_video_COPY_HEADERS) +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/videoscale.mk b/gst-plugins-base-subtitles0.10/android/videoscale.mk new file mode 100644 index 0000000..83afa38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/videoscale.mk @@ -0,0 +1,40 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +videoscale_LOCAL_SRC_FILES:= \ + gst/videoscale/gstvideoscale.c \ + gst/videoscale/gstvideoscaleorc-dist.c \ + gst/videoscale/vs_4tap.c \ + gst/videoscale/vs_fill_borders.c \ + gst/videoscale/vs_image.c \ + gst/videoscale/vs_scanline.c + +LOCAL_SRC_FILES:= $(addprefix ../,$(videoscale_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstvideo-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 \ + libgstpbutils-0.10 + +LOCAL_MODULE:= libgstvideoscale + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/android/videotestsrc.mk b/gst-plugins-base-subtitles0.10/android/videotestsrc.mk new file mode 100644 index 0000000..3385aa1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/android/videotestsrc.mk @@ -0,0 +1,38 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) + +LOCAL_ARM_MODE := arm + +videotestsrc_LOCAL_SRC_FILES:= \ + gst/videotestsrc/gstvideotestsrc.c \ + gst/videotestsrc/videotestsrc.c \ + gst/videotestsrc/gstvideotestsrcorc-dist.c \ + + +LOCAL_SRC_FILES:= $(addprefix ../,$(videotestsrc_LOCAL_SRC_FILES)) + +LOCAL_SHARED_LIBRARIES := \ + libgstcontroller-0.10 \ + libgstvideo-0.10 \ + libgstreamer-0.10 \ + libgstbase-0.10 \ + libglib-2.0 \ + libgthread-2.0 \ + libgmodule-2.0 \ + libgobject-2.0 + +LOCAL_MODULE:= libgstvideotestsrc + +LOCAL_CFLAGS := -DHAVE_CONFIG_H -DGSTREAMER_BUILT_FOR_ANDROID \ + $(GST_PLUGINS_BASE_CFLAGS) +# +# 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.10 +LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/gstreamer-0.10 +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) diff --git a/gst-plugins-base-subtitles0.10/autogen.sh b/gst-plugins-base-subtitles0.10/autogen.sh new file mode 100755 index 0000000..a163136 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/autogen.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +DIE=0 +package=gst-plugins-base +srcfile=gst/audiotestsrc/gstaudiotestsrc.c + +# source helper functions +if test ! -f common/gst-autogen.sh; +then + echo There is something wrong with your source tree. + echo You are missing common/gst-autogen.sh + exit 1 +fi +. common/gst-autogen.sh + +CONFIGURE_DEF_OPT='--enable-maintainer-mode --enable-gtk-doc --enable-plugin-docs' + +autogen_options $@ + +printf "+ check for build tools" +if test ! -z "$NOCHECK"; then echo " skipped"; else echo; fi +version_check "autoconf" "$AUTOCONF autoconf autoconf270 autoconf269 autoconf268 autoconf267 autoconf266 autoconf265 autoconf264 autoconf263 autoconf262 autoconf261 autoconf260" \ + "ftp://ftp.gnu.org/pub/gnu/autoconf/" 2 60 || DIE=1 +version_check "automake" "$AUTOMAKE automake automake-1.11 automake-1.10" \ + "ftp://ftp.gnu.org/pub/gnu/automake/" 1 10 || DIE=1 +version_check "autopoint" "autopoint" \ + "ftp://ftp.gnu.org/pub/gnu/gettext/" 0 14 || DIE=1 +version_check "libtoolize" "$LIBTOOLIZE libtoolize glibtoolize" \ + "ftp://ftp.gnu.org/pub/gnu/libtool/" 1 5 0 || DIE=1 +version_check "pkg-config" "" \ + "http://www.freedesktop.org/software/pkgconfig" 0 8 0 || DIE=1 + +die_check $DIE + +aclocal_check || DIE=1 +autoheader_check || DIE=1 + +die_check $DIE + +# if no arguments specified then this will be printed +if test -z "$*"; then + echo "+ checking for autogen.sh options" + echo " This autogen script will automatically run ./configure as:" + echo " ./configure $CONFIGURE_DEF_OPT" + echo " To pass any additional options, please specify them on the $0" + echo " command line." +fi + +toplevel_check $srcfile + +# autopoint +# older autopoint (< 0.12) has a tendency to complain about mkinstalldirs +if test -x mkinstalldirs; then rm mkinstalldirs; fi +# first remove patch if necessary, then run autopoint, then reapply +if test -f po/Makefile.in.in; +then + patch -p0 -R --forward < common/gettext.patch +fi +tool_run "$autopoint --force" +patch -p0 < common/gettext.patch + +tool_run "$libtoolize" "--copy --force" +tool_run "$aclocal" "-I m4 -I common/m4 $ACLOCAL_FLAGS" +tool_run "$autoheader" + +# touch the stamp-h.in build stamp so we don't re-run autoheader in maintainer mode +echo timestamp > stamp-h.in 2> /dev/null + +tool_run "$autoconf" +tool_run "$automake" "-a -c" + +# if enable exists, add an -enable option for each of the lines in that file +if test -f enable; then + for a in `cat enable`; do + CONFIGURE_FILE_OPT="--enable-$a" + done +fi + +# if disable exists, add an -disable option for each of the lines in that file +if test -f disable; then + for a in `cat disable`; do + CONFIGURE_FILE_OPT="$CONFIGURE_FILE_OPT --disable-$a" + done +fi + +test -n "$NOCONFIGURE" && { + echo "+ skipping configure stage for package $package, as requested." + echo "+ autogen.sh done." + exit 0 +} + +echo "+ running configure ... " +test ! -z "$CONFIGURE_DEF_OPT" && echo " ./configure default flags: $CONFIGURE_DEF_OPT" +test ! -z "$CONFIGURE_EXT_OPT" && echo " ./configure external flags: $CONFIGURE_EXT_OPT" +test ! -z "$CONFIGURE_FILE_OPT" && echo " ./configure enable/disable flags: $CONFIGURE_FILE_OPT" +echo + +./configure $CONFIGURE_DEF_OPT $CONFIGURE_EXT_OPT $CONFIGURE_FILE_OPT || { + echo " configure failed" + exit 1 +} + +echo "Now type 'make' to compile $package." diff --git a/gst-plugins-base-subtitles0.10/common/.gitignore b/gst-plugins-base-subtitles0.10/common/.gitignore new file mode 100644 index 0000000..23c1897 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/.gitignore @@ -0,0 +1,3 @@ +Makefile +Makefile.in +*~ diff --git a/gst-plugins-base-subtitles0.10/common/ChangeLog b/gst-plugins-base-subtitles0.10/common/ChangeLog new file mode 100644 index 0000000..92d0d25 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/ChangeLog @@ -0,0 +1,1712 @@ +2008-12-17 Edward Hervey <bilboed@gmail.com> + + * gst.supp: + And yet another variation of the GstAudioFilter leak. + +2008-12-15 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + Patch by: Roland Illig <roland dot illig at gmx dot de> + + * m4/gst-parser.m4: + Fix AG_GST_BISON_CHECK to handle version numbers with more than + two components (i.e. 2.4.1). Fixes bug #564507. + +2008-12-14 Edward Hervey <bilboed@gmail.com> + + * gst.supp: + And yet another variant of the GstAudioFilter leak. + +2008-12-13 Edward Hervey <edward.hervey@collabora.co.uk> + + * gst.supp: + Added variants of leaks of dynamic pad templates created in + GstAudioFilter. + Add conditional jump triggered by getaddrinfo (maybe glibc-2.9). + +2008-12-12 Edward Hervey <edward.hervey@collabora.co.uk> + + * gst.supp: + Fix leak in GIO called by gnomevfs. Nothing we can do about this. + +2008-12-12 Edward Hervey <edward.hervey@collabora.co.uk> + + * gst.supp: + Added another suppression for dynamic pad templates, in this case + GstAudioFilter. + Added suppression for PangoLanguage which can never be freed + according to the Pango API. + +2008-12-12 Edward Hervey <edward.hervey@collabora.co.uk> + + * gst.supp: + A whole bunch of suppressions detected on latest gentoo ~amd64. + Make some existing suppressions more generic (for subtle dependecy + code changes). + Added suppressions for glibc-2.9. + Added suppressions for new variants of ALSA leaks. + Added suppressions for a series of leaks in plugins registrations due + to some pad templates' caps calculated at runtime. + Added suppressions for variants of some leaks in pango/fontconfig. + Added suppressions for leak in gstffmpegcsp.c (nothing we can do + about it, but will only exist once). + +2008-12-04 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * m4/gst-plugin-docs.m4: + Remove the check if $have_gtk_doc equals yes as it's not defined + and $enable_gtk_doc should be good enough. + Also this restores the build of the plugin documentation. + +2008-12-01 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst.supp: + Add suppression variant for Ubuntu Hardy x86/64bit. + +2008-12-01 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Simplily uninstall rule. Its closer to upstream and fixes #150331. + +2008-11-29 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * m4/glib-gettext.m4: + Update glib-gettext.m4 from latest stable GLib release. + +2008-11-29 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + Patch by: Cygwin Ports maintainer + <yselkowitz at users dot sourceforge dot net> + + * gettext.patch: + Update the gettext patch for use with gettext 0.17 which is + required to build with libtool 2.2 because of conflicts. + First part of bug #556091. + +2008-11-29 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * m4/gtk-doc.m4: + * m4/pkg.m4: + Update gtk-doc and pkg-config m4 macros from their latest releases. + +2008-11-20 Michael Smith <msmith@songbirdnest.com> + + * m4/as-objc.m4: + Fix objective C test macro when none of the compilers are found at all. + +2008-10-30 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc.mak: + Also cp the entities here to all xinlcude based docs (workaround for + not being able to set up a search path). + +2008-10-17 Jan Schmidt <jan.schmidt@sun.com> + + * gtk-doc.mak: + Don't clobber the real registry cache file when + building docs. + +2008-10-07 Jan Schmidt - Sun Microsystems <jan.schmidt@sun.com> + + * m4/gst-error.m4: + Also disable the bogus "loop not entered at top" warnings appearing on Sparc Forte builds. + +2008-10-06 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc.mak: + Apply the same fix as below to gtk-doc.mak. Somehow did not end up in + CVS. + +2008-09-05 David Schleef <ds@schleef.org> + + * gtk-doc-plugins.mak: Fix the check for gtkdoc-rebase: don't + pass the 'which' error back to make. This fix is more specific + than what is in upstream. + +2008-09-05 David Schleef <ds@schleef.org> + + * gtk-doc.mak: Fix the check for gtkdoc-rebase: don't pass the + 'which' error back to make. This fix is more specific than + what is in upstream. + +2008-09-04 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Get closer to upstream makefiles. Don't install index.sgml twice. Call + gtkdoc-rebase (if exists). + +2008-08-21 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + Revert $(top_builddir) -> $(builddir) change of rev. 1.39 as there is + no variable called builddir. + +2008-07-31 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gst.supp: + Add suppressions for Ubunty Hardy x86/64bit, similar to earlier + versions and 32bit variant. + +2008-07-31 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * m4/gst-feature.m4: + Remove GST_DISABLE_(ENUMTYPES|INDEX|URI). + +2008-07-21 Tim-Philipp Müller <tim.muller at collabora co uk> + + * m4/gst-error.m4:: + When checking for GST_ERROR_CXXFLAGS, check each compiler flag + individually, not all together. + +2008-07-20 Tim-Philipp Müller <tim.muller at collabora co uk> + + * m4/gst-parser.m4:: + Fix bison version number detection for older --version + output format (as bison 1.28 on OSX 10.4 outputs). + Fixes #543853. + +2008-07-12 Stefan Kost <ensonic@users.sf.net> + + * plugins.xsl: + Split refsect2 also here to make "Element Pads" subtitle visible. + +2008-07-08 Sebastian Dröge <sebastian.droege@collabora.co.uk> + + * m4/gst-error.m4: + Add compiler flags to warn if declarations after statements or + variable length arrays are used. These are C99/GCC extensions and + are not supported by some compilers we want to support. + +2008-07-02 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + * gtk-doc-plugins.mak: + Only clean doc maintainer stamps in maintainer-clean. Fixes #539977. + +2008-06-20 Sebastian Dröge <slomo@circular-chaos.org> + + * gstdoc-scangobj: + Always use format strings for printf-like functions, even if they just + print a string. Fixes bug #536981. + +2008-06-20 Sebastian Dröge <slomo@circular-chaos.org> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Include CFLAGS and LDFLAGS in GTKDOC_CFLAGS and GTKDOC_LDFLAGS, + otherwise the values passed to configure are ignored. + Fixes bug #536978. + +2008-06-05 Tim-Philipp Müller <tim.muller at collabora co uk> + + * m4/gst-error.m4: + Add -fno-strict-aliasing when compiling with -Werror, to work around + warnings caused by G_LOCK with recent GLib versions (2.16.x) (#316221). + +2008-06-05 Jan Schmidt <jan.schmidt@sun.com> + + * gtk-doc.mak: + Don't copy html/*.png files unless they don't already exist + in the destdir. Fixes distcheck failure caused by permissions + problems trying to copy a file into the destdir when it already + exists. + +2008-05-28 Stefan Kost <ensonic@users.sf.net> + + * plugins.xsl: + The class was not shown in plugin docs. Fix typo in changelog below. + +2008-05-22 Jan Schmidt <jan.schmidt@sun.com> + + * gstdoc-scangobj: + Emit warnings if one of the GTypes we're expecting is 0 + when scanning. + +2008-05-21 Felipe Contreras <felipe.contreras@gmail.com> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix installing png images when gtk-doc is disabled. + +2008-05-21 Felipe Contreras <felipe.contreras@gmail.com> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Fix make clean when gtk-doc is disabled and other cleanups. + +2008-05-17 Jan Schmidt <jan.schmidt@sun.com> + + * gtk-doc-plugins.mak: + Be more quiet when the files don't yet exist. + +2008-05-16 Jan Schmidt <jan.schmidt@sun.com> + + * gstdoc-scangobj: + Add a mechanism for adding 'implicitly created' GTypes into the + scan, allowing for documenting plugin-private base classes that + provide signals or properties for public elements. + + * gtk-doc-plugins.mak: + Use $(builddir) instead of $(top_builddir) in a few places - there's + no need to hard code 'docs/plugins' as the only useable path. + +2008-05-14 Peter Kjellerstedt <pkj@axis.com> + + * m4/gst-feature.m4: + Report plug-ins without external dependencies that will not be built + even when the name of the plug-in is a substring of another plug-in, + e.g., goom vs. goom2k1. + +2008-05-14 Tim-Philipp Müller <tim.muller at collabora co uk> + + * gst.supp: + Add suppression for glibc bug on gutsy/x86-64 + +2008-05-12 Stefan Kost <ensonic@users.sf.net> + + * plugins.xsl: + Improve the layout of the caps, but splitting them on ";". + +2008-05-09 Sebastian Dröge <slomo@circular-chaos.org> + + Patch by: Brian Cameron <brian dot cameron at sun dot com> + + * m4/gst-default.m4: + Don't set the default audio sink to the default visualizer. + Fixes bug #532295. + +2008-05-07 Tim-Philipp Müller <tim.muller at collabora co uk> + + * check.mak: (help): + Document GST_CHECKS environment variable in checks 'make help'. + +2008-05-06 Sebastian Dröge <slomo@circular-chaos.org> + + Patch by: Marc-Andre Lureau <marcandre dot lureau at gmail dot com> + + * scangobj-merge.py: + Don't depend on Twisted just for the OrderedDict but implement our + own ordered dictionary class. Fixes bug #531577. + +2008-04-23 Edward Hervey <edward.hervey@collabora.co.uk> + + * gst.supp: + Re-arrange latest suppressions. + Add all known suppressions for ubuntu hardy. Same as for older + ubuntus, but with different codepaths. + +2008-04-22 Edward Hervey <bilboed@gmail.com> + + * gst.supp: Make tls leak suppression a bit more generic. + +2008-04-22 Edward Hervey <bilboed@gmail.com> + + * gst.supp: Fix ommission in latest commit. + Make tls leak suppression more generic in order to cover more + distributions (and hopefully also future distributions). + +2008-04-22 Edward Hervey <bilboed@gmail.com> + + * gst.supp: Add suppressions for Hardy. + They're just the newer versions of similar suppressions we had + for the previous versions of ubuntu. + +2008-04-15 Sebastian Dröge <slomo@circular-chaos.org> + + * Makefile.am: + * m4/Makefile.am: + Dist all files in common. Fixes bug #527984. + +2008-04-14 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-function.m4: + Rename AC_CACHE_VAL cache-ids to contain '_cv_' in order to make + autoconf-2.62 complain less. + +2008-04-13 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-args.m4: + * m4/gst-valgrind.m4: + Bump valgrind requirement to 3.0 (which was released in August 2005). + Fixes #489269. Also, check for version >=REQ and not >REQ. + +2008-04-09 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-default.m4: + Add --with-default-{audiosink|audiosrc|videosink|videosrc|visualizer} + configure switches (#519417). + +2008-04-03 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-args.m4: + Add --disable-foo switch for dependency-less plugins (#525586). + +2008-04-01 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-parser.m4: + Unconditionally require flex 2.5.31 and bison 1.875. + +2008-03-23 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-arch.m4: + amd64/x86_64 allows unaligned memory access too. + +2008-03-21 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-dowhile.m4: + Add macro that checks if the compiler supports do {} while (0) + macros and define HAVE_DOWHILE_MACROS if it does. This is + needed by glib/gmacros.h to use something else than + if (1) else for G_STMT_START/END when compling C++, which + causes compiler warnings because of ambigious else with g++ 4.3. + +2008-03-21 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-plugin-docs.m4: + * mangle-tmpl.py: + Don't depend on PyXML and use only XML modules that are shipped + with python. Fixes bug #519635. + +2008-03-07 Edward Hervey <edward.hervey@collabora.co.uk> + + * m4/gtk-doc.m4: (GTK_DOC_CHECK): + The previous commit to this file by Stefan Kost mentionned checking for + SED, but NOT checking for gtkdoc-check (wth is that doing there ??). + Therefore, removing the check for gtkdoc-check + +2008-03-03 David Schleef <ds@schleef.org> + + * m4/ax_create_stdint_h.m4: Oops, checked in the wrong copy of + this file. (Update from upstream) + +2008-03-03 David Schleef <ds@schleef.org> + + * m4/ax_create_stdint_h.m4: Update from upstream. Fixes a bug + compiling with MSVC. + +2008-03-03 Edward Hervey <edward.hervey@collabora.co.uk> + + * m4/pkg.m4: + Allow override of pkg-config results, as proposed by configure --help. + This is in fact just a backport from upstream pkg.m4. + Fixes #518892 + +2008-03-03 Peter Kjellerstedt <pkj@axis.com> + + * ChangeLog: + Changelog surgery of my previous commit to add bugzilla reference. + * m4/gst-args.m4: + Add AG_GST_CHECK_PLUGIN and AG_GST_DISABLE_PLUGIN to make it easier + to include and exclude plug-ins without external references, i.e., + plug-ins listed in GST_PLUGINS_SELECTED. (#498222) + +2008-03-03 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add another glibc suppression. + +2008-02-29 Peter Kjellerstedt <pkj@axis.com> + + * m4/gst-feature.m4: + Make the comment before defines generated via AG_GST_CHECK_FEATURE + look nicer. (#498222) + +2008-02-26 Jan Schmidt <jan.schmidt@sun.com> + + * m4/Makefile.am: + * m4/as-gcc-inline-assembly.m4: + Add Dave Schleef's GCC inline assembly detection macro + for using in gst-plugins-good in the goom 2k4 plugin. + +2008-02-25 Andy Wingo <wingo@pobox.com> + + * gst-autogen.sh: Instead of only passing certain arguments to + configure, pass anything that we didn't handle. Much friendlier. + Fixes #34412. + +2008-02-23 Jan Schmidt <Jan.Schmidt@sun.com> + + * m4/gst-error.m4: + Store the detected compiler flags into ERROR_CFLAGS rather than + ERROR_CXXFLAGS, and use the macro that checks the C compiler, not + the C++ one. + +2008-02-23 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-error.m4: + Reflow checks for additional warning flags so they're not + nested, which fixes the result reporting in the configure + output. + +2008-02-22 Tim-Philipp Müller <tim at centricular dot net> + + * m4/as-compiler-flag.m4: + Add AS_CXX_COMPILER_FLAG + + * m4/gst-error.m4: + Add AG_GST_SET_ERROR_CXXFLAGS (Forte bits need testing) + +2008-02-22 Tim-Philipp Müller <tim at centricular dot net> + + * gtk-doc-plugins.mak: + Add 'check-inspected-versions' target; this helps identify + files that should have been removed or where the version + number should (ideally) be updated before a release + (which doesn't happen automatically if the releaser doesn't + build that plugin locally). Not adding at a distcheck hook + yet though, because it's not really that important and would + probably also be a problem on buildbots. + +2008-02-22 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add even more glibc 2.7 suppressions. + +2008-02-22 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add another suppression for GLib caching some values after + the first call. + +2008-02-12 Sebastian Dröge <slomo@circular-chaos.org> + + Patch by: + Tim Mooney <mooney at dogbert dot cc dot ndsu dot nodak dot edu> + + * m4/gst-error.m4: + Use no%E_MACRO_REDEFINED on Solaris to prevent compiler warnings. + Fixes bug #515905. + +2008-02-11 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add a few more glibc 2.7 suppressions to make the avisubtitle unit + test valgrind clean. Fixes bug #515703. + +2008-02-08 Stefan Kost <ensonic@users.sf.net> + + * ChangeLog: + Changelog surgery for last commit. + +2008-02-08 Stefan Kost <ensonic@users.sf.net> + + * m4/gtk-doc.m4: + Conditionally check for SED. Also sync a bit with upstream macro. + +2008-02-08 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + Use '$(SED)' instead of 'sed'. Don't use -i for in-place as its gnu + only, move to a temp file instead. + +2008-02-06 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + As our docs are versioned, we need to patch the index.sgml file to have + correct paths there, unless we also want to fork gtk-doc's xsl (which + we don't). This hopefully fixes xrefs between modules. + +2008-02-02 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-feature.m4: + Use printf instead of echo as "echo -e" isn't POSIX and doesn't work + with strict POSIX shells like tcsh or dash and also not every platform + has a /bin/echo that supports it. + +2008-01-24 Stefan Kost <ensonic@users.sf.net> + + * ChangeLog: + ChangeLog surgery. + + * gstdoc-scangobj: + Sync the object scanner with gtk-doc fixes. Update args and hierarchy + files. + +2008-01-20 Sebastian Dröge <slomo@circular-chaos.org> + + * check.mak: + * coverage/lcov.mak: + * gtk-doc-plugins.mak: + * release.mak: + Use $(MAKE) instead of make to fix the build if GNU make is called + something else on the system. + + * m4/as-docbook.m4: + Fix path for docbook.xsl if we have no /etc/xml/catalog and add a + docbook-xsl search path for FreeBSD. + +2008-01-18 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add a suppression for a glibc bug: + http://valgrind.org/docs/manual/faq.html#faq.exit_errors> + +2008-01-18 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add some more glibc 2.7 suppressions and make the GLib suppressions + for the home/tmp/etc directory caching a bit more generic. + +2008-01-18 Sebastian Dröge <slomo@circular-chaos.org> + + * gst.supp: + Add some glibc 2.7 supressions as found on Debian/unstable. + +2008-01-14 Jan Schmidt <jan.schmidt@sun.com> + + * download-translations: + Apparently I have problems with leaving things commented out when + I edit shell scripts. + +2008-01-12 Jan Schmidt <Jan.Schmidt@sun.com> + + * download-translations: + Remove bash-isms + +2008-01-12 Jan Schmidt <Jan.Schmidt@sun.com> + + * check-exports: + Restore the cleanup rm of our tmp file which I didn't mean to leave + commented out. + +2008-01-12 Jan Schmidt <Jan.Schmidt@sun.com> + + * check-exports: + Fixes to make check-export work on both Solaris and Linux + + * m4/gst-error.m4: + Disable extra warning category (argument mismatch) as an error + on Forte, as it prevents the libcheck fail_if macros from compiling. + + * win32.mak: + Substitute the GStreamer version so things will keep working in 0.11 + +2008-01-11 Tim-Philipp Müller <tim at centricular dot net> + + Patch by: Peter Kjellerstedt <pkj axis com> + + * m4/gst-glib2.m4: + * m4/gst-libxml2.m4: + Improve/fix output from configure if either glib-2.0 or + libxml2 are not installed (#498222). + +2008-01-09 Stefan Kost <ensonic@users.sf.net> + + * coverage/lcov.mak: + Update coverage make-rules: use them conditionaly, use libtool mode + and use lcov to cleanup. + +2007-12-18 Sebastian Dröge <slomo@circular-chaos.org> + + * glib-gen.mak: + Also use #include "header" instead of #include <header> for the + headers that were used to generate the source files for the same + reason as below. + + Remove whitespace before #include. + +2007-12-18 Sebastian Dröge <slomo@circular-chaos.org> + + * glib-gen.mak: + Use #include "header" instead of #include <header> for the generated + enum C files as the file will always be in the same directory and + some compilers seem to be a bit strict about that unless . is added + to the include path. + + Include all headers that were used to generate the source files in + the C file as they're used there. + +2007-12-17 Tim-Philipp Müller <tim at centricular dot net> + + * win32.mak: (win32), (win32defs), (win32crlf): + Make check for CR LF in Visual C++ 6.0 project files + work, based on patch by David Schleef (#496722, #393626). + +2007-12-17 Tim-Philipp Müller <tim at centricular dot net> + + * Makefile.am: + Don't forget to dist the new win32.mak. + +2007-12-17 Tim-Philipp Müller <tim at centricular dot net> + + * win32.mak: (win32), (win32defs): + Move common win32 Makefile foo into this new file. + +2007-12-15 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + We should have never forked this that much :/. + +2007-12-13 Tim-Philipp Müller <tim at centricular dot net> + + * check-exports: + Fix build on the ppc64 build bot. + +2007-12-13 Tim-Philipp Müller <tim at centricular dot net> + + * check-exports: + Suppress more unintentional exports (too much hassle to rename them, + since the win32 project files would need changing too). + +2007-12-12 Tim-Philipp Müller <tim at centricular dot net> + + * Makefile.am: + check-exports should be disted. + +2007-12-12 Tim-Philipp Müller <tim at centricular dot net> + + * check-exports: + Add quick'n'dirty script to check the exported symbols of a library + against the symbols in the corresponding .def file (#493983). Based + on script by Ole André Vadla Ravnås. + +2007-11-06 Jan Schmidt <jan.schmidt@sun.com> + + * gtk-doc-plugins.mak: + Fix distcheck by making sure the types files are treated like the + other gtkdoc-scangobj generated files. + +2007-09-21 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-args.m4: + Let the AG_GST_ARG_ENABLE_EXPERIMENTAL macro default to disable + building of experimental plugins. Nobody uses it yet and the + --enable--experimental stuff from gst-plugins-good defaults to + disable too. + +2007-09-06 Tim-Philipp Müller <tim at centricular dot net> + + * gtk-doc-plugins.mak: + Just use the normal 'check' target and avoid a circular + dependency. + +2007-09-06 Tim-Philipp Müller <tim at centricular dot net> + + * gtk-doc-plugins.mak: + Add rule to error out if .hierarchy file contains tabs. + +2007-08-20 Tim-Philipp Müller <tim at centricular dot net> + + * download-translations: + * po.mak: + If there are new languages, they need to be added to po/LINGUAS. + +2007-08-20 Tim-Philipp Müller <tim at centricular dot net> + + * download-translations: + * po.mak: + Fix up 'download-po' a bit, so that we find new translations + for languages that aren't in our po/LINGUAS file yet too. + +2007-07-16 Jan Schmidt <thaytan@mad.scientist.com> + + * gst.supp: + Add a suppression for GLib caching the tmp dir seen on an + Ubuntu Feisty system. + +2007-07-13 Jan Schmidt <thaytan@mad.scientist.com> + + * m4/gst-feature.m4: + If we want to use 'echo -e', call /bin/echo instead of the shell's + since -e is a bash extension, and our /bin/sh might not be being + provided by bash. + +2007-07-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * po.mak: + Translation project has moved. Also, no idea how this used to + work given that we weren't downloading a .po file. + +2007-06-25 Stefan Kost <ensonic@users.sf.net> + + * gst-xmlinspect.py: + * plugins.xsl: + Also extract element caps for plugin-docs. Fixes parts of #117692. + +2007-06-21 Tim-Philipp Müller <tim at centricular dot net> + + Patch by: Andreas Schwab + + * m4/gst-feature.m4: + Fix quoting (#449493). + +2007-06-10 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-parser.m4: + Only generate the parser if bison >= 1.875 _and_ flex >= 2.5.31 is + installed and use pre-generated sources otherwise. Fixes bug #444820. + +2007-05-11 Michael Smith <msmith@fluendo.com> + + * gst.supp: + Suppression variant for our good friend the TLS leak, this time for + Ubuntu Feisty/x86. + +2007-05-09 Tim-Philipp Müller <tim at centricular dot net> + + * gtk-doc-plugins.mak: + Fix make distcheck again; change some spaces to tabs in makefile. + +2007-04-29 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak (-module): + Error out when the html build step gives warnings, so they get + fixed properly. + +2007-04-23 Stefan Kost <ensonic@users.sf.net> + + * m4/gst-feature.m4: + Add macro AG_GST_PARSE_SUBSYSTEM_DISABLES that checks the defines in + the configuration header and AC_DEFINES the setings. + +2007-04-19 Sebastian Dröge <slomo@circular-chaos.org> + + Patch by: Vincent Torri <vtorri at univ-evry dot fr> + + * m4/gst-parser.m4: + Put the AC_MSG_RESULT output in brackets to get it properly written to + the terminal. + +2007-04-18 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-parser.m4: + Check for flex >= 2.5.31 and set GENERATE_PARSER if we have at least + that version. Otherwise use pre-generated parser sources as we can't + raise the required flex version. HAVE_MT_SAVE_FLEX is obsolete now + as we use a new enough flex version anyway. First part of #349180 + +2007-04-10 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + Allow pre-setting the GST(PB)_TOOLS/PLUGINS_DIR variables to help + builds against older GStreamer. + +2007-03-25 Sebastian Dröge <slomo@circular-chaos.org> + + * m4/gst-parser.m4: + Fix the flex version check. It ignored the micro version before. + +2007-03-09 Jan Schmidt <thaytan@mad.scientist.com> + + * check.mak: + Use the same timeout when generating valgrind suppressions as + running the valgrind test. + + * gst.supp: + Add some more suppressions and stuff. + +2007-03-08 Jan Schmidt <thaytan@mad.scientist.com> + + * check.mak: + Make sure GSlice is disabled when building suppressions too. + + * gst.supp: + Add around *850* lines of suppressions for one-time initialisations + inside libasound and gconf/bonobo/ORBit. I feel so dirty. + +2007-03-07 Jan Schmidt <thaytan@mad.scientist.com> + + * gst.supp: + add a suppression for this GConf flup on the FC5 buildbot. + +2007-03-06 Jan Schmidt <thaytan@mad.scientist.com> + + * gst.supp: + Make the suppression a little more generic, to catch the FC5 + backtrace too. + +2007-03-06 Jan Schmidt <thaytan@mad.scientist.com> + + * gst.supp: + Add a suppression for libcdio 0.76. It leaks an internal struct + when the CD-ROM device is not accessible. + +2007-02-28 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-arch.m4: + Move a line that was in the wrong macro + +2007-02-28 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst.m4: + Add + * m4/gst-arch.m4: + * m4/gst-args.m4: + * m4/gst-check.m4: + * m4/gst-debuginfo.m4: + * m4/gst-default.m4: + * m4/gst-doc.m4: + * m4/gst-error.m4: + * m4/gst-feature.m4: + * m4/gst-function.m4: + * m4/gst-gettext.m4: + * m4/gst-glib2.m4: + * m4/gst-libxml2.m4: + * m4/gst-parser.m4: + * m4/gst-plugin-docs.m4: + * m4/gst-plugindir.m4: + * m4/gst-valgrind.m4: + * m4/gst-x11.m4: + Convert all macros to use AG_GST style so we can properly warn + when they're missing if configure.ac calls AG_GST_INIT + Will require update in all GStreamer modules. + +2007-02-11 Stefan Kost <ensonic@users.sf.net> + + * m4/gst-args.m4: + Remove 'enable' from configure switch description as this leads to + confusing lines like "disable enable builing ...". + * m4/gst-feature.m4: + Fix comment to sound less horrible. + +2007-02-07 Tim-Philipp Müller <tim at centricular dot net> + + Patch by: Will Newton <will.newton gmail com> + + * m4/gst-check.m4: + Use $PKG_CONFIG rather than pkg-config directly, the one in our path + might not be the one we want, like when cross-compiling. Also, other + macros such as PKG_CHECK_MODULES use $PKG_CONFIG, so we should + probably too just for consistency. Fixes #405288. + +2007-01-08 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-parser.m4: + Need to use double square brackets again so m4 doesn't remove them + (fixes #378931). + + * m4/gst-args.m4: + Use double square brackets here as well, for the same reason. + +2007-01-05 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-parser.m4: + Use 'sed' rather than 'tr' to strip trailing letters from version + numbers, since 'tr' might not be available and we know sed is + (#378931). + +2006-10-21 Tim-Philipp Müller <tim at centricular dot net> + + * check.mak: + Increase default timeout under valgrind, 60 is just too short and + some tests take a bit longer these days and not everyone has a + beefy machine. + +2006-09-29 Michael Smith <msmith@fluendo.com> + + * gst.supp: + More suppressions for edgy. + +2006-09-28 Jan Schmidt <thaytan@mad.scientist.com> + + * m4/gst-glib2.m4: + Use gmodule-no-export-2.0.pc instead of gmodule-2.0.pc - we neither + want nor need --export-dynamic (which ends up making us export a bunch + of unneeded symbols) + +2006-09-14 Tim-Philipp Müller <tim at centricular dot net> + + * gst.supp: + Some suppressions for the more recent ld.so in ubuntu edgy. + +2006-08-23 Tim-Philipp Müller <tim at centricular dot net> + + * gst.supp: + Shorten function trail so the suppression works on + my ubuntu dapper system with core cvs as well. + +2006-07-28 Jan Schmidt <thaytan@mad.scientist.com> + + * gst.supp: + Extra suppressions from my Ubuntu x86_64 machine + +2006-07-24 Tim-Philipp Müller <tim at centricular dot net> + + Patch by: Frederic Peters <fpeters at entrouvert com> + + * m4/gst-parser.m4: + Need to double square brackets in .m4 files. Should fix bison + version detection with version numbers like 1.23a (#348354). + +2006-07-24 Jan Schmidt <thaytan@mad.scientist.com> + + * check.mak: + Valgrind fails to find tests written in tests/check/ directly (rather + than a subdir) - because valgrind gets run with a filename that + doesn't contain a relative path, it goes searching /usr/bin instead. + Run with ./.... to make things work either way. + + * gtk-doc-plugins.mak: + Add $(top_builddir)/src as a place to look for plugins + when building too, since that's where gst-template keeps things + +2006-07-23 Stefan Kost <ensonic@users.sf.net> + + Patch by: Frederic Peters <fpeters@entrouvert.com> + + * m4/gst-parser.m4: + Fix bison detection (#348354) + +2006-07-21 Stefan Kost <ensonic@users.sf.net> + + * m4/gst-parser.m4: + check for bison and flex + +2006-07-13 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-plugin-docs.m4: + remove the configure argument for enabling plugin doc build; + having gtk-doc enabled and pyxml present is enough of a trigger + +2006-07-03 Thomas Vander Stichele <thomas at apestaart dot org> + + * coverage/lcov.mak: + fix up rules to work with gst-python as well + run "make lcov" to test and generate the reports + run "make lcov-reset" to redo it after that + +2006-07-02 Thomas Vander Stichele <thomas at apestaart dot org> + + * Makefile.am: + * check.mak: + add an inspect target that inspects every element feature, + so we can have that added for coverage + * coverage/lcov.mak: + add support for lcov + +2006-07-02 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + when building with gcov, reset CFLAGS and friends to O0 + +2006-07-02 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + Find the gcov that matches the gcc version + Only allow gcov if we use gcc + +2006-07-02 Thomas Vander Stichele <thomas at apestaart dot org> + + * Makefile.am: + * coverage/coverage-report-entry.pl: + * coverage/coverage-report.pl: + * coverage/coverage-report.xsl: + copy coverage reporting files from dbus + +2006-07-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + libtool strips gcov's -f flags, so libgcov does not get + linked in. Setting GCOV_LIBS with -lgcov fixes libtool's + stripping + also show what pkg-config-path we set + +2006-06-22 Tim-Philipp Müller <tim at centricular dot net> + + Patch by: Peter Kjellerstedt <pkj at axis com> + + * m4/gst-feature.m4: + Show list of plugins without external dependencies that + will not be built as well (#344136). + +2006-06-15 Tim-Philipp Müller <tim at centricular dot net> + + * m4/gst-plugin-docs.m4: + add GST_PLUGIN_DOCS, which checks for everything needed + to build the plugin docs (namely gtk-doc and pyxml); also + adds a new --enable-plugin-docs configure switch; will + set ENABLE_PLUGIN_DOCS conditional for use in Makefile.am + files (see #344039). + +2006-06-11 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + add GST_PKG_CHECK_MODULES, which in the normal case of checking + for a dependency lib for a plug-in only needs two arguments + to do the right thing. + * m4/gst-feature.m4: + clean up output a little of feature checking; also deal with + non-plug-in feature checks + * m4/Makefile.am: + * m4/gst-gstreamer.m4: + remove this file; it's a useless check + +2006-06-06 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-arch.m4: + add PPC64 so we can have separate structure sizes for it + +2006-06-05 Edward Hervey <edward@fluendo.com> + + * gtk-doc.mak: + Check for the proper .devhelp2 file to remove. + +2006-05-31 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc.mak: + allow a magic variable to suppress errors from docbuilding + +2006-05-30 Thomas Vander Stichele <thomas (at) apestaart (dot) org> + + * gtk-doc.mak: + error out if gtkdoc-mktmpl finds unused declarations + +2006-05-28 Edward Hervey <edward@fluendo.com> + + * gst.supp: + Reverting previous commit. That's good to know, Edward, but why ? + +2006-05-28 Edward Hervey <edward@fluendo.com> + + * gst.supp: + Added suppresion for memleak in g_option_context_parse on fc5-64 + +2006-05-19 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + set GSTPB_PLUGINS_DIR just like GST_PLUGINS_DIR + +2006-05-18 Tim-Philipp Müller <tim at centricular dot net> + + * check.mak: + Fix 'make help' in check directories, it should be + 'valgrind.gen-suppressions' not 'valgrind-gen-suppressions' + (not changing target to match help string on purpose to keep + scripts etc. functional). + +2006-05-18 Thomas Vander Stichele <thomas at apestaart dot org> + + Patch by: Peter Kjellerstedt + + * m4/gst-arch.m4: + add support for CRIS and CRISv32. + +2006-05-17 Jan Schmidt <thaytan@mad.scientist.com> + + * m4/gst-args.m4: + Fix the macros for command-line supplied package and origin names + so they don't end up being configure as "" (Fixes #341479) + +2006-05-14 Jan Schmidt <thaytan@mad.scientist.com> + + * gtk-doc.mak: + Add uninstall rule to remove .devhelp2 files. + +2006-05-09 Edward Hervey <edward@fluendo.com> + + * gst.supp: + Add suppression for GSlice version of + g_type_init calloc leak + +2006-04-05 Michael Smith <msmith@fluendo.com> + + * gst.supp: + Delete a bogus suppression for the registry code. + Generalise a suppression for a glib bug (see #337404) + +2006-04-04 Michael Smith <msmith@fluendo.com> + + * gst.supp: + Add a leak suppression: the existing glibc-doesn't-free-TLS one + wasn't triggering here. + +2006-04-04 Michael Smith <msmith@fluendo.com> + + * gst.supp: + Add some minimally-neccesary suppressions for my x86/dapper system. + +2006-04-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * plugins.xsl: + Do not display an origin link if origin does not start with http + See #323798 + +2006-04-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + * m4/gst-feature.m4: + add more macros + * m4/gst-x11.m4: + X11-related checks + +2006-04-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-version.m4: + newer version + * m4/gst-args.m4: + * m4/gst-doc.m4: + update and add other macros to be shared across projects + +2006-03-24 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst.supp: + add a suppression for g_parse_debug_string + +2006-03-23 Stefan Kost <ensonic@users.sf.net> + + * gstdoc-scangobj: + sync fully with gtkdoc-0.15 + +2006-03-23 Stefan Kost <ensonic@users.sf.net> + + * gstdoc-scangobj: + * gtk-doc.mak: + sync a little with gtk-doc mainline + +2006-03-17 Wim Taymans <wim@fluendo.com> + + * gst.supp: + add another clone suppression + change all glibc suppressions to match 2.3.* + +2006-03-09 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/check.m4: + fix test so it actually works when the normal check is used + over debian's/ubuntu's + +2006-03-08 Jan Schmidt <thaytan@mad.scientist.com> + + * check.mak: + Set G_SLICE=always-malloc when valgrinding tests + (closes #333272) + +2006-02-21 Jan Schmidt <thaytan@mad.scientist.com> + + * m4/gst-glib2.m4: + Fix debug output when the GLib version prerequisite is not found + +2006-02-13 Andy Wingo <wingo@pobox.com> + + * m4/check.m4: Hack around Debian/Ubuntu's broken installation of + the PIC version of check as libcheck_pic.a. Should work with + cross-compilation too. Grr. + +2006-02-06 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-default.m4: + switch to auto* sinks for defaults + +2006-02-02 Wim Taymans <wim@fluendo.com> + + * check.mak: + add a .valgrind.gen-suppressions target to aid in generating + suppressions + * gst.supp: + add more repressions from my debian glibc as of today + +2006-02-02 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak: + only add srcdir/gst if it exists + +2006-01-30 Thomas Vander Stichele <thomas at apestaart dot org> + + * release.mak: + don't complain about disted enums in win32 + +2006-01-20 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + AC_SUBST CFLAGS and LIBS + do a non-command because something is stripping out our AC_SUBST + +2006-01-20 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + * m4/gst-valgrind.m4: + properly give a "no" result manually when providing a + not-found action to fix configure output + +2006-01-20 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/pkg.m4: + update with a more recent version + +2006-01-07 Thomas Vander Stichele <thomas at apestaart dot org> + + * gettext.patch: + make Makefile depend on LINGUAS, so rebuilds work when adding + a language + +2006-01-03 Michael Smith <msmith@fluendo.com> + + * check.mak: + Clarify error message from valgrind test runs. + +2005-12-16 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-arch.m4: + define HOST_CPU + +2005-11-29 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + add a valgrind-forever target for tests + +2005-11-28 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + when a "make test.check" run fails, make it rerun the test with + at least debug level 2 + +2005-11-14 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/Makefile.am: + * m4/gst-check.m4: + fix check for base plugins + * m4/gst-default.m4: + add m4 to set default elements + +2005-10-18 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + check for tools correctly + +2005-10-18 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc.mak: + only enable breaking on new API when make distcheck passes, + not before + +2005-10-18 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + Resurrect Julien's dead body and wipe his mind clean + +2005-10-18 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-check.m4: + Kill Julien + +2005-10-17 Julien MOUTTE <julien@moutte.net> + + * m4/gst-check.m4: I know Thomas will kill me but this + ifelse statement seems incorrect as it is always setting + required to "yes". With this one it seems to work. Fixes + build of gst-plugins-base on my setup where gstreamer-check + is definitely not present/required. + +2005-10-18 Stefan Kost <ensonic@users.sf.net> + + * gtk-doc.mak: + make build break on new api that has not been added to the + sections file + +2005-10-17 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-glib2.m4: + * m4/Makefile.am: + * m4/gst-check.m4: + add macro for easy checks for GStreamer libs + +2005-10-16 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-glib2.m4: + update, warn in error cases + +2005-10-16 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-error.m4: + add GST_SET_DEFAULT_LEVEL + +2005-10-16 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/Makefile.am: + * m4/gst-gettext.m4: + remove the AM_GNU_GETTEXT* calls, they need to be in configure.ac + * m4/gst-glib2.m4: + clean up and re-use in core soon + * m4/gst-plugindir.m4: + macro to set up PLUGINDIR and plugindir define/var + +2005-10-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/Makefile.am: + * m4/gst-gettext.m4: + add macro for setting up gettext + +2005-10-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-args.m4: + add some .m4's for argument checking that can be shared among modules + +2005-10-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-libtool.m4: + set _LT_LDFLAGS + * m4/gst-libxml2.m4: + document + +2005-10-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-arch.m4: + indent a little + add AC_REQUIRE + * m4/gst-error.m4: + clean up + +2005-10-12 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-autogen.sh: + update version detection expression to catch stuff like + Libtool (libtool15) 1.5.0 + +2005-10-11 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst.supp: + commit 6 new suppressions related to g_module_open; can these + really not be folded into one ? + +2005-10-11 Edward Hervey <edward@fluendo.com> + + * gst.supp: + made the <g_type_init calloc 2> suppression more generic + Added pthread memleak suppresions + Added nss_parse_* memleak suppresion (used by g_option_context_parse) + +2005-10-11 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + be more strict, more leak resolution + * gst.supp: + clean up the g_type_init suppressions + +2005-10-07 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/Makefile.am: + * m4/gst-valgrind.m4: + put the valgrind detection in an .m4 + +2005-09-29 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + add some more targets, like "help", but also more intensive tests + +2005-09-23 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc.mak: + make certain doc warnings fatal so people maintain docs again + +2005-09-23 Thomas Vander Stichele <thomas at apestaart dot org> + + * Makefile.am: + * gtk-doc-plugins.mak: + * scangobj-merge.py: + merge additions from the .signals.new and .args.new file in + the original ones, only updating if necessary + +2005-09-23 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-xmlinspect.py: + * gstdoc-scangobj: + * gtk-doc-plugins.mak: + fix properly for new API; make update in plugins dir now works + +2005-09-20 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-xmlinspect.py: + * gstdoc-scangobj: + some fixes for new API + * gtk-doc-plugins.mak: + set environment properly + +2005-09-17 David Schleef <ds@schleef.org> + + * gtk-doc-plugins.mak: Use new environment variables. + +2005-09-16 Michael Smith <msmith@fluendo.com> + + * gstdoc-scangobj: + Make the scanobj code reflect registry/plugin API changes + +2005-09-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak: + split out scanobj step (which will be run by doc maintainer) + from scan step (which will be run on every build) + clean up some of the commands for make distcheck + +2005-09-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak: + * mangle-tmpl.py: + first stab at reorganizing the plugins build so we can maintain + element docs + +2005-09-14 David Schleef <ds@schleef.org> + + * as-libtool.mak: Remove + * m4/as-libtool.m4: The libtool bug that this worked around has + been fixed. + * m4/as-version.m4: Don't define GST_RELEASE, since it causes + config.h to be regenerated needlessly, and we don't use it. + +2005-09-14 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak: + error out on inspect failure + +2005-09-14 Michael Smith <msmith@fluendo.com> + + * glib-gen.mak: + Don't call glib-mkenums with arguments that confuse/break MinGW, + fixes 316155. + +2005-09-03 Thomas Vander Stichele <thomas at apestaart dot org> + + * gtk-doc-plugins.mak: + * gtk-doc.mak: + * m4/gst-doc.m4: + separate out gtk-doc and docbook stuff + have two separate --enable configure flags + +2005-08-26 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + add a .gdb target; rebuild registry for each target, otherwise + a code rebuild always triggers a reg rebuild, and it's just too + annoying + * gstdoc-scangobj: + +2005-08-21 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + separate out REGISTRY_ENVIRONMENT; we want to use that from + our valgrind runs, but we also want TESTS_ENVIRONMENT to contain + everything that the first test, gst-register, needs + +2005-08-21 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + parse output of valgrind and check for definitely lost, and error + out; somehow I was led to believe valgrind returns non-zero for + leaks, but I can't make it do that, so let's parse + +2005-08-20 Thomas Vander Stichele <thomas at apestaart dot org> + + * check.mak: + for some weird reason valgrind does not report actual memleaks + if GST_PLUGIN_PATH is set to anything but the core gstreamer dir + while valgrind is running. Since the registry is going to go + anyway, I don't want to waste any more time on this; I just run + valgrind without GST_PLUGIN_PATH set. Since the registry loading + doesn't check if GST_PLUGIN_PATH got changed as a reason to rebuild + the registry, that's actually fine. + +2005-08-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * mangle-tmpl.py: + keep original Long_Description; only insert an include if it's + not already the first line in there + * plugins.xsl: + output more information for plugins, including an origin hyperlink + +2005-08-15 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-xmlinspect.py: + a first stab at inspecting plugins and outputting an xml description + * gtk-doc-plugins.mak: + a gtk-doc using snippet for plugins documentation + * plugins.xsl: + a stylesheet to convert gst-xmlinspect.py output to docbook output + for inclusion in the gtk-doc stuff + +2005-07-20 Ronald S. Bultje <rbultje@ronald.bitfreak.net> + + * m4/gst-doc.m4: + s/pdf/eps/ in test for whether we output EPS images (#309379). + +2005-07-18 Andy Wingo <wingo@pobox.com> + + * m4/as-libtool-tags.m4: Ooh, backported from libtool 1.6. Much + better. Thanks, Paolo Bonzini! + + * m4/Makefile.am (EXTRA_DIST): + * m4/as-libtool-tags.m4: New file, tries to disable some CXX and + fortran checks. + +2005-07-08 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-error.m4: + add macro to set ERROR_CFLAGS + +2005-06-30 Jan Schmidt <thaytan@mad.scientist.com> + + * gst-autogen.sh: + Remove the old autoregen.sh if it exists before recreating it, + to prevent confusing any shell process that might be reading it + currently. + +2005-06-29 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gtk-doc.m4: + added + +2005-06-03 Stefan Kost <ensonic@users.sf.net> + + * gst-autogen.sh: create autoregen.sh *before* shifting the options + +2005-05-17 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-autogen.sh: only update autoregen.sh on actual runs + +2005-03-11 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/check.m4: m4 from the check unit test suite + +2004-12-14 David Schleef <ds@schleef.org> + + * m4/gst-arch.m4: remove MMX stuff, since it doesn't work and + isn't needed anywhere + +2004-12-08 Thomas Vander Stichele <thomas at apestaart dot org> + + * gst-autogen.sh: + allow failure command to be run so we can clean upfrom autopoint + +2004-09-03 Zeeshan Ali Khattak <zeenix@gmail.com> + * m4/gst-feature.m4: Trying to correct the GST_CHECK_CONFIGPROG macro + +2004-07-21 Benjamin Otte <otte@gnome.org> + + * m4/.cvsignore: exciting updates for libtool m4 files + +2004-07-12 David Schleef <ds@schleef.org> + + * m4/as-objc.m4: Add a macro to test for objective C + +2004-06-12 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-feature.m4: + not all of them support --plugin-libs, so redirect stderr + +2004-06-12 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-scrub-include.m4: + sync with upstream to 0.1.4. Fixes #132440 + +2004-06-07 Benjamin Otte <otte@gnome.org> + + * m4/gst-feature.m4: + write a big marker into configure output when checking next plugin + to allow easier parsing of why plugins are(n't) built. + +2004-06-01 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-compiler-flag.m4: + * m4/as-compiler.m4: + * m4/as-libtool.m4: + * m4/as-version.m4: + sync with upstream, change sticky options to -ko + +2004-05-24 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-scrub-include.m4: synced with upstream + +2004-05-03 Thomas Vander Stichele <thomas at apestaart dot org> + + * po.mak: + snippet for updating .po files + +2004-03-18 Thomas Vander Stichele <thomas at apestaart dot org> + + * Makefile.am: + * m4/Makefile.am: + integrate these with the dist + +2004-03-17 Thomas Vander Stichele <thomas at apestaart dot org> + + * release.mak: add a release target + +2004-03-09 Thomas Vander Stichele <thomas at apestaart dot org> + + patch by: Stephane Loeuillet + + * m4/ax_create_stdint_h.m4: + use head -n instead of head - (#136500) + +2004-03-05 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-doc.m4: don't build PS without dvips binary + +2004-02-22 Julio M. Merino Vidal <jmmv@menta.net> + + reviewed by: Benjamin Otte <otte@gnome.org> + + * m4/as-docbook.m4: + don't use == operator with test(1) (fixes #135115) + +2004-02-16 Thomas Vander Stichele <thomas at apestaart dot org> + + * common/m4/gst-arch.m4: x86_64 is x86 too (clue from Fedora 2 test) + +2004-02-13 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-feature.m4: + remove AM_CONDITIONAL for the subsystem since automake 1.6.x + requires that call be in configure.ac + +2004-02-13 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-libxml2.m4: + take required version as argument, and default to 2.4.9 if not + specified + +2004-02-12 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/gst-feature.m4: + rename and fix up GST_CHECK_DISABLE_SUBSYSTEM + +2004-02-11 Thomas Vander Stichele <thomas at apestaart dot org> + + * common/m4/as-ac-expand.m4: + * common/m4/as-auto-alt.m4: + * common/m4/as-compiler-flag.m4: + * common/m4/as-compiler.m4: + * common/m4/as-docbook.m4: + * common/m4/as-libtool.m4: + * common/m4/as-scrub-include.m4: + * common/m4/as-version.m4: + * common/m4/glib-gettext.m4: + * common/m4/gst-arch.m4: + * common/m4/gst-debuginfo.m4: + * common/m4/gst-doc.m4: + * common/m4/gst-feature.m4: + * common/m4/gst-function.m4: + * common/m4/gst-glib2.m4: + * common/m4/gst-gstreamer.m4: + * common/m4/gst-libxml2.m4: + * common/m4/gst-makecontext.m4: + * common/m4/gst-mcsc.m4: + * common/m4/pkg.m4: + fix underquoted macros as reported by automake 1.8.x (#133800) + +2004-02-11 Johan Dahlin <johan@gnome.org> + + * gst-autogen.sh: Use A-Z instead of A-z in sed expression to + avoid a warning + +2004-02-05 Thomas Vander Stichele <thomas (at) apestaart (dot) org> + + * m4/gst-doc.m4: + we use --output-format=xml and --ingnore-files options to + gtkdoc-mkdb, which got added between 0.9 and 1.0 + +2004-02-04 Thomas Vander Stichele <thomas at apestaart dot org> + + * m4/as-libtool.m4: remove AM_PROG_LIBTOOL so it can move back + to configure.ac to shut up libtoolize + +2004-02-03 Thomas Vander Stichele <thomas at apestaart dot org> + + * glib-gen.mak: added; used to generate enums and marshal code + +2004-01-13 Thomas Vander Stichele <thomas at apestaart dot org> + + * gettext.patch: added; used by autogen.sh to make sure + GETTEXT_PACKAGE is understood from po/Makefile.in.in -> po/Makefile.in + diff --git a/gst-plugins-base-subtitles0.10/common/Makefile.am b/gst-plugins-base-subtitles0.10/common/Makefile.am new file mode 100644 index 0000000..25966fc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = m4 + +EXTRA_DIST = \ + ChangeLog \ + gettext.patch \ + glib-gen.mak gtk-doc.mak upload-doc.mak \ + cruft.mak release.mak win32.mak po.mak \ + parallel-subdirs.mak \ + gst-autogen.sh \ + check-exports \ + c-to-xml.py mangle-tmpl.py scangobj-merge.py \ + gtk-doc-plugins.mak \ + plugins.xsl gstdoc-scangobj \ + gst.supp check.mak \ + coverage/lcov.mak \ + coverage/coverage-report.pl \ + coverage/coverage-report.xsl \ + coverage/coverage-report-entry.pl \ + download-translations \ + extract-release-date-from-doap-file \ + gst-indent \ + orc.mak diff --git a/gst-plugins-base-subtitles0.10/common/c-to-xml.py b/gst-plugins-base-subtitles0.10/common/c-to-xml.py new file mode 100644 index 0000000..397c112 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/c-to-xml.py @@ -0,0 +1,34 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +Convert a C program to valid XML to be included in docbook +""" + +import sys +import os +from xml.sax import saxutils + +def main(): + if len(sys.argv) == 1: + sys.stderr.write("Please specify a source file to convert") + sys.exit(1) + source = sys.argv[1] + + if not os.path.exists(source): + sys.stderr.write("%s does not exist.\n" % source) + sys.exit(1) + + content = open(source, "r").read() + + # print header + print '<?xml version="1.0"?>' + print '<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">' + print + print '<programlisting>' + + # print content + print saxutils.escape(content).encode('UTF-8') + print '</programlisting>' + +main() diff --git a/gst-plugins-base-subtitles0.10/common/check-exports b/gst-plugins-base-subtitles0.10/common/check-exports new file mode 100755 index 0000000..c6d3eca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/check-exports @@ -0,0 +1,72 @@ +#!/bin/sh +# check-exports +# +# quick'n'dirty script that retrieves the list of exported symbols of a given +# library using 'nm', and compares that against the list of symbols-to-export +# of our win32/common/libfoo.def files. + +if [ $# -ne 2 ]; then + echo "Usage: $0 library.def library.so" + exit 1 +fi + +def_path="$1" +def_name="$(basename $def_path)" +lib_path="$2" + +lib_result="`mktemp /tmp/defname.XXXXXX`" + +LC_ALL=C +export LC_ALL + +# On Solaris, add -p to get the correct output format +NMARGS= +if nm -V 2>&1 |grep Solaris > /dev/null; then + NMARGS=-p +fi + +# FIXME 0.11: in 0.11, we should change the export filter to only export +# _gst_foo, but not __gst_foo (we can't change this now, since we added +# __gst_debug_min and __gst_debug_enabled at some point and need to keep +# ABI compatibility). So below we special-case some symbols that shouldn't +# really be exported, either because we're too lazy to rename them to something +# that's not exported (like the _gst_parse_* stuff) or because we had them in +# public headers at some point although they shouldn't be and so we need to +# keep them exported now (like _gst_debug_init, +# __gst_element_factory_add_interface or +# __gst_element_factory_add_static_pad_template). We suppress them here to +# make sure they're at least not exported in the windows msvc build (they +# were never in the .def file, so they never got exported). +# _end is special cased because for some reason it is reported as an exported +# BSS symbol, unlike on linux where it's a local absolute symbol. +nm $NMARGS $lib_path | awk \ + '{ + if ($3 !~ /^_gst_parse_yy/ && \ + $3 !~ /^_gst_[a-z]*_init/ && \ + $3 !~ /^_gst_parse_launch/ && \ + $3 !~ /^__gst_element_details_/ && \ + $3 !~ /^__gst_element_factory_add_/ && \ + $3 !~ /^gst_interfaces_marshal/ && \ + $3 ~ /^[_]*(gst_|Gst|GST_).*/) + { + if ($2 ~ /^[BSDG]$/) + print "\t" $3 " DATA" + else if ($2 == "T") + print "\t" $3 + } + }' | sort | awk '{ if (NR == 1) print "EXPORTS"; print $0; }' \ + > $lib_result + +diffoutput=`diff -u $def_path $lib_result` +diffresult=$? + +rm $lib_result + +if test "$diffresult" -eq 0; then + exit 0; +else + echo -n "$diffoutput" >&2 + echo >&2 + exit 1; +fi + diff --git a/gst-plugins-base-subtitles0.10/common/check.mak b/gst-plugins-base-subtitles0.10/common/check.mak new file mode 100644 index 0000000..30487f1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/check.mak @@ -0,0 +1,181 @@ +# keep target around, since it's referenced in the modules' Makefiles +clean-local-check: + @echo + +if HAVE_VALGRIND +# hangs spectacularly on some machines, so let's not do this by default yet +check-valgrind: + $(MAKE) valgrind +else +check-valgrind: + @true +endif + +LOOPS = 10 + +# run any given test by running make test.check +# if the test fails, run it again at at least debug level 2 +%.check: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || \ + $(TESTS_ENVIRONMENT) \ + GST_DEBUG=$$GST_DEBUG,*:2 \ + CK_DEFAULT_TIMEOUT=20 \ + $* + +# run any given test in a loop +%.torture: % + @for i in `seq 1 $(LOOPS)`; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $*; done + +# run any given test in an infinite loop +%.forever: % + @while true; do \ + $(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=20 \ + $* || break; done + +# valgrind any given test by running make test.valgrind +%.valgrind: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --leak-resolution=high --num-callers=20 \ + ./$* 2>&1 | tee valgrind.log + @if grep "==" valgrind.log > /dev/null 2>&1; then \ + rm valgrind.log; \ + exit 1; \ + fi + @rm valgrind.log + +# valgrind any given test and generate suppressions for it +%.valgrind.gen-suppressions: % + @$(TESTS_ENVIRONMENT) \ + CK_DEFAULT_TIMEOUT=360 \ + G_SLICE=always-malloc \ + $(LIBTOOL) --mode=execute \ + $(VALGRIND_PATH) -q \ + $(foreach s,$(SUPPRESSIONS),--suppressions=$(s)) \ + --tool=memcheck --leak-check=full --trace-children=yes \ + --leak-resolution=high --num-callers=20 \ + --gen-suppressions=all \ + ./$* 2>&1 | tee suppressions.log + +# valgrind any given test until failure by running make test.valgrind-forever +%.valgrind-forever: % + @while $(MAKE) $*.valgrind; do \ + true; done + +# gdb any given test by running make test.gdb +%.gdb: % + @$(TESTS_ENVIRONMENT) \ + CK_FORK=no \ + $(LIBTOOL) --mode=execute \ + gdb $* + +# torture tests +torture: $(TESTS) + -rm test-registry.xml + @echo "Torturing tests ..." + @for i in `seq 1 $(LOOPS)`; do \ + $(MAKE) check || \ + (echo "Failure after $$i runs"; exit 1) || \ + exit 1; \ + done + @banner="All $(LOOPS) loops passed"; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo $$dashes; echo $$banner; echo $$dashes + +# forever tests +forever: $(TESTS) + -rm test-registry.xml + @echo "Forever tests ..." + @while true; do \ + $(MAKE) check || \ + (echo "Failure"; exit 1) || \ + exit 1; \ + done + +# valgrind all tests +valgrind: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi + +# valgrind all tests and generate suppressions +valgrind.gen-suppressions: $(TESTS) + @echo "Valgrinding tests ..." + @failed=0; \ + for t in $(filter-out $(VALGRIND_TESTS_DISABLE),$(TESTS)); do \ + $(MAKE) $$t.valgrind.gen-suppressions; \ + if test "$$?" -ne 0; then \ + echo "Valgrind error for test $$t"; \ + failed=`expr $$failed + 1`; \ + whicht="$$whicht $$t"; \ + fi; \ + done; \ + if test "$$failed" -ne 0; then \ + echo "$$failed tests had leaks or errors under valgrind:"; \ + echo "$$whicht"; \ + false; \ + fi + +# inspect every plugin feature +GST_INSPECT = $(GST_TOOLS_DIR)/gst-inspect-$(GST_MAJORMINOR) +inspect: + @echo "Inspecting features ..." + @for e in `$(TESTS_ENVIRONMENT) $(GST_INSPECT) | head -n -2 \ + | cut -d: -f2`; \ + do echo Inspecting $$e; \ + $(GST_INSPECT) $$e > /dev/null 2>&1; done + +help: + @echo + @echo "make check -- run all checks" + @echo "make torture -- run all checks $(LOOPS) times" + @echo "make (dir)/(test).check -- run the given check once" + @echo "make (dir)/(test).forever -- run the given check forever" + @echo "make (dir)/(test).torture -- run the given check $(LOOPS) times" + @echo + @echo "make (dir)/(test).gdb -- start up gdb for the given test" + @echo + @echo "make valgrind -- valgrind all tests" + @echo "make valgrind.gen-suppressions -- generate suppressions for all tests" + @echo " and save to suppressions.log" + @echo "make (dir)/(test).valgrind -- valgrind the given test" + @echo "make (dir)/(test).valgrind-forever -- valgrind the given test forever" + @echo "make (dir)/(test).valgrind.gen-suppressions -- generate suppressions" + @echo " and save to suppressions.log" + @echo "make inspect -- inspect all plugin features" + @echo + @echo + @echo "Additionally, you can use the GST_CHECKS environment variable to" + @echo "specify which test(s) should be run. This is useful if you are" + @echo "debugging a failure in one particular test, or want to reproduce" + @echo "a race condition in a single test." + @echo + @echo "Examples:" + @echo + @echo " GST_CHECKS=test_this,test_that make element/foobar.check" + @echo " GST_CHECKS=test_many_threads make element/foobar.forever" + @echo + diff --git a/gst-plugins-base-subtitles0.10/common/coverage/coverage-report-entry.pl b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report-entry.pl new file mode 100644 index 0000000..51c506c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report-entry.pl @@ -0,0 +1,69 @@ +#!/usr/bin/perl +# +# Copyright (C) 2006 Daniel Berrange +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +print <<EOF; +<html> +<head> +<title>Coverage report for $ARGV[0] + + + +

Coverage report for $ARGV[0]

+ +
+EOF
+
+
+while (<>) {
+    s/&/&/g;
+    s//>/g;
+
+    if (/^\s*function (\S+) called (\d+) returned \d+% blocks executed \d+%/) {
+	my $class = $2 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    } elsif (/^\s*branch\s+\d+\s+taken\s+(\d+)%\s+.*$/) {
+	my $class = $1 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    } elsif (/^\s*branch\s+\d+\s+never executed.*$/) {
+	my $class = "terrible";
+	$_ = "$_";
+    } elsif (/^\s*call\s+\d+\s+never executed.*$/) {
+	my $class = "terrible";
+	$_ = "$_";
+    } elsif (/^\s*call\s+\d+\s+returned\s+(\d+)%.*$/) {
+	my $class = $1 > 0 ? "perfect" : "terrible";
+	$_ = "$_";
+    }
+
+    print;
+}
+
+print <
+
+
+EOF
diff --git a/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.pl b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.pl
new file mode 100644
index 0000000..ed30f8d
--- /dev/null
+++ b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.pl
@@ -0,0 +1,125 @@
+#!/usr/bin/perl
+#
+# Copyright (C) 2006 Daniel Berrange
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+use warnings;
+use strict;
+
+my %coverage = ( functions => {}, files => {} );
+
+my %filemap;
+
+my $type;
+my $name;
+
+my @functions;
+
+while (<>) {
+    if (/^Function '(.*)'\s*$/) {
+	$type = "function";
+	$name = $1;
+	$coverage{$type}->{$name} = {};
+	push @functions, $name;
+    } elsif (/^File '(.*?)'\s*$/) {
+	$type = "file";
+	$name = $1;
+	$coverage{$type}->{$name} = {};
+
+	foreach my $func (@functions) {
+	    $coverage{"function"}->{$func}->{file} = $name;
+	}
+	@functions = ();
+    } elsif (/^Lines executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{lines} = $2;
+	$coverage{$type}->{$name}->{linesCoverage} = $1;
+    } elsif (/^Branches executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{branches} = $2;
+	$coverage{$type}->{$name}->{branchesCoverage} = $1;
+    } elsif (/^Taken at least once:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{conds} = $2;
+	$coverage{$type}->{$name}->{condsCoverage} = $1;
+    } elsif (/^Calls executed:(.*)%\s*of\s*(\d+)\s*$/) {
+	$coverage{$type}->{$name}->{calls} = $2;
+	$coverage{$type}->{$name}->{callsCoverage} = $1;
+    } elsif (/^No branches$/) {
+	$coverage{$type}->{$name}->{branches} = 0;
+	$coverage{$type}->{$name}->{branchesCoverage} = "100.00";
+	$coverage{$type}->{$name}->{conds} = 0;
+	$coverage{$type}->{$name}->{condsCoverage} = "100.00";
+    } elsif (/^No calls$/) {
+	$coverage{$type}->{$name}->{calls} = 0;
+	$coverage{$type}->{$name}->{callsCoverage} = "100.00";
+    } elsif (/^\s*(.*):creating '(.*)'\s*$/) {
+	$filemap{$1} = $2;
+    } elsif (/^\s*$/) {
+	# nada
+    } else {
+	warn "Shit [$_]\n";
+    }
+}
+
+my %summary;
+foreach my $type ("function", "file") {
+    $summary{$type} = {};
+    foreach my $m ("lines", "branches", "conds", "calls") {
+	my $totalGot = 0;
+	my $totalMiss = 0;
+	my $count = 0;
+	foreach my $func (keys %{$coverage{function}}) {
+	    $count++;
+	    my $got = $coverage{function}->{$func}->{$m};
+	    $totalGot += $got;
+	    my $miss = $got * $coverage{function}->{$func}->{$m ."Coverage"} / 100;
+	    $totalMiss += $miss;
+	}
+	$summary{$type}->{$m} = sprintf("%d", $totalGot);
+	$summary{$type}->{$m . "Coverage"} = sprintf("%.2f", $totalMiss / $totalGot * 100);
+    }
+}
+
+
+
+print "\n";
+
+foreach my $type ("function", "file") {
+    printf "<%ss>\n", $type;
+    foreach my $name (sort { $a cmp $b } keys %{$coverage{$type}}) {
+	my $rec = $coverage{$type}->{$name};
+	printf "  \n", $name, ($type eq "file" ? $filemap{$name} : $filemap{$rec->{file}});
+	printf "    \n", $rec->{lines}, $rec->{linesCoverage};
+	if (exists $rec->{branches}) {
+	    printf "    \n", $rec->{branches}, $rec->{branchesCoverage};
+	}
+	if (exists $rec->{conds}) {
+	    printf "    \n", $rec->{conds}, $rec->{condsCoverage};
+	}
+	if (exists $rec->{calls}) {
+	    printf "    \n", $rec->{calls}, $rec->{callsCoverage};
+	}
+	print  "  \n";
+    }
+
+    printf "  \n";
+    printf "    \n", $summary{$type}->{lines}, $summary{$type}->{linesCoverage};
+    printf "    \n", $summary{$type}->{branches}, $summary{$type}->{branchesCoverage};
+    printf "    \n", $summary{$type}->{conds}, $summary{$type}->{condsCoverage};
+    printf "    \n", $summary{$type}->{calls}, $summary{$type}->{callsCoverage};
+    printf  "  \n";
+    printf "\n", $type;
+}
+
+print "\n";
diff --git a/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.xsl b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.xsl
new file mode 100644
index 0000000..b19ebb6
--- /dev/null
+++ b/gst-plugins-base-subtitles0.10/common/coverage/coverage-report.xsl
@@ -0,0 +1,235 @@
+
+
+
+
+  
+
+  
+    
+      
+        Coverage report
+        
+      
+      
+        

Coverage report

+ + + +
+ + +

Function coverage

+ + + +
+ + + +

File coverage

+ + + +
+ + + + + + + + + + + + + + + + + + + + + odd + + + even + + + + + + + + + + + + + + odd + + + even + + + + + + +
NameLinesBranchesConditionsCalls
+
+ + + + + + + + + + + + + + Summary + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + perfect + + + excellant + + + good + + + poor + + + bad + + + terrible + + + + + % of + + +
diff --git a/gst-plugins-base-subtitles0.10/common/coverage/lcov.mak b/gst-plugins-base-subtitles0.10/common/coverage/lcov.mak new file mode 100644 index 0000000..fc1f6b2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/coverage/lcov.mak @@ -0,0 +1,43 @@ +## .PHONY so it always rebuilds it +.PHONY: lcov-reset lcov lcov-run lcov-report lcov-upload + +# run lcov from scratch, always +lcov-reset: + $(MAKE) lcov-run + $(MAKE) lcov-report + +# run lcov from scratch if the dir is not there +lcov: + $(MAKE) lcov-reset + +if GST_GCOV_ENABLED +# reset run coverage tests +lcov-run: + @-rm -rf lcov + lcov --directory . --zerocounters + -if test -d tests/check; then $(MAKE) -C tests/check inspect; fi + -$(MAKE) check + +# generate report based on current coverage data +lcov-report: + mkdir lcov + lcov --compat-libtool --directory . --capture --output-file lcov/lcov.info + lcov --list-full-path -l lcov/lcov.info | grep -v "`cd $(top_srcdir) && pwd`" | cut -d\| -f1 > lcov/remove + lcov --list-full-path -l lcov/lcov.info | grep "tests/check/" | cut -d\| -f1 >> lcov/remove + lcov --list-full-path -l lcov/lcov.info | grep "docs/plugins/" | cut -d\| -f1 >> lcov/remove + lcov -r lcov/lcov.info `cat lcov/remove` > lcov/lcov.cleaned.info + rm lcov/remove + mv lcov/lcov.cleaned.info lcov/lcov.info + genhtml -t "$(PACKAGE_STRING)" -o lcov --num-spaces 2 lcov/lcov.info + +lcov-upload: lcov + rsync -rvz -e ssh --delete lcov/* gstreamer.freedesktop.org:/srv/gstreamer.freedesktop.org/www/data/coverage/lcov/$(PACKAGE) + +else +lcov-run: + echo "Need to reconfigure with --enable-gcov" + +lcov-report: + echo "Need to reconfigure with --enable-gcov" +endif + diff --git a/gst-plugins-base-subtitles0.10/common/cruft.mak b/gst-plugins-base-subtitles0.10/common/cruft.mak new file mode 100644 index 0000000..53eec24 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/cruft.mak @@ -0,0 +1,56 @@ +# checks for left-over files in the (usually uninstalled) tree, ie. for +# stuff that best be deleted to avoid problems like having old plugin binaries +# lying around. +# +# set CRUFT_FILES and/or CRUFT_DIRS in your Makefile.am when you include this + +check-cruft: + @cruft_files=""; cruft_dirs=""; \ + for f in $(CRUFT_FILES); do \ + if test -e $$f; then \ + cruft_files="$$cruft_files $$f"; \ + fi \ + done; \ + for d in $(CRUFT_DIRS); do \ + if test -e $$d; then \ + cruft_dirs="$$cruft_dirs $$d"; \ + fi \ + done; \ + if test "x$$cruft_files$$cruft_dirs" != x; then \ + echo; \ + echo "**** CRUFT ALERT *****"; \ + echo; \ + echo "The following files and directories may not be needed any "; \ + echo "longer (usually because a plugin has been merged into "; \ + echo "another plugin, moved to a different module, or been "; \ + echo "renamed), and you probably want to clean them up if you "; \ + echo "don't have local changes: "; \ + echo; \ + for f in $$cruft_files; do echo "file $$f"; done; \ + echo; \ + for d in $$cruft_dirs; do echo "directory $$d"; done; \ + echo; \ + echo "'make clean-cruft' will remove these for you."; \ + echo; \ + fi + +clean-cruft-dirs: + @for d in $(CRUFT_DIRS); do \ + if test -e $$d; then \ + rm -r "$$d" && echo "Removed directory $$d"; \ + fi \ + done + +clean-cruft-files: + @for f in $(CRUFT_FILES); do \ + if test -e $$f; then \ + rm "$$f" && echo "Removed file $$f"; \ + fi \ + done + +clean-cruft: clean-cruft-dirs clean-cruft-files + +# also might want to add this to your Makefile.am: +# +# all-local: check-cruft + diff --git a/gst-plugins-base-subtitles0.10/common/download-translations b/gst-plugins-base-subtitles0.10/common/download-translations new file mode 100755 index 0000000..aef1d31 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/download-translations @@ -0,0 +1,152 @@ +#!/bin/sh +# Shell script to download the latest translations for a given GStreamer +# package from translationproject.org + + +# DOMAINS based on http://translationproject.org/extra/matrix.html +# We need to check all domains, not only po/LINGUAS, since there might be +# new translations +DOMAINS=\ +"af am ar az be bg pt_BR bs ca zh_CN cs cy da de el eo es et eu fa fi fr "\ +"ga en_GB gl gu he hi zh_HK hr hu id is it ja ko ku ky lg lt lv mk mn ms "\ +"mt nb ne nl nn or pa pl pt rm ro ru rw sk sl sq sr sv ta tq th tk "\ +"tr zh_TW uk ven vi wa xh zu" + +# for testing/debugging: +#DOMAINS="es fr hu sv pl xx" + +# check for 'diff' program +diff --version 2>/dev/null >/dev/null +if [ ! $? ]; then + echo "==== You must have the 'diff' program installed for this script ====" + exit 1 +fi + +# check for 'wget' program +wget --version 2>/dev/null >/dev/null +if [ ! $? ]; then + echo "==== You must have the 'wget' program installed for this script ====" + exit 1 +fi + +# make sure we're in the top-level directory +if [ ! -d ./po ]; then + echo "==== No ./po directory in the current working directory ====" + exit 1 +fi + +# make sure a package argument was passed to us +if [ -z "$1" ]; then + echo "Usage: $0 PACKAGE, e.g. $0 gst-plugins-good" + exit 1 +fi + +if test "$1" != "gstreamer" -a \ + "$1" != "gst-plugins-base" -a \ + "$1" != "gst-plugins-good" -a \ + "$1" != "gst-plugins-ugly" -a \ + "$1" != "gst-plugins-bad"; then + echo "Unexpected package '$1' ?!" + exit 1 +fi + +PACKAGE="$1" + +DOMAINS_TO_ADD="" +DOMAINS_UPDATED="" +DOMAINS_NOT_IN_LINGUAS="" + +echo "Downloading latest translation files for package $PACKAGE ..." +echo + +for d in $DOMAINS +do + PACKAGE_PO_URL_BASE="http://translationproject.org/latest/$PACKAGE" + PO_URL="$PACKAGE_PO_URL_BASE/$d.po" + PO_FILENAME="$PACKAGE.$d.po" + if wget -q -nc -O $PO_FILENAME $PO_URL; then + # we want all .po files in UTF-8 format really, so convert if needed.. + CHARSET=`grep Content-Type $PO_FILENAME | sed -e 's/.*charset=\(.*\)\\\\n.*/\1/'` + if test "x$CHARSET" != "xUTF-8" -a "x$CHARSET" != "xutf-8"; then + # note: things like the bugs address will be added back by make update-po + if msguniq $PO_FILENAME --no-location \ + --output-file=$PO_FILENAME.utf8 \ + --to-code=UTF-8; then + mv $PO_FILENAME.utf8 $PO_FILENAME + else + echo "**** $d: conversion from $CHARSET to UTF-8 failed ****" + fi + fi + if [ -f "po/$d.po" ]; then + # ./po/foo.po exists, so let's check if ours matches the latest from the + # translation project website + REVDATE_NEW=`grep PO-Revision-Date $PO_FILENAME`; + REVDATE_OLD=`grep PO-Revision-Date po/$d.po`; + CHARSET_OLD=`grep Content-Type po/$d.po | sed -e 's/.*charset=\(.*\)\\\\n.*/\1/'` + if test "x$REVDATE_NEW" = "x$REVDATE_OLD" -a "x$CHARSET_OLD" = "xUTF-8"; then + # note: source code line markers will be removed later by make upload-po + echo "$d.po: up-to-date" + rm -f $PO_FILENAME + else + mv $PO_FILENAME "po/$d.po" + if test "x$CHARSET_OLD" != "xUTF-8" -a "x$CHARSET_OLD" != "xutf-8"; then + echo "$d.po: update (and charset converted from $CHARSET_OLD to UTF-8)" + else + echo "$d.po: updated" + fi + DOMAINS_UPDATED="$DOMAINS_UPDATED $d" + fi + # make sure domain is listed in LINGUAS + if ! grep $d "po/LINGUAS" >/dev/null 2>/dev/null; then + DOMAINS_NOT_IN_LINGUAS="$DOMAINS_NOT_IN_LINGUAS $d" + fi + else + # ./po/foo.po doesn't exist, but foo.po exists on the translation project + # website, so it's probably a new translation + echo "$d.po: new language" + mv $PO_FILENAME "po/$d.po" + DOMAINS_UPDATED="$DOMAINS_UPDATED $d" + DOMAINS_TO_ADD="$DOMAINS_TO_ADD $d" + fi + else + rm -f $PO_FILENAME + echo "$d.po: failure (does probably not exist)" + fi +done + +if [ -n "$DOMAINS_UPDATED" ]; then + echo "====================================================================" + echo + echo "Language domains updated :$DOMAINS_UPDATED" + echo "Language domains to git add :$DOMAINS_TO_ADD" + echo + echo "Source: http://translationproject.org/latest/$PACKAGE/" + echo + if [ -n "$DOMAINS_TO_ADD" ]; then + CMD_STRING="git add" + for d in $DOMAINS_TO_ADD; do + CMD_STRING="$CMD_STRING po/$d.po" + done + echo "Please run" + echo + echo " $CMD_STRING" + echo + echo "now and add the following domains to the po/LINGUAS file:" + echo + echo " $DOMAINS_TO_ADD" + echo + echo + fi + echo "====================================================================" +fi + +if [ -n "$DOMAINS_NOT_IN_LINGUAS" ]; then + echo + echo "Existing domains missing from the po/LINGUAS file:" + echo + echo " $DOMAINS_NOT_IN_LINGUAS" + echo + echo +fi + + diff --git a/gst-plugins-base-subtitles0.10/common/extract-release-date-from-doap-file b/gst-plugins-base-subtitles0.10/common/extract-release-date-from-doap-file new file mode 100755 index 0000000..f2bc418 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/extract-release-date-from-doap-file @@ -0,0 +1,32 @@ +#!/bin/sh +# Shell script to extract the date given a release version and a .doap file + +if test "x$1" = "x" -o "x$2" = "x" -o ! -s "$2"; then + echo "Usage: $0 RELEASE-VERSION-NUMBER DOAP-FILE" >&2; + exit 1 +fi + +if ! grep '/dev/null ; then + echo "$2 does not look lika a .doap file" >&2; + exit 1 +fi + +if ! grep "$1" "$2" >/dev/null ; then + echo "$2 contains no reference to a version $1" >&2; + exit 1 +fi + +awk 'BEGIN {x=0} +{ +if ($0~"") {x=1; chunk=""} +if (x==1) { + if ($0~"") { chunk = chunk $0 } + if ($0~"") { chunk = chunk $0 } +} +if ($0~"") {x=0; print chunk} +}' < "$2" | \ +\ +grep ''"$1"'' | \ +\ +sed -e 's/^.*//' -e 's/<\/created>.*$//' + diff --git a/gst-plugins-base-subtitles0.10/common/gen-changelog.py b/gst-plugins-base-subtitles0.10/common/gen-changelog.py new file mode 100644 index 0000000..c79e7d3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gen-changelog.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python + +import sys +import subprocess +import re + +# Makes a GNU-Style ChangeLog from a git repository +# Handles git-svn repositories also + +# Arguments : same as for git log +release_refs={} + +def process_commit(lines, files): + # DATE NAME + # BLANK LINE + # Subject + # BLANK LINE + # ... + # FILES + fileincommit = False + lines = [x.strip() for x in lines if x.strip() and not x.startswith('git-svn-id')] + files = [x.strip() for x in files if x.strip()] + for l in lines: + if l.startswith('* ') and ':' in l: + fileincommit = True + break + + top_line = lines[0] + print top_line.strip() + print + if not fileincommit: + for f in files: + print '\t* %s:' % f + for l in lines[1:]: + print '\t ', l + print + +def output_commits(): + cmd = ['git', 'log', '--pretty=format:--START-COMMIT--%H%n%ai %an <%ae>%n%n%s%n%b%n--END-COMMIT--', + '--date=short', '--name-only'] + + start_tag = find_start_tag() + + if start_tag is None: + cmd.extend(sys.argv[1:]) + else: + cmd.extend(["%s..HEAD" % (start_tag)]) + + p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) + buf = [] + files = [] + filemode = False + for lin in p.stdout.readlines(): + if lin.startswith("--START-COMMIT--"): + if buf != []: + process_commit(buf, files) + hash = lin[16:].strip() + try: + rel = release_refs[hash] + print "=== release %d.%d.%d ===\n" % (int(rel[0]), int(rel[1]), int(rel[2])) + except: + pass + buf = [] + files = [] + filemode = False + elif lin.startswith("--END-COMMIT--"): + filemode = True + elif filemode == True: + files.append(lin) + else: + buf.append(lin) + if buf != []: + process_commit(buf, files) + +def get_rel_tags(): + # Populate the release_refs dict with the tags for previous releases + reltagre = re.compile("^([a-z0-9]{40}) refs\/tags\/RELEASE-([0-9]+)[-_.]([0-9]+)[-_.]([0-9]+)") + + cmd = ['git', 'show-ref', '--tags', '--dereference'] + p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) + for lin in p.stdout.readlines(): + match = reltagre.search (lin) + if match: + (sha, maj, min, nano) = match.groups() + release_refs[sha] = (maj, min, nano) + +def find_start_tag(): + starttagre = re.compile("^([a-z0-9]{40}) refs\/tags\/CHANGELOG_START") + cmd = ['git', 'show-ref', '--tags'] + p = subprocess.Popen(args=cmd, shell=False, stdout=subprocess.PIPE) + for lin in p.stdout.readlines(): + match = starttagre.search (lin) + if match: + return match.group(1) + return None + +if __name__ == "__main__": + get_rel_tags() + output_commits() diff --git a/gst-plugins-base-subtitles0.10/common/gettext.patch b/gst-plugins-base-subtitles0.10/common/gettext.patch new file mode 100644 index 0000000..682b905 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gettext.patch @@ -0,0 +1,12 @@ +--- po/Makefile.in.in.orig 2006-01-07 12:03:45.000000000 +0100 ++++ po/Makefile.in.in 2006-01-07 12:04:23.000000000 +0100 +@@ -11,6 +11,9 @@ + PACKAGE = @PACKAGE@ + VERSION = @VERSION@ + ++# thomas: add GETTEXT_PACKAGE substitution as used in Makevars ++GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ ++ + SHELL = /bin/sh + @SET_MAKE@ + diff --git a/gst-plugins-base-subtitles0.10/common/glib-gen.mak b/gst-plugins-base-subtitles0.10/common/glib-gen.mak new file mode 100644 index 0000000..ef93a5f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/glib-gen.mak @@ -0,0 +1,44 @@ +# these are the variables your Makefile.am should set +# the example is based on the colorbalance interface + +#glib_enum_headers=$(colorbalance_headers) +#glib_enum_define=GST_COLOR_BALANCE +#glib_enum_prefix=gst_color_balance + +enum_headers=$(foreach h,$(glib_enum_headers),\n\#include \"$(h)\") + +# these are all the rules generating the relevant files +%-marshal.h: %-marshal.list + $(AM_V_GEN)glib-genmarshal --header --prefix=$(glib_enum_prefix)_marshal $^ > $*-marshal.h.tmp && \ + mv $*-marshal.h.tmp $*-marshal.h + +%-marshal.c: %-marshal.list + $(AM_V_GEN)echo "#include \"$*-marshal.h\"" >> $*-marshal.c.tmp && \ + glib-genmarshal --body --prefix=$(glib_enum_prefix)_marshal $^ >> $*-marshal.c.tmp && \ + mv $*-marshal.c.tmp $*-marshal.c + +%-enumtypes.h: $(glib_enum_headers) + $(AM_V_GEN)glib-mkenums \ + --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \ + $^ > $@ + +%-enumtypes.c: $(glib_enum_headers) + @if test "x$(glib_enum_headers)" = "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi + $(AM_V_GEN)glib-mkenums \ + --fhead "#include \"$*-enumtypes.h\"\n$(enum_headers)" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static volatile gsize g_define_type_id__volatile = 0;\n if (g_once_init_enter (&g_define_type_id__volatile)) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n GType g_define_type_id = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n }\n return g_define_type_id__volatile;\n}\n" \ + $^ > $@ + +# a hack rule to make sure .Plo files exist because they get include'd +# from Makefile's +.deps/%-marshal.Plo: + @touch $@ + +.deps/%-enumtypes.Plo: + @touch $@ diff --git a/gst-plugins-base-subtitles0.10/common/gst-autogen.sh b/gst-plugins-base-subtitles0.10/common/gst-autogen.sh new file mode 100644 index 0000000..f05e021 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gst-autogen.sh @@ -0,0 +1,376 @@ +# a silly hack that generates autoregen.sh but it's handy +# Remove the old autoregen.sh first to create a new file, +# as the current one may be being read by the shell executing +# this script. +if [ -f "autoregen.sh" ]; then + rm autoregen.sh +fi +echo "#!/bin/sh" > autoregen.sh +echo "./autogen.sh $@ \$@" >> autoregen.sh +chmod +x autoregen.sh + +# helper functions for autogen.sh + +debug () +# print out a debug message if DEBUG is a defined variable +{ + if test ! -z "$DEBUG" + then + echo "DEBUG: $1" + fi +} + +version_get () +# based on the command's version output, set variables +# _MAJOR, _MINOR, _MICRO, _VERSION, using the given prefix as variable prefix +# +# arg 1: command binary name +# arg 2: (uppercased) variable name prefix +{ + COMMAND=$1 + VARPREFIX=`echo $2 | tr .,- _` + + # strip everything that's not a digit, then use cut to get the first field + pkg_version=`$COMMAND --version|head -n 1|sed 's/^.*)[^0-9]*//'|cut -d' ' -f1` + debug "pkg_version $pkg_version" + # remove any non-digit characters from the version numbers to permit numeric + # comparison + pkg_major=`echo $pkg_version | cut -d. -f1 | sed s/[a-zA-Z\-].*//g` + pkg_minor=`echo $pkg_version | cut -d. -f2 | sed s/[a-zA-Z\-].*//g` + pkg_micro=`echo $pkg_version | cut -d. -f3 | sed s/[a-zA-Z\-].*//g` + test -z "$pkg_major" && pkg_major=0 + test -z "$pkg_minor" && pkg_minor=0 + test -z "$pkg_micro" && pkg_micro=0 + debug "found major $pkg_major minor $pkg_minor micro $pkg_micro" + eval ${VARPREFIX}_MAJOR=$pkg_major + eval ${VARPREFIX}_MINOR=$pkg_minor + eval ${VARPREFIX}_MICRO=$pkg_micro + eval ${VARPREFIX}_VERSION=$pkg_version +} + +version_compare () +# Checks whether the version of VARPREFIX is equal to or +# newer than the requested version +# arg1: VARPREFIX +# arg2: MAJOR +# arg3: MINOR +# arg4: MICRO +{ + VARPREFIX=`echo $1 | tr .,- _` + MAJOR=$2 + MINOR=$3 + MICRO=$4 + + eval pkg_major=\$${VARPREFIX}_MAJOR; + eval pkg_minor=\$${VARPREFIX}_MINOR; + eval pkg_micro=\$${VARPREFIX}_MICRO; + + #start checking the version + debug "version_compare: $VARPREFIX against $MAJOR.$MINOR.$MICRO" + + # reset check + WRONG= + + if [ ! "$pkg_major" -gt "$MAJOR" ]; then + debug "major: $pkg_major <= $MAJOR" + if [ "$pkg_major" -lt "$MAJOR" ]; then + debug "major: $pkg_major < $MAJOR" + WRONG=1 + elif [ ! "$pkg_minor" -gt "$MINOR" ]; then + debug "minor: $pkg_minor <= $MINOR" + if [ "$pkg_minor" -lt "$MINOR" ]; then + debug "minor: $pkg_minor < $MINOR" + WRONG=1 + elif [ "$pkg_micro" -lt "$MICRO" ]; then + debug "micro: $pkg_micro < $MICRO" + WRONG=1 + fi + fi + fi + if test ! -z "$WRONG"; then + debug "version_compare: $VARPREFIX older than $MAJOR.$MINOR.$MICRO" + return 1 + fi + debug "version_compare: $VARPREFIX equal to/newer than $MAJOR.$MINOR.$MICRO" + return 0 +} + + +version_check () +# check the version of a package +# first argument : package name (executable) +# second argument : optional path where to look for it instead +# third argument : source download url +# rest of arguments : major, minor, micro version +# all consecutive ones : suggestions for binaries to use +# (if not specified in second argument) +{ + PACKAGE=$1 + PKG_PATH=$2 + URL=$3 + MAJOR=$4 + MINOR=$5 + MICRO=$6 + + # for backwards compatibility, we let PKG_PATH=PACKAGE when PKG_PATH null + if test -z "$PKG_PATH"; then PKG_PATH=$PACKAGE; fi + debug "major $MAJOR minor $MINOR micro $MICRO" + VERSION=$MAJOR + if test ! -z "$MINOR"; then VERSION=$VERSION.$MINOR; else MINOR=0; fi + if test ! -z "$MICRO"; then VERSION=$VERSION.$MICRO; else MICRO=0; fi + + debug "major $MAJOR minor $MINOR micro $MICRO" + + for SUGGESTION in $PKG_PATH; do + COMMAND="$SUGGESTION" + + # don't check if asked not to + test -z "$NOCHECK" && { + printf " checking for $COMMAND >= $VERSION ... " + } || { + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + } + + which $COMMAND > /dev/null 2>&1 + if test $? -eq 1; + then + debug "$COMMAND not found" + continue + fi + + VARPREFIX=`echo $COMMAND | sed 's/-//g' | tr [:lower:] [:upper:]` + version_get $COMMAND $VARPREFIX + + version_compare $VARPREFIX $MAJOR $MINOR $MICRO + if test $? -ne 0; then + echo "found $pkg_version, not ok !" + continue + else + echo "found $pkg_version, ok." + # we set a var with the same name as the package, but stripped of + # unwanted chars + VAR=`echo $PACKAGE | sed 's/-//g'` + debug "setting $VAR" + eval $VAR="$COMMAND" + return 0 + fi + done + + echo "$PACKAGE not found !" + echo "You must have $PACKAGE installed to compile $package." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at $URL" + return 1; +} + +aclocal_check () +{ + # normally aclocal is part of automake + # so we expect it to be in the same place as automake + # so if a different automake is supplied, we need to adapt as well + # so how's about replacing automake with aclocal in the set var, + # and saving that in $aclocal ? + # note, this will fail if the actual automake isn't called automake* + # or if part of the path before it contains it + if [ -z "$automake" ]; then + echo "Error: no automake variable set !" + return 1 + else + aclocal=`echo $automake | sed s/automake/aclocal/` + debug "aclocal: $aclocal" + if [ "$aclocal" != "aclocal" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-aclocal=$aclocal" + fi + if [ ! -x `which $aclocal` ]; then + echo "Error: cannot execute $aclocal !" + return 1 + fi + fi +} + +autoheader_check () +{ + # same here - autoheader is part of autoconf + # use the same voodoo + if [ -z "$autoconf" ]; then + echo "Error: no autoconf variable set !" + return 1 + else + autoheader=`echo $autoconf | sed s/autoconf/autoheader/` + debug "autoheader: $autoheader" + if [ "$autoheader" != "autoheader" ]; + then + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoheader=$autoheader" + fi + if [ ! -x `which $autoheader` ]; then + echo "Error: cannot execute $autoheader !" + return 1 + fi + fi + +} + +autoconf_2_52d_check () +{ + # autoconf 2.52d has a weird issue involving a yes:no error + # so don't allow it's use + test -z "$NOCHECK" && { + ac_version=`$autoconf --version|head -n 1|sed 's/^[a-zA-Z\.\ ()]*//;s/ .*$//'` + if test "$ac_version" = "2.52d"; then + echo "autoconf 2.52d has an issue with our current build." + echo "We don't know who's to blame however. So until we do, get a" + echo "regular version. RPM's of a working version are on the gstreamer site." + exit 1 + fi + } + return 0 +} +libtool_2_2_gettext_check () +{ + # libtool 2.2 needs autopoint 0.17 or higher + version_compare LIBTOOLIZE 2 2 0 + if test $? -eq 0 + then + version_compare AUTOPOINT 0 17 0 + if test $? -ne 0 + then + echo "libtool 2.2 requires autopoint 0.17 or higher" + return 1 + fi + fi + return 0 +} + + +die_check () +{ + # call with $DIE + # if set to 1, we need to print something helpful then die + DIE=$1 + if test "x$DIE" = "x1"; + then + echo + echo "- Please get the right tools before proceeding." + echo "- Alternatively, if you're sure we're wrong, run with --nocheck." + exit 1 + fi +} + +autogen_options () +{ + if test "x$1" = "x"; then + return 0 + fi + + while test "x$1" != "x" ; do + optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + case "$1" in + --noconfigure) + NOCONFIGURE=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --noconfigure" + echo "+ configure run disabled" + shift + ;; + --nocheck) + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --nocheck" + NOCHECK=defined + echo "+ autotools version check disabled" + shift + ;; + -d|--debug) + DEBUG=defined + AUTOGEN_EXT_OPT="$AUTOGEN_EXT_OPT --debug" + echo "+ debug output enabled" + shift + ;; + -h|--help) + echo "autogen.sh (autogen options) -- (configure options)" + echo "autogen.sh help options: " + echo " --noconfigure don't run the configure script" + echo " --nocheck don't do version checks" + echo " --debug debug the autogen process" + echo + echo " --with-autoconf PATH use autoconf in PATH" + echo " --with-automake PATH use automake in PATH" + echo + echo "Any argument either not in the above list or after a '--' will be " + echo "passed to ./configure." + exit 1 + ;; + --with-automake=*) + AUTOMAKE=$optarg + echo "+ using alternate automake in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-automake=$AUTOMAKE" + shift + ;; + --with-autoconf=*) + AUTOCONF=$optarg + echo "+ using alternate autoconf in $optarg" + CONFIGURE_DEF_OPT="$CONFIGURE_DEF_OPT --with-autoconf=$AUTOCONF" + shift + ;; + --) shift ; break ;; + *) + echo "+ passing argument $1 to configure" + CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $1" + shift + ;; + esac + done + + for arg do CONFIGURE_EXT_OPT="$CONFIGURE_EXT_OPT $arg"; done + if test ! -z "$CONFIGURE_EXT_OPT" + then + echo "+ options passed to configure: $CONFIGURE_EXT_OPT" + fi +} + +toplevel_check () +{ + srcfile=$1 + test -f $srcfile || { + echo "You must run this script in the top-level $package directory" + exit 1 + } +} + +tool_run () +{ + tool=$1 + options=$2 + run_if_fail=$3 + echo "+ running $tool $options..." + $tool $options || { + echo + echo $tool failed + eval $run_if_fail + exit 1 + } +} + +install_git_hooks () +{ + if test -d .git; then + # install pre-commit hook for doing clean commits + for hook in pre-commit; do + if test ! \( -x .git/hooks/$hook -a -L .git/hooks/$hook \); then + echo "+ Installing git $hook hook" + rm -f .git/hooks/$hook + ln -s ../../common/hooks/$hook.hook .git/hooks/$hook || { + # if we couldn't create a symbolic link, try doing a plain cp + if cp common/hooks/pre-commit.hook .git/hooks/pre-commit; then + chmod +x .git/hooks/pre-commit; + else + echo "********** Couldn't install git $hook hook **********"; + fi + } + fi + done + fi +} diff --git a/gst-plugins-base-subtitles0.10/common/gst-glib-gen.mak b/gst-plugins-base-subtitles0.10/common/gst-glib-gen.mak new file mode 100644 index 0000000..cc82bbd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gst-glib-gen.mak @@ -0,0 +1,45 @@ +# these are the variables your Makefile.am should set +# the example is based on the colorbalance interface + +#glib_enum_headers=$(colorbalance_headers) +#glib_enum_define=GST_COLOR_BALANCE +#glib_gen_prefix=gst_color_balance +#glib_gen_basename=colorbalance + +enum_headers=$(foreach h,$(glib_enum_headers),\n\#include \"$(h)\") + +# these are all the rules generating the relevant files +$(glib_gen_basename)-marshal.h: $(glib_gen_basename)-marshal.list + $(AM_V_GEN)glib-genmarshal --header --prefix=$(glib_gen_prefix)_marshal $^ > $(glib_gen_basename)-marshal.h.tmp && \ + mv $(glib_gen_basename)-marshal.h.tmp $(glib_gen_basename)-marshal.h + +$(glib_gen_basename)-marshal.c: $(glib_gen_basename)-marshal.list + $(AM_V_GEN)echo "#include \"$(glib_gen_basename)-marshal.h\"" >> $(glib_gen_basename)-marshal.c.tmp && \ + glib-genmarshal --body --prefix=$(glib_gen_prefix)_marshal $^ >> $(glib_gen_basename)-marshal.c.tmp && \ + mv $(glib_gen_basename)-marshal.c.tmp $(glib_gen_basename)-marshal.c + +$(glib_gen_basename)-enumtypes.h: $(glib_enum_headers) + $(AM_V_GEN)glib-mkenums \ + --fhead "#ifndef __$(glib_enum_define)_ENUM_TYPES_H__\n#define __$(glib_enum_define)_ENUM_TYPES_H__\n\n#include \n\nG_BEGIN_DECLS\n" \ + --fprod "\n/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define GST_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __$(glib_enum_define)_ENUM_TYPES_H__ */" \ + $^ > $@ + +$(glib_gen_basename)-enumtypes.c: $(glib_enum_headers) + @if test "x$(glib_enum_headers)" = "x"; then echo "ERROR: glib_enum_headers is empty, please fix Makefile"; exit 1; fi + $(AM_V_GEN)glib-mkenums \ + --fhead "#include \"$(glib_gen_basename)-enumtypes.h\"\n$(enum_headers)" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static volatile gsize g_define_type_id__volatile = 0;\n if (g_once_init_enter (&g_define_type_id__volatile)) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n GType g_define_type_id = g_@type@_register_static (\"@EnumName@\", values);\n g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);\n }\n return g_define_type_id__volatile;\n}\n" \ + $^ > $@ + +# a hack rule to make sure .Plo files exist because they get include'd +# from Makefile's +.deps/%-marshal.Plo: + @touch $@ + +.deps/%-enumtypes.Plo: + @touch $@ diff --git a/gst-plugins-base-subtitles0.10/common/gst-indent b/gst-plugins-base-subtitles0.10/common/gst-indent new file mode 100755 index 0000000..732b2ba --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gst-indent @@ -0,0 +1,49 @@ +#!/bin/sh +# +# Check that the code follows a consistant code style +# + +# Check for existence of indent, and error out if not present. +# On some *bsd systems the binary seems to be called gnunindent, +# so check for that first. + +version=`gnuindent --version 2>/dev/null` +if test "x$version" = "x"; then + version=`indent --version 2>/dev/null` + if test "x$version" = "x"; then + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + exit 1 + fi + INDENT=indent +else + INDENT=gnuindent +fi + +case `$INDENT --version` in + GNU*) + ;; + default) + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + echo "(Found $INDENT, but it doesn't seem to be GNU indent)" + exit 1 + ;; +esac + +INDENT_PARAMETERS="--braces-on-if-line \ + --case-brace-indentation0 \ + --case-indentation2 \ + --braces-after-struct-decl-line \ + --line-length80 \ + --no-tabs \ + --cuddle-else \ + --dont-line-up-parentheses \ + --continuation-indentation4 \ + --honour-newlines \ + --tab-size8 \ + --indent-level2 \ + --leave-preprocessor-space" + +$INDENT ${INDENT_PARAMETERS} $@ + diff --git a/gst-plugins-base-subtitles0.10/common/gst.supp b/gst-plugins-base-subtitles0.10/common/gst.supp new file mode 100644 index 0000000..7e24bc8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gst.supp @@ -0,0 +1,3929 @@ +### this file contains suppressions for valgrind when running +### the gstreamer unit tests +### it might be useful for wider use as well + +### syscall suppressions + +{ + + Memcheck:Param + clone(parent_tidptr) + fun:clone + fun:clone +} + +{ + + Memcheck:Param + clone(child_tidptr) + fun:clone + fun:clone +} + +{ + + Memcheck:Param + clone(tlsinfo) + fun:clone + fun:clone +} + +### glibc suppressions + +{ + + Memcheck:Cond + obj:/lib/ld-2.*.so + fun:dl_open_worker + obj:/lib/ld-2.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.*.so + fun:_dlerror_run + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file +} + +{ + + Memcheck:Cond + fun:strlen + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:/lib64/ld-2.*.so + obj:* + obj:* +} + +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} + +{ + + Memcheck:Cond + fun:* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +# glibc does not deallocate thread-local storage + +{ + + Memcheck:Leak + fun:calloc + fun:_dl_allocate_tls + fun:pthread_create@@* +} + +# I get an extra stack entry on x86/dapper +{ + + Memcheck:Leak + fun:calloc + obj:/lib/ld-2.3.*.so + fun:_dl_allocate_tls + fun:pthread_create@@* +} + + +{ + + Memcheck:Cond + fun:strstr + fun:__pthread_initialize_minimal + obj:/lib/libpthread-*.so + obj:/lib/libpthread-*.so + fun:call_init + fun:_dl_init + obj:/lib/ld-*.so +} + +# a thread-related free problem in glibc from Edgard +{ + __libc_freeres_rw_acess + Memcheck:Addr4 + obj:* + obj:* + obj:* + obj:* + obj:* + fun:__libc_freeres +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so +} + +# g_module_open-related problems +{ + + Memcheck:Addr2 + fun:memcpy + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:init_post + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Addr4 + fun:memcpy + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:gst_registry_scan_path_level + fun:init_post + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:do_sym + fun:_dl_sym + fun:dlsym_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlsym + fun:g_module_symbol + fun:g_module_open + fun:gst_plugin_load_file +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file +} +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name + fun:gst_plugin_feature_load +} + +{ + + Memcheck:Leak + fun:malloc + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:dl_open_worker + obj:/lib/ld-2.3.*.so + fun:_dl_open + fun:dlopen_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:do_sym + fun:_dl_sym + fun:dlsym_doit + obj:/lib/ld-2.3.*.so + fun:_dlerror_run + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Param + futex(uaddr2) + fun:pthread_once + obj:/lib/libc-2.3.*.so + obj:/lib/libc-2.3.*.so + fun:mbsnrtowcs + fun:vfprintf + fun:vsprintf + fun:sprintf + obj:/lib/libc-2.3.*.so + fun:tmpfile + fun:setup_pipe + fun:setup_messaging_with_key + fun:setup_messaging +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:_dl_sym + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + obj:/lib/i686/cmov/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libc-2.7.so + fun:iconv_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/i686/cmov/libdl-2.7.so + fun:dlopen +} + +# suppression for a glibc bug: +# http://valgrind.org/docs/manual/faq.html#faq.exit_errors> +{ + + Memcheck:Free + fun:free + obj:*libc-*.so + fun:__libc_freeres + fun:* + fun:_Exit +} + +# same as above, just so it works for tpm on gutsy/x86-64 +{ + + Memcheck:Free + fun:free + fun:free_mem + fun:__libc_freeres +} + +# valgrind doesn't allow me to specify a suppression for Addr1, Addr2, Addr4 +# as Addr*, so 3 copies for that; and then 2 of each for that pesky memcpy +{ + + Memcheck:Addr1 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr2 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} +{ + + Memcheck:Addr4 + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr1 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr2 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} +{ + + Memcheck:Addr4 + fun:memcpy + fun:_dl_signal_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/libc-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:_dl_open + obj:/lib/libdl-2.3.*.so + obj:/lib/ld-2.3.*.so +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.*.so + obj:/lib/libc-2.3.*.so + obj:/lib/ld-2.3.*.so + fun:_dl_open + obj:/lib/libdl-2.3.*.so + obj:/lib/ld-2.3.*.so + obj:/lib/libdl-2.3.*.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file + fun:gst_plugin_load_by_name + fun:gst_plugin_feature_load +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libc-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/tls/i686/cmov/libdl-2.3.6.so + fun:dlopen +} + +### glib suppressions +{ + + Memcheck:Cond + fun:g_parse_debug_string + obj:/usr/lib*/libglib-2.0.so.* + fun:g_slice_alloc + fun:g_slice_alloc0 +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_init* + fun:init_pre +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_fundamental +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:type_node_any_new_W +} + +{ + + Memcheck:Leak + fun:realloc + fun:g_realloc + fun:type_node_any_new_W +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:g_type_class_ref +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:type_add_flags_W +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:type_add_flags_W +} + +#pthread memleaks + +{ + Thread creation leak + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_initialize_minimal +} + +{ + Thread management leak + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_* +} + +{ + Thread management leak 2 + Memcheck:Leak + fun:memalign + fun:_dl_allocate* + fun:_dl_allocate* + fun:__pthread_* +} + +{ + pthread_create Syscall param write(buf) points to uninitialised byte(s) + Memcheck:Param + write(buf) + fun:pthread_create@@GLIBC_2.2.5 + fun:g_thread_create* + +} + +# nss_parse_* memleak (used by g_option_context_parse) +{ + nss_parse_* memleak + Memcheck:Leak + fun:malloc + fun:nss_parse_service_list + fun:__nss_database_lookup +} + +# liboil suppressions +{ + + Memcheck:Value8 + obj:/usr/lib/liboil-0.3.so.0.1.0 + obj:/usr/lib/liboil-0.3.so.0.1.0 + obj:/usr/lib/liboil-0.3.so.0.1.0 + fun:oil_cpu_fault_check_try + fun:oil_test_check_impl + fun:oil_class_optimize + fun:oil_optimize_all + fun:oil_init +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.3.6.so +} + +{ + + Memcheck:Param + futex(uaddr2) + fun:pthread_once + obj:/lib/libc-2.3.6.so + obj:/lib/libc-2.3.6.so + fun:setlocale + fun:init_pre + fun:g_option_context_parse + fun:gst_init_check + fun:gst_init + fun:gst_check_init + fun:main +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.3.6.so + obj:/lib/ld-2.3.6.so + fun:_dl_open + obj:/lib/libdl-2.3.6.so + obj:/lib/ld-2.3.6.so + obj:/lib/libdl-2.3.6.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_file +} +# this exists in a bunch of different variations, hence the short tail/trace +{ + + Memcheck:Addr4 + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} +{ + + Memcheck:Addr8 + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} + +# More edgy suppressions (Mike) +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:dlopen_doit + obj:/lib/ld-2.4.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:dlopen_doit + obj:/lib/ld-2.4.so + fun:_dlerror_run + fun:dlopen@@GLIBC_2.1 +} + +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + fun:do_sym + fun:_dl_sym +} + +# This one's overly general, but there's zero other information in the stack +# trace - just these five lines! +{ + + Memcheck:Cond + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so + obj:/lib/ld-2.4.so +} + +{ + + Memcheck:Leak + fun:calloc + obj:/lib/ld-2.4.so + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_2.1 +} + +# TLS leaks for feisty/x86 +{ + + Memcheck:Leak + fun:calloc + fun:allocate_dtv + fun:_dl_allocate_tls + fun:pthread_create@@GLIBC_2.1 +} + +{ + + Memcheck:Leak + fun:calloc + obj:/usr/lib/libcdio.so.6.0.1 + fun:cdio_open_am_linux + obj:/usr/lib/libcdio.so.6.0.1 + fun:cdio_open_am +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.5.so +} + +{ + + Memcheck:Cond + fun:snd_pcm_direct_shm_create_or_connect + fun:snd_pcm_dsnoop_open + fun:_snd_pcm_dsnoop_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} + +{ + + Memcheck:Cond + fun:snd*_pcm_hw_param_set_near +} + +{ + + Memcheck:Cond + ... + fun:snd*_pcm_hw_param_set_near +} + +{ + + Memcheck:Cond + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_close + obj:/*lib/libasound.so.2.0.0 +} +{ + + Memcheck:Cond + fun:snd_pcm_direct_shm_create_or_connect + fun:snd_pcm_dmix_open + fun:_snd_pcm_dmix_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_softvol_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} +{ + + Memcheck:Leak + fun:malloc + fun:strdup + fun:snd_dlobj_cache_add + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:snd_pcm_dsnoop_open + fun:_snd_pcm_dsnoop_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_plug_open + obj:/*lib/libasound.so.2.0.0 + fun:snd_pcm_open_slave + fun:_snd_pcm_asym_open + obj:/*lib/libasound.so.2.0.0 + obj:/*lib/libasound.so.2.0.0 +} +# Catch about 15 variations on inserting info into an ALSA +# internal cache +{ + + Memcheck:Leak + fun:malloc + ... + fun:snd*_dlobj_cache_add + obj:/*lib*/libasound.so.2.0.0 +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:snd_pcm_open_conf +} + +{ + + Memcheck:Leak + fun:*alloc + obj:/*lib*/libasound.so.2.0.0 + ... + fun:snd_config_hook_load +} + +{ + + Memcheck:Leak + fun:*alloc + obj:/*lib*/libasound.so.2.0.0 + ... + fun:snd_config_update_r + fun:snd_config_update +} +{ + + Memcheck:Leak + fun:*alloc + fun:strdup + ... + fun:snd_config_update_r + fun:snd_config_update +} +{ + + Memcheck:Leak + fun:malloc + obj:/lib/libc*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getgrnam_r + fun:getgrnam + fun:snd_pcm_direct_parse_open_conf +} + +{ + + Memcheck:Leak + fun:calloc + fun:_XCBInitDisplayLock + fun:XOpenDisplay +} + +# GConf internal initialisations related to getting the default client. +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:* + fun:PortableServer_POA_servant_to_reference + fun:* + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:ORBit_demarshal_value + fun:* + fun:ORBit_small_invoke_stub + fun:ConfigServer_get_default_database + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:IOP_generate_profiles + fun:ORBit_marshal_object + fun:ORBit_marshal_value + fun:* + fun:ORBit_small_invoke_stub + fun:ConfigServer_add_client + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_by_tc + fun:* + fun:PortableServer_POA_servant_to_reference + fun:* + fun:* + fun:* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_by_tc + obj:/usr/lib/libORBit-2.so.* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so.* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so.* + obj:/usr/lib/libgconf-2.so.* + fun:gconf_engine_get_default +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:* + fun:* + fun:gconf_activate_server +} + +# Some libORBit/bonobo initialisation stuff +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:ORBit_alloc_string + fun:CORBA_string_dup + fun:Bonobo_ActivationEnvValue_set + fun:bonobo_activation_init_activation_env + fun:bonobo_activation_orb_init + fun:bonobo_activation_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:PortableServer_POA_servant_to_reference + obj:/usr/lib/libbonobo-2.so* +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + fun:ORBit_small_allocbuf + fun:ORBit_adaptor_setup + obj:/usr/lib/libORBit-2.so* + fun:ORBit_POA_setup_root + fun:ORBit_init_internals + fun:CORBA_ORB_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc_tcval + fun:ORBit_adaptor_setup + fun:* + fun:ORBit_POA_setup_root + fun:ORBit_init_internals + fun:CORBA_ORB_init +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_allocbuf + fun:bonobo_activation_init_activation_env + fun:bonobo_activation_orb_init + fun:bonobo_activation_init +} + +# More GConf stuff from the FC5 buildbot, mostly variations on the +# above stack traces +{ + + Memcheck:Param + writev(vector[...]) + fun:writev + obj:/usr/lib/libORBit-2.so* + fun:link_connection_writev + fun:giop_send_buffer_write + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_ping + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:PortableServer_POA_servant_to_reference + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:CORBA_ORB_string_to_object + obj:/usr/lib/libgconf-2.so* + fun:gconf_get_current_lock_holder + fun:gconf_activate_server + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_demarshal_IOR + fun:ORBit_demarshal_object + fun:ORBit_demarshal_value + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_get_default_database + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:ORBit_alloc* + fun:ORBit_small_alloc* + obj:/usr/lib/libORBit-2.so* + fun:ORBit_OAObject_object_to_objkey + fun:IOP_generate_profiles + fun:ORBit_marshal_object + fun:ORBit_marshal_value + obj:/usr/lib/libORBit-2.so* + fun:ORBit_small_invoke_stub + fun:ORBit_small_invoke_stub_n + fun:ORBit_c_stub_invoke + fun:ConfigServer_add_client + obj:/usr/lib/libgconf-2.so* + obj:/usr/lib/libgconf-2.so* + fun:gconf_engine_get_default +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_home_dir +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_user_name +} +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.* + fun:g_get_tmp_dir +} + +{ + + Memcheck:Leak + fun:malloc + obj:*libc-*.so + fun:__nss_database_lookup + obj:* + obj:* + fun:getpwnam_r + obj:/usr/lib*/libglib-2.0.so.0.* + fun:g_get_host_name +} + + +## Some Fontconfig errors. +{ + + Memcheck:Leak + fun:malloc + fun:FcPatternObjectInsertElt + fun:FcPatternObjectAddWithBinding + fun:FcPatternAppend + fun:FcEndElement + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + fun:XML_ParseBuffer + fun:FcConfigParseAndLoad + fun:FcConfigParseAndLoad + fun:FcParseInclude + fun:FcEndElement + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + obj:/usr/lib/libexpat.so.* + fun:XML_ParseBuffer + fun:FcConfigParseAndLoad +} +{ + + Memcheck:Leak + fun:*alloc + ... + fun:FcInitLoadConfig +} + +# Issues with ubuntu Hardy, same crack as for previous ubuntus +{ + + Memcheck:Leak + fun:calloc + obj:* + fun:_dl_allocate_tls + fun:pthread_create@@* + obj:/usr/lib/libgthread* + fun:g_thread_* +} + +# I've made this version generic, so that it covers future modifications +# of library names +{ + + Memcheck:Leak + fun:calloc + obj:* + fun:_dl_allocate_tls + fun:pthread_create@@* + fun:g_thread_* +} + +# series of invalid read of size 4 in g_module_open for ubuntu +# hardy x86/32bit +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load_* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlopen + fun:g_module_open + fun:gst_plugin_load* +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:_dl_sym + obj:/lib/tls/i686/cmov/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open + fun:gst_plugin_load_* +} + +# series of invalid read of size 8 in g_module_open for ubuntu +# hardy x86/64bit +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlopen + fun:g_module_open +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/libdl-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libdl-2.7.so + fun:dlsym + fun:g_module_symbol + fun:g_module_open +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:__nss_passwd_lookup + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libc-2.7.so + fun:__nss_passwd_lookup + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libnss_compat-2.7.so + fun:_nss_compat_getpwnam_r + fun:getpwnam_r +} + +{ + + Memcheck:Addr4 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/tls/i686/cmov/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/tls/i686/cmov/libnss_compat-2.7.so + fun:_nss_compat_getpwnam_r + fun:getpwnam_r +} + +{ + + Memcheck:Addr8 + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/ld-2.7.so + obj:/lib/libc-2.7.so + obj:/lib/ld-2.7.so + fun:__libc_dlopen_mode + fun:__nss_lookup_function + obj:/lib/libc-2.7.so + fun:getpwnam_r +} + +## Leaks in ALSA (variations of leak from snd_config_load1) + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} +{ + + Memcheck:Leak + fun:calloc + fun:_snd_config_make + fun:_snd_config_make_add + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:malloc + fun:snd1_dlobj_cache_add + fun:snd_ctl_open_noupdate +} + +{ + + Memcheck:Leak + fun:malloc + fun:* + fun:snd1_dlobj_cache_add + fun:snd_ctl_open_noupdate +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:snd_config_load1 +} + + +# The following are leaks of caps that need to be created dynamically +# in the type registration of the plugin (used for pad templates). + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_new_simple + fun:* + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:* + fun:* + fun:g_type_class_ref + fun:gst_element_register + fun:gst_ogm_parse_plugin_init + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_video_test_src_base_init + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_video_test_src_getcaps + fun:gst_video_test_src_base_init + fun:g_type_class_ref + fun:gst_element_register +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_ffmpegcsp_codectype_to_caps + fun:gst_ffmpegcolorspace_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_ffmpegcolorspace_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_new_any + fun:gst_ffmpegdemux_register + fun:plugin_init +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_append + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_append + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_ptr_array_maybe_expand + fun:g_ptr_array_add + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_ptr_array_sized_new + fun:gst_caps_new_empty + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_array_maybe_expand + fun:g_array_sized_new + fun:* + fun:* + fun:* + fun:gst_value_init_and_copy + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:g_array_maybe_expand + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_audio_filter_class_add_pad_templates +} + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_riff_create_*_template_caps +} +{ + + Memcheck:Leak + fun:malloc + fun:realloc + fun:g_realloc + fun:* + fun:* + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_caps_append + fun:gst_riff_create_*_template_caps +} +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_array_sized_new + fun:* + fun:gst_structure_copy + fun:gst_caps_copy + fun:gst_caps_append + fun:gst_riff_create_*_template_caps +} + +## Leaks in pango (bilboed: gentoo unstable amd64) + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:pango_layout_get_pixel_extents +} +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:pango_language_from_string + fun:pango_language_get_default + fun:pango_context_init + fun:g_type_create_instance + fun:g_object_constructor + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + fun:pango_font_map_create_context +} + +{ + + Memcheck:Leak + fun:calloc + fun:g_malloc0 + fun:pango_language_from_string +} + + +## Leak of property_list in gstffmpegcfg.c +## This list is created in gst_ffmpegcsp_init(), called from +## gst_ffmpegenc_register. +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_datalist_id_set_data_full + fun:gst_ffmpeg_cfg_init + fun:gst_ffmpegenc_register + fun:plugin_init +} +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:g_datalist_id_set_data_full + fun:g_param_spec_set_qdata_full + fun:gst_ffmpeg_cfg_init + fun:gst_ffmpegenc_register + fun:plugin_init +} + + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:gst_ffmpeg_cfg_init + fun:gst_ffmpegenc_register +} + +## Leak of GIO module through gnomevfs + +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:* + fun:* + fun:g_type_create_instance + fun:* + fun:* + fun:* + fun:* + fun:g_io_module_new + fun:g_io_modules_load_all_in_directory + fun:* + fun:get_default_vfs +} + +## Conditional jump in getaddrinfo (bilboed, gentoo ~amd64, Dec 13 2008) +{ + + Memcheck:Cond + fun:gaih_inet + fun:getaddrinfo +} + +## Dynamic pad templates in mxfmux +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_slice_alloc + fun:gst_caps_new_empty + fun:gst_caps_from_string + fun:mxf_*_init + fun:plugin_init +} + +## We don't know if ffmpeg frees this or not and better pass a copy for safety +{ + + Memcheck:Leak + fun:malloc + fun:g_malloc + fun:g_strdup + fun:gst_ffmpeg_cfg_fill_context + fun:gst_ffmpegenc_setcaps + fun:gst_pad_set_caps +} + +## Leak/overreads with glibc-2.10 + +{ + + Memcheck:Value8 + fun:do_sym + fun:dlsym_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlsym +} +{ + + Memcheck:Cond + fun:do_sym + fun:dlsym_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlsym +} + +{ + + Memcheck:Value8 + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_relocate_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_check_map_versions + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_map_object* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_map_object* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + fun:_dl_check_caller + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Cond + fun:_dl_check_caller + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen* +} + +{ + + Memcheck:Value8 + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} +{ + + Memcheck:Cond + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} +{ + + Memcheck:Free + fun:free + obj:/lib*/libc-2.10.*.so + obj:/lib*/libc-2.10.*.so + fun:_vgnU_freeres +} + +{ + + Memcheck:Value8 + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +{ + + Memcheck:Cond + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} +{ + + Memcheck:Value8 + fun:_dl_sort_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +{ + + Memcheck:Cond + fun:_dl_sort_fini + fun:_dl_fini + fun:__run_exit_handlers + fun:exit +} + +# glibc-2.10 dl overreads +{ + + Memcheck:Value8 + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Cond + fun:_dl_fixup + fun:_dl_runtime_resolve +} + +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Cond + fun:_dl_lookup_symbol_x + fun:_dl_fixup + fun:_dl_runtime_resolve +} +{ + + Memcheck:Value8 + fun:call_init + fun:_dl_init +} +{ + + Memcheck:Value8 + fun:_dl_init +} +{ + + Memcheck:Value8 + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Cond + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_relocate_object + fun:dl_main +} +{ + + Memcheck:Value8 + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} +{ + + Memcheck:Cond + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start +} + +{ + + Memcheck:Cond + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:_dl_check_map_versions + fun:_dl_check_all_versions + fun:version_check_doit + fun:_dl_receive_error + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Cond + fun:init_tls + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_map_object_deps + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_protect_relro + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_setup_hash + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Cond + fun:* + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:* + fun:* + fun:_dl_map_object +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_check_map_versions + fun:_dl_check_all_versions +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Cond + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} +{ + + Memcheck:Cond + fun:* + fun:do_lookup_x + fun:_dl_lookup_symbol_x +} + +{ + + Memcheck:Value8 + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} +{ + + Memcheck:Cond + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} + +{ + + Memcheck:Value8 + fun:* + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} +{ + + Memcheck:Cond + fun:* + fun:_dl_name_match_p + fun:_dl_map_object + fun:dl_open_worker +} + +{ + + Memcheck:Value8 + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object +} +{ + + Memcheck:Cond + fun:_dl_lookup_symbol_x + fun:_dl_relocate_object +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Cond + fun:* + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Cond + fun:* + fun:_dl_check_map_versions +} +{ + + Memcheck:Value8 + fun:openaux +} +{ + + Memcheck:Value8 + fun:_dl_name_match_p + fun:_dl_map_object +} + +{ + + Memcheck:Cond + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Value8 + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Cond + fun:* + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_close_worker + fun:_dl_close + fun:_dl_catch_error + fun:dlerror_run +} + +{ + + Memcheck:Cond + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Value8 + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:fillin_rpath + fun:_dl_init_paths + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} +{ + + Memcheck:Param + open(filename) + fun:open + fun:open_verify + fun:_dl_map_object + fun:map_doit + fun:_dl_catch_error + fun:do_preload + fun:dl_main +} + +{ + + Memcheck:Param + stat(file_name) + fun:_xstat + fun:open_path + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker +} + +{ + + Memcheck:Cond + fun:* + fun:_dl_map_object_deps + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_map_object_deps + fun:dl_main +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:_dl_map_object_deps + fun:dl_main +} + +# glibc-2.10 tls issues +{ + + Memcheck:Cond + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:* + fun:init_tls + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:* + fun:init_tls + fun:dl_main +} + +{ + + Memcheck:Cond + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Value8 + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Cond + fun:* + fun:_dl_allocate_tls_init + fun:dl_main +} +{ + + Memcheck:Value8 + fun:* + fun:_dl_allocate_tls_init + fun:dl_main +} + +{ + + Memcheck:Cond + fun:__tls* + obj:* + obj:* + fun:_vgnU_freeres +} + +{ + + Memcheck:Param + arch_prctl(arg2) + fun:init_tls +} +# GLib caching tmp/home directories (glibc-2.10 variants) +{ + + Memcheck:Cond + fun:* + fun:dl_open_worker + fun:* + fun:* + fun:* + fun:_dl_catch_error + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Value8 + fun:* + fun:dl_open_worker + fun:* + fun:* + fun:* + fun:_dl_catch_error + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Cond + fun:dl_open_worker + fun:* + fun:* + fun:do_dlopen + fun:* + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} +{ + + Memcheck:Value8 + fun:dl_open_worker + fun:* + fun:* + fun:do_dlopen + fun:* + fun:dlerror_run + fun:* + fun:__nss_lookup_function + fun:__nss_lookup + fun:getpwnam* +} + +{ + + Memcheck:Value8 + fun:_dl_add_to_slotinfo + fun:dl_main +} +{ + + Memcheck:Param + open(filename) + fun:open + fun:open_verify + fun:open_path + fun:_dl_map_object +} + + + +# GModule issues with glibc-2.10 +{ + + Memcheck:Value8 + fun:* + fun:* + fun:dlsym + fun:g_module_symbol +} +{ + + Memcheck:Value8 + fun:g_module_* + fun:gst_plugin* +} +{ + + Memcheck:Value8 + fun:* + fun:g_module_* + fun:gst_plugin* +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:dlopen* + fun:g_module_open +} +{ + + Memcheck:Value8 + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:* + fun:dlsym + fun:g_module_symbol +} + +{ + + Memcheck:Value8 + fun:* + fun:* + fun:* + fun:* + fun:* + fun:dlopen* + fun:g_module_open +} + +# Leak in GSlice +{ + + Memcheck:Value8 + fun:g_parse_debug_string + fun:slice_config_init + fun:g_slice_init_nomessage + fun:_g_slice_thread_init_nomessage + fun:g_thread_init_glib +} + +# 2.10 pthread issues +{ + + Memcheck:Value8 + fun:__pthread_initialize_minimal +} + +# glibc 2.11 conditional +{ + + Memcheck:Cond + fun:_dl_relocate_object + fun:dl_main + fun:_dl_sysdep_start + fun:_dl_start + obj:/lib64/ld-2.11.so +} + +# glibc 2.11 Leak + +{ + + Memcheck:Leak + fun:*alloc + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_* + fun:_dl_* + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_* + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_map_object + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:_dl_new_object + fun:_dl_map_object_from_fd + fun:_dl_map_object + fun:openaux + fun:_dl_catch_error + fun:_dl_map_object_deps + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:_dl_* + fun:_dl_* + fun:_dl_* + fun:dl_open_worker + fun:_dl_catch_error + fun:_dl_open + fun:dlopen_doit + fun:_dl_catch_error + fun:_dlerror_run + fun:dlopen@@GLIBC_2.2.5 +} + +# glib type leaks +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_register_static +} + +# new registry system +# all of this will only be created once when loading registry. + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_priv_gst_registry_chunks_load_plugin +} + +# system-wide tags +# these tags are registered once + +{ + + Memcheck:Leak + fun:*alloc + fun:* + fun:* + fun:gst_tag_register + fun:_gst_tag_initialize +} + +# system-wide type classes that we keep referenced + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_class_ref +} + +# leaking cached queries which are only initialized once +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_gst_query_initialize + fun:init_post +} + +# macosx (leopard) library loader leak +{ + + Memcheck:Leak + fun:_Znwm + fun:_ZNSs4_Rep9_S_createEmmRKSaIcE + fun:_ZNSs12_S_constructIPKcEEPcT_S3_RKSaIcESt20forward_iterator_tag + fun:_ZNSsC2EPKcRKSaIcE + fun:_Z41__static_initialization_and_destruction_0ii + fun:_ZN16ImageLoaderMachO18doModInitFunctionsERKN11ImageLoader11LinkContextE +} + +# GObject type registration +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_g_atomic_array_copy +} + +{ + + Memcheck:Leak + fun:*alloc + fun:getdelim + obj:*libselinux* +} + +{ + + Memcheck:Leak + fun:*alloc + ... + obj:*/sed +} + +# GLib 2.23 interface vtable +{ + + Memcheck:Leak + fun:*alloc + ... + fun:g_type_add_interface_static +} + +{ + + Memcheck:Leak + fun:*alloc + obj:*/dash +} + +# libtool/gentoo fake leak +# it actually runs bash and valgrind complains +{ + + Memcheck:Leak + fun:*alloc + obj:/bin/bash +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:_gst_plugin_loader_client_run + fun:main +} diff --git a/gst-plugins-base-subtitles0.10/common/gstdoc-scangobj b/gst-plugins-base-subtitles0.10/common/gstdoc-scangobj new file mode 100755 index 0000000..688b2c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gstdoc-scangobj @@ -0,0 +1,1571 @@ +#!/usr/bin/env perl +# -*- cperl -*- +# +# gtk-doc - GTK DocBook documentation generator. +# Copyright (C) 1998 Damon Chaplin +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + +# +# This gets information about object hierarchies and signals +# by compiling a small C program. CFLAGS and LDFLAGS must be +# set appropriately before running this script. +# + +use Getopt::Long; + +my $GTK_DOC_PREFIX=`pkg-config --variable prefix gtk-doc`; +if ($GTK_DOC_PREFIX) { + chomp $GTK_DOC_PREFIX; + #print "Adding $GTK_DOC_PREFIX/share/gtk-doc/data to \@INC\n"; + unshift @INC, "$GTK_DOC_PREFIX/share/gtk-doc/data"; +} else { + unshift @INC, '/usr/share/gtk-doc/data'; +} +require "gtkdoc-common.pl"; + +# Options + +# name of documentation module +my $MODULE; +my $OUTPUT_DIR; +my $INSPECT_DIR; +my $PRINT_VERSION; +my $PRINT_HELP; +my $TYPE_INIT_FUNC="g_type_init ()"; + +# --nogtkinit is deprecated, as it is the default now anyway. +%optctl = (module => \$MODULE, + source => \$SOURCE, + types => \$TYPES_FILE, + nogtkinit => \$NO_GTK_INIT, + 'type-init-func' => \$TYPE_INIT_FUNC, + 'output-dir' => \$OUTPUT_DIR, + 'inspect-dir' => \$INSPECT_DIR, + 'version' => \$PRINT_VERSION, + 'help' => \$PRINT_HELP); + +GetOptions(\%optctl, "module=s", "source=s", "types:s", "output-dir:s", "inspect-dir:s", "nogtkinit", "type-init-func:s", "version", "help"); + +if ($NO_GTK_INIT) { + # Do nothing. This just avoids a warning. + # the option is not used anymore +} + +if ($PRINT_VERSION) { + print "1.5\n"; + exit 0; +} + +if (!$MODULE) { + $PRINT_HELP = 1; +} + +if ($PRINT_HELP) { + print "gstdoc-scangobj version 1.5\n"; + print "\n--module=MODULE_NAME Name of the doc module being parsed"; + print "\n--source=SOURCE_NAME Name of the source module for plugins"; + print "\n--types=FILE The name of the file to store the types in"; + print "\n--type-init-func=FUNC The init function to call instead of g_type_init ()"; + print "\n--output-dir=DIRNAME The directory where the results are stored"; + print "\n--inspect-dir=DIRNAME The directory where the plugin inspect data is stored"; + print "\n--version Print the version of this program"; + print "\n--help Print this help\n"; + exit 0; +} + +$OUTPUT_DIR = $OUTPUT_DIR ? $OUTPUT_DIR : "."; + +$TYPES_FILE = $TYPES_FILE ? $TYPES_FILE : "$OUTPUT_DIR/$MODULE.types"; + +open (TYPES, $TYPES_FILE) || die "Cannot open $TYPES_FILE: $!\n"; +open (OUTPUT, ">$MODULE-scan.c") || die "Cannot open $MODULE-scan.c: $!\n"; + +my $old_signals_filename = "$OUTPUT_DIR/$MODULE.signals"; +my $new_signals_filename = "$OUTPUT_DIR/$MODULE.signals.new"; +my $old_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy"; +my $new_hierarchy_filename = "$OUTPUT_DIR/$MODULE.hierarchy.new"; +my $old_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces"; +my $new_interfaces_filename = "$OUTPUT_DIR/$MODULE.interfaces.new"; +my $old_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites"; +my $new_prerequisites_filename = "$OUTPUT_DIR/$MODULE.prerequisites.new"; +my $old_args_filename = "$OUTPUT_DIR/$MODULE.args"; +my $new_args_filename = "$OUTPUT_DIR/$MODULE.args.new"; + +# write a C program to scan the types + +$includes = ""; +@types = (); +@impl_types = (); + +for () { + if (/^#include/) { + $includes .= $_; + } elsif (/^%/) { + next; + } elsif (/^\s*$/) { + next; + } elsif (/^type:(.*)$/) { + $t = $1; + chomp $t; + push @impl_types, $t; + } else { + chomp; + push @types, $_; + } +} + +$ntypes = @types + @impl_types + 1; + +print OUTPUT < +#include +#include +#include + +$includes + +#ifdef GTK_IS_WIDGET_CLASS +#include +#endif + +static GType *object_types = NULL; + +static GString *xmlstr = NULL; + +static const gchar* +xmlprint (gint indent, const gchar *tag, const gchar *data) +{ + const gchar indent_str[] = " "; + + /* reset */ + g_string_truncate (xmlstr, 0); + g_string_append_len (xmlstr, indent_str, MIN (indent, strlen (indent_str))); + g_string_append_printf (xmlstr, "<%s>", tag); + + if (data) { + gchar *s; + + s = g_markup_escape_text (data, -1); + g_string_append (xmlstr, s); + g_free (s); + } + + g_string_append_printf (xmlstr, "\\n", tag); + return xmlstr->str; +} + +static gint +gst_feature_sort_compare (gconstpointer a, gconstpointer b) +{ + return strcmp (((GstPluginFeature *)a)->name, ((GstPluginFeature *)b)->name); +} + +static gint +static_pad_template_compare (gconstpointer a, gconstpointer b) +{ + GstStaticPadTemplate *spt_a = (GstStaticPadTemplate *) a; + GstStaticPadTemplate *spt_b = (GstStaticPadTemplate *) b; + + /* we want SINK before SRC (enum is UNKNOWN, SRC, SINK) */ + if (spt_a->direction != spt_b->direction) + return spt_b->direction - spt_a->direction; + + /* we want ALWAYS first, SOMETIMES second, REQUEST last + * (enum is ALWAYS, SOMETIMES, REQUEST) */ + if (spt_a->presence != spt_b->presence) + return spt_a->presence - spt_b->presence; + + return strcmp (spt_a->name_template, spt_b->name_template); +} + +static GType * +get_object_types (void) +{ + gpointer g_object_class; + GList *plugins = NULL; + GList *factories = NULL; + GList *l; + GstElementFactory *factory = NULL; + GType type; + gint i = 0; + gboolean reinspect; + + /* get a list of features from plugins in our source module */ + plugins = gst_registry_get_plugin_list (gst_registry_get_default()); + + xmlstr = g_string_new (""); + + reinspect = !g_file_test ("scanobj-build.stamp", G_FILE_TEST_EXISTS); + + while (plugins) { + GList *features; + GstPlugin *plugin; + const gchar *source; + FILE *inspect = NULL; + gchar *inspect_name; + + plugin = (GstPlugin *) (plugins->data); + plugins = g_list_next (plugins); + source = gst_plugin_get_source (plugin); + /*g_print ("plugin: %s source: %s\\n", plugin->desc.name, source);*/ + if (!source || strcmp (source, "$SOURCE") != 0) { + continue; + } + + /* skip static coreelements plugin with pipeline and bin element factory */ + if (gst_plugin_get_filename (plugin) == NULL) + continue; + + g_print ("plugin: %s source: %s\\n", plugin->desc.name, source); + + if (reinspect) { + inspect_name = g_strdup_printf ("$INSPECT_DIR" G_DIR_SEPARATOR_S "plugin-%s.xml", + plugin->desc.name); + inspect = fopen (inspect_name, "w"); + if (inspect == NULL) { + g_error ("Could not open %s for writing: %s\\n", inspect_name, + g_strerror (errno)); + } + g_free (inspect_name); + + /* output plugin data */ + fputs ("\\n",inspect); + fputs (xmlprint(2, "name", plugin->desc.name),inspect); + fputs (xmlprint(2, "description", plugin->desc.description),inspect); + fputs (xmlprint(2, "filename", plugin->filename),inspect); + fputs (xmlprint(2, "basename", plugin->basename),inspect); + fputs (xmlprint(2, "version", plugin->desc.version),inspect); + fputs (xmlprint(2, "license", plugin->desc.license),inspect); + fputs (xmlprint(2, "source", plugin->desc.source),inspect); + fputs (xmlprint(2, "package", plugin->desc.package),inspect); + fputs (xmlprint(2, "origin", plugin->desc.origin),inspect); + fputs (" \\n", inspect); + } + + features = + gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), + plugin->desc.name); + + /* sort factories by feature->name */ + features = g_list_sort (features, gst_feature_sort_compare); + + while (features) { + GstPluginFeature *feature; + feature = GST_PLUGIN_FEATURE (features->data); + feature = gst_plugin_feature_load (feature); + if (!feature) { + g_warning ("Could not load plugin feature %s", + gst_plugin_feature_get_name (feature)); + } + + if (GST_IS_ELEMENT_FACTORY (feature)) { + const gchar *pad_dir[] = { "unknown","source","sink" }; + const gchar *pad_pres[] = { "always","sometimes","request" }; + GList *pads, *pad; + + /*g_print (" feature: %s\\n", feature->name);*/ + + factory = GST_ELEMENT_FACTORY (feature); + factories = g_list_prepend (factories, factory); + + if (reinspect) { + /* output element data */ + fputs (" \\n", inspect); + fputs (xmlprint(6, "name", feature->name),inspect); + fputs (xmlprint(6, "longname", gst_element_factory_get_longname (factory)),inspect); + fputs (xmlprint(6, "class", gst_element_factory_get_klass (factory)),inspect); + fputs (xmlprint(6, "description", gst_element_factory_get_description (factory)),inspect); + fputs (xmlprint(6, "author", gst_element_factory_get_author (factory)),inspect); + fputs (" \\n", inspect); + + /* output pad-template data */ + pads = g_list_copy ((GList *) gst_element_factory_get_static_pad_templates (factory)); + pads = g_list_sort (pads, static_pad_template_compare); + for (pad = pads; pad != NULL; pad = pad->next) { + GstStaticPadTemplate *pt = pad->data; + + fputs (" \\n", inspect); + fputs (xmlprint(10, "name", pt->name_template),inspect); + fputs (xmlprint(10, "direction", pad_dir[pt->direction]),inspect); + fputs (xmlprint(10, "presence", pad_pres[pt->presence]),inspect); + fputs (xmlprint(10, "details", pt->static_caps.string),inspect); + fputs (" \\n", inspect); + } + g_list_free (pads); + fputs (" \\n \\n", inspect); + } + } + features = g_list_next (features); + } + + if (reinspect) { + fputs (" \\n", inspect); + fclose (inspect); + } + } + + g_string_free (xmlstr, TRUE); + + g_message ("number of element factories: %d", g_list_length (factories)); + + /* allocate the object_types array to hold them */ + object_types = g_new0 (GType, g_list_length (factories)+$ntypes+1); + + l = factories; + i = 0; + + /* fill it */ + while (l) { + factory = GST_ELEMENT_FACTORY (l->data); + type = gst_element_factory_get_element_type (factory); + if (type != 0) { + g_message ("adding type %p for factory %s", (void *) type, gst_element_factory_get_longname (factory)); + object_types[i++] = type; + } else { + g_message ("type info for factory %s not found", + gst_element_factory_get_longname (factory)); + } + l = g_list_next (l); + } + +EOT + +# get_type functions: +for (@types) { +print OUTPUT < uppercase with '_' + * GFileMonitor -> file_monitor + * GIOExtensionPoint -> extension_point + * GtkTreeView -> tree_view + * if 2nd char is upper case too + * search for first lower case and go back one char + * else + * search for next upper case + */ + if (!strncmp (object_name, "Gtk", 3)) + object_arg = object_name + 3; + else if (!strncmp (object_name, "Gnome", 5)) + object_arg = object_name + 5; + else + object_arg = object_name; + + object_arg_lower = g_ascii_strdown (object_arg, -1); + sprintf (pos, "*%s\\n", object_arg_lower); + pos += strlen (pos); + if (!strncmp (object_arg_lower, "widget", 6)) + widget_num = 2; + g_free(object_arg_lower); + + /* Convert signal name to use underscores rather than dashes '-'. */ + strncpy (signal_name, query_info.signal_name, 127); + signal_name[127] = '\\0'; + for (i = 0; signal_name[i]; i++) + { + if (signal_name[i] == '-') + signal_name[i] = '_'; + } + + /* Output the signal parameters. */ + for (param = 0; param < query_info.n_params; param++) + { + type_name = get_type_name (query_info.param_types[param] & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer); + + /* Most arguments to the callback are called "arg1", "arg2", etc. + GtkWidgets are called "widget", "widget2", ... + GtkCallbacks are called "callback", "callback2", ... */ + if (!strcmp (type_name, "GtkWidget")) + { + arg_name = "widget"; + arg_num = &widget_num; + } + else if (!strcmp (type_name, "GtkCallback") + || !strcmp (type_name, "GtkCCallback")) + { + arg_name = "callback"; + arg_num = &callback_num; + } + else + { + arg_name = "arg"; + arg_num = ¶m_num; + } + sprintf (pos, "%s ", type_name); + pos += strlen (pos); + + if (!arg_num || *arg_num == 0) + sprintf (pos, "%s%s\\n", is_pointer ? "*" : " ", arg_name); + else + sprintf (pos, "%s%s%i\\n", is_pointer ? "*" : " ", arg_name, + *arg_num); + pos += strlen (pos); + + if (arg_num) + { + if (*arg_num == 0) + *arg_num = 2; + else + *arg_num += 1; + } + } + + pos = flags; + /* We use one-character flags for simplicity. */ + if (query_info.signal_flags & G_SIGNAL_RUN_FIRST) + *pos++ = 'f'; + if (query_info.signal_flags & G_SIGNAL_RUN_LAST) + *pos++ = 'l'; + if (query_info.signal_flags & G_SIGNAL_RUN_CLEANUP) + *pos++ = 'c'; + if (query_info.signal_flags & G_SIGNAL_NO_RECURSE) + *pos++ = 'r'; + if (query_info.signal_flags & G_SIGNAL_DETAILED) + *pos++ = 'd'; + if (query_info.signal_flags & G_SIGNAL_ACTION) + *pos++ = 'a'; + if (query_info.signal_flags & G_SIGNAL_NO_HOOKS) + *pos++ = 'h'; + *pos = 0; + + /* Output the return type and function name. */ + ret_type = get_type_name (query_info.return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE, &is_pointer); + + fprintf (fp, + "\\n%s::%s\\n%s%s\\n%s\\n%s\\n\\n", + object_name, query_info.signal_name, ret_type, is_pointer ? "*" : "", flags, buffer); +} + + +/* Returns the type name to use for a signal argument or return value, given + the GtkType from the signal info. It also sets is_pointer to TRUE if the + argument needs a '*' since it is a pointer. */ +static const gchar * +get_type_name (GType type, gboolean * is_pointer) +{ + const gchar *type_name; + + *is_pointer = FALSE; + type_name = g_type_name (type); + + switch (type) { + case G_TYPE_NONE: + case G_TYPE_CHAR: + case G_TYPE_UCHAR: + case G_TYPE_BOOLEAN: + case G_TYPE_INT: + case G_TYPE_UINT: + case G_TYPE_LONG: + case G_TYPE_ULONG: + case G_TYPE_FLOAT: + case G_TYPE_DOUBLE: + case G_TYPE_POINTER: + /* These all have normal C type names so they are OK. */ + return type_name; + + case G_TYPE_STRING: + /* A GtkString is really a gchar*. */ + *is_pointer = TRUE; + return "gchar"; + + case G_TYPE_ENUM: + case G_TYPE_FLAGS: + /* We use a gint for both of these. Hopefully a subtype with a decent + name will be registered and used instead, as GTK+ does itself. */ + return "gint"; + + case G_TYPE_BOXED: + /* The boxed type shouldn't be used itself, only subtypes. Though we + return 'gpointer' just in case. */ + return "gpointer"; + + case G_TYPE_PARAM: + /* A GParam is really a GParamSpec*. */ + *is_pointer = TRUE; + return "GParamSpec"; + +#if GLIB_CHECK_VERSION (2, 25, 9) + case G_TYPE_VARIANT: + *is_pointer = TRUE; + return "GVariant"; +#endif + +default: + break; + } + + /* For all GObject subclasses we can use the class name with a "*", + e.g. 'GtkWidget *'. */ + if (g_type_is_a (type, G_TYPE_OBJECT)) + *is_pointer = TRUE; + + /* Also catch non GObject root types */ + if (G_TYPE_IS_CLASSED (type)) + *is_pointer = TRUE; + + /* All boxed subtypes will be pointers as well. */ + /* Exception: GStrv */ + if (g_type_is_a (type, G_TYPE_BOXED) && + !g_type_is_a (type, G_TYPE_STRV)) + *is_pointer = TRUE; + + /* All pointer subtypes will be pointers as well. */ + if (g_type_is_a (type, G_TYPE_POINTER)) + *is_pointer = TRUE; + + /* But enums are not */ + if (g_type_is_a (type, G_TYPE_ENUM) || + g_type_is_a (type, G_TYPE_FLAGS)) + *is_pointer = FALSE; + + return type_name; +} + + +/* This outputs the hierarchy of all objects which have been initialized, + i.e. by calling their XXX_get_type() initialization function. */ +static void +output_object_hierarchy (void) +{ + FILE *fp; + gint i,j; + GType root, type; + GType root_types[$ntypes] = { G_TYPE_INVALID, }; + + fp = fopen (hierarchy_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", hierarchy_filename, g_strerror(errno)); + return; + } + output_hierarchy (fp, G_TYPE_OBJECT, 0); + output_hierarchy (fp, G_TYPE_INTERFACE, 0); + + for (i=0; object_types[i]; i++) { + root = object_types[i]; + while ((type = g_type_parent (root))) { + root = type; + } + if ((root != G_TYPE_OBJECT) && (root != G_TYPE_INTERFACE)) { + for (j=0; root_types[j]; j++) { + if (root == root_types[j]) { + root = G_TYPE_INVALID; break; + } + } + if(root) { + root_types[j] = root; + output_hierarchy (fp, root, 0); + } + } + } + + fclose (fp); +} + +/* This is called recursively to output the hierarchy of a object. */ +static void +output_hierarchy (FILE *fp, + GType type, + guint level) +{ + guint i; + GType *children; + guint n_children; + + if (!type) + return; + + for (i = 0; i < level; i++) + fprintf (fp, " "); + fprintf (fp, "%s\\n", g_type_name (type)); + + children = g_type_children (type, &n_children); + + for (i=0; i < n_children; i++) + output_hierarchy (fp, children[i], level + 1); + + g_free (children); +} + +static void output_object_interfaces (void) +{ + guint i; + FILE *fp; + + fp = fopen (interfaces_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", interfaces_filename, g_strerror(errno)); + return; + } + output_interfaces (fp, G_TYPE_OBJECT); + + for (i = 0; object_types[i]; i++) + { + if (!g_type_parent (object_types[i]) && + (object_types[i] != G_TYPE_OBJECT) && + G_TYPE_IS_INSTANTIATABLE (object_types[i])) + { + output_interfaces (fp, object_types[i]); + } + } + fclose (fp); +} + +static void +output_interfaces (FILE *fp, + GType type) +{ + guint i; + GType *children, *interfaces; + guint n_children, n_interfaces; + + if (!type) + return; + + interfaces = g_type_interfaces (type, &n_interfaces); + + if (n_interfaces > 0) + { + fprintf (fp, "%s", g_type_name (type)); + for (i=0; i < n_interfaces; i++) + fprintf (fp, " %s", g_type_name (interfaces[i])); + fprintf (fp, "\\n"); + } + g_free (interfaces); + + children = g_type_children (type, &n_children); + + for (i=0; i < n_children; i++) + output_interfaces (fp, children[i]); + + g_free (children); +} + +static void output_interface_prerequisites (void) +{ + FILE *fp; + + fp = fopen (prerequisites_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", prerequisites_filename, g_strerror(errno)); + return; + } + output_prerequisites (fp, G_TYPE_INTERFACE); + fclose (fp); +} + +static void +output_prerequisites (FILE *fp, + GType type) +{ +#if GLIB_CHECK_VERSION(2,1,0) + guint i; + GType *children, *prerequisites; + guint n_children, n_prerequisites; + + if (!type) + return; + + prerequisites = g_type_interface_prerequisites (type, &n_prerequisites); + + if (n_prerequisites > 0) + { + fprintf (fp, "%s", g_type_name (type)); + for (i=0; i < n_prerequisites; i++) + fprintf (fp, " %s", g_type_name (prerequisites[i])); + fprintf (fp, "\\n"); + } + g_free (prerequisites); + + children = g_type_children (type, &n_children); + + for (i=0; i < n_children; i++) + output_prerequisites (fp, children[i]); + + g_free (children); +#endif +} + +static void +output_args (void) +{ + FILE *fp; + gint i; + + fp = fopen (args_filename, "w"); + if (fp == NULL) + { + g_warning ("Couldn't open output file: %s : %s", args_filename, g_strerror(errno)); + return; + } + + for (i = 0; object_types[i]; i++) { + output_object_args (fp, object_types[i]); + } + + fclose (fp); +} + +static gint +compare_param_specs (const void *a, const void *b) +{ + GParamSpec *spec_a = *(GParamSpec **)a; + GParamSpec *spec_b = *(GParamSpec **)b; + + return strcmp (g_param_spec_get_name (spec_a), g_param_spec_get_name (spec_b)); +} + +/* Its common to have unsigned properties restricted + * to the signed range. Therefore we make this look + * a bit nicer by spelling out the max constants. + */ + +/* Don't use "==" with floats, it might trigger a gcc warning. */ +#define GTKDOC_COMPARE_FLOAT(x, y) (x <= y && x >= y) + +static gchar* +describe_double_constant (gdouble value) +{ + gchar *desc; + + if (GTKDOC_COMPARE_FLOAT (value, G_MAXDOUBLE)) + desc = g_strdup ("G_MAXDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MINDOUBLE)) + desc = g_strdup ("G_MINDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXDOUBLE)) + desc = g_strdup ("-G_MAXDOUBLE"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MAXFLOAT)) + desc = g_strdup ("G_MAXFLOAT"); + else if (GTKDOC_COMPARE_FLOAT (value, G_MINFLOAT)) + desc = g_strdup ("G_MINFLOAT"); + else if (GTKDOC_COMPARE_FLOAT (value, -G_MAXFLOAT)) + desc = g_strdup ("-G_MAXFLOAT"); + else{ + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", value); + } + + return desc; +} + +static gchar* +describe_signed_constant (gsize size, gint64 value) +{ + gchar *desc = NULL; + + switch (size) { + case 8: + if (value == G_MAXINT64) + desc = g_strdup ("G_MAXINT64"); + else if (value == G_MININT64) + desc = g_strdup ("G_MININT64"); + /* fall through */ + case 4: + if (sizeof (int) == 4) { + if (value == G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MININT) + desc = g_strdup ("G_MININT"); + else if (value == (gint64)G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + if (value == G_MAXLONG) + desc = g_strdup ("G_MAXLONG"); + else if (value == G_MINLONG) + desc = g_strdup ("G_MINLONG"); + else if (value == (gint64)G_MAXULONG) + desc = g_strdup ("G_MAXULONG"); + /* fall through */ + case 2: + if (sizeof (int) == 2) { + if (value == G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MININT) + desc = g_strdup ("G_MININT"); + else if (value == (gint64)G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + break; + default: + break; + } + if (!desc) + desc = g_strdup_printf ("%" G_GINT64_FORMAT, value); + + return desc; +} + +static gchar* +describe_unsigned_constant (gsize size, guint64 value) +{ + gchar *desc = NULL; + + switch (size) { + case 8: + if (value == G_MAXINT64) + desc = g_strdup ("G_MAXINT64"); + else if (value == G_MAXUINT64) + desc = g_strdup ("G_MAXUINT64"); + /* fall through */ + case 4: + if (sizeof (int) == 4) { + if (value == (guint64)G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + if (value == (guint64)G_MAXLONG) + desc = g_strdup ("G_MAXLONG"); + else if (value == G_MAXULONG) + desc = g_strdup ("G_MAXULONG"); + /* fall through */ + case 2: + if (sizeof (int) == 2) { + if (value == (guint64)G_MAXINT) + desc = g_strdup ("G_MAXINT"); + else if (value == G_MAXUINT) + desc = g_strdup ("G_MAXUINT"); + } + break; + default: + break; + } + if (!desc) + desc = g_strdup_printf ("%" G_GUINT64_FORMAT, value); + + return desc; +} + +static gchar* +describe_type (GParamSpec *spec) +{ + gchar *desc; + gchar *lower; + gchar *upper; + + if (G_IS_PARAM_SPEC_CHAR (spec)) + { + GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec); + + lower = describe_signed_constant (sizeof(gchar), pspec->minimum); + upper = describe_signed_constant (sizeof(gchar), pspec->maximum); + if (pspec->minimum == G_MININT8 && pspec->maximum == G_MAXINT8) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT8) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT8) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UCHAR (spec)) + { + GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec); + + lower = describe_unsigned_constant (sizeof(guchar), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guchar), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT8) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT8) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_INT (spec)) + { + GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec); + + lower = describe_signed_constant (sizeof(gint), pspec->minimum); + upper = describe_signed_constant (sizeof(gint), pspec->maximum); + if (pspec->minimum == G_MININT && pspec->maximum == G_MAXINT) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UINT (spec)) + { + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec); + + lower = describe_unsigned_constant (sizeof(guint), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guint), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec); + + lower = describe_signed_constant (sizeof(glong), pspec->minimum); + upper = describe_signed_constant (sizeof(glong), pspec->maximum); + if (pspec->minimum == G_MINLONG && pspec->maximum == G_MAXLONG) + desc = g_strdup (""); + else if (pspec->minimum == G_MINLONG) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXLONG) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_ULONG (spec)) + { + GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec); + + lower = describe_unsigned_constant (sizeof(gulong), pspec->minimum); + upper = describe_unsigned_constant (sizeof(gulong), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXULONG) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXULONG) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_INT64 (spec)) + { + GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec); + + lower = describe_signed_constant (sizeof(gint64), pspec->minimum); + upper = describe_signed_constant (sizeof(gint64), pspec->maximum); + if (pspec->minimum == G_MININT64 && pspec->maximum == G_MAXINT64) + desc = g_strdup (""); + else if (pspec->minimum == G_MININT64) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXINT64) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_UINT64 (spec)) + { + GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec); + + lower = describe_unsigned_constant (sizeof(guint64), pspec->minimum); + upper = describe_unsigned_constant (sizeof(guint64), pspec->maximum); + if (pspec->minimum == 0 && pspec->maximum == G_MAXUINT64) + desc = g_strdup (""); + else if (pspec->minimum == 0) + desc = g_strdup_printf ("<= %s", upper); + else if (pspec->maximum == G_MAXUINT64) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_FLOAT (spec)) + { + GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec); + + lower = describe_double_constant (pspec->minimum); + upper = describe_double_constant (pspec->maximum); + if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXFLOAT)) + { + if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT)) + desc = g_strdup (""); + else + desc = g_strdup_printf ("<= %s", upper); + } + else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXFLOAT)) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } + else if (G_IS_PARAM_SPEC_DOUBLE (spec)) + { + GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec); + + lower = describe_double_constant (pspec->minimum); + upper = describe_double_constant (pspec->maximum); + if (GTKDOC_COMPARE_FLOAT (pspec->minimum, -G_MAXDOUBLE)) + { + if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE)) + desc = g_strdup (""); + else + desc = g_strdup_printf ("<= %s", upper); + } + else if (GTKDOC_COMPARE_FLOAT (pspec->maximum, G_MAXDOUBLE)) + desc = g_strdup_printf (">= %s", lower); + else + desc = g_strdup_printf ("[%s,%s]", lower, upper); + g_free (lower); + g_free (upper); + } +#if GLIB_CHECK_VERSION (2, 12, 0) + else if (G_IS_PARAM_SPEC_GTYPE (spec)) + { + GParamSpecGType *pspec = G_PARAM_SPEC_GTYPE (spec); + gboolean is_pointer; + + desc = g_strdup (get_type_name (pspec->is_a_type, &is_pointer)); + } +#endif +#if GLIB_CHECK_VERSION (2, 25, 9) + else if (G_IS_PARAM_SPEC_VARIANT (spec)) + { + GParamSpecVariant *pspec = G_PARAM_SPEC_VARIANT (spec); + gchar *variant_type; + + variant_type = g_variant_type_dup_string (pspec->type); + desc = g_strdup_printf ("GVariant<%s>", variant_type); + g_free (variant_type); + } +#endif + else + { + desc = g_strdup (""); + } + + return desc; +} + +static gchar* +describe_default (GParamSpec *spec) +{ + gchar *desc; + + if (G_IS_PARAM_SPEC_CHAR (spec)) + { + GParamSpecChar *pspec = G_PARAM_SPEC_CHAR (spec); + + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UCHAR (spec)) + { + GParamSpecUChar *pspec = G_PARAM_SPEC_UCHAR (spec); + + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_BOOLEAN (spec)) + { + GParamSpecBoolean *pspec = G_PARAM_SPEC_BOOLEAN (spec); + + desc = g_strdup_printf ("%s", pspec->default_value ? "TRUE" : "FALSE"); + } + else if (G_IS_PARAM_SPEC_INT (spec)) + { + GParamSpecInt *pspec = G_PARAM_SPEC_INT (spec); + + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UINT (spec)) + { + GParamSpecUInt *pspec = G_PARAM_SPEC_UINT (spec); + + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecLong *pspec = G_PARAM_SPEC_LONG (spec); + + desc = g_strdup_printf ("%ld", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_LONG (spec)) + { + GParamSpecULong *pspec = G_PARAM_SPEC_ULONG (spec); + + desc = g_strdup_printf ("%lu", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_INT64 (spec)) + { + GParamSpecInt64 *pspec = G_PARAM_SPEC_INT64 (spec); + + desc = g_strdup_printf ("%" G_GINT64_FORMAT, pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UINT64 (spec)) + { + GParamSpecUInt64 *pspec = G_PARAM_SPEC_UINT64 (spec); + + desc = g_strdup_printf ("%" G_GUINT64_FORMAT, pspec->default_value); + } + else if (G_IS_PARAM_SPEC_UNICHAR (spec)) + { + GParamSpecUnichar *pspec = G_PARAM_SPEC_UNICHAR (spec); + + if (g_unichar_isprint (pspec->default_value)) + desc = g_strdup_printf ("'%c'", pspec->default_value); + else + desc = g_strdup_printf ("%u", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_ENUM (spec)) + { + GParamSpecEnum *pspec = G_PARAM_SPEC_ENUM (spec); + + GEnumValue *value = g_enum_get_value (pspec->enum_class, pspec->default_value); + if (value) + desc = g_strdup_printf ("%s", value->value_name); + else + desc = g_strdup_printf ("%d", pspec->default_value); + } + else if (G_IS_PARAM_SPEC_FLAGS (spec)) + { + GParamSpecFlags *pspec = G_PARAM_SPEC_FLAGS (spec); + guint default_value; + GString *acc; + + default_value = pspec->default_value; + acc = g_string_new (""); + + while (default_value) + { + GFlagsValue *value = g_flags_get_first_value (pspec->flags_class, default_value); + + if (!value) + break; + + if (acc->len > 0) + g_string_append (acc, "|"); + g_string_append (acc, value->value_name); + + default_value &= ~value->value; + } + + if (default_value == 0) + desc = g_string_free (acc, FALSE); + else + { + desc = g_strdup_printf ("%d", pspec->default_value); + g_string_free (acc, TRUE); + } + } + else if (G_IS_PARAM_SPEC_FLOAT (spec)) + { + GParamSpecFloat *pspec = G_PARAM_SPEC_FLOAT (spec); + + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", + pspec->default_value); + } + else if (G_IS_PARAM_SPEC_DOUBLE (spec)) + { + GParamSpecDouble *pspec = G_PARAM_SPEC_DOUBLE (spec); + + /* make sure floats are output with a decimal dot irrespective of + * current locale. Use formatd since we want human-readable numbers + * and do not need the exact same bit representation when deserialising */ + desc = g_malloc0 (G_ASCII_DTOSTR_BUF_SIZE); + g_ascii_formatd (desc, G_ASCII_DTOSTR_BUF_SIZE, "%g", + pspec->default_value); + } + else if (G_IS_PARAM_SPEC_STRING (spec)) + { + GParamSpecString *pspec = G_PARAM_SPEC_STRING (spec); + + if (pspec->default_value) + { + gchar *esc = g_strescape (pspec->default_value, NULL); + + desc = g_strdup_printf ("\\"%s\\"", esc); + + g_free (esc); + } + else + desc = g_strdup_printf ("NULL"); + } + else + { + desc = g_strdup (""); + } + + return desc; +} + + +static void +output_object_args (FILE *fp, GType object_type) +{ + gpointer class; + const gchar *object_class_name; + guint arg; + gchar flags[16], *pos; + GParamSpec **properties; + guint n_properties; + gboolean child_prop; + gboolean style_prop; + gboolean is_pointer; + const gchar *type_name; + gchar *type_desc; + gchar *default_value; + + if (G_TYPE_IS_OBJECT (object_type)) + { + class = g_type_class_peek (object_type); + if (!class) + return; + + properties = g_object_class_list_properties (class, &n_properties); + } +#if GLIB_MAJOR_VERSION > 2 || (GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION >= 3) + else if (G_TYPE_IS_INTERFACE (object_type)) + { + class = g_type_default_interface_ref (object_type); + + if (!class) + return; + + properties = g_object_interface_list_properties (class, &n_properties); + } +#endif + else + return; + + object_class_name = g_type_name (object_type); + + child_prop = FALSE; + style_prop = FALSE; + + while (TRUE) { + qsort (properties, n_properties, sizeof (GParamSpec *), compare_param_specs); + for (arg = 0; arg < n_properties; arg++) + { + GParamSpec *spec = properties[arg]; + const gchar *nick, *blurb, *dot; + + if (spec->owner_type != object_type) + continue; + + pos = flags; + /* We use one-character flags for simplicity. */ + if (child_prop && !style_prop) + *pos++ = 'c'; + if (style_prop) + *pos++ = 's'; + if (spec->flags & G_PARAM_READABLE) + *pos++ = 'r'; + if (spec->flags & G_PARAM_WRITABLE) + *pos++ = 'w'; + if (spec->flags & G_PARAM_CONSTRUCT) + *pos++ = 'x'; + if (spec->flags & G_PARAM_CONSTRUCT_ONLY) + *pos++ = 'X'; + *pos = 0; + + nick = g_param_spec_get_nick (spec); + blurb = g_param_spec_get_blurb (spec); + + dot = ""; + if (blurb) { + int str_len = strlen (blurb); + if (str_len > 0 && blurb[str_len - 1] != '.') + dot = "."; + } + + type_desc = describe_type (spec); + default_value = describe_default (spec); + type_name = get_type_name (spec->value_type, &is_pointer); + fprintf (fp, "\\n%s::%s\\n%s%s\\n%s\\n%s\\n%s\\n%s%s\\n%s\\n\\n\\n", + object_class_name, g_param_spec_get_name (spec), type_name, is_pointer ? "*" : "", type_desc, flags, nick ? nick : "(null)", blurb ? blurb : "(null)", dot, default_value); + g_free (type_desc); + g_free (default_value); + } + + g_free (properties); + +#ifdef GTK_IS_CONTAINER_CLASS + if (!child_prop && GTK_IS_CONTAINER_CLASS (class)) { + properties = gtk_container_class_list_child_properties (class, &n_properties); + child_prop = TRUE; + continue; + } +#endif + +#ifdef GTK_IS_CELL_AREA_CLASS + if (!child_prop && GTK_IS_CELL_AREA_CLASS (class)) { + properties = gtk_cell_area_class_list_cell_properties (class, &n_properties); + child_prop = TRUE; + continue; + } +#endif + +#ifdef GTK_IS_WIDGET_CLASS +#if GTK_CHECK_VERSION(2,1,0) + if (!style_prop && GTK_IS_WIDGET_CLASS (class)) { + properties = gtk_widget_class_list_style_properties (GTK_WIDGET_CLASS (class), &n_properties); + style_prop = TRUE; + continue; + } +#endif +#endif + + break; + } +} +EOT + +close OUTPUT; + +# Compile and run our file + +$CC = $ENV{CC} ? $ENV{CC} : "gcc"; +$LD = $ENV{LD} ? $ENV{LD} : $CC; +$CFLAGS = $ENV{CFLAGS} ? "$ENV{CFLAGS}" : ""; +$LDFLAGS = $ENV{LDFLAGS} ? $ENV{LDFLAGS} : ""; + +my $o_file; +if ($CC =~ /libtool/) { + $o_file = "$MODULE-scan.lo" +} else { + $o_file = "$MODULE-scan.o" +} + +print "gtk-doc: Compiling scanner\n"; +$command = "$CC $CFLAGS -c -o $o_file $MODULE-scan.c"; +system($command) == 0 or die "Compilation of scanner failed: $!\n"; + +print "gtk-doc: Linking scanner\n"; +$command = "$LD -o $MODULE-scan $o_file $LDFLAGS"; +system($command) == 0 or die "Linking of scanner failed: $!\n"; + +print "gtk-doc: Running scanner $MODULE-scan\n"; +system("sh -c ./$MODULE-scan") == 0 or die "Scan failed: $!\n"; + +if (!defined($ENV{"GTK_DOC_KEEP_INTERMEDIATE"})) { + unlink "./$MODULE-scan.c", "./$MODULE-scan.o", "./$MODULE-scan.lo", "./$MODULE-scan"; +} + +&UpdateFileIfChanged ($old_hierarchy_filename, $new_hierarchy_filename, 0); +&UpdateFileIfChanged ($old_interfaces_filename, $new_interfaces_filename, 0); +&UpdateFileIfChanged ($old_prerequisites_filename, $new_prerequisites_filename, 0); +# we will merge these in scangobj-merge.py +#&UpdateFileIfChanged ($old_signals_filename, $new_signals_filename, 0); +#&UpdateFileIfChanged ($old_args_filename, $new_args_filename, 0); + diff --git a/gst-plugins-base-subtitles0.10/common/gtk-doc-plugins.mak b/gst-plugins-base-subtitles0.10/common/gtk-doc-plugins.mak new file mode 100644 index 0000000..ca6a351 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gtk-doc-plugins.mak @@ -0,0 +1,379 @@ +# This is an include file specifically tuned for building documentation +# for GStreamer plug-ins + +help: + @echo + @echo "If you are a doc maintainer, run 'make update' to update" + @echo "the documentation files maintained in git" + @echo + @echo Other useful make targets: + @echo + @echo check-inspected-versions: make sure the inspected plugin info + @echo is up to date before a release + @echo + +# update the stuff maintained by doc maintainers +update: + $(MAKE) scanobj-update + $(MAKE) check-outdated-docs + +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +# thomas: make docs parallel installable +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@ + +MAINTAINER_DOC_STAMPS = \ + scanobj-build.stamp + +EXTRA_DIST = \ + $(MAINTAINER_DOC_STAMPS) \ + $(srcdir)/inspect/*.xml \ + $(SCANOBJ_FILES) \ + $(content_files) \ + $(extra_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_OVERRIDES) \ + $(DOC_MODULE)-sections.txt + +# we don't add scanobj-build.stamp here since they are built manually by docs +# maintainers and result is commited to git +DOC_STAMPS = \ + scan-build.stamp \ + tmpl-build.stamp \ + sgml-build.stamp \ + html-build.stamp \ + scan.stamp \ + tmpl.stamp \ + sgml.stamp \ + html.stamp + +# files generated/updated by gtkdoc-scangobj +SCANOBJ_FILES = \ + $(DOC_MODULE).signals \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).types \ + $(DOC_MODULE).args + +SCANOBJ_FILES_O = \ + .libs/$(DOC_MODULE)-scan.o + +# files generated/updated by gtkdoc-scan +SCAN_FILES = \ + $(DOC_MODULE)-sections.txt \ + $(DOC_MODULE)-overrides.txt \ + $(DOC_MODULE)-decl.txt \ + $(DOC_MODULE)-decl-list.txt + + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +# FC3 seems to need -scan.c to be part of CLEANFILES for distcheck +# no idea why FC4 can do without +CLEANFILES = \ + $(SCANOBJ_FILES_O) \ + $(DOC_MODULE)-scan.c \ + $(REPORT_FILES) \ + $(DOC_STAMPS) \ + inspect-registry.xml + +INSPECT_DIR = inspect + +if ENABLE_GTK_DOC +all-local: html-build.stamp + +### inspect GStreamer plug-ins; done by documentation maintainer ### + +# only look at the plugins in this module when building inspect .xml stuff +INSPECT_REGISTRY=$(top_builddir)/docs/plugins/inspect-registry.xml +INSPECT_ENVIRONMENT=\ + LC_ALL=C \ + GST_PLUGIN_SYSTEM_PATH= \ + GST_PLUGIN_PATH=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(top_builddir)/plugins:$(top_builddir)/src:$(top_builddir)/gnl \ + GST_REGISTRY=$(INSPECT_REGISTRY) \ + PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INSPECT_EXTRA_ENVIRONMENT) + +# update the element and plugin XML descriptions; store in inspect/ +inspect: + @-mkdir -p $(INSPECT_DIR) + +#### scan gobjects; done by documentation maintainer #### +scanobj-update: + -rm scanobj-build.stamp + $(MAKE) scanobj-build.stamp + +# TODO: finish elite script that updates the output files of this step +# instead of rewriting them, so that multiple maintainers can generate +# a collective set of args and signals +scanobj-build.stamp: $(SCANOBJ_DEPS) $(basefiles) inspect + @echo '*** Scanning GObjects ***' + @if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ + do \ + if test -e $(srcdir)/$$f; then cp -u $(srcdir)/$$f . ; fi; \ + done; \ + fi; \ + $(INSPECT_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS) $(WARNING_CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + $(GST_DOC_SCANOBJ) --type-init-func="gst_init(NULL,NULL)" \ + --module=$(DOC_MODULE) --source=$(PACKAGE) --inspect-dir=$(INSPECT_DIR) && \ + $(PYTHON) \ + $(top_srcdir)/common/scangobj-merge.py $(DOC_MODULE); \ + if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES); \ + do \ + cmp -s ./$$f $(srcdir)/$$f || cp ./$$f $(srcdir)/ ; \ + done; \ + fi; \ + touch scanobj-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(SCANOBJ_FILES_O): scan-build.stamp + @true + +### scan headers; done on every build ### +scan-build.stamp: $(HFILE_GLOB) $(EXTRA_HFILES) $(basefiles) scanobj-build.stamp + @echo '*** Scanning header files ***' + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + --source-dir=$(DOC_SOURCE_DIR) \ + --ignore-headers="$(IGNORE_HFILES)"; \ + touch scan-build.stamp + +#### update templates; done on every build #### + +### FIXME: make this error out again when docs are fixed for 0.X +# in a non-srcdir build, we need to copy files from the previous step +# and the files from previous runs of this step +tmpl-build.stamp: $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_OVERRIDES) + @echo '*** Rebuilding template files ***' + @if test x"$(srcdir)" != x. ; then \ + for f in $(SCANOBJ_FILES) $(SCAN_FILES); \ + do \ + if test -e $(srcdir)/$$f; then cp -u $(srcdir)/$$f . ; fi; \ + done; \ + fi + gtkdoc-mktmpl --module=$(DOC_MODULE) | tee tmpl-build.log + $(PYTHON) \ + $(top_srcdir)/common/mangle-tmpl.py $(srcdir)/$(INSPECT_DIR) tmpl + @rm -f tmpl-build.log + touch tmpl-build.stamp + +tmpl.stamp: tmpl-build.stamp + @true + +#### build xml; done on every build #### + +### FIXME: make this error out again when docs are fixed for 0.9 +sgml-build.stamp: tmpl.stamp scan-build.stamp $(CFILE_GLOB) $(top_srcdir)/common/plugins.xsl $(expand_content_files) + @echo '*** Building XML ***' + @-mkdir -p xml + @for a in $(srcdir)/$(INSPECT_DIR)/*.xml; do \ + xsltproc --stringparam module $(MODULE) \ + $(top_srcdir)/common/plugins.xsl $$a > xml/`basename $$a`; done + @for f in $(EXAMPLE_CFILES); do \ + $(PYTHON) $(top_srcdir)/common/c-to-xml.py $$f > xml/element-`basename $$f .c`.xml; done + gtkdoc-mkdb \ + --module=$(DOC_MODULE) \ + --source-dir=$(DOC_SOURCE_DIR) \ + --expand-content-files="$(expand_content_files)" \ + --main-sgml-file=$(srcdir)/$(DOC_MAIN_SGML_FILE) \ + --output-format=xml \ + --ignore-files="$(IGNORE_HFILES) $(IGNORE_CFILES)" \ + $(MKDB_OPTIONS) \ + | tee sgml-build.log + @if grep "WARNING:" sgml-build.log > /dev/null; then true; fi # exit 1; fi + cp ../version.entities xml + rm sgml-build.log + touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### build html; done on every step #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo '*** Building HTML ***' + if test -d html; then rm -rf html; fi + mkdir html + cp $(srcdir)/$(DOC_MAIN_SGML_FILE) html + @for f in $(content_files); do cp $(srcdir)/$$f html; done + cp -pr xml html + cp ../version.entities html + cd html && gtkdoc-mkhtml $(DOC_MODULE) $(DOC_MAIN_SGML_FILE) + mv html/index.sgml html/index.sgml.bak + $(SED) "s/ href=\"$(DOC_MODULE)\// href=\"$(DOC_MODULE)-@GST_MAJORMINOR@\//g" html/index.sgml.bak >html/index.sgml + rm -f html/index.sgml.bak + rm -f html/$(DOC_MAIN_SGML_FILE) + rm -rf html/xml + rm -f html/version.entities + test "x$(HTML_IMAGES)" = "x" || for i in "" $(HTML_IMAGES) ; do \ + if test "$$i" != ""; then cp $(srcdir)/$$i html ; fi; done + @echo '-- Fixing Crossreferences' + gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + touch html-build.stamp + +clean-local-gtkdoc: + rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build + if test x"$(srcdir)" != x. ; then \ + rm -rf $(SCANOBJ_FILES) $(SCAN_FILES) $(REPORT_FILES) \ + $(MAINTAINER_DOC_STAMPS); \ + fi +else +all-local: +clean-local-gtkdoc: +endif + +clean-local: clean-local-gtkdoc + rm -f *~ *.bak + rm -rf .libs + +distclean-local: + rm -f $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + rm -rf tmpl/*.sgml.bak + rm -f $(DOC_MODULE).hierarchy + rm -f *.stamp || true + if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(DOC_MODULE)-docs.sgml ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE)-overrides.txt ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -rf tmpl/*.sgml ; \ + rm -rf $(INSPECT_DIR); \ + fi + rm -rf *.o + +MAINTAINERCLEANFILES = $(MAINTAINER_DOC_STAMPS) + +# thomas: make docs parallel installable; devhelp requires majorminor too +install-data-local: + (installfiles=`echo $(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css`; \ + if test "$$installfiles" = '$(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css'; \ + then echo '-- Nothing to install' ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + pngfiles=`echo ./html/*.png`; \ + if test "$$pngfiles" != './html/*.png'; then \ + for i in $$pngfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + fi; \ + echo '-- Installing $(builddir)/html/$(DOC_MODULE).devhelp' ; \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE).devhelp \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@.devhelp; \ + if test -e $(builddir)/html/$(DOC_MODULE).devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE).devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@.devhelp2; \ + fi; \ + (which gtkdoc-rebase >/dev/null && \ + gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR)) || true ; \ + fi) +uninstall-local: + if test -d $(DESTDIR)$(TARGET_DIR); then \ + rm -rf $(DESTDIR)$(TARGET_DIR)/*; \ + rmdir -p $(DESTDIR)$(TARGET_DIR) 2>/dev/null || true; \ + else \ + echo '-- Nothing to uninstall' ; \ + fi; + +# +# Checks +# +if ENABLE_GTK_DOC +check-hierarchy: $(DOC_MODULE).hierarchy + @if grep ' ' $(DOC_MODULE).hierarchy; then \ + echo "$(DOC_MODULE).hierarchy contains tabs, please fix"; \ + /bin/false; \ + fi + +check: check-hierarchy +endif + +# wildcard is apparently not portable to other makes, hence the use of find +inspect_files = $(shell find $(srcdir)/$(INSPECT_DIR) -name '*.xml') + +check-inspected-versions: + @echo Checking plugin versions of inspected plugin data ...; \ + fail=0 ; \ + for each in $(inspect_files) ; do \ + if (grep -H '' $$each | grep -v '$(VERSION)'); then \ + echo $$each should be fixed to say version $(VERSION) or be removed ; \ + echo "sed -i -e 's//$(VERSION)<\/version>/'" $$each; \ + echo ; \ + fail=1; \ + fi ; \ + done ; \ + exit $$fail + +check-outdated-docs: + $(AM_V_GEN)echo Checking for outdated plugin inspect data ...; \ + fail=0 ; \ + if [ -d $(top_srcdir)/.git/ ]; then \ + files=`find $(srcdir)/inspect/ -name '*xml'`; \ + for f in $$files; do \ + ver=`grep '$(PACKAGE_VERSION)' $$f`; \ + if test "x$$ver" = "x"; then \ + plugin=`echo $$f | sed -e 's/^.*plugin-//' -e 's/.xml//'`; \ + # echo "Checking $$plugin $$f"; \ + pushd "$(top_srcdir)" >/dev/null; \ + pinit=`git grep -A3 GST_PLUGIN_DEFINE -- ext/ gst/ sys/ | grep "\"$$plugin\""`; \ + popd >/dev/null; \ + # echo "[$$pinit]"; \ + if test "x$$pinit" = "x"; then \ + printf " **** outdated docs for plugin %-15s: %s\n" $$plugin $$f; \ + fail=1; \ + fi; \ + fi; \ + done; \ + fi ; \ + exit $$fail + +# +# Require gtk-doc when making dist +# +if ENABLE_GTK_DOC +dist-check-gtkdoc: +else +dist-check-gtkdoc: + @echo "*** gtk-doc must be installed and enabled in order to make dist" + @false +endif + +# FIXME: decide whether we want to dist generated html or not +# also this only works, if the project has been build before +# we could dist html only if its there, but that might lead to missing html in +# tarballs +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/html + cp html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs check-outdated-docs inspect + +# avoid spurious build errors when distchecking with -jN +.NOTPARALLEL: diff --git a/gst-plugins-base-subtitles0.10/common/gtk-doc.mak b/gst-plugins-base-subtitles0.10/common/gtk-doc.mak new file mode 100644 index 0000000..91edeee --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/gtk-doc.mak @@ -0,0 +1,234 @@ +########################################################################### +# Everything below here is generic and you shouldn't need to change it. +########################################################################### +# thomas: except of course that we did + +# thomas: copied from glib-2 +# We set GPATH here; this gives us semantics for GNU make +# which are more like other make's VPATH, when it comes to +# whether a source that is a target of one rule is then +# searched for in VPATH/GPATH. +# +GPATH = $(srcdir) + +# thomas: make docs parallel installable +TARGET_DIR=$(HTML_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@ + +EXTRA_DIST = \ + $(content_files) \ + $(extra_files) \ + $(HTML_IMAGES) \ + $(DOC_MAIN_SGML_FILE) \ + $(DOC_MODULE).types \ + $(DOC_OVERRIDES) \ + $(DOC_MODULE)-sections.txt + +DOC_STAMPS = \ + setup-build.stamp \ + scan-build.stamp \ + sgml-build.stamp \ + html-build.stamp \ + setup.stamp \ + sgml.stamp \ + html.stamp + +SCANOBJ_FILES = \ + $(DOC_MODULE).args \ + $(DOC_MODULE).hierarchy \ + $(DOC_MODULE).interfaces \ + $(DOC_MODULE).prerequisites \ + $(DOC_MODULE).signals \ + .libs/$(DOC_MODULE)-scan.o + +REPORT_FILES = \ + $(DOC_MODULE)-undocumented.txt \ + $(DOC_MODULE)-undeclared.txt \ + $(DOC_MODULE)-unused.txt + +CLEANFILES = $(SCANOBJ_FILES) $(REPORT_FILES) $(DOC_STAMPS) doc-registry.xml + +if ENABLE_GTK_DOC +all-local: html-build.stamp + +#### setup #### + +setup.stamp: $(content_files) + -@if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + cp -p $(abs_srcdir)/$(DOC_MAIN_SGML_FILE) \ + $(abs_srcdir)/$(DOC_MODULE)-overrides.txt \ + $(abs_srcdir)/$(DOC_MODULE)-sections.txt \ + $(abs_srcdir)/$(DOC_MODULE).types \ + $(abs_builddir)/; \ + if test "x$(content_files)" != "x" ; then \ + for file in $(content_files) ; do \ + test -f $(abs_srcdir)/$$file || \ + cp -p $(abs_srcdir)/$$file $(abs_builddir)/; \ + done \ + fi \ + fi + touch setup.stamp + +#### scan #### + +# in the case of non-srcdir builds, the built gst directory gets added +# to gtk-doc scanning; but only then, to avoid duplicates +scan-build.stamp: $(HFILE_GLOB) $(CFILE_GLOB) + @echo '*** Scanning header files ***' + if grep -l '^..*$$' $(DOC_MODULE).types > /dev/null; \ + then \ + GST_PLUGIN_SYSTEM_PATH=`cd $(top_builddir) && pwd` \ + GST_PLUGIN_PATH= \ + GST_REGISTRY=doc-registry.xml \ + $(GTKDOC_EXTRA_ENVIRONMENT) \ + CC="$(GTKDOC_CC)" LD="$(GTKDOC_LD)" \ + CFLAGS="$(GTKDOC_CFLAGS) $(CFLAGS)" \ + LDFLAGS="$(GTKDOC_LIBS) $(LDFLAGS)" \ + gtkdoc-scangobj --type-init-func="gst_init(NULL,NULL)" \ + --module=$(DOC_MODULE) ; \ + else \ + for i in $(SCANOBJ_FILES) ; do \ + test -f $$i || touch $$i ; \ + done \ + fi + if test "x$(top_srcdir)" != "x$(top_builddir)"; \ + then \ + export BUILT_OPTIONS="--source-dir=$(DOC_BUILD_DIR)"; \ + fi; \ + gtkdoc-scan \ + $(SCAN_OPTIONS) $(EXTRA_HFILES) \ + --module=$(DOC_MODULE) \ + --source-dir=$(DOC_SOURCE_DIR) \ + $$BUILT_OPTIONS \ + --ignore-headers="$(IGNORE_HFILES)" + touch scan-build.stamp + +$(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(DOC_MODULE)-overrides.txt: scan-build.stamp + @true + +#### xml #### + +### FIXME: make this error out again when docs are complete +sgml-build.stamp: setup.stamp $(DOC_MODULE)-decl.txt $(SCANOBJ_FILES) $(DOC_MODULE)-sections.txt $(expand_content_files) + @echo '*** Building XML ***' + gtkdoc-mkdb --module=$(DOC_MODULE) --source-dir=$(DOC_SOURCE_DIR) --expand-content-files="$(expand_content_files)" --main-sgml-file=$(DOC_MAIN_SGML_FILE) --output-format=xml $(MKDB_OPTIONS) | tee sgml-build.log + @if grep "WARNING:" sgml-build.log > /dev/null; then true; fi # exit 1; fi + cp ../version.entities xml + rm sgml-build.log + touch sgml-build.stamp + +sgml.stamp: sgml-build.stamp + @true + +#### html #### + +html-build.stamp: sgml.stamp $(DOC_MAIN_SGML_FILE) $(content_files) + @echo '*** Building HTML ***' + @rm -rf html + @mkdir html + cp -pr xml html + cp ../version.entities ./ + @mkhtml_options=""; \ + gtkdoc-mkhtml 2>&1 --help | grep >/dev/null "\-\-path"; \ + if test "$(?)" = "0"; then \ + mkhtml_options=--path="$(abs_srcdir)"; \ + fi; \ + cd html && gtkdoc-mkhtml $$mkhtml_options $(MKHTML_OPTIONS) $(DOC_MODULE) ../$(DOC_MAIN_SGML_FILE) + mv html/index.sgml html/index.sgml.bak + $(SED) "s/ href=\"$(DOC_MODULE)\// href=\"$(DOC_MODULE)-@GST_MAJORMINOR@\//g" html/index.sgml.bak >html/index.sgml + rm -f html/index.sgml.bak + rm -rf html/xml + rm -f version.entities + test "x$(HTML_IMAGES)" = "x" || ( cd $(srcdir) && cp $(HTML_IMAGES) $(abs_builddir)/html ) + @echo '-- Fixing Crossreferences' + gtkdoc-fixxref --module=$(DOC_MODULE) --module-dir=html --html-dir=$(HTML_DIR) $(FIXXREF_OPTIONS) + touch html-build.stamp + +clean-local-gtkdoc: + rm -rf xml tmpl html +# clean files copied for nonsrcdir templates build + if test x"$(srcdir)" != x. ; then \ + rm -rf $(DOC_MODULE).types; \ + fi +else +all-local: +clean-local-gtkdoc: +endif + +clean-local: clean-local-gtkdoc + rm -f *~ *.bak + rm -rf .libs + +distclean-local: + rm -f $(REPORT_FILES) \ + $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + rm -rf tmpl/*.sgml.bak + rm -f $(DOC_MODULE).hierarchy + rm -f *.stamp || true + if test "$(abs_srcdir)" != "$(abs_builddir)" ; then \ + rm -f $(DOC_MODULE)-docs.sgml ; \ + rm -f $(DOC_MODULE).types ; \ + rm -f $(DOC_MODULE).interfaces ; \ + rm -f $(DOC_MODULE)-overrides.txt ; \ + rm -f $(DOC_MODULE).prerequisites ; \ + rm -f $(DOC_MODULE)-sections.txt ; \ + rm -rf tmpl/*.sgml ; \ + fi + rm -rf *.o + +maintainer-clean-local: clean + cd $(srcdir) && rm -rf html \ + xml $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt + +# thomas: make docs parallel installable; devhelp requires majorminor too +install-data-local: + (installfiles=`echo $(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css`; \ + if test "$$installfiles" = '$(builddir)/html/*.sgml $(builddir)/html/*.html $(builddir)/html/*.png $(builddir)/html/*.css'; \ + then echo '-- Nothing to install' ; \ + else \ + $(mkinstalldirs) $(DESTDIR)$(TARGET_DIR); \ + for i in $$installfiles; do \ + echo '-- Installing '$$i ; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(TARGET_DIR); \ + done; \ + echo '-- Installing $(builddir)/html/$(DOC_MODULE).devhelp' ; \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE).devhelp \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@.devhelp; \ + if test -e $(builddir)/html/$(DOC_MODULE).devhelp2; then \ + $(INSTALL_DATA) $(builddir)/html/$(DOC_MODULE).devhelp2 \ + $(DESTDIR)$(TARGET_DIR)/$(DOC_MODULE)-@GST_MAJORMINOR@.devhelp2; \ + fi; \ + (which gtkdoc-rebase >/dev/null && \ + gtkdoc-rebase --relative --dest-dir=$(DESTDIR) --html-dir=$(DESTDIR)$(TARGET_DIR)) || true ; \ + fi) +uninstall-local: + if test -d $(DESTDIR)$(TARGET_DIR); then \ + rm -rf $(DESTDIR)$(TARGET_DIR)/*; \ + rmdir -p $(DESTDIR)$(TARGET_DIR) 2>/dev/null || true; \ + else \ + echo '-- Nothing to uninstall' ; \ + fi; + + +# +# Require gtk-doc when making dist +# +if ENABLE_GTK_DOC +dist-check-gtkdoc: +else +dist-check-gtkdoc: + @echo "*** gtk-doc must be installed and enabled in order to make dist" + @false +endif + +dist-hook: dist-check-gtkdoc dist-hook-local + mkdir $(distdir)/html + cp html/* $(distdir)/html + -cp $(srcdir)/$(DOC_MODULE).types $(distdir)/ + -cp $(srcdir)/$(DOC_MODULE)-sections.txt $(distdir)/ + cd $(distdir) && rm -f $(DISTCLEANFILES) + -gtkdoc-rebase --online --relative --html-dir=$(distdir)/html + +.PHONY : dist-hook-local docs + +# avoid spurious build errors when distchecking with -jN +.NOTPARALLEL: diff --git a/gst-plugins-base-subtitles0.10/common/hooks/post-receive.hook b/gst-plugins-base-subtitles0.10/common/hooks/post-receive.hook new file mode 100755 index 0000000..cf1fe56 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/hooks/post-receive.hook @@ -0,0 +1,290 @@ +#!/usr/bin/perl -w +# +# Copyright 2005 Alexandre Julliard +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. + +use strict; +use open ':utf8'; +use Encode 'encode'; +use Cwd 'realpath'; + +binmode STDIN, ':utf8'; +binmode STDOUT, ':utf8'; + +sub git_config($); +sub get_repos_name(); + +# some parameters you may want to change + +# set this to something that takes "-s" +my $mailer = "/usr/bin/mail"; + +# debug mode +my $debug = 0; + +# configuration parameters + +# base URL of the gitweb repository browser +my $gitweb_url = "http://cgit.freedesktop.org/gstreamer"; + +# default repository name +my $repos_name = get_repos_name(); + +# max size of diffs in bytes +my $max_diff_size = 10000; + +# address for mail notices +my $commitlist_address = 'gstreamer-commits@lists.freedesktop.org'; +#my $commitlist_address = "bilboed"; + +# max number of individual notices before falling back to a single global notice +my $max_individual_notices = 100; + +# format an integer date + timezone as string +# algorithm taken from git's date.c +sub format_date($$) +{ + my ($time,$tz) = @_; + + if ($tz < 0) + { + my $minutes = (-$tz / 100) * 60 + (-$tz % 100); + $time -= $minutes * 60; + } + else + { + my $minutes = ($tz / 100) * 60 + ($tz % 100); + $time += $minutes * 60; + } + return gmtime($time) . sprintf " %+05d", $tz; +} + +# fetch a parameter from the git config file +sub git_config($) +{ + my ($param) = @_; + + open CONFIG, "-|" or exec "git", "config", $param; + my $ret = ; + chomp $ret if $ret; + close CONFIG or $ret = undef; + return $ret; +} + +# send an email notification +sub mail_notification($$$@) +{ + my ($name, $subject, $content_type, @text) = @_; + $subject = encode("MIME-Q",$subject); + if ($debug) + { + print "---------------------\n"; + print "To: $name\n"; + print "Subject: $subject\n"; + print "Content-Type: $content_type\n"; + print "\n", join("\n", @text), "\n"; + } + else + { + my $pid = open MAIL, "|-"; + return unless defined $pid; + if (!$pid) + { + exec $mailer, "-s", $subject, $name, or die "Cannot exec $mailer"; + } + print MAIL join("\n", @text), "\n"; + close MAIL; + } +} + +# get the default repository name +sub get_repos_name() +{ + my $dir = `git rev-parse --git-dir`; + chomp $dir; + my $repos = realpath($dir); + $repos =~ s/(.*?)((\.git\/)?\.git)$/$1/; + $repos =~ s/(.*)\/([^\/]+)\/?$/$2/; + return $repos; +} + +# extract the information from a commit or tag object and return a hash containing the various fields +sub get_object_info($) +{ + my $obj = shift; + my %info = (); + my @log = (); + my $do_log = 0; + + open TYPE, "-|" or exec "git", "cat-file", "-t", $obj or die "cannot run git-cat-file"; + my $type = ; + chomp $type; + close TYPE; + + open OBJ, "-|" or exec "git", "cat-file", $type, $obj or die "cannot run git-cat-file"; + while () + { + chomp; + if ($do_log) + { + last if /^-----BEGIN PGP SIGNATURE-----/; + push @log, $_; + } + elsif (/^(author|committer|tagger) ((.*)(<.*>)) (\d+) ([+-]\d+)$/) + { + $info{$1} = $2; + $info{$1 . "_name"} = $3; + $info{$1 . "_email"} = $4; + $info{$1 . "_date"} = $5; + $info{$1 . "_tz"} = $6; + } + elsif (/^tag (.*)$/) + { + $info{"tag"} = $1; + } + elsif (/^$/) { $do_log = 1; } + } + close OBJ; + + $info{"type"} = $type; + $info{"log"} = \@log; + return %info; +} + +# send a commit notice to a mailing list +sub send_commit_notice($$) +{ + my ($ref,$obj) = @_; + my %info = get_object_info($obj); + my @notice = (); + my $subject; + + printf "sending e-mail for $obj\n"; + + # TODO normal tags are not identified + if ($info{"type"} eq "tag") + { + push @notice, + "Module: $repos_name", + "Branch: $ref", + "Tag: $obj", + $gitweb_url ? "URL: $gitweb_url/tag/?id=$obj\n" : "", + "Tagger: " . $info{"tagger"}, + "Date: " . format_date($info{"tagger_date"},$info{"tagger_tz"}), + "", + join "\n", @{$info{"log"}}; + $subject = "Tag " . $info{"tag"} . ": " . ${$info{"log"}}[0]; + } + else + { + push @notice, + "Module: $repos_name", + "Branch: $ref", + "Commit: $obj", + $gitweb_url ? "URL: $gitweb_url/commit/?id=$obj\n" : "", + "Author: " . $info{"author"}, + "Date: " . format_date($info{"author_date"},$info{"author_tz"}), + "", + join "\n", @{$info{"log"}}, + "", + "---", + ""; + + open STAT, "-|" or exec "git", "diff-tree", "--stat", "-M", "--no-commit-id", $obj or die "cannot exec git-diff-tree"; + push @notice, join("", ); + close STAT; + + open DIFF, "-|" or exec "git", "diff-tree", "-p", "-M", "--no-commit-id", $obj or die "cannot exec git-diff-tree"; + my $diff = join( "", ); + close DIFF; + + if (($max_diff_size == -1) || (length($diff) < $max_diff_size)) + { + push @notice, $diff; + } + else + { + push @notice, "Diff: $gitweb_url/diff/?id=$obj" if $gitweb_url; + } + + if ($ref eq 'master') + { + $subject = $repos_name . ": " . ${$info{"log"}}[0]; + } + else + { + $subject = "[$ref] " . $repos_name . ": " . ${$info{"log"}}[0]; + } + } + + mail_notification($commitlist_address, $subject, "text/plain; charset=UTF-8", @notice); +} + +# send a global commit notice when there are too many commits for individual mails +sub send_global_notice($$$) +{ + my ($ref, $old_sha1, $new_sha1) = @_; + my @notice = (); + + open LIST, "-|" or exec "git", "rev-list", "--pretty", "^$old_sha1", "$new_sha1" or die "cannot exec git-rev-list"; + while () + { + chomp; + s/^commit /URL: $gitweb_url\/commit\/?id=/ if $gitweb_url; + push @notice, $_; + } + close LIST; + + mail_notification($commitlist_address, "New commits on branch $ref", "text/plain; charset=UTF-8", @notice); +} + +# send all the notices +sub send_all_notices($$$) +{ + my ($old_sha1, $new_sha1, $ref) = @_; + + $ref =~ s/^refs\/heads\///; + + if ($old_sha1 eq '0' x 40) # new ref + { + send_commit_notice( $ref, $new_sha1 ) if $commitlist_address; + return; + } + + my @commits = (); + + open LIST, "-|" or exec "git", "rev-list", "--topo-order", "^$old_sha1", "$new_sha1" or die "cannot exec git-rev-list"; + while () + { + chomp; + die "invalid commit $_" unless /^[0-9a-f]{40}$/; + unshift @commits, $_; + } + close LIST; + + if (@commits > $max_individual_notices) + { + send_global_notice( $ref, $old_sha1, $new_sha1 ) if $commitlist_address; + return; + } + + foreach my $commit (@commits) + { + send_commit_notice( $ref, $commit ) if $commitlist_address; + } +} + +# append repository path to URL +$gitweb_url .= "/$repos_name" if $gitweb_url; + +while (<>) +{ + chomp; + if (/^([0-9a-f]{40}) ([0-9a-f]{40}) (.*)$/) { send_all_notices( $1, $2, $3 ); } +} + +exit 0; diff --git a/gst-plugins-base-subtitles0.10/common/hooks/pre-commit.hook b/gst-plugins-base-subtitles0.10/common/hooks/pre-commit.hook new file mode 100755 index 0000000..aef1ce1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/hooks/pre-commit.hook @@ -0,0 +1,77 @@ +#!/bin/sh +# +# Check that the code follows a consistant code style +# + +# Check for existence of indent, and error out if not present. +# On some *bsd systems the binary seems to be called gnunindent, +# so check for that first. + +version=`gnuindent --version 2>/dev/null` +if test "x$version" = "x"; then + version=`indent --version 2>/dev/null` + if test "x$version" = "x"; then + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + exit 1 + fi + INDENT=indent +else + INDENT=gnuindent +fi + +case `$INDENT --version` in + GNU*) + ;; + default) + echo "GStreamer git pre-commit hook:" + echo "Did not find GNU indent, please install it before continuing." + echo "(Found $INDENT, but it doesn't seem to be GNU indent)" + exit 1 + ;; +esac + +INDENT_PARAMETERS="--braces-on-if-line \ + --case-brace-indentation0 \ + --case-indentation2 \ + --braces-after-struct-decl-line \ + --line-length80 \ + --no-tabs \ + --cuddle-else \ + --dont-line-up-parentheses \ + --continuation-indentation4 \ + --honour-newlines \ + --tab-size8 \ + --indent-level2 \ + --leave-preprocessor-space" + +echo "--Checking style--" +for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "\.c$"` ; do + # nf is the temporary checkout. This makes sure we check against the + # revision in the index (and not the checked out version). + nf=`git checkout-index --temp ${file} | cut -f 1` + newfile=`mktemp /tmp/${nf}.XXXXXX` || exit 1 + $INDENT ${INDENT_PARAMETERS} \ + $nf -o $newfile 2>> /dev/null + # FIXME: Call indent twice as it tends to do line-breaks + # different for every second call. + $INDENT ${INDENT_PARAMETERS} \ + $newfile 2>> /dev/null + diff -u -p "${nf}" "${newfile}" + r=$? + rm "${newfile}" + rm "${nf}" + if [ $r != 0 ] ; then +echo "=================================================================================================" +echo " Code style error in: $file " +echo " " +echo " Please fix before committing. Don't forget to run git add before trying to commit again. " +echo " If the whole file is to be committed, this should work (run from the top-level directory): " +echo " " +echo " gst-indent $file; git add $file; git commit" +echo " " +echo "=================================================================================================" + exit 1 + fi +done +echo "--Checking style pass--" diff --git a/gst-plugins-base-subtitles0.10/common/hooks/pre-receive.hook b/gst-plugins-base-subtitles0.10/common/hooks/pre-receive.hook new file mode 100644 index 0000000..7aa72e5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/hooks/pre-receive.hook @@ -0,0 +1,95 @@ +#!/usr/bin/env python +import sys +import os +import subprocess + +# This server-side pre-receive hook is to be put and activated in all modules +# that depend on the common submodule. +# +# It will check whether any modifications to the common 'submodule file' has a +# a valid commit SHA1 that exists in the common module. + +def commit_exists(sha1, gitdir): + """Returns True if the sha1 is a valid commit in the given + git directory""" + # FIXME: We're using 'git show' for the time being, but there's a small + # risk that there might be a valid SHA1 for a non-commit object. + env = os.environ.copy() + env["GIT_DIR"] = gitdir + sub = subprocess.Popen(["git", "show", sha1], env=env, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + while True: + res = sub.poll() + if res != None: + return res == 0 + +# location of the common git module +COMMON_GIT_DIR = "/git/gstreamer/common.git" + +pushvalid = True +error_badcommon = False +error_badcommit = False + +print "=> Checking for integrity of common submodule changes" +print + +for line in sys.stdin.readlines(): + # ref is the ref to be modified + # old is the old commit it was pointing to + # new is the new commit it was pointing to + old, new, ref = line.split(' ', 2) + + # 1. Get the latest change to common (if there was any changes) + sub = subprocess.Popen(["git", "diff", "%s..%s" % (old, new, ), "--", "common"], + stdout=subprocess.PIPE) + stdout, stderr = sub.communicate() + if stdout != "": + # Format of submodule special files + # Subproject commit + + # we get a diff, therefore only grab the last line + lastline = stdout.strip().rsplit('\n',1)[-1] + if not lastline.startswith("+Subproject commit"): + # this is bad, it means the diff has changed to something completely + # different + continue + subsha1 = lastline.rsplit(' ', 1)[-1] + print " Pack wants common to point to", subsha1 + if not commit_exists(subsha1, COMMON_GIT_DIR): + print " /!\\ Commit does not exist in common git module /!\\" + print " /!\\ for ref", ref + pushvalid = False + break + + # 2. Figure out if that commit exists in the common submodule + # (use GIT_DIR to execute commands in that directory) + + # Get the commit message + sub = subprocess.Popen(["git", "log", "--format=%s", + "%s..%s" % (old, new, )], stdout=subprocess.PIPE) + stdout, stderr = sub.communicate() + if stdout != "": + for line in stdout.strip().rsplit('\n',1): + if line.startswith("!"): + error_badcommit = True + pushvalid = False + break + +if pushvalid: + print " Incoming packet valid, proceeding to actual commit" + sys.exit(0) +else: + if error_badcommit: + print " Attempting to push commits with commit messages that start" + print " with '!'. Commit messages starting with '!' are reserved" + print " for private branches to prevent the commits from accidentally" + print " getting to the main repository." + if error_badcommon: + print " Attempting to push commits containing modifications to common" + print " that have not been commited to the actuall common module." + print + print " First push your changes to common/ before pushing the changes" + print " to the module using it." + sys.exit(-1) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/.gitignore b/gst-plugins-base-subtitles0.10/common/m4/.gitignore new file mode 100644 index 0000000..b36621e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/.gitignore @@ -0,0 +1,23 @@ +codeset.m4 +gettext.m4 +glibc21.m4 +iconv.m4 +intdiv0.m4 +inttypes-pri.m4 +inttypes.m4 +inttypes_h.m4 +isc-posix.m4 +lcmessage.m4 +lib-ld.m4 +lib-link.m4 +lib-prefix.m4 +progtest.m4 +stdint_h.m4 +uintmax_t.m4 +ulonglong.m4 + +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 + diff --git a/gst-plugins-base-subtitles0.10/common/m4/Makefile.am b/gst-plugins-base-subtitles0.10/common/m4/Makefile.am new file mode 100644 index 0000000..2ddb8a7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/Makefile.am @@ -0,0 +1,42 @@ +EXTRA_DIST = \ + README \ + as-ac-expand.m4 \ + as-auto-alt.m4 \ + as-compiler-flag.m4 \ + as-compiler.m4 \ + as-docbook.m4 \ + as-gcc-inline-assembly.m4 \ + as-libtool.m4 \ + as-libtool-tags.m4 \ + as-objc.m4 \ + as-python.m4 \ + as-scrub-include.m4 \ + as-version.m4 \ + ax_create_stdint_h.m4 \ + glib-gettext.m4 \ + gst-arch.m4 \ + gst-args.m4 \ + gst-check.m4 \ + gst-debuginfo.m4 \ + gst-default.m4 \ + gst-doc.m4 \ + gst-dowhile.m4 \ + gst-error.m4 \ + gst-feature.m4 \ + gst-function.m4 \ + gst-gettext.m4 \ + gst-glib2.m4 \ + gst-libxml2.m4 \ + gst-parser.m4 \ + gst-package-release-datetime.m4 \ + gst-platform.m4 \ + gst-plugindir.m4 \ + gst-plugin-docs.m4 \ + gst-valgrind.m4 \ + gst-x11.m4 \ + gst.m4 \ + gtk-doc.m4 \ + introspection.m4 \ + pkg.m4 \ + check.m4 \ + orc.m4 diff --git a/gst-plugins-base-subtitles0.10/common/m4/README b/gst-plugins-base-subtitles0.10/common/m4/README new file mode 100644 index 0000000..867a344 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/README @@ -0,0 +1,3 @@ +All aclocal .m4 files we need are put here and cat'd to acinclude.m4 in +the source root. Official ones (taken from the relevant devel packages) +are named as-is, unofficial ones (or changed ones) get a gst-prefix. diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-ac-expand.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-ac-expand.m4 new file mode 100644 index 0000000..d6c9e33 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-ac-expand.m4 @@ -0,0 +1,43 @@ +dnl as-ac-expand.m4 0.2.0 +dnl autostars m4 macro for expanding directories using configure's prefix +dnl thomas@apestaart.org + +dnl AS_AC_EXPAND(VAR, CONFIGURE_VAR) +dnl example +dnl AS_AC_EXPAND(SYSCONFDIR, $sysconfdir) +dnl will set SYSCONFDIR to /usr/local/etc if prefix=/usr/local + +AC_DEFUN([AS_AC_EXPAND], +[ + EXP_VAR=[$1] + FROM_VAR=[$2] + + dnl first expand prefix and exec_prefix if necessary + prefix_save=$prefix + exec_prefix_save=$exec_prefix + + dnl if no prefix given, then use /usr/local, the default prefix + if test "x$prefix" = "xNONE"; then + prefix="$ac_default_prefix" + fi + dnl if no exec_prefix given, then use prefix + if test "x$exec_prefix" = "xNONE"; then + exec_prefix=$prefix + fi + + full_var="$FROM_VAR" + dnl loop until it doesn't change anymore + while true; do + new_full_var="`eval echo $full_var`" + if test "x$new_full_var" = "x$full_var"; then break; fi + full_var=$new_full_var + done + + dnl clean up + full_var=$new_full_var + AC_SUBST([$1], "$full_var") + + dnl restore prefix and exec_prefix + prefix=$prefix_save + exec_prefix=$exec_prefix_save +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-auto-alt.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-auto-alt.m4 new file mode 100644 index 0000000..3f7920d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-auto-alt.m4 @@ -0,0 +1,50 @@ +dnl as-auto-alt.m4 0.0.2 +dnl autostars m4 macro for supplying alternate autotools versions to configure +dnl thomas@apestaart.org +dnl +dnl AS_AUTOTOOLS_ALTERNATE() +dnl +dnl supplies --with arguments for autoconf, autoheader, automake, aclocal + +AC_DEFUN([AS_AUTOTOOLS_ALTERNATE], +[ + dnl allow for different autoconf version + AC_ARG_WITH(autoconf, + AC_HELP_STRING([--with-autoconf], + [use a different autoconf for regeneration of Makefiles]), + [ + unset AUTOCONF + AM_MISSING_PROG(AUTOCONF, ${withval}) + AC_MSG_NOTICE([Using $AUTOCONF as autoconf]) + ]) + + dnl allow for different autoheader version + AC_ARG_WITH(autoheader, + AC_HELP_STRING([--with-autoheader], + [use a different autoheader for regeneration of Makefiles]), + [ + unset AUTOHEADER + AM_MISSING_PROG(AUTOHEADER, ${withval}) + AC_MSG_NOTICE([Using $AUTOHEADER as autoheader]) + ]) + + dnl allow for different automake version + AC_ARG_WITH(automake, + AC_HELP_STRING([--with-automake], + [use a different automake for regeneration of Makefiles]), + [ + unset AUTOMAKE + AM_MISSING_PROG(AUTOMAKE, ${withval}) + AC_MSG_NOTICE([Using $AUTOMAKE as automake]) + ]) + + dnl allow for different aclocal version + AC_ARG_WITH(aclocal, + AC_HELP_STRING([--with-aclocal], + [use a different aclocal for regeneration of Makefiles]), + [ + unset ACLOCAL + AM_MISSING_PROG(ACLOCAL, ${withval}) + AC_MSG_NOTICE([Using $ACLOCAL as aclocal]) + ]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-compiler-flag.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-compiler-flag.m4 new file mode 100644 index 0000000..882a4c7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-compiler-flag.m4 @@ -0,0 +1,64 @@ +dnl as-compiler-flag.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flags + +dnl David Schleef +dnl Tim-Philipp Müller + +dnl AS_COMPILER_FLAG(CFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_COMPILER_FLAG], +[ + AC_MSG_CHECKING([to see if compiler understands $1]) + + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $1" + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CFLAGS="$save_CFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + +dnl AS_CXX_COMPILER_FLAG(CPPFLAGS, ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CPPFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_CXX_COMPILER_FLAG], +[ + AC_REQUIRE([AC_PROG_CXX]) + + AC_MSG_CHECKING([to see if c++ compiler understands $1]) + + save_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $1" + + AC_LANG_PUSH(C++) + + AC_TRY_COMPILE([ ], [], [flag_ok=yes], [flag_ok=no]) + CPPFLAGS="$save_CPPFLAGS" + + if test "X$flag_ok" = Xyes ; then + $2 + true + else + $3 + true + fi + + AC_LANG_POP(C++) + + AC_MSG_RESULT([$flag_ok]) +]) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-compiler.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-compiler.m4 new file mode 100644 index 0000000..309a060 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-compiler.m4 @@ -0,0 +1,44 @@ +dnl as-compiler.m4 0.1.0 + +dnl autostars m4 macro for detection of compiler flavor + +dnl Thomas Vander Stichele + +dnl $Id: as-compiler.m4,v 1.4 2004/06/01 09:44:19 thomasvs Exp $ + +dnl AS_COMPILER(COMPILER) +dnl will set variable COMPILER to +dnl - gcc +dnl - forte +dnl - (empty) if no guess could be made + +AC_DEFUN([AS_COMPILER], +[ + as_compiler= + AC_MSG_CHECKING(for compiler flavour) + + dnl is it gcc ? + if test "x$GCC" = "xyes"; then + as_compiler="gcc" + fi + + dnl is it forte ? + AC_TRY_RUN([ +int main +(int argc, char *argv[]) +{ +#ifdef __sun + return 0; +#else + return 1; +#endif +} + ], as_compiler="forte", ,) + + if test "x$as_compiler" = "x"; then + AC_MSG_RESULT([unknown !]) + else + AC_MSG_RESULT($as_compiler) + fi + [$1]=$as_compiler +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-docbook.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-docbook.m4 new file mode 100644 index 0000000..8a1b32a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-docbook.m4 @@ -0,0 +1,66 @@ +dnl AS_DOCBOOK([, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl checks if xsltproc can build docbook documentation +dnl (which is possible if the catalog is set up properly +dnl I also tried checking for a specific version and type of docbook +dnl but xsltproc seemed to happily run anyway, so we can't check for that +dnl and version +dnl this macro takes inspiration from +dnl http://www.movement.uklinux.net/docs/docbook-autotools/configure.html +AC_DEFUN([AS_DOCBOOK], +[ + XSLTPROC_FLAGS=--nonet + DOCBOOK_ROOT= + TYPE_LC=xml + TYPE_UC=XML + DOCBOOK_VERSION=4.1.2 + + if test ! -f /etc/xml/catalog; then + for i in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh /usr/share/sgml/docbook/xsl-stylesheets/ /usr/local/share/xsl/docbook ; + do + if test -d "$i"; then + DOCBOOK_ROOT=$i + fi + done + else + XML_CATALOG=/etc/xml/catalog + CAT_ENTRY_START='' + fi + + dnl We need xsltproc to process the test + AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,) + XSLTPROC_WORKS=no + if test -n "$XSLTPROC"; then + AC_MSG_CHECKING([whether xsltproc docbook processing works]) + + if test -n "$XML_CATALOG"; then + DB_FILE="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl" + else + DB_FILE="$DOCBOOK_ROOT/xhtml/docbook.xsl" + fi + $XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END + + + + +END + if test "$?" = 0; then + XSLTPROC_WORKS=yes + fi + AC_MSG_RESULT($XSLTPROC_WORKS) + fi + + if test "x$XSLTPROC_WORKS" = "xyes"; then + dnl execute ACTION-IF-FOUND + ifelse([$1], , :, [$1]) + else + dnl execute ACTION-IF-NOT-FOUND + ifelse([$2], , :, [$2]) + fi + + AC_SUBST(XML_CATALOG) + AC_SUBST(XSLTPROC_FLAGS) + AC_SUBST(DOCBOOK_ROOT) + AC_SUBST(CAT_ENTRY_START) + AC_SUBST(CAT_ENTRY_END) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-gcc-inline-assembly.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-gcc-inline-assembly.m4 new file mode 100644 index 0000000..af32104 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-gcc-inline-assembly.m4 @@ -0,0 +1,52 @@ +dnl as-gcc-inline-assembly.m4 0.1.0 + +dnl autostars m4 macro for detection of gcc inline assembly + +dnl David Schleef + +dnl $Id$ + +dnl AS_COMPILER_FLAG(ACTION-IF-ACCEPTED, [ACTION-IF-NOT-ACCEPTED]) +dnl Tries to compile with the given CFLAGS. +dnl Runs ACTION-IF-ACCEPTED if the compiler can compile with the flags, +dnl and ACTION-IF-NOT-ACCEPTED otherwise. + +AC_DEFUN([AS_GCC_INLINE_ASSEMBLY], +[ + AC_MSG_CHECKING([if compiler supports gcc-style inline assembly]) + + AC_TRY_COMPILE([], [ +#ifdef __GNUC_MINOR__ +#if (__GNUC__ * 1000 + __GNUC_MINOR__) < 3004 +#error GCC before 3.4 has critical bugs compiling inline assembly +#endif +#endif +__asm__ (""::) ], [flag_ok=yes], [flag_ok=no]) + + if test "X$flag_ok" = Xyes ; then + $1 + true + else + $2 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + + +AC_DEFUN([AS_GCC_ASM_POWERPC_FPU], +[ + AC_MSG_CHECKING([if compiler supports FPU instructions on PowerPC]) + + AC_TRY_COMPILE([], [__asm__ ("fadd 0,0,0"::) ], [flag_ok=yes], [flag_ok=no]) + + if test "X$flag_ok" = Xyes ; then + $1 + true + else + $2 + true + fi + AC_MSG_RESULT([$flag_ok]) +]) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-libtool-tags.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-libtool-tags.m4 new file mode 100644 index 0000000..06f0ae4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-libtool-tags.m4 @@ -0,0 +1,83 @@ +dnl as-libtool-tags.m4 0.1.4 + +dnl autostars m4 macro for selecting libtool "tags" (languages) + +dnl Andy Wingo does not claim credit for this macro +dnl backported from libtool 1.6 by Paolo Bonzini +dnl see http://lists.gnu.org/archive/html/libtool/2003-12/msg00007.html + +dnl $Id$ + +dnl AS_LIBTOOL_TAGS([tags...]) + +dnl example +dnl AS_LIBTOOL_TAGS([]) for only C (no fortran, etc) + +dnl When AC_LIBTOOL_TAGS is used, I redefine _LT_AC_TAGCONFIG +dnl to be more similar to the libtool 1.6 implementation, which +dnl uses an m4 loop and m4 case instead of a shell loop. This +dnl way the CXX/GCJ/F77/RC tests are not always expanded. + +dnl AS_LIBTOOL_TAGS +dnl --------------- +dnl tags to enable +AC_DEFUN([AS_LIBTOOL_TAGS], +[m4_define([_LT_TAGS],[$1]) +m4_define([_LT_AC_TAGCONFIG], [ + # redefined LT AC TAGCONFIG + if test -f "$ltmain"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + AC_FOREACH([_LT_TAG], _LT_TAGS, + echo THOMAS: tag _LT_TAG + [m4_case(_LT_TAG, + [CXX], [ + if test -n "$CXX" && test "X$CXX" != "Xno"; then + echo "THOMAS: YAY CXX" + AC_LIBTOOL_LANG_CXX_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [F77], [ + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [GCJ], [ + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [RC], [ + if test -n "$RC" && test "X$RC" != "Xno"; then + AC_LIBTOOL_LANG_RC_CONFIG + available_tags="$available_tags _LT_TAG" + fi], + [m4_errprintn(m4_location[: error: invalid tag name: ]"_LT_TAG") + m4_exit(1)]) + ]) + echo THOMAS: available tags: $available_tags + fi + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + AC_MSG_NOTICE([updated available libtool tags with $available_tags.]) + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + + fi + +])dnl _LT_AC_TAG_CONFIG +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-libtool.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-libtool.m4 new file mode 100644 index 0000000..25de9d1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-libtool.m4 @@ -0,0 +1,45 @@ +dnl as-libtool.m4 0.1.4 + +dnl autostars m4 macro for libtool versioning + +dnl Thomas Vander Stichele + +dnl $Id: as-libtool.m4,v 1.10 2005/10/15 13:44:23 thomasvs Exp $ + +dnl AS_LIBTOOL(PREFIX, CURRENT, REVISION, AGE, [RELEASE]) + +dnl example +dnl AS_LIBTOOL(GST, 2, 0, 0) + +dnl this macro +dnl - defines [$PREFIX]_CURRENT, REVISION and AGE +dnl - defines [$PREFIX]_LIBVERSION +dnl - defines [$PREFIX]_LT_LDFLAGS to set versioning +dnl - AC_SUBST's them all + +dnl if RELEASE is given, then add a -release option to the LDFLAGS +dnl with the given release version +dnl then use [$PREFIX]_LT_LDFLAGS in the relevant Makefile.am's + +dnl call AM_PROG_LIBTOOL after this call + +AC_DEFUN([AS_LIBTOOL], +[ + [$1]_CURRENT=[$2] + [$1]_REVISION=[$3] + [$1]_AGE=[$4] + [$1]_LIBVERSION=[$2]:[$3]:[$4] + AC_SUBST([$1]_CURRENT) + AC_SUBST([$1]_REVISION) + AC_SUBST([$1]_AGE) + AC_SUBST([$1]_LIBVERSION) + + [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -version-info $[$1]_LIBVERSION" + if test ! -z "[$5]" + then + [$1]_LT_LDFLAGS="$[$1]_LT_LDFLAGS -release [$5]" + fi + AC_SUBST([$1]_LT_LDFLAGS) + + AC_LIBTOOL_DLOPEN +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-objc.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-objc.m4 new file mode 100644 index 0000000..1e7066a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-objc.m4 @@ -0,0 +1,56 @@ + + +# AC_PROG_OBJC([LIST-OF-COMPILERS]) +# +AC_DEFUN([AS_PROG_OBJC], +[ +AC_CHECK_TOOLS(OBJC, + [m4_default([$1], [objcc objc gcc cc CC])], + none) +AC_SUBST(OBJC) +OBJC_LDFLAGS="-lobjc" +AC_SUBST(OBJC_LDFLAGS) +if test "x$OBJC" != xnone ; then + _AM_DEPENDENCIES(OBJC) + AC_MSG_CHECKING([if Objective C compiler works]) + cat >>conftest.m < +@interface Moo:Object +{ +} +- moo; +int main(); +@end + +@implementation Moo +- moo +{ + exit(0); +} + +int main() +{ + id moo; + moo = [[Moo new]]; + [[moo moo]]; + return 1; +} +@end +EOF + ${OBJC} conftest.m ${OBJC_LDFLAGS} >&5 2>&5 + if test -f a.out -o -f a.exe ; then + result=yes + else + result=no + echo failed program is: >&5 + cat conftest.m >&5 + fi + rm -f conftest.m a.out a.exe + AC_MSG_RESULT([$result]) +else + _AM_DEPENDENCIES(OBJC) +fi + +]) + + diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-python.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-python.m4 new file mode 100644 index 0000000..eb9b175 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-python.m4 @@ -0,0 +1,152 @@ +## ------------------------ +## Python file handling +## From Andrew Dalke +## Updated by James Henstridge +## Updated by Andy Wingo to loop through possible pythons +## ------------------------ + +# AS_PATH_PYTHON([MINIMUM-VERSION]) + +# Adds support for distributing Python modules and packages. To +# install modules, copy them to $(pythondir), using the python_PYTHON +# automake variable. To install a package with the same name as the +# automake package, install to $(pkgpythondir), or use the +# pkgpython_PYTHON automake variable. + +# The variables $(pyexecdir) and $(pkgpyexecdir) are provided as +# locations to install python extension modules (shared libraries). +# Another macro is required to find the appropriate flags to compile +# extension modules. + +# If your package is configured with a different prefix to python, +# users will have to add the install directory to the PYTHONPATH +# environment variable, or create a .pth file (see the python +# documentation for details). + +# If the MINIMUM-VERSION argument is passed, AS_PATH_PYTHON will +# cause an error if the version of python installed on the system +# doesn't meet the requirement. MINIMUM-VERSION should consist of +# numbers and dots only. + +# Updated to loop over all possible python binaries by Andy Wingo +# +# Updated to only warn and unset PYTHON if no good one is found + +AC_DEFUN([AS_PATH_PYTHON], + [ + dnl Find a version of Python. I could check for python versions 1.4 + dnl or earlier, but the default installation locations changed from + dnl $prefix/lib/site-python in 1.4 to $prefix/lib/python1.5/site-packages + dnl in 1.5, and I don't want to maintain that logic. + + dnl should we do the version check? + PYTHON_CANDIDATES="python python2.2 python2.1 python2.0 python2 \ + python1.6 python1.5" + ifelse([$1],[], + [AC_PATH_PROG(PYTHON, $PYTHON_CANDIDATES)], + [ + AC_MSG_NOTICE(Looking for Python version >= $1) + changequote(<<, >>)dnl + prog=" +import sys, string +minver = '$1' +# split string by '.' and convert to numeric +minver_info = map(string.atoi, string.split(minver, '.')) +# we can now do comparisons on the two lists: +if sys.version_info >= tuple(minver_info): + sys.exit(0) +else: + sys.exit(1)" + changequote([, ])dnl + + python_good=false + for python_candidate in $PYTHON_CANDIDATES; do + unset PYTHON + AC_PATH_PROG(PYTHON, $python_candidate) 1> /dev/null 2> /dev/null + + if test "x$PYTHON" = "x"; then continue; fi + + if $PYTHON -c "$prog" 1>&AC_FD_CC 2>&AC_FD_CC; then + AC_MSG_CHECKING(["$PYTHON":]) + AC_MSG_RESULT([okay]) + python_good=true + break; + else + dnl clear the cache val + unset ac_cv_path_PYTHON + fi + done + ]) + + if test "$python_good" != "true"; then + AC_MSG_WARN([No suitable version of python found]) + PYTHON= + else + + AC_MSG_CHECKING([local Python configuration]) + + dnl Query Python for its version number. Getting [:3] seems to be + dnl the best way to do this; it's what "site.py" does in the standard + dnl library. Need to change quote character because of [:3] + + AC_SUBST(PYTHON_VERSION) + changequote(<<, >>)dnl + PYTHON_VERSION=`$PYTHON -c "import sys; print sys.version[:3]"` + changequote([, ])dnl + + + dnl Use the values of $prefix and $exec_prefix for the corresponding + dnl values of PYTHON_PREFIX and PYTHON_EXEC_PREFIX. These are made + dnl distinct variables so they can be overridden if need be. However, + dnl general consensus is that you shouldn't need this ability. + + AC_SUBST(PYTHON_PREFIX) + PYTHON_PREFIX='${prefix}' + + AC_SUBST(PYTHON_EXEC_PREFIX) + PYTHON_EXEC_PREFIX='${exec_prefix}' + + dnl At times (like when building shared libraries) you may want + dnl to know which OS platform Python thinks this is. + + AC_SUBST(PYTHON_PLATFORM) + PYTHON_PLATFORM=`$PYTHON -c "import sys; print sys.platform"` + + + dnl Set up 4 directories: + + dnl pythondir -- where to install python scripts. This is the + dnl site-packages directory, not the python standard library + dnl directory like in previous automake betas. This behaviour + dnl is more consistent with lispdir.m4 for example. + dnl + dnl Also, if the package prefix isn't the same as python's prefix, + dnl then the old $(pythondir) was pretty useless. + + AC_SUBST(pythondir) + pythondir=$PYTHON_PREFIX"/lib/python"$PYTHON_VERSION/site-packages + + dnl pkgpythondir -- $PACKAGE directory under pythondir. Was + dnl PYTHON_SITE_PACKAGE in previous betas, but this naming is + dnl more consistent with the rest of automake. + dnl Maybe this should be put in python.am? + + AC_SUBST(pkgpythondir) + pkgpythondir=\${pythondir}/$PACKAGE + + dnl pyexecdir -- directory for installing python extension modules + dnl (shared libraries) Was PYTHON_SITE_EXEC in previous betas. + + AC_SUBST(pyexecdir) + pyexecdir=$PYTHON_EXEC_PREFIX"/lib/python"$PYTHON_VERSION/site-packages + + dnl pkgpyexecdir -- $(pyexecdir)/$(PACKAGE) + dnl Maybe this should be put in python.am? + + AC_SUBST(pkgpyexecdir) + pkgpyexecdir=\${pyexecdir}/$PACKAGE + + AC_MSG_RESULT([looks good]) + + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-scrub-include.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-scrub-include.m4 new file mode 100644 index 0000000..3ed49b0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-scrub-include.m4 @@ -0,0 +1,36 @@ +dnl as-scrub-include.m4 0.0.4 + +dnl autostars m4 macro for scrubbing CFLAGS of system include dirs +dnl because gcc 3.x complains about including system including dirs + +dnl Thomas Vander Stichele + +dnl $Id: as-scrub-include.m4,v 1.7 2004/06/12 08:30:20 thomasvs Exp $ + +dnl This macro uses output of cpp -v and expects it to contain text that +dnl looks a little bit like this: +dnl #include <...> search starts here: +dnl /usr/local/include +dnl /usr/lib/gcc-lib/i386-redhat-linux/3.2/include +dnl /usr/include +dnl End of search list. + +dnl AS_SCRUB_INCLUDE(VAR) +dnl example +dnl AS_SCRUB_INCLUDE(CFLAGS) +dnl will remove all system include dirs from the given CFLAGS + +AC_DEFUN([AS_SCRUB_INCLUDE], +[ + GIVEN_CFLAGS=$[$1] + INCLUDE_DIRS=`echo | cpp -v 2>&1` + + dnl remove everything from this output between the "starts here" and "End of" + dnl line + INCLUDE_DIRS=`echo $INCLUDE_DIRS | sed -e 's/.*<...> search starts here://' | sed -e 's/End of search list.*//'` + for dir in $INCLUDE_DIRS; do + dnl use "" as the sed script so $dir gets expanded + GIVEN_CFLAGS=`echo $GIVEN_CFLAGS | sed -e "s#-I$dir ##"` + done + [$1]=$GIVEN_CFLAGS +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/as-version.m4 b/gst-plugins-base-subtitles0.10/common/m4/as-version.m4 new file mode 100644 index 0000000..22ff774 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/as-version.m4 @@ -0,0 +1,75 @@ +dnl as-version.m4 0.2.0 + +dnl autostars m4 macro for versioning + +dnl Thomas Vander Stichele + +dnl $Id: as-version.m4,v 1.15 2006/04/01 09:40:24 thomasvs Exp $ + +dnl AS_VERSION + +dnl example +dnl AS_VERSION + +dnl this macro +dnl - AC_SUBST's PACKAGE_VERSION_MAJOR, _MINOR, _MICRO +dnl - AC_SUBST's PACKAGE_VERSION_RELEASE, +dnl which can be used for rpm release fields +dnl - doesn't call AM_INIT_AUTOMAKE anymore because it prevents +dnl maintainer mode from running correctly +dnl +dnl don't forget to put #undef PACKAGE_VERSION_RELEASE in acconfig.h +dnl if you use acconfig.h + +AC_DEFUN([AS_VERSION], +[ + PACKAGE_VERSION_MAJOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f1) + PACKAGE_VERSION_MINOR=$(echo AC_PACKAGE_VERSION | cut -d'.' -f2) + PACKAGE_VERSION_MICRO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f3) + + AC_SUBST(PACKAGE_VERSION_MAJOR) + AC_SUBST(PACKAGE_VERSION_MINOR) + AC_SUBST(PACKAGE_VERSION_MICRO) +]) + +dnl AS_NANO(ACTION-IF-NANO-NON-NULL, [ACTION-IF-NANO-NULL]) + +dnl requires AC_INIT to be called before +dnl For projects using a fourth or nano number in your versioning to indicate +dnl development or prerelease snapshots, this macro allows the build to be +dnl set up differently accordingly. + +dnl this macro: +dnl - parses AC_PACKAGE_VERSION, set by AC_INIT, and extracts the nano number +dnl - sets the variable PACKAGE_VERSION_NANO +dnl - sets the variable PACKAGE_VERSION_RELEASE, which can be used +dnl for rpm release fields +dnl - executes ACTION-IF-NANO-NON-NULL or ACTION-IF-NANO-NULL + +dnl example: +dnl AS_NANO(RELEASE="yes", RELEASE="no") + +AC_DEFUN([AS_NANO], +[ + AC_MSG_CHECKING(nano version) + + NANO=$(echo AC_PACKAGE_VERSION | cut -d'.' -f4) + + if test x"$NANO" = x || test "x$NANO" = "x0" ; then + AC_MSG_RESULT([0 (release)]) + NANO=0 + PACKAGE_VERSION_RELEASE=1 + ifelse([$1], , :, [$1]) + else + AC_MSG_RESULT($NANO) + PACKAGE_VERSION_RELEASE=0.`date +%Y%m%d.%H%M%S` + if test "x$NANO" != "x1" ; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi + fi + PACKAGE_VERSION_NANO=$NANO + AC_SUBST(PACKAGE_VERSION_NANO) + AC_SUBST(PACKAGE_VERSION_RELEASE) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/ax_create_stdint_h.m4 b/gst-plugins-base-subtitles0.10/common/m4/ax_create_stdint_h.m4 new file mode 100644 index 0000000..13bf699 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/ax_create_stdint_h.m4 @@ -0,0 +1,734 @@ +##### http://autoconf-archive.cryp.to/ax_create_stdint_h.html +# +# SYNOPSIS +# +# AX_CREATE_STDINT_H [( HEADER-TO-GENERATE [, HEDERS-TO-CHECK])] +# +# DESCRIPTION +# +# the "ISO C9X: 7.18 Integer types " section requires the +# existence of an include file that defines a set of +# typedefs, especially uint8_t,int32_t,uintptr_t. Many older +# installations will not provide this file, but some will have the +# very same definitions in . In other enviroments we can +# use the inet-types in which would define the typedefs +# int8_t and u_int8_t respectivly. +# +# This macros will create a local "_stdint.h" or the headerfile given +# as an argument. In many cases that file will just "#include +# " or "#include ", while in other environments +# it will provide the set of basic 'stdint's definitions/typedefs: +# +# int8_t,uint8_t,int16_t,uint16_t,int32_t,uint32_t,intptr_t,uintptr_t +# int_least32_t.. int_fast32_t.. intmax_t +# +# which may or may not rely on the definitions of other files, or +# using the AC_CHECK_SIZEOF macro to determine the actual sizeof each +# type. +# +# if your header files require the stdint-types you will want to +# create an installable file mylib-int.h that all your other +# installable header may include. So if you have a library package +# named "mylib", just use +# +# AX_CREATE_STDINT_H(mylib-int.h) +# +# in configure.ac and go to install that very header file in +# Makefile.am along with the other headers (mylib.h) - and the +# mylib-specific headers can simply use "#include " to +# obtain the stdint-types. +# +# Remember, if the system already had a valid , the +# generated file will include it directly. No need for fuzzy +# HAVE_STDINT_H things... (oops, GCC 4.2.x has deliberatly disabled +# its stdint.h for non-c99 compilation and the c99-mode is not the +# default. Therefore this macro will not use the compiler's stdint.h +# - please complain to the GCC developers). +# +# LAST MODIFICATION +# +# 2007-06-27 +# +# COPYLEFT +# +# Copyright (c) 2007 Guido U. Draheim +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you +# make and distribute a modified version of the Autoconf Macro, you +# may extend this special exception to the GPL to apply to your +# modified version as well. + +AC_DEFUN([AX_CHECK_DATA_MODEL],[ + AC_CHECK_SIZEOF(char) + AC_CHECK_SIZEOF(short) + AC_CHECK_SIZEOF(int) + AC_CHECK_SIZEOF(long) + AC_CHECK_SIZEOF(void*) + ac_cv_char_data_model="" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_char" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_short" + ac_cv_char_data_model="$ac_cv_char_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_int" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_long" + ac_cv_long_data_model="$ac_cv_long_data_model$ac_cv_sizeof_voidp" + AC_MSG_CHECKING([data model]) + case "$ac_cv_char_data_model/$ac_cv_long_data_model" in + 122/242) ac_cv_data_model="IP16" ; n="standard 16bit machine" ;; + 122/244) ac_cv_data_model="LP32" ; n="standard 32bit machine" ;; + 122/*) ac_cv_data_model="i16" ; n="unusual int16 model" ;; + 124/444) ac_cv_data_model="ILP32" ; n="standard 32bit unixish" ;; + 124/488) ac_cv_data_model="LP64" ; n="standard 64bit unixish" ;; + 124/448) ac_cv_data_model="LLP64" ; n="unusual 64bit unixish" ;; + 124/*) ac_cv_data_model="i32" ; n="unusual int32 model" ;; + 128/888) ac_cv_data_model="ILP64" ; n="unusual 64bit numeric" ;; + 128/*) ac_cv_data_model="i64" ; n="unusual int64 model" ;; + 222/*2) ac_cv_data_model="DSP16" ; n="strict 16bit dsptype" ;; + 333/*3) ac_cv_data_model="DSP24" ; n="strict 24bit dsptype" ;; + 444/*4) ac_cv_data_model="DSP32" ; n="strict 32bit dsptype" ;; + 666/*6) ac_cv_data_model="DSP48" ; n="strict 48bit dsptype" ;; + 888/*8) ac_cv_data_model="DSP64" ; n="strict 64bit dsptype" ;; + 222/*|333/*|444/*|666/*|888/*) : + ac_cv_data_model="iDSP" ; n="unusual dsptype" ;; + *) ac_cv_data_model="none" ; n="very unusual model" ;; + esac + AC_MSG_RESULT([$ac_cv_data_model ($ac_cv_long_data_model, $n)]) +]) + +dnl AX_CHECK_HEADER_STDINT_X([HEADERLIST][,ACTION-IF]) +AC_DEFUN([AX_CHECK_HEADER_STDINT_X],[ +AC_CACHE_CHECK([for stdint uintptr_t], [ac_cv_header_stdint_x],[ + ac_cv_header_stdint_x="" # the 1997 typedefs (inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[stdint.h inttypes.h sys/inttypes.h sys/types.h]) + do + unset ac_cv_type_uintptr_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uintptr_t,[ac_cv_header_stdint_x=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + done + AC_MSG_CHECKING([for stdint uintptr_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_O],[ +AC_CACHE_CHECK([for stdint uint32_t], [ac_cv_header_stdint_o],[ + ac_cv_header_stdint_o="" # the 1995 typedefs (sys/inttypes.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[inttypes.h sys/inttypes.h sys/types.h stdint.h]) + do + unset ac_cv_type_uint32_t + unset ac_cv_type_uint64_t + AC_CHECK_TYPE(uint32_t,[ac_cv_header_stdint_o=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(uint64_t,[and64="/uint64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + break; + done + AC_MSG_CHECKING([for stdint uint32_t]) + ]) +]) + +AC_DEFUN([AX_CHECK_HEADER_STDINT_U],[ +AC_CACHE_CHECK([for stdint u_int32_t], [ac_cv_header_stdint_u],[ + ac_cv_header_stdint_u="" # the BSD typedefs (sys/types.h) + AC_MSG_RESULT([(..)]) + for i in m4_ifval([$1],[$1],[sys/types.h inttypes.h sys/inttypes.h]) ; do + unset ac_cv_type_u_int32_t + unset ac_cv_type_u_int64_t + AC_CHECK_TYPE(u_int32_t,[ac_cv_header_stdint_u=$i],continue,[#include <$i>]) + AC_CHECK_TYPE(u_int64_t,[and64="/u_int64_t"],[and64=""],[#include<$i>]) + m4_ifvaln([$2],[$2]) break + break; + done + AC_MSG_CHECKING([for stdint u_int32_t]) + ]) +]) + +AC_DEFUN([AX_CREATE_STDINT_H], +[# ------ AX CREATE STDINT H ------------------------------------- +AC_MSG_CHECKING([for stdint types]) +ac_stdint_h=`echo ifelse($1, , _stdint.h, $1)` +# try to shortcircuit - if the default include path of the compiler +# can find a "stdint.h" header then we assume that all compilers can. +AC_CACHE_VAL([ac_cv_header_stdint_t],[ +old_CXXFLAGS="$CXXFLAGS" ; CXXFLAGS="" +old_CPPFLAGS="$CPPFLAGS" ; CPPFLAGS="" +old_CFLAGS="$CFLAGS" ; CFLAGS="" +AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], +[ac_cv_stdint_result="(assuming C99 compatible system)" + ac_cv_header_stdint_t="stdint.h"; ], +[ac_cv_header_stdint_t=""]) +if test "$GCC" = "yes" && test ".$ac_cv_header_stdint_t" = "."; then +CFLAGS="-std=c99" +AC_TRY_COMPILE([#include ],[int_least32_t v = 0;], +[AC_MSG_WARN(your GCC compiler has a defunct stdint.h for its default-mode)]) +fi +CXXFLAGS="$old_CXXFLAGS" +CPPFLAGS="$old_CPPFLAGS" +CFLAGS="$old_CFLAGS" ]) + +v="... $ac_cv_header_stdint_h" +if test "$ac_stdint_h" = "stdint.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./stdint.h?)]) +elif test "$ac_stdint_h" = "inttypes.h" ; then + AC_MSG_RESULT([(are you sure you want them in ./inttypes.h?)]) +elif test "_$ac_cv_header_stdint_t" = "_" ; then + AC_MSG_RESULT([(putting them into $ac_stdint_h)$v]) +else + ac_cv_header_stdint="$ac_cv_header_stdint_t" + AC_MSG_RESULT([$ac_cv_header_stdint (shortcircuit)]) +fi + +if test "_$ac_cv_header_stdint_t" = "_" ; then # can not shortcircuit.. + +dnl .....intro message done, now do a few system checks..... +dnl btw, all old CHECK_TYPE macros do automatically "DEFINE" a type, +dnl therefore we use the autoconf implementation detail CHECK_TYPE_NEW +dnl instead that is triggered with 3 or more arguments (see types.m4) + +inttype_headers=`echo $2 | sed -e 's/,/ /g'` + +ac_cv_stdint_result="(no helpful system typedefs seen)" +AX_CHECK_HEADER_STDINT_X(dnl + stdint.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen uintptr_t$and64 in $i)") + +if test "_$ac_cv_header_stdint_x" = "_" ; then +AX_CHECK_HEADER_STDINT_O(dnl, + inttypes.h sys/inttypes.h stdint.h $inttype_headers, + ac_cv_stdint_result="(seen uint32_t$and64 in $i)") +fi + +if test "_$ac_cv_header_stdint_x" = "_" ; then +if test "_$ac_cv_header_stdint_o" = "_" ; then +AX_CHECK_HEADER_STDINT_U(dnl, + sys/types.h inttypes.h sys/inttypes.h $inttype_headers, + ac_cv_stdint_result="(seen u_int32_t$and64 in $i)") +fi fi + +dnl if there was no good C99 header file, do some typedef checks... +if test "_$ac_cv_header_stdint_x" = "_" ; then + AC_MSG_CHECKING([for stdint datatype model]) + AC_MSG_RESULT([(..)]) + AX_CHECK_DATA_MODEL +fi + +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_x" +elif test "_$ac_cv_header_stdint_o" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_o" +elif test "_$ac_cv_header_stdint_u" != "_" ; then + ac_cv_header_stdint="$ac_cv_header_stdint_u" +else + ac_cv_header_stdint="stddef.h" +fi + +AC_MSG_CHECKING([for extra inttypes in chosen header]) +AC_MSG_RESULT([($ac_cv_header_stdint)]) +dnl see if int_least and int_fast types are present in _this_ header. +unset ac_cv_type_int_least32_t +unset ac_cv_type_int_fast32_t +AC_CHECK_TYPE(int_least32_t,,,[#include <$ac_cv_header_stdint>]) +AC_CHECK_TYPE(int_fast32_t,,,[#include<$ac_cv_header_stdint>]) +AC_CHECK_TYPE(intmax_t,,,[#include <$ac_cv_header_stdint>]) + +fi # shortcircut to system "stdint.h" +# ------------------ PREPARE VARIABLES ------------------------------ +if test "$GCC" = "yes" ; then +ac_cv_stdint_message="using gnu compiler "`$CC --version | head -1` +else +ac_cv_stdint_message="using $CC" +fi + +AC_MSG_RESULT([make use of $ac_cv_header_stdint in $ac_stdint_h dnl +$ac_cv_stdint_result]) + +dnl ----------------------------------------------------------------- +# ----------------- DONE inttypes.h checks START header ------------- +AC_CONFIG_COMMANDS([$ac_stdint_h],[ +AC_MSG_NOTICE(creating $ac_stdint_h : $_ac_stdint_h) +ac_stdint=$tmp/_stdint.h + +echo "#ifndef" $_ac_stdint_h >$ac_stdint +echo "#define" $_ac_stdint_h "1" >>$ac_stdint +echo "#ifndef" _GENERATED_STDINT_H >>$ac_stdint +echo "#define" _GENERATED_STDINT_H '"'$PACKAGE $VERSION'"' >>$ac_stdint +echo "/* generated $ac_cv_stdint_message */" >>$ac_stdint +if test "_$ac_cv_header_stdint_t" != "_" ; then +echo "#define _STDINT_HAVE_STDINT_H" "1" >>$ac_stdint +echo "#include " >>$ac_stdint +echo "#endif" >>$ac_stdint +echo "#endif" >>$ac_stdint +else + +cat >>$ac_stdint < +#else +#include + +/* .................... configured part ............................ */ + +STDINT_EOF + +echo "/* whether we have a C99 compatible stdint header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_x" != "_" ; then + ac_header="$ac_cv_header_stdint_x" + echo "#define _STDINT_HEADER_INTPTR" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_INTPTR */" >>$ac_stdint +fi + +echo "/* whether we have a C96 compatible inttypes header file */" >>$ac_stdint +if test "_$ac_cv_header_stdint_o" != "_" ; then + ac_header="$ac_cv_header_stdint_o" + echo "#define _STDINT_HEADER_UINT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_UINT32 */" >>$ac_stdint +fi + +echo "/* whether we have a BSD compatible inet types header */" >>$ac_stdint +if test "_$ac_cv_header_stdint_u" != "_" ; then + ac_header="$ac_cv_header_stdint_u" + echo "#define _STDINT_HEADER_U_INT32" '"'"$ac_header"'"' >>$ac_stdint +else + echo "/* #undef _STDINT_HEADER_U_INT32 */" >>$ac_stdint +fi + +echo "" >>$ac_stdint + +if test "_$ac_header" != "_" ; then if test "$ac_header" != "stddef.h" ; then + echo "#include <$ac_header>" >>$ac_stdint + echo "" >>$ac_stdint +fi fi + +echo "/* which 64bit typedef has been found */" >>$ac_stdint +if test "$ac_cv_type_uint64_t" = "yes" ; then +echo "#define _STDINT_HAVE_UINT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_UINT64_T */" >>$ac_stdint +fi +if test "$ac_cv_type_u_int64_t" = "yes" ; then +echo "#define _STDINT_HAVE_U_INT64_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_U_INT64_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* which type model has been detected */" >>$ac_stdint +if test "_$ac_cv_char_data_model" != "_" ; then +echo "#define _STDINT_CHAR_MODEL" "$ac_cv_char_data_model" >>$ac_stdint +echo "#define _STDINT_LONG_MODEL" "$ac_cv_long_data_model" >>$ac_stdint +else +echo "/* #undef _STDINT_CHAR_MODEL // skipped */" >>$ac_stdint +echo "/* #undef _STDINT_LONG_MODEL // skipped */" >>$ac_stdint +fi +echo "" >>$ac_stdint + +echo "/* whether int_least types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_least32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_LEAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_LEAST32_T */" >>$ac_stdint +fi +echo "/* whether int_fast types were detected */" >>$ac_stdint +if test "$ac_cv_type_int_fast32_t" = "yes"; then +echo "#define _STDINT_HAVE_INT_FAST32_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INT_FAST32_T */" >>$ac_stdint +fi +echo "/* whether intmax_t type was detected */" >>$ac_stdint +if test "$ac_cv_type_intmax_t" = "yes"; then +echo "#define _STDINT_HAVE_INTMAX_T" "1" >>$ac_stdint +else +echo "/* #undef _STDINT_HAVE_INTMAX_T */" >>$ac_stdint +fi +echo "" >>$ac_stdint + + cat >>$ac_stdint <= 199901L +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#elif !defined __STRICT_ANSI__ +#if defined _MSC_VER || defined __WATCOMC__ || defined __BORLANDC__ +#define _HAVE_UINT64_T +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +#elif defined __GNUC__ || defined __MWERKS__ || defined __ELF__ +/* note: all ELF-systems seem to have loff-support which needs 64-bit */ +#if !defined _NO_LONGLONG +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef long long int64_t; +typedef unsigned long long uint64_t; +#endif + +#elif defined __alpha || (defined __mips && defined _ABIN32) +#if !defined _NO_LONGLONG +typedef long int64_t; +typedef unsigned long uint64_t; +#endif + /* compiler/cpu type to define int64_t */ +#endif +#endif +#endif + +#if defined _STDINT_HAVE_U_INT_TYPES +/* int8_t int16_t int32_t defined by inet code, redeclare the u_intXX types */ +typedef u_int8_t uint8_t; +typedef u_int16_t uint16_t; +typedef u_int32_t uint32_t; + +/* glibc compatibility */ +#ifndef __int8_t_defined +#define __int8_t_defined +#endif +#endif + +#ifdef _STDINT_NEED_INT_MODEL_T +/* we must guess all the basic types. Apart from byte-adressable system, */ +/* there a few 32-bit-only dsp-systems that we guard with BYTE_MODEL 8-} */ +/* (btw, those nibble-addressable systems are way off, or so we assume) */ + +dnl /* have a look at "64bit and data size neutrality" at */ +dnl /* http://unix.org/version2/whatsnew/login_64bit.html */ +dnl /* (the shorthand "ILP" types always have a "P" part) */ + +#if defined _STDINT_BYTE_MODEL +#if _STDINT_LONG_MODEL+0 == 242 +/* 2:4:2 = IP16 = a normal 16-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL == 444 +/* 2:4:4 = LP32 = a 32-bit system derived from a 16-bit */ +/* 4:4:4 = ILP32 = a normal 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 484 || _STDINT_LONG_MODEL+0 == 488 +/* 4:8:4 = IP32 = a 32-bit system prepared for 64-bit */ +/* 4:8:8 = LP64 = a normal 64-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* this system has a "long" of 64bit */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +typedef unsigned long uint64_t; +typedef long int64_t; +#endif +#elif _STDINT_LONG_MODEL+0 == 448 +/* LLP64 a 64-bit system derived from a 32-bit system */ +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; +#ifndef __int8_t_defined +#define __int8_t_defined +typedef char int8_t; +typedef short int16_t; +typedef int int32_t; +#endif +/* assuming the system has a "long long" */ +#ifndef _HAVE_UINT64_T +#define _HAVE_UINT64_T +#define _HAVE_LONGLONG_UINT64_T +typedef unsigned long long uint64_t; +typedef long long int64_t; +#endif +#else +#define _STDINT_NO_INT32_T +#endif +#else +#define _STDINT_NO_INT8_T +#define _STDINT_NO_INT32_T +#endif +#endif + +/* + * quote from SunOS-5.8 sys/inttypes.h: + * Use at your own risk. As of February 1996, the committee is squarely + * behind the fixed sized types; the "least" and "fast" types are still being + * discussed. The probability that the "fast" types may be removed before + * the standard is finalized is high enough that they are not currently + * implemented. + */ + +#if defined _STDINT_NEED_INT_LEAST_T +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_least64_t; +#endif + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_least64_t; +#endif + /* least types */ +#endif + +#if defined _STDINT_NEED_INT_FAST_T +typedef int8_t int_fast8_t; +typedef int int_fast16_t; +typedef int32_t int_fast32_t; +#ifdef _HAVE_UINT64_T +typedef int64_t int_fast64_t; +#endif + +typedef uint8_t uint_fast8_t; +typedef unsigned uint_fast16_t; +typedef uint32_t uint_fast32_t; +#ifdef _HAVE_UINT64_T +typedef uint64_t uint_fast64_t; +#endif + /* fast types */ +#endif + +#ifdef _STDINT_NEED_INTMAX_T +#ifdef _HAVE_UINT64_T +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; +#else +typedef long intmax_t; +typedef unsigned long uintmax_t; +#endif +#endif + +#ifdef _STDINT_NEED_INTPTR_T +#ifndef __intptr_t_defined +#define __intptr_t_defined +/* we encourage using "long" to store pointer values, never use "int" ! */ +#if _STDINT_LONG_MODEL+0 == 242 || _STDINT_LONG_MODEL+0 == 484 +typedef unsigned int uintptr_t; +typedef int intptr_t; +#elif _STDINT_LONG_MODEL+0 == 244 || _STDINT_LONG_MODEL+0 == 444 +typedef unsigned long uintptr_t; +typedef long intptr_t; +#elif _STDINT_LONG_MODEL+0 == 448 && defined _HAVE_UINT64_T +typedef uint64_t uintptr_t; +typedef int64_t intptr_t; +#else /* matches typical system types ILP32 and LP64 - but not IP16 or LLP64 */ +typedef unsigned long uintptr_t; +typedef long intptr_t; +#endif +#endif +#endif + +/* The ISO C99 standard specifies that in C++ implementations these + should only be defined if explicitly requested. */ +#if !defined __cplusplus || defined __STDC_CONSTANT_MACROS +#ifndef UINT32_C + +/* Signed. */ +# define INT8_C(c) c +# define INT16_C(c) c +# define INT32_C(c) c +# ifdef _HAVE_LONGLONG_UINT64_T +# define INT64_C(c) c ## L +# else +# define INT64_C(c) c ## LL +# endif + +/* Unsigned. */ +# define UINT8_C(c) c ## U +# define UINT16_C(c) c ## U +# define UINT32_C(c) c ## U +# ifdef _HAVE_LONGLONG_UINT64_T +# define UINT64_C(c) c ## UL +# else +# define UINT64_C(c) c ## ULL +# endif + +/* Maximal type. */ +# ifdef _HAVE_LONGLONG_UINT64_T +# define INTMAX_C(c) c ## L +# define UINTMAX_C(c) c ## UL +# else +# define INTMAX_C(c) c ## LL +# define UINTMAX_C(c) c ## ULL +# endif + + /* literalnumbers */ +#endif +#endif + +/* These limits are merily those of a two complement byte-oriented system */ + +/* Minimum of signed integral types. */ +# define INT8_MIN (-128) +# define INT16_MIN (-32767-1) +# define INT32_MIN (-2147483647-1) +# define INT64_MIN (-__INT64_C(9223372036854775807)-1) +/* Maximum of signed integral types. */ +# define INT8_MAX (127) +# define INT16_MAX (32767) +# define INT32_MAX (2147483647) +# define INT64_MAX (__INT64_C(9223372036854775807)) + +/* Maximum of unsigned integral types. */ +# define UINT8_MAX (255) +# define UINT16_MAX (65535) +# define UINT32_MAX (4294967295U) +# define UINT64_MAX (__UINT64_C(18446744073709551615)) + +/* Minimum of signed integral types having a minimum size. */ +# define INT_LEAST8_MIN INT8_MIN +# define INT_LEAST16_MIN INT16_MIN +# define INT_LEAST32_MIN INT32_MIN +# define INT_LEAST64_MIN INT64_MIN +/* Maximum of signed integral types having a minimum size. */ +# define INT_LEAST8_MAX INT8_MAX +# define INT_LEAST16_MAX INT16_MAX +# define INT_LEAST32_MAX INT32_MAX +# define INT_LEAST64_MAX INT64_MAX + +/* Maximum of unsigned integral types having a minimum size. */ +# define UINT_LEAST8_MAX UINT8_MAX +# define UINT_LEAST16_MAX UINT16_MAX +# define UINT_LEAST32_MAX UINT32_MAX +# define UINT_LEAST64_MAX UINT64_MAX + + /* shortcircuit*/ +#endif + /* once */ +#endif +#endif +STDINT_EOF +fi + if cmp -s $ac_stdint_h $ac_stdint 2>/dev/null; then + AC_MSG_NOTICE([$ac_stdint_h is unchanged]) + else + ac_dir=`AS_DIRNAME(["$ac_stdint_h"])` + AS_MKDIR_P(["$ac_dir"]) + rm -f $ac_stdint_h + mv $ac_stdint $ac_stdint_h + fi +],[# variables for create stdint.h replacement +PACKAGE="$PACKAGE" +VERSION="$VERSION" +ac_stdint_h="$ac_stdint_h" +_ac_stdint_h=AS_TR_CPP(_$PACKAGE-$ac_stdint_h) +ac_cv_stdint_message="$ac_cv_stdint_message" +ac_cv_header_stdint_t="$ac_cv_header_stdint_t" +ac_cv_header_stdint_x="$ac_cv_header_stdint_x" +ac_cv_header_stdint_o="$ac_cv_header_stdint_o" +ac_cv_header_stdint_u="$ac_cv_header_stdint_u" +ac_cv_type_uint64_t="$ac_cv_type_uint64_t" +ac_cv_type_u_int64_t="$ac_cv_type_u_int64_t" +ac_cv_char_data_model="$ac_cv_char_data_model" +ac_cv_long_data_model="$ac_cv_long_data_model" +ac_cv_type_int_least32_t="$ac_cv_type_int_least32_t" +ac_cv_type_int_fast32_t="$ac_cv_type_int_fast32_t" +ac_cv_type_intmax_t="$ac_cv_type_intmax_t" +]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/check.m4 b/gst-plugins-base-subtitles0.10/common/m4/check.m4 new file mode 100644 index 0000000..afd26eb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/check.m4 @@ -0,0 +1,181 @@ +dnl _AM_TRY_CHECK(MINIMUM-VERSION, EXTRA-CFLAGS, EXTRA-LIBS, CHECK-LIB-NAME +dnl [, ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS +dnl Done this way because of the brokenness that is +dnl https://launchpad.net/distros/ubuntu/+source/check/+bug/5840 +dnl + +AC_DEFUN([_AM_TRY_CHECK], +[ + min_check_version=$1 + extra_cflags=$2 + extra_libs=$3 + check_lib_name=$4 + + CHECK_CFLAGS="$extra_cflags" + CHECK_LIBS="$extra_libs -l$check_lib_name" + + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + + CFLAGS="$CFLAGS $CHECK_CFLAGS" + LIBS="$CHECK_LIBS $LIBS" + + AC_MSG_CHECKING(for check named $check_lib_name - version >= $min_check_version) + + rm -f conf.check-test + dnl unset no_check, since in our second run it would have been set to yes + dnl before + no_check= + AC_TRY_RUN([ +#include +#include + +#include + +int main () +{ + int major, minor, micro; + char *tmp_version; + + system ("touch conf.check-test"); + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = strdup("$min_check_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_check_version"); + return 1; + } + + if ((CHECK_MAJOR_VERSION != check_major_version) || + (CHECK_MINOR_VERSION != check_minor_version) || + (CHECK_MICRO_VERSION != check_micro_version)) + { + printf("\n*** The check header file (version %d.%d.%d) does not match\n", + CHECK_MAJOR_VERSION, CHECK_MINOR_VERSION, CHECK_MICRO_VERSION); + printf("*** the check library (version %d.%d.%d).\n", + check_major_version, check_minor_version, check_micro_version); + return 1; + } + + if ((check_major_version > major) || + ((check_major_version == major) && (check_minor_version > minor)) || + ((check_major_version == major) && (check_minor_version == minor) && (check_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** An old version of check (%d.%d.%d) was found.\n", + check_major_version, check_minor_version, check_micro_version); + printf("*** You need a version of check being at least %d.%d.%d.\n", major, minor, micro); + printf("***\n"); + printf("*** If you have already installed a sufficiently new version, this error\n"); + printf("*** probably means that the wrong copy of the check library and header\n"); + printf("*** file is being found. Rerun configure with the --with-check=PATH option\n"); + printf("*** to specify the prefix where the correct version was installed.\n"); + } + + return 1; +} +],, no_check=yes, [echo $ac_n "cross compiling; assumed OK... $ac_c"]) + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + + if test "x$no_check" = x ; then + AC_MSG_RESULT(yes) + ifelse([$5], , :, [$5]) + else + AC_MSG_RESULT(no) + if test -f conf.check-test ; then + : + else + echo "*** Could not run check test program, checking why..." + CFLAGS="$CFLAGS $CHECK_CFLAGS" + LIBS="$CHECK_LIBS $LIBS" + AC_TRY_LINK([ +#include +#include + +#include +], , [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding check. You'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for" + echo "*** the exact error that occured." ]) + + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + + CHECK_CFLAGS="" + CHECK_LIBS="" + + rm -f conf.check-test + ifelse([$6], , AC_MSG_ERROR([check not found]), [$6]) + fi +]) + + +dnl AM_PATH_CHECK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for check, and define CHECK_CFLAGS and CHECK_LIBS +dnl + +AC_DEFUN([AM_PATH_CHECK], +[ + AC_ARG_WITH(check, + [ --with-check=PATH prefix where check is installed [default=auto]]) + + AC_ARG_WITH(checklibname, + AC_HELP_STRING([--with-check-lib-name=NAME], + [name of the PIC check library (default=check)])) + + min_check_version=ifelse([$1], ,0.8.2,$1) + + if test x$with_check = xno; then + AC_MSG_RESULT(disabled) + ifelse([$3], , AC_MSG_ERROR([disabling check is not supported]), [$3]) + else + if test "x$with_check" != x; then + CHECK_EXTRA_CFLAGS="-I$with_check/include" + CHECK_EXTRA_LIBS="-L$with_check/lib" + else + CHECK_EXTRA_CFLAGS="" + CHECK_EXTRA_LIBS="" + fi + + if test x$with_checklibname = x; then + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + check_pic, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + check, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , AC_MSG_ERROR([check not found]), [$3]) + fi + fi + else + _AM_TRY_CHECK($min_check_version, $CHECK_EXTRA_CFLAGS, $CHECK_EXTRA_LIBS, + $with_checklibname, [have_check=true], [have_check=false]) + if test x$have_check = xtrue; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , AC_MSG_ERROR([check not found]), [$3]) + fi + fi + + AC_SUBST(CHECK_CFLAGS) + AC_SUBST(CHECK_LIBS) + rm -f conf.check-test + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/glib-gettext.m4 b/gst-plugins-base-subtitles0.10/common/m4/glib-gettext.m4 new file mode 100644 index 0000000..f8d442f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/glib-gettext.m4 @@ -0,0 +1,432 @@ +# Copyright (C) 1995-2002 Free Software Foundation, Inc. +# Copyright (C) 2001-2003,2004 Red Hat, Inc. +# +# This file is free software, distributed under the terms of the GNU +# General Public License. As a special exception to the GNU General +# Public License, this file may be distributed as part of a program +# that contains a configuration script generated by Autoconf, under +# the same distribution terms as the rest of that program. +# +# This file can be copied and used freely without restrictions. It can +# be used in projects which are not available under the GNU Public License +# but which still want to provide support for the GNU gettext functionality. +# +# Macro to add for using GNU gettext. +# Ulrich Drepper , 1995, 1996 +# +# Modified to never use included libintl. +# Owen Taylor , 12/15/1998 +# +# Major rework to remove unused code +# Owen Taylor , 12/11/2002 +# +# Added better handling of ALL_LINGUAS from GNU gettext version +# written by Bruno Haible, Owen Taylor 5/30/3002 +# +# Modified to require ngettext +# Matthias Clasen 08/06/2004 +# +# We need this here as well, since someone might use autoconf-2.5x +# to configure GLib then an older version to configure a package +# using AM_GLIB_GNU_GETTEXT +AC_PREREQ(2.53) + +dnl +dnl We go to great lengths to make sure that aclocal won't +dnl try to pull in the installed version of these macros +dnl when running aclocal in the glib directory. +dnl +m4_copy([AC_DEFUN],[glib_DEFUN]) +m4_copy([AC_REQUIRE],[glib_REQUIRE]) +dnl +dnl At the end, if we're not within glib, we'll define the public +dnl definitions in terms of our private definitions. +dnl + +# GLIB_LC_MESSAGES +#-------------------- +glib_DEFUN([GLIB_LC_MESSAGES], + [AC_CHECK_HEADERS([locale.h]) + if test $ac_cv_header_locale_h = yes; then + AC_CACHE_CHECK([for LC_MESSAGES], am_cv_val_LC_MESSAGES, + [AC_TRY_LINK([#include ], [return LC_MESSAGES], + am_cv_val_LC_MESSAGES=yes, am_cv_val_LC_MESSAGES=no)]) + if test $am_cv_val_LC_MESSAGES = yes; then + AC_DEFINE(HAVE_LC_MESSAGES, 1, + [Define if your file defines LC_MESSAGES.]) + fi + fi]) + +# GLIB_PATH_PROG_WITH_TEST +#---------------------------- +dnl GLIB_PATH_PROG_WITH_TEST(VARIABLE, PROG-TO-CHECK-FOR, +dnl TEST-PERFORMED-ON-FOUND_PROGRAM [, VALUE-IF-NOT-FOUND [, PATH]]) +glib_DEFUN([GLIB_PATH_PROG_WITH_TEST], +[# Extract the first word of "$2", so it can be a program name with args. +set dummy $2; ac_word=[$]2 +AC_MSG_CHECKING([for $ac_word]) +AC_CACHE_VAL(ac_cv_path_$1, +[case "[$]$1" in + /*) + ac_cv_path_$1="[$]$1" # Let the user override the test with a path. + ;; + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + for ac_dir in ifelse([$5], , $PATH, [$5]); do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if [$3]; then + ac_cv_path_$1="$ac_dir/$ac_word" + break + fi + fi + done + IFS="$ac_save_ifs" +dnl If no 4th arg is given, leave the cache variable unset, +dnl so AC_PATH_PROGS will keep looking. +ifelse([$4], , , [ test -z "[$]ac_cv_path_$1" && ac_cv_path_$1="$4" +])dnl + ;; +esac])dnl +$1="$ac_cv_path_$1" +if test ifelse([$4], , [-n "[$]$1"], ["[$]$1" != "$4"]); then + AC_MSG_RESULT([$]$1) +else + AC_MSG_RESULT(no) +fi +AC_SUBST($1)dnl +]) + +# GLIB_WITH_NLS +#----------------- +glib_DEFUN([GLIB_WITH_NLS], + dnl NLS is obligatory + [USE_NLS=yes + AC_SUBST(USE_NLS) + + gt_cv_have_gettext=no + + CATOBJEXT=NONE + XGETTEXT=: + INTLLIBS= + + AC_CHECK_HEADER(libintl.h, + [gt_cv_func_dgettext_libintl="no" + libintl_extra_libs="" + + # + # First check in libc + # + AC_CACHE_CHECK([for ngettext in libc], gt_cv_func_ngettext_libc, + [AC_TRY_LINK([ +#include +], + [return !ngettext ("","", 1)], + gt_cv_func_ngettext_libc=yes, + gt_cv_func_ngettext_libc=no) + ]) + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CACHE_CHECK([for dgettext in libc], gt_cv_func_dgettext_libc, + [AC_TRY_LINK([ +#include +], + [return !dgettext ("","")], + gt_cv_func_dgettext_libc=yes, + gt_cv_func_dgettext_libc=no) + ]) + fi + + if test "$gt_cv_func_ngettext_libc" = "yes" ; then + AC_CHECK_FUNCS(bind_textdomain_codeset) + fi + + # + # If we don't have everything we want, check in libintl + # + if test "$gt_cv_func_dgettext_libc" != "yes" \ + || test "$gt_cv_func_ngettext_libc" != "yes" \ + || test "$ac_cv_func_bind_textdomain_codeset" != "yes" ; then + + AC_CHECK_LIB(intl, bindtextdomain, + [AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dgettext, + gt_cv_func_dgettext_libintl=yes)])]) + + if test "$gt_cv_func_dgettext_libintl" != "yes" ; then + AC_MSG_CHECKING([if -liconv is needed to use gettext]) + AC_MSG_RESULT([]) + AC_CHECK_LIB(intl, ngettext, + [AC_CHECK_LIB(intl, dcgettext, + [gt_cv_func_dgettext_libintl=yes + libintl_extra_libs=-liconv], + :,-liconv)], + :,-liconv) + fi + + # + # If we found libintl, then check in it for bind_textdomain_codeset(); + # we'll prefer libc if neither have bind_textdomain_codeset(), + # and both have dgettext and ngettext + # + if test "$gt_cv_func_dgettext_libintl" = "yes" ; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS -lintl $libintl_extra_libs" + unset ac_cv_func_bind_textdomain_codeset + AC_CHECK_FUNCS(bind_textdomain_codeset) + LIBS="$glib_save_LIBS" + + if test "$ac_cv_func_bind_textdomain_codeset" = "yes" ; then + gt_cv_func_dgettext_libc=no + else + if test "$gt_cv_func_dgettext_libc" = "yes" \ + && test "$gt_cv_func_ngettext_libc" = "yes"; then + gt_cv_func_dgettext_libintl=no + fi + fi + fi + fi + + if test "$gt_cv_func_dgettext_libc" = "yes" \ + || test "$gt_cv_func_dgettext_libintl" = "yes"; then + gt_cv_have_gettext=yes + fi + + if test "$gt_cv_func_dgettext_libintl" = "yes"; then + INTLLIBS="-lintl $libintl_extra_libs" + fi + + if test "$gt_cv_have_gettext" = "yes"; then + AC_DEFINE(HAVE_GETTEXT,1, + [Define if the GNU gettext() function is already present or preinstalled.]) + GLIB_PATH_PROG_WITH_TEST(MSGFMT, msgfmt, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep 'dv '`"], no)dnl + if test "$MSGFMT" != "no"; then + glib_save_LIBS="$LIBS" + LIBS="$LIBS $INTLLIBS" + AC_CHECK_FUNCS(dcgettext) + MSGFMT_OPTS= + AC_MSG_CHECKING([if msgfmt accepts -c]) + GLIB_RUN_PROG([$MSGFMT -c -o /dev/null],[ +msgid "" +msgstr "" +"Content-Type: text/plain; charset=UTF-8\n" +"Project-Id-Version: test 1.0\n" +"PO-Revision-Date: 2007-02-15 12:01+0100\n" +"Last-Translator: test \n" +"Language-Team: C \n" +"MIME-Version: 1.0\n" +"Content-Transfer-Encoding: 8bit\n" +], [MSGFMT_OPTS=-c; AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])]) + AC_SUBST(MSGFMT_OPTS) + AC_PATH_PROG(GMSGFMT, gmsgfmt, $MSGFMT) + GLIB_PATH_PROG_WITH_TEST(XGETTEXT, xgettext, + [test -z "`$ac_dir/$ac_word -h 2>&1 | grep '(HELP)'`"], :) + AC_TRY_LINK(, [extern int _nl_msg_cat_cntr; + return _nl_msg_cat_cntr], + [CATOBJEXT=.gmo + DATADIRNAME=share], + [case $host in + *-*-solaris*) + dnl On Solaris, if bind_textdomain_codeset is in libc, + dnl GNU format message catalog is always supported, + dnl since both are added to the libc all together. + dnl Hence, we'd like to go with DATADIRNAME=share and + dnl and CATOBJEXT=.gmo in this case. + AC_CHECK_FUNC(bind_textdomain_codeset, + [CATOBJEXT=.gmo + DATADIRNAME=share], + [CATOBJEXT=.mo + DATADIRNAME=lib]) + ;; + *) + CATOBJEXT=.mo + DATADIRNAME=lib + ;; + esac]) + LIBS="$glib_save_LIBS" + INSTOBJEXT=.mo + else + gt_cv_have_gettext=no + fi + fi + ]) + + if test "$gt_cv_have_gettext" = "yes" ; then + AC_DEFINE(ENABLE_NLS, 1, + [always defined to indicate that i18n is enabled]) + fi + + dnl Test whether we really found GNU xgettext. + if test "$XGETTEXT" != ":"; then + dnl If it is not GNU xgettext we define it as : so that the + dnl Makefiles still can work. + if $XGETTEXT --omit-header /dev/null 2> /dev/null; then + : ; + else + AC_MSG_RESULT( + [found xgettext program is not GNU xgettext; ignore it]) + XGETTEXT=":" + fi + fi + + # We need to process the po/ directory. + POSUB=po + + AC_OUTPUT_COMMANDS( + [case "$CONFIG_FILES" in *po/Makefile.in*) + sed -e "/POTFILES =/r po/POTFILES" po/Makefile.in > po/Makefile + esac]) + + dnl These rules are solely for the distribution goal. While doing this + dnl we only have to keep exactly one list of the available catalogs + dnl in configure.in. + for lang in $ALL_LINGUAS; do + GMOFILES="$GMOFILES $lang.gmo" + POFILES="$POFILES $lang.po" + done + + dnl Make all variables we use known to autoconf. + AC_SUBST(CATALOGS) + AC_SUBST(CATOBJEXT) + AC_SUBST(DATADIRNAME) + AC_SUBST(GMOFILES) + AC_SUBST(INSTOBJEXT) + AC_SUBST(INTLLIBS) + AC_SUBST(PO_IN_DATADIR_TRUE) + AC_SUBST(PO_IN_DATADIR_FALSE) + AC_SUBST(POFILES) + AC_SUBST(POSUB) + ]) + +# AM_GLIB_GNU_GETTEXT +# ------------------- +# Do checks necessary for use of gettext. If a suitable implementation +# of gettext is found in either in libintl or in the C library, +# it will set INTLLIBS to the libraries needed for use of gettext +# and AC_DEFINE() HAVE_GETTEXT and ENABLE_NLS. (The shell variable +# gt_cv_have_gettext will be set to "yes".) It will also call AC_SUBST() +# on various variables needed by the Makefile.in.in installed by +# glib-gettextize. +dnl +glib_DEFUN([GLIB_GNU_GETTEXT], + [AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl + + GLIB_LC_MESSAGES + GLIB_WITH_NLS + + if test "$gt_cv_have_gettext" = "yes"; then + if test "x$ALL_LINGUAS" = "x"; then + LINGUAS= + else + AC_MSG_CHECKING(for catalogs to be installed) + NEW_LINGUAS= + for presentlang in $ALL_LINGUAS; do + useit=no + if test "%UNSET%" != "${LINGUAS-%UNSET%}"; then + desiredlanguages="$LINGUAS" + else + desiredlanguages="$ALL_LINGUAS" + fi + for desiredlang in $desiredlanguages; do + # Use the presentlang catalog if desiredlang is + # a. equal to presentlang, or + # b. a variant of presentlang (because in this case, + # presentlang can be used as a fallback for messages + # which are not translated in the desiredlang catalog). + case "$desiredlang" in + "$presentlang"*) useit=yes;; + esac + done + if test $useit = yes; then + NEW_LINGUAS="$NEW_LINGUAS $presentlang" + fi + done + LINGUAS=$NEW_LINGUAS + AC_MSG_RESULT($LINGUAS) + fi + + dnl Construct list of names of catalog files to be constructed. + if test -n "$LINGUAS"; then + for lang in $LINGUAS; do CATALOGS="$CATALOGS $lang$CATOBJEXT"; done + fi + fi + + dnl If the AC_CONFIG_AUX_DIR macro for autoconf is used we possibly + dnl find the mkinstalldirs script in another subdir but ($top_srcdir). + dnl Try to locate is. + MKINSTALLDIRS= + if test -n "$ac_aux_dir"; then + MKINSTALLDIRS="$ac_aux_dir/mkinstalldirs" + fi + if test -z "$MKINSTALLDIRS"; then + MKINSTALLDIRS="\$(top_srcdir)/mkinstalldirs" + fi + AC_SUBST(MKINSTALLDIRS) + + dnl Generate list of files to be processed by xgettext which will + dnl be included in po/Makefile. + test -d po || mkdir po + if test "x$srcdir" != "x."; then + if test "x`echo $srcdir | sed 's@/.*@@'`" = "x"; then + posrcprefix="$srcdir/" + else + posrcprefix="../$srcdir/" + fi + else + posrcprefix="../" + fi + rm -f po/POTFILES + sed -e "/^#/d" -e "/^\$/d" -e "s,.*, $posrcprefix& \\\\," -e "\$s/\(.*\) \\\\/\1/" \ + < $srcdir/po/POTFILES.in > po/POTFILES + ]) + +# AM_GLIB_DEFINE_LOCALEDIR(VARIABLE) +# ------------------------------- +# Define VARIABLE to the location where catalog files will +# be installed by po/Makefile. +glib_DEFUN([GLIB_DEFINE_LOCALEDIR], +[glib_REQUIRE([GLIB_GNU_GETTEXT])dnl +glib_save_prefix="$prefix" +glib_save_exec_prefix="$exec_prefix" +glib_save_datarootdir="$datarootdir" +test "x$prefix" = xNONE && prefix=$ac_default_prefix +test "x$exec_prefix" = xNONE && exec_prefix=$prefix +datarootdir=`eval echo "${datarootdir}"` +if test "x$CATOBJEXT" = "x.mo" ; then + localedir=`eval echo "${libdir}/locale"` +else + localedir=`eval echo "${datadir}/locale"` +fi +prefix="$glib_save_prefix" +exec_prefix="$glib_save_exec_prefix" +datarootdir="$glib_save_datarootdir" +AC_DEFINE_UNQUOTED($1, "$localedir", + [Define the location where the catalogs will be installed]) +]) + +dnl +dnl Now the definitions that aclocal will find +dnl +ifdef(glib_configure_in,[],[ +AC_DEFUN([AM_GLIB_GNU_GETTEXT],[GLIB_GNU_GETTEXT($@)]) +AC_DEFUN([AM_GLIB_DEFINE_LOCALEDIR],[GLIB_DEFINE_LOCALEDIR($@)]) +])dnl + +# GLIB_RUN_PROG(PROGRAM, TEST-FILE, [ACTION-IF-PASS], [ACTION-IF-FAIL]) +# +# Create a temporary file with TEST-FILE as its contents and pass the +# file name to PROGRAM. Perform ACTION-IF-PASS if PROGRAM exits with +# 0 and perform ACTION-IF-FAIL for any other exit status. +AC_DEFUN([GLIB_RUN_PROG], +[cat >conftest.foo <<_ACEOF +$2 +_ACEOF +if AC_RUN_LOG([$1 conftest.foo]); then + m4_ifval([$3], [$3], [:]) +m4_ifvaln([$4], [else $4])dnl +echo "$as_me: failed input was:" >&AS_MESSAGE_LOG_FD +sed 's/^/| /' conftest.foo >&AS_MESSAGE_LOG_FD +fi]) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-arch.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-arch.m4 new file mode 100644 index 0000000..2e935d2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-arch.m4 @@ -0,0 +1,141 @@ +dnl AG_GST_ARCH +dnl sets up defines and automake conditionals for host architecture +dnl checks endianness +dnl defines HOST_CPU + +AC_DEFUN([AG_GST_ARCH], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) dnl we use host_ variables + + dnl Determine CPU + case "x${host_cpu}" in + xi?86 | xk? | xi?86_64) + case $host_os in + solaris*) + AC_CHECK_DECL([__i386], [I386_ABI="yes"], [I386_ABI="no"]) + AC_CHECK_DECL([__amd64], [AMD64_ABI="yes"], [AMD64_ABI="no"]) + + if test "x$I386_ABI" = "xyes" ; then + HAVE_CPU_I386=yes + AC_DEFINE(HAVE_CPU_I386, 1, [Define if the host CPU is an x86]) + fi + if test "x$AMD64_ABI" = "xyes" ; then + HAVE_CPU_X86_64=yes + AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the host CPU is a x86_64]) + fi + ;; + *) + HAVE_CPU_I386=yes + AC_DEFINE(HAVE_CPU_I386, 1, [Define if the host CPU is an x86]) + + dnl FIXME could use some better detection + dnl (ie CPUID) + case "x${host_cpu}" in + xi386 | xi486) ;; + *) + AC_DEFINE(HAVE_RDTSC, 1, [Define if RDTSC is available]) ;; + esac + ;; + esac + ;; + xpowerpc) + HAVE_CPU_PPC=yes + AC_DEFINE(HAVE_CPU_PPC, 1, [Define if the host CPU is a PowerPC]) ;; + xpowerpc64) + HAVE_CPU_PPC64=yes + AC_DEFINE(HAVE_CPU_PPC64, 1, [Define if the host CPU is a 64 bit PowerPC]) ;; + xalpha*) + HAVE_CPU_ALPHA=yes + AC_DEFINE(HAVE_CPU_ALPHA, 1, [Define if the host CPU is an Alpha]) ;; + xarm*) + HAVE_CPU_ARM=yes + AC_DEFINE(HAVE_CPU_ARM, 1, [Define if the host CPU is an ARM]) ;; + xsparc*) + HAVE_CPU_SPARC=yes + AC_DEFINE(HAVE_CPU_SPARC, 1, [Define if the host CPU is a SPARC]) ;; + xmips*) + HAVE_CPU_MIPS=yes + AC_DEFINE(HAVE_CPU_MIPS, 1, [Define if the host CPU is a MIPS]) ;; + xhppa*) + HAVE_CPU_HPPA=yes + AC_DEFINE(HAVE_CPU_HPPA, 1, [Define if the host CPU is a HPPA]) ;; + xs390*) + HAVE_CPU_S390=yes + AC_DEFINE(HAVE_CPU_S390, 1, [Define if the host CPU is a S390]) ;; + xia64*) + HAVE_CPU_IA64=yes + AC_DEFINE(HAVE_CPU_IA64, 1, [Define if the host CPU is a IA64]) ;; + xm68k*) + HAVE_CPU_M68K=yes + AC_DEFINE(HAVE_CPU_M68K, 1, [Define if the host CPU is a M68K]) ;; + xx86_64) + HAVE_CPU_X86_64=yes + AC_DEFINE(HAVE_CPU_X86_64, 1, [Define if the host CPU is a x86_64]) ;; + xcris) + HAVE_CPU_CRIS=yes + AC_DEFINE(HAVE_CPU_CRIS, 1, [Define if the host CPU is a CRIS]) ;; + xcrisv32) + HAVE_CPU_CRISV32=yes + AC_DEFINE(HAVE_CPU_CRISV32, 1, [Define if the host CPU is a CRISv32]) ;; + esac + + dnl Determine endianness + AC_C_BIGENDIAN + + AM_CONDITIONAL(HAVE_CPU_I386, test "x$HAVE_CPU_I386" = "xyes") + AM_CONDITIONAL(HAVE_CPU_PPC, test "x$HAVE_CPU_PPC" = "xyes") + AM_CONDITIONAL(HAVE_CPU_PPC64, test "x$HAVE_CPU_PPC64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_ALPHA, test "x$HAVE_CPU_ALPHA" = "xyes") + AM_CONDITIONAL(HAVE_CPU_ARM, test "x$HAVE_CPU_ARM" = "xyes") + AM_CONDITIONAL(HAVE_CPU_SPARC, test "x$HAVE_CPU_SPARC" = "xyes") + AM_CONDITIONAL(HAVE_CPU_HPPA, test "x$HAVE_CPU_HPPA" = "xyes") + AM_CONDITIONAL(HAVE_CPU_MIPS, test "x$HAVE_CPU_MIPS" = "xyes") + AM_CONDITIONAL(HAVE_CPU_S390, test "x$HAVE_CPU_S390" = "xyes") + AM_CONDITIONAL(HAVE_CPU_IA64, test "x$HAVE_CPU_IA64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_M68K, test "x$HAVE_CPU_M68K" = "xyes") + AM_CONDITIONAL(HAVE_CPU_X86_64, test "x$HAVE_CPU_X86_64" = "xyes") + AM_CONDITIONAL(HAVE_CPU_CRIS, test "x$HAVE_CPU_CRIS" = "xyes") + AM_CONDITIONAL(HAVE_CPU_CRISV32, test "x$HAVE_CPU_CRISV32" = "xyes") + + AC_DEFINE_UNQUOTED(HOST_CPU, "$host_cpu", [the host CPU]) +]) + +dnl check if unaligned memory access works correctly +AC_DEFUN([AG_GST_UNALIGNED_ACCESS], [ + AC_MSG_CHECKING([if unaligned memory access works correctly]) + if test x"$as_cv_unaligned_access" = x ; then + case $host in + alpha*|arm*|hp*|mips*|sh*|sparc*|ia64*) + _AS_ECHO_N([(blacklisted) ]) + as_cv_unaligned_access=no + ;; + i?86*|x86_64*|amd64*|powerpc*|m68k*|cris*) + _AS_ECHO_N([(whitelisted) ]) + as_cv_unaligned_access=yes + ;; + esac + else + _AS_ECHO_N([(cached) ]) + fi + if test x"$as_cv_unaligned_access" = x ; then + AC_TRY_RUN([ +int main(int argc, char **argv) +{ + char array[] = "ABCDEFGH"; + unsigned int iarray[2]; + memcpy(iarray,array,8); +#define GET(x) (*(unsigned int *)((char *)iarray + (x))) + if(GET(0) != 0x41424344 && GET(0) != 0x44434241) return 1; + if(GET(1) != 0x42434445 && GET(1) != 0x45444342) return 1; + if(GET(2) != 0x43444546 && GET(2) != 0x46454443) return 1; + if(GET(3) != 0x44454647 && GET(3) != 0x47464544) return 1; + return 0; +} + ], as_cv_unaligned_access="yes", as_cv_unaligned_access="no") + fi + AC_MSG_RESULT($as_cv_unaligned_access) + if test "$as_cv_unaligned_access" = "yes"; then + AC_DEFINE_UNQUOTED(HAVE_UNALIGNED_ACCESS, 1, + [defined if unaligned memory access works correctly]) + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-args.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-args.m4 new file mode 100644 index 0000000..ccdd4da --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-args.m4 @@ -0,0 +1,330 @@ +dnl configure-time options shared among gstreamer modules + +dnl AG_GST_ARG_DEBUG +dnl AG_GST_ARG_PROFILING +dnl AG_GST_ARG_VALGRIND +dnl AG_GST_ARG_GCOV + +dnl AG_GST_ARG_EXAMPLES + +dnl AG_GST_ARG_WITH_PKG_CONFIG_PATH +dnl AG_GST_ARG_WITH_PACKAGE_NAME +dnl AG_GST_ARG_WITH_PACKAGE_ORIGIN + +dnl AG_GST_ARG_WITH_PLUGINS +dnl AG_GST_CHECK_PLUGIN +dnl AG_GST_DISABLE_PLUGIN + +dnl AG_GST_ARG_ENABLE_EXTERNAL +dnl AG_GST_ARG_ENABLE_EXPERIMENTAL +dnl AG_GST_ARG_ENABLE_BROKEN + +AC_DEFUN([AG_GST_ARG_DEBUG], +[ + dnl debugging stuff + AC_ARG_ENABLE(debug, + AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]), + [ + case "${enableval}" in + yes) USE_DEBUG=yes ;; + no) USE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; + esac + ], + [USE_DEBUG=yes]) dnl Default value +]) + +AC_DEFUN([AG_GST_ARG_PROFILING], +[ + AC_ARG_ENABLE(profiling, + AC_HELP_STRING([--enable-profiling], + [adds -pg to compiler commandline, for profiling]), + [ + case "${enableval}" in + yes) USE_PROFILING=yes ;; + no) USE_PROFILING=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-profiling) ;; + esac + ], + [USE_PROFILING=no]) dnl Default value +]) + +AC_DEFUN([AG_GST_ARG_VALGRIND], +[ + dnl valgrind inclusion + AC_ARG_ENABLE(valgrind, + AC_HELP_STRING([--disable-valgrind],[disable run-time valgrind detection]), + [ + case "${enableval}" in + yes) USE_VALGRIND="$USE_DEBUG" ;; + no) USE_VALGRIND=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;; + esac + ], + [USE_VALGRIND="$USE_DEBUG"]) dnl Default value + VALGRIND_REQ="3.0" + if test "x$USE_VALGRIND" = xyes; then + PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ, + USE_VALGRIND="yes", + [ + USE_VALGRIND="no" + AC_MSG_RESULT([no]) + ]) + fi + if test "x$USE_VALGRIND" = xyes; then + AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used]) + AC_MSG_NOTICE(Using extra code paths for valgrind) + fi +]) + +AC_DEFUN([AG_GST_ARG_GCOV], +[ + AC_ARG_ENABLE(gcov, + AC_HELP_STRING([--enable-gcov], + [compile with coverage profiling instrumentation (gcc only)]), + enable_gcov=$enableval, + enable_gcov=no) + if test x$enable_gcov = xyes ; then + if test "x$GCC" != "xyes" + then + AC_MSG_ERROR([gcov only works if gcc is used]) + fi + + AS_COMPILER_FLAG(["-fprofile-arcs"], + [GCOV_CFLAGS="$GCOV_CFLAGS -fprofile-arcs"], + true) + AS_COMPILER_FLAG(["-ftest-coverage"], + [GCOV_CFLAGS="$GCOV_CFLAGS -ftest-coverage"], + true) + dnl remove any -O flags - FIXME: is this needed ? + GCOV_CFLAGS=`echo "$GCOV_CFLAGS" | sed -e 's/-O[[0-9]]*//g'` + dnl libtool 1.5.22 and lower strip -fprofile-arcs from the flags + dnl passed to the linker, which is a bug; -fprofile-arcs implicitly + dnl links in -lgcov, so we do it explicitly here for the same effect + GCOV_LIBS=-lgcov + AC_SUBST(GCOV_CFLAGS) + AC_SUBST(GCOV_LIBS) + GCOV=`echo $CC | sed s/gcc/gcov/g` + AC_SUBST(GCOV) + + GST_GCOV_ENABLED=yes + AC_DEFINE_UNQUOTED(GST_GCOV_ENABLED, 1, + [Defined if gcov is enabled to force a rebuild due to config.h changing]) + dnl if gcov is used, we do not want default -O2 CFLAGS + if test "x$GST_GCOV_ENABLED" = "xyes" + then + CFLAGS="-O0" + AC_SUBST(CFLAGS) + CXXFLAGS="-O0" + AC_SUBST(CXXFLAGS) + FFLAGS="-O0" + AC_SUBST(FFLAGS) + CCASFLAGS="-O0" + AC_SUBST(CCASFLAGS) + AC_MSG_NOTICE([gcov enabled, setting CFLAGS and friends to $CFLAGS]) + fi + fi + AM_CONDITIONAL(GST_GCOV_ENABLED, test x$enable_gcov = xyes) +]) + +AC_DEFUN([AG_GST_ARG_EXAMPLES], +[ + AC_ARG_ENABLE(examples, + AC_HELP_STRING([--disable-examples], [disable building examples]), + [ + case "${enableval}" in + yes) BUILD_EXAMPLES=yes ;; + no) BUILD_EXAMPLES=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --disable-examples) ;; + esac + ], + [BUILD_EXAMPLES=yes]) dnl Default value + AM_CONDITIONAL(BUILD_EXAMPLES, test "x$BUILD_EXAMPLES" = "xyes") +]) + +AC_DEFUN([AG_GST_ARG_WITH_PKG_CONFIG_PATH], +[ + dnl possibly modify pkg-config path + AC_ARG_WITH(pkg-config-path, + AC_HELP_STRING([--with-pkg-config-path], + [colon-separated list of pkg-config(1) dirs]), + [ + export PKG_CONFIG_PATH=${withval} + AC_MSG_NOTICE(Set PKG_CONFIG_PATH to $PKG_CONFIG_PATH) + ]) +]) + + +dnl This macro requires that GST_GIT or GST_CVS is set to yes or no (release) +AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_NAME], +[ + dnl package name in plugins + AC_ARG_WITH(package-name, + AC_HELP_STRING([--with-package-name], + [specify package name to use in plugins]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-package-name) ;; + *) GST_PACKAGE_NAME="${withval}" ;; + esac + ], + [ + P=$1 + if test "x$P" = "x" + then + P=$PACKAGE_NAME + fi + + if test "x$PACKAGE_VERSION_NANO" = "x0" + then + GST_PACKAGE_NAME="$P source release" + else + if test "x$PACKAGE_VERSION_NANO" = "x1" + then + GST_PACKAGE_NAME="$P git" + else + GST_PACKAGE_NAME="$P prerelease" + fi + fi + ] + ) + AC_MSG_NOTICE(Using $GST_PACKAGE_NAME as package name) + AC_DEFINE_UNQUOTED(GST_PACKAGE_NAME, "$GST_PACKAGE_NAME", + [package name in plugins]) + AC_SUBST(GST_PACKAGE_NAME) +]) + +AC_DEFUN([AG_GST_ARG_WITH_PACKAGE_ORIGIN], +[ + dnl package origin URL + AC_ARG_WITH(package-origin, + AC_HELP_STRING([--with-package-origin], + [specify package origin URL to use in plugins]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-package-origin) ;; + *) GST_PACKAGE_ORIGIN="${withval}" ;; + esac + ], + [GST_PACKAGE_ORIGIN="[Unknown package origin]"] dnl Default value + ) + AC_MSG_NOTICE(Using $GST_PACKAGE_ORIGIN as package origin) + AC_DEFINE_UNQUOTED(GST_PACKAGE_ORIGIN, "$GST_PACKAGE_ORIGIN", + [package origin]) + AC_SUBST(GST_PACKAGE_ORIGIN) +]) + +dnl sets WITH_PLUGINS to the list of plug-ins given as an argument +dnl also clears GST_PLUGINS_ALL and GST_PLUGINS_SELECTED +AC_DEFUN([AG_GST_ARG_WITH_PLUGINS], +[ + AC_ARG_WITH(plugins, + AC_HELP_STRING([--with-plugins], + [comma-separated list of dependencyless plug-ins to compile]), + [WITH_PLUGINS=$withval], + [WITH_PLUGINS=]) + + GST_PLUGINS_ALL="" + GST_PLUGINS_SELECTED="" + + AC_SUBST(GST_PLUGINS_ALL) + AC_SUBST(GST_PLUGINS_SELECTED) +]) + +dnl AG_GST_CHECK_PLUGIN(PLUGIN-NAME) +dnl +dnl This macro adds the plug-in to GST_PLUGINS_ALL. Then it +dnl checks if WITH_PLUGINS is empty or the plugin is present in WITH_PLUGINS, +dnl and if so adds it to GST_PLUGINS_SELECTED. Then it checks if the plugin +dnl is present in WITHOUT_PLUGINS (ie. was disabled specifically) and if so +dnl removes it from GST_PLUGINS_SELECTED. +dnl +dnl The macro will call AM_CONDITIONAL(USE_PLUGIN_, ...) to allow +dnl control of what is built in Makefile.ams. +AC_DEFUN([AG_GST_CHECK_PLUGIN], +[ + GST_PLUGINS_ALL="$GST_PLUGINS_ALL [$1]" + + define([pname_def],translit([$1], -a-z, _a-z)) + + AC_ARG_ENABLE([$1], + AC_HELP_STRING([--disable-[$1]], [disable dependency-less $1 plugin]), + [ + case "${enableval}" in + yes) [gst_use_]pname_def=yes ;; + no) [gst_use_]pname_def=no ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-$1]) ;; + esac + ], + [[gst_use_]pname_def=yes]) dnl Default value + + if test x$[gst_use_]pname_def = xno; then + AC_MSG_NOTICE(disabling dependency-less plugin $1) + WITHOUT_PLUGINS="$WITHOUT_PLUGINS [$1]" + fi + undefine([pname_def]) + + if [[ -z "$WITH_PLUGINS" ]] || echo " [$WITH_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED="$GST_PLUGINS_SELECTED [$1]" + fi + if echo " [$WITHOUT_PLUGINS] " | tr , ' ' | grep -i " [$1] " > /dev/null; then + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + fi + AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), echo " $GST_PLUGINS_SELECTED " | grep -i " [$1] " > /dev/null) +]) + +dnl AG_GST_DISABLE_PLUGIN(PLUGIN-NAME) +dnl +dnl This macro disables the plug-in by removing it from +dnl GST_PLUGINS_SELECTED. +AC_DEFUN([AG_GST_DISABLE_PLUGIN], +[ + GST_PLUGINS_SELECTED=`echo " $GST_PLUGINS_SELECTED " | $SED -e 's/ [$1] / /'` + AM_CONDITIONAL([USE_PLUGIN_]translit([$1], a-z, A-Z), false) +]) + +AC_DEFUN([AG_GST_ARG_ENABLE_EXTERNAL], +[ + AG_GST_CHECK_FEATURE(EXTERNAL, [building of plug-ins with external deps],, + HAVE_EXTERNAL=yes, enabled, + [ + AC_MSG_NOTICE(building external plug-ins) + BUILD_EXTERNAL="yes" + ],[ + AC_MSG_WARN(all plug-ins with external dependencies will not be built) + BUILD_EXTERNAL="no" + ]) + # make BUILD_EXTERNAL available to Makefile.am + AM_CONDITIONAL(BUILD_EXTERNAL, test "x$BUILD_EXTERNAL" = "xyes") +]) + +dnl experimental plug-ins; stuff that hasn't had the dust settle yet +dnl read 'builds, but might not work' +AC_DEFUN([AG_GST_ARG_ENABLE_EXPERIMENTAL], +[ + AG_GST_CHECK_FEATURE(EXPERIMENTAL, [building of experimental plug-ins],, + HAVE_EXPERIMENTAL=yes, disabled, + [ + AC_MSG_WARN(building experimental plug-ins) + BUILD_EXPERIMENTAL="yes" + ],[ + AC_MSG_NOTICE(not building experimental plug-ins) + BUILD_EXPERIMENTAL="no" + ]) + # make BUILD_EXPERIMENTAL available to Makefile.am + AM_CONDITIONAL(BUILD_EXPERIMENTAL, test "x$BUILD_EXPERIMENTAL" = "xyes") +]) + +dnl broken plug-ins; stuff that doesn't seem to build at the moment +AC_DEFUN([AG_GST_ARG_ENABLE_BROKEN], +[ + AG_GST_CHECK_FEATURE(BROKEN, [building of broken plug-ins],, + HAVE_BROKEN=yes, disabled, + [ + AC_MSG_WARN([building broken plug-ins -- no bug reports on these, only patches ...]) + ],[ + AC_MSG_NOTICE([not building broken plug-ins]) + ]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-check.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-check.m4 new file mode 100644 index 0000000..3fd3acf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-check.m4 @@ -0,0 +1,262 @@ +dnl pkg-config-based checks for GStreamer modules and dependency modules + +dnl generic: +dnl AG_GST_PKG_CHECK_MODULES([PREFIX], [WHICH], [REQUIRED]) +dnl sets HAVE_[$PREFIX], [$PREFIX]_* +dnl AG_GST_CHECK_MODULES([PREFIX], [MODULE], [MINVER], [NAME], [REQUIRED]) +dnl sets HAVE_[$PREFIX], [$PREFIX]_* + +dnl specific: +dnl AG_GST_CHECK_GST([MAJMIN], [MINVER], [REQUIRED]) +dnl also sets/ACSUBSTs GST_TOOLS_DIR and GST_PLUGINS_DIR +dnl AG_GST_CHECK_GST_BASE([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_GDP([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_CONTROLLER([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_CHECK([MAJMIN], [MINVER], [REQUIRED]) +dnl AG_GST_CHECK_GST_PLUGINS_BASE([MAJMIN], [MINVER], [REQUIRED]) +dnl also sets/ACSUBSTs GSTPB_PLUGINS_DIR + +AC_DEFUN([AG_GST_PKG_CHECK_MODULES], +[ + which="[$2]" + dnl not required by default, since we use this mostly for plugin deps + required=ifelse([$3], , "no", [$3]) + + PKG_CHECK_MODULES([$1], $which, + [ + HAVE_[$1]="yes" + ], + [ + HAVE_[$1]="no" + if test "x$required" = "xyes"; then + AC_MSG_ERROR($[$1]_PKG_ERRORS) + else + AC_MSG_NOTICE($[$1]_PKG_ERRORS) + fi + ]) + + dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7 + dnl It gets done automatically in automake >= 1.7, which we now require +])) + +AC_DEFUN([AG_GST_CHECK_MODULES], +[ + module=[$2] + minver=[$3] + name="[$4]" + required=ifelse([$5], , "yes", [$5]) dnl required by default + + PKG_CHECK_MODULES([$1], $module >= $minver, + [ + HAVE_[$1]="yes" + ], + [ + HAVE_[$1]="no" + AC_MSG_NOTICE($[$1]_PKG_ERRORS) + if test "x$required" = "xyes"; then + AC_MSG_ERROR([no $module >= $minver ($name) found]) + else + AC_MSG_NOTICE([no $module >= $minver ($name) found]) + fi + ]) + + dnl AC_SUBST of CFLAGS and LIBS was not done before automake 1.7 + dnl It gets done automatically in automake >= 1.7, which we now require +])) + +AC_DEFUN([AG_GST_CHECK_GST], +[ + AG_GST_CHECK_MODULES(GST, gstreamer-[$1], [$2], [GStreamer], [$3]) + dnl allow setting before calling this macro to override + if test -z $GST_TOOLS_DIR; then + GST_TOOLS_DIR=`$PKG_CONFIG --variable=toolsdir gstreamer-[$1]` + if test -z $GST_TOOLS_DIR; then + AC_MSG_ERROR( + [no tools dir set in GStreamer pkg-config file, core upgrade needed.]) + fi + fi + AC_MSG_NOTICE([using GStreamer tools in $GST_TOOLS_DIR]) + AC_SUBST(GST_TOOLS_DIR) + + dnl check for where core plug-ins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_DIR; then + GST_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-[$1]` + if test -z $GST_PLUGINS_DIR; then + AC_MSG_ERROR( + [no pluginsdir set in GStreamer pkg-config file, core upgrade needed.]) + fi + fi + AC_MSG_NOTICE([using GStreamer plug-ins in $GST_PLUGINS_DIR]) + AC_SUBST(GST_PLUGINS_DIR) +]) + +AC_DEFUN([AG_GST_CHECK_GST_BASE], +[ + AG_GST_CHECK_MODULES(GST_BASE, gstreamer-base-[$1], [$2], + [GStreamer Base Libraries], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_GDP], +[ + AG_GST_CHECK_MODULES(GST_GDP, gstreamer-dataprotocol-[$1], [$2], + [GStreamer Data Protocol Library], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_CONTROLLER], +[ + AG_GST_CHECK_MODULES(GST_CONTROLLER, gstreamer-controller-[$1], [$2], + [GStreamer Controller Library], [$3]) +]) + +AC_DEFUN([AG_GST_CHECK_GST_CHECK], +[ + AG_GST_CHECK_MODULES(GST_CHECK, gstreamer-check-[$1], [$2], + [GStreamer Check unittest Library], [$3]) +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_BASE([GST-MAJORMINOR], [MIN-VERSION], [REQUIRED]) +dnl +dnl Sets GST_PLUGINS_BASE_CFLAGS and GST_PLUGINS_BASE_LIBS. +dnl +dnl Also sets GSTPB_PLUGINS_DIR (and for consistency also GST_PLUGINS_BASE_DIR) +dnl for use in Makefile.am. This is only really needed/useful in uninstalled +dnl setups, since in an installed setup all plugins will be found in +dnl GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BASE], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_BASE, gstreamer-plugins-base-[$1], [$2], + [GStreamer Base Plugins], [$3]) + + if test "x$HAVE_GST_PLUGINS_BASE" = "xyes"; then + dnl check for where base plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GSTPB_PLUGINS_DIR; then + GSTPB_PLUGINS_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-base-[$1]` + if test -z $GSTPB_PLUGINS_DIR; then + AC_MSG_ERROR( + [no pluginsdir set in GStreamer Base Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Base Plugins in $GSTPB_PLUGINS_DIR]) + GST_PLUGINS_BASE_DIR="$GSTPB_PLUGINS_DIR/gst:$GSTPB_PLUGINS_DIR/sys:$GSTPB_PLUGINS_DIR/ext" + AC_SUBST(GST_PLUGINS_BASE_DIR) + AC_SUBST(GSTPB_PLUGINS_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_GOOD([GST-MAJORMINOR], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_GOOD_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -good ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_GOOD], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_GOOD, gstreamer-plugins-good-[$1], [$2], + [GStreamer Good Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_GOOD" = "xyes"; then + dnl check for where good plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_GOOD_DIR; then + GST_PLUGINS_GOOD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-good-[$1]` + if test -z $GST_PLUGINS_GOOD_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Good Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Good Plugins in $GST_PLUGINS_GOOD_DIR]) + GST_PLUGINS_GOOD_DIR="$GST_PLUGINS_GOOD_DIR/gst:$GST_PLUGINS_GOOD_DIR/sys:$GST_PLUGINS_GOOD_DIR/ext" + AC_SUBST(GST_PLUGINS_GOOD_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_UGLY([GST-MAJORMINOR], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_UGLY_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -bad ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_UGLY], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_UGLY, gstreamer-plugins-ugly-[$1], [$2], + [GStreamer Ugly Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_UGLY" = "xyes"; then + dnl check for where ugly plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_UGLY_DIR; then + GST_PLUGINS_UGLY_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-ugly-[$1]` + if test -z $GST_PLUGINS_UGLY_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Ugly Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Ugly Plugins in $GST_PLUGINS_UGLY_DIR]) + GST_PLUGINS_UGLY_DIR="$GST_PLUGINS_UGLY_DIR/gst:$GST_PLUGINS_UGLY_DIR/sys:$GST_PLUGINS_UGLY_DIR/ext" + AC_SUBST(GST_PLUGINS_UGLY_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_BAD([GST-MAJORMINOR], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_BAD_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -ugly ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_BAD], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_BAD, gstreamer-plugins-bad-[$1], [$2], + [GStreamer Bad Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_BAD" = "xyes"; then + dnl check for where bad plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_BAD_DIR; then + GST_PLUGINS_BAD_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-bad-[$1]` + if test -z $GST_PLUGINS_BAD_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer Bad Plugins pkg-config file]) + fi + fi + AC_MSG_NOTICE([using GStreamer Bad Plugins in $GST_PLUGINS_BAD_DIR]) + GST_PLUGINS_BAD_DIR="$GST_PLUGINS_BAD_DIR/gst:$GST_PLUGINS_BAD_DIR/sys:$GST_PLUGINS_BAD_DIR/ext" + AC_SUBST(GST_PLUGINS_BAD_DIR) + fi +]) + +dnl =========================================================================== +dnl AG_GST_CHECK_GST_PLUGINS_FFMPEG([GST-MAJORMINOR], [MIN-VERSION]) +dnl +dnl Will set GST_PLUGINS_FFMPEG_DIR for use in Makefile.am. Note that this will +dnl only be set in an uninstalled setup, since -ffmpeg ships no .pc file and in +dnl an installed setup all plugins will be found in GST_PLUGINS_DIR anyway. +dnl =========================================================================== +AC_DEFUN([AG_GST_CHECK_GST_PLUGINS_FFMPEG], +[ + AG_GST_CHECK_MODULES(GST_PLUGINS_FFMPEG, gstreamer-plugins-ffmpeg-[$1], [$2], + [GStreamer FFmpeg Plugins], [no]) + + if test "x$HAVE_GST_PLUGINS_FFMPEG" = "xyes"; then + dnl check for where ffmpeg plugins got installed + dnl this is used for unit tests + dnl allow setting before calling this macro to override + if test -z $GST_PLUGINS_FFMPEG_DIR; then + GST_PLUGINS_FFMPEG_DIR=`$PKG_CONFIG --variable=pluginsdir gstreamer-plugins-ffmpeg-[$1]` + if test -z $GST_PLUGINS_FFMPEG_DIR; then + AC_MSG_ERROR([no pluginsdir set in GStreamer FFmpeg Plugins pkg-config file]) + fi + fi + GST_PLUGINS_FFMPEG_DIR="$GST_PLUGINS_FFMPEG_DIR/ext/ffmpeg" + AC_MSG_NOTICE([using GStreamer FFmpeg Plugins in $GST_PLUGINS_FFMPEG_DIR]) + AC_SUBST(GST_PLUGINS_FFMPEG_DIR) + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-debuginfo.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-debuginfo.m4 new file mode 100644 index 0000000..b48854d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-debuginfo.m4 @@ -0,0 +1,46 @@ +AC_DEFUN([AG_GST_DEBUGINFO], [ +AC_ARG_ENABLE(debug, +AC_HELP_STRING([--disable-debug],[disable addition of -g debugging info]), +[case "${enableval}" in + yes) USE_DEBUG=yes ;; + no) USE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug) ;; +esac], +[USE_DEBUG=yes]) dnl Default value + +AC_ARG_ENABLE(DEBUG, +AC_HELP_STRING([--disable-DEBUG],[disables compilation of debugging messages]), +[case "${enableval}" in + yes) ENABLE_DEBUG=yes ;; + no) ENABLE_DEBUG=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-DEBUG) ;; +esac], +[ENABLE_DEBUG=yes]) dnl Default value +if test x$ENABLE_DEBUG = xyes; then + AC_DEFINE(GST_DEBUG_ENABLED, 1, [Define if DEBUG statements should be compiled in]) +fi + +AC_ARG_ENABLE(INFO, +AC_HELP_STRING([--disable-INFO],[disables compilation of informational messages]), +[case "${enableval}" in + yes) ENABLE_INFO=yes ;; + no) ENABLE_INFO=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-INFO) ;; +esac], +[ENABLE_INFO=yes]) dnl Default value +if test x$ENABLE_INFO = xyes; then + AC_DEFINE(GST_INFO_ENABLED, 1, [Define if INFO statements should be compiled in]) +fi + +AC_ARG_ENABLE(debug-color, +AC_HELP_STRING([--disable-debug-color],[disables color output of DEBUG and INFO output]), +[case "${enableval}" in + yes) ENABLE_DEBUG_COLOR=yes ;; + no) ENABLE_DEBUG_COLOR=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-debug-color) ;; +esac], +[ENABLE_DEBUG_COLOR=yes]) dnl Default value +if test "x$ENABLE_DEBUG_COLOR" = xyes; then + AC_DEFINE(GST_DEBUG_COLOR, 1, [Define if debugging messages should be colorized]) +fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-default.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-default.m4 new file mode 100644 index 0000000..8de9756 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-default.m4 @@ -0,0 +1,120 @@ +dnl default elements used for tests and such + +dnl AG_GST_DEFAULT_ELEMENTS + +AC_DEFUN([AG_GST_DEFAULT_ELEMENTS], +[ + dnl decide on default elements + dnl FIXME: describe where exactly this gets used + dnl FIXME: decide if it's a problem that this could point to sinks from + dnl depending plugin modules + dnl FIXME: when can we just use autoaudiosrc and autovideosrc? + DEFAULT_AUDIOSINK="autoaudiosink" + DEFAULT_VIDEOSINK="autovideosink" + DEFAULT_AUDIOSRC="alsasrc" + DEFAULT_VIDEOSRC="v4l2src" + DEFAULT_VISUALIZER="goom" + case "$host" in + *-sun-* | *pc-solaris* ) + DEFAULT_AUDIOSRC="sunaudiosrc" + ;; + *-darwin* ) + DEFAULT_AUDIOSRC="osxaudiosrc" + ;; + esac + + dnl Default audio sink + AC_ARG_WITH(default-audiosink, + AC_HELP_STRING([--with-default-audiosink], [specify default audio sink]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosink) ;; + *) DEFAULT_AUDIOSINK="${withval}" ;; + esac + ], + [ + DEFAULT_AUDIOSINK="$DEFAULT_AUDIOSINK" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_AUDIOSINK as default audio sink) + AC_SUBST(DEFAULT_AUDIOSINK) + AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSINK, "$DEFAULT_AUDIOSINK", + [Default audio sink]) + + dnl Default audio source + AC_ARG_WITH(default-audiosrc, + AC_HELP_STRING([--with-default-audiosrc], [specify default audio source]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-audiosrc) ;; + *) DEFAULT_AUDIOSRC="${withval}" ;; + esac + ], + [ + DEFAULT_AUDIOSRC="$DEFAULT_AUDIOSRC" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_AUDIOSRC as default audio source) + AC_SUBST(DEFAULT_AUDIOSRC) + AC_DEFINE_UNQUOTED(DEFAULT_AUDIOSRC, "$DEFAULT_AUDIOSRC", + [Default audio source]) + + dnl Default video sink + AC_ARG_WITH(default-videosink, + AC_HELP_STRING([--with-default-videosink], [specify default video sink]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-videosink) ;; + *) DEFAULT_VIDEOSINK="${withval}" ;; + esac + ], + [ + DEFAULT_VIDEOSINK="$DEFAULT_VIDEOSINK" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VIDEOSINK as default video sink) + AC_SUBST(DEFAULT_VIDEOSINK) + AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSINK, "$DEFAULT_VIDEOSINK", + [Default video sink]) + + dnl Default video source + AC_ARG_WITH(default-videosrc, + AC_HELP_STRING([--with-default-videosrc], [specify default video source]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-videosrc) ;; + *) DEFAULT_VIDEOSRC="${withval}" ;; + esac + ], + [ + DEFAULT_VIDEOSRC="$DEFAULT_VIDEOSRC" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VIDEOSRC as default video source) + AC_SUBST(DEFAULT_VIDEOSRC) + AC_DEFINE_UNQUOTED(DEFAULT_VIDEOSRC, "$DEFAULT_VIDEOSRC", + [Default video source]) + + dnl Default visualizer + AC_ARG_WITH(default-visualizer, + AC_HELP_STRING([--with-default-visualizer], [specify default visualizer]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-default-visualizer) ;; + *) DEFAULT_VISUALIZER="${withval}" ;; + esac + ], + [ + DEFAULT_VISUALIZER="$DEFAULT_VISUALIZER" + ] dnl Default value as determined above + ) + AC_MSG_NOTICE(Using $DEFAULT_VISUALIZER as default visualizer) + AC_SUBST(DEFAULT_VISUALIZER) + AC_DEFINE_UNQUOTED(DEFAULT_VISUALIZER, "$DEFAULT_VISUALIZER", + [Default visualizer]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-doc.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-doc.m4 new file mode 100644 index 0000000..6521097 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-doc.m4 @@ -0,0 +1,148 @@ +AC_DEFUN([AG_GST_DOCBOOK_CHECK], +[ + dnl choose a location to install docbook docs in + if test "x$PACKAGE_TARNAME" = "x" + then + AC_MSG_ERROR([Internal error - PACKAGE_TARNAME not set]) + fi + docdir="\$(datadir)/doc/$PACKAGE_TARNAME-$GST_MAJORMINOR" + + dnl enable/disable docbook documentation building + AC_ARG_ENABLE(docbook, + AC_HELP_STRING([--enable-docbook], + [use docbook to build documentation [default=no]]),, + enable_docbook=no) + + have_docbook=no + + if test x$enable_docbook = xyes; then + dnl check if we actually have everything we need + + dnl check for docbook tools + AC_CHECK_PROG(HAVE_DOCBOOK2PS, docbook2ps, yes, no) + AC_CHECK_PROG(HAVE_DOCBOOK2HTML, docbook2html, yes, no) + AC_CHECK_PROG(HAVE_JADETEX, jadetex, yes, no) + AC_CHECK_PROG(HAVE_PS2PDF, ps2pdf, yes, no) + + # -V option appeared in 0.6.10 + docbook2html_min_version=0.6.10 + if test "x$HAVE_DOCBOOK2HTML" != "xno"; then + docbook2html_version=`docbook2html --version` + AC_MSG_CHECKING([docbook2html version ($docbook2html_version) >= $docbook2html_min_version]) + if perl -w < \$min_version_major) || + ((\$docbook2html_version_major == \$min_version_major) && + (\$docbook2html_version_minor >= \$min_version_minor)) || + ((\$docbook2html_version_major == \$min_version_major) && + (\$docbook2html_version_minor >= \$min_version_minor) && + (\$docbook2html_version_micro >= \$min_version_micro))) + ? 0 : 1); +EOF + then + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + HAVE_DOCBOOK2HTML=no + fi + fi + + dnl check if we can process docbook stuff + AS_DOCBOOK(have_docbook=yes, have_docbook=no) + + dnl check for extra tools + AC_CHECK_PROG(HAVE_DVIPS, dvips, yes, no) + AC_CHECK_PROG(HAVE_XMLLINT, xmllint, yes, no) + + dnl check for image conversion tools + AC_CHECK_PROG(HAVE_FIG2DEV, fig2dev, yes, no) + if test "x$HAVE_FIG2DEV" = "xno" ; then + AC_MSG_WARN([Did not find fig2dev (from xfig), images will not be generated.]) + fi + + dnl The following is a hack: if fig2dev doesn't display an error message + dnl for the desired type, we assume it supports it. + HAVE_FIG2DEV_EPS=no + if test "x$HAVE_FIG2DEV" = "xyes" ; then + fig2dev_quiet=`fig2dev -L eps &1 >/dev/null` + if test "x$fig2dev_quiet" = "x" ; then + HAVE_FIG2DEV_EPS=yes + fi + fi + HAVE_FIG2DEV_PNG=no + if test "x$HAVE_FIG2DEV" = "xyes" ; then + fig2dev_quiet=`fig2dev -L png &1 >/dev/null` + if test "x$fig2dev_quiet" = "x" ; then + HAVE_FIG2DEV_PNG=yes + fi + fi + HAVE_FIG2DEV_PDF=no + if test "x$HAVE_FIG2DEV" = "xyes" ; then + fig2dev_quiet=`fig2dev -L pdf &1 >/dev/null` + if test "x$fig2dev_quiet" = "x" ; then + HAVE_FIG2DEV_PDF=yes + fi + fi + + AC_CHECK_PROG(HAVE_PNGTOPNM, pngtopnm, yes, no) + AC_CHECK_PROG(HAVE_PNMTOPS, pnmtops, yes, no) + AC_CHECK_PROG(HAVE_EPSTOPDF, epstopdf, yes, no) + + dnl check if we can generate HTML + if test "x$HAVE_DOCBOOK2HTML" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes" && \ + test "x$HAVE_FIG2DEV_PNG" = "xyes"; then + DOC_HTML=yes + AC_MSG_NOTICE(Will output HTML documentation) + else + DOC_HTML=no + AC_MSG_NOTICE(Will not output HTML documentation) + fi + + dnl check if we can generate PS + if test "x$HAVE_DOCBOOK2PS" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes" && \ + test "x$HAVE_JADETEX" = "xyes" && \ + test "x$HAVE_FIG2DEV_EPS" = "xyes" && \ + test "x$HAVE_DVIPS" = "xyes" && \ + test "x$HAVE_PNGTOPNM" = "xyes" && \ + test "x$HAVE_PNMTOPS" = "xyes"; then + DOC_PS=yes + AC_MSG_NOTICE(Will output PS documentation) + else + DOC_PS=no + AC_MSG_NOTICE(Will not output PS documentation) + fi + + dnl check if we can generate PDF - using only ps2pdf + if test "x$DOC_PS" = "xyes" && \ + test "x$enable_docbook" = "xyes" && \ + test "x$HAVE_XMLLINT" = "xyes" && \ + test "x$HAVE_PS2PDF" = "xyes"; then + DOC_PDF=yes + AC_MSG_NOTICE(Will output PDF documentation) + else + DOC_PDF=no + AC_MSG_NOTICE(Will not output PDF documentation) + fi + + dnl if we don't have everything, we should disable + if test "x$have_docbook" != "xyes"; then + enable_docbook=no + fi + fi + + dnl if we're going to install documentation, tell us where + if test "x$have_docbook" = "xyes"; then + AC_MSG_NOTICE(Installing documentation in $docdir) + AC_SUBST(docdir) + fi + + AM_CONDITIONAL(ENABLE_DOCBOOK, test x$enable_docbook = xyes) + AM_CONDITIONAL(DOC_HTML, test x$DOC_HTML = xyes) + AM_CONDITIONAL(DOC_PDF, test x$DOC_PDF = xyes) + AM_CONDITIONAL(DOC_PS, test x$DOC_PS = xyes) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-dowhile.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-dowhile.m4 new file mode 100644 index 0000000..069808d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-dowhile.m4 @@ -0,0 +1,24 @@ +dnl +dnl Check for working do while(0) macros. This is used by G_STMT_START +dnl and G_STMT_END in glib/gmacros.h. Without having this defined we +dnl get "ambigious if-else" compiler warnings when compling C++ code. +dnl +dnl Copied from GLib's configure.in +dnl +AC_DEFUN([AG_GST_CHECK_DOWHILE_MACROS],[ + +dnl *** check for working do while(0) macros *** +AC_CACHE_CHECK([for working do while(0) macros], _cv_g_support_dowhile_macros, [ + AC_TRY_COMPILE([],[ + #define STMT_START do + #define STMT_END while(0) + #define STMT_TEST STMT_START { i = 0; } STMT_END + int main(void) { int i = 1; STMT_TEST; return i; }], + [_cv_g_support_dowhile_macros=yes], + [_cv_g_support_dowhile_macros=no], + [_cv_g_support_dowhile_macros=yes]) +]) +if test x$_cv_g_support_dowhile_macros = xyes; then + AC_DEFINE(HAVE_DOWHILE_MACROS, 1, [define for working do while(0) macros]) +fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-error.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-error.m4 new file mode 100644 index 0000000..f8f2364 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-error.m4 @@ -0,0 +1,213 @@ +dnl handle various error-related things + +dnl Thomas Vander Stichele +dnl Tim-Philipp Müller + +dnl Last modification: 2008-02-18 + +dnl AG_GST_SET_ERROR_CFLAGS([ADD-WERROR], [MORE_FLAGS]) +dnl AG_GST_SET_ERROR_CXXFLAGS([ADD-WERROR], [MORE_FLAGS]) +dnl AG_GST_SET_LEVEL_DEFAULT([IS-GIT-VERSION]) + + +dnl Sets WARNING_CFLAGS and ERROR_CFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_CFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_CFLAGS will contain flags to make those warnings fatal, +dnl unless ADD-WERROR is set to "no" +dnl +dnl If MORE_FLAGS is set, tries to add each of the given flags +dnl to WARNING_CFLAGS if the compiler supports them. Each flag is +dnl tested separately. +dnl +dnl These flags can be overridden at make time: +dnl make ERROR_CFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_CFLAGS], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AS_COMPILER_FLAG]) + + WARNING_CFLAGS="" + ERROR_CFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_COMPILER_FLAG(-Wall, + WARNING_CFLAGS="$WARNING_CFLAGS -Wall") + + dnl Warn if declarations after statements are used (C99 extension) + AS_COMPILER_FLAG(-Wdeclaration-after-statement, + WARNING_CFLAGS="$WARNING_CFLAGS -Wdeclaration-after-statement") + + dnl Warn if variable length arrays are used (C99 extension) + AS_COMPILER_FLAG(-Wvla, + WARNING_CFLAGS="$WARNING_CFLAGS -Wvla") + + dnl Warn for invalid pointer arithmetic + AS_COMPILER_FLAG(-Wpointer-arith, + WARNING_CFLAGS="$WARNING_CFLAGS -Wpointer-arith") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_COMPILER_FLAG(-Werror, ERROR_CFLAGS="$ERROR_CFLAGS -Werror") + + dnl if -Werror isn't suported, try -errwarn=%all (Sun Forte case) + if test "x$ERROR_CFLAGS" = "x" + then + AS_COMPILER_FLAG([-errwarn=%all], [ + ERROR_CFLAGS="-errwarn=%all" + dnl try -errwarn=%all,no%E_EMPTY_DECLARATION, + dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH, + dnl no%E_MACRO_REDEFINED (Sun Forte case) + dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon + dnl "statement not reached" disabled because there is g_assert_not_reached () in some places + dnl "macro redefined" because of gst/gettext.h + dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'? + for f in 'no%E_EMPTY_DECLARATION' \ + 'no%E_STATEMENT_NOT_REACHED' \ + 'no%E_ARGUEMENT_MISMATCH' \ + 'no%E_MACRO_REDEFINED' \ + 'no%E_LOOP_NOT_ENTERED_AT_TOP' + do + AS_COMPILER_FLAG([-errwarn=%all,$f], [ + ERROR_CFLAGS="$ERROR_CFLAGS,$f" + ]) + done + ]) + else + dnl Add -fno-strict-aliasing for GLib versions before 2.19.8 + dnl as before G_LOCK and friends caused strict aliasing compiler + dnl warnings. + PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [ + AS_COMPILER_FLAG(-fno-strict-aliasing, + ERROR_CFLAGS="$ERROR_CFLAGS -fno-strict-aliasing") + ]) + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_COMPILER_FLAG($each, + WARNING_CFLAGS="$WARNING_CFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_CFLAGS) + AC_SUBST(ERROR_CFLAGS) + AC_MSG_NOTICE([set WARNING_CFLAGS to $WARNING_CFLAGS]) + AC_MSG_NOTICE([set ERROR_CFLAGS to $ERROR_CFLAGS]) +]) + +dnl Sets WARNING_CXXFLAGS and ERROR_CXXFLAGS to something the compiler +dnl will accept and AC_SUBST them so they are available in Makefile +dnl +dnl WARNING_CXXFLAGS will contain flags to make the compiler emit more +dnl warnings. +dnl ERROR_CXXFLAGS will contain flags to make those warnings fatal, +dnl unless ADD-WERROR is set to "no" +dnl +dnl If MORE_FLAGS is set, tries to add each of the given flags +dnl to WARNING_CFLAGS if the compiler supports them. Each flag is +dnl tested separately. +dnl +dnl These flags can be overridden at make time: +dnl make ERROR_CXXFLAGS= +AC_DEFUN([AG_GST_SET_ERROR_CXXFLAGS], +[ + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AS_CXX_COMPILER_FLAG]) + + ERROR_CXXFLAGS="" + WARNING_CXXFLAGS="" + + dnl if we support -Wall, set it unconditionally + AS_CXX_COMPILER_FLAG(-Wall, WARNING_CXXFLAGS="$WARNING_CXXFLAGS -Wall") + + dnl if asked for, add -Werror if supported + if test "x$1" != "xno" + then + AS_CXX_COMPILER_FLAG(-Werror, ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Werror") + + if test "x$ERROR_CXXFLAGS" != "x" + then + dnl add exceptions + AS_CXX_COMPILER_FLAG([-Wno-non-virtual-dtor], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -Wno-non-virtual-dtor") + + dnl Add -fno-strict-aliasing for GLib versions before 2.19.8 + dnl as before G_LOCK and friends caused strict aliasing compiler + dnl warnings. + PKG_CHECK_EXISTS([glib-2.0 < 2.19.8], [ + AS_CXX_COMPILER_FLAG([-fno-strict-aliasing], + ERROR_CXXFLAGS="$ERROR_CXXFLAGS -fno-strict-aliasing") + ]) + else + dnl if -Werror isn't suported, try -errwarn=%all + AS_CXX_COMPILER_FLAG([-errwarn=%all], ERROR_CXXFLAGS="$ERROR_CXXFLAGS -errwarn=%all") + if test "x$ERROR_CXXFLAGS" != "x"; then + dnl try -errwarn=%all,no%E_EMPTY_DECLARATION, + dnl no%E_STATEMENT_NOT_REACHED,no%E_ARGUEMENT_MISMATCH, + dnl no%E_MACRO_REDEFINED (Sun Forte case) + dnl For Forte we need disable "empty declaration" warning produced by un-needed semicolon + dnl "statement not reached" disabled because there is g_assert_not_reached () in some places + dnl "macro redefined" because of gst/gettext.h + dnl FIXME: is it really supposed to be 'ARGUEMENT' and not 'ARGUMENT'? + dnl FIXME: do any of these work with the c++ compiler? if not, why + dnl do we check at all? + for f in 'no%E_EMPTY_DECLARATION' \ + 'no%E_STATEMENT_NOT_REACHED' \ + 'no%E_ARGUEMENT_MISMATCH' \ + 'no%E_MACRO_REDEFINED' \ + 'no%E_LOOP_NOT_ENTERED_AT_TOP' + do + AS_CXX_COMPILER_FLAG([-errwarn=%all,$f], ERROR_CXXFLAGS="$ERROR_CXXFLAGS,$f") + done + fi + fi + fi + + if test "x$2" != "x" + then + UNSUPPORTED="" + list="$2" + for each in $list + do + AS_CXX_COMPILER_FLAG($each, + WARNING_CXXFLAGS="$WARNING_CXXFLAGS $each", + UNSUPPORTED="$UNSUPPORTED $each") + done + if test "X$UNSUPPORTED" != X ; then + AC_MSG_NOTICE([unsupported compiler flags: $UNSUPPORTED]) + fi + fi + + AC_SUBST(WARNING_CXXFLAGS) + AC_SUBST(ERROR_CXXFLAGS) + AC_MSG_NOTICE([set WARNING_CXXFLAGS to $WARNING_CXXFLAGS]) + AC_MSG_NOTICE([set ERROR_CXXFLAGS to $ERROR_CXXFLAGS]) +]) + +dnl Sets the default error level for debugging messages +AC_DEFUN([AG_GST_SET_LEVEL_DEFAULT], +[ + dnl define correct errorlevel for debugging messages. We want to have + dnl GST_ERROR messages printed when running cvs builds + if test "x[$1]" = "xyes"; then + GST_LEVEL_DEFAULT=GST_LEVEL_ERROR + else + GST_LEVEL_DEFAULT=GST_LEVEL_NONE + fi + AC_DEFINE_UNQUOTED(GST_LEVEL_DEFAULT, $GST_LEVEL_DEFAULT, + [Default errorlevel to use]) + dnl AC_SUBST so we can use it for win32/common/config.h + AC_SUBST(GST_LEVEL_DEFAULT) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-feature.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-feature.m4 new file mode 100644 index 0000000..bfb3a1c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-feature.m4 @@ -0,0 +1,283 @@ +dnl Perform a check for a feature for GStreamer +dnl Richard Boulton +dnl Thomas Vander Stichele added useful stuff +dnl Last modification: 25/06/2001 +dnl +dnl AG_GST_CHECK_FEATURE(FEATURE-NAME, FEATURE-DESCRIPTION, +dnl DEPENDENT-PLUGINS, TEST-FOR-FEATURE, +dnl DISABLE-BY-DEFAULT, ACTION-IF-USE, ACTION-IF-NOTUSE) +dnl +dnl This macro adds a command line argument to allow the user to enable +dnl or disable a feature, and if the feature is enabled, performs a supplied +dnl test to check if the feature is available. +dnl +dnl The test should define HAVE_ to "yes" or "no" depending +dnl on whether the feature is available. +dnl +dnl The macro will set USE_ to "yes" or "no" depending on +dnl whether the feature is to be used. +dnl Thomas changed this, so that when USE_ was already set +dnl to no, then it stays that way. +dnl +dnl The macro will call AM_CONDITIONAL(USE_, ...) to allow +dnl the feature to control what is built in Makefile.ams. If you want +dnl additional actions resulting from the test, you can add them with the +dnl ACTION-IF-USE and ACTION-IF-NOTUSE parameters. +dnl +dnl FEATURE-NAME is the name of the feature, and should be in +dnl purely upper case characters. +dnl FEATURE-DESCRIPTION is used to describe the feature in help text for +dnl the command line argument. +dnl DEPENDENT-PLUGINS lists any plug-ins which depend on this feature. +dnl TEST-FOR-FEATURE is a test which sets HAVE_ to "yes" +dnl or "no" depending on whether the feature is +dnl available. +dnl DISABLE-BY-DEFAULT if "disabled", the feature is disabled by default, +dnl if any other value, the feature is enabled by default. +dnl ACTION-IF-USE any extra actions to perform if the feature is to be +dnl used. +dnl ACTION-IF-NOTUSE any extra actions to perform if the feature is not to +dnl be used. +dnl +dnl +dnl thomas : +dnl we also added a history. +dnl GST_PLUGINS_YES will contain all plugins to be built +dnl that were checked through AG_GST_CHECK_FEATURE +dnl GST_PLUGINS_NO will contain those that won't be built + +AC_DEFUN([AG_GST_CHECK_FEATURE], +[echo +AC_MSG_NOTICE(*** checking feature: [$2] ***) +if test "x[$3]" != "x" +then + AC_MSG_NOTICE(*** for plug-ins: [$3] ***) +fi +dnl +builtin(define, [gst_endisable], ifelse($5, [disabled], [enable], [disable]))dnl +dnl if it is set to NO, then don't even consider it for building +NOUSE= +if test "x$USE_[$1]" = "xno"; then + NOUSE="yes" +fi +AC_ARG_ENABLE(translit([$1], A-Z, a-z), + [ ]builtin(format, --%-26s gst_endisable %s, gst_endisable-translit([$1], A-Z, a-z), [$2]ifelse([$3],,,: [$3])), + [ case "${enableval}" in + yes) USE_[$1]=yes;; + no) USE_[$1]=no;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-translit([$1], A-Z, a-z)) ;; + esac], + [ USE_$1=]ifelse($5, [disabled], [no], [yes])) dnl DEFAULT + +dnl *** set it back to no if it was preset to no +if test "x$NOUSE" = "xyes"; then + USE_[$1]="no" + AC_MSG_WARN(*** $3 pre-configured not to be built) +fi +NOUSE= + +dnl *** If it's enabled + +if test x$USE_[$1] = xyes; then + dnl save compile variables before the test + + gst_check_save_LIBS=$LIBS + gst_check_save_LDFLAGS=$LDFLAGS + gst_check_save_CFLAGS=$CFLAGS + gst_check_save_CPPFLAGS=$CPPFLAGS + gst_check_save_CXXFLAGS=$CXXFLAGS + + HAVE_[$1]=no + dnl TEST_FOR_FEATURE + $4 + + LIBS=$gst_check_save_LIBS + LDFLAGS=$gst_check_save_LDFLAGS + CFLAGS=$gst_check_save_CFLAGS + CPPFLAGS=$gst_check_save_CPPFLAGS + CXXFLAGS=$gst_check_save_CXXFLAGS + + dnl If it isn't found, unset USE_[$1] + if test x$HAVE_[$1] = xno; then + USE_[$1]=no + else + ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will be built: [$3])]) + fi +fi +dnl *** Warn if it's disabled or not found +if test x$USE_[$1] = xyes; then + ifelse([$6], , :, [$6]) + if test "x$3" != "x"; then + GST_PLUGINS_YES="\t[$3]\n$GST_PLUGINS_YES" + fi + AC_DEFINE(HAVE_[$1], , [Define to enable $2]ifelse($3,,, [ (used by $3)]).) +else + ifelse([$3], , :, [AC_MSG_NOTICE(*** These plugins will not be built: [$3])]) + if test "x$3" != "x"; then + GST_PLUGINS_NO="\t[$3]\n$GST_PLUGINS_NO" + fi + ifelse([$7], , :, [$7]) +fi +dnl *** Define the conditional as appropriate +AM_CONDITIONAL(USE_[$1], test x$USE_[$1] = xyes) +]) + +dnl Use a -config program which accepts --cflags and --libs parameters +dnl to set *_CFLAGS and *_LIBS and check existence of a feature. +dnl Richard Boulton +dnl Last modification: 26/06/2001 +dnl AG_GST_CHECK_CONFIGPROG(FEATURE-NAME, CONFIG-PROG-FILENAME, MODULES) +dnl +dnl This check was written for GStreamer: it should be renamed and checked +dnl for portability if you decide to use it elsewhere. +dnl +AC_DEFUN([AG_GST_CHECK_CONFIGPROG], +[ + AC_PATH_PROG([$1]_CONFIG, [$2], no) + if test x$[$1]_CONFIG = xno; then + [$1]_LIBS= + [$1]_CFLAGS= + HAVE_[$1]=no + else + if [$2] --plugin-libs [$3] &> /dev/null; then + [$1]_LIBS=`[$2] --plugin-libs [$3]` + else + [$1]_LIBS=`[$2] --libs [$3]` + fi + [$1]_CFLAGS=`[$2] --cflags [$3]` + HAVE_[$1]=yes + fi + AC_SUBST([$1]_LIBS) + AC_SUBST([$1]_CFLAGS) +]) + +dnl Use AC_CHECK_LIB and AC_CHECK_HEADER to do both tests at once +dnl sets HAVE_module if we have it +dnl Richard Boulton +dnl Last modification: 26/06/2001 +dnl AG_GST_CHECK_LIBHEADER(FEATURE-NAME, LIB NAME, LIB FUNCTION, EXTRA LD FLAGS, +dnl HEADER NAME, ACTION-IF-FOUND, ACTION-IF-NOT-FOUND) +dnl +dnl This check was written for GStreamer: it should be renamed and checked +dnl for portability if you decide to use it elsewhere. +dnl +AC_DEFUN([AG_GST_CHECK_LIBHEADER], +[ + AC_CHECK_LIB([$2], [$3], HAVE_[$1]=yes, HAVE_[$1]=no,[$4]) + if test "x$HAVE_[$1]" = "xyes"; then + AC_CHECK_HEADER([$5], :, HAVE_[$1]=no) + if test "x$HAVE_[$1]" = "xyes"; then + dnl execute what needs to be + ifelse([$6], , :, [$6]) + else + ifelse([$7], , :, [$7]) + fi + else + ifelse([$7], , :, [$7]) + fi + AC_SUBST(HAVE_[$1]) +] +) + +dnl 2004-02-14 Thomas - changed to get set properly and use proper output +dnl 2003-06-27 Benjamin Otte - changed to make this work with gstconfig.h +dnl +dnl Add a subsystem --disable flag and all the necessary symbols and substitions +dnl +dnl AG_GST_CHECK_SUBSYSTEM_DISABLE(SYSNAME, [subsystem name]) +dnl +AC_DEFUN([AG_GST_CHECK_SUBSYSTEM_DISABLE], +[ + dnl this define will replace each literal subsys_def occurrence with + dnl the lowercase hyphen-separated subsystem + dnl e.g. if $1 is GST_DEBUG then subsys_def will be a macro with gst-debug + define([subsys_def],translit([$1], _A-Z, -a-z)) + + AC_ARG_ENABLE(subsys_def, + AC_HELP_STRING(--disable-subsys_def, [disable $2]), + [ + case "${enableval}" in + yes) GST_DISABLE_[$1]=no ;; + no) GST_DISABLE_[$1]=yes ;; + *) AC_MSG_ERROR([bad value ${enableval} for --enable-subsys_def]) ;; + esac + ], + [GST_DISABLE_[$1]=no]) dnl Default value + + if test x$GST_DISABLE_[$1] = xyes; then + AC_MSG_NOTICE([disabled subsystem [$2]]) + GST_DISABLE_[$1]_DEFINE="#define GST_DISABLE_$1 1" + else + GST_DISABLE_[$1]_DEFINE="/* #undef GST_DISABLE_$1 */" + fi + AC_SUBST(GST_DISABLE_[$1]_DEFINE) + undefine([subsys_def]) +]) + + +dnl Parse gstconfig.h for feature and defines add the symbols and substitions +dnl +dnl AG_GST_PARSE_SUBSYSTEM_DISABLE(GST_CONFIGPATH, FEATURE) +dnl +AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLE], +[ + grep >/dev/null "#undef GST_DISABLE_$2" $1 + if test $? = 0; then + GST_DISABLE_[$2]=0 + else + GST_DISABLE_[$2]=1 + fi + AC_SUBST(GST_DISABLE_[$2]) +]) + +dnl Parse gstconfig.h and defines add the symbols and substitions +dnl +dnl GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-0.10`"/gst/gstconfig.h" +dnl AG_GST_PARSE_SUBSYSTEM_DISABLES(GST_CONFIGPATH) +dnl +AC_DEFUN([AG_GST_PARSE_SUBSYSTEM_DISABLES], +[ + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,GST_DEBUG) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,LOADSAVE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PARSE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,TRACE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,ALLOC_TRACE) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,REGISTRY) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,PLUGIN) + AG_GST_PARSE_SUBSYSTEM_DISABLE($1,XML) +]) + + + +dnl relies on GST_PLUGINS_ALL, GST_PLUGINS_SELECTED, GST_PLUGINS_YES, +dnl GST_PLUGINS_NO, and BUILD_EXTERNAL +AC_DEFUN([AG_GST_OUTPUT_PLUGINS], [ + +printf "configure: *** Plug-ins without external dependencies that will be built:\n" +( for i in $GST_PLUGINS_SELECTED; do printf '\t'$i'\n'; done ) | sort +printf "\n" + +printf "configure: *** Plug-ins without external dependencies that will NOT be built:\n" +( for i in $GST_PLUGINS_ALL; do + case " $GST_PLUGINS_SELECTED " in + *\ $i\ *) + ;; + *) + printf '\t'$i'\n' + ;; + esac + done ) | sort +printf "\n" + +if test "x$BUILD_EXTERNAL" = "xno"; then + printf "configure: *** No plug-ins with external dependencies will be built\n" +else + printf "configure: *** Plug-ins with dependencies that will be built:" + printf "$GST_PLUGINS_YES\n" | sort + printf "\n" + printf "configure: *** Plug-ins with dependencies that will NOT be built:" + printf "$GST_PLUGINS_NO\n" | sort + printf "\n" +fi +]) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-function.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-function.m4 new file mode 100644 index 0000000..61adfd3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-function.m4 @@ -0,0 +1,63 @@ +dnl +dnl Check for compiler mechanism to show functions in debugging +dnl copied from an Ali patch floating on the internet +dnl +AC_DEFUN([AG_GST_CHECK_FUNCTION],[ + dnl #1: __PRETTY_FUNCTION__ + AC_MSG_CHECKING(whether $CC implements __PRETTY_FUNCTION__) + AC_CACHE_VAL(gst_cv_have_pretty_function,[ + AC_TRY_LINK([#include ], + [printf("%s", __PRETTY_FUNCTION__);], + gst_cv_have_pretty_function=yes, + gst_cv_have_pretty_function=no) + ]) + AC_MSG_RESULT($gst_cv_have_pretty_function) + if test "$gst_cv_have_pretty_function" = yes; then + AC_DEFINE(HAVE_PRETTY_FUNCTION, 1, + [defined if the compiler implements __PRETTY_FUNCTION__]) + fi + +dnl #2: __FUNCTION__ + AC_MSG_CHECKING(whether $CC implements __FUNCTION__) + AC_CACHE_VAL(gst_cv_have_function,[ + AC_TRY_LINK([#include ], + [printf("%s", __FUNCTION__);], + gst_cv_have_function=yes, + gst_cv_have_function=no) + ]) + AC_MSG_RESULT($gst_cv_have_function) + if test "$gst_cv_have_function" = yes; then + AC_DEFINE(HAVE_FUNCTION, 1, + [defined if the compiler implements __FUNCTION__]) + fi + +dnl #3: __func__ + AC_MSG_CHECKING(whether $CC implements __func__) + AC_CACHE_VAL(gst_cv_have_func,[ + AC_TRY_LINK([#include ], + [printf("%s", __func__);], + gst_cv_have_func=yes, + gst_cv_have_func=no) + ]) + AC_MSG_RESULT($gst_cv_have_func) + if test "$gst_cv_have_func" = yes; then + AC_DEFINE(HAVE_FUNC, 1, + [defined if the compiler implements __func__]) + fi + +dnl now define FUNCTION to whatever works, and fallback to "" + if test "$gst_cv_have_pretty_function" = yes; then + function=__PRETTY_FUNCTION__ + else + if test "$gst_cv_have_function" = yes; then + function=__FUNCTION__ + else + if test "$gst_cv_have_func" = yes; then + function=__func__ + else + function=\"\" + fi + fi + fi + AC_DEFINE_UNQUOTED(GST_FUNCTION, $function, [macro to use to show function name]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-gettext.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-gettext.m4 new file mode 100644 index 0000000..a63651b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-gettext.m4 @@ -0,0 +1,21 @@ +dnl gettext setup + +dnl AG_GST_GETTEXT([gettext-package]) +dnl defines GETTEXT_PACKAGE and LOCALEDIR + +AC_DEFUN([AG_GST_GETTEXT], +[ + if test "$USE_NLS" = "yes"; then + GETTEXT_PACKAGE=[$1] + else + GETTEXT_PACKAGE=[NULL] + fi + AC_SUBST(GETTEXT_PACKAGE) + AC_DEFINE_UNQUOTED([GETTEXT_PACKAGE], "$GETTEXT_PACKAGE", + [gettext package name]) + + dnl define LOCALEDIR in config.h + AS_AC_EXPAND(LOCALEDIR, $datadir/locale) + AC_DEFINE_UNQUOTED([LOCALEDIR], "$LOCALEDIR", + [gettext locale dir]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-glib2.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-glib2.m4 new file mode 100644 index 0000000..bafba41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-glib2.m4 @@ -0,0 +1,73 @@ +dnl check for a minimum version of GLib + +dnl AG_GST_GLIB_CHECK([minimum-version-required]) + +AC_DEFUN([AG_GST_GLIB_CHECK], +[ + AC_REQUIRE([AS_NANO]) + + dnl Minimum required version of GLib + GLIB_REQ=[$1] + if test "x$GLIB_REQ" = "x" + then + AC_MSG_ERROR([Please specify a required version for GLib 2.0]) + fi + AC_SUBST(GLIB_REQ) + + dnl Check for glib with everything + AG_GST_PKG_CHECK_MODULES(GLIB, + glib-2.0 >= $GLIB_REQ gobject-2.0 gthread-2.0 gmodule-no-export-2.0) + + if test "x$HAVE_GLIB" = "xno"; then + AC_MSG_ERROR([This package requires GLib >= $GLIB_REQ to compile.]) + fi + + dnl Add define to tell GLib that threading is always enabled within GStreamer + dnl code (optimisation, bypasses checks if the threading system is enabled + dnl when using threading primitives) + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_THREADS_MANDATORY" + + dnl Define G_DISABLE_DEPRECATED for GIT versions + if test "x$PACKAGE_VERSION_NANO" = "x1"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_DEPRECATED" + fi + + AC_ARG_ENABLE(gobject-cast-checks, + AS_HELP_STRING([--enable-gobject-cast-checks[=@<:@no/auto/yes@:>@]], + [Enable GObject cast checks]),, + [enable_gobject_cast_checks=auto]) + + if test "x$enable_gobject_cast_checks" = "xauto"; then + dnl For releases, turn off the cast checks + if test "x$PACKAGE_VERSION_NANO" = "x1"; then + enable_gobject_cast_checks=yes + else + enable_gobject_cast_checks=no + fi + fi + + if test "x$enable_gobject_cast_checks" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_CAST_CHECKS" + fi + + AC_ARG_ENABLE(glib-asserts, + AS_HELP_STRING([--enable-glib-asserts[=@<:@no/auto/yes@:>@]], + [Enable GLib assertion]),, + [enable_glib_assertions=auto]) + + if test "x$enable_glib_assertions" = "xauto"; then + dnl For releases, turn off the assertions + if test "x$PACKAGE_VERSION_NANO" = "x1"; then + enable_glib_assertions=yes + else + enable_glib_assertions=no + fi + fi + + if test "x$enable_glib_assertions" = "xno"; then + GLIB_EXTRA_CFLAGS="$GLIB_EXTRA_CFLAGS -DG_DISABLE_ASSERT" + fi + + dnl for the poor souls who for example have glib in /usr/local + AS_SCRUB_INCLUDE(GLIB_CFLAGS) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-libxml2.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-libxml2.m4 new file mode 100644 index 0000000..4a843f0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-libxml2.m4 @@ -0,0 +1,52 @@ +dnl call this macro with the minimum required version as an argument +dnl this macro sets and AC_SUBSTs XML_CFLAGS and XML_LIBS +dnl it also sets LIBXML_PKG, used for the pkg-config file + +AC_DEFUN([AG_GST_LIBXML2_CHECK], +[ + dnl Minimum required version of libxml2 + dnl default to 2.4.9 if not specified + LIBXML2_REQ=ifelse([$1],,2.4.9,[$1]) + AC_SUBST(LIBXML2_REQ) + + dnl check for libxml2 + PKG_CHECK_MODULES(XML, libxml-2.0 >= $LIBXML2_REQ, + HAVE_LIBXML2=yes, [ + AC_MSG_RESULT(no) + HAVE_LIBXML2=no + ]) + if test "x$HAVE_LIBXML2" = "xyes"; then + AC_DEFINE(HAVE_LIBXML2, 1, [Define if libxml2 is available]) + else + AC_MSG_ERROR([ + Need libxml2 and development headers/files to build GStreamer. + + You can do without libxml2 if you pass --disable-loadsave to + configure, but that breaks ABI, so don't do that unless you + are building for an embedded setup and know what you are doing. + ]) + fi + dnl this is for the .pc file + LIBXML_PKG=', libxml-2.0' + AC_SUBST(LIBXML_PKG) + AC_SUBST(XML_LIBS) + AC_SUBST(XML_CFLAGS) + + dnl XML_LIBS might pull in -lz without zlib actually being on the system, so + dnl try linking with these LIBS and CFLAGS + ac_save_CFLAGS=$CFLAGS + ac_save_LIBS=$LIBS + CFLAGS="$CFLAGS $XML_CFLAGS" + LIBS="$LIBS $XML_LIBS" + AC_TRY_LINK([ +#include +#include +],[ +/* function body */ +], + AC_MSG_NOTICE([Test xml2 program linked]), + AC_MSG_ERROR([Could not link libxml2 test program. Check if you have the necessary dependencies.]) + ) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-package-release-datetime.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-package-release-datetime.m4 new file mode 100644 index 0000000..126919b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-package-release-datetime.m4 @@ -0,0 +1,89 @@ +dnl macros to set GST_PACKAGE_RELEASE_DATETIME + +dnl =========================================================================== +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME +dnl +dnl Usage: +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME() +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no]...) +dnl sets the release datetime to the current date +dnl (no = this is not a release, but git or prerelease) +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD]) +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [YYYY-MM-DD]) +dnl sets the release datetime to the specified date (and time, if given) +dnl (yes = this is a release, not git or prerelease) +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [DOAP-FILE], [RELEASE-VERSION]) +dnl sets the release date to the release date associated with version +dnl RELEASE-VERSION in the .doap file DOAP-FILE +dnl (yes = this is a release, not git or prerelease) +dnl +dnl We need to treat pre-releases like git because there won't be an entry +dnl in the .doap file for pre-releases yet, and we don't want to use the +dnl date of the last release either. +dnl =========================================================================== +AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME], +[ + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME() + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes]...) + if test "x$1" = "xno" -o "x$1" = "x"; then + GST_PACKAGE_RELEASE_DATETIME=`date -u "+%Y-%m-%dT%H:%MZ"` + elif test "x$1" = "xyes"; then + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], ["YYYY-MM-DD"]) + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([no], [DOAP-FILE], [RELEASE-VERSION]) + if ( echo $1 | grep -e '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=$1 + else + dnl we assume the .doap file contains the date as YYYY-MM-DD + YYYY_MM_DD=`sh "${srcdir}/common/extract-release-date-from-doap-file" $3 $2`; + if test "x$YYYY_MM_DD" != "x"; then + GST_PACKAGE_RELEASE_DATETIME=$YYYY_MM_DD + else + AC_MSG_ERROR([SET_PACKAGE_RELEASE_DATETIME: could not extract + release date for release version $3 from $2]) + GST_PACKAGE_RELEASE_DATETIME="" + fi + fi + dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([YYYY-MM-DD]) + elif ( echo $1 | grep -e '^20[1-9][0-9]-[0-1][0-9]-[0-3][0-9]' >/dev/null ) ; then + GST_PACKAGE_RELEASE_DATETIME=$1 + else + AC_MSG_WARN([SET_PACKAGE_RELEASE_DATETIME: invalid first argument]) + GST_PACKAGE_RELEASE_DATETIME="" + fi + + if test "x$GST_PACKAGE_RELEASE_DATETIME" = "x"; then + AC_MSG_WARN([Invalid package release date time: $GST_PACKAGE_RELEASE_DATETIME]) + else + AC_MSG_NOTICE([Setting GST_PACKAGE_RELEASE_DATETIME to $GST_PACKAGE_RELEASE_DATETIME]) + + AC_DEFINE_UNQUOTED([GST_PACKAGE_RELEASE_DATETIME], + ["$GST_PACKAGE_RELEASE_DATETIME"], + [GStreamer package release date/time for plugins as YYYY-MM-DD]) + fi +]) + +dnl =========================================================================== +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO +dnl +dnl Usage: +dnl +dnl AG_GST_SET_PACKAGE_RELEASE_DATETIME([NANO-VERSION], [DOAP-FILE], [RELEASE-VERSION]) +dnl if NANO-VERSION is 0, sets the release date to the release date associated +dnl with version RELEASE-VERSION in the .doap file DOAP-FILE, otherwise sets +dnl the release date and time to the current date/time. +dnl +dnl We need to treat pre-releases like git because there won't be an entry +dnl in the .doap file for pre-releases yet, and we don't want to use the +dnl date of the last release either. +dnl =========================================================================== +AC_DEFUN([AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO], +[ + if test "x$1" = "x0"; then + AG_GST_SET_PACKAGE_RELEASE_DATETIME([yes], [ $2 ], [ $3 ]) + else + AG_GST_SET_PACKAGE_RELEASE_DATETIME([no]) + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-parser.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-parser.m4 new file mode 100644 index 0000000..2cae45d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-parser.m4 @@ -0,0 +1,55 @@ +AC_DEFUN([AG_GST_BISON_CHECK], +[ + dnl FIXME: check if AC_PROG_YACC is suitable here + dnl FIXME: make precious + AC_PATH_PROG(BISON_PATH, bison, no) + if test x$BISON_PATH = xno; then + AC_MSG_ERROR(Could not find bison) + fi + + dnl check bison version + dnl we need version >= 1.875 for the reentrancy support + dnl in the parser. + dnl First lines observed: 'bison (GNU Bison) 2.3' or 'GNU Bison version 1.28' + bison_min_version=1.875 + bison_version=`$BISON_PATH --version | head -n 1 | sed 's/^[[^0-9]]*//' | sed 's/[[^0-9]]*$//' | cut -d' ' -f1` + AC_MSG_CHECKING([bison version $bison_version >= $bison_min_version]) + + if perl -we "exit ((v$bison_version ge v$bison_min_version) ? 0 : 1)"; then + AC_MSG_RESULT([yes]) + else + AC_MSG_ERROR([no]) + fi +]) + +AC_DEFUN([AG_GST_FLEX_CHECK], +[ + dnl we require flex for building the parser + AC_PATH_PROG(FLEX_PATH, flex, no) + if test x$FLEX_PATH = xno; then + AC_MSG_ERROR(Could not find flex) + fi + + dnl check flex version + dnl we need version >= 2.5.31 for the reentrancy support + dnl in the parser. + flex_min_version=2.5.31 + flex_version=`$FLEX_PATH --version | head -n 1 | sed 's/^.* //' | sed 's/[[a-zA-Z]]*$//' | cut -d' ' -f1` + AC_MSG_CHECKING([flex version $flex_version >= $flex_min_version]) + if perl -w < \$min_version_major) || + ((\$flex_version_major == \$min_version_major) && + (\$flex_version_minor > \$min_version_minor)) || + ((\$flex_version_major == \$min_version_major) && + (\$flex_version_minor == \$min_version_minor) && + (\$flex_version_micro >= \$min_version_micro))) + ? 0 : 1); +EOF + then + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([no]) + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-platform.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-platform.m4 new file mode 100644 index 0000000..40d6faf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-platform.m4 @@ -0,0 +1,67 @@ +dnl AG_GST_PLATFORM +dnl Check for platform specific features and define some variables +dnl +dnl GST_EXTRA_MODULE_SUFFIX: contains a platform specific +dnl extra module suffix additional to G_MODULE_SUFFIX +dnl +dnl HAVE_OSX: Defined if compiling for OS X +dnl +dnl GST_HAVE_UNSAFE_FORK: Defined if fork is unsafe (Windows) +dnl +dnl HAVE_WIN32: Defined if compiling on Win32 +dnl + +AC_DEFUN([AG_GST_PLATFORM], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + + case $host_os in + rhapsody*) + AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix]) + ;; + darwin*) + AC_DEFINE_UNQUOTED(GST_EXTRA_MODULE_SUFFIX, [".dylib"], [Extra platform specific plugin suffix]) + AC_DEFINE_UNQUOTED(HAVE_OSX, 1, [Defined if compiling for OSX]) + ;; + cygwin*) + AC_DEFINE_UNQUOTED(GST_HAVE_UNSAFE_FORK, 1, [Defined when registry scanning through fork is unsafe]) + ;; + mingw* | msvc* | mks*) + dnl HAVE_WIN32 currently means "disable POSIXisms". + AC_DEFINE_UNQUOTED(HAVE_WIN32, 1, [Defined if compiling for Windows]) + + dnl define __MSVCRT_VERSION__ version if not set already by the + dnl compiler (ie. mostly for mingw). This is needed for things like + dnl __stat64 to be available. If set by the compiler, ensure it's + dnl new enough - we need at least WinXP SP2. + AC_TRY_COMPILE([ ], [ return __MSVCRT_VERSION__; ], [ + AC_TRY_COMPILE([ ], [ + #if __MSVCRT_VERSION__ < 0x0601 + #error "MSVCRT too old" + #endif + ], [ + AC_MSG_NOTICE([MSVCRT version looks ok]) + ], [ + AC_MSG_ERROR([MSVCRT version too old, need at least WinXP SP2]) + ]) + ], [ + AC_MSG_NOTICE([Setting MSVCRT version to 0x0601]) + AC_DEFINE_UNQUOTED(__MSVCRT_VERSION__, 0x0601, [We need at least WinXP SP2 for __stat64]) + ]) + ;; + *) + ;; + esac +]) + +AC_DEFUN([AG_GST_LIBTOOL_PREPARE], +[ + dnl Persuade libtool to also link (-l) a 'pure' (DirectX) static lib, + dnl i.e. as opposed to only import lib with dll counterpart. + dnl Needs to be tweaked before libtool's checks. + case $host_os in + cygwin* | mingw*) + lt_cv_deplibs_check_method=pass_all + ;; + esac +]) \ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-plugin-docs.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-plugin-docs.m4 new file mode 100644 index 0000000..dcfd61d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-plugin-docs.m4 @@ -0,0 +1,21 @@ +dnl AG_GST_PLUGIN_DOCS([MINIMUM-GTK-DOC-VERSION],[MINIMUM-PYTHON-VERSION]) +dnl +dnl checks for prerequisites for the common/mangle-tmpl.py script +dnl used when building the plugin documentation + +AC_DEFUN([AG_GST_PLUGIN_DOCS], +[ + AC_BEFORE([GTK_DOC_CHECK],[$0])dnl check for gtk-doc first + AC_BEFORE([AS_PATH_PYTHON],[$1])dnl find python first + + build_plugin_docs=no + AC_MSG_CHECKING([whether to build plugin documentation]) + if test x$enable_gtk_doc = xyes; then + build_plugin_docs=yes + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no (gtk-doc disabled or not available)]) + fi + + AM_CONDITIONAL(ENABLE_PLUGIN_DOCS, test x$build_plugin_docs = xyes) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-plugindir.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-plugindir.m4 new file mode 100644 index 0000000..09989d0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-plugindir.m4 @@ -0,0 +1,17 @@ +dnl AG_GST_SET_PLUGINDIR + +dnl AC_DEFINE PLUGINDIR to the full location where plug-ins will be installed +dnl AC_SUBST plugindir, to be used in Makefile.am's + +AC_DEFUN([AG_GST_SET_PLUGINDIR], +[ + dnl define location of plugin directory + AS_AC_EXPAND(PLUGINDIR, ${libdir}/gstreamer-$GST_MAJORMINOR) + AC_DEFINE_UNQUOTED(PLUGINDIR, "$PLUGINDIR", + [directory where plugins are located]) + AC_MSG_NOTICE([Using $PLUGINDIR as the plugin install location]) + + dnl plugin directory configure-time variable for use in Makefile.am + plugindir="\$(libdir)/gstreamer-$GST_MAJORMINOR" + AC_SUBST(plugindir) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-valgrind.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-valgrind.m4 new file mode 100644 index 0000000..5c0d608 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-valgrind.m4 @@ -0,0 +1,35 @@ +AC_DEFUN([AG_GST_VALGRIND_CHECK], +[ + dnl valgrind inclusion + AC_ARG_ENABLE(valgrind, + AC_HELP_STRING([--disable-valgrind], [disable run-time valgrind detection]), + [ + case "${enableval}" in + yes) USE_VALGRIND="$USE_DEBUG" ;; + no) USE_VALGRIND=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-valgrind) ;; + esac], + [ + USE_VALGRIND="$USE_DEBUG" + ]) dnl Default value + + VALGRIND_REQ="3.0" + if test "x$USE_VALGRIND" = xyes; then + PKG_CHECK_MODULES(VALGRIND, valgrind >= $VALGRIND_REQ, + USE_VALGRIND="yes", + [ + USE_VALGRIND="no" + AC_MSG_RESULT([no]) + ]) + fi + + if test "x$USE_VALGRIND" = xyes; then + AC_DEFINE(HAVE_VALGRIND, 1, [Define if valgrind should be used]) + AC_MSG_NOTICE(Using extra code paths for valgrind) + fi + AC_SUBST(VALGRIND_CFLAGS) + AC_SUBST(VALGRIND_LIBS) + + AC_PATH_PROG(VALGRIND_PATH, valgrind, no) + AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno") +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst-x11.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst-x11.m4 new file mode 100644 index 0000000..d3baf2d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst-x11.m4 @@ -0,0 +1,70 @@ +dnl macros for X-related detections +dnl AC_SUBST's HAVE_X, X_CFLAGS, X_LIBS +AC_DEFUN([AG_GST_CHECK_X], +[ + AC_PATH_XTRA + ac_cflags_save="$CFLAGS" + ac_cppflags_save="$CPPFLAGS" + CFLAGS="$CFLAGS $X_CFLAGS" + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + dnl now try to find the HEADER + AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no") + + if test "x$HAVE_X" = "xno" + then + AC_MSG_NOTICE([cannot find X11 development files]) + else + dnl this is much more than we want + X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS" + dnl AC_PATH_XTRA only defines the path needed to find the X libs, + dnl it does not add the libs; therefore we add them here + X_LIBS="$X_LIBS -lX11" + AC_SUBST(X_CFLAGS) + AC_SUBST(X_LIBS) + fi + AC_SUBST(HAVE_X) + + CFLAGS="$ac_cflags_save" + CPPFLAGS="$ac_cppflags_save" +]) + +dnl *** XVideo *** +dnl Look for the PIC library first, Debian requires it. +dnl Check debian-devel archives for gory details. +dnl 20020110: +dnl At the moment XFree86 doesn't distribute shared libXv due +dnl to unstable API. On many platforms you CAN NOT link a shared +dnl lib to a static non-PIC lib. This is what the xvideo GStreamer +dnl plug-in wants to do. So Debian distributes a PIC compiled +dnl version of the static lib for plug-ins to link to when it is +dnl inappropriate to link the main application to libXv directly. +dnl FIXME: add check if this platform can support linking to a +dnl non-PIC libXv, if not then don not use Xv. +dnl FIXME: perhaps warn user if they have a shared libXv since +dnl this is an error until XFree86 starts shipping one +AC_DEFUN([AG_GST_CHECK_XV], +[ + if test x$HAVE_X = xyes; then + AC_CHECK_LIB(Xv_pic, XvQueryExtension, + HAVE_XVIDEO="yes", HAVE_XVIDEO="no", + $X_LIBS -lXext) + + if test x$HAVE_XVIDEO = xyes; then + XVIDEO_LIBS="-lXv_pic -lXext" + AC_SUBST(XVIDEO_LIBS) + else + dnl try again using something else if we didn't find it first + if test x$HAVE_XVIDEO = xno; then + AC_CHECK_LIB(Xv, XvQueryExtension, + HAVE_XVIDEO="yes", HAVE_XVIDEO="no", + $X_LIBS -lXext) + + if test x$HAVE_XVIDEO = xyes; then + XVIDEO_LIBS="-lXv -lXext" + AC_SUBST(XVIDEO_LIBS) + fi + fi + fi + fi +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gst.m4 b/gst-plugins-base-subtitles0.10/common/m4/gst.m4 new file mode 100644 index 0000000..ddfde51 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gst.m4 @@ -0,0 +1,31 @@ +dnl AG_GST_INIT +dnl sets up use of GStreamer configure.ac macros +dnl all GStreamer autoconf macros are prefixed +dnl with AG_GST_ for public macros +dnl with _AG_GST_ for private macros + +AC_DEFUN([AG_GST_INIT], +[ + m4_pattern_forbid(^_?AG_GST_) +]) + +dnl AG_GST_PKG_CONFIG_PATH +dnl +dnl sets up a GST_PKG_CONFIG_PATH variable for use in Makefile.am +dnl which contains the path of the in-tree pkgconfig directory first +dnl and then any paths specified in PKG_CONFIG_PATH. +dnl +dnl We do this mostly so we don't have to use unportable shell constructs +dnl such as ${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH} in Makefile.am to handle +dnl the case where the environment variable is not set, but also in order +dnl to avoid a trailing ':' in the PKG_CONFIG_PATH which apparently causes +dnl problems with pkg-config on windows with msys/mingw. +AC_DEFUN([AG_GST_PKG_CONFIG_PATH], +[ + GST_PKG_CONFIG_PATH="\$(top_builddir)/pkgconfig" + if test "x$PKG_CONFIG_PATH" != "x"; then + GST_PKG_CONFIG_PATH="$GST_PKG_CONFIG_PATH:$PKG_CONFIG_PATH" + fi + AC_SUBST([GST_PKG_CONFIG_PATH]) + AC_MSG_NOTICE([Using GST_PKG_CONFIG_PATH = $GST_PKG_CONFIG_PATH]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/gtk-doc.m4 b/gst-plugins-base-subtitles0.10/common/m4/gtk-doc.m4 new file mode 100644 index 0000000..39a4e7d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/gtk-doc.m4 @@ -0,0 +1,42 @@ +dnl -*- mode: autoconf -*- + +# serial 1 + +dnl Usage: +dnl GTK_DOC_CHECK([minimum-gtk-doc-version]) +AC_DEFUN([GTK_DOC_CHECK], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + dnl for overriding the documentation installation directory + AC_ARG_WITH([html-dir], + AS_HELP_STRING([--with-html-dir=PATH], [path to installed docs]),, + [with_html_dir='${datadir}/gtk-doc/html']) + HTML_DIR="$with_html_dir" + AC_SUBST([HTML_DIR]) + + dnl enable/disable documentation building + AC_ARG_ENABLE([gtk-doc], + AS_HELP_STRING([--enable-gtk-doc], + [use gtk-doc to build documentation [[default=no]]]),, + [enable_gtk_doc=no]) + + if test x$enable_gtk_doc = xyes; then + ifelse([$1],[], + [PKG_CHECK_EXISTS([gtk-doc],, + AC_MSG_ERROR([gtk-doc not installed and --enable-gtk-doc requested]))], + [PKG_CHECK_EXISTS([gtk-doc >= $1],, + AC_MSG_ERROR([You need to have gtk-doc >= $1 installed to build gtk-doc]))]) + if test -z "$SED"; then + AC_PROG_SED + fi + fi + + AC_MSG_CHECKING([whether to build gtk-doc documentation]) + AC_MSG_RESULT($enable_gtk_doc) + + AC_PATH_PROGS(GTKDOC_CHECK,gtkdoc-check,) + + AM_CONDITIONAL([ENABLE_GTK_DOC], [test x$enable_gtk_doc = xyes]) + AM_CONDITIONAL([GTK_DOC_USE_LIBTOOL], [test -n "$LIBTOOL"]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/introspection.m4 b/gst-plugins-base-subtitles0.10/common/m4/introspection.m4 new file mode 100644 index 0000000..f9ce49c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/introspection.m4 @@ -0,0 +1,88 @@ +dnl -*- mode: autoconf -*- +dnl Copyright 2009 Johan Dahlin +dnl +dnl This file is free software; the author(s) gives unlimited +dnl permission to copy and/or distribute it, with or without +dnl modifications, as long as this notice is preserved. +dnl + +# serial 1 + +m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL], +[ + AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first + AC_BEFORE([LT_INIT],[$0])dnl setup libtool first + + dnl enable/disable introspection + m4_if([$2], [require], + [dnl + enable_introspection=yes + ],[dnl + AC_ARG_ENABLE(introspection, + AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]], + [Enable introspection for this build]),, + [enable_introspection=auto]) + ])dnl + + AC_MSG_CHECKING([for gobject-introspection]) + + dnl presence/version checking + AS_CASE([$enable_introspection], + [no], [dnl + found_introspection="no (disabled, use --enable-introspection to enable)" + ],dnl + [yes],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0],, + AC_MSG_ERROR([gobject-introspection-1.0 is not installed])) + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], + found_introspection=yes, + AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME])) + ],dnl + [auto],[dnl + PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no) + ],dnl + [dnl + AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@]) + ])dnl + + AC_MSG_RESULT([$found_introspection]) + + INTROSPECTION_SCANNER= + INTROSPECTION_COMPILER= + INTROSPECTION_GENERATE= + INTROSPECTION_GIRDIR= + INTROSPECTION_TYPELIBDIR= + if test "x$found_introspection" = "xyes"; then + INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` + INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0` + INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0` + INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)" + fi + AC_SUBST(INTROSPECTION_SCANNER) + AC_SUBST(INTROSPECTION_COMPILER) + AC_SUBST(INTROSPECTION_GENERATE) + AC_SUBST(INTROSPECTION_GIRDIR) + AC_SUBST(INTROSPECTION_TYPELIBDIR) + + AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes") +]) + + +dnl Usage: +dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version]) + +AC_DEFUN([GOBJECT_INTROSPECTION_CHECK], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1]) +]) + +dnl Usage: +dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version]) + + +AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE], +[ + _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require]) +]) diff --git a/gst-plugins-base-subtitles0.10/common/m4/orc.m4 b/gst-plugins-base-subtitles0.10/common/m4/orc.m4 new file mode 100644 index 0000000..3b2c6b5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/orc.m4 @@ -0,0 +1,68 @@ +dnl pkg-config-based checks for Orc + +dnl specific: +dnl ORC_CHECK([REQUIRED_VERSION]) + +AC_DEFUN([ORC_CHECK], +[ + ORC_REQ=ifelse([$1], , "0.4.6", [$1]) + + AC_ARG_ENABLE(orc, + AC_HELP_STRING([--enable-orc],[use Orc if installed]), + [case "${enableval}" in + auto) enable_orc=auto ;; + yes) enable_orc=yes ;; + no) enable_orc=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-orc) ;; + esac + ], + [enable_orc=auto]) dnl Default value + + if test "x$enable_orc" != "xno" ; then + PKG_CHECK_MODULES(ORC, orc-0.4 >= $ORC_REQ, [ + AC_DEFINE(HAVE_ORC, 1, [Use Orc]) + if test "x$ORCC" = "x" ; then + ORCC=`$PKG_CONFIG --variable=orcc orc-0.4` + fi + AC_SUBST(ORCC) + ORCC_FLAGS="--compat $ORC_REQ" + AC_SUBST(ORCC_FLAGS) + HAVE_ORC=yes + HAVE_ORCC=yes + if test "x$cross_compiling" = "xyes" ; then + HAVE_ORCC=no + fi + ], [ + if test "x$enable_orc" = "xyes" ; then + AC_MSG_ERROR([--enable-orc specified, but Orc >= $ORC_REQ not found]) + fi + AC_DEFINE(DISABLE_ORC, 1, [Disable Orc]) + HAVE_ORC=no + HAVE_ORCC=no + ]) + else + AC_DEFINE(DISABLE_ORC, 1, [Disable Orc]) + HAVE_ORC=no + HAVE_ORCC=no + fi + AM_CONDITIONAL(HAVE_ORC, [test "x$HAVE_ORC" = "xyes"]) + AM_CONDITIONAL(HAVE_ORCC, [test "x$HAVE_ORCC" = "xyes"]) + +])) + +AC_DEFUN([ORC_OUTPUT], +[ + if test "$HAVE_ORC" = yes ; then + printf "configure: *** Orc acceleration enabled.\n" + else + if test "x$enable_orc" = "xno" ; then + printf "configure: *** Orc acceleration disabled by --disable-orc. Slower code paths\n" + printf " will be used.\n" + else + printf "configure: *** Orc acceleration disabled. Requires Orc >= $ORC_REQ, which was\n" + printf " not found. Slower code paths will be used.\n" + fi + fi + printf "\n" +]) + diff --git a/gst-plugins-base-subtitles0.10/common/m4/pkg.m4 b/gst-plugins-base-subtitles0.10/common/m4/pkg.m4 new file mode 100644 index 0000000..996e294 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/m4/pkg.m4 @@ -0,0 +1,157 @@ +# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +# +# Copyright © 2004 Scott James Remnant . +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# PKG_PROG_PKG_CONFIG([MIN-VERSION]) +# ---------------------------------- +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi + +fi[]dnl +])# PKG_PROG_PKG_CONFIG + +# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# +# Check to see whether a particular set of modules exists. Similar +# to PKG_CHECK_MODULES(), but does not set variables or print errors. +# +# +# Similar to PKG_CHECK_MODULES, make sure that the first instance of +# this or PKG_CHECK_MODULES is called, or make sure to call +# PKG_CHECK_EXISTS manually +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_ifval([$2], [$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + + +# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +# --------------------------------------------- +m4_define([_PKG_CONFIG], +[if test -n "$PKG_CONFIG"; then + if test -n "$$1"; then + pkg_cv_[]$1="$$1" + else + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], + [pkg_failed=yes]) + fi +else + pkg_failed=untried +fi[]dnl +])# _PKG_CONFIG + +# _PKG_SHORT_ERRORS_SUPPORTED +# ----------------------------- +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])# _PKG_SHORT_ERRORS_SUPPORTED + + +# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +# [ACTION-IF-NOT-FOUND]) +# +# +# Note that if there is a possibility the first call to +# PKG_CHECK_MODULES might not happen, you should be sure to include an +# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +# +# +# -------------------------------------------------------------- +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + ifelse([$4], , [AC_MSG_ERROR(dnl +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT +])], + [AC_MSG_RESULT([no]) + $4]) +elif test $pkg_failed = untried; then + ifelse([$4], , [AC_MSG_FAILURE(dnl +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])], + [$4]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + ifelse([$3], , :, [$3]) +fi[]dnl +])# PKG_CHECK_MODULES diff --git a/gst-plugins-base-subtitles0.10/common/mangle-tmpl.py b/gst-plugins-base-subtitles0.10/common/mangle-tmpl.py new file mode 100644 index 0000000..bd4f948 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/mangle-tmpl.py @@ -0,0 +1,163 @@ +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +use the output from gst-xmlinspect.py to mangle tmpl/*.sgml and +insert/overwrite Short Description and Long Description +""" + +# FIXME: right now it uses pygst and scans on its own; +# we really should use inspect/*.xml instead since the result of +# gst-xmlinspect.py is committed by the docs maintainer, who can be +# expected to have pygst, but this step should be done for every docs build, +# so no pygst allowed + +# read in inspect/*.xml +# for every tmpl/element-(name).xml: mangle with details from element + +import glob +import re +import sys +import os + +class Tmpl: + def __init__(self, filename): + self.filename = filename + self._sectionids = [] + self._sections = {} + + def read(self): + """ + Read and parse the sections from the given file. + """ + lines = open(self.filename).readlines() + matcher = re.compile("\n") + id = None + + for line in lines: + match = matcher.search(line) + if match: + id = match.expand("\\1") + self._sectionids.append(id) + self._sections[id] = [] + else: + if not id: + sys.stderr.write( + "WARNING: line before a SECTION header: %s" % line) + else: + self._sections[id].append(line) + + def get_section(self, id): + """ + Get the content from the given section. + """ + return self._sections[id] + + def set_section(self, id, content): + """ + Replace the given section id with the given content. + """ + self._sections[id] = content + + def output(self): + """ + Return the output of the current template in the tmpl/*.sgml format. + """ + lines = [] + for id in self._sectionids: + lines.append("\n" % id) + for line in self._sections[id]: + lines.append(line) + + return "".join(lines) + + def write(self, backup=False): + """ + Write out the template file again, backing up the previous one. + """ + if backup: + target = self.filename + ".mangle.bak" + os.rename(self.filename, target) + + handle = open(self.filename, "w") + handle.write(self.output()) + handle.close() + +import xml.dom.minidom + +def get_elements(file): + elements = {} + doc = xml.dom.minidom.parse(file) + + elem = None + for e in doc.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'plugin': + elem = e + break + if elem == None: + return None + + elem2 = None + for e in elem.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'elements': + elem2 = e + break + if elem2 == None: + return None + + elem = elem2 + + for e in elem.childNodes: + if e.nodeType == e.ELEMENT_NODE and e.localName == 'element': + name = None + description = None + + for e2 in e.childNodes: + if e2.nodeType == e2.ELEMENT_NODE and e2.localName == 'name': + name = e2.childNodes[0].nodeValue.encode("UTF-8") + elif e2.nodeType == e2.ELEMENT_NODE and e2.localName == 'description': + if e2.childNodes: + description = e2.childNodes[0].nodeValue.encode("UTF-8") + else: + description = 'No description' + + if name != None and description != None: + elements[name] = {'description': description} + + return elements + +def main(): + if not len(sys.argv) == 3: + sys.stderr.write('Please specify the inspect/ dir and the tmpl/ dir') + sys.exit(1) + + inspectdir = sys.argv[1] + tmpldir = sys.argv[2] + + # parse all .xml files; build map of element name -> short desc + #for file in glob.glob("inspect/plugin-*.xml"): + elements = {} + for file in glob.glob("%s/plugin-*.xml" % inspectdir): + elements.update(get_elements(file)) + + for file in glob.glob("%s/element-*.sgml" % tmpldir): + base = os.path.basename(file) + element = base[len("element-"):-len(".sgml")] + tmpl = Tmpl(file) + tmpl.read() + if element in elements.keys(): + description = elements[element]['description'] + tmpl.set_section("Short_Description", "%s\n\n" % description) + + # put in an include if not yet there + line = '' + \ + '' + \ + '\n' + section = tmpl.get_section("Long_Description") + if not section[0] == line: + section.insert(0, line) + tmpl.set_section("Long_Description", section) + tmpl.write() + +main() diff --git a/gst-plugins-base-subtitles0.10/common/orc.mak b/gst-plugins-base-subtitles0.10/common/orc.mak new file mode 100644 index 0000000..a232b5d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/orc.mak @@ -0,0 +1,76 @@ +# +# This is a makefile.am fragment to build Orc code. +# +# Define ORC_SOURCE and then include this file, such as: +# +# ORC_SOURCE=gstadderorc +# include $(top_srcdir)/common/orc.mak +# +# This fragment will create tmp-orc.c and gstadderorc.h from +# gstadderorc.orc. +# +# When 'make dist' is run at the top level, or 'make orc-update' +# in a directory including this fragment, the generated source +# files will be copied to $(ORC_SOURCE)-dist.[ch]. These files +# should be checked in to git, since they are used if Orc is +# disabled. +# +# Note that this file defines BUILT_SOURCES, so any later usage +# of BUILT_SOURCES in the Makefile.am that includes this file +# must use '+='. +# + + +EXTRA_DIST = $(ORC_SOURCE).orc + +ORC_NODIST_SOURCES = tmp-orc.c $(ORC_SOURCE).h +BUILT_SOURCES = tmp-orc.c $(ORC_SOURCE).h + + +orc-update: tmp-orc.c $(ORC_SOURCE).h + $(top_srcdir)/common/gst-indent tmp-orc.c + cp tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c + cp $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h + +orcc_v_gen = $(orcc_v_gen_$(V)) +orcc_v_gen_ = $(orcc_v_gen_$(AM_DEFAULT_VERBOSITY)) +orcc_v_gen_0 = @echo " ORCC $@"; + +cp_v_gen = $(cp_v_gen_$(V)) +cp_v_gen_ = $(cp_v_gen_$(AM_DEFAULT_VERBOSITY)) +cp_v_gen_0 = @echo " CP $@"; + +if HAVE_ORCC +tmp-orc.c: $(srcdir)/$(ORC_SOURCE).orc + $(orcc_v_gen)$(ORCC) $(ORCC_FLAGS) --implementation --include glib.h -o tmp-orc.c $(srcdir)/$(ORC_SOURCE).orc + +$(ORC_SOURCE).h: $(srcdir)/$(ORC_SOURCE).orc + $(orcc_v_gen)$(ORCC) $(ORCC_FLAGS) --header --include glib.h -o $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE).orc +else +tmp-orc.c: $(srcdir)/$(ORC_SOURCE).orc $(srcdir)/$(ORC_SOURCE)-dist.c + $(cp_v_gen)cp $(srcdir)/$(ORC_SOURCE)-dist.c tmp-orc.c + +$(ORC_SOURCE).h: $(srcdir)/$(ORC_SOURCE).orc $(srcdir)/$(ORC_SOURCE)-dist.c + $(cp_v_gen)cp $(srcdir)/$(ORC_SOURCE)-dist.h $(ORC_SOURCE).h +endif + +clean-local: clean-orc +.PHONY: clean-orc +clean-orc: + rm -f tmp-orc.c $(ORC_SOURCE).h + +dist-hook: dist-hook-orc +.PHONY: dist-hook-orc + +# we try and copy updated orc -dist files below, but don't fail if it +# doesn't work as the srcdir might not be writable +dist-hook-orc: tmp-orc.c $(ORC_SOURCE).h + $(top_srcdir)/common/gst-indent tmp-orc.c + rm -f tmp-orc.c~ + cmp -s tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c || \ + cp tmp-orc.c $(srcdir)/$(ORC_SOURCE)-dist.c || true + cmp -s $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h || \ + cp $(ORC_SOURCE).h $(srcdir)/$(ORC_SOURCE)-dist.h || true + cp -p tmp-orc.c $(distdir)/$(ORC_SOURCE)-dist.c + cp -p $(ORC_SOURCE).h $(distdir)/$(ORC_SOURCE)-dist.h + diff --git a/gst-plugins-base-subtitles0.10/common/parallel-subdirs.mak b/gst-plugins-base-subtitles0.10/common/parallel-subdirs.mak new file mode 100644 index 0000000..36885df --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/parallel-subdirs.mak @@ -0,0 +1,13 @@ +# include this at the end of $MODULE/ext/Makefile.am to force make to +# build subdirectories in parallel when make -jN is used. We will end up +# descending into all subdirectories a second time, but only after the first +# (parallel) run has finished, so it should go right through the second time. + +.PHONY: independent-subdirs $(SUBDIRS) + +independent-subdirs: $(SUBDIRS) + +$(SUBDIRS): + $(MAKE) -C $@ + +all-recursive: independent-subdirs diff --git a/gst-plugins-base-subtitles0.10/common/plugins.xsl b/gst-plugins-base-subtitles0.10/common/plugins.xsl new file mode 100644 index 0000000..60515b6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/plugins.xsl @@ -0,0 +1,209 @@ + + + + + + + + + + + + -plugins- + + + + + + + + + + + + + + Element Information + + + + + plugin + + + + plugin- + + + + + + + + author + + + + + + + class + + + + + + + + + + Element Pads + + + + + name + + + + + + + direction + + + + + + + presence + + + + + + + + + details + + + + + + + + + + + + + + + + + + + + + -plugins-plugin- + + + + + + 3 + FIXME Library + + + + + + + + + + plugin- + + + + + + + Plugin Information + + + + filename + + + + + + + version + + + + + + + run-time license + + + + + + + package + + + + + + + origin + + + + + + + + + + + + + + + + + + + + + + + Elements + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/common/po.mak b/gst-plugins-base-subtitles0.10/common/po.mak new file mode 100644 index 0000000..e019fac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/po.mak @@ -0,0 +1,4 @@ +# rule to download the latest .po files +download-po: $(top_srcdir)/common/download-translations + $(top_srcdir)/common/download-translations $(PACKAGE) + diff --git a/gst-plugins-base-subtitles0.10/common/release.mak b/gst-plugins-base-subtitles0.10/common/release.mak new file mode 100644 index 0000000..4a9b7d5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/release.mak @@ -0,0 +1,25 @@ +# include this snippet to add a common release: target by using +# include $(top_srcdir)/common/release.mak + +# make bz2 as well +AUTOMAKE_OPTIONS = dist-bzip2 + +release: dist + $(MAKE) $(PACKAGE)-$(VERSION).tar.gz.md5 + $(MAKE) $(PACKAGE)-$(VERSION).tar.bz2.md5 + +# generate md5 sum files +%.md5: % + md5sum $< > $@ + +# check that no marshal or enumtypes files are included +# this in turn ensures that distcheck fails for missing .list files which is currently +# shadowed when the corresponding .c and .h files are included. +distcheck-hook: + @test "x" = "x`find $(distdir) -name \*-enumtypes.[ch] | grep -v win32`" && \ + test "x" = "x`find $(distdir) -name \*-marshal.[ch]`" || \ + ( $(ECHO) "*** Leftover enumtypes or marshal files in the tarball." && \ + $(ECHO) "*** Make sure the following files are not disted:" && \ + find $(distdir) -name \*-enumtypes.[ch] | grep -v win32 && \ + find $(distdir) -name \*-marshal.[ch] && \ + false ) diff --git a/gst-plugins-base-subtitles0.10/common/scangobj-merge.py b/gst-plugins-base-subtitles0.10/common/scangobj-merge.py new file mode 100755 index 0000000..5e84235 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/scangobj-merge.py @@ -0,0 +1,280 @@ +#!/usr/bin/python +# -*- Mode: Python -*- +# vi:si:et:sw=4:sts=4:ts=4 + +""" +parse, update and write .signals and .args files +""" + +import sys +import os + +def debug(*args): + pass + +# OrderedDict class based on +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 +# Licensed under the Python License +class OrderedDict(dict): + def __init__(self, dict = None): + self._keys = [] + dict.__init__(self, dict) + + def __delitem__(self, key): + dict.__delitem__(self, key) + self._keys.remove(key) + + def __setitem__(self, key, item): + dict.__setitem__(self, key, item) + if key not in self._keys: self._keys.append(key) + + def clear(self): + dict.clear(self) + self._keys = [] + + def copy(self): + dict = dict.copy(self) + dict._keys = self._keys[:] + return dict + + def items(self): + return zip(self._keys, self.values()) + + def keys(self): + return self._keys + + def popitem(self): + try: + key = self._keys[-1] + except IndexError: + raise KeyError('dictionary is empty') + + val = self[key] + del self[key] + + return (key, val) + + def setdefault(self, key, failobj = None): + dict.setdefault(self, key, failobj) + if key not in self._keys: self._keys.append(key) + + def update(self, dict): + dict.update(self, dict) + for key in dict.keys(): + if key not in self._keys: self._keys.append(key) + + def values(self): + return map(self.get, self._keys) + +class Object: + def __init__(self, name): + self._signals = OrderedDict() + self._args = OrderedDict() + self.name = name + + def __repr__(self): + return "" % self.name + + def add_signal(self, signal, overwrite=True): + if not overwrite and self._signals.has_key(signal.name): + raise IndexError, "signal %s already in %r" % (signal.name, self) + self._signals[signal.name] = signal + + def add_arg(self, arg, overwrite=True): + if not overwrite and self._args.has_key(arg.name): + raise IndexError, "arg %s already in %r" % (arg.name, self) + self._args[arg.name] = arg + +class Docable: + def __init__(self, **kwargs): + for key in self.attrs: + setattr(self, key, kwargs[key]) + self.dict = kwargs + + def __repr__(self): + return "<%r %s>" % (str(self.__class__), self.name) + +class Signal(Docable): + attrs = ['name', 'returns', 'args'] + +class Arg(Docable): + attrs = ['name', 'type', 'range', 'flags', 'nick', 'blurb', 'default'] + +class GDoc: + def load_file(self, filename): + try: + lines = open(filename).readlines() + self.load_data("".join(lines)) + except IOError: + print "WARNING - could not read from %s" % filename + + def save_file(self, filename, backup=False): + """ + Save the signals information to the given .signals file if the + file content changed. + """ + olddata = None + try: + lines = open(filename).readlines() + olddata = "".join(lines) + except IOError: + print "WARNING - could not read from %s" % filename + newdata = self.get_data() + if olddata and olddata == newdata: + return + + if olddata: + if backup: + os.rename(filename, filename + '.bak') + + handle = open(filename, "w") + handle.write(newdata) + handle.close() + +class Signals(GDoc): + def __init__(self): + self._objects = OrderedDict() + + def load_data(self, data): + """ + Load the .signals lines, creating our list of objects and signals. + """ + import re + smatcher = re.compile( + '(?s)' # make . match \n + '\n(.*?)\n' + ) + nmatcher = re.compile( + '' + '(?P\S*)' # store object + '::' + '(?P\S*)' # store signal + '' + ) + rmatcher = re.compile( + '(?s)' # make . match \n + '(?P\S*)\n' # store returns + '(?P.*)' # store args + ) + for block in smatcher.findall(data): + nmatch = nmatcher.search(block) + if nmatch: + o = nmatch.group('object') + debug("Found object", o) + debug("Found signal", nmatch.group('signal')) + if not self._objects.has_key(o): + object = Object(o) + self._objects[o] = object + + rmatch = rmatcher.search(block) + if rmatch: + dict = rmatch.groupdict().copy() + dict['name'] = nmatch.group('signal') + signal = Signal(**dict) + self._objects[o].add_signal(signal) + + def get_data(self): + lines = [] + for o in self._objects.values(): + for s in o._signals.values(): + block = """ +%(object)s::%(name)s +%(returns)s +%(args)s +""" + d = s.dict.copy() + d['object'] = o.name + lines.append(block % d) + + return "\n".join(lines) + '\n' + +class Args(GDoc): + def __init__(self): + self._objects = OrderedDict() + + def load_data(self, data): + """ + Load the .args lines, creating our list of objects and args. + """ + import re + amatcher = re.compile( + '(?s)' # make . match \n + '\n(.*?)\n' + ) + nmatcher = re.compile( + '' + '(?P\S*)' # store object + '::' + '(?P\S*)' # store arg + '' + ) + rmatcher = re.compile( + '(?s)' # make . match \n + '(?P\S*)\n' # store type + '(?P.*?)\n' # store range + '(?P\S*)\n' # store flags + '(?P.*?)\n' # store nick + '(?P.*?)\n' # store blurb + '(?P.*?)\n' # store default + ) + for block in amatcher.findall(data): + nmatch = nmatcher.search(block) + if nmatch: + o = nmatch.group('object') + debug("Found object", o) + debug("Found arg", nmatch.group('arg')) + if not self._objects.has_key(o): + object = Object(o) + self._objects[o] = object + + rmatch = rmatcher.search(block) + if rmatch: + dict = rmatch.groupdict().copy() + dict['name'] = nmatch.group('arg') + arg = Arg(**dict) + self._objects[o].add_arg(arg) + else: + print "ERROR: could not match arg from block %s" % block + + def get_data(self): + lines = [] + for o in self._objects.values(): + for a in o._args.values(): + block = """ +%(object)s::%(name)s +%(type)s +%(range)s +%(flags)s +%(nick)s +%(blurb)s +%(default)s + +""" + d = a.dict.copy() + d['object'] = o.name + lines.append(block % d) + + return "\n".join(lines) + '\n' + +def main(argv): + modulename = None + try: + modulename = argv[1] + except IndexError: + sys.stderr.write('Please provide a documentation module name\n') + sys.exit(1) + + print "Merging scangobj output for %s" % modulename + signals = Signals() + signals.load_file(modulename + '.signals') + signals.load_file(modulename + '.signals.new') + signals.save_file(modulename + '.signals', backup=True) + os.unlink(modulename + '.signals.new') + + args = Args() + args.load_file(modulename + '.args') + args.load_file(modulename + '.args.new') + args.save_file(modulename + '.args', backup=True) + os.unlink(modulename + '.args.new') + +main(sys.argv) diff --git a/gst-plugins-base-subtitles0.10/common/update-common b/gst-plugins-base-subtitles0.10/common/update-common new file mode 100755 index 0000000..0d56dcd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/update-common @@ -0,0 +1,65 @@ +#!/bin/sh +# +# This script will update all the modules listed below so that +# common points to master in the common module. +# +# If you have many of the GStreamer modules checked out in a particular +# directory, it's best to run this script from that directory. For +# example, I check everything out in ~/gst, so this file is +# ~/gst/common/update-common. To do an update, I do +# 'cd ~/gst ; ./common/update-common'. This will automatically use +# the refs in your existing checkout when cloning the temporary +# checkout. Alternatively, you can use the reference variable below. +# + +# Set this variable to point to any directory containing existing +# git # checkouts, and git will pull objects from there, decreasing +# network usage. +reference=~/gst + +set -e +set -x + +modules="gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad \ + gst-plugins-ugly gst-ffmpeg gst-python \ + gnonlin gst-plugins-gl gst-rtsp-server gst-editing-services" + +topdir=`pwd` +dir=`mktemp -d $topdir/common-update-XXXXXX` + +for module in $modules +do + cd $dir + if test -e $reference/$module/.git ; then + git clone --reference $reference/$module/.git --shared ssh://git.freedesktop.org/git/gstreamer/$module + elif test -e $topdir/$module/.git ; then + git clone --reference $topdir/$module/.git --shared ssh://git.freedesktop.org/git/gstreamer/$module + else + git clone ssh://git.freedesktop.org/git/gstreamer/$module + fi + cd $dir/$module + git submodule init + git submodule update + cd $dir/$module/common + ref_from=`git log --pretty=format:%h -n 1 HEAD` + git checkout master + git pull origin + ref_to=`git log --pretty=format:%h -n 1 HEAD` + echo updating common from $ref_from to $ref_to + if [ "$ref_from" != "$ref_to" ] ; then + cd $dir/$module + git add common + git commit -m "Automatic update of common submodule + +From $ref_from to $ref_to" + fi + cd $dir +done + +for module in $modules +do + cd $dir/$module + git push origin +done + +rm -rf $dir diff --git a/gst-plugins-base-subtitles0.10/common/upload-doc.mak b/gst-plugins-base-subtitles0.10/common/upload-doc.mak new file mode 100644 index 0000000..3bf9496 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/upload-doc.mak @@ -0,0 +1,66 @@ +# this snippet is to be included by both our docbook manuals +# and gtk-doc API references + +# it adds an upload target to each of these dir's Makefiles + +# each Makefile.am should define the following variables: +# - DOC: the base name of the documentation +# (faq, manual, pwg, gstreamer, gstreamer-libs) +# - FORMATS: the formats in which DOC is output +# (html ps pdf) + +# if you want to use it, make sure your $HOME/.ssh/config file contains the +# correct User entry for the Host entry for the DOC_SERVER + +# these variables define the location of the online docs +DOC_SERVER = gstreamer.freedesktop.org +DOC_BASE = /srv/gstreamer.freedesktop.org/www/data/doc +DOC_URL = $(DOC_SERVER):$(DOC_BASE) + +upload: $(FORMATS) + @if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Preparing docs for upload (rebasing cross-references) ..." ; \ + if test x$(builddir) != x$(srcdir); then \ + echo "make upload can only be used if srcdir == builddir"; \ + exit 1; \ + fi; \ + # gtkdoc-rebase sometimes gets confused, so reset everything to \ + # local links before rebasing to online links \ + gtkdoc-rebase --html-dir=$(builddir)/html 2>/dev/null 2>/dev/null ; \ + rebase=`gtkdoc-rebase --verbose --online --html-dir=$(builddir)/html` ; \ + echo "$$rebase" | grep -e "On-*line"; \ + for req in glib gobject gstreamer gstreamer-libs gst-plugins-base-libs; do \ + if ! ( echo "$$rebase" | grep -i -e "On-*line.*/$$req/" ); then \ + echo "===============================================================================" ; \ + echo " Could not determine online location for $$req docs. Cross-referencing will be " ; \ + echo " broken, so not uploading. Make sure the library's gtk-doc documentation is " ; \ + echo " installed somewhere in /usr/share/gtk-doc. " ; \ + echo "===============================================================================" ; \ + exit 1; \ + fi; \ + done; \ + export SRC="$$SRC html"; \ + fi; \ + if echo $(FORMATS) | grep ps > /dev/null; then export SRC="$$SRC $(DOC).ps"; fi; \ + if echo $(FORMATS) | grep pdf > /dev/null; then export SRC="$$SRC $(DOC).pdf"; fi; \ + \ + # upload releases to both 0.10.X/ and head/ subdirectories \ + if test "x$(PACKAGE_VERSION_NANO)" = x0; then \ + export DIR=$(DOC_BASE)/gstreamer/$(VERSION)/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + fi; \ + \ + export DIR=$(DOC_BASE)/gstreamer/head/$(DOC); \ + echo Uploading $$SRC to $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) mkdir -p $$DIR; \ + rsync -rv -e ssh --delete $$SRC $(DOC_SERVER):$$DIR; \ + ssh $(DOC_SERVER) chmod -R g+w $$DIR; \ + \ + if echo $(FORMATS) | grep html > /dev/null; then \ + echo "Un-preparing docs for upload (rebasing cross-references) ..." ; \ + gtkdoc-rebase --html-dir=$(builddir)/html ; \ + fi; \ + echo Done diff --git a/gst-plugins-base-subtitles0.10/common/win32.mak b/gst-plugins-base-subtitles0.10/common/win32.mak new file mode 100644 index 0000000..94afaec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/common/win32.mak @@ -0,0 +1,72 @@ +# various tests to make sure we dist the win32 stuff (for MSVC builds) right + +# the MANIFEST contains all win32 related files that should be disted +win32 = $(shell cat $(top_srcdir)/win32/MANIFEST) + +# wildcard is apparently not portable to other makes, hence the use of find +# these are library .def files with the symbols to export +win32defs = $(shell find $(top_srcdir)/win32/common -name '*.def') + +# wildcard is apparently not portable to other makes, hence the use of find +# these are files that need to be disted with CRLF line endings: +win32crlf = $(shell find $(top_srcdir)/win32 -name '*.dsw' -o -name '*.dsp') + +win32-debug: + @echo; \ + echo win32 = $(win32); \ + echo; \ + echo win32defs = $(win32defs); \ + echo; \ + echo win32crlf = $(win32crlf); \ + echo + +win32-check-crlf: + @echo Checking win32 files for CR LF line endings ...; \ + fail=0 ; \ + for each in $(win32crlf) ; do \ + result=`perl -e 'print grep(/\r\n/,<>)' "$$each" | wc -l`; \ + if test "$$result" = 0 ; then \ + echo $$each must be fixed to have CRLF line endings ; \ + fail=1; \ + fi ; \ + done ; \ + exit $$fail + +# make sure all symbols we export on linux are defined in the win32 .def too +# (don't care about other unixes for now, it's enough if it works on one of +# the linux build bots; we assume .so ) +check-exports: + @fail=0 ; \ + for l in $(win32defs); do \ + libbase=`basename "$$l" ".def"`; \ + libso=`find "$(top_builddir)" -name "$$libbase-@GST_MAJORMINOR@.so" | grep -v /_build/ | head -n1`; \ + libdef="$(top_srcdir)/win32/common/$$libbase.def"; \ + if test "x$$libso" != "x"; then \ + echo Checking symbols in $$libso; \ + if ! ($(top_srcdir)/common/check-exports $$libdef $$libso) ; then \ + fail=1; \ + fi; \ + fi; \ + done ; \ + if test $$fail != 0; then \ + echo '-----------------------------------------------------------'; \ + echo 'Run this to update the .def files:'; \ + echo 'make check-exports 2>&1 | patch -p1'; \ + echo '-----------------------------------------------------------'; \ + fi; \ + exit $$fail + +# complain about nonportable printf format strings (%lld, %llu, %zu etc.) +check-nonportable-print-format: + @fail=0 ; \ + loc=`find "$(top_srcdir)" -name '*.c' | xargs grep -n -e '%[0-9]*ll[udx]' -e '%[0-9]*z[udx]'`; \ + if test "x$$loc" != "x"; then \ + echo "Please fix the following print format strings:" ; \ + find "$(top_srcdir)" -name '*.c' | xargs grep -n -e '%[0-9]*ll[udx]' -e '%[0-9]*z[udx]'; \ + fail=1; \ + fi; \ + exit $$fail + +dist-hook: check-exports win32-check-crlf + + diff --git a/gst-plugins-base-subtitles0.10/configure.ac b/gst-plugins-base-subtitles0.10/configure.ac new file mode 100644 index 0000000..7ccc5c6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/configure.ac @@ -0,0 +1,1080 @@ +AC_PREREQ(2.60) + +dnl please read gstreamer/docs/random/autotools before changing this file + +dnl initialize autoconf +dnl releases only do -Wall, git and prerelease does -Werror too +dnl use a three digit version number for releases, and four for git/prerelease +AC_INIT(GStreamer Base Plug-ins, 0.10.34, + http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, + gst-plugins-base) + +AG_GST_INIT + +dnl initialize automake +AM_INIT_AUTOMAKE([-Wno-portability 1.10]) + +dnl define PACKAGE_VERSION_* variables +AS_VERSION + +dnl check if this is a release version +AS_NANO(GST_GIT="no", GST_GIT="yes") + +dnl can autoconf find the source ? +AC_CONFIG_SRCDIR([gst/audiotestsrc/gstaudiotestsrc.c]) + +dnl define the output header for config +AM_CONFIG_HEADER([config.h]) + +dnl AM_MAINTAINER_MODE only provides the option to configure to enable it +AM_MAINTAINER_MODE + +dnl sets host_* variables +AC_CANONICAL_HOST + +dnl use pretty build output with automake >= 1.11 +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])], + [AM_DEFAULT_VERBOSITY=1 + AC_SUBST(AM_DEFAULT_VERBOSITY)]) + +dnl our libraries and install dirs use major.minor as a version +GST_MAJORMINOR=$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR +dnl we override it here if we need to for the release candidate of new series +GST_MAJORMINOR=0.10 +AC_SUBST(GST_MAJORMINOR) + +dnl CURRENT, REVISION, AGE +dnl - library source changed -> increment REVISION +dnl - interfaces added/removed/changed -> increment CURRENT, REVISION = 0 +dnl - interfaces added -> increment AGE +dnl - interfaces removed -> AGE = 0 +dnl sets GST_LT_LDFLAGS +AS_LIBTOOL(GST, 24, 0, 24) + +dnl FIXME: this macro doesn't actually work; +dnl the generated libtool script has no support for the listed tags. +dnl So this needs to be fixed first if we want to use this +dnl AS_LIBTOOL_TAGS + +AC_LIBTOOL_WIN32_DLL +AM_PROG_LIBTOOL + +dnl *** required versions of GStreamer stuff *** +GST_REQ=0.10.34 + +dnl *** autotools stuff **** + +dnl allow for different autotools +AS_AUTOTOOLS_ALTERNATE + +dnl Add parameters for aclocal +AC_SUBST(ACLOCAL_AMFLAGS, "-I m4 -I common/m4") + +dnl set up gettext +dnl the version check needs to stay here because autopoint greps for it +AM_GNU_GETTEXT_VERSION([0.14]) +AM_GNU_GETTEXT([external]) +AG_GST_GETTEXT([gst-plugins-base-$GST_MAJORMINOR]) + +dnl *** check for arguments to configure *** + +AG_GST_ARG_DEBUG +AG_GST_ARG_PROFILING +AG_GST_ARG_VALGRIND +AG_GST_ARG_GCOV + +AG_GST_ARG_EXAMPLES + +AG_GST_ARG_WITH_PKG_CONFIG_PATH +AG_GST_ARG_WITH_PACKAGE_NAME +AG_GST_ARG_WITH_PACKAGE_ORIGIN + +AG_GST_PKG_CONFIG_PATH + +dnl let distro override plugin install helper path +AC_ARG_WITH(install-plugins-helper, + AC_HELP_STRING([--with-install-plugins-helper], + [specify path of helper script to call to install plugins]), + [ + case "${withval}" in + yes) AC_MSG_ERROR(bad value ${withval} for --with-install-plugins-helper) ;; + no) AC_MSG_ERROR(bad value ${withval} for --with-install-plugins-helper) ;; + *) GST_INSTALL_PLUGINS_HELPER="${withval}" ;; + esac + ], + [ + dnl Default value + AS_AC_EXPAND(GST_INSTALL_PLUGINS_HELPER,${libexecdir}/gst-install-plugins-helper) + ] +) +AC_MSG_NOTICE(Using $GST_INSTALL_PLUGINS_HELPER as plugin install helper) +AC_DEFINE_UNQUOTED(GST_INSTALL_PLUGINS_HELPER, "$GST_INSTALL_PLUGINS_HELPER", + [plugin install helper script]) +AC_SUBST(GST_INSTALL_PLUGINS_HELPER) + +AG_GST_ARG_WITH_PLUGINS + +AG_GST_ARG_ENABLE_EXTERNAL + +AG_GST_ARG_ENABLE_EXPERIMENTAL + +dnl *** checks for platform *** + +dnl * hardware/architecture * + +dnl common/m4/gst-arch.m4 +dnl check CPU type +AG_GST_ARCH + +dnl check for large file support +dnl affected plugins must include config.h +AC_SYS_LARGEFILE + +dnl *** checks for programs *** + +dnl find a compiler +AC_PROG_CC +AC_PROG_CC_STDC + +dnl check if the compiler supports '-c' and '-o' options +AM_PROG_CC_C_O + +dnl determine if c++ is available on this system +AC_PROG_CXX +dnl CXX may be set to some default even if no c++ compiler is available +dnl (thanks autotools!), so just try to compile some c++ code to make sure +AC_LANG_PUSH([C++]) +AC_TRY_COMPILE([ class Foo { int bar; };], , working_cxx=yes, working_cxx=no) +AC_LANG_POP([C++]) +AC_MSG_NOTICE([working c++ compiler found: $working_cxx]) +AM_CONDITIONAL(HAVE_CXX, test "x$working_cxx" = "xyes") + +AC_PATH_PROG(VALGRIND_PATH, valgrind, no) +AM_CONDITIONAL(HAVE_VALGRIND, test ! "x$VALGRIND_PATH" = "xno") + +dnl check for gobject-introspection +GOBJECT_INTROSPECTION_CHECK([0.9.12]) + +dnl check for documentation tools +GTK_DOC_CHECK([1.3]) +AS_PATH_PYTHON([2.1]) +AG_GST_PLUGIN_DOCS([1.3],[2.1]) + +dnl *** checks for libraries *** + +dnl libm, for sin() etc. +AC_CHECK_LIBM +AC_SUBST(LIBM) + +dnl *** checks for header files *** + +dnl check if we have ANSI C header files +AC_HEADER_STDC + +dnl used in gst/ffmpegcolorspace/mem.c +dnl FIXME: could be fixed by redefining av_malloc and av_free to GLib's +AC_CHECK_HEADERS([malloc.h]) + +ac_cppflags_save="$CPPFLAGS" +CPPFLAGS="`$PKG_CONFIG --cflags libxml-2.0`" +AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([ +#include + ],[ +#ifndef LIBXML_HTML_ENABLED +#error libxml2 has no HTML support +#endif /* LIBXML_HTML_ENABLED */ + ]), HAVE_LIBXML_HTML="yes", HAVE_LIBXML_HTML="no") +CPPFLAGS="$ac_cppflags_save" +AM_CONDITIONAL(HAVE_LIBXML_HTML, test "x$HAVE_LIBXML_HTML" = "xyes") + +dnl used in gst/tcp +AC_CHECK_HEADERS([sys/socket.h], + HAVE_SYS_SOCKET_H="yes", HAVE_SYS_SOCKET_H="no") +AM_CONDITIONAL(HAVE_SYS_SOCKET_H, test "x$HAVE_SYS_SOCKET_H" = "xyes") + +dnl used in gst-libs/gst/rtsp +AC_CHECK_HEADERS([winsock2.h], HAVE_WINSOCK2_H=yes) +if test "x$HAVE_WINSOCK2_H" = "xyes"; then + WIN32_LIBS="-lws2_32" + AC_SUBST(WIN32_LIBS) +fi + +dnl check for hstrerror, for gst-libs/gst/rtsp +save_libs="$LIBS" +AC_CHECK_FUNC(hstrerror, , + AC_CHECK_LIB(resolv, hstrerror, , + [AC_DEFINE(NO_HSTRERROR, 1, + [Define if you have no native hstrerror() function.])])) +HSTRERROR_LIBS=$LIBS +AC_SUBST(HSTRERROR_LIBS) +LIBS="$save_libs" + +dnl used in gst-libs/gst/pbutils and associated unit test +AC_CHECK_HEADERS([process.h sys/types.h sys/wait.h sys/stat.h]) + +dnl ffmpegcolorspace includes _stdint.h +dnl also, Windows does not have long long +AX_CREATE_STDINT_H + +dnl *** checks for functions *** +AC_CHECK_FUNCS([localtime_r gmtime_r]) + +dnl *** checks for math functions *** +LIBS_SAVE=$LIBS +LIBS="$LIBS $LIBM" +AC_CHECK_FUNCS(log2) +LIBS=$LIBS_SAVE + +dnl *** checks for types/defines *** + +dnl Check for FIONREAD ioctl declaration +dnl used in gst/tcp +GST_CHECK_FIONREAD + +dnl *** checks for structures *** + +dnl *** checks for compiler characteristics *** + +dnl *** checks for library functions *** + +dnl check for fseeko() +AC_FUNC_FSEEKO + +dnl Check for fast float to int casting as defined in C99 +dnl used in gst-libs/gst/floatcast/floatcast.h +save_libs=$LIBS +LIBS="$LIBS $LIBM" +AC_C99_FUNC_LRINT +AC_C99_FUNC_LRINTF +LIBS=$save_libs + +dnl Check for a way to display the function name in debug output +AG_GST_CHECK_FUNCTION + +dnl *** checks for socket and nsl libraries *** +AC_CHECK_FUNC(socket,,[AC_CHECK_LIB(socket,socket)]) +AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) + +dnl *** checks for dependency libraries *** + +dnl GLib is required +AG_GST_GLIB_CHECK([2.22]) + +ORC_CHECK([0.4.11]) + +dnl checks for gstreamer +dnl uninstalled is selected preferentially -- see pkg-config(1) +AG_GST_CHECK_GST($GST_MAJORMINOR, [$GST_REQ], yes) +AG_GST_CHECK_GST_BASE($GST_MAJORMINOR, [$GST_REQ], yes) +AG_GST_CHECK_GST_GDP($GST_MAJORMINOR, [$GST_REQ], yes) +AG_GST_CHECK_GST_CONTROLLER($GST_MAJORMINOR, [$GST_REQ], yes) +AG_GST_CHECK_GST_CHECK($GST_MAJORMINOR, [$GST_REQ], no) +AM_CONDITIONAL(HAVE_GST_CHECK, test "x$HAVE_GST_CHECK" = "xyes") + +dnl Check for documentation xrefs +GLIB_PREFIX="`$PKG_CONFIG --variable=prefix glib-2.0`" +GST_PREFIX="`$PKG_CONFIG --variable=prefix gstreamer-$GST_MAJORMINOR`" +AC_SUBST(GLIB_PREFIX) +AC_SUBST(GST_PREFIX) + +dnl GTK is optional and only used in examples +HAVE_GTK=no +HAVE_GTK_X11=no +GTK2_REQ=2.14.0 +GTK3_REQ=2.91.3 +if test "x$BUILD_EXAMPLES" = "xyes"; then + AC_MSG_CHECKING([which gtk+ version to compile examples against (optional)]) + AC_ARG_WITH([gtk], + AC_HELP_STRING([--with-gtk=3.0|2.0], + [which gtk+ version to compile against (default: 2.0)]), + [case "$with_gtk" in + 2.0) GTK_REQ=$GTK2_REQ ;; + 3.0) GTK_REQ=$GTK3_REQ ;; + *) AC_MSG_ERROR([invalid gtk+ version specified]);; + esac], + [with_gtk=2.0 + GTK_REQ=$GTK2_REQ]) + AC_MSG_RESULT([$with_gtk (>= $GTK_REQ)]) + PKG_CHECK_MODULES(GTK, gtk+-$with_gtk >= $GTK_REQ, HAVE_GTK=yes, HAVE_GTK=no) + dnl some examples need gtk+-x11 + PKG_CHECK_MODULES(GTK_X11, gtk+-x11-$with_gtk >= $GTK_REQ, HAVE_GTK_X11=yes, HAVE_GTK_X11=no) + AC_SUBST(GTK_LIBS) + AC_SUBST(GTK_CFLAGS) +fi +AM_CONDITIONAL(HAVE_GTK, test "x$HAVE_GTK" = "xyes") +AM_CONDITIONAL(HAVE_GTK_X11, test "x$HAVE_GTK_X11" = "xyes") + +dnl QT is optional and only used in examples +PKG_CHECK_MODULES(QT, QtGui >= 4.6, [ + HAVE_QT_GV=yes + HAVE_QT=yes +], [ + HAVE_QT_GV=no + PKG_CHECK_MODULES(QT, QtGui >= 4.0, HAVE_QT=yes, HAVE_QT=no) +]) +if test "x$HAVE_QT" = "xyes"; then + AC_MSG_CHECKING([Qt moc]) + QT4_MOC=`$PKG_CONFIG --variable=moc_location QtGui` + AC_MSG_RESULT($QT4_MOC) + AC_SUBST(QT4_MOC) +fi +AM_CONDITIONAL(HAVE_QT, test "x$HAVE_QT" = "xyes") +AM_CONDITIONAL(HAVE_QT_GV, test "x$HAVE_QT_GV" = "xyes") + +dnl chck for linux headers needed by the joystick seek example +AC_COMPILE_IFELSE( +[ + AC_LANG_PROGRAM([ + #include + #include + ],[ + struct js_event js; + js.type = JS_EVENT_AXIS; + ]) +], [ + HAVE_LINUX_JOYSTICK_HEADERS="yes" +], [ + HAVE_LINUX_JOYSTICK_HEADERS="no" +]) +AM_CONDITIONAL(HAVE_LINUX_JOYSTICK_HEADERS, test "x$HAVE_LINUX_JOYSTICK_HEADERS" = "xyes") + +dnl Check for -Bsymbolic-functions linker flag used to avoid +dnl intra-library PLT jumps, if available. +AC_ARG_ENABLE(Bsymbolic, + [AC_HELP_STRING([--disable-Bsymbolic], + [avoid linking with -Bsymbolic])],, + [SAVED_LDFLAGS="${LDFLAGS}" + AC_MSG_CHECKING([for -Bsymbolic-functions linker flag]) + LDFLAGS=-Wl,-Bsymbolic-functions + AC_TRY_LINK([], [int main (void) { return 0; }], + AC_MSG_RESULT(yes) + enable_Bsymbolic=yes, + AC_MSG_RESULT(no) + enable_Bsymbolic=no) + LDFLAGS="${SAVED_LDFLAGS}"]) + + +dnl *** set variables based on configure arguments *** + +dnl set license and copyright notice +GST_LICENSE="LGPL" +AC_DEFINE_UNQUOTED(GST_LICENSE, "$GST_LICENSE", [GStreamer license]) +AC_SUBST(GST_LICENSE) + +dnl set location of plugin directory +AG_GST_SET_PLUGINDIR + +dnl set release date/time +AG_GST_SET_PACKAGE_RELEASE_DATETIME_WITH_NANO([$PACKAGE_VERSION_NANO], + ["${srcdir}/gst-plugins-base.doap"], + [$PACKAGE_VERSION_MAJOR.$PACKAGE_VERSION_MINOR.$PACKAGE_VERSION_MICRO]) + +dnl define an ERROR_CFLAGS Makefile variable +dnl -Wformat-nonliteral - see ext/pango/gstclockoverlay.c and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39438 +AG_GST_SET_ERROR_CFLAGS($GST_GIT, [ + -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls -Wundef + -Wwrite-strings -Wformat-nonliteral -Wformat-security + -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return + -Wno-multichar -Wnested-externs ]) + +dnl define an ERROR_CXXFLAGS Makefile variable +AG_GST_SET_ERROR_CXXFLAGS($GST_GIT, [ + -Wmissing-declarations -Wredundant-decls -Wundef + -Wwrite-strings -Wformat-nonliteral -Wformat-security + -Winit-self -Wmissing-include-dirs -Waddress -Waggregate-return + -Wno-multichar]) + +dnl define correct level for debugging messages +AG_GST_SET_LEVEL_DEFAULT($GST_GIT) + +dnl used in examples +AG_GST_DEFAULT_ELEMENTS + +dnl needed for encoding-target +GST_DATADIR="$GST_PREFIX/share" +AC_DEFINE_UNQUOTED(GST_DATADIR, "$GST_DATADIR", [system wide data directory]) +AC_DEFINE_UNQUOTED(GST_MAJORMINOR, "$GST_MAJORMINOR", [major/minor version]) + +dnl behaviour of speex based audio resampler +AC_MSG_CHECKING(which audio resample format to use for integer) +AC_ARG_WITH([audioresample_format], + AS_HELP_STRING([--with-audioresample-format],[Which implementation should be used for integer audio resampling, int/float/auto, (default is auto)]), + [ac_cv_audioresample_format=$withval], [ac_cv_audioresample_format=auto])dnl +AC_MSG_RESULT($ac_cv_audioresample_format) +case $ac_cv_audioresample_format in + int) + AC_DEFINE(AUDIORESAMPLE_FORMAT_INT,1,[The int implementation should be used for integer audio resampling]) + AC_SUBST(AUDIORESAMPLE_FORMAT_INT) + ;; + float) + AC_DEFINE(AUDIORESAMPLE_FORMAT_FLOAT,1,[The float implementation should be used for integer audio resampling]) + AC_SUBST(AUDIORESAMPLE_FORMAT_FLOAT) + ;; + auto) + AC_DEFINE(AUDIORESAMPLE_FORMAT_AUTO,1,[The implementation that should be used for integer audio resampling witll be benchmarked at runtime]) + AC_SUBST(AUDIORESAMPLE_FORMAT_AUTO) +esac + +dnl *** plug-ins to include *** + +dnl these are all the gst plug-ins, compilable without additional libs +AG_GST_CHECK_PLUGIN(adder) +AG_GST_CHECK_PLUGIN(app) +AG_GST_CHECK_PLUGIN(audioconvert) +AG_GST_CHECK_PLUGIN(audiorate) +AG_GST_CHECK_PLUGIN(audiotestsrc) +AG_GST_CHECK_PLUGIN(encoding) +AG_GST_CHECK_PLUGIN(ffmpegcolorspace) +AG_GST_CHECK_PLUGIN(gdp) +AG_GST_CHECK_PLUGIN(playback) +AG_GST_CHECK_PLUGIN(audioresample) +AG_GST_CHECK_PLUGIN(subparse) +AG_GST_CHECK_PLUGIN(tcp) +AG_GST_CHECK_PLUGIN(typefind) +AG_GST_CHECK_PLUGIN(videotestsrc) +AG_GST_CHECK_PLUGIN(videorate) +AG_GST_CHECK_PLUGIN(videoscale) +AG_GST_CHECK_PLUGIN(volume) + +dnl check for gstreamer core features (subsystems) +dnl FIXME: this assumes srcdir == builddir for uninstalled setups +GST_CONFIGPATH=`$PKG_CONFIG --variable=includedir gstreamer-0.10`"/gst/gstconfig.h" +AG_GST_PARSE_SUBSYSTEM_DISABLES($GST_CONFIGPATH) +AM_CONDITIONAL(USE_XML, test $GST_DISABLE_XML != "1") + +dnl disable plug-ins that require libxml2's HTML support if it is not available +if test "x$HAVE_LIBXML_HTML" != "xyes"; then + AG_GST_DISABLE_PLUGIN(subparse) +fi + +dnl disable plug-ins that require sys/socket.h if it is not available +if test "x$HAVE_SYS_SOCKET_H" != "xyes"; then + AG_GST_DISABLE_PLUGIN(tcp) +fi + +dnl iso-codes is optional, used by libgsttag +AC_ARG_ENABLE(iso-codes, +AC_HELP_STRING([--enable-iso-codes],[use iso-codes if installed]), +[case "${enableval}" in + yes) enable_iso_codes=yes ;; + no) enable_iso_codes=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-iso-codes) ;; +esac +], +[enable_iso_codes=yes]) dnl Default value + +AC_MSG_CHECKING([whether to use iso-codes if they are available]) +if test "x$enable_iso_codes" = "xyes"; then + AC_MSG_RESULT([yes]) + have_iso_codes=no + AC_MSG_CHECKING([whether iso-codes are available on this system]) + if $PKG_CONFIG iso-codes; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([whether iso-codes has iso-639 domain]) + if $PKG_CONFIG --variable=domains iso-codes | $GREP -q 639 ; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([for iso-codes prefix]) + ISO_CODES_PREFIX=`$PKG_CONFIG --variable=prefix iso-codes` + if test -d "$ISO_CODES_PREFIX"; then + AC_MSG_RESULT([yes]) + AC_MSG_CHECKING([ISO_CODES_PREFIX]) + AC_MSG_RESULT([$ISO_CODES_PREFIX]) + ISO_639_DOMAIN="iso_639" + AC_MSG_CHECKING([ISO_639_DOMAIN]) + AC_MSG_RESULT([$ISO_639_DOMAIN]) + have_iso_codes=yes + AC_DEFINE([HAVE_ISO_CODES], [1], [make use of iso-codes for ISO-639]) + AC_DEFINE_UNQUOTED([ISO_CODES_PREFIX], ["$ISO_CODES_PREFIX"], [prefix]) + ISO_CODES_VERSION=`$PKG_CONFIG --modversion iso-codes` + AC_DEFINE_UNQUOTED([ISO_CODES_VERSION], ["$ISO_CODES_VERSION"], [ ]) + else + AC_MSG_RESULT([no]) + fi + else + AC_MSG_RESULT([no]) + fi + else + AC_MSG_RESULT([no]) + fi + AM_CONDITIONAL(USE_ISO_CODES, test "x$have_iso_codes" = "xyes") +else + AC_MSG_RESULT([no (disabled via --disable-iso-codes)]) + AM_CONDITIONAL(USE_ISO_CODES, false) +fi + +dnl *** sys plug-ins *** + +echo +AC_MSG_NOTICE([Checking libraries for plugins in sys/]) +echo + +dnl *** X11 *** +translit(dnm, m, l) AM_CONDITIONAL(USE_X, true) +AG_GST_CHECK_FEATURE(X, [X libraries and plugins], + [ximagesink], [ + AC_PATH_XTRA + ac_cflags_save="$CFLAGS" + ac_cppflags_save="$CPPFLAGS" + CFLAGS="$CFLAGS $X_CFLAGS" + CPPFLAGS="$CPPFLAGS $X_CFLAGS" + + dnl now try to find the HEADER + AC_CHECK_HEADER(X11/Xlib.h, HAVE_X="yes", HAVE_X="no") + + if test "x$HAVE_X" = "xno" + then + AC_MSG_NOTICE([cannot find X11 development files]) + else + dnl this is much more than we want + X_LIBS="$X_LIBS $X_PRE_LIBS $X_EXTRA_LIBS" + dnl AC_PATH_XTRA only defines the path needed to find the X libs, + dnl it does not add the libs; therefore we add them here + X_LIBS="$X_LIBS -lX11" + AC_SUBST(X_CFLAGS) + AC_SUBST(X_LIBS) + fi + AC_SUBST(HAVE_X) + CFLAGS="$ac_cflags_save" + CPPFLAGS="$ac_cppflags_save" +]) + +dnl Check for Xv extension +translit(dnm, m, l) AM_CONDITIONAL(USE_XVIDEO, true) +AG_GST_CHECK_FEATURE(XVIDEO, [X11 XVideo extensions], + [xvimagesink], [ + AG_GST_CHECK_XV +]) + +dnl check for X Shm +translit(dnm, m, l) AM_CONDITIONAL(USE_XSHM, true) +AG_GST_CHECK_FEATURE(XSHM, [X Shared Memory extension], , [ + if test x$HAVE_X = xyes; then + AC_CHECK_LIB(Xext, XShmAttach, + HAVE_XSHM="yes", HAVE_XSHM="no", + $X_LIBS) + if test "x$HAVE_XSHM" = "xyes"; then + XSHM_LIBS="-lXext" + else + dnl On AIX, it is in XextSam instead, but we still need -lXext + AC_CHECK_LIB(XextSam, XShmAttach, + HAVE_XSHM="yes", HAVE_XSHM="no", + $X_LIBS) + if test "x$HAVE_XSHM" = "xyes"; then + XSHM_LIBS="-lXext -lXextSam" + fi + fi + fi +], , [ + AC_SUBST(HAVE_XSHM) + AC_SUBST(XSHM_LIBS) +]) + +dnl v4l/v4l2 checks have been moved down because they require X + +dnl *** Video 4 Linux *** +dnl for information about the header/define, see sys/v4l/gstv4lelement.h +dnl renamed to GST_V4L in accordance with V4L2 below +translit(dnm, m, l) AM_CONDITIONAL(USE_GST_V4L, true) +AG_GST_CHECK_FEATURE(GST_V4L, [Video 4 Linux], video4linux, [ + AC_CHECK_DECL(VID_TYPE_MPEG_ENCODER, HAVE_GST_V4L="yes", HAVE_GST_V4L="no", [ +#include +#define _LINUX_TIME_H +#define __user +#include + ]) + + dnl we can build v4l without Xv, but then we won't have XOverlay support + if test "x$HAVE_GST_V4L" = "xyes" -a "x$HAVE_XVIDEO" != "xyes" + then + AC_MSG_NOTICE([NO XVIDEO FOUND, VIDEO4LINUX WILL BE BUILT]) + AC_MSG_NOTICE([WITHOUT XOVERLAY SUPPORT]) + fi +]) + +# Optional gudev for device probing +AC_ARG_WITH([gudev], + AC_HELP_STRING([--with-gudev], + [device detection with gudev]), + [], + [with_gudev=check]) +if test x$HAVE_GST_V4L = xyes; then + if test x$with_gudev != xno; then + PKG_CHECK_MODULES(GUDEV, [ gudev-1.0 >= 143 ], + [ have_gudev=yes + AC_DEFINE(HAVE_GUDEV, 1, + [Whether gudev is available for device detection]) + AC_DEFINE([G_UDEV_API_IS_SUBJECT_TO_CHANGE], 1, [I know the API is subject to change.]) + ], [ + have_gudev=no + ]) + else + have_gudev=no + fi +fi +AC_SUBST(GUDEV_CFLAGS) +AC_SUBST(GUDEV_LIBS) + +dnl *** ext plug-ins *** +dnl keep this list sorted alphabetically ! + +if test "x$BUILD_EXTERNAL" = "xyes"; then + +echo +AC_MSG_NOTICE([Checking libraries for plugins in ext/]) +echo + +dnl *** alsa *** +translit(dnm, m, l) AM_CONDITIONAL(USE_ALSA, true) +AG_GST_CHECK_FEATURE(ALSA, [ALSA], alsa, [ + PKG_CHECK_MODULES(ALSA, alsa >= 0.9.1, [ + HAVE_ALSA="yes" + AC_SUBST(ALSA_CFLAGS) + AC_SUBST(ALSA_LIBS) + ], [ + AM_PATH_ALSA(0.9.1, HAVE_ALSA="yes", HAVE_ALSA="no") + ]) +]) + +dnl *** CDParanoia *** +dnl Note: upstream has a pkg-config file only in post-10.2 SVN so far +translit(dnm, m, l) AM_CONDITIONAL(USE_CDPARANOIA, true) +AG_GST_CHECK_FEATURE(CDPARANOIA, [CDParanoia], cdparanoia, [ + PKG_CHECK_MODULES(CDPARANOIA, cdparanoia-3 >= 10.2, [ + HAVE_CDPARANOIA="yes" + ], [ + AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface, + cdda_open, -lm, + cdda_interface.h, + CDPARANOIA_LIBS="-lcdda_interface -lcdda_paranoia" + HEADER_DIR="no" + FOUND_CDPARANOIA="yes") + if test "x$FOUND_CDPARANOIA" != "xyes"; + then + AG_GST_CHECK_LIBHEADER(CDPARANOIA, cdda_interface, + cdda_open, -lm, + cdda/cdda_interface.h, + CDPARANOIA_LIBS="-lcdda_interface -lcdda_paranoia" + HEADER_DIR="yes" + FOUND_CDPARANOIA="yes") + fi + if test "x$HEADER_DIR" = "xyes"; + then + AC_DEFINE_UNQUOTED(CDPARANOIA_HEADERS_IN_DIR, , + defined if cdda headers are in a cdda/ directory) + fi + if test "x$FOUND_CDPARANOIA" = "xyes"; + then + AC_CHECK_LIB(cdda_paranoia, + paranoia_cachemodel_size, + : , + HAVE_CDPARANOIA=no, + [-lcdda_interface]) + fi + + AC_SUBST(CDPARANOIA_LIBS) + ]) +]) +dnl FIXME : add second check somehow if that is necessary +dnl AC_CHECK_LIB(cdda_paranoia, paranoia_init, : , HAVE_CDPARANOIA=no, -lcdda_interface ) +dnl AC_CHECK_HEADER(cdda_paranoia.h, :, HAVE_CDPARANOIA=no) + +dnl *** GNOME VFS *** +translit(dnm, m, l) AM_CONDITIONAL(USE_GNOME_VFS, true) +AG_GST_CHECK_FEATURE(GNOME_VFS, [GNOME VFS], gnomevfs, [ + PKG_CHECK_MODULES(GNOME_VFS, gnome-vfs-2.0, [ + HAVE_GNOME_VFS="yes" + AC_SUBST(GNOME_VFS_CFLAGS) + AC_SUBST(GNOME_VFS_LIBS) + GNOME_VFS_MODULES_DIR="`$PKG_CONFIG --variable=modulesdir gnome-vfs-2.0`" + AC_DEFINE_UNQUOTED(GNOME_VFS_MODULES_DIR, "$GNOME_VFS_MODULES_DIR", + [The GnomeVFS modules directory.]) + ],[ + HAVE_GNOME_VFS="no" + ] + ) +]) + +dnl *** ivorbis *** +dnl AM_PATH_IVORBIS only takes two options +translit(dnm, m, l) AM_CONDITIONAL(USE_IVORBIS, true) +AG_GST_CHECK_FEATURE(IVORBIS, [integer vorbis plug-in], ivorbisdec, [ + AG_GST_PKG_CHECK_MODULES(IVORBIS, vorbisidec) + if test $HAVE_IVORBIS = no + then + IVORBIS_LIBS= + IVORBIS_CFLAGS= + AC_CHECK_LIB(vorbisidec, vorbis_block_init, + [IVORBIS_LIBS=-lvorbisidec + HAVE_IVORBIS=yes + case $host in + arm-*-*) + IVORBIS_CFLAGS="-D_ARM_ASSEM_ $IVORBIS_CFLAGS" + esac + ], + HAVE_IVORBIS=no) + AC_SUBST(IVORBIS_LIBS) + AC_SUBST(IVORBIS_CFLAGS) + else + AC_CHECK_LIB(vorbisidec, vorbis_dsp_pcmout, + AC_DEFINE([USE_TREMOLO],1, "Define if building for android"), + USE_TREMOLO=no) + fi +]) + +dnl *** libgio *** +translit(dnm, m, l) AM_CONDITIONAL(USE_GIO, true) +AG_GST_CHECK_FEATURE(GIO, [GIO library], gio, [ + PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.16, [ + HAVE_GIO="yes" + GIO_MODULE_DIR="`$PKG_CONFIG --variable=giomoduledir gio-2.0`" + AC_DEFINE_UNQUOTED(GIO_MODULE_DIR, "$GIO_MODULE_DIR", + [The GIO modules directory.]) + GIO_LIBDIR="`$PKG_CONFIG --variable=libdir gio-2.0`" + AC_DEFINE_UNQUOTED(GIO_LIBDIR, "$GIO_LIBDIR", + [The GIO library directory.]) + ], [ + HAVE_GIO="no" + ]) + AC_SUBST(GIO_CFLAGS) + AC_SUBST(GIO_LIBS) + AC_SUBST(GIO_LDFLAGS) +]) + +dnl *** libvisual *** +translit(dnm, m, l) AM_CONDITIONAL(USE_LIBVISUAL, true) +AG_GST_CHECK_FEATURE(LIBVISUAL, [libvisual visualization library], libvisual, [ + AG_GST_PKG_CHECK_MODULES(LIBVISUAL, libvisual-0.4 >= 0.4.0) + if test $HAVE_LIBVISUAL = no + then + AG_GST_PKG_CHECK_MODULES(LIBVISUAL, libvisual = 0.2.0) + if test x$HAVE_LIBVISUAL = xyes; then + LIBVIS_PLUGINSDIR="`$PKG_CONFIG --variable=pluginsbasedir libvisual-0.2`" + fi + else + if test x$HAVE_LIBVISUAL = xyes; then + LIBVIS_PLUGINSDIR="`$PKG_CONFIG --variable=pluginsbasedir libvisual-0.4`" + fi + fi + AC_MSG_NOTICE([libvisual pluginsdir: $LIBVIS_PLUGINSDIR]) + if test x$LIBVIS_PLUGINSDIR != x; then + AC_DEFINE_UNQUOTED(LIBVISUAL_PLUGINSBASEDIR, + "$LIBVIS_PLUGINSDIR", + [directory in which the detected libvisual's plugins are located]) + fi +]) + +dnl *** ogg *** +translit(dnm, m, l) AM_CONDITIONAL(USE_OGG, true) +AG_GST_CHECK_FEATURE(OGG, [Xiph Ogg library], ogg, [ + AG_GST_PKG_CHECK_MODULES(OGG, ogg >= 1.0) + if test $HAVE_OGG = no + then + XIPH_PATH_OGG(HAVE_OGG="yes", HAVE_OGG="no") + AS_SCRUB_INCLUDE(OGG_CFLAGS) + fi +]) + +dnl *** pango *** +translit(dnm, m, l) AM_CONDITIONAL(USE_PANGO, true) +AG_GST_CHECK_FEATURE(PANGO, [Pango font rendering], pango, [ + AG_GST_PKG_CHECK_MODULES(PANGO, pango >= 1.16.0 pangocairo >= 1.16.0) +]) + +dnl *** theora *** +translit(dnm, m, l) AM_CONDITIONAL(USE_THEORA, true) +AG_GST_CHECK_FEATURE(THEORA, [Xiph Theora video codec], theora, [ + AG_GST_PKG_CHECK_MODULES(THEORA, theoradec >= 1.1 theoraenc >= 1.1) +]) + +dnl *** vorbis *** +dnl AM_PATH_VORBIS only takes two options +translit(dnm, m, l) AM_CONDITIONAL(USE_VORBIS, true) +AG_GST_CHECK_FEATURE(VORBIS, [Xiph Vorbis audio codec], vorbis, [ + AG_GST_PKG_CHECK_MODULES(VORBIS, vorbis >= 1.0 vorbisenc >= 1.0) + if test $HAVE_VORBIS = no + then + XIPH_PATH_VORBIS(HAVE_VORBIS="yes", HAVE_VORBIS="no") + AS_SCRUB_INCLUDE(VORBIS_CFLAGS) + fi +]) + +if test "x$HAVE_VORBIS" = "xyes"; then + ac_cflags_save="$CFLAGS" + AC_COMPILE_IFELSE( + AC_LANG_PROGRAM([ +#include + ],[ +vorbis_dsp_state *v; + +vorbis_synthesis_restart (v); + ]), HAVE_VSR=yes, HAVE_VSR=no) + if test "x$HAVE_VSR" = "xyes"; then + AC_DEFINE_UNQUOTED(HAVE_VORBIS_SYNTHESIS_RESTART, 1, + [defined if vorbis_synthesis_restart is present]) + fi + CFLAGS="$ac_cflags_save" +fi + +else + +dnl not building plugins with external dependencies, +dnl but we still need to set the conditionals +AM_CONDITIONAL(USE_ALSA, false) +AM_CONDITIONAL(USE_CDPARANOIA, false) +AM_CONDITIONAL(USE_GIO, false) +AM_CONDITIONAL(USE_GNOME_VFS, false) +AM_CONDITIONAL(USE_IVORBIS, false) +AM_CONDITIONAL(USE_LIBVISUAL, false) +AM_CONDITIONAL(USE_OGG, false) +AM_CONDITIONAL(USE_PANGO, false) +AM_CONDITIONAL(USE_THEORA, false) +AM_CONDITIONAL(USE_VORBIS, false) + +fi dnl of EXT plugins + +dnl seeking needs freetype, so check for it here +PKG_CHECK_MODULES(FT2, freetype2 >= 2.0.9, HAVE_FT2="yes", [ + AC_CHECK_FT2(2.0.9, HAVE_FT2="yes", HAVE_FT2="no") +]) +dnl make the HAVE_FT2 variable available to automake and Makefile.am +AM_CONDITIONAL(HAVE_FT2, test "x$HAVE_FT2" = "xyes") +AC_SUBST(FT2_CFLAGS) +AC_SUBST(FT2_LIBS) + +dnl *** finalize CFLAGS, LDFLAGS, LIBS + +dnl Overview: +dnl GST_OPTION_CFLAGS: common flags for profiling, debugging, errors, ... +dnl GST_*: flags shared by built objects to link against GStreamer +dnl GST_PLUGINS_BASE_CFLAGS: to link internally against the plugins base libs +dnl (compare to other modules) or for i18n +dnl GST_ALL_LDFLAGS: linker flags shared by all +dnl GST_LIB_LDFLAGS: additional linker flags for all libaries +dnl GST_LT_LDFLAGS: library versioning of our libraries +dnl GST_PLUGIN_LDFLAGS: flags to be used for all plugins + +dnl GST_OPTION_CFLAGS +if test "x$USE_DEBUG" = xyes; then + PROFILE_CFLAGS="-g" +fi +AC_SUBST(PROFILE_CFLAGS) + +if test "x$PACKAGE_VERSION_NANO" = "x1"; then + dnl Define _only_ when compiling a git version (not pre-releases or releases) + DEPRECATED_CFLAGS="-DGST_DISABLE_DEPRECATED" +else + DEPRECATED_CFLAGS="" +fi +AC_SUBST(DEPRECATED_CFLAGS) + +dnl every flag in GST_OPTION_CFLAGS and GST_OPTION_CXXFLAGS can be overridden +dnl at make time with e.g. make ERROR_CFLAGS="" +GST_OPTION_CFLAGS="\$(WARNING_CFLAGS) \$(ERROR_CFLAGS) \$(DEBUG_CFLAGS) \$(PROFILE_CFLAGS) \$(GCOV_CFLAGS) \$(OPT_CFLAGS) \$(DEPRECATED_CFLAGS)" +GST_OPTION_CXXFLAGS="\$(WARNING_CXXFLAGS) \$(ERROR_CXXFLAGS) \$(DEBUG_CFLAGS) \$(PROFILE_CFLAGS) \$(GCOV_CFLAGS) \$(OPT_CFLAGS) \$(DEPRECATED_CFLAGS)" +AC_SUBST(GST_OPTION_CFLAGS) +AC_SUBST(GST_OPTION_CXXFLAGS) + +dnl our libraries need to be versioned correctly +AC_SUBST(GST_LT_LDFLAGS) + +dnl GST_PLUGINS_BASE_CFLAGS +dnl prefer internal headers to already installed ones +dnl also add builddir include for enumtypes and marshal +GST_PLUGINS_BASE_CFLAGS="-I\$(top_srcdir)/gst-libs -I\$(top_builddir)/gst-libs" +AC_SUBST(GST_PLUGINS_BASE_CFLAGS) + +dnl FIXME: do we want to rename to GST_ALL_* ? +dnl add GST_OPTION_CFLAGS, but overridable +GST_CXXFLAGS="$GLIB_CFLAGS $GST_CFLAGS $GLIB_EXTRA_CFLAGS \$(GST_OPTION_CXXFLAGS)" +GST_CFLAGS="$GLIB_CFLAGS $GST_CFLAGS $GLIB_EXTRA_CFLAGS \$(GST_OPTION_CFLAGS)" +AC_SUBST(GST_CFLAGS) +AC_SUBST(GST_CXXFLAGS) +dnl add GCOV libs because libtool strips -fprofile-arcs -ftest-coverage +GST_LIBS="$GST_LIBS \$(GCOV_LIBS)" +AC_SUBST(GST_LIBS) + +dnl LDFLAGS really should only contain flags, not libs - they get added before +dnl whatevertarget_LIBS and -L flags here affect the rest of the linking +GST_ALL_LDFLAGS="-no-undefined" +if test "x${enable_Bsymbolic}" = "xyes"; then + GST_ALL_LDFLAGS="$GST_ALL_LDFLAGS -Wl,-Bsymbolic-functions" +fi +AC_SUBST(GST_ALL_LDFLAGS) + +dnl GST_LIB_LDFLAGS +dnl linker flags shared by all libraries +dnl LDFLAGS modifier defining exported symbols from built libraries +dnl (export _gst_foo but not __gst_foo) +GST_LIB_LDFLAGS="-export-symbols-regex ^_?\(gst_\|Gst\|GST_\).*" +AC_SUBST(GST_LIB_LDFLAGS) + +dnl this really should only contain flags, not libs - they get added before +dnl whatevertarget_LIBS and -L flags here affect the rest of the linking +GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_desc.*' $GST_ALL_LDFLAGS" +AC_SUBST(GST_PLUGIN_LDFLAGS) + +dnl *** output files *** + +AC_CONFIG_FILES( +Makefile +gst-plugins-base.spec +gst/Makefile +gst/adder/Makefile +gst/app/Makefile +gst/audioconvert/Makefile +gst/audiorate/Makefile +gst/audiotestsrc/Makefile +gst/encoding/Makefile +gst/ffmpegcolorspace/Makefile +gst/gdp/Makefile +gst/playback/Makefile +gst/audioresample/Makefile +gst/subparse/Makefile +gst/tcp/Makefile +gst/typefind/Makefile +gst/videotestsrc/Makefile +gst/videorate/Makefile +gst/videoscale/Makefile +gst/volume/Makefile +sys/Makefile +sys/ximage/Makefile +sys/xvimage/Makefile +sys/v4l/Makefile +ext/Makefile +ext/alsa/Makefile +ext/cdparanoia/Makefile +ext/gnomevfs/Makefile +ext/gio/Makefile +ext/libvisual/Makefile +ext/ogg/Makefile +ext/pango/Makefile +ext/theora/Makefile +ext/vorbis/Makefile +gst-libs/Makefile +gst-libs/gst/Makefile +gst-libs/gst/audio/Makefile +gst-libs/gst/app/Makefile +gst-libs/gst/cdda/Makefile +gst-libs/gst/fft/Makefile +gst-libs/gst/floatcast/Makefile +gst-libs/gst/interfaces/Makefile +gst-libs/gst/netbuffer/Makefile +gst-libs/gst/riff/Makefile +gst-libs/gst/rtp/Makefile +gst-libs/gst/rtsp/Makefile +gst-libs/gst/sdp/Makefile +gst-libs/gst/tag/Makefile +gst-libs/gst/pbutils/Makefile +gst-libs/gst/pbutils/gstpluginsbaseversion.h +gst-libs/gst/video/Makefile +tools/Makefile +pkgconfig/Makefile +pkgconfig/gstreamer-audio.pc +pkgconfig/gstreamer-audio-uninstalled.pc +pkgconfig/gstreamer-app.pc +pkgconfig/gstreamer-app-uninstalled.pc +pkgconfig/gstreamer-cdda.pc +pkgconfig/gstreamer-cdda-uninstalled.pc +pkgconfig/gstreamer-fft.pc +pkgconfig/gstreamer-fft-uninstalled.pc +pkgconfig/gstreamer-floatcast.pc +pkgconfig/gstreamer-floatcast-uninstalled.pc +pkgconfig/gstreamer-interfaces.pc +pkgconfig/gstreamer-interfaces-uninstalled.pc +pkgconfig/gstreamer-netbuffer.pc +pkgconfig/gstreamer-netbuffer-uninstalled.pc +pkgconfig/gstreamer-pbutils.pc +pkgconfig/gstreamer-pbutils-uninstalled.pc +pkgconfig/gstreamer-riff.pc +pkgconfig/gstreamer-riff-uninstalled.pc +pkgconfig/gstreamer-rtp.pc +pkgconfig/gstreamer-rtp-uninstalled.pc +pkgconfig/gstreamer-rtsp.pc +pkgconfig/gstreamer-rtsp-uninstalled.pc +pkgconfig/gstreamer-sdp.pc +pkgconfig/gstreamer-sdp-uninstalled.pc +pkgconfig/gstreamer-tag.pc +pkgconfig/gstreamer-tag-uninstalled.pc +pkgconfig/gstreamer-video.pc +pkgconfig/gstreamer-video-uninstalled.pc +pkgconfig/gstreamer-plugins-base.pc +pkgconfig/gstreamer-plugins-base-uninstalled.pc +tests/Makefile +tests/check/Makefile +tests/examples/Makefile +tests/examples/app/Makefile +tests/examples/dynamic/Makefile +tests/examples/encoding/Makefile +tests/examples/gio/Makefile +tests/examples/overlay/Makefile +tests/examples/seek/Makefile +tests/examples/snapshot/Makefile +tests/examples/playrec/Makefile +tests/examples/volume/Makefile +tests/examples/v4l/Makefile +tests/files/Makefile +tests/icles/Makefile +tests/icles/playback/Makefile +docs/Makefile +docs/design/Makefile +docs/libs/Makefile +docs/plugins/Makefile +docs/version.entities +po/Makefile.in +common/Makefile +common/m4/Makefile +m4/Makefile +) + +dnl Create the config.h file for Visual Studio builds +dnl Beware of spaces and /'s in some of the shell variable contents. +sed \ + -e 's/.*config.h.in.*autoheader.*/\/* Autogenerated config.h created for win32 Visual Studio builds *\/\n\n\/* PREFIX -- specifically added for Windows for easier moving *\/\n#define PREFIX "C:\\\\gstreamer"/' \ + -e 's/.* GST_INSTALL_PLUGINS_HELPER/#define GST_INSTALL_PLUGINS_HELPER PREFIX "\\\\libexec\\\\gst-install-plugins-helper.exe"/' \ + -e 's/.* GETTEXT_PACKAGE$/#define GETTEXT_PACKAGE "'$GETTEXT_PACKAGE'"/' \ + -e 's/.* GST_DATADIR$/#define GST_DATADIR PREFIX "\\\\share"/' \ + -e 's/.* GST_LEVEL_DEFAULT$/#define GST_LEVEL_DEFAULT GST_LEVEL_ERROR/' \ + -e 's/.* GST_LICENSE$/#define GST_LICENSE "'$GST_LICENSE'"/' \ + -e 's/.* GST_MAJORMINOR$/#define GST_MAJORMINOR "'$GST_MAJORMINOR'"/' \ + -e "s,.* GST_PACKAGE_NAME$,#define GST_PACKAGE_NAME \"${GST_PACKAGE_NAME}\"," \ + -e 's/.* GST_PACKAGE_ORIGIN$/#define GST_PACKAGE_ORIGIN "Unknown package origin"/' \ + -e "s,.* GST_PACKAGE_RELEASE_DATETIME$,#define GST_PACKAGE_RELEASE_DATETIME \"${GST_PACKAGE_RELEASE_DATETIME}\"," \ + -e 's/.* HAVE_CPU_I386$/#define HAVE_CPU_I386 1/' \ + -e 's/.* HAVE_FGETPOS$/#define HAVE_FGETPOS 1/' \ + -e 's/.* HAVE_FSETPOS$/#define HAVE_FSETPOS 1/' \ + -e 's/.* HAVE_ISO_CODES$/#undef HAVE_ISO_CODES/' \ + -e 's/.* HAVE_LIBXML2$/#define HAVE_LIBXML2 1/' \ + -e 's/.* HAVE_PROCESS_H$/#define HAVE_PROCESS_H 1/' \ + -e 's/.* HAVE_STDLIB_H$/#define HAVE_STDLIB_H 1/' \ + -e 's/.* HAVE_STRING_H$/#define HAVE_STRING_H 1/' \ + -e 's/.* HAVE_SYS_STAT_H$/#define HAVE_SYS_STAT_H 1/' \ + -e 's/.* HAVE_SYS_TYPES_H$/#define HAVE_SYS_TYPES_H 1/' \ + -e 's/.* HAVE_WIN32$/#define HAVE_WIN32 1/' \ + -e 's/.* HAVE_WINSOCK2_H$/#define HAVE_WINSOCK2_H 1/' \ + -e 's/.* HOST_CPU$/#define HOST_CPU "i686"/' \ + -e 's/.* ISO_CODES_PREFIX$/#undef ISO_CODES_PREFIX/' \ + -e 's/.* ISO_CODES_VERSION$/#undef ISO_CODES_VERSION/' \ + -e 's/.* LIBDIR$/#ifdef _DEBUG\n# define LIBDIR PREFIX "\\\\debug\\\\lib"\n#else\n# define LIBDIR PREFIX "\\\\lib"\n#endif/' \ + -e 's/.* LOCALEDIR$/#define LOCALEDIR PREFIX "\\\\share\\\\locale"/' \ + -e "s/.* PACKAGE$/#define PACKAGE \"$PACKAGE\"/" \ + -e 's/.* PACKAGE_BUGREPORT$/#define PACKAGE_BUGREPORT "http:\/\/bugzilla.gnome.org\/enter_bug.cgi?product=GStreamer"/' \ + -e "s/.* PACKAGE_NAME$/#define PACKAGE_NAME \"$PACKAGE_NAME\"/" \ + -e "s/.* PACKAGE_STRING$/#define PACKAGE_STRING \"$PACKAGE_STRING\"/" \ + -e 's/.* PACKAGE_TARNAME$/#define PACKAGE_TARNAME "'$PACKAGE_TARNAME'"/' \ + -e 's/.* PACKAGE_VERSION$/#define PACKAGE_VERSION "'$PACKAGE_VERSION'"/' \ + -e 's/.* PLUGINDIR$/#ifdef _DEBUG\n# define PLUGINDIR PREFIX "\\\\debug\\\\lib\\\\gstreamer-0.10"\n#else\n# define PLUGINDIR PREFIX "\\\\lib\\\\gstreamer-0.10"\n#endif/' \ + -e 's/.* USE_BINARY_REGISTRY$/#define USE_BINARY_REGISTRY/' \ + -e 's/.* VERSION$/#define VERSION "'$VERSION'"/' \ + -e "s/.* DEFAULT_AUDIOSINK$/#define DEFAULT_AUDIOSINK \"directsoundsink\"/" \ + -e "s/.* DEFAULT_VIDEOSINK$/#define DEFAULT_VIDEOSINK \"directdrawsink\"/" \ + -e "s/.* DEFAULT_VISUALIZER$/#define DEFAULT_VISUALIZER \"goom\"/" \ + config.h.in >win32/common/config.h-new + + + +AC_OUTPUT + +AG_GST_OUTPUT_PLUGINS +ORC_OUTPUT + diff --git a/gst-plugins-base-subtitles0.10/debian/HACKING.Debian b/gst-plugins-base-subtitles0.10/debian/HACKING.Debian new file mode 100644 index 0000000..e316488 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/HACKING.Debian @@ -0,0 +1,91 @@ +Hacking GStreamer for Debian +============================ + +An addition to the README.Debian that has Debian package hacking notes. + +Everything should now be versioned. + +- To update dependencies edit debian/build-deps.in + +- To rebuild package files from .in files: + + debian/rules maint + +- After a version update to check for missing files run: + + debian/maint missing + debian/maint missing-libs + debian/maint missing-so + +- To update package files edit gstreamer-foo then rebuild package files. This + will generate the gstreamerX.Y-foo file. Also update debian/rules and + debian/control.in as needed. + +- The packaging tries to stay close of upstream choice. gstreamerX.Y-misc has + most of the files, extra packages are made for the sinks and by group of + depends (gnome, x, ...) + +- Provide gstreamerX.Y-videosink and gstreamerX.Y-audiosink as needed. + +- All interfaces and generic libraries go in libgstreamer-plugins, libraries + with external dependencies have their own package such as libgstreamer-gconf. + +- Applications go in gstreamerX.Y-plugins-base-apps + + +File listing +------------ + +build-deps: + - generated from "build-deps.in" in "rules + debian/build-deps:": + * "build-deps.in" lists build-depends for Debian main packages + - serves generation with "control.in" and "mk.control" of "control" in + "rules debian/control::" +build-deps.in: + - lists build-depends for Debian main packages + - serves generation with "extra deps" of "build-deps" in "rules + debian/build-deps:" +changelog: handled classically +compat: handled classically +control: + - generated for "rules maint" + - generated from "control.in" and "build-deps" in "rules debian/control::": + * "build-deps" lists build-depends to be inserted in "control + Build-Depends:" + * "control.in" serves of template for package descriptions of Debian main + packages and makes use of special stanzas enclosed in "@" such as + "@GST_ABI" which are replaced via sed in "rules debian/control::" +control.in: + - serves generation of "control" in "rules debian/control::" via "mk.control" + called in "rules debian/control::" + - template for package descriptions of Debian main packages and makes use of + special stanzas enclosed in "@" such as "@GST_ABI" which are replaced via + sed in "rules debian/control::" +copyright: handled classically +gstreamer-$plugin.install: + - serves the generation of $gst_pkgname-$plugin.install (for example + gstreamer-alsa.install serves the generation of gstreamerX.Y-alsa.install) in + "rules pre-build::" via dynamic "@"-enclosed variables replacement + - some plugins are handled specially and some special variables are available +gstreamer-plugins-base-apps.install: this isn't really a plugin, but the + gstreamerX.Y-plugins-base-apps package +gstreamer-plugins-base-apps.manpages: man pages for the gstreamerX.Y-plugins-base-apps + package +HACKING.Debian: this file +libgstreamer-plugins-base-dev.install libgstreamer-plugins-base.install: handled similarly has gstreamerX.Y-plugins-base-apps +maint: makefile wrapping some targets of "rules" with some sh filtering +mk.control: + - Perl script serving the generation of "control" which reads "build-deps" + and "control.in", and replaces the "BUILDDEPS" stanza with the build-deps +patches: handled classically +README.Debian: handled classically +rules: handled classically, with special targets "maint:", and + "debian/build-deps:" +watch: handled classically + +This file is the initial work of: +David I. Lehn Tue, 13 Apr 2004 21:28:55 -0400 +and had some additions by: +Loic Minier Sun, 19 Jun 2005 19:04:58 +0200 +Sebastien Bacher Wed, 14 Dec 2005 17:00:21 +0100 diff --git a/gst-plugins-base-subtitles0.10/debian/README.Debian b/gst-plugins-base-subtitles0.10/debian/README.Debian new file mode 100644 index 0000000..5149382 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/README.Debian @@ -0,0 +1,64 @@ +Gstreamer for Debian +==================== +This package contains the GStreamer plugin distribution. + +More information can be found at http://gstreamer.net/ + +As of GStreamer plugins version 0.8.0 all packages are versioned and +parallel installable with other releases with other major.minor +versions. For example, 0.8.x series is versioned as 0.8 and parallel +installable with both unversioned 0.6.x series and future 0.9.x and +beyond. The version part is represented as VER below. + +GStreamer plugins are split into a number of packages: + +plugins without external dependencies: + + gstreamerVER-misc many independent plugins + +plugins with external dependencies: + + gstreamerVER-alsa + gstreamerVER-gnomevfs + gstreamerVER-x + +libraries and library plugins: + + libgstreamer-plugins-baseVER-# various libs + libgstreamer-plugins-baseVER-dev development files for above package + +documentation: + + gstreamerVER-plugins-base-doc html documentation + +applications: + + gstreamerVER-plugins-base-apps small script apps to using gst-launch + + +Notes +===== + +ChangeLog +--------- + +The upstream ChangeLog is not included in all the plugin packages due to its +large size. Please see upstream sources if you are interested in detailed +source changes. + +External tools support +---------------------- + +Your favorite codec isn't wrapped as a plugin? External programs can be +used to process streams. Take a look at "pipefilter" element or try +something like this (untested): + + $ mkfifo fifo + $ gst-launch myaudiosrc ! filesink location=fifo & + $ cat fifo | my_encoder > output_file + + +David I. Lehn Tue, 23 Mar 2004 04:38:37 -0500 + +update: +Sebastien Bacher Wed, 14 Dec 2005 17:00:21 +0100 diff --git a/gst-plugins-base-subtitles0.10/debian/TODO.Debian b/gst-plugins-base-subtitles0.10/debian/TODO.Debian new file mode 100644 index 0000000..065cc10 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/TODO.Debian @@ -0,0 +1,18 @@ + +WIP: +- ping alsa plugin submitters of bugs now against libasound + +- document adding a plugin (depends: in control, var in debian/rules...) + thoroughly + +- sort out things of gstreamer0.10-misc + +- fix Depends in gstreamer0.10-plugins with non-linux Depends (alsa...)? + +- add *.la to -dev packages + +- install changelog and symlinks + +- bump up build-deps on xlibs to ensure libraries are in /usr/lib when I + relibtoolize + diff --git a/gst-plugins-base-subtitles0.10/debian/api b/gst-plugins-base-subtitles0.10/debian/api new file mode 100644 index 0000000..96a7839 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/api @@ -0,0 +1,8 @@ +# subsystem: GStreamer +# src-pkg: gst-plugins-base0.10 +interface: gstreamer0.10-plugins-base +type: library +libs-pkg: libgstreamer-plugins-base0.10-0 +dev-pkg: libgstreamer-plugins-base0.10-dev +state: stable +scope: Nokia MeeGo diff --git a/gst-plugins-base-subtitles0.10/debian/changelog b/gst-plugins-base-subtitles0.10/debian/changelog new file mode 100644 index 0000000..7dda187 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/changelog @@ -0,0 +1,2458 @@ +gst-plugins-base-subtitles0.10 (0.10.34-0maemo1+0m6) unstable; urgency=low + + * Created package gst-plugins-base-subtitles0.10 base on gst-plugins-base0.10 + + -- Roman Moravcik Wed, 22 Jun 2011 08:07:13 +0200 + +gst-plugins-base0.10 (0.10.34-0maemo1+0m6) unstable; urgency=low + + * This entry has been added by BIFH queue processor + version has been changed to 0.10.34-0maemo1+0m6 + + -- BIFH Bot Wed, 18 May 2011 14:45:01 +0300 + +gst-plugins-base0.10 (0.10.34-0maemo1) unstable; urgency=low + + * New (minor) upstream release. + * uridecodebin: use bitrate to configure streaming buffer-duration + default case + * Fixes: NB#225307 - Excessive delay when playing some clips + + -- Rene Stadler Wed, 18 May 2011 14:45:00 +0300 + +gst-plugins-base0.10 (0.10.32.2-0maemo1) unstable; urgency=low + + * New upstream pre-release. + * Fixes: NB#245552 - GStreamer doesn't provide tag definition for + exposure compensation + * tag: add support for setting XMP schemas + * Fixes: NB#246293 - Unable configure xmp schema for captured video and + image metadata + * Add unit test for videoscale negotiation regression fix. + * ringbuffer: fix potential deadlock on state change + + -- Rene Stadler Tue, 26 Apr 2011 17:34:19 +0300 + +gst-plugins-base0.10 (0.10.32-0maemo6) unstable; urgency=low + + * baseaudiosink: add upstream fix to keep clock running during + EOS. Required for NB#200893 - "dsp_thread: eos timed out..." received + after requesting GST_STATE_PAUSED near EOS + + -- Rene Stadler Tue, 19 Apr 2011 02:10:35 +0300 + +gst-plugins-base0.10 (0.10.32-0maemo5) unstable; urgency=low + + * Add dependencies to required -doc packages. + * Change MeeGo API scope to "Nokia MeeGo". + * baseaudiosink: add upstream bugfix for pausing near EOS + * Fixes: NB#200893 - "dsp_thread: eos timed out..." received after + requesting GST_STATE_PAUSED near EOS + * Add encodebin-related bugfixes from upstream for audiorate, videorate, + pbutils. + + -- Rene Stadler Wed, 09 Mar 2011 19:33:58 +0200 + +gst-plugins-base0.10 (0.10.32-0maemo4) unstable; urgency=low + + * Move optional plugins to extra. + * Fixes: NB#198530 - Gstreamer allocates >0.5MB when it's initialized, in + gst_registry_binary_read_cache() + + -- Stefan Kost Thu, 03 Mar 2011 09:56:37 +0200 + +gst-plugins-base0.10 (0.10.32-0maemo3) unstable; urgency=low + + * Require released gstreamer (core) version again. + * Disable glib asserts in non-debug builds. + * Add support for "nodocs" in DEB_BUILD_OPTIONS. + * Add upstream fixes: + * Fixes: NB#183323 - There's no GST_TAG for 'encoded by' id3v24 property + * Fixes: NB#228184 - playbin2: after replacing a video sink with the + pipeline in NULL, it still returns the old one + + -- Rene Stadler Thu, 24 Feb 2011 19:05:22 +0200 + +gst-plugins-base0.10 (0.10.32-0maemo2) unstable; urgency=low + + * Lower required core version a bit. + + -- Rene Stadler Wed, 26 Jan 2011 13:32:52 +0200 + +gst-plugins-base0.10 (0.10.32-0maemo1) unstable; urgency=low + + * New upstream release. + * Add xmp tag fix for crasher, from master branch. + * Fixes: NB#220537 - Crash while trying to play recorded video from + postcapture + + -- Rene Stadler Tue, 25 Jan 2011 17:09:49 +0200 + +gst-plugins-base0.10 (0.10.31.3-0maemo1) unstable; urgency=low + + * New upstream pre-release. + + -- Rene Stadler Fri, 14 Jan 2011 17:41:45 +0200 + +gst-plugins-base0.10 (0.10.31.2-0maemo2) unstable; urgency=low + + * Install new encodebin plugin. + + -- Rene Stadler Fri, 14 Jan 2011 13:28:34 +0200 + +gst-plugins-base0.10 (0.10.31.2-0maemo1) unstable; urgency=low + + * New upstream pre-release. + * Add missing build dependency. + * Fixes: NB#216662 - gst-plugins-base0.10: add python to build-deps + + -- Rene Stadler Mon, 10 Jan 2011 18:21:43 +0200 + +gst-plugins-base0.10 (0.10.30.5-0maemo1) unstable; urgency=low + + * New upstream pre-release. Fixes a small memory leak. Disables "stream + synchronizer". + * Fixes: NB#200893 - "dsp_thread: eos timed out..." received after + requesting GST_STATE_PAUSED near EOS + + -- Rene Stadler Fri, 19 Nov 2010 16:36:45 +0200 + +gst-plugins-base0.10 (0.10.30-git382-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-382-g0d39e28. + + -- Rene Stadler Tue, 02 Nov 2010 21:14:36 +0200 + +gst-plugins-base0.10 (0.10.30-git250-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-250-g78b2ab6. + + -- Rene Stadler Thu, 30 Sep 2010 17:31:28 +0300 + +gst-plugins-base0.10 (0.10.30-git243-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-243-g97d4940. + * Fixes: NB#192853 - "oe" ligature character is not supported in WAV + file + * Fixes: NB#194794 - Euro sign is not present in AVI file description + * Update Meego api file. + * Fixes: NB#195211 - Source package 'gst-plugins-base0.10' interfaces + not frozen + + -- Rene Stadler Wed, 29 Sep 2010 14:33:23 +0300 + +gst-plugins-base0.10 (0.10.30-git224-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-224-g6ecbdab. + * Fix build dependencies. + * Fixes: NB#192344 - add autopoint to build-deps + + -- Rene Stadler Wed, 22 Sep 2010 19:14:22 +0300 + +gst-plugins-base0.10 (0.10.30-git130-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-130-ge75e7df. + + -- Rene Stadler Wed, 01 Sep 2010 15:45:46 +0300 + +gst-plugins-base0.10 (0.10.30-git40-0maemo2) unstable; urgency=low + + * streamsynchronizer: fix a set o regressions (e.g. deadlock when a stream + reaches EOS without having seen data). + * Fixes: NB#158981 - GStreamer hangs when performing consecutive + out-of-limits seeks in PAUSED state + + -- Marco Ballesio Fri, 13 Aug 2010 09:00:00 +0300 + +gst-plugins-base0.10 (0.10.30-git40-0maemo1) unstable; urgency=low + + * Update to git master v0.10.30-40-g818f395. + * oggdemux: extract vorbis metadata in fast tagreading mode (without a + decoder). + * Fixes: NB#166634 - All the metadata details are not extracted for ogg + files + + -- Rene Stadler Tue, 27 Jul 2010 15:03:08 +0300 + +gst-plugins-base0.10 (0.10.29.4-0maemo1) unstable; urgency=low + + * Update to pre-release. + + * tagreading: Fix "unknown" codec tag missing after one usage. + * Fixes: NB#177150 - tagreadbin only finds unkown audio codec for + asf files once + * xvimagesink: Add Maemo-specific overlay stacking order property + support. + * Fixes: NB#167045 - Add XV_STACKING support to xvimagesink + * Add MeeGo API file. + * Fixes: NB#173662 - Add an API file to gstreamer0.10-plugins-base + * Move pango, gdp plugins from -extra to the main package. + + -- Rene Stadler Thu, 08 Jul 2010 19:05:28 +0300 + +gst-plugins-base0.10 (0.10.29-git81-0maemo1) unstable; urgency=low + + * Update to git master v0.10.29-81-ga6a125e. + * Fixes: NB#166293 - Increasing number of GLIB CRITICAL messages from + GStreamer leading ultimately to application crash/exit + * Drop unused gnomevfs legacy patches. + + -- Rene Stadler Fri, 14 May 2010 18:00:35 +0300 + +gst-plugins-base0.10 (0.10.29-git40-0maemo2) unstable; urgency=low + + * decodebin2: don't plug decoders when we don't need them (in some cases) + * Fixes: NB#164872 - GES unable to play any clip due to multiple decoder + allocation + + -- Rene Stadler Fri, 07 May 2010 13:16:06 +0300 + +gst-plugins-base0.10 (0.10.29-git40-0maemo1) unstable; urgency=low + + * Update to git master v0.10.29-40-gf99cb8b. + + -- Rene Stadler Wed, 05 May 2010 14:38:52 +0300 + +gst-plugins-base0.10 (0.10.28-git169-0maemo2) unstable; urgency=low + + * Add ivorbisdec plugin. + + -- Rene Stadler Mon, 19 Apr 2010 17:28:28 +0300 + +gst-plugins-base0.10 (0.10.28-git169-0maemo1) unstable; urgency=low + + * Update to git master v0.10.28-169-g3ec87ee. + * Fixes: NB#163614 - Only audio is heard while playing default video + clip + + -- Rene Stadler Wed, 14 Apr 2010 19:57:30 +0300 + +gst-plugins-base0.10 (0.10.28-git130-0maemo1) unstable; urgency=low + + * Update to master v0.10.28-130-gb37c993 + * Fixes: NB#161467 - MPEG4 video with uncommon FOURCC fails to play + * Fixes: NB#158981 - GStreamer hangs when performing consecutive + out-of-limits seeks in PAUSED state + * Fixes: NB#158402 - Playback freezes if paused near end of stream + + -- Rene Stadler Thu, 01 Apr 2010 14:55:35 +0300 + +gst-plugins-base0.10 (0.10.28-0maemo2) unstable; urgency=low + + * Fix tagreading patch. + + -- Rene Stadler Wed, 31 Mar 2010 21:13:36 +0300 + +gst-plugins-base0.10 (0.10.28-0maemo1) unstable; urgency=low + + * New upstream version. + + -- Rene Stadler Fri, 26 Mar 2010 18:02:50 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo15) unstable; urgency=low + + * Add OGG plugin. + * Drop GnomeVFS plugin package. + * Remove Debian .symbols file. + + -- Rene Stadler Wed, 24 Mar 2010 16:32:53 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo14) unstable; urgency=low + + * uridecodebin: Fix leaking of queue and typefinder elements. + * playbin2: Fix leaking of selector request pads. + * Helps NB#139441 - Memory leak in mafw-dbus-wrapper with Mp3 playback + over UPnP + + -- Rene Stadler Mon, 15 Feb 2010 20:03:01 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo13) unstable; urgency=low + + * basertppayload: Reject empty caps. + + -- Rene Stadler Fri, 22 Jan 2010 18:28:49 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo12) unstable; urgency=low + + * basertppayload: Change ptime to be in nanoseconds instead of + milliseconds and change data type to unsigned integer. + + -- Rene Stadler Thu, 21 Jan 2010 15:17:59 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo11) unstable; urgency=low + + * tagreadbin: Fix possible deadlock on shutdown. + * Fixes: NB#153179 - deadlock in tagreadbin + + -- Rene Stadler Fri, 15 Jan 2010 15:26:25 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo10) unstable; urgency=low + + * basertpaudiopayload: Respecet ptime if it is given + * rtpbasepayload: Store ptime from caps + * basertppayload: Accept maxptime from caps + * Fixes: NB#152494 - Import ptime/maxptime patches in gst-p-base/good + + -- Harri Mähönen Fri, 08 Jan 2010 13:02:49 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo9) unstable; urgency=low + + * xvimagesink: Add disable-colorkey property. + * Fixes: NB#128210 - Xv video sink should be able to disable color + keying + + -- Rene Stadler Mon, 21 Dec 2009 20:19:57 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo8) unstable; urgency=low + + * playsink: fix playback of videos with subtitles when subtitles are + disabled + * Fixes: NB#149693 - m4a podcast with subtitles fails to play with + playbin2 flags=99 + + -- Rene Stadler Wed, 09 Dec 2009 15:48:30 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo7) unstable; urgency=low + + * playbin2: Fix possible problems when re-using sinks (e.g. MAFW). + * baseaudiosink: Fix initial clock calibration value. + * baseaudiosink: Fix time adjustment when slaving, fixing (permanent) + audio dropout when re-using sinks after changing clock (when pausing + stream). + * Fixes: NB#135792 - rtsp audio streams cannot be resumed after pausing + + -- Rene Stadler Wed, 25 Nov 2009 19:49:18 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo6) unstable; urgency=low + + * baseaudiosrc: Fix startup position in ringbuffer. + * Fixes: NB#145101 AV Sync: Audio lags the Video beyond 30 seconds for + recorded videos + + -- Rene Stadler Mon, 09 Nov 2009 13:24:16 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo5) unstable; urgency=low + + * Workaround more filetypes causing problems when ID3-tagged. + * Fixes: NB#142716 - Playback of the provided wma songs fails, 100% cpu + load in mafw-gst-renderer + + -- Rene Stadler Wed, 28 Oct 2009 11:30:58 +0200 + +gst-plugins-base0.10 (0.10.25-0maemo4) unstable; urgency=low + + * basertpaudiopayload: Fix frame size. Fixes iLBC mode 30 call + regression. + * Fixes: NB#142953 - N900 to PC ilbc gtalk voip call is broken + * Fixes: NB#135559 - Poor speech quality in Google Talk + + -- Rene Stadler Fri, 23 Oct 2009 13:01:29 +0300 + +gst-plugins-base0.10 (0.10.25-0maemo3) unstable; urgency=low + + * baseaudiosrc: Fix timestamp/base_time comparision. This caused severe + timing problems when an audio source was added to a running pipeline. + + -- Rene Stadler Fri, 16 Oct 2009 15:00:58 +0300 + +gst-plugins-base0.10 (0.10.25-0maemo2) unstable; urgency=low + + * Work around decoding problem for ID3-tagged quicktime files. + * Fixes: NB#134099 - M4A Files are not played as ringtone, although can + be selected + + -- Rene Stadler Tue, 13 Oct 2009 14:20:10 +0300 + +gst-plugins-base0.10 (0.10.25-0maemo1) unstable; urgency=low + + * New upstream version. + * Fixes: NB#136325 - Bad VoIP audio experience on receiver side + * Fixes: NB#134936 - Add a 'prerolling-render' property to avoid + rendering while prerolling + * Add libcairo2-dev build dependency. + + -- Rene Stadler Tue, 06 Oct 2009 13:04:24 +0300 + +gst-plugins-base0.10 (0.10.24-0maemo1) unstable; urgency=low + + * New upstream version. + * Always build with -Wno-error. + + -- Rene Stadler Tue, 15 Sep 2009 17:24:17 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo6) unstable; urgency=low + + * queue2: Fix error handling corner case to not appear like a hang. + + -- Rene Stadler Fri, 11 Sep 2009 15:43:21 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo5) unstable; urgency=low + + * tagreadbin: Fix possible crash on NULL caps. + * Fixes: NB#135291 - tracker-extract is crashing for wav file + + -- Rene Stadler Wed, 09 Sep 2009 11:43:55 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo4) unstable; urgency=low + + * Enable NEON optimization compilation flags in ARM builds. + * Fixes: NB#124297 - Still image preview should be shown as soon as + possible + * Also compile debug builds with -O2. + + -- Rene Stadler Tue, 18 Aug 2009 15:51:59 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo3) unstable; urgency=low + + * Use -O2 optimization flag in release mode. Partially fixes NB#129635. + + -- Harri Mahonen Thu, 30 Jul 2009 10:53:24 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo2) unstable; urgency=low + + * ffmpegcolorspace: optimizations for colorspaceconversion + * playbin: better errormessages + * uridecodebin: handle uri-schemas incasesensitive + * Fixes: NB#124297 - Still image preview should be shown as soon as + possible + + -- Stefan Kost Thu, 16 Jul 2009 17:29:59 +0300 + +gst-plugins-base0.10 (0.10.23-git246-0maemo1) unstable; urgency=low + + * Update to v0.10.23-246-g8937c89. + + -- Rene Stadler Mon, 06 Jul 2009 00:24:29 +0300 + +gst-plugins-base0.10 (0.10.23-0maemo5) unstable; urgency=low + + * audiosrc: Fix get_offset. + * Fixes: NB#113906 - First timestamps not increasing with reused pulsesrc + + -- Rene Stadler Wed, 24 Jun 2009 16:14:05 +0300 + +gst-plugins-base0.10 (0.10.23-0maemo4) unstable; urgency=low + + * playbin2: Fix pulsesink initial volume handling even more. + * Fixes MAFW playback volume being 100% after pausing for one minute. + + -- Rene Stadler Wed, 10 Jun 2009 18:16:56 +0300 + +gst-plugins-base0.10 (0.10.23-0maemo3) unstable; urgency=low + + * playbin2: Fix pulsesink initial volume/mute handling. + * Fixes: NB#108833 - System volume & application volume settings not in + sync. + + -- Rene Stadler Mon, 25 May 2009 15:50:41 +0300 + +gst-plugins-base0.10 (0.10.23-0maemo2) unstable; urgency=low + + * Add new fast tagreading. + * Fixes: NB#99656 - Tagreadbin can't be used to obtain content information + + -- Rene Stadler Tue, 19 May 2009 15:43:09 +0300 + +gst-plugins-base0.10 (0.10.23-0maemo1) unstable; urgency=low + + * New upstream release. + * Drop old playbin patch that added unused functionality. + * Fixes: NB#116050 - crash in rtcp parsing in ssrcdemux + + -- Rene Stadler Thu, 14 May 2009 18:07:00 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo15) unstable; urgency=low + + * Include app library in correct library package, fixes app plugin being + unloadable. + + -- Rene Stadler Thu, 07 May 2009 17:06:42 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo14) unstable; urgency=low + + * uridecodebin: Enable buffering for the upnpav:// protocol. + * Fixes: NB#106636 - UPNP:Buffering not displayed when launched from + file manager + * Ship app plugin. + + -- Rene Stadler Tue, 05 May 2009 14:42:30 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo13) unstable; urgency=low + + * rtp: Don't assert on invalid RTCP packet data. + * Fixes: NB#111610 - gst rtcp parser asserts on invalid packets + * Disable GObject cast checks and GStreamer logging (unless debug build + option is given). + + -- Rene Stadler Mon, 20 Apr 2009 14:05:07 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo12) unstable; urgency=low + + * playbin2: Fix leaking audio/video sinks set through properties. + * audioresample: Add upstream patch to improve sample rate negotiation. + + -- Rene Stadler Fri, 03 Apr 2009 16:26:12 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo11) unstable; urgency=low + + * xvimagesink: Change default color key, use display depth to calculate + max value, fix conversion for 16 bit visuals. + * Fixes: NB#96153 - GStreamer does not report video overlay color + correctly + * Move pango plugin from -x to -extra package. + + -- Rene Stadler Tue, 31 Mar 2009 14:26:55 +0300 + +gst-plugins-base0.10 (0.10.22-1maemo10) unstable; urgency=low + + * Cherry-pick playbin2 fix for a bad regression introduced with + 0.10.22-1maemo8. + * Fixes: NB#100182 - Media player is crashing with the signal : + Application 'mp_ap_name' process 'mediaplayer' and 'mafw-dbus-wrapper' + + -- Rene Stadler Thu, 12 Mar 2009 18:47:51 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo9) unstable; urgency=low + + * Fix gnomevfs upnpav:// protocol support patch. + * Fixes: NB#94870 - Not able to play music via UPnP server(shared media) + * Cherry-pick Mark's latest decodebin2 deadlock fix. + * Fixes: NB#103949 - Dbus connectivity lost when double clicking of + MPEG4 clip in MTG + + -- Rene Stadler Thu, 12 Mar 2009 12:23:25 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo8) experimental; urgency=low + + * Cherry-pick Mark's playbin2 deadlock fixes. Fixes: NB#90571 + (No state change from READY to PAUSED received for playbin). + Partial fix for NB#93647 (pipeline deadlocks on downwards state + change). + * Cherry-pick Stefan's cleanup patches to silence Coverity. Small + improvements for ximagesink. + + -- Rene Stadler Mon, 02 Mar 2009 16:21:01 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo7) experimental; urgency=low + + * Add Maemo specific patch to change baseaudiosrc, baseaudiosink default + latency-time from 10 to 40ms, which improves global CPU usage with + PulseAudio. Affects users that do not set the latency-time explictly + (MAFW/Media Player, event sounds). + * Cherry-pick playbin2 fixes from upstream: Many leaks fixed (including + fix of the audio sink), possible crasher, small performance + improvement. + * New package gstreamer0.10-plugins-base-extra, shipping the gdp plugin + (very useful for debugging). + + -- Rene Stadler Fri, 27 Feb 2009 19:21:05 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo6) experimental; urgency=low + + * Fix transparency when pipeline changes state. Fixes: NB#100663 + + -- Maemo Multimedia Wed, 18 Feb 2009 12:36:36 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo5) experimental; urgency=low + + * Add debugging info to xvimagesink. + + -- Maemo Multimedia Wed, 11 Feb 2009 10:06:43 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo4) experimental; urgency=low + + * playbin2: Implement GST_PLAY_FLAG_NATIVE_AUDIO and _VIDEO. + * speexresample: Disable integer resampler to skip benchmarking. + + -- Maemo Multimedia Wed, 04 Feb 2009 17:22:39 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo3) experimental; urgency=low + + * Backport #570356: Make the flac check more tight not to mistake + some AAC files for FLAC. + + -- Maemo Multimedia Wed, 04 Feb 2009 11:43:29 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo2) experimental; urgency=low + + * Enabled debug packages for alsa, gnomevfs and x. Fixes: NB#99911 + + -- Maemo Multimedia Fri, 30 Jan 2009 11:03:01 +0200 + +gst-plugins-base0.10 (0.10.22-1maemo1) experimental; urgency=low + + * New upstream release with Maemo-specific patches applied. + + -- Maemo Multimedia Thu, 22 Jan 2009 09:18:46 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo10) experimental; urgency=low + + * Removed locatilization files. + + -- Stefan Kost Wed, 14 Jan 2009 13:16:39 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo9) experimental; urgency=low + + * Don't reset the colorkey when reusing xvimagesink. backported from current + cvs. + + -- Stefan Kost Tue, 13 Jan 2009 15:10:47 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo8) experimental; urgency=low + + * Resurrect xvideo changes for overlays. + + -- Stefan Kost Mon, 15 Dec 2008 11:52:01 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo7) experimental; urgency=low + + * Remove GstImplementsInterface redirection in fast-tagreading. + + -- Stefan Kost Thu, 11 Dec 2008 14:44:45 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo6) experimental; urgency=low + + * Add seek test application of gstreamer0.10-plugins-base-apps package. + + -- Stefan Kost Wed, 26 Nov 2008 12:36:07 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo5) experimental; urgency=low + + * Don't post an error when we can't configure the volume but post a + warning instead. Fixes #561780. + http://webcvs.freedesktop.org/gstreamer/gst-plugins-base/gst/playback/gstplaysink.c?r1=1.19&r2=1.20 + + -- Stefan Kost Mon, 24 Nov 2008 09:31:30 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo4) experimental; urgency=low + + * Remove gst photography interface that was moved to plugins-camera + + -- Stefan Kost Mon, 3 Nov 2008 11:18:50 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo3) experimental; urgency=low + + * Fixed changelog + * Enabled --enable-experimental flag in debian/rules to get GIO. + * Added GIO to installation. GIO installation file defined. + + -- Stefan Kost Thu, 30 Oct 2008 15:13:48 +0200 + +gst-plugins-base0.10 (0.10.21-2maemo2) experimental; urgency=low + + * New tagged version (0.10.21-2maemo2). + + -- Stefan Kost Wed, 22 Oct 2008 10:33:35 +0300 + +gst-plugins-base0.10 (0.10.21-2maemo1) experimental; urgency=low + + * New upstream version 0.10.21 with Debian experimental patches and + Maemo-specific patches applied. + + -- Stefan Kost Tue, 14 Oct 2008 08:57:10 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo12) unstable; urgency=low + + * Implemented: NR#191979 + + -- Stefan Kost Tue, 21 Oct 2008 12:57:16 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo11) unstable; urgency=low + + * Added shake indicator GstMessage name and enum in GstPhotography interface + + -- Stefan Kost Mon, 20 Oct 2008 13:36:05 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo10) unstable; urgency=low + + * Changed focus mode handling in GstPhotography interface + + -- Stefan Kost Thu, 16 Oct 2008 13:39:29 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo9) unstable; urgency=low + + * Fixed an error in one makefile that made the build to fail + + -- Stefan Kost Tue, 14 Oct 2008 14:25:05 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo8) unstable; urgency=low + + * Add xvimagesink back to distribution + * Update TagReadBin documentation + * Make TagReadBin to use queue2 instead of queue + + -- Stefan Kost Fri, 10 Oct 2008 13:22:47 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo7) unstable; urgency=low + + * Add sanity checks for photography.c function parameters + * Add missing file: tests/icles/test-colorkey.c + + -- Stefan Kost Tue, 7 Oct 2008 10:43:01 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo6) unstable; urgency=low + + * Implement setting the colorkey and querying this capability. Patch + available upstream at http://bugzilla.gnome.org/show_bug.cgi?id=554533. + + -- Stefan Kost Wed, 1 Oct 2008 11:33:23 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo5) unstable; urgency=low + + * Fix libgsttag linking + + -- Stefan Kost Mon, 15 Sep 2008 13:00:40 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo4) unstable; urgency=low + + * Added a function to prepare an element for photo capturing + * Sync xvimagesink with CVS head + + -- Stefan Kost Mon, 15 Sep 2008 11:08:17 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo3) unstable; urgency=low + + * Modified vv4l2src so that it works with OMAP3 camera + * Fixed a segfault from "seek" test application + + -- Stefan Kost Thu, 21 Aug 2008 10:27:14 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo2) unstable; urgency=low + + * Disabled xvimagesink + * Disabled dh_gstscancodecs to make it compile under sbox + + -- Stefan Kost Thu, 14 Aug 2008 13:28:58 +0300 + +gst-plugins-base0.10 (0.10.20-0maemo1) unstable; urgency=low + + * New upstream release 0.10.20 with Maemo-specific modifications + + -- Stefan Kost Tue, 5 Aug 2008 09:48:21 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo9) unstable; urgency=low + + * Updates to GstPhotography interface + * Minor update to TagReader interface documentation + + -- Stefan Kost Mon, 21 Jul 2008 15:43:00 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo8) unstable; urgency=low + + * Updated GstPhotography interface + + -- Stefan Kost Tue, 15 Jul 2008 10:31:37 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo7) unstable; urgency=low + + * Add xvimagesink colorkey properties + + -- Stefan Kost Wed, 25 Jun 2008 16:43:42 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo6) unstable; urgency=low + + * Added gst photo inteface + + -- Stefan Kost Fri, 13 Jun 2008 12:43:55 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo5) unstable; urgency=low + + * Backported decodebin2 and uridecodebin from CVS + * Optimized mp3 and mpeg_sys typefinding a bit + + -- Stefan Kost Fri, 6 Jun 2008 09:51:27 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo4) unstable; urgency=low + + * Now TagReader interface can be used to skip tag reading process + * Updated tagreadbin and tagdemux to work with this new interface + + -- Stefan Kost Mon, 19 May 2008 12:15:53 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo3) unstable; urgency=low + + * Now TagReadBin gets actually installed into deb package + * Fixed bugs and memory leaks in tagreadbin + + -- Stefan Kost Fri, 25 Apr 2008 14:09:57 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo2) unstable; urgency=low + + * Added features to seek.c test application + * Now TagDemux implements TagReader interface + * Added TagReader interface + * Added TagReadBin + * Removed xvimagesink patches + + -- Stefan Kost Thu, 24 Apr 2008 15:00:19 +0300 + +gst-plugins-base0.10 (0.10.19-0maemo1) unstable; urgency=low + + * New upstream release 0.10.19 with Maemo-specific modifications. + + -- Stefan Kost Tue, 8 Apr 2008 15:34:42 +0300 + +gst-plugins-base0.10 (0.10.17-0maemo3) unstable; urgency=low + + * Remove forced tcp interleaved mode for rtsp + + -- Stefan Kost Tue, 11 Mar 2008 11:52:05 +0200 + +gst-plugins-base0.10 (0.10.17-0maemo2) unstable; urgency=low + + * Handle negative delay from alsa snd_pcm_delay + * Updated dependecies + + -- Stefan Kost Thu, 14 Feb 2008 09:46:00 +0200 + +gst-plugins-base0.10 (0.10.17-0maemo1) unstable; urgency=low + + * New upstream release 0.10.17. + + -- Stefan Kost Thu, 31 Jan 2008 10:59:21 +0200 + +gst-plugins-base0.10 (0.10.15-2maemo4) unstable; urgency=low + + * Sync playbin/playbin2 related updates from gst cvs + + -- Stefan Kost Thu, 10 Jan 2008 10:17:09 +0200 + +gst-plugins-base0.10 (0.10.15-2maemo3) unstable; urgency=low + + * Added a couple of valgrind suppressions to disable unnecessary errors + + -- Stefan Kost Fri, 21 Dec 2007 11:47:45 +0200 + +gst-plugins-base0.10 (0.10.15-2maemo2) unstable; urgency=low + + * Imported Maemo-specific modifications from 0.10.13 + + -- Stefan Kost Wed, 5 Dec 2007 14:55:27 +0200 + +gst-plugins-base0.10 (0.10.15-2maemo1) unstable; urgency=low + + * Branched version for Maemo + * Removed debian-specific patches + * Removed some package dependencies + * Removed some plugins from install files + * Changed maintainer information + * Added running of autogen.sh into debian/rules + + -- Stefan Kost Tue, 27 Nov 2007 17:24:38 +0200 + +gst-plugins-base0.10 (0.10.15-2) unstable; urgency=low + + * debian/rules, + debian/build-deps.in: + + Use HOME instead of GNOME_VFS_HOME as the variable name changed in + 2.20.0-2. (Closes: #451905) + + -- Sebastian Dröge Mon, 19 Nov 2007 17:24:06 +0100 + +gst-plugins-base0.10 (0.10.15-1) unstable; urgency=low + + * New upstream release, "Light Years Ahead", with API additions: + + Fixes FTBFS if built twice in a row (Closes: #442587). + + debian/patches/02_short-ogg-files.patch: + - Dropped, merged upstream. + + debian/control.in: + - Update gstreamer0.10 build dependency to >= 0.10.14.1. + + debian/libgstreamer-plugins-base.install: + - Add new libgstfft library. + + -- Sebastian Dröge Tue, 13 Nov 2007 15:06:10 +0100 + +gst-plugins-base0.10 (0.10.14-4) unstable; urgency=low + + * debian/patches/02_short-ogg-files.patch: + + Fix playback of very short Ogg/Vorbis files. Patch from upstream CVS, + (Closes: #441364). + * debian/rules: + + s/curdir/CURDIR/ to fix FTBFS. + * debian/build-deps.in: + + Fix minimal required GnomeVFS version. + + -- Sebastian Dröge Sun, 09 Sep 2007 12:01:19 +0200 + +gst-plugins-base0.10 (0.10.14-3) unstable; urgency=low + + * debian/build-deps.in, + debian/rules: + + Require GnomeVFS >= 2.18.1-4 for the GNOME_VFS_HOME environment + variable and use this and GST_REGISTRY for the dh_gstscancodecs call + to make it work on buildds with non-writable homes. + + -- Sebastian Dröge Fri, 07 Sep 2007 16:08:15 +0200 + +gst-plugins-base0.10 (0.10.14-2) unstable; urgency=low + + [ Sebastian Dröge ] + * debian/rules: + + Correctly set LD_LIBRARY_PATH for dh_gstscancodecs. + * debian/control.in: + + Recommend libgnomevfs2-extra on gstreamer0.10-gnomevfs. This is + necessary to get HTTP support (Closes: #432363). + + [ Loic Minier ] + * Fix LD_LIBRARY_PATH. + * Drop misc obsolete compatibility vars from rules. + * Drop useless $(version). + * Cleanup rules. + + [ Sebastian Dröge ] + * debian/rules: + + Don't call dh_gstscancodecs for now. As GnomeVFS needs a writable home + directory when initializing dh_gstscancodecs fails on the GnomeVFS + plugin and the build fails (Closes: #435978). + + -- Sebastian Dröge Mon, 13 Aug 2007 14:22:15 +0200 + +gst-plugins-base0.10 (0.10.14-1) unstable; urgency=low + + [ Sebastian Dröge ] + * New upstream release 'Light Years Ahead', with API additions: + + Uses ALSA mixer notifications instead of polling (Closes: #424016). + * debian/patches/20_oggmux-schroedinger.patch: + + Dropped, merged upstream. + * debian/rules: + + Update gstreamer0.10 build dependency to >= 0.10.13.1. + * debian/libgstreamer-plugins-base.install: + + Add new libgstrtsp and libgstsdp libraries. + * debian/gstreamer-plugins-base.install: + + Add queue2 and uridecodebin plugins. + * debian/control.in: + + Suggest libvisual-0.4-plugins in gstreamer0.10-plugins-base for the + libvisual plugin. + + Use ${binary:Version} instead of ${Source-Version} to make lintian + happy. + + [ Loic Minier ] + * Pass --with-install-plugins-helper="/usr/bin/gnome-codec-install" to + configure; thanks Julian Andres Klode; suggest gnome-app-install; + closes: 434999. + + [ Sebastian Dröge ] + * debian/rules, + debian/build-deps.in: + + Run dh_gstscancodecs to export the codecs database. + + -- Sebastian Dröge Fri, 03 Aug 2007 17:31:53 +0200 + +gst-plugins-base0.10 (0.10.13-2) unstable; urgency=low + + * debian/patches/20_oggmux-schroedinger.patch: + + Patch from upstream CVS to fix muxing of Dirac video in Ogg containers. + + -- Sebastian Dröge Thu, 07 Jun 2007 16:29:57 +0200 + +gst-plugins-base0.10 (0.10.13-1) unstable; urgency=low + + * New upstream release with some API additions, "What's going on?": + + Fixes internal dataflow error with subtitles (Closes: #425323). + * debian/rules: + + There's no gstreamer0.10-theora package anymore since ages so don't try + to generate an install file for it. + * debian/control: + + Update libtheora build dependency. At least 1.0alpha5 is now required. + + -- Sebastian Dröge Tue, 05 Jun 2007 17:29:51 +0200 + +gst-plugins-base0.10 (0.10.12.1+cvs20070529-1) unstable; urgency=low + + * Prepare CVS snapshot + * Bump libgstreamer0.10-dev build-depend to 0.10.12.1 + * Add myself to Uploaders + + -- Sjoerd Simons Tue, 29 May 2007 09:08:13 +0200 + +gst-plugins-base0.10 (0.10.12-2) unstable; urgency=low + + * Upload to unstable + * Merge experimental branch: + + New upstream release 0.10.12, "Zombie Horde": + - Updated german translations (Closes: #379505) + - debian/rules: + . Update gstreamer build dependency to >= 0.10.11.1 + - debian/libgstreamer-plugins-base.install: + . Add libgstpbutils-0.10 library + - debian/patches/20_oggdemux-check-bos.patch: + . Dropped, applied upstream + + Let libgstreamer-plugins-base0.10-dev depend on the same version of + libgstreamer0.10-dev as the one gst-plugins-base0.10 build-depends on. + (Loic Minier) + + debian/control: + - Updated to use my debian.org mail address + + New upstream release 0.10.11, "Dumb things": + - debian/patches/70_relibtoolize.patch: + . Dropped, upstream uses Debian's libtool + - debian/build-deps.in: + . Raise liboil0.3-dev build dependency to >= 0.3.8 + - debian/rules: + . Raise gstreamer0.10 build-dependency to >= 0.10.10.1 + - debian/gstreamer-plugins-base.install: + . Add decodebin2 plugin + + -- Sebastian Dröge Mon, 9 Apr 2007 23:40:49 +0200 + +gst-plugins-base0.10 (0.10.10-4) unstable; urgency=medium + + * Fix superfluous .orig file in patch 20_oggdemux-check-bos; + thanks Luk Claes. + + -- Loic Minier Mon, 29 Jan 2007 17:59:40 +0100 + +gst-plugins-base0.10 (0.10.10-3) unstable; urgency=medium + + * New patch, 20_oggdemux-check-bos, fixes handling of problems when reading + BOS pages in the oggdemux element; reported by Sam Hocevar; from + GNOME #399340; closes: #407004. + + -- Loic Minier Mon, 22 Jan 2007 17:39:59 +0100 + +gst-plugins-base0.10 (0.10.10-2) unstable; urgency=low + + * Drop superfluous libgstvideo4linux.so lines in + gstreamer-plugins-base.install; thanks Aurelien Jarno for fixing + GNU/kFreeBSD again! closes: #391853. + + -- Loic Minier Mon, 6 Nov 2006 18:50:31 +0100 + +gst-plugins-base0.10 (0.10.10-1) unstable; urgency=low + + [ Sebastian Dröge ] + * New upstream release, "Chorizo", some API additions. + - Fix handling of ALSA emu10k1 mixer tracks. (Closes: #387095) + - debian/patches/70_relibtoolize.patch: + + Updated + - debian/rules: + + Bump libgstreamer0.10-dev build dependency to (>= 0.10.9.1) + - debian/gstreamer-plugins-base.install: + + Add the new GDP element + + [ Loic Minier ] + * Force generation of debian/control, whatever the timestamps say. + * Fix duplicate dependencies. + + -- Loic Minier Fri, 15 Sep 2006 17:54:16 +0200 + +gst-plugins-base0.10 (0.10.9-3) unstable; urgency=low + + * debian/rules, + debian/control.in: + + Add a -dbg package + * debian/compat, + debian/build-deps.in: + + Bump debhelper compat level to 5 + + -- Sebastian Dröge Wed, 23 Aug 2006 22:14:56 +0200 + +gst-plugins-base0.10 (0.10.9-2) unstable; urgency=medium + + * Don't build the doc on arm and m68k. It's painfully long, and -- at least + on arm -- it segfaults; this is to lower the impact of #383147. + * Update TODO list. + + -- Loic Minier Sat, 19 Aug 2006 23:25:01 +0200 + +gst-plugins-base0.10 (0.10.9-1) unstable; urgency=low + + * New upstream release, "I walk the line", with API additions. + - Bump up libgstreamer0.10-dev build-dep to >= 0.10.8.1. + - Update 10_gnome-vfs-dav-url patch. + - Drop 11_audioresample-non-negociated-errors patch, merged upstream. + - Update 70_relibtoolize patch. + + -- Loic Minier Sat, 15 Jul 2006 11:01:08 +0200 + +gst-plugins-base0.10 (0.10.8-2) unstable; urgency=low + + [ Loic Minier ] + * New patch, 10_gnome-vfs-dav-url, to allow the gnomevfs plugin to handle + dav:// URIs, thanks Mike Hommey. (Closes: #370362) + * New patch, 11_audioresample-non-negociated-errors from upstream, to clear + the internal state of audioresample properly and hence avoid + "non-negociated" errors. (Closes: #376544) + + [ Sebastian Dröge ] + * Change libvisual0.2-dev Build-Depends to libvisual-0.4-dev + + -- Sebastian Dröge Thu, 6 Jul 2006 11:07:35 +0200 + +gst-plugins-base0.10 (0.10.8-1) unstable; urgency=low + + * New upstream release, "Moar gij ziet mij nie". + - Bump up libgstreamer0.10-dev build-dep to >= 0.10.6.1. + - New patch, 70_relibtoolize, ditto. + - Drop 01_alsasink-query-rates, included and changed upstream. + - Query the supported sampling rates from ALSA (Closes: #365877) + + -- Loic Minier Sun, 11 Jun 2006 14:50:05 +0200 + +gst-plugins-base0.10 (0.10.7-2) unstable; urgency=low + + * Bump up Standards-Version to 3.7.2. + [debian/control, debian/control.in] + * Export OIL_CPU_FLAGS=0 for commands launched during the build process as + it can cause build failures on buildds with specific hardware at build + time. + [debian/rules] + + -- Loic Minier Thu, 18 May 2006 14:48:33 +0200 + +gst-plugins-base0.10 (0.10.7-1) unstable; urgency=low + + * Stop shipping /usr/lib/*.la files in libgstreamer-plugins-base-dev. + [debian/libgstreamer-plugins-base-dev.install] + * New upstream release, "Leave the gun", with API additions. + - Bump up inter-dependencies to 0.10.7. + [debian/control] + - Drop relibtoolizing patch as this release was libtoolized under Debian + or a derivative. + [debian/patches/70_relibtoolize.patch] + - Bump up libsgtreamer0.10-dev build-dep to >= 0.10.5.1. + [debian/control, debian/rules] + + -- Loic Minier Sun, 14 May 2006 21:57:10 +0200 + +gst-plugins-base0.10 (0.10.6-1) unstable; urgency=low + + * New upstream release, "Chao". + - Relibtoolize. + [debian/patches/70_relibtoolize.patch] + + -- Loic Minier Fri, 28 Apr 2006 23:10:10 +0200 + +gst-plugins-base0.10 (0.10.5.2-1) unstable; urgency=low + + * New upstream pre-release, with API additions. + - Bump up libgstreamer0.10-dev build-dep to 0.10.4.1. + [debian/control, debian/rules] + - Relibtoolize. + [debian/patches/70_relibtoolize.patch] + + -- Loic Minier Tue, 18 Apr 2006 10:45:48 +0200 + +gst-plugins-base0.10 (0.10.5-1) unstable; urgency=low + + * New upstream release, "Net", with API additions. + - Relibtoolize. + [debian/patches/70_relibtoolize.patch] + - Drop patch to detect NFS mounts, merged upstream. + [debian/patches/02_gnomevfssrc.patch] + + -- Loic Minier Fri, 17 Mar 2006 17:54:20 +0100 + +gst-plugins-base0.10 (0.10.4-1) unstable; urgency=low + + [ Loic Minier ] + * New upstream release, "Power", with API additions. + - Bump up libgstreamer0.10-dev build-dep to >= 0.10.4. + [debian/control, debian/rules] + - Drop patch for force linking against the PIC version of libcheck since + upstream implemented a better fix. + [debian/patches/10_libcheck-macro-force-pic.patch] + - Relibtoolize. + [debian/patches/70_relibtoolize.patch] + + [ Sebastian Dröge ] + * debian/patches/02_gnomevfssrc.patch (from GStreamer CVS): + + gnome_vfs_uri_is_local() alone is not a good indicator whether we can + operate in pull-mode with a specific URI, as it returns FALSE for + file:// URIs that point to an NFS-mounted path. Be more conservative + here: whitelist local files, blacklist http URIs and use the old + mechanism for anything else (Closes: GNOME #334216). + + -- Sebastian Dröge Sun, 12 Mar 2006 17:31:46 +0100 + +gst-plugins-base0.10 (0.10.3-1) unstable; urgency=low + + * New upstream release, "Under Pressure". (Closes: #352773) + + -- Loic Minier Tue, 14 Feb 2006 10:36:59 +0100 + +gst-plugins-base0.10 (0.10.2.3-1) unstable; urgency=low + + * New upstream pre-release. + * Add visual plugin. + . Install plugin. + [debian/gstreamer-plugins-base.install] + . Add libvisual0.2-dev (>= 0.2.0) build-dep. + [debian/build-deps, debian/build-deps.in, debian/control] + * Use upstream descriptions in packages descriptions. + [debian/control, debian/control.in] + + -- Loic Minier Sat, 11 Feb 2006 17:23:37 +0100 + +gst-plugins-base0.10 (0.10.2.2-1) unstable; urgency=low + + * New upstream pre-release. + - Bump liboil0.3-dev build-dep to >= 0.3.6. + [debian/control, debian/build-deps, debian/build-deps.in] + - Bump libgstreamer0.10-dev build-dep to >= 0.10.2.2 + [debian/control, debian/rules] + - Relibtoolize. + [debian/patches/70_relibtoolize.patch] + + -- Loic Minier Wed, 8 Feb 2006 18:01:48 +0100 + +gst-plugins-base0.10 (0.10.2-2) unstable; urgency=high + + * Bump libgstreamer0.10-dev build-dep to 0.10.2, thanks Bastian Blank. + (Closes: #348526) + [debian/control, debian/rules] + + -- Loic Minier Fri, 20 Jan 2006 13:58:23 +0100 + +gst-plugins-base0.10 (0.10.2-1) unstable; urgency=low + + * New upstream release, "Then the devil is six". + - Add new libgstcdda library. + [debian/libgstreamer-plugins-base.install, debian/control, + debian/control.in] + - Add new cdparanaoia plugin. + [debian/gstreamer-plugins-base.install] + + -- Loic Minier Mon, 16 Jan 2006 23:14:17 +0100 + +gst-plugins-base0.10 (0.10.1-1) unstable; urgency=medium + + * Drop the version requirement on gstreamer0.10-tools as it might end being + unsatisfied. + [debian/control, debian/control.in] + * Call dh_perl in binary-post-install/$(gst_pkgname)-plugins-base-apps and + use ${perl:Depends}. + [debian/control, debian/control.in, debian/rules] + * New upstream release. + - Upload as non-native package. (Closes: #345573) + - Relibtoolize and build-depend on libxt-dev (>= 6.8.2.dfsg.1-3) as an + additionnal safety measure. (Closes: #345327) + [debian/build-deps, debian/build-deps.in, debian/control, + debian/patches/70_relibtoolize.patch] + - Drop gst-launch-ext and update description of base-apps. + [debian/control, debian/control.in, + debian/gstreamer-plugins-base-apps.install, + debian/gstreamer-plugins-base-apps.manpages] + - Drop unused cdparanoia patch applied upstream. + [debian/patches/50_cdparanoia-fix-eos-detection-of-last-title.patch] + - Bump GST_LIB_DEV_DEP to 0.10.0.2. + [debian/control, debian/rules] + * Drop unused GST_PLUGINS_BASE_LIB_DEV_DEP and use the upstream version + (gst_version) in lieu of gst_plugins_base_version for inter-deps + consistency. + [debian/rules] + * Use gst_plugins_base_lib_dep to define shlibs. + [debian/rules] + * Force linking against libcheck_pic instead of libcheck. Warning: to use + this patch you need to relibtoolize afterwards or patch configure too. + [debian/patches/10_libcheck-macro-force-pic.patch] + + -- Loic Minier Tue, 3 Jan 2006 22:23:12 +0100 + +gst-plugins-base0.10 (0.10.0-3) unstable; urgency=low + + * Fix the package name, that's gstreamer0.10-plugins-base + [debian/gstreamer-plugins-base.install, debian/rules] + + -- Sebastien Bacher Thu, 22 Dec 2005 11:39:27 +0100 + +gst-plugins-base0.10 (0.10.0-2) unstable; urgency=low + + * Rename gstreamer0.10-misc to gstreamer0.10-plugins-good for consistency. + [debian/control, debian/control.in, debian/gstreamer-misc.install, + debian/gstreamer-plugins-good.install, debian/rules] + + -- Loic Minier Wed, 21 Dec 2005 19:35:20 +0100 + +gst-plugins-base0.10 (0.10.0-1) unstable; urgency=low + + [ Sebastien Bacher ] + * New package: + - build the documentation [debian/rules] + - no action needed to register the plugins with the new version + [debian/gstreamer-plugin-template.postinst, + debian/gstreamer-plugin-template.postrm, + debian/libgstreamer-plugins.postinst, + debian/libgstreamer-plugins.postrm, debian/rules] + - drop mechanism to build extra packages for other distributions around, + it's not useful for base [debian/extras, debian/rules] + - drop transitionnal workaround [debian/gstreamer-plugin-template.preinst] + - new gstreamer-plugin-base-doc package [debian/control.in, debian/rules] + - remove obsolete patches + [debian/patches/10_wavpack-high-quality-segfault.patch, + debian/patches/30_alsa-verify-accepted-period-size.patch, + debian/patches/31_alsa-advanced-probing.patch, + debian/patches/40_audioscale-timestamps-and-durations.patch, + debian/patches/50_ladspa-quiet.patch] + - updated the Build-Depends [debian/build-dep.in] + - updated the packages descriptions [debian/control.in] + - updated the packages names/list [debian/control.in, + debian/gstreamer-a52dec.install, debian/gstreamer-aa.install, + debian/gstreamer-artsd.install, debian/gstreamer-audiofile.install, + debian/gstreamer-avifile.install, debian/gstreamer-caca.install, + debian/gstreamer-cdio.install, debian/gstreamer-dvd.install, + debian/gstreamer-dv.install, debian/gstreamer-esd.install, + debian/gstreamer-festival.install, debian/gstreamer-flac.install, + debian/gstreamer-gsm.install, debian/gstreamer-gtk.install, + debian/gstreamer-hermes.install, debian/gstreamer-jpeg.install, + debian/gstreamer-lame.install, debian/gstreamer-mad.install, + debian/gstreamer-mikmod.install, debian/gstreamer-mms.install, + debian/gstreamer-mpeg2dec.install, debian/gstreamer-oss.install, + debian/gstreamer-sdl.install, debian/gstreamer-sid.install, + debian/gstreamer-speex.install, debian/gstreamer-swfdec.install, + debian/libgstreamer-gconf.install, debian/libgstreamer-gconf-dev.install, + debian/gstreamer-vorbis.install, debian/rules] + - updated the packages lists [debian/gstreamer-misc.install, + debian/libgstreamer-plugins-base-dev.install, + debian/libgstreamer-plugins-base.install] + - updated packages content + [debian/gstreamer-misc.install, debian/gstreamer-x.install] + - updated the version [debian/rules] + - updated watch file [debian/watch] + + [ Loic Minier ] + * Minor cleanups. + [debian/rules] + * Add Sebastien Bacher to Uploaders. + [debian/control, debian/control.in] + + -- Loic Minier Sat, 17 Dec 2005 18:11:03 +0100 + +gst-plugins0.8 (0.8.11-3) unstable; urgency=medium + + * New CDIO plugin package. + . Add libcdio-dev build-dep for CDIO support. + [debian/build-deps.in, debian/build-deps, debian/control] + . Add package description and file listing. + [debian/gstreamer-cdio.install, debian/control.in, debian/control] + . List package in plugins build-list. [debian/rules] + . List package in gstreamer-plugins deps. + [debian/control.in, debian/control] + * New MMS plugin package. (Closes: #301246) + . Add libmms-dev build-dep for mms:// and mmsh:// support. + [debian/build-deps.in, debian/build-deps, debian/control] + . Add package description and file listing. + [debian/gstreamer-cdio.install, debian/control.in, debian/control] + . List package in plugins build-list. [debian/rules] + . List package in gstreamer-plugins deps. + [debian/control.in, debian/control] + * Fix the homepage of the mikmod page and stop linking to an adult web site. + [debian/control, debian/control.in] + * Remove "Section: libs" from binary packages. + [debian/control, debian/control.in] + * Exit with non-zero code when requesting an unknown plugin. + [debian/extra] + * Add sample code to permit other distros to build additional plugins. + [debian/rules] + * Minor cleanups. + [debian/rules] + * New Gtk / Gdk package to split out this dep-tree for KDE folks, from + Ubuntu, thanks Sebastien Bacher. + . Add package description and file listing, remove it from -misc. + [debian/control.in, debian/control, debian/gstreamer-gtk.install, + debian/gstreamer-misc.install] + . List package in plugins build-list. [debian/rules] + . List package in gstreamer-plugins deps. + [debian/control.in, debian/control] + . Only "Replace" with -misc in the first version doing the split + (0.8.11-0ubuntu3), no Conflict needed. + * Add wavpack support, build the wavpack plugin and ship it in -misc. + (Closes: #339598) + . Add a libwavpack-dev build-dep. + [debian/build-deps, debian/build-deps.in] + . Ship plugin in -misc. + [debian/gstreamer-misc.install] + . Adjust the size of the internal decode buffer dynamically instead of + assuming 0.5 seconds are enough; fixes a segfault when playing files + encoded with -h; upstream bug: #317774; fix committed in branch + BRANCH-GSTREAMER-0_8. + [debian/patches/10_wavpack-high-quality-segfault.patch] + * Backport some interesting upstream fixes from CVS fixing most resampling + issues for non-standard bitrates and for complex ALSA configurations + (especially dmix), thanks Tim-Philipp Müller, Luca Ognibene, and others. + (Closes: #323447, #324163, #326135, #340038) + - When doing _set_period_size_near(), see what period size was actually + set in the end and continue working with that value instead of just + assuming the desired period size was accepted; upstream bug #318767; + fix committed in branch BRANCH-GSTREAMER-0_8. + [debian/patches/30_alsa-verify-accepted-period-size.patch] + - Don't mess up timestamps and durations when resampling by more than a + factor of 2 (e.g. 8kHz => 48kHz); upstream bug #318273; fix committed + in branch BRANCH-GSTREAMER-0_8. + [debian/patches/40_audioscale-timestamps-and-durations.patch] + - When the default device is being used, try to probe the caps of the + underlying device instead if possible. This should give more narrowly + defined caps that are closer to the hardware's capabilities. This is + enabled by default, but can be switched off via the new + 'advanced-probing' property; upstream bug #315121; fix committed in + branch BRANCH-GSTREAMER-0_8. + [debian/patches/31_alsa-advanced-probing.patch] + * Drop the polypaudio plugin package. (Closes: #342278) + . Drop libpolyp-dev (>= 0.7) build-dep. + [debian/build-deps.in, debian/build-deps, debian/control] + . Remove package description and file listing. + [debian/gstreamer-polypaudio.install, debian/control.in, debian/control] + . Remove package from plugins build-list. [debian/rules] + . Remove package from gstreamer-plugins deps. + [debian/control.in, debian/control] + * Add libgconf2-dev, libglib2.0-dev, liborbit2-dev, libpopt-dev, libxml2-dev + deps to libgstreamer-gconf0.8-dev as listed in its .la files. + [debian/control, debian/control.in] + * Add libglib2.0-dev, libpopt-dev, libxml2-dev deps to + libgstreamer-plugins0.8-dev as listed in its .la files. + [debian/control, debian/control.in] + * Fix EOS detection for last title (fixes gnome-cd hanging after last track + ends), thanks Gustavo Noronha Silva; upstream bug #317630; fix committed + in branch BRANCH-GSTREAMER-0_8. (Closes: #330954) + [debian/patches/50_cdparanoia-fix-eos-detection-of-last-title.patch] + * Don't overwrite DEB_CONFIGURE_EXTRA_FLAGS. + [debian/rules] + + -- Loic Minier Sun, 11 Dec 2005 14:52:38 +0100 + +gst-plugins0.8 (0.8.11-2) unstable; urgency=high + + * Add misc:depends to all binary packages. (Closes: #329759) + + -- Loic Minier Mon, 17 Oct 2005 21:41:54 +0200 + +gst-plugins0.8 (0.8.11-1) unstable; urgency=low + + * Override gstreamer-dv section to extra because it depends on libavc1394-0 + which is in extra. [debian/control, debian/control.in] + * Bump libflac-dev build-dependency for the latest flac soname change + (libflac6 -> libflac7). (Closes: #325940) + * New upstream release, "... And Thanks For All The Fix". + - New plugin imagemixer. [debian/gstreamer-misc.install] + - New plugin dvdsubdec. [debian/gstreamer-misc.install] + - Drop obsolete artsd patch, merged upstream. + [debian/patches/25_artds-no-name.patch] + * Update FSF address. [debian/copyright] + * Add cairo plugin. [debian/build-deps, debian/build-deps.in, + debian/control, debian/gstreamer-misc.install] + + -- Loic Minier Sun, 4 Sep 2005 21:19:47 +0200 + +gst-plugins0.8 (0.8.10-3) unstable; urgency=high + + * Urgency high because this fixes some RC bugs and 0.8.10-2 was caught in + the C++ transition. + * Bump up build-deps to get versions past the C++ transition. + [debian/build-deps, debian/build-deps.in, debian/control] + - libsdl1.2-dev + - libsidplay1-dev (Closes: #321315) + - libarts1-dev, libartsc0-dev + * Change X11 build-deps for the Xorg transition. + [debian/build-deps, debian/build-deps.in, debian/control] + - remove xlibs-dev and xlibs-pic. + - add libx11-dev, libxext-dev, and libxv-dev. + * Drop jack plugin. [debian/build-deps, debian/build-deps.in, + debian/control, debian/control.in, debian/gstreamer-jack.install, + debian/rules] (Closes: #321648) + * Add libgstglimagesink plugin. [debian/gstreamer-x.install] + * Add libgstfreeze plugin. (Closes: #318146) [debian/gstreamer-misc.install] + * Let libgstreamer-gconf suggest gnome-media. (Closes: #294490) + [debian/control, debian/control.in] + + -- Loic Minier Fri, 12 Aug 2005 18:36:58 +0200 + +gst-plugins0.8 (0.8.10-2) unstable; urgency=medium + + [ Sebastien Bacher ] + * debian/build-deps.in: + - list libpolyp-dev. + * debian/control.in: + - gstreamer0.8-plugins depends on gstreamer0.8-polypaudio. + - gstreamer0.8-polypaudio description. + * gstreamer-polypaudio.install: + - install libpolypaudio.so. + * debian/rules: + - list polypaudio. + + [ Loic Minier ] + * Update jack dependency. (Closes: #317197) + [debian/build-deps, debian/build-deps.in, debian/control] + * Update aalib dependency. (Closes: #320886) + [debian/build-deps, debian/build-deps.in, debian/control] + + * Urgency medium because of RC. + + -- Loic Minier Sun, 10 Jul 2005 19:27:08 +0200 + +gst-plugins0.8 (0.8.10-1) unstable; urgency=low + + * Loic Minier: + * New upstream release "Jangle". + - Bump inter-dependencies to >= 0.8.10. + * Use upstream fix for the "name" property of the artsdsink element. + [debian/patches/25_artds-no-name.patch] + + -- Loic Minier Sat, 2 Jul 2005 21:04:40 +0200 + +gst-plugins0.8 (0.8.9-2) unstable; urgency=medium + + * Loic Minier: + * Urgency medium as last gstreamer0.8 release exposed an artsdsink + problem fixed here. + * Add a versioned dependency with >= current-upstream-version to all + current shlibs inter-dependencies to ensure consistency of symbols. + (Closes: #315556) [debian/control, debian/control.in, debian/rules] + * Remove the "name" property in the artsd plugin as it interferes with + the usage of this property within GStreamer. (Closes: #314762) + [debian/patches/25_artds-no-name.patch] + * Call gst-register and gst-compprep with GST_REGISTRY in their + environment to override the default behavior of writing to + /root/.gstreamer-0.8, waiting for an upstream fix. + [debian/gstreamer-plugin-template.postinst, + debian/gstreamer-plugin-template.postrm] + * Add a postinst/postrm snipset to register plugins in + libgstreamer-plugins0.8. (Closes: #283658) + [debian/libgstreamer-plugins.postrm, + debian/libgstreamer-plugins.postinst, debian/changelog, debian/rules] + * Remove left over /root/.gstreamer-0.8 tree if it hasn't been modified. + [debian/gstreamer-plugin-template.preinst, debian/rules] + * Set Maintainer to group. [debian/control, debian/control.in] + * Bump Standards-Version to 3.6.2, no change needed. + [debian/control, debian/control.in] + * Workaround type-handling bug #315761. + [debian/control, debian/control.in, debian/rules] + + -- Loic Minier Mon, 27 Jun 2005 15:44:35 +0200 + +gst-plugins0.8 (0.8.9-1) unstable; urgency=low + + * Loic Minier: + * New upstream release "Old Hat". + - Fix SIGFPE in alsasrc. (Closes: #279399) + - New Musepack plugin package. + . Add libmpcdec-dev build-dep for Musepack support, this is now + detected in a Debian compatible manner via mpcdec/mpcdec.h and + -lmpcdec. [debian/build-deps.in, debian/build-deps, debian/control] + . Add package description and file listing. + [debian/gstreamer-musepack.install, debian/control.in, + debian/control] + . List package in plugins build-list. [debian/rules] + . List package in gstreamer-plugins deps. + [debian/control.in, debian/control] + - Renamed and updated "ladspa" patch. + [debian/patches/ladspa-quiet.patch, + debian/patches/50_ladspa-quiet.patch] + - Add video4linuxradio plugin to the gstreamer-misc package. + [debian/rules] + * Add compatibility block for older dpkg and use DEB_HOST_ARCH_OS. + * Add myself as uploader. [debian/control.in, debian/control] + * Fix indentation and executable permission of package maintaining + helpers. [debian/extra, debian/maint, debian/mk.control] + * Remove more bits from the arts plugin, left over in 0.8.1-2. + [debian/extra, debian/gstreamer-arts.install] + * Document the role of most files. [debian/HACKING.Debian] + * Add a TODO list for the Debian package. [debian/TODO.Debian] + + -- Loic Minier Tue, 21 Jun 2005 07:47:04 +0200 + +gst-plugins0.8 (0.8.8-3) unstable; urgency=low + + * debian/build-deps.in: + * Bump liboil dependency to liboil0.3-dev. gst-plugins doesn't yet use + 0.3 itself but the swfdec plugin build requires it. + + -- David I. Lehn Wed, 30 Mar 2005 19:08:07 -0500 + +gst-plugins0.8 (0.8.8-2) unstable; urgency=low + + * debian/control.in: + * gstreamer0.8-vorbis depends on gstreamer0.8-misc >= 0.8.8-1 + (Closes: #300082, #299954, #299921) + + -- David I. Lehn Thu, 17 Mar 2005 12:53:38 -0500 + +gst-plugins0.8 (0.8.8-1) unstable; urgency=low + + * New upstream + * debian/patches/flac.patch: + * Remove: included upstream + * debian/gstreamer-misc.install: + * Add new plugins: autodetect, dvdlpcmdec, puzzle, rfbsrc, subparse + * Add new plugins with lib dependencies: gconfelements, mng, shout2 + (Closes: #292011) + * debian/build-deps.in: + * Add: libmng-dev, libshout3-dev + * Upstream fixes: + * Xv falls back to X11 (Closes: #296848) + * Better audio sink selection (Closes: #284210) + * alsasink crash (Closes: #296751) + + -- David I. Lehn Wed, 16 Mar 2005 01:00:39 -0500 + +gst-plugins0.8 (0.8.7-3) unstable; urgency=low + + * debian/rules, debian/build-deps.in + * Apply additional kfreebsd-gnu patch (Closes: #272568) + * debian/patches/flac.patch: + * Upstream fix for FLAC API change (Closes: #290784) + + -- David I. Lehn Mon, 17 Jan 2005 17:53:42 -0500 + +gst-plugins0.8 (0.8.7-2) unstable; urgency=low + + * debian/rules: + * Bump libgstreamer0.8-dev dependency to >= 0.8.7.1 + + -- David I. Lehn Sat, 8 Jan 2005 15:50:45 -0500 + +gst-plugins0.8 (0.8.7-1) unstable; urgency=low + + * New upstream + * debian/build-deps.in, debian/control.in, debian/rules, + debian/gstreamer-dv.install, debian/gstreamer-misc.install: + * Patch build system for kfreebsd-gnu (Closes: #272568) + * debian/rules: + * Distribute NEWS (as requested in #275717) + * debian/gstreamer-misc.install: + * Add new plugins: apetag, tta + * debian/patches/configure-speex.patch: + * Remove patch, included upstream + * debian/build-deps.in: + * Build against latest libflac-dev + + -- David I. Lehn Fri, 7 Jan 2005 13:52:27 -0500 + +gst-plugins0.8 (0.8.6-1) unstable; urgency=low + + * New upstream + * Rhythmbox hangs/crashes fixes (Closes: #245757, #277146) + * Rhythmbox silence after resume play fixes (Closes: #261841) + * Ogg seeking fixes (Closes: #277396) + * debian/build-deps.in: + * Bump libswfdec to libswfdec0.3-dev + * Add libavc1394-dev + * Add liboil0.2-dev + * Versioned libspeex-dev + * debian/gstreamer-misc.install: + * Add new plugin: equalizer + * debian/watch: + * Add watch file + * debian/rules: + * Update GStreamer core dev dependency to 0.8.4 + * ext/ladspa/gstladspa.c, debian/patches/ladspa-quiet.patch: + * Move patch to debian/patches/ + + -- David I. Lehn Mon, 29 Nov 2004 04:02:43 -0500 + +gst-plugins0.8 (0.8.5-1) unstable; urgency=low + + * New upstream + * debian/rules: + * Use CDBS simple-patchsys + * debian/control: to debian/control:: for newer CDBS + * debian/patches/configure-speex.diff: + * Fix speex detection + + -- David I. Lehn Wed, 6 Oct 2004 20:15:52 -0400 + +gst-plugins0.8 (0.8.4-1) unstable; urgency=low + + * New upstream + * debian/control.in: + * Add -theora package to -plugins package + * debian/rules: + * Drop upstream ChangeLog from plugin packages due to size + * debian/README.Debian: + * Add note about ChangeLog + + -- David I. Lehn Thu, 2 Sep 2004 23:03:44 -0400 + +gst-plugins0.8 (0.8.3-1) unstable; urgency=low + + * New upstream + * debian/control.in, debian/build-deps.in, debian/gstreamer-theora.install, + debian/rules: + * New theora plugin + * debian/gstreamer-misc.install: + * Add new plugins: alphacolor, decodebin, multifilesink, playbin + + -- David I. Lehn Sat, 7 Aug 2004 09:50:10 -0400 + +gst-plugins0.8 (0.8.2-3) unstable; urgency=high + + * debian/libgstreamer-gconf.postinst: + Remove. schema install now handled by dh_gconf which moved the schema + location causing old hardcoded /etc path to fail. + (Closes: #259538, #259119, #259205) + * Urgency high: GNOME team wants this in sarge now. + + -- David I. Lehn Fri, 16 Jul 2004 09:17:18 -0400 + +gst-plugins0.8 (0.8.2-2) unstable; urgency=low + + * debian/rules: + * Bump libgstreamer0.8-dev dep up to get fixed shlibs + * Rebuild with proper shlibs (Closes: #256181, #256494) + + -- David I. Lehn Wed, 7 Jul 2004 01:16:48 -0400 + +gst-plugins0.8 (0.8.2-1) unstable; urgency=medium + + * New upstream + * debian/build-deps.in: + * Add libdts-dev + * ext/Makefile.{am,in}: + * Fix so dts dir is built + * debian/gstreamer-misc.install: + * Add DTS plugin + * Added alpha, audiorate, dtsdec, multipart, videobox, videomixer, and + videorate + * debian/rules: + * Update libgstreamer0.8-dev build dependency to 0.8.3-2 + * debian/control.in: + * Remove explicit libgstreamer deps, autodetected now + + -- David I. Lehn Wed, 23 Jun 2004 23:50:53 -0400 + +gst-plugins0.8 (0.8.1-4) unstable; urgency=low + + * gst-libs/gst/riff/riff-media.c: + * caps type typo fix from CVS + * gst-libs/gst/resample/private.h: + * disabled ppc code fix from CVS (Closes: #252991) + * sys/v4l/gstv4lsrc.c: + * caps fix NULL->any from CVS + + -- David I. Lehn Wed, 16 Jun 2004 01:24:41 -0400 + +gst-plugins0.8 (0.8.1-3) unstable; urgency=low + + * rerun autoget.sh to fix arm builds (Closes: #251592) + * gconf/gstreamer.schemas.in, gcon/gstreamer-0.8.schemas: + s/xvideosink/xvimagesink/ (Closes: #250575) + + -- David I. Lehn Tue, 1 Jun 2004 10:10:37 -0400 + +gst-plugins0.8 (0.8.1-2) unstable; urgency=low + + * debian/build-deps.in: + * Update "libdv2-dev" to "libdv4-dev | libdv-dev" + * debian/control.in, debian/extra, debian/rules: + * Remove arts plugin. Detection, flags, and include directory build code + is too buggy for plugin to build at the moment. + + -- David I. Lehn Thu, 29 Apr 2004 18:10:48 -0400 + +gst-plugins0.8 (0.8.1-1) unstable; urgency=low + + * New upstream + * debian/gstreamer-misc.install: + * add libgstdebug.so + + -- David I. Lehn Sun, 18 Apr 2004 01:04:36 -0400 + +gst-plugins0.8 (0.8.0-2) unstable; urgency=low + + * Bump to -2 to ease upgrades for early -1 testers + * debian/build-deps.in: + * Add libgtk2.0-dev + + -- David I. Lehn Thu, 15 Apr 2004 17:50:14 -0400 + +gst-plugins0.8 (0.8.0-1) unstable; urgency=low + + * New upstream (Closes: #234071, #240663) + * debian/rules: + * Switch to CDBS + * Version now at 0.8 + * Convert various control files to versioned ones for build + * Add/rename/remove generated plugins files + * debian/control.in: + * Update Standards-Version to 3.6.1 + * Add -caca and -speex plugins + * Remove -http plugin + * debian/build-deps.in: + * Add cdbs + * Update debhelper >= 4.1.0 + * Add caca, speex, and pango deps + * Remove libghttp-dev + * debian/gstreamer-http.install + * Remove + * debian/gstreamer-{speex|caca}.install: + * Add new plugins + * debian/*.install: + * Append debian/tmp for CDBS + * General cleanups to support versioned files and locations + * debian/gstreamer-esd.install: + * Remove libgstesdmod + * Change libgstesdsink to libgstesd + * debian/gstreamer-plugin-libs.install: + * Stick locale info in here for lack of a better place + * debian/gstreamer-plugin-libs[-dev].install: + * Add support for colorbalance, mixer, navigation, propertyprobe, tag, + tuner, xoverlay, and xwindowlistener + * Add pkgconfig support for plugins, interfaces, and media-info + * debian/gstreamer-gnomevfs.install: + * s/libgstgnomevfs{src|sink}.so/libgstgnomevfs.so/ + * debian/gstreamer-colorspace.install: + * Rename to gstreamer-hermes.install + * Move generic and ffmpeg based colorspace plugins to -misc + * Provide gstreamerX.Y-colorspace + * debian/gstreamer-misc.install: + * v4l/v4l2 support merged to libgstvideo4linux[2].so + * Add gdkpixbuf, interleave, nassink, ogg, smoothwave, tagedit, + textoverlay, timeoverlay, typefindfunctions, videobalance, videodrop, + videofilter, videoflip + * Move generic and ffmpeg based colorspace plugins from -hermes + * Provide gstreamerX.Y-colorspace + * debian/gstreamer-plugin-libs.install: + * Rename to libgstreamer-plugins.install + * debian/gstreamer-plugin-libs-dev.install: + * Rename to libgstreamer-plugins-dev.install + * debian/gstreamer-gconf.install: + * Rename libgstreamer-gconf.install + * Remove dev files + * debian/gstreamer-gconf.postinst: + * Rename to libgstreamer-gconf.postinst + * debian/libgstreamer-gconf-dev.install: + * Added + * Add dev parts from gstreamer-gconf.install + * configure.ac, configure: + * Patch from CVS to get arts to detect on Debian boxen + * ext/speex/gstspeex{dec,enc}.c: + * Upstream patch for static pad templates (caused gst-compprep-0.8 bugs) + * ext/ladspa/gstladspa.c: + * Change g_warning to DEBUG_OBJ to silence gst-compprep + * ext/libcaca/gstcacsink.c: + * Upstream patch to avoid cacasink windows with gst-inspect/compprep + + -- David I. Lehn Wed, 14 Apr 2004 19:14:14 -0400 + +gst-plugins0.7 (0.7.6-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Wed, 17 Mar 2004 19:06:48 -0500 + +gst-plugins0.7 (0.7.5-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Wed, 17 Mar 2004 18:47:19 -0500 + +gst-plugins0.7 (0.7.4-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Wed, 17 Mar 2004 18:46:27 -0500 + +gst-plugins0.7 (0.7.3-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Wed, 17 Mar 2004 18:42:05 -0500 + +gst-plugins0.7 (0.7.1-1) unstable; urgency=low + + * New upstream + * Versioning package as 0.7 + + -- David I. Lehn Wed, 17 Mar 2004 18:31:51 -0500 + +gst-plugins (0.6.4-4) unstable; urgency=low + + * ext/alsa/gstalsa.h: + * Patch to compile with alsa-lib 1.0.x (Closes: #231870) + + -- David I. Lehn Sat, 14 Feb 2004 17:49:01 -0500 + +gst-plugins (0.6.4-3) unstable; urgency=low + + * debian/build-deps.in: + * Update jack dependency to libjack0.80.0-dev (>= 0.94.0) + (Closes: #221620, #228784) + * Update libmpeg2 dependency to libmpeg2-4-dev (>= 0.4.0b) + * ext/mpeg2dec/gstmpeg2dec.c: Patch for libmpeg2 0.4.0b + + -- David I. Lehn Mon, 26 Jan 2004 18:21:45 -0500 + +gst-plugins (0.6.4-2) unstable; urgency=low + + * debian/rules: Disable ffmpeg for everything but i386 due to PIC issues + (Closes: #219284) + + -- David I. Lehn Thu, 6 Nov 2003 16:30:35 -0500 + +gst-plugins (0.6.4-1) unstable; urgency=low + + * New upstream + * ESD updates (Closes: #218736) + * Acknowledge NMU (Closes: #217981, #213811) + * Rebuild to fix gconf liblinc1 dependency (Closes: #217771) + * gstreamer-misc: add v4l2 support (Closes: #199900) + * Use pre-Linux-2.6 videodev.h to compile v4l support + + -- David I. Lehn Mon, 3 Nov 2003 15:10:59 -0500 + +gst-plugins (0.6.3-1.1) unstable; urgency=low + + * NMU - Patch from Jordi Mallach + * debian/build-deps.in: libgconf2-dev and libgnomevfs2-dev need GNOME 2.4 + versions for the liblinc1 transition (closes: #217981). + * debian/rules: gstreamer build-dep should be versioned (>= 0.6.3) + (closes: #213811). + + -- LaMont Jones Thu, 30 Oct 2003 09:12:11 -0700 + +gst-plugins (0.6.3-1) unstable; urgency=low + + * New upstream + * Includes ESD seeking fix (Closes: #201171) + + -- David I. Lehn Mon, 1 Sep 2003 23:15:49 -0400 + +gst-plugins (0.6.2-2) unstable; urgency=low + + * Fix ffmpeg makefile install rule to work even when ffmpeg build is + disabled (Closes: #198148, #199072) + * Apply partial patches from running autogen.sh to fix arm builds (excluding + other unrelated generated file changes) (Closes: #199872) + * Update to support libdvdnav 0.1.9 API + + -- David I. Lehn Fri, 11 Jul 2003 01:01:15 -0400 + +gst-plugins (0.6.2-1) unstable; urgency=low + + * New upstream + * Add dv1394src to gstreamer-dv + + -- David I. Lehn Thu, 12 Jun 2003 11:39:51 -0400 + +gst-plugins (0.6.1-2) unstable; urgency=low + + * (unreleased) + * Adapt to gstreamer package merge: remove -core, -core-libs, -core-libs-dev + dependencies as needed. Fixes missing scheduler bugs. + (Closes: #181503, #191720) + * Use versioned gst-{register,compprep}-0.6 + * Update jack dependency to libjack0.71.2-dev (Closes: #195401) + * Update libdvdnav dependency to (>= 0.1.7) and revert patch for + compatibility with 0.1.3. + * Update libdvdread2 dependency to libdvdread3-dev + * Remove DISPLAY unset hacks from postinst/postrm scripts and fix non-X + installs with 0.6.2 CVS xvideosink patch. (Closes: #165372, #168438) + * Link libgstplay to libgstcontrol. (Closes: #194107) + + -- David I. Lehn Thu, 5 Jun 2003 02:29:44 -0400 + +gst-plugins (0.6.1-1) unstable; urgency=low + + * New upstream + * Update maintainer address to @debian.org + * gstreamer-gconf libs properly linked upstream (Closes: Bug#187353) + * debian/control.in: + * gstreamer-vorbis depends on gstreamer-core-libs (Closes: Bug#188606) + * Apply gnomevfs patch from http://bugzilla.gnome.org/show_bug.cgi?id=94113 + * ffmpeg plugin only builds, and now is only packaged, on i386/powerpc (Yes + this is bad - better shared lib support needed.) (Closes: Bug#186525) + * Revert dvdnav support to libdvdnav 0.1.3 API + * Unset DISPLAY before calling gst-register/gst-compprep + * ext/ladspa/gstladspa.c:472: s/g_warning/GST_DEBUG/ to avoid printing of a + warning on every plugin package install when swh-plugins is installed. + (sinCos plugin executes this code path) + + -- David I. Lehn Sat, 3 May 2003 18:30:16 -0400 + +gst-plugins (0.6.0-4) unstable; urgency=low + + * debian/build-deps.in: + * Updated libvorbis-dev to (>= 1.0.0-2) (Closes: Bug#184671) + + -- David I. Lehn Fri, 14 Mar 2003 11:12:21 -0500 + +gst-plugins (0.6.0-3) unstable; urgency=low + + * debian/build-deps.in: + * Add libartsc0-dev so artsc-config is present so arts[d] plugins get + built so the arts[d] packages actually include the arts[d] plugins + (Closes: Bug#181438) + * Update JACK dependency to 0.50.0 + + -- David I. Lehn Fri, 7 Mar 2003 23:51:46 -0500 + +gst-plugins (0.6.0-2) unstable; urgency=low + + * NMU (with maintainer's permission) + * Change libarts-dev build-dep to libarts1-dev (Closes: #180537) + + -- David Schleef Mon, 10 Feb 2003 21:33:47 -0800 + +gst-plugins (0.6.0-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Sat, 1 Feb 2003 21:51:54 -0500 + +gst-plugins (0.5.2.3-1) unstable; urgency=low + + * New upstream + + -- David I. Lehn Thu, 30 Jan 2003 23:52:08 -0500 + +gst-plugins (0.5.2.2-1) unstable; urgency=low + + * New upstream + * pre-release for 0.6.0 + * debian/gstreamer-gconf.install: + * add gstreamer-gconf-*.pc + * debian/gstreamer-misc.install: + * remove libgstaviparse.so + + -- David I. Lehn Wed, 29 Jan 2003 15:07:06 -0500 + +gst-plugins (0.5.2-1) unstable; urgency=low + + * New upstream + * debian/build-deps.in: + - Update swfdec dependency to 0.2.0 + * debian/gstreamer-misc.install: + - add libgstaviparse.so + + -- David I. Lehn Thu, 23 Jan 2003 22:17:31 -0500 + +gst-plugins (0.5.1-1) unstable; urgency=low + + * New upstream + * Update GStreamer dependency to 0.5.1 + * Update JACK dependency to 0.44.0 + * Remove gstreamer-avifile package (avifile not supported on many + architectures and upstream is deprecating it in favor of ffmpeg) + * Add support for building unsupported plugin packages (avifile, lame, etc) + * Tighten shlib deps for gstreamer-plugin-libs and gstreamer-gconf packages + (may split off true lib* packages eventually, was trying to avoid even + more packages) + * gstreamer-misc: add oneton and vbidec + * Rebuild for newer sid libs (Closes: Bug#177410) + * Various small fixes from CVS + + -- David I. Lehn Mon, 20 Jan 2003 11:57:26 -0500 + +gst-plugins (0.5.0-1) unstable; urgency=low + + * New upstream + * Update libpng dependency to libpng12-0-dev + * Patch from CVS to support mpeg2dec 0.3.1 + * Patch from CVS to improve X error handling and remote X usage + * gstreamer-plugin-libs[-dev]: add media-info lib + * gstreamer-misc: add png plugin + * Use swfdec 0.1.3 API: s/swf_init/swfdec_decoder_new/ to avoid symbol + conflicts with avifile plugin + + -- David I. Lehn Tue, 17 Dec 2002 20:27:42 -0500 + +gst-plugins (0.4.2-2) unstable; urgency=low + + * Update JACK dependency to 0.40.1 + * Apply gst-launch-ext perlism patch (Closes: #170736) + * Apply patch from Erik Meusel to allow building with + other KDE arts packages (Closes: Bug#167538) + * Update mpeg2dec dependency to 0.3.0, convert over to gstmpeg2deccvs plugin + code, and adjust mpeg2dec check + * Add Provides: for virtual gstreamer-{audio,video}sink packages to make it + easier for applications to ensure output sinks are available. This isn't + foolproof and it's possible that a rare user might not need the standard + packaged audio/video sinks. For now those users can use the "equivs" + package to get around the problem. (Closes: Bug#169968) + + -- David I. Lehn Wed, 4 Dec 2002 02:25:41 -0500 + +gst-plugins (0.4.2-1.1) unstable; urgency=low + + * NMU + * Depend on swfdec-0.1.2-3, since it had a bug. + + -- David Schleef Tue, 12 Nov 2002 17:43:48 -0800 + +gst-plugins (0.4.2-1) unstable; urgency=low + + * New upstream + * Add libpng2-dev to Build-Depends for snapshot + * Add smpte, snapshot, and wavenc to gstreamer-misc + * Add video and play libs to gstreamer-plugin-libs{-dev} + * Add gstreamer-swfdec plugin package + * Add hack to swfdec plugin to not segfault when avifile also loaded due to + symbols conflicts. This annoyance will spew errors during gst-compprep + and probably will cause errors in apps that use both swfdec and avifile. + * Tighten dependency on libgstreamer until upstream code can deal with + multiple plugin versions and upgrades better + * Move gstreamer-plugin-apps to Section: utils from x11 + + -- David I. Lehn Wed, 6 Nov 2002 21:41:01 -0500 + +gst-plugins (0.4.1-1) unstable; urgency=low + + * New upstream + * Update FLAC dependency to 1.0.4 and add support patch from CVS + * Rebuild for libflac4 (Closes: Bug#163549) + * Build gconf code as a library rather than a plugin + * Improved plugin descriptions + * Added to -misc: cdplayer, videocrop, videotestsrc, mixmatrix + * Add autotools-dev to Build-Depends + * Update config.{guess,sub} + + -- David I. Lehn Mon, 7 Oct 2002 17:51:43 -0400 + +gst-plugins (0.4.0.2-cvs20020919-1) unstable; urgency=low + + * CVS snapshot, release branch + * gstreamer-gconf.files: libgstgconf.so moved to /usr/lib + * added control.in, build-deps, and mk.control script. Edit control.in + and/or build-deps, and run 'debian/rules debian/control' from toplevel + directory to recreate debian/control. This should make it a lot + easier to diff build dependencies. + + -- David Schleef Thu, 19 Sep 2002 15:18:41 -0700 + +gst-plugins (0.4.0-5) unstable; urgency=low + + * Update Build-Depends + * Use pkg-config checking vs m4 macros for libdv + + -- David I. Lehn Fri, 23 Aug 2002 10:33:29 -0400 + +gst-plugins (0.4.0-4) unstable; urgency=low + + * Fixes from CVS for gstgnomevfssrc.c and endian issue in vorbisfile.c + + -- David I. Lehn Fri, 2 Aug 2002 20:51:38 -0400 + +gst-plugins (0.4.0-3) unstable; urgency=low + + * Add ladspa-sdk to Build-Depends + * Removed qcam plugin from -misc. + It's i386 only and probably not widely used. Will figure out how to + package in the future if someone needs it. + + -- David I. Lehn Mon, 29 Jul 2002 16:32:33 -0400 + +gst-plugins (0.4.0-2) unstable; urgency=low + + * Clean up the Build-Depends: + - stricter versioning + - remove gnome deps (used for examples which are not build now) + * Fix segfault in vorbis.m4 check + + -- David I. Lehn Mon, 29 Jul 2002 10:47:12 -0400 + +gst-plugins (0.4.0-1) unstable; urgency=low + + * New upstream + * FLAC compile fixes from CVS + * DV comiled fixes + * Upated ltmain hack + * autogen.sh with more recent tools + * Update config.{guess,sub} + * Added plugin packages: -gconf, -http, -jack, -dv + * Added dvdnav plugin to -dvd + * Removed osshelper plugin from -oss + * Added xvideosink back to -x + * Added effectv, filter, and qtdemux plugins to -misc + * Rename gstreamer-lib-misc{-dev} to gstreamer-plugin-libs{-dev} to match + gstreamer core. + * Added gstreamer-plugin-apps package for a lonely 2 scripts + * Renamed gstreamer-all to gstreamer-plugins + + -- David I. Lehn Tue, 16 Jul 2002 02:10:07 -0400 + +gst-plugins (0.3.4-2) unstable; urgency=low + + * Rebuild for new avifile + + -- David I. Lehn Wed, 24 Apr 2002 14:06:46 -0400 + +gst-plugins (0.3.4-1) unstable; urgency=low + + * New upstream + * Fix mpeg2dec.m4 to use newer mpeg2dec libs + + -- David I. Lehn Mon, 15 Apr 2002 03:34:21 -0400 + +gst-plugins (0.3.3-2) unstable; urgency=low + + * Port a52dec plugin to 0.7.3 API (applied upstream) + * Use a52dec packages in Debian vs current external ones + * This switches a52dec plugin to static linking + * Remove LAME support + * No LAME packages in Debian to depend on + * Added explanation in README.Debian since this will likely + cause no end of "Why is there no LAME plugin?" + * Depend on and rebuild for mpeg2dec 0.2.1 + * Depend on and rebuild for glib 2.0 + * Remove gtk from Build-Depends: (not needed for the built plugins) + + -- David I. Lehn Sat, 23 Mar 2002 17:52:03 -0500 + +gst-plugins (0.3.3-1) unstable; urgency=low + + * New upstream version + * SDL fixed upstream, remove patch + * Require libid3tag for mad support + * Remove xvideosink from gstreamer-x package in favor of videosink + Needed to be removed due to symbol conflicts with videosink + * Sync with upstream changes: + * Added videosink to gstreamer-x package + * parseau renamed to auparse in -misc + * Added various plugins to -misc: goom, monoscope, modplug, ... + * Note: new upstream scripts gst-launch-ext and gst-visualise not + packaged yet + + -- David I. Lehn Thu, 21 Mar 2002 02:06:21 -0500 + +gst-plugins (0.3.2-3) unstable; urgency=low + + * Rebuild for glib/gtk 1.3.15 + + -- David I. Lehn Mon, 25 Feb 2002 00:06:51 -0500 + +gst-plugins (0.3.2-2) unstable; urgency=low + + * Build against liblinc1 and newer gnomevfs + + -- David I. Lehn Sun, 17 Feb 2002 15:52:57 -0500 + +gst-plugins (0.3.2-1) unstable; urgency=low + + * New upstream release + * Many diffs merged upstream + * Unversioned plugins upstream, just packaging .so (no .la, .a) + * Added cdxa plugin to -misc + * Various plugins in -misc moved around and merged upstream + + -- David I. Lehn Fri, 15 Feb 2002 21:54:27 -0500 + +gst-plugins (0.3.1-4) unstable; urgency=low + + * Rebuild for glib/gtk 1.3.13 + + -- David I. Lehn Wed, 6 Feb 2002 02:16:16 -0500 + +gst-plugins (0.3.1-3) unstable; urgency=low + + * Fix arts symbol problem (add -lartsflow -lartsflow_idl) + * Replace m4/gst-sdl.m4 with Debian's sdl.m4 + * Use SDL_LIBS_FOR_PLUGINS instead of SDL_LIBS + + -- David I. Lehn Wed, 23 Jan 2002 12:37:00 -0500 + +gst-plugins (0.3.1-2) unstable; urgency=low + + * Rebuild against fixed gstreamer.pc in libgst-dev 0.3.1-2 + Should just link to libxml2 now rather than v1 and v2 + + -- David I. Lehn Wed, 23 Jan 2002 02:29:49 -0500 + +gst-plugins (0.3.1-1) unstable; urgency=low + + * Upstream split plugins into new package + * Upstream removed mpg123 plugin - use mad plugin + * Upstream removed ac3dec plugin - use a52dec + * Added -lib-misc and -lib-misc-dev packages for + library plugins and headers + * Patch to link all plugins to GST_LIBS + + -- David I. Lehn Fri, 11 Jan 2002 11:22:01 -0500 + +gstreamer (0.3.0-3) unstable; urgency=low + + * Remove upstream ChangeLog from packages: 128k changelog.gz per + plugin package for 40 packages is too much + + -- David I. Lehn Tue, 25 Dec 2001 23:36:28 -0500 + +gstreamer (0.3.0-2) unstable; urgency=low + + * Fix bug that slipped into 0.3.0: s/aasink/xvideosink/ in + gstplay/gstplay.c + + -- David I. Lehn Tue, 25 Dec 2001 17:56:29 -0500 + +gstreamer (0.3.0-1) unstable; urgency=low + + * New upstream release + * Attempt to update various Build-Depends versions + * Added plugin packages: -a52dec, -dvd, -mikmod, -sid + * Renamed -elements to -core + * Added to -core: gstbasicscheduler + * Moved from -common to -core: gsttypes, autoplug related + * Renamed -common to -misc + * Added to -misc: speed, qcam, bytesteram, control, silence, sinesrc, + mpegstream, playondemand, resample + * Added gstreamer-guilaunch to gstreamer-tools package + * Added dependencies on unofficial LAME packages + * Use PIC libs for Xv + * Disable broken building of PDF/PS docs + * Renamed -all-plugins to -all + * Disable docs -- too hard to build + + -- David I. Lehn Fri, 21 Dec 2001 12:00:02 -0500 + +gstreamer (0.2.1-4) unstable; urgency=low + + * Fix some problems reported from lintian 1.20.14: + * copyright-lists-upstream-authors-like-dh_make + * debian-changelog-file-contains-user-emacs-settings + * Patch from CVS to link libgst into plugins + Plugins now properly depend on libgst package + * Use RedHat Gtk+-1.3 hack to fix relink issues with ltmain.sh + * Patch from CVS for xvideosink segfault when no DISPLAY set + * Remove builddir references from gstreamer-config.in + * Move libgstelements.la from libgst-dev to gstreamer-elements + + -- David I. Lehn Tue, 28 Aug 2001 20:05:28 -0400 + +gstreamer (0.2.1-3) unstable; urgency=low + + * Update build dependencies to FLAC 1.0 + * Enable debug features + * Fixup broken doc build -scan voodoo with link into .libs/ dir + + -- David I. Lehn Sun, 5 Aug 2001 23:04:28 -0400 + +gstreamer (0.2.1-2) unstable; urgency=low + + * Fix lib deps: run debhelper tools in the right order + * Added arts dir to Makefile.am SUBDIRS so it builds again + * Changed libmpeg2dec to libgstmpeg2dec to avoid naming issues + when using -lmpeg2dec + * Updated system_encode/ with CVS segfaulter bug fix + + -- David I. Lehn Thu, 19 Jul 2001 15:47:24 -0400 + +gstreamer (0.2.1-1) unstable; urgency=low + + * New upstream 0.2.1: "Return of the Sedi Master" + * New plugin packages: -festival, -flac, -avifile, -x + * New plugins in -common: chart, deinterlace, udp + * Added some post-0.2.1 fixes for FLAC, build system, ALSA + + -- David I. Lehn Thu, 28 Jun 2001 20:15:15 -0400 + +gstreamer (0.2.0-6) unstable; urgency=low + + * Move -compprep to -runtime and call it same places as -register + * Do -register and -compprep in postrm instead of prerm + * Make -arts plugin actually build all the source (sent upstream) + * Purge of -runtime removes /etc/gstreamer + + -- David I. Lehn Tue, 19 Jun 2001 13:09:32 -0400 + +gstreamer (0.2.0-5) unstable; urgency=low + + * Added element package dependencies to libgstmediaplay0 + + -- David I. Lehn Mon, 18 Jun 2001 11:18:53 -0400 + +gstreamer (0.2.0-4) unstable; urgency=low + + * Add --gst-mask=0 to -runtime.postinst + + -- David I. Lehn Fri, 15 Jun 2001 11:47:24 -0400 + +gstreamer (0.2.0-3) unstable; urgency=low + + * Fix the plugin control file symlink creation + * Add audiofile to Build-Depends + + -- David I. Lehn Fri, 15 Jun 2001 05:22:28 -0400 + +gstreamer (0.2.0-2) unstable; urgency=low + + * Fixed ALSA checks to not include -lasound in -every- link + * Update LAME plugin to use latest CVS API + * Removed OSS src/sink from -common.files (was in -oss too) + * Swapped -arts.files and -artsd.files contents + + -- David I. Lehn Fri, 15 Jun 2001 04:02:21 -0400 + +gstreamer (0.2.0-1) unstable; urgency=low + + * Added gstreamer-compprep manpage + * Upgrade to 0.2.0 + + -- David I. Lehn Thu, 7 Jun 2001 12:53:59 -0400 + +gstreamer (0.2.0-0.3) unstable; urgency=low + + * GStreamer 0.2.0-pre3 + + -- David I. Lehn Wed, 6 Jun 2001 15:09:59 -0400 + +gstreamer (0.2.0-0.2) unstable; urgency=low + + * GStreamer 0.2.0-pre2 + CVS 20010604 + * Added -artsd (vs -arts), -audiofile, -gnomevfs, -gsm, -jpeg, + -oss, and -sdl plugin packages + * Added osshelper lib to oss package + * Added more AVI related plugins and autoplug libs to -common + * Added pkgconfig file to libgst-dev + * Added gstreamer-all-plugins pseudo package that depends on + all other plugin pacakges + + -- David I. Lehn Mon, 4 Jun 2001 17:33:20 -0400 + +gstreamer (0.2.0-0.1) unstable; urgency=low + + * GStreamer 0.2.0-pre1 + + -- David I. Lehn Thu, 31 May 2001 17:16:23 -0400 + +gstreamer (0.1.1.20010504-1) unstable; urgency=low + + * Latest CVS code + + -- David I. Lehn Fri, 4 May 2001 21:48:45 -0400 + +gstreamer (0.1.1.20010430-2) unstable; urgency=low + + * Added -colorspace package for Hermes dependent conversion + * Added -arts package for aRts sink + + -- David I. Lehn Tue, 1 May 2001 19:46:08 -0400 + +gstreamer (0.1.1.20010430-1) unstable; urgency=low + + * Latest CVS code + * Added -aa package for aasink output + * Added -mad package for mad mp3 decoder + + -- David I. Lehn Mon, 30 Apr 2001 18:25:52 -0400 + +gstreamer (0.1.1.20010320-1) unstable; urgency=low + + * Latest CVS code + * enable main docs + * disable broken plugin docs with new option + + -- David I. Lehn Tue, 20 Mar 2001 18:15:19 -0500 + +gstreamer (0.1.1.20010315-1) unstable; urgency=low + + * Latest CVS code + * Added man pages + * Split mpeg2dec to seperate plugin + * libgst Architectures updated to cothread supported archs + + -- David I. Lehn Thu, 15 Mar 2001 20:17:19 -0500 + +gstreamer (0.1.1-1) unstable; urgency=low + + * New upstream release + * disable docs build, broken at the momemnt + + -- David I. Lehn Sun, 25 Feb 2001 17:58:25 -0500 + +gstreamer (0.1.0-2) unstable; urgency=low + + * debian/rules: call configure instead of autogen.sh + + -- David I. Lehn Sat, 24 Feb 2001 18:31:36 -0500 + +gstreamer (0.1.0-1) unstable; urgency=low + + * Initial Release. + + -- David I. Lehn Mon, 15 Jan 2001 18:25:18 -0500 diff --git a/gst-plugins-base-subtitles0.10/debian/compat b/gst-plugins-base-subtitles0.10/debian/compat new file mode 100644 index 0000000..7ed6ff8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/compat @@ -0,0 +1 @@ +5 diff --git a/gst-plugins-base-subtitles0.10/debian/control b/gst-plugins-base-subtitles0.10/debian/control new file mode 100644 index 0000000..336bb59 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/control @@ -0,0 +1,46 @@ +Source: gst-plugins-base-subtitles0.10 +Section: libs +Priority: optional +Maintainer: Roman Moravcik +XSBC-Original-Maintainer: Maemo Multimedia , Maintainers of GStreamer packages +XSBC-Original-Uploaders: Loic Minier , + Sebastien Bacher , + Sebastian Dröge , + Sjoerd Simons +Build-Depends: libgstreamer0.10-dev (>= 0.10.34), libasound2-dev (>= 0.9.0) [arm armel i386], autotools-dev, automake1.10, autopoint, cdbs (>= 0.4.20), debhelper (>= 5), pkg-config (>= 0.11.0), libxv-dev (>= 6.8.2.dfsg.1-3), liborc-0.4-dev (>= 0.4.10), libogg-dev, libcairo2-dev, libpango1.0-dev, libglib2.0-dev (>= 2.2.0), libxml2-dev (>= 2.4.23), zlib1g-dev (>= 1:1.1.4), gstreamer-tools (>= 0.10.14), libvorbisidec-dev, python +Build-Depends-Indep: gtk-doc-tools +Standards-Version: 3.8.0 +Homepage: http://gstreamer.freedesktop.org + +Package: gstreamer0.10-plugins-base-subtitles +Architecture: any +Section: libs +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Extra GStreamer plugins from the "base" set + GStreamer is a streaming media framework, based on graphs of filters + which operate on media data. Applications using this library can do + anything from real-time sound processing to playing videos, and just + about anything else media-related. Its plugin-based architecture means + that new data types or processing capabilities can be added simply by + installing new plug-ins. + . + This package contains the GStreamer plugins from the "base" set, an + essential exemplary set of elements. + +Package: gstreamer0.10-plugins-base-subtitles-dbg +Architecture: any +Section: libdevel +Priority: extra +Depends: gstreamer0.10-plugins-base-subtitles (= ${binary:Version}) +Description: Extra GStreamer plugins from the "base" set + GStreamer is a streaming media framework, based on graphs of filters + which operate on media data. Applications using this library can do + anything from real-time sound processing to playing videos, and just + about anything else media-related. Its plugin-based architecture means + that new data types or processing capabilities can be added simply by + installing new plug-ins. + . + This package contains unstripped shared libraries. It is provided primarily + to provide a backtrace with names in a debugger, this makes it somewhat + easier to interpret core dumps. The libraries are installed in + /usr/lib/debug and are automatically used by gdb. diff --git a/gst-plugins-base-subtitles0.10/debian/control.in b/gst-plugins-base-subtitles0.10/debian/control.in new file mode 100644 index 0000000..336bb59 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/control.in @@ -0,0 +1,46 @@ +Source: gst-plugins-base-subtitles0.10 +Section: libs +Priority: optional +Maintainer: Roman Moravcik +XSBC-Original-Maintainer: Maemo Multimedia , Maintainers of GStreamer packages +XSBC-Original-Uploaders: Loic Minier , + Sebastien Bacher , + Sebastian Dröge , + Sjoerd Simons +Build-Depends: libgstreamer0.10-dev (>= 0.10.34), libasound2-dev (>= 0.9.0) [arm armel i386], autotools-dev, automake1.10, autopoint, cdbs (>= 0.4.20), debhelper (>= 5), pkg-config (>= 0.11.0), libxv-dev (>= 6.8.2.dfsg.1-3), liborc-0.4-dev (>= 0.4.10), libogg-dev, libcairo2-dev, libpango1.0-dev, libglib2.0-dev (>= 2.2.0), libxml2-dev (>= 2.4.23), zlib1g-dev (>= 1:1.1.4), gstreamer-tools (>= 0.10.14), libvorbisidec-dev, python +Build-Depends-Indep: gtk-doc-tools +Standards-Version: 3.8.0 +Homepage: http://gstreamer.freedesktop.org + +Package: gstreamer0.10-plugins-base-subtitles +Architecture: any +Section: libs +Depends: ${misc:Depends}, ${shlibs:Depends} +Description: Extra GStreamer plugins from the "base" set + GStreamer is a streaming media framework, based on graphs of filters + which operate on media data. Applications using this library can do + anything from real-time sound processing to playing videos, and just + about anything else media-related. Its plugin-based architecture means + that new data types or processing capabilities can be added simply by + installing new plug-ins. + . + This package contains the GStreamer plugins from the "base" set, an + essential exemplary set of elements. + +Package: gstreamer0.10-plugins-base-subtitles-dbg +Architecture: any +Section: libdevel +Priority: extra +Depends: gstreamer0.10-plugins-base-subtitles (= ${binary:Version}) +Description: Extra GStreamer plugins from the "base" set + GStreamer is a streaming media framework, based on graphs of filters + which operate on media data. Applications using this library can do + anything from real-time sound processing to playing videos, and just + about anything else media-related. Its plugin-based architecture means + that new data types or processing capabilities can be added simply by + installing new plug-ins. + . + This package contains unstripped shared libraries. It is provided primarily + to provide a backtrace with names in a debugger, this makes it somewhat + easier to interpret core dumps. The libraries are installed in + /usr/lib/debug and are automatically used by gdb. diff --git a/gst-plugins-base-subtitles0.10/debian/copyright b/gst-plugins-base-subtitles0.10/debian/copyright new file mode 100644 index 0000000..e3e9f94 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/copyright @@ -0,0 +1,31 @@ +This package was debianized by David I. Lehn on +Mon, 15 Jan 2001 18:21:37 -0500. + +It was downloaded from http://gstreamer.net/ + +Upstream Authors: + + Erik Walthinsen + Wim Taymans + Richard Boulton + and many more... + +Copyright: + + This package is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This package is distributed in the hope that 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 package; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +On Debian GNU/Linux systems, the complete text of the GNU Lesser General +Public License can be found in `/usr/share/common-licenses/LGPL'. + diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-alsa.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-alsa.install new file mode 100644 index 0000000..457aba8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-alsa.install @@ -0,0 +1 @@ +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstalsa.so diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.install new file mode 100644 index 0000000..165ec59 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.install @@ -0,0 +1,2 @@ +debian/tmp/usr/bin/gst-tagread +debian/tmp/usr/bin/gst-visualise-@GST_ABI@ diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.manpages b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.manpages new file mode 100644 index 0000000..f309211 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-apps.manpages @@ -0,0 +1 @@ +debian/tmp/usr/share/man/man1/gst-visualise-@GST_ABI@.1 diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-doc.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-doc.install new file mode 100644 index 0000000..133e6a2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-doc.install @@ -0,0 +1 @@ +debian/tmp/usr/share/gtk-doc diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-extra.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-extra.install new file mode 100644 index 0000000..c0a6789 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-extra.install @@ -0,0 +1,6 @@ +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstadder.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstaudiotestsrc.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstgdp.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstpango.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstvideotestsrc.so + diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-subtitles.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-subtitles.install new file mode 100644 index 0000000..ea737f2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base-subtitles.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstpango.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstsubparse.so diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base.install new file mode 100644 index 0000000..972d0d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-plugins-base.install @@ -0,0 +1,18 @@ +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstapp.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstaudioconvert.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstaudiorate.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstaudioresample.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstdecodebin.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstdecodebin2.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstencodebin.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstffmpegcolorspace.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstgio.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstivorbisdec.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstogg.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstplaybin.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgsttagreading.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgsttcp.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgsttypefindfunctions.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstvideorate.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstvideoscale.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstvolume.so diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer-x.install b/gst-plugins-base-subtitles0.10/debian/gstreamer-x.install new file mode 100644 index 0000000..3b131fe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer-x.install @@ -0,0 +1,2 @@ +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstximagesink.so +debian/tmp/usr/lib/gstreamer-@GST_ABI@/libgstxvimagesink.so diff --git a/gst-plugins-base-subtitles0.10/debian/gstreamer0.10-plugins-base-tests.install b/gst-plugins-base-subtitles0.10/debian/gstreamer0.10-plugins-base-tests.install new file mode 100644 index 0000000..93748d4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/gstreamer0.10-plugins-base-tests.install @@ -0,0 +1,49 @@ +tests/check/elements/.libs/alsa /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/.libs/appsink /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/.libs/appsrc /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/.libs/audioconvert /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/.libs/audioresample /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/.libs/videoscale /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/adder /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/audiorate /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/audiotestsrc /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/decodebin /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/decodebin2 /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/ffmpegcolorspace /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/gdpdepay /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/gdppay /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/multifdsink /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/playbin /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/playbin2 /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/subparse /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/textoverlay /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/videorate /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/videotestsrc /usr/share/gstreamer0.10-plugins-base-tests +tests/check/elements/volume /usr/share/gstreamer0.10-plugins-base-tests +tests/check/generic/clock-selection /usr/share/gstreamer0.10-plugins-base-tests +tests/check/generic/states /usr/share/gstreamer0.10-plugins-base-tests +tests/check/gst/typefindfunctions /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/audio /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/cddabasesrc /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/fft /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/mixer /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/navigation /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/netbuffer /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/pbutils /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/profile /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/rtp /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/rtsp /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/tag /usr/share/gstreamer0.10-plugins-base-tests +tests/check/libs/.libs/video /usr/share/gstreamer0.10-plugins-base-tests +tests/check/orc/adder /usr/share/gstreamer0.10-plugins-base-tests/orc +tests/check/orc/audioconvert /usr/share/gstreamer0.10-plugins-base-tests/orc +tests/check/orc/videoscale /usr/share/gstreamer0.10-plugins-base-tests/orc +tests/check/orc/videotestsrc /usr/share/gstreamer0.10-plugins-base-tests/orc +tests/check/orc/volume /usr/share/gstreamer0.10-plugins-base-tests/orc +tests/check/pipelines/.libs/simple-launch-lines /usr/share/gstreamer0.10-plugins-base-tests +tests/check/pipelines/basetime /usr/share/gstreamer0.10-plugins-base-tests +tests/check/pipelines/capsfilter-renegotiation /usr/share/gstreamer0.10-plugins-base-tests +tests/check/pipelines/gio /usr/share/gstreamer0.10-plugins-base-tests +tests/check/pipelines/oggmux /usr/share/gstreamer0.10-plugins-base-tests +tests/check/pipelines/streamheader /usr/share/gstreamer0.10-plugins-base-tests +tests/check/tests.xml /usr/share/gstreamer0.10-plugins-base-tests diff --git a/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base-dev.install b/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base-dev.install new file mode 100644 index 0000000..9e992ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base-dev.install @@ -0,0 +1,3 @@ +debian/tmp/usr/include/gstreamer-@GST_ABI@/gst/*/*.h +debian/tmp/usr/lib/*.so +debian/tmp/usr/lib/pkgconfig/*.pc diff --git a/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base.install b/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base.install new file mode 100644 index 0000000..2381504 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/libgstreamer-plugins-base.install @@ -0,0 +1,13 @@ +debian/tmp/usr/lib/libgstapp-0.10.so.* +debian/tmp/usr/lib/libgstaudio-0.10.so.* +debian/tmp/usr/lib/libgstcdda-0.10.so.* +debian/tmp/usr/lib/libgstfft-0.10.so.* +debian/tmp/usr/lib/libgstinterfaces-0.10.so.* +debian/tmp/usr/lib/libgstnetbuffer-0.10.so.* +debian/tmp/usr/lib/libgstpbutils-0.10.so.* +debian/tmp/usr/lib/libgstriff-0.10.so.* +debian/tmp/usr/lib/libgstrtp-0.10.so.* +debian/tmp/usr/lib/libgstrtsp-0.10.so.* +debian/tmp/usr/lib/libgstsdp-0.10.so.* +debian/tmp/usr/lib/libgsttag-0.10.so.* +debian/tmp/usr/lib/libgstvideo-0.10.so.* diff --git a/gst-plugins-base-subtitles0.10/debian/maint b/gst-plugins-base-subtitles0.10/debian/maint new file mode 100755 index 0000000..de89a47 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/maint @@ -0,0 +1,13 @@ +#!/usr/bin/make -f + +missing: + make -f debian/rules list-missing + +missing-so: + make -f debian/rules list-missing | grep so$$ | cut -c 2- + +missing-libs: + for i in `make -f debian/rules list-missing | grep so$$ | cut -c 2-`; do echo "=== $$i ==="; ldd debian/tmp/$$i; echo; done + +.PHONY: missing missing-so missing-libs + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0001-tag-add-new-GstTagReader-interface-to-allow-fine-tun.patch b/gst-plugins-base-subtitles0.10/debian/patches/0001-tag-add-new-GstTagReader-interface-to-allow-fine-tun.patch new file mode 100644 index 0000000..4be2d45 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0001-tag-add-new-GstTagReader-interface-to-allow-fine-tun.patch @@ -0,0 +1,494 @@ +From ce8841a1b178ca7e9cd139d4e687a36650392cd6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Fri, 22 May 2009 19:38:01 +0100 +Subject: [PATCH] tag: add new GstTagReader interface to allow fine-tuning of + tag-reading behaviour + +API: gst_tag_reader_get_type +API: gst_tag_reader_add_interface_to_type +API: gst_tag_reader_set_tag_reading_mode +API: gst_tag_reader_get_tag_reading_mode +API: gst_tag_reading_mode_get_type + +The GstTagReader interface may be implemented by elements that +extract metadata to allow the fine-tuning of the tag-reading +process (see #564749). +--- + docs/libs/gst-plugins-base-libs-docs.sgml | 1 + + docs/libs/gst-plugins-base-libs-sections.txt | 17 ++ + gst-libs/gst/tag/Makefile.am | 5 +- + gst-libs/gst/tag/gsttagreader.c | 286 ++++++++++++++++++++++++++ + gst-libs/gst/tag/gsttagreader.h | 110 ++++++++++ + 5 files changed, 417 insertions(+), 2 deletions(-) + create mode 100644 gst-libs/gst/tag/gsttagreader.c + create mode 100644 gst-libs/gst/tag/gsttagreader.h + +diff --git a/docs/libs/gst-plugins-base-libs-docs.sgml b/docs/libs/gst-plugins-base-libs-docs.sgml +index b7b61a7..453fb9a 100644 +--- a/docs/libs/gst-plugins-base-libs-docs.sgml ++++ b/docs/libs/gst-plugins-base-libs-docs.sgml +@@ -190,6 +190,7 @@ + + + ++ + + + +diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt +index 41235a0..b667b45 100644 +--- a/docs/libs/gst-plugins-base-libs-sections.txt ++++ b/docs/libs/gst-plugins-base-libs-sections.txt +@@ -1822,6 +1822,23 @@ gst_tag_get_language_code_iso_639_2B + gst_tag_get_language_code_iso_639_2T + + ++
++gsttagreader ++gst/tag/gsttagreader.h ++GstTagReader ++GstTagReadingMode ++gst_tag_reader_add_interface_to_type ++gst_tag_reader_set_tag_reading_mode ++gst_tag_reader_get_tag_reading_mode ++ ++gst_tag_reading_mode_get_type ++GST_TAG_READER ++GST_TYPE_TAG_READER ++GST_IS_TAG_READER ++GST_TAG_READER_GET_IFACE ++GstTagReaderInterface ++
++ + # base utils + +
+diff --git a/gst-libs/gst/tag/Makefile.am b/gst-libs/gst/tag/Makefile.am +index 9977d66..d12c7b7 100644 +--- a/gst-libs/gst/tag/Makefile.am ++++ b/gst-libs/gst/tag/Makefile.am +@@ -2,13 +2,14 @@ libgsttagincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/tag + + libgsttaginclude_HEADERS = \ +- tag.h gsttagdemux.h xmpwriter.h ++ tag.h gsttagdemux.h xmpwriter.h gsttagreader.h + + lib_LTLIBRARIES = libgsttag-@GST_MAJORMINOR@.la + + libgsttag_@GST_MAJORMINOR@_la_SOURCES = \ + gstvorbistag.c gstid3tag.c gstxmptag.c gstexiftag.c \ +- lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c ++ lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c \ ++ gsttagreader.c + libgsttag_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) + libgsttag_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) + libgsttag_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +diff --git a/gst-libs/gst/tag/gsttagreader.c b/gst-libs/gst/tag/gsttagreader.c +new file mode 100644 +index 0000000..cfbd480 +--- /dev/null ++++ b/gst-libs/gst/tag/gsttagreader.c +@@ -0,0 +1,286 @@ ++/* GStreamer Tag Reader interface ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * Copyright (C) 2008 Nokia Corporation. ++ * ++ * Contact: Stefan Kost ++ * ++ * tagreader.c: Tag Reader interface design ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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:gsttagreader ++ * @short_description: Interface for setting a tag reading mode on elements ++ * supporting it ++ * ++ * ++ * ++ * The #GstTagReader interface may be implemented by elements that extract ++ * metadata to allow the fine-tuning of the tag-reading process. The interface ++ * is not required by all elements that extract tags - it is perfectly ++ * acceptable to post tag messages on the bus and not implement this ++ * interface. The interface merely serves to indicate that an element supports ++ * one or more special tag reading modes which when set might result in ++ * more efficient tag processing in certain cases. ++ * ++ * ++ * ++ * Use cases ++ * ++ * There are currently two main use cases for this interface: ++ * ++ * ++ * by-passing possibly time- or memory-consuming tag extraction: useful ++ * for example if the goal is to just play a file, but things like embedded ++ * coverart or tags are not of interest. ++ * ++ * ++ * optimised tag and stream info extraction: useful if all that's of interest ++ * is tags and other metadata and full-scale playback functionality is not ++ * required; this allows demuxers to bypass possibly expensive index processing ++ * or index building, for example. ++ * ++ * ++ * ++ * ++ * ++ * How to use #GstTagReader in applications ++ * ++ * Application writers who want to avoid the (usually very small) overhead of ++ * tag extraction when playing back media can put uridecodebin or decodebin2 ++ * (or the elements in their pipeline directly, if they implement the ++ * interface) into tag reading mode #GST_TAG_READING_MODE_SKIP_TAGS using ++ * gst_tag_reader_set_tag_reading_mode() before starting the pipeline. ++ * ++ * ++ * Application writers who want to extract tags and other metadata as fast and ++ * efficiently as possible should use the 'tagreadbin' element, which will ++ * handle everything for them, and which will then use the #GstTagReader ++ * interface internally. ++ * ++ * ++ * ++ * How to implement the #GstTagReader in elements ++ * ++ * #GstTagReader is a 'dummy interface' similar to #GstTagSetter, meaning that ++ * there are no interface methods to implement. All that needs to be done is ++ * to add the interface to an element's GType in the element's _get_type() ++ * function or GST_BOILERPLATE_FULL macro. This can be done using the ++ * convenience function gst_tag_reader_add_interface_to_type(). ++ * ++ * ++ * Elements implementing the interface should then query the configured tag ++ * reading mode when starting up (ie. in the start function or in the ++ * state change function in the NULL to READY transition), using ++ * gst_tag_reader_get_tag_reading_mode(). ++ * ++ * ++ * In #GST_TAG_READING_MODE_SKIP_TAGS mode elements should skip metadata ++ * processing wherever this is possible without affecting functionality ++ * otherwise. Element should not post TAG messages on the bus in this mode. ++ * ++ * ++ * In #GST_TAG_READING_MODE_DEFAULT mode elements should behave like they ++ * normally would. For most elements this means tag extraction and normal ++ * stream handling. ++ * ++ * ++ * In #GST_TAG_READING_MODE_TAGS_ONLY mode elements are requested to skip ++ * any non-essential data processing. Demuxers, for example, may choose not ++ * to parse a seek index or build a seek table, but should still parse ++ * file headers and add pads and push newsegment events and data as they ++ * usually would (however, they are not required to reproduce output in the ++ * way they would for normal playback, e.g. they may push only key frames, ++ * which is all that is required for thumbnailing purposes). ++ * ++ * ++ * Elements in #GST_TAG_READING_MODE_TAGS_ONLY are required to properly ++ * aggregate or pass upstream flow returns. If they are driving the pipeline ++ * they will also need to EOS on #GST_FLOW_UNEXPECTED flow returns from ++ * downstream. This is how the tagreadbin element will ++ * stop streaming once it has collected all information. ++ * ++ * ++ * ++ * Tag-handling guidelines for all demuxers and parsers ++ * ++ * Below some general guidelines on how demuxers, parsers and decoders should ++ * handle tags. ++ * ++ * ++ * Demuxers should push tag events for 'global' tag before pushing tags ++ * with per-stream information. This global tag list should contain a ++ * #GST_TAG_CONTAINER_FORMAT tag. They also should push global tags and ++ * per-stream tags separately. ++ * ++ * ++ * Parsers and decoders should ensure that they cache tag events received from ++ * upstream and push them on their source pad before any tags of their own ++ * are pushed, maintaining the order of the tag events as they came in. ++ * ++ * ++ * Since 0.10.24 ++ * ++ * ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "gsttagreader.h" ++ ++/* key for g_object_{set|get}_qdata() */ ++static GQuark tag_reading_mode_quark = 0; ++ ++#define GST_TAG_READER_GET_MODE(obj) \ ++ GPOINTER_TO_INT (g_object_get_qdata (obj, tag_reading_mode_quark)) ++#define GST_TAG_READER_SET_MODE(obj,mode) \ ++ g_object_set_qdata (obj, tag_reading_mode_quark, GINT_TO_POINTER (mode)) ++ ++GType ++gst_tag_reader_get_type (void) ++{ ++ static GType gst_tag_reader_type = 0; ++ ++ if (!gst_tag_reader_type) { ++ static const GTypeInfo gst_tag_reader_info = { ++ sizeof (GstTagReaderInterface), ++ (GBaseInitFunc) NULL, ++ NULL, ++ NULL, ++ NULL, ++ NULL, ++ 0, ++ 0, ++ NULL, ++ }; ++ ++ gst_tag_reader_type = g_type_register_static (G_TYPE_INTERFACE, ++ "GstTagReader", &gst_tag_reader_info, 0); ++ ++ tag_reading_mode_quark = g_quark_from_static_string ("GstTagReadingMode"); ++ } ++ ++ return gst_tag_reader_type; ++} ++ ++/** ++ * gst_tag_reader_add_interface_to_type: ++ * @type: a newly-registered GType ++ * ++ * Convenience function to add the #GstTagReader interface to an element. ++ * Use from within the element's _get_type() function or in connection ++ * with GST_BOILERPLATE_FULL. ++ * ++ * Since: 0.10.24 ++ */ ++void ++gst_tag_reader_add_interface_to_type (GType type) ++{ ++ static const GInterfaceInfo tr_iface_info = { NULL, NULL, NULL, }; ++ ++ g_type_add_interface_static (type, GST_TYPE_TAG_READER, &tr_iface_info); ++} ++ ++/** ++ * gst_tag_reader_set_tag_reading_mode: ++ * @reader: a #GstTagReader to set the tag reading mode on. ++ * @mode: tag reading mode to operate in. ++ * ++ * This will set the tag reader's mode of operation. You should ++ * use this method to tell a tag reader capable element in which ++ * #GstTagReadingMode the reader should operate in. ++ * ++ * This function will take the object lock and must not be called with the ++ * object lock already held. ++ * ++ * Since: 0.10.24 ++ */ ++void ++gst_tag_reader_set_tag_reading_mode (GstTagReader * reader, ++ GstTagReadingMode mode) ++{ ++ GObject *obj; ++ ++ g_return_if_fail (reader != NULL); ++ g_return_if_fail (GST_IS_TAG_READER (reader)); ++ g_return_if_fail (GST_IS_ELEMENT (reader)); ++ ++ obj = G_OBJECT (reader); ++ ++ GST_OBJECT_LOCK (obj); ++ if (GST_STATE (obj) == GST_STATE_NULL) { ++ GST_TAG_READER_SET_MODE (obj, mode); ++ GST_LOG_OBJECT (obj, "configured mode: %d", mode); ++ } else if (GST_TAG_READER_GET_MODE (obj) != mode) { ++ g_warning ("Can't set tag reading mode on element '%s': element must be " ++ "in NULL state", GST_ELEMENT_NAME (obj)); ++ } ++ GST_OBJECT_UNLOCK (obj); ++} ++ ++/** ++ * gst_tag_reader_get_tag_reading_mode: ++ * @reader: a #GstTagReader to get the tag reading mode from. ++ * ++ * Query the currently configured #GstTagReadingMode. ++ * ++ * This function will take the object lock and must not be called with the ++ * object lock already held. ++ * ++ * Returns: configured tag reading mode. ++ * ++ * Since: 0.10.24 ++ */ ++GstTagReadingMode ++gst_tag_reader_get_tag_reading_mode (GstTagReader * reader) ++{ ++ GstTagReadingMode mode; ++ GObject *obj; ++ ++ g_return_val_if_fail (reader != NULL, GST_TAG_READING_MODE_DEFAULT); ++ g_return_val_if_fail (GST_IS_TAG_READER (reader), ++ GST_TAG_READING_MODE_DEFAULT); ++ g_return_val_if_fail (GST_IS_ELEMENT (reader), GST_TAG_READING_MODE_DEFAULT); ++ ++ obj = G_OBJECT (reader); ++ ++ GST_OBJECT_LOCK (obj); ++ mode = GST_TAG_READER_GET_MODE (obj); ++ GST_OBJECT_UNLOCK (obj); ++ ++ return mode; ++} ++ ++GType ++gst_tag_reading_mode_get_type (void) ++{ ++ static GType etype = 0; ++ if (etype == 0) { ++ static const GEnumValue values[] = { ++ {GST_TAG_READING_MODE_DEFAULT, "GST_TAG_READING_MODE_DEFAULT", "default"}, ++ {GST_TAG_READING_MODE_TAGS_ONLY, "GST_TAG_READING_MODE_TAGS_ONLY", ++ "tags-only"}, ++ {GST_TAG_READING_MODE_SKIP_TAGS, "GST_TAG_READING_MODE_SKIP_TAGS", ++ "skip-tags"}, ++ {0, NULL, NULL} ++ }; ++ etype = g_enum_register_static ("GstTagReadingMode", values); ++ } ++ return etype; ++} +diff --git a/gst-libs/gst/tag/gsttagreader.h b/gst-libs/gst/tag/gsttagreader.h +new file mode 100644 +index 0000000..5c39f85 +--- /dev/null ++++ b/gst-libs/gst/tag/gsttagreader.h +@@ -0,0 +1,110 @@ ++/* GStreamer Tag Reader interface ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * Copyright (C) 2008 Nokia Corporation. ++ * ++ * Contact: Stefan Kost ++ * ++ * tagreader.h: Tag Reader interface design ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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_TAG_READER_H__ ++#define __GST_TAG_READER_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++/** ++ * GstTagReadingMode: ++ * @GST_TAG_READING_MODE_DEFAULT: parse both metadata and audio/video stream ++ * data ++ * @GST_TAG_READING_MODE_TAGS_ONLY: parse metadata and process only as much ++ * audio/video data as required to extract basic information about the ++ * stream such as tags, available streams and duration ++ * @GST_TAG_READING_MODE_SKIP_TAGS: don't extract any metadata, just process ++ * the audio/video stream data (behaviour should generally be the same as ++ * with #GST_TAG_READING_MODE_DEFAULT, only that tag extraction is skipped) ++ * ++ * Available tag reading modes. ++ * ++ * Since: 0.10.24 ++ */ ++/* keep gst_tag_reading_mode_get_type() in sync when adding enums here */ ++typedef enum { ++ GST_TAG_READING_MODE_DEFAULT = 0, ++ GST_TAG_READING_MODE_TAGS_ONLY, ++ GST_TAG_READING_MODE_SKIP_TAGS ++} GstTagReadingMode; ++ ++#define GST_TYPE_TAG_READING_MODE (gst_tag_reading_mode_get_type()) ++GType gst_tag_reading_mode_get_type (void); ++ ++ ++#define GST_TYPE_TAG_READER \ ++ (gst_tag_reader_get_type ()) ++#define GST_TAG_READER(obj) \ ++ (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_READER, GstTagReader)) ++#define GST_IS_TAG_READER(obj) \ ++ (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_READER)) ++#define GST_TAG_READER_GET_IFACE(inst) \ ++ (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TAG_READER, \ ++ GstTagReaderInterface)) ++ ++/** ++ * GstTagReader: ++ * ++ * Opaque #GstTagReader structure (dummy typedef to denote object instances ++ * which implement the #GstTagReader interface). ++ * ++ * Since: 0.10.24 ++ */ ++typedef struct _GstTagReader GstTagReader; ++typedef struct _GstTagReaderInterface GstTagReaderInterface; ++ ++/** ++ * GstTagReaderInterface: ++ * ++ * Dummy interface structure. Elements do not need to implement any interface ++ * methods, all they need to do is query the desired tag reading mode via ++ * gst_tag_reader_get_tag_reading_mode() where and when appropriate/required. ++ * ++ * Since: 0.10.24 ++ */ ++struct _GstTagReaderInterface { ++ GTypeInterface iface; ++ ++ /* methods: no methods to implement at this time */ ++ ++ /* interfaces don't need padding, so no padding here */ ++}; ++ ++GType gst_tag_reader_get_type (void); ++ ++void gst_tag_reader_add_interface_to_type (GType type); ++ ++/* public methods */ ++ ++void gst_tag_reader_set_tag_reading_mode (GstTagReader * reader, ++ GstTagReadingMode mode); ++ ++GstTagReadingMode gst_tag_reader_get_tag_reading_mode (GstTagReader * reader); ++ ++G_END_DECLS ++ ++#endif /* __GST_TAG_READER_H__ */ ++ diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0002-playback-make-uridecodebin-and-decodebin2-implement-.patch b/gst-plugins-base-subtitles0.10/debian/patches/0002-playback-make-uridecodebin-and-decodebin2-implement-.patch new file mode 100644 index 0000000..3c4a823 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0002-playback-make-uridecodebin-and-decodebin2-implement-.patch @@ -0,0 +1,133 @@ +From 43667763dd6e5aa95fea97651a3355981d3bce8e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Fri, 22 May 2009 20:10:00 +0100 +Subject: [PATCH] playback: make uridecodebin and decodebin2 implement the + tagreader interface + +.. so they can proxy the configured tag reading mode to any elements they +auto-plug. Tagreadbin will use this. +--- + gst/playback/Makefile.am | 1 + + gst/playback/gstdecodebin2.c | 16 ++++++++++++++++ + gst/playback/gsturidecodebin.c | 13 ++++++++++++- + 3 files changed, 29 insertions(+), 1 deletions(-) + +diff --git a/gst/playback/Makefile.am b/gst/playback/Makefile.am +index 3adb56d..2c336f3 100644 +--- a/gst/playback/Makefile.am ++++ b/gst/playback/Makefile.am +@@ -44,6 +44,7 @@ nodist_libgstdecodebin2_la_SOURCES = $(built_sources) + libgstdecodebin2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) + libgstdecodebin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + libgstdecodebin2_la_LIBADD = \ ++ $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) + libgstdecodebin2_la_LIBTOOLFLAGS = --tag=disable-static +diff --git a/gst/playback/gstdecodebin2.c b/gst/playback/gstdecodebin2.c +index 31b5ebb..e73d3b7 100644 +--- a/gst/playback/gstdecodebin2.c ++++ b/gst/playback/gstdecodebin2.c +@@ -88,6 +88,7 @@ + #include + #include + #include ++#include + + #include "gstplay-marshal.h" + #include "gstplay-enum.h" +@@ -170,6 +171,7 @@ struct _GstDecodeBin + GList *blocked_pads; /* pads that have set to block */ + + gboolean expose_allstreams; /* Whether to expose unknow type streams or not */ ++ GstTagReadingMode tag_mode; + }; + + struct _GstDecodeBinClass +@@ -510,6 +512,8 @@ gst_decode_bin_get_type (void) + gst_decode_bin_type = + g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2", + &gst_decode_bin_info, 0); ++ ++ gst_tag_reader_add_interface_to_type (gst_decode_bin_type); + } + + return gst_decode_bin_type; +@@ -1742,6 +1746,15 @@ connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, + continue; + } + ++ /* if it's a tag reader, configure the tag reading mode */ ++ if (dbin->tag_mode != GST_TAG_READING_MODE_DEFAULT && ++ GST_IS_TAG_READER (element)) { ++ GST_DEBUG_OBJECT (dbin, "setting tag reading mode %d on element %s", ++ dbin->tag_mode, GST_ELEMENT_NAME (element)); ++ gst_tag_reader_set_tag_reading_mode (GST_TAG_READER (element), ++ dbin->tag_mode); ++ } ++ + /* ... activate it ... We do this before adding it to the bin so that we + * don't accidentally make it post error messages that will stop + * everything. */ +@@ -3645,6 +3658,9 @@ gst_decode_bin_change_state (GstElement * element, GstStateChange transition) + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: ++ dbin->tag_mode = ++ gst_tag_reader_get_tag_reading_mode (GST_TAG_READER (dbin)); ++ GST_LOG_OBJECT (dbin, "tag reading mode: %d", dbin->tag_mode); + if (dbin->typefind == NULL) + goto missing_typefind; + break; +diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c +index bf10583..8c4e3f2 100644 +--- a/gst/playback/gsturidecodebin.c ++++ b/gst/playback/gsturidecodebin.c +@@ -33,6 +33,7 @@ + #include + #include + #include ++#include + + #include "gstplay-marshal.h" + #include "gstplay-enum.h" +@@ -104,6 +105,8 @@ struct _GstURIDecodeBin + gboolean expose_allstreams; /* Whether to expose unknow type streams or not */ + + guint64 ring_buffer_max_size; /* 0 means disabled */ ++ ++ GstTagReadingMode tag_mode; + }; + + struct _GstURIDecodeBinClass +@@ -186,7 +189,8 @@ enum + static guint gst_uri_decode_bin_signals[LAST_SIGNAL] = { 0 }; + + GType gst_uri_decode_bin_get_type (void); +-GST_BOILERPLATE (GstURIDecodeBin, gst_uri_decode_bin, GstBin, GST_TYPE_BIN); ++GST_BOILERPLATE_FULL (GstURIDecodeBin, gst_uri_decode_bin, GstBin, ++ GST_TYPE_BIN, gst_tag_reader_add_interface_to_type); + + static void remove_decoders (GstURIDecodeBin * bin, gboolean force); + static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id, +@@ -1544,6 +1548,10 @@ make_decoder (GstURIDecodeBin * decoder) + if (decodebin->numsinkpads == 0) + goto no_typefind; + ++ /* configure tag reading mode */ ++ gst_tag_reader_set_tag_reading_mode (GST_TAG_READER (decodebin), ++ decoder->tag_mode); ++ + /* connect signals to proxy */ + g_signal_connect (decodebin, "unknown-type", + G_CALLBACK (proxy_unknown_type_signal), decoder); +@@ -2385,6 +2393,9 @@ gst_uri_decode_bin_change_state (GstElement * element, + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: ++ decoder->tag_mode = ++ gst_tag_reader_get_tag_reading_mode (GST_TAG_READER (decoder)); ++ GST_LOG_OBJECT (decoder, "tag reading mode: %d", decoder->tag_mode); + if (!setup_source (decoder)) + goto source_failed; + break; diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0003-tagreading-add-tagreadbin-element-for-fast-and-easy-.patch b/gst-plugins-base-subtitles0.10/debian/patches/0003-tagreading-add-tagreadbin-element-for-fast-and-easy-.patch new file mode 100644 index 0000000..7a0eed3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0003-tagreading-add-tagreadbin-element-for-fast-and-easy-.patch @@ -0,0 +1,2467 @@ +From 6c810495ff6c876e17c7eaf260959683c77450a5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Sat, 23 May 2009 00:42:01 +0100 +Subject: [PATCH] tagreading: add tagreadbin element for fast and easy + metadata extraction + +Similar to playbin, just for metadata (in future maybe also thumbnailing). +See #564749. +--- + configure.ac | 2 + + docs/plugins/Makefile.am | 1 + + docs/plugins/gst-plugins-base-plugins-docs.sgml | 2 + + docs/plugins/gst-plugins-base-plugins-sections.txt | 17 + + docs/plugins/inspect/plugin-tagreading.xml | 23 + + gst/tagreading/Makefile.am | 28 + + gst/tagreading/gsttagreadbin.c | 893 ++++++++++++++++++++ + gst/tagreading/gsttagreadbin.h | 104 +++ + gst/tagreading/gsttagreadutils.c | 309 +++++++ + gst/tagreading/gsttagreadutils.h | 62 ++ + gst/tagreading/gsttagsink.c | 785 +++++++++++++++++ + gst/tagreading/gsttagsink.h | 103 +++ + 12 files changed, 2329 insertions(+), 0 deletions(-) + create mode 100644 docs/plugins/inspect/plugin-tagreading.xml + create mode 100644 gst/tagreading/Makefile.am + create mode 100644 gst/tagreading/gsttagreadbin.c + create mode 100644 gst/tagreading/gsttagreadbin.h + create mode 100644 gst/tagreading/gsttagreadutils.c + create mode 100644 gst/tagreading/gsttagreadutils.h + create mode 100644 gst/tagreading/gsttagsink.c + create mode 100644 gst/tagreading/gsttagsink.h + +diff --git a/configure.ac b/configure.ac +index 8131f8a..7a6ae5a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -430,6 +430,7 @@ AG_GST_CHECK_PLUGIN(gdp) + AG_GST_CHECK_PLUGIN(playback) + AG_GST_CHECK_PLUGIN(audioresample) + AG_GST_CHECK_PLUGIN(subparse) ++AG_GST_CHECK_PLUGIN(tagreading) + AG_GST_CHECK_PLUGIN(tcp) + AG_GST_CHECK_PLUGIN(typefind) + AG_GST_CHECK_PLUGIN(videotestsrc) +@@ -931,6 +932,7 @@ gst/gdp/Makefile + gst/playback/Makefile + gst/audioresample/Makefile + gst/subparse/Makefile ++gst/tagreading/Makefile + gst/tcp/Makefile + gst/typefind/Makefile + gst/videotestsrc/Makefile +diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am +index c987b85..8226d38 100644 +--- a/docs/plugins/Makefile.am ++++ b/docs/plugins/Makefile.am +@@ -111,6 +111,7 @@ EXTRA_HFILES = \ + $(top_srcdir)/gst/playback/gstsubtitleoverlay.h \ + $(top_srcdir)/gst/audiorate/gstaudiorate.h \ + $(top_srcdir)/gst/audioresample/gstaudioresample.h \ ++ $(top_srcdir)/gst/tagreading/gsttagreadbin.h \ + $(top_srcdir)/gst/tcp/gstmultifdsink.h \ + $(top_srcdir)/gst/tcp/gsttcpclientsrc.h \ + $(top_srcdir)/gst/tcp/gsttcpclientsink.h \ +diff --git a/docs/plugins/gst-plugins-base-plugins-docs.sgml b/docs/plugins/gst-plugins-base-plugins-docs.sgml +index ea603d6..deebd97 100644 +--- a/docs/plugins/gst-plugins-base-plugins-docs.sgml ++++ b/docs/plugins/gst-plugins-base-plugins-docs.sgml +@@ -46,6 +46,7 @@ + + + ++ + + + +@@ -93,6 +94,7 @@ + + + ++ + + + +diff --git a/docs/plugins/gst-plugins-base-plugins-sections.txt b/docs/plugins/gst-plugins-base-plugins-sections.txt +index e94c450..97dc8ca 100644 +--- a/docs/plugins/gst-plugins-base-plugins-sections.txt ++++ b/docs/plugins/gst-plugins-base-plugins-sections.txt +@@ -504,6 +504,23 @@ gst_subtitle_overlay_get_type +
+ +
++element-tagreadbin ++tagreadbin ++GstTagReadBin ++ ++GST_TAG_READ_BIN ++GST_TAG_READ_BIN_CLASS ++GST_TYPE_TAG_READ_BIN ++GST_IS_TAG_READ_BIN ++GST_IS_TAG_READ_BIN_CLASS ++GST_TAG_READ_BIN_DYN_LOCK ++GST_TAG_READ_BIN_DYN_UNLOCK ++GST_TAG_READ_BIN_SHUTDOWN_LOCK ++GST_TAG_READ_BIN_SHUTDOWN_UNLOCK ++GstTagReadBinClass ++
++ ++
+ element-tcpclientsrc + tcpclientsrc + GstTCPClientSrc +diff --git a/docs/plugins/inspect/plugin-tagreading.xml b/docs/plugins/inspect/plugin-tagreading.xml +new file mode 100644 +index 0000000..6d00a48 +--- /dev/null ++++ b/docs/plugins/inspect/plugin-tagreading.xml +@@ -0,0 +1,23 @@ ++ ++ tagreading ++ Tag reading support ++ ../../gst/tagreading/.libs/libgsttagreading.so ++ libgsttagreading.so ++ 0.10.22.3 ++ LGPL ++ gst-plugins-base ++ GStreamer Base Plug-ins CVS/prerelease ++ Unknown package origin ++ ++ ++ tagreadbin ++ Tag Read Bin ++ Generic/Bin/Metadata ++ Extract metadata from an uri ++ Tim-Philipp Müller <tim centricular net> ++ ++ ++ ++ ++ ++ +\ No newline at end of file +diff --git a/gst/tagreading/Makefile.am b/gst/tagreading/Makefile.am +new file mode 100644 +index 0000000..0a0d32d +--- /dev/null ++++ b/gst/tagreading/Makefile.am +@@ -0,0 +1,28 @@ ++plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@ ++ ++plugin_LTLIBRARIES = libgsttagreading.la ++ ++libgsttagreading_la_SOURCES = \ ++ gsttagreadbin.c \ ++ gsttagreadbin.h \ ++ gsttagreadutils.c \ ++ gsttagreadutils.h \ ++ gsttagsink.c \ ++ gsttagsink.h ++libgsttagreading_la_CFLAGS = \ ++ $(GST_PLUGINS_BASE_CFLAGS) \ ++ $(GST_BASE_CFLAGS) \ ++ $(GST_CFLAGS) ++libgsttagreading_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) ++libgsttagreading_la_LIBADD = \ ++ $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ ++ $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ ++ $(GST_BASE_LIBS) \ ++ $(GST_LIBS) ++libgsttagreading_la_LIBTOOLFLAGS = --tag=disable-static ++ ++noinst_HEADERS = \ ++ gsttagreadbin.h \ ++ gsttagreadutils.h \ ++ gsttagsink.h ++ +diff --git a/gst/tagreading/gsttagreadbin.c b/gst/tagreading/gsttagreadbin.c +new file mode 100644 +index 0000000..d62d8eb +--- /dev/null ++++ b/gst/tagreading/gsttagreadbin.c +@@ -0,0 +1,893 @@ ++/* GStreamer tag read bin ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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-tagreadbin ++ * @short_description: Extract metadata (tags and stream info) ++ * ++ * ++ * ++ * Tagreadbin is a stand-alone element that extracts metadata (tags and ++ * other stream info such as video resolution, audio sample rate etc.) from ++ * files given an URI. ++ * ++ * ++ * ++ * This element is still considered EXPERIMENTAL. Even though we don't expect ++ * any changes, the API provided in properties, signals and bus messages may ++ * yet change in the near future. ++ * ++ * ++ * ++ * Tagreadbin will open the file requested and automatically plug the elements ++ * required to extract the metadata. Only demuxers, parsers or specialised tag ++ * reading elements (implementing the #GstTagReader interface) will be used. No ++ * decoders will be plugged, unless video thumbnailing has been requested ++ * (which is not implemented yet). ++ * ++ * ++ * ++ * Basic usage ++ * ++ * Tagreadbin is a #GstPipeline, so it can be used like any other GStreamer ++ * pipeline. In particular, you can retrieve the #GstBus to watch for tag ++ * and error messages using gst_pipeline_get_bus(). Once the ++ * uri property has been set, the element should be ++ * set to PLAYING state using gst_element_set_state(). TAG and ERROR messages ++ * will then be posted on the pipeline's #GstBus soon after. If there was no ++ * error, one or more TAG messages will be posted on the bus, followed by an ++ * EOS message. Once an ERROR or EOS message has been received, the element ++ * should be shut down by setting it to NULL state with gst_element_set_state(). ++ * It can then be re-used to extract metadata from another file. ++ * ++ * ++ * ++ * Tag messages ++ * ++ * Tagreadbin will collect tags from various elements and try to group them. ++ * The first tag message posted on the bus should contain the 'global tags', ++ * ie. tags that are valid for all sub-streams contained in the file. At the ++ * very least, this taglist should contain information about the container ++ * format in a #GST_TAG_CONTAINER_FORMAT tag (where applicable, otherwise it ++ * will contain a translated string saying 'Unknown'). If there is a ++ * #GST_TAG_DURATION tag it will contain the maximum value of all the stream ++ * durations (as queried). ++ * ++ * ++ * After the tag message with the global tags there will be one tag message ++ * for each audio/video/subtitle stream, containing the information for that ++ * particular stream. At the very least, there should be a #GST_TAG_AUDIO_CODEC, ++ * #GST_TAG_VIDEO_CODEC, #GST_TAG_SUBITLE_CODEC, or #GST_TAG_CODEC tag. There ++ * may also be a #GST_TAG_DURATION tag with the stream's duration. ++ * ++ * ++ * For audio streams, there will be "channels" and "rate" tags (of type int) ++ * in the taglist, provided that information could be extracted. ++ * ++ * ++ * For video streams, there will be "width", "height", "pixel-aspect-ratio" ++ * and "framerate" fields (of type int, int, fraction and fraction respectively) ++ * if that information was available. A framerate of 0/N means that the ++ * framerate is variable and no average framerate is known. ++ * ++ * ++ * Just like playbin, this element does not expose any pads. ++ * ++ * ++ * Since 0.10.24 ++ * ++ * ++ */ ++ ++/* TODO: ++ * - thumbnailing ++ * ++ * - wait with preroll until duration stabilises (e.g. for mp3/aac/mpeg) ++ * ++ * - missing plugin messages ++ * ++ * - Fix parser/decoder elements so that global tags / stream tags ++ * differentiation actually works right, ie. make sure they send tags ++ * received from upstream before pushing their own tags (we'll only consider ++ * taglists received before the first taglist with a *_CODEC tag suitable ++ * for global tags) ++ */ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include "gsttagreadbin.h" ++#include "gsttagreadutils.h" ++#include "gsttagsink.h" ++ ++#include ++#include ++ ++#include ++ ++GST_DEBUG_CATEGORY (tagreadbin_debug); ++#define GST_CAT_DEFAULT tagreadbin_debug ++ ++/* from gst/playback/gstplay-enum.h */ ++typedef enum ++{ ++ GST_AUTOPLUG_SELECT_TRY, ++ GST_AUTOPLUG_SELECT_EXPOSE, ++ GST_AUTOPLUG_SELECT_SKIP ++} GstAutoplugSelectResult; ++ ++/* props */ ++#define DEFAULT_URI NULL ++ ++enum ++{ ++ PROP_0, ++ PROP_URI ++}; ++ ++static void gst_tag_read_bin_dispose (GObject * object); ++static void gst_tag_read_bin_finalize (GObject * object); ++static void gst_tag_read_bin_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * spec); ++static void gst_tag_read_bin_get_property (GObject * object, guint prop_id, ++ GValue * value, GParamSpec * spec); ++ ++static GstStateChangeReturn gst_tag_read_bin_change_state (GstElement * element, ++ GstStateChange transition); ++static void gst_tag_read_bin_handle_message (GstBin * bin, GstMessage * msg); ++ ++GST_BOILERPLATE (GstTagReadBin, gst_tag_read_bin, GstPipeline, ++ GST_TYPE_PIPELINE); ++ ++static void ++gst_tag_read_bin_base_init (gpointer g_klass) ++{ ++ /* nothing to do */ ++} ++ ++static void ++gst_tag_read_bin_class_init (GstTagReadBinClass * klass) ++{ ++ GstElementClass *gstelement_klass = (GstElementClass *) klass; ++ GObjectClass *gobject_klass = (GObjectClass *) klass; ++ GstBinClass *gstbin_klass = (GstBinClass *) klass; ++ ++ gst_element_class_set_details_simple (gstelement_klass, ++ "Tag Read Bin", "Generic/Bin/Metadata", "Extract metadata from an uri", ++ "Tim-Philipp Müller "); ++ ++ gobject_klass->set_property = gst_tag_read_bin_set_property; ++ gobject_klass->get_property = gst_tag_read_bin_get_property; ++ ++ gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_tag_read_bin_dispose); ++ gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_tag_read_bin_finalize); ++ ++ /** ++ * GstTagReadBin:uri ++ * ++ * URI to extract metadata from. Only file:// URIs are supported at the ++ * moment. To create an URI from a filename, you can use g_filename_to_uri(). ++ */ ++ g_object_class_install_property (gobject_klass, PROP_URI, ++ g_param_spec_string ("uri", "URI", "URI to extract tags from", ++ NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ ++ gstelement_klass->change_state = ++ GST_DEBUG_FUNCPTR (gst_tag_read_bin_change_state); ++ ++ gstbin_klass->handle_message = ++ GST_DEBUG_FUNCPTR (gst_tag_read_bin_handle_message); ++} ++ ++static gboolean ++gst_tag_read_bin_factory_is_demuxer (GstElementFactory * factory) ++{ ++ const gchar *klass = gst_element_factory_get_klass (factory); ++ ++ return (klass != NULL && strstr (klass, "Demux") != NULL); ++} ++ ++static gboolean ++gst_tag_read_bin_factory_is_parser (GstElementFactory * factory) ++{ ++ const gchar *klass = gst_element_factory_get_klass (factory); ++ ++ return (klass != NULL && strstr (klass, "Parse") != NULL); ++} ++ ++static gboolean ++gst_tag_read_bin_factory_is_metadata_extractor (GstElementFactory * factory) ++{ ++ const gchar *klass = gst_element_factory_get_klass (factory); ++ ++ return (klass && strstr (klass, "Metadata") && strstr (klass, "Extracter")); ++} ++ ++static gboolean ++gst_tag_read_bin_factory_is_tag_reader (GstElementFactory * factory) ++{ ++ guint rank; ++ const gchar *klass; ++ ++ klass = gst_element_factory_get_klass (factory); ++ ++ /* only demuxers, parsers or metadata extractor elements can play ++ * (note: in parcticular, we don't want to plug decodebin2 even though ++ * it does implement the tag reader interface as well) */ ++ if (!gst_tag_read_bin_factory_is_demuxer (factory) && ++ !gst_tag_read_bin_factory_is_parser (factory) && ++ !gst_tag_read_bin_factory_is_metadata_extractor (factory)) { ++ return FALSE; ++ } ++ ++ /* tag readers are fine whatever their rank */ ++ if (gst_element_factory_has_interface (factory, "GstTagReader")) { ++ GST_LOG ("selecting %s, it implements the tag reader interface", ++ GST_PLUGIN_FEATURE_NAME (factory)); ++ return TRUE; ++ } ++ ++ /* only select elements with autoplugging rank */ ++ rank = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory)); ++ if (rank < GST_RANK_MARGINAL) ++ return FALSE; ++ ++ GST_LOG ("selecting %s, class/rank ok", GST_PLUGIN_FEATURE_NAME (factory)); ++ return TRUE; ++} ++ ++/* function used to sort element features. We first sort on the tag reader ++ * interface, then rank, then on the element name (to get a consistent, ++ * predictable list) */ ++static gint ++gst_tag_read_bin_compare_ranks (GValue * v1, GValue * v2) ++{ ++ const gchar *rname1, *rname2; ++ GstPluginFeature *f1, *f2; ++ gboolean is_tagreader1, is_tagreader2; ++ gint diff; ++ ++ f1 = g_value_get_object (v1); ++ f2 = g_value_get_object (v2); ++ ++ is_tagreader1 = gst_element_factory_has_interface (GST_ELEMENT_FACTORY (f1), ++ "GstTagReader"); ++ is_tagreader2 = gst_element_factory_has_interface (GST_ELEMENT_FACTORY (f2), ++ "GstTagReader"); ++ ++ if (is_tagreader1 != is_tagreader2) ++ return (is_tagreader2) ? 1 : -1; ++ ++ diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); ++ if (diff != 0) ++ return diff; ++ ++ rname1 = gst_plugin_feature_get_name (f1); ++ rname2 = gst_plugin_feature_get_name (f2); ++ ++ diff = strcmp (rname2, rname1); ++ ++ return diff; ++} ++ ++static GValueArray * ++gst_tag_read_bin_get_tag_readers (void) ++{ ++ GValueArray *result; ++ GList *l, *list; ++ ++ result = g_value_array_new (0); ++ ++ /* get the feature list using the filter */ ++ list = gst_registry_get_feature_list (gst_registry_get_default (), ++ GST_TYPE_ELEMENT_FACTORY); ++ ++ /* filter and convert to an array */ ++ for (l = list; l != NULL; l = l->next) { ++ GstElementFactory *factory = GST_ELEMENT_FACTORY (l->data); ++ ++ if (gst_tag_read_bin_factory_is_tag_reader (factory)) { ++ GValue val = { 0, }; ++ ++ g_value_init (&val, GST_TYPE_ELEMENT_FACTORY); ++ g_value_set_object (&val, factory); ++ g_value_array_append (result, &val); ++ g_value_unset (&val); ++ } ++ } ++ ++ gst_plugin_feature_list_free (list); ++ ++ /* sort on tag reader interface rank and name */ ++ g_value_array_sort (result, (GCompareFunc) gst_tag_read_bin_compare_ranks); ++ ++ return result; ++} ++ ++static gboolean ++gst_tag_read_bin_factory_list_has_demuxer (GValueArray * factories) ++{ ++ guint i; ++ ++ for (i = 0; i < factories->n_values; ++i) { ++ GstElementFactory *factory; ++ GValue *val; ++ ++ val = g_value_array_get_nth (factories, i); ++ factory = GST_ELEMENT_FACTORY (g_value_get_object (val)); ++ ++ if (gst_tag_read_bin_factory_is_demuxer (factory)) ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++static void ++gst_tag_read_bin_init (GstTagReadBin * tbin, GstTagReadBinClass * klass) ++{ ++ tbin->dyn_lock = g_mutex_new (); ++ ++ /* cache interesting element factories */ ++ tbin->elements = gst_tag_read_bin_get_tag_readers (); ++} ++ ++static void ++gst_tag_read_bin_dispose (GObject * object) ++{ ++ GstTagReadBin *tbin = GST_TAG_READ_BIN (object); ++ ++ g_value_array_free (tbin->elements); ++ ++ G_OBJECT_CLASS (parent_class)->dispose (object); ++} ++ ++static void ++gst_tag_read_bin_finalize (GObject * object) ++{ ++ GstTagReadBin *tbin = GST_TAG_READ_BIN (object); ++ ++ g_mutex_free (tbin->dyn_lock); ++ tbin->dyn_lock = NULL; ++ g_free (tbin->uri); ++ tbin->uri = NULL; ++ ++ G_OBJECT_CLASS (parent_class)->finalize (object); ++} ++ ++static void ++gst_tag_read_bin_post_tags (GstTagReadBin * tbin) ++{ ++ GstTagList *tags; ++ guint i; ++ ++ GST_DEBUG_OBJECT (tbin, "posting tags"); ++ ++ tags = gst_tag_sink_get_global_tags (GST_TAG_SINK (tbin->tagsink)); ++ GST_INFO_OBJECT (tbin, "global tags: %" GST_PTR_FORMAT, tags); ++ if (tags != NULL) { ++ /* if there's no container format in the tags, add one based on caps */ ++ if (!gst_tag_read_utils_list_has_container_tag (tags) && ++ tbin->container_caps != NULL) { ++ gst_tag_read_utils_add_container_tag_from_caps (tags, ++ tbin->container_caps); ++ } ++ ++ GST_BIN_CLASS (parent_class)->handle_message (GST_BIN (tbin), ++ gst_message_new_tag (GST_OBJECT_CAST (tbin), tags)); ++ } ++ ++ for (i = 0;; ++i) { ++ tags = gst_tag_sink_get_stream_tags (GST_TAG_SINK (tbin->tagsink), i); ++ ++ /* there should always at least be a *_CODEC tag based on the caps */ ++ if (tags == NULL) ++ break; ++ ++ GST_BIN_CLASS (parent_class)->handle_message (GST_BIN (tbin), ++ gst_message_new_tag (GST_OBJECT_CAST (tbin), tags)); ++ } ++} ++ ++static void ++gst_tag_read_bin_handle_message (GstBin * bin, GstMessage * msg) ++{ ++ GstTagReadBin *tbin = GST_TAG_READ_BIN (bin); ++ ++ /* Suppress all tag messages from other elements. We'll collect tags from ++ * the pads and then post messages of our own when we're done and we have ++ * all the information */ ++ switch (GST_MESSAGE_TYPE (msg)) { ++ case GST_MESSAGE_TAG: ++ { ++ GST_LOG_OBJECT (bin, "suppressing tags from element %s: %" GST_PTR_FORMAT, ++ GST_OBJECT_NAME (msg->src), msg->structure); ++ GST_OBJECT_LOCK (tbin); ++ tbin->tag_messages = g_list_append (tbin->tag_messages, msg); ++ msg = NULL; ++ GST_OBJECT_UNLOCK (tbin); ++ break; ++ } ++ case GST_MESSAGE_ASYNC_DONE: ++ { ++ if (msg->src == GST_OBJECT_CAST (tbin->tagsink)) { ++ GST_DEBUG_OBJECT (bin, "done collecting tags"); ++ gst_tag_read_bin_post_tags (tbin); ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ ++ if (msg != NULL) ++ GST_BIN_CLASS (parent_class)->handle_message (bin, msg); ++} ++ ++ ++static void ++gst_tag_read_bin_set_uri (GstTagReadBin * tbin, const gchar * uri) ++{ ++ if (uri == NULL || !gst_uri_is_valid (uri)) { ++ g_warning ("Can't set invalid URI '%s' on tagreadbin element %s", ++ GST_STR_NULL (uri), GST_ELEMENT_NAME (tbin)); ++ return; ++ } ++ ++ GST_FIXME_OBJECT (tbin, "Add support for non-file:// URIs"); ++ ++ if (!gst_uri_has_protocol (uri, "file")) { ++ g_warning ("Tagreadbin only supports file:// URIs for the time being"); ++ return; ++ } ++ ++ GST_OBJECT_LOCK (tbin); ++ if (tbin->uri != uri) { ++ g_free (tbin->uri); ++ tbin->uri = g_strdup (uri); ++ } ++ GST_OBJECT_UNLOCK (tbin); ++ ++ GST_INFO_OBJECT (tbin, "Set URI to '%s'", uri); ++} ++ ++static void ++gst_tag_read_bin_set_property (GObject * object, guint prop_id, ++ const GValue * value, GParamSpec * pspec) ++{ ++ GstTagReadBin *tbin = GST_TAG_READ_BIN (object); ++ ++ switch (prop_id) { ++ case PROP_URI: ++ gst_tag_read_bin_set_uri (tbin, g_value_get_string (value)); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++gst_tag_read_bin_get_property (GObject * object, guint prop_id, GValue * value, ++ GParamSpec * pspec) ++{ ++ GstTagReadBin *tbin = GST_TAG_READ_BIN (object); ++ ++ switch (prop_id) { ++ case PROP_URI: ++ GST_OBJECT_LOCK (tbin); ++ g_value_set_string (value, tbin->uri); ++ GST_OBJECT_UNLOCK (tbin); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++/* This function is called when a new pad is added to uridecodebin. */ ++static void ++tag_read_bin_decodebin_pad_added (GstElement * decodebin, GstPad * pad, ++ GstTagReadBin * tbin) ++{ ++ GstPadLinkReturn res; ++ GstPad *request_pad; ++ ++ GST_TAG_READ_BIN_SHUTDOWN_LOCK (tbin, shutdown); ++ ++ request_pad = gst_element_get_request_pad (tbin->tagsink, "sink%d"); ++ GST_LOG_OBJECT (request_pad, "got new request pad"); ++ tbin->request_pads = g_list_prepend (tbin->request_pads, request_pad); ++ ++ res = gst_pad_link (pad, request_pad); ++ ++ if (GST_PAD_LINK_SUCCESSFUL (res)) { ++ GST_DEBUG_OBJECT (tbin, "linked new pad %s:%s to %s:%s", ++ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (request_pad)); ++ } else { ++ GST_WARNING_OBJECT (tbin, "failed to link new pad %s:%s to %s:%s: %d", ++ GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (request_pad), res); ++ } ++ ++ GST_TAG_READ_BIN_SHUTDOWN_UNLOCK (tbin); ++ return; ++ ++shutdown: ++ { ++ GST_DEBUG_OBJECT (tbin, "shutdown"); ++ return; ++ } ++} ++ ++/* we get called when all pads are available and we must connect the sinks to ++ * them. ++ * The main purpose of the code is to see if we have video/audio and subtitles ++ * and pick the right pipelines to display them. ++ * ++ * The selectors installed on the group tell us about the presence of ++ * audio/video and subtitle streams. This allows us to see if we need ++ * visualisation, video or/and audio. ++ */ ++static void ++tag_read_bin_decodebin_no_more_pads (GstElement * decodebin, ++ GstTagReadBin * tbin) ++{ ++ GST_DEBUG_OBJECT (decodebin, "no more pads"); ++} ++ ++static GValueArray * ++gst_factory_list_filter_by_sinkcaps (GValueArray * array, const GstCaps * caps) ++{ ++ GValueArray *result; ++ gint i; ++ ++ result = g_value_array_new (0); ++ ++ GST_DEBUG ("finding factories for %" GST_PTR_FORMAT, caps); ++ ++ /* loop over all the factories */ ++ for (i = 0; i < array->n_values; i++) { ++ GValue *value; ++ GstElementFactory *factory; ++ const GList *templates; ++ GList *walk; ++ ++ value = g_value_array_get_nth (array, i); ++ factory = g_value_get_object (value); ++ ++ /* get the templates from the element factory */ ++ templates = gst_element_factory_get_static_pad_templates (factory); ++ for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { ++ GstStaticPadTemplate *templ = walk->data; ++ ++ /* we only care about the sink templates */ ++ if (templ->direction == GST_PAD_SINK) { ++ GstCaps *intersect; ++ GstCaps *tmpl_caps; ++ ++ /* try to intersect the caps with the caps of the template */ ++ tmpl_caps = gst_static_caps_get (&templ->static_caps); ++ ++ /* FIXME, intersect is not the right method, we ideally want to check ++ * for a subset here */ ++ intersect = gst_caps_intersect (caps, tmpl_caps); ++ gst_caps_unref (tmpl_caps); ++ ++ /* check if the intersection is empty */ ++ if (!gst_caps_is_empty (intersect)) { ++ /* non empty intersection, we can use this element */ ++ GValue resval = { 0, }; ++ g_value_init (&resval, G_TYPE_OBJECT); ++ g_value_set_object (&resval, factory); ++ g_value_array_append (result, &resval); ++ g_value_unset (&resval); ++ gst_caps_unref (intersect); ++ break; ++ } ++ gst_caps_unref (intersect); ++ } ++ } ++ } ++ GST_DEBUG ("found %u factories for %" GST_PTR_FORMAT, result->n_values, caps); ++ return result; ++} ++ ++/* Called when we must provide a list of factories to plug pad with caps */ ++static GValueArray * ++tag_read_bin_decodebin_autoplug_factories (GstElement * decodebin, ++ GstPad * pad, GstCaps * caps, GstTagReadBin * tbin) ++{ ++ GValueArray *result = NULL; ++ ++ GST_TAG_READ_BIN_SHUTDOWN_LOCK (tbin, shutdown); ++ ++ GST_DEBUG_OBJECT (tbin, "getting factories for caps %" GST_PTR_FORMAT, caps); ++ ++ /* filter out the elements based on the caps */ ++ result = gst_factory_list_filter_by_sinkcaps (tbin->elements, caps); ++ ++ if (tbin->container_caps == NULL && ++ gst_tag_read_bin_factory_list_has_demuxer (result)) { ++ GST_DEBUG_OBJECT (tbin, "possible container caps: %" GST_PTR_FORMAT, caps); ++ gst_caps_replace (&tbin->container_caps, caps); ++ } ++ ++ GST_DEBUG_OBJECT (tbin, "found %u factories", result->n_values); ++ ++ /* nothing else found => expose pad as it is now and hope for the best */ ++ if (result->n_values == 0) { ++ if (!gst_tag_read_utils_caps_complete (caps)) { ++ GST_FIXME ("caps without all the info we want and no more tagreaders/" ++ "parsers to plug for %" GST_PTR_FORMAT, caps); ++ } ++ g_value_array_free (result); ++ result = NULL; ++ } ++ ++ GST_TAG_READ_BIN_SHUTDOWN_UNLOCK (tbin); ++ ++ return result; ++ ++shutdown: ++ { ++ GST_DEBUG_OBJECT (tbin, "shutdown"); ++ return NULL; ++ } ++} ++ ++static gboolean ++tag_read_bin_decodebin_autoplug_continue (GstElement * decodebin, GstPad * pad, ++ GstCaps * caps, GstTagReadBin * tbin) ++{ ++ GstFormat fmt = GST_FORMAT_TIME; ++ gboolean do_continue = FALSE; ++ gboolean query_ok, capsinfo_ok; ++ gint64 dur = 0; ++ ++ GST_TAG_READ_BIN_SHUTDOWN_LOCK (tbin, shutdown); ++ ++ GST_DEBUG_OBJECT (tbin, "continue with caps %" GST_PTR_FORMAT "?", caps); ++ ++ query_ok = gst_pad_query_duration (pad, &fmt, &dur) && (dur > 0); ++ GST_LOG_OBJECT (tbin, "duration query: res=%d, duration=%" G_GINT64_FORMAT, ++ query_ok, dur); ++ ++ capsinfo_ok = gst_tag_read_utils_caps_complete (caps); ++ GST_LOG_OBJECT (tbin, "caps info complete: %d", capsinfo_ok); ++ ++ /* stop if we have both a duration and the caps are complete enough */ ++ do_continue = !query_ok || !capsinfo_ok; ++ GST_LOG_OBJECT (tbin, "continue: %d", do_continue); ++ ++ GST_TAG_READ_BIN_SHUTDOWN_UNLOCK (tbin); ++ return do_continue; ++ ++shutdown: ++ { ++ GST_DEBUG_OBJECT (tbin, "shutting down"); ++ return FALSE; ++ } ++} ++ ++/* We are asked to select an element. We can return TRY or EXPOSE */ ++static GstAutoplugSelectResult ++tag_read_bin_decodebin_autoplug_select (GstElement * decodebin, GstPad * pad, ++ GstCaps * caps, GstElementFactory * factory, GstTagReadBin * tbin) ++{ ++ GST_LOG_OBJECT (tbin, "selecting %s for caps %" GST_PTR_FORMAT, ++ GST_PLUGIN_FEATURE_NAME (factory), caps); ++ ++ return GST_AUTOPLUG_SELECT_TRY; ++} ++ ++#define REMOVE_SIGNAL(obj,id) \ ++if (id) { \ ++ g_signal_handler_disconnect (obj, id); \ ++ id = 0; \ ++} ++ ++static void ++gst_tag_read_bin_cleanup (GstTagReadBin * tbin) ++{ ++ while (tbin->request_pads) { ++ GstPad *pad = tbin->request_pads->data; ++ ++ gst_element_release_request_pad (tbin->tagsink, pad); ++ gst_object_unref (pad); ++ tbin->request_pads = ++ g_list_delete_link (tbin->request_pads, tbin->request_pads); ++ } ++ if (tbin->uridecodebin) { ++ GST_LOG_OBJECT (tbin, "removing existing decodebin"); ++ REMOVE_SIGNAL (tbin->uridecodebin, tbin->pad_added_id); ++ REMOVE_SIGNAL (tbin->uridecodebin, tbin->no_more_pads_id); ++ REMOVE_SIGNAL (tbin->uridecodebin, tbin->autoplug_factories_id); ++ REMOVE_SIGNAL (tbin->uridecodebin, tbin->autoplug_select_id); ++ gst_element_set_state (tbin->uridecodebin, GST_STATE_NULL); ++ gst_bin_remove (GST_BIN (tbin), tbin->uridecodebin); ++ tbin->uridecodebin = NULL; ++ GST_DEBUG_OBJECT (tbin, "removed decodebin"); ++ } ++ if (tbin->tagsink) { ++ GST_LOG_OBJECT (tbin, "removing tagsink"); ++ gst_element_set_state (tbin->tagsink, GST_STATE_NULL); ++ gst_bin_remove (GST_BIN (tbin), tbin->tagsink); ++ tbin->tagsink = NULL; ++ GST_DEBUG_OBJECT (tbin, "removed tagsink"); ++ } ++ while (tbin->tag_messages) { ++ gst_message_unref (tbin->tag_messages->data); ++ tbin->tag_messages = g_list_delete_link (tbin->tag_messages, ++ tbin->tag_messages); ++ } ++ gst_caps_replace (&tbin->container_caps, NULL); ++} ++ ++static gboolean ++gst_tag_read_bin_setup (GstTagReadBin * tbin) ++{ ++ GstStateChangeReturn state_ret; ++ GstState pending; ++ ++ tbin->container_caps = NULL; ++ ++ GST_DEBUG_OBJECT (tbin, "creating new decodebin"); ++ tbin->uridecodebin = gst_element_factory_make ("uridecodebin", NULL); ++ if (tbin->uridecodebin == NULL) ++ goto no_decodebin; ++ ++ gst_tag_reader_set_tag_reading_mode (GST_TAG_READER (tbin->uridecodebin), ++ GST_TAG_READING_MODE_TAGS_ONLY); ++ ++ gst_bin_add (GST_BIN_CAST (tbin), tbin->uridecodebin); ++ ++ /* pad-added: we connect the newly exposed pad to the tagsink */ ++ tbin->pad_added_id = g_signal_connect (tbin->uridecodebin, "pad-added", ++ G_CALLBACK (tag_read_bin_decodebin_pad_added), tbin); ++ ++ /* no-more-pads: we just connect this for logging purposes */ ++ tbin->no_more_pads_id = g_signal_connect (tbin->uridecodebin, "no-more-pads", ++ G_CALLBACK (tag_read_bin_decodebin_no_more_pads), tbin); ++ ++ /* autoplug-factories: will be called when a new media type is found. We ++ * return a list of tagreaders or parser for decodebin to try */ ++ tbin->autoplug_factories_id = ++ g_signal_connect (tbin->uridecodebin, "autoplug-factories", ++ G_CALLBACK (tag_read_bin_decodebin_autoplug_factories), tbin); ++ ++ /* autoplug-continue: determine whether we've got the kind of caps we're ++ * looking for etc. or if we want to plug further tagreaders/parsers */ ++ tbin->autoplug_continue_id = g_signal_connect (tbin->uridecodebin, ++ "autoplug-continue", ++ G_CALLBACK (tag_read_bin_decodebin_autoplug_continue), tbin); ++ ++ /* autoplug-select: report what's being plugged next */ ++ tbin->autoplug_select_id = g_signal_connect (tbin->uridecodebin, ++ "autoplug-select", G_CALLBACK (tag_read_bin_decodebin_autoplug_select), ++ tbin); ++ ++ g_object_set (tbin->uridecodebin, "uri", tbin->uri, NULL); ++ ++ GST_STATE_LOCK (tbin); ++ pending = GST_STATE_PENDING (tbin); ++ GST_STATE_UNLOCK (tbin); ++ ++ tbin->tagsink = g_object_new (GST_TYPE_TAG_SINK, NULL); ++ gst_bin_add (GST_BIN (tbin), tbin->tagsink); ++ gst_element_set_state (tbin->tagsink, pending); ++ ++ state_ret = gst_element_set_state (tbin->uridecodebin, pending); ++ if (state_ret == GST_STATE_CHANGE_FAILURE) ++ goto decodebin_failure; ++ ++ return TRUE; ++ ++ /* ERRORS */ ++no_decodebin: ++ { ++ gst_element_post_message (GST_ELEMENT_CAST (tbin), ++ gst_missing_element_message_new (GST_ELEMENT (tbin), "uridecodebin")); ++ GST_ELEMENT_ERROR (tbin, CORE, MISSING_PLUGIN, (NULL), ("no uridecodebin")); ++ return FALSE; ++ } ++decodebin_failure: ++ { ++ GST_DEBUG_OBJECT (tbin, "decodebin state change failed"); ++ gst_tag_read_bin_cleanup (tbin); ++ /* an error message should have been posted already, but better be safe */ ++ GST_ELEMENT_ERROR (tbin, CORE, STATE_CHANGE, (NULL), (NULL)); ++ return FALSE; ++ } ++} ++ ++static GstStateChangeReturn ++gst_tag_read_bin_change_state (GstElement * element, GstStateChange transition) ++{ ++ GstStateChangeReturn ret; ++ GstTagReadBin *tbin; ++ ++ tbin = GST_TAG_READ_BIN (element); ++ ++ GST_LOG_OBJECT (tbin, "transition %s -> %s", ++ gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), ++ gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); ++ ++ switch (transition) { ++ case GST_STATE_CHANGE_READY_TO_PAUSED: ++ GST_LOG_OBJECT (tbin, "clearing shutdown flag"); ++ g_atomic_int_set (&tbin->shutdown, 0); ++ if (!gst_tag_read_bin_setup (tbin)) ++ return GST_STATE_CHANGE_FAILURE; ++ break; ++ case GST_STATE_CHANGE_PAUSED_TO_READY: ++ GST_LOG_OBJECT (tbin, "setting shutdown flag"); ++ g_atomic_int_set (&tbin->shutdown, 1); ++ ++ /* wait for all callbacks to end by taking the lock. ++ * No dynamic (critical) new callbacks will ++ * be able to happen as we set the shutdown flag. */ ++ GST_TAG_READ_BIN_DYN_LOCK (tbin); ++ GST_LOG_OBJECT (tbin, "dynamic lock taken, we can continue shutdown"); ++ GST_TAG_READ_BIN_DYN_UNLOCK (tbin); ++ break; ++ case GST_STATE_CHANGE_PAUSED_TO_PLAYING: ++ gst_element_post_message (element, ++ gst_message_new_eos (GST_OBJECT_CAST (element))); ++ break; ++ case GST_STATE_CHANGE_READY_TO_NULL: ++ break; ++ default: ++ break; ++ } ++ ++ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); ++ if (ret == GST_STATE_CHANGE_FAILURE) ++ return ret; ++ ++ switch (transition) { ++ case GST_STATE_CHANGE_PAUSED_TO_READY: ++ case GST_STATE_CHANGE_READY_TO_NULL: ++ gst_tag_read_bin_cleanup (tbin); ++ break; ++ default: ++ break; ++ } ++ ++ GST_LOG_OBJECT (tbin, "transition %s -> %s, returning %s", ++ gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), ++ gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), ++ gst_element_state_change_return_get_name (ret)); ++ ++ return ret; ++} ++ ++static gboolean ++plugin_init (GstPlugin * plugin) ++{ ++ GST_DEBUG_CATEGORY_INIT (tagreadbin_debug, "tagreadbin", 0, "Tag read bin"); ++ ++ gst_tag_read_utils_register_caps_tags (); ++ ++ return gst_element_register (plugin, "tagreadbin", GST_RANK_NONE, ++ GST_TYPE_TAG_READ_BIN); ++} ++ ++GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, ++ "tagreading", "Tag reading support", plugin_init, VERSION, GST_LICENSE, ++ GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) +diff --git a/gst/tagreading/gsttagreadbin.h b/gst/tagreading/gsttagreadbin.h +new file mode 100644 +index 0000000..d380bce +--- /dev/null ++++ b/gst/tagreading/gsttagreadbin.h +@@ -0,0 +1,104 @@ ++/* GStreamer tag read bin ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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_TAG_READ_BIN_H__ ++#define __GST_TAG_READ_BIN_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++#define GST_TYPE_TAG_READ_BIN (gst_tag_read_bin_get_type()) ++#define GST_TAG_READ_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_READ_BIN,GstTagReadBin)) ++#define GST_TAG_READ_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_READ_BIN,GstTagReadBinClass)) ++#define GST_IS_TAG_READ_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_READ_BIN)) ++#define GST_IS_TAG_READ_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_READ_BIN)) ++ ++#define GST_TAG_READ_BIN_DYN_LOCK(tbin) g_mutex_lock ((tbin)->dyn_lock) ++#define GST_TAG_READ_BIN_DYN_UNLOCK(tbin) g_mutex_unlock ((tbin)->dyn_lock) ++ ++/* lock for shutdown */ ++#define GST_TAG_READ_BIN_SHUTDOWN_LOCK(tbin,label) \ ++G_STMT_START { \ ++ if (G_UNLIKELY (g_atomic_int_get (&tbin->shutdown))) \ ++ goto label; \ ++ GST_TAG_READ_BIN_DYN_LOCK (tbin); \ ++ if (G_UNLIKELY (g_atomic_int_get (&tbin->shutdown))) { \ ++ GST_TAG_READ_BIN_DYN_UNLOCK (tbin); \ ++ goto label; \ ++ } \ ++} G_STMT_END ++ ++/* unlock for shutdown */ ++#define GST_TAG_READ_BIN_SHUTDOWN_UNLOCK(bin) \ ++ GST_TAG_READ_BIN_DYN_UNLOCK (bin); \ ++ ++typedef struct _GstTagReadBin GstTagReadBin; ++typedef struct _GstTagReadBinClass GstTagReadBinClass; ++ ++/** ++ * GstTagReadBin: ++ * ++ * tagreadbin element structure (opaque) ++ * ++ */ ++struct _GstTagReadBin ++{ ++ GstPipeline parent; ++ ++ /*< private >*/ ++ GstElement * uridecodebin; ++ gchar * uri; ++ ++ GstElement * tagsink; ++ ++ /* factories we can use for selecting elements */ ++ GValueArray * elements; ++ ++ /* lock protecting dynamic adding/removing */ ++ GMutex * dyn_lock; ++ ++ /* if we are shutting down or not */ ++ gint shutdown; /* ATOMIC */ ++ ++ /* tag messages we dropped (to compare to tag events collected from pads) */ ++ GList *tag_messages; /* OBJECT_LOCK */ ++ ++ GstCaps *container_caps; /* DYN_LOCK */ ++ ++ GList *request_pads; /* DYN_LOCK */ ++ ++ /* decodebin signals */ ++ gulong pad_added_id; ++ gulong no_more_pads_id; ++ gulong autoplug_factories_id; ++ gulong autoplug_continue_id; ++ gulong autoplug_select_id; ++}; ++ ++struct _GstTagReadBinClass ++{ ++ GstPipelineClass parent_class; ++}; ++ ++GType gst_tag_read_bin_get_type (void); ++ ++G_END_DECLS ++ ++#endif /* __GST_TAG_READ_BIN_H__ */ +diff --git a/gst/tagreading/gsttagreadutils.c b/gst/tagreading/gsttagreadutils.c +new file mode 100644 +index 0000000..acaebb6 +--- /dev/null ++++ b/gst/tagreading/gsttagreadutils.c +@@ -0,0 +1,309 @@ ++/* GStreamer tag read bin utilities ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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 "gsttagreadutils.h" ++#include ++ ++GST_DEBUG_CATEGORY_EXTERN (tagreadbin_debug); ++#define GST_CAT_DEFAULT tagreadbin_debug ++ ++GstTagReadStreamType ++gst_tag_read_utils_get_caps_type (const GstCaps * caps) ++{ ++ GstStructure *s; ++ const gchar *name; ++ ++ s = gst_caps_get_structure (caps, 0); ++ name = gst_structure_get_name (s); ++ ++ if (g_str_equal (name, "video/x-dvd-subpicture") || ++ g_str_has_prefix (name, "text/")) { ++ return GST_TAG_READ_STREAM_TYPE_SUBTITLE; ++ } ++ ++ if (g_str_has_prefix (name, "application/x-subtitle")) ++ return GST_TAG_READ_STREAM_TYPE_SUBTITLE; ++ ++ if (g_str_has_prefix (name, "audio/")) ++ return GST_TAG_READ_STREAM_TYPE_AUDIO; ++ ++ if (g_str_has_prefix (name, "video/") || g_str_has_prefix (name, "image/")) { ++ return GST_TAG_READ_STREAM_TYPE_VIDEO; ++ } ++ ++ return GST_TAG_READ_STREAM_TYPE_UNKNOWN; ++} ++ ++gboolean ++gst_tag_read_utils_caps_complete (const GstCaps * caps) ++{ ++ GstStructure *s; ++ const gchar *name; ++ gboolean complete; ++ ++ s = gst_caps_get_structure (caps, 0); ++ name = gst_structure_get_name (s); ++ ++ if (g_str_equal (name, "video/x-dvd-subpicture") || ++ g_str_has_prefix (name, "text/")) { ++ complete = TRUE; ++ } else if (g_str_has_prefix (name, "application/x-subtitle")) { ++ /* subtitle parser might give us more info */ ++ complete = FALSE; ++ } else if (g_str_has_prefix (name, "audio/")) { ++ complete = gst_structure_has_field (s, "channels") && ++ gst_structure_has_field (s, "rate"); ++ } else if (g_str_has_prefix (name, "video/") || ++ g_str_has_prefix (name, "image/")) { ++ complete = gst_structure_has_field (s, "width") && ++ gst_structure_has_field (s, "height"); ++ } else { ++ complete = FALSE; ++ } ++ ++ return complete; ++} ++ ++void ++gst_tag_read_utils_add_codec_tag_from_caps (GstTagList * tags, ++ const GstCaps * caps) ++{ ++ GstTagReadStreamType type; ++ const gchar *tag_name, *tag_name_unknown; ++ ++ gst_pb_utils_init (); ++ ++ type = gst_tag_read_utils_get_caps_type (caps); ++ switch (type) { ++ case GST_TAG_READ_STREAM_TYPE_AUDIO: ++ tag_name = GST_TAG_AUDIO_CODEC; ++ tag_name_unknown = GST_TAG_AUDIO_CODEC "-unknown"; ++ break; ++ case GST_TAG_READ_STREAM_TYPE_VIDEO: ++ tag_name = GST_TAG_VIDEO_CODEC; ++ tag_name_unknown = GST_TAG_VIDEO_CODEC "-unknown"; ++ break; ++ case GST_TAG_READ_STREAM_TYPE_SUBTITLE: ++ tag_name = GST_TAG_SUBTITLE_CODEC; ++ tag_name_unknown = GST_TAG_SUBTITLE_CODEC "-unknown"; ++ break; ++ default: ++ tag_name = GST_TAG_CODEC; ++ tag_name_unknown = GST_TAG_CODEC "-unknown"; ++ break; ++ } ++ ++ GST_LOG ("Adding %s field to tags from %" GST_PTR_FORMAT, tag_name, caps); ++ gst_pb_utils_add_codec_description_to_tag_list (tags, tag_name, caps); ++ ++ if (!gst_tag_read_utils_list_has_codec_tag (tags)) { ++ GST_FIXME ("Couldn't get codec name for caps %" GST_PTR_FORMAT, caps); ++ if (!gst_tag_exists (tag_name_unknown)) { ++ gst_tag_register (tag_name_unknown, GST_TAG_FLAG_ENCODED, ++ G_TYPE_BOOLEAN, "codec unknown", ++ "TRUE if the codec is not known and the *-codec " ++ "tag contains the string 'unknown' or somesuch", NULL); ++ ++ /* FIXME: translate */ ++ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, tag_name, ++ "Unknown", tag_name_unknown, TRUE, NULL); ++ } ++ } ++} ++ ++/* FIXME: remove once we depend on 0.10.24 */ ++#ifndef GST_TAG_CONTAINER_FORMAT ++#define GST_TAG_CONTAINER_FORMAT "container-format" ++#endif ++ ++void ++gst_tag_read_utils_add_container_tag_from_caps (GstTagList * tags, ++ const GstCaps * caps) ++{ ++ gst_pb_utils_init (); ++ ++ /* FIXME: remove once we depend on 0.10.24 */ ++ if (!gst_tag_exists (GST_TAG_CONTAINER_FORMAT)) { ++ gst_tag_register (GST_TAG_CONTAINER_FORMAT, GST_TAG_FLAG_ENCODED, ++ G_TYPE_STRING, "container format", "container format", NULL); ++ } ++ ++ GST_LOG ("Adding container-format field to tags from %" GST_PTR_FORMAT, caps); ++ gst_pb_utils_add_codec_description_to_tag_list (tags, ++ GST_TAG_CONTAINER_FORMAT, caps); ++ ++ /* Adding bogus container-format tag */ ++ if (!gst_tag_read_utils_list_has_container_tag (tags)) { ++ GST_FIXME ("Couldn't get container format for caps %" GST_PTR_FORMAT, caps); ++ ++ if (!gst_tag_exists ("container-format-unknown")) { ++ gst_tag_register ("container-format-unknown", GST_TAG_FLAG_ENCODED, ++ G_TYPE_BOOLEAN, "container format unknown", ++ "TRUE if the container format is not known and the contaier-format " ++ "tag contains the string 'unknown' or somesuch", NULL); ++ } ++ ++ /* FIXME: translate */ ++ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_CONTAINER_FORMAT, ++ "Unknown", "container-format-unknown", TRUE, NULL); ++ } ++} ++ ++gboolean ++gst_tag_read_utils_list_has_container_tag (GstTagList * tags) ++{ ++ const GValue *v; ++ ++ v = gst_tag_list_get_value_index (tags, GST_TAG_CONTAINER_FORMAT, 0); ++ return (v != NULL); ++} ++ ++gboolean ++gst_tag_read_utils_list_has_codec_tag (GstTagList * tags) ++{ ++ return (gst_tag_list_get_value_index (tags, GST_TAG_CODEC, 0) != NULL) || ++ (gst_tag_list_get_value_index (tags, GST_TAG_VIDEO_CODEC, 0) != NULL) || ++ (gst_tag_list_get_value_index (tags, GST_TAG_AUDIO_CODEC, 0) != NULL); ++} ++ ++static void ++gst_tag_read_utils_list_merge_field (GstTagList * tags, GstStructure * s, ++ const gchar * field, GType expected_type) ++{ ++ const GValue *v; ++ ++ if ((v = gst_structure_get_value (s, field))) { ++ if (G_VALUE_TYPE (v) == expected_type) { ++ if (gst_tag_list_get_value_index (tags, field, 0) != NULL) { ++ GST_WARNING ("overwriting tag '%s' with value from caps", field); ++ } ++ gst_tag_list_add_values (tags, GST_TAG_MERGE_REPLACE, field, v, NULL); ++ GST_LOG ("added field '%s' to taglist %" GST_PTR_FORMAT, field, tags); ++ } else { ++ GST_WARNING ("field '%s' in caps %" GST_PTR_FORMAT " does not have the " ++ "expected type (%s)", field, s, g_type_name (expected_type)); ++ } ++ } else { ++ GST_LOG ("no field '%s' in caps %" GST_PTR_FORMAT, field, s); ++ } ++} ++ ++void ++gst_tag_read_utils_register_caps_tags (void) ++{ ++ /* audio tags */ ++ if (!gst_tag_exists ("channels")) { ++ gst_tag_register ("channels", GST_TAG_FLAG_ENCODED, ++ G_TYPE_INT, "channels", "number of audio channels", NULL); ++ } ++ if (!gst_tag_exists ("rate")) { ++ gst_tag_register ("rate", GST_TAG_FLAG_ENCODED, ++ G_TYPE_INT, "rate", "sample rate of audio", NULL); ++ } ++ ++ /* video/image tags */ ++ if (!gst_tag_exists ("width")) { ++ gst_tag_register ("width", GST_TAG_FLAG_ENCODED, ++ G_TYPE_INT, "width", "width of video or image", NULL); ++ } ++ if (!gst_tag_exists ("height")) { ++ gst_tag_register ("height", GST_TAG_FLAG_ENCODED, ++ G_TYPE_INT, "height", "height of video or image", NULL); ++ } ++ if (!gst_tag_exists ("framerate")) { ++ gst_tag_register ("framerate", GST_TAG_FLAG_ENCODED, ++ GST_TYPE_FRACTION, "framerate", "framerate of video", NULL); ++ } ++ if (!gst_tag_exists ("pixel-aspect-ratio")) { ++ gst_tag_register ("pixel-aspect-ratio", GST_TAG_FLAG_ENCODED, ++ GST_TYPE_FRACTION, "pixel-aspect-ratio", "PAR of video", NULL); ++ } ++} ++ ++void ++gst_tag_read_utils_list_add_caps_info (GstTagList * tags, const GstCaps * caps) ++{ ++ GstTagReadStreamType type; ++ GstStructure *s; ++ ++ if (caps == NULL) ++ return; ++ ++ gst_tag_read_utils_register_caps_tags (); ++ ++ s = gst_caps_get_structure (caps, 0); ++ ++ type = gst_tag_read_utils_get_caps_type (caps); ++ switch (type) { ++ /* keep fields in sync with gst_tag_read_utils_register_caps_tags() */ ++ case GST_TAG_READ_STREAM_TYPE_AUDIO: ++ gst_tag_read_utils_list_merge_field (tags, s, "channels", G_TYPE_INT); ++ gst_tag_read_utils_list_merge_field (tags, s, "rate", G_TYPE_INT); ++ break; ++ /* keep fields in sync with gst_tag_read_utils_register_caps_tags() */ ++ case GST_TAG_READ_STREAM_TYPE_VIDEO: ++ gst_tag_read_utils_list_merge_field (tags, s, "width", G_TYPE_INT); ++ gst_tag_read_utils_list_merge_field (tags, s, "height", G_TYPE_INT); ++ gst_tag_read_utils_list_merge_field (tags, s, "framerate", ++ GST_TYPE_FRACTION); ++ gst_tag_read_utils_list_merge_field (tags, s, "pixel-aspect-ratio", ++ GST_TYPE_FRACTION); ++ break; ++ case GST_TAG_READ_STREAM_TYPE_SUBTITLE: ++ break; ++ default: ++ break; ++ } ++} ++ ++void ++gst_tag_read_utils_list_add_duration (GstTagList * tags, GstClockTime dur) ++{ ++ if (GST_CLOCK_TIME_IS_VALID (dur) && dur > 0) { ++ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_DURATION, dur, NULL); ++ GST_LOG ("added field 'duration' to taglist %" GST_PTR_FORMAT, tags); ++ } else { ++ GST_DEBUG ("not adding 'duration' field to taglist, duration not valid"); ++ } ++} ++ ++static void ++taglist_remove_private_foreach_func (const GstTagList * list, ++ const gchar * tag, gpointer user_data) ++{ ++ GList **p_list = user_data; ++ ++ /* tag is a quark string, we don't need to worry about it getting freed */ ++ if (g_str_has_prefix (tag, "private-")) ++ *p_list = g_list_prepend (*p_list, (gpointer) tag); ++} ++ ++void ++gst_tag_read_utils_list_remove_private_tags (GstTagList * tags) ++{ ++ GList *list = NULL; ++ ++ gst_tag_list_foreach (tags, taglist_remove_private_foreach_func, &list); ++ while (list != NULL) { ++ gst_tag_list_remove_tag (tags, list->data); ++ GST_LOG ("Removed tag %s, taglist now %" GST_PTR_FORMAT, ++ (const char *) list->data, tags); ++ list = g_list_delete_link (list, list); ++ } ++} +diff --git a/gst/tagreading/gsttagreadutils.h b/gst/tagreading/gsttagreadutils.h +new file mode 100644 +index 0000000..06ce9ea +--- /dev/null ++++ b/gst/tagreading/gsttagreadutils.h +@@ -0,0 +1,62 @@ ++/* GStreamer tag read bin utilities ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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_TAG_READ_UTILS_H__ ++#define __GST_TAG_READ_UTILS_H__ ++ ++#include ++ ++G_BEGIN_DECLS ++ ++typedef enum ++{ ++ GST_TAG_READ_STREAM_TYPE_UNKNOWN = 0, ++ GST_TAG_READ_STREAM_TYPE_AUDIO, ++ GST_TAG_READ_STREAM_TYPE_VIDEO, ++ GST_TAG_READ_STREAM_TYPE_SUBTITLE ++} GstTagReadStreamType; ++ ++GstTagReadStreamType gst_tag_read_utils_get_caps_type (const GstCaps * caps); ++ ++gboolean gst_tag_read_utils_caps_complete (const GstCaps * caps); ++ ++void gst_tag_read_utils_add_codec_tag_from_caps (GstTagList * tags, ++ const GstCaps * caps); ++ ++void gst_tag_read_utils_add_container_tag_from_caps (GstTagList * tags, ++ const GstCaps * caps); ++ ++gboolean gst_tag_read_utils_list_has_codec_tag (GstTagList * tags); ++ ++gboolean gst_tag_read_utils_list_has_container_tag (GstTagList * tags); ++ ++ ++void gst_tag_read_utils_register_caps_tags (void); ++ ++void gst_tag_read_utils_list_add_caps_info (GstTagList * tags, ++ const GstCaps * caps); ++ ++void gst_tag_read_utils_list_add_duration (GstTagList * tags, ++ GstClockTime dur); ++ ++void gst_tag_read_utils_list_remove_private_tags (GstTagList * tags); ++ ++G_END_DECLS ++ ++#endif /* __GST_TAG_UTILS_H__ */ +diff --git a/gst/tagreading/gsttagsink.c b/gst/tagreading/gsttagsink.c +new file mode 100644 +index 0000000..3741897 +--- /dev/null ++++ b/gst/tagreading/gsttagsink.c +@@ -0,0 +1,785 @@ ++/* GStreamer tag read bin sink ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * License along with this library; if not, write to the ++ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, ++ * Boston, MA 02111-1307, USA. ++ */ ++ ++/* Sink with N request sink pads; collects caps and tags on each stream ++ * until we have seen a buffer or EOS event on all streams. Once we've ++ * collected all the data we want, the sink "prerolls". ++ * ++ * We derive from basesink to avoid having to implement async state change ++ * behaviour ourselves, which is quite tricky to get right. ++ * ++ * Of course we could have done all this very differently, eg. use one sink per ++ * stream or use buffer probes in the tagreadbin etc., but having a separate ++ * element that handles all the collection logic seems conceptually nicer. ++ * If http://bugzilla.gnome.org/show_bug.cgi?id=342155 gets implemented, ++ * we could just derive one tagsink per stream and then use that API. ++ * (we currently don't even need this, but we might in the future, e.g. ++ * should we want to preroll only once the duration returned is somewhat ++ * stable, or if we want to get a thumbnail of the N-th keyframe or so.) ++ */ ++ ++#ifdef HAVE_CONFIG_H ++#include "config.h" ++#endif ++ ++#include ++ ++#include "gsttagsink.h" ++#include "gsttagreadutils.h" ++#include ++ ++/* after this many buffers we mark a stream as done even if haven't gotten ++ * all the information we're looking for yet (caps, duration etc.) */ ++#define GST_TAG_SINK_MAX_BUFFERS 90 ++ ++GST_DEBUG_CATEGORY_EXTERN (tagreadbin_debug); ++#define GST_CAT_DEFAULT tagreadbin_debug ++ ++static GstStaticPadTemplate sinkn_template = ++GST_STATIC_PAD_TEMPLATE ("sink%d", GST_PAD_SINK, ++ GST_PAD_REQUEST, GST_STATIC_CAPS_ANY); ++static GstStaticPadTemplate sink_template = ++GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, ++ GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); ++ ++static void gst_tag_sink_dispose (GObject * object); ++static void gst_tag_sink_finalize (GObject * object); ++static gboolean gst_tag_sink_start (GstBaseSink * basesink); ++static gboolean gst_tag_sink_stop (GstBaseSink * basesink); ++static gboolean gst_tag_sink_unlock (GstBaseSink * basesink); ++static GstPad *gst_tag_sink_request_pad (GstElement * element, ++ GstPadTemplate * templ, const gchar * unused); ++static void gst_tag_sink_release_pad (GstElement * element, GstPad * pad); ++static gboolean gst_tag_sink_sink_event (GstPad * pad, GstEvent * event); ++static gboolean gst_tag_sink_setcaps (GstPad * pad, GstCaps * caps); ++ ++GST_BOILERPLATE (GstTagSink, gst_tag_sink, GstBaseSink, GST_TYPE_BASE_SINK); ++ ++static void ++gst_tag_sink_base_init (gpointer g_klass) ++{ ++ /* nothing to do */ ++} ++ ++static void ++gst_tag_sink_class_init (GstTagSinkClass * klass) ++{ ++ GstBaseSinkClass *basesink_klass = (GstBaseSinkClass *) klass; ++ GstElementClass *element_klass = (GstElementClass *) klass; ++ GObjectClass *gobject_klass = (GObjectClass *) klass; ++ ++ /* dummy template for the normal base sink "sink" pad, which is never ++ * actually linked, we only use it to force basesink to preroll for us ++ * when we're ready */ ++ gst_element_class_add_pad_template (element_klass, ++ gst_static_pad_template_get (&sink_template)); ++ ++ /* template for the request pads, which are used */ ++ gst_element_class_add_pad_template (element_klass, ++ gst_static_pad_template_get (&sinkn_template)); ++ ++ gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_tag_sink_dispose); ++ gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_tag_sink_finalize); ++ ++ element_klass->release_pad = GST_DEBUG_FUNCPTR (gst_tag_sink_release_pad); ++ element_klass->request_new_pad = GST_DEBUG_FUNCPTR (gst_tag_sink_request_pad); ++ ++ basesink_klass->start = GST_DEBUG_FUNCPTR (gst_tag_sink_start); ++ basesink_klass->stop = GST_DEBUG_FUNCPTR (gst_tag_sink_stop); ++ basesink_klass->unlock = GST_DEBUG_FUNCPTR (gst_tag_sink_unlock); ++} ++ ++static void ++gst_tag_sink_init (GstTagSink * tagsink, GstTagSinkClass * klass) ++{ ++ g_static_rec_mutex_init (&tagsink->streams_lock); ++ tagsink->streams = g_array_new (FALSE, FALSE, sizeof (GstTagSinkStream)); ++ ++ gst_base_sink_set_async_enabled (GST_BASE_SINK (tagsink), TRUE); ++ gst_base_sink_set_sync (GST_BASE_SINK (tagsink), FALSE); ++} ++ ++static void ++gst_tag_sink_dispose (GObject * object) ++{ ++ GstTagSink *tagsink = GST_TAG_SINK (object); ++ ++ if (tagsink->streams != NULL) { ++ if (tagsink->streams->len > 0) { ++ g_warning ("GstTagSink: %u unreleased pads in ::dispose()", ++ tagsink->streams->len); ++ } ++ /* just leak the contents of any unreleased streams (shouldn't happen) */ ++ g_array_free (tagsink->streams, TRUE); ++ tagsink->streams = NULL; ++ } ++ ++ G_OBJECT_CLASS (parent_class)->dispose (object); ++} ++ ++static void ++gst_tag_sink_finalize (GObject * object) ++{ ++ GstTagSink *tagsink = GST_TAG_SINK (object); ++ ++ g_static_rec_mutex_free (&tagsink->streams_lock); ++ ++ if (tagsink->global_tags) { ++ gst_tag_list_free (tagsink->global_tags); ++ tagsink->global_tags = NULL; ++ } ++ G_OBJECT_CLASS (parent_class)->finalize (object); ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static gboolean ++gst_tag_sink_stream_query_duration (GstTagSinkStream * stream) ++{ ++ GstFormat fmt = GST_FORMAT_TIME; ++ gboolean res; ++ gint64 dur = -1; ++ ++ res = gst_pad_query_peer_duration (stream->pad, &fmt, &dur) && (dur > 0); ++ ++ /* this likely indicates a bug in some upstream element */ ++ if (!res && GST_CLOCK_TIME_IS_VALID (stream->duration)) ++ GST_ERROR_OBJECT (stream->pad, "previous duration good, now we got none"); ++ else ++ stream->duration = dur; ++ ++ GST_LOG_OBJECT (stream->pad, "duration: %" GST_TIME_FORMAT, ++ GST_TIME_ARGS (dur)); ++ ++ return res; ++} ++ ++static gboolean ++gst_tag_sink_stream_is_done (GstTagSinkStream * stream) ++{ ++ /* we're definitely done if we've seen an EOS */ ++ if (stream->got_eos) { ++ /* warn if we didn't get anything before the EOS */ ++ if (stream->last_buffer == NULL) ++ GST_WARNING_OBJECT (stream->pad, "EOS without any buffer"); ++ if (!gst_tag_sink_stream_query_duration (stream)) ++ GST_WARNING_OBJECT (stream->pad, "EOS and duration query failed"); ++ return TRUE; ++ } ++ ++ if (stream->last_buffer == NULL) { ++ GST_LOG_OBJECT (stream->pad, "no buffer yet"); ++ return FALSE; ++ } ++ ++ /* bail out after this many buffers */ ++ if (stream->num_buffers >= GST_TAG_SINK_MAX_BUFFERS) { ++ GST_WARNING_OBJECT (stream->pad, "Marking stream as done after %u buffers," ++ " even if we don't have caps and/or duration yet", stream->num_buffers); ++ return TRUE; ++ } ++ ++ if (stream->caps == NULL) { ++ GST_LOG_OBJECT (stream->pad, "got buffer, but no caps!"); ++ return FALSE; ++ } ++ ++ if (!gst_tag_sink_stream_query_duration (stream)) { ++ GST_LOG_OBJECT (stream->pad, "no duration yet"); ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static gboolean ++gst_tag_sink_check_preroll (GstTagSink * tagsink, GstTagSinkStream * stream) ++{ ++ /* have we prerolled already? */ ++ if (!tagsink->async_pending) ++ return TRUE; ++ ++ /* is this stream done? */ ++ if (!gst_tag_sink_stream_is_done (stream)) { ++ GST_LOG_OBJECT (stream->pad, "stream not done yet"); ++ return FALSE; ++ } ++ ++ if (!stream->done) { ++ stream->done = TRUE; ++ --tagsink->num_streams_pending; ++ GST_INFO_OBJECT (stream->pad, "stream is done now, %u more pending", ++ tagsink->num_streams_pending); ++ } ++ ++ if (tagsink->num_streams_pending > 0) { ++ GST_LOG_OBJECT (tagsink, "still %u streams pending", ++ tagsink->num_streams_pending); ++ return FALSE; ++ } ++ ++ GST_INFO_OBJECT (tagsink, "info on all sink pads complete, preroll"); ++ ++ tagsink->async_pending = FALSE; ++ ++ /* just send an EOS event on basesink's sink pad to make us preroll. We ++ * can't use gst_base_sink_do_preroll() because it won't set the internal ++ * EOS flag right, which will make it do a _wait_for_preroll() when going ++ * back from PLAYING to PAUSED. ++ * If you think this is ugly, try deriving from GstElement and implement ++ * async state change behaviour in a correct and race-free way. */ ++ GST_LOG_OBJECT (tagsink, "pushing EOS event on sinkpad to make us preroll"); ++ gst_pad_send_event (GST_BASE_SINK_PAD (tagsink), ++ gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0)); ++ gst_pad_send_event (GST_BASE_SINK_PAD (tagsink), gst_event_new_eos ()); ++ GST_LOG_OBJECT (tagsink, "pushed EOS"); ++ return TRUE; ++} ++ ++/* must be called with the STREAMS_LOCK held */ ++static GstTagSinkStream * ++gst_tag_sink_get_stream_from_pad (GstTagSink * tagsink, GstPad * pad) ++{ ++ gint i; ++ ++ for (i = 0; i < tagsink->streams->len; ++i) { ++ GstTagSinkStream *s; ++ ++ s = &g_array_index (tagsink->streams, GstTagSinkStream, i); ++ if (s->pad == pad) ++ return s; ++ } ++ ++ return NULL; ++} ++ ++static gboolean ++gst_tag_sink_setcaps (GstPad * pad, GstCaps * caps) ++{ ++ GstTagSinkStream *s; ++ GstTagSink *tagsink; ++ ++ tagsink = GST_TAG_SINK (GST_PAD_PARENT (pad)); ++ ++ GST_INFO_OBJECT (pad, "caps: %" GST_PTR_FORMAT, caps); ++ ++ GST_TAG_SINK_STREAMS_LOCK (tagsink); ++ s = gst_tag_sink_get_stream_from_pad (tagsink, pad); ++ gst_caps_replace (&s->caps, caps); ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ ++ return TRUE; ++} ++ ++static gboolean ++gst_tag_sink_sink_event (GstPad * pad, GstEvent * event) ++{ ++ GstTagSink *tagsink; ++ ++ tagsink = GST_TAG_SINK (GST_PAD_PARENT (pad)); ++ ++ GST_LOG_OBJECT (pad, "%s event: %" GST_PTR_FORMAT, ++ GST_EVENT_TYPE_NAME (event), event->structure); ++ ++ GST_TAG_SINK_SHUTDOWN_LOCK (tagsink, shutdown); ++ ++ switch (GST_EVENT_TYPE (event)) { ++ case GST_EVENT_EOS: ++ { ++ GstTagSinkStream *s; ++ ++ s = gst_tag_sink_get_stream_from_pad (tagsink, pad); ++ if (!s->got_eos) { ++ s->got_eos = TRUE; ++ gst_tag_sink_check_preroll (tagsink, s); ++ } ++ break; ++ } ++ case GST_EVENT_TAG: ++ { ++ GstTagSinkStream *s; ++ GstTagList *taglist = NULL; ++ ++ gst_event_parse_tag (event, &taglist); ++ ++ s = gst_tag_sink_get_stream_from_pad (tagsink, pad); ++ taglist = gst_tag_list_copy (taglist); ++ gst_tag_read_utils_list_remove_private_tags (taglist); ++ s->tags = g_list_append (s->tags, taglist); ++ break; ++ } ++ default: ++ break; ++ } ++ ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ return gst_pad_event_default (pad, event); ++ ++shutdown: ++ { ++ GST_DEBUG_OBJECT (tagsink, "shutting down"); ++ return FALSE; ++ } ++} ++ ++static GstFlowReturn ++gst_tag_sink_chain (GstPad * pad, GstBuffer * buf) ++{ ++ GstTagSinkStream *s; ++ GstFlowReturn flow; ++ GstTagSink *tagsink; ++ ++ tagsink = GST_TAG_SINK (GST_PAD_PARENT (pad)); ++ ++ GST_TAG_SINK_SHUTDOWN_LOCK (tagsink, shutdown); ++ ++ s = gst_tag_sink_get_stream_from_pad (tagsink, pad); ++ ++ /* if we're done already, just skip straight to the preroll check */ ++ if (s->done) ++ goto check_preroll; ++ ++ if (s->caps == NULL) ++ GST_ERROR_OBJECT (pad, "received buffer without caps"); ++ ++ ++s->num_buffers; ++ gst_buffer_replace (&s->last_buffer, buf); ++ GST_LOG_OBJECT (pad, "buffer %d", s->num_buffers); ++ ++check_preroll: ++ ++ if (gst_tag_sink_check_preroll (tagsink, s)) { ++ gst_pad_push_event (pad, gst_event_new_flush_start ()); ++ flow = GST_FLOW_WRONG_STATE; ++ } else { ++ flow = GST_FLOW_OK; ++ } ++ ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ ++done: ++ ++ gst_buffer_unref (buf); ++ return flow; ++ ++shutdown: ++ { ++ GST_DEBUG_OBJECT (tagsink, "shutting down"); ++ flow = GST_FLOW_WRONG_STATE; ++ goto done; ++ } ++} ++ ++static GstPad * ++gst_tag_sink_request_pad (GstElement * element, GstPadTemplate * templ, ++ const gchar * unused) ++{ ++ GstTagSinkStream stream = { NULL, }; ++ GstTagSink *tagsink; ++ GstPad *pad; ++ gchar *name; ++ gint padcount; ++ ++ if (templ->direction != GST_PAD_SINK) ++ goto not_sink; ++ ++ tagsink = GST_TAG_SINK (element); ++ ++ /* increment pad counter */ ++ padcount = g_atomic_int_exchange_and_add (&tagsink->padcount, 1); ++ ++ name = g_strdup_printf ("sink%d", padcount); ++ pad = gst_pad_new_from_template (templ, name); ++ GST_DEBUG_OBJECT (tagsink, "request new pad %s, got pad %p", name, pad); ++ g_free (name); ++ ++ gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_setcaps)); ++ gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_sink_event)); ++ gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_chain)); ++ ++ gst_pad_set_active (pad, TRUE); ++ ++ stream.pad = gst_object_ref (pad); ++ stream.duration = GST_CLOCK_TIME_NONE; ++ stream.done = FALSE; ++ ++ /* takes ownership of the pad */ ++ if (!gst_element_add_pad (element, pad)) ++ goto could_not_add; ++ ++ GST_TAG_SINK_STREAMS_LOCK (tagsink); ++ ++tagsink->num_streams_pending; ++ g_array_append_vals (tagsink->streams, &stream, 1); ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ ++ GST_INFO_OBJECT (stream.pad, "added pad"); ++ return stream.pad; ++ ++ /* ERRORS */ ++not_sink: ++ { ++ g_warning ("GstTagSink: requested new pad that is not a SINK pad!"); ++ return NULL; ++ } ++could_not_add: ++ { ++ GST_DEBUG_OBJECT (element, "could not add pad %s", GST_PAD_NAME (pad)); ++ gst_object_unref (pad); ++ return NULL; ++ } ++} ++ ++static void ++gst_tag_sink_release_pad (GstElement * element, GstPad * pad) ++{ ++ GstTagSinkStream stream = { NULL, }; ++ GstTagSink *tagsink; ++ gint i; ++ ++ tagsink = GST_TAG_SINK (element); ++ GST_DEBUG_OBJECT (tagsink, "release pad %s", GST_PAD_NAME (pad)); ++ ++ GST_TAG_SINK_STREAMS_LOCK (tagsink); ++ for (i = 0; i < tagsink->streams->len; ++i) { ++ GstTagSinkStream *s; ++ ++ s = &g_array_index (tagsink->streams, GstTagSinkStream, i); ++ if (s->pad == pad) { ++ stream = *s; ++ g_array_remove_index (tagsink->streams, i); ++ break; ++ } ++ } ++ ++ if (stream.pad != NULL && !stream.done) ++ --tagsink->num_streams_pending; ++ ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ ++ if (stream.pad == NULL) { ++ GST_ERROR_OBJECT (tagsink, "pad %s:%s to release not found in pad list!", ++ GST_DEBUG_PAD_NAME (pad)); ++ } else { ++ GST_INFO_OBJECT (stream.pad, "releasing pad"); ++ gst_caps_replace (&stream.caps, NULL); ++ g_list_foreach (stream.tags, (GFunc) gst_tag_list_free, NULL); ++ g_list_free (stream.tags); ++ stream.tags = NULL; ++ if (stream.stream_tags) { ++ gst_tag_list_free (stream.stream_tags); ++ stream.stream_tags = NULL; ++ } ++ gst_pad_set_active (stream.pad, FALSE); ++ gst_element_remove_pad (element, stream.pad); ++ gst_object_unref (stream.pad); ++ stream.pad = NULL; ++ gst_buffer_replace (&stream.last_buffer, NULL); ++ GST_INFO_OBJECT (tagsink, "released pad"); ++ } ++} ++ ++static gboolean ++gst_tag_sink_start (GstBaseSink * basesink) ++{ ++ GstTagSink *tagsink = GST_TAG_SINK (basesink); ++ ++ GST_LOG ("here we go"); ++ tagsink->async_pending = TRUE; ++ tagsink->num_streams_pending = 0; ++ return TRUE; ++} ++ ++static gboolean ++gst_tag_sink_unlock (GstBaseSink * basesink) ++{ ++ GstTagSink *tagsink = GST_TAG_SINK (basesink); ++ ++ GST_LOG_OBJECT (tagsink, "setting shutdown flag"); ++ g_atomic_int_set (&tagsink->shutdown, 1); ++ return TRUE; ++} ++ ++static gboolean ++gst_tag_sink_stop (GstBaseSink * basesink) ++{ ++ GstTagSink *tagsink = GST_TAG_SINK (basesink); ++ ++ g_atomic_int_set (&tagsink->shutdown, 1); ++ /* wait for all pad callbacks to end by taking the lock. ++ * No dynamic (critical) new callbacks will ++ * be able to happen as we set the shutdown flag. */ ++ GST_LOG_OBJECT (tagsink, "trying to acquire streams lock"); ++ GST_TAG_SINK_STREAMS_LOCK (tagsink); ++ GST_LOG_OBJECT (tagsink, "streams lock taken, we can continue shutdown"); ++ GST_TAG_SINK_STREAMS_UNLOCK (tagsink); ++ return TRUE; ++} ++ ++/* methods used by tagreadbin */ ++ ++/* FIXME: make API in core to test structures/taglists for equality public */ ++static gboolean ++tag_lists_are_equal (GstTagList * tags1, GstTagList * tags2) ++{ ++ GstCaps *caps1, *caps2; ++ gboolean res; ++ ++ /* not very efficient, but simple .. */ ++ caps1 = gst_caps_new_full (gst_structure_copy (tags1), NULL); ++ caps2 = gst_caps_new_full (gst_structure_copy (tags2), NULL); ++ res = gst_caps_is_equal (caps1, caps2); ++ gst_caps_unref (caps1); ++ gst_caps_unref (caps2); ++ return res; ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static GList * ++gst_tag_sink_stream_find_tags (GstTagSinkStream * stream, GstTagList * tags) ++{ ++ GList *l; ++ ++ for (l = stream->tags; l != NULL; l = l->next) { ++ if (tag_lists_are_equal (l->data, tags)) ++ return l; ++ } ++ ++ return NULL; ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static void ++gst_tag_sink_remove_tags_from_all_streams (GstTagSink * tsink, ++ GstTagList * global_tags) ++{ ++ GstTagList *copy; ++ guint i; ++ ++ copy = gst_tag_list_copy (global_tags); ++ for (i = 0; i < tsink->streams->len; ++i) { ++ GstTagSinkStream *stream; ++ GList *node; ++ ++ stream = &g_array_index (tsink->streams, GstTagSinkStream, i); ++ if ((node = gst_tag_sink_stream_find_tags (stream, copy))) { ++ gst_tag_list_free (node->data); ++ stream->tags = g_list_delete_link (stream->tags, node); ++ } ++ } ++ gst_tag_list_free (copy); ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static gboolean ++gst_tag_sink_stream_has_tags (GstTagSinkStream * stream, GstTagList * tags) ++{ ++ return (gst_tag_sink_stream_find_tags (stream, tags) != NULL); ++} ++ ++/* must be called with STREAMS_LOCK held */ ++static gboolean ++gst_tag_sink_tags_are_global (GstTagSink * tsink, GstTagList * tags) ++{ ++ gboolean res = TRUE; ++ guint i; ++ ++ /* Are the given tags common to all streams? */ ++ for (i = 0; i < tsink->streams->len; ++i) { ++ GstTagSinkStream *stream; ++ ++ stream = &g_array_index (tsink->streams, GstTagSinkStream, i); ++ if (!gst_tag_sink_stream_has_tags (stream, tags)) { ++ res = FALSE; ++ break; ++ } ++ } ++ ++ GST_LOG_OBJECT (tsink, "tags %" GST_PTR_FORMAT " are %s", tags, ++ (res) ? "global" : "not global"); ++ ++ return res; ++} ++ ++/* Try to determine 'global tags' common to all streams. Must be called with ++ * STREAMS_LOCK held. */ ++static void ++gst_tag_sink_find_global_tags (GstTagSink * tsink) ++{ ++ GList *l, *global_lists = NULL; ++ GstClockTime max_dur = 0; ++ guint i; ++ ++ if (tsink->global_tags != NULL) ++ return; ++ ++start: ++ ++ /* Find all tags that are common to all streams */ ++ for (i = 0; i < tsink->streams->len; ++i) { ++ GstTagSinkStream *stream; ++ ++ stream = &g_array_index (tsink->streams, GstTagSinkStream, i); ++ for (l = stream->tags; l != NULL; l = l->next) { ++ GstTagList *tags = l->data; ++ ++ /* only tags received before a taglist with a *_CODEC tag are global */ ++ if (gst_tag_read_utils_list_has_codec_tag (tags)) ++ break; ++ ++ if (gst_tag_sink_tags_are_global (tsink, tags)) { ++ GST_DEBUG_OBJECT (tsink, "global tags: %" GST_PTR_FORMAT, tags); ++ global_lists = g_list_prepend (global_lists, gst_tag_list_copy (tags)); ++ gst_tag_sink_remove_tags_from_all_streams (tsink, tags); ++ goto start; ++ } ++ } ++ } ++ ++ global_lists = g_list_reverse (global_lists); ++ ++ if (global_lists == NULL) ++ goto no_global_tags; ++ ++ /* merge all global tags into one tag list */ ++ tsink->global_tags = gst_tag_list_new (); ++ while ((l = global_lists)) { ++ gst_tag_list_insert (tsink->global_tags, l->data, GST_TAG_MERGE_APPEND); ++ gst_tag_list_free (l->data); ++ global_lists = g_list_delete_link (global_lists, l); ++ } ++ ++done: ++ ++ /* Find biggest duration of all streams */ ++ max_dur = 0; ++ for (i = 0; i < tsink->streams->len; ++i) { ++ GstTagSinkStream *stream; ++ ++ stream = &g_array_index (tsink->streams, GstTagSinkStream, i); ++ if (GST_CLOCK_TIME_IS_VALID (stream->duration)) ++ max_dur = MAX (stream->duration, max_dur); ++ } ++ ++ gst_tag_read_utils_list_add_duration (tsink->global_tags, max_dur); ++ ++ GST_INFO_OBJECT (tsink, "global tags: %" GST_PTR_FORMAT, tsink->global_tags); ++ return; ++ ++no_global_tags: ++ { ++ GST_LOG_OBJECT (tsink, "couldn't find any global tags"); ++ tsink->global_tags = gst_tag_list_new (); ++ goto done; ++ } ++ ++} ++ ++GstTagList * ++gst_tag_sink_get_global_tags (GstTagSink * tsink) ++{ ++ GstTagList *ret = NULL; ++ ++ GST_TAG_SINK_STREAMS_LOCK (tsink); ++ ++ gst_tag_sink_find_global_tags (tsink); ++ ++ if (tsink->global_tags != NULL) { ++ ret = gst_tag_list_copy (tsink->global_tags); ++ } else { ++ ret = gst_tag_list_new (); ++ } ++ ++ GST_TAG_SINK_STREAMS_UNLOCK (tsink); ++ ++ return ret; ++} ++ ++/* Postprocess stream tags. Must be called with the STREAMS_LOCK held */ ++static void ++gst_tag_sink_stream_analyse_tags (GstTagSink * tsink, GstTagSinkStream * stream) ++{ ++ GList *l; ++ ++ /* have we done all of this before? */ ++ if (stream->stream_tags != NULL) ++ return; ++ ++ /* remove global tags first if we haven't done that yet */ ++ gst_tag_sink_find_global_tags (tsink); ++ ++ /* merge all remaining tags into one tag list */ ++ stream->stream_tags = gst_tag_list_new (); ++ while ((l = stream->tags)) { ++ gst_tag_list_insert (stream->stream_tags, l->data, GST_TAG_MERGE_APPEND); ++ gst_tag_list_free (l->data); ++ stream->tags = g_list_delete_link (stream->tags, l); ++ } ++ ++ /* if we don't have a codec tag for this stream, add one based on the caps */ ++ if (!gst_tag_read_utils_list_has_codec_tag (stream->stream_tags)) { ++ gst_tag_read_utils_add_codec_tag_from_caps (stream->stream_tags, ++ stream->caps); ++ } ++ ++ /* merge interesting stuff from tags into the tags */ ++ gst_tag_read_utils_list_add_caps_info (stream->stream_tags, stream->caps); ++ ++ /* merge duration into the tags */ ++ gst_tag_read_utils_list_add_duration (stream->stream_tags, stream->duration); ++ ++ GST_INFO_OBJECT (tsink, "stream tags: %" GST_PTR_FORMAT, stream->stream_tags); ++} ++ ++/* will return an empty tag list for 'no tags' and NULL if no such stream ++ * (although there should always be at least a codec tag based on the caps) */ ++GstTagList * ++gst_tag_sink_get_stream_tags (GstTagSink * tsink, guint num) ++{ ++ GstTagSinkStream *stream; ++ GstTagList *ret; ++ ++ GST_TAG_SINK_STREAMS_LOCK (tsink); ++ ++ if (num >= tsink->streams->len) { ++ ret = NULL; ++ goto out; ++ } ++ ++ stream = &g_array_index (tsink->streams, GstTagSinkStream, num); ++ ++ if (stream->stream_tags != NULL) { ++ ret = gst_tag_list_copy (stream->stream_tags); ++ goto out; ++ } ++ ++ gst_tag_sink_stream_analyse_tags (tsink, stream); ++ ++ if (stream->stream_tags != NULL) { ++ ret = gst_tag_list_copy (stream->stream_tags); ++ } else { ++ ret = gst_tag_list_new (); ++ GST_LOG_OBJECT (tsink, "no stream tags for stream %u", num); ++ } ++ ++out: ++ ++ GST_TAG_SINK_STREAMS_UNLOCK (tsink); ++ ++ return ret; ++} +diff --git a/gst/tagreading/gsttagsink.h b/gst/tagreading/gsttagsink.h +new file mode 100644 +index 0000000..adf5ff3 +--- /dev/null ++++ b/gst/tagreading/gsttagsink.h +@@ -0,0 +1,103 @@ ++/* GStreamer tag read bin sink ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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_TAG_SINK_H__ ++#define __GST_TAG_SINK_H__ ++ ++#include ++#include ++ ++G_BEGIN_DECLS ++ ++#define GST_TYPE_TAG_SINK (gst_tag_sink_get_type()) ++#define GST_TAG_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_SINK,GstTagSink)) ++#define GST_TAG_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_SINK,GstTagSinkClass)) ++#define GST_IS_TAG_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_SINK)) ++#define GST_IS_TAG_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_SINK)) ++ ++#define GST_TAG_SINK_STREAMS_LOCK(tsink) g_static_rec_mutex_lock (&tsink->streams_lock) ++#define GST_TAG_SINK_STREAMS_UNLOCK(tsink) g_static_rec_mutex_unlock (&tsink->streams_lock) ++ ++/* lock for shutdown */ ++#define GST_TAG_SINK_SHUTDOWN_LOCK(tsink,label) \ ++G_STMT_START { \ ++ if (G_UNLIKELY (g_atomic_int_get (&tsink->shutdown))) \ ++ goto label; \ ++ GST_TAG_SINK_STREAMS_LOCK (tsink); \ ++ if (G_UNLIKELY (g_atomic_int_get (&tsink->shutdown))) { \ ++ GST_TAG_SINK_STREAMS_UNLOCK (tsink); \ ++ goto label; \ ++ } \ ++} G_STMT_END ++ ++/* unlock for shutdown */ ++#define GST_TAG_SINK_SHUTDOWN_UNLOCK(tsink) \ ++ GST_TAG_SINK_STREAMS_UNLOCK (tsink); \ ++ ++typedef struct _GstTagSink GstTagSink; ++typedef struct _GstTagSinkClass GstTagSinkClass; ++ ++typedef struct { ++ GstPad *pad; ++ GstCaps *caps; ++ GList *tags; /* tags received through events, sorted */ ++ GstBuffer *last_buffer; ++ guint num_buffers; ++ gboolean got_eos; ++ GstTagList *stream_tags; /* merged (non-global) tags */ ++ GstClockTime duration; /* duration, or GST_CLOCK_TIME_NONE */ ++ gboolean done; /* got all the info we need */ ++} GstTagSinkStream; ++ ++struct _GstTagSink ++{ ++ GstBaseSink basesink; ++ ++ /*< private >*/ ++ gint padcount; /* ATOMIC */ ++ ++ /* if we are shutting down or not */ ++ gint shutdown; /* ATOMIC */ ++ ++ gboolean async_pending; /* STREAMS_LOCK */ ++ ++ /* number of streams for which we don't have all the info we want yet */ ++ guint num_streams_pending; /* STREAMS_LOCK */ ++ ++ GStaticRecMutex streams_lock; ++ GArray *streams; /* STREAMS_LOCK */ ++ ++ GstTagList *global_tags; /* STREAMS_LOCK */ ++}; ++ ++struct _GstTagSinkClass ++{ ++ GstBaseSinkClass basesink_class; ++}; ++ ++GType gst_tag_sink_get_type (void); ++ ++GstTagList * gst_tag_sink_get_global_tags (GstTagSink * sink); ++ ++GstTagList * gst_tag_sink_get_stream_tags (GstTagSink * sink, guint num); ++ ++ ++G_END_DECLS ++ ++#endif /* __GST_TAG_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0004-tagreading-add-gst-tagread-test-app-to-examples.patch b/gst-plugins-base-subtitles0.10/debian/patches/0004-tagreading-add-gst-tagread-test-app-to-examples.patch new file mode 100644 index 0000000..20bca78 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0004-tagreading-add-gst-tagread-test-app-to-examples.patch @@ -0,0 +1,357 @@ +From aa8dd50e9c9c37476a803cd5dc530786dd2a4104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Sat, 23 May 2009 00:45:33 +0100 +Subject: [PATCH] tagreading: add gst-tagread test app to examples + +Uses tagreadbin to extract tags from the given files/directories and +prints them out. See #564749. +--- + .gitignore | 1 + + configure.ac | 1 + + tests/examples/Makefile.am | 2 +- + tests/examples/tagreading/Makefile.am | 6 + + tests/examples/tagreading/gst-tagread.c | 285 +++++++++++++++++++++++++++++++ + 5 files changed, 294 insertions(+), 1 deletions(-) + create mode 100644 tests/examples/tagreading/Makefile.am + create mode 100644 tests/examples/tagreading/gst-tagread.c + +diff --git a/.gitignore b/.gitignore +index 005392e..b8398ca 100644 +--- a/.gitignore ++++ b/.gitignore +@@ -27,6 +27,7 @@ depcomp + autoregen.sh + ABOUT-NLS + _stdint.h ++tests/examples/tagreading/gst-tagread + + gst-plugins-base-*.tar* + +diff --git a/configure.ac b/configure.ac +index 7a6ae5a..4de8751 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1015,6 +1015,7 @@ tests/examples/snapshot/Makefile + tests/examples/playrec/Makefile + tests/examples/volume/Makefile + tests/examples/v4l/Makefile ++tests/examples/tagreading/Makefile + tests/files/Makefile + tests/icles/Makefile + tests/icles/playback/Makefile +diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am +index 48c38a5..87d6e15 100644 +--- a/tests/examples/Makefile.am ++++ b/tests/examples/Makefile.am +@@ -8,7 +8,7 @@ if USE_GIO + GIO_SUBDIRS = gio + endif + +-SUBDIRS = app dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume v4l encoding ++SUBDIRS = app dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume v4l encoding tagreading + + DIST_SUBDIRS = app dynamic gio overlay seek snapshot playrec volume v4l encoding + +diff --git a/tests/examples/tagreading/Makefile.am b/tests/examples/tagreading/Makefile.am +new file mode 100644 +index 0000000..2d34c54 +--- /dev/null ++++ b/tests/examples/tagreading/Makefile.am +@@ -0,0 +1,6 @@ ++noinst_PROGRAMS = gst-tagread ++ ++gst_tagread_SOURCES = gst-tagread.c ++gst_tagread_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) ++gst_tagread_LDFLAGS = $(GST_LIBS) ++ +diff --git a/tests/examples/tagreading/gst-tagread.c b/tests/examples/tagreading/gst-tagread.c +new file mode 100644 +index 0000000..4576b5f +--- /dev/null ++++ b/tests/examples/tagreading/gst-tagread.c +@@ -0,0 +1,285 @@ ++/* GStreamer Command-Line Tag Reading Example ++ * Copyright (C) 2009 Tim-Philipp Müller ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Library General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Library General Public License for more details. ++ * ++ * You should have received a copy of the GNU Library General Public ++ * 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 ++#include ++ ++static gboolean print_version = FALSE; ++ ++static GstElement *tagreadbin = NULL; ++ ++static void ++print_tag (const GstTagList * list, const gchar * tag, gpointer unused) ++{ ++ gint i, count; ++ ++ count = gst_tag_list_get_tag_size (list, tag); ++ ++ for (i = 0; i < count; i++) { ++ gchar *str; ++ ++ if (gst_tag_get_type (tag) == G_TYPE_STRING) { ++ if (!gst_tag_list_get_string_index (list, tag, i, &str)) ++ g_assert_not_reached (); ++ } else if (gst_tag_get_type (tag) == GST_TYPE_BUFFER) { ++ GstBuffer *img; ++ ++ img = gst_value_get_buffer (gst_tag_list_get_value_index (list, tag, i)); ++ if (img) { ++ gchar *caps_str; ++ ++ caps_str = GST_BUFFER_CAPS (img) ? ++ gst_caps_to_string (GST_BUFFER_CAPS (img)) : g_strdup ("unknown"); ++ str = g_strdup_printf ("buffer of %u bytes, type: %s", ++ GST_BUFFER_SIZE (img), caps_str); ++ g_free (caps_str); ++ } else { ++ str = g_strdup ("NULL buffer"); ++ } ++ } else { ++ str = ++ g_strdup_value_contents (gst_tag_list_get_value_index (list, tag, i)); ++ } ++ ++ if (i == 0) { ++ g_print ("%25s: %s\n", gst_tag_get_nick (tag), str); ++ } else { ++ g_print ("%25s: %s\n", "", str); ++ } ++ ++ g_free (str); ++ } ++} ++ ++static GList * ++extract_tags (const gchar * uri) ++{ ++ GstStateChangeReturn ret; ++ gboolean got_error = FALSE; ++ gboolean got_eos = FALSE; ++ GList *list = NULL; ++ ++ g_print ("\n\nURI: %s\n", uri); ++ ++ if (tagreadbin == NULL) { ++ tagreadbin = gst_element_factory_make ("tagreadbin", NULL); ++ if (tagreadbin == NULL) ++ g_error ("Could not create 'tagreadbin' element, check your setup!"); ++ } ++ ++ g_object_set (tagreadbin, "uri", uri, NULL); ++ ++ /* this might fail, but if it does there'll be an error message on the bus */ ++ ret = gst_element_set_state (tagreadbin, GST_STATE_PLAYING); ++ do { ++ GstMessage *msg; ++ ++ msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (tagreadbin), ++ 5 * GST_SECOND, GST_MESSAGE_TAG | GST_MESSAGE_ERROR | GST_MESSAGE_EOS); ++ ++ /* no message for 5 seconds? - bad */ ++ if (msg == NULL) { ++ if (ret == GST_STATE_CHANGE_FAILURE) { ++ g_warning ("tagreadbin state change failed, but did not get an error " ++ "message! (uri: %s)", uri); ++ } else { ++ g_warning ("No tags or EOS for more than 5 seconds, bailing out! " ++ "(uri: %s)", uri); ++ } ++ break; ++ } ++ ++ switch (GST_MESSAGE_TYPE (msg)) { ++ case GST_MESSAGE_TAG:{ ++ GstTagList *tags = NULL; ++ ++ gst_message_parse_tag (msg, &tags); ++ GST_LOG ("TAG: %" GST_PTR_FORMAT, tags); ++ list = g_list_append (list, tags); ++ break; ++ } ++ case GST_MESSAGE_EOS: ++ GST_LOG ("EOS"); ++ got_eos = TRUE; ++ break; ++ case GST_MESSAGE_ERROR:{ ++ GError *err = NULL; ++ gchar *dbg = NULL; ++ ++ gst_message_parse_error (msg, &err, &dbg); ++ if (err) { ++ g_warning ("Failed to read tags from %s:\nError: %s\nDebug: %s\n", ++ uri, err->message, (dbg) ? dbg : "(No debug details)"); ++ g_error_free (err); ++ g_free (dbg); ++ got_error = TRUE; ++ } ++ break; ++ } ++ default: ++ g_assert_not_reached (); ++ break; ++ } ++ gst_message_unref (msg); ++ } ++ while (!(got_error || got_eos)); ++ ++ /* In case we got here after a timeout, some applications may prefer to not ++ * set the state to NULL here and instead throw away (and leak) the ++ * tagreadbin instance and continue with a new one, in case the reason for ++ * the timeout was that the streaming thread deadlocked due to a buggy ++ * element, in which case _set_state() is likely to deadlock too). */ ++ gst_element_set_state (tagreadbin, GST_STATE_NULL); ++ ++ /* FIXME: should be able to re-use */ ++ gst_object_unref (tagreadbin); ++ tagreadbin = NULL; ++ ++ if (got_error) { ++ g_list_foreach (list, (GFunc) gst_tag_list_free, NULL); ++ g_list_free (list); ++ list = NULL; ++ } ++ ++ return list; ++} ++ ++static void ++process_file (const gchar * filename) ++{ ++ GError *err = NULL; ++ GList *tags; ++ GDir *dir; ++ gchar *uri, *path; ++ guint i; ++ ++ /* Recurse into directories */ ++ if ((dir = g_dir_open (filename, 0, NULL))) { ++ const gchar *entry; ++ ++ while ((entry = g_dir_read_name (dir))) { ++ gchar *path; ++ ++ path = g_strconcat (filename, G_DIR_SEPARATOR_S, entry, NULL); ++ process_file (path); ++ g_free (path); ++ } ++ ++ g_dir_close (dir); ++ return; ++ } ++ ++ if (!g_path_is_absolute (filename)) { ++ gchar *cur_dir; ++ ++ cur_dir = g_get_current_dir (); ++ path = g_build_filename (cur_dir, filename, NULL); ++ g_free (cur_dir); ++ } else { ++ path = g_strdup (filename); ++ } ++ ++ uri = g_filename_to_uri (path, NULL, &err); ++ g_free (path); ++ path = NULL; ++ ++ if (err) { ++ g_warning ("Couldn't convert filename to URI: %s\n", err->message); ++ g_error_free (err); ++ return; ++ } ++ ++ /* now get the tags */ ++ tags = extract_tags (uri); ++ ++ /* .. and print them */ ++ i = 0; ++ while (tags != NULL) { ++ GstTagList *taglist = tags->data; ++ ++ if (i == 0) ++ g_print ("\nCONTAINER TAGS:\n"); ++ else ++ g_print ("\nSTREAM #%u TAGS:\n", i); ++ ++ gst_tag_list_foreach (taglist, print_tag, NULL); ++ gst_tag_list_free (taglist); ++ tags = g_list_delete_link (tags, tags); ++ ++i; ++ } ++ ++ g_free (uri); ++} ++ ++int ++main (int argc, char **argv) ++{ ++ gchar **filenames = NULL; ++ guint num, i; ++ GError *err = NULL; ++ GOptionContext *ctx; ++ GOptionEntry options[] = { ++ {"version", 0, 0, G_OPTION_ARG_NONE, &print_version, ++ N_("Print version information and exit"), NULL}, ++ {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}, ++ {NULL} ++ }; ++ ++#ifdef ENABLE_NLS ++ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); ++ bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); ++ textdomain (GETTEXT_PACKAGE); ++#endif ++ ++ if (!g_thread_supported ()) ++ g_thread_init (NULL); ++ ++ ctx = g_option_context_new ("FILES"); ++ g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); ++ g_option_context_add_group (ctx, gst_init_get_option_group ()); ++ if (!g_option_context_parse (ctx, &argc, &argv, &err)) { ++ g_print ("Error initializing: %s\n", GST_STR_NULL (err->message)); ++ exit (1); ++ } ++ g_option_context_free (ctx); ++ ++ if (print_version) { ++ g_print ("gst-tagread version " VERSION "\n"); ++ exit (0); ++ } ++ ++ if (filenames == NULL || *filenames == NULL) { ++ g_print ("Please pass one or more filenames to gst-tagread\n\n"); ++ return 1; ++ } ++ ++ num = g_strv_length (filenames); ++ ++ for (i = 0; i < num; ++i) { ++ process_file (filenames[i]); ++ } ++ ++ g_strfreev (filenames); ++ ++ return 0; ++} diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0005-tagreadbin-don-t-try-to-guess-codec-tag-from-NULL-ca.patch b/gst-plugins-base-subtitles0.10/debian/patches/0005-tagreadbin-don-t-try-to-guess-codec-tag-from-NULL-ca.patch new file mode 100644 index 0000000..c847c19 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0005-tagreadbin-don-t-try-to-guess-codec-tag-from-NULL-ca.patch @@ -0,0 +1,25 @@ +From 09628395d26c18dab61914d190821622e6555929 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Tue, 1 Sep 2009 15:29:24 +0100 +Subject: [PATCH] tagreadbin: don't try to guess codec tag from NULL caps in + the tagsink + +Fixes crash when the caps are NULL for some reason (NB #135291). +--- + gst/tagreading/gsttagsink.c | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/gst/tagreading/gsttagsink.c b/gst/tagreading/gsttagsink.c +index 3741897..6de9626 100644 +--- a/gst/tagreading/gsttagsink.c ++++ b/gst/tagreading/gsttagsink.c +@@ -732,7 +732,8 @@ gst_tag_sink_stream_analyse_tags (GstTagSink * tsink, GstTagSinkStream * stream) + } + + /* if we don't have a codec tag for this stream, add one based on the caps */ +- if (!gst_tag_read_utils_list_has_codec_tag (stream->stream_tags)) { ++ if (stream->caps != NULL && ++ !gst_tag_read_utils_list_has_codec_tag (stream->stream_tags)) { + gst_tag_read_utils_add_codec_tag_from_caps (stream->stream_tags, + stream->caps); + } diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0006-gst-tagread-add-loop-N-command-line-option-to-tagrea.patch b/gst-plugins-base-subtitles0.10/debian/patches/0006-gst-tagread-add-loop-N-command-line-option-to-tagrea.patch new file mode 100644 index 0000000..c98645c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0006-gst-tagread-add-loop-N-command-line-option-to-tagrea.patch @@ -0,0 +1,64 @@ +From 9cf1100a4a5f227c372d493bc3ae176401da5af6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Tue, 29 Sep 2009 12:33:39 +0100 +Subject: [PATCH] gst-tagread: add --loop=N command line option to tagreading + example + +This is useful for testing and benchmarking purposes. +--- + tests/examples/tagreading/gst-tagread.c | 14 +++++++++++++- + 1 files changed, 13 insertions(+), 1 deletions(-) + +diff --git a/tests/examples/tagreading/gst-tagread.c b/tests/examples/tagreading/gst-tagread.c +index 4576b5f..0f94ce9 100644 +--- a/tests/examples/tagreading/gst-tagread.c ++++ b/tests/examples/tagreading/gst-tagread.c +@@ -25,6 +25,7 @@ + #include + + static gboolean print_version = FALSE; ++static gint loop_iterations = 1; + + static GstElement *tagreadbin = NULL; + +@@ -171,7 +172,7 @@ process_file (const gchar * filename) + GList *tags; + GDir *dir; + gchar *uri, *path; +- guint i; ++ guint i, loop; + + /* Recurse into directories */ + if ((dir = g_dir_open (filename, 0, NULL))) { +@@ -209,6 +210,10 @@ process_file (const gchar * filename) + return; + } + ++ loop = loop_iterations; ++ ++again: ++ + /* now get the tags */ + tags = extract_tags (uri); + +@@ -228,6 +233,11 @@ process_file (const gchar * filename) + ++i; + } + ++ if (loop > 1) { ++ --loop; ++ goto again; ++ } ++ + g_free (uri); + } + +@@ -241,6 +251,8 @@ main (int argc, char **argv) + GOptionEntry options[] = { + {"version", 0, 0, G_OPTION_ARG_NONE, &print_version, + N_("Print version information and exit"), NULL}, ++ {"loop", 'l', 0, G_OPTION_ARG_INT, &loop_iterations, ++ N_("Print version information and exit"), NULL}, + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}, + {NULL} + }; diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0007-tagreadbin-avoid-deadlock-on-state-change-PAUSED_TO_.patch b/gst-plugins-base-subtitles0.10/debian/patches/0007-tagreadbin-avoid-deadlock-on-state-change-PAUSED_TO_.patch new file mode 100644 index 0000000..0f736d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0007-tagreadbin-avoid-deadlock-on-state-change-PAUSED_TO_.patch @@ -0,0 +1,51 @@ +From ad8d21103f48f265f206abaabd3075fd33d619be Mon Sep 17 00:00:00 2001 +From: Mark Nauwelaerts +Date: Thu, 14 Jan 2010 12:04:20 +0100 +Subject: [PATCH] tagreadbin: avoid deadlock on state change PAUSED_TO_READY + +--- + gst/tagreading/gsttagsink.c | 24 ++++++++++++++++++++++++ + 1 files changed, 24 insertions(+), 0 deletions(-) + +diff --git a/gst/tagreading/gsttagsink.c b/gst/tagreading/gsttagsink.c +index 6de9626..d6c4ba4 100644 +--- a/gst/tagreading/gsttagsink.c ++++ b/gst/tagreading/gsttagsink.c +@@ -386,6 +386,28 @@ shutdown: + } + } + ++static gboolean ++gst_tag_sink_activate_push (GstPad * pad, gboolean active) ++{ ++ gboolean result = TRUE; ++ GstTagSink *tagsink; ++ ++ tagsink = (GstTagSink *) (GST_PAD_PARENT (pad)); ++ ++ /* a request pad's thread may be held locked in basesink sink pad ++ * in wait_preroll (if things went really quick PAUSED -> PLAYING -> PAUSED). ++ * State change to READY may (likely) select request pad for deactivation ++ * first, so we need to unlock the streaming thread */ ++ if (tagsink && !active) { ++ GST_DEBUG_OBJECT (tagsink, "flushing basesink sinkpad"); ++ gst_pad_send_event (GST_BASE_SINK_PAD (tagsink), ++ gst_event_new_flush_start ()); ++ } ++ ++ return result; ++} ++ ++ + static GstPad * + gst_tag_sink_request_pad (GstElement * element, GstPadTemplate * templ, + const gchar * unused) +@@ -412,6 +434,8 @@ gst_tag_sink_request_pad (GstElement * element, GstPadTemplate * templ, + gst_pad_set_setcaps_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_setcaps)); + gst_pad_set_event_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_sink_event)); + gst_pad_set_chain_function (pad, GST_DEBUG_FUNCPTR (gst_tag_sink_chain)); ++ gst_pad_set_activatepush_function (pad, ++ GST_DEBUG_FUNCPTR (gst_tag_sink_activate_push)); + + gst_pad_set_active (pad, TRUE); + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0008-Fix-rounding-of-source-width-in-gstvideosink.c.patch b/gst-plugins-base-subtitles0.10/debian/patches/0008-Fix-rounding-of-source-width-in-gstvideosink.c.patch new file mode 100644 index 0000000..276a8c4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0008-Fix-rounding-of-source-width-in-gstvideosink.c.patch @@ -0,0 +1,24 @@ +From 3b4e8237dcc2bc3a5f202aff10a838382c858288 Mon Sep 17 00:00:00 2001 +From: Maemo Multimedia +Date: Thu, 16 Oct 2008 09:27:44 +0300 +Subject: [PATCH] Fix rounding of source width in gstvideosink.c. + +--- + gst-libs/gst/video/Makefile.am | 4 ++-- + 1 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am +index 21ce6e4..92c81e6 100644 +--- a/gst-libs/gst/video/Makefile.am ++++ b/gst-libs/gst/video/Makefile.am +@@ -21,8 +21,8 @@ libgstvideo_@GST_MAJORMINOR@include_HEADERS = \ + video.h gstvideosink.h gstvideofilter.h + nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS = $(built_headers) + +-libgstvideo_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +-libgstvideo_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) ++libgstvideo_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) -std=c99 ++libgstvideo_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) -lm + libgstvideo_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + + include $(top_srcdir)/common/gst-glib-gen.mak diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0009-typefind-optimize-MP3-and-MPEG_SYS-typefinding.patch b/gst-plugins-base-subtitles0.10/debian/patches/0009-typefind-optimize-MP3-and-MPEG_SYS-typefinding.patch new file mode 100644 index 0000000..5d78171 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0009-typefind-optimize-MP3-and-MPEG_SYS-typefinding.patch @@ -0,0 +1,100 @@ +From 68507fbfe3c266c51f4b674b8b635a7b63ee7e60 Mon Sep 17 00:00:00 2001 +From: Maemo Multimedia +Date: Thu, 22 Jan 2009 08:57:50 +0200 +Subject: [PATCH] typefind: optimize MP3 and MPEG_SYS typefinding + +--- + gst/typefind/gsttypefindfunctions.c | 32 ++++++++++++++++++++++++++------ + 1 files changed, 26 insertions(+), 6 deletions(-) + +diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c +index 98dbade..2a3a733 100644 +--- a/gst/typefind/gsttypefindfunctions.c ++++ b/gst/typefind/gsttypefindfunctions.c +@@ -826,6 +826,18 @@ aac_type_find (GstTypeFind * tf, gpointer unused) + "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "adif", NULL); + break; ++ ++ GST_DEBUG ("No next frame found... (should have been at 0x%x)", len); ++ } else if (!memcmp (c.data, "ADIF", 4)) { ++ /* ADIF header */ ++ GstCaps *caps = gst_caps_new_simple ("audio/mpeg", ++ "framed", G_TYPE_BOOLEAN, FALSE, ++ "mpegversion", G_TYPE_INT, 4, ++ NULL); ++ ++ gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps); ++ gst_caps_unref (caps); ++ break; + } + + next: +@@ -987,7 +999,7 @@ mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off, + { + guint8 *data = NULL; + guint8 *data_end = NULL; +- guint size; ++ guint size, oldsize = 0; + guint64 skipped; + gint last_free_offset = -1; + gint last_free_framelen = -1; +@@ -1000,13 +1012,14 @@ mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off, + skipped = 0; + while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) { + if (size <= 0) { +- size = GST_MP3_TYPEFIND_SYNC_SIZE * 2; ++ size = oldsize ? oldsize : GST_MP3_TYPEFIND_SYNC_SIZE * 2; + do { + size /= 2; + data = gst_type_find_peek (tf, skipped + start_off, size); + } while (size > 10 && !data); + if (!data) + break; ++ oldsize = size; + data_end = data + size; + } + if (*data == 0xFF) { +@@ -1814,14 +1827,16 @@ mpeg_sys_type_find (GstTypeFind * tf, gpointer unused) + guint pack_size; + guint since_last_sync = 0; + guint32 sync_word = 0xffffffff; ++ guint offset = 0; + ++possible: + G_STMT_START { + gint len; + +- len = MPEG2_MAX_PROBE_LENGTH; ++ len = MPEG2_MAX_PROBE_LENGTH / 4; + do { + len = len / 2; +- data = gst_type_find_peek (tf, 0, 5 + len); ++ data = gst_type_find_peek (tf, offset, 5 + len); + } while (data == NULL && len >= 32); + + if (!data) +@@ -1882,9 +1897,8 @@ mpeg_sys_type_find (GstTypeFind * tf, gpointer unused) + } + } + +- sync_word |= data[0]; ++ sync_word |= *data++; + since_last_sync++; +- data++; + + /* If we have found MAX headers, and *some* were pes headers (pack headers + * are optional in an mpeg system stream) then return our high-probability +@@ -1899,6 +1913,12 @@ mpeg_sys_type_find (GstTypeFind * tf, gpointer unused) + if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS) + goto suggest; + ++ if (pack_headers + pes_headers > 0) { ++ offset += data - data0; ++ if (offset < MPEG2_MAX_PROBE_LENGTH) ++ goto possible; ++ } ++ + return; + suggest: + { diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch b/gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch new file mode 100644 index 0000000..59f67db --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0010-playbasebin-add-network-queue-support-adding-nw-queu.patch @@ -0,0 +1,423 @@ +From 7186918c4d8ecb95f7b669205f7b06c1f462b6b2 Mon Sep 17 00:00:00 2001 +From: Maemo Multimedia +Date: Thu, 22 Jan 2009 09:02:18 +0200 +Subject: [PATCH] playbasebin: add network queue support, adding nw-queue + property + +--- + gst/playback/gstplaybasebin.c | 256 ++++++++++++++++++++++++++++++++--------- + gst/playback/gstplaybasebin.h | 1 + + 2 files changed, 205 insertions(+), 52 deletions(-) + +diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c +index 847e12f..7f81da6 100644 +--- a/gst/playback/gstplaybasebin.c ++++ b/gst/playback/gstplaybasebin.c +@@ -29,6 +29,11 @@ + + #include + ++#define SCAN_SINKS_FROM_REGISTRY ++#define PREROLL_QUEUE_MAX_BUFFERS 5 ++#define PREROLL_QUEUE_MAX_BYTES (1 * 1024 * 1024) ++#define NETWORK_QUEUE_MAX_BUFFERS 100 ++ + GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug); + #define GST_CAT_DEFAULT gst_play_base_bin_debug + +@@ -59,7 +64,8 @@ enum + ARG_AUDIO, + ARG_TEXT, + ARG_SUBTITLE_ENCODING, +- ARG_CONNECTION_SPEED ++ ARG_CONNECTION_SPEED, ++ ARG_NW_QUEUE + }; + + static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass); +@@ -94,6 +100,8 @@ static void set_active_source (GstPlayBaseBin * play_base_bin, + static gboolean probe_triggered (GstPad * pad, GstEvent * event, + gpointer user_data); + static void setup_substreams (GstPlayBaseBin * play_base_bin); ++static void queue_threshold_reached (GstElement * queue, GstPlayBaseBin ++ * play_base_bin); + + static GstPipelineClass *parent_class; + +@@ -215,6 +223,10 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass) + "Network connection speed in kbps (0 = unknown)", + 0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ g_object_class_install_property (gobject_klass, ARG_NW_QUEUE, ++ g_param_spec_boolean ("nw-queue", "Use network queue", ++ "Use separate queue for network buffering instead of using " ++ "internal audio/video queues.", FALSE, G_PARAM_READWRITE)); + + GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0, + "playbasebin"); +@@ -236,6 +248,7 @@ gst_play_base_bin_init (GstPlayBaseBin * play_base_bin) + play_base_bin->suburi = NULL; + play_base_bin->need_rebuild = TRUE; + play_base_bin->is_stream = FALSE; ++ play_base_bin->use_nw_queue = FALSE; + play_base_bin->source = NULL; + play_base_bin->decoders = NULL; + play_base_bin->subtitle = NULL; +@@ -518,7 +531,6 @@ group_is_muted (GstPlayBaseGroup * group) + /* + * Buffer/cache checking. + */ +- + static inline void + fill_buffer (GstPlayBaseBin * play_base_bin, gint percent) + { +@@ -716,12 +728,18 @@ queue_overrun (GstElement * queue, GstPlayBaseBin * play_base_bin) + + preroll_remove_overrun (queue, play_base_bin); + +- group_commit (play_base_bin, FALSE, +- GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) == +- GST_OBJECT_CAST (play_base_bin->subtitle)); ++ // Commit the group only when we are using "stupid" buffering, because when ++ // using separate network queue element this preroll queue size is much ++ // smaller, causing premature overrun (decodebin2 is still in the ++ // pad expose-unlocking loop when that happens) ++ if (play_base_bin->use_nw_queue == FALSE) { ++ group_commit (play_base_bin, FALSE, ++ GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) == ++ GST_OBJECT_CAST (play_base_bin->subtitle)); + +- /* notify end of buffering */ +- queue_threshold_reached (queue, play_base_bin); ++ /* notify end of buffering */ ++ queue_threshold_reached (queue, play_base_bin); ++ } + } + + /* this signal is only added when in streaming mode to catch underruns +@@ -832,6 +850,11 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, + "max-size-buffers", 0, "max-size-bytes", + 2 * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL); + } ++ } else if (play_base_bin->use_nw_queue) { ++ g_object_set (G_OBJECT (preroll), ++ "max-size-buffers", PREROLL_QUEUE_MAX_BUFFERS, ++ "max-size-bytes", PREROLL_QUEUE_MAX_BYTES, ++ "max-size-time", play_base_bin->queue_size, NULL); + } else { + g_object_set (G_OBJECT (preroll), + "max-size-buffers", 0, "max-size-bytes", +@@ -860,42 +883,45 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, + g_object_set_data (G_OBJECT (preroll), "overrun_signal_id", + GINT_TO_POINTER (overrun_sig)); + +- if (play_base_bin->is_stream && +- ((type == GST_STREAM_TYPE_VIDEO && +- group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) || +- (type == GST_STREAM_TYPE_AUDIO && +- group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) { +- GstPad *sinkpad; +- guint id; +- +- /* catch deadlocks when we are network buffering in time but the max-limit +- * in bytes is hit. */ +- g_signal_connect (G_OBJECT (preroll), "overrun", +- G_CALLBACK (queue_deadlock_check), play_base_bin); +- +- /* attach pointer to playbasebin */ +- g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin); +- +- /* give updates on queue size */ +- sinkpad = gst_element_get_static_pad (preroll, "sink"); +- id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll); +- GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)", +- GST_DEBUG_PAD_NAME (sinkpad), sinkpad); +- g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id)); +- +- /* catch eos and flush events so that we can ignore underruns */ +- id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event), +- preroll); +- g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id)); +- +- gst_object_unref (sinkpad); ++ if (play_base_bin->use_nw_queue == FALSE) { ++ if (play_base_bin->is_stream && ++ ((type == GST_STREAM_TYPE_VIDEO && ++ group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) || ++ (type == GST_STREAM_TYPE_AUDIO && ++ group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) { ++ GstPad *sinkpad; ++ guint id; + +- /* When we connect this queue, it will start running and immediatly +- * fire an underrun. */ +- g_signal_connect (G_OBJECT (preroll), "underrun", +- G_CALLBACK (queue_out_of_data), play_base_bin); +- /* configure threshold and callbacks */ +- queue_out_of_data (preroll, play_base_bin); ++ /* catch deadlocks when we are network buffering in time but the max-limit ++ * in bytes is hit. */ ++ g_signal_connect (G_OBJECT (preroll), "overrun", ++ G_CALLBACK (queue_deadlock_check), play_base_bin); ++ ++ /* attach pointer to playbasebin */ ++ g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin); ++ ++ /* give updates on queue size */ ++ sinkpad = gst_element_get_static_pad (preroll, "sink"); ++ id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), ++ preroll); ++ GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)", ++ GST_DEBUG_PAD_NAME (sinkpad), sinkpad); ++ g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id)); ++ ++ /* catch eos and flush events so that we can ignore underruns */ ++ id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event), ++ preroll); ++ g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id)); ++ ++ gst_object_unref (sinkpad); ++ ++ /* When we connect this queue, it will start running and immediatly ++ * fire an underrun. */ ++ g_signal_connect (G_OBJECT (preroll), "underrun", ++ G_CALLBACK (queue_out_of_data), play_base_bin); ++ /* configure threshold and callbacks */ ++ queue_out_of_data (preroll, play_base_bin); ++ } + } + + /* listen for EOS so we can switch groups when one ended. */ +@@ -1508,10 +1534,7 @@ setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri) + if (!source) + goto unknown_uri; + +- if (g_getenv ("USE_DECODEBIN2")) +- subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder"); +- else +- subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder"); ++ subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder"); + g_signal_connect (subdecodebin, "element-added", + G_CALLBACK (decodebin_element_added_cb), play_base_bin); + g_signal_connect (subdecodebin, "element-removed", +@@ -1572,7 +1595,7 @@ array_has_value (const gchar * values[], const gchar * value) + /* list of URIs that we consider to be streams and that need buffering. + * We have no mechanism yet to figure this out with a query. */ + static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://", +- "mmsu://", "mmst://", "myth://", NULL ++ "mmsu://", "mmst://", "myth://", "upnpav://", "obex://", "smb://", NULL + }; + + /* blacklisted URIs, we know they will always fail. */ +@@ -1974,16 +1997,80 @@ remove_decoders (GstPlayBaseBin * bin) + bin->decoders = NULL; + } + ++#ifdef SCAN_SINKS_FROM_REGISTRY ++ ++/* filter function for sink elements */ ++static gboolean ++gst_play_base_bin_sink_factory_filter (GstPluginFeature * feature, ++ GstPlayBaseBin * bin) ++{ ++ guint rank; ++ const gchar *klass; ++ ++ /* we only care about element factories */ ++ if (!GST_IS_ELEMENT_FACTORY (feature)) ++ return FALSE; ++ ++ klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature)); ++ /* only sinks */ ++ if (strstr (klass, "Sink") == NULL) { ++ return FALSE; ++ } ++ ++ /* only select elements with autoplugging rank */ ++ rank = gst_plugin_feature_get_rank (feature); ++ if (rank < GST_RANK_MARGINAL) ++ return FALSE; ++ ++ return TRUE; ++} ++ ++static GstCaps * ++get_supported_sink_caps (GstPlayBaseBin * bin) ++{ ++ GList *sink_factories; ++ GstCaps *sink_caps = gst_caps_new_empty (); ++ GstCaps *caps = NULL; ++ const GList *item, *pad_templates; ++ GstStaticPadTemplate *templ; ++ ++ /* filter out the sink factories; ++ stop decodebin construction when compatible sink is found */ ++ sink_factories = gst_default_registry_feature_filter ( ++ (GstPluginFeatureFilter) gst_play_base_bin_sink_factory_filter, ++ FALSE, bin); ++ ++ /* scan sink caps from registry, assumes only 1 pad template per sink */ ++ for (item = sink_factories; item != NULL; item = item->next) { ++ pad_templates = ++ gst_element_factory_get_static_pad_templates (GST_ELEMENT_FACTORY ++ (item->data)); ++ templ = pad_templates->data; ++ /* Get caps from template */ ++ caps = gst_caps_make_writable (gst_static_pad_template_get_caps (templ)); ++ if (!gst_caps_is_any (caps)) { ++ gst_caps_append (sink_caps, caps); ++ } else { ++ gst_caps_unref (caps); ++ } ++ } ++ ++ gst_plugin_feature_list_free (sink_factories); ++ GST_DEBUG_OBJECT (bin, "Sink caps from registry: %" GST_PTR_FORMAT, ++ sink_caps); ++ ++ return sink_caps; ++ ++} ++#endif ++ + static GstElement * + make_decoder (GstPlayBaseBin * play_base_bin) + { + GstElement *decoder; + + /* now create the decoder element */ +- if (g_getenv ("USE_DECODEBIN2")) +- decoder = gst_element_factory_make ("decodebin2", NULL); +- else +- decoder = gst_element_factory_make ("decodebin", NULL); ++ decoder = gst_element_factory_make ("decodebin2", NULL); + if (!decoder) + goto no_decodebin; + +@@ -2010,6 +2097,14 @@ make_decoder (GstPlayBaseBin * play_base_bin) + + play_base_bin->decoders = g_slist_prepend (play_base_bin->decoders, decoder); + ++#ifdef SCAN_SINKS_FROM_REGISTRY ++ { ++ GstCaps *sink_caps = get_supported_sink_caps (play_base_bin); ++ g_object_set (decoder, "caps", sink_caps, NULL); ++ gst_caps_unref (sink_caps); ++ } ++#endif ++ + return decoder; + + /* ERRORS */ +@@ -2021,6 +2116,32 @@ no_decodebin: + } + } + ++/* SOURCE ! NETWORK QUEUE ! DECODEBIN ! SINKS */ ++static gboolean ++add_network_queue (GstPlayBaseBin * play_base_bin, GstElement * decoder) ++{ ++ gboolean ret = FALSE; ++ GstElement *nw_queue = gst_element_factory_make ("queue2", "nw_queue"); ++ ++ /* Add network queue to bin */ ++ if (nw_queue && gst_bin_add (GST_BIN_CAST (play_base_bin), nw_queue)) { ++ /* Link network queue */ ++ if (gst_element_link (play_base_bin->source, nw_queue) && ++ gst_element_link (nw_queue, decoder)) { ++ /* Set queue2 properties */ ++ g_object_set (G_OBJECT (nw_queue), ++ "max-size-buffers", NETWORK_QUEUE_MAX_BUFFERS, ++ "max-size-bytes", 0, ++ "max-size-time", (guint64) 0, ++ "use-buffering", TRUE, "use-rate-estimate", FALSE, NULL); ++ ret = TRUE; ++ } else { ++ gst_bin_remove (GST_BIN_CAST (play_base_bin), nw_queue); ++ } ++ } ++ return ret; ++} ++ + static void + remove_source (GstPlayBaseBin * bin) + { +@@ -2040,6 +2161,17 @@ remove_source (GstPlayBaseBin * bin) + } + gst_bin_remove (GST_BIN_CAST (bin), source); + bin->source = NULL; ++ ++ if (bin->use_nw_queue) { ++ if (bin->is_stream) { ++ GstElement *nw_queue = ++ gst_bin_get_by_name (GST_BIN_CAST (bin), "nw_queue"); ++ GST_DEBUG_OBJECT (bin, "removing network queue element"); ++ gst_element_set_state (nw_queue, GST_STATE_NULL); ++ gst_bin_remove (GST_BIN_CAST (bin), nw_queue); ++ gst_object_unref (nw_queue); ++ } ++ } + } + } + +@@ -2210,13 +2342,27 @@ setup_source (GstPlayBaseBin * play_base_bin) + "Source has dynamic output pads, %d pending", play_base_bin->pending); + } else { + GstElement *decoder; ++ gboolean link_ok = FALSE; + + /* no dynamic source, we can link now */ + decoder = make_decoder (play_base_bin); + if (!decoder) + goto no_decodebin; + +- if (!gst_element_link (play_base_bin->source, decoder)) ++ if (play_base_bin->use_nw_queue) { ++ /* FIXME: network queue isn't added with source having dynamic pads */ ++ if (play_base_bin->is_stream) { ++ GST_DEBUG_OBJECT (play_base_bin, ++ "linking source to decoder using network queue"); ++ link_ok = add_network_queue (play_base_bin, decoder); ++ } else { ++ GST_DEBUG_OBJECT (play_base_bin, "linking source to decoder"); ++ link_ok = gst_element_link (play_base_bin->source, decoder); ++ } ++ } else { ++ link_ok = gst_element_link (play_base_bin->source, decoder); ++ } ++ if (!link_ok) + goto could_not_link; + } + +@@ -2631,6 +2777,9 @@ gst_play_base_bin_set_property (GObject * object, guint prop_id, + g_slist_free (list); + break; + } ++ case ARG_NW_QUEUE: ++ play_base_bin->use_nw_queue = g_value_get_boolean (value); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -2718,6 +2867,9 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value, + g_value_set_string (value, play_base_bin->subencoding); + GST_OBJECT_UNLOCK (play_base_bin); + break; ++ case ARG_NW_QUEUE: ++ g_value_set_boolean (value, play_base_bin->use_nw_queue); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +diff --git a/gst/playback/gstplaybasebin.h b/gst/playback/gstplaybasebin.h +index c8c8649..26c9fcd 100644 +--- a/gst/playback/gstplaybasebin.h ++++ b/gst/playback/gstplaybasebin.h +@@ -88,6 +88,7 @@ struct _GstPlayBaseBin { + gboolean subtitle_done; + gboolean need_rebuild; + gboolean raw_decoding_mode; /* Use smaller queues when source outputs raw data */ ++ gboolean use_nw_queue; + + GSList *subtitle_elements; /* subtitle elements that have 'subtitle-encoding' property */ + gchar *subencoding; /* encoding to propagate to the above subtitle elements */ diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0011-Startup-benchmarking-test.patch b/gst-plugins-base-subtitles0.10/debian/patches/0011-Startup-benchmarking-test.patch new file mode 100644 index 0000000..c781ed1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0011-Startup-benchmarking-test.patch @@ -0,0 +1,296 @@ +From d1d935579a6248dd10a6681f130404519f815276 Mon Sep 17 00:00:00 2001 +From: Maemo Multimedia +Date: Thu, 22 Jan 2009 09:57:49 +0200 +Subject: [PATCH] Startup benchmarking test + +--- + configure.ac | 1 + + tests/benchmarks/Makefile.am | 4 + + tests/benchmarks/startup.c | 255 ++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 260 insertions(+), 0 deletions(-) + create mode 100644 tests/benchmarks/Makefile.am + create mode 100644 tests/benchmarks/startup.c + +diff --git a/configure.ac b/configure.ac +index 4de8751..a7e72c6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1003,6 +1003,7 @@ pkgconfig/gstreamer-video-uninstalled.pc + pkgconfig/gstreamer-plugins-base.pc + pkgconfig/gstreamer-plugins-base-uninstalled.pc + tests/Makefile ++tests/benchmarks/Makefile + tests/check/Makefile + tests/examples/Makefile + tests/examples/app/Makefile +diff --git a/tests/benchmarks/Makefile.am b/tests/benchmarks/Makefile.am +new file mode 100644 +index 0000000..93a2440 +--- /dev/null ++++ b/tests/benchmarks/Makefile.am +@@ -0,0 +1,4 @@ ++noinst_PROGRAMS = startup ++ ++AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) ++LDADD = $(GST_LIBS) +diff --git a/tests/benchmarks/startup.c b/tests/benchmarks/startup.c +new file mode 100644 +index 0000000..4d39f9d +--- /dev/null ++++ b/tests/benchmarks/startup.c +@@ -0,0 +1,255 @@ ++#include ++#include ++#include ++ ++GList *sink_list = NULL; ++GMainLoop *loop = NULL; ++GstClockTime generic_start; ++GstClockTime generic_end; ++GstClockTime null_start; ++GstClockTime paused_start; ++GstClockTime playing_end; ++guint profile = 0; ++guint id = 0; ++ ++static GstClockTime ++gst_get_current_time (void) ++{ ++ GTimeVal tv; ++ ++ g_get_current_time (&tv); ++ return GST_TIMEVAL_TO_TIME (tv); ++} ++ ++void dbin_dpad_cb (GstElement* e, ++ GstPad* pad, ++ gboolean cont, ++ gpointer user_data) ++{ ++ GstElement *pipeline; ++ GstCaps *padcaps; ++ gboolean audio = FALSE; ++ ++ pipeline = (GstElement *) user_data; ++ ++ padcaps = gst_pad_get_caps (pad); ++ ++ if (padcaps) { ++ GstStructure *stru; ++ const gchar *name; ++ ++ stru = gst_caps_get_structure ((const GstCaps *) padcaps, 0); ++ name = gst_structure_get_name (stru); ++ if (g_strrstr (name, "audio/x-raw")) { ++ audio = TRUE; ++ } ++ gst_caps_unref (padcaps); ++ } ++ ++ if (audio) { ++#if 0 ++ GstElement *conv, *resamp, *sink; ++ GstBin *bin; ++ GstPad *spad, *gpad; ++ ++ printf ("creating audio bin\n"); ++ ++ bin = (GstBin *) gst_bin_new ("abin"); ++ gst_object_ref (bin); ++ gst_object_sink (bin); ++ ++ conv = gst_element_factory_make ("audioconvert", "aconv"); ++ resamp = gst_element_factory_make ("audioresample", "aresample"); ++ sink = gst_element_factory_make ("autoaudiosink", "audiosink"); ++ ++ gst_bin_add_many (bin, conv, resamp, sink, NULL); ++ gst_element_link_pads (conv, "src", resamp, "sink"); ++ gst_element_link_pads (resamp, "src", sink, "sink"); ++ ++ gst_bin_add (GST_BIN_CAST (pipeline), GST_ELEMENT_CAST (bin)); ++ ++ spad = gst_element_get_static_pad (conv, "sink"); ++ gpad = gst_ghost_pad_new ("sink", spad); ++ gst_element_add_pad (GST_ELEMENT_CAST (bin), gpad); ++ gst_object_unref (spad); ++ ++ gst_pad_link (pad, gpad); ++ sink_list = g_list_append (sink_list, bin); ++#else ++ GstElement *sink; ++ GstPad *spad; ++ ++ sink = gst_element_factory_make ("alsasink", "audiosink"); ++ gst_bin_add (GST_BIN_CAST (pipeline), sink); ++ gst_element_set_state (sink, GST_STATE_PAUSED); ++ spad = gst_element_get_static_pad (sink, "sink"); ++ gst_pad_link (pad, spad); ++ gst_object_unref (spad); ++ sink_list = g_list_append (sink_list, sink); ++#endif ++ ++ } ++ else { ++ GstElement *fsink; ++ GstPad *fsinkpad; ++ ++ printf ("creating fakesink for non-audio pad\n"); ++ ++ fsink = gst_element_factory_make ("fakesink", NULL); ++ sink_list = g_list_append (sink_list, fsink); ++ gst_element_set_state (fsink, GST_STATE_PAUSED); ++ gst_bin_add (GST_BIN_CAST (pipeline), fsink); ++ fsinkpad = gst_element_get_static_pad (fsink, "sink"); ++ gst_pad_link (pad, fsinkpad); ++ gst_object_unref (fsinkpad); ++ } ++} ++ ++ ++static gboolean ++metadata_bus_async_cb (GstBus *bus, GstMessage *msg, gpointer data) ++{ ++ GError *error = NULL; ++ GstElement *pipeline = (GstElement *) data; ++ gboolean stop = FALSE; ++ ++ switch (GST_MESSAGE_TYPE (msg)) { ++ case GST_MESSAGE_ERROR: ++ gst_message_parse_error (msg, &error, NULL); ++ printf ("ERROR: %s\n", error->message); ++ g_error_free (error); ++ stop = TRUE; ++ break; ++ case GST_MESSAGE_EOS: ++ printf (" EOS\n"); ++ stop = TRUE; ++ break; ++ case GST_MESSAGE_STATE_CHANGED: ++ { ++ GstElement *sender = (GstElement *) GST_MESSAGE_SRC (msg); ++ if (sender == pipeline) { ++ GstState newstate; ++ gst_message_parse_state_changed (msg, NULL, &newstate, NULL); ++ if (newstate == GST_STATE_PLAYING) { ++ if (profile) { ++ system ("opcontrol --stop"); ++ printf ("=== PROFILER STOPPED ===\n"); ++ } ++ playing_end = gst_get_current_time (); ++ printf ("Startup time from NULL: %" GST_TIME_FORMAT "\n", ++ GST_TIME_ARGS (playing_end - null_start)); ++ printf ("Startup time from PAUSED: %" GST_TIME_FORMAT "\n", ++ GST_TIME_ARGS (playing_end - paused_start)); ++ stop = TRUE; ++ } ++ else if (newstate == GST_STATE_PAUSED) { ++ paused_start = gst_get_current_time (); ++ } ++ } ++ } ++ default: ++ break; ++ } ++ ++ if (stop) { ++ gst_element_set_state (pipeline, GST_STATE_READY); ++ g_main_loop_quit (loop); ++ } ++ ++ return TRUE; ++} ++ ++int main(int argc, char **argv) ++{ ++ GstElement *pipeline; ++ GstBus *bus; ++ int pipe_type = 0; ++ ++ if(argc < 4) { ++ printf ("\nUSAGE: %s []\n\n", argv[0]); ++ printf (" Pipeline type: 0: Hardcoded MP3 pipeline\n"); ++ printf (" 1: Playbin2\n"); ++ printf (" 2: Decodebin2\n\n"); ++ exit (1); ++ } ++ ++ pipe_type = atoi (argv[1]); ++ profile = atoi (argv[2]); ++ ++ printf ("============================================================\n"); ++ ++ generic_start = gst_get_current_time (); ++ gst_init (&argc, &argv); ++ generic_end = gst_get_current_time (); ++ ++ printf ("gst_init() time: %" GST_TIME_FORMAT "\n", ++ GST_TIME_ARGS (generic_end - generic_start)); ++ ++ if (pipe_type == 0) { ++ GstElement *src, *dec, *sink; ++ pipeline = gst_element_factory_make ("pipeline", NULL); ++ src = gst_element_factory_make ("filesrc", NULL); ++ dec = gst_element_factory_make ("omx_mp3dec", NULL); ++ sink = gst_element_factory_make ("alsasink", NULL); ++ gst_bin_add_many (GST_BIN_CAST (pipeline), src, dec, sink, NULL); ++ gst_element_link_many (src, dec, sink, NULL); ++ ++ g_object_set (G_OBJECT (src), "location", argv[3], NULL); ++ g_object_set (G_OBJECT (dec), "use-timestamps", FALSE, NULL); ++ } ++ else if (pipe_type == 1) { ++ pipeline = gst_element_factory_make ("playbin2", NULL); ++ g_object_set (G_OBJECT (pipeline), "uri", argv[3], NULL); ++ g_object_set (G_OBJECT (pipeline), "skip-metadata", TRUE, NULL); ++ } ++ else if (pipe_type == 2) { ++ GstElement *src, *dec; ++ GstCaps *filecaps; ++ ++ pipeline = gst_element_factory_make ("pipeline", NULL); ++ src = gst_element_factory_make ("filesrc", NULL); ++ dec = gst_element_factory_make ("decodebin2", NULL); ++ gst_bin_add_many (GST_BIN_CAST (pipeline), src, dec, NULL); ++ gst_element_link_many (src, dec, NULL); ++ ++ g_object_set (G_OBJECT (src), "location", argv[3], NULL); ++ g_object_set (G_OBJECT (dec), "skip-metadata", TRUE, NULL); ++ ++ if (argc >= 5) { ++ printf ("Setting caps '%s' to skip typefinding!\n", argv[4]); ++ filecaps = gst_caps_from_string (argv[4]); ++ g_object_set (G_OBJECT (dec), "sink-caps", filecaps, NULL); ++ gst_caps_unref (filecaps); ++ } ++ ++ id = g_signal_connect (G_OBJECT (dec), "new-decoded-pad", ++ G_CALLBACK (dbin_dpad_cb), pipeline); ++ ++ } ++ else { ++ printf ("Unknown pipeline type\n"); ++ goto leave; ++ } ++ ++ loop = g_main_loop_new (NULL, FALSE); ++ bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); ++ gst_bus_add_watch (bus, metadata_bus_async_cb, pipeline); ++ ++ if (profile) { ++ system ("opcontrol --start"); ++ printf ("=== PROFILER RUNNING ===\n"); ++ } ++ ++ null_start = gst_get_current_time (); ++ gst_element_set_state (pipeline, GST_STATE_PLAYING); ++ g_main_loop_run (loop); ++ ++ gst_element_set_state (pipeline, GST_STATE_NULL); ++ gst_object_unref (bus); ++ gst_object_unref (GST_OBJECT (pipeline)); ++ ++leave: ++ printf ("============================================================\n"); ++ ++ return 0; ++} diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0012-baseaudiosrc-sink-Change-default-latency-time-to-40m.patch b/gst-plugins-base-subtitles0.10/debian/patches/0012-baseaudiosrc-sink-Change-default-latency-time-to-40m.patch new file mode 100644 index 0000000..7191c71 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0012-baseaudiosrc-sink-Change-default-latency-time-to-40m.patch @@ -0,0 +1,39 @@ +From 22b90c4f607b01e2036f9451b5167b0cc434434a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20Stadler?= +Date: Fri, 20 Feb 2009 20:32:31 +0200 +Subject: [PATCH] baseaudiosrc, sink: Change default latency-time to 40ms + (Maemo specific change) + +This decreases the CPU load when using pulseaudio, giving a nice benefit in +Maemo devices. +--- + gst-libs/gst/audio/gstbaseaudiosink.c | 2 +- + gst-libs/gst/audio/gstbaseaudiosrc.c | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-libs/gst/audio/gstbaseaudiosink.c +index 6093092..0582712 100644 +--- a/gst-libs/gst/audio/gstbaseaudiosink.c ++++ b/gst-libs/gst/audio/gstbaseaudiosink.c +@@ -72,7 +72,7 @@ enum + + /* FIXME: 0.11, store the buffer_time and latency_time in nanoseconds */ + #define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND) +-#define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND) ++#define DEFAULT_LATENCY_TIME ((40 * GST_MSECOND) / GST_USECOND) + #define DEFAULT_PROVIDE_CLOCK TRUE + #define DEFAULT_SLAVE_METHOD GST_BASE_AUDIO_SINK_SLAVE_SKEW + +diff --git a/gst-libs/gst/audio/gstbaseaudiosrc.c b/gst-libs/gst/audio/gstbaseaudiosrc.c +index 7c7ec93..ba45aba 100644 +--- a/gst-libs/gst/audio/gstbaseaudiosrc.c ++++ b/gst-libs/gst/audio/gstbaseaudiosrc.c +@@ -87,7 +87,7 @@ enum + }; + + #define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND) +-#define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND) ++#define DEFAULT_LATENCY_TIME ((40 * GST_MSECOND) / GST_USECOND) + #define DEFAULT_ACTUAL_BUFFER_TIME -1 + #define DEFAULT_ACTUAL_LATENCY_TIME -1 + #define DEFAULT_PROVIDE_CLOCK TRUE diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0013-Install-gst-tagread-example-program.patch b/gst-plugins-base-subtitles0.10/debian/patches/0013-Install-gst-tagread-example-program.patch new file mode 100644 index 0000000..0b09a60 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0013-Install-gst-tagread-example-program.patch @@ -0,0 +1,19 @@ +From eae8ee77bd63c2e0bfd0f6ff11219d0a4180399c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20Stadler?= +Date: Tue, 19 May 2009 11:59:42 +0300 +Subject: [PATCH] Install gst-tagread example program. + +--- + tests/examples/tagreading/Makefile.am | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/tests/examples/tagreading/Makefile.am b/tests/examples/tagreading/Makefile.am +index 2d34c54..7500adc 100644 +--- a/tests/examples/tagreading/Makefile.am ++++ b/tests/examples/tagreading/Makefile.am +@@ -1,4 +1,4 @@ +-noinst_PROGRAMS = gst-tagread ++bin_PROGRAMS = gst-tagread + + gst_tagread_SOURCES = gst-tagread.c + gst_tagread_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0014-NEON-optimized-version-of-uyvy_to_rgb24-function.patch b/gst-plugins-base-subtitles0.10/debian/patches/0014-NEON-optimized-version-of-uyvy_to_rgb24-function.patch new file mode 100644 index 0000000..05c6ccd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0014-NEON-optimized-version-of-uyvy_to_rgb24-function.patch @@ -0,0 +1,161 @@ +From 324f67541827f4027b54d03b67c79e649980d0dc Mon Sep 17 00:00:00 2001 +From: Siarhei Siamashka +Date: Mon, 13 Jul 2009 17:29:02 +0300 +Subject: [PATCH] NEON optimized version of uyvy_to_rgb24 function + +--- + gst/ffmpegcolorspace/imgconvert.c | 134 +++++++++++++++++++++++++++++++++++++ + 1 files changed, 134 insertions(+), 0 deletions(-) + +diff --git a/gst/ffmpegcolorspace/imgconvert.c b/gst/ffmpegcolorspace/imgconvert.c +index cb145bb..2436a20 100644 +--- a/gst/ffmpegcolorspace/imgconvert.c ++++ b/gst/ffmpegcolorspace/imgconvert.c +@@ -827,6 +827,137 @@ img_copy (AVPicture * dst, const AVPicture * src, + } + } + ++#ifdef __ARM_NEON__ ++/* ++ * ARM NEON optimized implementation of UYVY -> RGB24 convertor ++ */ ++static void ++uyvy422_to_rgb24_line_neon (uint8_t * dst, uint8_t * src, int n) ++{ ++ /* and this is the NEON code itself */ ++ static __attribute__ ((aligned (16))) uint16_t acc_r[8] = { ++ 22840, 22840, 22840, 22840, 22840, 22840, 22840, 22840, ++ }; ++ static __attribute__ ((aligned (16))) uint16_t acc_g[8] = { ++ 17312, 17312, 17312, 17312, 17312, 17312, 17312, 17312, ++ }; ++ static __attribute__ ((aligned (16))) uint16_t acc_b[8] = { ++ 28832, 28832, 28832, 28832, 28832, 28832, 28832, 28832, ++ }; ++ /* ++ * Registers: ++ * q0, q1 : d0, d1, d2, d3 - are used for initial loading of YUV data ++ * q2 : d4, d5 - are used for storing converted RGB data ++ * q3 : d6, d7 - are used for temporary storage ++ * ++ * q4-q7 - reserved ++ * ++ * q8, q9 : d16, d17, d18, d19 - are used for expanded Y data ++ * q10 : d20, d21 ++ * q11 : d22, d23 ++ * q12 : d24, d25 ++ * q13 : d26, d27 ++ * q13, q14, q15 - various constants (#16, #149, #204, #50, #104, #154) ++ */ ++ asm volatile (".macro convert_macroblock size\n" ++ /* load up to 16 source pixels in UYVY format */ ++ ".if \\size == 16\n" ++ "pld [%[src], #128]\n" ++ "vld1.32 {d0, d1, d2, d3}, [%[src]]!\n" ++ ".elseif \\size == 8\n" ++ "vld1.32 {d0, d1}, [%[src]]!\n" ++ ".elseif \\size == 4\n" ++ "vld1.32 {d0}, [%[src]]!\n" ++ ".elseif \\size == 2\n" ++ "vld1.32 {d0[0]}, [%[src]]!\n" ++ ".else\n" ".error \"unsupported macroblock size\"\n" ".endif\n" ++ /* convert from 'packed' to 'planar' representation */ ++ "vuzp.8 d0, d1\n" /* d1 - separated Y data (first 8 bytes) */ ++ "vuzp.8 d2, d3\n" /* d3 - separated Y data (next 8 bytes) */ ++ "vuzp.8 d0, d2\n" /* d0 - separated U data, d2 - separated V data */ ++ /* split even and odd Y color components */ ++ "vuzp.8 d1, d3\n" /* d1 - evenY, d3 - oddY */ ++ /* clip upper and lower boundaries */ ++ "vqadd.u8 q0, q0, q4\n" "vqadd.u8 q1, q1, q4\n" "vqsub.u8 q0, q0, q5\n" "vqsub.u8 q1, q1, q5\n" "vshr.u8 d4, d2, #1\n" /* d4 = V >> 1 */ ++ "vmull.u8 q8, d1, d27\n" /* q8 = evenY * 149 */ ++ "vmull.u8 q9, d3, d27\n" /* q9 = oddY * 149 */ ++ "vld1.16 {d20, d21}, [%[acc_r], :128]\n" /* q10 - initialize accumulator for red */ ++ "vsubw.u8 q10, q10, d4\n" /* red acc -= (V >> 1) */ ++ "vmlsl.u8 q10, d2, d28\n" /* red acc -= V * 204 */ ++ "vld1.16 {d22, d23}, [%[acc_g], :128]\n" /* q11 - initialize accumulator for green */ ++ "vmlsl.u8 q11, d2, d30\n" /* green acc -= V * 104 */ ++ "vmlsl.u8 q11, d0, d29\n" /* green acc -= U * 50 */ ++ "vld1.16 {d24, d25}, [%[acc_b], :128]\n" /* q12 - initialize accumulator for blue */ ++ "vmlsl.u8 q12, d0, d30\n" /* blue acc -= U * 104 */ ++ "vmlsl.u8 q12, d0, d31\n" /* blue acc -= U * 154 */ ++ "vhsub.s16 q3, q8, q10\n" /* calculate even red components */ ++ "vhsub.s16 q10, q9, q10\n" /* calculate odd red components */ ++ "vqshrun.s16 d0, q3, #6\n" /* right shift, narrow and saturate even red components */ ++ "vqshrun.s16 d3, q10, #6\n" /* right shift, narrow and saturate odd red components */ ++ "vhadd.s16 q3, q8, q11\n" /* calculate even green components */ ++ "vhadd.s16 q11, q9, q11\n" /* calculate odd green components */ ++ "vqshrun.s16 d1, q3, #6\n" /* right shift, narrow and saturate even green components */ ++ "vqshrun.s16 d4, q11, #6\n" /* right shift, narrow and saturate odd green components */ ++ "vhsub.s16 q3, q8, q12\n" /* calculate even blue components */ ++ "vhsub.s16 q12, q9, q12\n" /* calculate odd blue components */ ++ "vqshrun.s16 d2, q3, #6\n" /* right shift, narrow and saturate even blue components */ ++ "vqshrun.s16 d5, q12, #6\n" /* right shift, narrow and saturate odd blue components */ ++ "vzip.8 d0, d3\n" /* join even and odd red components */ ++ "vzip.8 d1, d4\n" /* join even and odd green components */ ++ "vzip.8 d2, d5\n" /* join even and odd blue components */ ++ ".if \\size == 16\n" "vst3.8 {d0, d1, d2}, [%[dst]]!\n" "vst3.8 {d3, d4, d5}, [%[dst]]!\n" ".elseif \\size == 8\n" "vst3.8 {d0, d1, d2}, [%[dst]]!\n" ".elseif \\size == 4\n" "vst3.8 {d0[0], d1[0], d2[0]}, [%[dst]]!\n" "vst3.8 {d0[1], d1[1], d2[1]}, [%[dst]]!\n" "vst3.8 {d0[2], d1[2], d2[2]}, [%[dst]]!\n" "vst3.8 {d0[3], d1[3], d2[3]}, [%[dst]]!\n" ".elseif \\size == 2\n" "vst3.8 {d0[0], d1[0], d2[0]}, [%[dst]]!\n" "vst3.8 {d0[1], d1[1], d2[1]}, [%[dst]]!\n" ".else\n" ".error \"unsupported macroblock size\"\n" ".endif\n" ".endm\n" "vmov.u8 d8, #15\n" /* add this to U/V to saturate upper boundary */ ++ "vmov.u8 d9, #20\n" /* add this to Y to saturate upper boundary */ ++ "vmov.u8 d10, #31\n" /* sub this from U/V to saturate lower boundary */ ++ "vmov.u8 d11, #36\n" /* sub this from Y to saturate lower boundary */ ++ "vmov.u8 d26, #16\n" ++ "vmov.u8 d27, #149\n" ++ "vmov.u8 d28, #204\n" ++ "vmov.u8 d29, #50\n" ++ "vmov.u8 d30, #104\n" ++ "vmov.u8 d31, #154\n" ++ "subs %[n], %[n], #16\n" ++ "blt 2f\n" ++ "1:\n" ++ "convert_macroblock 16\n" ++ "subs %[n], %[n], #16\n" ++ "bge 1b\n" ++ "2:\n" ++ "tst %[n], #8\n" ++ "beq 3f\n" ++ "convert_macroblock 8\n" ++ "3:\n" ++ "tst %[n], #4\n" ++ "beq 4f\n" ++ "convert_macroblock 4\n" ++ "4:\n" ++ "tst %[n], #2\n" ++ "beq 5f\n" ++ "convert_macroblock 2\n" ++ "5:\n" ++ ".purgem convert_macroblock\n":[src] "+&r" (src),[dst] "+&r" (dst), ++ [n] "+&r" (n) ++ :[acc_r] "r" (&acc_r[0]),[acc_g] "r" (&acc_g[0]),[acc_b] "r" (&acc_b[0]) ++ :"cc", "memory", "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11", /* "d12", "d13", "d14", "d15", */ ++ "d16", "d17", "d18", "d19", "d20", "d21", "d22", "d23", ++ "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31"); ++} ++ ++static void ++uyvy422_to_rgb24_neon (AVPicture * dst, const AVPicture * src, ++ int width, int height) ++{ ++ uint8_t *s, *d; ++ d = dst->data[0]; ++ s = src->data[0]; ++ for (; height > 0; height--) { ++ uyvy422_to_rgb24_line_neon (d, s, width); ++ d += dst->linesize[0]; ++ s += src->linesize[0]; ++ } ++} ++ ++#endif ++ + /* XXX: totally non optimized */ + + static void +@@ -3178,6 +3309,9 @@ static ConvertEntry convert_table[] = { + {PIX_FMT_YUV422, PIX_FMT_ABGR32, yuv422_to_abgr32}, + {PIX_FMT_YUV422, PIX_FMT_ARGB32, yuv422_to_argb32}, + ++#ifdef __ARM_NEON__ ++ {PIX_FMT_UYVY422, PIX_FMT_RGB24, uyvy422_to_rgb24_neon}, ++#endif + {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p}, + {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p}, + {PIX_FMT_UYVY422, PIX_FMT_GRAY8, uyvy422_to_gray}, diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0015-ARM-NEON-optimized-version-of-uyvy422_to_yuv420p-fun.patch b/gst-plugins-base-subtitles0.10/debian/patches/0015-ARM-NEON-optimized-version-of-uyvy422_to_yuv420p-fun.patch new file mode 100644 index 0000000..d120379 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0015-ARM-NEON-optimized-version-of-uyvy422_to_yuv420p-fun.patch @@ -0,0 +1,180 @@ +From 04c686998b70b616d6c3a13cc694cf0811ba8650 Mon Sep 17 00:00:00 2001 +From: Siarhei Siamashka +Date: Tue, 14 Jul 2009 21:50:18 +0300 +Subject: [PATCH] ARM NEON optimized version of uyvy422_to_yuv420p function + +--- + gst/ffmpegcolorspace/imgconvert.c | 153 +++++++++++++++++++++++++++++++++++++ + 1 files changed, 153 insertions(+), 0 deletions(-) + +diff --git a/gst/ffmpegcolorspace/imgconvert.c b/gst/ffmpegcolorspace/imgconvert.c +index 2436a20..67cb19d 100644 +--- a/gst/ffmpegcolorspace/imgconvert.c ++++ b/gst/ffmpegcolorspace/imgconvert.c +@@ -956,6 +956,158 @@ uyvy422_to_rgb24_neon (AVPicture * dst, const AVPicture * src, + } + } + ++/* ++ * ARM NEON optimized implementation of UYVY -> YV12 convertor ++ */ ++static void ++uyvy422_to_yuv420p_neon (AVPicture * dst, const AVPicture * src, ++ int width, int height) ++{ ++ asm volatile ++ (".macro convert_macroblock_uyvy422_to_yuv420p size, store_c, src, lum, cb, cr\n" ++ /* load up to 16 source pixels in UYVY format */ ++ ".if \\size == 16\n" " vld1.8 {d0, d1, d2, d3}, [\\src]!\n" " pld [\\src, #256]\n" ".elseif \\size == 8\n" " vld1.8 {d0, d1}, [\\src]!\n" ".elseif \\size == 4\n" " vld1.8 {d0}, [\\src]!\n" ".elseif \\size == 2\n" " vld1.8 {d0[0]}, [\\src]!\n" " vld1.8 {d0[1]}, [\\src]!\n" " vld1.8 {d0[2]}, [\\src]!\n" " vld1.8 {d0[3]}, [\\src]!\n" ".elseif \\size == 1\n" " vld1.8 {d0[0]}, [\\src]!\n" " vld1.8 {d0[1]}, [\\src]!\n" " vld1.8 {d0[2]}, [\\src]!\n" ".else\n" " .error \"unsupported macroblock size\"\n" ".endif\n" " vuzp.8 d0, d1\n" /* d1 - separated Y (first 8 bytes) */ ++ " vuzp.8 d2, d3\n" /* d3 - separated Y (next 8 bytes) */ ++ " vuzp.8 d0, d2\n" /* d0 - separated U, d2 - separated V */ ++ " vswp d1, d2\n" /* exchange d1 and d2 */ ++ ".if \\size == 16\n" ++ " vst1.8 {d2, d3}, [\\lum]!\n" ++ ".if \\store_c\n" ++ " vst1.8 {d0}, [\\cb]!\n" ++ " vst1.8 {d1}, [\\cr]!\n" ++ ".endif\n" ++ ".elseif \\size == 8\n" ++ " vst1.8 {d2}, [\\lum]!\n" ++ ".if \\store_c\n" ++ " vst1.8 {d0[0]}, [\\cb]!\n" ++ " vst1.8 {d0[1]}, [\\cb]!\n" ++ " vst1.8 {d0[2]}, [\\cb]!\n" ++ " vst1.8 {d0[3]}, [\\cb]!\n" ++ " vst1.8 {d1[0]}, [\\cr]!\n" ++ " vst1.8 {d1[1]}, [\\cr]!\n" ++ " vst1.8 {d1[2]}, [\\cr]!\n" ++ " vst1.8 {d1[3]}, [\\cr]!\n" ++ ".endif\n" ++ ".elseif \\size == 4\n" ++ " vst1.8 {d2[0]}, [\\lum]!\n" ++ " vst1.8 {d2[1]}, [\\lum]!\n" ++ " vst1.8 {d2[2]}, [\\lum]!\n" ++ " vst1.8 {d2[3]}, [\\lum]!\n" ++ ".if \\store_c\n" ++ " vst1.8 {d0[0]}, [\\cb]!\n" ++ " vst1.8 {d0[1]}, [\\cb]!\n" ++ " vst1.8 {d1[0]}, [\\cr]!\n" ++ " vst1.8 {d1[1]}, [\\cr]!\n" ++ ".endif\n" ++ ".elseif \\size == 2\n" ++ " vst1.8 {d2[0]}, [\\lum]!\n" ++ " vst1.8 {d2[1]}, [\\lum]!\n" ++ ".if \\store_c\n" ++ " vst1.8 {d0[0]}, [\\cb]!\n" ++ " vst1.8 {d1[0]}, [\\cr]!\n" ++ ".endif\n" ++ ".elseif \\size == 1\n" ++ " vst1.8 {d2[0]}, [\\lum]!\n" ++ ".if \\store_c\n" ++ " vst1.8 {d0[0]}, [\\cb]!\n" ++ " vst1.8 {d1[0]}, [\\cr]!\n" ++ ".endif\n" ++ ".else\n" ++ " .error \"unsupported macroblock size\"\n" ".endif\n" ".endm\n"); ++ ++ const uint8_t *p, *p1; ++ uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; ++ int w; ++ ++ p1 = src->data[0]; ++ ++ lum1 = dst->data[0]; ++ cb1 = dst->data[1]; ++ cr1 = dst->data[2]; ++ ++ for (; height >= 1; height -= 2) { ++ p = p1; ++ lum = lum1; ++ cb = cb1; ++ cr = cr1; ++ w = width; ++#if 1 ++ asm volatile (" subs %[w], %[w], #16\n" ++ " blt 2f\n" ++ "1:\n" ++ " convert_macroblock_uyvy422_to_yuv420p 16, 1, %[p], %[lum], %[cb], %[cr]\n" ++ " subs %[w], %[w], #16\n" ++ " bge 1b\n" ++ "2:\n" ++ " .irp size, 8, 4, 2, 1\n" ++ " tst %[w], #\\size\n" ++ " beq 3f\n" ++ " convert_macroblock_uyvy422_to_yuv420p \\size, 1, %[p], %[lum], %[cb], %[cr]\n" ++ "3:\n" ++ " .endr\n":[w] "+&r" (w),[p] "+&r" (p),[lum] "+&r" (lum), ++ [cb] "+&r" (cb),[cr] "+&r" (cr) ++ ::"cc", "memory", "d0", "d1", "d2", "d3"); ++#else ++ for (; w >= 2; w -= 2) { ++ lum[0] = p[1]; ++ cb[0] = p[0]; ++ lum[1] = p[3]; ++ cr[0] = p[2]; ++ p += 4; ++ lum += 2; ++ cb++; ++ cr++; ++ } ++ if (w) { ++ lum[0] = p[1]; ++ cb[0] = p[0]; ++ cr[0] = p[2]; ++ cb++; ++ cr++; ++ } ++#endif ++ p1 += src->linesize[0]; ++ lum1 += dst->linesize[0]; ++ if (height > 1) { ++ p = p1; ++ lum = lum1; ++ w = width; ++#if 1 ++ asm volatile (" subs %[w], %[w], #16\n" ++ " blt 2f\n" ++ "1:\n" ++ " convert_macroblock_uyvy422_to_yuv420p 16, 0, %[p], %[lum], %[cb], %[cr]\n" ++ " subs %[w], %[w], #16\n" ++ " bge 1b\n" ++ "2:\n" ++ " .irp size, 8, 4, 2, 1\n" ++ " tst %[w], #\\size\n" ++ " beq 3f\n" ++ " convert_macroblock_uyvy422_to_yuv420p \\size, 0, %[p], %[lum], %[cb], %[cr]\n" ++ "3:\n" ++ " .endr\n":[w] "+&r" (w),[p] "+&r" (p),[lum] "+&r" (lum), ++ [cb] "+&r" (cb),[cr] "+&r" (cr) ++ ::"cc", "memory", "d0", "d1", "d2", "d3"); ++#else ++ for (w = width; w >= 2; w -= 2) { ++ lum[0] = p[1]; ++ lum[1] = p[3]; ++ p += 4; ++ lum += 2; ++ } ++ if (w) { ++ lum[0] = p[1]; ++ } ++#endif ++ p1 += src->linesize[0]; ++ lum1 += dst->linesize[0]; ++ } ++ cb1 += dst->linesize[1]; ++ cr1 += dst->linesize[2]; ++ } ++ asm volatile (".purgem convert_macroblock_uyvy422_to_yuv420p\n"); ++} ++ + #endif + + /* XXX: totally non optimized */ +@@ -3311,6 +3463,7 @@ static ConvertEntry convert_table[] = { + + #ifdef __ARM_NEON__ + {PIX_FMT_UYVY422, PIX_FMT_RGB24, uyvy422_to_rgb24_neon}, ++ {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p_neon}, + #endif + {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p}, + {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p}, diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0016-typefinding-workaround-for-hangs-with-ID3-tagged-m4a.patch b/gst-plugins-base-subtitles0.10/debian/patches/0016-typefinding-workaround-for-hangs-with-ID3-tagged-m4a.patch new file mode 100644 index 0000000..0e124c9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0016-typefinding-workaround-for-hangs-with-ID3-tagged-m4a.patch @@ -0,0 +1,29 @@ +From 6ad17ea0835daec54df10f4aaadcd95f597dfa02 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Tue, 6 Oct 2009 10:33:20 +0100 +Subject: [PATCH] typefinding: workaround for hangs with ID3-tagged m4a files + +This works around a race condition in decodebin2/playbin2 in +the most low-risk and least intrusive way possible (NB#134099). +--- + gst/typefind/gsttypefindfunctions.c | 7 +++++++ + 1 files changed, 7 insertions(+), 0 deletions(-) + +diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c +index 2a3a733..a6cfdeb 100644 +--- a/gst/typefind/gsttypefindfunctions.c ++++ b/gst/typefind/gsttypefindfunctions.c +@@ -550,6 +550,13 @@ id3v1_type_find (GstTypeFind * tf, gpointer unused) + guint8 *data = gst_type_find_peek (tf, -128, 3); + + if (data && memcmp (data, "TAG", 3) == 0) { ++ /* HACK: don't typefind as ID3 if this looks like a quicktime/m4a file, ++ * to avoid race condition/bug in decodebin2 that keeps id3demux ! qtdemux ++ * from prerolling at times (Nokia Music Manager creates such files) */ ++ data = gst_type_find_peek (tf, 0, 8); ++ if (data && memcmp (data + 4, "ftyp", 4) == 0) ++ return; ++ + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS); + } + } diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0017-typefinding-extend-workaround-to-ID3-tagged-ASF-WAV-.patch b/gst-plugins-base-subtitles0.10/debian/patches/0017-typefinding-extend-workaround-to-ID3-tagged-ASF-WAV-.patch new file mode 100644 index 0000000..6310f85 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0017-typefinding-extend-workaround-to-ID3-tagged-ASF-WAV-.patch @@ -0,0 +1,42 @@ +From 7ba7157378dcc9c73da475ee1fcb2590da4a7104 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= +Date: Thu, 22 Oct 2009 10:06:04 +0100 +Subject: [PATCH] typefinding: extend workaround to ID3-tagged ASF, WAV and + AVI files. + +NB #142716. +--- + gst/typefind/gsttypefindfunctions.c | 20 +++++++++++++++----- + 1 files changed, 15 insertions(+), 5 deletions(-) + +diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c +index a6cfdeb..c44b653 100644 +--- a/gst/typefind/gsttypefindfunctions.c ++++ b/gst/typefind/gsttypefindfunctions.c +@@ -551,11 +551,21 @@ id3v1_type_find (GstTypeFind * tf, gpointer unused) + + if (data && memcmp (data, "TAG", 3) == 0) { + /* HACK: don't typefind as ID3 if this looks like a quicktime/m4a file, +- * to avoid race condition/bug in decodebin2 that keeps id3demux ! qtdemux +- * from prerolling at times (Nokia Music Manager creates such files) */ +- data = gst_type_find_peek (tf, 0, 8); +- if (data && memcmp (data + 4, "ftyp", 4) == 0) +- return; ++ * (or an ASF or WAV/AVI file) to avoid race condition/bug in decodebin2 ++ * that keeps id3demux ! qtdemux and similar pipelines from prerolling ++ * at times (Nokia Music Manager creates such files) */ ++ data = gst_type_find_peek (tf, 0, 16); ++ if (data) { ++ const guint8 asf_marker[16] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66, ++ 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c ++ }; ++ ++ if (memcmp (data + 4, "ftyp", 4) == 0 || ++ memcmp (data, asf_marker, 16) == 0 || ++ (memcmp (data, "RIFF", 4) == 0 && memcmp (data + 8, "AVI", 3) == 0)) { ++ return; ++ } ++ } + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS); + } diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0018-tagreading-fix-unknown-codec-tag-missing-after-first.patch b/gst-plugins-base-subtitles0.10/debian/patches/0018-tagreading-fix-unknown-codec-tag-missing-after-first.patch new file mode 100644 index 0000000..9d45d4c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0018-tagreading-fix-unknown-codec-tag-missing-after-first.patch @@ -0,0 +1,29 @@ +From 8db39cceb378ee6bc78d5060cda9e7002280dd7f Mon Sep 17 00:00:00 2001 +From: Sreerenj Balachandran +Date: Thu, 1 Jul 2010 15:16:57 +0200 +Subject: [PATCH] tagreading: fix "unknown" codec tag missing after first time + +--- + gst/tagreading/gsttagreadutils.c | 8 ++++---- + 1 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/gst/tagreading/gsttagreadutils.c b/gst/tagreading/gsttagreadutils.c +index acaebb6..14b3e67 100644 +--- a/gst/tagreading/gsttagreadutils.c ++++ b/gst/tagreading/gsttagreadutils.c +@@ -119,11 +119,11 @@ gst_tag_read_utils_add_codec_tag_from_caps (GstTagList * tags, + G_TYPE_BOOLEAN, "codec unknown", + "TRUE if the codec is not known and the *-codec " + "tag contains the string 'unknown' or somesuch", NULL); +- +- /* FIXME: translate */ +- gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, tag_name, +- "Unknown", tag_name_unknown, TRUE, NULL); + } ++ ++ /* FIXME: translate */ ++ gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, tag_name, ++ "Unknown", tag_name_unknown, TRUE, NULL); + } + } + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0019-xvimagesink-add-disable-colorkey-property-Maemo-spec.patch b/gst-plugins-base-subtitles0.10/debian/patches/0019-xvimagesink-add-disable-colorkey-property-Maemo-spec.patch new file mode 100644 index 0000000..ef9998d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0019-xvimagesink-add-disable-colorkey-property-Maemo-spec.patch @@ -0,0 +1,167 @@ +From 048db61bc6cf06b2554867f6dfb8e088eb3bf951 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20Stadler?= +Date: Mon, 21 Dec 2009 17:34:26 +0200 +Subject: [PATCH] xvimagesink: add disable-colorkey property (Maemo specific) + +--- + sys/xvimage/xvimagesink.c | 57 +++++++++++++++++++++++++++++++++++++++++++- + sys/xvimage/xvimagesink.h | 4 +++ + 2 files changed, 59 insertions(+), 2 deletions(-) + +diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c +index 30368d5..63f7e77 100644 +--- a/sys/xvimage/xvimagesink.c ++++ b/sys/xvimage/xvimagesink.c +@@ -188,7 +188,8 @@ enum + PROP_COLORKEY, + PROP_DRAW_BORDERS, + PROP_WINDOW_WIDTH, +- PROP_WINDOW_HEIGHT ++ PROP_WINDOW_HEIGHT, ++ PROP_DISABLE_COLORKEY + }; + + static GstVideoSinkClass *parent_class = NULL; +@@ -774,6 +775,7 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, + { + GstVideoRectangle result; + gboolean draw_border = FALSE; ++ gboolean disable_colorkey; + + /* We take the flow_lock. If expose is in there we don't want to run + concurrently from the data flow thread */ +@@ -831,6 +833,16 @@ gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, + + g_mutex_lock (xvimagesink->x_lock); + ++ disable_colorkey = g_atomic_int_get (&xvimagesink->disable_colorkey); ++ if (G_UNLIKELY (disable_colorkey != xvimagesink->disable_colorkey_set)) { ++ GST_LOG_OBJECT (xvimagesink, "Setting disable-colorkey to %d", ++ (disable_colorkey ? 1 : 0)); ++ XvSetPortAttribute (xvimagesink->xcontext->disp, ++ xvimagesink->xcontext->xv_port_id, xvimagesink->disable_colorkey_atom, ++ disable_colorkey ? 1 : 0); ++ xvimagesink->disable_colorkey_set = disable_colorkey; ++ } ++ + if (draw_border && xvimagesink->draw_borders) { + gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow, + result); +@@ -1431,18 +1443,20 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, + + /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */ + { +- int count, todo = 3; ++ int count, todo = 4; + XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp, + xcontext->xv_port_id, &count); + static const char autopaint[] = "XV_AUTOPAINT_COLORKEY"; + static const char dbl_buffer[] = "XV_DOUBLE_BUFFER"; + static const char colorkey[] = "XV_COLORKEY"; ++ static const char disable_colorkey[] = "XV_DISABLE_COLORKEY"; + + GST_DEBUG_OBJECT (xvimagesink, "Checking %d Xv port attributes", count); + + xvimagesink->have_autopaint_colorkey = FALSE; + xvimagesink->have_double_buffer = FALSE; + xvimagesink->have_colorkey = FALSE; ++ xvimagesink->have_disable_colorkey = FALSE; + + for (i = 0; ((i < count) && todo); i++) + if (!strcmp (attr[i].name, autopaint)) { +@@ -1508,6 +1522,22 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, + } + todo--; + xvimagesink->have_colorkey = TRUE; ++ } else if (!strcmp (attr[i].name, disable_colorkey)) { ++ const Atom atom = XInternAtom (xcontext->disp, disable_colorkey, False); ++ gboolean disable_colorkey; ++ ++ GST_LOG_OBJECT (xvimagesink, "Setting disable-colorkey to %d", ++ (xvimagesink->disable_colorkey ? 1 : 0)); ++ ++ disable_colorkey = g_atomic_int_get (&xvimagesink->disable_colorkey); ++ XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, ++ (disable_colorkey ? 1 : 0)); ++ xvimagesink->disable_colorkey_set = disable_colorkey; ++ ++ todo--; ++ xvimagesink->have_disable_colorkey = TRUE; ++ ++ xvimagesink->disable_colorkey_atom = atom; + } + + XFree (attr); +@@ -3291,6 +3321,10 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id, + case PROP_DRAW_BORDERS: + xvimagesink->draw_borders = g_value_get_boolean (value); + break; ++ case PROP_DISABLE_COLORKEY: ++ g_atomic_int_set (&xvimagesink->disable_colorkey, ++ g_value_get_boolean (value)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -3379,6 +3413,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, + else + g_value_set_uint64 (value, 0); + break; ++ case PROP_DISABLE_COLORKEY: ++ g_value_set_boolean (value, xvimagesink->disable_colorkey); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -3503,6 +3540,9 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink) + xvimagesink->par = NULL; + xvimagesink->handle_expose = TRUE; + xvimagesink->autopaint_colorkey = TRUE; ++ xvimagesink->disable_colorkey = FALSE; ++ xvimagesink->disable_colorkey_set = FALSE; ++ xvimagesink->disable_colorkey_atom = None; + + /* on 16bit displays this becomes r,g,b = 1,2,3 + * on 24bit displays this becomes r,g,b = 8,8,16 +@@ -3670,6 +3710,19 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) + "Height of the window", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + ++ /* ++ * GstXvImageSink:disable-colorkey ++ * ++ * Whether to disable colorkeying (disabling has the same effect as painting ++ * the color key everywhere). ++ * ++ * This is a Maemo-specific property. ++ */ ++ g_object_class_install_property (gobject_class, PROP_DISABLE_COLORKEY, ++ g_param_spec_boolean ("disable-colorkey", "Disable colorkeying", ++ "Whether to disable colorkey", FALSE, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gobject_class->finalize = gst_xvimagesink_finalize; + + gstelement_class->change_state = +diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h +index 0181018..ddc0e06 100644 +--- a/sys/xvimage/xvimagesink.h ++++ b/sys/xvimage/xvimagesink.h +@@ -276,6 +276,9 @@ struct _GstXvImageSink { + /* port attributes */ + gboolean autopaint_colorkey; + gint colorkey; ++ gboolean disable_colorkey; ++ gboolean disable_colorkey_set; ++ Atom disable_colorkey_atom; + + gboolean draw_borders; + +@@ -283,6 +286,7 @@ struct _GstXvImageSink { + gboolean have_autopaint_colorkey; + gboolean have_colorkey; + gboolean have_double_buffer; ++ gboolean have_disable_colorkey; + + /* stream metadata */ + gchar *media_title; diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0020-xvimagesink-Add-property-for-the-XV_STACKING-port-at.patch b/gst-plugins-base-subtitles0.10/debian/patches/0020-xvimagesink-Add-property-for-the-XV_STACKING-port-at.patch new file mode 100644 index 0000000..d533d02 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0020-xvimagesink-Add-property-for-the-XV_STACKING-port-at.patch @@ -0,0 +1,115 @@ +From b3dd3e7d8e6437cad01df6168003f366d3eb131a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= +Date: Mon, 3 May 2010 15:00:11 -0400 +Subject: [PATCH] xvimagesink: Add property for the XV_STACKING port attribute + (Maemo specific) + +--- + sys/xvimage/xvimagesink.c | 31 +++++++++++++++++++++++++++++-- + sys/xvimage/xvimagesink.h | 3 ++- + 2 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/sys/xvimage/xvimagesink.c b/sys/xvimage/xvimagesink.c +index 63f7e77..1a61fe1 100644 +--- a/sys/xvimage/xvimagesink.c ++++ b/sys/xvimage/xvimagesink.c +@@ -189,7 +189,8 @@ enum + PROP_DRAW_BORDERS, + PROP_WINDOW_WIDTH, + PROP_WINDOW_HEIGHT, +- PROP_DISABLE_COLORKEY ++ PROP_DISABLE_COLORKEY, ++ PROP_STACKING + }; + + static GstVideoSinkClass *parent_class = NULL; +@@ -1443,13 +1444,14 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, + + /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */ + { +- int count, todo = 4; ++ int count, todo = 6; + XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp, + xcontext->xv_port_id, &count); + static const char autopaint[] = "XV_AUTOPAINT_COLORKEY"; + static const char dbl_buffer[] = "XV_DOUBLE_BUFFER"; + static const char colorkey[] = "XV_COLORKEY"; + static const char disable_colorkey[] = "XV_DISABLE_COLORKEY"; ++ static const char stacking[] = "XV_STACKING"; + + GST_DEBUG_OBJECT (xvimagesink, "Checking %d Xv port attributes", count); + +@@ -1538,6 +1540,18 @@ gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, + xvimagesink->have_disable_colorkey = TRUE; + + xvimagesink->disable_colorkey_atom = atom; ++ } else if (!strcmp (attr[i].name, stacking)) { ++ const Atom atom = XInternAtom (xcontext->disp, stacking, False); ++ gint stacking_num; ++ ++ GST_LOG_OBJECT (xvimagesink, "Setting Xv stacking order to %d", ++ xvimagesink->stacking); ++ ++ stacking_num = g_atomic_int_get (&xvimagesink->stacking); ++ XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, ++ stacking_num); ++ ++ todo--; + } + + XFree (attr); +@@ -3325,6 +3339,10 @@ gst_xvimagesink_set_property (GObject * object, guint prop_id, + g_atomic_int_set (&xvimagesink->disable_colorkey, + g_value_get_boolean (value)); + break; ++ case PROP_STACKING: ++ g_atomic_int_set (&xvimagesink->stacking, ++ g_value_get_uint (value)); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -3416,6 +3434,9 @@ gst_xvimagesink_get_property (GObject * object, guint prop_id, + case PROP_DISABLE_COLORKEY: + g_value_set_boolean (value, xvimagesink->disable_colorkey); + break; ++ case PROP_STACKING: ++ g_value_set_uint (value, xvimagesink->stacking); ++ break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; +@@ -3543,6 +3564,7 @@ gst_xvimagesink_init (GstXvImageSink * xvimagesink) + xvimagesink->disable_colorkey = FALSE; + xvimagesink->disable_colorkey_set = FALSE; + xvimagesink->disable_colorkey_atom = None; ++ xvimagesink->stacking = 0; + + /* on 16bit displays this becomes r,g,b = 1,2,3 + * on 24bit displays this becomes r,g,b = 8,8,16 +@@ -3723,6 +3745,11 @@ gst_xvimagesink_class_init (GstXvImageSinkClass * klass) + "Whether to disable colorkey", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + ++ g_object_class_install_property (gobject_class, PROP_STACKING, ++ g_param_spec_uint ("stacking", "Stacking order", ++ "The port stacking order (0=auto, 1=bottom, 2=top", 0, 2, 0, ++ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); ++ + gobject_class->finalize = gst_xvimagesink_finalize; + + gstelement_class->change_state = +diff --git a/sys/xvimage/xvimagesink.h b/sys/xvimage/xvimagesink.h +index ddc0e06..12ac3e9 100644 +--- a/sys/xvimage/xvimagesink.h ++++ b/sys/xvimage/xvimagesink.h +@@ -279,7 +279,8 @@ struct _GstXvImageSink { + gboolean disable_colorkey; + gboolean disable_colorkey_set; + Atom disable_colorkey_atom; +- ++ gint stacking; ++ + gboolean draw_borders; + + /* port features */ diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0021-Fix-libgstpbutils-libgstvideo-linking.patch b/gst-plugins-base-subtitles0.10/debian/patches/0021-Fix-libgstpbutils-libgstvideo-linking.patch new file mode 100644 index 0000000..1d4499b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0021-Fix-libgstpbutils-libgstvideo-linking.patch @@ -0,0 +1,58 @@ +From 6b907a22af2596928132d72a83366a41d0a91e1c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ren=C3=A9=20Stadler?= +Date: Thu, 3 Mar 2011 18:49:43 +0200 +Subject: [PATCH] Fix libgstpbutils/libgstvideo linking + +Not sure why this is suddenly needed, but otherwise linkage will fail +in our build system (though nowhere else). +--- + tests/check/Makefile.am | 9 +++++++-- + tests/examples/encoding/Makefile.am | 1 + + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am +index 8b8782d..573a4b1 100644 +--- a/tests/check/Makefile.am ++++ b/tests/check/Makefile.am +@@ -238,6 +238,7 @@ libs_discoverer_CFLAGS = \ + -DGST_TEST_FILE="\"$(abs_top_srcdir)/tests/files/partialframe.mjpeg\"" + libs_discoverer_LDADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ ++ $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + + libs_fft_CFLAGS = \ +@@ -311,7 +312,9 @@ libs_profile_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + libs_profile_LDADD = \ +- $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(LDADD) ++ $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ ++ $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ ++ $(LDADD) + + libs_xmpwriter_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ +@@ -379,7 +382,9 @@ elements_playbin2_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + elements_decodebin_LDADD = $(GST_BASE_LIBS) $(LDADD) + elements_decodebin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +-elements_encodebin_LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(GST_BASE_LIBS) $(LDADD) ++elements_encodebin_LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ ++ $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ ++ $(GST_BASE_LIBS) $(LDADD) + elements_encodebin_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) + + elements_decodebin2_LDADD = $(GST_BASE_LIBS) $(LDADD) +diff --git a/tests/examples/encoding/Makefile.am b/tests/examples/encoding/Makefile.am +index 2bcc902..be3378a 100644 +--- a/tests/examples/encoding/Makefile.am ++++ b/tests/examples/encoding/Makefile.am +@@ -6,6 +6,7 @@ EXTRA_DIST = gstcapslist.h + noinst_PROGRAMS = $(examples) + + LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ ++ $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_LIBS) + AM_CFLAGS = -I$(top_builddir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) \ diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0022-tag-xmp-Write-the-same-tag-to-all-schemas.patch b/gst-plugins-base-subtitles0.10/debian/patches/0022-tag-xmp-Write-the-same-tag-to-all-schemas.patch new file mode 100644 index 0000000..b7ca1c2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0022-tag-xmp-Write-the-same-tag-to-all-schemas.patch @@ -0,0 +1,117 @@ +From bdaa1fab0a20839f050659a52ab8855a203fe96c Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Mon, 18 Apr 2011 10:20:00 -0300 +Subject: [PATCH] tag: xmp: Write the same tag to all schemas + +Instead of writing only the xmp tag for the first found entry +that matches the gstreamer tag, look for all mappings to write +the tag to different schemas. + +The rationale here is that some reader application might only +be interested on a particular schema tags, so we should try +to write as many tags for all schemas. +--- + gst-libs/gst/tag/gstxmptag.c | 56 +++++++++++++++++++++++++++++++++--------- + 1 files changed, 44 insertions(+), 12 deletions(-) + +diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c +index ca05895..cc6c766 100644 +--- a/gst-libs/gst/tag/gstxmptag.c ++++ b/gst-libs/gst/tag/gstxmptag.c +@@ -182,6 +182,21 @@ gst_xmp_schema_new () + */ + static GHashTable *__xmp_schemas; + ++static GstXmpSchema * ++_gst_xmp_get_schema (const gchar * name) ++{ ++ GQuark key; ++ GstXmpSchema *schema; ++ ++ key = g_quark_from_string (name); ++ ++ schema = g_hash_table_lookup (__xmp_schemas, GUINT_TO_POINTER (key)); ++ if (!schema) { ++ GST_WARNING ("Schema %s doesn't exist", name); ++ } ++ return schema; ++} ++ + static void + _gst_xmp_add_schema (const gchar * name, GstXmpSchema * schema) + { +@@ -240,6 +255,7 @@ _gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema, + * appended, and the API is not public, so we shouldn't + * have our lists modified during usage + */ ++#if 0 + static GPtrArray * + _xmp_tag_get_mapping (const gchar * gst_tag, XmpSerializationData * serdata) + { +@@ -260,6 +276,7 @@ _xmp_tag_get_mapping (const gchar * gst_tag, XmpSerializationData * serdata) + } + return ret; + } ++#endif + + /* finds the gst tag that maps to this xmp tag in this schema */ + static const gchar * +@@ -1520,22 +1537,14 @@ gst_value_serialize_xmp (const GValue * value) + } + + static void +-write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) ++write_one_tag (const GstTagList * list, const gchar * tag, ++ GPtrArray * xmp_tag_array, gpointer user_data) + { + guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index; + XmpSerializationData *serialization_data = user_data; + GString *data = serialization_data->data; +- GPtrArray *xmp_tag_array = NULL; + char *s; + +- /* map gst-tag to xmp tag */ +- xmp_tag_array = _xmp_tag_get_mapping (tag, serialization_data); +- +- if (!xmp_tag_array) { +- GST_WARNING ("no mapping for %s to xmp", tag); +- return; +- } +- + for (tag_index = 0; tag_index < xmp_tag_array->len; tag_index++) { + XmpTag *xmp_tag; + +@@ -1635,8 +1644,31 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, + g_string_append (data, ">\n"); + g_string_append (data, "\n"); + +- /* iterate the taglist */ +- gst_tag_list_foreach (list, write_one_tag, &serialization_data); ++ /* iterate the schemas */ ++ if (schemas == NULL) { ++ /* use all schemas */ ++ schemas = gst_tag_xmp_list_schemas (); ++ } ++ i = 0; ++ for (i = 0; schemas[i] != NULL; i++) { ++ GstXmpSchema *schema = _gst_xmp_get_schema (schemas[i]); ++ GHashTableIter iter; ++ gpointer key, value; ++ ++ if (schema == NULL) ++ continue; ++ ++ /* Iterate over the hashtable */ ++ g_hash_table_iter_init (&iter, schema); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ const gchar *tag = g_quark_to_string (GPOINTER_TO_UINT (key)); ++ ++ if (gst_tag_list_get_value_index (list, tag, 0) != NULL) { ++ write_one_tag (list, tag, value, (gpointer) & serialization_data); ++ } ++ ++ } ++ } + + /* xmp footer */ + g_string_append (data, "\n"); diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0023-tag-xmp-Fixing-schema-maps.patch b/gst-plugins-base-subtitles0.10/debian/patches/0023-tag-xmp-Fixing-schema-maps.patch new file mode 100644 index 0000000..3615a6b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0023-tag-xmp-Fixing-schema-maps.patch @@ -0,0 +1,39 @@ +From 8fabef8750e185ac249df7cec42896017a5c6854 Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Mon, 18 Apr 2011 23:16:59 -0300 +Subject: [PATCH] tag: xmp: Fixing schema maps + +Do not forget to create a new schema for every supported schema +instead of reusing the same object +--- + gst-libs/gst/tag/gstxmptag.c | 3 +++ + 1 files changed, 3 insertions(+), 0 deletions(-) + +diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c +index cc6c766..b9fee8f 100644 +--- a/gst-libs/gst/tag/gstxmptag.c ++++ b/gst-libs/gst/tag/gstxmptag.c +@@ -905,6 +905,7 @@ _init_xmp_tag_map (gpointer user_data) + _gst_xmp_add_schema ("tiff", schema); + + /* exif schema */ ++ schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME, + "exif:DateTimeOriginal", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, +@@ -984,6 +985,7 @@ _init_xmp_tag_map (gpointer user_data) + _gst_xmp_add_schema ("exif", schema); + + /* photoshop schema */ ++ schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); +@@ -992,6 +994,7 @@ _init_xmp_tag_map (gpointer user_data) + _gst_xmp_add_schema ("photoshop", schema); + + /* iptc4xmpcore schema */ ++ schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0024-tag-xmp-Add-struct-xmp-tag-type-support.patch b/gst-plugins-base-subtitles0.10/debian/patches/0024-tag-xmp-Add-struct-xmp-tag-type-support.patch new file mode 100644 index 0000000..83408f0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0024-tag-xmp-Add-struct-xmp-tag-type-support.patch @@ -0,0 +1,556 @@ +From 2c10edefb47f82a72a27fb54fb181c4e3ea440cf Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Mon, 18 Apr 2011 16:54:54 -0300 +Subject: [PATCH] tag: xmp: Add struct xmp tag type support + +Adds support for writing the xmp struct tag type, it is a compound tag +that has inner tags. +--- + gst-libs/gst/tag/gstxmptag.c | 357 +++++++++++++++++++++++------------------- + 1 files changed, 195 insertions(+), 162 deletions(-) + +diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c +index b9fee8f..1a6e3c1 100644 +--- a/gst-libs/gst/tag/gstxmptag.c ++++ b/gst-libs/gst/tag/gstxmptag.c +@@ -112,14 +112,31 @@ xmp_serialization_data_use_schema (XmpSerializationData * serdata, + return FALSE; + } + ++typedef enum ++{ ++ GstXmpTagTypeSimple = 0, ++ GstXmpTagTypeBag, ++ GstXmpTagTypeSeq, ++ GstXmpTagTypeStruct, ++ ++ /* Not really a xmp type, this is a tag that in gst is represented with ++ * a single value and on xmp it needs 2 (or more) simple values ++ * ++ * e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary ++ * tags in the exif's schema. One of them stores the absolute elevation, ++ * and the other one stores if it is above of below sea level. ++ */ ++ GstXmpTagTypeCompound ++} GstXmpTagType; + +-#define GST_XMP_TAG_TYPE_SIMPLE 0 +-#define GST_XMP_TAG_TYPE_BAG 1 +-#define GST_XMP_TAG_TYPE_SEQ 2 + struct _XmpTag + { ++ const gchar *gst_tag; + const gchar *tag_name; +- gint type; ++ GstXmpTagType type; ++ ++ /* Used for struct and compound types */ ++ GSList *children; + + XmpSerializationFunc serialize; + XmpDeserializationFunc deserialize; +@@ -129,10 +146,10 @@ static GstTagMergeMode + xmp_tag_get_merge_mode (XmpTag * xmptag) + { + switch (xmptag->type) { +- case GST_XMP_TAG_TYPE_BAG: +- case GST_XMP_TAG_TYPE_SEQ: ++ case GstXmpTagTypeBag: ++ case GstXmpTagTypeSeq: + return GST_TAG_MERGE_APPEND; +- case GST_XMP_TAG_TYPE_SIMPLE: ++ case GstXmpTagTypeSimple: + default: + return GST_TAG_MERGE_KEEP; + } +@@ -142,11 +159,11 @@ static const gchar * + xmp_tag_get_type_name (XmpTag * xmptag) + { + switch (xmptag->type) { +- case GST_XMP_TAG_TYPE_SEQ: ++ case GstXmpTagTypeSeq: + return "rdf:Seq"; + default: + g_assert_not_reached (); +- case GST_XMP_TAG_TYPE_BAG: ++ case GstXmpTagTypeBag: + return "rdf:Bag"; + } + } +@@ -159,14 +176,9 @@ struct _PendingXmpTag + }; + typedef struct _PendingXmpTag PendingXmpTag; + +- + /* + * A schema is a mapping of strings (the tag name in gstreamer) to a list of +- * tags in xmp (XmpTag). We need a list because some tags are split into 2 +- * when serialized into xmp. +- * e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary +- * tags in the exif's schema. One of them stores the absolute elevation, +- * and the other one stores if it is above of below sea level. ++ * tags in xmp (XmpTag). + */ + typedef GHashTable GstXmpSchema; + #define gst_xmp_schema_lookup g_hash_table_lookup +@@ -214,40 +226,70 @@ _gst_xmp_add_schema (const gchar * name, GstXmpSchema * schema) + } + + static void +-_gst_xmp_schema_add_mapping (GstXmpSchema * schema, const gchar * gst_tag, +- GPtrArray * array) ++_gst_xmp_schema_add_mapping (GstXmpSchema * schema, XmpTag * tag) + { + GQuark key; + +- key = g_quark_from_string (gst_tag); ++ key = g_quark_from_string (tag->gst_tag); + + if (gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key))) { +- GST_WARNING ("Tag %s already present for the schema", gst_tag); ++ GST_WARNING ("Tag %s already present for the schema", tag->gst_tag); + g_assert_not_reached (); + return; + } +- gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), array); ++ gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), tag); + } + +-static void +-_gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema, +- const gchar * gst_tag, const gchar * xmp_tag, gint xmp_type, +- XmpSerializationFunc serialization_func, ++static XmpTag * ++gst_xmp_tag_create (const gchar * gst_tag, const gchar * xmp_tag, ++ gint xmp_type, XmpSerializationFunc serialization_func, + XmpDeserializationFunc deserialization_func) + { + XmpTag *xmpinfo; +- GPtrArray *array; + + xmpinfo = g_slice_new (XmpTag); ++ xmpinfo->gst_tag = gst_tag; + xmpinfo->tag_name = xmp_tag; + xmpinfo->type = xmp_type; + xmpinfo->serialize = serialization_func; + xmpinfo->deserialize = deserialization_func; ++ xmpinfo->children = NULL; + +- array = g_ptr_array_sized_new (1); +- g_ptr_array_add (array, xmpinfo); ++ return xmpinfo; ++} + +- _gst_xmp_schema_add_mapping (schema, gst_tag, array); ++static XmpTag * ++gst_xmp_tag_create_compound (const gchar * gst_tag, const gchar * xmp_tag_a, ++ const gchar * xmp_tag_b, XmpSerializationFunc serialization_func_a, ++ XmpSerializationFunc serialization_func_b, ++ XmpDeserializationFunc deserialization_func) ++{ ++ XmpTag *xmptag; ++ XmpTag *xmptag_a = ++ gst_xmp_tag_create (gst_tag, xmp_tag_a, GstXmpTagTypeSimple, ++ serialization_func_a, deserialization_func); ++ XmpTag *xmptag_b = ++ gst_xmp_tag_create (gst_tag, xmp_tag_b, GstXmpTagTypeSimple, ++ serialization_func_b, deserialization_func); ++ ++ xmptag = ++ gst_xmp_tag_create (gst_tag, NULL, GstXmpTagTypeCompound, NULL, NULL); ++ ++ xmptag->children = g_slist_prepend (xmptag->children, xmptag_b); ++ xmptag->children = g_slist_prepend (xmptag->children, xmptag_a); ++ ++ return xmptag; ++} ++ ++static void ++_gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema, ++ const gchar * gst_tag, const gchar * xmp_tag, gint xmp_type, ++ XmpSerializationFunc serialization_func, ++ XmpDeserializationFunc deserialization_func) ++{ ++ _gst_xmp_schema_add_mapping (schema, ++ gst_xmp_tag_create (gst_tag, xmp_tag, xmp_type, serialization_func, ++ deserialization_func)); + } + + /* +@@ -286,22 +328,30 @@ _gst_xmp_schema_get_mapping_reverse (GstXmpSchema * schema, + GHashTableIter iter; + gpointer key, value; + const gchar *ret = NULL; +- gint index; + + /* Iterate over the hashtable */ + g_hash_table_iter_init (&iter, schema); + while (!ret && g_hash_table_iter_next (&iter, &key, &value)) { +- GPtrArray *array = (GPtrArray *) value; +- +- /* each mapping might contain complementary tags */ +- for (index = 0; index < array->len; index++) { +- XmpTag *xmpinfo = (XmpTag *) g_ptr_array_index (array, index); ++ XmpTag *xmpinfo = (XmpTag *) value; + ++ if (xmpinfo->tag_name) { + if (strcmp (xmpinfo->tag_name, xmp_tag) == 0) { + *_xmp_tag = xmpinfo; + ret = g_quark_to_string (GPOINTER_TO_UINT (key)); + goto out; + } ++ } else if (xmpinfo->children) { ++ GSList *iter; ++ for (iter = xmpinfo->children; iter; iter = g_slist_next (iter)) { ++ XmpTag *child = iter->data; ++ if (strcmp (child->tag_name, xmp_tag) == 0) { ++ *_xmp_tag = child; ++ ret = g_quark_to_string (GPOINTER_TO_UINT (key)); ++ goto out; ++ } ++ } ++ } else { ++ g_assert_not_reached (); + } + } + +@@ -856,7 +906,6 @@ deserialize_tiff_orientation (XmpTag * xmptag, GstTagList * taglist, + static gpointer + _init_xmp_tag_map (gpointer user_data) + { +- GPtrArray *array; + XmpTag *xmpinfo; + GstXmpSchema *schema; + +@@ -868,136 +917,95 @@ _init_xmp_tag_map (gpointer user_data) + */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_ARTIST, +- "dc:creator", GST_XMP_TAG_TYPE_SEQ, NULL, NULL); ++ "dc:creator", GstXmpTagTypeSeq, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_COPYRIGHT, +- "dc:rights", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "dc:rights", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE, "dc:date", +- GST_XMP_TAG_TYPE_SEQ, NULL, NULL); ++ GstXmpTagTypeSeq, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DESCRIPTION, +- "dc:description", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "dc:description", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_KEYWORDS, +- "dc:subject", GST_XMP_TAG_TYPE_BAG, NULL, NULL); ++ "dc:subject", GstXmpTagTypeBag, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_TITLE, "dc:title", +- GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ GstXmpTagTypeSimple, NULL, NULL); + /* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */ + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_VIDEO_CODEC, +- "dc:format", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "dc:format", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_add_schema ("dc", schema); + + /* xap (xmp) schema */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING, +- "xmp:Rating", GST_XMP_TAG_TYPE_SIMPLE, NULL, deserialize_xmp_rating); ++ "xmp:Rating", GstXmpTagTypeSimple, NULL, deserialize_xmp_rating); + _gst_xmp_add_schema ("xap", schema); + + /* tiff */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, +- GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GST_XMP_TAG_TYPE_SIMPLE, NULL, ++ GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GstXmpTagTypeSimple, NULL, + NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MODEL, +- "tiff:Model", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "tiff:Model", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_APPLICATION_NAME, +- "tiff:Software", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "tiff:Software", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_IMAGE_ORIENTATION, +- "tiff:Orientation", GST_XMP_TAG_TYPE_SIMPLE, serialize_tiff_orientation, ++ "tiff:Orientation", GstXmpTagTypeSimple, serialize_tiff_orientation, + deserialize_tiff_orientation); + _gst_xmp_add_schema ("tiff", schema); + + /* exif schema */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME, +- "exif:DateTimeOriginal", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "exif:DateTimeOriginal", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_LATITUDE, "exif:GPSLatitude", +- GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_latitude, +- deserialize_exif_latitude); ++ GstXmpTagTypeSimple, serialize_exif_latitude, deserialize_exif_latitude); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_LONGITUDE, +- "exif:GPSLongitude", GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_longitude, ++ "exif:GPSLongitude", GstXmpTagTypeSimple, serialize_exif_longitude, + deserialize_exif_longitude); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, "exif:ExposureBiasValue", +- GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ GstXmpTagTypeSimple, NULL, NULL); + + /* compound exif tags */ +- array = g_ptr_array_sized_new (2); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSAltitude"; +- xmpinfo->serialize = serialize_exif_altitude; +- xmpinfo->deserialize = deserialize_exif_altitude; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSAltitudeRef"; +- xmpinfo->serialize = serialize_exif_altituderef; +- xmpinfo->deserialize = deserialize_exif_altitude; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- _gst_xmp_schema_add_mapping (schema, GST_TAG_GEO_LOCATION_ELEVATION, array); +- +- array = g_ptr_array_sized_new (2); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSSpeed"; +- xmpinfo->serialize = serialize_exif_gps_speed; +- xmpinfo->deserialize = deserialize_exif_gps_speed; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSSpeedRef"; +- xmpinfo->serialize = serialize_exif_gps_speedref; +- xmpinfo->deserialize = deserialize_exif_gps_speed; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- _gst_xmp_schema_add_mapping (schema, +- GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, array); +- +- array = g_ptr_array_sized_new (2); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSTrack"; +- xmpinfo->serialize = serialize_exif_gps_direction; +- xmpinfo->deserialize = deserialize_exif_gps_track; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSTrackRef"; +- xmpinfo->serialize = serialize_exif_gps_directionref; +- xmpinfo->deserialize = deserialize_exif_gps_track; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- _gst_xmp_schema_add_mapping (schema, +- GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, array); ++ xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_ELEVATION, ++ "exif:GPSAltitude", "exif:GPSAltitudeRef", serialize_exif_altitude, ++ serialize_exif_altituderef, deserialize_exif_altitude); ++ _gst_xmp_schema_add_mapping (schema, xmpinfo); ++ ++ xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, ++ "exif:GPSSpeed", "exif:GPSSpeedRef", serialize_exif_gps_speed, ++ serialize_exif_gps_speedref, deserialize_exif_gps_speed); ++ _gst_xmp_schema_add_mapping (schema, xmpinfo); ++ ++ xmpinfo = ++ gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, ++ "exif:GPSTrack", "exif:GPSTrackRef", serialize_exif_gps_direction, ++ serialize_exif_gps_directionref, deserialize_exif_gps_track); ++ _gst_xmp_schema_add_mapping (schema, xmpinfo); ++ ++ xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, ++ "exif:GPSImgDirection", "exif:GPSImgDirectionRef", ++ serialize_exif_gps_direction, serialize_exif_gps_directionref, ++ deserialize_exif_gps_img_direction); ++ _gst_xmp_schema_add_mapping (schema, xmpinfo); + +- array = g_ptr_array_sized_new (2); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSImgDirection"; +- xmpinfo->serialize = serialize_exif_gps_direction; +- xmpinfo->deserialize = deserialize_exif_gps_img_direction; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- xmpinfo = g_slice_new (XmpTag); +- xmpinfo->tag_name = "exif:GPSImgDirectionRef"; +- xmpinfo->serialize = serialize_exif_gps_directionref; +- xmpinfo->deserialize = deserialize_exif_gps_img_direction; +- xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; +- g_ptr_array_add (array, xmpinfo); +- _gst_xmp_schema_add_mapping (schema, +- GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, array); + _gst_xmp_add_schema ("exif", schema); + + /* photoshop schema */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country", +- GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_CITY, +- "photoshop:City", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ "photoshop:City", GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_add_schema ("photoshop", schema); + + /* iptc4xmpcore schema */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location", +- GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); ++ GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_add_schema ("Iptc4xmpCore", schema); + + return NULL; +@@ -1540,62 +1548,93 @@ gst_value_serialize_xmp (const GValue * value) + } + + static void +-write_one_tag (const GstTagList * list, const gchar * tag, +- GPtrArray * xmp_tag_array, gpointer user_data) ++write_one_tag (const GstTagList * list, XmpTag * xmp_tag, gpointer user_data) + { +- guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index; ++ guint i = 0, ct; + XmpSerializationData *serialization_data = user_data; + GString *data = serialization_data->data; + char *s; + +- for (tag_index = 0; tag_index < xmp_tag_array->len; tag_index++) { +- XmpTag *xmp_tag; ++ /* struct type handled differently */ ++ if (xmp_tag->type == GstXmpTagTypeStruct || ++ xmp_tag->type == GstXmpTagTypeCompound) { ++ GSList *iter; ++ gboolean use_it = FALSE; ++ ++ /* check if any of the inner tags are present on the taglist */ ++ for (iter = xmp_tag->children; iter && !use_it; iter = g_slist_next (iter)) { ++ XmpTag *child_tag = iter->data; + +- xmp_tag = g_ptr_array_index (xmp_tag_array, tag_index); +- string_open_tag (data, xmp_tag->tag_name); ++ if (gst_tag_list_get_value_index (list, child_tag->gst_tag, 0) != NULL) { ++ use_it = TRUE; ++ break; ++ } ++ } + +- /* fast path for single valued tag */ +- if (ct == 1 || xmp_tag->type == GST_XMP_TAG_TYPE_SIMPLE) { ++ if (use_it) { ++ if (xmp_tag->tag_name) ++ string_open_tag (data, xmp_tag->tag_name); ++ /* now write it */ ++ for (iter = xmp_tag->children; iter; iter = g_slist_next (iter)) { ++ write_one_tag (list, iter->data, user_data); ++ } ++ if (xmp_tag->tag_name) ++ string_close_tag (data, xmp_tag->tag_name); ++ } ++ return; ++ } ++ ++ /* at this point we must have a gst_tag */ ++ g_assert (xmp_tag->gst_tag); ++ if (gst_tag_list_get_value_index (list, xmp_tag->gst_tag, 0) == NULL) ++ return; ++ ++ ct = gst_tag_list_get_tag_size (list, xmp_tag->gst_tag); ++ string_open_tag (data, xmp_tag->tag_name); ++ ++ /* fast path for single valued tag */ ++ if (ct == 1 || xmp_tag->type == GstXmpTagTypeSimple) { ++ if (xmp_tag->serialize) { ++ s = xmp_tag->serialize (gst_tag_list_get_value_index (list, ++ xmp_tag->gst_tag, 0)); ++ } else { ++ s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, ++ xmp_tag->gst_tag, 0)); ++ } ++ if (s) { ++ g_string_append (data, s); ++ g_free (s); ++ } else { ++ GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag); ++ } ++ } else { ++ const gchar *typename; ++ ++ typename = xmp_tag_get_type_name (xmp_tag); ++ ++ string_open_tag (data, typename); ++ for (i = 0; i < ct; i++) { ++ GST_DEBUG ("mapping %s[%u/%u] to xmp", xmp_tag->gst_tag, i, ct); + if (xmp_tag->serialize) { +- s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, 0)); ++ s = xmp_tag->serialize (gst_tag_list_get_value_index (list, ++ xmp_tag->gst_tag, i)); + } else { +- s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag, +- 0)); ++ s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, ++ xmp_tag->gst_tag, i)); + } + if (s) { ++ string_open_tag (data, "rdf:li"); + g_string_append (data, s); ++ string_close_tag (data, "rdf:li"); + g_free (s); + } else { +- GST_WARNING ("unhandled type for %s to xmp", tag); +- } +- } else { +- const gchar *typename; +- +- typename = xmp_tag_get_type_name (xmp_tag); +- +- string_open_tag (data, typename); +- for (i = 0; i < ct; i++) { +- GST_DEBUG ("mapping %s[%u/%u] to xmp", tag, i, ct); +- if (xmp_tag->serialize) { +- s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, i)); +- } else { +- s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag, +- i)); +- } +- if (s) { +- string_open_tag (data, "rdf:li"); +- g_string_append (data, s); +- string_close_tag (data, "rdf:li"); +- g_free (s); +- } else { +- GST_WARNING ("unhandled type for %s to xmp", tag); +- } ++ GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag); + } +- string_close_tag (data, typename); + } +- +- string_close_tag (data, xmp_tag->tag_name); ++ string_close_tag (data, typename); + } ++ ++ string_close_tag (data, xmp_tag->tag_name); + } + + /** +@@ -1652,7 +1691,6 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, + /* use all schemas */ + schemas = gst_tag_xmp_list_schemas (); + } +- i = 0; + for (i = 0; schemas[i] != NULL; i++) { + GstXmpSchema *schema = _gst_xmp_get_schema (schemas[i]); + GHashTableIter iter; +@@ -1664,12 +1702,7 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, + /* Iterate over the hashtable */ + g_hash_table_iter_init (&iter, schema); + while (g_hash_table_iter_next (&iter, &key, &value)) { +- const gchar *tag = g_quark_to_string (GPOINTER_TO_UINT (key)); +- +- if (gst_tag_list_get_value_index (list, tag, 0) != NULL) { +- write_one_tag (list, tag, value, (gpointer) & serialization_data); +- } +- ++ write_one_tag (list, value, (gpointer) & serialization_data); + } + } + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0025-tag-xmp-Add-support-for-reading-struct-tags.patch b/gst-plugins-base-subtitles0.10/debian/patches/0025-tag-xmp-Add-support-for-reading-struct-tags.patch new file mode 100644 index 0000000..5be682f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0025-tag-xmp-Add-support-for-reading-struct-tags.patch @@ -0,0 +1,194 @@ +From 6e0213e903e1afe4fc65add8f5e1595057e646a7 Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Tue, 19 Apr 2011 11:00:24 -0300 +Subject: [PATCH] tag: xmp: Add support for reading struct tags + +Adds a context variable that controls if the parsing is on +'top level' tags or inside a struct tag. +--- + gst-libs/gst/tag/gstxmptag.c | 99 ++++++++++++++++++++++++++++++++++-------- + 1 files changed, 81 insertions(+), 18 deletions(-) + +diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c +index 1a6e3c1..296804a 100644 +--- a/gst-libs/gst/tag/gstxmptag.c ++++ b/gst-libs/gst/tag/gstxmptag.c +@@ -170,7 +170,6 @@ xmp_tag_get_type_name (XmpTag * xmptag) + + struct _PendingXmpTag + { +- const gchar *gst_tag; + XmpTag *xmp_tag; + gchar *str; + }; +@@ -1045,11 +1044,14 @@ struct _GstXmpNamespaceMap + /* parsing */ + + static void +-read_one_tag (GstTagList * list, const gchar * tag, XmpTag * xmptag, ++read_one_tag (GstTagList * list, XmpTag * xmptag, + const gchar * v, GSList ** pending_tags) + { + GType tag_type; + GstTagMergeMode merge_mode; ++ const gchar *tag = xmptag->gst_tag; ++ ++ g_return_if_fail (tag != NULL); + + if (xmptag && xmptag->deserialize) { + xmptag->deserialize (xmptag, list, tag, xmptag->tag_name, v, pending_tags); +@@ -1236,10 +1238,12 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + gboolean in_tag; + gchar *part, *pp; + guint i; +- const gchar *last_tag = NULL; + XmpTag *last_xmp_tag = NULL; + GSList *pending_tags = NULL; + ++ /* Used for strucuture xmp tags */ ++ XmpTag *context_tag = NULL; ++ + GstXmpNamespaceMap ns_map[] = { + {"dc", NULL}, + {"exif", NULL}, +@@ -1255,6 +1259,8 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (GST_BUFFER_SIZE (buffer) > 0, NULL); + ++ GST_LOG ("Starting xmp parsing"); ++ + xps = (const gchar *) GST_BUFFER_DATA (buffer); + len = GST_BUFFER_SIZE (buffer); + xpe = &xps[len + 1]; +@@ -1354,19 +1360,41 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + } + } + } else { +- const gchar *gst_tag; + XmpTag *xmp_tag = NULL; + /* FIXME: eventualy rewrite ns + * find ':' + * check if ns before ':' is in ns_map and ns_map[i].gstreamer_ns!=NULL + * do 2 stage filter in tag_matches + */ +- gst_tag = _gst_xmp_tag_get_mapping_reverse (as, &xmp_tag); +- if (gst_tag) { ++ if (context_tag) { ++ GSList *iter; ++ ++ for (iter = context_tag->children; iter; ++ iter = g_slist_next (iter)) { ++ XmpTag *child = iter->data; ++ ++ GST_DEBUG ("Looking at child tag %s : %s", child->tag_name, ++ as); ++ if (strcmp (child->tag_name, as) == 0) { ++ xmp_tag = child; ++ break; ++ } ++ } ++ ++ } else { ++ GST_LOG ("Looking for tag: %s", as); ++ _gst_xmp_tag_get_mapping_reverse (as, &xmp_tag); ++ } ++ if (xmp_tag) { + PendingXmpTag *ptag; + ++ GST_DEBUG ("Found xmp tag: %s -> %s", xmp_tag->tag_name, ++ xmp_tag->gst_tag); ++ ++ /* we shouldn't find a xmp structure here */ ++ g_assert (xmp_tag->gst_tag != NULL); ++ + ptag = g_slice_new (PendingXmpTag); +- ptag->gst_tag = gst_tag; + ptag->xmp_tag = xmp_tag; + ptag->str = g_strdup (v); + +@@ -1393,15 +1421,42 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + + /* skip rdf tags for now */ + if (strncmp (part, "rdf:", 4)) { +- const gchar *parttag; ++ /* if we're inside some struct, we look only on its children */ ++ if (context_tag) { ++ GSList *iter; ++ ++ /* check if this is the closing of the context */ ++ if (part[0] == '/' ++ && strcmp (part + 1, context_tag->tag_name) == 0) { ++ GST_DEBUG ("Closing context tag %s", part); ++ context_tag = NULL; ++ } else { ++ ++ for (iter = context_tag->children; iter; ++ iter = g_slist_next (iter)) { ++ XmpTag *child = iter->data; + +- parttag = _gst_xmp_tag_get_mapping_reverse (part, &last_xmp_tag); +- if (parttag) { +- last_tag = parttag; ++ GST_DEBUG ("Looking at child tag %s : %s", child->tag_name, ++ part); ++ if (strcmp (child->tag_name, part) == 0) { ++ last_xmp_tag = child; ++ break; ++ } ++ } ++ } ++ ++ } else { ++ GST_LOG ("Looking for tag: %s", part); ++ _gst_xmp_tag_get_mapping_reverse (part, &last_xmp_tag); ++ if (last_xmp_tag && last_xmp_tag->type == GstXmpTagTypeStruct) { ++ context_tag = last_xmp_tag; ++ last_xmp_tag = NULL; ++ } + } + } + } + } ++ GST_LOG ("Next cycle"); + /* next cycle */ + ne++; + if (ne < xp2) { +@@ -1421,15 +1476,23 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + if (ns[0] != '\n' && &ns[1] <= ne) { + /* only log non-newline nodes, we still have to parse them */ + GST_INFO ("txt: %s", part); +- if (last_tag) { ++ if (last_xmp_tag) { + PendingXmpTag *ptag; + +- ptag = g_slice_new (PendingXmpTag); +- ptag->gst_tag = last_tag; +- ptag->xmp_tag = last_xmp_tag; +- ptag->str = g_strdup (part); ++ GST_DEBUG ("Found tag %s -> %s", last_xmp_tag->tag_name, ++ last_xmp_tag->gst_tag); ++ ++ if (last_xmp_tag->type == GstXmpTagTypeStruct) { ++ g_assert (context_tag == NULL); /* we can't handle struct nesting currently */ + +- pending_tags = g_slist_append (pending_tags, ptag); ++ context_tag = last_xmp_tag; ++ } else { ++ ptag = g_slice_new (PendingXmpTag); ++ ptag->xmp_tag = last_xmp_tag; ++ ptag->str = g_strdup (part); ++ ++ pending_tags = g_slist_append (pending_tags, ptag); ++ } + } + } + /* next cycle */ +@@ -1444,7 +1507,7 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + + pending_tags = g_slist_delete_link (pending_tags, pending_tags); + +- read_one_tag (list, ptag->gst_tag, ptag->xmp_tag, ptag->str, &pending_tags); ++ read_one_tag (list, ptag->xmp_tag, ptag->str, &pending_tags); + + g_free (ptag->str); + g_slice_free (PendingXmpTag, ptag); diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0026-tag-xmp-Add-Iptc4xmpExt-schema-support.patch b/gst-plugins-base-subtitles0.10/debian/patches/0026-tag-xmp-Add-Iptc4xmpExt-schema-support.patch new file mode 100644 index 0000000..084977a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0026-tag-xmp-Add-Iptc4xmpExt-schema-support.patch @@ -0,0 +1,64 @@ +From ae1068e2e51670519b6730107a724a0d2c354cfd Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Mon, 18 Apr 2011 23:28:13 -0300 +Subject: [PATCH] tag: xmp: Add Iptc4xmpExt schema support + +Adds Iptc4xmpExt schema with country, city and sublocation +tags mapped +--- + gst-libs/gst/tag/gstxmptag.c | 21 +++++++++++++++++++++ + 1 files changed, 21 insertions(+), 0 deletions(-) + +diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c +index 296804a..a85ccf4 100644 +--- a/gst-libs/gst/tag/gstxmptag.c ++++ b/gst-libs/gst/tag/gstxmptag.c +@@ -51,6 +51,7 @@ static const gchar *schema_list[] = { + "exif", + "photoshop", + "Iptc4xmpCore", ++ "Iptc4xmpExt", + NULL + }; + +@@ -1007,6 +1008,24 @@ _init_xmp_tag_map (gpointer user_data) + GstXmpTagTypeSimple, NULL, NULL); + _gst_xmp_add_schema ("Iptc4xmpCore", schema); + ++ /* iptc4xmpext schema */ ++ schema = gst_xmp_schema_new (); ++ xmpinfo = gst_xmp_tag_create (NULL, "Iptc4xmpExt:LocationShown", ++ GstXmpTagTypeStruct, NULL, NULL); ++ xmpinfo->children = g_slist_prepend (xmpinfo->children, ++ gst_xmp_tag_create (GST_TAG_GEO_LOCATION_SUBLOCATION, ++ "LocationDetails:Sublocation", GstXmpTagTypeSimple, NULL, NULL)); ++ xmpinfo->children = ++ g_slist_prepend (xmpinfo->children, ++ gst_xmp_tag_create (GST_TAG_GEO_LOCATION_CITY, ++ "LocationDetails:City", GstXmpTagTypeSimple, NULL, NULL)); ++ xmpinfo->children = ++ g_slist_prepend (xmpinfo->children, ++ gst_xmp_tag_create (GST_TAG_GEO_LOCATION_COUNTRY, ++ "LocationDetails:Country", GstXmpTagTypeSimple, NULL, NULL)); ++ _gst_xmp_schema_add_mapping (schema, xmpinfo); ++ _gst_xmp_add_schema ("Iptc4xmpExt", schema); ++ + return NULL; + } + +@@ -1031,6 +1050,7 @@ static const GstXmpNamespaceMatch ns_match[] = { + {"xap", "http://ns.adobe.com/xap/1.0/"}, + {"photoshop", "http://ns.adobe.com/photoshop/1.0/"}, + {"Iptc4xmpCore", "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"}, ++ {"Iptc4xmpExt", "http://iptc.org/std/Iptc4xmpExt/2008-02-29/"}, + {NULL, NULL} + }; + +@@ -1251,6 +1271,7 @@ gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) + {"xap", NULL}, + {"photoshop", NULL}, + {"Iptc4xmpCore", NULL}, ++ {"Iptc4xmpExt", NULL}, + {NULL, NULL} + }; + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0027-tests-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch b/gst-plugins-base-subtitles0.10/debian/patches/0027-tests-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch new file mode 100644 index 0000000..0fb86e0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0027-tests-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch @@ -0,0 +1,59 @@ +From 20e5394e98aa25abb17838cc5d70fa1035c5fd1d Mon Sep 17 00:00:00 2001 +From: Thiago Santos +Date: Tue, 19 Apr 2011 08:41:53 -0300 +Subject: [PATCH] tests: xmp: New tests for the Iptc4xmpExt tags + +--- + tests/check/libs/tag.c | 15 +++++++++++---- + 1 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c +index c963ce5..555cdb8 100644 +--- a/tests/check/libs/tag.c ++++ b/tests/check/libs/tag.c +@@ -913,12 +913,13 @@ tag_list_equals (GstTagList * taglist, GstTagList * taglist2) + } + + static void +-do_xmp_tag_serialization_deserialization (GstTagList * taglist) ++do_xmp_tag_serialization_deserialization (GstTagList * taglist, ++ const gchar ** schemas) + { + GstTagList *taglist2; + GstBuffer *buf; + +- buf = gst_tag_list_to_xmp_buffer (taglist, TRUE); ++ buf = gst_tag_list_to_xmp_buffer_full (taglist, TRUE, schemas); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + + tag_list_equals (taglist, taglist2); +@@ -935,7 +936,7 @@ do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag, + + gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value); + +- do_xmp_tag_serialization_deserialization (taglist); ++ do_xmp_tag_serialization_deserialization (taglist, NULL); + gst_tag_list_free (taglist); + } + +@@ -1122,13 +1123,19 @@ GST_END_TEST; + + GST_START_TEST (test_xmp_compound_tags) + { ++ const gchar *schemas[] = { "Iptc4xmpExt", NULL }; + GstTagList *taglist = gst_tag_list_new (); + + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1", + GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3", + NULL); ++ do_xmp_tag_serialization_deserialization (taglist, NULL); ++ gst_tag_list_free (taglist); + +- do_xmp_tag_serialization_deserialization (taglist); ++ taglist = gst_tag_list_new (); ++ gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_GEO_LOCATION_COUNTRY, ++ "Brazil", GST_TAG_GEO_LOCATION_CITY, "Campina Grande", NULL); ++ do_xmp_tag_serialization_deserialization (taglist, schemas); + gst_tag_list_free (taglist); + } + diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0028-uridecodebin-remove-some-dead-code.patch b/gst-plugins-base-subtitles0.10/debian/patches/0028-uridecodebin-remove-some-dead-code.patch new file mode 100644 index 0000000..360794c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0028-uridecodebin-remove-some-dead-code.patch @@ -0,0 +1,61 @@ +From ae686aad03ab47762e6aa0017c4f33b5a8791032 Mon Sep 17 00:00:00 2001 +From: Mark Nauwelaerts +Date: Tue, 26 Apr 2011 11:27:40 +0200 +Subject: [PATCH] uridecodebin: remove some dead code + +... which was dead as pads were never added to the list, and need not be added, +since removing them is handled by a pad callback. +--- + gst/playback/gsturidecodebin.c | 19 ------------------- + 1 files changed, 0 insertions(+), 19 deletions(-) + +diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c +index 8c4e3f2..361b164 100644 +--- a/gst/playback/gsturidecodebin.c ++++ b/gst/playback/gsturidecodebin.c +@@ -92,7 +92,6 @@ struct _GstURIDecodeBin + guint have_type_id; /* have-type signal id from typefind */ + GSList *decodebins; + GSList *pending_decodebins; +- GSList *srcpads; + gint numpads; + + /* for dynamic sources */ +@@ -1429,22 +1428,6 @@ remove_decoders (GstURIDecodeBin * bin, gboolean force) + } + + static void +-remove_pads (GstURIDecodeBin * bin) +-{ +- GSList *walk; +- +- for (walk = bin->srcpads; walk; walk = g_slist_next (walk)) { +- GstPad *pad = GST_PAD_CAST (walk->data); +- +- GST_DEBUG_OBJECT (bin, "removing old pad"); +- gst_pad_set_active (pad, FALSE); +- gst_element_remove_pad (GST_ELEMENT_CAST (bin), pad); +- } +- g_slist_free (bin->srcpads); +- bin->srcpads = NULL; +-} +- +-static void + proxy_unknown_type_signal (GstElement * element, GstPad * pad, GstCaps * caps, + GstURIDecodeBin * dec) + { +@@ -2414,14 +2397,12 @@ gst_uri_decode_bin_change_state (GstElement * element, + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG ("paused to ready"); + remove_decoders (decoder, FALSE); +- remove_pads (decoder); + remove_source (decoder); + do_async_done (decoder); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + GST_DEBUG ("ready to null"); + remove_decoders (decoder, TRUE); +- remove_pads (decoder); + remove_source (decoder); + break; + default: diff --git a/gst-plugins-base-subtitles0.10/debian/patches/0029-uridecodebin-use-bitrate-to-configure-streaming-buff.patch b/gst-plugins-base-subtitles0.10/debian/patches/0029-uridecodebin-use-bitrate-to-configure-streaming-buff.patch new file mode 100644 index 0000000..4d91e48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/0029-uridecodebin-use-bitrate-to-configure-streaming-buff.patch @@ -0,0 +1,202 @@ +From 4a8a2fcb49d44cc41e924db3a94bfc8998224744 Mon Sep 17 00:00:00 2001 +From: Mark Nauwelaerts +Date: Tue, 26 Apr 2011 13:37:51 +0200 +Subject: [PATCH] uridecodebin: use bitrate to configure streaming + buffer-duration default case + +In particular, in audio only cases whose (estimated) metadata provides bitrate +information, the buffer-size based on such bitrate (and buffer-duration) +will be much more reasonable than queue2 default buffer-size. +--- + gst/playback/gsturidecodebin.c | 125 +++++++++++++++++++++++++++++++++++++++- + 1 files changed, 123 insertions(+), 2 deletions(-) + +diff --git a/gst/playback/gsturidecodebin.c b/gst/playback/gsturidecodebin.c +index 361b164..6469d90 100644 +--- a/gst/playback/gsturidecodebin.c ++++ b/gst/playback/gsturidecodebin.c +@@ -58,6 +58,12 @@ typedef struct _GstURIDecodeBinClass GstURIDecodeBinClass; + #define GST_URI_DECODE_BIN_LOCK(dec) (g_mutex_lock(GST_URI_DECODE_BIN_GET_LOCK(dec))) + #define GST_URI_DECODE_BIN_UNLOCK(dec) (g_mutex_unlock(GST_URI_DECODE_BIN_GET_LOCK(dec))) + ++typedef struct _GstURIDecodeBinStream ++{ ++ gulong probe_id; ++ guint bitrate; ++} GstURIDecodeBinStream; ++ + /** + * GstURIDecodeBin + * +@@ -92,6 +98,7 @@ struct _GstURIDecodeBin + guint have_type_id; /* have-type signal id from typefind */ + GSList *decodebins; + GSList *pending_decodebins; ++ GHashTable *streams; + gint numpads; + + /* for dynamic sources */ +@@ -938,7 +945,99 @@ source_no_more_pads (GstElement * element, GstURIDecodeBin * bin) + no_more_pads_full (element, FALSE, bin); + } + +-/* Called by the signal handlers when a decodebin has ++static void ++configure_stream_buffering (GstURIDecodeBin * decoder) ++{ ++ GstElement *queue = NULL; ++ GHashTableIter iter; ++ gpointer key, value; ++ gint bitrate = 0; ++ ++ /* automatic configuration enabled ? */ ++ if (decoder->buffer_size != -1) ++ return; ++ ++ GST_URI_DECODE_BIN_LOCK (decoder); ++ if (decoder->queue) ++ queue = gst_object_ref (decoder->queue); ++ ++ g_hash_table_iter_init (&iter, decoder->streams); ++ while (g_hash_table_iter_next (&iter, &key, &value)) { ++ GstURIDecodeBinStream *stream = value; ++ ++ if (stream->bitrate && bitrate >= 0) ++ bitrate += stream->bitrate; ++ else ++ bitrate = -1; ++ } ++ GST_URI_DECODE_BIN_UNLOCK (decoder); ++ ++ GST_DEBUG_OBJECT (decoder, "overall bitrate %d", bitrate); ++ if (!queue) ++ return; ++ ++ if (bitrate > 0) { ++ guint64 time; ++ guint bytes; ++ ++ /* all streams have a bitrate; ++ * configure queue size based on queue duration using combined bitrate */ ++ g_object_get (queue, "max-size-time", &time, NULL); ++ GST_DEBUG_OBJECT (decoder, "queue buffering time %" GST_TIME_FORMAT, ++ GST_TIME_ARGS (time)); ++ if (time > 0) { ++ bytes = gst_util_uint64_scale (time, bitrate, 8 * GST_SECOND); ++ GST_DEBUG_OBJECT (decoder, "corresponds to buffer size %d", bytes); ++ g_object_set (queue, "max-size-bytes", bytes, NULL); ++ } ++ } ++ ++ gst_object_unref (queue); ++} ++ ++static gboolean ++decoded_pad_event_probe (GstPad * pad, GstEvent * event, ++ GstURIDecodeBin * decoder) ++{ ++ GST_LOG_OBJECT (pad, "%s, decoder %p", GST_EVENT_TYPE_NAME (event), decoder); ++ ++ /* look for a bitrate tag */ ++ switch (GST_EVENT_TYPE (event)) { ++ case GST_EVENT_TAG: ++ { ++ GstTagList *list; ++ guint bitrate = 0; ++ GstURIDecodeBinStream *stream; ++ ++ gst_event_parse_tag (event, &list); ++ if (!gst_tag_list_get_uint_index (list, GST_TAG_NOMINAL_BITRATE, 0, ++ &bitrate)) { ++ gst_tag_list_get_uint_index (list, GST_TAG_BITRATE, 0, &bitrate); ++ } ++ GST_DEBUG_OBJECT (pad, "found bitrate %u", bitrate); ++ if (bitrate) { ++ GST_URI_DECODE_BIN_LOCK (decoder); ++ stream = g_hash_table_lookup (decoder->streams, pad); ++ GST_URI_DECODE_BIN_UNLOCK (decoder); ++ if (stream) { ++ stream->bitrate = bitrate; ++ /* no longer need this probe now */ ++ gst_pad_remove_event_probe (pad, stream->probe_id); ++ /* configure buffer if possible */ ++ configure_stream_buffering (decoder); ++ } ++ } ++ break; ++ } ++ default: ++ break; ++ } ++ ++ /* never drop */ ++ return TRUE; ++} ++ ++/* Called by the signal handlers when a decodebin has + * found a new raw pad. + */ + static void +@@ -948,6 +1047,7 @@ new_decoded_pad_cb (GstElement * element, GstPad * pad, gboolean last, + GstPad *newpad; + GstPadTemplate *pad_tmpl; + gchar *padname; ++ GstURIDecodeBinStream *stream; + + GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d", + GST_PAD_NAME (pad), last); +@@ -965,11 +1065,19 @@ new_decoded_pad_cb (GstElement * element, GstPad * pad, gboolean last, + /* store ref to the ghostpad so we can remove it */ + g_object_set_data (G_OBJECT (pad), "uridecodebin.ghostpad", newpad); + ++ /* add event probe to monitor tags */ ++ stream = g_slice_alloc0 (sizeof (GstURIDecodeBinStream)); ++ stream->probe_id = ++ gst_pad_add_event_probe (pad, G_CALLBACK (decoded_pad_event_probe), ++ decoder); ++ GST_URI_DECODE_BIN_LOCK (decoder); ++ g_hash_table_insert (decoder->streams, pad, stream); ++ GST_URI_DECODE_BIN_UNLOCK (decoder); ++ + gst_pad_set_active (newpad, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (decoder), newpad); + } + +- + static gboolean + source_pad_event_probe (GstPad * pad, GstEvent * event, + GstURIDecodeBin * decoder) +@@ -1782,6 +1890,12 @@ could_not_link: + } + } + ++static void ++free_stream (gpointer value) ++{ ++ g_slice_free (GstURIDecodeBinStream, value); ++} ++ + /* remove source and all related elements */ + static void + remove_source (GstURIDecodeBin * bin) +@@ -1815,6 +1929,10 @@ remove_source (GstURIDecodeBin * bin) + gst_bin_remove (GST_BIN_CAST (bin), bin->typefind); + bin->typefind = NULL; + } ++ if (bin->streams) { ++ g_hash_table_destroy (bin->streams); ++ bin->streams = NULL; ++ } + /* Don't loose the SOURCE flag */ + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE); + } +@@ -1909,6 +2027,9 @@ setup_source (GstURIDecodeBin * decoder) + /* remove the old decoders now, if any */ + remove_decoders (decoder, FALSE); + ++ /* stream admin setup */ ++ decoder->streams = g_hash_table_new_full (NULL, NULL, NULL, free_stream); ++ + /* see if the source element emits raw audio/video all by itself, + * if so, we can create streams for the pads and be done with it. + * Also check that is has source pads, if not, we assume it will diff --git a/gst-plugins-base-subtitles0.10/debian/patches/series b/gst-plugins-base-subtitles0.10/debian/patches/series new file mode 100644 index 0000000..6646c05 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/patches/series @@ -0,0 +1,29 @@ +0001-tag-add-new-GstTagReader-interface-to-allow-fine-tun.patch +0002-playback-make-uridecodebin-and-decodebin2-implement-.patch +0003-tagreading-add-tagreadbin-element-for-fast-and-easy-.patch +0004-tagreading-add-gst-tagread-test-app-to-examples.patch +0005-tagreadbin-don-t-try-to-guess-codec-tag-from-NULL-ca.patch +0006-gst-tagread-add-loop-N-command-line-option-to-tagrea.patch +0007-tagreadbin-avoid-deadlock-on-state-change-PAUSED_TO_.patch +0008-Fix-rounding-of-source-width-in-gstvideosink.c.patch +0009-typefind-optimize-MP3-and-MPEG_SYS-typefinding.patch +0010-playbasebin-add-network-queue-support-adding-nw-queu.patch +0011-Startup-benchmarking-test.patch +0012-baseaudiosrc-sink-Change-default-latency-time-to-40m.patch +0013-Install-gst-tagread-example-program.patch +0014-NEON-optimized-version-of-uyvy_to_rgb24-function.patch +0015-ARM-NEON-optimized-version-of-uyvy422_to_yuv420p-fun.patch +0016-typefinding-workaround-for-hangs-with-ID3-tagged-m4a.patch +0017-typefinding-extend-workaround-to-ID3-tagged-ASF-WAV-.patch +0018-tagreading-fix-unknown-codec-tag-missing-after-first.patch +0019-xvimagesink-add-disable-colorkey-property-Maemo-spec.patch +0020-xvimagesink-Add-property-for-the-XV_STACKING-port-at.patch +0021-Fix-libgstpbutils-libgstvideo-linking.patch +0022-tag-xmp-Write-the-same-tag-to-all-schemas.patch +0023-tag-xmp-Fixing-schema-maps.patch +0024-tag-xmp-Add-struct-xmp-tag-type-support.patch +0025-tag-xmp-Add-support-for-reading-struct-tags.patch +0026-tag-xmp-Add-Iptc4xmpExt-schema-support.patch +0027-tests-xmp-New-tests-for-the-Iptc4xmpExt-tags.patch +0028-uridecodebin-remove-some-dead-code.patch +0029-uridecodebin-use-bitrate-to-configure-streaming-buff.patch diff --git a/gst-plugins-base-subtitles0.10/debian/rules b/gst-plugins-base-subtitles0.10/debian/rules new file mode 100755 index 0000000..2207703 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/rules @@ -0,0 +1,198 @@ +#!/usr/bin/make -f + +-include /usr/share/cdbs/1/rules/debhelper.mk +-include /usr/share/cdbs/1/rules/simple-patchsys.mk +-include /usr/share/cdbs/1/class/gnome.mk +-include /usr/share/cdbs/1/rules/utils.mk + +LDFLAGS += -Wl,-z,defs -Wl,-O1 -Wl,--as-needed + +CFLAGS += -Wno-error + +ifneq (,$(filter noopt,$(DEB_BUILD_OPTIONS))) + CFLAGS += -O0 +else + CFLAGS += -O2 +endif + +ifneq (,$(findstring nodocs,$(DEB_BUILD_OPTIONS))) + DEB_CONFIGURE_EXTRA_FLAGS += --disable-gtk-doc --disable-docbook + common-install-indep:: + mkdir -p debian/tmp/usr/share/gtk-doc +else + DEB_CONFIGURE_EXTRA_FLAGS += --enable-gtk-doc --enable-docbook +endif + +ifeq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) + CFLAGS += -DG_DISABLE_CAST_CHECKS -DGST_DISABLE_GST_DEBUG=1 + DEB_CONFIGURE_EXTRA_FLAGS += --enable-glib-asserts=no +else + DEB_CONFIGURE_EXTRA_FLAGS += --enable-glib-asserts=yes +endif + +ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + NUMJOBS = $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) + MAKEFLAGS += -j$(NUMJOBS) +endif + +DEB_MAKE_CHECK_TARGET = check GST_CHECKS=disable ORC_CODE=debug || true + +# upstream version with epoch +gst_version := $(shell echo $(DEB_VERSION) | cut -d '-' -f 1) +gst_major := 0 +gst_minor := 10 +gst_abi := $(gst_major).$(gst_minor) +# gstreamer library package names +gst_lib := libgstreamer$(gst_abi)-0 +gst_lib_dev := libgstreamer$(gst_abi)-dev +# what gstreamer version is needed +gst_lib_dev_dep := $(gst_lib_dev) (>= 0.10.22) + +gst_pkgname := gstreamer$(gst_abi) +gst_deb_abi := $(gst_abi)-0 + +# gst-plugins-base library package names +gst_plugins_base_lib := libgstreamer-plugins-base$(gst_deb_abi) +gst_plugins_base_lib_dev := libgstreamer-plugins-base$(gst_abi)-dev +# gst-plugins-base library shlibs +gst_plugins_base_lib_dep := "$(gst_plugins_base_lib) (>= $(gst_version))" + +# debug package +DEB_DH_STRIP_ARGS += --dbg-package=$(gst_pkgname)-plugins-base-dbg + +DEB_COMPRESS_EXCLUDE = .sgml .devhelp .ps .pdf + +# The plugins are basically the same. +# Link special names to a template file. +# still need "*.install" to be done by hand + +PLUGINS += plugins-base x alsa plugins-base-extra plugins-base-subtitles +VERSIONIZE += \ + plugins-base-apps.install \ + plugins-base-apps.manpages \ + plugins-base-doc.install \ + +# setup links for packages +pre-build:: + for p in $(PLUGINS); do \ + rm -f debian/$(gst_pkgname)-$$p.install; \ + cat debian/gstreamer-$$p.install | \ + sed 's/@GST_ABI@/$(gst_abi)/g' \ + >debian/$(gst_pkgname)-$$p.install; \ + done + for f in $(VERSIONIZE); do \ + cat debian/gstreamer-$$f | \ + sed 's/@GST_ABI@/$(gst_abi)/g' \ + >debian/$(gst_pkgname)-$$f; \ + done + rm -f debian/libgstreamer-plugins-base$(gst_deb_abi).install + cat debian/libgstreamer-plugins-base.install | \ + sed 's/@GST_ABI@/$(gst_abi)/g' \ + >debian/libgstreamer-plugins-base$(gst_deb_abi).install + rm -f debian/libgstreamer-plugins-base$(gst_abi)-dev.install + cat debian/libgstreamer-plugins-base-dev.install | \ + sed 's/@GST_ABI@/$(gst_abi)/g' \ + >debian/libgstreamer-plugins-base$(gst_abi)-dev.install + +maint: debian/control + +debian/stamp-autogen: + ./autogen.sh --noconfigure + touch $@ + +post-patches:: debian/stamp-autogen + +debian/control:: debian/control.in debian/rules debian/changelog force + cat debian/control.in | \ + sed 's/@GST_VERSION@/$(gst_version)/g' | \ + sed 's/@GST_ABI@/$(gst_abi)/g' | \ + sed 's/@GST_PKGNAME@/$(gst_pkgname)/g' | \ + sed 's/@GST_LIB@/$(gst_lib)/g' | \ + sed 's/@GST_LIB_DEV@/$(gst_lib_dev)/g' | \ + sed 's/@GST_LIB_DEV_DEP@/$(gst_lib_dev_dep)/g' | \ + sed 's/@GST_PLUGINS_BASE_LIB@/$(gst_plugins_base_lib)/g' | \ + sed 's/@GST_PLUGINS_BASE_LIB_DEV@/$(gst_plugins_base_lib_dev)/g' >$@ + +DEB_CONFIGURE_EXTRA_FLAGS += \ + --enable-introspection=no \ + --disable-nls \ + --enable-debug \ + --enable-experimental \ + --with-audioresample-format=int \ + --with-package-name=$(GST_PACKAGE_NAME) \ + --with-package-origin=$(GST_PACKAGE_ORIGIN) \ + --with-install-plugins-helper="/usr/bin/gstreamer-codec-install" + +clean:: + # get rid of the symlinks + for i in $(PLUGINS); do \ + rm -f debian/$(gst_pkgname)-$$i.install; \ + rm -f debian/$(gst_pkgname)-$$i.preinst; \ + done + for f in $(VERSIONIZE); do \ + rm -f debian/$(gst_pkgname)-$$f; \ + done + rm -f debian/libgstreamer-plugins-base$(gst_deb_abi).install + rm -f debian/libgstreamer-plugins-base$(gst_abi)-dev.install + +binary-post-install/$(gst_pkgname)-plugins-base-apps:: + dh_perl + +DEB_DH_MAKESHLIBS_ARGS_$(gst_plugins_base_lib) += -V $(gst_plugins_base_lib_dep) -- -c4 +DEB_INSTALL_DOCS_ALL += debian/README.Debian NEWS +DEB_SHLIBDEPS_INCLUDE += debian/libgstreamer-plugins-base$(gst_deb_abi)/usr/lib +# Disable inclusion of large upstream ChangeLog +DEB_INSTALL_CHANGELOGS_ALL := + +# override shlibs for libraries from this source before computing dependencies +# of packages generated from this source; we already have inter-dependencies +# expressed manually in the control file, we do not need the shlibs to add +# duplicates +# (this rule runs just before the dh_shlibdeps) +common-binary-fixup-arch:: + mkdir -p $(CURDIR)/fake-home + HOME=$(CURDIR)/fake-home \ + LD_LIBRARY_PATH=debian/libgstreamer-plugins-base0.10-0/usr/lib:$(LD_LIBRARY_PATH) \ + dh_gstscancodecs + -rm -f debian/shlibs.local + rm -rf $(CURDIR)/fake-home + cat debian/*/DEBIAN/shlibs | \ + sed -n -r -e 's/(([^ ]+: )?([^ ]+) ([^ ]+)) .*/\1/p' \ + >debian/shlibs.local + +# (this rules runs just after the dh_shlibdeps) +common-binary-predeb-arch:: + -rm -f debian/shlibs.local + +force: + +.PHONY: maint force + +UPSTREAM_REF=master +PATCHES_REF=maemo-patches + +update-patch-series: + mkdir -p $(CURDIR)/debian/patches + rm -f $(CURDIR)/debian/patches/*.patch + git format-patch -N -o $(CURDIR)/debian/patches $(PATCHES_REF) ^$(UPSTREAM_REF) | \ + xargs -n 1 basename > $(CURDIR)/debian/patches/series + for patch in $$(ls $(CURDIR)/debian/patches/*.patch) ; \ + do \ + lines=$$(cat $$patch | wc -l) ; \ + head -n $$(($$lines - 3)) $$patch > $${patch}.chomped ; \ + mv $${patch}.chomped $$patch ; \ + done + +update-common: COMMIT = $(shell git rev-parse $(shell git rev-parse --verify MERGE_HEAD || git merge-base $(UPSTREAM_REF) HEAD):common) +update-common: + @if ! git diff-files --ignore-submodules --quiet common || \ + ! git diff-index --ignore-submodules --cached --quiet HEAD -- common; then \ + echo "your common/ directory state is dirty"; \ + exit 1; \ + fi + if test -d $(CURDIR)/common ; then rm -rfv $(CURDIR)/common ; git rm -r --cached --ignore-unmatch $(CURDIR)/common ; fi + git clone -n git://anongit.freedesktop.org/gstreamer/common $(CURDIR)/common + cd $(CURDIR)/common && git checkout -f $(COMMIT) + rm -rfv $(CURDIR)/common/.git + git add $(CURDIR)/common + @echo "common update staged, git commit to proceed" diff --git a/gst-plugins-base-subtitles0.10/debian/watch b/gst-plugins-base-subtitles0.10/debian/watch new file mode 100644 index 0000000..9a09b96 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/debian/watch @@ -0,0 +1,2 @@ +version=2 +http://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-(0\.10\..*)\.tar\.gz diff --git a/gst-plugins-base-subtitles0.10/docs/.gitignore b/gst-plugins-base-subtitles0.10/docs/.gitignore new file mode 100644 index 0000000..e5a7abe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/.gitignore @@ -0,0 +1 @@ +version.entities diff --git a/gst-plugins-base-subtitles0.10/docs/Makefile.am b/gst-plugins-base-subtitles0.10/docs/Makefile.am new file mode 100644 index 0000000..b0d55f4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/Makefile.am @@ -0,0 +1,18 @@ +if ENABLE_GTK_DOC +if ENABLE_PLUGIN_DOCS +PLUGIN_DOCS_DIRS = plugins +else +PLUGIN_DOCS_DIRS = +endif +else +PLUGIN_DOCS_DIRS = plugins +endif + +SUBDIRS = design libs $(PLUGIN_DOCS_DIRS) +DIST_SUBDIRS = design libs plugins + +EXTRA_DIST = \ + version.entities.in + +upload: + @if test "x$(SUBDIRS)" != x; then for a in $(SUBDIRS); do cd $$a; make upload; cd ..; done; fi diff --git a/gst-plugins-base-subtitles0.10/docs/design/Makefile.am b/gst-plugins-base-subtitles0.10/docs/design/Makefile.am new file mode 100644 index 0000000..357af4c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/Makefile.am @@ -0,0 +1,11 @@ +SUBDIRS = + + +EXTRA_DIST = \ + design-audiosinks.txt \ + design-decodebin.txt \ + design-encoding.txt \ + design-orc-integration.txt \ + draft-keyframe-force.txt \ + draft-va.txt \ + part-playbin2.txt diff --git a/gst-plugins-base-subtitles0.10/docs/design/design-audiosinks.txt b/gst-plugins-base-subtitles0.10/docs/design/design-audiosinks.txt new file mode 100644 index 0000000..0a84a98 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/design-audiosinks.txt @@ -0,0 +1,138 @@ +Audiosink design +---------------- + +Requirements: + + - must operate chain based. + Most simple playback pipelines will push audio from the decoders + into the audio sink. + + - must operate getrange based + Most professional audio applications will operate in a mode where + the audio sink pulls samples from the pipeline. This is typically + done in a callback from the audiosink requesting N samples. The + callback is either scheduled from a thread or from an interrupt + from the audio hardware device. + + - Exact sample accurate clocks. + the audiosink must be able to provide a clock that is sample + accurate even if samples are dropped or when discontinuities are + found in the stream. + + - Exact timing of playback. + The audiosink must be able to play samples at their exact times. + + - use DMA access when possible. + When the hardware can do DMA we should use it. This should also + work over bufferpools to avoid data copying to/from kernel space. + + +Design: + + The design is based on a set of base classes and the concept of a + ringbuffer of samples. + + +-----------+ - provide preroll, rendering, timing + + basesink + - caps nego + +-----+-----+ + | + +-----V----------+ - manages ringbuffer + + baseaudiosink + - manages scheduling (push/pull) + +-----+----------+ - manages clock/query/seek + | - manages scheduling of samples in the ringbuffer + | - manages caps parsing + | + +-----V------+ - default ringbuffer implementation with a GThread + + audiosink + - subclasses provide open/read/close methods + +------------+ + + The ringbuffer is a contiguous piece of memory divided into segtotal + pieces of segments. Each segment has segsize bytes. + + play position + v + +---+---+---+-------------------------------------+----------+ + + 0 | 1 | 2 | .... | segtotal | + +---+---+---+-------------------------------------+----------+ + <---> + segsize bytes = N samples * bytes_per_sample. + + + The ringbuffer has a play position, which is expressed in + segments. The play position is where the device is currently reading + samples from the buffer. + + The ringbuffer can be put to the PLAYING or STOPPED state. + + In the STOPPED state no samples are played to the device and the play + pointer does not advance. + + In the PLAYING state samples are written to the device and the ringbuffer + should call a configurable callback after each segment is written to the + device. In this state the play pointer is advanced after each segment is + written. + + A write operation to the ringbuffer will put new samples in the ringbuffer. + If there is not enough space in the ringbuffer, the write operation will + block. The playback of the buffer never stops, even if the buffer is + empty. When the buffer is empty, silence is played by the device. + + The ringbuffer is implemented with lockfree atomic operations, especially + on the reading side so that low-latency operations are possible. + + Whenever new samples are to be put into the ringbuffer, the position of the + read pointer is taken. The required write position is taken and the diff + is made between the required qnd actual position. If the defference is <0, + the sample is too late. If the difference is bigger than segtotal, the + writing part has to wait for the play pointer to advance. + + +Scheduling: + + - chain based mode: + + In chain based mode, bytes are written into the ringbuffer. This operation + will eventually block when the ringbuffer is filled. + + When no samples arrive in time, the ringbuffer will play silence. Each + buffer that arrives will be placed into the ringbuffer at the correct + times. This means that dropping samples or inserting silence is done + automatically and very accurate and independend of the play pointer. + + In this mode, the ringbuffer is usually kept as full as possible. When + using a small buffer (small segsize and segtotal), the latency for audio + to start from the sink to when it is played can be kept low but at least + one context switch has to be made between read and write. + + - getrange based mode + + In getrange based mode, the baseaudiosink will use the callback function + of the ringbuffer to get a segsize samples from the peer element. These + samples will then be placed in the ringbuffer at the next play position. + It is assumed that the getrange function returns fast enough to fill the + ringbuffer before the play pointer reaches the write pointer. + + In this mode, the ringbuffer is usually kept as empty as possible. There + is no context switch needed between the elements that create the samples + and the actual writing of the samples to the device. + + +DMA mode: + + - Elements that can do DMA based access to the audio device have to subclass + from the GstBaseAudioSink class and wrap the DMA ringbuffer in a subclass + of GstRingBuffer. + + The ringbuffer subclass should trigger a callback after writing or playing + each sample to the device. This callback can be triggered from a thread or + from a signal from the audio device. + + +Clocks: + + The GstBaseAudioSink class will use the ringbuffer to act as a clock provider. + It can do this by using the play pointer and the delay to calculate the + clock time. + + + diff --git a/gst-plugins-base-subtitles0.10/docs/design/design-decodebin.txt b/gst-plugins-base-subtitles0.10/docs/design/design-decodebin.txt new file mode 100644 index 0000000..3491945 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/design-decodebin.txt @@ -0,0 +1,205 @@ +Decodebin design + +GstDecodeBin +------------ + +Description: + + Autoplug and decode to raw media + + Input : single pad with ANY caps Output : Dynamic pads + +* Contents + + _ a GstTypeFindElement connected to the single sink pad + + _ optionnaly a demuxer/parser + + _ optionnaly one or more DecodeGroup + +* Autoplugging + + The goal is to reach 'target' caps (by default raw media). + + This is done by using the GstCaps of a source pad and finding the available +demuxers/decoders GstElement that can be linked to that pad. + + The process starts with the source pad of typefind and stops when no more +non-target caps are left. It is commonly done while pre-rolling, but can also +happen whenever a new pad appears on any element. + + Once a target caps has been found, that pad is ghosted and the +'new-decoded-pad' signal is emitted. + + If no compatible elements can be found for a GstCaps, the pad is ghosted and +the 'unknown-type' signal is emitted. + + +* Assisted auto-plugging + + When starting the auto-plugging process for a given GstCaps, two signals are +emitted in the following way in order to allow the application/user to assist or +fine-tune the process. + + _ 'autoplug-continue' : + + gboolean user_function (GstElement * decodebin, GstPad *pad, GstCaps * caps) + + This signal is fired at the very beginning with the source pad GstCaps. If + the callback returns TRUE, the process continues normally. If the callback + returns FALSE, then the GstCaps are considered as a target caps and the + autoplugging process stops. + + - 'autoplug-factories' : + + GValueArray user_function (GstElement* decodebin, GstPad* pad, + GstCaps* caps); + + Get a list of elementfactories for @pad with @caps. This function is used to + instruct decodebin2 of the elements it should try to autoplug. The default + behaviour when this function is not overridern is to get all elements that + can handle @caps from the registry sorted by rank. + + - 'autoplug-select' : + + gint user_function (GstElement* decodebin, GstPad* pad, GstCaps* caps, + GValueArray* factories); + + This signal is fired once autoplugging has got a list of compatible + GstElementFactory. The signal is emitted with the GstCaps of the source pad + and a pointer on the GValueArray of compatible factories. + + The callback should return the index of the elementfactory in @factories + that should be tried next. + + If the callback returns -1, the autoplugging process will stop as if no + compatible factories were found. + + The default implementation of this function will try to autoplug the first + factory of the list. + +* Target Caps + + The target caps are a read/write GObject property of decodebin. + + By default the target caps are: + + _ Raw audio : audio/x-raw-int, audio/x-raw-float + + _ and raw video : video/x-raw-rgb, video/x-raw-yuv + + _ and Text : text/plain, text/x-pango-markup + + +* media chain/group handling + + When autoplugging, all streams coming out of a demuxer will be grouped in a +DecodeGroup. + + All new source pads created on that demuxer after it has emitted the +'no-more-pads' signal will be put in another DecodeGroup. + + Only one decodegroup can be active at any given time. If a new decodegroup is +created while another one exists, that decodegroup will be set as blocking until +the existing one has drained. + + + +DecodeGroup +----------- + +Description: + + Streams belonging to the same group/chain of a media file. + +* Contents + + The DecodeGroup contains: + + _ a GstMultiQueue to which all streams of a the media group are connected. + + _ the eventual decoders which are autoplugged in order to produce the + requested target pads. + +* Proper group draining + + The DecodeGroup takes care that all the streams in the group are completely +drained (EOS has come through all source ghost pads). + +* Pre-roll and block + + The DecodeGroup has a global blocking feature. If enabled, all the ghosted +source pads for that group will be blocked. + + A method is available to unblock all blocked pads for that group. + + + +GstMultiQueue +------------- + +Description: + + Multiple input-output data queue + + The GstMultiQueue achieves the same functionnality as GstQueue, with a few +differences: + + * Multiple streams handling. + + The element handles queueing data on more than one stream at once. To + achieve such a feature it has request sink pads (sink_%d) and 'sometimes' src + pads (src_%d). + + When requesting a given sinkpad, the associated srcpad for that stream will + be created. Ex: requesting sink_1 will generate src_1. + + + * Non-starvation on multiple streams. + + If more than one stream is used with the element, the streams' queues will + be dynamically grown (up to a limit), in order to ensure that no stream is + risking data starvation. This guarantees that at any given time there are at + least N bytes queued and available for each individual stream. + + If an EOS event comes through a srcpad, the associated queue should be + considered as 'not-empty' in the queue-size-growing algorithm. + + + * Non-linked srcpads graceful handling. + + A GstTask is started for all srcpads when going to GST_STATE_PAUSED. + + The task are blocking against a GCondition which will be fired in two + different cases: + + _ When the associated queue has received a buffer. + + _ When the associated queue was previously declared as 'not-linked' and the + first buffer of the queue is scheduled to be pushed synchronously in + relation to the order in which it arrived globally in the element (see + 'Synchronous data pushing' below). + + When woken up by the GCondition, the GstTask will try to push the next + GstBuffer/GstEvent on the queue. If pushing the GstBuffer/GstEvent returns + GST_FLOW_NOT_LINKED, then the associated queue is marked as 'not-linked'. If + pushing the GstBuffer/GstEvent succeeded the queue will no longer be marked as + 'not-linked'. + + If pushing on all srcpads returns GstFlowReturn different from GST_FLOW_OK, + then all the srcpads' tasks are stopped and subsequent pushes on sinkpads will + return GST_FLOW_NOT_LINKED. + + * Synchronous data pushing for non-linked pads. + + In order to better support dynamic switching between streams, the multiqueue + (unlike the current GStreamer queue) continues to push buffers on non-linked + pads rather than shutting down. + + In addition, to prevent a non-linked stream from very quickly consuming all + available buffers and thus 'racing ahead' of the other streams, the element + must ensure that buffers and inlined events for a non-linked stream are pushed + in the same order as they were received, relative to the other streams + controlled by the element. This means that a buffer cannot be pushed to a + non-linked pad any sooner than buffers in any other stream which were received + before it. diff --git a/gst-plugins-base-subtitles0.10/docs/design/design-encoding.txt b/gst-plugins-base-subtitles0.10/docs/design/design-encoding.txt new file mode 100644 index 0000000..dda79ad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/design-encoding.txt @@ -0,0 +1,571 @@ +Encoding and Muxing +------------------- + +Summary +------- + A. Problems + B. Goals + 1. EncodeBin + 2. Encoding Profile System + 3. Helper Library for Profiles + I. Use-cases researched + + +A. Problems this proposal attempts to solve +------------------------------------------- + +* Duplication of pipeline code for gstreamer-based applications + wishing to encode and or mux streams, leading to subtle differences + and inconsistencies accross those applications. + +* No unified system for describing encoding targets for applications + in a user-friendly way. + +* No unified system for creating encoding targets for applications, + resulting in duplication of code accross all applications, + differences and inconsistencies that come with that duplication, + and applications hardcoding element names and settings resulting in + poor portability. + + + +B. Goals +-------- + +1. Convenience encoding element + + Create a convenience GstBin for encoding and muxing several streams, + hereafter called 'EncodeBin'. + + This element will only contain one single property, which is a + profile. + +2. Define a encoding profile system + +2. Encoding profile helper library + + Create a helper library to: + * create EncodeBin instances based on profiles, and + * help applications to create/load/save/browse those profiles. + + + + +1. EncodeBin +------------ + +1.1 Proposed API +---------------- + + EncodeBin is a GstBin subclass. + + It implements the GstTagSetter interface, by which it will proxy the + calls to the muxer. + + Only two introspectable property (i.e. usable without extra API): + * A GstEncodingProfile* + * The name of the profile to use + + When a profile is selected, encodebin will: + * Add REQUEST sinkpads for all the GstStreamProfile + * Create the muxer and expose the source pad + + Whenever a request pad is created, encodebin will: + * Create the chain of elements for that pad + * Ghost the sink pad + * Return that ghost pad + + This allows reducing the code to the minimum for applications + wishing to encode a source for a given profile: + + ... + + encbin = gst_element_factory_make("encodebin, NULL); + g_object_set (encbin, "profile", "N900/H264 HQ", NULL); + gst_element_link (encbin, filesink); + + ... + + vsrcpad = gst_element_get_src_pad(source, "src1"); + vsinkpad = gst_element_get_request_pad (encbin, "video_%d"); + gst_pad_link(vsrcpad, vsinkpad); + + ... + + +1.2 Explanation of the Various stages in EncodeBin +-------------------------------------------------- + + This describes the various stages which can happen in order to end + up with a multiplexed stream that can then be stored or streamed. + +1.2.1 Incoming streams + + The streams fed to EncodeBin can be of various types: + + * Video + * Uncompressed (but maybe subsampled) + * Compressed + * Audio + * Uncompressed (audio/x-raw-{int|float}) + * Compressed + * Timed text + * Private streams + + +1.2.2 Steps involved for raw video encoding + +(0) Incoming Stream + +(1) Transform raw video feed (optional) + + Here we modify the various fundamental properties of a raw video + stream to be compatible with the intersection of: + * The encoder GstCaps and + * The specified "Stream Restriction" of the profile/target + + The fundamental properties that can be modified are: + * width/height + This is done with a video scaler. + The DAR (Display Aspect Ratio) MUST be respected. + If needed, black borders can be added to comply with the target DAR. + * framerate + * format/colorspace/depth + All of this is done with a colorspace converter + +(2) Actual encoding (optional for raw streams) + + An encoder (with some optional settings) is used. + +(3) Muxing + + A muxer (with some optional settings) is used. + +(4) Outgoing encoded and muxed stream + + +1.2.3 Steps involved for raw audio encoding + + This is roughly the same as for raw video, expect for (1) + +(1) Transform raw audo feed (optional) + + We modify the various fundamental properties of a raw audio stream to + be compatible with the intersection of: + * The encoder GstCaps and + * The specified "Stream Restriction" of the profile/target + + The fundamental properties that can be modifier are: + * Number of channels + * Type of raw audio (integer or floating point) + * Depth (number of bits required to encode one sample) + + +1.2.4 Steps involved for encoded audio/video streams + + Steps (1) and (2) are replaced by a parser if a parser is available + for the given format. + + +1.2.5 Steps involved for other streams + + Other streams will just be forwarded as-is to the muxer, provided the + muxer accepts the stream type. + + + + +2. Encoding Profile System +-------------------------- + + This work is based on: + * The existing GstPreset system for elements [0] + * The gnome-media GConf audio profile system [1] + * The investigation done into device profiles by Arista and + Transmageddon [2 and 3] + +2.2 Terminology +--------------- + +* Encoding Target Category + A Target Category is a classification of devices/systems/use-cases + for encoding. + + Such a classification is required in order for: + * Applications with a very-specific use-case to limit the number of + profiles they can offer the user. A screencasting application has + no use with the online services targets for example. + * Offering the user some initial classification in the case of a + more generic encoding application (like a video editor or a + transcoder). + + Ex: + Consumer devices + Online service + Intermediate Editing Format + Screencast + Capture + Computer + +* Encoding Profile Target + A Profile Target describes a specific entity for which we wish to + encode. + A Profile Target must belong to at least one Target Category. + It will define at least one Encoding Profile. + + Ex (with category): + Nokia N900 (Consumer device) + Sony PlayStation 3 (Consumer device) + Youtube (Online service) + DNxHD (Intermediate editing format) + HuffYUV (Screencast) + Theora (Computer) + +* Encoding Profile + A specific combination of muxer, encoders, presets and limitations. + + Ex: + Nokia N900/H264 HQ + Ipod/High Quality + DVD/Pal + Youtube/High Quality + HTML5/Low Bandwith + DNxHD + +2.3 Encoding Profile +-------------------- + +An encoding profile requires the following information: + + * Name + This string is not translatable and must be unique. + A recommendation to guarantee uniqueness of the naming could be: + / + * Description + This is a translatable string describing the profile + * Muxing format + This is a string containing the GStreamer media-type of the + container format. + * Muxing preset + This is an optional string describing the preset(s) to use on the + muxer. + * Multipass setting + This is a boolean describing whether the profile requires several + passes. + * List of Stream Profile + +2.3.1 Stream Profiles + +A Stream Profile consists of: + + * Type + The type of stream profile (audio, video, text, private-data) + * Encoding Format + This is a string containing the GStreamer media-type of the encoding + format to be used. If encoding is not to be applied, the raw audio + media type will be used. + * Encoding preset + This is an optional string describing the preset(s) to use on the + encoder. + * Restriction + This is an optional GstCaps containing the restriction of the + stream that can be fed to the encoder. + This will generally containing restrictions in video + width/heigh/framerate or audio depth. + * presence + This is an integer specifying how many streams can be used in the + containing profile. 0 means that any number of streams can be + used. + * pass + This is an integer which is only meaningful if the multipass flag + has been set in the profile. If it has been set it indicates which + pass this Stream Profile corresponds to. + +2.4 Example profile +------------------- + +The representation used here is XML only as an example. No decision is +made as to which formatting to use for storing targets and profiles. + + + Nokia N900 + Consumer Device + + Nokia N900/H264 HQ + Nokia N900/MP3 + Nokia N900/AAC + + + + + Nokia N900/H264 HQ + + High Quality H264/AAC for the Nokia N900 + + video/quicktime,variant=iso + + + audio + audio/mpeg,mpegversion=4 + Quality High/Main + audio/x-raw-int,channels=[1,2] + 1 + + + video + video/x-h264 + Profile Baseline/Quality High + + video/x-raw-yuv,width=[16, 800],\ + height=[16, 480],framerate=[1/1, 30000/1001] + + 1 + + + + + +2.5 API +------- + A proposed C API is contained in the gstprofile.h file in this directory. + + +2.6 Modifications required in the existing GstPreset system +----------------------------------------------------------- + +2.6.1. Temporary preset. + + Currently a preset needs to be saved on disk in order to be + used. + + This makes it impossible to have temporary presets (that exist only + during the lifetime of a process), which might be required in the + new proposed profile system + +2.6.2 Categorisation of presets. + + Currently presets are just aliases of a group of property/value + without any meanings or explanation as to how they exclude each + other. + + Take for example the H264 encoder. It can have presets for: + * passes (1,2 or 3 passes) + * profiles (Baseline, Main, ...) + * quality (Low, medium, High) + + In order to programmatically know which presets exclude each other, + we here propose the categorisation of these presets. + + This can be done in one of two ways + 1. in the name (by making the name be [:]) + This would give for example: "Quality:High", "Profile:Baseline" + 2. by adding a new _meta key + This would give for example: _meta/category:quality + +2.6.3 Aggregation of presets. + + There can be more than one choice of presets to be done for an + element (quality, profile, pass). + + This means that one can not currently describe the full + configuration of an element with a single string but with many. + + The proposal here is to extend the GstPreset API to be able to set + all presets using one string and a well-known separator ('/'). + + This change only requires changes in the core preset handling code. + + This would allow doing the following: + gst_preset_load_preset (h264enc, + "pass:1/profile:baseline/quality:high"); + +2.7 Points to be determined +--------------------------- + + This document hasn't determined yet how to solve the following + problems: + +2.7.1 Storage of profiles + + One proposal for storage would be to use a system wide directory + (like $prefix/share/gstreamer-0.10/profiles) and store XML files for + every individual profiles. + + Users could then add their own profiles in ~/.gstreamer-0.10/profiles + + This poses some limitations as to what to do if some applications + want to have some profiles limited to their own usage. + + +3. Helper library for profiles +------------------------------ + + These helper methods could also be added to existing libraries (like + GstPreset, GstPbUtils, ..). + + The various API proposed are in the accompanying gstprofile.h file. + +3.1 Getting user-readable names for formats + + This is already provided by GstPbUtils. + +3.2 Hierarchy of profiles + + The goal is for applications to be able to present to the user a list + of combo-boxes for choosing their output profile: + + [ Category ] # optional, depends on the application + [ Device/Site/.. ] # optional, depends on the application + [ Profile ] + + Convenience methods are offered to easily get lists of categories, + devices, and profiles. + +3.3 Creating Profiles + + The goal is for applications to be able to easily create profiles. + + The applications needs to be able to have a fast/efficient way to: + * select a container format and see all compatible streams he can use + with it. + * select a codec format and see which container formats he can use + with it. + + The remaining parts concern the restrictions to encoder + input. + +3.4 Ensuring availability of plugins for Profiles + + When an application wishes to use a Profile, it should be able to + query whether it has all the needed plugins to use it. + + This part will use GstPbUtils to query, and if needed install the + missing plugins through the installed distribution plugin installer. + + +I. Use-cases researched +----------------------- + + This is a list of various use-cases where encoding/muxing is being + used. + +* Transcoding + + The goal is to convert with as minimal loss of quality any input + file for a target use. + A specific variant of this is transmuxing (see below). + + Example applications: Arista, Transmageddon + +* Rendering timelines + + The incoming streams are a collection of various segments that need + to be rendered. + Those segments can vary in nature (i.e. the video width/height can + change). + This requires the use of identiy with the single-segment property + activated to transform the incoming collection of segments to a + single continuous segment. + + Example applications: PiTiVi, Jokosher + +* Encoding of live sources + + The major risk to take into account is the encoder not encoding the + incoming stream fast enough. This is outside of the scope of + encodebin, and should be solved by using queues between the sources + and encodebin, as well as implementing QoS in encoders and sources + (the encoders emitting QoS events, and the upstream elements + adapting themselves accordingly). + + Example applications: camerabin, cheese + +* Screencasting applications + + This is similar to encoding of live sources. + The difference being that due to the nature of the source (size and + amount/frequency of updates) one might want to do the encoding in + two parts: + * The actual live capture is encoded with a 'almost-lossless' codec + (such as huffyuv) + * Once the capture is done, the file created in the first step is + then rendered to the desired target format. + + Fixing sources to only emit region-updates and having encoders + capable of encoding those streams would fix the need for the first + step but is outside of the scope of encodebin. + + Example applications: Istanbul, gnome-shell, recordmydesktop + +* Live transcoding + + This is the case of an incoming live stream which will be + broadcasted/transmitted live. + One issue to take into account is to reduce the encoding latency to + a minimum. This should mostly be done by picking low-latency + encoders. + + Example applications: Rygel, Coherence + +* Transmuxing + + Given a certain file, the aim is to remux the contents WITHOUT + decoding into either a different container format or the same + container format. + Remuxing into the same container format is useful when the file was + not created properly (for example, the index is missing). + Whenever available, parsers should be applied on the encoded streams + to validate and/or fix the streams before muxing them. + + Metadata from the original file must be kept in the newly created + file. + + Example applications: Arista, Transmaggedon + +* Loss-less cutting + + Given a certain file, the aim is to extract a certain part of the + file without going through the process of decoding and re-encoding + that file. + This is similar to the transmuxing use-case. + + Example applications: PiTiVi, Transmageddon, Arista, ... + +* Multi-pass encoding + + Some encoders allow doing a multi-pass encoding. + The initial pass(es) are only used to collect encoding estimates and + are not actually muxed and outputted. + The final pass uses previously collected information, and the output + is then muxed and outputted. + +* Archiving and intermediary format + + The requirement is to have lossless + +* CD ripping + + Example applications: Sound-juicer + +* DVD ripping + + Example application: Thoggen + + + +* Research links + + Some of these are still active documents, some other not + +[0] GstPreset API documentation + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gstreamer/html/GstPreset.html + +[1] gnome-media GConf profiles + http://www.gnome.org/~bmsmith/gconf-docs/C/gnome-media.html + +[2] Research on a Device Profile API + http://gstreamer.freedesktop.org/wiki/DeviceProfile + +[3] Research on defining presets usage + http://gstreamer.freedesktop.org/wiki/PresetDesign + diff --git a/gst-plugins-base-subtitles0.10/docs/design/design-orc-integration.txt b/gst-plugins-base-subtitles0.10/docs/design/design-orc-integration.txt new file mode 100644 index 0000000..d5d146c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/design-orc-integration.txt @@ -0,0 +1,204 @@ + +Orc Integration +=============== + +Sections +-------- + + - About Orc + - Fast memcpy() + - Normal Usage + - Build Process + - Testing + - Orc Limitations + + +About Orc +--------- + +Orc code can be in one of two forms: in .orc files that is converted +by orcc to C code that calls liborc functions, or C code that calls +liborc to create complex operations at runtime. The former is mostly +for functions with predetermined functionality. The latter is for +functionality that is determined at runtime, where writing .orc +functions for all combinations would be prohibitive. Orc also has +a fast memcpy and memset which are useful independently. + + +Fast memcpy() +------------- + +*** This part is not integrated yet. *** + +Orc has built-in functions orc_memcpy() and orc_memset() that work +like memcpy() and memset(). These are meant for large copies only. +A reasonable cutoff for using orc_memcpy() instead of memcpy() is +if the number of bytes is generally greater than 100. DO NOT use +orc_memcpy() if the typical is size is less than 20 bytes, especially +if the size is known at compile time, as these cases are inlined by +the compiler. + +(Example: sys/ximage/ximagesink.c) + +Add $(ORC_CFLAGS) to libgstximagesink_la_CFLAGS and $(ORC_LIBS) to +libgstximagesink_la_LIBADD. Then, in the source file, add: + + #ifdef HAVE_ORC + #include + #else + #define orc_memcpy(a,b,c) memcpy(a,b,c) + #endif + +Then switch relevant uses of memcpy() to orc_memcpy(). + +The above example works whether or not Orc is enabled at compile +time. + + +Normal Usage +------------ + +The following lines are added near the top of Makefile.am for plugins +that use Orc code in .orc files (this is for the volume plugin): + + ORC_BASE=volume + include $(top_srcdir)/common/orc.mk + +Also add the generated source file to the plugin build: + + nodist_libgstvolume_la_SOURCES = $(ORC_SOURCES) + +And of course, add $(ORC_CFLAGS) to libgstvolume_la_CFLAGS, and +$(ORC_LIBS) to libgstvolume_la_LIBADD. + +The value assigned to ORC_BASE does not need to be related to +the name of the plugin. + + +Advanced Usage +-------------- + +The Holy Grail of Orc usage is to programmatically generate Orc code +at runtime, have liborc compile it into binary code at runtime, and +then execute this code. Currently, the best example of this is in +Schroedinger. An example of how this would be used is audioconvert: +given an input format, channel position manipulation, dithering and +quantizing configuration, and output format, a Orc code generator +would create an OrcProgram, add the appropriate instructions to do +each step based on the configuration, and then compile the program. +Sucessfully compiling the program would return a function pointer +that can be called to perform the operation. + +This sort of advanced usage requires structural changes to current +plugins (e.g., audioconvert) and will probably be developed +incrementally. Moreover, if such code is intended to be used without +Orc as strict build/runtime requirement, two codepaths would need to +be developed and tested. For this reason, until GStreamer requires +Orc, I think it's a good idea to restrict such advanced usage to the +cog plugin in -bad, which requires Orc. + + +Build Process +------------- + +The goal of the build process is to make Orc non-essential for most +developers and users. This is not to say you shouldn't have Orc +installed -- without it, you will get slow backup C code, just that +people compiling GStreamer are not forced to switch from Liboil to +Orc immediately. + +With Orc installed, the build process will use the Orc Compiler (orcc) +to convert each .orc file into a temporary C source (tmp-orc.c) and a +temporary header file (${name}orc.h if constructed from ${base}.orc). +The C source file is compiled and linked to the plugin, and the header +file is included by other source files in the plugin. + +If 'make orc-update' is run in the source directory, the files +tmp-orc.c and ${base}orc.h are copied to ${base}orc-dist.c and +${base}orc-dist.h respectively. The -dist.[ch] files are automatically +disted via orc.mk. The -dist.[ch] files should be checked in to +git whenever the .orc source is changed and checked in. Example +workflow: + + edit .orc file + ... make, test, etc. + make orc-update + git add volume.orc volumeorc-dist.c volumeorc-dist.h + git commit + +At 'make dist' time, all of the .orc files are compiled, and then +copied to their -dist.[ch] counterparts, and then the -dist.[ch] +files are added to the dist directory. + +Without Orc installed (or --disable-orc given to configure), the +-dist.[ch] files are copied to tmp-orc.c and ${name}orc.h. When +compiled Orc disabled, DISABLE_ORC is defined in config.h, and +the C backup code is compiled. This backup code is pure C, and +does not include orc headers or require linking against liborc. + +The common/orc.mk build method is limited by the inflexibility of +automake. The file tmp-orc.c must be a fixed filename, using ORC_NAME +to generate the filename does not work because it conflicts with +automake's dependency generation. Building multiple .orc files +is not possible due to this restriction. + + +Testing +------- + +If you create another .orc file, please add it to +tests/orc/Makefile.am. This causes automatic test code to be +generated and run during 'make check'. Each function in the .orc +file is tested by comparing the results of executing the run-time +compiled code and the C backup function. + + +Orc Limitations +--------------- + +audioconvert + + Orc doesn't have a mechanism for generating random numbers, which + prevents its use as-is for dithering. One way around this is to + generate suitable dithering values in one pass, then use those + values in a second Orc-based pass. + + Orc doesn't handle 64-bit float, for no good reason. + + Irrespective of Orc handling 64-bit float, it would be useful to + have a direct 32-bit float to 16-bit integer conversion. + + audioconvert is a good candidate for programmatically generated + Orc code. + + audioconvert enumerates functions in terms of big-endian vs. + little-endian. Orc's functions are "native" and "swapped". + Programmatically generating code removes the need to worry about + this. + + Orc doesn't handle 24-bit samples. Fixing this is not a priority + (for ds). + +videoscale + + Orc doesn't handle horizontal resampling yet. The plan is to add + special sampling opcodes, for nearest, bilinear, and cubic + interpolation. + +videotestsrc + + Lots of code in videotestsrc needs to be rewritten to be SIMD + (and Orc) friendly, e.g., stuff that uses oil_splat_u8(). + + A fast low-quality random number generator in Orc would be useful + here. + +volume + + Many of the comments on audioconvert apply here as well. + + There are a bunch of FIXMEs in here that are due to misapplied + patches. + + + diff --git a/gst-plugins-base-subtitles0.10/docs/design/draft-keyframe-force.txt b/gst-plugins-base-subtitles0.10/docs/design/draft-keyframe-force.txt new file mode 100644 index 0000000..8dd0f01 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/draft-keyframe-force.txt @@ -0,0 +1,91 @@ +Forcing keyframes +----------------- + +Consider the following use case: + + We have a pipeline that performs video and audio capture from a live source, + compresses and muxes the streams and writes the resulting data into a file. + + Inside the uncompressed video data we have a specific pattern inserted at + specific moments that should trigger a switch to a new file, meaning, we close + the existing file we are writing to and start writing to a new file. + + We want the new file to start with a keyframe so that one can start decoding + the file immediatly. + +Components: + + 1) We need an element that is able to detect the pattern in the video stream. + + 2) We need to inform the video encoder that it should start encoding a keyframe + starting from exactly the frame with the pattern. + + 3) We need to inform the demuxer that it should flush out any pending data and + start creating the start of a new file with the keyframe as a first video + frame. + + 4) We need to inform the sink element that it should start writing to the next + file. This requires application interaction to instruct the sink of the new + filename. The application should also be free to ignore the boundary and + continue to write to the existing file. The application will typically use + an event pad probe to detect the custom event. + +Implementation: + + The implementation would consist of generating a GST_EVENT_CUSTOM_DOWNSTREAM + event that marks the keyframe boundary. This event is inserted into the + pipeline by the application upon a certain trigger. In the above use case this + trigger would be given by the element that detects the pattern, in the form of + an element message. + + The custom event would travel further downstream to instruct encoder, muxer and + sink about the possible switch. + + The information passed in the event consists of: + + name: GstForceKeyUnit + (G_TYPE_UINT64)"timestamp" : the timestamp of the buffer that + triggered the event. + (G_TYPE_UINT64)"stream-time" : the stream position that triggered the + event. + (G_TYPE_UINT64)"running-time" : the running time of the stream when the + event was triggered. + (G_TYPE_BOOLEAN)"all-headers" : Send all headers, including those in + the caps or those sent at the start of + the stream. + + .... : optional other data fields. + + Note that this event is purely informational, no element is required to + perform an action but it should forward the event downstream, just like any + other event it does not handle. + + Elements understanding the event should behave as follows: + + 1) The video encoder receives the event before the next frame. Upon reception + of the event it schedules to encode the next frame as a keyframe. + Before pushing out the encoded keyframe it must push the GstForceKeyUnit + event downstream. + + 2) The muxer receives the GstForceKeyUnit event and flushes out its current state, + preparing to produce data that can be used as a keyunit. Before pushing out + the new data it pushes the GstForceKeyUnit event downstream. + + 3) The application receives the GstForceKeyUnit on a sink padprobe of the sink + and reconfigures the sink to make it perform new actions after receiving + the next buffer. + + +Upstream +-------- + +When using RTP packets can get lost or receivers can be added at any time, +they may request a new key frame. + +An downstream element sends an upstream "GstForceKeyUnit" event up the +pipeline. + +When an element produces some kind of key unit in output, but has +no such concept in its input (like an encoder that takes raw frames), +it consumes the event (doesn't pass it upstream), and instead sends +a downstream GstForceKeyUnit event and a new keyframe. diff --git a/gst-plugins-base-subtitles0.10/docs/design/draft-va.txt b/gst-plugins-base-subtitles0.10/docs/design/draft-va.txt new file mode 100644 index 0000000..a63a643 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/draft-va.txt @@ -0,0 +1,111 @@ +Video Acceleration +------------------ + +Status: + + DRAFT. + +Purpose: + + Provide an standarized generic way to introduce Video Acceleration APIs in + already available elements instead of duplicating those into specialized ones. + + Provide a mechanism for a light GstBuffer subclassing in order to be able + exchange VA related context and surfaces between elements. + + Provide some basic primitives to be used in the elements keeping + the implementation of those in the backends of the helper library. + + The motivation of this proposal is: + - to avoid multiple duplicty of code + - to avoid the use of GstBuffer subclassing and be more close to GstBuffer2 + - to avoid the overhead that's introduced with subclassing/GType checks + - to permit multiple elements interact having a common standard + +Proposal: + + video/x-raw-va + + Light subclassing embeding an structure in the data field of a standard + GstBuffer. + + struct { + context; + surface; + flags; + subpicture, x, y, w, h; + parent * + ... + } VASurface + + GstVA helper library + -------------------- + + Common API that it's implemented by a backend for each VA API. + + +-------+ +---------------+ + | |----> | VDPAU backend | + | GstVA | +---------------+ + | | +---------------+ + | |----> | VAAPI backend | + +-------+ +---------------+ + + gst_va_init () : Iterate in the backends and try to initialize those, stops + when a backend is able to be created. + + bool gst_va_available() : permit to query if there's VA available in runtime. + + GstBuffer * gst_va_buffer_new (vacontext, vasurface, vaflags, parent*, + free_func*): + Create a new GstBuffer with the proper light subclass and store on it + the provided context, surface, flags... + - parent* and free_func* to implement a mechanism to return surfaces in + the pool driven by parent. + + gst_va_buffer_get_context (GstBuffer *) + gst_va_buffer_get_surface (GstBuffer *) + gst_va_buffer_get_flags (GstBuffer *) + .... + Some public/private? accessors to be able recover fields from a VA GstBuffer + internal structure. + + Primitives: + + gst_va_render_display (GstBuffer * va, display, x, y, w, h, ...) + Put a surface in the screen at the specified position. + + gst_va_render_pixmap (GstBuffer * va, pixmap *, w, h, ...) + Put a surface in a pixmap, to be used paired with GLX_texture_from_pixmap to + upload into a OpenGL texture. + + gst_va_render_memory (GstBuffer * va, planes *, strides *, w, h, ...) + To pull back into main memory a VA surface. + + gst_va_buffer_associate_subpicture (GstBuffer * va, GstBuffer * subpicture, + x, y, w, h,...) + Take a reference of subpicture and keep it in va internal structure. + +Use cases: + + Instead of create a new specialized element for each API just change + a generic element once. + + To add support for a new API just have to create a new backend. + + xvimagesink + ----------- + + - In _setcaps negotiate accept VA kind of stream when gst_va_init and + gst_va_available tell us that we have hardware capable of it. + + - In _render when the buffers have the VA flag render display it with + gst_va_render_display() + + videomixer, dvdspu, textoverlay, ... + ------------------------------------ + + - In _setcaps negotiate accept VA kind of stream when gst_va_init and + gst_va_available tell us that we have hardware capable of it. + + - Use gst_va_buffer_associate_subpicture () where necessary. + diff --git a/gst-plugins-base-subtitles0.10/docs/design/part-interlaced-video.txt b/gst-plugins-base-subtitles0.10/docs/design/part-interlaced-video.txt new file mode 100644 index 0000000..6593146 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/part-interlaced-video.txt @@ -0,0 +1,99 @@ +Interlaced Video +================ + +Video buffers have a number of states identifiable through a combination of caps +and buffer flags. + +Possible states: +- Progressive +- Interlaced + - Plain + - One field + - Two fields + - Three fields - this should be a progressive buffer with a repeated 'first' + field that can be used for telecine pulldown + - Telecine + - One field + - Two fields + - Progressive + - Interlaced (a.k.a. 'mixed'; the fields are from different frames) + - Three fields - this should be a progressive buffer with a repeated 'first' + field that can be used for telecine pulldown + +Note: it can be seen that the different between the plain interlaced and +telecine states is that in the telecine state, buffers containing two fields may +be progressive. + +Tools for identification: +- Caps + - interlaced - boolean + - interlacing-method - string - "unknown"/"telecine" +- Flags - GST_VIDEO_BUFFER_... + - TFF + - RFF + - ONEFIELD + - PROGRESSIVE + + +Identification of Buffer States +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Note that flags are not necessarily interpreted in the same way for all +different states nor are they necessarily required nor make sense in all cases. + + +Progressive +........... + +If the caps have no interlaced field, or have interlaced=false, then the buffer +is progressive. Note the possibility for progressive buffers in telecine streams +as well. + + +Plain Interlaced +................ + +If the caps have interlaced=true and either do not contain the +interlacing-method field or contain interlacing-method=unknown, then the buffer +is plain interlaced. + +GST_VIDEO_BUFFER_TFF indicates whether the top or bottom field is to be +displayed first. The timestamp on the buffer corresponds to the first field. +(FIXME - is the duration of the buffer the duration of both fields; each field's +duration is half the buffer duration) + +GST_VIDEO_BUFFER_RFF indicates that the first field (indicated by the TFF flag) +should be repeated. This is generally only used for telecine purposes but as the +telecine state was added long after the interlaced state was added and defined, +this flag remains valid for plain interlaced buffers. + +GST_VIDEO_BUFFER_ONEFIELD means that only the field indicated through the TFF +flag is to be used. The other field should be ignored. + + +Telecine +........ + +If the caps have interlaced=true and interlacing-method=telecine then the +buffers are in some form of telecine state. + +The TFF and ONEFIELD flags have the same semantics as for the plain interlaced +state. + +GST_VIDEO_BUFFER_RFF in the telecine state indicates that the buffer contains +only repeated fields that are present in other buffers and are as such +unneeded. For example, in a sequence of three telecined frames, we might have: + +AtAb AtBb BtBb + +In this situation, we only need the first and third buffers as the second +buffer contains fields present in the first and third. + +The telecine state require one additional flag to be able to identify +progressive buffers. + +GST_VIDEO_BUFFER_PROGRESSIVE means that the buffer containing two fields is a +progressive frame. The implication is that if this flag is not set, the buffer +is an 'interlaced' or 'mixed' buffer that contains two fields that, when +combined with fields from adjacent buffers, allow reconstruction of progressive +frames. diff --git a/gst-plugins-base-subtitles0.10/docs/design/part-playbin2.txt b/gst-plugins-base-subtitles0.10/docs/design/part-playbin2.txt new file mode 100644 index 0000000..195d048 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/design/part-playbin2.txt @@ -0,0 +1,69 @@ +playbin2 +-------- + +The purpose of this element is to decode and render the media contained in a +given generic uri. The element extends GstPipeline and is typically used in +playback situations. + +Required features: + + - accept and play any valid uri. This includes + - rendering video/audio + - overlaying subtitles on the video + - optionally read external subtitle files + - allow for hardware (non raw) sinks + - selection of audio/video/subtitle streams based on language. + - perform network buffering/incremental download + - gapless playback + - support for visualisations with configurable sizes + - ability to reject files that are too big, or of a format that would require + too much CPU/memory usage. + - be very efficient with adding elements such as converters to reduce the + amount of negotiation that has to happen. + - handle chained oggs. This includes having support for dynamic pad add and + remove from a demuxer. + +Components +---------- + +* decodebin2 + + - performs the autoplugging of demuxers/decoders + - emits signals when for steering the autoplugging + - to decide if a non-raw media format is acceptable as output + - to sort the possible decoders for a non-raw format + - see also decodebin2 design doc + +* uridecodebin + + - combination of a source to handle the given uri, an optional queueing element + and one or more decodebin2 elements to decode the non-raw streams. + +* playsink + + - handles display of audio/video/text. + - has request audio/video/text input pad. There is only one sinkpad per type. + The requested pads define the configuration of the internal pipeline. + - allows for setting audio/video sinks or does automatic sink selection. + - allows for configuration of visualisation element. + - allows for enable/disable of visualisation, audio and video. + +* playbin2 + + - combination of one or more uridecodebin elements to read the uri and subtitle + uri. + - support for queuing new media to support gapless playback. + - handles stream selection. + - uses playsink to display. + - selection of sinks and configuration of uridecodebin with raw output formats. + + +Gapless playback +---------------- + +playbin2 has an "about-to-finish" signal. The application should configure a new +uri (and optional suburi) in the callback. When the current media finishes, this +new media will be played next. + + + diff --git a/gst-plugins-base-subtitles0.10/docs/libs/.gitignore b/gst-plugins-base-subtitles0.10/docs/libs/.gitignore new file mode 100644 index 0000000..cae0859 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/.gitignore @@ -0,0 +1,21 @@ +*.stamp +html +tmpl +xml +Makefile +Makefile.in +*-decl.txt +*-decl-list.txt +*-presed-scan.c +*-undeclared.txt +*-undocumented.txt +*-unused.txt +*.args +*.hierarchy +*.interfaces +*.prerequisites +*.signals +doc-registry.xml + +*-unused.sgml +*.bak diff --git a/gst-plugins-base-subtitles0.10/docs/libs/Makefile.am b/gst-plugins-base-subtitles0.10/docs/libs/Makefile.am new file mode 100644 index 0000000..af2632c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/Makefile.am @@ -0,0 +1,106 @@ +## Process this file with automake to produce Makefile.in + +# FIXME: fix the docs then remove this variable +DOCS_ARE_INCOMPLETE_PLEASE_FIXME=yespleasedo + +# The name of the module, e.g. 'glib'. +#DOC_MODULE=gst-plugins-libs-@GST_MAJORMINOR@ +DOC_MODULE=gst-plugins-base-libs + +# for upload-doc.mak +DOC=gst-plugins-base-libs +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# generated basefiles +#basefiles = \ +## $(DOC_MODULE).types \ +# $(DOC_MODULE)-sections.txt \ +# $(DOC_MODULE)-docs.sgml + +# ugly hack to make -unused.sgml work +#unused-build.stamp: +# BUILDDIR=`pwd` && \ +# cd $(srcdir)/tmpl && \ +# ln -sf gstreamer-libs-unused.sgml \ +# $$BUILDDIR/tmpl/gstreamer-libs-@GST_MAJORMINOR@-unused.sgml +# touch unused-build.stamp + +# these rules are added to create parallel docs using GST_MAJORMINOR +#$(basefiles): gstreamer-libs-@GST_MAJORMINOR@%: gstreamer-libs% +# cp $< $@ + +#CLEANFILES = $(basefiles) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(top_srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR=$(top_srcdir)/gst-libs/gst +DOC_BUILD_DIR=$(top_builddir)/gst-libs/gst + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED" + +# FIXME : +# there's something wrong with gstreamer-sections.txt not being in the dist +# maybe it doesn't resolve; we're adding it below for now +#EXTRA_DIST = gstreamer.types.in gstreamer.hierarchy $(DOC_MODULE)-sections.txt gstreamer-sections.txt $(DOC_MAIN_SGML_FILE) + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode --output-format=xml + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GST_PREFIX)/share/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(DOC_SOURCE_DIR)/*/*.h +CFILE_GLOB=$(DOC_SOURCE_DIR)/*/*.c + +# this is a wingo addition +# thomasvs: another nice wingo addition would be an explanation on why +# this is useful ;) + +SCANOBJ_DEPS = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/cdda/libgstcdda-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/fft/libgstfft-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/rtsp/libgstrtsp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/sdp/libgstsdp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la + +# Header files to ignore when scanning. +IGNORE_HFILES = pbutils-private.h + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = compiling.sgml + +# Other files to distribute. +extra_files = + +# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib +# contains GtkObjects/GObjects and you want to document signals and properties. +GTKDOC_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) +GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_BASE_LIBS) + +GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC) +GTKDOC_LD=$(LIBTOOL) --tag=CC --mode=link $(CC) + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +#DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt +DOC_OVERRIDES = + +include $(top_srcdir)/common/gtk-doc.mak diff --git a/gst-plugins-base-subtitles0.10/docs/libs/compiling.sgml b/gst-plugins-base-subtitles0.10/docs/libs/compiling.sgml new file mode 100644 index 0000000..70a130c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/compiling.sgml @@ -0,0 +1,48 @@ + + +%version-entities; +]> + + +Compiling +3 +GStreamer-Base Library + + + +Compiling against the base plugins libraries + +How to compile against the base plugins libraries + + + + +Compiling against the base plugins libraries + + +To compile against these libraries, you need to tell the compiler where to +find the header files and libraries. This is done with the +pkg-config utility. + + +The following interactive shell session demonstrates how +pkg-config is used: + +$ pkg-config --cflags gstreamer-plugins-base-&GST_MAJORMINOR; +-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -pthread -I/usr/include/gstreamer-&GST_MAJORMINOR; -I/usr/include/glib-2.0 -I/usr/lib/glib-2.0/include -I/usr/include/libxml2 +$ pkg-config --libs gstreamer-plugins-base-&GST_MAJORMINOR; +-Wl,--export-dynamic -pthread -lgstreamer-&GST_MAJORMINOR; -lgobject-2.0 -lgmodule-2.0 -ldl -lgthread-2.0 -lxml2 -lpthread -lz -lm -lglib-2.0 + + + + +Note that, because of the number of libraries provided in this package, +the pkg-config information does not add -l flags itself +to choose the libraries to link to. You must add these yourself to select +which of the libraries you want to use. + + + + diff --git a/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-docs.sgml b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-docs.sgml new file mode 100644 index 0000000..b7b61a7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-docs.sgml @@ -0,0 +1,240 @@ + + +%version-entities; +]> + + + GStreamer Base Plugins &GST_MAJORMINOR; Library Reference Manual + + for GStreamer Base Library &GST_MAJORMINOR; (&GST_VERSION;) + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base-libs/html/. + + + + + GStreamer Base Plugins Libraries + + This manual describes the libraries provided by the GStreamer Base Plugins + package. + + + + + App Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstapp-&GST_MAJORMINOR; to the library flags. + + + To use it the functionality, insert an appsrc or appsink element into a pipeline and call the appropriate functions on the element. + + + + + + + Audio Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstaudio-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + + + + + + CDDA Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstcdda-&GST_MAJORMINOR; to the library flags. + + + + + + FFT Library + + The gstfft library is based on + kissfft + by Mark Borgerding. + + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstfft-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + FloatCast Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstfloatcase-&GST_MAJORMINOR; to the library flags. + + + + + + Interfaces Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstinterfaces-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + + + + + + + + + Network Buffer Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstnetbuffer-&GST_MAJORMINOR; to the library flags. + + + + + + Riff Media Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstriff-&GST_MAJORMINOR; to the library flags. + + + + + + RTP Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstrtp-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + + RTSP Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstrtsp-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + + + + SDP Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstsdp-&GST_MAJORMINOR; to the library flags. + + + + + + Tag Support Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgsttag-&GST_MAJORMINOR; to the library flags. + + + + + + + + + + + Base Utils Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstpbutils-&GST_MAJORMINOR; to the library + flags. + + + + + + + + + + + + Video Library + + This library should be linked to by getting cflags and libs from + gstreamer-plugins-base-&GST_MAJORMINOR;.pc and adding + -lgstvideo-&GST_MAJORMINOR; to the library flags. + + + + + + + + + Object Hierarchy + + + + + Index + + + + Index of deprecated API + + + + + diff --git a/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-overrides.txt b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-overrides.txt new file mode 100644 index 0000000..e69de29 diff --git a/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-sections.txt b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-sections.txt new file mode 100644 index 0000000..41235a0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs-sections.txt @@ -0,0 +1,2250 @@ +# app +
+gstappsrc +appsrc +gst/app/gstappsrc.h +GstAppSrc +GstAppStreamType +gst_app_src_set_caps +gst_app_src_get_caps +gst_app_src_get_latency +gst_app_src_set_latency +gst_app_src_set_size +gst_app_src_get_size +gst_app_src_set_stream_type +gst_app_src_get_stream_type +gst_app_src_set_max_bytes +gst_app_src_get_max_bytes +gst_app_src_get_emit_signals +gst_app_src_set_emit_signals +GstAppSrcCallbacks +gst_app_src_set_callbacks +gst_app_src_push_buffer +gst_app_src_end_of_stream + +GstAppSrcClass +GST_APP_SRC +GST_APP_SRC_CAST +GST_IS_APP_SRC +GST_TYPE_APP_SRC +gst_app_src_get_type +GST_APP_SRC_CLASS +GST_IS_APP_SRC_CLASS +GST_APP_BUFFER +GST_APP_BUFFER_CLASS +GST_IS_APP_BUFFER +GST_IS_APP_BUFFER_CLASS +GST_TYPE_APP_BUFFER + +GstAppSrcPrivate +GstAppBuffer +GstAppBufferClass +GstAppBufferFinalizeFunc +gst_app_buffer_get_type +gst_app_buffer_new +
+ +
+gstappsink +appsink +gst/app/gstappsink.h +GstAppSink +gst_app_sink_set_caps +gst_app_sink_get_caps +gst_app_sink_is_eos +gst_app_sink_set_emit_signals +gst_app_sink_get_emit_signals +gst_app_sink_set_max_buffers +gst_app_sink_get_max_buffers +gst_app_sink_set_drop +gst_app_sink_get_drop +gst_app_sink_pull_preroll +gst_app_sink_pull_buffer +gst_app_sink_pull_buffer_list +GstAppSinkCallbacks +gst_app_sink_set_callbacks + +GstAppSinkPrivate +GstAppSinkClass +GST_APP_SINK +GST_APP_SINK_CAST +GST_IS_APP_SINK +GST_TYPE_APP_SINK +gst_app_sink_get_type +GST_APP_SINK_CLASS +GST_IS_APP_SINK_CLASS +
+ +# audio + +
+gstaudio +gst/audio/audio.h +GstAudioFieldFlag +GST_FRAMES_TO_CLOCK_TIME +GST_CLOCK_TIME_TO_FRAMES +GST_AUDIO_DEF_RATE +GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS +GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS +GST_AUDIO_INT_PAD_TEMPLATE_CAPS +GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS +gst_audio_frame_byte_size +gst_audio_frame_length +gst_audio_duration_from_pad_buffer +gst_audio_is_buffer_framed +gst_audio_structure_set_int +gst_audio_buffer_clip + +GST_TYPE_BUFFER_FORMAT +GST_TYPE_BUFFER_FORMAT_TYPE +gst_buffer_format_get_type +gst_buffer_format_type_get_type +
+ +
+gstaudioclock +gst/audio/gstaudioclock.h +GstAudioClock +GstAudioClockGetTimeFunc +gst_audio_clock_new +gst_audio_clock_new_full +gst_audio_clock_adjust +gst_audio_clock_get_time +gst_audio_clock_reset +gst_audio_clock_invalidate + +GstAudioClockClass +GST_AUDIO_CLOCK +GST_IS_AUDIO_CLOCK +GST_TYPE_AUDIO_CLOCK +gst_audio_clock_get_type +GST_AUDIO_CLOCK_CLASS +GST_IS_AUDIO_CLOCK_CLASS +GST_AUDIO_CLOCK_CAST +
+ +
+gstaudiofilter +gst/audio/gstaudiofilter.h +GstAudioFilter +GstAudioFilterClass +gst_audio_filter_class_add_pad_templates + +GST_AUDIO_FILTER +GST_IS_AUDIO_FILTER +GST_TYPE_AUDIO_FILTER +gst_audio_filter_get_type +GST_AUDIO_FILTER_CLASS +GST_IS_AUDIO_FILTER_CLASS +GST_AUDIO_FILTER_CAST +GST_AUDIO_FILTER_CLASS_CAST +
+ +
+gstaudiomixerutils +gst/audio/mixerutils.h +GstAudioMixerFilterFunc +gst_audio_default_registry_mixer_filter +
+ +
+gstaudiosink +gst/audio/gstaudiosink.h +GstAudioSink +GstAudioSinkClass + +GST_AUDIO_SINK +GST_IS_AUDIO_SINK +GST_TYPE_AUDIO_SINK +gst_audio_sink_get_type +GST_AUDIO_SINK_CLASS +GST_IS_AUDIO_SINK_CLASS +GST_AUDIO_SINK_GET_CLASS +
+ +
+gstaudiosrc +gst/audio/gstaudiosrc.h +GstAudioSrc +GstAudioSrcClass + +GST_AUDIO_SRC +GST_IS_AUDIO_SRC +GST_TYPE_AUDIO_SRC +gst_audio_src_get_type +GST_AUDIO_SRC_CLASS +GST_IS_AUDIO_SRC_CLASS +GST_AUDIO_SRC_GET_CLASS +
+ +
+gstbaseaudiosink +gst/audio/gstbaseaudiosink.h +GstBaseAudioSink +GstBaseAudioSinkClass +GstBaseAudioSinkSlaveMethod + +GST_BASE_AUDIO_SINK_CLOCK +GST_BASE_AUDIO_SINK_PAD +gst_base_audio_sink_create_ringbuffer +gst_base_audio_sink_set_provide_clock +gst_base_audio_sink_get_provide_clock +gst_base_audio_sink_set_slave_method +gst_base_audio_sink_get_slave_method +gst_base_audio_sink_get_drift_tolerance +gst_base_audio_sink_set_drift_tolerance + +GST_BASE_AUDIO_SINK +GST_IS_BASE_AUDIO_SINK +GST_TYPE_BASE_AUDIO_SINK +gst_base_audio_sink_get_type +GST_BASE_AUDIO_SINK_CLASS +GST_IS_BASE_AUDIO_SINK_CLASS +GST_BASE_AUDIO_SINK_GET_CLASS +GstBaseAudioSinkPrivate +gst_base_audio_sink_slave_method_get_type +GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD +
+ +
+gstbaseaudiosrc +gst/audio/gstbaseaudiosrc.h +GstBaseAudioSrc +GstBaseAudioSrcClass +GstBaseAudioSrcSlaveMethod + +GST_BASE_AUDIO_SRC_CLOCK +GST_BASE_AUDIO_SRC_PAD +gst_base_audio_src_create_ringbuffer +gst_base_audio_src_set_provide_clock +gst_base_audio_src_get_provide_clock +gst_base_audio_src_get_slave_method +gst_base_audio_src_set_slave_method + +GstBaseAudioSrcPrivate +GST_BASE_AUDIO_SRC +GST_IS_BASE_AUDIO_SRC +GST_TYPE_BASE_AUDIO_SRC +gst_base_audio_src_get_type +GST_BASE_AUDIO_SRC_CLASS +GST_IS_BASE_AUDIO_SRC_CLASS +GST_BASE_AUDIO_SRC_GET_CLASS +gst_base_audio_src_slave_method_get_type +GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD +
+ +
+gstmultichannel +gst/audio/multichannel.h +GstAudioChannelPosition +gst_audio_fixate_channel_positions +gst_audio_get_channel_positions +gst_audio_set_caps_channel_positions_list +gst_audio_set_channel_positions +gst_audio_set_structure_channel_positions_list +gst_audio_check_channel_positions + +GST_TYPE_AUDIO_CHANNEL_POSITION +gst_audio_channel_position_get_type +
+ +
+gstringbuffer +gst/audio/gstringbuffer.h +GstRingBuffer +GstRingBufferClass +GstRingBufferSpec +GstRingBufferCallback +GstRingBufferSegState +GstRingBufferState +GstBufferFormat +GstBufferFormatType + +GST_RING_BUFFER_BROADCAST +GST_RING_BUFFER_GET_COND +GST_RING_BUFFER_SIGNAL +GST_RING_BUFFER_WAIT + +gst_ring_buffer_set_callback + +gst_ring_buffer_acquire +gst_ring_buffer_release +gst_ring_buffer_is_acquired + +gst_ring_buffer_activate +gst_ring_buffer_is_active + +gst_ring_buffer_start +gst_ring_buffer_pause +gst_ring_buffer_stop + +gst_ring_buffer_delay +gst_ring_buffer_samples_done +gst_ring_buffer_set_sample +gst_ring_buffer_commit +gst_ring_buffer_commit_full +gst_ring_buffer_convert + +gst_ring_buffer_prepare_read +gst_ring_buffer_read +gst_ring_buffer_clear +gst_ring_buffer_clear_all +gst_ring_buffer_advance + +gst_ring_buffer_close_device +gst_ring_buffer_open_device +gst_ring_buffer_device_is_open + +gst_ring_buffer_may_start +gst_ring_buffer_parse_caps +gst_ring_buffer_set_flushing + + +GST_TYPE_RING_BUFFER +GST_RING_BUFFER +GST_RING_BUFFER_CLASS +GST_RING_BUFFER_GET_CLASS +GST_IS_RING_BUFFER +GST_IS_RING_BUFFER_CLASS +GST_RING_BUFFER_CAST +gst_ring_buffer_get_type +GST_TYPE_RING_BUFFER_SEG_STATE +gst_ring_buffer_seg_state_get_type +GST_TYPE_RING_BUFFER_STATE +gst_ring_buffer_state_get_type + +gst_ring_buffer_debug_spec_buff +gst_ring_buffer_debug_spec_caps +
+ + +# cdda + +
+gstcddabasesrc +gst/cdda/gstcddabasesrc.h +GstCddaBaseSrc +GstCddaBaseSrcClass +GstCddaBaseSrcTrack +GstCddaBaseSrcMode +gst_cdda_base_src_add_track + +GST_TYPE_CDDA_BASE_SRC_MODE +gst_cdda_base_src_mode_get_type +GST_CDDA_BASE_SRC +GST_CDDA_BASE_SRC_CLASS +GST_CDDA_BASE_SRC_GET_CLASS +GST_IS_CDDA_BASE_SRC +GST_IS_CDDA_BASE_SRC_CLASS +GST_TYPE_CDDA_BASE_SRC +gst_cdda_base_src_get_type +
+ +# fft + +
+gstfft +gst/fft/gstfft.h +GstFFTWindow +gst_fft_next_fast_length +
+ +
+gstffts16 +gst/fft/gstffts16.h +GstFFTS16 +GstFFTS16Complex +gst_fft_s16_new +gst_fft_s16_fft +gst_fft_s16_inverse_fft +gst_fft_s16_window +gst_fft_s16_free + +kiss_fft_s16 +kiss_fft_s16_alloc +kiss_fft_s16_cfg +kiss_fft_s16_cleanup +kiss_fft_s16_cpx +kiss_fft_s16_free +kiss_fft_s16_next_fast_size +kiss_fft_s16_scalar +kiss_fft_s16_stride +KISS_FFT_S16_COS +KISS_FFT_S16_MALLOC +KISS_FFT_S16_SIN +
+ +
+gstffts32 +gst/fft/gstffts32.h +GstFFTS32 +GstFFTS32Complex +gst_fft_s32_new +gst_fft_s32_fft +gst_fft_s32_inverse_fft +gst_fft_s32_window +gst_fft_s32_free + +kiss_fft_s32 +kiss_fft_s32_alloc +kiss_fft_s32_cfg +kiss_fft_s32_cleanup +kiss_fft_s32_cpx +kiss_fft_s32_free +kiss_fft_s32_next_fast_size +kiss_fft_s32_scalar +kiss_fft_s32_stride +KISS_FFT_S32_COS +KISS_FFT_S32_MALLOC +KISS_FFT_S32_SIN + +
+ +
+gstfftf32 +gst/fft/gstfftf32.h +GstFFTF32 +GstFFTF32Complex +gst_fft_f32_new +gst_fft_f32_fft +gst_fft_f32_inverse_fft +gst_fft_f32_window +gst_fft_f32_free + +kiss_fft_f32 +kiss_fft_f32_alloc +kiss_fft_f32_cfg +kiss_fft_f32_cleanup +kiss_fft_f32_cpx +kiss_fft_f32_free +kiss_fft_f32_next_fast_size +kiss_fft_f32_scalar +kiss_fft_f32_stride +KISS_FFT_F32_COS +KISS_FFT_F32_MALLOC +KISS_FFT_F32_SIN +
+ +
+gstfftf64 +gst/fft/gstfftf64.h +GstFFTF64 +GstFFTF64Complex +gst_fft_f64_new +gst_fft_f64_fft +gst_fft_f64_inverse_fft +gst_fft_f64_window +gst_fft_f64_free + +kiss_fft_f64 +kiss_fft_f64_alloc +kiss_fft_f64_cfg +kiss_fft_f64_cleanup +kiss_fft_f64_cpx +kiss_fft_f64_free +kiss_fft_f64_next_fast_size +kiss_fft_f64_scalar +kiss_fft_f64_stride +KISS_FFT_F64_COS +KISS_FFT_F64_MALLOC +KISS_FFT_F64_SIN +
+ +# floatcast + +
+gstfloatcast +gst/floatcast/floatcast.h +gst_cast_double +gst_cast_float +
+ + +# interfaces + +
+gstcolorbalance +gst/interfaces/color.h +GstColorBalance +GstColorBalanceClass +GstColorBalanceType +gst_color_balance_list_channels +gst_color_balance_get_value +gst_color_balance_set_value +gst_color_balance_value_changed +gst_color_balance_get_balance_type + +GST_COLOR_BALANCE +GST_COLOR_BALANCE_CLASS +GST_COLOR_BALANCE_GET_CLASS +GST_COLOR_BALANCE_TYPE +GST_IS_COLOR_BALANCE +GST_IS_COLOR_BALANCE_CLASS +GST_TYPE_COLOR_BALANCE +GST_TYPE_COLOR_BALANCE_TYPE +gst_color_balance_get_type +gst_color_balance_type_get_type +
+ +
+gstcolorbalancechannel +gst/interfaces/colorbalancechannel.h +GstColorBalanceChannel +GstColorBalanceChannelClass + +GST_COLOR_BALANCE_CHANNEL +GST_COLOR_BALANCE_CHANNEL_CLASS +GST_IS_COLOR_BALANCE_CHANNEL +GST_IS_COLOR_BALANCE_CHANNEL_CLASS +GST_TYPE_COLOR_BALANCE_CHANNEL +gst_color_balance_channel_get_type +
+ +
+gstmixer +gst/interfaces/mixer.h +GstMixer +GstMixerType +GstMixerFlags +GstMixerMessageType + +gst_mixer_list_tracks +gst_mixer_get_volume +gst_mixer_set_volume + +gst_mixer_set_mute +gst_mixer_set_record +gst_mixer_set_option + +gst_mixer_mute_toggled +gst_mixer_record_toggled +gst_mixer_volume_changed +gst_mixer_option_changed +gst_mixer_options_list_changed +gst_mixer_get_option + +gst_mixer_mixer_changed + +gst_mixer_get_mixer_flags +gst_mixer_get_mixer_type + +gst_mixer_message_get_type +gst_mixer_message_parse_mute_toggled +gst_mixer_message_parse_option_changed +gst_mixer_message_parse_record_toggled +gst_mixer_message_parse_volume_changed +gst_mixer_message_parse_options_list_changed + + +GstMixerClass +GST_TYPE_MIXER +GST_TYPE_MIXER_TYPE +GST_TYPE_MIXER_FLAGS +GST_TYPE_MIXER_MESSAGE_TYPE +GST_MIXER +GST_MIXER_CLASS +GST_MIXER_GET_CLASS +GST_MIXER_TYPE +GST_IS_MIXER +GST_IS_MIXER_CLASS +GST_TYPE_STREAM_VOLUME_FORMAT +gst_mixer_get_type +gst_mixer_type_get_type +gst_mixer_flags_get_type +gst_mixer_message_type_get_type +gst_stream_volume_format_get_type +
+ +
+gstmixeroptions +gst/interfaces/mixer.h +GstMixerOptions +gst_mixer_options_get_values + +GstMixerOptionsClass +GST_TYPE_MIXER_OPTIONS +GST_MIXER_OPTIONS +GST_MIXER_OPTIONS_CLASS +GST_IS_MIXER_OPTIONS +GST_IS_MIXER_OPTIONS_CLASS +GST_MIXER_OPTIONS_GET_CLASS +gst_mixer_options_get_type +
+ +
+gstmixertrack +gst/interfaces/mixer.h +GstMixerTrack +GstMixerTrackFlags +GST_MIXER_TRACK_HAS_FLAG + +GstMixerTrackClass +GST_TYPE_MIXER_TRACK +GST_TYPE_MIXER_TRACK_FLAGS +GST_MIXER_TRACK +GST_MIXER_TRACK_CLASS +GST_IS_MIXER_TRACK +GST_IS_MIXER_TRACK_CLASS +gst_mixer_track_flags_get_type +gst_mixer_track_get_type +
+ +
+gstnavigation +gst/interfaces/navigation.h +GstNavigation +GstNavigationInterface +GstNavigationCommand +GstNavigationEventType +GstNavigationMessageType +GstNavigationQueryType + +gst_navigation_send_event +gst_navigation_send_key_event +gst_navigation_send_mouse_event +gst_navigation_send_command + +gst_navigation_event_parse_command +gst_navigation_event_parse_key_event +gst_navigation_event_parse_mouse_button_event +gst_navigation_event_parse_mouse_move_event +gst_navigation_message_get_type +gst_navigation_message_new_angles_changed +gst_navigation_message_new_commands_changed +gst_navigation_message_new_mouse_over +gst_navigation_message_parse_mouse_over +gst_navigation_message_parse_angles_changed +gst_navigation_query_new_angles +gst_navigation_query_get_type +gst_navigation_query_new_commands +gst_navigation_query_parse_angles +gst_navigation_query_parse_commands_length +gst_navigation_query_parse_commands_nth +gst_navigation_query_set_angles +gst_navigation_query_set_commands +gst_navigation_query_set_commandsv + +GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU +GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU +GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU +GST_NAVIGATION_COMMAND_DVD_MENU +GST_NAVIGATION_COMMAND_DVD_ROOT_MENU +GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU +GST_NAVIGATION_COMMAND_DVD_TITLE_MENU + + +GST_TYPE_NAVIGATION +GST_NAVIGATION +GST_NAVIGATION_GET_IFACE +GST_TYPE_NAVIGATION_COMMAND +GST_TYPE_NAVIGATION_EVENT_TYPE +GST_TYPE_NAVIGATION_MESSAGE_TYPE +GST_TYPE_NAVIGATION_QUERY_TYPE +GST_IS_NAVIGATION +gst_navigation_get_type +gst_navigation_event_get_type +gst_navigation_event_type_get_type +gst_navigation_message_type_get_type +gst_navigation_query_type_get_type +gst_navigation_command_get_type +
+ +
+gstpropertyprobe +gst/interfaces/propertyprobe.h +GstPropertyProbe +GstPropertyProbeInterface + +gst_property_probe_get_properties +gst_property_probe_get_property +gst_property_probe_get_values +gst_property_probe_get_values_name +gst_property_probe_needs_probe +gst_property_probe_needs_probe_name +gst_property_probe_probe_and_get_values +gst_property_probe_probe_and_get_values_name +gst_property_probe_probe_property +gst_property_probe_probe_property_name + +GST_TYPE_PROPERTY_PROBE +GST_PROPERTY_PROBE +GST_PROPERTY_PROBE_GET_IFACE +GST_IS_PROPERTY_PROBE +gst_property_probe_get_type +
+ +
+gststreamvolume +gst/interfaces/streamvolume.h +GstStreamVolume +GstStreamVolumeFormat + +gst_stream_volume_get_volume +gst_stream_volume_set_volume + +gst_stream_volume_get_mute +gst_stream_volume_set_mute + +gst_stream_volume_convert_volume + + +GstStreamVolumeInterface +GST_TYPE_STREAM_VOLUME +GST_STREAM_VOLUME +GST_STREAM_VOLUME_INTERFACE +GST_STREAM_VOLUME_GET_INTERFACE +GST_IS_STREAM_VOLUME +GST_IS_STREAM_VOLUME_INTERFACE +gst_stream_volume_get_type +
+ +
+gsttuner +gst/interfaces/tuner.h +GstTuner +GstTunerClass + +gst_tuner_list_channels +gst_tuner_get_channel +gst_tuner_set_channel + +gst_tuner_list_norms +gst_tuner_get_norm +gst_tuner_set_norm + +gst_tuner_get_frequency +gst_tuner_set_frequency +gst_tuner_signal_strength + +gst_tuner_find_norm_by_name +gst_tuner_find_channel_by_name + +gst_tuner_channel_changed +gst_tuner_norm_changed +gst_tuner_frequency_changed +gst_tuner_signal_changed + +GST_TYPE_TUNER +GST_TUNER +GST_TUNER_CLASS +GST_TUNER_GET_CLASS +GST_IS_TUNER +GST_IS_TUNER_CLASS +gst_tuner_get_type +
+ +
+gsttunerchannel +gst/interfaces/tuner.h +GstTunerChannel +GstTunerChannelFlags +GST_TUNER_CHANNEL_HAS_FLAG + +GstTunerChannelClass +GST_TYPE_TUNER_CHANNEL +GST_TYPE_TUNER_CHANNEL_FLAGS +GST_TUNER_CHANNEL +GST_TUNER_CHANNEL_CLASS +GST_IS_TUNER_CHANNEL +GST_IS_TUNER_CHANNEL_CLASS +gst_tuner_channel_flags_get_type +gst_tuner_channel_get_type +
+ +
+gsttunernorm +gst/interfaces/tuner.h +GstTunerNorm + +GstTunerNormClass +GST_TYPE_TUNER_NORM +GST_TUNER_NORM +GST_TUNER_NORM_CLASS +GST_IS_TUNER_NORM +GST_IS_TUNER_NORM_CLASS +gst_tuner_norm_get_type +
+ +
+gstvideoorientation +gst/interfaces/videoorientation.h +GstVideoOrientation +GstVideoOrientationInterface +gst_video_orientation_get_hcenter +gst_video_orientation_get_hflip +gst_video_orientation_get_vcenter +gst_video_orientation_get_vflip +gst_video_orientation_set_hcenter +gst_video_orientation_set_hflip +gst_video_orientation_set_vcenter +gst_video_orientation_set_vflip + +GST_TYPE_VIDEO_ORIENTATION +GST_VIDEO_ORIENTATION +GST_IS_VIDEO_ORIENTATION +GST_VIDEO_ORIENTATION_GET_IFACE +gst_video_orientation_get_type +
+ +
+gstxoverlay +gst/interfaces/xoverlay.h +GstXOverlay +GstXOverlayClass +gst_x_overlay_set_xwindow_id +gst_x_overlay_got_xwindow_id +gst_x_overlay_got_window_handle +gst_x_overlay_set_window_handle +gst_x_overlay_prepare_xwindow_id +gst_x_overlay_expose +gst_x_overlay_handle_events +gst_x_overlay_set_render_rectangle + +GST_TYPE_X_OVERLAY +GST_X_OVERLAY +GST_X_OVERLAY_CLASS +GST_X_OVERLAY_GET_CLASS +GST_IS_X_OVERLAY +GST_IS_X_OVERLAY_CLASS +gst_x_overlay_get_type +
+ + +# netbuffer + +
+gstnetbuffer +gst/netbuffer/gstnetbuffer.h +GstNetBuffer +GstNetType +GST_NETADDRESS_MAX_LEN +GstNetAddress + +gst_netbuffer_new +gst_netaddress_get_net_type + +gst_netaddress_set_ip4_address +gst_netaddress_get_ip4_address + +gst_netaddress_set_ip6_address +gst_netaddress_get_ip6_address + +gst_netaddress_get_address_bytes +gst_netaddress_set_address_bytes + +gst_netaddress_equal + +gst_netaddress_to_string + +GstNetBufferClass +GST_TYPE_NETBUFFER +GST_NETBUFFER +GST_NETBUFFER_CLASS +GST_NETBUFFER_GET_CLASS +GST_IS_NETBUFFER +GST_IS_NETBUFFER_CLASS +gst_netbuffer_get_type +
+ + +# riff + +
+gstriff +gst/riff/riff-media.h +GST_RIFF_00 +GST_RIFF_0021 +GST_RIFF_0031 +GST_RIFF_0032 +GST_RIFF_00AM +GST_RIFF_00__ +GST_RIFF_00db +GST_RIFF_00dc +GST_RIFF_00dx +GST_RIFF_00id +GST_RIFF_00iv +GST_RIFF_00pc +GST_RIFF_00rt +GST_RIFF_00vc +GST_RIFF_00xm +GST_RIFF_00xx +GST_RIFF_01 +GST_RIFF_01dc +GST_RIFF_01pc +GST_RIFF_01wb +GST_RIFF_02 +GST_RIFF_03 +GST_RIFF_04 +GST_RIFF_05 +GST_RIFF_06 +GST_RIFF_07 +GST_RIFF_AURA +GST_RIFF_BW10 +GST_RIFF_CCC +GST_RIFF_CRAM +GST_RIFF_CVID +GST_RIFF_CYUV +GST_RIFF_DIB +GST_RIFF_DISP +GST_RIFF_DIV3 +GST_RIFF_DMB1 +GST_RIFF_FCCH_MSVC +GST_RIFF_FCCH_RLE +GST_RIFF_FCCH_msvc +GST_RIFF_FCC_auds +GST_RIFF_FCC_iavs +GST_RIFF_FCC_pads +GST_RIFF_FCC_txts +GST_RIFF_FCC_vidc +GST_RIFF_FCC_vids +GST_RIFF_FF00 +GST_RIFF_H263 +GST_RIFF_I420 +GST_RIFF_IDIT +GST_RIFF_IJPG +GST_RIFF_INFO_IARL +GST_RIFF_INFO_IART +GST_RIFF_INFO_ICMS +GST_RIFF_INFO_ICMT +GST_RIFF_INFO_ICOP +GST_RIFF_INFO_ICRD +GST_RIFF_INFO_ICRP +GST_RIFF_INFO_IDIM +GST_RIFF_INFO_IDPI +GST_RIFF_INFO_IENG +GST_RIFF_INFO_IGNR +GST_RIFF_INFO_IKEY +GST_RIFF_INFO_ILGT +GST_RIFF_INFO_IMED +GST_RIFF_INFO_INAM +GST_RIFF_INFO_IPLT +GST_RIFF_INFO_IPRD +GST_RIFF_INFO_ISBJ +GST_RIFF_INFO_ISFT +GST_RIFF_INFO_ISHP +GST_RIFF_INFO_ISRC +GST_RIFF_INFO_ISRF +GST_RIFF_INFO_ITCH +GST_RIFF_ISBJ +GST_RIFF_ISFT +GST_RIFF_IV31 +GST_RIFF_IV32 +GST_RIFF_IV41 +GST_RIFF_IV50 +GST_RIFF_IYUV +GST_RIFF_JPEG +GST_RIFF_L263 +GST_RIFF_LIST_AVIX +GST_RIFF_LIST_INFO +GST_RIFF_LIST_adtl +GST_RIFF_LIST_hdrl +GST_RIFF_LIST_movi +GST_RIFF_LIST_odml +GST_RIFF_LIST_strl +GST_RIFF_M263 +GST_RIFF_MJPG +GST_RIFF_MPIX +GST_RIFF_MVI1 +GST_RIFF_NONE +GST_RIFF_PACK +GST_RIFF_Q1_0 +GST_RIFF_RAW +GST_RIFF_RGB +GST_RIFF_RIFF_AVI +GST_RIFF_RIFF_CDXA +GST_RIFF_RIFF_WAVE +GST_RIFF_RLE4 +GST_RIFF_RLE8 +GST_RIFF_RT21 +GST_RIFF_SFMC +GST_RIFF_TAG_acid +GST_RIFF_TAG_AVF0 +GST_RIFF_TAG_BEXT +GST_RIFF_TAG_JUNK +GST_RIFF_TAG_JUNQ +GST_RIFF_TAG_LIST +GST_RIFF_TAG_RIFF +GST_RIFF_TAG_RIFX +GST_RIFF_TAG_avih +GST_RIFF_TAG_bext +GST_RIFF_TAG_cue +GST_RIFF_TAG_data +GST_RIFF_TAG_dmlh +GST_RIFF_TAG_fact +GST_RIFF_TAG_fmt +GST_RIFF_TAG_idx1 +GST_RIFF_TAG_plst +GST_RIFF_TAG_strd +GST_RIFF_TAG_strf +GST_RIFF_TAG_strh +GST_RIFF_TAG_strn +GST_RIFF_TAG_vedt +GST_RIFF_TRAN +GST_RIFF_ULTI +GST_RIFF_V422 +GST_RIFF_VDOW +GST_RIFF_VIXL +GST_RIFF_VSSH +GST_RIFF_VYUY +GST_RIFF_WHAM +GST_RIFF_WINX +GST_RIFF_WPY2 +GST_RIFF_XMPG +GST_RIFF_Y41P +GST_RIFF_YUV8 +GST_RIFF_YUV9 +GST_RIFF_YUY2 +GST_RIFF_YV12 +GST_RIFF_YVU9 +GST_RIFF_azpr +GST_RIFF_bw10 +GST_RIFF_ccc +GST_RIFF_cram +GST_RIFF_cvid +GST_RIFF_cyuv +GST_RIFF_dmb1 +GST_RIFF_h263 +GST_RIFF_i263 +GST_RIFF_i420 +GST_RIFF_iv31 +GST_RIFF_iv32 +GST_RIFF_iv41 +GST_RIFF_iv50 +GST_RIFF_iyuv +GST_RIFF_jpeg +GST_RIFF_m263 +GST_RIFF_mJPG +GST_RIFF_mvi1 +GST_RIFF_none +GST_RIFF_pack +GST_RIFF_rec +GST_RIFF_rgb +GST_RIFF_rle4 +GST_RIFF_rle8 +GST_RIFF_rpza +GST_RIFF_rt21 +GST_RIFF_tran +GST_RIFF_ulti +GST_RIFF_v422 +GST_RIFF_vixl +GST_RIFF_vyuy +GST_RIFF_wham +GST_RIFF_x263 +GST_RIFF_xmpg +GST_RIFF_y41p +GST_RIFF_yuy2 +GST_RIFF_yv12 + +gst_riff_acid +gst_riff_create_audio_caps +gst_riff_create_audio_template_caps +gst_riff_create_iavs_caps +gst_riff_create_iavs_template_caps +gst_riff_create_video_caps +gst_riff_create_video_template_caps +gst_riff_dmlh +gst_riff_index_entry +gst_riff_init +gst_riff_parse_chunk +gst_riff_parse_file_header +gst_riff_parse_info +gst_riff_parse_strf_auds +gst_riff_parse_strf_iavs +gst_riff_parse_strf_vids +gst_riff_parse_strh +gst_riff_read_chunk +gst_riff_strf_auds +gst_riff_strf_iavs +gst_riff_strf_vids +gst_riff_strh + +
+ + +# rtp + +
+gstbasertpaudiopayload +gst/rtp/gstbasertpaudiopayload.h +GstBaseRTPAudioPayload +GstBaseRTPAudioPayloadClass + +gst_base_rtp_audio_payload_set_frame_based +gst_base_rtp_audio_payload_set_frame_options +gst_base_rtp_audio_payload_set_sample_based +gst_base_rtp_audio_payload_set_sample_options +gst_base_rtp_audio_payload_get_adapter +gst_base_rtp_audio_payload_push +gst_base_rtp_audio_payload_flush +gst_base_rtp_audio_payload_set_samplebits_options + +GST_TYPE_BASE_RTP_AUDIO_PAYLOAD +GST_BASE_RTP_AUDIO_PAYLOAD +GST_BASE_RTP_AUDIO_PAYLOAD_CLASS +GST_IS_BASE_RTP_AUDIO_PAYLOAD +GST_IS_BASE_RTP_AUDIO_PAYLOAD_CLASS +GST_BASE_RTP_AUDIO_PAYLOAD_CAST +gst_base_rtp_audio_payload_get_type +GstBaseRTPAudioPayloadPrivate +
+ +
+gstbasertpdepayload +gst/rtp/gstbasertpdepayload.h +GstBaseRTPDepayload +GstBaseRTPDepayloadClass + +GST_BASE_RTP_DEPAYLOAD_SINKPAD +GST_BASE_RTP_DEPAYLOAD_SRCPAD + +gst_base_rtp_depayload_push +gst_base_rtp_depayload_push_ts +gst_base_rtp_depayload_push_list + + +GstBaseRTPDepayloadPrivate +GST_TYPE_BASE_RTP_DEPAYLOAD +GST_BASE_RTP_DEPAYLOAD +GST_BASE_RTP_DEPAYLOAD_CLASS +GST_BASE_RTP_DEPAYLOAD_GET_CLASS +GST_IS_BASE_RTP_DEPAYLOAD +GST_IS_BASE_RTP_DEPAYLOAD_CLASS +GST_BASE_RTP_PAYLOAD_CAST +gst_base_rtp_depayload_get_type +GstBaseRTPPayloadPrivate + + +QUEUE_LOCK_INIT +QUEUE_LOCK_FREE +QUEUE_LOCK +QUEUE_UNLOCK +
+ +
+gstbasertppayload +gst/rtp/gstbasertppayload.h +GstBaseRTPPayload +GstBaseRTPPayloadClass + +GST_BASE_RTP_PAYLOAD_MTU +GST_BASE_RTP_PAYLOAD_PT +GST_BASE_RTP_PAYLOAD_SINKPAD +GST_BASE_RTP_PAYLOAD_SRCPAD + +gst_basertppayload_is_filled +gst_basertppayload_push +gst_basertppayload_push_list +gst_basertppayload_set_options +gst_basertppayload_set_outcaps + +GST_TYPE_BASE_RTP_PAYLOAD +GST_BASE_RTP_PAYLOAD +GST_BASE_RTP_PAYLOAD_CLASS +GST_BASE_RTP_PAYLOAD_GET_CLASS +GST_IS_BASE_RTP_PAYLOAD +GST_IS_BASE_RTP_PAYLOAD_CLASS +gst_basertppayload_get_type +
+ +
+gstrtcpbuffer +gst/rtp/gstrtcpbuffer.h + +GST_RTCP_VERSION + +GST_RTCP_MAX_SDES +GST_RTCP_MAX_BYE_SSRC_COUNT +GST_RTCP_MAX_RB_COUNT +GST_RTCP_MAX_SDES_ITEM_COUNT +GST_RTCP_VALID_MASK +GST_RTCP_VALID_VALUE + +GstRTCPType +GstRTCPPacket +GstRTCPSDESType +GstRTCPFBType + +gst_rtcp_buffer_new_take_data +gst_rtcp_buffer_new_copy_data + +gst_rtcp_buffer_validate_data +gst_rtcp_buffer_validate + +gst_rtcp_buffer_new +gst_rtcp_buffer_end + +gst_rtcp_buffer_get_packet_count +gst_rtcp_buffer_get_first_packet +gst_rtcp_packet_move_to_next +gst_rtcp_buffer_add_packet +gst_rtcp_packet_remove + +gst_rtcp_packet_get_padding +gst_rtcp_packet_get_count +gst_rtcp_packet_get_type +gst_rtcp_packet_get_length + +gst_rtcp_packet_sr_get_sender_info +gst_rtcp_packet_sr_set_sender_info + +gst_rtcp_packet_rr_get_ssrc +gst_rtcp_packet_rr_set_ssrc + +gst_rtcp_packet_get_rb_count +gst_rtcp_packet_get_rb +gst_rtcp_packet_add_rb +gst_rtcp_packet_set_rb + +gst_rtcp_packet_sdes_get_item_count +gst_rtcp_packet_sdes_first_item +gst_rtcp_packet_sdes_next_item +gst_rtcp_packet_sdes_get_ssrc +gst_rtcp_packet_sdes_first_entry +gst_rtcp_packet_sdes_next_entry +gst_rtcp_packet_sdes_get_entry +gst_rtcp_packet_sdes_copy_entry + +gst_rtcp_packet_sdes_add_item +gst_rtcp_packet_sdes_add_entry + +gst_rtcp_packet_bye_get_ssrc_count +gst_rtcp_packet_bye_get_nth_ssrc +gst_rtcp_packet_bye_add_ssrc +gst_rtcp_packet_bye_add_ssrcs + +gst_rtcp_packet_bye_get_reason_len +gst_rtcp_packet_bye_get_reason +gst_rtcp_packet_bye_set_reason + +gst_rtcp_packet_fb_get_type +gst_rtcp_packet_fb_set_type + +gst_rtcp_packet_fb_get_sender_ssrc +gst_rtcp_packet_fb_set_sender_ssrc + +gst_rtcp_packet_fb_get_media_ssrc +gst_rtcp_packet_fb_set_media_ssrc + +gst_rtcp_packet_fb_get_fci_length +gst_rtcp_packet_fb_set_fci_length +gst_rtcp_packet_fb_get_fci + +gst_rtcp_ntp_to_unix +gst_rtcp_unix_to_ntp + +gst_rtcp_sdes_name_to_type +gst_rtcp_sdes_type_to_name + + +
+ +
+gstrtppayloads +gst/rtp/gstrtppayload.h +GstRTPPayload +GST_RTP_PAYLOAD_IS_DYNAMIC + +GstRTPPayloadInfo + +gst_rtp_payload_info_for_name +gst_rtp_payload_info_for_pt + + +GST_RTP_PAYLOAD_DYNAMIC_STRING +GST_RTP_PAYLOAD_G723_53_STRING +GST_RTP_PAYLOAD_G723_63_STRING +GST_RTP_PAYLOAD_G728_STRING +GST_RTP_PAYLOAD_G729_STRING +GST_RTP_PAYLOAD_GSM_STRING +GST_RTP_PAYLOAD_H263_STRING +GST_RTP_PAYLOAD_L16_MONO_STRING +GST_RTP_PAYLOAD_L16_STEREO_STRING +GST_RTP_PAYLOAD_MPA_STRING +GST_RTP_PAYLOAD_MPV_STRING +GST_RTP_PAYLOAD_PCMA_STRING +GST_RTP_PAYLOAD_PCMU_STRING +GST_RTP_PAYLOAD_TS41_STRING +GST_RTP_PAYLOAD_TS48_STRING +GST_RTP_PAYLOAD_1016_STRING +GST_RTP_PAYLOAD_CELLB_STRING +GST_RTP_PAYLOAD_CN_STRING +GST_RTP_PAYLOAD_DVI4_11025_STRING +GST_RTP_PAYLOAD_DVI4_16000_STRING +GST_RTP_PAYLOAD_DVI4_22050_STRING +GST_RTP_PAYLOAD_DVI4_8000_STRING +GST_RTP_PAYLOAD_G721_STRING +GST_RTP_PAYLOAD_G722_STRING +GST_RTP_PAYLOAD_G723_53 +GST_RTP_PAYLOAD_G723_63 +GST_RTP_PAYLOAD_G723_STRING +GST_RTP_PAYLOAD_H261_STRING +GST_RTP_PAYLOAD_JPEG_STRING +GST_RTP_PAYLOAD_LPC_STRING +GST_RTP_PAYLOAD_MP2T_STRING +GST_RTP_PAYLOAD_NV_STRING +GST_RTP_PAYLOAD_QCELP_STRING +GST_RTP_PAYLOAD_TS41 +GST_RTP_PAYLOAD_TS48 +
+ +
+gstrtpbuffer +gst/rtp/gstrtpbuffer.h + +GST_RTP_VERSION + +gst_rtp_buffer_allocate_data + +gst_rtp_buffer_new_take_data +gst_rtp_buffer_new_copy_data +gst_rtp_buffer_new_allocate +gst_rtp_buffer_new_allocate_len +gst_rtp_buffer_list_from_buffer + +gst_rtp_buffer_calc_header_len +gst_rtp_buffer_calc_packet_len +gst_rtp_buffer_calc_payload_len + +gst_rtp_buffer_validate +gst_rtp_buffer_validate_data + +gst_rtp_buffer_set_packet_len +gst_rtp_buffer_get_packet_len + +gst_rtp_buffer_get_header_len + +gst_rtp_buffer_get_version +gst_rtp_buffer_set_version + +gst_rtp_buffer_get_padding +gst_rtp_buffer_set_padding +gst_rtp_buffer_pad_to + +gst_rtp_buffer_get_extension +gst_rtp_buffer_set_extension +gst_rtp_buffer_get_extension_data + +gst_rtp_buffer_get_ssrc +gst_rtp_buffer_set_ssrc + +gst_rtp_buffer_get_csrc_count +gst_rtp_buffer_get_csrc +gst_rtp_buffer_set_csrc + +gst_rtp_buffer_get_marker +gst_rtp_buffer_set_marker + +gst_rtp_buffer_get_payload_type +gst_rtp_buffer_set_payload_type + +gst_rtp_buffer_get_seq +gst_rtp_buffer_set_seq + +gst_rtp_buffer_get_timestamp +gst_rtp_buffer_set_timestamp + +gst_rtp_buffer_get_payload_buffer +gst_rtp_buffer_get_payload_subbuffer +gst_rtp_buffer_get_payload_len +gst_rtp_buffer_get_payload + +gst_rtp_buffer_default_clock_rate +gst_rtp_buffer_compare_seqnum +gst_rtp_buffer_ext_timestamp +gst_rtp_buffer_set_extension_data + +gst_rtp_buffer_list_validate + +gst_rtp_buffer_list_get_payload_len + +gst_rtp_buffer_list_get_payload_type +gst_rtp_buffer_list_set_payload_type + +gst_rtp_buffer_list_get_seq +gst_rtp_buffer_list_set_seq + +gst_rtp_buffer_list_get_ssrc +gst_rtp_buffer_list_set_ssrc + +gst_rtp_buffer_list_get_timestamp +gst_rtp_buffer_list_set_timestamp + +gst_rtp_buffer_get_extension_onebyte_header +gst_rtp_buffer_get_extension_twobytes_header +gst_rtp_buffer_add_extension_onebyte_header +gst_rtp_buffer_add_extension_twobytes_header + +gst_rtp_buffer_list_get_extension_onebyte_header +gst_rtp_buffer_list_get_extension_twobytes_header +gst_rtp_buffer_list_add_extension_onebyte_header +gst_rtp_buffer_list_add_extension_twobytes_header +
+ +# rtsp +
+gstrtspdefs +gst/rtsp/gstrtspdefs.h +GST_RTSP_CHECK +GstRTSPEvent +GstRTSPResult +GstRTSPFamily +GstRTSPState +GstRTSPVersion +GstRTSPMethod +GstRTSPAuthMethod +GST_RTSP_AUTH_MAX +GstRTSPHeaderField +GstRTSPStatusCode +gst_rtsp_strresult +gst_rtsp_method_as_text +gst_rtsp_version_as_text +gst_rtsp_header_as_text +gst_rtsp_header_allow_multiple +gst_rtsp_status_as_text +gst_rtsp_options_as_text +gst_rtsp_find_header_field +gst_rtsp_find_method + +GST_TYPE_RTSP_AUTH_METHOD +GST_TYPE_RTSP_EVENT +GST_TYPE_RTSP_FAMILY +GST_TYPE_RTSP_HEADER_FIELD +GST_TYPE_RTSP_LOWER_TRANS +GST_TYPE_RTSP_METHOD +GST_TYPE_RTSP_RESULT +GST_TYPE_RTSP_STATE +GST_TYPE_RTSP_STATUS_CODE +GST_TYPE_RTSP_URL +GST_TYPE_RTSP_VERSION +gst_rtsp_event_get_type +gst_rtsp_auth_method_get_type +gst_rtsp_family_get_type +gst_rtsp_method_get_type +gst_rtsp_result_get_type +gst_rtsp_state_get_type +gst_rtsp_status_code_get_type +gst_rtsp_version_get_type +gst_rtsp_header_field_get_type +
+ +
+gstrtsptransport +gst/rtsp/gstrtsptransport.h +GstRTSPTransMode +GstRTSPProfile +GstRTSPRange +GstRTSPLowerTrans +GstRTSPTransport +gst_rtsp_transport_new +gst_rtsp_transport_init +gst_rtsp_transport_parse +gst_rtsp_transport_as_text +gst_rtsp_transport_get_mime +gst_rtsp_transport_get_manager +gst_rtsp_transport_free + +gst_rtsp_lower_trans_get_type +
+ +
+gstrtspbase64 +gst/rtsp/gstrtspbase64.h +gst_rtsp_base64_encode +gst_rtsp_base64_decode_ip +
+ +
+gstrtspconnection +gst/rtsp/gstrtspconnection.h +GstRTSPConnection +gst_rtsp_connection_create +gst_rtsp_connection_create_from_fd +gst_rtsp_connection_accept +gst_rtsp_connection_connect +gst_rtsp_connection_close +gst_rtsp_connection_free + +gst_rtsp_connection_read +gst_rtsp_connection_write +gst_rtsp_connection_poll + +gst_rtsp_connection_send +gst_rtsp_connection_receive + +gst_rtsp_connection_next_timeout +gst_rtsp_connection_reset_timeout + +gst_rtsp_connection_flush + +gst_rtsp_connection_set_auth +gst_rtsp_connection_set_auth_param +gst_rtsp_connection_clear_auth_params + +gst_rtsp_connection_set_qos_dscp + +gst_rtsp_connection_set_ip +gst_rtsp_connection_get_ip + +gst_rtsp_connection_get_url + +gst_rtsp_connection_set_tunneled +gst_rtsp_connection_is_tunneled + +gst_rtsp_connection_get_tunnelid +gst_rtsp_connection_do_tunnel + +gst_rtsp_connection_get_readfd +gst_rtsp_connection_get_writefd +gst_rtsp_connection_set_http_mode +gst_rtsp_connection_set_proxy + +GstRTSPWatch +GstRTSPWatchFuncs +gst_rtsp_watch_new +gst_rtsp_watch_unref +gst_rtsp_watch_attach +gst_rtsp_watch_reset +gst_rtsp_watch_queue_message +gst_rtsp_watch_queue_data +gst_rtsp_watch_send_message +gst_rtsp_watch_write_data +
+ +
+gstrtspextension +gst/rtsp/gstrtspextension.h +GstRTSPExtension +GstRTSPExtensionInterface + +GST_IS_RTSP_EXTENSION +GST_RTSP_EXTENSION +GST_RTSP_EXTENSION_GET_IFACE +GST_TYPE_RTSP_EXTENSION +gst_rtsp_extension_after_send +gst_rtsp_extension_before_send +gst_rtsp_extension_configure_stream +gst_rtsp_extension_detect_server +gst_rtsp_extension_get_transports +gst_rtsp_extension_parse_sdp +gst_rtsp_extension_receive_request +gst_rtsp_extension_send +gst_rtsp_extension_setup_media +gst_rtsp_extension_stream_select +gst_rtsp_extension_get_type +
+ +
+gstrtspmessage +gst/rtsp/gstrtspmessage.h +GstRTSPMsgType +GstRTSPMessage +gst_rtsp_message_new +gst_rtsp_message_init +gst_rtsp_message_unset +gst_rtsp_message_free +gst_rtsp_message_get_type +gst_rtsp_message_new_request +gst_rtsp_message_init_request +gst_rtsp_message_parse_request +gst_rtsp_message_new_response +gst_rtsp_message_init_response +gst_rtsp_message_parse_response +gst_rtsp_message_new_data +gst_rtsp_message_init_data +gst_rtsp_message_parse_data +gst_rtsp_message_add_header +gst_rtsp_message_take_header +gst_rtsp_message_remove_header +gst_rtsp_message_get_header +gst_rtsp_message_append_headers +gst_rtsp_message_set_body +gst_rtsp_message_take_body +gst_rtsp_message_get_body +gst_rtsp_message_steal_body +gst_rtsp_message_dump +
+ +
+gstrtspurl +gst/rtsp/gstrtspurl.h +GST_RTSP_DEFAULT_PORT +GstRTSPUrl +gst_rtsp_url_parse +gst_rtsp_url_copy +gst_rtsp_url_free +gst_rtsp_url_get_request_uri +gst_rtsp_url_set_port +gst_rtsp_url_get_port +gst_rtsp_url_decode_path_components + +gst_rtsp_url_get_type +
+ +
+gstrtsprange +gst/rtsp/gstrtsrange.h +GstRTSPRangeUnit +GstRTSPTimeRange +GstRTSPTime +GstRTSPTimeType +gst_rtsp_range_parse +gst_rtsp_range_to_string +gst_rtsp_range_free +
+ +# sdp +
+gstsdpmessage +gst/sdp/gstsdpmessage.h +GstSDPResult +GstSDPOrigin +GstSDPConnection +GST_SDP_BWTYPE_CT +GST_SDP_BWTYPE_AS +GST_SDP_BWTYPE_EXT_PREFIX +GST_SDP_BWTYPE_RR +GST_SDP_BWTYPE_RS +GST_SDP_BWTYPE_TIAS +GstSDPBandwidth +GstSDPTime +GstSDPZone +GstSDPKey +GstSDPAttribute +GstSDPMedia +GstSDPMessage +gst_sdp_message_new +gst_sdp_message_init +gst_sdp_message_uninit +gst_sdp_message_free + +gst_sdp_message_parse_buffer +gst_sdp_message_as_text + +gst_sdp_message_parse_uri +gst_sdp_message_as_uri + +gst_sdp_address_is_multicast + +gst_sdp_message_get_version +gst_sdp_message_set_version +gst_sdp_message_get_origin +gst_sdp_message_set_origin +gst_sdp_message_get_session_name +gst_sdp_message_set_session_name +gst_sdp_message_get_information +gst_sdp_message_set_information +gst_sdp_message_get_uri +gst_sdp_message_set_uri +gst_sdp_message_emails_len +gst_sdp_message_get_email +gst_sdp_message_add_email +gst_sdp_message_phones_len +gst_sdp_message_get_phone +gst_sdp_message_add_phone +gst_sdp_message_get_connection +gst_sdp_message_set_connection +gst_sdp_message_bandwidths_len +gst_sdp_message_get_bandwidth +gst_sdp_message_add_bandwidth +gst_sdp_message_times_len +gst_sdp_message_get_time +gst_sdp_message_add_time +gst_sdp_message_zones_len +gst_sdp_message_get_zone +gst_sdp_message_add_zone +gst_sdp_message_get_key +gst_sdp_message_set_key +gst_sdp_message_attributes_len +gst_sdp_message_get_attribute +gst_sdp_message_get_attribute_val +gst_sdp_message_get_attribute_val_n +gst_sdp_message_add_attribute +gst_sdp_message_medias_len +gst_sdp_message_get_media +gst_sdp_message_add_media +gst_sdp_message_dump + +gst_sdp_media_new +gst_sdp_media_init +gst_sdp_media_uninit +gst_sdp_media_free +gst_sdp_media_get_media +gst_sdp_media_set_media +gst_sdp_media_get_port +gst_sdp_media_get_num_ports +gst_sdp_media_set_port_info +gst_sdp_media_get_proto +gst_sdp_media_set_proto +gst_sdp_media_formats_len +gst_sdp_media_get_format +gst_sdp_media_add_format +gst_sdp_media_get_information +gst_sdp_media_set_information +gst_sdp_media_connections_len +gst_sdp_media_get_connection +gst_sdp_media_add_connection +gst_sdp_media_bandwidths_len +gst_sdp_media_get_bandwidth +gst_sdp_media_add_bandwidth +gst_sdp_media_get_key +gst_sdp_media_set_key +gst_sdp_media_attributes_len +gst_sdp_media_get_attribute +gst_sdp_media_get_attribute_val +gst_sdp_media_get_attribute_val_n +gst_sdp_media_add_attribute +gst_sdp_media_as_text +
+ +# tag + +
+gsttag +gst/tag/tag.h +GST_TAG_MUSICBRAINZ_TRACKID +GST_TAG_MUSICBRAINZ_ARTISTID +GST_TAG_MUSICBRAINZ_ALBUMID +GST_TAG_MUSICBRAINZ_ALBUMARTISTID +GST_TAG_MUSICBRAINZ_TRMID +GST_TAG_MUSICBRAINZ_SORTNAME +GST_TAG_CDDA_CDDB_DISCID +GST_TAG_CDDA_CDDB_DISCID_FULL +GST_TAG_CDDA_MUSICBRAINZ_DISCID +GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL +GST_TAG_CDDA_TRACK_TAGS +GST_TAG_CMML_CLIP +GST_TAG_CMML_HEAD +GST_TAG_CMML_STREAM +GST_TAG_CAPTURING_SHUTTER_SPEED +GST_TAG_CAPTURING_FOCAL_RATIO +GST_TAG_CAPTURING_FOCAL_LENGTH +GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO +GST_TAG_CAPTURING_ISO_SPEED +GST_TAG_CAPTURING_EXPOSURE_PROGRAM +GST_TAG_CAPTURING_EXPOSURE_MODE +GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE +GST_TAG_CAPTURING_GAIN_ADJUSTMENT +GST_TAG_CAPTURING_WHITE_BALANCE +GST_TAG_CAPTURING_CONTRAST +GST_TAG_CAPTURING_SATURATION +GST_TAG_CAPTURING_SHARPNESS +GST_TAG_CAPTURING_FLASH_FIRED +GST_TAG_CAPTURING_FLASH_MODE +GST_TAG_CAPTURING_METERING_MODE +GST_TAG_CAPTURING_SOURCE +GST_TAG_IMAGE_HORIZONTAL_PPI +GST_TAG_IMAGE_VERTICAL_PPI +gst_tag_register_musicbrainz_tags +gst_tag_freeform_string_to_utf8 +gst_tag_parse_extended_comment +gst_tag_image_data_to_image_buffer +GstTagImageType + +GST_TYPE_TAG_IMAGE_TYPE +gst_tag_image_type_get_type + +GstTagEntryMatch +
+ +
+gsttagvorbis +gst/tag/tag.h + +gst_tag_from_vorbis_tag +gst_tag_to_vorbis_tag +gst_vorbis_tag_add +gst_tag_to_vorbis_comments + +gst_tag_list_from_vorbiscomment_buffer +gst_tag_list_to_vorbiscomment_buffer + +gst_vorbis_tag_get_type +
+ +
+gsttagid3 +gst/tag/tag.h + +gst_tag_id3_genre_count +gst_tag_id3_genre_get +gst_tag_list_new_from_id3v1 +gst_tag_from_id3_tag +gst_tag_from_id3_user_tag +gst_tag_to_id3_tag +gst_tag_list_add_id3_image +
+ +
+gsttagxmp +gst/tag/tag.h +gst_tag_list_from_xmp_buffer +gst_tag_list_to_xmp_buffer + +
+ +
+gsttagexif +gst/tag/tag.h +gst_tag_list_to_exif_buffer +gst_tag_list_to_exif_buffer_with_tiff_header +gst_tag_list_from_exif_buffer +gst_tag_list_from_exif_buffer_with_tiff_header + +
+ +
+gsttagdemux +gst/tag/gsttagdemux.h +GstTagDemux +GstTagDemuxClass +GstTagDemuxResult + +GstTagDemuxPrivate +GST_IS_TAG_DEMUX +GST_IS_TAG_DEMUX_CLASS +GST_TAG_DEMUX +GST_TAG_DEMUX_CLASS +GST_TYPE_TAG_DEMUX +GST_TYPE_TAG_DEMUX_RESULT +gst_tag_demux_get_type +gst_tag_demux_result_get_type +
+ +
+gsttaglanguagecodes +gst/tag/tag.h + +gst_tag_get_language_codes +gst_tag_get_language_name +gst_tag_get_language_code +gst_tag_get_language_code_iso_639_1 +gst_tag_get_language_code_iso_639_2B +gst_tag_get_language_code_iso_639_2T +
+ +# base utils + +
+gstpbutils +gst/pbutils/pbutils.h + +gst_pb_utils_init + +GST_PLUGINS_BASE_VERSION_MAJOR +GST_PLUGINS_BASE_VERSION_MINOR +GST_PLUGINS_BASE_VERSION_MICRO +GST_PLUGINS_BASE_VERSION_NANO +GST_CHECK_PLUGINS_BASE_VERSION +gst_plugins_base_version +gst_plugins_base_version_string +
+ +
+gstpbutilsmissingplugins +gst/pbutils/missing-plugins.h + +gst_missing_plugin_message_get_installer_detail +gst_missing_plugin_message_get_description +gst_is_missing_plugin_message + +gst_missing_decoder_message_new +gst_missing_encoder_message_new +gst_missing_uri_source_message_new +gst_missing_uri_sink_message_new +gst_missing_element_message_new + +gst_missing_uri_source_installer_detail_new +gst_missing_uri_sink_installer_detail_new +gst_missing_element_installer_detail_new +gst_missing_decoder_installer_detail_new +gst_missing_encoder_installer_detail_new +
+ +
+gstpbutilsinstallplugins +gst/pbutils/install-plugins.h + +GstInstallPluginsReturn +GstInstallPluginsResultFunc +gst_install_plugins_async +gst_install_plugins_sync +gst_install_plugins_return_get_name +gst_install_plugins_installation_in_progress +gst_install_plugins_supported + +GstInstallPluginsContext +gst_install_plugins_context_new +gst_install_plugins_context_free +gst_install_plugins_context_set_xid + +GST_TYPE_INSTALL_PLUGINS_CONTEXT +GST_TYPE_INSTALL_PLUGINS_RETURN +gst_install_plugins_context_get_type +gst_install_plugins_return_get_type +
+ +
+gstpbutilsdescriptions +gst/pbutils/descriptions.h + +gst_pb_utils_get_source_description +gst_pb_utils_get_sink_description +gst_pb_utils_get_decoder_description +gst_pb_utils_get_encoder_description +gst_pb_utils_get_element_description + +gst_pb_utils_add_codec_description_to_tag_list +gst_pb_utils_get_codec_description +
+ +
+gstpbutilscodecutils +gst/pbutils/codec-utils.h + +gst_codec_utils_aac_get_sample_rate_from_index +gst_codec_utils_aac_get_profile +gst_codec_utils_aac_get_level +gst_codec_utils_aac_caps_set_level_and_profile + +gst_codec_utils_h264_get_profile +gst_codec_utils_h264_get_level +gst_codec_utils_h264_caps_set_level_and_profile + +gst_codec_utils_mpeg4video_get_profile +gst_codec_utils_mpeg4video_get_level +gst_codec_utils_mpeg4video_caps_set_level_and_profile +
+ +
+encoding-profile +gst/pbutils/encoding-profile.h +GstEncodingProfile +gst_encoding_profile_unref +gst_encoding_profile_ref +gst_encoding_profile_find +gst_encoding_profile_get_name +gst_encoding_profile_get_description +gst_encoding_profile_get_format +gst_encoding_profile_get_preset +gst_encoding_profile_get_presence +gst_encoding_profile_get_restriction +gst_encoding_profile_set_name +gst_encoding_profile_set_description +gst_encoding_profile_set_format +gst_encoding_profile_set_preset +gst_encoding_profile_set_restriction +gst_encoding_profile_set_presence +gst_encoding_profile_is_equal +gst_encoding_profile_get_input_caps +gst_encoding_profile_get_type_nick + +GstEncodingContainerProfile +gst_encoding_container_profile_new +gst_encoding_container_profile_add_profile +gst_encoding_container_profile_contains_profile +gst_encoding_container_profile_get_profiles + +GstEncodingAudioProfile +gst_encoding_audio_profile_new + +GstEncodingVideoProfile +gst_encoding_video_profile_new +gst_encoding_video_profile_get_pass +gst_encoding_video_profile_get_variableframerate +gst_encoding_video_profile_set_pass +gst_encoding_video_profile_set_variableframerate + +GST_ENCODING_CATEGORY_DEVICE +GST_ENCODING_CATEGORY_ONLINE_SERVICE +GST_ENCODING_CATEGORY_STORAGE_EDITING +GST_ENCODING_CATEGORY_CAPTURE +GstEncodingTarget +gst_encoding_target_unref +gst_encoding_target_ref +gst_encoding_target_new +gst_encoding_target_get_name +gst_encoding_target_get_category +gst_encoding_target_get_description +gst_encoding_target_get_profiles +gst_encoding_target_get_profile +gst_encoding_target_add_profile +gst_encoding_target_save +gst_encoding_target_save_to_file +gst_encoding_target_load +gst_encoding_target_load_from_file +gst_encoding_list_all_targets +gst_encoding_list_available_categories + +GST_ENCODING_PROFILE +GST_IS_ENCODING_PROFILE +GST_TYPE_ENCODING_PROFILE +gst_encoding_profile_get_type +GST_ENCODING_TARGET +GST_IS_ENCODING_TARGET +GST_TYPE_ENCODING_TARGET +gst_encoding_target_get_type +GstEncodingProfileClass +GST_TYPE_ENCODING_CONTAINER_PROFILE +GST_ENCODING_CONTAINER_PROFILE +gst_encoding_container_profile_get_type +GST_TYPE_ENCODING_VIDEO_PROFILE +GST_ENCODING_VIDEO_PROFILE +GST_IS_ENCODING_VIDEO_PROFILE +GstEncodingVideoProfileClass +gst_encoding_video_profile_get_type +GST_TYPE_ENCODING_AUDIO_PROFILE +GST_ENCODING_AUDIO_PROFILE +GST_IS_ENCODING_AUDIO_PROFILE +GstEncodingAudioProfileClass +gst_encoding_audio_profile_get_type +GST_IS_ENCODING_CONTAINER_PROFILE +GstEncodingContainerProfileClass +GstEncodingTargetClass +
+ + + +# video + +
+gstvideo +gst/video/video.h +GST_VIDEO_BLUE_MASK_15 +GST_VIDEO_BLUE_MASK_15_INT +GST_VIDEO_BLUE_MASK_16 +GST_VIDEO_BLUE_MASK_16_INT +GST_VIDEO_BYTE1_MASK_24 +GST_VIDEO_BYTE1_MASK_24_INT +GST_VIDEO_BYTE1_MASK_32 +GST_VIDEO_BYTE1_MASK_32_INT +GST_VIDEO_BYTE2_MASK_24 +GST_VIDEO_BYTE2_MASK_24_INT +GST_VIDEO_BYTE2_MASK_32 +GST_VIDEO_BYTE2_MASK_32_INT +GST_VIDEO_BYTE3_MASK_24 +GST_VIDEO_BYTE3_MASK_24_INT +GST_VIDEO_BYTE3_MASK_32 +GST_VIDEO_BYTE3_MASK_32_INT +GST_VIDEO_BYTE4_MASK_32 +GST_VIDEO_BYTE4_MASK_32_INT +GST_VIDEO_CAPS_ABGR +GST_VIDEO_CAPS_ARGB +GST_VIDEO_CAPS_BGR +GST_VIDEO_CAPS_BGRA +GST_VIDEO_CAPS_BGRx +GST_VIDEO_CAPS_BGRx_HOST_ENDIAN +GST_VIDEO_CAPS_RGB +GST_VIDEO_CAPS_RGBA +GST_VIDEO_CAPS_RGB_15 +GST_VIDEO_CAPS_RGB_16 +GST_VIDEO_CAPS_RGBx +GST_VIDEO_CAPS_YUV +GST_VIDEO_CAPS_xBGR +GST_VIDEO_CAPS_xRGB +GST_VIDEO_CAPS_xRGB_HOST_ENDIAN +GST_VIDEO_CAPS_BGR_15 +GST_VIDEO_CAPS_BGR_16 +GST_VIDEO_CAPS_RGB8_PALETTED +GST_VIDEO_CAPS_GRAY8 +GST_VIDEO_CAPS_GRAY16 +GST_VIDEO_FPS_RANGE +GST_VIDEO_GREEN_MASK_15 +GST_VIDEO_GREEN_MASK_15_INT +GST_VIDEO_GREEN_MASK_16 +GST_VIDEO_GREEN_MASK_16_INT +GST_VIDEO_RED_MASK_15 +GST_VIDEO_RED_MASK_15_INT +GST_VIDEO_RED_MASK_16 +GST_VIDEO_RED_MASK_16_INT +GST_VIDEO_SIZE_RANGE +GST_VIDEO_BUFFER_TFF +GST_VIDEO_BUFFER_RFF +GST_VIDEO_BUFFER_ONEFIELD +GstVideoFormat +gst_video_calculate_display_ratio +gst_video_frame_rate +gst_video_get_size +gst_video_format_convert +gst_video_format_new_caps +gst_video_format_new_caps_interlaced +gst_video_format_get_component_height +gst_video_format_get_component_offset +gst_video_format_get_component_width +gst_video_format_get_pixel_stride +gst_video_format_get_row_stride +gst_video_format_get_size +gst_video_format_has_alpha +gst_video_format_is_rgb +gst_video_format_is_gray +gst_video_format_is_yuv +gst_video_format_to_fourcc +gst_video_format_from_fourcc +gst_video_format_parse_caps +gst_video_format_parse_caps_interlaced +gst_video_parse_caps_framerate +gst_video_parse_caps_pixel_aspect_ratio +gst_video_parse_caps_color_matrix +gst_video_parse_caps_chroma_site +gst_video_parse_caps_palette +GstVideoConvertFrameCallback +gst_video_convert_frame +gst_video_convert_frame_async +gst_video_event_new_still_frame +gst_video_event_parse_still_frame + +gst_video_format_get_type +GST_TYPE_VIDEO_FORMAT +
+ +
+gstvideofilter +gst/video/gstvideofilter.h +GstVideoFilter +GstVideoFilterClass + +GST_TYPE_VIDEO_FILTER +GST_VIDEO_FILTER +GST_VIDEO_FILTER_CLASS +GST_VIDEO_FILTER_GET_CLASS +GST_IS_VIDEO_FILTER +GST_IS_VIDEO_FILTER_CLASS +gst_video_filter_get_type +
+ +
+gstvideosink +gst/video/gstvideosink.h +GstVideoSink +GstVideoSinkClass +GstVideoRectangle +GST_VIDEO_SINK_HEIGHT +GST_VIDEO_SINK_PAD +GST_VIDEO_SINK_WIDTH +gst_video_sink_center_rect + +GstVideoSinkPrivate +GST_TYPE_VIDEO_SINK +GST_VIDEO_SINK +GST_VIDEO_SINK_CAST +GST_VIDEO_SINK_CLASS +GST_VIDEO_SINK_GET_CLASS +GST_IS_VIDEO_SINK +GST_IS_VIDEO_SINK_CLASS +gst_video_sink_get_type +
+ +
+gstdiscoverer +gst/pbutils/pbutils.h + +GstDiscoverer +gst_discoverer_new +gst_discoverer_start +gst_discoverer_stop +gst_discoverer_discover_uri +gst_discoverer_discover_uri_async + +GstDiscovererInfo +GstDiscovererResult +gst_discoverer_info_get_duration +gst_discoverer_info_get_misc +gst_discoverer_info_get_result +gst_discoverer_info_get_stream_info +gst_discoverer_info_get_stream_list +gst_discoverer_info_get_tags +gst_discoverer_info_get_uri +gst_discoverer_info_get_seekable +gst_discoverer_info_ref +gst_discoverer_info_unref + +GstDiscovererStreamInfo +GstDiscovererContainerInfo +GstDiscovererAudioInfo +GstDiscovererVideoInfo +gst_discoverer_stream_info_get_caps +gst_discoverer_stream_info_get_misc +gst_discoverer_stream_info_get_next +gst_discoverer_stream_info_get_previous +gst_discoverer_stream_info_get_tags +gst_discoverer_stream_info_ref +gst_discoverer_stream_info_unref +gst_discoverer_stream_info_list_free +gst_discoverer_stream_info_get_stream_type_nick +gst_discoverer_info_get_audio_streams +gst_discoverer_info_get_container_streams +gst_discoverer_info_get_streams +gst_discoverer_info_get_video_streams +gst_discoverer_audio_info_get_bitrate +gst_discoverer_audio_info_get_channels +gst_discoverer_audio_info_get_depth +gst_discoverer_audio_info_get_max_bitrate +gst_discoverer_audio_info_get_sample_rate +gst_discoverer_container_info_get_streams +gst_discoverer_video_info_get_bitrate +gst_discoverer_video_info_get_depth +gst_discoverer_video_info_get_framerate_denom +gst_discoverer_video_info_get_framerate_num +gst_discoverer_video_info_get_height +gst_discoverer_video_info_is_interlaced +gst_discoverer_video_info_is_image +gst_discoverer_video_info_get_max_bitrate +gst_discoverer_video_info_get_par_denom +gst_discoverer_video_info_get_par_num +gst_discoverer_video_info_get_width + +GST_DISCOVERER +GST_DISCOVERER_AUDIO_INFO +GST_DISCOVERER_CLASS +GST_DISCOVERER_CONTAINER_INFO +GST_DISCOVERER_INFO +GST_DISCOVERER_STREAM_INFO +GST_DISCOVERER_VIDEO_INFO +GST_IS_DISCOVERER +GST_IS_DISCOVERER_INFO +GST_IS_DISCOVERER_AUDIO_INFO +GST_IS_DISCOVERER_CLASS +GST_IS_DISCOVERER_CONTAINER_INFO +GST_IS_DISCOVERER_STREAM_INFO +GST_IS_DISCOVERER_VIDEO_INFO +GST_TYPE_DISCOVERER +GST_TYPE_DISCOVERER_AUDIO_INFO +GST_TYPE_DISCOVERER_CONTAINER_INFO +GST_TYPE_DISCOVERER_INFO +GST_TYPE_DISCOVERER_RESULT +GST_TYPE_DISCOVERER_STREAM_INFO +GST_TYPE_DISCOVERER_VIDEO_INFO +GstDiscovererAudioInfoClass +GstDiscovererClass +GstDiscovererContainerInfoClass +GstDiscovererPrivate +GstDiscovererStreamInfoClass +GstDiscovererVideoInfoClass +GstDiscovererInfoClass +gst_discoverer_audio_info_get_type +gst_discoverer_container_info_get_type +gst_discoverer_get_type +gst_discoverer_info_get_type +gst_discoverer_info_copy +gst_discoverer_result_get_type +gst_discoverer_stream_info_get_type +gst_discoverer_video_info_get_type +
+ +# private + +
+private + +bind_textdomain_codeset +bindtextdomain +dcgettext +dcngettext +dgettext +dngettext +gettext +gettext_noop +ngettext +textdomain +_ +N_ +
diff --git a/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs.types b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs.types new file mode 100644 index 0000000..f6c06af --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/libs/gst-plugins-base-libs.types @@ -0,0 +1,72 @@ +#include + + +#include +gst_audio_clock_get_type +#include +gst_audio_filter_get_type +#include +gst_audio_sink_get_type +#include +gst_audio_src_get_type +#include +gst_base_audio_sink_get_type +#include +gst_base_audio_src_get_type +#include +gst_ring_buffer_get_type + + +#include +gst_cdda_base_src_get_type + + +#include +gst_color_balance_get_type +gst_color_balance_channel_get_type +#include +gst_mixer_get_type +gst_mixer_options_get_type +gst_mixer_track_get_type +#include +gst_navigation_get_type +#include +gst_property_probe_get_type +#include +gst_tuner_get_type +gst_tuner_channel_get_type +gst_tuner_norm_get_type +#include +gst_stream_volume_get_type +#include +gst_video_orientation_get_type +#include +gst_x_overlay_get_type + + +#include +gst_base_rtp_depayload_get_type +#include +gst_basertppayload_get_type +#include +gst_base_rtp_audio_payload_get_type + + +#include +gst_video_filter_get_type +#include +gst_video_sink_get_type + +#include +gst_discoverer_get_type + +#include +#include +gst_encoding_profile_get_type +gst_encoding_video_profile_get_type +gst_encoding_video_profile_get_type +gst_encoding_audio_profile_get_type +gst_encoding_container_profile_get_type +gst_encoding_target_get_type + + diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/.gitignore b/gst-plugins-base-subtitles0.10/docs/plugins/.gitignore new file mode 100644 index 0000000..7d868e5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/.gitignore @@ -0,0 +1,25 @@ +Makefile +Makefile.in + +*-decl.txt +*-decl-list.txt +*-undeclared.txt +*-undocumented.txt +*-unused.txt + +tmpl +xml +html +tmpl/*.sgml + +gst-plugins-base-plugins-scan +gst-plugins-base-plugins-scan.c +inspect-registry.* + +html-build.stamp +html.stamp +scan-build.stamp +sgml-build.stamp +sgml.stamp +tmpl-build.stamp +tmpl.stamp diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/Makefile.am b/gst-plugins-base-subtitles0.10/docs/plugins/Makefile.am new file mode 100644 index 0000000..c987b85 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/Makefile.am @@ -0,0 +1,152 @@ +GST_DOC_SCANOBJ = $(top_srcdir)/common/gstdoc-scangobj + +## Process this file with automake to produce Makefile.in + +# The name of the module, e.g. 'glib'. +#DOC_MODULE=gst-plugins-libs-@GST_MAJORMINOR@ +MODULE=gst-plugins-base +DOC_MODULE=$(MODULE)-plugins + +# for upload-doc.mak +DOC=$(MODULE)-plugins +FORMATS=html +html: html-build.stamp +include $(top_srcdir)/common/upload-doc.mak + +# generated basefiles +#basefiles = \ +## $(DOC_MODULE).types \ +# $(DOC_MODULE)-sections.txt \ +# $(DOC_MODULE)-docs.sgml + +# ugly hack to make -unused.sgml work +#unused-build.stamp: +# BUILDDIR=`pwd` && \ +# cd $(srcdir)/tmpl && \ +# ln -sf gstreamer-libs-unused.sgml \ +# $$BUILDDIR/tmpl/gstreamer-libs-@GST_MAJORMINOR@-unused.sgml +# touch unused-build.stamp + +# these rules are added to create parallel docs using GST_MAJORMINOR +#$(basefiles): gstreamer-libs-@GST_MAJORMINOR@%: gstreamer-libs% +# cp $< $@ + +#CLEANFILES = $(basefiles) + +# The top-level SGML file. Change it if you want. +DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml + +# The directory containing the source code. Relative to $(top_srcdir). +# gtk-doc will search all .c & .h files beneath here for inline comments +# documenting functions and macros. +DOC_SOURCE_DIR = $(top_srcdir) + +# Extra options to supply to gtkdoc-scan. +SCAN_OPTIONS= + +# Extra options to supply to gtkdoc-mkdb. +MKDB_OPTIONS=--sgml-mode + +# Extra options to supply to gtkdoc-fixref. +FIXXREF_OPTIONS=--extra-dir=$(top_builddir)/docs/libs/html \ + --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(GST_PREFIX)/share/gtk-doc/html \ + --extra-dir=$(datadir)/gtk-doc/html + +# Used for dependencies. +HFILE_GLOB=$(DOC_SOURCE_DIR)/*/*/*.h +CFILE_GLOB=$(DOC_SOURCE_DIR)/*/*/*.c + +# this is a wingo addition +# thomasvs: another nice wingo addition would be an explanation on why +# this is useful ;) + +SCANOBJ_DEPS = + +# Header files to ignore when scanning. +IGNORE_HFILES = avcodec.h gstffmpegcodecmap.h dsputil.h arch.h speex_resampler.h speex_resampler_wrapper.h fixed_arm4.h fixed_arm5e.h fixed_bfin.h fixed_debug.h fixed_generic.h resample_sse.h +IGNORE_CFILES = utils.c mem.c imgconvert.c + +# we add all .h files of elements that have signals/args we want +# sadly this also pulls in the private methods - maybe we should +# move those around in the source ? +# also, we should add some stuff here conditionally based on whether +# or not the plugin will actually build +# but I'm not sure about that - it might be this Just Works given that +# the registry won't have the element + +EXTRA_HFILES = \ + $(top_srcdir)/ext/alsa/gstalsamixerelement.h \ + $(top_srcdir)/ext/alsa/gstalsasink.h \ + $(top_srcdir)/ext/alsa/gstalsasrc.h \ + $(top_srcdir)/ext/cdparanoia/gstcdparanoiasrc.h \ + $(top_srcdir)/ext/gio/gstgiosink.h \ + $(top_srcdir)/ext/gio/gstgiosrc.h \ + $(top_srcdir)/ext/gio/gstgiostreamsink.h \ + $(top_srcdir)/ext/gio/gstgiostreamsrc.h \ + $(top_srcdir)/ext/gnomevfs/gstgnomevfssink.h \ + $(top_srcdir)/ext/gnomevfs/gstgnomevfssrc.h \ + $(top_srcdir)/ext/ogg/gstoggdemux.h \ + $(top_srcdir)/ext/ogg/gstoggmux.h \ + $(top_srcdir)/ext/pango/gstclockoverlay.h \ + $(top_srcdir)/ext/pango/gsttextoverlay.h \ + $(top_srcdir)/ext/pango/gsttextrender.h \ + $(top_srcdir)/ext/pango/gsttimeoverlay.h \ + $(top_srcdir)/ext/theora/gsttheoradec.h \ + $(top_srcdir)/ext/theora/gsttheoraenc.h \ + $(top_srcdir)/ext/theora/gsttheoraparse.h \ + $(top_srcdir)/ext/vorbis/gstvorbisdec.h \ + $(top_srcdir)/ext/vorbis/gstvorbisenc.h \ + $(top_srcdir)/ext/vorbis/gstvorbisparse.h \ + $(top_srcdir)/ext/vorbis/gstvorbistag.h \ + $(top_srcdir)/gst/adder/gstadder.h \ + $(top_srcdir)/gst/audioconvert/audioconvert.h \ + $(top_srcdir)/gst/audioconvert/gstaudioconvert.h \ + $(top_srcdir)/gst/audiotestsrc/gstaudiotestsrc.h \ + $(top_srcdir)/gst/encoding/gstencodebin.h \ + $(top_srcdir)/gst/ffmpegcolorspace/gstffmpegcolorspace.h \ + $(top_srcdir)/gst/gdp/gstgdpdepay.h \ + $(top_srcdir)/gst/gdp/gstgdppay.h \ + $(top_srcdir)/gst/playback/gstplay-enum.h \ + $(top_srcdir)/gst/playback/gstsubtitleoverlay.h \ + $(top_srcdir)/gst/audiorate/gstaudiorate.h \ + $(top_srcdir)/gst/audioresample/gstaudioresample.h \ + $(top_srcdir)/gst/tcp/gstmultifdsink.h \ + $(top_srcdir)/gst/tcp/gsttcpclientsrc.h \ + $(top_srcdir)/gst/tcp/gsttcpclientsink.h \ + $(top_srcdir)/gst/tcp/gsttcpserversrc.h \ + $(top_srcdir)/gst/tcp/gsttcpserversink.h \ + $(top_builddir)/gst/tcp/gsttcp-enumtypes.h \ + $(top_srcdir)/gst/tcp/gsttcp.h \ + $(top_srcdir)/gst/videorate/gstvideorate.h \ + $(top_srcdir)/gst/videoscale/gstvideoscale.h \ + $(top_srcdir)/gst/videotestsrc/gstvideotestsrc.h \ + $(top_srcdir)/gst/volume/gstvolume.h \ + $(top_srcdir)/sys/ximage/ximagesink.h \ + $(top_srcdir)/sys/xvimage/xvimagesink.h \ + $(top_srcdir)/gst-libs/gst/app/gstappsrc.h \ + $(top_srcdir)/gst-libs/gst/app/gstappsink.h + +# Images to copy into HTML directory. +HTML_IMAGES = + +# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE). +content_files = + +# Other files to distribute. +extra_files = + +# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib +# contains GtkObjects/GObjects and you want to document signals and properties. +GTKDOC_CFLAGS = $(GST_BASE_CFLAGS) -I$(top_builddir) -I$(top_builddir)/gst-libs +GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_BASE_LIBS) + +GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC) +GTKDOC_LD=$(LIBTOOL) --tag=CC --mode=link $(CC) + +# If you need to override some of the declarations, place them in this file +# and uncomment this line. +#DOC_OVERRIDES = $(DOC_MODULE)-overrides.txt +DOC_OVERRIDES = + +include $(top_srcdir)/common/gtk-doc-plugins.mak diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-docs.sgml b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-docs.sgml new file mode 100644 index 0000000..ea603d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-docs.sgml @@ -0,0 +1,113 @@ + + +%version-entities; +]> + + + + GStreamer Base Plugins &GST_MAJORMINOR; Plugins Reference Manual + + for GStreamer Base Plugins &GST_MAJORMINOR; (&GST_VERSION;) + The latest version of this documentation can be found on-line at + http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-base/html/. + + + + + gst-plugins-base Elements + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gst-plugins-base Plugins + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gst-plugins-base Classes + + + + diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-overrides.txt b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-overrides.txt new file mode 100644 index 0000000..57b5802 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-overrides.txt @@ -0,0 +1,30 @@ + +GstDecodeBin +struct _GstDecodeBin { +}; + + +GstDecodeBin2 +struct _GstDecodeBin2 { +}; + + +GstPlayBaseBin +struct _GstPlayBaseBin { +}; + + +GstPlayBin +struct _GstPlayBin { +}; + + +GstPlayBin2 +struct _GstPlayBin2 { +}; + + +GstURIDecodeBin +struct _GstURIDecodeBin { +}; + diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-sections.txt b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-sections.txt new file mode 100644 index 0000000..e94c450 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins-sections.txt @@ -0,0 +1,826 @@ +
+element-adder +adder +GstAdder + +GST_ADDER +GST_IS_ADDER +GST_TYPE_ADDER +GST_ADDER_CLASS +GST_IS_ADDER_CLASS +GST_ADDER_GET_CLASS +gst_adder_get_type +GstAdderClass +GstAdderFormat +GstAdderFunction +GstAdderInputChannel +
+ +
+element-appsrc +appsrc +GstAppSrc + +gst_app_src_set_caps +gst_app_src_get_caps +gst_app_src_set_size +gst_app_src_get_size +gst_app_src_set_stream_type +gst_app_src_get_stream_type +gst_app_src_set_max_bytes +gst_app_src_get_max_bytes +gst_app_src_set_latency +gst_app_src_get_latency +gst_app_src_set_emit_signals +gst_app_src_get_emit_signals +gst_app_src_push_buffer +gst_app_src_end_of_stream +GstAppSrcCallbacks +gst_app_src_set_callbacks + +GstAppSrcClass +GstAppSrcPrivate +GstAppStreamType +GST_APP_SRC +GST_IS_APP_SRC +GST_TYPE_APP_SRC +gst_app_src_get_type +GST_APP_SRC_CLASS +GST_IS_APP_SRC_CLASS +
+ +
+element-appsink +appsink +GstAppSink + +gst_app_sink_set_caps +gst_app_sink_get_caps +gst_app_sink_is_eos +gst_app_sink_set_emit_signals +gst_app_sink_get_emit_signals +gst_app_sink_set_max_buffers +gst_app_sink_get_max_buffers +gst_app_sink_set_drop +gst_app_sink_get_drop +gst_app_sink_pull_preroll +gst_app_sink_pull_buffer +gst_app_sink_set_callbacks +GstAppSinkClass +GstAppSinkPrivate +GstAppSinkCallbacks +GST_APP_SINK +GST_IS_APP_SINK +GST_TYPE_APP_SINK +gst_app_sink_get_type +GST_APP_SINK_CLASS +GST_IS_APP_SINK_CLASS +
+ +
+element-alsamixer +alsamixer +GstAlsaMixerElement + +GstAlsaMixerElementClass +GST_ALSA_MIXER_ELEMENT +GST_IS_ALSA_MIXER_ELEMENT +GST_TYPE_ALSA_MIXER_ELEMENT +gst_alsa_mixer_element_get_type +GST_ALSA_MIXER_ELEMENT_CLASS +GST_IS_ALSA_MIXER_ELEMENT_CLASS +
+ +
+element-alsasink +alsasink +GstAlsaSink + +GstAlsaSinkClass +GST_ALSA_SINK +GST_ALSA_SINK_CAST +GST_IS_ALSA_SINK +GST_TYPE_ALSA_SINK +GST_ALSA_SINK_CLASS +GST_IS_ALSA_SINK_CLASS +GST_ALSA_SINK_GET_LOCK +GST_ALSA_SINK_LOCK +GST_ALSA_SINK_UNLOCK +gst_alsasink_get_type +
+ +
+element-alsasrc +alsasrc +GstAlsaSrc + +GstAlsaSrcClass +GST_ALSA_SRC +GST_IS_ALSA_SRC +GST_TYPE_ALSA_SRC +GST_ALSA_SRC_CLASS +GST_IS_ALSA_SRC_CLASS +GST_ALSA_SRC_CAST +GST_ALSA_SRC_GET_LOCK +GST_ALSA_SRC_LOCK +GST_ALSA_SRC_UNLOCK +gst_alsasrc_get_type +
+ +
+element-audioconvert +audioconvert +GstAudioConvert +GstAudioConvertDithering +GstAudioConvertNoiseShaping + +GST_AUDIO_CONVERT +GST_AUDIO_CONVERT_CLASS +GST_IS_AUDIO_CONVERT +GST_IS_AUDIO_CONVERT_CLASS +GST_TYPE_AUDIO_CONVERT +GstAudioConvertClass +AudioConvertCtx +AudioConvertFmt +AudioConvertMix +AudioConvertPack +AudioConvertQuantize +AudioConvertUnpack +audio_convert_clean_context +audio_convert_clean_fmt +audio_convert_convert +audio_convert_get_sizes +audio_convert_prepare_context +
+ +
+element-audiorate +audiorate +GstAudioRate + +GST_AUDIO_RATE +GST_IS_AUDIO_RATE +GST_TYPE_AUDIO_RATE +gst_audio_rate_get_type +GST_AUDIO_RATE_CLASS +GST_IS_AUDIO_RATE_CLASS +GstAudioRateClass +
+ +
+element-audioresample +audioresample +GstAudioResample + +GST_AUDIO_RESAMPLE +GST_IS_AUDIO_RESAMPLE +GST_TYPE_AUDIO_RESAMPLE +gst_audio_resample_get_type +GST_AUDIO_RESAMPLE_CLASS +GST_IS_AUDIO_RESAMPLE_CLASS +GstAudioResampleClass +
+ +
+element-audiotestsrc +audiotestsrc +GstAudioTestSrc +GstAudioTestSrcWave + +GST_AUDIO_TEST_SRC +GST_AUDIO_TEST_SRC_CLASS +GST_IS_AUDIO_TEST_SRC +GST_IS_AUDIO_TEST_SRC_CLASS +GST_TYPE_AUDIO_TEST_SRC +GstAudioTestSrcClass +GstAudioTestSrcFormat +gst_audio_test_src_get_type +GstPinkNoise +PINK_MAX_RANDOM_ROWS +PINK_RANDOM_BITS +PINK_RANDOM_SHIFT +ProcessFunc +
+ +
+element-cdparanoiasrc +cdparanoiasrc +GstCdParanoiaSrc + +GstCdParanoiaSrcClass +GST_CD_PARANOIA_SRC +GST_CD_PARANOIA_SRC_CLASS +GST_CD_PARANOIA_SRC_GET_CLASS +GST_IS_CD_PARANOIA_SRC +GST_IS_CD_PARANOIA_SRC_CLASS +GST_TYPE_CD_PARANOIA_SRC +gst_cd_paranoia_src_get_type +size16 +size32 +
+ +
+element-clockoverlay +clockoverlay +GstClockOverlay + +GST_CLOCK_OVERLAY +GST_CLOCK_OVERLAY_CLASS +GST_IS_CLOCK_OVERLAY +GST_IS_CLOCK_OVERLAY_CLASS +GST_TYPE_CLOCK_OVERLAY +GstClockOverlayClass +gst_clock_overlay_get_type +
+ +
+element-decodebin +decodebin +GstDecodeBin + +
+ +
+element-decodebin2 +decodebin2 +GstDecodeBin2 + +
+ +
+element-encodebin +encodebin +GstEncodeBin + +GST_ENCODE_BIN +GST_ENCODE_BIN_CLASS +GST_IS_ENCODE_BIN +GST_IS_ENCODE_BIN_CLASS +GST_TYPE_ENCODE_BIN +GstEncodeBinClass +gst_encode_bin_get_type +
+ + + +
+element-ffmpegcolorspace +ffmpegcolorspace +GstFFMpegCsp + +GST_FFMPEGCSP +GST_FFMPEGCSP_CLASS +GST_IS_FFMPEGCSP +GST_IS_FFMPEGCSP_CLASS +GST_TYPE_FFMPEGCSP +GstFFMpegCspClass +
+ +
+element-gdpdepay +gdpdepay +GstGDPDepay + +GstGDPDepayClass +GstGDPDepayState +GST_GDP_DEPAY +GST_GDP_DEPAY_CLASS +GST_IS_GDP_DEPAY +GST_IS_GDP_DEPAY_CLASS +GST_TYPE_GDP_DEPAY +gst_gdp_depay_plugin_init +
+ +
+element-gdppay +gdppay +GstGDPPay + +GstGDPPayClass +GST_GDP_PAY +GST_GDP_PAY_CLASS +GST_IS_GDP_PAY +GST_IS_GDP_PAY_CLASS +GST_TYPE_GDP_PAY +gst_gdp_pay_plugin_init +
+ +
+element-giosink +giosink +GstGioSink + +GstGioSinkClass +GST_GIO_SINK +GST_GIO_SINK_CLASS +GST_IS_GIO_SINK +GST_IS_GIO_SINK_CLASS +GST_TYPE_GIO_SINK +gst_gio_sink_get_type +
+ +
+element-giosrc +giosrc +GstGioSrc + +GstGioSrcClass +GST_GIO_SRC +GST_GIO_SRC_CLASS +GST_IS_GIO_SRC +GST_IS_GIO_SRC_CLASS +GST_TYPE_GIO_SRC +gst_gio_src_get_type +
+ +
+element-giostreamsink +giostreamsink +GstGioStreamSink + +GstGioStreamSinkClass +GST_GIO_STREAM_SINK +GST_GIO_STREAM_SINK_CLASS +GST_IS_GIO_STREAM_SINK +GST_IS_GIO_STREAM_SINK_CLASS +GST_TYPE_GIO_STREAM_SINK +gst_gio_stream_sink_get_type +
+ +
+element-giostreamsrc +giostreamsrc +GstGioStreamSrc + +GstGioStreamSrcClass +GST_GIO_STREAM_SRC +GST_GIO_STREAM_SRC_CLASS +GST_IS_GIO_STREAM_SRC +GST_IS_GIO_STREAM_SRC_CLASS +GST_TYPE_GIO_STREAM_SRC +gst_gio_stream_src_get_type +
+ +
+element-multifdsink +multifdsink +GstMultiFdSink +GstRecoverPolicy +GstSyncMethod +GstClientStatus +GstTCPProtocol +GstTCPUnitType + +CLIENTS_LOCK +CLIENTS_LOCK_FREE +CLIENTS_LOCK_INIT +CLIENTS_UNLOCK +GST_TYPE_MULTI_FD_SINK +GST_IS_MULTI_FD_SINK +GST_IS_MULTI_FD_SINK_CLASS +GST_MULTI_FD_SINK +GST_MULTI_FD_SINK_CLASS +GST_MULTI_FD_SINK_GET_CLASS +GstTCPClient +GstMultiFdSinkFlags +GstMultiFdSinkClass +gst_multi_fd_sink_add +gst_multi_fd_sink_add_full +gst_multi_fd_sink_clear +gst_multi_fd_sink_get_stats +gst_multi_fd_sink_get_type +gst_multi_fd_sink_remove +gst_multi_fd_sink_remove_flush +GST_TYPE_TCP_PROTOCOL +gst_tcp_protocol_get_type +
+ +
+element-gnomevfssink +gnomevfssink +GstGnomeVFSSink + +GstGnomeVFSSinkClass +GST_GNOME_VFS_SINK_CLASS +GST_TYPE_GNOME_VFS_SINK +GST_IS_GNOME_VFS_SINK +gst_gnome_vfs_sink_get_type +GST_IS_GNOME_VFS_SINK_CLASS +GST_GNOME_VFS_SINK +
+ +
+element-gnomevfssrc +gnomevfssrc +GstGnomeVFSSrc + +GST_GNOME_VFS_SRC +GST_GNOME_VFS_SRC_CLASS +GST_IS_GNOME_VFS_SRC +GST_IS_GNOME_VFS_SRC_CLASS +GST_TYPE_GNOME_VFS_SRC +GstGnomeVFSSrcClass +gst_gnome_vfs_src_get_type +
+ +
+element-oggdemux +oggdemux +GstOggDemux + +GST_OGG_DEMUX +GST_OGG_DEMUX_CLASS +GST_IS_OGG_DEMUX +GST_IS_OGG_DEMUX_CLASS +GST_TYPE_OGG_DEMUX +GstOggDemuxClass +GST_IS_OGG_PAD +GST_IS_OGG_PAD_CLASS +GST_OGG_PAD +GST_OGG_PAD_CLASS +GST_TYPE_OGG_PAD +GstOggChain +GstOggPad +GstOggPadClass +GstOggPadMode +GstOggPadState +
+ +
+element-oggmux +oggmux +GstOggMux + +gst_ogg_mux_get_type +GST_OGG_MUX +GST_OGG_MUX_CLASS +GST_IS_OGG_MUX +GST_IS_OGG_MUX_CLASS +GST_TYPE_OGG_MUX +GstOggMuxClass +
+ +
+gstplaybasebin +GstPlayBaseBin +GstPlayBaseBin + +
+ +
+element-playbin +playbin +GstPlayBin + +
+ +
+element-playbin2 +playbin2 +GstPlayBin2 +GstPlayFlags + +gst_play_flags_get_type +GST_TYPE_PLAY_FLAGS +
+ +
+element-subtitleoverlay +subtitleoverlay +GstSubtitleOverlay + +GstSubtitleOverlayClass + +GST_IS_SUBTITLE_OVERLAY +GST_IS_SUBTITLE_OVERLAY_CLASS +GST_SUBTITLE_OVERLAY +GST_SUBTITLE_OVERLAY_CAST +GST_SUBTITLE_OVERLAY_CLASS +GST_SUBTITLE_OVERLAY_LOCK +GST_SUBTITLE_OVERLAY_UNLOCK +GST_TYPE_SUBTITLE_OVERLAY +gst_subtitle_overlay_plugin_init +gst_subtitle_overlay_get_type +
+ +
+element-tcpclientsrc +tcpclientsrc +GstTCPClientSrc + +GstTCPClientSrcClass +GST_TCP_CLIENT_SRC +GST_TCP_CLIENT_SINK_CLASS +GstTCPClientSrcFlags +GST_TYPE_TCP_CLIENT_SRC +gst_tcp_client_src_get_type +GST_IS_TCP_CLIENT_SRC_CLASS +GST_IS_TCP_CLIENT_SRC +
+ +
+element-tcpclientsink +tcpclientsink +GstTCPClientSink + +GstTCPClientSinkClass +GST_TCP_CLIENT_SINK +GST_TCP_CLIENT_SRC_CLASS +GstTCPClientSinkFlags +GST_TYPE_TCP_CLIENT_SINK +gst_tcp_client_sink_get_type +GST_IS_TCP_CLIENT_SINK_CLASS +GST_IS_TCP_CLIENT_SINK +
+ +
+element-tcpserversrc +tcpserversrc +GstTCPServerSrc + +GstTCPServerSrcClass +GST_TCP_SERVER_SRC +GST_TCP_SERVER_SRC_CLASS +GstTCPServerSrcFlags +GST_TYPE_TCP_SERVER_SRC +gst_tcp_server_src_get_type +GST_IS_TCP_SERVER_SRC_CLASS +GST_IS_TCP_SERVER_SRC +
+ +
+element-tcpserversink +tcpserversink +GstTCPServerSink + +GstTCPServerSinkClass +GST_TCP_SERVER_SINK +GST_TCP_SERVER_SINK_CLASS +GstTCPServerSinkFlags +GST_TYPE_TCP_SERVER_SINK +gst_tcp_server_sink_get_type +GST_IS_TCP_SERVER_SINK_CLASS +GST_IS_TCP_SERVER_SINK +TCP_DEFAULT_HOST +TCP_DEFAULT_PORT +TCP_HIGHEST_PORT +gst_tcp_gdp_read_buffer +gst_tcp_gdp_read_caps +gst_tcp_gdp_read_event +gst_tcp_gdp_write_buffer +gst_tcp_gdp_write_caps +gst_tcp_gdp_write_event +gst_tcp_host_to_ip +gst_tcp_read_buffer +gst_tcp_socket_close +gst_tcp_socket_write +
+ +
+element-textoverlay +textoverlay +GstTextOverlay +GstTextOverlayVAlign +GstTextOverlayHAlign +GstTextOverlayWrapMode + +GST_TEXT_OVERLAY +GST_TEXT_OVERLAY_CLASS +GST_TEXT_OVERLAY_GET_CLASS +GST_IS_TEXT_OVERLAY +GST_IS_TEXT_OVERLAY_CLASS +GST_TYPE_TEXT_OVERLAY +GstTextOverlayClass +gst_text_overlay_get_type +GstTextOverlayLineAlign +
+ +
+element-textrender +textrender +GstTextRender + +GST_TEXT_RENDER +GST_TEXT_RENDER_CLASS +GST_TEXT_RENDER_GET_CLASS +GST_IS_TEXT_RENDER +GST_IS_TEXT_RENDER_CLASS +GST_TYPE_TEXT_RENDER +GstTextRenderClass +gst_text_render_get_type +
+ +
+element-theoradec +theoradec +GstTheoraDec + +GST_THEORA_DEC +GST_IS_THEORA_DEC +GST_TYPE_THEORA_DEC +GST_THEORA_DEC_CLASS +GST_IS_THEORA_DEC_CLASS +GstTheoraDecClass +
+ +
+element-theoraenc +theoraenc +GstTheoraEnc +GstTheoraEncBorderMode + +GST_THEORA_ENC +GST_THEORA_ENC_CLASS +GST_IS_THEORA_ENC +GST_IS_THEORA_ENC_CLASS +GST_TYPE_THEORA_ENC +GstTheoraEncClass +
+ +
+element-theoraparse +theoraparse +GstTheoraParse + +GstTheoraParseClass +GST_THEORA_PARSE +GST_IS_THEORA_PARSE +GST_TYPE_THEORA_PARSE +gst_theora_parse_get_type +GST_THEORA_PARSE_CLASS +GST_IS_THEORA_PARSE_CLASS +
+ +
+element-timeoverlay +timeoverlay +GstTimeOverlay + +GST_TIME_OVERLAY +GST_TIME_OVERLAY_CLASS +GST_IS_TIME_OVERLAY +GST_IS_TIME_OVERLAY_CLASS +GST_TYPE_TIME_OVERLAY +GstTimeOverlayClass +gst_time_overlay_get_type +
+ +
+element-uridecodebin +uridecodebin +GstURIDecodeBin +GstAutoplugSelectResult + +GST_TYPE_AUTOPLUG_SELECT_RESULT +gst_autoplug_select_result_get_type +
+ +
+element-videorate +videorate +GstVideoRate + +GstVideoRateClass +GST_VIDEO_RATE +GST_IS_VIDEO_RATE +GST_TYPE_VIDEO_RATE +GST_VIDEO_RATE_CLASS +GST_IS_VIDEO_RATE_CLASS +
+ +
+element-videoscale +videoscale +GstVideoScale +GstVideoScaleMethod + +GstVideoScaleClass +GST_CAT_DEFAULT +GST_VIDEO_SCALE +GST_IS_VIDEO_SCALE +GST_TYPE_VIDEO_SCALE +gst_video_scale_get_type +GST_VIDEO_SCALE_CLASS +GST_IS_VIDEO_SCALE_CLASS +
+ +
+element-videotestsrc +videotestsrc +GstVideoTestSrc +GstVideoTestSrcPattern +GstVideoTestSrcColorSpec + +GST_VIDEO_TEST_SRC +GST_VIDEO_TEST_SRC_CLASS +GST_IS_VIDEO_TEST_SRC +GST_IS_VIDEO_TEST_SRC_CLASS +GST_TYPE_VIDEO_TEST_SRC +GstVideoTestSrcClass +gst_video_test_src_get_type +
+ +
+element-volume +volume +GstVolume + +GST_VOLUME +GST_VOLUME_CLASS +GST_IS_VOLUME +GST_IS_VOLUME_CLASS +GST_TYPE_VOLUME +GstVolumeClass +gst_volume_get_type +
+ +
+element-vorbisdec +vorbisdec +GstVorbisDec + +GstVorbisDecClass +GST_VORBIS_DEC +GST_IS_VORBIS_DEC +GST_TYPE_VORBIS_DEC +gst_vorbis_dec_get_type +GST_VORBIS_DEC_CLASS +GST_IS_VORBIS_DEC_CLASS +
+ +
+element-vorbisenc +vorbisenc +GstVorbisEnc + +GstVorbisEncClass +GST_IS_VORBISENC +GST_VORBISENC_CLASS +GST_VORBISENC +GST_TYPE_VORBISENC +GST_IS_VORBISENC_CLASS +gst_vorbis_enc_get_type +
+ +
+element-vorbisparse +vorbisparse +GstVorbisParse + +GstVorbisParseClass +GST_VORBIS_PARSE +GST_IS_VORBIS_PARSE +GST_TYPE_VORBIS_PARSE +gst_vorbis_parse_get_type +GST_VORBIS_PARSE_CLASS +GST_IS_VORBIS_PARSE_CLASS +
+ +
+element-vorbistag +vorbistag +GstVorbisTag + +GstVorbisTagClass +GST_VORBIS_TAG +GST_IS_VORBIS_TAG +GST_TYPE_VORBIS_TAG +gst_vorbis_tag_get_type +GST_VORBIS_TAG_CLASS +GST_IS_VORBIS_TAG_CLASS +
+ +
+element-ximagesink +ximagesink +GstXImageSink + +GST_XIMAGESINK +GST_XIMAGESINK_CLASS +GST_IS_XIMAGESINK +GST_IS_XIMAGESINK_CLASS +GST_TYPE_XIMAGESINK +gst_ximagesink_get_type +GstXImageBuffer +GstXImageBufferClass +GstXImageSinkClass +GstXContext +GstXWindow +
+ +
+element-xvimagesink +xvimagesink +GstXvImageSink + +GST_XVIMAGESINK +GST_XVIMAGESINK_CLASS +GST_IS_XVIMAGESINK +GST_IS_XVIMAGESINK_CLASS +GST_TYPE_XVIMAGESINK +gst_xvimagesink_get_type +GstXvImageBuffer +GstXvImageBufferClass +GstXvImageFormat +GstXvImageSinkClass +
diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.args b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.args new file mode 100644 index 0000000..04f3a63 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.args @@ -0,0 +1,3490 @@ + +GstXvImageSink::brightness +gint +[-1000,1000] +rw +Brightness +The brightness of the video. +0 + + + +GstXvImageSink::contrast +gint +[-1000,1000] +rw +Contrast +The contrast of the video. +0 + + + +GstXvImageSink::display +gchar* + +rw +Display +X Display name. +NULL + + + +GstXvImageSink::hue +gint +[-1000,1000] +rw +Hue +The hue of the video. +0 + + + +GstXvImageSink::pixel-aspect-ratio +gchar* + +rw +Pixel Aspect Ratio +The pixel aspect ratio of the device. +"1/1" + + + +GstXvImageSink::saturation +gint +[-1000,1000] +rw +Saturation +The saturation of the video. +0 + + + +GstXvImageSink::synchronous +gboolean + +rw +Synchronous +When enabled, runs the X display in synchronous mode. (used only for debugging). +FALSE + + + +GstXvImageSink::force-aspect-ratio +gboolean + +rw +Force aspect ratio +When enabled, scaling will respect original aspect ratio. +FALSE + + + +GstXvImageSink::device +gchar* + +rw +Adaptor number +The number of the video adaptor. +"0" + + + +GstXvImageSink::device-name +gchar* + +r +Adaptor name +The name of the video adaptor. +NULL + + + +GstXvImageSink::handle-events +gboolean + +rw +Handle XEvents +When enabled, XEvents will be selected and handled. +TRUE + + + +GstXvImageSink::double-buffer +gboolean + +rw +Double-buffer +Whether to double-buffer the output. +TRUE + + + +GstXvImageSink::handle-expose +gboolean + +rw +Handle expose +When enabled, the current frame will always be drawn in response to X Expose events. +TRUE + + + +GstXvImageSink::autopaint-colorkey +gboolean + +rw +Autofill with colorkey +Whether to autofill overlay with colorkey. +TRUE + + + +GstXvImageSink::colorkey +gint + +rw +Colorkey +Color to use for the overlay mask. +0 + + + +GstXvImageSink::draw-borders +gboolean + +rw +Colorkey +Draw black borders to fill unused area in force-aspect-ratio mode. +TRUE + + + +GstXvImageSink::window-height +guint64 + +r +window-height +Height of the window. +0 + + + +GstXvImageSink::window-width +guint64 + +r +window-width +Width of the window. +0 + + + +GstXImageSink::display +gchar* + +rw +Display +X Display name. +NULL + + + +GstXImageSink::pixel-aspect-ratio +gchar* + +rw +Pixel Aspect Ratio +The pixel aspect ratio of the device. +"1/1" + + + +GstXImageSink::synchronous +gboolean + +rw +Synchronous +When enabled, runs the X display in synchronous mode. (used only for debugging). +FALSE + + + +GstXImageSink::force-aspect-ratio +gboolean + +rw +Force aspect ratio +When enabled, reverse caps negotiation (scaling) will respect original aspect ratio. +FALSE + + + +GstXImageSink::handle-events +gboolean + +rw +Handle XEvents +When enabled, XEvents will be selected and handled. +TRUE + + + +GstXImageSink::handle-expose +gboolean + +rw +Handle expose +When enabled, the current frame will always be drawn in response to X Expose events. +TRUE + + + +GstXImageSink::window-height +guint64 + +r +window-height +Height of the window. +0 + + + +GstXImageSink::window-width +guint64 + +r +window-width +Width of the window. +0 + + + +GstV4lSrc::autoprobe +gboolean + +rw +Autoprobe +Whether the device should be probed for all possible features. +TRUE + + + +GstV4lSrc::autoprobe-fps +gboolean + +rw +Autoprobe FPS +Whether the device should be probed for framerates. +TRUE + + + +GstV4lSrc::copy-mode +gboolean + +rw +Copy mode +Whether to send out copies of buffers, or direct pointers to the mmap region. +TRUE + + + +GstV4lSrc::timestamp-offset +gint64 + +rw +Timestamp offset +A time offset subtracted from timestamps set on buffers (in ns). +0 + + + +GstAudioresample::filter-length +gint +>= 0 +rwx +filter length +Length of the resample filter. +16 + + + +GstVolume::mute +gboolean + +rw +Mute +mute channel. +FALSE + + + +GstVolume::volume +gdouble +[0,10] +rw +Volume +volume factor, 1.0=100%. +1 + + + +GstVideoTestSrc::pattern +GstVideoTestSrcPattern + +rw +Pattern +Type of test pattern to generate. +SMPTE 100% color bars + + + +GstVideoTestSrc::timestamp-offset +gint64 + +rw +Timestamp offset +An offset added to timestamps set on buffers (in ns). +0 + + + +GstVideoTestSrc::is-live +gboolean + +rw +Is Live +Whether to act as a live source. +FALSE + + + +GstVideoTestSrc::peer-alloc +gboolean + +rw +Peer Alloc +Ask the peer to allocate an output buffer. +TRUE + + + +GstVideoTestSrc::colorspec +GstVideoTestSrcColorSpec + +rw +Color Specification +Generate video in the given color specification (Deprecated: use a caps filter with video/x-raw-yuv,color-matrix="sdtv" or "hdtv" instead). +ITU-R Rec. BT.601 + + + +GstVideoTestSrc::k0 +gint + +rw +Zoneplate zero order phase +Zoneplate zero order phase, for generating plain fields or phase offsets. +0 + + + +GstVideoTestSrc::kt +gint + +rw +Zoneplate 1st order t phase +Zoneplate 1st order t phase, for generating phase rotation as a function of time. +0 + + + +GstVideoTestSrc::kt2 +gint + +rw +Zoneplate 2nd order t phase +Zoneplate 2nd order t phase, t*t/256 cycles per picture. +0 + + + +GstVideoTestSrc::kx +gint + +rw +Zoneplate 1st order x phase +Zoneplate 1st order x phase, for generating constant horizontal frequencies. +0 + + + +GstVideoTestSrc::kx2 +gint + +rw +Zoneplate 2nd order x phase +Zoneplate 2nd order x phase, normalised to kx2/256 cycles per horizontal pixel at width/2 from origin. +0 + + + +GstVideoTestSrc::kxt +gint + +rw +Zoneplate x*t product phase +Zoneplate x*t product phase, normalised to kxy/256 cycles per vertical pixel at width/2 from origin. +0 + + + +GstVideoTestSrc::kxy +gint + +rw +Zoneplate x*y product phase +Zoneplate x*y product phase. +0 + + + +GstVideoTestSrc::ky +gint + +rw +Zoneplate 1st order y phase +Zoneplate 1st order y phase, for generating contant vertical frequencies. +0 + + + +GstVideoTestSrc::ky2 +gint + +rw +Zoneplate 2nd order y phase +Zoneplate 2nd order y phase, normailsed to ky2/256 cycles per vertical pixel at height/2 from origin. +0 + + + +GstVideoTestSrc::kyt +gint + +rw +Zoneplate y*t product phase +Zoneplate y*t product phase. +0 + + + +GstVideoTestSrc::xoffset +gint + +rw +Zoneplate 2nd order products x offset +Zoneplate 2nd order products x offset. +0 + + + +GstVideoTestSrc::yoffset +gint + +rw +Zoneplate 2nd order products y offset +Zoneplate 2nd order products y offset. +0 + + + +GstVideoTestSrc::background-color +guint + +rw +Background Color +Background color to use (big-endian ARGB). +4278190080 + + + +GstVideoTestSrc::foreground-color +guint + +rw +Foreground Color +Foreground color to use (big-endian ARGB). +4294967295 + + + +GstVideoTestSrc::horizontal-speed +gint + +rw +Horizontal Speed +Scroll image number of pixels per frame (positive is scroll to the left). +0 + + + +GstVideoscale::method +GstVideoscaleMethod + +rw +method +method. +Nearest Neighbour + + + +GstVideorate::drop +guint64 + +r +Drop +Number of dropped frames. +0 + + + +GstVideorate::duplicate +guint64 + +r +Duplicate +Number of duplicated frames. +0 + + + +GstVideorate::in +guint64 + +r +In +Number of input frames. +0 + + + +GstVideorate::new-pref +gdouble +[0,1] +rw +New Pref +Value indicating how much to prefer new frames. +1 + + + +GstVideorate::out +guint64 + +r +Out +Number of output frames. +0 + + + +GstVideorate::silent +gboolean + +rw +silent +Don't emit notify for dropped and duplicated frames. +TRUE + + + +GstTCPClientSink::host +gchar* + +rw +Host +The host/IP to send the packets to. +"localhost" + + + +GstTCPClientSink::port +gint +[0,65535] +rw +Port +The port to send the packets to. +4953 + + + +GstTCPClientSink::protocol +GstTCPProtocol + +rw +Protocol +The protocol to wrap data in. +GST_TCP_PROTOCOL_NONE + + + +GstTCPClientSrc::host +gchar* + +rw +Host +The host IP address to receive packets from. +"localhost" + + + +GstTCPClientSrc::port +gint +[0,65535] +rw +Port +The port to receive packets from. +4953 + + + +GstTCPClientSrc::protocol +GstTCPProtocol + +rw +Protocol +The protocol to wrap data in. +GST_TCP_PROTOCOL_NONE + + + +GstTCPServerSink::host +gchar* + +rw +host +The host/IP to send the packets to. +"localhost" + + + +GstTCPServerSink::port +gint +[0,65535] +rw +port +The port to send the packets to. +4953 + + + +GstTCPServerSrc::host +gchar* + +rw +Host +The hostname to listen as. +NULL + + + +GstTCPServerSrc::port +gint +[0,65535] +rw +Port +The port to listen to. +4953 + + + +GstTCPServerSrc::protocol +GstTCPProtocol + +rw +Protocol +The protocol to wrap data in. +GST_TCP_PROTOCOL_NONE + + + +GstMultiFdSink::buffers-max +gint +>= G_MAXULONG +rw +Buffers max +max number of buffers to queue for a client (-1 = no limit). +-1 + + + +GstMultiFdSink::buffers-queued +guint + +r +Buffers queued +Number of buffers currently queued. +0 + + + +GstMultiFdSink::buffers-soft-max +gint +>= G_MAXULONG +rw +Buffers soft max +Recover client when going over this limit (-1 = no limit). +-1 + + + +GstMultiFdSink::bytes-served +guint64 + +r +Bytes served +Total number of bytes send to all clients. +0 + + + +GstMultiFdSink::bytes-to-serve +guint64 + +r +Bytes to serve +Number of bytes received to serve to clients. +0 + + + +GstMultiFdSink::mode +GstFDSetMode + +rw +Mode +The mode for selecting activity on the fds (deprecated). +Poll + + + +GstMultiFdSink::protocol +GstTCPProtocol + +rw +Protocol +The protocol to wrap data in. GDP protocol here is deprecated. Please use gdppay element. +GST_TCP_PROTOCOL_NONE + + + +GstMultiFdSink::recover-policy +GstRecoverPolicy + +rw +Recover Policy +How to recover when client reaches the soft max. +Do not try to recover + + + +GstMultiFdSink::sync-clients +gboolean + +rw +Sync clients +(DEPRECATED) Sync clients to a keyframe. +FALSE + + + +GstMultiFdSink::sync-method +GstSyncMethod + +rw +Sync Method +How to sync new clients to the stream. +Serve starting from the latest buffer + + + +GstMultiFdSink::timeout +guint64 + +rw +Timeout +Maximum inactivity timeout in nanoseconds for a client (0 = no limit). +0 + + + +GstMultiFdSink::buffers-min +gint +>= G_MAXULONG +rw +Buffers min +min number of buffers to queue (-1 = as few as possible). +-1 + + + +GstMultiFdSink::burst-unit +GstTCPUnitType + +rw +Burst unit +The format of the burst units (when sync-method is burst[[-with]-keyframe]). +Undefined + + + +GstMultiFdSink::burst-value +guint64 + +rw +Burst value +The amount of burst expressed in burst-unit. +0 + + + +GstMultiFdSink::bytes-min +gint +>= G_MAXULONG +rw +Bytes min +min number of bytes to queue (-1 = as little as possible). +-1 + + + +GstMultiFdSink::time-min +gint64 +>= G_MAXULONG +rw +Time min +min number of time to queue (-1 = as little as possible). +-1 + + + +GstMultiFdSink::unit-type +GstTCPUnitType + +rw +Units type +The unit to measure the max/soft-max/queued properties. +Buffers + + + +GstMultiFdSink::units-max +gint64 +>= G_MAXULONG +rw +Units max +max number of units to queue (-1 = no limit). +-1 + + + +GstMultiFdSink::units-soft-max +gint64 +>= G_MAXULONG +rw +Units soft max +Recover client when going over this limit (-1 = no limit). +-1 + + + +GstMultiFdSink::qos-dscp +gint +[G_MAXULONG,63] +rw +QoS diff srv code point +Quality of Service, differentiated services code point (-1 default). +-1 + + + +GstMultiFdSink::handle-read +gboolean + +rw +Handle Read +Handle client reads and discard the data. +TRUE + + + +GstMultiFdSink::resend-streamheader +gboolean + +rw +Resend streamheader +Resend the streamheader if it changes in the caps. +TRUE + + + +GstMultiFdSink::num-fds +guint + +r +Number of fds +The current number of client file descriptors. +0 + + + +GstDecodeBin::threaded +gboolean + +rw +Threaded +Use threads. +FALSE + + + +GstDecodeBin::sink-caps +GstCaps* + +rw +Sink Caps +The caps of the input data. (NULL = use typefind element). + + + + +GstPlayBin::audio-sink +GstElement* + +rw +Audio Sink +the audio output element to use (NULL = default sink). + + + + +GstPlayBin::frame +GstBuffer* + +r +Frame +The last frame (NULL = no video available). + + + + +GstPlayBin::subtitle-font-desc +gchar* + +w +Subtitle font description +Pango font description of font to be used for subtitle rendering. +NULL + + + +GstPlayBin::video-sink +GstElement* + +rw +Video Sink +the video output element to use (NULL = default sink). + + + + +GstPlayBin::vis-plugin +GstElement* + +rw +Vis plugin +the visualization element to use (NULL = none). + + + + +GstPlayBin::volume +gdouble +[0,10] +rw +volume +volume. +1 + + + +GstPlayBin::connection-speed +guint + +rw +Connection Speed +Network connection speed in kbps (0 = unknown). +0 + + + +GstAudiorate::add +guint64 + +r +Add +Number of added samples. +0 + + + +GstAudiorate::drop +guint64 + +r +Drop +Number of dropped samples. +0 + + + +GstAudiorate::in +guint64 + +r +In +Number of input samples. +0 + + + +GstAudiorate::out +guint64 + +r +Out +Number of output samples. +0 + + + +GstAudiorate::silent +gboolean + +rw +silent +Don't emit notify for dropped and duplicated frames. +TRUE + + + +GstVorbisEnc::bitrate +gint +[G_MAXULONG,250001] +rw +Target Bitrate +Attempt to encode at a bitrate averaging this (in bps). This uses the bitrate management engine, and is not recommended for most users. Quality is a better alternative. (-1 == disabled). +-1 + + + +GstVorbisEnc::last-message +gchar* + +r +last-message +The last status message. +NULL + + + +GstVorbisEnc::managed +gboolean + +rw +Managed +Enable bitrate management engine. +FALSE + + + +GstVorbisEnc::max-bitrate +gint +[G_MAXULONG,250001] +rw +Maximum Bitrate +Specify a maximum bitrate (in bps). Useful for streaming applications. (-1 == disabled). +-1 + + + +GstVorbisEnc::min-bitrate +gint +[G_MAXULONG,250001] +rw +Minimum Bitrate +Specify a minimum bitrate (in bps). Useful for encoding for a fixed-size channel. (-1 == disabled). +-1 + + + +GstVorbisEnc::quality +gfloat +[-0.1,1] +rw +Quality +Specify quality instead of specifying a particular bitrate. +0.3 + + + +GstTheoraDec::crop +gboolean + +rw +Crop +Crop the image to the visible region. +TRUE + + + +GstTheoraEnc::bitrate +gint +[0,16777215] +rw +Bitrate +Compressed video bitrate (kbps). +0 + + + +GstTheoraEnc::border +GstTheoraEncBorderMode + +rw +Border +ignored and kept for API compat only. +Black Border + + + +GstTheoraEnc::center +gboolean + +rw +Center +ignored and kept for API compat only. +TRUE + + + +GstTheoraEnc::keyframe-auto +gboolean + +rw +Keyframe Auto +Automatic keyframe detection. +TRUE + + + +GstTheoraEnc::keyframe-force +gint +[1,32768] +rw +Keyframe force +Force keyframe every N frames. +64 + + + +GstTheoraEnc::keyframe-freq +gint +[1,32768] +rw +Keyframe frequency +Keyframe frequency. +64 + + + +GstTheoraEnc::keyframe-mindistance +gint +[1,32768] +rw +Keyframe mindistance +ignored and kept for API compat only. +8 + + + +GstTheoraEnc::keyframe-threshold +gint +[0,32768] +rw +Keyframe threshold +ignored and kept for API compat only. +80 + + + +GstTheoraEnc::noise-sensitivity +gint +[0,32768] +rw +Noise sensitivity +ignored and kept for API compat only. +1 + + + +GstTheoraEnc::quality +gint +[0,63] +rw +Quality +Video quality. +48 + + + +GstTheoraEnc::quick +gboolean + +rw +Quick +ignored and kept for API compat only. +TRUE + + + +GstTheoraEnc::sharpness +gint +[0,2] +rw +Sharpness +ignored and kept for API compat only. +0 + + + +GstTheoraEnc::speed-level +gint +[0,2] +rwx +Speed level +Controls the amount of analysis performed when encoding. Higher values trade compression quality for speed. This property requires libtheora version >= 1.0, and the maximum value may vary based on encoder version. +1 + + + +GstTheoraEnc::cap-overflow +gboolean + +rw +VP3 Compatible +Enable capping of bit reservoir overflows. +TRUE + + + +GstTheoraEnc::cap-underflow +gboolean + +rw +VP3 Compatible +Enable capping of bit reservoir underflows. +FALSE + + + +GstTheoraEnc::drop-frames +gboolean + +rw +VP3 Compatible +Allow or disallow frame dropping. +TRUE + + + +GstTheoraEnc::rate-buffer +gint +[0,1000] +rw +Rate Control Buffer +Sets the size of the rate control buffer, in units of frames. The default value of 0 instructs the encoder to automatically select an appropriate value. +0 + + + +GstTheoraEnc::vp3-compatible +gboolean + +rw +VP3 Compatible +Disables non-VP3 compatible features. +FALSE + + + +GstTheoraEnc::multipass-cache-file +gchar* + +rw +Multipass Cache File +Multipass cache file. +NULL + + + +GstTheoraEnc::multipass-mode +GstTheoraEncMultipassMode + +rw +Multipass mode +Single pass or first/second pass. +Single pass + + + +GstGnomeVFSSrc::handle +GnomeVFSHandle* + +rw +GnomeVFSHandle +Handle for GnomeVFS. + + + + +GstGnomeVFSSrc::iradio-genre +gchar* + +r +iradio-genre +Genre of the stream. +NULL + + + +GstGnomeVFSSrc::iradio-mode +gboolean + +rw +iradio-mode +Enable internet radio mode (extraction of shoutcast/icecast metadata). +FALSE + + + +GstGnomeVFSSrc::iradio-name +gchar* + +r +iradio-name +Name of the stream. +NULL + + + +GstGnomeVFSSrc::iradio-title +gchar* + +r +iradio-title +Name of currently playing song. +NULL + + + +GstGnomeVFSSrc::iradio-url +gchar* + +r +iradio-url +Homepage URL for radio stream. +NULL + + + +GstGnomeVFSSrc::location +gchar* + +rw +File Location +Location of the file to read. +NULL + + + +GstGnomeVFSSrc::random-access +gboolean + +rw +random-mode +Enable random file access. +FALSE + + + +GstOggMux::max-delay +guint64 + +rw +Max delay +Maximum delay in multiplexing streams. +500000000 + + + +GstOggMux::max-page-delay +guint64 + +rw +Max page delay +Maximum delay for sending out a page. +500000000 + + + +GstAlsaSrc::device +gchar* + +rw +Device +ALSA device, as defined in an asound configuration file. +"default" + + + +GstAlsaSrc::device-name +gchar* + +r +Device name +Human-readable name of the sound device. +"" + + + +GstAlsaSrc::card-name +gchar* + +r +Card name +Human-readable name of the sound card. +"" + + + +GstAlsaSink::device +gchar* + +rw +Device +ALSA device, as defined in an asound configuration file. +"default" + + + +GstAlsaSink::device-name +gchar* + +r +Device name +Human-readable name of the sound device. +"" + + + +GstAlsaSink::card-name +gchar* + +r +Card name +Human-readable name of the sound card. +"" + + + +GstAudioTestSrc::freq +gdouble +[0,20000] +rw +Frequency +Frequency of test signal. +440 + + + +GstAudioTestSrc::is-live +gboolean + +rw +Is Live +Whether to act as a live source. +FALSE + + + +GstAudioTestSrc::samplesperbuffer +gint +>= 1 +rw +Samples per buffer +Number of samples in each outgoing buffer. +1024 + + + +GstAudioTestSrc::timestamp-offset +gint64 + +rw +Timestamp offset +An offset added to timestamps set on buffers (in ns). +0 + + + +GstAudioTestSrc::volume +gdouble +[0,1] +rw +Volume +Volume of test signal. +0.8 + + + +GstAudioTestSrc::wave +GstAudioTestSrcWave + +rw +Waveform +Oscillator waveform. +Sine + + + +GstAudioTestSrc::can-activate-pull +gboolean + +rw +Can activate pull +Can activate in pull mode. +FALSE + + + +GstAudioTestSrc::can-activate-push +gboolean + +rw +Can activate push +Can activate in push mode. +TRUE + + + +GstVideoScale::method +GstVideoScaleMethod + +rw +method +method. +Bilinear + + + +GstVideoScale::add-borders +gboolean + +rw +Add Borders +Add black borders if necessary to keep the display aspect ratio. +FALSE + + + +GstVideoRate::drop +guint64 + +r +Drop +Number of dropped frames. +0 + + + +GstVideoRate::duplicate +guint64 + +r +Duplicate +Number of duplicated frames. +0 + + + +GstVideoRate::in +guint64 + +r +In +Number of input frames. +0 + + + +GstVideoRate::new-pref +gdouble +[0,1] +rw +New Pref +Value indicating how much to prefer new frames (unused). +1 + + + +GstVideoRate::out +guint64 + +r +Out +Number of output frames. +0 + + + +GstVideoRate::silent +gboolean + +rw +silent +Don't emit notify for dropped and duplicated frames. +TRUE + + + +GstVideoRate::skip-to-first +gboolean + +rw +Skip to first buffer +Don't produce buffers before the first one we receive. +FALSE + + + +GstAudioRate::add +guint64 + +r +Add +Number of added samples. +0 + + + +GstAudioRate::drop +guint64 + +r +Drop +Number of dropped samples. +0 + + + +GstAudioRate::in +guint64 + +r +In +Number of input samples. +0 + + + +GstAudioRate::out +guint64 + +r +Out +Number of output samples. +0 + + + +GstAudioRate::silent +gboolean + +rw +silent +Don't emit notify for dropped and duplicated frames. +TRUE + + + +GstAudioRate::tolerance +guint64 + +rw +tolerance +Only act if timestamp jitter/imperfection exceeds indicated tolerance (ns). +0 + + + +GstAudioRate::skip-to-first +gboolean + +rw +Skip to first buffer +Don't produce buffers before the first one we receive. +FALSE + + + +GstTextRender::font-desc +gchar* + +w +font description +Pango font description of font to be used for rendering. See documentation of pango_font_description_from_string for syntax. +"" + + + +GstTextRender::halignment +GstTextRenderHAlign + +rw +horizontal alignment +Horizontal alignment of the text. +center + + + +GstTextRender::line-alignment +GstTextRenderLineAlign + +rw +line alignment +Alignment of text lines relative to each other. +center + + + +GstTextRender::valignment +GstTextRenderVAlign + +rw +vertical alignment +Vertical alignment of the text. +baseline + + + +GstTextRender::xpad +gint +>= 0 +rw +horizontal paddding +Horizontal paddding when using left/right alignment. +25 + + + +GstTextRender::ypad +gint +>= 0 +rw +vertical padding +Vertical padding when using top/bottom alignment. +25 + + + +GstTextOverlay::deltax +gint + +rw +X position modifier +Shift X position to the left or to the right. Unit is pixels. +0 + + + +GstTextOverlay::deltay +gint + +rw +Y position modifier +Shift Y position up or down. Unit is pixels. +0 + + + +GstTextOverlay::font-desc +gchar* + +w +font description +Pango font description of font to be used for rendering. See documentation of pango_font_description_from_string for syntax. +"" + + + +GstTextOverlay::halign +gchar* + +w +horizontal alignment +Horizontal alignment of the text (deprecated; use halignment). +"center" + + + +GstTextOverlay::shaded-background +gboolean + +rw +shaded background +Whether to shade the background under the text area. +FALSE + + + +GstTextOverlay::text +gchar* + +rw +text +Text to be display. +"" + + + +GstTextOverlay::valign +gchar* + +w +vertical alignment +Vertical alignment of the text (deprecated; use valignment). +"baseline" + + + +GstTextOverlay::wrap-mode +GstTextOverlayWrapMode + +rw +wrap mode +Whether to wrap the text and if so how. +wordchar + + + +GstTextOverlay::xpad +gint +>= 0 +rw +horizontal paddding +Horizontal paddding when using left/right alignment. +25 + + + +GstTextOverlay::ypad +gint +>= 0 +rw +vertical padding +Vertical padding when using top/bottom alignment. +25 + + + +GstTextOverlay::halignment +GstTextOverlayHAlign + +rw +horizontal alignment +Horizontal alignment of the text. +center + + + +GstTextOverlay::valignment +GstTextOverlayVAlign + +rw +vertical alignment +Vertical alignment of the text. +baseline + + + +GstTextOverlay::line-alignment +GstTextOverlayLineAlign + +rw +line alignment +Alignment of text lines relative to each other. +center + + + +GstTextOverlay::silent +gboolean + +rw +silent +Whether to render the text string. +FALSE + + + +GstTextOverlay::wait-text +gboolean + +rw +Wait Text +Whether to wait for subtitles. +TRUE + + + +GstTextOverlay::auto-resize +gboolean + +rw +auto resize +Automatically adjust font size to screen-size. +TRUE + + + +GstTextOverlay::vertical-render +gboolean + +rw +vertical render +Vertical Render. +FALSE + + + +GstTextOverlay::color +guint + +rw +Color +Color to use for text (big-endian ARGB). +4294967295 + + + +GstTextOverlay::xpos +gdouble +[0,1] +rw +horizontal position +Horizontal position when using position alignment. +0.5 + + + +GstTextOverlay::ypos +gdouble +[0,1] +rw +vertical position +Vertical position when using position alignment. +0.5 + + + +CDParanoia::abort-on-skip +gboolean + +rw +Abort on skip +Abort on imperfect reads/skips. +FALSE + + + +CDParanoia::default-sectors +gint +[-1,100] +rw +Default sectors +Force default number of sectors in read to n sectors. +-1 + + + +CDParanoia::device +gchararray + +rw +Device +CD device location. +"/dev/cdrom" + + + +CDParanoia::discid +gchararray + +r +discid +The dics id. +NULL + + + +CDParanoia::endian +GstParanoiaEndian + +rw +Endian +Force endian on drive. +treat drive as little endian + + + +CDParanoia::generic-device +gchararray + +rw +Generic device +Use specified generic scsi device. +NULL + + + +CDParanoia::never-skip +gint +>= 0 +rw +Never skip +never accept any less than perfect data reconstruction (don't allow 'V's) but if [n] is given, skip after [n] retries without progress. +0 + + + +CDParanoia::paranoia-mode +GstParanoiaMode + +rw +Paranoia mode +Type of checking to perform. +Disable paranoid checking + + + +CDParanoia::read-speed +gint + +rw +Read speed +Read from device at specified speed. +-1 + + + +CDParanoia::search-overlap +gint +[-1,75] +rw +Search overlap +Force minimum overlap search during verification to n sectors. +-1 + + + +CDParanoia::toc-bias +gboolean + +rw +TOC bias +Assume that the beginning offset of track 1 as reported in the TOC will be addressed as LBA 0. Necessary for some Toshiba drives to get track boundaries. +FALSE + + + +CDParanoia::toc-offset +gint + +rw +TOC offset +Add sectors to the values reported. +0 + + + +GstAlsaMixerElement::device +gchar* + +rw +Device +ALSA device, as defined in an asound configuration file. +"default" + + + +GstAlsaMixerElement::device-name +gchar* + +r +Device name +Human-readable name of the sound device. +"" + + + +GstGnomeVFSSink::handle +GnomeVFSHandle* + +rw +GnomeVFSHandle +Handle for GnomeVFS. + + + + +GstGnomeVFSSink::location +gchar* + +rw +File Location +Location of the file to write. +NULL + + + +GstGnomeVFSSink::uri +GnomeVFSURI* + +rw +GnomeVFSURI +URI for GnomeVFS. + + + + +GstCdParanoiaSrc::generic-device +gchar* + +rw +Generic device +Use specified generic scsi device. +NULL + + + +GstCdParanoiaSrc::paranoia-mode +GstCdParanoiaMode + +rw +Paranoia mode +Type of checking to perform. +PARANOIA_MODE_FRAGMENT + + + +GstCdParanoiaSrc::read-speed +gint +>= G_MAXULONG +rw +Read speed +Read from device at specified speed. +-1 + + + +GstCdParanoiaSrc::search-overlap +gint +[G_MAXULONG,75] +rw +Search overlap +Force minimum overlap search during verification to n sectors. +-1 + + + +GstCdParanoiaSrc::cache-size +gint +>= G_MAXULONG +rw +Cache size +Set CD cache size to n sectors (-1 = auto). +-1 + + + +GstSubParse::subtitle-encoding +gchar* + +rw +subtitle charset encoding +Encoding to assume if input subtitles are not in UTF-8 or any other Unicode encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstSubParse::video-fps +GstFraction + +rw +Video framerate +Framerate of the video stream. This is needed by some subtitle formats to synchronize subtitles and video properly. If not set and the subtitle format requires it subtitles may be out of sync. + + + + +GstTheoraParse::synchronization-points +GValueArray* + +rw +Synchronization points +An array of (granuletime, buffertime) pairs. + + + + +GstGDPPay::crc-header +gboolean + +rw +CRC Header +Calculate and store a CRC checksum on the header. +TRUE + + + +GstGDPPay::crc-payload +gboolean + +rw +CRC Payload +Calculate and store a CRC checksum on the payload. +FALSE + + + +GstGDPPay::version +GstDPVersion + +rw +Version +Version of the GStreamer Data Protocol. +GST_DP_VERSION_1_0 + + + +GstDecodeBin2::caps +GstCaps* + +rw +Caps +The caps on which to stop decoding. + + + + +GstDecodeBin2::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstDecodeBin2::sink-caps +GstCaps* + +rw +Sink Caps +The caps of the input data. (NULL = use typefind element). + + + + +GstDecodeBin2::high-percent +gint +[0,100] +rw +High percent +High threshold for buffering to finish. +99 + + + +GstDecodeBin2::low-percent +gint +[0,100] +rw +Low percent +Low threshold for buffering to start. +10 + + + +GstDecodeBin2::max-size-buffers +guint + +rw +Max. size (buffers) +Max. number of buffers in the queue (0=automatic). +0 + + + +GstDecodeBin2::max-size-bytes +guint + +rw +Max. size (bytes) +Max. amount of bytes in the queue (0=automatic). +0 + + + +GstDecodeBin2::max-size-time +guint64 + +rw +Max. size (ns) +Max. amount of data in the queue (in ns, 0=automatic). +0 + + + +GstDecodeBin2::use-buffering +gboolean + +rw +Use Buffering +Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds. +FALSE + + + +GstDecodeBin2::post-stream-topology +gboolean + +rw +Post Stream Topology +Post stream-topology messages. +FALSE + + + +GstDecodeBin2::expose-all-streams +gboolean + +rw +Expose All Streams +Expose all streams, including those of unknown type or that don't match the 'caps' property. +TRUE + + + +GstURIDecodeBin::uri +gchar* + +rw +URI +URI to decode. +NULL + + + +GstURIDecodeBin::connection-speed +guint +<= 4294967 +rw +Connection Speed +Network connection speed in kbps (0 = unknown). +0 + + + +GstURIDecodeBin::caps +GstCaps* + +rw +Caps +The caps on which to stop decoding. (NULL = default). + + + + +GstURIDecodeBin::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstURIDecodeBin::source +GstElement* + +r +Source +Source object used. + + + + +GstURIDecodeBin::buffer-duration +gint64 +>= G_MAXULONG +rw +Buffer duration (ns) +Buffer duration when buffering streams (-1 default value). +-1 + + + +GstURIDecodeBin::buffer-size +gint +>= G_MAXULONG +rw +Buffer size (bytes) +Buffer size when buffering streams (-1 default value). +-1 + + + +GstURIDecodeBin::download +gboolean + +rw +Download +Attempt download buffering when buffering network streams. +FALSE + + + +GstURIDecodeBin::use-buffering +gboolean + +rw +Use Buffering +Perform buffering on demuxed/parsed media. +FALSE + + + +GstURIDecodeBin::expose-all-streams +gboolean + +rw +Expose All Streams +Expose all streams, including those of unknown type or that don't match the 'caps' property. +TRUE + + + +GstURIDecodeBin::ring-buffer-max-size +guint64 +<= G_MAXUINT +rw +Max. ring buffer size (bytes) +Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled). +0 + + + +GstQueue2::current-level-buffers +guint + +r +Current level (buffers) +Current number of buffers in the queue. +0 + + + +GstQueue2::current-level-bytes +guint + +r +Current level (kB) +Current amount of data in the queue (bytes). +0 + + + +GstQueue2::current-level-time +guint64 + +r +Current level (ns) +Current amount of data in the queue (in ns). +0 + + + +GstQueue2::high-percent +gint +[0,100] +rw +High percent +High threshold for buffering to finish. +99 + + + +GstQueue2::low-percent +gint +[0,100] +rw +Low percent +Low threshold for buffering to start. +10 + + + +GstQueue2::max-size-buffers +guint + +rw +Max. size (buffers) +Max. number of buffers in the queue (0=disable). +100 + + + +GstQueue2::max-size-bytes +guint + +rw +Max. size (kB) +Max. amount of data in the queue (bytes, 0=disable). +2097152 + + + +GstQueue2::max-size-time +guint64 + +rw +Max. size (ns) +Max. amount of data in the queue (in ns, 0=disable). +2000000000 + + + +GstQueue2::temp-location +gchar* + +rw +Temporary File Location +Location to store temporary files in (Deprecated: Only read this property, use temp-tmpl to configure the name template). +NULL + + + +GstQueue2::use-buffering +gboolean + +rw +Use buffering +Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds. +FALSE + + + +GstQueue2::use-rate-estimate +gboolean + +rw +Use Rate Estimate +Estimate the bitrate of the stream to calculate time level. +TRUE + + + +GstQueue2::temp-template +gchar* + +rw +Temporary File Template +File template to store temporary files in, should contain directory and XXXXXX. (NULL == disabled). +NULL + + + +GstAudioConvert::dithering +GstAudioConvertDithering + +rw +Dithering +Selects between different dithering methods. +Triangular dithering (default) + + + +GstAudioConvert::noise-shaping +GstAudioConvertNoiseShaping + +rw +Noise shaping +Selects between different noise shaping methods. +No noise shaping (default) + + + +GstPlayBin2::audio-sink +GstElement* + +rw +Audio Sink +the audio output element to use (NULL = default sink). + + + + +GstPlayBin2::connection-speed +guint +<= 4294967 +rw +Connection Speed +Network connection speed in kbps (0 = unknown). +0 + + + +GstPlayBin2::current-audio +gint +>= G_MAXULONG +rw +Current audio +Currently playing audio stream (-1 = auto). +-1 + + + +GstPlayBin2::current-text +gint +>= G_MAXULONG +rw +Current Text +Currently playing text stream (-1 = auto). +-1 + + + +GstPlayBin2::current-video +gint +>= G_MAXULONG +rw +Current Video +Currently playing video stream (-1 = auto). +-1 + + + +GstPlayBin2::flags +GstPlayFlags + +rw +Flags +Flags to control behaviour. +Render the video stream|Render the audio stream|Render subtitles|Use software volume + + + +GstPlayBin2::frame +GstBuffer* + +r +Frame +The last frame (NULL = no video available). + + + + +GstPlayBin2::n-audio +gint +>= 0 +r +Number Audio +Total number of audio streams. +0 + + + +GstPlayBin2::n-text +gint +>= 0 +r +Number Text +Total number of text streams. +0 + + + +GstPlayBin2::n-video +gint +>= 0 +r +Number Video +Total number of video streams. +0 + + + +GstPlayBin2::source +GstElement* + +r +Source +Source element. + + + + +GstPlayBin2::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstPlayBin2::subtitle-font-desc +gchar* + +w +Subtitle font description +Pango font description of font to be used for subtitle rendering. +NULL + + + +GstPlayBin2::suburi +gchar* + +rw +.sub-URI +Optional URI of a subtitle. +NULL + + + +GstPlayBin2::uri +gchar* + +rw +URI +URI of the media to play. +NULL + + + +GstPlayBin2::video-sink +GstElement* + +rw +Video Sink +the video output element to use (NULL = default sink). + + + + +GstPlayBin2::vis-plugin +GstElement* + +rw +Vis plugin +the visualization element to use (NULL = default). + + + + +GstPlayBin2::volume +gdouble +[0,10] +rw +Volume +The audio volume, 1.0=100%. +1 + + + +GstPlayBin2::mute +gboolean + +rw +Mute +Mute the audio channel without changing the volume. +FALSE + + + +GstPlayBin2::buffer-duration +gint64 +>= G_MAXULONG +rw +Buffer duration (ns) +Buffer duration when buffering network streams. +-1 + + + +GstPlayBin2::buffer-size +gint +>= G_MAXULONG +rw +Buffer size (bytes) +Buffer size when buffering network streams. +-1 + + + +GstPlayBin2::text-sink +GstElement* + +rw +Text plugin +the text output element to use (NULL = default textoverlay). + + + + +GstPlayBin2::subpic-sink +GstElement* + +rw +Subpicture plugin +the subpicture output element to use (NULL = default dvdspu). + + + + +GstPlayBin2::av-offset +gint64 + +rw +AV Offset +The synchronisation offset between audio and video in nanoseconds. +0 + + + +GstPlayBin2::ring-buffer-max-size +guint64 +<= G_MAXUINT +rw +Max. ring buffer size (bytes) +Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled). +0 + + + +GstGioSink::location +gchar* + +rw +Location +URI location to write to. +NULL + + + +GstGioSink::file +GFile* + +rw +File +GFile to write to. + + + + +GstGioSrc::location +gchar* + +rw +Location +URI location to read from. +NULL + + + +GstGioSrc::file +GFile* + +rw +File +GFile to read from. + + + + +GstGioStreamSink::stream +GOutputStream* + +rw +Stream +Stream to write to. + + + + +GstGioStreamSrc::stream +GInputStream* + +rw +Stream +Stream to read from. + + + + +GstPlayBaseBin::connection-speed +guint + +rw +Connection Speed +Network connection speed in kbps (0 = unknown). +0 + + + +GstPlayBaseBin::current-audio +gint +>= -1 +rw +Current audio +Currently playing audio stream (-1 = none). +-1 + + + +GstPlayBaseBin::current-text +gint +>= -1 +rw +Current text +Currently playing text stream (-1 = none). +-1 + + + +GstPlayBaseBin::current-video +gint +>= -1 +rw +Current video +Currently playing video stream (-1 = none). +-1 + + + +GstPlayBaseBin::nstreams +gint +>= 0 +r +NStreams +number of streams. +0 + + + +GstPlayBaseBin::queue-min-threshold +guint64 +<= G_MAXINT64 +rw +Queue min threshold +Buffering low threshold of internal queues in nanoseconds. +900000000 + + + +GstPlayBaseBin::queue-size +guint64 +<= G_MAXINT64 +rw +Queue size +Size of internal queues in nanoseconds. +3000000000 + + + +GstPlayBaseBin::queue-threshold +guint64 +<= G_MAXINT64 +rw +Queue threshold +Buffering threshold of internal queues in nanoseconds. +2850000000 + + + +GstPlayBaseBin::source +GstElement* + +r +Source +Source element. + + + + +GstPlayBaseBin::stream-info +gpointer + +r +Stream info +List of streaminfo. + + + + +GstPlayBaseBin::stream-info-value-array +GValueArray* + +r +StreamInfo GValueArray +value array of streaminfo. + + + + +GstPlayBaseBin::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstPlayBaseBin::suburi +gchar* + +rw +.sub-URI +Optional URI of a subtitle. +NULL + + + +GstPlayBaseBin::uri +gchar* + +rw +URI +URI of the media to play. +NULL + + + +GstSpeexResample::filter-length +gint +>= 0 +rwx +Filter length +DEPRECATED, DON'T USE THIS! Length of the resample filter. +64 + + + +GstSpeexResample::quality +gint +[0,10] +rwx +Quality +Resample quality with 0 being the lowest and 10 being the best. +4 + + + +GstClockOverlay::time-format +gchar* + +rw +Date/Time Format +Format to use for time and date value, as in strftime. +"%H:%M:%S" + + + +GstAppSink::caps +GstCaps* + +rw +Caps +The allowed caps for the sink pad. + + + + +GstAppSink::drop +gboolean + +rw +Drop +Drop old buffers when the buffer queue is filled. +FALSE + + + +GstAppSink::emit-signals +gboolean + +rw +Emit signals +Emit new-preroll, new-buffer and new-buffer-list signals. +FALSE + + + +GstAppSink::eos +gboolean + +r +EOS +Check if the sink is EOS or not started. +TRUE + + + +GstAppSink::max-buffers +guint + +rw +Max Buffers +The maximum number of buffers to queue internally (0 = unlimited). +0 + + + +GstAppSrc::block +gboolean + +rw +Block +Block push-buffer when max-bytes are queued. +FALSE + + + +GstAppSrc::caps +GstCaps* + +rw +Caps +The allowed caps for the src pad. + + + + +GstAppSrc::format +GstFormat + +rw +Format +The format of the segment events and seek. +GST_FORMAT_BYTES + + + +GstAppSrc::is-live +gboolean + +rw +Is Live +Whether to act as a live source. +FALSE + + + +GstAppSrc::max-bytes +guint64 + +rw +Max bytes +The maximum number of bytes to queue internally (0 = unlimited). +200000 + + + +GstAppSrc::max-latency +gint64 +>= G_MAXULONG +rw +Max Latency +The maximum latency (-1 = unlimited). +-1 + + + +GstAppSrc::min-latency +gint64 +>= G_MAXULONG +rw +Min Latency +The minimum latency (-1 = default). +-1 + + + +GstAppSrc::size +gint64 +>= G_MAXULONG +rw +Size +The size of the data stream in bytes (-1 if unknown). +-1 + + + +GstAppSrc::stream-type +GstAppStreamType + +rw +Stream Type +the type of the stream. +GST_APP_STREAM_TYPE_STREAM + + + +GstAppSrc::emit-signals +gboolean + +rw +Emit signals +Emit need-data, enough-data and seek-data signals. +TRUE + + + +GstAppSrc::min-percent +guint +<= 100 +rw +Min Percent +Emit need-data when queued bytes drops below this percent of max-bytes. +0 + + + +GstAudioResample::filter-length +gint +>= 0 +rw +Filter length +Length of the resample filter. +64 + + + +GstAudioResample::quality +gint +[0,10] +rwx +Quality +Resample quality with 0 being the lowest and 10 being the best. +4 + + + +GstAdder::caps +GstCaps* + +rw +Target caps +Set target format for mixing (NULL means ANY). Setting this property takes a reference to the supplied GstCaps object. + + + + +GstPlaySink::flags +GstPlayFlags + +rw +Flags +Flags to control behaviour. +Render the video stream|Render the audio stream|Render subtitles|Use software volume + + + +GstPlaySink::mute +gboolean + +rw +Mute +Mute the audio channel without changing the volume. +FALSE + + + +GstPlaySink::subtitle-font-desc +gchar* + +w +Subtitle font description +Pango font description of font to be used for subtitle rendering. +NULL + + + +GstPlaySink::vis-plugin +GstElement* + +rw +Vis plugin +the visualization element to use (NULL = default). + + + + +GstPlaySink::volume +gdouble +[0,10] +rw +Volume +The audio volume, 1.0=100%. +1 + + + +GstPlaySink::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstPlaySink::av-offset +gint64 + +rw +AV Offset +The synchronisation offset between audio and video in nanoseconds. +0 + + + +GstPlaySink::frame +GstBuffer* + +r +Frame +The last frame (NULL = no video available). + + + + +GstSubtitleOverlay::font-desc +gchar* + +rw +Subtitle font description +Pango font description of font to be used for subtitle rendering. +NULL + + + +GstSubtitleOverlay::silent +gboolean + +rw +Silent +Whether to show subtitles. +FALSE + + + +GstSubtitleOverlay::subtitle-encoding +gchar* + +rw +subtitle encoding +Encoding to assume if input subtitles are not in UTF-8 encoding. If not set, the GST_SUBTITLE_ENCODING environment variable will be checked for an encoding to use. If that is not set either, ISO-8859-15 will be assumed. +NULL + + + +GstEncodeBin::audio-jitter-tolerance +guint64 + +rw +Audio jitter tolerance +Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns). +20000000 + + + +GstEncodeBin::avoid-reencoding +gboolean + +rw +Avoid re-encoding +Whether to re-encode portions of compatible video streams that lay on segment boundaries. +FALSE + + + +GstEncodeBin::profile +GstEncodingProfile* + +rw +Profile +The GstEncodingProfile to use. + + + + +GstEncodeBin::queue-buffers-max +guint + +rw +Max. size (buffers) +Max. number of buffers in the queue (0=disable). +200 + + + +GstEncodeBin::queue-bytes-max +guint + +rw +Max. size (kB) +Max. amount of data in the queue (bytes, 0=disable). +10485760 + + + +GstEncodeBin::queue-time-max +guint64 + +rw +Max. size (ns) +Max. amount of data in the queue (in ns, 0=disable). +1000000000 + + diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.hierarchy b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.hierarchy new file mode 100644 index 0000000..a49dbfe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.hierarchy @@ -0,0 +1,133 @@ +GObject + GstObject + GstPad + GstPadTemplate + GstPluginFeature + GstElementFactory + GstTypeFindFactory + GstIndexFactory + GstElement + GstBin + GstPipeline + GstPlayBaseBin + GstPlayBin + GstPlayBin2 + GstDecodeBin2 + GstURIDecodeBin + GstDecodeBin + GstPlaySink + GstSubtitleOverlay + GstEncodeBin + GstVorbisEnc + GstVorbisDec + GstVorbisParse + GstVorbisTag + GstVisual + GstVisualjess + GstVisualbumpscope + GstVisualcorona + GstVisualinfinite + GstVisualjakdaw + GstVisuallv_analyzer + GstVisuallv_scope + GstVisualoinksie + GstBaseSrc + GstPushSrc + GstCddaBaseSrc + GstCdParanoiaSrc + GstBaseAudioSrc + GstAudioSrc + GstAlsaSrc + GstVideoTestSrc + GstTCPClientSrc + GstTCPServerSrc + GstGioBaseSrc + GstGioSrc + GstGioStreamSrc + GstGnomeVFSSrc + GstAppSrc + GstAudioTestSrc + GstBaseSink + GstGioBaseSink + GstGioSink + GstGioStreamSink + GstBaseAudioSink + GstAudioSink + GstAlsaSink + GstGnomeVFSSink + GstVideoSink + GstXImageSink + GstXvImageSink + GstAppSink + GstTCPClientSink + GstMultiFdSink + GstTCPServerSink + GstTextOverlay + GstTimeOverlay + GstClockOverlay + GstTextRender + GstAlsaMixerElement + GstTheoraDec + GstTheoraEnc + GstTheoraParse + GstOggDemux + GstOggMux + GstOgmParse + GstOgmAudioParse + GstOgmVideoParse + GstOgmTextParse + GstOggParse + GstOggAviParse + GstAdder + GstBaseTransform + GstVideoFilter + GstVideoScale + GstFFMpegCsp + GstAudioFilter + GstVolume + GstAudioConvert + GstAudioResample + GstVideoRate + GstStreamSelector + GstGDPDepay + GstGDPPay + GstSubParse + GstSsaParse + GstAudioRate + GstBus + GstTask + GstTaskPool + GstClock + GstSystemClock + GstAudioClock + GstPlugin + GstRegistry + GstRingBuffer + GstAudioSrcRingBuffer + GstAudioSinkRingBuffer + GstSignalObject + GstMixerTrack + GstMixerOptions + GstStreamInfo + GstColorBalanceChannel + PangoFontMap + PangoFcFontMap + PangoCairoFcFontMap + PangoContext + GInputStream + GOutputStream +GInterface + GTypePlugin + GstChildProxy + GstURIHandler + GstTagSetter + GstPreset + GstImplementsInterface + GstMixer + GstPropertyProbe + GstNavigation + GstXOverlay + GstColorBalance + GstStreamVolume + PangoCairoFontMap + GFile diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.interfaces b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.interfaces new file mode 100644 index 0000000..772e582 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.interfaces @@ -0,0 +1,30 @@ +GstBin GstChildProxy +GstPipeline GstChildProxy +GstPlayBaseBin GstChildProxy +GstPlayBin GstChildProxy +GstPlayBin2 GstChildProxy GstStreamVolume +GstDecodeBin2 GstChildProxy +GstURIDecodeBin GstChildProxy +GstDecodeBin GstChildProxy +GstPlaySink GstChildProxy +GstSubtitleOverlay GstChildProxy +GstEncodeBin GstChildProxy +GstVorbisEnc GstTagSetter GstPreset +GstVorbisTag GstTagSetter +GstCddaBaseSrc GstURIHandler +GstCdParanoiaSrc GstURIHandler +GstAlsaSrc GstImplementsInterface GstMixer GstPropertyProbe +GstGioSrc GstURIHandler +GstGnomeVFSSrc GstURIHandler +GstAppSrc GstURIHandler +GstGioSink GstURIHandler +GstAlsaSink GstPropertyProbe +GstGnomeVFSSink GstURIHandler +GstXImageSink GstImplementsInterface GstNavigation GstXOverlay +GstXvImageSink GstImplementsInterface GstNavigation GstXOverlay GstColorBalance GstPropertyProbe +GstAppSink GstURIHandler +GstAlsaMixerElement GstImplementsInterface GstMixer GstPropertyProbe +GstTheoraEnc GstPreset +GstOggMux GstPreset +GstVolume GstImplementsInterface GstMixer GstStreamVolume +PangoCairoFcFontMap PangoCairoFontMap diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.prerequisites b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.prerequisites new file mode 100644 index 0000000..e81698c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.prerequisites @@ -0,0 +1,9 @@ +GstChildProxy GstObject +GstTagSetter GstElement +GstImplementsInterface GstElement +GstMixer GstImplementsInterface GstElement +GstXOverlay GstImplementsInterface GstElement +GstColorBalance GstImplementsInterface GstElement +GstStreamVolume GObject +PangoCairoFontMap PangoFontMap +GFile GObject diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.signals b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.signals new file mode 100644 index 0000000..67d8e8d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.signals @@ -0,0 +1,507 @@ + +GstMultiFdSink::add +void +la +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstMultiFdSink::clear +void +la +GstMultiFdSink *gstmultifdsink + + + +GstMultiFdSink::client-added +void +l +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstMultiFdSink::client-removed +void +l +GstMultiFdSink *gstmultifdsink +gint arg1 +GstClientStatus arg2 + + + +GstMultiFdSink::get-stats +GValueArray* +la +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstMultiFdSink::remove +void +la +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstMultiFdSink::client-fd-removed +void +l +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstMultiFdSink::add-full +void +la +GstMultiFdSink *gstmultifdsink +gint arg1 +GstSyncMethod arg2 +GstTCPUnitType arg3 +guint64 arg4 +GstTCPUnitType arg5 +guint64 arg6 + + + +GstMultiFdSink::remove-flush +void +la +GstMultiFdSink *gstmultifdsink +gint arg1 + + + +GstDecodeBin::new-decoded-pad +void +l +GstDecodeBin *gstdecodebin +GstPad *arg1 +gboolean arg2 + + + +GstDecodeBin::removed-decoded-pad +void +l +GstDecodeBin *gstdecodebin +GstPad *arg1 + + + +GstDecodeBin::unknown-type +void +l +GstDecodeBin *gstdecodebin +GstPad *arg1 +GstCaps *arg2 + + + +CDParanoia::smilie-change +void +CDParanoia *cdparanoia +gchar *arg1 + + + +CDParanoia::transport-error +void +CDParanoia *cdparanoia +gint arg1 + + + +CDParanoia::uncorrected-error +void +CDParanoia *cdparanoia +gint arg1 + + + +GstGnomeVFSSink::allow-overwrite +gboolean +c +GstGnomeVFSSink *gstgnomevfssink +GnomeVFSURI *arg1 + + + +GstCdParanoiaSrc::transport-error +void +l +GstCdParanoiaSrc *gstcdparanoiasrc +gint arg1 + + + +GstCdParanoiaSrc::uncorrected-error +void +l +GstCdParanoiaSrc *gstcdparanoiasrc +gint arg1 + + + +GstDecodeBin2::autoplug-continue +gboolean +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +GstCaps *arg2 + + + +GstDecodeBin2::autoplug-sort +GValueArray* +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +GstCaps *arg2 +GValueArray *arg3 + + + +GstDecodeBin2::new-decoded-pad +void +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +gboolean arg2 + + + +GstDecodeBin2::removed-decoded-pad +void +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 + + + +GstDecodeBin2::unknown-type +void +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +GstCaps *arg2 + + + +GstDecodeBin2::autoplug-factories +GValueArray* +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +GstCaps *arg2 + + + +GstDecodeBin2::autoplug-select +GstAutoplugSelectResult +l +GstDecodeBin2 *gstdecodebin2 +GstPad *arg1 +GstCaps *arg2 +GstElementFactory *arg3 + + + +GstDecodeBin2::drained +void +l +GstDecodeBin2 *gstdecodebin2 + + + +GstURIDecodeBin::autoplug-continue +gboolean +l +GstURIDecodeBin *gsturidecodebin +GstPad *arg1 +GstCaps *arg2 + + + +GstURIDecodeBin::autoplug-factories +GValueArray* +l +GstURIDecodeBin *gsturidecodebin +GstPad *arg1 +GstCaps *arg2 + + + +GstURIDecodeBin::autoplug-select +GstAutoplugSelectResult +l +GstURIDecodeBin *gsturidecodebin +GstPad *arg1 +GstCaps *arg2 +GstElementFactory *arg3 + + + +GstURIDecodeBin::unknown-type +void +l +GstURIDecodeBin *gsturidecodebin +GstPad *arg1 +GstCaps *arg2 + + + +GstURIDecodeBin::drained +void +l +GstURIDecodeBin *gsturidecodebin + + + +GstURIDecodeBin::autoplug-sort +GValueArray* +l +GstURIDecodeBin *gsturidecodebin +GstPad *arg1 +GstCaps *arg2 +GValueArray *arg3 + + + +GstURIDecodeBin::source-setup +void +l +GstURIDecodeBin *gsturidecodebin +GstElement *arg1 + + + +GstPlayBin2::about-to-finish +void +l +GstPlayBin2 *gstplaybin2 + + + +GstPlayBin2::audio-changed +void +l +GstPlayBin2 *gstplaybin2 + + + +GstPlayBin2::get-audio-tags +GstTagList* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::get-text-tags +GstTagList* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::get-video-tags +GstTagList* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::text-changed +void +l +GstPlayBin2 *gstplaybin2 + + + +GstPlayBin2::video-changed +void +l +GstPlayBin2 *gstplaybin2 + + + +GstPlayBin2::convert-frame +GstBuffer* +la +GstPlayBin2 *gstplaybin2 +GstCaps *arg1 + + + +GstPlayBin2::get-audio-pad +GstPad* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::get-text-pad +GstPad* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::get-video-pad +GstPad* +la +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::audio-tags-changed +void +l +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::text-tags-changed +void +l +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::video-tags-changed +void +l +GstPlayBin2 *gstplaybin2 +gint arg1 + + + +GstPlayBin2::source-setup +void +l +GstPlayBin2 *gstplaybin2 +GstElement *arg1 + + + +GstAppSink::eos +void +l +GstAppSink *gstappsink + + + +GstAppSink::new-buffer +void +l +GstAppSink *gstappsink + + + +GstAppSink::new-preroll +void +l +GstAppSink *gstappsink + + + +GstAppSink::pull-buffer +GstBuffer* +la +GstAppSink *gstappsink + + + +GstAppSink::pull-preroll +GstBuffer* +la +GstAppSink *gstappsink + + + +GstAppSink::new-buffer-list +void +l +GstAppSink *gstappsink + + + +GstAppSink::pull-buffer-list +GstBufferList* +la +GstAppSink *gstappsink + + + +GstAppSrc::end-of-stream +GstFlowReturn +la +GstAppSrc *gstappsrc + + + +GstAppSrc::enough-data +void +l +GstAppSrc *gstappsrc + + + +GstAppSrc::need-data +void +l +GstAppSrc *gstappsrc +guint arg1 + + + +GstAppSrc::push-buffer +GstFlowReturn +la +GstAppSrc *gstappsrc +GstBuffer *arg1 + + + +GstAppSrc::seek-data +gboolean +l +GstAppSrc *gstappsrc +guint64 arg1 + + + +GstPlaySink::reconfigure +gboolean +la +GstPlaySink *gstplaysink + + + +GstPlaySink::convert-frame +GstBuffer* +la +GstPlaySink *gstplaysink +GstCaps *arg1 + + + +GstEncodeBin::request-pad +GstPad* +la +GstEncodeBin *gstencodebin +GstCaps *arg1 + + diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.types b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.types new file mode 100644 index 0000000..9f4950e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/gst-plugins-base-plugins.types @@ -0,0 +1 @@ +#include diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect-build.stamp b/gst-plugins-base-subtitles0.10/docs/plugins/inspect-build.stamp new file mode 100644 index 0000000..e69de29 diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect.stamp b/gst-plugins-base-subtitles0.10/docs/plugins/inspect.stamp new file mode 100644 index 0000000..e0cb139 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect.stamp @@ -0,0 +1 @@ +timestamp \ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-adder.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-adder.xml new file mode 100644 index 0000000..d550573 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-adder.xml @@ -0,0 +1,34 @@ + + adder + Adds multiple streams + ../../gst/adder/.libs/libgstadder.so + libgstadder.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + adder + Adder + Generic/Audio + Add N audio channels together + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink%d + sink + request +
audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean){ true, false }; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }
+
+ + src + source + always +
audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean){ true, false }; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-alsa.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-alsa.xml new file mode 100644 index 0000000..78eaa69 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-alsa.xml @@ -0,0 +1,52 @@ + + alsa + ALSA plugin library + ../../ext/alsa/.libs/libgstalsa.so + libgstalsa.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + alsamixer + Alsa mixer + Generic/Audio + Control sound input and output levels with ALSA + Leif Johnson <leif@ambient.2y.net> + + + + + alsasink + Audio sink (ALSA) + Sink/Audio + Output to a sound card via ALSA + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)32, depth=(int)32, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)24, depth=(int)24, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)32, depth=(int)24, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, signed=(boolean){ true, false }, width=(int)8, depth=(int)8, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-iec958
+
+
+
+ + alsasrc + Audio source (ALSA) + Source/Audio + Read from a sound card via ALSA + Wim Taymans <wim@fluendo.com> + + + src + source + always +
audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)32, depth=(int)32, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)32, depth=(int)24, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)24, depth=(int)24, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, endianness=(int){ 1234, 4321 }, signed=(boolean){ true, false }, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]; audio/x-raw-int, signed=(boolean){ true, false }, width=(int)8, depth=(int)8, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-app.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-app.xml new file mode 100644 index 0000000..80f5001 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-app.xml @@ -0,0 +1,43 @@ + + app + Elements used to communicate with applications + ../../gst/app/.libs/libgstapp.so + libgstapp.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + appsink + AppSink + Generic/Sink + Allow the application to get access to raw buffer + David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com> + + + sink + sink + always +
ANY
+
+
+
+ + appsrc + AppSrc + Generic/Source + Allow the application to feed buffers to a pipeline + David Schleef <ds@schleef.org>, Wim Taymans <wim.taymans@gmail.com> + + + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioconvert.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioconvert.xml new file mode 100644 index 0000000..f2867ba --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioconvert.xml @@ -0,0 +1,34 @@ + + audioconvert + Convert audio to different formats + ../../gst/audioconvert/.libs/libgstaudioconvert.so + libgstaudioconvert.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + audioconvert + Audio converter + Filter/Converter/Audio + Convert audio to different formats + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)64; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)32; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)32, depth=(int)[ 1, 32 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)24, depth=(int)[ 1, 24 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)16, depth=(int)[ 1, 16 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)8, depth=(int)[ 1, 8 ], signed=(boolean){ true, false }
+
+ + src + source + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)64; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)32; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)32, depth=(int)[ 1, 32 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)24, depth=(int)[ 1, 24 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)16, depth=(int)[ 1, 16 ], signed=(boolean){ true, false }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int)8, depth=(int)[ 1, 8 ], signed=(boolean){ true, false }
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiorate.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiorate.xml new file mode 100644 index 0000000..68f0ef8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiorate.xml @@ -0,0 +1,34 @@ + + audiorate + Adjusts audio frames + ../../gst/audiorate/.libs/libgstaudiorate.so + libgstaudiorate.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + audiorate + Audio rate adjuster + Filter/Effect/Audio + Drops/duplicates/adjusts timestamps on audio samples to make a perfect stream + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], signed=(boolean){ true, false }; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int){ 32, 64 }
+
+ + src + source + always +
audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], signed=(boolean){ true, false }; audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int){ 1234, 4321 }, width=(int){ 32, 64 }
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioresample.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioresample.xml new file mode 100644 index 0000000..82b53e9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audioresample.xml @@ -0,0 +1,34 @@ + + audioresample + Resamples audio + ../../gst/audioresample/.libs/libgstaudioresample.so + libgstaudioresample.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + audioresample + Audio resampler + Filter/Converter/Audio + Resamples audio + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)24, depth=(int)24, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean)true
+
+ + src + source + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)24, depth=(int)24, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true; audio/x-raw-int, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean)true
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiotestsrc.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiotestsrc.xml new file mode 100644 index 0000000..9f6f4d3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-audiotestsrc.xml @@ -0,0 +1,28 @@ + + audiotestsrc + Creates audio test signals of given frequency and volume + ../../gst/audiotestsrc/.libs/libgstaudiotestsrc.so + libgstaudiotestsrc.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + audiotestsrc + Audio test source + Source/Audio + Creates audio test signals of given frequency and volume + Stefan Kost <ensonic@users.sf.net> + + + src + source + always +
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)32, depth=(int)32, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-cdparanoia.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-cdparanoia.xml new file mode 100644 index 0000000..5e90eca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-cdparanoia.xml @@ -0,0 +1,28 @@ + + cdparanoia + Read audio from CD in paranoid mode + ../../ext/cdparanoia/.libs/libgstcdparanoia.so + libgstcdparanoia.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + cdparanoiasrc + CD Audio (cdda) Source, Paranoia IV + Source/File + Read audio from CD in paranoid mode + Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com> + + + src + source + always +
audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)2
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-decodebin.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-decodebin.xml new file mode 100644 index 0000000..f37abd0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-decodebin.xml @@ -0,0 +1,34 @@ + + decodebin + decoder bin + ../../gst/playback/.libs/libgstdecodebin.so + libgstdecodebin.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + decodebin + Decoder Bin + Generic/Bin/Decoder + Autoplug and decode to raw media + Wim Taymans <wim.taymans@gmail.com> + + + sink + sink + always +
ANY
+
+ + src%d + source + sometimes +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-encoding.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-encoding.xml new file mode 100644 index 0000000..a5db521 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-encoding.xml @@ -0,0 +1,46 @@ + + encoding + various encoding-related elements + ../../gst/encoding/.libs/libgstencodebin.so + libgstencodebin.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + encodebin + Encoder Bin + Generic/Bin/Encoder + Convenience encoding/muxing element + Edward Hervey <edward.hervey@collabora.co.uk> + + + audio_%d + sink + request +
ANY
+
+ + private_%d + sink + request +
ANY
+
+ + video_%d + sink + request +
ANY
+
+ + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ffmpegcolorspace.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ffmpegcolorspace.xml new file mode 100644 index 0000000..25ae9e3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ffmpegcolorspace.xml @@ -0,0 +1,34 @@ + + ffmpegcolorspace + colorspace conversion copied from FFMpeg 0.4.9-pre1 + ../../gst/ffmpegcolorspace/.libs/libgstffmpegcolorspace.so + libgstffmpegcolorspace.so + 0.10.34 + LGPL + gst-plugins-base + FFMpeg + http://ffmpeg.sourceforge.net/ + + + ffmpegcolorspace + FFMPEG Colorspace converter + Filter/Converter/Video + Converts video from one colorspace to another + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
video/x-raw-yuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc){ I420, NV12, NV21, YV12, YUY2, Y42B, Y444, YUV9, YVU9, Y41B, Y800, Y8 , GREY, Y16 , UYVY, YVYU, IYU1, v308, AYUV, A420 }; 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-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)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)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)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)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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-yuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc){ I420, NV12, NV21, YV12, YUY2, Y42B, Y444, YUV9, YVU9, Y41B, Y800, Y8 , GREY, Y16 , UYVY, YVYU, IYU1, v308, AYUV, A420 }; 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-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)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)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)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)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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gdp.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gdp.xml new file mode 100644 index 0000000..c1ed224 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gdp.xml @@ -0,0 +1,55 @@ + + gdp + Payload/depayload GDP packets + ../../gst/gdp/.libs/libgstgdp.so + libgstgdp.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + gdpdepay + GDP Depayloader + GDP/Depayloader + Depayloads GStreamer Data Protocol buffers + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
application/x-gdp
+
+ + src + source + always +
ANY
+
+
+
+ + gdppay + GDP Payloader + GDP/Payloader + Payloads GStreamer Data Protocol buffers + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
ANY
+
+ + src + source + always +
application/x-gdp
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gio.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gio.xml new file mode 100644 index 0000000..b2661d0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gio.xml @@ -0,0 +1,73 @@ + + gio + GIO elements + ../../ext/gio/.libs/libgstgio.so + libgstgio.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + giosink + GIO sink + Sink/File + Write to any GIO-supported location + René Stadler <mail@renestadler.de>, Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
ANY
+
+
+
+ + giosrc + GIO source + Source/File + Read from any GIO-supported location + René Stadler <mail@renestadler.de>, Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + src + source + always +
ANY
+
+
+
+ + giostreamsink + GIO stream sink + Sink + Write to any GIO stream + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
ANY
+
+
+
+ + giostreamsrc + GIO stream source + Source + Read from any GIO stream + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gnomevfs.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gnomevfs.xml new file mode 100644 index 0000000..b6847f4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-gnomevfs.xml @@ -0,0 +1,43 @@ + + gnomevfs + elements to read from and write to Gnome-VFS uri's + ../../ext/gnomevfs/.libs/libgstgnomevfs.so + libgstgnomevfs.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + gnomevfssink + GnomeVFS Sink + Sink/File + Write a stream to a GnomeVFS URI + Bastien Nocera <hadess@hadess.net> + + + sink + sink + always +
ANY
+
+
+
+ + gnomevfssrc + GnomeVFS Source + Source/File + Read from any GnomeVFS-supported file + Bastien Nocera <hadess@hadess.net>, GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-libvisual.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-libvisual.xml new file mode 100644 index 0000000..d1f4a3e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-libvisual.xml @@ -0,0 +1,181 @@ + + libvisual + libvisual visualization plugins + ../../ext/libvisual/.libs/libgstlibvisual.so + libgstlibvisual.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + libvisual_bumpscope + libvisual Bumpscope plugin plugin v.0.0.1 + Visualization + Bumpscope visual plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_corona + libvisual libvisual corona plugin plugin v.0.1 + Visualization + Libvisual corona plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_infinite + libvisual infinite plugin plugin v.0.1 + Visualization + Infinite visual plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_jakdaw + libvisual Jakdaw plugin plugin v.0.0.1 + Visualization + jakdaw visual plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_jess + libvisual jess plugin plugin v.0.1 + Visualization + Jess visual plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_lv_analyzer + libvisual libvisual analyzer plugin v.1.0 + Visualization + Libvisual analyzer plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_lv_scope + libvisual libvisual scope plugin v.0.1 + Visualization + Libvisual scope plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + libvisual_oinksie + libvisual oinksie plugin plugin v.0.1 + Visualization + Libvisual Oinksie visual plugin + Benjamin Otte <otte@gnome.org> + + + sink + sink + always +
audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int)1234, signed=(boolean)true, channels=(int){ 1, 2 }, rate=(int){ 8000, 11250, 22500, 32000, 44100, 48000, 96000 }
+
+ + src + source + always +
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)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)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ogg.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ogg.xml new file mode 100644 index 0000000..691d07e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ogg.xml @@ -0,0 +1,160 @@ + + ogg + ogg stream manipulation (info about ogg: http://xiph.org) + ../../ext/ogg/.libs/libgstogg.so + libgstogg.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + oggaviparse + Ogg AVI parser + Codec/Parser + parse an ogg avi stream into pages (info about ogg: http://xiph.org) + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
application/x-ogg-avi
+
+ + src + source + always +
audio/x-vorbis
+
+
+
+ + oggdemux + Ogg demuxer + Codec/Demuxer + demux ogg streams (info about ogg: http://xiph.org) + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
application/ogg; application/x-annodex
+
+ + src_%d + source + sometimes +
ANY
+
+
+
+ + oggmux + Ogg muxer + Codec/Muxer + mux ogg streams (info about ogg: http://xiph.org) + Wim Taymans <wim@fluendo.com> + + + sink_%d + sink + request +
video/x-theora; audio/x-vorbis; audio/x-flac; audio/x-speex; audio/x-celt; application/x-ogm-video; application/x-ogm-audio; video/x-dirac; video/x-smoke; video/x-vp8; text/x-cmml, encoded=(boolean)true; subtitle/x-kate; application/x-kate
+
+ + src + source + always +
application/ogg
+
+
+
+ + oggparse + Ogg parser + Codec/Parser + parse ogg streams into pages (info about ogg: http://xiph.org) + Michael Smith <msmith@fluendo.com> + + + sink + sink + always +
application/ogg
+
+ + src + source + always +
application/ogg
+
+
+
+ + ogmaudioparse + OGM audio stream parser + Codec/Decoder/Audio + parse an OGM audio header and stream + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
application/x-ogm-audio
+
+ + src + source + sometimes +
audio/ms-gsm, rate=(int)[ 1, 96000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)2, rate=(int)[ 16000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-raw-int, endianness=(int)1234, signed=(boolean){ true, false }, width=(int){ 8, 16, 24, 32 }, depth=(int)[ 1, 32 ], rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-vorbis, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 2 ]; audio/x-ac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ]; audio/x-dts; audio/mpeg, mpegversion=(int)4, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 8 ]; audio/x-alaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-mulaw, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ]; audio/x-wms, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)microsoft, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 1000, 48000 ], channels=(int)[ 1, 2 ], block_align=(int)[ 1, 2147483647 ]; audio/x-truespeech, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/x-wma, wmaversion=(int)1, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)2, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-wma, wmaversion=(int)3, bitrate=(int)[ 0, 2147483647 ], rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 6 ], block_align=(int)[ 1, 2147483647 ]; audio/x-vnd.sony.atrac3, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-raw-float, endianness=(int)1234, width=(int){ 32, 64 }, rate=(int)[ 1000, 192000 ], channels=(int)[ 1, 8 ]; audio/x-voxware, voxwaretype=(int)117, rate=(int)[ 1000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk4, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dk3, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/x-adpcm, layout=(string)dvi, rate=(int)[ 8000, 96000 ], channels=(int)[ 1, 2 ]; audio/AMR, rate=(int)8000, channels=(int)1; audio/AMR-WB, rate=(int)16000, channels=(int)1; audio/x-siren; application/x-ogg-avi
+
+
+
+ + ogmtextparse + OGM text stream parser + Codec/Decoder/Subtitle + parse an OGM text header and stream + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
application/x-ogm-text
+
+ + src + source + sometimes +
text/plain
+
+
+
+ + ogmvideoparse + OGM video stream parser + Codec/Decoder/Video + parse an OGM video header and stream + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
application/x-ogm-video
+
+ + src + source + sometimes +
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 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-pango.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-pango.xml new file mode 100644 index 0000000..fe62a8b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-pango.xml @@ -0,0 +1,103 @@ + + pango + Pango-based text rendering and overlay + ../../ext/pango/.libs/libgstpango.so + libgstpango.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + clockoverlay + Clock overlay + Filter/Editor/Video + Overlays the current clock time on a video stream + Tim-Philipp Müller <tim@centricular.net> + + + video_sink + sink + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + textoverlay + Text overlay + Filter/Editor/Video + Adds text strings on top of a video buffer + David Schleef <ds@schleef.org>, Zeeshan Ali <zeeshan.ali@nokia.com> + + + text_sink + sink + always +
text/x-pango-markup; text/plain
+
+ + video_sink + sink + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+ + textrender + Text renderer + Filter/Editor/Video + Renders a text string to an image bitmap + David Schleef <ds@schleef.org>, GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
text/x-pango-markup; text/plain
+
+ + src + source + always +
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 ]
+
+
+
+ + timeoverlay + Time overlay + Filter/Editor/Video + Overlays buffer time stamps on a video stream + Tim-Philipp Müller <tim@centricular.net> + + + video_sink + sink + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
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)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)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)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)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)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)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)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-yuv, format=(fourcc){ AYUV, I420, UYVY, NV12, NV21 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-playback.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-playback.xml new file mode 100644 index 0000000..83d07d3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-playback.xml @@ -0,0 +1,97 @@ + + playback + various playback elements + ../../gst/playback/.libs/libgstplaybin.so + libgstplaybin.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + playbin + Player Bin + Generic/Bin/Player + Autoplug and play media from an uri + Wim Taymans <wim.taymans@gmail.com> + + + + + playbin2 + Player Bin 2 + Generic/Bin/Player + Autoplug and play media from an uri + Wim Taymans <wim.taymans@gmail.com> + + + + + playsink + Player Sink + Generic/Bin/Sink + Convenience sink for multiple streams + Wim Taymans <wim.taymans@gmail.com> + + + audio_raw_sink + sink + request +
ANY
+
+ + audio_sink + sink + request +
ANY
+
+ + text_sink + sink + request +
ANY
+
+ + video_raw_sink + sink + request +
ANY
+
+ + video_sink + sink + request +
ANY
+
+
+
+ + subtitleoverlay + Subtitle Overlay + Video/Overlay/Subtitle + Overlays a video stream with subtitles + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + subtitle_sink + sink + always +
ANY
+
+ + video_sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-subparse.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-subparse.xml new file mode 100644 index 0000000..ec7a1ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-subparse.xml @@ -0,0 +1,55 @@ + + subparse + Subtitle parsing + ../../gst/subparse/.libs/libgstsubparse.so + libgstsubparse.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + ssaparse + SSA Subtitle Parser + Codec/Parser/Subtitle + Parses SSA subtitle streams + Tim-Philipp Müller <tim centricular net> + + + sink + sink + always +
application/x-ssa; application/x-ass
+
+ + src + source + always +
text/x-pango-markup
+
+
+
+ + subparse + Subtitle parser + Codec/Parser/Subtitle + Parses subtitle (.sub) files into text streams + Gustavo J. A. M. Carneiro <gjc@inescporto.pt>, GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
application/x-subtitle; application/x-subtitle-sami; application/x-subtitle-tmplayer; application/x-subtitle-mpl2; application/x-subtitle-dks; application/x-subtitle-qttext
+
+ + src + source + always +
text/plain; text/x-pango-markup
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-tcp.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-tcp.xml new file mode 100644 index 0000000..82cf63d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-tcp.xml @@ -0,0 +1,88 @@ + + tcp + transfer data over the network via TCP + ../../gst/tcp/.libs/libgsttcp.so + libgsttcp.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + multifdsink + Multi filedescriptor sink + Sink/Network + Send data to multiple filedescriptors + Thomas Vander Stichele <thomas at apestaart dot org>, Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
ANY
+
+
+
+ + tcpclientsink + TCP client sink + Sink/Network + Send data as a client over the network via TCP + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
ANY
+
+
+
+ + tcpclientsrc + TCP client source + Source/Network + Receive data as a client over the network via TCP + Thomas Vander Stichele <thomas at apestaart dot org> + + + src + source + always +
ANY
+
+
+
+ + tcpserversink + TCP server sink + Sink/Network + Send data as a server over the network via TCP + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
ANY
+
+
+
+ + tcpserversrc + TCP server source + Source/Network + Receive data as a server over the network via TCP + Thomas Vander Stichele <thomas at apestaart dot org> + + + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-theora.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-theora.xml new file mode 100644 index 0000000..a972089 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-theora.xml @@ -0,0 +1,76 @@ + + theora + Theora plugin library + ../../ext/theora/.libs/libgsttheora.so + libgsttheora.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + theoradec + Theora video decoder + Codec/Decoder/Video + decode raw theora streams to raw YUV video + Benjamin Otte <otte@gnome.org>, Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
video/x-theora
+
+ + src + source + always +
video/x-raw-yuv, format=(fourcc){ I420, Y42B, Y444 }, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]
+
+
+
+ + theoraenc + Theora video encoder + Codec/Encoder/Video + encode raw YUV video to a theora stream + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
video/x-raw-yuv, format=(fourcc){ I420, Y42B, Y444 }, framerate=(fraction)[ 1/2147483647, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]
+
+ + src + source + always +
video/x-theora
+
+
+
+ + theoraparse + Theora video parser + Codec/Parser/Video + parse raw theora streams + Andy Wingo <wingo@pobox.com> + + + sink + sink + always +
video/x-theora
+
+ + src + source + always +
video/x-theora
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-typefindfunctions.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-typefindfunctions.xml new file mode 100644 index 0000000..bcce4f3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-typefindfunctions.xml @@ -0,0 +1,13 @@ + + typefindfunctions + default typefind functions + ../../gst/typefind/.libs/libgsttypefindfunctions.so + libgsttypefindfunctions.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + \ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-uridecodebin.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-uridecodebin.xml new file mode 100644 index 0000000..caac56d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-uridecodebin.xml @@ -0,0 +1,49 @@ + + uridecodebin + URI Decoder bin + ../../gst/playback/.libs/libgstdecodebin2.so + libgstdecodebin2.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + decodebin2 + Decoder Bin + Generic/Bin/Decoder + Autoplug and decode to raw media + Edward Hervey <edward.hervey@collabora.co.uk>, Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
ANY
+
+ + src%d + source + sometimes +
ANY
+
+
+
+ + uridecodebin + URI Decoder + Generic/Bin/Decoder + Autoplug and decode an URI to raw media + Wim Taymans <wim.taymans@gmail.com> + + + src%d + source + sometimes +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-video4linux.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-video4linux.xml new file mode 100644 index 0000000..eddf4b1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-video4linux.xml @@ -0,0 +1,28 @@ + + video4linux + elements for Video 4 Linux + ../../sys/v4l/.libs/libgstvideo4linux.so + libgstvideo4linux.so + 0.10.32.1 + LGPL + gst-plugins-base + GStreamer Base Plug-ins git + Unknown package origin + + + v4lsrc + Video (video4linux/raw) Source + Source/Video + Reads raw frames from a video4linux device + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + src + source + always +
ANY
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videorate.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videorate.xml new file mode 100644 index 0000000..d469b97 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videorate.xml @@ -0,0 +1,34 @@ + + videorate + Adjusts video frames + ../../gst/videorate/.libs/libgstvideorate.so + libgstvideorate.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + videorate + Video rate adjuster + Filter/Effect/Video + Drops/duplicates/adjusts timestamps on video frames to make a perfect stream + Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
video/x-raw-yuv; video/x-raw-rgb; video/x-raw-gray; image/jpeg; image/png
+
+ + src + source + always +
video/x-raw-yuv; video/x-raw-rgb; video/x-raw-gray; image/jpeg; image/png
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videoscale.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videoscale.xml new file mode 100644 index 0000000..76f0298 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videoscale.xml @@ -0,0 +1,34 @@ + + videoscale + Resizes video + ../../gst/videoscale/.libs/libgstvideoscale.so + libgstvideoscale.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + videoscale + Video scaler + Filter/Converter/Video/Scaler + Resizes video + Wim Taymans <wim.taymans@chello.be> + + + sink + sink + always +
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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)v308, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y16 , width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y800, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y8 , width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)GREY, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AY64, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)v308, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YUY2, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y16 , width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y800, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y8 , width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)GREY, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AY64, width=(int)[ 1, 32767 ], height=(int)[ 1, 32767 ], 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, 32767 ], height=(int)[ 1, 32767 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videotestsrc.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videotestsrc.xml new file mode 100644 index 0000000..7d90f1e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-videotestsrc.xml @@ -0,0 +1,28 @@ + + videotestsrc + Creates a test video stream + ../../gst/videotestsrc/.libs/libgstvideotestsrc.so + libgstvideotestsrc.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + videotestsrc + Video test source + Source/Video + Creates a test video stream + David A. Schleef <ds@schleef.org> + + + src + source + always +
video/x-raw-yuv, format=(fourcc)YUY2, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVYU, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)v308, color-matrix=(string){ sdtv, hdtv }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AYUV, color-matrix=(string){ sdtv, hdtv }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)v210, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)v216, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVP, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AY64, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YVU9, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YUV9, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)YV12, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)I420, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)NV12, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)NV21, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y41B, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y42B, color-matrix=(string){ sdtv, hdtv }, chroma-site=(string){ mpeg2, jpeg }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y444, color-matrix=(string){ sdtv, hdtv }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)Y800, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, endianness=(int)4321, depth=(int)24, 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, endianness=(int)4321, depth=(int)24, 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, endianness=(int)4321, depth=(int)24, 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, endianness=(int)4321, depth=(int)24, 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, endianness=(int)4321, depth=(int)32, 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, endianness=(int)4321, depth=(int)32, 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, endianness=(int)4321, depth=(int)32, 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)32, endianness=(int)4321, depth=(int)32, 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)24, endianness=(int)4321, depth=(int)24, 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, endianness=(int)4321, depth=(int)24, 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)16, endianness=(int)1234, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, endianness=(int)1234, depth=(int)15, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)64, endianness=(int)4321, depth=(int)64, 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-bayer, format=(string)bggr, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-bayer, format=(string)rggb, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-bayer, format=(string)grbg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-bayer, format=(string)gbrg, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-volume.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-volume.xml new file mode 100644 index 0000000..8bbfc58 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-volume.xml @@ -0,0 +1,34 @@ + + volume + plugin for controlling audio volume + ../../gst/volume/.libs/libgstvolume.so + libgstvolume.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + volume + Volume + Filter/Effect/Audio + Set volume on audio/raw streams + Andy Wingo <wingo@pobox.com> + + + sink + sink + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)24, depth=(int)24, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean)true
+
+ + src + source + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int){ 32, 64 }; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)8, depth=(int)8, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)16, depth=(int)16, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)24, depth=(int)24, signed=(boolean)true; audio/x-raw-int, channels=(int)[ 1, 2147483647 ], rate=(int)[ 1, 2147483647 ], endianness=(int)1234, width=(int)32, depth=(int)32, signed=(boolean)true
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-vorbis.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-vorbis.xml new file mode 100644 index 0000000..f94b83f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-vorbis.xml @@ -0,0 +1,97 @@ + + vorbis + Vorbis plugin library + ../../ext/vorbis/.libs/libgstvorbis.so + libgstvorbis.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + vorbisdec + Vorbis audio decoder + Codec/Decoder/Audio + decode raw vorbis streams to float audio + Benjamin Otte <otte@gnome.org>, Chris Lord <chris@openedhand.com> + + + sink + sink + always +
audio/x-vorbis
+
+ + src + source + always +
audio/x-raw-float, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 256 ], endianness=(int)1234, width=(int)32
+
+
+
+ + vorbisenc + Vorbis audio encoder + Codec/Encoder/Audio + Encodes audio in Vorbis format + Monty <monty@xiph.org>, Wim Taymans <wim@fluendo.com> + + + sink + sink + always +
audio/x-raw-float, rate=(int)[ 1, 200000 ], channels=(int)[ 1, 256 ], endianness=(int)1234, width=(int)32
+
+ + src + source + always +
audio/x-vorbis
+
+
+
+ + vorbisparse + VorbisParse + Codec/Parser/Audio + parse raw vorbis streams + Thomas Vander Stichele <thomas at apestaart dot org> + + + sink + sink + always +
audio/x-vorbis
+
+ + src + source + always +
audio/x-vorbis
+
+
+
+ + vorbistag + VorbisTag + Formatter/Metadata + Retags vorbis streams + James Livingston <doclivingston@gmail.com> + + + sink + sink + always +
audio/x-vorbis
+
+ + src + source + always +
audio/x-vorbis
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ximagesink.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ximagesink.xml new file mode 100644 index 0000000..07578e6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-ximagesink.xml @@ -0,0 +1,28 @@ + + ximagesink + X11 video output element based on standard Xlib calls + ../../sys/ximage/.libs/libgstximagesink.so + libgstximagesink.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + ximagesink + Video sink + Sink/Video + A standard X based videosink + Julien Moutte <julien@moutte.net> + + + sink + sink + always +
video/x-raw-rgb, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-xvimagesink.xml b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-xvimagesink.xml new file mode 100644 index 0000000..8b3a91b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/plugins/inspect/plugin-xvimagesink.xml @@ -0,0 +1,28 @@ + + xvimagesink + XFree86 video output plugin using Xv extension + ../../sys/xvimage/.libs/libgstxvimagesink.so + libgstxvimagesink.so + 0.10.34 + LGPL + gst-plugins-base + GStreamer Base Plug-ins source release + Unknown package origin + + + xvimagesink + Video sink + Sink/Video + A Xv based videosink + Julien Moutte <julien@moutte.net> + + + sink + sink + always +
video/x-raw-rgb, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]; video/x-raw-yuv, framerate=(fraction)[ 0/1, 2147483647/1 ], width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]
+
+
+
+
+
\ No newline at end of file diff --git a/gst-plugins-base-subtitles0.10/docs/plugins/scanobj-build.stamp b/gst-plugins-base-subtitles0.10/docs/plugins/scanobj-build.stamp new file mode 100644 index 0000000..e69de29 diff --git a/gst-plugins-base-subtitles0.10/docs/random/ChangeLog-0.8 b/gst-plugins-base-subtitles0.10/docs/random/ChangeLog-0.8 new file mode 100644 index 0000000..a350d14 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/random/ChangeLog-0.8 @@ -0,0 +1,15589 @@ +2005-02-22 Ronald S. Bultje + + * sys/oss/gstosselement.c: (gst_osselement_class_probe_devices): + Kick the hell out of gcc for not warning me about a symbol conflict. + +2005-02-22 Luca Ognibene + + Reviewed by: Tim-Philipp Müller + + * ext/gdk_pixbuf/pixbufscale.c: (gst_pixbufscale_link): + Don't leak caps string (fixes #168134) + + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_class_init), + (gst_jpegenc_init), (gst_jpegenc_finalize), + (gst_jpegenc_change_state): + Don't leak line buffers and context struct (fixes #168133). + +2005-02-21 Tim-Philipp Müller + + * configure.ac: + * ext/dirac/gstdiracdec.cc: + (gst_diracdec_chain): + Since dirac 0.5.0 the framerate in dirac is expressed as a + rational number. Fix build and up requirement to 0.5.0, and + also pass parameters to gst_diracdec_link in the right order + (fixes #167959). + +2005-02-21 Maciej Katafiasz + + * ext/faad/gstfaad.c: (gst_faad_sinkconnect), (gst_faad_chain): + * ext/faad/gstfaad.h: + TEH LONGEST DEBUGGING SESSION EVAR is over. Fix interaction with + certain invalid muxed streams, where some packets will contain + junk after decoder data. Partially fixes #149158. + +2005-02-21 Jan Schmidt + * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcmdec_chain): + Make sure we only write to writable buffers + +2005-02-20 Tim-Philipp Müller + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data): + Do actually fix invalid RIFF fmt header values for alaw + and mulaw audio instead of just saying so. + + * gst/wavparse/gstwavparse.c: (gst_wavparse_fmt): + Give gst_riff_create_audio_caps_with_data() a chance to + fix up broken format header fields before extracting any + parameters from the header. (fixes #167633) + +2005-02-19 Martin Holters + + Reviewed by: Tim-Philipp Müller + + * gst/audioconvert/bufferframesconvert.c: + (buffer_frames_convert_link): + Don't leak othercaps. (fixes #167878) + +2005-02-19 Arwed v. Merkatz + + * configure.ac: + * ext/libvisual/visual.c: (gst_visual_srclink), + (gst_visual_change_state): + Support libvisual 0.2.0. + +2005-02-18 Tim-Philipp Müller + + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_chain): + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_resync), (gst_jpegenc_chain): + Use same rowstrides for I420 as used everywhere else. + +2005-02-17 Tim-Philipp Müller + + * gst/avi/gstavidemux.c: (gst_avi_demux_invert): + Declare variables at beginning of block and make gcc-2.95 happy + (fixes # 167482, patch by Gergely Nagy). + + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpclientsrc.h: + Move some includes into the header, so that struct sockaddr_in is + defined when it should be defined on FreeBSD as well (fixes + #167483). + + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_init_receive): + Don't pass uninitialised values to setsockopt() here either. + +2005-02-17 Luca Ognibene + + Reviewed by: Tim-Philipp Müller + + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_init_send): + Don't pass uninitialised values to setsockopt(). (fixes #167704) + +2005-02-16 Ronald S. Bultje + + * gst/playback/gstplaybin.c: (add_sink): + Invert bin_add/link order to workaround deadlock in opt. + +2005-02-15 Ronald S. Bultje + + * gst/modplug/gstmodplug.cc: + Add missing break causing position queries to fail. + +2005-02-15 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_populate): + Granpos can apparently be -1, which screws up calculations... + +2005-02-16 Jan Schmidt + + * sys/ximage/ximagesink.c: (gst_ximagesink_chain), + (gst_ximagesink_send_pending_navigation), + (gst_ximagesink_navigation_send_event), (gst_ximagesink_finalize), + (gst_ximagesink_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain), + (gst_xvimagesink_send_pending_navigation), + (gst_xvimagesink_navigation_send_event), + (gst_xvimagesink_finalize), (gst_xvimagesink_init): + * sys/xvimage/xvimagesink.h: + Use a mutex protected list to marshal navigation + events into the stream thread from whichever thread + sends them. + +2005-02-15 Tim-Philipp Müller + + * gst/speed/demo-mp3.c: (time_tick_cb), (main): + Display current position and track length; misc. clean-ups. + + * gst/speed/gstspeed.c: (speed_get_query_types), (speed_src_query), + (speed_init), (speed_chain): + Add query function, so that the stream length and current position + get adjusted when queried (note that current position queries may + still be wrong if the audio sink returns values based on buffer + timestamps instead of passing on the query). + +2005-02-13 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link), + (gst_audio_convert_channels): + create channel conversion matrix when linking + * gst/audioconvert/.cvsignore: + * gst/audioconvert/Makefile.am: + * gst/audioconvert/channelmixtest.c: (main): + add (ugly) test that ensures stereo <=> mono conversion works + correctly + +2005-02-13 Benjamin Otte + + * gst/audioconvert/gstchannelmix.h: + include missing header file + * gst/audioconvert/gstchannelmix.c: + (gst_audio_convert_fill_compatible): + use same sign for both channels when converting to/from compatible + channel. Previously used different signs made the signals cancel + each other out and appear like silence. (fixes #167269) + +2005-02-12 Tim-Philipp Müller + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: + Convert to and from YV12 (fixes #156379). + +2005-02-12 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new), + (gst_ximagesink_sink_link), (gst_ximagesink_change_state), + (gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_expose), (gst_ximagesink_set_property), + (gst_ximagesink_finalize), (gst_ximagesink_init): Protect interface + methods from chain and negotiation and vice versa (Fixes #166142). + * sys/ximage/ximagesink.h: Add stream_lock. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_free), + (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_expose): Check for xcontext before trying to link. + +2005-02-12 Tim-Philipp Müller + + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_open): + Don't send "Hey! You gave me a NULL pointer you naughty person" as + error message when we can't open the DVD device (when dvdnav_open() + fails, src->dvdnav is NULL, so dvdnav_err_to_string() will return + the above). Send something more useful instead (fixes #167117). + +2005-02-11 Julien MOUTTE + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_sink_link), (gst_xvimagesink_change_state), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_free), + (gst_xvimagesink_buffer_alloc), (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_expose), (gst_xvimagesink_set_property), + (gst_xvimagesink_finalize), (gst_xvimagesink_init): Protect interface + methods from chain and negotiation and vice versa (Fixes #166142). + Fix a possible bug of images in the buffer pool being discarded because + we are looking at the wrong geometry. + * sys/xvimage/xvimagesink.h: Add stream_lock. + +2005-02-11 David Schleef + + * ext/mpeg2dec/gstmpeg2dec.c: (crop_buffer): Change uint to + unsigned int. (fixes #167128) + +2005-02-11 David Schleef + + * gst/librfb/Makefile.am: Testing stuff before committing is + for wimps... and people with fast machines. Fix stupid + mistake. + +2005-02-11 David Schleef + + * configure.ac: Pull in librfb from my CVS tree, because it is + too small and annoying to be separate. Move rfbsrc plugin + to gst/. + * ext/Makefile.am: + * ext/librfb/Makefile.am: + * ext/librfb/gstrfbsrc.c: + * gst/librfb/Makefile.am: + * gst/librfb/gstrfbsrc.c: + * gst/librfb/rfb.c: + * gst/librfb/rfb.h: + * gst/librfb/rfbbuffer.c: + * gst/librfb/rfbbuffer.h: + * gst/librfb/rfbbytestream.c: + * gst/librfb/rfbbytestream.h: + * gst/librfb/rfbcontext.h: + * gst/librfb/rfbdecoder.c: + * gst/librfb/rfbdecoder.h: + * gst/librfb/rfbutil.h: + +2005-02-10 Tim-Philipp Müller + + * gst/speed/Makefile.am: + * gst/speed/demo-mp3.c: (main): + * gst/speed/filter.func: + * gst/speed/gstspeed.c: (speed_link), (speed_parse_caps), + (speed_class_init), (speed_init), (speed_chain_int16), + (speed_chain_float32), (speed_chain), (speed_set_property), + (speed_get_property), (speed_change_state): + * gst/speed/gstspeed.h: + Fix speed element and make it chain-based (fixes #156467), + and make it handle more than one channel. + +2005-02-10 Jan Schmidt + + * ext/dts/gstdtsdec.c: (gst_dtsdec_init), (gst_dtsdec_channels), + (gst_dtsdec_handle_event), (gst_dtsdec_handle_frame), + (gst_dtsdec_chain), (gst_dtsdec_change_state): + * ext/dts/gstdtsdec.h: + Don't clobber the stack constructing the channels array. + Make the element chain-based. DTS tracks can now be played. + +2005-02-09 Tim-Philipp Müller + + * gst-libs/gst/audio/multichannel.h: + * gst-libs/gst/gconf/gconf.h: + * gst-libs/gst/idct/idct.h: + * gst-libs/gst/media-info/media-info-priv.h: + * gst-libs/gst/play/play.h: + * gst-libs/gst/resample/private.h: + * gst-libs/gst/resample/resample.h: + * gst-libs/gst/riff/riff-ids.h: + * gst-libs/gst/video/video.h: + * gst-libs/gst/video/videosink.h: + Add G_BEGIN_DECLS and G_END_DECLS around headers where + missing, so that they work when included from C++ code. + +2005-02-09 David Schleef + + * testsuite/gst-lint: Check for non-statically scoped + parent_class variables. This won't be a problem once + plugins are loaded with RTLD_LOCAL. + +2005-02-09 Ronald S. Bultje + + * ext/mplex/gstmplexibitstream.cc: + gcc madness. + +2005-02-09 Ronald S. Bultje + + * ext/ogg/gstogmparse.c: + * gst/debug/gstnavigationtest.c: + Die, thou faulty symbol pollutors (non-static parent_class). + +2005-02-08 Ronald S. Bultje + + * ext/mplex/gstmplexibitstream.cc: + Fix event handling (#165525). + +2005-02-08 Ronald S. Bultje + + * ext/mikmod/gstmikmod.c: + * gst/modplug/gstmodplug.cc: + Add missing endianness to template (fixes #165509). + +2005-02-08 Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_data): + Fix wrong order of reading of optional bytes (#165290). + +2005-02-08 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + Implement FILLER event awareness. + +2005-02-08 Ronald S. Bultje + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_convert): + Fix track calculations (#166208). + +2005-02-08 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * ext/libpng/gstpngdec.c: (gst_pngdec_init), (gst_pngdec_chain): + * ext/libpng/gstpngenc.c: + Fix byte-order, use proper fixed caps. Fixes #164197. + +2005-02-08 Jan Schmidt + + * configure.ac: + Add dvdlpcmdec + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_reset), + (free_all_buffers), (gst_mpeg2dec_alloc_buffer): + Don't push buffers if the src pad isn't negotiated yet. + + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_buffer_to_default_format), + (gst_audio_convert_buffer_from_default_format): + Add support for 24-bit width. + + * gst/dvdlpcmdec/.cvsignore: + * gst/dvdlpcmdec/Makefile.am: + * gst/dvdlpcmdec/gstdvdlpcmdec.c: (gst_dvdlpcmdec_get_type), + (gst_dvdlpcmdec_base_init), (gst_dvdlpcmdec_class_init), + (gst_dvdlpcm_reset), (gst_dvdlpcmdec_init), (gst_dvdlpcmdec_link), + (gst_dvdlpcmdec_chain), (gst_dvdlpcmdec_change_state), + (plugin_init): + * gst/dvdlpcmdec/gstdvdlpcmdec.h: + New decoder for rearranging DVD LPCM into our audio/x-raw-int + format. Needs support for the channels maps if someone can find + a DVD LPCM track with > 2 channels. + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_handle_dvd_event), + (gst_dvd_demux_send_discont), (gst_dvd_demux_handle_discont), + (gst_dvd_demux_get_audio_stream), (gst_dvd_demux_process_private): + * gst/mpegstream/gstdvddemux.h: + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_discont), + (gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_init_stream), + (gst_mpeg_demux_send_subbuffer), (gst_mpeg_demux_handle_src_query): + * gst/mpegstream/gstmpegdemux.h: + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_reset), + (gst_mpeg_parse_parse_packhead), (gst_mpeg_parse_loop), + (gst_mpeg_parse_get_rate), (gst_mpeg_parse_convert_src), + (gst_mpeg_parse_handle_src_query), + (gst_mpeg_parse_handle_src_event): + Use audio/x-dvd-lpcm for LPCM output. + Add DTS output. + +2005-02-08 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * gst/alpha/gstalphacolor.c: (gst_alpha_color_sink_link), + (transform_rgb), (transform_bgr), (gst_alpha_color_chain): + Add BGRA handling (#165736). + +2005-02-08 Francis Labonte + + Reviewed by: Ronald S. Bultje + + * gst/law/alaw-decode.c: (alawdec_link): + * gst/law/alaw-encode.c: (alawenc_link): + * gst/law/mulaw-decode.c: (mulawdec_link): + * gst/law/mulaw-encode.c: (mulawenc_link): + Fix caps memleaks (#166600). + +2005-02-08 Tim-Philipp Müller + + * ext/tarkin/mem.h: + * ext/tarkin/wavelet.h: + * ext/tarkin/yuv.h: + * gst/ffmpegcolorspace/avcodec.h: + Include "_stdint.h" instead of . Fixes build on + systems that don't have stdint.h, like Solaris9 (fixes #166631). + +2005-02-05 Ronald S. Bultje + + * sys/ximage/ximagesink.c: (gst_ximagesink_change_state): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_clear), + (gst_xvimagesink_change_state): + Clear window on PAUSED->READY instead of READY->PAUSED. Stop + Xv video (and thereby regenerate Xv colourkey) in clear() so + that PLAY -> READY -> PLAY works (fixes #162504). + +2005-02-05 Ronald S. Bultje + + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_getcaps): + Switch to list instead of range, since MJPEG-devices really just + support decimations, not any size. + +2005-02-05 Jan Schmidt + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_open_decoder), + (gst_mpeg2dec_reset), (free_all_buffers), + (gst_mpeg2dec_alloc_buffer), (handle_sequence): + * ext/mpeg2dec/gstmpeg2dec.h: + The libmpeg2 user-allocated buffer management is awkward, + to say the least. Hopefully this fixes things. + +2005-02-04 Andy Wingo + + * gst/audioconvert/bufferframesconvert.c + (buffer_frames_convert_fixate): New function, fixates to 256 + frames per buffer by default. (Much better than 1.) + (buffer_frames_convert_init): Set the fixate function for both src + and sink pad. + (buffer_frames_convert_link): After success setting nonfixed caps, + get the negotiated caps so we can know how many buffer-frames it + will be. No idea how this worked at all before. + +2005-02-05 Jan Schmidt + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init), + (gst_mpeg2dec_close_decoder), (put_buffer), (check_buffer), + (free_buffer), (free_all_buffers), (gst_mpeg2dec_alloc_buffer), + (handle_sequence), (handle_picture): + * ext/mpeg2dec/gstmpeg2dec.h: + Rearrange buffer tracking and refcounting and refactor + a little for readability. + +2005-02-04 Jan Schmidt + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l/gstv4ljpegsrc.c: (gst_v4ljpegsrc_get_type), + (gst_v4ljpegsrc_base_init), (gst_v4ljpegsrc_class_init), + (gst_v4ljpegsrc_init), (gst_v4ljpegsrc_src_link), + (gst_v4ljpegsrc_getcaps), (gst_v4ljpegsrc_get): + * sys/v4l/gstv4ljpegsrc.h: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_open), (gst_v4lsrc_src_link): + * sys/v4l/v4l_calls.h: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_palette_name), + (gst_v4lsrc_get_fps): + * sys/v4l/v4lsrc_calls.h: + Add new v4ljpegsrc for handling the ov51x hacky "I'll give + you jpeg inside rgb frames" driver. + Don't error in the v4lsrc link function, just return + REFUSED. + +2005-02-03 Ronald S. Bultje + + * sys/qcam/gstqcamsrc.c: (gst_qcamsrc_change_state), + (gst_qcamsrc_open): + Use GST_ELEMENT_ERROR, not g_warning, if open failed. + +2005-02-02 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_video_caps): + Change caps on MJPEG-B so it doesn't interfere with MJPEG/JPEG. + +2005-02-02 Ronald S. Bultje + + * ext/raw1394/gstdv1394src.c: (gst_dv1394src_change_state): + Reset negotiated state on PAUSED->READY. + +2005-02-02 David Schleef + + * configure.ac: Put DEFAULT_AUDIOSINK in config.h and use + whereever possible. (Fixes #165997) + * examples/capsfilter/capsfilter1.c: (main): + * examples/dynparams/filter.c: (create_ui): + * examples/seeking/cdparanoia.c: (get_track_info), (main): + * examples/seeking/chained.c: (main): + * examples/seeking/seek.c: (make_mod_pipeline), (make_dv_pipeline), + (make_wav_pipeline), (make_flac_pipeline), (make_sid_pipeline), + (make_vorbis_pipeline), (make_mp3_pipeline), (make_avi_pipeline), + (make_mpeg_pipeline), (make_mpegnt_pipeline): + * examples/seeking/spider_seek.c: (make_spider_pipeline): + * examples/switch/switcher.c: (main): + * ext/dv/demo-play.c: (main): + * ext/faad/gstfaad.c: (gst_faad_change_state): + * ext/mad/gstmad.c: (gst_mad_chain): + * ext/smoothwave/demo-osssrc.c: (main): + * gst-libs/gst/gconf/gconf.c: (gst_gconf_set_string), + (gst_gconf_render_bin_from_description), + (gst_gconf_get_default_audio_sink), + (gst_gconf_get_default_video_sink), + (gst_gconf_get_default_audio_src), + (gst_gconf_get_default_video_src), + (gst_gconf_get_default_visualization_element): + * gst/level/demo.c: (main): + * gst/level/plot.c: (main): + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element): + * gst/playback/test.c: (gen_video_element), (gen_audio_element): + * gst/playondemand/demo-mp3.c: (setup_pipeline): + * gst/sine/demo-dparams.c: (main): + * gst/spectrum/demo-osssrc.c: (main): + * gst/speed/demo-mp3.c: (main): + * gst/volume/demo.c: (main): + * testsuite/embed/embed.c: (main): + +2005-02-02 Jan Schmidt + + * gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_class_init), + (gst_tcpclientsink_finalize): + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_class_init), + (gst_tcpclientsrc_finalize): + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init), + (gst_tcpserversink_init), (gst_tcpserversink_finalize): + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_class_init), + (gst_tcpserversrc_init), (gst_tcpserversrc_finalize): + Don't leak the hostname when shutting down. + In tcpserversrc, take a copy of the default hostname. + +2005-02-01 Ronald S. Bultje + + * ext/raw1394/gstdv1394src.c: (gst_dv1394src_iso_receive): + Set caps to systemstream=TRUE. + +2005-02-01 Ronald S. Bultje + + * testsuite/Makefile.am: + Fix more OSX buildbots. + +2005-02-02 Jan Schmidt + + * ext/mpeg2dec/gstmpeg2dec.c: + Don't send things to NULL PAD_PEERs + + * gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_chain): + Copy-on-write the incoming buffer. + + * gst/mpegstream/gstdvddemux.h: + * gst/mpegstream/gstmpegclock.h: + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead), + (normal_seek), (gst_mpeg_demux_handle_src_event): + * gst/mpegstream/gstmpegdemux.h: + * gst/mpegstream/gstmpegpacketize.h: + * gst/mpegstream/gstmpegparse.c: + (gst_mpeg_parse_update_streaminfo), (gst_mpeg_parse_reset), + (gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead), + (gst_mpeg_parse_loop), (gst_mpeg_parse_get_rate), + (gst_mpeg_parse_convert_src), (gst_mpeg_parse_handle_src_query), + (gst_mpeg_parse_handle_src_event), (gst_mpeg_parse_change_state): + * gst/mpegstream/gstmpegparse.h: + * gst/mpegstream/gstrfc2250enc.h: + Various changes to the way time is computed that make seeking and + total time estimation much better here. + Use G_BEGIN/END_DECLS instead of __cplusplus + + * gst/videocrop/gstvideocrop.c: (gst_video_crop_chain): + Use gst_buffer_stamp instead of only copying the TIMESTAMP + +2005-02-01 Ronald S. Bultje + + * gst/subparse/gstsubparse.c: + Fix OSX buildbot. + +2005-01-31 Tim-Philipp Müller + + * ext/theora/theoraenc.c: (theora_buffer_from_packet), + (theora_enc_chain), (theora_enc_change_state): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_init), + (gst_vorbisenc_buffer_from_packet), (gst_vorbisenc_chain), + (gst_vorbisenc_change_state): + * ext/vorbis/vorbisenc.h: + Set granulepos and timestamp correctly for streams not + starting at 0, taking into account the initial delay. + +2005-01-31 Tim-Philipp Müller + + * gst/mpegstream/gstdvddemux.c: + Add audio/x-dts to audio pad template caps + +2005-01-30 David Schleef + + * ext/polyp/polypsink.c: (gst_polypsink_base_init), + (create_context), (gst_polypsink_link): Fix silly endianness + bug. Add some debugging. Remove float from caps; it doesn't + work. Attempt to get remote audio working. + +2005-01-29 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_video_caps): + Add 3IV2 fourcc. + +2005-01-29 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_add_stream), (swap_line), + (gst_avi_demux_invert), (gst_avi_demux_process_next_entry), + (gst_avi_demux_stream_data): + * gst/avi/gstavidemux.h: + Invert DIB images. Fixes #132341. + +2005-01-29 Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_chain): + D'oh, reference the palette data, not the palette structure. + Fixes color distortion in #132341. + +2005-01-29 Ronald S. Bultje + + * gst/videoscale/gstvideoscale.c: (gst_videoscale_link): + PAR can be non-fixed when not provided as argument (#162626). + +2005-01-29 David Moore + + Reviewed by: Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), + (gst_qtdemux_loop_header): + Re-apply patch from #142272 that allows non-seekable sources, + re-proposed by Daniel Drake . + +2005-01-29 Ronald S. Bultje + + * gst/rtp/gstrtpgsmenc.c: (gst_rtpgsmenc_init): + Use the src template for creating the src pad (#162330). + +2005-01-29 Ronald S. Bultje + + * configure.ac: + * ext/musepack/Makefile.am: + * ext/musepack/gstmusepackdec.c: (gst_musepackdec_class_init), + (gst_musepackdec_init), (gst_musepackdec_dispose), + (gst_musepackdec_src_query), (gst_musepackdec_src_convert), + (gst_musepack_stream_init), (gst_musepackdec_loop), + (gst_musepackdec_change_state): + * ext/musepack/gstmusepackdec.cpp: + * ext/musepack/gstmusepackdec.h: + * ext/musepack/gstmusepackreader.c: (gst_musepack_reader_peek), + (gst_musepack_reader_read), (gst_musepack_reader_seek), + (gst_musepack_reader_tell), (gst_musepack_reader_get_size), + (gst_musepack_reader_canseek), (gst_musepack_init_reader): + * ext/musepack/gstmusepackreader.cpp: + * ext/musepack/gstmusepackreader.h: + Update to 1.1 API (#165446). + +2005-01-28 Ronald S. Bultje + + * ext/Makefile.am: + Unbreak buildbot. + +2005-01-28 Andy Wingo + + * ext/dv/gstdvdec.c: Change the pixel aspect ratio of dvdec output + to reflect a different dubious internet source. Add a reference + and some commentary. + +2005-01-28 Ronald S. Bultje + + * gst/playback/gststreamselector.c: (gst_stream_selector_init), + (gst_stream_selector_get_caps), (gst_stream_selector_chain): + * gst/playback/gststreamselector.h: + Be more selective when we're redoing caps negotiation from + within the chain function on a stream change. + +2005-01-28 Ronald S. Bultje + + * configure.ac: + * ext/Makefile.am: + * ext/amrnb/Makefile.am: + * ext/amrnb/amrnb.c: (plugin_init): + * ext/amrnb/amrnbdec.c: (gst_amrnbdec_get_type), + (gst_amrnbdec_base_init), (gst_amrnbdec_class_init), + (gst_amrnbdec_init), (gst_amrnbdec_link), (gst_amrnbdec_chain), + (gst_amrnbdec_state_change): + * ext/amrnb/amrnbdec.h: + * ext/amrnb/amrnbparse.c: (gst_amrnbparse_get_type), + (gst_amrnbparse_base_init), (gst_amrnbparse_class_init), + (gst_amrnbparse_init), (gst_amrnbparse_formats), + (gst_amrnbparse_querytypes), (gst_amrnbparse_query), + (gst_amrnbparse_handle_event), (gst_amrnbparse_reserve), + (gst_amrnbparse_loop), (gst_amrnbparse_state_change): + * ext/amrnb/amrnbparse.h: + Add support for AMR-NB (mobile phone audio format; #155163, #163286). + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add AMR-NB/-WB raw formats. + * ext/alsa/gstalsa.c: (gst_alsa_link): + Keep valid time when changing format. + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (qtdemux_parse_trak): + Add some more format-specific options (#140141, #143555, #155163). + +2005-01-28 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_blockgroup): + Fix logic error in timing of subtitle stream synchronization. + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): + Add skip-chunk, which is found in kodak-camera streams. + +2005-01-27 Thomas Vander Stichele + + * po/LINGUAS: + * po/vi.po: + Adding Vietnamese translation (submitted by Clytie Siddall) + +2005-01-27 Ronald S. Bultje + + * gst/playback/gstdecodebin.c: (try_to_link_1): + Use realpad for signal. + +2005-01-27 Ronald S. Bultje + + * ext/mad/gstid3demuxbin.c: (gst_id3demux_bin_base_init): + Fix category so decodebin picks it up. + +2005-01-27 Ronald S. Bultje + + * ext/mad/Makefile.am: + * ext/mad/gstid3demuxbin.c: (gst_id3demux_bin_get_type), + (gst_id3demux_bin_base_init), (gst_id3demux_bin_class_init), + (gst_id3demux_bin_init), (gst_id3demux_bin_remove_pad), + (found_type), (gst_id3demux_bin_change_state): + * ext/mad/gstid3tag.c: (gst_id3_tag_add_src_pad), + (gst_id3_tag_init), (gst_id3_tag_handle_event), + (gst_id3_tag_src_link), (gst_id3_tag_chain), + (gst_id3_tag_change_state), (plugin_init): + * ext/mad/gstmad.h: + Add id3demuxbin (which is a simple bin consisting of id3demux + and typefind), take over rank from id3demux, remove typefind + code from id3demux. Makes all broken mp3s that I know of work, + and thereby fixes #152688. + +2005-01-27 Edward Hervey + + Reviewed by: Ronald S. Bultje + + * ext/mad/gstmad.c: (gst_mad_src_event): + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_event): + Allow seeks on audio pad, make mad forward those (#164826). + * gst/audioscale/gstaudioscale.c: (gst_audioscale_chain): + Set duration (#165335). + +2005-01-27 Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_init), + (gst_asf_demux_commit_taglist), (gst_asf_demux_process_comment), + (gst_asf_demux_process_ext_content_desc), + (gst_asf_demux_change_state), (gst_asf_demux_add_audio_stream), + (gst_asf_demux_add_video_stream), (gst_asf_demux_setup_pad): + * gst/asfdemux/gstasfdemux.h: + Improve metadata display, e.g. if the metadata comes before the + streams are loaded (which is perfectly valid). + +2005-01-27 Ronald S. Bultje + + * tools/gst-launch-ext-m.m: + Fix AVI/ASF pipelines (#165340). + +2005-01-26 Amaury Jacquot + * ext/cairo/gsttextoverlay.c: include string.h and strings.h to fix + build failure on amd64 + +2005-01-26 Tim-Philipp Müller + + * ext/mad/gstid3tag.c: (mad_id3_parse_latin1_string), + (mad_id3_parse_comment_frame), (gst_mad_id3_to_tag_list): + Check environment variables GST_ID3V2_TAG_ENCODING, + GST_ID3_TAG_ENCODING and GST_TAG_ENCODING for a colon-separated + list of character encodings to force interpretation of non-unicode + strings stored in an ID3v2 tag to a particular encoding. If none + is specified, try to use current locale's encoding, then fall back + to ISO-8859-1 (which will always succeed). (Resolves #149274) + * gst/tags/gstid3tag.c: (gst_tag_from_id3_tag), + (gst_tag_extract_id3v1_string), (gst_tag_list_new_from_id3v1): + Check environment variables GST_ID3V1_TAG_ENCODING, + GST_ID3_TAG_ENCODING and GST_TAG_ENCODING for a colon-separated + list of character encodings to use in case a string encountered + in an ID3v1 tag is not valid UTF-8 already. If no encoding is + specified, try to use the current locale's encoding, then fall + back to ISO-8859-1 (which will always succeed). + +2005-01-25 Benjamin Otte + + * ext/mad/gstmad.c: (gst_mad_check_caps_reset), (gst_mad_chain): + - on half framerate, compute the rate in advance so the comparisons + don't compare wrong values + - don't use mad_synth/frame_mute anymore, this mirrors mad_decoder + behaviour + - don't use mad_header_decode anymore, mad_frame_decode does that + automatically + - when getting rid of consumed bytes, reset the stream's skiplen + (fixes #163867) + +2005-01-26 Jan Schmidt + + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init) + Use 1/2 a second for default max_discont, as PES streams from DVB + seem to have larger spacings in the SCR. + Fix a typo. + +2005-01-25 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (group_commit): + Notify delayed stream-info availability. + +2005-01-26 Jan Schmidt + * ext/a52dec/gsta52dec.c: (gst_a52dec_push), + (gst_a52dec_handle_event), (gst_a52dec_chain): + Add some debug output. Check that a discont has a valid + time associated. + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event), + (gst_alsa_sink_loop): + Ignore TAG events. A little extra debug for broken timestamps. + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_init), (dvdnavsrc_loop), + (dvdnavsrc_change_state): + Ensure we send a discont to engage the link before we send any + other events. + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_init), + (dvdreadsrc_finalize), (_close), (_open), (_seek_title), + (_seek_chapter), (seek_sector), (dvdreadsrc_get), + (dvdreadsrc_uri_get_uri), (dvdreadsrc_uri_set_uri): + Handle URI of the form dvd://title[,chapter[,angle]]. Currently only + dvd://title works in totem because typefinding sends a seek that ends + up going back to chapter 1 regardless. + * ext/mpeg2dec/gstmpeg2dec.c: + * ext/mpeg2dec/gstmpeg2dec.h: + Output correct timestamps and handle disconts. + * ext/ogg/gstoggdemux.c: (get_relative): + Small guard against a null dereference. + * ext/pango/gsttextoverlay.c: (gst_textoverlay_finalize), + (gst_textoverlay_set_property): + Free memory when done. Don't call gst_event_filler_get_duration on + EOS events. Use GST_LOG and GST_WARNING instead of g_message and + g_warning. + * ext/smoothwave/gstsmoothwave.c: (gst_smoothwave_init), + (draw_line), (gst_smoothwave_dispose), (gst_sw_sinklink), + (gst_sw_srclink), (gst_smoothwave_chain): + Draw solid lines, prettier colours. + * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_init): + Add a default palette that'll work for some movies. + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_init), + (gst_dvd_demux_handle_dvd_event), (gst_dvd_demux_send_discont), + (gst_dvd_demux_send_subbuffer), (gst_dvd_demux_reset): + * gst/mpegstream/gstdvddemux.h: + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_discont), + (gst_mpeg_demux_parse_syshead), (gst_mpeg_demux_parse_pes): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_init), + (gst_mpeg_parse_handle_discont), (gst_mpeg_parse_parse_packhead): + * gst/mpegstream/gstmpegparse.h: + Use PTM/NAV events when for timestamp adjustment when connected to + dvdnavsrc. Don't use many discont events where one suffices. + * gst/playback/gstplaybasebin.c: (group_destroy), + (gen_preroll_element), (gst_play_base_bin_add_element): + * gst/playback/gstplaybasebin.h: + Make sure we remove subtitles from the same bin we put them in. + * gst/subparse/gstsubparse.c: (convert_encoding), (parse_subrip), + (gst_subparse_buffer_format_autodetect), + (gst_subparse_change_state): + Fix some memleaks and invalid accesses. + * gst/typefind/gsttypefindfunctions.c: (ogganx_type_find), + (oggskel_type_find), (cmml_type_find), (plugin_init): + Some typefind functions for Annodex v3.0 files + * gst/wavparse/gstwavparse.h: + GstRiffReadClass is the correct parent class. + +2005-01-25 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + Add extradata to huffyuv (fixes #165013). + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_vids_with_data): + Fix extradata extraction if it is in the chunk size. + +2005-01-25 Edward Hervey + + Reviewed by: Ronald S. Bultje + + * gst/effectv/gstquark.c: (gst_quarktv_class_init), + (gst_quarktv_change_state), (gst_quarktv_dispose): + Memory free'ing location fix (#164708). + +2005-01-25 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (group_commit), + (gen_preroll_element), (probe_triggered), (gen_source_element), + (setup_source), (gst_play_base_bin_change_state), + (gst_play_base_bin_add_element): + Don't block for streams. + * gst/playback/gststreaminfo.c: (stream_info_change_state), + (gst_stream_info_set_mute): + Use gst_pad_set_active_recursive. + +2005-01-25 Andy Wingo + + * sys/v4l/gstv4lelement.c (gst_v4l_iface_supported): Fix compile + for #ifndef HAVE_XVIDEO. + +2005-01-24 Jeffrey C. Ollie + + reviewed by: Maciej Katafiasz + + * ext/gsm/gstgsmdec.c: (gst_gsmdec_init), (gst_gsmdec_chain): + * ext/gsm/gstgsmdec.h: + * ext/gsm/gstgsmenc.c: (gst_gsmenc_init), (gst_gsmenc_chain): + * ext/gsm/gstgsmenc.h: + Fix rate to 8kHz as per spec, removes obscure errors when no rate + was given by property. Add proper buffer timestamps and offsets. + +2005-01-24 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data): + Audio can be <8000Hz. + +2005-01-22 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_change_state): + Explicit state change to workaround refcount bugs. + +2005-01-22 Ronald S. Bultje + + * gst/avi/gstavimux.c: (gst_avimux_write_tag), + (gst_avimux_riff_get_avi_header): + Fix... + +2005-01-19 Ronald S. Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_element_data), + (gst_riff_read_element_data): + * gst-libs/gst/riff/riff-read.h: + Add _peek version (req'ed in CDXA). + * gst/cdxaparse/gstcdxaparse.c: (gst_cdxaparse_init), + (gst_cdxaparse_loop): + Fix parsing in playbin. + * gst/playback/gstdecodebin.c: (close_pad_link): + Ignore current_ pads, they cause major annoyance. + +2005-01-19 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + Safety guard. + +2005-01-19 Ronald S. Bultje + + * gst/avi/gstavimux.c: (gst_avimux_write_tag): + Fix padding... + +2005-01-19 Ronald S. Bultje + + * gst/matroska/ebml-read.c: (gst_ebml_read_buffer): + Allow for 0-sized buffers. Fixes length query problems in + starwars.mkv from the testsuite. + +2005-01-19 Tim-Philipp Müller + + * gst/videobox/gstvideobox.c: (gst_video_box_copy_plane_i420), + (gst_video_box_i420), (gst_video_box_chain): + Fix row strides for I420 (fixes #163159) + +2005-01-19 Ronald S. Bultje + + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_parse_packhead): + MPEG2 has a useful rate property, so we can actually use that. + For MPEG-1, continue using the bytes/time properties. + +2005-01-19 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_template_caps): + Add intel-h263. + +2005-01-19 Ronald S. Bultje + + * ext/mad/gstmad.c: (gst_mad_check_caps_reset), (gst_mad_chain): + Fail if caps negotiation fails. Should fix #162184, and should + definately be in there regardless of it fixing the actual bug. + * gst/avi/gstavimux.c: (gst_avimux_get_type), (gst_avimux_init), + (gst_avimux_write_tag), (gst_avimux_riff_get_avi_header), + (gst_avimux_riff_get_avix_header), + (gst_avimux_riff_get_video_header), + (gst_avimux_riff_get_audio_header), (gst_avimux_write_index), + (gst_avimux_start_file), (gst_avimux_handle_event), + (gst_avimux_change_state): + * gst/avi/gstavimux.h: + Refactor structure writing to use GST_WRITE_UINT macros, add + metadata writing support. + +2005-01-18 Ronald S. Bultje + + * gst/playback/gststreaminfo.c: (gst_stream_info_dispose): + Elements may already be destroyed when this function is called. + +2005-01-18 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), + (gst_qtdemux_loop_header), (gst_qtdemux_handle_esds): + More memory leak fixes (#149162). + +2005-01-18 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), + (gst_qtdemux_add_stream): + Fix two memleaks. + +2005-01-18 Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_srcgetcaps): + Argh... + +2005-01-17 Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_srcgetcaps): + Fix off-by-one bug. Fixes warnings during playback of sincity.mp4 + when fixating to six channels in Totem. + +2005-01-17 Tim-Philipp Müller + + * ext/dvdread/dvdreadsrc.c: (get_next_cell_for): + Fix compile warnings on Solaris 10 buildbot + +2005-01-17 Tim-Philipp Müller + + * ext/dvdread/dvdreadsrc.c: (_read): + Don't read beyond the last cell in a chapter (fixes + invalid memory access) + +2005-01-17 Tim-Philipp Müller + + * ext/dvdread/stream_labels.c: + (dvdreadsrc_get_audio_stream_labels): + Use NULL for an empty GList instead of g_list_alloc(); fix + memory leaks; s/LCPM/LPCM/; use g_strdup_printf() instead + of GString (easier to bulk free later) + +2005-01-17 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps): + Fix BGRA32 caps (#164209). + +2005-01-17 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_caps_to_pixfmt): + alpha_mask can be RGBA/ABGR. Fixes #164265. + +2005-01-17 Francis Labonte + + Reviewed by: Ronald S. Bultje + + * ext/mpeg2dec/gstmpeg2dec.c: (crop_buffer), + (gst_mpeg2dec_alloc_buffer): + * ext/mpeg2dec/gstmpeg2dec.h: + Crop if decoding size is not the actual image size (#163676). + +2005-01-17 Steve Baker + + Reviewed by: Ronald S. Bultje + + * gst/typefind/gsttypefindfunctions.c: (aiff_type_find), + (svx_type_find), (sds_type_find), (ircam_type_find), (plugin_init): + Add libsndfile typefind functions (#163309). + +2005-01-17 Ronald S. Bultje + + * tools/gst-launch-ext-m.m: + Add .aac, fix .m1v/.m2v (#163891). + +2005-01-17 Ronald S. Bultje + + * ext/alsa/gstalsaclock.c: (gst_alsa_clock_wait): + Sanity check, don't wait endlessly since the clock might not + actually run at this point (which is a deadlock). Fixes #164069. + +2005-01-16 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (probe_triggered): + Of course, only pause if group is done... + +2005-01-16 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (probe_triggered): + Thread safety. + +2005-01-16 Jan Schmidt + + * ext/swfdec/gstswfdec.c: (gst_swfdec_change_state): + Don't return state change success when the parent + failed. + +2005-01-16 Ronald S. Bultje + + * gst/avi/gstavimux.c: (gst_avimux_handle_event): + Free events (fix memleak in #162905). + +2005-01-15 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_caps_to_pixfmt): + Fix for depth = 15. Fixes #161675. + +2005-01-14 Ronald S. Bultje + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_getcaps): + Set FPS correctly, even for webcams and the like. + * sys/v4l/v4l_calls.c: (gst_v4l_set_chan_norm): + Don error on setting while capturing. + +2005-01-14 Stephane LOEUILLET + + * ext/dv/gstdvdec.c: + * gst/subparse/gstsubparse.c: (parse_mdvdsub): + * gst/y4m/gsty4mencode.c: (gst_y4mencode_sinkconnect): + I'm a bad boy. using /1001. to force C to do float division + and not integer division (as it did in my last commit) + Thanks to David I. Lehn for pointing this mistake. + +2005-01-14 Ronald S. Bultje + + * sys/v4l/gstv4lelement.c: (gst_v4l_iface_supported): + Revert Johan´s 1.35->1.36 since it breaks compat. + +2005-01-14 Stephane LOEUILLET + + * ext/dv/gstdvdec.c: + * ext/libfame/gstlibfame.c: + * gst/subparse/gstsubparse.c: (parse_mdvdsub): + * gst/y4m/gsty4mencode.c: (gst_y4mencode_sinkconnect): + replace framerate aproximations by their real value + (24000/1001, 30000/1001, 60000/1001) + Finish fixing bug #164049 + +2005-01-13 Thomas Vander Stichele + + * ext/ogg/gstoggmux.c: + eos/bos debugging + * gst/tcp/gstmultifdsink.c: + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + improve reusability of elements after state changes and errors + make multifdsink throw away streamheaders when receiving new ones + +2005-01-13 Ronald S. Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_rates_probe): + Fix for if items are already in list... + +2005-01-12 Benjamin Otte + + * gst/adder/gstadder.c: (gst_adder_loop): + fix adder a bit so it doesn't screw up with events as much anymore + +2005-01-12 Jan Schmidt + + * ext/gdk_pixbuf/pixbufscale.c: (gst_pixbufscale_link), + (pixbufscale_scale), (gst_pixbufscale_chain): + * ext/gdk_pixbuf/pixbufscale.h: + Incorporate changes from Tim-Philipp Mueller + to ensure rowstrides are calculated the same way as + ffmpegcolorspace + Use gst_buffer_stamp instead of copying TIMESTAMP manually, so + that we pick up duration and offset also. + +2005-01-11 Ronald S. Bultje + + * gst/avi/gstavimux.c: (gst_avimux_class_init), + (gst_avimux_pad_unlink), (gst_avimux_release_pad): + Reusability fixes. + +2005-01-11 Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_update), + (gst_alsa_mixer_get_volume), (gst_alsa_mixer_set_volume), + (gst_alsa_mixer_set_mute), (gst_alsa_mixer_set_record), + (gst_alsa_mixer_set_option), (gst_alsa_mixer_get_option): + Update flags when requested. + +2005-01-11 Ronald S. Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_rates_probe): + Fix dmix. + +2005-01-11 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (gst_play_base_bin_dispose), + (probe_triggered), (new_decoded_pad), (gen_source_element), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (gst_play_bin_init), (group_switch), (remove_sinks), (setup_sinks), + (gst_play_bin_change_state): + Implement group-switch signal for use in apps to clear metadata + cache, clean up subtitle, add suburi property instead of # hack, + some error-out fixes. + +2005-01-11 Ronald S. Bultje + + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + Debug. + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_grab_frame): + If we got a state change in the _get handler, don't return success. + +2005-01-10 Stephane LOEUILLET + + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_my_output_message), + (gst_jpegdec_my_emit_message), (gst_jpegdec_init): + Make jpegdec quiet on MJPEG decoding + * gst/asfdemux/README: + Fix mimetypes for MJPEG and H263 + +2005-01-10 Ronald S. Bultje + + * ext/theora/theoradec.c: (theora_dec_chain): + Fix broken code generation by gcc by swapping arguments. + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query): + Fix \n in debug. + +2005-01-10 Stephane LOEUILLET + + * TODO: + delete this file, it is by far outdated + * ext/alsa/gstalsa.1: remove + * ext/alsa/gstalsa.c: (add_rates), (add_channels), (gst_alsa_caps), + (gst_alsa_check_sample_rates), (gst_alsa_rates_probe), + (gst_alsa_get_caps): + Add HW probing for supported sample rates. Fixes #161704 + +2005-01-10 Ronald S. Bultje + + * gst/audioscale/gstaudioscale.c: (gst_audioscale_chain): + Don't crash, biatch! :). + +2005-01-10 Ronald S. Bultje + + * ext/musepack/gstmusepackreader.cpp: + * gst/apetag/apedemux.c: (gst_ape_demux_stream_data): + Some work on tags - still doesn't work in playbin... + * gst/audioscale/gstaudioscale.c: (gst_audioscale_chain): + Handle events... + +2005-01-10 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_parse_tree): + Also shove tags on kid pads. + +2005-01-10 Ronald S. Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_use_event): + Don't bail on unknown events. + * gst/audioscale/gstaudioscale.c: (gst_audioscale_chain): + Don't crash on events before negotiation. + * gst/avi/gstavidemux.c: (gst_avi_demux_add_stream): + Send tags on pads, too. + * gst/playback/gststreamselector.c: + (gst_stream_selector_request_new_pad): + Forward events on first pad if no input was selected yet. + +2005-01-10 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (setup_substreams): + Don't disable streamtype if the stream doesn't exist, since + then playing a video after audio will disable both and nothing + will happen. Fixes the testsuite. + +2005-01-10 Ronald S. Bultje + + * sys/v4l/gstv4lxoverlay.c: (gst_v4l_xoverlay_interface_init), + (gst_v4l_xoverlay_set_xwindow_id): + * sys/v4l2/gstv4l2xoverlay.c: (gst_v4l2_xoverlay_interface_init), + (gst_v4l2_xoverlay_set_xwindow_id): + Add debug categories, fix overlay disabling. + +2005-01-10 Stephane LOEUILLET + + * ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_get_caps): + * ext/alsa/gstalsa.h: + Add HW probing for period_count/size and buffer_size MIX/MAX + Adjust default/user defined value if out of bounds + Should fix bug #162024 + +2005-01-09 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event): + Fix warning (#161191). + +2005-01-09 Stephane LOEUILLET + + * ext/dvdread/stream_labels.c: + (dvdreadsrc_get_audio_stream_labels): + Fix warning (init the good variable in switch default) + +2005-01-09 Koop Mast + + Reviewed by: Ronald S. Bultje + + * gst/tta/gstttaparse.c: (gst_tta_src_event): + Fix gcc-2.95 compile (#163485). + +2005-01-09 Ronald S. Bultje + + * configure.ac: + * ext/flac/gstflacenc.c: (gst_flacenc_init), + (gst_flacenc_seek_callback), (gst_flacenc_write_callback), + (gst_flacenc_tell_callback), (gst_flacenc_chain), + (gst_flacenc_change_state): + * ext/flac/gstflacenc.h: + Update for API change in flac-1.1.1. Update requirement in + configure.ac. Fixes #162974. + +2005-01-09 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (group_destroy): + Remove hack to get rid of assert and get rid of unlinked + signals properly. + +2005-01-09 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (setup_source): + Set source to NULL so that resources are free'ed. Fixes issues + with playback of CDDA and similar device-accessing things. + +2005-01-09 Ronald S. Bultje + + * testsuite/embed/Makefile.am: + test->noinst, fix make test in buildbot. + +2005-01-09 Stephane LOEUILLET + + * ext/dvdread/stream_labels.c: new file + * ext/dvdread/stream_labels.h: new file + * ext/dvdread/Makefile.am: + * ext/dvdread/dvdreadsrc.c: (_seek_title): + Extract audio stream label from DVD IFO files. + It only dump them on the console for now, still have to + make playbin aware of them. + +2005-01-09 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (setup_source): + Fix hanging subs. + +2005-01-09 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_init), + (gen_preroll_element), (remove_groups), (setup_subtitle), + (gen_source_element), (setup_source): + * gst/playback/gstplaybasebin.h: + Multiple .sub files is just a stupid idea... Fix some threading + mistakes. Interestingly, external .sub files cause playbin to + hang, I don't know why... Parsing fixes contributed by François + Kooman . + +2005-01-09 Ronald S. Bultje + + * testsuite/embed/Makefile.am: + Fix buildbot. + +2005-01-09 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * ext/libpng/gstpngenc.c: (gst_pngenc_class_init), + (gst_pngenc_init), (gst_pngenc_chain), (gst_pngenc_get_property), + (gst_pngenc_set_property): + * ext/libpng/gstpngenc.h: + Add compression level property (#163323). + +2005-01-09 Ronald S. Bultje + + * configure.ac: + * examples/capsfilter/capsfilter1.c: (main): + * examples/seeking/spider_seek.c: (make_spider_pipeline): + * ext/dvdread/Makefile.am: + * ext/dvdread/demo-play: + * ext/dvdread/demo-play.c: + * gconf/gstreamer.schemas.in: + * gst-libs/gst/gconf/gconf.c: + * sys/v4l/TODO: + * testsuite/Makefile.am: + * testsuite/embed/Makefile.am: + * testsuite/embed/embed.c: (cb_expose), (main): + Remove all references to xvideosink, fix examples (#140845). + * gst/playback/gstplaybasebin.c: (group_destroy): + Apparently, disposal does not unlink - so do explicitely. + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + Add debug. + +2005-01-09 Maciej Katafiasz + + * README: fix PKG_CONFIG_PATH instructions, what was there + previously was breaking default search path, not nice. + Fixes #163358 + +2005-01-09 Ronald S. Bultje + + * gst/audioscale/gstaudioscale.c: (gst_audioscale_init), + (gst_audioscale_chain): + %#^@^#@^@#^#@^#@^@#^@#^@#^@#^#@^#@^#@^@#^#@ fix seeking + when resampling - how the ^@$^!@^! is this possible?!? + +2005-01-09 Ronald S. Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_change_state): + Reset variables on READY. + * gst/matroska/matroska-mux.c: (gst_matroska_mux_request_new_pad), + (gst_matroska_mux_loop): + Require data before writing header. + +2005-01-09 Francis Labonte + + Reviewed by: Ronald S. Bultje + + * ext/mad/gstmad.c: (gst_mad_chain): + Don't call mad_stream_sync() directly after recovering sync. + Fixes #151661. + +2005-01-09 Martin Eikermann + + Reviewed by: Ronald S. Bultje + + * ext/snapshot/gstsnapshot.c: (gst_snapshot_class_init), + (snapshot_handler), (gst_snapshot_sinkconnect), + (gst_snapshot_chain): + Allocate resources when required, fix recursive signal emission + and fix caps. Fixes #161667. + +2005-01-09 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * ext/libpng/gstpngdec.c: (gst_pngdec_src_getcaps), + (gst_pngdec_chain): + Handle only 8-bppc (bits-per-pixel-component) images, better + error handling and correct strides. Fixes #163177. + * ext/libpng/gstpngenc.c: (gst_pngenc_sinklink), + (gst_pngenc_chain): + Better error handling. Fixes #163348. + +2005-01-09 Ronald S. Bultje + + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_get_type), + (dvdnavsrc_uri_get_type), (dvdnavsrc_uri_get_protocols), + (dvdnavsrc_uri_get_uri), (dvdnavsrc_uri_set_uri), + (dvdnavsrc_uri_handler_init): + Add DVD-nav URI (dvdnav://) for Totem testing purposes. + * gst/playback/gstplaybasebin.c: (gen_source_element): + Add MMS to streaming URIs. + +2005-01-09 Ronald S. Bultje + + * sys/ximage/ximagesink.c: (gst_ximagesink_navigation_send_event): + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_navigation_send_event): + Check for pad availability before sending event. + +2005-01-08 Ronald S. Bultje + + * gst-plugins.spec.in: + Add subparse. + +2005-01-08 Ronald S. Bultje + + * configure.ac: + Since we use functions from CVS, up requirement. + +2005-01-08 Ronald S. Bultje + + * gst/playback/Makefile.am: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (group_destroy), (group_commit), (group_is_muted), + (gen_preroll_element), (add_stream), (unknown_type), + (probe_triggered), (preroll_unlinked), (mute_stream), + (silence_stream), (new_decoded_pad), (setup_substreams), + (setup_source), (get_active_source), (mute_group_type), + (muted_group_change_state), (set_active_source), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property), + (play_base_eos), (gst_play_base_bin_change_state): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (add_sink), (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_info_class_init), + (gst_stream_info_dispose), (stream_info_mute_pad), + (stream_info_change_state), (gst_stream_info_set_mute): + * gst/playback/gststreamselector.c: (gst_stream_selector_get_type), + (gst_stream_selector_base_init), (gst_stream_selector_class_init), + (gst_stream_selector_init), (gst_stream_selector_dispose), + (gst_stream_selector_get_linked_pad), + (gst_stream_selector_get_caps), (gst_stream_selector_link), + (gst_stream_selector_get_linked_pads), + (gst_stream_selector_request_new_pad), (gst_stream_selector_chain): + * gst/playback/gststreamselector.h: + Adding stream selection support plus required properties for + applications to use this. Fully fixes #100931. + +2005-01-08 Benjamin Otte + + * gst/games/gstpuzzle.c: (nav_event_handler): + - handle nav events differently: forward every event no matter if it + was handled or not. + - translate events + You can now cheat by using navigationtest ! puzzle and moving the + mouse close to the edge of a tile. ;) + +2005-01-08 Ronald S. Bultje + + * configure.ac: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_new): + * ext/ogg/gstogmparse.c: (gst_ogm_text_parse_get_type), + (gst_ogm_text_parse_base_init), (gst_ogm_text_parse_init), + (gst_ogm_parse_get_sink_querytypes), (gst_ogm_parse_sink_convert), + (gst_ogm_parse_sink_query), (gst_ogm_parse_chain), + (gst_ogm_parse_plugin_init): + * ext/pango/gsttextoverlay.c: (gst_textoverlay_linkedpads), + (gst_textoverlay_link), (gst_textoverlay_getcaps), + (gst_textoverlay_event), (gst_textoverlay_video_chain), + (gst_textoverlay_loop), (gst_textoverlay_init), (plugin_init): + * ext/pango/gsttextoverlay.h: + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), + (gst_matroska_demux_handle_seek_event), + (gst_matroska_demux_sync_streams), + (gst_matroska_demux_parse_blockgroup), + (gst_matroska_demux_subtitle_caps), + (gst_matroska_demux_plugin_init): + * gst/matroska/matroska-ids.h: + * gst/playback/gstdecodebin.c: (close_pad_link): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_init), + (gen_preroll_element), (remove_groups), (add_stream), + (new_decoded_pad), (setup_subtitles), (gen_source_element), + (setup_source): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gen_text_element), (setup_sinks): + * gst/subparse/Makefile.am: + * gst/subparse/gstsubparse.c: (gst_subparse_get_type), + (gst_subparse_base_init), (gst_subparse_class_init), + (gst_subparse_init), (gst_subparse_formats), + (gst_subparse_eventmask), (gst_subparse_event), + (gst_subparse_handle_event), (convert_encoding), (get_next_line), + (parse_mdvdsub), (parse_mdvdsub_init), (parse_subrip), + (parse_subrip_deinit), (parse_subrip_init), (parse_mpsub), + (parse_mpsub_deinit), (parse_mpsub_init), + (gst_subparse_buffer_format_autodetect), + (gst_subparse_format_autodetect), (gst_subparse_loop), + (gst_subparse_change_state), (gst_subparse_type_find), + (plugin_init): + * gst/subparse/gstsubparse.h: + * gst/typefind/gsttypefindfunctions.c: (ogmtext_type_find), + (plugin_init): + Add subtitle support, .sub parser (supports SRT and MPsub), + OGM text support, Matroska UTF-8 text support, deadlock fixes + all over the place, subtitle awareness in decodebin/playbin + and some fixes to textoverlay to handle subtitles in a stream + correctly. Fixes #100931. + +2005-01-08 Ronald S. Bultje + + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query): + Check for pad availability before doing a query on it. + +2005-01-08 Stephane LOEUILLET + + * ext/dv/gstdvdec.c: + really fix bpp24/32 dvdec caps (classic rgba indeed) + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc): + don't send text tags if they are empty (bis repetita) + +2005-01-08 Stephane LOEUILLET + + * ext/dv/gstdvdec.c: + remove unneeded comment from dvdec + (related to DV 4CC codes in AVI files) + moved them in gstreamer/docs/random/mimetypes + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc): + don't send text tags if they are empty + fix mem leak on error path + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (img_get_alpha_info): + * gst/ffmpegcolorspace/imgconvert_template.h: + adds BGR32 and BGRA32 to ffmpegcolorspace + (still bad colors, fixing it on next commit) + helps with dvdec outputing BGR32 + +2005-01-08 Stephane LOEUILLET + + * ext/dv/gstdvdec.c: + Fix audio caps i just broke (missing ',') + * gst/matroska/matroska-mux.c: (gst_matroska_mux_get_type), + (gst_matroska_mux_reset): + Fix typo + add FIXME about old "x-gst-metadata" crap + +2005-01-07 Stephane LOEUILLET + + * ext/dv/demo-play.c: (main): + xvideosink -> xvimagesink + * ext/dv/gstdvdec.c: + change rgb 32/32 caps to 24/32 (no alpha) + change nb of channels to be a list (2 or 4, not 2) + change sample rate to be a list (32, 44.1, 48 kHz) not a range + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc): + Add 'date/year' to extracted metadata list + +2005-01-07 Ronald S. Bultje + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_fixate): + The return value of fixate_to does not imply that the requested + value was set, so don't assume. + +2005-01-07 Gergely Nagy + + Reviewed by: Ronald S. Bultje + + * ext/libpng/gstpngdec.c: + * ext/libpng/gstpngenc.c: (gst_pngenc_base_init), + (gst_pngenc_sinklink), (gst_pngenc_init), (gst_pngenc_chain): + * ext/libpng/gstpngenc.h: + Alpha support (encoder; #163161), mime fixage. + +2005-01-07 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * ext/faac/gstfaac.c: (gst_faac_outputformat_get_type), + (gst_faac_class_init), (gst_faac_init), (gst_faac_srcconnect), + (gst_faac_set_property), (gst_faac_get_property): + * ext/faac/gstfaac.h: + Allow for ADTS output (#153434). + +2005-01-07 Ronald S. Bultje + + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_getcaps): + Fix against template (#150576). + +2005-01-06 Benjamin Otte + + * gst/games/gstpuzzle.c: (draw_puzzle): + don't draw a puzzle if either width or height of tiles would be 0. + +2005-01-06 Benjamin Otte + + * gst/games/gstpuzzle.c: (gst_puzzle_get_type), + (gst_puzzle_class_init), (gst_puzzle_finalize): + no memleaks, please + (gst_puzzle_create), (gst_puzzle_init), + (gst_puzzle_set_property), (gst_puzzle_setup): + change initialization code around so we don't reshuffle on resize + (draw_puzzle): + fix another stupid typo + +2005-01-06 Benjamin Otte + + * gst/games/gstvideoimage.c: (copy_hline_YUY2): + fix stupid typo that borked copying on YUY2 + +2005-01-06 Benjamin Otte + + * gst/games/gstpuzzle.c: (draw_puzzle): + fix edges when image sizes aren't multiples of tile sizes + +2005-01-06 Benjamin Otte + + * gst/games/gstpuzzle.c: (gst_puzzle_base_init): + make RGB endianness work correctly + (gst_puzzle_show), (gst_puzzle_swap), (gst_puzzle_move): + refactor and fix race with initial shuffling + (nav_event_handler): + allow using the mouse to puzzle + (draw_puzzle): + insist on tiles having width and height as multiples of 4 to get + clean YUV image handling + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_handle_xevents), (gst_xvimagesink_buffer_alloc): + s/DEBUG/LOG/ for common messages + (gst_xvimagesink_navigation_send_event): + fix mouse event translation to not include screen PAR + * sys/ximage/ximagesink.c: (gst_ximagesink_navigation_send_event): + fix mouse event translation to actually work + +2005-01-06 Stephane LOEUILLET + + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc): + Extract TrackNumber metadata + clean up code + * gst/games/gstvideoimage.c: (gst_video_image_draw_rectangle): + Hope this is the good fix (var used unitialised) + +2005-01-06 Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_chain): + Only increment timestamp if it's valid. Fixes raw AAC streams. + +2005-01-06 Benjamin Otte + + * configure.ac: + * gst/games/Makefile.am: + * gst/games/gstpuzzle.c: + add a puzzle game with... + * gst/games/gstvideoimage.c: + * gst/games/gstvideoimage.h: + ... full colorspace support (that includes YUV9 and RGB16)) stolen + from videotestsrc and made into something that would be a nice + library for a lot of other plugins. + +2005-01-06 Stephane LOEUILLET + + * configure.ac: + don't compile faad plugin if a RC of 2.0 is found + Fixes #155346 (and FC1 buildbot) + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc): + try to make Solaris compiler happier + +2005-01-06 Paul Jack + + Reviewed by: Ronald S. Bultje + + * ext/snapshot/gstsnapshot.c: (gst_snapshot_class_init): + Fix segfault (#161667). + +2005-01-05 Ronald S. Bultje + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_getcaps): + Fix framerate reporting. + +2005-01-05 Stephane LOEUILLET + + * gst-libs/gst/riff/riff-ids.h: + * gst/wavenc/riff.h: + Add AMR (VBR and CBR) ids to riff.h audio codec list + * gst/asfdemux/gstasfdemux.c: + (gst_asf_demux_process_ext_content_desc), + (gst_asf_demux_process_object): + Retrieve more tags from ASF files (Genre, AlbumTitle, Artist) + +2005-01-05 Martin Eikermann + + Reviewed by: Ronald S. Bultje + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_class_init), + (gst_dvd_demux_handle_discont): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_class_init), + (gst_mpeg_demux_handle_discont): + Recreate pads on new-media (#160730). + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_new_pad): + Send discont even if manager changes timestamps (#161929). + +2005-01-05 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst-libs/gst/resample/resample.c: (gst_resample_sinc_ft_s16): + Fix invalid memory access (#159211). + +2005-01-05 Ronald S. Bultje + + * examples/gstplay/player.c: (main): + Don't iterate. + * examples/seeking/seek.c: (fixate), (make_playerbin_pipeline): + Add visualizations. + * ext/a52dec/gsta52dec.c: (gst_a52dec_push), + (gst_a52dec_handle_frame): + Set duration. + * ext/dvdnav/gst-dvd: + Add audioconvert. Fixes #161325. + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_get): + Explicitely case to gint64. Possible valgrind error. + * gst-libs/gst/play/play.c: (caps_set), (setup_size), + (gst_play_tick_callback), (gst_play_change_state), + (gst_play_dispose), (gst_play_init), (gst_play_class_init), + (gst_play_set_location), (gst_play_get_location), + (gst_play_seek_to_time), (gst_play_set_data_src), + (gst_play_set_video_sink), (gst_play_set_audio_sink), + (gst_play_set_visualization), (gst_play_connect_visualization), + (gst_play_get_framerate), (gst_play_get_all_by_interface), + (gst_play_new): + Use playbin. Fixes #139749 and #147744. + * gst/apetag/apedemux.c: (gst_ape_demux_parse_tags): + Add genre tag. + * gst/audioscale/gstaudioscale.c: (gst_audioscale_method_get_type), + (audioscale_get_type), (gst_audioscale_base_init), + (gst_audioscale_class_init), (gst_audioscale_expand_caps), + (gst_audioscale_getcaps), (gst_audioscale_fixate), + (gst_audioscale_link), (gst_audioscale_get_buffer), + (gst_audioscale_decrease_rate), (gst_audioscale_increase_rate), + (gst_audioscale_init), (gst_audioscale_dispose), + (gst_audioscale_chain), (gst_audioscale_set_property), + (gst_audioscale_get_property), (plugin_init): + Indent properly. + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_process_private): + Fix LPCM. + * gst/qtdemux/qtdemux.c: (qtdemux_parse_udta), + (qtdemux_tag_add_str), (qtdemux_tag_add_num), + (qtdemux_tag_add_gnre), (qtdemux_video_caps): + Add more metadata (fixes #162656). + +2005-01-05 Thomas Vander Stichele + + * configure.ac: + back to cvs + +=== release 0.8.7 === + +2005-01-05 Thomas Vander Stichele + + * NEWS: + * RELEASE: + * configure.ac: + releasing 0.8.7, "Hyperspace" + +2005-01-05 Thomas Vander Stichele + + patch by: Tim-Philipp Müller + + * gst/playback/gstplaybasebin.c: + Fix for #162924 - free caps after use, not before + +2005-01-04 Thomas Vander Stichele + + patch by: Ronald Bultje + + * gst/playback/gstplaybasebin.c: + * gst/wavparse/gstwavparse.c: + Fix for #154773 - fixes playback of small .wav files + +2005-01-03 Thomas Vander Stichele + + patch by: Ronald Bultje + + * gst/audioscale/gstaudioscale.c: + Fix for #162819 - make audioscale reusable + Fixes playback of more than one file with playbin/totem + +2004-12-29 Thomas Vander Stichele + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + * gst/ffmpegcolorspace/imgconvert.c: + clean up the mess that made me cry and avoid needless duplication + +2004-12-29 Thomas Vander Stichele + + * gst/ffmpegcolorspace/imgconvert.c: + give some indication of why we're segfaulting + +2004-12-29 Ronald S. Bultje + + * configure.ac: + Fix indentation, fix v4l2 plugin detection. + * ext/Makefile.am: + Fix libmms location (Maciej, use diff -u!). + * ext/alsa/gstalsa.c: (gst_alsa_init): + Initialize caps cache to NULL. + * gst/playback/gstplaybin.c: (gst_play_bin_change_state): + Only change state on audiosink if it exists. + +2004-12-28 Maciej Katafiasz + + * gst/matroska/matroska-demux.c: + * gst/matroska/matroska-ids.h: + * gst/matroska/matroska-demux.h: + Fix Vorbis streams failing to decode in some files, where cluster_time + isn't 0, because then it doesn't send codec_priv before actual data. + Remove time-based test and replace it with marker set on beginning of + new stream + +2004-12-28 David Schleef + + Merge patch from Ronald fixing problems with streaming + text. + * ext/cairo/gstcairo.c: (plugin_init): + * ext/cairo/gsttextoverlay.c: (gst_textoverlay_render_text), + (gst_text_overlay_blit_1), (gst_text_overlay_blit_sub2x2), + (gst_textoverlay_video_chain), (gst_textoverlay_loop), + (gst_textoverlay_font_init), (gst_textoverlay_init), + (gst_textoverlay_set_property): + * ext/cairo/gsttextoverlay.h: + +2004-12-27 David Schleef + + * ext/cairo/gsttextoverlay.c: (gst_textoverlay_render_text), + (gst_text_overlay_blit_1), (gst_text_overlay_blit_sub2x2), + (gst_textoverlay_video_chain), (gst_textoverlay_loop), + (gst_textoverlay_font_init), (gst_textoverlay_init), + (gst_textoverlay_set_property): Improvements to actually + render text as white on black outline on video, including + font selection and horizontal/vertical alignment. (Ronald's + christmas present) + * ext/cairo/gsttextoverlay.h: + +2004-12-26 Stephane Loeuillet + + * ext/ogg/gstogg.c: + * ext/ogg/gstogmparse.c: + fix ogm[audio/video]parse plugin registration + (riff won't load if bytestream is already loaded) + +2004-12-24 Thomas Vander Stichele + + * gst/audioconvert/gstchannelmix.c: + fix for GLIB < 2.4 + +2004-12-24 Thomas Vander Stichele + + * Makefile.am: + * configure.ac: + disable docs again until it actually passes make distcheck. + +2004-12-24 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_type_get), (qtdemux_audio_caps): + * gst/typefind/gsttypefindfunctions.c: (q3gp_type_find), + (plugin_init): + Add 3GP (variables name Q3GP because they can't start with a + number). Add samr audio fourcc (used in .3gp files), decoder + is work in progress. Also do a GST_WARNING instead of ERROR + in case of unknown nodes, to decrease output. + +2004-12-24 Thomas Vander Stichele + + * Makefile.am: + really fix dist + +2004-12-23 Thomas Vander Stichele + + * configure.ac: + * ext/speex/gstspeexdec.h: + * ext/speex/gstspeexenc.h: + Fixes #158382. Make speex plugin compatible with both 1.0 and 1.1. + Fix detection code in configure.ac + +2004-12-23 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_blockgroup): + Save position, so that queries give proper return values. Don't + know how this could ever have worked before... + +2004-12-23 Thomas Vander Stichele + + * configure.ac: + Put additional LAME check inside the conditional. Fixes #152339 + +2004-12-23 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index), + (gst_avi_demux_stream_scan): + Add some more debug. Fix logic error when setting movi offset + while reading index. + +2004-12-23 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index), + (gst_avi_demux_stream_scan), (gst_avi_demux_handle_seek), + (gst_avi_demux_process_next_entry): + Add some debugging. Better detection of broken indexes and the + accompanying index recovery. No infinite loops on state changes + when we're still in our loopfunction. + +2004-12-22 Ronald S. Bultje + + * configure.ac: + Fix up. + +2004-12-22 Archana Shah + + Reviewed by: Ronald S. Bultje + + * sys/sunaudio/gstsunmixer.c: (gst_sunaudiomixer_set_volume): + Normalizing the value before setting + (gst_sunaudiomixer_get_volume): + Normalizing the value after getting. Fixes bug# 161980 + +2004-12-22 Christian Fredrik Kalager Schaller + + * Makefile.am: Make sure docs gets disted + * docs/Makefile.am: Make sure all needed files get disted + * gst-plugins.spec.in: latest updates + +2004-12-22 Wim Taymans + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_add_element): + Revert patch 1.38 as clock distribution over schedulers does + not work correcly in the core yet. + +2004-12-21 Stephane Loeuillet + + * sys/oss/README: remove this file, which predates my birth + (and which content is by far outdated) + +2004-12-20 Stefan Kost + + * Makefile.am: + * configure.ac: + * docs/Makefile.am: + * docs/libs/Makefile.am: + * docs/libs/gst-plugins-libs-docs.sgml: + * docs/libs/gst-plugins-libs-sections.txt: + * docs/libs/tmpl/gstgconf.sgml: + * docs/upload.mak: + * docs/version.entities.in: + Added boilerplate gtk-doc files for plugin-libs documentation. + +2004-12-19 Stephane Loeuillet + + * gst/auparse/gstauparse.c: fix int and float audio caps + +2004-12-19 Ronald S. Bultje + + * sys/v4l/gstv4lelement.c: (gst_v4l_iface_supported): + * sys/v4l2/gstv4l2element.c: (gst_v4l2_iface_supported): + g_assert() can be a macro, don't use #ifdef inside it. + +2004-12-19 Edward Hervey + + Reviewed by: Ronald S. Bultje + + * gst/videorate/gstvideorate.c: (gst_videorate_blank_data), + (gst_videorate_init), (gst_videorate_chain), + (gst_videorate_change_state): + Event handling (fixes #159986). + +2004-12-19 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + Add BLZ0 (Blizzard's version of DivX) fourcc. + +2004-12-18 David Schleef + + * gst/tta/gstttadec.c: (gst_tta_dec_link): And yet another + portability fix. + +2004-12-18 David Schleef + + * gst/tta/ttadec.h: Disable some header code that isn't used + and clearly isn't portable. + +2004-12-18 David Schleef + + * gst/ffmpegcolorspace/imgconvert.c: (get_pix_fmt_info), + (avcodec_get_chroma_sub_sample), (avcodec_get_pix_fmt_name), + (avcodec_get_pix_fmt), (avpicture_layout), + (avcodec_get_pix_fmt_loss), (avg_bits_per_pixel), (img_copy), + (get_convert_table_entry), (img_convert), (img_get_alpha_info): + Fix code to not use GCC extensions (and c99 extensions that + Forte does not like.) + +2004-12-19 Tim-Philipp Müller + + Reviewed by: Ronald S. Bultje + + * gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_link), + (gst_deinterlace_chain): + Rowstride fixes. Fixes #161039. + * gst/videocrop/gstvideocrop.c: (gst_video_crop_init), + (gst_video_crop_get_property), (gst_video_crop_add_to_struct_val), + (gst_video_crop_getcaps), (gst_video_crop_link), + (gst_video_crop_i420), (gst_video_crop_chain), + (gst_video_crop_change_state): + Rework of negotiation. Actually works now. Fixes #158650. + +2004-12-18 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_ebmlnum_sint): + That was very stupid. + +2004-12-18 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_blockgroup): + Fix possible crasher. + +2004-12-18 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_ebmlnum_uint), + (gst_matroska_ebmlnum_sint), (gst_matroska_demux_parse_blockgroup): + Lace sizes can be zero. + +2004-12-18 Ronald S. Bultje + + * ext/musepack/gstmusepackdec.cpp: + Fetch error return values. Fixes #161624. + * gst/apetag/apedemux.c: (gst_ape_demux_stream_data): + Really EOS. + +2004-12-18 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index): + Work for truncated (unfinished download etc.) files. Fixes #160514. + +2004-12-18 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + Fix for integer overflow. Makes #156001 not crash. Probably masks + the real bug. + +2004-12-17 Ronald S. Bultje + + * gst/ac3parse/gstac3parse.c: (plugin_init): + Parsers never have ranks. Fixes #159651. + +2004-12-17 Benjamin Otte + + * gst/playback/gstdecodebin.c: (compare_ranks): + make sure the facotries are ordered the same every time even if they + have the same rank by using the name + * gst/playback/gstdecodebin.c: (find_compatibles): + make sure we don't add factories to the list twice + +2004-12-16 David Schleef + + * configure.ac: look for musepack headers as musepack/*.h + (fixes #159847) + * ext/musepack/gstmusepackdec.h: use + * ext/musepack/gstmusepackreader.h: same + +2004-12-17 Ronald S. Bultje + + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_auds_with_data): + Read extradata correctly (fixes #155879). + +2004-12-16 David Schleef + + * gst/audioscale/gstaudioscale.c: allow passthru of >2 channel + audio. does _not_ attempt or allow conversion unless channels + is 1 or 2. + +2004-12-16 Christian Fredrik Kalager Schaller + + * tools/gst-launch-ext-m.m: fix mpeg and vob pipelines + +2004-12-16 David Schleef + + * gst/audioscale/gstaudioscale.c: the resample library only + handles 1 or 2 channels. Change caps to compensate. + +2004-12-16 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: (aac_rate_idx), (aac_profile_idx), + (gst_matroska_demux_audio_caps): + Some MPEG-AAC hacks, because else it doesn't work... + +2004-12-16 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_template_caps): + Add h264. + +2004-12-16 Ronald S. Bultje + + * gst-libs/gst/audio/Makefile.am: + Try to fix buildbot. + +2004-12-16 Thomas Vander Stichele + + * gst/tcp/gstmultifdsink.c: + Clean up and uniformize debugging. + +2004-12-16 Edward Hervey + + Reviewed by: Ronald S. Bultje + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_class_init), + (gst_dvd_demux_reset), (gst_dvd_demux_change_state): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_reset), + (gst_mpeg_demux_change_state): + Reset on ready. Fixes 160276. + +2004-12-16 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_pad_link): + Fix memleak (#154815). + +2004-12-16 James Bowes + + Reviewed by: Ronald S. Bultje + + * ext/musicbrainz/gsttrm.c: (gst_musicbrainz_class_init), + (gst_musicbrainz_init), (gst_musicbrainz_chain), + (gst_musicbrainz_set_property), (gst_musicbrainz_get_property): + * ext/musicbrainz/gsttrm.h: + Add support for using a proxy server when getting a trm id from + the MusicBrainz database (#149613). + +2004-12-16 Christophe Fergeau + + Reviewed by: Ronald S. Bultje + + * gst/playback/gstdecodebin.c: (new_pad), (close_link): + * gst/playback/gstplaybasebin.c: (new_decoded_pad): + Fix memleaks (#157233). + +2004-12-16 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst-libs/gst/resample/resample.c: (gst_resample_close): + * gst-libs/gst/resample/resample.h: + * gst/audioscale/gstaudioscale.c: + Fix memleak (#159215). + +2004-12-16 Toni Willberg + + Reviewed by: Ronald S. Bultje + + * sys/oss/gstosselement.c: (gst_osselement_probe_caps): + * sys/oss/oss_probe.c: (main): + Check for mono/stereo support (similar to samplerate probing), + fixes #159433. Also add missing copyright header to oss_probe.c. + +2004-12-15 David Schleef + + * configure.ac: add audioresample and cairo plugins. Remove + HAVE_MMX stuff, because it's not used. + * ext/Makefile.am: same + * ext/audioresample/Makefile.am: You are not ready for an + audio resampling element based on audioresample. + * ext/audioresample/gstaudioresample.c: + * ext/audioresample/gstaudioresample.h: + * ext/cairo/Makefile.am: You are not ready for overlay elements + based on cairo. Don't look too closely, these elements kinda + suck right now. + * ext/cairo/gstcairo.c: new + * ext/cairo/gsttextoverlay.c: new + * ext/cairo/gsttextoverlay.h: new + * ext/cairo/gsttimeoverlay.c: new + * ext/cairo/gsttimeoverlay.h: new + * gst-libs/gst/media-info/media-info-priv.h: fix compile + problem with compilers that don't support variadic macros. + +2004-12-15 Balamurali Viswanathan + + Reviewed by: David Schleef + + * sys/sunaudio/gstsunaudio.c: (plugin_init): Apply patch from + Bala, registering sunaudiosrc (oops!), and cleaning up code a + bit. Also ran indent-gst. + * sys/sunaudio/gstsunaudiosrc.c: (gst_sunaudiosrc_init), + (gst_sunaudiosrc_change_state), (gst_sunaudiosrc_get), + (gst_sunaudiosrc_setparams): + +2004-12-14 David Schleef + + * gst/festival/gstfestival.c: (gst_festival_chain): Set the + output rate to 16000. Should fix #160235. + +2004-12-14 Zaheer Abbas Merali + + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find): + Add typefinding for mpeg2 pes streams + +2004-12-13 David Schleef + + * configure.ac: Applied patch from bug #143659, making default + sources and sinks OS-dependent (for Solaris), and added code + for OS/X. + * gconf/gstreamer.schemas.in: use OS-dependent sinks in gconf. + +2004-12-13 Stephane Loeuillet + + * gst-libs/gst/riff/riff-media.c: + forgot to add h2.64 to avidemux template caps + +2004-12-13 Stephane Loeuillet + + * gst/wavenc/riff.h: + * gst-libs/gst/riff/riff-media.c: + * gst-libs/gst/riff/riff-ids.h: + * gst/avi/gstavimux.c + add 4CC code for VideoSoft h264 in AVI (VSSH) + fixes bug #160655 + remove s323 from riff, it's quicktime specific :( + +2004-12-13 Stephane Loeuillet + + * gst/asfdemux/README + * gst/wavenc/riff.h + * gst-libs/gst/riff/riff-ids.h + * gst-libs/gst/riff/riff-media.c + * gst/qtdemux/qtdemux.c: + add new 4CC codes for h263 related codecs + fixes partially bug #155163 + +2004-12-12 Christian Fredrik Kalager Schaller + + * configure.ac: Update polyaudio requirement to 0.7 + * ext/polyp/polypsink.c: (create_stream): add patch from iain (158258) + +2004-12-11 Zaheer Abbas Merali + + * gst/interleave/deinterleave.c: + fix my name's spelling! :) + +2004-12-11 Stephane Loeuillet + + * AUTHORS ChangeLog + * gst/auparse/gstauparse.c + * gst/interleave/deinterleave.c + * gst/law/: + alaw-decode.c alaw-encode.c + mulaw-decode.c mulaw-encode.c + * gst/oneton/gstoneton.c + * sys/osxaudio/: + gstosxaudioelement.c gstosxaudiosink.c gstosxaudiosrc.c + * sys/osxvideo/: + cocoawindow.h cocoawindow.m + osxvideosink.h osxvideosink.m + + put the same mail address for Zaheer Abbas Merali everywhere + +2004-12-10 Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_loop): + Align by packetsize, and assert that we a packet available before + playing. The first makes webstreams work (they often include + trailing padding data in a packet), the second allows pausing a + ASF stream in totem without getting demux errors afterwards. + +2004-12-09 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (get_relative): + Check for non-NULL before accessing member (end-of-chain). + +2004-12-09 Ronald S. Bultje + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_class_init), + (cdparanoia_set_property), (cdparanoia_get_property): + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_class_init), + (dvdnavsrc_set_property), (dvdnavsrc_get_property): + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init), + (dvdreadsrc_init), (dvdreadsrc_set_property), + (dvdreadsrc_get_property): + * sys/vcd/vcdsrc.c: (gst_vcdsrc_class_init), + (gst_vcdsrc_set_property), (gst_vcdsrc_get_property): + Synchronize property names where not yet the case. Devices are + now device=X, other versions are deprecated (but still exist). + Also use g_free() unconditionally. + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (setup_source), (gst_play_base_bin_get_property): + Expose source. + +2004-12-09 Thomas Vander Stichele + + * configure.ac: move GCONF macro outside conditional for the am + conditional. Fixes #160439 + +2004-12-08 David Schleef + + * tools/gst-visualise-m.m: Switch to elements that currently + exist. + +2004-12-08 Ronald S. Bultje + + * ext/ogg/gstogmparse.c: (gst_ogm_parse_chain): + We love wrong commas. + +2004-12-08 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_handle_src_query): + Don't set DEFAULT, unsupported - makes length display incorrectly + in some cases. + +2004-12-07 Christian Fredrik Kalager Schaller + + * gst/monoscope/README: remove blurb about files being GPL + * gst/monoscope/gstmonoscope.c: Change license field to LGPL + * gst/monoscope/monoscope.c: Change license to BSD with explanation + monoscope is now effectively LGPL licensed + +2004-12-07 Christian Fredrik Kalager Schaller + + * gst/monoscope/README: Update information to be more correct + * gst/monoscope/convolve.c: Relicense to LGPL + * gst/monoscope/convolve.h: Relicense to LGPL + +2004-12-06 Arwed v. Merkatz + + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain): + set BUFFER_DURATION to correct values (mpeg1 audio frame length is fixed) + * gst/matroska/matroska-mux.c: (gst_matroska_mux_audio_pad_link): + set default_duration for mpeg1 audio + +2004-12-06 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_get_caps), (gst_alsa_close_audio): + * ext/alsa/gstalsa.h: + refactor big chunks of the core caps negotiation code to make it + a lot faster, because people claim it's really slow + (actually, just cache the getcaps when the device is opened) + +2004-12-06 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_init), + (gst_a52dec_handle_event), (gst_a52dec_update_streaminfo), + (gst_a52dec_handle_frame), (gst_a52dec_chain), + (gst_a52dec_change_state), (plugin_init): + * ext/a52dec/gsta52dec.h: + Do something useful with timestamps. Make chain-based (since + there's really no reason to be loopbased). + * gst/avi/gstavidemux.c: (gst_avi_demux_process_next_entry): + Update current_byte/frame correctly. + +2004-12-04 Ronald S. Bultje + + * gst/apetag/apedemux.c: (gst_ape_demux_parse_tags), + (gst_ape_demux_stream_init): + Forward tags, too. + +2004-12-04 Ronald S. Bultje + + * gst/apetag/apedemux.c: (gst_ape_demux_stream_init): + Let's make sure we're done typefinding when detecting tags. + +2004-12-03 Ronald S. Bultje + + * gst/matroska/ebml-read.c: (gst_ebml_read_class_init), + (gst_ebml_read_init), (gst_ebml_read_use_event), + (gst_ebml_read_element_id), (gst_ebml_peek_id), + (gst_ebml_read_seek), (gst_ebml_read_skip), + (gst_ebml_read_reserve), (gst_ebml_read_buffer), + (gst_ebml_read_master): + * gst/matroska/ebml-read.h: + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_contents), + (gst_matroska_demux_loop_stream), (gst_matroska_demux_audio_caps): + Disgustingly evil hack for working around INTERRUPT events and + their extremely annoying habit of being a pain in the ass. We + simply peek a cluster before reading any of it. + +2004-12-03 Ronald S. Bultje + + * ext/musepack/gstmusepackdec.cpp: + There's also floating point libmusepacks. + +2004-12-03 Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_chanpos_from_gst), + (gst_faad_chanpos_to_gst), (gst_faad_chain): + Set DURATION even if source buffer didn't. Also use increasing + timestamps. + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data): + Block_align can have larger values than 8192. + +2004-12-02 Ronald S. Bultje + + * gst/law/alaw-decode.c: (alawdec_getcaps), (alawdec_link): + * gst/law/alaw-encode.c: (alawenc_getcaps), (alawenc_link): + * gst/law/mulaw-decode.c: (mulawdec_getcaps), (mulawdec_link): + * gst/law/mulaw-encode.c: (mulawenc_getcaps), (mulawenc_link): + Fix caps. + +2004-12-01 Ronald S. Bultje + + * sys/v4l/v4l_calls.c: (gst_v4l_get_chan_names): + Fix logic bug. + +2004-12-01 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_type_find): + Yay, another one. + +2004-12-01 Ronald S. Bultje + + * ext/esd/esdsink.c: (gst_esdsink_chain): + Make error actually say something useful (fixes #156798). + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_template_caps): + Add Intel Video 5.0 fourcc (IV50). + +2004-12-01 Christophe Fergeau + + * ext/mad/gstmad.c: (mpg123_parse_xing_header): fix xing header + detection on mono and stereo mp3 files. + +2004-12-01 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_change_state): + Don't crash on EMPTY caps (e.g. when the demuxer didn't recognize + the contained stream). + +2004-12-01 Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_srcconnect), (gst_faad_chain): + Oops, remove debug. + +2004-12-01 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst/law/alaw-decode.c: (alawdec_getcaps): + * gst/law/mulaw-decode.c: (mulawdec_getcaps): + Prevent warnings when negotiating caps (fixes #159338). + +2004-12-01 Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_chain): + Remove old leftover that shouldn't be there... + +2004-12-01 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_use_event): + Don't forward DISCONT events (fixes #159684). + +2004-12-01 Ronald S. Bultje + + * gst/playback/gstplaybin.c: (remove_sinks), (setup_sinks): + Unlink manually since sometimes bin disposal (and therefore + pad unlinking) is delayed, which will cause a new media file + to not be able to start playing instantly. + +2004-11-29 Ronald S. Bultje + + * gst/playback/gststreaminfo.c: (stream_info_mute_pad): + On mute of an unlinked stream, check for pad availability so + we don't crash on unlinked pad. + +2004-11-29 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index), + (gst_avi_demux_massage_index): + Fix quite humiliating bug in omitting 0-sized index chunks but + forgetting to count them for timestamps. + +2004-11-29 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_loop): + Actually leave the loop if we failed to sync. Don't crash. + +2004-11-28 Ronald S. Bultje + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_get_audio_stream), + (gst_dvd_demux_process_private): + * gst/mpegstream/gstdvddemux.h: + Fix crash (#159759). Doesn't work, though. :-(. + +2004-11-28 Benjamin Otte + + * gst/audioconvert/gstchannelmix.c: (gst_audio_convert_mix): + more overwriting protection due to modifying channels one by one + instead of all at once + +2004-11-28 Ronald S. Bultje + + * gst/audioconvert/gstchannelmix.c: + (gst_audio_convert_fill_normalize): + Normalize using absolute values. + +2004-11-28 Julien MOUTTE + + * configure.ac: + * ext/Makefile.am: + * ext/directfb/Makefile.am: + * ext/directfb/directfbvideosink.c: (gst_directfbvideosink_create), + (gst_directfbvideosink_get_pixel_format), + (gst_directfbvideosink_get_format_from_fourcc), + (gst_directfbvideosink_fixate), (gst_directfbvideosink_getcaps), + (gst_directfbvideosink_sink_link), + (gst_directfbvideosink_change_state), + (gst_directfbvideosink_chain), (gst_directfbvideosink_buffer_free), + (gst_directfbvideosink_buffer_alloc), + (gst_directfbvideosink_interface_supported), + (gst_directfbvideosink_interface_init), + (gst_directfbvideosink_navigation_send_event), + (gst_directfbvideosink_navigation_init), + (gst_directfbvideosink_set_property), + (gst_directfbvideosink_get_property), + (gst_directfbvideosink_finalize), (gst_directfbvideosink_init), + (gst_directfbvideosink_base_init), + (gst_directfbvideosink_class_init), + (gst_directfbvideosink_get_type), (plugin_init): + * ext/directfb/directfbvideosink.h: Adding a first version of + directfbvideosink. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_init): Initializing some + more. + +2004-11-28 Benjamin Otte + + * gst/audioconvert/gstchannelmix.c: (gst_audio_convert_mix): + walk the samples backwards if out_channels > in_channels so we don't + overwrite data + +2004-11-28 Ronald S. Bultje + + * gst/audioconvert/Makefile.am: + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init), + (gst_audio_convert_link), (gst_audio_convert_change_state), + (gst_audio_convert_channels): + * gst/audioconvert/gstchannelmix.c: + (gst_audio_convert_unset_matrix), + (gst_audio_convert_fill_identical), + (gst_audio_convert_fill_compatible), + (gst_audio_convert_detect_pos), (gst_audio_convert_fill_one_other), + (gst_audio_convert_fill_others), + (gst_audio_convert_fill_normalize), + (gst_audio_convert_fill_matrix), (gst_audio_convert_setup_matrix), + (gst_audio_convert_passthrough), (gst_audio_convert_mix): + * gst/audioconvert/gstchannelmix.h: + Implement a channel mixer. + +2004-11-28 Martin Soto + + * ext/alsa/gstalsasink.c (gst_alsa_sink_loop): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsa.c (gst_alsa_set_clock): + Make alsasink actually honor gst_element_set_clock and use that + clock instead of its internal one. + +2004-11-27 Christophe Fergeau + + * gst/playback/gstplaybasebin.c: (setup_source): fixed a caps leak + (gst_play_base_bin_change_state): nullify source and decoder when + going from READY to NULL so that we don't try to do weird stuff with + them when going from NULL to READY + * gst/playback/gstplaybin.c: (gst_play_bin_init): use gst_object_unref + instead of g_object_unref + (gen_video_element), (gen_audio_element): more refcounting fixes, now + it should be correct + (gst_play_bin_change_state): don't call remove_sinks if we are + currently disposing the object + +2004-11-27 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_loop): + Don't forget bass if it's there. Else left channel is silent... + +2004-11-27 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_loop), + (gst_a52dec_change_state): + Don't do sample adjusting anymore, we use float audio now. + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_fixate): + Don't fixate to non-existing properties. + +2004-11-27 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_channels), + (gst_a52dec_change_state): + Advertise that we can do surround sound. + +2004-11-27 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_reneg): + Add buffer-frames=0. + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_get_type), + (dvdreadsrc_init), (dvdreadsrc_get_event_mask), + (dvdreadsrc_get_query_types), (dvdreadsrc_get_formats), + (dvdreadsrc_srcpad_event), (dvdreadsrc_srcpad_query), + (_seek_title), (_seek_chapter), (get_next_cell_for), (_read), + (seek_sector), (dvdreadsrc_get), (dvdreadsrc_open_file), + (dvdreadsrc_change_state), (dvdreadsrc_uri_get_type), + (dvdreadsrc_uri_get_protocols), (dvdreadsrc_uri_get_uri), + (dvdreadsrc_uri_set_uri), (dvdreadsrc_uri_handler_init): + * ext/dvdread/dvdreadsrc.h: + Add seeking, querying for bytes, sectors, title, angle and + chapter. Handle multiple chapters. Relicense to LGPL because + Billy agreed on that (thanks Billy!). + +2004-11-27 Christophe Fergeau + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_dispose): + call parent dispose method + +2004-11-27 Martin Soto + + * gst-libs/gst/audio/audioclock.c (gst_audio_clock_set_active) + (gst_audio_clock_get_internal_time): + Fix active <-> inactive transitions: ensure time value always + grows and avoid abrupt value changes. + +2004-11-27 Arwed v. Merkatz + + * configure.ac: + * gst/tta/Makefile.am: + * gst/tta/crc32.h: + * gst/tta/filters.h: + * gst/tta/gsttta.c: + * gst/tta/gstttadec.c: + * gst/tta/gstttadec.h: + * gst/tta/gstttaparse.c: + * gst/tta/gstttaparse.h: + * gst/tta/ttadec.h: + added TTA parser and decoder + +2004-11-26 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (probe_triggered), (check_queue), (buffer_underrun), + (buffer_running), (buffer_overrun), (gen_source_element), + (setup_source): + * gst/playback/gstplaybasebin.h: + Implement buffering. Needs some more work. + +2004-11-26 Ronald S. Bultje + + * ext/theora/theoradec.c: (theora_dec_chain): + Fix ilog mask range overflow. + +2004-11-26 Ronald S. Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_get_caps): + Don't omit the last (which in case of dmix is the only :) ) + channel count. Don't set channels if <= 2. + +2004-11-26 Christophe Fergeau + + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element): Removed 2 obsolete comments + +2004-11-26 Stephane Loeuillet + + * ext/vorbis/oggvorbisenc.c + * ext/vorbis/vorbisenc.c : + change description fields of those plugins to differentiate them + (pitivi show Encoders by description, they had the same one) + +2004-11-25 Christophe Fergeau + + Reviewed by: Ronald S. Bultje + + * gst/playback/gstplaybin.c: (gst_play_bin_dispose), + (gst_play_bin_set_property), (gen_video_element), + (gen_audio_element): + Refcounting fixes for provided audio-/videosinks. + +2004-11-25 Ronald S. Bultje + + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element), (setup_sinks), (gst_play_bin_change_state): + Don't reference all sinks, but only the video- and audiosinks. + The vis. element should be disposed when we're done with it. + We don't have any reason to keep it around. This fixes warnings + when reusing playbin for playing multiple audio files with + vis. enabled. Also release audio device on pause - idea stolen + from Rhythmbox. + +2004-11-25 Ronald S. Bultje + + * ext/a52dec/gsta52dec.c: (gst_a52dec_channels), (gst_a52dec_push), + (gst_a52dec_reneg), (gst_a52dec_loop), (plugin_init): + * ext/alsa/gstalsa.c: (gst_alsa_get_caps): + * ext/alsa/gstalsaplugin.c: (plugin_init): + * ext/dts/gstdtsdec.c: (gst_dtsdec_channels), + (gst_dtsdec_renegotiate), (gst_dtsdec_loop), (plugin_init): + * ext/faad/gstfaad.c: (gst_faad_init), (gst_faad_chanpos_from_gst), + (gst_faad_chanpos_to_gst), (gst_faad_sinkconnect), + (gst_faad_srcgetcaps), (gst_faad_srcconnect), (gst_faad_chain), + (gst_faad_change_state), (plugin_init): + * ext/faad/gstfaad.h: + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + * gst-libs/gst/audio/Makefile.am: + * gst-libs/gst/audio/audio.c: (plugin_init): + * gst-libs/gst/audio/multichannel.c: + (gst_audio_check_channel_positions), + (gst_audio_get_channel_positions), + (gst_audio_set_channel_positions), + (gst_audio_set_structure_channel_positions_list), + (add_list_to_struct), (gst_audio_set_caps_channel_positions_list), + (gst_audio_fixate_channel_positions): + * gst-libs/gst/audio/multichannel.h: + * gst-libs/gst/audio/testchannels.c: (main): + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_class_init), (gst_audio_convert_init), + (gst_audio_convert_dispose), (gst_audio_convert_getcaps), + (gst_audio_convert_parse_caps), (gst_audio_convert_link), + (gst_audio_convert_fixate), (gst_audio_convert_channels): + * gst/audioconvert/plugin.c: (plugin_init): + Surround sound support. + +2004-11-25 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_push): + Fix position for discont if we're close as well. Nitpicking, but + saves a few milliseconds of extra waiting or skipping. + +2004-11-25 Ronald S. Bultje + + * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter): + We sometimes need parsers for playback, so add those too. + +2004-11-25 Ronald S. Bultje + + * configure.ac: + * gst/apetag/Makefile.am: + * gst/apetag/apedemux.c: (gst_ape_demux_get_type), + (gst_ape_demux_base_init), (gst_ape_demux_class_init), + (gst_ape_demux_init), (gst_ape_demux_get_src_formats), + (gst_ape_demux_get_src_query_types), + (gst_ape_demux_handle_src_query), (gst_ape_demux_get_event_mask), + (gst_ape_demux_handle_src_event), (gst_ape_demux_handle_event), + (gst_ape_demux_typefind_peek), (gst_ape_demux_typefind_get_length), + (gst_ape_demux_typefind_suggest), (gst_ape_demux_typefind), + (gst_ape_demux_parse_tags), (gst_ape_demux_stream_init), + (gst_ape_demux_stream_data), (gst_ape_demux_loop), + (gst_ape_demux_change_state): + * gst/apetag/apedemux.h: + * gst/apetag/apetag.c: (plugin_init): + * gst/typefind/gsttypefindfunctions.c: (apetag_type_find), + (plugin_init): + APE v1/2 tag reader plus typefind function. + +2004-11-25 Ronald S. Bultje + + * configure.ac: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_add_element): + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find): + Remove hacks for older core. Require newer core version + accordingly. + +2004-11-25 Ronald S. Bultje + + * gst/cdxaparse/Makefile.am: + * gst/cdxaparse/gstcdxaparse.c: (gst_cdxaparse_get_type), + (gst_cdxaparse_class_init), (gst_cdxaparse_init), + (gst_cdxaparse_loop), (gst_cdxaparse_change_state), (plugin_init): + * gst/cdxaparse/gstcdxaparse.h: + * gst/cdxaparse/gstcdxastrip.c: (gst_cdxastrip_get_type), + (gst_cdxastrip_base_init), (gst_cdxastrip_class_init), + (gst_cdxastrip_init), (gst_cdxastrip_get_src_formats), + (gst_cdxastrip_get_src_query_types), + (gst_cdxastrip_handle_src_query), (gst_cdxastrip_get_event_mask), + (gst_cdxastrip_handle_src_event), (gst_cdxastrip_strip), + (gst_cdxastrip_sync), (gst_cdxastrip_handle_event), + (gst_cdxastrip_chain), (gst_cdxastrip_change_state): + * gst/cdxaparse/gstcdxastrip.h: + SVCD/VCD header stripping separated from CDXA image parsing. + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find), + (plugin_init): + Add VCD/SVCD header typefinding for VCD/SVCD. + * sys/vcd/vcdsrc.c: (gst_vcdsrc_get_type), (gst_vcdsrc_base_init), + (gst_vcdsrc_class_init), (gst_vcdsrc_init), + (gst_vcdsrc_set_property), (gst_vcdsrc_get_property), + (gst_vcdsrc_get_event_mask), (gst_vcdsrc_get_query_types), + (gst_vcdsrc_get_formats), (gst_vcdsrc_srcpad_event), + (gst_vcdsrc_srcpad_query), (gst_vcdsrc_get), + (gst_vcdsrc_open_file), (gst_vcdsrc_close_file), + (gst_vcdsrc_change_state), (gst_vcdsrc_msf), + (gst_vcdsrc_recalculate), (gst_vcdsrc_uri_get_type), + (gst_vcdsrc_uri_get_protocols), (gst_vcdsrc_uri_get_uri), + (gst_vcdsrc_uri_set_uri), (gst_vcdsrc_uri_handler_init): + * sys/vcd/vcdsrc.h: + Fix up, add seeking, querying, URI interface. Works in totem now. + +2004-11-25 Thomas Vander Stichele + + * configure.ac: + back to CVS + +=== release 0.8.6 === + +2004-11-25 Thomas Vander Stichele + + * NEWS: + * RELEASE: + * configure.ac: + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/it.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + releasing 0.8.6, "IOU Love" + +2004-11-23 Thomas Vander Stichele + + patch by: Ronald Bultje + + * gst/playback/gstplaybasebin.c: + Fix unplayable files error handling. Fixes #158365 + +2004-11-23 Thomas Vander Stichele + + patch by: Ronald Bultje + + * gst/typefind/gsttypefindfunctions.c: + Fix broken mp3 typefinding. Fixes #158375 + +2004-11-23 Thomas Vander Stichele + + patch by: Ronald Bultje + + * ext/ogg/gstoggdemux.c: + Fix sync on broken files. Fixes #158976 + +2004-11-23 Thomas Vander Stichele + + patch by: Edward Hervey + + * ext/libpng/gstpngenc.c: + Copy over buffer properties. Fixes #158832 + +2004-11-23 Thomas Vander Stichele + + patch by: Tim-Philipp Müller + + * ext/dvdread/dvdreadsrc.c: + Fixes invalid reads (#158462) + +2004-11-23 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4lsrc_calls.c: + Probe less and cache it. Fixes #159187. + +2004-11-23 Thomas Vander Stichele + + * gst/videorate/gstvideorate.c: + Handle all video formats. Fixes #159186. + +2004-11-16 Jan Schmidt + * gst/synaesthesia/gstsynaesthesia.c: + (gst_synaesthesia_class_init), (gst_synaesthesia_init), + (gst_synaesthesia_dispose), (gst_synaesthesia_finalize), + (gst_synaesthesia_sink_link), (gst_synaesthesia_src_getcaps), + (gst_synaesthesia_src_link), (gst_synaesthesia_chain), + (gst_synaesthesia_change_state), (plugin_init): + Fix up synaesthesia to work under different samplerates/ buffer sizes. + Force 320x200 output, as that's the only thing the underlying + synaesthesia implementation supports. Still needs to be made + re-entrant. + +2004-11-14 Ronald S. Bultje + + * configure.ac: + Fix mpeg2enc configure check (similar to mplex check below). + +2004-11-14 Koop Mast + + reviewed by: Ronald S. Bultje + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + Fix for gcc-2.95 (fixes #158221). + +2004-11-13 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_add_element): + Re-add clock distribution hack (until new core is released). + Fixes #158125. + +2004-11-13 Arwed v. Merkatz + * configure.ac: + fix mplex configure check segfaulting on some systems (bug #140994) + +2004-11-13 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_pcm_wait): + add debugging + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + do a wait when we enter the loop func with no data available to + write instead of getting into an 100% CPU loop by just returning and + being called again by the scheduler + +2004-11-13 Jan Schmidt + + * configure.ac: + * ext/libvisual/visual.c: (gst_visual_get_type), + (libvisual_log_handler), (gst_visual_getcaps), + (gst_visual_srclink), (gst_visual_change_state), (make_valid_name), + (plugin_init): + Update libvisual to 0.1.7. Link in the debug handling to gstreamer + * ext/smoothwave/Makefile.am: + * ext/smoothwave/demo-osssrc.c: (main): + * ext/smoothwave/gstsmoothwave.c: (gst_smoothwave_class_init), + (gst_smoothwave_init), (gst_smoothwave_dispose), (gst_sw_sinklink), + (gst_sw_srclink), (gst_smoothwave_chain), (gst_sw_change_state), + (plugin_init): + * ext/smoothwave/gstsmoothwave.h: + Make gstsmoothwave a working element in the 20th century. + + * gst/chart/gstchart.c: (gst_chart_init), (gst_chart_srcconnect): + Fix incorrect link function + +2004-11-12 Ronald S. Bultje + + * gst/volume/gstvolume.c: + Allow buffer-frames=0. + +2004-11-12 Iain + + * configure.ac: Check for polypaudio + + * ext/Makefile.am: Build the polyp dir + + * ext/polyp: The polypsink sources. + +2004-10-30 Iain + + * gst/interleave/interleave.c (interleave_unlink): Change the src pads + caps to reflect the new number of channels. + +2004-11-12 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + Fix for negotiation order problem. This would show when the + ALSA loopfuction was called before any other function. ALSA + wouldn't do anything because we're not negotiated yet, leading + to an infinite loop. Showed in e.g. Rhythmbox. Fixes #158006. + +2004-11-11 Tim-Philipp Müller + + reviewed by: Ronald S. Bultje + + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query): + No warnings (#157986). + +2004-11-11 Ronald S. Bultje + + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Prefer apev1/2 and id3v1 (at end of file) over musepack. + +2004-11-11 Ronald S. Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_loop_stream): + Signal no-more-pads (so it works in playbin). + +2004-11-11 Ronald S. Bultje + + * ext/musepack/gstmusepackreader.cpp: + Workaround for older core. + +2004-11-11 Ronald S. Bultje + + * gst/ffmpegcolorspace/imgconvert.c: (yuv420p_to_yuv422): + Actually test for odd width/height rather than testing whether + a temporary variable that was 0 before we subtracted 1 is now + not equal to zero (which it always is). + +2004-11-11 Zaheer Abbas Merali + + * sys/v4l2/gstv4l2element.c: (gst_v4l2_iface_supported): + Fix compilation if HAVE_XVIDEO is not defined + +2004-11-11 Zaheer Abbas Merali + + * sys/v4l/gstv4lelement.c: (gst_v4l_iface_supported): + Fix compilation if HAVE_XVIDEO is not defined + +2004-11-11 Jan Schmidt + + * gst/goom/gstgoom.c: (gst_goom_class_init), (gst_goom_init), + (gst_goom_dispose), (gst_goom_sinkconnect), (gst_goom_chain), + (gst_goom_change_state), (plugin_init): + Use the bytestream adapter so goom doesn't depend on the input + buffer size. + Add a debug category + +2004-11-11 Ronald S. Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_change_state): + Only set hardware parameters *after* negotiation. Before + negotiation, it will set ANY and that seems to cause crashes + (see e.g. #151288, #153227). + +2004-11-10 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_get_time): + This seems to be antique leftover. It needs to pass error + checking. + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_init), + (gst_sdlvideosink_deinitsdl), (gst_sdlvideosink_initsdl), + (gst_sdlvideosink_destroy), (gst_sdlvideosink_create), + (gst_sdlvideosink_sinkconnect), (gst_sdlvideosink_chain): + Fix GstXOverlay implementation (#151059). + +2004-11-10 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_change_state): + Don't assert (#157853). + +2004-11-10 Ronald S. Bultje + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event), + Fix bytes/samples confustion. + (gst_alsa_sink_mmap), (gst_alsa_sink_loop): + Fix for underrun (#144389). + +2004-11-09 Ronald S. Bultje + + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find): + Disable halfway-seek for pending release (since it needs a new + core release). + +2004-11-09 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4lsrc_calls.c: + add autoprobe-fps property so we can separate autoprobing parts + +2004-11-09 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: + * sys/v4l/v4lsrc_calls.c: + initialise fourcc to catch unset fourcc's, and debug + +2004-11-09 Wim Taymans + + * gst/playback/README: + * gst/playback/gstdecodebin.c: (close_pad_link), (try_to_link_1): + * gst/playback/gstplaybin.c: (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_set_property), + (remove_sinks), (setup_sinks), (gst_play_bin_change_state), + (gst_play_bin_get_event_masks), (gst_play_bin_send_event), + (gst_play_bin_get_formats), (gst_play_bin_convert), + (gst_play_bin_get_query_types), (gst_play_bin_query): + Cleanups and some more documentation. + +2004-11-09 Jan Schmidt + + * ext/libcaca/gstcacasink.c: (gst_cacasink_class_init), + (gst_cacasink_init), (gst_cacasink_chain): + * ext/libcaca/gstcacasink.h: + Cacasink inherits from VideoSink, so let that store the clock. + +2004-11-09 Wim Taymans + + * gst/playback/README: + * gst/playback/gstplaybasebin.c: (group_destroy), (group_is_muted), + (add_stream), (unknown_type), (add_element_stream), (no_more_pads), + (probe_triggered), (preroll_unlinked), (new_decoded_pad), + (gst_play_base_bin_change_state), (gst_play_base_bin_found_tag): + * gst/playback/gstplaybin.c: (gen_vis_element), (remove_sinks), + (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_info_set_mute), + (gst_stream_info_is_mute), (gst_stream_info_set_property): + * gst/playback/gststreaminfo.h: + Updated README. + Only switch groups if all streams have muted (EOSed). + Send Tags in sync with the stream playback instead of in + the playback/preroll phase. + Some cleanups, free the fakesrc elements. + +2004-11-09 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_get_caps_internal): + buffer-frames property was missing + * ext/arts/gst_arts.c: + rate missing from sinkcaps + * ext/audiofile/gstafparse.c: + * ext/audiofile/gstafsink.c: + * ext/audiofile/gstafsrc.c: + * ext/swfdec/gstswfdec.c: + int audio doesn't know buffer-frames + * ext/cdparanoia/gstcdparanoia.c: + int audio doesn't know chunksize either + * ext/nas/nassink.c: + it's endianness, not endianess + * gst-libs/gst/audio/audio.h: + make float standard pad template caps really describe float + * gst/law/mulaw.c: (linear_factory): + signed only, please + * gst/mpegstream/gstdvddemux.c: + widths of 20 are not valid + +2004-11-08 Thomas Vander Stichele + + Submitted by: Luca Ferretti + + * po/LINGUAS: + * po/it.po: + Add Italian + +2004-11-08 Wim Taymans + + * gst/playback/README: + * gst/playback/gstdecodebin.c: (close_pad_link), (try_to_link_1): + * gst/playback/gstplaybasebin.c: (probe_triggered), + (gst_play_base_bin_change_state): + Updated README, added more comments for fixmes etc.. + +2004-11-08 Wim Taymans + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_add_element): + We can remove this hack now. + +2004-11-08 Wim Taymans + + * gst/videomixer/videomixer.c: (gst_videomixer_blend_ayuv_ayuv), + (gst_videomixer_fill_checker), (gst_videomixer_fill_color), + (gst_videomixer_blend_buffers), (gst_videomixer_loop): + Only mix AYUV for maximum quality. + +2004-11-08 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (get_relative), (gst_ogg_demux_src_query), + (gst_ogg_demux_push), (gst_ogg_pad_push): + Let's act as if we're synchronized now! :). + * ext/theora/theoradec.c: (theora_dec_chain): + Add some debug. + +2004-11-08 Wim Taymans + + * gst/alpha/gstalpha.c: (gst_alpha_method_get_type), + (gst_alpha_set_property), (gst_alpha_sink_link), + (gst_alpha_set_ayuv), (gst_alpha_set_i420), + (gst_alpha_chroma_key_ayuv), (gst_alpha_chroma_key_i420), + (gst_alpha_init_params), (gst_alpha_chain): + Implement alpha functions for AYUV too, this increases + accuracy quite a bit. + +2004-11-08 Wim Taymans + + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_caps_to_pixfmt), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_caps_remove_format_info): + * gst/ffmpegcolorspace/imgconvert.c: (avpicture_get_size), + (shrink12), (img_get_alpha_info), (deinterlace_line), + (deinterlace_line_inplace): + * gst/ffmpegcolorspace/imgconvert_template.h: + Added AYUV colorspace and handle RGBA a bit more respectful. + +2004-11-08 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + Actually always send a discont (cornercase when resending the + same serial-tagged chain twice). + +2004-11-08 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_clear), + (gst_ximagesink_finalize): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_finalize): Some more cleanups, leaks fixed and checks. + +2004-11-08 Wim Taymans + + * gst/typefind/gsttypefindfunctions.c: (aac_type_find): + Don't segfault on NULL data. + +2004-11-08 Wim Taymans + + * gst/playback/gstdecodebin.c: (unlinked): + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (gst_play_base_bin_init), (group_create), (get_active_group), + (get_building_group), (group_destroy), (group_commit), + (queue_overrun), (remove_groups), (add_stream), (unknown_type), + (add_element_stream), (no_more_pads), (probe_triggered), + (preroll_unlinked), (new_decoded_pad), (removed_decoded_pad), + (state_change), (setup_source), (gst_play_base_bin_get_property), + (gst_play_base_bin_change_state), (gst_play_base_bin_add_element), + (gst_play_base_bin_link_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (remove_sinks), (setup_sinks), (gst_play_bin_change_state): + Add support for chained ogg files. Prepare for playlist + support. This patch introduces the concept of pad groups, which + together compose one playable media file. + +2004-11-07 David Schleef + + * testsuite/gst-lint: Check for pad templates that aren't statically + scoped. + +2004-11-07 Ronald S. Bultje + + * configure.ac: + * ext/Makefile.am: + * ext/musepack/Makefile.am: + * ext/musepack/gstmusepackdec.cpp: + * ext/musepack/gstmusepackdec.h: + * ext/musepack/gstmusepackreader.cpp: + * ext/musepack/gstmusepackreader.h: + Add musepack decoder. + * ext/faad/gstfaad.c: (gst_faad_base_init): + Make pad templates static. + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find), + (plugin_init): + Add musepack typefinder, make mp3 typefinding work halfway stream, + which doesn't actually work yet because id3demux doesn't implement + _get_length(). + +2004-11-07 Ronald S. Bultje + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_queue_pads), (gst_ogg_mux_loop): + Fix interrupt event handling (#144436). + +2004-11-07 Ronald S. Bultje + + * ext/mad/gstid3tag.c: (gst_id3_tag_do_typefind): + Hide unused glory. + +2004-11-06 Tim-Philipp Müller + + reviewed by: Ronald S. Bultje + + * ext/vorbis/vorbisenc.c: (raw_caps_factory): + Fix weird caps (#157548). + +2004-11-06 Tim-Philipp Müller + + Reviewed by: Ronald S. Bultje + + * gst/rtp/gstrtpgsmparse.c: (gst_rtpgsm_caps_nego): + Add missing NULL terminator (#157543). + +2004-11-05 Thomas Vander Stichele + + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversrc.c: + ports can go up to 65535. Move common defines to gsttcp.h + +2004-11-05 Wim Taymans + + * gst/videotestsrc/videotestsrc.c: (paint_setup_Y41B), + (paint_hline_Y41B), (paint_setup_Y42B), (paint_hline_Y42B): + Added two more colorspaces. + +2004-11-05 Wim Taymans + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (avpicture_get_size), + (yuv422p_to_yuv422), (yuv420p_to_yuv422), (shrink12), + (img_convert), (deinterlace_line), (deinterlace_line_inplace): + More stride fixes. + +2004-11-05 Wim Taymans + + * gst/alpha/gstalpha.c: (gst_alpha_set_property), (gst_alpha_add), + (gst_alpha_chroma_key), (gst_alpha_init_params), (gst_alpha_chain): + * gst/videomixer/videomixer.c: (gst_videomixer_blend_ayuv_i420), + (gst_videomixer_fill_checker), (gst_videomixer_blend_buffers), + (gst_videomixer_loop): + More stride fixes. + +2004-11-05 Benjamin Otte + + * ext/mad/gstmad.c: (gst_mad_chain): + don't overflow data buffer. Flush not needed sync data when syncing + failed. + +2004-11-04 Wim Taymans + + * gst/alpha/gstalpha.c: (gst_alpha_method_get_type), + (gst_alpha_class_init), (gst_alpha_init), (gst_alpha_set_property), + (gst_alpha_get_property), (gst_alpha_add), (gst_alpha_chroma_key), + (gst_alpha_init_params), (gst_alpha_chain), + (gst_alpha_change_state): + Updated the chroma keying algorithm with something more + sophisticated. + +2004-11-03 Wim Taymans + + * gst/videomixer/videomixer.c: (gst_videomixer_blend_ayuv_i420), + (gst_videomixer_fill_checker), (gst_videomixer_fill_color), + (gst_videomixer_blend_buffers), (gst_videomixer_loop): + Fix stride issues. Does not completely work for odd + heights. + +2004-11-03 Wim Taymans + + * gst/alpha/gstalpha.c: (gst_alpha_method_get_type), + (gst_alpha_chroma_key), (gst_alpha_chain): + Fix stride issues. Does not completely work for odd + heights. + +2004-11-03 Christophe Fergeau + + * gst/videoscale/gstvideoscale.c: (gst_videoscale_getcaps): + * gst/videoscale/videoscale.c: (videoscale_find_by_structure): + leak fixes + +2004-11-03 Wim Taymans + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/imgconvert.c: (avpicture_get_size), + (avpicture_alloc): + * gst/ffmpegcolorspace/imgconvert_template.h: + Use correct _fill function to get correct strides. + +2004-11-02 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (gst_qtdemux_add_stream), (qtdemux_parse), (qtdemux_parse_tree), + (qtdemux_parse_udta), (qtdemux_tag_add), (gst_qtdemux_handle_esds): + Change all g_print()s to debugging. Add a bunch of consistency + checks. + +2004-11-02 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (try_to_link_1), (get_our_ghost_pad), (remove_element_chain), + (unlinked), (no_more_pads), (close_link): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_init), + (unknown_type), (add_element_stream), (new_decoded_pad), + (removed_decoded_pad), (setup_source): + * gst/playback/gststreaminfo.c: (gst_stream_info_get_type), + (gst_stream_info_class_init), (gst_stream_info_init), + (gst_stream_info_new), (gst_stream_info_dispose), + (stream_info_mute_pad), (gst_stream_info_set_property), + (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + Fix playback of multiple files. + a slightly different approach to handling dynamic pad removals. + This one only looks at pads that we have linked. + +2004-11-01 Christophe Fergeau + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_finalize): fix an "invalid + free" warning from libc. + +2004-11-01 Ronald S. Bultje + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (get_unconnected_element), (remove_starting_from), (pad_removed), + (close_link): + Implement support for dynamic pad changing. We listen to "live" + pad removals (i.e. while playing) and re-setup autoplugging + after that. Playbasebin/playbin need some more work for this + to finally work, but decodebin supports (and replugs) chained + ogg now. + +2004-11-02 Jan Schmidt + + * ext/alsa/gstalsa.c: (gst_alsa_class_init), (gst_alsa_dispose), + (gst_alsa_finalize): + * ext/cdaudio/gstcdaudio.c: (gst_cdaudio_class_init), + (gst_cdaudio_finalize): + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_class_init), + (cdparanoia_finalize): + * ext/divx/gstdivxdec.c: (gst_divxdec_dispose): + * ext/divx/gstdivxenc.c: (gst_divxenc_dispose): + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init), + (dvdreadsrc_finalize): + * ext/flac/gstflacdec.c: (gst_flacdec_class_init), + (gst_flacdec_finalize): + * ext/flac/gstflacenc.c: (gst_flacenc_class_init), + (gst_flacenc_finalize): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_class_init), + (gst_gnomevfssink_finalize): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_class_init), + (gst_gnomevfssrc_finalize): + * ext/libfame/gstlibfame.c: (gst_fameenc_class_init), + (gst_fameenc_finalize): + * ext/nas/nassink.c: (gst_nassink_class_init), + (gst_nassink_finalize): + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_finalize), + (gst_sdlvideosink_class_init): + * ext/sndfile/gstsf.c: (gst_sf_dispose): + * gst-libs/gst/mixer/mixertrack.c: (gst_mixer_track_dispose): + * gst-libs/gst/tuner/tunerchannel.c: (gst_tuner_channel_dispose): + * gst-libs/gst/tuner/tunernorm.c: (gst_tuner_norm_dispose): + * gst-libs/gst/xwindowlistener/xwindowlistener.c: + (gst_x_window_listener_dispose): + * gst/audioscale/gstaudioscale.c: + * gst/playondemand/gstplayondemand.c: (play_on_demand_class_init), + (play_on_demand_finalize): + * gst/videofilter/gstvideobalance.c: (gst_videobalance_dispose): + * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain): + * sys/cdrom/gstcdplayer.c: (cdplayer_class_init), + (cdplayer_finalize): + * sys/glsink/glimagesink.c: (gst_glimagesink_finalize), + (gst_glimagesink_class_init): + * sys/oss/gstosselement.c: (gst_osselement_class_init), + (gst_osselement_finalize): + * sys/oss/gstosssink.c: (gst_osssink_dispose): + * sys/oss/gstosssrc.c: (gst_osssrc_dispose): + * sys/v4l/gstv4lelement.c: (gst_v4lelement_dispose): + Fixes a bunch of problems with finalize and dispose functions, + either assumptions that dispose is only called once, or not calling + the parent class dispose/finalize function + +2004-11-01 Stefan Kost + + * ext/esd/esdsink.c: (gst_esdsink_init), (gst_esdsink_link): + added two api precondition guards + use g_strdup with getenv to fix crash when using ENVVAR + +2004-11-01 Jan Schmidt + * ext/esd/esdsink.c: (gst_esdsink_class_init), + (gst_esdsink_finalize): + Use a finalize function, not dispose, and more importantly, + call the parent class finalize function too + +2004-11-01 Johan Dahlin + + * ext/ogg/gstoggdemux.c: + * gst/tags/gstvorbistag.c: + Plug leaks. + +2004-10-31 Benjamin Otte + + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_chain): + lotsa memleaks today. But they're all small... + +2004-10-31 Benjamin Otte + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + another memleak crushed + +2004-10-31 Benjamin Otte + + * gst/tags/gstvorbistag.c: (gst_tag_to_vorbis_comments): + fix memleak + +2004-10-31 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + Hack to prevent crash when going to READY inside signal handler + while this function is active. + +2004-10-31 Ronald S. Bultje + + * gst/ffmpegcolorspace/Makefile.am: + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/common.h: + * gst/ffmpegcolorspace/dsputil.c: (dsputil_static_init): + * gst/ffmpegcolorspace/dsputil.h: + * gst/ffmpegcolorspace/gstffmpeg.c: (plugin_init): + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_get_palette), (gst_ffmpeg_set_palette), + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_smpfmt_to_caps), + (gst_ffmpegcsp_codectype_to_caps), (gst_ffmpeg_caps_to_smpfmt), + (gst_ffmpeg_caps_to_pixfmt), (gst_ffmpegcsp_caps_with_codectype), + (gst_ffmpegcsp_avpicture_fill): + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcsp_caps_remove_format_info), (gst_ffmpegcsp_getcaps), + (gst_ffmpegcsp_pad_link), (gst_ffmpegcsp_get_type), + (gst_ffmpegcsp_base_init), (gst_ffmpegcsp_class_init), + (gst_ffmpegcsp_init), (gst_ffmpegcsp_chain), + (gst_ffmpegcsp_change_state), (gst_ffmpegcsp_set_property), + (gst_ffmpegcsp_get_property), (gst_ffmpegcolorspace_register): + * gst/ffmpegcolorspace/imgconvert.c: + (avcodec_get_chroma_sub_sample), (avcodec_get_pix_fmt_name), + (avcodec_get_pix_fmt), (avpicture_fill), (avpicture_layout), + (avpicture_get_size), (avcodec_get_pix_fmt_loss), + (avg_bits_per_pixel), (avcodec_find_best_pix_fmt1), + (avcodec_find_best_pix_fmt), (img_copy_plane), (img_copy), + (yuv422_to_yuv420p), (uyvy422_to_yuv420p), (uyvy422_to_yuv422p), + (yuv422_to_yuv422p), (yuv422p_to_yuv422), (yuv422p_to_uyvy422), + (uyvy411_to_yuv411p), (yuv420p_to_yuv422), (C_JPEG_TO_CCIR), + (img_convert_init), (img_apply_table), (shrink41), (shrink21), + (shrink12), (shrink22), (shrink44), (grow21_line), (grow41_line), + (grow21), (grow22), (grow41), (grow44), (conv411), + (gif_clut_index), (build_rgb_palette), (bitcopy_n), (mono_to_gray), + (monowhite_to_gray), (monoblack_to_gray), (gray_to_mono), + (gray_to_monowhite), (gray_to_monoblack), (avpicture_alloc), + (avpicture_free), (is_yuv_planar), (img_convert), + (get_alpha_info_pal8), (img_get_alpha_info), (deinterlace_line), + (deinterlace_line_inplace), (deinterlace_bottom_field), + (deinterlace_bottom_field_inplace), (avpicture_deinterlace): + * gst/ffmpegcolorspace/imgconvert_template.h: + * gst/ffmpegcolorspace/mem.c: (av_malloc), (av_realloc), (av_free): + * gst/ffmpegcolorspace/mmx.h: + * gst/ffmpegcolorspace/utils.c: (av_mallocz), (av_strdup), + (av_fast_realloc), (av_mallocz_static), (av_free_static), + (av_freep), (avcodec_get_context_defaults), + (avcodec_alloc_context), (avcodec_init): + Sync back from gst-ffmpeg. Deprecates ffcolorspace. Adds palette + handling plus update from ffmpeg CVS. Large clean-up. + +2004-10-31 Ronald S. Bultje + + * gst/playback/Makefile.am: + We need the marshallers for decodebin, too. + +2004-10-30 David Schleef + + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): Make + quicktime typefinding work with 64-bit offsets. + +2004-10-30 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_handle_sink_event): + Set EOS on the element when processing an EOS event. + * ext/speex/gstspeexdec.h: + * ext/speex/gstspeexenc.h: + Only keep a const ptr to the mode + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data), + (gst_riff_create_audio_template_caps): + Allow WMAV3, with up to 6 channels. + * gst/asfdemux/gstasfmux.c: (gst_asfmux_request_new_pad): + Don't call gst_pad_set_event_function on a sink pad. + * gst/mpegstream/gstdvddemux.c: + (gst_dvd_demux_get_subpicture_stream), + (gst_dvd_demux_set_cur_audio), (gst_dvd_demux_set_cur_subpicture): + Copy the explicit caps that were set across to the cur_* pads, + instead of trying to use a possibly non-existent negotiated caps. + Reset the type of subpicture pads to UNKNOWN after calling + init_stream, so that the caps get set. + +2004-10-29 Martin Pitt + + Reviewed by: Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_chunk): + Don't touch buffer if it is of size 0 (fixes #151064). + +2004-10-29 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_push), (gst_ogg_pad_push): + Synchronized discont handling. + +2004-10-29 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event), + (gst_ogg_demux_push): + Make seeking sort-of exact again (fixes #156387). + +2004-10-29 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (unknown_type), + (add_element_stream), (new_decoded_pad), + (gst_play_base_bin_change_state): + * gst/playback/gststreaminfo.c: (gst_stream_info_class_init), + (gst_stream_info_init), (gst_stream_info_new), + (gst_stream_info_dispose), (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + Make caps explicitely available. Makes testing for unsupported + types possible. Improves error reporting. + +2004-10-29 Ronald S. Bultje + + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_buffer_to_default_format): + Really don't touch read-only buffers (#156563). + +2004-10-29 Sebastien Cote + + Reviewd by: Ronald S. Bultje + + * gst/wavparse/gstwavparse.c: (gst_wavparse_fmt): + Fix memleak (#155223). + +2004-10-29 Wim Taymans + + * gst/tcp/.cvsignore: + * gst/tcp/gstmultifdsink.c: (gst_sync_method_get_type), + (gst_multifdsink_class_init), (gst_multifdsink_init), + (gst_multifdsink_add), (gst_multifdsink_remove), + (gst_multifdsink_remove_client_link), (is_sync_frame), + (gst_multifdsink_new_client), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_set_property), + (gst_multifdsink_get_property): + * gst/tcp/gstmultifdsink.h: + Added burst on connect sync_method, deprecated sync_clients, + streamlined the sync code some more. + +2004-10-29 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (thread_error), (setup_source), + (gst_play_base_bin_change_state): + Improve error reporting. + +2004-10-28 Wim Taymans + + * gst/tcp/Makefile.am: + * gst/tcp/fdsetstress.c: (mess_some_more), (run_test), (main): + * gst/tcp/gstfdset.c: (nearest_pow), (resize), (ensure_size), + (gst_fdset_new), (gst_fdset_free), (gst_fdset_set_mode), + (gst_fdset_fd_ctl_write), (gst_fdset_fd_ctl_read), + (gst_fdset_fd_has_closed), (gst_fdset_fd_has_error), + (gst_fdset_fd_can_read), (gst_fdset_fd_can_write), + (gst_fdset_wait): + Added more locks around fdset structures. Fixed/reworked + the poll array resizing code. + Added stress test for fdset. + +2004-10-28 Zaheer Abbas Merali + + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audiofilter_link): + fix build + +2004-10-28 Benjamin Otte + + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audiofilter_link): + fix link function to always query channels and query width for + floats + * configure.ac: + add equalizer dir + * gst/equalizer/Makefile.am: + * gst/equalizer/gstiirequalizer.c: (gst_iir_equalizer_get_type), + (gst_iir_equalizer_base_init), (gst_iir_equalizer_class_init), + (gst_iir_equalizer_init), (gst_iir_equalizer_finalize), + (arg_to_scale), (setup_filter), + (gst_iir_equalizer_compute_frequencies), + (gst_iir_equalizer_set_property), (gst_iir_equalizer_get_property), + (gst_iir_equalizer_filter_inplace), (gst_iir_equalizer_setup), + (plugin_init): + add an equalizer + +2004-10-27 Thomas Vander Stichele + + Submitted by: Kjartan Maraas + + * po/LINGUAS: + * po/nb.po: + Added Norwegian Bokmaal translation + +2004-10-27 Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + Don't break on options (fixes #156488). + +2004-10-27 Thomas Vander Stichele + + * configure.ac: + * ext/cdaudio/Makefile.am: + * sys/Makefile.am: + fix build on older automake + +2004-10-26 Wim Taymans + + * ext/dv/gstdvdec.c: (gst_dvdec_video_getcaps), + (gst_dvdec_video_link), (gst_dvdec_push), (gst_dvdec_loop): + Allow a little margin when negotiating the framerate. + +2004-10-26 Stefan Kost + + * gst/level/gstlevel.c: + synchonised naming of pads and pad-templates + +2004-10-26 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event), + (gst_ogg_demux_handle_event), (_find_chain_get_unknown_part), + (_find_streams_check), (gst_ogg_demux_push): + Fix EOS again. Needs to be done in a better way. We should not + remove the pad if there is no new chained stream. + +2004-10-26 Iain + + * ext/ogg/gstoggdemux.c (gst_ogg_pad_new): Free the tag list. + * gst/audioscale/gstaudioscale.c (gst_audioscale_link): Free the copy + of the caps. + * gst/interleave/interleave.c (interleave_class_init): Hook up release + pad. + (interleave_release_pad): Remove the pad. + * gst/level/gstlevel.c: Allow the level to take 1 or 2 channels. + * sys/sunaudio/gstsunaudio.c (gst_sunaudio_setparams): Pay attention to + the set device. + * sys/xvimage/xvimagesink.c (gst_xvimagesink_get_xv_support): Free the + attrs + (gst_xvimagesink_xcontext_clear): Free the xcontext. + (gst_xvimagesink_finalize): Free the par. + +2004-10-26 Ronald S. Bultje + + * gst/avi/gstavimux.c: (gst_avimux_audsinkconnect), + (gst_avimux_stop_file): + First calculate the rate, and only then use it. Hdr.rate is a + multiple and not a derivative of hdr.scale. Scale is not the + same as blockalign but is solely related to rate. + +2004-10-26 Ronald S. Bultje + + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_init), + (gst_gnomevfssink_handle_event), (gst_gnomevfssink_chain): + Implement seeking. + +2004-10-25 James Henstridge + + Reviewed by: David Schleef + + * examples/gstplay/player.c: (got_stream_length), (main): + * examples/seeking/cdplayer.c: (update_scale): + * examples/seeking/seek.c: (format_value), (update_scale): + * examples/seeking/spider_seek.c: (format_value), (update_scale), + (stop_seek): + Build fixes on AMD64. + +2004-10-25 Zaheer Abbas Merali + + reviewed by: Ronald Bultje + + * sys/v4l/v4l_calls.c: (gst_v4l_get_chan_names): + Fix for some v4l cards which hang in v4lsrc + +2004-10-25 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_remove), + (gst_ogg_demux_push), (gst_ogg_chains_clear): + Make sure to remove the pad when a new chain is + encountered. Set some vars to NULL so we don't try + to reference freed memory. + +2004-10-25 Wim Taymans + + * examples/seeking/Makefile.am: + * examples/seeking/cdplayer.c: (update_scale): + * examples/seeking/chained.c: (unlinked), (new_pad), (main): + * examples/seeking/playbin.c: (make_playerbin_pipeline), + (format_value), (update_scale), (iterate), (start_seek), + (stop_seek), (print_media_info), (play_cb), (pause_cb), (stop_cb), + (print_usage), (main): + Added some more examples, update others. + +2004-10-25 Ronald S. Bultje + + * ext/flac/gstflacdec.c: (gst_flacdec_update_metadata): + * ext/speex/gstspeexdec.c: (speex_dec_chain): + * ext/theora/theoradec.c: (theora_dec_chain): + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + Add codec-name metadata. + +2004-10-25 Takao Fujiwara + + Reviewd by: Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + * ext/alsa/gstalsamixertrack.h: + * po/POTFILES.in: + ALSA mixer track label internationalization (#154054). + +2004-10-25 Ronald S. Bultje + + * ext/theora/theoradec.c: (theora_dec_chain): + Export bitrate as metadata. + +2004-10-25 Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + * ext/alsa/gstalsamixertrack.h: + Fix names, fix loop. + +2004-10-25 Ronald S. Bultje + + * ext/speex/gstspeexdec.c: (gst_speex_dec_init), + (speex_dec_convert): + sinkconvert function so oggdemux can get the file length (totem). + +2004-10-25 James Morrison + + Reviewed by: Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_chunk): + Don't push incomplete packets. + * gst/typefind/gsttypefindfunctions.c: (m4a_type_find): + Fix MPEG-4 audio typefinding. + +2004-10-25 Ronald S. Bultje + + * sys/v4l/Makefile.am: + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l/gstv4lelement.c: (gst_v4lelement_get_type), + (gst_v4lelement_init), (gst_v4lelement_dispose), + (gst_v4lelement_change_state): + * sys/v4l/gstv4lelement.h: + * sys/v4l/gstv4lxoverlay.c: (gst_v4l_xoverlay_open), + (gst_v4l_xoverlay_close), (idle_refresh), + (gst_v4l_xoverlay_set_xwindow_id): + * sys/v4l/gstv4lxoverlay.h: + * sys/v4l/v4l-overlay_calls.c: + * sys/v4l/v4l_calls.h: + * sys/v4l2/Makefile.am: + * sys/v4l2/gstv4l2.c: (plugin_init): + * sys/v4l2/gstv4l2element.c: (gst_v4l2element_get_type), + (gst_v4l2element_init), (gst_v4l2element_dispose), + (gst_v4l2element_change_state): + * sys/v4l2/gstv4l2element.h: + * sys/v4l2/gstv4l2xoverlay.c: (gst_v4l2_xoverlay_open), + (gst_v4l2_xoverlay_close), (idle_refresh), + (gst_v4l2_xoverlay_set_xwindow_id): + * sys/v4l2/gstv4l2xoverlay.h: + * sys/v4l2/v4l2-overlay_calls.c: + * sys/v4l2/v4l2_calls.h: + Remove client-side overlay handling, use the X-server v4l plugin + for that. Nicer overlay, less code. Also make the plugin + compileable without X (but then without overlay, obviously). + Makes xwindowlistener obsolete, should we remove that? + +2004-10-25 Ronald S. Bultje + + * sys/oss/gstosssrc.c: (gst_osssrc_get_time), (gst_osssrc_get), + (gst_osssrc_src_query): + * sys/oss/gstosssrc.h: + OK, so people want offset in DEFAULT. This time, actually fix all + cases. + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_getcaps): + Add FPS properly. + +2004-10-24 Ronald S. Bultje + + * gst/asfdemux/gstasfmux.c: + * gst/avi/gstavimux.c: + Framerate. + +2004-10-24 Ronald S. Bultje + + * sys/v4l2/gstv4l2element.c: (gst_v4l2element_set_property): + Fix properties (channel, norm, frequency). + +2004-10-24 Ronald S. Bultje + + * sys/v4l2/gstv4l2element.c: (gst_v4l2element_get_property): + Flag typo. + * sys/v4l2/v4l2_calls.c: (gst_v4l2_set_defaults): + No warnings. + +2004-10-24 Ronald S. Bultje + + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_clear_format_list): + Fix hang. + +2004-10-24 Ronald S. Bultje + + * sys/v4l2/gstv4l2element.h: + Yet Another Hack (tm) for kernel header borkedness. + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_init), + (gst_v4l2src_v4l2fourcc_to_caps), (gst_v4l2_fourcc_from_structure), + (gst_v4l2src_link), (gst_v4l2src_getcaps), + (gst_v4l2src_change_state): + * sys/v4l2/gstv4l2src.h: + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_capture_init), + (gst_v4l2src_capture_start), (gst_v4l2src_capture_stop): + Fix caps, keep track of state, work. + +2004-10-24 Ronald S. Bultje + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_getcaps): + Quiet. + +2004-10-24 Ronald S. Bultje + + * sys/oss/gstosssrc.c: (gst_osssrc_get): + Don't mix bytes and samples. + +2004-10-24 Ronald S. Bultje + + * ext/ogg/gstoggmux.c: + Basic pad template which accepts OGM tracks, speex, flac, vorbis + and theora. Any is incorrect. + * gst/asfdemux/gstasfmux.c: (gst_asfmux_vidsink_link): + Fix caps. + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_base_init): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_base_init), + (gst_v4lmjpegsrc_init), (gst_v4lmjpegsrc_srcconnect), + (gst_v4lmjpegsrc_getcaps), (gst_v4lmjpegsrc_change_state): + * sys/v4l/gstv4lmjpegsrc.h: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_src_link), (gst_v4lsrc_getcaps), + (gst_v4lsrc_change_state): + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_capture_start), + (gst_v4lmjpegsrc_capture_stop): + Fix caps. Keep track of internal state. Work. + +2004-10-23 Ronald S. Bultje + + * ext/Makefile.am: + Fix the build fixes. + +2004-10-23 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (_find_chain_seek), + (gst_ogg_pad_push): + Check for pad availability before using it. + * ext/ogg/gstoggdemux.c: (_find_chain_process): + Fix parsing of chained ogg. Needs more work on the decoder side. + +2004-10-22 Benjamin Otte + + * gst/spectrum/Makefile.am: + * gst/spectrum/demo-osssrc.c: (spectrum_chain), (main), + (idle_func): + Fix demo and reenable it. Yes, I'm currently playing with audio + analysis tools + +2004-10-22 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + We love it if files that start at zero work too... + +2004-10-22 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_iterate): + Handle files with missing EOS headers. + +2004-10-21 Zaheer Abbas Merali + + * gst/tcp/gsttcpserversink.c: + (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_init_send): + Zero some variables first (need for accept not to return EINVAL) + +2004-10-20 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_pad_push): + * ext/theora/theoradec.c: (theora_dec_sink_convert), + (theora_dec_chain): + * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), + (gst_vorbis_dec_init), (vorbis_dec_convert), (vorbis_dec_chain): + Seeking and querying finetune. + +2004-10-20 Thomas Vander Stichele + + * configure.ac: + * ext/Makefile.am: + * ext/raw1394/Makefile.am: + fix the build + +2004-10-20 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_iterate): + Wrong return. + * gst/playback/Makefile.am: + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init): + * gst/playback/gstplay-marshal.list: + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init): + Fix marshallers. + +2004-10-18 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event): + Silence. + +2004-10-18 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_pad_populate), + (gst_ogg_pad_push): + Yay for non-lineair granulepos in theora. + +2004-10-18 Wim Taymans + + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_video_getcaps), + (gst_dvdec_video_link), (gst_dvdec_push), (gst_dvdec_loop): + * ext/dv/gstdvdec.h: + Make sure we renegotiate aspect ratio when the camera switches. + +2004-10-18 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_pad_push): + Start at zero. + * ext/theora/theoradec.c: (theora_dec_chain): + Skip headers. Bad idea for chained ogg, but fixes seeking. + +2004-10-18 Wim Taymans + + * configure.ac: + I swear, this is the last time I touch this. + +2004-10-18 Ronald S. Bultje + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_pad_populate), + (_read_bos_process), (gst_ogg_demux_iterate), (gst_ogg_pad_new): + Faster seeking. + * ext/theora/theoradec.c: (theora_dec_sink_convert): + Time-to-default conversion. + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + Don't error on unknown packets, just skip. We should probably + read them if we want to support chained ogg. + +2004-10-18 Wim Taymans + + * configure.ac: + Added cdaudio to wrong list. + +2004-10-18 Wim Taymans + + * configure.ac: + Revive cdaudio. + +2004-10-18 Wim Taymans + + * ext/dv/gstdvdec.c: (gst_dvdec_video_getcaps), + (gst_dvdec_video_link), (gst_dvdec_push): + * ext/jpeg/gstsmokeenc.c: (gst_smokeenc_class_init), + (gst_smokeenc_resync), (gst_smokeenc_chain): + Fix mimetype on smoke encoder. + Add aspect ratio to dvdec. Not sure if these + values are correct though.... + +2004-10-18 Wim Taymans + + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_class_init): + Fix vorbis property descriptions and ranges. + +2004-10-18 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_iterate): + Really do nothing when no data is available. + Go to the playing state when the stream is not seekable + instead of failing. + +2004-10-18 Wim Taymans + + * ext/cdaudio/gstcdaudio.c: (_do_init), (gst_cdaudio_base_init), + (gst_cdaudio_get_event_masks), (gst_cdaudio_send_event), + (gst_cdaudio_query), (plugin_init), (cdaudio_uri_get_type), + (cdaudio_uri_get_protocols), (cdaudio_uri_get_uri), + (cdaudio_uri_set_uri), (cdaudio_uri_handler_init): + Added uri handler for cd:// + Port to new API. + +2004-10-18 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (find_compatibles), (close_pad_link), + (try_to_link_1), (no_more_pads), (close_link), (type_found): + * gst/playback/gstplaybasebin.c: (gen_preroll_element), + (remove_prerolls), (unknown_type), (add_element_stream), + (new_decoded_pad), (setup_source), (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_link_stream): + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_vis_element), (remove_sinks), (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), + (gst_stream_info_get_type), (gst_stream_info_class_init), + (gst_stream_info_init), (gst_stream_info_new), + (gst_stream_info_dispose), (stream_info_mute_pad), + (gst_stream_info_set_property), (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + Add sink padtemplate to decodebin. + Added some more comments. + Make queue size configurable in playbasebin. + Added possibility to use elements as sinks (ex cdaudio). + +2004-10-15 Wim Taymans + + * ext/speex/gstspeexenc.c: (gst_speexenc_class_init), + (gst_speexenc_chain): + Fix speex timestamps so that it gets muxed properly. + +2004-10-15 Wim Taymans + + * ext/raw1394/gstdv1394src.c: (gst_dv1394src_get_type), + (gst_dv1394src_base_init), (gst_dv1394src_class_init), + (gst_dv1394src_init), (gst_dv1394src_dispose), + (gst_dv1394src_iso_receive), (gst_dv1394src_discover_avc_node), + (gst_dv1394src_change_state), (gst_dv1394src_get_event_mask), + (gst_dv1394src_event), (gst_dv1394src_get_formats), + (gst_dv1394src_convert), (gst_dv1394src_get_query_types), + (gst_dv1394src_query), (gst_dv1394src_uri_get_type), + (gst_dv1394src_uri_get_protocols), (gst_dv1394src_uri_get_uri), + (gst_dv1394src_uri_set_uri), (gst_dv1394src_uri_handler_init): + * ext/raw1394/gstdv1394src.h: + Added conversion/query functions. + Update buffer timestamps, + Added signals. + Added uri dv:// so it might play from the firewire in playbin. + Fix a possible leak. + Added debugging. + +2004-10-15 Wim Taymans + + * ext/raw1394/gstdv1394src.c: (gst_dv1394src_class_init), + (gst_dv1394src_init), (gst_dv1394src_set_property), + (gst_dv1394src_get_property), (gst_dv1394src_iso_receive), + (gst_dv1394src_discover_avc_node), (gst_dv1394src_change_state): + * ext/raw1394/gstdv1394src.h: + Added AV/C VTR control support needed for some cameras. + Added automatic port detection. + Added properties for selecting the channel. + The configure.ac script is not yet updated to reflect the + new libavc1394 and librom1394 dependencies. + +2004-10-15 Wim Taymans + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (qtdemux_parse), (gst_qtdemux_handle_esds): + An esds box is not a container. + Fix parsing of mp4v boxes. + Do not try to renegotiate fps for each frame. Need to + find a better method. This should fix mp4 playback. + +2004-10-14 David Schleef + + * configure.ac: update for swfdec-0.3 and liboil-0.2 + * ext/swfdec/gstswfdec.c: update for swfdec-0.3 + * ext/swfdec/gstswfdec.h: same + * gst/videofilter/gstvideobalance.c: update for liboil-0.2 + * gst/videotestsrc/videotestsrc.c: same + +2004-10-14 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_remove_client_link), + (is_sync_frame), (gst_multifdsink_new_client), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_change_state): + Turn warnings into info. + Don't allow a state change in the streaming thread. + +2004-10-14 Thomas Vander Stichele + + * ext/vorbis/oggvorbisenc.c: + * ext/vorbis/vorbisdec.c: + fix template sample rate + +2004-10-13 Wim Taymans + + * ext/mad/gstmad.c: (gst_mad_check_caps_reset), (gst_mad_chain): + Decoding the header first fixes some problems in resyncing + in more mp3s. + +2004-10-12 Wim Taymans + + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_vis_element), (remove_sinks), (setup_sinks): + Added vis plugin support, need to configure the vis + element to activate it. + +2004-10-12 Ronald S. Bultje + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_get), + (gst_gnomevfssrc_srcpad_query), (gst_gnomevfssrc_srcpad_event): + Some debug. + * gst/avi/gstavidemux.c: (gst_avi_demux_reset), + (gst_avi_demux_handle_src_event), (gst_avi_demux_read_superindex), + (gst_avi_demux_read_subindexes), (gst_avi_demux_add_stream), + (gst_avi_demux_stream_index), (gst_avi_demux_skip), + (gst_avi_demux_sync), (gst_avi_demux_stream_scan), + (gst_avi_demux_massage_index), (gst_avi_demux_stream_header): + * gst/avi/gstavidemux.h: + Support for openDML-2.0 indx/ix## chunks. Support for broken index + recovery (where, if part of the index is broken, we will still read + the rest of the index and recover the broken part by stream + scanning). More broken media support. EOS workarounds. General AVI + braindamage headache recovery. Aspirin included. + +2004-10-11 Ronald S. Bultje + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_open), + (cdparanoia_event), (cdparanoia_query): + Get rid of hideous lead-in. + +2004-10-11 Wim Taymans + + * gst/playback/gstplaybasebin.c: (setup_source): + Wrong var used to get g_list_next. + +2004-10-11 Ronald S. Bultje + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_class_init), + (cdparanoia_get), (cdparanoia_open): + Report discid as metadata, add duration. + +2004-10-11 Wim Taymans + + * gst/playback/gstplaybasebin.c: (setup_source): + Cleanup the previous pipeline a little earlier for the + case that a source element provides raw data. + +2004-10-11 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_chain): + reset v1 tag offset when there is no v1 tag. Fixes id3demux always + consuming the last 128 bytes, even though it was valid mp3 data. + +2004-10-10 Zaheer Abbas Merali + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_palette_to_caps), + (gst_v4lsrc_getcaps), (gst_v4lsrc_get): + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay): + Change g_warnings to GST_WARNING_OBJECT and fix colourspace issue + +2004-10-10 Zaheer Abbas Merali + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_src_link), (gst_v4lsrc_getcaps): + Fix for webcams that support only specific width or height + +2004-10-09 Tim-Philipp Müller + + Reviewed by: Ronald S. Bultje + + * gst/wavenc/gstwavenc.c: (gst_wavenc_stop_file): + Fix wrong discont event setup (fixes #154967). + +2004-10-09 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst/auparse/gstauparse.c: (gst_auparse_chain): + Error out on invalid data (fixes #154807). + +2004-10-09 Tim-Philipp Müller + + Reviewed by: Ronald S. Bultje + + * ext/dvdread/dvdreadsrc.c: (_read): + Make titles > 0 work again (fixes #154834). + +2004-10-09 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_template_caps): + WMV3 missing in template caps. + +2004-10-09 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_massage_index): + OK, so the original code was too strict. It makes random AVI files + hang for seconds upon opening, which is unacceptable and is far + beyond the original goal of getting multiple chunks for one-chunk + sounc stream files. So now do just that. + +2004-10-09 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (setup_source), + (gst_play_base_bin_change_state): + Actually clean up streaminfo if output fails. This would trigger + if, for example, there was no CD in the drive. No preroll, so + a streaminfo structure is created, but the subsequent state change + of the thread fails. + * gst/playback/gstplaybin.c: (gst_play_bin_change_state): + Don't change state if parent failed. + +2004-10-08 Ronald S. Bultje + + * gst/playback/gstplaybin.c: (gst_play_bin_class_init), + (gst_play_bin_init), (gst_play_bin_get_property), (handoff), + (gen_video_element), (remove_sinks): + Add small bits of code for screenshot handling. + +2004-10-08 Wim Taymans + + * gst/playback/gstplaybin.c: (gst_play_bin_set_property), + (gen_video_element), (gen_audio_element), (setup_sinks): + Don't assume the user provided sinks are named "sink"... + +2004-10-08 Wim Taymans + + * gst/playback/gstplaybasebin.c: (gen_preroll_element), + (unknown_type), (setup_source), (gst_play_base_bin_remove_element), + (gst_play_base_bin_link_stream): + Do not try to autoplug sources that generate raw streams like + cdparanoia. + disconnect the preroll overrun signal when we don't need it anymore. + +2004-10-08 Milosz Derezynski + + * ext/cdparanoia/gstcdparanoia.c: (_do_init), + Added reworked patch from #154903 from milosz derezynski (deadchip). + +2004-10-08 Wim Taymans + + * ext/cdparanoia/gstcdparanoia.c: (_do_init), + (cdparanoia_base_init), (cdparanoia_class_init), (cdparanoia_init), + (cdparanoia_dispose), (cdparanoia_get), (cdparanoia_change_state), + (cdparanoia_convert), (cdparanoia_uri_get_type), + (cdparanoia_uri_get_protocols), (cdparanoia_uri_get_uri), + (cdparanoia_uri_set_uri), (cdparanoia_uri_handler_init): + * ext/cdparanoia/gstcdparanoia.h: + This adds the cdda:// uri. + +2004-10-08 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (find_compatibles), (close_pad_link), + (try_to_link_1), (no_more_pads), (close_link), (type_found): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (unknown_type), (gst_play_base_bin_remove_element), + (gst_play_base_bin_link_stream): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_init), + (gst_play_bin_set_property), (gen_video_element), + (gen_audio_element), (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), + (gst_stream_info_get_type), (gst_stream_info_class_init), + (gst_stream_info_init), (gst_stream_info_new), + (gst_stream_info_dispose), (stream_info_mute_pad), + (gst_stream_info_set_property), (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + Reuse the audio and video bins. + Some internal cleanups in the stream selection code. + +2004-10-08 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_sink_link), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link), + (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): + * sys/xvimage/xvimagesink.h: Reverting Ronald's changes as the issue is + not coming from those elements. Moreover these elements should not keep + the xid they have been given when in NULL state. + +2004-10-07 Ronald S. Bultje + + * sys/ximage/ximagesink.c: (gst_ximagesink_sink_link), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link), + (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): + * sys/xvimage/xvimagesink.h: + Actually only create a new toplevel window if we're not gonna + embed it right after. + +2004-10-07 Wim Taymans + + * gst/playback/gstplaybasebin.c: (play_base_bin_mute_pad), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream): + * gst/playback/gstplaybin.c: (setup_sinks): + Implement muting/unmuting of streams, mute streams that are not + used. + +2004-10-07 Wim Taymans + + * gst/typefind/gsttypefindfunctions.c: (ac3_type_find), + (plugin_init): + Added lame audio/x-ac3 typefind function. + +2004-10-06 Thomas Vander Stichele + + * configure.ac: + bump nano to cvs + +=== release 0.8.5 === + +2004-10-06 Thomas Vander Stichele + + * NEWS: + * RELEASE: + * configure.ac: + releasing 0.8.5, "Take You On" + +2004-10-06 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (find_compatibles), (close_pad_link), (try_to_link_1), (new_pad), + (no_more_pads), (close_link), (type_found): + * gst/playback/gstplaybasebin.c: (new_decoded_pad): + * gst/playback/gstplaybin.c: (gen_video_element): + Do not signal the no_more_pads after the first pad when + we are plugging a non dynamic element with multiple + output pads (like swfdec, dvdec, ...). + +2004-10-06 Thomas Vander Stichele + + * configure.ac: + bump for prerelease + +2004-10-06 Stephane Loeuillet + + * gst/wavparse/gstwavparse.c: + add ATRAC3 to STATIC CAPS to fix a warning + + * gst/matroska/ebml-read.c: + * gst-libs/gst/riff/riff-read.c: + fix typos + +2004-10-06 Stephane Loeuillet + + * gst-libs/gst/riff/riff-media.c: + generate caps for ATRAC3 audio streams + + * gst/realmedia/rmdemux.c: + generate caps for ATRAC3 audio streams + +2004-10-06 Stephane Loeuillet + + * gst/wavparse/Makefile.am + * gst/wavparse/riff.h + * gst/wavparse/wavparse.vcproj + riff.h removal (unused and duplication with riff-ids.h) + +2004-10-06 Stephane Loeuillet + + * gst/wavparse/gstwavparse.h + remove duplicated defines for audio codec codes + + * gst-libs/gst/riff/riff-ids.h + * gst/wavenc/riff.h: + add "4CC" code for ATRAC3 audio streams + add "4CC" code for ITU_G721_ADPCM (unused for now) + +2004-10-06 Wim Taymans + + * gst/flx/gstflxdec.c: (gst_flxdec_init), (gst_flxdec_loop): + Actually _do_ negotiation. Pass gdouble as arg instead + of guint64 for the framerate. + +2004-10-06 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (find_compatibles), (close_pad_link), (try_to_link_1), + (no_more_pads), (close_link), (type_found): + * gst/playback/gstplaybasebin.c: (new_decoded_pad): + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element): + Set state on newly added element to READY so that negotiation + can happen ASAP. + Addes some more debug info. + Do not try to plug pads with multiple caps structures or ANY + because it is too dangerous since we do not do dynamic + replugging. + +2004-10-06 Thomas Vander Stichele + + written by: Gora Mohanty + + * po/LINGUAS: + * po/or.po: + add Oriya translation + +2004-10-05 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_massage_index): + Prevent overwrite of size member. Makes audio sound crappy. + +2004-10-05 Stephane Loeuillet + + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + Add rmvb to the list of known RealMedia extensions + +2004-10-05 Wim Taymans + + * ext/libmng/gstmngdec.c: (gst_mngdec_loop), (mngdec_error), + (mngdec_openstream), (mngdec_closestream), + (mngdec_handle_sink_event), (mngdec_readdata), + (mngdec_gettickcount), (mngdec_settimer), (mngdec_processheader), + (mngdec_getcanvasline), (mngdec_refresh), + (gst_mngdec_change_state): + Set the framerate correctly. + +2004-10-04 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_massage_index): + There was something wrong with the index massaging. + +2004-10-04 Wim Taymans + + * ext/jpeg/gstjpeg.c: (smoke_type_find), (plugin_init): + * ext/jpeg/gstsmokedec.c: (gst_smokedec_init), + (gst_smokedec_chain): + * ext/jpeg/gstsmokedec.h: + * ext/jpeg/gstsmokeenc.c: (gst_smokeenc_class_init), + (gst_smokeenc_init), (gst_smokeenc_resync), (gst_smokeenc_chain): + * ext/jpeg/gstsmokeenc.h: + * ext/jpeg/smokecodec.c: (smokecodec_encode_new), + (smokecodec_decode_new), (smokecodec_info_free), + (smokecodec_set_quality), (smokecodec_get_quality), + (smokecodec_set_threshold), (smokecodec_get_threshold), + (smokecodec_set_bitrate), (smokecodec_get_bitrate), + (find_best_size), (abs_diff), (put), (smokecodec_encode_id), + (smokecodec_encode), (smokecodec_parse_id), + (smokecodec_parse_header), (smokecodec_decode): + * ext/jpeg/smokecodec.h: + * ext/jpeg/smokeformat.h: + Updated smoke, new bitstream, allows embedding in ogg. + +2004-10-04 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_event): + Fix seeking in some files. All this code is no longer needed (and + actually breaks stuff) because we now synchronize the full index + right when reading the header. + +2004-10-04 Wim Taymans + + * configure.ac: + configure update for libmng. + +2004-10-04 Wim Taymans + + * ext/libmng/Makefile.am: + * ext/libmng/gstmng.c: (plugin_init): + * ext/libmng/gstmng.h: + * ext/libmng/gstmngdec.c: (gst_mngdec_get_type), + (gst_mngdec_base_init), (gst_mngdec_class_init), + (gst_mngdec_sinklink), (gst_mngdec_init), (gst_mngdec_src_getcaps), + (gst_mngdec_loop), (gst_mngdec_get_property), + (gst_mngdec_set_property), (mngdec_error), (mngdec_openstream), + (mngdec_closestream), (mngdec_handle_sink_event), + (mngdec_readdata), (mngdec_gettickcount), (mngdec_settimer), + (mngdec_processheader), (mngdec_getcanvasline), (mngdec_refresh), + (gst_mngdec_change_state): + * ext/libmng/gstmngdec.h: + * ext/libmng/gstmngenc.c: (gst_mngenc_get_type), + (mng_caps_factory), (raw_caps_factory), (gst_mngenc_base_init), + (gst_mngenc_class_init), (gst_mngenc_sinklink), (gst_mngenc_init), + (gst_mngenc_chain), (gst_mngenc_get_property), + (gst_mngenc_set_property): + * ext/libmng/gstmngenc.h: + Added basic MNG decoder. Needs more work. The encoder does + not work yet. + +2004-10-04 Ronald S. Bultje + + * gst/realmedia/rmdemux.c: (gst_rmdemux_handle_sink_event), + (gst_rmdemux_loop), (gst_rmdemux_add_stream), + (gst_rmdemux_parse_mdpr), (gst_rmdemux_dump_mdpr): + Don't hang on length=0 chunks. Some negotiation fixes. Signal + no-more-pads. + +2004-10-04 Thomas Vander Stichele + + * configure.ac: + you need at least 1.0.4 of speex + +2004-10-04 Iain + + * ext/speex/gstspeexdec.h: Revert the includes changes. + + * ext/speex/gstspeexenc.[ch]: Revert the includes changes. + +2004-09-30 Iain + + * sys/sunaudio/gstsunaudio.c (gst_sunaudiosink_open): Use the device + found during init or set as a property instead of hardcoding /dev/audio + +2004-10-04 Ronald S. Bultje + + * gst/realmedia/rmdemux.c: (gst_rmdemux_class_init), + (gst_rmdemux_init), (gst_rmdemux_handle_sink_event), + (gst_rmdemux_loop), (gst_rmdemux_add_stream), (re_hexdump_bytes), + (re_dump_pascal_string), (gst_rmdemux_dump__rmf), + (gst_rmdemux_dump_prop), (gst_rmdemux_parse_mdpr), + (gst_rmdemux_dump_mdpr), (gst_rmdemux_dump_indx), + (gst_rmdemux_dump_data): + Use debug category, fix EOS handling. filesrc ! rmdemux now + works. + +2004-10-04 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index), + (gst_avi_demux_stream_scan), (sort), (gst_avi_demux_massage_index), + (gst_avi_demux_stream_header), (gst_avi_demux_stream_data): + Improve allocation, cutting and sorting of the index. How takes a + few seconds instead of minutes. + +2004-10-03 Christophe Fergeau + + * gst/realmedia/rmdemux.c: (gst_rmdemux_parse_mdpr): + fixed compilation + +2004-10-02 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_template_caps): + Add wing commander format mimetype/fourccs. + * gst/avi/gstavidemux.c: (gst_avi_demux_massage_index): + Don't crash if some value is 0. + +2004-10-02 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_template_caps): + Add DIB fourcc (raw, palettized 8-bit RGB). + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_vids_with_data): + Oops, fix strf_data reading bug. + * gst/avi/gstavidemux.c: (gst_avi_demux_add_stream): + Use a non-NULL tag. + * gst/qtdemux/qtdemux.c: (qtdemux_parse_trak): + Time for hacks. Sorry Dave. At least one quicktime movie (a + trailer) that I've encountered contains multiple video tracks. + One of those is the actual video track, the other are one-frame + tracks (images). Unfortunately, the number of frames according + to the trak header is 1 for each, so that doesn't help. So + instead, I look at the duration and discard tracks with a + duration shorter than 20% of the length of the stream. Better + than nothing. + +2004-10-01 Christian Schaller + + * ext/ivorbis/vorbis.c: + Patch from Phil Blundell (Bug 152341) + +2004-10-01 Wim Taymans + + * ext/speex/gstspeexdec.c: (gst_speex_dec_class_init), + (speex_dec_get_formats), (speex_dec_convert), + (speex_dec_src_query), (speex_dec_src_event), (speex_dec_event), + (speex_dec_chain), (gst_speexdec_get_property), + (gst_speexdec_set_property): + Small cleanups. + +2004-10-01 Wim Taymans + + * gst/wavparse/gstwavparse.c: (gst_wavparse_class_init), + (gst_wavparse_stream_init), (gst_wavparse_fmt), + (gst_wavparse_other), (gst_wavparse_loop), + (gst_wavparse_pad_convert), (gst_wavparse_pad_query), + (gst_wavparse_srcpad_event): + * gst/wavparse/gstwavparse.h: + Added some more debugging info. + Fix the case where the length of the file is 0. + Make sure we seek to sample borders. + +2004-10-01 Wim Taymans + + * gst/playback/README: + * gst/playback/gstdecodebin.c: (gst_decode_bin_factory_filter), + (gst_decode_bin_init), (find_compatibles), (close_pad_link), + (try_to_link_1), (no_more_pads), (close_link), (type_found): + Add some debug info to decodebin, update README + +2004-10-01 Ronald S. Bultje + + * ext/dvdnav/dvdnavsrc.c: (dvdnav_handle_navigation_event): + Don't use g_print(); use GST_DEBUG(). + +2004-10-01 Ronald S. Bultje + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_queue_pads): + Handle EOS properly. + +2004-10-01 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * ext/faad/gstfaad.c: (gst_faad_init), (gst_faad_sinkconnect), + (gst_faad_chain), (gst_faad_change_state): + * ext/faad/gstfaad.h: + Allow playback of raw (unframed) MPEG AAC files (#148993). + +2004-10-01 Sebastien Cote + + Reviewed by: Ronald S. Bultje + + * gst/wavparse/gstwavparse.c: (gst_wavparse_fmt): + Throw error if we didn't recognize the stream. Fixes #152289. + +2004-10-01 Ronald S. Bultje + + * gst/videoscale/gstvideoscale.c: (gst_videoscale_link): + Fix negotiation. + +2004-10-01 Francis Labonte + + Reviewed by: Ronald S. Bultje + + * gst/wavparse/gstwavparse.c: (gst_wavparse_fmt): + Fix memleak. + +2004-10-01 Balamurali Viswanathan + + Reviewed by: Ronald S. Bultje + + * sys/sunaudio/gstsunaudio.c: (gst_sunaudiosink_setparams): + Solve #152805. + * sys/sunaudio/gstsunmixer.c: (gst_sunaudiomixer_set_mute): + Solve 152806. + +2004-10-01 Ronald S. Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_audio_caps_with_data): + Add codec_data handling (like asfdemux used to do). + * gst/asfdemux/gstasf.c: (plugin_init): + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_base_init), + (gst_asf_demux_add_audio_stream), (gst_asf_demux_add_video_stream): + Use riff-media for caps creation instead of our own (mostly + broken) copy of its functions. + +2004-10-01 Ronald S. Bultje + + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_try_capture): + Don't actually error out if we get another return value than + -EINVAL. Opposite to what I first thought, drivers have random + return values for this, although -EINVAL is the expected return + value. Since this is not fatal, we shouldn't use + GST_ELEMENT_ERROR() but just GST_ERROR_OBJECT(). + +2004-10-01 Ronald S. Bultje + + * ext/dvdread/dvdreadsrc.c: (dvdreadsrc_class_init), + (dvdreadsrc_init), (dvdreadsrc_dispose), (dvdreadsrc_set_property), + (dvdreadsrc_get_property), (_open), (_seek), (_read), + (dvdreadsrc_get), (dvdreadsrc_open_file), + (dvdreadsrc_change_state): + Fix. Don't do one big huge loop around the whole DVD, that will + cache all data and thus eat sizeof(dvd) (several GB) before we + see something. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): + Actually NULL'ify event after using it. + * gst/matroska/ebml-read.c: (gst_ebml_read_use_event), + (gst_ebml_read_handle_event), (gst_ebml_read_element_id), + (gst_ebml_read_element_length), (gst_ebml_read_element_data), + (gst_ebml_read_seek), (gst_ebml_read_skip): + Handle events. + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_base_init), + (gst_dvd_demux_init), (gst_dvd_demux_get_audio_stream), + (gst_dvd_demux_get_subpicture_stream), (gst_dvd_demux_plugin_init): + Fix timing (this will probably break if I seek using menus, but + I didn't get there yet). VOBs and normal DVDs should now work. + Add a mpeg2-only pad with high rank so this get autoplugged for + MPEG-2 movies. + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_base_init), + (gst_mpeg_demux_class_init), (gst_mpeg_demux_init), + (gst_mpeg_demux_new_output_pad), (gst_mpeg_demux_get_video_stream), + (gst_mpeg_demux_get_audio_stream), + (gst_mpeg_demux_get_private_stream), (gst_mpeg_demux_parse_packet), + (gst_mpeg_demux_parse_pes), (gst_mpeg_demux_plugin_init): + Use this as second rank for MPEG-1 and MPEG-2. Still use this for + MPEG-1 but use dvddemux for MPEG-2. + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init), + (gst_mpeg_parse_init), (gst_mpeg_parse_new_pad), + (gst_mpeg_parse_parse_packhead): + Timing. Only add pad template if it exists. Add sink template from + class and not from ourselves. This means we will always use the + correct sink template even if it is not the one defined in this + file. + +2004-09-29 Wim Taymans + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_packet), + (gst_mpeg_demux_parse_pes): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_parse_packhead): + Fix playback of mpeg again, timestamps where screwed up by + patch 1.61. + +2004-09-29 Ronald S. Bultje + + * ext/flac/gstflacdec.c: (gst_flacdec_src_query): + Only return true if we actually filled something in. Prevents + player applications from showing a random length for flac files. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_class_init), + (gst_riff_read_use_event), (gst_riff_read_handle_event), + (gst_riff_read_seek), (gst_riff_read_skip), (gst_riff_read_strh), + (gst_riff_read_strf_vids_with_data), + (gst_riff_read_strf_auds_with_data), (gst_riff_read_strf_iavs): + OK, ok, so I implemented event handling. Apparently it's normal + that we receive random events at random points without asking + for it. + * gst/avi/gstavidemux.c: (gst_avi_demux_reset), + (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), + (gst_avi_demux_handle_src_event), (gst_avi_demux_stream_index), + (gst_avi_demux_sync), (gst_avi_demux_stream_scan), + (gst_avi_demux_massage_index), (gst_avi_demux_stream_header), + (gst_avi_demux_handle_seek), (gst_avi_demux_process_next_entry), + (gst_avi_demux_stream_data), (gst_avi_demux_loop): + * gst/avi/gstavidemux.h: + Implement non-lineair chunk handling and subchunk processing. + The first solves playback of AVI files where the audio and video + data of individual buffers that we read are not synchronized. + This should not happen according to the wonderful AVI specs, but + of course it does happen in reality. It is also a prerequisite for + the second. Subchunk processing allows us to cut chunks in small + pieces and process each of these pieces separately. This is + required because I've seen several AVI files with incredibly large + audio chunks, even some files with only one audio chunk for the + whole file. This allows for proper playback including seeking. + This patch is supposed to fix all AVI A/V sync issues. + * gst/flx/gstflxdec.c: (gst_flxdec_class_init), + (flx_decode_chunks), (flx_decode_color), (gst_flxdec_loop): + Work. + * gst/modplug/gstmodplug.cc: + Proper return value setting for the query() function. + * gst/playback/gstplaybasebin.c: (setup_source): + Being in non-playing state (after, e.g., EOS) is not necessarily + a bad thing. Allow for that. This fixes playback of short files. + They don't actually playback fully now, because the clock already + runs. This means that small files (<500kB) with a small length + (<2sec) will still not or barely play. Other files, such as mod + or flx, will work correctly, however. + +2004-09-28 Wim Taymans + + * ext/speex/gstspeex.c: (plugin_init): + * ext/speex/gstspeexdec.c: (gst_speex_dec_base_init), + (gst_speex_dec_class_init), (speex_dec_get_formats), + (speex_get_event_masks), (speex_get_query_types), + (gst_speex_dec_init), (speex_dec_convert), (speex_dec_src_query), + (speex_dec_src_event), (speex_dec_event), (speex_dec_chain), + (gst_speexdec_get_property), (gst_speexdec_set_property), + (speex_dec_change_state): + * ext/speex/gstspeexdec.h: + * ext/speex/gstspeexenc.c: (gst_speexenc_get_formats), + (gst_speexenc_get_type), (speex_caps_factory), (raw_caps_factory), + (gst_speexenc_base_init), (gst_speexenc_class_init), + (gst_speexenc_sinkconnect), (gst_speexenc_convert_src), + (gst_speexenc_convert_sink), (gst_speexenc_get_query_types), + (gst_speexenc_src_query), (gst_speexenc_init), + (gst_speexenc_get_tag_value), (comment_init), (comment_add), + (gst_speexenc_metadata_set1), (gst_speexenc_set_metadata), + (gst_speexenc_setup), (gst_speexenc_buffer_from_data), + (gst_speexenc_push_buffer), (gst_speexenc_set_header_on_caps), + (gst_speexenc_chain), (gst_speexenc_get_property), + (gst_speexenc_set_property), (gst_speexenc_change_state): + * ext/speex/gstspeexenc.h: + Rewrote speex encoder, make sure it can be embedded in ogg. + Implemented speex decoder. + +2004-09-28 Christian Schaller + + * configure.ac: + Remove kioslave plugin. Markey is brewing a new working one + * ext/Makefile.am: Remove kioslave plugin + * ext/kio: remove + * gst-plugins.spec.in: remove kio plugin from spec + +2004-09-27 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_remove_client_link), + (is_sync_frame), (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_new_client), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients): + * gst/tcp/gstmultifdsink.h: + Make syncing to keyframes actually work for new clients and lagging + clients. + +2004-09-26 Benjamin Otte + + * gst/debug/gstnavigationtest.c: (gst_navigationtest_class_init), + (gst_navigationtest_handle_src_event), (draw_box_planar411), + (gst_navigationtest_planar411), (gst_navigationtest_change_state): + * gst/debug/gstnavigationtest.h: + make navigationtest display button-press and button-release events + +2004-09-26 Iain + + * gst/interleave/interleave.c (all_channels_new_media): Checks if all + the channels have received a new media event. + (interleave_buffered_loop): Compresses a new media event on all + channels into one. + +2004-09-26 Iain + + * gst/wavenc/gstwavenc.c (gst_wavenc_chain): Company says we need to + call the sinkpad's default event handler and not the srcpads. He also + says this is confusing :) + (gst_wavenc_stop_file): Company says that seek events only go upstream + we should send a discontinuous downstream instead. + +2004-09-25 Christian Schaller + + * Update SPEC file to be usable in conjunction with Fedora Core, + Fedora.us and freshrpms packages + * Fix typo in multifilesrc test Makefile + +2004-09-24 Wim Taymans + + * gst/playback/gstplaybasebin.c: (new_decoded_pad): + Only signal the no_more_pads signal when we have + added the stream to our list. + +2004-09-24 Wim Taymans + + * gst/playback/gstplaybasebin.c: (remove_prerolls), + (new_decoded_pad): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (setup_sinks): + Don't try to preroll or decode more than one audio/video + track. + +2004-09-24 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_change_state): + Throw error if we failed to find a suitable output. This should + throw an error if we successfully set up a pipeline (e.g. because + we recognized a media file) but found no decodable streams in it + (e.g. because it contains only media stream types for which we + have no decoders, or because it's not a media type). + +2004-09-23 Ronald S. Bultje + + * ext/dirac/Makefile.am: + * ext/dirac/gstdirac.cc: + * ext/dirac/gstdiracdec.cc: + * ext/dirac/gstdiracdec.h: + Do something. Don't actually know if this works because I don't + have a demuxer yet. + * ext/gsm/gstgsmdec.c: (gst_gsmdec_getcaps): + Add channels=1 to caps returned from _getcaps(). + * ext/ogg/gstogmparse.c: (gst_ogm_audio_parse_get_type), + (gst_ogm_video_parse_get_type), (gst_ogm_audio_parse_base_init), + (gst_ogm_video_parse_base_init), (gst_ogm_parse_init), + (gst_ogm_audio_parse_init), (gst_ogm_video_parse_init), + (gst_ogm_parse_sink_convert), (gst_ogm_parse_chain), + (gst_ogm_parse_change_state): + Separate between audio/video so ogmaudioparse actually uses the + audio pad templates. Both audio and video work now, including + autoplugging. Also use sometimes-srcpad hack. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): + Handle events better. Don't hang on infinite loops. + * gst/avi/gstavidemux.c: (gst_avi_demux_class_init), + (gst_avi_demux_init), (gst_avi_demux_reset), + (gst_avi_demux_src_convert), (gst_avi_demux_handle_src_query), + (gst_avi_demux_stream_header), (gst_avi_demux_stream_data), + (gst_avi_demux_change_state): + * gst/avi/gstavidemux.h: + Improve A/V sync. Still not perfect. + * gst/matroska/ebml-read.c: (gst_ebml_read_seek), + (gst_ebml_read_skip): + Handle events better. + * gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event), + (gst_qtdemux_loop_header), (qtdemux_parse_trak), + (qtdemux_audio_caps): + Add IMA4. Improve event handling. Save offset after a seek when + the headers are at the end of the file so that we don't end up in + an infinite loop. + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): + Add low-priority typefind support for files with no length. + +2004-09-23 Zaheer Abbas Merali + + * testsuite/multifilesink/Makefile.am: + fix typo + +2004-09-22 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_destroy): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls): Fix + mistakes from thaytan's patches. + +2004-09-23 Jan Schmidt + + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_destroy): + For completeness, XSync in the destroy function as xvimage does. + +2004-09-23 Jan Schmidt + + * ext/gdk_pixbuf/pixbufscale.c: (gst_pixbufscale_getcaps): + Correct caps negotiation + * gst/volume/gstvolume.c: (volume_chain_float), + (volume_chain_int16): + Modify debug output to be little more informative + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_destroy): + Add XSync calls after detaching from the shared memory segment to + avoid a crash. + +2004-09-22 Zaheer Abbas Merali + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_init), + (gst_ogg_mux_next_buffer), (gst_ogg_mux_loop): + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_init), + (gst_vorbisenc_chain): + * ext/vorbis/vorbisenc.h: + remove explicit newmedia support from oggmux and vorbisenc + add debug category to vorbisenc + * gst/multifilesink/gstmultifilesink.c: + (gst_multifilesink_class_init), (gst_multifilesink_init), + (gst_multifilesink_dispose), (gst_multifilesink_set_location), + (gst_multifilesink_set_property), (gst_multifilesink_next_file), + (gst_multifilesink_handle_event), (gst_multifilesink_chain), + (plugin_init): + * gst/multifilesink/gstmultifilesink.h: + add support for streamheader in multifilesink + +2004-09-22 Ronald S. Bultje + + * gst/asfdemux/gstasfdemux.c: (_read_var_length), (_read_guid), + (gst_asf_demux_process_segment), (gst_asf_demux_handle_data), + (gst_asf_demux_process_chunk), (gst_asf_demux_handle_sink_event): + Prevent infinite loops. More correct error reporting. + * gst/auparse/gstauparse.c: (gst_auparse_chain): + Error out if negotiation fails. + * gst/playback/gstplaybasebin.c: (setup_source), + (gst_play_base_bin_change_state), (gst_play_base_bin_error), + (gst_play_base_bin_found_tag): + Error/tag forwarding. Pre-roll fixes for source errors on state + changes (e.g. "file does not exist") to prevent hangs. + +2004-09-21 Zaheer Abbas Merali + + * testsuite/multifilesink/Makefile.am: + * testsuite/multifilesink/lame_test.c: (gst_newmedia_base_init), + (gst_newmedia_class_init), (gst_newmedia_init), + (gst_newmedia_chain), (gst_newmedia_trigger), (test_format), + (newfile_signal), (test_signal), (main): + * testsuite/multifilesink/multifilesrc_test.c: (main): + * testsuite/multifilesink/oggtheora_test.c: + (gst_newmedia_base_init), (gst_newmedia_class_init), + (gst_newmedia_init), (gst_newmedia_chain), (gst_newmedia_trigger), + (test_format), (newfile_signal), (test_signal), (main): + * testsuite/multifilesink/oggvorbis_test.c: + (gst_newmedia_base_init), (gst_newmedia_class_init), + (gst_newmedia_init), (gst_newmedia_chain), (gst_newmedia_trigger), + (test_format), (newfile_signal), (test_signal), (main): + * testsuite/multifilesink/wavenc_test.c: (gst_newmedia_base_init), + (gst_newmedia_class_init), (gst_newmedia_init), + (gst_newmedia_chain), (gst_newmedia_trigger), (test_format), + (newfile_signal), (test_signal), (main): + New media tests + +2004-09-20 Christian Schaller + + * Fix mikmod license to LGPL as they have relicensed + * Move Dirac and Effectv into LGPL section of README_license + +2004-09-20 Ronald S. Bultje + + * ext/mad/gstmad.c: (gst_mad_check_caps_reset), + (gst_mad_change_state): + Allow for mp3 rate/channels changes. However, only very + conservatively. Reason that we *have* to enable this is smiply + because the mad find_sync() function is not good enough, it will + regularly sync on random data as valid frames and therefore make + us provide random caps as *final* caps of the stream. The best fix + I could think of is to simply require several of the same stream + changes in a row before we change caps. + The actual testcase that works now is # + * ext/ogg/Makefile.am: + * ext/ogg/gstogg.c: (plugin_init): + * ext/ogg/gstogmparse.c: + OGM support (video only for now; I need an audio sample file). + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_base_init), + (gst_asf_demux_process_stream), (gst_asf_demux_video_caps), + (gst_asf_demux_add_video_stream): + WMV extradata. + * gst/playback/gstplaybasebin.c: (unknown_type): + Don't error out on single unknown-types after all. It's wrong. + If we found type of video and audio but not of a subtitle stream, + it will still error out (which is unwanted). Will find a better fix + later on. + * gst/typefind/gsttypefindfunctions.c: (ogmvideo_type_find), + (ogmaudio_type_find), (plugin_init): + OGM support. + +2004-09-20 Johan Dahlin + + * ext/jpeg/gstjpegdec.c (gst_jpegdec_chain): Allocate the buffer + after setting caps. + +2004-09-19 Zaheer Abbas Merali + + * gst/wavenc/gstwavenc.c: (gst_wavenc_init), (gst_wavenc_chain): + * gst/wavenc/gstwavenc.h: + Added newmedia support to wavenc + +2004-09-17 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_fd_has_closed), + (gst_fdset_fd_has_error), (gst_fdset_fd_can_read), + (gst_fdset_fd_can_write), (gst_fdset_wait): + * gst/tcp/gstmultifdsink.c: (gst_client_status_get_type), + (gst_multifdsink_init), (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_get_stats), + (gst_multifdsink_remove_client_link), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_handle_clients), + (gst_multifdsink_close), (gst_multifdsink_change_state): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init), + (gst_tcpserversink_removed): + Small cleanups in fdset.c + Use a hastable to map fd to the client structure for faster + lookup in _remove and get_stats. + Added virtual function to close the fds. + Handle clients even when the select/poll call was unblocked because + of a command. + Implement syncing to keyframe in the recovery procedure. + +2004-09-16 Iain + + * gst/audioconvert/gstaudioconvert.c (_fixate_caps_to_int): Free the + try caps. + +2004-09-15 Ronald S. Bultje + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_get_audio_stream): + Caps are only set if the type of the stream is unknown, but this + is initialized in ->init_stream(), so set to UNKNOWN after calling + ->init_stream() so that capsnego starts. + +2004-09-15 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query), + (gst_avi_demux_stream_data): + Just hardcode for raw audio then. AVI audio sucks. + +2004-09-15 Arwed v. Merkatz + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_audio_caps): + * gst/matroska/matroska-mux.c: (audiosink_templ), + (gst_matroska_mux_audio_pad_link): + * gst/typefind/gsttypefindfunctions.c: (tta_caps), (plugin_init): + Use audio/x-ttafile for tta files and audio/x-tta for raw tta frames. + +2004-09-15 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query), + (gst_avi_demux_stream_data): + Try to fix a/v sync issues. + +2004-09-15 David Schleef + + * configure.ac: remove NASM check, since we don't use it. Update + dirac check to 0.4 + * ext/dirac/gstdiracdec.cc: update to current 0.4 API + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + Initialized variables. + * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), + (gst_qtdemux_loop_header), (qtdemux_parse), (qtdemux_parse_trak), + (gst_qtdemux_handle_esds), (qtdemux_audio_caps): Fix seeking, add + SVQ3 format + +2004-09-15 Ronald S. Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query), + (gst_avi_demux_add_stream), (gst_avi_demux_stream_data): + * gst/avi/gstavidemux.h: + Fix for compressed audio (mp3) timestamp generation. How did this + ever work? + +2004-09-15 Ronald S. Bultje + + * gst/playback/gstplaybin.c: (gst_play_bin_get_property): + Volume is a double not a float. + +2004-09-15 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_remove_client_link), + (gst_multifdsink_handle_clients), (gst_multifdsink_change_state): + Don't close the fd in multifdsink as we didn't open it in the + first place. Some cleanups. + +2004-09-15 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop): + Fix the case where the muxer would mark pages as delta + frames when they are not (vorbis only ogg). + +2004-09-15 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: (state_change), (setup_source), + (gst_play_base_bin_change_state): + Handle the case where we failed to setup a clear pipeline. This + will throw an error (or EOS, another nice case) and if you don't + catch that, the app will wait for the signal forever (and thus + hang). + +2004-09-15 Ronald S. Bultje + + * ext/gnomevfs/gstgnomevfssink.c: + (gst_gnomevfssink_uri_get_protocols): + * ext/gnomevfs/gstgnomevfssrc.c: + (gst_gnomevfssrc_uri_get_protocols): + * ext/gnomevfs/gstgnomevfsuri.c: (gst_gnomevfs_get_supported_uris): + * ext/gnomevfs/gstgnomevfsuri.h: + Use _uri_new() instead of _open(), so it doesn't take as long and + Christophe's computer won't hang. + * gst/playback/gstplaybasebin.c: (unknown_type): + Throw error on unknown media type, so apps actually display it. + +2004-09-14 Brian Cameron + + * gst/playback/gstplaybasebin.c: (queue_overrun), (no_more_pads), + (setup_source), (gst_play_base_bin_set_property), + (gst_play_base_bin_add_element): + * gst/playback/gstplaybin.c: (gst_play_bin_send_event): + Some more work on making sure seeking pauses the pipeline and + that changing the uri actually does something. + +2004-09-17 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_wait): + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_close): + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_init_send), + (gst_tcpserversink_close): + Be a bit more paranoid when freeing memory. + +2004-09-13 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_add_stream), + (qtdemux_parse_trak): + Don't crash by dividing by zero (see sample movie in #126922). + +2004-09-13 Ronald S. Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_audio_caps): + Don't touch non-existing data (fixes crash on file in #140147). + +2004-09-13 Ronald S. Bultje + + * gst/playback/gstplaybasebin.c: + (gst_play_base_bin_dispose), (gst_play_base_bin_set_property): + Handle double disposals, and proper change of URIs. + +2004-09-13 Martin Eikermann + + * gst/mpegstream/gstmpegparse.c: + fix synchronistation for streams recorded from digital PCR + fixes bug #119376 + +2004-09-13 Ronald S. Bultje + + * ext/gnomevfs/Makefile.am: + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_get_type), + (gst_gnomevfssink_dispose), (gst_gnomevfssink_init), + (gst_gnomevfssink_uri_get_type), + (gst_gnomevfssink_uri_get_protocols), + (gst_gnomevfssink_uri_get_uri), (gst_gnomevfssink_uri_set_uri), + (gst_gnomevfssink_uri_handler_init), + (gst_gnomevfssink_set_property), (gst_gnomevfssink_get_property), + (gst_gnomevfssink_open_file), (gst_gnomevfssink_close_file): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_get_type), + (gst_gnomevfssrc_init), (gst_gnomevfssrc_dispose), + (gst_gnomevfssrc_uri_get_type), + (gst_gnomevfssrc_uri_get_protocols), (gst_gnomevfssrc_uri_get_uri), + (gst_gnomevfssrc_uri_set_uri), (gst_gnomevfssrc_uri_handler_init), + (gst_gnomevfssrc_set_property), (gst_gnomevfssrc_get_property), + (gst_gnomevfssrc_open_file), (gst_gnomevfssrc_close_file): + * ext/gnomevfs/gstgnomevfsuri.c: (gst_gnomevfs_get_supported_uris): + * ext/gnomevfs/gstgnomevfsuri.h: + Add URI support to Gnome-VFS plugins. Tries to load a fixed list + of fake URIs to see which this version of Gnome-VFS likes, and + uses that for the Gst-URI interface. Makes playbin support http:// + streams. Also fix up some stupid behaviour in gnomevfssrc. + +2004-09-13 Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_update), + (gst_alsa_mixer_get_volume), (gst_alsa_mixer_set_volume), + (gst_alsa_mixer_set_mute), (gst_alsa_mixer_set_record), + (gst_alsa_mixer_set_option), (gst_alsa_mixer_get_option): + Update mixer (to sync with other sessions) if we try to obtain + a new value. This makes alsamixer work accross applications. + * ext/alsa/gstalsasink.c: (gst_alsa_sink_get_time): + Only call sync functions if we're running, else alsalib asserts. + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query): + Sometimes fails to compile. Possibly a gcc bug. + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element): + Add a reference to an application-provided object, because we lose + this same reference if we add it to the bin. If we don't do this, + we can only use this object once and thus crash if we go from + ready to playing, back to ready and back to playing again. + Also add an audioscale element because several cheap soundcards - + like mine - don't support all samplerates. + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), + (gst_ximagesink_xcontext_clear), (gst_ximagesink_change_state): + Fix wrong order or PAR calls. Makes automatically obtained PAR + from the X server atually being used. + +2004-09-12 David Schleef + + Fixes: #151879, #151881, #151882, #151883, #151884, #151886, + #151887, #152102, #152247. + * examples/indexing/indexmpeg.c: 64-bit warning fixes. + * examples/seeking/cdparanoia.c: same + * examples/seeking/cdplayer.c: same + * examples/seeking/seek.c: same + * examples/seeking/spider_seek.c: same + * examples/seeking/vorbisfile.c: same + * examples/stats/mp2ogg.c: same + * ext/esd/esdsink.c: (gst_esdsink_class_init), + (gst_esdsink_dispose): Dispose of element properly. + * ext/ivorbis/vorbisfile.c: (gst_ivorbisfile_seek): 64-bit warning + fixes. + * ext/nas/nassink.c: (gst_nassink_class_init), + (gst_nassink_dispose): Dispose of element correctly. + * gst/wavenc/gstwavenc.c: (gst_wavenc_chain): Fix leak. + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_destroy): + Fix 64-bit warning. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_destroy): + Fix 64-bit warning. + +2004-09-12 Stephane Loeuillet + + * configure.ac : change speex detection as 1.1.6 now uses + .pc/pkg-config and they changed their headers location. + +2004-09-09 Arwed v. Merkatz + + * gst/matroska/matroska-mux.h: + * gst/matroska/matroska-mux.c: (gst_matroska_mux_reset), + (gst_matroska_mux_start), (gst_matroska_mux_finish), + (gst_matroska_mux_write_data): + Write multiple blocks/frames per cluster. + Write meta-seek information (seek heads). + +2004-09-09 Scott Wheeler + + * gst/gstplaybin.c: (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (gen_audio_element), (gen_audio_element): + Add a volume element / property to the pipeline. + +2004-09-07 Wim Taymans + + * gst/videomixer/videomixer.c: (gst_videomixer_blend_buffers): + Copy timestamps from the master pad to the output buffers. + +2004-09-03 Thomas Vander Stichele + + * ext/raw1394/gstdv1394src.c: + throw errors when applicable + +2004-09-01 Arwed v. Merkatz + + * gst/matroska/ebml-ids.h: + * gst/matroska/ebml-read.c: (gst_ebml_read_date): + * gst/matroska/ebml-write.c: (gst_ebml_write_date): + * gst/matroska/matroska-mux.c: (gst_matroska_mux_finish): + automatically convert unix time <-> ebml time when reading/writing + a date, use gst_ebml_write_uint to write CUETIME, + not gst_ebml_write_date. + * gst/matroska/matroska-ids.h: + * gst/matroska/matroska-mux.c: (gst_matroska_mux_create_uid), + (gst_matroska_mux_reset), (gst_matroska_mux_audio_pad_link), + (gst_matroska_mux_track_header), (gst_matroska_mux_start), + (gst_matroska_mux_write_data): + Write track and segment UIDs, write muxing date, write + TRACKDEFAULTDURATION for TTA audio, write BLOCKDURATION if known. + Create cues for audio only files. + +2004-08-31 Ronald S. Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + Re-commit ALSA switches. + * gst/adder/gstadder.c: (gst_adder_loop): + 64-bit fix (#151416). + * gst/debug/progressreport.c: (gst_progressreport_report): + 64-bit fix (#151419). + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_contents): + 64-bit fix (#151420). + * gst/playback/test3.c: (update_scale): + 64-bit fix (#151421). + +2004-08-31 Thomas Vander Stichele + + * configure.ac: + bump nano to cvs + +=== release 0.8.4 === + +2004-08-02 Thomas Vander Stichele + + * configure.ac: releasing 0.8.4, "Alias" + +2004-08-31 Thomas Vander Stichele + + * ext/theora/Makefile.am: + fix makefile. Fixes #151462. + +2004-08-30 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_free), (gst_fdset_wait): + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_add), + (gst_multifdsink_remove_client_link), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write): + * gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_init_send): + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_init_receive): + Fix some memory leaks. + +2004-08-30 Thomas Vander Stichele + + Patch by: David Schleef + + * configure.ac: + * sys/Makefile.am: + rename our detection macro for V4L2. Fixes #151236. + +2004-08-30 Thomas Vander Stichele + + Patch by: David Schleef + + * configure.ac: + check to define LAMEPRESET. Fixes #151232. + +2004-08-27 David Schleef + + * sys/glsink/glimagesink.c: (gst_glimagesink_ximage_put), + (gst_glimagesink_xwindow_new), (gst_glimagesink_xcontext_get), + (gst_glimagesink_fixate): Move local variable declarations to + make gcc-2.95 happy. + +2004-08-27 Thomas Vander Stichele + + * configure.ac: + bump nano for prerelease + +2004-08-27 David Schleef + + * sys/sunaudio/Makefile.am: Add sunaudiosrc patch from Bala + * sys/sunaudio/gstsunaudiosrc.c: + * sys/sunaudio/gstsunaudiosrc.h: + +2004-08-27 Arwed v. Merkatz + + * gst/matroska/ebml-read.c: (gst_ebml_peed_id), (gst_ebml_read_element_id), + handle EOS correctly + * gst/matroska/matroska-mux.c: (gst_matroska_mux_video_pad_link): + * gst/matroska/matroska-mux.h: + added BITMAPINFOHEADER structure, mux video/x-divx and video/x-xvid in + VFW compatibility mode + +2004-08-27 Thomas Vander Stichele + + patch by: Zaheer Abbas Merali + + * ext/ogg/gstoggmux.c: + * ext/vorbis/vorbisenc.c: + * ext/vorbis/vorbisenc.h: + handle NEWMEDIA + +2004-08-26 Arwed v. Merkatz + + * gst/matroska/ebml-write.c: (gst_ebml_write_float), + fix byte order reversion on little endian machines. + * gst/matroska/matroska-mux.c: (audiosink_templ), + (gst_matroska_mux_audio_pad_link): + add TTA codec to the list of supported codecs. + * gst/matroska/matroska-mux.c: (gst_matroska_mux_init), + (gst_matroska_mux_start), (gst_matroska_mux_finish), + (gst_matroska_mux_write_data): + * gst/matroska/matroska-mux.h: + write segment duration correctly, write muxing app string, fixes bugs + #140897 and #140898. + * gst/matroska/matroska-mux.c: (gst_matroska_mux_loop), + wait for all pads to be negotiated before starting to mux. + +2004-08-26 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_init), (gst_lame_chain): + * ext/lame/gstlame.h: + Added new media support to lame + +2004-08-25 Arwed v. Merkatz + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_parse_blockgroup), + send vorbis headers at the beginning of a stream, fixes bug #141554. + Interpret BLOCKDURATION and set buffer duration accordingly, fixes + bug #148950. + * gst/matroska/matroska-demux.c: (gst_matroska_demux_audio_caps), + (gst_matroska_demux_plugin_init): + * gst/matroska/matroska-ids.h: + enable demuxing of TTA audio streams, fixes bug #148951. + * gst/typefind/gsttypefindfunctions.c: (tta_type_find), (plugin_init), + enable typefinding for TTA audio files, fixes bug #148711. + * ext/xvid/gstxviddec.c: (gst_xviddec_chain), + set XVID_LOWDELAY flag for decoding so xvid always returns an image, + fixes playback of packed bitstream and xvid with bframes, bug #135407. + +2004-08-24 Sebastien Cote + + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head), + (gst_riff_read_element_data), (gst_riff_read_seek), + (gst_riff_read_skip): fix infinite loop in wavparse, fixes bug + #144616, patch reviewed by Ronald and committed by Christophe Fergeau + + +2004-08-23 Iain + + * ext/mad/gstid3tag.c (gst_mad_id3_to_tag_list): Special case COMM + tags. They appear to be handled differently to normal. + (tag_list_to_id3_tag_foreach): Ditto. + +2004-08-22 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop): + Make sure we never send -1 granulepos. + +2004-08-20 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_loop): + I will accept bitchslappings with non sharp objects. + +2004-08-20 Zaheer Abbas Merali + + * configure.ac: + Clean up the test for lame presets + +2004-08-19 Zaheer Abbas Merali + + * configure.ac: + * ext/lame/Makefile.am: + * ext/lame/gstlame.c: (gst_lame_class_init), + (gst_lame_set_property), (gst_lame_get_property), (gst_lame_setup): + Only enable lame presets if version of lame has presets in API + +2004-08-19 Jan Schmidt + * gst/udp/gstudpsrc.c: (gst_udpsrc_init), (gst_udpsrc_get): + * gst/udp/gstudpsrc.h: + Don't call gst_pad_push in a get function. Fixes #150449 + +2004-08-18 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_free), (gst_fdset_set_mode), + (gst_fdset_get_mode), (gst_fdset_add_fd), (gst_fdset_remove_fd), + (gst_fdset_fd_ctl_write), (gst_fdset_fd_ctl_read), + (gst_fdset_fd_has_closed), (gst_fdset_fd_has_error), + (gst_fdset_fd_can_read), (gst_fdset_fd_can_write), + (gst_fdset_wait): + * gst/tcp/gstfdset.h: + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_add), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write): + * gst/tcp/gstmultifdsink.h: + Some extra checks in gstfdset. + Only use send() when the fd is a socket. Don't try to + read from write only fds. + +2004-08-18 Wim Taymans + + * gst/tcp/gstfdset.c: (gst_fdset_add_fd), (gst_fdset_remove_fd), + (gst_fdset_fd_ctl_write), (gst_fdset_fd_ctl_read), + (gst_fdset_fd_has_closed), (gst_fdset_fd_has_error), + (gst_fdset_fd_can_read), (gst_fdset_fd_can_write), + (gst_fdset_wait): + Add more locking and bounds checking. + +2004-08-18 Wim Taymans + + * gst/tcp/gstfdset.c: (ensure_size), (gst_fdset_wait): + Realloc test fdset in the lock and right before starting + the poll call. Bump the limit to 4096. + +2004-08-17 David Schleef + + * sys/sunaudio/Makefile.am: + * sys/sunaudio/gstsunaudio.c: Fix caps to handle full range + of rates and channels. Make debugging less obnoxious. + + Patch from Balamurali Viswanathan implementing a mixer for + Sun audio. (bug #144091): + * sys/sunaudio/gstsunelement.c: + * sys/sunaudio/gstsunelement.h: + * sys/sunaudio/gstsunmixer.c: + * sys/sunaudio/gstsunmixer.h: + +2004-08-17 Zaheer Abbas Merali + + * gst/audioscale/gstaudioscale.c: + * gst/audioscale/gstaudioscale.h: + made audioscale resample from any sample rate to any sample rate + +2004-08-17 Thomas Vander Stichele + + * ext/libpng/gstpngdec.c: + error out on unsupported types + +2004-08-17 Iain + + * ext/flac/gstflacenc.c (gst_flacenc_update_quality): Only set the + mid_side and loose_mid_side properties if its a stereo stream. + +2004-08-17 Wim Taymans + + * ext/theora/theoradec.c: (gst_theora_dec_class_init), + (theora_get_formats), (theora_dec_src_convert), + (theora_dec_sink_convert), (theora_dec_src_query), + (theora_dec_src_event), (theora_dec_event), (theora_dec_chain): + Add a debug line. + +2004-08-17 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_iterate), + (gst_ogg_pad_push): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_init), + (gst_ogg_mux_request_new_pad), (gst_ogg_mux_next_buffer), + (gst_ogg_mux_buffer_from_page), (gst_ogg_mux_push_page), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop): + Mark delta units in the muxer. + Try to decode the packet after an out-of-sync error from + libogg. + +2004-08-17 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_init), (gst_multifdsink_add), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_set_property), (gst_multifdsink_get_property): + * gst/tcp/gstmultifdsink.h: + Added option to send a keyframe to clients as the first buffer. + Make timeout property writable. + +2004-08-17 Thomas Vander Stichele + + patch by: Wim Taymans + + * gst/tcp/gstfdset.c: + * gst/tcp/gstmultifdsink.c: + fix index comparison, should include 0 + +2004-08-16 Wim Taymans + + * gst/tcp/gstfdset.c: (ensure_size), (gst_fdset_new), + (gst_fdset_add_fd), (gst_fdset_remove_fd), + (gst_fdset_fd_has_closed), (gst_fdset_fd_has_error), + (gst_fdset_fd_can_read), (gst_fdset_fd_can_write), + (gst_fdset_wait): + copy when reallocing for poll so the select arguments don't get + changed during the call + +2004-08-16 Wim Taymans + + * ext/theora/theoraenc.c: (gst_border_mode_get_type), + (gst_theora_enc_class_init), (theora_enc_sink_link), + (theora_buffer_from_packet), (theora_enc_chain): + Fix bug where buffers were not marked as keyframes + correctly. + +2004-08-15 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_vbrmode_get_type), + (gst_lame_preset_get_type), (gst_lame_class_init): + describe the enum values for vbr mode and presets more verbosely + +2004-08-13 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_mode_get_type), + (gst_lame_quality_get_type), (gst_lame_padding_get_type), + (gst_lame_preset_get_type), (gst_lame_class_init), (gst_lame_init), + (gst_lame_set_property), (gst_lame_get_property), (gst_lame_setup): + * ext/lame/gstlame.h: + add preset property to lame so it can use lame presets + +2004-08-13 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_get_property): + whoops forgot break, thanks teuf + +2004-08-13 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_vbrmode_get_type), + (gst_lame_class_init), (gst_lame_src_getcaps), + (gst_lame_sink_link), (gst_lame_init), (gst_lame_set_property), + (gst_lame_get_property), (gst_lame_setup): + * ext/lame/gstlame.h: + fix lame's broken vbr stuff, allow it to resample if need be, and also + make xing header optional + +2004-08-12 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_src_getcaps), (gst_lame_init): + added getcaps function so samplerate doesnt get fixated to silly values + +2004-08-12 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_src_link): + revert previous fix + +2004-08-12 Johan Dahlin + + * sys/v4l/gstv4lelement.c (gst_v4l_iface_supported): Remove bogus + checks. Doesn't matter what state we are in. Interfaces are a + compile time thing, not runtime. It also broke the python bindings. + +2004-08-12 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_src_link): + made source pad link function check if sinkpad is ok..fixes the problem + where core fixates the output rate of lame stupidly + +2004-08-12 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_src_link), (gst_v4lsrc_fixate): + * sys/v4l/v4l_calls.c: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_set_capture): + fix fixate function to handle nonsimple caps. + remove bogus check in _link + cleanups + +2004-08-12 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_class_init), (gst_lame_init): + set default compression ratio parameter to 0.0 so bitrate parameter + works :) + +2004-08-11 David Schleef + + * gst/tcp/gstfdset.c: Fix compile problem on OS/X. + +2004-08-11 David Schleef + + * gst/mpeg1sys/gstmpeg1systemencode.c: Oops, this was correct + before. + +2004-08-11 David Schleef + + * gst-libs/gst/video/videosink.h: Change copyright block to LGPL. + +2004-08-11 David Schleef + + * ext/pango/gsttextoverlay.c: Add copyright block and fix plugin + license field + * gst-libs/gst/idct/Makefile.am: Remove mmx/sse code + * gst-libs/gst/video/gstvideosink.c: Change copyright block to + LGPL. + * gst/auparse/gstauparse.c: Fix plugin license field. + * gst/monoscope/gstmonoscope.c: Fix plugin license field. + * gst/mpeg1sys/gstmpeg1systemencode.c: Fix plugin license field. + * gst/rtp/gstrtp.c: Fix plugin license field. + +2004-08-11 Wim Taymans + + * gst/tcp/Makefile.am: + * gst/tcp/gstfdset.c: (gst_fdset_mode_get_type), (nearest_pow), + (ensure_size), (gst_fdset_new), (gst_fdset_free), + (gst_fdset_set_mode), (gst_fdset_get_mode), (gst_fdset_add_fd), + (gst_fdset_remove_fd), (gst_fdset_fd_ctl_write), + (gst_fdset_fd_ctl_read), (gst_fdset_fd_has_closed), + (gst_fdset_fd_has_error), (gst_fdset_fd_can_read), + (gst_fdset_fd_can_write), (gst_fdset_wait): + * gst/tcp/gstfdset.h: + * gst/tcp/gstmultifdsink.c: (gst_unit_type_get_type), + (gst_multifdsink_class_init), (gst_multifdsink_init), + (gst_multifdsink_add), (gst_multifdsink_remove), + (gst_multifdsink_clear), (gst_multifdsink_get_stats), + (gst_multifdsink_remove_client_link), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_caps), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_set_property), + (gst_multifdsink_get_property), (gst_multifdsink_init_send), + (gst_multifdsink_close): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init), + (gst_tcpserversink_init), (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_handle_wait), (gst_tcpserversink_init_send), + (gst_tcpserversink_close): + * gst/tcp/gsttcpserversink.h: + Abstracted away the select call, implemented poll (yes we ran into + the 1024 limit in production). + +2004-08-11 Thomas Vander Stichele + + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcpplugin.c: + improve debuggging, remove assert + +2004-08-10 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_unit_type_get_type), + (gst_client_status_get_type), (gst_multifdsink_class_init), + (gst_multifdsink_init), (gst_multifdsink_remove_client_link), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_set_property), + (gst_multifdsink_get_property): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp-marshal.list: + Starting to prepare for specifying buffer time in other units + than buffers. Expose remove reason in signal. + +2004-08-10 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_clear), + (gst_multifdsink_remove_client_link), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients), + (gst_multifdsink_chain), (gst_multifdsink_close): + * gst/tcp/gstmultifdsink.h: + Added more debugging info. Changed the way clients are + removed from the lists. Fixed a bug where a bad file descriptor + could cause many clients to be removed. + +2004-08-06 Benjamin Otte + + * gst/videotestsrc/gstvideotestsrc.c: (generate_capslist): + allow all pixel-aspect-ratios, not just 1:1 + +2004-08-09 David Schleef + + * sys/glsink/ARB_multitexture.h: Remove old files. + * sys/glsink/EXT_paletted_texture.h: + * sys/glsink/NV_register_combiners.h: + * sys/glsink/gstgl_nvimage.c: + * sys/glsink/gstgl_pdrimage.c: + * sys/glsink/gstgl_rgbimage.c: + * sys/glsink/gstglsink.c: + * sys/glsink/gstglsink.h: + * sys/glsink/gstglxwindow.c: + * sys/glsink/regcomb_yuvrgb.c: + +2004-08-09 David Schleef + + Patch from Gernot Ziegler rewriting the + GL sink plugin. (Bug #147302) + + * configure.ac: Test for OpenGL + * sys/Makefile.am: Use test for OpenGL + * sys/glsink/Makefile.am: + * sys/glsink/glimagesink.c: rewrite + * sys/glsink/glimagesink.h: rewrite + +2004-08-09 David Schleef + + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_base_init): Only allow + sane framerates. + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): same + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): same + * testsuite/gst-lint: Test for G_GUINT64_FORMAT usage near gettext. + +2004-08-09 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_get_stats), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients): + Do a bit more logging, make the client_read code more robust. + +2004-08-09 Thomas Vander Stichele + + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_init_source), + (gst_jpegdec_fill_input_buffer), (gst_jpegdec_skip_input_data), + (gst_jpegdec_resync_to_restart), (gst_jpegdec_term_source), + (gst_jpegdec_init), (gst_jpegdec_chain): + * gst/multipart/multipartdemux.c: (gst_multipart_demux_init), + (gst_multipart_demux_chain), (gst_multipart_demux_change_state): + cleanups, debugging fixes and memleak plugging + +2004-08-09 Wim Taymans + + * ext/theora/theoradec.c: (gst_theora_dec_class_init), + (theora_get_formats), (theora_dec_src_convert), + (theora_dec_sink_convert), (theora_dec_src_query), + (theora_dec_src_event), (theora_dec_event), (theora_dec_chain), + (theora_dec_change_state): + Don't crash on missing header packets. + +2004-08-09 Thomas Vander Stichele + + * po/LINGUAS: + * po/sq.po: + Added Albanian translation (Laurent Dhima) + * po/cs.po: + updated + +2004-08-09 Thomas Vander Stichele + + * ext/lame/gstlame.c: + fix/add debugging + +2004-08-09 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: + * sys/xvimage/xvimagesink.c: + assign all TOO_LAZY's to a real category. Thanks to Warthy Warthog. + +2004-08-06 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_get_stats), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients): + Make sure we don't try to read more from a client that what + ioctl says us or we deadlock. + +2004-08-05 Thomas Vander Stichele + + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_src_link), + (gst_videotestsrc_change_state), (gst_videotestsrc_src_query), + (gst_videotestsrc_handle_src_event), (gst_videotestsrc_get): + decouple running_time and n_frames so it can handle changing + framerate while running + +2004-08-05 Thomas Vander Stichele + + * po/nl.po: + * po/sv.po: + updated translations + +2004-08-04 Benjamin Otte + + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_get_capslist), (generate_capslist), + (plugin_init): + generate the list of supported caps at startup and reuse it instead + of always generating it + +2004-07-30 Benjamin Otte + + * gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link): + whoops, last checkin broke normal build + +2004-08-03 Benjamin Otte + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_get_volume), + (gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute), + (gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option), + (gst_alsa_mixer_get_option): + * ext/dvdnav/dvdnavsrc.c: (dvdnav_get_event_name), + (dvdnavsrc_print_event): + * ext/ogg/gstoggdemux.c: (_find_chain_process), (gst_ogg_print): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_pad_link), + (gst_ogg_mux_pad_unlink): + * gst/multipart/multipartmux.c: (gst_multipart_mux_pad_link), + (gst_multipart_mux_pad_unlink): + * gst/videofilter/gstvideobalance.c: + (gst_videobalance_colorbalance_set_value): + * gst/videomixer/videomixer.c: (gst_videomixer_pad_link), + (gst_videomixer_pad_unlink): + * po/uk.po: + * sys/oss/gstossmixer.c: + * sys/v4l/gstv4lcolorbalance.c: + * sys/v4l/gstv4ltuner.c: + * sys/v4l/v4lsrc_calls.c: + * sys/v4l2/gstv4l2colorbalance.c: + * sys/v4l2/gstv4l2tuner.c: + compile fixes for --disable-gst-debug, G_DISABLE_ASSERT and friends + +2004-08-03 Benjamin Otte + + * examples/dynparams/filter.c: (ui_control_create): + * examples/gstplay/player.c: (print_tag): + * ext/alsa/gstalsa.c: (gst_alsa_request_new_pad): + * ext/gdk_pixbuf/gstgdkanimation.c: + (gst_gdk_animation_iter_may_advance): + * ext/jack/gstjack.c: (gst_jack_request_new_pad): + * ext/mad/gstid3tag.c: (gst_mad_id3_to_tag_list), + (tag_list_to_id3_tag_foreach), (gst_id3_tag_handle_event): + * ext/vorbis/oggvorbisenc.c: (gst_oggvorbisenc_get_tag_value): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_get_tag_value): + * ext/xine/xineaudiodec.c: (gst_xine_audio_dec_chain): + * gst-libs/gst/media-info/media-info-test.c: (print_tag): + * gst/sine/demo-dparams.c: (main): + * gst/tags/gstvorbistag.c: (gst_tag_to_vorbis_comments): + * testsuite/alsa/formats.c: (create_pipeline): + * testsuite/alsa/sinesrc.c: (sinesrc_force_caps), (sinesrc_get): + fixes for G_DISABLE_ASSERT and friends + * gst/typefind/gsttypefindfunctions.c: (aac_type_find), + (mp3_type_frame_length_from_header), (mp3_type_find), + (plugin_init): + require mp3 typefinding to have at least MIN_HEADERS valid headers + add typefinding for AAC adts files + +2004-08-04 Jan Schmidt + + * sys/ximage/ximagesink.c: + (gst_ximagesink_calculate_pixel_aspect_ratio): + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio): + Make sure we calculate pixel-aspect-ratio using floating point maths + +2004-08-03 Thomas Vander Stichele + + * po/uk.po: + updated translation + +2004-08-03 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get): + add debugging for display PAR calculation + +2004-08-02 David Schleef + + * configure.ac: Fix mikmod CFLAGS. + +2004-07-27 Benjamin Otte + + * gst/audioscale/gstaudioscale.c: + - fix templates to only support S16, it's the only format that works + - make caps nego code use try_set_caps_nonfixed and fixation instead + of try_set_caps twice, which is not nice for autopluggers + - change rank to secondary, so autopluggers can pick it up after + audioconvert + +2004-08-02 Iain + + * gst/interleave/interleave.c (interleave_init), + (interleave_request_new_pad), + (interleave_pad_removed), + (interleave_buffered_loop): Use the real pad count, not the artificial + one. + +2004-08-02 Thomas Vander Stichele + + * configure.ac: bump nano back to development + +=== release 0.8.3 === + +2004-08-02 Thomas Vander Stichele + + * configure.ac: releasing 0.8.3, "Water" + +2004-08-02 Thomas Vander Stichele + + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio), + (gst_xvimagesink_xcontext_clear), (gst_xvimagesink_sink_link), + (gst_xvimagesink_change_state), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + apply similar PAR fixes as to ximagesink + +2004-08-02 Thomas Vander Stichele + + patch from: Benjamin Otte + + * ext/lame/gstlame.c: (gst_lame_src_link), (gst_lame_init): + add link function to lame. Fixes #148986. + +2004-08-02 Johan Dahlin + + * gst/multipart/multipartmux.c (gst_multipart_mux_next_buffer): + fix debugging log + +2004-07-30 David Schleef + + * gst/videomixer/Makefile.am: Fix things that should have been + fixed in the last checkin. + +2004-07-30 David Schleef + + * gst/multipart/Makefile.am: Fix things that should have been + fixed in the last checkin. + +2004-07-30 David Schleef + + * testsuite/multifilesink/Makefile.am: Fix unused variable. + +2004-07-30 Thomas Vander Stichele + + * configure.ac: + bump nano for prerelease + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/nl.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + updates + +2004-07-30 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_remove), + (gst_multifdsink_clear), (gst_multifdsink_get_stats), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer), (gst_multifdsink_handle_clients): + * gst/tcp/gstmultifdsink.h: + Recover from a select with a bad file descriptor by removing + the client. + +2004-07-30 Thomas Vander Stichele + + * configure.ac: + fix requirement of core + * gst-libs/gst/play/play.c: (gst_play_error_plugin), + (gst_play_pipeline_setup): + don't use colorspace element. do use hermescolorspace element. + make macro to get a colorspace element. + mark strings for translation. + * po/POTFILES.in: + add play.c + * po/af.po: + * po/az.po: + * po/cs.po: + * po/en_GB.po: + * po/hu.po: + * po/nl.po: + * po/sr.po: + * po/sv.po: + * po/uk.po: + update translations + +2004-07-30 Zaheer Abbas Merali + + * ext/libpng/gstpngenc.c: (gst_pngenc_class_init): + fix default for newmedia flag + +2004-07-30 Wim Taymans + + * ext/theora/theoradec.c: (gst_theora_dec_class_init), + (gst_theora_dec_init), (theora_get_formats), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), + (theora_dec_chain), (theora_dec_set_property), + (theora_dec_get_property): + * ext/theora/theoraenc.c: (gst_border_mode_get_type), + (gst_theora_enc_class_init), (gst_theora_enc_init), + (theora_enc_sink_link), (theora_enc_chain), + (theora_enc_set_property), (theora_enc_get_property): + Added cropping option to theora decoder. + Added border option to theora encoder. + +2004-07-30 Zaheer Abbas Merali + + * ext/libpng/gstpngenc.c: (gst_pngenc_class_init), + (gst_pngenc_init), (gst_pngenc_chain), (gst_pngenc_get_property), + (gst_pngenc_set_property): + * ext/libpng/gstpngenc.h: + Added newmedia support to pngenc so now gst-launch-0.8 videotestsrc ! ffmpegcolorspace ! pngenc snapshot=false newmedia=true ! multifilesink location=blah%d.png works as expected + +2004-07-30 Wim Taymans + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_sink_link), (theora_enc_chain), + (theora_enc_set_property), (theora_enc_get_property): + Fix encoding of non-multiple-of-16 video. + +2004-07-29 David Schleef + + * configure.ac: make test for audiofile more strict + +2004-07-25 Benjamin Otte + + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + give different names to typefind functions + +2004-07-28 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_calculate_pixel_aspect_ratio), + (gst_ximagesink_xcontext_get), (gst_ximagesink_getcaps), + (gst_ximagesink_sink_link), (gst_ximagesink_change_state), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_set_property), + (gst_ximagesink_get_property), (gst_ximagesink_init): + * sys/ximage/ximagesink.h: + allocate PAR's dynamically. + use autodetected PAR if no object-set PAR is given. + add workaround for directfb's X not setting physical size. + fix to xvimagesink will follow tomorrow. + +2004-07-28 Zaheer Abbas Merali + + * ext/lame/gstlame.c: (gst_lame_chain): send tag events downstream + * ext/shout2/gstshout2.c: (gst_shout2send_protocol_get_type), + (gst_shout2send_get_type), (gst_shout2send_set_clock), + (gst_shout2send_class_init), (gst_shout2send_init), + (set_shout_metadata), (gst_shout2send_set_metadata), + (gst_shout2send_chain), (gst_shout2send_set_property), + (gst_shout2send_get_property), (gst_shout2send_connect), + (gst_shout2send_change_state): + * ext/shout2/gstshout2.h: + - fix for sending mp3 audio to icecast2 server, if pad link function not + called before PAUSED state + - added option to use GStreamer clock sync (as opposed to libshout's own sync) + - added tagging support for mp3 audio broadcasted + * gst/monoscope/gstmonoscope.c: (gst_monoscope_class_init): + debug info + +2004-07-28 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query), + (gst_ogg_demux_push): + Return query failure when we don't know the length of + an ogg stream insteda of returning TRUE with a bogus value. + +2004-07-28 Wim Taymans + + * ext/theora/theoradec.c: (theora_get_formats), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), + (theora_dec_chain): + Don't screw up the 1 Chroma for 1 luma sample situation when we + have an odd offset/width by adding a black border in those cases. + +2004-07-28 Wim Taymans + + * ext/theora/theoradec.c: (theora_get_formats), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), + (theora_dec_chain): + * ext/theora/theoraenc.c: (theora_enc_sink_link): + Added first attempt at cropping of the image as required by the + theora spec. We need more properties in the caps (offset_x, + offset_y,stride) to implement this correctly. + +2004-07-28 Jan Schmidt + + * ext/dvdnav/README: + Update the README to use dvddemux + * ext/gdk_pixbuf/pixbufscale.c: (gst_pixbufscale_getcaps): + Ensure getcaps returns a subset of the template caps + * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_base_init), + (gst_mpeg2subt_init): + Ensure getcaps returns a subset of the template caps + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_class_init), + (gst_dvd_demux_init), (gst_dvd_demux_get_video_stream), + (gst_dvd_demux_get_subpicture_stream), + (gst_dvd_demux_send_subbuffer), (gst_dvd_demux_set_cur_subpicture): + * gst/mpegstream/gstdvddemux.h: + Set the explicit caps on the current_video pad before pushing + anything + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_get_video_stream), + (gst_mpeg_demux_get_audio_stream): + Free caps used to gst_pad_set_explicit_caps, which takes a const + GstCaps * + +2004-07-28 Thomas Vander Stichele + + * configure.ac: update GStreamer requirement to 0.8.4 because of + GstFraction. + +2004-07-28 Wim Taymans + + * gst/wavparse/gstwavparse.c: (gst_wavparse_fmt), + (gst_wavparse_handle_seek), (gst_wavparse_srcpad_event): + Add the pad to the element after setting up the caps. This + makes it a lot easier to autoplug. + +2004-07-27 Steve Lhomme + + * gst/median/gstmedian.c: + * gst/mpeg2subt/gstmpeg2subt.c: + * gst/mpegaudioparse/gstmpegaudioparse.c: + * gst/mpegstream/gstdvddemux.c: + * gst/mpegstream/gstmpegdemux.c: + * gst/mpegstream/gstmpegpacketize.c: + * gst/rtjpeg/gstrtjpeg.c: + * gst/rtjpeg/gstrtjpegdec.c: + * gst/rtjpeg/gstrtjpegenc.c: + * gst/sine/gstsinesrc.c: + * gst/smooth/gstsmooth.c: + * gst/smpte/gstsmpte.c: + * gst/smpte/gstsmpte.h: + * gst/stereo/gststereo.c: + * gst/videofilter/gstgamma.c: + * gst/videofilter/gstvideobalance.c: + * gst/videofilter/gstvideofilter.c: + * gst/videofilter/gstvideoflip.c: + * gst/videoscale/gstvideoscale.c: + * gst/videoscale/videoscale.c: + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/videotestsrc.c: + * gst/wavenc/gstwavenc.c: + * gst/wavparse/gstwavparse.c: + fix local includes and 64 bits constants + +2004-07-27 Steve Lhomme + + * win32/gst.sln: + * gst-libs/gst/*/*.vcproj: + * gst/*/*.vcproj: + more working plugins + +2004-07-27 Zaheer Abbas Merali + + * testsuite/alsa/Makefile.am: + * testsuite/alsa/srcstate.c: + add test for alsasrc changing state + +2004-07-27 Zaheer Abbas Merali + + * gst/silence/gstsilence.c: (gst_silence_init), (gst_silence_link), + (gst_silence_get): + * gst/silence/gstsilence.h: + fix silence generation for 16bit raw audio + +2004-07-27 Thomas Vander Stichele + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_metadata), + (gst_matroska_demux_video_caps), (gst_matroska_demux_plugin_init): + * gst/mpegaudio/common.c: + * gst/videoscale/gstvideoscale.c: (gst_videoscale_class_init), + (gst_videoscale_getcaps), (gst_videoscale_link), + (gst_videoscale_src_fixate), (gst_videoscale_init), + (gst_videoscale_finalize): + * gst/videoscale/gstvideoscale.h: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_get_capslist): + * gst/wavenc/gstwavenc.c: + * sys/oss/gstossmixer.c: (fill_labels): + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_handle_xevents), + (gst_ximagesink_calculate_pixel_aspect_ratio), + (gst_ximagesink_xcontext_get), (gst_ximagesink_fixate), + (gst_ximagesink_getcaps), (gst_ximagesink_sink_link), + (gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_set_property), (gst_ximagesink_get_property), + (gst_ximagesink_init), (gst_ximagesink_class_init): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: + (gst_xvimagesink_calculate_pixel_aspect_ratio), + (gst_xvimagesink_xcontext_get), (gst_xvimagesink_sink_link), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): + * sys/xvimage/xvimagesink.h: + first batch of pixel aspect ratio commits. + +2004-07-27 Thomas Vander Stichele + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_class_init), (gst_ffmpegcolorspace_chain): + * gst/ffmpegcolorspace/imgconvert.c: (avpicture_fill): + handle stride, needs work if we want to move stride handling + upstream, but works correctly for our purposes. + +2004-07-27 Thomas Vander Stichele + + * gst/videoscale/README: + add testing examples + * gst/videoscale/gstvideoscale.c: (gst_videoscale_link), + (gst_videoscale_chain): + * gst/videoscale/videoscale.c: (gst_videoscale_setup), + (gst_videoscale_get_size): + add get_size function that handles stride like videotestsrc. + fixes conversion for YUV formats for as much as I can test them. + +2004-07-27 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_destroy): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_destroy), + (gst_xvimagesink_xvimage_put): + further cleanups, logging, error handling and synchronizing + +2004-07-27 Wim Taymans + + * gst/videomixer/videomixer.c: (gst_videomixer_pad_get_type), + (gst_videomixer_pad_class_init), (gst_videomixer_pad_get_property), + (gst_videomixer_pad_set_property), + (gst_videomixer_pad_sinkconnect), (gst_videomixer_pad_init), + (gst_video_mixer_background_get_type), (gst_videomixer_get_type), + (gst_videomixer_class_init), (gst_videomixer_init), + (gst_videomixer_getcaps), (gst_videomixer_request_new_pad), + (gst_videomixer_blend_ayuv_i420), (pad_zorder_compare), + (gst_videomixer_sort_pads), (gst_videomixer_fill_checker), + (gst_videomixer_fill_color), (gst_videomixer_fill_queues), + (gst_videomixer_blend_buffers), (gst_videomixer_update_queues), + (gst_videomixer_loop), (plugin_init): + Be a nicer negotiation citizen and provide a getcaps function on + the srcpad. This also fixes a crash when resizing. + +2004-07-27 Julien MOUTTE + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new): Some fixes to image size calculation. + +2004-07-27 Wim Taymans + + * ext/libpng/gstpngdec.c: (gst_pngdec_src_getcaps): + * ext/libpng/gstpngenc.c: (gst_pngenc_class_init), + (gst_pngenc_init), (gst_pngenc_chain), (gst_pngenc_get_property), + (gst_pngenc_set_property): + * ext/libpng/gstpngenc.h: + Added snapshot property to pngenc. + removed g_print from pngdec + +2004-07-27 Steve Lhomme + + * gst/ac3parse/ac3parse.vcproj + * gst/adder/adder.vcproj + * gst/alpha/alpha.vcproj + * gst/alpha/alphacolor.vcproj + * gst/asfdemux/asf.vcproj + * gst/audioconvert/audioconvert.vcproj + * gst/audiorate/audiorate.vcproj + * gst/audioscale/audioscale.vcproj + * gst/auparse/auparse.vcproj + * gst/avi/avi.vcproj + * gst/cdxaparse/cdxaparse.vcproj + * gst/chart/chart.vcproj + * gst/colorspace/colorspace.vcproj + * gst/cutter/cutter.vcproj + * gst/debug/debug.vcproj + * gst/debug/efence.vcproj + * gst/debug/navigationtest.vcproj + * gst/deinterlace/deinterlace.vcproj + * gst/effectv/effectv.vcproj + * gst/ffmpegcolorspace/ffmpegcolorspace.vcproj + * gst/filter/filter.vcproj + * gst/flx/flxdec.vcproj + * gst/goom/goom.vcproj + * gst/interleave/interleave.vcproj + * gst/law/alaw.vcproj + * gst/law/mulaw.vcproj + * gst/matroska/matroska.vcproj + * gst/median/median.vcproj + * gst/mixmatrix/mixmatrix.vcproj + * gst/mpeg1sys/mpeg1systemencode.vcproj + * gst/mpeg1videoparse/mp1videoparse.vcproj + * gst/mpeg2sub/mpeg2subt.vcproj + * gst/mpegaudio/mpegaudio.vcproj + * gst/mpegaudioparse/mpegaudioparse.vcproj + * gst/mpegstream/mpegstream.vcproj + * gst/multifilesink/multifilesink.vcproj + * gst/multipart/multipart.vcproj + * gst/oneton/oneton.vcproj + * gst/overlay/overlay.vcproj + * gst/passthrough/passthrough.vcproj + * gst/qtdemux/qtdemux.vcproj + * gst/realmedia/rmdemux.vcproj + * gst/rtjpeg/rtjpeg.vcproj + * gst/rtp/rtp.vcproj + * gst/silence/silence.vcproj + * gst/sine/sinesrc.vcproj + * gst/smooth/smooth.vcproj + * gst/smpte/smpte.vcproj + * gst/spectrum/spectrum.vcproj + * gst/speed/speed.vcproj + * gst/stereo/stereo.vcproj + * gst/switch/switch.vcproj + * gst/tags/tagedit.vcproj + * gst/tcp/tcp.vcproj + * gst/typefind/typefindfunctions.vcproj + * gst/udp/udp.vcproj + * gst/videobox/videobox.vcproj + * gst/videocrop/videocrop.vcproj + * gst/videodrop/videodrop.vcproj + * gst/videofilter/gamma.vcproj + * gst/videofilter/videobalance.vcproj + * gst/videofilter/videofilter.vcproj + * gst/videofilter/videoflip.vcproj + * gst/videoflip/videoflip.vcproj + * gst/videomixer/videomixer.vcproj + * gst/videorate/videorate.vcproj + * gst/videoscale/videoscale.vcproj + * gst/videotestsrc/videotestsrc.vcproj + * gst/virtualdub/virtualdub.vcproj + * gst/volenv/volenv.vcproj + * gst/volume/volume.vcproj + * gst/wavenc/wavenc.vcproj + * gst/wavparse/wavparse.vcproj + * gst/y4m/y4menc.vcproj + * gst-libs/gst/audio/audio.vcproj + * gst-libs/gst/audio/audiofilter.vcproj + * gst-libs/gst/colorbalance/colorbalance.vcproj + * gst-libs/gst/idct/idtc.vcproj + * gst-libs/gst/media-info/media-info.vcproj + * gst-libs/gst/mixer/mixer.vcproj + * gst-libs/gst/navigation/navigation.vcproj + * gst-libs/gst/play/play.vcproj + * gst-libs/gst/propertyprobe/propertyprobe.vcproj + * gst-libs/gst/resample/resample.vcproj + * gst-libs/gst/riff/riff.vcproj + * gst-libs/gst/tuner/tuner.vcproj + * gst-libs/gst/video/video.vcproj + * gst-libs/gst/xoverlay/xoverlay.vcproj + avoid problems with math.h, fix release dependancy + rename GStreamer-0.8.lib to libgstreamer.lib + +2004-07-27 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_decorate): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_decorate): When + the atom is not available we have to unlock the mutex. Fixes #148023 + +2004-07-26 Steve Lhomme + + * gst-libs/gst/media-info/media-info.h: + issue for a vararg macro with MSVC + +2004-07-26 Steve Lhomme + + * gst/effectv/effectv.vcproj + * gst-libs/gst/idct/idct.vcproj: + * gst-libs/gst/media-info/media-info.vcproj: + * gst-libs/gst/navigation/navigation.vcproj: + * gst-libs/gst/propertyprobe/propertyprobe.vcproj: + * gst-libs/gst/video/video.vcproj: + * gst-libs/gst/xoverlay/xoverlay.vcproj: + fixes for build problems + +2004-07-26 Steve Lhomme + + * gst-libs/gst/audio/audio.def: + * gst-libs/gst/audio/riff.def: + add some definitions needed by plugins + +2004-07-26 Steve Lhomme + + * gst/asfdemux/gstasfmux.c + Fix some 64 bits constants to be glib friendly + +2004-07-26 Steve Lhomme + + * gst/ac3parse/gstac3parse.c + * gst/audioscale/gstaudioscale.c + * gst/auparse/gstauparse.c + * gst/colorspace/gstcolorspace.c + * gst/colorspace/yuv2rgb.h + local include fixes + +2004-07-26 Steve Lhomme + + * win32/gst.sln + add more plugins to the build + +2004-07-26 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new): Some more fixes to image size calculation. + +2004-07-26 Thomas Vander Stichele + + * gst/level/gstlevel.c: (gst_level_link), (gst_level_chain), + (gst_level_set_property), (gst_level_get_property), + (gst_level_base_init), (gst_level_class_init): + add debugging categories. cleanups. + +2004-07-26 Thomas Vander Stichele + + * gst/videoscale/videoscale.c: (gst_videoscale_setup), + (gst_videoscale_planar411), (gst_videoscale_planar400), + (gst_videoscale_packed422), (gst_videoscale_packed422rev), + (gst_videoscale_scale_nearest_str1), + (gst_videoscale_scale_nearest_str2), + (gst_videoscale_scale_nearest_str4), + (gst_videoscale_scale_nearest_16bit), + (gst_videoscale_scale_nearest_24bit): + fixed stride issues + tested with 320x240 -> 321, 322, 324 x240 + tested with YV12, I420, YUY2, UYVY + fixed packed422rev (don't think it could have worked before) + by testing with UYVY + +2004-07-26 Benjamin Otte + + * ext/lame/gstlame.c: (gst_lame_sink_link), (gst_lame_init), + (gst_lame_chain), (gst_lame_setup), (gst_lame_change_state), + (plugin_init): + add debugging category, add error checks like checking return values + of setup calls, make sure it still works after + PLAYING=>NULL=>PLAYING, fix encoding of mono streams + +2004-07-26 Wim Taymans + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_get_video_stream), + (gst_mpeg_demux_get_audio_stream), + (gst_mpeg_demux_process_private): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_send_data): + Check for error codes from the negotiation functions. Make sure + we really set the pad caps when a new pad is created. + +2004-07-26 Thomas Vander Stichele + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_caps_to_pix_fmt): + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_pad_link): + don't make function do two things at the same time without reason. + +2004-07-26 Steve Lhomme + + * gst/ac3parse/ac3parse.vcproj + * gst/adder/adder.vcproj + * gst/alpha/alpha.vcproj + * gst/alpha/alphacolor.vcproj + * gst/asfdemux/asf.vcproj + * gst/audioconvert/audioconvert.vcproj + * gst/audiorate/audiorate.vcproj + * gst/audioscale/audioscale.vcproj + * gst/auparse/auparse.vcproj + * gst/avi/avi.vcproj + * gst/cdxaparse/cdxaparse.vcproj + * gst/chart/chart.vcproj + * gst/colorspace/colorspace.vcproj + * gst/cutter/cutter.vcproj + * gst/debug/debug.vcproj + * gst/debug/efence.vcproj + * gst/debug/navigationtest.vcproj + * gst/deinterlace/deinterlace.vcproj + * gst/effectv/effectv.vcproj + * gst/ffmpegcolorspace/ffmpegcolorspace.vcproj + * gst/filter/filter.vcproj + * gst/flx/flxdec.vcproj + * gst/goom/goom.vcproj + * gst/interleave/interleave.vcproj + * gst/law/alaw.vcproj + * gst/law/mulaw.vcproj + * gst/matroska/matroska.vcproj + * gst/median/median.vcproj + * gst/mixmatrix/mixmatrix.vcproj + * gst/mpeg1sys/mpeg1systemencode.vcproj + * gst/mpeg1videoparse/mp1videoparse.vcproj + * gst/mpeg2sub/mpeg2subt.vcproj + * gst/mpegaudio/mpegaudio.vcproj + * gst/mpegaudioparse/mpegaudioparse.vcproj + * gst/mpegstream/mpegstream.vcproj + * gst/multifilesink/multifilesink.vcproj + * gst/multipart/multipart.vcproj + * gst/oneton/oneton.vcproj + * gst/overlay/overlay.vcproj + * gst/passthrough/passthrough.vcproj + * gst/qtdemux/qtdemux.vcproj + * gst/realmedia/rmdemux.vcproj + * gst/rtjpeg/rtjpeg.vcproj + * gst/rtp/rtp.vcproj + * gst/silence/silence.vcproj + * gst/sine/sinesrc.vcproj + * gst/smooth/smooth.vcproj + * gst/smpte/smpte.vcproj + * gst/spectrum/spectrum.vcproj + * gst/speed/speed.vcproj + * gst/stereo/stereo.vcproj + * gst/switch/switch.vcproj + * gst/tags/tagedit.vcproj + * gst/tcp/tcp.vcproj + * gst/typefind/typefindfunctions.vcproj + * gst/udp/udp.vcproj + * gst/videobox/videobox.vcproj + * gst/videocrop/videocrop.vcproj + * gst/videodrop/videodrop.vcproj + * gst/videofilter/gamma.vcproj + * gst/videofilter/videobalance.vcproj + * gst/videofilter/videofilter.vcproj + * gst/videofilter/videoflip.vcproj + * gst/videoflip/videoflip.vcproj + * gst/videomixer/videomixer.vcproj + * gst/videorate/videorate.vcproj + * gst/videoscale/videoscale.vcproj + * gst/videotestsrc/videotestsrc.vcproj + * gst/virtualdub/virtualdub.vcproj + * gst/volenv/volenv.vcproj + * gst/volume/volume.vcproj + * gst/wavenc/wavenc.vcproj + * gst/wavparse/wavparse.vcproj + * gst/y4m/y4menc.vcproj + more plugins supported under windows + +2004-07-26 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_ximage_put), (gst_ximagesink_renegotiate_size), + (gst_ximagesink_chain), (gst_ximagesink_buffer_alloc): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc): + Add debugging statements. Use the sizes as returned by the + *CreateImage calls. + +2004-07-26 Johan Dahlin + + * gst/tcp/gsttcpclientsrc.c (gst_tcpclientsrc_get): Make sure that + the pad is negotiated. + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c (gst_ffmpegcolorspace_chain): Ditto + +2004-07-26 Steve Lhomme + + * gst-libs/gst/colorbalance/colorbalance.vcproj: + * gst-libs/gst/idct/idct.vcproj: + * gst-libs/gst/media-info/media-info.vcproj: + * gst-libs/gst/mixer/mixer.vcproj: + * gst-libs/gst/navigation/navigation.vcproj: + * gst-libs/gst/play/play.vcproj: + * gst-libs/gst/propertyprobe/propertyprobe.vcproj: + * gst-libs/gst/resample/resample.vcproj: + * gst-libs/gst/tuner/tuner.vcproj: + * gst-libs/gst/video/video.vcproj: + * gst-libs/gst/xoverlay/xoverlay.vcproj: + more plugins supported under windows + +2004-07-25 Iain + + * gst/wavparse/gstwavparse.c (gst_wavparse_fmt): Set the caps on the + pad now rather than when the pad is created because state changes wipe + explicit caps (fixes #148043). + +2004-07-25 Sebastien Cote + + reviewed by Benjamin Otte + + * ext/mad/gstmad.c: + fix mad plugin crashing on Sun (fixes #148289) + +2004-07-25 Steve Lhomme + + * gst/avi/avi.def: + * gst/avi/avi.vcproj: + * gst/matroska/matroska.def: + * gst/matroska/matroska.vcproj: + remove unused .def files + +2004-07-25 Steve Lhomme + + * gst-libs/gst/audio/gstaudiofilter.c: + Clean the local include + +2004-07-25 Steve Lhomme + + * win32/gst.sln: + * gst-libs/gst/audio/audio.def: + * gst-libs/gst/audio/audio.vcproj: + * gst-libs/gst/audio/audiofilter.vcproj: + * gst-libs/gst/audio/riff.def: + * gst-libs/gst/audio/riff.vcproj: + * gst-libs/gst/gst-libs.def: + * gst-libs/gst/gst-libs.vcproj: + * gst/avi/avi.vcproj: + * gst/avi/avi.vcproj: + Copy the files where needed after building, cleaner projects + +2004-07-25 Steve Lhomme + + * gst/matroska/ebml-write.c: + Fix some 64 bits constants to be glib friendly + +2004-07-24 Steve Lhomme + + * win32/gst.sln: + * gst-libs/gst/gst-libs.def: + * gst-libs/gst/gst-libs.vcproj: + * gst/matroska/matroska.def: + * gst/matroska/matroska.vcproj: + Add the preliminary canvas to build plugins on Win32 + +2004-07-23 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + don't enfore negotiation from source side, it breaks + sinesrc ! audioconvert ! osssink + +2004-07-22 David Schleef + + * gst/typefind/gsttypefindfunctions.c: (plugin_init): Add typefind + for ELF files, since they can easily be recognized as audio/mpeg. + (bug #147441) + +2004-07-22 Thomas Vander Stichele + + * gst/videoscale/videoscale.c: (gst_videoscale_setup), + (gst_videoscale_planar411), (gst_videoscale_scale_nearest_32bit), + (gst_videoscale_scale_nearest_24bit), + (gst_videoscale_scale_nearest_16bit): + fix 16bit and 24bit for stride (24bit might need testing) + don't pretend we do more than one algorithm + +2004-07-22 Zaheer Abbas Merali + + * configure.ac: + * gst/Makefile.am: + * gst/multifilesink/Makefile.am: + * gst/multifilesink/gstmultifilesink.c: + (gst_multifilesink_get_formats), + (gst_multifilesink_get_query_types), (_do_init), + (gst_multifilesink_base_init), (gst_multifilesink_class_init), + (gst_multifilesink_init), (gst_multifilesink_dispose), + (gst_multifilesink_set_location), (gst_multifilesink_set_property), + (gst_multifilesink_get_property), (gst_multifilesink_open_file), + (gst_multifilesink_close_file), (gst_multifilesink_next_file), + (gst_multifilesink_pad_query), (gst_multifilesink_handle_event), + (gst_multifilesink_chain), (gst_multifilesink_change_state), + (gst_multifilesink_uri_get_type), + (gst_multifilesink_uri_get_protocols), + (gst_multifilesink_uri_get_uri), (gst_multifilesink_uri_set_uri), + (gst_multifilesink_uri_handler_init), (plugin_init): + * gst/multifilesink/gstmultifilesink.h: + * testsuite/Makefile.am: + * testsuite/multifilesink/Makefile.am: + * testsuite/multifilesink/fakesrc_test.c: (gst_newmedia_base_init), + (gst_newmedia_class_init), (gst_newmedia_init), + (gst_newmedia_chain), (gst_newmedia_trigger), (test_format), + (newfile_signal), (test_signal), (main): + multifilesink plugin for creating new files every time a new media + discontinuity event occurs + +2004-07-22 Wim Taymans + + * gst/alpha/Makefile.am: + * gst/alpha/gstalphacolor.c: (gst_alpha_color_get_type), + (gst_alpha_color_base_init), (gst_alpha_color_class_init), + (gst_alpha_color_init), (gst_alpha_color_set_property), + (gst_alpha_color_get_property), (gst_alpha_color_sink_link), + (transform), (gst_alpha_color_chain), + (gst_alpha_color_change_state), (plugin_init): + Stupid plugin to to RGBA to AYUV conversion because none of + the colorspace plugins can handle that yet. + +2004-07-22 Wim Taymans + + * examples/seeking/seek.c: (update_scale), (main): + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_is_dynamic), + (gst_decode_bin_factory_filter), (compare_ranks), (print_feature), + (gst_decode_bin_init), (gst_decode_bin_dispose), + (find_compatibles), (close_pad_link), (try_to_link_1), (new_pad), + (no_more_pads), (close_link), (type_found), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (plugin_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type), + (gst_play_base_bin_class_init), (gst_play_base_bin_init), + (gst_play_base_bin_dispose), (queue_overrun), + (gen_preroll_element), (remove_prerolls), (unknown_type), + (no_more_pads), (new_stream), (setup_source), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property), + (play_base_eos), (gst_play_base_bin_change_state), + (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream), + (gst_play_base_bin_unlink_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybin.c: (gen_video_element), + (gen_audio_element): + * gst/playback/gststreaminfo.h: + More playback updates, attempt to fix things after the state change + breakage. + +2004-07-22 Thomas Vander Stichele + + * gst/videoscale/videoscale.c: (gst_videoscale_planar411), + (gst_videoscale_scale_nearest_16bit): + comment algorithm + +2004-07-22 Thomas Vander Stichele + + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_class_init), (gst_videotestsrc_src_link), + (gst_videotestsrc_init), (gst_videotestsrc_get), + (gst_videotestsrc_set_pattern), (gst_videotestsrc_set_property), + (gst_videotestsrc_get_property): + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + cleanup and commenting + +2004-07-21 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_init), + (gst_ogg_demux_get_formats), (gst_ogg_demux_src_query), + (gst_ogg_demux_src_event), (gst_ogg_demux_src_convert), + (gst_ogg_demux_handle_event), (gst_ogg_demux_seek_before), + (_find_chain_get_unknown_part), (_find_streams_check), + (gst_ogg_demux_push), (gst_ogg_pad_push): + * ext/theora/theoradec.c: (theora_get_formats), + (theora_dec_src_convert), (theora_dec_sink_convert), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), + (theora_dec_chain): + * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), + (vorbis_dec_convert), (vorbis_dec_src_query), + (vorbis_dec_src_event), (vorbis_dec_event): + More seeking fixes, oggdemux now supports seeking to time and + uses the downstream element to convert granulepos to time. + Seeking in theora-only ogg files now works. + +2004-07-21 Wim Taymans + + * ext/theora/theoradec.c: (gst_theora_dec_init), + (theora_get_formats), (theora_get_event_masks), + (theora_get_query_types), (theora_dec_src_convert), + (theora_dec_sink_convert), (theora_dec_src_query), + (theora_dec_src_event), (theora_dec_event), (theora_dec_chain): + * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), + (vorbis_get_event_masks), (vorbis_get_query_types), + (gst_vorbis_dec_init), (vorbis_dec_convert), + (vorbis_dec_src_query), (vorbis_dec_src_event), (vorbis_dec_event): + Added query/convert/formats functions to vorbis and theora decoders + so that the outside world can use them too. Fixed seeking on an + ogg/theora/vorbis file by disabling the seeking seeking on the + theora srcpad. + +2004-07-21 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_renegotiate_size), (gst_ximagesink_sink_link), + (gst_ximagesink_chain), (gst_ximagesink_set_xwindow_id): Optimize + images creation for both elements. We don't create the image on caps + nego or renego, we just destroy the internal one if present if it does + not match the needs. The chain function takes care of creating a new + image when needed. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_xwindow_decorate), (gst_xvimagesink_sink_link), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_xwindow_id): Additionally xvimage now contains + the image format information. The buffer pool checks for the context + image format and discard images with different formats. + * sys/xvimage/xvimagesink.h: Adding im_format in the xvimage structure. + +2004-07-21 Thomas Vander Stichele + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_chain): + no point in doing any chaining if the pad we want to push from + isn't usable. + +2004-07-20 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data): + Fix double end-to-native symbol conversion (#148021). + +2004-07-20 David Schleef + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_decorate): + Don't use an Atom that doesn't exist. + +2004-07-20 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_get_stats), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer): + * gst/tcp/gstmultifdsink.h: + More multifdsink stats. Avoid deadlock by releasing locks + before sending out a signal. + +2004-07-20 Thomas Vander Stichele + + * po/LINGUAS: + * po/hu.po: + added Hungarian translation (Laszlo Dvornik) + +2004-07-20 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer): + * gst/tcp/gsttcp-marshal.list: + Fixed the stupid marshal definition. + +2004-07-20 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_init), (gst_multifdsink_add), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_queue_buffer), (gst_multifdsink_chain), + (gst_multifdsink_set_property), (gst_multifdsink_get_property), + (gst_multifdsink_init_send): + * gst/tcp/gstmultifdsink.h: + Added more stats, added timeout for a client, fixed some typos + and added some comments. + +2004-07-20 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_class_init), + (gst_multifdsink_add), (gst_multifdsink_get_stats), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_write): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcp-marshal.list: + Added get_stats method that returns a GValueArray of + stats values. + +2004-07-19 Benjamin Otte + + * ext/ladspa/gstladspa.c: (gst_ladspa_base_init): + make sure longname, description and author are valid UTF-8 + +2004-07-19 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_change_state), + (gst_ximagesink_set_property): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_change_state), + (gst_xvimagesink_set_property): + make sure SYNCHRONOUS is respected after getting the X context + +2004-07-18 Thomas Vander Stichele + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_handle_src_event), + (gst_matroska_demux_parse_blockgroup): + * gst/matroska/matroska-ids.h: + add BlockReference tag and ignore it to clear out log. + ignore NAVIGATION events to clear out log. + +2004-07-18 Thomas Vander Stichele + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_class_init), + (gst_matroska_demux_add_stream): + * gst/matroska/matroska-mux.c: (gst_matroska_mux_class_init): + add debug categories + +2004-07-16 Wim Taymans + + * ext/libpng/Makefile.am: + * ext/libpng/gstpng.c: (plugin_init): + * ext/libpng/gstpngdec.c: (user_error_fn), (user_warning_fn), + (gst_pngdec_get_type), (gst_pngdec_base_init), + (gst_pngdec_class_init), (gst_pngdec_sinklink), (gst_pngdec_init), + (gst_pngdec_src_getcaps), (user_read_data), (gst_pngdec_chain): + * ext/libpng/gstpngdec.h: + Added png decoder. + +2004-07-16 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror), + (gst_ximagesink_check_xshm_calls), (gst_ximagesink_ximage_new), + (gst_ximagesink_ximage_destroy), (gst_ximagesink_sink_link), + (gst_ximagesink_chain), (gst_ximagesink_buffer_free), + (gst_ximagesink_buffer_alloc): + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_destroy), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_free), + (gst_xvimagesink_buffer_alloc): + * sys/xvimage/xvimagesink.h: Getting the 2 video sinks synchronized + again. Using internal data pointer of the x(v)image to store image's + data to be coherent with the buffer alloc mechanism. Investigated the + image destruction code to be sure that everything gets freed correctly. + +2004-07-16 Wim Taymans + + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_vids_with_data), + (gst_riff_read_strf_auds_with_data): + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query), + (gst_avi_demux_add_stream), (gst_avi_demux_stream_header): + Make sure we don't create 0 sized subbuffers in riff-read. + Signal the no more pads signal after reading the avi header. + +2004-07-16 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_is_dynamic), + (gst_decode_bin_factory_filter), (compare_ranks), (print_feature), + (gst_decode_bin_init), (gst_decode_bin_dispose), + (find_compatibles), (close_pad_link), (try_to_link_1), (new_pad), + (no_more_pads), (close_link), (type_found), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (gst_decode_bin_change_state), (plugin_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type), + (gst_play_base_bin_class_init), (gst_play_base_bin_init), + (gst_play_base_bin_dispose), (queue_overrun), + (gen_preroll_element), (remove_prerolls), (unknown_type), + (no_more_pads), (new_stream), (setup_source), + (gst_play_base_bin_set_property), (gst_play_base_bin_get_property), + (play_base_eos), (gst_play_base_bin_change_state), + (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream), + (gst_play_base_bin_unlink_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybasebin.h: + Better error recovery. Added configurable preroll queue size. Faster + detection of no-more-pads. + +2004-07-16 Wim Taymans + + * gst-libs/gst/video/video.h: + Added 32 bits RGBA. Not sure if we should use another mime-type + for alpha rgb. Currently the presence of the alpha_mask property + signals an alpha channel. + +2004-07-16 Wim Taymans + + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + FPS seems to be 0.0 to MAX everywhere else. + +2004-07-15 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + mp42/mp43 (no caps) exist too. + * gst/matroska/matroska-demux.c: (gst_matroska_demux_video_caps): + Set pixel_width/height; we've got them in-caps. + * gst/typefind/gsttypefindfunctions.c: (plugin_init): + * gst/wavparse/gstwavparse.c: (plugin_init): + Both are valid primary. + * sys/oss/gstossmixer.c: + Remove i18n hack and enable translations. + +2004-07-15 Benjamin Otte + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_destroy): + fix for non-shm xv. Original patch by Tim Ringenbach (fixes #147248) + +2004-07-15 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_open_audio), + (gst_alsa_sw_params_dump), (gst_alsa_hw_params_dump), + (gst_alsa_close_audio): + disable some of the debugging code for now. Writing debugging to a + buffer is broken in current alsalib releases. + +2004-07-12 Benjamin Otte + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_alloc_buffer): + use bufferpools + +2004-07-14 Thomas Vander Stichele + + * ext/theora/theoradec.c: (gst_theora_dec_class_init), + (theora_dec_src_query), (theora_dec_event): + * ext/theora/theoraenc.c: (gst_theora_enc_class_init): + add debugging categories. Remove \n's. + +2004-07-13 Johan Dahlin + + * gst/playback/gstplaybin.c (gst_play_bin_set_property) + (gst_play_bin_get_property): Impl. + +2004-07-13 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_seek_before): + When trying to find the stream length, seek back N pages + instead of just one, where N is the number of streams in + the current chain. + +2004-07-13 Wim Taymans + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_audio_caps_with_data), + (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + * gst-libs/gst/riff/riff-media.h: + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_vids_with_data), + (gst_riff_read_strf_auds_with_data), (gst_riff_read_strf_auds): + * gst-libs/gst/riff/riff-read.h: + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query), + (gst_avi_demux_add_stream): + Set codec_data on caps for avidemuxer. + +2004-07-12 David Schleef + + * configure.ac: Fix test for Objective C + +2004-07-12 Jan Schmidt + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_get_capslist), + (gst_gdk_pixbuf_chain): + Add svg and pcx to template caps, and ensure that getcaps returns a + subset of the template caps. + Copy each row manually for output, as gdkpixbuf may pad the + rowstride to a 32-bit word boundary. + +2004-07-12 Wim Taymans + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps), + (gst_riff_create_video_template_caps): + Fix the template caps to include some more media types. + +2004-07-12 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_factory_filter), + (compare_ranks), (print_feature), (gst_decode_bin_init), + (gst_decode_bin_dispose), (find_compatibles), (close_pad_link), + (try_to_link_1), (new_pad), (close_link), (type_found), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (gst_decode_bin_change_state), (plugin_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type), + (gst_play_base_bin_class_init), (gst_play_base_bin_init), + (gst_play_base_bin_dispose), (queue_overrun), + (gen_preroll_element), (remove_prerolls), (no_more_pads), + (new_stream), (setup_source), (gst_play_base_bin_set_property), + (gst_play_base_bin_get_property), (play_base_eos), + (gst_play_base_bin_change_state), (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream), + (gst_play_base_bin_unlink_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_set_property), + (gst_play_bin_get_property), (gen_video_element), + (gen_audio_element), (remove_sinks), (setup_sinks), + (gst_play_bin_change_state), (gst_play_bin_get_event_masks), + (gst_play_bin_send_event), (gst_play_bin_get_formats), + (gst_play_bin_convert), (gst_play_bin_get_query_types), + (gst_play_bin_query), (plugin_init): + * gst/playback/test4.c: (main): + More fixes on reusing of the element. + +2004-07-11 Benjamin Otte + + * ext/mad/gstmad.c: (normal_seek): + allow seeking for other methods than just SET + +2004-07-11 Andy Wingo + + * gst/audioconvert/gstaudioconvert.c (gst_audio_convert_link): For + float, "any" caps -> buffer_frames=[0,MAX]. + + * gst/interleave/interleave.c (interleave_getcaps): Seems the core + doesn't intersect our caps with the template any more. Do it + ourselves. + (interleave_buffered_loop): Use g_newa instead of malloc/free. + +2004-07-09 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_factory_filter), + (compare_ranks), (print_feature), (gst_decode_bin_init), + (gst_decode_bin_dispose), (find_compatibles), (close_pad_link), + (try_to_link_1), (new_pad), (close_link), (type_found), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (gst_decode_bin_change_state), (plugin_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type), + (gst_play_base_bin_class_init), (gst_play_base_bin_init), + (gst_play_base_bin_dispose), (queue_overrun), + (gen_preroll_element), (remove_prerolls), (no_more_pads), + (new_stream), (setup_source), (gst_play_base_bin_set_property), + (gst_play_base_bin_get_property), (play_base_eos), + (gst_play_base_bin_change_state), (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream), + (gst_play_base_bin_unlink_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_set_property), + (gst_play_bin_get_property), (gen_video_element), + (gen_audio_element), (remove_sinks), (setup_sinks), + (gst_play_bin_change_state), (gst_play_bin_get_event_masks), + (gst_play_bin_send_event), (gst_play_bin_get_formats), + (gst_play_bin_convert), (gst_play_bin_get_query_types), + (gst_play_bin_query), (plugin_init): + * gst/playback/test4.c: (main): + Work on object reuse and seeking. + +2004-07-09 Wim Taymans + + * examples/seeking/seek.c: (iterate): + Don't consume all CPU in the idle loop. + +2004-07-09 Wim Taymans + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_new_output_pad), + (gst_mpeg_demux_parse_packet), (gst_mpeg_demux_process_private): + Add pad to element *after* setting the pad functions so that + the scheduler can use the correct ones. + +2004-07-09 Wim Taymans + + * ext/theora/theoradec.c: (theora_dec_from_granulepos), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_chain): + Sync to keyframe after seek + +2004-07-09 Thomas Vander Stichele + + * ext/alsa/gstalsa.c: (gst_alsa_change_state): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event), + (gst_alsa_sink_loop), (gst_alsa_sink_change_state): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_change_state): + * ext/libvisual/visual.c: (gst_visual_change_state): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_change_state): + * ext/theora/theoradec.c: (theora_dec_change_state): + * ext/theora/theoraenc.c: (theora_enc_change_state): + * ext/vorbis/vorbisdec.c: (vorbis_dec_change_state): + * gst-libs/gst/navigation/navigation.c: + * gst/adder/gstadder.c: (gst_adder_change_state): + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_chain), + (gst_audio_convert_get_buffer): + * gst/multipart/multipartdemux.c: + (gst_multipart_demux_change_state): + * gst/playback/gstdecodebin.c: (gst_decode_bin_change_state): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_change_state): + * gst/playback/gstplaybin.c: (gst_play_bin_change_state): + * gst/videoscale/gstvideoscale.c: + (gst_videoscale_handle_src_event): + * gst/volume/gstvolume.c: (volume_chain_int16): + don't assert in state change, this should be done by the base + GstElement class. + various debugging fixes. + +2004-07-08 Thomas Vander Stichele + + * configure.ac: + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup), + (gst_play_dispose), (gst_play_set_location), + (gst_play_set_data_src), (gst_play_set_video_sink), + (gst_play_set_audio_sink), (gst_play_set_visualization), + (gst_play_connect_visualization), (gst_play_get_sink_element), + (gst_play_get_all_by_interface): + * gst-libs/gst/play/play.h: + add new method to get elements implementing an interface. + add various error logging + +2004-07-08 Wim Taymans + + * examples/seeking/seek.c: (make_dv_pipeline), (make_avi_pipeline), + (make_mpeg_pipeline), (make_mpegnt_pipeline), + (make_playerbin_pipeline), (query_durations_elems), + (query_durations_pads), (query_positions_elems), + (query_positions_pads), (update_scale), (iterate), (stop_seek), + (main): + Added playbin seeking example. + +2004-07-08 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_set_location), + (gst_play_set_data_src), (gst_play_set_video_sink), + (gst_play_set_audio_sink), (gst_play_set_visualization), + (gst_play_connect_visualization), (gst_play_get_framerate): + use a macro to look up elements from hash table + +2004-07-08 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup), + (gst_play_get_length_callback), (gst_play_set_location), + (gst_play_seek_to_time), (gst_play_set_data_src), + (gst_play_set_video_sink), (gst_play_set_audio_sink), + (gst_play_set_visualization), (gst_play_connect_visualization), + (gst_play_get_sink_element): + - add debugging info + - fix looking up sink elements by iterating over complete caps + - put everything except for source and autoplugger in a complete bin + +2004-07-08 Thomas Vander Stichele + + * ext/alsa/gstalsa.c: (gst_alsa_drain_audio): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_flush_one_pad), + (gst_alsa_sink_check_event), (gst_alsa_sink_mmap), + (gst_alsa_sink_write), (gst_alsa_sink_loop): + * ext/alsa/gstalsasink.h: + - add debugging info + - clean up schizophrenia of data/buffer/event + - fix double event unref error + +2004-07-08 Wim Taymans + + * gst/playback/Makefile.am: + Add headers to noinst + +2004-07-08 Thomas Vander Stichele + + * tools/gst-launch-ext-m.m: + * tools/gst-launch-ext.1.in: + convert to the third millenium + +2004-07-07 David Schleef + + * sys/dxr3/Makefile.am: noinst_SOURCES should be nodist_SOURCES + +2004-07-07 Wim Taymans + + * gst/playback/Makefile.am: + * gst/playback/README: + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_factory_filter), + (compare_ranks), (print_feature), (gst_decode_bin_init), + (gst_decode_bin_dispose), (find_compatibles), (close_pad_link), + (try_to_link_1), (new_pad), (close_link), (type_found), + (gst_decode_bin_set_property), (gst_decode_bin_get_property), + (plugin_init): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type), + (gst_play_base_bin_class_init), (gst_play_base_bin_init), + (gst_play_base_bin_dispose), (rebuild_pipeline), (queue_overrun), + (gen_preroll_element), (no_more_pads), (new_stream), + (setup_source), (gst_play_base_bin_set_property), + (gst_play_base_bin_get_property), (gst_play_base_bin_change_state), + (gst_play_base_bin_add_element), + (gst_play_base_bin_remove_element), + (gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream), + (gst_play_base_bin_unlink_stream), + (gst_play_base_bin_get_streaminfo): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_dispose), (gst_play_bin_set_property), + (gst_play_bin_get_property), (gen_video_element), + (gen_audio_element), (setup_sinks), (gst_play_bin_change_state), + (gst_play_bin_get_event_masks), (gst_play_bin_send_event), + (gst_play_bin_get_formats), (gst_play_bin_convert), + (gst_play_bin_get_query_types), (gst_play_bin_query), + (plugin_init): + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), + (gst_stream_info_get_type), (gst_stream_info_class_init), + (gst_stream_info_init), (gst_stream_info_new), + (gst_stream_info_dispose), (gst_stream_info_set_property), + (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + * gst/playback/test.c: (gen_video_element), (gen_audio_element), + (main): + * gst/playback/test2.c: (main): + * gst/playback/test3.c: (update_scale), (main): + More playbin fixes. Added README. Do better element filtering. + Added base class to preroll media. Added test apps. + +2004-07-07 Thomas Vander Stichele + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_flush_decoder): + * ext/mpeg2dec/gstmpeg2dec.h: + various debugging improvements. Reset stream to next picture + instead of sequence header, otherwise seeks cannot work. + +2004-07-07 Wim Taymans + + * gst/videobox/gstvideobox.c: (gst_video_box_fill_get_type), + (gst_video_box_class_init), (gst_video_box_set_property), + (gst_video_box_i420), (gst_video_box_ayuv), (gst_video_box_chain): + Use pad_alloc where possible. + +2004-07-07 Wim Taymans + + * sys/oss/gstosselement.c: (gst_osselement_reset), + (gst_osselement_parse_caps): + * sys/oss/gstosselement.h: + * sys/oss/gstosssrc.c: (gst_osssrc_get): + Fix offset on osssrc. + +2004-07-07 Wim Taymans + + * ext/theora/theora.c: (plugin_init): + * ext/theora/theoradec.c: (theora_dec_from_granulepos), + (theora_dec_src_query), (theora_dec_chain): + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_sink_link), (theora_buffer_from_packet), + (theora_push_packet), (theora_enc_chain): + Fix theora granulepos calculation. + Fix overflow in duration/position calculation. + Bump rank to PRIMARY for theoradec. + Use granulepos of last packet to calculate position. + Set keyframe flag on buffers when needed. + +2004-07-06 David Schleef + + * gst/playback/Makefile.am: 'test' in bin_PROGRAMS? Are you + serious? (Fixed, obviously.) + +2004-07-06 Thomas Vander Stichele + + * po/LINGUAS: + * po/cs.po: + added Czech translation (Miloslav Trmac) + +2004-07-05 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_factory_filter), + (compare_ranks), (gst_decode_bin_init), (gst_decode_bin_dispose), + (find_compatibles), (close_pad_link), (try_to_link_1), (new_pad), + (close_link), (type_found), (gst_decode_bin_set_property), + (gst_decode_bin_get_property), (gst_decode_bin_get_event_masks), + (gst_decode_bin_send_event), (gst_decode_bin_get_formats), + (gst_decode_bin_convert), (gst_decode_bin_get_query_types), + (gst_decode_bin_query), (plugin_init): + * gst/playback/gstplaybin.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_dispose), (rebuild_pipeline), (get_audio_element), + (get_video_element), (new_pad), (setup_source), + (gst_play_bin_set_property), (gst_play_bin_get_property), + (gst_play_bin_change_state), (gst_play_bin_add_element), + (gst_play_bin_remove_element), (gst_play_bin_get_event_masks), + (gst_play_bin_send_event), (gst_play_bin_get_formats), + (gst_play_bin_convert), (gst_play_bin_get_query_types), + (gst_play_bin_query), (gst_play_bin_get_clock), (plugin_init): + * gst/playback/test.c: (main): + More fixes, cleaned up playbin, make it use decodebin. Added + threaded property to playbin. + +2004-07-05 Wim Taymans + + * configure.ac: + * gst/playback/Makefile.am: + * gst/playback/decodetest.c: (main): + * gst/playback/gstdecodebin.c: (gst_decode_bin_get_type), + (gst_decode_bin_class_init), (gst_decode_bin_factory_filter), + (compare_ranks), (gst_decode_bin_init), (gst_decode_bin_dispose), + (find_compatibles), (close_pad_link), (try_to_link_1), (new_pad), + (close_link), (type_found), (gst_decode_bin_set_property), + (gst_decode_bin_get_property), (gst_decode_bin_change_state), + (gst_decode_bin_get_event_masks), (gst_decode_bin_send_event), + (gst_decode_bin_get_formats), (gst_decode_bin_convert), + (gst_decode_bin_get_query_types), (gst_decode_bin_query), + (plugin_init): + * gst/playback/gstplaybin.c: (gst_play_bin_get_type), + (gst_play_bin_class_init), (gst_play_bin_init), + (gst_play_bin_dispose), (gen_default_output), (rebuild_pipeline), + (collect_sink_pads), (find_compatibles), (close_pad_link), + (try_to_link_1), (new_pad), (close_link), (type_found), + (setup_source), (gst_play_bin_set_property), + (gst_play_bin_get_property), (gst_play_bin_factory_filter), + (compare_ranks), (gst_play_bin_collect_factories), + (gst_play_bin_change_state), (gst_play_bin_add_element), + (gst_play_bin_remove_element), (gst_play_bin_get_event_masks), + (gst_play_bin_send_event), (gst_play_bin_get_formats), + (gst_play_bin_convert), (gst_play_bin_get_query_types), + (gst_play_bin_query), (gst_play_bin_get_clock), (plugin_init): + * gst/playback/test.c: (main): + Added some playback helper elements and some test apps, very alpha + still. + +2004-07-04 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_xrun_recovery): + only restart audio when we indeed have an xrun to fix repeated + xruns. Fix suggested by Giuliano Pochini. + +2004-07-03 David Schleef + + * ext/alsa/gstalsaplugin.c: (gst_alsa_error_wrapper): Disable + call to gst_debug_log() if debugging is disabled (bug #145118) + +2004-07-03 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_xrun_recovery): + use our own functions for restarting the alsa device. + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + I should apply patches myself - use MIN for the third argument, not + the second, this fixes seeking + +2004-07-02 David Schleef + + * ext/flac/gstflacdec.c: (gst_flacdec_class_init), + (gst_flacdec_write): Actually, GST_PAD_CAPS() has nothing to + do with the logic. + +2004-07-02 David Schleef + + * ext/flac/gstflacdec.c: (gst_flacdec_write): Set duration on + output buffers. Fix logic mistake. (bug #144866) + +2004-07-02 David Schleef + + * gst-libs/gst/xoverlay/Makefile.am: xoverlay no longer depends + on X. (bug #144753) + +2004-07-02 David Schleef + + * gst/wavenc/gstwavenc.c: (gst_wavenc_setup), + (gst_wavenc_stop_file): Switch to GST_WRITE_UINT32_LE macros + (bug #144624) + * sys/oss/gstosselement.c: (gst_osselement_probe_caps), + (gst_osselement_rate_probe_check): Add another workaround for + buggy drivers (bug #145336) + +2004-07-02 David Schleef + + * gst/tcp/gstmultifdsink.c: (gst_multifdsink_handle_client_write): + Most systems don't have MSG_NOSIGNAL. + +2004-07-02 Thomas Vander Stichele + + * Makefile.am: + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/tuner/Makefile.am: + (hopefully) fix both install and dist and make error message useful. + needs testing across automakes. + +2004-07-02 Benjamin Otte + + * ext/ogg/gstogg.c: (plugin_init): + we require bytestream now + * ext/ogg/gstoggdemux.c: + huge diff to implement chain setup in a fast and generic way. This + improves tag reading and startup of huge files (read: Theora videos) + quite a bit. It probably contains bugs, too, so please test. + Seeking is not improved to the fast method. + +2004-06-29 Wim Taymans + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + * ext/ogg/gstoggmux.c: + Fix memleak in oggdemux when running unconnected pads. + doc update in mux, start working on keyframe mode. + +2004-06-29 Benjamin Otte + + * sys/oss/gstosssink.c: + * sys/oss/gstosssrc.c: + advertise correct template caps - we indeed do non-native endianness + and 8bit audio has no endianness + * sys/ximage/ximagesink.c: (gst_ximagesink_getcaps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_getcaps): + avoid (wrong) duplications in getcaps function and return + template caps + +2004-06-29 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_recover_policy_get_type), + (gst_multifdsink_class_init), (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_clear), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_caps), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_thread), + (gst_multifdsink_init_send), (gst_multifdsink_close): + Fix wrong GList iteration that could crash the server when + more then 2 clients disconnect at the same time. Read all the + pending commands in one batch to recover from command storms under + very heavy load. + +2004-06-28 Wim Taymans + + * gst/videomixer/videomixer.c: (gst_videomixer_pad_get_type), + (gst_videomixer_pad_class_init), (gst_videomixer_pad_get_property), + (gst_videomixer_pad_set_property), + (gst_videomixer_pad_sinkconnect), (gst_videomixer_pad_init), + (gst_video_mixer_background_get_type), (gst_videomixer_get_type), + (gst_videomixer_class_init), (gst_videomixer_init), + (gst_videomixer_request_new_pad), (gst_videomixer_blend_ayuv_i420), + (pad_zorder_compare), (gst_videomixer_sort_pads), + (gst_videomixer_fill_checker), (gst_videomixer_fill_color), + (gst_videomixer_fill_queues), (gst_videomixer_blend_buffers), + (gst_videomixer_update_queues), (gst_videomixer_loop), + (plugin_init): + Avoid divide by zero, choose masterpad as the pad with the highest + framerate. + +2004-06-27 Julien Moutte + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_decorate), + (gst_ximagesink_xwindow_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_decorate), + (gst_xvimagesink_xwindow_new): I prefer locking the mutex in the + function directly. We might want to call it from somewhere else one day. + +2004-06-27 Julien Moutte + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_decorate), + (gst_ximagesink_xwindow_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_decorate), + (gst_xvimagesink_xwindow_new): Trying to fix the random behaviour of + window decorations. + +2004-06-27 Wim Taymans + + * ext/dv/gstdvdec.c: (gst_dvdec_class_init), (gst_dvdec_init), + (gst_dvdec_video_getcaps), (gst_dvdec_video_link), + (gst_dvdec_push), (gst_dvdec_loop), (gst_dvdec_change_state), + (gst_dvdec_set_property), (gst_dvdec_get_property): + * ext/dv/gstdvdec.h: + Implement drop_factor property to lower the framerate with + a factor. + +2004-06-27 Thomas Vander Stichele + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/tuner/Makefile.am: + unbreak Company's fix that didn't install the -enum.h files + +2004-06-27 Wim Taymans + + * ext/dv/gstdvdec.c: (gst_dvdec_push), (gst_dvdec_loop), + (gst_dvdec_change_state): + * ext/dv/gstdvdec.h: + Fix timestamp, duration and offset of the buffers. + +2004-06-27 Wim Taymans + + * gst/tcp/gstmultifdsink.c: (gst_recover_policy_get_type), + (gst_multifdsink_class_init), (gst_multifdsink_add), + (gst_multifdsink_remove), (gst_multifdsink_clear), + (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_caps), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_thread), + (gst_multifdsink_init_send), (gst_multifdsink_close): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpserversink.c: + (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_handle_select), (gst_tcpserversink_close): + More multifdsink fixes, more recovery policy fixes. + Removed stupid g_print + +2004-06-26 Wim Taymans + + * gst/tcp/Makefile.am: + * gst/tcp/gstmultifdsink.c: (gst_recover_policy_get_type), + (gst_multifdsink_get_type), (gst_multifdsink_base_init), + (gst_multifdsink_class_init), (gst_multifdsink_init), + (gst_multifdsink_debug_fdset), (gst_multifdsink_client_remove), + (gst_multifdsink_handle_client_read), + (gst_multifdsink_client_queue_data), + (gst_multifdsink_client_queue_caps), + (gst_multifdsink_client_queue_buffer), + (gst_multifdsink_handle_client_write), + (gst_multifdsink_recover_client), (gst_multifdsink_queue_buffer), + (gst_multifdsink_handle_clients), (gst_multifdsink_thread), + (gst_multifdsink_chain), (gst_multifdsink_set_property), + (gst_multifdsink_get_property), (gst_multifdsink_init_send), + (gst_multifdsink_close), (gst_multifdsink_change_state): + * gst/tcp/gstmultifdsink.h: + * gst/tcp/gsttcpplugin.c: (plugin_init): + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_get_type), + (gst_tcpserversink_class_init), (gst_tcpserversink_init), + (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_handle_select), + (gst_tcpserversink_set_property), (gst_tcpserversink_get_property), + (gst_tcpserversink_init_send), (gst_tcpserversink_close): + * gst/tcp/gsttcpserversink.h: + Added multifdsink, made tcpserversink a subclass of fdsink, removed + one of the locks, added recovery policy to multifdsink. + +2004-06-26 Thomas Vander Stichele + + * gst/videorate/gstvideorate.c: (gst_videorate_chain): + fix decision for when getting frames with same timestamp + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init), + (gst_v4lsrc_get), (gst_v4lsrc_set_property), + (gst_v4lsrc_get_property): + * sys/v4l/gstv4lsrc.h: + add latency offset property + +2004-06-26 Thomas Vander Stichele + + * gst/videorate/gstvideorate.c: (gst_videorate_chain), + (plugin_init): + fix debugging. add category. + +2004-06-25 Thomas Vander Stichele + + * gst/sine/gstsinesrc.c: (gst_sinesrc_get): + fix wrong offsets + +2004-06-25 Thomas Vander Stichele + + * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), + (gst_alsa_src_get_time), (gst_alsa_src_loop), + (gst_alsa_src_change_state): + return a time that is in sync with the element's processing + +2004-06-25 Wim Taymans + + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init), + (gst_tcpserversink_init), (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_client_remove), + (gst_tcpserversink_handle_client_read), + (gst_tcpserversink_client_queue_data), + (gst_tcpserversink_client_queue_caps), + (gst_tcpserversink_client_queue_buffer), + (gst_tcpserversink_handle_client_write), + (gst_tcpserversink_queue_buffer), + (gst_tcpserversink_handle_clients), (gst_tcpserversink_thread), + (gst_tcpserversink_chain), (gst_tcpserversink_set_property), + (gst_tcpserversink_get_property), (gst_tcpserversink_init_send), + (gst_tcpserversink_close): + * gst/tcp/gsttcpserversink.h: + Serversink rewrite. Really do non blocking writes to clients and + maintain an internal queue to handle slower clients while not + disturbing fast clients. + +2004-06-25 Thomas Vander Stichele + + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get): + better debug, don't override OFFSET and OFFSET_END + +2004-06-25 Iain + + * gst-libs/gst/media-info/media-info-priv.c (gmi_set_mime): Add + name=source for the wavparse pipeline. + +2004-06-24 Johan Dahlin + + * ext/theora/theoraenc.c (theora_enc_chain): Call + gst_pad_try_set_caps instead of gst_pad_set_explicit_caps so the + streamheader caps are set correctly. + +2004-06-24 Thomas Vander Stichele + + * ext/vorbis/vorbisenc.c: (raw_caps_factory), + (gst_vorbisenc_setup), (gst_vorbisenc_set_property): + respect minimum bitrate; same could be done for max bitrate + +2004-06-24 Thomas Vander Stichele + + * ext/vorbis/vorbisenc.c: (raw_caps_factory), + (gst_vorbisenc_setup): + fix sample rate range + +2004-06-24 Thomas Vander Stichele + + * ext/vorbis/oggvorbisenc.c: (gst_oggvorbisenc_class_init), + (gst_oggvorbisenc_setup): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_class_init), + (gst_vorbisenc_setup): + resolve ambiguities in code and description + +2004-06-24 Wim Taymans + + * ext/alsa/gstalsa.c: (gst_alsa_start), (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), + (gst_alsa_src_update_avail), (gst_alsa_src_loop): + Use alsa trigger_tstamp to get the timestamp of the first + sample in the buffer for more precise sync. Some cleanups. + +2004-06-24 Wim Taymans + + * gst/audiorate/gstaudiorate.c: (gst_audiorate_link), + (gst_audiorate_init), (gst_audiorate_chain), + (gst_audiorate_set_property), (gst_audiorate_get_property): + * gst/videorate/gstvideorate.c: (gst_videorate_class_init), + (gst_videorate_chain): + Added some logging, fixed an overflow bug in videorate. + +2004-06-24 Benjamin Otte + + * ext/kio/Makefile.am: + fix for builddir != srcdir and distcheck + +2004-06-24 Benjamin Otte + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/tuner/Makefile.am: + * gst/tcp/Makefile.am: + * sys/dxr3/Makefile.am: + don't include -enumtypes.[ch] or -marshal.[ch] files in the disted + tarball. + Also add all *.list files that were missing. + * Makefile.am: + add a distcheck hook to ensure the above doesn't happen again. + +2004-06-23 David I. Lehn + + * ext/Makefile.am: s/DTS_DIR=dvdread/DTS_DIR=dts/ + +2004-06-23 Colin Walters + + * m4/Makefile.am: Distribute gst-fionread.m4. + +2004-06-23 Thomas Vander Stichele + + * configure.ac: back to dev + +2004-06-23 Wim Taymans + + * ext/alsa/gstalsa.c: (gst_alsa_change_state), (gst_alsa_start), + (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event), + (gst_alsa_sink_loop), (gst_alsa_sink_get_time): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), + (gst_alsa_src_get_time), (gst_alsa_src_update_avail), + (gst_alsa_src_loop): + Add clock to alsasrc. Take new capture timestamp when + restarting after an overrun. Split up some functions between + alsasrc and alsasink. + +=== release 0.8.2 === + +2004-06-23 Thomas Vander Stichele + + * ext/alsa/gstalsa.c: (gst_alsa_init), (gst_alsa_dispose), + (gst_alsa_change_state), (gst_alsa_update_avail), + (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + merge back changes from release + +2004-06-23 Wim Taymans + + * gst/audiorate/gstaudiorate.c: (gst_audiorate_class_init), + (gst_audiorate_init), (gst_audiorate_chain), + (gst_audiorate_set_property), (gst_audiorate_get_property): + Implement sample dropping and notify + +2004-06-22 Wim Taymans + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_sink_link), (theora_buffer_from_packet), + (theora_push_packet), (theora_enc_chain): + Some cleanups, make sure the timestamps are correct. + +2004-06-22 Wim Taymans + + * ext/alsa/gstalsa.c: (gst_alsa_get_time), (gst_alsa_clock_update), + (gst_alsa_change_state), (gst_alsa_update_avail), + (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasrc.c: (gst_alsa_src_loop): + Cleanups, take queued samples into account when reporting + the time. + +2004-06-22 Wim Taymans + + * gst/videorate/gstvideorate.c: (gst_videorate_class_init), + (gst_videorate_init): + Initialize the property as well. + +2004-06-22 Wim Taymans + + * gst/videorate/gstvideorate.c: (gst_videorate_class_init), + (gst_videorate_init), (gst_videorate_chain), + (gst_videorate_set_property), (gst_videorate_get_property): + Add property to make videorate silent. + Add property to prefer new frames over old ones. + +2004-06-22 Zaheer Abbas Merali + + * sys/osxvideo/Makefile.am: + Workaround so that the osxvideo .so file gets linked with the + Cocoa, OpenGL and QuickTime frameworks + +2004-06-22 Zaheer Abbas Merali + + * sys/osxaudio/Makefile.am: + Workaround so that the osxaudio .so file gets linked with the + CoreAudio framework + +2004-06-22 Zaheer Abbas Merali + + * configure.ac: + Whoops, my fault...fixed build issues + +2004-06-22 Zaheer Abbas Merali + + * configure.ac: + Add objective-c support if running in Darwin/Mac OS X + * sys/Makefile.am: + * sys/osxvideo: + * sys/osxvideo/Makefile.am: + * sys/osxvideo/osxvideosink.h: + * sys/osxvideo/osxvideosink.m: + * sys/osxvideo/cocoawindow.h: + * sys/osxvideo/cocoawindow.m: + Add osxvideosink, a cocoa-based osx video sink + + +2004-06-19 Jan Schmidt + * ext/dvdnav/gst-dvd: + Grab the gconf key from the right spot + * gst/debug/gstnavseek.c: (gst_navseek_init), + (gst_navseek_segseek), (gst_navseek_handle_src_event), + (gst_navseek_chain): + * gst/debug/gstnavseek.h: + Add 's', 'e' and 'l' keypresses to navseek to define the start,end + and loop parameters of a segment seek. + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_init), + (gst_videotestsrc_get_event_masks), + (gst_videotestsrc_handle_src_event), (gst_videotestsrc_get): + * gst/videotestsrc/gstvideotestsrc.h: + Add seeking support to videotestsrc + Initialise the timestamp_offset variable. + +2004-06-18 Wim Taymans + + * ext/sidplay/gstsiddec.cc: + Fix negotiation and set correct end offset. + +2004-06-18 Thomas Vander Stichele + + * configure.ac: branch and prerelease + +2004-06-17 Thomas Vander Stichele + + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_init), + (gst_tcpclientsrc_getcaps), (gst_tcpclientsrc_get), + (gst_tcpclientsrc_init_receive): + * gst/tcp/gsttcpclientsrc.h: + read caps when connecting to server for GDP so we set them correctly + +2004-06-17 Thomas Vander Stichele + + * gst/videorate/gstvideorate.c: (gst_videorate_chain): + notify drops and duplicates + * gst/videoscale/videoscale.c: (videoscale_get_structure): + no good reason to limit ourselves to 100x100 + +2004-06-17 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init), + (gst_v4lsrc_open), (gst_v4lsrc_src_link), (gst_v4lsrc_getcaps), + (gst_v4lsrc_get), (gst_v4lsrc_set_property), + (gst_v4lsrc_get_property): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4l_calls.c: (gst_v4l_set_window_properties), + (gst_v4l_open), (gst_v4l_get_picture), (gst_v4l_get_audio), + (gst_v4l_set_audio): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_grab_frame), + (gst_v4lsrc_try_capture): + * sys/v4l/v4lsrc_calls.h: + change try_palette to more general try_capture + add autoprobe option so we can turn off autoprobing + various fixes + +2004-06-17 Thomas Vander Stichele + + * configure.ac: + add videorate + * sys/ximage/ximagesink.c: (gst_ximagesink_finalize), + (gst_ximagesink_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_finalize), + (gst_xvimagesink_class_init): + run them as finalize, not dispose, since dispose can be invoked + multiple times + +2004-06-17 Wim Taymans + + * ext/alsa/gstalsa.c: (gst_alsa_init), (gst_alsa_dispose), + (gst_alsa_get_time), (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsaclock.c: (gst_alsa_clock_get_type): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_init), (gst_alsa_src_loop), + (gst_alsa_src_change_state): + * ext/alsa/gstalsasrc.h: + Make the xrun code timestamp and offset the buffers correctly. + moved the clock to the base class, use alsa methods to get time. + Do correct timestamping on outgoing buffers. + +2004-06-17 Wim Taymans + + * gst/audiorate/Makefile.am: + * gst/audiorate/gstaudiorate.c: (gst_audiorate_get_type), + (gst_audiorate_base_init), (gst_audiorate_class_init), + (gst_audiorate_link), (gst_audiorate_init), (gst_audiorate_chain), + (gst_audiorate_set_property), (gst_audiorate_get_property), + (gst_audiorate_change_state), (plugin_init): + Added an audiorate converter that fills in gaps. + +2004-06-17 Johan Dahlin + + * ext/tcp/*: Revert Zaheer changes, to make things actually work again. + +2004-06-16 Wim Taymans + + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_get): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_sync_mode_get_type), + (gst_v4lsrc_class_init), (gst_v4lsrc_init), (gst_v4lsrc_get_fps), + (gst_v4lsrc_get), (gst_v4lsrc_set_property), + (gst_v4lsrc_get_property): + * sys/v4l/gstv4lsrc.h: + Added a copy mode to v4lsrc where it will output a copied version + of its internal hardware buffer. + Fix the wrong FLAG_SET usage. The flags are integers, not bits, you + can't | them. + +2004-06-16 Wim Taymans + + * sys/oss/gstosssrc.c: (gst_osssrc_get): + Timestamp fixes. + +2004-06-16 Wim Taymans + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_sync_mode_get_type), + (gst_v4lsrc_class_init), (gst_v4lsrc_init), (gst_v4lsrc_get_fps), + (gst_v4lsrc_get), (gst_v4lsrc_set_property), + (gst_v4lsrc_get_property): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay): + Added a sync mode enum property to control v4lsrc timestamp method + Removed the use-fixed-fps property and moved functionality in + the enum. + Don't error on an error value from v4l-conf, it might not always + be a real error. + +2004-06-16 Wim Taymans + + * gst/videorate/Makefile.am: + * gst/videorate/gstvideorate.c: (gst_videorate_get_type), + (gst_videorate_base_init), (gst_videorate_class_init), + (gst_videorate_getcaps), (gst_videorate_link), + (gst_videorate_init), (gst_videorate_chain), + (gst_videorate_set_property), (gst_videorate_get_property), + (gst_videorate_change_state), (plugin_init): + Added a video timestamp corrector. + +2004-06-15 Zaheer Abbas Merali + + fixed a potential leak with previous commit + + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head): + +2004-06-15 Zaheer Abbas Merali + + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head): + Added missing refcount, fixes bug #144425 + Cheers Tim for finding the bug + +2004-06-15 Thomas Vander Stichele + + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l/gstv4lcolorbalance.c: + * sys/v4l/gstv4lcolorbalance.h: + * sys/v4l/gstv4lelement.c: + * sys/v4l/gstv4lelement.h: + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): + * sys/v4l/gstv4lmjpegsink.h: + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): + * sys/v4l/gstv4lmjpegsrc.h: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get_fps_list), + (gst_v4lsrc_get_fps), (gst_v4lsrc_srcconnect), + (gst_v4lsrc_getcaps), (gst_v4lsrc_get): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/gstv4ltuner.c: + * sys/v4l/gstv4ltuner.h: + * sys/v4l/gstv4lxoverlay.c: + * sys/v4l/gstv4lxoverlay.h: + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay), + (gst_v4l_set_window), (gst_v4l_enable_overlay): + * sys/v4l/v4l_calls.c: (gst_v4l_set_window_properties), + (gst_v4l_open), (gst_v4l_get_picture), (gst_v4l_get_audio), + (gst_v4l_set_audio): + * sys/v4l/v4l_calls.h: + * sys/v4l/v4lmjpegsink_calls.c: (gst_v4lmjpegsink_sync_thread), + (gst_v4lmjpegsink_queue_frame), (gst_v4lmjpegsink_sync_frame), + (gst_v4lmjpegsink_set_buffer), (gst_v4lmjpegsink_set_playback), + (gst_v4lmjpegsink_playback_init), + (gst_v4lmjpegsink_playback_start), (gst_v4lmjpegsink_get_buffer), + (gst_v4lmjpegsink_play_frame), (gst_v4lmjpegsink_wait_frame), + (gst_v4lmjpegsink_playback_stop), + (gst_v4lmjpegsink_playback_deinit): + * sys/v4l/v4lmjpegsink_calls.h: + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_queue_frame), + (gst_v4lmjpegsrc_sync_next_frame), (gst_v4lmjpegsrc_set_buffer), + (gst_v4lmjpegsrc_set_capture), (gst_v4lmjpegsrc_set_capture_m), + (gst_v4lmjpegsrc_capture_init), (gst_v4lmjpegsrc_capture_start), + (gst_v4lmjpegsrc_grab_frame), (gst_v4lmjpegsrc_requeue_frame), + (gst_v4lmjpegsrc_capture_stop), (gst_v4lmjpegsrc_capture_deinit): + * sys/v4l/v4lmjpegsrc_calls.h: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_queue_frame), + (gst_v4lsrc_sync_frame), (gst_v4lsrc_set_capture), + (gst_v4lsrc_capture_init), (gst_v4lsrc_capture_start), + (gst_v4lsrc_grab_frame), (gst_v4lsrc_requeue_frame), + (gst_v4lsrc_capture_stop), (gst_v4lsrc_capture_deinit), + (gst_v4lsrc_try_palette): + * sys/v4l/v4lsrc_calls.h: + bunch of paranoia cleanups + +2004-06-14 David Schleef + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_init), + (cdparanoia_get), (cdparanoia_open), (cdparanoia_change_state): + Send discont events and change timestamps appropriately when + we get a seek event. (bug #144240) + * ext/cdparanoia/gstcdparanoia.h: + +2004-06-14 Benjamin Otte + + * ext/alsa/gstalsa.c: Use snd_pcm_hw_params_set_rate _near instead of + snd_pcm_hw_params_set_rate since the latter fails for no good + reason on some setups. + +2004-06-14 David Schleef + + * gst/volume/demo.c: (value_changed_callback): exp10() is not + standard. Thank you for playing. + +2004-06-14 Wim Taymans + + * gst/ffmpegcolorspace/imgconvert.c: (img_convert): + Patch 1.3 broke the ordering of the colorspace info and + made the plugin basically work by coincidence, reordered + the info. + +2004-06-14 Thomas Vander Stichele + + * ext/lame/gstlame.c: + * ext/mad/gstmad.c: + sync caps. Make sure mad can only output a list of rates, not + a full range. In the future, have three caps lists for each of the + mpeg versions. Change mpegversion to a double as well. + +2004-06-14 Thomas Vander Stichele + + * gst/volume/.cvsignore: + * gst/volume/Makefile.am: + * gst/volume/demo.c: (value_changed_callback), (idler), + (setup_gui), (main): + added small demo app + +2004-06-13 Jan Schmidt + * ext/esd/esdsink.c: (gst_esdsink_change_state): + * ext/esd/esdsink.h: + Close the esd connection on pause, because esd will just wait - + blocking all other esd clients indefinitely. + +2004-06-12 Christophe Fergeau + + * gst/tags/gstvorbistag.c: replaced a g_warning which I added in my + previous commit with GST_DEBUG + +2004-06-12 Thomas Vander Stichele + + * configure.ac: + add a header check for a dvdread header in dvdnav. Fixes #133002 + +2004-06-12 Zaheer Abbas Merali + + * gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_init_send): + * gst/tcp/gsttcpclientsink.h: + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_init_receive): + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_init), + (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_init_send): + * gst/tcp/gsttcpserversink.h: + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_init_receive): + * gst/tcp/gsttcpserversrc.h: + Modified the tcp plugins so they are portable (IPv4,IPv6, any future + version of IP) + +2004-06-12 Zaheer Abbas Merali + + * configure.ac: + Added ogg library so that OSX detects libtheora properly + +2004-06-11 Wim Taymans + + * ext/theora/theoradec.c: (theora_dec_chain), + (theora_dec_change_state): + Don't try to decode frames before we received a keyframe. + +2004-06-11 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init), + (gst_ogg_mux_init), (gst_ogg_mux_next_buffer), + (gst_ogg_mux_get_headers), (gst_ogg_mux_set_header_on_caps), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop), + (gst_ogg_mux_get_property), (gst_ogg_mux_set_property): + Added property to set the maximum delay of a page. + +2004-06-10 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_class_init), + (gst_ogg_mux_init), (gst_ogg_mux_next_buffer), + (gst_ogg_mux_get_headers), (gst_ogg_mux_set_header_on_caps), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop), + (gst_ogg_mux_get_property), (gst_ogg_mux_set_property): + Added max-delay property to control the maximum amount + of data to put in one page. + +2004-06-10 Wim Taymans + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (gst_theora_enc_init), (theora_enc_sink_link), + (theora_buffer_from_packet), (theora_enc_set_property), + (theora_enc_get_property): + Set duration on encoded buffer, added some more properties + +2004-06-10 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer), + (gst_ogg_mux_get_headers), (gst_ogg_mux_set_header_on_caps), + (gst_ogg_mux_send_headers), (gst_ogg_mux_loop): + * ext/theora/theoraenc.c: (theora_enc_chain): + Fix refcounting bugs + +2004-06-10 Ronald Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_init), + (gst_asf_demux_loop), (gst_asf_demux_process_file), + (gst_asf_demux_process_data), (gst_asf_demux_handle_data), + (gst_asf_demux_process_object), (gst_asf_demux_get_stream), + (gst_asf_demux_process_chunk), (gst_asf_demux_handle_sink_event), + (gst_asf_demux_handle_src_event), (gst_asf_demux_handle_src_query), + (gst_asf_demux_change_state): + * gst/asfdemux/gstasfdemux.h: + You know Chimaira? "I - HATE - EVERYTHING". Yeah, that's what this + feels like. I think we should set a new requirement for demuxers + from now on to implement sane loop functions, data loops, query + and seek functions before first commit into CVS. And this commit + fixes all of the above. + +2004-06-10 Christophe Fergeau + + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_add): make sure parsed + vorbis comments are properly encoded in UTF-8 before adding them + to a GstTagList + +2004-06-09 Benjamin Otte + + * ext/alsa/gstalsa.c: (add_channels): + handle min <= max correctly + * ext/alsa/gstalsa.c: (gst_alsa_fixate_to_mimetype), + (gst_alsa_fixate_field_nearest_int), (gst_alsa_fixate): + add fixation functions so we fixate correctly. No preferring of alaw + anymore because it's the first structure. + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsa.c: (gst_alsa_sw_params_dump), + (gst_alsa_hw_params_dump): + add functions to ease debugging in alsalib + * ext/alsa/gstalsa.c: (gst_alsa_probe_hw_params), + (gst_alsa_set_hw_params), (gst_alsa_set_sw_params), + (gst_alsa_start_audio): + only specify hw params if we really setup a format (fixes #134007 - + or at least works around it) + +2004-06-09 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_init), + (gst_ogg_mux_next_buffer), (gst_ogg_mux_buffer_from_page), + (gst_ogg_mux_push_page), (gst_ogg_mux_get_headers), + (gst_ogg_mux_set_header_on_caps), (gst_ogg_mux_send_headers), + (gst_ogg_mux_loop): + Use stream caps to setup the initial pages in the ogg stream. + Correctly set the streamheader caps on the srcpad. + +2004-06-09 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get_fps_list), + (gst_v4lsrc_get_fps), (gst_v4lsrc_srcconnect), + (gst_v4lsrc_getcaps): + * sys/v4l/v4l_calls.c: (gst_v4l_set_window_properties), + (gst_v4l_get_picture), (gst_v4l_get_audio), (gst_v4l_set_audio): + add querying of fps lists for webcams. Negotiating to a framerate + now works. + +2004-06-08 Thomas Vander Stichele + + * ext/theora/theoraenc.c: (theora_buffer_from_packet), + (theora_push_buffer), (theora_push_packet), + (theora_set_header_on_caps), (theora_enc_chain): + mark buffers and put on streamheader, raw theora streaming + now works too, whee + +2004-06-08 Thomas Vander Stichele + + * gst/tcp/gsttcp.c: (gst_tcp_gdp_read_header), + (gst_tcp_gdp_read_caps): + do a looping read for caps and GDP headers too + +2004-06-08 Thomas Vander Stichele + + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get): + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_get): + return EOS instead of NULL in _get + +2004-06-08 Wim Taymans + + * gst/tcp/gsttcp.c: (gst_tcp_gdp_read_header), + (gst_tcp_gdp_read_caps), (gst_tcp_gdp_write_header), + (gst_tcp_gdp_write_caps): + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get): + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_gdp_read_caps), + (gst_tcpserversrc_gdp_read_header), (gst_tcpserversrc_get): + Memory leak fixes + +2004-06-08 Thomas Vander Stichele + + * ext/vorbis/Makefile.am: + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisparse.c: (gst_vorbis_parse_base_init), + (gst_vorbis_parse_class_init), (gst_vorbis_parse_init), + (vorbis_parse_set_header_on_caps), (vorbis_parse_chain), + (vorbis_parse_change_state): + * ext/vorbis/vorbisparse.h: + adding a vorbisparse element that marks the buffers, streaming + raw vorbis using GDP now works, whee + +2004-06-08 Wim Taymans + + * ext/jpeg/Makefile.am: + * ext/jpeg/README: + * ext/jpeg/gstjpeg.c: (plugin_init): + * ext/jpeg/gstsmokedec.c: (gst_smokedec_get_type), + (gst_smokedec_base_init), (gst_smokedec_class_init), + (gst_smokedec_init), (gst_smokedec_link), (gst_smokedec_chain): + * ext/jpeg/gstsmokedec.h: + * ext/jpeg/gstsmokeenc.c: (gst_smokeenc_get_type), + (gst_smokeenc_base_init), (gst_smokeenc_class_init), + (gst_smokeenc_init), (gst_smokeenc_getcaps), (gst_smokeenc_link), + (gst_smokeenc_resync), (gst_smokeenc_chain), + (gst_smokeenc_set_property), (gst_smokeenc_get_property): + * ext/jpeg/gstsmokeenc.h: + * ext/jpeg/smokecodec.c: (smokecodec_init_destination), + (smokecodec_flush_destination), (smokecodec_term_destination), + (smokecodec_init_source), (smokecodec_fill_input_buffer), + (smokecodec_skip_input_data), (smokecodec_resync_to_restart), + (smokecodec_term_source), (smokecodec_encode_new), + (smokecodec_decode_new), (smokecodec_info_free), + (smokecodec_set_quality), (smokecodec_get_quality), + (smokecodec_set_threshold), (smokecodec_get_threshold), + (smokecodec_set_bitrate), (smokecodec_get_bitrate), + (find_best_size), (abs_diff), (put), (smokecodec_encode), + (smokecodec_parse_header), (smokecodec_decode): + * ext/jpeg/smokecodec.h: + Added a new simple jpeg based codec + +2004-06-08 Wim Taymans + + * gst/multipart/multipartmux.c: (gst_multipart_mux_class_init), + (gst_multipart_mux_loop): + Fix memory leak + +2004-06-08 Thomas Vander Stichele + + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_get): + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_client_remove), + (gst_tcpserversink_handle_client_read), (gst_tcp_buffer_write), + (gst_tcpserversink_handle_client_write), (gst_tcpserversink_chain), + (gst_tcpserversink_init_send), (gst_tcpserversink_close): + * gst/tcp/gsttcpserversink.h: + take streamheader into account + +2004-06-08 Thomas Vander Stichele + + * gst/level/Makefile.am: + * gst/level/gstlevel.c: (gst_level_class_init): + clean up marshal generation + +2004-06-08 Thomas Vander Stichele + + * gst/tcp/Makefile.am: + * gst/tcp/gsttcpclientsink.c: (gst_tcpclientsink_get_type), + (gst_tcpclientsink_class_init), (gst_tcpclientsink_init), + (gst_tcpclientsink_set_property), (gst_tcpclientsink_get_property): + * gst/tcp/gsttcpclientsrc.c: (gst_tcpclientsrc_class_init), + (gst_tcpclientsrc_init), (gst_tcpclientsrc_set_property), + (gst_tcpclientsrc_get_property): + * gst/tcp/gsttcpserversink.c: (gst_tcpserversink_class_init), + (gst_tcpserversink_init), (gst_tcpserversink_handle_server_read), + (gst_tcpserversink_handle_client_read), + (gst_tcpserversink_handle_client_write), + (gst_tcpserversink_set_property), (gst_tcpserversink_get_property): + * gst/tcp/gsttcpserversink.h: + add signals client-added and client-removed + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_class_init), + (gst_tcpserversrc_init), (gst_tcpserversrc_set_property), + (gst_tcpserversrc_get_property): + uniformized, change default protocol to NONE + * gst/tcp/gsttcp-marshal.list: added +2004-06-07 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + handle discont events if they happen before caps nego + +2004-06-07 Wim Taymans + + * gst/multipart/multipartdemux.c: (gst_multipart_demux_base_init), + (gst_multipart_find_pad_by_mime), (gst_multipart_demux_chain), + (gst_multipart_demux_plugin_init): + * gst/multipart/multipartmux.c: (gst_multipart_mux_class_init), + (gst_multipart_mux_init), (gst_multipart_mux_loop), + (gst_multipart_mux_change_state): + Small updates, fix a memleak + +2004-06-07 Stephane Loeuillet + + * configure.ac: OSS portability + * ext/arts/gst_arts.c: idem + * sys/oss/gstosselement.c: idem + * sys/oss/gstossmixer.c: idem + * sys/oss/gstosssink.c: idem + * sys/oss/gstosssrc.c: idem + * sys/oss/oss_probe.c: idem + - check for soundcard.h in different places for some BSD + +2004-06-07 Jan Schmidt + + * AUTHORS: + Add me to the authors file + * configure.ac: + Increase the libdv requirement to >= version 0.100 + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_src_convert), + (gst_dvdec_src_query), (gst_dvdec_handle_sink_event), + (gst_dvdec_push), (gst_dvdec_loop), (gst_dvdec_change_state): + * ext/dv/gstdvdec.h: + Add support for the new_media flag when sending DISCONT events + Make the querying work when video pad is not linked + +2004-06-07 Tim-Philipp Müller + + reviewed by Benjamin Otte + + * gst/mixmatrix/mixmatrix.c: (gst_mixmatrix_init): + create a NULL-initialized array of pads, so we don't think they + exist already. (fixes #143130) + +2004-06-07 Benjamin Otte + + * gst/mixmatrix/mixmatrix.c: (gst_mixmatrix_init), + (mixmatrix_resize), (gst_mixmatrix_set_all_caps), + (gst_mixmatrix_request_new_pad), (gst_mixmatrix_loop): + don't use // coments + +2004-06-07 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_samples_to_timestamp): + cast to GstClockTime to get higher granularity + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + use gst_element_set_time_delay to get the exact time + * ext/mad/gstmad.c: (gst_mad_chain): + use the negotiated rate instead of the current frame's rate which + might be wrong because of bit errors. This avoids emitting totally + bogus timestamps and screwing sync. + (fixes #143454) + +2004-06-07 Tim-Philipp Müller + + reviewed by Benjamin Otte + + * gst/adder/gstadder.c: (gst_adder_loop): + properly error out when no negotiation has happened yet. (fixes + #143032) + +2004-06-06 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event): + forward correctly transformed offset in discont events. Based on + patch by Arwed v. Merkatz. (fixes #142851) + +2004-06-06 David Schleef + + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: that's + G_HAVE_GNUC_VARARGS, not G_HAVE_GNU_VARARGS. Should fix compile + problems on several systems. + +2004-06-06 Benjamin Otte + + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init): + use explicit caps on the srcpad + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + properly error out if caps couldn't be set (fixes #142764) + +2004-06-06 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_probe_hw_params), + (gst_alsa_set_hw_params), (gst_alsa_set_sw_params), + (gst_alsa_start_audio): + - don't call set_periods_integer anymore, it breaks the + configuration randomly + - call snd_pcm_hw_params_set_access directly instead of using masks + - don't fail if the sw_params can't be set, just use the default + params and hope it works. Alsalib has weird issues when you touch + sw_params and does no proper error reporting about what failed. + * ext/alsa/gstalsa.c: (gst_alsa_open_audio), + (gst_alsa_close_audio): + make our alsa debugging go via gst debugging and not conditionally + defined + * ext/alsa/gstalsa.h: + add ALSA_DEBUG_FLUSH macro + * ext/alsa/gstalsaplugin.c: (gst_alsa_error_wrapper), + (plugin_init): + wrap alsa errors to be printed via the gst debugging system and not + spammed to stderr + +2004-06-04 Ronald Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_init), + (gst_qtdemux_handle_src_query), (gst_qtdemux_handle_src_event), + (gst_qtdemux_handle_sink_event), (gst_qtdemux_change_state), + (gst_qtdemux_loop_header), (qtdemux_dump_mvhd), + (qtdemux_parse_trak): + * gst/qtdemux/qtdemux.h: + Bitch. Also known as seeking, querying & co. + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_chain), + (gst_osssink_change_state): + * sys/oss/gstosssink.h: + Resyncing is for weenies, this hack is no longer needed and was + broken anyway (since it - unintendedly - always leaves resync to + TRUE). + +2004-06-05 Andrew Turner + + * gst/tcp/gsttcp.c: portability (Solaris 10/FreeBSD) + * gst/tcp/gsttcpclientsrc.h: idem + - define MSG_NOSIGNAL if not done + - include unistd.h for off_t + (fixes #143749) + +2004-06-05 Benjamin Otte + + * configure.ac: + * ext/kio/Makefile.am: + check for qt's moc preprocessor explicitly and use it + +2004-06-03 Thomas Vander Stichele + + * gst/tcp/gsttcp.c: (gst_tcp_socket_write): + don't get a signal for EPIPE on socket writes + (somebody check if this works on other platforms) + +2004-06-02 Thomas Vander Stichele + + * ext/alsa/gstalsaclock.c: (gst_alsa_clock_get_type): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_loop): + check error condition on available samples correctly + +2004-06-02 Thomas Vander Stichele + + * ext/alsa/gstalsasrc.c: (gst_alsa_src_get_time): + avoid a segfault + * gst/tcp/gsttcp.c: (gst_tcp_socket_write), (gst_tcp_socket_read), + (gst_tcp_gdp_read_header), (gst_tcp_gdp_read_caps): + * gst/tcp/gsttcpserversrc.c: (gst_tcpserversrc_gdp_read_caps), + (gst_tcpserversrc_gdp_read_header): + use ssize_t over size_t since the former is signed and thus the + check for error codes can work + +2004-06-02 Wim Taymans + + reviewed by: Johan + + * gst/multipart/multipartmux.c: (gst_multipart_mux_class_init), + (gst_multipart_mux_loop): + Oops + +2004-06-02 Wim Taymans + + * gst/multipart/multipartmux.c: (gst_multipart_mux_class_init), + (gst_multipart_mux_init), (gst_multipart_mux_loop), + (gst_multipart_mux_get_property), (gst_multipart_mux_set_property), + (gst_multipart_mux_change_state): + Added configurable boundary specifier, added the value as a + caps field as well. + +2004-06-02 Zaheer Abbas Merali + + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpserversrc.c: + - portability fix, to compile on OSX + (fixes #143146) + + * sys/osxaudio/gstosxaudioelement.c: + * sys/osxaudio/gstosxaudiosink.c: + * sys/osxaudio/gstosxaudiosrc.c: + - compilation warnings on OSX + (fixes #143153) + +2004-06-02 Stephane Loeuillet + + * ext/vorbis/vorbisdec.c : sign warning fixes + + * gst-libs/gst/mixer/mixertrack.c : + do no use defines which are glib 2.4 specific + +2004-06-01 Christophe Fergeau + + * ext/flac/gstflactag.c: strip ending framing bit from vorbiscomment + buffer since libflac doesn't expect it (reports a sync error when + it encounters that) + + +2004-06-01 Owen Fraser-Green + + * gst-libs/gst/mixer/mixertrack.h: Changed struct syntax + * gst-libs/gst/mixer/mixertrack.c: + (gst_mixer_track_get_property), (get_mixer_track_init), + (get_mixer_track_get_property): Added property accessors + * gst-libs/gst/mixer/mixeroptions.h: Changed struct syntax + * gst-libs/gst/mixer/mixeroptions.c: + (gst_mixer_options_get_values): Added + * gst-libs/gst/mixer/mixer.h: Changed GstMixerClass syntax + * gst-libs/gst/mixer/mixer.c: Fixed comment + + +2004-06-01 Thomas Vander Stichele + + * ext/alsa/gstalsa.c: (gst_alsa_open_audio): + improve error messages on open + + +2004-06-01 Thomas Vander Stichele + + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay): + check if v4l-conf is in path + +2004-06-01 Thomas Vander Stichele + + * gst-libs/gst/media-info/media-info-priv.c: (gmi_set_mime): + change assert to a more readable error message + +2004-05-31 Stephane Loeuillet + + * gst-libs/gst/tuner/tunerchannel.h: + - add a freq_multiplicator field to make the conversion + between internal frequency unit and Hz + * sys/v4l/gstv4lelement.c: + * sys/v4l2/gstv4l2element.c: + - change default video device to /dev/video0 + * sys/v4l/v4l_calls.c: + * sys/v4l2/v4l2_calls.c: + - we only expose frequency to the user in Hz instead of + bastard v4lX unit (either 62.5kHz or 62.5Hz) + +2004-05-31 Jan Schmidt + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + Initialise b_o_s and e_o_s variables + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + Add some unusual fourcc's from mplayer avi's + * gst/multipart/multipartmux.c: (gst_multipart_mux_plugin_init): + Make the muxer have rank GST_RANK_NONE, so it doesn't mess up + autoplugging. + +2004-05-28 Wim Taymans + + * configure.ac: + * gst/alpha/Makefile.am: + * gst/alpha/gstalpha.c: (gst_alpha_method_get_type), + (gst_alpha_get_type), (gst_alpha_base_init), + (gst_alpha_class_init), (gst_alpha_init), (gst_alpha_set_property), + (gst_alpha_get_property), (gst_alpha_sink_link), (gst_alpha_add), + (gst_alpha_chroma_key), (gst_alpha_chain), + (gst_alpha_change_state), (plugin_init): + A plugin to add an alpha channel to I420 video. Can optionally do + chroma keying. + * gst/multipart/Makefile.am: + * gst/multipart/multipart.c: (plugin_init): + * gst/multipart/multipartdemux.c: (gst_multipart_demux_base_init), + (gst_multipart_demux_class_init), (gst_multipart_demux_init), + (gst_multipart_demux_finalize), (gst_multipart_demux_handle_event), + (gst_multipart_find_pad_by_mime), (gst_multipart_demux_chain), + (gst_multipart_demux_change_state), + (gst_multipart_demux_plugin_init): + * gst/multipart/multipartmux.c: (gst_multipart_mux_get_type), + (gst_multipart_mux_base_init), (gst_multipart_mux_class_init), + (gst_multipart_mux_get_sink_event_masks), (gst_multipart_mux_init), + (gst_multipart_mux_sinkconnect), (gst_multipart_mux_pad_link), + (gst_multipart_mux_pad_unlink), + (gst_multipart_mux_request_new_pad), + (gst_multipart_mux_handle_src_event), + (gst_multipart_mux_next_buffer), (gst_multipart_mux_compare_pads), + (gst_multipart_mux_queue_pads), (gst_multipart_mux_loop), + (gst_multipart_mux_get_property), (gst_multipart_mux_set_property), + (gst_multipart_mux_change_state), (gst_multipart_mux_plugin_init): + A Multipart demuxer/muxer. Not sure if it violates specs. Used to + send multipart jpeg images to a browser. + * gst/videobox/Makefile.am: + * gst/videobox/README: + * gst/videobox/gstvideobox.c: (gst_video_box_fill_get_type), + (gst_video_box_get_type), (gst_video_box_base_init), + (gst_video_box_class_init), (gst_video_box_init), + (gst_video_box_set_property), (gst_video_box_get_property), + (gst_video_box_sink_link), (gst_video_box_i420), + (gst_video_box_ayuv), (gst_video_box_chain), + (gst_video_box_change_state), (plugin_init): + Crops or adds borders around an image. can do alpha channel + borders as well. + * gst/videomixer/Makefile.am: + * gst/videomixer/README: + * gst/videomixer/videomixer.c: (gst_videomixer_pad_get_type), + (gst_videomixer_pad_base_init), (gst_videomixer_pad_class_init), + (gst_videomixer_pad_get_sink_event_masks), + (gst_videomixer_pad_get_property), + (gst_videomixer_pad_set_property), + (gst_videomixer_pad_sinkconnect), (gst_videomixer_pad_link), + (gst_videomixer_pad_unlink), (gst_videomixer_pad_init), + (gst_video_mixer_background_get_type), (gst_videomixer_get_type), + (gst_videomixer_base_init), (gst_videomixer_class_init), + (gst_videomixer_init), (gst_videomixer_request_new_pad), + (gst_videomixer_handle_src_event), + (gst_videomixer_blend_ayuv_i420), (gst_videomixer_fill_checker), + (gst_videomixer_fill_color), (gst_videomixer_fill_queues), + (gst_videomixer_blend_buffers), (gst_videomixer_update_queues), + (gst_videomixer_loop), (gst_videomixer_get_property), + (gst_videomixer_set_property), (gst_videomixer_change_state), + (plugin_init): + Generic video mixer plugin, can handle multiple inputs all with + different framerates and video sizes. Is fully alpha channel + aware. + +2004-05-27 Ronald Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + Select first track as master track. Not sure how else to handle + that... + * ext/ogg/gstoggmux.c: (gst_ogg_mux_next_buffer): + Discard discont events. Should fix #142962. + +2004-05-26 Ronald Bultje + + * ext/alsa/Makefile.am: + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_interface_init), + (gst_alsa_mixer_build_list), (gst_alsa_mixer_get_volume), + (gst_alsa_mixer_set_volume), (gst_alsa_mixer_set_mute), + (gst_alsa_mixer_set_record), (gst_alsa_mixer_set_option), + (gst_alsa_mixer_get_option): + * ext/alsa/gstalsamixer.h: + * ext/alsa/gstalsamixeroptions.c: + (gst_alsa_mixer_options_get_type), + (gst_alsa_mixer_options_class_init), (gst_alsa_mixer_options_init), + (gst_alsa_mixer_options_new): + * ext/alsa/gstalsamixeroptions.h: + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_new): + * ext/alsa/gstalsamixertrack.h: + Add enumerations (as GstMixerOptions). Make correct distinction + between input/output tracks. Add capture/playback private flag. + Use flag to decide on whether to set capture or playback volumes + or switches. Use playback and record switches. + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/mixer/mixer-marshal.list: + * gst-libs/gst/mixer/mixer.c: (gst_mixer_class_init), + (gst_mixer_set_option), (gst_mixer_get_option), + (gst_mixer_mute_toggled), (gst_mixer_record_toggled), + (gst_mixer_volume_changed), (gst_mixer_option_changed): + * gst-libs/gst/mixer/mixer.h: + * gst-libs/gst/mixer/mixeroptions.c: (gst_mixer_options_get_type), + (gst_mixer_options_class_init), (gst_mixer_options_init), + (gst_mixer_options_dispose): + * gst-libs/gst/mixer/mixeroptions.h: + Add GstMixerOptions. + * sys/oss/gstosselement.c: (gst_osselement_class_probe_devices): + Rename Audio Mixer to OSS Mixer (similar to Alsa Mixer). Fix + broken device detection on computers with multiple OSS sound + cards. + +2004-05-26 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_fixate): + fixate nicely even when the peer is not negotiating + +2004-05-25 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_parse_caps): + make sure we don't allow depth > width + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_fixate): + fixate endianness to G_BYTE_ORDER as default + * gst/audioscale/gstaudioscale.c: + we don't handle another endianness as host-endianness + +2004-05-25 David Schleef + + * gst/ffmpegcolorspace/mem.c: malloc() is in stdlib.h, not malloc.h + +2004-05-24 Benjamin Otte + + * ext/vorbis/oggvorbisenc.c: (gst_oggvorbisenc_sinkconnect), + (gst_oggvorbisenc_setup): + properly fail when we can't setup the vorbis encoder due to + unsupported settings + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_sinkconnect), + (gst_vorbisenc_setup): + same + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + fix case where warnings occured when one pad was unlinked while the + other's link function was called + +2004-05-24 Thomas Vander Stichele + + * gst/tcp/Makefile.am: + use GST_ENABLE_NEW + +2004-05-24 Benjamin Otte + + * gst-libs/gst/resample/private.h: + don't use optimizations that are #if 0'ed + +2004-05-24 Wim Taymans + + * gst/avi/gstavidemux.c: (gst_avi_demux_handle_src_query): + Fix potential division by zero error and hopefully get + the position query right to get correct timestamps on avi + audio. + +2004-05-24 Wim Taymans + + * gst/videoscale/videoscale.c: (gst_videoscale_scale_nearest), + (gst_videoscale_scale_nearest_str2), + (gst_videoscale_scale_nearest_str4), + (gst_videoscale_scale_nearest_32bit), + (gst_videoscale_scale_nearest_24bit), + (gst_videoscale_scale_nearest_16bit): + Fix the scaling algorithm and avoid a buffer overflow. + removed the while loop in the scaling function as it + was used for point sampling only. + +2004-05-24 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_get_type), + (gst_id3_tag_class_init), (gst_id3_tag_init), + (gst_id3_tag_set_property), (gst_id3_tag_get_tag_to_render), + (gst_id3_tag_handle_event), (gst_id3_tag_do_caps_nego), + (gst_id3_tag_send_tag_event): + lots of fixes to make id3mux work and id3demux work correctly + +2004-05-24 Stephane Loeuillet + + * ext/Makefile.am: + add rules to build shout2send (was removed by accident + when this module was no more marked experimental/broken) + +2004-05-24 Zaheer Abbas Merali + + * ext/shout2/gstshout2.c: + * ext/shout2/gstshout2.h: + adding a "connection problem" signal to shout2send + (fixes #142954) + +2004-05-21 Thomas Vander Stichele + + * ext/kio/kioreceiver.cpp: + * ext/kio/kioreceiver.h: + fix sign comparison issues + +2004-05-21 Stephane Loeuillet + + * gst/cdxaparse/gstcdxaparse.c: + * gst/cdxaparse/gstcdxaparse.h: + some renaming + add some checks/sanity + prepare for seek addition + + * sys/sunaudio/gstsunaudio.c: + remove exported dupe init function + +2004-05-21 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_get_formats), + (gst_dvdec_src_convert), (gst_dvdec_sink_convert): + Fix format conversion and position querying. + * gst/debug/progressreport.c: (gst_progressreport_report): + Don't output a bogus total value that we didn't query. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + Always set XV_AUTOPAINT_COLORKEY to true. Fixes xvimagesink showing + only a blank window after xine has been used. + +2004-05-21 Thomas Vander Stichele + + * m4/as-arts.m4: + sync with upstream version to fix test on FC2 + readd with -ko to preserve Id header + +2004-05-20 Stephane Loeuillet + + * configure.ac: + test for FIONREAD ioctl in sys/filio.h for Solaris compat. + * gst/tcp/gsttcpclientsrc.c: idem + * gst/tcp/gsttcpserversink.c: idem + * gst/tcp/gsttcpserversrc.c: idem + * m4/gst-fionread.m4: idem + + * sys/sunaudio/gstsunaudio.c: change category to Sink/Audio + + * configure.ac: enable speex plugin for speex 1.1.5+ + * ext/speex/gstspeexenc.c: fix cast warning + + * ext/esd/README: fix typo + +2004-05-20 David Schleef + + * configure.ac: Minor cosmetic change to convince the buildbot to + reautogen. + * sys/sunaudio/gstsunaudio.c: (gst_sunaudiosink_class_init), + (gst_sunaudiosink_init), (gst_sunaudiosink_getcaps), + (gst_sunaudiosink_pad_link), (gst_sunaudiosink_chain), + (gst_sunaudiosink_setparams), (gst_sunaudiosink_open), + (gst_sunaudiosink_close), (gst_sunaudiosink_change_state), + (gst_sunaudiosink_set_property), (gst_sunaudiosink_get_property): + More hacking. Plays audio now. + +2004-05-20 David Schleef + + * configure.ac: + * sys/Makefile.am: + +2004-05-20 David Schleef + + * sys/osxaudio/Makefile.am: New OS X audio plugin by Zaheer Abbas Merali + * sys/osxaudio/gstosxaudio.c: + * sys/osxaudio/gstosxaudioelement.c: + * sys/osxaudio/gstosxaudioelement.h: + * sys/osxaudio/gstosxaudiosink.c: + * sys/osxaudio/gstosxaudiosink.h: + * sys/osxaudio/gstosxaudiosrc.c: + * sys/osxaudio/gstosxaudiosrc.h: + +2004-05-20 Thomas Vander Stichele + + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_set_header_on_caps), + (gst_vorbisenc_chain): + put the codec headers on the caps as streamheader as well as + pushing them out + +2004-05-20 Thomas Vander Stichele + + * ext/vorbis/vorbisenc.c: (vorbis_granule_time_copy), + (gst_vorbisenc_buffer_from_packet), (gst_vorbisenc_push_buffer), + (gst_vorbisenc_push_packet), (gst_vorbisenc_chain): + split up push_packet into two functions + +2004-05-20 Thomas Vander Stichele + + * gst/tcp/.cvsignore: + ignore enums + * gst/tcp/Makefile.am: + * gst/tcp/README: + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpclientsink.c: + * gst/tcp/gsttcpclientsink.h: + * gst/tcp/gsttcpclientsrc.c: + * gst/tcp/gsttcpclientsrc.h: + * gst/tcp/gsttcpplugin.c: + * gst/tcp/gsttcpserversink.c: + * gst/tcp/gsttcpserversink.h: + * gst/tcp/gsttcpserversrc.c: + * gst/tcp/gsttcpserversrc.h: + add new tcp elements + +2004-05-19 Wim Taymans + + * gst/law/mulaw-conversion.c: (mulaw_encode): + Fix overflow bug in ulaw encoding. + +2004-05-19 Benjamin Otte + + * ext/mad/gstmad.c: (gst_mad_handle_event): + don't unref the event twice + +2004-05-19 Benjamin Otte + + * configure.ac: + remove -Wno-sign-compare + +2004-05-19 Benjamin Otte + + * configure.ac: + remove -DG_DISABLE_DEPRECATED. It's not usable without workarounds + if you want to work against glib 2.2 and 2.4 + +2004-05-19 Thomas Vander Stichele + + * gst/tcp/Makefile.am: + * gst/tcp/gsttcp.c: + * gst/tcp/gsttcp.h: + * gst/tcp/gsttcpsink.h: + * gst/tcp/gsttcpsrc.h: + gsttcp -> gsttcpplugin + CVS surgery in preparation for tcp merge + +2004-05-19 Benjamin Otte + + * gst/debug/tests.c: (md5_get_value): + fix segfault on gst-inspect + +2004-05-19 Benjamin Otte + + * gst/debug/testplugin.c: + * gst/debug/tests.c: + * gst/debug/tests.h: + add new extensible and configurable testing element. Current tests + include buffer count, stream length, timestamp/duration matching and + md5. + * gst/debug/Makefile.am: + * gst/debug/gstdebug.c: (plugin_init): + add infrastructure for new element + +2004-05-19 Johan Dahlin + + * ext/dv/gstdvdec.c (gst_dvdec_quality_get_type): Add proper + ending of the array. Fixes gst-inspect segfault on ppc. + +2004-05-19 Stephane Loeuillet + + * ext/dirac/gstdiracdec.cc : change category to Codec/Decoder/Video + + * m4/a52.m4 : don't fix a test that should fail with current a52dec lib + +2004-05-18 David Schleef + + * gst/ffmpegcolorspace/imgconvert.c: (img_convert): Fixes for + warnings (bugs, actually) noticed by gcc but not forte. + +2004-05-18 David Schleef + + * sys/sunaudio/Makefile.am: + * sys/sunaudio/gstsunaudio.c: New sunaudiosink + +2004-05-18 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_change_state), + (gst_qtdemux_loop_header): Patch from dcm@acm.org (David Moore) + to allow qtdemux to use non-seekable streams. (bug #142272) + +2004-05-18 David Schleef + + * gst-libs/gst/resample/resample.c: (gst_resample_sinc_ft_s16), + (gst_resample_sinc_ft_float): Remove use of static temporary + buffer. This code was obviously not supposed to last long, but + it's stuck in our ABI, so it required a little hack to make it + ABI-compatible. Fixes #142585. + * gst-libs/gst/resample/resample.h: same. + +2004-05-18 David Schleef + + * configure.ac: Add sunaudio + * examples/Makefile.am: make gstplay depend on gconf + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: Remove c99-isms + * gst/ffmpegcolorspace/imgconvert.c: (build_rgb_palette), + (convert_table_lookup), (img_convert): remove c99-isms + * gst/ffmpegcolorspace/imgconvert_template.h: make a constant + unsigned, to fix a warning on Solaris + * gst/mpeg1sys/systems.c: bcopy->memcpy + * gst/rtjpeg/RTjpeg.c: (RTjpeg_yuvrgb8): bcopy->memcpy + * sys/Makefile.am: Add sunaudio + +2004-05-18 Wim Taymans + + * ext/ogg/gstoggmux.c: (gst_ogg_mux_get_type), (gst_ogg_mux_init), + (gst_ogg_mux_sinkconnect), (gst_ogg_mux_request_new_pad), + (gst_ogg_mux_next_buffer), (gst_ogg_mux_push_page), + (gst_ogg_mux_compare_pads), (gst_ogg_mux_queue_pads), + (gst_ogg_mux_loop): + Fix an ugly memleak where the muxer didn't flush enough ogg + pages. This also resulted in badly muxed ogg files. + +2004-05-18 Stephane Loeuillet + + * gst/asfdemux/asfheaders.c : + * gst/asfdemux/asfheaders.h : + * gst/asfdemux/gstasfdemux.c : + - fix ASF_OBJ_PADDING guid + - add 3 new object guids (language list, metadata, + extended stream properties) + - add a function to parse extended header objects + +2004-05-18 Benjamin Otte + + * sys/oss/gstosselement.c: (gst_osselement_sync_parms): + remove leftover debugging g_print + +2004-05-17 Ronald Bultje + + * ext/mad/gstmad.c: (gst_mad_handle_event): + Fix for when the first format in a discont event is not a + byte-based one. Should fix #137710. + +2004-05-18 Stephane Loeuillet + + * m4/a52.m4 : fix compilation with -Wall -Werror + * m4/libfame.m4 : idem + * m4/libmikmod.m4 : idem + +2004-05-17 Benjamin Otte + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_comment): + signal the new tags before giving up the reference + +2004-05-17 Benjamin Otte + + * ext/shout2/gstshout2.c: + use application/ogg instead of application/x-ogg (patch by Patrick + Guimond, fixes #142432) + * sys/oss/gstosselement.c: (gst_osselement_reset), + (gst_osselement_sync_parms): + don't set fragment size unless specified (fixes #142493) + +2004-05-17 Stephane Loeuillet + + * configure.ac : fix compilation of v4l2src with "-Wall -Werror" + fixes #142664 + +2004-05-17 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_chain): + compute offsets correctly for internal buffers so timestamps are set + correctly when we can't seek. Also handle cases where there are no + offsets. (based on a patch by David Moore, fixes #142507) + +2004-05-17 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + use correct variable when determining amount of data to skip so we + don't skip into the void and segfault + +2004-05-16 Benjamin Otte + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_audio_caps): + Hi, I'm a memleak + +2004-05-16 Stephane Loeuillet + + * gst/asfdemux/gstasfdemux.c: + - fix a mem leak and always propagate tags + - add WMV3 to known video codecs (but no decoder yet) + - replace "surplus data" at end of audio header for what + it is : codec specific data + - fix a typo + +2004-05-16 Arwed v. Merkatz + + reviewed by: Ronald Bultje + + * gst-libs/gst/audio/audioclock.c: + Fix wrong return type (#142205). + +2004-05-16 Ronald Bultje + + * ext/mad/gstmad.c: (gst_mad_class_init), (gst_mad_init): + Ignore CRCs by default (fixes #142566). + +2004-05-16 Ronald Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_open), + (gst_alsa_mixer_close), (gst_alsa_mixer_supported), + (gst_alsa_mixer_build_list), (gst_alsa_mixer_free_list), + (gst_alsa_mixer_change_state), (gst_alsa_mixer_list_tracks), + (gst_alsa_mixer_get_volume), (gst_alsa_mixer_set_volume), + (gst_alsa_mixer_set_mute), (gst_alsa_mixer_set_record): + Fix for cases where we fail to attach to a mixer. + +2004-05-16 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): + Don't touch events after not owning them anymore. + * gst/wavparse/gstwavparse.c: (gst_wavparse_base_init), + (gst_wavparse_fmt), (gst_wavparse_other), + (gst_wavparse_handle_seek), (gst_wavparse_loop), + (gst_wavparse_pad_convert), (gst_wavparse_pad_query), + (gst_wavparse_srcpad_event): + * gst/wavparse/gstwavparse.h: + Add seeking, fix querying. + +2004-05-16 Stephane Loeuillet + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_comment): + - process comments even if they don't end with \0\0 + g_convert would ignore them if present and works well without them + +2004-05-16 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_caps), (gst_alsa_get_caps): + simplify caps + +2004-05-16 Benjamin Otte + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_comment): + don't write to memory we might not write to - g_convert does that + for us anyway (fixes #142613) + (gst_asf_demux_audio_caps): + comment out gst_util_dump_mem + +2004-05-16 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + compute correct expected timestamps after seek (broken since + last commit) + * ext/gdk_pixbuf/pixbufscale.c: (pixbufscale_init): + rename element and debugging category to gdkpixbufscale + +2004-05-16 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + add error checking to snd_pcm_delay and remove duplicate call to + snd_pcm_delay that caused issues (see inline code comments) + * ext/alsa/gstalsasink.c: (gst_alsa_sink_get_time): + make more readable and fix return value when snd_pcm_delay fails + (fixes #142586) + +2004-05-15 Jan Schmidt + * ext/gdk_pixbuf/pixbufscale.c: (gst_pixbufscale_method_get_type), + (gst_pixbufscale_get_type), (gst_pixbufscale_base_init), + (gst_pixbufscale_class_init), (gst_pixbufscale_getcaps), + (gst_pixbufscale_link), (gst_pixbufscale_init), + (gst_pixbufscale_handle_src_event), (pixbufscale_scale), + (gst_pixbufscale_chain), (gst_pixbufscale_set_property), + (gst_pixbufscale_get_property), (pixbufscale_init): + * ext/gdk_pixbuf/pixbufscale.h: + Add these files I forgot earlier + +2004-05-15 Jan Schmidt + * ext/gdk_pixbuf/Makefile.am: + * ext/gdk_pixbuf/gstgdkpixbuf.c: (plugin_init): + * ext/gdk_pixbuf/gstgdkpixbuf.h: + Add new pixbufscale element to scale RGB video + using gdk_pixbuf, because gdk_pixbuf does BILINEAR + and HYPER interpolation correctly. + * ext/theora/theoraenc.c: (theora_enc_chain), + Discard buffer and return if explicit caps could not be set + (theora_enc_get_property): + Make _get return kbps for the bitrate consistent with + the _set function. + + +2004-05-14 Benjamin Otte + + * ext/libvisual/visual.c: (gst_visual_chain): + add missing visual_audio_analyze + +2004-05-14 David Schleef + + * ext/esd/esdsink.c: (gst_esdsink_chain): Fix crash when ESD + is killed while we're playing. + * gst/qtdemux/qtdemux.c: (qtdemux_parse): call + gst_element_no_more_pads(). + +2004-05-14 Stephane Loeuillet + + * gst-libs/gst/riff/riff-read.c : + - fix INFO tag extraction in RIFF/AVI files + because gst_event_unref (event) also freed taglist + - avoid a mem leak + +2004-05-13 Stephane Loeuillet + + * ext/mad/gstid3tag.c : move from "Codec/(Dem/M)uxer" to "Codec/(Dem/M)uxer/Audio" + * gst/wavenc/gstwavenc.c : move from "Codec/Encoder/Audio" to "Codec/Muxer/Audio" + + * gst/auparse/gstauparse.c : + - add code (commented for now) to support audio/x-adpcm on src pad + (we have no decoder for those layout yet) + + * gst/cdxaparse/gstcdxaparse.c : + * gst/cdxaparse/gstcdxaparse.h : + - partial rewrite using RiffRead (ripped iain's wavparse code) + + * gst/rtp/gstrtpL16enc.c : typo + * gst/rtp/gstrtpgsmenc.c : typo + +2004-05-13 Benjamin Otte + + * configure.ac: + check for exact version of libvisual, it's not supposed to be + API/ABI stable yet + +2004-05-13 Benjamin Otte + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_push): + signal no-more-pads + +2004-05-13 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_src_convert) + Report which format was used for GST_FORMAT_DEFAULT + * gst/debug/Makefile.am: + * gst/debug/gstdebug.c: (plugin_init): + * gst/debug/progressreport.c: (gst_progressreport_base_init), + (gst_progressreport_class_init), (gst_progressreport_init), + (gst_progressreport_report), (gst_progressreport_set_property), + (gst_progressreport_get_property), (gst_progressreport_chain), + (gst_progressreport_plugin_init): + Add progressreport element for testing. + +2004-05-13 Thomas Vander Stichele + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get), (gst_v4lsrc_change_state): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4lmjpegsink_calls.c: (gst_v4lmjpegsink_playback_init): + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_capture_init): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_capture_init), + (gst_v4lsrc_grab_frame): + add more debugging + send a discont at start + +2004-05-12 Colin Walters + + * gst/asfdemux/gstasfdemux.c (gst_asf_demux_process_segment): Avoid + inflooping if we can't find a chunk. Or in other words, don't blow + chunks if we don't have a chunk to blow. + +2004-05-13 Jan Schmidt + * ext/audiofile/gstafsrc.c: (gst_afsrc_get): + Remove old debug output + * ext/dv/gstdvdec.c: (gst_dvdec_quality_get_type), + (gst_dvdec_class_init), (gst_dvdec_loop), (gst_dvdec_change_state), + (gst_dvdec_set_property), (gst_dvdec_get_property): + Change the quality setting to an enum, so it works from gst-launch + Don't renegotiate a non-linked pad. Allows audio only decoding. + * gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_getcaps), + (gst_deinterlace_link), (gst_deinterlace_init): + * gst/videodrop/gstvideodrop.c: (gst_videodrop_getcaps), + (gst_videodrop_link): + Some caps negotiation fixes + +2004-05-12 Stephane Loeuillet + + * ext/tarkin/gsttarkin.c : + - Change RANK from NONE to PRIMARY + * ext/gdk_pixbuf/gstgdkpixbuf.c : + - Change RANK from NONE to MARGINAL + * ext/divx/gstdivxenc.c : + - Change RANK from PRIMARY to NONE (encoder/spider issue) + +2004-05-12 Thomas Vander Stichele + + * ext/vorbis/vorbisenc.c: (vorbis_granule_time_copy), + (gst_vorbisenc_push_packet): + copy a function that was added between 1.0 and 1.0.1 until we + depend on worthwhile features of post-1.0 + +2004-05-12 Benjamin Otte + + * configure.ac: + enable shout2 by default + * ext/shout2/gstshout2.c: (gst_shout2send_protocol_get_type), + (gst_shout2send_base_init), (gst_shout2send_init), + (gst_shout2send_connect), (gst_shout2send_change_state): + * ext/shout2/gstshout2.h: + make this work again. Based on a patch by Zaheer Abbas Merali (fixes + #142262) + * ext/theora/theora.c: (plugin_init): + don't set rank on encoders + +2004-05-11 Jeremy Simon + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_audio_caps): + Use codec_data property instead of flag1 and flag2 for wma + +2004-05-11 Stephane Loeuillet + + * gst/cdxaparse/gstcdxaparse.c : + - Add mpegversion to CAPS to make it link + - Rank is as GST_RANK_SECONDARY instead of NONE + * gst/auparse/gstauparse.c : + - Document all audio encoding we can encounter from Solaris 9 + headers and libsndfile information. + - Increase max. rate from 48000 to 192000 (to match other elements) + - Don't try to play junk data between header and samples + +2004-05-11 Benjamin Otte + + * ext/libvisual/visual.c: (gst_visual_getcaps): + use the right caps depending on endianness (I hope) + * ext/ogg/gstoggmux.c: (gst_ogg_mux_plugin_init): + use GST_RANK_NONE for all non-decoding elements or spider gets + mighty confused + +2004-05-11 Ronald Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_comment): + Fix some odd cases and fix BE metadata parsing of unicode16 text. + +2004-05-11 Benjamin Otte + + * gst/switch/gstswitch.c: (gst_switch_release_pad), + (gst_switch_request_new_pad), (gst_switch_poll_sinkpads), + (gst_switch_loop), (gst_switch_get_type): + whoever that was: DO NOT IMPORT PRIVATE SYMBOLS THAT ARE NOT IN + HEADERS. Had to be said. + +2004-05-10 David Schleef + + * configure.ac: Add prototype Dirac support. + * ext/Makefile.am: + * ext/dirac/Makefile.am: + * ext/dirac/gstdirac.cc: + * ext/dirac/gstdiracdec.cc: + +2004-05-10 Ronald Bultje + + * gst/auparse/gstauparse.c: (gst_auparse_class_init), + (gst_auparse_init), (gst_auparse_chain), + (gst_auparse_change_state): + Hack around spider. Remove me some day please. + +2004-05-10 Ronald Bultje + + * gst/auparse/gstauparse.c: (gst_auparse_chain): + Fix for some uninitialized variables in previous patch, also + makes it work. Fixes #142286 while we're at it. + +2004-05-11 Stephane Loeuillet + + * gst/auparse/gstauparse.c: + fixes a-law, adds mu-law, linear pcm (8,16,24,32), ieee (32, 64) + only unsupported formats are ADPCM/CCITT G.72x + reviewed by Ronald + * gst-libs/gst/audio/audio.h: adds 24bit depth to PCM (x-raw-int) + +2004-05-10 Wim Taymans + + * ext/vorbis/Makefile.am: + * ext/vorbis/README: + * ext/vorbis/oggvorbisenc.c: (gst_oggvorbisenc_get_formats), + (oggvorbisenc_get_type), (vorbis_caps_factory), (raw_caps_factory), + (gst_oggvorbisenc_base_init), (gst_oggvorbisenc_class_init), + (gst_oggvorbisenc_sinkconnect), (gst_oggvorbisenc_convert_src), + (gst_oggvorbisenc_convert_sink), + (gst_oggvorbisenc_get_query_types), (gst_oggvorbisenc_src_query), + (gst_oggvorbisenc_init), (gst_oggvorbisenc_get_tag_value), + (gst_oggvorbisenc_metadata_set1), (gst_oggvorbisenc_set_metadata), + (get_constraints_string), (update_start_message), + (gst_oggvorbisenc_setup), (gst_oggvorbisenc_write_page), + (gst_oggvorbisenc_chain), (gst_oggvorbisenc_get_property), + (gst_oggvorbisenc_set_property), (gst_oggvorbisenc_change_state): + * ext/vorbis/oggvorbisenc.h: + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisenc.c: (vorbis_caps_factory), + (raw_caps_factory), (gst_vorbisenc_class_init), + (gst_vorbisenc_init), (gst_vorbisenc_setup), + (gst_vorbisenc_push_packet), (gst_vorbisenc_chain), + (gst_vorbisenc_get_property), (gst_vorbisenc_set_property): + * ext/vorbis/vorbisenc.h: + Added a raw vorbis encoder to be used with the oggmuxer. + We still need the old encoder for some gnome applications, + read the README to find out how that works. + The raw encoder is called "rawvorbisenc" until 0.9. + +2004-05-10 Wim Taymans + + * ext/ogg/gstogg.c: (plugin_init): + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_plugin_init), + (gst_ogg_print): + * ext/ogg/gstoggmux.c: (gst_ogg_mux_get_type), + (gst_ogg_mux_base_init), (gst_ogg_mux_class_init), + (gst_ogg_mux_get_sink_event_masks), (gst_ogg_mux_init), + (gst_ogg_mux_sinkconnect), (gst_ogg_mux_pad_link), + (gst_ogg_mux_pad_unlink), (gst_ogg_mux_request_new_pad), + (gst_ogg_mux_handle_src_event), (gst_ogg_mux_next_buffer), + (gst_ogg_mux_push_page), (gst_ogg_mux_compare_pads), + (gst_ogg_mux_queue_pads), (gst_ogg_mux_loop), + (gst_ogg_mux_get_property), (gst_ogg_mux_set_property), + (gst_ogg_mux_change_state), (gst_ogg_mux_plugin_init): + Added an ogg muxer. + Small typo fixes in the demuxer. + +2004-05-10 Wim Taymans + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_sink_link), (theora_push_packet), (theora_enc_chain), + (theora_enc_change_state), (theora_enc_set_property), + (theora_enc_get_property): + Mark the last packet with an EOS flag which is not really needed + in gstreamer. + Do some better video framerate initialisation. + Update the buffer timestamp. + +2004-05-10 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_change_state): + Return the result of the parent state change call + +2004-05-10 Stephane Loeuillet + + * gst/law/alaw.c : alawdec should be registered with type ALAWDEC, not ALAWENC + * gst/law/alaw-decode.c : put audio/x-alaw on pads, instead of audio/x-mulaw + * gst/law/alaw-encode.c : (idem) + * ext/a52dec/gsta52dec.c : mark audio/a52, audio/ac3 as deprecated in a comment + * gst/ac3parse/gstac3parse.c : audio/ac3 => audio/x-ac3 + * gst/realmedia/rmdemux.c : audio/a52 => audio/x-ac3 + +2004-05-09 Benjamin Otte + + * ext/alsa/gstalsasrc.c: (gst_alsa_src_loop): + don't use a fixed buffer size when writing variable length data to + it. Fixes memory corruption and makes alsasrc work + +2004-05-09 Ronald Bultje + + * ext/gnomevfs/gstgnomevfssink.c: + (_gst_boolean_allow_overwrite_accumulator), + (gst_gnomevfssink_class_init), (gst_gnomevfssink_open_file): + Run glib's default signal handler (??) in RUN_CLEANUP rather than + RUN_LAST, and don't use that to set the accumulator value because + then it's always FALSE. + +2004-05-09 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_audio_caps), + (gst_riff_create_audio_template_caps): + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head): + Fix for unaligned RIFF files (i.e. where all the chunks together + in a LIST chunk are not of the same size as the size given in + the LIST chunk header). Fixes several odd WAVE files. Also fix + ADPCM (block_align property) in audio, so that wavparse based + on this works now as it used to stand-alone. + +2004-05-09 Edward Hervey + + reviewed by Benjamin Otte + + * ext/a52dec/gsta52dec.c: + * ext/divx/gstdivxdec.c: + * ext/divx/gstdivxenc.c: + * ext/dts/gstdtsdec.c: (gst_dtsdec_base_init): + * ext/faac/gstfaac.c: (gst_faac_base_init): + * ext/faad/gstfaad.c: (gst_faad_base_init): + * ext/ivorbis/vorbisfile.c: + * ext/lame/gstlame.c: + * ext/libfame/gstlibfame.c: + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/musicbrainz/gsttrm.c: (gst_musicbrainz_base_init): + * ext/sidplay/gstsiddec.cc: + * ext/speex/gstspeexdec.c: + * ext/speex/gstspeexenc.c: + * ext/xvid/gstxviddec.c: + * ext/xvid/gstxvidenc.c: + correct klasses. Mostly s,Codec/(Audio|Video),\1/Codec, + (fixes #142193) + +2004-05-08 Ronald Bultje + + * ext/alsa/gstalsa.c: (device_list), + (gst_alsa_class_probe_devices): + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_open): + Fix alsa oddness in mixer after the combination of using mixer + in source/sink elements and using hw:x,y instead of just hw:x. + +2004-05-09 Benjamin Otte + + * gst/wavparse/gstwavparse.c: (gst_wavparse_destroy_sourcepad), + (gst_wavparse_create_sourcepad): + make PAUSED=>READY=>PAUSED=READY work by not destroying NULL + sourcepads + +2004-05-09 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + allow discont events before caps nego + +2004-05-08 Benjamin Otte + + * ext/vorbis/vorbisdec.c: (vorbis_dec_event): + don't leak events + +2004-05-08 Benjamin Otte + + * gst/level/gstlevel.c: (gst_level_link), (gst_level_chain), + (gst_level_change_state), (gst_level_init): + * gst/level/gstlevel.h: + figure out if we're initialized directly instead of keeping a + variable that's wrong in 90% of cases + don't initialize pads and then leak them and use a new unitialized + pad. (fixes #142084) + these were bugs so n00bish I didn't find them for an hour :/ + +2004-05-08 Iain + + * gst/wavparse/gstwavparse.[ch]: Rewrote to use RiffRead instead. + * gst-libs/gst/riff/riff-read.c (gst_riff_read_peek_head): Unstatic it + (gst_riff_read_element_data): Ditto, and added a got_bytes argument to + return the length that was read. + (gst_riff_read_strf_auds): Allow fmt tags as well. + +2004-05-07 David Schleef + + * ext/faad/gstfaad.c: (gst_faad_sinkconnect): HACK to correct + signed char assumption in faad.h. + +2004-05-07 Ronald Bultje + + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_v4l2fourcc_to_caps): + Missing break, detected by Daniel Gazard . + +2004-05-07 Colin Walters + + * gst/volume/gstvolume.c (gst_volume_dispose): Unref dpman. + * ext/flac/gstflacdec.c (gst_flacdec_dispose): Add dispose + function. + * gst/audioscale/gstaudioscale.c (gst_audioscale_dispose): + Add dispose function. + +2004-05-08 Jan Schmidt + * ext/dv/gstdvdec.c: (gst_dvdec_video_link): + Fix caps nego and pad templates. RGB mode caps should + work now. + * ext/dvdnav/gst-dvd: + Move mpeg2dec inside the thread because otherwise the + queue rejects cap changes mid-stream + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_get_type), + (gst_mpeg2dec_flush_decoder): + For mpeg2dec > 0.4.0, call the flush function instead of + manually extracting all in-flight frames. + * ext/raw1394/gstdv1394src.c: (gst_dv1394src_factory), + (gst_dv1394src_init), (gst_dv1394src_iso_receive): + Change mime type video/dv go video/x-dv to match the + rest of gst-plugins + +2004-05-07 Ronald Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_build_list): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_get_type), + (gst_alsa_sink_class_init): + * ext/alsa/gstalsasink.h: + * ext/alsa/gstalsasrc.c: (gst_alsa_src_get_type), + (gst_alsa_src_class_init): + * ext/alsa/gstalsasrc.h: + Make alsasink/src a subclass of alsamixer so that mixer stuff + shows up in gst-rec. Needs some finetuning. + +2004-05-05 Benjamin Otte + + * ext/lame/gstlame.c: (gst_lame_chain): + simplify + * ext/mad/gstmad.c: (gst_mad_handle_event): + fix event leak + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find): + be able to detect mp3 files < 4096 bytes + +2004-05-06 Wim Taymans + + * ext/theora/theoraenc.c: (gst_theora_enc_class_init), + (theora_enc_sink_link), (theora_push_packet), (theora_enc_chain), + (theora_enc_set_property), (theora_enc_get_property): + Also encode the first frame, cleanup some code. + +2004-05-06 Wim Taymans + + * ext/mpeg2enc/gstmpeg2enc.cc: + Forward events first before deciding that negotiation was + not performed. + +2004-05-06 Wim Taymans + + * gst/wavenc/gstwavenc.c: (gst_wavenc_chain): + First process the events before deciding that negotiation + was not performed. + +2004-05-06 Wim Taymans + + * ext/theora/Makefile.am: + * ext/theora/theora.c: (plugin_init): + * ext/theora/theoradec.c: (theora_dec_change_state): + * ext/theora/theoraenc.c: (gst_theora_enc_base_init), + (gst_theora_enc_class_init), (gst_theora_enc_init), + (theora_enc_sink_link), (theora_enc_event), (theora_push_packet), + (theora_enc_chain), (theora_enc_change_state), + (theora_enc_set_property), (theora_enc_get_property): + Added a theora encoder, grouped the encoder and decoder into the + same plugin. + +2004-05-05 Thomas Vander Stichele + + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_get_type), + (gst_jpegenc_chain): + fix DURATION on outgoing buffers + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_sink_event): + debug using time formats + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_sink_link): + windows with width/height 0 generate X errors, so don't allow them + +2004-05-05 Wim Taymans + + * ext/mpeg2dec/gstmpeg2dec.c: (src_templ), + (gst_mpeg2dec_base_init), (gst_mpeg2dec_init), + (gst_mpeg2dec_negotiate_format): + * ext/mpeg2dec/gstmpeg2dec.h: + removed the static pad template so that we can add the + more accurate framerate value to the caps. + + +2004-05-04 Benjamin Otte + + * configure.ac: + check for kdemacros.h, too (should fix #141821) + * ext/vorbis/vorbisdec.c: (vorbis_dec_event), (vorbis_dec_chain): + don't crash if no header was sent, but nicely error out (fixes part + of #141554) + +2004-05-04 Wim Taymans + + * ext/mpeg2enc/gstmpeg2enc.cc: (gst_mpeg2enc_dispose): call the + parent dispose function to avoid segfault on destroy. + +2004-05-04 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (gst_ximagesink_sink_link), + (plugin_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_sink_link): + clean up debugging caps + also recreate xvimage when format has changed + +2004-05-04 Benjamin Otte + + * ext/libvisual/Makefile.am: + * ext/libvisual/visual.c: (gst_visual_class_init), + (gst_visual_init), (gst_visual_dispose), (gst_visual_getcaps), + (gst_visual_srclink), (gst_visual_chain), + (gst_visual_change_state), (plugin_init): + use a GstAdapter to correctly adapt buffer sizes - allows using a + framerate + +2004-05-03 Thomas Vander Stichele + + * sys/v4l/gstv4lelement.h: + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get_fps), (gst_v4lsrc_getcaps), + (gst_v4lsrc_buffer_free): + * sys/v4l/v4l_calls.c: (gst_v4l_get_capabilities): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_queue_frame), + (gst_v4lsrc_sync_frame), (gst_v4lsrc_grab_frame), + (gst_v4lsrc_requeue_frame): + move some debugging categories around + query for fps index and set accordingly if found + +2004-05-03 Stephane Loeuillet + + * ext/lame/gstlame.c: + correct defaults that lame_init puts out of range + +2004-05-03 Thomas Vander Stichele + + * ext/divx/gstdivxenc.c: (gst_divxenc_get_type), + (gst_divxenc_class_init): + fix range since -1 is the default + * gst/mpeg1sys/gstmpeg1systemencode.c: + (gst_mpeg1_system_encode_get_type), (gst_system_encode_multiplex): + * gst/rtjpeg/gstrtjpegdec.c: (gst_rtjpegdec_get_type), + (gst_rtjpegdec_chain): + * gst/rtjpeg/gstrtjpegenc.c: (gst_rtjpegenc_get_type), + (gst_rtjpegenc_chain): + * sys/qcam/gstqcamsrc.c: (gst_autoexp_mode_get_type), + (gst_qcamsrc_get_type), (gst_qcamsrc_change_state): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_get_type): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_get_type): + * sys/v4l/gstv4lsrc.c: + * sys/v4l/v4l_calls.c: (gst_v4l_open): + * sys/v4l/v4lmjpegsink_calls.c: (gst_v4lmjpegsink_playback_init): + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_capture_init): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_capture_init): + * sys/vcd/vcdsrc.c: (vcdsrc_get_type), (vcdsrc_get): + remove gst_info calls + +2004-05-03 Thomas Vander Stichele + + * Makefile.am: + * po/af.po: + * po/az.po: + * po/en_GB.po: + * po/nl.po: + * po/sr.po: + * po/sv.po: + Updated translations + +2004-05-03 Thomas Vander Stichele + + * gst/audioconvert/gstaudioconvert.c: (_fixate_caps_to_int): + refactor/comment code + +2004-05-02 Ronald Bultje + + * gst/asfdemux/Makefile.am: + * gst/asfdemux/asfheaders.c: + * gst/asfdemux/asfheaders.h: + * gst/asfdemux/gstasf.c: (plugin_init): + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_get_type), + (gst_asf_demux_base_init), (gst_asf_demux_process_comment), + (gst_asf_demux_setup_pad): + * gst/asfdemux/gstasfdemux.h: + * gst/asfdemux/gstasfmux.c: + * gst/asfdemux/gstasfmux.h: + Add tagging support to demuxer, split out registration in its own + file instead of in demux (hacky), and prevent having some tables + in our memory multiple times (in asfheaders.h). + +2004-05-01 Ronald Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_metadata): + * gst/matroska/matroska-ids.h: + Basic tag reading support. + +2004-04-30 Ronald Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_audio_caps): + Really detect ac-3 audio. + * gst/typefind/gsttypefindfunctions.c: (matroska_type_find): + really detect matroska files (off-by-1). + +2004-04-30 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (gst_qtdemux_add_stream), (qtdemux_parse), (qtdemux_type_get), + (qtdemux_dump_stsz), (qtdemux_dump_stco), (qtdemux_dump_co64), + (qtdemux_dump_unknown), (qtdemux_parse_tree), (qtdemux_parse_udta), + (qtdemux_tag_add), (get_size), (gst_qtdemux_handle_esds): More qtdemux + hackage -- parse a lot more atoms, extract a few tags. One might even + mistake this for tag support. Maybe it is. + * gst/qtdemux/qtdemux.h: + +2004-04-30 Colin Walters + + * ext/alsa/gstalsasink.c (gst_alsa_sink_mmap): Plug a memleak. + +2004-04-30 Thomas Vander Stichele + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_getcaps): + remove broken nego fix + +2004-04-30 Benjamin Otte + + * configure.ac: + * ext/Makefile.am: + * ext/libvisual/Makefile.am: + * ext/libvisual/visual.c: + add initial support for libvisual (http://libvisual.sourceforge.net) + libvisual is still quite alpha, so expect crashes in there :) + +2004-04-29 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_add_stream), (qtdemux_parse), + (qtdemux_parse_trak), (get_size), (gst_qtdemux_handle_esds): Hacked + up qtdemux to make it spit out codec_data. Do _not_ look at this + code; you will no longer respect me. + +2004-04-29 Stephane Loeuillet + + * ext/alsa/gstalsa.c : (gst_alsa_class_probe_devices) + * ext/alsa/gstalsa.h : + change alsa pcm device discovery to find more than 1 device + per card. code review by Ronald. + +2004-04-29 David Schleef + + * sys/oss/gstosselement.c: (gst_osselement_rate_probe_check): + Add a check for a driver bug on FreeBSD. (bug #140565) + +2004-04-29 Thomas Vander Stichele + + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_get_type): + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_get_type), + (gst_jpegenc_getcaps): + move format setting to inner loop + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_getcaps): + use GST_PAD_CAPS if available so that we use already negotiated + caps + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (qtdemux_parse_moov), (qtdemux_parse): + extra debugging + * sys/qcam/qcam-Linux.c: (qc_lock_wait), (qc_unlock): + * sys/qcam/qcam-os.c: (qc_lock_wait), (qc_unlock): + move hardcoded path to DEFINE + +2004-04-28 David Schleef + + * gst/speed/gstspeed.c: (speed_parse_caps): Fix caps parsing. + (bug #140064) + +2004-04-28 Ronald Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_class_probe_devices): + Don't probe for playback device if we're a source element. Fixes + #139658. + +2004-04-29 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event), + (gst_id3_tag_chain): + rewrite buffer offset + +2004-04-28 Ronald Bultje + + * configure.ac: + * ext/Makefile.am: + * ext/dts/Makefile.am: + * ext/dts/gstdtsdec.c: (gst_dtsdec_get_type), + (gst_dtsdec_base_init), (gst_dtsdec_class_init), (gst_dtsdec_init), + (gst_dtsdec_channels), (gst_dtsdec_renegotiate), + (gst_dtsdec_handle_event), (gst_dtsdec_update_streaminfo), + (gst_dtsdec_loop), (gst_dtsdec_change_state), + (gst_dtsdec_set_property), (gst_dtsdec_get_property), + (plugin_init): + * ext/dts/gstdtsdec.h: + New DTS decoder. + * ext/faad/gstfaad.c: (gst_faad_sinkconnect), + (gst_faad_srcconnect): + Add ESDS atom handling (.m4a). + +2004-04-27 Ronald Bultje + + * ext/divx/gstdivxdec.c: (plugin_init): + Remove comment that makes no sense. + * ext/mad/gstid3tag.c: (gst_id3_tag_set_property): + Fix for obvious typo that resulted in warnings during gst-register. + * ext/xvid/gstxviddec.c: (gst_xviddec_src_link), + (gst_xviddec_sink_link): + Fix caps negotiation a bit better. + * gst/qtdemux/qtdemux.c: (qtdemux_parse_trak): + We call this 'codec_data', not 'esds'. + +2004-04-27 Benjamin Otte + + * gst/monoscope/gstmonoscope.c: + make sure we only provide 256x128 + * gst/monoscope/monoscope.c: (monoscope_init): + assert size of 256x128 + +2004-04-27 Thomas Vander Stichele + + * Makefile.am: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_init), (gst_v4lsrc_fixate), + (gst_v4lsrc_getcaps), (gst_v4lsrc_buffer_free): + fixate to max width and height of device + +2004-04-27 Thomas Vander Stichele + + * Makefile.am: + * sys/v4l/gstv4l.c: + * sys/v4l/gstv4lsrc.c: + * sys/v4l/v4l_calls.c: + * sys/v4l/v4lsrc_calls.c: + fix for qc-usb driver which fakes having more than one buffer + by handing the same buffer twice, which confused GStreamer's/v4lsrc + buffer_free override + add debugging + +2004-04-27 Thomas Vander Stichele + + * Makefile.am: + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_class_init), (gst_videotestsrc_change_state), + (gst_videotestsrc_init), (gst_videotestsrc_get), + (gst_videotestsrc_set_property), (gst_videotestsrc_get_property): + * gst/videotestsrc/gstvideotestsrc.h: + add num-buffers property + + 2004-04-26 Benjamin Otte + + * ext/mad/gstid3tag.c: (plugin_init): + set id3mux rank to NONE so it doesn't confuse spider + require audio/mpeg,mpegversion=1 in id3mux + +2004-04-26 Benjamin Otte + + * configure.ac: + detect faad correctly as non-working if it's indeed non-working + +2004-04-26 Thomas Vander Stichele + + * Makefile.am: + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_get_type), + (gst_jpegenc_class_init), (gst_jpegenc_getcaps): + fix _getcaps so it only negotiates to its supported format + +2004-04-25 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (_fixate_caps_to_int): + fix memleak + +2004-04-23 Benjamin Otte + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + audio/x-raw-int with height rules! not. Now it's depth. + +2004-04-22 Ronald Bultje + + * gst/wavparse/gstwavparse.c: (gst_wavparse_create_sourcepad), + (gst_wavparse_parse_fmt), (gst_wavparse_handle_sink_event), + (gst_wavparse_loop): + Missing variable initialization. Add handling of DVI ADPCM. Fix + mis-parsing of LIST chunks. This works around a bug where we mis- + parse non-aligning LIST chunks (so LIST chunks where the contents + don't align with the actual LIST size). The correct fix is to use + rifflib, I'm not going to fix wavparse - too much work. All this + fixes #104878. + +2004-04-22 Zaheer Abbas Merali + + reviewed by Benjamin Otte + + * ext/shout/gstshout.c: (gst_icecastsend_change_state): + fix shoutcast not working (fixes #140844) + +2004-04-22 Benjamin Otte + + * ext/hermes/gsthermescolorspace.c: + (gst_hermes_colorspace_caps_remove_format_info): + * gst/colorspace/gstcolorspace.c: + (gst_colorspace_caps_remove_format_info): + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_caps_remove_format_info): + s/gst_caps_simplify/gst_caps_do_simplify/ + +2004-04-22 Benjamin Otte + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + mpegversion is an int + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_base_init): + don't try to create pad templates with NULL caps, use any caps + instead. + +2004-04-20 David Schleef + + * ext/sdl/Makefile.am: Link against libgstinterfaces, not + libgstxoverlay. jmmv@menta.net (Julio M. Merino Vidal) + (bug #140384) + +2004-04-20 Daniel Gazard + + reviewed by David Schleef + + * ext/mad/gstid3tag.c: Add stdlib.h + * gst/rtp/gstrtpgsmenc.c: same + * gst/tags/gstid3tag.c: same + * gst/udp/gstudpsrc.c: (gst_udpsrc_get): Fix GST_DISABLE_LOADSAVE + * gst/tcp/gsttcpsink.c: (gst_tcpsink_sink_link): Adjust + GST_DISABLE_LOADSAVE use. + * gst/udp/gstudpsink.c: (gst_udpsink_sink_link): Likewise. + * gst/tcp/gsttcpsrc.c: (gst_tcpsrc_get): Likewise. + * ext/gnomevfs/gstgnomevfssrc.c: Include (needed by + atol(3)). + * sys/oss/gstosselement.h: Include (needed for dev_t). + * gst/tags/gstvorbistag.c: Include (needed by + strtoul(3)). + * gst/rtp/gstrtpL16enc.c: Include (needed by random(3)). + * ext/mad/Makefile.am: (libgstmad_la_CFLAGS): Add $(MAD_CFLAGS) + $(ID3_CFLAGS). + * ext/libfame/Makefile.am: (libgstlibfame_la_CFLAGS): Add + $(LIBFAME_CFLAGS). + +2004-04-20 David Schleef + + * gst/realmedia/rmdemux.c: This was supposed to part of the + last checkin. Same idea. + +2004-04-20 Daniel Gazard + + reviewed by David Schleef + + * configure.ac: bump required gstreamer version to 0.8.1.1 + because of following changes [--ds] + + * gst-libs/gst/riff/riff-read.c: Include gst/gstutils.h. + (gst_riff_peek_head, gst_riff_peek_list, gst_riff_read_list) + (gst_riff_read_header): Use GST_READ_UINT* + macros to access possibly unaligned memory. + + * gst/typefind/gsttypefindfunctions.c: Include gst/gstutils.h. + (mp3_type_find): Use GST_READ_UINT* + macros to access possibly unaligned memory. + (mp3_type_find, mpeg1_parse_header, qt_type_find) + (speex_type_find): Likewise + + * gst/tags/gstvorbistag.c: (ADVANCE): Likewise + + * gst/qtdemux/qtdemux.c: Include stdlib.h (needed by realloc). + (QTDEMUX_GUINT32_GET, QTDEMUX_GUINT16_GET, QTDEMUX_FP32_GET) + (QTDEMUX_FP16_GET, QTDEMUX_FOURCC_GET) + (gst_qtdemux_loop_header, gst_qtdemux_loop_header) + (qtdemux_node_dump_foreach, qtdemux_tree_get_child_by_type) + (qtdemux_tree_get_sibling_by_type): Use GST_READ_UINT* + macros to access possibly unaligned memory. + + * gst/mpegstream/gstmpegpacketize.c: (parse_generic, parse_chunk): + Likewise. + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead) + (gst_mpeg_demux_parse_packet, gst_mpeg_demux_parse_pes): Likewise. + + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain): + Likewise. + + * gst/mpeg2sub/gstmpeg2subt.c: (GST_BUFFER_DATA) + (gst_mpeg2subt_chain_subtitle): Likewise. + + * gst/mpeg1videoparse/gstmp1videoparse.c: (mp1videoparse_parse_seq) + (gst_mp1videoparse_time_code, gst_mp1videoparse_real_chain): + Likewise. + + * gst/mpeg1sys/buffer.c: (mpeg1mux_buffer_update_audio_info): + Likewise. + + * gst/cdxaparse/gstcdxaparse.c: (gst_bytestream_peek_bytes): + Likewise. + + * gst/asfdemux/gstasfdemux.c: (_read_var_length, _read_uint): + Likewise. + +2004-04-20 Thomas Vander Stichele + + * configure.ac: + update required version of GStreamer because of GST_TIME_FORMAT + +2004-04-20 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_init): + remove leftover g_print + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + don't try setting only a subset of the caps. We don't want to kill + autoplugging on purpose + +2004-04-20 Thomas Vander Stichele + + * sys/ximage/ximagesink.c: (plugin_init): + * sys/xvimage/xvimagesink.c: (plugin_init): + add debugging categories + +2004-04-20 Thomas Vander Stichele + + * po/en_GB.po: + * po/LINGUAS: + Adding en_GB translation (Gareth Owen) + +2004-04-20 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event), + (qtdemux_parse), (qtdemux_type_get), (qtdemux_dump_mvhd), + (qtdemux_dump_tkhd), (qtdemux_dump_stsd), (qtdemux_dump_unknown), + (qtdemux_parse_trak), (qtdemux_video_caps), (qtdemux_audio_caps): + A number of new features and hacks to extract the esds atom and + put it into the caps. (bug #137724) + +2004-04-19 David Schleef + + * gconf/Makefile.am: Fix for non-GNU make + * gst-libs/gst/Makefile.am: Change directory order to handle + GstPlay linking with gstinterfaces + * gst-libs/gst/audio/make_filter: make use of tr portable + * gst-libs/gst/play/Makefile.am: Add intended \ + * gst-libs/gst/xwindowlistener/xwindowlistener.c: + (gst_xwin_set_clips): Switch to ISO variadic macro. Use a + function prototype instead of void *. + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: Switch to ISO variadic + macro. + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_chain): wrap NULL in GST_ELEMENT_ERROR call + * gst/videofilter/make_filter: make use of tr portable + * pkgconfig/Makefile.am: Remove GNU extension in Makefile target + +2004-04-19 Thomas Vander Stichele + + * po/LINGUAS: + * po/uk.po: + Added Ukrainian translation (Maxim V. Dziumanenko) + +2004-04-18 Ronald Bultje + + * ext/gsm/gstgsmdec.c: (gst_gsmdec_init), (gst_gsmdec_getcaps), + (gst_gsmdec_link), (gst_gsmdec_chain): + Fix capsnego, simplify chain function slightly. + * gst/qtdemux/qtdemux.c: (qtdemux_audio_caps): + Add GSM. + +2004-04-18 Ronald Bultje + + * gst/wavparse/gstwavparse.c: (gst_wavparse_init), + (gst_wavparse_destroy_sourcepad), (gst_wavparse_create_sourcepad), + (gst_wavparse_parse_fmt), (gst_wavparse_change_state): + Hack to make wavparse work with spider (always -> sometimes pad). + Fixes #135862 && #140411. + +2004-04-18 Benjamin Otte + + * sys/oss/gstosselement.c: (gst_osselement_sync_parms), + (gst_osselement_rate_probe_check), + (gst_osselement_rate_check_rate), (gst_osselement_rate_add_rate): + get rid of \n in debug output + +2004-04-17 Iain + + * gst/wavparse/gstwavparse.c (gst_wavparse_loop): Allow all events, + not just EOS. + +2004-04-17 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_get_type), + (gst_id3_tag_class_init), (gst_id3_tag_get_caps), + (gst_id3_tag_add_src_pad), (gst_id3_tag_init), + (gst_id3_tag_set_property), (gst_id3_tag_do_caps_nego), + (gst_id3_tag_src_link), (gst_id3_tag_chain), + (gst_id3_tag_change_state), (plugin_init): + deprecate id3tag element and replace with id3demux/id3mux. + great side effect: this ugly file is now even uglier, yay! + * ext/mad/gstmad.h: + remove non-available function + update for new get_type + +2004-04-17 Benjamin Otte + + * configure.ac: + require mpeg2dec >= 0.4.0 + +2004-04-17 Benjamin Otte + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_xcontext_get), (gst_xvimagesink_change_state), + (gst_xvimagesink_set_xwindow_id): + call GST_ELEMENT_ERROR whenever get_xcontext fails. Includes + assorted cleanup fixes. + +2004-04-16 David Schleef + + * sys/ximage/ximagesink.h: Compile fix for FreeBSD. (bug #140268) + * sys/xvimage/xvimagesink.h: same + +2004-04-16 Thomas Vander Stichele + + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_open_file): + Fix GST_ELEMENT_ERROR with (NULL) + +2004-04-15 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data): + Add div[3456] as fourccs for DivX 3 (fixes #140137). + +2004-04-15 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: + (gst_riff_create_video_caps_with_data), + (gst_riff_create_video_caps), (gst_riff_create_audio_caps), + (gst_riff_create_video_template_caps), + (gst_riff_create_audio_template_caps): + * gst-libs/gst/riff/riff-media.h: + * gst-libs/gst/riff/riff-read.c: + (gst_riff_read_strf_vids_with_data), (gst_riff_read_strf_vids): + * gst-libs/gst/riff/riff-read.h: + * gst/avi/gstavidemux.c: (gst_avi_demux_add_stream): + Add MS RLE support. I added some functions to read out strf chunks + into strf chunks and the data behind it. This is usually color + palettes (as in RLE, but also in 8-bit RGB). Also use those during + caps creation. Lastly, add ADPCM (similar to wavparse - which + should eventually be rifflib based). + * gst/matroska/matroska-demux.c: (gst_matroska_demux_class_init), + (gst_matroska_demux_init), (gst_matroska_demux_reset): + * gst/matroska/matroska-demux.h: + Remove placeholders for some prehistoric tagging system. Didn't add + support for any tag system really anyway. + * gst/qtdemux/qtdemux.c: + Add support for audio/x-m4a (MPEG-4) through spider. + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt), + (gst_wavparse_loop): + ADPCM support (#135862). Increase max. buffer size because we + cannot split buffers for ADPCM (screws references) and I've seen + files with 2048 byte chunks. 4096 seems safe for now. + +2004-04-15 Thomas Vander Stichele + + * configure.ac: bump nano to 1 + +=== release 0.8.1 === + +2004-04-15 Thomas Vander Stichele + + * configure.ac: releasing 0.8.1, "Comforting Sounds" + +2004-04-14 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Fix typo in divxversion (3 instead of 4 for "DIVX" fourcc). + Fixes #140058 + +2004-04-14 Thomas Vander Stichele + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_plugin_init): + lower rank of dvddemux so that it's not used for mpeg playback. + +2004-04-14 Benjamin Otte + + * configure.ac: + save libs correctly when checking mad + +2004-04-14 Thomas Vander Stichele + + * ext/mad/gstid3tag.c: (plugin_init): + lower rank of id3tag as proposed by Benjamin. Fixes #139926. + +2004-04-13 David Schleef + + * common/m4/gst-feature.m4: Call -config scripts with + --plugin-libs if it is supported. + * gst/avi/gstavimux.c: (gst_avimux_vidsinkconnect): sequences of + JPEG images are image/jpeg. + * gst/debug/Makefile.am: + * gst/debug/negotiation.c: (gst_negotiation_class_init), + (gst_negotiation_getcaps), (gst_negotiation_pad_link), + (gst_negotiation_update_caps), (gst_negotiation_get_property), + (gst_negotiation_plugin_init): Add a property that acts like + filter caps. + * testsuite/gst-lint: Move license checking to be a standard + test. + +2004-04-13 David Schleef + + * gst/avi/gstavidemux.c: (gst_avi_demux_reset): Fix memleak. + patch from Sebastien Cote (bug #139958) + +2004-04-13 Thomas Vander Stichele + + * examples/gstplay/Makefile.am: + * examples/gstplay/player.c: (main): + make the commandline player example use gconf settings + +2004-04-13 Thomas Vander Stichele + + * ext/libcaca/gstcacasink.c: (gst_cacasink_class_init), + (gst_cacasink_sinkconnect), (gst_cacasink_init), + (gst_cacasink_chain), (gst_cacasink_open), (gst_cacasink_close): + init/end library during state transition, not object + creation/disposal. get rid of custom dispose handler. + + +2004-04-12 Christian Schaller + + * sys/oss/gstosselement.c: s/lstat/stat/ from freeBSD, since it can + be a symlink + +2004-04-11 Ronald Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_data): + Handle JUNK chunks inside data section. Prevents warnings. + +2004-04-11 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_video_template_caps): + Add MS video v1. + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_index), + (gst_avi_demux_stream_data): + Add support for "rec-list" chunks. + +2004-04-11 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_audio_caps): + Fix another codecname mismatch. + +2004-04-11 Ronald Bultje + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Fix divx caps mismatch and move from video/x-jpeg to image/jpeg + so that MJPEG plays back. + +2004-04-10 Ronald Bultje + + * gst/mpeg1videoparse/gstmp1videoparse.c: (gst_mp1videoparse_init), + (gst_mp1videoparse_real_chain), (gst_mp1videoparse_change_state): + * gst/mpeg1videoparse/gstmp1videoparse.h: + Fix for some slight mis-cuts in buffer parsing, and for some + potential overflows or faults-causers. Adds disconts. Also fixes + #139105 while we're at it. + +2004-04-10 Ronald Bultje + + * configure.ac: + * sys/v4l2/gstv4l2element.h: + Workaround for missing struct v4l2_buffer declaration in Suse 9 + and Mandrake 10 linux/videodev2.h header file (#135919). + +2004-04-10 Ronald Bultje + + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_open_file): + Bail out if no filename was given. + +2004-04-10 Ronald Bultje + + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_v4l2fourcc_to_caps), + (gst_v4l2_fourcc_from_structure): + Add Y41B/Y42B YUV formats (see #125732), fix Y41P (was typo'ed to + Y41B somewhere). + +2004-04-09 Benjamin Otte + + * ext/gnomevfs/gstgnomevfssink.c: + (_gst_boolean_allow_overwrite_accumulator), + (gst_gnomevfssink_class_init): + fix erase signal - if any handler returns false the file will not be + overwritten. If no handler is connected, the file will not be + overwritten either. + renamed signal to "allow-overwrite" + * ext/mad/gstid3tag.c: (tag_list_to_id3_tag_foreach): + free string when adding it to ID3 failed + * ext/vorbis/vorbisdec.c: (vorbis_dec_event): + unref event when done + * gst/audioconvert/gstaudioconvert.c: (_fixate_caps_to_int): + free caps + * gst/typefind/gsttypefindfunctions.c: + (mpeg_video_stream_type_find): + fix invalid read + +2004-04-08 David Schleef + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_register): Change rank to PRIMARY. + +2004-04-08 David Schleef + + * gst/colorspace/gstcolorspace.c: Don't advertise a conversion + we don't support (bug #139532) + +2004-04-07 Thomas Vander Stichele + + * ext/mad/gstmad.c: (gst_mad_handle_event), + (gst_mad_check_caps_reset), (gst_mad_chain), + (gst_mad_change_state): + only set explicit caps if they haven't been set before for + this stream. MPEG-audio sample rate/channels aren't allowed + to change in-stream. + Fixes #139382 + +2004-04-06 Ronald Bultje + + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_base_init), + (_gst_boolean_did_something_accumulator), + (gst_gnomevfssink_class_init), (gst_gnomevfssink_dispose), + (gst_gnomevfssink_init), (gst_gnomevfssink_set_property), + (gst_gnomevfssink_get_property), (gst_gnomevfssink_open_file), + (gst_gnomevfssink_close_file), (gst_gnomevfssink_chain), + (gst_gnomevfssink_change_state): + Fix erase signal. Don't erase by default. Remove handoff signal. + Remove erase property. Don't segfault. General cleanup. + +2004-04-07 Benjamin Otte + + * gst-libs/gst/gconf/test-gconf.c: (main): + add missing gst_init + +2004-04-07 Benjamin Otte + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_dispose): + free the mutexes, too + +2004-04-07 Benjamin Otte + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_dispose): + actually free the URI string + * ext/mad/gstid3tag.c: (gst_id3_tag_src_event): + compute offset correctly when passing discont events + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event): + don't leak discont events + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_video_caps): + add some missing breaks so caps aren't copied randomly + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_get_video_stream): + if we realloc memory, we better use it + +2004-04-06 Benjamin Otte + + * ext/mad/gstmad.c: (normal_seek): + fix GST_FORMAT_TIME usage + +2004-04-05 David Schleef + + * ext/kio/kiosrc.cpp: Undefine KDE_DEPRECATED so we can use + a deprecated function (hack!) + +2004-04-05 Benjamin Otte + + * ext/esd/esdmon.c: (gst_esdmon_get): + fix nonterminated vararg and memleak + +2004-04-05 Benjamin Otte + + * ext/ladspa/gstladspa.c: (gst_ladspa_class_init), + (gst_ladspa_init), (gst_ladspa_force_src_caps), + (gst_ladspa_set_property), (gst_ladspa_get_property), + (gst_ladspa_instantiate), (gst_ladspa_activate), + (gst_ladspa_deactivate), (gst_ladspa_loop), (gst_ladspa_chain): + clean up debugging + +2004-04-05 Stefan Kost + + reviewed by Benjamin Otte + + * ext/ladspa/gstladspa.c: (gst_ladspa_class_init): + check for broken LADSPA parameters (fixes #138635) + +2004-04-05 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_getcaps): + advertise buffer-frames correctly on sinkpads + +2004-04-05 Thomas Vander Stichele + + * ext/mad/gstmad.c: (gst_mad_get_type), (gst_mad_layer_get_type), + (gst_mad_mode_get_type), (gst_mad_emphasis_get_type), + (gst_mad_get_event_masks), (gst_mad_get_query_types), (index_seek), + (normal_seek), (gst_mad_src_event), (gst_mad_handle_event), + (gst_mad_check_caps_reset), (gst_mad_chain): + add more debugging, only reset caps when we're not in error state + +2004-04-05 Thomas Vander Stichele + + * ext/mad/gstmad.c: add debugging category, comment + cleanups + +2004-04-05 Julio M. Merino Vidal + + reviewed by Benjamin Otte + + * configure.ac: + fix == in test(1) operator + +2004-04-05 Julio M. Merino Vidal + + reviewed by Benjamin Otte + + * configure.ac: + fix --export-symblos-regex to a working regex. + +2004-04-04 Benjamin Otte + + * sys/oss/.cvsignore: + add for oss_probe + +2004-04-03 Tim-Phillip Müller + + reviewed by Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event): + add missing 'new_media' argument (fixes #138168) + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_handle_seek_event): + add vararg terminator (fixes #138169) + +2004-04-02 David Schleef + + * ext/gdk_pixbuf/Makefile.am: Make sure gstgdkanimation.h is + disted (bug #138914) + +2004-04-01 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_change_state), + (gst_alsa_close_audio): + handle case better where a soundcard can't pause + * ext/ogg/gstoggdemux.c: + don't crash when we get events but don't have pads yet + +2004-04-01 Thomas Vander Stichele + + * sys/oss/gstosselement.c: (gst_osselement_probe_caps): + throw an error if we couldn't probe any caps. + +2004-04-01 Jan Schmidt + + * ext/dvdnav/gst-dvd: + Add a really simple sample DVD player + +2004-04-01 Jan Schmidt + + * ext/a52dec/gsta52dec.c: (gst_a52dec_get_type), (gst_a52dec_init), + (gst_a52dec_push), (gst_a52dec_handle_event), + (gst_a52dec_update_streaminfo), (gst_a52dec_loop), + (gst_a52dec_change_state): + * ext/a52dec/gsta52dec.h: + Use a debug category, Output timestamps correctly + Emit tag info, Handle events, tell liba52dec about cpu + capabilities so it can use MMX etc. + * ext/dv/gstdvdec.c: (gst_dvdec_loop), (gst_dvdec_change_state): + Fix a crasher accessing invalid memory + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_init), + (dvdnavsrc_update_highlight), (dvdnavsrc_loop), + (dvdnavsrc_get_event_mask), (dvdnav_handle_navigation_event), + (dvdnavsrc_event), (dvdnavsrc_get_formats), (dvdnavsrc_convert), + (dvdnavsrc_query): + Some support for byte-format seeking. + Small fixes for still frames and menu button overlays + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_get_type), + (gst_mpeg2dec_alloc_buffer): + Use a debug category. Adjust the report level of several items to + LOG. Call mpeg2_custom_fbuf to mark our buffers as 'custom buffers' + so it doesn't lose the GstBuffer pointer + * gst/debug/Makefile.am: + * gst/debug/gstdebug.c: (plugin_init): + * gst/debug/gstnavseek.c: (gst_navseek_get_type), + (gst_navseek_base_init), (gst_navseek_class_init), + (gst_navseek_init), (gst_navseek_seek), + (gst_navseek_handle_src_event), (gst_navseek_set_property), + (gst_navseek_get_property), (gst_navseek_chain), + (gst_navseek_plugin_init): + * gst/debug/gstnavseek.h: + Add the navseek debug element for seeking back and forth in a + video stream using arrow keys. + * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_get_type), + (gst_mpeg2subt_base_init), (gst_mpeg2subt_class_init), + (gst_mpeg2subt_init), (gst_mpeg2subt_finalize), + (gst_mpeg2subt_getcaps_video), (gst_mpeg2subt_link_video), + (gst_mpeg2subt_handle_video), (gst_mpeg2subt_src_event), + (gst_mpeg2subt_parse_header), (gst_get_nibble), + (gst_setup_palette), (gst_get_rle_code), (gst_draw_rle_line), + (gst_merge_uv_data), (gst_mpeg2subt_merge_title), + (gst_update_still_frame), (gst_mpeg2subt_handle_subtitle), + (gst_mpeg2subt_handle_dvd_event), (gst_mpeg2subt_loop): + * gst/mpeg2sub/gstmpeg2subt.h: + Pretty much a complete rewrite. Now a loopbased element. May still + require work to properly synchronise subtitle buffers. + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_process_private), + (gst_dvd_demux_send_subbuffer): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_send_subbuffer): + Don't attempt to create subbuffers of size 0 + Reduce a couple of error outputs to warnings. + * gst/y4m/gsty4mencode.c: (gst_y4mencode_sinkconnect), + (gst_y4mencode_chain): + Output the y4m frame header correctly. + +2004-04-01 Thomas Vander Stichele + + * gst/adder/gstadder.c: (gst_adder_get_type), (gst_adder_loop): + throw errors instead of allowing SIGFPE + +2004-04-01 Thomas Vander Stichele + + * gst-libs/gst/gconf/gconf.c: (gst_gconf_get_string), + (gst_gconf_render_bin_from_key): + leak plugging and style fixing + +2004-03-31 David Schleef + + * gst/audioscale/gstaudioscale.c: (gst_audioscale_expand_value), + (gst_audioscale_getcaps): Fix getcaps to expand and union lists. + (bug #138225) + * gst/debug/Makefile.am: + * gst/debug/breakmydata.c: (gst_break_my_data_plugin_init): + * gst/debug/gstdebug.c: (plugin_init): Merge elements into one + plugin. + * gst/debug/negotiation.c: (gst_gst_negotiation_get_type), + (gst_negotiation_base_init), (gst_negotiation_class_init), + (gst_negotiation_init), (gst_negotiation_getcaps), + (gst_negotiation_pad_link), (gst_negotiation_chain), + (gst_negotiation_set_property), (gst_negotiation_get_property), + (gst_negotiation_plugin_init): New element to talk about random + negotiation things happening in a pipeline. + +2004-03-31 Thomas Vander Stichele + + * gst/adder/gstadder.c: (gst_adder_get_type), (gst_adder_loop): + fix integer addition with help of Stefan Kost + +2004-03-31 Thomas Vander Stichele + + * po/nl.po: updated Dutch translation (Elros Cyriatan) + +2004-03-30 David Schleef + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_alloc_buffer), + (gst_mpeg2dec_negotiate_format): Handle Y42B-format MPEG + video, patch from Matthew.Spencer@eu.sony.com (Matthew Spencer) + (bug #137504) + * ext/mpeg2dec/gstmpeg2dec.h: + +2004-03-30 David Schleef + + * ext/gdk_pixbuf/Makefile.am: Remove spurious rules. (bug #136527) + +2004-03-30 David Schleef + + * tools/gst-launch-ext-m.m: Applied patch from gnome@flyn.org (W. + Michael Petullo) to handle .mov + +2004-03-30 Benjamin Otte + + * sys/oss/gstosselement.c: (gst_osselement_probe_caps), + (gst_osselement_rate_check_rate): + probe caps correctly for sound cards that only support one format + +2004-03-30 Benjamin Otte + + * ext/kio/kiosrc.cpp: (process_events): + update handling event processing if inside KDE - untested + +2004-03-29 David Schleef + + * ext/hermes/gsthermescolorspace.c: (plugin_init): decrease rank + by 2 to not interfere with other colorspaces. + * ext/pango/gsttextoverlay.c: (plugin_init): change rank to NONE + * gst/colorspace/gstcolorspace.c: (plugin_init): decrease rank by + one to not interfere with ffmpeg_colorspace. + +2004-03-29 David Schleef + + * ext/alsa/gstalsa.c: (gst_alsa_fixate): Don't fixate fields that + aren't in the caps. + * gst/sine/gstsinesrc.c: change rate caps to [1,MAX] + * gst/videocrop/gstvideocrop.c: (plugin_init): Change rank to NONE. + +2004-03-30 Benjamin Otte + + * gst-libs/gst/riff/riff-media.c: + fail on error, don't try to set stuff on NULL caps + +2004-03-30 Benjamin Otte + + * configure.ac: + * ext/Makefile.am: + * ext/kio/Makefile.am: + * ext/kio/kioreceiver.cpp: + * ext/kio/kioreceiver.h: + * ext/kio/kiosrc.cpp: + * ext/kio/kiosrc.h: + add experimental kiosrc plugin + * ext/alsa/gstalsaplugin.c: (plugin_init): + initialize debugging category only when we're sure registering the + plugins worked. + +2004-03-29 Thomas Vander Stichele + + * examples/gstplay/player.c: (main): + * gst-libs/gst/play/play.c: (gst_play_class_init), + (gst_play_set_location), (gst_play_set_data_src), + (gst_play_set_video_sink), (gst_play_set_audio_sink), + (gst_play_set_visualization), (gst_play_connect_visualization): + check return values of element_set_state and return FALSE where + failed + +2004-03-29 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event): + try harder to check if an event is really a discont + +2004-03-29 Thomas Vander Stichele + + * po/LINGUAS: adding Azerbaijani (Mətin Əmirov) + * po/az.po: + +2004-03-28 Benjamin Otte + + * gst/mpegstream/gstdvddemux.c: (gst_dvd_demux_process_private): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead), + (gst_mpeg_demux_parse_packet), (gst_mpeg_demux_parse_pes): + get rid of non-standard "..." ranges in case statements. + +2004-03-27 Martin Soto + + * gst/mpegstream/gstmpegdemux.c: + * gst/mpegstream/gstmpegdemux.h: Complete overhaul. All DVD + specific functionality split to the new dvddemux element. + * gst/mpegstream/gstdvddemux.c: + * gst/mpegstream/gstdvddemux.h: New demultiplexer for DVD (VOB) + streams, derived from mpegdemux. + * gst/mpegstream/gstmpegparse.c: Discontinuity handling cleaned + up. SCR based timestamp rewriting can be turned off (will probably + completely disappear soon). + * ext/dvdnav/dvdnavsrc.c: Changes resulting from a few months + hacking. General cleanup. All printf statements replaced by + debugging messages. Almost complete libdvdnav support. + (dvdnavsrc_class_init): Got rid of unnecessary signals (replaced + by events. New properties for audio and subpicture languages. + (dvdnavsrc_update_highlight): Now uses events. + (dvdnavsrc_user_op): Cleaned up. + (dvdnavsrc_get): Renamed to dvdnavsrc_loop (element is now loop + based). Lots of cleanup, and propper support for most libdvdnav + events. + (dvdnavsrc_make_dvd_event): New function. + (dvdnavsrc_make_dvd_nav_packet_event): New function. + (dvdnavsrc_make_clut_change_event): New function. + +2004-03-26 Benjamin Otte + + * gst/typefind/gsttypefindfunctions.c: (theora_type_find): + fix bug where typefinding would claim it's theora whenever less then + 7 bytes of data were available + +2004-03-25 Ronald Bultje + + * gst/law/alaw-decode.c: (alawdec_getcaps), (alawdec_link), + (gst_alawdec_base_init), (gst_alawdec_class_init), + (gst_alawdec_init), (gst_alawdec_chain): + * gst/law/alaw-encode.c: (alawenc_getcaps), (alawenc_link), + (gst_alawenc_base_init), (gst_alawenc_class_init), + (gst_alawenc_init), (gst_alawenc_chain): + * gst/law/mulaw-decode.c: (mulawdec_getcaps), (mulawdec_link), + (gst_mulawdec_base_init), (gst_mulawdec_class_init), + (gst_mulawdec_init), (gst_mulawdec_chain): + * gst/law/mulaw-encode.c: (mulawenc_getcaps), (mulawenc_link), + (gst_mulawenc_base_init), (gst_mulawenc_class_init), + (gst_mulawenc_init), (gst_mulawenc_chain): + Fix capsnego in all four, remove the unused property functions and + simplify the chain functions slightly. I guess we could use macros + or something similar for those, since the code is so similar, but + I'm currently too lazy... + +2004-03-24 David Schleef + + * sys/oss/gstosselement.c: (gst_osselement_sync_parms), + (gst_osselement_close_audio), (gst_osselement_probe_caps), + (gst_osselement_get_format_structure), + (gst_osselement_rate_probe_check), (gst_osselement_rate_add_range), + (gst_osselement_rate_check_rate), (gst_osselement_rate_add_rate), + (gst_osselement_rate_int_compare): Add code to handle rate probing + (bug #120883) + * sys/oss/gstosselement.h: same + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_getcaps): + Use rate probing provided by osselement. + * sys/oss/gstosssrc.c: (gst_osssrc_init), (gst_osssrc_getcaps): same + +2004-03-24 Ronald Bultje + + * ext/xvid/gstxvidenc.c: (gst_xvidenc_set_property), + (gst_xvidenc_get_property): + ulong/int mess-up. + +2004-03-24 David Schleef + + * ext/speex/gstspeexdec.c: (gst_speexdec_base_init), + (gst_speexdec_init): + * ext/speex/gstspeexenc.c: (gst_speexenc_base_init), + (gst_speexenc_init): Create the pad template correctly (from + the static pad template, not a NULL pointer.) + +2004-03-25 Benjamin Otte + + * gst/debug/Makefile.am: + * gst/debug/breakmydata.c: + add element that quasi-randomly changes bytes in the stream. + Intended use is robustness checking of demuxers and decoders in + media tests. + +2004-03-24 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_open_audio), + (gst_alsa_probe_hw_params): + * ext/alsa/gstalsa.h: + debugging output fixes + +2004-03-24 Benjamin Otte + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_set_property): + don't g_return_if_fail if element is PLAYING, fail silently as every + other element. + * gst/effectv/gstquark.c: (gst_quarktv_chain): + only fix needed for cast lvalue issues in gst-plugins + * gst/volenv/gstvolenv.c: (gst_volenv_init): + add proxy_getcaps + +2004-03-24 Benjamin Otte + + * gst/level/gstlevel.c: (gst_level_init): + add proxying getcaps function, so level doesn't advertise impossible + caps + +2004-03-24 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event), + (gst_qtdemux_loop_header), (qtdemux_parse_moov), (qtdemux_parse), + (qtdemux_node_dump_foreach), (qtdemux_dump_mvhd), + (qtdemux_dump_tkhd), (qtdemux_dump_elst), (qtdemux_dump_mdhd), + (qtdemux_dump_hdlr), (qtdemux_dump_vmhd), (qtdemux_dump_dref), + (qtdemux_dump_stsd), (qtdemux_dump_stts), (qtdemux_dump_stss), + (qtdemux_dump_stsc), (qtdemux_dump_stsz), (qtdemux_dump_stco), + (qtdemux_dump_co64), (qtdemux_dump_dcom), (qtdemux_dump_cmvd), + (qtdemux_parse_tree), (qtdemux_parse_trak): Fix debugging + messages. Divide the chunk size by the compression ratio + (needed for MACE audio) + +2004-03-23 Ronald Bultje + + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain): + Fix buffer overflow read error. + +2004-03-23 Ronald Bultje + + * ext/alsa/gstalsa.h: + Remove unused entry. + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps): + Add cinepak. + * gst/videodrop/gstvideodrop.c: (gst_videodrop_getcaps), + (gst_videodrop_link), (gst_videodrop_chain): + Fix, sort of. Was horribly broken with new capsnego. Bah... + +2004-03-23 Jeremy Simon + + * gst/typefind/gsttypefindfunctions.c: (ape_type_find), + (plugin_init): + Add a monkeysaudio typefind function + +2004-03-23 Johan Dahlin + + * gst-libs/gst/play/play.c (gst_play_audio_fixate) + (gst_play_video_fixate): Check so the structure has the field + before trying to fixate them, this makes it possible to have + fakesinks for video and audio output without printing errors on + the output console. + +2004-03-22 David Schleef + + * sys/oss/Makefile.am: + * sys/oss/oss_probe.c: (main), (probe_check), (add_range), + (check_rate), (add_rate): Rate probing test app. + +2004-03-21 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link), + (_fixate_caps_to_int), (gst_audio_convert_fixate): + add a fixation function that pretty much does the right thing (fixes + #137556) + +2004-03-20 David I. Lehn + + * configure.ac: GST_PACKAGE default: s/GStreamer/GStreamer Plugins/ + +2004-03-20 Tim-Phillip Müller + + reviewed by: Benjamin Otte + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + terminate gst_event_new_discontinuous correctly (fixes parts of + #137711) + +2004-03-19 David Schleef + + * gst-libs/gst/Makefile.am: Enable xoverlay unconditionally, + since it doesn't depend on X, and it's part of our ABI. + +2004-03-19 Iain + + * gst/interleave/deinterleave.c (deinterleave_sink_link): Use the + is_int in the structure, not the local variable. + +2004-03-19 David Schleef + + * ext/librfb/gstrfbsrc.c: (gst_rfbsrc_change_state), + (gst_rfbsrc_init), (gst_rfbsrc_getcaps), (gst_rfbsrc_fixate), + (gst_rfbsrc_link), (gst_rfbsrc_paint_rect), (gst_rfbsrc_get): + Improvements in caps negotiation. + +2004-03-18 Thomas Vander Stichele + + * po/LINGUAS: + * po/af.po: + adding Afrikaans (Petri Jooste) + +2004-03-18 Thomas Vander Stichele + + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_chain): + throw error instead of g_critical (#137588) + +2004-03-18 Thomas Vander Stichele + + * Makefile.am: + * configure.ac: + dist common and m4 correctly + * po/sv.po: + +2004-03-17 David Schleef + + * pkgconfig/gstreamer-media-info.pc.in: Add Version. + (bug #137348) + +2004-03-17 Thomas Vander Stichele + + * po/LINGUAS: + * po/sv.po: + adding Swedish translation (Christian Rose) + +2004-03-17 Thomas Vander Stichele + + * Makefile.am: use release.mak + +2004-03-16 Thomas Vander Stichele + + * common/ChangeLog: + * common/gst-autogen.sh: + add some explanation about the version detection + * configure.ac: + fix X check + +2004-03-16 Thomas Vander Stichele + + * configure.ac: bump nano to 1 + +=== release 0.8.0 === + +2004-03-16 Thomas Vander Stichele + + * configure.ac: release 0.8.0, "Pharmaceutical Itch" + +2004-03-16 Thomas Vander Stichele + + * configure.ac: + update libtool version + * gst-libs/gst/media-info/Makefile.am: + actually use libtool version + +2004-03-15 Thomas Vander Stichele + + * configure.ac: fix speex detection to work with 1.0 but not 1.1 + +2004-03-15 Thomas Vander Stichele + + * configure.ac: + * gst-plugins.spec.in: + * pkgconfig/Makefile.am: + * pkgconfig/gstreamer-gconf-uninstalled.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-libs-uninstalled.pc.in: + * pkgconfig/gstreamer-libs.pc.in: + * pkgconfig/gstreamer-media-info-uninstalled.pc.in: + * pkgconfig/gstreamer-play-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins.pc.in: + remove @VERSION@ from some of the pc files since core and plugins + are decoupled. + created gstreamer-plugins.pc as it's a better name, but keeping + -libs around for now to get fixes upstream done first. + +2004-03-15 Julien MOUTTE + + * gst-libs/gst/play/play.c: (gst_play_get_framerate), + (gst_play_get_sink_element): First draft of gst_play_get_framerate. + * gst-libs/gst/play/play.h: + +2004-03-15 Thomas Vander Stichele + + * *.c, *.cc: don't mix tabs and spaces + +2004-03-15 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup): + use the new ffmpegcolorspace + * gst-plugins.spec.in: + package new colorspace and media-info + * configure.ac: + * pkgconfig/Makefile.am: + fix some more disting issues + * pkgconfig/gstreamer-media-info-uninstalled.pc.in: + * pkgconfig/gstreamer-media-info.pc.in: + generate media-info pc files + +2004-03-15 Johan Dahlin + + * *.h: Revert indenting + +2004-03-15 Thomas Vander Stichele + + * configure.ac: + adding ffmpegcolorspace element + * gst/ffmpegcolorspace/Makefile.am: + * gst/ffmpegcolorspace/avcodec.h: + * gst/ffmpegcolorspace/common.h: + * gst/ffmpegcolorspace/dsputil.c: (dsputil_static_init): + * gst/ffmpegcolorspace/dsputil.h: + * gst/ffmpegcolorspace/gstffmpeg.c: (plugin_init): + * gst/ffmpegcolorspace/gstffmpegcodecmap.c: + (gst_ffmpeg_pixfmt_to_caps), (gst_ffmpeg_pix_fmt_to_caps), + (gst_ffmpeg_caps_to_pix_fmt): + * gst/ffmpegcolorspace/gstffmpegcodecmap.h: + * gst/ffmpegcolorspace/gstffmpegcolorspace.c: + (gst_ffmpegcolorspace_caps_remove_format_info), + (gst_ffmpegcolorspace_getcaps), (gst_ffmpegcolorspace_pad_link), + (gst_ffmpegcolorspace_get_type), (gst_ffmpegcolorspace_base_init), + (gst_ffmpegcolorspace_class_init), (gst_ffmpegcolorspace_init), + (gst_ffmpegcolorspace_chain), (gst_ffmpegcolorspace_change_state), + (gst_ffmpegcolorspace_set_property), + (gst_ffmpegcolorspace_get_property), + (gst_ffmpegcolorspace_register): + * gst/ffmpegcolorspace/imgconvert.c: + (avcodec_get_chroma_sub_sample), (avcodec_get_pix_fmt_name), + (avcodec_get_pix_fmt), (avpicture_fill), (avpicture_layout), + (avpicture_get_size), (avcodec_get_pix_fmt_loss), + (avg_bits_per_pixel), (avcodec_find_best_pix_fmt1), + (avcodec_find_best_pix_fmt), (img_copy_plane), (img_copy), + (yuv422_to_yuv420p), (yuv422_to_yuv422p), (yuv422p_to_yuv422), + (C_JPEG_TO_CCIR), (img_convert_init), (img_apply_table), + (shrink41), (shrink21), (shrink12), (shrink22), (shrink44), + (grow21_line), (grow41_line), (grow21), (grow22), (grow41), + (grow44), (conv411), (gif_clut_index), (build_rgb_palette), + (bitcopy_n), (mono_to_gray), (monowhite_to_gray), + (monoblack_to_gray), (gray_to_mono), (gray_to_monowhite), + (gray_to_monoblack), (avpicture_alloc), (avpicture_free), + (is_yuv_planar), (img_convert), (get_alpha_info_pal8), + (img_get_alpha_info), (deinterlace_line), + (deinterlace_line_inplace), (deinterlace_bottom_field), + (deinterlace_bottom_field_inplace), (avpicture_deinterlace): + * gst/ffmpegcolorspace/imgconvert_template.h: + * gst/ffmpegcolorspace/mem.c: (av_malloc), (av_realloc), (av_free): + * gst/ffmpegcolorspace/mmx.h: + * gst/ffmpegcolorspace/utils.c: (avcodec_init): + adding ffmpegcolorspace element supplied by Ronald after cleaning + up and pulling in the right bits of upstream source. + I'm sure a better C/compiler wizard could do some cleaning up (for + example use GLIB's malloc stuff), but as a first pass this + works very well + +2004-03-15 Thomas Vander Stichele + + * ext/alsa/gstalsa.h: + I assume Ronald forgot to commit the change to have cardname + as a struct member. Expect some public spanking at the next + opportunity. + +2004-03-15 Ronald Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_get_property), + (gst_alsa_open_audio), (gst_alsa_close_audio): + * ext/alsa/gstalsa.c: + Don't open the device if we're a mixer (= padless). + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_class_init), + (gst_alsa_mixer_init), (gst_alsa_mixer_open), + (gst_alsa_mixer_close), (gst_alsa_mixer_change_state): + Open mixer during state change rather than during object + initialization. Also, get a device name. Currently in a somewhat + hackish fashion, but I didn't really find something better. + +2004-03-14 Thomas Vander Stichele + + * *.c, *.h: run gst-indent + +2004-03-14 Benjamin Otte + + * gst/modplug/gstmodplug.cc: + * gst/modplug/gstmodplug.h: + set correct timestamps on outgoing buffers + +2004-03-14 Benjamin Otte + + * gst/modplug/gstmodplug.cc: + handle events - don't do crap when a discont arrives that's not + necessary + This allows correct loading and playback of mods in Rhythmbox + +2004-03-14 Benjamin Otte + + * configure.ac: + * gst-libs/gst/gconf/Makefile.am: + * pkgconfig/Makefile.am: + move gstreamer-gconf pkgconfig files to pkgconfig/ dir. Make sure + they get rebuilt properly + * configure.ac: + when checking for vorbis, try pkgconfig first. + * gst/modplug/gstmodplug.cc: + add fixate function + +2004-03-14 Ronald Bultje + + * gst/qtdemux/qtdemux.c: (qtdemux_parse_trak): + Fix for obvious mistake, where we first shift the offset and then + read a samplesize element assuming the old offset. Note that this + part still has something weird, i.e. my movies containing those + don't actually play well, but at least there's something that looks + like sound now. + +2004-03-14 Jan Schmidt + * gst/typefind/gsttypefindfunctions.c: (speex_type_find), + (plugin_init): + Add a typefind function for speex format + +2004-03-13 Ronald Bultje + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_video_caps), + (gst_asf_demux_setup_pad): + Use 25fps as our "fake" fps value (marked for fixage in 0.9.x) + instead of 0. Reason is simple: some elements have a fps range + of 1-max instead of 0-max. So now ASF video actually works. + +2004-03-13 Thomas Vander Stichele + + * po/LINGUAS: + * po/sr.po: + adding serbian as a language + +2004-03-13 Benjamin Otte + + * gst/sine/gstsinesrc.c: (gst_sinesrc_get): + return taglist correctly from _get function, don't gst_pad_push it. + (fixes #137042) + +2004-03-13 Jan Schmidt + * ext/alsa/gstalsa.c: (gst_alsa_class_probe_devices): + +2004-03-13 Ronald Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_free_list): + * ext/alsa/gstalsamixertrack.c: (gst_alsa_mixer_track_class_init), + (gst_alsa_mixer_track_new): + * ext/alsa/gstalsamixertrack.h: + Fix ancient leftovers... MixerTrack is a GObject. + +2004-03-13 Ronald Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_class_probe_devices): + * sys/oss/gstosselement.c: (gst_osselement_class_probe_devices): + Don't block during probing... + +2004-03-12 Ronald Bultje + + * ext/alsa/gstalsa.c: (gst_alsa_get_type), (gst_alsa_class_init), + (gst_alsa_get_property), (gst_alsa_probe_get_properties), + (gst_alsa_class_probe_devices), (gst_alsa_class_list_devices), + (gst_alsa_probe_probe_property), (gst_alsa_probe_needs_probe), + (gst_alsa_probe_get_values), (gst_alsa_probe_interface_init), + (gst_alsa_open_audio), (gst_alsa_close_audio): + * ext/alsa/gstalsa.h: + Add propertyprobe interface implementation, add some device-name + property, all this so that it looks good in gnome-volume-control. + +2004-03-12 David Schleef + + * configure.ac: the Hermes library controls hermescolorspace, not + colorspace. + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_base_init), + (gst_mpeg2dec_init): minor pet peeve: disable code with #ifdef, + not /* */ + * ext/sdl/sdlvideosink.c: Change XID to unsigned long. + * ext/sdl/sdlvideosink.h: ditto. + * gst/colorspace/gstcolorspace.c: Fix old comments about Hermes + +2004-03-12 Benjamin Otte + + * gst-libs/gst/xoverlay/xoverlay.c: (gst_x_overlay_set_xwindow_id), + (gst_x_overlay_got_xwindow_id): + * gst-libs/gst/xoverlay/xoverlay.h: + replace XID with unsigned long to get rid of the xlibs dependency in + XOverlay (fixes #137004) + +2004-03-13 Jan Schmidt + * gst/effectv/gstaging.c: (gst_agingtv_base_init), + (gst_agingtv_setup): + * gst/effectv/gstdice.c: (gst_dicetv_get_type), + (gst_dicetv_base_init), (gst_dicetv_class_init), + (gst_dicetv_setup), (gst_dicetv_init), (gst_dicetv_draw): + * gst/effectv/gstedge.c: (gst_edgetv_get_type), + (gst_edgetv_base_init), (gst_edgetv_class_init), (gst_edgetv_init), + (gst_edgetv_setup), (gst_edgetv_rgb32): + * gst/effectv/gsteffectv.c: + * gst/effectv/gstquark.c: (gst_quarktv_link), (gst_quarktv_init), + (gst_quarktv_set_property): + * gst/effectv/gstrev.c: (gst_revtv_get_type), + (gst_revtv_base_init), (gst_revtv_class_init), (gst_revtv_init), + (gst_revtv_setup), (gst_revtv_rgb32): + * gst/effectv/gstshagadelic.c: (gst_shagadelictv_get_type), + (gst_shagadelictv_base_init), (gst_shagadelictv_class_init), + (gst_shagadelictv_init), (gst_shagadelictv_setup), + (gst_shagadelictv_rgb32): + * gst/effectv/gstvertigo.c: (gst_vertigotv_get_type), + (gst_vertigotv_base_init), (gst_vertigotv_class_init), + (gst_vertigotv_setup), (gst_vertigotv_init), (gst_vertigotv_rgb32): + * gst/effectv/gstwarp.c: + Port everything that can be ported to videofilter and fix up the caps. + Can someone with a big-endian machine please check these? + +2004-03-10 Ronald Bultje + + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_get_time), + (gst_osssink_chain), (gst_osssink_change_state): + Latest fixes for A/V sync, audio playback and such. This is about + all... MPEG playback issues are mostly related to the async build- + up of MPEG files, I cannot fix that. Use basicgthread to solve it. + +2004-03-10 Thomas Vander Stichele + + patch from: Stephane Loeuillet + + * configure.ac: + use pkg-config for some libraries, falling back to the old .m4 way + (fixes #131270) + * m4/libdv.m4: + removed + +2004-03-10 Thomas Vander Stichele + + * configure.ac: + * tools/Makefile.am: + * tools/Makefile.in: + * tools/gst-launch-ext-m.m: + * tools/gst-launch-ext.1.in: + * tools/gst-visualise-m.m: + * tools/gst-visualise.1: + * tools/gst-visualise.1.in: + reorganizing generation of script tools + +2004-03-10 Ronald Bultje + + * ext/divx/gstdivxdec.c: + Downgrade priority. We prefer ffdec_mpeg4. + * ext/faad/gstfaad.c: (gst_faad_srcgetcaps), (gst_faad_srcconnect), + (gst_faad_chain), (gst_faad_change_state): + Fix capsnego. Doesn't work for some sounds because we don't have + a 5:1 to stereo element. + * ext/xvid/gstxvid.c: (plugin_init): + Add priority. + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_chain), + (gst_osssink_change_state): + Add discont handling. + +2004-03-09 Colin Walters + + * gst/audioconvert/gstaudioconvert.c: Fix typo in width 8 + conversion. + +2004-03-09 Benjamin Otte + + * gst-libs/gst/mixer/mixer.c: (gst_mixer_class_init): + the signals take 2 arguments + +2004-03-09 David Schleef + + * ext/alsa/gstalsa.c: (gst_alsa_request_new_pad), + (gst_alsa_fixate): Add fixate function. (bug #136686) + * ext/alsa/gstalsa.h: + * ext/alsa/gstalsasink.c: (gst_alsa_sink_init): + +2004-03-09 Benjamin Otte + + * ext/mikmod/gstmikmod.c: (gst_mikmod_init), (gst_mikmod_loop), + (gst_mikmod_change_state): + * ext/mikmod/gstmikmod.h: + make mikmod's loop function not loop infinitely and call + gst_element_yield anymore + * gst/modplug/gstmodplug.cc: + fix pad negotiation (fixes #136590) + +2004-03-09 David Schleef + + * ext/lcs/Makefile.am: Fix so that the lcs colorspace plugin + doesn't conflict with the internal colorspace plugin. + * gst-libs/gst/audio/make_filter: Use `` instead of $() to + satisfy the crappy-ass shell shipped by a certain vendor. + * gst/videofilter/make_filter: same (bug #135299) + +2004-03-09 Thomas Vander Stichele + + * configure.ac: bump nano to 1 + +=== release 0.7.6 === + +2004-03-09 Thomas Vander Stichele + + * configure.in: releasing 0.7.6, "There" + +2004-03-09 Thomas Vander Stichele + + * pkgconfig/gstreamer-play-uninstalled.pc.in: + * pkgconfig/gstreamer-play.pc.in: + synchronize the two + +2004-03-09 Thomas Vander Stichele + + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_base_init), + (cdparanoia_open), (cdparanoia_event): + fix/add error handling + * po/POTFILES.in: + add cdparanoia source + * tools/Makefile.am: + make scripts executable + +2004-03-09 Thomas Vander Stichele + + * configure.ac: + * ext/vorbis/Makefile.am: + * sys/Makefile.am: + remove id3types, vorbisfile and xvideosink from the build (#133783) + +2004-03-08 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_info): + Fix metadata read crash (#136537). + +2004-03-08 Thomas Vander Stichele + + * gst-libs/gst/media-info/media-info-priv.c: (gmi_set_mime): + * gst-libs/gst/media-info/media-info.c: (gst_media_info_read): + adding mime types, fixing the one-stop function + +2004-03-08 Christian Schaller + + * ext/nas/nassink.c and /ext/nas/nassink.h: + More NAS love from Arwed von Merkatz + So lets all sing 'Can you feel the NAS tonight' + +2004-03-08 Christian Schaller + + * tools/gst-launch-ext.in: + Replace vorbisfile with oggdemux/vorbisdec/audioconvert + +2004-03-08 Thomas Vander Stichele + + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_base_init), + (gst_mpeg2dec_init): + remove the user_data pad for now, because it is being used in + fixating causing MPEG playback to fixate on 1000 Hz for playback. + If someone knows how to fix this properly, please do. + +2004-03-08 Thomas Vander Stichele + + * sys/oss/gstosssink.c: (gst_osssink_get_delay), + (gst_osssink_get_time): + add a warning, IMO this won't get triggered anymore, remove later + +2004-03-07 David Schleef + + * gst/qtdemux/qtdemux.c: (qtdemux_video_caps): Added Cinepak + format (bug #136470) + +2004-03-07 Thomas Vander Stichele + + * gst-libs/Makefile.am: + * gst-libs/gst/media-info/Makefile.am: + * gst-libs/gst/media-info/media-info-priv.c: (found_tag_callback), + (error_callback), (gst_media_info_error_create), + (gst_media_info_error_element), (gmip_init), (gmip_reset), + (gmi_clear_decoder), (gmip_find_type_pre), (gmip_find_type): + * gst-libs/gst/media-info/media-info-priv.h: + * gst-libs/gst/media-info/media-info-test.c: (main): + * gst-libs/gst/media-info/media-info.c: (gst_media_info_init), + (gst_media_info_class_init), (gst_media_info_instance_init), + (gst_media_info_set_source), (gst_media_info_read_with_idler), + (gst_media_info_read_idler), (gst_media_info_read): + * gst-libs/gst/media-info/media-info.h: + fixed, should work now + +2004-03-07 Christian Schaller + + * ext/nas/nassink.c: + A bunch of NAS fixes from Arwed von Merkatz + +2004-03-06 Ronald Bultje + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_add_stream), + (qtdemux_parse_trak): + Fix crash (j might be greater than n_samples, in which case we're + writing outside the allocated space for the array) and memleak. + +2004-03-06 Ronald Bultje + + * sys/oss/gstosssink.c: (gst_osssink_chain): + And another caller that couldn't handle delay < 0 (unsigned + integer overflow). Video now continues playing on an audio + buffer underrun, and the clock continues working. Audio still + stalls. + +2004-03-06 Ronald Bultje + + * sys/oss/gstosssink.c: (gst_osssink_get_delay), + (gst_osssink_get_time): + get_delay() may return values lower than 0. In those cases, we + should not actually cast to *unsigned* int64, that will break + stuff horribly. In my case, it screwed up A/V sync in movies + in totem rather badly. + +2004-03-06 Christophe Fergeau + + * ext/faac/gstfaac.c: (gst_faac_chain): + * ext/flac/gstflactag.c: (gst_flac_tag_chain): + * ext/libpng/gstpngenc.c: (user_write_data): + * ext/mikmod/gstmikmod.c: (gst_mikmod_loop): + * gst/ac3parse/gstac3parse.c: (gst_ac3parse_chain): + * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_chain_subtitle): + * gst/mpegstream/gstrfc2250enc.c: (gst_rfc2250_enc_add_slice): + Fix several misuse of gst_buffer_merge (it doesn't take ownership + of any buffer), should fix some leaks. I hope I didn't unref buffers + that shouldn't be... + +2004-03-06 Thomas Vander Stichele + + * gst-libs/gst/media-info/media-info-priv.c: (have_type_callback), + (deep_notify_callback), (tag_flag_score), (found_tag_callback), + (error_callback), (gmi_reset), (gmi_seek_to_track), + (gmi_get_decoder), (gmi_set_mime), (gmip_find_type_pre), + (gmip_find_type_post), (gmip_find_stream_post), + (gmip_find_track_streaminfo_post): + * gst-libs/gst/media-info/media-info-priv.h: + * gst-libs/gst/media-info/media-info-test.c: (print_tag), + (info_print), (main): + * gst-libs/gst/media-info/media-info.c: + (gst_media_info_error_create), (gst_media_info_error_element), + (gst_media_info_instance_init), (gst_media_info_get_property), + (gst_media_info_new), (gst_media_info_set_source), + (gst_media_info_read_idler), (gst_media_info_read): + * gst-libs/gst/media-info/media-info.h: + first pass at making this work again. This seems to work on + tagged ogg/vorbis and mp3 files. + +2004-03-06 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_chain): + fix huge leak: gst_buffer_merge doesn't unref the first argument + itself. + +2004-03-06 Thomas Vander Stichele + + * ext/mad/gstmad.c: (gst_mad_class_init), (gst_mad_update_info): + report layer/mode/emphasis + +2004-03-06 Christophe Fergeau + + * ext/mad/gstmad.c: (gst_mad_chain): fixed caps leak + +2004-03-06 Thomas Vander Stichele + + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_new): + signal serial + +2004-03-06 Thomas Vander Stichele + + * ext/vorbis/vorbis.c: (plugin_init): + * ext/vorbis/vorbisdec.c: (vorbis_dec_get_formats), + (gst_vorbis_dec_init), (vorbis_dec_event): + add debug category + make vorbisdec handle _BYTE and _TIME queries + +2004-03-06 Christophe Fergeau + + * ext/mad/gstmad.c: (gst_mad_chain): send the average bitrate read + from the xing header + +2004-03-06 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_getcaps), + (gst_audio_convert_link), (gst_audio_convert_change_state), + (gst_audio_convert_buffer_from_default_format): + do conversions from/to float correctly, fix some caps nego errors, + export correct supported caps in template and getcaps, use correct + caps in try_set_caps functions + +2004-03-06 Christophe Fergeau + + For some reason, I only committed a ChangeLog entry yesterday and + not the corresponding code... + * ext/mad/gstmad.c: Fix detection of Xing headers + * gst/tags/gstid3tag.c: Changes to support TLEN tags + +2004-03-06 Benjamin Otte + + * ext/ogg/gstoggdemux.c: (gst_ogg_get_pad_by_pad), + (gst_ogg_demux_src_query): + make sure to handle the case where there's no current chain + gracefully. + +2004-03-05 David Schleef + + * ext/aalib/gstaasink.c: (gst_aasink_fixate), (gst_aasink_init): + Add fixate function. (bug #131128) + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_init), + (gst_sdlvideosink_fixate): Add fixate function. + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + Fix attempt to print a non-pointer using GST_PTR_FORMAT. + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt): + Fix missing break that was causing ulaw to be interpreted as + raw int. + +2004-03-05 David Schleef + + * gst/mpegstream/gstrfc2250enc.c: (gst_rfc2250_enc_add_slice): + Fix code that ignores return value of gst_buffer_merge(). + (bug #114560) + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_descramble_segment): + * gst/mpegstream/gstrfc2250enc.c: (gst_rfc2250_enc_add_slice): same + * testsuite/gst-lint: Check for above. + +2004-03-05 David Schleef + + * gst/udp/gstudpsrc.c: (gst_udpsrc_get): Check for unfixed + caps and throw an element error. (bug #136334) + +2004-03-05 David Schleef + + * ext/faad/gstfaad.c: (gst_faad_init), (gst_faad_srcgetcaps), + (gst_faad_chain): Fix negotiation. + * ext/librfb/gstrfbsrc.c: (gst_rfbsrc_handle_src_event): Add + key and button events. + * gst-libs/gst/floatcast/floatcast.h: Fix a minor bug in this + dung heap of code. + * gst-libs/gst/gconf/gstreamer-gconf-uninstalled.pc.in: gstgconf + depends on gconf + * gst-libs/gst/gconf/gstreamer-gconf.pc.in: same + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup), + (gst_play_video_fixate), (gst_play_audio_fixate): Add a fixate + function to encourage better negotiation, particularly between + audioconvert and osssink. + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_chain): + * gst/qtdemux/qtdemux.c: (qtdemux_parse_trak): Make some debugging + more important. + * gst/typefind/gsttypefindfunctions.c: Fix mistake in flash + typefinding. + * gst/vbidec/vbiscreen.c: Add glib header + * pkgconfig/gstreamer-play.pc.in: Depends on gst-interfaces. + +2004-03-06 Christophe Fergeau + + * ext/mad/gstmad.c: Fix detection of Xing headers + * gst/tags/gstid3tag.c: Changes to support TLEN tags + +2004-03-06 Thomas Vander Stichele + + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt), + (gst_wavparse_pad_convert), (gst_wavparse_pad_query): + debug updates + +2004-03-06 Christophe Fergeau + + * ext/mad/gstid3tag.c: (gst_mad_id3_to_tag_list): + * ext/mad/gstmad.c: (gst_mad_init), (is_xhead), + (mpg123_parse_xing_header), (gst_mad_chain): parse Xing header in vbr + files, and report the parsed length as a GST_TAG_DURATION tag. + * gst/tags/gstid3tag.c: support TLEN (duration) tag + +2004-03-05 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_channels): + convert channels correctly. convert correctly to unsigned. + +2004-03-05 Julien MOUTTE + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_change_state): Check if + we have a window before clearing it. + +2004-03-05 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_change_state): Check if we + have a window before clearing it. + +2004-03-05 Thomas Vander Stichele + + * gconf/gstreamer.schemas.in: + * gst-libs/gst/gconf/Makefile.am: + version installation path the same way as for 0.6 + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-libs-uninstalled.pc.in: + * pkgconfig/gstreamer-play-uninstalled.pc.in: + remove comment that was fixed + +2004-03-05 David Schleef + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_get_src_formats), + (gst_qtdemux_src_convert), (gst_qtdemux_get_src_query_types), + (gst_qtdemux_get_event_mask), (gst_qtdemux_handle_src_query), + (gst_qtdemux_handle_src_event), (gst_qtdemux_add_stream): + Add prototype code for handling seeking and querying. + +2004-03-04 Ronald Bultje + + * examples/gstplay/player.c: (main): + Initialize variables to NULL. Prevents a segfault because the + (uninitialized) variable is not NULL, resulting in a crash on + trying to reach error->message. + +2004-03-05 Benjamin Otte + + * gst/audioconvert/gstaudioconvert.c: + (gst_audio_convert_buffer_to_default_format): + make float=>int conversion work correctly even in cornercases. + +2004-03-04 David I. Lehn + + * debian/README.Debian: + * debian/build-deps: + * debian/changelog: + * debian/control: + * debian/control.in: + * debian/copyright: + * debian/gstreamer-a52dec.files: + * debian/gstreamer-aa.files: + * debian/gstreamer-alsa.files: + * debian/gstreamer-alsa.manpages: + * debian/gstreamer-arts.files: + * debian/gstreamer-artsd.files: + * debian/gstreamer-audiofile.files: + * debian/gstreamer-avifile.files: + * debian/gstreamer-cdparanoia.files: + * debian/gstreamer-colorspace.files: + * debian/gstreamer-doc.files: + * debian/gstreamer-dv.files: + * debian/gstreamer-dvd.files: + * debian/gstreamer-esd.files: + * debian/gstreamer-festival.files: + * debian/gstreamer-flac.files: + * debian/gstreamer-gconf.conffiles: + * debian/gstreamer-gconf.files: + * debian/gstreamer-gconf.postinst: + * debian/gstreamer-gnomevfs.files: + * debian/gstreamer-gsm.files: + * debian/gstreamer-http.files: + * debian/gstreamer-jack.files: + * debian/gstreamer-jpeg.files: + * debian/gstreamer-mad.files: + * debian/gstreamer-mikmod.files: + * debian/gstreamer-misc.files: + * debian/gstreamer-mpeg2dec.files: + * debian/gstreamer-oss.files: + * debian/gstreamer-plugin-apps.files: + * debian/gstreamer-plugin-apps.manpages: + * debian/gstreamer-plugin-libs-dev.files: + * debian/gstreamer-plugin-libs.files: + * debian/gstreamer-plugin-template.postinst: + * debian/gstreamer-plugin-template.postrm: + * debian/gstreamer-sdl.files: + * debian/gstreamer-sid.files: + * debian/gstreamer-vorbis.files: + * debian/gstreamer-x.files: + * debian/mk.control: + * debian/rules: + Debian package info not maintained here. + +2004-03-04 Thomas Vander Stichele + + * ext/aalib/gstaasink.c: (gst_aasink_class_init): + * ext/cdaudio/gstcdaudio.c: (gst_cdaudio_class_init): + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_class_init): + * ext/divx/gstdivxenc.c: (gst_divxenc_class_init): + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_class_init): + * ext/gsm/gstgsmenc.c: (gst_gsmenc_class_init): + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_class_init): + * ext/musicbrainz/gsttrm.c: (gst_musicbrainz_class_init): + * ext/speex/gstspeexenc.c: (gst_speexenc_class_init): + * ext/xvid/gstxvidenc.c: (gst_xvidenc_class_init): + * gst-libs/gst/colorbalance/colorbalance.c: + (gst_color_balance_class_init): + * gst-libs/gst/colorbalance/colorbalancechannel.c: + (gst_color_balance_channel_class_init): + * gst-libs/gst/mixer/mixer.c: (gst_mixer_class_init): + * gst-libs/gst/play/play.c: (gst_play_class_init): + * gst-libs/gst/propertyprobe/propertyprobe.c: + (gst_property_probe_iface_init): + * gst-libs/gst/tuner/tuner.c: (gst_tuner_class_init): + * gst-libs/gst/tuner/tunerchannel.c: + (gst_tuner_channel_class_init): + * gst-libs/gst/xoverlay/xoverlay.c: (gst_x_overlay_base_init): + * gst/cutter/gstcutter.c: (gst_cutter_class_init): + * gst/effectv/gstvertigo.c: (gst_vertigotv_class_init): + * sys/cdrom/gstcdplayer.c: (cdplayer_class_init): + * sys/dxr3/dxr3spusink.c: (dxr3spusink_class_init): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_class_init): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_class_init): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init): + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_class_init): + fix signals to use - instead of _ + * ext/libcaca/gstcacasink.h: + * ext/sdl/sdlvideosink.h: + fix header rename + +2004-03-04 David Schleef + + * testsuite/gst-lint: Add a check for bad signal names. + +2004-03-04 + + reviewed by David Schleef + + * gst/videofilter/gstgamma.c: (gst_gamma_rgb32): Fix typo that + modified the alpha channel and caused a warning. (bug #136192) + +2004-04-03 Christian Schaller + + * gst-plugins.spec.in: + Change names of plugins to actually be correct. Try to keep things + alphabetical to avoid getting beat up by Thomas + +2004-03-03 Julien MOUTTE + + * gst-libs/gst/gconf/gconf.c: (gst_gconf_get_default_video_sink): + Using ximagesink as a default if no gconf key found. We should + probably consider using alsasink instead of osssink for the audio + part. + +2004-03-02 Thomas Vander Stichele + + * configure.ac: + fix --with-plugins, don't think it ever worked before + * gst-plugins.spec.in: + even more updates + +2004-03-01 Ronald Bultje + + * ext/sdl/sdlvideosink.h: + * sys/ximage/ximagesink.h: + * sys/xvideo/xvideosink.h: + * sys/xvimage/xvimagesink.h: + Fix for move of gstvideosink.h -> videosink.h. + +2004-03-02 Thomas Vander Stichele + + * gst-libs/gst/xwindowlistener/Makefile.am: + this is a plugin library, not a library + +2004-03-01 David Schleef + + * AUTHORS: Added some names. Add yourself if you're still + missing. + +2004-03-01 David Schleef + + * MAINTAINERS: Add + +2004-03-01 Thomas Vander Stichele + + * gst-plugins.spec.in: clean up spec file + +2004-03-01 Thomas Vander Stichele + + * gst-libs/gst/video/Makefile.am: + * gst-libs/gst/video/gstvideosink.c: + * gst-libs/gst/video/gstvideosink.h: + rename gstvideosink.h to videosink.h to match other headers + * gst/mixmatrix/Makefile.am: + fix plugin filename + * gst/tags/Makefile.am: fix plugin filename + +2004-03-01 Thomas Vander Stichele + + * gst/tags/Makefile.am: fix plugin filename + +2004-03-01 Thomas Vander Stichele + + * examples/gstplay/player.c: (got_time_tick), (main): + add error handler + display time_tick more readably + * gst/mixmatrix/Makefile.am: + fix plugin file name + +2004-02-29 Christophe Fergeau + + * sys/oss/gstosselement.c: (gst_osselement_probe), + (device_combination_append), (gst_osselement_class_probe_devices): + * sys/oss/gstosselement.h: + Reworked enumeration of oss dsps and mixers so that gst-mixer works + on my system using alsa oss emulation, fixes bug #135597 + +2004-02-29 Ronald Bultje + + * gst/videodrop/gstvideodrop.c: (gst_videodrop_init), + (gst_videodrop_chain), (gst_videodrop_change_state): + * gst/videodrop/gstvideodrop.h: + Work based on timestamp of input data, not based on the expected + framerate from the input. The consequence is that this element now + not only scales framerates, but also functions as a framerate + corrector or framerate stabilizer/constantizer. + +2004-02-27 David Schleef + + patches from jmmv@menta.net (Julio M. Merino Vidal) + + * gst/interleave/deinterleave.c: (deinterleave_chain): Fix + GST_ELEMENT_ERROR call (bug #135634) + * gst/interleave/interleave.c: (interleave_buffered_loop), + (interleave_bytestream_loop): Don't use alloca() (bug #135640) + * sys/cdrom/gstcdplayer_ioctl_bsd.h: Fix ioctls on NetBSD (bug #135645) + * sys/oss/gstosssink.c: (gst_osssink_get_delay), + (gst_osssink_chain): Fix ioctls on NetBSD. (bug #135644) + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_sync_next_frame), + (gst_v4lmjpegsrc_set_capture), (gst_v4lmjpegsrc_set_capture_m), + (gst_v4lmjpegsrc_capture_init), (gst_v4lmjpegsrc_requeue_frame): + Fix GST_ELEMENT_ERROR call. + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_try_palette): Fix + GST_ELEMENT_ERROR call. + +2004-02-27 Benjamin Otte + + * gst-libs/gst/audio/audio.h: + add macro to make sure header isn't included twice + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_chunk): + don't use gst_buffer_free + * gst/playondemand/filter.func: + don't use gst_data_free. Free data only once. + +2004-02-26 David Schleef + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/tuner/Makefile.am: + * gst/level/Makefile.am: -marshal.[ch] and -enum.[ch] files + should not be disted, -marshal.h files should not be installed, + and -enum.h files _should_ be installed. Fix to make this the + case. + +=== release 0.7.5 === + +2004-02-26 Thomas Vander Stichele + + * configure.ac: release 0.7.5, "Under The Sea" + +2004-02-25 Thomas Vander Stichele + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link), + (gst_audio_convert_change_state), (gst_audio_convert_get_buffer): + * gst/videoscale/gstvideoscale.c: + * sys/oss/gstosselement.c: (gst_osselement_sync_parms): + assorted debug/warning fixes + +2004-02-25 Thomas Vander Stichele + + * gst/videoscale/gstvideoscale.c: (gst_videoscale_getcaps), + (gst_videoscale_init), (gst_videoscale_chain), + (gst_videoscale_set_property), (plugin_init): + * gst/videoscale/gstvideoscale.h: + * gst/videoscale/videoscale.c: (gst_videoscale_setup), + (gst_videoscale_scale_rgb), (gst_videoscale_planar411), + (gst_videoscale_planar400), (gst_videoscale_packed422), + (gst_videoscale_packed422rev), (gst_videoscale_32bit), + (gst_videoscale_24bit), (gst_videoscale_16bit), + (gst_videoscale_bilinear), (gst_videoscale_bicubic), + (gst_videoscale_scale_plane_slow), + (gst_videoscale_scale_point_sample), + (gst_videoscale_scale_nearest), + (gst_videoscale_scale_nearest_str2), + (gst_videoscale_scale_nearest_str4), + (gst_videoscale_scale_nearest_32bit), + (gst_videoscale_scale_nearest_24bit), + (gst_videoscale_scale_nearest_16bit): + add debugging category and use it properly + fix use of GST_PTR_FORMAT + +2004-02-25 Andy Wingo + + * gst/interleave/interleave.c (interleave_buffered_loop): Always + push only when channel->buffer is NULL. Prevents segfaults doing + the state change after a nonlocal exit, like a scheme exception. + + * gst/audioconvert/gstaudioconvert.c (gst_audio_convert_getcaps): + Handle the case where the intersected caps is empty. + +2004-02-25 Thomas Vander Stichele + + * gst/law/mulaw-decode.c: (mulawdec_link): + * gst/law/mulaw.c: (plugin_init): + fix mulawdec so it actually works again + +2004-02-24 Arwed v. Merkatz + + reviewed by: David Schleef + + * gst/videofilter/gstgamma.c: (gst_gamma_class_init), + (gst_gamma_init), (gst_gamma_set_property), + (gst_gamma_get_property), (gst_gamma_calculate_tables), + (gst_gamma_rgb24), (gst_gamma_rgb32): Adds gamma correction + for RGB, with separate r g and b correction factors. (#131167) + +2004-02-24 Thomas Vander Stichele + + * ext/vorbis/vorbisdec.c: (vorbis_dec_chain): + only signal tags for bitrate if they're > 0 (#134894) + +2004-02-24 David Schleef + + * gst/qtdemux/qtdemux.c: (plugin_init), (gst_qtdemux_loop_header), + (qtdemux_parse_moov), (qtdemux_parse), (qtdemux_node_dump_foreach), + (qtdemux_dump_mvhd), (qtdemux_dump_tkhd), (qtdemux_dump_elst), + (qtdemux_dump_mdhd), (qtdemux_dump_hdlr), (qtdemux_dump_vmhd), + (qtdemux_dump_dref), (qtdemux_dump_stsd), (qtdemux_dump_stts), + (qtdemux_dump_stss), (qtdemux_dump_stsc), (qtdemux_dump_stsz), + (qtdemux_dump_stco), (qtdemux_dump_co64), (qtdemux_dump_dcom), + (qtdemux_dump_cmvd), (qtdemux_parse_tree), (qtdemux_parse_trak): + Cleanups. Convert g_prints to GST_LOGs. Add qtdemux debug + category. Attempt to fix timestamp calculation. + +2004-02-24 Johan Dahlin + + * gst-libs/gst/gconf/gconf.c: Add \n to g_print error messages + +2004-02-23 Thomas Vander Stichele + + * configure.ac: + * gconf/Makefile.am: + * gconf/gstreamer.schemas: + * gst-libs/gst/gconf/Makefile.am: + * gst-libs/gst/gconf/gconf.c: + version gconf schemas and install locations + +2004-02-23 Benjamin Otte + + * ext/xine/xineinput.c: (gst_xine_input_dispose): + (gst_xine_input_subclass_init): + call parent dispose. + change pad template for CD reader correctly + * ext/xine/Makefile.am: + * ext/xine/gstxine.h: + * ext/xine/xine.c: (plugin_init): + * ext/xine/xineaudiosink.c: + wrap audio sinks, too + * gst-libs/gst/resample/private.h: + * gst-libs/gst/resample/resample.c: (gst_resample_init), + (gst_resample_reinit), (gst_resample_scale), + (gst_resample_nearest_s16), (gst_resample_bilinear_s16), + (gst_resample_sinc_slow_s16), (gst_resample_sinc_s16), + (gst_resample_sinc_ft_s16), (gst_resample_nearest_float), + (gst_resample_bilinear_float), (gst_resample_sinc_slow_float), + (gst_resample_sinc_float), (gst_resample_sinc_ft_float): + * gst-libs/gst/resample/resample.h: + * gst/audioscale/gstaudioscale.c: (gst_audioscale_method_get_type), + (gst_audioscale_class_init), (gst_audioscale_link), + (gst_audioscale_get_buffer), (gst_audioscale_init), + (gst_audioscale_chain), (gst_audioscale_set_property), + (gst_audioscale_get_property): + * gst/audioscale/gstaudioscale.h: + s/resample_*/gst_resample_*/i to not clobber namespaces + +2004-02-23 Julien MOUTTE + + * gst-libs/gst/riff/riff-media.c: (gst_riff_create_video_caps), + (gst_riff_create_audio_caps), (gst_riff_create_iavs_caps), + (gst_riff_create_video_template_caps), + (gst_riff_create_audio_template_caps), + (gst_riff_create_iavs_template_caps): + * gst-libs/gst/riff/riff-media.h: + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_base_init), + (gst_asf_demux_audio_caps), (gst_asf_demux_add_audio_stream), + (gst_asf_demux_video_caps), (gst_asf_demux_add_video_stream): + * gst/avi/gstavidemux.c: (gst_avi_demux_add_stream): + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream), + (gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps), + (gst_matroska_demux_plugin_init): First batch implementing audio and + video codec tags in demuxers. + +2004-02-22 Benjamin Otte + + * ext/xine/Makefile.am: + * ext/xine/gstxine.h: + * ext/xine/xine.c: (plugin_init): + * ext/xine/xineinput.c: + add input plugin wrapper. Playback from files, http, mms and cdda + works. + * ext/xine/xineaudiodec.c: (gst_xine_audio_dec_chain): + remove leftover G_GNUC_UNUSED + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_stream), + (gst_asf_demux_identify_guid): + improve debugging output + +2004-02-22 Benjamin Otte + + reported by: Padraig O'Briain + + * autogen.sh: + replace test -e with test -x for mkinstalldirs to be more portable. + (fixes #134816) + +2004-02-22 Benjamin Otte + + reported by: Stefan Kost + + * gst/audioconvert/gstaudioconvert.c: (plugin_init): + set rank to PRIMARY + * gst/volume/gstvolume.c: (plugin_init): + set rank to NONE + fixes #134960 + +2004-02-22 Julio M. Merino Vidal + + reviewed by Benjamin Otte + + * ext/flac/gstflacenc.c: (gst_flacenc_chain): + escape NULL strings in GST_ELEMENT_ERROR properly (fixes #135116) + +2004-02-22 Benjamin Otte + + * configure.ac: + export [_]*{gst,Gst,GST}.* symbols from plugins + +2004-02-22 Christophe Fergeau + + reviewed by: Benjamin Otte + + * ext/lame/gstlame.c: (add_one_tag): + * ext/mad/gstid3tag.c: (gst_mad_id3_to_tag_list): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_get_tag_value), + (gst_vorbisenc_metadata_set1): + * gst/tags/gstid3tag.c: + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_add): + apply fixes from bugs #135042 (lame can't write tags) and #133817 + (add GST_ALBUM_VOLUME_{COUNT,NUMBER} tags) + +2004-02-22 Ramon Garcia + + * configure.ac: Export only gst_plugin_desc from plugins. + Note that this change only makes any effect with Linux using libtool + 1.5.2 or higher. Otherwise it is silently ignored, but it would build + fine. And don't try to have several versions of libtool in different + directories. + +2004-02-20 Andy Wingo + + * gst/intfloat/, gst/oneton: Removed, replaced by audioconvert and + interleave respectively. + + * gst/interleave/deinterleave.c: New plugin: deinterleave + (replaces on oneton). + * gst/interleave/interleave.c: New plugin: interleave. + * gst/interleave/plugin.h: Support file. + * gst/interleave/plugin.c: Support file. + + * configure.ac: Remove intfloat and oneton, add interleave. + + * ext/sndfile/gstsf.c: Handle events better. + + * gst/audioconvert/gstaudioconvert.c: Change to support int2float + and float2int operation. int2float has scheduling problems as + noted in in2float_chain. + +2004-02-20 Benjamin Otte + + * ext/xine/Makefile.am: + * ext/xine/gstxine.h: + * ext/xine/xine.c: + * ext/xine/xineaudiodec.c: + * ext/xine/xinecaps.c: + add first version of xine plugin wrapper. Currently only wraps the + QDM2 win32 DLL, and even that only in proof-of-concept quality. + * configure.ac: + * ext/Makefile.am: + add xine plugin wrapper, disabled by default. Use --enable-xine to + build. Note that it'll segfault on gst-register if you don't remove + the goom and tvtime post plugins from xine. + * gst/qtdemux/qtdemux.c: (gst_qtdemux_handle_sink_event), + (qtdemux_parse), (qtdemux_parse_trak), (qtdemux_audio_caps): + add extradata parsing for QDM2. + change around debugging prints. + +2004-02-19 Benjamin Otte + + * ext/lame/gstlame.c: (gst_lame_chain): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_chain): + use gst_tag_list_insert when you want to insert tags + +2004-02-18 David Schleef + + * configure.ac: Move massink to gst-rotten + * ext/Makefile.am: + * ext/mas/Makefile.am: + * ext/mas/massink.c: + * ext/mas/massink.h: + +2004-02-18 David Schleef + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (plugin_init): Disable gdk_pixbuf + typefinding, since it seems to be worse than nothing. + * gst/typefind/gsttypefindfunctions.c: (qt_type_find): Add ftyp + atom to recognize .mp4 and .m4a files as video/quicktime. + +2004-02-18 David Schleef + + * gst/sine/demo-dparams.c: (quit_live), + (dynparm_log_value_changed), (dynparm_value_changed), (main): + Use double dparams, not float. + * gst/sine/gstsinesrc.c: (gst_sinesrc_class_init), + (gst_sinesrc_init): Change sync default to FALSE, since multiple + sync'd elements don't really work correctly. + * gst/volume/gstvolume.c: (volume_class_init), (volume_init), + (volume_update_volume), (volume_get_property): Change dparam + to double. + +2004-02-18 Julien MOUTTE + + * sys/ximage/ximagesink.c: + (gst_ximagesink_xwindow_update_geometry), + (gst_ximagesink_renegotiate_size), (gst_ximagesink_handle_xevents), + (gst_ximagesink_change_state), (gst_ximagesink_expose), + (gst_ximagesink_init): Rework the way software video scaling works. So + now we check on each chain call if the video frames are feeling the + window. If not we try to renegotiate caps. On failure we memorize that + and we won't try again for that PLAYING sessions. + * sys/ximage/ximagesink.h: Adding a boolean to store the caps renego + failure. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_init): initialize the + synchronous flag. + +2004-02-18 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup): + break up _link so we can give a better debug message for errors + +2004-02-18 Thomas Vander Stichele + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (plugin_init): + set up debug category + +2004-02-18 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_handle_xevents), (gst_ximagesink_expose): Reorganizing + the way renegotiation work. The event handling function is not taking + care of external windows and renegotiate method check for pad flags + NEGOTIATING. Should fix : #133209 + +2004-02-17 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_expose): Checking if the + pad is negotiating before trying renegotiation. + +2004-02-17 Thomas Vander Stichele + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_type_find): + pass on all possible mime types as typefind hints + +2004-02-17 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new): Fix a + possible SHM leak if we crash. All other apps using XShm are doing + that. + +2004-02-17 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_expose): Renegotiate size on expose. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_expose): Update window + size on expose. + +2004-02-16 Benjamin Otte + + * testsuite/alsa/sinesrc.c: + cosmetic fix to fix compile issue with gcc 2.95.4 + +2004-02-16 Julien MOUTTE + + * ext/alsa/gstalsa.c: (gst_alsa_open_audio), + (gst_alsa_timestamp_to_bytes): Alsa should trigger an error if it + failed opening the audio device. + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_ximage_destroy), (gst_ximagesink_ximage_put), + (gst_ximagesink_xwindow_new), (gst_ximagesink_xwindow_destroy), + (gst_ximagesink_xwindow_resize), (gst_ximagesink_xwindow_clear), + (gst_ximagesink_renegotiate_size), (gst_ximagesink_handle_xevents), + (gst_ximagesink_xcontext_get), (gst_ximagesink_xcontext_clear), + (gst_ximagesink_change_state), (gst_ximagesink_chain), + (gst_ximagesink_set_xwindow_id): Clearing window in READY TO PAUSED. + Removing some useless g_return_if_fail like wingo suggested. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_xvimage_destroy), (gst_xvimagesink_xvimage_put), + (gst_xvimagesink_xwindow_new), (gst_xvimagesink_xwindow_destroy), + (gst_xvimagesink_xwindow_resize), (gst_xvimagesink_xwindow_clear), + (gst_xvimagesink_update_colorbalance), + (gst_xvimagesink_handle_xevents), (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_get_fourcc_from_caps), + (gst_xvimagesink_change_state), (gst_xvimagesink_chain), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_colorbalance_list_channels), + (gst_xvimagesink_colorbalance_set_value), + (gst_xvimagesink_colorbalance_get_value): Clearing window in READY TO + PAUSED. Removing some useless g_return_if_fail like wingo suggested. + +2004-02-16 Thomas Vander Stichele + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_chain): + throw error when not negotiated instead of asserting + +2004-02-15 Julien MOUTTE + + * gst/switch/gstswitch.c: (gst_switch_loop): More fixes for + correct data refcounting. + +2004-02-15 Julien MOUTTE + + * gst/switch/gstswitch.c: (gst_switch_change_state), + (gst_switch_class_init): Cleaning the sinkpads correctly on state + change, mostly the EOS flag. + +2004-02-15 Julien MOUTTE + + * examples/gstplay/player.c: (got_eos), (main): Adding some + output for debugging. + * gst-libs/gst/play/play.c: (gst_play_state_change): Stop our + timeouts if we go to any state different from PLAYING. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_seek): Fix some + more EOS bugs in riff lib. + +2004-02-14 Julien MOUTTE + + * gst-libs/gst/play/play.c: (gst_play_connect_visualization): Disable + visualization until i find a way to fix switch correctly. + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head): Fix a bug when + EOS arrives. + * gst/switch/gstswitch.c: (gst_switch_release_pad), + (gst_switch_request_new_pad), (gst_switch_poll_sinkpads), + (gst_switch_loop), (gst_switch_dispose), (gst_switch_class_init): + Reworked switch to get a more correct behaviour with events and refing + of data stored in sinkpads. + * gst/switch/gstswitch.h: Adding an eos flag for every sinkpad so that + we don't pull from a pad in EOS. + +2004-02-14 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_chain): + remove v1 tag even if we can't read it (makes sure we don't detect + it again) + +2004-02-14 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_pcm_wait), + (gst_alsa_xrun_recovery): + * ext/alsa/gstalsa.h: + try xrun recovery when wait failed. Make xrun recovery function + return TRUE/FALSE to indicate success. (might fix #134354) + +2004-02-13 David Schleef + + * gst/sine/demo-dparams.c: (dynparm_log_value_changed), + (dynparm_value_changed), (main): Convert from float to double. + * gst/sine/gstsinesrc.c: (gst_sinesrc_init): same. + +2004-02-13 David Schleef + + * gst/silence/gstsilence.c: (gst_silence_class_init), + (gst_silence_set_clock), (gst_silence_get), + (gst_silence_set_property), (gst_silence_get_property): + * gst/silence/gstsilence.h: Add sync property. + * gst/sine/gstsinesrc.c: (gst_sinesrc_class_init), + (gst_sinesrc_init), (gst_sinesrc_set_clock), (gst_sinesrc_get), + (gst_sinesrc_set_property), (gst_sinesrc_get_property): + * gst/sine/gstsinesrc.h: Add sync property. + +2004-02-13 David Schleef + + * gst/intfloat/gstint2float.c: (conv_f32_s16), + (gst_int2float_chain_gint16): Change stdint usage to glib types. + +2004-02-13 Thomas Vander Stichele + + * configure.ac: + * ext/Makefile.am: + * gst-libs/ext/Makefile.am: + move ffmpeg plugin to gst-ffmpeg module + +2004-02-13 Thomas Vander Stichele + + * configure.ac: use GST_ARCH to detect architecture + +2004-02-12 Julien MOUTTE + + * gst/vbidec/vbiscreen.c: Fixing thomasvs fixes. Missing header. + +2004-02-12 Thomas Vander Stichele + + * ext/ladspa/gstladspa.c: (gst_ladspa_base_init): + classify LADSPA plugins based on number of src/sink pads + (#133663, Stefan Kost) + * gst/sine/gstsinesrc.c: (gst_sinesrc_init): + fix dparams registration + (#133528, Stefan Kost) + * gst/vbidec/vbiscreen.c: (vbiscreen_set_current_cell): + fix use of isprint and use g_ascii_isprint instead + (#133316, Stefan Kost) + +2004-02-11 David Schleef + + Convert a few inner loops to use liboil. This is currently + optional, and is only enabled if liboil is present (duh!). + * configure.ac: Check for liboil-0.1 + * gst/intfloat/Makefile.am: + * gst/intfloat/gstint2float.c: (conv_f32_s16), (scalarmult_f32), + (gst_int2float_chain_gint16): + * gst/videofilter/Makefile.am: + * gst/videofilter/gstvideobalance.c: (gst_videobalance_class_init), + (tablelookup_u8), (gst_videobalance_planar411): + * gst/videotestsrc/Makefile.am: + * gst/videotestsrc/gstvideotestsrc.c: (plugin_init): + * gst/videotestsrc/videotestsrc.c: (splat_u8), (paint_hline_YUY2), + (paint_hline_IYU2), (paint_hline_str4), (paint_hline_str3), + (paint_hline_RGB565), (paint_hline_xRGB1555): + +2004-02-11 David Schleef + + * ext/lcs/gstcolorspace.c: (colorspace_find_lcs_format), + (gst_colorspace_caps_get_fourcc), (colorspace_setup_converter), + (gst_colorspace_getcaps), (gst_colorspace_link), + (gst_colorspace_base_init), (gst_colorspace_init), + (gst_colorspace_chain), (gst_colorspace_change_state), + (plugin_init): Merge Ronald's patch (bug #117897) and update + for new caps and negotiation. Seems to work, although it + shows off bugs in lcs. + +2004-02-11 David Schleef + + * ext/alsa/Makefile.am: Fix linking against libgstinterfaces. + (bug #133886) Noticed by bugs@leroutier.net (Stephane LOEUILLET) + +2004-02-11 David Schleef + + * ext/librfb/gstrfbsrc.c: (gst_rfbsrc_class_init), + (gst_rfbsrc_change_state), (gst_rfbsrc_init), + (gst_rfbsrc_set_property), (gst_rfbsrc_get_property): + Add server and port properties + +2004-02-11 Thomas Vander Stichele + + * m4/a52.m4: + * m4/aalib.m4: + * m4/as-ffmpeg.m4: + * m4/as-liblame.m4: + * m4/as-slurp-ffmpeg.m4: + * m4/check-libheader.m4: + * m4/esd.m4: + * m4/freetype2.m4: + * m4/gconf-2.m4: + * m4/glib.m4: + * m4/gst-alsa.m4: + * m4/gst-artsc.m4: + * m4/gst-ivorbis.m4: + * m4/gst-matroska.m4: + * m4/gst-sdl.m4: + * m4/gst-shout2.m4: + * m4/gst-sid.m4: + * m4/gtk.m4: + * m4/libdv.m4: + * m4/libfame.m4: + * m4/libmikmod.m4: + * m4/ogg.m4: + * m4/vorbis.m4: + fix underquotedness of macros (#133800) + * m4/as-avifile.m4: + * m4/xmms.m4: + removed because no longer used + +2004-02-11 Thomas Vander Stichele + + * configure.ac: + require gettext 0.11.5 so ulonglong.m4 gets checked out and copied + by autopoint (fixes #132996) + +2004-02-11 Benjamin Otte + + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_base_init): + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_base_init): + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_base_init): + * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_base_init): + fix memleaks + +2004-02-11 David Schleef + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_sink_link), + (gst_gdk_pixbuf_chain): Fix logic bug causing spurious errors. + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_base_init), + (gst_jpegdec_init), (gst_jpegdec_chain): Fix negotiation. + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_base_init), + (gst_jpegenc_class_init), (gst_jpegenc_init), + (gst_jpegenc_getcaps), (gst_jpegenc_link), (gst_jpegenc_resync), + (gst_jpegenc_chain), (gst_jpegenc_set_property), + (gst_jpegenc_get_property): Fix negotiation. Add some properties. + * ext/jpeg/gstjpegenc.h: Fix negotiation. + +2004-02-10 Benjamin Otte + + * ext/mikmod/gstmikmod.c: (gst_mikmod_init), + (gst_mikmod_srcfixate), (gst_mikmod_srclink), (gst_mikmod_loop): + * ext/mikmod/gstmikmod.h: + fix caps negotiation in mikmod + * ext/ogg/gstoggdemux.c: (gst_ogg_print): + output debug information + +2004-02-08 Benjamin Otte + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/navigation/Makefile.am: + * gst-libs/gst/xoverlay/Makefile.am: + remove unused GST_OPT_CFLAGS from Makefiles + include X_CFLAGS and X_LIBS in xoverlay. (#131948) + +2004-02-07 David Schleef + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_handle_event): Don't + push events to pads that haven't been created (#133508) + +2004-02-07 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_src_convert), + (gst_dvdec_sink_convert), (gst_dvdec_handle_sink_event), + (gst_dvdec_video_getcaps), (gst_dvdec_video_link), + (gst_dvdec_loop), (gst_dvdec_change_state): + Second attempt at committing a working dvdec element. + +2004-02-06 David Schleef + + Build fixes for OS X: (see #129600) + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_strh), + (gst_riff_read_strf_vids), (gst_riff_read_strf_auds), + (gst_riff_read_strf_iavs): + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_avih), + (gst_avi_demux_stream_odml): + * gst/playondemand/Makefile.am: + * gst/rtp/rtp-packet.c: + +2004-02-05 David Schleef + + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_loop): Revert + last change, because it Just Doesn't Compile. + +2004-02-05 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_chain): + skip undecodable id3v2 tag instead of keeping it + +2004-02-05 David Schleef + + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain): + Unref leaked buffer. (Noticed by Ronald) + +2004-02-05 David I. Lehn + + * pkgconfig/gstreamer-libs-uninstalled.pc.in: + Sync requires with other checks. >= vs =. + +2004-02-06 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_init), (gst_dvdec_video_getcaps), + (gst_dvdec_video_link), (gst_dvdec_loop): + * ext/dv/gstdvdec.h: + rework the caps negotiation so that dvdec works again instead + of just segfaulting. + +=== release 0.7.4 === + +2004-02-06 Thomas Vander Stichele + + * NEWS: GStreamer Plugins 0.7.4 "For Great Justice" released + * configure.ac: changed for release + +2004-02-05 Thomas Vander Stichele + + * gst-libs/gst/gconf/gstreamer-gconf-uninstalled.pc.in: + * pkgconfig/gstreamer-interfaces-uninstalled.pc.in: + * pkgconfig/gstreamer-libs-uninstalled.pc.in: + * pkgconfig/gstreamer-play-uninstalled.pc.in: + reworked patch by David Lehn to fix libdir and includedir for + uninstalled libraries + removed play and gconf from gstreamer-libs since they have their + own pkgconfig files + +2004-02-04 David Schleef + + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt): Fix a caps + memleak. + +2004-02-05 Benjamin Otte + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_info): + use correct GST_TAG_ENCODER tag + +2004-02-05 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_change_state): + be sure to stop the clock when going to paused + * sys/oss/gstosssink.c: (gst_osssink_change_state): + reset number of transmitted when going to ready. + fixes #132935 + +2004-02-05 Charles Schmidt + + reviewed by Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_mad_id3_to_tag_list): + extract track count (fixes #133410) + +2004-02-04 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_do_caps_nego): + that should be !=, not == (fixes #132519) + +2004-02-04 David Schleef + + Make sure set_explicit_caps() is called before adding pad. + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop): + * gst/id3/gstid3types.c: (gst_id3types_loop): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead): + * gst/realmedia/rmdemux.c: (gst_rmdemux_add_stream): + +2004-02-04 Thomas Vander Stichele + + * configure.ac: + bump nano to 2, first prerelease + put back AM_PROG_LIBTOOL + +2004-02-04 Thomas Vander Stichele + + * testsuite/alsa/Makefile.am: + these are user test apps, not automatic testsuite tests + +2004-02-04 David Schleef + + Convert GST_DEBUG_CAPS() to GST_DEBUG(): + * gst/mpeg1videoparse/gstmp1videoparse.c: + (mp1videoparse_parse_seq): + * gst/realmedia/rmdemux.c: (gst_rmdemux_add_stream): + * gst/videoscale/gstvideoscale.c: (gst_videoscale_getcaps): + * sys/xvideo/gstxwindow.c: (_gst_xwindow_new): + * sys/xvideo/xvideosink.c: (gst_xvideosink_sinkconnect), + (gst_xvideosink_getcaps): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + * testsuite/gst-lint: more tests + +2004-02-04 David Schleef + + Replace use of GST_PAD_FORMATS_FUNCTION() and similar macros + with the code that they would expand to. + * ext/flac/gstflacdec.c: (gst_flacdec_get_src_formats), + (gst_flacdec_get_src_query_types), + (gst_flacdec_get_src_event_masks): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_get_formats), + (gst_gnomevfssrc_get_query_types), + (gst_gnomevfssrc_get_event_mask): + +2004-02-04 Benjamin Otte + + * gst/sine/gstsinesrc.c: (gst_sinesrc_class_init), + (gst_sinesrc_dispose): + fix memleak by properly disposing sinesrc + +2004-02-04 Julien MOUTTE + + * gst-libs/gst/xoverlay/xoverlay.c: (gst_x_overlay_expose): + * gst-libs/gst/xoverlay/xoverlay.h: Adding the _expose method to tell + an overlay to redraw the image because it has been exposed. + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_destroy), + (gst_ximagesink_ximage_put), (gst_ximagesink_expose), + (gst_ximagesink_xoverlay_init), (gst_ximagesink_init): + * sys/ximage/ximagesink.h: Implement expose method from XOverlay + interface + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_destroy), + (gst_xvimagesink_xvimage_put), (gst_xvimagesink_expose), + (gst_xvimagesink_xoverlay_init), (gst_xvimagesink_init): + * sys/xvimage/xvimagesink.h: Implement expose method from XOverlay + interface + +2004-02-03 Benjamin Otte + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_type_find): + more memleak fixage + +2004-02-03 Benjamin Otte + + * ext/gdk_pixbuf/gstgdkpixbuf.c: (plugin_init): + * gst/typefind/gsttypefindfunctions.c: + fix memleaks shown by gst-typefind + +2004-02-03 Thomas Vander Stichele + + * common/glib-gen.mak: + add hack rule to touch .Plo files + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/tuner/Makefile.am: + remove glib_root variable + +2004-02-03 Benjamin Otte + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_add_stream): + set explicit caps before adding the element, so the autopluggers can + plug correctly. + * gst/typefind/gsttypefindfunctions.c: (mp3_type_find), + (mpeg2_sys_type_find), (mpeg1_sys_type_find), + (mpeg_video_type_find), (mpeg_video_stream_type_find), + (dv_type_find): + fix memleaks in typefind functions. gst_type_find_suggest takes a const + argument. + +2004-02-03 Thomas Vander Stichele + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/colorbalance/colorbalance-marshal.list: + * gst-libs/gst/colorbalance/colorbalance.c: + * gst-libs/gst/colorbalance/colorbalance.h: + * gst-libs/gst/colorbalance/colorbalancemarshal.list: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/mixer/mixer-marshal.list: + * gst-libs/gst/mixer/mixer.c: + * gst-libs/gst/mixer/mixer.h: + * gst-libs/gst/mixer/mixermarshal.list: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/play/play.h: + * gst-libs/gst/tuner/Makefile.am: + * gst-libs/gst/tuner/tuner-marshal.list: + * gst-libs/gst/tuner/tuner.c: + * gst-libs/gst/tuner/tuner.h: + * gst-libs/gst/tuner/tunermarshal.list: + use new glib-gen.mak snippet to clean up Makefile.am + fix various bugs in Makefile.am's + +2004-02-03 Benjamin Otte + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain): + handle chain parsing correctly in the multichain case + * ext/theora/theoradec.c: (gst_theora_dec_init), (_theora_ilog), + (theora_dec_from_granulepos), (theora_dec_to_granulepos), + (theora_dec_src_query), (theora_dec_src_event), (theora_dec_event), + (theora_dec_chain): + handle events and queries correctly + +2004-02-03 David I. Lehn + + * .cvsignore: + Ignore generated file _stdint.h. + +2004-02-03 David I. Lehn + + * gst-libs/gst/colorbalance/Makefile.am: + * gst-libs/gst/colorbalance/colorbalance.h: + * gst-libs/gst/mixer/Makefile.am: + * gst-libs/gst/mixer/mixer.h: + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/play/play.h: + * gst-libs/gst/tuner/Makefile.am: + * gst-libs/gst/tuner/tuner.h: + Generate enum type code with glib-mkenums. + * gst-libs/gst/colorbalance/.cvsignore: + * gst-libs/gst/mixer/.cvsignore: + * gst-libs/gst/play/.cvsignore: + * gst-libs/gst/tuner/.cvsignore: + Ignore generated files. + +2004-02-03 David I. Lehn + + * gst-libs/gst/audio/.cvsignore: + Ignore generated file. + * gst-libs/gst/audio/Makefile.am: + Do not install example filter. + +2004-02-03 David I. Lehn + + * examples/switch/.cvsignore: + Ignore generated file. + +2004-02-03 Benjamin Otte + + * common/m4/ax_create_stdint_h.m4: + * configure.ac: + add AX_CREATE_STDINT_H to get correct type definitions for a52dec in + _stdint.h. + * Makefile.am: + remove generated _stdint.h in DISTCLEANFILES + * ext/a52dec/gsta52dec.c: + include _stdint.h for a52dec. (should fix #133064) + +2004-02-02 Jeremy Simon + + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_add), + (gst_tag_to_vorbis_comments): + Add replaygain support to vorbistag + +2004-02-02 Jeremy Simon + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), + (gst_ffmpeg_caps_to_extradata): + Fix SVQ3 caps flag properties + Use glib macro for bytes swap + +2004-02-02 Thomas Vander Stichele + + * ext/audiofile/gstafsink.c: (gst_afsink_plugin_init): + * ext/audiofile/gstafsrc.c: (gst_afsrc_plugin_init): + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + * ext/sndfile/gstsf.c: (plugin_init): + * gst/avi/gstavi.c: (plugin_init): + * sys/dxr3/dxr3init.c: (plugin_init): + * sys/oss/gstossaudio.c: (plugin_init): + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l2/gstv4l2.c: (plugin_init): + remove textdomain calls + * po/nl.po: + update Dutch translation + +2004-02-02 Julien MOUTTE + + * gst-libs/gst/play/play.c: (gst_play_pipeline_setup), + (gst_play_set_audio_sink): Moving volume in the audio thread for + instantaneous volume change. Maybe i will add another volume in front + of visualization later, not sure yet though. + +2004-02-02 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_renegotiate_size), + (gst_ximagesink_handle_xevents): Better X events handling, only take + the latest events for configure and motion. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): same. + +2004-02-02 Jon Trowbridge + + reviewed by: David Schleef + + Fix memory leaks: + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_register): + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_register): + +2004-02-02 David Schleef + + code cleanup. Change bzero() to memset(). Remove duplicate ; at ends + of lines. + * ext/cdparanoia/gstcdparanoia.c: (cdparanoia_event): + * ext/flac/gstflactag.c: (gst_flac_tag_chain): + * ext/xvid/gstxviddec.c: (gst_xviddec_src_link): + * gst-libs/gst/play/play.c: (gst_play_get_sink_element): + * gst/ac3parse/gstac3parse.c: (gst_ac3parse_chain): + * gst/effectv/gstedge.c: (gst_edgetv_sinkconnect): + * gst/effectv/gstvertigo.c: (gst_vertigotv_sinkconnect): + * gst/intfloat/float22int.c: (gst_float2_2_int_getcaps), + (gst_float2_2_int_link): + * gst/mpeg2sub/gstmpeg2subt.c: (gst_mpeg2subt_chain_subtitle): + * gst/rtjpeg/RTjpeg.c: (RTjpeg_init_mcompress): + * gst/tcp/gsttcpsink.c: (gst_tcpsink_init_send): + * gst/tcp/gsttcpsrc.c: (gst_tcpsrc_init_receive): + * gst/udp/gstudpsink.c: (gst_udpsink_init_send): + * gst/udp/gstudpsrc.c: (gst_udpsrc_init_receive): + * sys/v4l/gstv4lelement.c: (gst_v4lelement_init): + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_set_capture): + * testsuite/gst-lint: Add tests for bzero and ;; + +2004-02-02 David Schleef + + * gst/debug/efence.c: Add fallback if MAP_ANONYMOUS isn't defined. + +2004-02-02 Thomas Vander Stichele + + * ext/aalib/gstaasink.c: (gst_aasink_open): + * ext/alsa/gstalsa.c: (gst_alsa_link), (gst_alsa_xrun_recovery): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_loop): + * ext/audiofile/gstafsink.c: (gst_afsink_open_file), + (gst_afsink_close_file): + * ext/audiofile/gstafsrc.c: (gst_afsrc_open_file), + (gst_afsrc_close_file): + * ext/divx/gstdivxdec.c: (gst_divxdec_setup), (gst_divxdec_chain): + * ext/divx/gstdivxenc.c: (gst_divxenc_setup), (gst_divxenc_chain): + * ext/dv/gstdvdec.c: (gst_dvdec_loop): + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_user_op), (dvdnavsrc_get): + * ext/esd/esdmon.c: (gst_esdmon_get): + * ext/esd/esdsink.c: (gst_esdsink_chain), (gst_esdsink_open_audio): + * ext/faac/gstfaac.c: (gst_faac_chain): + * ext/faad/gstfaad.c: (gst_faad_chain): + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain): + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop): + * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_loop): + * ext/flac/gstflacdec.c: (gst_flacdec_error_callback), + (gst_flacdec_loop): + * ext/flac/gstflacenc.c: (gst_flacenc_chain): + * ext/flac/gstflactag.c: (gst_flac_tag_chain): + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_chain): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_open_file), + (gst_gnomevfssink_close_file): + * ext/gnomevfs/gstgnomevfssrc.c: (audiocast_init), + (gst_gnomevfssrc_open_file): + * ext/ivorbis/vorbisfile.c: (gst_ivorbisfile_loop): + * ext/lame/gstlame.c: (gst_lame_sink_link), (gst_lame_chain): + * ext/lcs/gstcolorspace.c: (gst_colorspace_srcconnect_func): + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event), + (gst_id3_tag_do_typefind), (gst_id3_tag_chain): + * ext/mad/gstmad.c: (gst_mad_chain): + * ext/mikmod/gstmikmod.c: (gst_mikmod_loop): + * ext/mpeg2dec/gstmpeg2dec.c: + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/mplex/gstmplex.cc: + * ext/mplex/gstmplexibitstream.cc: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain), + (gst_ogg_demux_push): + * ext/raw1394/gstdv1394src.c: + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_lock), + (gst_sdlvideosink_initsdl), (gst_sdlvideosink_create): + * ext/sndfile/gstsf.c: (gst_sf_open_file), (gst_sf_close_file), + (gst_sf_loop): + * ext/speex/gstspeexenc.c: (gst_speexenc_chain): + * ext/swfdec/gstswfdec.c: (gst_swfdec_loop): + * ext/tarkin/gsttarkindec.c: (gst_tarkindec_chain): + * ext/tarkin/gsttarkinenc.c: (gst_tarkinenc_chain): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_chain): + * ext/vorbis/vorbisfile.c: (gst_vorbisfile_loop): + * ext/xvid/gstxviddec.c: (gst_xviddec_setup), (gst_xviddec_chain): + * ext/xvid/gstxvidenc.c: (gst_xvidenc_setup), (gst_xvidenc_chain): + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head), + (gst_riff_read_element_data), (gst_riff_read_seek), + (gst_riff_peek_list), (gst_riff_read_list), (gst_riff_read_header): + * gst/adder/gstadder.c: (gst_adder_loop): + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_segment), + (gst_asf_demux_process_stream), (gst_asf_demux_get_stream): + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_init), + (gst_avi_demux_add_stream), (gst_avi_demux_stream_header): + * gst/avi/gstavimux.c: (gst_avimux_stop_file): + * gst/flx/gstflxdec.c: (gst_flxdec_loop): + * gst/goom/gstgoom.c: (gst_goom_chain): + * gst/id3/gstid3types.c: (gst_id3types_loop): + * gst/intfloat/float22int.c: (gst_float2_2_int_chain): + * gst/intfloat/gstfloat2int.c: (gst_float2int_loop): + * gst/intfloat/gstint2float.c: (gst_int2float_chain_gint16): + * gst/matroska/ebml-read.c: (gst_ebml_read_element_id), + (gst_ebml_read_element_length), (gst_ebml_read_element_data), + (gst_ebml_read_seek), (gst_ebml_read_uint), (gst_ebml_read_sint), + (gst_ebml_read_float), (gst_ebml_read_header): + * gst/matroska/matroska-demux.c: (gst_matroska_demux_init_stream), + (gst_matroska_demux_parse_blockgroup): + * gst/monoscope/gstmonoscope.c: (gst_monoscope_chain): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_loop): + * gst/oneton/gstoneton.c: (gst_oneton_chain): + * gst/silence/gstsilence.c: (gst_silence_get): + * gst/sine/gstsinesrc.c: (gst_sinesrc_get): + * gst/smpte/gstsmpte.c: (gst_smpte_loop): + * gst/speed/gstspeed.c: (speed_loop): + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_chain): + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + * gst/volenv/gstvolenv.c: (gst_volenv_chain): + * gst/wavenc/gstwavenc.c: (gst_wavenc_chain): + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt), + (gst_wavparse_loop): + * sys/dxr3/dxr3audiosink.c: (dxr3audiosink_open), + (dxr3audiosink_set_mode_pcm), (dxr3audiosink_set_mode_ac3), + (dxr3audiosink_close): + * sys/dxr3/dxr3spusink.c: (dxr3spusink_open), (dxr3spusink_close): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_open), + (dxr3videosink_close), (dxr3videosink_write_data): + * sys/oss/gstosselement.c: (gst_osselement_open_audio): + * sys/oss/gstosssink.c: (gst_osssink_chain): + * sys/oss/gstosssrc.c: (gst_osssrc_get): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_chain): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_buffer_free): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_buffer_free): + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay), + (gst_v4l_set_window), (gst_v4l_enable_overlay): + * sys/v4l/v4l_calls.c: (gst_v4l_get_capabilities), (gst_v4l_open), + (gst_v4l_set_chan_norm), (gst_v4l_get_signal), + (gst_v4l_get_frequency), (gst_v4l_set_frequency), + (gst_v4l_get_picture), (gst_v4l_set_picture), (gst_v4l_get_audio), + (gst_v4l_set_audio): + * sys/v4l/v4l_calls.h: + * sys/v4l/v4lmjpegsink_calls.c: (gst_v4lmjpegsink_sync_thread), + (gst_v4lmjpegsink_queue_frame), (gst_v4lmjpegsink_set_playback), + (gst_v4lmjpegsink_playback_init), + (gst_v4lmjpegsink_playback_start): + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_queue_frame): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_queue_frame), + (gst_v4lsrc_sync_frame), (gst_v4lsrc_capture_init), + (gst_v4lsrc_requeue_frame), (gst_v4lsrc_try_palette): + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_get): + * sys/v4l2/v4l2-overlay_calls.c: (gst_v4l2_set_display), + (gst_v4l2_set_window), (gst_v4l2_enable_overlay): + * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), + (gst_v4l2_fill_lists), (gst_v4l2_open), (gst_v4l2_get_norm), + (gst_v4l2_set_norm), (gst_v4l2_get_input), (gst_v4l2_set_input), + (gst_v4l2_get_output), (gst_v4l2_set_output), + (gst_v4l2_get_frequency), (gst_v4l2_set_frequency), + (gst_v4l2_signal_strength), (gst_v4l2_get_attribute), + (gst_v4l2_set_attribute): + * sys/v4l2/v4l2_calls.h: + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list), + (gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame), + (gst_v4l2src_get_capture), (gst_v4l2src_set_capture), + (gst_v4l2src_capture_init), (gst_v4l2src_capture_start), + (gst_v4l2src_capture_stop): + * sys/vcd/vcdsrc.c: (vcdsrc_open_file): + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), + (gst_ximagesink_chain): + * sys/xvideo/xvideosink.c: (gst_xvideosink_buffer_new), + (gst_xvideosink_sinkconnect), (gst_xvideosink_chain), + (gst_xvideosink_xwindow_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_chain): + +2004-02-02 Thomas Vander Stichele + + * gst/volume/gstvolume.c: (gst_volume_set_volume), + (gst_volume_get_volume), (volume_class_init), (volume_init), + (volume_chain_int16), (volume_update_volume): + * gst/volume/gstvolume.h: + make code more readable by removing magic numbers + make mixer interface export 0-100 range + make it internally map to 0.0-1.0 range so users don't distort + output by putting the sliders at full volume + +2004-02-02 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_tick_callback), + (gst_play_state_change), (gst_play_seek_to_time): + block the tick callback for 0.5 secs after doing a seek + +2004-02-02 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_new): + check for GError + +2004-02-01 Julien MOUTTE + + * gst-libs/gst/play/play.c: (gst_play_seek_to_time), + (gst_play_new): Accepting NULL GError, blocking time tick while seeking. + * sys/ximage/ximagesink.c: (gst_ximagesink_sink_link), + (gst_ximagesink_chain), (gst_ximagesink_init): s/sinkconnect/sink_link + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sink_link), + (gst_xvimagesink_chain), (gst_xvimagesink_init): s/sinkconnect/sink_link + +2004-02-01 Thomas Vander Stichele + + * configure.ac: + * ext/vorbis/vorbisdec.c: (vorbis_dec_event): + check for a function added in vorbis 1.1 + +2004-01-31 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_change_state), (gst_alsa_start), + (gst_alsa_drain_audio), (gst_alsa_stop_audio): + really start/stop clock only on PLAYING <=> PAUSED + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + remove \n from debugging lines + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain): + make it work when seeking does not + * ext/vorbis/vorbisdec.c: (vorbis_dec_event): + reset on DISCONT + +2004-01-31 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_change_state), (gst_alsa_start): + start clock on PAUSED=>PLAYING, not later + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + extract correct time for different discont formats + (gst_alsa_sink_get_time): + don't segfault when no format is negotiated yet, just return 0 + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event), + (gst_ogg_demux_handle_event), (gst_ogg_demux_push), + (gst_ogg_pad_push): + handle flush and discont events correctly + * ext/vorbis/vorbisdec.c: (vorbis_dec_event), (vorbis_dec_chain): + handle discont events correctly + +2004-01-31 Thomas Vander Stichele + + * gst-libs/gst/play/play.c: (gst_play_error_quark), + (gst_play_error_create), (gst_play_error_plugin), + (gst_play_pipeline_setup), (gst_play_init), (gst_play_new): + * gst-libs/gst/play/play.h: + add error handling during creation + * examples/gstplay/player.c: (main): + use new gst_play_new + + +2004-01-31 Benjamin Otte + + * ext/theora/theoradec.c: (theora_dec_chain): + make comments work + * ext/vorbis/vorbisdec.c: (vorbis_dec_src_query), + (vorbis_dec_src_event), (vorbis_dec_chain): + add encoder tag, fix tag reading to be more error tolerant, change + BITRATE to NOMINAL_BITRATE, add debugging, don't unref events after + gst_pad_event_default. + * gst/tags/gstvorbistag.c: + (gst_tag_list_from_vorbiscomment_buffer): + undefine function specific define at end of function + +2004-01-31 Jeremy Simon + + * ext/flac/gstflac.c: (plugin_init): + * ext/flac/gstflacdec.c: (gst_flacdec_class_init): + * ext/flac/gstflacdec.h: + * ext/flac/gstflacenc.h: + Fix typos + +2004-01-30 David I. Lehn + + * examples/gstplay/player.c: s/gstplay.h/play.h/ + +2004-01-30 Thomas Vander Stichele + + * gst-libs/gst/play/Makefile.am: + * gst-libs/gst/play/gstplay.c: + * gst-libs/gst/play/gstplay.h: + * gst-libs/gst/play/play.c: + more surgery, operation complete + +2004-01-30 Thomas Vander Stichele + + * gst-libs/gst/play/play.old.c: + * gst-libs/gst/play/play.old.h: + after CVS surgery by moving, remove + * gst-libs/gst/play/playpipelines.c: + remove + + * gst/intfloat/float22int.c: (gst_float2_2_int_chain): + add negotiation error + +2004-01-30 Thomas Vander Stichele + + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_event), + (gst_ogg_demux_push): + add some seeking debug info + send a flush when seeking + +2004-01-30 Benjamin Otte + + * configure.ac: + use AC_C_INLINE + * configure.ac: + * ext/Makefile.am: + * ext/theora/Makefile.am: + * ext/theora/theoradec.c: + add theora video decoder. Does just do simple decoding for now and + has been tested against Theora cvs only. It only works when theora + is compiled with --enable-static. + * ext/vorbis/vorbisdec.c: (vorbis_dec_event): + always reset packetno on DISCONT + +2004-01-30 Ronald Bultje + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead): + Fix audio. + +2004-01-30 Ronald Bultje + + * gst/mpegaudioparse/gstmpegaudioparse.c: + (mp3_type_frame_length_from_header): + Fix header parsing - stolen from ffmpeg (thank you! :) ). + +2004-01-30 Ronald Bultje + + * ext/esd/esdsink.c: (gst_esdsink_init): + Since we have static pad template caps, we don't need to negotiate; + either the core errors out or we know the format. + +2004-01-30 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head), + (gst_riff_read_seek): + * gst/matroska/ebml-read.c: (gst_ebml_read_element_id), + (gst_ebml_read_seek): + Fix event handling. + +2004-01-30 Benjamin Otte + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps): + removee video/x-theora from vp3 decoder, it doesn't handle raw + theora streams + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_init): + fix bug with finalizing element that never went to PAUSED + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_src_query): + length and position queries were swapped + * ext/vorbis/vorbisdec.c: (gst_vorbis_dec_init), + (vorbis_dec_from_granulepos), (vorbis_dec_src_query), + (vorbis_dec_src_event): + implement querying time and bytes + +2004-01-30 Thomas Vander Stichele + + * just about every source file: + gst_element_error -> GST_ELEMENT_ERROR + +2004-01-29 Julien MOUTTE + + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_get): Fixing seeking + emiting FLUSH and even before DISCONT. + * gst-libs/gst/play/gstplay.c: (gst_play_seek_to_time): Fix seeking to + get the best instant seeking as possible yay! + +2004-01-29 Ronald Bultje + + * gst/mpeg1videoparse/gstmp1videoparse.c: + (gst_mp1videoparse_real_chain): + Committed wrong version last week... Grr... Didn't notice until now. + +2004-01-29 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_new): Emit the + have_xwindow_id signal in xwindow_create. + +2004-01-29 Benjamin Otte + + * ext/ogg/gstoggdemux.c: + lots of changes - mainly support for chained bitstreams, seeking, + querying and bugfixes of course + * ext/vorbis/Makefile.am: + * ext/vorbis/vorbisdec.c: + * ext/vorbis/vorbisdec.h: + add vorbisdec raw vorbis decoder + * ext/vorbis/vorbis.c: (plugin_init): + register vorbisdec as PRIMARY, vorbisfile as SECONDARY + * gst/intfloat/Makefile.am: + * gst/intfloat/float22int.c: + * gst/intfloat/float22int.h: + * gst/intfloat/gstintfloatconvert.c: (plugin_init): + add float2intnew plugin. It converts multichannel interleaved float to + multichannel interleaved int. The name should probably be changed. + * gst/typefind/gsttypefindfunctions.c: (theora_type_find), + (plugin_init): + add typefinding for raw theora video so oggdemux can detect it. + +2004-01-28 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_seek_to_time): seek on video + sink element first. + * gst/videoscale/gstvideoscale.c: + (gst_videoscale_handle_src_event): Fixing src event handler. + +2004-01-28 Ronald Bultje + + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_class_init), (gst_v4lsrc_init), + (gst_v4lsrc_open), (gst_v4lsrc_close), + (gst_v4lsrc_palette_to_caps), (gst_v4lsrc_srcconnect), + (gst_v4lsrc_getcaps), (gst_v4lsrc_set_clock): + * sys/v4l/gstv4lsrc.h: + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_capture_start), + (gst_v4lsrc_grab_frame), (gst_v4lsrc_capture_stop): + Implement resizing... Hack. But that's why v4l is b0rked... + +2004-01-28 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_check_xshm_calls), + (gst_ximagesink_ximage_new), (gst_ximagesink_ximage_destroy), + (gst_ximagesink_ximage_put), (gst_ximagesink_xwindow_new), + (gst_ximagesink_xwindow_destroy): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_new), (gst_xvimagesink_xvimage_destroy), + (gst_xvimagesink_xwindow_new), (gst_xvimagesink_xwindow_destroy), + (gst_xvimagesink_xwindow_resize), (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_xcontext_get): Removing some useless debugs messages, + correctly cleaning the image created to check xshm calls on succes, + added a lot of XSync calls in X11 functions, and fixed a segfault when + no image format was defined before negotiation happened. + +2004-01-28 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_query_func): + use gst_element_get_time to get correct time + +2004-01-28 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xerror), + (gst_ximagesink_check_xshm_calls), (gst_ximagesink_ximage_destroy), + (gst_ximagesink_xcontext_get), (gst_ximagesink_class_init): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xerror), + (gst_xvimagesink_check_xshm_calls), + (gst_xvimagesink_xvimage_destroy), (gst_xvimagesink_xcontext_get): Our + X plugins are now able to detect that XShm calls will fail even if the + server claims that it has XShm support (remote displays most of the + time). We then log the error as a GST_DEBUG and set use_shm to FALSE + so that we use non XShm functions. This feature is almost useless for + xvimagesink as Xv is not supported on remote displays anyway, but + it might happen than even on the local display XShm calls fail. + +2004-01-27 David Schleef + + * ext/esd/esdsink.c: (gst_esdsink_class_init), (gst_esdsink_init), + (gst_esdsink_link), (gst_esdsink_get_time), (gst_esdsink_chain), + (gst_esdsink_change_state): Fix sync issues in esdsink. Also + changed esdsink to only use 44100,16,2, since esd sucks at rate + conversion and esdsink has had difficulty negotiating. + +2004-01-27 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_tick_callback), + (gst_play_seek_to_time): Fixing the way to get current position. + +2004-01-27 Benjamin Otte + + * sys/oss/gstosssink.c: (gst_osssink_sink_query): + use gst_element_get_time to get correct time + +2004-01-27 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_set_location): The easiest + fix ever... Inverting 2 lines of code make spider autoplug correctly + tagged mp3 ! + +2004-01-27 David Schleef + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + Use gst_pad_try_set_caps_nonfixed(). + +2004-01-27 David Schleef + + * gst/ac3parse/gstac3parse.c: update to checklist 5 + * gst/adder/gstadder.c: rewrite negotiation. update to checklist 5 + * gst/audioconvert/gstaudioconvert.c: update to checklist 5 + * gst/audioscale/gstaudioscale.c: same + * gst/auparse/gstauparse.c: same + * gst/avi/gstavidemux.c: same + +2004-01-27 Benjamin Otte + + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_handle_sink_event): + stop processing after EOS + +2004-01-27 Benjamin Otte + + * gst/asfdemux/asfheaders.h: + * gst/asfdemux/gstasfdemux.c: + * gst/asfdemux/gstasfmux.c: (gst_asfmux_put_guid), + (gst_asfmux_put_string), (gst_asfmux_put_wav_header), + (gst_asfmux_put_vid_header), (gst_asfmux_put_bmp_header): + lot's of fixes to make data extraction simpler and get the code + architecture and compiler independant. Add debugging category + * gst/goom/gstgoom.c: (gst_goom_change_state): + reset channel count on PAUSED=>READY, not READY=>PAUSED + +2004-01-26 Colin Walters + + * ext/gnomevfs/gstgnomevfssrc.c (gst_gnomevfssrc_get): Remove ugly + code to pull a bigger buffer in iradio mode. This as a side effect + makes typefinding work. + +2004-01-26 Jeremy Simon + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_caps_to_extradata): + Fix SVQ3 decoding on PPC + +2004-01-26 Julien MOUTTE + + * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain): Dunno how + that one managed to stay there... Fixed. + +2004-01-26 Jeremy Simon + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), + (gst_ffmpeg_caps_to_extradata), (gst_ffmpeg_caps_to_pixfmt): + * gst/qtdemux/qtdemux.c: (plugin_init), (qtdemux_parse_trak), + (qtdemux_video_caps): + * gst/qtdemux/qtdemux.h: + Add SVQ3 specific flags to qtdemux and ffmpeg + +2004-01-26 Benjamin Otte + + * gst-libs/gst/audio/audio.h: + remove buffer-frames from audio caps + * gst/audioconvert/gstaudioconvert.c: + fix plugin to really work. + +2004-01-25 Ronald Bultje + + * gst-libs/gst/mixer/mixer.c: + * gst-libs/gst/propertyprobe/propertyprobe.c: + * gst-libs/gst/tuner/tuner.c: (gst_tuner_find_norm_by_name), + (gst_tuner_find_channel_by_name): + * gst-libs/gst/tuner/tuner.h: + Add gtk-doc style comments. Also fix a function name. + +2004-01-25 Ronald Bultje + + * ext/divx/gstdivxdec.c: (gst_divxdec_init), + (gst_divxdec_negotiate): + Fix for new capsnego - also fixes gst-player with divxdec. + +2004-01-25 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), + (gst_play_identity_handoff), (gst_play_set_location), + (gst_play_set_visualization), (gst_play_connect_visualization): Another + try in visualization implementation. Still have an issue with switch + blocking when pulling from video_queue and only audio comes out of + spider. + * gst/switch/gstswitch.c: (gst_switch_release_pad), + (gst_switch_poll_sinkpads), (gst_switch_class_init): Implementing pad + release method. And check if the pad is usable before pulling. + +2004-01-25 Ronald Bultje + + * gst/videofilter/gstvideobalance.c: (gst_videobalance_dispose), + (gst_videobalance_init), + (gst_videobalance_colorbalance_list_channels), + (gst_videobalance_colorbalance_set_value), + (gst_videobalance_colorbalance_get_value), + (gst_videobalance_update_properties), + (gst_videobalance_update_tables_planar411), + (gst_videobalance_planar411): + * gst/videofilter/gstvideobalance.h: + Implement lookup-tables. +/- 10x faster. + +2004-01-25 Ronald Bultje + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_avih), + (gst_avi_demux_stream_odml), (gst_avi_demux_stream_index): + The index reading was broken. The rest worked fine, but the whole + goal of my rewrite was to make avidemux readable, and this was + not at all readable. Please use typed variables. + +2004-01-25 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_info): + Additional pad usability check. + * gst/mpeg1videoparse/gstmp1videoparse.c: (gst_mp1videoparse_init), + (mp1videoparse_find_next_gop), (gst_mp1videoparse_time_code), + (gst_mp1videoparse_real_chain): + Fix MPEG video stream parsing. The original plugin had several + issues, including not timestamping streams where the source was + not timestamped (this happens with PTS values in mpeg system + streams, but MPEG video is also a valid stream on its own so + that needs timestamps too). We use the display time code for that + for now. Also, if one incoming buffer contains multiple valid + frames, we push them all on correctly now, including proper EOS + handling. Lastly, several potential segfaults were fixed, and we + properly sync on new sequence/gop headers to include them in next, + not previous frames (since they're header for the next frame, not + the previous). Also see #119206. + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_chain), + (bpf_from_header): + Move caps setting so we only do it after finding several valid + MPEG-1 fraes sequentially, not right after the first one (which + might be coincidental). + * gst/typefind/gsttypefindfunctions.c: (mpeg1_sys_type_find), + (mpeg_video_type_find), (mpeg_video_stream_type_find), + (plugin_init): + Add unsynced MPEG video stream typefinding, and change some + probability values so we detect streams rightly. The idea is as + follows: I can have an unsynced system stream which contains + video. In the current code, I would randomly get a type for either + system or video stream type found, because the probabilities are + being calculated rather randomly. I now use fixed values, so we + always prefer system stream if that was found (and that is how it + should be). If no system stream was found, we can still identity the stream as video-only. + +2004-01-23 Benjamin Otte + + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_avih), + (gst_avi_demux_stream_odml), (gst_avi_demux_stream_index): + don't write to buffer. Extract data without the need of + __attribute__ ((packed)) + +2004-01-23 Ronald Bultje + + * gst/typefind/gsttypefindfunctions.c: (mpeg1_parse_header), + (mpeg1_sys_type_find): + Fix MPEG-1 stream typefinding. + +2004-01-23 Ronald Bultje + + * gst/typefind/gsttypefindfunctions.c: (mpeg2_sys_type_find): + Fix typefinding for MPEG-1 system streams, similar to MPEG-2. + +2004-01-23 Thomas Vander Stichele + + * ext/esd/esdsink.c: (gst_esdsink_open_audio): + * ext/esd/gstesd.c: (plugin_init): + private debugging, better error reporting + +2004-01-23 Ronald Bultje + + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_class_init), + (gst_riff_read_init), (gst_riff_read_change_state): + * gst-libs/gst/riff/riff-read.h: + Remove stuff fromold metadata system. + +2004-01-23 Ronald Bultje + + * ext/ogg/gstoggdemux.c: + Fix wrong file comment. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_info): + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_header): + Add metadata reading properly. + +2004-01-23 Thomas Vander Stichele + + * ext/Makefile.am: + Fix nas DIST_SUBDIRS + Uraeus: + Fix bug where make distcheck doesn't get run on adding stuff to + the build. + +2004-01-23 Ronald Bultje + + * ext/divx/gstdivxdec.c: (gst_divxdec_init), (gst_divxdec_setup): + * ext/divx/gstdivxdec.h: + Fix divx3 ("msmpeg4") playback using divxdec. + +2004-01-23 Benjamin Otte + + * gst/typefind/gsttypefindfunctions.c: + (mp3_type_frame_length_from_header): fix bug in length computation + (mp3_type_find): improve debugging output + +2004-01-23 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), + (gst_play_set_location), (gst_play_seek_to_time), + (gst_play_set_audio_sink), (gst_play_set_visualization), + (gst_play_connect_visualization), (gst_play_get_sink_element): Reworked + the pipeline from scratch. Visualization is back and switch went out as + i realized it was not possible to use the way i wanted. + * sys/ximage/ximagesink.c: (gst_ximagesink_imagepool_clear), + (gst_ximagesink_change_state), (gst_ximagesink_dispose): Move xcontext + clearing in state change from READY to NULL. So that one can clean the + X ressources keeping the element. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_imagepool_clear), (gst_xvimagesink_change_state), + (gst_xvimagesink_colorbalance_set_value), + (gst_xvimagesink_colorbalance_get_value), + (gst_xvimagesink_set_property), (gst_xvimagesink_dispose), + (gst_xvimagesink_init): Same xcontext cleaning than ximagesink in state + change from READY to NULL and fixed some stupid bugs in colorbalance + get/set values. Also added the following feature : when nobody tries to + set some values to the colorbalance levels before the xcontext is + grabbed, then when creating channels list from Xv attributes we set the + internal values to the Xv defaults. This way we handle buggy Xv drivers + that set default hue values far from the middle of the range (Thanks + to Jon Trowbridge for pointing that issue). + * sys/xvimage/xvimagesink.h: Adding a cb_changed boolean to know if + colorbalance levels have been set before xcontext is grabbed. + +2004-01-22 Ronald Bultje + + * sys/oss/gstosselement.c: (gst_osselement_class_probe_devices): + Fix the ossmixer case where we shouldn't open /dev/dsp* because + it might block operations (which is bad for a mixer). + +2004-01-22 Thomas Vander Stichele + + * gst-libs/gst/media-info/media-info-priv.c: (have_type_callback), + (deep_notify_callback), (gmi_set_decoder), (gmi_clear_decoder), + (gmip_find_type_pre): + * gst-libs/gst/media-info/media-info-priv.h: + * gst-libs/gst/media-info/media-info.c: + (gst_media_info_instance_init), (gst_media_info_read_idler): + add fakesink to get caps on decoder src pad again + fix callback prototype to match new have_type signal signature + +2004-01-22 Thomas Vander Stichele + + * gst/adder/gstadder.c: (gst_adder_link): + fix non-compile and cut-n-paste code + +2004-01-21 David Schleef + + * ext/swfdec/gstswfdec.c: (gst_swfdec_video_getcaps), + (gst_swfdec_video_link), (copy_image), (gst_swfdec_loop), + (gst_swfdec_init), (gst_swfdec_change_state): + * ext/swfdec/gstswfdec.h: + Fix negotiation. + * gst/adder/gstadder.c: (gst_adder_link), (gst_adder_init), + (gst_adder_request_new_pad): Fix negotiation. + * gst/goom/gstgoom.c: (gst_goom_init), (gst_goom_src_fixate): + Add a fixate function. + * gst/intfloat/gstfloat2int.c: + * gst/intfloat/gstfloat2int.h: + * gst/intfloat/gstint2float.c: + * gst/intfloat/gstint2float.h: + Completely rewrite the negotiation. Doesn't quite work yet, + due to some buffer-frames problem. + +2004-01-21 Thomas Vander Stichele + + * ext/gnomevfs/gstgnomevfssrc.c: + * sys/v4l2/v4l2_calls.h: + fix includes for distcheck + +2004-01-21 Christian Schaller + + * ext/nas/ + Add libnas (network audio system) plugin, patch from Arwed von Merkatz + based on earlier patch from Laurent Vivier + +2004-01-20 Jeremy Simon + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_caps_to_extradata): + Fix wma caps property + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_audio_caps): + Fix typo (flags1 and flags2) + +2004-01-20 Thomas Vander Stichele + + * gst-libs/gst/media-info/media-info-priv.c: + (deep_notify_callback), (gmi_seek_to_track), (gmi_get_decoder), + (gmip_find_type_pre), (gmip_find_type), (gmip_find_stream_post), + (gmip_find_stream), (gmip_find_track_metadata), + (gmip_find_track_streaminfo_post), (gmip_find_track_streaminfo), + (gmip_find_track_format): + * gst-libs/gst/media-info/media-info-priv.h: + * gst-libs/gst/media-info/media-info-test.c: (main): + * gst-libs/gst/media-info/media-info.c: (gst_media_info_init), + (gst_media_info_read_idler), (gst_media_info_read): + * gst-libs/gst/media-info/media-info.h: + register debugging category and use it for debugging + +2004-01-20 Thomas Vander Stichele + + * ext/vorbis/vorbisfile.c: (gst_vorbisfile_update_streaminfo), + (gst_vorbisfile_new_link): + signal streaminfo through tags + +2004-01-20 Ronald Bultje + + * ext/mplex/gstmplex.cc: + * ext/mplex/gstmplexibitstream.cc: + g++ doesn't like NULL in our i18n/error macros, should be + either (NULL) or (""). + +2004-01-20 Ronald Bultje + + * sys/dxr3/dxr3audiosink.c: + * sys/dxr3/dxr3init.c: + * sys/dxr3/dxr3spusink.c: (dxr3spusink_close): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_close): + Fix more error error error errors (missing includes here). + +2004-01-20 Ronald Bultje + + * ext/mpeg2enc/gstmpeg2encpicturereader.cc: + fix thomas' error errors. + +2004-01-20 Thomas Vander Stichele + + * ext/mpeg2enc/gstmpeg2enc.cc: + fix error errors. + +2004-01-20 Ronald Bultje + + * ext/divx/gstdivxdec.c: (gst_divxdec_setup), (gst_divxdec_chain): + * ext/divx/gstdivxenc.c: (gst_divxenc_setup), (gst_divxenc_chain): + Fix for new error system. + +2004-01-20 Thomas Vander Stichele + + * ext/divx/gstdivxenc.c: (gst_divxenc_setup), (gst_divxenc_chain): + fix for new error reporting + +2004-01-20 David Schleef + + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents), + (gst_ximagesink_xcontext_get), (gst_ximagesink_getcaps), + (gst_ximagesink_set_xwindow_id): Change to using a framerate + of [1,100] instead of [0,MAX], since 0 isn't handled correctly, + and neither is 100+, most likely. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support), + (gst_xvimagesink_getcaps): same + +2004-01-19 Benjamin Otte + + * configure.ac: + Up version requirement to 2.0.3 (not yet released) to avoid symbol + clashes with ffmpeg. + +2004-01-20 Julien MOUTTE + + * gst/switch/gstswitch.c: (gst_switch_request_new_pad), + (gst_switch_init): Fixed switch element : proxying link and setting + caps from src to sink on request. + +2004-01-19 Thomas Vander Stichele + + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_overlay): + * sys/v4l2/v4l2-overlay_calls.c: (gst_v4l2_set_display), + (gst_v4l2_set_window), (gst_v4l2_enable_overlay): + fix element_error + +2004-01-19 Thomas Vander Stichele + + * sys/v4l/v4l_calls.h: + * sys/v4l2/v4l2_calls.h: + element_error fixes + +2004-01-19 Thomas Vander Stichele + + * gst-libs/gst/gst-i18n-plugin.h: + add locale.h + remove config.h inclusion + +2004-01-19 Thomas Vander Stichele + + * autogen.sh: + adding autopoint invocation + * Makefile.am: + * configure.ac: + * gst-libs/gst/gettext.h: + adding gettext bits + * ext/audiofile/gstafsink.c: (gst_afsink_plugin_init): + * ext/audiofile/gstafsrc.c: (gst_afsrc_plugin_init): + * ext/gnomevfs/gstgnomevfs.c: (plugin_init): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_open_file), + (gst_gnomevfssink_close_file): + * ext/gnomevfs/gstgnomevfssrc.c: (gst_gnomevfssrc_open_file): + * ext/sndfile/gstsf.c: (gst_sf_loop), (plugin_init): + * gst-libs/gst/gst-i18n-plugin.h: + * gst/avi/gstavi.c: (plugin_init): + * sys/dxr3/dxr3init.c: (plugin_init): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_write_data): + * sys/oss/gstossaudio.c: (plugin_init): + * sys/oss/gstosselement.c: (gst_osselement_open_audio): + * sys/v4l/gstv4l.c: (plugin_init): + * sys/v4l/v4l_calls.c: (gst_v4l_open): + * sys/v4l2/gstv4l2.c: (plugin_init): + * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), + (gst_v4l2_fill_lists), (gst_v4l2_get_norm), (gst_v4l2_set_norm), + (gst_v4l2_get_input), (gst_v4l2_set_input), (gst_v4l2_get_output), + (gst_v4l2_set_output), (gst_v4l2_get_frequency), + (gst_v4l2_set_frequency), (gst_v4l2_signal_strength), + (gst_v4l2_get_attribute), (gst_v4l2_set_attribute): + make sure locale and translation domain are set + fix translated strings + * po/.cvsignore: + * po/LINGUAS: + * po/Makevars: + * po/POTFILES.in: + * po/nl.po: + put translation files into place + * sys/xvideo/imagetest.c: (main): + * ext/dv/demo-play.c: (main): + fix unnecessary translations + +2004-01-19 Thomas Vander Stichele + + * ext/sndfile/gstsf.c: + * gst/avi/gstavimux.c: + * ext/audiofile/gstafsink.c: + * ext/audiofile/gstafsrc.c: + * ext/gnomevfs/gstgnomevfssink.c: + * ext/gnomevfs/gstgnomevfssrc.c: + * sys/oss/gstosselement.c: + * sys/v4l/v4l_calls.h: + fix i18n include + +2004-01-19 Thomas Vander Stichele + + * sys/v4l2/v4l2_calls.c: (gst_v4l2_get_capabilities), + (gst_v4l2_fill_lists), (gst_v4l2_open), (gst_v4l2_get_norm), + (gst_v4l2_set_norm), (gst_v4l2_get_input), (gst_v4l2_set_input), + (gst_v4l2_get_output), (gst_v4l2_set_output), + (gst_v4l2_get_frequency), (gst_v4l2_set_frequency), + (gst_v4l2_signal_strength), (gst_v4l2_get_attribute), + (gst_v4l2_set_attribute): + update to new error handling + +2004-01-19 Thomas Vander Stichele + + * ext/sidplay/gstsiddec.cc: + * gst/modplug/gstmodplug.cc: + parenthese NULL because C++ seems angry about it + +2004-01-19 Thomas Vander Stichele + + * gst-libs/gst/gst-i18n-plugin.h: + add skeleton i18n stuff, but needs to be further implemented + +2004-01-18 Thomas Vander Stichele + + * examples/gstplay/player.c: (main): + * ext/aalib/gstaasink.c: (gst_aasink_open): + * ext/alsa/gstalsa.c: (gst_alsa_link), (gst_alsa_xrun_recovery): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_loop): + * ext/alsa/gstalsasrc.c: (gst_alsa_src_loop): + * ext/audiofile/gstafsink.c: (gst_afsink_open_file), + (gst_afsink_close_file): + * ext/audiofile/gstafsrc.c: (gst_afsrc_open_file), + (gst_afsrc_close_file): + * ext/divx/gstdivxdec.c: (gst_divxdec_setup), (gst_divxdec_chain): + * ext/dv/gstdvdec.c: (gst_dvdec_loop): + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_user_op), (dvdnavsrc_get): + * ext/esd/esdmon.c: (gst_esdmon_get): + * ext/esd/esdsink.c: (gst_esdsink_chain): + * ext/faac/gstfaac.c: (gst_faac_chain): + * ext/faad/gstfaad.c: (gst_faad_chain): + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain): + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop): + * ext/ffmpeg/gstffmpegmux.c: (gst_ffmpegmux_loop): + * ext/flac/gstflacdec.c: (gst_flacdec_error_callback), + (gst_flacdec_loop): + * ext/flac/gstflacenc.c: (gst_flacenc_chain): + * ext/flac/gstflactag.c: (gst_flac_tag_chain): + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_chain): + * ext/gnomevfs/gstgnomevfssink.c: (gst_gnomevfssink_open_file), + (gst_gnomevfssink_close_file): + * ext/gnomevfs/gstgnomevfssrc.c: (audiocast_init), + (gst_gnomevfssrc_open_file): + * ext/ivorbis/vorbisfile.c: (gst_ivorbisfile_loop): + * ext/lame/gstlame.c: (gst_lame_sink_link), (gst_lame_chain): + * ext/lcs/gstcolorspace.c: (gst_colorspace_srcconnect_func): + * ext/mad/gstid3tag.c: (gst_id3_tag_handle_event), + (gst_id3_tag_do_typefind), (gst_id3_tag_chain): + * ext/mad/gstmad.c: (gst_mad_chain): + * ext/mikmod/gstmikmod.c: (gst_mikmod_loop): + * ext/mpeg2dec/gstmpeg2dec.c: + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/mpeg2enc/gstmpeg2encpicturereader.cc: + * ext/mplex/gstmplex.cc: + * ext/mplex/gstmplexibitstream.cc: + * ext/ogg/gstoggdemux.c: (gst_ogg_demux_chain), + (gst_ogg_demux_push), (gst_ogg_pad_push): + * ext/raw1394/gstdv1394src.c: + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_lock), + (gst_sdlvideosink_initsdl), (gst_sdlvideosink_create): + * ext/sidplay/gstsiddec.cc: + * ext/sndfile/gstsf.c: (gst_sf_open_file), (gst_sf_close_file), + (gst_sf_loop): + * ext/speex/gstspeexenc.c: (gst_speexenc_chain): + * ext/tarkin/gsttarkindec.c: (gst_tarkindec_chain): + * ext/tarkin/gsttarkinenc.c: (gst_tarkinenc_chain): + * ext/vorbis/vorbisenc.c: (gst_vorbisenc_chain): + * ext/vorbis/vorbisfile.c: (gst_vorbisfile_loop): + * ext/xvid/gstxviddec.c: (gst_xviddec_setup), (gst_xviddec_chain): + * ext/xvid/gstxvidenc.c: (gst_xvidenc_setup), (gst_xvidenc_chain): + * gst-libs/gst/Makefile.am: + * gst-libs/gst/riff/riff-read.c: (gst_riff_peek_head), + (gst_riff_read_element_data), (gst_riff_read_seek), + (gst_riff_peek_list), (gst_riff_read_list), (gst_riff_read_header): + * gst/adder/gstadder.c: (gst_adder_parse_caps), (gst_adder_loop): + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_process_segment), + (gst_asf_demux_process_stream), (gst_asf_demux_get_stream): + * gst/avi/gstavidemux.c: (gst_avi_demux_stream_init), + (gst_avi_demux_add_stream), (gst_avi_demux_stream_header): + * gst/avi/gstavimux.c: (gst_avimux_stop_file): + * gst/flx/gstflxdec.c: (gst_flxdec_loop): + * gst/goom/gstgoom.c: (gst_goom_chain): + * gst/id3/gstid3types.c: (gst_id3types_loop): + * gst/intfloat/gstfloat2int.c: (gst_float2int_loop): + * gst/intfloat/gstint2float.c: (gst_int2float_chain_gint16): + * gst/matroska/ebml-read.c: (gst_ebml_read_element_id), + (gst_ebml_read_element_length), (gst_ebml_read_element_data), + (gst_ebml_read_seek), (gst_ebml_read_uint), (gst_ebml_read_sint), + (gst_ebml_read_float), (gst_ebml_read_header): + * gst/matroska/matroska-demux.c: (gst_matroska_demux_init_stream), + (gst_matroska_demux_parse_blockgroup): + * gst/modplug/gstmodplug.cc: + * gst/monoscope/gstmonoscope.c: (gst_monoscope_chain): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_loop): + * gst/oneton/gstoneton.c: (gst_oneton_chain): + * gst/silence/gstsilence.c: (gst_silence_get): + * gst/sine/gstsinesrc.c: (gst_sinesrc_get): + * gst/smpte/gstsmpte.c: (gst_smpte_loop): + * gst/speed/gstspeed.c: (speed_loop): + * gst/tags/gstvorbistag.c: (gst_vorbis_tag_chain): + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + * gst/volenv/gstvolenv.c: (gst_volenv_chain): + * gst/wavenc/gstwavenc.c: (gst_wavenc_chain): + * gst/wavparse/gstwavparse.c: (gst_wavparse_parse_fmt), + (gst_wavparse_loop): + * sys/dxr3/dxr3audiosink.c: (dxr3audiosink_open), + (dxr3audiosink_set_mode_pcm), (dxr3audiosink_set_mode_ac3), + (dxr3audiosink_close): + * sys/dxr3/dxr3spusink.c: (dxr3spusink_open), (dxr3spusink_close): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_open), + (dxr3videosink_close), (dxr3videosink_write_data): + * sys/oss/gstosselement.c: (gst_osselement_open_audio): + * sys/oss/gstosselement.h: + * sys/oss/gstosssink.c: (gst_osssink_get_type), (gst_osssink_init), + (gst_osssink_chain): + * sys/oss/gstosssrc.c: (gst_osssrc_get): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_chain): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_buffer_free): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_buffer_free): + * sys/v4l/v4l-overlay_calls.c: (gst_v4l_set_window), + (gst_v4l_enable_overlay): + * sys/v4l/v4l_calls.c: (gst_v4l_get_capabilities), (gst_v4l_open), + (gst_v4l_set_chan_norm), (gst_v4l_get_signal), + (gst_v4l_get_frequency), (gst_v4l_set_frequency), + (gst_v4l_get_picture), (gst_v4l_set_picture), (gst_v4l_get_audio), + (gst_v4l_set_audio): + * sys/v4l/v4l_calls.h: + * sys/v4l/v4lmjpegsink_calls.c: (gst_v4lmjpegsink_sync_thread), + (gst_v4lmjpegsink_queue_frame), (gst_v4lmjpegsink_set_playback), + (gst_v4lmjpegsink_playback_init), + (gst_v4lmjpegsink_playback_start): + * sys/v4l/v4lmjpegsrc_calls.c: (gst_v4lmjpegsrc_queue_frame), + (gst_v4lmjpegsrc_sync_next_frame), (gst_v4lmjpegsrc_set_capture), + (gst_v4lmjpegsrc_set_capture_m), (gst_v4lmjpegsrc_capture_init), + (gst_v4lmjpegsrc_requeue_frame): + * sys/v4l/v4lsrc_calls.c: (gst_v4lsrc_queue_frame), + (gst_v4lsrc_sync_frame), (gst_v4lsrc_capture_init), + (gst_v4lsrc_requeue_frame), (gst_v4lsrc_try_palette): + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_get): + * sys/v4l2/v4l2src_calls.c: (gst_v4l2src_fill_format_list), + (gst_v4l2src_queue_frame), (gst_v4l2src_grab_frame), + (gst_v4l2src_get_capture), (gst_v4l2src_set_capture), + (gst_v4l2src_capture_init), (gst_v4l2src_capture_start), + (gst_v4l2src_capture_stop): + * sys/vcd/vcdsrc.c: (vcdsrc_open_file): + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), + (gst_ximagesink_chain): + * sys/xvideo/xvideosink.c: (gst_xvideosink_buffer_new), + (gst_xvideosink_sinkconnect), (gst_xvideosink_chain), + (gst_xvideosink_xwindow_new): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_chain): + use new error signal, function and categories + +2004-01-18 Jeremy Simon + + * configure.ac: + * ext/Makefile.am: + * ext/musicbrainz/gsttrm.c: + * ext/musicbrainz/gsttrm.h: + * ext/musicbrainz/Makefile.am: + Add a trm plugin + +2004-01-18 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_set_property), + (gst_ximagesink_get_property), (gst_ximagesink_class_init): Adding + synchronous property for debugging. + * sys/ximage/ximagesink.h: Adding the synchronous boolean flag. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_set_property): Moving a pointer declaration to a + smaller block, fixing indent. + +2004-01-16 David Schleef + + * gst/videofilter/gstvideobalance.c: Fix regression; changing a + property affects the video stream. + * sys/xvimage/xvimagesink.c: + * sys/xvimage/xvimagesink.h: + Add synchronous property for debugging. Should probably be + disabled in non-CVS builds. Make sure that the Xv attribute + exists before we set it (crash!). Fix a silly float bug that + caused colorbalance to just not work. + +2004-01-17 Christian Schaller + + * tools/gst-launch-ext.in - update for new plugins + +2004-01-16 David Schleef + + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_connect): Fix use of + already-freed caps. + +2994-01-16 Christian Schaller + + * Update spec for new colorspace plugin and libcaca plugin + * Fix compilation of libcaca plugin (clock -> id) + +2004-01-16 Julien MOUTTE + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_update_colorbalance), + (gst_xvimagesink_xcontext_get), (gst_xvimagesink_change_state), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_colorbalance_set_value), + (gst_xvimagesink_colorbalance_get_value), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_init), (gst_xvimagesink_class_init): Implementing + correct colorbalance properties. They can now be set when the element + is still in NULL state. The values will be committed to the Xv Port + when xcontext is initialized. + * sys/xvimage/xvimagesink.h: Added hue, saturation, contrast, + brightness int values in the GstXvImagesink structure. + +2004-01-16 Ronald Bultje + + * gst-libs/gst/Makefile.am: + restructure so having local patches works easier. + +2004-01-16 Ronald Bultje + + * ext/mpeg2enc/Makefile.am: + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/mpeg2enc/gstmpeg2encpicturereader.cc: + Bugfix with respect to EOS handling. + +2004-01-16 Ronald Bultje + + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_connect): + Link with right caps (else, it segfaults). + * ext/mplex/gstmplexjob.cc: + Fix for slight API change in 1.6.1.93 release of mjpegtools. + +2004-01-15 David Schleef + + * gst-libs/gst/audio/Makefile.am: + Add gstaudiofiltertemplate.c and building of gstaudiofilterexample.c + from the template. + * gst-libs/gst/audio/gstaudiofilter.c: + * gst-libs/gst/audio/gstaudiofilter.h: + Add bytes_per_sample and size and n_samples calculation. + * gst-libs/gst/audio/gstaudiofilterexample.c: + Remove, now autogenerated. + * gst-libs/gst/audio/gstaudiofiltertemplate.c: + Moved from gstaudiofilterexample, object name changed, code added + so that it actually works. + * gst-libs/gst/audio/make_filter: + Script to build an audiofilter subclass from the template. + * gst/colorspace/Makefile.am: + * gst/colorspace/yuv2yuv.c: + Remove file, since it's GPL, and we don't use it. + +2004-01-15 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_chain): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain): Making both of + them use the buffer free function to test how the buffer was allocated. + +2004-01-15 David Schleef + + * ext/esd/esdsink.c: (gst_esdsink_class_init): Remove property + that handles osssink fallback. + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_init), + (gst_audio_convert_getcaps): + * gst/qtdemux/qtdemux.c: (qtdemux_audio_caps): + Add audio/x-qdm2 for QDM2 audio. + * gst/sine/gstsinesrc.c: (gst_sinesrc_get): + * gst/sine/gstsinesrc.h: Add example of how to implement tags. + * gst/videoscale/gstvideoscale.c: (gst_videoscale_getcaps): + Decrease minimum size to 16x16. + * gst/wavparse/gstwavparse.c: + Convert disabled pad template caps to new caps. + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_chain): Throw element error when display cannot + be opened. Increase minimum framerate to 1.0. Check the data + free function on a buffer to make sure it is the type we expect + before manipulating it. + +2004-01-15 Julien MOUTTE + + * gst/videofilter/gstvideobalance.c: (gst_videobalance_init), + (gst_videobalance_colorbalance_set_value): Implement passthru if + settings are in the middle. + * tools/gst-launch-ext.in: Stop using xvideosink, use ximagesink. + +2004-01-15 Ronald Bultje + + * gst/videofilter/Makefile.am: + * gst/volume/Makefile.am: + Since we use videofilter symbols, link to it. + +2004-01-15 Julien MOUTTE + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_interface_init): Setting + mixer interface type to HARDWARE. + * gst-libs/gst/mixer/mixer.c: (gst_mixer_class_init): Adding a default + type to SOFTWARE. + * gst-libs/gst/mixer/mixer.h: Adding mixer interface type and macro. + * gst-libs/gst/mixer/mixertrack.h: Adding mixertrack flag SOFTWARE. + * gst/volume/gstvolume.c: (gst_volume_interface_supported), + (gst_volume_interface_init), (gst_volume_list_tracks), + (gst_volume_set_volume), (gst_volume_get_volume), + (gst_volume_set_mute), (gst_volume_mixer_init), + (gst_volume_dispose), (gst_volume_get_type), (volume_class_init), + (volume_init): Implementing mixer interface. + * gst/volume/gstvolume.h: Adding tracklist for mixer interface. + * sys/oss/gstosselement.c: (gst_osselement_get_type), + (gst_osselement_change_state): Removing some trailing commas in + structures. + * sys/oss/gstossmixer.c: (gst_ossmixer_interface_init): Setting mixer + interface type to HARDWARE. + * sys/v4l/gstv4lcolorbalance.c: + (gst_v4l_color_balance_interface_init): Setting colorbalance interface + type to HARDWARE. + * sys/v4l2/gstv4l2colorbalance.c: + (gst_v4l2_color_balance_interface_init): Setting colorbalance + interface type to HARDWARE. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain): use exactly the + same code than ximagesink for event handling. + +2004-01-15 Ronald Bultje + + * ext/snapshot/Makefile.am: + * ext/snapshot/gstsnapshot.c: (gst_snapshot_sinkconnect), + (gst_snapshot_chain): + * ext/snapshot/gstsnapshot.h: + This has to be a joke... Snapshot should be connected to a tee, + colorspace element before it and EOS after that, where the other + src of the tee receives normal data. + The current way is *wrong*. + +2004-01-15 Ronald Bultje + + * ext/hermes/gsthermescolorspace.c: + Fix another compile error. Same as below. + +2004-01-15 Ronald Bultje + + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/yuv2yuv.c: (gst_colorspace_yuy2_to_i420), + (gst_colorspace_i420_to_yv12): + Fix compiling... Didn't test if it actually works. + +2004-01-15 David Schleef + + * configure.ac: + * gst/colorspace/Makefile.am: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspace.h: + * gst/colorspace/yuv2rgb.c: + * gst/colorspace/yuv2rgb.h: + Duplicate the ext/hermes colorspace plugin, and remove Hermes + code and GPL code. Fix for new caps negotiation. Rewrite + much of the format handling code, and some of the conversion + code. Basically, rewrote almost everything. This element + handles I420, YV12 to RGB conversions. + * ext/hermes/Makefile.am: + * ext/hermes/gsthermescolorspace.c: + Rename colorspace to hermescolorspace. Fix negotiation issues. + Remove non-Hermes related code. This element handles lots of + RGB to RGB conversions, but no YUV. + * ext/hermes/gstcolorspace.c: + * ext/hermes/gstcolorspace.h: + * ext/hermes/rgb2yuv.c: + * ext/hermes/yuv2rgb.c: + * ext/hermes/yuv2rgb.h: + * ext/hermes/yuv2rgb_mmx16.s: + * ext/hermes/yuv2yuv.c: + * ext/hermes/yuv2yuv.h: + Remove old code. + +2004-01-14 Colin Walters + + * ext/mad/gstid3tag.c (gst_id3_tag_chain): Don't nego caps if + they've already been. + +2004-01-15 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_do_caps_nego): + assume tag mode when pad is not connected + +2004-01-15 Benjamin Otte + + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + Don't update the time of the clock + (gst_alsa_sink_loop): + sync to the clock given to alsasink, not the own clock + * sys/oss/gstosssink.c: (gst_osssink_chain): + sync to the clock + (gst_osssink_change_state): + activate the clock + * sys/ximage/ximagesink.c: (gst_ximagesink_chain): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain): + remove bogus code that made DISCONT events unhandled + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_video_caps): + explicitly case to double in _set_simple. (fixes 2nd warning in bug + #131502) + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_read_object_header), + (gst_asf_demux_handle_sink_event), (gst_asf_demux_audio_caps), + (gst_asf_demux_add_audio_stream), (gst_asf_demux_video_caps): + convert g_warning because of wrong asf data to GST_WARNINGs (fixes + 2nd warning in bug #131502) + +2004-01-14 Julien MOUTTE + + * gst/videofilter/gstvideobalance.c: (gst_videobalance_init), + (gst_videobalance_colorbalance_set_value), + (gst_videobalance_colorbalance_get_value): Fixing videobalance ranges + for colorbalance interface implementation. + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get), + (gst_ximagesink_set_property), (gst_ximagesink_get_property), + (gst_ximagesink_dispose), (gst_ximagesink_init), + (gst_ximagesink_class_init): Adding DISPLAY property. + * sys/ximage/ximagesink.h: Adding display_name to store display. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_set_property), (gst_xvimagesink_get_property), + (gst_xvimagesink_dispose), (gst_xvimagesink_init), + (gst_xvimagesink_class_init): Adding DISPLAY property and colorbalance + properties (they still need polishing though for gst-launch use : no + xcontext yet, i ll do that tomorrow). + * sys/xvimage/xvimagesink.h: Adding display_name to store display. + +2004-01-14 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup), + (gst_play_set_location), (gst_play_set_visualization): Preparing + switch integration, adding videobalance in the pipeline. + +2004-01-14 Julien MOUTTE + + * gst-libs/gst/colorbalance/colorbalance.c: + (gst_color_balance_class_init): Adding a default type. + * gst-libs/gst/colorbalance/colorbalance.h: Adding a macro to access + the type. + * gst/videofilter/gstvideobalance.c: (gst_videobalance_get_type), + (gst_videobalance_dispose), (gst_videobalance_class_init), + (gst_videobalance_init), (gst_videobalance_interface_supported), + (gst_videobalance_interface_init), + (gst_videobalance_colorbalance_list_channels), + (gst_videobalance_colorbalance_set_value), + (gst_videobalance_colorbalance_get_value), + (gst_videobalance_colorbalance_init): Implementing colorbalance + interface. + * gst/videofilter/gstvideobalance.h: Adding colorbalance channels + list. + * sys/ximage/ximagesink.c: (gst_ximagesink_set_xwindow_id): Fixing a + bug which was triggering a BadAccess X error when setting an overlay + before pad was really negotiated. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_colorbalance_init): + Using the colorbalance type macro. + +2004-01-14 Benjamin Otte + + * ext/flac/gstflacenc.c: (gst_flacenc_set_metadata), + (gst_flacenc_chain): + handle tags correctly + * gst/tags/gstid3tag.c: (gst_tag_list_new_from_id3v1): + extract ID3v1 tags correctly + +2004-01-14 Ronald Bultje + + * gst/typefind/gsttypefindfunctions.c: (matroska_type_find), + (plugin_init): + Improve matroska typefinding for odd-typed headers... + +2004-01-14 Ronald Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream): + Fix for using incremental number on padnames. + +2004-01-14 Ronald Bultje + + * ext/divx/gstdivxdec.c: + * ext/divx/gstdivxenc.c: + Set category to divx4linux instead of divx (too generic). + * gst/wavparse/gstwavparse.c: (gst_wavparse_init), + (gst_wavparse_parse_fmt), (gst_wavparse_handle_sink_event), + (gst_wavparse_loop), (gst_wavparse_change_state): + * gst/wavparse/gstwavparse.h: + fix parsing of WAV files with non-standard fmt-tag size and fix + skipping of unrecognized chunks... Someone please fix this thing + to use rifflib so all this is automated. + * sys/v4l/Makefile.am: + * sys/v4l2/Makefile.am: + Add X_CFLAGS because we depend on X (for overlay). + +2004-01-14 Jan Schmidt + + * ext/mpeg2dec/gstmpeg2dec.c: + Don't issue a timestamp unless we tagged the frame + with a PTS. + +2004-01-14 Benjamin Otte + + * gst-libs/gst/play/gstplay.c: (gst_play_tick_callback): + Query the audio element to get the time, not the clock. We're + interested in the element's time here. + +2004-01-14 Benjamin Otte + + * ext/aalib/gstaasink.c: (gst_aasink_chain): + * ext/alsa/gstalsasink.c: (gst_alsa_sink_check_event): + * ext/esd/esdsink.c: (gst_esdsink_chain): + * ext/libcaca/gstcacasink.c: (gst_cacasink_chain): + * ext/mas/massink.c: (gst_massink_chain): + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_chain): + * gst/matroska/matroska-demux.c: (gst_matroska_demux_parse_index), + (gst_matroska_demux_parse_metadata): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_loop), + (gst_mpeg_parse_release_locks): + * gst/tcp/gsttcpsink.c: (gst_tcpsink_chain): + * gst/udp/gstudpsink.c: (gst_udpsink_chain): + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + * sys/oss/gstosssink.c: (gst_osssink_init), (gst_osssink_chain), + (gst_osssink_change_state): + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_chain): + * sys/ximage/ximagesink.c: (gst_ximagesink_chain): + * sys/xvideo/xvideosink.c: (gst_xvideosink_chain), + (gst_xvideosink_release_locks): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain): + use element time. + * ext/alsa/gstalsaclock.c: (gst_alsa_clock_start), + (gst_alsa_clock_stop): + * gst-libs/gst/audio/audioclock.c: (gst_audio_clock_set_active), + (gst_audio_clock_get_internal_time): + simplify for use with new clocking code. + * testsuite/alsa/Makefile.am: + * testsuite/alsa/sinesrc.c: (sinesrc_init), (sinesrc_force_caps): + fix testsuite for new caps system + +2004-01-14 Benjamin Otte + + * ext/flac/gstflacdec.c: (gst_flacdec_update_metadata): + * ext/flac/gstflacenc.c: (add_one_tag): + length is already host endian, no need to convert. Fixes playback of + tagged files on PPC. (bug #128384) + +2004-01-13 Julien MOUTTE + + * gst-libs/gst/colorbalance/colorbalance.h: Adding a type to the + colorbalance interface stating if it is hardware based or software + based. + * gst/videofilter/gstvideobalance.c: (gst_videobalance_planar411): + Removing a trailing comma. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_colorbalance_init): Integrating a patch from Jon + Trowbridge querying Xv adaptor for min/max value as + the documentation seems to be wrong on the -1000 to 1000 interval. + +2004-01-12 David Schleef + + * gst/debug/efence.c: (gst_efence_init), (gst_efence_chain), + (gst_efence_buffer_alloc), (gst_fenced_buffer_new), + (gst_fenced_buffer_default_free), (gst_fenced_buffer_default_copy): + Fix negotiation. Add a bufferalloc function for the sink pad, + and generally clean up some of the code. + +2004-01-12 Julien MOUTTE + + * gst-libs/gst/colorbalance/colorbalancechannel.c: + (gst_color_balance_channel_dispose): Adding safety check in dispose + method. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_xcontext_clear), + (gst_xvimagesink_interface_supported), + (gst_xvimagesink_colorbalance_list_channels), + (gst_xvimagesink_colorbalance_set_value), + (gst_xvimagesink_colorbalance_get_value), + (gst_xvimagesink_colorbalance_init), (gst_xvimagesink_get_type): + Adding colorbalance interface support to set XV parameters such as + HUE, BRIGHTNESS, CONTRAST, SATURATION. + * sys/xvimage/xvimagesink.h: Adding the channels list for colorbalance + interface. + +2004-01-12 Thomas Vander Stichele + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_get_type), + (gst_audio_convert_class_init), (gst_audioconvert_getcaps), + (gst_audio_convert_init), (gst_audio_convert_set_property), + (gst_audio_convert_get_property), (gst_audio_convert_chain), + (gst_audio_convert_link), + (gst_audio_convert_buffer_to_default_format), + (gst_audio_convert_buffer_from_default_format), (plugin_init): + - implement _getcaps and use it + - improve linking + - remove float caps since no float conversion is actually done + - remove properties and arguments that were to be used for rate + conversion + +2004-01-12 Thomas Vander Stichele + + * gst-libs/gst/audio/audio.c: (_gst_audio_structure_set_list), + (gst_audio_structure_set_int): + * gst-libs/gst/audio/audio.h: + add helper functions for _getcaps matching the standard audio + templates + +2004-01-12 David Schleef + + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_link): + Test that pad is negotiated before getting its caps. + +2004-01-12 Julien MOUTTE + + * gst-libs/gst/play/gstplay.c: (gst_play_get_sink_element): When + analyzing the pads of an element the bin is mostly in READY state so + no caps were negotiated. This helper function needs to work with + _get_caps directly then. I was not freeing them though, added that to + fix the mem leak. + +2004-01-12 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_chain): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain): Fixing the + direct put buffers detection. I prefer checking GST_BUFFER_PRIVATE + than the free_func. + +2004-01-12 Thomas Vander Stichele + + * sys/oss/gstossaudio.c: (plugin_init): + * sys/oss/gstosselement.c: (gst_osselement_sync_parms): + * sys/oss/gstosselement.h: + make an oss debugging category + make failure more descriptive + +2004-01-11 David Schleef + + * ext/ffmpeg/gstffmpeg.c: + * ext/ffmpeg/gstffmpegcodecmap.c: + * ext/ffmpeg/gstffmpegdec.c: + * ext/ffmpeg/gstffmpegenc.c: + * ext/ffmpeg/gstffmpegprotocol.c: + * ext/gdk_pixbuf/gstgdkanimation.c: + * ext/jpeg/gstjpeg.c: + * ext/libpng/gstpng.c: + * ext/mpeg2dec/perftest.c: + * ext/speex/gstspeex.c: + * gst-libs/gst/resample/dtos.c: + * gst/intfloat/gstintfloatconvert.c: + * gst/oneton/gstoneton.c: + * gst/rtjpeg/RTjpeg.c: + * gst/rtp/gstrtp.c: + * sys/dxr3/dxr3init.c: + * sys/glsink/gstgl_nvimage.c: + * sys/glsink/gstgl_pdrimage.c: + * sys/glsink/gstglsink.c: + * testsuite/gst-lint: + Make sure everybody wraps #include "config.h" in #ifdef HAVE_CONFIG_H + +2004-01-11 David Schleef + + * ext/alsa/gstalsasrc.c: (gst_alsa_src_set_caps): + * ext/faac/gstfaac.c: (gst_faac_sinkconnect): + * ext/gdk_pixbuf/gstgdkanimation.c: + (gst_gdk_animation_iter_create_pixbuf): + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_sink_link), + (gst_gdk_pixbuf_chain): + * ext/gdk_pixbuf/gstgdkpixbuf.h: + * ext/jack/gstjack.c: (gst_jack_change_state): + * ext/xvid/gstxviddec.c: (gst_xviddec_sink_link): + * gst-libs/gst/play/gstplay.c: (gst_play_get_sink_element): + * gst-libs/gst/play/play.c: (gst_play_get_sink_element): + * gst/videofilter/gstvideofilter.c: + (gst_videofilter_set_output_size): + Remove all usage of gst_pad_get_caps(), and replace it with + gst_pad_get_allowed_caps() or gst_pad_get_negotiated_cap(). + +2004-01-11 David Schleef + + * configure.ac: + * ext/Makefile.am: Fixes to make ext/libcaca compile. + * ext/divx/gstdivxdec.c: + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_sink_link), + (gst_gdk_pixbuf_init), (gst_gdk_pixbuf_chain): Make gdkpixbufdec + handle images that span multiple buffers. Now work with both + filesrc ! gdkpixbufdec and qtdemux ! gdkpixbufdec. + * ext/gdk_pixbuf/gstgdkpixbuf.h: + * ext/libcaca/gstcacasink.h: Fixes needed due to recent + video/video.h changes + * ext/xvid/gstxvid.c: (gst_xvid_csp_to_caps): same + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_get), + (gst_v4lmjpegsrc_buffer_free): Use buffer free function instead + of GstData free function. + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get), (gst_v4lsrc_buffer_free): + same. + +2004-01-12 Benjamin Otte + + * sys/v4l2/gstv4l2element.c: (gst_v4l2element_class_init), + (gst_v4l2element_dispose), (gst_v4l2element_set_property), + (gst_v4l2element_get_property): + * sys/v4l2/v4l2_calls.c: (gst_v4l2_set_defaults), (gst_v4l2_open): + add norm, channel and frequency properties. + * sys/v4l2/gstv4l2tuner.c: + fixes for tuner interface changes + * sys/v4l2/gstv4l2element.h: + * sys/v4l2/gstv4l2src.c: + * sys/v4l2/gstv4l2src.h: + * sys/v4l2/v4l2src_calls.c: + * sys/v4l2/v4l2src_calls.h: + rework v4l2src to work with saa1734 cards and allow mmaped buffers. + +2004-01-12 Benjamin Otte + + * gst-libs/gst/tuner/tuner.c: (gst_tuner_class_init), + (gst_tuner_find_norm_by_name), (gst_v4l2_find_channel_by_name), + (gst_tuner_channel_changed), (gst_tuner_norm_changed), + (gst_tuner_frequency_changed), (gst_tuner_signal_changed): + * gst-libs/gst/tuner/tuner.h: + GObjects aren't const. + Add find_by_name functions. + Add checks to _changed functions. + * sys/v4l/gstv4ltuner.c: (gst_v4l_tuner_get_channel), + (gst_v4l_tuner_get_norm): + Fixes for above. + +2004-01-12 Benjamin Otte + + * gst-libs/gst/video/video.h: + Fix caps template names to be understandable. + Prefix everything with GST_VIDEO. + * ext/aalib/gstaasink.c: + * ext/divx/gstdivxdec.c: + * ext/divx/gstdivxenc.c: + * ext/gdk_pixbuf/gstgdkpixbuf.c: + * ext/hermes/gstcolorspace.c: (gst_colorspace_base_init): + * ext/jpeg/gstjpegdec.c: (raw_caps_factory): + * ext/jpeg/gstjpegenc.c: (raw_caps_factory): + * ext/libcaca/gstcacasink.c: + * ext/libpng/gstpngenc.c: (raw_caps_factory): + * ext/snapshot/gstsnapshot.c: + * ext/swfdec/gstswfdec.c: + * ext/xvid/gstxviddec.c: + * ext/xvid/gstxvidenc.c: + * gst/chart/gstchart.c: + * gst/deinterlace/gstdeinterlace.c: + * gst/effectv/gsteffectv.c: + * gst/flx/gstflxdec.c: (gst_flxdec_loop): + * gst/goom/gstgoom.c: + * gst/median/gstmedian.c: + * gst/monoscope/gstmonoscope.c: (gst_monoscope_init), + (gst_monoscope_srcconnect), (gst_monoscope_chain): + * gst/overlay/gstoverlay.c: + * gst/smooth/gstsmooth.c: + * gst/smpte/gstsmpte.c: + * gst/synaesthesia/gstsynaesthesia.c: + * gst/videocrop/gstvideocrop.c: + * gst/videodrop/gstvideodrop.c: + * gst/y4m/gsty4mencode.c: + * sys/qcam/gstqcamsrc.c: + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_palette_to_caps): + Make them work with new video.h file. + * sys/ximage/ximagesink.c: (gst_ximagesink_chain), + (gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain), + (gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc): + Make it work with new buffer allocation system. + +2004-01-11 Julien MOUTTE + + * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_chain): Fixing the + pad_alloc_buffer implementation to use ->srcpad + * ext/hermes/gstcolorspace.c: (gst_colorspace_chain): Fixing the + pad_alloc_buffer implementation to use ->srcpad + * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain): Fixing the + pad_alloc_buffer implementation to use ->srcpad + * sys/ximage/ximagesink.c: (gst_ximagesink_ximage_new), + (gst_ximagesink_chain), (gst_ximagesink_buffer_free), + (gst_ximagesink_buffer_alloc): Now only use GST_BUFFER_PRIVATE to keep + a reference to everything we need. + * sys/ximage/ximagesink.h: adding a reference to the sink in the image. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xvimage_new), + (gst_xvimagesink_chain), (gst_xvimagesink_buffer_free), + (gst_xvimagesink_buffer_alloc): Now only use GST_BUFFER_PRIVATE to keep + a reference to everything we need. + * sys/xvimage/xvimagesink.h: adding a reference to the sink in the image + +2004-01-11 David Schleef + + * ext/divx/gstdivxenc.c: remove bogus gst_caps_is_fixed() test + * gst/debug/efence.c: (gst_efence_chain), (gst_fenced_buffer_new), + (gst_fenced_buffer_default_copy): Fix for rename of buffer private + structure members. + * gst/effectv/gstwarp.c: (gst_warptv_setup): Don't reset the time + value during a resize/renegotiation. + * gst/videofilter/gstvideofilter.c: (gst_videofilter_chain): use + gst_pad_alloc_buffer(); + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_get), + (gst_v4lmjpegsrc_buffer_free): Fix for rename of buffer private + structure members. + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_get), (gst_v4lsrc_buffer_free): + Fix for rename of buffer private structure members. + * sys/ximage/ximagesink.c: (gst_ximagesink_chain), + (gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc): + Fix for rename of buffer private structure members. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain), + (gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc): + Fix for rename of buffer private structure members. + +2004-01-11 Arwed v. Merkatz + + reviewed by: David Schleef + + * gst/videofilter/Makefile.am: + * gst/videofilter/gstgamma.c: Gamma correction filter. Modified + from the patch by ds to fit in with recent make_filter changes. + +2004-01-11 Julien MOUTTE + + * configure.ac: Adding examples/switch/Makefile + * examples/Makefile.am: Adding examples/switch + * examples/switch/Makefile.am: Adding switcher example. + * examples/switch/switcher.c: (got_eos), (idle_iterate), + (switch_timer), (main): Adding an example demonstrating switch usage + with 2 videotestsrc showing different patterns. + * gst/switch/gstswitch.c: (gst_switch_request_new_pad), + (gst_switch_init): Fixing switch with the new caps system. + +2004-01-11 Benjamin Otte + + * gst-libs/gst/video/video.h: + Fix 32bit caps. Issue remaining: The macro names are chosen poorly. + They should probably be like + GST_VIDEO_PAD_TEMPLATE_CAPS_{RGB,BGR,RGBx,BGRx}. + +2004-01-11 Benjamin Otte + + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (qtdemux_parse_trak): + fix audio chunk size/timestamp calculation + +2004-01-11 Benjamin Otte + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps): + fix SVQ3 caps + +2004-01-11 Steve Baker + + * gst/effectv/gstaging.c: (gst_agingtv_get_type), + (gst_agingtv_base_init), (gst_agingtv_class_init), + (gst_agingtv_init), (gst_agingtv_setup), (gst_agingtv_rgb32), + (gst_agingtv_set_property), (gst_agingtv_get_property): + Port agingTV to videofilter + +2004-01-09 Julien MOUTTE + + * ext/hermes/gstcolorspace.c: (gst_colorspace_chain): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + +2004-01-09 Julien MOUTTE + + * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_chain): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * gst-libs/gst/xoverlay/xoverlay.c: + (gst_x_overlay_got_desired_size): Updating doc for the xid being 0. + * gst/videoscale/gstvideoscale.c: (gst_videoscale_chain): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + Implementing gst_pad_alloc_buffer to use optimized buffer allocation. + * sys/ximage/ximagesink.c: (gst_ximagesink_chain), + (gst_ximagesink_buffer_free), (gst_ximagesink_buffer_alloc), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_init): Implementing + the bufferalloc_function to replace bufferpools, fixing the XOverlay + interface implementation to handle xid being 0 and fix some bugs + triggered by Benjamin's testcase. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_chain), + (gst_xvimagesink_buffer_free), (gst_xvimagesink_buffer_alloc), + (gst_xvimagesink_set_xwindow_id), (gst_xvimagesink_init): Implementing + the bufferalloc_function to replace bufferpools, fixing the XOverlay + interface implementation to handle xid being 0 and fix some bugs + triggered by Benjamin's testcase. + +2004-01-09 David Schleef + + * ext/librfb/gstrfbsrc.c: Hacking. Added actual decoding and + mouse pointer events. It works. + +2004-01-09 Ronald Bultje + + * ext/divx/gstdivxenc.c: (gst_divxenc_init): + Use explicit caps - fix capsnego. + * ext/xvid/gstxviddec.c: + * ext/xvid/gstxvidenc.c: + Remove macro-inside-macro which caused compile errors. + * gst-libs/gst/riff/riff-read.c: (gst_riff_read_header): + Error out if it's not a RIFF file. Else we error out without + gst_element_error() which is not good... + +2004-01-08 David Schleef + + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_connect): + Fix pad_link function to handle formats that ffmpeg returns + as multiple caps structures. + * gst/videofilter/gstvideofilter.c: (gst_videofilter_chain): + Only complain if source buffer is _smaller_ than expected. + * gst/videoscale/gstvideoscale.c: (gst_videoscale_init), + (gst_videoscale_handle_src_event): Resize navigation events + when passing them upstream. + * gst/videotestsrc/gstvideotestsrc.c: + * gst/videotestsrc/gstvideotestsrc.h: + * gst/videotestsrc/videotestsrc.c: + * gst/videotestsrc/videotestsrc.h: + Rewrite many of the buffer painting functions to handle odd + sizes (for many formats, size%4!=0 or size%8!=0). Most have + been verified to work with my video card. + * testsuite/gst-lint: Add check for elements calling + gst_pad_get_caps() instead of gst_pad_get_allowed_caps(). + +2004-01-08 David Schleef + + * gst/videodrop/gstvideodrop.c: (gst_videodrop_getcaps), + (gst_videodrop_link), (gst_videodrop_init): Fix negotiation. + +2004-01-08 Julien MOUTTE + + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): A + configure event is not emiting the desired size signal. That fixes + aspect ratio issues with gst-player. + +2004-01-08 Ronald Bultje + + * gst/median/gstmedian.c: (gst_median_link), (gst_median_init): + Fix capsnego. + +2004-01-08 Julien MOUTTE + + * ext/sdl/sdlvideosink.c: (gst_sdlvideosink_create): Using XOverlay + public method to fire size signal. + +2004-01-07 Julien MOUTTE + + * examples/gstplay/Makefile.am: Adding the interface library. + * gst-libs/gst/play/Makefile.am: Adding the interface library. + * gst-libs/gst/play/gstplay.c: (gst_play_set_video_sink): Connecting to the XOverlay size signal instead of GstVideoSink. + * gst-libs/gst/play/gstplay.h: Including the XOverlay interface to check + GST_IS_X_OVERLAY before signal connect. + * gst-libs/gst/video/gstvideosink.c: (gst_videosink_class_init): + Removing the have_video_size signal. + * gst-libs/gst/video/gstvideosink.h: Removing the have_video_size signal + and associated public method. + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents), + (gst_ximagesink_sinkconnect): Using XOverlay public method to fire size + signal. + * sys/xvideo/xvideosink.c: (gst_xvideosink_sinkconnect), + (gst_xvideosink_xwindow_new): Using XOverlay public method to fire size + signal. + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_sinkconnect): + Using XOverlay public method to fire size signal. + +2004-01-07 David Schleef + + * gst/videofilter/Makefile.am: + * gst/videofilter/gstvideotemplate.c: + * gst/videofilter/make_filter: + Create gstvideoexample.c in a srcdir!=builddir friendly way. + Convert make_filter to /bin/sh script. + +2004-01-07 Thomas Vander Stichele + + * gst/modplug/gstmodplug.cc: fix element description + +2004-01-07 Julien MOUTTE + + * examples/gstplay/player.c: (got_time_tick), (got_stream_length), + (got_video_size): Adding some new lines in g_print calls. + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new), + (gst_ximagesink_xwindow_destroy), (gst_ximagesink_xwindow_resize), + (gst_ximagesink_handle_xevents), (gst_ximagesink_fixate), + (gst_ximagesink_sinkconnect), (gst_ximagesink_change_state), + (gst_ximagesink_chain), (gst_ximagesink_buffer_new), + (gst_ximagesink_set_xwindow_id), (gst_ximagesink_get_desired_size): + Complete code review, reverting some stuff i disagree with, adding + some fixes : time synchronization on invalid timestamps, renegotiation + of private window. + * sys/ximage/ximagesink.h: + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_xwindow_destroy), + (gst_xvimagesink_xwindow_resize), (gst_xvimagesink_handle_xevents), + (gst_xvimagesink_get_xv_support), (gst_xvimagesink_xcontext_get), + (gst_xvimagesink_fixate), (gst_xvimagesink_sinkconnect), + (gst_xvimagesink_change_state), (gst_xvimagesink_chain), + (gst_xvimagesink_buffer_new), + (gst_xvimagesink_navigation_send_event), + (gst_xvimagesink_set_xwindow_id), + (gst_xvimagesink_get_desired_size), + (gst_xvimagesink_xoverlay_init): Complete code review, reverting some + stuff i disagree with, adding some fixes : Renegotiation of private + window, implementing get_desired_size. + +2004-01-07 Ronald Bultje + + * ext/audiofile/gstafsink.c: (gst_afsink_init), (gst_afsink_chain), + (gst_afsink_handle_event): + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_init): + * gst/avi/gstavimux.c: (gst_avimux_request_new_pad): + * sys/dxr3/dxr3audiosink.c: (dxr3audiosink_init): + * sys/dxr3/dxr3spusink.c: (dxr3spusink_init): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_init): + Fix for instantiate-test (see core). Also remove dead code from + jpegenc (which still needs fixing, but that's lower on my TODO + list...). + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_getcaps): + Never return NULL as caps. + +2004-01-07 David Schleef + + * configure.ac: + * ext/Makefile.am: + * ext/librfb/Makefile.am: + * ext/librfb/gstrfbsrc.c: + New source plugin based on librfb-0.1. RFB (remote framebuffer) + is the protocol used by VNC. + +2004-01-07 David Schleef + + * gst/videofilter/gstvideotemplate.c: + * gst/videofilter/gstvideotemplate.h: + * gst/videofilter/make_filter: + Merge videotemplate header into source file. + * gst/effectv/Makefile.am: + * gst/effectv/gsteffectv.c: (plugin_init): + * gst/effectv/gstwarp.c: + Make warpTV a subclass of videofilter. + +2004-01-07 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_mad_id3_to_tag_list): + Add guard against invalid utf-8 conversions in mad. Just in case. + +2004-01-07 Benjamin Otte + + * sys/oss/gstosssink.c: (gst_osssink_sink_fixate): + Fix for bug shown by poisoning + +2004-01-06 Ronald Bultje + + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_get), + (gst_v4lmjpegsrc_buffer_free): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_palette_to_caps), + (gst_v4lsrc_srcconnect), (gst_v4lsrc_getcaps), (gst_v4lsrc_get), + (gst_v4lsrc_buffer_free): + Fix for removed bufferpools. + +2004-01-07 Jan Schmidt + + * ext/dv/gstdvdec.c: (gst_dvdec_loop): + Fix caps negotiation. + + * ext/dvdnav/dvdnavsrc.c: (dvdnavsrc_class_init), + (dvdnavsrc_update_buttoninfo), (dvdnavsrc_get), + (dvdnavsrc_get_event_mask), (dvdnav_handle_navigation_event), + (dvdnavsrc_event): + * ext/mpeg2dec/gstmpeg2dec.c: + * gst-libs/gst/navigation/navigation.c: + (gst_navigation_send_key_event), (gst_navigation_send_mouse_event): + * gst-libs/gst/navigation/navigation.h: + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_handle_src_event): + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_handle_xevents): + Super-simple first version of mouse and keyboard events. Clicking + on a DVD menu now works, although it may not take you where you + expected. + + * gst/sine/gstsinesrc.c: (gst_sinesrc_src_fixate): + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_src_fixate): + These fixate functions were broken - they never actually + fixated :) + +2004-01-06 Ronald Bultje + + * ext/shout/gstshout.c: (gst_icecastsend_base_init), + (gst_icecastsend_init): + fix for new caps system. + * gst-libs/gst/mixer/mixertrack.h: + * sys/oss/gstossmixer.c: (gst_ossmixer_build_list): + Add 'master track' flag (for tools like ACME that only want to + change the main volume). + +2004-01-07 Jan Schmidt + + * ext/xvid/gstxvid.c: (gst_xvid_structure_to_csp), + (gst_xvid_csp_to_caps): + * ext/xvid/gstxviddec.c: (gst_xviddec_src_getcaps): + * ext/xvid/gstxvidenc.c: + ifdef out ARGB type when it isn't available + in xvidcore 1.0.0beta2 + +2004-01-06 Ronald Bultje + + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_loop): + When we have received a new SCR right in the first buffer after + a seek (so in the same cycle that handles the discont), we should + handle the buffer instead of unreffing it, else we lose data. + +2004-01-06 Iain + + * gst/intfloat/gstint2float.c (gst_int2float_link): Set the + buffer-frames caps too. + + * gst/oneton/gstoneton.c (gst_oneton_sink_connect): Only create the new + caps that we need, don't destroy them all and rebuild them. And when + creating src pads, use the src pad template rather than the sink... + +2004-01-05 Ronald Bultje + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead): + Add pad to element *after* setting functions such as event handler. + Without this, the scheduler (opt) will link pads, set the event + handler from the default event function (dispatcher in gstpad.c) + and *after* that, we will set our own event function, which will + thus never be used (and thus mpegdemux doesn't handle events). + +2004-01-04 David Schleef + + Fix the fixate functions to handle new prototype: + * gst/sine/gstsinesrc.c: (gst_sinesrc_src_fixate): + * gst/videotestsrc/gstvideotestsrc.c: + (gst_videotestsrc_src_fixate): + * sys/oss/gstosssink.c: (gst_osssink_sink_fixate): + * sys/ximage/ximagesink.c: (gst_ximagesink_fixate): + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_fixate): + +2004-01-04 Benjamin Otte + + * sys/ximage/ximagesink.h: + * sys/ximage/ximagesink.c: (gst_ximagesink_xwindow_new), + (gst_ximagesink_xwindow_destroy), (gst_ximagesink_sinkconnect), + (gst_ximagesink_change_state), (gst_ximagesink_set_xwindow_id), + (gst_ximagesink_xoverlay_init): + assorted fixes to make (re)embedding work + * sys/ximage/ximagesink.c: (gst_ximagesink_sinkconnect), + (gst_ximagesink_get_desired_size): + implement desired size additions to XOverlay + +2004-01-04 Benjamin Otte + + * gst-libs/gst/xoverlay/xoverlay.c: (gst_x_overlay_base_init), + (gst_x_overlay_got_xwindow_id), (gst_x_overlay_get_desired_size), + (gst_x_overlay_got_desired_size): + * gst-libs/gst/xoverlay/xoverlay.h: + Add optional "desired size" signal and querying. + +2004-01-04 Ronald Bultje + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_blockgroup): + Fix EBML-laced block parsing. Diffs are relative to previous + lace, not the first lace. Thanks to Mosu from the Matroska + team for detecting this. + * gst/wavparse/gstwavparse.c: (gst_wavparse_init), + (gst_wavparse_parse_fmt), (gst_wavparse_getcaps), + (gst_wavparse_handle_sink_event), (gst_wavparse_loop), + (gst_wavparse_change_state): + * gst/wavparse/gstwavparse.h: + Quickfix for capsnego. + +2004-01-04 Ronald Bultje + + * gst/wavenc/gstwavenc.c: (set_property), (gst_wavenc_init): + Fix indenting, fix pad creation. + +2004-01-04 Ronald Bultje + + * ext/xvid/gstxviddec.c: (gst_xviddec_init), + (gst_xviddec_src_getcaps), (gst_xviddec_src_link), + (gst_xviddec_sink_link): + Implement src_getcaps() so proper size caps is negotiated. + +2004-01-04 Ronald Bultje + + * ext/flac/gstflacdec.c: (gst_flacdec_loop): + Finish flac decoder on EOS. See #116178. + +2004-01-04 Ronald Bultje + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_src_getcaps), + (gst_matroska_demux_add_stream): + * gst/matroska/matroska-ids.h: + Add getcaps() function to fix capsnego... + +2004-01-04 Ronald Bultje + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead), + (gst_mpeg_demux_parse_packet), (gst_mpeg_demux_parse_pes): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_parse_packhead): + Fix more integer overflows. Again, see #126967. + +2004-01-03 Ronald Bultje + + * ext/mpeg2dec/gstmpeg2dec.c: + Add support for mpeg2dec-0.4.0 (released two weeks ago). See + #130416. + +2004-01-03 Ronald Bultje + + * configure.ac: + * ext/xvid/gstxvid.c: (gst_xvid_init), (gst_xvid_error), + (gst_xvid_structure_to_csp), (gst_xvid_csp_to_caps): + * ext/xvid/gstxvid.h: + * ext/xvid/gstxviddec.c: (gst_xviddec_class_init), + (gst_xviddec_init), (gst_xviddec_setup), (gst_xviddec_chain), + (gst_xviddec_src_link), (gst_xviddec_sink_link), + (gst_xviddec_change_state): + * ext/xvid/gstxviddec.h: + * ext/xvid/gstxvidenc.c: (gst_xvidenc_profile_get_type), + (gst_xvidenc_base_init), (gst_xvidenc_class_init), + (gst_xvidenc_init), (gst_xvidenc_setup), (gst_xvidenc_chain), + (gst_xvidenc_link), (gst_xvidenc_set_property), + (gst_xvidenc_get_property), (gst_xvidenc_change_state): + * ext/xvid/gstxvidenc.h: + Update xvid plugin to latest xvid (1.0.0-beta3) API. + +2004-01-03 Ronald Bultje + + * gst/rtp/rtp-packet.c: + Add sys/types.h include, since OS X doesn't define in_addr_t + in netinet/in.h, like it does on Linux (see #129600). + +2004-01-03 Thomas Canty + + reviewed by: Ronald Bultje + + * ext/alsa/gstalsamixer.c: (gst_alsa_mixer_dispose): + Correct logic of dispose function (see #129306). + +2004-01-03 Ronald Bultje + + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_pes): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_class_init), + (gst_mpeg_parse_init): + * gst/mpegstream/gstmpegparse.h: + Remove clock (which was never provided, i.e. dead code), and + also fix integer overflows at high PTS values (see #126967). + +2004-01-03 Ronald Bultje + + * ext/flac/gstflacdec.c: + * ext/libpng/gstpngenc.h: + * ext/mikmod/gstmikmod.h: + OS X fixes (see #126628). + +2004-01-02 David Schleef + + * ext/alsa/gstalsasrc.c: (gst_alsa_src_pad_factory), + (gst_alsa_src_base_init): Remove bogus "src" request pad. + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_base_init), + (gst_mpeg_parse_class_init): Move pad template registration + to class_init, since the derived class (mpegdemux) doesn't + want them. + +2004-01-03 Ronald Bultje + + * sys/ximage/Makefile.am: + * sys/xvideo/Makefile.am: + * sys/xvimage/Makefile.am: + Move interface libs from LDFLAGS to LIBADD, fix relocation errors + after installation (see #127664). + +2004-01-02 David Schleef + + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_init), + (gst_ffmpegenc_connect): Negotiation fixes. + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_negotiate_format): + Remove inappropriate gst_caps_free(). + * sys/ximage/ximagesink.c: (gst_ximagesink_sinkconnect): + Reenable Ronald's internal resize code, since the core handles + it correctly now. + +2004-01-02 Ronald Bultje + + * sys/v4l/gstv4lmjpegsink.c: (gst_v4lmjpegsink_init): + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_init): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_base_init), (gst_v4lsrc_init): + Fix pad template stuff. + +2004-01-02 Ronald Bultje + + * gst/matroska/ebml-read.c: (gst_ebml_read_sint): + * gst/matroska/ebml-write.c: (gst_ebml_write_sint): + fix signed integer reading/writing. + +2004-01-02 Benjamin Otte + + * ext/alsa/README: + Remove outdated document + +2004-01-03 Jan Schmidt + + * gst/cutter/gstcutter.c: (gst_cutter_init): + src pad was being created twice - oops. + +2004-01-02 Ronald Bultje + + * sys/ximage/ximagesink.c: (gst_ximagesink_sinkconnect): + Comment out internal resize. It doesn't handle the resulting + XEvent internally, does another try_set_caps() which leads to + a really nice loop. + Real fix will come when Julien and Dave are awake. ;). + +2004-01-02 Ronald Bultje + + * ext/mpeg2enc/gstmpeg2enc.cc: + fix const/nonconst compile issue. + +2004-01-02 David Schleef + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_fixate), + (gst_xvimagesink_sinkconnect), (gst_xvimagesink_init): + Add fixate function and a check for bad formats. + +2004-01-01 David Schleef + + Negotiation fixes: + * gst-libs/gst/audio/gstaudiofilter.c: (gst_audiofilter_link), + (gst_audiofilter_init): + * gst/debug/efence.c: (gst_efence_init): + * gst/deinterlace/gstdeinterlace.c: (gst_deinterlace_link), + (gst_deinterlace_init): + * gst/volume/gstvolume.c: (volume_connect): + +2004-01-01 David Schleef + + Convert elements to use gst_pad_use_explicit_caps() where + appropriate: + * ext/a52dec/gsta52dec.c: (gst_a52dec_init), (gst_a52dec_reneg): + * ext/audiofile/gstafparse.c: (gst_afparse_init), + (gst_afparse_open_file): + * ext/audiofile/gstafsrc.c: (gst_afsrc_init), + (gst_afsrc_open_file): + * ext/esd/esdmon.c: (gst_esdmon_init), (gst_esdmon_get): + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_init), + (gst_ffmpegdec_chain): + * ext/ffmpeg/gstffmpegdemux.c: (gst_ffmpegdemux_loop): + * ext/flac/gstflacdec.c: (gst_flacdec_init), (gst_flacdec_write): + * ext/gdk_pixbuf/gstgdkpixbuf.c: (gst_gdk_pixbuf_init), + (gst_gdk_pixbuf_chain): + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_init), (gst_jpegdec_link), + (gst_jpegdec_chain): + * ext/mad/gstmad.c: (gst_mad_init), (gst_mad_chain): + * ext/mikmod/gstmikmod.c: (gst_mikmod_init), + (gst_mikmod_negotiate): + * ext/mpeg2dec/gstmpeg2dec.c: (gst_mpeg2dec_init), + (gst_mpeg2dec_negotiate_format): + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/ogg/gstoggdemux.c: (gst_ogg_pad_push): + * ext/speex/gstspeexdec.c: (gst_speexdec_init), + (gst_speexdec_sinkconnect): + * ext/swfdec/gstswfdec.c: (gst_swfdec_loop), (gst_swfdec_init): + * ext/vorbis/vorbisfile.c: (gst_vorbisfile_init), + (gst_vorbisfile_new_link): + * gst/ac3parse/gstac3parse.c: (gst_ac3parse_init), + (gst_ac3parse_chain): + * gst/asfdemux/gstasfdemux.c: (gst_asf_demux_add_audio_stream), + (gst_asf_demux_setup_pad): + * gst/auparse/gstauparse.c: (gst_auparse_init), + (gst_auparse_chain): + * gst/id3/gstid3types.c: (gst_id3types_loop): + * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_stream): + * gst/mpeg1videoparse/gstmp1videoparse.c: (gst_mp1videoparse_init), + (mp1videoparse_parse_seq): + * gst/mpegaudioparse/gstmpegaudioparse.c: (gst_mp3parse_init), + (bpf_from_header): + * gst/mpegstream/gstmpegdemux.c: (gst_mpeg_demux_parse_syshead), + (gst_mpeg_demux_parse_pes), (gst_mpeg_demux_lpcm_set_caps): + * gst/mpegstream/gstmpegparse.c: (gst_mpeg_parse_init), + (gst_mpeg_parse_send_data): + * gst/qtdemux/qtdemux.c: (gst_qtdemux_loop_header), + (gst_qtdemux_add_stream): + * gst/realmedia/rmdemux.c: (gst_rmdemux_add_stream): + * gst/wavparse/gstwavparse.c: (gst_wavparse_init), + (gst_wavparse_parse_fmt): + +2004-01-01 Ronald Bultje + + * configure.ac: + Fix configure check for mpeg2enc. We need 1.6.1.93 instead of + 1.6.1.92, since the pkg-config file of 1.6.1.92 is borked and + it therefore uses the wrong include paths. Too bad... Note + that 1.6.1.93 is not release yet. ;). + Also add a check for mplex, which is now using the lib'ified + mplex from mjpegtools, too. + * ext/ffmpeg/gstffmpegcodecmap.c: + Add codec_tag for 3ivx/xvid. For xvid, this should fix playback + issues. I don't think ffmpeg handles 3ivx correctly, so this + probably won't work. But it won't hurt either. + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_connect), + (gst_ffmpegdec_chain): + * ext/ffmpeg/gstffmpegenc.c: (gst_ffmpegenc_connect), + (gst_ffmpegenc_chain_audio): + Fix memleak in audio encoding. Close codec if open fails, this + calls the cleanup routines so we can re-use the context. + * ext/mpeg2enc/gstmpeg2enc.cc: + Fix pad template names/types, fix memory issue with getcaps(). + * ext/mpeg2enc/gstmpeg2encoder.cc: + * ext/mpeg2enc/gstmpeg2encoder.hh: + Fix compile issue with new caps system (const thingy). + * ext/mpeg2enc/gstmpeg2encpicturereader.cc: + * ext/mpeg2enc/gstmpeg2encpicturereader.hh: + We read a first frame right on initing, so that we have a caps + when we init the output. This caps is cached in padprivate and + read as first frame. + * ext/mplex/Makefile.am: + * ext/mplex/gstmplex.cc: + * ext/mplex/gstmplex.h: + * ext/mplex/gstmplex.hh: + * ext/mplex/gstmplexibitstream.cc: + * ext/mplex/gstmplexibitstream.hh: + * ext/mplex/gstmplexjob.cc: + * ext/mplex/gstmplexjob.hh: + * ext/mplex/gstmplexoutputstream.cc: + * ext/mplex/gstmplexoutputstream.hh: + We wrap mjpegtools mplex. So I rewrote the plugin. The old plugin + had issues, didn't do capsnego, supported only a subset of the + mplex features and required a mplex fork in our local CVS. Plus + that it worked agaist a very old mplex version. Rewriting was + faster than updating it. + * gst-libs/ext/Makefile.am: + * gst-libs/ext/mplex/INSTRUCT: + * gst-libs/ext/mplex/Makefile.am: + * gst-libs/ext/mplex/README: + * gst-libs/ext/mplex/TODO: + * gst-libs/ext/mplex/ac3strm_in.cc: + * gst-libs/ext/mplex/audiostrm.hh: + * gst-libs/ext/mplex/audiostrm_out.cc: + * gst-libs/ext/mplex/aunit.hh: + * gst-libs/ext/mplex/bits.cc: + * gst-libs/ext/mplex/bits.hh: + * gst-libs/ext/mplex/buffer.cc: + * gst-libs/ext/mplex/buffer.hh: + * gst-libs/ext/mplex/fastintfns.h: + * gst-libs/ext/mplex/format_codes.h: + * gst-libs/ext/mplex/inputstrm.cc: + * gst-libs/ext/mplex/inputstrm.hh: + * gst-libs/ext/mplex/lpcmstrm_in.cc: + * gst-libs/ext/mplex/mjpeg_logging.cc: + * gst-libs/ext/mplex/mjpeg_logging.h: + * gst-libs/ext/mplex/mjpeg_types.h: + * gst-libs/ext/mplex/mpastrm_in.cc: + * gst-libs/ext/mplex/mpegconsts.cc: + * gst-libs/ext/mplex/mpegconsts.h: + * gst-libs/ext/mplex/mplexconsts.hh: + * gst-libs/ext/mplex/multplex.cc: + * gst-libs/ext/mplex/outputstream.hh: + * gst-libs/ext/mplex/padstrm.cc: + * gst-libs/ext/mplex/padstrm.hh: + * gst-libs/ext/mplex/stillsstream.cc: + * gst-libs/ext/mplex/stillsstream.hh: + * gst-libs/ext/mplex/systems.cc: + * gst-libs/ext/mplex/systems.hh: + * gst-libs/ext/mplex/vector.cc: + * gst-libs/ext/mplex/vector.hh: + * gst-libs/ext/mplex/videostrm.hh: + * gst-libs/ext/mplex/videostrm_in.cc: + * gst-libs/ext/mplex/videostrm_out.cc: + * gst-libs/ext/mplex/yuv4mpeg.cc: + * gst-libs/ext/mplex/yuv4mpeg.h: + * gst-libs/ext/mplex/yuv4mpeg_intern.h: + * gst-libs/ext/mplex/yuv4mpeg_ratio.cc: + We don't fork mjpegtools' mplex in our CVS anymore. + * gst/avi/gstavidemux.c: (gst_avi_demux_src_getcaps), + (gst_avi_demux_add_stream): + * gst/avi/gstavidemux.h: + Add getcaps() function for proper caps nego. This makes some + parts of AVI playback/reading work. + * sys/ximage/ximagesink.c: (gst_ximagesink_sinkconnect): + Resize window on new capsnego. This is probably wrong, but + I'm still committing it because with current capsnego, the + first successfull capsnego is auto-fixated, therefore rounded + down to the lowest values in the caps. this results in a 16x16 + XWindow that is not reized when real capsnego finishes. + Dave, I see more cases of this, do you know a proper solution? + * tools/gst-launch-ext.in: + Fix MPEG-4 AAC (Apple iPod/iTunes) file commandline. + +2003-12-31 David Schleef + + * gst/tcp/gsttcpsrc.c: (gst_tcpsrc_get): + * gst/udp/gstudpsrc.c: (gst_udpsrc_get): + Change gst_pad_proxy_link() to gst_pad_try_set_caps() + +2003-12-30 David Schleef + + * ext/ffmpeg/gstffmpegcolorspace.c: + (gst_ffmpegcsp_caps_remove_format_info), (gst_ffmpegcsp_getcaps), + (gst_ffmpegcsp_pad_link), (gst_ffmpegcsp_init), + (gst_ffmpegcsp_chain): Negotiation fixes + * ext/mad/gstmad.c: (gst_mad_chain): Negotiation fixes + * gst/audioconvert/gstaudioconvert.c: (gst_audio_convert_chain), + (gst_audio_convert_link), (gst_audio_convert_channels): + * gst/audioscale/gstaudioscale.c: (gst_audioscale_getcaps), + (gst_audioscale_link), (gst_audioscale_get_buffer), + (gst_audioscale_chain): Negotiation fixes + * gst/audioscale/gstaudioscale.h: + * gst/videofilter/gstvideofilter.c: + (gst_videofilter_format_get_structure), (gst_videofilter_getcaps), + (gst_videofilter_link), (gst_videofilter_init), + (gst_videofilter_set_output_size), (gst_videofilter_setup), + (gst_videofilter_find_format_by_structure): + * gst/videofilter/gstvideofilter.h: Negotiation fixes + * gst/videoscale/gstvideoscale.c: (gst_videoscale_getcaps), + (gst_videoscale_link): + * gst/videoscale/videoscale.c: (videoscale_get_structure), + (videoscale_find_by_structure), (gst_videoscale_setup): + * gst/videoscale/videoscale.h: Negotiation fixes + * sys/ximage/ximagesink.c: (gst_ximagesink_handle_xevents), + (gst_ximagesink_fixate), (gst_ximagesink_init): Add a fixate + function, restrict resizing to a multiple of 4 (hack until + everyone supports odd sizes correctly). + +2003-12-29 Colin Walters + + * ext/esd/esdsink.c (gst_esdsink_link): Fix typo; get depth instead of + signed. + +2003-12-30 Jan Schmidt + + * ext/sndfile/gstsf.c: (gst_sf_loop): + Fix warning about discarding const qualifier + +2003-12-27 Jeremy Simon + + * gst/cutter/gstcutter.c: + * gst/videoscale/gstvideoscale.c: + * gst/volenv/gstvolenv.c: + * gst-libs/gst/audio/audio.c: + * gst-libs/gst/video/video.c: + Fix warnings + +2003-12-27 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_open_audio): + Don't send ALSA debugging to stderr. + * ext/alsa/gstalsa.h: + Use GST_WARNING instead of g_warning when ALSA functions fail. + +2003-12-27 Benjamin Otte + + * sys/xvimage/xvimagesink.c: (gst_xvimagesink_get_xv_support): + Free XVAdapterInfo correctly. + +2003-12-27 Benjamin Otte + + * ext/mad/gstid3tag.c: (gst_id3_tag_add_src_pad), + (gst_id3_tag_do_caps_nego), (gst_id3_tag_src_link): + Make id3tag use correct caps nego. + +2003-12-27 Amaury Jacquot + + * ext/ivorbis/vorbis.c: + * ext/ivorbis/vorbisenc.h: + * ext/ivorbis/vorbisfile.c: + Modify so that it uses the new caps things + +2003-12-27 Benjamin Otte + + * testsuite/spider/spider1.c: (main): + * testsuite/spider/spider2.c: (main): + * testsuite/spider/spider3.c: (main): + Make tests compile again. They probably don't work. + +2003-12-24 Colin Walters + + * sys/oss/gstosssink.c (gst_osssink_sink_fixate): Return NULL if + we can't fixate the caps anymore. + +2003-12-23 David Schleef + + * gst/volume/gstvolume.c: (volume_init): Proxy getcaps. + * sys/oss/gstosssink.c: (gst_osssink_init), + (gst_osssink_sink_fixate): Add fixate function. + +2003-12-24 Ronald Bultje + + * ext/ffmpeg/gstffmpegcodecmap.c: + * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_getcaps), + (gst_ffmpegcsp_srcconnect_func), (gst_ffmpegcsp_sinkconnect), + (gst_ffmpegcsp_srcconnect), (gst_ffmpegcsp_get_type), + (gst_ffmpegcsp_base_init), (gst_ffmpegcsp_class_init), + (gst_ffmpegcsp_init), (gst_ffmpegcsp_chain), + (gst_ffmpegcsp_change_state), (gst_ffmpegcsp_set_property), + (gst_ffmpegcsp_get_property), (gst_ffmpegcsp_register): + fix typo in RGB masks, and move back to "old" colorspace + capsnego code until whoever wrote this new crap has actually + tested it so that it works. + And yes, this works, keep it that way please. + +2003-12-23 Ronald Bultje + + * ext/divx/gstdivxdec.c: (gst_divxdec_base_init), + (gst_divxdec_init), (gst_divxdec_negotiate): + * ext/divx/gstdivxdec.h: + * ext/divx/gstdivxenc.c: (gst_divxenc_base_init), + (gst_divxenc_init): + * ext/faac/gstfaac.c: (gst_faac_base_init), (gst_faac_init), + (gst_faac_sinkconnect), (gst_faac_srcconnect): + * ext/mpeg2enc/gstmpeg2enc.cc: + * ext/mpeg2enc/gstmpeg2encoder.cc: + * ext/mpeg2enc/gstmpeg2encpicturereader.cc: + * sys/dxr3/dxr3audiosink.c: (dxr3audiosink_base_init), + (dxr3audiosink_init), (dxr3audiosink_pcm_sinklink): + * sys/dxr3/dxr3spusink.c: (dxr3spusink_base_init), + (dxr3spusink_init): + * sys/dxr3/dxr3videosink.c: (dxr3videosink_base_init), + (dxr3videosink_init): + Fix caps breakage after Dave's caps branch merge. + +2003-12-23 Ronald Bultje + + * sys/ximage/ximagesink.c: (gst_ximagesink_xcontext_get): + Fix for 24bpp display. + +2003-12-23 Colin Walters + + * ext/gnomevfs/gstgnomevfssink.c: Add ARG_HANDLE property that takes + a GnomeVFSHandle directly. + +2003-12-22 Benjamin Otte + + * gst/volume/Makefile.am: + * gst/volume/gstvolume.c: (volume_connect), (volume_parse_caps), + (volume_base_init), (volume_init): + Reenable volume element and fix to work with new caps stuff. + Rhythmbox needs this. + +2003-12-22 Benjamin Otte + + * gst/qtdemux/qtdemux.c: (plugin_init): + qtdemux requires bytestream + +2003-12-22 Benjamin Otte + + * ext/alsa/gstalsa.c: (gst_alsa_get_caps), (gst_alsa_link): + Fix remaining caps handling errors due to CAPS merge. + +2003-12-22 Benjamin Otte + + * ext/faad/gstfaad.c: (gst_faad_base_init), (gst_faad_init), + (gst_faad_sinkconnect), (gst_faad_srcgetcaps), + (gst_faad_srcconnect): + Port to new caps system. + +2003-12-21 Julien MOUTTE + + * examples/gstplay/player.c: (got_time_tick), (got_stream_length), + (got_video_size), (main): using g_print instead of g_message. + * gst-libs/gst/play/gstplay.c: (gst_play_pipeline_setup): Fixing EOS + signal which was not emitted because of "switch" element added to the + bin but not connected. (Removing from the bin temporarily) + +2003-12-21 Julien MOUTTE + + * configure.ac: X_DISPLAY_MISSING is set to 1 if AC_PATH_XTRA fails to + find X development files. I don't understand the previous tests and + they fail on my debian/ppc unstable. This one works. + * examples/gstplay/player.c: (main): Set the pipeline to READY before + exiting. + * gst-libs/gst/play/gstplay.c: (gst_play_get_length_callback), + (gst_play_set_video_sink), (gst_play_set_audio_sink), + (gst_play_set_visualization): Add some safety checks in set_ methods + and state_change. This was throwing some ugly CRITICAL messages when + pipeline was getting disposed and casts were failing. + +2003-12-21 Ronald Bultje + + * configure.ac: + Improve mpeg2enc detection. This is for distributions that do + ship mjpegtools, but without mpeg2enc. Also does object check + for might there ever be ABI incompatibility. + * ext/mpeg2enc/gstmpeg2enc.cc: + Add Andrew as second maintainer (he's helping me), and also add + an error if no caps was set. This happens if I pull before capsnego + and that's something I should solve sometime else. + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_parse_blockgroup): + Fix time parsing. + * gst/matroska/matroska-mux.c: (gst_matroska_mux_audio_pad_link), + (gst_matroska_mux_track_header): + Add caps to templates. + * gst/mpegaudioparse/gstmpegaudioparse.c: (mp3_sink_factory): + Add mpegversion=1 to prevent confusion with MPEG/AAC. + * gst/mpegstream/gstmpegdemux.c: + Remove layer since it causes warnings about unfixed caps. + * gst/videotestsrc/gstvideotestsrc.c: (gst_videotestsrc_get): + Fix obvious typo (we error out if caps were set, we should of + course error out if *no* caps were set). + * sys/oss/gstosselement.c: (gst_osselement_convert): + Fix format conversion, we confused bits/bytes. + * sys/oss/gstosselement.h: + Improve documentation for 'bps'. + * sys/v4l/TODO: + Remove stuff about plugins that need removing - this was done + ages ago. + * sys/v4l/gstv4lmjpegsrc.c: (gst_v4lmjpegsrc_init), + (gst_v4lmjpegsrc_src_convert), (gst_v4lmjpegsrc_src_query): + * sys/v4l/gstv4lsrc.c: (gst_v4lsrc_init), (gst_v4lsrc_src_convert), + (gst_v4lsrc_src_query): + * sys/v4l2/gstv4l2src.c: (gst_v4l2src_init), + (gst_v4l2src_src_convert), (gst_v4l2src_src_query): + Add get_query_types(), get_formats() and query() functions. + +2003-12-21 Thomas Vander Stichele + + * ChangeLog: moved to gstreamer/docs/random/old/ChangeLog.gst-plugins + * moved CVS to freedesktop.org + diff --git a/gst-plugins-base-subtitles0.10/docs/random/LICENSE b/gst-plugins-base-subtitles0.10/docs/random/LICENSE new file mode 100644 index 0000000..1fedf92 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/random/LICENSE @@ -0,0 +1,18 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ diff --git a/gst-plugins-base-subtitles0.10/docs/version.entities.in b/gst-plugins-base-subtitles0.10/docs/version.entities.in new file mode 100644 index 0000000..79a6898 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/docs/version.entities.in @@ -0,0 +1,2 @@ + + diff --git a/gst-plugins-base-subtitles0.10/ext/Makefile.am b/gst-plugins-base-subtitles0.10/ext/Makefile.am new file mode 100644 index 0000000..b441978 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/Makefile.am @@ -0,0 +1,85 @@ +if USE_ALSA +ALSA_DIR=alsa +else +ALSA_DIR= +endif + +if USE_CDPARANOIA +CDPARANOIA_DIR=cdparanoia +else +CDPARANOIA_DIR= +endif + +if USE_GIO +GIO_DIR=gio +else +GIO_DIR= +endif + +if USE_GNOME_VFS +GNOMEVFS_DIR=gnomevfs +else +GNOMEVFS_DIR= +endif + +if USE_LIBVISUAL +LIBVISUAL_DIR=libvisual +else +LIBVISUAL_DIR= +endif + +if USE_OGG +OGG_DIR=ogg +else +OGG_DIR= +endif + +if USE_PANGO +PANGO_DIR = pango +else +PANGO_DIR = +endif + +if USE_VORBIS +VORBIS_DIR=vorbis +endif + +if USE_IVORBIS +VORBIS_DIR=vorbis +endif + +if !USE_VORBIS +if !USE_IVORBIS +VORBIS_DIR= +endif +endif + +if USE_THEORA +THEORA_DIR=theora +else +THEORA_DIR= +endif + +SUBDIRS = \ + $(ALSA_DIR) \ + $(CDPARANOIA_DIR) \ + $(GIO_DIR) \ + $(GNOMEVFS_DIR) \ + $(LIBVISUAL_DIR) \ + $(OGG_DIR) \ + $(PANGO_DIR) \ + $(THEORA_DIR) \ + $(VORBIS_DIR) + +DIST_SUBDIRS = \ + alsa \ + cdparanoia \ + gio \ + gnomevfs \ + libvisual \ + ogg \ + pango \ + theora \ + vorbis + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/Makefile.am b/gst-plugins-base-subtitles0.10/ext/alsa/Makefile.am new file mode 100644 index 0000000..38cde48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/Makefile.am @@ -0,0 +1,36 @@ +plugin_LTLIBRARIES = libgstalsa.la + +libgstalsa_la_SOURCES = \ + gstalsadeviceprobe.c \ + gstalsamixer.c \ + gstalsamixerelement.c \ + gstalsamixertrack.c \ + gstalsamixeroptions.c \ + gstalsaplugin.c \ + gstalsasink.c \ + gstalsasrc.c \ + gstalsa.c + +libgstalsa_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) \ + $(ALSA_CFLAGS) +libgstalsa_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(ALSA_LIBS) + +libgstalsa_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstalsa_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstalsa.h \ + gstalsadeviceprobe.h \ + gstalsamixer.h \ + gstalsamixerelement.h \ + gstalsamixertrack.h \ + gstalsamixeroptions.h \ + gstalsasrc.h \ + gstalsasink.h diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.c new file mode 100644 index 0000000..94ed44c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.c @@ -0,0 +1,571 @@ +/* Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "gstalsa.h" + +#include + +static GstCaps * +gst_alsa_detect_rates (GstObject * obj, snd_pcm_hw_params_t * hw_params, + GstCaps * in_caps) +{ + GstCaps *caps; + guint min, max; + gint err, dir, min_rate, max_rate, i; + + GST_LOG_OBJECT (obj, "probing sample rates ..."); + + if ((err = snd_pcm_hw_params_get_rate_min (hw_params, &min, &dir)) < 0) + goto min_rate_err; + + if ((err = snd_pcm_hw_params_get_rate_max (hw_params, &max, &dir)) < 0) + goto max_rate_err; + + min_rate = min; + max_rate = max; + + if (min_rate < 4000) + min_rate = 4000; /* random 'sensible minimum' */ + + if (max_rate <= 0) + max_rate = G_MAXINT; /* or maybe just use 192400 or so? */ + else if (max_rate > 0 && max_rate < 4000) + max_rate = MAX (4000, min_rate); + + GST_DEBUG_OBJECT (obj, "Min. rate = %u (%d)", min_rate, min); + GST_DEBUG_OBJECT (obj, "Max. rate = %u (%d)", max_rate, max); + + caps = gst_caps_make_writable (in_caps); + + for (i = 0; i < gst_caps_get_size (caps); ++i) { + GstStructure *s; + + s = gst_caps_get_structure (caps, i); + if (min_rate == max_rate) { + gst_structure_set (s, "rate", G_TYPE_INT, min_rate, NULL); + } else { + gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, + min_rate, max_rate, NULL); + } + } + + return caps; + + /* ERRORS */ +min_rate_err: + { + GST_ERROR_OBJECT (obj, "failed to query minimum sample rate: %s", + snd_strerror (err)); + gst_caps_unref (in_caps); + return NULL; + } +max_rate_err: + { + GST_ERROR_OBJECT (obj, "failed to query maximum sample rate: %s", + snd_strerror (err)); + gst_caps_unref (in_caps); + return NULL; + } +} + +static const struct +{ + const int width; + const int depth; + const int sformat; + const int uformat; +} pcmformats[] = { + { + 8, 8, SND_PCM_FORMAT_S8, SND_PCM_FORMAT_U8}, { + 16, 16, SND_PCM_FORMAT_S16, SND_PCM_FORMAT_U16}, { + 32, 24, SND_PCM_FORMAT_S24, SND_PCM_FORMAT_U24}, { +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) /* no endian-unspecific enum available */ + 24, 24, SND_PCM_FORMAT_S24_3LE, SND_PCM_FORMAT_U24_3LE}, { +#else + 24, 24, SND_PCM_FORMAT_S24_3BE, SND_PCM_FORMAT_U24_3BE}, { +#endif + 32, 32, SND_PCM_FORMAT_S32, SND_PCM_FORMAT_U32} +}; + +static GstCaps * +gst_alsa_detect_formats (GstObject * obj, snd_pcm_hw_params_t * hw_params, + GstCaps * in_caps) +{ + snd_pcm_format_mask_t *mask; + GstStructure *s; + GstCaps *caps; + gint i; + + snd_pcm_format_mask_malloc (&mask); + snd_pcm_hw_params_get_format_mask (hw_params, mask); + + caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (in_caps); ++i) { + GstStructure *scopy; + gint w, width = 0, depth = 0; + + s = gst_caps_get_structure (in_caps, i); + if (!gst_structure_has_name (s, "audio/x-raw-int")) { + GST_WARNING_OBJECT (obj, "skipping non-int format"); + continue; + } + if (!gst_structure_get_int (s, "width", &width) || + !gst_structure_get_int (s, "depth", &depth)) + continue; + if (width == 0 || (width % 8) != 0) + continue; /* Only full byte widths are valid */ + for (w = 0; w < G_N_ELEMENTS (pcmformats); w++) + if (pcmformats[w].width == width && pcmformats[w].depth == depth) + break; + if (w == G_N_ELEMENTS (pcmformats)) + continue; /* Unknown format */ + + if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat) && + snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) { + /* template contains { true, false } or just one, leave it as it is */ + scopy = gst_structure_copy (s); + } else if (snd_pcm_format_mask_test (mask, pcmformats[w].sformat)) { + scopy = gst_structure_copy (s); + gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + } else if (snd_pcm_format_mask_test (mask, pcmformats[w].uformat)) { + scopy = gst_structure_copy (s); + gst_structure_set (scopy, "signed", G_TYPE_BOOLEAN, FALSE, NULL); + } else { + scopy = NULL; + } + if (scopy) { + if (width > 8) { + /* TODO: proper endianness detection, for now it's CPU endianness only */ + gst_structure_set (scopy, "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); + } + gst_caps_append_structure (caps, scopy); + } + } + + snd_pcm_format_mask_free (mask); + gst_caps_unref (in_caps); + return caps; +} + +/* we don't have channel mappings for more than this many channels */ +#define GST_ALSA_MAX_CHANNELS 8 + +static GstStructure * +get_channel_free_structure (const GstStructure * in_structure) +{ + GstStructure *s = gst_structure_copy (in_structure); + + gst_structure_remove_field (s, "channels"); + return s; +} + +static void +caps_add_channel_configuration (GstCaps * caps, + const GstStructure * in_structure, gint min_chans, gint max_chans) +{ + GstAudioChannelPosition pos[8] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT + }; + GstStructure *s = NULL; + gint c; + + if (min_chans == max_chans && max_chans <= 2) { + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", G_TYPE_INT, max_chans, NULL); + gst_caps_append_structure (caps, s); + return; + } + + g_assert (min_chans >= 1); + + /* mono and stereo don't need channel configurations */ + if (min_chans == 2) { + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", G_TYPE_INT, 2, NULL); + gst_caps_append_structure (caps, s); + } else if (min_chans == 1 && max_chans >= 2) { + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 2, NULL); + gst_caps_append_structure (caps, s); + } + + /* don't know whether to use 2.1 or 3.0 here - but I suspect + * alsa might work around that/fix it somehow. Can we tell alsa + * what our channel layout is like? */ + if (max_chans >= 3 && min_chans <= 3) { + GstAudioChannelPosition pos_21[3] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE + }; + + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", G_TYPE_INT, 3, NULL); + gst_audio_set_channel_positions (s, pos_21); + gst_caps_append_structure (caps, s); + } + + /* everything else (4, 6, 8 channels) needs a channel layout */ + for (c = MAX (4, min_chans); c <= 8; c += 2) { + if (max_chans >= c) { + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", G_TYPE_INT, c, NULL); + gst_audio_set_channel_positions (s, pos); + gst_caps_append_structure (caps, s); + } + } + + for (c = MAX (9, min_chans); c <= max_chans; ++c) { + GstAudioChannelPosition *ch_layout; + guint i; + + ch_layout = g_new (GstAudioChannelPosition, c); + for (i = 0; i < c; ++i) { + ch_layout[i] = GST_AUDIO_CHANNEL_POSITION_NONE; + } + s = get_channel_free_structure (in_structure); + gst_structure_set (s, "channels", G_TYPE_INT, c, NULL); + gst_audio_set_channel_positions (s, ch_layout); + gst_caps_append_structure (caps, s); + g_free (ch_layout); + } +} + +static GstCaps * +gst_alsa_detect_channels (GstObject * obj, snd_pcm_hw_params_t * hw_params, + GstCaps * in_caps) +{ + GstCaps *caps; + guint min, max; + gint min_chans, max_chans; + gint err, i; + + GST_LOG_OBJECT (obj, "probing channels ..."); + + if ((err = snd_pcm_hw_params_get_channels_min (hw_params, &min)) < 0) + goto min_chan_error; + + if ((err = snd_pcm_hw_params_get_channels_max (hw_params, &max)) < 0) + goto max_chan_error; + + /* note: the above functions may return (guint) -1 */ + min_chans = min; + max_chans = max; + + if (min_chans < 0) { + min_chans = 1; + max_chans = GST_ALSA_MAX_CHANNELS; + } else if (max_chans < 0) { + max_chans = GST_ALSA_MAX_CHANNELS; + } + + if (min_chans > max_chans) { + gint temp; + + GST_WARNING_OBJECT (obj, "minimum channels > maximum channels (%d > %d), " + "please fix your soundcard drivers", min, max); + temp = min_chans; + min_chans = max_chans; + max_chans = temp; + } + + /* pro cards seem to return large numbers for min_channels */ + if (min_chans > GST_ALSA_MAX_CHANNELS) { + GST_DEBUG_OBJECT (obj, "min_chans = %u, looks like a pro card", min_chans); + if (max_chans < min_chans) { + max_chans = min_chans; + } else { + /* only support [max_chans; max_chans] for these cards for now + * to avoid inflating the source caps with loads of structures ... */ + min_chans = max_chans; + } + } else { + min_chans = MAX (min_chans, 1); + max_chans = MIN (GST_ALSA_MAX_CHANNELS, max_chans); + } + + GST_DEBUG_OBJECT (obj, "Min. channels = %d (%d)", min_chans, min); + GST_DEBUG_OBJECT (obj, "Max. channels = %d (%d)", max_chans, max); + + caps = gst_caps_new_empty (); + + for (i = 0; i < gst_caps_get_size (in_caps); ++i) { + GstStructure *s; + GType field_type; + gint c_min = min_chans; + gint c_max = max_chans; + + s = gst_caps_get_structure (in_caps, i); + /* the template caps might limit the number of channels (like alsasrc), + * in which case we don't want to return a superset, so hack around this + * for the two common cases where the channels are either a fixed number + * or a min/max range). Example: alsasrc template has channels = [1,2] and + * the detection will claim to support 8 channels for device 'plughw:0' */ + field_type = gst_structure_get_field_type (s, "channels"); + if (field_type == G_TYPE_INT) { + gst_structure_get_int (s, "channels", &c_min); + gst_structure_get_int (s, "channels", &c_max); + } else if (field_type == GST_TYPE_INT_RANGE) { + const GValue *val; + + val = gst_structure_get_value (s, "channels"); + c_min = CLAMP (gst_value_get_int_range_min (val), min_chans, max_chans); + c_max = CLAMP (gst_value_get_int_range_max (val), min_chans, max_chans); + } else { + c_min = min_chans; + c_max = max_chans; + } + + caps_add_channel_configuration (caps, s, c_min, c_max); + } + + gst_caps_unref (in_caps); + + return caps; + + /* ERRORS */ +min_chan_error: + { + GST_ERROR_OBJECT (obj, "failed to query minimum channel count: %s", + snd_strerror (err)); + return NULL; + } +max_chan_error: + { + GST_ERROR_OBJECT (obj, "failed to query maximum channel count: %s", + snd_strerror (err)); + return NULL; + } +} + +snd_pcm_t * +gst_alsa_open_iec958_pcm (GstObject * obj) +{ + char *iec958_pcm_name = NULL; + snd_pcm_t *pcm = NULL; + int res; + char devstr[256]; /* Storage for local 'default' device string */ + + /* + * Try and open our default iec958 device. Fall back to searching on card x + * if this fails, which should only happen on older alsa setups + */ + + /* The string will be one of these: + * SPDIF_CON: Non-audio flag not set: + * spdif:{AES0 0x0 AES1 0x82 AES2 0x0 AES3 0x2} + * SPDIF_CON: Non-audio flag set: + * spdif:{AES0 0x2 AES1 0x82 AES2 0x0 AES3 0x2} + */ + sprintf (devstr, + "iec958:{AES0 0x%02x AES1 0x%02x AES2 0x%02x AES3 0x%02x}", + IEC958_AES0_CON_EMPHASIS_NONE | IEC958_AES0_NONAUDIO, + IEC958_AES1_CON_ORIGINAL | IEC958_AES1_CON_PCM_CODER, + 0, IEC958_AES3_CON_FS_48000); + + GST_DEBUG_OBJECT (obj, "Generated device string \"%s\"", devstr); + iec958_pcm_name = devstr; + + res = snd_pcm_open (&pcm, iec958_pcm_name, SND_PCM_STREAM_PLAYBACK, 0); + if (G_UNLIKELY (res < 0)) { + GST_DEBUG_OBJECT (obj, "failed opening IEC958 device: %s", + snd_strerror (res)); + pcm = NULL; + } + + return pcm; +} + + +/* + * gst_alsa_probe_supported_formats: + * + * Takes the template caps and returns the subset which is actually + * supported by this device. + * + */ + +GstCaps * +gst_alsa_probe_supported_formats (GstObject * obj, snd_pcm_t * handle, + const GstCaps * template_caps) +{ + snd_pcm_hw_params_t *hw_params; + snd_pcm_stream_t stream_type; + GstCaps *caps; + gint err; + + snd_pcm_hw_params_malloc (&hw_params); + if ((err = snd_pcm_hw_params_any (handle, hw_params)) < 0) + goto error; + + stream_type = snd_pcm_stream (handle); + + caps = gst_caps_copy (template_caps); + + if (!(caps = gst_alsa_detect_formats (obj, hw_params, caps))) + goto subroutine_error; + + if (!(caps = gst_alsa_detect_rates (obj, hw_params, caps))) + goto subroutine_error; + + if (!(caps = gst_alsa_detect_channels (obj, hw_params, caps))) + goto subroutine_error; + + /* Try opening IEC958 device to see if we can support that format (playback + * only for now but we could add SPDIF capture later) */ + if (stream_type == SND_PCM_STREAM_PLAYBACK) { + snd_pcm_t *pcm = gst_alsa_open_iec958_pcm (obj); + + if (G_LIKELY (pcm)) { + gst_caps_append (caps, gst_caps_new_simple ("audio/x-iec958", NULL)); + snd_pcm_close (pcm); + } + } + + snd_pcm_hw_params_free (hw_params); + return caps; + + /* ERRORS */ +error: + { + GST_ERROR_OBJECT (obj, "failed to query formats: %s", snd_strerror (err)); + snd_pcm_hw_params_free (hw_params); + return NULL; + } +subroutine_error: + { + GST_ERROR_OBJECT (obj, "failed to query formats"); + snd_pcm_hw_params_free (hw_params); + return NULL; + } +} + +/* returns the card name when the device number is unknown or -1 */ +static gchar * +gst_alsa_find_device_name_no_handle (GstObject * obj, const gchar * devcard, + gint device_num, snd_pcm_stream_t stream) +{ + snd_ctl_card_info_t *info = NULL; + snd_ctl_t *ctl = NULL; + gchar *ret = NULL; + gint dev = -1; + + GST_LOG_OBJECT (obj, "[%s] device=%d", devcard, device_num); + + if (snd_ctl_open (&ctl, devcard, 0) < 0) + return NULL; + + snd_ctl_card_info_malloc (&info); + if (snd_ctl_card_info (ctl, info) < 0) + goto done; + + if (device_num != -1) { + while (snd_ctl_pcm_next_device (ctl, &dev) == 0 && dev >= 0) { + if (dev == device_num) { + snd_pcm_info_t *pcminfo; + + snd_pcm_info_malloc (&pcminfo); + snd_pcm_info_set_device (pcminfo, dev); + snd_pcm_info_set_subdevice (pcminfo, 0); + snd_pcm_info_set_stream (pcminfo, stream); + if (snd_ctl_pcm_info (ctl, pcminfo) < 0) { + snd_pcm_info_free (pcminfo); + break; + } + + ret = (gchar *) snd_pcm_info_get_name (pcminfo); + if (ret) { + ret = g_strdup (ret); + GST_LOG_OBJECT (obj, "name from pcminfo: %s", ret); + } + snd_pcm_info_free (pcminfo); + if (ret) + break; + } + } + } + + if (ret == NULL) { + char *name = NULL; + gint card; + + GST_LOG_OBJECT (obj, "trying card name"); + card = snd_ctl_card_info_get_card (info); + snd_card_get_name (card, &name); + ret = g_strdup (name); + free (name); + } + +done: + snd_ctl_card_info_free (info); + snd_ctl_close (ctl); + + return ret; +} + +gchar * +gst_alsa_find_card_name (GstObject * obj, const gchar * devcard, + snd_pcm_stream_t stream) +{ + return gst_alsa_find_device_name_no_handle (obj, devcard, -1, stream); +} + +gchar * +gst_alsa_find_device_name (GstObject * obj, const gchar * device, + snd_pcm_t * handle, snd_pcm_stream_t stream) +{ + gchar *ret = NULL; + + if (device != NULL) { + gchar *dev, *comma; + gint devnum; + + GST_LOG_OBJECT (obj, "Trying to get device name from string '%s'", device); + + /* only want name:card bit, but not devices and subdevices */ + dev = g_strdup (device); + if ((comma = strchr (dev, ','))) { + *comma = '\0'; + devnum = atoi (comma + 1); + ret = gst_alsa_find_device_name_no_handle (obj, dev, devnum, stream); + } + g_free (dev); + } + + if (ret == NULL && handle != NULL) { + snd_pcm_info_t *info; + + GST_LOG_OBJECT (obj, "Trying to get device name from open handle"); + snd_pcm_info_malloc (&info); + snd_pcm_info (handle, info); + ret = g_strdup (snd_pcm_info_get_name (info)); + snd_pcm_info_free (info); + } + + GST_LOG_OBJECT (obj, "Device name for device '%s': %s", + GST_STR_NULL (device), GST_STR_NULL (ret)); + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.h new file mode 100644 index 0000000..92466d2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsa.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2001 CodeFactory AB + * Copyright (C) 2001 Thomas Nyberg + * Copyright (C) 2001-2002 Andy Wingo + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __GST_ALSA_H__ +#define __GST_ALSA_H__ + + +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API + +#include +#include +#include +#include + +#define GST_CHECK_ALSA_VERSION(major,minor,micro) \ + (SND_LIB_MAJOR > (major) || \ + (SND_LIB_MAJOR == (major) && SND_LIB_MINOR > (minor)) || \ + (SND_LIB_MAJOR == (major) && SND_LIB_MINOR == (minor) && \ + SND_LIB_SUBMINOR >= (micro))) + +GST_DEBUG_CATEGORY_EXTERN (alsa_debug); +#define GST_CAT_DEFAULT alsa_debug + +snd_pcm_t * gst_alsa_open_iec958_pcm (GstObject * obj); + +GstCaps * gst_alsa_probe_supported_formats (GstObject * obj, + snd_pcm_t * handle, + const GstCaps * template_caps); + +gchar * gst_alsa_find_device_name (GstObject * obj, + const gchar * device, + snd_pcm_t * handle, + snd_pcm_stream_t stream); + +gchar * gst_alsa_find_card_name (GstObject * obj, + const gchar * devcard, + snd_pcm_stream_t stream); + + +#endif /* __GST_ALSA_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.c new file mode 100644 index 0000000..83596a3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.c @@ -0,0 +1,210 @@ +/* Copyright (C) 2001 CodeFactory AB + * Copyright (C) 2001 Thomas Nyberg + * Copyright (C) 2001-2002 Andy Wingo + * Copyright (C) 2003 Benjamin Otte + * Copyright (C) 2005 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstalsadeviceprobe.h" +#include "gst/interfaces/propertyprobe.h" + +static const GList * +gst_alsa_device_property_probe_get_properties (GstPropertyProbe * probe) +{ + GObjectClass *klass = G_OBJECT_GET_CLASS (probe); + static GList *list = NULL; + + /* well, not perfect, but better than no locking at all. + * In the worst case we leak a list node, so who cares? */ + GST_CLASS_LOCK (GST_OBJECT_CLASS (klass)); + + if (!list) { + GParamSpec *pspec; + + pspec = g_object_class_find_property (klass, "device"); + list = g_list_append (NULL, pspec); + } + + GST_CLASS_UNLOCK (GST_OBJECT_CLASS (klass)); + + return list; +} + +static GList * +gst_alsa_get_device_list (snd_pcm_stream_t stream) +{ + snd_ctl_t *handle; + int card, dev; + snd_ctl_card_info_t *info; + snd_pcm_info_t *pcminfo; + gboolean mixer = (stream == -1); + GList *list = NULL; + + if (stream == -1) + stream = 0; + + snd_ctl_card_info_malloc (&info); + snd_pcm_info_malloc (&pcminfo); + card = -1; + + if (snd_card_next (&card) < 0 || card < 0) { + /* no soundcard found */ + GST_WARNING ("No soundcard found"); + goto beach; + } + + while (card >= 0) { + gchar name[32]; + + g_snprintf (name, sizeof (name), "hw:%d", card); + if (snd_ctl_open (&handle, name, 0) < 0) { + goto next_card; + } + if (snd_ctl_card_info (handle, info) < 0) { + snd_ctl_close (handle); + goto next_card; + } + + if (mixer) { + list = g_list_append (list, g_strdup (name)); + } else { + dev = -1; + while (1) { + gchar *gst_device; + + snd_ctl_pcm_next_device (handle, &dev); + + if (dev < 0) + break; + snd_pcm_info_set_device (pcminfo, dev); + snd_pcm_info_set_subdevice (pcminfo, 0); + snd_pcm_info_set_stream (pcminfo, stream); + if (snd_ctl_pcm_info (handle, pcminfo) < 0) { + continue; + } + + gst_device = g_strdup_printf ("hw:%d,%d", card, dev); + list = g_list_append (list, gst_device); + } + } + snd_ctl_close (handle); + next_card: + if (snd_card_next (&card) < 0) { + break; + } + } + +beach: + snd_ctl_card_info_free (info); + snd_pcm_info_free (pcminfo); + + return list; +} + +static void +gst_alsa_device_property_probe_probe_property (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + if (!g_str_equal (pspec->name, "device")) { + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + } +} + +static gboolean +gst_alsa_device_property_probe_needs_probe (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + /* don't cache probed data */ + return TRUE; +} + +static GValueArray * +gst_alsa_device_property_probe_get_values (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstElementClass *klass; + const GList *templates; + snd_pcm_stream_t mode = -1; + GValueArray *array; + GValue value = { 0, }; + GList *l, *list; + + if (!g_str_equal (pspec->name, "device")) { + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + return NULL; + } + + klass = GST_ELEMENT_GET_CLASS (GST_ELEMENT (probe)); + + /* I'm pretty sure ALSA has a good way to do this. However, their cool + * auto-generated documentation is pretty much useless if you try to + * do function-wise look-ups. */ + /* we assume one pad template at max [zero=mixer] */ + templates = gst_element_class_get_pad_template_list (klass); + if (templates) { + if (GST_PAD_TEMPLATE_DIRECTION (templates->data) == GST_PAD_SRC) + mode = SND_PCM_STREAM_CAPTURE; + else + mode = SND_PCM_STREAM_PLAYBACK; + } + + list = gst_alsa_get_device_list (mode); + + if (list == NULL) { + GST_LOG_OBJECT (probe, "No devices found"); + return NULL; + } + + array = g_value_array_new (g_list_length (list)); + g_value_init (&value, G_TYPE_STRING); + for (l = list; l != NULL; l = l->next) { + GST_LOG_OBJECT (probe, "Found device: %s", (gchar *) l->data); + g_value_take_string (&value, (gchar *) l->data); + l->data = NULL; + g_value_array_append (array, &value); + } + g_value_unset (&value); + g_list_free (list); + + return array; +} + +static void +gst_alsa_property_probe_interface_init (GstPropertyProbeInterface * iface) +{ + iface->get_properties = gst_alsa_device_property_probe_get_properties; + iface->probe_property = gst_alsa_device_property_probe_probe_property; + iface->needs_probe = gst_alsa_device_property_probe_needs_probe; + iface->get_values = gst_alsa_device_property_probe_get_values; +} + +void +gst_alsa_type_add_device_property_probe_interface (GType type) +{ + static const GInterfaceInfo probe_iface_info = { + (GInterfaceInitFunc) gst_alsa_property_probe_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_PROPERTY_PROBE, + &probe_iface_info); +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.h new file mode 100644 index 0000000..b60b0fe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsadeviceprobe.h @@ -0,0 +1,33 @@ +/* Copyright (C) 2001 CodeFactory AB + * Copyright (C) 2001 Thomas Nyberg + * Copyright (C) 2001-2002 Andy Wingo + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __GST_ALSA_DEVICE_PROBE_H__ +#define __GST_ALSA_DEVICE_PROBE_H__ + +#include "gstalsa.h" + +G_BEGIN_DECLS + +void gst_alsa_type_add_device_property_probe_interface (GType type); + +G_END_DECLS + +#endif /* __GST_ALSA_DEVICE_PROBE_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.c new file mode 100644 index 0000000..b30a7bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.c @@ -0,0 +1,957 @@ +/* ALSA mixer implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-alsamixer + * @see_also: alsasink, alsasrc + * + * This element controls various aspects such as the volume and balance + * of an audio device using the ALSA api. + * + * The application should query and use the interfaces provided by this + * element to control the device. + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstalsamixer.h" +#include + +static void gst_alsa_mixer_update_option (GstAlsaMixer * mixer, + GstAlsaMixerOptions * alsa_opts); +static void gst_alsa_mixer_update_track (GstAlsaMixer * mixer, + GstAlsaMixerTrack * alsa_track); +static int gst_alsa_mixer_handle_callback (snd_mixer_t * handle, + unsigned int mask, snd_mixer_elem_t * elem); + +/* First some utils, then the mixer implementation */ +static gboolean +gst_alsa_mixer_open (GstAlsaMixer * mixer) +{ + gint err; + snd_ctl_t *ctl; + snd_ctl_card_info_t *card_info; + + g_return_val_if_fail (mixer->handle == NULL, FALSE); + + /* open and initialize the mixer device */ + err = snd_mixer_open (&mixer->handle, 0); + if (err < 0 || mixer->handle == NULL) + goto open_failed; + + if ((err = snd_mixer_attach (mixer->handle, mixer->device)) < 0) { + GST_WARNING ("Cannot open mixer for sound device '%s': %s", mixer->device, + snd_strerror (err)); + goto error; + } + + if ((err = snd_mixer_selem_register (mixer->handle, NULL, NULL)) < 0) { + GST_WARNING ("Cannot register mixer elements: %s", snd_strerror (err)); + goto error; + } + + if ((err = snd_mixer_load (mixer->handle)) < 0) { + GST_WARNING ("Cannot load mixer settings: %s", snd_strerror (err)); + goto error; + } + + snd_mixer_set_callback_private (mixer->handle, mixer); + snd_mixer_set_callback (mixer->handle, gst_alsa_mixer_handle_callback); + + /* now get the device name, any of this is not fatal */ + g_free (mixer->cardname); + if ((err = snd_ctl_open (&ctl, mixer->device, 0)) < 0) { + GST_WARNING ("Cannot open CTL: %s", snd_strerror (err)); + goto no_card_name; + } + + snd_ctl_card_info_malloc (&card_info); + if ((err = snd_ctl_card_info (ctl, card_info)) < 0) { + GST_WARNING ("Cannot get card info: %s", snd_strerror (err)); + snd_ctl_close (ctl); + goto no_card_name; + } + + mixer->cardname = g_strdup (snd_ctl_card_info_get_name (card_info)); + GST_DEBUG ("Card name = %s", GST_STR_NULL (mixer->cardname)); + snd_ctl_card_info_free (card_info); + snd_ctl_close (ctl); + +no_card_name: + if (mixer->cardname == NULL) { + mixer->cardname = g_strdup ("Unknown"); + GST_DEBUG ("Cannot find card name"); + } + + GST_INFO ("Successfully opened mixer for device '%s'.", mixer->device); + + return TRUE; + + /* ERROR */ +open_failed: + { + GST_WARNING ("Cannot open mixer: %s", snd_strerror (err)); + mixer->handle = NULL; + return FALSE; + } +error: + { + snd_mixer_close (mixer->handle); + mixer->handle = NULL; + return FALSE; + } +} + +static snd_mixer_elem_t * +gst_alsa_mixer_find_master_mixer (GstAlsaMixer * mixer, snd_mixer_t * handle) +{ + snd_mixer_elem_t *element; + gint i, count; + + count = snd_mixer_get_count (handle); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + /* Check if we have a playback mixer labelled as 'Master' */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + strcmp (snd_mixer_selem_get_name (element), "Master") == 0) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, check if we have a playback mixer labelled as 'Front' */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + strcmp (snd_mixer_selem_get_name (element), "Front") == 0) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, check if we have a playback mixer labelled as 'PCM' */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + strcmp (snd_mixer_selem_get_name (element), "PCM") == 0) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, check if we have a playback mixer labelled as 'Speaker' */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + strcmp (snd_mixer_selem_get_name (element), "Speaker") == 0) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, check if we have a playback mixer with both volume and switch that + * is not mono */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + snd_mixer_selem_has_playback_switch (element) && + !snd_mixer_selem_is_playback_mono (element)) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, check if we have any playback mixer with both volume and switch */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element) && + snd_mixer_selem_has_playback_switch (element)) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + /* If not, take any playback mixer with a volume control */ + element = snd_mixer_first_elem (handle); + for (i = 0; i < count; i++) { + if (snd_mixer_selem_has_playback_volume (element)) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return element; + } + element = snd_mixer_elem_next (element); + } + + g_static_rec_mutex_unlock (mixer->rec_mutex); + /* Looks like we're out of luck ... */ + return NULL; +} + +static void +gst_alsa_mixer_update (GstAlsaMixer * mixer, snd_mixer_elem_t * elem) +{ + GList *item; + + g_return_if_fail (mixer != NULL); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + for (item = mixer->tracklist; item != NULL; item = item->next) { + if (GST_IS_ALSA_MIXER_TRACK (item->data)) { + if (elem && (GST_ALSA_MIXER_TRACK (item->data)->element != elem)) + continue; + + gst_alsa_mixer_update_track (mixer, GST_ALSA_MIXER_TRACK (item->data)); + } else if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) { + if (elem && (GST_ALSA_MIXER_OPTIONS (item->data)->element != elem)) + continue; + + gst_alsa_mixer_update_option (mixer, GST_ALSA_MIXER_OPTIONS (item->data)); + } + } + + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +static int +gst_alsa_mixer_elem_handle_callback (snd_mixer_elem_t * elem, unsigned int mask) +{ + GstAlsaMixer *mixer = + (GstAlsaMixer *) snd_mixer_elem_get_callback_private (elem); + + GST_LOG ("ALSA elem cb"); + + g_return_val_if_fail (mixer != NULL, 1); + + gst_alsa_mixer_update (mixer, elem); + + return 0; +} + +static int +gst_alsa_mixer_handle_callback (snd_mixer_t * handle, unsigned int mask, + snd_mixer_elem_t * elem) +{ + GstAlsaMixer *mixer = + (GstAlsaMixer *) snd_mixer_get_callback_private (handle); + + GST_LOG ("ALSA cb"); + + g_return_val_if_fail (mixer != NULL, 1); + + /* Hopefully won't be call recursively and will handle pending elem events */ + snd_mixer_handle_events (mixer->handle); + + gst_alsa_mixer_update (mixer, elem); + + return 0; +} + +static void +gst_alsa_mixer_ensure_track_list (GstAlsaMixer * mixer) +{ + gint i, count; + snd_mixer_elem_t *element, *master; + GList *item; + + g_return_if_fail (mixer->handle != NULL); + + if (mixer->tracklist) + return; + + g_static_rec_mutex_lock (mixer->rec_mutex); + + master = gst_alsa_mixer_find_master_mixer (mixer, mixer->handle); + + count = snd_mixer_get_count (mixer->handle); + element = snd_mixer_first_elem (mixer->handle); + + /* build track list + * + * Some ALSA tracks may have playback and capture capabilities. + * Here we model them as two separate GStreamer tracks. + */ + + for (i = 0; i < count; i++) { + GstMixerTrack *play_track = NULL; + GstMixerTrack *cap_track = NULL; + const gchar *name; + GList *item; + gint samename = 0; + + name = snd_mixer_selem_get_name (element); + + /* prevent dup names */ + for (item = mixer->tracklist; item != NULL; item = item->next) { + snd_mixer_elem_t *temp; + + if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) + temp = GST_ALSA_MIXER_OPTIONS (item->data)->element; + else + temp = GST_ALSA_MIXER_TRACK (item->data)->element; + + if (strcmp (name, snd_mixer_selem_get_name (temp)) == 0) + samename++; + } + + GST_LOG ("[%s] probing element #%u, mixer->dir=%u", name, i, mixer->dir); + + if (mixer->dir & GST_ALSA_MIXER_PLAYBACK) { + gboolean has_playback_switch, has_playback_volume; + + has_playback_switch = snd_mixer_selem_has_playback_switch (element); + has_playback_volume = snd_mixer_selem_has_playback_volume (element); + + GST_LOG ("[%s] PLAYBACK: has_playback_volume=%d, has_playback_switch=%d" + "%s", name, has_playback_volume, has_playback_switch, + (element == master) ? " MASTER" : ""); + + if (has_playback_volume) { + gint flags = GST_MIXER_TRACK_OUTPUT; + + if (element == master) + flags |= GST_MIXER_TRACK_MASTER; + + play_track = gst_alsa_mixer_track_new (element, samename, i, + flags, FALSE, NULL, FALSE); + + } else if (has_playback_switch) { + /* simple mute switch */ + play_track = gst_alsa_mixer_track_new (element, samename, i, + GST_MIXER_TRACK_OUTPUT, TRUE, NULL, FALSE); + } + + if (snd_mixer_selem_is_enumerated (element)) { + GstMixerOptions *opts = gst_alsa_mixer_options_new (element, i); + + GST_LOG ("[%s] is enumerated (%d)", name, i); + mixer->tracklist = g_list_append (mixer->tracklist, opts); + } + } + + if (mixer->dir & GST_ALSA_MIXER_CAPTURE) { + gboolean has_capture_switch, has_common_switch; + gboolean has_capture_volume, has_common_volume; + + has_capture_switch = snd_mixer_selem_has_capture_switch (element); + has_common_switch = snd_mixer_selem_has_common_switch (element); + has_capture_volume = snd_mixer_selem_has_capture_volume (element); + has_common_volume = snd_mixer_selem_has_common_volume (element); + + GST_LOG ("[%s] CAPTURE: has_capture_volume=%d, has_common_volume=%d, " + "has_capture_switch=%d, has_common_switch=%d, play_track=%p", name, + has_capture_volume, has_common_volume, has_capture_switch, + has_common_switch, play_track); + + if (has_capture_volume && !(play_track && has_common_volume)) { + cap_track = gst_alsa_mixer_track_new (element, samename, i, + GST_MIXER_TRACK_INPUT, FALSE, NULL, play_track != NULL); + } else if (has_capture_switch && !(play_track && has_common_switch)) { + cap_track = gst_alsa_mixer_track_new (element, samename, i, + GST_MIXER_TRACK_INPUT, TRUE, NULL, play_track != NULL); + } + } + + + if (play_track && cap_track) { + GST_ALSA_MIXER_TRACK (play_track)->shared_mute = + GST_ALSA_MIXER_TRACK (cap_track); + GST_ALSA_MIXER_TRACK (cap_track)->shared_mute = + GST_ALSA_MIXER_TRACK (play_track); + } + + if (play_track) + mixer->tracklist = g_list_append (mixer->tracklist, play_track); + + if (cap_track) + mixer->tracklist = g_list_append (mixer->tracklist, cap_track); + + element = snd_mixer_elem_next (element); + } + + for (item = mixer->tracklist; item != NULL; item = item->next) { + snd_mixer_elem_t *temp; + + if (GST_IS_ALSA_MIXER_OPTIONS (item->data)) + temp = GST_ALSA_MIXER_OPTIONS (item->data)->element; + else + temp = GST_ALSA_MIXER_TRACK (item->data)->element; + + snd_mixer_elem_set_callback (temp, gst_alsa_mixer_elem_handle_callback); + snd_mixer_elem_set_callback_private (temp, mixer); + } + + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +static void +task_monitor_alsa (gpointer data) +{ + struct pollfd *pfds; + int nfds, rnfds; + unsigned short revents; + GstAlsaMixer *mixer = (GstAlsaMixer *) data; + gint ret; + + g_static_rec_mutex_lock (mixer->rec_mutex); + + nfds = snd_mixer_poll_descriptors_count (mixer->handle); + if (nfds <= 0) { + GST_ERROR ("snd_mixer_poll_descriptors_count <= 0: %d", nfds); + /* FIXME: sleep ? stop monitoring ? */ + g_static_rec_mutex_unlock (mixer->rec_mutex); + return; + } + + pfds = g_newa (struct pollfd, nfds + 1); + rnfds = snd_mixer_poll_descriptors (mixer->handle, pfds, nfds); + g_assert (rnfds <= nfds); + + if (rnfds < 0) { + GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), ("alsa error: %s", + snd_strerror (rnfds))); + gst_task_pause (mixer->task); + g_static_rec_mutex_unlock (mixer->rec_mutex); + return; + } + + pfds[rnfds].fd = mixer->pfd[0]; + pfds[rnfds].events = POLLIN | POLLPRI | POLLHUP | POLLERR; + pfds[rnfds].revents = 0; + + g_static_rec_mutex_unlock (mixer->rec_mutex); + + GST_LOG ("task loop"); + ret = poll (pfds, rnfds + 1, -1); + + if (ret < 0) { + GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + gst_task_pause (mixer->task); + return; + } + + g_static_rec_mutex_lock (mixer->rec_mutex); + + ret = + snd_mixer_poll_descriptors_revents (mixer->handle, pfds, nfds, &revents); + if (ret < 0) { + GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), ("alsa error: %s", + snd_strerror (ret))); + gst_task_pause (mixer->task); + } else if (revents & (POLLIN | POLLPRI)) { + GST_DEBUG ("Handling events"); + snd_mixer_handle_events (mixer->handle); + } else if (revents & (POLLERR | POLLNVAL | POLLHUP)) { + GST_ELEMENT_ERROR (mixer, RESOURCE, READ, (NULL), (NULL)); + gst_task_pause (mixer->task); + } + + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +/* API */ + +GstAlsaMixer * +gst_alsa_mixer_new (const char *device, GstAlsaMixerDirection dir) +{ + GstAlsaMixer *ret = NULL; + + g_return_val_if_fail (device != NULL, NULL); + + ret = g_new0 (GstAlsaMixer, 1); + + if (pipe (ret->pfd) == -1) + goto error; + + ret->rec_mutex = g_new (GStaticRecMutex, 1); + g_static_rec_mutex_init (ret->rec_mutex); + + ret->task_mutex = g_new (GStaticRecMutex, 1); + g_static_rec_mutex_init (ret->task_mutex); + + ret->task = gst_task_create (task_monitor_alsa, ret); + gst_task_set_lock (ret->task, ret->task_mutex); + + ret->device = g_strdup (device); + ret->dir = dir; + + if (!gst_alsa_mixer_open (ret)) + goto error; + + if (gst_task_start (ret->task) == FALSE) { + GST_WARNING ("Could not start alsamixer task"); + } + + return ret; + + /* ERRORS */ +error: + { + gst_alsa_mixer_free (ret); + return NULL; + } +} + +void +gst_alsa_mixer_free (GstAlsaMixer * mixer) +{ + g_return_if_fail (mixer != NULL); + + if (mixer->task) { + if (write (mixer->pfd[1], "stop", 5) <= 0) { + GST_ERROR ("Cannot send " "stop" " to alsamixer task"); + close (mixer->pfd[1]); + mixer->pfd[1] = -1; + } + + if (gst_task_join (mixer->task) == FALSE) { + GST_ERROR ("Cannot join alsamixer task"); + } + + gst_object_unref (mixer->task); + mixer->task = NULL; + } + + g_static_rec_mutex_free (mixer->task_mutex); + g_free (mixer->task_mutex); + mixer->task_mutex = NULL; + + if (mixer->pfd[0] > 0) { + close (mixer->pfd[0]); + mixer->pfd[0] = -1; + } + + if (mixer->pfd[1] > 0) { + close (mixer->pfd[1]); + mixer->pfd[1] = -1; + } + + if (mixer->interface) { + g_object_unref (G_OBJECT (mixer->interface)); + mixer->interface = NULL; + } + + if (mixer->device) { + g_free (mixer->device); + mixer->device = NULL; + } + + if (mixer->cardname) { + g_free (mixer->cardname); + mixer->cardname = NULL; + } + + if (mixer->tracklist) { + g_list_foreach (mixer->tracklist, (GFunc) g_object_unref, NULL); + g_list_free (mixer->tracklist); + mixer->tracklist = NULL; + } + + if (mixer->handle) { + snd_mixer_close (mixer->handle); + mixer->handle = NULL; + } + + g_static_rec_mutex_free (mixer->rec_mutex); + g_free (mixer->rec_mutex); + mixer->rec_mutex = NULL; + + g_free (mixer); +} + +const GList * +gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer) +{ + g_return_val_if_fail (mixer->handle != NULL, NULL); + + gst_alsa_mixer_ensure_track_list (mixer); + + return (const GList *) mixer->tracklist; +} + +void +gst_alsa_mixer_get_volume (GstAlsaMixer * mixer, GstMixerTrack * track, + gint * volumes) +{ + gint i; + GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track); + + g_return_if_fail (mixer->handle != NULL); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + gst_alsa_mixer_track_update (alsa_track); + + if (track->flags & GST_MIXER_TRACK_OUTPUT) { /* return playback volume */ + + /* Is emulated mute flag activated? */ + if (track->flags & GST_MIXER_TRACK_MUTE && + !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) { + for (i = 0; i < track->num_channels; i++) + volumes[i] = alsa_track->volumes[i]; + } else { + for (i = 0; i < track->num_channels; i++) { + long tmp = 0; + + snd_mixer_selem_get_playback_volume (alsa_track->element, i, &tmp); + alsa_track->volumes[i] = volumes[i] = (gint) tmp; + } + } + + } else if (track->flags & GST_MIXER_TRACK_INPUT) { /* return capture volume */ + + /* Is emulated record flag activated? */ + if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH || + track->flags & GST_MIXER_TRACK_RECORD) { + for (i = 0; i < track->num_channels; i++) { + long tmp = 0; + + snd_mixer_selem_get_capture_volume (alsa_track->element, i, &tmp); + alsa_track->volumes[i] = volumes[i] = (gint) tmp; + } + } else { + for (i = 0; i < track->num_channels; i++) + volumes[i] = alsa_track->volumes[i]; + } + } + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +static gboolean +check_if_volumes_are_the_same (guint num_channels, gint * volumes) +{ + guint i; + + if (num_channels <= 1) + return TRUE; + + for (i = 1; i < num_channels; i++) { + if (volumes[i] != volumes[0]) + return FALSE; + } + + return TRUE; +} + +void +gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, GstMixerTrack * track, + gint * volumes) +{ + GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track); + gint i; + + g_return_if_fail (mixer->handle != NULL); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + gst_alsa_mixer_track_update (alsa_track); + + if (track->flags & GST_MIXER_TRACK_OUTPUT) { + + /* Is emulated mute flag activated? */ + if (track->flags & GST_MIXER_TRACK_MUTE && + !(alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH)) { + for (i = 0; i < track->num_channels; i++) + alsa_track->volumes[i] = volumes[i]; + } else { + if (check_if_volumes_are_the_same (track->num_channels, volumes)) { + snd_mixer_selem_set_playback_volume_all (alsa_track->element, + volumes[0]); + for (i = 0; i < track->num_channels; i++) + alsa_track->volumes[i] = volumes[0]; + } else { + for (i = 0; i < track->num_channels; i++) { + alsa_track->volumes[i] = volumes[i]; + snd_mixer_selem_set_playback_volume (alsa_track->element, i, + volumes[i]); + } + } + } + + } else if (track->flags & GST_MIXER_TRACK_INPUT) { + + /* Is emulated record flag activated? */ + if (track->flags & GST_MIXER_TRACK_RECORD || + alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) { + if (check_if_volumes_are_the_same (track->num_channels, volumes)) { + snd_mixer_selem_set_capture_volume_all (alsa_track->element, + volumes[0]); + for (i = 0; i < track->num_channels; i++) + alsa_track->volumes[i] = volumes[0]; + } else { + for (i = 0; i < track->num_channels; i++) { + alsa_track->volumes[i] = volumes[i]; + snd_mixer_selem_set_capture_volume (alsa_track->element, i, + volumes[i]); + } + } + } else { + for (i = 0; i < track->num_channels; i++) + alsa_track->volumes[i] = volumes[i]; + } + } + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +void +gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, GstMixerTrack * track, + gboolean mute) +{ + GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track); + + g_return_if_fail (mixer->handle != NULL); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + gst_alsa_mixer_track_update (alsa_track); + + if (! !(mute) == ! !(track->flags & GST_MIXER_TRACK_MUTE)) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return; + } + if (mute) { + track->flags |= GST_MIXER_TRACK_MUTE; + + if (alsa_track->shared_mute) + ((GstMixerTrack *) (alsa_track->shared_mute))->flags |= + GST_MIXER_TRACK_MUTE; + } else { + track->flags &= ~GST_MIXER_TRACK_MUTE; + + if (alsa_track->shared_mute) + ((GstMixerTrack *) (alsa_track->shared_mute))->flags &= + ~GST_MIXER_TRACK_MUTE; + } + + if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_PSWITCH) { + snd_mixer_selem_set_playback_switch_all (alsa_track->element, mute ? 0 : 1); + } else { + gint i; + GstAlsaMixerTrack *ctrl_track; + + if ((track->flags & GST_MIXER_TRACK_INPUT) + && alsa_track->shared_mute != NULL) + ctrl_track = alsa_track->shared_mute; + else + ctrl_track = alsa_track; + + for (i = 0; i < ((GstMixerTrack *) ctrl_track)->num_channels; i++) { + long vol = + mute ? ((GstMixerTrack *) ctrl_track)-> + min_volume : ctrl_track->volumes[i]; + snd_mixer_selem_set_playback_volume (ctrl_track->element, i, vol); + } + } + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +void +gst_alsa_mixer_set_record (GstAlsaMixer * mixer, + GstMixerTrack * track, gboolean record) +{ + GstAlsaMixerTrack *alsa_track = GST_ALSA_MIXER_TRACK (track); + + g_return_if_fail (mixer->handle != NULL); + + g_static_rec_mutex_lock (mixer->rec_mutex); + + gst_alsa_mixer_track_update (alsa_track); + + if (! !(record) == ! !(track->flags & GST_MIXER_TRACK_RECORD)) { + g_static_rec_mutex_unlock (mixer->rec_mutex); + return; + } + + if (record) { + track->flags |= GST_MIXER_TRACK_RECORD; + } else { + track->flags &= ~GST_MIXER_TRACK_RECORD; + } + + if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH) { + snd_mixer_selem_set_capture_switch_all (alsa_track->element, + record ? 1 : 0); + + /* update all tracks in same exlusive cswitch group */ + if (alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL) { + GList *item; + + for (item = mixer->tracklist; item != NULL; item = item->next) { + + if (GST_IS_ALSA_MIXER_TRACK (item->data)) { + GstAlsaMixerTrack *item_alsa_track = + GST_ALSA_MIXER_TRACK (item->data); + + if (item_alsa_track->alsa_flags & GST_ALSA_MIXER_TRACK_CSWITCH_EXCL && + item_alsa_track->capture_group == alsa_track->capture_group) { + gst_alsa_mixer_track_update (item_alsa_track); + } + } + } + } + } else { + gint i; + + for (i = 0; i < track->num_channels; i++) { + long vol = record ? alsa_track->volumes[i] : track->min_volume; + + snd_mixer_selem_set_capture_volume (alsa_track->element, i, vol); + } + } + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +void +gst_alsa_mixer_set_option (GstAlsaMixer * mixer, + GstMixerOptions * opts, gchar * value) +{ + gint idx = -1, n = 0; + GList *item; + GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts); + + g_return_if_fail (mixer->handle != NULL); + + for (item = opts->values; item != NULL; item = item->next, n++) { + if (!strcmp (item->data, value)) { + idx = n; + break; + } + } + if (idx == -1) + return; + + g_static_rec_mutex_lock (mixer->rec_mutex); + snd_mixer_selem_set_enum_item (alsa_opts->element, 0, idx); + g_static_rec_mutex_unlock (mixer->rec_mutex); +} + +const gchar * +gst_alsa_mixer_get_option (GstAlsaMixer * mixer, GstMixerOptions * opts) +{ + gint ret; + guint idx; + GstAlsaMixerOptions *alsa_opts = GST_ALSA_MIXER_OPTIONS (opts); + + g_return_val_if_fail (mixer->handle != NULL, NULL); + g_static_rec_mutex_lock (mixer->rec_mutex); + ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx); + g_static_rec_mutex_unlock (mixer->rec_mutex); + if (ret == 0) + return g_list_nth_data (opts->values, idx); + else + return snd_strerror (ret); /* feeble attempt at error handling */ +} + +GstMixerFlags +gst_alsa_mixer_get_mixer_flags (GstAlsaMixer * mixer) +{ + g_return_val_if_fail (mixer != NULL, GST_MIXER_FLAG_NONE); + + return GST_MIXER_FLAG_AUTO_NOTIFICATIONS; +} + +static void +gst_alsa_mixer_update_option (GstAlsaMixer * mixer, + GstAlsaMixerOptions * alsa_opts) +{ + gint ret; + guint idx; + /* const */ gchar *option; + + if (mixer->interface == NULL) { + GST_WARNING ("Cannot send update notifications, no GstMixer * given"); + return; + } + g_static_rec_mutex_lock (mixer->rec_mutex); + ret = snd_mixer_selem_get_enum_item (alsa_opts->element, 0, &idx); + g_static_rec_mutex_unlock (mixer->rec_mutex); + if (ret == 0) { + option = g_list_nth_data (GST_MIXER_OPTIONS (alsa_opts)->values, idx); + gst_mixer_option_changed (mixer->interface, GST_MIXER_OPTIONS (alsa_opts), + option); + } +} + +static void +gst_alsa_mixer_update_track (GstAlsaMixer * mixer, + GstAlsaMixerTrack * alsa_track) +{ + GstMixerTrack *track = (GstMixerTrack *) alsa_track; + gboolean old_mute; + gboolean old_record; + gint i, n_channels; + gint *old_volumes; + + GST_DEBUG ("Updating track %" GST_PTR_FORMAT, alsa_track); + + if (mixer->interface == NULL) { + GST_WARNING ("Cannot send update notifications, no GstMixer * given"); + return; + } + + old_mute = ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); + old_record = ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); + old_volumes = g_new (gint, track->num_channels); + n_channels = track->num_channels; + memcpy (old_volumes, alsa_track->volumes, + sizeof (gint) * track->num_channels); + + gst_alsa_mixer_track_update (alsa_track); + + if (old_record != + ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD))) { + gst_mixer_record_toggled (mixer->interface, track, + ! !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_RECORD)); + } + if (old_mute != ! !(GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE))) { + gst_mixer_mute_toggled (mixer->interface, track, + ! !GST_MIXER_TRACK_HAS_FLAG (track, GST_MIXER_TRACK_MUTE)); + } + + n_channels = MIN (n_channels, track->num_channels); + for (i = 0; i < n_channels; i++) { + if (old_volumes[i] != alsa_track->volumes[i]) { + gst_mixer_volume_changed (mixer->interface, track, alsa_track->volumes); + break; + } + } + g_free (old_volumes); +} + +/* utility function for gstalsamixerelement to set the interface */ +void +_gst_alsa_mixer_set_interface (GstAlsaMixer * mixer, GstMixer * interface) +{ + g_return_if_fail (mixer != NULL && mixer->interface == NULL); + g_return_if_fail (interface != NULL); + + mixer->interface = g_object_ref (G_OBJECT (interface)); +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.h new file mode 100644 index 0000000..ccc3784 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixer.h @@ -0,0 +1,217 @@ +/* ALSA mixer interface implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __GST_ALSA_MIXER_H__ +#define __GST_ALSA_MIXER_H__ + + +#include "gstalsa.h" + +#include +#include "gstalsamixeroptions.h" +#include "gstalsamixertrack.h" + + +G_BEGIN_DECLS + +/* This does not get you what you think it does, use obj->mixer */ +/* #define GST_ALSA_MIXER(obj) ((GstAlsaMixer*)(obj)) */ + +typedef struct _GstAlsaMixer GstAlsaMixer; + +typedef enum { + GST_ALSA_MIXER_CAPTURE = 1<<0, + GST_ALSA_MIXER_PLAYBACK = 1<<1, + GST_ALSA_MIXER_ALL = GST_ALSA_MIXER_CAPTURE | GST_ALSA_MIXER_PLAYBACK +} GstAlsaMixerDirection; + +/** + * GstAlsaMixer: + * + * Opaque data structure + */ +struct _GstAlsaMixer +{ + GList * tracklist; /* list of available tracks */ + + snd_mixer_t * handle; + + GstTask * task; + GStaticRecMutex * task_mutex; + GStaticRecMutex * rec_mutex; + + int pfd[2]; + + GstMixer * interface; + gchar * device; + gchar * cardname; + + GstAlsaMixerDirection dir; +}; + + +GstAlsaMixer* gst_alsa_mixer_new (const gchar *device, + GstAlsaMixerDirection dir); +void gst_alsa_mixer_free (GstAlsaMixer *mixer); + +const GList* gst_alsa_mixer_list_tracks (GstAlsaMixer * mixer); +void gst_alsa_mixer_set_volume (GstAlsaMixer * mixer, + GstMixerTrack * track, + gint * volumes); +void gst_alsa_mixer_get_volume (GstAlsaMixer * mixer, + GstMixerTrack * track, + gint * volumes); +void gst_alsa_mixer_set_record (GstAlsaMixer * mixer, + GstMixerTrack * track, + gboolean record); +void gst_alsa_mixer_set_mute (GstAlsaMixer * mixer, + GstMixerTrack * track, + gboolean mute); +void gst_alsa_mixer_set_option (GstAlsaMixer * mixer, + GstMixerOptions * opts, + gchar * value); +const gchar* gst_alsa_mixer_get_option (GstAlsaMixer * mixer, + GstMixerOptions * opts); +void _gst_alsa_mixer_set_interface (GstAlsaMixer * mixer, + GstMixer * interface); +GstMixerFlags gst_alsa_mixer_get_mixer_flags (GstAlsaMixer *mixer); + +#define GST_IMPLEMENT_ALSA_MIXER_METHODS(Type, interface_as_function) \ +static gboolean \ +interface_as_function ## _supported (Type *this, GType iface_type) \ +{ \ + g_assert (iface_type == GST_TYPE_MIXER); \ + \ + return (this->mixer != NULL); \ +} \ + \ +static const GList* \ +interface_as_function ## _list_tracks (GstMixer * mixer) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_val_if_fail (this != NULL, NULL); \ + g_return_val_if_fail (this->mixer != NULL, NULL); \ + \ + return gst_alsa_mixer_list_tracks (this->mixer); \ +} \ + \ +static void \ +interface_as_function ## _set_volume (GstMixer * mixer, GstMixerTrack * track, \ + gint * volumes) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_if_fail (this != NULL); \ + g_return_if_fail (this->mixer != NULL); \ + \ + gst_alsa_mixer_set_volume (this->mixer, track, volumes); \ +} \ + \ +static void \ +interface_as_function ## _get_volume (GstMixer * mixer, GstMixerTrack * track, \ + gint * volumes) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_if_fail (this != NULL); \ + g_return_if_fail (this->mixer != NULL); \ + \ + gst_alsa_mixer_get_volume (this->mixer, track, volumes); \ +} \ + \ +static void \ +interface_as_function ## _set_record (GstMixer * mixer, GstMixerTrack * track, \ + gboolean record) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_if_fail (this != NULL); \ + g_return_if_fail (this->mixer != NULL); \ + \ + gst_alsa_mixer_set_record (this->mixer, track, record); \ +} \ + \ +static void \ +interface_as_function ## _set_mute (GstMixer * mixer, GstMixerTrack * track, \ + gboolean mute) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_if_fail (this != NULL); \ + g_return_if_fail (this->mixer != NULL); \ + \ + gst_alsa_mixer_set_mute (this->mixer, track, mute); \ +} \ + \ +static void \ +interface_as_function ## _set_option (GstMixer * mixer, GstMixerOptions * opts, \ + gchar * value) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_if_fail (this != NULL); \ + g_return_if_fail (this->mixer != NULL); \ + \ + gst_alsa_mixer_set_option (this->mixer, opts, value); \ +} \ + \ +static const gchar* \ +interface_as_function ## _get_option (GstMixer * mixer, GstMixerOptions * opts) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_val_if_fail (this != NULL, NULL); \ + g_return_val_if_fail (this->mixer != NULL, NULL); \ + \ + return gst_alsa_mixer_get_option (this->mixer, opts); \ +} \ + \ +static GstMixerFlags \ +interface_as_function ## _get_mixer_flags (GstMixer * mixer) \ +{ \ + Type *this = (Type*) mixer; \ + \ + g_return_val_if_fail (this != NULL, GST_MIXER_FLAG_NONE); \ + g_return_val_if_fail (this->mixer != NULL, GST_MIXER_FLAG_NONE); \ + \ + return gst_alsa_mixer_get_mixer_flags (this->mixer); \ +} \ + \ +static void \ +interface_as_function ## _interface_init (GstMixerClass * klass) \ +{ \ + GST_MIXER_TYPE (klass) = GST_MIXER_HARDWARE; \ + \ + /* set up the interface hooks */ \ + klass->list_tracks = interface_as_function ## _list_tracks; \ + klass->set_volume = interface_as_function ## _set_volume; \ + klass->get_volume = interface_as_function ## _get_volume; \ + klass->set_mute = interface_as_function ## _set_mute; \ + klass->set_record = interface_as_function ## _set_record; \ + klass->set_option = interface_as_function ## _set_option; \ + klass->get_option = interface_as_function ## _get_option; \ + klass->get_mixer_flags = interface_as_function ## _get_mixer_flags; \ +} + + +G_END_DECLS + + +#endif /* __GST_ALSA_MIXER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.c new file mode 100644 index 0000000..ec80039 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.c @@ -0,0 +1,244 @@ +/* ALSA mixer implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstalsamixerelement.h" +#include "gstalsadeviceprobe.h" + +#define DEFAULT_PROP_DEVICE "default" +#define DEFAULT_PROP_DEVICE_NAME "" + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_NAME +}; + +static void gst_alsa_mixer_element_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstAlsaMixerElement, gst_alsa_mixer_element, + GstElement, GST_TYPE_ELEMENT, gst_alsa_mixer_element_init_interfaces); + +/* massive macro that takes care of all the GstMixer stuff */ +GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaMixerElement, gst_alsa_mixer_element); + +static void gst_alsa_mixer_element_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_alsa_mixer_element_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_alsa_mixer_element_finalize (GObject * object); + +static GstStateChangeReturn gst_alsa_mixer_element_change_state (GstElement + * element, GstStateChange transition); + +static gboolean +gst_alsa_mixer_element_interface_supported (GstAlsaMixerElement * this, + GType interface_type) +{ + if (interface_type == GST_TYPE_MIXER) { + return gst_alsa_mixer_element_supported (this, interface_type); + } + + g_return_val_if_reached (FALSE); +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = (gpointer) gst_alsa_mixer_element_interface_supported; +} + +static void +gst_alsa_mixer_element_init_interfaces (GType type) +{ + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) gst_alsa_mixer_element_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); + + gst_alsa_type_add_device_property_probe_interface (type); +} + +static void +gst_alsa_mixer_element_base_init (gpointer klass) +{ + gst_element_class_set_details_simple (GST_ELEMENT_CLASS (klass), + "Alsa mixer", "Generic/Audio", + "Control sound input and output levels with ALSA", + "Leif Johnson "); +} + +static void +gst_alsa_mixer_element_class_init (GstAlsaMixerElementClass * klass) +{ + GstElementClass *element_class; + GObjectClass *gobject_class; + + element_class = (GstElementClass *) klass; + gobject_class = (GObjectClass *) klass; + + gobject_class->finalize = gst_alsa_mixer_element_finalize; + gobject_class->get_property = gst_alsa_mixer_element_get_property; + gobject_class->set_property = gst_alsa_mixer_element_set_property; + + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Device", + "ALSA device, as defined in an asound configuration file", + DEFAULT_PROP_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Device name", + "Human-readable name of the sound device", + DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_alsa_mixer_element_change_state); +} + +static void +gst_alsa_mixer_element_finalize (GObject * obj) +{ + GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (obj); + + g_free (this->device); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_alsa_mixer_element_init (GstAlsaMixerElement * this, + GstAlsaMixerElementClass * klass) +{ + this->mixer = NULL; + this->device = g_strdup (DEFAULT_PROP_DEVICE); +} + +static void +gst_alsa_mixer_element_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object); + + switch (prop_id) { + case PROP_DEVICE:{ + GST_OBJECT_LOCK (this); + g_free (this->device); + this->device = g_value_dup_string (value); + /* make sure we never set NULL, this is nice when we want to open the + * device. */ + if (this->device == NULL) + this->device = g_strdup (DEFAULT_PROP_DEVICE); + GST_OBJECT_UNLOCK (this); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_alsa_mixer_element_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (object); + + switch (prop_id) { + case PROP_DEVICE:{ + GST_OBJECT_LOCK (this); + g_value_set_string (value, this->device); + GST_OBJECT_UNLOCK (this); + break; + } + case PROP_DEVICE_NAME:{ + GST_OBJECT_LOCK (this); + if (this->mixer) { + g_value_set_string (value, this->mixer->cardname); + } else { + g_value_set_string (value, NULL); + } + GST_OBJECT_UNLOCK (this); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_alsa_mixer_element_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstAlsaMixerElement *this = GST_ALSA_MIXER_ELEMENT (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!this->mixer) { + this->mixer = gst_alsa_mixer_new (this->device, GST_ALSA_MIXER_ALL); + if (!this->mixer) + goto open_failed; + _gst_alsa_mixer_set_interface (this->mixer, GST_MIXER (element)); + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + if (this->mixer) { + gst_alsa_mixer_free (this->mixer); + this->mixer = NULL; + } + break; + default: + break; + } + + return ret; + + /* ERRORS */ +open_failed: + { + GST_ELEMENT_ERROR (element, RESOURCE, OPEN_READ_WRITE, (NULL), + ("Failed to open alsa mixer device '%s'", this->device)); + return GST_STATE_CHANGE_FAILURE; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.h new file mode 100644 index 0000000..16cb245 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixerelement.h @@ -0,0 +1,61 @@ +/* ALSA mixer interface implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __GST_ALSA_MIXER_ELEMENT_H__ +#define __GST_ALSA_MIXER_ELEMENT_H__ + + +#include "gstalsa.h" +#include "gstalsamixer.h" + +G_BEGIN_DECLS + +#define GST_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElement)) +#define GST_ALSA_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_ELEMENT,GstAlsaMixerElementClass)) +#define GST_IS_ALSA_MIXER_ELEMENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_ELEMENT)) +#define GST_IS_ALSA_MIXER_ELEMENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_ELEMENT)) +#define GST_TYPE_ALSA_MIXER_ELEMENT (gst_alsa_mixer_element_get_type()) + +typedef struct _GstAlsaMixerElement GstAlsaMixerElement; +typedef struct _GstAlsaMixerElementClass GstAlsaMixerElementClass; + +/** + * GstAlsaMixerElement + * + * Opaque datastructure. + */ +struct _GstAlsaMixerElement { + GstElement parent; + + GstAlsaMixer *mixer; + gchar *device; +}; + +struct _GstAlsaMixerElementClass { + GstElementClass parent; +}; + + +GType gst_alsa_mixer_element_get_type (void); + + +G_END_DECLS + + +#endif /* __GST_ALSA_MIXER_ELEMENT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.c new file mode 100644 index 0000000..20bb89d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.c @@ -0,0 +1,109 @@ +/* ALSA mixer object implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstalsamixeroptions.h" + +static void gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts); +static void gst_alsa_mixer_options_class_init (gpointer g_class, + gpointer class_data); + +static GstMixerOptionsClass *parent_class = NULL; + +GType +gst_alsa_mixer_options_get_type (void) +{ + static GType opts_type = 0; + + if (!opts_type) { + static const GTypeInfo opts_info = { + sizeof (GstAlsaMixerOptionsClass), + NULL, + NULL, + gst_alsa_mixer_options_class_init, + NULL, + NULL, + sizeof (GstAlsaMixerOptions), + 0, + (GInstanceInitFunc) gst_alsa_mixer_options_init, + }; + + opts_type = + g_type_register_static (GST_TYPE_MIXER_OPTIONS, "GstAlsaMixerOptions", + &opts_info, 0); + } + + return opts_type; +} + +static void +gst_alsa_mixer_options_class_init (gpointer g_class, gpointer class_data) +{ + parent_class = g_type_class_peek_parent (g_class); +} + +static void +gst_alsa_mixer_options_init (GstAlsaMixerOptions * alsa_opts) +{ +} + +GstMixerOptions * +gst_alsa_mixer_options_new (snd_mixer_elem_t * element, gint track_num) +{ + GstMixerOptions *opts; + GstAlsaMixerOptions *alsa_opts; + GstMixerTrack *track; + const gchar *label; + guint index; + gint num, i; + gchar str[256]; + + label = snd_mixer_selem_get_name (element); + index = snd_mixer_selem_get_index (element); + + GST_LOG ("[%s,%u]", label, index); + + opts = g_object_new (GST_ALSA_MIXER_OPTIONS_TYPE, + "untranslated-label", label, "index", index, NULL); + alsa_opts = (GstAlsaMixerOptions *) opts; + track = (GstMixerTrack *) opts; + + /* set basic information */ + track->label = g_strdup (label); /* FIXME: translate this? */ + track->num_channels = 0; + track->flags = 0; + alsa_opts->element = element; + alsa_opts->track_num = track_num; + + /* get enumerations for switch/options object */ + num = snd_mixer_selem_get_enum_items (element); + for (i = 0; i < num; i++) { + if (snd_mixer_selem_get_enum_item_name (element, i, 255, str) < 0) { + g_object_unref (G_OBJECT (alsa_opts)); + return NULL; + } + + opts->values = g_list_append (opts->values, g_strdup (str)); + } + + return opts; +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.h new file mode 100644 index 0000000..b3c36c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixeroptions.h @@ -0,0 +1,62 @@ +/* ALSA mixer options object. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __GST_ALSA_MIXER_OPTIONS_H__ +#define __GST_ALSA_MIXER_OPTIONS_H__ + + +#include "gstalsa.h" +#include + + +G_BEGIN_DECLS + + +#define GST_ALSA_MIXER_OPTIONS_TYPE (gst_alsa_mixer_options_get_type ()) +#define GST_ALSA_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptions)) +#define GST_ALSA_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_OPTIONS,GstAlsaMixerOptionsClass)) +#define GST_IS_ALSA_MIXER_OPTIONS(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_OPTIONS)) +#define GST_IS_ALSA_MIXER_OPTIONS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_OPTIONS)) +#define GST_TYPE_ALSA_MIXER_OPTIONS (gst_alsa_mixer_options_get_type()) + + +typedef struct _GstAlsaMixerOptions GstAlsaMixerOptions; +typedef struct _GstAlsaMixerOptionsClass GstAlsaMixerOptionsClass; + + +struct _GstAlsaMixerOptions { + GstMixerOptions parent; + snd_mixer_elem_t *element; /* the ALSA mixer element for this track */ + gint track_num; +}; + +struct _GstAlsaMixerOptionsClass { + GstMixerOptionsClass parent; +}; + + +GType gst_alsa_mixer_options_get_type (void); +GstMixerOptions *gst_alsa_mixer_options_new (snd_mixer_elem_t * element, + gint track_num); + + +G_END_DECLS + + +#endif /* __GST_ALSA_MIXER_OPTIONS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.c new file mode 100644 index 0000000..a1fdb7f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.c @@ -0,0 +1,355 @@ +/* ALSA mixer track implementation. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include "gstalsamixertrack.h" + +static void gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track); +static void gst_alsa_mixer_track_class_init (gpointer g_class, + gpointer class_data); + +static GstMixerTrackClass *parent_class = NULL; + +GType +gst_alsa_mixer_track_get_type (void) +{ + static GType track_type = 0; + + if (!track_type) { + static const GTypeInfo track_info = { + sizeof (GstAlsaMixerTrackClass), + NULL, + NULL, + gst_alsa_mixer_track_class_init, + NULL, + NULL, + sizeof (GstAlsaMixerTrack), + 0, + (GInstanceInitFunc) gst_alsa_mixer_track_init, + NULL + }; + + track_type = + g_type_register_static (GST_TYPE_MIXER_TRACK, "GstAlsaMixerTrack", + &track_info, 0); + } + + return track_type; +} + +static void +gst_alsa_mixer_track_class_init (gpointer g_class, gpointer class_data) +{ + parent_class = g_type_class_peek_parent (g_class); +} + +static void +gst_alsa_mixer_track_init (GstAlsaMixerTrack * alsa_track) +{ +} + +static void +gst_alsa_mixer_track_update_alsa_capabilities (GstAlsaMixerTrack * alsa_track) +{ + alsa_track->alsa_flags = 0; + alsa_track->capture_group = -1; + + /* common flags */ + if (snd_mixer_selem_has_common_volume (alsa_track->element)) + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_VOLUME; + + if (snd_mixer_selem_has_common_switch (alsa_track->element)) + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_SWITCH; + + /* Since we create two separate mixer track objects for alsa elements that + * support both playback and capture, we're going to 'hide' the alsa flags + * that don't pertain to this mixer track from alsa_flags, otherwise + * gst_alsa_mixer_track_update() is going to do things we don't want */ + + /* playback flags */ + if ((GST_MIXER_TRACK (alsa_track)->flags & GST_MIXER_TRACK_OUTPUT)) { + if (snd_mixer_selem_has_playback_volume (alsa_track->element)) + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PVOLUME; + + if (snd_mixer_selem_has_playback_switch (alsa_track->element)) + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_PSWITCH; + } + + /* capture flags */ + if ((GST_MIXER_TRACK (alsa_track)->flags & GST_MIXER_TRACK_INPUT)) { + if (snd_mixer_selem_has_capture_volume (alsa_track->element)) + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CVOLUME; + + if (snd_mixer_selem_has_capture_switch (alsa_track->element)) { + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH; + + if (snd_mixer_selem_has_capture_switch_exclusive (alsa_track->element)) { + alsa_track->alsa_flags |= GST_ALSA_MIXER_TRACK_CSWITCH_EXCL; + alsa_track->capture_group = + snd_mixer_selem_get_capture_group (alsa_track->element); + } + } + } + + GST_LOG ("[%s] alsa_flags=0x%08x, capture_group=%d", + snd_mixer_selem_get_name (alsa_track->element), + alsa_track->alsa_flags, alsa_track->capture_group); +} + +inline static gboolean +alsa_track_has_cap (GstAlsaMixerTrack * alsa_track, guint32 flag) +{ + return ((alsa_track->alsa_flags & flag) != 0); +} + +GstMixerTrack * +gst_alsa_mixer_track_new (snd_mixer_elem_t * element, + gint num, gint track_num, gint flags, gboolean sw, + GstAlsaMixerTrack * shared_mute_track, gboolean append_capture) +{ + GstAlsaMixerTrack *alsa_track; + GstMixerTrack *track; + const gchar *name; + guint index; + const gchar *label; + gint i; + long min = 0, max = 0; + const struct + { + const gchar orig[12]; + const gchar trans[12]; + } alsa_track_labels[] = { + { + "Master", N_("Master")}, { + "Bass", N_("Bass")}, { + "Treble", N_("Treble")}, { + "PCM", N_("PCM")}, { + "Synth", N_("Synth")}, { + "Line", N_("Line-in")}, { + "CD", N_("CD")}, { + "Mic", N_("Microphone")}, { + "PC Speaker", N_("PC Speaker")}, { + "Playback", N_("Playback")}, { + "Capture", N_("Capture")} + }; + + name = snd_mixer_selem_get_name (element); + index = snd_mixer_selem_get_index (element); + + GST_LOG + ("[%s,%u] num=%d,track_num=%d,flags=0x%08x,sw=%s,shared_mute_track=%p", + name, index, num, track_num, flags, (sw) ? "true" : "false", + shared_mute_track); + + track = (GstMixerTrack *) g_object_new (GST_ALSA_MIXER_TRACK_TYPE, + "untranslated-label", name, "index", index, NULL); + + alsa_track = (GstAlsaMixerTrack *) track; + + GST_LOG ("[%s] created new mixer track %p", name, track); + + /* This reflects the assumptions used for GstAlsaMixerTrack */ + if (!(!!(flags & GST_MIXER_TRACK_OUTPUT) ^ !!(flags & GST_MIXER_TRACK_INPUT))) { + GST_ERROR ("Mixer track must be either output or input!"); + g_return_val_if_reached (NULL); + } + + track->flags = flags; + alsa_track->element = element; + alsa_track->shared_mute = shared_mute_track; + alsa_track->track_num = track_num; + alsa_track->alsa_channels = 0; + + gst_alsa_mixer_track_update_alsa_capabilities (alsa_track); + + if (flags & GST_MIXER_TRACK_OUTPUT) { + while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && + snd_mixer_selem_has_playback_channel (element, + alsa_track->alsa_channels)) { + alsa_track->alsa_channels++; + } + GST_LOG ("[%s] %d output channels", name, alsa_track->alsa_channels); + } else if (flags & GST_MIXER_TRACK_INPUT) { + while (alsa_track->alsa_channels < GST_ALSA_MAX_CHANNELS && + snd_mixer_selem_has_capture_channel (element, + alsa_track->alsa_channels)) { + alsa_track->alsa_channels++; + } + GST_LOG ("[%s] %d input channels", name, alsa_track->alsa_channels); + } else { + g_assert_not_reached (); + } + + if (sw) + track->num_channels = 0; + else + track->num_channels = alsa_track->alsa_channels; + + /* translate the name if we can */ + label = name; + for (i = 0; i < G_N_ELEMENTS (alsa_track_labels); ++i) { + if (g_utf8_collate (label, alsa_track_labels[i].orig) == 0) { + label = _(alsa_track_labels[i].trans); + break; + } + } + + if (num == 0) { + track->label = g_strdup_printf ("%s%s%s", label, + append_capture ? " " : "", append_capture ? _("Capture") : ""); + } else { + track->label = g_strdup_printf ("%s%s%s %d", label, + append_capture ? " " : "", append_capture ? _("Capture") : "", num); + } + + /* set volume information */ + if (track->num_channels > 0) { + if ((flags & GST_MIXER_TRACK_OUTPUT)) + snd_mixer_selem_get_playback_volume_range (element, &min, &max); + else + snd_mixer_selem_get_capture_volume_range (element, &min, &max); + } + track->min_volume = (gint) min; + track->max_volume = (gint) max; + + for (i = 0; i < track->num_channels; i++) { + long tmp = 0; + + if (flags & GST_MIXER_TRACK_OUTPUT) + snd_mixer_selem_get_playback_volume (element, i, &tmp); + else + snd_mixer_selem_get_capture_volume (element, i, &tmp); + + alsa_track->volumes[i] = (gint) tmp; + } + + gst_alsa_mixer_track_update (alsa_track); + + return track; +} + +void +gst_alsa_mixer_track_update (GstAlsaMixerTrack * alsa_track) +{ + GstMixerTrack *track = (GstMixerTrack *) alsa_track; + gint i; + gint audible = !(track->flags & GST_MIXER_TRACK_MUTE); + + if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME)) { + /* update playback volume */ + for (i = 0; i < track->num_channels; i++) { + long vol = 0; + + snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol); + alsa_track->volumes[i] = (gint) vol; + } + } + + if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME)) { + /* update capture volume */ + for (i = 0; i < track->num_channels; i++) { + long vol = 0; + + snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol); + alsa_track->volumes[i] = (gint) vol; + } + } + + /* Any updates in flags? */ + if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PSWITCH)) { + int v = 0; + + audible = 0; + for (i = 0; i < alsa_track->alsa_channels; ++i) { + snd_mixer_selem_get_playback_switch (alsa_track->element, i, &v); + audible += v; + } + + } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_PVOLUME) && + track->flags & GST_MIXER_TRACK_MUTE) { + /* check if user has raised volume with a parallel running application */ + + for (i = 0; i < track->num_channels; i++) { + long vol = 0; + + snd_mixer_selem_get_playback_volume (alsa_track->element, i, &vol); + + if (vol > track->min_volume) { + audible = 1; + break; + } + } + } + + if (!!(audible) != !(track->flags & GST_MIXER_TRACK_MUTE)) { + if (audible) { + track->flags &= ~GST_MIXER_TRACK_MUTE; + + if (alsa_track->shared_mute) + ((GstMixerTrack *) (alsa_track->shared_mute))->flags &= + ~GST_MIXER_TRACK_MUTE; + } else { + track->flags |= GST_MIXER_TRACK_MUTE; + + if (alsa_track->shared_mute) + ((GstMixerTrack *) (alsa_track->shared_mute))->flags |= + GST_MIXER_TRACK_MUTE; + } + } + + if (track->flags & GST_MIXER_TRACK_INPUT) { + gint recording = track->flags & GST_MIXER_TRACK_RECORD; + + if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CSWITCH)) { + int v = 0; + + recording = 0; + for (i = 0; i < alsa_track->alsa_channels; ++i) { + snd_mixer_selem_get_capture_switch (alsa_track->element, i, &v); + recording += v; + } + + } else if (alsa_track_has_cap (alsa_track, GST_ALSA_MIXER_TRACK_CVOLUME) && + !(track->flags & GST_MIXER_TRACK_RECORD)) { + /* check if user has raised volume with a parallel running application */ + + for (i = 0; i < track->num_channels; i++) { + long vol = 0; + + snd_mixer_selem_get_capture_volume (alsa_track->element, i, &vol); + + if (vol > track->min_volume) { + recording = 1; + break; + } + } + } + + if (recording) + track->flags |= GST_MIXER_TRACK_RECORD; + else + track->flags &= ~GST_MIXER_TRACK_RECORD; + } + +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.h new file mode 100644 index 0000000..acc64cb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsamixertrack.h @@ -0,0 +1,79 @@ +/* ALSA mixer track object. + * Copyright (C) 2003 Leif Johnson + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#ifndef __GST_ALSA_MIXER_TRACK_H__ +#define __GST_ALSA_MIXER_TRACK_H__ + + +#include "gstalsa.h" +#include + + +G_BEGIN_DECLS + + +#define GST_ALSA_MIXER_TRACK_TYPE (gst_alsa_mixer_track_get_type ()) +#define GST_ALSA_MIXER_TRACK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrack)) +#define GST_ALSA_MIXER_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_MIXER_TRACK,GstAlsaMixerTrackClass)) +#define GST_IS_ALSA_MIXER_TRACK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_MIXER_TRACK)) +#define GST_IS_ALSA_MIXER_TRACK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_MIXER_TRACK)) +#define GST_TYPE_ALSA_MIXER_TRACK (gst_alsa_mixer_track_get_type()) + +typedef struct _GstAlsaMixerTrack GstAlsaMixerTrack; +typedef struct _GstAlsaMixerTrackClass GstAlsaMixerTrackClass; + +#define GST_ALSA_MIXER_TRACK_VOLUME (1<<0) /* common volume */ +#define GST_ALSA_MIXER_TRACK_PVOLUME (1<<1) +#define GST_ALSA_MIXER_TRACK_CVOLUME (1<<2) +#define GST_ALSA_MIXER_TRACK_SWITCH (1<<3) /* common switch */ +#define GST_ALSA_MIXER_TRACK_PSWITCH (1<<4) +#define GST_ALSA_MIXER_TRACK_CSWITCH (1<<5) +#define GST_ALSA_MIXER_TRACK_CSWITCH_EXCL (1<<6) + +#define GST_ALSA_MAX_CHANNELS (SND_MIXER_SCHN_LAST+1) + +struct _GstAlsaMixerTrack { + GstMixerTrack parent; + snd_mixer_elem_t *element; /* the ALSA mixer element for this track */ + GstAlsaMixerTrack *shared_mute; + gint track_num; + guint32 alsa_flags; /* alsa track capabilities */ + gint alsa_channels; + gint capture_group; + gint volumes[GST_ALSA_MAX_CHANNELS]; +}; + +struct _GstAlsaMixerTrackClass { + GstMixerTrackClass parent; +}; + +GType gst_alsa_mixer_track_get_type (void); +GstMixerTrack * gst_alsa_mixer_track_new (snd_mixer_elem_t * element, + gint num, + gint track_num, + gint flags, + gboolean sw, /* is simple switch? */ + GstAlsaMixerTrack * shared_mute_track, + gboolean label_append_capture); +void gst_alsa_mixer_track_update (GstAlsaMixerTrack * alsa_track); + +G_END_DECLS + + +#endif /* __GST_ALSA_MIXER_TRACK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsaplugin.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsaplugin.c new file mode 100644 index 0000000..69f539d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsaplugin.c @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2001 CodeFactory AB + * Copyright (C) 2001 Thomas Nyberg + * Copyright (C) 2001-2002 Andy Wingo + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstalsasink.h" +#include "gstalsasrc.h" +#include "gstalsamixerelement.h" + +#include + +GST_DEBUG_CATEGORY (alsa_debug); + +/* ALSA debugging wrapper */ +static void +gst_alsa_error_wrapper (const char *file, int line, const char *function, + int err, const char *fmt, ...) +{ +#ifndef GST_DISABLE_GST_DEBUG + va_list args; + gchar *str; + + va_start (args, fmt); + str = g_strdup_vprintf (fmt, args); + va_end (args); + /* FIXME: use GST_LEVEL_ERROR here? Currently warning is used because we're + * able to catch enough of the errors that would be printed otherwise + */ + gst_debug_log (alsa_debug, GST_LEVEL_WARNING, file, function, line, NULL, + "alsalib error: %s%s%s", str, err ? ": " : "", + err ? snd_strerror (err) : ""); + g_free (str); +#endif +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + int err; + + if (!gst_element_register (plugin, "alsamixer", GST_RANK_NONE, + GST_TYPE_ALSA_MIXER_ELEMENT)) + return FALSE; + if (!gst_element_register (plugin, "alsasrc", GST_RANK_PRIMARY, + GST_TYPE_ALSA_SRC)) + return FALSE; + if (!gst_element_register (plugin, "alsasink", GST_RANK_PRIMARY, + GST_TYPE_ALSA_SINK)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (alsa_debug, "alsa", 0, "alsa plugins"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + err = snd_lib_error_set_handler (gst_alsa_error_wrapper); + if (err != 0) + GST_WARNING ("failed to set alsa error handler"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "alsa", + "ALSA plugin library", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.c new file mode 100644 index 0000000..2fb37df --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.c @@ -0,0 +1,954 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * Copyright (C) 2006 Tim-Philipp Müller + * + * gstalsasink.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-alsasink + * @see_also: alsasrc, alsamixer + * + * This element renders raw audio samples using the ALSA api. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! alsasink + * ]| Play an Ogg/Vorbis file. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "gstalsa.h" +#include "gstalsasink.h" +#include "gstalsadeviceprobe.h" + +#include + +#define DEFAULT_DEVICE "default" +#define DEFAULT_DEVICE_NAME "" +#define DEFAULT_CARD_NAME "" +#define SPDIF_PERIOD_SIZE 1536 +#define SPDIF_BUFFER_SIZE 15360 + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_NAME, + PROP_CARD_NAME, + PROP_LAST +}; + +static void gst_alsasink_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstAlsaSink, gst_alsasink, GstAudioSink, + GST_TYPE_AUDIO_SINK, gst_alsasink_init_interfaces); + +static void gst_alsasink_finalise (GObject * object); +static void gst_alsasink_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_alsasink_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstCaps *gst_alsasink_getcaps (GstBaseSink * bsink); + +static gboolean gst_alsasink_open (GstAudioSink * asink); +static gboolean gst_alsasink_prepare (GstAudioSink * asink, + GstRingBufferSpec * spec); +static gboolean gst_alsasink_unprepare (GstAudioSink * asink); +static gboolean gst_alsasink_close (GstAudioSink * asink); +static guint gst_alsasink_write (GstAudioSink * asink, gpointer data, + guint length); +static guint gst_alsasink_delay (GstAudioSink * asink); +static void gst_alsasink_reset (GstAudioSink * asink); + +static gint output_ref; /* 0 */ +static snd_output_t *output; /* NULL */ +static GStaticMutex output_mutex = G_STATIC_MUTEX_INIT; + + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +# define ALSA_SINK_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN" +#else +# define ALSA_SINK_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN" +#endif + +static GstStaticPadTemplate alsasink_sink_factory = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 32, " + "depth = (int) 32, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 24, " + "depth = (int) 24, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 32, " + "depth = (int) 24, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SINK_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 16, " + "depth = (int) 16, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 8, " + "depth = (int) 8, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ];" + "audio/x-iec958") + ); + +static void +gst_alsasink_finalise (GObject * object) +{ + GstAlsaSink *sink = GST_ALSA_SINK (object); + + g_free (sink->device); + g_mutex_free (sink->alsa_lock); + + g_static_mutex_lock (&output_mutex); + --output_ref; + if (output_ref == 0) { + snd_output_close (output); + output = NULL; + } + g_static_mutex_unlock (&output_mutex); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_alsasink_init_interfaces (GType type) +{ + gst_alsa_type_add_device_property_probe_interface (type); +} + +static void +gst_alsasink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Audio sink (ALSA)", "Sink/Audio", + "Output to a sound card via ALSA", "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&alsasink_sink_factory)); +} + +static void +gst_alsasink_class_init (GstAlsaSinkClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSinkClass *gstbasesink_class; + GstAudioSinkClass *gstaudiosink_class; + + gobject_class = (GObjectClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + gstaudiosink_class = (GstAudioSinkClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_alsasink_finalise; + gobject_class->get_property = gst_alsasink_get_property; + gobject_class->set_property = gst_alsasink_set_property; + + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasink_getcaps); + + gstaudiosink_class->open = GST_DEBUG_FUNCPTR (gst_alsasink_open); + gstaudiosink_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasink_prepare); + gstaudiosink_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasink_unprepare); + gstaudiosink_class->close = GST_DEBUG_FUNCPTR (gst_alsasink_close); + gstaudiosink_class->write = GST_DEBUG_FUNCPTR (gst_alsasink_write); + gstaudiosink_class->delay = GST_DEBUG_FUNCPTR (gst_alsasink_delay); + gstaudiosink_class->reset = GST_DEBUG_FUNCPTR (gst_alsasink_reset); + + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Device", + "ALSA device, as defined in an asound configuration file", + DEFAULT_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Device name", + "Human-readable name of the sound device", DEFAULT_DEVICE_NAME, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CARD_NAME, + g_param_spec_string ("card-name", "Card name", + "Human-readable name of the sound card", DEFAULT_CARD_NAME, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_alsasink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAlsaSink *sink; + + sink = GST_ALSA_SINK (object); + + switch (prop_id) { + case PROP_DEVICE: + g_free (sink->device); + sink->device = g_value_dup_string (value); + /* setting NULL restores the default device */ + if (sink->device == NULL) { + sink->device = g_strdup (DEFAULT_DEVICE); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_alsasink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAlsaSink *sink; + + sink = GST_ALSA_SINK (object); + + switch (prop_id) { + case PROP_DEVICE: + g_value_set_string (value, sink->device); + break; + case PROP_DEVICE_NAME: + g_value_take_string (value, + gst_alsa_find_device_name (GST_OBJECT_CAST (sink), + sink->device, sink->handle, SND_PCM_STREAM_PLAYBACK)); + break; + case PROP_CARD_NAME: + g_value_take_string (value, + gst_alsa_find_card_name (GST_OBJECT_CAST (sink), + sink->device, SND_PCM_STREAM_PLAYBACK)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_alsasink_init (GstAlsaSink * alsasink, GstAlsaSinkClass * g_class) +{ + GST_DEBUG_OBJECT (alsasink, "initializing alsasink"); + + alsasink->device = g_strdup (DEFAULT_DEVICE); + alsasink->handle = NULL; + alsasink->cached_caps = NULL; + alsasink->alsa_lock = g_mutex_new (); + + g_static_mutex_lock (&output_mutex); + if (output_ref == 0) { + snd_output_stdio_attach (&output, stdout, 0); + ++output_ref; + } + g_static_mutex_unlock (&output_mutex); +} + +#define CHECK(call, error) \ +G_STMT_START { \ +if ((err = call) < 0) \ + goto error; \ +} G_STMT_END; + +static GstCaps * +gst_alsasink_getcaps (GstBaseSink * bsink) +{ + GstElementClass *element_class; + GstPadTemplate *pad_template; + GstAlsaSink *sink = GST_ALSA_SINK (bsink); + GstCaps *caps; + + if (sink->handle == NULL) { + GST_DEBUG_OBJECT (sink, "device not open, using template caps"); + return NULL; /* base class will get template caps for us */ + } + + if (sink->cached_caps) { + GST_LOG_OBJECT (sink, "Returning cached caps"); + return gst_caps_ref (sink->cached_caps); + } + + element_class = GST_ELEMENT_GET_CLASS (sink); + pad_template = gst_element_class_get_pad_template (element_class, "sink"); + g_return_val_if_fail (pad_template != NULL, NULL); + + caps = gst_alsa_probe_supported_formats (GST_OBJECT (sink), sink->handle, + gst_pad_template_get_caps (pad_template)); + + if (caps) { + sink->cached_caps = gst_caps_ref (caps); + } + + GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, caps); + + return caps; +} + +static int +set_hwparams (GstAlsaSink * alsa) +{ + guint rrate; + gint err; + snd_pcm_hw_params_t *params; + guint period_time, buffer_time; + + snd_pcm_hw_params_malloc (¶ms); + + GST_DEBUG_OBJECT (alsa, "Negotiating to %d channels @ %d Hz (format = %s) " + "SPDIF (%d)", alsa->channels, alsa->rate, + snd_pcm_format_name (alsa->format), alsa->iec958); + + /* start with requested values, if we cannot configure alsa for those values, + * we set these values to -1, which will leave the default alsa values */ + buffer_time = alsa->buffer_time; + period_time = alsa->period_time; + +retry: + /* choose all parameters */ + CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config); + /* set the interleaved read/write format */ + CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access), + wrong_access); + /* set the sample format */ + if (alsa->iec958) { + /* Try to use big endian first else fallback to le and swap bytes */ + if (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format) < 0) { + alsa->format = SND_PCM_FORMAT_S16_LE; + alsa->need_swap = TRUE; + GST_DEBUG_OBJECT (alsa, "falling back to little endian with swapping"); + } else { + alsa->need_swap = FALSE; + } + } + CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format), + no_sample_format); + /* set the count of channels */ + CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels), + no_channels); + /* set the stream rate */ + rrate = alsa->rate; + CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL), + no_rate); + if (rrate != alsa->rate) + goto rate_match; + +#ifndef GST_DISABLE_GST_DEBUG + /* get and dump some limits */ + { + guint min, max; + + snd_pcm_hw_params_get_buffer_time_min (params, &min, NULL); + snd_pcm_hw_params_get_buffer_time_max (params, &max, NULL); + + GST_DEBUG_OBJECT (alsa, "buffer time %u, min %u, max %u", + alsa->buffer_time, min, max); + + snd_pcm_hw_params_get_period_time_min (params, &min, NULL); + snd_pcm_hw_params_get_period_time_max (params, &max, NULL); + + GST_DEBUG_OBJECT (alsa, "period time %u, min %u, max %u", + alsa->period_time, min, max); + + snd_pcm_hw_params_get_periods_min (params, &min, NULL); + snd_pcm_hw_params_get_periods_max (params, &max, NULL); + + GST_DEBUG_OBJECT (alsa, "periods min %u, max %u", min, max); + } +#endif + + /* now try to configure the buffer time and period time, if one + * of those fail, we fall back to the defaults and emit a warning. */ + if (buffer_time != -1 && !alsa->iec958) { + /* set the buffer time */ + if ((err = snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params, + &buffer_time, NULL)) < 0) { + GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set buffer time %i for playback: %s", + buffer_time, snd_strerror (err))); + /* disable buffer_time the next round */ + buffer_time = -1; + goto retry; + } + GST_DEBUG_OBJECT (alsa, "buffer time %u", buffer_time); + } + if (period_time != -1 && !alsa->iec958) { + /* set the period time */ + if ((err = snd_pcm_hw_params_set_period_time_near (alsa->handle, params, + &period_time, NULL)) < 0) { + GST_ELEMENT_WARNING (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set period time %i for playback: %s", + period_time, snd_strerror (err))); + /* disable period_time the next round */ + period_time = -1; + goto retry; + } + GST_DEBUG_OBJECT (alsa, "period time %u", period_time); + } + + /* Set buffer size and period size manually for SPDIF */ + if (G_UNLIKELY (alsa->iec958)) { + snd_pcm_uframes_t buffer_size = SPDIF_BUFFER_SIZE; + snd_pcm_uframes_t period_size = SPDIF_PERIOD_SIZE; + + CHECK (snd_pcm_hw_params_set_buffer_size_near (alsa->handle, params, + &buffer_size), buffer_size); + CHECK (snd_pcm_hw_params_set_period_size_near (alsa->handle, params, + &period_size, NULL), period_size); + } + + /* write the parameters to device */ + CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params); + + /* now get the configured values */ + CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size), + buffer_size); + CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL), + period_size); + + GST_DEBUG_OBJECT (alsa, "buffer size %lu, period size %lu", alsa->buffer_size, + alsa->period_size); + + snd_pcm_hw_params_free (params); + return 0; + + /* ERRORS */ +no_config: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Broken configuration for playback: no configurations available: %s", + snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +wrong_access: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Access type not available for playback: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +no_sample_format: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Sample format not available for playback: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +no_channels: + { + gchar *msg = NULL; + + if ((alsa->channels) == 1) + msg = g_strdup (_("Could not open device for playback in mono mode.")); + if ((alsa->channels) == 2) + msg = g_strdup (_("Could not open device for playback in stereo mode.")); + if ((alsa->channels) > 2) + msg = + g_strdup_printf (_ + ("Could not open device for playback in %d-channel mode."), + alsa->channels); + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg), + ("%s", snd_strerror (err))); + g_free (msg); + snd_pcm_hw_params_free (params); + return err; + } +no_rate: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Rate %iHz not available for playback: %s", + alsa->rate, snd_strerror (err))); + return err; + } +rate_match: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err)); + snd_pcm_hw_params_free (params); + return -EINVAL; + } +buffer_size: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to get buffer size for playback: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +period_size: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to get period size for playback: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +set_hw_params: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set hw params for playback: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +} + +static int +set_swparams (GstAlsaSink * alsa) +{ + int err; + snd_pcm_sw_params_t *params; + + snd_pcm_sw_params_malloc (¶ms); + + /* get the current swparams */ + CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config); + /* start the transfer when the buffer is almost full: */ + /* (buffer_size / avail_min) * avail_min */ + CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params, + (alsa->buffer_size / alsa->period_size) * alsa->period_size), + start_threshold); + + /* allow the transfer when at least period_size samples can be processed */ + CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params, + alsa->period_size), set_avail); + +#if GST_CHECK_ALSA_VERSION(1,0,16) + /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */ +#else + /* align all transfers to 1 sample */ + CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align); +#endif + + /* write the parameters to the playback device */ + CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params); + + snd_pcm_sw_params_free (params); + return 0; + + /* ERRORS */ +no_config: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to determine current swparams for playback: %s", + snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +start_threshold: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set start threshold mode for playback: %s", + snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +set_avail: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set avail min for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +#if !GST_CHECK_ALSA_VERSION(1,0,16) +set_align: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set transfer align for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +#endif +set_sw_params: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set sw params for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +} + +static gboolean +alsasink_parse_spec (GstAlsaSink * alsa, GstRingBufferSpec * spec) +{ + /* Initialize our boolean */ + alsa->iec958 = FALSE; + + switch (spec->type) { + case GST_BUFTYPE_LINEAR: + GST_DEBUG_OBJECT (alsa, + "Linear format : depth=%d, width=%d, sign=%d, bigend=%d", spec->depth, + spec->width, spec->sign, spec->bigend); + + alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width, + spec->sign ? 0 : 1, spec->bigend ? 1 : 0); + break; + case GST_BUFTYPE_FLOAT: + switch (spec->format) { + case GST_FLOAT32_LE: + alsa->format = SND_PCM_FORMAT_FLOAT_LE; + break; + case GST_FLOAT32_BE: + alsa->format = SND_PCM_FORMAT_FLOAT_BE; + break; + case GST_FLOAT64_LE: + alsa->format = SND_PCM_FORMAT_FLOAT64_LE; + break; + case GST_FLOAT64_BE: + alsa->format = SND_PCM_FORMAT_FLOAT64_BE; + break; + default: + goto error; + } + break; + case GST_BUFTYPE_A_LAW: + alsa->format = SND_PCM_FORMAT_A_LAW; + break; + case GST_BUFTYPE_MU_LAW: + alsa->format = SND_PCM_FORMAT_MU_LAW; + break; + case GST_BUFTYPE_IEC958: + alsa->format = SND_PCM_FORMAT_S16_BE; + alsa->iec958 = TRUE; + break; + default: + goto error; + + } + alsa->rate = spec->rate; + alsa->channels = spec->channels; + alsa->buffer_time = spec->buffer_time; + alsa->period_time = spec->latency_time; + alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED; + + return TRUE; + + /* ERRORS */ +error: + { + return FALSE; + } +} + +static gboolean +gst_alsasink_open (GstAudioSink * asink) +{ + GstAlsaSink *alsa; + gint err; + + alsa = GST_ALSA_SINK (asink); + + /* open in non-blocking mode, we'll use snd_pcm_wait() for space to become + * available. */ + CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_PLAYBACK, + SND_PCM_NONBLOCK), open_error); + GST_LOG_OBJECT (alsa, "Opened device %s", alsa->device); + + return TRUE; + + /* ERRORS */ +open_error: + { + if (err == -EBUSY) { + GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY, + (_("Could not open audio device for playback. " + "Device is being used by another application.")), + ("Device '%s' is busy", alsa->device)); + } else { + GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, + (_("Could not open audio device for playback.")), + ("Playback open error on device '%s': %s", alsa->device, + snd_strerror (err))); + } + return FALSE; + } +} + +static gboolean +gst_alsasink_prepare (GstAudioSink * asink, GstRingBufferSpec * spec) +{ + GstAlsaSink *alsa; + gint err; + + alsa = GST_ALSA_SINK (asink); + + if (spec->format == GST_IEC958) { + snd_pcm_close (alsa->handle); + alsa->handle = gst_alsa_open_iec958_pcm (GST_OBJECT (alsa)); + if (G_UNLIKELY (!alsa->handle)) { + goto no_iec958; + } + } + + if (!alsasink_parse_spec (alsa, spec)) + goto spec_parse; + + CHECK (set_hwparams (alsa), hw_params_failed); + CHECK (set_swparams (alsa), sw_params_failed); + + alsa->bytes_per_sample = spec->bytes_per_sample; + spec->segsize = alsa->period_size * spec->bytes_per_sample; + spec->segtotal = alsa->buffer_size / alsa->period_size; + + { + snd_output_t *out_buf = NULL; + char *msg = NULL; + + snd_output_buffer_open (&out_buf); + snd_pcm_dump_hw_setup (alsa->handle, out_buf); + snd_output_buffer_string (out_buf, &msg); + GST_DEBUG_OBJECT (alsa, "Hardware setup: \n%s", msg); + snd_output_close (out_buf); + snd_output_buffer_open (&out_buf); + snd_pcm_dump_sw_setup (alsa->handle, out_buf); + snd_output_buffer_string (out_buf, &msg); + GST_DEBUG_OBJECT (alsa, "Software setup: \n%s", msg); + snd_output_close (out_buf); + } + + return TRUE; + + /* ERRORS */ +no_iec958: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_WRITE, (NULL), + ("Could not open IEC958 (SPDIF) device for playback")); + return FALSE; + } +spec_parse: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Error parsing spec")); + return FALSE; + } +hw_params_failed: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Setting of hwparams failed: %s", snd_strerror (err))); + return FALSE; + } +sw_params_failed: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Setting of swparams failed: %s", snd_strerror (err))); + return FALSE; + } +} + +static gboolean +gst_alsasink_unprepare (GstAudioSink * asink) +{ + GstAlsaSink *alsa; + + alsa = GST_ALSA_SINK (asink); + + snd_pcm_drop (alsa->handle); + snd_pcm_hw_free (alsa->handle); + + return TRUE; +} + +static gboolean +gst_alsasink_close (GstAudioSink * asink) +{ + GstAlsaSink *alsa = GST_ALSA_SINK (asink); + + if (alsa->handle) { + snd_pcm_close (alsa->handle); + alsa->handle = NULL; + } + gst_caps_replace (&alsa->cached_caps, NULL); + + return TRUE; +} + + +/* + * Underrun and suspend recovery + */ +static gint +xrun_recovery (GstAlsaSink * alsa, snd_pcm_t * handle, gint err) +{ + GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err); + + if (err == -EPIPE) { /* under-run */ + err = snd_pcm_prepare (handle); + if (err < 0) + GST_WARNING_OBJECT (alsa, + "Can't recovery from underrun, prepare failed: %s", + snd_strerror (err)); + return 0; + } else if (err == -ESTRPIPE) { + while ((err = snd_pcm_resume (handle)) == -EAGAIN) + g_usleep (100); /* wait until the suspend flag is released */ + + if (err < 0) { + err = snd_pcm_prepare (handle); + if (err < 0) + GST_WARNING_OBJECT (alsa, + "Can't recovery from suspend, prepare failed: %s", + snd_strerror (err)); + } + return 0; + } + return err; +} + +static guint +gst_alsasink_write (GstAudioSink * asink, gpointer data, guint length) +{ + GstAlsaSink *alsa; + gint err; + gint cptr; + gint16 *ptr = data; + + alsa = GST_ALSA_SINK (asink); + + if (alsa->iec958 && alsa->need_swap) { + guint i; + + GST_DEBUG_OBJECT (asink, "swapping bytes"); + for (i = 0; i < length / 2; i++) { + ptr[i] = GUINT16_SWAP_LE_BE (ptr[i]); + } + } + + GST_LOG_OBJECT (asink, "received audio samples buffer of %u bytes", length); + + cptr = length / alsa->bytes_per_sample; + + GST_ALSA_SINK_LOCK (asink); + while (cptr > 0) { + /* start by doing a blocking wait for free space. Set the timeout + * to 4 times the period time */ + err = snd_pcm_wait (alsa->handle, (4 * alsa->period_time / 1000)); + if (err < 0) { + GST_DEBUG_OBJECT (asink, "wait error, %d", err); + } else { + err = snd_pcm_writei (alsa->handle, ptr, cptr); + } + + GST_DEBUG_OBJECT (asink, "written %d frames out of %d", err, cptr); + if (err < 0) { + GST_DEBUG_OBJECT (asink, "Write error: %s", snd_strerror (err)); + if (err == -EAGAIN) { + continue; + } else if (xrun_recovery (alsa, alsa->handle, err) < 0) { + goto write_error; + } + continue; + } + + ptr += snd_pcm_frames_to_bytes (alsa->handle, err); + cptr -= err; + } + GST_ALSA_SINK_UNLOCK (asink); + + return length - (cptr * alsa->bytes_per_sample); + +write_error: + { + GST_ALSA_SINK_UNLOCK (asink); + return length; /* skip one period */ + } +} + +static guint +gst_alsasink_delay (GstAudioSink * asink) +{ + GstAlsaSink *alsa; + snd_pcm_sframes_t delay; + int res; + + alsa = GST_ALSA_SINK (asink); + + res = snd_pcm_delay (alsa->handle, &delay); + if (G_UNLIKELY (res < 0)) { + /* on errors, report 0 delay */ + GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res); + delay = 0; + } + if (G_UNLIKELY (delay < 0)) { + /* make sure we never return a negative delay */ + GST_WARNING_OBJECT (alsa, "snd_pcm_delay returned negative delay"); + delay = 0; + } + + return delay; +} + +static void +gst_alsasink_reset (GstAudioSink * asink) +{ + GstAlsaSink *alsa; + gint err; + + alsa = GST_ALSA_SINK (asink); + + GST_ALSA_SINK_LOCK (asink); + GST_DEBUG_OBJECT (alsa, "drop"); + CHECK (snd_pcm_drop (alsa->handle), drop_error); + GST_DEBUG_OBJECT (alsa, "prepare"); + CHECK (snd_pcm_prepare (alsa->handle), prepare_error); + GST_DEBUG_OBJECT (alsa, "reset done"); + GST_ALSA_SINK_UNLOCK (asink); + + return; + + /* ERRORS */ +drop_error: + { + GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s", + snd_strerror (err)); + GST_ALSA_SINK_UNLOCK (asink); + return; + } +prepare_error: + { + GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s", + snd_strerror (err)); + GST_ALSA_SINK_UNLOCK (asink); + return; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.h new file mode 100644 index 0000000..902dbf7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasink.h @@ -0,0 +1,86 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstalsasink.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ALSASINK_H__ +#define __GST_ALSASINK_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_ALSA_SINK (gst_alsasink_get_type()) +#define GST_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SINK,GstAlsaSink)) +#define GST_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SINK,GstAlsaSinkClass)) +#define GST_IS_ALSA_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SINK)) +#define GST_IS_ALSA_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SINK)) +#define GST_ALSA_SINK_CAST(obj) ((GstAlsaSink *) (obj)) + +typedef struct _GstAlsaSink GstAlsaSink; +typedef struct _GstAlsaSinkClass GstAlsaSinkClass; + +#define GST_ALSA_SINK_GET_LOCK(obj) (GST_ALSA_SINK_CAST (obj)->alsa_lock) +#define GST_ALSA_SINK_LOCK(obj) (g_mutex_lock (GST_ALSA_SINK_GET_LOCK (obj))) +#define GST_ALSA_SINK_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_SINK_GET_LOCK (obj))) + +/** + * GstAlsaSink: + * + * Opaque data structure + */ +struct _GstAlsaSink { + GstAudioSink sink; + + gchar *device; + + snd_pcm_t *handle; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + + snd_pcm_access_t access; + snd_pcm_format_t format; + guint rate; + guint channels; + gint bytes_per_sample; + gboolean iec958; + gboolean need_swap; + + guint buffer_time; + guint period_time; + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + + GstCaps *cached_caps; + + GMutex *alsa_lock; +}; + +struct _GstAlsaSinkClass { + GstAudioSinkClass parent_class; +}; + +GType gst_alsasink_get_type(void); + +G_END_DECLS + +#endif /* __GST_ALSASINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.c b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.c new file mode 100644 index 0000000..d9e6bc8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.c @@ -0,0 +1,859 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstalsasrc.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-alsasrc + * @see_also: alsasink, alsamixer + * + * This element reads data from an audio card using the ALSA API. + * + * + * Example pipelines + * |[ + * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg + * ]| Record from a sound card using ALSA and encode to Ogg/Vorbis. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include + +#include "gstalsasrc.h" +#include "gstalsadeviceprobe.h" + +#include + +#define DEFAULT_PROP_DEVICE "default" +#define DEFAULT_PROP_DEVICE_NAME "" +#define DEFAULT_PROP_CARD_NAME "" + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_NAME, + PROP_CARD_NAME, + PROP_LAST +}; + +static void gst_alsasrc_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstAlsaSrc, gst_alsasrc, GstAudioSrc, + GST_TYPE_AUDIO_SRC, gst_alsasrc_init_interfaces); + +GST_IMPLEMENT_ALSA_MIXER_METHODS (GstAlsaSrc, gst_alsasrc_mixer); + +static void gst_alsasrc_finalize (GObject * object); +static void gst_alsasrc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_alsasrc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstCaps *gst_alsasrc_getcaps (GstBaseSrc * bsrc); + +static gboolean gst_alsasrc_open (GstAudioSrc * asrc); +static gboolean gst_alsasrc_prepare (GstAudioSrc * asrc, + GstRingBufferSpec * spec); +static gboolean gst_alsasrc_unprepare (GstAudioSrc * asrc); +static gboolean gst_alsasrc_close (GstAudioSrc * asrc); +static guint gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length); +static guint gst_alsasrc_delay (GstAudioSrc * asrc); +static void gst_alsasrc_reset (GstAudioSrc * asrc); + +/* AlsaSrc signals and args */ +enum +{ + LAST_SIGNAL +}; + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +# define ALSA_SRC_FACTORY_ENDIANNESS "LITTLE_ENDIAN, BIG_ENDIAN" +#else +# define ALSA_SRC_FACTORY_ENDIANNESS "BIG_ENDIAN, LITTLE_ENDIAN" +#endif + +static GstStaticPadTemplate alsasrc_src_factory = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 32, " + "depth = (int) 32, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 32, " + "depth = (int) 24, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 24, " + "depth = (int) 24, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "endianness = (int) { " ALSA_SRC_FACTORY_ENDIANNESS " }, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 16, " + "depth = (int) 16, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]; " + "audio/x-raw-int, " + "signed = (boolean) { TRUE, FALSE }, " + "width = (int) 8, " + "depth = (int) 8, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]") + ); + +static void +gst_alsasrc_finalize (GObject * object) +{ + GstAlsaSrc *src = GST_ALSA_SRC (object); + + g_free (src->device); + g_mutex_free (src->alsa_lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_alsasrc_interface_supported (GstAlsaSrc * this, GType interface_type) +{ + /* only support this one interface (wrapped by GstImplementsInterface) */ + g_assert (interface_type == GST_TYPE_MIXER); + + return gst_alsasrc_mixer_supported (this, interface_type); +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = (gpointer) gst_alsasrc_interface_supported; +} + +static void +gst_alsasrc_init_interfaces (GType type) +{ + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) gst_alsasrc_mixer_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); + + gst_alsa_type_add_device_property_probe_interface (type); +} + +static void +gst_alsasrc_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Audio source (ALSA)", "Source/Audio", + "Read from a sound card via ALSA", "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&alsasrc_src_factory)); +} + +static void +gst_alsasrc_class_init (GstAlsaSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + GstAudioSrcClass *gstaudiosrc_class; + + gobject_class = (GObjectClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstaudiosrc_class = (GstAudioSrcClass *) klass; + + gobject_class->finalize = gst_alsasrc_finalize; + gobject_class->get_property = gst_alsasrc_get_property; + gobject_class->set_property = gst_alsasrc_set_property; + + gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_alsasrc_getcaps); + + gstaudiosrc_class->open = GST_DEBUG_FUNCPTR (gst_alsasrc_open); + gstaudiosrc_class->prepare = GST_DEBUG_FUNCPTR (gst_alsasrc_prepare); + gstaudiosrc_class->unprepare = GST_DEBUG_FUNCPTR (gst_alsasrc_unprepare); + gstaudiosrc_class->close = GST_DEBUG_FUNCPTR (gst_alsasrc_close); + gstaudiosrc_class->read = GST_DEBUG_FUNCPTR (gst_alsasrc_read); + gstaudiosrc_class->delay = GST_DEBUG_FUNCPTR (gst_alsasrc_delay); + gstaudiosrc_class->reset = GST_DEBUG_FUNCPTR (gst_alsasrc_reset); + + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Device", + "ALSA device, as defined in an asound configuration file", + DEFAULT_PROP_DEVICE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Device name", + "Human-readable name of the sound device", + DEFAULT_PROP_DEVICE_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CARD_NAME, + g_param_spec_string ("card-name", "Card name", + "Human-readable name of the sound card", + DEFAULT_PROP_CARD_NAME, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_alsasrc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAlsaSrc *src; + + src = GST_ALSA_SRC (object); + + switch (prop_id) { + case PROP_DEVICE: + g_free (src->device); + src->device = g_value_dup_string (value); + if (src->device == NULL) { + src->device = g_strdup (DEFAULT_PROP_DEVICE); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_alsasrc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAlsaSrc *src; + + src = GST_ALSA_SRC (object); + + switch (prop_id) { + case PROP_DEVICE: + g_value_set_string (value, src->device); + break; + case PROP_DEVICE_NAME: + g_value_take_string (value, + gst_alsa_find_device_name (GST_OBJECT_CAST (src), + src->device, src->handle, SND_PCM_STREAM_CAPTURE)); + break; + case PROP_CARD_NAME: + g_value_take_string (value, + gst_alsa_find_card_name (GST_OBJECT_CAST (src), + src->device, SND_PCM_STREAM_CAPTURE)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_alsasrc_init (GstAlsaSrc * alsasrc, GstAlsaSrcClass * g_class) +{ + GST_DEBUG_OBJECT (alsasrc, "initializing"); + + alsasrc->device = g_strdup (DEFAULT_PROP_DEVICE); + alsasrc->cached_caps = NULL; + + alsasrc->alsa_lock = g_mutex_new (); +} + +#define CHECK(call, error) \ +G_STMT_START { \ +if ((err = call) < 0) \ + goto error; \ +} G_STMT_END; + + +static GstCaps * +gst_alsasrc_getcaps (GstBaseSrc * bsrc) +{ + GstElementClass *element_class; + GstPadTemplate *pad_template; + GstAlsaSrc *src; + GstCaps *caps; + + src = GST_ALSA_SRC (bsrc); + + if (src->handle == NULL) { + GST_DEBUG_OBJECT (src, "device not open, using template caps"); + return NULL; /* base class will get template caps for us */ + } + + if (src->cached_caps) { + GST_LOG_OBJECT (src, "Returning cached caps"); + return gst_caps_ref (src->cached_caps); + } + + element_class = GST_ELEMENT_GET_CLASS (src); + pad_template = gst_element_class_get_pad_template (element_class, "src"); + g_return_val_if_fail (pad_template != NULL, NULL); + + caps = gst_alsa_probe_supported_formats (GST_OBJECT (src), src->handle, + gst_pad_template_get_caps (pad_template)); + + if (caps) { + src->cached_caps = gst_caps_ref (caps); + } + + GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps); + + return caps; +} + +static int +set_hwparams (GstAlsaSrc * alsa) +{ + guint rrate; + gint err; + snd_pcm_hw_params_t *params; + + snd_pcm_hw_params_malloc (¶ms); + + /* choose all parameters */ + CHECK (snd_pcm_hw_params_any (alsa->handle, params), no_config); + /* set the interleaved read/write format */ + CHECK (snd_pcm_hw_params_set_access (alsa->handle, params, alsa->access), + wrong_access); + /* set the sample format */ + CHECK (snd_pcm_hw_params_set_format (alsa->handle, params, alsa->format), + no_sample_format); + /* set the count of channels */ + CHECK (snd_pcm_hw_params_set_channels (alsa->handle, params, alsa->channels), + no_channels); + /* set the stream rate */ + rrate = alsa->rate; + CHECK (snd_pcm_hw_params_set_rate_near (alsa->handle, params, &rrate, NULL), + no_rate); + if (rrate != alsa->rate) + goto rate_match; + + if (alsa->buffer_time != -1) { + /* set the buffer time */ + CHECK (snd_pcm_hw_params_set_buffer_time_near (alsa->handle, params, + &alsa->buffer_time, NULL), buffer_time); + } + if (alsa->period_time != -1) { + /* set the period time */ + CHECK (snd_pcm_hw_params_set_period_time_near (alsa->handle, params, + &alsa->period_time, NULL), period_time); + } + + /* write the parameters to device */ + CHECK (snd_pcm_hw_params (alsa->handle, params), set_hw_params); + + CHECK (snd_pcm_hw_params_get_buffer_size (params, &alsa->buffer_size), + buffer_size); + + CHECK (snd_pcm_hw_params_get_period_size (params, &alsa->period_size, NULL), + period_size); + + snd_pcm_hw_params_free (params); + return 0; + + /* ERRORS */ +no_config: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Broken configuration for recording: no configurations available: %s", + snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +wrong_access: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Access type not available for recording: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +no_sample_format: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Sample format not available for recording: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +no_channels: + { + gchar *msg = NULL; + + if ((alsa->channels) == 1) + msg = g_strdup (_("Could not open device for recording in mono mode.")); + if ((alsa->channels) == 2) + msg = g_strdup (_("Could not open device for recording in stereo mode.")); + if ((alsa->channels) > 2) + msg = + g_strdup_printf (_ + ("Could not open device for recording in %d-channel mode"), + alsa->channels); + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, ("%s", msg), + ("%s", snd_strerror (err))); + g_free (msg); + snd_pcm_hw_params_free (params); + return err; + } +no_rate: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Rate %iHz not available for recording: %s", + alsa->rate, snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +rate_match: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Rate doesn't match (requested %iHz, get %iHz)", alsa->rate, err)); + snd_pcm_hw_params_free (params); + return -EINVAL; + } +buffer_time: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set buffer time %i for recording: %s", + alsa->buffer_time, snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +buffer_size: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to get buffer size for recording: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +period_time: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set period time %i for recording: %s", alsa->period_time, + snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +period_size: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to get period size for recording: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +set_hw_params: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set hw params for recording: %s", snd_strerror (err))); + snd_pcm_hw_params_free (params); + return err; + } +} + +static int +set_swparams (GstAlsaSrc * alsa) +{ + int err; + snd_pcm_sw_params_t *params; + + snd_pcm_sw_params_malloc (¶ms); + + /* get the current swparams */ + CHECK (snd_pcm_sw_params_current (alsa->handle, params), no_config); + /* allow the transfer when at least period_size samples can be processed */ + CHECK (snd_pcm_sw_params_set_avail_min (alsa->handle, params, + alsa->period_size), set_avail); + /* start the transfer on first read */ + CHECK (snd_pcm_sw_params_set_start_threshold (alsa->handle, params, + 0), start_threshold); + +#if GST_CHECK_ALSA_VERSION(1,0,16) + /* snd_pcm_sw_params_set_xfer_align() is deprecated, alignment is always 1 */ +#else + /* align all transfers to 1 sample */ + CHECK (snd_pcm_sw_params_set_xfer_align (alsa->handle, params, 1), set_align); +#endif + + /* write the parameters to the recording device */ + CHECK (snd_pcm_sw_params (alsa->handle, params), set_sw_params); + + snd_pcm_sw_params_free (params); + return 0; + + /* ERRORS */ +no_config: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to determine current swparams for playback: %s", + snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +start_threshold: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set start threshold mode for playback: %s", + snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +set_avail: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set avail min for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +#if !GST_CHECK_ALSA_VERSION(1,0,16) +set_align: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set transfer align for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +#endif +set_sw_params: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Unable to set sw params for playback: %s", snd_strerror (err))); + snd_pcm_sw_params_free (params); + return err; + } +} + +static gboolean +alsasrc_parse_spec (GstAlsaSrc * alsa, GstRingBufferSpec * spec) +{ + switch (spec->type) { + case GST_BUFTYPE_LINEAR: + alsa->format = snd_pcm_build_linear_format (spec->depth, spec->width, + spec->sign ? 0 : 1, spec->bigend ? 1 : 0); + break; + case GST_BUFTYPE_FLOAT: + switch (spec->format) { + case GST_FLOAT32_LE: + alsa->format = SND_PCM_FORMAT_FLOAT_LE; + break; + case GST_FLOAT32_BE: + alsa->format = SND_PCM_FORMAT_FLOAT_BE; + break; + case GST_FLOAT64_LE: + alsa->format = SND_PCM_FORMAT_FLOAT64_LE; + break; + case GST_FLOAT64_BE: + alsa->format = SND_PCM_FORMAT_FLOAT64_BE; + break; + default: + goto error; + } + break; + case GST_BUFTYPE_A_LAW: + alsa->format = SND_PCM_FORMAT_A_LAW; + break; + case GST_BUFTYPE_MU_LAW: + alsa->format = SND_PCM_FORMAT_MU_LAW; + break; + default: + goto error; + + } + alsa->rate = spec->rate; + alsa->channels = spec->channels; + alsa->buffer_time = spec->buffer_time; + alsa->period_time = spec->latency_time; + alsa->access = SND_PCM_ACCESS_RW_INTERLEAVED; + + return TRUE; + + /* ERRORS */ +error: + { + return FALSE; + } +} + +static gboolean +gst_alsasrc_open (GstAudioSrc * asrc) +{ + GstAlsaSrc *alsa; + gint err; + + alsa = GST_ALSA_SRC (asrc); + + CHECK (snd_pcm_open (&alsa->handle, alsa->device, SND_PCM_STREAM_CAPTURE, + SND_PCM_NONBLOCK), open_error); + + if (!alsa->mixer) + alsa->mixer = gst_alsa_mixer_new (alsa->device, GST_ALSA_MIXER_CAPTURE); + + return TRUE; + + /* ERRORS */ +open_error: + { + if (err == -EBUSY) { + GST_ELEMENT_ERROR (alsa, RESOURCE, BUSY, + (_("Could not open audio device for recording. " + "Device is being used by another application.")), + ("Device '%s' is busy", alsa->device)); + } else { + GST_ELEMENT_ERROR (alsa, RESOURCE, OPEN_READ, + (_("Could not open audio device for recording.")), + ("Recording open error on device '%s': %s", alsa->device, + snd_strerror (err))); + } + return FALSE; + } +} + +static gboolean +gst_alsasrc_prepare (GstAudioSrc * asrc, GstRingBufferSpec * spec) +{ + GstAlsaSrc *alsa; + gint err; + + alsa = GST_ALSA_SRC (asrc); + + if (!alsasrc_parse_spec (alsa, spec)) + goto spec_parse; + + CHECK (snd_pcm_nonblock (alsa->handle, 0), non_block); + + CHECK (set_hwparams (alsa), hw_params_failed); + CHECK (set_swparams (alsa), sw_params_failed); + CHECK (snd_pcm_prepare (alsa->handle), prepare_failed); + + alsa->bytes_per_sample = spec->bytes_per_sample; + spec->segsize = alsa->period_size * spec->bytes_per_sample; + spec->segtotal = alsa->buffer_size / alsa->period_size; + spec->silence_sample[0] = 0; + spec->silence_sample[1] = 0; + spec->silence_sample[2] = 0; + spec->silence_sample[3] = 0; + + return TRUE; + + /* ERRORS */ +spec_parse: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Error parsing spec")); + return FALSE; + } +non_block: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Could not set device to blocking: %s", snd_strerror (err))); + return FALSE; + } +hw_params_failed: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Setting of hwparams failed: %s", snd_strerror (err))); + return FALSE; + } +sw_params_failed: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Setting of swparams failed: %s", snd_strerror (err))); + return FALSE; + } +prepare_failed: + { + GST_ELEMENT_ERROR (alsa, RESOURCE, SETTINGS, (NULL), + ("Prepare failed: %s", snd_strerror (err))); + return FALSE; + } +} + +static gboolean +gst_alsasrc_unprepare (GstAudioSrc * asrc) +{ + GstAlsaSrc *alsa; + + alsa = GST_ALSA_SRC (asrc); + + snd_pcm_drop (alsa->handle); + snd_pcm_hw_free (alsa->handle); + snd_pcm_nonblock (alsa->handle, 1); + + return TRUE; +} + +static gboolean +gst_alsasrc_close (GstAudioSrc * asrc) +{ + GstAlsaSrc *alsa = GST_ALSA_SRC (asrc); + + snd_pcm_close (alsa->handle); + alsa->handle = NULL; + + if (alsa->mixer) { + gst_alsa_mixer_free (alsa->mixer); + alsa->mixer = NULL; + } + + gst_caps_replace (&alsa->cached_caps, NULL); + + return TRUE; +} + +/* + * Underrun and suspend recovery + */ +static gint +xrun_recovery (GstAlsaSrc * alsa, snd_pcm_t * handle, gint err) +{ + GST_DEBUG_OBJECT (alsa, "xrun recovery %d", err); + + if (err == -EPIPE) { /* under-run */ + err = snd_pcm_prepare (handle); + if (err < 0) + GST_WARNING_OBJECT (alsa, + "Can't recovery from underrun, prepare failed: %s", + snd_strerror (err)); + return 0; + } else if (err == -ESTRPIPE) { + while ((err = snd_pcm_resume (handle)) == -EAGAIN) + g_usleep (100); /* wait until the suspend flag is released */ + + if (err < 0) { + err = snd_pcm_prepare (handle); + if (err < 0) + GST_WARNING_OBJECT (alsa, + "Can't recovery from suspend, prepare failed: %s", + snd_strerror (err)); + } + return 0; + } + return err; +} + +static guint +gst_alsasrc_read (GstAudioSrc * asrc, gpointer data, guint length) +{ + GstAlsaSrc *alsa; + gint err; + gint cptr; + gint16 *ptr; + + alsa = GST_ALSA_SRC (asrc); + + cptr = length / alsa->bytes_per_sample; + ptr = data; + + GST_ALSA_SRC_LOCK (asrc); + while (cptr > 0) { + if ((err = snd_pcm_readi (alsa->handle, ptr, cptr)) < 0) { + if (err == -EAGAIN) { + GST_DEBUG_OBJECT (asrc, "Read error: %s", snd_strerror (err)); + continue; + } else if (xrun_recovery (alsa, alsa->handle, err) < 0) { + goto read_error; + } + continue; + } + + ptr += err * alsa->channels; + cptr -= err; + } + GST_ALSA_SRC_UNLOCK (asrc); + + return length - (cptr * alsa->bytes_per_sample); + +read_error: + { + GST_ALSA_SRC_UNLOCK (asrc); + return length; /* skip one period */ + } +} + +static guint +gst_alsasrc_delay (GstAudioSrc * asrc) +{ + GstAlsaSrc *alsa; + snd_pcm_sframes_t delay; + int res; + + alsa = GST_ALSA_SRC (asrc); + + res = snd_pcm_delay (alsa->handle, &delay); + if (G_UNLIKELY (res < 0)) { + GST_DEBUG_OBJECT (alsa, "snd_pcm_delay returned %d", res); + delay = 0; + } + + return CLAMP (delay, 0, alsa->buffer_size); +} + +static void +gst_alsasrc_reset (GstAudioSrc * asrc) +{ + GstAlsaSrc *alsa; + gint err; + + alsa = GST_ALSA_SRC (asrc); + + GST_ALSA_SRC_LOCK (asrc); + GST_DEBUG_OBJECT (alsa, "drop"); + CHECK (snd_pcm_drop (alsa->handle), drop_error); + GST_DEBUG_OBJECT (alsa, "prepare"); + CHECK (snd_pcm_prepare (alsa->handle), prepare_error); + GST_DEBUG_OBJECT (alsa, "reset done"); + GST_ALSA_SRC_UNLOCK (asrc); + + return; + + /* ERRORS */ +drop_error: + { + GST_ERROR_OBJECT (alsa, "alsa-reset: pcm drop error: %s", + snd_strerror (err)); + GST_ALSA_SRC_UNLOCK (asrc); + return; + } +prepare_error: + { + GST_ERROR_OBJECT (alsa, "alsa-reset: pcm prepare error: %s", + snd_strerror (err)); + GST_ALSA_SRC_UNLOCK (asrc); + return; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.h b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.h new file mode 100644 index 0000000..d0fcbf0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/alsa/gstalsasrc.h @@ -0,0 +1,86 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstalsasrc.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_ALSASRC_H__ +#define __GST_ALSASRC_H__ + +#include +#include "gstalsa.h" +#include "gstalsamixer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_ALSA_SRC (gst_alsasrc_get_type()) +#define GST_ALSA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ALSA_SRC,GstAlsaSrc)) +#define GST_ALSA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ALSA_SRC,GstAlsaSrcClass)) +#define GST_IS_ALSA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ALSA_SRC)) +#define GST_IS_ALSA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ALSA_SRC)) +#define GST_ALSA_SRC_CAST(obj) ((GstAlsaSrc *)(obj)) + +#define GST_ALSA_SRC_GET_LOCK(obj) (GST_ALSA_SRC_CAST (obj)->alsa_lock) +#define GST_ALSA_SRC_LOCK(obj) (g_mutex_lock (GST_ALSA_SRC_GET_LOCK (obj))) +#define GST_ALSA_SRC_UNLOCK(obj) (g_mutex_unlock (GST_ALSA_SRC_GET_LOCK (obj))) + +typedef struct _GstAlsaSrc GstAlsaSrc; +typedef struct _GstAlsaSrcClass GstAlsaSrcClass; + +/** + * GstAlsaSrc: + * + * Opaque data structure + */ +struct _GstAlsaSrc { + GstAudioSrc src; + + gchar *device; + + snd_pcm_t *handle; + snd_pcm_hw_params_t *hwparams; + snd_pcm_sw_params_t *swparams; + + GstCaps *cached_caps; + + snd_pcm_access_t access; + snd_pcm_format_t format; + guint rate; + guint channels; + gint bytes_per_sample; + + guint buffer_time; + guint period_time; + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + + GstAlsaMixer *mixer; + + GMutex *alsa_lock; +}; + +struct _GstAlsaSrcClass { + GstAudioSrcClass parent_class; +}; + +GType gst_alsasrc_get_type(void); + +G_END_DECLS + +#endif /* __GST_ALSASRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/cdparanoia/Makefile.am b/gst-plugins-base-subtitles0.10/ext/cdparanoia/Makefile.am new file mode 100644 index 0000000..e2a2238 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/cdparanoia/Makefile.am @@ -0,0 +1,17 @@ +plugin_LTLIBRARIES = libgstcdparanoia.la + +libgstcdparanoia_la_SOURCES = gstcdparanoiasrc.c +libgstcdparanoia_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) \ + $(CDPARANOIA_CFLAGS) +libgstcdparanoia_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/cdda/libgstcdda-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(CDPARANOIA_LIBS) +libgstcdparanoia_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstcdparanoia_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstcdparanoiasrc.h diff --git a/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.c b/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.c new file mode 100644 index 0000000..5ea182d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.c @@ -0,0 +1,541 @@ +/* -*- Mode: C; tab-width: 2; indent-tabs-mode: t; c-basic-offset: 2 -*- */ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * <2005> Wim Taymans + * <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "gstcdparanoiasrc.h" +#include "gst/gst-i18n-plugin.h" + +enum +{ + TRANSPORT_ERROR, + UNCORRECTED_ERROR, + NUM_SIGNALS +}; + +enum +{ + PROP_0, + PROP_READ_SPEED, + PROP_PARANOIA_MODE, + PROP_SEARCH_OVERLAP, + PROP_GENERIC_DEVICE, + PROP_CACHE_SIZE +}; + +#define DEFAULT_READ_SPEED -1 +#define DEFAULT_SEARCH_OVERLAP -1 +#define DEFAULT_PARANOIA_MODE PARANOIA_MODE_FRAGMENT +#define DEFAULT_GENERIC_DEVICE NULL +#define DEFAULT_CACHE_SIZE -1 + +GST_DEBUG_CATEGORY_STATIC (gst_cd_paranoia_src_debug); +#define GST_CAT_DEFAULT gst_cd_paranoia_src_debug + +GST_BOILERPLATE (GstCdParanoiaSrc, gst_cd_paranoia_src, GstCddaBaseSrc, + GST_TYPE_CDDA_BASE_SRC); + +static void gst_cd_paranoia_src_finalize (GObject * obj); +static void gst_cd_paranoia_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_cd_paranoia_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static GstBuffer *gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * src, + gint sector); +static gboolean gst_cd_paranoia_src_open (GstCddaBaseSrc * src, + const gchar * device); +static void gst_cd_paranoia_src_close (GstCddaBaseSrc * src); + +/* We use these to serialize calls to paranoia_read() among several + * cdparanoiasrc instances. We do this because it's the only reasonably + * easy way to find out the calling object from within the paranoia + * callback, and we need the object instance in there to emit our signals */ +static GstCdParanoiaSrc *cur_cb_source; +static GStaticMutex cur_cb_mutex = G_STATIC_MUTEX_INIT; + +static gint cdpsrc_signals[NUM_SIGNALS]; /* all 0 */ + +#define GST_TYPE_CD_PARANOIA_MODE (gst_cd_paranoia_mode_get_type()) +static GType +gst_cd_paranoia_mode_get_type (void) +{ + static const GFlagsValue paranoia_modes[] = { + {PARANOIA_MODE_DISABLE, "PARANOIA_MODE_DISABLE", "disable"}, + {PARANOIA_MODE_FRAGMENT, "PARANOIA_MODE_FRAGMENT", "fragment"}, + {PARANOIA_MODE_OVERLAP, "PARANOIA_MODE_OVERLAP", "overlap"}, + {PARANOIA_MODE_SCRATCH, "PARANOIA_MODE_SCRATCH", "scratch"}, + {PARANOIA_MODE_REPAIR, "PARANOIA_MODE_REPAIR", "repair"}, + {PARANOIA_MODE_FULL, "PARANOIA_MODE_FULL", "full"}, + {0, NULL, NULL}, + }; + + static GType type; /* 0 */ + + if (!type) { + type = g_flags_register_static ("GstCdParanoiaMode", paranoia_modes); + } + + return type; +} + +static void +gst_cd_paranoia_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "CD Audio (cdda) Source, Paranoia IV", "Source/File", + "Read audio from CD in paranoid mode", + "Erik Walthinsen , Wim Taymans "); +} + +static void +gst_cd_paranoia_src_init (GstCdParanoiaSrc * src, GstCdParanoiaSrcClass * klass) +{ + src->d = NULL; + src->p = NULL; + src->next_sector = -1; + + src->search_overlap = DEFAULT_SEARCH_OVERLAP; + src->paranoia_mode = DEFAULT_PARANOIA_MODE; + src->read_speed = DEFAULT_READ_SPEED; + src->generic_device = g_strdup (DEFAULT_GENERIC_DEVICE); + src->cache_size = DEFAULT_CACHE_SIZE; +} + +static void +gst_cd_paranoia_src_class_init (GstCdParanoiaSrcClass * klass) +{ + GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->set_property = gst_cd_paranoia_src_set_property; + gobject_class->get_property = gst_cd_paranoia_src_get_property; + gobject_class->finalize = gst_cd_paranoia_src_finalize; + + cddabasesrc_class->open = gst_cd_paranoia_src_open; + cddabasesrc_class->close = gst_cd_paranoia_src_close; + cddabasesrc_class->read_sector = gst_cd_paranoia_src_read_sector; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_GENERIC_DEVICE, + g_param_spec_string ("generic-device", "Generic device", + "Use specified generic scsi device", DEFAULT_GENERIC_DEVICE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_READ_SPEED, + g_param_spec_int ("read-speed", "Read speed", + "Read from device at specified speed", -1, G_MAXINT, + DEFAULT_READ_SPEED, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PARANOIA_MODE, + g_param_spec_flags ("paranoia-mode", "Paranoia mode", + "Type of checking to perform", GST_TYPE_CD_PARANOIA_MODE, + DEFAULT_PARANOIA_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEARCH_OVERLAP, + g_param_spec_int ("search-overlap", "Search overlap", + "Force minimum overlap search during verification to n sectors", -1, + 75, DEFAULT_SEARCH_OVERLAP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstCdParanoiaSrc:cache-size + * + * Set CD cache size to n sectors (-1 = auto) + * + * Since: 0.10.24 + */ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_CACHE_SIZE, + g_param_spec_int ("cache-size", "Cache size", + "Set CD cache size to n sectors (-1 = auto)", -1, + G_MAXINT, DEFAULT_CACHE_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* FIXME: we don't really want signals for this, but messages on the bus, + * but then we can't check any longer whether anyone is interested in them */ + /** + * GstCdParanoiaSrc::transport-error + * @cdparanoia: The CdParanoia instance + * @sector: The sector number at which the error was encountered. + * + * This signal is emitted whenever an error occurs while reading. + * CdParanoia will attempt to recover the data. + */ + cdpsrc_signals[TRANSPORT_ERROR] = + g_signal_new ("transport-error", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstCdParanoiaSrcClass, transport_error), + NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + /** + * GstCdParanoiaSrc::uncorrected-error + * @cdparanoia: The CdParanoia instance + * @sector: The sector number at which the error was encountered. + * + * This signal is emitted whenever an uncorrectable error occurs while + * reading. The data could not be read. + */ + cdpsrc_signals[UNCORRECTED_ERROR] = + g_signal_new ("uncorrected-error", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstCdParanoiaSrcClass, uncorrected_error), + NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); +} + +static gboolean +gst_cd_paranoia_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + gint i, cache_size; + + GST_DEBUG_OBJECT (src, "trying to open device %s (generic-device=%s) ...", + device, GST_STR_NULL (src->generic_device)); + + /* find the device */ + if (src->generic_device != NULL) { + src->d = cdda_identify_scsi (src->generic_device, device, FALSE, NULL); + } else { + if (device != NULL) { + src->d = cdda_identify (device, FALSE, NULL); + } else { + src->d = cdda_identify ("/dev/cdrom", FALSE, NULL); + } + } + + /* fail if the device couldn't be found */ + if (src->d == NULL) + goto no_device; + + /* set verbosity mode */ + cdda_verbose_set (src->d, CDDA_MESSAGE_FORGETIT, CDDA_MESSAGE_FORGETIT); + + /* open the disc */ + if (cdda_open (src->d)) + goto open_failed; + + if (src->read_speed != -1) { + cdda_speed_set (src->d, src->read_speed); + } + + for (i = 1; i < src->d->tracks + 1; i++) { + GstCddaBaseSrcTrack track = { 0, }; + + track.num = i; + track.is_audio = IS_AUDIO (src->d, i - 1); + track.start = cdda_track_firstsector (src->d, i); + track.end = cdda_track_lastsector (src->d, i); + track.tags = NULL; + + gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &track); + } + + /* create the paranoia struct and set it up */ + src->p = paranoia_init (src->d); + if (src->p == NULL) + goto init_failed; + + paranoia_modeset (src->p, src->paranoia_mode); + GST_INFO_OBJECT (src, "set paranoia mode to 0x%02x", src->paranoia_mode); + + if (src->search_overlap != -1) { + paranoia_overlapset (src->p, src->search_overlap); + GST_INFO_OBJECT (src, "search overlap set to %u", src->search_overlap); + } + + cache_size = src->cache_size; + if (cache_size == -1) { + /* if paranoia mode is low (the default), assume we're doing playback */ + if (src->paranoia_mode <= PARANOIA_MODE_FRAGMENT) + cache_size = 150; + else + cache_size = paranoia_cachemodel_size (src->p, -1); + } + paranoia_cachemodel_size (src->p, cache_size); + GST_INFO_OBJECT (src, "set cachemodel size to %u", cache_size); + + src->next_sector = -1; + + return TRUE; + + /* ERRORS */ +no_device: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not open CD device for reading.")), ("cdda_identify failed")); + return FALSE; + } +open_failed: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Could not open CD device for reading.")), ("cdda_open failed")); + cdda_close (src->d); + src->d = NULL; + return FALSE; + } +init_failed: + { + GST_ELEMENT_ERROR (src, LIBRARY, INIT, + ("failed to initialize paranoia"), ("failed to initialize paranoia")); + return FALSE; + } +} + +static void +gst_cd_paranoia_src_close (GstCddaBaseSrc * cddabasesrc) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + + if (src->p) { + paranoia_free (src->p); + src->p = NULL; + } + + if (src->d) { + cdda_close (src->d); + src->d = NULL; + } + + src->next_sector = -1; +} + +static void +gst_cd_paranoia_dummy_callback (long inpos, int function) +{ + /* Used by instanced where no one is interested what's happening here */ +} + +static void +gst_cd_paranoia_paranoia_callback (long inpos, int function) +{ + GstCdParanoiaSrc *src = cur_cb_source; + gint sector = (gint) (inpos / CD_FRAMEWORDS); + + switch (function) { + case PARANOIA_CB_SKIP: + GST_INFO_OBJECT (src, "Skip at sector %d", sector); + g_signal_emit (src, cdpsrc_signals[UNCORRECTED_ERROR], 0, sector); + break; + case PARANOIA_CB_READERR: + GST_INFO_OBJECT (src, "Transport error at sector %d", sector); + g_signal_emit (src, cdpsrc_signals[TRANSPORT_ERROR], 0, sector); + break; + default: + break; + } +} + +static gboolean +gst_cd_paranoia_src_signal_is_being_watched (GstCdParanoiaSrc * src, gint sig) +{ + return g_signal_has_handler_pending (src, cdpsrc_signals[sig], 0, FALSE); +} + +static GstBuffer * +gst_cd_paranoia_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (cddabasesrc); + GstBuffer *buf; + gboolean do_serialize; + gint16 *cdda_buf; + +#if 0 + /* Do we really need to output this? (tpm) */ + /* Due to possible autocorrections of start sectors of audio tracks on + * multisession cds, we can maybe not compute the correct discid. + * So issue a warning. + * See cdparanoia/interface/common-interface.c:FixupTOC */ + if (src->d && src->d->cd_extra) { + g_message + ("DiscID on multisession discs might be broken. Use at own risk."); + } +#endif + + if (src->next_sector == -1 || src->next_sector != sector) { + if (paranoia_seek (src->p, sector, SEEK_SET) == -1) + goto seek_failed; + + GST_DEBUG_OBJECT (src, "successfully seeked to sector %d", sector); + src->next_sector = sector; + } + + do_serialize = + gst_cd_paranoia_src_signal_is_being_watched (src, TRANSPORT_ERROR) || + gst_cd_paranoia_src_signal_is_being_watched (src, UNCORRECTED_ERROR); + + if (do_serialize) { + GST_LOG_OBJECT (src, "Signal handlers connected, serialising access"); + g_static_mutex_lock (&cur_cb_mutex); + GST_LOG_OBJECT (src, "Got lock"); + cur_cb_source = src; + + cdda_buf = paranoia_read (src->p, gst_cd_paranoia_paranoia_callback); + + cur_cb_source = NULL; + GST_LOG_OBJECT (src, "Releasing lock"); + g_static_mutex_unlock (&cur_cb_mutex); + } else { + cdda_buf = paranoia_read (src->p, gst_cd_paranoia_dummy_callback); + } + + if (cdda_buf == NULL) + goto read_failed; + + buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW); + memcpy (GST_BUFFER_DATA (buf), cdda_buf, CD_FRAMESIZE_RAW); + + /* cdda base class will take care of timestamping etc. */ + ++src->next_sector; + + return buf; + + /* ERRORS */ +seek_failed: + { + GST_WARNING_OBJECT (src, "seek to sector %d failed!", sector); + GST_ELEMENT_ERROR (src, RESOURCE, SEEK, + (_("Could not seek CD.")), + ("paranoia_seek to %d failed: %s", sector, g_strerror (errno))); + return NULL; + } +read_failed: + { + GST_WARNING_OBJECT (src, "read at sector %d failed!", sector); + GST_ELEMENT_ERROR (src, RESOURCE, READ, + (_("Could not read CD.")), + ("paranoia_read at %d failed: %s", sector, g_strerror (errno))); + return NULL; + } +} + +static void +gst_cd_paranoia_src_finalize (GObject * obj) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (obj); + + g_free (src->generic_device); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_cd_paranoia_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case PROP_GENERIC_DEVICE:{ + g_free (src->generic_device); + src->generic_device = g_value_dup_string (value); + if (src->generic_device && src->generic_device[0] == '\0') { + g_free (src->generic_device); + src->generic_device = NULL; + } + break; + } + case PROP_READ_SPEED:{ + src->read_speed = g_value_get_int (value); + if (src->read_speed == 0) + src->read_speed = -1; + break; + } + case PROP_PARANOIA_MODE:{ + src->paranoia_mode = g_value_get_flags (value) & PARANOIA_MODE_FULL; + break; + } + case PROP_SEARCH_OVERLAP:{ + src->search_overlap = g_value_get_int (value); + break; + } + case PROP_CACHE_SIZE:{ + src->cache_size = g_value_get_int (value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (src); +} + +static void +gst_cd_paranoia_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstCdParanoiaSrc *src = GST_CD_PARANOIA_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case PROP_READ_SPEED: + g_value_set_int (value, src->read_speed); + break; + case PROP_PARANOIA_MODE: + g_value_set_flags (value, src->paranoia_mode); + break; + case PROP_GENERIC_DEVICE: + g_value_set_string (value, src->generic_device); + break; + case PROP_SEARCH_OVERLAP: + g_value_set_int (value, src->search_overlap); + break; + case PROP_CACHE_SIZE: + g_value_set_int (value, src->cache_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (src); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_cd_paranoia_src_debug, "cdparanoiasrc", 0, + "CD Paranoia Source"); + + if (!gst_element_register (plugin, "cdparanoiasrc", GST_RANK_SECONDARY, + GST_TYPE_CD_PARANOIA_SRC)) + return FALSE; + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + + return TRUE; +} + + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "cdparanoia", + "Read audio from CD in paranoid mode", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.h b/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.h new file mode 100644 index 0000000..6cec23c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/cdparanoia/gstcdparanoiasrc.h @@ -0,0 +1,100 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_CD_PARANOIA_SRC_H__ +#define __GST_CD_PARANOIA_SRC_H__ + +#include "gst/cdda/gstcddabasesrc.h" + +G_BEGIN_DECLS + +#define size16 gint16 +#define size32 gint32 + +#ifdef CDPARANOIA_HEADERS_IN_DIR + #include + #include +#else + #include + #include +#endif + +#define GST_TYPE_CD_PARANOIA_SRC (gst_cd_paranoia_src_get_type()) +#define GST_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrc)) +#define GST_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_PARANOIA_SRC,GstCdParanoiaSrcClass)) +#define GST_IS_CD_PARANOIA_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_PARANOIA_SRC)) +#define GST_IS_CD_PARANOIA_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_PARANOIA_SRC)) +#define GST_CD_PARANOIA_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdParanoiaSrcClass)) + +typedef struct _GstCdParanoiaSrc GstCdParanoiaSrc; +typedef struct _GstCdParanoiaSrcClass GstCdParanoiaSrcClass; + +/** + * GstCdParanoiaSrc: + * + * The cdparanoia object structure. + */ +struct _GstCdParanoiaSrc { + GstCddaBaseSrc cddabasesrc; + + /*< private >*/ + cdrom_drive *d; + cdrom_paranoia *p; + + gint next_sector; /* -1 or next sector we expect to + * read, so we know when to do a seek */ + + gint paranoia_mode; + gint read_speed; + gint search_overlap; + gint cache_size; + + gchar *generic_device; +}; + +struct _GstCdParanoiaSrcClass { + GstCddaBaseSrcClass parent_class; + + /* signal callbacks */ + /** + * GstCdParanoiaSrcClass::transport-error: + * @src: the GstCddaBaseSrc source element object + * @sector: the sector at which the error happened + * + * This signal is emitted when a sector could not be read + * because of a transport error. + */ + void (*transport_error) (GstCdParanoiaSrc * src, gint sector); + /** + * GstCdParanoiaSrcClass::uncorrected-error: + * @src: the GstCddaBaseSrc source element object + * @sector: the sector at which the error happened + * + * This signal is emitted when a sector could not be read + * because of a transport error. + */ + void (*uncorrected_error) (GstCdParanoiaSrc * src, gint sector); +}; + +GType gst_cd_paranoia_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_CD_PARANOIA_SRC_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/gio/Makefile.am b/gst-plugins-base-subtitles0.10/ext/gio/Makefile.am new file mode 100644 index 0000000..f4b1611 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/Makefile.am @@ -0,0 +1,29 @@ +# plugindir is set in configure + +plugin_LTLIBRARIES = libgstgio.la + +# sources used to compile this plug-in +libgstgio_la_SOURCES = \ + gstgio.c \ + gstgiobasesink.c \ + gstgiobasesrc.c \ + gstgiosink.c \ + gstgiosrc.c \ + gstgiostreamsink.c \ + gstgiostreamsrc.c + +libgstgio_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GIO_CFLAGS) +libgstgio_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GIO_LIBS) +libgstgio_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) $(GIO_LDFLAGS) +libgstgio_la_LIBTOOLFLAGS = --tag=disable-static + +# headers we need but don't want installed +noinst_HEADERS = \ + gstgio.h \ + gstgiobasesink.h \ + gstgiobasesrc.h \ + gstgiosink.h \ + gstgiosrc.h \ + gstgiostreamsink.h \ + gstgiostreamsrc.h + diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgio.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgio.c new file mode 100644 index 0000000..3bf9c69 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgio.c @@ -0,0 +1,259 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstgio.h" +#include "gstgiosink.h" +#include "gstgiosrc.h" +#include "gstgiostreamsink.h" +#include "gstgiostreamsrc.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_gio_debug); +#define GST_CAT_DEFAULT gst_gio_debug + +/* @func_name: Name of the GIO function, for debugging messages. + * @err: Error location. *err may be NULL, but err must be non-NULL. + * @ret: Flow return location. May be NULL. Is set to either #GST_FLOW_ERROR + * or #GST_FLOW_WRONG_STATE. + * + * Returns: TRUE to indicate a handled error. Error at given location err will + * be freed and *err will be set to NULL. A FALSE return indicates an unhandled + * error: The err location is unchanged and guaranteed to be != NULL. ret, if + * given, is set to GST_FLOW_ERROR. + */ +gboolean +gst_gio_error (gpointer element, const gchar * func_name, GError ** err, + GstFlowReturn * ret) +{ + gboolean handled = TRUE; + + if (ret) + *ret = GST_FLOW_ERROR; + + if (GST_GIO_ERROR_MATCHES (*err, CANCELLED)) { + GST_DEBUG_OBJECT (element, "blocking I/O call cancelled (%s)", func_name); + if (ret) + *ret = GST_FLOW_WRONG_STATE; + } else if (*err != NULL) { + handled = FALSE; + } else { + GST_ELEMENT_ERROR (element, LIBRARY, FAILED, (NULL), + ("%s call failed without error set", func_name)); + } + + if (handled) + g_clear_error (err); + + return handled; +} + +GstFlowReturn +gst_gio_seek (gpointer element, GSeekable * stream, guint64 offset, + GCancellable * cancel) +{ + gboolean success; + GstFlowReturn ret; + GError *err = NULL; + + GST_LOG_OBJECT (element, "seeking to offset %" G_GINT64_FORMAT, offset); + + success = g_seekable_seek (stream, offset, G_SEEK_SET, cancel, &err); + + if (success) + ret = GST_FLOW_OK; + else if (!gst_gio_error (element, "g_seekable_seek", &err, &ret)) { + GST_ELEMENT_ERROR (element, RESOURCE, SEEK, (NULL), + ("Could not seek: %s", err->message)); + g_clear_error (&err); + } + + return ret; +} + +static gpointer +_internal_get_supported_protocols (gpointer data) +{ + const gchar *const *schemes; + gchar **our_schemes; + guint num; + gint i, j; + + schemes = g_vfs_get_supported_uri_schemes (g_vfs_get_default ()); + num = g_strv_length ((gchar **) schemes); + + if (num == 0) { + GST_WARNING ("No GIO supported URI schemes found"); + return NULL; + } + + our_schemes = g_new0 (gchar *, num + 1); + + /* - Filter http/https as we can't support the icy stuff with GIO. + * Use souphttpsrc if you need that. + * - Filter cdda as it doesn't support musicbrainz stuff and everything + * else one expects from a cdda source. Use cdparanoiasrc or cdiosrc + * for cdda. + */ + for (i = 0, j = 0; i < num; i++) { + if (strcmp (schemes[i], "http") == 0 || strcmp (schemes[i], "https") == 0 + || strcmp (schemes[i], "cdda") == 0) + continue; + + our_schemes[j] = g_strdup (schemes[i]); + j++; + } + + return our_schemes; +} + +static gchar ** +gst_gio_get_supported_protocols (void) +{ + static GOnce once = G_ONCE_INIT; + + g_once (&once, _internal_get_supported_protocols, NULL); + return (gchar **) once.retval; +} + +static GstURIType +gst_gio_uri_handler_get_type_sink (void) +{ + return GST_URI_SINK; +} + +static GstURIType +gst_gio_uri_handler_get_type_src (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_gio_uri_handler_get_protocols (void) +{ + static gchar **protocols = NULL; + + if (!protocols) + protocols = gst_gio_get_supported_protocols (); + + return protocols; +} + +static const gchar * +gst_gio_uri_handler_get_uri (GstURIHandler * handler) +{ + GstElement *element = GST_ELEMENT (handler); + const gchar *uri; + + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + + g_object_get (G_OBJECT (element), "location", &uri, NULL); + + return uri; +} + +static gboolean +gst_gio_uri_handler_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstElement *element = GST_ELEMENT (handler); + + g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE); + + if (GST_STATE (element) == GST_STATE_PLAYING || + GST_STATE (element) == GST_STATE_PAUSED) + return FALSE; + + g_object_set (G_OBJECT (element), "location", uri, NULL); + + return TRUE; +} + +static void +gst_gio_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + gboolean sink = GPOINTER_TO_INT (iface_data); /* See in do_init below. */ + + if (sink) + iface->get_type = gst_gio_uri_handler_get_type_sink; + else + iface->get_type = gst_gio_uri_handler_get_type_src; + iface->get_protocols = gst_gio_uri_handler_get_protocols; + iface->get_uri = gst_gio_uri_handler_get_uri; + iface->set_uri = gst_gio_uri_handler_set_uri; +} + +void +gst_gio_uri_handler_do_init (GType type) +{ + GInterfaceInfo uri_handler_info = { + gst_gio_uri_handler_init, + NULL, + NULL + }; + + /* Store information for uri_handler_init to use for distinguishing the + * element types. This lets us use a single interface implementation for both + * classes. */ + uri_handler_info.interface_data = GINT_TO_POINTER (g_type_is_a (type, + GST_TYPE_BASE_SINK)); + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_handler_info); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret = TRUE; + + GST_DEBUG_CATEGORY_INIT (gst_gio_debug, "gio", 0, "GIO elements"); + + gst_plugin_add_dependency_simple (plugin, NULL, GIO_MODULE_DIR, NULL, + GST_PLUGIN_DEPENDENCY_FLAG_NONE); + gst_plugin_add_dependency_simple (plugin, "LD_LIBRARY_PATH", GIO_LIBDIR, + "gvfsd", GST_PLUGIN_DEPENDENCY_FLAG_NONE); + + /* FIXME: Rank is MARGINAL for now, should be at least SECONDARY+1 in the future + * to replace gnomevfssink/src. For testing purposes PRIMARY+1 one makes sense + * so it gets autoplugged and preferred over filesrc/sink. */ + + ret &= gst_element_register (plugin, "giosink", GST_RANK_SECONDARY, + GST_TYPE_GIO_SINK); + + ret &= gst_element_register (plugin, "giosrc", GST_RANK_SECONDARY, + GST_TYPE_GIO_SRC); + + ret &= gst_element_register (plugin, "giostreamsink", GST_RANK_NONE, + GST_TYPE_GIO_STREAM_SINK); + + ret &= gst_element_register (plugin, "giostreamsrc", GST_RANK_NONE, + GST_TYPE_GIO_STREAM_SRC); + + return ret; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "gio", + "GIO elements", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgio.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgio.h new file mode 100644 index 0000000..01183e1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgio.h @@ -0,0 +1,42 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_H__ +#define __GST_GIO_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_GIO_ERROR_MATCHES(err, code) g_error_matches (err, G_IO_ERROR, G_IO_ERROR_##code) + +#define GST_GIO_STREAM_IS_SEEKABLE(stream) (G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream))) + +gboolean gst_gio_error (gpointer element, const gchar *func_name, + GError **err, GstFlowReturn *ret); +GstFlowReturn gst_gio_seek (gpointer element, GSeekable *stream, guint64 offset, + GCancellable *cancel); +void gst_gio_uri_handler_do_init (GType type); + +G_END_DECLS + +#endif /* __GST_GIO_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.c new file mode 100644 index 0000000..40a64eb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.c @@ -0,0 +1,347 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include "gstgiobasesink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gio_base_sink_debug); +#define GST_CAT_DEFAULT gst_gio_base_sink_debug + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_BOILERPLATE (GstGioBaseSink, gst_gio_base_sink, GstBaseSink, + GST_TYPE_BASE_SINK); + +static void gst_gio_base_sink_finalize (GObject * object); +static gboolean gst_gio_base_sink_start (GstBaseSink * base_sink); +static gboolean gst_gio_base_sink_stop (GstBaseSink * base_sink); +static gboolean gst_gio_base_sink_unlock (GstBaseSink * base_sink); +static gboolean gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink); +static gboolean gst_gio_base_sink_event (GstBaseSink * base_sink, + GstEvent * event); +static GstFlowReturn gst_gio_base_sink_render (GstBaseSink * base_sink, + GstBuffer * buffer); +static gboolean gst_gio_base_sink_query (GstPad * pad, GstQuery * query); + +static void +gst_gio_base_sink_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_base_sink_debug, "gio_base_sink", 0, + "GIO base sink"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +static void +gst_gio_base_sink_class_init (GstGioBaseSinkClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseSinkClass *gstbasesink_class = (GstBaseSinkClass *) klass; + + gobject_class->finalize = gst_gio_base_sink_finalize; + + gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_sink_start); + gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_sink_stop); + gstbasesink_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock); + gstbasesink_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_gio_base_sink_unlock_stop); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_gio_base_sink_event); + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_gio_base_sink_render); +} + +static void +gst_gio_base_sink_init (GstGioBaseSink * sink, GstGioBaseSinkClass * gclass) +{ + gst_pad_set_query_function (GST_BASE_SINK_PAD (sink), + GST_DEBUG_FUNCPTR (gst_gio_base_sink_query)); + + gst_base_sink_set_sync (GST_BASE_SINK (sink), FALSE); + + sink->cancel = g_cancellable_new (); +} + +static void +gst_gio_base_sink_finalize (GObject * object) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (object); + + if (sink->cancel) { + g_object_unref (sink->cancel); + sink->cancel = NULL; + } + + if (sink->stream) { + g_object_unref (sink->stream); + sink->stream = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static gboolean +gst_gio_base_sink_start (GstBaseSink * base_sink) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + GstGioBaseSinkClass *gbsink_class = GST_GIO_BASE_SINK_GET_CLASS (sink); + + sink->position = 0; + + /* FIXME: This will likely block */ + sink->stream = gbsink_class->get_stream (sink); + if (G_UNLIKELY (!G_IS_OUTPUT_STREAM (sink->stream))) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("No output stream provided by subclass")); + return FALSE; + } else if (G_UNLIKELY (g_output_stream_is_closed (sink->stream))) { + GST_ELEMENT_ERROR (sink, LIBRARY, FAILED, (NULL), + ("Output stream is already closed")); + return FALSE; + } + + GST_DEBUG_OBJECT (sink, "started sink"); + + return TRUE; +} + +static gboolean +gst_gio_base_sink_stop (GstBaseSink * base_sink) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + GstGioBaseSinkClass *klass = GST_GIO_BASE_SINK_GET_CLASS (sink); + gboolean success; + GError *err = NULL; + + if (klass->close_on_stop && G_IS_OUTPUT_STREAM (sink->stream)) { + GST_DEBUG_OBJECT (sink, "closing stream"); + + /* FIXME: can block but unfortunately we can't use async operations + * here because they require a running main loop */ + success = g_output_stream_close (sink->stream, sink->cancel, &err); + + if (!success && !gst_gio_error (sink, "g_output_stream_close", &err, NULL)) { + GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL), + ("gio_output_stream_close failed: %s", err->message)); + g_clear_error (&err); + } else if (!success) { + GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL), + ("g_output_stream_close failed")); + } else { + GST_DEBUG_OBJECT (sink, "g_outut_stream_close succeeded"); + } + + g_object_unref (sink->stream); + sink->stream = NULL; + } else { + success = g_output_stream_flush (sink->stream, sink->cancel, &err); + + if (!success && !gst_gio_error (sink, "g_output_stream_flush", &err, NULL)) { + GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL), + ("gio_output_stream_flush failed: %s", err->message)); + g_clear_error (&err); + } else if (!success) { + GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL), + ("g_output_stream_flush failed")); + } else { + GST_DEBUG_OBJECT (sink, "g_outut_stream_flush succeeded"); + } + + g_object_unref (sink->stream); + sink->stream = NULL; + } + + return TRUE; +} + +static gboolean +gst_gio_base_sink_unlock (GstBaseSink * base_sink) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + + GST_LOG_OBJECT (sink, "triggering cancellation"); + + g_cancellable_cancel (sink->cancel); + + return TRUE; +} + +static gboolean +gst_gio_base_sink_unlock_stop (GstBaseSink * base_sink) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + + GST_LOG_OBJECT (sink, "resetting cancellable"); + + g_cancellable_reset (sink->cancel); + + return TRUE; +} + +static gboolean +gst_gio_base_sink_event (GstBaseSink * base_sink, GstEvent * event) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + GstFlowReturn ret = GST_FLOW_OK; + + if (sink->stream == NULL) + return TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + if (G_IS_OUTPUT_STREAM (sink->stream)) { + GstFormat format; + gint64 offset; + + gst_event_parse_new_segment (event, NULL, NULL, &format, &offset, NULL, + NULL); + + if (format != GST_FORMAT_BYTES) { + GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format", + gst_format_get_name (format)); + break; + } + + if (GST_GIO_STREAM_IS_SEEKABLE (sink->stream)) { + ret = gst_gio_seek (sink, G_SEEKABLE (sink->stream), offset, + sink->cancel); + if (ret == GST_FLOW_OK) + sink->position = offset; + } else { + ret = GST_FLOW_NOT_SUPPORTED; + } + } + break; + + case GST_EVENT_EOS: + case GST_EVENT_FLUSH_START: + if (G_IS_OUTPUT_STREAM (sink->stream)) { + gboolean success; + GError *err = NULL; + + success = g_output_stream_flush (sink->stream, sink->cancel, &err); + + if (!success && !gst_gio_error (sink, "g_output_stream_flush", &err, + &ret)) { + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), + ("flush failed: %s", err->message)); + g_clear_error (&err); + } + } + break; + + default: + break; + } + + return (ret == GST_FLOW_OK); +} + +static GstFlowReturn +gst_gio_base_sink_render (GstBaseSink * base_sink, GstBuffer * buffer) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (base_sink); + gssize written; + gboolean success; + GError *err = NULL; + + g_return_val_if_fail (G_IS_OUTPUT_STREAM (sink->stream), GST_FLOW_ERROR); + + GST_LOG_OBJECT (sink, "writing %u bytes to offset %" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (buffer), sink->position); + + written = g_output_stream_write (sink->stream, + GST_BUFFER_DATA (buffer), GST_BUFFER_SIZE (buffer), sink->cancel, &err); + + success = (written >= 0); + + if (G_UNLIKELY (success && written < GST_BUFFER_SIZE (buffer))) { + /* FIXME: Can this happen? Should we handle it gracefully? gnomevfssink + * doesn't... */ + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), + ("Could not write to stream: (short write, only %" + G_GSSIZE_FORMAT " bytes of %d bytes written)", + written, GST_BUFFER_SIZE (buffer))); + return GST_FLOW_ERROR; + } + + if (success) { + sink->position += written; + return GST_FLOW_OK; + + } else { + GstFlowReturn ret; + + if (!gst_gio_error (sink, "g_output_stream_write", &err, &ret)) { + if (GST_GIO_ERROR_MATCHES (err, NO_SPACE)) { + GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL), + ("Could not write to stream: %s", err->message)); + } else { + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, (NULL), + ("Could not write to stream: %s", err->message)); + } + g_clear_error (&err); + } + + return ret; + } +} + +static gboolean +gst_gio_base_sink_query (GstPad * pad, GstQuery * query) +{ + GstGioBaseSink *sink = GST_GIO_BASE_SINK (GST_PAD_PARENT (pad)); + GstFormat format; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + gst_query_parse_position (query, &format, NULL); + switch (format) { + case GST_FORMAT_BYTES: + case GST_FORMAT_DEFAULT: + gst_query_set_position (query, GST_FORMAT_BYTES, sink->position); + return TRUE; + default: + return FALSE; + } + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + return TRUE; + case GST_QUERY_URI: + if (GST_IS_URI_HANDLER (sink)) { + const gchar *uri; + + uri = gst_uri_handler_get_uri (GST_URI_HANDLER (sink)); + gst_query_set_uri (query, uri); + return TRUE; + } + return FALSE; + default: + return gst_pad_query_default (pad, query); + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.h new file mode 100644 index 0000000..7f13a85 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesink.h @@ -0,0 +1,71 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_BASE_SINK_H__ +#define __GST_GIO_BASE_SINK_H__ + +#include "gstgio.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_BASE_SINK \ + (gst_gio_base_sink_get_type()) +#define GST_GIO_BASE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SINK,GstGioBaseSink)) +#define GST_GIO_BASE_SINK_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GIO_BASE_SINK, GstGioBaseSinkClass)) +#define GST_GIO_BASE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SINK,GstGioBaseSinkClass)) +#define GST_IS_GIO_BASE_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SINK)) +#define GST_IS_GIO_BASE_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SINK)) + +typedef struct _GstGioBaseSink GstGioBaseSink; +typedef struct _GstGioBaseSinkClass GstGioBaseSinkClass; + +struct _GstGioBaseSink +{ + GstBaseSink sink; + + /* < protected > */ + GCancellable *cancel; + guint64 position; + + /* < private > */ + GOutputStream *stream; +}; + +struct _GstGioBaseSinkClass +{ + GstBaseSinkClass parent_class; + + GOutputStream * (*get_stream) (GstGioBaseSink *bsink); + gboolean close_on_stop; +}; + +GType gst_gio_base_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_BASE_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.c new file mode 100644 index 0000000..133e12c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.c @@ -0,0 +1,447 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include "gstgiobasesrc.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_gio_base_src_debug); +#define GST_CAT_DEFAULT gst_gio_base_src_debug + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_BOILERPLATE (GstGioBaseSrc, gst_gio_base_src, GstBaseSrc, + GST_TYPE_BASE_SRC); + +static void gst_gio_base_src_finalize (GObject * object); + +static gboolean gst_gio_base_src_start (GstBaseSrc * base_src); +static gboolean gst_gio_base_src_stop (GstBaseSrc * base_src); +static gboolean gst_gio_base_src_get_size (GstBaseSrc * base_src, + guint64 * size); +static gboolean gst_gio_base_src_is_seekable (GstBaseSrc * base_src); +static gboolean gst_gio_base_src_unlock (GstBaseSrc * base_src); +static gboolean gst_gio_base_src_unlock_stop (GstBaseSrc * base_src); +static gboolean gst_gio_base_src_check_get_range (GstBaseSrc * base_src); +static GstFlowReturn gst_gio_base_src_create (GstBaseSrc * base_src, + guint64 offset, guint size, GstBuffer ** buf); +static gboolean gst_gio_base_src_query (GstBaseSrc * base_src, + GstQuery * query); + +static void +gst_gio_base_src_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_base_src_debug, "gio_base_src", 0, + "GIO base source"); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); +} + +static void +gst_gio_base_src_class_init (GstGioBaseSrcClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; + + gobject_class->finalize = gst_gio_base_src_finalize; + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gio_base_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gio_base_src_stop); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gio_base_src_get_size); + gstbasesrc_class->is_seekable = + GST_DEBUG_FUNCPTR (gst_gio_base_src_is_seekable); + gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock); + gstbasesrc_class->unlock_stop = + GST_DEBUG_FUNCPTR (gst_gio_base_src_unlock_stop); + gstbasesrc_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_gio_base_src_check_get_range); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gio_base_src_create); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_gio_base_src_query); +} + +static void +gst_gio_base_src_init (GstGioBaseSrc * src, GstGioBaseSrcClass * gclass) +{ + src->cancel = g_cancellable_new (); +} + +static void +gst_gio_base_src_finalize (GObject * object) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (object); + + if (src->cancel) { + g_object_unref (src->cancel); + src->cancel = NULL; + } + + if (src->stream) { + g_object_unref (src->stream); + src->stream = NULL; + } + + if (src->cache) { + gst_buffer_unref (src->cache); + src->cache = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static gboolean +gst_gio_base_src_start (GstBaseSrc * base_src) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + GstGioBaseSrcClass *gbsrc_class = GST_GIO_BASE_SRC_GET_CLASS (src); + + src->position = 0; + + /* FIXME: This will likely block */ + src->stream = gbsrc_class->get_stream (src); + if (G_UNLIKELY (!G_IS_INPUT_STREAM (src->stream))) { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("No input stream provided by subclass")); + return FALSE; + } else if (G_UNLIKELY (g_input_stream_is_closed (src->stream))) { + GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL), + ("Input stream is already closed")); + return FALSE; + } + + if (G_IS_SEEKABLE (src->stream)) + src->position = g_seekable_tell (G_SEEKABLE (src->stream)); + + GST_DEBUG_OBJECT (src, "started source"); + + return TRUE; +} + +static gboolean +gst_gio_base_src_stop (GstBaseSrc * base_src) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + GstGioBaseSrcClass *klass = GST_GIO_BASE_SRC_GET_CLASS (src); + gboolean success; + GError *err = NULL; + + if (klass->close_on_stop && G_IS_INPUT_STREAM (src->stream)) { + GST_DEBUG_OBJECT (src, "closing stream"); + + /* FIXME: can block but unfortunately we can't use async operations + * here because they require a running main loop */ + success = g_input_stream_close (src->stream, src->cancel, &err); + + if (!success && !gst_gio_error (src, "g_input_stream_close", &err, NULL)) { + GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL), + ("g_input_stream_close failed: %s", err->message)); + g_clear_error (&err); + } else if (!success) { + GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL), + ("g_input_stream_close failed")); + } else { + GST_DEBUG_OBJECT (src, "g_input_stream_close succeeded"); + } + + g_object_unref (src->stream); + src->stream = NULL; + } else { + g_object_unref (src->stream); + src->stream = NULL; + } + + return TRUE; +} + +static gboolean +gst_gio_base_src_get_size (GstBaseSrc * base_src, guint64 * size) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + + if (G_IS_FILE_INPUT_STREAM (src->stream)) { + GFileInfo *info; + GError *err = NULL; + + info = g_file_input_stream_query_info (G_FILE_INPUT_STREAM (src->stream), + G_FILE_ATTRIBUTE_STANDARD_SIZE, src->cancel, &err); + + if (info != NULL) { + *size = g_file_info_get_size (info); + g_object_unref (info); + GST_DEBUG_OBJECT (src, "found size: %" G_GUINT64_FORMAT, *size); + return TRUE; + } + + if (!gst_gio_error (src, "g_file_input_stream_query_info", &err, NULL)) { + + if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED)) + GST_DEBUG_OBJECT (src, "size information not available"); + else + GST_WARNING_OBJECT (src, "size information retrieval failed: %s", + err->message); + + g_clear_error (&err); + } + } + + if (GST_GIO_STREAM_IS_SEEKABLE (src->stream)) { + goffset old; + goffset stream_size; + gboolean ret; + GSeekable *seekable = G_SEEKABLE (src->stream); + GError *err = NULL; + + old = g_seekable_tell (seekable); + + ret = g_seekable_seek (seekable, 0, G_SEEK_END, src->cancel, &err); + if (!ret) { + if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) { + if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED)) + GST_DEBUG_OBJECT (src, + "Seeking to the end of stream is not supported"); + else + GST_WARNING_OBJECT (src, "Seeking to end of stream failed: %s", + err->message); + g_clear_error (&err); + } else { + GST_WARNING_OBJECT (src, "Seeking to end of stream failed"); + } + return FALSE; + } + + stream_size = g_seekable_tell (seekable); + + ret = g_seekable_seek (seekable, old, G_SEEK_SET, src->cancel, &err); + if (!ret) { + if (!gst_gio_error (src, "g_seekable_seek", &err, NULL)) { + if (GST_GIO_ERROR_MATCHES (err, NOT_SUPPORTED)) + GST_ERROR_OBJECT (src, "Seeking to the old position not supported"); + else + GST_ERROR_OBJECT (src, "Seeking to the old position failed: %s", + err->message); + g_clear_error (&err); + } else { + GST_ERROR_OBJECT (src, "Seeking to the old position faile"); + } + return FALSE; + } + + if (stream_size >= 0) { + *size = stream_size; + return TRUE; + } + } + + return FALSE; +} + +static gboolean +gst_gio_base_src_is_seekable (GstBaseSrc * base_src) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + gboolean seekable; + + seekable = GST_GIO_STREAM_IS_SEEKABLE (src->stream); + + GST_DEBUG_OBJECT (src, "can seek: %d", seekable); + + return seekable; +} + +static gboolean +gst_gio_base_src_unlock (GstBaseSrc * base_src) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + + GST_LOG_OBJECT (src, "triggering cancellation"); + + g_cancellable_cancel (src->cancel); + + return TRUE; +} + +static gboolean +gst_gio_base_src_unlock_stop (GstBaseSrc * base_src) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + + GST_LOG_OBJECT (src, "resetting cancellable"); + + g_cancellable_reset (src->cancel); + + return TRUE; +} + +static gboolean +gst_gio_base_src_check_get_range (GstBaseSrc * base_src) +{ + return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS, + check_get_range, (base_src), FALSE); +} + +static GstFlowReturn +gst_gio_base_src_create (GstBaseSrc * base_src, guint64 offset, guint size, + GstBuffer ** buf_return) +{ + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + + g_return_val_if_fail (G_IS_INPUT_STREAM (src->stream), GST_FLOW_ERROR); + + /* If we have the requested part in our cache take a subbuffer of that, + * otherwise fill the cache again with at least 4096 bytes from the + * requested offset and return a subbuffer of that. + * + * We need caching because every read/seek operation will need to go + * over DBus if our backend is GVfs and this is painfully slow. */ + if (src->cache && offset >= GST_BUFFER_OFFSET (src->cache) && + offset + size <= GST_BUFFER_OFFSET_END (src->cache)) { + GST_DEBUG_OBJECT (src, "Creating subbuffer from cached buffer: offset %" + G_GUINT64_FORMAT " length %u", offset, size); + + buf = gst_buffer_create_sub (src->cache, + offset - GST_BUFFER_OFFSET (src->cache), size); + + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + size; + GST_BUFFER_SIZE (buf) = size; + } else { + guint cachesize = MAX (4096, size); + gssize read, res; + gboolean success, eos; + GError *err = NULL; + + if (src->cache) { + gst_buffer_unref (src->cache); + src->cache = NULL; + } + + if (G_UNLIKELY (offset != src->position)) { + if (!GST_GIO_STREAM_IS_SEEKABLE (src->stream)) + return GST_FLOW_NOT_SUPPORTED; + + GST_DEBUG_OBJECT (src, "Seeking to position %" G_GUINT64_FORMAT, offset); + ret = gst_gio_seek (src, G_SEEKABLE (src->stream), offset, src->cancel); + + if (ret == GST_FLOW_OK) + src->position = offset; + else + return ret; + } + + src->cache = gst_buffer_try_new_and_alloc (cachesize); + if (G_UNLIKELY (src->cache == NULL)) { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", cachesize); + return GST_FLOW_ERROR; + } + + GST_LOG_OBJECT (src, "Reading %u bytes from offset %" G_GUINT64_FORMAT, + cachesize, offset); + + /* GIO sometimes gives less bytes than requested although + * it's not at the end of file. SMB for example only + * supports reads up to 64k. So we loop here until we get at + * at least the requested amount of bytes or a read returns + * nothing. */ + read = 0; + while (size - read > 0 && (res = + g_input_stream_read (G_INPUT_STREAM (src->stream), + GST_BUFFER_DATA (src->cache) + read, cachesize - read, + src->cancel, &err)) > 0) { + read += res; + } + + success = (read >= 0); + eos = (cachesize > 0 && read == 0); + + if (!success && !gst_gio_error (src, "g_input_stream_read", &err, &ret)) { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Could not read from stream: %s", err->message)); + g_clear_error (&err); + } + + if (success && !eos) { + src->position += read; + GST_BUFFER_SIZE (src->cache) = read; + + GST_BUFFER_OFFSET (src->cache) = offset; + GST_BUFFER_OFFSET_END (src->cache) = offset + read; + + GST_DEBUG_OBJECT (src, "Read successful"); + GST_DEBUG_OBJECT (src, "Creating subbuffer from new " + "cached buffer: offset %" G_GUINT64_FORMAT " length %u", offset, + size); + + buf = gst_buffer_create_sub (src->cache, 0, MIN (size, read)); + + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + MIN (size, read); + GST_BUFFER_SIZE (buf) = MIN (size, read); + } else { + GST_DEBUG_OBJECT (src, "Read not successful"); + gst_buffer_unref (src->cache); + src->cache = NULL; + buf = NULL; + } + + if (eos) + ret = GST_FLOW_UNEXPECTED; + } + + *buf_return = buf; + + return ret; +} + +static gboolean +gst_gio_base_src_query (GstBaseSrc * base_src, GstQuery * query) +{ + gboolean ret = FALSE; + GstGioBaseSrc *src = GST_GIO_BASE_SRC (base_src); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_URI: + if (GST_IS_URI_HANDLER (src)) { + const gchar *uri = gst_uri_handler_get_uri (GST_URI_HANDLER (src)); + gst_query_set_uri (query, uri); + ret = TRUE; + } + break; + default: + ret = FALSE; + break; + } + + if (!ret) + ret = GST_BASE_SRC_CLASS (parent_class)->query (base_src, query); + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.h new file mode 100644 index 0000000..7a14859 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiobasesrc.h @@ -0,0 +1,72 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_BASE_SRC_H__ +#define __GST_GIO_BASE_SRC_H__ + +#include "gstgio.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_BASE_SRC \ + (gst_gio_base_src_get_type()) +#define GST_GIO_BASE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrc)) +#define GST_GIO_BASE_SRC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_GIO_BASE_SRC, GstGioBaseSrcClass)) +#define GST_GIO_BASE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_BASE_SRC,GstGioBaseSrcClass)) +#define GST_IS_GIO_BASE_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_BASE_SRC)) +#define GST_IS_GIO_BASE_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_BASE_SRC)) + +typedef struct _GstGioBaseSrc GstGioBaseSrc; +typedef struct _GstGioBaseSrcClass GstGioBaseSrcClass; + +struct _GstGioBaseSrc +{ + GstBaseSrc src; + + /* < protected > */ + GCancellable *cancel; + guint64 position; + + /* < private > */ + GInputStream *stream; + GstBuffer *cache; +}; + +struct _GstGioBaseSrcClass +{ + GstBaseSrcClass parent_class; + + GInputStream * (*get_stream) (GstGioBaseSrc *bsrc); + gboolean close_on_stop; +}; + +GType gst_gio_base_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_BASE_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.c new file mode 100644 index 0000000..69e05e5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.c @@ -0,0 +1,319 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-giosink + * @see_also: #GstFileSink, #GstGnomeVFSSink, #GstGioSrc + * + * This plugin writes incoming data to a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GIO library or it's VFS backends. Common protocols are 'file', 'ftp', + * or 'smb'. + * + * If the URI or #GFile already exists giosink will post a message of + * type %GST_MESSAGE_ELEMENT with name "file-exists" on the bus. The message + * also contains the #GFile and the corresponding URI. + * Applications can use the "file-exists" message to notify the user about + * the problem and to set a different target location or to remove the + * existing file. Note that right after the "file-exists" message a normal + * error message is posted on the bus which should be ignored if "file-exists" + * is handled by the application, for example by calling + * gst_bus_set_flushing(bus, TRUE) after the "file-exists" message was + * received and gst_bus_set_flushing(bus, FALSE) after the problem is + * resolved. + * + * Similar to the "file-exist" message a "not-mounted" message is posted + * on the bus if the target location is not mounted yet and needs to be + * mounted. This message can be used by application to mount the location + * and retry after the location was mounted successfully. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=input.xyz ! giosink location=file:///home/joe/out.xyz + * ]| The above pipeline will simply copy a local file. Instead of giosink, + * we could just as well have used the filesink element here. + * |[ + * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! giosink location=smb://othercomputer/foo.flac + * ]| The above pipeline will re-encode an mp3 file into FLAC format and store + * it on a remote host using the Samba protocol. + * |[ + * gst-launch -v audiotestsrc num-buffers=100 ! vorbisenc ! oggmux ! giosink location=file:///home/foo/bar.ogg + * ]| The above pipeline will encode a 440Hz sine wave to Ogg Vorbis and stores + * it in the home directory of user foo. + * + */ + +/* FIXME: We would like to mount the enclosing volume of an URL + * if it isn't mounted yet but this is possible async-only. + * Unfortunately this requires a running main loop from the + * default context and we can't guarantuee this! + * + * We would also like to do authentication while mounting. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstgiosink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gio_sink_debug); +#define GST_CAT_DEFAULT gst_gio_sink_debug + +/* Filter signals and args */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_LOCATION, + PROP_FILE +}; + +GST_BOILERPLATE_FULL (GstGioSink, gst_gio_sink, GstGioBaseSink, + GST_TYPE_GIO_BASE_SINK, gst_gio_uri_handler_do_init); + +static void gst_gio_sink_finalize (GObject * object); +static void gst_gio_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gio_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GOutputStream *gst_gio_sink_get_stream (GstGioBaseSink * base_sink); + +static void +gst_gio_sink_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_sink_debug, "gio_sink", 0, "GIO sink"); + + gst_element_class_set_details_simple (element_class, "GIO sink", + "Sink/File", + "Write to any GIO-supported location", + "Ren\xc3\xa9 Stadler , " + "Sebastian Dröge "); +} + +static void +gst_gio_sink_class_init (GstGioSinkClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstGioBaseSinkClass *gstgiobasesink_class = (GstGioBaseSinkClass *) klass; + + gobject_class->finalize = gst_gio_sink_finalize; + gobject_class->set_property = gst_gio_sink_set_property; + gobject_class->get_property = gst_gio_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "Location", "URI location to write to", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstGioSink:file + * + * %GFile to write to. + * + * Since: 0.10.20 + **/ + g_object_class_install_property (gobject_class, PROP_FILE, + g_param_spec_object ("file", "File", "GFile to write to", + G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstgiobasesink_class->get_stream = + GST_DEBUG_FUNCPTR (gst_gio_sink_get_stream); + gstgiobasesink_class->close_on_stop = TRUE; +} + +static void +gst_gio_sink_init (GstGioSink * sink, GstGioSinkClass * gclass) +{ +} + +static void +gst_gio_sink_finalize (GObject * object) +{ + GstGioSink *sink = GST_GIO_SINK (object); + + if (sink->file) { + g_object_unref (sink->file); + sink->file = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_gio_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGioSink *sink = GST_GIO_SINK (object); + + switch (prop_id) { + case PROP_LOCATION:{ + const gchar *uri = NULL; + + if (GST_STATE (sink) == GST_STATE_PLAYING || + GST_STATE (sink) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new location or GFile not supported in PLAYING or PAUSED state"); + break; + } + + GST_OBJECT_LOCK (GST_OBJECT (sink)); + if (sink->file) + g_object_unref (sink->file); + + uri = g_value_get_string (value); + + if (uri) { + sink->file = g_file_new_for_uri (uri); + + if (!sink->file) { + GST_ERROR ("Could not create GFile for URI '%s'", uri); + } + } else { + sink->file = NULL; + } + GST_OBJECT_UNLOCK (GST_OBJECT (sink)); + break; + } + case PROP_FILE: + if (GST_STATE (sink) == GST_STATE_PLAYING || + GST_STATE (sink) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new location or GFile not supported in PLAYING or PAUSED state"); + break; + } + + GST_OBJECT_LOCK (GST_OBJECT (sink)); + if (sink->file) + g_object_unref (sink->file); + + sink->file = g_value_dup_object (value); + + GST_OBJECT_UNLOCK (GST_OBJECT (sink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gio_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGioSink *sink = GST_GIO_SINK (object); + + switch (prop_id) { + case PROP_LOCATION:{ + gchar *uri; + + GST_OBJECT_LOCK (GST_OBJECT (sink)); + if (sink->file) { + uri = g_file_get_uri (sink->file); + g_value_set_string (value, uri); + g_free (uri); + } else { + g_value_set_string (value, NULL); + } + GST_OBJECT_UNLOCK (GST_OBJECT (sink)); + break; + } + case PROP_FILE: + GST_OBJECT_LOCK (GST_OBJECT (sink)); + g_value_set_object (value, sink->file); + GST_OBJECT_UNLOCK (GST_OBJECT (sink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GOutputStream * +gst_gio_sink_get_stream (GstGioBaseSink * bsink) +{ + GstGioSink *sink = GST_GIO_SINK (bsink); + GOutputStream *stream; + GCancellable *cancel = GST_GIO_BASE_SINK (sink)->cancel; + GError *err = NULL; + gchar *uri; + + if (sink->file == NULL) { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("No location or GFile given")); + return NULL; + } + + uri = g_file_get_uri (sink->file); + if (!uri) + uri = g_strdup ("(null)"); + + stream = + G_OUTPUT_STREAM (g_file_create (sink->file, G_FILE_CREATE_NONE, cancel, + &err)); + + if (!stream) { + if (!gst_gio_error (sink, "g_file_create", &err, NULL)) { + /*if (GST_GIO_ERROR_MATCHES (err, EXISTS)) */ + /* FIXME: Retry with replace if overwrite == TRUE! */ + + if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) { + GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, (NULL), + ("Could not open location %s for writing: %s", uri, err->message)); + } else if (GST_GIO_ERROR_MATCHES (err, EXISTS)) { + gst_element_post_message (GST_ELEMENT_CAST (sink), + gst_message_new_element (GST_OBJECT_CAST (sink), + gst_structure_new ("file-exists", "file", G_TYPE_FILE, + sink->file, "uri", G_TYPE_STRING, uri, NULL))); + + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("Location %s already exists: %s", uri, err->message)); + } else if (GST_GIO_ERROR_MATCHES (err, NOT_MOUNTED)) { + gst_element_post_message (GST_ELEMENT_CAST (sink), + gst_message_new_element (GST_OBJECT_CAST (sink), + gst_structure_new ("not-mounted", "file", G_TYPE_FILE, + sink->file, "uri", G_TYPE_STRING, uri, NULL))); + + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("Location %s not mounted: %s", uri, err->message)); + } else { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("Could not open location %s for writing: %s", uri, err->message)); + } + + g_clear_error (&err); + } + g_free (uri); + return NULL; + } + + GST_DEBUG_OBJECT (sink, "opened location %s", uri); + + g_free (uri); + + return stream; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.h new file mode 100644 index 0000000..494d5db --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosink.h @@ -0,0 +1,68 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_SINK_H__ +#define __GST_GIO_SINK_H__ + +#include "gstgio.h" +#include "gstgiobasesink.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_SINK \ + (gst_gio_sink_get_type()) +#define GST_GIO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SINK,GstGioSink)) +#define GST_GIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SINK,GstGioSinkClass)) +#define GST_IS_GIO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SINK)) +#define GST_IS_GIO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SINK)) + +typedef struct _GstGioSink GstGioSink; +typedef struct _GstGioSinkClass GstGioSinkClass; + +/** + * GstGioSink: + * + * Opaque data structure. + */ +struct _GstGioSink +{ + GstGioBaseSink sink; + + /*< private >*/ + GFile *file; +}; + +struct _GstGioSinkClass +{ + GstGioBaseSinkClass parent_class; +}; + +GType gst_gio_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.c new file mode 100644 index 0000000..5fd810e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.c @@ -0,0 +1,339 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-giosrc + * @see_also: #GstFileSrc, #GstGnomeVFSSrc, #GstGioSink + * + * This plugin reads data from a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GIO library or it's VFS backends. Common protocols are 'file', 'http', + * 'ftp', or 'smb'. + * + * If an URI or #GFile is not mounted giosrc will post a message of type + * %GST_MESSAGE_ELEMENT with name "not-mounted" on the bus. The message + * also contains the #GFile and the corresponding URI. + * Applications can use the "not-mounted" message to mount the #GFile + * by calling g_file_mount_enclosing_volume() and then restart the + * pipeline after the mounting has succeeded. Note that right after the + * "not-mounted" message a normal error message is posted on the bus which + * should be ignored if "not-mounted" is handled by the application, for + * example by calling gst_bus_set_flushing(bus, TRUE) after the "not-mounted" + * message was received and gst_bus_set_flushing(bus, FALSE) after the + * mounting was successful. + * + * + * Example launch lines + * |[ + * gst-launch -v giosrc location=file:///home/joe/foo.xyz ! fakesink + * ]| The above pipeline will simply read a local file and do nothing with the + * data read. Instead of giosrc, we could just as well have used the + * filesrc element here. + * |[ + * gst-launch -v giosrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz + * ]| The above pipeline will copy a file from a remote host to the local file + * system using the Samba protocol. + * |[ + * gst-launch -v giosrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink + * ]| The above pipeline will read and decode and play an mp3 file from a + * web server using the http protocol. + * + */ + +/* FIXME: We would like to mount the enclosing volume of an URL + * if it isn't mounted yet but this is possible async-only. + * Unfortunately this requires a running main loop from the + * default context and we can't guarantuee this! + * + * We would also like to do authentication while mounting. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstgiosrc.h" +#include + +GST_DEBUG_CATEGORY_STATIC (gst_gio_src_debug); +#define GST_CAT_DEFAULT gst_gio_src_debug + +enum +{ + PROP_0, + PROP_LOCATION, + PROP_FILE +}; + +GST_BOILERPLATE_FULL (GstGioSrc, gst_gio_src, GstGioBaseSrc, + GST_TYPE_GIO_BASE_SRC, gst_gio_uri_handler_do_init); + +static void gst_gio_src_finalize (GObject * object); + +static void gst_gio_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gio_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GInputStream *gst_gio_src_get_stream (GstGioBaseSrc * bsrc); + +static gboolean gst_gio_src_check_get_range (GstBaseSrc * base_src); + +static void +gst_gio_src_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_src_debug, "gio_src", 0, "GIO source"); + + gst_element_class_set_details_simple (element_class, "GIO source", + "Source/File", + "Read from any GIO-supported location", + "Ren\xc3\xa9 Stadler , " + "Sebastian Dröge "); +} + +static void +gst_gio_src_class_init (GstGioSrcClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseSrcClass *gstbasesrc_class = (GstBaseSrcClass *) klass; + GstGioBaseSrcClass *gstgiobasesrc_class = (GstGioBaseSrcClass *) klass; + + gobject_class->finalize = gst_gio_src_finalize; + gobject_class->set_property = gst_gio_src_set_property; + gobject_class->get_property = gst_gio_src_get_property; + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "Location", "URI location to read from", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstGioSrc:file + * + * %GFile to read from. + * + * Since: 0.10.20 + **/ + g_object_class_install_property (gobject_class, PROP_FILE, + g_param_spec_object ("file", "File", "GFile to read from", + G_TYPE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_gio_src_check_get_range); + + gstgiobasesrc_class->get_stream = GST_DEBUG_FUNCPTR (gst_gio_src_get_stream); + gstgiobasesrc_class->close_on_stop = TRUE; +} + +static void +gst_gio_src_init (GstGioSrc * src, GstGioSrcClass * gclass) +{ +} + +static void +gst_gio_src_finalize (GObject * object) +{ + GstGioSrc *src = GST_GIO_SRC (object); + + if (src->file) { + g_object_unref (src->file); + src->file = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_gio_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGioSrc *src = GST_GIO_SRC (object); + + switch (prop_id) { + case PROP_LOCATION:{ + const gchar *uri = NULL; + + if (GST_STATE (src) == GST_STATE_PLAYING || + GST_STATE (src) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new location or GFile not supported in PLAYING or PAUSED state"); + break; + } + + GST_OBJECT_LOCK (GST_OBJECT (src)); + if (src->file) + g_object_unref (src->file); + + uri = g_value_get_string (value); + + if (uri) { + src->file = g_file_new_for_uri (uri); + + if (!src->file) { + GST_ERROR ("Could not create GFile for URI '%s'", uri); + } + } else { + src->file = NULL; + } + GST_OBJECT_UNLOCK (GST_OBJECT (src)); + break; + } + case PROP_FILE: + if (GST_STATE (src) == GST_STATE_PLAYING || + GST_STATE (src) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new location or GFile not supported in PLAYING or PAUSED state"); + break; + } + + GST_OBJECT_LOCK (GST_OBJECT (src)); + if (src->file) + g_object_unref (src->file); + + src->file = g_value_dup_object (value); + + GST_OBJECT_UNLOCK (GST_OBJECT (src)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gio_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGioSrc *src = GST_GIO_SRC (object); + + switch (prop_id) { + case PROP_LOCATION:{ + gchar *uri; + + GST_OBJECT_LOCK (GST_OBJECT (src)); + if (src->file) { + uri = g_file_get_uri (src->file); + g_value_set_string (value, uri); + g_free (uri); + } else { + g_value_set_string (value, NULL); + } + GST_OBJECT_UNLOCK (GST_OBJECT (src)); + break; + } + case PROP_FILE: + GST_OBJECT_LOCK (GST_OBJECT (src)); + g_value_set_object (value, src->file); + GST_OBJECT_UNLOCK (GST_OBJECT (src)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_gio_src_check_get_range (GstBaseSrc * base_src) +{ + GstGioSrc *src = GST_GIO_SRC (base_src); + gchar *scheme; + + if (src->file == NULL) + goto done; + + scheme = g_file_get_uri_scheme (src->file); + if (scheme == NULL) + goto done; + + if (strcmp (scheme, "file") == 0) { + GST_LOG_OBJECT (src, "local URI, assuming random access is possible"); + g_free (scheme); + return TRUE; + } else if (strcmp (scheme, "http") == 0 || strcmp (scheme, "https") == 0) { + GST_LOG_OBJECT (src, "blacklisted protocol '%s', " + "no random access possible", scheme); + g_free (scheme); + return FALSE; + } + + g_free (scheme); + +done: + + GST_DEBUG_OBJECT (src, "undecided about random access, asking base class"); + + return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_SRC_CLASS, + check_get_range, (base_src), FALSE); +} + + +static GInputStream * +gst_gio_src_get_stream (GstGioBaseSrc * bsrc) +{ + GstGioSrc *src = GST_GIO_SRC (bsrc); + GError *err = NULL; + GInputStream *stream; + GCancellable *cancel = bsrc->cancel; + gchar *uri = NULL; + + if (src->file == NULL) { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("No location or GFile given")); + return NULL; + } + + uri = g_file_get_uri (src->file); + if (!uri) + uri = g_strdup ("(null)"); + + stream = G_INPUT_STREAM (g_file_read (src->file, cancel, &err)); + + if (stream == NULL && !gst_gio_error (src, "g_file_read", &err, NULL)) { + if (GST_GIO_ERROR_MATCHES (err, NOT_FOUND)) { + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), + ("Could not open location %s for reading: %s", uri, err->message)); + } else if (GST_GIO_ERROR_MATCHES (err, NOT_MOUNTED)) { + gst_element_post_message (GST_ELEMENT_CAST (src), + gst_message_new_element (GST_OBJECT_CAST (src), + gst_structure_new ("not-mounted", "file", G_TYPE_FILE, src->file, + "uri", G_TYPE_STRING, uri, NULL))); + + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Location %s not mounted: %s", uri, err->message)); + } else { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Could not open location %s for reading: %s", uri, err->message)); + } + + g_free (uri); + g_clear_error (&err); + return NULL; + } else if (stream == NULL) { + g_free (uri); + return NULL; + } + + GST_DEBUG_OBJECT (src, "opened location %s", uri); + g_free (uri); + + return stream; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.h new file mode 100644 index 0000000..080d3d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiosrc.h @@ -0,0 +1,68 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_SRC_H__ +#define __GST_GIO_SRC_H__ + +#include "gstgio.h" +#include "gstgiobasesrc.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_SRC \ + (gst_gio_src_get_type()) +#define GST_GIO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_SRC,GstGioSrc)) +#define GST_GIO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_SRC,GstGioSrcClass)) +#define GST_IS_GIO_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_SRC)) +#define GST_IS_GIO_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_SRC)) + +typedef struct _GstGioSrc GstGioSrc; +typedef struct _GstGioSrcClass GstGioSrcClass; + +/** + * GstGioSrc: + * + * Opaque data structure. + */ +struct _GstGioSrc +{ + GstGioBaseSrc src; + + /*< private >*/ + GFile *file; +}; + +struct _GstGioSrcClass +{ + GstGioBaseSrcClass parent_class; +}; + +GType gst_gio_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.c new file mode 100644 index 0000000..02dac71 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.c @@ -0,0 +1,198 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-giostreamsink + * + * This plugin writes incoming data to a custom GIO #GOutputStream. + * + * It can, for example, be used to write a stream to memory with a + * #GMemoryOuputStream or to write to a file with a #GFileOuputStream. + * + * + * Example code + * + * The following example writes the received data to a #GMemoryOutputStream. + * |[ + +#include <gst/gst.h> +#include <gio/gio.h> + +... + +GstElement *sink; +GMemoryOuputStream *stream; +// out_data will contain the received data +guint8 *out_data; + +... + +stream = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (NULL, 0, + (GReallocFunc) g_realloc, (GDestroyNotify) g_free)); +sink = gst_element_factory_make ("giostreamsink", "sink"); +g_object_set (G_OBJECT (sink), "stream", stream, NULL); + +... + +// after processing get the written data +out_data = g_memory_ouput_stream_get_data (G_MEMORY_OUTPUT_STREAM (stream)); + +... + + * ]| + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstgiostreamsink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_sink_debug); +#define GST_CAT_DEFAULT gst_gio_stream_sink_debug + +/* Filter signals and args */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_STREAM +}; + +GST_BOILERPLATE (GstGioStreamSink, gst_gio_stream_sink, GstGioBaseSink, + GST_TYPE_GIO_BASE_SINK); + +static void gst_gio_stream_sink_finalize (GObject * object); +static void gst_gio_stream_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gio_stream_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GOutputStream *gst_gio_stream_sink_get_stream (GstGioBaseSink * bsink); + +static void +gst_gio_stream_sink_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_stream_sink_debug, "gio_stream_sink", 0, + "GIO stream sink"); + + gst_element_class_set_details_simple (element_class, "GIO stream sink", + "Sink", + "Write to any GIO stream", + "Sebastian Dröge "); +} + +static void +gst_gio_stream_sink_class_init (GstGioStreamSinkClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstGioBaseSinkClass *ggbsink_class = (GstGioBaseSinkClass *) klass; + + gobject_class->finalize = gst_gio_stream_sink_finalize; + gobject_class->set_property = gst_gio_stream_sink_set_property; + gobject_class->get_property = gst_gio_stream_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_STREAM, + g_param_spec_object ("stream", "Stream", "Stream to write to", + G_TYPE_OUTPUT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + ggbsink_class->get_stream = + GST_DEBUG_FUNCPTR (gst_gio_stream_sink_get_stream); +} + +static void +gst_gio_stream_sink_init (GstGioStreamSink * sink, + GstGioStreamSinkClass * gclass) +{ +} + +static void +gst_gio_stream_sink_finalize (GObject * object) +{ + GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object); + + if (sink->stream) { + g_object_unref (sink->stream); + sink->stream = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_gio_stream_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object); + + switch (prop_id) { + case PROP_STREAM:{ + GObject *stream; + + if (GST_STATE (sink) == GST_STATE_PLAYING || + GST_STATE (sink) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new stream not supported in PLAYING or PAUSED state"); + break; + } + + stream = g_value_dup_object (value); + if (sink->stream) + g_object_unref (sink->stream); + sink->stream = G_OUTPUT_STREAM (stream); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gio_stream_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGioStreamSink *sink = GST_GIO_STREAM_SINK (object); + + switch (prop_id) { + case PROP_STREAM: + g_value_set_object (value, GST_GIO_BASE_SINK (sink)->stream); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GOutputStream * +gst_gio_stream_sink_get_stream (GstGioBaseSink * bsink) +{ + GstGioStreamSink *sink = GST_GIO_STREAM_SINK (bsink); + + return (sink->stream) ? g_object_ref (sink->stream) : NULL; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.h new file mode 100644 index 0000000..5e6206b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsink.h @@ -0,0 +1,68 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_STREAM_SINK_H__ +#define __GST_GIO_STREAM_SINK_H__ + +#include "gstgio.h" +#include "gstgiobasesink.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_STREAM_SINK \ + (gst_gio_stream_sink_get_type()) +#define GST_GIO_STREAM_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSink)) +#define GST_GIO_STREAM_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SINK,GstGioStreamSinkClass)) +#define GST_IS_GIO_STREAM_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SINK)) +#define GST_IS_GIO_STREAM_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SINK)) + +typedef struct _GstGioStreamSink GstGioStreamSink; +typedef struct _GstGioStreamSinkClass GstGioStreamSinkClass; + +/** + * GstGioStreamSink: + * + * Opaque data structure. + */ +struct _GstGioStreamSink +{ + GstGioBaseSink sink; + + /* < private > */ + GOutputStream *stream; +}; + +struct _GstGioStreamSinkClass +{ + GstGioBaseSinkClass parent_class; +}; + +GType gst_gio_stream_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_STREAM_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.c b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.c new file mode 100644 index 0000000..bd6c686 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.c @@ -0,0 +1,191 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-giostreamsrc + * + * This plugin reads data from a custom GIO #GInputStream. + * + * It can, for example, be used to read data from memory with a + * #GMemoryInputStream or to read from a file with a + * #GFileInputStream. + * + * + * Example code + * + * The following example reads data from a #GMemoryInputStream. + * |[ + +#include <gst/gst.h> +#include <gio/gio.h> + +... + +GstElement *src; +GMemoryInputStream *stream; +// in_data will contain the data to send +guint8 *in_data; +gint i; + +... +in_data = g_new (guint8, 512); +for (i = 0; i < 512; i++) + in_data[i] = i % 256; + +stream = G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (in_data, 512, + (GDestroyNotify) g_free)); +src = gst_element_factory_make ("giostreamsrc", "src"); +g_object_set (G_OBJECT (src), "stream", stream, NULL); + +... + + * ]| + * + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include "gstgiostreamsrc.h" + +GST_DEBUG_CATEGORY_STATIC (gst_gio_stream_src_debug); +#define GST_CAT_DEFAULT gst_gio_stream_src_debug + +enum +{ + PROP_0, + PROP_STREAM +}; + +GST_BOILERPLATE (GstGioStreamSrc, gst_gio_stream_src, GstGioBaseSrc, + GST_TYPE_GIO_BASE_SRC); + +static void gst_gio_stream_src_finalize (GObject * object); +static void gst_gio_stream_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gio_stream_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GInputStream *gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc); + +static void +gst_gio_stream_src_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + GST_DEBUG_CATEGORY_INIT (gst_gio_stream_src_debug, "gio_stream_src", 0, + "GIO source"); + + gst_element_class_set_details_simple (element_class, "GIO stream source", + "Source", + "Read from any GIO stream", + "Sebastian Dröge "); +} + +static void +gst_gio_stream_src_class_init (GstGioStreamSrcClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstGioBaseSrcClass *gstgiobasesrc_class = (GstGioBaseSrcClass *) klass; + + gobject_class->finalize = gst_gio_stream_src_finalize; + gobject_class->set_property = gst_gio_stream_src_set_property; + gobject_class->get_property = gst_gio_stream_src_get_property; + + g_object_class_install_property (gobject_class, PROP_STREAM, + g_param_spec_object ("stream", "Stream", "Stream to read from", + G_TYPE_INPUT_STREAM, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstgiobasesrc_class->get_stream = + GST_DEBUG_FUNCPTR (gst_gio_stream_src_get_stream); +} + +static void +gst_gio_stream_src_init (GstGioStreamSrc * src, GstGioStreamSrcClass * gclass) +{ +} + +static void +gst_gio_stream_src_finalize (GObject * object) +{ + GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object); + + if (src->stream) { + g_object_unref (src->stream); + src->stream = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_gio_stream_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object); + + switch (prop_id) { + case PROP_STREAM:{ + GObject *stream; + + if (GST_STATE (src) == GST_STATE_PLAYING || + GST_STATE (src) == GST_STATE_PAUSED) { + GST_WARNING + ("Setting a new stream not supported in PLAYING or PAUSED state"); + break; + } + + stream = g_value_dup_object (value); + if (src->stream) + g_object_unref (src->stream); + src->stream = G_INPUT_STREAM (stream); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gio_stream_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGioStreamSrc *src = GST_GIO_STREAM_SRC (object); + + switch (prop_id) { + case PROP_STREAM: + g_value_set_object (value, src->stream); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GInputStream * +gst_gio_stream_src_get_stream (GstGioBaseSrc * bsrc) +{ + GstGioStreamSrc *src = GST_GIO_STREAM_SRC (bsrc); + + return (src->stream) ? g_object_ref (src->stream) : NULL; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.h b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.h new file mode 100644 index 0000000..975a277 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gio/gstgiostreamsrc.h @@ -0,0 +1,68 @@ +/* GStreamer + * + * Copyright (C) 2007 Rene Stadler + * Copyright (C) 2007-2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GIO_STREAM_SRC_H__ +#define __GST_GIO_STREAM_SRC_H__ + +#include "gstgio.h" +#include "gstgiobasesrc.h" + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GIO_STREAM_SRC \ + (gst_gio_stream_src_get_type()) +#define GST_GIO_STREAM_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrc)) +#define GST_GIO_STREAM_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GIO_STREAM_SRC,GstGioStreamSrcClass)) +#define GST_IS_GIO_STREAM_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GIO_STREAM_SRC)) +#define GST_IS_GIO_STREAM_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GIO_STREAM_SRC)) + +typedef struct _GstGioStreamSrc GstGioStreamSrc; +typedef struct _GstGioStreamSrcClass GstGioStreamSrcClass; + +/** + * GstGioStreamSrc: + * + * Opaque data structure. + */ +struct _GstGioStreamSrc +{ + GstGioBaseSrc src; + + /* < private > */ + GInputStream *stream; +}; + +struct _GstGioStreamSrcClass +{ + GstGioBaseSrcClass parent_class; +}; + +GType gst_gio_stream_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_GIO_STREAM_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/Makefile.am b/gst-plugins-base-subtitles0.10/ext/gnomevfs/Makefile.am new file mode 100644 index 0000000..ed18d39 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/Makefile.am @@ -0,0 +1,21 @@ +plugin_LTLIBRARIES = libgstgnomevfs.la + +libgstgnomevfs_la_SOURCES = \ + gstgnomevfs.c \ + gstgnomevfssink.c \ + gstgnomevfssrc.c \ + gstgnomevfsuri.c + +libgstgnomevfs_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GNOME_VFS_CFLAGS) +libgstgnomevfs_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) $(GNOME_VFS_LIBS) +libgstgnomevfs_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstgnomevfs_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstgnomevfs.h \ + gstgnomevfssink.h \ + gstgnomevfssrc.h \ + gstgnomevfsuri.h diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.c b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.c new file mode 100644 index 0000000..c00254e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.c @@ -0,0 +1,143 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gnomevfs.c: register gnomevfs elements + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst/gst-i18n-plugin.h" + +#include "gstgnomevfs.h" +#include "gstgnomevfssrc.h" +#include "gstgnomevfssink.h" + +#include +#include + +#include + +gchar * +gst_gnome_vfs_location_to_uri_string (const gchar * location) +{ + gchar *newloc, *ret; + + if (location == NULL) + return NULL; + + /* already an URI string? */ + if (strstr (location, "://")) + return g_strdup (location); + + newloc = gnome_vfs_escape_path_string (location); + + if (newloc && *newloc == '/') { + ret = g_strdup_printf ("file://%s", newloc); + } else { + gchar *curdir; + + curdir = g_get_current_dir (); + ret = g_strdup_printf ("file://%s/%s", curdir, newloc); + g_free (curdir); + } + + g_free (newloc); + return ret; +} + +GType +gst_gnome_vfs_uri_get_type (void) +{ + static GType type; /* 0 */ + + if (type == 0) { + type = g_boxed_type_register_static ("GnomeVFSURI", + (GBoxedCopyFunc) gnome_vfs_uri_ref, + (GBoxedFreeFunc) gnome_vfs_uri_unref); + } + + return type; +} + +static gpointer +gst_gnome_vfs_handle_copy (gpointer handle) +{ + return handle; +} + +static void +gst_gnome_vfs_handle_free (gpointer handle) +{ + return; +} + +GType +gst_gnome_vfs_handle_get_type (void) +{ + static GType type; /* 0 */ + + if (type == 0) { + /* hackish, but makes it show up nicely in gst-inspect */ + type = g_boxed_type_register_static ("GnomeVFSHandle", + (GBoxedCopyFunc) gst_gnome_vfs_handle_copy, + (GBoxedFreeFunc) gst_gnome_vfs_handle_free); + } + + return type; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + /* gnome vfs engine init */ + if (!gnome_vfs_initialized ()) { + if (!gnome_vfs_init ()) { + GST_WARNING ("Failed to initialize GnomeVFS - not registering plugin!"); + return FALSE; + } + } + + gst_plugin_add_dependency_simple (plugin, NULL, GNOME_VFS_MODULES_DIR, NULL, + GST_PLUGIN_DEPENDENCY_FLAG_NONE); + + if (!gst_element_register (plugin, "gnomevfssrc", GST_RANK_MARGINAL, + gst_gnome_vfs_src_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "gnomevfssink", GST_RANK_MARGINAL, + gst_gnome_vfs_sink_get_type ())) + return FALSE; + +#ifdef ENABLE_NLS +/* FIXME: add category + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, LOCALEDIR); + */ + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "gnomevfs", + "elements to read from and write to Gnome-VFS uri's", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.h b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.h new file mode 100644 index 0000000..f2228be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfs.h @@ -0,0 +1,38 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_GNOME_VFS_H__ +#define __GST_GNOME_VFS_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GNOME_VFS_URI (gst_gnome_vfs_uri_get_type ()) +#define GST_TYPE_GNOME_VFS_HANDLE (gst_gnome_vfs_handle_get_type ()) + +GType gst_gnome_vfs_uri_get_type (void); +GType gst_gnome_vfs_handle_get_type (void); + +gchar * gst_gnome_vfs_location_to_uri_string (const gchar * location); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.c b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.c new file mode 100644 index 0000000..1a5f31f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.c @@ -0,0 +1,628 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2003 Colin Walters + * 2005 Tim-Philipp Müller + * + * gstgnomevfssink.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-gnomevfssink + * @see_also: #GstFileSink, #GstGnomeVFSSrc + * + * This plugin writes incoming data to a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GnomeVFS library. Common protocols are 'file', 'ftp', or 'smb'. + * + * Applications can connect to the #GstGnomeVFSSink::allow-overwrite signal to + * receive a callback when an existing file will be overwritten. The return + * value of the signal will determine if gnomevfssink will overwrite the + * resource or abort with an error. + * + * + * Example launch lines + * |[ + * gst-launch -v filesrc location=input.xyz ! gnomevfssink location=file:///home/joe/out.xyz + * ]| The above pipeline will simply copy a local file. Instead of gnomevfssink, + * we could just as well have used the filesink element here. + * |[ + * gst-launch -v filesrc location=foo.mp3 ! mad ! flacenc ! gnomevfssink location=smb://othercomputer/foo.flac + * ]| The above pipeline will re-encode an mp3 file into FLAC format and store + * it on a remote host using the Samba protocol. + * + * + * Last reviewed on 2006-02-28 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstgnomevfssink.h" + +#include "gst/gst-i18n-plugin.h" + +#include +#include +#include +#include + +enum +{ + SIGNAL_ERASE_ASK, + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_LOCATION, + ARG_URI, + ARG_HANDLE +}; + +static void gst_gnome_vfs_sink_finalize (GObject * obj); + +static void gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static void gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink); +static void gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink); +static gboolean gst_gnome_vfs_sink_start (GstBaseSink * basesink); +static gboolean gst_gnome_vfs_sink_stop (GstBaseSink * basesink); +static GstFlowReturn gst_gnome_vfs_sink_render (GstBaseSink * basesink, + GstBuffer * buffer); +static gboolean gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, + GstEvent * event); +static gboolean gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query); + +static guint gst_gnome_vfs_sink_signals[LAST_SIGNAL]; /* all 0 */ + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_gnome_vfs_sink_debug); +#define GST_CAT_DEFAULT gst_gnome_vfs_sink_debug + +static void +gst_gnome_vfs_sink_do_init (GType type) +{ + static const GInterfaceInfo urihandler_info = { + gst_gnome_vfs_sink_uri_handler_init, + NULL, + NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info); + + GST_DEBUG_CATEGORY_INIT (gst_gnome_vfs_sink_debug, "gnomevfssink", 0, + "Gnome VFS sink element"); +} + +GST_BOILERPLATE_FULL (GstGnomeVFSSink, gst_gnome_vfs_sink, GstBaseSink, + GST_TYPE_BASE_SINK, gst_gnome_vfs_sink_do_init); + +static void +gst_gnome_vfs_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (element_class, + "GnomeVFS Sink", "Sink/File", + "Write a stream to a GnomeVFS URI", "Bastien Nocera "); +} + +static gboolean +_gst_boolean_allow_overwrite_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gboolean allow_overwrite; + + allow_overwrite = g_value_get_boolean (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boolean (return_accu, allow_overwrite); + + /* stop emission if signal doesn't allow overwriting */ + return allow_overwrite; +} + +static void +gst_gnome_vfs_sink_class_init (GstGnomeVFSSinkClass * klass) +{ + GstBaseSinkClass *basesink_class; + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + basesink_class = (GstBaseSinkClass *) klass; + + gobject_class->set_property = gst_gnome_vfs_sink_set_property; + gobject_class->get_property = gst_gnome_vfs_sink_get_property; + gobject_class->finalize = gst_gnome_vfs_sink_finalize; + + g_object_class_install_property (gobject_class, ARG_LOCATION, + g_param_spec_string ("location", "File Location", + "Location of the file to write", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_URI, + g_param_spec_boxed ("uri", "GnomeVFSURI", "URI for GnomeVFS", + GST_TYPE_GNOME_VFS_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_HANDLE, + g_param_spec_boxed ("handle", "GnomeVFSHandle", "Handle for GnomeVFS", + GST_TYPE_GNOME_VFS_HANDLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstGnomeVFSSink::allow-overwrite + * @sink: the object which received the signal + * @uri: the URI to be overwritten + * + * This signal is fired when gnomevfssink is about to overwrite an + * existing resource. The application can connect to this signal and ask + * the user if the resource may be overwritten. + * + * Returns: A boolean indicating that the resource may be overwritten. + */ + gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK] = + g_signal_new ("allow-overwrite", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_CLEANUP, G_STRUCT_OFFSET (GstGnomeVFSSinkClass, erase_ask), + _gst_boolean_allow_overwrite_accumulator, NULL, + gst_marshal_BOOLEAN__POINTER, G_TYPE_BOOLEAN, 1, GST_TYPE_GNOME_VFS_URI); + + basesink_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_stop); + basesink_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_start); + basesink_class->event = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_handle_event); + basesink_class->render = GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_render); + basesink_class->get_times = NULL; +} + +static void +gst_gnome_vfs_sink_finalize (GObject * obj) +{ + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (obj); + + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_gnome_vfs_sink_init (GstGnomeVFSSink * sink, GstGnomeVFSSinkClass * klass) +{ + gst_pad_set_query_function (GST_BASE_SINK_PAD (sink), + GST_DEBUG_FUNCPTR (gst_gnome_vfs_sink_query)); + + sink->uri = NULL; + sink->uri_name = NULL; + sink->handle = NULL; + sink->own_handle = FALSE; + sink->current_pos = 0; + + GST_BASE_SINK (sink)->sync = FALSE; +} + +static void +gst_gnome_vfs_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGnomeVFSSink *sink; + GstState cur_state; + + sink = GST_GNOME_VFS_SINK (object); + + gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0); + + if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) { + GST_WARNING_OBJECT (sink, "cannot set property when PAUSED or PLAYING"); + return; + } + + GST_OBJECT_LOCK (sink); + + switch (prop_id) { + case ARG_LOCATION:{ + const gchar *new_location; + + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + + new_location = g_value_get_string (value); + if (new_location) { + sink->uri_name = gst_gnome_vfs_location_to_uri_string (new_location); + sink->uri = gnome_vfs_uri_new (sink->uri_name); + } + break; + } + case ARG_URI:{ + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + if (g_value_get_boxed (value)) { + sink->uri = (GnomeVFSURI *) g_value_dup_boxed (value); + sink->uri_name = gnome_vfs_uri_to_string (sink->uri, 0); + } + break; + } + case ARG_HANDLE:{ + if (sink->uri) { + gnome_vfs_uri_unref (sink->uri); + sink->uri = NULL; + } + if (sink->uri_name) { + g_free (sink->uri_name); + sink->uri_name = NULL; + } + sink->handle = g_value_get_boxed (value); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (sink); +} + +static void +gst_gnome_vfs_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGnomeVFSSink *sink; + + sink = GST_GNOME_VFS_SINK (object); + + GST_OBJECT_LOCK (sink); + + switch (prop_id) { + case ARG_LOCATION: + g_value_set_string (value, sink->uri_name); + break; + case ARG_URI: + g_value_set_boxed (value, sink->uri); + break; + case ARG_HANDLE: + g_value_set_boxed (value, sink->handle); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + GST_OBJECT_UNLOCK (sink); +} + +static gboolean +gst_gnome_vfs_sink_open_file (GstGnomeVFSSink * sink) +{ + GnomeVFSResult result; + + if (sink->uri) { + /* open the file, all permissions, umask will apply */ + result = gnome_vfs_create_uri (&(sink->handle), sink->uri, + GNOME_VFS_OPEN_WRITE, TRUE, + GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE | + GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE | + GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE); + + /* if the file existed and the property says to ask, then ask! */ + if (result == GNOME_VFS_ERROR_FILE_EXISTS) { + gboolean erase_anyway = FALSE; + + g_signal_emit (G_OBJECT (sink), + gst_gnome_vfs_sink_signals[SIGNAL_ERASE_ASK], 0, sink->uri, + &erase_anyway); + if (erase_anyway) { + result = gnome_vfs_create_uri (&(sink->handle), sink->uri, + GNOME_VFS_OPEN_WRITE, FALSE, + GNOME_VFS_PERM_USER_READ | GNOME_VFS_PERM_USER_WRITE | + GNOME_VFS_PERM_GROUP_READ | GNOME_VFS_PERM_GROUP_WRITE | + GNOME_VFS_PERM_OTHER_READ | GNOME_VFS_PERM_OTHER_WRITE); + } + } + + GST_DEBUG_OBJECT (sink, "open: %s", gnome_vfs_result_to_string (result)); + + if (result != GNOME_VFS_OK) { + gchar *filename = gnome_vfs_uri_to_string (sink->uri, + GNOME_VFS_URI_HIDE_PASSWORD); + + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, + (_("Could not open vfs file \"%s\" for writing: %s."), + filename, gnome_vfs_result_to_string (result)), GST_ERROR_SYSTEM); + g_free (filename); + return FALSE; + } + sink->own_handle = TRUE; + } else if (!sink->handle) { + GST_ELEMENT_ERROR (sink, RESOURCE, FAILED, (_("No filename given")), + (NULL)); + return FALSE; + } else { + sink->own_handle = FALSE; + } + + sink->current_pos = 0; + + return TRUE; +} + +static void +gst_gnome_vfs_sink_close_file (GstGnomeVFSSink * sink) +{ + GnomeVFSResult result; + + if (sink->own_handle) { + /* close the file */ + result = gnome_vfs_close (sink->handle); + + if (result != GNOME_VFS_OK) { + gchar *filename = gnome_vfs_uri_to_string (sink->uri, + GNOME_VFS_URI_HIDE_PASSWORD); + + GST_ELEMENT_ERROR (sink, RESOURCE, CLOSE, + (_("Could not close vfs file \"%s\"."), filename), GST_ERROR_SYSTEM); + g_free (filename); + } + + sink->own_handle = FALSE; + sink->handle = NULL; + } +} + +static gboolean +gst_gnome_vfs_sink_start (GstBaseSink * basesink) +{ + gboolean ret; + + ret = gst_gnome_vfs_sink_open_file (GST_GNOME_VFS_SINK (basesink)); + + return ret; +} + +static gboolean +gst_gnome_vfs_sink_stop (GstBaseSink * basesink) +{ + GST_DEBUG_OBJECT (basesink, "closing ..."); + gst_gnome_vfs_sink_close_file (GST_GNOME_VFS_SINK (basesink)); + return TRUE; +} + +static gboolean +gst_gnome_vfs_sink_handle_event (GstBaseSink * basesink, GstEvent * event) +{ + GstGnomeVFSSink *sink; + gboolean ret = TRUE; + + sink = GST_GNOME_VFS_SINK (basesink); + + GST_DEBUG_OBJECT (sink, "processing %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT:{ + GnomeVFSResult res; + GstFormat format; + gint64 offset; + + gst_event_parse_new_segment (event, NULL, NULL, &format, &offset, + NULL, NULL); + + if (format != GST_FORMAT_BYTES) { + GST_WARNING_OBJECT (sink, "ignored NEWSEGMENT event in %s format", + gst_format_get_name (format)); + break; + } + + GST_LOG_OBJECT (sink, "seeking to offset %" G_GINT64_FORMAT, offset); + res = gnome_vfs_seek (sink->handle, GNOME_VFS_SEEK_START, offset); + + if (res != GNOME_VFS_OK) { + GST_ERROR_OBJECT (sink, "Failed to seek to offset %" + G_GINT64_FORMAT ": %s", offset, gnome_vfs_result_to_string (res)); + ret = FALSE; + } else { + sink->current_pos = offset; + } + + break; + } + + case GST_EVENT_FLUSH_START: + case GST_EVENT_EOS:{ + /* No need to flush with GnomeVfs */ + break; + } + default: + break; + } + + return ret; +} + +static gboolean +gst_gnome_vfs_sink_query (GstPad * pad, GstQuery * query) +{ + GstGnomeVFSSink *sink; + GstFormat format; + + sink = GST_GNOME_VFS_SINK (GST_PAD_PARENT (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + gst_query_parse_position (query, &format, NULL); + switch (format) { + case GST_FORMAT_DEFAULT: + case GST_FORMAT_BYTES: + gst_query_set_position (query, GST_FORMAT_BYTES, sink->current_pos); + return TRUE; + default: + return FALSE; + } + + case GST_QUERY_FORMATS: + gst_query_set_formats (query, 2, GST_FORMAT_DEFAULT, GST_FORMAT_BYTES); + return TRUE; + + case GST_QUERY_URI: + gst_query_set_uri (query, sink->uri_name); + return TRUE; + + default: + return gst_pad_query_default (pad, query); + } +} + +static GstFlowReturn +gst_gnome_vfs_sink_render (GstBaseSink * basesink, GstBuffer * buf) +{ + GnomeVFSFileSize written, cur_pos; + GstGnomeVFSSink *sink; + GnomeVFSResult result; + GstFlowReturn ret; + + sink = GST_GNOME_VFS_SINK (basesink); + + if (gnome_vfs_tell (sink->handle, &cur_pos) == GNOME_VFS_OK) { + /* bring up to date with current position for proper reporting */ + sink->current_pos = cur_pos; + } + + result = gnome_vfs_write (sink->handle, GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf), &written); + + switch (result) { + case GNOME_VFS_OK:{ + GST_DEBUG_OBJECT (sink, "wrote %" G_GINT64_FORMAT " bytes at %" + G_GINT64_FORMAT, (gint64) written, (gint64) cur_pos); + + if (written < GST_BUFFER_SIZE (buf)) { + /* FIXME: what to do here? (tpm) */ + g_warning ("%s: %d bytes should be written, only %" + G_GUINT64_FORMAT " bytes written", G_STRLOC, + GST_BUFFER_SIZE (buf), written); + } + + sink->current_pos += GST_BUFFER_SIZE (buf); + ret = GST_FLOW_OK; + break; + } + case GNOME_VFS_ERROR_NO_SPACE:{ + /* TODO: emit signal/send msg on out-of-diskspace and + * handle this gracefully (see open bug) (tpm) */ + GST_ELEMENT_ERROR (sink, RESOURCE, NO_SPACE_LEFT, (NULL), + ("bufsize=%u, written=%u", GST_BUFFER_SIZE (buf), (guint) written)); + ret = GST_FLOW_ERROR; + break; + } + default:{ + gchar *filename = gnome_vfs_uri_to_string (sink->uri, + GNOME_VFS_URI_HIDE_PASSWORD); + + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, + (_("Error while writing to file \"%s\"."), filename), + ("%s, bufsize=%u, written=%u", gnome_vfs_result_to_string (result), + GST_BUFFER_SIZE (buf), (guint) written)); + + g_free (filename); + ret = GST_FLOW_ERROR; + break; + } + } + + return ret; +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_gnome_vfs_sink_uri_get_type (void) +{ + return GST_URI_SINK; +} + +static gchar ** +gst_gnome_vfs_sink_uri_get_protocols (void) +{ + return gst_gnomevfs_get_supported_uris (); +} + +static const gchar * +gst_gnome_vfs_sink_uri_get_uri (GstURIHandler * handler) +{ + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler); + + return sink->uri_name; +} + +static gboolean +gst_gnome_vfs_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstGnomeVFSSink *sink = GST_GNOME_VFS_SINK (handler); + GstState cur_state; + + gst_element_get_state (GST_ELEMENT (sink), &cur_state, NULL, 0); + + if (cur_state == GST_STATE_PLAYING || cur_state == GST_STATE_PAUSED) { + GST_WARNING_OBJECT (sink, "cannot set uri when PAUSED or PLAYING"); + return FALSE; + } + + g_object_set (sink, "location", uri, NULL); + + return TRUE; +} + +static void +gst_gnome_vfs_sink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_gnome_vfs_sink_uri_get_type; + iface->get_protocols = gst_gnome_vfs_sink_uri_get_protocols; + iface->get_uri = gst_gnome_vfs_sink_uri_get_uri; + iface->set_uri = gst_gnome_vfs_sink_uri_set_uri; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.h b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.h new file mode 100644 index 0000000..409add9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssink.h @@ -0,0 +1,84 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2003 Colin Walters + * 2005 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GNOME_VFS_SINK_H__ +#define __GST_GNOME_VFS_SINK_H__ + +#include "gstgnomevfs.h" +#include "gstgnomevfsuri.h" +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GNOME_VFS_SINK \ + (gst_gnome_vfs_sink_get_type()) +#define GST_GNOME_VFS_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSink)) +#define GST_GNOME_VFS_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SINK,GstGnomeVFSSinkClass)) +#define GST_IS_GNOME_VFS_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SINK)) +#define GST_IS_GNOME_VFS_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SINK)) + +typedef struct _GstGnomeVFSSink GstGnomeVFSSink; +typedef struct _GstGnomeVFSSinkClass GstGnomeVFSSinkClass; + +/** + * GstGnomeVFSSink: + * + * Opaque data structure. + */ +struct _GstGnomeVFSSink +{ + GstBaseSink basesink; + + /*< private >*/ + + /* uri */ + GnomeVFSURI *uri; + gchar *uri_name; + + /* handle */ + GnomeVFSHandle *handle; + + /* whether we opened the handle ourselves */ + gboolean own_handle; + + guint64 current_pos; +}; + +struct _GstGnomeVFSSinkClass +{ + GstBaseSinkClass basesink_class; + + /* signals */ + gboolean (*erase_ask) (GstElement * element, GnomeVFSURI * uri); +}; + +GType gst_gnome_vfs_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_SINK_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.c b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.c new file mode 100644 index 0000000..4b2507c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.c @@ -0,0 +1,895 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2002 Kristian Rietveld + * 2002,2003 Colin Walters + * + * gnomevfssrc.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-gnomevfssrc + * @see_also: #GstFileSrc, #GstGnomeVFSSink + * + * This plugin reads data from a local or remote location specified + * by an URI. This location can be specified using any protocol supported by + * the GnomeVFS library. Common protocols are 'file', 'http', 'ftp', or 'smb'. + * + * In case the #GstGnomeVFSSrc:iradio-mode property is set and the + * location is a http resource, gnomevfssrc will send special icecast http + * headers to the server to request additional icecast metainformation. If + * the server is not an icecast server, it will display the same behaviour + * as if the #GstGnomeVFSSrc:iradio-mode property was not set. However, + * if the server is in fact an icecast server, gnomevfssrc will output + * data with a media type of application/x-icy, in which case you will + * need to use the #GstICYDemux element as follow-up element to extract + * the icecast meta data and to determine the underlying media type. + * + * + * Example launch lines + * |[ + * gst-launch -v gnomevfssrc location=file:///home/joe/foo.xyz ! fakesink + * ]| The above pipeline will simply read a local file and do nothing with the + * data read. Instead of gnomevfssrc, we could just as well have used the + * filesrc element here. + * |[ + * gst-launch -v gnomevfssrc location=smb://othercomputer/foo.xyz ! filesink location=/home/joe/foo.xyz + * ]| The above pipeline will copy a file from a remote host to the local file + * system using the Samba protocol. + * |[ + * gst-launch -v gnomevfssrc location=http://music.foobar.com/demo.mp3 ! mad ! audioconvert ! audioresample ! alsasink + * ]| The above pipeline will read and decode and play an mp3 file from a + * web server using the http protocol. + * + */ + + +#define BROKEN_SIG 1 +/*#undef BROKEN_SIG */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst/gst-i18n-plugin.h" + +#include "gstgnomevfssrc.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* gnome-vfs.h doesn't include the following header, which we need: */ +#include + +GST_DEBUG_CATEGORY_STATIC (gnomevfssrc_debug); +#define GST_CAT_DEFAULT gnomevfssrc_debug + +static GStaticMutex count_lock = G_STATIC_MUTEX_INIT; +static gint ref_count = 0; +static gboolean vfs_owner = FALSE; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + ARG_0, + ARG_HANDLE, + ARG_LOCATION, + ARG_IRADIO_MODE, + ARG_IRADIO_NAME, + ARG_IRADIO_GENRE, + ARG_IRADIO_URL, + ARG_IRADIO_TITLE +}; + +static void gst_gnome_vfs_src_base_init (gpointer g_class); +static void gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass); +static void gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc); +static void gst_gnome_vfs_src_finalize (GObject * object); +static void gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static void gst_gnome_vfs_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_gnome_vfs_src_stop (GstBaseSrc * src); +static gboolean gst_gnome_vfs_src_start (GstBaseSrc * src); +static gboolean gst_gnome_vfs_src_is_seekable (GstBaseSrc * src); +static gboolean gst_gnome_vfs_src_check_get_range (GstBaseSrc * src); +static gboolean gst_gnome_vfs_src_get_size (GstBaseSrc * src, guint64 * size); +static GstFlowReturn gst_gnome_vfs_src_create (GstBaseSrc * basesrc, + guint64 offset, guint size, GstBuffer ** buffer); +static gboolean gst_gnome_vfs_src_query (GstBaseSrc * src, GstQuery * query); + +static GstElementClass *parent_class = NULL; + +GType +gst_gnome_vfs_src_get_type (void) +{ + static GType gnomevfssrc_type = 0; + + if (!gnomevfssrc_type) { + static const GTypeInfo gnomevfssrc_info = { + sizeof (GstGnomeVFSSrcClass), + gst_gnome_vfs_src_base_init, + NULL, + (GClassInitFunc) gst_gnome_vfs_src_class_init, + NULL, + NULL, + sizeof (GstGnomeVFSSrc), + 0, + (GInstanceInitFunc) gst_gnome_vfs_src_init, + }; + static const GInterfaceInfo urihandler_info = { + gst_gnome_vfs_src_uri_handler_init, + NULL, + NULL + }; + + gnomevfssrc_type = + g_type_register_static (GST_TYPE_BASE_SRC, + "GstGnomeVFSSrc", &gnomevfssrc_info, 0); + g_type_add_interface_static (gnomevfssrc_type, GST_TYPE_URI_HANDLER, + &urihandler_info); + } + return gnomevfssrc_type; +} + +static void +gst_gnome_vfs_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_set_details_simple (element_class, + "GnomeVFS Source", "Source/File", + "Read from any GnomeVFS-supported file", + "Bastien Nocera , " + "GStreamer maintainers "); + + GST_DEBUG_CATEGORY_INIT (gnomevfssrc_debug, "gnomevfssrc", 0, + "Gnome-VFS Source"); +} + +static void +gst_gnome_vfs_src_class_init (GstGnomeVFSSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasesrc_class = GST_BASE_SRC_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_gnome_vfs_src_finalize; + gobject_class->set_property = gst_gnome_vfs_src_set_property; + gobject_class->get_property = gst_gnome_vfs_src_get_property; + + /* properties */ + gst_element_class_install_std_props (GST_ELEMENT_CLASS (klass), + "location", ARG_LOCATION, G_PARAM_READWRITE, NULL); + g_object_class_install_property (gobject_class, + ARG_HANDLE, + g_param_spec_boxed ("handle", + "GnomeVFSHandle", "Handle for GnomeVFS", + GST_TYPE_GNOME_VFS_HANDLE, + GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /* icecast stuff */ + g_object_class_install_property (gobject_class, + ARG_IRADIO_MODE, + g_param_spec_boolean ("iradio-mode", + "iradio-mode", + "Enable internet radio mode (extraction of shoutcast/icecast metadata)", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, + ARG_IRADIO_NAME, + g_param_spec_string ("iradio-name", + "iradio-name", "Name of the stream", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_IRADIO_GENRE, + g_param_spec_string ("iradio-genre", "iradio-genre", + "Genre of the stream", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_IRADIO_URL, + g_param_spec_string ("iradio-url", "iradio-url", + "Homepage URL for radio stream", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_IRADIO_TITLE, + g_param_spec_string ("iradio-title", "iradio-title", + "Name of currently playing song", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_stop); + gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_get_size); + gstbasesrc_class->is_seekable = + GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_is_seekable); + gstbasesrc_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_check_get_range); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_create); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_gnome_vfs_src_query); +} + +static void +gst_gnome_vfs_src_init (GstGnomeVFSSrc * gnomevfssrc) +{ + gnomevfssrc->uri = NULL; + gnomevfssrc->uri_name = NULL; + gnomevfssrc->handle = NULL; + gnomevfssrc->curoffset = 0; + gnomevfssrc->seekable = FALSE; + + gnomevfssrc->iradio_mode = FALSE; + gnomevfssrc->http_callbacks_pushed = FALSE; + gnomevfssrc->iradio_name = NULL; + gnomevfssrc->iradio_genre = NULL; + gnomevfssrc->iradio_url = NULL; + gnomevfssrc->iradio_title = NULL; + + g_static_mutex_lock (&count_lock); + if (ref_count == 0) { + /* gnome vfs engine init */ + if (gnome_vfs_initialized () == FALSE) { + gnome_vfs_init (); + vfs_owner = TRUE; + } + } + ref_count++; + g_static_mutex_unlock (&count_lock); +} + +static void +gst_gnome_vfs_src_finalize (GObject * object) +{ + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (object); + + g_static_mutex_lock (&count_lock); + ref_count--; + if (ref_count == 0 && vfs_owner) { + if (gnome_vfs_initialized () == TRUE) { + gnome_vfs_shutdown (); + } + } + g_static_mutex_unlock (&count_lock); + + if (src->uri) { + gnome_vfs_uri_unref (src->uri); + src->uri = NULL; + } + + g_free (src->uri_name); + src->uri_name = NULL; + + g_free (src->iradio_name); + src->iradio_name = NULL; + + g_free (src->iradio_genre); + src->iradio_genre = NULL; + + g_free (src->iradio_url); + src->iradio_url = NULL; + + g_free (src->iradio_title); + src->iradio_title = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* + * URI interface support. + */ + +static GstURIType +gst_gnome_vfs_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_gnome_vfs_src_uri_get_protocols (void) +{ + return gst_gnomevfs_get_supported_uris (); +} + +static const gchar * +gst_gnome_vfs_src_uri_get_uri (GstURIHandler * handler) +{ + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler); + + return src->uri_name; +} + +static gboolean +gst_gnome_vfs_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (handler); + + if (GST_STATE (src) == GST_STATE_PLAYING || + GST_STATE (src) == GST_STATE_PAUSED) + return FALSE; + + g_object_set (G_OBJECT (src), "location", uri, NULL); + + return TRUE; +} + +static void +gst_gnome_vfs_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_gnome_vfs_src_uri_get_type; + iface->get_protocols = gst_gnome_vfs_src_uri_get_protocols; + iface->get_uri = gst_gnome_vfs_src_uri_get_uri; + iface->set_uri = gst_gnome_vfs_src_uri_set_uri; +} + +static void +gst_gnome_vfs_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (object); + + switch (prop_id) { + case ARG_LOCATION:{ + const gchar *new_location; + + /* the element must be stopped or paused in order to do this */ + if (GST_STATE (src) == GST_STATE_PLAYING || + GST_STATE (src) == GST_STATE_PAUSED) + break; + + if (src->uri) { + gnome_vfs_uri_unref (src->uri); + src->uri = NULL; + } + if (src->uri_name) { + g_free (src->uri_name); + src->uri_name = NULL; + } + + new_location = g_value_get_string (value); + if (new_location) { + src->uri_name = gst_gnome_vfs_location_to_uri_string (new_location); + src->uri = gnome_vfs_uri_new (src->uri_name); + } + break; + } + case ARG_HANDLE: + if (GST_STATE (src) == GST_STATE_NULL || + GST_STATE (src) == GST_STATE_READY) { + if (src->uri) { + gnome_vfs_uri_unref (src->uri); + src->uri = NULL; + } + if (src->uri_name) { + g_free (src->uri_name); + src->uri_name = NULL; + } + src->handle = g_value_get_boxed (value); + } + break; + case ARG_IRADIO_MODE: + src->iradio_mode = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gnome_vfs_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (object); + + switch (prop_id) { + case ARG_LOCATION: + g_value_set_string (value, src->uri_name); + break; + case ARG_HANDLE: + g_value_set_boxed (value, src->handle); + break; + case ARG_IRADIO_MODE: + g_value_set_boolean (value, src->iradio_mode); + break; + case ARG_IRADIO_NAME: + g_value_set_string (value, src->iradio_name); + break; + case ARG_IRADIO_GENRE: + g_value_set_string (value, src->iradio_genre); + break; + case ARG_IRADIO_URL: + g_value_set_string (value, src->iradio_url); + break; + case ARG_IRADIO_TITLE: + g_value_set_string (value, src->iradio_title); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static char * +gst_gnome_vfs_src_unicodify (const char *str) +{ + const gchar *env_vars[] = { "GST_ICY_TAG_ENCODING", + "GST_TAG_ENCODING", NULL + }; + + return gst_tag_freeform_string_to_utf8 (str, -1, env_vars); +} + +static void +gst_gnome_vfs_src_send_additional_headers_callback (gconstpointer in, + gsize in_size, gpointer out, gsize out_size, gpointer callback_data) +{ + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data); + GnomeVFSModuleCallbackAdditionalHeadersOut *out_args = + (GnomeVFSModuleCallbackAdditionalHeadersOut *) out; + + if (!src->iradio_mode) + return; + GST_DEBUG_OBJECT (src, "sending headers\n"); + + out_args->headers = g_list_append (out_args->headers, + g_strdup ("icy-metadata:1\r\n")); +} + +static void +gst_gnome_vfs_src_received_headers_callback (gconstpointer in, + gsize in_size, gpointer out, gsize out_size, gpointer callback_data) +{ + GList *i; + gint icy_metaint; + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (callback_data); + GnomeVFSModuleCallbackReceivedHeadersIn *in_args = + (GnomeVFSModuleCallbackReceivedHeadersIn *) in; + + /* This is only used for internet radio stuff right now */ + if (!src->iradio_mode) + return; + + GST_DEBUG_OBJECT (src, "receiving internet radio metadata\n"); + + /* FIXME: Could we use "Accept-Ranges: bytes" + * http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.5 + * to enable pull-mode? + */ + + for (i = in_args->headers; i; i = i->next) { + char *data = (char *) i->data; + char *value = strchr (data, ':'); + char *key; + + if (!value) + continue; + + value++; + g_strstrip (value); + if (!strlen (value)) + continue; + + GST_LOG_OBJECT (src, "data %s", data); + + /* Icecast stuff */ + if (strncmp (data, "icy-metaint:", 12) == 0) { /* ugh */ + if (sscanf (data + 12, "%d", &icy_metaint) == 1) { + if (icy_metaint > 0) { + GstCaps *icy_caps; + + icy_caps = gst_caps_new_simple ("application/x-icy", + "metadata-interval", G_TYPE_INT, icy_metaint, NULL); + gst_pad_set_caps (GST_BASE_SRC_PAD (src), icy_caps); + gst_caps_unref (icy_caps); + } + } + continue; + } + + if (!strncmp (data, "icy-", 4)) + key = data + 4; + else + continue; + + GST_DEBUG_OBJECT (src, "key: %s", key); + if (!strncmp (key, "name", 4)) { + g_free (src->iradio_name); + src->iradio_name = gst_gnome_vfs_src_unicodify (value); + if (src->iradio_name) + g_object_notify (G_OBJECT (src), "iradio-name"); + } else if (!strncmp (key, "genre", 5)) { + g_free (src->iradio_genre); + src->iradio_genre = gst_gnome_vfs_src_unicodify (value); + if (src->iradio_genre) + g_object_notify (G_OBJECT (src), "iradio-genre"); + } else if (!strncmp (key, "url", 3)) { + g_free (src->iradio_url); + src->iradio_url = gst_gnome_vfs_src_unicodify (value); + if (src->iradio_url) + g_object_notify (G_OBJECT (src), "iradio-url"); + } + } +} + +static void +gst_gnome_vfs_src_push_callbacks (GstGnomeVFSSrc * src) +{ + if (src->http_callbacks_pushed) + return; + + GST_DEBUG_OBJECT (src, "pushing callbacks"); + gnome_vfs_module_callback_push + (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS, + gst_gnome_vfs_src_send_additional_headers_callback, src, NULL); + gnome_vfs_module_callback_push + (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS, + gst_gnome_vfs_src_received_headers_callback, src, NULL); + + src->http_callbacks_pushed = TRUE; +} + +static void +gst_gnome_vfs_src_pop_callbacks (GstGnomeVFSSrc * src) +{ + if (!src->http_callbacks_pushed) + return; + + GST_DEBUG_OBJECT (src, "popping callbacks"); + gnome_vfs_module_callback_pop + (GNOME_VFS_MODULE_CALLBACK_HTTP_SEND_ADDITIONAL_HEADERS); + gnome_vfs_module_callback_pop + (GNOME_VFS_MODULE_CALLBACK_HTTP_RECEIVED_HEADERS); + + src->http_callbacks_pushed = FALSE; +} + +/* + * Read a new buffer from src->reqoffset, takes care of events + * and seeking and such. + */ +static GstFlowReturn +gst_gnome_vfs_src_create (GstBaseSrc * basesrc, guint64 offset, guint size, + GstBuffer ** buffer) +{ + GnomeVFSResult res; + GstBuffer *buf; + GnomeVFSFileSize readbytes; + guint8 *data; + guint todo; + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (basesrc); + + GST_DEBUG ("now at %" G_GINT64_FORMAT ", reading from %" G_GUINT64_FORMAT + ", size %u", src->curoffset, offset, size); + + /* seek if required */ + if (G_UNLIKELY (src->curoffset != offset)) { + GST_DEBUG ("need to seek"); + if (src->seekable) { + GST_DEBUG ("seeking to %" G_GUINT64_FORMAT, offset); + res = gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_START, offset); + if (res != GNOME_VFS_OK) + goto seek_failed; + src->curoffset = offset; + } else { + goto cannot_seek; + } + } + + buf = gst_buffer_try_new_and_alloc (size); + if (G_UNLIKELY (buf == NULL)) { + GST_ERROR_OBJECT (src, "Failed to allocate %u bytes", size); + return GST_FLOW_ERROR; + } + + data = GST_BUFFER_DATA (buf); + + todo = size; + while (todo > 0) { + /* this can return less that we ask for */ + res = gnome_vfs_read (src->handle, data, todo, &readbytes); + + if (G_UNLIKELY (res == GNOME_VFS_ERROR_EOF || (res == GNOME_VFS_OK + && readbytes == 0))) + goto eos; + + if (G_UNLIKELY (res != GNOME_VFS_OK)) + goto read_failed; + + if (readbytes < todo) { + data = &data[readbytes]; + todo -= readbytes; + } else { + todo = 0; + } + GST_LOG (" got size %" G_GUINT64_FORMAT, readbytes); + } + GST_BUFFER_OFFSET (buf) = src->curoffset; + src->curoffset += size; + + /* we're done, return the buffer */ + *buffer = buf; + + return GST_FLOW_OK; + +seek_failed: + { + GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), + ("Failed to seek to requested position %" G_GINT64_FORMAT ": %s", + offset, gnome_vfs_result_to_string (res))); + return GST_FLOW_ERROR; + } +cannot_seek: + { + GST_ELEMENT_ERROR (src, RESOURCE, SEEK, (NULL), + ("Requested seek from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT + " on non-seekable stream", src->curoffset, offset)); + return GST_FLOW_ERROR; + } +read_failed: + { + gst_buffer_unref (buf); + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Failed to read data: %s", gnome_vfs_result_to_string (res))); + return GST_FLOW_ERROR; + } +eos: + { + gst_buffer_unref (buf); + GST_DEBUG_OBJECT (src, "Reading data gave EOS"); + return GST_FLOW_UNEXPECTED; + } +} + +static gboolean +gst_gnome_vfs_src_query (GstBaseSrc * basesrc, GstQuery * query) +{ + gboolean ret = FALSE; + GstGnomeVFSSrc *src = GST_GNOME_VFS_SRC (basesrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_URI: + gst_query_set_uri (query, src->uri_name); + ret = TRUE; + break; + default: + ret = FALSE; + break; + } + + if (!ret) + ret = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + + return ret; +} + +static gboolean +gst_gnome_vfs_src_is_seekable (GstBaseSrc * basesrc) +{ + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (basesrc); + + return src->seekable; +} + +static gboolean +gst_gnome_vfs_src_check_get_range (GstBaseSrc * basesrc) +{ + GstGnomeVFSSrc *src; + const gchar *protocol; + + src = GST_GNOME_VFS_SRC (basesrc); + + if (src->uri == NULL) { + GST_WARNING_OBJECT (src, "no URI set yet"); + return FALSE; + } + + if (gnome_vfs_uri_is_local (src->uri)) { + GST_LOG_OBJECT (src, "local URI (%s), assuming random access is possible", + GST_STR_NULL (src->uri_name)); + return TRUE; + } + + /* blacklist certain protocols we know won't work getrange-based */ + protocol = gnome_vfs_uri_get_scheme (src->uri); + if (protocol == NULL) + goto undecided; + + if (strcmp (protocol, "http") == 0 || strcmp (protocol, "https") == 0) { + GST_LOG_OBJECT (src, "blacklisted protocol '%s', no random access possible" + " (URI=%s)", protocol, GST_STR_NULL (src->uri_name)); + return FALSE; + } + + /* fall through to undecided */ + +undecided: + { + /* don't know what to do, let the basesrc class decide for us */ + GST_LOG_OBJECT (src, "undecided about URI '%s', let base class handle it", + GST_STR_NULL (src->uri_name)); + + if (GST_BASE_SRC_CLASS (parent_class)->check_get_range) + return GST_BASE_SRC_CLASS (parent_class)->check_get_range (basesrc); + + return FALSE; + } +} + +static gboolean +gst_gnome_vfs_src_get_size (GstBaseSrc * basesrc, guint64 * size) +{ + GstGnomeVFSSrc *src; + GnomeVFSFileInfo *info; + GnomeVFSFileInfoOptions options; + GnomeVFSResult res; + + src = GST_GNOME_VFS_SRC (basesrc); + + *size = -1; + info = gnome_vfs_file_info_new (); + options = GNOME_VFS_FILE_INFO_DEFAULT | GNOME_VFS_FILE_INFO_FOLLOW_LINKS; + res = gnome_vfs_get_file_info_from_handle (src->handle, info, options); + if (res == GNOME_VFS_OK) { + if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) { + *size = info->size; + GST_DEBUG_OBJECT (src, "from handle: %" G_GUINT64_FORMAT " bytes", *size); + } else if (src->own_handle && gnome_vfs_uri_is_local (src->uri)) { + GST_DEBUG_OBJECT (src, + "file size not known, file local, trying fallback"); + res = gnome_vfs_get_file_info_uri (src->uri, info, options); + if (res == GNOME_VFS_OK && + (info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_SIZE) != 0) { + *size = info->size; + GST_DEBUG_OBJECT (src, "from uri: %" G_GUINT64_FORMAT " bytes", *size); + } + } + } else { + GST_WARNING_OBJECT (src, "getting info failed: %s", + gnome_vfs_result_to_string (res)); + } + gnome_vfs_file_info_unref (info); + + if (*size == (GnomeVFSFileSize) - 1) + return FALSE; + + GST_DEBUG_OBJECT (src, "return size %" G_GUINT64_FORMAT, *size); + + return TRUE; +} + +/* open the file, do stuff necessary to go to PAUSED state */ +static gboolean +gst_gnome_vfs_src_start (GstBaseSrc * basesrc) +{ + GnomeVFSResult res; + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (basesrc); + + gst_gnome_vfs_src_push_callbacks (src); + + if (src->uri != NULL) { + GnomeVFSOpenMode mode = GNOME_VFS_OPEN_READ; + + /* this can block... */ + res = gnome_vfs_open_uri (&src->handle, src->uri, mode); + if (res != GNOME_VFS_OK) + goto open_failed; + src->own_handle = TRUE; + } else if (!src->handle) { + goto no_filename; + } else { + src->own_handle = FALSE; + } + + if (gnome_vfs_seek (src->handle, GNOME_VFS_SEEK_CURRENT, 0) == GNOME_VFS_OK) { + src->seekable = TRUE; + } else { + src->seekable = FALSE; + } + + return TRUE; + + /* ERRORS */ +open_failed: + { + gchar *filename = gnome_vfs_uri_to_string (src->uri, + GNOME_VFS_URI_HIDE_PASSWORD); + + gst_gnome_vfs_src_pop_callbacks (src); + + if (res == GNOME_VFS_ERROR_NOT_FOUND || + res == GNOME_VFS_ERROR_HOST_NOT_FOUND || + res == GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE) { + GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, (NULL), + ("Could not open vfs file \"%s\" for reading: %s (%d)", + filename, gnome_vfs_result_to_string (res), res)); + } else { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Could not open vfs file \"%s\" for reading: %s (%d)", + filename, gnome_vfs_result_to_string (res), res)); + } + g_free (filename); + return FALSE; + } +no_filename: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), ("No filename given")); + return FALSE; + } +} + +static gboolean +gst_gnome_vfs_src_stop (GstBaseSrc * basesrc) +{ + GstGnomeVFSSrc *src; + + src = GST_GNOME_VFS_SRC (basesrc); + + gst_gnome_vfs_src_pop_callbacks (src); + + if (src->own_handle) { + GnomeVFSResult res; + + res = gnome_vfs_close (src->handle); + if (res != GNOME_VFS_OK) { + GST_ELEMENT_ERROR (src, RESOURCE, CLOSE, (NULL), + ("Could not close vfs handle: %s", gnome_vfs_result_to_string (res))); + } + src->handle = NULL; + } + src->curoffset = 0; + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.h b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.h new file mode 100644 index 0000000..31c1f65 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfssrc.h @@ -0,0 +1,87 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2002 Kristian Rietveld + * 2002,2003 Colin Walters + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_GNOME_VFS_SRC_H__ +#define __GST_GNOME_VFS_SRC_H__ + +#include + +#include "gstgnomevfs.h" +#include "gstgnomevfsuri.h" +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GNOME_VFS_SRC \ + (gst_gnome_vfs_src_get_type()) +#define GST_GNOME_VFS_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrc)) +#define GST_GNOME_VFS_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNOME_VFS_SRC,GstGnomeVFSSrcClass)) +#define GST_IS_GNOME_VFS_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNOME_VFS_SRC)) +#define GST_IS_GNOME_VFS_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNOME_VFS_SRC)) + +typedef struct _GstGnomeVFSSrc GstGnomeVFSSrc; +typedef struct _GstGnomeVFSSrcClass GstGnomeVFSSrcClass; + +/** + * GstGnomeVFSSrc: + * + * Opaque data structure. + */ +struct _GstGnomeVFSSrc +{ + GstBaseSrc basesrc; + + /* uri, file, ... */ + GnomeVFSURI *uri; + gchar *uri_name; + GnomeVFSHandle *handle; + gboolean own_handle; + GnomeVFSFileOffset curoffset; /* current offset in file */ + gboolean seekable; + + /* shoutcast/icecast metadata extraction handling */ + gboolean iradio_mode; + gboolean http_callbacks_pushed; + + gchar *iradio_name; + gchar *iradio_genre; + gchar *iradio_url; + gchar *iradio_title; +}; + +struct _GstGnomeVFSSrcClass +{ + GstBaseSrcClass basesrc_class; +}; + +GType gst_gnome_vfs_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_SRC_H__ */ + + diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.c b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.c new file mode 100644 index 0000000..e811c31 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.c @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2001 Bastien Nocera + * 2003 Colin Walters + * + * gstgnomevfssink.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gstgnomevfsuri.h" + +#include + +/* FIXME: move this to source and sink and remove this file: + * e.g. sinks cannot save to http:// and src cannot read from burn:// + */ +static gpointer +_internal_get_supported_uris (gpointer data) +{ + /* no dav/davs in the list, because they don't appear to be reliable enough */ + const gchar *uris[] = { + "http://localhost/bla", + "https://localhost/bla", + "file:///bla", + "smb://localhost/bla", + "ftp://localhost/bla", + "sftp://localhost/bla", + "nfs://localhost/bla", + "ssh://localhost/bla", + "burn://" + }; + GnomeVFSURI *uri; + gchar **result; + gint n, r = 0; + + result = g_new0 (gchar *, G_N_ELEMENTS (uris) + 1); + for (n = 0; n < G_N_ELEMENTS (uris); n++) { + uri = gnome_vfs_uri_new (uris[n]); + if (uri != NULL) { + gchar *protocol = g_strdup (uris[n]); + gint n; + + gnome_vfs_uri_unref (uri); + for (n = 0; protocol[n] != '\0'; n++) { + if (protocol[n] == ':') { + protocol[n] = '\0'; + break; + } + } + + GST_DEBUG ("adding protocol '%s'", protocol); + result[r++] = protocol; + } else { + GST_DEBUG ("could not create GnomeVfsUri from '%s'", uris[n]); + } + } + result[r] = NULL; + + return result; +} + +gchar ** +gst_gnomevfs_get_supported_uris (void) +{ + static GOnce once = G_ONCE_INIT; + + g_once (&once, _internal_get_supported_uris, NULL); + return (gchar **) once.retval; +} diff --git a/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.h b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.h new file mode 100644 index 0000000..f99b1f7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/gnomevfs/gstgnomevfsuri.h @@ -0,0 +1,32 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_GNOME_VFS_URI_H__ +#define __GST_GNOME_VFS_URI_H__ + +#include + +G_BEGIN_DECLS + +gchar **gst_gnomevfs_get_supported_uris (void); + +G_END_DECLS + +#endif /* __GST_GNOME_VFS_URI_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/libvisual/Makefile.am b/gst-plugins-base-subtitles0.10/ext/libvisual/Makefile.am new file mode 100644 index 0000000..839900e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/libvisual/Makefile.am @@ -0,0 +1,8 @@ +plugin_LTLIBRARIES = libgstlibvisual.la + +libgstlibvisual_la_SOURCES = visual.c +libgstlibvisual_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(LIBVISUAL_CFLAGS) +libgstlibvisual_la_LIBADD = $(GST_BASE_LIBS) $(LIBVISUAL_LIBS) +libgstlibvisual_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstlibvisual_la_LIBTOOLFLAGS = --tag=disable-static + diff --git a/gst-plugins-base-subtitles0.10/ext/libvisual/visual.c b/gst-plugins-base-subtitles0.10/ext/libvisual/visual.c new file mode 100644 index 0000000..48c1e27 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/libvisual/visual.c @@ -0,0 +1,1027 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include +#include + +#define GST_TYPE_VISUAL (gst_visual_get_type()) +#define GST_IS_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VISUAL)) +#define GST_VISUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VISUAL,GstVisual)) +#define GST_IS_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VISUAL)) +#define GST_VISUAL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VISUAL,GstVisualClass)) +#define GST_VISUAL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VISUAL, GstVisualClass)) + +typedef struct _GstVisual GstVisual; +typedef struct _GstVisualClass GstVisualClass; + +GST_DEBUG_CATEGORY_STATIC (libvisual_debug); +#define GST_CAT_DEFAULT (libvisual_debug) + +/* amounf of samples before we can feed libvisual */ +#define VISUAL_SAMPLES 512 + +#define DEFAULT_WIDTH 320 +#define DEFAULT_HEIGHT 240 +#define DEFAULT_FPS_N 25 +#define DEFAULT_FPS_D 1 + +struct _GstVisual +{ + GstElement element; + + /* pads */ + GstPad *sinkpad; + GstPad *srcpad; + GstSegment segment; + + /* libvisual stuff */ + VisAudio *audio; + VisVideo *video; + VisActor *actor; + + /* audio/video state */ + gint channels; + gint rate; /* Input samplerate */ + gint bps; + + /* framerate numerator & denominator */ + gint fps_n; + gint fps_d; + gint width; + gint height; + GstClockTime duration; + guint outsize; + + /* samples per frame based on caps */ + guint spf; + + /* state stuff */ + GstAdapter *adapter; + guint count; + + /* QoS stuff *//* with LOCK */ + gdouble proportion; + GstClockTime earliest_time; +}; + +struct _GstVisualClass +{ + GstElementClass parent_class; + + VisPluginRef *plugin; +}; + +GType gst_visual_get_type (void); + + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN "; " +#if G_BYTE_ORDER == G_BIG_ENDIAN + GST_VIDEO_CAPS_RGB "; " +#else + GST_VIDEO_CAPS_BGR "; " +#endif + GST_VIDEO_CAPS_RGB_16) + ); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "width = (int) 16, " + "depth = (int) 16, " + "endianness = (int) BYTE_ORDER, " + "signed = (boolean) TRUE, " "channels = (int) { 1, 2 }, " +#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000 + "rate = (int) { 8000, 11250, 22500, 32000, 44100, 48000, 96000 }" +#else + "rate = (int) [ 1000, MAX ]" +#endif + ) + ); + + +static void gst_visual_class_init (gpointer g_class, gpointer class_data); +static void gst_visual_init (GstVisual * visual); +static void gst_visual_dispose (GObject * object); + +static GstStateChangeReturn gst_visual_change_state (GstElement * element, + GstStateChange transition); +static GstFlowReturn gst_visual_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_visual_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_visual_src_event (GstPad * pad, GstEvent * event); + +static gboolean gst_visual_src_query (GstPad * pad, GstQuery * query); + +static gboolean gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_visual_src_setcaps (GstPad * pad, GstCaps * caps); +static GstCaps *gst_visual_getcaps (GstPad * pad); +static void libvisual_log_handler (const char *message, const char *funcname, + void *priv); + +static GstElementClass *parent_class = NULL; + +GType +gst_visual_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo info = { + sizeof (GstVisualClass), + NULL, + NULL, + gst_visual_class_init, + NULL, + NULL, + sizeof (GstVisual), + 0, + (GInstanceInitFunc) gst_visual_init, + }; + + type = g_type_register_static (GST_TYPE_ELEMENT, "GstVisual", &info, 0); + } + return type; +} + +static void +libvisual_log_handler (const char *message, const char *funcname, void *priv) +{ + GST_CAT_LEVEL_LOG (libvisual_debug, (GstDebugLevel) (priv), NULL, "%s - %s", + funcname, message); +} + +static void +gst_visual_class_init (gpointer g_class, gpointer class_data) +{ + GstVisualClass *klass = GST_VISUAL_CLASS (g_class); + GstElementClass *element = GST_ELEMENT_CLASS (g_class); + GObjectClass *object = G_OBJECT_CLASS (g_class); + + klass->plugin = class_data; + + element->change_state = gst_visual_change_state; + + if (class_data == NULL) { + parent_class = g_type_class_peek_parent (g_class); + } else { + char *longname = g_strdup_printf ("libvisual %s plugin v.%s", + klass->plugin->info->name, klass->plugin->info->version); + + /* FIXME: improve to only register what plugin supports? */ + gst_element_class_add_pad_template (element, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element, + gst_static_pad_template_get (&sink_template)); + gst_element_class_set_details_simple (element, + longname, "Visualization", + klass->plugin->info->about, "Benjamin Otte "); + + g_free (longname); + } + + object->dispose = gst_visual_dispose; +} + +static void +gst_visual_init (GstVisual * visual) +{ + /* create the sink and src pads */ + visual->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_setcaps_function (visual->sinkpad, gst_visual_sink_setcaps); + gst_pad_set_chain_function (visual->sinkpad, gst_visual_chain); + gst_pad_set_event_function (visual->sinkpad, gst_visual_sink_event); + gst_element_add_pad (GST_ELEMENT (visual), visual->sinkpad); + + visual->srcpad = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_setcaps_function (visual->srcpad, gst_visual_src_setcaps); + gst_pad_set_getcaps_function (visual->srcpad, gst_visual_getcaps); + gst_pad_set_event_function (visual->srcpad, gst_visual_src_event); + gst_pad_set_query_function (visual->srcpad, gst_visual_src_query); + gst_element_add_pad (GST_ELEMENT (visual), visual->srcpad); + + visual->adapter = gst_adapter_new (); +} + +static void +gst_visual_clear_actors (GstVisual * visual) +{ + if (visual->actor) { + visual_object_unref (VISUAL_OBJECT (visual->actor)); + visual->actor = NULL; + } + if (visual->video) { + visual_object_unref (VISUAL_OBJECT (visual->video)); + visual->video = NULL; + } + if (visual->audio) { + visual_object_unref (VISUAL_OBJECT (visual->audio)); + visual->audio = NULL; + } +} + +static void +gst_visual_dispose (GObject * object) +{ + GstVisual *visual = GST_VISUAL (object); + + if (visual->adapter) { + g_object_unref (visual->adapter); + visual->adapter = NULL; + } + gst_visual_clear_actors (visual); + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); +} + +static void +gst_visual_reset (GstVisual * visual) +{ + gst_adapter_clear (visual->adapter); + gst_segment_init (&visual->segment, GST_FORMAT_UNDEFINED); + + GST_OBJECT_LOCK (visual); + visual->proportion = 1.0; + visual->earliest_time = -1; + GST_OBJECT_UNLOCK (visual); +} + +static GstCaps * +gst_visual_getcaps (GstPad * pad) +{ + GstCaps *ret; + GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); + int depths; + + if (!visual->actor) { + ret = gst_caps_copy (gst_pad_get_pad_template_caps (visual->srcpad)); + goto beach; + } + + ret = gst_caps_new_empty (); + depths = visual_actor_get_supported_depth (visual->actor); + if (depths < 0) { + /* FIXME: set an error */ + goto beach; + } + if (depths == VISUAL_VIDEO_DEPTH_GL) { + /* We can't handle GL only plugins */ + goto beach; + } + + GST_DEBUG_OBJECT (visual, "libvisual plugin supports depths %u (0x%04x)", + depths, depths); + /* if (depths & VISUAL_VIDEO_DEPTH_32BIT) Always supports 32bit output */ + gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_xRGB_HOST_ENDIAN)); + + if (depths & VISUAL_VIDEO_DEPTH_24BIT) { +#if G_BYTE_ORDER == G_BIG_ENDIAN + gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB)); +#else + gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_BGR)); +#endif + } + if (depths & VISUAL_VIDEO_DEPTH_16BIT) { + gst_caps_append (ret, gst_caps_from_string (GST_VIDEO_CAPS_RGB_16)); + } + +beach: + + GST_DEBUG_OBJECT (visual, "returning caps %" GST_PTR_FORMAT, ret); + gst_object_unref (visual); + return ret; +} + +static gboolean +gst_visual_src_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); + GstStructure *structure; + gint depth, pitch; + + structure = gst_caps_get_structure (caps, 0); + + GST_DEBUG_OBJECT (visual, "src pad got caps %" GST_PTR_FORMAT, caps); + + if (!gst_structure_get_int (structure, "width", &visual->width)) + goto error; + if (!gst_structure_get_int (structure, "height", &visual->height)) + goto error; + if (!gst_structure_get_int (structure, "bpp", &depth)) + goto error; + if (!gst_structure_get_fraction (structure, "framerate", &visual->fps_n, + &visual->fps_d)) + goto error; + + visual_video_set_depth (visual->video, + visual_video_depth_enum_from_value (depth)); + visual_video_set_dimension (visual->video, visual->width, visual->height); + pitch = GST_ROUND_UP_4 (visual->width * visual->video->bpp); + visual_video_set_pitch (visual->video, pitch); + visual_actor_video_negotiate (visual->actor, 0, FALSE, FALSE); + + /* precalc some values */ + visual->outsize = visual->video->height * pitch; + visual->spf = + gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n); + visual->duration = + gst_util_uint64_scale_int (GST_SECOND, visual->fps_d, visual->fps_n); + + gst_object_unref (visual); + return TRUE; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (visual, "error parsing caps"); + gst_object_unref (visual); + return FALSE; + } +} + +static gboolean +gst_visual_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "channels", &visual->channels); + gst_structure_get_int (structure, "rate", &visual->rate); + + /* this is how many samples we need to fill one frame at the requested + * framerate. */ + if (visual->fps_n != 0) { + visual->spf = + gst_util_uint64_scale_int (visual->rate, visual->fps_d, visual->fps_n); + } + visual->bps = visual->channels * sizeof (gint16); + + gst_object_unref (visual); + return TRUE; +} + +static gboolean +gst_vis_src_negotiate (GstVisual * visual) +{ + GstCaps *othercaps, *target; + GstStructure *structure; + GstCaps *caps; + + caps = gst_pad_get_caps (visual->srcpad); + + /* see what the peer can do */ + othercaps = gst_pad_peer_get_caps (visual->srcpad); + if (othercaps) { + target = gst_caps_intersect (othercaps, caps); + gst_caps_unref (othercaps); + gst_caps_unref (caps); + + if (gst_caps_is_empty (target)) + goto no_format; + + gst_caps_truncate (target); + } else { + /* need a copy, we'll be modifying it when fixating */ + target = gst_caps_copy (caps); + gst_caps_unref (caps); + } + + /* fixate in case something is not fixed. This does nothing if the value is + * already fixed. For video we always try to fixate to something like + * 320x240x25 by convention. */ + structure = gst_caps_get_structure (target, 0); + gst_structure_fixate_field_nearest_int (structure, "width", DEFAULT_WIDTH); + gst_structure_fixate_field_nearest_int (structure, "height", DEFAULT_HEIGHT); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", + DEFAULT_FPS_N, DEFAULT_FPS_D); + + gst_pad_set_caps (visual->srcpad, target); + gst_caps_unref (target); + + return TRUE; + + /* ERRORS */ +no_format: + { + GST_ELEMENT_ERROR (visual, STREAM, FORMAT, (NULL), + ("could not negotiate output format")); + gst_caps_unref (target); + return FALSE; + } +} + +static gboolean +gst_visual_sink_event (GstPad * pad, GstEvent * event) +{ + GstVisual *visual; + gboolean res; + + visual = GST_VISUAL (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + res = gst_pad_push_event (visual->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + /* reset QoS and adapter. */ + gst_visual_reset (visual); + res = gst_pad_push_event (visual->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + gboolean update; + + /* the newsegment values are used to clip the input samples + * and to convert the incomming timestamps to running time so + * we can do QoS */ + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + /* now configure the values */ + gst_segment_set_newsegment_full (&visual->segment, update, + rate, arate, format, start, stop, time); + + /* and forward */ + res = gst_pad_push_event (visual->srcpad, event); + break; + } + default: + res = gst_pad_push_event (visual->srcpad, event); + break; + } + + gst_object_unref (visual); + return res; +} + +static gboolean +gst_visual_src_event (GstPad * pad, GstEvent * event) +{ + GstVisual *visual; + gboolean res; + + visual = GST_VISUAL (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_QOS: + { + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + + gst_event_parse_qos (event, &proportion, &diff, ×tamp); + + /* save stuff for the _chain function */ + GST_OBJECT_LOCK (visual); + visual->proportion = proportion; + if (diff >= 0) + /* we're late, this is a good estimate for next displayable + * frame (see part-qos.txt) */ + visual->earliest_time = timestamp + 2 * diff + visual->duration; + else + visual->earliest_time = timestamp + diff; + + GST_OBJECT_UNLOCK (visual); + + res = gst_pad_push_event (visual->sinkpad, event); + break; + } + default: + res = gst_pad_push_event (visual->sinkpad, event); + break; + } + + gst_object_unref (visual); + return res; +} + +static gboolean +gst_visual_src_query (GstPad * pad, GstQuery * query) +{ + gboolean res; + GstVisual *visual; + + visual = GST_VISUAL (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + /* We need to send the query upstream and add the returned latency to our + * own */ + GstClockTime min_latency, max_latency; + gboolean us_live; + GstClockTime our_latency; + guint max_samples; + + if ((res = gst_pad_peer_query (visual->sinkpad, query))) { + gst_query_parse_latency (query, &us_live, &min_latency, &max_latency); + + GST_DEBUG_OBJECT (visual, "Peer latency: min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); + + /* the max samples we must buffer buffer */ + max_samples = MAX (VISUAL_SAMPLES, visual->spf); + our_latency = + gst_util_uint64_scale_int (max_samples, GST_SECOND, visual->rate); + + GST_DEBUG_OBJECT (visual, "Our latency: %" GST_TIME_FORMAT, + GST_TIME_ARGS (our_latency)); + + /* we add some latency but only if we need to buffer more than what + * upstream gives us */ + min_latency += our_latency; + if (max_latency != -1) + max_latency += our_latency; + + GST_DEBUG_OBJECT (visual, "Calculated total latency : min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); + + gst_query_set_latency (query, TRUE, min_latency, max_latency); + } + break; + } + default: + res = gst_pad_peer_query (visual->sinkpad, query); + break; + } + + gst_object_unref (visual); + + return res; +} + +/* allocate and output buffer, if no format was negotiated, this + * function will negotiate one. After calling this function, a + * reverse negotiation could have happened. */ +static GstFlowReturn +get_buffer (GstVisual * visual, GstBuffer ** outbuf) +{ + GstFlowReturn ret; + + /* we don't know an output format yet, pick one */ + if (GST_PAD_CAPS (visual->srcpad) == NULL) { + if (!gst_vis_src_negotiate (visual)) + return GST_FLOW_NOT_NEGOTIATED; + } + + GST_DEBUG_OBJECT (visual, "allocating output buffer with caps %" + GST_PTR_FORMAT, GST_PAD_CAPS (visual->srcpad)); + + /* now allocate a buffer with the last negotiated format. + * Downstream could renegotiate a new format, which will trigger + * our setcaps function on the source pad. */ + ret = + gst_pad_alloc_buffer_and_set_caps (visual->srcpad, + GST_BUFFER_OFFSET_NONE, visual->outsize, + GST_PAD_CAPS (visual->srcpad), outbuf); + + /* no buffer allocated, we don't care why. */ + if (ret != GST_FLOW_OK) + return ret; + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_visual_chain (GstPad * pad, GstBuffer * buffer) +{ + GstBuffer *outbuf = NULL; + guint i; + GstVisual *visual = GST_VISUAL (gst_pad_get_parent (pad)); + GstFlowReturn ret = GST_FLOW_OK; + guint avail; + + GST_DEBUG_OBJECT (visual, "chain function called"); + + /* If we don't have an output format yet, preallocate a buffer to try and + * set one */ + if (GST_PAD_CAPS (visual->srcpad) == NULL) { + ret = get_buffer (visual, &outbuf); + if (ret != GST_FLOW_OK) { + gst_buffer_unref (buffer); + goto beach; + } + } + + /* resync on DISCONT */ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { + gst_adapter_clear (visual->adapter); + } + + GST_DEBUG_OBJECT (visual, + "Input buffer has %d samples, time=%" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (buffer) / visual->bps, GST_BUFFER_TIMESTAMP (buffer)); + + gst_adapter_push (visual->adapter, buffer); + + while (TRUE) { + gboolean need_skip; + const guint16 *data; + guint64 dist, timestamp; + + GST_DEBUG_OBJECT (visual, "processing buffer"); + + avail = gst_adapter_available (visual->adapter); + GST_DEBUG_OBJECT (visual, "avail now %u", avail); + + /* we need at least VISUAL_SAMPLES samples */ + if (avail < VISUAL_SAMPLES * visual->bps) + break; + + /* we need at least enough samples to make one frame */ + if (avail < visual->spf * visual->bps) + break; + + /* get timestamp of the current adapter byte */ + timestamp = gst_adapter_prev_timestamp (visual->adapter, &dist); + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* convert bytes to time */ + dist /= visual->bps; + timestamp += gst_util_uint64_scale_int (dist, GST_SECOND, visual->rate); + } + + if (timestamp != -1) { + gint64 qostime; + + /* QoS is done on running time */ + qostime = gst_segment_to_running_time (&visual->segment, GST_FORMAT_TIME, + timestamp); + qostime += visual->duration; + + GST_OBJECT_LOCK (visual); + /* check for QoS, don't compute buffers that are known to be late */ + need_skip = visual->earliest_time != -1 && + qostime <= visual->earliest_time; + GST_OBJECT_UNLOCK (visual); + + if (need_skip) { + GST_WARNING_OBJECT (visual, + "QoS: skip ts: %" GST_TIME_FORMAT ", earliest: %" GST_TIME_FORMAT, + GST_TIME_ARGS (qostime), GST_TIME_ARGS (visual->earliest_time)); + goto skip; + } + } + + /* Read VISUAL_SAMPLES samples per channel */ + data = + (const guint16 *) gst_adapter_peek (visual->adapter, + VISUAL_SAMPLES * visual->bps); + +#if defined(VISUAL_API_VERSION) && VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000 + { + VisBuffer *lbuf, *rbuf; + guint16 ldata[VISUAL_SAMPLES], rdata[VISUAL_SAMPLES]; + VisAudioSampleRateType rate; + + lbuf = visual_buffer_new_with_buffer (ldata, sizeof (ldata), NULL); + rbuf = visual_buffer_new_with_buffer (rdata, sizeof (rdata), NULL); + + if (visual->channels == 2) { + for (i = 0; i < VISUAL_SAMPLES; i++) { + ldata[i] = *data++; + rdata[i] = *data++; + } + } else { + for (i = 0; i < VISUAL_SAMPLES; i++) { + ldata[i] = *data; + rdata[i] = *data++; + } + } + + switch (visual->rate) { + case 8000: + rate = VISUAL_AUDIO_SAMPLE_RATE_8000; + break; + case 11250: + rate = VISUAL_AUDIO_SAMPLE_RATE_11250; + break; + case 22500: + rate = VISUAL_AUDIO_SAMPLE_RATE_22500; + break; + case 32000: + rate = VISUAL_AUDIO_SAMPLE_RATE_32000; + break; + case 44100: + rate = VISUAL_AUDIO_SAMPLE_RATE_44100; + break; + case 48000: + rate = VISUAL_AUDIO_SAMPLE_RATE_48000; + break; + case 96000: + rate = VISUAL_AUDIO_SAMPLE_RATE_96000; + break; + default: + visual_object_unref (VISUAL_OBJECT (lbuf)); + visual_object_unref (VISUAL_OBJECT (rbuf)); + GST_ERROR_OBJECT (visual, "unsupported rate %d", visual->rate); + ret = GST_FLOW_ERROR; + goto beach; + break; + } + + visual_audio_samplepool_input_channel (visual->audio->samplepool, + lbuf, + rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, + (char *) VISUAL_AUDIO_CHANNEL_LEFT); + visual_audio_samplepool_input_channel (visual->audio->samplepool, rbuf, + rate, VISUAL_AUDIO_SAMPLE_FORMAT_S16, + (char *) VISUAL_AUDIO_CHANNEL_RIGHT); + + visual_object_unref (VISUAL_OBJECT (lbuf)); + visual_object_unref (VISUAL_OBJECT (rbuf)); + + } +#else + if (visual->channels == 2) { + for (i = 0; i < VISUAL_SAMPLES; i++) { + visual->audio->plugpcm[0][i] = *data++; + visual->audio->plugpcm[1][i] = *data++; + } + } else { + for (i = 0; i < VISUAL_SAMPLES; i++) { + visual->audio->plugpcm[0][i] = *data; + visual->audio->plugpcm[1][i] = *data++; + } + } +#endif + + /* alloc a buffer if we don't have one yet, this happens + * when we pushed a buffer in this while loop before */ + if (outbuf == NULL) { + ret = get_buffer (visual, &outbuf); + if (ret != GST_FLOW_OK) { + goto beach; + } + } + visual_video_set_buffer (visual->video, GST_BUFFER_DATA (outbuf)); + visual_audio_analyze (visual->audio); + visual_actor_run (visual->actor, visual->audio); + visual_video_set_buffer (visual->video, NULL); + GST_DEBUG_OBJECT (visual, "rendered one frame"); + + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + GST_BUFFER_DURATION (outbuf) = visual->duration; + + ret = gst_pad_push (visual->srcpad, outbuf); + outbuf = NULL; + + skip: + GST_DEBUG_OBJECT (visual, "finished frame, flushing %u samples from input", + visual->spf); + + /* Flush out the number of samples per frame */ + gst_adapter_flush (visual->adapter, visual->spf * visual->bps); + + /* quit the loop if something was wrong */ + if (ret != GST_FLOW_OK) + break; + } + +beach: + + if (outbuf != NULL) + gst_buffer_unref (outbuf); + + gst_object_unref (visual); + + return ret; +} + +static GstStateChangeReturn +gst_visual_change_state (GstElement * element, GstStateChange transition) +{ + GstVisual *visual = GST_VISUAL (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + visual->actor = + visual_actor_new (GST_VISUAL_GET_CLASS (visual)->plugin->info-> + plugname); + visual->video = visual_video_new (); + visual->audio = visual_audio_new (); + /* can't have a play without actors */ + if (!visual->actor || !visual->video) + goto no_actors; + + if (visual_actor_realize (visual->actor) != 0) + goto no_realize; + + visual_actor_set_video (visual->actor, visual->video); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_visual_reset (visual); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_visual_clear_actors (visual); + break; + default: + break; + } + + return ret; + + /* ERRORS */ +no_actors: + { + GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL), + ("could not create actors")); + gst_visual_clear_actors (visual); + return GST_STATE_CHANGE_FAILURE; + } +no_realize: + { + GST_ELEMENT_ERROR (visual, LIBRARY, INIT, (NULL), + ("could not realize actor")); + gst_visual_clear_actors (visual); + return GST_STATE_CHANGE_FAILURE; + } +} + +static void +make_valid_name (char *name) +{ + /* + * Replace invalid chars with _ in the type name + */ + static const gchar extra_chars[] = "-_+"; + gchar *p = name; + + for (; *p; p++) { + int valid = ((p[0] >= 'A' && p[0] <= 'Z') || + (p[0] >= 'a' && p[0] <= 'z') || + (p[0] >= '0' && p[0] <= '9') || strchr (extra_chars, p[0])); + if (!valid) + *p = '_'; + } +} + +static gboolean +gst_visual_actor_plugin_is_gl (VisObject * plugin, const gchar * name) +{ + gboolean is_gl; + gint depth; + +#if !defined(VISUAL_API_VERSION) + + depth = VISUAL_PLUGIN_ACTOR (plugin)->depth; + is_gl = (depth == VISUAL_VIDEO_DEPTH_GL); + +#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000 + + depth = VISUAL_ACTOR_PLUGIN (plugin)->vidoptions.depth; + /* FIXME: how to figure this out correctly in 0.4? */ + is_gl = (depth & VISUAL_VIDEO_DEPTH_GL) == VISUAL_VIDEO_DEPTH_GL; + +#else +# error what libvisual version is this? +#endif + + if (!is_gl) { + GST_DEBUG ("plugin %s is not a GL plugin (%d), registering", name, depth); + } else { + GST_DEBUG ("plugin %s is a GL plugin (%d), ignoring", name, depth); + } + + return is_gl; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + guint i, count; + VisList *list; + + GST_DEBUG_CATEGORY_INIT (libvisual_debug, "libvisual", 0, + "libvisual audio visualisations"); + +#ifdef LIBVISUAL_PLUGINSBASEDIR + gst_plugin_add_dependency_simple (plugin, "HOME/.libvisual/actor", + LIBVISUAL_PLUGINSBASEDIR "/actor", NULL, GST_PLUGIN_DEPENDENCY_FLAG_NONE); +#endif + + visual_log_set_verboseness (VISUAL_LOG_VERBOSENESS_LOW); + visual_log_set_info_handler (libvisual_log_handler, (void *) GST_LEVEL_INFO); + visual_log_set_warning_handler (libvisual_log_handler, + (void *) GST_LEVEL_WARNING); + visual_log_set_critical_handler (libvisual_log_handler, + (void *) GST_LEVEL_ERROR); + visual_log_set_error_handler (libvisual_log_handler, + (void *) GST_LEVEL_ERROR); + + if (!visual_is_initialized ()) + if (visual_init (NULL, NULL) != 0) + return FALSE; + + list = visual_actor_get_list (); + +#if !defined(VISUAL_API_VERSION) + count = visual_list_count (list); +#elif VISUAL_API_VERSION >= 4000 && VISUAL_API_VERSION < 5000 + count = visual_collection_size (VISUAL_COLLECTION (list)); +#endif + + for (i = 0; i < count; i++) { + VisPluginRef *ref = visual_list_get (list, i); + VisPluginData *visplugin = NULL; + gboolean skip = FALSE; + GType type; + gchar *name; + GTypeInfo info = { + sizeof (GstVisualClass), + NULL, + NULL, + gst_visual_class_init, + NULL, + ref, + sizeof (GstVisual), + 0, + NULL + }; + + visplugin = visual_plugin_load (ref); + + if (ref->info->plugname == NULL) + continue; + + /* Blacklist some plugins */ + if (strcmp (ref->info->plugname, "gstreamer") == 0 || + strcmp (ref->info->plugname, "gdkpixbuf") == 0) { + skip = TRUE; + } else { + /* Ignore plugins that only support GL output for now */ + skip = gst_visual_actor_plugin_is_gl (visplugin->info->plugin, + visplugin->info->plugname); + } + + visual_plugin_unload (visplugin); + + if (!skip) { + name = g_strdup_printf ("GstVisual%s", ref->info->plugname); + make_valid_name (name); + type = g_type_register_static (GST_TYPE_VISUAL, name, &info, 0); + g_free (name); + + name = g_strdup_printf ("libvisual_%s", ref->info->plugname); + make_valid_name (name); + if (!gst_element_register (plugin, name, GST_RANK_NONE, type)) { + g_free (name); + return FALSE; + } + g_free (name); + } + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "libvisual", + "libvisual visualization plugins", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/Makefile.am b/gst-plugins-base-subtitles0.10/ext/ogg/Makefile.am new file mode 100644 index 0000000..3d23821 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/Makefile.am @@ -0,0 +1,45 @@ +plugin_LTLIBRARIES = libgstogg.la + +libgstogg_la_SOURCES = \ + gstogg.c \ + gstoggdemux.c \ + gstoggmux.c \ + gstogmparse.c \ + gstoggaviparse.c \ + gstoggparse.c \ + gstoggstream.c \ + dirac_parse.c \ + vorbis_parse.c + +noinst_HEADERS = \ + gstogg.h \ + gstoggdemux.h \ + gstoggmux.h \ + gstoggstream.h \ + dirac_parse.h \ + vorbis_parse.h + +libgstogg_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(OGG_CFLAGS) +libgstogg_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/riff/libgstriff-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(OGG_LIBS) +libgstogg_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstogg_la_LIBTOOLFLAGS = --tag=disable-static + + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstogg -:SHARED libgstogg \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstogg_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstogg_la_CFLAGS) \ + -:LDFLAGS $(libgstogg_la_LDFLAGS) \ + $(libgstogg_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/README b/gst-plugins-base-subtitles0.10/ext/ogg/README new file mode 100644 index 0000000..557e9d5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/README @@ -0,0 +1,366 @@ +This document describes some things to know about the Ogg format, as well +as implementation details in GStreamer. + +INTRODUCTION +============ + +ogg and the granulepos +---------------------- + +An ogg stream contains pages with a serial number and a granulepos. +The granulepos is a 64 bit signed integer. It is a value that in some way +represents a time since the start of the stream. +The interpretation as such is however both codec-specific and +stream-specific. + +ogg has no notion of time: it only knows about bytes and granulepos values +on pages. + +The granule position is just a number; the only guarantee for a valid ogg +stream is that within a logical stream, this number never decreases. + +While logically a granulepos value can be constructed for every ogg packet, +the page is marked with only one granulepos value: the granulepos of the +last packet to end on that page. + +theora and the granulepos +------------------------- + +The granulepos in theora is an encoding of the frame number of the last +key frame ("i frame"), and the number of frames since the last key frame +("p frame"). The granulepos is constructed as the sum of the first number, +shifted to the left for granuleshift bits, and the second number: +granulepos = pframe << granuleshift + iframe + +(This means that given a framenumber or a timestamp, one cannot generate + the one and only granulepos for that page; several granulepos possibilities + correspond to this frame number. You also need the last keyframe, as well + as the granuleshift. + However, given a granulepos, the theora codec can still map that to a + unique timestamp and frame number for that theora stream) + + Note: currently theora stores the "presentation time" as the granulepos; + ie. a first data page with one packet contains one video frame and + will be marked with 0/0. Changing that to be 1/0 (so that it + represents the number of decodable frames up to that point, like + for Vorbis) is being discussed. + +vorbis and granulepos +--------------------- + +In Vorbis, the granulepos represents the number of samples that can be +decoded from all packets up to that point. + +In GStreamer, the vorbisenc elements produces a stream where: +- OFFSET is the time corresponding to the granulepos + number of bytes produced before +- OFFSET_END is the granulepos of the produced vorbis buffer +- TIMESTAMP is the timestamp matching the begin of the buffer +- DURATION is set to the length in time of the buffer + +Ogg media mapping +----------------- + +Ogg defines a mapping for each media type that it embeds. + +For Vorbis: + + - 3 header pages, with granulepos 0. + - 1 page with 1 packet header identification + - N pages with 2 packets comments and codebooks + - granulepos is samplenumber of next page + - one packet can contain a variable number of samples but one frame + that should be handed to the vorbis decoder. + +For Theora + + - 3 header pages, with granulepos 0. + - 1 page with 1 packet header identification + - N pages with 2 packets comments and codebooks + - granulepos is framenumber of last packet in page, where framenumber + is a combination of keyframe number and p frames since keyframe. + - one packet contains 1 frame + + + + +DEMUXING +======== + +ogg demuxer +----------- + +This ogg demuxer has two modes of operation, which both share a significant +amount of code. The first mode is the streaming mode which is automatically +selected when the demuxer is connected to a non-getrange based element. When +connected to a getrange based element the ogg demuxer can do full seeking +with great efficiency. + +1) the streaming mode. + +In this mode, the ogg demuxer receives buffers in the _chain() function which +are then simply submited to the ogg sync layer. Pages are then processed when +the sync layer detects them, pads are created for new chains and packets are +sent to the peer elements of the pads. + +In this mode, no seeking is possible. This is the typical case when the +stream is read from a network source. + +In this mode, no setup is done at startup, the pages are just read and decoded. +A new logical chain is detected when one of the pages has the BOS flag set. At +this point the existing pads are removed and new pads are created for all the +logical streams in this new chain. + + +2) the random access mode. + + In this mode, the ogg file is first scanned to detect the position and length +of all chains. This scanning is performed using a recursive binary search +algorithm that is explained below. + + find_chains(start, end) + { + ret1 = read_next_pages (start); + ret2 = read_prev_page (end); + + if (WAS_HEADER (ret1)) { + } + else { + } + + } + + a) read first and last pages + + start end + V V + +-----------------------+-------------+--------------------+ + | 111 | 222 | 333 | + BOS BOS BOS EOS + + + after reading start, serial 111, BOS, chain[0] = 111 + after reading end, serial 333, EOS + + start serialno != end serialno, binary search start, (end-start)/2 + + start bisect end + V V V + +-----------------------+-------------+--------------------+ + | 111 | 222 | 333 | + + + after reading start, serial 111, BOS, chain[0] = 111 + after reading end, serial 222, EOS + + while ( + + + +testcases +--------- + + a) stream without BOS + + +----------------------------------------------------------+ + 111 | + EOS + + b) chained stream, first chain without BOS + + +-------------------+--------------------------------------+ + 111 | 222 | + BOS EOS + + + c) chained stream + + +-------------------+--------------------------------------+ + | 111 | 222 | + BOS BOS EOS + + + d) chained stream, second without BOS + + +-------------------+--------------------------------------+ + | 111 | 222 | + BOS EOS + +What can an ogg demuxer do? +--------------------------- + +An ogg demuxer can read pages and get the granulepos from them. +It can ask the decoder elements to convert a granulepos to time. + +An ogg demuxer can also get the granulepos of the first and the last page of a +stream to get the start and end timestamp of that stream. +It can also get the length in bytes of the stream +(when the peer is seekable, that is). + +An ogg demuxer is therefore basically able to seek to any byte position and +timestamp. + +When asked to seek to a given granulepos, the ogg demuxer should always convert +the value to a timestamp using the peer decoder element conversion function. It +can then binary search the file to eventually end up on the page with the given +granule pos or a granulepos with the same timestamp. + +Seeking in ogg currently +------------------------ + +When seeking in an ogg, the decoders can choose to forward the seek event as a +granulepos or a timestamp to the ogg demuxer. + +In the case of a granulepos, the ogg demuxer will seek back to the beginning of +the stream and skip pages until it finds one with the requested timestamp. + +In the case of a timestamp, the ogg demuxer also seeks back to the beginning of +the stream. For each page it reads, it asks the decoder element to convert the +granulepos back to a timestamp. The ogg demuxer keeps on skipping pages until +the page has a timestamp bigger or equal to the requested one. + +It is therefore important that the decoder elements in vorbis can convert a +granulepos into a timestamp or never seek on timestamp on the oggdemuxer. + +The default format on the oggdemuxer source pads is currently defined as a the +granulepos of the packets, it is also the value of the OFFSET field in the +GstBuffer. + +MUXING +====== + +Oggmux +------ + +The ogg muxer's job is to output complete Ogg pages such that the absolute +time represented by the valid (ie, not -1) granulepos values on those pages +never decreases. This has to be true for all logical streams in the group at +the same time. + +To achieve this, encoders are required to pass along the exact time that the +granulepos represents for each ogg packet that it pushes to the ogg muxer. +This is ESSENTIAL: without this exact time representation of the granulepos, +the muxer can not produce valid streams. + +The ogg muxer has a packet queue per sink pad. From this queue a page can +be flushed when: + - total byte size of queued packets exceeds a given value + - total time duration of queued packets exceeds a given value + - total byte size of queued packets exceeds maximum Ogg page size + - eos of the pad + - encoder sent a command to flush out an ogg page after this new packet + (in 0.8, through a flush event; in 0.10, with a GstOggBuffer) + - muxer wants a flush to happen (so it can output pages) + +The ogg muxer also has a page queue per sink pad. This queue collects +Ogg pages from the corresponding packet queue. Each page is also marked +with the timestamp that the granulepos in the header represents. + +A page can be flushed from this collection of page queues when: +- ideally, every page queue has at least one page with a valid granulepos + -> choose the page, from all queues, with the lowest timestamp value +- if not, muxer can wait if the following limits aren't reached: + - total byte size of any page queue exceeds a limit + - total time duration of any page queue exceeds a limit +- if this limit is reached, then: + - request a page flush from packet queue to page queue for each queue + that does not have pages + - now take the page from all queues with the lowest timestamp value + - make sure all later-coming data is marked as old, either to be still + output (but producing an invalid stream, though it can be fixed later) + or dropped (which means it's gone forever) + +The oggmuxer uses the offset fields to fill in the granulepos in the pages. + +GStreamer implementation details +-------------------------------- +As said before, the basic rule is that the ogg muxer needs an exact time +representation for each granulepos. This needs to be provided by the encoder. + +Potential problems are: + - initial offsets for a raw stream need to be preserved somehow. Example: + if the first audio sample has time 0.5, the granulepos in the vorbis encoder + needs to be adjusted to take this into account. + - initial offsets may need be on rate boundaries. Example: + if the framerate is 5 fps, and the first video frame has time 0.1 s, the + granulepos cannot correctly represent this timestamp. + This can be handled out-of-band (initial offset in another muxing format, + skeleton track with initial offsets, ...) + +Given that the basic rule for muxing is that the muxer needs an exact timestamp +matching the granulepos, we need some way of communicating this time value +from encoders to the Ogg muxer. So we need a mechanism to communicate +a granulepos and its time representation for each GstBuffer. + +(This is an instance of a more generic problem - having a way to attach + more fields to a GstBuffer) + +Possible ways: +- setting TIMESTAMP to this value: bad - this value represents the end time + of the buffer, and thus conflicts with GStreamer's idea of what TIMESTAMP + is. This would cause problems muxing the encoded stream in other muxing + formats, or for streaming. Note that this is what was done in GStreamer 0.8 +- setting DURATION to GP_TIME - TIMESTAMP: bad - this breaks the concept of + duration for this frame. Take the video example above; each buffer would + have a correct timestamp, but always a 0.1 s duration as opposed to the + correct 0.2 s duration +- subclassing GstBuffer: clean, but requires a common header used between + ogg muxer and all encoders that can be muxed into ogg. Also, what if + a format can be muxed into more than one container, and they each have + their own "extra" info to communicate ? +- adding key/value pairs to GstBuffer: clean, but requires changes to + core. Also, the overhead of allocating e.g. a GstStructure for *each* buffer + may be expensive. +- "cheating": + - abuse OFFSET to store the timestamp matching this granulepos + - abuse OFFSET_END to store the granulepos value + The drawback here is that before, it made sense to use OFFSET and OFFSET_END + to store a byte count. Given that this is not used for anything critical + (you can't store a raw theora or vorbis stream in a file anyway), + this is what's being done for now. + +In practice +----------- +- all encoders of formats that can be muxed into Ogg produce a stream where: + - OFFSET is abused to be the timestamp corresponding exactly to the + granulepos + - OFFSET_END is abused to be the granulepos of the encoded theora buffer + - TIMESTAMP is the timestamp matching the begin of the buffer + - DURATION is the length in time of the buffer + +- initial delays should be handled in the GStreamer encoders by mangling + the granulepos of the encoded packet to take the delay into account as + best as possible and store that in OFFSET; + this then brings TIMESTAMP + DURATION to within less + than a frame period of the granulepos's time representation + The ogg muxer will then create new ogg packets with this OFFSET as + the granulepos. So in effect, the granulepos produced by the encoders + does not get used directly. + +TODO +---- +- decide on a proper mechanism for communicating extra per-buffer fields +- the ogg muxer sets timestamp and duration on outgoing ogg pages based on + timestamp/duration of incoming ogg packets. + Note that: + - since the ogg muxer *has* to output pages sorted by gp time, representing + end time of the page, this means that the buffer's timestamps are not + necessarily monotonically increasing + - timestamp + duration of buffers don't match up; the duration represents + the length of the ogg page *for that stream*. Hence, for a normal + two-stream file, the sum of all durations is twice the length of the + muxed file. + +TESTING +------- +Proper muxing can be tested by generating test files with command lines like: +- video and audio start from 0: +gst-launch -v videotestsrc ! theoraenc ! oggmux audiotestsrc ! audioconvert ! vorbisenc ! identity ! oggmux0. oggmux0. ! filesink location=test.ogg + +- video starts after audio: +gst-launch -v videotestsrc timestamp-offset=500000000 ! theoraenc ! oggmux audiotestsrc ! audioconvert ! vorbisenc ! identity ! oggmux0. oggmux0. ! filesink location=test.ogg + +- audio starts after video: +gst-launch -v videotestsrc ! theoraenc ! oggmux audiotestsrc timestamp-offset=500000000 ! audioconvert ! vorbisenc ! identity ! oggmux0. oggmux0. ! filesink location=test.ogg + +The resulting files can be verified with oggz-validate for correctness. diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.c b/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.c new file mode 100644 index 0000000..3a3193d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.c @@ -0,0 +1,498 @@ + +#include "dirac_parse.h" +#include + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +typedef struct _Unpack Unpack; + +struct _Unpack +{ + unsigned char *data; + int n_bits_left; + int index; + int guard_bit; +}; + +static void schro_unpack_init_with_data (Unpack * unpack, unsigned char *data, + int n_bytes, unsigned int guard_bit); + +static unsigned int schro_unpack_decode_bit (Unpack * unpack); +static unsigned int schro_unpack_decode_uint (Unpack * unpack); + + +void schro_video_format_set_std_video_format (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_frame_rate (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_aspect_ratio (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_signal_range (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_colour_spec (DiracSequenceHeader * format, + int index); + + + + +int +dirac_sequence_header_parse (DiracSequenceHeader * header, + unsigned char *data, int n_bytes) +{ + int bit; + int index; + Unpack _unpack; + Unpack *unpack = &_unpack; + int major_version; + int minor_version; + int profile; + int level; + + memset (header, 0, sizeof (*header)); + + schro_unpack_init_with_data (unpack, data, n_bytes, 1); + + /* parse parameters */ + major_version = schro_unpack_decode_uint (unpack); + minor_version = schro_unpack_decode_uint (unpack); + profile = schro_unpack_decode_uint (unpack); + level = schro_unpack_decode_uint (unpack); + + /* base video header */ + index = schro_unpack_decode_uint (unpack); + schro_video_format_set_std_video_format (header, index); + + header->major_version = major_version; + header->minor_version = minor_version; + header->profile = profile; + header->level = level; + + /* source parameters */ + /* frame dimensions */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->width = schro_unpack_decode_uint (unpack); + header->height = schro_unpack_decode_uint (unpack); + } + + /* chroma header */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->chroma_format = schro_unpack_decode_uint (unpack); + } + + /* scan header */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->interlaced = schro_unpack_decode_uint (unpack); + } + + /* frame rate */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->frame_rate_numerator = schro_unpack_decode_uint (unpack); + header->frame_rate_denominator = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_frame_rate (header, index); + } + } + + /* aspect ratio */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->aspect_ratio_numerator = schro_unpack_decode_uint (unpack); + header->aspect_ratio_denominator = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_aspect_ratio (header, index); + } + } + + /* clean area */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->clean_width = schro_unpack_decode_uint (unpack); + header->clean_height = schro_unpack_decode_uint (unpack); + header->left_offset = schro_unpack_decode_uint (unpack); + header->top_offset = schro_unpack_decode_uint (unpack); + } + + /* signal range */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->luma_offset = schro_unpack_decode_uint (unpack); + header->luma_excursion = schro_unpack_decode_uint (unpack); + header->chroma_offset = schro_unpack_decode_uint (unpack); + header->chroma_excursion = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_signal_range (header, index); + } + } + + /* colour spec */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + schro_video_format_set_std_colour_spec (header, index); + if (index == 0) { + /* colour primaries */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->colour_primaries = schro_unpack_decode_uint (unpack); + } + /* colour matrix */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->colour_matrix = schro_unpack_decode_uint (unpack); + } + /* transfer function */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->transfer_function = schro_unpack_decode_uint (unpack); + } + } + } + + header->interlaced_coding = schro_unpack_decode_uint (unpack); + + return 1; +} + +/* standard stuff */ + +static DiracSequenceHeader schro_video_formats[] = { + {0, 0, 0, 0, + 0, /* custom */ + 640, 480, SCHRO_CHROMA_420, + FALSE, FALSE, + 24000, 1001, 1, 1, + 640, 480, 0, 0, + 0, 255, 128, 255, + 0, 0, 0}, + {0, 0, 0, 0, + 1, /* QSIF525 */ + 176, 120, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 176, 120, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 2, /* QCIF */ + 176, 144, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 176, 144, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 3, /* SIF525 */ + 352, 240, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 352, 240, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 4, /* CIF */ + 352, 288, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 352, 288, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 5, /* 4SIF525 */ + 704, 480, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 704, 480, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 6, /* 4CIF */ + 704, 576, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 704, 576, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 7, /* SD480I-60 */ + 720, 480, SCHRO_CHROMA_422, + TRUE, FALSE, + 30000, 1001, 10, 11, + 704, 480, 8, 0, + 64, 876, 512, 896, + 1, 1, 0}, + {0, 0, 0, 0, + 8, /* SD576I-50 */ + 720, 576, SCHRO_CHROMA_422, + TRUE, TRUE, + 25, 1, 12, 11, + 704, 576, 8, 0, + 64, 876, 512, 896, + 2, 1, 0}, + {0, 0, 0, 0, + 9, /* HD720P-60 */ + 1280, 720, SCHRO_CHROMA_422, + FALSE, TRUE, + 60000, 1001, 1, 1, + 1280, 720, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 10, /* HD720P-50 */ + 1280, 720, SCHRO_CHROMA_422, + FALSE, TRUE, + 50, 1, 1, 1, + 1280, 720, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 11, /* HD1080I-60 */ + 1920, 1080, SCHRO_CHROMA_422, + TRUE, TRUE, + 30000, 1001, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 12, /* HD1080I-50 */ + 1920, 1080, SCHRO_CHROMA_422, + TRUE, TRUE, + 25, 1, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 13, /* HD1080P-60 */ + 1920, 1080, SCHRO_CHROMA_422, + FALSE, TRUE, + 60000, 1001, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 14, /* HD1080P-50 */ + 1920, 1080, SCHRO_CHROMA_422, + FALSE, TRUE, + 50, 1, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 15, /* DC2K */ + 2048, 1080, SCHRO_CHROMA_444, + FALSE, TRUE, + 24, 1, 1, 1, + 2048, 1080, 0, 0, + 256, 3504, 2048, 3584, + 3, 0, 0}, + {0, 0, 0, 0, + 16, /* DC4K */ + 4096, 2160, SCHRO_CHROMA_444, + FALSE, TRUE, + 24, 1, 1, 1, + 2048, 1536, 0, 0, + 256, 3504, 2048, 3584, + 3, 0, 0}, +}; + +void +schro_video_format_set_std_video_format (DiracSequenceHeader * format, + int index) +{ + + if (index < 0 || index >= ARRAY_SIZE (schro_video_formats)) { + return; + } + + memcpy (format, schro_video_formats + index, sizeof (DiracSequenceHeader)); +} + +typedef struct _SchroFrameRate SchroFrameRate; +struct _SchroFrameRate +{ + int numerator; + int denominator; +}; + +static SchroFrameRate schro_frame_rates[] = { + {0, 0}, + {24000, 1001}, + {24, 1}, + {25, 1}, + {30000, 1001}, + {30, 1}, + {50, 1}, + {60000, 1001}, + {60, 1}, + {15000, 1001}, + {25, 2} +}; + +void +schro_video_format_set_std_frame_rate (DiracSequenceHeader * format, int index) +{ + if (index < 1 || index >= ARRAY_SIZE (schro_frame_rates)) { + return; + } + + format->frame_rate_numerator = schro_frame_rates[index].numerator; + format->frame_rate_denominator = schro_frame_rates[index].denominator; +} + +typedef struct _SchroPixelAspectRatio SchroPixelAspectRatio; +struct _SchroPixelAspectRatio +{ + int numerator; + int denominator; +}; + +static const SchroPixelAspectRatio schro_aspect_ratios[] = { + {0, 0}, + {1, 1}, + {10, 11}, + {12, 11}, + {40, 33}, + {16, 11}, + {4, 3} +}; + +void +schro_video_format_set_std_aspect_ratio (DiracSequenceHeader * format, + int index) +{ + if (index < 1 || index >= ARRAY_SIZE (schro_aspect_ratios)) { + return; + } + + format->aspect_ratio_numerator = schro_aspect_ratios[index].numerator; + format->aspect_ratio_denominator = schro_aspect_ratios[index].denominator; + +} + +typedef struct _SchroSignalRangeStruct SchroSignalRangeStruct; +struct _SchroSignalRangeStruct +{ + int luma_offset; + int luma_excursion; + int chroma_offset; + int chroma_excursion; +}; + +static const SchroSignalRangeStruct schro_signal_ranges[] = { + {0, 0, 0, 0}, + {0, 255, 128, 255}, + {16, 219, 128, 224}, + {64, 876, 512, 896}, + {256, 3504, 2048, 3584} +}; + +void +schro_video_format_set_std_signal_range (DiracSequenceHeader * format, int i) +{ + if (i < 1 || i >= ARRAY_SIZE (schro_signal_ranges)) { + return; + } + + format->luma_offset = schro_signal_ranges[i].luma_offset; + format->luma_excursion = schro_signal_ranges[i].luma_excursion; + format->chroma_offset = schro_signal_ranges[i].chroma_offset; + format->chroma_excursion = schro_signal_ranges[i].chroma_excursion; +} + +typedef struct _SchroColourSpecStruct SchroColourSpecStruct; +struct _SchroColourSpecStruct +{ + int colour_primaries; + int colour_matrix; + int transfer_function; +}; + +static const SchroColourSpecStruct schro_colour_specs[] = { + { /* Custom */ + SCHRO_COLOUR_PRIMARY_HDTV, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* SDTV 525 */ + SCHRO_COLOUR_PRIMARY_SDTV_525, + SCHRO_COLOUR_MATRIX_SDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* SDTV 625 */ + SCHRO_COLOUR_PRIMARY_SDTV_625, + SCHRO_COLOUR_MATRIX_SDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* HDTV */ + SCHRO_COLOUR_PRIMARY_HDTV, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* Cinema */ + SCHRO_COLOUR_PRIMARY_CINEMA, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA} +}; + +void +schro_video_format_set_std_colour_spec (DiracSequenceHeader * format, int i) +{ + if (i < 0 || i >= ARRAY_SIZE (schro_colour_specs)) { + return; + } + + format->colour_primaries = schro_colour_specs[i].colour_primaries; + format->colour_matrix = schro_colour_specs[i].colour_matrix; + format->transfer_function = schro_colour_specs[i].transfer_function; +} + + +/* unpack */ + +static void +schro_unpack_init_with_data (Unpack * unpack, unsigned char *data, + int n_bytes, unsigned int guard_bit) +{ + memset (unpack, 0, sizeof (Unpack)); + + unpack->data = data; + unpack->n_bits_left = 8 * n_bytes; + unpack->guard_bit = guard_bit; +} + +static unsigned int +schro_unpack_decode_bit (Unpack * unpack) +{ + int bit; + + if (unpack->n_bits_left < 1) { + return unpack->guard_bit; + } + bit = (unpack->data[unpack->index >> 3] >> (7 - (unpack->index & 7))) & 1; + unpack->index++; + unpack->n_bits_left--; + + return bit; +} + +static unsigned int +schro_unpack_decode_uint (Unpack * unpack) +{ + int count; + int value; + + count = 0; + value = 0; + while (!schro_unpack_decode_bit (unpack)) { + count++; + value <<= 1; + value |= schro_unpack_decode_bit (unpack); + } + + return (1 << count) - 1 + value; +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.h b/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.h new file mode 100644 index 0000000..9dc4ffe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/dirac_parse.h @@ -0,0 +1,178 @@ + +#ifndef __DIRAC_PARSE_H__ +#define __DIRAC_PARSE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +typedef enum _SchroParseCode { + SCHRO_PARSE_CODE_SEQUENCE_HEADER = 0x00, + SCHRO_PARSE_CODE_END_OF_SEQUENCE = 0x10, + SCHRO_PARSE_CODE_AUXILIARY_DATA = 0x20, + SCHRO_PARSE_CODE_PADDING = 0x30, + + SCHRO_PARSE_CODE_INTRA_REF = 0x0c, + SCHRO_PARSE_CODE_INTRA_NON_REF = 0x08, + SCHRO_PARSE_CODE_INTRA_REF_NOARITH = 0x4c, + SCHRO_PARSE_CODE_INTRA_NON_REF_NOARITH = 0x48, + + SCHRO_PARSE_CODE_INTER_REF_1 = 0x0d, + SCHRO_PARSE_CODE_INTER_REF_1_NOARITH = 0x4d, + SCHRO_PARSE_CODE_INTER_REF_2 = 0x0e, + SCHRO_PARSE_CODE_INTER_REF_2_NOARITH = 0x4e, + + SCHRO_PARSE_CODE_INTER_NON_REF_1 = 0x09, + SCHRO_PARSE_CODE_INTER_NON_REF_1_NOARITH = 0x49, + SCHRO_PARSE_CODE_INTER_NON_REF_2 = 0x0a, + SCHRO_PARSE_CODE_INTER_NON_REF_2_NOARITH = 0x4a, + + SCHRO_PARSE_CODE_LD_INTRA_REF = 0xcc, + SCHRO_PARSE_CODE_LD_INTRA_NON_REF = 0xc8 +} SchroParseCode; + +#define SCHRO_PARSE_CODE_PICTURE(is_ref,n_refs,is_lowdelay,is_noarith) \ + (8 | ((is_ref)<<2) | (n_refs) | ((is_lowdelay)<<7) | ((is_noarith)<<6)) + +#define SCHRO_PARSE_CODE_IS_SEQ_HEADER(x) ((x) == SCHRO_PARSE_CODE_SEQUENCE_HEADER) +#define SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(x) ((x) == SCHRO_PARSE_CODE_END_OF_SEQUENCE) +#define SCHRO_PARSE_CODE_IS_AUXILIARY_DATA(x) ((x) == SCHRO_PARSE_CODE_AUXILIARY_DATA) +#define SCHRO_PARSE_CODE_IS_PADDING(x) ((x) == SCHRO_PARSE_CODE_PADDING) +#define SCHRO_PARSE_CODE_IS_PICTURE(x) ((x) & 0x8) +#define SCHRO_PARSE_CODE_IS_LOW_DELAY(x) (((x) & 0x88) == 0x88) +#define SCHRO_PARSE_CODE_IS_CORE_SYNTAX(x) (((x) & 0x88) == 0x08) +#define SCHRO_PARSE_CODE_USING_AC(x) (((x) & 0x48) == 0x08) +#define SCHRO_PARSE_CODE_IS_REFERENCE(x) (((x) & 0xc) == 0x0c) +#define SCHRO_PARSE_CODE_IS_NON_REFERENCE(x) (((x) & 0xc) == 0x08) +#define SCHRO_PARSE_CODE_NUM_REFS(x) ((x) & 0x3) +#define SCHRO_PARSE_CODE_IS_INTRA(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) == 0) +#define SCHRO_PARSE_CODE_IS_INTER(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) > 0) + +#define SCHRO_PARSE_HEADER_SIZE (4+1+4+4) + +typedef enum _SchroVideoFormatEnum { + SCHRO_VIDEO_FORMAT_CUSTOM = 0, + SCHRO_VIDEO_FORMAT_QSIF, + SCHRO_VIDEO_FORMAT_QCIF, + SCHRO_VIDEO_FORMAT_SIF, + SCHRO_VIDEO_FORMAT_CIF, + SCHRO_VIDEO_FORMAT_4SIF, + SCHRO_VIDEO_FORMAT_4CIF, + SCHRO_VIDEO_FORMAT_SD480I_60, + SCHRO_VIDEO_FORMAT_SD576I_50, + SCHRO_VIDEO_FORMAT_HD720P_60, + SCHRO_VIDEO_FORMAT_HD720P_50, + SCHRO_VIDEO_FORMAT_HD1080I_60, + SCHRO_VIDEO_FORMAT_HD1080I_50, + SCHRO_VIDEO_FORMAT_HD1080P_60, + SCHRO_VIDEO_FORMAT_HD1080P_50, + SCHRO_VIDEO_FORMAT_DC2K_24, + SCHRO_VIDEO_FORMAT_DC4K_24 +} SchroVideoFormatEnum; + +typedef enum _SchroChromaFormat { + SCHRO_CHROMA_444 = 0, + SCHRO_CHROMA_422, + SCHRO_CHROMA_420 +} SchroChromaFormat; + +#define SCHRO_CHROMA_FORMAT_H_SHIFT(format) (((format) == SCHRO_CHROMA_444)?0:1) +#define SCHRO_CHROMA_FORMAT_V_SHIFT(format) (((format) == SCHRO_CHROMA_420)?1:0) + +typedef enum _SchroSignalRange { + SCHRO_SIGNAL_RANGE_CUSTOM = 0, + SCHRO_SIGNAL_RANGE_8BIT_FULL = 1, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO = 2, + SCHRO_SIGNAL_RANGE_10BIT_VIDEO = 3, + SCHRO_SIGNAL_RANGE_12BIT_VIDEO = 4 +} SchroSignalRange; + +typedef enum _SchroColourSpec { + SCHRO_COLOUR_SPEC_CUSTOM = 0, + SCHRO_COLOUR_SPEC_SDTV_525 = 1, + SCHRO_COLOUR_SPEC_SDTV_625 = 2, + SCHRO_COLOUR_SPEC_HDTV = 3, + SCHRO_COLOUR_SPEC_CINEMA = 4 +} SchroColourSpec; + +typedef enum _SchroColourPrimaries { + SCHRO_COLOUR_PRIMARY_HDTV = 0, + SCHRO_COLOUR_PRIMARY_SDTV_525 = 1, + SCHRO_COLOUR_PRIMARY_SDTV_625 = 2, + SCHRO_COLOUR_PRIMARY_CINEMA = 3 +} SchroColourPrimaries; + +typedef enum _SchroColourMatrix { + SCHRO_COLOUR_MATRIX_HDTV = 0, + SCHRO_COLOUR_MATRIX_SDTV = 1, + SCHRO_COLOUR_MATRIX_REVERSIBLE = 2 +}SchroColourMatrix; + +typedef enum _SchroTransferFunction { + SCHRO_TRANSFER_CHAR_TV_GAMMA = 0, + SCHRO_TRANSFER_CHAR_EXTENDED_GAMUT = 1, + SCHRO_TRANSFER_CHAR_LINEAR = 2, + SCHRO_TRANSFER_CHAR_DCI_GAMMA = 3 +} SchroTransferFunction; + + + +typedef struct _DiracSequenceHeader DiracSequenceHeader; + +struct _DiracSequenceHeader { + int major_version; + int minor_version; + int profile; + int level; + + int index; + int width; + int height; + int chroma_format; + + int interlaced; + int top_field_first; + + int frame_rate_numerator; + int frame_rate_denominator; + int aspect_ratio_numerator; + int aspect_ratio_denominator; + + int clean_width; + int clean_height; + int left_offset; + int top_offset; + + int luma_offset; + int luma_excursion; + int chroma_offset; + int chroma_excursion; + + int colour_primaries; + int colour_matrix; + int transfer_function; + + int interlaced_coding; + + int unused0; + int unused1; + int unused2; +}; + + +int dirac_sequence_header_parse (DiracSequenceHeader *header, + unsigned char *data, int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.c new file mode 100644 index 0000000..d1f16b8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.c @@ -0,0 +1,46 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include "gstogg.h" +#include "gstoggdemux.h" +#include "gstoggmux.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_ogg_demux_plugin_init (plugin); + gst_ogg_mux_plugin_init (plugin); + gst_ogm_parse_plugin_init (plugin); + gst_ogg_parse_plugin_init (plugin); + gst_ogg_avi_parse_plugin_init (plugin); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "ogg", + "ogg stream manipulation (info about ogg: http://xiph.org)", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.h b/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.h new file mode 100644 index 0000000..6f1393c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstogg.h @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstoggdemux.c: ogg stream demuxer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OGG_H__ +#define __GST_OGG_H__ + +#include + +gboolean gst_ogm_parse_plugin_init (GstPlugin * plugin); +gboolean gst_ogg_parse_plugin_init (GstPlugin * plugin); +gboolean gst_ogg_avi_parse_plugin_init (GstPlugin * plugin); + +#endif /* __GST_OGG_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggaviparse.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggaviparse.c new file mode 100644 index 0000000..2851e52 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggaviparse.c @@ -0,0 +1,476 @@ +/* GStreamer + * Copyright (C) 2006 Wim Taymans + * + * gstoggaviparse.c: ogg avi stream parser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Ogg in AVI is mostly done for vorbis audio. In the codec_data we receive the + * first 3 packets of the raw vorbis data. On the sinkpad we receive full-blown Ogg + * pages. + * Before extracting the packets out of the ogg pages, we push the raw vorbis + * header packets to the decoder. + * We don't use the incomming timestamps but use the ganulepos on the ogg pages + * directly. + * This parser only does ogg/vorbis for now. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "gstogg.h" + +GST_DEBUG_CATEGORY_STATIC (gst_ogg_avi_parse_debug); +#define GST_CAT_DEFAULT gst_ogg_avi_parse_debug + +#define GST_TYPE_OGG_AVI_PARSE (gst_ogg_avi_parse_get_type()) +#define GST_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse)) +#define GST_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_AVI_PARSE, GstOggAviParse)) +#define GST_IS_OGG_AVI_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_AVI_PARSE)) +#define GST_IS_OGG_AVI_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_AVI_PARSE)) + +static GType gst_ogg_avi_parse_get_type (void); + +typedef struct _GstOggAviParse GstOggAviParse; +typedef struct _GstOggAviParseClass GstOggAviParseClass; + +struct _GstOggAviParse +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + gboolean discont; + gint serial; + + ogg_sync_state sync; + ogg_stream_state stream; +}; + +struct _GstOggAviParseClass +{ + GstElementClass parent_class; +}; + +static void gst_ogg_avi_parse_base_init (gpointer g_class); +static void gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass); +static void gst_ogg_avi_parse_init (GstOggAviParse * ogg); +static GstElementClass *parent_class = NULL; + +static GType +gst_ogg_avi_parse_get_type (void) +{ + static GType ogg_avi_parse_type = 0; + + if (!ogg_avi_parse_type) { + static const GTypeInfo ogg_avi_parse_info = { + sizeof (GstOggAviParseClass), + gst_ogg_avi_parse_base_init, + NULL, + (GClassInitFunc) gst_ogg_avi_parse_class_init, + NULL, + NULL, + sizeof (GstOggAviParse), + 0, + (GInstanceInitFunc) gst_ogg_avi_parse_init, + }; + + ogg_avi_parse_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstOggAviParse", + &ogg_avi_parse_info, 0); + } + return ogg_avi_parse_type; +} + +enum +{ + PROP_0 +}; + +static GstStaticPadTemplate ogg_avi_parse_src_template_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-vorbis") + ); + +static GstStaticPadTemplate ogg_avi_parse_sink_template_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-ogg-avi") + ); + +static void gst_ogg_avi_parse_finalize (GObject * object); +static GstStateChangeReturn gst_ogg_avi_parse_change_state (GstElement * + element, GstStateChange transition); +static gboolean gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps); + +static void +gst_ogg_avi_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Ogg AVI parser", "Codec/Parser", + "parse an ogg avi stream into pages (info about ogg: http://xiph.org)", + "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_avi_parse_sink_template_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_avi_parse_src_template_factory)); +} + +static void +gst_ogg_avi_parse_class_init (GstOggAviParseClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gstelement_class->change_state = gst_ogg_avi_parse_change_state; + + gobject_class->finalize = gst_ogg_avi_parse_finalize; +} + +static void +gst_ogg_avi_parse_init (GstOggAviParse * ogg) +{ + /* create the sink and source pads */ + ogg->sinkpad = + gst_pad_new_from_static_template (&ogg_avi_parse_sink_template_factory, + "sink"); + gst_pad_set_setcaps_function (ogg->sinkpad, gst_ogg_avi_parse_setcaps); + gst_pad_set_event_function (ogg->sinkpad, gst_ogg_avi_parse_event); + gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_avi_parse_chain); + gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad); + + ogg->srcpad = + gst_pad_new_from_static_template (&ogg_avi_parse_src_template_factory, + "src"); + gst_pad_use_fixed_caps (ogg->srcpad); + gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad); +} + +static void +gst_ogg_avi_parse_finalize (GObject * object) +{ + GstOggAviParse *ogg = GST_OGG_AVI_PARSE (object); + + GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg); + + ogg_sync_clear (&ogg->sync); + ogg_stream_clear (&ogg->stream); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_ogg_avi_parse_setcaps (GstPad * pad, GstCaps * caps) +{ + GstOggAviParse *ogg; + GstStructure *structure; + const GValue *codec_data; + GstBuffer *buffer; + guint8 *data; + guint size; + guint32 sizes[3]; + GstCaps *outcaps; + gint i, offs; + + ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad)); + + structure = gst_caps_get_structure (caps, 0); + + /* take codec data */ + codec_data = gst_structure_get_value (structure, "codec_data"); + if (codec_data == NULL) + goto no_data; + + /* only buffers are valid */ + if (G_VALUE_TYPE (codec_data) != GST_TYPE_BUFFER) + goto wrong_format; + + /* Now parse the data */ + buffer = gst_value_get_buffer (codec_data); + + /* first 22 bytes are bits_per_sample, channel_mask, GUID + * Then we get 3 LE guint32 with the 3 header sizes + * then we get the bytes of the 3 headers. */ + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + GST_LOG_OBJECT (ogg, "configuring codec_data of size %u", size); + + /* skip headers */ + data += 22; + size -= 22; + + /* we need at least 12 bytes for the packet sizes of the 3 headers */ + if (size < 12) + goto buffer_too_small; + + /* read sizes of the 3 headers */ + sizes[0] = GST_READ_UINT32_LE (data); + sizes[1] = GST_READ_UINT32_LE (data + 4); + sizes[2] = GST_READ_UINT32_LE (data + 8); + + GST_DEBUG_OBJECT (ogg, "header sizes: %u %u %u", sizes[0], sizes[1], + sizes[2]); + + size -= 12; + + /* and we need at least enough data for all the headers */ + if (size < sizes[0] + sizes[1] + sizes[2]) + goto buffer_too_small; + + /* set caps */ + outcaps = gst_caps_new_simple ("audio/x-vorbis", NULL); + gst_pad_set_caps (ogg->srcpad, outcaps); + + /* copy header data */ + offs = 34; + for (i = 0; i < 3; i++) { + GstBuffer *out; + + /* now output the raw vorbis header packets */ + out = gst_buffer_create_sub (buffer, offs, sizes[i]); + gst_buffer_set_caps (out, outcaps); + gst_pad_push (ogg->srcpad, out); + + offs += sizes[i]; + } + gst_caps_unref (outcaps); + + return TRUE; + + /* ERRORS */ +no_data: + { + GST_DEBUG_OBJECT (ogg, "no codec_data found in caps"); + return FALSE; + } +wrong_format: + { + GST_DEBUG_OBJECT (ogg, "codec_data is not a buffer"); + return FALSE; + } +buffer_too_small: + { + GST_DEBUG_OBJECT (ogg, "codec_data is too small"); + return FALSE; + } +} + +static gboolean +gst_ogg_avi_parse_event (GstPad * pad, GstEvent * event) +{ + GstOggAviParse *ogg; + gboolean ret; + + ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + ret = gst_pad_push_event (ogg->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + ogg_sync_reset (&ogg->sync); + ogg_stream_reset (&ogg->stream); + ogg->discont = TRUE; + ret = gst_pad_push_event (ogg->srcpad, event); + break; + default: + ret = gst_pad_push_event (ogg->srcpad, event); + break; + } + return ret; +} + +static GstFlowReturn +gst_ogg_avi_parse_push_packet (GstOggAviParse * ogg, ogg_packet * packet) +{ + GstBuffer *buffer; + GstFlowReturn result; + + /* allocate space for header and body */ + buffer = gst_buffer_new_and_alloc (packet->bytes); + memcpy (GST_BUFFER_DATA (buffer), packet->packet, packet->bytes); + + GST_LOG_OBJECT (ogg, "created buffer %p from page", buffer); + + GST_BUFFER_OFFSET_END (buffer) = packet->granulepos; + + if (ogg->discont) { + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + ogg->discont = FALSE; + } + + result = gst_pad_push (ogg->srcpad, buffer); + + return result; +} + +static GstFlowReturn +gst_ogg_avi_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn result = GST_FLOW_OK; + GstOggAviParse *ogg; + guint8 *data; + guint size; + gchar *oggbuf; + gint ret = -1; + + ogg = GST_OGG_AVI_PARSE (GST_OBJECT_PARENT (pad)); + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", size); + + if (GST_BUFFER_IS_DISCONT (buffer)) { + ogg_sync_reset (&ogg->sync); + ogg->discont = TRUE; + } + + /* write data to sync layer */ + oggbuf = ogg_sync_buffer (&ogg->sync, size); + memcpy (oggbuf, data, size); + ogg_sync_wrote (&ogg->sync, size); + gst_buffer_unref (buffer); + + /* try to get as many packets out of the stream as possible */ + do { + ogg_page page; + + /* try to swap out a page */ + ret = ogg_sync_pageout (&ogg->sync, &page); + if (ret == 0) { + GST_DEBUG_OBJECT (ogg, "need more data"); + break; + } else if (ret == -1) { + GST_DEBUG_OBJECT (ogg, "discont in pages"); + ogg->discont = TRUE; + } else { + /* new unknown stream, init the ogg stream with the serial number of the + * page. */ + if (ogg->serial == -1) { + ogg->serial = ogg_page_serialno (&page); + ogg_stream_init (&ogg->stream, ogg->serial); + } + + /* submit page */ + if (ogg_stream_pagein (&ogg->stream, &page) != 0) { + GST_WARNING_OBJECT (ogg, "ogg stream choked on page resetting stream"); + ogg_sync_reset (&ogg->sync); + ogg->discont = TRUE; + continue; + } + + /* try to get as many packets as possible out of the page */ + do { + ogg_packet packet; + + ret = ogg_stream_packetout (&ogg->stream, &packet); + GST_LOG_OBJECT (ogg, "packetout gave %d", ret); + switch (ret) { + case 0: + break; + case -1: + /* out of sync, We mark a DISCONT. */ + ogg->discont = TRUE; + break; + case 1: + result = gst_ogg_avi_parse_push_packet (ogg, &packet); + if (result != GST_FLOW_OK) + goto done; + break; + default: + GST_WARNING_OBJECT (ogg, + "invalid return value %d for ogg_stream_packetout, resetting stream", + ret); + break; + } + } + while (ret != 0); + } + } + while (ret != 0); + +done: + return result; +} + +static GstStateChangeReturn +gst_ogg_avi_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstOggAviParse *ogg; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + + ogg = GST_OGG_AVI_PARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + ogg_sync_init (&ogg->sync); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + ogg_sync_reset (&ogg->sync); + ogg_stream_reset (&ogg->stream); + ogg->serial = -1; + ogg->discont = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + ogg_sync_clear (&ogg->sync); + break; + default: + break; + } + return result; +} + +gboolean +gst_ogg_avi_parse_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_ogg_avi_parse_debug, "oggaviparse", 0, + "ogg avi parser"); + + return gst_element_register (plugin, "oggaviparse", GST_RANK_PRIMARY, + GST_TYPE_OGG_AVI_PARSE); +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.c new file mode 100644 index 0000000..67d2321 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.c @@ -0,0 +1,3683 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstoggdemux.c: ogg stream demuxer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-oggdemux + * @see_also: oggmux + * + * This element demuxes ogg files into their encoded audio and video components. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=test.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink + * ]| Decodes the vorbis audio stored inside an ogg container. + * + * + * Last reviewed on 2006-12-30 (0.10.5) + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "gstoggdemux.h" + +#define CHUNKSIZE (8500) /* this is out of vorbisfile */ + +#define GST_FLOW_LIMIT GST_FLOW_CUSTOM_ERROR + +#define GST_CHAIN_LOCK(ogg) g_mutex_lock((ogg)->chain_lock) +#define GST_CHAIN_UNLOCK(ogg) g_mutex_unlock((ogg)->chain_lock) + +GST_DEBUG_CATEGORY (gst_ogg_demux_debug); +GST_DEBUG_CATEGORY (gst_ogg_demux_setup_debug); +#define GST_CAT_DEFAULT gst_ogg_demux_debug + + +static ogg_packet * +_ogg_packet_copy (const ogg_packet * packet) +{ + ogg_packet *ret = g_new0 (ogg_packet, 1); + + *ret = *packet; + ret->packet = g_memdup (packet->packet, packet->bytes); + + return ret; +} + +static void +_ogg_packet_free (ogg_packet * packet) +{ + g_free (packet->packet); + g_free (packet); +} + +static ogg_page * +gst_ogg_page_copy (ogg_page * page) +{ + ogg_page *p = g_new0 (ogg_page, 1); + + /* make a copy of the page */ + p->header = g_memdup (page->header, page->header_len); + p->header_len = page->header_len; + p->body = g_memdup (page->body, page->body_len); + p->body_len = page->body_len; + + return p; +} + +static void +gst_ogg_page_free (ogg_page * page) +{ + g_free (page->header); + g_free (page->body); + g_free (page); +} + +static gboolean gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, + GstOggChain * chain); +static gboolean gst_ogg_demux_activate_chain (GstOggDemux * ogg, + GstOggChain * chain, GstEvent * event); +static void gst_ogg_chain_mark_discont (GstOggChain * chain); + +static gboolean gst_ogg_demux_perform_seek (GstOggDemux * ogg, + GstEvent * event); +static gboolean gst_ogg_demux_receive_event (GstElement * element, + GstEvent * event); + +static void gst_ogg_pad_dispose (GObject * object); +static void gst_ogg_pad_finalize (GObject * object); + +static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad); +static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query); +static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event); +static GstCaps *gst_ogg_pad_getcaps (GstPad * pad); +static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain, + glong serialno); + +static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg, + GstOggPad * pad, GstFlowReturn ret); +static void gst_ogg_demux_sync_streams (GstOggDemux * ogg); + +GstCaps *gst_ogg_demux_set_header_on_caps (GstOggDemux * ogg, + GstCaps * caps, GList * headers); + +GType gst_ogg_pad_get_type (void); +G_DEFINE_TYPE (GstOggPad, gst_ogg_pad, GST_TYPE_PAD); + +static void +gst_ogg_pad_class_init (GstOggPadClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gst_ogg_pad_dispose; + gobject_class->finalize = gst_ogg_pad_finalize; +} + +static void +gst_ogg_pad_init (GstOggPad * pad) +{ + gst_pad_set_event_function (GST_PAD (pad), + GST_DEBUG_FUNCPTR (gst_ogg_pad_event)); + gst_pad_set_getcaps_function (GST_PAD (pad), + GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps)); + gst_pad_set_query_type_function (GST_PAD (pad), + GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types)); + gst_pad_set_query_function (GST_PAD (pad), + GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query)); + + pad->mode = GST_OGG_PAD_MODE_INIT; + + pad->current_granule = -1; + pad->keyframe_granule = -1; + + pad->start_time = GST_CLOCK_TIME_NONE; + + pad->last_stop = GST_CLOCK_TIME_NONE; + + pad->have_type = FALSE; + pad->continued = NULL; + pad->map.headers = NULL; + pad->map.queued = NULL; +} + +static void +gst_ogg_pad_dispose (GObject * object) +{ + GstOggPad *pad = GST_OGG_PAD (object); + + pad->chain = NULL; + pad->ogg = NULL; + + g_list_foreach (pad->map.headers, (GFunc) _ogg_packet_free, NULL); + g_list_free (pad->map.headers); + pad->map.headers = NULL; + g_list_foreach (pad->map.queued, (GFunc) _ogg_packet_free, NULL); + g_list_free (pad->map.queued); + pad->map.queued = NULL; + + g_free (pad->map.index); + pad->map.index = NULL; + + /* clear continued pages */ + g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL); + g_list_free (pad->continued); + pad->continued = NULL; + + if (pad->map.caps) { + gst_caps_unref (pad->map.caps); + pad->map.caps = NULL; + } + + if (pad->map.taglist) { + gst_tag_list_free (pad->map.taglist); + pad->map.taglist = NULL; + } + + ogg_stream_reset (&pad->map.stream); + + G_OBJECT_CLASS (gst_ogg_pad_parent_class)->dispose (object); +} + +static void +gst_ogg_pad_finalize (GObject * object) +{ + GstOggPad *pad = GST_OGG_PAD (object); + + ogg_stream_clear (&pad->map.stream); + + G_OBJECT_CLASS (gst_ogg_pad_parent_class)->finalize (object); +} + +static const GstQueryType * +gst_ogg_pad_query_types (GstPad * pad) +{ + static const GstQueryType query_types[] = { + GST_QUERY_DURATION, + GST_QUERY_SEEKING, + 0 + }; + + return query_types; +} + +static GstCaps * +gst_ogg_pad_getcaps (GstPad * pad) +{ + return gst_caps_ref (GST_PAD_CAPS (pad)); +} + +static gboolean +gst_ogg_pad_src_query (GstPad * pad, GstQuery * query) +{ + gboolean res = TRUE; + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION: + { + GstFormat format; + gint64 total_time = -1; + + gst_query_parse_duration (query, &format, NULL); + /* can only get position in time */ + if (format != GST_FORMAT_TIME) + goto wrong_format; + + if (ogg->total_time != -1) { + /* we can return the total length */ + total_time = ogg->total_time; + } else { + gint bitrate = ogg->bitrate; + + /* try with length and bitrate */ + if (bitrate > 0) { + GstQuery *uquery; + + /* ask upstream for total length in bytes */ + uquery = gst_query_new_duration (GST_FORMAT_BYTES); + if (gst_pad_peer_query (ogg->sinkpad, uquery)) { + gint64 length; + + gst_query_parse_duration (uquery, NULL, &length); + + /* estimate using the bitrate */ + total_time = + gst_util_uint64_scale (length, 8 * GST_SECOND, bitrate); + + GST_LOG_OBJECT (ogg, + "length: %" G_GINT64_FORMAT ", bitrate %d, total_time %" + GST_TIME_FORMAT, length, bitrate, GST_TIME_ARGS (total_time)); + } + gst_query_unref (uquery); + } + } + + gst_query_set_duration (query, GST_FORMAT_TIME, total_time); + break; + } + case GST_QUERY_SEEKING: + { + GstFormat format; + + gst_query_parse_seeking (query, &format, NULL, NULL, NULL); + if (format == GST_FORMAT_TIME) { + gboolean seekable = FALSE; + gint64 stop = -1; + + if (ogg->pullmode) { + seekable = TRUE; + stop = ogg->total_time; + } else if (ogg->current_chain->streams->len) { + gint i; + + seekable = FALSE; + for (i = 0; i < ogg->current_chain->streams->len; i++) { + GstOggPad *pad = + g_array_index (ogg->current_chain->streams, GstOggPad *, i); + + seekable |= (pad->map.index != NULL && pad->map.n_index != 0); + + if (pad->map.index != NULL && pad->map.n_index != 0) { + GstOggIndex *idx; + GstClockTime idx_time; + + idx = &pad->map.index[pad->map.n_index - 1]; + idx_time = + gst_util_uint64_scale (idx->timestamp, GST_SECOND, + pad->map.kp_denom); + if (stop == -1) + stop = idx_time; + else + stop = MAX (idx_time, stop); + } + } + } + + gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, stop); + } else { + res = FALSE; + } + break; + } + + default: + res = gst_pad_query_default (pad, query); + break; + } +done: + gst_object_unref (ogg); + + return res; + + /* ERRORS */ +wrong_format: + { + GST_DEBUG_OBJECT (ogg, "only query duration on TIME is supported"); + res = FALSE; + goto done; + } +} + +static gboolean +gst_ogg_demux_receive_event (GstElement * element, GstEvent * event) +{ + gboolean res; + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (element); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* now do the seek */ + res = gst_ogg_demux_perform_seek (ogg, event); + gst_event_unref (event); + break; + default: + GST_DEBUG_OBJECT (ogg, "We only handle seek events here"); + goto error; + } + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (ogg, "error handling event"); + gst_event_unref (event); + return FALSE; + } +} + +static gboolean +gst_ogg_pad_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* now do the seek */ + res = gst_ogg_demux_perform_seek (ogg, event); + gst_event_unref (event); + break; + default: + res = gst_pad_event_default (pad, event); + break; + } + gst_object_unref (ogg); + + return res; +} + +static void +gst_ogg_pad_reset (GstOggPad * pad) +{ + ogg_stream_reset (&pad->map.stream); + + GST_DEBUG_OBJECT (pad, "doing reset"); + + /* clear continued pages */ + g_list_foreach (pad->continued, (GFunc) gst_ogg_page_free, NULL); + g_list_free (pad->continued); + pad->continued = NULL; + + pad->last_ret = GST_FLOW_OK; + pad->last_stop = GST_CLOCK_TIME_NONE; + pad->current_granule = -1; + pad->keyframe_granule = -1; + pad->is_eos = FALSE; +} + +/* queue data, basically takes the packet, puts it in a buffer and store the + * buffer in the queued list. */ +static GstFlowReturn +gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet) +{ +#ifndef GST_DISABLE_GST_DEBUG + GstOggDemux *ogg = pad->ogg; +#endif + + GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08lx", pad, + pad->map.serialno); + + pad->map.queued = g_list_append (pad->map.queued, _ogg_packet_copy (packet)); + + /* we are ok now */ + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, + gboolean push_headers) +{ + GstBuffer *buf = NULL; + GstFlowReturn ret, cret; + GstOggDemux *ogg = pad->ogg; + gint64 current_time; + GstOggChain *chain; + gint64 duration; + gint offset; + gint trim; + GstClockTime out_timestamp, out_duration; + guint64 out_offset, out_offset_end; + gboolean delta_unit = FALSE; + + cret = GST_FLOW_OK; + + GST_DEBUG_OBJECT (ogg, + "%p streaming to peer serial %08lx", pad, pad->map.serialno); + + if (pad->map.is_ogm) { + const guint8 *data; + long bytes; + + data = packet->packet; + bytes = packet->bytes; + + if (bytes < 1) + goto empty_packet; + + if ((data[0] & 1) || (data[0] & 3 && pad->map.is_ogm_text)) { + /* We don't push header packets for OGM */ + goto done; + } + + offset = 1 + (((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1)); + delta_unit = (((data[0] & 0x08) >> 3) == 0); + + trim = 0; + + /* Strip trailing \0 for subtitles */ + if (pad->map.is_ogm_text) { + while (bytes && data[bytes - 1] == 0) { + trim++; + bytes--; + } + } + } else if (pad->map.is_vp8) { + if ((packet->bytes >= 7 && memcmp (packet->packet, "OVP80\2 ", 7) == 0) || + packet->b_o_s || + (packet->bytes >= 5 && memcmp (packet->packet, "OVP80", 5) == 0)) { + /* We don't push header packets for VP8 */ + goto done; + } + offset = 0; + trim = 0; + } else { + offset = 0; + trim = 0; + } + + /* get timing info for the packet */ + duration = gst_ogg_stream_get_packet_duration (&pad->map, packet); + GST_DEBUG_OBJECT (ogg, "packet duration %" G_GUINT64_FORMAT, duration); + + if (packet->b_o_s) { + out_timestamp = GST_CLOCK_TIME_NONE; + out_duration = GST_CLOCK_TIME_NONE; + out_offset = 0; + out_offset_end = -1; + } else { + if (packet->granulepos != -1) { + pad->current_granule = gst_ogg_stream_granulepos_to_granule (&pad->map, + packet->granulepos); + pad->keyframe_granule = + gst_ogg_stream_granulepos_to_key_granule (&pad->map, + packet->granulepos); + GST_DEBUG_OBJECT (ogg, "new granule %" G_GUINT64_FORMAT, + pad->current_granule); + } else if (ogg->segment.rate > 0.0 && pad->current_granule != -1) { + pad->current_granule += duration; + GST_DEBUG_OBJECT (ogg, "interpollating granule %" G_GUINT64_FORMAT, + pad->current_granule); + } + if (ogg->segment.rate < 0.0 && packet->granulepos == -1) { + /* negative rates, only set timestamp on the packets with a granulepos */ + out_timestamp = -1; + out_duration = -1; + out_offset = -1; + out_offset_end = -1; + } else { + /* we only push buffers after we have a valid granule. This is done so that + * we nicely skip packets without a timestamp after a seek. This is ok + * because we base or seek on the packet after the page with the smaller + * timestamp. */ + if (pad->current_granule == -1) + goto no_timestamp; + + if (pad->map.is_ogm) { + out_timestamp = gst_ogg_stream_granule_to_time (&pad->map, + pad->current_granule); + out_duration = gst_util_uint64_scale (duration, + GST_SECOND * pad->map.granulerate_d, pad->map.granulerate_n); + } else if (pad->map.is_sparse) { + out_timestamp = gst_ogg_stream_granule_to_time (&pad->map, + pad->current_granule); + if (duration == GST_CLOCK_TIME_NONE) { + out_duration = GST_CLOCK_TIME_NONE; + } else { + out_duration = gst_util_uint64_scale (duration, + GST_SECOND * pad->map.granulerate_d, pad->map.granulerate_n); + } + } else { + out_timestamp = gst_ogg_stream_granule_to_time (&pad->map, + pad->current_granule - duration); + out_duration = + gst_ogg_stream_granule_to_time (&pad->map, + pad->current_granule) - out_timestamp; + } + out_offset_end = + gst_ogg_stream_granule_to_granulepos (&pad->map, + pad->current_granule, pad->keyframe_granule); + out_offset = + gst_ogg_stream_granule_to_time (&pad->map, pad->current_granule); + } + } + + if (pad->map.is_ogm_text) { + /* check for invalid buffer sizes */ + if (G_UNLIKELY (offset + trim >= packet->bytes)) + goto empty_packet; + } + + if (!pad->added) + goto not_added; + + buf = gst_buffer_new_and_alloc (packet->bytes - offset - trim); + gst_buffer_set_caps (buf, GST_PAD_CAPS (pad)); + + /* set delta flag for OGM content */ + if (delta_unit) + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + + /* copy packet in buffer */ + memcpy (buf->data, packet->packet + offset, packet->bytes - offset - trim); + + GST_BUFFER_TIMESTAMP (buf) = out_timestamp; + GST_BUFFER_DURATION (buf) = out_duration; + GST_BUFFER_OFFSET (buf) = out_offset; + GST_BUFFER_OFFSET_END (buf) = out_offset_end; + + /* Mark discont on the buffer */ + if (pad->discont) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + pad->discont = FALSE; + } + + pad->last_stop = ogg->segment.last_stop; + + /* don't push the header packets when we are asked to skip them */ + if (!packet->b_o_s || push_headers) { + ret = gst_pad_push (GST_PAD_CAST (pad), buf); + buf = NULL; + + /* combine flows */ + cret = gst_ogg_demux_combine_flows (ogg, pad, ret); + } + + /* we're done with skeleton stuff */ + if (pad->map.is_skeleton) + goto done; + + /* check if valid granulepos, then we can calculate the current + * position. We know the granule for each packet but we only want to update + * the last_stop when we have a valid granulepos on the packet because else + * our time jumps around for the different streams. */ + if (packet->granulepos < 0) + goto done; + + /* convert to time */ + current_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map, + packet->granulepos); + + /* convert to stream time */ + if ((chain = pad->chain)) { + gint64 chain_start = 0; + + if (chain->segment_start != GST_CLOCK_TIME_NONE) + chain_start = chain->segment_start; + + current_time = current_time - chain_start + chain->begin_time; + } + + /* and store as the current position */ + gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time); + + GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT, + GST_TIME_ARGS (current_time)); + + /* check stream eos */ + if ((ogg->segment.rate > 0.0 && ogg->segment.stop != GST_CLOCK_TIME_NONE && + current_time > ogg->segment.stop) || + (ogg->segment.rate < 0.0 && ogg->segment.start != GST_CLOCK_TIME_NONE && + current_time < ogg->segment.start)) { + GST_DEBUG_OBJECT (ogg, "marking pad %p EOS", pad); + pad->is_eos = TRUE; + } + +done: + if (buf) + gst_buffer_unref (buf); + /* return combined flow result */ + return cret; + + /* special cases */ +empty_packet: + { + GST_DEBUG_OBJECT (ogg, "Skipping empty packet"); + goto done; + } + +no_timestamp: + { + GST_DEBUG_OBJECT (ogg, "skipping packet: no valid granule found yet"); + goto done; + } +not_added: + { + GST_DEBUG_OBJECT (ogg, "pad not added yet"); + goto done; + } +} + +static guint64 +gst_ogg_demux_collect_start_time (GstOggDemux * ogg, GstOggChain * chain) +{ + gint i; + guint64 start_time = G_MAXUINT64; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + if (pad->map.is_sparse) + continue; + + /* can do this if the pad start time is not defined */ + if (pad->start_time == GST_CLOCK_TIME_NONE) { + start_time = G_MAXUINT64; + break; + } else { + start_time = MIN (start_time, pad->start_time); + } + } + return start_time; +} + +/* submit a packet to the oggpad, this function will run the + * typefind code for the pad if this is the first packet for this + * stream + */ +static GstFlowReturn +gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet) +{ + gint64 granule; + GstFlowReturn ret = GST_FLOW_OK; + + GstOggDemux *ogg = pad->ogg; + + GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08lx", pad, + pad->map.serialno); + + if (!pad->have_type) { + pad->have_type = gst_ogg_stream_setup_map (&pad->map, packet); + if (!pad->have_type) { + pad->map.caps = gst_caps_new_simple ("application/x-unknown", NULL); + } + if (pad->map.is_skeleton) { + GST_DEBUG_OBJECT (ogg, "we have a fishead"); + /* copy values over to global ogg level */ + ogg->basetime = pad->map.basetime; + ogg->prestime = pad->map.prestime; + + /* use total time to update the total ogg time */ + if (ogg->total_time == -1) { + ogg->total_time = pad->map.total_time; + } else if (pad->map.total_time > 0) { + ogg->total_time = MAX (ogg->total_time, pad->map.total_time); + } + } + if (pad->map.caps) { + gst_pad_set_caps (GST_PAD (pad), pad->map.caps); + } else { + GST_WARNING_OBJECT (ogg, "stream parser didn't create src pad caps"); + } + } + + if (pad->map.is_skeleton) { + guint32 serialno; + GstOggPad *skel_pad; + GstOggSkeleton type; + + /* try to parse the serialno first */ + if (gst_ogg_map_parse_fisbone (&pad->map, packet->packet, packet->bytes, + &serialno, &type)) { + + GST_WARNING_OBJECT (pad->ogg, + "got skeleton packet for stream 0x%08x", serialno); + + skel_pad = gst_ogg_chain_get_stream (pad->chain, serialno); + if (skel_pad) { + switch (type) { + case GST_OGG_SKELETON_FISBONE: + /* parse the remainder of the fisbone in the pad with the serialno, + * note that we ignore the start_time as this is usually wrong for + * live streams */ + gst_ogg_map_add_fisbone (&skel_pad->map, &pad->map, packet->packet, + packet->bytes, NULL); + break; + case GST_OGG_SKELETON_INDEX: + gst_ogg_map_add_index (&skel_pad->map, &pad->map, packet->packet, + packet->bytes); + + /* use total time to update the total ogg time */ + if (ogg->total_time == -1) { + ogg->total_time = skel_pad->map.total_time; + } else if (skel_pad->map.total_time > 0) { + ogg->total_time = MAX (ogg->total_time, skel_pad->map.total_time); + } + break; + default: + break; + } + + } else { + GST_WARNING_OBJECT (pad->ogg, + "found skeleton fisbone for an unknown stream 0x%08x", serialno); + } + } + } + + granule = gst_ogg_stream_granulepos_to_granule (&pad->map, + packet->granulepos); + if (granule != -1) { + GST_DEBUG_OBJECT (ogg, "%p has granulepos %" G_GINT64_FORMAT, pad, granule); + pad->current_granule = granule; + } + + /* restart header packet count when seeing a b_o_s page; + * particularly useful following a seek or even following chain finding */ + if (packet->b_o_s) { + GST_DEBUG_OBJECT (ogg, "b_o_s packet, resetting header packet count"); + pad->map.n_header_packets_seen = 0; + if (!pad->map.have_headers) { + GST_DEBUG_OBJECT (ogg, "clearing header packets"); + g_list_foreach (pad->map.headers, (GFunc) _ogg_packet_free, NULL); + g_list_free (pad->map.headers); + pad->map.headers = NULL; + } + } + + /* Overload the value of b_o_s in ogg_packet with a flag whether or + * not this is a header packet. Maybe some day this could be cleaned + * up. */ + packet->b_o_s = gst_ogg_stream_packet_is_header (&pad->map, packet); + if (!packet->b_o_s) { + GST_DEBUG ("found non-header packet"); + pad->map.have_headers = TRUE; + if (pad->start_time == GST_CLOCK_TIME_NONE) { + gint64 duration = gst_ogg_stream_get_packet_duration (&pad->map, packet); + GST_DEBUG ("duration %" G_GINT64_FORMAT, duration); + if (duration != -1) { + pad->map.accumulated_granule += duration; + GST_DEBUG ("accumulated granule %" G_GINT64_FORMAT, + pad->map.accumulated_granule); + } + + if (packet->granulepos != -1) { + ogg_int64_t start_granule; + gint64 granule; + + granule = gst_ogg_stream_granulepos_to_granule (&pad->map, + packet->granulepos); + + if (granule > pad->map.accumulated_granule) + start_granule = granule - pad->map.accumulated_granule; + else + start_granule = 0; + + pad->start_time = gst_ogg_stream_granule_to_time (&pad->map, + start_granule); + GST_DEBUG ("start time %" G_GINT64_FORMAT, pad->start_time); + } else { + packet->granulepos = gst_ogg_stream_granule_to_granulepos (&pad->map, + pad->map.accumulated_granule, pad->keyframe_granule); + } + } + } else { + /* look for tags in header packet (before inc header count) */ + gst_ogg_stream_extract_tags (&pad->map, packet); + pad->map.n_header_packets_seen++; + if (!pad->map.have_headers) { + pad->map.headers = + g_list_append (pad->map.headers, _ogg_packet_copy (packet)); + GST_DEBUG ("keeping header packet %d", pad->map.n_header_packets_seen); + } + } + + /* we know the start_time of the pad data, see if we + * can activate the complete chain if this is a dynamic + * chain. We need all the headers too for this. */ + if (pad->start_time != GST_CLOCK_TIME_NONE && pad->map.have_headers) { + GstOggChain *chain = pad->chain; + + /* check if complete chain has start time */ + if (chain == ogg->building_chain) { + GstEvent *event = NULL; + + if (ogg->resync) { + guint64 start_time; + + GST_DEBUG_OBJECT (ogg, "need to resync"); + + /* when we need to resync after a seek, we wait until we have received + * timestamps on all streams */ + start_time = gst_ogg_demux_collect_start_time (ogg, chain); + + if (start_time != G_MAXUINT64) { + gint64 segment_time; + + GST_DEBUG_OBJECT (ogg, "start_time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + + if (chain->segment_start < start_time) + segment_time = + (start_time - chain->segment_start) + chain->begin_time; + else + segment_time = chain->begin_time; + + /* create the newsegment event we are going to send out */ + event = gst_event_new_new_segment (FALSE, ogg->segment.rate, + GST_FORMAT_TIME, start_time, chain->segment_stop, segment_time); + + ogg->resync = FALSE; + } + } else { + /* see if we have enough info to activate the chain, we have enough info + * when all streams have a valid start time. */ + if (gst_ogg_demux_collect_chain_info (ogg, chain)) { + + GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->segment_start)); + GST_DEBUG_OBJECT (ogg, "segment_stop: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->segment_stop)); + GST_DEBUG_OBJECT (ogg, "segment_time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->begin_time)); + + /* create the newsegment event we are going to send out */ + event = gst_event_new_new_segment (FALSE, ogg->segment.rate, + GST_FORMAT_TIME, chain->segment_start, chain->segment_stop, + chain->begin_time); + } + } + + if (event) { + gst_event_set_seqnum (event, ogg->seqnum); + + gst_ogg_demux_activate_chain (ogg, chain, event); + + ogg->building_chain = NULL; + } + } + } + + /* if we are building a chain, store buffer for when we activate + * it. This path is taken if we operate in streaming mode. */ + if (ogg->building_chain) { + /* bos packets where stored in the header list so we can discard + * them here*/ + if (!packet->b_o_s) + ret = gst_ogg_demux_queue_data (pad, packet); + } + /* else we are completely streaming to the peer */ + else { + ret = gst_ogg_demux_chain_peer (pad, packet, !ogg->pullmode); + } + return ret; +} + +/* flush at most @npackets from the stream layer. All packets if + * @npackets is 0; + */ +static GstFlowReturn +gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets) +{ + GstFlowReturn result = GST_FLOW_OK; + gboolean done = FALSE; + GstOggDemux *ogg; + + ogg = pad->ogg; + + while (!done) { + int ret; + ogg_packet packet; + + ret = ogg_stream_packetout (&pad->map.stream, &packet); + switch (ret) { + case 0: + GST_LOG_OBJECT (ogg, "packetout done"); + done = TRUE; + break; + case -1: + GST_LOG_OBJECT (ogg, "packetout discont"); + gst_ogg_chain_mark_discont (pad->chain); + break; + case 1: + GST_LOG_OBJECT (ogg, "packetout gave packet of size %ld", packet.bytes); + result = gst_ogg_pad_submit_packet (pad, &packet); + /* not linked is not a problem, it's possible that we are still + * collecting headers and that we don't have exposed the pads yet */ + if (result == GST_FLOW_NOT_LINKED) + break; + else if (result <= GST_FLOW_UNEXPECTED) + goto could_not_submit; + break; + default: + GST_WARNING_OBJECT (ogg, + "invalid return value %d for ogg_stream_packetout, resetting stream", + ret); + gst_ogg_pad_reset (pad); + break; + } + if (npackets > 0) { + npackets--; + done = (npackets == 0); + } + } + return result; + + /* ERRORS */ +could_not_submit: + { + GST_WARNING_OBJECT (ogg, + "could not submit packet for stream %08lx, error: %d", + pad->map.serialno, result); + gst_ogg_pad_reset (pad); + return result; + } +} + +/* submit a page to an oggpad, this function will then submit all + * the packets in the page. + */ +static GstFlowReturn +gst_ogg_pad_submit_page (GstOggPad * pad, ogg_page * page) +{ + GstFlowReturn result = GST_FLOW_OK; + GstOggDemux *ogg; + gboolean continued = FALSE; + + ogg = pad->ogg; + + /* for negative rates we read pages backwards and must therefore be carefull + * with continued pages */ + if (ogg->segment.rate < 0.0) { + gint npackets; + + continued = ogg_page_continued (page); + + /* number of completed packets in the page */ + npackets = ogg_page_packets (page); + if (!continued) { + /* page is not continued so it contains at least one packet start. It's + * possible that no packet ends on this page (npackets == 0). In that + * case, the next (continued) page(s) we kept contain the remainder of the + * packets. We mark npackets=1 to make us start decoding the pages in the + * remainder of the algorithm. */ + if (npackets == 0) + npackets = 1; + } + GST_LOG_OBJECT (ogg, "continued: %d, %d packets", continued, npackets); + + if (npackets == 0) { + GST_LOG_OBJECT (ogg, "no decodable packets, we need a previous page"); + goto done; + } + } + + if (ogg_stream_pagein (&pad->map.stream, page) != 0) + goto choked; + + /* flush all packets in the stream layer, this might not give a packet if + * the page had no packets finishing on the page (npackets == 0). */ + result = gst_ogg_pad_stream_out (pad, 0); + + if (pad->continued) { + ogg_packet packet; + + /* now send the continued pages to the stream layer */ + while (pad->continued) { + ogg_page *p = (ogg_page *) pad->continued->data; + + GST_LOG_OBJECT (ogg, "submitting continued page %p", p); + if (ogg_stream_pagein (&pad->map.stream, p) != 0) + goto choked; + + pad->continued = g_list_delete_link (pad->continued, pad->continued); + + /* free the page */ + gst_ogg_page_free (p); + } + + GST_LOG_OBJECT (ogg, "flushing last continued packet"); + /* flush 1 continued packet in the stream layer */ + result = gst_ogg_pad_stream_out (pad, 1); + + /* flush all remaining packets, we pushed them in the previous round. + * We don't use _reset() because we still want to get the discont when + * we submit a next page. */ + while (ogg_stream_packetout (&pad->map.stream, &packet) != 0); + } + +done: + /* keep continued pages (only in reverse mode) */ + if (continued) { + ogg_page *p = gst_ogg_page_copy (page); + + GST_LOG_OBJECT (ogg, "keeping continued page %p", p); + pad->continued = g_list_prepend (pad->continued, p); + } + + return result; + +choked: + { + GST_WARNING_OBJECT (ogg, + "ogg stream choked on page (serial %08lx), resetting stream", + pad->map.serialno); + gst_ogg_pad_reset (pad); + /* we continue to recover */ + return GST_FLOW_OK; + } +} + + +static GstOggChain * +gst_ogg_chain_new (GstOggDemux * ogg) +{ + GstOggChain *chain = g_new0 (GstOggChain, 1); + + GST_DEBUG_OBJECT (ogg, "creating new chain %p", chain); + chain->ogg = ogg; + chain->offset = -1; + chain->bytes = -1; + chain->have_bos = FALSE; + chain->streams = g_array_new (FALSE, TRUE, sizeof (GstOggPad *)); + chain->begin_time = GST_CLOCK_TIME_NONE; + chain->segment_start = GST_CLOCK_TIME_NONE; + chain->segment_stop = GST_CLOCK_TIME_NONE; + chain->total_time = GST_CLOCK_TIME_NONE; + + return chain; +} + +static void +gst_ogg_chain_free (GstOggChain * chain) +{ + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + gst_object_unref (pad); + } + g_array_free (chain->streams, TRUE); + g_free (chain); +} + +static void +gst_ogg_pad_mark_discont (GstOggPad * pad) +{ + pad->discont = TRUE; + pad->map.last_size = 0; +} + +static void +gst_ogg_chain_mark_discont (GstOggChain * chain) +{ + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + gst_ogg_pad_mark_discont (pad); + } +} + +static void +gst_ogg_chain_reset (GstOggChain * chain) +{ + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + gst_ogg_pad_reset (pad); + } +} + +static GstOggPad * +gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) +{ + GstOggPad *ret; + GstTagList *list; + gchar *name; + + GST_DEBUG_OBJECT (chain->ogg, "creating new stream %08lx in chain %p", + serialno, chain); + + ret = g_object_new (GST_TYPE_OGG_PAD, NULL); + /* we own this one */ + gst_object_ref (ret); + gst_object_sink (ret); + + GST_PAD_DIRECTION (ret) = GST_PAD_SRC; + gst_ogg_pad_mark_discont (ret); + + ret->chain = chain; + ret->ogg = chain->ogg; + + ret->map.serialno = serialno; + if (ogg_stream_init (&ret->map.stream, serialno) != 0) + goto init_failed; + + name = g_strdup_printf ("serial_%08lx", serialno); + gst_object_set_name (GST_OBJECT (ret), name); + g_free (name); + + /* FIXME: either do something with it or remove it */ + list = gst_tag_list_new (); + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_SERIAL, serialno, + NULL); + gst_tag_list_free (list); + + GST_DEBUG_OBJECT (chain->ogg, + "created new ogg src %p for stream with serial %08lx", ret, serialno); + + g_array_append_val (chain->streams, ret); + + return ret; + + /* ERRORS */ +init_failed: + { + GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.", + serialno); + gst_object_unref (ret); + return NULL; + } +} + +static GstOggPad * +gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno) +{ + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + if (pad->map.serialno == serialno) + return pad; + } + return NULL; +} + +static gboolean +gst_ogg_chain_has_stream (GstOggChain * chain, glong serialno) +{ + return gst_ogg_chain_get_stream (chain, serialno) != NULL; +} + +/* signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 + /* FILL ME */ +}; + +static GstStaticPadTemplate ogg_demux_src_template_factory = +GST_STATIC_PAD_TEMPLATE ("src_%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate ogg_demux_sink_template_factory = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/ogg; application/x-annodex") + ); + +static void gst_ogg_demux_finalize (GObject * object); + +static GstFlowReturn gst_ogg_demux_read_chain (GstOggDemux * ogg, + GstOggChain ** chain); +static GstFlowReturn gst_ogg_demux_read_end_chain (GstOggDemux * ogg, + GstOggChain * chain); + +static gboolean gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event); +static void gst_ogg_demux_loop (GstOggPad * pad); +static GstFlowReturn gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_ogg_demux_sink_activate (GstPad * sinkpad); +static gboolean gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, + gboolean active); +static gboolean gst_ogg_demux_sink_activate_push (GstPad * sinkpad, + gboolean active); +static GstStateChangeReturn gst_ogg_demux_change_state (GstElement * element, + GstStateChange transition); +static gboolean gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event); + +static void gst_ogg_print (GstOggDemux * demux); + +GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT); + +static void +gst_ogg_demux_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Ogg demuxer", "Codec/Demuxer", + "demux ogg streams (info about ogg: http://xiph.org)", + "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_demux_sink_template_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_demux_src_template_factory)); +} + +static void +gst_ogg_demux_class_init (GstOggDemuxClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gstelement_class->change_state = gst_ogg_demux_change_state; + gstelement_class->send_event = gst_ogg_demux_receive_event; + + gobject_class->finalize = gst_ogg_demux_finalize; +} + +static void +gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class) +{ + /* create the sink pad */ + ogg->sinkpad = + gst_pad_new_from_static_template (&ogg_demux_sink_template_factory, + "sink"); + + gst_pad_set_event_function (ogg->sinkpad, gst_ogg_demux_sink_event); + gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_demux_chain); + gst_pad_set_activate_function (ogg->sinkpad, gst_ogg_demux_sink_activate); + gst_pad_set_activatepull_function (ogg->sinkpad, + gst_ogg_demux_sink_activate_pull); + gst_pad_set_activatepush_function (ogg->sinkpad, + gst_ogg_demux_sink_activate_push); + gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad); + + ogg->chain_lock = g_mutex_new (); + ogg->chains = g_array_new (FALSE, TRUE, sizeof (GstOggChain *)); + + ogg->newsegment = NULL; +} + +static void +gst_ogg_demux_finalize (GObject * object) +{ + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (object); + + g_array_free (ogg->chains, TRUE); + g_mutex_free (ogg->chain_lock); + ogg_sync_clear (&ogg->sync); + + if (ogg->newsegment) + gst_event_unref (ogg->newsegment); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_ogg_demux_reset_streams (GstOggDemux * ogg) +{ + GstOggChain *chain; + guint i; + + chain = ogg->current_chain; + if (chain == NULL) + return; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i); + + stream->start_time = -1; + stream->map.accumulated_granule = 0; + } + ogg->building_chain = chain; + ogg->current_chain = NULL; + ogg->resync = TRUE; +} + +static gboolean +gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + res = gst_ogg_demux_send_event (ogg, event); + break; + case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (ogg, "got a flush stop event"); + ogg_sync_reset (&ogg->sync); + res = gst_ogg_demux_send_event (ogg, event); + gst_ogg_demux_reset_streams (ogg); + break; + case GST_EVENT_NEWSEGMENT: + GST_DEBUG_OBJECT (ogg, "got a new segment event"); + gst_event_unref (event); + res = TRUE; + break; + case GST_EVENT_EOS: + { + GST_DEBUG_OBJECT (ogg, "got an EOS event"); + res = gst_ogg_demux_send_event (ogg, event); + if (ogg->current_chain == NULL) { + GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), + ("can't get first chain")); + } + break; + } + default: + res = gst_ogg_demux_send_event (ogg, event); + break; + } + gst_object_unref (ogg); + + return res; +} + +/* submit the given buffer to the ogg sync */ +static GstFlowReturn +gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer) +{ + gint size; + guint8 *data; + gchar *oggbuffer; + GstFlowReturn ret = GST_FLOW_OK; + + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size); + if (G_UNLIKELY (size == 0)) + goto done; + + oggbuffer = ogg_sync_buffer (&ogg->sync, size); + if (G_UNLIKELY (oggbuffer == NULL)) + goto no_buffer; + + memcpy (oggbuffer, data, size); + if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0)) + goto write_failed; + +done: + gst_buffer_unref (buffer); + + return ret; + + /* ERRORS */ +no_buffer: + { + GST_ELEMENT_ERROR (ogg, STREAM, DECODE, + (NULL), ("failed to get ogg sync buffer")); + ret = GST_FLOW_ERROR; + goto done; + } +write_failed: + { + GST_ELEMENT_ERROR (ogg, STREAM, DECODE, + (NULL), ("failed to write %d bytes to the sync buffer", size)); + ret = GST_FLOW_ERROR; + goto done; + } +} + +/* in random access mode this code updates the current read position + * and resets the ogg sync buffer so that the next read will happen + * from this new location. + */ +static void +gst_ogg_demux_seek (GstOggDemux * ogg, gint64 offset) +{ + GST_LOG_OBJECT (ogg, "seeking to %" G_GINT64_FORMAT, offset); + + ogg->offset = offset; + ogg->read_offset = offset; + ogg_sync_reset (&ogg->sync); +} + +/* read more data from the current offset and submit to + * the ogg sync layer. + */ +static GstFlowReturn +gst_ogg_demux_get_data (GstOggDemux * ogg, gint64 end_offset) +{ + GstFlowReturn ret; + GstBuffer *buffer; + + GST_LOG_OBJECT (ogg, + "get data %" G_GINT64_FORMAT " %" G_GINT64_FORMAT " %" G_GINT64_FORMAT, + ogg->read_offset, ogg->length, end_offset); + + if (end_offset > 0 && ogg->read_offset >= end_offset) + goto boundary_reached; + + if (ogg->read_offset == ogg->length) + goto eos; + + ret = gst_pad_pull_range (ogg->sinkpad, ogg->read_offset, CHUNKSIZE, &buffer); + if (ret != GST_FLOW_OK) + goto error; + + ogg->read_offset += GST_BUFFER_SIZE (buffer); + + ret = gst_ogg_demux_submit_buffer (ogg, buffer); + + return ret; + + /* ERROR */ +boundary_reached: + { + GST_LOG_OBJECT (ogg, "reached boundary"); + return GST_FLOW_LIMIT; + } +eos: + { + GST_LOG_OBJECT (ogg, "reached EOS"); + return GST_FLOW_UNEXPECTED; + } +error: + { + GST_WARNING_OBJECT (ogg, "got %d (%s) from pull range", ret, + gst_flow_get_name (ret)); + return ret; + } +} + +/* Read the next page from the current offset. + * boundary: number of bytes ahead we allow looking for; + * -1 if no boundary + * + * @offset will contain the offset the next page starts at when this function + * returns GST_FLOW_OK. + * + * GST_FLOW_UNEXPECTED is returned on EOS. + * + * GST_FLOW_LIMIT is returned when we did not find a page before the + * boundary. If @boundary is -1, this is never returned. + * + * Any other error returned while retrieving data from the peer is returned as + * is. + */ +static GstFlowReturn +gst_ogg_demux_get_next_page (GstOggDemux * ogg, ogg_page * og, + gint64 boundary, gint64 * offset) +{ + gint64 end_offset = -1; + GstFlowReturn ret; + + GST_LOG_OBJECT (ogg, + "get next page, current offset %" G_GINT64_FORMAT ", bytes boundary %" + G_GINT64_FORMAT, ogg->offset, boundary); + + if (boundary >= 0) + end_offset = ogg->offset + boundary; + + while (TRUE) { + glong more; + + if (end_offset > 0 && ogg->offset >= end_offset) + goto boundary_reached; + + more = ogg_sync_pageseek (&ogg->sync, og); + + GST_LOG_OBJECT (ogg, "pageseek gave %ld", more); + + if (more < 0) { + /* skipped n bytes */ + ogg->offset -= more; + GST_LOG_OBJECT (ogg, "skipped %ld bytes, offset %" G_GINT64_FORMAT, + more, ogg->offset); + } else if (more == 0) { + /* we need more data */ + if (boundary == 0) + goto boundary_reached; + + GST_LOG_OBJECT (ogg, "need more data"); + ret = gst_ogg_demux_get_data (ogg, end_offset); + if (ret != GST_FLOW_OK) + break; + } else { + gint64 res_offset = ogg->offset; + + /* got a page. Return the offset at the page beginning, + advance the internal offset past the page end */ + if (offset) + *offset = res_offset; + ret = GST_FLOW_OK; + + ogg->offset += more; + + GST_LOG_OBJECT (ogg, + "got page at %" G_GINT64_FORMAT ", serial %08x, end at %" + G_GINT64_FORMAT ", granule %" G_GINT64_FORMAT, res_offset, + ogg_page_serialno (og), ogg->offset, + (gint64) ogg_page_granulepos (og)); + break; + } + } + GST_LOG_OBJECT (ogg, "returning %d", ret); + + return ret; + + /* ERRORS */ +boundary_reached: + { + GST_LOG_OBJECT (ogg, + "offset %" G_GINT64_FORMAT " >= end_offset %" G_GINT64_FORMAT, + ogg->offset, end_offset); + return GST_FLOW_LIMIT; + } +} + +/* from the current offset, find the previous page, seeking backwards + * until we find the page. + */ +static GstFlowReturn +gst_ogg_demux_get_prev_page (GstOggDemux * ogg, ogg_page * og, gint64 * offset) +{ + GstFlowReturn ret; + gint64 begin = ogg->offset; + gint64 end = begin; + gint64 cur_offset = -1; + + GST_LOG_OBJECT (ogg, "getting page before %" G_GINT64_FORMAT, begin); + + while (cur_offset == -1) { + begin -= CHUNKSIZE; + if (begin < 0) + begin = 0; + + /* seek CHUNKSIZE back */ + gst_ogg_demux_seek (ogg, begin); + + /* now continue reading until we run out of data, if we find a page + * start, we save it. It might not be the final page as there could be + * another page after this one. */ + while (ogg->offset < end) { + gint64 new_offset; + + ret = + gst_ogg_demux_get_next_page (ogg, og, end - ogg->offset, &new_offset); + /* we hit the upper limit, offset contains the last page start */ + if (ret == GST_FLOW_LIMIT) { + GST_LOG_OBJECT (ogg, "hit limit"); + break; + } + /* something went wrong */ + if (ret == GST_FLOW_UNEXPECTED) { + new_offset = 0; + GST_LOG_OBJECT (ogg, "got unexpected"); + } else if (ret != GST_FLOW_OK) { + GST_LOG_OBJECT (ogg, "got error %d", ret); + return ret; + } + + GST_LOG_OBJECT (ogg, "found page at %" G_GINT64_FORMAT, new_offset); + + /* offset is next page start */ + cur_offset = new_offset; + } + } + + GST_LOG_OBJECT (ogg, "found previous page at %" G_GINT64_FORMAT, cur_offset); + + /* we have the offset. Actually snork and hold the page now */ + gst_ogg_demux_seek (ogg, cur_offset); + ret = gst_ogg_demux_get_next_page (ogg, og, -1, NULL); + if (ret != GST_FLOW_OK) { + GST_WARNING_OBJECT (ogg, "can't get last page at %" G_GINT64_FORMAT, + cur_offset); + /* this shouldn't be possible */ + return ret; + } + + if (offset) + *offset = cur_offset; + + return ret; +} + +static gboolean +gst_ogg_demux_deactivate_current_chain (GstOggDemux * ogg) +{ + gint i; + GstOggChain *chain = ogg->current_chain; + + if (chain == NULL) + return TRUE; + + GST_DEBUG_OBJECT (ogg, "deactivating chain %p", chain); + + /* send EOS on all the pads */ + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + GstEvent *event; + + if (!pad->added) + continue; + + event = gst_event_new_eos (); + gst_event_set_seqnum (event, ogg->seqnum); + gst_pad_push_event (GST_PAD_CAST (pad), event); + + GST_DEBUG_OBJECT (ogg, "removing pad %" GST_PTR_FORMAT, pad); + + /* deactivate first */ + gst_pad_set_active (GST_PAD_CAST (pad), FALSE); + + gst_element_remove_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad)); + + pad->added = FALSE; + } + /* if we cannot seek back to the chain, we can destroy the chain + * completely */ + if (!ogg->pullmode) { + gst_ogg_chain_free (chain); + } + ogg->current_chain = NULL; + + return TRUE; +} + +GstCaps * +gst_ogg_demux_set_header_on_caps (GstOggDemux * ogg, GstCaps * caps, + GList * headers) +{ + GstStructure *structure; + GValue array = { 0 }; + + GST_LOG_OBJECT (ogg, "caps: %" GST_PTR_FORMAT, caps); + + if (G_UNLIKELY (!caps)) + return NULL; + if (G_UNLIKELY (!headers)) + return NULL; + + caps = gst_caps_make_writable (caps); + structure = gst_caps_get_structure (caps, 0); + + g_value_init (&array, GST_TYPE_ARRAY); + + while (headers) { + GValue value = { 0 }; + GstBuffer *buffer; + ogg_packet *op = headers->data; + g_assert (op); + buffer = gst_buffer_new_and_alloc (op->bytes); + memcpy (GST_BUFFER_DATA (buffer), op->packet, op->bytes); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_take_buffer (&value, buffer); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + headers = headers->next; + } + + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + GST_LOG_OBJECT (ogg, "here are the newly set caps: %" GST_PTR_FORMAT, caps); + + return caps; +} + +static gboolean +gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain, + GstEvent * event) +{ + gint i; + gint bitrate, idx_bitrate; + + g_return_val_if_fail (chain != NULL, FALSE); + + if (chain == ogg->current_chain) { + if (event) + gst_event_unref (event); + return TRUE; + } + + + GST_DEBUG_OBJECT (ogg, "activating chain %p", chain); + + bitrate = idx_bitrate = 0; + + /* first add the pads */ + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad; + + pad = g_array_index (chain->streams, GstOggPad *, i); + + if (pad->map.idx_bitrate) + idx_bitrate = MAX (idx_bitrate, pad->map.idx_bitrate); + + bitrate += pad->map.bitrate; + + /* mark discont */ + gst_ogg_pad_mark_discont (pad); + pad->last_ret = GST_FLOW_OK; + + if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL) + continue; + + GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad); + + /* activate first */ + gst_pad_set_active (GST_PAD_CAST (pad), TRUE); + + gst_element_add_pad (GST_ELEMENT (ogg), GST_PAD_CAST (pad)); + pad->added = TRUE; + } + /* prefer the index bitrate over the ones encoded in the streams */ + ogg->bitrate = (idx_bitrate ? idx_bitrate : bitrate); + + /* after adding the new pads, remove the old pads */ + gst_ogg_demux_deactivate_current_chain (ogg); + + ogg->current_chain = chain; + + /* we are finished now */ + gst_element_no_more_pads (GST_ELEMENT (ogg)); + + /* FIXME, must be sent from the streaming thread */ + if (event) { + gst_ogg_demux_send_event (ogg, event); + + gst_element_found_tags (GST_ELEMENT_CAST (ogg), + gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "Ogg", NULL)); + } + + GST_DEBUG_OBJECT (ogg, "starting chain"); + + /* then send out any headers and queued packets */ + for (i = 0; i < chain->streams->len; i++) { + GList *walk; + GstOggPad *pad; + + pad = g_array_index (chain->streams, GstOggPad *, i); + + /* FIXME also streaming thread */ + if (pad->map.taglist) { + GST_DEBUG_OBJECT (ogg, "pushing tags"); + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (ogg), + GST_PAD_CAST (pad), pad->map.taglist); + pad->map.taglist = NULL; + } + + /* Set headers on caps */ + pad->map.caps = + gst_ogg_demux_set_header_on_caps (ogg, pad->map.caps, pad->map.headers); + gst_pad_set_caps (GST_PAD_CAST (pad), pad->map.caps); + + GST_DEBUG_OBJECT (ogg, "pushing headers"); + /* push headers */ + for (walk = pad->map.headers; walk; walk = g_list_next (walk)) { + ogg_packet *p = walk->data; + + gst_ogg_demux_chain_peer (pad, p, TRUE); + } + + GST_DEBUG_OBJECT (ogg, "pushing queued buffers"); + /* push queued packets */ + for (walk = pad->map.queued; walk; walk = g_list_next (walk)) { + ogg_packet *p = walk->data; + + gst_ogg_demux_chain_peer (pad, p, TRUE); + _ogg_packet_free (p); + } + /* and free the queued buffers */ + g_list_free (pad->map.queued); + pad->map.queued = NULL; + } + return TRUE; +} + +static gboolean +do_binary_search (GstOggDemux * ogg, GstOggChain * chain, gint64 begin, + gint64 end, gint64 begintime, gint64 endtime, gint64 target, + gint64 * offset) +{ + gint64 best; + GstFlowReturn ret; + gint64 result = 0; + + best = begin; + + GST_DEBUG_OBJECT (ogg, + "chain offset %" G_GINT64_FORMAT ", end offset %" G_GINT64_FORMAT, + begin, end); + GST_DEBUG_OBJECT (ogg, + "chain begin time %" GST_TIME_FORMAT ", end time %" GST_TIME_FORMAT, + GST_TIME_ARGS (begintime), GST_TIME_ARGS (endtime)); + GST_DEBUG_OBJECT (ogg, "target %" GST_TIME_FORMAT, GST_TIME_ARGS (target)); + + /* perform the seek */ + while (begin < end) { + gint64 bisect; + + if ((end - begin < CHUNKSIZE) || (endtime == begintime)) { + bisect = begin; + } else { + /* take a (pretty decent) guess, avoiding overflow */ + gint64 rate = (end - begin) * GST_MSECOND / (endtime - begintime); + + bisect = (target - begintime) / GST_MSECOND * rate + begin - CHUNKSIZE; + + if (bisect <= begin) + bisect = begin; + GST_DEBUG_OBJECT (ogg, "Initial guess: %" G_GINT64_FORMAT, bisect); + } + gst_ogg_demux_seek (ogg, bisect); + + while (begin < end) { + ogg_page og; + + GST_DEBUG_OBJECT (ogg, + "after seek, bisect %" G_GINT64_FORMAT ", begin %" G_GINT64_FORMAT + ", end %" G_GINT64_FORMAT, bisect, begin, end); + + ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, &result); + GST_LOG_OBJECT (ogg, "looking for next page returned %" G_GINT64_FORMAT, + result); + + if (ret == GST_FLOW_LIMIT) { + /* we hit the upper limit, go back a bit */ + if (bisect <= begin + 1) { + end = begin; /* found it */ + } else { + if (bisect == 0) + goto seek_error; + + bisect -= CHUNKSIZE; + if (bisect <= begin) + bisect = begin + 1; + + gst_ogg_demux_seek (ogg, bisect); + } + } else if (ret == GST_FLOW_OK) { + /* found offset of next ogg page */ + gint64 granulepos; + GstClockTime granuletime; + GstOggPad *pad; + + /* get the granulepos */ + GST_LOG_OBJECT (ogg, "found next ogg page at %" G_GINT64_FORMAT, + result); + granulepos = ogg_page_granulepos (&og); + if (granulepos == -1) { + GST_LOG_OBJECT (ogg, "granulepos of next page is -1"); + continue; + } + + /* get the stream */ + pad = gst_ogg_chain_get_stream (chain, ogg_page_serialno (&og)); + if (pad == NULL || pad->map.is_skeleton) + continue; + + /* convert granulepos to time */ + granuletime = gst_ogg_stream_get_end_time_for_granulepos (&pad->map, + granulepos); + if (granuletime < pad->start_time) + continue; + + GST_LOG_OBJECT (ogg, "granulepos %" G_GINT64_FORMAT " maps to time %" + GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime)); + + granuletime -= pad->start_time; + granuletime += chain->begin_time; + + GST_DEBUG_OBJECT (ogg, + "found page with granule %" G_GINT64_FORMAT " and time %" + GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (granuletime)); + + if (granuletime < target) { + best = result; /* raw offset of packet with granulepos */ + begin = ogg->offset; /* raw offset of next page */ + begintime = granuletime; + + bisect = begin; /* *not* begin + 1 */ + } else { + if (bisect <= begin + 1) { + end = begin; /* found it */ + } else { + if (end == ogg->offset) { /* we're pretty close - we'd be stuck in */ + end = result; + bisect -= CHUNKSIZE; /* an endless loop otherwise. */ + if (bisect <= begin) + bisect = begin + 1; + gst_ogg_demux_seek (ogg, bisect); + } else { + end = result; + endtime = granuletime; + break; + } + } + } + } else + goto seek_error; + } + } + GST_DEBUG_OBJECT (ogg, "seeking to %" G_GINT64_FORMAT, best); + gst_ogg_demux_seek (ogg, best); + *offset = best; + + return TRUE; + + /* ERRORS */ +seek_error: + { + GST_DEBUG_OBJECT (ogg, "got a seek error"); + return FALSE; + } +} + +static gboolean +do_index_search (GstOggDemux * ogg, GstOggChain * chain, gint64 begin, + gint64 end, gint64 begintime, gint64 endtime, gint64 target, + gint64 * p_offset, gint64 * p_timestamp) +{ + guint i; + guint64 timestamp, offset; + guint64 r_timestamp, r_offset; + gboolean result = FALSE; + + target -= begintime; + + r_offset = -1; + r_timestamp = -1; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + timestamp = target; + if (gst_ogg_map_search_index (&pad->map, TRUE, ×tamp, &offset)) { + GST_INFO ("found %" G_GUINT64_FORMAT " at offset %" G_GUINT64_FORMAT, + timestamp, offset); + + if (r_offset == -1 || offset < r_offset) { + r_offset = offset; + r_timestamp = timestamp; + } + result |= TRUE; + } + } + + if (p_timestamp) + *p_timestamp = r_timestamp; + if (p_offset) + *p_offset = r_offset; + + return result; +} + +/* + * do seek to time @position, return FALSE or chain and TRUE + */ +static gboolean +gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment, + gboolean accurate, gboolean keyframe, GstOggChain ** rchain) +{ + guint64 position; + GstOggChain *chain = NULL; + gint64 begin, end; + gint64 begintime, endtime; + gint64 target, keytarget; + gint64 best; + gint64 total; + gint64 result = 0; + GstFlowReturn ret; + gint i, pending, len; + gboolean first_parsed_page = TRUE; + + position = segment->last_stop; + + /* first find the chain to search in */ + total = ogg->total_time; + if (ogg->chains->len == 0) + goto no_chains; + + for (i = ogg->chains->len - 1; i >= 0; i--) { + chain = g_array_index (ogg->chains, GstOggChain *, i); + total -= chain->total_time; + if (position >= total) + break; + } + + /* first step, locate page containing the required data */ + begin = chain->offset; + end = chain->end_offset; + begintime = chain->begin_time; + endtime = begintime + chain->total_time; + target = position - total + begintime; + + if (!do_binary_search (ogg, chain, begin, end, begintime, endtime, target, + &best)) + goto seek_error; + + /* second step: find pages for all streams, we use the keyframe_granule to keep + * track of which ones we saw. If we have seen a page for each stream we can + * calculate the positions of each keyframe. */ + GST_DEBUG_OBJECT (ogg, "find keyframes"); + len = pending = chain->streams->len; + + /* figure out where the keyframes are */ + keytarget = target; + + while (TRUE) { + ogg_page og; + gint64 granulepos; + GstOggPad *pad; + GstClockTime keyframe_time, granule_time; + + ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, &result); + GST_LOG_OBJECT (ogg, "looking for next page returned %" G_GINT64_FORMAT, + result); + if (ret == GST_FLOW_LIMIT) { + GST_LOG_OBJECT (ogg, "reached limit"); + break; + } else if (ret != GST_FLOW_OK) + goto seek_error; + + /* get the stream */ + pad = gst_ogg_chain_get_stream (chain, ogg_page_serialno (&og)); + if (pad == NULL) + continue; + + if (pad->map.is_skeleton) + goto next; + + granulepos = ogg_page_granulepos (&og); + if (granulepos == -1 || granulepos == 0) { + GST_LOG_OBJECT (ogg, "granulepos of next page is -1"); + continue; + } + + /* we only do this the first time we pass here */ + if (first_parsed_page) { + /* Now that we have a time reference from the page, we can check + * whether all streams still have pages from here on. + * + * This would be more elegant before the loop, but getting the page from + * there without breaking anything would be more costly */ + granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map, + granulepos); + for (i = 0; i < len; i++) { + GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i); + + if (stream == pad) + /* we already know we have at least one page (the current one) + * for this stream */ + continue; + + if (granule_time > stream->map.total_time) + /* we won't encounter any more pages of this stream, so we don't + * try finding a key frame for it */ + pending--; + } + first_parsed_page = FALSE; + } + + + /* in reverse we want to go past the page with the lower timestamp */ + if (segment->rate < 0.0) { + /* get time for this pad */ + granule_time = gst_ogg_stream_get_end_time_for_granulepos (&pad->map, + granulepos); + + GST_LOG_OBJECT (ogg, + "looking at page with ts %" GST_TIME_FORMAT ", target %" + GST_TIME_FORMAT, GST_TIME_ARGS (granule_time), + GST_TIME_ARGS (target)); + if (granule_time < target) + continue; + } + + /* we've seen this pad before */ + if (pad->keyframe_granule != -1) + continue; + + /* convert granule of this pad to the granule of the keyframe */ + pad->keyframe_granule = + gst_ogg_stream_granulepos_to_key_granule (&pad->map, granulepos); + GST_LOG_OBJECT (ogg, "marking stream granule %" G_GINT64_FORMAT, + pad->keyframe_granule); + + /* get time of the keyframe */ + keyframe_time = + gst_ogg_stream_granule_to_time (&pad->map, pad->keyframe_granule); + GST_LOG_OBJECT (ogg, "stream %08lx granule time %" GST_TIME_FORMAT, + pad->map.serialno, GST_TIME_ARGS (keyframe_time)); + + /* collect smallest value */ + if (keyframe_time != -1) { + keyframe_time += begintime; + if (keyframe_time < keytarget) + keytarget = keyframe_time; + } + + next: + pending--; + if (pending == 0) + break; + } + + /* for negative rates we will get to the keyframe backwards */ + if (segment->rate < 0.0) + goto done; + + if (keytarget != target) { + GST_LOG_OBJECT (ogg, "final seek to target %" GST_TIME_FORMAT, + GST_TIME_ARGS (keytarget)); + + /* last step, seek to the location of the keyframe */ + if (!do_binary_search (ogg, chain, begin, end, begintime, endtime, + keytarget, &best)) + goto seek_error; + } else { + /* seek back to previous position */ + GST_LOG_OBJECT (ogg, "keyframe on target"); + gst_ogg_demux_seek (ogg, best); + } + +done: + if (keyframe) { + if (segment->rate > 0.0) + segment->time = keytarget; + segment->last_stop = keytarget - begintime; + } + + *rchain = chain; + + return TRUE; + +no_chains: + { + GST_DEBUG_OBJECT (ogg, "no chains"); + return FALSE; + } +seek_error: + { + GST_DEBUG_OBJECT (ogg, "got a seek error"); + return FALSE; + } +} + +/* does not take ownership of the event */ +static gboolean +gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event) +{ + GstOggChain *chain = NULL; + gboolean res; + gboolean flush, accurate, keyframe; + GstFormat format; + gdouble rate; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + gint64 cur, stop; + gboolean update; + guint32 seqnum; + GstEvent *tevent; + + if (event) { + GST_DEBUG_OBJECT (ogg, "seek with event"); + + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + /* we can only seek on time */ + if (format != GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (ogg, "can only seek on TIME"); + goto error; + } + seqnum = gst_event_get_seqnum (event); + } else { + GST_DEBUG_OBJECT (ogg, "seek without event"); + + flags = 0; + rate = 1.0; + seqnum = gst_util_seqnum_next (); + } + + GST_DEBUG_OBJECT (ogg, "seek, rate %g", rate); + + flush = flags & GST_SEEK_FLAG_FLUSH; + accurate = flags & GST_SEEK_FLAG_ACCURATE; + keyframe = flags & GST_SEEK_FLAG_KEY_UNIT; + + /* first step is to unlock the streaming thread if it is + * blocked in a chain call, we do this by starting the flush. because + * we cannot yet hold any streaming lock, we have to protect the chains + * with their own lock. */ + if (flush) { + gint i; + + tevent = gst_event_new_flush_start (); + gst_event_set_seqnum (tevent, seqnum); + + gst_event_ref (tevent); + gst_pad_push_event (ogg->sinkpad, tevent); + + GST_CHAIN_LOCK (ogg); + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + gint j; + + for (j = 0; j < chain->streams->len; j++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, j); + + gst_event_ref (tevent); + gst_pad_push_event (GST_PAD (pad), tevent); + } + } + GST_CHAIN_UNLOCK (ogg); + + gst_event_unref (tevent); + } else { + gst_pad_pause_task (ogg->sinkpad); + } + + /* now grab the stream lock so that streaming cannot continue, for + * non flushing seeks when the element is in PAUSED this could block + * forever. */ + GST_PAD_STREAM_LOCK (ogg->sinkpad); + + if (ogg->segment_running && !flush) { + /* create the segment event to close the current segment */ + if ((chain = ogg->current_chain)) { + GstEvent *newseg; + gint64 chain_start = 0; + + if (chain->segment_start != GST_CLOCK_TIME_NONE) + chain_start = chain->segment_start; + + newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate, + GST_FORMAT_TIME, ogg->segment.start + chain_start, + ogg->segment.last_stop + chain_start, ogg->segment.time); + /* set the seqnum of the running segment */ + gst_event_set_seqnum (newseg, ogg->seqnum); + + /* send segment on old chain, FIXME, must be sent from streaming thread. */ + gst_ogg_demux_send_event (ogg, newseg); + } + } + + if (event) { + gst_segment_set_seek (&ogg->segment, rate, format, flags, + cur_type, cur, stop_type, stop, &update); + } + + GST_DEBUG_OBJECT (ogg, "segment positions set to %" GST_TIME_FORMAT "-%" + GST_TIME_FORMAT, GST_TIME_ARGS (ogg->segment.start), + GST_TIME_ARGS (ogg->segment.stop)); + + /* we need to stop flushing on the srcpad as we're going to use it + * next. We can do this as we have the STREAM lock now. */ + if (flush) { + tevent = gst_event_new_flush_stop (); + gst_event_set_seqnum (tevent, seqnum); + gst_pad_push_event (ogg->sinkpad, tevent); + } + + { + gint i; + + /* reset all ogg streams now, need to do this from within the lock to + * make sure the streaming thread is not messing with the stream */ + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + + gst_ogg_chain_reset (chain); + } + } + + /* for reverse we will already seek accurately */ + res = gst_ogg_demux_do_seek (ogg, &ogg->segment, accurate, keyframe, &chain); + + /* seek failed, make sure we continue the current chain */ + if (!res) { + GST_DEBUG_OBJECT (ogg, "seek failed"); + chain = ogg->current_chain; + } else { + GST_DEBUG_OBJECT (ogg, "seek success"); + } + + if (!chain) + goto no_chain; + + /* now we have a new position, prepare for streaming again */ + { + GstEvent *event; + gint64 stop; + gint64 start; + gint64 last_stop, begin_time; + + /* we have to send the flush to the old chain, not the new one */ + if (flush) { + tevent = gst_event_new_flush_stop (); + gst_event_set_seqnum (tevent, seqnum); + gst_ogg_demux_send_event (ogg, tevent); + } + + /* we need this to see how far inside the chain we need to start */ + if (chain->begin_time != GST_CLOCK_TIME_NONE) + begin_time = chain->begin_time; + else + begin_time = 0; + + /* segment.start gives the start over all chains, we calculate the amount + * of time into this chain we need to start */ + start = ogg->segment.start - begin_time; + if (chain->segment_start != GST_CLOCK_TIME_NONE) + start += chain->segment_start; + + if ((stop = ogg->segment.stop) == -1) + stop = ogg->segment.duration; + + /* segment.stop gives the stop time over all chains, calculate the amount of + * time we need to stop in this chain */ + if (stop != -1) { + if (stop > begin_time) + stop -= begin_time; + else + stop = 0; + stop += chain->segment_start; + /* we must stop when this chain ends and switch to the next chain to play + * the remainder of the segment. */ + stop = MIN (stop, chain->segment_stop); + } + + last_stop = ogg->segment.last_stop; + if (chain->segment_start != GST_CLOCK_TIME_NONE) + last_stop += chain->segment_start; + + /* create the segment event we are going to send out */ + if (ogg->segment.rate >= 0.0) + event = gst_event_new_new_segment (FALSE, ogg->segment.rate, + ogg->segment.format, last_stop, stop, ogg->segment.time); + else + event = gst_event_new_new_segment (FALSE, ogg->segment.rate, + ogg->segment.format, start, last_stop, ogg->segment.time); + + gst_event_set_seqnum (event, seqnum); + + if (chain != ogg->current_chain) { + /* switch to different chain, send segment on new chain */ + gst_ogg_demux_activate_chain (ogg, chain, event); + } else { + /* mark discont and send segment on current chain */ + gst_ogg_chain_mark_discont (chain); + /* This event should be sent from the streaming thread (sink pad task) */ + if (ogg->newsegment) + gst_event_unref (ogg->newsegment); + ogg->newsegment = event; + } + + /* notify start of new segment */ + if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) { + GstMessage *message; + + message = gst_message_new_segment_start (GST_OBJECT (ogg), + GST_FORMAT_TIME, ogg->segment.last_stop); + gst_message_set_seqnum (message, seqnum); + + gst_element_post_message (GST_ELEMENT (ogg), message); + } + + ogg->segment_running = TRUE; + ogg->seqnum = seqnum; + /* restart our task since it might have been stopped when we did the + * flush. */ + gst_pad_start_task (ogg->sinkpad, (GstTaskFunction) gst_ogg_demux_loop, + ogg->sinkpad); + } + + /* streaming can continue now */ + GST_PAD_STREAM_UNLOCK (ogg->sinkpad); + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (ogg, "seek failed"); + return FALSE; + } +no_chain: + { + GST_DEBUG_OBJECT (ogg, "no chain to seek in"); + GST_PAD_STREAM_UNLOCK (ogg->sinkpad); + return FALSE; + } +} + +static gboolean +gst_ogg_demux_perform_seek_push (GstOggDemux * ogg, GstEvent * event) +{ + gint bitrate; + gboolean res = TRUE; + GstFormat format; + gdouble rate; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + GstEvent *sevent; + GstOggChain *chain; + gint64 best, best_time; + + gst_event_parse_seek (event, &rate, &format, &flags, + &start_type, &start, &stop_type, &stop); + + if (format != GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (ogg, "can only seek on TIME"); + goto error; + } + + chain = ogg->current_chain; + if (!chain) + return FALSE; + + if (do_index_search (ogg, chain, 0, -1, 0, -1, start, &best, &best_time)) { + /* the index gave some result */ + GST_DEBUG_OBJECT (ogg, + "found offset %" G_GINT64_FORMAT " with time %" G_GUINT64_FORMAT, + best, best_time); + start = best; + } else if ((bitrate = ogg->bitrate) > 0) { + /* try with bitrate convert the seek positions to bytes */ + if (start_type != GST_SEEK_TYPE_NONE) { + start = gst_util_uint64_scale (start, bitrate, 8 * GST_SECOND); + } + if (stop_type != GST_SEEK_TYPE_NONE) { + stop = gst_util_uint64_scale (stop, bitrate, 8 * GST_SECOND); + } + } else { + /* we don't know */ + res = FALSE; + } + + if (res) { + GST_DEBUG_OBJECT (ogg, + "seeking to %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT, start, stop); + /* do seek */ + sevent = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + start_type, start, stop_type, stop); + + res = gst_pad_push_event (ogg->sinkpad, sevent); + } + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (ogg, "seek failed"); + return FALSE; + } +} + +static gboolean +gst_ogg_demux_perform_seek (GstOggDemux * ogg, GstEvent * event) +{ + gboolean res; + + if (ogg->pullmode) { + res = gst_ogg_demux_perform_seek_pull (ogg, event); + } else { + res = gst_ogg_demux_perform_seek_push (ogg, event); + } + return res; +} + + +/* finds each bitstream link one at a time using a bisection search + * (has to begin by knowing the offset of the lb's initial page). + * Recurses for each link so it can alloc the link storage after + * finding them all, then unroll and fill the cache at the same time + */ +static GstFlowReturn +gst_ogg_demux_bisect_forward_serialno (GstOggDemux * ogg, + gint64 begin, gint64 searched, gint64 end, GstOggChain * chain, glong m) +{ + gint64 endsearched = end; + gint64 next = end; + ogg_page og; + GstFlowReturn ret; + gint64 offset; + GstOggChain *nextchain; + + GST_LOG_OBJECT (ogg, + "bisect begin: %" G_GINT64_FORMAT ", searched: %" G_GINT64_FORMAT + ", end %" G_GINT64_FORMAT ", chain: %p", begin, searched, end, chain); + + /* the below guards against garbage seperating the last and + * first pages of two links. */ + while (searched < endsearched) { + gint64 bisect; + + if (endsearched - searched < CHUNKSIZE) { + bisect = searched; + } else { + bisect = (searched + endsearched) / 2; + } + + gst_ogg_demux_seek (ogg, bisect); + ret = gst_ogg_demux_get_next_page (ogg, &og, -1, &offset); + + if (ret == GST_FLOW_UNEXPECTED) { + endsearched = bisect; + } else if (ret == GST_FLOW_OK) { + glong serial = ogg_page_serialno (&og); + + if (!gst_ogg_chain_has_stream (chain, serial)) { + endsearched = bisect; + next = offset; + } else { + searched = offset + og.header_len + og.body_len; + } + } else + return ret; + } + + GST_LOG_OBJECT (ogg, "current chain ends at %" G_GINT64_FORMAT, searched); + + chain->end_offset = searched; + ret = gst_ogg_demux_read_end_chain (ogg, chain); + if (ret != GST_FLOW_OK) + return ret; + + GST_LOG_OBJECT (ogg, "found begin at %" G_GINT64_FORMAT, next); + + gst_ogg_demux_seek (ogg, next); + ret = gst_ogg_demux_read_chain (ogg, &nextchain); + if (ret == GST_FLOW_UNEXPECTED) { + nextchain = NULL; + ret = GST_FLOW_OK; + GST_LOG_OBJECT (ogg, "no next chain"); + } else if (ret != GST_FLOW_OK) + goto done; + + if (searched < end && nextchain != NULL) { + ret = gst_ogg_demux_bisect_forward_serialno (ogg, next, ogg->offset, + end, nextchain, m + 1); + if (ret != GST_FLOW_OK) + goto done; + } + GST_LOG_OBJECT (ogg, "adding chain %p", chain); + + g_array_insert_val (ogg->chains, 0, chain); + +done: + return ret; +} + +/* read a chain from the ogg file. This code will + * read all BOS pages and will create and return a GstOggChain + * structure with the results. + * + * This function will also read N pages from each stream in the + * chain and submit them to the decoders. When the decoder has + * decoded the first buffer, we know the timestamp of the first + * page in the chain. + */ +static GstFlowReturn +gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) +{ + GstFlowReturn ret; + GstOggChain *chain = NULL; + gint64 offset = ogg->offset; + ogg_page op; + gboolean done; + gint i; + + GST_LOG_OBJECT (ogg, "reading chain at %" G_GINT64_FORMAT, offset); + + /* first read the BOS pages, do typefind on them, create + * the decoders, send data to the decoders. */ + while (TRUE) { + GstOggPad *pad; + glong serial; + + ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL); + if (ret != GST_FLOW_OK) { + GST_WARNING_OBJECT (ogg, "problem reading BOS page: ret=%d", ret); + break; + } + if (!ogg_page_bos (&op)) { + GST_WARNING_OBJECT (ogg, "page is not BOS page"); + /* if we did not find a chain yet, assume this is a bogus stream and + * ignore it */ + if (!chain) + ret = GST_FLOW_UNEXPECTED; + break; + } + + if (chain == NULL) { + chain = gst_ogg_chain_new (ogg); + chain->offset = offset; + } + + serial = ogg_page_serialno (&op); + if (gst_ogg_chain_get_stream (chain, serial) != NULL) { + GST_WARNING_OBJECT (ogg, "found serial %08lx BOS page twice, ignoring", + serial); + continue; + } + + pad = gst_ogg_chain_new_stream (chain, serial); + gst_ogg_pad_submit_page (pad, &op); + } + + if (ret != GST_FLOW_OK || chain == NULL) { + if (ret == GST_FLOW_OK) { + GST_WARNING_OBJECT (ogg, "no chain was found"); + ret = GST_FLOW_ERROR; + } else if (ret != GST_FLOW_UNEXPECTED) { + GST_WARNING_OBJECT (ogg, "failed to read chain"); + } else { + GST_DEBUG_OBJECT (ogg, "done reading chains"); + } + if (chain) { + gst_ogg_chain_free (chain); + } + if (res_chain) + *res_chain = NULL; + return ret; + } + + chain->have_bos = TRUE; + GST_LOG_OBJECT (ogg, "read bos pages, init decoder now"); + + /* now read pages until we receive a buffer from each of the + * stream decoders, this will tell us the timestamp of the + * first packet in the chain then */ + + /* save the offset to the first non bos page in the chain: if searching for + * pad->first_time we read past the end of the chain, we'll seek back to this + * position + */ + offset = ogg->offset; + + done = FALSE; + while (!done) { + glong serial; + gboolean known_serial = FALSE; + GstFlowReturn ret; + + serial = ogg_page_serialno (&op); + done = TRUE; + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + GST_LOG_OBJECT (ogg, "serial %08lx time %" GST_TIME_FORMAT, + pad->map.serialno, GST_TIME_ARGS (pad->start_time)); + + if (pad->map.serialno == serial) { + known_serial = TRUE; + + /* submit the page now, this will fill in the start_time when the + * internal decoder finds it */ + gst_ogg_pad_submit_page (pad, &op); + + if (!pad->map.is_skeleton && pad->start_time == -1 + && ogg_page_eos (&op)) { + /* got EOS on a pad before we could find its start_time. + * We have no chance of finding a start_time for every pad so + * stop searching for the other start_time(s). + */ + done = TRUE; + break; + } + } + /* the timestamp will be filled in when we submit the pages */ + if (!pad->map.is_sparse) + done &= (pad->start_time != GST_CLOCK_TIME_NONE); + + GST_LOG_OBJECT (ogg, "done %08lx now %d", pad->map.serialno, done); + } + + /* we read a page not belonging to the current chain: seek back to the + * beginning of the chain + */ + if (!known_serial) { + GST_LOG_OBJECT (ogg, "unknown serial %08lx", serial); + gst_ogg_demux_seek (ogg, offset); + break; + } + + if (!done) { + ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL); + if (ret != GST_FLOW_OK) + break; + } + } + GST_LOG_OBJECT (ogg, "done reading chain"); + /* now we can fill in the missing info using queries */ + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + if (pad->map.is_skeleton) + continue; + + pad->mode = GST_OGG_PAD_MODE_STREAMING; + } + + if (res_chain) + *res_chain = chain; + + return GST_FLOW_OK; +} + +/* read the last pages from the ogg stream to get the final + * page end_offsets. + */ +static GstFlowReturn +gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain) +{ + gint64 begin = chain->end_offset; + gint64 end = begin; + gint64 last_granule = -1; + GstOggPad *last_pad = NULL; + GstFlowReturn ret; + gboolean done = FALSE; + ogg_page og; + gint i; + + while (!done) { + begin -= CHUNKSIZE; + if (begin < 0) + begin = 0; + + gst_ogg_demux_seek (ogg, begin); + + /* now continue reading until we run out of data, if we find a page + * start, we save it. It might not be the final page as there could be + * another page after this one. */ + while (ogg->offset < end) { + ret = gst_ogg_demux_get_next_page (ogg, &og, end - ogg->offset, NULL); + + if (ret == GST_FLOW_LIMIT) + break; + if (ret != GST_FLOW_OK) + return ret; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + if (pad->map.is_sparse) + continue; + + if (pad->map.serialno == ogg_page_serialno (&og)) { + gint64 granulepos = ogg_page_granulepos (&og); + + if (granulepos != -1) { + last_granule = granulepos; + last_pad = pad; + done = TRUE; + } + break; + } + } + } + } + + if (last_pad) { + chain->segment_stop = + gst_ogg_stream_get_end_time_for_granulepos (&last_pad->map, + last_granule); + } else { + chain->segment_stop = GST_CLOCK_TIME_NONE; + } + + GST_INFO ("segment stop %" G_GUINT64_FORMAT, chain->segment_stop); + + return GST_FLOW_OK; +} + +/* find a pad with a given serial number + */ +static GstOggPad * +gst_ogg_demux_find_pad (GstOggDemux * ogg, glong serialno) +{ + GstOggPad *pad; + gint i; + + /* first look in building chain if any */ + if (ogg->building_chain) { + pad = gst_ogg_chain_get_stream (ogg->building_chain, serialno); + if (pad) + return pad; + } + + /* then look in current chain if any */ + if (ogg->current_chain) { + pad = gst_ogg_chain_get_stream (ogg->current_chain, serialno); + if (pad) + return pad; + } + + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + + pad = gst_ogg_chain_get_stream (chain, serialno); + if (pad) + return pad; + } + return NULL; +} + +/* find a chain with a given serial number + */ +static GstOggChain * +gst_ogg_demux_find_chain (GstOggDemux * ogg, glong serialno) +{ + GstOggPad *pad; + + pad = gst_ogg_demux_find_pad (ogg, serialno); + if (pad) { + return pad->chain; + } + return NULL; +} + +/* returns TRUE if all streams have valid start time */ +static gboolean +gst_ogg_demux_collect_chain_info (GstOggDemux * ogg, GstOggChain * chain) +{ + gboolean res = TRUE; + + chain->total_time = GST_CLOCK_TIME_NONE; + GST_DEBUG_OBJECT (ogg, "trying to collect chain info"); + + /* see if we have a start time on all streams */ + chain->segment_start = gst_ogg_demux_collect_start_time (ogg, chain); + + if (chain->segment_start == G_MAXUINT64) { + /* not yet, stream some more data */ + res = FALSE; + } else if (chain->segment_stop != GST_CLOCK_TIME_NONE) { + /* we can calculate a total time */ + chain->total_time = chain->segment_stop - chain->segment_start; + } + + GST_DEBUG ("total time %" G_GUINT64_FORMAT, chain->total_time); + + GST_DEBUG_OBJECT (ogg, "return %d", res); + + return res; +} + +static void +gst_ogg_demux_collect_info (GstOggDemux * ogg) +{ + gint i; + + /* collect all info */ + ogg->total_time = 0; + + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + + chain->begin_time = ogg->total_time; + + gst_ogg_demux_collect_chain_info (ogg, chain); + + ogg->total_time += chain->total_time; + } + gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time); +} + +/* find all the chains in the ogg file, this reads the first and + * last page of the ogg stream, if they match then the ogg file has + * just one chain, else we do a binary search for all chains. + */ +static GstFlowReturn +gst_ogg_demux_find_chains (GstOggDemux * ogg) +{ + ogg_page og; + GstPad *peer; + GstFormat format; + gboolean res; + gulong serialno; + GstOggChain *chain; + GstFlowReturn ret; + + /* get peer to figure out length */ + if ((peer = gst_pad_get_peer (ogg->sinkpad)) == NULL) + goto no_peer; + + /* find length to read last page, we store this for later use. */ + format = GST_FORMAT_BYTES; + res = gst_pad_query_duration (peer, &format, &ogg->length); + gst_object_unref (peer); + if (!res || ogg->length <= 0) + goto no_length; + + GST_DEBUG_OBJECT (ogg, "file length %" G_GINT64_FORMAT, ogg->length); + + /* read chain from offset 0, this is the first chain of the + * ogg file. */ + gst_ogg_demux_seek (ogg, 0); + ret = gst_ogg_demux_read_chain (ogg, &chain); + if (ret != GST_FLOW_OK) + goto no_first_chain; + + /* read page from end offset, we use this page to check if its serial + * number is contained in the first chain. If this is the case then + * this ogg is not a chained ogg and we can skip the scanning. */ + gst_ogg_demux_seek (ogg, ogg->length); + ret = gst_ogg_demux_get_prev_page (ogg, &og, NULL); + if (ret != GST_FLOW_OK) + goto no_last_page; + + serialno = ogg_page_serialno (&og); + + if (!gst_ogg_chain_has_stream (chain, serialno)) { + /* the last page is not in the first stream, this means we should + * find all the chains in this chained ogg. */ + ret = + gst_ogg_demux_bisect_forward_serialno (ogg, 0, 0, ogg->length, chain, + 0); + } else { + /* we still call this function here but with an empty range so that + * we can reuse the setup code in this routine. */ + ret = + gst_ogg_demux_bisect_forward_serialno (ogg, 0, ogg->length, + ogg->length, chain, 0); + } + if (ret != GST_FLOW_OK) + goto done; + + /* all fine, collect and print */ + gst_ogg_demux_collect_info (ogg); + + /* dump our chains and streams */ + gst_ogg_print (ogg); + +done: + return ret; + + /*** error cases ***/ +no_peer: + { + GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("we don't have a peer")); + return GST_FLOW_NOT_LINKED; + } +no_length: + { + GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get file length")); + return GST_FLOW_NOT_SUPPORTED; + } +no_first_chain: + { + GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), ("can't get first chain")); + return GST_FLOW_ERROR; + } +no_last_page: + { + GST_DEBUG_OBJECT (ogg, "can't get last page"); + if (chain) + gst_ogg_chain_free (chain); + return ret; + } +} + +static GstFlowReturn +gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) +{ + GstOggPad *pad; + gint64 granule; + glong serialno; + GstFlowReturn result = GST_FLOW_OK; + + serialno = ogg_page_serialno (page); + granule = ogg_page_granulepos (page); + + GST_LOG_OBJECT (ogg, + "processing ogg page (serial %08lx, pageno %ld, granulepos %" + G_GINT64_FORMAT ", bos %d)", + serialno, ogg_page_pageno (page), granule, ogg_page_bos (page)); + + if (ogg_page_bos (page)) { + GstOggChain *chain; + + /* first page */ + /* see if we know about the chain already */ + chain = gst_ogg_demux_find_chain (ogg, serialno); + if (chain) { + GstEvent *event; + gint64 start = 0; + + if (chain->segment_start != GST_CLOCK_TIME_NONE) + start = chain->segment_start; + + /* create the newsegment event we are going to send out */ + event = gst_event_new_new_segment (FALSE, ogg->segment.rate, + GST_FORMAT_TIME, start, chain->segment_stop, chain->begin_time); + gst_event_set_seqnum (event, ogg->seqnum); + + GST_DEBUG_OBJECT (ogg, + "segment: start %" GST_TIME_FORMAT ", stop %" GST_TIME_FORMAT + ", time %" GST_TIME_FORMAT, GST_TIME_ARGS (start), + GST_TIME_ARGS (chain->segment_stop), + GST_TIME_ARGS (chain->begin_time)); + + /* activate it as it means we have a non-header, this will also deactivate + * the currently running chain. */ + gst_ogg_demux_activate_chain (ogg, chain, event); + pad = gst_ogg_demux_find_pad (ogg, serialno); + } else { + GstClockTime chain_time; + gint64 current_time; + + /* this can only happen in push mode */ + if (ogg->pullmode) + goto unknown_chain; + + current_time = ogg->segment.last_stop; + + /* time of new chain is current time */ + chain_time = current_time; + + if (ogg->building_chain == NULL) { + GstOggChain *newchain; + + newchain = gst_ogg_chain_new (ogg); + newchain->offset = 0; + /* set new chain begin time aligned with end time of old chain */ + newchain->begin_time = chain_time; + GST_DEBUG_OBJECT (ogg, "new chain, begin time %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain_time)); + + /* and this is the one we are building now */ + ogg->building_chain = newchain; + } + pad = gst_ogg_chain_new_stream (ogg->building_chain, serialno); + } + } else { + pad = gst_ogg_demux_find_pad (ogg, serialno); + } + if (pad) { + result = gst_ogg_pad_submit_page (pad, page); + } else { + /* no pad. This means an ogg page without bos has been seen for this + * serialno. we just ignore it but post a warning... */ + GST_ELEMENT_WARNING (ogg, STREAM, DECODE, + (NULL), ("unknown ogg pad for serial %08lx detected", serialno)); + return GST_FLOW_OK; + } + return result; + + /* ERRORS */ +unknown_chain: + { + GST_ELEMENT_ERROR (ogg, STREAM, DECODE, + (NULL), ("unknown ogg chain for serial %08lx detected", serialno)); + return GST_FLOW_ERROR; + } +} + +/* streaming mode, receive a buffer, parse it, create pads for + * the serialno, submit pages and packets to the oggpads + */ +static GstFlowReturn +gst_ogg_demux_chain (GstPad * pad, GstBuffer * buffer) +{ + GstOggDemux *ogg; + gint ret = 0; + GstFlowReturn result = GST_FLOW_OK; + + ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad)); + + GST_DEBUG_OBJECT (ogg, "chain"); + result = gst_ogg_demux_submit_buffer (ogg, buffer); + + while (result == GST_FLOW_OK) { + ogg_page page; + + ret = ogg_sync_pageout (&ogg->sync, &page); + if (ret == 0) + /* need more data */ + break; + if (ret == -1) { + /* discontinuity in the pages */ + GST_DEBUG_OBJECT (ogg, "discont in page found, continuing"); + } else { + result = gst_ogg_demux_handle_page (ogg, &page); + } + } + if (ret == 0 || result == GST_FLOW_OK) { + gst_ogg_demux_sync_streams (ogg); + } + return result; +} + +static gboolean +gst_ogg_demux_send_event (GstOggDemux * ogg, GstEvent * event) +{ + GstOggChain *chain = ogg->current_chain; + gboolean res = TRUE; + + if (chain) { + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); + + gst_event_ref (event); + GST_DEBUG_OBJECT (pad, "Pushing event %" GST_PTR_FORMAT, event); + res &= gst_pad_push_event (GST_PAD (pad), event); + } + } + gst_event_unref (event); + + return res; +} + +static GstFlowReturn +gst_ogg_demux_combine_flows (GstOggDemux * ogg, GstOggPad * pad, + GstFlowReturn ret) +{ + GstOggChain *chain; + + /* store the value */ + pad->last_ret = ret; + + /* any other error that is not-linked can be returned right + * away */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + + /* only return NOT_LINKED if all other pads returned NOT_LINKED */ + chain = ogg->current_chain; + if (chain) { + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *opad = g_array_index (chain->streams, GstOggPad *, i); + + ret = opad->last_ret; + /* some other return value (must be SUCCESS but we can return + * other values as well) */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + } + /* if we get here, all other pads were unlinked and we return + * NOT_LINKED then */ + } +done: + return ret; +} + +/* returns TRUE if all streams in current chain reached EOS, FALSE otherwise */ +static gboolean +gst_ogg_demux_check_eos (GstOggDemux * ogg) +{ + GstOggChain *chain; + gboolean eos = TRUE; + + chain = ogg->current_chain; + if (G_LIKELY (chain)) { + gint i; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *opad = g_array_index (chain->streams, GstOggPad *, i); + + eos = eos && opad->is_eos; + } + } else { + eos = FALSE; + } + + return eos; +} + +static GstFlowReturn +gst_ogg_demux_loop_forward (GstOggDemux * ogg) +{ + GstFlowReturn ret; + GstBuffer *buffer; + + if (ogg->offset == ogg->length) { + GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT + " == %" G_GINT64_FORMAT, ogg->offset, ogg->length); + ret = GST_FLOW_UNEXPECTED; + goto done; + } + + GST_LOG_OBJECT (ogg, "pull data %" G_GINT64_FORMAT, ogg->offset); + ret = gst_pad_pull_range (ogg->sinkpad, ogg->offset, CHUNKSIZE, &buffer); + if (ret != GST_FLOW_OK) { + GST_LOG_OBJECT (ogg, "Failed pull_range"); + goto done; + } + + ogg->offset += GST_BUFFER_SIZE (buffer); + + if (G_UNLIKELY (ogg->newsegment)) { + gst_ogg_demux_send_event (ogg, ogg->newsegment); + ogg->newsegment = NULL; + } + + ret = gst_ogg_demux_chain (ogg->sinkpad, buffer); + if (ret != GST_FLOW_OK) { + GST_LOG_OBJECT (ogg, "Failed demux_chain"); + goto done; + } + + /* check for the end of the segment */ + if (gst_ogg_demux_check_eos (ogg)) { + GST_LOG_OBJECT (ogg, "got EOS"); + ret = GST_FLOW_UNEXPECTED; + goto done; + } +done: + return ret; +} + +/* reverse mode. + * + * We read the pages backwards and send the packets forwards. The first packet + * in the page will be pushed with the DISCONT flag set. + * + * Special care has to be taken for continued pages, which we can only decode + * when we have the previous page(s). + */ +static GstFlowReturn +gst_ogg_demux_loop_reverse (GstOggDemux * ogg) +{ + GstFlowReturn ret; + ogg_page page; + gint64 offset; + + if (ogg->offset == 0) { + GST_LOG_OBJECT (ogg, "no more data to pull %" G_GINT64_FORMAT + " == 0", ogg->offset); + ret = GST_FLOW_UNEXPECTED; + goto done; + } + + GST_LOG_OBJECT (ogg, "read page from %" G_GINT64_FORMAT, ogg->offset); + ret = gst_ogg_demux_get_prev_page (ogg, &page, &offset); + if (ret != GST_FLOW_OK) + goto done; + + ogg->offset = offset; + + if (G_UNLIKELY (ogg->newsegment)) { + gst_ogg_demux_send_event (ogg, ogg->newsegment); + ogg->newsegment = NULL; + } + + ret = gst_ogg_demux_handle_page (ogg, &page); + if (ret != GST_FLOW_OK) + goto done; + + /* check for the end of the segment */ + if (gst_ogg_demux_check_eos (ogg)) { + GST_LOG_OBJECT (ogg, "got EOS"); + ret = GST_FLOW_UNEXPECTED; + goto done; + } +done: + return ret; +} + +static void +gst_ogg_demux_sync_streams (GstOggDemux * ogg) +{ + GstClockTime cur; + GstOggChain *chain; + guint i; + + chain = ogg->current_chain; + cur = ogg->segment.last_stop; + if (chain == NULL || cur == -1) + return; + + for (i = 0; i < chain->streams->len; i++) { + GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, i); + + /* Theoretically, we should be doing this for all streams, but we're only + * doing it for known-to-be-sparse streams at the moment in order not to + * break things for wrongly-muxed streams (like we used to produce once) */ + if (stream->map.is_sparse && stream->last_stop != GST_CLOCK_TIME_NONE) { + + /* Does this stream lag? Random threshold of 2 seconds */ + if (GST_CLOCK_DIFF (stream->last_stop, cur) > (2 * GST_SECOND)) { + GST_DEBUG_OBJECT (stream, "synchronizing stream with others by " + "advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->last_stop), GST_TIME_ARGS (cur)); + stream->last_stop = cur; + /* advance stream time (FIXME: is this right, esp. time_pos?) */ + gst_pad_push_event (GST_PAD_CAST (stream), + gst_event_new_new_segment (TRUE, ogg->segment.rate, + GST_FORMAT_TIME, stream->last_stop, -1, stream->last_stop)); + } + } + } +} + +/* random access code + * + * - first find all the chains and streams by scanning the file. + * - then get and chain buffers, just like the streaming case. + * - when seeking, we can use the chain info to perform the seek. + */ +static void +gst_ogg_demux_loop (GstOggPad * pad) +{ + GstOggDemux *ogg; + GstFlowReturn ret; + GstEvent *event; + + ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (pad)); + + if (ogg->need_chains) { + gboolean res; + + /* this is the only place where we write chains and thus need to lock. */ + GST_CHAIN_LOCK (ogg); + ret = gst_ogg_demux_find_chains (ogg); + GST_CHAIN_UNLOCK (ogg); + if (ret != GST_FLOW_OK) + goto chain_read_failed; + + ogg->need_chains = FALSE; + + GST_OBJECT_LOCK (ogg); + ogg->running = TRUE; + event = ogg->event; + ogg->event = NULL; + GST_OBJECT_UNLOCK (ogg); + + /* and seek to configured positions without FLUSH */ + res = gst_ogg_demux_perform_seek_pull (ogg, event); + if (event) + gst_event_unref (event); + + if (!res) + goto seek_failed; + } + + if (ogg->segment.rate >= 0.0) + ret = gst_ogg_demux_loop_forward (ogg); + else + ret = gst_ogg_demux_loop_reverse (ogg); + + if (ret != GST_FLOW_OK) + goto pause; + + gst_ogg_demux_sync_streams (ogg); + return; + + /* ERRORS */ +chain_read_failed: + { + /* error was posted */ + goto pause; + } +seek_failed: + { + GST_ELEMENT_ERROR (ogg, STREAM, DEMUX, (NULL), + ("failed to start demuxing ogg")); + ret = GST_FLOW_ERROR; + goto pause; + } +pause: + { + const gchar *reason = gst_flow_get_name (ret); + GstEvent *event = NULL; + + GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason); + ogg->segment_running = FALSE; + gst_pad_pause_task (ogg->sinkpad); + + if (ret == GST_FLOW_UNEXPECTED) { + /* perform EOS logic */ + if (ogg->segment.flags & GST_SEEK_FLAG_SEGMENT) { + gint64 stop; + GstMessage *message; + + /* for segment playback we need to post when (in stream time) + * we stopped, this is either stop (when set) or the duration. */ + if ((stop = ogg->segment.stop) == -1) + stop = ogg->segment.duration; + + GST_LOG_OBJECT (ogg, "Sending segment done, at end of segment"); + message = + gst_message_new_segment_done (GST_OBJECT (ogg), GST_FORMAT_TIME, + stop); + gst_message_set_seqnum (message, ogg->seqnum); + + gst_element_post_message (GST_ELEMENT (ogg), message); + } else { + /* normal playback, send EOS to all linked pads */ + GST_LOG_OBJECT (ogg, "Sending EOS, at end of stream"); + event = gst_event_new_eos (); + } + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) { + GST_ELEMENT_ERROR (ogg, STREAM, FAILED, + (_("Internal data stream error.")), + ("stream stopped, reason %s", reason)); + event = gst_event_new_eos (); + } + + /* For wrong-state we still want to pause the task and stop + * but no error message or other things are necessary. + * wrong-state is no real error and will be caused by flushing, + * e.g. because of a flushing seek. + */ + if (event) { + gst_event_set_seqnum (event, ogg->seqnum); + gst_ogg_demux_send_event (ogg, event); + } + return; + } +} + +static void +gst_ogg_demux_clear_chains (GstOggDemux * ogg) +{ + gint i; + + gst_ogg_demux_deactivate_current_chain (ogg); + + GST_CHAIN_LOCK (ogg); + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + + gst_ogg_chain_free (chain); + } + ogg->chains = g_array_set_size (ogg->chains, 0); + GST_CHAIN_UNLOCK (ogg); +} + +/* this function is called when the pad is activated and should start + * processing data. + * + * We check if we can do random access to decide if we work push or + * pull based. + */ +static gboolean +gst_ogg_demux_sink_activate (GstPad * sinkpad) +{ + if (gst_pad_check_pull_range (sinkpad)) { + GST_DEBUG_OBJECT (sinkpad, "activating pull"); + return gst_pad_activate_pull (sinkpad, TRUE); + } else { + GST_DEBUG_OBJECT (sinkpad, "activating push"); + return gst_pad_activate_push (sinkpad, TRUE); + } +} + +/* this function gets called when we activate ourselves in push mode. + * We cannot seek (ourselves) in the stream */ +static gboolean +gst_ogg_demux_sink_activate_push (GstPad * sinkpad, gboolean active) +{ + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad)); + + ogg->pullmode = FALSE; + ogg->resync = FALSE; + + return TRUE; +} + +/* this function gets called when we activate ourselves in pull mode. + * We can perform random access to the resource and we start a task + * to start reading */ +static gboolean +gst_ogg_demux_sink_activate_pull (GstPad * sinkpad, gboolean active) +{ + GstOggDemux *ogg; + + ogg = GST_OGG_DEMUX (GST_OBJECT_PARENT (sinkpad)); + + if (active) { + ogg->need_chains = TRUE; + ogg->pullmode = TRUE; + + return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_ogg_demux_loop, + sinkpad); + } else { + return gst_pad_stop_task (sinkpad); + } +} + +static GstStateChangeReturn +gst_ogg_demux_change_state (GstElement * element, GstStateChange transition) +{ + GstOggDemux *ogg; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + + ogg = GST_OGG_DEMUX (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + ogg->basetime = 0; + ogg_sync_init (&ogg->sync); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + ogg_sync_reset (&ogg->sync); + ogg->running = FALSE; + ogg->bitrate = 0; + ogg->segment_running = FALSE; + ogg->total_time = -1; + gst_segment_init (&ogg->segment, GST_FORMAT_TIME); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_ogg_demux_clear_chains (ogg); + GST_OBJECT_LOCK (ogg); + ogg->running = FALSE; + ogg->segment_running = FALSE; + GST_OBJECT_UNLOCK (ogg); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + ogg_sync_clear (&ogg->sync); + break; + default: + break; + } + return result; +} + +gboolean +gst_ogg_demux_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_debug, "oggdemux", 0, "ogg demuxer"); + GST_DEBUG_CATEGORY_INIT (gst_ogg_demux_setup_debug, "oggdemux_setup", 0, + "ogg demuxer setup stage when parsing pipeline"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + return gst_element_register (plugin, "oggdemux", GST_RANK_PRIMARY, + GST_TYPE_OGG_DEMUX); +} + +/* prints all info about the element */ +#undef GST_CAT_DEFAULT +#define GST_CAT_DEFAULT gst_ogg_demux_setup_debug + +#ifdef GST_DISABLE_GST_DEBUG + +static void +gst_ogg_print (GstOggDemux * ogg) +{ + /* NOP */ +} + +#else /* !GST_DISABLE_GST_DEBUG */ + +static void +gst_ogg_print (GstOggDemux * ogg) +{ + guint j, i; + + GST_INFO_OBJECT (ogg, "%u chains", ogg->chains->len); + GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (ogg->total_time)); + + for (i = 0; i < ogg->chains->len; i++) { + GstOggChain *chain = g_array_index (ogg->chains, GstOggChain *, i); + + GST_INFO_OBJECT (ogg, " chain %d (%u streams):", i, chain->streams->len); + GST_INFO_OBJECT (ogg, + " offset: %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT, chain->offset, + chain->end_offset); + GST_INFO_OBJECT (ogg, " begin time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->begin_time)); + GST_INFO_OBJECT (ogg, " total time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->total_time)); + GST_INFO_OBJECT (ogg, " segment start: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->segment_start)); + GST_INFO_OBJECT (ogg, " segment stop: %" GST_TIME_FORMAT, + GST_TIME_ARGS (chain->segment_stop)); + + for (j = 0; j < chain->streams->len; j++) { + GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j); + + GST_INFO_OBJECT (ogg, " stream %08lx:", stream->map.serialno); + GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->start_time)); + } + } +} +#endif /* GST_DISABLE_GST_DEBUG */ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.h b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.h new file mode 100644 index 0000000..031627b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggdemux.h @@ -0,0 +1,178 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstoggdemux.c: ogg stream demuxer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OGG_DEMUX_H__ +#define __GST_OGG_DEMUX_H__ + +#include + +#include + +#include "gstoggstream.h" + +G_BEGIN_DECLS + +#define GST_TYPE_OGG_PAD (gst_ogg_pad_get_type()) +#define GST_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PAD, GstOggPad)) +#define GST_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PAD, GstOggPad)) +#define GST_IS_OGG_PAD(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PAD)) +#define GST_IS_OGG_PAD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PAD)) + +typedef struct _GstOggPad GstOggPad; +typedef struct _GstOggPadClass GstOggPadClass; + +#define GST_TYPE_OGG_DEMUX (gst_ogg_demux_get_type()) +#define GST_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_DEMUX, GstOggDemux)) +#define GST_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_DEMUX, GstOggDemux)) +#define GST_IS_OGG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_DEMUX)) +#define GST_IS_OGG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_DEMUX)) + +GType gst_ogg_demux_get_type (void); + +typedef struct _GstOggDemux GstOggDemux; +typedef struct _GstOggDemuxClass GstOggDemuxClass; +typedef struct _GstOggChain GstOggChain; + +/* all information needed for one ogg chain (relevant for chained bitstreams) */ +struct _GstOggChain +{ + GstOggDemux *ogg; + + gint64 offset; /* starting offset of chain */ + gint64 end_offset; /* end offset of chain */ + gint64 bytes; /* number of bytes */ + + gboolean have_bos; + + GArray *streams; + + GstClockTime total_time; /* the total time of this chain, this is the MAX of + the totals of all streams */ + GstClockTime begin_time; /* when this chain starts in the stream */ + + GstClockTime segment_start; /* the timestamp of the first sample, this is the MIN of + the start times of all streams. */ + GstClockTime segment_stop; /* the timestamp of the last page, this is the MAX of the + streams. */ +}; + +/* different modes for the pad */ +typedef enum +{ + GST_OGG_PAD_MODE_INIT, /* we are feeding our internal decoder to get info */ + GST_OGG_PAD_MODE_STREAMING, /* we are streaming buffers to the outside */ +} GstOggPadMode; + +/* all information needed for one ogg stream */ +struct _GstOggPad +{ + GstPad pad; /* subclass GstPad */ + + gboolean have_type; + GstOggPadMode mode; + + GstOggChain *chain; /* the chain we are part of */ + GstOggDemux *ogg; /* the ogg demuxer we are part of */ + + GstOggStream map; + + gint64 packetno; + gint64 current_granule; + gint64 keyframe_granule; + + GstClockTime start_time; /* the timestamp of the first sample */ + + gint64 first_granule; /* the granulepos of first page == first sample in next page */ + GstClockTime first_time; /* the timestamp of the second page or granuletime of first page */ + + GstClockTime last_stop; /* last_stop when last push occured; used to detect when we + * need to send a newsegment update event for sparse streams */ + + GList *continued; + + gboolean discont; + GstFlowReturn last_ret; /* last return of _pad_push() */ + gboolean is_eos; + + gboolean added; +}; + +struct _GstOggPadClass +{ + GstPadClass parent_class; +}; + +/** + * GstOggDemux: + * + * The ogg demuxer object structure. + */ +struct _GstOggDemux +{ + GstElement element; + + GstPad *sinkpad; + + gint64 length; + gint64 read_offset; + gint64 offset; + + gboolean pullmode; + gboolean running; + + gboolean need_chains; + gboolean resync; + + /* state */ + GMutex *chain_lock; /* we need the lock to protect the chains */ + GArray *chains; /* list of chains we know */ + GstClockTime total_time; + gint bitrate; /* bitrate of the current chain */ + + GstOggChain *current_chain; + GstOggChain *building_chain; + + /* playback start/stop positions */ + GstSegment segment; + gboolean segment_running; + guint32 seqnum; + + GstEvent *event; + GstEvent *newsegment; /* pending newsegment to be sent from _loop */ + + /* annodex stuff */ + gint64 basetime; + gint64 prestime; + + /* ogg stuff */ + ogg_sync_state sync; +}; + +struct _GstOggDemuxClass +{ + GstElementClass parent_class; +}; + +gboolean gst_ogg_demux_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_OGG_DEMUX_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.c new file mode 100644 index 0000000..4dda50b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.c @@ -0,0 +1,1805 @@ +/* OGG muxer plugin for GStreamer + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-oggmux + * @see_also: oggdemux + * + * This element merges streams (audio and video) into ogg files. + * + * + * Example pipelines + * |[ + * gst-launch v4l2src num-buffers=500 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! theoraenc ! oggmux ! filesink location=video.ogg + * ]| Encodes a video stream captured from a v4l2-compatible camera to Ogg/Theora + * (the encoding will stop automatically after 500 frames) + * + * + * Last reviewed on 2008-02-06 (0.10.17) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include "gstoggmux.h" + +/* memcpy - if someone knows a way to get rid of it, please speak up + * note: the ogg docs even say you need this... */ +#include +#include +#include /* rand, srand, atoi */ + +GST_DEBUG_CATEGORY_STATIC (gst_ogg_mux_debug); +#define GST_CAT_DEFAULT gst_ogg_mux_debug + +/* This isn't generally what you'd want with an end-time macro, because + technically the end time of a buffer with invalid duration is invalid. But + for sorting ogg pages this is what we want. */ +#define GST_BUFFER_END_TIME(buf) \ + (GST_BUFFER_DURATION_IS_VALID (buf) \ + ? GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf) \ + : GST_BUFFER_TIMESTAMP (buf)) + +#define GST_BUFFER_RUNNING_TIME(buf, oggpad) \ + (GST_BUFFER_DURATION_IS_VALID (buf) \ + ? gst_segment_to_running_time (&(oggpad)->segment, GST_FORMAT_TIME, \ + GST_BUFFER_TIMESTAMP (buf)) : 0) + +#define GST_GP_FORMAT "[gp %8" G_GINT64_FORMAT "]" +#define GST_GP_CAST(_gp) ((gint64) _gp) + +typedef enum +{ + GST_OGG_FLAG_BOS = GST_ELEMENT_FLAG_LAST, + GST_OGG_FLAG_EOS +} +GstOggFlag; + +/* OggMux signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +/* set to 0.5 seconds by default */ +#define DEFAULT_MAX_DELAY G_GINT64_CONSTANT(500000000) +#define DEFAULT_MAX_PAGE_DELAY G_GINT64_CONSTANT(500000000) +enum +{ + ARG_0, + ARG_MAX_DELAY, + ARG_MAX_PAGE_DELAY, +}; + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/ogg") + ); + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("video/x-theora; " + "audio/x-vorbis; audio/x-flac; audio/x-speex; audio/x-celt; " + "application/x-ogm-video; application/x-ogm-audio; video/x-dirac; " + "video/x-smoke; video/x-vp8; text/x-cmml, encoded = (boolean) TRUE; " + "subtitle/x-kate; application/x-kate") + ); + +static void gst_ogg_mux_base_init (gpointer g_class); +static void gst_ogg_mux_class_init (GstOggMuxClass * klass); +static void gst_ogg_mux_init (GstOggMux * ogg_mux); +static void gst_ogg_mux_finalize (GObject * object); + +static GstFlowReturn +gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux); +static gboolean gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event); +static GstPad *gst_ogg_mux_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_ogg_mux_release_pad (GstElement * element, GstPad * pad); + +static void gst_ogg_mux_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_ogg_mux_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstStateChangeReturn gst_ogg_mux_change_state (GstElement * element, + GstStateChange transition); + +static GstElementClass *parent_class = NULL; + +/*static guint gst_ogg_mux_signals[LAST_SIGNAL] = { 0 }; */ + +GType +gst_ogg_mux_get_type (void) +{ + static GType ogg_mux_type = 0; + + if (G_UNLIKELY (ogg_mux_type == 0)) { + static const GTypeInfo ogg_mux_info = { + sizeof (GstOggMuxClass), + gst_ogg_mux_base_init, + NULL, + (GClassInitFunc) gst_ogg_mux_class_init, + NULL, + NULL, + sizeof (GstOggMux), + 0, + (GInstanceInitFunc) gst_ogg_mux_init, + }; + static const GInterfaceInfo preset_info = { + NULL, + NULL, + NULL + }; + + ogg_mux_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstOggMux", &ogg_mux_info, + 0); + + g_type_add_interface_static (ogg_mux_type, GST_TYPE_PRESET, &preset_info); + } + return ogg_mux_type; +} + +static void +gst_ogg_mux_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + + gst_element_class_set_details_simple (element_class, + "Ogg muxer", "Codec/Muxer", + "mux ogg streams (info about ogg: http://xiph.org)", + "Wim Taymans "); +} + +static void +gst_ogg_mux_class_init (GstOggMuxClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_ogg_mux_finalize; + gobject_class->get_property = gst_ogg_mux_get_property; + gobject_class->set_property = gst_ogg_mux_set_property; + + gstelement_class->request_new_pad = gst_ogg_mux_request_new_pad; + gstelement_class->release_pad = gst_ogg_mux_release_pad; + + g_object_class_install_property (gobject_class, ARG_MAX_DELAY, + g_param_spec_uint64 ("max-delay", "Max delay", + "Maximum delay in multiplexing streams", 0, G_MAXUINT64, + DEFAULT_MAX_DELAY, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_MAX_PAGE_DELAY, + g_param_spec_uint64 ("max-page-delay", "Max page delay", + "Maximum delay for sending out a page", 0, G_MAXUINT64, + DEFAULT_MAX_PAGE_DELAY, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = gst_ogg_mux_change_state; + +} + +#if 0 +static const GstEventMask * +gst_ogg_mux_get_sink_event_masks (GstPad * pad) +{ + static const GstEventMask gst_ogg_mux_sink_event_masks[] = { + {GST_EVENT_EOS, 0}, + {GST_EVENT_DISCONTINUOUS, 0}, + {0,} + }; + + return gst_ogg_mux_sink_event_masks; +} +#endif + +static void +gst_ogg_mux_clear (GstOggMux * ogg_mux) +{ + ogg_mux->pulling = NULL; + ogg_mux->need_headers = TRUE; + ogg_mux->delta_pad = NULL; + ogg_mux->offset = 0; + ogg_mux->next_ts = 0; + ogg_mux->last_ts = GST_CLOCK_TIME_NONE; +} + +static void +gst_ogg_mux_init (GstOggMux * ogg_mux) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (ogg_mux); + + ogg_mux->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "src"), "src"); + gst_pad_set_event_function (ogg_mux->srcpad, gst_ogg_mux_handle_src_event); + gst_element_add_pad (GST_ELEMENT (ogg_mux), ogg_mux->srcpad); + + GST_OBJECT_FLAG_SET (GST_ELEMENT (ogg_mux), GST_OGG_FLAG_BOS); + + /* seed random number generator for creation of serial numbers */ + srand (time (NULL)); + + ogg_mux->collect = gst_collect_pads_new (); + gst_collect_pads_set_function (ogg_mux->collect, + (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_ogg_mux_collected), + ogg_mux); + + ogg_mux->max_delay = DEFAULT_MAX_DELAY; + ogg_mux->max_page_delay = DEFAULT_MAX_PAGE_DELAY; + + gst_ogg_mux_clear (ogg_mux); +} + +static void +gst_ogg_mux_finalize (GObject * object) +{ + GstOggMux *ogg_mux; + + ogg_mux = GST_OGG_MUX (object); + + if (ogg_mux->collect) { + gst_object_unref (ogg_mux->collect); + ogg_mux->collect = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_ogg_mux_ogg_pad_destroy_notify (GstCollectData * data) +{ + GstOggPadData *oggpad = (GstOggPadData *) data; + GstBuffer *buf; + + ogg_stream_clear (&oggpad->map.stream); + gst_caps_replace (&oggpad->map.caps, NULL); + + if (oggpad->pagebuffers) { + while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) { + gst_buffer_unref (buf); + } + g_queue_free (oggpad->pagebuffers); + oggpad->pagebuffers = NULL; + } +} + +static GstPadLinkReturn +gst_ogg_mux_sinkconnect (GstPad * pad, GstPad * peer) +{ + GstOggMux *ogg_mux; + + ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (ogg_mux, "sinkconnect triggered on %s", GST_PAD_NAME (pad)); + + gst_object_unref (ogg_mux); + + return GST_PAD_LINK_OK; +} + +static gboolean +gst_ogg_mux_sink_event (GstPad * pad, GstEvent * event) +{ + GstOggMux *ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad)); + GstOggPadData *ogg_pad = (GstOggPadData *) gst_pad_get_element_private (pad); + gboolean ret = FALSE; + + GST_DEBUG_OBJECT (pad, "Got %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT:{ + gboolean update; + gdouble rate; + gdouble applied_rate; + GstFormat format; + gint64 start, stop, position; + + gst_event_parse_new_segment_full (event, &update, &rate, + &applied_rate, &format, &start, &stop, &position); + + /* We don't support non time NEWSEGMENT events */ + if (format != GST_FORMAT_TIME) { + gst_event_unref (event); + event = NULL; + break; + } + + gst_segment_set_newsegment_full (&ogg_pad->segment, update, rate, + applied_rate, format, start, stop, position); + + break; + } + case GST_EVENT_FLUSH_STOP:{ + gst_segment_init (&ogg_pad->segment, GST_FORMAT_TIME); + break; + } + default: + break; + } + + /* now GstCollectPads can take care of the rest, e.g. EOS */ + if (event != NULL) + ret = ogg_pad->collect_event (pad, event); + + gst_object_unref (ogg_mux); + return ret; +} + +static gboolean +gst_ogg_mux_is_serialno_present (GstOggMux * ogg_mux, guint32 serialno) +{ + GSList *walk; + + walk = ogg_mux->collect->data; + while (walk) { + GstOggPadData *pad = (GstOggPadData *) walk->data; + if (pad->map.serialno == serialno) + return TRUE; + walk = walk->next; + } + + return FALSE; +} + +static guint32 +gst_ogg_mux_generate_serialno (GstOggMux * ogg_mux) +{ + guint32 serialno; + + do { + serialno = g_random_int_range (0, G_MAXINT32); + } while (gst_ogg_mux_is_serialno_present (ogg_mux, serialno)); + + return serialno; +} + +static GstPad * +gst_ogg_mux_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * req_name) +{ + GstOggMux *ogg_mux; + GstPad *newpad; + GstElementClass *klass; + + g_return_val_if_fail (templ != NULL, NULL); + + if (templ->direction != GST_PAD_SINK) + goto wrong_direction; + + g_return_val_if_fail (GST_IS_OGG_MUX (element), NULL); + ogg_mux = GST_OGG_MUX (element); + + klass = GST_ELEMENT_GET_CLASS (element); + + if (templ != gst_element_class_get_pad_template (klass, "sink_%d")) + goto wrong_template; + + { + gint serial; + gchar *name; + + if (req_name == NULL || strlen (req_name) < 6) { + /* no name given when requesting the pad, use random serial number */ + serial = gst_ogg_mux_generate_serialno (ogg_mux); + } else { + /* parse serial number from requested padname */ + serial = atoi (&req_name[5]); + } + /* create new pad with the name */ + GST_DEBUG_OBJECT (ogg_mux, "Creating new pad for serial %d", serial); + name = g_strdup_printf ("sink_%d", serial); + newpad = gst_pad_new_from_template (templ, name); + g_free (name); + + /* construct our own wrapper data structure for the pad to + * keep track of its status */ + { + GstOggPadData *oggpad; + + oggpad = (GstOggPadData *) + gst_collect_pads_add_pad_full (ogg_mux->collect, newpad, + sizeof (GstOggPadData), gst_ogg_mux_ogg_pad_destroy_notify); + ogg_mux->active_pads++; + + oggpad->map.serialno = serial; + ogg_stream_init (&oggpad->map.stream, oggpad->map.serialno); + oggpad->packetno = 0; + oggpad->pageno = 0; + oggpad->eos = FALSE; + /* we assume there will be some control data first for this pad */ + oggpad->state = GST_OGG_PAD_STATE_CONTROL; + oggpad->new_page = TRUE; + oggpad->first_delta = FALSE; + oggpad->prev_delta = FALSE; + oggpad->data_pushed = FALSE; + oggpad->pagebuffers = g_queue_new (); + oggpad->map.headers = NULL; + oggpad->map.queued = NULL; + + gst_segment_init (&oggpad->segment, GST_FORMAT_TIME); + + oggpad->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad); + gst_pad_set_event_function (newpad, + GST_DEBUG_FUNCPTR (gst_ogg_mux_sink_event)); + } + } + + /* setup some pad functions */ + gst_pad_set_link_function (newpad, gst_ogg_mux_sinkconnect); + + /* dd the pad to the element */ + gst_element_add_pad (element, newpad); + + return newpad; + + /* ERRORS */ +wrong_direction: + { + g_warning ("ogg_mux: request pad that is not a SINK pad\n"); + return NULL; + } +wrong_template: + { + g_warning ("ogg_mux: this is not our template!\n"); + return NULL; + } +} + +static void +gst_ogg_mux_release_pad (GstElement * element, GstPad * pad) +{ + GstOggMux *ogg_mux; + + ogg_mux = GST_OGG_MUX (gst_pad_get_parent (pad)); + + gst_collect_pads_remove_pad (ogg_mux->collect, pad); + gst_element_remove_pad (element, pad); + + gst_object_unref (ogg_mux); +} + +/* handle events */ +static gboolean +gst_ogg_mux_handle_src_event (GstPad * pad, GstEvent * event) +{ + GstEventType type; + + type = event ? GST_EVENT_TYPE (event) : GST_EVENT_UNKNOWN; + + switch (type) { + case GST_EVENT_SEEK: + /* disable seeking for now */ + return FALSE; + default: + break; + } + + return gst_pad_event_default (pad, event); +} + +static GstBuffer * +gst_ogg_mux_buffer_from_page (GstOggMux * mux, ogg_page * page, gboolean delta) +{ + GstBuffer *buffer; + + /* allocate space for header and body */ + buffer = gst_buffer_new_and_alloc (page->header_len + page->body_len); + memcpy (GST_BUFFER_DATA (buffer), page->header, page->header_len); + memcpy (GST_BUFFER_DATA (buffer) + page->header_len, + page->body, page->body_len); + + /* Here we set granulepos as our OFFSET_END to give easy direct access to + * this value later. Before we push it, we reset this to OFFSET + SIZE + * (see gst_ogg_mux_push_buffer). */ + GST_BUFFER_OFFSET_END (buffer) = ogg_page_granulepos (page); + if (delta) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + GST_LOG_OBJECT (mux, GST_GP_FORMAT + " created buffer %p from ogg page", + GST_GP_CAST (ogg_page_granulepos (page)), buffer); + + return buffer; +} + +static GstFlowReturn +gst_ogg_mux_push_buffer (GstOggMux * mux, GstBuffer * buffer, + GstOggPadData * oggpad) +{ + GstCaps *caps; + + /* fix up OFFSET and OFFSET_END again */ + GST_BUFFER_OFFSET (buffer) = mux->offset; + mux->offset += GST_BUFFER_SIZE (buffer); + GST_BUFFER_OFFSET_END (buffer) = mux->offset; + + /* Ensure we have monotonically increasing timestamps in the output. */ + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { + gint64 run_time = GST_BUFFER_RUNNING_TIME (buffer, oggpad); + if (mux->last_ts != GST_CLOCK_TIME_NONE && run_time < mux->last_ts) + GST_BUFFER_TIMESTAMP (buffer) = mux->last_ts; + else + mux->last_ts = run_time; + } + + caps = gst_pad_get_negotiated_caps (mux->srcpad); + gst_buffer_set_caps (buffer, caps); + if (caps) + gst_caps_unref (caps); + + return gst_pad_push (mux->srcpad, buffer); +} + +/* if all queues have at least one page, dequeue the page with the lowest + * timestamp */ +static gboolean +gst_ogg_mux_dequeue_page (GstOggMux * mux, GstFlowReturn * flowret) +{ + GSList *walk; + GstOggPadData *opad = NULL; /* "oldest" pad */ + GstClockTime oldest = GST_CLOCK_TIME_NONE; + GstBuffer *buf = NULL; + gboolean ret = FALSE; + + *flowret = GST_FLOW_OK; + + walk = mux->collect->data; + while (walk) { + GstOggPadData *pad = (GstOggPadData *) walk->data; + + /* We need each queue to either be at EOS, or have one or more pages + * available with a set granulepos (i.e. not -1), otherwise we don't have + * enough data yet to determine which stream needs to go next for correct + * time ordering. */ + if (pad->pagebuffers->length == 0) { + if (pad->eos) { + GST_LOG_OBJECT (pad->collect.pad, + "pad is EOS, skipping for dequeue decision"); + } else { + GST_LOG_OBJECT (pad->collect.pad, + "no pages in this queue, can't dequeue"); + return FALSE; + } + } else { + /* We then need to check for a non-negative granulepos */ + int i; + gboolean valid = FALSE; + + for (i = 0; i < pad->pagebuffers->length; i++) { + buf = g_queue_peek_nth (pad->pagebuffers, i); + /* Here we check the OFFSET_END, which is actually temporarily the + * granulepos value for this buffer */ + if (GST_BUFFER_OFFSET_END (buf) != -1) { + valid = TRUE; + break; + } + } + if (!valid) { + GST_LOG_OBJECT (pad->collect.pad, + "No page timestamps in queue, can't dequeue"); + return FALSE; + } + } + + walk = g_slist_next (walk); + } + + walk = mux->collect->data; + while (walk) { + GstOggPadData *pad = (GstOggPadData *) walk->data; + + /* any page with a granulepos of -1 can be pushed immediately. + * TODO: it CAN be, but it seems silly to do so? */ + buf = g_queue_peek_head (pad->pagebuffers); + while (buf && GST_BUFFER_OFFSET_END (buf) == -1) { + GST_LOG_OBJECT (pad->collect.pad, "[gp -1] pushing page"); + g_queue_pop_head (pad->pagebuffers); + *flowret = gst_ogg_mux_push_buffer (mux, buf, pad); + buf = g_queue_peek_head (pad->pagebuffers); + ret = TRUE; + } + + if (buf) { + /* if no oldest buffer yet, take this one */ + if (oldest == GST_CLOCK_TIME_NONE) { + GST_LOG_OBJECT (mux, "no oldest yet, taking buffer %p from pad %" + GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT, + buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf))); + oldest = GST_BUFFER_OFFSET (buf); + opad = pad; + } else { + /* if we have an oldest, compare with this one */ + if (GST_BUFFER_OFFSET (buf) < oldest) { + GST_LOG_OBJECT (mux, "older buffer %p, taking from pad %" + GST_PTR_FORMAT " with gp time %" GST_TIME_FORMAT, + buf, pad->collect.pad, GST_TIME_ARGS (GST_BUFFER_OFFSET (buf))); + oldest = GST_BUFFER_OFFSET (buf); + opad = pad; + } + } + } + walk = g_slist_next (walk); + } + + if (oldest != GST_CLOCK_TIME_NONE) { + g_assert (opad); + buf = g_queue_pop_head (opad->pagebuffers); + GST_LOG_OBJECT (opad->collect.pad, + GST_GP_FORMAT " pushing oldest page buffer %p (granulepos time %" + GST_TIME_FORMAT ")", GST_BUFFER_OFFSET_END (buf), buf, + GST_TIME_ARGS (GST_BUFFER_OFFSET (buf))); + *flowret = gst_ogg_mux_push_buffer (mux, buf, opad); + ret = TRUE; + } + + return ret; +} + +/* put the given ogg page on a per-pad queue, timestamping it correctly. + * after that, dequeue and push as many pages as possible. + * Caller should make sure: + * pad->timestamp was set with the timestamp of the first packet put + * on the page + * pad->timestamp_end was set with the timestamp + duration of the last packet + * put on the page + * pad->gp_time was set with the time matching the gp of the last + * packet put on the page + * + * will also reset timestamp and timestamp_end, so caller func can restart + * counting. + */ +static GstFlowReturn +gst_ogg_mux_pad_queue_page (GstOggMux * mux, GstOggPadData * pad, + ogg_page * page, gboolean delta) +{ + GstFlowReturn ret; + GstBuffer *buffer = gst_ogg_mux_buffer_from_page (mux, page, delta); + + /* take the timestamp of the first packet on this page */ + GST_BUFFER_TIMESTAMP (buffer) = pad->timestamp; + GST_BUFFER_DURATION (buffer) = pad->timestamp_end - pad->timestamp; + /* take the gp time of the last completed packet on this page */ + GST_BUFFER_OFFSET (buffer) = pad->gp_time; + + /* the next page will start where the current page's end time leaves off */ + pad->timestamp = pad->timestamp_end; + + g_queue_push_tail (pad->pagebuffers, buffer); + GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT + " queued buffer page %p (gp time %" + GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT + "), %d page buffers queued", GST_GP_CAST (ogg_page_granulepos (page)), + buffer, GST_TIME_ARGS (GST_BUFFER_OFFSET (buffer)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + g_queue_get_length (pad->pagebuffers)); + + while (gst_ogg_mux_dequeue_page (mux, &ret)) { + if (ret != GST_FLOW_OK) + break; + } + + return ret; +} + +/* + * Given two pads, compare the buffers queued on it. + * Returns: + * 0 if they have an equal priority + * -1 if the first is better + * 1 if the second is better + * Priority decided by: a) validity, b) older timestamp, c) smaller number + * of muxed pages + */ +static gint +gst_ogg_mux_compare_pads (GstOggMux * ogg_mux, GstOggPadData * first, + GstOggPadData * second) +{ + guint64 firsttime, secondtime; + + /* if the first pad doesn't contain anything or is even NULL, return + * the second pad as best candidate and vice versa */ + if (first == NULL || (first->buffer == NULL && first->next_buffer == NULL)) + return 1; + if (second == NULL || (second->buffer == NULL && second->next_buffer == NULL)) + return -1; + + /* no timestamp on first buffer, it must go first */ + if (first->buffer) + firsttime = GST_BUFFER_TIMESTAMP (first->buffer); + else + firsttime = GST_BUFFER_TIMESTAMP (first->next_buffer); + if (firsttime == GST_CLOCK_TIME_NONE) + return -1; + + /* no timestamp on second buffer, it must go first */ + if (second->buffer) + secondtime = GST_BUFFER_TIMESTAMP (second->buffer); + else + secondtime = GST_BUFFER_TIMESTAMP (second->next_buffer); + if (secondtime == GST_CLOCK_TIME_NONE) + return 1; + + firsttime = gst_segment_to_running_time (&first->segment, GST_FORMAT_TIME, + firsttime); + secondtime = gst_segment_to_running_time (&second->segment, GST_FORMAT_TIME, + secondtime); + + /* first buffer has higher timestamp, second one should go first */ + if (secondtime < firsttime) + return 1; + /* second buffer has higher timestamp, first one should go first */ + else if (secondtime > firsttime) + return -1; + else { + /* buffers with equal timestamps, prefer the pad that has the + * least number of pages muxed */ + if (second->pageno < first->pageno) + return 1; + else if (second->pageno > first->pageno) + return -1; + } + + /* same priority if all of the above failed */ + return 0; +} + +/* make sure at least one buffer is queued on all pads, two if possible + * + * if pad->buffer == NULL, pad->next_buffer != NULL, then + * we do not know if the buffer is the last or not + * if pad->buffer != NULL, pad->next_buffer != NULL, then + * pad->buffer is not the last buffer for the pad + * if pad->buffer != NULL, pad->next_buffer == NULL, then + * pad->buffer if the last buffer for the pad + * + * returns a pointer to an oggpad that holds the best buffer, or + * NULL when no pad was usable. "best" means the buffer marked + * with the lowest timestamp. If best->buffer == NULL then nothing + * should be done until more data arrives */ +static GstOggPadData * +gst_ogg_mux_queue_pads (GstOggMux * ogg_mux) +{ + GstOggPadData *bestpad = NULL, *still_hungry = NULL; + GSList *walk; + + /* try to make sure we have a buffer from each usable pad first */ + walk = ogg_mux->collect->data; + while (walk) { + GstOggPadData *pad; + GstCollectData *data; + + data = (GstCollectData *) walk->data; + pad = (GstOggPadData *) data; + + walk = g_slist_next (walk); + + GST_LOG_OBJECT (data->pad, "looking at pad for buffer"); + + /* try to get a new buffer for this pad if needed and possible */ + if (pad->buffer == NULL) { + GstBuffer *buf; + + /* shift the buffer along if needed (it's okay if next_buffer is NULL) */ + if (pad->buffer == NULL) { + GST_LOG_OBJECT (data->pad, "shifting buffer %" GST_PTR_FORMAT, + pad->next_buffer); + pad->buffer = pad->next_buffer; + pad->next_buffer = NULL; + } + + buf = gst_collect_pads_pop (ogg_mux->collect, data); + GST_LOG_OBJECT (data->pad, "popped buffer %" GST_PTR_FORMAT, buf); + + /* On EOS we get a NULL buffer */ + if (buf != NULL) { + if (ogg_mux->delta_pad == NULL && + GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) + ogg_mux->delta_pad = pad; + + /* if we need headers */ + if (pad->state == GST_OGG_PAD_STATE_CONTROL) { + /* and we have one */ + ogg_packet packet; + gboolean is_header; + + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + else + packet.granulepos = 0; + + /* if we're not yet in data mode, ensure we're setup on the first packet */ + if (!pad->have_type) { + /* Use headers in caps, if any; this will allow us to be resilient + * to starting streams on the fly, and some streams (like VP8 + * at least) do not send headers packets, as other muxers don't + * expect/need them. */ + pad->have_type = + gst_ogg_stream_setup_map_from_caps_headers (&pad->map, + GST_BUFFER_CAPS (buf)); + + if (!pad->have_type) { + /* fallback on the packet */ + pad->have_type = gst_ogg_stream_setup_map (&pad->map, &packet); + } + if (!pad->have_type) { + GST_ERROR_OBJECT (pad, "mapper didn't recognise input stream " + "(pad caps: %" GST_PTR_FORMAT ")", GST_PAD_CAPS (pad)); + } else { + GST_DEBUG_OBJECT (pad, "caps detected: %" GST_PTR_FORMAT, + pad->map.caps); + } + } + + if (pad->have_type) + is_header = gst_ogg_stream_packet_is_header (&pad->map, &packet); + else /* fallback (FIXME 0.11: remove IN_CAPS hack) */ + is_header = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + + if (is_header) { + GST_DEBUG_OBJECT (ogg_mux, + "got header buffer in control state, ignoring"); + /* just ignore */ + pad->map.n_header_packets_seen++; + gst_buffer_unref (buf); + buf = NULL; + } else { + GST_DEBUG_OBJECT (ogg_mux, + "got data buffer in control state, switching to data mode"); + /* this is a data buffer so switch to data state */ + pad->state = GST_OGG_PAD_STATE_DATA; + } + } + } else { + GST_DEBUG_OBJECT (data->pad, "EOS on pad"); + if (!pad->eos) { + ogg_page page; + + /* it's no longer active */ + ogg_mux->active_pads--; + + /* Just gone to EOS. Flush existing page(s) */ + pad->eos = TRUE; + + while (ogg_stream_flush (&pad->map.stream, &page)) { + /* Place page into the per-pad queue */ + gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, pad->first_delta); + /* increment the page number counter */ + pad->pageno++; + /* mark other pages as delta */ + pad->first_delta = TRUE; + } + } + } + + pad->next_buffer = buf; + } + + /* we should have a buffer now, see if it is the best pad to + * pull on */ + if (pad->buffer || pad->next_buffer) { + if (gst_ogg_mux_compare_pads (ogg_mux, bestpad, pad) > 0) { + GST_LOG_OBJECT (data->pad, + "new best pad, with buffers %" GST_PTR_FORMAT + " and %" GST_PTR_FORMAT, pad->buffer, pad->next_buffer); + + bestpad = pad; + } + } else if (!pad->eos) { + GST_LOG_OBJECT (data->pad, "hungry pad"); + still_hungry = pad; + } + } + + if (still_hungry) + /* drop back into collectpads... */ + return still_hungry; + else + return bestpad; +} + +static GList * +gst_ogg_mux_get_headers (GstOggPadData * pad) +{ + GList *res = NULL; + GstStructure *structure; + GstCaps *caps; + GstPad *thepad; + + thepad = pad->collect.pad; + + GST_LOG_OBJECT (thepad, "getting headers"); + + caps = gst_pad_get_negotiated_caps (thepad); + if (caps != NULL) { + const GValue *streamheader; + + structure = gst_caps_get_structure (caps, 0); + streamheader = gst_structure_get_value (structure, "streamheader"); + if (streamheader != NULL) { + GST_LOG_OBJECT (thepad, "got header"); + if (G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) { + GArray *bufarr = g_value_peek_pointer (streamheader); + gint i; + + GST_LOG_OBJECT (thepad, "got fixed list"); + + for (i = 0; i < bufarr->len; i++) { + GValue *bufval = &g_array_index (bufarr, GValue, i); + + GST_LOG_OBJECT (thepad, "item %d", i); + if (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER) { + GstBuffer *buf = g_value_peek_pointer (bufval); + + GST_LOG_OBJECT (thepad, "adding item %d to header list", i); + + gst_buffer_ref (buf); + res = g_list_append (res, buf); + } + } + } else { + GST_LOG_OBJECT (thepad, "streamheader is not fixed list"); + } + + /* Start a new page for every CMML buffer */ + if (gst_structure_has_name (structure, "text/x-cmml")) + pad->always_flush_page = TRUE; + } else if (gst_structure_has_name (structure, "video/x-dirac")) { + res = g_list_append (res, pad->buffer); + pad->buffer = pad->next_buffer; + pad->next_buffer = NULL; + pad->always_flush_page = TRUE; + } else { + GST_LOG_OBJECT (thepad, "caps don't have streamheader"); + } + gst_caps_unref (caps); + } else { + GST_LOG_OBJECT (thepad, "got empty caps as negotiated format"); + } + return res; +} + +static GstCaps * +gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers) +{ + GstStructure *structure; + GValue array = { 0 }; + GList *walk = buffers; + + caps = gst_caps_make_writable (caps); + + structure = gst_caps_get_structure (caps, 0); + + /* put buffers in a fixed list */ + g_value_init (&array, GST_TYPE_ARRAY); + + while (walk) { + GstBuffer *buf = GST_BUFFER (walk->data); + GstBuffer *copy; + GValue value = { 0 }; + + walk = walk->next; + + /* mark buffer */ + GST_LOG ("Setting IN_CAPS on buffer of length %d", GST_BUFFER_SIZE (buf)); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + + g_value_init (&value, GST_TYPE_BUFFER); + copy = gst_buffer_copy (buf); + gst_value_set_buffer (&value, copy); + gst_buffer_unref (copy); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + } + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + + return caps; +} + +/* + * For each pad we need to write out one (small) header in one + * page that allows decoders to identify the type of the stream. + * After that we need to write out all extra info for the decoders. + * In the case of a codec that also needs data as configuration, we can + * find that info in the streamcaps. + * After writing the headers we must start a new page for the data. + */ +static GstFlowReturn +gst_ogg_mux_send_headers (GstOggMux * mux) +{ + GSList *walk; + GList *hbufs, *hwalk; + GstCaps *caps; + GstFlowReturn ret; + + hbufs = NULL; + ret = GST_FLOW_OK; + + GST_LOG_OBJECT (mux, "collecting headers"); + + walk = mux->collect->data; + while (walk) { + GstOggPadData *pad; + GstPad *thepad; + + pad = (GstOggPadData *) walk->data; + thepad = pad->collect.pad; + + walk = g_slist_next (walk); + + GST_LOG_OBJECT (mux, "looking at pad %s:%s", GST_DEBUG_PAD_NAME (thepad)); + + /* if the pad has no buffer, we don't care */ + if (pad->buffer == NULL && pad->next_buffer == NULL) + continue; + + /* now figure out the headers */ + pad->map.headers = gst_ogg_mux_get_headers (pad); + } + + GST_LOG_OBJECT (mux, "creating BOS pages"); + walk = mux->collect->data; + while (walk) { + GstOggPadData *pad; + GstBuffer *buf; + ogg_packet packet; + ogg_page page; + GstPad *thepad; + GstCaps *caps; + GstStructure *structure; + GstBuffer *hbuf; + + pad = (GstOggPadData *) walk->data; + thepad = pad->collect.pad; + caps = gst_pad_get_negotiated_caps (thepad); + structure = gst_caps_get_structure (caps, 0); + + walk = walk->next; + + pad->packetno = 0; + + GST_LOG_OBJECT (thepad, "looping over headers"); + + if (pad->map.headers) { + buf = GST_BUFFER (pad->map.headers->data); + pad->map.headers = g_list_remove (pad->map.headers, buf); + } else if (pad->buffer) { + buf = pad->buffer; + gst_buffer_ref (buf); + } else if (pad->next_buffer) { + buf = pad->next_buffer; + gst_buffer_ref (buf); + } else { + /* fixme -- should be caught in the previous list traversal. */ + GST_OBJECT_LOCK (thepad); + g_critical ("No headers or buffers on pad %s:%s", + GST_DEBUG_PAD_NAME (thepad)); + GST_OBJECT_UNLOCK (thepad); + continue; + } + + /* create a packet from the buffer */ + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + if (packet.granulepos == -1) + packet.granulepos = 0; + /* mark BOS and packet number */ + packet.b_o_s = (pad->packetno == 0); + packet.packetno = pad->packetno++; + /* mark EOS */ + packet.e_o_s = 0; + + /* swap the packet in */ + ogg_stream_packetin (&pad->map.stream, &packet); + gst_buffer_unref (buf); + + GST_LOG_OBJECT (thepad, "flushing out BOS page"); + if (!ogg_stream_flush (&pad->map.stream, &page)) + g_critical ("Could not flush BOS page"); + + hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE); + + GST_LOG_OBJECT (mux, "swapped out page with mime type %s", + gst_structure_get_name (structure)); + + /* quick hack: put Theora, VP8 and Dirac video pages at the front. + * Ideally, we would have a settable enum for which Ogg + * profile we work with, and order based on that. + * (FIXME: if there is more than one video stream, shouldn't we only put + * one's BOS into the first page, followed by an audio stream's BOS, and + * only then followed by the remaining video and audio streams?) */ + if (gst_structure_has_name (structure, "video/x-theora")) { + GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Theora"); + hbufs = g_list_prepend (hbufs, hbuf); + } else if (gst_structure_has_name (structure, "video/x-dirac")) { + GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Dirac"); + hbufs = g_list_prepend (hbufs, hbuf); + pad->always_flush_page = TRUE; + } else if (gst_structure_has_name (structure, "video/x-vp8")) { + GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "VP8"); + hbufs = g_list_prepend (hbufs, hbuf); + } else { + hbufs = g_list_append (hbufs, hbuf); + } + gst_caps_unref (caps); + } + + GST_LOG_OBJECT (mux, "creating next headers"); + walk = mux->collect->data; + while (walk) { + GstOggPadData *pad; + GstPad *thepad; + + pad = (GstOggPadData *) walk->data; + thepad = pad->collect.pad; + + walk = walk->next; + + GST_LOG_OBJECT (mux, "looping over headers for pad %s:%s", + GST_DEBUG_PAD_NAME (thepad)); + + hwalk = pad->map.headers; + while (hwalk) { + GstBuffer *buf = GST_BUFFER (hwalk->data); + ogg_packet packet; + ogg_page page; + + hwalk = hwalk->next; + + /* create a packet from the buffer */ + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + if (packet.granulepos == -1) + packet.granulepos = 0; + /* mark BOS and packet number */ + packet.b_o_s = (pad->packetno == 0); + packet.packetno = pad->packetno++; + /* mark EOS */ + packet.e_o_s = 0; + + /* swap the packet in */ + ogg_stream_packetin (&pad->map.stream, &packet); + gst_buffer_unref (buf); + + /* if last header, flush page */ + if (hwalk == NULL) { + GST_LOG_OBJECT (mux, + "flushing page as packet %" G_GUINT64_FORMAT " is first or " + "last packet", (guint64) packet.packetno); + while (ogg_stream_flush (&pad->map.stream, &page)) { + GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE); + + GST_LOG_OBJECT (mux, "swapped out page"); + hbufs = g_list_append (hbufs, hbuf); + } + } else { + GST_LOG_OBJECT (mux, "try to swap out page"); + /* just try to swap out a page then */ + while (ogg_stream_pageout (&pad->map.stream, &page) > 0) { + GstBuffer *hbuf = gst_ogg_mux_buffer_from_page (mux, &page, FALSE); + + GST_LOG_OBJECT (mux, "swapped out page"); + hbufs = g_list_append (hbufs, hbuf); + } + } + } + g_list_free (pad->map.headers); + pad->map.headers = NULL; + } + /* hbufs holds all buffers for the headers now */ + + /* create caps with the buffers */ + caps = gst_pad_get_caps (mux->srcpad); + if (caps) { + caps = gst_ogg_mux_set_header_on_caps (caps, hbufs); + gst_pad_set_caps (mux->srcpad, caps); + gst_caps_unref (caps); + } + /* and send the buffers */ + while (hbufs != NULL) { + GstBuffer *buf = GST_BUFFER (hbufs->data); + + hbufs = g_list_delete_link (hbufs, hbufs); + + if ((ret = gst_ogg_mux_push_buffer (mux, buf, NULL)) != GST_FLOW_OK) + break; + } + /* free any remaining nodes/buffers in case we couldn't push them */ + g_list_foreach (hbufs, (GFunc) gst_mini_object_unref, NULL); + g_list_free (hbufs); + + return ret; +} + +/* this function is called to process data on the best pending pad. + * + * basic idea: + * + * 1) store the selected pad and keep on pulling until we fill a + * complete ogg page or the ogg page is filled above the max-delay + * threshold. This is needed because the ogg spec says that + * you should fill a complete page with data from the same logical + * stream. When the page is filled, go back to 1). + * 2) before filling a page, read ahead one more buffer to see if this + * packet is the last of the stream. We need to do this because the ogg + * spec mandates that the last packet should have the EOS flag set before + * sending it to ogg. if pad->buffer is NULL we need to wait to find out + * whether there are any more buffers. + * 3) pages get queued on a per-pad queue. Every time a page is queued, a + * dequeue is called, which will dequeue the oldest page on any pad, provided + * that ALL pads have at least one marked page in the queue (or remaining + * pads are at EOS) + */ +static GstFlowReturn +gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best) +{ + GstFlowReturn ret = GST_FLOW_OK; + gboolean delta_unit; + gint64 granulepos = 0; + GstClockTime timestamp, gp_time; + + GST_LOG_OBJECT (ogg_mux, "best pad %" GST_PTR_FORMAT + ", currently pulling from %" GST_PTR_FORMAT, best->collect.pad, + ogg_mux->pulling); + + /* best->buffer is non-NULL, either the pad is EOS's or there is a next + * buffer */ + if (best->next_buffer == NULL && !best->eos) { + GST_WARNING_OBJECT (ogg_mux, "no subsequent buffer and EOS not reached"); + return GST_FLOW_WRONG_STATE; + } + + /* if we were already pulling from one pad, but the new "best" buffer is + * from another pad, we need to check if we have reason to flush a page + * for the pad we were pulling from before */ + if (ogg_mux->pulling && best && + ogg_mux->pulling != best && ogg_mux->pulling->buffer) { + GstOggPadData *pad = ogg_mux->pulling; + GstClockTime last_ts = GST_BUFFER_END_TIME (pad->buffer); + + /* if the next packet in the current page is going to make the page + * too long, we need to flush */ + if (last_ts > ogg_mux->next_ts + ogg_mux->max_delay) { + ogg_page page; + + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT " stored packet %" G_GINT64_FORMAT + " will make page too long, flushing", + GST_BUFFER_OFFSET_END (pad->buffer), + (gint64) pad->map.stream.packetno); + + while (ogg_stream_flush (&pad->map.stream, &page)) { + /* end time of this page is the timestamp of the next buffer */ + ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer); + /* Place page into the per-pad queue */ + ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, + pad->first_delta); + /* increment the page number counter */ + pad->pageno++; + /* mark other pages as delta */ + pad->first_delta = TRUE; + } + pad->new_page = TRUE; + ogg_mux->pulling = NULL; + } + } + + /* if we don't know which pad to pull on, use the best one */ + if (ogg_mux->pulling == NULL) { + ogg_mux->pulling = best; + GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from best pad"); + + /* remember timestamp and gp time of first buffer for this new pad */ + if (ogg_mux->pulling != NULL) { + ogg_mux->next_ts = GST_BUFFER_TIMESTAMP (ogg_mux->pulling->buffer); + GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "updated times, next ts %" + GST_TIME_FORMAT, GST_TIME_ARGS (ogg_mux->next_ts)); + } else { + /* no pad to pull on, send EOS */ + gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ()); + return GST_FLOW_WRONG_STATE; + } + } + + if (ogg_mux->need_headers) { + ret = gst_ogg_mux_send_headers (ogg_mux); + ogg_mux->need_headers = FALSE; + } + + /* we are pulling from a pad, continue to do so until a page + * has been filled and queued */ + if (ogg_mux->pulling != NULL) { + ogg_packet packet; + ogg_page page; + GstBuffer *buf, *tmpbuf; + GstOggPadData *pad = ogg_mux->pulling; + gint64 duration; + gboolean force_flush; + + GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, "pulling from pad"); + + /* now see if we have a buffer */ + buf = pad->buffer; + if (buf == NULL) { + GST_DEBUG_OBJECT (ogg_mux, "pad was EOS"); + ogg_mux->pulling = NULL; + return GST_FLOW_OK; + } + + delta_unit = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + duration = GST_BUFFER_DURATION (buf); + + /* if the current "next timestamp" on the pad is unset, then this is the + * first packet on the new page. Update our pad's page timestamp */ + if (ogg_mux->pulling->timestamp == GST_CLOCK_TIME_NONE) { + ogg_mux->pulling->timestamp = GST_BUFFER_TIMESTAMP (buf); + GST_LOG_OBJECT (ogg_mux->pulling->collect.pad, + "updated pad timestamp to %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + } + /* create a packet from the buffer */ + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + if (packet.granulepos == -1) + packet.granulepos = 0; + /* mark BOS and packet number */ + packet.b_o_s = (pad->packetno == 0); + packet.packetno = pad->packetno++; + GST_LOG_OBJECT (pad->collect.pad, GST_GP_FORMAT + " packet %" G_GINT64_FORMAT " (%ld bytes) created from buffer", + GST_GP_CAST (packet.granulepos), (gint64) packet.packetno, + packet.bytes); + + packet.e_o_s = (pad->eos ? 1 : 0); + tmpbuf = NULL; + + /* we flush when we see a new keyframe */ + force_flush = (pad->prev_delta && !delta_unit) || pad->always_flush_page; + if (duration != -1) { + pad->duration += duration; + /* if page duration exceeds max, flush page */ + if (pad->duration > ogg_mux->max_page_delay) { + force_flush = TRUE; + pad->duration = 0; + } + } + + if (GST_BUFFER_IS_DISCONT (buf)) { + if (pad->data_pushed) { + GST_LOG_OBJECT (pad->collect.pad, "got discont"); + packet.packetno++; + /* No public API for this; hack things in */ + pad->map.stream.pageno++; + force_flush = TRUE; + } else { + GST_LOG_OBJECT (pad->collect.pad, "discont at stream start"); + } + } + + /* flush the currently built page if necessary */ + if (force_flush) { + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT " forced flush of page before this packet", + GST_BUFFER_OFFSET_END (pad->buffer)); + while (ogg_stream_flush (&pad->map.stream, &page)) { + /* end time of this page is the timestamp of the next buffer */ + ogg_mux->pulling->timestamp_end = GST_BUFFER_TIMESTAMP (pad->buffer); + ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, + pad->first_delta); + + /* increment the page number counter */ + pad->pageno++; + /* mark other pages as delta */ + pad->first_delta = TRUE; + } + pad->new_page = TRUE; + } + + /* if this is the first packet of a new page figure out the delta flag */ + if (pad->new_page) { + if (delta_unit) { + /* mark the page as delta */ + pad->first_delta = TRUE; + } else { + /* got a keyframe */ + if (ogg_mux->delta_pad == pad) { + /* if we get it on the pad with deltaunits, + * we mark the page as non delta */ + pad->first_delta = FALSE; + } else if (ogg_mux->delta_pad != NULL) { + /* if there are pads with delta frames, we + * must mark this one as delta */ + pad->first_delta = TRUE; + } else { + pad->first_delta = FALSE; + } + } + pad->new_page = FALSE; + } + + /* save key unit to track delta->key unit transitions */ + pad->prev_delta = delta_unit; + + /* swap the packet in */ + if (packet.e_o_s == 1) + GST_DEBUG_OBJECT (pad->collect.pad, "swapping in EOS packet"); + if (packet.b_o_s == 1) + GST_DEBUG_OBJECT (pad->collect.pad, "swapping in BOS packet"); + + ogg_stream_packetin (&pad->map.stream, &packet); + pad->data_pushed = TRUE; + + gp_time = GST_BUFFER_OFFSET (pad->buffer); + granulepos = GST_BUFFER_OFFSET_END (pad->buffer); + timestamp = GST_BUFFER_TIMESTAMP (pad->buffer); + + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", gp time %" + GST_TIME_FORMAT ", timestamp %" GST_TIME_FORMAT " packetin'd", + granulepos, (gint64) packet.packetno, GST_TIME_ARGS (gp_time), + GST_TIME_ARGS (timestamp)); + /* don't need the old buffer anymore */ + gst_buffer_unref (pad->buffer); + /* store new readahead buffer */ + pad->buffer = tmpbuf; + + /* let ogg write out the pages now. The packet we got could end + * up in more than one page so we need to write them all */ + if (ogg_stream_pageout (&pad->map.stream, &page) > 0) { + /* we have a new page, so we need to timestamp it correctly. + * if this fresh packet ends on this page, then the page's granulepos + * comes from that packet, and we should set this buffer's timestamp */ + + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT " packet %" G_GINT64_FORMAT ", time %" + GST_TIME_FORMAT ") caused new page", + granulepos, (gint64) packet.packetno, GST_TIME_ARGS (timestamp)); + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT " new page %ld", + GST_GP_CAST (ogg_page_granulepos (&page)), pad->map.stream.pageno); + + if (ogg_page_granulepos (&page) == granulepos) { + /* the packet we streamed in finishes on the current page, + * because the page's granulepos is the granulepos of the last + * packet completed on that page, + * so update the timestamp that we will give to the page */ + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT + " packet finishes on current page, updating gp time to %" + GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (gp_time)); + pad->gp_time = gp_time; + } else { + GST_LOG_OBJECT (pad->collect.pad, + GST_GP_FORMAT + " packet spans beyond current page, keeping old gp time %" + GST_TIME_FORMAT, granulepos, GST_TIME_ARGS (pad->gp_time)); + } + + /* push the page */ + /* end time of this page is the timestamp of the next buffer */ + pad->timestamp_end = timestamp; + ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, pad->first_delta); + pad->pageno++; + /* mark next pages as delta */ + pad->first_delta = TRUE; + + /* use an inner loop here to flush the remaining pages and + * mark them as delta frames as well */ + while (ogg_stream_pageout (&pad->map.stream, &page) > 0) { + if (ogg_page_granulepos (&page) == granulepos) { + /* the page has taken up the new packet completely, which means + * the packet ends the page and we can update the gp time + * before pushing out */ + pad->gp_time = gp_time; + } + + /* we have a complete page now, we can push the page + * and make sure to pull on a new pad the next time around */ + ret = gst_ogg_mux_pad_queue_page (ogg_mux, pad, &page, + pad->first_delta); + /* increment the page number counter */ + pad->pageno++; + } + /* need a new page as well */ + pad->new_page = TRUE; + pad->duration = 0; + /* we're done pulling on this pad, make sure to choose a new + * pad for pulling in the next iteration */ + ogg_mux->pulling = NULL; + } + + /* Update the gp time, if necessary, since any future page will have at + * least this gp time. + */ + if (pad->gp_time < gp_time) { + pad->gp_time = gp_time; + GST_LOG_OBJECT (pad->collect.pad, + "Updated running gp time of pad %" GST_PTR_FORMAT + " to %" GST_TIME_FORMAT, pad->collect.pad, GST_TIME_ARGS (gp_time)); + } + } + + return ret; +} + +/* all_pads_eos: + * + * Checks if all pads are EOS'd by peeking. + * + * Returns TRUE if all pads are EOS. + */ +static gboolean +all_pads_eos (GstCollectPads * pads) +{ + GSList *walk; + gboolean alleos = TRUE; + + walk = pads->data; + while (walk) { + GstBuffer *buf; + GstCollectData *data = (GstCollectData *) walk->data; + + buf = gst_collect_pads_peek (pads, data); + if (buf) { + alleos = FALSE; + gst_buffer_unref (buf); + goto beach; + } + walk = walk->next; + } +beach: + return alleos; +} + +/* This function is called when there is data on all pads. + * + * It finds a pad to pull on, this is done by looking at the buffers + * to decide which one to use, and using the 'oldest' one first. It then calls + * gst_ogg_mux_process_best_pad() to process as much data as possible. + * + * If all the pads have received EOS, it flushes out all data by continually + * getting the best pad and calling gst_ogg_mux_process_best_pad() until they + * are all empty, and then sends EOS. + */ +static GstFlowReturn +gst_ogg_mux_collected (GstCollectPads * pads, GstOggMux * ogg_mux) +{ + GstOggPadData *best; + GstFlowReturn ret; + gint activebefore; + + GST_LOG_OBJECT (ogg_mux, "collected"); + + activebefore = ogg_mux->active_pads; + + /* queue buffers on all pads; find a buffer with the lowest timestamp */ + best = gst_ogg_mux_queue_pads (ogg_mux); + if (best && !best->buffer) { + GST_DEBUG_OBJECT (ogg_mux, "No buffer available on best pad"); + return GST_FLOW_OK; + } + + if (!best) { + return GST_FLOW_WRONG_STATE; + } + + ret = gst_ogg_mux_process_best_pad (ogg_mux, best); + + if (ogg_mux->active_pads < activebefore) { + /* If the active pad count went down, this mean at least one pad has gone + * EOS. Since CollectPads only calls _collected() once when all pads are + * EOS, and our code doesn't _pop() from all pads we need to check that by + * peeking on all pads, else we won't be called again and the muxing will + * not terminate (push out EOS). */ + + /* if all the pads have been removed, flush all pending data */ + if ((ret == GST_FLOW_OK) && all_pads_eos (pads)) { + GST_LOG_OBJECT (ogg_mux, "no pads remaining, flushing data"); + + do { + best = gst_ogg_mux_queue_pads (ogg_mux); + if (best) + ret = gst_ogg_mux_process_best_pad (ogg_mux, best); + } while ((ret == GST_FLOW_OK) && (best != NULL)); + + GST_DEBUG_OBJECT (ogg_mux, "Pushing EOS"); + gst_pad_push_event (ogg_mux->srcpad, gst_event_new_eos ()); + } + } + + return ret; +} + +static void +gst_ogg_mux_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstOggMux *ogg_mux; + + ogg_mux = GST_OGG_MUX (object); + + switch (prop_id) { + case ARG_MAX_DELAY: + g_value_set_uint64 (value, ogg_mux->max_delay); + break; + case ARG_MAX_PAGE_DELAY: + g_value_set_uint64 (value, ogg_mux->max_page_delay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ogg_mux_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstOggMux *ogg_mux; + + ogg_mux = GST_OGG_MUX (object); + + switch (prop_id) { + case ARG_MAX_DELAY: + ogg_mux->max_delay = g_value_get_uint64 (value); + break; + case ARG_MAX_PAGE_DELAY: + ogg_mux->max_page_delay = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* reset all variables in the ogg pads. */ +static void +gst_ogg_mux_init_collectpads (GstCollectPads * collect) +{ + GSList *walk; + + walk = collect->data; + while (walk) { + GstOggPadData *oggpad = (GstOggPadData *) walk->data; + + ogg_stream_init (&oggpad->map.stream, oggpad->map.serialno); + oggpad->packetno = 0; + oggpad->pageno = 0; + oggpad->eos = FALSE; + /* we assume there will be some control data first for this pad */ + oggpad->state = GST_OGG_PAD_STATE_CONTROL; + oggpad->new_page = TRUE; + oggpad->first_delta = FALSE; + oggpad->prev_delta = FALSE; + oggpad->data_pushed = FALSE; + oggpad->pagebuffers = g_queue_new (); + + gst_segment_init (&oggpad->segment, GST_FORMAT_TIME); + + walk = g_slist_next (walk); + } +} + +/* Clear all buffers from the collectpads object */ +static void +gst_ogg_mux_clear_collectpads (GstCollectPads * collect) +{ + GSList *walk; + + for (walk = collect->data; walk; walk = g_slist_next (walk)) { + GstOggPadData *oggpad = (GstOggPadData *) walk->data; + GstBuffer *buf; + + ogg_stream_clear (&oggpad->map.stream); + + while ((buf = g_queue_pop_head (oggpad->pagebuffers)) != NULL) { + gst_buffer_unref (buf); + } + g_queue_free (oggpad->pagebuffers); + oggpad->pagebuffers = NULL; + + if (oggpad->buffer) { + gst_buffer_unref (oggpad->buffer); + oggpad->buffer = NULL; + } + if (oggpad->next_buffer) { + gst_buffer_unref (oggpad->next_buffer); + oggpad->next_buffer = NULL; + } + + gst_segment_init (&oggpad->segment, GST_FORMAT_TIME); + } +} + +static GstStateChangeReturn +gst_ogg_mux_change_state (GstElement * element, GstStateChange transition) +{ + GstOggMux *ogg_mux; + GstStateChangeReturn ret; + + ogg_mux = GST_OGG_MUX (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_ogg_mux_clear (ogg_mux); + gst_ogg_mux_init_collectpads (ogg_mux->collect); + gst_collect_pads_start (ogg_mux->collect); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_collect_pads_stop (ogg_mux->collect); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_ogg_mux_clear_collectpads (ogg_mux->collect); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +gboolean +gst_ogg_mux_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_ogg_mux_debug, "oggmux", 0, "ogg muxer"); + + return gst_element_register (plugin, "oggmux", GST_RANK_PRIMARY, + GST_TYPE_OGG_MUX); +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.h b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.h new file mode 100644 index 0000000..933226d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggmux.h @@ -0,0 +1,144 @@ +/* OGG muxer plugin for GStreamer + * Copyright (C) 2004 Wim Taymans + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OGG_MUX_H__ +#define __GST_OGGEMUX_H__ + +#include + +#include +#include +#include "gstoggstream.h" + +G_BEGIN_DECLS + +#define GST_TYPE_OGG_MUX (gst_ogg_mux_get_type()) +#define GST_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_MUX, GstOggMux)) +#define GST_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_MUX, GstOggMux)) +#define GST_IS_OGG_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_MUX)) +#define GST_IS_OGG_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_MUX)) + +typedef struct _GstOggMux GstOggMux; +typedef struct _GstOggMuxClass GstOggMuxClass; + +typedef enum +{ + GST_OGG_PAD_STATE_CONTROL = 0, + GST_OGG_PAD_STATE_DATA = 1 +} +GstOggPadState; + +/* all information needed for one ogg stream */ +typedef struct +{ + GstCollectData collect; /* we extend the CollectData */ + + GstOggStream map; + gboolean have_type; + + GstSegment segment; + + /* These two buffers make a very simple queue - they enter as 'next_buffer' + * and (usually) leave as 'buffer', except at EOS, when buffer will be NULL */ + GstBuffer *buffer; /* the first waiting buffer for the pad */ + GstBuffer *next_buffer; /* the second waiting buffer for the pad */ + + gint64 packetno; /* number of next packet */ + gint64 pageno; /* number of next page */ + guint64 duration; /* duration of current page */ + gboolean eos; + gint64 offset; + GstClockTime timestamp; /* timestamp of the first packet on the next + * page to be dequeued */ + GstClockTime timestamp_end; /* end timestamp of last complete packet on + the next page to be dequeued */ + GstClockTime gp_time; /* time corresponding to the gp value of the + last complete packet on the next page to be + dequeued */ + + GstOggPadState state; /* state of the pad */ + + GQueue *pagebuffers; /* List of pages in buffers ready for pushing */ + + gboolean new_page; /* starting a new page */ + gboolean first_delta; /* was the first packet in the page a delta */ + gboolean prev_delta; /* was the previous buffer a delta frame */ + gboolean data_pushed; /* whether we pushed data already */ + + GstPadEventFunction collect_event; + + gboolean always_flush_page; +} +GstOggPadData; + +/** + * GstOggMux: + * + * The ogg muxer object structure. + */ +struct _GstOggMux +{ + GstElement element; + + /* source pad */ + GstPad *srcpad; + + /* sinkpads */ + GstCollectPads *collect; + + /* number of pads which have not received EOS */ + gint active_pads; + + /* the pad we are currently using to fill a page */ + GstOggPadData *pulling; + + /* next timestamp for the page */ + GstClockTime next_ts; + + /* Last timestamp actually output on src pad */ + GstClockTime last_ts; + + /* offset in stream */ + guint64 offset; + + /* need_headers */ + gboolean need_headers; + + guint64 max_delay; + guint64 max_page_delay; + + GstOggPadData *delta_pad; /* when a delta frame is detected on a stream, we mark + pages as delta frames up to the page that has the + keyframe */ + +}; + +struct _GstOggMuxClass +{ + GstElementClass parent_class; +}; + +GType gst_ogg_mux_get_type (void); + +gboolean gst_ogg_mux_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* __GST_OGG_MUX_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggparse.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggparse.c new file mode 100644 index 0000000..eae0acd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggparse.c @@ -0,0 +1,758 @@ +/* GStreamer + * Copyright (C) 2005 Michael Smith + * + * gstoggparse.c: ogg stream parser + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* This ogg parser is essentially a subset of the ogg demuxer - rather than + * fully demuxing into packets, we only parse out the pages, create one + * GstBuffer per page, set all the appropriate flags on those pages, set caps + * appropriately (particularly the 'streamheader' which gives all the header + * pages required for initialing decode). + * + * It's dramatically simpler than the full demuxer as it does not support + * seeking. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "gstogg.h" +#include "gstoggstream.h" + +GST_DEBUG_CATEGORY_STATIC (gst_ogg_parse_debug); +#define GST_CAT_DEFAULT gst_ogg_parse_debug + +#define GST_TYPE_OGG_PARSE (gst_ogg_parse_get_type()) +#define GST_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_OGG_PARSE, GstOggParse)) +#define GST_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_OGG_PARSE, GstOggParse)) +#define GST_IS_OGG_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_OGG_PARSE)) +#define GST_IS_OGG_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_OGG_PARSE)) + +static GType gst_ogg_parse_get_type (void); + +typedef struct _GstOggParse GstOggParse; +typedef struct _GstOggParseClass GstOggParseClass; + +struct _GstOggParse +{ + GstElement element; + + GstPad *sinkpad; /* Sink pad we're reading data from */ + + GstPad *srcpad; /* Source pad we're writing to */ + + GSList *oggstreams; /* list of GstOggStreams for known streams */ + + gint64 offset; /* Current stream offset */ + + gboolean in_headers; /* Set if we're reading headers for streams */ + + gboolean last_page_not_bos; /* Set if we've seen a non-BOS page */ + + ogg_sync_state sync; /* Ogg page synchronisation */ + + GstCaps *caps; /* Our src caps */ + + GstOggStream *video_stream; /* Stream used to construct delta_unit flags */ +}; + +struct _GstOggParseClass +{ + GstElementClass parent_class; +}; + +static void gst_ogg_parse_base_init (gpointer g_class); +static void gst_ogg_parse_class_init (GstOggParseClass * klass); +static void gst_ogg_parse_init (GstOggParse * ogg); +static GstElementClass *parent_class = NULL; + +static GType +gst_ogg_parse_get_type (void) +{ + static GType ogg_parse_type = 0; + + if (!ogg_parse_type) { + static const GTypeInfo ogg_parse_info = { + sizeof (GstOggParseClass), + gst_ogg_parse_base_init, + NULL, + (GClassInitFunc) gst_ogg_parse_class_init, + NULL, + NULL, + sizeof (GstOggParse), + 0, + (GInstanceInitFunc) gst_ogg_parse_init, + }; + + ogg_parse_type = g_type_register_static (GST_TYPE_ELEMENT, "GstOggParse", + &ogg_parse_info, 0); + } + return ogg_parse_type; +} + +static void +free_stream (GstOggStream * stream) +{ + g_list_foreach (stream->headers, (GFunc) gst_mini_object_unref, NULL); + g_list_foreach (stream->unknown_pages, (GFunc) gst_mini_object_unref, NULL); + g_list_foreach (stream->stored_buffers, (GFunc) gst_mini_object_unref, NULL); + + g_free (stream); +} + +static void +gst_ogg_parse_delete_all_streams (GstOggParse * ogg) +{ + g_slist_foreach (ogg->oggstreams, (GFunc) free_stream, NULL); + g_slist_free (ogg->oggstreams); + ogg->oggstreams = NULL; +} + +static GstOggStream * +gst_ogg_parse_new_stream (GstOggParse * parser, ogg_page * page) +{ + GstOggStream *stream; + ogg_packet packet; + int ret; + guint32 serialno; + + serialno = ogg_page_serialno (page); + + GST_DEBUG_OBJECT (parser, "creating new stream %08x", serialno); + + stream = g_new0 (GstOggStream, 1); + + stream->serialno = serialno; + stream->in_headers = 1; + + if (ogg_stream_init (&stream->stream, serialno) != 0) { + GST_ERROR ("Could not initialize ogg_stream struct for serial %08x.", + serialno); + return NULL; + } + + /* FIXME check return */ + ogg_stream_pagein (&stream->stream, page); + + /* FIXME check return */ + ret = ogg_stream_packetout (&stream->stream, &packet); + if (ret == 1) { + gst_ogg_stream_setup_map (stream, &packet); + if (stream->is_video) { + parser->video_stream = stream; + } + } + + parser->oggstreams = g_slist_append (parser->oggstreams, stream); + + return stream; +} + +static GstOggStream * +gst_ogg_parse_find_stream (GstOggParse * parser, guint32 serialno) +{ + GSList *l; + + for (l = parser->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + + if (stream->serialno == serialno) + return stream; + } + return NULL; +} + +/* signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 + /* FILL ME */ +}; + +static GstStaticPadTemplate ogg_parse_src_template_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/ogg") + ); + +static GstStaticPadTemplate ogg_parse_sink_template_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/ogg") + ); + +static void gst_ogg_parse_dispose (GObject * object); +static GstStateChangeReturn gst_ogg_parse_change_state (GstElement * element, + GstStateChange transition); +static GstFlowReturn gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer); + +static void +gst_ogg_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Ogg parser", "Codec/Parser", + "parse ogg streams into pages (info about ogg: http://xiph.org)", + "Michael Smith "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_parse_sink_template_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&ogg_parse_src_template_factory)); +} + +static void +gst_ogg_parse_class_init (GstOggParseClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gstelement_class->change_state = gst_ogg_parse_change_state; + + gobject_class->dispose = gst_ogg_parse_dispose; +} + +static void +gst_ogg_parse_init (GstOggParse * ogg) +{ + /* create the sink and source pads */ + ogg->sinkpad = + gst_pad_new_from_static_template (&ogg_parse_sink_template_factory, + "sink"); + ogg->srcpad = + gst_pad_new_from_static_template (&ogg_parse_src_template_factory, "src"); + + /* TODO: Are there any events we must handle? */ + /* gst_pad_set_event_function (ogg->sinkpad, gst_ogg_parse_handle_event); */ + gst_pad_set_chain_function (ogg->sinkpad, gst_ogg_parse_chain); + + gst_element_add_pad (GST_ELEMENT (ogg), ogg->sinkpad); + gst_element_add_pad (GST_ELEMENT (ogg), ogg->srcpad); + + ogg->oggstreams = NULL; +} + +static void +gst_ogg_parse_dispose (GObject * object) +{ + GstOggParse *ogg = GST_OGG_PARSE (object); + + GST_LOG_OBJECT (ogg, "Disposing of object %p", ogg); + + ogg_sync_clear (&ogg->sync); + gst_ogg_parse_delete_all_streams (ogg); + + if (ogg->caps) { + gst_caps_unref (ogg->caps); + ogg->caps = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->dispose) + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/* submit the given buffer to the ogg sync */ +static GstFlowReturn +gst_ogg_parse_submit_buffer (GstOggParse * ogg, GstBuffer * buffer) +{ + guint size; + guint8 *data; + gchar *oggbuffer; + GstFlowReturn ret = GST_FLOW_OK; + + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size); + if (G_UNLIKELY (size == 0)) + goto done; + + oggbuffer = ogg_sync_buffer (&ogg->sync, size); + if (G_UNLIKELY (oggbuffer == NULL)) { + GST_ELEMENT_ERROR (ogg, STREAM, DECODE, + (NULL), ("failed to get ogg sync buffer")); + ret = GST_FLOW_ERROR; + goto done; + } + + memcpy (oggbuffer, data, size); + if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0)) { + GST_ELEMENT_ERROR (ogg, STREAM, DECODE, + (NULL), ("failed to write %d bytes to the sync buffer", size)); + ret = GST_FLOW_ERROR; + } + +done: + gst_buffer_unref (buffer); + + return ret; +} + +static void +gst_ogg_parse_append_header (GValue * array, GstBuffer * buf) +{ + GValue value = { 0 }; + /* We require a copy to avoid circular refcounts */ + GstBuffer *buffer = gst_buffer_copy (buf); + + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, buffer); + gst_value_array_append_value (array, &value); + g_value_unset (&value); + +} + +typedef enum +{ + PAGE_HEADER, /* Header page */ + PAGE_DATA, /* Data page */ + PAGE_PENDING, /* We don't know yet, we'll have to see some future pages */ +} page_type; + +static page_type +gst_ogg_parse_is_header (GstOggParse * ogg, GstOggStream * stream, + ogg_page * page) +{ + ogg_int64_t gpos = ogg_page_granulepos (page); + + if (gpos < 0) + return PAGE_PENDING; + + /* This is good enough for now, but technically requires codec-specific + * behaviour to be perfect. This is where we need the mooted library for + * this stuff, which nobody has written. + */ + if (gpos > 0) + return PAGE_DATA; + else + return PAGE_HEADER; +} + +static GstBuffer * +gst_ogg_parse_buffer_from_page (ogg_page * page, + guint64 offset, GstClockTime timestamp) +{ + int size = page->header_len + page->body_len; + GstBuffer *buf = gst_buffer_new_and_alloc (size); + + memcpy (GST_BUFFER_DATA (buf), page->header, page->header_len); + memcpy (GST_BUFFER_DATA (buf) + page->header_len, page->body, page->body_len); + + GST_BUFFER_TIMESTAMP (buf) = timestamp; + GST_BUFFER_OFFSET (buf) = offset; + GST_BUFFER_OFFSET_END (buf) = offset + size; + + return buf; +} + + +/* Reads in buffers, parses them, reframes into one-buffer-per-ogg-page, submits + * pages to output pad. + */ +static GstFlowReturn +gst_ogg_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstOggParse *ogg; + GstFlowReturn result = GST_FLOW_OK; + gint ret = -1; + guint32 serialno; + GstBuffer *pagebuffer; + GstClockTime buffertimestamp = GST_BUFFER_TIMESTAMP (buffer); + + ogg = GST_OGG_PARSE (GST_OBJECT_PARENT (pad)); + + GST_LOG_OBJECT (ogg, "Chain function received buffer of size %d", + GST_BUFFER_SIZE (buffer)); + + gst_ogg_parse_submit_buffer (ogg, buffer); + + while (ret != 0 && result == GST_FLOW_OK) { + ogg_page page; + + /* We use ogg_sync_pageseek() rather than ogg_sync_pageout() so that we can + * track how many bytes the ogg layer discarded (in the case of sync errors, + * etc.); this allows us to accurately track the current stream offset + */ + ret = ogg_sync_pageseek (&ogg->sync, &page); + if (ret == 0) { + /* need more data, that's fine... */ + break; + } else if (ret < 0) { + /* discontinuity; track how many bytes we skipped (-ret) */ + ogg->offset -= ret; + } else { + gint64 granule = ogg_page_granulepos (&page); +#ifndef GST_DISABLE_GST_DEBUG + int bos = ogg_page_bos (&page); +#endif + guint64 startoffset = ogg->offset; + GstOggStream *stream; + gboolean keyframe; + + serialno = ogg_page_serialno (&page); + stream = gst_ogg_parse_find_stream (ogg, serialno); + + GST_LOG_OBJECT (ogg, "Timestamping outgoing buffer as %" GST_TIME_FORMAT, + GST_TIME_ARGS (buffertimestamp)); + + if (stream) { + buffertimestamp = gst_ogg_stream_get_end_time_for_granulepos (stream, + granule); + if (ogg->video_stream) { + if (stream == ogg->video_stream) { + keyframe = gst_ogg_stream_granulepos_is_key_frame (stream, granule); + } else { + keyframe = FALSE; + } + } else { + keyframe = TRUE; + } + } else { + buffertimestamp = GST_CLOCK_TIME_NONE; + keyframe = TRUE; + } + pagebuffer = gst_ogg_parse_buffer_from_page (&page, startoffset, + buffertimestamp); + + /* We read out 'ret' bytes, so we set the next offset appropriately */ + ogg->offset += ret; + + GST_LOG_OBJECT (ogg, + "processing ogg page (serial %08x, pageno %ld, " + "granule pos %" G_GUINT64_FORMAT ", bos %d, offset %" + G_GUINT64_FORMAT "-%" G_GUINT64_FORMAT ") keyframe=%d", + serialno, ogg_page_pageno (&page), + granule, bos, startoffset, ogg->offset, keyframe); + + if (ogg_page_bos (&page)) { + /* If we've seen this serialno before, this is technically an error, + * we log this case but accept it - this one replaces the previous + * stream with this serialno. We can do this since we're streaming, and + * not supporting seeking... + */ + GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno); + + if (stream != NULL) { + GST_LOG_OBJECT (ogg, "Incorrect stream; repeats serial number %u " + "at offset %" G_GINT64_FORMAT, serialno, ogg->offset); + } + + if (ogg->last_page_not_bos) { + GST_LOG_OBJECT (ogg, "Deleting all referenced streams, found a new " + "chain starting with serial %u", serialno); + gst_ogg_parse_delete_all_streams (ogg); + } + + stream = gst_ogg_parse_new_stream (ogg, &page); + + ogg->last_page_not_bos = FALSE; + + gst_buffer_ref (pagebuffer); + stream->headers = g_list_append (stream->headers, pagebuffer); + + if (!ogg->in_headers) { + GST_LOG_OBJECT (ogg, + "Found start of new chain at offset %" G_GUINT64_FORMAT, + startoffset); + ogg->in_headers = 1; + } + + /* For now, we just keep the header buffer in the stream->headers list; + * it actually gets output once we've collected the entire set + */ + } else { + /* Non-BOS page. Either: we're outside headers, and this isn't a + * header (normal data), outside headers and this is (error!), inside + * headers, this is (append header), or inside headers and this isn't + * (we've found the end of headers; flush the lot!) + * + * Before that, we flag that the last page seen (this one) was not a + * BOS page; that way we know that when we next see a BOS page it's a + * new chain, and we can flush all existing streams. + */ + page_type type; + GstOggStream *stream = gst_ogg_parse_find_stream (ogg, serialno); + + if (!stream) { + GST_LOG_OBJECT (ogg, + "Non-BOS page unexpectedly found at %" G_GINT64_FORMAT, + ogg->offset); + goto failure; + } + + ogg->last_page_not_bos = TRUE; + + type = gst_ogg_parse_is_header (ogg, stream, &page); + + if (type == PAGE_PENDING && ogg->in_headers) { + gst_buffer_ref (pagebuffer); + + stream->unknown_pages = g_list_append (stream->unknown_pages, + pagebuffer); + } else if (type == PAGE_HEADER) { + if (!ogg->in_headers) { + GST_LOG_OBJECT (ogg, "Header page unexpectedly found outside " + "headers at offset %" G_GINT64_FORMAT, ogg->offset); + goto failure; + } else { + /* Append the header to the buffer list, after any unknown previous + * pages + */ + stream->headers = g_list_concat (stream->headers, + stream->unknown_pages); + g_list_free (stream->unknown_pages); + gst_buffer_ref (pagebuffer); + stream->headers = g_list_append (stream->headers, pagebuffer); + } + } else { /* PAGE_DATA, or PAGE_PENDING but outside headers */ + if (ogg->in_headers) { + /* First non-header page... set caps, flush headers. + * + * First up, we build a single GValue list of all the pagebuffers + * we're using for the headers, in order. + * Then we set this on the caps structure. Then we can start pushing + * buffers for the headers, and finally we send this non-header + * page. + */ + GstCaps *caps; + GstStructure *structure; + GValue array = { 0 }; + gint count = 0; + gboolean found_pending_headers = FALSE; + GSList *l; + + g_value_init (&array, GST_TYPE_ARRAY); + + for (l = ogg->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + + if (g_list_length (stream->headers) == 0) { + GST_LOG_OBJECT (ogg, "No primary header found for stream %08lx", + stream->serialno); + goto failure; + } + + gst_ogg_parse_append_header (&array, + GST_BUFFER (stream->headers->data)); + count++; + } + + for (l = ogg->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + GList *j; + + /* already appended the first header, now do headers 2-N */ + for (j = stream->headers->next; j != NULL; j = j->next) { + gst_ogg_parse_append_header (&array, GST_BUFFER (j->data)); + count++; + } + } + + caps = gst_pad_get_caps (ogg->srcpad); + caps = gst_caps_make_writable (caps); + + structure = gst_caps_get_structure (caps, 0); + gst_structure_set_value (structure, "streamheader", &array); + + gst_pad_set_caps (ogg->srcpad, caps); + + g_value_unset (&array); + + if (ogg->caps) + gst_caps_unref (ogg->caps); + ogg->caps = caps; + + GST_LOG_OBJECT (ogg, "Set \"streamheader\" caps with %d buffers " + "(one per page)", count); + + /* Now, we do the same thing, but push buffers... */ + for (l = ogg->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + GstBuffer *buf = GST_BUFFER (stream->headers->data); + + buf = gst_buffer_make_metadata_writable (buf); + gst_buffer_set_caps (buf, caps); + + result = gst_pad_push (ogg->srcpad, buf); + if (result != GST_FLOW_OK) + return result; + } + for (l = ogg->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + GList *j; + + /* pushed the first one for each stream already, now do 2-N */ + for (j = stream->headers->next; j != NULL; j = j->next) { + GstBuffer *buf = GST_BUFFER (j->data); + + buf = gst_buffer_make_metadata_writable (buf); + gst_buffer_set_caps (buf, caps); + + result = gst_pad_push (ogg->srcpad, buf); + if (result != GST_FLOW_OK) + return result; + } + } + + ogg->in_headers = 0; + + /* And finally the pending data pages */ + for (l = ogg->oggstreams; l != NULL; l = l->next) { + GstOggStream *stream = (GstOggStream *) l->data; + GList *k; + + if (stream->unknown_pages == NULL) + continue; + + if (found_pending_headers) { + GST_WARNING_OBJECT (ogg, "Incorrectly muxed headers found at " + "approximate offset %" G_GINT64_FORMAT, ogg->offset); + } + found_pending_headers = TRUE; + + GST_LOG_OBJECT (ogg, "Pushing %d pending pages after headers", + g_list_length (stream->unknown_pages) + 1); + + for (k = stream->unknown_pages; k != NULL; k = k->next) { + GstBuffer *buf; + + buf = gst_buffer_make_metadata_writable (GST_BUFFER (k->data)); + gst_buffer_set_caps (buf, caps); + result = gst_pad_push (ogg->srcpad, buf); + if (result != GST_FLOW_OK) + return result; + } + g_list_foreach (stream->unknown_pages, + (GFunc) gst_mini_object_unref, NULL); + g_list_free (stream->unknown_pages); + stream->unknown_pages = NULL; + } + } + + if (granule == -1) { + stream->stored_buffers = g_list_append (stream->stored_buffers, + pagebuffer); + } else { + while (stream->stored_buffers) { + GstBuffer *buf = stream->stored_buffers->data; + + buf = gst_buffer_make_metadata_writable (buf); + gst_buffer_set_caps (buf, ogg->caps); + GST_BUFFER_TIMESTAMP (buf) = buffertimestamp; + if (!keyframe) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } else { + keyframe = FALSE; + } + + result = gst_pad_push (ogg->srcpad, buf); + if (result != GST_FLOW_OK) + return result; + + stream->stored_buffers = + g_list_delete_link (stream->stored_buffers, + stream->stored_buffers); + } + + pagebuffer = gst_buffer_make_metadata_writable (pagebuffer); + gst_buffer_set_caps (pagebuffer, ogg->caps); + if (!keyframe) { + GST_BUFFER_FLAG_SET (pagebuffer, GST_BUFFER_FLAG_DELTA_UNIT); + } else { + keyframe = FALSE; + } + + result = gst_pad_push (ogg->srcpad, pagebuffer); + if (result != GST_FLOW_OK) + return result; + } + } + } + } + } + + return result; + +failure: + gst_pad_push_event (GST_PAD (ogg->srcpad), gst_event_new_eos ()); + return GST_FLOW_ERROR; +} + +static GstStateChangeReturn +gst_ogg_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstOggParse *ogg; + GstStateChangeReturn result = GST_STATE_CHANGE_FAILURE; + + ogg = GST_OGG_PARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + ogg_sync_init (&ogg->sync); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + ogg_sync_reset (&ogg->sync); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + result = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + ogg_sync_clear (&ogg->sync); + break; + default: + break; + } + return result; +} + +gboolean +gst_ogg_parse_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_ogg_parse_debug, "oggparse", 0, "ogg parser"); + + return gst_element_register (plugin, "oggparse", GST_RANK_NONE, + GST_TYPE_OGG_PARSE); +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.c new file mode 100644 index 0000000..e843f48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.c @@ -0,0 +1,2108 @@ +/* GStreamer Ogg Granulepos Mapping Utility Functions + * Copyright (C) 2006 Tim-Philipp Müller + * Copyright (C) 2009 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstoggstream.h" +#include "dirac_parse.h" +#include "vorbis_parse.h" + +#include + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (gst_ogg_demux_debug); +GST_DEBUG_CATEGORY_EXTERN (gst_ogg_demux_setup_debug); +#define GST_CAT_DEFAULT gst_ogg_demux_debug + +typedef struct _GstOggMap GstOggMap; + +typedef gboolean (*GstOggMapSetupFunc) (GstOggStream * pad, + ogg_packet * packet); +typedef GstClockTime (*GstOggMapToTimeFunc) (GstOggStream * pad, + gint64 granulepos); +typedef gint64 (*GstOggMapToGranuleFunc) (GstOggStream * pad, + gint64 granulepos); +typedef gint64 (*GstOggMapToGranuleposFunc) (GstOggStream * pad, + gint64 granule, gint64 keyframe_granule); + +/* returns TRUE if the granulepos denotes a key frame */ +typedef gboolean (*GstOggMapIsKeyFrameFunc) (GstOggStream * pad, + gint64 granulepos); + +/* returns TRUE if the given packet is a stream header packet */ +typedef gboolean (*GstOggMapIsHeaderPacketFunc) (GstOggStream * pad, + ogg_packet * packet); +typedef gint64 (*GstOggMapPacketDurationFunc) (GstOggStream * pad, + ogg_packet * packet); +typedef void (*GstOggMapExtractTagsFunc) (GstOggStream * pad, + ogg_packet * packet); + +typedef gint64 (*GstOggMapGranuleposToKeyGranuleFunc) (GstOggStream * pad, + gint64 granulepos); + +#define SKELETON_FISBONE_MIN_SIZE 52 +#define SKELETON_FISHEAD_3_3_MIN_SIZE 112 +#define SKELETON_FISHEAD_4_0_MIN_SIZE 80 + +struct _GstOggMap +{ + const gchar *id; + int id_length; + int min_packet_size; + const gchar *media_type; + GstOggMapSetupFunc setup_func; + GstOggMapToGranuleFunc granulepos_to_granule_func; + GstOggMapToGranuleposFunc granule_to_granulepos_func; + GstOggMapIsKeyFrameFunc is_key_frame_func; + GstOggMapIsHeaderPacketFunc is_header_func; + GstOggMapPacketDurationFunc packet_duration_func; + GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func; + GstOggMapExtractTagsFunc extract_tags_func; +}; + +extern const GstOggMap mappers[]; + +GstClockTime +gst_ogg_stream_get_packet_start_time (GstOggStream * pad, ogg_packet * packet) +{ + int duration; + + if (packet->granulepos == -1) { + return GST_CLOCK_TIME_NONE; + } + + duration = gst_ogg_stream_get_packet_duration (pad, packet); + if (duration == -1) { + return GST_CLOCK_TIME_NONE; + } + + return gst_ogg_stream_granule_to_time (pad, + gst_ogg_stream_granulepos_to_granule (pad, + packet->granulepos) - duration); +} + +GstClockTime +gst_ogg_stream_get_start_time_for_granulepos (GstOggStream * pad, + gint64 granulepos) +{ + if (pad->frame_size == 0) + return GST_CLOCK_TIME_NONE; + + return gst_ogg_stream_granule_to_time (pad, + gst_ogg_stream_granulepos_to_granule (pad, granulepos)); +} + +GstClockTime +gst_ogg_stream_get_end_time_for_granulepos (GstOggStream * pad, + gint64 granulepos) +{ + return gst_ogg_stream_granule_to_time (pad, + gst_ogg_stream_granulepos_to_granule (pad, granulepos)); +} + +GstClockTime +gst_ogg_stream_granule_to_time (GstOggStream * pad, gint64 granule) +{ + if (granule == 0 || pad->granulerate_n == 0 || pad->granulerate_d == 0) + return 0; + + return gst_util_uint64_scale (granule, GST_SECOND * pad->granulerate_d, + pad->granulerate_n); +} + +gint64 +gst_ogg_stream_granulepos_to_granule (GstOggStream * pad, gint64 granulepos) +{ + if (granulepos == -1 || granulepos == 0) { + return granulepos; + } + + if (mappers[pad->map].granulepos_to_granule_func == NULL) { + GST_WARNING ("Failed to convert granulepos to granule"); + return -1; + } + + return mappers[pad->map].granulepos_to_granule_func (pad, granulepos); +} + +gint64 +gst_ogg_stream_granulepos_to_key_granule (GstOggStream * pad, gint64 granulepos) +{ + if (mappers[pad->map].granulepos_to_key_granule_func) + return mappers[pad->map].granulepos_to_key_granule_func (pad, granulepos); + + if (granulepos == -1 || granulepos == 0) { + return granulepos; + } + + return granulepos >> pad->granuleshift; +} + +gint64 +gst_ogg_stream_granule_to_granulepos (GstOggStream * pad, gint64 granule, + gint64 keyframe_granule) +{ + if (granule == -1 || granule == 0) { + return granule; + } + + if (mappers[pad->map].granule_to_granulepos_func == NULL) { + GST_WARNING ("Failed to convert granule to granulepos"); + return -1; + } + + return mappers[pad->map].granule_to_granulepos_func (pad, granule, + keyframe_granule); +} + +gboolean +gst_ogg_stream_granulepos_is_key_frame (GstOggStream * pad, gint64 granulepos) +{ + if (granulepos == -1) { + return FALSE; + } + + if (mappers[pad->map].is_key_frame_func == NULL) { + GST_WARNING ("Failed to determine key frame"); + return FALSE; + } + + return mappers[pad->map].is_key_frame_func (pad, granulepos); +} + +gboolean +gst_ogg_stream_packet_is_header (GstOggStream * pad, ogg_packet * packet) +{ + if (mappers[pad->map].is_header_func == NULL) { + GST_WARNING ("Failed to determine header"); + return FALSE; + } + + return mappers[pad->map].is_header_func (pad, packet); +} + +gint64 +gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet * packet) +{ + if (mappers[pad->map].packet_duration_func == NULL) { + GST_WARNING ("Failed to determine packet duration"); + return -1; + } + + return mappers[pad->map].packet_duration_func (pad, packet); +} + + +void +gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet) +{ + if (mappers[pad->map].extract_tags_func == NULL) { + GST_DEBUG ("No tag extraction"); + return; + } + + mappers[pad->map].extract_tags_func (pad, packet); +} + +/* some generic functions */ + +static gboolean +is_keyframe_true (GstOggStream * pad, gint64 granulepos) +{ + return TRUE; +} + +static gint64 +granulepos_to_granule_default (GstOggStream * pad, gint64 granulepos) +{ + gint64 keyindex, keyoffset; + + if (pad->granuleshift != 0) { + keyindex = granulepos >> pad->granuleshift; + keyoffset = granulepos - (keyindex << pad->granuleshift); + return keyindex + keyoffset; + } else { + return granulepos; + } +} + + +static gint64 +granule_to_granulepos_default (GstOggStream * pad, gint64 granule, + gint64 keyframe_granule) +{ + gint64 keyoffset; + + if (pad->granuleshift != 0) { + /* If we don't know where the previous keyframe is yet, assume it is + at 0 or 1, depending on bitstream version. If nothing else, this + avoids getting negative granpos back. */ + if (keyframe_granule < 0) + keyframe_granule = pad->theora_has_zero_keyoffset ? 0 : 1; + keyoffset = granule - keyframe_granule; + return (keyframe_granule << pad->granuleshift) | keyoffset; + } else { + return granule; + } +} + +#ifdef unused +static gboolean +is_header_unknown (GstOggStream * pad, ogg_packet * packet) +{ + GST_WARNING ("don't know how to detect header"); + return FALSE; +} +#endif + +static gboolean +is_header_true (GstOggStream * pad, ogg_packet * packet) +{ + return TRUE; +} + +static gboolean +is_header_count (GstOggStream * pad, ogg_packet * packet) +{ + if (pad->n_header_packets_seen < pad->n_header_packets) { + return TRUE; + } + return FALSE; +} + +static gint64 +packet_duration_constant (GstOggStream * pad, ogg_packet * packet) +{ + return pad->frame_size; +} + +/* helper: extracts tags from vorbis comment ogg packet. + * Returns result in *tags after free'ing existing *tags (if any) */ +static gboolean +tag_list_from_vorbiscomment_packet (ogg_packet * packet, + const guint8 * id_data, const guint id_data_length, GstTagList ** tags) +{ + GstBuffer *buf = NULL; + gchar *encoder = NULL; + GstTagList *list; + gboolean ret = TRUE; + + g_return_val_if_fail (tags != NULL, FALSE); + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) packet->packet; + GST_BUFFER_SIZE (buf) = packet->bytes; + + list = gst_tag_list_from_vorbiscomment_buffer (buf, id_data, id_data_length, + &encoder); + + if (!list) { + GST_WARNING ("failed to decode vorbis comments"); + ret = FALSE; + goto exit; + } + + if (encoder) { + if (encoder[0]) + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER, encoder, + NULL); + g_free (encoder); + } + +exit: + if (*tags) + gst_tag_list_free (*tags); + *tags = list; + + gst_buffer_unref (buf); + + return ret; +} + +/* theora */ + +static gboolean +setup_theora_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint w, h, par_d, par_n; + guint8 vmaj, vmin, vrev; + + vmaj = data[7]; + vmin = data[8]; + vrev = data[9]; + + w = GST_READ_UINT24_BE (data + 14) & 0xFFFFFF; + h = GST_READ_UINT24_BE (data + 17) & 0xFFFFFF; + + pad->granulerate_n = GST_READ_UINT32_BE (data + 22); + pad->granulerate_d = GST_READ_UINT32_BE (data + 26); + + par_n = GST_READ_UINT24_BE (data + 30); + par_d = GST_READ_UINT24_BE (data + 33); + + GST_LOG ("fps = %d/%d, PAR = %u/%u, width = %u, height = %u", + pad->granulerate_n, pad->granulerate_d, par_n, par_d, w, h); + + /* 2 bits + 3 bits = 5 bits KFGSHIFT */ + pad->granuleshift = ((GST_READ_UINT8 (data + 40) & 0x03) << 3) + + (GST_READ_UINT8 (data + 41) >> 5); + + pad->is_video = TRUE; + pad->n_header_packets = 3; + pad->frame_size = 1; + + pad->bitrate = GST_READ_UINT24_BE (data + 37); + GST_LOG ("bit rate: %d", pad->bitrate); + + if (pad->granulerate_n == 0 || pad->granulerate_d == 0) { + GST_WARNING ("frame rate %d/%d", pad->granulerate_n, pad->granulerate_d); + return FALSE; + } + + /* The interpretation of the granule position has changed with 3.2.1. + The granule is now made from the number of frames encoded, rather than + the index of the frame being encoded - so there is a difference of 1. */ + pad->theora_has_zero_keyoffset = + ((vmaj << 16) | (vmin << 8) | vrev) < 0x030201; + + pad->caps = gst_caps_new_simple ("video/x-theora", NULL); + + if (w > 0 && h > 0) { + gst_caps_set_simple (pad->caps, "width", G_TYPE_INT, w, "height", + G_TYPE_INT, h, NULL); + } + + /* PAR of 0:N, N:0 and 0:0 is allowed and maps to 1:1 */ + if (par_n == 0 || par_d == 0) + par_n = par_d = 1; + + /* only add framerate now so caps look prettier, with width/height first */ + gst_caps_set_simple (pad->caps, "framerate", GST_TYPE_FRACTION, + pad->granulerate_n, pad->granulerate_d, "pixel-aspect-ratio", + GST_TYPE_FRACTION, par_n, par_d, NULL); + + return TRUE; +} + +static gint64 +granulepos_to_granule_theora (GstOggStream * pad, gint64 granulepos) +{ + gint64 keyindex, keyoffset; + + if (pad->granuleshift != 0) { + keyindex = granulepos >> pad->granuleshift; + keyoffset = granulepos - (keyindex << pad->granuleshift); + if (pad->theora_has_zero_keyoffset) { + keyoffset++; + } + return keyindex + keyoffset; + } else { + return granulepos; + } +} + +static gboolean +is_keyframe_theora (GstOggStream * pad, gint64 granulepos) +{ + gint64 frame_mask; + + if (granulepos == (gint64) - 1) + return FALSE; + + frame_mask = (1 << pad->granuleshift) - 1; + + return ((granulepos & frame_mask) == 0); +} + +static gboolean +is_header_theora (GstOggStream * pad, ogg_packet * packet) +{ + return (packet->bytes > 0 && (packet->packet[0] & 0x80) == 0x80); +} + +static void +extract_tags_theora (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes > 0 && packet->packet[0] == 0x81) { + tag_list_from_vorbiscomment_packet (packet, + (const guint8 *) "\201theora", 7, &pad->taglist); + + if (!pad->taglist) + pad->taglist = gst_tag_list_new (); + + if (pad->bitrate) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, (guint) pad->bitrate, NULL); + } +} + +/* dirac */ + +static gboolean +setup_dirac_mapper (GstOggStream * pad, ogg_packet * packet) +{ + int ret; + DiracSequenceHeader header; + + ret = dirac_sequence_header_parse (&header, packet->packet + 13, + packet->bytes - 13); + if (ret == 0) { + GST_DEBUG ("Failed to parse Dirac sequence header"); + return FALSE; + } + + pad->is_video = TRUE; + pad->granulerate_n = header.frame_rate_numerator * 2; + pad->granulerate_d = header.frame_rate_denominator; + pad->granuleshift = 22; + pad->n_header_packets = 1; + pad->frame_size = 2; + + if (header.interlaced_coding != 0) { + GST_DEBUG ("non-progressive Dirac coding not implemented"); + return FALSE; + } + + pad->caps = gst_caps_new_simple ("video/x-dirac", + "width", G_TYPE_INT, header.width, + "height", G_TYPE_INT, header.height, + "interlaced", G_TYPE_BOOLEAN, header.interlaced, + "pixel-aspect-ratio", GST_TYPE_FRACTION, + header.aspect_ratio_numerator, header.aspect_ratio_denominator, + "framerate", GST_TYPE_FRACTION, header.frame_rate_numerator, + header.frame_rate_denominator, NULL); + + return TRUE; +} + +#define OGG_DIRAC_GRANULE_LOW_MASK ((1<<22) - 1) +static gboolean +is_keyframe_dirac (GstOggStream * pad, gint64 granulepos) +{ + int dist_h; + int dist_l; + int dist; + + if (granulepos == -1) + return -1; + + dist_h = (granulepos >> 22) & 0xff; + dist_l = granulepos & 0xff; + dist = (dist_h << 8) | dist_l; + + return (dist == 0); +} + +static gint64 +granulepos_to_granule_dirac (GstOggStream * pad, gint64 gp) +{ + gint64 pt; + int delay; + gint64 dt; + + pt = ((gp >> 22) + (gp & OGG_DIRAC_GRANULE_LOW_MASK)) >> 9; + delay = (gp >> 9) & 0x1fff; + dt = pt - delay; + + GST_DEBUG ("pt %" G_GINT64_FORMAT " delay %d", pt, delay); + + return dt + 4; +} + +static gint64 +granule_to_granulepos_dirac (GstOggStream * pad, gint64 granule, + gint64 keyframe_granule) +{ + /* This conversion requires knowing more details about the Dirac + * stream. */ + return -1; +} + +static gint64 +granulepos_to_key_granule_dirac (GstOggStream * pad, gint64 gp) +{ + gint64 pt; + int dist_h; + int dist_l; + int dist; + int delay; + gint64 dt; + + if (gp == -1 || gp == 0) + return gp; + + pt = ((gp >> 22) + (gp & OGG_DIRAC_GRANULE_LOW_MASK)) >> 9; + dist_h = (gp >> 22) & 0xff; + dist_l = gp & 0xff; + dist = (dist_h << 8) | dist_l; + delay = (gp >> 9) & 0x1fff; + dt = pt - delay; + + return dt - 2 * dist + 4; +} + +/* VP8 */ + +static gboolean +setup_vp8_mapper (GstOggStream * pad, ogg_packet * packet) +{ + gint width, height, par_n, par_d, fps_n, fps_d; + + if (packet->bytes < 26) { + GST_DEBUG ("Failed to parse VP8 BOS page"); + return FALSE; + } + + width = GST_READ_UINT16_BE (packet->packet + 8); + height = GST_READ_UINT16_BE (packet->packet + 10); + par_n = GST_READ_UINT24_BE (packet->packet + 12); + par_d = GST_READ_UINT24_BE (packet->packet + 15); + fps_n = GST_READ_UINT32_BE (packet->packet + 18); + fps_d = GST_READ_UINT32_BE (packet->packet + 22); + + pad->is_video = TRUE; + pad->is_vp8 = TRUE; + pad->granulerate_n = fps_n; + pad->granulerate_d = fps_d; + pad->n_header_packets = 2; + pad->frame_size = 1; + + pad->caps = gst_caps_new_simple ("video/x-vp8", + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "pixel-aspect-ratio", GST_TYPE_FRACTION, + par_n, par_d, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, NULL); + + return TRUE; +} + +static gboolean +is_keyframe_vp8 (GstOggStream * pad, gint64 granulepos) +{ + guint64 gpos = granulepos; + + if (granulepos == -1) + return FALSE; + + /* Get rid of flags */ + gpos >>= 3; + + return ((gpos & 0x07ffffff) == 0); +} + +static gint64 +granulepos_to_granule_vp8 (GstOggStream * pad, gint64 gpos) +{ + guint64 gp = (guint64) gpos; + guint32 pt; + guint32 dist; + + pt = (gp >> 32); + dist = (gp >> 3) & 0x07ffffff; + + GST_DEBUG ("pt %u, dist %u", pt, dist); + + return pt; +} + +static gint64 +granule_to_granulepos_vp8 (GstOggStream * pad, gint64 granule, + gint64 keyframe_granule) +{ + /* FIXME: This requires to look into the content of the packets + * because the simple granule counter doesn't know about invisible + * frames... + */ + return -1; +} + +/* Check if this packet contains an invisible frame or not */ +static gint64 +packet_duration_vp8 (GstOggStream * pad, ogg_packet * packet) +{ + guint32 hdr; + + if (packet->bytes < 3) + return 0; + + hdr = GST_READ_UINT24_LE (packet->packet); + + return (((hdr >> 4) & 1) != 0) ? 1 : 0; +} + +static gint64 +granulepos_to_key_granule_vp8 (GstOggStream * pad, gint64 granulepos) +{ + guint64 gp = granulepos; + guint64 pts = (gp >> 32); + guint32 dist = (gp >> 3) & 0x07ffffff; + + if (granulepos == -1 || granulepos == 0) + return granulepos; + + if (dist > pts) + return 0; + + return pts - dist; +} + +static gboolean +is_header_vp8 (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes >= 5 && packet->packet[0] == 0x4F && + packet->packet[1] == 0x56 && packet->packet[2] == 0x50 && + packet->packet[3] == 0x38 && packet->packet[4] == 0x30) + return TRUE; + return FALSE; +} + +static void +extract_tags_vp8 (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes >= 7 && memcmp (packet->packet, "OVP80\2 ", 7) == 0) { + tag_list_from_vorbiscomment_packet (packet, + (const guint8 *) "OVP80\2 ", 7, &pad->taglist); + } +} + +/* vorbis */ + +static gboolean +setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint chans; + + data += 1 + 6; + pad->version = GST_READ_UINT32_LE (data); + data += 4; + chans = GST_READ_UINT8 (data); + data += 1; + pad->granulerate_n = GST_READ_UINT32_LE (data); + pad->granulerate_d = 1; + pad->granuleshift = 0; + pad->last_size = 0; + GST_LOG ("sample rate: %d", pad->granulerate_n); + + data += 4; + pad->bitrate_upper = GST_READ_UINT32_LE (data); + data += 4; + pad->bitrate_nominal = GST_READ_UINT32_LE (data); + data += 4; + pad->bitrate_lower = GST_READ_UINT32_LE (data); + + if (pad->bitrate_nominal > 0) + pad->bitrate = pad->bitrate_nominal; + + if (pad->bitrate_upper > 0 && !pad->bitrate) + pad->bitrate = pad->bitrate_upper; + + if (pad->bitrate_lower > 0 && !pad->bitrate) + pad->bitrate = pad->bitrate_lower; + + GST_LOG ("bit rate: %d", pad->bitrate); + + pad->n_header_packets = 3; + + if (pad->granulerate_n == 0) + return FALSE; + + parse_vorbis_header_packet (pad, packet); + + pad->caps = gst_caps_new_simple ("audio/x-vorbis", + "rate", G_TYPE_INT, pad->granulerate_n, "channels", G_TYPE_INT, chans, + NULL); + + return TRUE; +} + +static gboolean +is_header_vorbis (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes > 0 && (packet->packet[0] & 0x01) == 0) + return FALSE; + + if (packet->packet[0] == 5) { + parse_vorbis_setup_packet (pad, packet); + } + + return TRUE; +} + +static void +extract_tags_vorbis (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes == 0 || (packet->packet[0] & 0x01) == 0) + return; + + if (((guint8 *) (packet->packet))[0] == 0x03) { + tag_list_from_vorbiscomment_packet (packet, + (const guint8 *) "\003vorbis", 7, &pad->taglist); + + if (!pad->taglist) + pad->taglist = gst_tag_list_new (); + + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER_VERSION, pad->version, NULL); + + if (pad->bitrate_nominal > 0) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_NOMINAL_BITRATE, (guint) pad->bitrate_nominal, NULL); + + if (pad->bitrate_upper > 0) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MAXIMUM_BITRATE, (guint) pad->bitrate_upper, NULL); + + if (pad->bitrate_lower > 0) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MINIMUM_BITRATE, (guint) pad->bitrate_lower, NULL); + + if (pad->bitrate) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, (guint) pad->bitrate, NULL); + } +} + +static gint64 +packet_duration_vorbis (GstOggStream * pad, ogg_packet * packet) +{ + int mode; + int size; + int duration; + + if (packet->packet[0] & 1) + return 0; + + mode = (packet->packet[0] >> 1) & ((1 << pad->vorbis_log2_num_modes) - 1); + size = pad->vorbis_mode_sizes[mode] ? pad->long_size : pad->short_size; + + if (pad->last_size == 0) { + duration = 0; + } else { + duration = pad->last_size / 4 + size / 4; + } + pad->last_size = size; + + GST_DEBUG ("duration %d", (int) duration); + + return duration; +} + +/* speex */ + + +static gboolean +setup_speex_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint chans; + + data += 8 + 20 + 4 + 4; + pad->granulerate_n = GST_READ_UINT32_LE (data); + pad->granulerate_d = 1; + pad->granuleshift = 0; + + data += 4 + 4 + 4; + chans = GST_READ_UINT32_LE (data); + data += 4; + pad->bitrate = GST_READ_UINT32_LE (data); + + GST_LOG ("sample rate: %d, channels: %u", pad->granulerate_n, chans); + GST_LOG ("bit rate: %d", pad->bitrate); + + pad->n_header_packets = GST_READ_UINT32_LE (packet->packet + 68) + 2; + pad->frame_size = GST_READ_UINT32_LE (packet->packet + 64) * + GST_READ_UINT32_LE (packet->packet + 56); + + if (pad->granulerate_n == 0) + return FALSE; + + pad->caps = gst_caps_new_simple ("audio/x-speex", "rate", G_TYPE_INT, + pad->granulerate_n, "channels", G_TYPE_INT, chans, NULL); + + return TRUE; +} + +static void +extract_tags_count (GstOggStream * pad, ogg_packet * packet) +{ + /* packet 2 must be comment packet */ + if (packet->bytes > 0 && pad->n_header_packets_seen == 1) { + tag_list_from_vorbiscomment_packet (packet, NULL, 0, &pad->taglist); + + if (!pad->taglist) + pad->taglist = gst_tag_list_new (); + + if (pad->bitrate) + gst_tag_list_add (pad->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, (guint) pad->bitrate, NULL); + } +} + + +/* flac */ + +static gboolean +setup_fLaC_mapper (GstOggStream * pad, ogg_packet * packet) +{ + pad->granulerate_n = 0; + pad->granulerate_d = 1; + pad->granuleshift = 0; + + pad->n_header_packets = 3; + + pad->caps = gst_caps_new_simple ("audio/x-flac", NULL); + + return TRUE; +} + +static gboolean +is_header_fLaC (GstOggStream * pad, ogg_packet * packet) +{ + if (pad->n_header_packets_seen == 1) { + pad->granulerate_n = (packet->packet[14] << 12) | + (packet->packet[15] << 4) | ((packet->packet[16] >> 4) & 0xf); + } + + if (pad->n_header_packets_seen < pad->n_header_packets) { + return TRUE; + } + + return FALSE; +} + +static gboolean +setup_flac_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint chans; + + /* see http://flac.sourceforge.net/ogg_mapping.html */ + + pad->granulerate_n = (GST_READ_UINT32_BE (data + 27) & 0xFFFFF000) >> 12; + pad->granulerate_d = 1; + pad->granuleshift = 0; + chans = ((GST_READ_UINT32_BE (data + 27) & 0x00000E00) >> 9) + 1; + + GST_DEBUG ("sample rate: %d, channels: %u", pad->granulerate_n, chans); + + pad->n_header_packets = GST_READ_UINT16_BE (packet->packet + 7); + + if (pad->granulerate_n == 0) + return FALSE; + + pad->caps = gst_caps_new_simple ("audio/x-flac", "rate", G_TYPE_INT, + pad->granulerate_n, "channels", G_TYPE_INT, chans, NULL); + + return TRUE; +} + +static gboolean +is_header_flac (GstOggStream * pad, ogg_packet * packet) +{ + return (packet->bytes > 0 && (packet->packet[0] != 0xff)); +} + +static gint64 +packet_duration_flac (GstOggStream * pad, ogg_packet * packet) +{ + int block_size_index; + + if (packet->bytes < 4) + return -1; + + block_size_index = packet->packet[2] >> 4; + if (block_size_index == 1) + return 192; + if (block_size_index >= 2 && block_size_index <= 5) { + return 576 << (block_size_index - 2); + } + if (block_size_index >= 8) { + return 256 << (block_size_index - 8); + } + if (block_size_index == 6 || block_size_index == 7) { + guint len, bytes = (block_size_index - 6) + 1; + guint8 tmp; + + if (packet->bytes < 4 + 1 + bytes) + return -1; + tmp = packet->packet[4]; + /* utf-8 prefix */ + len = 0; + while (tmp & 0x80) { + len++; + tmp <<= 1; + } + if (len == 2) + return -1; + if (len == 0) + len++; + if (packet->bytes < 4 + len + bytes) + return -1; + if (bytes == 1) { + return packet->packet[4 + len] + 1; + } else { + return GST_READ_UINT16_BE (packet->packet + 4 + len) + 1; + } + } + return -1; +} + +static void +extract_tags_flac (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes > 4 && ((packet->packet[0] & 0x7F) == 0x4)) { + tag_list_from_vorbiscomment_packet (packet, + packet->packet, 4, &pad->taglist); + } +} + +/* fishead */ + +static gboolean +setup_fishead_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data; + gint64 prestime_n, prestime_d; + gint64 basetime_n, basetime_d; + + data = packet->packet; + + data += 8; /* header */ + + pad->skeleton_major = GST_READ_UINT16_LE (data); + data += 2; + pad->skeleton_minor = GST_READ_UINT16_LE (data); + data += 2; + + prestime_n = (gint64) GST_READ_UINT64_LE (data); + data += 8; + prestime_d = (gint64) GST_READ_UINT64_LE (data); + data += 8; + basetime_n = (gint64) GST_READ_UINT64_LE (data); + data += 8; + basetime_d = (gint64) GST_READ_UINT64_LE (data); + data += 8; + + /* FIXME: we don't use basetime anywhere in the demuxer! */ + if (basetime_d != 0) + pad->basetime = gst_util_uint64_scale (GST_SECOND, basetime_n, basetime_d); + else + pad->basetime = -1; + + if (prestime_d != 0) + pad->prestime = gst_util_uint64_scale (GST_SECOND, prestime_n, prestime_d); + else + pad->prestime = -1; + + /* Ogg Skeleton 3.3+ streams provide additional information in the header */ + if (packet->bytes >= SKELETON_FISHEAD_3_3_MIN_SIZE && pad->skeleton_major == 3 + && pad->skeleton_minor > 0) { + gint64 firstsampletime_n, firstsampletime_d; + gint64 lastsampletime_n, lastsampletime_d; + gint64 firstsampletime, lastsampletime; + guint64 segment_length, content_offset; + + firstsampletime_n = GST_READ_UINT64_LE (data + 64); + firstsampletime_d = GST_READ_UINT64_LE (data + 72); + lastsampletime_n = GST_READ_UINT64_LE (data + 80); + lastsampletime_d = GST_READ_UINT64_LE (data + 88); + segment_length = GST_READ_UINT64_LE (data + 96); + content_offset = GST_READ_UINT64_LE (data + 104); + + GST_INFO ("firstsampletime %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + firstsampletime_n, firstsampletime_d); + GST_INFO ("lastsampletime %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + lastsampletime_n, lastsampletime_d); + GST_INFO ("segment length %" G_GUINT64_FORMAT, segment_length); + GST_INFO ("content offset %" G_GUINT64_FORMAT, content_offset); + + if (firstsampletime_d > 0) + firstsampletime = gst_util_uint64_scale (GST_SECOND, + firstsampletime_n, firstsampletime_d); + else + firstsampletime = 0; + + if (lastsampletime_d > 0) + lastsampletime = gst_util_uint64_scale (GST_SECOND, + lastsampletime_n, lastsampletime_d); + else + lastsampletime = 0; + + if (lastsampletime > firstsampletime) + pad->total_time = lastsampletime - firstsampletime; + else + pad->total_time = -1; + + GST_INFO ("skeleton fishead parsed total: %" GST_TIME_FORMAT, + GST_TIME_ARGS (pad->total_time)); + } else if (packet->bytes >= SKELETON_FISHEAD_4_0_MIN_SIZE + && pad->skeleton_major == 4) { + guint64 segment_length, content_offset; + + segment_length = GST_READ_UINT64_LE (data + 64); + content_offset = GST_READ_UINT64_LE (data + 72); + + GST_INFO ("segment length %" G_GUINT64_FORMAT, segment_length); + GST_INFO ("content offset %" G_GUINT64_FORMAT, content_offset); + } else { + pad->total_time = -1; + } + + GST_INFO ("skeleton fishead %u.%u parsed (basetime: %" GST_TIME_FORMAT + ", prestime: %" GST_TIME_FORMAT ")", pad->skeleton_major, + pad->skeleton_minor, GST_TIME_ARGS (pad->basetime), + GST_TIME_ARGS (pad->prestime)); + + pad->is_skeleton = TRUE; + pad->is_sparse = TRUE; + + pad->caps = gst_caps_new_simple ("none/none", NULL); + + return TRUE; +} + +gboolean +gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size, + guint32 * serialno, GstOggSkeleton * type) +{ + GstOggSkeleton stype; + guint serial_offset; + + if (size < SKELETON_FISBONE_MIN_SIZE) { + GST_WARNING ("small fisbone packet of size %d, ignoring", size); + return FALSE; + } + + if (memcmp (data, "fisbone\0", 8) == 0) { + GST_INFO ("got fisbone packet"); + stype = GST_OGG_SKELETON_FISBONE; + serial_offset = 12; + } else if (memcmp (data, "index\0", 6) == 0) { + GST_INFO ("got index packet"); + stype = GST_OGG_SKELETON_INDEX; + serial_offset = 6; + } else if (memcmp (data, "fishead\0", 8) == 0) { + return FALSE; + } else { + GST_WARNING ("unknown skeleton packet \"%10.10s\"", data); + return FALSE; + } + + if (serialno) + *serialno = GST_READ_UINT32_LE (data + serial_offset); + + if (type) + *type = stype; + + return TRUE; +} + +gboolean +gst_ogg_map_add_fisbone (GstOggStream * pad, GstOggStream * skel_pad, + const guint8 * data, guint size, GstClockTime * p_start_time) +{ + GstClockTime start_time; + gint64 start_granule; + + if (pad->have_fisbone) { + GST_DEBUG ("already have fisbone, ignoring second one"); + return FALSE; + } + + /* skip "fisbone\0" + headers offset + serialno + num headers */ + data += 8 + 4 + 4 + 4; + + pad->have_fisbone = TRUE; + + /* we just overwrite whatever was set before by the format-specific setup */ + pad->granulerate_n = GST_READ_UINT64_LE (data); + pad->granulerate_d = GST_READ_UINT64_LE (data + 8); + + start_granule = GST_READ_UINT64_LE (data + 16); + pad->preroll = GST_READ_UINT32_LE (data + 24); + pad->granuleshift = GST_READ_UINT8 (data + 28); + + start_time = granulepos_to_granule_default (pad, start_granule); + + GST_INFO ("skeleton fisbone parsed " + "(start time: %" GST_TIME_FORMAT + " granulerate_n: %d granulerate_d: %d " + " preroll: %" G_GUINT32_FORMAT " granuleshift: %d)", + GST_TIME_ARGS (start_time), + pad->granulerate_n, pad->granulerate_d, pad->preroll, pad->granuleshift); + + if (p_start_time) + *p_start_time = start_time; + + return TRUE; +} + +static gboolean +read_vlc (const guint8 ** data, guint * size, guint64 * result) +{ + gint shift = 0; + guint8 byte; + + *result = 0; + + do { + if (G_UNLIKELY (*size < 1)) + return FALSE; + + byte = **data; + *result |= ((byte & 0x7f) << shift); + shift += 7; + + (*data)++; + (*size)--; + } while ((byte & 0x80) != 0x80); + + return TRUE; +} + +gboolean +gst_ogg_map_add_index (GstOggStream * pad, GstOggStream * skel_pad, + const guint8 * data, guint size) +{ + guint64 i, n_keypoints, isize; + guint64 offset, timestamp; + guint64 offset_d, timestamp_d; + + if (pad->index) { + GST_DEBUG ("already have index, ignoring second one"); + return TRUE; + } + + if ((skel_pad->skeleton_major == 3 && size < 26) || + (skel_pad->skeleton_major == 4 && size < 62)) { + GST_WARNING ("small index packet of size %u, ignoring", size); + return FALSE; + } + + /* skip "index\0" + serialno */ + data += 6 + 4; + size -= 6 + 4; + + n_keypoints = GST_READ_UINT64_LE (data); + + data += 8; + size -= 8; + + pad->kp_denom = GST_READ_UINT64_LE (data); + if (pad->kp_denom == 0) + pad->kp_denom = 1; + + data += 8; + size -= 8; + + if (skel_pad->skeleton_major == 4) { + gint64 firstsampletime_n; + gint64 lastsampletime_n; + gint64 firstsampletime, lastsampletime; + + firstsampletime_n = GST_READ_UINT64_LE (data + 0); + lastsampletime_n = GST_READ_UINT64_LE (data + 8); + + GST_INFO ("firstsampletime %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + firstsampletime_n, pad->kp_denom); + GST_INFO ("lastsampletime %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, + lastsampletime_n, pad->kp_denom); + + firstsampletime = gst_util_uint64_scale (GST_SECOND, + firstsampletime_n, pad->kp_denom); + lastsampletime = gst_util_uint64_scale (GST_SECOND, + lastsampletime_n, pad->kp_denom); + + if (lastsampletime > firstsampletime) + pad->total_time = lastsampletime - firstsampletime; + else + pad->total_time = -1; + + GST_INFO ("skeleton index parsed total: %" GST_TIME_FORMAT, + GST_TIME_ARGS (pad->total_time)); + + data += 16; + size -= 16; + } + + GST_INFO ("skeleton index has %" G_GUINT64_FORMAT " keypoints, denom: %" + G_GINT64_FORMAT, n_keypoints, pad->kp_denom); + + pad->index = g_try_new (GstOggIndex, n_keypoints); + if (!pad->index) + return FALSE; + + isize = 0; + offset = 0; + timestamp = 0; + + for (i = 0; i < n_keypoints; i++) { + /* read deltas */ + if (!read_vlc (&data, &size, &offset_d)) + break; + if (!read_vlc (&data, &size, ×tamp_d)) + break; + + offset += offset_d; + timestamp += timestamp_d; + + pad->index[i].offset = offset; + pad->index[i].timestamp = timestamp; + isize++; + + GST_INFO ("offset %" G_GUINT64_FORMAT " time %" G_GUINT64_FORMAT, offset, + timestamp); + } + if (isize != n_keypoints) { + GST_WARNING ("truncated index, expected %" G_GUINT64_FORMAT ", found %" + G_GUINT64_FORMAT, n_keypoints, isize); + } + pad->n_index = isize; + /* try to use the index to estimate the bitrate */ + if (isize > 2) { + guint64 so, eo, st, et, b, t; + + /* get start and end offset and timestamps */ + so = pad->index[0].offset; + st = pad->index[0].timestamp; + eo = pad->index[isize - 1].offset; + et = pad->index[isize - 1].timestamp; + + b = eo - so; + t = et - st; + + GST_DEBUG ("bytes/time %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT, b, t); + + /* this is the total stream bitrate according to this index */ + pad->idx_bitrate = gst_util_uint64_scale (8 * b, pad->kp_denom, t); + + GST_DEBUG ("bitrate %" G_GUINT64_FORMAT, pad->idx_bitrate); + } + + return TRUE; +} + +static gint +gst_ogg_index_compare (const GstOggIndex * index, const guint64 * ts, + gpointer user_data) +{ + if (index->timestamp < *ts) + return -1; + else if (index->timestamp > *ts) + return 1; + else + return 0; +} + +gboolean +gst_ogg_map_search_index (GstOggStream * pad, gboolean before, + guint64 * timestamp, guint64 * offset) +{ + guint64 n_index; + guint64 ts; + GstOggIndex *best; + + n_index = pad->n_index; + if (n_index == 0 || pad->index == NULL) + return FALSE; + + ts = gst_util_uint64_scale (*timestamp, pad->kp_denom, GST_SECOND); + GST_INFO ("timestamp %" G_GUINT64_FORMAT, ts); + + best = + gst_util_array_binary_search (pad->index, n_index, sizeof (GstOggIndex), + (GCompareDataFunc) gst_ogg_index_compare, GST_SEARCH_MODE_BEFORE, &ts, + NULL); + + if (best == NULL) + return FALSE; + + GST_INFO ("found at index %u", (guint) (best - pad->index)); + + if (offset) + *offset = best->offset; + if (timestamp) + *timestamp = + gst_util_uint64_scale (best->timestamp, GST_SECOND, pad->kp_denom); + + return TRUE; +} + +/* Do we need these for something? + * ogm->hdr.size = GST_READ_UINT32_LE (&data[13]); + * ogm->hdr.time_unit = GST_READ_UINT64_LE (&data[17]); + * ogm->hdr.samples_per_unit = GST_READ_UINT64_LE (&data[25]); + * ogm->hdr.default_len = GST_READ_UINT32_LE (&data[33]); + * ogm->hdr.buffersize = GST_READ_UINT32_LE (&data[37]); + * ogm->hdr.bits_per_sample = GST_READ_UINT32_LE (&data[41]); + */ + +static gboolean +is_header_ogm (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes >= 1 && (packet->packet[0] & 0x01)) + return TRUE; + + return FALSE; +} + +static void +extract_tags_ogm (GstOggStream * pad, ogg_packet * packet) +{ + if (!(packet->packet[0] & 1) && (packet->packet[0] & 3 && pad->is_ogm_text)) { + tag_list_from_vorbiscomment_packet (packet, + (const guint8 *) "\003vorbis", 7, &pad->taglist); + } +} + +static gint64 +packet_duration_ogm (GstOggStream * pad, ogg_packet * packet) +{ + const guint8 *data; + int samples; + int offset; + int n; + + data = packet->packet; + offset = 1 + (((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1)); + + if (offset > packet->bytes) { + GST_ERROR ("buffer too small"); + return -1; + } + + samples = 0; + for (n = offset - 1; n > 0; n--) { + samples = (samples << 8) | data[n]; + } + + return samples; +} + +static gboolean +setup_ogmaudio_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint32 fourcc; + + pad->granulerate_n = GST_READ_UINT64_LE (data + 25); + pad->granulerate_d = 1; + + fourcc = GST_READ_UINT32_LE (data + 9); + GST_DEBUG ("fourcc: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); + + pad->caps = gst_riff_create_audio_caps (fourcc, NULL, NULL, NULL, NULL, NULL); + + GST_LOG ("sample rate: %d", pad->granulerate_n); + if (pad->granulerate_n == 0) + return FALSE; + + if (pad->caps) { + gst_caps_set_simple (pad->caps, + "rate", G_TYPE_INT, pad->granulerate_n, NULL); + } else { + pad->caps = gst_caps_new_simple ("audio/x-ogm-unknown", + "fourcc", GST_TYPE_FOURCC, fourcc, + "rate", G_TYPE_INT, pad->granulerate_n, NULL); + } + + pad->n_header_packets = 1; + pad->is_ogm = TRUE; + + return TRUE; +} + +static gboolean +setup_ogmvideo_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + guint32 fourcc; + int width, height; + gint64 time_unit; + + GST_DEBUG ("time unit %d", GST_READ_UINT32_LE (data + 16)); + GST_DEBUG ("samples per unit %d", GST_READ_UINT32_LE (data + 24)); + + pad->is_video = TRUE; + pad->granulerate_n = 10000000; + time_unit = GST_READ_UINT64_LE (data + 17); + if (time_unit > G_MAXINT || time_unit < G_MININT) { + GST_WARNING ("timeunit is out of range"); + } + pad->granulerate_d = (gint) CLAMP (time_unit, G_MININT, G_MAXINT); + + GST_LOG ("fps = %d/%d = %.3f", + pad->granulerate_n, pad->granulerate_d, + (double) pad->granulerate_n / pad->granulerate_d); + + fourcc = GST_READ_UINT32_LE (data + 9); + width = GST_READ_UINT32_LE (data + 45); + height = GST_READ_UINT32_LE (data + 49); + GST_DEBUG ("fourcc: %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); + + pad->caps = gst_riff_create_video_caps (fourcc, NULL, NULL, NULL, NULL, NULL); + + if (pad->caps == NULL) { + pad->caps = gst_caps_new_simple ("video/x-ogm-unknown", + "fourcc", GST_TYPE_FOURCC, fourcc, + "framerate", GST_TYPE_FRACTION, pad->granulerate_n, + pad->granulerate_d, NULL); + } else { + gst_caps_set_simple (pad->caps, + "framerate", GST_TYPE_FRACTION, pad->granulerate_n, + pad->granulerate_d, + "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + } + GST_DEBUG ("caps: %" GST_PTR_FORMAT, pad->caps); + + pad->n_header_packets = 1; + pad->frame_size = 1; + pad->is_ogm = TRUE; + + return TRUE; +} + +static gboolean +setup_ogmtext_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + gint64 time_unit; + + pad->granulerate_n = 10000000; + time_unit = GST_READ_UINT64_LE (data + 17); + if (time_unit > G_MAXINT || time_unit < G_MININT) { + GST_WARNING ("timeunit is out of range"); + } + pad->granulerate_d = (gint) CLAMP (time_unit, G_MININT, G_MAXINT); + + GST_LOG ("fps = %d/%d = %.3f", + pad->granulerate_n, pad->granulerate_d, + (double) pad->granulerate_n / pad->granulerate_d); + + if (pad->granulerate_d <= 0) + return FALSE; + + pad->caps = gst_caps_new_simple ("text/plain", NULL); + + pad->n_header_packets = 1; + pad->is_ogm = TRUE; + pad->is_ogm_text = TRUE; + pad->is_sparse = TRUE; + + return TRUE; +} + +/* PCM */ + +#define OGGPCM_FMT_S8 0x00000000 /* Signed integer 8 bit */ +#define OGGPCM_FMT_U8 0x00000001 /* Unsigned integer 8 bit */ +#define OGGPCM_FMT_S16_LE 0x00000002 /* Signed integer 16 bit little endian */ +#define OGGPCM_FMT_S16_BE 0x00000003 /* Signed integer 16 bit big endian */ +#define OGGPCM_FMT_S24_LE 0x00000004 /* Signed integer 24 bit little endian */ +#define OGGPCM_FMT_S24_BE 0x00000005 /* Signed integer 24 bit big endian */ +#define OGGPCM_FMT_S32_LE 0x00000006 /* Signed integer 32 bit little endian */ +#define OGGPCM_FMT_S32_BE 0x00000007 /* Signed integer 32 bit big endian */ + +#define OGGPCM_FMT_ULAW 0x00000010 /* G.711 u-law encoding (8 bit) */ +#define OGGPCM_FMT_ALAW 0x00000011 /* G.711 A-law encoding (8 bit) */ + +#define OGGPCM_FMT_FLT32_LE 0x00000020 /* IEEE Float [-1,1] 32 bit little endian */ +#define OGGPCM_FMT_FLT32_BE 0x00000021 /* IEEE Float [-1,1] 32 bit big endian */ +#define OGGPCM_FMT_FLT64_LE 0x00000022 /* IEEE Float [-1,1] 64 bit little endian */ +#define OGGPCM_FMT_FLT64_BE 0x00000023 /* IEEE Float [-1,1] 64 bit big endian */ + + +static gboolean +setup_pcm_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + int format; + int channels; + GstCaps *caps; + + pad->granulerate_n = GST_READ_UINT32_LE (data + 16); + pad->granulerate_d = 1; + GST_LOG ("sample rate: %d", pad->granulerate_n); + + format = GST_READ_UINT32_LE (data + 12); + channels = GST_READ_UINT8 (data + 21); + + pad->n_header_packets = 2 + GST_READ_UINT32_LE (data + 24); + + if (pad->granulerate_n == 0) + return FALSE; + + switch (format) { + case OGGPCM_FMT_S8: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 8, + "width", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_U8: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 8, + "width", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL); + break; + case OGGPCM_FMT_S16_LE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 16, + "width", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_S16_BE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 16, + "width", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_S24_LE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 24, + "width", G_TYPE_INT, 24, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_S24_BE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 24, + "width", G_TYPE_INT, 24, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_S32_LE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 32, + "width", G_TYPE_INT, 32, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_S32_BE: + caps = gst_caps_new_simple ("audio/x-raw-int", + "depth", G_TYPE_INT, 32, + "width", G_TYPE_INT, 32, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "signed", G_TYPE_BOOLEAN, TRUE, NULL); + break; + case OGGPCM_FMT_ULAW: + caps = gst_caps_new_simple ("audio/x-mulaw", NULL); + break; + case OGGPCM_FMT_ALAW: + caps = gst_caps_new_simple ("audio/x-alaw", NULL); + break; + case OGGPCM_FMT_FLT32_LE: + caps = gst_caps_new_simple ("audio/x-raw-float", + "width", G_TYPE_INT, 32, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL); + break; + case OGGPCM_FMT_FLT32_BE: + caps = gst_caps_new_simple ("audio/x-raw-float", + "width", G_TYPE_INT, 32, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL); + break; + case OGGPCM_FMT_FLT64_LE: + caps = gst_caps_new_simple ("audio/x-raw-float", + "width", G_TYPE_INT, 64, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL); + break; + case OGGPCM_FMT_FLT64_BE: + caps = gst_caps_new_simple ("audio/x-raw-float", + "width", G_TYPE_INT, 64, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL); + break; + default: + return FALSE; + } + + gst_caps_set_simple (caps, "audio/x-raw-int", + "rate", G_TYPE_INT, pad->granulerate_n, + "channels", G_TYPE_INT, channels, NULL); + pad->caps = caps; + + return TRUE; +} + +/* cmml */ + +static gboolean +setup_cmml_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + + pad->granulerate_n = GST_READ_UINT64_LE (data + 12); + pad->granulerate_d = GST_READ_UINT64_LE (data + 20); + pad->granuleshift = data[28]; + GST_LOG ("sample rate: %d", pad->granulerate_n); + + pad->n_header_packets = 3; + + if (pad->granulerate_n == 0) + return FALSE; + + data += 4 + (4 + 4 + 4); + GST_DEBUG ("blocksize0: %u", 1 << (data[0] >> 4)); + GST_DEBUG ("blocksize1: %u", 1 << (data[0] & 0x0F)); + + pad->caps = gst_caps_new_simple ("text/x-cmml", NULL); + pad->is_sparse = TRUE; + + return TRUE; +} + +/* celt */ + +static gboolean +setup_celt_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + + pad->granulerate_n = GST_READ_UINT32_LE (data + 36); + pad->granulerate_d = 1; + pad->granuleshift = 0; + GST_LOG ("sample rate: %d", pad->granulerate_n); + + pad->frame_size = GST_READ_UINT32_LE (packet->packet + 44); + pad->n_header_packets = GST_READ_UINT32_LE (packet->packet + 56) + 2; + + if (pad->granulerate_n == 0) + return FALSE; + + pad->caps = gst_caps_new_simple ("audio/x-celt", + "rate", G_TYPE_INT, pad->granulerate_n, NULL); + + return TRUE; +} + +/* kate */ + +static gboolean +setup_kate_mapper (GstOggStream * pad, ogg_packet * packet) +{ + guint8 *data = packet->packet; + const char *category; + + if (packet->bytes < 64) + return FALSE; + + pad->granulerate_n = GST_READ_UINT32_LE (data + 24); + pad->granulerate_d = GST_READ_UINT32_LE (data + 28); + pad->granuleshift = GST_READ_UINT8 (data + 15); + GST_LOG ("sample rate: %d", pad->granulerate_n); + + pad->n_header_packets = GST_READ_UINT8 (data + 11); + GST_LOG ("kate header packets: %d", pad->n_header_packets); + + if (pad->granulerate_n == 0) + return FALSE; + + category = (const char *) data + 48; + if (strcmp (category, "subtitles") == 0 || strcmp (category, "SUB") == 0 || + strcmp (category, "spu-subtitles") == 0 || + strcmp (category, "K-SPU") == 0) { + pad->caps = gst_caps_new_simple ("subtitle/x-kate", NULL); + } else { + pad->caps = gst_caps_new_simple ("application/x-kate", NULL); + } + + pad->is_sparse = TRUE; + + return TRUE; +} + +static gint64 +packet_duration_kate (GstOggStream * pad, ogg_packet * packet) +{ + gint64 duration; + + if (packet->bytes < 1) + return 0; + + switch (packet->packet[0]) { + case 0x00: /* text data */ + if (packet->bytes < 1 + 8 * 2) { + duration = 0; + } else { + duration = GST_READ_UINT64_LE (packet->packet + 1 + 8); + if (duration < 0) + duration = 0; + } + break; + default: + duration = GST_CLOCK_TIME_NONE; + break; + } + + return duration; +} + +static void +extract_tags_kate (GstOggStream * pad, ogg_packet * packet) +{ + GstTagList *list = NULL; + + if (packet->bytes <= 0) + return; + + switch (packet->packet[0]) { + case 0x80:{ + const gchar *canonical; + char language[16]; + + if (packet->bytes < 64) { + GST_WARNING ("Kate ID header packet is less than 64 bytes, ignored"); + break; + } + + /* the language tag is 16 bytes at offset 32, ensure NUL terminator */ + memcpy (language, packet->packet + 32, 16); + language[15] = 0; + + /* language is an ISO 639-1 code or RFC 3066 language code, we + * truncate to ISO 639-1 */ + g_strdelimit (language, NULL, '\0'); + canonical = gst_tag_get_language_code_iso_639_1 (language); + if (canonical) { + list = gst_tag_list_new_full (GST_TAG_LANGUAGE_CODE, canonical, NULL); + } else { + GST_WARNING ("Unknown or invalid language code %s, ignored", language); + } + break; + } + case 0x81: + tag_list_from_vorbiscomment_packet (packet, + (const guint8 *) "\201kate\0\0\0\0", 9, &list); + break; + default: + break; + } + + if (list) { + if (pad->taglist) { + /* ensure the comment packet cannot override the category/language + from the identification header */ + gst_tag_list_insert (pad->taglist, list, GST_TAG_MERGE_KEEP_ALL); + } else + pad->taglist = list; + } +} + + +/* *INDENT-OFF* */ +/* indent hates our freedoms */ +const GstOggMap mappers[] = { + { + "\200theora", 7, 42, + "video/x-theora", + setup_theora_mapper, + granulepos_to_granule_theora, + granule_to_granulepos_default, + is_keyframe_theora, + is_header_theora, + packet_duration_constant, + NULL, + extract_tags_theora + }, + { + "\001vorbis", 7, 22, + "audio/x-vorbis", + setup_vorbis_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_vorbis, + packet_duration_vorbis, + NULL, + extract_tags_vorbis + }, + { + "Speex", 5, 80, + "audio/x-speex", + setup_speex_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_count, + packet_duration_constant, + NULL, + extract_tags_count + }, + { + "PCM ", 8, 0, + "audio/x-raw-int", + setup_pcm_mapper, + NULL, + NULL, + NULL, + is_header_count, + NULL, + NULL, + NULL + }, + { + "CMML\0\0\0\0", 8, 0, + "text/x-cmml", + setup_cmml_mapper, + NULL, + NULL, + NULL, + is_header_count, + NULL, + NULL, + NULL + }, + { + "Annodex", 7, 0, + "application/x-annodex", + setup_fishead_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + NULL, + is_header_count, + NULL, + NULL, + NULL + }, + { + "fishead", 7, 64, + "application/octet-stream", + setup_fishead_mapper, + NULL, + NULL, + NULL, + is_header_true, + NULL, + NULL, + NULL + }, + { + "fLaC", 4, 0, + "audio/x-flac", + setup_fLaC_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_fLaC, + packet_duration_flac, + NULL, + NULL + }, + { + "\177FLAC", 5, 36, + "audio/x-flac", + setup_flac_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_flac, + packet_duration_flac, + NULL, + extract_tags_flac + }, + { + "AnxData", 7, 0, + "application/octet-stream", + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL + }, + { + "CELT ", 8, 0, + "audio/x-celt", + setup_celt_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + NULL, + is_header_count, + packet_duration_constant, + NULL, + extract_tags_count + }, + { + "\200kate\0\0\0", 8, 0, + "text/x-kate", + setup_kate_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + NULL, + is_header_count, + packet_duration_kate, + NULL, + extract_tags_kate + }, + { + "BBCD\0", 5, 13, + "video/x-dirac", + setup_dirac_mapper, + granulepos_to_granule_dirac, + granule_to_granulepos_dirac, + is_keyframe_dirac, + is_header_count, + packet_duration_constant, + granulepos_to_key_granule_dirac, + NULL + }, + { + "OVP80\1\1", 7, 4, + "video/x-vp8", + setup_vp8_mapper, + granulepos_to_granule_vp8, + granule_to_granulepos_vp8, + is_keyframe_vp8, + is_header_vp8, + packet_duration_vp8, + granulepos_to_key_granule_vp8, + extract_tags_vp8 + }, + { + "\001audio\0\0\0", 9, 53, + "application/x-ogm-audio", + setup_ogmaudio_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_ogm, + packet_duration_ogm, + NULL, + NULL + }, + { + "\001video\0\0\0", 9, 53, + "application/x-ogm-video", + setup_ogmvideo_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + NULL, + is_header_ogm, + packet_duration_constant, + NULL, + NULL + }, + { + "\001text\0\0\0", 9, 9, + "application/x-ogm-text", + setup_ogmtext_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + is_keyframe_true, + is_header_ogm, + packet_duration_ogm, + NULL, + extract_tags_ogm + } +}; +/* *INDENT-ON* */ + +gboolean +gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet * packet) +{ + int i; + gboolean ret; + + for (i = 0; i < G_N_ELEMENTS (mappers); i++) { + if (packet->bytes >= mappers[i].min_packet_size && + packet->bytes >= mappers[i].id_length && + memcmp (packet->packet, mappers[i].id, mappers[i].id_length) == 0) { + + GST_DEBUG ("found mapper for '%s'", mappers[i].id); + + if (mappers[i].setup_func) + ret = mappers[i].setup_func (pad, packet); + else + continue; + + if (ret) { + GST_DEBUG ("got stream type %" GST_PTR_FORMAT, pad->caps); + pad->map = i; + return TRUE; + } else { + GST_WARNING ("mapper '%s' did not accept setup header", + mappers[i].media_type); + } + } + } + + return FALSE; +} + +gboolean +gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad, + const GstCaps * caps) +{ + const GstStructure *structure; + const GstBuffer *buf; + const GValue *streamheader; + const GValue *first_element; + ogg_packet packet; + + GST_INFO ("Checking streamheader on caps %" GST_PTR_FORMAT, caps); + + if (caps == NULL) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + streamheader = gst_structure_get_value (structure, "streamheader"); + + if (streamheader == NULL) { + GST_LOG ("no streamheader field in caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + if (!GST_VALUE_HOLDS_ARRAY (streamheader)) { + GST_ERROR ("streamheader field not an array, caps: %" GST_PTR_FORMAT, caps); + return FALSE; + } + + if (gst_value_array_get_size (streamheader) == 0) { + GST_ERROR ("empty streamheader field in caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + first_element = gst_value_array_get_value (streamheader, 0); + + if (!GST_VALUE_HOLDS_BUFFER (first_element)) { + GST_ERROR ("first streamheader not a buffer, caps: %" GST_PTR_FORMAT, caps); + return FALSE; + } + + buf = gst_value_get_buffer (first_element); + if (buf == NULL || GST_BUFFER_SIZE (buf) == 0) { + GST_ERROR ("invalid first streamheader buffer"); + return FALSE; + } + + GST_MEMDUMP ("streamheader", GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + + GST_INFO ("Found headers on caps, using those to determine type"); + return gst_ogg_stream_setup_map (pad, &packet); +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.h b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.h new file mode 100644 index 0000000..f843692 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstoggstream.h @@ -0,0 +1,139 @@ +/* GStreamer + * Copyright (C) 2009 David Schleef + * + * gstoggstream.h: header for GstOggStream + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_OGG_STREAM_H__ +#define __GST_OGG_STREAM_H__ + +#include + +#include +#include + +G_BEGIN_DECLS + +typedef enum { + GST_OGG_SKELETON_FISBONE, + GST_OGG_SKELETON_INDEX, +} GstOggSkeleton; + +typedef struct { + guint64 offset; + guint64 timestamp; +} GstOggIndex; + +typedef struct _GstOggStream GstOggStream; + +struct _GstOggStream +{ + ogg_stream_state stream; + + glong serialno; + GList *headers; + gboolean have_headers; + GList *queued; + + /* for oggparse */ + gboolean in_headers; + GList *unknown_pages; + GList *stored_buffers; + + gint map; + gboolean is_skeleton; + gboolean have_fisbone; + gint granulerate_n; + gint granulerate_d; + guint32 preroll; + guint granuleshift; + gint n_header_packets; + gint n_header_packets_seen; + gint64 accumulated_granule; + gint frame_size; + gint bitrate; + guint64 total_time; + gboolean is_sparse; + + GstCaps *caps; + + gboolean is_video; + /* vorbis stuff */ + int nln_increments[4]; + int nsn_increment; + int short_size; + int long_size; + int vorbis_log2_num_modes; + int vorbis_mode_sizes[256]; + int last_size; + int version; + gint bitrate_upper; + gint bitrate_nominal; + gint bitrate_lower; + GstTagList *taglist; + /* theora stuff */ + gboolean theora_has_zero_keyoffset; + /* VP8 stuff */ + gboolean is_vp8; + /* OGM stuff */ + gboolean is_ogm; + gboolean is_ogm_text; + /* fishead stuff */ + guint16 skeleton_major, skeleton_minor; + gint64 prestime; + gint64 basetime; + /* index */ + guint n_index; + GstOggIndex *index; + guint64 kp_denom; + guint64 idx_bitrate; +}; + + +gboolean gst_ogg_stream_setup_map (GstOggStream * pad, ogg_packet *packet); +gboolean gst_ogg_stream_setup_map_from_caps_headers (GstOggStream * pad, + const GstCaps * caps); +GstClockTime gst_ogg_stream_get_end_time_for_granulepos (GstOggStream *pad, + gint64 granulepos); +GstClockTime gst_ogg_stream_get_start_time_for_granulepos (GstOggStream *pad, + gint64 granulepos); +GstClockTime gst_ogg_stream_granule_to_time (GstOggStream *pad, gint64 granule); +gint64 gst_ogg_stream_granulepos_to_granule (GstOggStream * pad, gint64 granulepos); +gint64 gst_ogg_stream_granulepos_to_key_granule (GstOggStream * pad, gint64 granulepos); +gint64 gst_ogg_stream_granule_to_granulepos (GstOggStream * pad, gint64 granule, gint64 keyframe_granule); +GstClockTime gst_ogg_stream_get_packet_start_time (GstOggStream *pad, + ogg_packet *packet); +gboolean gst_ogg_stream_granulepos_is_key_frame (GstOggStream *pad, + gint64 granulepos); +gboolean gst_ogg_stream_packet_is_header (GstOggStream *pad, ogg_packet *packet); +gint64 gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet *packet); +void gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet); + +gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size, + guint32 * serialno, GstOggSkeleton *type); +gboolean gst_ogg_map_add_fisbone (GstOggStream * pad, GstOggStream * skel_pad, const guint8 * data, guint size, + GstClockTime * p_start_time); +gboolean gst_ogg_map_add_index (GstOggStream * pad, GstOggStream * skel_pad, const guint8 * data, guint size); +gboolean gst_ogg_map_search_index (GstOggStream * pad, gboolean before, guint64 *timestamp, guint64 *offset); + + + + +G_END_DECLS + +#endif /* __GST_OGG_STREAM_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/gstogmparse.c b/gst-plugins-base-subtitles0.10/ext/ogg/gstogmparse.c new file mode 100644 index 0000000..6b054a2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/gstogmparse.c @@ -0,0 +1,965 @@ +/* GStreamer OGM parsing + * Copyright (C) 2004 Ronald Bultje + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include +#include + +#include "gstogg.h" + +GST_DEBUG_CATEGORY_STATIC (gst_ogm_parse_debug); +#define GST_CAT_DEFAULT gst_ogm_parse_debug + +#define GST_TYPE_OGM_VIDEO_PARSE (gst_ogm_video_parse_get_type()) +#define GST_IS_OGM_VIDEO_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_VIDEO_PARSE)) + +#define GST_TYPE_OGM_AUDIO_PARSE (gst_ogm_audio_parse_get_type()) +#define GST_IS_OGM_AUDIO_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_AUDIO_PARSE)) + +#define GST_TYPE_OGM_TEXT_PARSE (gst_ogm_text_parse_get_type()) +#define GST_IS_OGM_TEXT_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_TEXT_PARSE)) + +#define GST_TYPE_OGM_PARSE (gst_ogm_parse_get_type()) +#define GST_OGM_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_OGM_PARSE, GstOgmParse)) +#define GST_OGM_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_OGM_PARSE, GstOgmParse)) +#define GST_IS_OGM_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_OGM_PARSE)) +#define GST_IS_OGM_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_OGM_PARSE)) +#define GST_OGM_PARSE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_OGM_PARSE, GstOgmParseClass)) + +typedef struct _stream_header_video +{ + gint32 width; + gint32 height; +} stream_header_video; + +typedef struct _stream_header_audio +{ + gint16 channels; + gint16 blockalign; + gint32 avgbytespersec; +} stream_header_audio; + +/* sizeof(stream_header) might differ due to structure packing and + * alignment differences on some architectures, so not using that */ +#define OGM_STREAM_HEADER_SIZE (8+4+4+8+8+4+4+4+8) + +typedef struct _stream_header +{ + gchar streamtype[8]; + gchar subtype[4 + 1]; + + /* size of the structure */ + gint32 size; + + /* in reference time */ + gint64 time_unit; + + gint64 samples_per_unit; + + /* in media time */ + gint32 default_len; + + gint32 buffersize; + gint32 bits_per_sample; + + union + { + stream_header_video video; + stream_header_audio audio; + /* text has no additional data */ + } s; +} stream_header; + +typedef struct _GstOgmParse +{ + GstElement element; + + /* pads */ + GstPad *srcpad, *sinkpad; + GstPadTemplate *srcpadtempl; + + /* we need to cache events that we receive before creating the source pad */ + GList *cached_events; + + /* audio or video */ + stream_header hdr; + + /* expected next granulepos (used for timestamp guessing) */ + guint64 next_granulepos; +} GstOgmParse; + +typedef struct _GstOgmParseClass +{ + GstElementClass parent_class; +} GstOgmParseClass; + +static GstStaticPadTemplate sink_factory_video = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-ogm-video")); +static GstStaticPadTemplate sink_factory_audio = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-ogm-audio")); +static GstStaticPadTemplate sink_factory_text = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-ogm-text")); +static GstPadTemplate *video_src_templ, *audio_src_templ, *text_src_templ; + +static GType gst_ogm_audio_parse_get_type (void); +static GType gst_ogm_video_parse_get_type (void); +static GType gst_ogm_text_parse_get_type (void); +static GType gst_ogm_parse_get_type (void); + +static void gst_ogm_audio_parse_base_init (GstOgmParseClass * klass); +static void gst_ogm_video_parse_base_init (GstOgmParseClass * klass); +static void gst_ogm_text_parse_base_init (GstOgmParseClass * klass); +static void gst_ogm_parse_class_init (GstOgmParseClass * klass); +static void gst_ogm_parse_init (GstOgmParse * ogm); +static void gst_ogm_video_parse_init (GstOgmParse * ogm); +static void gst_ogm_audio_parse_init (GstOgmParse * ogm); +static void gst_ogm_text_parse_init (GstOgmParse * ogm); + +static const GstQueryType *gst_ogm_parse_get_sink_querytypes (GstPad * pad); +static gboolean gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query); +static gboolean gst_ogm_parse_sink_convert (GstPad * pad, GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value); + +static GstFlowReturn gst_ogm_parse_chain (GstPad * pad, GstBuffer * buffer); + +static GstStateChangeReturn gst_ogm_parse_change_state (GstElement * element, + GstStateChange transition); + +static GstElementClass *parent_class = NULL; + +static GType +gst_ogm_parse_get_type (void) +{ + static GType ogm_parse_type = 0; + + if (!ogm_parse_type) { + static const GTypeInfo ogm_parse_info = { + sizeof (GstOgmParseClass), + NULL, + NULL, + (GClassInitFunc) gst_ogm_parse_class_init, + NULL, + NULL, + sizeof (GstOgmParse), + 0, + (GInstanceInitFunc) gst_ogm_parse_init, + }; + + ogm_parse_type = + g_type_register_static (GST_TYPE_ELEMENT, + "GstOgmParse", &ogm_parse_info, 0); + } + + return ogm_parse_type; +} + +static GType +gst_ogm_audio_parse_get_type (void) +{ + static GType ogm_audio_parse_type = 0; + + if (!ogm_audio_parse_type) { + static const GTypeInfo ogm_audio_parse_info = { + sizeof (GstOgmParseClass), + (GBaseInitFunc) gst_ogm_audio_parse_base_init, + NULL, + NULL, + NULL, + NULL, + sizeof (GstOgmParse), + 0, + (GInstanceInitFunc) gst_ogm_audio_parse_init, + }; + + ogm_audio_parse_type = + g_type_register_static (GST_TYPE_OGM_PARSE, + "GstOgmAudioParse", &ogm_audio_parse_info, 0); + } + + return ogm_audio_parse_type; +} + +static GType +gst_ogm_video_parse_get_type (void) +{ + static GType ogm_video_parse_type = 0; + + if (!ogm_video_parse_type) { + static const GTypeInfo ogm_video_parse_info = { + sizeof (GstOgmParseClass), + (GBaseInitFunc) gst_ogm_video_parse_base_init, + NULL, + NULL, + NULL, + NULL, + sizeof (GstOgmParse), + 0, + (GInstanceInitFunc) gst_ogm_video_parse_init, + }; + + ogm_video_parse_type = + g_type_register_static (GST_TYPE_OGM_PARSE, + "GstOgmVideoParse", &ogm_video_parse_info, 0); + } + + return ogm_video_parse_type; +} + +static GType +gst_ogm_text_parse_get_type (void) +{ + static GType ogm_text_parse_type = 0; + + if (!ogm_text_parse_type) { + static const GTypeInfo ogm_text_parse_info = { + sizeof (GstOgmParseClass), + (GBaseInitFunc) gst_ogm_text_parse_base_init, + NULL, + NULL, + NULL, + NULL, + sizeof (GstOgmParse), + 0, + (GInstanceInitFunc) gst_ogm_text_parse_init, + }; + + ogm_text_parse_type = + g_type_register_static (GST_TYPE_OGM_PARSE, + "GstOgmTextParse", &ogm_text_parse_info, 0); + } + + return ogm_text_parse_type; +} + +static void +gst_ogm_audio_parse_base_init (GstOgmParseClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstCaps *caps = gst_riff_create_audio_template_caps (); + + gst_element_class_set_details_simple (element_class, + "OGM audio stream parser", "Codec/Decoder/Audio", + "parse an OGM audio header and stream", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory_audio)); + audio_src_templ = gst_pad_template_new ("src", + GST_PAD_SRC, GST_PAD_SOMETIMES, caps); + gst_element_class_add_pad_template (element_class, audio_src_templ); +} + +static void +gst_ogm_video_parse_base_init (GstOgmParseClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstCaps *caps = gst_riff_create_video_template_caps (); + + gst_element_class_set_details_simple (element_class, + "OGM video stream parser", "Codec/Decoder/Video", + "parse an OGM video header and stream", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory_video)); + video_src_templ = gst_pad_template_new ("src", + GST_PAD_SRC, GST_PAD_SOMETIMES, caps); + gst_element_class_add_pad_template (element_class, video_src_templ); +} + +static void +gst_ogm_text_parse_base_init (GstOgmParseClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstCaps *caps = gst_caps_new_simple ("text/plain", NULL, NULL); + + gst_element_class_set_details_simple (element_class, + "OGM text stream parser", "Codec/Decoder/Subtitle", + "parse an OGM text header and stream", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory_text)); + text_src_templ = gst_pad_template_new ("src", + GST_PAD_SRC, GST_PAD_SOMETIMES, caps); + gst_element_class_add_pad_template (element_class, text_src_templ); +} + +static void +gst_ogm_parse_class_init (GstOgmParseClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_ogm_parse_change_state); +} + +static void +gst_ogm_parse_init (GstOgmParse * ogm) +{ + memset (&ogm->hdr, 0, sizeof (ogm->hdr)); + ogm->next_granulepos = 0; + ogm->srcpad = NULL; + ogm->cached_events = NULL; +} + +static void +gst_ogm_audio_parse_init (GstOgmParse * ogm) +{ + ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_audio, "sink"); + gst_pad_set_query_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query)); + gst_pad_set_chain_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_chain)); + gst_pad_set_event_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad); + + ogm->srcpad = NULL; + ogm->srcpadtempl = audio_src_templ; +} + +static void +gst_ogm_video_parse_init (GstOgmParse * ogm) +{ + ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_video, "sink"); + gst_pad_set_query_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query)); + gst_pad_set_chain_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_chain)); + gst_pad_set_event_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad); + + ogm->srcpad = NULL; + ogm->srcpadtempl = video_src_templ; +} + +static void +gst_ogm_text_parse_init (GstOgmParse * ogm) +{ + ogm->sinkpad = gst_pad_new_from_static_template (&sink_factory_text, "sink"); + gst_pad_set_query_type_function (ogm->sinkpad, + gst_ogm_parse_get_sink_querytypes); + gst_pad_set_query_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_query)); + gst_pad_set_chain_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_chain)); + gst_pad_set_event_function (ogm->sinkpad, + GST_DEBUG_FUNCPTR (gst_ogm_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (ogm), ogm->sinkpad); + + ogm->srcpad = NULL; + ogm->srcpadtempl = text_src_templ; +} + +static const GstQueryType * +gst_ogm_parse_get_sink_querytypes (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_POSITION, + 0 + }; + + return types; +} + +static gboolean +gst_ogm_parse_sink_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = FALSE; + GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad)); + + switch (src_format) { + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_TIME: + switch (ogm->hdr.streamtype[0]) { + case 'a': + *dest_value = GST_SECOND * src_value / ogm->hdr.samples_per_unit; + res = TRUE; + break; + case 'v': + case 't': + *dest_value = (GST_SECOND / 10000000) * + ogm->hdr.time_unit * src_value; + res = TRUE; + break; + default: + break; + } + break; + default: + break; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + switch (ogm->hdr.streamtype[0]) { + case 'a': + *dest_value = ogm->hdr.samples_per_unit * src_value / GST_SECOND; + res = TRUE; + break; + case 'v': + case 't': + *dest_value = src_value / + ((GST_SECOND / 10000000) * ogm->hdr.time_unit); + res = TRUE; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + + gst_object_unref (ogm); + return res; +} + +static gboolean +gst_ogm_parse_sink_query (GstPad * pad, GstQuery * query) +{ + GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad)); + GstFormat format; + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 val; + + gst_query_parse_position (query, &format, NULL); + + if (format != GST_FORMAT_DEFAULT && format != GST_FORMAT_TIME) + break; + + if ((res = gst_ogm_parse_sink_convert (pad, + GST_FORMAT_DEFAULT, ogm->next_granulepos, &format, &val))) { + /* don't know the total length here.. */ + gst_query_set_position (query, format, val); + } + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + /* peel off input */ + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if ((res = gst_ogm_parse_sink_convert (pad, src_fmt, src_val, + &dest_fmt, &dest_val))) { + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (ogm); + return res; +} + +static GstFlowReturn +gst_ogm_parse_stream_header (GstOgmParse * ogm, const guint8 * data, guint size) +{ + GstCaps *caps = NULL; + + /* stream header */ + if (size < OGM_STREAM_HEADER_SIZE) + goto buffer_too_small; + + if (!memcmp (data, "video\000\000\000", 8)) { + ogm->hdr.s.video.width = GST_READ_UINT32_LE (&data[44]); + ogm->hdr.s.video.height = GST_READ_UINT32_LE (&data[48]); + } else if (!memcmp (data, "audio\000\000\000", 8)) { + ogm->hdr.s.audio.channels = GST_READ_UINT32_LE (&data[44]); + ogm->hdr.s.audio.blockalign = GST_READ_UINT32_LE (&data[46]); + ogm->hdr.s.audio.avgbytespersec = GST_READ_UINT32_LE (&data[48]); + } else if (!memcmp (data, "text\000\000\000\000", 8)) { + /* nothing here */ + } else { + goto cannot_decode; + } + memcpy (ogm->hdr.streamtype, &data[0], 8); + memcpy (ogm->hdr.subtype, &data[8], 4); + ogm->hdr.subtype[4] = '\0'; + ogm->hdr.size = GST_READ_UINT32_LE (&data[12]); + ogm->hdr.time_unit = GST_READ_UINT64_LE (&data[16]); + ogm->hdr.samples_per_unit = GST_READ_UINT64_LE (&data[24]); + ogm->hdr.default_len = GST_READ_UINT32_LE (&data[32]); + ogm->hdr.buffersize = GST_READ_UINT32_LE (&data[36]); + ogm->hdr.bits_per_sample = GST_READ_UINT32_LE (&data[40]); + + switch (ogm->hdr.streamtype[0]) { + case 'a':{ + guint codec_id = 0; + + if (sscanf (ogm->hdr.subtype, "%04x", &codec_id) != 1) { + GST_WARNING_OBJECT (ogm, "cannot parse subtype %s", ogm->hdr.subtype); + } + + caps = + gst_riff_create_audio_caps (codec_id, NULL, NULL, NULL, NULL, NULL); + + if (caps == NULL) { + GST_WARNING_OBJECT (ogm, "no audio caps for codec %u found", codec_id); + caps = gst_caps_new_simple ("audio/x-ogm-unknown", "codec_id", + G_TYPE_INT, (gint) codec_id, NULL); + } + + gst_caps_set_simple (caps, + "channels", G_TYPE_INT, ogm->hdr.s.audio.channels, + "rate", G_TYPE_INT, ogm->hdr.samples_per_unit, NULL); + + GST_LOG_OBJECT (ogm, "Type: %s, subtype: 0x%04x, channels: %d, " + "samplerate: %d, blockalign: %d, bps: %d, caps = %" GST_PTR_FORMAT, + ogm->hdr.streamtype, codec_id, ogm->hdr.s.audio.channels, + (gint) ogm->hdr.samples_per_unit, ogm->hdr.s.audio.blockalign, + ogm->hdr.s.audio.avgbytespersec, caps); + break; + } + case 'v':{ + guint32 fourcc; + gint time_unit; + + fourcc = GST_MAKE_FOURCC (ogm->hdr.subtype[0], + ogm->hdr.subtype[1], ogm->hdr.subtype[2], ogm->hdr.subtype[3]); + + caps = gst_riff_create_video_caps (fourcc, NULL, NULL, NULL, NULL, NULL); + + if (caps == NULL) { + GST_WARNING_OBJECT (ogm, "could not find video caps for fourcc %" + GST_FOURCC_FORMAT, GST_FOURCC_ARGS (fourcc)); + caps = gst_caps_new_simple ("video/x-ogm-unknown", "fourcc", + GST_TYPE_FOURCC, fourcc, NULL); + break; + } + + GST_LOG_OBJECT (ogm, "Type: %s, subtype: %" GST_FOURCC_FORMAT + ", size: %dx%d, timeunit: %" G_GINT64_FORMAT + " (fps: %lf), s/u: %" G_GINT64_FORMAT ", " + "def.len: %d, bufsize: %d, bps: %d, caps = %" GST_PTR_FORMAT, + ogm->hdr.streamtype, GST_FOURCC_ARGS (fourcc), + ogm->hdr.s.video.width, ogm->hdr.s.video.height, + ogm->hdr.time_unit, 10000000. / ogm->hdr.time_unit, + ogm->hdr.samples_per_unit, ogm->hdr.default_len, + ogm->hdr.buffersize, ogm->hdr.bits_per_sample, caps); + + /* GST_TYPE_FRACTION contains gint */ + if (ogm->hdr.time_unit > G_MAXINT || ogm->hdr.time_unit < G_MININT) + GST_WARNING_OBJECT (ogm, "timeunit is out of range"); + + time_unit = (gint) CLAMP (ogm->hdr.time_unit, G_MININT, G_MAXINT); + gst_caps_set_simple (caps, + "width", G_TYPE_INT, ogm->hdr.s.video.width, + "height", G_TYPE_INT, ogm->hdr.s.video.height, + "framerate", GST_TYPE_FRACTION, 10000000, time_unit, NULL); + break; + } + case 't':{ + GST_LOG_OBJECT (ogm, "Type: %s, s/u: %" G_GINT64_FORMAT + ", timeunit=%" G_GINT64_FORMAT, + ogm->hdr.streamtype, ogm->hdr.samples_per_unit, ogm->hdr.time_unit); + caps = gst_caps_new_simple ("text/plain", NULL); + break; + } + default: + g_assert_not_reached (); + } + + if (caps == NULL) + goto cannot_decode; + + if (ogm->srcpad) { + GstCaps *current_caps = GST_PAD_CAPS (ogm->srcpad); + + if (current_caps && caps && !gst_caps_is_equal (current_caps, caps)) { + GST_WARNING_OBJECT (ogm, "Already an existing pad %s:%s", + GST_DEBUG_PAD_NAME (ogm->srcpad)); + gst_pad_set_active (ogm->srcpad, FALSE); + gst_element_remove_pad (GST_ELEMENT (ogm), ogm->srcpad); + ogm->srcpad = NULL; + } else { + GST_DEBUG_OBJECT (ogm, "Existing pad has the same caps, do nothing"); + } + } + + if (ogm->srcpad == NULL) { + GList *l, *cached_events; + + ogm->srcpad = gst_pad_new_from_template (ogm->srcpadtempl, "src"); + gst_pad_use_fixed_caps (ogm->srcpad); + gst_pad_set_caps (ogm->srcpad, caps); + gst_pad_set_active (ogm->srcpad, TRUE); + gst_element_add_pad (GST_ELEMENT (ogm), ogm->srcpad); + GST_INFO_OBJECT (ogm, "Added pad %s:%s with caps %" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (ogm->srcpad), caps); + + GST_OBJECT_LOCK (ogm); + cached_events = ogm->cached_events; + ogm->cached_events = NULL; + GST_OBJECT_UNLOCK (ogm); + + for (l = cached_events; l; l = l->next) { + GstEvent *event = GST_EVENT_CAST (l->data); + + GST_DEBUG_OBJECT (ogm, "Pushing cached event %" GST_PTR_FORMAT, event); + gst_pad_push_event (ogm->srcpad, event); + } + g_list_free (cached_events); + + { + GstTagList *tags; + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_SUBTITLE_CODEC, + "Ogm", NULL); + gst_element_found_tags_for_pad (GST_ELEMENT (ogm), ogm->srcpad, tags); + } + } + + gst_caps_unref (caps); + + return GST_FLOW_OK; + +/* ERRORS */ +buffer_too_small: + { + GST_ELEMENT_ERROR (ogm, STREAM, WRONG_TYPE, ("Buffer too small"), (NULL)); + return GST_FLOW_ERROR; + } +cannot_decode: + { + GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("unknown ogm format")); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_ogm_parse_comment_packet (GstOgmParse * ogm, GstBuffer * buf) +{ + GstFlowReturn ret; + + if (ogm->srcpad == NULL) { + GST_DEBUG ("no source pad"); + return GST_FLOW_WRONG_STATE; + } + + /* if this is not a subtitle stream, push the vorbiscomment packet + * on downstream, the respective decoder will handle it; if it is + * a subtitle stream, we will have to handle the comment ourself */ + if (ogm->hdr.streamtype[0] == 't') { + GstTagList *tags; + + tags = gst_tag_list_from_vorbiscomment_buffer (buf, + (guint8 *) "\003vorbis", 7, NULL); + + if (tags) { + GST_DEBUG_OBJECT (ogm, "tags = %" GST_PTR_FORMAT, tags); + gst_element_found_tags_for_pad (GST_ELEMENT (ogm), ogm->srcpad, tags); + } else { + GST_DEBUG_OBJECT (ogm, "failed to extract tags from vorbis comment"); + } + /* do not push packet downstream, just let parent unref it */ + ret = GST_FLOW_OK; + } else { + buf = gst_buffer_copy (buf); + gst_buffer_set_caps (buf, GST_PAD_CAPS (ogm->srcpad)); + ret = gst_pad_push (ogm->srcpad, buf); + } + + return ret; +} + +static void +gst_ogm_text_parse_strip_trailing_zeroes (GstOgmParse * ogm, GstBuffer * buf) +{ + const guint8 *data; + guint size; + + g_assert (gst_buffer_is_metadata_writable (buf)); + + /* zeroes are not valid UTF-8 characters, so strip them from output */ + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + while (size > 0 && data[size - 1] == '\0') { + --size; + } + + GST_BUFFER_SIZE (buf) = size; +} + +static GstFlowReturn +gst_ogm_parse_data_packet (GstOgmParse * ogm, GstBuffer * buf) +{ + GstFlowReturn ret; + const guint8 *data; + GstBuffer *sbuf; + gboolean keyframe; + guint size, len, n, xsize = 0; + + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + + if ((data[0] & 0x01) != 0) + goto invalid_startcode; + + /* data - push on */ + len = ((data[0] & 0xc0) >> 6) | ((data[0] & 0x02) << 1); + keyframe = (((data[0] & 0x08) >> 3) != 0); + + if ((1 + len) > size) + goto buffer_too_small; + + for (n = len; n > 0; n--) { + xsize = (xsize << 8) | data[n]; + } + + GST_LOG_OBJECT (ogm, "[0x%02x] samples: %d, hdrbytes: %d, datasize: %d", + data[0], xsize, len, size - len - 1); + + sbuf = gst_buffer_create_sub (buf, len + 1, size - len - 1); + + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) + ogm->next_granulepos = GST_BUFFER_OFFSET_END (buf); + + switch (ogm->hdr.streamtype[0]) { + case 't': + case 'v':{ + GstClockTime ts, next_ts; + guint samples; + + samples = (ogm->hdr.streamtype[0] == 'v') ? 1 : xsize; + + if (!keyframe) { + GST_BUFFER_FLAG_SET (sbuf, GST_BUFFER_FLAG_DELTA_UNIT); + } + + /* shouldn't this be granulepos - samples? (tpm) */ + ts = gst_util_uint64_scale (ogm->next_granulepos, + ogm->hdr.time_unit * GST_SECOND, 10000000); + next_ts = gst_util_uint64_scale (ogm->next_granulepos + samples, + ogm->hdr.time_unit * GST_SECOND, 10000000); + + GST_BUFFER_TIMESTAMP (sbuf) = ts; + GST_BUFFER_DURATION (sbuf) = next_ts - ts; + + ogm->next_granulepos += samples; + + if (ogm->hdr.streamtype[0] == 't') { + gst_ogm_text_parse_strip_trailing_zeroes (ogm, sbuf); + } + break; + } + case 'a':{ + GstClockTime ts, next_ts; + + /* shouldn't this be granulepos - samples? (tpm) */ + ts = gst_util_uint64_scale_int (ogm->next_granulepos, + GST_SECOND, ogm->hdr.samples_per_unit); + next_ts = gst_util_uint64_scale_int (ogm->next_granulepos + xsize, + GST_SECOND, ogm->hdr.samples_per_unit); + + GST_BUFFER_TIMESTAMP (sbuf) = ts; + GST_BUFFER_DURATION (sbuf) = next_ts - ts; + + ogm->next_granulepos += xsize; + break; + } + default: + g_assert_not_reached (); + break; + } + + if (ogm->srcpad) { + gst_buffer_set_caps (sbuf, GST_PAD_CAPS (ogm->srcpad)); + GST_LOG_OBJECT (ogm, "Pushing buffer with ts=%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sbuf))); + ret = gst_pad_push (ogm->srcpad, sbuf); + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (ogm, "Flow on %s:%s = %s", + GST_DEBUG_PAD_NAME (ogm->srcpad), gst_flow_get_name (ret)); + } + } else { + ret = GST_FLOW_WRONG_STATE; + } + + return ret; + +/* ERRORS */ +invalid_startcode: + { + GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), + ("unexpected packet startcode 0x%02x", data[0])); + return GST_FLOW_ERROR; + } +buffer_too_small: + { + GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), + ("buffer too small, len+1=%u, size=%u", len + 1, size)); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_ogm_parse_chain (GstPad * pad, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstOgmParse *ogm = GST_OGM_PARSE (GST_PAD_PARENT (pad)); + guint8 *data = GST_BUFFER_DATA (buf); + guint size = GST_BUFFER_SIZE (buf); + + if (size < 1) + goto buffer_too_small; + + GST_LOG_OBJECT (ogm, "Packet with start code 0x%02x", data[0]); + + switch (data[0]) { + case 0x01:{ + ret = gst_ogm_parse_stream_header (ogm, data + 1, size - 1); + break; + } + case 0x03:{ + ret = gst_ogm_parse_comment_packet (ogm, buf); + break; + } + default:{ + ret = gst_ogm_parse_data_packet (ogm, buf); + break; + } + } + + gst_buffer_unref (buf); + + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (ogm, "Flow: %s", gst_flow_get_name (ret)); + } + + return ret; + +/* ERRORS */ +buffer_too_small: + { + GST_ELEMENT_ERROR (ogm, STREAM, DECODE, (NULL), ("buffer too small")); + gst_buffer_unref (buf); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_ogm_parse_sink_event (GstPad * pad, GstEvent * event) +{ + GstOgmParse *ogm = GST_OGM_PARSE (gst_pad_get_parent (pad)); + gboolean res; + + GST_LOG_OBJECT (ogm, "processing %s event", GST_EVENT_TYPE_NAME (event)); + + GST_OBJECT_LOCK (ogm); + if (ogm->srcpad == NULL) { + ogm->cached_events = g_list_append (ogm->cached_events, event); + GST_OBJECT_UNLOCK (ogm); + res = TRUE; + } else { + GST_OBJECT_UNLOCK (ogm); + res = gst_pad_event_default (pad, event); + } + + gst_object_unref (ogm); + return res; +} + +static GstStateChangeReturn +gst_ogm_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstOgmParse *ogm = GST_OGM_PARSE (element); + + ret = parent_class->change_state (element, transition); + if (ret != GST_STATE_CHANGE_SUCCESS) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (ogm->srcpad) { + gst_pad_set_active (ogm->srcpad, FALSE); + gst_element_remove_pad (element, ogm->srcpad); + ogm->srcpad = NULL; + } + memset (&ogm->hdr, 0, sizeof (ogm->hdr)); + ogm->next_granulepos = 0; + g_list_foreach (ogm->cached_events, (GFunc) gst_mini_object_unref, NULL); + g_list_free (ogm->cached_events); + ogm->cached_events = NULL; + break; + default: + break; + } + + return ret; +} + +gboolean +gst_ogm_parse_plugin_init (GstPlugin * plugin) +{ + gst_riff_init (); + + GST_DEBUG_CATEGORY_INIT (gst_ogm_parse_debug, "ogmparse", 0, "ogm parser"); + + return gst_element_register (plugin, "ogmaudioparse", GST_RANK_PRIMARY, + GST_TYPE_OGM_AUDIO_PARSE) && + gst_element_register (plugin, "ogmvideoparse", GST_RANK_PRIMARY, + GST_TYPE_OGM_VIDEO_PARSE) && + gst_element_register (plugin, "ogmtextparse", GST_RANK_PRIMARY, + GST_TYPE_OGM_TEXT_PARSE); +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.c b/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.c new file mode 100644 index 0000000..844f18b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.c @@ -0,0 +1,240 @@ +/* + This file borrowed from liboggz + */ +/* + Copyright (C) 2003 Commonwealth Scientific and Industrial Research + Organisation (CSIRO) Australia + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of CSIRO Australia nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + * oggz_auto.c + * + * Conrad Parker + */ + +#include "config.h" + +#include +#include + +#include "gstoggstream.h" +#include "vorbis_parse.h" + +/* + * Vorbis packets can be short or long, and each packet overlaps the previous + * and next packets. The granulepos of a packet is always the last sample + * that is completely decoded at the end of decoding that packet - i.e. the + * last packet before the first overlapping packet. If the sizes of packets + * are 's' and 'l', then the increment will depend on the previous and next + * packet types: + * v prev<<1 | next + * lll: l/2 3 + * lls: 3l/4 - s/4 2 + * lsl: s/2 + * lss: s/2 + * sll: l/4 + s/4 1 + * sls: l/2 0 + * ssl: s/2 + * sss: s/2 + * + * The previous and next packet types can be inferred from the current packet + * (additional information is not required) + * + * The two blocksizes can be determined from the first header packet, by reading + * byte 28. 1 << (packet[28] >> 4) == long_size. + * 1 << (packet[28] & 0xF) == short_size. + * + * (see http://xiph.org/vorbis/doc/Vorbis_I_spec.html for specification) + */ + + +void +parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet) +{ + /* + * on the first (b_o_s) packet, determine the long and short sizes, + * and then calculate l/2, l/4 - s/4, 3 * l/4 - s/4, l/2 - s/2 and s/2 + */ + int short_size; + int long_size; + + long_size = 1 << (packet->packet[28] >> 4); + short_size = 1 << (packet->packet[28] & 0xF); + + pad->nln_increments[3] = long_size >> 1; + pad->nln_increments[2] = 3 * (long_size >> 2) - (short_size >> 2); + pad->nln_increments[1] = (long_size >> 2) + (short_size >> 2); + pad->nln_increments[0] = pad->nln_increments[3]; + pad->short_size = short_size; + pad->long_size = long_size; + pad->nsn_increment = short_size >> 1; +} + +void +parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op) +{ + /* + * the code pages, a whole bunch of other fairly useless stuff, AND, + * RIGHT AT THE END (of a bunch of variable-length compressed rubbish that + * basically has only one actual set of values that everyone uses BUT YOU + * CAN'T BE SURE OF THAT, OH NO YOU CAN'T) is the only piece of data that's + * actually useful to us - the packet modes (because it's inconceivable to + * think people might want _just that_ and nothing else, you know, for + * seeking and stuff). + * + * Fortunately, because of the mandate that non-used bits must be zero + * at the end of the packet, we might be able to sneakily work backwards + * and find out the information we need (namely a mapping of modes to + * packet sizes) + */ + unsigned char *current_pos = &op->packet[op->bytes - 1]; + int offset; + int size; + int size_check; + int *mode_size_ptr; + int i; + int ii; + + /* + * This is the format of the mode data at the end of the packet for all + * Vorbis Version 1 : + * + * [ 6:number_of_modes ] + * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ] + * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ] + * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ] + * [ 1:framing(1) ] + * + * e.g.: + * + * <- + * 0 0 0 0 0 1 0 0 + * 0 0 1 0 0 0 0 0 + * 0 0 1 0 0 0 0 0 + * 0 0 1|0 0 0 0 0 + * 0 0 0 0|0|0 0 0 + * 0 0 0 0 0 0 0 0 + * 0 0 0 0|0 0 0 0 + * 0 0 0 0 0 0 0 0 + * 0 0 0 0|0 0 0 0 + * 0 0 0|1|0 0 0 0 | + * 0 0 0 0 0 0 0 0 V + * 0 0 0|0 0 0 0 0 + * 0 0 0 0 0 0 0 0 + * 0 0 1|0 0 0 0 0 + * 0 0|1|0 0 0 0 0 + * + * + * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a + * bit of 1. + * Let's find our last 1 bit first. + * + */ + + size = 0; + + offset = 8; + while (!((1 << --offset) & *current_pos)) { + if (offset == 0) { + offset = 8; + current_pos -= 1; + } + } + + while (1) { + + /* + * from current_pos-5:(offset+1) to current_pos-1:(offset+1) should + * be zero + */ + offset = (offset + 7) % 8; + if (offset == 7) + current_pos -= 1; + + if (((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0) + || + current_pos[-4] != 0 + || + current_pos[-3] != 0 + || + current_pos[-2] != 0 + || ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0) + ) { + break; + } + + size += 1; + + current_pos -= 5; + + } + + /* Give ourselves a chance to recover if we went back too far by using + * the size check. */ + for (ii = 0; ii < 2; ii++) { + if (offset > 4) { + size_check = (current_pos[0] >> (offset - 5)) & 0x3F; + } else { + /* mask part of byte from current_pos */ + size_check = (current_pos[0] & ((1 << (offset + 1)) - 1)); + /* shift to appropriate position */ + size_check <<= (5 - offset); + /* or in part of byte from current_pos - 1 */ + size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >> + (offset + 3); + } + + size_check += 1; + if (size_check == size) { + break; + } + offset = (offset + 1) % 8; + if (offset == 0) + current_pos += 1; + current_pos += 5; + size -= 1; + } + + /* Store mode size information in our info struct */ + i = -1; + while ((1 << (++i)) < size); + pad->vorbis_log2_num_modes = i; + + mode_size_ptr = pad->vorbis_mode_sizes; + + for (i = 0; i < size; i++) { + offset = (offset + 1) % 8; + if (offset == 0) + current_pos += 1; + *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1; + current_pos += 5; + } + +} diff --git a/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.h b/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.h new file mode 100644 index 0000000..9a8781b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/ogg/vorbis_parse.h @@ -0,0 +1,30 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * gstoggdemux.c: ogg stream demuxer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_VORBIS_PARSE_H__ +#define __GST_VORBIS_PARSE_H__ + +#include + +void parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet); +void parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op); + +#endif /* __GST_VORBIS_PARSE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/pango/Makefile.am b/gst-plugins-base-subtitles0.10/ext/pango/Makefile.am new file mode 100644 index 0000000..2ffea22 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/Makefile.am @@ -0,0 +1,30 @@ +plugin_LTLIBRARIES = libgstpango.la + +noinst_HEADERS = \ + gstclockoverlay.h \ + gsttextoverlay.h \ + gsttextrender.h \ + gsttimeoverlay.h + +libgstpango_la_SOURCES = \ + gstclockoverlay.c \ + gsttextoverlay.c \ + gsttextrender.c \ + gsttimeoverlay.c + +libgstpango_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CONTROLLER_CFLAGS) \ + $(GST_CFLAGS) \ + $(PANGO_CFLAGS) +libgstpango_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_CONTROLLER_LIBS) \ + $(GST_LIBS) \ + $(PANGO_LIBS) +libgstpango_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstpango_la_LIBTOOLFLAGS = --tag=disable-static + diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.c b/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.c new file mode 100644 index 0000000..d90cff1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.c @@ -0,0 +1,248 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-clockoverlay + * @see_also: #GstTextOverlay, #GstTimeOverlay + * + * This element overlays the current clock time on top of a video + * stream. You can position the text and configure the font details + * using the properties of the #GstTextOverlay class. By default, the + * time is displayed in the top left corner of the picture, with some + * padding to the left and to the top. + * + * + * Example launch lines + * |[ + * gst-launch -v videotestsrc ! clockoverlay ! xvimagesink + * ]| Display the current time in the top left corner of the video picture + * |[ + * gst-launch -v videotestsrc ! clockoverlay halign=right valign=bottom text="Edge City" shaded-background=true ! ffmpegcolorspace ! ximagesink + * ]| Another pipeline that displays the current time with some leading + * text in the bottom right corner of the video picture, with the background + * of the text being shaded in order to make it more legible on top of a + * bright video background. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + + +#define DEFAULT_PROP_TIMEFORMAT "%H:%M:%S" + +enum +{ + PROP_0, + PROP_TIMEFORMAT, + PROP_LAST +}; + +GST_BOILERPLATE (GstClockOverlay, gst_clock_overlay, GstTextOverlay, + GST_TYPE_TEXT_OVERLAY); + +static void +gst_clock_overlay_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, "Clock overlay", + "Filter/Editor/Video", + "Overlays the current clock time on a video stream", + "Tim-Philipp Müller "); +} + + +static void gst_clock_overlay_finalize (GObject * object); +static void gst_clock_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_clock_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gchar * +gst_clock_overlay_render_time (GstClockOverlay * overlay) +{ + struct tm *t; + time_t now; + gchar buf[256]; + +#ifdef HAVE_LOCALTIME_R + struct tm dummy; +#endif + + now = time (NULL); + +#ifdef HAVE_LOCALTIME_R + /* Need to call tzset explicitly when calling localtime_r for changes + to the timezone between calls to be visible. */ + tzset (); + t = localtime_r (&now, &dummy); +#else + /* on win32 this apparently returns a per-thread struct which would be fine */ + t = localtime (&now); +#endif + + if (t == NULL) + return g_strdup ("--:--:--"); + + if (strftime (buf, sizeof (buf), overlay->format, t) == 0) + return g_strdup (""); + return g_strdup (buf); +} + +/* Called with lock held */ +static gchar * +gst_clock_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame) +{ + gchar *time_str, *txt, *ret; + GstClockOverlay *clock_overlay = GST_CLOCK_OVERLAY (overlay); + + txt = g_strdup (overlay->default_text); + + time_str = gst_clock_overlay_render_time (clock_overlay); + if (txt != NULL && *txt != '\0') { + ret = g_strdup_printf ("%s %s", txt, time_str); + } else { + ret = time_str; + time_str = NULL; + } + + if (g_strcmp0 (ret, clock_overlay->text)) { + overlay->need_render = TRUE; + g_free (clock_overlay->text); + clock_overlay->text = g_strdup (ret); + } + + g_free (txt); + g_free (time_str); + + return ret; +} + +static void +gst_clock_overlay_class_init (GstClockOverlayClass * klass) +{ + GObjectClass *gobject_class; + GstTextOverlayClass *gsttextoverlay_class; + PangoContext *context; + PangoFontDescription *font_description; + + gobject_class = (GObjectClass *) klass; + gsttextoverlay_class = (GstTextOverlayClass *) klass; + + gobject_class->finalize = gst_clock_overlay_finalize; + gobject_class->set_property = gst_clock_overlay_set_property; + gobject_class->get_property = gst_clock_overlay_get_property; + + gsttextoverlay_class->get_text = gst_clock_overlay_get_text; + + g_object_class_install_property (gobject_class, PROP_TIMEFORMAT, + g_param_spec_string ("time-format", "Date/Time Format", + "Format to use for time and date value, as in strftime.", + DEFAULT_PROP_TIMEFORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_mutex_lock (GST_TEXT_OVERLAY_CLASS (klass)->pango_lock); + context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context; + + pango_context_set_language (context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); + + font_description = pango_font_description_new (); + pango_font_description_set_family_static (font_description, "Monospace"); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, 18 * PANGO_SCALE); + pango_context_set_font_description (context, font_description); + pango_font_description_free (font_description); + g_mutex_unlock (GST_TEXT_OVERLAY_CLASS (klass)->pango_lock); +} + + +static void +gst_clock_overlay_finalize (GObject * object) +{ + GstClockOverlay *overlay = GST_CLOCK_OVERLAY (object); + + g_free (overlay->format); + g_free (overlay->text); + overlay->format = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static void +gst_clock_overlay_init (GstClockOverlay * overlay, GstClockOverlayClass * klass) +{ + GstTextOverlay *textoverlay; + + textoverlay = GST_TEXT_OVERLAY (overlay); + + textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP; + textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT; + + overlay->format = g_strdup (DEFAULT_PROP_TIMEFORMAT); +} + + +static void +gst_clock_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstClockOverlay *overlay = GST_CLOCK_OVERLAY (object); + + GST_OBJECT_LOCK (overlay); + switch (prop_id) { + case PROP_TIMEFORMAT: + g_free (overlay->format); + overlay->format = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (overlay); +} + + +static void +gst_clock_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstClockOverlay *overlay = GST_CLOCK_OVERLAY (object); + + GST_OBJECT_LOCK (overlay); + switch (prop_id) { + case PROP_TIMEFORMAT: + g_value_set_string (value, overlay->format); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (overlay); +} diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.h b/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.h new file mode 100644 index 0000000..15a82ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gstclockoverlay.h @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_CLOCK_OVERLAY_H__ +#define __GST_CLOCK_OVERLAY_H__ + +#include "gsttextoverlay.h" + +G_BEGIN_DECLS + +#define GST_TYPE_CLOCK_OVERLAY \ + (gst_clock_overlay_get_type()) +#define GST_CLOCK_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CLOCK_OVERLAY,GstClockOverlay)) +#define GST_CLOCK_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CLOCK_OVERLAY,GstClockOverlayClass)) +#define GST_IS_CLOCK_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CLOCK_OVERLAY)) +#define GST_IS_CLOCK_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CLOCK_OVERLAY)) + +typedef struct _GstClockOverlay GstClockOverlay; +typedef struct _GstClockOverlayClass GstClockOverlayClass; + +/** + * GstClockOverlay: + * + * Opaque clockoverlay data structure. + */ +struct _GstClockOverlay { + GstTextOverlay textoverlay; + gchar *format; /* as in strftime () */ + gchar *text; +}; + +struct _GstClockOverlayClass { + GstTextOverlayClass parent_class; +}; + +GType gst_clock_overlay_get_type (void); + + +/* This is a hack hat allows us to use nonliterals for strftime without + * triggering a warning from -Wformat-nonliteral. We need to allow this + * because we export the format string as a property of the element. + * For the inspiration of this and a discussion of why this is necessary, + * see http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39438 + */ +#ifdef __GNUC__ +#pragma GCC system_header +static size_t my_strftime(char *s, size_t max, const char *format, + const struct tm *tm) +{ + return strftime (s, max, format, tm); +} +#define strftime my_strftime +#endif + + +G_END_DECLS + +#endif /* __GST_CLOCK_OVERLAY_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.c b/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.c new file mode 100644 index 0000000..d4775ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.c @@ -0,0 +1,2752 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * Copyright (C) <2006> Julien Moutte + * Copyright (C) <2006> Zeeshan Ali + * Copyright (C) <2006-2008> Tim-Philipp Müller + * Copyright (C) <2009> Young-Ho Cha + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-textoverlay + * @see_also: #GstTextRender, #GstClockOverlay, #GstTimeOverlay, #GstSubParse + * + * This plugin renders text on top of a video stream. This can be either + * static text or text from buffers received on the text sink pad, e.g. + * as produced by the subparse element. If the text sink pad is not linked, + * the text set via the "text" property will be rendered. If the text sink + * pad is linked, text will be rendered as it is received on that pad, + * honouring and matching the buffer timestamps of both input streams. + * + * The text can contain newline characters and text wrapping is enabled by + * default. + * + * + * Example launch lines + * |[ + * gst-launch -v videotestsrc ! textoverlay text="Room A" valign=top halign=left ! xvimagesink + * ]| Here is a simple pipeline that displays a static text in the top left + * corner of the video picture + * |[ + * gst-launch -v filesrc location=subtitles.srt ! subparse ! txt. videotestsrc ! timeoverlay ! textoverlay name=txt shaded-background=yes ! xvimagesink + * ]| Here is another pipeline that displays subtitles from an .srt subtitle + * file, centered at the bottom of the picture and with a rectangular shading + * around the text in the background: + * + * If you do not have such a subtitle file, create one looking like this + * in a text editor: + * |[ + * 1 + * 00:00:03,000 --> 00:00:05,000 + * Hello? (3-5s) + * + * 2 + * 00:00:08,000 --> 00:00:13,000 + * Yes, this is a subtitle. Don't + * you like it? (8-13s) + * + * 3 + * 00:00:18,826 --> 00:01:02,886 + * Uh? What are you talking about? + * I don't understand (18-62s) + * ]| + * + * + */ + +/* FIXME: alloc segment as part of instance struct */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include "gsttextoverlay.h" +#include "gsttimeoverlay.h" +#include "gstclockoverlay.h" +#include "gsttextrender.h" +#include + +/* FIXME: + * - use proper strides and offset for I420 + * - if text is wider than the video picture, it does not get + * clipped properly during blitting (if wrapping is disabled) + * - make 'shading_value' a property (or enum: light/normal/dark/verydark)? + */ + +GST_DEBUG_CATEGORY (pango_debug); +#define GST_CAT_DEFAULT pango_debug + +#define DEFAULT_PROP_TEXT "" +#define DEFAULT_PROP_SHADING FALSE +#define DEFAULT_PROP_VALIGNMENT GST_TEXT_OVERLAY_VALIGN_BASELINE +#define DEFAULT_PROP_HALIGNMENT GST_TEXT_OVERLAY_HALIGN_CENTER +#define DEFAULT_PROP_VALIGN "baseline" +#define DEFAULT_PROP_HALIGN "center" +#define DEFAULT_PROP_XPAD 25 +#define DEFAULT_PROP_YPAD 25 +#define DEFAULT_PROP_DELTAX 0 +#define DEFAULT_PROP_DELTAY 0 +#define DEFAULT_PROP_XPOS 0.5 +#define DEFAULT_PROP_YPOS 0.5 +#define DEFAULT_PROP_WRAP_MODE GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR +#define DEFAULT_PROP_FONT_DESC "" +#define DEFAULT_PROP_SILENT FALSE +#define DEFAULT_PROP_LINE_ALIGNMENT GST_TEXT_OVERLAY_LINE_ALIGN_CENTER +#define DEFAULT_PROP_WAIT_TEXT TRUE +#define DEFAULT_PROP_AUTO_ADJUST_SIZE TRUE +#define DEFAULT_PROP_VERTICAL_RENDER FALSE +#define DEFAULT_PROP_COLOR 0xffffffff + +/* make a property of me */ +#define DEFAULT_SHADING_VALUE -80 + +#define MINIMUM_OUTLINE_OFFSET 1.0 +#define DEFAULT_SCALE_BASIS 640 + +#define COMP_Y(ret, r, g, b) \ +{ \ + ret = (int) (((19595 * r) >> 16) + ((38470 * g) >> 16) + ((7471 * b) >> 16)); \ + ret = CLAMP (ret, 0, 255); \ +} + +#define COMP_U(ret, r, g, b) \ +{ \ + ret = (int) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + ((32768 * b) >> 16) + 128); \ + ret = CLAMP (ret, 0, 255); \ +} + +#define COMP_V(ret, r, g, b) \ +{ \ + ret = (int) (((32768 * r) >> 16) - ((27439 * g) >> 16) - ((5329 * b) >> 16) + 128); \ + ret = CLAMP (ret, 0, 255); \ +} + +#define BLEND(ret, alpha, v0, v1) \ +{ \ + ret = (v0 * alpha + v1 * (255 - alpha)) / 255; \ +} + +#define OVER(ret, alphaA, Ca, alphaB, Cb, alphaNew) \ +{ \ + gint _tmp; \ + _tmp = (Ca * alphaA + Cb * alphaB * (255 - alphaA) / 255) / alphaNew; \ + ret = CLAMP (_tmp, 0, 255); \ +} + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +# define CAIRO_ARGB_A 3 +# define CAIRO_ARGB_R 2 +# define CAIRO_ARGB_G 1 +# define CAIRO_ARGB_B 0 +#else +# define CAIRO_ARGB_A 0 +# define CAIRO_ARGB_R 1 +# define CAIRO_ARGB_G 2 +# define CAIRO_ARGB_B 3 +#endif + +enum +{ + PROP_0, + PROP_TEXT, + PROP_SHADING, + PROP_VALIGN, /* deprecated */ + PROP_HALIGN, /* deprecated */ + PROP_HALIGNMENT, + PROP_VALIGNMENT, + PROP_XPAD, + PROP_YPAD, + PROP_DELTAX, + PROP_DELTAY, + PROP_XPOS, + PROP_YPOS, + PROP_WRAP_MODE, + PROP_FONT_DESC, + PROP_SILENT, + PROP_LINE_ALIGNMENT, + PROP_WAIT_TEXT, + PROP_AUTO_ADJUST_SIZE, + PROP_VERTICAL_RENDER, + PROP_COLOR, + PROP_LAST +}; + +static GstStaticPadTemplate src_template_factory = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_BGRA ";" + GST_VIDEO_CAPS_ARGB ";" + GST_VIDEO_CAPS_ABGR ";" + GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}")) + ); + +static GstStaticPadTemplate video_sink_template_factory = + GST_STATIC_PAD_TEMPLATE ("video_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx ";" + GST_VIDEO_CAPS_RGBx ";" + GST_VIDEO_CAPS_xRGB ";" + GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_RGBA ";" + GST_VIDEO_CAPS_BGRA ";" + GST_VIDEO_CAPS_ARGB ";" + GST_VIDEO_CAPS_ABGR ";" + GST_VIDEO_CAPS_YUV ("{AYUV, I420, UYVY, NV12, NV21}")) + ); + +static GstStaticPadTemplate text_sink_template_factory = + GST_STATIC_PAD_TEMPLATE ("text_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/x-pango-markup; text/plain") + ); + +#define GST_TYPE_TEXT_OVERLAY_VALIGN (gst_text_overlay_valign_get_type()) +static GType +gst_text_overlay_valign_get_type (void) +{ + static GType text_overlay_valign_type = 0; + static const GEnumValue text_overlay_valign[] = { + {GST_TEXT_OVERLAY_VALIGN_BASELINE, "baseline", "baseline"}, + {GST_TEXT_OVERLAY_VALIGN_BOTTOM, "bottom", "bottom"}, + {GST_TEXT_OVERLAY_VALIGN_TOP, "top", "top"}, + {GST_TEXT_OVERLAY_VALIGN_POS, "position", "position"}, + {GST_TEXT_OVERLAY_VALIGN_CENTER, "center", "center"}, + {0, NULL, NULL}, + }; + + if (!text_overlay_valign_type) { + text_overlay_valign_type = + g_enum_register_static ("GstTextOverlayVAlign", text_overlay_valign); + } + return text_overlay_valign_type; +} + +#define GST_TYPE_TEXT_OVERLAY_HALIGN (gst_text_overlay_halign_get_type()) +static GType +gst_text_overlay_halign_get_type (void) +{ + static GType text_overlay_halign_type = 0; + static const GEnumValue text_overlay_halign[] = { + {GST_TEXT_OVERLAY_HALIGN_LEFT, "left", "left"}, + {GST_TEXT_OVERLAY_HALIGN_CENTER, "center", "center"}, + {GST_TEXT_OVERLAY_HALIGN_RIGHT, "right", "right"}, + {GST_TEXT_OVERLAY_HALIGN_POS, "position", "position"}, + {0, NULL, NULL}, + }; + + if (!text_overlay_halign_type) { + text_overlay_halign_type = + g_enum_register_static ("GstTextOverlayHAlign", text_overlay_halign); + } + return text_overlay_halign_type; +} + + +#define GST_TYPE_TEXT_OVERLAY_WRAP_MODE (gst_text_overlay_wrap_mode_get_type()) +static GType +gst_text_overlay_wrap_mode_get_type (void) +{ + static GType text_overlay_wrap_mode_type = 0; + static const GEnumValue text_overlay_wrap_mode[] = { + {GST_TEXT_OVERLAY_WRAP_MODE_NONE, "none", "none"}, + {GST_TEXT_OVERLAY_WRAP_MODE_WORD, "word", "word"}, + {GST_TEXT_OVERLAY_WRAP_MODE_CHAR, "char", "char"}, + {GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR, "wordchar", "wordchar"}, + {0, NULL, NULL}, + }; + + if (!text_overlay_wrap_mode_type) { + text_overlay_wrap_mode_type = + g_enum_register_static ("GstTextOverlayWrapMode", + text_overlay_wrap_mode); + } + return text_overlay_wrap_mode_type; +} + +#define GST_TYPE_TEXT_OVERLAY_LINE_ALIGN (gst_text_overlay_line_align_get_type()) +static GType +gst_text_overlay_line_align_get_type (void) +{ + static GType text_overlay_line_align_type = 0; + static const GEnumValue text_overlay_line_align[] = { + {GST_TEXT_OVERLAY_LINE_ALIGN_LEFT, "left", "left"}, + {GST_TEXT_OVERLAY_LINE_ALIGN_CENTER, "center", "center"}, + {GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT, "right", "right"}, + {0, NULL, NULL} + }; + + if (!text_overlay_line_align_type) { + text_overlay_line_align_type = + g_enum_register_static ("GstTextOverlayLineAlign", + text_overlay_line_align); + } + return text_overlay_line_align_type; +} + +#define GST_TEXT_OVERLAY_GET_COND(ov) (((GstTextOverlay *)ov)->cond) +#define GST_TEXT_OVERLAY_WAIT(ov) (g_cond_wait (GST_TEXT_OVERLAY_GET_COND (ov), GST_OBJECT_GET_LOCK (ov))) +#define GST_TEXT_OVERLAY_SIGNAL(ov) (g_cond_signal (GST_TEXT_OVERLAY_GET_COND (ov))) +#define GST_TEXT_OVERLAY_BROADCAST(ov)(g_cond_broadcast (GST_TEXT_OVERLAY_GET_COND (ov))) + +static GstStateChangeReturn gst_text_overlay_change_state (GstElement * element, + GstStateChange transition); + +static GstCaps *gst_text_overlay_getcaps (GstPad * pad); +static gboolean gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps); +static gboolean gst_text_overlay_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_text_overlay_src_query (GstPad * pad, GstQuery * query); + +static gboolean gst_text_overlay_video_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_text_overlay_video_chain (GstPad * pad, + GstBuffer * buffer); +static GstFlowReturn gst_text_overlay_video_bufferalloc (GstPad * pad, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buffer); + +static gboolean gst_text_overlay_text_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_text_overlay_text_chain (GstPad * pad, + GstBuffer * buffer); +static GstPadLinkReturn gst_text_overlay_text_pad_link (GstPad * pad, + GstPad * peer); +static void gst_text_overlay_text_pad_unlink (GstPad * pad); +static void gst_text_overlay_pop_text (GstTextOverlay * overlay); +static void gst_text_overlay_update_render_mode (GstTextOverlay * overlay); + +static void gst_text_overlay_finalize (GObject * object); +static void gst_text_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_text_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_text_overlay_adjust_values_with_fontdesc (GstTextOverlay * + overlay, PangoFontDescription * desc); + +GST_BOILERPLATE (GstTextOverlay, gst_text_overlay, GstElement, + GST_TYPE_ELEMENT); + +static void +gst_text_overlay_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstTextOverlayClass *klass = GST_TEXT_OVERLAY_CLASS (g_class); + PangoFontMap *fontmap; + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&video_sink_template_factory)); + + /* ugh */ + if (!GST_IS_TIME_OVERLAY_CLASS (g_class) && + !GST_IS_CLOCK_OVERLAY_CLASS (g_class)) { + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&text_sink_template_factory)); + } + + gst_element_class_set_details_simple (element_class, "Text overlay", + "Filter/Editor/Video", + "Adds text strings on top of a video buffer", + "David Schleef , " "Zeeshan Ali "); + + /* Only lock for the subclasses here, the base class + * doesn't have this mutex yet and it's not necessary + * here */ + if (klass->pango_lock) + g_mutex_lock (klass->pango_lock); + fontmap = pango_cairo_font_map_get_default (); + klass->pango_context = + pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); + if (klass->pango_lock) + g_mutex_unlock (klass->pango_lock); +} + +static gchar * +gst_text_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame) +{ + return g_strdup (overlay->default_text); +} + +static void +gst_text_overlay_class_init (GstTextOverlayClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_text_overlay_finalize; + gobject_class->set_property = gst_text_overlay_set_property; + gobject_class->get_property = gst_text_overlay_get_property; + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_text_overlay_change_state); + + klass->pango_lock = g_mutex_new (); + + klass->get_text = gst_text_overlay_get_text; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TEXT, + g_param_spec_string ("text", "text", + "Text to be display.", DEFAULT_PROP_TEXT, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SHADING, + g_param_spec_boolean ("shaded-background", "shaded background", + "Whether to shade the background under the text area", + DEFAULT_PROP_SHADING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGNMENT, + g_param_spec_enum ("valignment", "vertical alignment", + "Vertical alignment of the text", GST_TYPE_TEXT_OVERLAY_VALIGN, + DEFAULT_PROP_VALIGNMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGNMENT, + g_param_spec_enum ("halignment", "horizontal alignment", + "Horizontal alignment of the text", GST_TYPE_TEXT_OVERLAY_HALIGN, + DEFAULT_PROP_HALIGNMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGN, + g_param_spec_string ("valign", "vertical alignment", + "Vertical alignment of the text (deprecated; use valignment)", + DEFAULT_PROP_VALIGN, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGN, + g_param_spec_string ("halign", "horizontal alignment", + "Horizontal alignment of the text (deprecated; use halignment)", + DEFAULT_PROP_HALIGN, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPAD, + g_param_spec_int ("xpad", "horizontal paddding", + "Horizontal paddding when using left/right alignment", 0, G_MAXINT, + DEFAULT_PROP_XPAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPAD, + g_param_spec_int ("ypad", "vertical padding", + "Vertical padding when using top/bottom alignment", 0, G_MAXINT, + DEFAULT_PROP_YPAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAX, + g_param_spec_int ("deltax", "X position modifier", + "Shift X position to the left or to the right. Unit is pixels.", + G_MININT, G_MAXINT, DEFAULT_PROP_DELTAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DELTAY, + g_param_spec_int ("deltay", "Y position modifier", + "Shift Y position up or down. Unit is pixels.", G_MININT, G_MAXINT, + DEFAULT_PROP_DELTAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstTextOverlay:xpos + * + * Horizontal position of the rendered text when using positioned alignment. + * + * Since: 0.10.31 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPOS, + g_param_spec_double ("xpos", "horizontal position", + "Horizontal position when using position alignment", 0, 1.0, + DEFAULT_PROP_XPOS, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstTextOverlay:ypos + * + * Vertical position of the rendered text when using positioned alignment. + * + * Since: 0.10.31 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPOS, + g_param_spec_double ("ypos", "vertical position", + "Vertical position when using position alignment", 0, 1.0, + DEFAULT_PROP_YPOS, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WRAP_MODE, + g_param_spec_enum ("wrap-mode", "wrap mode", + "Whether to wrap the text and if so how.", + GST_TYPE_TEXT_OVERLAY_WRAP_MODE, DEFAULT_PROP_WRAP_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC, + g_param_spec_string ("font-desc", "font description", + "Pango font description of font to be used for rendering. " + "See documentation of pango_font_description_from_string " + "for syntax.", DEFAULT_PROP_FONT_DESC, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstTextOverlay:color + * + * Color of the rendered text. + * + * Since: 0.10.31 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COLOR, + g_param_spec_uint ("color", "Color", + "Color to use for text (big-endian ARGB).", 0, G_MAXUINT32, + DEFAULT_PROP_COLOR, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstTextOverlay:line-alignment + * + * Alignment of text lines relative to each other (for multi-line text) + * + * Since: 0.10.15 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LINE_ALIGNMENT, + g_param_spec_enum ("line-alignment", "line alignment", + "Alignment of text lines relative to each other.", + GST_TYPE_TEXT_OVERLAY_LINE_ALIGN, DEFAULT_PROP_LINE_ALIGNMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstTextOverlay:silent + * + * If set, no text is rendered. Useful to switch off text rendering + * temporarily without removing the textoverlay element from the pipeline. + * + * Since: 0.10.15 + **/ + /* FIXME 0.11: rename to "visible" or "text-visible" or "render-text" */ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SILENT, + g_param_spec_boolean ("silent", "silent", + "Whether to render the text string", + DEFAULT_PROP_SILENT, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstTextOverlay:wait-text + * + * If set, the video will block until a subtitle is received on the text pad. + * If video and subtitles are sent in sync, like from the same demuxer, this + * property should be set. + * + * Since: 0.10.20 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WAIT_TEXT, + g_param_spec_boolean ("wait-text", "Wait Text", + "Whether to wait for subtitles", + DEFAULT_PROP_WAIT_TEXT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_AUTO_ADJUST_SIZE, g_param_spec_boolean ("auto-resize", "auto resize", + "Automatically adjust font size to screen-size.", + DEFAULT_PROP_AUTO_ADJUST_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VERTICAL_RENDER, + g_param_spec_boolean ("vertical-render", "vertical render", + "Vertical Render.", DEFAULT_PROP_VERTICAL_RENDER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_text_overlay_finalize (GObject * object) +{ + GstTextOverlay *overlay = GST_TEXT_OVERLAY (object); + + g_free (overlay->default_text); + + if (overlay->text_image) { + g_free (overlay->text_image); + overlay->text_image = NULL; + } + + if (overlay->layout) { + g_object_unref (overlay->layout); + overlay->layout = NULL; + } + + if (overlay->text_buffer) { + gst_buffer_unref (overlay->text_buffer); + overlay->text_buffer = NULL; + } + + if (overlay->cond) { + g_cond_free (overlay->cond); + overlay->cond = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_text_overlay_init (GstTextOverlay * overlay, GstTextOverlayClass * klass) +{ + GstPadTemplate *template; + PangoFontDescription *desc; + + /* video sink */ + template = gst_static_pad_template_get (&video_sink_template_factory); + overlay->video_sinkpad = gst_pad_new_from_template (template, "video_sink"); + gst_object_unref (template); + gst_pad_set_getcaps_function (overlay->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps)); + gst_pad_set_setcaps_function (overlay->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps)); + gst_pad_set_event_function (overlay->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_video_event)); + gst_pad_set_chain_function (overlay->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_video_chain)); + gst_pad_set_bufferalloc_function (overlay->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_video_bufferalloc)); + gst_element_add_pad (GST_ELEMENT (overlay), overlay->video_sinkpad); + + if (!GST_IS_TIME_OVERLAY_CLASS (klass) && !GST_IS_CLOCK_OVERLAY_CLASS (klass)) { + /* text sink */ + template = gst_static_pad_template_get (&text_sink_template_factory); + overlay->text_sinkpad = gst_pad_new_from_template (template, "text_sink"); + gst_object_unref (template); + gst_pad_set_setcaps_function (overlay->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_setcaps_txt)); + gst_pad_set_event_function (overlay->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_text_event)); + gst_pad_set_chain_function (overlay->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_text_chain)); + gst_pad_set_link_function (overlay->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_link)); + gst_pad_set_unlink_function (overlay->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_text_pad_unlink)); + gst_element_add_pad (GST_ELEMENT (overlay), overlay->text_sinkpad); + } + + /* (video) source */ + template = gst_static_pad_template_get (&src_template_factory); + overlay->srcpad = gst_pad_new_from_template (template, "src"); + gst_object_unref (template); + gst_pad_set_getcaps_function (overlay->srcpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_getcaps)); + gst_pad_set_event_function (overlay->srcpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_src_event)); + gst_pad_set_query_function (overlay->srcpad, + GST_DEBUG_FUNCPTR (gst_text_overlay_src_query)); + gst_element_add_pad (GST_ELEMENT (overlay), overlay->srcpad); + + overlay->line_align = DEFAULT_PROP_LINE_ALIGNMENT; + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + overlay->layout = + pango_layout_new (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_context); + desc = + pango_context_get_font_description (GST_TEXT_OVERLAY_GET_CLASS + (overlay)->pango_context); + gst_text_overlay_adjust_values_with_fontdesc (overlay, desc); + + overlay->color = DEFAULT_PROP_COLOR; + overlay->halign = DEFAULT_PROP_HALIGNMENT; + overlay->valign = DEFAULT_PROP_VALIGNMENT; + overlay->xpad = DEFAULT_PROP_XPAD; + overlay->ypad = DEFAULT_PROP_YPAD; + overlay->deltax = DEFAULT_PROP_DELTAX; + overlay->deltay = DEFAULT_PROP_DELTAY; + overlay->xpos = DEFAULT_PROP_XPOS; + overlay->ypos = DEFAULT_PROP_YPOS; + + overlay->wrap_mode = DEFAULT_PROP_WRAP_MODE; + + overlay->want_shading = DEFAULT_PROP_SHADING; + overlay->shading_value = DEFAULT_SHADING_VALUE; + overlay->silent = DEFAULT_PROP_SILENT; + overlay->wait_text = DEFAULT_PROP_WAIT_TEXT; + overlay->auto_adjust_size = DEFAULT_PROP_AUTO_ADJUST_SIZE; + + overlay->default_text = g_strdup (DEFAULT_PROP_TEXT); + overlay->need_render = TRUE; + overlay->text_image = NULL; + overlay->use_vertical_render = DEFAULT_PROP_VERTICAL_RENDER; + gst_text_overlay_update_render_mode (overlay); + + overlay->fps_n = 0; + overlay->fps_d = 1; + + overlay->text_buffer = NULL; + overlay->text_linked = FALSE; + overlay->cond = g_cond_new (); + gst_segment_init (&overlay->segment, GST_FORMAT_TIME); + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); +} + +static void +gst_text_overlay_update_wrap_mode (GstTextOverlay * overlay) +{ + if (overlay->wrap_mode == GST_TEXT_OVERLAY_WRAP_MODE_NONE) { + GST_DEBUG_OBJECT (overlay, "Set wrap mode NONE"); + pango_layout_set_width (overlay->layout, -1); + } else { + int width; + + if (overlay->auto_adjust_size) { + width = DEFAULT_SCALE_BASIS * PANGO_SCALE; + if (overlay->use_vertical_render) { + width = width * (overlay->height - overlay->ypad * 2) / overlay->width; + } + } else { + width = + (overlay->use_vertical_render ? overlay->height : overlay->width) * + PANGO_SCALE; + } + + GST_DEBUG_OBJECT (overlay, "Set layout width %d", overlay->width); + GST_DEBUG_OBJECT (overlay, "Set wrap mode %d", overlay->wrap_mode); + pango_layout_set_width (overlay->layout, width); + pango_layout_set_wrap (overlay->layout, (PangoWrapMode) overlay->wrap_mode); + } +} + +static void +gst_text_overlay_update_render_mode (GstTextOverlay * overlay) +{ + PangoMatrix matrix = PANGO_MATRIX_INIT; + PangoContext *context = pango_layout_get_context (overlay->layout); + + if (overlay->use_vertical_render) { + pango_matrix_rotate (&matrix, -90); + pango_context_set_base_gravity (context, PANGO_GRAVITY_AUTO); + pango_context_set_matrix (context, &matrix); + pango_layout_set_alignment (overlay->layout, PANGO_ALIGN_LEFT); + } else { + pango_context_set_base_gravity (context, PANGO_GRAVITY_SOUTH); + pango_context_set_matrix (context, &matrix); + pango_layout_set_alignment (overlay->layout, overlay->line_align); + } +} + +static gboolean +gst_text_overlay_setcaps_txt (GstPad * pad, GstCaps * caps) +{ + GstTextOverlay *overlay; + GstStructure *structure; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + structure = gst_caps_get_structure (caps, 0); + overlay->have_pango_markup = + gst_structure_has_name (structure, "text/x-pango-markup"); + + gst_object_unref (overlay); + + return TRUE; +} + +/* FIXME: upstream nego (e.g. when the video window is resized) */ + +static gboolean +gst_text_overlay_setcaps (GstPad * pad, GstCaps * caps) +{ + GstTextOverlay *overlay; + GstStructure *structure; + gboolean ret = FALSE; + const GValue *fps; + + if (!GST_PAD_IS_SINK (pad)) + return TRUE; + + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + overlay->width = 0; + overlay->height = 0; + structure = gst_caps_get_structure (caps, 0); + fps = gst_structure_get_value (structure, "framerate"); + + if (fps + && gst_video_format_parse_caps (caps, &overlay->format, &overlay->width, + &overlay->height)) { + ret = gst_pad_set_caps (overlay->srcpad, caps); + } + + overlay->fps_n = gst_value_get_fraction_numerator (fps); + overlay->fps_d = gst_value_get_fraction_denominator (fps); + + if (ret) { + GST_OBJECT_LOCK (overlay); + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + gst_text_overlay_update_wrap_mode (overlay); + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + GST_OBJECT_UNLOCK (overlay); + } + + gst_object_unref (overlay); + + return ret; +} + +static void +gst_text_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTextOverlay *overlay = GST_TEXT_OVERLAY (object); + + GST_OBJECT_LOCK (overlay); + switch (prop_id) { + case PROP_TEXT: + g_free (overlay->default_text); + overlay->default_text = g_value_dup_string (value); + overlay->need_render = TRUE; + break; + case PROP_SHADING: + overlay->want_shading = g_value_get_boolean (value); + break; + case PROP_XPAD: + overlay->xpad = g_value_get_int (value); + break; + case PROP_YPAD: + overlay->ypad = g_value_get_int (value); + break; + case PROP_DELTAX: + overlay->deltax = g_value_get_int (value); + break; + case PROP_DELTAY: + overlay->deltay = g_value_get_int (value); + break; + case PROP_XPOS: + overlay->xpos = g_value_get_double (value); + break; + case PROP_YPOS: + overlay->ypos = g_value_get_double (value); + break; + case PROP_HALIGN:{ + const gchar *s = g_value_get_string (value); + + if (s && g_ascii_strcasecmp (s, "left") == 0) + overlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT; + else if (s && g_ascii_strcasecmp (s, "center") == 0) + overlay->halign = GST_TEXT_OVERLAY_HALIGN_CENTER; + else if (s && g_ascii_strcasecmp (s, "right") == 0) + overlay->halign = GST_TEXT_OVERLAY_HALIGN_RIGHT; + else + g_warning ("Invalid value '%s' for textoverlay property 'halign'", + GST_STR_NULL (s)); + break; + } + case PROP_VALIGN:{ + const gchar *s = g_value_get_string (value); + + if (s && g_ascii_strcasecmp (s, "baseline") == 0) + overlay->valign = GST_TEXT_OVERLAY_VALIGN_BASELINE; + else if (s && g_ascii_strcasecmp (s, "bottom") == 0) + overlay->valign = GST_TEXT_OVERLAY_VALIGN_BOTTOM; + else if (s && g_ascii_strcasecmp (s, "top") == 0) + overlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP; + else + g_warning ("Invalid value '%s' for textoverlay property 'valign'", + GST_STR_NULL (s)); + break; + } + case PROP_VALIGNMENT: + overlay->valign = g_value_get_enum (value); + break; + case PROP_HALIGNMENT: + overlay->halign = g_value_get_enum (value); + break; + case PROP_WRAP_MODE: + overlay->wrap_mode = g_value_get_enum (value); + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + gst_text_overlay_update_wrap_mode (overlay); + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + break; + case PROP_FONT_DESC: + { + PangoFontDescription *desc; + const gchar *fontdesc_str; + + fontdesc_str = g_value_get_string (value); + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + desc = pango_font_description_from_string (fontdesc_str); + if (desc) { + GST_LOG_OBJECT (overlay, "font description set: %s", fontdesc_str); + pango_layout_set_font_description (overlay->layout, desc); + gst_text_overlay_adjust_values_with_fontdesc (overlay, desc); + pango_font_description_free (desc); + } else { + GST_WARNING_OBJECT (overlay, "font description parse failed: %s", + fontdesc_str); + } + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + break; + } + case PROP_COLOR: + overlay->color = g_value_get_uint (value); + break; + case PROP_SILENT: + overlay->silent = g_value_get_boolean (value); + break; + case PROP_LINE_ALIGNMENT: + overlay->line_align = g_value_get_enum (value); + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + pango_layout_set_alignment (overlay->layout, + (PangoAlignment) overlay->line_align); + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + break; + case PROP_WAIT_TEXT: + overlay->wait_text = g_value_get_boolean (value); + break; + case PROP_AUTO_ADJUST_SIZE: + overlay->auto_adjust_size = g_value_get_boolean (value); + overlay->need_render = TRUE; + break; + case PROP_VERTICAL_RENDER: + overlay->use_vertical_render = g_value_get_boolean (value); + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + gst_text_overlay_update_render_mode (overlay); + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + overlay->need_render = TRUE; + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + overlay->need_render = TRUE; + GST_OBJECT_UNLOCK (overlay); +} + +static void +gst_text_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTextOverlay *overlay = GST_TEXT_OVERLAY (object); + + GST_OBJECT_LOCK (overlay); + switch (prop_id) { + case PROP_TEXT: + g_value_set_string (value, overlay->default_text); + break; + case PROP_SHADING: + g_value_set_boolean (value, overlay->want_shading); + break; + case PROP_XPAD: + g_value_set_int (value, overlay->xpad); + break; + case PROP_YPAD: + g_value_set_int (value, overlay->ypad); + break; + case PROP_DELTAX: + g_value_set_int (value, overlay->deltax); + break; + case PROP_DELTAY: + g_value_set_int (value, overlay->deltay); + break; + case PROP_XPOS: + g_value_set_double (value, overlay->xpos); + break; + case PROP_YPOS: + g_value_set_double (value, overlay->ypos); + break; + case PROP_VALIGNMENT: + g_value_set_enum (value, overlay->valign); + break; + case PROP_HALIGNMENT: + g_value_set_enum (value, overlay->halign); + break; + case PROP_WRAP_MODE: + g_value_set_enum (value, overlay->wrap_mode); + break; + case PROP_SILENT: + g_value_set_boolean (value, overlay->silent); + break; + case PROP_LINE_ALIGNMENT: + g_value_set_enum (value, overlay->line_align); + break; + case PROP_WAIT_TEXT: + g_value_set_boolean (value, overlay->wait_text); + break; + case PROP_AUTO_ADJUST_SIZE: + g_value_set_boolean (value, overlay->auto_adjust_size); + break; + case PROP_VERTICAL_RENDER: + g_value_set_boolean (value, overlay->use_vertical_render); + break; + case PROP_COLOR: + g_value_set_uint (value, overlay->color); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + overlay->need_render = TRUE; + GST_OBJECT_UNLOCK (overlay); +} + +static gboolean +gst_text_overlay_src_query (GstPad * pad, GstQuery * query) +{ + gboolean ret = FALSE; + GstTextOverlay *overlay = NULL; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + ret = gst_pad_peer_query (overlay->video_sinkpad, query); + + gst_object_unref (overlay); + + return ret; +} + +static gboolean +gst_text_overlay_src_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstTextOverlay *overlay = NULL; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + GstSeekFlags flags; + + /* We don't handle seek if we have not text pad */ + if (!overlay->text_linked) { + GST_DEBUG_OBJECT (overlay, "seek received, pushing upstream"); + ret = gst_pad_push_event (overlay->video_sinkpad, event); + goto beach; + } + + GST_DEBUG_OBJECT (overlay, "seek received, driving from here"); + + gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); + + /* Flush downstream, only for flushing seek */ + if (flags & GST_SEEK_FLAG_FLUSH) + gst_pad_push_event (overlay->srcpad, gst_event_new_flush_start ()); + + /* Mark ourself as flushing, unblock chains */ + GST_OBJECT_LOCK (overlay); + overlay->video_flushing = TRUE; + overlay->text_flushing = TRUE; + gst_text_overlay_pop_text (overlay); + GST_OBJECT_UNLOCK (overlay); + + /* Seek on each sink pad */ + gst_event_ref (event); + ret = gst_pad_push_event (overlay->video_sinkpad, event); + if (ret) { + ret = gst_pad_push_event (overlay->text_sinkpad, event); + } else { + gst_event_unref (event); + } + break; + } + default: + if (overlay->text_linked) { + gst_event_ref (event); + ret = gst_pad_push_event (overlay->video_sinkpad, event); + gst_pad_push_event (overlay->text_sinkpad, event); + } else { + ret = gst_pad_push_event (overlay->video_sinkpad, event); + } + break; + } + +beach: + gst_object_unref (overlay); + + return ret; +} + +static GstCaps * +gst_text_overlay_getcaps (GstPad * pad) +{ + GstTextOverlay *overlay; + GstPad *otherpad; + GstCaps *caps; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + if (pad == overlay->srcpad) + otherpad = overlay->video_sinkpad; + else + otherpad = overlay->srcpad; + + /* we can do what the peer can */ + caps = gst_pad_peer_get_caps (otherpad); + if (caps) { + GstCaps *temp; + const GstCaps *templ; + + GST_DEBUG_OBJECT (pad, "peer caps %" GST_PTR_FORMAT, caps); + + /* filtered against our padtemplate */ + templ = gst_pad_get_pad_template_caps (otherpad); + GST_DEBUG_OBJECT (pad, "our template %" GST_PTR_FORMAT, templ); + temp = gst_caps_intersect (caps, templ); + GST_DEBUG_OBJECT (pad, "intersected %" GST_PTR_FORMAT, temp); + gst_caps_unref (caps); + /* this is what we can do */ + caps = temp; + } else { + /* no peer, our padtemplate is enough then */ + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + GST_DEBUG_OBJECT (overlay, "returning %" GST_PTR_FORMAT, caps); + + gst_object_unref (overlay); + + return caps; +} + +static void +gst_text_overlay_adjust_values_with_fontdesc (GstTextOverlay * overlay, + PangoFontDescription * desc) +{ + gint font_size = pango_font_description_get_size (desc) / PANGO_SCALE; + overlay->shadow_offset = (double) (font_size) / 13.0; + overlay->outline_offset = (double) (font_size) / 15.0; + if (overlay->outline_offset < MINIMUM_OUTLINE_OFFSET) + overlay->outline_offset = MINIMUM_OUTLINE_OFFSET; +} + +#define CAIRO_UNPREMULTIPLY(a,r,g,b) G_STMT_START { \ + b = (a > 0) ? MIN ((b * 255 + a / 2) / a, 255) : 0; \ + g = (a > 0) ? MIN ((g * 255 + a / 2) / a, 255) : 0; \ + r = (a > 0) ? MIN ((r * 255 + a / 2) / a, 255) : 0; \ +} G_STMT_END + +static inline void +gst_text_overlay_blit_1 (GstTextOverlay * overlay, guchar * dest, gint xpos, + gint ypos, guchar * text_image, guint dest_stride) +{ + gint i, j = 0; + gint x, y; + guchar r, g, b, a; + guchar *pimage; + guchar *py; + gint width = overlay->image_width; + gint height = overlay->image_height; + + if (xpos < 0) { + xpos = 0; + } + + if (xpos + width > overlay->width) { + width = overlay->width - xpos; + } + + if (ypos + height > overlay->height) { + height = overlay->height - ypos; + } + + dest += (ypos / 1) * dest_stride; + + for (i = 0; i < height; i++) { + pimage = text_image + 4 * (i * overlay->image_width); + py = dest + i * dest_stride + xpos; + for (j = 0; j < width; j++) { + b = pimage[CAIRO_ARGB_B]; + g = pimage[CAIRO_ARGB_G]; + r = pimage[CAIRO_ARGB_R]; + a = pimage[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a, r, g, b); + + pimage += 4; + if (a == 0) { + py++; + continue; + } + COMP_Y (y, r, g, b); + x = *py; + BLEND (*py++, a, y, x); + } + } +} + +static inline void +gst_text_overlay_blit_sub2x2cbcr (GstTextOverlay * overlay, + guchar * destcb, guchar * destcr, gint xpos, gint ypos, guchar * text_image, + guint destcb_stride, guint destcr_stride, guint pix_stride) +{ + gint i, j; + gint x, cb, cr; + gushort r, g, b, a; + gushort r1, g1, b1, a1; + guchar *pimage1, *pimage2; + guchar *pcb, *pcr; + gint width = overlay->image_width - 2; + gint height = overlay->image_height - 2; + + xpos *= pix_stride; + + if (xpos < 0) { + xpos = 0; + } + + if (xpos + width > overlay->width) { + width = overlay->width - xpos; + } + + if (ypos + height > overlay->height) { + height = overlay->height - ypos; + } + + destcb += (ypos / 2) * destcb_stride; + destcr += (ypos / 2) * destcr_stride; + + for (i = 0; i < height; i += 2) { + pimage1 = text_image + 4 * (i * overlay->image_width); + pimage2 = pimage1 + 4 * overlay->image_width; + pcb = destcb + (i / 2) * destcb_stride + xpos / 2; + pcr = destcr + (i / 2) * destcr_stride + xpos / 2; + for (j = 0; j < width; j += 2) { + b = pimage1[CAIRO_ARGB_B]; + g = pimage1[CAIRO_ARGB_G]; + r = pimage1[CAIRO_ARGB_R]; + a = pimage1[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a, r, g, b); + pimage1 += 4; + + b1 = pimage1[CAIRO_ARGB_B]; + g1 = pimage1[CAIRO_ARGB_G]; + r1 = pimage1[CAIRO_ARGB_R]; + a1 = pimage1[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a1, r1, g1, b1); + b += b1; + g += g1; + r += r1; + a += a1; + pimage1 += 4; + + b1 = pimage2[CAIRO_ARGB_B]; + g1 = pimage2[CAIRO_ARGB_G]; + r1 = pimage2[CAIRO_ARGB_R]; + a1 = pimage2[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a1, r1, g1, b1); + b += b1; + g += g1; + r += r1; + a += a1; + pimage2 += 4; + + /* + 2 for rounding */ + b1 = pimage2[CAIRO_ARGB_B]; + g1 = pimage2[CAIRO_ARGB_G]; + r1 = pimage2[CAIRO_ARGB_R]; + a1 = pimage2[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a1, r1, g1, b1); + b += b1 + 2; + g += g1 + 2; + r += r1 + 2; + a += a1 + 2; + pimage2 += 4; + + b /= 4; + g /= 4; + r /= 4; + a /= 4; + + if (a == 0) { + pcb += pix_stride; + pcr += pix_stride; + continue; + } + COMP_U (cb, r, g, b); + COMP_V (cr, r, g, b); + + x = *pcb; + BLEND (*pcb, a, cb, x); + x = *pcr; + BLEND (*pcr, a, cr, x); + + pcb += pix_stride; + pcr += pix_stride; + } + } +} + +static void +gst_text_overlay_render_pangocairo (GstTextOverlay * overlay, + const gchar * string, gint textlen) +{ + cairo_t *cr; + cairo_surface_t *surface; + PangoRectangle ink_rect, logical_rect; + cairo_matrix_t cairo_matrix; + int width, height; + double scalef = 1.0; + double a, r, g, b; + + g_mutex_lock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); + + if (overlay->auto_adjust_size) { + /* 640 pixel is default */ + scalef = (double) (overlay->width) / DEFAULT_SCALE_BASIS; + } + pango_layout_set_width (overlay->layout, -1); + /* set text on pango layout */ + pango_layout_set_markup (overlay->layout, string, textlen); + + /* get subtitle image size */ + pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect); + + width = (logical_rect.width + overlay->shadow_offset) * scalef; + + if (width + overlay->deltax > + (overlay->use_vertical_render ? overlay->height : overlay->width)) { + /* + * subtitle image width is larger then overlay width + * so rearrange overlay wrap mode. + */ + gst_text_overlay_update_wrap_mode (overlay); + pango_layout_get_pixel_extents (overlay->layout, &ink_rect, &logical_rect); + width = overlay->width; + } + + height = + (logical_rect.height + logical_rect.y + overlay->shadow_offset) * scalef; + if (height > overlay->height) { + height = overlay->height; + } + if (overlay->use_vertical_render) { + PangoRectangle rect; + PangoContext *context; + PangoMatrix matrix = PANGO_MATRIX_INIT; + int tmp; + + context = pango_layout_get_context (overlay->layout); + + pango_matrix_rotate (&matrix, -90); + + rect.x = rect.y = 0; + rect.width = width; + rect.height = height; + pango_matrix_transform_pixel_rectangle (&matrix, &rect); + matrix.x0 = -rect.x; + matrix.y0 = -rect.y; + + pango_context_set_matrix (context, &matrix); + + cairo_matrix.xx = matrix.xx; + cairo_matrix.yx = matrix.yx; + cairo_matrix.xy = matrix.xy; + cairo_matrix.yy = matrix.yy; + cairo_matrix.x0 = matrix.x0; + cairo_matrix.y0 = matrix.y0; + cairo_matrix_scale (&cairo_matrix, scalef, scalef); + + tmp = height; + height = width; + width = tmp; + } else { + cairo_matrix_init_scale (&cairo_matrix, scalef, scalef); + } + + /* reallocate surface */ + overlay->text_image = g_realloc (overlay->text_image, 4 * width * height); + + surface = cairo_image_surface_create_for_data (overlay->text_image, + CAIRO_FORMAT_ARGB32, width, height, width * 4); + cr = cairo_create (surface); + + /* clear surface */ + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + if (overlay->want_shading) + cairo_paint_with_alpha (cr, overlay->shading_value); + + /* apply transformations */ + cairo_set_matrix (cr, &cairo_matrix); + + /* FIXME: We use show_layout everywhere except for the surface + * because it's really faster and internally does all kinds of + * caching. Unfortunately we have to paint to a cairo path for + * the outline and this is slow. Once Pango supports user fonts + * we should use them, see + * https://bugzilla.gnome.org/show_bug.cgi?id=598695 + * + * Idea would the be, to create a cairo user font that + * does shadow, outline, text painting in the + * render_glyph function. + */ + + /* draw shadow text */ + cairo_save (cr); + cairo_translate (cr, overlay->shadow_offset, overlay->shadow_offset); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.5); + pango_cairo_show_layout (cr, overlay->layout); + cairo_restore (cr); + + /* draw outline text */ + cairo_save (cr); + cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); + cairo_set_line_width (cr, overlay->outline_offset); + pango_cairo_layout_path (cr, overlay->layout); + cairo_stroke (cr); + cairo_restore (cr); + + a = (overlay->color >> 24) & 0xff; + r = (overlay->color >> 16) & 0xff; + g = (overlay->color >> 8) & 0xff; + b = (overlay->color >> 0) & 0xff; + + /* draw text */ + cairo_save (cr); + cairo_set_source_rgba (cr, r / 255.0, g / 255.0, b / 255.0, a / 255.0); + pango_cairo_show_layout (cr, overlay->layout); + cairo_restore (cr); + + cairo_destroy (cr); + cairo_surface_destroy (surface); + overlay->image_width = width; + overlay->image_height = height; + overlay->baseline_y = ink_rect.y; + + g_mutex_unlock (GST_TEXT_OVERLAY_GET_CLASS (overlay)->pango_lock); +} + +#define BOX_XPAD 6 +#define BOX_YPAD 6 + +static inline void +gst_text_overlay_shade_planar_Y (GstTextOverlay * overlay, guchar * dest, + gint x0, gint x1, gint y0, gint y1) +{ + gint i, j, dest_stride; + + dest_stride = gst_video_format_get_row_stride (overlay->format, 0, + overlay->width); + + x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width); + x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width); + + y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height); + y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height); + + for (i = y0; i < y1; ++i) { + for (j = x0; j < x1; ++j) { + gint y = dest[(i * dest_stride) + j] + overlay->shading_value; + + dest[(i * dest_stride) + j] = CLAMP (y, 0, 255); + } + } +} + +static inline void +gst_text_overlay_shade_packed_Y (GstTextOverlay * overlay, guchar * dest, + gint x0, gint x1, gint y0, gint y1) +{ + gint i, j; + guint dest_stride, pixel_stride, component_offset; + + dest_stride = gst_video_format_get_row_stride (overlay->format, 0, + overlay->width); + pixel_stride = gst_video_format_get_pixel_stride (overlay->format, 0); + component_offset = + gst_video_format_get_component_offset (overlay->format, 0, overlay->width, + overlay->height); + + x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width); + x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width); + + y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height); + y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height); + + if (x0 != 0) + x0 = gst_video_format_get_component_width (overlay->format, 0, x0); + if (x1 != 0) + x1 = gst_video_format_get_component_width (overlay->format, 0, x1); + + if (y0 != 0) + y0 = gst_video_format_get_component_height (overlay->format, 0, y0); + if (y1 != 0) + y1 = gst_video_format_get_component_height (overlay->format, 0, y1); + + for (i = y0; i < y1; i++) { + for (j = x0; j < x1; j++) { + gint y; + gint y_pos; + + y_pos = (i * dest_stride) + j * pixel_stride + component_offset; + y = dest[y_pos] + overlay->shading_value; + + dest[y_pos] = CLAMP (y, 0, 255); + } + } +} + +#define gst_text_overlay_shade_BGRx gst_text_overlay_shade_xRGB +#define gst_text_overlay_shade_RGBx gst_text_overlay_shade_xRGB +#define gst_text_overlay_shade_xBGR gst_text_overlay_shade_xRGB +static inline void +gst_text_overlay_shade_xRGB (GstTextOverlay * overlay, guchar * dest, + gint x0, gint x1, gint y0, gint y1) +{ + gint i, j; + + x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width); + x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width); + + y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height); + y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height); + + for (i = y0; i < y1; i++) { + for (j = x0; j < x1; j++) { + gint y, y_pos, k; + + y_pos = (i * 4 * overlay->width) + j * 4; + for (k = 0; k < 4; k++) { + y = dest[y_pos + k] + overlay->shading_value; + dest[y_pos + k] = CLAMP (y, 0, 255); + } + } + } +} + +#define ARGB_SHADE_FUNCTION(name, OFFSET) \ +static inline void \ +gst_text_overlay_shade_##name (GstTextOverlay * overlay, guchar * dest, \ +gint x0, gint x1, gint y0, gint y1) \ +{ \ + gint i, j;\ + \ + x0 = CLAMP (x0 - BOX_XPAD, 0, overlay->width);\ + x1 = CLAMP (x1 + BOX_XPAD, 0, overlay->width);\ + \ + y0 = CLAMP (y0 - BOX_YPAD, 0, overlay->height);\ + y1 = CLAMP (y1 + BOX_YPAD, 0, overlay->height);\ + \ + for (i = y0; i < y1; i++) {\ + for (j = x0; j < x1; j++) {\ + gint y, y_pos, k;\ + y_pos = (i * 4 * overlay->width) + j * 4;\ + for (k = OFFSET; k < 3+OFFSET; k++) {\ + y = dest[y_pos + k] + overlay->shading_value;\ + dest[y_pos + k] = CLAMP (y, 0, 255);\ + }\ + }\ + }\ +} +ARGB_SHADE_FUNCTION (ARGB, 1); +ARGB_SHADE_FUNCTION (ABGR, 1); +ARGB_SHADE_FUNCTION (RGBA, 0); +ARGB_SHADE_FUNCTION (BGRA, 0); + + +/* FIXME: + * - use proper strides and offset for I420 + * - don't draw over the edge of the picture (try a longer + * text with a huge font size) + */ + +static inline void +gst_text_overlay_blit_NV12_NV21 (GstTextOverlay * overlay, + guint8 * yuv_pixels, gint xpos, gint ypos) +{ + int y_stride, uv_stride; + int u_offset, v_offset; + int h, w; + + /* because U/V is 2x2 subsampled, we need to round, either up or down, + * to a boundary of integer number of U/V pixels: + */ + xpos = GST_ROUND_UP_2 (xpos); + ypos = GST_ROUND_UP_2 (ypos); + + w = overlay->width; + h = overlay->height; + + y_stride = gst_video_format_get_row_stride (overlay->format, 0, w); + uv_stride = gst_video_format_get_row_stride (overlay->format, 1, w); + u_offset = gst_video_format_get_component_offset (overlay->format, 1, w, h); + v_offset = gst_video_format_get_component_offset (overlay->format, 2, w, h); + + gst_text_overlay_blit_1 (overlay, yuv_pixels, xpos, ypos, overlay->text_image, + y_stride); + gst_text_overlay_blit_sub2x2cbcr (overlay, yuv_pixels + u_offset, + yuv_pixels + v_offset, xpos, ypos, overlay->text_image, uv_stride, + uv_stride, 2); +} + +static inline void +gst_text_overlay_blit_I420 (GstTextOverlay * overlay, + guint8 * yuv_pixels, gint xpos, gint ypos) +{ + int y_stride, u_stride, v_stride; + int u_offset, v_offset; + int h, w; + + /* because U/V is 2x2 subsampled, we need to round, either up or down, + * to a boundary of integer number of U/V pixels: + */ + xpos = GST_ROUND_UP_2 (xpos); + ypos = GST_ROUND_UP_2 (ypos); + + w = overlay->width; + h = overlay->height; + + y_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, w); + u_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, w); + v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, w); + u_offset = + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1, w, h); + v_offset = + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2, w, h); + + gst_text_overlay_blit_1 (overlay, yuv_pixels, xpos, ypos, overlay->text_image, + y_stride); + gst_text_overlay_blit_sub2x2cbcr (overlay, yuv_pixels + u_offset, + yuv_pixels + v_offset, xpos, ypos, overlay->text_image, u_stride, + v_stride, 1); +} + +static inline void +gst_text_overlay_blit_UYVY (GstTextOverlay * overlay, + guint8 * yuv_pixels, gint xpos, gint ypos) +{ + int a0, r0, g0, b0; + int a1, r1, g1, b1; + int y0, y1, u, v; + int i, j; + int h, w; + guchar *pimage, *dest; + + /* because U/V is 2x horizontally subsampled, we need to round to a + * boundary of integer number of U/V pixels in x dimension: + */ + xpos = GST_ROUND_UP_2 (xpos); + + w = overlay->image_width - 2; + h = overlay->image_height - 2; + + if (xpos < 0) { + xpos = 0; + } + + if (xpos + w > overlay->width) { + w = overlay->width - xpos; + } + + if (ypos + h > overlay->height) { + h = overlay->height - ypos; + } + + for (i = 0; i < h; i++) { + pimage = overlay->text_image + i * overlay->image_width * 4; + dest = yuv_pixels + (i + ypos) * overlay->width * 2 + xpos * 2; + for (j = 0; j < w; j += 2) { + b0 = pimage[CAIRO_ARGB_B]; + g0 = pimage[CAIRO_ARGB_G]; + r0 = pimage[CAIRO_ARGB_R]; + a0 = pimage[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a0, r0, g0, b0); + pimage += 4; + + b1 = pimage[CAIRO_ARGB_B]; + g1 = pimage[CAIRO_ARGB_G]; + r1 = pimage[CAIRO_ARGB_R]; + a1 = pimage[CAIRO_ARGB_A]; + CAIRO_UNPREMULTIPLY (a1, r1, g1, b1); + pimage += 4; + + a0 += a1 + 2; + a0 /= 2; + if (a0 == 0) { + dest += 4; + continue; + } + + COMP_Y (y0, r0, g0, b0); + COMP_Y (y1, r1, g1, b1); + + b0 += b1 + 2; + g0 += g1 + 2; + r0 += r1 + 2; + + b0 /= 2; + g0 /= 2; + r0 /= 2; + + COMP_U (u, r0, g0, b0); + COMP_V (v, r0, g0, b0); + + BLEND (*dest, a0, u, *dest); + dest++; + BLEND (*dest, a0, y0, *dest); + dest++; + BLEND (*dest, a0, v, *dest); + dest++; + BLEND (*dest, a0, y1, *dest); + dest++; + } + } +} + +static inline void +gst_text_overlay_blit_AYUV (GstTextOverlay * overlay, + guint8 * rgb_pixels, gint xpos, gint ypos) +{ + int a, r, g, b, a1; + int y, u, v; + int i, j; + int h, w; + guchar *pimage, *dest; + + w = overlay->image_width; + h = overlay->image_height; + + if (xpos < 0) { + xpos = 0; + } + + if (xpos + w > overlay->width) { + w = overlay->width - xpos; + } + + if (ypos + h > overlay->height) { + h = overlay->height - ypos; + } + + for (i = 0; i < h; i++) { + pimage = overlay->text_image + i * overlay->image_width * 4; + dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; + for (j = 0; j < w; j++) { + a = pimage[CAIRO_ARGB_A]; + b = pimage[CAIRO_ARGB_B]; + g = pimage[CAIRO_ARGB_G]; + r = pimage[CAIRO_ARGB_R]; + + CAIRO_UNPREMULTIPLY (a, r, g, b); + + // convert background to yuv + COMP_Y (y, r, g, b); + COMP_U (u, r, g, b); + COMP_V (v, r, g, b); + + // preform text "OVER" background alpha compositing + a1 = a + (dest[0] * (255 - a)) / 255 + 1; // add 1 to prevent divide by 0 + OVER (dest[1], a, y, dest[0], dest[1], a1); + OVER (dest[2], a, u, dest[0], dest[2], a1); + OVER (dest[3], a, v, dest[0], dest[3], a1); + dest[0] = a1 - 1; // remove the temporary 1 we added + + pimage += 4; + dest += 4; + } + } +} + +#define xRGB_BLIT_FUNCTION(name, R, G, B) \ +static inline void \ +gst_text_overlay_blit_##name (GstTextOverlay * overlay, \ + guint8 * rgb_pixels, gint xpos, gint ypos) \ +{ \ + int a, r, g, b; \ + int i, j; \ + int h, w; \ + guchar *pimage, *dest; \ + \ + w = overlay->image_width; \ + h = overlay->image_height; \ + \ + if (xpos < 0) { \ + xpos = 0; \ + } \ + \ + if (xpos + w > overlay->width) { \ + w = overlay->width - xpos; \ + } \ + \ + if (ypos + h > overlay->height) { \ + h = overlay->height - ypos; \ + } \ + \ + for (i = 0; i < h; i++) { \ + pimage = overlay->text_image + i * overlay->image_width * 4; \ + dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; \ + for (j = 0; j < w; j++) { \ + a = pimage[CAIRO_ARGB_A]; \ + b = pimage[CAIRO_ARGB_B]; \ + g = pimage[CAIRO_ARGB_G]; \ + r = pimage[CAIRO_ARGB_R]; \ + CAIRO_UNPREMULTIPLY (a, r, g, b); \ + b = (b*a + dest[B] * (255-a)) / 255; \ + g = (g*a + dest[G] * (255-a)) / 255; \ + r = (r*a + dest[R] * (255-a)) / 255; \ + \ + dest[B] = b; \ + dest[G] = g; \ + dest[R] = r; \ + pimage += 4; \ + dest += 4; \ + } \ + } \ +} +xRGB_BLIT_FUNCTION (xRGB, 1, 2, 3); +xRGB_BLIT_FUNCTION (BGRx, 2, 1, 0); +xRGB_BLIT_FUNCTION (xBGR, 3, 2, 1); +xRGB_BLIT_FUNCTION (RGBx, 0, 1, 2); + +#define ARGB_BLIT_FUNCTION(name, A, R, G, B) \ +static inline void \ +gst_text_overlay_blit_##name (GstTextOverlay * overlay, \ + guint8 * rgb_pixels, gint xpos, gint ypos) \ +{ \ + int a, r, g, b, a1; \ + int i, j; \ + int h, w; \ + guchar *pimage, *dest; \ + \ + w = overlay->image_width; \ + h = overlay->image_height; \ + \ + if (xpos < 0) { \ + xpos = 0; \ + } \ + \ + if (xpos + w > overlay->width) { \ + w = overlay->width - xpos; \ + } \ + \ + if (ypos + h > overlay->height) { \ + h = overlay->height - ypos; \ + } \ + \ + for (i = 0; i < h; i++) { \ + pimage = overlay->text_image + i * overlay->image_width * 4; \ + dest = rgb_pixels + (i + ypos) * 4 * overlay->width + xpos * 4; \ + for (j = 0; j < w; j++) { \ + a = pimage[CAIRO_ARGB_A]; \ + b = pimage[CAIRO_ARGB_B]; \ + g = pimage[CAIRO_ARGB_G]; \ + r = pimage[CAIRO_ARGB_R]; \ + CAIRO_UNPREMULTIPLY (a, r, g, b); \ + a1 = a + (dest[A] * (255 - a)) / 255 + 1; \ + OVER (dest[R], a, r, dest[0], dest[R], a1); \ + OVER (dest[G], a, g, dest[0], dest[G], a1); \ + OVER (dest[B], a, b, dest[0], dest[B], a1); \ + dest[A] = a1 - 1; \ + pimage += 4; \ + dest += 4; \ + } \ + } \ +} +ARGB_BLIT_FUNCTION (RGBA, 3, 0, 1, 2); +ARGB_BLIT_FUNCTION (BGRA, 3, 2, 1, 0); +ARGB_BLIT_FUNCTION (ARGB, 0, 1, 2, 3); +ARGB_BLIT_FUNCTION (ABGR, 0, 3, 2, 1); + +static void +gst_text_overlay_render_text (GstTextOverlay * overlay, + const gchar * text, gint textlen) +{ + gchar *string; + + if (!overlay->need_render) { + GST_DEBUG ("Using previously rendered text."); + return; + } + + /* -1 is the whole string */ + if (text != NULL && textlen < 0) { + textlen = strlen (text); + } + + if (text != NULL) { + string = g_strndup (text, textlen); + } else { /* empty string */ + string = g_strdup (" "); + } + g_strdelimit (string, "\r\t", ' '); + textlen = strlen (string); + + /* FIXME: should we check for UTF-8 here? */ + + GST_DEBUG ("Rendering '%s'", string); + gst_text_overlay_render_pangocairo (overlay, string, textlen); + + g_free (string); + + overlay->need_render = FALSE; +} + +static GstFlowReturn +gst_text_overlay_push_frame (GstTextOverlay * overlay, GstBuffer * video_frame) +{ + gint xpos, ypos; + gint width, height; + GstTextOverlayVAlign valign; + GstTextOverlayHAlign halign; + + width = overlay->image_width; + height = overlay->image_height; + + video_frame = gst_buffer_make_writable (video_frame); + + if (overlay->use_vertical_render) + halign = GST_TEXT_OVERLAY_HALIGN_RIGHT; + else + halign = overlay->halign; + + switch (halign) { + case GST_TEXT_OVERLAY_HALIGN_LEFT: + xpos = overlay->xpad; + break; + case GST_TEXT_OVERLAY_HALIGN_CENTER: + xpos = (overlay->width - width) / 2; + break; + case GST_TEXT_OVERLAY_HALIGN_RIGHT: + xpos = overlay->width - width - overlay->xpad; + break; + case GST_TEXT_OVERLAY_HALIGN_POS: + xpos = (gint) (overlay->width * overlay->xpos) - width / 2; + xpos = CLAMP (xpos, 0, overlay->width - width); + if (xpos < 0) + xpos = 0; + break; + default: + xpos = 0; + } + xpos += overlay->deltax; + + if (overlay->use_vertical_render) + valign = GST_TEXT_OVERLAY_VALIGN_TOP; + else + valign = overlay->valign; + + switch (valign) { + case GST_TEXT_OVERLAY_VALIGN_BOTTOM: + ypos = overlay->height - height - overlay->ypad; + break; + case GST_TEXT_OVERLAY_VALIGN_BASELINE: + ypos = overlay->height - (height + overlay->ypad); + break; + case GST_TEXT_OVERLAY_VALIGN_TOP: + ypos = overlay->ypad; + break; + case GST_TEXT_OVERLAY_VALIGN_POS: + ypos = (gint) (overlay->height * overlay->ypos) - height / 2; + ypos = CLAMP (ypos, 0, overlay->height - height); + break; + case GST_TEXT_OVERLAY_VALIGN_CENTER: + ypos = (overlay->height - height) / 2; + break; + default: + ypos = overlay->ypad; + break; + } + ypos += overlay->deltay; + + /* shaded background box */ + if (overlay->want_shading) { + switch (overlay->format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + gst_text_overlay_shade_planar_Y (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_UYVY: + gst_text_overlay_shade_packed_Y (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_xRGB: + gst_text_overlay_shade_xRGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_xBGR: + gst_text_overlay_shade_xBGR (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_BGRx: + gst_text_overlay_shade_BGRx (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_RGBx: + gst_text_overlay_shade_RGBx (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_ARGB: + gst_text_overlay_shade_ARGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_ABGR: + gst_text_overlay_shade_ABGR (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_RGBA: + gst_text_overlay_shade_RGBA (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + case GST_VIDEO_FORMAT_BGRA: + gst_text_overlay_shade_BGRA (overlay, + GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width, + ypos, ypos + overlay->image_height); + break; + default: + g_assert_not_reached (); + } + } + + if (ypos < 0) + ypos = 0; + + if (overlay->text_image) { + switch (overlay->format) { + case GST_VIDEO_FORMAT_I420: + gst_text_overlay_blit_I420 (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + gst_text_overlay_blit_NV12_NV21 (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_UYVY: + gst_text_overlay_blit_UYVY (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_AYUV: + gst_text_overlay_blit_AYUV (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_BGRx: + gst_text_overlay_blit_BGRx (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_xRGB: + gst_text_overlay_blit_xRGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_RGBx: + gst_text_overlay_blit_RGBx (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_xBGR: + gst_text_overlay_blit_xBGR (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_ARGB: + gst_text_overlay_blit_ARGB (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_ABGR: + gst_text_overlay_blit_ABGR (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_RGBA: + gst_text_overlay_blit_RGBA (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + case GST_VIDEO_FORMAT_BGRA: + gst_text_overlay_blit_BGRA (overlay, + GST_BUFFER_DATA (video_frame), xpos, ypos); + break; + default: + g_assert_not_reached (); + } + } + return gst_pad_push (overlay->srcpad, video_frame); +} + +static GstPadLinkReturn +gst_text_overlay_text_pad_link (GstPad * pad, GstPad * peer) +{ + GstTextOverlay *overlay; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (overlay, "Text pad linked"); + + overlay->text_linked = TRUE; + + gst_object_unref (overlay); + + return GST_PAD_LINK_OK; +} + +static void +gst_text_overlay_text_pad_unlink (GstPad * pad) +{ + GstTextOverlay *overlay; + + /* don't use gst_pad_get_parent() here, will deadlock */ + overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad)); + + GST_DEBUG_OBJECT (overlay, "Text pad unlinked"); + + overlay->text_linked = FALSE; + + gst_segment_init (&overlay->text_segment, GST_FORMAT_UNDEFINED); +} + +static gboolean +gst_text_overlay_text_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstTextOverlay *overlay = NULL; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + GST_LOG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT:{ + GstFormat fmt; + gboolean update; + gdouble rate, applied_rate; + gint64 cur, stop, time; + + overlay->text_eos = FALSE; + + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &fmt, &cur, &stop, &time); + + if (fmt == GST_FORMAT_TIME) { + GST_OBJECT_LOCK (overlay); + gst_segment_set_newsegment_full (&overlay->text_segment, update, rate, + applied_rate, GST_FORMAT_TIME, cur, stop, time); + GST_DEBUG_OBJECT (overlay, "TEXT SEGMENT now: %" GST_SEGMENT_FORMAT, + &overlay->text_segment); + GST_OBJECT_UNLOCK (overlay); + } else { + GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL), + ("received non-TIME newsegment event on text input")); + } + + gst_event_unref (event); + ret = TRUE; + + /* wake up the video chain, it might be waiting for a text buffer or + * a text segment update */ + GST_OBJECT_LOCK (overlay); + GST_TEXT_OVERLAY_BROADCAST (overlay); + GST_OBJECT_UNLOCK (overlay); + break; + } + case GST_EVENT_FLUSH_STOP: + GST_OBJECT_LOCK (overlay); + GST_INFO_OBJECT (overlay, "text flush stop"); + overlay->text_flushing = FALSE; + overlay->text_eos = FALSE; + gst_text_overlay_pop_text (overlay); + gst_segment_init (&overlay->text_segment, GST_FORMAT_TIME); + GST_OBJECT_UNLOCK (overlay); + gst_event_unref (event); + ret = TRUE; + break; + case GST_EVENT_FLUSH_START: + GST_OBJECT_LOCK (overlay); + GST_INFO_OBJECT (overlay, "text flush start"); + overlay->text_flushing = TRUE; + GST_TEXT_OVERLAY_BROADCAST (overlay); + GST_OBJECT_UNLOCK (overlay); + gst_event_unref (event); + ret = TRUE; + break; + case GST_EVENT_EOS: + GST_OBJECT_LOCK (overlay); + overlay->text_eos = TRUE; + GST_INFO_OBJECT (overlay, "text EOS"); + /* wake up the video chain, it might be waiting for a text buffer or + * a text segment update */ + GST_TEXT_OVERLAY_BROADCAST (overlay); + GST_OBJECT_UNLOCK (overlay); + gst_event_unref (event); + ret = TRUE; + break; + default: + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (overlay); + + return ret; +} + +static gboolean +gst_text_overlay_video_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstTextOverlay *overlay = NULL; + + overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "received event %s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate; + gint64 start, stop, time; + gboolean update; + + GST_DEBUG_OBJECT (overlay, "received new segment"); + + gst_event_parse_new_segment (event, &update, &rate, &format, &start, + &stop, &time); + + if (format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (overlay, "VIDEO SEGMENT now: %" GST_SEGMENT_FORMAT, + &overlay->segment); + + gst_segment_set_newsegment (&overlay->segment, update, rate, format, + start, stop, time); + } else { + GST_ELEMENT_WARNING (overlay, STREAM, MUX, (NULL), + ("received non-TIME newsegment event on video input")); + } + + ret = gst_pad_event_default (pad, event); + break; + } + case GST_EVENT_EOS: + GST_OBJECT_LOCK (overlay); + GST_INFO_OBJECT (overlay, "video EOS"); + overlay->video_eos = TRUE; + GST_OBJECT_UNLOCK (overlay); + ret = gst_pad_event_default (pad, event); + break; + case GST_EVENT_FLUSH_START: + GST_OBJECT_LOCK (overlay); + GST_INFO_OBJECT (overlay, "video flush start"); + overlay->video_flushing = TRUE; + GST_TEXT_OVERLAY_BROADCAST (overlay); + GST_OBJECT_UNLOCK (overlay); + ret = gst_pad_event_default (pad, event); + break; + case GST_EVENT_FLUSH_STOP: + GST_OBJECT_LOCK (overlay); + GST_INFO_OBJECT (overlay, "video flush stop"); + overlay->video_flushing = FALSE; + overlay->video_eos = FALSE; + gst_segment_init (&overlay->segment, GST_FORMAT_TIME); + GST_OBJECT_UNLOCK (overlay); + ret = gst_pad_event_default (pad, event); + break; + default: + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (overlay); + + return ret; +} + +static GstFlowReturn +gst_text_overlay_video_bufferalloc (GstPad * pad, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buffer) +{ + GstTextOverlay *overlay = GST_TEXT_OVERLAY (gst_pad_get_parent (pad)); + GstFlowReturn ret = GST_FLOW_WRONG_STATE; + GstPad *allocpad; + + GST_OBJECT_LOCK (overlay); + allocpad = overlay->srcpad ? gst_object_ref (overlay->srcpad) : NULL; + GST_OBJECT_UNLOCK (overlay); + + if (allocpad) { + ret = gst_pad_alloc_buffer (allocpad, offset, size, caps, buffer); + gst_object_unref (allocpad); + } + + gst_object_unref (overlay); + return ret; +} + +/* Called with lock held */ +static void +gst_text_overlay_pop_text (GstTextOverlay * overlay) +{ + g_return_if_fail (GST_IS_TEXT_OVERLAY (overlay)); + + if (overlay->text_buffer) { + GST_DEBUG_OBJECT (overlay, "releasing text buffer %p", + overlay->text_buffer); + gst_buffer_unref (overlay->text_buffer); + overlay->text_buffer = NULL; + } + + /* Let the text task know we used that buffer */ + GST_TEXT_OVERLAY_BROADCAST (overlay); +} + +/* We receive text buffers here. If they are out of segment we just ignore them. + If the buffer is in our segment we keep it internally except if another one + is already waiting here, in that case we wait that it gets kicked out */ +static GstFlowReturn +gst_text_overlay_text_chain (GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstTextOverlay *overlay = NULL; + gboolean in_seg = FALSE; + gint64 clip_start = 0, clip_stop = 0; + + overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad)); + + GST_OBJECT_LOCK (overlay); + + if (overlay->text_flushing) { + GST_OBJECT_UNLOCK (overlay); + ret = GST_FLOW_WRONG_STATE; + GST_LOG_OBJECT (overlay, "text flushing"); + goto beach; + } + + if (overlay->text_eos) { + GST_OBJECT_UNLOCK (overlay); + ret = GST_FLOW_UNEXPECTED; + GST_LOG_OBJECT (overlay, "text EOS"); + goto beach; + } + + GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT " BUFFER: ts=%" + GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, &overlay->segment, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer) + + GST_BUFFER_DURATION (buffer))); + + if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))) { + GstClockTime stop; + + if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buffer))) + stop = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + else + stop = GST_CLOCK_TIME_NONE; + + in_seg = gst_segment_clip (&overlay->text_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer), stop, &clip_start, &clip_stop); + } else { + in_seg = TRUE; + } + + if (in_seg) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + GST_BUFFER_TIMESTAMP (buffer) = clip_start; + else if (GST_BUFFER_DURATION_IS_VALID (buffer)) + GST_BUFFER_DURATION (buffer) = clip_stop - clip_start; + + /* Wait for the previous buffer to go away */ + while (overlay->text_buffer != NULL) { + GST_DEBUG ("Pad %s:%s has a buffer queued, waiting", + GST_DEBUG_PAD_NAME (pad)); + GST_TEXT_OVERLAY_WAIT (overlay); + GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad)); + if (overlay->text_flushing) { + GST_OBJECT_UNLOCK (overlay); + ret = GST_FLOW_WRONG_STATE; + goto beach; + } + } + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + gst_segment_set_last_stop (&overlay->text_segment, GST_FORMAT_TIME, + clip_start); + + overlay->text_buffer = buffer; + /* That's a new text buffer we need to render */ + overlay->need_render = TRUE; + + /* in case the video chain is waiting for a text buffer, wake it up */ + GST_TEXT_OVERLAY_BROADCAST (overlay); + } + + GST_OBJECT_UNLOCK (overlay); + +beach: + + return ret; +} + +static GstFlowReturn +gst_text_overlay_video_chain (GstPad * pad, GstBuffer * buffer) +{ + GstTextOverlayClass *klass; + GstTextOverlay *overlay; + GstFlowReturn ret = GST_FLOW_OK; + gboolean in_seg = FALSE; + gint64 start, stop, clip_start = 0, clip_stop = 0; + gchar *text = NULL; + + overlay = GST_TEXT_OVERLAY (GST_PAD_PARENT (pad)); + klass = GST_TEXT_OVERLAY_GET_CLASS (overlay); + + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + goto missing_timestamp; + + /* ignore buffers that are outside of the current segment */ + start = GST_BUFFER_TIMESTAMP (buffer); + + if (!GST_BUFFER_DURATION_IS_VALID (buffer)) { + stop = GST_CLOCK_TIME_NONE; + } else { + stop = start + GST_BUFFER_DURATION (buffer); + } + + GST_LOG_OBJECT (overlay, "%" GST_SEGMENT_FORMAT " BUFFER: ts=%" + GST_TIME_FORMAT ", end=%" GST_TIME_FORMAT, &overlay->segment, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop)); + + /* segment_clip() will adjust start unconditionally to segment_start if + * no stop time is provided, so handle this ourselves */ + if (stop == GST_CLOCK_TIME_NONE && start < overlay->segment.start) + goto out_of_segment; + + in_seg = gst_segment_clip (&overlay->segment, GST_FORMAT_TIME, start, stop, + &clip_start, &clip_stop); + + if (!in_seg) + goto out_of_segment; + + /* if the buffer is only partially in the segment, fix up stamps */ + if (clip_start != start || (stop != -1 && clip_stop != stop)) { + GST_DEBUG_OBJECT (overlay, "clipping buffer timestamp/duration to segment"); + buffer = gst_buffer_make_metadata_writable (buffer); + GST_BUFFER_TIMESTAMP (buffer) = clip_start; + if (stop != -1) + GST_BUFFER_DURATION (buffer) = clip_stop - clip_start; + } + + /* now, after we've done the clipping, fix up end time if there's no + * duration (we only use those estimated values internally though, we + * don't want to set bogus values on the buffer itself) */ + if (stop == -1) { + GstStructure *s; + gint fps_num, fps_denom; + + s = gst_caps_get_structure (GST_PAD_CAPS (pad), 0); + if (gst_structure_get_fraction (s, "framerate", &fps_num, &fps_denom) && + fps_num && fps_denom) { + GST_DEBUG_OBJECT (overlay, "estimating duration based on framerate"); + stop = start + gst_util_uint64_scale_int (GST_SECOND, fps_denom, fps_num); + } else { + GST_WARNING_OBJECT (overlay, "no duration, assuming minimal duration"); + stop = start + 1; /* we need to assume some interval */ + } + } + + gst_object_sync_values (G_OBJECT (overlay), GST_BUFFER_TIMESTAMP (buffer)); + +wait_for_text_buf: + + GST_OBJECT_LOCK (overlay); + + if (overlay->video_flushing) + goto flushing; + + if (overlay->video_eos) + goto have_eos; + + if (overlay->silent) { + GST_OBJECT_UNLOCK (overlay); + ret = gst_pad_push (overlay->srcpad, buffer); + + /* Update last_stop */ + gst_segment_set_last_stop (&overlay->segment, GST_FORMAT_TIME, clip_start); + + return ret; + } + + /* Text pad not linked, rendering internal text */ + if (!overlay->text_linked) { + if (klass->get_text) { + text = klass->get_text (overlay, buffer); + } else { + text = g_strdup (overlay->default_text); + } + + GST_LOG_OBJECT (overlay, "Text pad not linked, rendering default " + "text: '%s'", GST_STR_NULL (text)); + + GST_OBJECT_UNLOCK (overlay); + + if (text != NULL && *text != '\0') { + /* Render and push */ + gst_text_overlay_render_text (overlay, text, -1); + ret = gst_text_overlay_push_frame (overlay, buffer); + } else { + /* Invalid or empty string */ + ret = gst_pad_push (overlay->srcpad, buffer); + } + } else { + /* Text pad linked, check if we have a text buffer queued */ + if (overlay->text_buffer) { + gboolean pop_text = FALSE, valid_text_time = TRUE; + GstClockTime text_start = GST_CLOCK_TIME_NONE; + GstClockTime text_end = GST_CLOCK_TIME_NONE; + GstClockTime text_running_time = GST_CLOCK_TIME_NONE; + GstClockTime text_running_time_end = GST_CLOCK_TIME_NONE; + GstClockTime vid_running_time, vid_running_time_end; + + /* if the text buffer isn't stamped right, pop it off the + * queue and display it for the current video frame only */ + if (!GST_BUFFER_TIMESTAMP_IS_VALID (overlay->text_buffer) || + !GST_BUFFER_DURATION_IS_VALID (overlay->text_buffer)) { + GST_WARNING_OBJECT (overlay, + "Got text buffer with invalid timestamp or duration"); + pop_text = TRUE; + valid_text_time = FALSE; + } else { + text_start = GST_BUFFER_TIMESTAMP (overlay->text_buffer); + text_end = text_start + GST_BUFFER_DURATION (overlay->text_buffer); + } + + vid_running_time = + gst_segment_to_running_time (&overlay->segment, GST_FORMAT_TIME, + start); + vid_running_time_end = + gst_segment_to_running_time (&overlay->segment, GST_FORMAT_TIME, + stop); + + /* If timestamp and duration are valid */ + if (valid_text_time) { + text_running_time = + gst_segment_to_running_time (&overlay->segment, GST_FORMAT_TIME, + text_start); + text_running_time_end = + gst_segment_to_running_time (&overlay->segment, GST_FORMAT_TIME, + text_end); + } + + GST_LOG_OBJECT (overlay, "T: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (text_running_time), + GST_TIME_ARGS (text_running_time_end)); + GST_LOG_OBJECT (overlay, "V: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT, + GST_TIME_ARGS (vid_running_time), + GST_TIME_ARGS (vid_running_time_end)); + + /* Text too old or in the future */ + if (valid_text_time && text_running_time_end <= vid_running_time) { + /* text buffer too old, get rid of it and do nothing */ + GST_LOG_OBJECT (overlay, "text buffer too old, popping"); + pop_text = FALSE; + gst_text_overlay_pop_text (overlay); + GST_OBJECT_UNLOCK (overlay); + goto wait_for_text_buf; + } else if (valid_text_time && vid_running_time_end <= text_running_time) { + GST_LOG_OBJECT (overlay, "text in future, pushing video buf"); + GST_OBJECT_UNLOCK (overlay); + /* Push the video frame */ + ret = gst_pad_push (overlay->srcpad, buffer); + } else { + gchar *in_text; + gsize in_size; + + in_text = (gchar *) GST_BUFFER_DATA (overlay->text_buffer); + in_size = GST_BUFFER_SIZE (overlay->text_buffer); + + /* g_markup_escape_text() absolutely requires valid UTF8 input, it + * might crash otherwise. We don't fall back on GST_SUBTITLE_ENCODING + * here on purpose, this is something that needs fixing upstream */ + if (!g_utf8_validate (in_text, in_size, NULL)) { + const gchar *end = NULL; + + GST_WARNING_OBJECT (overlay, "received invalid UTF-8"); + in_text = g_strndup (in_text, in_size); + while (!g_utf8_validate (in_text, in_size, &end) && end) + *((gchar *) end) = '*'; + } + + /* Get the string */ + if (overlay->have_pango_markup) { + text = g_strndup (in_text, in_size); + } else { + text = g_markup_escape_text (in_text, in_size); + } + + if (text != NULL && *text != '\0') { + gint text_len = strlen (text); + + while (text_len > 0 && (text[text_len - 1] == '\n' || + text[text_len - 1] == '\r')) { + --text_len; + } + GST_DEBUG_OBJECT (overlay, "Rendering text '%*s'", text_len, text); + gst_text_overlay_render_text (overlay, text, text_len); + } else { + GST_DEBUG_OBJECT (overlay, "No text to render (empty buffer)"); + gst_text_overlay_render_text (overlay, " ", 1); + } + + if (in_text != (gchar *) GST_BUFFER_DATA (overlay->text_buffer)) + g_free (in_text); + + GST_OBJECT_UNLOCK (overlay); + ret = gst_text_overlay_push_frame (overlay, buffer); + + if (valid_text_time && text_running_time_end <= vid_running_time_end) { + GST_LOG_OBJECT (overlay, "text buffer not needed any longer"); + pop_text = TRUE; + } + } + if (pop_text) { + GST_OBJECT_LOCK (overlay); + gst_text_overlay_pop_text (overlay); + GST_OBJECT_UNLOCK (overlay); + } + } else { + gboolean wait_for_text_buf = TRUE; + + if (overlay->text_eos) + wait_for_text_buf = FALSE; + + if (!overlay->wait_text) + wait_for_text_buf = FALSE; + + /* Text pad linked, but no text buffer available - what now? */ + if (overlay->text_segment.format == GST_FORMAT_TIME) { + GstClockTime text_start_running_time, text_last_stop_running_time; + GstClockTime vid_running_time; + + vid_running_time = + gst_segment_to_running_time (&overlay->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + text_start_running_time = + gst_segment_to_running_time (&overlay->text_segment, + GST_FORMAT_TIME, overlay->text_segment.start); + text_last_stop_running_time = + gst_segment_to_running_time (&overlay->text_segment, + GST_FORMAT_TIME, overlay->text_segment.last_stop); + + if ((GST_CLOCK_TIME_IS_VALID (text_start_running_time) && + vid_running_time < text_start_running_time) || + (GST_CLOCK_TIME_IS_VALID (text_last_stop_running_time) && + vid_running_time < text_last_stop_running_time)) { + wait_for_text_buf = FALSE; + } + } + + if (wait_for_text_buf) { + GST_DEBUG_OBJECT (overlay, "no text buffer, need to wait for one"); + GST_TEXT_OVERLAY_WAIT (overlay); + GST_DEBUG_OBJECT (overlay, "resuming"); + GST_OBJECT_UNLOCK (overlay); + goto wait_for_text_buf; + } else { + GST_OBJECT_UNLOCK (overlay); + GST_LOG_OBJECT (overlay, "no need to wait for a text buffer"); + ret = gst_pad_push (overlay->srcpad, buffer); + } + } + } + + g_free (text); + + /* Update last_stop */ + gst_segment_set_last_stop (&overlay->segment, GST_FORMAT_TIME, clip_start); + + return ret; + +missing_timestamp: + { + GST_WARNING_OBJECT (overlay, "buffer without timestamp, discarding"); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + +flushing: + { + GST_OBJECT_UNLOCK (overlay); + GST_DEBUG_OBJECT (overlay, "flushing, discarding buffer"); + gst_buffer_unref (buffer); + return GST_FLOW_WRONG_STATE; + } +have_eos: + { + GST_OBJECT_UNLOCK (overlay); + GST_DEBUG_OBJECT (overlay, "eos, discarding buffer"); + gst_buffer_unref (buffer); + return GST_FLOW_UNEXPECTED; + } +out_of_segment: + { + GST_DEBUG_OBJECT (overlay, "buffer out of segment, discarding"); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } +} + +static GstStateChangeReturn +gst_text_overlay_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstTextOverlay *overlay = GST_TEXT_OVERLAY (element); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_OBJECT_LOCK (overlay); + overlay->text_flushing = TRUE; + overlay->video_flushing = TRUE; + /* pop_text will broadcast on the GCond and thus also make the video + * chain exit if it's waiting for a text buffer */ + gst_text_overlay_pop_text (overlay); + GST_OBJECT_UNLOCK (overlay); + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_OBJECT_LOCK (overlay); + overlay->text_flushing = FALSE; + overlay->video_flushing = FALSE; + overlay->video_eos = FALSE; + overlay->text_eos = FALSE; + gst_segment_init (&overlay->segment, GST_FORMAT_TIME); + gst_segment_init (&overlay->text_segment, GST_FORMAT_TIME); + GST_OBJECT_UNLOCK (overlay); + break; + default: + break; + } + + return ret; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_controller_init (NULL, NULL); + + if (!gst_element_register (plugin, "textoverlay", GST_RANK_NONE, + GST_TYPE_TEXT_OVERLAY) || + !gst_element_register (plugin, "timeoverlay", GST_RANK_NONE, + GST_TYPE_TIME_OVERLAY) || + !gst_element_register (plugin, "clockoverlay", GST_RANK_NONE, + GST_TYPE_CLOCK_OVERLAY) || + !gst_element_register (plugin, "textrender", GST_RANK_NONE, + GST_TYPE_TEXT_RENDER)) { + return FALSE; + } + + /*texttestsrc_plugin_init(module, plugin); */ + + GST_DEBUG_CATEGORY_INIT (pango_debug, "pango", 0, "Pango elements"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, + "pango", "Pango-based text rendering and overlay", plugin_init, + VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.h b/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.h new file mode 100644 index 0000000..5cd4260 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttextoverlay.h @@ -0,0 +1,171 @@ +#ifndef __GST_TEXT_OVERLAY_H__ +#define __GST_TEXT_OVERLAY_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TEXT_OVERLAY (gst_text_overlay_get_type()) +#define GST_TEXT_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GST_TYPE_TEXT_OVERLAY, GstTextOverlay)) +#define GST_TEXT_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + GST_TYPE_TEXT_OVERLAY,GstTextOverlayClass)) +#define GST_TEXT_OVERLAY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ + GST_TYPE_TEXT_OVERLAY, GstTextOverlayClass)) +#define GST_IS_TEXT_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + GST_TYPE_TEXT_OVERLAY)) +#define GST_IS_TEXT_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + GST_TYPE_TEXT_OVERLAY)) + +typedef struct _GstTextOverlay GstTextOverlay; +typedef struct _GstTextOverlayClass GstTextOverlayClass; + +/** + * GstTextOverlayVAlign: + * @GST_TEXT_OVERLAY_VALIGN_BASELINE: draw text on the baseline + * @GST_TEXT_OVERLAY_VALIGN_BOTTOM: draw text on the bottom + * @GST_TEXT_OVERLAY_VALIGN_TOP: draw text on top + * @GST_TEXT_OVERLAY_VALIGN_POS: draw text according to the #GstTextOverlay:ypos property + * @GST_TEXT_OVERLAY_VALIGN_CENTER: draw text vertically centered + * + * Vertical alignment of the text. + */ +typedef enum { + GST_TEXT_OVERLAY_VALIGN_BASELINE, + GST_TEXT_OVERLAY_VALIGN_BOTTOM, + GST_TEXT_OVERLAY_VALIGN_TOP, + GST_TEXT_OVERLAY_VALIGN_POS, + GST_TEXT_OVERLAY_VALIGN_CENTER +} GstTextOverlayVAlign; + +/** + * GstTextOverlayHAlign: + * @GST_TEXT_OVERLAY_HALIGN_LEFT: align text left + * @GST_TEXT_OVERLAY_HALIGN_CENTER: align text center + * @GST_TEXT_OVERLAY_HALIGN_RIGHT: align text right + * @GST_TEXT_OVERLAY_HALIGN_POS: position text according to the #GstTextOverlay:xpos property + * + * Horizontal alignment of the text. + */ +/* FIXME 0.11: remove GST_TEXT_OVERLAY_HALIGN_UNUSED */ +typedef enum { + GST_TEXT_OVERLAY_HALIGN_LEFT, + GST_TEXT_OVERLAY_HALIGN_CENTER, + GST_TEXT_OVERLAY_HALIGN_RIGHT, + GST_TEXT_OVERLAY_HALIGN_UNUSED, + GST_TEXT_OVERLAY_HALIGN_POS +} GstTextOverlayHAlign; + +/** + * GstTextOverlayWrapMode: + * @GST_TEXT_OVERLAY_WRAP_MODE_NONE: no wrapping + * @GST_TEXT_OVERLAY_WRAP_MODE_WORD: do word wrapping + * @GST_TEXT_OVERLAY_WRAP_MODE_CHAR: do char wrapping + * @GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR: do word and char wrapping + * + * Whether to wrap the text and if so how. + */ +typedef enum { + GST_TEXT_OVERLAY_WRAP_MODE_NONE = -1, + GST_TEXT_OVERLAY_WRAP_MODE_WORD = PANGO_WRAP_WORD, + GST_TEXT_OVERLAY_WRAP_MODE_CHAR = PANGO_WRAP_CHAR, + GST_TEXT_OVERLAY_WRAP_MODE_WORD_CHAR = PANGO_WRAP_WORD_CHAR +} GstTextOverlayWrapMode; + +/** + * GstTextOverlayLineAlign: + * @GST_TEXT_OVERLAY_LINE_ALIGN_LEFT: lines are left-aligned + * @GST_TEXT_OVERLAY_LINE_ALIGN_CENTER: lines are center-aligned + * @GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT: lines are right-aligned + * + * Alignment of text lines relative to each other + */ +typedef enum { + GST_TEXT_OVERLAY_LINE_ALIGN_LEFT = PANGO_ALIGN_LEFT, + GST_TEXT_OVERLAY_LINE_ALIGN_CENTER = PANGO_ALIGN_CENTER, + GST_TEXT_OVERLAY_LINE_ALIGN_RIGHT = PANGO_ALIGN_RIGHT +} GstTextOverlayLineAlign; + +/** + * GstTextOverlay: + * + * Opaque textoverlay object structure + */ +struct _GstTextOverlay { + GstElement element; + + GstPad *video_sinkpad; + GstPad *text_sinkpad; + GstPad *srcpad; + + GstSegment segment; + GstSegment text_segment; + GstBuffer *text_buffer; + gboolean text_linked; + gboolean video_flushing; + gboolean video_eos; + gboolean text_flushing; + gboolean text_eos; + + GCond *cond; /* to signal removal of a queued text + * buffer, arrival of a text buffer, + * a text segment update, or a change + * in status (e.g. shutdown, flushing) */ + + gint width; + gint height; + gint fps_n; + gint fps_d; + GstVideoFormat format; + + GstTextOverlayVAlign valign; + GstTextOverlayHAlign halign; + GstTextOverlayWrapMode wrap_mode; + GstTextOverlayLineAlign line_align; + + gint xpad; + gint ypad; + gint deltax; + gint deltay; + gdouble xpos; + gdouble ypos; + gchar *default_text; + gboolean want_shading; + gboolean silent; + gboolean wait_text; + guint color; + + PangoLayout *layout; + gdouble shadow_offset; + gdouble outline_offset; + guchar *text_image; + gint image_width; + gint image_height; + gint baseline_y; + + gboolean auto_adjust_size; + gboolean need_render; + + gint shading_value; /* for timeoverlay subclass */ + + gboolean have_pango_markup; + gboolean use_vertical_render; +}; + +struct _GstTextOverlayClass { + GstElementClass parent_class; + + PangoContext *pango_context; + GMutex *pango_lock; + + gchar * (*get_text) (GstTextOverlay *overlay, GstBuffer *video_frame); +}; + +GType gst_text_overlay_get_type(void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_TEXT_OVERLAY_H */ diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.c b/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.c new file mode 100644 index 0000000..c937244 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.c @@ -0,0 +1,705 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * Copyright (C) <2009> Young-Ho Cha + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/** + * SECTION:element-textrender + * @see_also: #GstTextOverlay + * + * This plugin renders text received on the text sink pad to a video + * buffer (retaining the alpha channel), so it can later be overlayed + * on top of video streams using other elements. + * + * The text can contain newline characters. (FIXME: What about text + * wrapping? It does not make sense in this context) + * + * + * Example launch lines + * |[ + * gst-launch -v filesrc location=subtitles.srt ! subparse ! textrender ! xvimagesink + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#include "gsttextrender.h" +#include + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +# define CAIRO_ARGB_A 3 +# define CAIRO_ARGB_R 2 +# define CAIRO_ARGB_G 1 +# define CAIRO_ARGB_B 0 +#else +# define CAIRO_ARGB_A 0 +# define CAIRO_ARGB_R 1 +# define CAIRO_ARGB_G 2 +# define CAIRO_ARGB_B 3 +#endif + +GST_DEBUG_CATEGORY_EXTERN (pango_debug); +#define GST_CAT_DEFAULT pango_debug + +#define MINIMUM_OUTLINE_OFFSET 1.0 + +#define DEFAULT_PROP_VALIGNMENT GST_TEXT_RENDER_VALIGN_BASELINE +#define DEFAULT_PROP_HALIGNMENT GST_TEXT_RENDER_HALIGN_CENTER +#define DEFAULT_PROP_LINE_ALIGNMENT GST_TEXT_RENDER_LINE_ALIGN_CENTER +#define DEFAULT_PROP_XPAD 25 +#define DEFAULT_PROP_YPAD 25 + +#define DEFAULT_RENDER_WIDTH 720 +#define DEFAULT_RENDER_HEIGHT 576 + +enum +{ + PROP_0, + PROP_HALIGNMENT, + PROP_VALIGNMENT, + PROP_LINE_ALIGNMENT, + PROP_XPAD, + PROP_YPAD, + PROP_FONT_DESC +}; + + +static GstStaticPadTemplate src_template_factory = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV") ";" GST_VIDEO_CAPS_ARGB) + ); + +static GstStaticPadTemplate sink_template_factory = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/x-pango-markup; text/plain") + ); + +#define GST_TYPE_TEXT_RENDER_VALIGN (gst_text_render_valign_get_type()) +static GType +gst_text_render_valign_get_type (void) +{ + static GType text_render_valign_type = 0; + static const GEnumValue text_render_valign[] = { + {GST_TEXT_RENDER_VALIGN_BASELINE, "baseline", "baseline"}, + {GST_TEXT_RENDER_VALIGN_BOTTOM, "bottom", "bottom"}, + {GST_TEXT_RENDER_VALIGN_TOP, "top", "top"}, + {0, NULL, NULL}, + }; + + if (!text_render_valign_type) { + text_render_valign_type = + g_enum_register_static ("GstTextRenderVAlign", text_render_valign); + } + return text_render_valign_type; +} + +#define GST_TYPE_TEXT_RENDER_HALIGN (gst_text_render_halign_get_type()) +static GType +gst_text_render_halign_get_type (void) +{ + static GType text_render_halign_type = 0; + static const GEnumValue text_render_halign[] = { + {GST_TEXT_RENDER_HALIGN_LEFT, "left", "left"}, + {GST_TEXT_RENDER_HALIGN_CENTER, "center", "center"}, + {GST_TEXT_RENDER_HALIGN_RIGHT, "right", "right"}, + {0, NULL, NULL}, + }; + + if (!text_render_halign_type) { + text_render_halign_type = + g_enum_register_static ("GstTextRenderHAlign", text_render_halign); + } + return text_render_halign_type; +} + +#define GST_TYPE_TEXT_RENDER_LINE_ALIGN (gst_text_render_line_align_get_type()) +static GType +gst_text_render_line_align_get_type (void) +{ + static GType text_render_line_align_type = 0; + static const GEnumValue text_render_line_align[] = { + {GST_TEXT_RENDER_LINE_ALIGN_LEFT, "left", "left"}, + {GST_TEXT_RENDER_LINE_ALIGN_CENTER, "center", "center"}, + {GST_TEXT_RENDER_LINE_ALIGN_RIGHT, "right", "right"}, + {0, NULL, NULL} + }; + + if (!text_render_line_align_type) { + text_render_line_align_type = + g_enum_register_static ("GstTextRenderLineAlign", + text_render_line_align); + } + return text_render_line_align_type; +} + +static void gst_text_render_adjust_values_with_fontdesc (GstTextRender * + render, PangoFontDescription * desc); + +GST_BOILERPLATE (GstTextRender, gst_text_render, GstElement, GST_TYPE_ELEMENT); + +static void gst_text_render_finalize (GObject * object); +static void gst_text_render_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_text_render_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static void +gst_text_render_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template_factory)); + + gst_element_class_set_details_simple (element_class, "Text renderer", + "Filter/Editor/Video", + "Renders a text string to an image bitmap", + "David Schleef , " + "GStreamer maintainers "); +} + +static void +gst_text_render_class_init (GstTextRenderClass * klass) +{ + GObjectClass *gobject_class; + PangoFontMap *fontmap; + + gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_text_render_finalize; + gobject_class->set_property = gst_text_render_set_property; + gobject_class->get_property = gst_text_render_get_property; + + fontmap = pango_cairo_font_map_get_default (); + klass->pango_context = + pango_cairo_font_map_create_context (PANGO_CAIRO_FONT_MAP (fontmap)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FONT_DESC, + g_param_spec_string ("font-desc", "font description", + "Pango font description of font " + "to be used for rendering. " + "See documentation of " + "pango_font_description_from_string" + " for syntax.", "", G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_VALIGNMENT, + g_param_spec_enum ("valignment", "vertical alignment", + "Vertical alignment of the text", GST_TYPE_TEXT_RENDER_VALIGN, + DEFAULT_PROP_VALIGNMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HALIGNMENT, + g_param_spec_enum ("halignment", "horizontal alignment", + "Horizontal alignment of the text", GST_TYPE_TEXT_RENDER_HALIGN, + DEFAULT_PROP_HALIGNMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_XPAD, + g_param_spec_int ("xpad", "horizontal paddding", + "Horizontal paddding when using left/right alignment", 0, G_MAXINT, + DEFAULT_PROP_XPAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_YPAD, + g_param_spec_int ("ypad", "vertical padding", + "Vertical padding when using top/bottom alignment", 0, G_MAXINT, + DEFAULT_PROP_YPAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_LINE_ALIGNMENT, + g_param_spec_enum ("line-alignment", "line alignment", + "Alignment of text lines relative to each other.", + GST_TYPE_TEXT_RENDER_LINE_ALIGN, DEFAULT_PROP_LINE_ALIGNMENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_text_render_adjust_values_with_fontdesc (GstTextRender * render, + PangoFontDescription * desc) +{ + gint font_size = pango_font_description_get_size (desc) / PANGO_SCALE; + + render->shadow_offset = (double) (font_size) / 13.0; + render->outline_offset = (double) (font_size) / 15.0; + if (render->outline_offset < MINIMUM_OUTLINE_OFFSET) + render->outline_offset = MINIMUM_OUTLINE_OFFSET; +} + +static void +gst_text_render_render_pangocairo (GstTextRender * render) +{ + cairo_t *cr; + cairo_surface_t *surface; + cairo_t *cr_shadow; + cairo_surface_t *surface_shadow; + PangoRectangle ink_rect, logical_rect; + gint width, height; + + pango_layout_get_pixel_extents (render->layout, &ink_rect, &logical_rect); + + width = logical_rect.width + render->shadow_offset; + height = logical_rect.height + logical_rect.y + render->shadow_offset; + + surface_shadow = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); + cr_shadow = cairo_create (surface_shadow); + + /* clear shadow surface */ + cairo_set_operator (cr_shadow, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr_shadow); + cairo_set_operator (cr_shadow, CAIRO_OPERATOR_OVER); + + /* draw shadow text */ + cairo_save (cr_shadow); + cairo_set_source_rgba (cr_shadow, 0.0, 0.0, 0.0, 0.5); + cairo_translate (cr_shadow, render->shadow_offset, render->shadow_offset); + pango_cairo_show_layout (cr_shadow, render->layout); + cairo_restore (cr_shadow); + + /* draw outline text */ + cairo_save (cr_shadow); + cairo_set_source_rgb (cr_shadow, 0.0, 0.0, 0.0); + cairo_set_line_width (cr_shadow, render->outline_offset); + pango_cairo_layout_path (cr_shadow, render->layout); + cairo_stroke (cr_shadow); + cairo_restore (cr_shadow); + + cairo_destroy (cr_shadow); + + render->text_image = g_realloc (render->text_image, 4 * width * height); + + surface = cairo_image_surface_create_for_data (render->text_image, + CAIRO_FORMAT_ARGB32, width, height, width * 4); + cr = cairo_create (surface); + cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); + cairo_paint (cr); + cairo_set_operator (cr, CAIRO_OPERATOR_OVER); + + /* set default color */ + cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); + + cairo_save (cr); + /* draw text */ + pango_cairo_show_layout (cr, render->layout); + cairo_restore (cr); + + /* composite shadow with offset */ + cairo_set_operator (cr, CAIRO_OPERATOR_DEST_OVER); + cairo_set_source_surface (cr, surface_shadow, 0.0, 0.0); + cairo_paint (cr); + + cairo_destroy (cr); + cairo_surface_destroy (surface_shadow); + cairo_surface_destroy (surface); + render->image_width = width; + render->image_height = height; +} + +static void +gst_text_render_check_argb (GstTextRender * render) +{ + GstCaps *peer_caps; + peer_caps = gst_pad_get_allowed_caps (render->srcpad); + if (G_LIKELY (peer_caps)) { + guint i = 0, n = 0; + + n = gst_caps_get_size (peer_caps); + GST_DEBUG_OBJECT (render, "peer allowed caps (%u structure(s)) are %" + GST_PTR_FORMAT, n, peer_caps); + + /* Check if AYUV or ARGB is first */ + for (i = 0; i < n; i++) { + GstStructure *s = gst_caps_get_structure (peer_caps, i); + if (gst_structure_has_name (s, "video/x-raw-rgb") && + gst_structure_has_field (s, "alpha_mask")) { + render->use_ARGB = TRUE; + break; + } else if (gst_structure_has_name (s, "video/x-raw-yuv")) { + guint fourcc; + if (gst_structure_get_fourcc (s, "format", &fourcc) && + fourcc == GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')) { + render->use_ARGB = FALSE; + break; + } + } + } + gst_caps_unref (peer_caps); + } +} + +static gboolean +gst_text_render_setcaps (GstPad * pad, GstCaps * caps) +{ + GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad)); + GstStructure *structure; + gboolean ret = FALSE; + gint width = 0, height = 0; + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + + GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps); + + if (width >= render->image_width && height >= render->image_height) { + render->width = width; + render->height = height; + ret = TRUE; + } + + gst_text_render_check_argb (render); + + gst_object_unref (render); + return ret; +} + +static void +gst_text_render_fixate_caps (GstPad * pad, GstCaps * caps) +{ + GstTextRender *render = GST_TEXT_RENDER (gst_pad_get_parent (pad)); + GstStructure *s = gst_caps_get_structure (caps, 0); + + GST_DEBUG ("Fixating caps %" GST_PTR_FORMAT, caps); + gst_structure_fixate_field_nearest_int (s, "width", render->image_width); + gst_structure_fixate_field_nearest_int (s, "height", render->image_height); + GST_DEBUG ("Fixated to %" GST_PTR_FORMAT, caps); + + gst_object_unref (render); +} + +#define CAIRO_UNPREMULTIPLY(a,r,g,b) G_STMT_START { \ + b = (a > 0) ? MIN ((b * 255 + a / 2) / a, 255) : 0; \ + g = (a > 0) ? MIN ((g * 255 + a / 2) / a, 255) : 0; \ + r = (a > 0) ? MIN ((r * 255 + a / 2) / a, 255) : 0; \ +} G_STMT_END + +static void +gst_text_renderer_image_to_ayuv (GstTextRender * render, guchar * pixbuf, + int xpos, int ypos, int stride) +{ + int y; /* text bitmap coordinates */ + guchar *p, *bitp; + guchar a, r, g, b; + int width, height; + + width = render->image_width; + height = render->image_height; + bitp = render->text_image; + + for (y = 0; y < height; y++) { + int n; + p = pixbuf + (ypos + y) * stride + xpos * 4; + for (n = 0; n < width; n++) { + b = bitp[CAIRO_ARGB_B]; + g = bitp[CAIRO_ARGB_G]; + r = bitp[CAIRO_ARGB_R]; + a = bitp[CAIRO_ARGB_A]; + bitp += 4; + + /* Cairo uses pre-multiplied ARGB, unpremultiply it */ + CAIRO_UNPREMULTIPLY (a, r, g, b); + + *p++ = a; + *p++ = CLAMP ((int) (((19595 * r) >> 16) + ((38470 * g) >> 16) + + ((7471 * b) >> 16)), 0, 255); + *p++ = CLAMP ((int) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + + ((32768 * b) >> 16) + 128), 0, 255); + *p++ = CLAMP ((int) (((32768 * r) >> 16) - ((27439 * g) >> 16) - + ((5329 * b) >> 16) + 128), 0, 255); + } + } +} + +static void +gst_text_renderer_image_to_argb (GstTextRender * render, guchar * pixbuf, + int xpos, int ypos, int stride) +{ + int i, j; + guchar *p, *bitp; + int width, height; + + width = render->image_width; + height = render->image_height; + bitp = render->text_image; + + for (i = 0; i < height; i++) { + p = pixbuf + (ypos + i) * stride + xpos * 4; + for (j = 0; j < width; j++) { + p[0] = bitp[CAIRO_ARGB_A]; + p[1] = bitp[CAIRO_ARGB_R]; + p[2] = bitp[CAIRO_ARGB_G]; + p[3] = bitp[CAIRO_ARGB_B]; + + /* Cairo uses pre-multiplied ARGB, unpremultiply it */ + CAIRO_UNPREMULTIPLY (p[0], p[1], p[2], p[3]); + + bitp += 4; + p += 4; + } + } +} + +static GstFlowReturn +gst_text_render_chain (GstPad * pad, GstBuffer * inbuf) +{ + GstTextRender *render; + GstFlowReturn ret; + GstBuffer *outbuf; + GstCaps *caps = NULL; + guint8 *data = GST_BUFFER_DATA (inbuf); + guint size = GST_BUFFER_SIZE (inbuf); + gint n; + gint xpos, ypos; + + render = GST_TEXT_RENDER (gst_pad_get_parent (pad)); + + /* somehow pango barfs over "\0" buffers... */ + while (size > 0 && + (data[size - 1] == '\r' || + data[size - 1] == '\n' || data[size - 1] == '\0')) { + size--; + } + + /* render text */ + GST_DEBUG ("rendering '%*s'", size, data); + pango_layout_set_markup (render->layout, (gchar *) data, size); + gst_text_render_render_pangocairo (render); + + gst_text_render_check_argb (render); + + if (!render->use_ARGB) { + caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_AYUV, render->width, + render->height, 1, 1, 1, 1); + } else { + caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_ARGB, render->width, + render->height, 1, 1, 1, 1); + } + + if (!gst_pad_set_caps (render->srcpad, caps)) { + gst_caps_unref (caps); + GST_ELEMENT_ERROR (render, CORE, NEGOTIATION, (NULL), (NULL)); + ret = GST_FLOW_ERROR; + goto done; + } + + GST_DEBUG ("Allocating buffer WxH = %dx%d", render->width, render->height); + ret = + gst_pad_alloc_buffer_and_set_caps (render->srcpad, GST_BUFFER_OFFSET_NONE, + render->width * render->height * 4, caps, &outbuf); + + if (ret != GST_FLOW_OK) + goto done; + + gst_buffer_copy_metadata (outbuf, inbuf, GST_BUFFER_COPY_TIMESTAMPS); + data = GST_BUFFER_DATA (outbuf); + + if (render->use_ARGB) { + memset (data, 0, render->width * render->height * 4); + } else { + for (n = 0; n < render->width * render->height; n++) { + data[n * 4] = data[n * 4 + 1] = 0; + data[n * 4 + 2] = data[n * 4 + 3] = 128; + } + } + + switch (render->halign) { + case GST_TEXT_RENDER_HALIGN_LEFT: + xpos = render->xpad; + break; + case GST_TEXT_RENDER_HALIGN_CENTER: + xpos = (render->width - render->image_width) / 2; + break; + case GST_TEXT_RENDER_HALIGN_RIGHT: + xpos = render->width - render->image_width - render->xpad; + break; + default: + xpos = 0; + } + + switch (render->valign) { + case GST_TEXT_RENDER_VALIGN_BOTTOM: + ypos = render->height - render->image_height - render->ypad; + break; + case GST_TEXT_RENDER_VALIGN_BASELINE: + ypos = render->height - (render->image_height + render->ypad); + break; + case GST_TEXT_RENDER_VALIGN_TOP: + ypos = render->ypad; + break; + default: + ypos = render->ypad; + break; + } + + if (render->text_image) { + if (render->use_ARGB) { + gst_text_renderer_image_to_argb (render, data, xpos, ypos, + render->width * 4); + } else { + gst_text_renderer_image_to_ayuv (render, data, xpos, ypos, + render->width * 4); + } + } + + ret = gst_pad_push (render->srcpad, outbuf); + +done: + if (caps) + gst_caps_unref (caps); + gst_buffer_unref (inbuf); + gst_object_unref (render); + return ret; +} + +static void +gst_text_render_finalize (GObject * object) +{ + GstTextRender *render = GST_TEXT_RENDER (object); + + g_free (render->text_image); + + if (render->layout) + g_object_unref (render->layout); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_text_render_init (GstTextRender * render, GstTextRenderClass * klass) +{ + GstPadTemplate *template; + + /* sink */ + template = gst_static_pad_template_get (&sink_template_factory); + render->sinkpad = gst_pad_new_from_template (template, "sink"); + gst_object_unref (template); + gst_pad_set_chain_function (render->sinkpad, + GST_DEBUG_FUNCPTR (gst_text_render_chain)); + gst_element_add_pad (GST_ELEMENT (render), render->sinkpad); + + /* source */ + template = gst_static_pad_template_get (&src_template_factory); + render->srcpad = gst_pad_new_from_template (template, "src"); + gst_object_unref (template); + gst_pad_set_fixatecaps_function (render->srcpad, + GST_DEBUG_FUNCPTR (gst_text_render_fixate_caps)); + gst_pad_set_setcaps_function (render->srcpad, + GST_DEBUG_FUNCPTR (gst_text_render_setcaps)); + + gst_element_add_pad (GST_ELEMENT (render), render->srcpad); + + render->line_align = DEFAULT_PROP_LINE_ALIGNMENT; + render->layout = + pango_layout_new (GST_TEXT_RENDER_GET_CLASS (render)->pango_context); + pango_layout_set_alignment (render->layout, + (PangoAlignment) render->line_align); + + render->halign = DEFAULT_PROP_HALIGNMENT; + render->valign = DEFAULT_PROP_VALIGNMENT; + render->xpad = DEFAULT_PROP_XPAD; + render->ypad = DEFAULT_PROP_YPAD; + + render->width = DEFAULT_RENDER_WIDTH; + render->height = DEFAULT_RENDER_HEIGHT; + + render->use_ARGB = FALSE; +} + +static void +gst_text_render_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTextRender *render = GST_TEXT_RENDER (object); + + switch (prop_id) { + case PROP_VALIGNMENT: + render->valign = g_value_get_enum (value); + break; + case PROP_HALIGNMENT: + render->halign = g_value_get_enum (value); + break; + case PROP_LINE_ALIGNMENT: + render->line_align = g_value_get_enum (value); + pango_layout_set_alignment (render->layout, + (PangoAlignment) render->line_align); + break; + case PROP_XPAD: + render->xpad = g_value_get_int (value); + break; + case PROP_YPAD: + render->ypad = g_value_get_int (value); + break; + case PROP_FONT_DESC: + { + PangoFontDescription *desc; + + desc = pango_font_description_from_string (g_value_get_string (value)); + if (desc) { + GST_LOG ("font description set: %s", g_value_get_string (value)); + GST_OBJECT_LOCK (render); + pango_layout_set_font_description (render->layout, desc); + gst_text_render_adjust_values_with_fontdesc (render, desc); + pango_font_description_free (desc); + gst_text_render_render_pangocairo (render); + GST_OBJECT_UNLOCK (render); + } else { + GST_WARNING ("font description parse failed: %s", + g_value_get_string (value)); + } + break; + } + + default: + break; + } +} + +static void +gst_text_render_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTextRender *render = GST_TEXT_RENDER (object); + + switch (prop_id) { + case PROP_VALIGNMENT: + g_value_set_enum (value, render->valign); + break; + case PROP_HALIGNMENT: + g_value_set_enum (value, render->halign); + break; + case PROP_LINE_ALIGNMENT: + g_value_set_enum (value, render->line_align); + break; + case PROP_XPAD: + g_value_set_int (value, render->xpad); + break; + case PROP_YPAD: + g_value_set_int (value, render->ypad); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.h b/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.h new file mode 100644 index 0000000..66d37db --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttextrender.h @@ -0,0 +1,104 @@ +#ifndef __GST_TEXT_RENDER_H__ +#define __GST_TEXT_RENDER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TEXT_RENDER (gst_text_render_get_type()) +#define GST_TEXT_RENDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ + GST_TYPE_TEXT_RENDER, GstTextRender)) +#define GST_TEXT_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ + GST_TYPE_TEXT_RENDER, GstTextRenderClass)) +#define GST_TEXT_RENDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),\ + GST_TYPE_TEXT_RENDER, GstTextRenderClass)) +#define GST_IS_TEXT_RENDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ + GST_TYPE_TEXT_RENDER)) +#define GST_IS_TEXT_RENDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ + GST_TYPE_TEXT_RENDER)) + +typedef struct _GstTextRender GstTextRender; +typedef struct _GstTextRenderClass GstTextRenderClass; + +/** + * GstTextRenderVAlign: + * @GST_TEXT_RENDER_VALIGN_BASELINE: draw text on the baseline + * @GST_TEXT_RENDER_VALIGN_BOTTOM: draw text on the bottom + * @GST_TEXT_RENDER_VALIGN_TOP: draw test on top + * + * Vertical alignment of the text. + */ +typedef enum { + GST_TEXT_RENDER_VALIGN_BASELINE, + GST_TEXT_RENDER_VALIGN_BOTTOM, + GST_TEXT_RENDER_VALIGN_TOP +} GstTextRenderVAlign; + +/** + * GstTextRenderHAlign: + * @GST_TEXT_RENDER_HALIGN_LEFT: align text left + * @GST_TEXT_RENDER_HALIGN_CENTER: align text center + * @GST_TEXT_RENDER_HALIGN_RIGHT: align text right + * + * Horizontal alignment of the text. + */ +typedef enum { + GST_TEXT_RENDER_HALIGN_LEFT, + GST_TEXT_RENDER_HALIGN_CENTER, + GST_TEXT_RENDER_HALIGN_RIGHT +} GstTextRenderHAlign; + +/** + * GstTextRenderLineAlign: + * @GST_TEXT_RENDER_LINE_ALIGN_LEFT: lines are left-aligned + * @GST_TEXT_RENDER_LINE_ALIGN_CENTER: lines are center-aligned + * @GST_TEXT_RENDER_LINE_ALIGN_RIGHT: lines are right-aligned + * + * Alignment of text lines relative to each other + */ +typedef enum { + GST_TEXT_RENDER_LINE_ALIGN_LEFT = PANGO_ALIGN_LEFT, + GST_TEXT_RENDER_LINE_ALIGN_CENTER = PANGO_ALIGN_CENTER, + GST_TEXT_RENDER_LINE_ALIGN_RIGHT = PANGO_ALIGN_RIGHT +} GstTextRenderLineAlign; + +/** + * GstTextRender: + * + * Opaque textrender data structure. + */ +struct _GstTextRender { + GstElement element; + + GstPad *sinkpad, *srcpad; + gint width; + gint height; + PangoLayout *layout; + gdouble shadow_offset; + gdouble outline_offset; + guchar *text_image; + gint image_width; + gint image_height; + gint baseline_y; + gboolean use_ARGB; + + GstTextRenderVAlign valign; + GstTextRenderHAlign halign; + GstTextRenderLineAlign line_align; + + gint xpad; + gint ypad; +}; + +struct _GstTextRenderClass { + GstElementClass parent_class; + + PangoContext *pango_context; +}; + +GType gst_text_render_get_type(void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_TEXT_RENDER_H */ diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.c b/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.c new file mode 100644 index 0000000..27fab92 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.c @@ -0,0 +1,153 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-timeoverlay + * @see_also: #GstTextOverlay, #GstClockOverlay + * + * This element overlays the buffer time stamps of a video stream on + * top of itself. You can position the text and configure the font details + * using the properties of the #GstTextOverlay class. By default, the + * time stamp is displayed in the top left corner of the picture, with some + * padding to the left and to the top. + * + * + * |[ + * gst-launch -v videotestsrc ! timeoverlay ! xvimagesink + * ]| Display the time stamps in the top left + * corner of the video picture. + * |[ + * gst-launch -v videotestsrc ! timeoverlay halign=right valign=bottom text="Stream time:" shaded-background=true ! xvimagesink + * ]| Another pipeline that displays the time stamps with some leading + * text in the bottom right corner of the video picture, with the background + * of the text being shaded in order to make it more legible on top of a + * bright video background. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +GST_BOILERPLATE (GstTimeOverlay, gst_time_overlay, GstTextOverlay, + GST_TYPE_TEXT_OVERLAY); + +static void +gst_time_overlay_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, "Time overlay", + "Filter/Editor/Video", + "Overlays buffer time stamps on a video stream", + "Tim-Philipp Müller "); +} + +static gchar * +gst_time_overlay_render_time (GstTimeOverlay * overlay, GstClockTime time) +{ + guint hours, mins, secs, msecs; + + if (!GST_CLOCK_TIME_IS_VALID (time)) + return g_strdup (""); + + hours = (guint) (time / (GST_SECOND * 60 * 60)); + mins = (guint) ((time / (GST_SECOND * 60)) % 60); + secs = (guint) ((time / GST_SECOND) % 60); + msecs = (guint) ((time % GST_SECOND) / (1000 * 1000)); + + return g_strdup_printf ("%u:%02u:%02u.%03u", hours, mins, secs, msecs); +} + +/* Called with lock held */ +static gchar * +gst_time_overlay_get_text (GstTextOverlay * overlay, GstBuffer * video_frame) +{ + GstClockTime time = GST_BUFFER_TIMESTAMP (video_frame); + gchar *time_str, *txt, *ret; + + overlay->need_render = TRUE; + + if (!GST_CLOCK_TIME_IS_VALID (time)) { + GST_DEBUG ("buffer without valid timestamp"); + return g_strdup (""); + } + + GST_DEBUG ("buffer with timestamp %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + txt = g_strdup (overlay->default_text); + + time_str = gst_time_overlay_render_time (GST_TIME_OVERLAY (overlay), time); + if (txt != NULL && *txt != '\0') { + ret = g_strdup_printf ("%s %s", txt, time_str); + } else { + ret = time_str; + time_str = NULL; + } + + g_free (txt); + g_free (time_str); + + return ret; +} + +static void +gst_time_overlay_class_init (GstTimeOverlayClass * klass) +{ + GstTextOverlayClass *gsttextoverlay_class; + PangoContext *context; + PangoFontDescription *font_description; + + gsttextoverlay_class = (GstTextOverlayClass *) klass; + + gsttextoverlay_class->get_text = gst_time_overlay_get_text; + + g_mutex_lock (GST_TEXT_OVERLAY_CLASS (klass)->pango_lock); + context = GST_TEXT_OVERLAY_CLASS (klass)->pango_context; + + pango_context_set_language (context, pango_language_from_string ("en_US")); + pango_context_set_base_dir (context, PANGO_DIRECTION_LTR); + + font_description = pango_font_description_new (); + pango_font_description_set_family_static (font_description, "Monospace"); + pango_font_description_set_style (font_description, PANGO_STYLE_NORMAL); + pango_font_description_set_variant (font_description, PANGO_VARIANT_NORMAL); + pango_font_description_set_weight (font_description, PANGO_WEIGHT_NORMAL); + pango_font_description_set_stretch (font_description, PANGO_STRETCH_NORMAL); + pango_font_description_set_size (font_description, 18 * PANGO_SCALE); + pango_context_set_font_description (context, font_description); + pango_font_description_free (font_description); + g_mutex_unlock (GST_TEXT_OVERLAY_CLASS (klass)->pango_lock); +} + +static void +gst_time_overlay_init (GstTimeOverlay * overlay, GstTimeOverlayClass * klass) +{ + GstTextOverlay *textoverlay; + + textoverlay = GST_TEXT_OVERLAY (overlay); + + textoverlay->valign = GST_TEXT_OVERLAY_VALIGN_TOP; + textoverlay->halign = GST_TEXT_OVERLAY_HALIGN_LEFT; +} diff --git a/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.h b/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.h new file mode 100644 index 0000000..5fbfba9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/pango/gsttimeoverlay.h @@ -0,0 +1,61 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_TIME_OVERLAY_H__ +#define __GST_TIME_OVERLAY_H__ + +#include "gsttextoverlay.h" + +G_BEGIN_DECLS + +#define GST_TYPE_TIME_OVERLAY \ + (gst_time_overlay_get_type()) +#define GST_TIME_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TIME_OVERLAY,GstTimeOverlay)) +#define GST_TIME_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TIME_OVERLAY,GstTimeOverlayClass)) +#define GST_IS_TIME_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TIME_OVERLAY)) +#define GST_IS_TIME_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TIME_OVERLAY)) + +typedef struct _GstTimeOverlay GstTimeOverlay; +typedef struct _GstTimeOverlayClass GstTimeOverlayClass; + +/** + * GstTimeOverlay: + * + * Opaque timeoverlay data structure. + */ +struct _GstTimeOverlay { + GstTextOverlay textoverlay; +}; + +struct _GstTimeOverlayClass { + GstTextOverlayClass parent_class; +}; + +GType gst_time_overlay_get_type (void); + +G_END_DECLS + +#endif /* __GST_TIME_OVERLAY_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/theora/Makefile.am b/gst-plugins-base-subtitles0.10/ext/theora/Makefile.am new file mode 100644 index 0000000..c4a5eec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/Makefile.am @@ -0,0 +1,21 @@ +plugin_LTLIBRARIES = libgsttheora.la + +noinst_HEADERS = gsttheoraenc.h \ + gsttheoradec.h \ + gsttheoraparse.h + +libgsttheora_la_SOURCES = gsttheora.c \ + gsttheoraenc.c \ + gsttheoradec.c \ + gsttheoraparse.c + +libgsttheora_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(THEORA_CFLAGS) +libgsttheora_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(THEORA_LIBS) +libgsttheora_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgsttheora_la_LIBTOOLFLAGS = --tag=disable-static + diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheora.c b/gst-plugins-base-subtitles0.10/ext/theora/gsttheora.c new file mode 100644 index 0000000..37f3211 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheora.c @@ -0,0 +1,52 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +extern GType gst_theora_dec_get_type (void); +extern GType gst_theora_enc_get_type (void); +extern GType gst_theora_parse_get_type (void); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "theoradec", GST_RANK_PRIMARY, + gst_theora_dec_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "theoraenc", GST_RANK_PRIMARY, + gst_theora_enc_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "theoraparse", GST_RANK_NONE, + gst_theora_parse_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "theora", + "Theora plugin library", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.c b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.c new file mode 100644 index 0000000..96e12ee --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.c @@ -0,0 +1,1601 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-theoradec + * @see_also: theoraenc, oggdemux + * + * This element decodes theora streams into raw video + * Theora is a royalty-free + * video codec maintained by the Xiph.org + * Foundation, based on the VP3 codec. + * + * + * Example pipeline + * |[ + * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! xvimagesink + * ]| This example pipeline will decode an ogg stream and decodes the theora video. Refer to + * the theoraenc example to create the ogg file. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gsttheoradec.h" +#include +#include + +#define GST_CAT_DEFAULT theoradec_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define THEORA_DEF_CROP TRUE +#define THEORA_DEF_TELEMETRY_MV 0 +#define THEORA_DEF_TELEMETRY_MBMODE 0 +#define THEORA_DEF_TELEMETRY_QI 0 +#define THEORA_DEF_TELEMETRY_BITS 0 + +enum +{ + PROP_0, + PROP_CROP, + PROP_TELEMETRY_MV, + PROP_TELEMETRY_MBMODE, + PROP_TELEMETRY_QI, + PROP_TELEMETRY_BITS +}; + +static GstStaticPadTemplate theora_dec_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "format = (fourcc) { I420, Y42B, Y444 }, " + "framerate = (fraction) [0/1, MAX], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") + ); + +static GstStaticPadTemplate theora_dec_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-theora") + ); + +GST_BOILERPLATE (GstTheoraDec, gst_theora_dec, GstElement, GST_TYPE_ELEMENT); + +static void theora_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void theora_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static gboolean theora_dec_sink_event (GstPad * pad, GstEvent * event); +static gboolean theora_dec_setcaps (GstPad * pad, GstCaps * caps); +static GstFlowReturn theora_dec_chain (GstPad * pad, GstBuffer * buffer); +static GstStateChangeReturn theora_dec_change_state (GstElement * element, + GstStateChange transition); +static gboolean theora_dec_src_event (GstPad * pad, GstEvent * event); +static gboolean theora_dec_src_query (GstPad * pad, GstQuery * query); +static gboolean theora_dec_src_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); + +#if 0 +static const GstFormat *theora_get_formats (GstPad * pad); +#endif +#if 0 +static const GstEventMask *theora_get_event_masks (GstPad * pad); +#endif +static const GstQueryType *theora_get_query_types (GstPad * pad); + + +static void +gst_theora_dec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_dec_src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_dec_sink_factory)); + gst_element_class_set_details_simple (element_class, + "Theora video decoder", "Codec/Decoder/Video", + "decode raw theora streams to raw YUV video", + "Benjamin Otte , Wim Taymans "); +} + +static gboolean +gst_theora_dec_ctl_is_supported (int req) +{ + /* should return TH_EFAULT or TH_EINVAL if supported, and TH_EIMPL if not */ + return (th_decode_ctl (NULL, req, NULL, 0) != TH_EIMPL); +} + +static void +gst_theora_dec_class_init (GstTheoraDecClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = theora_dec_set_property; + gobject_class->get_property = theora_dec_get_property; + + g_object_class_install_property (gobject_class, PROP_CROP, + g_param_spec_boolean ("crop", "Crop", + "Crop the image to the visible region", THEORA_DEF_CROP, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + if (gst_theora_dec_ctl_is_supported (TH_DECCTL_SET_TELEMETRY_MV)) { + g_object_class_install_property (gobject_class, PROP_TELEMETRY_MV, + g_param_spec_int ("visualize-motion-vectors", + "Visualize motion vectors", + "Show motion vector selection overlaid on image. " + "Value gives a mask for motion vector (MV) modes to show", + 0, 0xffff, THEORA_DEF_TELEMETRY_MV, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } + + if (gst_theora_dec_ctl_is_supported (TH_DECCTL_SET_TELEMETRY_MBMODE)) { + g_object_class_install_property (gobject_class, PROP_TELEMETRY_MBMODE, + g_param_spec_int ("visualize-macroblock-modes", + "Visualize macroblock modes", + "Show macroblock mode selection overlaid on image. " + "Value gives a mask for macroblock (MB) modes to show", + 0, 0xffff, THEORA_DEF_TELEMETRY_MBMODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } + + if (gst_theora_dec_ctl_is_supported (TH_DECCTL_SET_TELEMETRY_QI)) { + g_object_class_install_property (gobject_class, PROP_TELEMETRY_QI, + g_param_spec_int ("visualize-quantization-modes", + "Visualize adaptive quantization modes", + "Show adaptive quantization mode selection overlaid on image. " + "Value gives a mask for quantization (QI) modes to show", + 0, 0xffff, THEORA_DEF_TELEMETRY_QI, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } + + if (gst_theora_dec_ctl_is_supported (TH_DECCTL_SET_TELEMETRY_BITS)) { + /* FIXME: make this a boolean instead? The value scales the bars so + * they're less wide. Default is to use full width, and anything else + * doesn't seem particularly useful, since the smaller bars just disappear + * then (they almost disappear for a value of 2 already). */ + g_object_class_install_property (gobject_class, PROP_TELEMETRY_BITS, + g_param_spec_int ("visualize-bit-usage", + "Visualize bitstream usage breakdown", + "Sets the bitstream breakdown visualization mode. " + "Values influence the width of the bit usage bars to show", + 0, 0xff, THEORA_DEF_TELEMETRY_BITS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } + + gstelement_class->change_state = theora_dec_change_state; + + GST_DEBUG_CATEGORY_INIT (theoradec_debug, "theoradec", 0, "Theora decoder"); +} + +static void +gst_theora_dec_init (GstTheoraDec * dec, GstTheoraDecClass * g_class) +{ + dec->sinkpad = + gst_pad_new_from_static_template (&theora_dec_sink_factory, "sink"); + gst_pad_set_event_function (dec->sinkpad, theora_dec_sink_event); + gst_pad_set_setcaps_function (dec->sinkpad, theora_dec_setcaps); + gst_pad_set_chain_function (dec->sinkpad, theora_dec_chain); + gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); + + dec->srcpad = + gst_pad_new_from_static_template (&theora_dec_src_factory, "src"); + gst_pad_set_event_function (dec->srcpad, theora_dec_src_event); + gst_pad_set_query_type_function (dec->srcpad, theora_get_query_types); + gst_pad_set_query_function (dec->srcpad, theora_dec_src_query); + gst_pad_use_fixed_caps (dec->srcpad); + + gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); + + dec->crop = THEORA_DEF_CROP; + dec->telemetry_mv = THEORA_DEF_TELEMETRY_MV; + dec->telemetry_mbmode = THEORA_DEF_TELEMETRY_MBMODE; + dec->telemetry_qi = THEORA_DEF_TELEMETRY_QI; + dec->telemetry_bits = THEORA_DEF_TELEMETRY_BITS; + dec->gather = NULL; + dec->decode = NULL; + dec->queued = NULL; + dec->pendingevents = NULL; +} + +static void +gst_theora_dec_reset (GstTheoraDec * dec) +{ + dec->need_keyframe = TRUE; + dec->last_timestamp = -1; + dec->discont = TRUE; + dec->frame_nr = -1; + dec->seqnum = gst_util_seqnum_next (); + dec->dropped = 0; + dec->processed = 0; + gst_segment_init (&dec->segment, GST_FORMAT_TIME); + + GST_OBJECT_LOCK (dec); + dec->proportion = 1.0; + dec->earliest_time = -1; + GST_OBJECT_UNLOCK (dec); + + g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->queued); + dec->queued = NULL; + g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->gather); + dec->gather = NULL; + g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->decode); + dec->decode = NULL; + g_list_foreach (dec->pendingevents, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->pendingevents); + dec->pendingevents = NULL; + + if (dec->tags) { + gst_tag_list_free (dec->tags); + dec->tags = NULL; + } +} + +#if 0 +static const GstFormat * +theora_get_formats (GstPad * pad) +{ + static GstFormat src_formats[] = { + GST_FORMAT_DEFAULT, /* frames in this case */ + GST_FORMAT_TIME, + GST_FORMAT_BYTES, + 0 + }; + static GstFormat sink_formats[] = { + GST_FORMAT_DEFAULT, + GST_FORMAT_TIME, + 0 + }; + + return (GST_PAD_IS_SRC (pad) ? src_formats : sink_formats); +} +#endif + +#if 0 +static const GstEventMask * +theora_get_event_masks (GstPad * pad) +{ + static const GstEventMask theora_src_event_masks[] = { + {GST_EVENT_SEEK, GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH}, + {0,} + }; + + return theora_src_event_masks; +} +#endif + +static const GstQueryType * +theora_get_query_types (GstPad * pad) +{ + static const GstQueryType theora_src_query_types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + GST_QUERY_CONVERT, + 0 + }; + + return theora_src_query_types; +} + + +static gboolean +theora_dec_src_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstTheoraDec *dec; + guint64 scale = 1; + + if (src_format == *dest_format) { + *dest_value = src_value; + return TRUE; + } + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + /* we need the info part before we can done something */ + if (!dec->have_header) + goto no_header; + + switch (src_format) { + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = gst_util_uint64_scale_int (src_value, 8, + dec->info.pic_height * dec->info.pic_width * dec->output_bpp); + break; + case GST_FORMAT_TIME: + /* seems like a rather silly conversion, implement me if you like */ + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = + dec->output_bpp * (dec->info.pic_width * dec->info.pic_height) / + 8; + case GST_FORMAT_DEFAULT: + *dest_value = scale * gst_util_uint64_scale (src_value, + dec->info.fps_numerator, dec->info.fps_denominator * GST_SECOND); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * dec->info.fps_denominator, dec->info.fps_numerator); + break; + case GST_FORMAT_BYTES: + *dest_value = gst_util_uint64_scale_int (src_value, + dec->output_bpp * dec->info.pic_width * dec->info.pic_height, 8); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } +done: + gst_object_unref (dec); + return res; + + /* ERRORS */ +no_header: + { + GST_DEBUG_OBJECT (dec, "no header yet, cannot convert"); + res = FALSE; + goto done; + } +} + +#if 0 +static gboolean +theora_dec_sink_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstTheoraDec *dec; + + if (src_format == *dest_format) { + *dest_value = src_value; + return TRUE; + } + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + /* we need the info part before we can done something */ + if (!dec->have_header) + goto no_header; + + switch (src_format) { + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = _theora_granule_start_time (dec, src_value); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + { + guint rest; + + /* framecount */ + *dest_value = gst_util_uint64_scale (src_value, + dec->info.fps_numerator, GST_SECOND * dec->info.fps_denominator); + + /* funny way of calculating granulepos in theora */ + rest = *dest_value / dec->info.keyframe_granule_shift; + *dest_value -= rest; + *dest_value <<= dec->granule_shift; + *dest_value += rest; + break; + } + default: + res = FALSE; + break; + } + break; + default: + res = FALSE; + } +done: + gst_object_unref (dec); + return res; + + /* ERRORS */ +no_header: + { + GST_DEBUG_OBJECT (dec, "no header yet, cannot convert"); + res = FALSE; + goto done; + } +} +#endif + +static gboolean +theora_dec_src_query (GstPad * pad, GstQuery * query) +{ + GstTheoraDec *dec; + + gboolean res = FALSE; + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 value; + GstFormat format; + gint64 time; + + /* parse format */ + gst_query_parse_position (query, &format, NULL); + + time = dec->last_timestamp; + time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time); + + GST_LOG_OBJECT (dec, + "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time)); + + if (!(res = + theora_dec_src_convert (pad, GST_FORMAT_TIME, time, &format, + &value))) + goto error; + + gst_query_set_position (query, format, value); + + GST_LOG_OBJECT (dec, + "query %p: we return %" G_GINT64_FORMAT " (format %u)", query, value, + format); + break; + } + case GST_QUERY_DURATION: + { + /* forward to peer for total */ + res = gst_pad_peer_query (dec->sinkpad, query); + if (!res) + goto error; + + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + theora_dec_src_convert (pad, src_fmt, src_val, &dest_fmt, + &dest_val))) + goto error; + + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (dec, "query failed"); + goto done; + } +} + +static gboolean +theora_dec_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstTheoraDec *dec; + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstFormat format, tformat; + gdouble rate; + GstEvent *real_seek; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + gint64 cur, stop; + gint64 tcur, tstop; + guint32 seqnum; + + gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, + &stop_type, &stop); + seqnum = gst_event_get_seqnum (event); + gst_event_unref (event); + + /* we have to ask our peer to seek to time here as we know + * nothing about how to generate a granulepos from the src + * formats or anything. + * + * First bring the requested format to time + */ + tformat = GST_FORMAT_TIME; + if (!(res = theora_dec_src_convert (pad, format, cur, &tformat, &tcur))) + goto convert_error; + if (!(res = theora_dec_src_convert (pad, format, stop, &tformat, &tstop))) + goto convert_error; + + /* then seek with time on the peer */ + real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, + flags, cur_type, tcur, stop_type, tstop); + gst_event_set_seqnum (real_seek, seqnum); + + res = gst_pad_push_event (dec->sinkpad, real_seek); + break; + } + case GST_EVENT_QOS: + { + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + + gst_event_parse_qos (event, &proportion, &diff, ×tamp); + + /* we cannot randomly skip frame decoding since we don't have + * B frames. we can however use the timestamp and diff to not + * push late frames. This would at least save us the time to + * crop/memcpy the data. */ + GST_OBJECT_LOCK (dec); + dec->proportion = proportion; + dec->earliest_time = timestamp + diff; + GST_OBJECT_UNLOCK (dec); + + GST_DEBUG_OBJECT (dec, "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT, + GST_TIME_ARGS (timestamp), diff); + + res = gst_pad_push_event (dec->sinkpad, event); + break; + } + default: + res = gst_pad_push_event (dec->sinkpad, event); + break; + } +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +convert_error: + { + GST_DEBUG_OBJECT (dec, "could not convert format"); + goto done; + } +} + +static gboolean +theora_dec_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstTheoraDec *dec; + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + GST_LOG_OBJECT (dec, "handling event"); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_theora_dec_reset (dec); + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_EOS: + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + /* we need TIME format */ + if (format != GST_FORMAT_TIME) + goto newseg_wrong_format; + + GST_DEBUG_OBJECT (dec, + "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, + update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (time)); + + /* now configure the values */ + gst_segment_set_newsegment_full (&dec->segment, update, + rate, arate, format, start, stop, time); + dec->seqnum = gst_event_get_seqnum (event); + + /* We don't forward this unless/until the decoder is initialised */ + if (dec->have_header) { + ret = gst_pad_push_event (dec->srcpad, event); + } else { + dec->pendingevents = g_list_append (dec->pendingevents, event); + ret = TRUE; + } + break; + } + case GST_EVENT_TAG: + { + if (dec->have_header) + /* and forward */ + ret = gst_pad_push_event (dec->srcpad, event); + else { + /* store it to send once we're initialized */ + dec->pendingevents = g_list_append (dec->pendingevents, event); + ret = TRUE; + } + break; + } + default: + ret = gst_pad_push_event (dec->srcpad, event); + break; + } +done: + gst_object_unref (dec); + + return ret; + + /* ERRORS */ +newseg_wrong_format: + { + GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); + gst_event_unref (event); + goto done; + } +} + +static gboolean +theora_dec_setcaps (GstPad * pad, GstCaps * caps) +{ + GstTheoraDec *dec; + GstStructure *s; + const GValue *codec_data; + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + s = gst_caps_get_structure (caps, 0); + + /* parse the par, this overrides the encoded par */ + dec->have_par = gst_structure_get_fraction (s, "pixel-aspect-ratio", + &dec->par_num, &dec->par_den); + + if ((codec_data = gst_structure_get_value (s, "codec_data"))) { + if (G_VALUE_TYPE (codec_data) == GST_TYPE_BUFFER) { + GstBuffer *buffer; + guint8 *data; + guint size; + guint offset; + + buffer = gst_value_get_buffer (codec_data); + + offset = 0; + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + while (size > 2) { + guint psize; + GstBuffer *buf; + + psize = (data[0] << 8) | data[1]; + /* skip header */ + data += 2; + size -= 2; + offset += 2; + + /* make sure we don't read too much */ + psize = MIN (psize, size); + + buf = gst_buffer_create_sub (buffer, offset, psize); + + /* first buffer is a discont buffer */ + if (offset == 2) + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + + /* now feed it to the decoder we can ignore the error */ + theora_dec_chain (pad, buf); + + /* skip the data */ + size -= psize; + data += psize; + offset += psize; + } + } + } + + gst_object_unref (dec); + + return TRUE; +} + +static GstFlowReturn +theora_handle_comment_packet (GstTheoraDec * dec, ogg_packet * packet) +{ + gchar *encoder = NULL; + GstBuffer *buf; + GstTagList *list; + + GST_DEBUG_OBJECT (dec, "parsing comment packet"); + + buf = gst_buffer_new (); + GST_BUFFER_SIZE (buf) = packet->bytes; + GST_BUFFER_DATA (buf) = packet->packet; + + list = + gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\201theora", 7, + &encoder); + + gst_buffer_unref (buf); + + if (!list) { + GST_ERROR_OBJECT (dec, "couldn't decode comments"); + list = gst_tag_list_new (); + } + if (encoder) { + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER, encoder, NULL); + g_free (encoder); + } + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER_VERSION, dec->info.version_major, + GST_TAG_VIDEO_CODEC, "Theora", NULL); + + if (dec->info.target_bitrate > 0) { + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, dec->info.target_bitrate, + GST_TAG_NOMINAL_BITRATE, dec->info.target_bitrate, NULL); + } + + dec->tags = list; + + return GST_FLOW_OK; +} + +static GstFlowReturn +theora_handle_type_packet (GstTheoraDec * dec, ogg_packet * packet) +{ + GstCaps *caps; + gint par_num, par_den; + GstFlowReturn ret = GST_FLOW_OK; + GList *walk; + guint32 fourcc; + + GST_DEBUG_OBJECT (dec, "fps %d/%d, PAR %d/%d", + dec->info.fps_numerator, dec->info.fps_denominator, + dec->info.aspect_numerator, dec->info.aspect_denominator); + + /* calculate par + * the info.aspect_* values reflect PAR; + * 0:x and x:0 are allowed and can be interpreted as 1:1. + */ + if (dec->have_par) { + /* we had a par on the sink caps, override the encoded par */ + GST_DEBUG_OBJECT (dec, "overriding with input PAR"); + par_num = dec->par_num; + par_den = dec->par_den; + } else { + /* take encoded par */ + par_num = dec->info.aspect_numerator; + par_den = dec->info.aspect_denominator; + } + if (par_num == 0 || par_den == 0) { + par_num = par_den = 1; + } + /* theora has: + * + * width/height : dimension of the encoded frame + * pic_width/pic_height : dimension of the visible part + * pic_x/pic_y : offset in encoded frame where visible part starts + */ + GST_DEBUG_OBJECT (dec, "dimension %dx%d, PAR %d/%d", dec->info.pic_width, + dec->info.pic_height, par_num, par_den); + GST_DEBUG_OBJECT (dec, "frame dimension %dx%d, offset %d:%d", + dec->info.pic_width, dec->info.pic_height, + dec->info.pic_x, dec->info.pic_y); + + if (dec->info.pixel_fmt == TH_PF_420) { + dec->output_bpp = 12; /* Average bits per pixel. */ + fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0'); + } else if (dec->info.pixel_fmt == TH_PF_422) { + dec->output_bpp = 16; + fourcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B'); + } else if (dec->info.pixel_fmt == TH_PF_444) { + dec->output_bpp = 24; + fourcc = GST_MAKE_FOURCC ('Y', '4', '4', '4'); + } else { + GST_ERROR_OBJECT (dec, "Invalid pixel format %d", dec->info.pixel_fmt); + return GST_FLOW_ERROR; + } + + if (dec->crop) { + dec->width = dec->info.pic_width; + dec->height = dec->info.pic_height; + dec->offset_x = dec->info.pic_x; + dec->offset_y = dec->info.pic_y; + /* Ensure correct offsets in chroma for formats that need it + * by rounding the offset. libtheora will add proper pixels, + * so no need to handle them ourselves. */ + if (dec->offset_x & 1 && dec->info.pixel_fmt != TH_PF_444) { + dec->offset_x--; + dec->width++; + } + if (dec->offset_y & 1 && dec->info.pixel_fmt == TH_PF_420) { + dec->offset_y--; + dec->height++; + } + } else { + /* no cropping, use the encoded dimensions */ + dec->width = dec->info.frame_width; + dec->height = dec->info.frame_height; + dec->offset_x = 0; + dec->offset_y = 0; + } + + GST_DEBUG_OBJECT (dec, "after fixup frame dimension %dx%d, offset %d:%d", + dec->width, dec->height, dec->offset_x, dec->offset_y); + + /* done */ + dec->decoder = th_decode_alloc (&dec->info, dec->setup); + + if (th_decode_ctl (dec->decoder, TH_DECCTL_SET_TELEMETRY_MV, + &dec->telemetry_mv, sizeof (dec->telemetry_mv)) != TH_EIMPL) { + GST_WARNING_OBJECT (dec, "Could not enable MV visualisation"); + } + if (th_decode_ctl (dec->decoder, TH_DECCTL_SET_TELEMETRY_MBMODE, + &dec->telemetry_mbmode, sizeof (dec->telemetry_mbmode)) != TH_EIMPL) { + GST_WARNING_OBJECT (dec, "Could not enable MB mode visualisation"); + } + if (th_decode_ctl (dec->decoder, TH_DECCTL_SET_TELEMETRY_QI, + &dec->telemetry_qi, sizeof (dec->telemetry_qi)) != TH_EIMPL) { + GST_WARNING_OBJECT (dec, "Could not enable QI mode visualisation"); + } + if (th_decode_ctl (dec->decoder, TH_DECCTL_SET_TELEMETRY_BITS, + &dec->telemetry_bits, sizeof (dec->telemetry_bits)) != TH_EIMPL) { + GST_WARNING_OBJECT (dec, "Could not enable BITS mode visualisation"); + } + + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, fourcc, + "framerate", GST_TYPE_FRACTION, + dec->info.fps_numerator, dec->info.fps_denominator, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_num, par_den, + "width", G_TYPE_INT, dec->width, "height", G_TYPE_INT, dec->height, + "color-matrix", G_TYPE_STRING, "sdtv", + "chroma-site", G_TYPE_STRING, "jpeg", NULL); + gst_pad_set_caps (dec->srcpad, caps); + gst_caps_unref (caps); + + dec->have_header = TRUE; + + if (dec->pendingevents) { + for (walk = dec->pendingevents; walk; walk = g_list_next (walk)) + gst_pad_push_event (dec->srcpad, GST_EVENT_CAST (walk->data)); + g_list_free (dec->pendingevents); + dec->pendingevents = NULL; + } + + if (dec->tags) { + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (dec), dec->srcpad, + dec->tags); + dec->tags = NULL; + } + + return ret; +} + +static GstFlowReturn +theora_handle_header_packet (GstTheoraDec * dec, ogg_packet * packet) +{ + GstFlowReturn res; + int ret; + + GST_DEBUG_OBJECT (dec, "parsing header packet"); + + ret = th_decode_headerin (&dec->info, &dec->comment, &dec->setup, packet); + if (ret < 0) + goto header_read_error; + + switch (packet->packet[0]) { + case 0x81: + res = theora_handle_comment_packet (dec, packet); + break; + case 0x82: + res = theora_handle_type_packet (dec, packet); + break; + default: + /* ignore */ + g_warning ("unknown theora header packet found"); + case 0x80: + /* nothing special, this is the identification header */ + res = GST_FLOW_OK; + break; + } + return res; + + /* ERRORS */ +header_read_error: + { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("couldn't read header packet")); + return GST_FLOW_ERROR; + } +} + +/* returns TRUE if buffer is within segment, else FALSE. + * if Buffer is on segment border, it's timestamp and duration will be clipped */ +static gboolean +clip_buffer (GstTheoraDec * dec, GstBuffer * buf) +{ + gboolean res = TRUE; + GstClockTime in_ts, in_dur, stop; + gint64 cstart, cstop; + + in_ts = GST_BUFFER_TIMESTAMP (buf); + in_dur = GST_BUFFER_DURATION (buf); + + GST_LOG_OBJECT (dec, + "timestamp:%" GST_TIME_FORMAT " , duration:%" GST_TIME_FORMAT, + GST_TIME_ARGS (in_ts), GST_TIME_ARGS (in_dur)); + + /* can't clip without TIME segment */ + if (dec->segment.format != GST_FORMAT_TIME) + goto beach; + + /* we need a start time */ + if (!GST_CLOCK_TIME_IS_VALID (in_ts)) + goto beach; + + /* generate valid stop, if duration unknown, we have unknown stop */ + stop = + GST_CLOCK_TIME_IS_VALID (in_dur) ? (in_ts + in_dur) : GST_CLOCK_TIME_NONE; + + /* now clip */ + if (!(res = gst_segment_clip (&dec->segment, GST_FORMAT_TIME, + in_ts, stop, &cstart, &cstop))) + goto beach; + + /* update timestamp and possibly duration if the clipped stop time is + * valid */ + GST_BUFFER_TIMESTAMP (buf) = cstart; + if (GST_CLOCK_TIME_IS_VALID (cstop)) + GST_BUFFER_DURATION (buf) = cstop - cstart; + +beach: + GST_LOG_OBJECT (dec, "%sdropping", (res ? "not " : "")); + return res; +} + +static GstFlowReturn +theora_dec_push_forward (GstTheoraDec * dec, GstBuffer * buf) +{ + GstFlowReturn result = GST_FLOW_OK; + + if (clip_buffer (dec, buf)) { + if (dec->discont) { + GST_LOG_OBJECT (dec, "setting DISCONT"); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + dec->discont = FALSE; + } + result = gst_pad_push (dec->srcpad, buf); + } else { + gst_buffer_unref (buf); + } + + return result; +} + +static GstFlowReturn +theora_dec_push_reverse (GstTheoraDec * dec, GstBuffer * buf) +{ + GstFlowReturn result = GST_FLOW_OK; + + dec->queued = g_list_prepend (dec->queued, buf); + + return result; +} + +/* Allocate buffer and copy image data into Y444 format */ +static GstFlowReturn +theora_handle_image (GstTheoraDec * dec, th_ycbcr_buffer buf, GstBuffer ** out) +{ + gint width, height, stride; + GstFlowReturn result; + int i, plane; + GstVideoFormat format; + guint8 *dest, *src; + + switch (dec->info.pixel_fmt) { + case TH_PF_444: + format = GST_VIDEO_FORMAT_Y444; + break; + case TH_PF_420: + format = GST_VIDEO_FORMAT_I420; + break; + case TH_PF_422: + format = GST_VIDEO_FORMAT_Y42B; + break; + default: + g_assert_not_reached (); + } + + result = + gst_pad_alloc_buffer_and_set_caps (dec->srcpad, GST_BUFFER_OFFSET_NONE, + gst_video_format_get_size (format, dec->width, dec->height), + GST_PAD_CAPS (dec->srcpad), out); + if (G_UNLIKELY (result != GST_FLOW_OK)) { + GST_DEBUG_OBJECT (dec, "could not get buffer, reason: %s", + gst_flow_get_name (result)); + return result; + } + + for (plane = 0; plane < 3; plane++) { + width = gst_video_format_get_component_width (format, plane, dec->width); + height = gst_video_format_get_component_height (format, plane, dec->height); + stride = gst_video_format_get_row_stride (format, plane, dec->width); + + dest = + GST_BUFFER_DATA (*out) + gst_video_format_get_component_offset (format, + plane, dec->width, dec->height); + src = buf[plane].data; + src += ((height == dec->height) ? dec->offset_y : dec->offset_y / 2) + * buf[plane].stride; + src += (width == dec->width) ? dec->offset_x : dec->offset_x / 2; + + for (i = 0; i < height; i++) { + memcpy (dest, src, width); + + dest += stride; + src += buf[plane].stride; + } + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +theora_handle_data_packet (GstTheoraDec * dec, ogg_packet * packet, + GstClockTime outtime, GstClockTime outdur) +{ + /* normal data packet */ + th_ycbcr_buffer buf; + GstBuffer *out; + gboolean keyframe; + GstFlowReturn result; + ogg_int64_t gp; + + if (G_UNLIKELY (!dec->have_header)) + goto not_initialized; + + /* get timestamp and durations */ + if (outtime == -1) + outtime = dec->last_timestamp; + if (outdur == -1) + outdur = gst_util_uint64_scale_int (GST_SECOND, dec->info.fps_denominator, + dec->info.fps_numerator); + + /* calculate expected next timestamp */ + if (outtime != -1 && outdur != -1) + dec->last_timestamp = outtime + outdur; + + /* the second most significant bit of the first data byte is cleared + * for keyframes. We can only check it if it's not a zero-length packet. */ + keyframe = packet->bytes && ((packet->packet[0] & 0x40) == 0); + if (G_UNLIKELY (keyframe)) { + GST_DEBUG_OBJECT (dec, "we have a keyframe"); + dec->need_keyframe = FALSE; + } else if (G_UNLIKELY (dec->need_keyframe)) { + goto dropping; + } + + GST_DEBUG_OBJECT (dec, "parsing data packet"); + + /* this does the decoding */ + if (G_UNLIKELY (th_decode_packetin (dec->decoder, packet, &gp) < 0)) + goto decode_error; + + if (outtime != -1) { + gboolean need_skip; + GstClockTime running_time; + GstClockTime earliest_time; + gdouble proportion; + + /* qos needs to be done on running time */ + running_time = gst_segment_to_running_time (&dec->segment, GST_FORMAT_TIME, + outtime); + + GST_OBJECT_LOCK (dec); + proportion = dec->proportion; + earliest_time = dec->earliest_time; + /* check for QoS, don't perform the last steps of getting and + * pushing the buffers that are known to be late. */ + need_skip = earliest_time != -1 && running_time <= earliest_time; + GST_OBJECT_UNLOCK (dec); + + if (need_skip) { + GstMessage *qos_msg; + guint64 stream_time; + gint64 jitter; + + GST_DEBUG_OBJECT (dec, "skipping decoding: qostime %" + GST_TIME_FORMAT " <= %" GST_TIME_FORMAT, + GST_TIME_ARGS (running_time), GST_TIME_ARGS (earliest_time)); + + dec->dropped++; + + stream_time = + gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, outtime); + jitter = GST_CLOCK_DIFF (running_time, earliest_time); + + qos_msg = + gst_message_new_qos (GST_OBJECT_CAST (dec), FALSE, running_time, + stream_time, outtime, outdur); + gst_message_set_qos_values (qos_msg, jitter, proportion, 1000000); + gst_message_set_qos_stats (qos_msg, GST_FORMAT_BUFFERS, + dec->processed, dec->dropped); + gst_element_post_message (GST_ELEMENT_CAST (dec), qos_msg); + + goto dropping_qos; + } + } + + /* this does postprocessing and set up the decoded frame + * pointers in our yuv variable */ + if (G_UNLIKELY (th_decode_ycbcr_out (dec->decoder, buf) < 0)) + goto no_yuv; + + if (G_UNLIKELY ((buf[0].width != dec->info.frame_width) + || (buf[0].height != dec->info.frame_height))) + goto wrong_dimensions; + + result = theora_handle_image (dec, buf, &out); + if (result != GST_FLOW_OK) + return result; + + GST_BUFFER_OFFSET (out) = dec->frame_nr; + if (dec->frame_nr != -1) + dec->frame_nr++; + GST_BUFFER_OFFSET_END (out) = dec->frame_nr; + + GST_BUFFER_TIMESTAMP (out) = outtime; + GST_BUFFER_DURATION (out) = outdur; + + dec->processed++; + + if (dec->segment.rate >= 0.0) + result = theora_dec_push_forward (dec, out); + else + result = theora_dec_push_reverse (dec, out); + + return result; + + /* ERRORS */ +not_initialized: + { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("no header sent yet")); + return GST_FLOW_ERROR; + } +dropping: + { + GST_WARNING_OBJECT (dec, "dropping frame because we need a keyframe"); + dec->discont = TRUE; + return GST_FLOW_OK; + } +dropping_qos: + { + if (dec->frame_nr != -1) + dec->frame_nr++; + dec->discont = TRUE; + GST_WARNING_OBJECT (dec, "dropping frame because of QoS"); + return GST_FLOW_OK; + } +decode_error: + { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("theora decoder did not decode data packet")); + return GST_FLOW_ERROR; + } +no_yuv: + { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, DECODE, + (NULL), ("couldn't read out YUV image")); + return GST_FLOW_ERROR; + } +wrong_dimensions: + { + GST_ELEMENT_ERROR (GST_ELEMENT (dec), STREAM, FORMAT, + (NULL), ("dimensions of image do not match header")); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +theora_dec_decode_buffer (GstTheoraDec * dec, GstBuffer * buf) +{ + ogg_packet packet; + GstFlowReturn result = GST_FLOW_OK; + GstClockTime timestamp, duration; + + /* make ogg_packet out of the buffer */ + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = -1; + packet.packetno = 0; /* we don't really care */ + packet.b_o_s = dec->have_header ? 0 : 1; + /* EOS does not matter for the decoder */ + packet.e_o_s = 0; + + GST_LOG_OBJECT (dec, "decode buffer of size %ld", packet.bytes); + + /* save last seem timestamp for interpolating the next timestamps using the + * framerate when we need to */ + timestamp = GST_BUFFER_TIMESTAMP (buf); + duration = GST_BUFFER_DURATION (buf); + + GST_DEBUG_OBJECT (dec, "header=%02x, outtime=%" GST_TIME_FORMAT, + packet.bytes ? packet.packet[0] : -1, GST_TIME_ARGS (timestamp)); + + /* switch depending on packet type. A zero byte packet is always a data + * packet; we don't dereference it in that case. */ + if (packet.bytes && packet.packet[0] & 0x80) { + if (dec->have_header) { + GST_WARNING_OBJECT (GST_OBJECT (dec), "Ignoring header"); + goto done; + } + result = theora_handle_header_packet (dec, &packet); + } else { + result = theora_handle_data_packet (dec, &packet, timestamp, duration); + } + +done: + return result; +} + +/* For reverse playback we use a technique that can be used for + * any keyframe based video codec. + * + * Input: + * Buffer decoding order: 7 8 9 4 5 6 1 2 3 EOS + * Keyframe flag: K K + * Discont flag: D D D + * + * - Each Discont marks a discont in the decoding order. + * - The keyframes mark where we can start decoding. + * + * First we prepend incomming buffers to the gather queue, whenever we receive + * a discont, we flush out the gather queue. + * + * The above data will be accumulated in the gather queue like this: + * + * gather queue: 9 8 7 + * D + * + * Whe buffer 4 is received (with a DISCONT), we flush the gather queue like + * this: + * + * while (gather) + * take head of queue and prepend to decode queue. + * if we copied a keyframe, decode the decode queue. + * + * After we flushed the gather queue, we add 4 to the (now empty) gather queue. + * We get the following situation: + * + * gather queue: 4 + * decode queue: 7 8 9 + * + * After we received 5 (Keyframe) and 6: + * + * gather queue: 6 5 4 + * decode queue: 7 8 9 + * + * When we receive 1 (DISCONT) which triggers a flush of the gather queue: + * + * Copy head of the gather queue (6) to decode queue: + * + * gather queue: 5 4 + * decode queue: 6 7 8 9 + * + * Copy head of the gather queue (5) to decode queue. This is a keyframe so we + * can start decoding. + * + * gather queue: 4 + * decode queue: 5 6 7 8 9 + * + * Decode frames in decode queue, store raw decoded data in output queue, we + * can take the head of the decode queue and prepend the decoded result in the + * output queue: + * + * gather queue: 4 + * decode queue: + * output queue: 9 8 7 6 5 + * + * Now output all the frames in the output queue, picking a frame from the + * head of the queue. + * + * Copy head of the gather queue (4) to decode queue, we flushed the gather + * queue and can now store input buffer in the gather queue: + * + * gather queue: 1 + * decode queue: 4 + * + * When we receive EOS, the queue looks like: + * + * gather queue: 3 2 1 + * decode queue: 4 + * + * Fill decode queue, first keyframe we copy is 2: + * + * gather queue: 1 + * decode queue: 2 3 4 + * + * Decoded output: + * + * gather queue: 1 + * decode queue: + * output queue: 4 3 2 + * + * Leftover buffer 1 cannot be decoded and must be discarded. + */ +static GstFlowReturn +theora_dec_flush_decode (GstTheoraDec * dec) +{ + GstFlowReturn res = GST_FLOW_OK; + + while (dec->decode) { + GstBuffer *buf = GST_BUFFER_CAST (dec->decode->data); + + GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT, + buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + /* decode buffer, prepend to output queue */ + res = theora_dec_decode_buffer (dec, buf); + + /* don't need it anymore now */ + gst_buffer_unref (buf); + + dec->decode = g_list_delete_link (dec->decode, dec->decode); + } + while (dec->queued) { + GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data); + + /* iterate ouput queue an push downstream */ + res = gst_pad_push (dec->srcpad, buf); + + dec->queued = g_list_delete_link (dec->queued, dec->queued); + } + + return res; +} + +static GstFlowReturn +theora_dec_chain_reverse (GstTheoraDec * dec, gboolean discont, GstBuffer * buf) +{ + GstFlowReturn res = GST_FLOW_OK; + + /* if we have a discont, move buffers to the decode list */ + if (G_UNLIKELY (discont)) { + GST_DEBUG_OBJECT (dec, "received discont,gathering buffers"); + while (dec->gather) { + GstBuffer *gbuf; + guint8 *data; + + gbuf = GST_BUFFER_CAST (dec->gather->data); + /* remove from the gather list */ + dec->gather = g_list_delete_link (dec->gather, dec->gather); + /* copy to decode queue */ + dec->decode = g_list_prepend (dec->decode, gbuf); + + /* if we copied a keyframe, flush and decode the decode queue */ + data = GST_BUFFER_DATA (gbuf); + if ((data[0] & 0x40) == 0) { + GST_DEBUG_OBJECT (dec, "copied keyframe"); + res = theora_dec_flush_decode (dec); + } + } + } + + /* add buffer to gather queue */ + GST_DEBUG_OBJECT (dec, "gathering buffer %p, size %u", buf, + GST_BUFFER_SIZE (buf)); + dec->gather = g_list_prepend (dec->gather, buf); + + return res; +} + +static GstFlowReturn +theora_dec_chain_forward (GstTheoraDec * dec, gboolean discont, + GstBuffer * buffer) +{ + GstFlowReturn result; + + result = theora_dec_decode_buffer (dec, buffer); + + gst_buffer_unref (buffer); + + return result; +} + +static GstFlowReturn +theora_dec_chain (GstPad * pad, GstBuffer * buf) +{ + GstTheoraDec *dec; + GstFlowReturn res; + gboolean discont; + + dec = GST_THEORA_DEC (gst_pad_get_parent (pad)); + + /* peel of DISCONT flag */ + discont = GST_BUFFER_IS_DISCONT (buf); + + /* resync on DISCONT */ + if (G_UNLIKELY (discont)) { + GST_DEBUG_OBJECT (dec, "received DISCONT buffer"); + dec->need_keyframe = TRUE; + dec->last_timestamp = -1; + dec->discont = TRUE; + } + + if (dec->segment.rate > 0.0) + res = theora_dec_chain_forward (dec, discont, buf); + else + res = theora_dec_chain_reverse (dec, discont, buf); + + gst_object_unref (dec); + + return res; +} + +static GstStateChangeReturn +theora_dec_change_state (GstElement * element, GstStateChange transition) +{ + GstTheoraDec *dec = GST_THEORA_DEC (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + th_info_clear (&dec->info); + th_comment_clear (&dec->comment); + GST_DEBUG_OBJECT (dec, "Setting have_header to FALSE in READY->PAUSED"); + dec->have_header = FALSE; + dec->have_par = FALSE; + gst_theora_dec_reset (dec); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + th_info_clear (&dec->info); + th_comment_clear (&dec->comment); + th_setup_free (dec->setup); + dec->setup = NULL; + th_decode_free (dec->decoder); + dec->decoder = NULL; + gst_theora_dec_reset (dec); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static void +theora_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTheoraDec *dec = GST_THEORA_DEC (object); + + switch (prop_id) { + case PROP_CROP: + dec->crop = g_value_get_boolean (value); + break; + case PROP_TELEMETRY_MV: + dec->telemetry_mv = g_value_get_int (value); + break; + case PROP_TELEMETRY_MBMODE: + dec->telemetry_mbmode = g_value_get_int (value); + break; + case PROP_TELEMETRY_QI: + dec->telemetry_qi = g_value_get_int (value); + break; + case PROP_TELEMETRY_BITS: + dec->telemetry_bits = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +theora_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTheoraDec *dec = GST_THEORA_DEC (object); + + switch (prop_id) { + case PROP_CROP: + g_value_set_boolean (value, dec->crop); + break; + case PROP_TELEMETRY_MV: + g_value_set_int (value, dec->telemetry_mv); + break; + case PROP_TELEMETRY_MBMODE: + g_value_set_int (value, dec->telemetry_mbmode); + break; + case PROP_TELEMETRY_QI: + g_value_set_int (value, dec->telemetry_qi); + break; + case PROP_TELEMETRY_BITS: + g_value_set_int (value, dec->telemetry_bits); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.h b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.h new file mode 100644 index 0000000..f672211 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoradec.h @@ -0,0 +1,120 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_THEORADEC_H__ +#define __GST_THEORADEC_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_THEORA_DEC \ + (gst_theora_dec_get_type()) +#define GST_THEORA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_DEC,GstTheoraDec)) +#define GST_THEORA_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_DEC,GstTheoraDecClass)) +#define GST_IS_THEORA_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_DEC)) +#define GST_IS_THEORA_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_DEC)) + +typedef struct _GstTheoraDec GstTheoraDec; +typedef struct _GstTheoraDecClass GstTheoraDecClass; + +/** + * GstTheoraDec: + * + * Opaque object data structure. + */ +struct _GstTheoraDec +{ + GstElement element; + + /* Pads */ + GstPad *sinkpad; + GstPad *srcpad; + + /* theora decoder state */ + th_dec_ctx *decoder; + //theora_state state; + th_setup_info *setup; + th_info info; + th_comment comment; + + gboolean have_header; + + GstClockTime last_timestamp; + guint64 frame_nr; + gboolean need_keyframe; + gint width, height; + gint offset_x, offset_y; + gint output_bpp; + + /* telemetry debuging options */ + gint telemetry_mv; + gint telemetry_mbmode; + gint telemetry_qi; + gint telemetry_bits; + + gboolean crop; + + /* list of buffers that need timestamps */ + GList *queued; + /* list of raw output buffers */ + GList *output; + /* gather/decode queues for reverse playback */ + GList *gather; + GList *decode; + GList *pendingevents; + + GstTagList *tags; + + /* segment info */ /* with STREAM_LOCK */ + GstSegment segment; + gboolean discont; + guint32 seqnum; + + /* QoS stuff */ /* with LOCK*/ + gdouble proportion; + GstClockTime earliest_time; + guint64 processed; + guint64 dropped; + + gboolean have_par; + gint par_num; + gint par_den; +}; + +struct _GstTheoraDecClass +{ + GstElementClass parent_class; +}; + +GType gst_theora_dec_get_type (void); + +G_END_DECLS + +#endif /* __GST_THEORADEC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.c b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.c new file mode 100644 index 0000000..c580675 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.c @@ -0,0 +1,1565 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-theoraenc + * @see_also: theoradec, oggmux + * + * This element encodes raw video into a Theora stream. + * Theora is a royalty-free + * video codec maintained by the Xiph.org + * Foundation, based on the VP3 codec. + * + * The theora codec internally only supports encoding of images that are a + * multiple of 16 pixels in both X and Y direction. It is however perfectly + * possible to encode images with other dimensions because an arbitrary + * rectangular cropping region can be set up. This element will automatically + * set up a correct cropping region if the dimensions are not multiples of 16 + * pixels. + * + * To control the quality of the encoding, the #GstTheoraEnc::bitrate and + * #GstTheoraEnc::quality properties can be used. These two properties are + * mutualy exclusive. Setting the bitrate property will produce a constant + * bitrate (CBR) stream while setting the quality property will produce a + * variable bitrate (VBR) stream. + * + * + * Example pipeline + * |[ + * gst-launch -v videotestsrc num-buffers=1000 ! theoraenc ! oggmux ! filesink location=videotestsrc.ogg + * ]| This example pipeline will encode a test video source to theora muxed in an + * ogg container. Refer to the theoradec documentation to decode the create + * stream. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gsttheoraenc.h" + +#include +#include /* free */ + +#include +#include + +#define GST_CAT_DEFAULT theoraenc_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +#define GST_TYPE_BORDER_MODE (gst_border_mode_get_type()) +static GType +gst_border_mode_get_type (void) +{ + static GType border_mode_type = 0; + static const GEnumValue border_mode[] = { + {BORDER_NONE, "No Border", "none"}, + {BORDER_BLACK, "Black Border", "black"}, + {BORDER_MIRROR, "Mirror image in borders", "mirror"}, + {0, NULL, NULL}, + }; + + if (!border_mode_type) { + border_mode_type = + g_enum_register_static ("GstTheoraEncBorderMode", border_mode); + } + return border_mode_type; +} + +#define GST_TYPE_MULTIPASS_MODE (gst_multipass_mode_get_type()) +static GType +gst_multipass_mode_get_type (void) +{ + static GType multipass_mode_type = 0; + static const GEnumValue multipass_mode[] = { + {MULTIPASS_MODE_SINGLE_PASS, "Single pass", "single-pass"}, + {MULTIPASS_MODE_FIRST_PASS, "First pass", "first-pass"}, + {MULTIPASS_MODE_SECOND_PASS, "Second pass", "second-pass"}, + {0, NULL, NULL}, + }; + + if (!multipass_mode_type) { + multipass_mode_type = + g_enum_register_static ("GstTheoraEncMultipassMode", multipass_mode); + } + return multipass_mode_type; +} + +/* taken from theora/lib/toplevel.c */ +static int +_ilog (unsigned int v) +{ + int ret = 0; + + while (v) { + ret++; + v >>= 1; + } + return (ret); +} + +#define THEORA_DEF_BITRATE 0 +#define THEORA_DEF_QUALITY 48 +#define THEORA_DEF_KEYFRAME_AUTO TRUE +#define THEORA_DEF_KEYFRAME_FREQ 64 +#define THEORA_DEF_KEYFRAME_FREQ_FORCE 64 +#define THEORA_DEF_SPEEDLEVEL 1 +#define THEORA_DEF_VP3_COMPATIBLE FALSE +#define THEORA_DEF_DROP_FRAMES TRUE +#define THEORA_DEF_CAP_OVERFLOW TRUE +#define THEORA_DEF_CAP_UNDERFLOW FALSE +#define THEORA_DEF_RATE_BUFFER 0 +#define THEORA_DEF_MULTIPASS_CACHE_FILE NULL +#define THEORA_DEF_MULTIPASS_MODE MULTIPASS_MODE_SINGLE_PASS +enum +{ + PROP_0, + PROP_CENTER, + PROP_BORDER, + PROP_BITRATE, + PROP_QUALITY, + PROP_QUICK, + PROP_KEYFRAME_AUTO, + PROP_KEYFRAME_FREQ, + PROP_KEYFRAME_FREQ_FORCE, + PROP_KEYFRAME_THRESHOLD, + PROP_KEYFRAME_MINDISTANCE, + PROP_NOISE_SENSITIVITY, + PROP_SHARPNESS, + PROP_SPEEDLEVEL, + PROP_VP3_COMPATIBLE, + PROP_DROP_FRAMES, + PROP_CAP_OVERFLOW, + PROP_CAP_UNDERFLOW, + PROP_RATE_BUFFER, + PROP_MULTIPASS_CACHE_FILE, + PROP_MULTIPASS_MODE + /* FILL ME */ +}; + +/* this function does a straight granulepos -> timestamp conversion */ +static GstClockTime +granulepos_to_timestamp (GstTheoraEnc * theoraenc, ogg_int64_t granulepos) +{ + guint64 iframe, pframe; + int shift = theoraenc->info.keyframe_granule_shift; + + if (granulepos < 0) + return GST_CLOCK_TIME_NONE; + + iframe = granulepos >> shift; + pframe = granulepos - (iframe << shift); + + /* num and den are 32 bit, so we can safely multiply with GST_SECOND */ + return gst_util_uint64_scale ((guint64) (iframe + pframe), + GST_SECOND * theoraenc->info.fps_denominator, + theoraenc->info.fps_numerator); +} + +/* Generate a dummy encoder context for use in th_encode_ctl queries + Release with th_encode_free() + This and the next routine from theora/examples/libtheora_info.c */ +static th_enc_ctx * +dummy_encode_ctx (void) +{ + th_enc_ctx *ctx; + th_info info; + + /* set the minimal video parameters */ + th_info_init (&info); + info.frame_width = 320; + info.frame_height = 240; + info.fps_numerator = 1; + info.fps_denominator = 1; + + /* allocate and initialize a context object */ + ctx = th_encode_alloc (&info); + if (!ctx) + GST_WARNING ("Failed to allocate dummy encoder context."); + + /* clear the info struct */ + th_info_clear (&info); + + return ctx; +} + +/* Query the current and maximum values for the 'speed level' setting. + This can be used to ask the encoder to trade off encoding quality + vs. performance cost, for example to adapt to realtime constraints. */ +static int +check_speed_level (th_enc_ctx * ctx, int *current, int *max) +{ + int ret; + + /* query the current speed level */ + ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL, current, sizeof (int)); + if (ret) { + GST_WARNING ("Error %d getting current speed level.", ret); + return ret; + } + /* query the maximum speed level, which varies by encoder version */ + ret = th_encode_ctl (ctx, TH_ENCCTL_GET_SPLEVEL_MAX, max, sizeof (int)); + if (ret) { + GST_WARNING ("Error %d getting maximum speed level.", ret); + return ret; + } + + return 0; +} + +static GstStaticPadTemplate theora_enc_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "format = (fourcc) { I420, Y42B, Y444 }, " + "framerate = (fraction) [1/MAX, MAX], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") + ); + +static GstStaticPadTemplate theora_enc_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-theora") + ); + +static void +_do_init (GType object_type) +{ + const GInterfaceInfo preset_interface_info = { + NULL, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + g_type_add_interface_static (object_type, GST_TYPE_PRESET, + &preset_interface_info); +} + +GST_BOILERPLATE_FULL (GstTheoraEnc, gst_theora_enc, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static gboolean theora_enc_sink_event (GstPad * pad, GstEvent * event); +static gboolean theora_enc_src_event (GstPad * pad, GstEvent * event); +static GstFlowReturn theora_enc_chain (GstPad * pad, GstBuffer * buffer); +static GstStateChangeReturn theora_enc_change_state (GstElement * element, + GstStateChange transition); +static GstCaps *theora_enc_sink_getcaps (GstPad * pad); +static gboolean theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps); +static void theora_enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void theora_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void theora_enc_finalize (GObject * object); + +static gboolean theora_enc_write_multipass_cache (GstTheoraEnc * enc, + gboolean begin, gboolean eos); + +static void +gst_theora_enc_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_enc_src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_enc_sink_factory)); + gst_element_class_set_details_simple (element_class, + "Theora video encoder", "Codec/Encoder/Video", + "encode raw YUV video to a theora stream", + "Wim Taymans "); +} + +static void +gst_theora_enc_class_init (GstTheoraEncClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + /* query runtime encoder properties */ + th_enc_ctx *th_ctx; + int default_speed_level = THEORA_DEF_SPEEDLEVEL; + int max_speed_level = default_speed_level; + + GST_DEBUG_CATEGORY_INIT (theoraenc_debug, "theoraenc", 0, "Theora encoder"); + + th_ctx = dummy_encode_ctx (); + if (th_ctx) { + if (!check_speed_level (th_ctx, &default_speed_level, &max_speed_level)) + GST_WARNING + ("Failed to determine settings for the speed-level property."); + th_encode_free (th_ctx); + } + + gobject_class->set_property = theora_enc_set_property; + gobject_class->get_property = theora_enc_get_property; + gobject_class->finalize = theora_enc_finalize; + + g_object_class_install_property (gobject_class, PROP_CENTER, + g_param_spec_boolean ("center", "Center", + "ignored and kept for API compat only", TRUE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BORDER, + g_param_spec_enum ("border", "Border", + "ignored and kept for API compat only", + GST_TYPE_BORDER_MODE, BORDER_BLACK, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* general encoding stream options */ + g_object_class_install_property (gobject_class, PROP_BITRATE, + g_param_spec_int ("bitrate", "Bitrate", "Compressed video bitrate (kbps)", + 0, (1 << 24) - 1, THEORA_DEF_BITRATE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); + g_object_class_install_property (gobject_class, PROP_QUALITY, + g_param_spec_int ("quality", "Quality", "Video quality", 0, 63, + THEORA_DEF_QUALITY, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | + GST_PARAM_MUTABLE_PLAYING)); + g_object_class_install_property (gobject_class, PROP_QUICK, + g_param_spec_boolean ("quick", "Quick", + "ignored and kept for API compat only", TRUE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KEYFRAME_AUTO, + g_param_spec_boolean ("keyframe-auto", "Keyframe Auto", + "Automatic keyframe detection", THEORA_DEF_KEYFRAME_AUTO, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ, + g_param_spec_int ("keyframe-freq", "Keyframe frequency", + "Keyframe frequency", 1, 32768, THEORA_DEF_KEYFRAME_FREQ, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KEYFRAME_FREQ_FORCE, + g_param_spec_int ("keyframe-force", "Keyframe force", + "Force keyframe every N frames", 1, 32768, + THEORA_DEF_KEYFRAME_FREQ_FORCE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KEYFRAME_THRESHOLD, + g_param_spec_int ("keyframe-threshold", "Keyframe threshold", + "ignored and kept for API compat only", 0, 32768, 80, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KEYFRAME_MINDISTANCE, + g_param_spec_int ("keyframe-mindistance", "Keyframe mindistance", + "ignored and kept for API compat only", 1, 32768, 8, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_NOISE_SENSITIVITY, + g_param_spec_int ("noise-sensitivity", "Noise sensitivity", + "ignored and kept for API compat only", 0, 32768, 1, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SHARPNESS, + g_param_spec_int ("sharpness", "Sharpness", + "ignored and kept for API compat only", 0, 2, 0, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SPEEDLEVEL, + g_param_spec_int ("speed-level", "Speed level", + "Controls the amount of analysis performed when encoding." + " Higher values trade compression quality for speed." + " This property requires libtheora version >= 1.0" + ", and the maximum value may vary based on encoder version.", + 0, max_speed_level, default_speed_level, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_VP3_COMPATIBLE, + g_param_spec_boolean ("vp3-compatible", "VP3 Compatible", + "Disables non-VP3 compatible features", + THEORA_DEF_VP3_COMPATIBLE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DROP_FRAMES, + g_param_spec_boolean ("drop-frames", "VP3 Compatible", + "Allow or disallow frame dropping", + THEORA_DEF_DROP_FRAMES, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAP_OVERFLOW, + g_param_spec_boolean ("cap-overflow", "VP3 Compatible", + "Enable capping of bit reservoir overflows", + THEORA_DEF_CAP_OVERFLOW, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAP_UNDERFLOW, + g_param_spec_boolean ("cap-underflow", "VP3 Compatible", + "Enable capping of bit reservoir underflows", + THEORA_DEF_CAP_UNDERFLOW, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_RATE_BUFFER, + g_param_spec_int ("rate-buffer", "Rate Control Buffer", + "Sets the size of the rate control buffer, in units of frames. " + "The default value of 0 instructs the encoder to automatically " + "select an appropriate value", + 0, 1000, THEORA_DEF_RATE_BUFFER, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MULTIPASS_CACHE_FILE, + g_param_spec_string ("multipass-cache-file", "Multipass Cache File", + "Multipass cache file", THEORA_DEF_MULTIPASS_CACHE_FILE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MULTIPASS_MODE, + g_param_spec_enum ("multipass-mode", "Multipass mode", + "Single pass or first/second pass", GST_TYPE_MULTIPASS_MODE, + THEORA_DEF_MULTIPASS_MODE, + (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = theora_enc_change_state; +} + +static void +gst_theora_enc_init (GstTheoraEnc * enc, GstTheoraEncClass * g_class) +{ + enc->sinkpad = + gst_pad_new_from_static_template (&theora_enc_sink_factory, "sink"); + gst_pad_set_chain_function (enc->sinkpad, theora_enc_chain); + gst_pad_set_event_function (enc->sinkpad, theora_enc_sink_event); + gst_pad_set_getcaps_function (enc->sinkpad, theora_enc_sink_getcaps); + gst_pad_set_setcaps_function (enc->sinkpad, theora_enc_sink_setcaps); + gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); + + enc->srcpad = + gst_pad_new_from_static_template (&theora_enc_src_factory, "src"); + gst_pad_set_event_function (enc->srcpad, theora_enc_src_event); + gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad); + + gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED); + + enc->video_bitrate = THEORA_DEF_BITRATE; + enc->video_quality = THEORA_DEF_QUALITY; + enc->keyframe_auto = THEORA_DEF_KEYFRAME_AUTO; + enc->keyframe_freq = THEORA_DEF_KEYFRAME_FREQ; + enc->keyframe_force = THEORA_DEF_KEYFRAME_FREQ_FORCE; + + enc->expected_ts = GST_CLOCK_TIME_NONE; + + /* enc->speed_level is set to the libtheora default by the constructor */ + enc->vp3_compatible = THEORA_DEF_VP3_COMPATIBLE; + enc->drop_frames = THEORA_DEF_DROP_FRAMES; + enc->cap_overflow = THEORA_DEF_CAP_OVERFLOW; + enc->cap_underflow = THEORA_DEF_CAP_UNDERFLOW; + enc->rate_buffer = THEORA_DEF_RATE_BUFFER; + + enc->multipass_mode = THEORA_DEF_MULTIPASS_MODE; + enc->multipass_cache_file = THEORA_DEF_MULTIPASS_CACHE_FILE; +} + +static void +theora_enc_clear_multipass_cache (GstTheoraEnc * enc) +{ + if (enc->multipass_cache_fd) { + g_io_channel_shutdown (enc->multipass_cache_fd, TRUE, NULL); + g_io_channel_unref (enc->multipass_cache_fd); + enc->multipass_cache_fd = NULL; + } + + if (enc->multipass_cache_adapter) { + gst_object_unref (enc->multipass_cache_adapter); + enc->multipass_cache_adapter = NULL; + } +} + +static void +theora_enc_finalize (GObject * object) +{ + GstTheoraEnc *enc = GST_THEORA_ENC (object); + + GST_DEBUG_OBJECT (enc, "Finalizing"); + if (enc->encoder) + th_encode_free (enc->encoder); + th_comment_clear (&enc->comment); + th_info_clear (&enc->info); + g_free (enc->multipass_cache_file); + + theora_enc_clear_multipass_cache (enc); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +theora_enc_reset (GstTheoraEnc * enc) +{ + ogg_uint32_t keyframe_force; + int rate_flags; + + GST_OBJECT_LOCK (enc); + enc->info.target_bitrate = enc->video_bitrate; + enc->info.quality = enc->video_quality; + enc->bitrate_changed = FALSE; + enc->quality_changed = FALSE; + GST_OBJECT_UNLOCK (enc); + + if (enc->encoder) + th_encode_free (enc->encoder); + enc->encoder = th_encode_alloc (&enc->info); + /* We ensure this function cannot fail. */ + g_assert (enc->encoder != NULL); + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level, + sizeof (enc->speed_level)); + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_VP3_COMPATIBLE, + &enc->vp3_compatible, sizeof (enc->vp3_compatible)); + + rate_flags = 0; + if (enc->drop_frames) + rate_flags |= TH_RATECTL_DROP_FRAMES; + if (enc->drop_frames) + rate_flags |= TH_RATECTL_CAP_OVERFLOW; + if (enc->drop_frames) + rate_flags |= TH_RATECTL_CAP_UNDERFLOW; + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_FLAGS, + &rate_flags, sizeof (rate_flags)); + + if (enc->rate_buffer) { + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_RATE_BUFFER, + &enc->rate_buffer, sizeof (enc->rate_buffer)); + } else { + /* FIXME */ + } + + keyframe_force = enc->keyframe_auto ? + enc->keyframe_force : enc->keyframe_freq; + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_KEYFRAME_FREQUENCY_FORCE, + &keyframe_force, sizeof (keyframe_force)); + + /* Get placeholder data */ + if (enc->multipass_cache_fd + && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) + theora_enc_write_multipass_cache (enc, TRUE, FALSE); +} + +static void +theora_enc_clear (GstTheoraEnc * enc) +{ + enc->packetno = 0; + enc->bytes_out = 0; + enc->granulepos_offset = 0; + enc->timestamp_offset = 0; + + enc->next_ts = GST_CLOCK_TIME_NONE; + enc->next_discont = FALSE; + enc->expected_ts = GST_CLOCK_TIME_NONE; +} + +static char * +theora_enc_get_supported_formats (void) +{ + th_enc_ctx *encoder; + th_info info; + struct + { + th_pixel_fmt pixelformat; + const char *fourcc; + } formats[] = { + { + TH_PF_420, "I420"}, { + TH_PF_422, "Y42B"}, { + TH_PF_444, "Y444"} + }; + GString *string = NULL; + guint i; + + th_info_init (&info); + info.frame_width = 16; + info.frame_height = 16; + info.fps_numerator = 25; + info.fps_denominator = 1; + for (i = 0; i < G_N_ELEMENTS (formats); i++) { + info.pixel_fmt = formats[i].pixelformat; + + encoder = th_encode_alloc (&info); + if (encoder == NULL) + continue; + + GST_LOG ("format %s is supported", formats[i].fourcc); + th_encode_free (encoder); + + if (string == NULL) { + string = g_string_new (formats[i].fourcc); + } else { + g_string_append (string, ", "); + g_string_append (string, formats[i].fourcc); + } + } + th_info_clear (&info); + + return string == NULL ? NULL : g_string_free (string, FALSE); +} + +static GstCaps * +theora_enc_sink_getcaps (GstPad * pad) +{ + GstCaps *caps; + char *supported_formats, *caps_string; + + supported_formats = theora_enc_get_supported_formats (); + if (!supported_formats) { + GST_WARNING ("no supported formats found. Encoder disabled?"); + return gst_caps_new_empty (); + } + + caps_string = g_strdup_printf ("video/x-raw-yuv, " + "format = (fourcc) { %s }, " + "framerate = (fraction) [1/MAX, MAX], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]", + supported_formats); + caps = gst_caps_from_string (caps_string); + g_free (caps_string); + g_free (supported_formats); + GST_DEBUG ("Supported caps: %" GST_PTR_FORMAT, caps); + + return caps; +} + +static gboolean +theora_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstStructure *structure = gst_caps_get_structure (caps, 0); + GstTheoraEnc *enc = GST_THEORA_ENC (gst_pad_get_parent (pad)); + guint32 fourcc; + const GValue *par; + gint fps_n, fps_d; + + gst_structure_get_fourcc (structure, "format", &fourcc); + gst_structure_get_int (structure, "width", &enc->width); + gst_structure_get_int (structure, "height", &enc->height); + gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + + th_info_clear (&enc->info); + th_info_init (&enc->info); + /* Theora has a divisible-by-sixteen restriction for the encoded video size but + * we can define a picture area using pic_width/pic_height */ + enc->info.frame_width = GST_ROUND_UP_16 (enc->width); + enc->info.frame_height = GST_ROUND_UP_16 (enc->height); + enc->info.pic_width = enc->width; + enc->info.pic_height = enc->height; + switch (fourcc) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + enc->info.pixel_fmt = TH_PF_420; + break; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + enc->info.pixel_fmt = TH_PF_422; + break; + case GST_MAKE_FOURCC ('Y', '4', '4', '4'): + enc->info.pixel_fmt = TH_PF_444; + break; + default: + g_assert_not_reached (); + } + + enc->info.fps_numerator = enc->fps_n = fps_n; + enc->info.fps_denominator = enc->fps_d = fps_d; + if (par) { + enc->info.aspect_numerator = gst_value_get_fraction_numerator (par); + enc->info.aspect_denominator = gst_value_get_fraction_denominator (par); + } else { + /* setting them to 0 indicates that the decoder can chose a good aspect + * ratio, defaulting to 1/1 */ + enc->info.aspect_numerator = 0; + enc->info.aspect_denominator = 0; + } + + enc->info.colorspace = TH_CS_UNSPECIFIED; + + /* as done in theora */ + enc->info.keyframe_granule_shift = _ilog (enc->keyframe_force - 1); + GST_DEBUG_OBJECT (enc, + "keyframe_frequency_force is %d, granule shift is %d", + enc->keyframe_force, enc->info.keyframe_granule_shift); + + theora_enc_reset (enc); + enc->initialised = TRUE; + + gst_object_unref (enc); + + return TRUE; +} + +static guint64 +granulepos_add (guint64 granulepos, guint64 addend, gint shift) +{ + guint64 iframe, pframe; + + iframe = granulepos >> shift; + pframe = granulepos - (iframe << shift); + iframe += addend; + + return (iframe << shift) + pframe; +} + +/* prepare a buffer for transmission by passing data through libtheora */ +static GstFlowReturn +theora_buffer_from_packet (GstTheoraEnc * enc, ogg_packet * packet, + GstClockTime timestamp, GstClockTime running_time, + GstClockTime duration, GstBuffer ** buffer) +{ + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + + buf = gst_buffer_new_and_alloc (packet->bytes); + if (!buf) { + GST_WARNING_OBJECT (enc, "Could not allocate buffer"); + ret = GST_FLOW_ERROR; + goto done; + } + + memcpy (GST_BUFFER_DATA (buf), packet->packet, packet->bytes); + gst_buffer_set_caps (buf, GST_PAD_CAPS (enc->srcpad)); + /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its + * time representation */ + GST_BUFFER_OFFSET_END (buf) = + granulepos_add (packet->granulepos, enc->granulepos_offset, + enc->info.keyframe_granule_shift); + GST_BUFFER_OFFSET (buf) = granulepos_to_timestamp (enc, + GST_BUFFER_OFFSET_END (buf)); + + GST_BUFFER_TIMESTAMP (buf) = timestamp; + GST_BUFFER_DURATION (buf) = duration; + + if (enc->next_discont) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + enc->next_discont = FALSE; + } + + /* the second most significant bit of the first data byte is cleared + * for keyframes */ + if (packet->bytes > 0 && (packet->packet[0] & 0x40) == 0) { + GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } else { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } + enc->packetno++; + +done: + *buffer = buf; + return ret; +} + +/* push out the buffer and do internal bookkeeping */ +static GstFlowReturn +theora_push_buffer (GstTheoraEnc * enc, GstBuffer * buffer) +{ + GstFlowReturn ret; + + enc->bytes_out += GST_BUFFER_SIZE (buffer); + + ret = gst_pad_push (enc->srcpad, buffer); + + return ret; +} + +static GstFlowReturn +theora_push_packet (GstTheoraEnc * enc, ogg_packet * packet, + GstClockTime timestamp, GstClockTime running_time, GstClockTime duration) +{ + GstBuffer *buf; + GstFlowReturn ret; + + ret = + theora_buffer_from_packet (enc, packet, timestamp, running_time, duration, + &buf); + if (ret == GST_FLOW_OK) + ret = theora_push_buffer (enc, buf); + + return ret; +} + +static GstCaps * +theora_set_header_on_caps (GstCaps * caps, GSList * buffers) +{ + GstStructure *structure; + GValue array = { 0 }; + GValue value = { 0 }; + GstBuffer *buffer; + GSList *walk; + + caps = gst_caps_make_writable (caps); + structure = gst_caps_get_structure (caps, 0); + + /* put copies of the buffers in a fixed list */ + g_value_init (&array, GST_TYPE_ARRAY); + + for (walk = buffers; walk; walk = walk->next) { + buffer = walk->data; + + /* mark buffer */ + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS); + + /* Copy buffer, because we can't use the original - + * it creates a circular refcount with the caps<->buffers */ + buffer = gst_buffer_copy (buffer); + + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, buffer); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + + /* Unref our copy */ + gst_buffer_unref (buffer); + } + + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + + return caps; +} + +static void +theora_enc_force_keyframe (GstTheoraEnc * enc) +{ + GstClockTime next_ts; + + /* make sure timestamps increment after resetting the decoder */ + next_ts = enc->next_ts + enc->timestamp_offset; + + theora_enc_reset (enc); + enc->granulepos_offset = + gst_util_uint64_scale (next_ts, enc->fps_n, GST_SECOND * enc->fps_d); + enc->timestamp_offset = next_ts; + enc->next_ts = 0; +} + +static gboolean +theora_enc_sink_event (GstPad * pad, GstEvent * event) +{ + GstTheoraEnc *enc; + ogg_packet op; + gboolean res; + + enc = GST_THEORA_ENC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &time); + + gst_segment_set_newsegment_full (&enc->segment, update, rate, + applied_rate, format, start, stop, time); + + res = gst_pad_push_event (enc->srcpad, event); + break; + } + case GST_EVENT_EOS: + if (enc->initialised) { + /* push last packet with eos flag, should not be called */ + while (th_encode_packetout (enc->encoder, 1, &op)) { + GstClockTime next_time = + th_granule_time (enc->encoder, op.granulepos) * GST_SECOND; + + theora_push_packet (enc, &op, GST_CLOCK_TIME_NONE, enc->next_ts, + next_time - enc->next_ts); + enc->next_ts = next_time; + } + } + if (enc->initialised && enc->multipass_cache_fd + && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) + theora_enc_write_multipass_cache (enc, TRUE, TRUE); + + theora_enc_clear_multipass_cache (enc); + + res = gst_pad_push_event (enc->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&enc->segment, GST_FORMAT_UNDEFINED); + res = gst_pad_push_event (enc->srcpad, event); + break; + case GST_EVENT_CUSTOM_DOWNSTREAM: + { + const GstStructure *s; + + s = gst_event_get_structure (event); + + if (gst_structure_has_name (s, "GstForceKeyUnit")) + theora_enc_force_keyframe (enc); + res = gst_pad_push_event (enc->srcpad, event); + break; + } + default: + res = gst_pad_push_event (enc->srcpad, event); + break; + } + return res; +} + +static gboolean +theora_enc_src_event (GstPad * pad, GstEvent * event) +{ + GstTheoraEnc *enc; + gboolean res = TRUE; + + enc = GST_THEORA_ENC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_UPSTREAM: + { + const GstStructure *s; + + s = gst_event_get_structure (event); + + if (gst_structure_has_name (s, "GstForceKeyUnit")) { + GST_OBJECT_LOCK (enc); + enc->force_keyframe = TRUE; + GST_OBJECT_UNLOCK (enc); + /* consume the event */ + res = TRUE; + gst_event_unref (event); + } else { + res = gst_pad_push_event (enc->sinkpad, event); + } + break; + } + default: + res = gst_pad_push_event (enc->sinkpad, event); + break; + } + + return res; +} + +static gboolean +theora_enc_is_discontinuous (GstTheoraEnc * enc, GstClockTime timestamp, + GstClockTime duration) +{ + GstClockTimeDiff max_diff; + gboolean ret = FALSE; + + /* Allow 3/4 a frame off */ + max_diff = (enc->info.fps_denominator * GST_SECOND * 3) / + (enc->info.fps_numerator * 4); + + if (timestamp != GST_CLOCK_TIME_NONE + && enc->expected_ts != GST_CLOCK_TIME_NONE) { + if ((GstClockTimeDiff) (timestamp - enc->expected_ts) > max_diff) { + GST_DEBUG_OBJECT (enc, "Incoming TS %" GST_TIME_FORMAT + " exceeds expected value %" GST_TIME_FORMAT + " by too much, marking discontinuity", + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (enc->expected_ts)); + ret = TRUE; + } + } + + if (GST_CLOCK_TIME_IS_VALID (duration)) + enc->expected_ts = timestamp + duration; + else + enc->expected_ts = GST_CLOCK_TIME_NONE; + + return ret; +} + +static void +theora_enc_init_buffer (th_ycbcr_buffer buf, th_info * info, guint8 * data) +{ + GstVideoFormat format; + guint i; + + switch (info->pixel_fmt) { + case TH_PF_444: + format = GST_VIDEO_FORMAT_Y444; + break; + case TH_PF_420: + format = GST_VIDEO_FORMAT_I420; + break; + case TH_PF_422: + format = GST_VIDEO_FORMAT_Y42B; + break; + default: + g_assert_not_reached (); + } + + /* According to Theora developer Timothy Terriberry, the Theora + * encoder will not use memory outside of pic_width/height, even when + * the frame size is bigger. The values outside this region will be encoded + * to default values. + * Due to this, setting the frame's width/height as the buffer width/height + * is perfectly ok, even though it does not strictly look ok. + */ + for (i = 0; i < 3; i++) { + buf[i].width = + gst_video_format_get_component_width (format, i, info->frame_width); + buf[i].height = + gst_video_format_get_component_height (format, i, info->frame_height); + + buf[i].data = + data + gst_video_format_get_component_offset (format, i, + info->pic_width, info->pic_height); + buf[i].stride = + gst_video_format_get_row_stride (format, i, info->pic_width); + } +} + +static gboolean +theora_enc_read_multipass_cache (GstTheoraEnc * enc) +{ + GstBuffer *cache_buf; + const guint8 *cache_data; + gsize bytes_read = 0, bytes_consumed = 0; + GIOStatus stat = G_IO_STATUS_NORMAL; + gboolean done = FALSE; + + while (!done) { + if (gst_adapter_available (enc->multipass_cache_adapter) == 0) { + cache_buf = gst_buffer_new_and_alloc (512); + stat = g_io_channel_read_chars (enc->multipass_cache_fd, + (gchar *) GST_BUFFER_DATA (cache_buf), GST_BUFFER_SIZE (cache_buf), + &bytes_read, NULL); + + if (bytes_read <= 0) { + gst_buffer_unref (cache_buf); + break; + } else { + GST_BUFFER_SIZE (cache_buf) = bytes_read; + + gst_adapter_push (enc->multipass_cache_adapter, cache_buf); + } + } + if (gst_adapter_available (enc->multipass_cache_adapter) == 0) + break; + + bytes_read = + MIN (gst_adapter_available (enc->multipass_cache_adapter), 512); + + cache_data = gst_adapter_peek (enc->multipass_cache_adapter, bytes_read); + + bytes_consumed = + th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_IN, (guint8 *) cache_data, + bytes_read); + done = bytes_consumed <= 0; + if (bytes_consumed > 0) + gst_adapter_flush (enc->multipass_cache_adapter, bytes_consumed); + } + + if (stat == G_IO_STATUS_ERROR || (stat == G_IO_STATUS_EOF && bytes_read == 0) + || bytes_consumed < 0) { + GST_ELEMENT_ERROR (enc, RESOURCE, READ, (NULL), + ("Failed to read multipass cache file")); + return FALSE; + } + return TRUE; +} + +static gboolean +theora_enc_write_multipass_cache (GstTheoraEnc * enc, gboolean begin, + gboolean eos) +{ + GError *err = NULL; + GIOStatus stat = G_IO_STATUS_NORMAL; + gint bytes_read = 0; + gsize bytes_written = 0; + gchar *buf; + + if (begin) + stat = g_io_channel_seek_position (enc->multipass_cache_fd, 0, G_SEEK_SET, + &err); + if (stat != G_IO_STATUS_ERROR) { + do { + bytes_read = + th_encode_ctl (enc->encoder, TH_ENCCTL_2PASS_OUT, &buf, sizeof (buf)); + if (bytes_read > 0) + g_io_channel_write_chars (enc->multipass_cache_fd, buf, bytes_read, + &bytes_written, NULL); + } while (bytes_read > 0 && bytes_written > 0); + + } + + if (stat == G_IO_STATUS_ERROR || bytes_read < 0 || bytes_written < 0) { + if (begin) { + if (eos) + GST_ELEMENT_WARNING (enc, RESOURCE, WRITE, (NULL), + ("Failed to seek to beginning of multipass cache file: %s", + err->message)); + else + GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL), + ("Failed to seek to beginning of multipass cache file: %s", + err->message)); + } else { + GST_ELEMENT_ERROR (enc, RESOURCE, WRITE, (NULL), + ("Failed to write multipass cache file")); + } + if (err) + g_error_free (err); + + return FALSE; + } + return TRUE; +} + +static GstFlowReturn +theora_enc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstTheoraEnc *enc; + ogg_packet op; + GstClockTime timestamp, duration, running_time; + GstFlowReturn ret; + gboolean force_keyframe; + + enc = GST_THEORA_ENC (GST_PAD_PARENT (pad)); + + /* we keep track of two timelines. + * - The timestamps from the incomming buffers, which we copy to the outgoing + * encoded buffers as-is. We need to do this as we simply forward the + * newsegment events. + * - The running_time of the buffers, which we use to construct the granulepos + * in the packets. + */ + timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_DURATION (buffer); + + running_time = + gst_segment_to_running_time (&enc->segment, GST_FORMAT_TIME, timestamp); + if ((gint64) running_time < 0) { + GST_DEBUG_OBJECT (enc, "Dropping buffer, timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + GST_OBJECT_LOCK (enc); + if (enc->bitrate_changed) { + long int bitrate = enc->video_bitrate; + + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_BITRATE, &bitrate, + sizeof (long int)); + enc->bitrate_changed = FALSE; + } + + if (enc->quality_changed) { + long int quality = enc->video_quality; + + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_QUALITY, &quality, + sizeof (long int)); + enc->quality_changed = FALSE; + } + + /* see if we need to schedule a keyframe */ + force_keyframe = enc->force_keyframe; + enc->force_keyframe = FALSE; + GST_OBJECT_UNLOCK (enc); + + if (force_keyframe) { + GstClockTime stream_time; + GstStructure *s; + + stream_time = gst_segment_to_stream_time (&enc->segment, + GST_FORMAT_TIME, timestamp); + + s = gst_structure_new ("GstForceKeyUnit", + "timestamp", G_TYPE_UINT64, timestamp, + "stream-time", G_TYPE_UINT64, stream_time, + "running-time", G_TYPE_UINT64, running_time, NULL); + + theora_enc_force_keyframe (enc); + + gst_pad_push_event (enc->srcpad, + gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s)); + } + + /* make sure we copy the discont flag to the next outgoing buffer when it's + * set on the incomming buffer */ + if (GST_BUFFER_IS_DISCONT (buffer)) { + enc->next_discont = TRUE; + } + + if (enc->packetno == 0) { + /* no packets written yet, setup headers */ + GstCaps *caps; + GstBuffer *buf; + GSList *buffers = NULL; + int result; + + enc->granulepos_offset = 0; + enc->timestamp_offset = 0; + + GST_DEBUG_OBJECT (enc, "output headers"); + /* Theora streams begin with three headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. The + third header holds the bitstream codebook. We merely need to + make the headers, then pass them to libtheora one at a time; + libtheora handles the additional Ogg bitstream constraints */ + + /* create the remaining theora headers */ + th_comment_clear (&enc->comment); + th_comment_init (&enc->comment); + + while ((result = + th_encode_flushheader (enc->encoder, &enc->comment, &op)) > 0) { + ret = + theora_buffer_from_packet (enc, &op, GST_CLOCK_TIME_NONE, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, &buf); + if (ret != GST_FLOW_OK) { + goto header_buffer_alloc; + } + buffers = g_slist_prepend (buffers, buf); + } + if (result < 0) { + g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL); + g_slist_free (buffers); + goto encoder_disabled; + } + + buffers = g_slist_reverse (buffers); + + /* mark buffers and put on caps */ + caps = gst_pad_get_caps (enc->srcpad); + caps = theora_set_header_on_caps (caps, buffers); + GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps); + gst_pad_set_caps (enc->srcpad, caps); + + g_slist_foreach (buffers, (GFunc) gst_buffer_set_caps, caps); + + gst_caps_unref (caps); + + /* push out the header buffers */ + while (buffers) { + buf = buffers->data; + buffers = g_slist_delete_link (buffers, buffers); + if ((ret = theora_push_buffer (enc, buf)) != GST_FLOW_OK) { + g_slist_foreach (buffers, (GFunc) gst_buffer_unref, NULL); + g_slist_free (buffers); + goto header_push; + } + } + + enc->granulepos_offset = + gst_util_uint64_scale (running_time, enc->fps_n, + GST_SECOND * enc->fps_d); + enc->timestamp_offset = running_time; + enc->next_ts = 0; + } + + { + th_ycbcr_buffer ycbcr; + gint res; + + theora_enc_init_buffer (ycbcr, &enc->info, GST_BUFFER_DATA (buffer)); + + if (theora_enc_is_discontinuous (enc, running_time, duration)) { + theora_enc_reset (enc); + enc->granulepos_offset = + gst_util_uint64_scale (running_time, enc->fps_n, + GST_SECOND * enc->fps_d); + enc->timestamp_offset = running_time; + enc->next_ts = 0; + enc->next_discont = TRUE; + } + + if (enc->multipass_cache_fd + && enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) { + if (!theora_enc_read_multipass_cache (enc)) { + ret = GST_FLOW_ERROR; + goto multipass_read_failed; + } + } + + res = th_encode_ycbcr_in (enc->encoder, ycbcr); + /* none of the failure cases can happen here */ + g_assert (res == 0); + + if (enc->multipass_cache_fd + && enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS) { + if (!theora_enc_write_multipass_cache (enc, FALSE, FALSE)) { + ret = GST_FLOW_ERROR; + goto multipass_write_failed; + } + } + + ret = GST_FLOW_OK; + while (th_encode_packetout (enc->encoder, 0, &op)) { + GstClockTime next_time; + + next_time = th_granule_time (enc->encoder, op.granulepos) * GST_SECOND; + + ret = + theora_push_packet (enc, &op, timestamp, enc->next_ts, + next_time - enc->next_ts); + + enc->next_ts = next_time; + if (ret != GST_FLOW_OK) + goto data_push; + } + gst_buffer_unref (buffer); + } + + return ret; + + /* ERRORS */ +multipass_read_failed: + { + gst_buffer_unref (buffer); + return ret; + } +multipass_write_failed: + { + gst_buffer_unref (buffer); + return ret; + } +header_buffer_alloc: + { + gst_buffer_unref (buffer); + return ret; + } +header_push: + { + gst_buffer_unref (buffer); + return ret; + } +data_push: + { + gst_buffer_unref (buffer); + return ret; + } +encoder_disabled: + { + GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), + ("libtheora has been compiled with the encoder disabled")); + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } +} + +static GstStateChangeReturn +theora_enc_change_state (GstElement * element, GstStateChange transition) +{ + GstTheoraEnc *enc; + GstStateChangeReturn ret; + + enc = GST_THEORA_ENC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT (enc, "READY->PAUSED Initing theora state"); + th_info_init (&enc->info); + th_comment_init (&enc->comment); + enc->packetno = 0; + enc->force_keyframe = FALSE; + + if (enc->multipass_mode >= MULTIPASS_MODE_FIRST_PASS) { + GError *err = NULL; + + if (!enc->multipass_cache_file) { + ret = GST_STATE_CHANGE_FAILURE; + GST_ELEMENT_ERROR (enc, LIBRARY, SETTINGS, (NULL), (NULL)); + return ret; + } + enc->multipass_cache_fd = + g_io_channel_new_file (enc->multipass_cache_file, + (enc->multipass_mode == MULTIPASS_MODE_FIRST_PASS ? "w" : "r"), + &err); + + if (enc->multipass_mode == MULTIPASS_MODE_SECOND_PASS) + enc->multipass_cache_adapter = gst_adapter_new (); + + if (!enc->multipass_cache_fd) { + ret = GST_STATE_CHANGE_FAILURE; + GST_ELEMENT_ERROR (enc, RESOURCE, OPEN_READ, (NULL), + ("Failed to open multipass cache file: %s", err->message)); + g_error_free (err); + return ret; + } + + g_io_channel_set_encoding (enc->multipass_cache_fd, NULL, NULL); + } + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (enc, "PAUSED->READY Clearing theora state"); + if (enc->encoder) { + th_encode_free (enc->encoder); + enc->encoder = NULL; + } + th_comment_clear (&enc->comment); + th_info_clear (&enc->info); + + theora_enc_clear (enc); + enc->initialised = FALSE; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static void +theora_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTheoraEnc *enc = GST_THEORA_ENC (object); + + switch (prop_id) { + case PROP_CENTER: + case PROP_BORDER: + case PROP_QUICK: + case PROP_KEYFRAME_THRESHOLD: + case PROP_KEYFRAME_MINDISTANCE: + case PROP_NOISE_SENSITIVITY: + case PROP_SHARPNESS: + /* kept for API compat, but ignored */ + break; + case PROP_BITRATE: + GST_OBJECT_LOCK (enc); + enc->video_bitrate = g_value_get_int (value) * 1000; + enc->bitrate_changed = TRUE; + GST_OBJECT_UNLOCK (enc); + break; + case PROP_QUALITY: + GST_OBJECT_LOCK (enc); + if (GST_STATE (enc) >= GST_STATE_PAUSED && enc->video_bitrate > 0) { + GST_WARNING_OBJECT (object, "Can't change from bitrate to quality mode" + " while playing"); + } else { + enc->video_quality = g_value_get_int (value); + enc->video_bitrate = 0; + enc->quality_changed = TRUE; + } + GST_OBJECT_UNLOCK (enc); + break; + case PROP_KEYFRAME_AUTO: + enc->keyframe_auto = g_value_get_boolean (value); + break; + case PROP_KEYFRAME_FREQ: + enc->keyframe_freq = g_value_get_int (value); + break; + case PROP_KEYFRAME_FREQ_FORCE: + enc->keyframe_force = g_value_get_int (value); + break; + case PROP_SPEEDLEVEL: + enc->speed_level = g_value_get_int (value); + if (enc->encoder) { + th_encode_ctl (enc->encoder, TH_ENCCTL_SET_SPLEVEL, &enc->speed_level, + sizeof (enc->speed_level)); + } + break; + case PROP_VP3_COMPATIBLE: + enc->vp3_compatible = g_value_get_boolean (value); + break; + case PROP_DROP_FRAMES: + enc->drop_frames = g_value_get_boolean (value); + break; + case PROP_CAP_OVERFLOW: + enc->cap_overflow = g_value_get_boolean (value); + break; + case PROP_CAP_UNDERFLOW: + enc->cap_underflow = g_value_get_boolean (value); + break; + case PROP_RATE_BUFFER: + enc->rate_buffer = g_value_get_int (value); + break; + case PROP_MULTIPASS_CACHE_FILE: + enc->multipass_cache_file = g_value_dup_string (value); + break; + case PROP_MULTIPASS_MODE: + enc->multipass_mode = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +theora_enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTheoraEnc *enc = GST_THEORA_ENC (object); + + switch (prop_id) { + case PROP_CENTER: + g_value_set_boolean (value, TRUE); + break; + case PROP_BORDER: + g_value_set_enum (value, BORDER_BLACK); + break; + case PROP_BITRATE: + GST_OBJECT_LOCK (enc); + g_value_set_int (value, enc->video_bitrate / 1000); + GST_OBJECT_UNLOCK (enc); + break; + case PROP_QUALITY: + GST_OBJECT_LOCK (enc); + g_value_set_int (value, enc->video_quality); + GST_OBJECT_UNLOCK (enc); + break; + case PROP_QUICK: + g_value_set_boolean (value, TRUE); + break; + case PROP_KEYFRAME_AUTO: + g_value_set_boolean (value, enc->keyframe_auto); + break; + case PROP_KEYFRAME_FREQ: + g_value_set_int (value, enc->keyframe_freq); + break; + case PROP_KEYFRAME_FREQ_FORCE: + g_value_set_int (value, enc->keyframe_force); + break; + case PROP_KEYFRAME_THRESHOLD: + g_value_set_int (value, 80); + break; + case PROP_KEYFRAME_MINDISTANCE: + g_value_set_int (value, 8); + break; + case PROP_NOISE_SENSITIVITY: + g_value_set_int (value, 1); + break; + case PROP_SHARPNESS: + g_value_set_int (value, 0); + break; + case PROP_SPEEDLEVEL: + g_value_set_int (value, enc->speed_level); + break; + case PROP_VP3_COMPATIBLE: + g_value_set_boolean (value, enc->vp3_compatible); + break; + case PROP_DROP_FRAMES: + g_value_set_boolean (value, enc->drop_frames); + break; + case PROP_CAP_OVERFLOW: + g_value_set_boolean (value, enc->cap_overflow); + break; + case PROP_CAP_UNDERFLOW: + g_value_set_boolean (value, enc->cap_underflow); + break; + case PROP_RATE_BUFFER: + g_value_set_int (value, enc->rate_buffer); + break; + case PROP_MULTIPASS_CACHE_FILE: + g_value_set_string (value, enc->multipass_cache_file); + break; + case PROP_MULTIPASS_MODE: + g_value_set_enum (value, enc->multipass_mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.h b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.h new file mode 100644 index 0000000..08707d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraenc.h @@ -0,0 +1,140 @@ +/* GStreamer + * Copyright (C) 2004 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_THEORAENC_H__ +#define __GST_THEORAENC_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_THEORA_ENC \ + (gst_theora_enc_get_type()) +#define GST_THEORA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_ENC,GstTheoraEnc)) +#define GST_THEORA_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_ENC,GstTheoraEncClass)) +#define GST_IS_THEORA_ENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_ENC)) +#define GST_IS_THEORA_ENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_ENC)) + +typedef struct _GstTheoraEnc GstTheoraEnc; +typedef struct _GstTheoraEncClass GstTheoraEncClass; + +/** + * GstTheoraEncBorderMode: + * @BORDER_NONE: no border + * @BORDER_BLACK: black border + * @BORDER_MIRROR: Mirror image in border + * + * Border color to add when sizes not multiple of 16. + */ +typedef enum +{ + BORDER_NONE, + BORDER_BLACK, + BORDER_MIRROR +} +GstTheoraEncBorderMode; + +/** + * GstTheoraEncMultipassMode: + * @MULTIPASS_MODE_SINGLE_PASS: Single pass encoding + * @MULTIPASS_MODE_FIRST_PASS: First pass of two pass encoding + * @MULTIPASS_MODE_SECOND_PASS: Second pass of two pass encoding + * + */ +typedef enum +{ + MULTIPASS_MODE_SINGLE_PASS, + MULTIPASS_MODE_FIRST_PASS, + MULTIPASS_MODE_SECOND_PASS +} GstTheoraEncMultipassMode; + +/** + * GstTheoraEnc: + * + * Opaque data structure. + */ +struct _GstTheoraEnc +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstSegment segment; + + ogg_stream_state to; + + th_enc_ctx *encoder; + th_info info; + th_comment comment; + gboolean initialised; + + gint video_bitrate; /* bitrate target for Theora video */ + gboolean bitrate_changed; + gint video_quality; /* Theora quality selector 0 = low, 63 = high */ + gboolean quality_changed; + gboolean keyframe_auto; + gint keyframe_freq; + gint keyframe_force; + + gint info_width, info_height; + gint width, height; + gint fps_n, fps_d; + GstClockTime next_ts; + + GstClockTime expected_ts; + gboolean next_discont; + + gboolean force_keyframe; + + guint packetno; + guint64 bytes_out; + guint64 granulepos_offset; + guint64 timestamp_offset; + + gint speed_level; + gboolean vp3_compatible; + gboolean drop_frames; + gboolean cap_overflow; + gboolean cap_underflow; + int rate_buffer; + + GstTheoraEncMultipassMode multipass_mode; + GIOChannel *multipass_cache_fd; + GstAdapter *multipass_cache_adapter; + gchar *multipass_cache_file; +}; + +struct _GstTheoraEncClass +{ + GstElementClass parent_class; +}; + +GType gst_theora_enc_get_type (void); + +G_END_DECLS + +#endif /* __GST_THEORAENC_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.c b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.c new file mode 100644 index 0000000..0ce68d9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.c @@ -0,0 +1,936 @@ +/* GStreamer + * Copyright (C) <2004> Thomas Vander Stichele + * Copyright (C) 2006 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-theoraparse + * @see_also: theoradec, oggdemux, vorbisparse + * + * The theoraparse element will parse the header packets of the Theora + * stream and put them as the streamheader in the caps. This is used in the + * multifdsink case where you want to stream live theora streams to multiple + * clients, each client has to receive the streamheaders first before they can + * consume the theora packets. + * + * 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 + * theoraparse outputs have all of the metadata that oggmux expects to receive, + * which allows you to (for example) remux an ogg/theora file. + * + * In addition, this element allows you to fix badly synchronized streams. You + * pass in an array of (granule time, buffer time) synchronization points via + * the synchronization-points GValueArray property, and this element will adjust + * the granulepos values that it outputs. The adjustment will be made by + * offsetting all buffers that it outputs by a specified amount, and updating + * that offset from the value array whenever a keyframe is processed. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=video.ogg ! oggdemux ! theoraparse ! fakesink + * ]| This pipeline shows that the streamheader is set in the caps, and that each + * buffer has the timestamp, duration, offset, and offset_end set. + * |[ + * gst-launch filesrc location=video.ogg ! oggdemux ! theoraparse \ + * ! oggmux ! filesink location=video-remuxed.ogg + * ]| This pipeline shows remuxing. video-remuxed.ogg might not be exactly the same + * as video.ogg, but they should produce exactly the same decoded data. + * + * + * Last reviewed on 2008-05-28 (0.10.20) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gsttheoraparse.h" + +#define GST_CAT_DEFAULT theoraparse_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +static GstStaticPadTemplate theora_parse_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-theora") + ); + +static GstStaticPadTemplate theora_parse_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-theora") + ); + +enum +{ + PROP_0, + PROP_SYNCHRONIZATION_POINTS +}; + +GST_BOILERPLATE (GstTheoraParse, gst_theora_parse, GstElement, + GST_TYPE_ELEMENT); + +static void theora_parse_dispose (GObject * object); +static void theora_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void theora_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static GstFlowReturn theora_parse_chain (GstPad * pad, GstBuffer * buffer); +static GstStateChangeReturn theora_parse_change_state (GstElement * element, + GstStateChange transition); +static gboolean theora_parse_sink_event (GstPad * pad, GstEvent * event); +static gboolean theora_parse_src_query (GstPad * pad, GstQuery * query); + +static void +gst_theora_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_parse_src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&theora_parse_sink_factory)); + gst_element_class_set_details_simple (element_class, + "Theora video parser", "Codec/Parser/Video", + "parse raw theora streams", "Andy Wingo "); +} + +static void +gst_theora_parse_class_init (GstTheoraParseClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->dispose = theora_parse_dispose; + gobject_class->get_property = theora_parse_get_property; + gobject_class->set_property = theora_parse_set_property; + + /** + * GstTheoraParse:sychronization-points + * + * An array of (granuletime, buffertime) pairs + * + * Since: 0.10.10 + */ + g_object_class_install_property (gobject_class, PROP_SYNCHRONIZATION_POINTS, + g_param_spec_value_array ("synchronization-points", + "Synchronization points", + "An array of (granuletime, buffertime) pairs", + g_param_spec_uint64 ("time", "Time", + "Time (either granuletime or buffertime)", 0, G_MAXUINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS), + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = theora_parse_change_state; + + GST_DEBUG_CATEGORY_INIT (theoraparse_debug, "theoraparse", 0, + "Theora parser"); +} + +static void +gst_theora_parse_init (GstTheoraParse * parse, GstTheoraParseClass * g_class) +{ + parse->sinkpad = + gst_pad_new_from_static_template (&theora_parse_sink_factory, "sink"); + gst_pad_set_chain_function (parse->sinkpad, theora_parse_chain); + gst_pad_set_event_function (parse->sinkpad, theora_parse_sink_event); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + parse->srcpad = + gst_pad_new_from_static_template (&theora_parse_src_factory, "src"); + gst_pad_set_query_function (parse->srcpad, theora_parse_src_query); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); +} + +static void +theora_parse_dispose (GObject * object) +{ + GstTheoraParse *parse = GST_THEORA_PARSE (object); + + g_free (parse->times); + parse->times = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +theora_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTheoraParse *parse = GST_THEORA_PARSE (object); + + switch (prop_id) { + case PROP_SYNCHRONIZATION_POINTS: + { + GValueArray *array; + guint i; + + array = g_value_get_boxed (value); + + if (array) { + if (array->n_values % 2) + goto odd_values; + + g_free (parse->times); + parse->times = g_new (GstClockTime, array->n_values); + parse->npairs = array->n_values / 2; + for (i = 0; i < array->n_values; i++) + parse->times[i] = g_value_get_uint64 (&array->values[i]); + } else { + g_free (parse->times); + parse->npairs = 0; + } + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; + +odd_values: + { + g_critical ("expected an even number of time values for " + "synchronization-points"); + return; + } +} + +static void +theora_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTheoraParse *parse = GST_THEORA_PARSE (object); + + switch (prop_id) { + case PROP_SYNCHRONIZATION_POINTS: + { + GValueArray *array = NULL; + guint i; + + array = g_value_array_new (parse->npairs * 2); + + for (i = 0; i < parse->npairs; i++) { + GValue v = { 0, }; + + g_value_init (&v, G_TYPE_UINT64); + g_value_set_uint64 (&v, parse->times[i * 2]); + g_value_array_append (array, &v); + g_value_set_uint64 (&v, parse->times[i * 2 + 1]); + g_value_array_append (array, &v); + g_value_unset (&v); + } + + g_value_set_boxed (value, array); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +theora_parse_set_header_on_caps (GstTheoraParse * parse, GstCaps * caps) +{ + GstBuffer **bufs; + GstStructure *structure; + gint i; + GValue array = { 0 }; + GValue value = { 0 }; + + bufs = parse->streamheader; + structure = gst_caps_get_structure (caps, 0); + g_value_init (&array, GST_TYPE_ARRAY); + + for (i = 0; i < 3; i++) { + if (bufs[i] == NULL) + continue; + + bufs[i] = gst_buffer_make_metadata_writable (bufs[i]); + GST_BUFFER_FLAG_SET (bufs[i], GST_BUFFER_FLAG_IN_CAPS); + + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, bufs[i]); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + } + + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); +} + +/* two tasks to do here: set the streamheader on the caps, and use libtheora to + parse the headers */ +static void +theora_parse_set_streamheader (GstTheoraParse * parse) +{ + GstCaps *caps; + gint i; + guint32 bitstream_version; + th_setup_info *setup = NULL; + + g_assert (!parse->streamheader_received); + + caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad)); + theora_parse_set_header_on_caps (parse, caps); + GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps); + gst_pad_set_caps (parse->srcpad, caps); + gst_caps_unref (caps); + + for (i = 0; i < 3; i++) { + ogg_packet packet; + GstBuffer *buf; + int ret; + + buf = parse->streamheader[i]; + if (buf == NULL) + continue; + + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + packet.packetno = i + 1; + packet.e_o_s = 0; + packet.b_o_s = (i == 0); + ret = th_decode_headerin (&parse->info, &parse->comment, &setup, &packet); + if (ret < 0) { + GST_WARNING_OBJECT (parse, "Failed to decode Theora header %d: %d\n", + i + 1, ret); + } + } + if (setup) { + th_setup_free (setup); + } + + parse->fps_n = parse->info.fps_numerator; + parse->fps_d = parse->info.fps_denominator; + parse->shift = parse->info.keyframe_granule_shift; + + /* With libtheora-1.0beta1 the granulepos scheme was changed: + * where earlier the granulepos refered to the index/beginning + * of a frame, it now refers to the end, which matches the use + * in vorbis/speex. We check the bitstream version from the header so + * we know which way to interpret the incoming granuepos + */ + bitstream_version = (parse->info.version_major << 16) | + (parse->info.version_minor << 8) | parse->info.version_subminor; + parse->is_old_bitstream = (bitstream_version <= 0x00030200); + + parse->streamheader_received = TRUE; +} + +static void +theora_parse_drain_event_queue (GstTheoraParse * parse) +{ + while (parse->event_queue->length) { + GstEvent *event; + + event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); + gst_pad_event_default (parse->sinkpad, event); + } +} + +static void +theora_parse_push_headers (GstTheoraParse * parse) +{ + gint i; + + theora_parse_drain_event_queue (parse); + + if (!parse->streamheader_received) + theora_parse_set_streamheader (parse); + + /* ignore return values, we pass along the result of pushing data packets only + */ + for (i = 0; i < 3; i++) { + GstBuffer *buf; + + if ((buf = parse->streamheader[i])) { + buf = gst_buffer_make_metadata_writable (buf); + gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad)); + gst_pad_push (parse->srcpad, buf); + parse->streamheader[i] = NULL; + } + } +} + +static void +theora_parse_clear_queue (GstTheoraParse * parse) +{ + while (parse->buffer_queue->length) { + GstBuffer *buf; + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + gst_buffer_unref (buf); + } + while (parse->event_queue->length) { + GstEvent *event; + + event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); + gst_event_unref (event); + } +} + +static gint64 +make_granulepos (GstTheoraParse * parse, gint64 keyframe, gint64 frame) +{ + gint64 iframe; + + if (keyframe == -1) + keyframe = 0; + /* If using newer theora, offset the granulepos by +1, see comment in + * theora_parse_set_streamheader. + * + * We don't increment keyframe directly, as internally we always index frames + * starting from 0 and we do some sanity checking below. */ + if (!parse->is_old_bitstream) + iframe = keyframe + 1; + else + iframe = keyframe; + + g_return_val_if_fail (frame >= keyframe, -1); + g_return_val_if_fail (frame - keyframe < 1 << parse->shift, -1); + + return (iframe << parse->shift) + (frame - keyframe); +} + +static void +parse_granulepos (GstTheoraParse * parse, gint64 granulepos, + gint64 * keyframe, gint64 * frame) +{ + gint64 kf; + + kf = granulepos >> parse->shift; + /* If using newer theora, offset the granulepos by -1, see comment + * in theora_parse_set_streamheader */ + if (!parse->is_old_bitstream) + kf -= 1; + if (keyframe) + *keyframe = kf; + if (frame) + *frame = kf + (granulepos & ((1 << parse->shift) - 1)); +} + +static gboolean +is_keyframe (GstBuffer * buf) +{ + if (!GST_BUFFER_DATA (buf)) + return FALSE; + if (!GST_BUFFER_SIZE (buf)) + return FALSE; + return ((GST_BUFFER_DATA (buf)[0] & 0x40) == 0); +} + +static void +theora_parse_munge_granulepos (GstTheoraParse * parse, GstBuffer * buf, + gint64 keyframe, gint64 frame) +{ + gint64 frames_diff; + GstClockTimeDiff time_diff; + + if (keyframe == frame) { + gint i; + + /* update granule_offset */ + for (i = 0; i < parse->npairs; i++) { + if (parse->times[i * 2] >= GST_BUFFER_OFFSET (buf)) + break; + } + if (i > 0) { + /* time_diff gets reset below */ + time_diff = parse->times[i * 2 - 1] - parse->times[i * 2 - 2]; + parse->granule_offset = gst_util_uint64_scale (time_diff, + parse->fps_n, parse->fps_d * GST_SECOND); + parse->granule_offset <<= parse->shift; + } + } + + frames_diff = parse->granule_offset >> parse->shift; + time_diff = gst_util_uint64_scale_int (GST_SECOND * frames_diff, + parse->fps_d, parse->fps_n); + + GST_DEBUG_OBJECT (parse, "offsetting theora stream by %" G_GINT64_FORMAT + " frames (%" GST_TIME_FORMAT ")", frames_diff, GST_TIME_ARGS (time_diff)); + + GST_BUFFER_OFFSET_END (buf) += parse->granule_offset; + GST_BUFFER_OFFSET (buf) += time_diff; + GST_BUFFER_TIMESTAMP (buf) += time_diff; +} + +static GstFlowReturn +theora_parse_push_buffer (GstTheoraParse * parse, GstBuffer * buf, + gint64 keyframe, gint64 frame) +{ + + GstClockTime this_time, next_time; + + this_time = gst_util_uint64_scale_int (GST_SECOND * frame, + parse->fps_d, parse->fps_n); + + next_time = gst_util_uint64_scale_int (GST_SECOND * (frame + 1), + parse->fps_d, parse->fps_n); + + GST_BUFFER_OFFSET_END (buf) = make_granulepos (parse, keyframe, frame); + GST_BUFFER_OFFSET (buf) = this_time; + GST_BUFFER_TIMESTAMP (buf) = this_time; + GST_BUFFER_DURATION (buf) = next_time - this_time; + + gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad)); + + if (parse->times) + theora_parse_munge_granulepos (parse, buf, keyframe, frame); + + GST_DEBUG_OBJECT (parse, "pushing buffer with granulepos %" G_GINT64_FORMAT + "|%" G_GINT64_FORMAT, keyframe, frame - keyframe); + + return gst_pad_push (parse->srcpad, buf); +} + +static GstFlowReturn +theora_parse_drain_queue_prematurely (GstTheoraParse * parse) +{ + GstFlowReturn ret = GST_FLOW_OK; + + /* got an EOS event, make sure to push out any buffers that were in the queue + * -- won't normally be the case, but this catches the + * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous + * stream. */ + + GST_DEBUG_OBJECT (parse, "got EOS, draining queue"); + + /* if we get an eos before pushing the streamheaders, drain our events before + * eos */ + theora_parse_drain_event_queue (parse); + + while (!g_queue_is_empty (parse->buffer_queue)) { + GstBuffer *buf; + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + + parse->prev_frame++; + + if (is_keyframe (buf)) + /* we have a keyframe */ + parse->prev_keyframe = parse->prev_frame; + else + GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT; + + if (parse->prev_keyframe < 0) { + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) { + parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf), + &parse->prev_keyframe, NULL); + } else { + /* No previous keyframe known; can't extract one from this frame. That + * means we can't do any valid output for this frame, just continue to + * the next frame. + */ + gst_buffer_unref (buf); + continue; + } + } + + ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe, + parse->prev_frame); + + if (ret != GST_FLOW_OK) + goto done; + } + +done: + return ret; +} + +static GstFlowReturn +theora_parse_drain_queue (GstTheoraParse * parse, gint64 granulepos) +{ + GstFlowReturn ret = GST_FLOW_OK; + gint64 keyframe, prev_frame, frame; + + parse_granulepos (parse, granulepos, &keyframe, &frame); + + GST_DEBUG ("draining queue of length %d", + g_queue_get_length (parse->buffer_queue)); + + GST_LOG_OBJECT (parse, "gp %" G_GINT64_FORMAT ", kf %" G_GINT64_FORMAT + ", frame %" G_GINT64_FORMAT, granulepos, keyframe, frame); + + prev_frame = frame - g_queue_get_length (parse->buffer_queue); + + GST_LOG_OBJECT (parse, + "new prev %" G_GINT64_FORMAT ", prev %" G_GINT64_FORMAT, prev_frame, + parse->prev_frame); + + if (prev_frame < parse->prev_frame) { + GST_WARNING ("jumped %" G_GINT64_FORMAT + " frames backwards! not sure what to do here", + parse->prev_frame - prev_frame); + parse->prev_frame = prev_frame; + } else if (prev_frame > parse->prev_frame) { + GST_INFO ("discontinuity detected (%" G_GINT64_FORMAT + " frames)", prev_frame - parse->prev_frame); + if (keyframe <= prev_frame && keyframe > parse->prev_keyframe) + parse->prev_keyframe = keyframe; + parse->prev_frame = prev_frame; + } + + while (!g_queue_is_empty (parse->buffer_queue)) { + GstBuffer *buf; + + parse->prev_frame++; + g_assert (parse->prev_frame >= 0); + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + + if (is_keyframe (buf)) + /* we have a keyframe */ + parse->prev_keyframe = parse->prev_frame; + else + GST_BUFFER_FLAGS (buf) |= GST_BUFFER_FLAG_DELTA_UNIT; + + ret = theora_parse_push_buffer (parse, buf, parse->prev_keyframe, + parse->prev_frame); + + if (ret != GST_FLOW_OK) + goto done; + } + +done: + return ret; +} + +static GstFlowReturn +theora_parse_queue_buffer (GstTheoraParse * parse, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + + buf = gst_buffer_make_metadata_writable (buf); + + g_queue_push_tail (parse->buffer_queue, buf); + + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) { + if (parse->prev_keyframe < 0) { + parse_granulepos (parse, GST_BUFFER_OFFSET_END (buf), + &parse->prev_keyframe, NULL); + } + ret = theora_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf)); + } + + return ret; +} + +static GstFlowReturn +theora_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstFlowReturn ret; + GstTheoraParse *parse; + guint8 *data; + guint size; + gboolean have_header; + + parse = GST_THEORA_PARSE (gst_pad_get_parent (pad)); + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + have_header = FALSE; + if (size >= 1) { + if (data[0] & 0x80) + have_header = TRUE; + } + + if (have_header) { + if (parse->send_streamheader) { + /* we need to collect the headers still */ + /* so put it on the streamheader list and return */ + if (data[0] >= 0x80 && data[0] <= 0x82) + parse->streamheader[data[0] - 0x80] = buffer; + } + ret = GST_FLOW_OK; + } else { + /* data packet, push the headers we collected before */ + if (parse->send_streamheader) { + theora_parse_push_headers (parse); + parse->send_streamheader = FALSE; + } + + ret = theora_parse_queue_buffer (parse, buffer); + } + + gst_object_unref (parse); + + return ret; +} + +static gboolean +theora_parse_queue_event (GstTheoraParse * parse, GstEvent * event) +{ + g_queue_push_tail (parse->event_queue, event); + return TRUE; +} + +static gboolean +theora_parse_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret; + GstTheoraParse *parse; + + parse = GST_THEORA_PARSE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + theora_parse_clear_queue (parse); + parse->prev_keyframe = -1; + parse->prev_frame = -1; + ret = gst_pad_event_default (pad, event); + break; + case GST_EVENT_EOS: + theora_parse_drain_queue_prematurely (parse); + ret = gst_pad_event_default (pad, event); + break; + default: + if (parse->send_streamheader && GST_EVENT_IS_SERIALIZED (event)) + ret = theora_parse_queue_event (parse, event); + else + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (parse); + + return ret; +} + +static gboolean +theora_parse_src_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstTheoraParse *parse; + guint64 scale = 1; + + if (src_format == *dest_format) { + *dest_value = src_value; + return TRUE; + } + + parse = GST_THEORA_PARSE (gst_pad_get_parent (pad)); + + /* we need the info part before we can done something */ + if (!parse->streamheader_received) + goto no_header; + + switch (src_format) { + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = gst_util_uint64_scale_int (src_value, 2, + parse->info.pic_height * parse->info.pic_width * 3); + break; + case GST_FORMAT_TIME: + /* seems like a rather silly conversion, implement me if you like */ + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = 3 * (parse->info.pic_width * parse->info.pic_height) / 2; + case GST_FORMAT_DEFAULT: + *dest_value = scale * gst_util_uint64_scale (src_value, + parse->info.fps_numerator, + parse->info.fps_denominator * GST_SECOND); + break; + default: + GST_DEBUG_OBJECT (parse, "cannot convert to format %s", + gst_format_get_name (*dest_format)); + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * parse->info.fps_denominator, + parse->info.fps_numerator); + break; + case GST_FORMAT_BYTES: + *dest_value = gst_util_uint64_scale_int (src_value, + 3 * parse->info.pic_width * parse->info.pic_height, 2); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } +done: + gst_object_unref (parse); + return res; + + /* ERRORS */ +no_header: + { + GST_DEBUG_OBJECT (parse, "no header yet, cannot convert"); + res = FALSE; + goto done; + } +} + +static gboolean +theora_parse_src_query (GstPad * pad, GstQuery * query) +{ + GstTheoraParse *parse; + + gboolean res = FALSE; + + parse = GST_THEORA_PARSE (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 frame, value; + GstFormat my_format, format; + gint64 time; + + frame = parse->prev_frame; + + GST_LOG_OBJECT (parse, + "query %p: we have current frame: %" G_GINT64_FORMAT, query, frame); + + /* parse format */ + gst_query_parse_position (query, &format, NULL); + + /* and convert to the final format in two steps with time as the + * intermediate step */ + my_format = GST_FORMAT_TIME; + if (!(res = + theora_parse_src_convert (parse->sinkpad, GST_FORMAT_DEFAULT, + frame, &my_format, &time))) + goto error; + + /* fixme: handle segments + time = (time - parse->segment.start) + parse->segment.time; + */ + + GST_LOG_OBJECT (parse, + "query %p: our time: %" GST_TIME_FORMAT " (conv to %s)", + query, GST_TIME_ARGS (time), gst_format_get_name (format)); + + if (!(res = + theora_parse_src_convert (pad, my_format, time, &format, &value))) + goto error; + + gst_query_set_position (query, format, value); + + GST_LOG_OBJECT (parse, + "query %p: we return %" G_GINT64_FORMAT " (format %u)", query, value, + format); + + break; + } + case GST_QUERY_DURATION: + /* forward to peer for total */ + if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query))) + goto error; + break; + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + theora_parse_src_convert (pad, src_fmt, src_val, &dest_fmt, + &dest_val))) + goto error; + + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } +done: + gst_object_unref (parse); + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (parse, "query failed"); + goto done; + } +} + +static GstStateChangeReturn +theora_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstTheoraParse *parse = GST_THEORA_PARSE (element); + GstStateChangeReturn ret; + gint i; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + th_info_init (&parse->info); + th_comment_init (&parse->comment); + parse->send_streamheader = TRUE; + parse->buffer_queue = g_queue_new (); + parse->event_queue = g_queue_new (); + parse->prev_keyframe = -1; + parse->prev_frame = -1; + parse->granule_offset = 0; + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + th_info_clear (&parse->info); + th_comment_clear (&parse->comment); + theora_parse_clear_queue (parse); + g_queue_free (parse->buffer_queue); + g_queue_free (parse->event_queue); + parse->buffer_queue = NULL; + for (i = 0; i < 3; i++) { + if (parse->streamheader[i]) { + gst_buffer_unref (parse->streamheader[i]); + parse->streamheader[i] = NULL; + } + } + parse->streamheader_received = FALSE; + break; + default: + break; + } + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.h b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.h new file mode 100644 index 0000000..8314287 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/theora/gsttheoraparse.h @@ -0,0 +1,87 @@ +/* -*- c-basic-offset: 2 -*- + * GStreamer + * Copyright (C) <2004> Thomas Vander Stichele + * Copyright (C) 2006 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_THEORA_PARSE_H__ +#define __GST_THEORA_PARSE_H__ + + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_THEORA_PARSE \ + (gst_theora_parse_get_type()) +#define GST_THEORA_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_THEORA_PARSE,GstTheoraParse)) +#define GST_THEORA_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_THEORA_PARSE,GstTheoraParseClass)) +#define GST_IS_THEORA_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_THEORA_PARSE)) +#define GST_IS_THEORA_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_THEORA_PARSE)) + +typedef struct _GstTheoraParse GstTheoraParse; +typedef struct _GstTheoraParseClass GstTheoraParseClass; + +/** + * GstTheoraParse: + * + * Opaque data structure. + */ +struct _GstTheoraParse { + GstElement element; + + GstPad * sinkpad; + GstPad * srcpad; + + gboolean send_streamheader; + gboolean streamheader_received; + gboolean is_old_bitstream; + GstBuffer * streamheader[3]; + + GQueue * event_queue; + GQueue * buffer_queue; + + th_info info; + th_comment comment; + + gint64 prev_frame; + gint64 prev_keyframe; + guint32 fps_n; + guint32 fps_d; + gint shift; + gint64 granule_offset; + + GstClockTime *times; + gint npairs; +}; + +struct _GstTheoraParseClass { + GstElementClass parent_class; +}; + +GType gst_theora_parse_get_type(void); + +G_END_DECLS + +#endif /* __GST_THEORA_PARSE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/Makefile.am b/gst-plugins-base-subtitles0.10/ext/vorbis/Makefile.am new file mode 100644 index 0000000..7c18ff1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/Makefile.am @@ -0,0 +1,60 @@ +plugin_LTLIBRARIES = + +if USE_VORBIS +plugin_LTLIBRARIES += libgstvorbis.la + +libgstvorbis_la_SOURCES = gstvorbis.c \ + gstvorbisdec.c \ + gstvorbisdeclib.c \ + gstvorbisenc.c \ + gstvorbisparse.c \ + gstvorbistag.c \ + gstvorbiscommon.c + +libgstvorbis_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(VORBIS_CFLAGS) +## AM_PATH_VORBIS also sets VORBISENC_LIBS +libgstvorbis_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(GST_LIBS) \ + $(VORBIS_LIBS) $(VORBISENC_LIBS) +libgstvorbis_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvorbis_la_LIBTOOLFLAGS = --tag=disable-static +endif + +if USE_IVORBIS +plugin_LTLIBRARIES += libgstivorbisdec.la + +libgstivorbisdec_la_SOURCES = gstivorbisdec.c \ + gstvorbisdec.c gstvorbisdeclib.c gstvorbiscommon.c +libgstivorbisdec_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ + -DTREMOR $(IVORBIS_CFLAGS) +libgstivorbisdec_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(GST_LIBS) $(IVORBIS_LIBS) +libgstivorbisdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstivorbisdec_la_LIBTOOLFLAGS = --tag=disable-static +endif + +noinst_HEADERS = gstvorbisenc.h \ + gstvorbisdec.h \ + gstvorbisdeclib.h \ + gstvorbisparse.h \ + gstvorbistag.h \ + gstvorbiscommon.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstivorbisdec -:SHARED libgstivorbisdec \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstivorbisdec_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstivorbisdec_la_CFLAGS) \ + -:LDFLAGS $(libgstivorbisdec_la_LDFLAGS) \ + $(libgstivorbisdec_la_LIBADD) \ + -lvorbisidec \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/README b/gst-plugins-base-subtitles0.10/ext/vorbis/README new file mode 100644 index 0000000..6b31510 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/README @@ -0,0 +1,16 @@ +oggvorbisenc : encodes to vorbis inside an ogg stream. This is not the + GStreamer way of doing things and should be removed for + 0.9. It is still called "vorbisenc" for backward compatibility + reasons. It also takes integer audio as input. +vorbisenc : Encodes to a raw vorbis stream and should be used together + with an ogg muxer such as "oggmux" it is called "rawvorbisenc". + It also takes raw float samples as input. + +TODO for 0.9: + +- remove oggvorbisenc.c and oggvorbisenc.h +- remove references to oggvorbisenc.[ch] in the Makefile and in vorbis.c +- remove the element vorbisenc. +- rename the element rawvorbisenc to vorbisenc. + + diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstivorbisdec.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstivorbisdec.c new file mode 100644 index 0000000..d938238 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstivorbisdec.c @@ -0,0 +1,47 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstvorbisdec.h" + +GST_DEBUG_CATEGORY (vorbisdec_debug); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + + /* if tremor is around, there is probably good reason for it, so preferred */ + if (!gst_element_register (plugin, "ivorbisdec", GST_RANK_SECONDARY, + gst_vorbis_dec_get_type ())) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "ivorbisdec", 0, + "vorbis decoding element (integer decoder)"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "ivorbisdec", + "Vorbis Tremor decoder", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbis.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbis.c new file mode 100644 index 0000000..f710aaa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbis.c @@ -0,0 +1,73 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst/tag/tag.h" + +#include "gstvorbisenc.h" +#include "gstvorbisdec.h" +#include "gstvorbisparse.h" +#include "gstvorbistag.h" + +GST_DEBUG_CATEGORY (vorbisenc_debug); +GST_DEBUG_CATEGORY (vorbisdec_debug); +GST_DEBUG_CATEGORY (vorbisparse_debug); +GST_DEBUG_CATEGORY (vorbistag_debug); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "vorbisenc", GST_RANK_PRIMARY, + GST_TYPE_VORBISENC)) + return FALSE; + + if (!gst_element_register (plugin, "vorbisdec", GST_RANK_PRIMARY, + gst_vorbis_dec_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "vorbisparse", GST_RANK_NONE, + gst_vorbis_parse_get_type ())) + return FALSE; + + if (!gst_element_register (plugin, "vorbistag", GST_RANK_NONE, + gst_vorbis_tag_get_type ())) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (vorbisenc_debug, "vorbisenc", 0, + "vorbis encoding element"); + GST_DEBUG_CATEGORY_INIT (vorbisdec_debug, "vorbisdec", 0, + "vorbis decoding element"); + GST_DEBUG_CATEGORY_INIT (vorbisparse_debug, "vorbisparse", 0, + "vorbis parsing element"); + GST_DEBUG_CATEGORY_INIT (vorbistag_debug, "vorbistag", 0, + "vorbis tagging element"); + + gst_tag_register_musicbrainz_tags (); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vorbis", + "Vorbis plugin library", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.c new file mode 100644 index 0000000..c4dd408 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.c @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstvorbiscommon.h" + +/* http://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-800004.3.9 */ +const GstAudioChannelPosition gst_vorbis_channel_positions[][8] = { + { /* Mono */ + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}, + { /* Stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Stereo + Centre */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Quadraphonic */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Stereo + Centre + rear stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Full 5.1 Surround */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, + }, + { /* 6.1 Surround, in Vorbis spec since 2010-01-13 */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE}, + { /* 7.1 Surround, in Vorbis spec since 2010-01-13 */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE}, +}; diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.h new file mode 100644 index 0000000..563b8f7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbiscommon.h @@ -0,0 +1,28 @@ +/* GStreamer + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_VORBIS_COMMON_H__ +#define __GST_VORBIS_COMMON_H__ + +#include +#include + +extern const GstAudioChannelPosition gst_vorbis_channel_positions[][8]; + +#endif /* __GST_VORBIS_COMMON_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.c new file mode 100644 index 0000000..645c27d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.c @@ -0,0 +1,1301 @@ +/* GStreamer + * Copyright (C) 2004 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-vorbisdec + * @see_also: vorbisenc, oggdemux + * + * This element decodes a Vorbis stream to raw float audio. + * Vorbis is a royalty-free + * audio codec maintained by the Xiph.org + * Foundation. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! alsasink + * ]| Decode an Ogg/Vorbis. To create an Ogg/Vorbis file refer to the documentation of vorbisenc. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstvorbisdec.h" +#include +#include +#include +#include + +#include "gstvorbiscommon.h" + +GST_DEBUG_CATEGORY_EXTERN (vorbisdec_debug); +#define GST_CAT_DEFAULT vorbisdec_debug + +static GstStaticPadTemplate vorbis_dec_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_VORBIS_DEC_SRC_CAPS); + +static GstStaticPadTemplate vorbis_dec_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-vorbis") + ); + +GST_BOILERPLATE (GST_VORBIS_DEC_GLIB_TYPE_NAME, gst_vorbis_dec, GstElement, + GST_TYPE_ELEMENT); + +static void vorbis_dec_finalize (GObject * object); +static gboolean vorbis_dec_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn vorbis_dec_chain (GstPad * pad, GstBuffer * buffer); +static GstFlowReturn vorbis_dec_chain_forward (GstVorbisDec * vd, + gboolean discont, GstBuffer * buffer); +static GstFlowReturn vorbis_dec_chain_reverse (GstVorbisDec * vd, + gboolean discont, GstBuffer * buf); +static GstStateChangeReturn vorbis_dec_change_state (GstElement * element, + GstStateChange transition); + +static gboolean vorbis_dec_src_event (GstPad * pad, GstEvent * event); +static gboolean vorbis_dec_src_query (GstPad * pad, GstQuery * query); +static gboolean vorbis_dec_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); + +static gboolean vorbis_dec_sink_query (GstPad * pad, GstQuery * query); + +static void +gst_vorbis_dec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstPadTemplate *src_template, *sink_template; + + src_template = gst_static_pad_template_get (&vorbis_dec_src_factory); + gst_element_class_add_pad_template (element_class, src_template); + + sink_template = gst_static_pad_template_get (&vorbis_dec_sink_factory); + gst_element_class_add_pad_template (element_class, sink_template); + + gst_element_class_set_details_simple (element_class, + "Vorbis audio decoder", "Codec/Decoder/Audio", + GST_VORBIS_DEC_DESCRIPTION, + "Benjamin Otte , Chris Lord "); +} + +static void +gst_vorbis_dec_class_init (GstVorbisDecClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->finalize = vorbis_dec_finalize; + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (vorbis_dec_change_state); +} + +static const GstQueryType * +vorbis_get_query_types (GstPad * pad) +{ + static const GstQueryType vorbis_dec_src_query_types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + GST_QUERY_CONVERT, + 0 + }; + + return vorbis_dec_src_query_types; +} + +static void +gst_vorbis_dec_init (GstVorbisDec * dec, GstVorbisDecClass * g_class) +{ + dec->sinkpad = gst_pad_new_from_static_template (&vorbis_dec_sink_factory, + "sink"); + + gst_pad_set_event_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (vorbis_dec_sink_event)); + gst_pad_set_chain_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (vorbis_dec_chain)); + gst_pad_set_query_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (vorbis_dec_sink_query)); + gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); + + dec->srcpad = gst_pad_new_from_static_template (&vorbis_dec_src_factory, + "src"); + + gst_pad_set_event_function (dec->srcpad, + GST_DEBUG_FUNCPTR (vorbis_dec_src_event)); + gst_pad_set_query_type_function (dec->srcpad, + GST_DEBUG_FUNCPTR (vorbis_get_query_types)); + gst_pad_set_query_function (dec->srcpad, + GST_DEBUG_FUNCPTR (vorbis_dec_src_query)); + gst_pad_use_fixed_caps (dec->srcpad); + gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); + + dec->queued = NULL; + dec->pendingevents = NULL; + dec->taglist = NULL; +} + +static void +vorbis_dec_finalize (GObject * object) +{ + /* Release any possibly allocated libvorbis data. + * _clear functions can safely be called multiple times + */ + GstVorbisDec *vd = GST_VORBIS_DEC (object); + +#ifndef USE_TREMOLO + vorbis_block_clear (&vd->vb); +#endif + + vorbis_dsp_clear (&vd->vd); + vorbis_comment_clear (&vd->vc); + vorbis_info_clear (&vd->vi); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_vorbis_dec_reset (GstVorbisDec * dec) +{ + dec->last_timestamp = GST_CLOCK_TIME_NONE; + dec->discont = TRUE; + dec->seqnum = gst_util_seqnum_next (); + gst_segment_init (&dec->segment, GST_FORMAT_TIME); + + g_list_foreach (dec->queued, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->queued); + dec->queued = NULL; + g_list_foreach (dec->gather, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->gather); + dec->gather = NULL; + g_list_foreach (dec->decode, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->decode); + dec->decode = NULL; + g_list_foreach (dec->pendingevents, (GFunc) gst_mini_object_unref, NULL); + g_list_free (dec->pendingevents); + dec->pendingevents = NULL; + + if (dec->taglist) + gst_tag_list_free (dec->taglist); + dec->taglist = NULL; +} + + +static gboolean +vorbis_dec_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstVorbisDec *dec; + guint64 scale = 1; + + if (src_format == *dest_format) { + *dest_value = src_value; + return TRUE; + } + + dec = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + + if (!dec->initialized) + goto no_header; + + if (dec->sinkpad == pad && + (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) + goto no_format; + + switch (src_format) { + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = dec->width * dec->vi.channels; + case GST_FORMAT_DEFAULT: + *dest_value = + scale * gst_util_uint64_scale_int (src_value, dec->vi.rate, + GST_SECOND); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = src_value * dec->width * dec->vi.channels; + break; + case GST_FORMAT_TIME: + *dest_value = + gst_util_uint64_scale_int (src_value, GST_SECOND, dec->vi.rate); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = src_value / (dec->width * dec->vi.channels); + break; + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, + dec->vi.rate * dec->width * dec->vi.channels); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +no_header: + { + GST_DEBUG_OBJECT (dec, "no header packets received"); + res = FALSE; + goto done; + } +no_format: + { + GST_DEBUG_OBJECT (dec, "formats unsupported"); + res = FALSE; + goto done; + } +} + +static gboolean +vorbis_dec_src_query (GstPad * pad, GstQuery * query) +{ + GstVorbisDec *dec; + gboolean res = FALSE; + + dec = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + if (G_UNLIKELY (dec == NULL)) + return FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 value; + GstFormat format; + gint64 time; + + gst_query_parse_position (query, &format, NULL); + + /* we start from the last seen time */ + time = dec->last_timestamp; + /* correct for the segment values */ + time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time); + + GST_LOG_OBJECT (dec, + "query %p: our time: %" GST_TIME_FORMAT, query, GST_TIME_ARGS (time)); + + /* and convert to the final format */ + if (!(res = + vorbis_dec_convert (pad, GST_FORMAT_TIME, time, &format, &value))) + goto error; + + gst_query_set_position (query, format, value); + + GST_LOG_OBJECT (dec, + "query %p: we return %" G_GINT64_FORMAT " (format %u)", query, value, + format); + + break; + } + case GST_QUERY_DURATION: + { + res = gst_pad_peer_query (dec->sinkpad, query); + if (!res) + goto error; + + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val))) + goto error; + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +error: + { + GST_WARNING_OBJECT (dec, "error handling query"); + goto done; + } +} + +static gboolean +vorbis_dec_sink_query (GstPad * pad, GstQuery * query) +{ + GstVorbisDec *dec; + gboolean res; + + dec = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + vorbis_dec_convert (pad, src_fmt, src_val, &dest_fmt, &dest_val))) + goto error; + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +error: + { + GST_DEBUG_OBJECT (dec, "error converting value"); + goto done; + } +} + +static gboolean +vorbis_dec_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstVorbisDec *dec; + + dec = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + if (G_UNLIKELY (dec == NULL)) { + gst_event_unref (event); + return FALSE; + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstFormat format, tformat; + gdouble rate; + GstEvent *real_seek; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + gint64 cur, stop; + gint64 tcur, tstop; + guint32 seqnum; + + gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, + &stop_type, &stop); + seqnum = gst_event_get_seqnum (event); + gst_event_unref (event); + + /* First bring the requested format to time */ + tformat = GST_FORMAT_TIME; + if (!(res = vorbis_dec_convert (pad, format, cur, &tformat, &tcur))) + goto convert_error; + if (!(res = vorbis_dec_convert (pad, format, stop, &tformat, &tstop))) + goto convert_error; + + /* then seek with time on the peer */ + real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, + flags, cur_type, tcur, stop_type, tstop); + gst_event_set_seqnum (real_seek, seqnum); + + res = gst_pad_push_event (dec->sinkpad, real_seek); + break; + } + default: + res = gst_pad_push_event (dec->sinkpad, event); + break; + } +done: + gst_object_unref (dec); + + return res; + + /* ERRORS */ +convert_error: + { + GST_DEBUG_OBJECT (dec, "cannot convert start/stop for seek"); + goto done; + } +} + +static gboolean +vorbis_dec_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstVorbisDec *dec; + + dec = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + + GST_LOG_OBJECT (dec, "handling event"); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + if (dec->segment.rate < 0.0) + vorbis_dec_chain_reverse (dec, TRUE, NULL); + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_FLUSH_START: + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + /* here we must clean any state in the decoder */ +#ifdef HAVE_VORBIS_SYNTHESIS_RESTART + vorbis_synthesis_restart (&dec->vd); +#endif + gst_vorbis_dec_reset (dec); + ret = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + gboolean update; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + /* we need time for now */ + if (format != GST_FORMAT_TIME) + goto newseg_wrong_format; + + GST_DEBUG_OBJECT (dec, + "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, + update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (time)); + + /* now configure the values */ + gst_segment_set_newsegment_full (&dec->segment, update, + rate, arate, format, start, stop, time); + dec->seqnum = gst_event_get_seqnum (event); + + if (dec->initialized) + /* and forward */ + ret = gst_pad_push_event (dec->srcpad, event); + else { + /* store it to send once we're initialized */ + dec->pendingevents = g_list_append (dec->pendingevents, event); + ret = TRUE; + } + break; + } + case GST_EVENT_TAG: + { + if (dec->initialized) + /* and forward */ + ret = gst_pad_push_event (dec->srcpad, event); + else { + /* store it to send once we're initialized */ + dec->pendingevents = g_list_append (dec->pendingevents, event); + ret = TRUE; + } + break; + } + default: + ret = gst_pad_push_event (dec->srcpad, event); + break; + } +done: + gst_object_unref (dec); + + return ret; + + /* ERRORS */ +newseg_wrong_format: + { + GST_DEBUG_OBJECT (dec, "received non TIME newsegment"); + goto done; + } +} + +static GstFlowReturn +vorbis_handle_identification_packet (GstVorbisDec * vd) +{ + GstCaps *caps; + const GstAudioChannelPosition *pos = NULL; + gint width = GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH; + + switch (vd->vi.channels) { + case 1: + case 2: + /* nothing */ + break; + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + pos = gst_vorbis_channel_positions[vd->vi.channels - 1]; + break; + default:{ + gint i; + GstAudioChannelPosition *posn = + g_new (GstAudioChannelPosition, vd->vi.channels); + + GST_ELEMENT_WARNING (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("Using NONE channel layout for more than 8 channels")); + + for (i = 0; i < vd->vi.channels; i++) + posn[i] = GST_AUDIO_CHANNEL_POSITION_NONE; + + pos = posn; + } + } + + /* negotiate width with downstream */ + caps = gst_pad_get_allowed_caps (vd->srcpad); + if (caps) { + if (!gst_caps_is_empty (caps)) { + GstStructure *s; + + s = gst_caps_get_structure (caps, 0); + /* template ensures 16 or 32 */ + gst_structure_get_int (s, "width", &width); + + GST_INFO_OBJECT (vd, "using %s with %d channels and %d bit audio depth", + gst_structure_get_name (s), vd->vi.channels, width); + } + gst_caps_unref (caps); + } + vd->width = width >> 3; + + /* select a copy_samples function, this way we can have specialized versions + * for mono/stereo and avoid the depth switch in tremor case */ + vd->copy_samples = get_copy_sample_func (vd->vi.channels, vd->width); + + caps = gst_caps_copy (gst_pad_get_pad_template_caps (vd->srcpad)); + gst_caps_set_simple (caps, "rate", G_TYPE_INT, vd->vi.rate, + "channels", G_TYPE_INT, vd->vi.channels, + "width", G_TYPE_INT, width, NULL); + + if (pos) { + gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); + } + + if (vd->vi.channels > 8) { + g_free ((GstAudioChannelPosition *) pos); + } + + gst_pad_set_caps (vd->srcpad, caps); + gst_caps_unref (caps); + + return GST_FLOW_OK; +} + +static GstFlowReturn +vorbis_handle_comment_packet (GstVorbisDec * vd, ogg_packet * packet) +{ + guint bitrate = 0; + gchar *encoder = NULL; + GstTagList *list, *old_list; + GstBuffer *buf; + + GST_DEBUG_OBJECT (vd, "parsing comment packet"); + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = gst_ogg_packet_data (packet); + GST_BUFFER_SIZE (buf) = gst_ogg_packet_size (packet); + + list = + gst_tag_list_from_vorbiscomment_buffer (buf, (guint8 *) "\003vorbis", 7, + &encoder); + + old_list = vd->taglist; + vd->taglist = gst_tag_list_merge (vd->taglist, list, GST_TAG_MERGE_REPLACE); + + if (old_list) + gst_tag_list_free (old_list); + gst_tag_list_free (list); + gst_buffer_unref (buf); + + if (!vd->taglist) { + GST_ERROR_OBJECT (vd, "couldn't decode comments"); + vd->taglist = gst_tag_list_new (); + } + if (encoder) { + if (encoder[0]) + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER, encoder, NULL); + g_free (encoder); + } + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_ENCODER_VERSION, vd->vi.version, + GST_TAG_AUDIO_CODEC, "Vorbis", NULL); + if (vd->vi.bitrate_nominal > 0 && vd->vi.bitrate_nominal <= 0x7FFFFFFF) { + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_NOMINAL_BITRATE, (guint) vd->vi.bitrate_nominal, NULL); + bitrate = vd->vi.bitrate_nominal; + } + if (vd->vi.bitrate_upper > 0 && vd->vi.bitrate_upper <= 0x7FFFFFFF) { + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MAXIMUM_BITRATE, (guint) vd->vi.bitrate_upper, NULL); + if (!bitrate) + bitrate = vd->vi.bitrate_upper; + } + if (vd->vi.bitrate_lower > 0 && vd->vi.bitrate_lower <= 0x7FFFFFFF) { + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MINIMUM_BITRATE, (guint) vd->vi.bitrate_lower, NULL); + if (!bitrate) + bitrate = vd->vi.bitrate_lower; + } + if (bitrate) { + gst_tag_list_add (vd->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, (guint) bitrate, NULL); + } + + if (vd->initialized) { + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (vd), vd->srcpad, + vd->taglist); + vd->taglist = NULL; + } else { + /* Only post them as messages for the time being. * + * They will be pushed on the pad once the decoder is initialized */ + gst_element_post_message (GST_ELEMENT_CAST (vd), + gst_message_new_tag (GST_OBJECT (vd), gst_tag_list_copy (vd->taglist))); + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +vorbis_handle_type_packet (GstVorbisDec * vd) +{ + GList *walk; + gint res; + + g_assert (vd->initialized == FALSE); + +#ifdef USE_TREMOLO + if (G_UNLIKELY ((res = vorbis_dsp_init (&vd->vd, &vd->vi)))) + goto synthesis_init_error; +#else + if (G_UNLIKELY ((res = vorbis_synthesis_init (&vd->vd, &vd->vi)))) + goto synthesis_init_error; + + if (G_UNLIKELY ((res = vorbis_block_init (&vd->vd, &vd->vb)))) + goto block_init_error; +#endif + + vd->initialized = TRUE; + + if (vd->pendingevents) { + for (walk = vd->pendingevents; walk; walk = g_list_next (walk)) + gst_pad_push_event (vd->srcpad, GST_EVENT_CAST (walk->data)); + g_list_free (vd->pendingevents); + vd->pendingevents = NULL; + } + + if (vd->taglist) { + /* The tags have already been sent on the bus as messages. */ + gst_pad_push_event (vd->srcpad, gst_event_new_tag (vd->taglist)); + vd->taglist = NULL; + } + return GST_FLOW_OK; + + /* ERRORS */ +synthesis_init_error: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("couldn't initialize synthesis (%d)", res)); + return GST_FLOW_ERROR; + } +block_init_error: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("couldn't initialize block (%d)", res)); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +vorbis_handle_header_packet (GstVorbisDec * vd, ogg_packet * packet) +{ + GstFlowReturn res; + gint ret; + + GST_DEBUG_OBJECT (vd, "parsing header packet"); + + /* Packetno = 0 if the first byte is exactly 0x01 */ + packet->b_o_s = ((gst_ogg_packet_data (packet))[0] == 0x1) ? 1 : 0; + +#ifdef USE_TREMOLO + if ((ret = vorbis_dsp_headerin (&vd->vi, &vd->vc, packet))) +#else + if ((ret = vorbis_synthesis_headerin (&vd->vi, &vd->vc, packet))) +#endif + goto header_read_error; + + switch ((gst_ogg_packet_data (packet))[0]) { + case 0x01: + res = vorbis_handle_identification_packet (vd); + break; + case 0x03: + res = vorbis_handle_comment_packet (vd, packet); + break; + case 0x05: + res = vorbis_handle_type_packet (vd); + break; + default: + /* ignore */ + g_warning ("unknown vorbis header packet found"); + res = GST_FLOW_OK; + break; + } + return res; + + /* ERRORS */ +header_read_error: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("couldn't read header packet (%d)", ret)); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +vorbis_dec_push_forward (GstVorbisDec * dec, GstBuffer * buf) +{ + GstFlowReturn result; + + /* clip */ + if (!(buf = gst_audio_buffer_clip (buf, &dec->segment, dec->vi.rate, + dec->vi.channels * dec->width))) { + GST_LOG_OBJECT (dec, "clipped buffer"); + return GST_FLOW_OK; + } + + if (dec->discont) { + GST_LOG_OBJECT (dec, "setting DISCONT"); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + dec->discont = FALSE; + } + + GST_DEBUG_OBJECT (dec, + "pushing time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + + result = gst_pad_push (dec->srcpad, buf); + + return result; +} + +static GstFlowReturn +vorbis_dec_push_reverse (GstVorbisDec * dec, GstBuffer * buf) +{ + GstFlowReturn result = GST_FLOW_OK; + + dec->queued = g_list_prepend (dec->queued, buf); + + return result; +} + +static void +vorbis_do_timestamps (GstVorbisDec * vd, GstBuffer * buf, gboolean reverse, + GstClockTime timestamp, GstClockTime duration) +{ + /* interpolate reverse */ + if (vd->last_timestamp != -1 && duration != -1 && reverse) + vd->last_timestamp -= duration; + + /* take buffer timestamp, use interpolated timestamp otherwise */ + if (timestamp != -1) + vd->last_timestamp = timestamp; + else + timestamp = vd->last_timestamp; + + /* interpolate forwards */ + if (vd->last_timestamp != -1 && duration != -1 && !reverse) + vd->last_timestamp += duration; + + GST_LOG_OBJECT (vd, + "keeping timestamp %" GST_TIME_FORMAT " ts %" GST_TIME_FORMAT " dur %" + GST_TIME_FORMAT, GST_TIME_ARGS (vd->last_timestamp), + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (duration)); + + if (buf) { + GST_BUFFER_TIMESTAMP (buf) = timestamp; + GST_BUFFER_DURATION (buf) = duration; + } +} + +static GstFlowReturn +vorbis_handle_data_packet (GstVorbisDec * vd, ogg_packet * packet, + GstClockTime timestamp, GstClockTime duration) +{ +#ifdef USE_TREMOLO + vorbis_sample_t *pcm; +#else + vorbis_sample_t **pcm; +#endif + guint sample_count; + GstBuffer *out = NULL; + GstFlowReturn result; + gint size; + + if (G_UNLIKELY (!vd->initialized)) + goto not_initialized; + + /* normal data packet */ + /* FIXME, we can skip decoding if the packet is outside of the + * segment, this is however not very trivial as we need a previous + * packet to decode the current one so we must be carefull not to + * throw away too much. For now we decode everything and clip right + * before pushing data. */ + +#ifdef USE_TREMOLO + if (G_UNLIKELY (vorbis_dsp_synthesis (&vd->vd, packet, 1))) + goto could_not_read; +#else + if (G_UNLIKELY (vorbis_synthesis (&vd->vb, packet))) + goto could_not_read; + + if (G_UNLIKELY (vorbis_synthesis_blockin (&vd->vd, &vd->vb) < 0)) + goto not_accepted; +#endif + + /* assume all goes well here */ + result = GST_FLOW_OK; + + /* count samples ready for reading */ +#ifdef USE_TREMOLO + if ((sample_count = vorbis_dsp_pcmout (&vd->vd, NULL, 0)) == 0) +#else + if ((sample_count = vorbis_synthesis_pcmout (&vd->vd, NULL)) == 0) +#endif + goto done; + + size = sample_count * vd->vi.channels * vd->width; + GST_LOG_OBJECT (vd, "%d samples ready for reading, size %d", sample_count, + size); + + /* alloc buffer for it */ + result = + gst_pad_alloc_buffer_and_set_caps (vd->srcpad, GST_BUFFER_OFFSET_NONE, + size, GST_PAD_CAPS (vd->srcpad), &out); + if (G_UNLIKELY (result != GST_FLOW_OK)) + goto done; + + /* get samples ready for reading now, should be sample_count */ +#ifdef USE_TREMOLO + pcm = GST_BUFFER_DATA (out); + if (G_UNLIKELY ((vorbis_dsp_pcmout (&vd->vd, pcm, sample_count)) != sample_count)) +#else + if (G_UNLIKELY ((vorbis_synthesis_pcmout (&vd->vd, &pcm)) != sample_count)) +#endif + goto wrong_samples; + +#ifndef USE_TREMOLO + /* copy samples in buffer */ + vd->copy_samples ((vorbis_sample_t *) GST_BUFFER_DATA (out), pcm, + sample_count, vd->vi.channels, vd->width); +#endif + + GST_LOG_OBJECT (vd, "setting output size to %d", size); + GST_BUFFER_SIZE (out) = size; + + /* this should not overflow */ + if (duration == -1) + duration = sample_count * GST_SECOND / vd->vi.rate; + + vorbis_do_timestamps (vd, out, FALSE, timestamp, duration); + + if (vd->segment.rate >= 0.0) + result = vorbis_dec_push_forward (vd, out); + else + result = vorbis_dec_push_reverse (vd, out); + +done: + if (out == NULL) { + /* no output, still keep track of timestamps */ + vorbis_do_timestamps (vd, NULL, FALSE, timestamp, duration); + } + +#ifdef USE_TREMOLO + vorbis_dsp_read (&vd->vd, sample_count); +#else + vorbis_synthesis_read (&vd->vd, sample_count); +#endif + + return result; + + /* ERRORS */ +not_initialized: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("no header sent yet")); + return GST_FLOW_ERROR; + } +could_not_read: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("couldn't read data packet")); + return GST_FLOW_ERROR; + } +not_accepted: + { + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("vorbis decoder did not accept data packet")); + return GST_FLOW_ERROR; + } +wrong_samples: + { + gst_buffer_unref (out); + GST_ELEMENT_ERROR (GST_ELEMENT (vd), STREAM, DECODE, + (NULL), ("vorbis decoder reported wrong number of samples")); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +vorbis_dec_decode_buffer (GstVorbisDec * vd, GstBuffer * buffer) +{ + ogg_packet *packet; + ogg_packet_wrapper packet_wrapper; + GstFlowReturn result = GST_FLOW_OK; + + /* make ogg_packet out of the buffer */ + gst_ogg_packet_wrapper_from_buffer (&packet_wrapper, buffer); + packet = gst_ogg_packet_from_wrapper (&packet_wrapper); + /* set some more stuff */ + packet->granulepos = -1; + packet->packetno = 0; /* we don't care */ + /* EOS does not matter, it is used in vorbis to implement clipping the last + * block of samples based on the granulepos. We clip based on segments. */ + packet->e_o_s = 0; + + GST_LOG_OBJECT (vd, "decode buffer of size %ld", packet->bytes); + + /* error out on empty header packets, but just skip empty data packets */ + if (G_UNLIKELY (packet->bytes == 0)) { + if (vd->initialized) + goto empty_buffer; + else + goto empty_header; + } + + /* switch depending on packet type */ + if ((gst_ogg_packet_data (packet))[0] & 1) { + if (vd->initialized) { + GST_WARNING_OBJECT (vd, "Already initialized, so ignoring header packet"); + goto done; + } + result = vorbis_handle_header_packet (vd, packet); + } else { + GstClockTime timestamp, duration; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + duration = GST_BUFFER_DURATION (buffer); + + result = vorbis_handle_data_packet (vd, packet, timestamp, duration); + } + +done: + return result; + +empty_buffer: + { + /* don't error out here, just ignore the buffer, it's invalid for vorbis + * but not fatal. */ + GST_WARNING_OBJECT (vd, "empty buffer received, ignoring"); + result = GST_FLOW_OK; + goto done; + } + +/* ERRORS */ +empty_header: + { + GST_ELEMENT_ERROR (vd, STREAM, DECODE, (NULL), ("empty header received")); + result = GST_FLOW_ERROR; + vd->discont = TRUE; + goto done; + } +} + +/* + * Input: + * Buffer decoding order: 7 8 9 4 5 6 3 1 2 EOS + * Discont flag: D D D D + * + * - Each Discont marks a discont in the decoding order. + * + * for vorbis, each buffer is a keyframe when we have the previous + * buffer. This means that to decode buffer 7, we need buffer 6, which + * arrives out of order. + * + * we first gather buffers in the gather queue until we get a DISCONT. We + * prepend each incomming buffer so that they are in reversed order. + * + * gather queue: 9 8 7 + * decode queue: + * output queue: + * + * When a DISCONT is received (buffer 4), we move the gather queue to the + * decode queue. This is simply done be taking the head of the gather queue + * and prepending it to the decode queue. This yields: + * + * gather queue: + * decode queue: 7 8 9 + * output queue: + * + * Then we decode each buffer in the decode queue in order and put the output + * buffer in the output queue. The first buffer (7) will not produce any output + * because it needs the previous buffer (6) which did not arrive yet. This + * yields: + * + * gather queue: + * decode queue: 7 8 9 + * output queue: 9 8 + * + * Then we remove the consumed buffers from the decode queue. Buffer 7 is not + * completely consumed, we need to keep it around for when we receive buffer + * 6. This yields: + * + * gather queue: + * decode queue: 7 + * output queue: 9 8 + * + * Then we accumulate more buffers: + * + * gather queue: 6 5 4 + * decode queue: 7 + * output queue: + * + * prepending to the decode queue on DISCONT yields: + * + * gather queue: + * decode queue: 4 5 6 7 + * output queue: + * + * after decoding and keeping buffer 4: + * + * gather queue: + * decode queue: 4 + * output queue: 7 6 5 + * + * Etc.. + */ +static GstFlowReturn +vorbis_dec_flush_decode (GstVorbisDec * dec) +{ + GstFlowReturn res = GST_FLOW_OK; + GList *walk; + + walk = dec->decode; + + GST_DEBUG_OBJECT (dec, "flushing buffers to decoder"); + + while (walk) { + GList *next; + GstBuffer *buf = GST_BUFFER_CAST (walk->data); + + GST_DEBUG_OBJECT (dec, "decoding buffer %p, ts %" GST_TIME_FORMAT, + buf, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + next = g_list_next (walk); + + /* decode buffer, prepend to output queue */ + res = vorbis_dec_decode_buffer (dec, buf); + + /* if we generated output, we can discard the buffer, else we + * keep it in the queue */ + if (dec->queued) { + GST_DEBUG_OBJECT (dec, "decoded buffer to %p", dec->queued->data); + dec->decode = g_list_delete_link (dec->decode, walk); + gst_buffer_unref (buf); + } else { + GST_DEBUG_OBJECT (dec, "buffer did not decode, keeping"); + } + walk = next; + } + while (dec->queued) { + GstBuffer *buf = GST_BUFFER_CAST (dec->queued->data); + GstClockTime timestamp, duration; + + timestamp = GST_BUFFER_TIMESTAMP (buf); + duration = GST_BUFFER_DURATION (buf); + + vorbis_do_timestamps (dec, buf, TRUE, timestamp, duration); + res = vorbis_dec_push_forward (dec, buf); + + dec->queued = g_list_delete_link (dec->queued, dec->queued); + } + return res; +} + +static GstFlowReturn +vorbis_dec_chain_reverse (GstVorbisDec * vd, gboolean discont, GstBuffer * buf) +{ + GstFlowReturn result = GST_FLOW_OK; + + /* if we have a discont, move buffers to the decode list */ + if (G_UNLIKELY (discont)) { + GST_DEBUG_OBJECT (vd, "received discont"); + while (vd->gather) { + GstBuffer *gbuf; + + gbuf = GST_BUFFER_CAST (vd->gather->data); + /* remove from the gather list */ + vd->gather = g_list_delete_link (vd->gather, vd->gather); + /* copy to decode queue */ + vd->decode = g_list_prepend (vd->decode, gbuf); + } + /* flush and decode the decode queue */ + result = vorbis_dec_flush_decode (vd); + } + + if (G_LIKELY (buf)) { + GST_DEBUG_OBJECT (vd, + "gathering buffer %p of size %u, time %" GST_TIME_FORMAT + ", dur %" GST_TIME_FORMAT, buf, GST_BUFFER_SIZE (buf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + + /* add buffer to gather queue */ + vd->gather = g_list_prepend (vd->gather, buf); + } + + return result; +} + +static GstFlowReturn +vorbis_dec_chain_forward (GstVorbisDec * vd, gboolean discont, + GstBuffer * buffer) +{ + GstFlowReturn result; + + result = vorbis_dec_decode_buffer (vd, buffer); + + gst_buffer_unref (buffer); + + return result; +} + +static GstFlowReturn +vorbis_dec_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVorbisDec *vd; + GstFlowReturn result = GST_FLOW_OK; + gboolean discont; + + vd = GST_VORBIS_DEC (gst_pad_get_parent (pad)); + + discont = GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT); + + /* resync on DISCONT */ + if (G_UNLIKELY (discont)) { + GST_DEBUG_OBJECT (vd, "received DISCONT buffer"); + vd->last_timestamp = GST_CLOCK_TIME_NONE; +#ifdef HAVE_VORBIS_SYNTHESIS_RESTART + vorbis_synthesis_restart (&vd->vd); +#endif + vd->discont = TRUE; + } + + if (vd->segment.rate >= 0.0) + result = vorbis_dec_chain_forward (vd, discont, buffer); + else + result = vorbis_dec_chain_reverse (vd, discont, buffer); + + gst_object_unref (vd); + + return result; +} + +static GstStateChangeReturn +vorbis_dec_change_state (GstElement * element, GstStateChange transition) +{ + GstVorbisDec *vd = GST_VORBIS_DEC (element); + GstStateChangeReturn res; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + vorbis_info_init (&vd->vi); + vorbis_comment_init (&vd->vc); + vd->initialized = FALSE; + gst_vorbis_dec_reset (vd); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + res = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (vd, "PAUSED -> READY, clearing vorbis structures"); + vd->initialized = FALSE; + +#ifndef USE_TREMOLO + vorbis_block_clear (&vd->vb); +#endif + + vorbis_dsp_clear (&vd->vd); + vorbis_comment_clear (&vd->vc); + vorbis_info_clear (&vd->vi); + gst_vorbis_dec_reset (vd); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return res; +} diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.h new file mode 100644 index 0000000..04e4677 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdec.h @@ -0,0 +1,96 @@ +/* -*- c-basic-offset: 2 -*- + * GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_VORBIS_DEC_H__ +#define __GST_VORBIS_DEC_H__ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gstvorbisdeclib.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VORBIS_DEC \ + (gst_vorbis_dec_get_type()) +#define GST_VORBIS_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_DEC,GstVorbisDec)) +#define GST_VORBIS_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_DEC,GstVorbisDecClass)) +#define GST_IS_VORBIS_DEC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_DEC)) +#define GST_IS_VORBIS_DEC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_DEC)) + +typedef struct _GstVorbisDec GstVorbisDec; +typedef struct _GstVorbisDecClass GstVorbisDecClass; + +/** + * GstVorbisDec: + * + * Opaque data structure. + */ +struct _GstVorbisDec { + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + vorbis_dsp_state vd; + vorbis_info vi; + vorbis_comment vc; + +#ifndef USE_TREMOLO + vorbis_block vb; +#endif + + gboolean initialized; + guint width; + + /* list of buffers that need timestamps */ + GList *queued; + /* gather/decode queues for reverse playback */ + GList *gather; + GList *decode; + + GstSegment segment; + gboolean discont; + guint32 seqnum; + + GstClockTime last_timestamp; + + GList *pendingevents; + GstTagList *taglist; + + CopySampleFunc copy_samples; +}; + +struct _GstVorbisDecClass { + GstElementClass parent_class; +}; + +GType gst_vorbis_dec_get_type(void); + +G_END_DECLS + +#endif /* __GST_VORBIS_DEC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.c new file mode 100644 index 0000000..1ddce38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.c @@ -0,0 +1,252 @@ +/* GStreamer + * Copyright (C) 2010 Mark Nauwelaerts + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * + * Tremor modifications <2006>: + * Chris Lord, OpenedHand Ltd. , http://www.o-hand.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gstvorbisdeclib.h" + +#ifndef TREMOR +/* These samples can be outside of the float -1.0 -- 1.0 range, this + * is allowed, downstream elements are supposed to clip */ +static void +copy_samples_m (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples, + gint channels, gint width) +{ + memcpy (out, in[0], samples * sizeof (float)); +} + +static void +copy_samples_s (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples, + gint channels, gint width) +{ +#ifdef GST_VORBIS_DEC_SEQUENTIAL + memcpy (out, in[0], samples * sizeof (float)); + out += samples; + memcpy (out, in[1], samples * sizeof (float)); +#else + gint j; + + for (j = 0; j < samples; j++) { + *out++ = in[0][j]; + *out++ = in[1][j]; + } +#endif +} + +static void +copy_samples (vorbis_sample_t * out, vorbis_sample_t ** in, guint samples, + gint channels, gint width) +{ +#ifdef GST_VORBIS_DEC_SEQUENTIAL + gint i; + + for (i = 0; i < channels; i++) { + memcpy (out, in[i], samples * sizeof (float)); + out += samples; + } +#else + gint i, j; + + for (j = 0; j < samples; j++) { + for (i = 0; i < channels; i++) { + *out++ = in[i][j]; + } + } +#endif +} + +CopySampleFunc +get_copy_sample_func (gint channels, gint width) +{ + CopySampleFunc f = NULL; + + g_assert (width == 4); + + switch (channels) { + case 1: + f = copy_samples_m; + break; + case 2: + f = copy_samples_s; + break; + default: + f = copy_samples; + break; + } + + return f; +} + +#else + +/* Taken from Tremor, misc.h */ +#ifdef _ARM_ASSEM_ +static inline ogg_int32_t +CLIP_TO_15 (ogg_int32_t x) +{ + int tmp; + asm volatile ("subs %1, %0, #32768\n\t" + "movpl %0, #0x7f00\n\t" + "orrpl %0, %0, #0xff\n" + "adds %1, %0, #32768\n\t" + "movmi %0, #0x8000":"+r" (x), "=r" (tmp) + ::"cc"); + + return (x); +} +#else +static inline ogg_int32_t +CLIP_TO_15 (ogg_int32_t x) +{ + int ret = x; + + ret -= ((x <= 32767) - 1) & (x - 32767); + ret -= ((x >= -32768) - 1) & (x + 32768); + return (ret); +} +#endif + +static void +copy_samples_32_m (vorbis_sample_t * _out, vorbis_sample_t ** _in, + guint samples, gint channels, gint width) +{ + gint32 *out = (gint32 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint j; + + for (j = 0; j < samples; j++) { + *out++ = CLIP_TO_15 (in[0][j] >> 9); + } +} + +static void +copy_samples_32_s (vorbis_sample_t * _out, vorbis_sample_t ** _in, + guint samples, gint channels, gint width) +{ + gint32 *out = (gint32 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint j; + + for (j = 0; j < samples; j++) { + *out++ = CLIP_TO_15 (in[0][j] >> 9); + *out++ = CLIP_TO_15 (in[1][j] >> 9); + } +} + +static void +copy_samples_32 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples, + gint channels, gint width) +{ + gint32 *out = (gint32 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint i, j; + + for (j = 0; j < samples; j++) { + for (i = 0; i < channels; i++) { + *out++ = CLIP_TO_15 (in[i][j] >> 9); + } + } +} + +static void +copy_samples_16_m (vorbis_sample_t * _out, vorbis_sample_t ** _in, + guint samples, gint channels, gint width) +{ + gint16 *out = (gint16 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint j; + + for (j = 0; j < samples; j++) { + *out++ = CLIP_TO_15 (in[0][j] >> 9); + } +} + +static void +copy_samples_16_s (vorbis_sample_t * _out, vorbis_sample_t ** _in, + guint samples, gint channels, gint width) +{ + gint16 *out = (gint16 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint j; + + for (j = 0; j < samples; j++) { + *out++ = CLIP_TO_15 (in[0][j] >> 9); + *out++ = CLIP_TO_15 (in[1][j] >> 9); + } +} + +static void +copy_samples_16 (vorbis_sample_t * _out, vorbis_sample_t ** _in, guint samples, + gint channels, gint width) +{ + gint16 *out = (gint16 *) _out; + ogg_int32_t **in = (ogg_int32_t **) _in; + gint i, j; + + for (j = 0; j < samples; j++) { + for (i = 0; i < channels; i++) { + *out++ = CLIP_TO_15 (in[i][j] >> 9); + } + } +} + +CopySampleFunc +get_copy_sample_func (gint channels, gint width) +{ + CopySampleFunc f = NULL; + + if (width == 4) { + switch (channels) { + case 1: + f = copy_samples_32_m; + break; + case 2: + f = copy_samples_32_s; + break; + default: + f = copy_samples_32; + break; + } + } else if (width == 2) { + switch (channels) { + case 1: + f = copy_samples_16_m; + break; + case 2: + f = copy_samples_16_s; + break; + default: + f = copy_samples_16; + break; + } + } else { + g_assert_not_reached (); + } + return f; +} + +#endif diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.h new file mode 100644 index 0000000..ca00af9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisdeclib.h @@ -0,0 +1,164 @@ +/* GStreamer + * Copyright (C) 2010 Mark Nauwelaerts + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * + * Tremor modifications <2006>: + * Chris Lord, OpenedHand Ltd. , http://www.o-hand.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_VORBIS_DEC_LIB_H__ +#define __GST_VORBIS_DEC_LIB_H__ + +#include + +#ifndef TREMOR + +#include + +typedef float vorbis_sample_t; +typedef ogg_packet ogg_packet_wrapper; + +#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to float audio" + +#define GST_VORBIS_DEC_SRC_CAPS \ + GST_STATIC_CAPS ("audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 256 ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32") + +#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH (32) + +#define GST_VORBIS_DEC_GLIB_TYPE_NAME GstVorbisDec + +static inline guint8 * +gst_ogg_packet_data (ogg_packet * p) +{ + return (guint8 *) p->packet; +} + +static inline gint +gst_ogg_packet_size (ogg_packet * p) +{ + return p->bytes; +} + +static inline void +gst_ogg_packet_wrapper_from_buffer (ogg_packet * packet, GstBuffer * buffer) +{ + packet->packet = GST_BUFFER_DATA (buffer); + packet->bytes = GST_BUFFER_SIZE (buffer); +} + +static inline ogg_packet * +gst_ogg_packet_from_wrapper (ogg_packet_wrapper * packet) +{ + return packet; +} + +#else + +#ifdef USE_TREMOLO + #include + #include + typedef ogg_int16_t vorbis_sample_t; +#else + #include + typedef ogg_int32_t vorbis_sample_t; +#endif + +typedef struct _ogg_packet_wrapper ogg_packet_wrapper; + +struct _ogg_packet_wrapper { + ogg_packet packet; + ogg_reference ref; + ogg_buffer buf; +}; + +#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to integer audio" + +#define GST_VORBIS_DEC_SRC_CAPS \ + GST_STATIC_CAPS ("audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 6 ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 16, 32 }, " \ + "depth = (int) 16, " \ + "signed = (boolean) true") + +#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH (16) + +/* we need a different type name here */ +#define GST_VORBIS_DEC_GLIB_TYPE_NAME GstIVorbisDec + +/* and still have it compile */ +typedef struct _GstVorbisDec GstIVorbisDec; +typedef struct _GstVorbisDecClass GstIVorbisDecClass; + +/* compensate minor variation */ +#define vorbis_synthesis(a, b) vorbis_synthesis (a, b, 1) + +static inline guint8 * +gst_ogg_packet_data (ogg_packet * p) +{ + return (guint8 *) p->packet->buffer->data; +} + +static inline gint +gst_ogg_packet_size (ogg_packet * p) +{ + return p->packet->buffer->size; +} + +static inline void +gst_ogg_packet_wrapper_from_buffer (ogg_packet_wrapper * packet, + GstBuffer * buffer) +{ + ogg_reference *ref = &packet->ref; + ogg_buffer *buf = &packet->buf; + + buf->data = GST_BUFFER_DATA (buffer); + buf->size = GST_BUFFER_SIZE (buffer); + buf->refcount = 1; + buf->ptr.owner = NULL; + buf->ptr.next = NULL; + + ref->buffer = buf; + ref->begin = 0; + ref->length = buf->size; + ref->next = NULL; + + packet->packet.packet = ref; + packet->packet.bytes = ref->length; +} + +static inline ogg_packet * +gst_ogg_packet_from_wrapper (ogg_packet_wrapper * packet) +{ + return &(packet->packet); +} + +#endif + +typedef void (*CopySampleFunc)(vorbis_sample_t *out, vorbis_sample_t **in, + guint samples, gint channels, gint width); + +CopySampleFunc get_copy_sample_func (gint channels, gint width); + +#endif /* __GST_VORBIS_DEC_LIB_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.c new file mode 100644 index 0000000..9cdf484 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.c @@ -0,0 +1,1427 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-vorbisenc + * @see_also: vorbisdec, oggmux + * + * This element encodes raw float audio into a Vorbis stream. + * Vorbis is a royalty-free + * audio codec maintained by the Xiph.org + * Foundation. + * + * + * Example pipelines + * |[ + * gst-launch -v audiotestsrc wave=sine num-buffers=100 ! audioconvert ! vorbisenc ! oggmux ! filesink location=sine.ogg + * ]| Encode a test sine signal to Ogg/Vorbis. Note that the resulting file + * will be really small because a sine signal compresses very well. + * |[ + * gst-launch -v alsasrc ! audioconvert ! vorbisenc ! oggmux ! filesink location=alsasrc.ogg + * ]| Record from a sound card using ALSA and encode to Ogg/Vorbis. + * + * + * Last reviewed on 2006-03-01 (0.10.4) + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include +#include +#include "gstvorbisenc.h" + +#include "gstvorbiscommon.h" + +GST_DEBUG_CATEGORY_EXTERN (vorbisenc_debug); +#define GST_CAT_DEFAULT vorbisenc_debug + +static GstStaticPadTemplate vorbis_enc_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-float, " + "rate = (int) [ 1, 200000 ], " + "channels = (int) [ 1, 256 ], " "endianness = (int) BYTE_ORDER, " + "width = (int) 32") + ); + +static GstStaticPadTemplate vorbis_enc_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-vorbis") + ); + +enum +{ + ARG_0, + ARG_MAX_BITRATE, + ARG_BITRATE, + ARG_MIN_BITRATE, + ARG_QUALITY, + ARG_MANAGED, + ARG_LAST_MESSAGE +}; + +static GstFlowReturn gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc); + +/* this function takes into account the granulepos_offset and the subgranule + * time offset */ +static GstClockTime +granulepos_to_timestamp_offset (GstVorbisEnc * vorbisenc, + ogg_int64_t granulepos) +{ + if (granulepos >= 0) + return gst_util_uint64_scale ((guint64) granulepos + + vorbisenc->granulepos_offset, GST_SECOND, vorbisenc->frequency) + + vorbisenc->subgranule_offset; + return GST_CLOCK_TIME_NONE; +} + +/* this function does a straight granulepos -> timestamp conversion */ +static GstClockTime +granulepos_to_timestamp (GstVorbisEnc * vorbisenc, ogg_int64_t granulepos) +{ + if (granulepos >= 0) + return gst_util_uint64_scale ((guint64) granulepos, + GST_SECOND, vorbisenc->frequency); + return GST_CLOCK_TIME_NONE; +} + +#define MAX_BITRATE_DEFAULT -1 +#define BITRATE_DEFAULT -1 +#define MIN_BITRATE_DEFAULT -1 +#define QUALITY_DEFAULT 0.3 +#define LOWEST_BITRATE 6000 /* lowest allowed for a 8 kHz stream */ +#define HIGHEST_BITRATE 250001 /* highest allowed for a 44 kHz stream */ + +static gboolean gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc); + +static void gst_vorbis_enc_dispose (GObject * object); +static void gst_vorbis_enc_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_vorbis_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static GstStateChangeReturn gst_vorbis_enc_change_state (GstElement * element, + GstStateChange transition); +static void gst_vorbis_enc_add_interfaces (GType vorbisenc_type); + +GST_BOILERPLATE_FULL (GstVorbisEnc, gst_vorbis_enc, GstElement, + GST_TYPE_ELEMENT, gst_vorbis_enc_add_interfaces); + +static void +gst_vorbis_enc_add_interfaces (GType vorbisenc_type) +{ + static const GInterfaceInfo tag_setter_info = { NULL, NULL, NULL }; + static const GInterfaceInfo preset_info = { NULL, NULL, NULL }; + + g_type_add_interface_static (vorbisenc_type, GST_TYPE_TAG_SETTER, + &tag_setter_info); + g_type_add_interface_static (vorbisenc_type, GST_TYPE_PRESET, &preset_info); +} + +static void +gst_vorbis_enc_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstPadTemplate *src_template, *sink_template; + + + src_template = gst_static_pad_template_get (&vorbis_enc_src_factory); + gst_element_class_add_pad_template (element_class, src_template); + + sink_template = gst_static_pad_template_get (&vorbis_enc_sink_factory); + gst_element_class_add_pad_template (element_class, sink_template); + gst_element_class_set_details_simple (element_class, + "Vorbis audio encoder", "Codec/Encoder/Audio", + "Encodes audio in Vorbis format", + "Monty , " "Wim Taymans "); +} + +static void +gst_vorbis_enc_class_init (GstVorbisEncClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_vorbis_enc_set_property; + gobject_class->get_property = gst_vorbis_enc_get_property; + gobject_class->dispose = gst_vorbis_enc_dispose; + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MAX_BITRATE, + g_param_spec_int ("max-bitrate", "Maximum Bitrate", + "Specify a maximum bitrate (in bps). Useful for streaming " + "applications. (-1 == disabled)", + -1, HIGHEST_BITRATE, MAX_BITRATE_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BITRATE, + g_param_spec_int ("bitrate", "Target Bitrate", + "Attempt to encode at a bitrate averaging this (in bps). " + "This uses the bitrate management engine, and is not recommended for most users. " + "Quality is a better alternative. (-1 == disabled)", -1, + HIGHEST_BITRATE, BITRATE_DEFAULT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MIN_BITRATE, + g_param_spec_int ("min-bitrate", "Minimum Bitrate", + "Specify a minimum bitrate (in bps). Useful for encoding for a " + "fixed-size channel. (-1 == disabled)", -1, HIGHEST_BITRATE, + MIN_BITRATE_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY, + g_param_spec_float ("quality", "Quality", + "Specify quality instead of specifying a particular bitrate.", -0.1, + 1.0, QUALITY_DEFAULT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MANAGED, + g_param_spec_boolean ("managed", "Managed", + "Enable bitrate management engine", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_LAST_MESSAGE, + g_param_spec_string ("last-message", "last-message", + "The last status message", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_vorbis_enc_change_state); +} + +static void +gst_vorbis_enc_dispose (GObject * object) +{ + GstVorbisEnc *vorbisenc = GST_VORBISENC (object); + + if (vorbisenc->sinkcaps) { + gst_caps_unref (vorbisenc->sinkcaps); + vorbisenc->sinkcaps = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static GstCaps * +gst_vorbis_enc_generate_sink_caps (void) +{ + GstCaps *caps = gst_caps_new_empty (); + int i, c; + + gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float", + "rate", GST_TYPE_INT_RANGE, 1, 200000, + "channels", G_TYPE_INT, 1, + "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, + NULL)); + + gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float", + "rate", GST_TYPE_INT_RANGE, 1, 200000, + "channels", G_TYPE_INT, 2, + "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, + NULL)); + + for (i = 3; i <= 8; i++) { + GValue chanpos = { 0 }; + GValue pos = { 0 }; + GstStructure *structure; + + g_value_init (&chanpos, GST_TYPE_ARRAY); + g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); + + for (c = 0; c < i; c++) { + g_value_set_enum (&pos, gst_vorbis_channel_positions[i - 1][c]); + gst_value_array_append_value (&chanpos, &pos); + } + g_value_unset (&pos); + + structure = gst_structure_new ("audio/x-raw-float", + "rate", GST_TYPE_INT_RANGE, 1, 200000, + "channels", G_TYPE_INT, i, + "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, NULL); + gst_structure_set_value (structure, "channel-positions", &chanpos); + g_value_unset (&chanpos); + + gst_caps_append_structure (caps, structure); + } + + gst_caps_append_structure (caps, gst_structure_new ("audio/x-raw-float", + "rate", GST_TYPE_INT_RANGE, 1, 200000, + "channels", GST_TYPE_INT_RANGE, 9, 256, + "endianness", G_TYPE_INT, G_BYTE_ORDER, "width", G_TYPE_INT, 32, + NULL)); + + return caps; +} + +static GstCaps * +gst_vorbis_enc_sink_getcaps (GstPad * pad) +{ + GstVorbisEnc *vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad)); + + if (vorbisenc->sinkcaps == NULL) + vorbisenc->sinkcaps = gst_vorbis_enc_generate_sink_caps (); + + return gst_caps_ref (vorbisenc->sinkcaps); +} + +static gboolean +gst_vorbis_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVorbisEnc *vorbisenc; + GstStructure *structure; + + vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad)); + vorbisenc->setup = FALSE; + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "channels", &vorbisenc->channels); + gst_structure_get_int (structure, "rate", &vorbisenc->frequency); + + gst_vorbis_enc_setup (vorbisenc); + + if (vorbisenc->setup) + return TRUE; + + return FALSE; +} + +static gboolean +gst_vorbis_enc_convert_src (GstPad * pad, GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstVorbisEnc *vorbisenc; + gint64 avg; + + vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); + + if (vorbisenc->samples_in == 0 || + vorbisenc->bytes_out == 0 || vorbisenc->frequency == 0) { + gst_object_unref (vorbisenc); + return FALSE; + } + + avg = (vorbisenc->bytes_out * vorbisenc->frequency) / (vorbisenc->samples_in); + + switch (src_format) { + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, avg); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = gst_util_uint64_scale_int (src_value, avg, GST_SECOND); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } + gst_object_unref (vorbisenc); + return res; +} + +static gboolean +gst_vorbis_enc_convert_sink (GstPad * pad, GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + guint scale = 1; + gint bytes_per_sample; + GstVorbisEnc *vorbisenc; + + vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); + + bytes_per_sample = vorbisenc->channels * 2; + + switch (src_format) { + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + if (bytes_per_sample == 0) + return FALSE; + *dest_value = src_value / bytes_per_sample; + break; + case GST_FORMAT_TIME: + { + gint byterate = bytes_per_sample * vorbisenc->frequency; + + if (byterate == 0) + return FALSE; + *dest_value = + gst_util_uint64_scale_int (src_value, GST_SECOND, byterate); + break; + } + default: + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = src_value * bytes_per_sample; + break; + case GST_FORMAT_TIME: + if (vorbisenc->frequency == 0) + return FALSE; + *dest_value = + gst_util_uint64_scale_int (src_value, GST_SECOND, + vorbisenc->frequency); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = bytes_per_sample; + /* fallthrough */ + case GST_FORMAT_DEFAULT: + *dest_value = + gst_util_uint64_scale_int (src_value, + scale * vorbisenc->frequency, GST_SECOND); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } + gst_object_unref (vorbisenc); + return res; +} + +static gint64 +gst_vorbis_enc_get_latency (GstVorbisEnc * vorbisenc) +{ + /* FIXME, this probably depends on the bitrate and other setting but for now + * we return this value, which was obtained by totally unscientific + * measurements */ + return 58 * GST_MSECOND; +} + +static const GstQueryType * +gst_vorbis_enc_get_query_types (GstPad * pad) +{ + static const GstQueryType gst_vorbis_enc_src_query_types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + GST_QUERY_CONVERT, + 0 + }; + + return gst_vorbis_enc_src_query_types; +} + +static gboolean +gst_vorbis_enc_src_query (GstPad * pad, GstQuery * query) +{ + gboolean res = TRUE; + GstVorbisEnc *vorbisenc; + GstPad *peerpad; + + vorbisenc = GST_VORBISENC (gst_pad_get_parent (pad)); + peerpad = gst_pad_get_peer (GST_PAD (vorbisenc->sinkpad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat fmt, req_fmt; + gint64 pos, val; + + gst_query_parse_position (query, &req_fmt, NULL); + if ((res = gst_pad_query_position (peerpad, &req_fmt, &val))) { + gst_query_set_position (query, req_fmt, val); + break; + } + + fmt = GST_FORMAT_TIME; + if (!(res = gst_pad_query_position (peerpad, &fmt, &pos))) + break; + + if ((res = gst_pad_query_convert (peerpad, fmt, pos, &req_fmt, &val))) { + gst_query_set_position (query, req_fmt, val); + } + break; + } + case GST_QUERY_DURATION: + { + GstFormat fmt, req_fmt; + gint64 dur, val; + + gst_query_parse_duration (query, &req_fmt, NULL); + if ((res = gst_pad_query_duration (peerpad, &req_fmt, &val))) { + gst_query_set_duration (query, req_fmt, val); + break; + } + + fmt = GST_FORMAT_TIME; + if (!(res = gst_pad_query_duration (peerpad, &fmt, &dur))) + break; + + if ((res = gst_pad_query_convert (peerpad, fmt, dur, &req_fmt, &val))) { + gst_query_set_duration (query, req_fmt, val); + } + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + gst_vorbis_enc_convert_src (pad, src_fmt, src_val, &dest_fmt, + &dest_val))) + goto error; + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + case GST_QUERY_LATENCY: + { + gboolean live; + GstClockTime min_latency, max_latency; + gint64 latency; + + if ((res = gst_pad_query (peerpad, query))) { + gst_query_parse_latency (query, &live, &min_latency, &max_latency); + + latency = gst_vorbis_enc_get_latency (vorbisenc); + + /* add our latency */ + min_latency += latency; + if (max_latency != -1) + max_latency += latency; + + gst_query_set_latency (query, live, min_latency, max_latency); + } + break; + } + default: + res = gst_pad_query (peerpad, query); + break; + } + +error: + gst_object_unref (peerpad); + gst_object_unref (vorbisenc); + return res; +} + +static gboolean +gst_vorbis_enc_sink_query (GstPad * pad, GstQuery * query) +{ + gboolean res = TRUE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + gst_vorbis_enc_convert_sink (pad, src_fmt, src_val, &dest_fmt, + &dest_val))) + goto error; + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + +error: + return res; +} + +static void +gst_vorbis_enc_init (GstVorbisEnc * vorbisenc, GstVorbisEncClass * klass) +{ + vorbisenc->sinkpad = + gst_pad_new_from_static_template (&vorbis_enc_sink_factory, "sink"); + gst_pad_set_event_function (vorbisenc->sinkpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_event)); + gst_pad_set_chain_function (vorbisenc->sinkpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_chain)); + gst_pad_set_setcaps_function (vorbisenc->sinkpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_setcaps)); + gst_pad_set_getcaps_function (vorbisenc->sinkpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_getcaps)); + gst_pad_set_query_function (vorbisenc->sinkpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_sink_query)); + gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->sinkpad); + + vorbisenc->srcpad = + gst_pad_new_from_static_template (&vorbis_enc_src_factory, "src"); + gst_pad_set_query_function (vorbisenc->srcpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_src_query)); + gst_pad_set_query_type_function (vorbisenc->srcpad, + GST_DEBUG_FUNCPTR (gst_vorbis_enc_get_query_types)); + gst_element_add_pad (GST_ELEMENT (vorbisenc), vorbisenc->srcpad); + + vorbisenc->channels = -1; + vorbisenc->frequency = -1; + + vorbisenc->managed = FALSE; + vorbisenc->max_bitrate = MAX_BITRATE_DEFAULT; + vorbisenc->bitrate = BITRATE_DEFAULT; + vorbisenc->min_bitrate = MIN_BITRATE_DEFAULT; + vorbisenc->quality = QUALITY_DEFAULT; + vorbisenc->quality_set = FALSE; + vorbisenc->last_message = NULL; +} + +static void +gst_vorbis_enc_metadata_set1 (const GstTagList * list, const gchar * tag, + gpointer vorbisenc) +{ + GstVorbisEnc *enc = GST_VORBISENC (vorbisenc); + GList *vc_list, *l; + + vc_list = gst_tag_to_vorbis_comments (list, tag); + + for (l = vc_list; l != NULL; l = l->next) { + const gchar *vc_string = (const gchar *) l->data; + gchar *key = NULL, *val = NULL; + + GST_LOG_OBJECT (vorbisenc, "vorbis comment: %s", vc_string); + if (gst_tag_parse_extended_comment (vc_string, &key, NULL, &val, TRUE)) { + vorbis_comment_add_tag (&enc->vc, key, val); + g_free (key); + g_free (val); + } + } + + g_list_foreach (vc_list, (GFunc) g_free, NULL); + g_list_free (vc_list); +} + +static void +gst_vorbis_enc_set_metadata (GstVorbisEnc * enc) +{ + GstTagList *merged_tags; + const GstTagList *user_tags; + + vorbis_comment_init (&enc->vc); + + user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (enc)); + + GST_DEBUG_OBJECT (enc, "upstream tags = %" GST_PTR_FORMAT, enc->tags); + GST_DEBUG_OBJECT (enc, "user-set tags = %" GST_PTR_FORMAT, user_tags); + + /* gst_tag_list_merge() will handle NULL for either or both lists fine */ + merged_tags = gst_tag_list_merge (user_tags, enc->tags, + gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (enc))); + + if (merged_tags) { + GST_DEBUG_OBJECT (enc, "merged tags = %" GST_PTR_FORMAT, merged_tags); + gst_tag_list_foreach (merged_tags, gst_vorbis_enc_metadata_set1, enc); + gst_tag_list_free (merged_tags); + } +} + +static gchar * +get_constraints_string (GstVorbisEnc * vorbisenc) +{ + gint min = vorbisenc->min_bitrate; + gint max = vorbisenc->max_bitrate; + gchar *result; + + if (min > 0 && max > 0) + result = g_strdup_printf ("(min %d bps, max %d bps)", min, max); + else if (min > 0) + result = g_strdup_printf ("(min %d bps, no max)", min); + else if (max > 0) + result = g_strdup_printf ("(no min, max %d bps)", max); + else + result = g_strdup_printf ("(no min or max)"); + + return result; +} + +static void +update_start_message (GstVorbisEnc * vorbisenc) +{ + gchar *constraints; + + g_free (vorbisenc->last_message); + + if (vorbisenc->bitrate > 0) { + if (vorbisenc->managed) { + constraints = get_constraints_string (vorbisenc); + vorbisenc->last_message = + g_strdup_printf ("encoding at average bitrate %d bps %s", + vorbisenc->bitrate, constraints); + g_free (constraints); + } else { + vorbisenc->last_message = + g_strdup_printf + ("encoding at approximate bitrate %d bps (VBR encoding enabled)", + vorbisenc->bitrate); + } + } else { + if (vorbisenc->quality_set) { + if (vorbisenc->managed) { + constraints = get_constraints_string (vorbisenc); + vorbisenc->last_message = + g_strdup_printf + ("encoding at quality level %2.2f using constrained VBR %s", + vorbisenc->quality, constraints); + g_free (constraints); + } else { + vorbisenc->last_message = + g_strdup_printf ("encoding at quality level %2.2f", + vorbisenc->quality); + } + } else { + constraints = get_constraints_string (vorbisenc); + vorbisenc->last_message = + g_strdup_printf ("encoding using bitrate management %s", constraints); + g_free (constraints); + } + } + + g_object_notify (G_OBJECT (vorbisenc), "last_message"); +} + +static gboolean +gst_vorbis_enc_setup (GstVorbisEnc * vorbisenc) +{ + vorbisenc->setup = FALSE; + + if (vorbisenc->bitrate < 0 && vorbisenc->min_bitrate < 0 + && vorbisenc->max_bitrate < 0) { + vorbisenc->quality_set = TRUE; + } + + update_start_message (vorbisenc); + + /* choose an encoding mode */ + /* (mode 0: 44kHz stereo uncoupled, roughly 128kbps VBR) */ + vorbis_info_init (&vorbisenc->vi); + + if (vorbisenc->quality_set) { + if (vorbis_encode_setup_vbr (&vorbisenc->vi, + vorbisenc->channels, vorbisenc->frequency, + vorbisenc->quality) != 0) { + GST_ERROR_OBJECT (vorbisenc, + "vorbisenc: initialisation failed: invalid parameters for quality"); + vorbis_info_clear (&vorbisenc->vi); + return FALSE; + } + + /* do we have optional hard quality restrictions? */ + if (vorbisenc->max_bitrate > 0 || vorbisenc->min_bitrate > 0) { + struct ovectl_ratemanage_arg ai; + + vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_GET, &ai); + + ai.bitrate_hard_min = vorbisenc->min_bitrate; + ai.bitrate_hard_max = vorbisenc->max_bitrate; + ai.management_active = 1; + + vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, &ai); + } + } else { + long min_bitrate, max_bitrate; + + min_bitrate = vorbisenc->min_bitrate > 0 ? vorbisenc->min_bitrate : -1; + max_bitrate = vorbisenc->max_bitrate > 0 ? vorbisenc->max_bitrate : -1; + + if (vorbis_encode_setup_managed (&vorbisenc->vi, + vorbisenc->channels, + vorbisenc->frequency, + max_bitrate, vorbisenc->bitrate, min_bitrate) != 0) { + GST_ERROR_OBJECT (vorbisenc, + "vorbis_encode_setup_managed " + "(c %d, rate %d, max br %ld, br %d, min br %ld) failed", + vorbisenc->channels, vorbisenc->frequency, max_bitrate, + vorbisenc->bitrate, min_bitrate); + vorbis_info_clear (&vorbisenc->vi); + return FALSE; + } + } + + if (vorbisenc->managed && vorbisenc->bitrate < 0) { + vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_AVG, NULL); + } else if (!vorbisenc->managed) { + /* Turn off management entirely (if it was turned on). */ + vorbis_encode_ctl (&vorbisenc->vi, OV_ECTL_RATEMANAGE_SET, NULL); + } + vorbis_encode_setup_init (&vorbisenc->vi); + + /* set up the analysis state and auxiliary encoding storage */ + vorbis_analysis_init (&vorbisenc->vd, &vorbisenc->vi); + vorbis_block_init (&vorbisenc->vd, &vorbisenc->vb); + + vorbisenc->next_ts = 0; + + vorbisenc->setup = TRUE; + + return TRUE; +} + +static GstFlowReturn +gst_vorbis_enc_clear (GstVorbisEnc * vorbisenc) +{ + GstFlowReturn ret = GST_FLOW_OK; + + if (vorbisenc->setup) { + vorbis_analysis_wrote (&vorbisenc->vd, 0); + ret = gst_vorbis_enc_output_buffers (vorbisenc); + + vorbisenc->setup = FALSE; + } + + /* clean up and exit. vorbis_info_clear() must be called last */ + vorbis_block_clear (&vorbisenc->vb); + vorbis_dsp_clear (&vorbisenc->vd); + vorbis_info_clear (&vorbisenc->vi); + + vorbisenc->header_sent = FALSE; + + return ret; +} + +/* prepare a buffer for transmission by passing data through libvorbis */ +static GstBuffer * +gst_vorbis_enc_buffer_from_packet (GstVorbisEnc * vorbisenc, + ogg_packet * packet) +{ + GstBuffer *outbuf; + + outbuf = gst_buffer_new_and_alloc (packet->bytes); + memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes); + /* see ext/ogg/README; OFFSET_END takes "our" granulepos, OFFSET its + * time representation */ + GST_BUFFER_OFFSET_END (outbuf) = packet->granulepos + + vorbisenc->granulepos_offset; + GST_BUFFER_OFFSET (outbuf) = granulepos_to_timestamp (vorbisenc, + GST_BUFFER_OFFSET_END (outbuf)); + GST_BUFFER_TIMESTAMP (outbuf) = vorbisenc->next_ts; + + /* update the next timestamp, taking granulepos_offset and subgranule offset + * into account */ + vorbisenc->next_ts = + granulepos_to_timestamp_offset (vorbisenc, packet->granulepos) + + vorbisenc->initial_ts; + GST_BUFFER_DURATION (outbuf) = + vorbisenc->next_ts - GST_BUFFER_TIMESTAMP (outbuf); + + if (vorbisenc->next_discont) { + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + vorbisenc->next_discont = FALSE; + } + + gst_buffer_set_caps (outbuf, vorbisenc->srccaps); + + GST_LOG_OBJECT (vorbisenc, "encoded buffer of %d bytes", + GST_BUFFER_SIZE (outbuf)); + return outbuf; +} + +/* the same as above, but different logic for setting timestamp and granulepos + * */ +static GstBuffer * +gst_vorbis_enc_buffer_from_header_packet (GstVorbisEnc * vorbisenc, + ogg_packet * packet) +{ + GstBuffer *outbuf; + + outbuf = gst_buffer_new_and_alloc (packet->bytes); + memcpy (GST_BUFFER_DATA (outbuf), packet->packet, packet->bytes); + GST_BUFFER_OFFSET (outbuf) = vorbisenc->bytes_out; + GST_BUFFER_OFFSET_END (outbuf) = 0; + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; + + gst_buffer_set_caps (outbuf, vorbisenc->srccaps); + + GST_DEBUG ("created header packet buffer, %d bytes", + GST_BUFFER_SIZE (outbuf)); + return outbuf; +} + +/* push out the buffer and do internal bookkeeping */ +static GstFlowReturn +gst_vorbis_enc_push_buffer (GstVorbisEnc * vorbisenc, GstBuffer * buffer) +{ + vorbisenc->bytes_out += GST_BUFFER_SIZE (buffer); + + GST_DEBUG_OBJECT (vorbisenc, + "Pushing buffer with GP %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, + GST_BUFFER_OFFSET_END (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + return gst_pad_push (vorbisenc->srcpad, buffer); +} + +static GstFlowReturn +gst_vorbis_enc_push_packet (GstVorbisEnc * vorbisenc, ogg_packet * packet) +{ + GstBuffer *outbuf; + + outbuf = gst_vorbis_enc_buffer_from_packet (vorbisenc, packet); + return gst_vorbis_enc_push_buffer (vorbisenc, outbuf); +} + +/* Set a copy of these buffers as 'streamheader' on the caps. + * We need a copy to avoid these buffers ending up with (indirect) refs on + * themselves + */ +static GstCaps * +gst_vorbis_enc_set_header_on_caps (GstCaps * caps, GstBuffer * buf1, + GstBuffer * buf2, GstBuffer * buf3) +{ + GstBuffer *buf; + GstStructure *structure; + GValue array = { 0 }; + GValue value = { 0 }; + + caps = gst_caps_make_writable (caps); + structure = gst_caps_get_structure (caps, 0); + + /* mark buffers */ + GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS); + + /* put buffers in a fixed list */ + g_value_init (&array, GST_TYPE_ARRAY); + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_copy (buf1); + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_copy (buf2); + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_copy (buf3); + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&value); + g_value_unset (&array); + + return caps; +} + +static gboolean +gst_vorbis_enc_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstVorbisEnc *vorbisenc; + + vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* Tell the library we're at end of stream so that it can handle + * the last frame and mark end of stream in the output properly */ + GST_DEBUG_OBJECT (vorbisenc, "EOS, clearing state and sending event on"); + gst_vorbis_enc_clear (vorbisenc); + + res = gst_pad_push_event (vorbisenc->srcpad, event); + break; + case GST_EVENT_TAG: + if (vorbisenc->tags) { + GstTagList *list; + + gst_event_parse_tag (event, &list); + gst_tag_list_insert (vorbisenc->tags, list, + gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (vorbisenc))); + } else { + g_assert_not_reached (); + } + res = gst_pad_push_event (vorbisenc->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, position; + + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + if (format == GST_FORMAT_TIME) { + gst_segment_set_newsegment (&vorbisenc->segment, update, rate, format, + start, stop, position); + if (vorbisenc->initial_ts == GST_CLOCK_TIME_NONE) { + GST_DEBUG_OBJECT (vorbisenc, "Initial segment %" GST_SEGMENT_FORMAT, + &vorbisenc->segment); + vorbisenc->initial_ts = start; + } + } + } + /* fall through */ + default: + res = gst_pad_push_event (vorbisenc->srcpad, event); + break; + } + return res; +} + +static gboolean +gst_vorbis_enc_buffer_check_discontinuous (GstVorbisEnc * vorbisenc, + GstClockTime timestamp, GstClockTime duration) +{ + gboolean ret = FALSE; + + if (timestamp != GST_CLOCK_TIME_NONE && + vorbisenc->expected_ts != GST_CLOCK_TIME_NONE && + timestamp + duration != vorbisenc->expected_ts) { + /* It turns out that a lot of elements don't generate perfect streams due + * to rounding errors. So, we permit small errors (< 1/2 a sample) without + * causing a discont. + */ + int halfsample = GST_SECOND / vorbisenc->frequency / 2; + + if ((GstClockTimeDiff) (timestamp - vorbisenc->expected_ts) > halfsample) { + GST_DEBUG_OBJECT (vorbisenc, "Expected TS %" GST_TIME_FORMAT + ", buffer TS %" GST_TIME_FORMAT, + GST_TIME_ARGS (vorbisenc->expected_ts), GST_TIME_ARGS (timestamp)); + ret = TRUE; + } + } + + if (timestamp != GST_CLOCK_TIME_NONE && duration != GST_CLOCK_TIME_NONE) { + vorbisenc->expected_ts = timestamp + duration; + } else + vorbisenc->expected_ts = GST_CLOCK_TIME_NONE; + + return ret; +} + +static GstFlowReturn +gst_vorbis_enc_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVorbisEnc *vorbisenc; + GstFlowReturn ret = GST_FLOW_OK; + gfloat *data; + gulong size; + gulong i, j; + float **vorbis_buffer; + GstBuffer *buf1, *buf2, *buf3; + gboolean first = FALSE; + GstClockTime timestamp = GST_CLOCK_TIME_NONE; + GstClockTime running_time = GST_CLOCK_TIME_NONE; + + vorbisenc = GST_VORBISENC (GST_PAD_PARENT (pad)); + + if (!vorbisenc->setup) + goto not_setup; + + buffer = gst_audio_buffer_clip (buffer, &vorbisenc->segment, + vorbisenc->frequency, 4 * vorbisenc->channels); + if (buffer == NULL) { + GST_DEBUG_OBJECT (vorbisenc, "Dropping buffer, out of segment"); + return GST_FLOW_OK; + } + running_time = + gst_segment_to_running_time (&vorbisenc->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + timestamp = running_time + vorbisenc->initial_ts; + GST_DEBUG_OBJECT (vorbisenc, "Initial ts is %" GST_TIME_FORMAT, + GST_TIME_ARGS (vorbisenc->initial_ts)); + if (!vorbisenc->header_sent) { + /* Vorbis streams begin with three headers; the initial header (with + most of the codec setup parameters) which is mandated by the Ogg + bitstream spec. The second header holds any comment fields. The + third header holds the bitstream codebook. We merely need to + make the headers, then pass them to libvorbis one at a time; + libvorbis handles the additional Ogg bitstream constraints */ + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + GstCaps *caps; + + /* first, make sure header buffers get timestamp == 0 */ + vorbisenc->next_ts = 0; + vorbisenc->granulepos_offset = 0; + vorbisenc->subgranule_offset = 0; + + GST_DEBUG_OBJECT (vorbisenc, "creating and sending header packets"); + gst_vorbis_enc_set_metadata (vorbisenc); + vorbis_analysis_headerout (&vorbisenc->vd, &vorbisenc->vc, &header, + &header_comm, &header_code); + vorbis_comment_clear (&vorbisenc->vc); + + /* create header buffers */ + buf1 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header); + buf2 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_comm); + buf3 = gst_vorbis_enc_buffer_from_header_packet (vorbisenc, &header_code); + + /* mark and put on caps */ + vorbisenc->srccaps = gst_caps_new_simple ("audio/x-vorbis", NULL); + caps = vorbisenc->srccaps; + caps = gst_vorbis_enc_set_header_on_caps (caps, buf1, buf2, buf3); + + /* negotiate with these caps */ + GST_DEBUG ("here are the caps: %" GST_PTR_FORMAT, caps); + gst_pad_set_caps (vorbisenc->srcpad, caps); + + gst_buffer_set_caps (buf1, caps); + gst_buffer_set_caps (buf2, caps); + gst_buffer_set_caps (buf3, caps); + + /* push out buffers */ + /* push_buffer takes the reference even for failure */ + if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf1)) != GST_FLOW_OK) + goto failed_header_push; + if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf2)) != GST_FLOW_OK) { + buf2 = NULL; + goto failed_header_push; + } + if ((ret = gst_vorbis_enc_push_buffer (vorbisenc, buf3)) != GST_FLOW_OK) { + buf3 = NULL; + goto failed_header_push; + } + + /* now adjust starting granulepos accordingly if the buffer's timestamp is + nonzero */ + vorbisenc->next_ts = timestamp; + vorbisenc->expected_ts = timestamp; + vorbisenc->granulepos_offset = gst_util_uint64_scale + (running_time, vorbisenc->frequency, GST_SECOND); + vorbisenc->subgranule_offset = 0; + vorbisenc->subgranule_offset = + (vorbisenc->next_ts - vorbisenc->initial_ts) - + granulepos_to_timestamp_offset (vorbisenc, 0); + + vorbisenc->header_sent = TRUE; + first = TRUE; + } + + if (vorbisenc->expected_ts != GST_CLOCK_TIME_NONE && + timestamp < vorbisenc->expected_ts) { + guint64 diff = vorbisenc->expected_ts - timestamp; + guint64 diff_bytes; + + GST_WARNING_OBJECT (vorbisenc, "Buffer is older than previous " + "timestamp + duration (%" GST_TIME_FORMAT "< %" GST_TIME_FORMAT + "), cannot handle. Clipping buffer.", + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (vorbisenc->expected_ts)); + + diff_bytes = + GST_CLOCK_TIME_TO_FRAMES (diff, + vorbisenc->frequency) * vorbisenc->channels * sizeof (gfloat); + if (diff_bytes >= GST_BUFFER_SIZE (buffer)) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + buffer = gst_buffer_make_metadata_writable (buffer); + GST_BUFFER_DATA (buffer) += diff_bytes; + GST_BUFFER_SIZE (buffer) -= diff_bytes; + + GST_BUFFER_TIMESTAMP (buffer) += diff; + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + GST_BUFFER_DURATION (buffer) -= diff; + } + + if (gst_vorbis_enc_buffer_check_discontinuous (vorbisenc, timestamp, + GST_BUFFER_DURATION (buffer)) && !first) { + GST_WARNING_OBJECT (vorbisenc, + "Buffer is discontinuous, flushing encoder " + "and restarting (Discont from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT + ")", GST_TIME_ARGS (vorbisenc->next_ts), GST_TIME_ARGS (timestamp)); + /* Re-initialise encoder (there's unfortunately no API to flush it) */ + if ((ret = gst_vorbis_enc_clear (vorbisenc)) != GST_FLOW_OK) + return ret; + if (!gst_vorbis_enc_setup (vorbisenc)) + return GST_FLOW_ERROR; /* Should be impossible, we can only get here if + we successfully initialised earlier */ + + /* Now, set our granulepos offset appropriately. */ + vorbisenc->next_ts = timestamp; + /* We need to round to the nearest whole number of samples, not just do + * a truncating division here */ + vorbisenc->granulepos_offset = gst_util_uint64_scale + (running_time + GST_SECOND / vorbisenc->frequency / 2 + - vorbisenc->subgranule_offset, vorbisenc->frequency, GST_SECOND); + + vorbisenc->header_sent = TRUE; + + /* And our next output buffer must have DISCONT set on it */ + vorbisenc->next_discont = TRUE; + } + + /* Sending zero samples to libvorbis marks EOS, so we mustn't do that */ + if (GST_BUFFER_SIZE (buffer) == 0) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + /* data to encode */ + data = (gfloat *) GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer) / (vorbisenc->channels * sizeof (float)); + + /* expose the buffer to submit data */ + vorbis_buffer = vorbis_analysis_buffer (&vorbisenc->vd, size); + + /* deinterleave samples, write the buffer data */ + for (i = 0; i < size; i++) { + for (j = 0; j < vorbisenc->channels; j++) { + vorbis_buffer[j][i] = *data++; + } + } + + /* tell the library how much we actually submitted */ + vorbis_analysis_wrote (&vorbisenc->vd, size); + + GST_LOG_OBJECT (vorbisenc, "wrote %lu samples to vorbis", size); + + vorbisenc->samples_in += size; + + gst_buffer_unref (buffer); + + ret = gst_vorbis_enc_output_buffers (vorbisenc); + + return ret; + + /* error cases */ +not_setup: + { + gst_buffer_unref (buffer); + GST_ELEMENT_ERROR (vorbisenc, CORE, NEGOTIATION, (NULL), + ("encoder not initialized (input is not audio?)")); + return GST_FLOW_UNEXPECTED; + } +failed_header_push: + { + GST_WARNING_OBJECT (vorbisenc, "Failed to push headers"); + /* buf1 is always already unreffed */ + if (buf2) + gst_buffer_unref (buf2); + if (buf3) + gst_buffer_unref (buf3); + gst_buffer_unref (buffer); + return ret; + } +} + +static GstFlowReturn +gst_vorbis_enc_output_buffers (GstVorbisEnc * vorbisenc) +{ + GstFlowReturn ret; + + /* vorbis does some data preanalysis, then divides up blocks for + more involved (potentially parallel) processing. Get a single + block for encoding now */ + while (vorbis_analysis_blockout (&vorbisenc->vd, &vorbisenc->vb) == 1) { + ogg_packet op; + + GST_LOG_OBJECT (vorbisenc, "analysed to a block"); + + /* analysis */ + vorbis_analysis (&vorbisenc->vb, NULL); + vorbis_bitrate_addblock (&vorbisenc->vb); + + while (vorbis_bitrate_flushpacket (&vorbisenc->vd, &op)) { + GST_LOG_OBJECT (vorbisenc, "pushing out a data packet"); + ret = gst_vorbis_enc_push_packet (vorbisenc, &op); + + if (ret != GST_FLOW_OK) + return ret; + } + } + + return GST_FLOW_OK; +} + +static void +gst_vorbis_enc_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVorbisEnc *vorbisenc; + + g_return_if_fail (GST_IS_VORBISENC (object)); + + vorbisenc = GST_VORBISENC (object); + + switch (prop_id) { + case ARG_MAX_BITRATE: + g_value_set_int (value, vorbisenc->max_bitrate); + break; + case ARG_BITRATE: + g_value_set_int (value, vorbisenc->bitrate); + break; + case ARG_MIN_BITRATE: + g_value_set_int (value, vorbisenc->min_bitrate); + break; + case ARG_QUALITY: + g_value_set_float (value, vorbisenc->quality); + break; + case ARG_MANAGED: + g_value_set_boolean (value, vorbisenc->managed); + break; + case ARG_LAST_MESSAGE: + g_value_set_string (value, vorbisenc->last_message); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vorbis_enc_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVorbisEnc *vorbisenc; + + g_return_if_fail (GST_IS_VORBISENC (object)); + + vorbisenc = GST_VORBISENC (object); + + switch (prop_id) { + case ARG_MAX_BITRATE: + { + gboolean old_value = vorbisenc->managed; + + vorbisenc->max_bitrate = g_value_get_int (value); + if (vorbisenc->max_bitrate >= 0 + && vorbisenc->max_bitrate < LOWEST_BITRATE) { + g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE); + vorbisenc->max_bitrate = LOWEST_BITRATE; + } + if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0) + vorbisenc->managed = TRUE; + else + vorbisenc->managed = FALSE; + + if (old_value != vorbisenc->managed) + g_object_notify (object, "managed"); + break; + } + case ARG_BITRATE: + vorbisenc->bitrate = g_value_get_int (value); + if (vorbisenc->bitrate >= 0 && vorbisenc->bitrate < LOWEST_BITRATE) { + g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE); + vorbisenc->bitrate = LOWEST_BITRATE; + } + break; + case ARG_MIN_BITRATE: + { + gboolean old_value = vorbisenc->managed; + + vorbisenc->min_bitrate = g_value_get_int (value); + if (vorbisenc->min_bitrate >= 0 + && vorbisenc->min_bitrate < LOWEST_BITRATE) { + g_warning ("Lowest allowed bitrate is %d", LOWEST_BITRATE); + vorbisenc->min_bitrate = LOWEST_BITRATE; + } + if (vorbisenc->min_bitrate > 0 && vorbisenc->max_bitrate > 0) + vorbisenc->managed = TRUE; + else + vorbisenc->managed = FALSE; + + if (old_value != vorbisenc->managed) + g_object_notify (object, "managed"); + break; + } + case ARG_QUALITY: + vorbisenc->quality = g_value_get_float (value); + if (vorbisenc->quality >= 0.0) + vorbisenc->quality_set = TRUE; + else + vorbisenc->quality_set = FALSE; + break; + case ARG_MANAGED: + vorbisenc->managed = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_vorbis_enc_change_state (GstElement * element, GstStateChange transition) +{ + GstVorbisEnc *vorbisenc = GST_VORBISENC (element); + GstStateChangeReturn res; + + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + vorbisenc->tags = gst_tag_list_new (); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + vorbisenc->setup = FALSE; + vorbisenc->next_discont = FALSE; + vorbisenc->header_sent = FALSE; + gst_segment_init (&vorbisenc->segment, GST_FORMAT_TIME); + vorbisenc->initial_ts = GST_CLOCK_TIME_NONE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + vorbis_block_clear (&vorbisenc->vb); + vorbis_dsp_clear (&vorbisenc->vd); + vorbis_info_clear (&vorbisenc->vi); + g_free (vorbisenc->last_message); + vorbisenc->last_message = NULL; + if (vorbisenc->srccaps) { + gst_caps_unref (vorbisenc->srccaps); + vorbisenc->srccaps = NULL; + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_tag_list_free (vorbisenc->tags); + vorbisenc->tags = NULL; + default: + break; + } + + return res; +} diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.h new file mode 100644 index 0000000..9375a16 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisenc.h @@ -0,0 +1,101 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_VORBIS_ENC_H__ +#define __GST_VORBIS_ENC_H__ + + +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VORBISENC \ + (gst_vorbis_enc_get_type()) +#define GST_VORBISENC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBISENC,GstVorbisEnc)) +#define GST_VORBISENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBISENC,GstVorbisEncClass)) +#define GST_IS_VORBISENC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBISENC)) +#define GST_IS_VORBISENC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBISENC)) + +typedef struct _GstVorbisEnc GstVorbisEnc; +typedef struct _GstVorbisEncClass GstVorbisEncClass; + +/** + * GstVorbisEnc: + * + * Opaque data structure. + */ +struct _GstVorbisEnc { + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstCaps *srccaps; + GstCaps *sinkcaps; + + vorbis_info vi; /* struct that stores all the static vorbis bitstream + settings */ + vorbis_comment vc; /* struct that stores all the user comments */ + + vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */ + vorbis_block vb; /* local working space for packet->PCM decode */ + + gboolean managed; + gint bitrate; + gint min_bitrate; + gint max_bitrate; + gfloat quality; + gboolean quality_set; + + gint channels; + gint frequency; + + guint64 samples_in; + guint64 bytes_out; + GstClockTime next_ts; + GstClockTime expected_ts; + gboolean next_discont; + guint64 granulepos_offset; + gint64 subgranule_offset; + GstSegment segment; + GstClockTime initial_ts; + + GstTagList * tags; + + gboolean setup; + gboolean header_sent; + gchar *last_message; +}; + +struct _GstVorbisEncClass { + GstElementClass parent_class; +}; + +GType gst_vorbis_enc_get_type(void); + +G_END_DECLS + +#endif /* __GST_VORBIS_ENC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.c new file mode 100644 index 0000000..53fd7b1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.c @@ -0,0 +1,670 @@ +/* GStreamer + * Copyright (C) <2004> Thomas Vander Stichele + * Copyright (C) 2006 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-vorbisparse + * @see_also: vorbisdec, oggdemux, theoraparse + * + * The vorbisparse element will parse the header packets of the Vorbis + * stream and put them as the streamheader in the caps. This is used in the + * multifdsink case where you want to stream live vorbis streams to multiple + * clients, each client has to receive the streamheaders first before they can + * consume the vorbis packets. + * + * This element also makes sure that the buffers that it pushes out are properly + * timestamped and that their offset and offset_end are set. The buffers that + * vorbisparse outputs have all of the metadata that oggmux expects to receive, + * which allows you to (for example) remux an ogg/vorbis file. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisparse ! fakesink + * ]| This pipeline shows that the streamheader is set in the caps, and that each + * buffer has the timestamp, duration, offset, and offset_end set. + * |[ + * gst-launch filesrc location=sine.ogg ! oggdemux ! vorbisparse \ + * ! oggmux ! filesink location=sine-remuxed.ogg + * ]| This pipeline shows remuxing. sine-remuxed.ogg might not be exactly the same + * as sine.ogg, but they should produce exactly the same decoded data. + * + * + * Last reviewed on 2006-04-01 (0.10.4.1) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstvorbisparse.h" + +GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug); +#define GST_CAT_DEFAULT vorbisparse_debug + +static GstStaticPadTemplate vorbis_parse_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-vorbis") + ); + +static GstStaticPadTemplate vorbis_parse_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-vorbis") + ); + +GST_BOILERPLATE (GstVorbisParse, gst_vorbis_parse, GstElement, + GST_TYPE_ELEMENT); + +static GstFlowReturn vorbis_parse_chain (GstPad * pad, GstBuffer * buffer); +static GstStateChangeReturn vorbis_parse_change_state (GstElement * element, + GstStateChange transition); +static gboolean vorbis_parse_sink_event (GstPad * pad, GstEvent * event); +static gboolean vorbis_parse_src_query (GstPad * pad, GstQuery * query); +static gboolean vorbis_parse_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value); +static GstFlowReturn vorbis_parse_parse_packet (GstVorbisParse * parse, + GstBuffer * buf); + +static void +gst_vorbis_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&vorbis_parse_src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&vorbis_parse_sink_factory)); + gst_element_class_set_details_simple (element_class, + "VorbisParse", "Codec/Parser/Audio", + "parse raw vorbis streams", + "Thomas Vander Stichele "); +} + +static void +gst_vorbis_parse_class_init (GstVorbisParseClass * klass) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gstelement_class->change_state = vorbis_parse_change_state; + + klass->parse_packet = GST_DEBUG_FUNCPTR (vorbis_parse_parse_packet); +} + +static void +gst_vorbis_parse_init (GstVorbisParse * parse, GstVorbisParseClass * g_class) +{ + parse->sinkpad = + gst_pad_new_from_static_template (&vorbis_parse_sink_factory, "sink"); + gst_pad_set_chain_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (vorbis_parse_chain)); + gst_pad_set_event_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (vorbis_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + parse->srcpad = + gst_pad_new_from_static_template (&vorbis_parse_src_factory, "src"); + gst_pad_set_query_function (parse->srcpad, + GST_DEBUG_FUNCPTR (vorbis_parse_src_query)); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); +} + +static void +vorbis_parse_set_header_on_caps (GstVorbisParse * parse, GstCaps * caps) +{ + GstBuffer *buf1, *buf2, *buf3; + GstStructure *structure; + GValue array = { 0 }; + GValue value = { 0 }; + + g_assert (parse); + g_assert (parse->streamheader); + g_assert (parse->streamheader->next); + g_assert (parse->streamheader->next->next); + buf1 = parse->streamheader->data; + g_assert (buf1); + buf2 = parse->streamheader->next->data; + g_assert (buf2); + buf3 = parse->streamheader->next->next->data; + g_assert (buf3); + + structure = gst_caps_get_structure (caps, 0); + + /* mark buffers */ + GST_BUFFER_FLAG_SET (buf1, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (buf2, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_FLAG_SET (buf3, GST_BUFFER_FLAG_IN_CAPS); + + /* put buffers in a fixed list */ + g_value_init (&array, GST_TYPE_ARRAY); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, buf1); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, buf2); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, buf3); + gst_value_array_append_value (&array, &value); + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&value); + g_value_unset (&array); +} + +static void +vorbis_parse_drain_event_queue (GstVorbisParse * parse) +{ + while (parse->event_queue->length) { + GstEvent *event; + + event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); + gst_pad_event_default (parse->sinkpad, event); + } +} + +static void +vorbis_parse_push_headers (GstVorbisParse * parse) +{ + /* mark and put on caps */ + GstCaps *caps; + GstBuffer *outbuf, *outbuf1, *outbuf2, *outbuf3; + ogg_packet packet; + + /* get the headers into the caps, passing them to vorbis as we go */ + caps = gst_caps_make_writable (gst_pad_get_caps (parse->srcpad)); + vorbis_parse_set_header_on_caps (parse, caps); + GST_DEBUG_OBJECT (parse, "here are the caps: %" GST_PTR_FORMAT, caps); + gst_pad_set_caps (parse->srcpad, caps); + gst_caps_unref (caps); + + outbuf = GST_BUFFER_CAST (parse->streamheader->data); + packet.packet = GST_BUFFER_DATA (outbuf); + packet.bytes = GST_BUFFER_SIZE (outbuf); + packet.granulepos = GST_BUFFER_OFFSET_END (outbuf); + packet.packetno = 1; + packet.e_o_s = 0; + packet.b_o_s = 1; + vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet); + parse->sample_rate = parse->vi.rate; + outbuf1 = outbuf; + + outbuf = GST_BUFFER_CAST (parse->streamheader->next->data); + packet.packet = GST_BUFFER_DATA (outbuf); + packet.bytes = GST_BUFFER_SIZE (outbuf); + packet.granulepos = GST_BUFFER_OFFSET_END (outbuf); + packet.packetno = 2; + packet.e_o_s = 0; + packet.b_o_s = 0; + vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet); + outbuf2 = outbuf; + + outbuf = GST_BUFFER_CAST (parse->streamheader->next->next->data); + packet.packet = GST_BUFFER_DATA (outbuf); + packet.bytes = GST_BUFFER_SIZE (outbuf); + packet.granulepos = GST_BUFFER_OFFSET_END (outbuf); + packet.packetno = 3; + packet.e_o_s = 0; + packet.b_o_s = 0; + vorbis_synthesis_headerin (&parse->vi, &parse->vc, &packet); + outbuf3 = outbuf; + + /* first process queued events */ + vorbis_parse_drain_event_queue (parse); + + /* push out buffers, ignoring return value... */ + outbuf1 = gst_buffer_make_metadata_writable (outbuf1); + gst_buffer_set_caps (outbuf1, GST_PAD_CAPS (parse->srcpad)); + gst_pad_push (parse->srcpad, outbuf1); + outbuf2 = gst_buffer_make_metadata_writable (outbuf2); + gst_buffer_set_caps (outbuf2, GST_PAD_CAPS (parse->srcpad)); + gst_pad_push (parse->srcpad, outbuf2); + outbuf3 = gst_buffer_make_metadata_writable (outbuf3); + gst_buffer_set_caps (outbuf3, GST_PAD_CAPS (parse->srcpad)); + gst_pad_push (parse->srcpad, outbuf3); + + g_list_free (parse->streamheader); + parse->streamheader = NULL; +} + +static void +vorbis_parse_clear_queue (GstVorbisParse * parse) +{ + while (parse->buffer_queue->length) { + GstBuffer *buf; + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + gst_buffer_unref (buf); + } + while (parse->event_queue->length) { + GstEvent *event; + + event = GST_EVENT_CAST (g_queue_pop_head (parse->event_queue)); + gst_event_unref (event); + } +} + +static GstFlowReturn +vorbis_parse_push_buffer (GstVorbisParse * parse, GstBuffer * buf, + gint64 granulepos) +{ + guint64 samples; + + /* our hack as noted below */ + samples = GST_BUFFER_OFFSET (buf); + + GST_BUFFER_OFFSET_END (buf) = granulepos; + GST_BUFFER_DURATION (buf) = samples * GST_SECOND / parse->sample_rate; + GST_BUFFER_OFFSET (buf) = granulepos * GST_SECOND / parse->sample_rate; + GST_BUFFER_TIMESTAMP (buf) = + GST_BUFFER_OFFSET (buf) - GST_BUFFER_DURATION (buf); + + gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad)); + + return gst_pad_push (parse->srcpad, buf); +} + +static GstFlowReturn +vorbis_parse_drain_queue_prematurely (GstVorbisParse * parse) +{ + GstFlowReturn ret = GST_FLOW_OK; + gint64 granulepos = MAX (parse->prev_granulepos, 0); + + /* got an EOS event, make sure to push out any buffers that were in the queue + * -- won't normally be the case, but this catches the + * didn't-get-a-granulepos-on-the-last-packet case. Assuming a continuous + * stream. */ + + /* if we got EOS before any buffers came, go ahead and push the other events + * first */ + vorbis_parse_drain_event_queue (parse); + + while (!g_queue_is_empty (parse->buffer_queue)) { + GstBuffer *buf; + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + + granulepos += GST_BUFFER_OFFSET (buf); + ret = vorbis_parse_push_buffer (parse, buf, granulepos); + + if (ret != GST_FLOW_OK) + goto done; + } + + parse->prev_granulepos = granulepos; + +done: + return ret; +} + +static GstFlowReturn +vorbis_parse_drain_queue (GstVorbisParse * parse, gint64 granulepos) +{ + GstFlowReturn ret = GST_FLOW_OK; + GList *walk; + gint64 cur = granulepos; + gint64 gp; + + for (walk = parse->buffer_queue->head; walk; walk = walk->next) + cur -= GST_BUFFER_OFFSET (walk->data); + + if (parse->prev_granulepos != -1) + cur = MAX (cur, parse->prev_granulepos); + + while (!g_queue_is_empty (parse->buffer_queue)) { + GstBuffer *buf; + + buf = GST_BUFFER_CAST (g_queue_pop_head (parse->buffer_queue)); + + cur += GST_BUFFER_OFFSET (buf); + gp = CLAMP (cur, 0, granulepos); + + ret = vorbis_parse_push_buffer (parse, buf, gp); + + if (ret != GST_FLOW_OK) + goto done; + } + + parse->prev_granulepos = granulepos; + +done: + return ret; +} + +static GstFlowReturn +vorbis_parse_queue_buffer (GstVorbisParse * parse, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + long blocksize; + ogg_packet packet; + + buf = gst_buffer_make_metadata_writable (buf); + + packet.packet = GST_BUFFER_DATA (buf); + packet.bytes = GST_BUFFER_SIZE (buf); + packet.granulepos = GST_BUFFER_OFFSET_END (buf); + packet.packetno = parse->packetno + parse->buffer_queue->length; + packet.e_o_s = 0; + + blocksize = vorbis_packet_blocksize (&parse->vi, &packet); + + /* temporarily store the sample count in OFFSET -- we overwrite this later */ + + if (parse->prev_blocksize < 0) + GST_BUFFER_OFFSET (buf) = 0; + else + GST_BUFFER_OFFSET (buf) = (blocksize + parse->prev_blocksize) / 4; + + parse->prev_blocksize = blocksize; + + g_queue_push_tail (parse->buffer_queue, buf); + + if (GST_BUFFER_OFFSET_END_IS_VALID (buf)) + ret = vorbis_parse_drain_queue (parse, GST_BUFFER_OFFSET_END (buf)); + + return ret; +} + +static GstFlowReturn +vorbis_parse_parse_packet (GstVorbisParse * parse, GstBuffer * buf) +{ + GstFlowReturn ret; + guint8 *data; + guint size; + gboolean have_header; + + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + + parse->packetno++; + + have_header = FALSE; + if (size >= 1) { + if (data[0] >= 0x01 && data[0] <= 0x05) + have_header = TRUE; + } + + if (have_header) { + if (!parse->streamheader_sent) { + /* we need to collect the headers still */ + /* so put it on the streamheader list and return */ + parse->streamheader = g_list_append (parse->streamheader, buf); + } + ret = GST_FLOW_OK; + } else { + /* data packet, push the headers we collected before */ + if (!parse->streamheader_sent) { + vorbis_parse_push_headers (parse); + parse->streamheader_sent = TRUE; + } + ret = vorbis_parse_queue_buffer (parse, buf); + } + + return ret; +} + +static GstFlowReturn +vorbis_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVorbisParseClass *klass; + GstVorbisParse *parse; + + parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad)); + klass = GST_VORBIS_PARSE_CLASS (G_OBJECT_GET_CLASS (parse)); + + g_assert (klass->parse_packet != NULL); + + return klass->parse_packet (parse, buffer); +} + +static gboolean +vorbis_parse_queue_event (GstVorbisParse * parse, GstEvent * event) +{ + GstFlowReturn ret = TRUE; + + g_queue_push_tail (parse->event_queue, event); + + return ret; +} + +static gboolean +vorbis_parse_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret; + GstVorbisParse *parse; + + parse = GST_VORBIS_PARSE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + vorbis_parse_clear_queue (parse); + parse->prev_granulepos = -1; + parse->prev_blocksize = -1; + ret = gst_pad_event_default (pad, event); + break; + case GST_EVENT_EOS: + vorbis_parse_drain_queue_prematurely (parse); + ret = gst_pad_event_default (pad, event); + break; + default: + if (!parse->streamheader_sent && GST_EVENT_IS_SERIALIZED (event)) + ret = vorbis_parse_queue_event (parse, event); + else + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (parse); + + return ret; +} + +static gboolean +vorbis_parse_convert (GstPad * pad, + GstFormat src_format, gint64 src_value, + GstFormat * dest_format, gint64 * dest_value) +{ + gboolean res = TRUE; + GstVorbisParse *parse; + guint64 scale = 1; + + parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad)); + + /* fixme: assumes atomic access to lots of instance variables modified from + * the streaming thread, including 64-bit variables */ + + if (parse->packetno < 4) + return FALSE; + + if (src_format == *dest_format) { + *dest_value = src_value; + return TRUE; + } + + if (parse->sinkpad == pad && + (src_format == GST_FORMAT_BYTES || *dest_format == GST_FORMAT_BYTES)) + return FALSE; + + switch (src_format) { + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_BYTES: + scale = sizeof (float) * parse->vi.channels; + case GST_FORMAT_DEFAULT: + *dest_value = + scale * gst_util_uint64_scale_int (src_value, parse->vi.rate, + GST_SECOND); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_BYTES: + *dest_value = src_value * sizeof (float) * parse->vi.channels; + break; + case GST_FORMAT_TIME: + *dest_value = + gst_util_uint64_scale_int (src_value, GST_SECOND, parse->vi.rate); + break; + default: + res = FALSE; + } + break; + case GST_FORMAT_BYTES: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = src_value / (sizeof (float) * parse->vi.channels); + break; + case GST_FORMAT_TIME: + *dest_value = gst_util_uint64_scale_int (src_value, GST_SECOND, + parse->vi.rate * sizeof (float) * parse->vi.channels); + break; + default: + res = FALSE; + } + break; + default: + res = FALSE; + } + + return res; +} + +static gboolean +vorbis_parse_src_query (GstPad * pad, GstQuery * query) +{ + gint64 granulepos; + GstVorbisParse *parse; + gboolean res = FALSE; + + parse = GST_VORBIS_PARSE (GST_PAD_PARENT (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + gint64 value; + + granulepos = parse->prev_granulepos; + + gst_query_parse_position (query, &format, NULL); + + /* and convert to the final format */ + if (!(res = + vorbis_parse_convert (pad, GST_FORMAT_DEFAULT, granulepos, + &format, &value))) + goto error; + + /* fixme: support segments + value = (value - parse->segment_start) + parse->segment_time; + */ + + gst_query_set_position (query, format, value); + + GST_LOG_OBJECT (parse, "query %p: peer returned granulepos: %" + G_GUINT64_FORMAT " - we return %" G_GUINT64_FORMAT " (format %u)", + query, granulepos, value, format); + + break; + } + case GST_QUERY_DURATION: + { + /* fixme: not threadsafe */ + /* query peer for total length */ + if (!gst_pad_is_linked (parse->sinkpad)) { + GST_WARNING_OBJECT (parse, "sink pad %" GST_PTR_FORMAT " is not linked", + parse->sinkpad); + goto error; + } + if (!(res = gst_pad_query (GST_PAD_PEER (parse->sinkpad), query))) + goto error; + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (!(res = + vorbis_parse_convert (pad, src_fmt, src_val, &dest_fmt, + &dest_val))) + goto error; + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + return res; + +error: + { + GST_WARNING_OBJECT (parse, "error handling query"); + return res; + } +} + +static GstStateChangeReturn +vorbis_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstVorbisParse *parse = GST_VORBIS_PARSE (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + vorbis_info_init (&parse->vi); + vorbis_comment_init (&parse->vc); + parse->prev_granulepos = -1; + parse->prev_blocksize = -1; + parse->packetno = 0; + parse->streamheader_sent = FALSE; + parse->buffer_queue = g_queue_new (); + parse->event_queue = g_queue_new (); + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + vorbis_info_clear (&parse->vi); + vorbis_comment_clear (&parse->vc); + vorbis_parse_clear_queue (parse); + g_queue_free (parse->buffer_queue); + parse->buffer_queue = NULL; + g_queue_free (parse->event_queue); + parse->event_queue = NULL; + break; + default: + break; + } + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.h new file mode 100644 index 0000000..6538949 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbisparse.h @@ -0,0 +1,82 @@ +/* -*- c-basic-offset: 2 -*- + * GStreamer + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_VORBIS_PARSE_H__ +#define __GST_VORBIS_PARSE_H__ + + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VORBIS_PARSE \ + (gst_vorbis_parse_get_type()) +#define GST_VORBIS_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_PARSE,GstVorbisParse)) +#define GST_VORBIS_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_PARSE,GstVorbisParseClass)) +#define GST_IS_VORBIS_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_PARSE)) +#define GST_IS_VORBIS_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_PARSE)) + +typedef struct _GstVorbisParse GstVorbisParse; +typedef struct _GstVorbisParseClass GstVorbisParseClass; + +/** + * GstVorbisParse: + * + * Opaque data structure. + */ +struct _GstVorbisParse { + GstElement element; + + GstPad * sinkpad; + GstPad * srcpad; + + guint packetno; + gboolean streamheader_sent; + GList * streamheader; + + GQueue * event_queue; + GQueue * buffer_queue; + + vorbis_info vi; + vorbis_comment vc; + + gint64 prev_granulepos; + gint32 prev_blocksize; + guint32 sample_rate; +}; + +struct _GstVorbisParseClass { + GstElementClass parent_class; + + /* virtual functions */ + GstFlowReturn (*parse_packet) (GstVorbisParse * parse, GstBuffer * buf); +}; + +GType gst_vorbis_parse_get_type(void); + +G_END_DECLS + +#endif /* __GST_VORBIS_PARSE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.c b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.c new file mode 100644 index 0000000..8a2db41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.c @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2006 James Livingston + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-vorbistag + * @see_also: #oggdemux, #oggmux, #vorbisparse, #GstTagSetter + * + * The vorbistags element can change the tag contained within a raw + * vorbis stream. Specifically, it modifies the comments header packet + * of the vorbis stream. + * + * The element will also process the stream as the #vorbisparse element does + * so it can be used when remuxing an Ogg Vorbis stream, without additional + * elements. + * + * Applications can set the tags to write using the #GstTagSetter interface. + * Tags contained withing the vorbis bitstream will be picked up + * automatically (and merged according to the merge mode set via the tag + * setter interface). + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=foo.ogg ! oggdemux ! vorbistag ! oggmux ! filesink location=bar.ogg + * ]| This element is not useful with gst-launch, because it does not support + * setting the tags on a #GstTagSetter interface. Conceptually, the element + * will usually be used in this order though. + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include + +#include "gstvorbistag.h" + + +GST_DEBUG_CATEGORY_EXTERN (vorbisparse_debug); +#define GST_CAT_DEFAULT vorbisparse_debug + +static GstFlowReturn gst_vorbis_tag_parse_packet (GstVorbisParse * parse, + GstBuffer * buffer); + +#define _do_init(type) \ + G_STMT_START{ \ + static const GInterfaceInfo tag_setter_info = { \ + NULL, \ + NULL, \ + NULL \ + }; \ + g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, \ + &tag_setter_info); \ + }G_STMT_END + +GST_BOILERPLATE_FULL (GstVorbisTag, gst_vorbis_tag, GstVorbisParse, + GST_TYPE_VORBIS_PARSE, _do_init); + + +static void +gst_vorbis_tag_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "VorbisTag", "Formatter/Metadata", + "Retags vorbis streams", "James Livingston "); +} + +static void +gst_vorbis_tag_class_init (GstVorbisTagClass * klass) +{ + GstVorbisParseClass *vorbisparse_class = GST_VORBIS_PARSE_CLASS (klass); + + vorbisparse_class->parse_packet = gst_vorbis_tag_parse_packet; +} + +static void +gst_vorbis_tag_init (GstVorbisTag * tagger, GstVorbisTagClass * g_class) +{ + /* nothing to do */ +} + + +static GstFlowReturn +gst_vorbis_tag_parse_packet (GstVorbisParse * parse, GstBuffer * buffer) +{ + GstTagList *old_tags, *new_tags; + const GstTagList *user_tags; + GstVorbisTag *tagger; + gchar *encoder = NULL; + GstBuffer *new_buf; + + /* just pass everything except the comments packet */ + if (GST_BUFFER_SIZE (buffer) >= 1 && GST_BUFFER_DATA (buffer)[0] != 0x03) { + return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, buffer); + } + + tagger = GST_VORBIS_TAG (parse); + + old_tags = + gst_tag_list_from_vorbiscomment_buffer (buffer, (guint8 *) "\003vorbis", + 7, &encoder); + user_tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (tagger)); + + /* build new tag list */ + new_tags = gst_tag_list_merge (user_tags, old_tags, + gst_tag_setter_get_tag_merge_mode (GST_TAG_SETTER (tagger))); + gst_tag_list_free (old_tags); + + new_buf = + gst_tag_list_to_vorbiscomment_buffer (new_tags, (guint8 *) "\003vorbis", + 7, encoder); + gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + + gst_tag_list_free (new_tags); + g_free (encoder); + gst_buffer_unref (buffer); + + return GST_VORBIS_PARSE_CLASS (parent_class)->parse_packet (parse, new_buf); +} diff --git a/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.h b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.h new file mode 100644 index 0000000..9a44300 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/ext/vorbis/gstvorbistag.h @@ -0,0 +1,63 @@ +/* -*- c-basic-offset: 2 -*- + * GStreamer + * Copyright (C) <2006> James Livingston + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_VORBIS_TAG_H__ +#define __GST_VORBIS_TAG_H__ + +#include "gstvorbisparse.h" + + +G_BEGIN_DECLS + + +#define GST_TYPE_VORBIS_TAG \ + (gst_vorbis_tag_get_type()) +#define GST_VORBIS_TAG(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VORBIS_TAG,GstVorbisTag)) +#define GST_VORBIS_TAG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VORBIS_TAG,GstVorbisTagClass)) +#define GST_IS_VORBIS_TAG(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VORBIS_TAG)) +#define GST_IS_VORBIS_TAG_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VORBIS_TAG)) + + +typedef struct _GstVorbisTag GstVorbisTag; +typedef struct _GstVorbisTagClass GstVorbisTagClass; + +/** + * GstVorbisTag: + * + * Opaque data structure. + */ +struct _GstVorbisTag { + GstVorbisParse parse; +}; + +struct _GstVorbisTagClass { + GstVorbisParseClass parent_class; +}; + +GType gst_vorbis_tag_get_type(void); + +G_END_DECLS + +#endif /* __GST_VORBIS_TAG_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/Makefile.am new file mode 100644 index 0000000..062cb55 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = gst diff --git a/gst-plugins-base-subtitles0.10/gst-libs/ext/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/ext/.gitignore new file mode 100644 index 0000000..20645e6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/ext/.gitignore @@ -0,0 +1 @@ +ffmpeg diff --git a/gst-plugins-base-subtitles0.10/gst-libs/ext/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/ext/Makefile.am new file mode 100644 index 0000000..f9beb01 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/ext/Makefile.am @@ -0,0 +1,2 @@ +SUBDIRS = +DIST_SUBDIRS = diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/Makefile.am new file mode 100644 index 0000000..c776f8e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/Makefile.am @@ -0,0 +1,44 @@ +# The interfaces directory has to be built before the others, +# otherwise some generated header files will be missing for the +# plugins in the other directories. +# Also, the tag directory has to be built before the cdda directory. +SUBDIRS = \ + interfaces \ + tag \ + audio \ + cdda \ + fft \ + floatcast \ + netbuffer \ + riff \ + rtp \ + sdp \ + rtsp \ + video \ + pbutils \ + app + +noinst_HEADERS = gettext.h gst-i18n-plugin.h + +# dependencies: +audio: interfaces + +cdda: tag + +riff: tag audio + +rtsp: sdp + +pbutils: video + +INDEPENDENT_SUBDIRS = \ + interfaces tag fft floatcast netbuffer rtp sdp video app + +.PHONY: independent-subdirs $(INDEPENDENT_SUBDIRS) + +independent-subdirs: $(INDEPENDENT_SUBDIRS) + +$(INDEPENDENT_SUBDIRS): + $(MAKE) -C $@ + +all-recursive: independent-subdirs diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/.gitignore new file mode 100644 index 0000000..9f0ae4b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/.gitignore @@ -0,0 +1,2 @@ +gstapp-marshal.c +gstapp-marshal.h diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/Makefile.am new file mode 100644 index 0000000..bbd3df7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/Makefile.am @@ -0,0 +1,99 @@ +lib_LTLIBRARIES = libgstapp-@GST_MAJORMINOR@.la + +glib_enum_define = GST_APP +glib_gen_prefix = __gst_app +glib_gen_basename = gstapp + +include $(top_srcdir)/common/gst-glib-gen.mak + +built_sources = gstapp-marshal.c +built_headers = gstapp-marshal.h + +BUILT_SOURCES = $(built_sources) $(built_headers) + +nodist_libgstapp_@GST_MAJORMINOR@_la_SOURCES = \ + $(built_sources) + +libgstapp_@GST_MAJORMINOR@_la_SOURCES = gstappsrc.c gstappbuffer.c gstappsink.c +libgstapp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstapp_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) +libgstapp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) +libgstapp_@GST_MAJORMINOR@_la_LIBTOOLFLAGS = --tag=disable-static + +libgstapp_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/app +libgstapp_@GST_MAJORMINOR@include_HEADERS = \ + gstappsrc.h \ + gstappbuffer.h \ + gstappsink.h + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = gstapp-marshal.list + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstApp-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstapp_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstapp_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstapp_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/app/%',$(libgstapp_@GST_MAJORMINOR@include_HEADERS)) + +GstApp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstapp-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstApp \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstapp-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-app-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstapp -:SHARED libgstapp-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstapp_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstapp_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstapp_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstapp_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstapp_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/app \ + -:HEADERS $(libgstapp_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstapp-marshal.list b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstapp-marshal.list new file mode 100644 index 0000000..ad35948 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstapp-marshal.list @@ -0,0 +1,5 @@ +BOOLEAN:UINT64 +ENUM:OBJECT +ENUM:VOID +VOID:UINT + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.c new file mode 100644 index 0000000..2fa72bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.c @@ -0,0 +1,108 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +#include "gstappbuffer.h" + +static void gst_app_buffer_init (GstAppBuffer * buffer, gpointer g_class); +static void gst_app_buffer_class_init (gpointer g_class, gpointer class_data); +static void gst_app_buffer_finalize (GstAppBuffer * buffer); + +static GstBufferClass *parent_class; + +GType +gst_app_buffer_get_type (void) +{ + static volatile gsize app_buffer_type = 0; + + if (g_once_init_enter (&app_buffer_type)) { + static const GTypeInfo app_buffer_info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_app_buffer_class_init, + NULL, + NULL, + sizeof (GstAppBuffer), + 0, + (GInstanceInitFunc) gst_app_buffer_init, + NULL + }; + GType tmp = g_type_register_static (GST_TYPE_BUFFER, "GstAppBuffer", + &app_buffer_info, 0); + g_once_init_leave (&app_buffer_type, tmp); + } + + return (GType) app_buffer_type; +} + +static void +gst_app_buffer_init (GstAppBuffer * buffer, gpointer g_class) +{ + +} + +static void +gst_app_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + mini_object_class->finalize = + (GstMiniObjectFinalizeFunction) gst_app_buffer_finalize; + + parent_class = g_type_class_peek_parent (g_class); +} + +static void +gst_app_buffer_finalize (GstAppBuffer * buffer) +{ + g_return_if_fail (buffer != NULL); + g_return_if_fail (GST_IS_APP_BUFFER (buffer)); + + if (buffer->finalize) { + buffer->finalize (buffer->priv); + } + + GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (buffer)); +} + +GstBuffer * +gst_app_buffer_new (void *data, int length, + GstAppBufferFinalizeFunc finalize, void *priv) +{ + GstAppBuffer *buffer; + + buffer = (GstAppBuffer *) gst_mini_object_new (GST_TYPE_APP_BUFFER); + + GST_BUFFER_DATA (buffer) = data; + GST_BUFFER_SIZE (buffer) = length; + + buffer->finalize = finalize; + buffer->priv = priv; + + return GST_BUFFER (buffer); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.h new file mode 100644 index 0000000..532f2ae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappbuffer.h @@ -0,0 +1,64 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_APP_BUFFER_H_ +#define _GST_APP_BUFFER_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_APP_BUFFER \ + (gst_app_buffer_get_type()) +#define GST_APP_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_BUFFER,GstAppBuffer)) +#define GST_APP_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_BUFFER,GstAppBufferClass)) +#define GST_IS_APP_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_BUFFER)) +#define GST_IS_APP_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_BUFFER)) + +typedef struct _GstAppBuffer GstAppBuffer; +typedef struct _GstAppBufferClass GstAppBufferClass; +typedef void (*GstAppBufferFinalizeFunc) (void *priv); + +struct _GstAppBuffer +{ + GstBuffer buffer; + + /*< private >*/ + GstAppBufferFinalizeFunc finalize; + void *priv; +}; + +struct _GstAppBufferClass +{ + GstBufferClass buffer_class; +}; + +GType gst_app_buffer_get_type(void); + +GstBuffer *gst_app_buffer_new (void *data, int length, + GstAppBufferFinalizeFunc finalize, void *priv); + +G_END_DECLS + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.c new file mode 100644 index 0000000..07a3989 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.c @@ -0,0 +1,1443 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-appsink + * + * Appsink is a sink plugin that supports many different methods for making + * the application get a handle on the GStreamer data in a pipeline. Unlike + * most GStreamer elements, Appsink provides external API functions. + * + * For the documentation of the API, please see the + * libgstapp section in + * the GStreamer Plugins Base Libraries documentation. + * + * Since: 0.10.22 + */ + + +/** + * SECTION:gstappsink + * @short_description: Easy way for applications to extract buffers from a + * pipeline + * @see_also: #GstBaseSink, appsrc + * + * Appsink is a sink plugin that supports many different methods for making + * the application get a handle on the GStreamer data in a pipeline. Unlike + * most GStreamer elements, Appsink provides external API functions. + * + * appsink can be used by linking to the gstappsink.h header file to access the + * methods or by using the appsink action signals and properties. + * + * The normal way of retrieving buffers from appsink is by using the + * gst_app_sink_pull_buffer() and gst_app_sink_pull_preroll() methods. + * These methods block until a buffer becomes available in the sink or when the + * sink is shut down or reaches EOS. + * + * Appsink will internally use a queue to collect buffers from the streaming + * thread. If the application is not pulling buffers fast enough, this queue + * will consume a lot of memory over time. The "max-buffers" property can be + * used to limit the queue size. The "drop" property controls whether the + * streaming thread blocks or if older buffers are dropped when the maximum + * queue size is reached. Note that blocking the streaming thread can negatively + * affect real-time performance and should be avoided. + * + * If a blocking behaviour is not desirable, setting the "emit-signals" property + * to %TRUE will make appsink emit the "new-buffer" and "new-preroll" signals + * when a buffer can be pulled without blocking. + * + * The "caps" property on appsink can be used to control the formats that + * appsink can receive. This property can contain non-fixed caps, the format of + * the pulled buffers can be obtained by getting the buffer caps. + * + * If one of the pull-preroll or pull-buffer methods return %NULL, the appsink + * is stopped or in the EOS state. You can check for the EOS state with the + * "eos" property or with the gst_app_sink_is_eos() method. + * + * The eos signal can also be used to be informed when the EOS state is reached + * to avoid polling. + * + * Last reviewed on 2008-12-17 (0.10.22) + * + * Since: 0.10.22 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include + +#include "gstappsink.h" + +struct _GstAppSinkPrivate +{ + GstCaps *caps; + gboolean emit_signals; + guint max_buffers; + gboolean drop; + + GCond *cond; + GMutex *mutex; + GQueue *queue; + GstBuffer *preroll; + gboolean flushing; + gboolean unlock; + gboolean started; + gboolean is_eos; + + GstAppSinkCallbacks callbacks; + gpointer user_data; + GDestroyNotify notify; + + gboolean buffer_lists_supported; +}; + +GST_DEBUG_CATEGORY_STATIC (app_sink_debug); +#define GST_CAT_DEFAULT app_sink_debug + +enum +{ + /* signals */ + SIGNAL_EOS, + SIGNAL_NEW_PREROLL, + SIGNAL_NEW_BUFFER, + SIGNAL_NEW_BUFFER_LIST, + + /* actions */ + SIGNAL_PULL_PREROLL, + SIGNAL_PULL_BUFFER, + SIGNAL_PULL_BUFFER_LIST, + + LAST_SIGNAL +}; + +#define DEFAULT_PROP_EOS TRUE +#define DEFAULT_PROP_EMIT_SIGNALS FALSE +#define DEFAULT_PROP_MAX_BUFFERS 0 +#define DEFAULT_PROP_DROP FALSE + +enum +{ + PROP_0, + PROP_CAPS, + PROP_EOS, + PROP_EMIT_SIGNALS, + PROP_MAX_BUFFERS, + PROP_DROP, + PROP_LAST +}; + +static GstStaticPadTemplate gst_app_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_app_sink_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static void gst_app_sink_dispose (GObject * object); +static void gst_app_sink_finalize (GObject * object); + +static void gst_app_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_app_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_app_sink_unlock_start (GstBaseSink * bsink); +static gboolean gst_app_sink_unlock_stop (GstBaseSink * bsink); +static gboolean gst_app_sink_start (GstBaseSink * psink); +static gboolean gst_app_sink_stop (GstBaseSink * psink); +static gboolean gst_app_sink_event (GstBaseSink * sink, GstEvent * event); +static GstFlowReturn gst_app_sink_preroll (GstBaseSink * psink, + GstBuffer * buffer); +static GstFlowReturn gst_app_sink_render_common (GstBaseSink * psink, + GstMiniObject * data, gboolean is_list); +static GstFlowReturn gst_app_sink_render (GstBaseSink * psink, + GstBuffer * buffer); +static GstFlowReturn gst_app_sink_render_list (GstBaseSink * psink, + GstBufferList * list); +static GstCaps *gst_app_sink_getcaps (GstBaseSink * psink); +static GstMiniObject *gst_app_sink_pull_object (GstAppSink * appsink); + +static guint gst_app_sink_signals[LAST_SIGNAL] = { 0 }; + +static void +_do_init (GType filesrc_type) +{ + static const GInterfaceInfo urihandler_info = { + gst_app_sink_uri_handler_init, + NULL, + NULL + }; + g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, + &urihandler_info); +} + +GST_BOILERPLATE_FULL (GstAppSink, gst_app_sink, GstBaseSink, GST_TYPE_BASE_SINK, + _do_init); + +/* Can't use glib-genmarshal for this, as it doesn't know how to handle + * GstMiniObject-based types, which are a new fundamental type */ +static void +gst_app_marshal_BUFFER__VOID (GClosure * closure, + GValue * return_value, + guint n_param_values, + const GValue * param_values, + gpointer invocation_hint, gpointer marshal_data) +{ + typedef GstBuffer *(*GMarshalFunc_BUFFER__VOID) (gpointer data1, + gpointer data2); + register GMarshalFunc_BUFFER__VOID callback; + register GCClosure *cc = (GCClosure *) closure; + register gpointer data1, data2; + GstBuffer *v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 1); + + if (G_CCLOSURE_SWAP_DATA (closure)) { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } else { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = + (GMarshalFunc_BUFFER__VOID) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, data2); + + gst_value_take_buffer (return_value, v_return); +} + +static void +gst_app_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (app_sink_debug, "appsink", 0, "appsink element"); + + gst_element_class_set_details_simple (element_class, "AppSink", + "Generic/Sink", "Allow the application to get access to raw buffer", + "David Schleef , Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_app_sink_template)); +} + +static void +gst_app_sink_class_init (GstAppSinkClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass; + + gobject_class->dispose = gst_app_sink_dispose; + gobject_class->finalize = gst_app_sink_finalize; + + gobject_class->set_property = gst_app_sink_set_property; + gobject_class->get_property = gst_app_sink_get_property; + + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Caps", + "The allowed caps for the sink pad", GST_TYPE_CAPS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EOS, + g_param_spec_boolean ("eos", "EOS", + "Check if the sink is EOS or not started", DEFAULT_PROP_EOS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS, + g_param_spec_boolean ("emit-signals", "Emit signals", + "Emit new-preroll, new-buffer and new-buffer-list signals", + DEFAULT_PROP_EMIT_SIGNALS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_BUFFERS, + g_param_spec_uint ("max-buffers", "Max Buffers", + "The maximum number of buffers to queue internally (0 = unlimited)", + 0, G_MAXUINT, DEFAULT_PROP_MAX_BUFFERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_DROP, + g_param_spec_boolean ("drop", "Drop", + "Drop old buffers when the buffer queue is filled", DEFAULT_PROP_DROP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAppSink::eos: + * @appsink: the appsink element that emited the signal + * + * Signal that the end-of-stream has been reached. This signal is emited from + * the steaming thread. + */ + gst_app_sink_signals[SIGNAL_EOS] = + g_signal_new ("eos", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSinkClass, eos), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstAppSink::new-preroll: + * @appsink: the appsink element that emited the signal + * + * Signal that a new preroll buffer is available. + * + * This signal is emited from the steaming thread and only when the + * "emit-signals" property is %TRUE. + * + * The new preroll buffer can be retrieved with the "pull-preroll" action + * signal or gst_app_sink_pull_preroll() either from this signal callback + * or from any other thread. + * + * Note that this signal is only emited when the "emit-signals" property is + * set to %TRUE, which it is not by default for performance reasons. + */ + gst_app_sink_signals[SIGNAL_NEW_PREROLL] = + g_signal_new ("new-preroll", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSinkClass, new_preroll), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstAppSink::new-buffer: + * @appsink: the appsink element that emited the signal + * + * Signal that a new buffer is available. + * + * This signal is emited from the steaming thread and only when the + * "emit-signals" property is %TRUE. + * + * The new buffer can be retrieved with the "pull-buffer" action + * signal or gst_app_sink_pull_buffer() either from this signal callback + * or from any other thread. + * + * Note that this signal is only emited when the "emit-signals" property is + * set to %TRUE, which it is not by default for performance reasons. + */ + gst_app_sink_signals[SIGNAL_NEW_BUFFER] = + g_signal_new ("new-buffer", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSinkClass, new_buffer), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstAppSink::new-buffer-list: + * @appsink: the appsink element that emited the signal + * + * Signal that a new bufferlist is available. + * + * This signal is emited from the steaming thread and only when the + * "emit-signals" property is %TRUE. + * + * The new buffer can be retrieved with the "pull-buffer-list" action + * signal or gst_app_sink_pull_buffer_list() either from this signal callback + * or from any other thread. + * + * Note that this signal is only emited when the "emit-signals" property is + * set to %TRUE, which it is not by default for performance reasons. + */ + gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] = + g_signal_new ("new-buffer-list", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstAppSinkClass, new_buffer_list), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstAppSink::pull-preroll: + * @appsink: the appsink element to emit this signal on + * + * Get the last preroll buffer in @appsink. This was the buffer that caused the + * appsink to preroll in the PAUSED state. This buffer can be pulled many times + * and remains available to the application even after EOS. + * + * This function is typically used when dealing with a pipeline in the PAUSED + * state. Calling this function after doing a seek will give the buffer right + * after the seek position. + * + * Note that the preroll buffer will also be returned as the first buffer + * when calling gst_app_sink_pull_buffer() or the "pull-buffer" action signal. + * + * If an EOS event was received before any buffers, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * This function blocks until a preroll buffer or EOS is received or the appsink + * element is set to the READY/NULL state. + * + * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. + */ + gst_app_sink_signals[SIGNAL_PULL_PREROLL] = + g_signal_new ("pull-preroll", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass, + pull_preroll), NULL, NULL, gst_app_marshal_BUFFER__VOID, + GST_TYPE_BUFFER, 0, G_TYPE_NONE); + /** + * GstAppSink::pull-buffer: + * @appsink: the appsink element to emit this signal on + * + * This function blocks until a buffer or EOS becomes available or the appsink + * element is set to the READY/NULL state. + * + * This function will only return buffers when the appsink is in the PLAYING + * state. All rendered buffers will be put in a queue so that the application + * can pull buffers at its own rate. + * + * Note that when the application does not pull buffers fast enough, the + * queued buffers could consume a lot of memory, especially when dealing with + * raw video frames. It's possible to control the behaviour of the queue with + * the "drop" and "max-buffers" properties. + * + * If an EOS event was received before any buffers, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. + */ + gst_app_sink_signals[SIGNAL_PULL_BUFFER] = + g_signal_new ("pull-buffer", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass, + pull_buffer), NULL, NULL, gst_app_marshal_BUFFER__VOID, + GST_TYPE_BUFFER, 0, G_TYPE_NONE); + /** + * GstAppSink::pull-buffer-list: + * @appsink: the appsink element to emit this signal on + * + * This function blocks until a buffer list or EOS becomes available or the appsink + * element is set to the READY/NULL state. + * + * This function will only return bufferlists when the appsink is in the PLAYING + * state. All rendered bufferlists will be put in a queue so that the application + * can pull bufferlists at its own rate. + * + * Note that when the application does not pull bufferlists fast enough, the + * queued bufferlists could consume a lot of memory, especially when dealing with + * raw video frames. It's possible to control the behaviour of the queue with + * the "drop" and "max-buffers" properties. + * + * If an EOS event was received before any buffers, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS. + */ + gst_app_sink_signals[SIGNAL_PULL_BUFFER_LIST] = + g_signal_new ("pull-buffer-list", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSinkClass, + pull_buffer_list), NULL, NULL, gst_app_marshal_BUFFER__VOID, + GST_TYPE_BUFFER_LIST, 0, G_TYPE_NONE); + + basesink_class->unlock = gst_app_sink_unlock_start; + basesink_class->unlock_stop = gst_app_sink_unlock_stop; + basesink_class->start = gst_app_sink_start; + basesink_class->stop = gst_app_sink_stop; + basesink_class->event = gst_app_sink_event; + basesink_class->preroll = gst_app_sink_preroll; + basesink_class->render = gst_app_sink_render; + basesink_class->render_list = gst_app_sink_render_list; + basesink_class->get_caps = gst_app_sink_getcaps; + + klass->pull_preroll = gst_app_sink_pull_preroll; + klass->pull_buffer = gst_app_sink_pull_buffer; + klass->pull_buffer_list = gst_app_sink_pull_buffer_list; + + g_type_class_add_private (klass, sizeof (GstAppSinkPrivate)); +} + +static void +gst_app_sink_init (GstAppSink * appsink, GstAppSinkClass * klass) +{ + GstAppSinkPrivate *priv; + + priv = appsink->priv = + G_TYPE_INSTANCE_GET_PRIVATE (appsink, GST_TYPE_APP_SINK, + GstAppSinkPrivate); + + priv->mutex = g_mutex_new (); + priv->cond = g_cond_new (); + priv->queue = g_queue_new (); + + priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS; + priv->max_buffers = DEFAULT_PROP_MAX_BUFFERS; + priv->drop = DEFAULT_PROP_DROP; +} + +static void +gst_app_sink_dispose (GObject * obj) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (obj); + GstAppSinkPrivate *priv = appsink->priv; + GstMiniObject *queue_obj; + + GST_OBJECT_LOCK (appsink); + if (priv->caps) { + gst_caps_unref (priv->caps); + priv->caps = NULL; + } + if (priv->notify) { + priv->notify (priv->user_data); + } + priv->user_data = NULL; + priv->notify = NULL; + + GST_OBJECT_UNLOCK (appsink); + + g_mutex_lock (priv->mutex); + if (priv->preroll) { + gst_buffer_unref (priv->preroll); + priv->preroll = NULL; + } + while ((queue_obj = g_queue_pop_head (priv->queue))) + gst_mini_object_unref (queue_obj); + g_mutex_unlock (priv->mutex); + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +static void +gst_app_sink_finalize (GObject * obj) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (obj); + GstAppSinkPrivate *priv = appsink->priv; + + g_mutex_free (priv->mutex); + g_cond_free (priv->cond); + g_queue_free (priv->queue); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_app_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (object); + + switch (prop_id) { + case PROP_CAPS: + gst_app_sink_set_caps (appsink, gst_value_get_caps (value)); + break; + case PROP_EMIT_SIGNALS: + gst_app_sink_set_emit_signals (appsink, g_value_get_boolean (value)); + break; + case PROP_MAX_BUFFERS: + gst_app_sink_set_max_buffers (appsink, g_value_get_uint (value)); + break; + case PROP_DROP: + gst_app_sink_set_drop (appsink, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_app_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (object); + + switch (prop_id) { + case PROP_CAPS: + { + GstCaps *caps; + + caps = gst_app_sink_get_caps (appsink); + gst_value_set_caps (value, caps); + if (caps) + gst_caps_unref (caps); + break; + } + case PROP_EOS: + g_value_set_boolean (value, gst_app_sink_is_eos (appsink)); + break; + case PROP_EMIT_SIGNALS: + g_value_set_boolean (value, gst_app_sink_get_emit_signals (appsink)); + break; + case PROP_MAX_BUFFERS: + g_value_set_uint (value, gst_app_sink_get_max_buffers (appsink)); + break; + case PROP_DROP: + g_value_set_boolean (value, gst_app_sink_get_drop (appsink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_app_sink_unlock_start (GstBaseSink * bsink) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (bsink); + GstAppSinkPrivate *priv = appsink->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "unlock start"); + priv->unlock = TRUE; + g_cond_signal (priv->cond); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_sink_unlock_stop (GstBaseSink * bsink) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (bsink); + GstAppSinkPrivate *priv = appsink->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "unlock stop"); + priv->unlock = FALSE; + g_cond_signal (priv->cond); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static void +gst_app_sink_flush_unlocked (GstAppSink * appsink) +{ + GstMiniObject *obj; + GstAppSinkPrivate *priv = appsink->priv; + + GST_DEBUG_OBJECT (appsink, "flush stop appsink"); + priv->is_eos = FALSE; + gst_buffer_replace (&priv->preroll, NULL); + while ((obj = g_queue_pop_head (priv->queue))) + gst_mini_object_unref (obj); + g_cond_signal (priv->cond); +} + +#define NEW_BUFFER_LIST_SIGID \ + gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST] + +static gboolean +gst_app_sink_check_buffer_lists_support (GstAppSink * appsink) +{ + gboolean ret; + + ret = (appsink->priv->callbacks.new_buffer_list != NULL) || + g_signal_has_handler_pending (appsink, NEW_BUFFER_LIST_SIGID, 0, FALSE); + + GST_INFO_OBJECT (appsink, "application supports buffer lists: %d", ret); + return ret; +} + +static gboolean +gst_app_sink_start (GstBaseSink * psink) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (psink); + GstAppSinkPrivate *priv = appsink->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "starting"); + priv->flushing = FALSE; + priv->started = TRUE; + priv->buffer_lists_supported = + gst_app_sink_check_buffer_lists_support (appsink); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_sink_stop (GstBaseSink * psink) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (psink); + GstAppSinkPrivate *priv = appsink->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "stopping"); + priv->flushing = TRUE; + priv->started = FALSE; + gst_app_sink_flush_unlocked (appsink); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_sink_event (GstBaseSink * sink, GstEvent * event) +{ + GstAppSink *appsink = GST_APP_SINK_CAST (sink); + GstAppSinkPrivate *priv = appsink->priv; + + switch (event->type) { + case GST_EVENT_EOS: + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "receiving EOS"); + priv->is_eos = TRUE; + g_cond_signal (priv->cond); + g_mutex_unlock (priv->mutex); + + /* emit EOS now */ + if (priv->callbacks.eos) + priv->callbacks.eos (appsink, priv->user_data); + else + g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_EOS], 0); + + break; + case GST_EVENT_FLUSH_START: + /* we don't have to do anything here, the base class will call unlock + * which will make sure we exit the _render method */ + GST_DEBUG_OBJECT (appsink, "received FLUSH_START"); + break; + case GST_EVENT_FLUSH_STOP: + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsink, "received FLUSH_STOP"); + gst_app_sink_flush_unlocked (appsink); + g_mutex_unlock (priv->mutex); + break; + default: + break; + } + return TRUE; +} + +static GstFlowReturn +gst_app_sink_preroll (GstBaseSink * psink, GstBuffer * buffer) +{ + GstFlowReturn res = GST_FLOW_OK; + GstAppSink *appsink = GST_APP_SINK_CAST (psink); + GstAppSinkPrivate *priv = appsink->priv; + gboolean emit; + + g_mutex_lock (priv->mutex); + if (priv->flushing) + goto flushing; + + GST_DEBUG_OBJECT (appsink, "setting preroll buffer %p", buffer); + gst_buffer_replace (&priv->preroll, buffer); + + g_cond_signal (priv->cond); + emit = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + if (priv->callbacks.new_preroll) + res = priv->callbacks.new_preroll (appsink, priv->user_data); + else if (emit) + g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_PREROLL], 0); + + return res; + +flushing: + { + GST_DEBUG_OBJECT (appsink, "we are flushing"); + g_mutex_unlock (priv->mutex); + return GST_FLOW_WRONG_STATE; + } +} + +static GstFlowReturn +gst_app_sink_render_common (GstBaseSink * psink, GstMiniObject * data, + gboolean is_list) +{ + GstFlowReturn ret; + GstAppSink *appsink = GST_APP_SINK_CAST (psink); + GstAppSinkPrivate *priv = appsink->priv; + gboolean emit; + +restart: + g_mutex_lock (priv->mutex); + if (priv->flushing) + goto flushing; + + GST_DEBUG_OBJECT (appsink, "pushing render buffer%s %p on queue (%d)", + is_list ? " list" : "", data, priv->queue->length); + + while (priv->max_buffers > 0 && priv->queue->length >= priv->max_buffers) { + if (priv->drop) { + GstMiniObject *obj; + + /* we need to drop the oldest buffer/list and try again */ + obj = g_queue_pop_head (priv->queue); + GST_DEBUG_OBJECT (appsink, "dropping old buffer/list %p", obj); + gst_mini_object_unref (obj); + } else { + GST_DEBUG_OBJECT (appsink, "waiting for free space, length %d >= %d", + priv->queue->length, priv->max_buffers); + + if (priv->unlock) { + /* we are asked to unlock, call the wait_preroll method */ + g_mutex_unlock (priv->mutex); + if ((ret = gst_base_sink_wait_preroll (psink)) != GST_FLOW_OK) + goto stopping; + + /* we are allowed to continue now */ + goto restart; + } + + /* wait for a buffer to be removed or flush */ + g_cond_wait (priv->cond, priv->mutex); + if (priv->flushing) + goto flushing; + } + } + /* we need to ref the buffer when pushing it in the queue */ + g_queue_push_tail (priv->queue, gst_mini_object_ref (data)); + g_cond_signal (priv->cond); + emit = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + if (is_list) { + if (priv->callbacks.new_buffer_list) + priv->callbacks.new_buffer_list (appsink, priv->user_data); + else if (emit) + g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER_LIST], 0); + } else { + if (priv->callbacks.new_buffer) + priv->callbacks.new_buffer (appsink, priv->user_data); + else if (emit) + g_signal_emit (appsink, gst_app_sink_signals[SIGNAL_NEW_BUFFER], 0); + } + return GST_FLOW_OK; + +flushing: + { + GST_DEBUG_OBJECT (appsink, "we are flushing"); + g_mutex_unlock (priv->mutex); + return GST_FLOW_WRONG_STATE; + } +stopping: + { + GST_DEBUG_OBJECT (appsink, "we are stopping"); + return ret; + } +} + +static GstFlowReturn +gst_app_sink_render (GstBaseSink * psink, GstBuffer * buffer) +{ + return gst_app_sink_render_common (psink, GST_MINI_OBJECT_CAST (buffer), + FALSE); +} + +static GstFlowReturn +gst_app_sink_render_list (GstBaseSink * sink, GstBufferList * list) +{ + GstBufferListIterator *it; + GstFlowReturn flow; + GstAppSink *appsink; + GstBuffer *group; + + appsink = GST_APP_SINK_CAST (sink); + + if (appsink->priv->buffer_lists_supported) + return gst_app_sink_render_common (sink, GST_MINI_OBJECT_CAST (list), TRUE); + + /* The application doesn't support buffer lists, extract individual buffers + * then and push them one-by-one */ + GST_INFO_OBJECT (sink, "chaining each group in list as a merged buffer"); + + it = gst_buffer_list_iterate (list); + + if (gst_buffer_list_iterator_next_group (it)) { + do { + group = gst_buffer_list_iterator_merge_group (it); + if (group == NULL) { + group = gst_buffer_new (); + GST_DEBUG_OBJECT (sink, "chaining empty group"); + } else { + GST_DEBUG_OBJECT (sink, "chaining group"); + } + flow = gst_app_sink_render (sink, group); + gst_buffer_unref (group); + } while (flow == GST_FLOW_OK && gst_buffer_list_iterator_next_group (it)); + } else { + GST_DEBUG_OBJECT (sink, "chaining empty group"); + group = gst_buffer_new (); + flow = gst_app_sink_render (sink, group); + gst_buffer_unref (group); + } + + gst_buffer_list_iterator_free (it); + + return flow; +} + +static GstCaps * +gst_app_sink_getcaps (GstBaseSink * psink) +{ + GstCaps *caps; + GstAppSink *appsink = GST_APP_SINK_CAST (psink); + GstAppSinkPrivate *priv = appsink->priv; + + GST_OBJECT_LOCK (appsink); + if ((caps = priv->caps)) + gst_caps_ref (caps); + GST_DEBUG_OBJECT (appsink, "got caps %" GST_PTR_FORMAT, caps); + GST_OBJECT_UNLOCK (appsink); + + return caps; +} + +static GstMiniObject * +gst_app_sink_pull_object (GstAppSink * appsink) +{ + GstMiniObject *obj = NULL; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + + while (TRUE) { + GST_DEBUG_OBJECT (appsink, "trying to grab a buffer/list"); + if (!priv->started) + goto not_started; + + if (!g_queue_is_empty (priv->queue)) + break; + + if (priv->is_eos) + goto eos; + + /* nothing to return, wait */ + GST_DEBUG_OBJECT (appsink, "waiting for a buffer/list"); + g_cond_wait (priv->cond, priv->mutex); + } + obj = g_queue_pop_head (priv->queue); + GST_DEBUG_OBJECT (appsink, "we have a buffer/list %p", obj); + g_cond_signal (priv->cond); + g_mutex_unlock (priv->mutex); + + return obj; + + /* special conditions */ +eos: + { + GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); + g_mutex_unlock (priv->mutex); + return NULL; + } +not_started: + { + GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); + g_mutex_unlock (priv->mutex); + return NULL; + } +} + +/* external API */ + +/** + * gst_app_sink_set_caps: + * @appsink: a #GstAppSink + * @caps: caps to set + * + * Set the capabilities on the appsink element. This function takes + * a copy of the caps structure. After calling this method, the sink will only + * accept caps that match @caps. If @caps is non-fixed, you must check the caps + * on the buffers to get the actual used caps. + * + * Since: 0.10.22 + */ +void +gst_app_sink_set_caps (GstAppSink * appsink, const GstCaps * caps) +{ + GstCaps *old; + GstAppSinkPrivate *priv; + + g_return_if_fail (GST_IS_APP_SINK (appsink)); + + priv = appsink->priv; + + GST_OBJECT_LOCK (appsink); + GST_DEBUG_OBJECT (appsink, "setting caps to %" GST_PTR_FORMAT, caps); + if ((old = priv->caps) != caps) { + if (caps) + priv->caps = gst_caps_copy (caps); + else + priv->caps = NULL; + if (old) + gst_caps_unref (old); + } + GST_OBJECT_UNLOCK (appsink); +} + +/** + * gst_app_sink_get_caps: + * @appsink: a #GstAppSink + * + * Get the configured caps on @appsink. + * + * Returns: the #GstCaps accepted by the sink. gst_caps_unref() after usage. + * + * Since: 0.10.22 + */ +GstCaps * +gst_app_sink_get_caps (GstAppSink * appsink) +{ + GstCaps *caps; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); + + priv = appsink->priv; + + GST_OBJECT_LOCK (appsink); + if ((caps = priv->caps)) + gst_caps_ref (caps); + GST_DEBUG_OBJECT (appsink, "getting caps of %" GST_PTR_FORMAT, caps); + GST_OBJECT_UNLOCK (appsink); + + return caps; +} + +/** + * gst_app_sink_is_eos: + * @appsink: a #GstAppSink + * + * Check if @appsink is EOS, which is when no more buffers can be pulled because + * an EOS event was received. + * + * This function also returns %TRUE when the appsink is not in the PAUSED or + * PLAYING state. + * + * Returns: %TRUE if no more buffers can be pulled and the appsink is EOS. + * + * Since: 0.10.22 + */ +gboolean +gst_app_sink_is_eos (GstAppSink * appsink) +{ + gboolean ret; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + if (!priv->started) + goto not_started; + + if (priv->is_eos && g_queue_is_empty (priv->queue)) { + GST_DEBUG_OBJECT (appsink, "we are EOS and the queue is empty"); + ret = TRUE; + } else { + GST_DEBUG_OBJECT (appsink, "we are not yet EOS"); + ret = FALSE; + } + g_mutex_unlock (priv->mutex); + + return ret; + +not_started: + { + GST_DEBUG_OBJECT (appsink, "we are stopped, return TRUE"); + g_mutex_unlock (priv->mutex); + return TRUE; + } +} + +/** + * gst_app_sink_set_emit_signals: + * @appsink: a #GstAppSink + * @emit: the new state + * + * Make appsink emit the "new-preroll" and "new-buffer" signals. This option is + * by default disabled because signal emission is expensive and unneeded when + * the application prefers to operate in pull mode. + * + * Since: 0.10.22 + */ +void +gst_app_sink_set_emit_signals (GstAppSink * appsink, gboolean emit) +{ + GstAppSinkPrivate *priv; + + g_return_if_fail (GST_IS_APP_SINK (appsink)); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + priv->emit_signals = emit; + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_sink_get_emit_signals: + * @appsink: a #GstAppSink + * + * Check if appsink will emit the "new-preroll" and "new-buffer" signals. + * + * Returns: %TRUE if @appsink is emiting the "new-preroll" and "new-buffer" + * signals. + * + * Since: 0.10.22 + */ +gboolean +gst_app_sink_get_emit_signals (GstAppSink * appsink) +{ + gboolean result; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + result = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + return result; +} + +/** + * gst_app_sink_set_max_buffers: + * @appsink: a #GstAppSink + * @max: the maximum number of buffers to queue + * + * Set the maximum amount of buffers that can be queued in @appsink. After this + * amount of buffers are queued in appsink, any more buffers will block upstream + * elements until a buffer is pulled from @appsink. + * + * Since: 0.10.22 + */ +void +gst_app_sink_set_max_buffers (GstAppSink * appsink, guint max) +{ + GstAppSinkPrivate *priv; + + g_return_if_fail (GST_IS_APP_SINK (appsink)); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + if (max != priv->max_buffers) { + priv->max_buffers = max; + /* signal the change */ + g_cond_signal (priv->cond); + } + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_sink_get_max_buffers: + * @appsink: a #GstAppSink + * + * Get the maximum amount of buffers that can be queued in @appsink. + * + * Returns: The maximum amount of buffers that can be queued. + * + * Since: 0.10.22 + */ +guint +gst_app_sink_get_max_buffers (GstAppSink * appsink) +{ + guint result; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), 0); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + result = priv->max_buffers; + g_mutex_unlock (priv->mutex); + + return result; +} + +/** + * gst_app_sink_set_drop: + * @appsink: a #GstAppSink + * @drop: the new state + * + * Instruct @appsink to drop old buffers when the maximum amount of queued + * buffers is reached. + * + * Since: 0.10.22 + */ +void +gst_app_sink_set_drop (GstAppSink * appsink, gboolean drop) +{ + GstAppSinkPrivate *priv; + + g_return_if_fail (GST_IS_APP_SINK (appsink)); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + if (priv->drop != drop) { + priv->drop = drop; + /* signal the change */ + g_cond_signal (priv->cond); + } + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_sink_get_drop: + * @appsink: a #GstAppSink + * + * Check if @appsink will drop old buffers when the maximum amount of queued + * buffers is reached. + * + * Returns: %TRUE if @appsink is dropping old buffers when the queue is + * filled. + * + * Since: 0.10.22 + */ +gboolean +gst_app_sink_get_drop (GstAppSink * appsink) +{ + gboolean result; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), FALSE); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + result = priv->drop; + g_mutex_unlock (priv->mutex); + + return result; +} + +/** + * gst_app_sink_pull_preroll: + * @appsink: a #GstAppSink + * + * Get the last preroll buffer in @appsink. This was the buffer that caused the + * appsink to preroll in the PAUSED state. This buffer can be pulled many times + * and remains available to the application even after EOS. + * + * This function is typically used when dealing with a pipeline in the PAUSED + * state. Calling this function after doing a seek will give the buffer right + * after the seek position. + * + * Note that the preroll buffer will also be returned as the first buffer + * when calling gst_app_sink_pull_buffer(). + * + * If an EOS event was received before any buffers, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * This function blocks until a preroll buffer or EOS is received or the appsink + * element is set to the READY/NULL state. + * + * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. + * + * Since: 0.10.22 + */ +GstBuffer * +gst_app_sink_pull_preroll (GstAppSink * appsink) +{ + GstBuffer *buf = NULL; + GstAppSinkPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SINK (appsink), NULL); + + priv = appsink->priv; + + g_mutex_lock (priv->mutex); + + while (TRUE) { + GST_DEBUG_OBJECT (appsink, "trying to grab a buffer"); + if (!priv->started) + goto not_started; + + if (priv->preroll != NULL) + break; + + if (priv->is_eos) + goto eos; + + /* nothing to return, wait */ + GST_DEBUG_OBJECT (appsink, "waiting for the preroll buffer"); + g_cond_wait (priv->cond, priv->mutex); + } + buf = gst_buffer_ref (priv->preroll); + GST_DEBUG_OBJECT (appsink, "we have the preroll buffer %p", buf); + g_mutex_unlock (priv->mutex); + + return buf; + + /* special conditions */ +eos: + { + GST_DEBUG_OBJECT (appsink, "we are EOS, return NULL"); + g_mutex_unlock (priv->mutex); + return NULL; + } +not_started: + { + GST_DEBUG_OBJECT (appsink, "we are stopped, return NULL"); + g_mutex_unlock (priv->mutex); + return NULL; + } +} + +/** + * gst_app_sink_pull_buffer: + * @appsink: a #GstAppSink + * + * This function blocks until a buffer or EOS becomes available or the appsink + * element is set to the READY/NULL state. + * + * This function will only return buffers when the appsink is in the PLAYING + * state. All rendered buffers will be put in a queue so that the application + * can pull buffers at its own rate. Note that when the application does not + * pull buffers fast enough, the queued buffers could consume a lot of memory, + * especially when dealing with raw video frames. + * + * If an EOS event was received before any buffers, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * Returns: a #GstBuffer or NULL when the appsink is stopped or EOS. + * + * Since: 0.10.22 + */ + +GstBuffer * +gst_app_sink_pull_buffer (GstAppSink * appsink) +{ + GST_DEBUG_OBJECT (appsink, "pull a buffer"); + return GST_BUFFER_CAST (gst_app_sink_pull_object (appsink)); +} + +/** + * gst_app_sink_pull_buffer_list: + * @appsink: a #GstAppSink + * + * This function blocks until a buffer list or EOS becomes available or the + * appsink element is set to the READY/NULL state. + * + * This function will only return buffer lists when the appsink is in the + * PLAYING state. All rendered buffer lists will be put in a queue so that + * the application can pull buffer lists at its own rate. Note that when + * the application does not pull buffer lists fast enough, the queued buffer + * lists could consume a lot of memory, especially when dealing with raw + * video frames. + * + * If an EOS event was received before any buffer lists, this function returns + * %NULL. Use gst_app_sink_is_eos () to check for the EOS condition. + * + * Returns: a #GstBufferList or NULL when the appsink is stopped or EOS. + */ +GstBufferList * +gst_app_sink_pull_buffer_list (GstAppSink * appsink) +{ + GST_DEBUG_OBJECT (appsink, "pull a buffer list"); + return GST_BUFFER_LIST_CAST (gst_app_sink_pull_object (appsink)); +} + +/** + * gst_app_sink_set_callbacks: + * @appsink: a #GstAppSink + * @callbacks: the callbacks + * @user_data: a user_data argument for the callbacks + * @notify: a destroy notify function + * + * Set callbacks which will be executed for each new preroll, new buffer and eos. + * This is an alternative to using the signals, it has lower overhead and is thus + * less expensive, but also less flexible. + * + * If callbacks are installed, no signals will be emited for performance + * reasons. + * + * Since: 0.10.23 + */ +void +gst_app_sink_set_callbacks (GstAppSink * appsink, + GstAppSinkCallbacks * callbacks, gpointer user_data, GDestroyNotify notify) +{ + GDestroyNotify old_notify; + GstAppSinkPrivate *priv; + + g_return_if_fail (GST_IS_APP_SINK (appsink)); + g_return_if_fail (callbacks != NULL); + + priv = appsink->priv; + + GST_OBJECT_LOCK (appsink); + old_notify = priv->notify; + + if (old_notify) { + gpointer old_data; + + old_data = priv->user_data; + + priv->user_data = NULL; + priv->notify = NULL; + GST_OBJECT_UNLOCK (appsink); + + old_notify (old_data); + + GST_OBJECT_LOCK (appsink); + } + priv->callbacks = *callbacks; + priv->user_data = user_data; + priv->notify = notify; + priv->buffer_lists_supported = + gst_app_sink_check_buffer_lists_support (appsink); + GST_OBJECT_UNLOCK (appsink); +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_app_sink_uri_get_type (void) +{ + return GST_URI_SINK; +} + +static gchar ** +gst_app_sink_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "appsink", NULL }; + + return protocols; +} + +static const gchar * +gst_app_sink_uri_get_uri (GstURIHandler * handler) +{ + return "appsink"; +} + +static gboolean +gst_app_sink_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + gchar *protocol; + gboolean ret; + + protocol = gst_uri_get_protocol (uri); + ret = !strcmp (protocol, "appsink"); + g_free (protocol); + + return ret; +} + +static void +gst_app_sink_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_app_sink_uri_get_type; + iface->get_protocols = gst_app_sink_uri_get_protocols; + iface->get_uri = gst_app_sink_uri_get_uri; + iface->set_uri = gst_app_sink_uri_set_uri; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.h new file mode 100644 index 0000000..3e0bc41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsink.h @@ -0,0 +1,141 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_APP_SINK_H_ +#define _GST_APP_SINK_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_APP_SINK \ + (gst_app_sink_get_type()) +#define GST_APP_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_SINK,GstAppSink)) +#define GST_APP_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_SINK,GstAppSinkClass)) +#define GST_IS_APP_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_SINK)) +#define GST_IS_APP_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_SINK)) +/* Since 0.10.23 */ +#define GST_APP_SINK_CAST(obj) \ + ((GstAppSink*)(obj)) + +typedef struct _GstAppSink GstAppSink; +typedef struct _GstAppSinkClass GstAppSinkClass; +typedef struct _GstAppSinkPrivate GstAppSinkPrivate; + +/** + * GstAppSinkCallbacks: + * @eos: Called when the end-of-stream has been reached. This callback + * is called from the steaming thread. + * @new_preroll: Called when a new preroll buffer is available. + * This callback is called from the steaming thread. + * The new preroll buffer can be retrieved with + * gst_app_sink_pull_preroll() either from this callback + * or from any other thread. + * @new_buffer: Called when a new buffer is available. + * This callback is called from the steaming thread. + * The new buffer can be retrieved with + * gst_app_sink_pull_buffer() either from this callback + * or from any other thread. + * @new_buffer_list: Called when a new bufferlist is available. + * This callback is called from the steaming thread. + * The new bufferlist can be retrieved with + * gst_app_sink_pull_buffer_list() either from this callback + * or from any other thread. + * + * A set of callbacks that can be installed on the appsink with + * gst_app_sink_set_callbacks(). + * + * Since: 0.10.23 + */ +typedef struct { + void (*eos) (GstAppSink *sink, gpointer user_data); + GstFlowReturn (*new_preroll) (GstAppSink *sink, gpointer user_data); + GstFlowReturn (*new_buffer) (GstAppSink *sink, gpointer user_data); + GstFlowReturn (*new_buffer_list) (GstAppSink *sink, gpointer user_data); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 1]; +} GstAppSinkCallbacks; + +struct _GstAppSink +{ + GstBaseSink basesink; + + /*< private >*/ + GstAppSinkPrivate *priv; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstAppSinkClass +{ + GstBaseSinkClass basesink_class; + + /* signals */ + void (*eos) (GstAppSink *sink); + void (*new_preroll) (GstAppSink *sink); + void (*new_buffer) (GstAppSink *sink); + + /* actions */ + GstBuffer * (*pull_preroll) (GstAppSink *sink); + GstBuffer * (*pull_buffer) (GstAppSink *sink); + + /* ABI added */ + GstBufferList * (*new_buffer_list) (GstAppSink *sink); + GstBufferList * (*pull_buffer_list) (GstAppSink *sink); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 2]; +}; + +GType gst_app_sink_get_type(void); + +void gst_app_sink_set_caps (GstAppSink *appsink, const GstCaps *caps); +GstCaps * gst_app_sink_get_caps (GstAppSink *appsink); + +gboolean gst_app_sink_is_eos (GstAppSink *appsink); + +void gst_app_sink_set_emit_signals (GstAppSink *appsink, gboolean emit); +gboolean gst_app_sink_get_emit_signals (GstAppSink *appsink); + +void gst_app_sink_set_max_buffers (GstAppSink *appsink, guint max); +guint gst_app_sink_get_max_buffers (GstAppSink *appsink); + +void gst_app_sink_set_drop (GstAppSink *appsink, gboolean drop); +gboolean gst_app_sink_get_drop (GstAppSink *appsink); + +GstBuffer * gst_app_sink_pull_preroll (GstAppSink *appsink); +GstBuffer * gst_app_sink_pull_buffer (GstAppSink *appsink); +GstBufferList * gst_app_sink_pull_buffer_list (GstAppSink *appsink); + +void gst_app_sink_set_callbacks (GstAppSink * appsink, + GstAppSinkCallbacks *callbacks, + gpointer user_data, + GDestroyNotify notify); + +G_END_DECLS + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.c new file mode 100644 index 0000000..f051711 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.c @@ -0,0 +1,1689 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-appsrc + * + * The appsrc element can be used by applications to insert data into a + * GStreamer pipeline. Unlike most GStreamer elements, Appsrc provides + * external API functions. + * + * For the documentation of the API, please see the + * libgstapp section in the + * GStreamer Plugins Base Libraries documentation. + * + * Since: 0.10.22 + */ + +/** + * SECTION:gstappsrc + * @short_description: Easy way for applications to inject buffers into a + * pipeline + * @see_also: #GstBaseSrc, appsink + * + * The appsrc element can be used by applications to insert data into a + * GStreamer pipeline. Unlike most GStreamer elements, Appsrc provides + * external API functions. + * + * appsrc can be used by linking with the libgstapp library to access the + * methods directly or by using the appsrc action signals. + * + * Before operating appsrc, the caps property must be set to a fixed caps + * describing the format of the data that will be pushed with appsrc. An + * exception to this is when pushing buffers with unknown caps, in which case no + * caps should be set. This is typically true of file-like sources that push raw + * byte buffers. + * + * The main way of handing data to the appsrc element is by calling the + * gst_app_src_push_buffer() method or by emiting the push-buffer action signal. + * This will put the buffer onto a queue from which appsrc will read from in its + * streaming thread. It is important to note that data transport will not happen + * from the thread that performed the push-buffer call. + * + * The "max-bytes" property controls how much data can be queued in appsrc + * before appsrc considers the queue full. A filled internal queue will always + * signal the "enough-data" signal, which signals the application that it should + * stop pushing data into appsrc. The "block" property will cause appsrc to + * block the push-buffer method until free data becomes available again. + * + * When the internal queue is running out of data, the "need-data" signal is + * emited, which signals the application that it should start pushing more data + * into appsrc. + * + * In addition to the "need-data" and "enough-data" signals, appsrc can emit the + * "seek-data" signal when the "stream-mode" property is set to "seekable" or + * "random-access". The signal argument will contain the new desired position in + * the stream expressed in the unit set with the "format" property. After + * receiving the seek-data signal, the application should push-buffers from the + * new position. + * + * These signals allow the application to operate the appsrc in two different + * ways: + * + * The push model, in which the application repeadedly calls the push-buffer method + * with a new buffer. Optionally, the queue size in the appsrc can be controlled + * with the enough-data and need-data signals by respectively stopping/starting + * the push-buffer calls. This is a typical mode of operation for the + * stream-type "stream" and "seekable". Use this model when implementing various + * network protocols or hardware devices. + * + * The pull model where the need-data signal triggers the next push-buffer call. + * This mode is typically used in the "random-access" stream-type. Use this + * model for file access or other randomly accessable sources. In this mode, a + * buffer of exactly the amount of bytes given by the need-data signal should be + * pushed into appsrc. + * + * In all modes, the size property on appsrc should contain the total stream + * size in bytes. Setting this property is mandatory in the random-access mode. + * For the stream and seekable modes, setting this property is optional but + * recommended. + * + * When the application is finished pushing data into appsrc, it should call + * gst_app_src_end_of_stream() or emit the end-of-stream action signal. After + * this call, no more buffers can be pushed into appsrc until a flushing seek + * happened or the state of the appsrc has gone through READY. + * + * Last reviewed on 2008-12-17 (0.10.10) + * + * Since: 0.10.22 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include "gstapp-marshal.h" +#include "gstappsrc.h" + +struct _GstAppSrcPrivate +{ + GCond *cond; + GMutex *mutex; + GQueue *queue; + + GstCaps *caps; + gint64 size; + GstAppStreamType stream_type; + guint64 max_bytes; + GstFormat format; + gboolean block; + + gboolean flushing; + gboolean started; + gboolean is_eos; + guint64 queued_bytes; + guint64 offset; + GstAppStreamType current_type; + + guint64 min_latency; + guint64 max_latency; + gboolean emit_signals; + guint min_percent; + + GstAppSrcCallbacks callbacks; + gpointer user_data; + GDestroyNotify notify; +}; + +GST_DEBUG_CATEGORY_STATIC (app_src_debug); +#define GST_CAT_DEFAULT app_src_debug + +enum +{ + /* signals */ + SIGNAL_NEED_DATA, + SIGNAL_ENOUGH_DATA, + SIGNAL_SEEK_DATA, + + /* actions */ + SIGNAL_PUSH_BUFFER, + SIGNAL_END_OF_STREAM, + + LAST_SIGNAL +}; + +#define DEFAULT_PROP_SIZE -1 +#define DEFAULT_PROP_STREAM_TYPE GST_APP_STREAM_TYPE_STREAM +#define DEFAULT_PROP_MAX_BYTES 200000 +#define DEFAULT_PROP_FORMAT GST_FORMAT_BYTES +#define DEFAULT_PROP_BLOCK FALSE +#define DEFAULT_PROP_IS_LIVE FALSE +#define DEFAULT_PROP_MIN_LATENCY -1 +#define DEFAULT_PROP_MAX_LATENCY -1 +#define DEFAULT_PROP_EMIT_SIGNALS TRUE +#define DEFAULT_PROP_MIN_PERCENT 0 + +enum +{ + PROP_0, + PROP_CAPS, + PROP_SIZE, + PROP_STREAM_TYPE, + PROP_MAX_BYTES, + PROP_FORMAT, + PROP_BLOCK, + PROP_IS_LIVE, + PROP_MIN_LATENCY, + PROP_MAX_LATENCY, + PROP_EMIT_SIGNALS, + PROP_MIN_PERCENT, + PROP_LAST +}; + +static GstStaticPadTemplate gst_app_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GType +gst_app_stream_type_get_type (void) +{ + static volatile gsize stream_type_type = 0; + static const GEnumValue stream_type[] = { + {GST_APP_STREAM_TYPE_STREAM, "GST_APP_STREAM_TYPE_STREAM", "stream"}, + {GST_APP_STREAM_TYPE_SEEKABLE, "GST_APP_STREAM_TYPE_SEEKABLE", "seekable"}, + {GST_APP_STREAM_TYPE_RANDOM_ACCESS, "GST_APP_STREAM_TYPE_RANDOM_ACCESS", + "random-access"}, + {0, NULL, NULL} + }; + + if (g_once_init_enter (&stream_type_type)) { + GType tmp = g_enum_register_static ("GstAppStreamType", stream_type); + g_once_init_leave (&stream_type_type, tmp); + } + + return (GType) stream_type_type; +} + +static void gst_app_src_uri_handler_init (gpointer g_iface, + gpointer iface_data); + +static void gst_app_src_dispose (GObject * object); +static void gst_app_src_finalize (GObject * object); + +static void gst_app_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_app_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_app_src_set_latencies (GstAppSrc * appsrc, + gboolean do_min, guint64 min, gboolean do_max, guint64 max); + +static GstFlowReturn gst_app_src_create (GstBaseSrc * bsrc, + guint64 offset, guint size, GstBuffer ** buf); +static gboolean gst_app_src_start (GstBaseSrc * bsrc); +static gboolean gst_app_src_stop (GstBaseSrc * bsrc); +static gboolean gst_app_src_unlock (GstBaseSrc * bsrc); +static gboolean gst_app_src_unlock_stop (GstBaseSrc * bsrc); +static gboolean gst_app_src_do_seek (GstBaseSrc * src, GstSegment * segment); +static gboolean gst_app_src_is_seekable (GstBaseSrc * src); +static gboolean gst_app_src_check_get_range (GstBaseSrc * src); +static gboolean gst_app_src_do_get_size (GstBaseSrc * src, guint64 * size); +static gboolean gst_app_src_query (GstBaseSrc * src, GstQuery * query); + +static GstFlowReturn gst_app_src_push_buffer_action (GstAppSrc * appsrc, + GstBuffer * buffer); + +static guint gst_app_src_signals[LAST_SIGNAL] = { 0 }; + +static void +_do_init (GType filesrc_type) +{ + static const GInterfaceInfo urihandler_info = { + gst_app_src_uri_handler_init, + NULL, + NULL + }; + g_type_add_interface_static (filesrc_type, GST_TYPE_URI_HANDLER, + &urihandler_info); +} + +GST_BOILERPLATE_FULL (GstAppSrc, gst_app_src, GstBaseSrc, GST_TYPE_BASE_SRC, + _do_init); + +static void +gst_app_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (app_src_debug, "appsrc", 0, "appsrc element"); + + gst_element_class_set_details_simple (element_class, "AppSrc", + "Generic/Source", "Allow the application to feed buffers to a pipeline", + "David Schleef , Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_app_src_template)); +} + +static void +gst_app_src_class_init (GstAppSrcClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass; + + gobject_class->dispose = gst_app_src_dispose; + gobject_class->finalize = gst_app_src_finalize; + + gobject_class->set_property = gst_app_src_set_property; + gobject_class->get_property = gst_app_src_get_property; + + /** + * GstAppSrc::caps + * + * The GstCaps that will negotiated downstream and will be put + * on outgoing buffers. + */ + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Caps", + "The allowed caps for the src pad", GST_TYPE_CAPS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::format + * + * The format to use for segment events. When the source is producing + * timestamped buffers this property should be set to GST_FORMAT_TIME. + */ + g_object_class_install_property (gobject_class, PROP_FORMAT, + g_param_spec_enum ("format", "Format", + "The format of the segment events and seek", GST_TYPE_FORMAT, + DEFAULT_PROP_FORMAT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::size + * + * The total size in bytes of the data stream. If the total size is known, it + * is recommended to configure it with this property. + */ + g_object_class_install_property (gobject_class, PROP_SIZE, + g_param_spec_int64 ("size", "Size", + "The size of the data stream in bytes (-1 if unknown)", + -1, G_MAXINT64, DEFAULT_PROP_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::stream-type + * + * The type of stream that this source is producing. For seekable streams the + * application should connect to the seek-data signal. + */ + g_object_class_install_property (gobject_class, PROP_STREAM_TYPE, + g_param_spec_enum ("stream-type", "Stream Type", + "the type of the stream", GST_TYPE_APP_STREAM_TYPE, + DEFAULT_PROP_STREAM_TYPE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::max-bytes + * + * The maximum amount of bytes that can be queued internally. + * After the maximum amount of bytes are queued, appsrc will emit the + * "enough-data" signal. + */ + g_object_class_install_property (gobject_class, PROP_MAX_BYTES, + g_param_spec_uint64 ("max-bytes", "Max bytes", + "The maximum number of bytes to queue internally (0 = unlimited)", + 0, G_MAXUINT64, DEFAULT_PROP_MAX_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::block + * + * When max-bytes are queued and after the enough-data signal has been emited, + * block any further push-buffer calls until the amount of queued bytes drops + * below the max-bytes limit. + */ + g_object_class_install_property (gobject_class, PROP_BLOCK, + g_param_spec_boolean ("block", "Block", + "Block push-buffer when max-bytes are queued", + DEFAULT_PROP_BLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAppSrc::is-live + * + * Instruct the source to behave like a live source. This includes that it + * will only push out buffers in the PLAYING state. + */ + g_object_class_install_property (gobject_class, PROP_IS_LIVE, + g_param_spec_boolean ("is-live", "Is Live", + "Whether to act as a live source", + DEFAULT_PROP_IS_LIVE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::min-latency + * + * The minimum latency of the source. A value of -1 will use the default + * latency calculations of #GstBaseSrc. + */ + g_object_class_install_property (gobject_class, PROP_MIN_LATENCY, + g_param_spec_int64 ("min-latency", "Min Latency", + "The minimum latency (-1 = default)", + -1, G_MAXINT64, DEFAULT_PROP_MIN_LATENCY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAppSrc::max-latency + * + * The maximum latency of the source. A value of -1 means an unlimited amout + * of latency. + */ + g_object_class_install_property (gobject_class, PROP_MAX_LATENCY, + g_param_spec_int64 ("max-latency", "Max Latency", + "The maximum latency (-1 = unlimited)", + -1, G_MAXINT64, DEFAULT_PROP_MAX_LATENCY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAppSrc::emit-signals + * + * Make appsrc emit the "need-data", "enough-data" and "seek-data" signals. + * This option is by default enabled for backwards compatibility reasons but + * can disabled when needed because signal emission is expensive. + * + * Since: 0.10.23 + */ + g_object_class_install_property (gobject_class, PROP_EMIT_SIGNALS, + g_param_spec_boolean ("emit-signals", "Emit signals", + "Emit need-data, enough-data and seek-data signals", + DEFAULT_PROP_EMIT_SIGNALS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAppSrc::empty-percent + * + * Make appsrc emit the "need-data" signal when the amount of bytes in the + * queue drops below this percentage of max-bytes. + * + * Since: 0.10.27 + */ + g_object_class_install_property (gobject_class, PROP_MIN_PERCENT, + g_param_spec_uint ("min-percent", "Min Percent", + "Emit need-data when queued bytes drops below this percent of max-bytes", + 0, 100, DEFAULT_PROP_MIN_PERCENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAppSrc::need-data: + * @appsrc: the appsrc element that emited the signal + * @length: the amount of bytes needed. + * + * Signal that the source needs more data. In the callback or from another + * thread you should call push-buffer or end-of-stream. + * + * @length is just a hint and when it is set to -1, any number of bytes can be + * pushed into @appsrc. + * + * You can call push-buffer multiple times until the enough-data signal is + * fired. + */ + gst_app_src_signals[SIGNAL_NEED_DATA] = + g_signal_new ("need-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSrcClass, need_data), + NULL, NULL, __gst_app_marshal_VOID__UINT, G_TYPE_NONE, 1, G_TYPE_UINT); + + /** + * GstAppSrc::enough-data: + * @appsrc: the appsrc element that emited the signal + * + * Signal that the source has enough data. It is recommended that the + * application stops calling push-buffer until the need-data signal is + * emited again to avoid excessive buffer queueing. + */ + gst_app_src_signals[SIGNAL_ENOUGH_DATA] = + g_signal_new ("enough-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSrcClass, enough_data), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstAppSrc::seek-data: + * @appsrc: the appsrc element that emited the signal + * @offset: the offset to seek to + * + * Seek to the given offset. The next push-buffer should produce buffers from + * the new @offset. + * This callback is only called for seekable stream types. + * + * Returns: %TRUE if the seek succeeded. + */ + gst_app_src_signals[SIGNAL_SEEK_DATA] = + g_signal_new ("seek-data", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstAppSrcClass, seek_data), + NULL, NULL, __gst_app_marshal_BOOLEAN__UINT64, G_TYPE_BOOLEAN, 1, + G_TYPE_UINT64); + + /** + * GstAppSrc::push-buffer: + * @appsrc: the appsrc + * @buffer: a buffer to push + * + * Adds a buffer to the queue of buffers that the appsrc element will + * push to its source pad. This function does not take ownership of the + * buffer so the buffer needs to be unreffed after calling this function. + * + * When the block property is TRUE, this function can block until free space + * becomes available in the queue. + */ + gst_app_src_signals[SIGNAL_PUSH_BUFFER] = + g_signal_new ("push-buffer", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSrcClass, + push_buffer), NULL, NULL, __gst_app_marshal_ENUM__OBJECT, + GST_TYPE_FLOW_RETURN, 1, GST_TYPE_BUFFER); + + /** + * GstAppSrc::end-of-stream: + * @appsrc: the appsrc + * + * Notify @appsrc that no more buffer are available. + */ + gst_app_src_signals[SIGNAL_END_OF_STREAM] = + g_signal_new ("end-of-stream", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstAppSrcClass, + end_of_stream), NULL, NULL, __gst_app_marshal_ENUM__VOID, + GST_TYPE_FLOW_RETURN, 0, G_TYPE_NONE); + + basesrc_class->create = gst_app_src_create; + basesrc_class->start = gst_app_src_start; + basesrc_class->stop = gst_app_src_stop; + basesrc_class->unlock = gst_app_src_unlock; + basesrc_class->unlock_stop = gst_app_src_unlock_stop; + basesrc_class->do_seek = gst_app_src_do_seek; + basesrc_class->is_seekable = gst_app_src_is_seekable; + basesrc_class->check_get_range = gst_app_src_check_get_range; + basesrc_class->get_size = gst_app_src_do_get_size; + basesrc_class->get_size = gst_app_src_do_get_size; + basesrc_class->query = gst_app_src_query; + + klass->push_buffer = gst_app_src_push_buffer_action; + klass->end_of_stream = gst_app_src_end_of_stream; + + g_type_class_add_private (klass, sizeof (GstAppSrcPrivate)); +} + +static void +gst_app_src_init (GstAppSrc * appsrc, GstAppSrcClass * klass) +{ + GstAppSrcPrivate *priv; + + priv = appsrc->priv = G_TYPE_INSTANCE_GET_PRIVATE (appsrc, GST_TYPE_APP_SRC, + GstAppSrcPrivate); + + priv->mutex = g_mutex_new (); + priv->cond = g_cond_new (); + priv->queue = g_queue_new (); + + priv->size = DEFAULT_PROP_SIZE; + priv->stream_type = DEFAULT_PROP_STREAM_TYPE; + priv->max_bytes = DEFAULT_PROP_MAX_BYTES; + priv->format = DEFAULT_PROP_FORMAT; + priv->block = DEFAULT_PROP_BLOCK; + priv->min_latency = DEFAULT_PROP_MIN_LATENCY; + priv->max_latency = DEFAULT_PROP_MAX_LATENCY; + priv->emit_signals = DEFAULT_PROP_EMIT_SIGNALS; + priv->min_percent = DEFAULT_PROP_MIN_PERCENT; + + gst_base_src_set_live (GST_BASE_SRC (appsrc), DEFAULT_PROP_IS_LIVE); +} + +static void +gst_app_src_flush_queued (GstAppSrc * src) +{ + GstBuffer *buf; + GstAppSrcPrivate *priv = src->priv; + + while ((buf = g_queue_pop_head (priv->queue))) + gst_buffer_unref (buf); + priv->queued_bytes = 0; +} + +static void +gst_app_src_dispose (GObject * obj) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (obj); + GstAppSrcPrivate *priv = appsrc->priv; + + if (priv->caps) { + gst_caps_unref (priv->caps); + priv->caps = NULL; + } + gst_app_src_flush_queued (appsrc); + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +static void +gst_app_src_finalize (GObject * obj) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (obj); + GstAppSrcPrivate *priv = appsrc->priv; + + g_mutex_free (priv->mutex); + g_cond_free (priv->cond); + g_queue_free (priv->queue); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_app_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (object); + GstAppSrcPrivate *priv = appsrc->priv; + + switch (prop_id) { + case PROP_CAPS: + gst_app_src_set_caps (appsrc, gst_value_get_caps (value)); + break; + case PROP_SIZE: + gst_app_src_set_size (appsrc, g_value_get_int64 (value)); + break; + case PROP_STREAM_TYPE: + gst_app_src_set_stream_type (appsrc, g_value_get_enum (value)); + break; + case PROP_MAX_BYTES: + gst_app_src_set_max_bytes (appsrc, g_value_get_uint64 (value)); + break; + case PROP_FORMAT: + priv->format = g_value_get_enum (value); + break; + case PROP_BLOCK: + priv->block = g_value_get_boolean (value); + break; + case PROP_IS_LIVE: + gst_base_src_set_live (GST_BASE_SRC (appsrc), + g_value_get_boolean (value)); + break; + case PROP_MIN_LATENCY: + gst_app_src_set_latencies (appsrc, TRUE, g_value_get_int64 (value), + FALSE, -1); + break; + case PROP_MAX_LATENCY: + gst_app_src_set_latencies (appsrc, FALSE, -1, TRUE, + g_value_get_int64 (value)); + break; + case PROP_EMIT_SIGNALS: + gst_app_src_set_emit_signals (appsrc, g_value_get_boolean (value)); + break; + case PROP_MIN_PERCENT: + priv->min_percent = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_app_src_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (object); + GstAppSrcPrivate *priv = appsrc->priv; + + switch (prop_id) { + case PROP_CAPS: + { + GstCaps *caps; + + /* we're missing a _take_caps() function to transfer ownership */ + caps = gst_app_src_get_caps (appsrc); + gst_value_set_caps (value, caps); + if (caps) + gst_caps_unref (caps); + break; + } + case PROP_SIZE: + g_value_set_int64 (value, gst_app_src_get_size (appsrc)); + break; + case PROP_STREAM_TYPE: + g_value_set_enum (value, gst_app_src_get_stream_type (appsrc)); + break; + case PROP_MAX_BYTES: + g_value_set_uint64 (value, gst_app_src_get_max_bytes (appsrc)); + break; + case PROP_FORMAT: + g_value_set_enum (value, priv->format); + break; + case PROP_BLOCK: + g_value_set_boolean (value, priv->block); + break; + case PROP_IS_LIVE: + g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (appsrc))); + break; + case PROP_MIN_LATENCY: + { + guint64 min; + + gst_app_src_get_latency (appsrc, &min, NULL); + g_value_set_int64 (value, min); + break; + } + case PROP_MAX_LATENCY: + { + guint64 max; + + gst_app_src_get_latency (appsrc, &max, NULL); + g_value_set_int64 (value, max); + break; + } + case PROP_EMIT_SIGNALS: + g_value_set_boolean (value, gst_app_src_get_emit_signals (appsrc)); + break; + case PROP_MIN_PERCENT: + g_value_set_uint (value, priv->min_percent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_app_src_unlock (GstBaseSrc * bsrc) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc); + GstAppSrcPrivate *priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsrc, "unlock start"); + priv->flushing = TRUE; + g_cond_broadcast (priv->cond); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_src_unlock_stop (GstBaseSrc * bsrc) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc); + GstAppSrcPrivate *priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsrc, "unlock stop"); + priv->flushing = FALSE; + g_cond_broadcast (priv->cond); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_src_start (GstBaseSrc * bsrc) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc); + GstAppSrcPrivate *priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsrc, "starting"); + priv->started = TRUE; + /* set the offset to -1 so that we always do a first seek. This is only used + * in random-access mode. */ + priv->offset = -1; + priv->flushing = FALSE; + g_mutex_unlock (priv->mutex); + + gst_base_src_set_format (bsrc, priv->format); + + return TRUE; +} + +static gboolean +gst_app_src_stop (GstBaseSrc * bsrc) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc); + GstAppSrcPrivate *priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + GST_DEBUG_OBJECT (appsrc, "stopping"); + priv->is_eos = FALSE; + priv->flushing = TRUE; + priv->started = FALSE; + gst_app_src_flush_queued (appsrc); + g_mutex_unlock (priv->mutex); + + return TRUE; +} + +static gboolean +gst_app_src_is_seekable (GstBaseSrc * src) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (src); + GstAppSrcPrivate *priv = appsrc->priv; + gboolean res = FALSE; + + switch (priv->stream_type) { + case GST_APP_STREAM_TYPE_STREAM: + break; + case GST_APP_STREAM_TYPE_SEEKABLE: + case GST_APP_STREAM_TYPE_RANDOM_ACCESS: + res = TRUE; + break; + } + return res; +} + +static gboolean +gst_app_src_check_get_range (GstBaseSrc * src) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (src); + GstAppSrcPrivate *priv = appsrc->priv; + gboolean res = FALSE; + + switch (priv->stream_type) { + case GST_APP_STREAM_TYPE_STREAM: + case GST_APP_STREAM_TYPE_SEEKABLE: + break; + case GST_APP_STREAM_TYPE_RANDOM_ACCESS: + res = TRUE; + break; + } + return res; +} + +static gboolean +gst_app_src_do_get_size (GstBaseSrc * src, guint64 * size) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (src); + + *size = gst_app_src_get_size (appsrc); + + return TRUE; +} + +static gboolean +gst_app_src_query (GstBaseSrc * src, GstQuery * query) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (src); + GstAppSrcPrivate *priv = appsrc->priv; + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GstClockTime min, max; + gboolean live; + + /* Query the parent class for the defaults */ + res = gst_base_src_query_latency (src, &live, &min, &max); + + /* overwrite with our values when we need to */ + g_mutex_lock (priv->mutex); + if (priv->min_latency != -1) + min = priv->min_latency; + if (priv->max_latency != -1) + max = priv->max_latency; + g_mutex_unlock (priv->mutex); + + gst_query_set_latency (query, live, min, max); + break; + } + default: + res = GST_BASE_SRC_CLASS (parent_class)->query (src, query); + break; + } + + return res; +} + +/* will be called in push mode */ +static gboolean +gst_app_src_do_seek (GstBaseSrc * src, GstSegment * segment) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (src); + GstAppSrcPrivate *priv = appsrc->priv; + gint64 desired_position; + gboolean res = FALSE; + + desired_position = segment->last_stop; + + GST_DEBUG_OBJECT (appsrc, "seeking to %" G_GINT64_FORMAT ", format %s", + desired_position, gst_format_get_name (segment->format)); + + /* no need to try to seek in streaming mode */ + if (priv->stream_type == GST_APP_STREAM_TYPE_STREAM) + return TRUE; + + if (priv->callbacks.seek_data) + res = priv->callbacks.seek_data (appsrc, desired_position, priv->user_data); + else { + gboolean emit; + + g_mutex_lock (priv->mutex); + emit = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + if (emit) + g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_SEEK_DATA], 0, + desired_position, &res); + } + + if (res) { + GST_DEBUG_OBJECT (appsrc, "flushing queue"); + gst_app_src_flush_queued (appsrc); + priv->is_eos = FALSE; + } else { + GST_WARNING_OBJECT (appsrc, "seek failed"); + } + + return res; +} + +/* must be called with the appsrc mutex */ +static gboolean +gst_app_src_emit_seek (GstAppSrc * appsrc, guint64 offset) +{ + gboolean res = FALSE; + gboolean emit; + GstAppSrcPrivate *priv = appsrc->priv; + + emit = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + GST_DEBUG_OBJECT (appsrc, + "we are at %" G_GINT64_FORMAT ", seek to %" G_GINT64_FORMAT, + priv->offset, offset); + + if (priv->callbacks.seek_data) + res = priv->callbacks.seek_data (appsrc, offset, priv->user_data); + else if (emit) + g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_SEEK_DATA], 0, + offset, &res); + + g_mutex_lock (priv->mutex); + + return res; +} + +/* must be called with the appsrc mutex. After this call things can be + * flushing */ +static void +gst_app_src_emit_need_data (GstAppSrc * appsrc, guint size) +{ + gboolean emit; + GstAppSrcPrivate *priv = appsrc->priv; + + emit = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + /* we have no data, we need some. We fire the signal with the size hint. */ + if (priv->callbacks.need_data) + priv->callbacks.need_data (appsrc, size, priv->user_data); + else if (emit) + g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_NEED_DATA], 0, size, + NULL); + + g_mutex_lock (priv->mutex); + /* we can be flushing now because we released the lock */ +} + +static GstFlowReturn +gst_app_src_create (GstBaseSrc * bsrc, guint64 offset, guint size, + GstBuffer ** buf) +{ + GstAppSrc *appsrc = GST_APP_SRC_CAST (bsrc); + GstAppSrcPrivate *priv = appsrc->priv; + GstFlowReturn ret; + GstCaps *caps; + + GST_OBJECT_LOCK (appsrc); + caps = priv->caps ? gst_caps_ref (priv->caps) : NULL; + if (G_UNLIKELY (priv->size != bsrc->segment.duration && + bsrc->segment.format == GST_FORMAT_BYTES)) { + GST_DEBUG_OBJECT (appsrc, + "Size changed from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT, + bsrc->segment.duration, priv->size); + gst_segment_set_duration (&bsrc->segment, GST_FORMAT_BYTES, priv->size); + GST_OBJECT_UNLOCK (appsrc); + + gst_element_post_message (GST_ELEMENT (appsrc), + gst_message_new_duration (GST_OBJECT (appsrc), GST_FORMAT_BYTES, + priv->size)); + } else { + GST_OBJECT_UNLOCK (appsrc); + } + + g_mutex_lock (priv->mutex); + /* check flushing first */ + if (G_UNLIKELY (priv->flushing)) + goto flushing; + + if (priv->stream_type == GST_APP_STREAM_TYPE_RANDOM_ACCESS) { + /* if we are dealing with a random-access stream, issue a seek if the offset + * changed. */ + if (G_UNLIKELY (priv->offset != offset)) { + gboolean res; + + /* do the seek */ + res = gst_app_src_emit_seek (appsrc, offset); + + if (G_UNLIKELY (!res)) + /* failing to seek is fatal */ + goto seek_error; + + priv->offset = offset; + } + } + + while (TRUE) { + /* return data as long as we have some */ + if (!g_queue_is_empty (priv->queue)) { + guint buf_size; + + *buf = g_queue_pop_head (priv->queue); + buf_size = GST_BUFFER_SIZE (*buf); + + GST_DEBUG_OBJECT (appsrc, "we have buffer %p of size %u", *buf, buf_size); + + priv->queued_bytes -= buf_size; + + /* only update the offset when in random_access mode */ + if (priv->stream_type == GST_APP_STREAM_TYPE_RANDOM_ACCESS) + priv->offset += buf_size; + if (caps) { + *buf = gst_buffer_make_metadata_writable (*buf); + gst_buffer_set_caps (*buf, caps); + } + + /* signal that we removed an item */ + g_cond_broadcast (priv->cond); + + /* see if we go lower than the empty-percent */ + if (priv->min_percent && priv->max_bytes) { + if (priv->queued_bytes * 100 / priv->max_bytes <= priv->min_percent) + /* ignore flushing state, we got a buffer and we will return it now. + * Errors will be handled in the next round */ + gst_app_src_emit_need_data (appsrc, size); + } + ret = GST_FLOW_OK; + break; + } else { + gst_app_src_emit_need_data (appsrc, size); + + /* we can be flushing now because we released the lock above */ + if (G_UNLIKELY (priv->flushing)) + goto flushing; + + /* if we have a buffer now, continue the loop and try to return it. In + * random-access mode (where a buffer is normally pushed in the above + * signal) we can still be empty because the pushed buffer got flushed or + * when the application pushes the requested buffer later, we support both + * possiblities. */ + if (!g_queue_is_empty (priv->queue)) + continue; + + /* no buffer yet, maybe we are EOS, if not, block for more data. */ + } + + /* check EOS */ + if (G_UNLIKELY (priv->is_eos)) + goto eos; + + /* nothing to return, wait a while for new data or flushing. */ + g_cond_wait (priv->cond, priv->mutex); + } + g_mutex_unlock (priv->mutex); + if (caps) + gst_caps_unref (caps); + return ret; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (appsrc, "we are flushing"); + g_mutex_unlock (priv->mutex); + if (caps) + gst_caps_unref (caps); + return GST_FLOW_WRONG_STATE; + } +eos: + { + GST_DEBUG_OBJECT (appsrc, "we are EOS"); + g_mutex_unlock (priv->mutex); + if (caps) + gst_caps_unref (caps); + return GST_FLOW_UNEXPECTED; + } +seek_error: + { + g_mutex_unlock (priv->mutex); + if (caps) + gst_caps_unref (caps); + GST_ELEMENT_ERROR (appsrc, RESOURCE, READ, ("failed to seek"), + GST_ERROR_SYSTEM); + return GST_FLOW_ERROR; + } +} + +/* external API */ + +/** + * gst_app_src_set_caps: + * @appsrc: a #GstAppSrc + * @caps: caps to set + * + * Set the capabilities on the appsrc element. This function takes + * a copy of the caps structure. After calling this method, the source will + * only produce caps that match @caps. @caps must be fixed and the caps on the + * buffers must match the caps or left NULL. + * + * Since: 0.10.22 + */ +void +gst_app_src_set_caps (GstAppSrc * appsrc, const GstCaps * caps) +{ + GstCaps *old; + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + GST_DEBUG_OBJECT (appsrc, "setting caps to %" GST_PTR_FORMAT, caps); + if ((old = priv->caps) != caps) { + if (caps) + priv->caps = gst_caps_copy (caps); + else + priv->caps = NULL; + if (old) + gst_caps_unref (old); + } + GST_OBJECT_UNLOCK (appsrc); +} + +/** + * gst_app_src_get_caps: + * @appsrc: a #GstAppSrc + * + * Get the configured caps on @appsrc. + * + * Returns: the #GstCaps produced by the source. gst_caps_unref() after usage. + * + * Since: 0.10.22 + */ +GstCaps * +gst_app_src_get_caps (GstAppSrc * appsrc) +{ + GstCaps *caps; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), NULL); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + if ((caps = priv->caps)) + gst_caps_ref (caps); + GST_DEBUG_OBJECT (appsrc, "getting caps of %" GST_PTR_FORMAT, caps); + GST_OBJECT_UNLOCK (appsrc); + + return caps; +} + +/** + * gst_app_src_set_size: + * @appsrc: a #GstAppSrc + * @size: the size to set + * + * Set the size of the stream in bytes. A value of -1 means that the size is + * not known. + * + * Since: 0.10.22 + */ +void +gst_app_src_set_size (GstAppSrc * appsrc, gint64 size) +{ + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + GST_DEBUG_OBJECT (appsrc, "setting size of %" G_GINT64_FORMAT, size); + priv->size = size; + GST_OBJECT_UNLOCK (appsrc); +} + +/** + * gst_app_src_get_size: + * @appsrc: a #GstAppSrc + * + * Get the size of the stream in bytes. A value of -1 means that the size is + * not known. + * + * Returns: the size of the stream previously set with gst_app_src_set_size(); + * + * Since: 0.10.22 + */ +gint64 +gst_app_src_get_size (GstAppSrc * appsrc) +{ + gint64 size; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), -1); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + size = priv->size; + GST_DEBUG_OBJECT (appsrc, "getting size of %" G_GINT64_FORMAT, size); + GST_OBJECT_UNLOCK (appsrc); + + return size; +} + +/** + * gst_app_src_set_stream_type: + * @appsrc: a #GstAppSrc + * @type: the new state + * + * Set the stream type on @appsrc. For seekable streams, the "seek" signal must + * be connected to. + * + * A stream_type stream + * + * Since: 0.10.22 + */ +void +gst_app_src_set_stream_type (GstAppSrc * appsrc, GstAppStreamType type) +{ + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + GST_DEBUG_OBJECT (appsrc, "setting stream_type of %d", type); + priv->stream_type = type; + GST_OBJECT_UNLOCK (appsrc); +} + +/** + * gst_app_src_get_stream_type: + * @appsrc: a #GstAppSrc + * + * Get the stream type. Control the stream type of @appsrc + * with gst_app_src_set_stream_type(). + * + * Returns: the stream type. + * + * Since: 0.10.22 + */ +GstAppStreamType +gst_app_src_get_stream_type (GstAppSrc * appsrc) +{ + gboolean stream_type; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), FALSE); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + stream_type = priv->stream_type; + GST_DEBUG_OBJECT (appsrc, "getting stream_type of %d", stream_type); + GST_OBJECT_UNLOCK (appsrc); + + return stream_type; +} + +/** + * gst_app_src_set_max_bytes: + * @appsrc: a #GstAppSrc + * @max: the maximum number of bytes to queue + * + * Set the maximum amount of bytes that can be queued in @appsrc. + * After the maximum amount of bytes are queued, @appsrc will emit the + * "enough-data" signal. + * + * Since: 0.10.22 + */ +void +gst_app_src_set_max_bytes (GstAppSrc * appsrc, guint64 max) +{ + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + if (max != priv->max_bytes) { + GST_DEBUG_OBJECT (appsrc, "setting max-bytes to %" G_GUINT64_FORMAT, max); + priv->max_bytes = max; + /* signal the change */ + g_cond_broadcast (priv->cond); + } + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_src_get_max_bytes: + * @appsrc: a #GstAppSrc + * + * Get the maximum amount of bytes that can be queued in @appsrc. + * + * Returns: The maximum amount of bytes that can be queued. + * + * Since: 0.10.22 + */ +guint64 +gst_app_src_get_max_bytes (GstAppSrc * appsrc) +{ + guint64 result; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), 0); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + result = priv->max_bytes; + GST_DEBUG_OBJECT (appsrc, "getting max-bytes of %" G_GUINT64_FORMAT, result); + g_mutex_unlock (priv->mutex); + + return result; +} + +static void +gst_app_src_set_latencies (GstAppSrc * appsrc, gboolean do_min, guint64 min, + gboolean do_max, guint64 max) +{ + GstAppSrcPrivate *priv = appsrc->priv; + gboolean changed = FALSE; + + g_mutex_lock (priv->mutex); + if (do_min && priv->min_latency != min) { + priv->min_latency = min; + changed = TRUE; + } + if (do_max && priv->max_latency != max) { + priv->max_latency = max; + changed = TRUE; + } + g_mutex_unlock (priv->mutex); + + if (changed) { + GST_DEBUG_OBJECT (appsrc, "posting latency changed"); + gst_element_post_message (GST_ELEMENT_CAST (appsrc), + gst_message_new_latency (GST_OBJECT_CAST (appsrc))); + } +} + +/** + * gst_app_src_set_latency: + * @appsrc: a #GstAppSrc + * @min: the min latency + * @max: the min latency + * + * Configure the @min and @max latency in @src. If @min is set to -1, the + * default latency calculations for pseudo-live sources will be used. + * + * Since: 0.10.22 + */ +void +gst_app_src_set_latency (GstAppSrc * appsrc, guint64 min, guint64 max) +{ + gst_app_src_set_latencies (appsrc, TRUE, min, TRUE, max); +} + +/** + * gst_app_src_get_latency: + * @appsrc: a #GstAppSrc + * @min: the min latency + * @max: the min latency + * + * Retrieve the min and max latencies in @min and @max respectively. + * + * Since: 0.10.22 + */ +void +gst_app_src_get_latency (GstAppSrc * appsrc, guint64 * min, guint64 * max) +{ + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + if (min) + *min = priv->min_latency; + if (max) + *max = priv->max_latency; + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_src_set_emit_signals: + * @appsrc: a #GstAppSrc + * @emit: the new state + * + * Make appsrc emit the "new-preroll" and "new-buffer" signals. This option is + * by default disabled because signal emission is expensive and unneeded when + * the application prefers to operate in pull mode. + * + * Since: 0.10.23 + */ +void +gst_app_src_set_emit_signals (GstAppSrc * appsrc, gboolean emit) +{ + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + priv->emit_signals = emit; + g_mutex_unlock (priv->mutex); +} + +/** + * gst_app_src_get_emit_signals: + * @appsrc: a #GstAppSrc + * + * Check if appsrc will emit the "new-preroll" and "new-buffer" signals. + * + * Returns: %TRUE if @appsrc is emiting the "new-preroll" and "new-buffer" + * signals. + * + * Since: 0.10.23 + */ +gboolean +gst_app_src_get_emit_signals (GstAppSrc * appsrc) +{ + gboolean result; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), FALSE); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + result = priv->emit_signals; + g_mutex_unlock (priv->mutex); + + return result; +} + +static GstFlowReturn +gst_app_src_push_buffer_full (GstAppSrc * appsrc, GstBuffer * buffer, + gboolean steal_ref) +{ + gboolean first = TRUE; + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), GST_FLOW_ERROR); + g_return_val_if_fail (GST_IS_BUFFER (buffer), GST_FLOW_ERROR); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + + while (TRUE) { + /* can't accept buffers when we are flushing or EOS */ + if (priv->flushing) + goto flushing; + + if (priv->is_eos) + goto eos; + + if (priv->max_bytes && priv->queued_bytes >= priv->max_bytes) { + GST_DEBUG_OBJECT (appsrc, + "queue filled (%" G_GUINT64_FORMAT " >= %" G_GUINT64_FORMAT ")", + priv->queued_bytes, priv->max_bytes); + + if (first) { + gboolean emit; + + emit = priv->emit_signals; + /* only signal on the first push */ + g_mutex_unlock (priv->mutex); + + if (priv->callbacks.enough_data) + priv->callbacks.enough_data (appsrc, priv->user_data); + else if (emit) + g_signal_emit (appsrc, gst_app_src_signals[SIGNAL_ENOUGH_DATA], 0, + NULL); + + g_mutex_lock (priv->mutex); + /* continue to check for flushing/eos after releasing the lock */ + first = FALSE; + continue; + } + if (priv->block) { + GST_DEBUG_OBJECT (appsrc, "waiting for free space"); + /* we are filled, wait until a buffer gets popped or when we + * flush. */ + g_cond_wait (priv->cond, priv->mutex); + } else { + /* no need to wait for free space, we just pump more data into the + * queue hoping that the caller reacts to the enough-data signal and + * stops pushing buffers. */ + break; + } + } else + break; + } + + GST_DEBUG_OBJECT (appsrc, "queueing buffer %p", buffer); + if (!steal_ref) + gst_buffer_ref (buffer); + g_queue_push_tail (priv->queue, buffer); + priv->queued_bytes += GST_BUFFER_SIZE (buffer); + g_cond_broadcast (priv->cond); + g_mutex_unlock (priv->mutex); + + return GST_FLOW_OK; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are flushing", buffer); + if (steal_ref) + gst_buffer_unref (buffer); + g_mutex_unlock (priv->mutex); + return GST_FLOW_WRONG_STATE; + } +eos: + { + GST_DEBUG_OBJECT (appsrc, "refuse buffer %p, we are EOS", buffer); + if (steal_ref) + gst_buffer_unref (buffer); + g_mutex_unlock (priv->mutex); + return GST_FLOW_UNEXPECTED; + } +} + +/** + * gst_app_src_push_buffer: + * @appsrc: a #GstAppSrc + * @buffer: a #GstBuffer to push + * + * Adds a buffer to the queue of buffers that the appsrc element will + * push to its source pad. This function takes ownership of the buffer. + * + * When the block property is TRUE, this function can block until free + * space becomes available in the queue. + * + * Returns: #GST_FLOW_OK when the buffer was successfuly queued. + * #GST_FLOW_WRONG_STATE when @appsrc is not PAUSED or PLAYING. + * #GST_FLOW_UNEXPECTED when EOS occured. + * + * Since: 0.10.22 + */ +GstFlowReturn +gst_app_src_push_buffer (GstAppSrc * appsrc, GstBuffer * buffer) +{ + return gst_app_src_push_buffer_full (appsrc, buffer, TRUE); +} + +/* push a buffer without stealing the ref of the buffer. This is used for the + * action signal. */ +static GstFlowReturn +gst_app_src_push_buffer_action (GstAppSrc * appsrc, GstBuffer * buffer) +{ + return gst_app_src_push_buffer_full (appsrc, buffer, FALSE); +} + +/** + * gst_app_src_end_of_stream: + * @appsrc: a #GstAppSrc + * + * Indicates to the appsrc element that the last buffer queued in the + * element is the last buffer of the stream. + * + * Returns: #GST_FLOW_OK when the EOS was successfuly queued. + * #GST_FLOW_WRONG_STATE when @appsrc is not PAUSED or PLAYING. + * + * Since: 0.10.22 + */ +GstFlowReturn +gst_app_src_end_of_stream (GstAppSrc * appsrc) +{ + GstAppSrcPrivate *priv; + + g_return_val_if_fail (GST_IS_APP_SRC (appsrc), GST_FLOW_ERROR); + + priv = appsrc->priv; + + g_mutex_lock (priv->mutex); + /* can't accept buffers when we are flushing. We can accept them when we are + * EOS although it will not do anything. */ + if (priv->flushing) + goto flushing; + + GST_DEBUG_OBJECT (appsrc, "sending EOS"); + priv->is_eos = TRUE; + g_cond_broadcast (priv->cond); + g_mutex_unlock (priv->mutex); + + return GST_FLOW_OK; + + /* ERRORS */ +flushing: + { + g_mutex_unlock (priv->mutex); + GST_DEBUG_OBJECT (appsrc, "refuse EOS, we are flushing"); + return GST_FLOW_WRONG_STATE; + } +} + +/** + * gst_app_src_set_callbacks: + * @appsrc: a #GstAppSrc + * @callbacks: the callbacks + * @user_data: a user_data argument for the callbacks + * @notify: a destroy notify function + * + * Set callbacks which will be executed when data is needed, enough data has + * been collected or when a seek should be performed. + * This is an alternative to using the signals, it has lower overhead and is thus + * less expensive, but also less flexible. + * + * If callbacks are installed, no signals will be emited for performance + * reasons. + * + * Since: 0.10.23 + */ +void +gst_app_src_set_callbacks (GstAppSrc * appsrc, + GstAppSrcCallbacks * callbacks, gpointer user_data, GDestroyNotify notify) +{ + GDestroyNotify old_notify; + GstAppSrcPrivate *priv; + + g_return_if_fail (GST_IS_APP_SRC (appsrc)); + g_return_if_fail (callbacks != NULL); + + priv = appsrc->priv; + + GST_OBJECT_LOCK (appsrc); + old_notify = priv->notify; + + if (old_notify) { + gpointer old_data; + + old_data = priv->user_data; + + priv->user_data = NULL; + priv->notify = NULL; + GST_OBJECT_UNLOCK (appsrc); + + old_notify (old_data); + + GST_OBJECT_LOCK (appsrc); + } + priv->callbacks = *callbacks; + priv->user_data = user_data; + priv->notify = notify; + GST_OBJECT_UNLOCK (appsrc); +} + +/*** GSTURIHANDLER INTERFACE *************************************************/ + +static GstURIType +gst_app_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_app_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "appsrc", NULL }; + + return protocols; +} + +static const gchar * +gst_app_src_uri_get_uri (GstURIHandler * handler) +{ + return "appsrc"; +} + +static gboolean +gst_app_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + gchar *protocol; + gboolean ret; + + protocol = gst_uri_get_protocol (uri); + ret = !strcmp (protocol, "appsrc"); + g_free (protocol); + + return ret; +} + +static void +gst_app_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_app_src_uri_get_type; + iface->get_protocols = gst_app_src_uri_get_protocols; + iface->get_uri = gst_app_src_uri_get_uri; + iface->set_uri = gst_app_src_uri_set_uri; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.h new file mode 100644 index 0000000..041cb68 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/app/gstappsrc.h @@ -0,0 +1,153 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_APP_SRC_H_ +#define _GST_APP_SRC_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_APP_SRC \ + (gst_app_src_get_type()) +#define GST_APP_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_APP_SRC,GstAppSrc)) +#define GST_APP_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_APP_SRC,GstAppSrcClass)) +#define GST_IS_APP_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_APP_SRC)) +#define GST_IS_APP_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_APP_SRC)) +/* Since 0.10.23 */ +#define GST_APP_SRC_CAST(obj) \ + ((GstAppSrc*)(obj)) + +typedef struct _GstAppSrc GstAppSrc; +typedef struct _GstAppSrcClass GstAppSrcClass; +typedef struct _GstAppSrcPrivate GstAppSrcPrivate; + +/** + * GstAppSrcCallbacks: + * @need_data: Called when the appsrc needs more data. A buffer or EOS should be + * pushed to appsrc from this thread or another thread. @length is just a hint + * and when it is set to -1, any number of bytes can be pushed into @appsrc. + * @enough_data: Called when appsrc has enough data. It is recommended that the + * application stops calling push-buffer until the need_data callback is + * emited again to avoid excessive buffer queueing. + * @seek_data: Called when a seek should be performed to the offset. + * The next push-buffer should produce buffers from the new @offset. + * This callback is only called for seekable stream types. + * + * A set of callbacks that can be installed on the appsrc with + * gst_app_src_set_callbacks(). + * + * Since: 0.10.23 + */ +typedef struct { + void (*need_data) (GstAppSrc *src, guint length, gpointer user_data); + void (*enough_data) (GstAppSrc *src, gpointer user_data); + gboolean (*seek_data) (GstAppSrc *src, guint64 offset, gpointer user_data); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +} GstAppSrcCallbacks; + +/** + * GstAppStreamType: + * @GST_APP_STREAM_TYPE_STREAM: No seeking is supported in the stream, such as a + * live stream. + * @GST_APP_STREAM_TYPE_SEEKABLE: The stream is seekable but seeking might not + * be very fast, such as data from a webserver. + * @GST_APP_STREAM_TYPE_RANDOM_ACCESS: The stream is seekable and seeking is fast, + * such as in a local file. + * + * The stream type. + */ +typedef enum +{ + GST_APP_STREAM_TYPE_STREAM, + GST_APP_STREAM_TYPE_SEEKABLE, + GST_APP_STREAM_TYPE_RANDOM_ACCESS +} GstAppStreamType; + +struct _GstAppSrc +{ + GstBaseSrc basesrc; + + /*< private >*/ + GstAppSrcPrivate *priv; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstAppSrcClass +{ + GstBaseSrcClass basesrc_class; + + /* signals */ + void (*need_data) (GstAppSrc *src, guint length); + void (*enough_data) (GstAppSrc *src); + gboolean (*seek_data) (GstAppSrc *src, guint64 offset); + + /* actions */ + GstFlowReturn (*push_buffer) (GstAppSrc *src, GstBuffer *buffer); + GstFlowReturn (*end_of_stream) (GstAppSrc *src); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_app_src_get_type(void); + +/* GType getter for GstAppStreamType, since 0.10.32 */ +#define GST_TYPE_APP_STREAM_TYPE (gst_app_stream_type_get_type ()) +GType gst_app_stream_type_get_type (void); + +void gst_app_src_set_caps (GstAppSrc *appsrc, const GstCaps *caps); +GstCaps* gst_app_src_get_caps (GstAppSrc *appsrc); + +void gst_app_src_set_size (GstAppSrc *appsrc, gint64 size); +gint64 gst_app_src_get_size (GstAppSrc *appsrc); + +void gst_app_src_set_stream_type (GstAppSrc *appsrc, GstAppStreamType type); +GstAppStreamType gst_app_src_get_stream_type (GstAppSrc *appsrc); + +void gst_app_src_set_max_bytes (GstAppSrc *appsrc, guint64 max); +guint64 gst_app_src_get_max_bytes (GstAppSrc *appsrc); + +void gst_app_src_set_latency (GstAppSrc *appsrc, guint64 min, guint64 max); +void gst_app_src_get_latency (GstAppSrc *appsrc, guint64 *min, guint64 *max); + +void gst_app_src_set_emit_signals (GstAppSrc *appsrc, gboolean emit); +gboolean gst_app_src_get_emit_signals (GstAppSrc *appsrc); + +GstFlowReturn gst_app_src_push_buffer (GstAppSrc *appsrc, GstBuffer *buffer); +GstFlowReturn gst_app_src_end_of_stream (GstAppSrc *appsrc); + +void gst_app_src_set_callbacks (GstAppSrc * appsrc, + GstAppSrcCallbacks *callbacks, + gpointer user_data, + GDestroyNotify notify); + +G_END_DECLS + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/.gitignore new file mode 100644 index 0000000..1b3d8d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/.gitignore @@ -0,0 +1,4 @@ +libgstaudio_la-multichannel-enumtypes.lo +audio-enumtypes.c +audio-enumtypes.h +testchannels diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/Makefile.am new file mode 100644 index 0000000..e531e73 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/Makefile.am @@ -0,0 +1,132 @@ +# variables used for enum/marshal generation +glib_enum_headers= \ + multichannel.h \ + gstringbuffer.h + +glib_enum_define = GST_AUDIO +glib_gen_prefix = gst_audio +glib_gen_basename = audio + +built_sources = audio-enumtypes.c +built_headers = audio-enumtypes.h +BUILT_SOURCES = $(built_sources) $(built_headers) + +lib_LTLIBRARIES = \ + libgstaudio-@GST_MAJORMINOR@.la + +CLEANFILES = $(BUILT_SOURCES) + +libgstaudio_@GST_MAJORMINOR@_la_SOURCES = \ + audio.c \ + gstringbuffer.c \ + gstaudioclock.c \ + mixerutils.c \ + multichannel.c \ + gstbaseaudiosink.c \ + gstbaseaudiosrc.c \ + gstaudiofilter.c \ + gstaudiosink.c \ + gstaudiosrc.c +nodist_libgstaudio_@GST_MAJORMINOR@_la_SOURCES = $(built_sources) $(built_headers) + +libgstaudio_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/audio +libgstaudio_@GST_MAJORMINOR@include_HEADERS = \ + audio.h \ + gstringbuffer.h \ + gstaudioclock.h \ + gstaudiofilter.h \ + gstbaseaudiosink.h \ + gstbaseaudiosrc.h \ + gstaudiosink.h \ + gstaudiosrc.h \ + mixerutils.h \ + multichannel.h + +nodist_libgstaudio_@GST_MAJORMINOR@include_HEADERS = \ + audio-enumtypes.h + +libgstaudio_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstaudio_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la +libgstaudio_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +noinst_PROGRAMS = testchannels +testchannels_SOURCES = testchannels.c +testchannels_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +testchannels_LDADD = $(GST_LIBS) + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstAudio-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstaudio_@GST_MAJORMINOR@include_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstaudio_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstaudio_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstaudio_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/audio/%',$(libgstaudio_@GST_MAJORMINOR@include_HEADERS)) +gir_cincludes+=$(patsubst %,--c-include='gst/audio/%',$(nodist_libgstaudio_@GST_MAJORMINOR@include_HEADERS)) + +GstAudio-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstaudio-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstAudio \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + $(gir_cincludes) \ + --add-include-path=$(builddir)/../interfaces \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstaudio-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --include=GstInterfaces-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg gstreamer-interfaces-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-audio-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=$(builddir)/../interfaces \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstaudio -:SHARED libgstaudio-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstaudio_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstaudio_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudio_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstaudio_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstaudio_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/tag \ + -:HEADERS $(libgstaudio_@GST_MAJORMINOR@include_HEADERS) \ + $(nodist_libgstaudio_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/TODO b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/TODO new file mode 100644 index 0000000..887f340 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/TODO @@ -0,0 +1,15 @@ +TODO +---- + +- audio base classes: + - GstBaseAudioSink + - parse caps into rinbuffer spec, also make sure surround sound + is parsed correctly. + - implement seek/query/convert + - implement getrange scheduling + - simple resampling + - more accurate master/slave calibration handling + - faster audio cutoff when going to PAUSED + - resubmit samples from ringbuffer when doing PAUSED->PLAYING again + - the ringbuffer should have a state where it is filling up the + buffer before going to playing. diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.c new file mode 100644 index 0000000..bf99a52 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.c @@ -0,0 +1,435 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudio + * @short_description: Support library for audio elements + * + * This library contains some helper functions for audio elements. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "audio.h" +#include "audio-enumtypes.h" + +#include + +/** + * gst_audio_frame_byte_size: + * @pad: the #GstPad to get the caps from + * + * Calculate byte size of an audio frame. + * + * Returns: the byte size, or 0 if there was an error + */ +int +gst_audio_frame_byte_size (GstPad * pad) +{ + /* FIXME: this should be moved closer to the gstreamer core + * and be implemented for every mime type IMO + */ + + int width = 0; + int channels = 0; + const GstCaps *caps = NULL; + GstStructure *structure; + + /* get caps of pad */ + caps = GST_PAD_CAPS (pad); + + if (caps == NULL) { + /* ERROR: could not get caps of pad */ + g_warning ("gstaudio: could not get caps of pad %s:%s\n", + GST_DEBUG_PAD_NAME (pad)); + return 0; + } + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "channels", &channels); + return (width / 8) * channels; +} + +/** + * gst_audio_frame_length: + * @pad: the #GstPad to get the caps from + * @buf: the #GstBuffer + * + * Calculate length of buffer in frames. + * + * Returns: 0 if there's an error, or the number of frames if everything's ok + */ +long +gst_audio_frame_length (GstPad * pad, GstBuffer * buf) +{ + /* FIXME: this should be moved closer to the gstreamer core + * and be implemented for every mime type IMO + */ + int frame_byte_size = 0; + + frame_byte_size = gst_audio_frame_byte_size (pad); + if (frame_byte_size == 0) + /* error */ + return 0; + /* FIXME: this function assumes the buffer size to be a whole multiple + * of the frame byte size + */ + return GST_BUFFER_SIZE (buf) / frame_byte_size; +} + +/** + * gst_audio_duration_from_pad_buffer: + * @pad: the #GstPad to get the caps from + * @buf: the #GstBuffer + * + * Calculate length in nanoseconds of audio buffer @buf based on capabilities of + * @pad. + * + * Returns: the length. + */ +GstClockTime +gst_audio_duration_from_pad_buffer (GstPad * pad, GstBuffer * buf) +{ + long bytes = 0; + int width = 0; + int channels = 0; + int rate = 0; + + GstClockTime length; + + const GstCaps *caps = NULL; + GstStructure *structure; + + g_assert (GST_IS_BUFFER (buf)); + /* get caps of pad */ + caps = GST_PAD_CAPS (pad); + if (caps == NULL) { + /* ERROR: could not get caps of pad */ + g_warning ("gstaudio: could not get caps of pad %s:%s\n", + GST_DEBUG_PAD_NAME (pad)); + length = GST_CLOCK_TIME_NONE; + } else { + structure = gst_caps_get_structure (caps, 0); + bytes = GST_BUFFER_SIZE (buf); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "channels", &channels); + gst_structure_get_int (structure, "rate", &rate); + + g_assert (bytes != 0); + g_assert (width != 0); + g_assert (channels != 0); + g_assert (rate != 0); + length = (bytes * 8 * GST_SECOND) / (rate * channels * width); + } + return length; +} + +/** + * gst_audio_is_buffer_framed: + * @pad: the #GstPad to get the caps from + * @buf: the #GstBuffer + * + * Check if the buffer size is a whole multiple of the frame size. + * + * Returns: %TRUE if buffer size is multiple. + */ +gboolean +gst_audio_is_buffer_framed (GstPad * pad, GstBuffer * buf) +{ + if (GST_BUFFER_SIZE (buf) % gst_audio_frame_byte_size (pad) == 0) + return TRUE; + else + return FALSE; +} + +/* _getcaps helper functions + * sets structure fields to default for audio type + * flag determines which structure fields to set to default + * keep these functions in sync with the templates in audio.h + */ + +/* private helper function + * sets a list on the structure + * pass in structure, fieldname for the list, type of the list values, + * number of list values, and each of the values, terminating with NULL + */ +static void +_gst_audio_structure_set_list (GstStructure * structure, + const gchar * fieldname, GType type, int number, ...) +{ + va_list varargs; + GValue value = { 0 }; + GArray *array; + int j; + + g_return_if_fail (structure != NULL); + + g_value_init (&value, GST_TYPE_LIST); + array = g_value_peek_pointer (&value); + + va_start (varargs, number); + + for (j = 0; j < number; ++j) { + int i; + gboolean b; + + GValue list_value = { 0 }; + + switch (type) { + case G_TYPE_INT: + i = va_arg (varargs, int); + + g_value_init (&list_value, G_TYPE_INT); + g_value_set_int (&list_value, i); + break; + case G_TYPE_BOOLEAN: + b = va_arg (varargs, gboolean); + g_value_init (&list_value, G_TYPE_BOOLEAN); + g_value_set_boolean (&list_value, b); + break; + default: + g_warning + ("_gst_audio_structure_set_list: LIST of given type not implemented."); + } + g_array_append_val (array, list_value); + + } + gst_structure_set_value (structure, fieldname, &value); + va_end (varargs); +} + +/** + * gst_audio_structure_set_int: + * @structure: a #GstStructure + * @flag: a set of #GstAudioFieldFlag + * + * Do not use anymore. + * + * Deprecated: use gst_structure_set() + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +typedef enum +{ + GST_AUDIO_FIELD_RATE = (1 << 0), + GST_AUDIO_FIELD_CHANNELS = (1 << 1), + GST_AUDIO_FIELD_ENDIANNESS = (1 << 2), + GST_AUDIO_FIELD_WIDTH = (1 << 3), + GST_AUDIO_FIELD_DEPTH = (1 << 4), + GST_AUDIO_FIELD_SIGNED = (1 << 5), +} GstAudioFieldFlag; +void +gst_audio_structure_set_int (GstStructure * structure, GstAudioFieldFlag flag); +#endif /* GST_DISABLE_DEPRECATED */ + +void +gst_audio_structure_set_int (GstStructure * structure, GstAudioFieldFlag flag) +{ + /* was added here: + * http://webcvs.freedesktop.org/gstreamer/gst-plugins-base/gst-libs/gst/audio/audio.c?r1=1.16&r2=1.17 + * but it is not used + */ + if (flag & GST_AUDIO_FIELD_RATE) + gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, + NULL); + if (flag & GST_AUDIO_FIELD_CHANNELS) + gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, + NULL); + if (flag & GST_AUDIO_FIELD_ENDIANNESS) + _gst_audio_structure_set_list (structure, "endianness", G_TYPE_INT, 2, + G_LITTLE_ENDIAN, G_BIG_ENDIAN, NULL); + if (flag & GST_AUDIO_FIELD_WIDTH) + _gst_audio_structure_set_list (structure, "width", G_TYPE_INT, 3, 8, 16, 32, + NULL); + if (flag & GST_AUDIO_FIELD_DEPTH) + gst_structure_set (structure, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL); + if (flag & GST_AUDIO_FIELD_SIGNED) + _gst_audio_structure_set_list (structure, "signed", G_TYPE_BOOLEAN, 2, TRUE, + FALSE, NULL); +} +#endif /* GST_REMOVE_DEPRECATED */ + +/** + * gst_audio_buffer_clip: + * @buffer: The buffer to clip. + * @segment: Segment in %GST_FORMAT_TIME or %GST_FORMAT_DEFAULT to which the buffer should be clipped. + * @rate: sample rate. + * @frame_size: size of one audio frame in bytes. + * + * Clip the the buffer to the given %GstSegment. + * + * After calling this function the caller does not own a reference to + * @buffer anymore. + * + * Returns: %NULL if the buffer is completely outside the configured segment, + * otherwise the clipped buffer is returned. + * + * If the buffer has no timestamp, it is assumed to be inside the segment and + * is not clipped + * + * Since: 0.10.14 + */ +GstBuffer * +gst_audio_buffer_clip (GstBuffer * buffer, GstSegment * segment, gint rate, + gint frame_size) +{ + GstBuffer *ret; + GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE; + guint64 offset = GST_BUFFER_OFFSET_NONE, offset_end = GST_BUFFER_OFFSET_NONE; + guint8 *data; + guint size; + + gboolean change_duration = TRUE, change_offset = TRUE, change_offset_end = + TRUE; + + g_return_val_if_fail (segment->format == GST_FORMAT_TIME || + segment->format == GST_FORMAT_DEFAULT, buffer); + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + /* No timestamp - assume the buffer is completely in the segment */ + return buffer; + + /* Get copies of the buffer metadata to change later. + * Calculate the missing values for the calculations, + * they won't be changed later though. */ + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + if (GST_BUFFER_DURATION_IS_VALID (buffer)) { + duration = GST_BUFFER_DURATION (buffer); + } else { + change_duration = FALSE; + duration = gst_util_uint64_scale (size / frame_size, GST_SECOND, rate); + } + + if (GST_BUFFER_OFFSET_IS_VALID (buffer)) { + offset = GST_BUFFER_OFFSET (buffer); + } else { + change_offset = FALSE; + offset = 0; + } + + if (GST_BUFFER_OFFSET_END_IS_VALID (buffer)) { + offset_end = GST_BUFFER_OFFSET_END (buffer); + } else { + change_offset_end = FALSE; + offset_end = offset + size / frame_size; + } + + if (segment->format == GST_FORMAT_TIME) { + /* Handle clipping for GST_FORMAT_TIME */ + + gint64 start, stop, cstart, cstop, diff; + + start = timestamp; + stop = timestamp + duration; + + if (gst_segment_clip (segment, GST_FORMAT_TIME, + start, stop, &cstart, &cstop)) { + + diff = cstart - start; + if (diff > 0) { + timestamp = cstart; + + if (change_duration) + duration -= diff; + + diff = gst_util_uint64_scale (diff, rate, GST_SECOND); + if (change_offset) + offset += diff; + data += diff * frame_size; + size -= diff * frame_size; + } + + diff = stop - cstop; + if (diff > 0) { + /* duration is always valid if stop is valid */ + duration -= diff; + + diff = gst_util_uint64_scale (diff, rate, GST_SECOND); + if (change_offset_end) + offset_end -= diff; + size -= diff * frame_size; + } + } else { + gst_buffer_unref (buffer); + return NULL; + } + } else { + /* Handle clipping for GST_FORMAT_DEFAULT */ + gint64 start, stop, cstart, cstop, diff; + + g_return_val_if_fail (GST_BUFFER_OFFSET_IS_VALID (buffer), buffer); + + start = offset; + stop = offset_end; + + if (gst_segment_clip (segment, GST_FORMAT_DEFAULT, + start, stop, &cstart, &cstop)) { + + diff = cstart - start; + if (diff > 0) { + offset = cstart; + + timestamp = gst_util_uint64_scale (cstart, GST_SECOND, rate); + + if (change_duration) + duration -= gst_util_uint64_scale (diff, GST_SECOND, rate); + + data += diff * frame_size; + size -= diff * frame_size; + } + + diff = stop - cstop; + if (diff > 0) { + offset_end = cstop; + + if (change_duration) + duration -= gst_util_uint64_scale (diff, GST_SECOND, rate); + + size -= diff * frame_size; + } + } else { + gst_buffer_unref (buffer); + return NULL; + } + } + + /* Get a metadata writable buffer and apply all changes */ + ret = gst_buffer_make_metadata_writable (buffer); + + GST_BUFFER_TIMESTAMP (ret) = timestamp; + GST_BUFFER_SIZE (ret) = size; + GST_BUFFER_DATA (ret) = data; + + if (change_duration) + GST_BUFFER_DURATION (ret) = duration; + if (change_offset) + GST_BUFFER_OFFSET (ret) = offset; + if (change_offset_end) + GST_BUFFER_OFFSET_END (ret) = offset_end; + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.def b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.def new file mode 100644 index 0000000..96a3ac0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.def @@ -0,0 +1,5 @@ +EXPORTS + gst_plugin_desc + gst_audio_length + gst_audio_is_buffer_framed + gst_audio_highest_sample_value diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.h new file mode 100644 index 0000000..43bf594 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.h @@ -0,0 +1,185 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2001> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#ifndef __GST_AUDIO_AUDIO_H__ +#define __GST_AUDIO_AUDIO_H__ + +G_BEGIN_DECLS + +/* For people that are looking at this source: the purpose of these defines is + * to make GstCaps a bit easier, in that you don't have to know all of the + * properties that need to be defined. you can just use these macros. currently + * (8/01) the only plugins that use these are the passthrough, speed, volume, + * adder, and [de]interleave plugins. These are for convenience only, and do not + * specify the 'limits' of GStreamer. you might also use these definitions as a + * base for making your own caps, if need be. + * + * For example, to make a source pad that can output streams of either mono + * float or any channel int: + * + * template = gst_pad_template_new + * ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + * gst_caps_append(gst_caps_new ("sink_int", "audio/x-raw-int", + * GST_AUDIO_INT_PAD_TEMPLATE_PROPS), + * gst_caps_new ("sink_float", "audio/x-raw-float", + * GST_AUDIO_FLOAT_PAD_TEMPLATE_PROPS)), + * NULL); + * + * sinkpad = gst_pad_new_from_template(template, "sink"); + * + * Andy Wingo, 18 August 2001 + * Thomas, 6 September 2002 */ + +/* conversion macros */ +/** + * GST_FRAMES_TO_CLOCK_TIME: + * @frames: sample frames + * @rate: sampling rate + * + * Calculate clocktime from sample @frames and @rate. + */ +#define GST_FRAMES_TO_CLOCK_TIME(frames, rate) \ + ((GstClockTime) gst_util_uint64_scale_round (frames, GST_SECOND, rate)) + +/** + * GST_CLOCK_TIME_TO_FRAMES: + * @clocktime: clock time + * @rate: sampling rate + * + * Calculate frames from @clocktime and sample @rate. + */ +#define GST_CLOCK_TIME_TO_FRAMES(clocktime, rate) \ + gst_util_uint64_scale_round (clocktime, rate, GST_SECOND) + +/** + * GST_AUDIO_DEF_RATE: + * + * Standard sampling rate used in consumer audio. + */ +#define GST_AUDIO_DEF_RATE 44100 + +/** + * GST_AUDIO_INT_PAD_TEMPLATE_CAPS: + * + * Template caps for integer audio. Can be used when defining a + * #GstStaticPadTemplate + */ +#define GST_AUDIO_INT_PAD_TEMPLATE_CAPS \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) { 8, 16, 24, 32 }, " \ + "depth = (int) [ 1, 32 ], " \ + "signed = (boolean) { true, false }" + +/** + * GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS: + * + * Template caps for 16bit integer stereo audio in native byte-order. + * Can be used when defining a #GstStaticPadTemplate + */ +#define GST_AUDIO_INT_STANDARD_PAD_TEMPLATE_CAPS \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) 2, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) true" + +/** + * GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS: + * + * Template caps for float audio. Can be used when defining a + * #GstStaticPadTemplate + */ +#define GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN , BIG_ENDIAN }, " \ + "width = (int) { 32, 64 }" + +/** + * GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS: + * + * Template caps for 32bit float mono audio in native byte-order. + * Can be used when defining a #GstStaticPadTemplate + */ +#define GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS \ + "audio/x-raw-float, " \ + "width = (int) 32, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) 1, " \ + "endianness = (int) BYTE_ORDER" + +/* + * this library defines and implements some helper functions for audio + * handling + */ + +/* get byte size of audio frame (based on caps of pad */ +int gst_audio_frame_byte_size (GstPad* pad); + +/* get length in frames of buffer */ +long gst_audio_frame_length (GstPad* pad, GstBuffer* buf); + +GstClockTime gst_audio_duration_from_pad_buffer (GstPad * pad, GstBuffer * buf); + +/* check if the buffer size is a whole multiple of the frame size */ +gboolean gst_audio_is_buffer_framed (GstPad* pad, GstBuffer* buf); + +/* functions useful for _getcaps functions */ +/** + * GstAudioFieldFlag: + * @GST_AUDIO_FIELD_RATE: add rate field to caps + * @GST_AUDIO_FIELD_CHANNELS: add channels field to caps + * @GST_AUDIO_FIELD_ENDIANNESS: add endianness field to caps + * @GST_AUDIO_FIELD_WIDTH: add width field to caps + * @GST_AUDIO_FIELD_DEPTH: add depth field to caps + * @GST_AUDIO_FIELD_SIGNED: add signed field to caps + * + * Do not use anymore. + * + * Deprecated: use gst_structure_set() directly + */ +#ifndef GST_DISABLE_DEPRECATED +typedef enum { + GST_AUDIO_FIELD_RATE = (1 << 0), + GST_AUDIO_FIELD_CHANNELS = (1 << 1), + GST_AUDIO_FIELD_ENDIANNESS = (1 << 2), + GST_AUDIO_FIELD_WIDTH = (1 << 3), + GST_AUDIO_FIELD_DEPTH = (1 << 4), + GST_AUDIO_FIELD_SIGNED = (1 << 5) +} GstAudioFieldFlag; +#endif + +#ifndef GST_DISABLE_DEPRECATED +void gst_audio_structure_set_int (GstStructure *structure, GstAudioFieldFlag flag); +#endif /* GST_DISABLE_DEPRECATED */ + +GstBuffer *gst_audio_buffer_clip (GstBuffer *buffer, GstSegment *segment, gint rate, gint frame_size); + +G_END_DECLS + +#endif /* __GST_AUDIO_AUDIO_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.vcproj b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.vcproj new file mode 100644 index 0000000..2111531 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audio.vcproj @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audiofilter.vcproj b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audiofilter.vcproj new file mode 100644 index 0000000..d551260 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/audiofilter.vcproj @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.c new file mode 100644 index 0000000..9d6e485 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.c @@ -0,0 +1,314 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * audioclock.c: Clock for use by audio plugins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudioclock + * @short_description: Helper object for implementing audio clocks + * @see_also: #GstBaseAudioSink, #GstSystemClock + * + * #GstAudioClock makes it easy for elements to implement a #GstClock, they + * simply need to provide a function that returns the current clock time. + * + * This object is internally used to implement the clock in #GstBaseAudioSink. + * + * Last reviewed on 2006-09-27 (0.10.12) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstaudioclock.h" + +GST_DEBUG_CATEGORY_STATIC (gst_audio_clock_debug); +#define GST_CAT_DEFAULT gst_audio_clock_debug + +static void gst_audio_clock_class_init (GstAudioClockClass * klass); +static void gst_audio_clock_init (GstAudioClock * clock); + +static void gst_audio_clock_dispose (GObject * object); + +static GstClockTime gst_audio_clock_get_internal_time (GstClock * clock); + +static GstSystemClockClass *parent_class = NULL; + +/* static guint gst_audio_clock_signals[LAST_SIGNAL] = { 0 }; */ + +GType +gst_audio_clock_get_type (void) +{ + static volatile gsize clock_type = 0; + static const GTypeInfo clock_info = { + sizeof (GstAudioClockClass), + NULL, + NULL, + (GClassInitFunc) gst_audio_clock_class_init, + NULL, + NULL, + sizeof (GstAudioClock), + 4, + (GInstanceInitFunc) gst_audio_clock_init, + NULL + }; + + if (g_once_init_enter (&clock_type)) { + GType tmp = g_type_register_static (GST_TYPE_SYSTEM_CLOCK, "GstAudioClock", + &clock_info, 0); + g_once_init_leave (&clock_type, tmp); + } + + return (GType) clock_type; +} + +static void +gst_audio_clock_class_init (GstAudioClockClass * klass) +{ + GstClockClass *gstclock_class; + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + gstclock_class = (GstClockClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_audio_clock_dispose; + gstclock_class->get_internal_time = gst_audio_clock_get_internal_time; + + GST_DEBUG_CATEGORY_INIT (gst_audio_clock_debug, "audioclock", 0, + "audioclock"); +} + +static void +gst_audio_clock_init (GstAudioClock * clock) +{ + GST_DEBUG_OBJECT (clock, "init"); + clock->last_time = 0; + clock->abidata.ABI.time_offset = 0; + GST_OBJECT_FLAG_SET (clock, GST_CLOCK_FLAG_CAN_SET_MASTER); +} + +static void +gst_audio_clock_dispose (GObject * object) +{ + GstAudioClock *clock = GST_AUDIO_CLOCK (object); + + if (clock->abidata.ABI.destroy_notify && clock->user_data) + clock->abidata.ABI.destroy_notify (clock->user_data); + clock->abidata.ABI.destroy_notify = NULL; + clock->user_data = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/** + * gst_audio_clock_new: + * @name: the name of the clock + * @func: a function + * @user_data: user data + * + * Create a new #GstAudioClock instance. Whenever the clock time should be + * calculated it will call @func with @user_data. When @func returns + * #GST_CLOCK_TIME_NONE, the clock will return the last reported time. + * + * Returns: a new #GstAudioClock casted to a #GstClock. + */ +GstClock * +gst_audio_clock_new (const gchar * name, GstAudioClockGetTimeFunc func, + gpointer user_data) +{ + GstAudioClock *aclock = + GST_AUDIO_CLOCK (g_object_new (GST_TYPE_AUDIO_CLOCK, "name", name, NULL)); + + aclock->func = func; + aclock->user_data = user_data; + + return (GstClock *) aclock; +} + +/** + * gst_audio_clock_new_full: + * @name: the name of the clock + * @func: a function + * @user_data: user data + * @destroy_notify: #GDestroyNotify for @user_data + * + * Create a new #GstAudioClock instance. Whenever the clock time should be + * calculated it will call @func with @user_data. When @func returns + * #GST_CLOCK_TIME_NONE, the clock will return the last reported time. + * + * Returns: a new #GstAudioClock casted to a #GstClock. + * + * Since: 0.10.31 + */ +GstClock * +gst_audio_clock_new_full (const gchar * name, GstAudioClockGetTimeFunc func, + gpointer user_data, GDestroyNotify destroy_notify) +{ + GstAudioClock *aclock = + GST_AUDIO_CLOCK (g_object_new (GST_TYPE_AUDIO_CLOCK, "name", name, NULL)); + + aclock->func = func; + aclock->user_data = user_data; + aclock->abidata.ABI.destroy_notify = destroy_notify; + + return (GstClock *) aclock; +} + +/** + * gst_audio_clock_reset: + * @clock: a #GstAudioClock + * @time: a #GstClockTime + * + * Inform @clock that future calls to #GstAudioClockGetTimeFunc will return values + * starting from @time. The clock will update an internal offset to make sure that + * future calls to internal_time will return an increasing result as required by + * the #GstClock object. + */ +void +gst_audio_clock_reset (GstAudioClock * clock, GstClockTime time) +{ + GstClockTimeDiff time_offset; + + if (clock->last_time >= time) + time_offset = clock->last_time - time; + else + time_offset = -(time - clock->last_time); + + clock->abidata.ABI.time_offset = time_offset; + + GST_DEBUG_OBJECT (clock, + "reset clock to %" GST_TIME_FORMAT ", last %" GST_TIME_FORMAT ", offset %" + GST_TIME_FORMAT, GST_TIME_ARGS (time), GST_TIME_ARGS (clock->last_time), + GST_TIME_ARGS (time_offset)); +} + +static GstClockTime +gst_audio_clock_func_invalid (GstClock * clock, gpointer user_data) +{ + return GST_CLOCK_TIME_NONE; +} + +static GstClockTime +gst_audio_clock_get_internal_time (GstClock * clock) +{ + GstAudioClock *aclock; + GstClockTime result; + + aclock = GST_AUDIO_CLOCK_CAST (clock); + + result = aclock->func (clock, aclock->user_data); + if (result == GST_CLOCK_TIME_NONE) { + result = aclock->last_time; + } else { + result += aclock->abidata.ABI.time_offset; + /* clock must be increasing */ + if (aclock->last_time < result) + aclock->last_time = result; + else + result = aclock->last_time; + } + + GST_DEBUG_OBJECT (clock, + "result %" GST_TIME_FORMAT ", last_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (result), GST_TIME_ARGS (aclock->last_time)); + + return result; +} + +/** + * gst_audio_clock_get_time: + * @clock: a #GstAudioClock + * + * Report the time as returned by the #GstAudioClockGetTimeFunc without applying + * any offsets. + * + * Returns: the time as reported by the time function of the audio clock + * + * Since: 0.10.23 + */ +GstClockTime +gst_audio_clock_get_time (GstClock * clock) +{ + GstAudioClock *aclock; + GstClockTime result; + + aclock = GST_AUDIO_CLOCK_CAST (clock); + + result = aclock->func (clock, aclock->user_data); + if (result == GST_CLOCK_TIME_NONE) { + GST_DEBUG_OBJECT (clock, "no time, reuse last"); + result = aclock->last_time - aclock->abidata.ABI.time_offset; + } + + GST_DEBUG_OBJECT (clock, + "result %" GST_TIME_FORMAT ", last_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (result), GST_TIME_ARGS (aclock->last_time)); + + return result; +} + +/** + * gst_audio_clock_adjust: + * @clock: a #GstAudioClock + * @time: a #GstClockTime + * + * Adjust @time with the internal offset of the audio clock. + * + * Returns: @time adjusted with the internal offset. + * + * Since: 0.10.23 + */ +GstClockTime +gst_audio_clock_adjust (GstClock * clock, GstClockTime time) +{ + GstAudioClock *aclock; + GstClockTime result; + + aclock = GST_AUDIO_CLOCK_CAST (clock); + + result = time + aclock->abidata.ABI.time_offset; + + return result; +} + +/** + * gst_audio_clock_invalidate: + * @clock: a #GstAudioClock + * + * Invalidate the clock function. Call this function when the provided + * #GstAudioClockGetTimeFunc cannot be called anymore, for example, when the + * user_data becomes invalid. + * + * After calling this function, @clock will return the last returned time for + * the rest of its lifetime. + * + * Since: 0.10.31 + */ +void +gst_audio_clock_invalidate (GstClock * clock) +{ + GstAudioClock *aclock; + + aclock = GST_AUDIO_CLOCK_CAST (clock); + + aclock->func = gst_audio_clock_func_invalid; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.h new file mode 100644 index 0000000..fb50bcf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudioclock.h @@ -0,0 +1,108 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstaudioclock.h: Clock for use by audio plugins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_CLOCK_H__ +#define __GST_AUDIO_CLOCK_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_AUDIO_CLOCK \ + (gst_audio_clock_get_type()) +#define GST_AUDIO_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CLOCK,GstAudioClock)) +#define GST_AUDIO_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_CLOCK,GstAudioClockClass)) +#define GST_IS_AUDIO_CLOCK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CLOCK)) +#define GST_IS_AUDIO_CLOCK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_CLOCK)) +#define GST_AUDIO_CLOCK_CAST(obj) \ + ((GstAudioClock*)(obj)) + +typedef struct _GstAudioClock GstAudioClock; +typedef struct _GstAudioClockClass GstAudioClockClass; + +/** + * GstAudioClockGetTimeFunc: + * @clock: the #GstAudioClock + * @user_data: user data + * + * This function will be called whenever the current clock time needs to be + * calculated. If this function returns #GST_CLOCK_TIME_NONE, the last reported + * time will be returned by the clock. + * + * Returns: the current time or #GST_CLOCK_TIME_NONE if the previous time should + * be used. + */ +typedef GstClockTime (*GstAudioClockGetTimeFunc) (GstClock *clock, gpointer user_data); + +/** + * GstAudioClock: + * @clock: parent #GstSystemClock + * + * Opaque #GstAudioClock. + */ +struct _GstAudioClock { + GstSystemClock clock; + + /* --- protected --- */ + GstAudioClockGetTimeFunc func; + gpointer user_data; + + GstClockTime last_time; + + /*< private >*/ + union { + struct { + GstClockTimeDiff time_offset; + GDestroyNotify destroy_notify; + } ABI; + /* adding + 0 to mark ABI change to be undone later */ + gpointer _gst_reserved[GST_PADDING + 0]; + } abidata; +}; + +struct _GstAudioClockClass { + GstSystemClockClass parent_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_clock_get_type (void); +GstClock* gst_audio_clock_new (const gchar *name, GstAudioClockGetTimeFunc func, + gpointer user_data); +GstClock* gst_audio_clock_new_full (const gchar *name, GstAudioClockGetTimeFunc func, + gpointer user_data, GDestroyNotify destroy_notify); +void gst_audio_clock_reset (GstAudioClock *clock, GstClockTime time); + +GstClockTime gst_audio_clock_get_time (GstClock * clock); +GstClockTime gst_audio_clock_adjust (GstClock * clock, GstClockTime time); + +void gst_audio_clock_invalidate (GstClock * clock); + +G_END_DECLS + +#endif /* __GST_AUDIO_CLOCK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.c new file mode 100644 index 0000000..ca928d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.c @@ -0,0 +1,205 @@ +/* GStreamer audio filter base class + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * Copyright (C) <2007> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudiofilter + * @short_description: Base class for simple audio filters + * + * #GstAudioFilter is a #GstBaseTransform-derived base class for simple audio + * filters, ie. those that output the same format that they get as input. + * + * #GstAudioFilter will parse the input format for you (with error checking) + * before calling your setup function. Also, elements deriving from + * #GstAudioFilter may use gst_audio_filter_class_add_pad_templates() from + * their base_init function to easily configure the set of caps/formats that + * the element is able to handle. + * + * Derived classes should override the #GstAudioFilterClass.setup() and + * #GstBaseTransformClass.transform_ip() and/or + * #GstBaseTransformClass.transform() + * virtual functions in their class_init function. + * + * Last reviewed on 2007-02-03 (0.10.11.1) + * + * Since: 0.10.12 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstaudiofilter.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (audiofilter_dbg); +#define GST_CAT_DEFAULT audiofilter_dbg + +static GstStateChangeReturn gst_audio_filter_change_state (GstElement * element, + GstStateChange transition); +static gboolean gst_audio_filter_set_caps (GstBaseTransform * btrans, + GstCaps * incaps, GstCaps * outcaps); +static gboolean gst_audio_filter_get_unit_size (GstBaseTransform * btrans, + GstCaps * caps, guint * size); + +#define do_init G_STMT_START { \ + GST_DEBUG_CATEGORY_INIT (audiofilter_dbg, "audiofilter", 0, "audiofilter"); \ +} G_STMT_END + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstAudioFilter, gst_audio_filter, + GST_TYPE_BASE_TRANSFORM, do_init); + +static void +gst_audio_filter_class_init (GstAudioFilterClass * klass) +{ + GstBaseTransformClass *basetrans_class = (GstBaseTransformClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_audio_filter_change_state); + basetrans_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_filter_set_caps); + basetrans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_audio_filter_get_unit_size); + + /* FIXME: Ref the GstRingerBuffer class to get it's debug category + * initialized. gst_ring_buffer_parse_caps () which we use later + * uses this debug category. + */ + g_type_class_ref (GST_TYPE_RING_BUFFER); +} + +static void +gst_audio_filter_init (GstAudioFilter * self) +{ + /* nothing to do here */ +} + +/* we override the state change vfunc here instead of GstBaseTransform's stop + * vfunc, so GstAudioFilter-derived elements can override ::stop() for their + * own purposes without having to worry about chaining up */ +static GstStateChangeReturn +gst_audio_filter_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstAudioFilter *filter = GST_AUDIO_FILTER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + memset (&filter->format, 0, sizeof (GstRingBufferSpec)); + /* to make gst_buffer_spec_parse_caps() happy */ + filter->format.latency_time = GST_SECOND; + break; + default: + break; + } + + ret = + GST_ELEMENT_CLASS (gst_audio_filter_parent_class)->change_state (element, + transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + gst_caps_replace (&filter->format.caps, NULL); + break; + default: + break; + } + + return ret; +} + +static gboolean +gst_audio_filter_set_caps (GstBaseTransform * btrans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstAudioFilterClass *klass; + GstAudioFilter *filter = GST_AUDIO_FILTER (btrans); + gboolean ret = TRUE; + + GST_LOG_OBJECT (filter, "caps: %" GST_PTR_FORMAT, incaps); + + if (!gst_ring_buffer_parse_caps (&filter->format, incaps)) { + GST_WARNING_OBJECT (filter, "couldn't parse %" GST_PTR_FORMAT, incaps); + return FALSE; + } + + klass = GST_AUDIO_FILTER_CLASS_CAST (G_OBJECT_GET_CLASS (filter)); + + if (klass->setup) + ret = klass->setup (filter, &filter->format); + + return ret; +} + +static gboolean +gst_audio_filter_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) +{ + GstStructure *structure; + gboolean ret = TRUE; + gint width, channels; + + structure = gst_caps_get_structure (caps, 0); + + ret &= gst_structure_get_int (structure, "width", &width); + ret &= gst_structure_get_int (structure, "channels", &channels); + + if (ret) + *size = (width / 8) * channels; + + return ret; +} + +/** + * gst_audio_filter_class_add_pad_templates: + * @klass: an #GstAudioFilterClass + * @allowed_caps: what formats the filter can handle, as #GstCaps + * + * Convenience function to add pad templates to this element class, with + * @allowed_caps as the caps that can be handled. + * + * This function is usually used from within a GObject base_init function. + * + * Since: 0.10.12 + */ +void +gst_audio_filter_class_add_pad_templates (GstAudioFilterClass * klass, + const GstCaps * allowed_caps) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GstPadTemplate *pad_template; + + g_return_if_fail (GST_IS_AUDIO_FILTER_CLASS (klass)); + g_return_if_fail (GST_IS_CAPS (allowed_caps)); + + pad_template = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + gst_caps_copy (allowed_caps)); + gst_element_class_add_pad_template (element_class, pad_template); + gst_object_unref (pad_template); + + pad_template = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + gst_caps_copy (allowed_caps)); + gst_element_class_add_pad_template (element_class, pad_template); + gst_object_unref (pad_template); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.h new file mode 100644 index 0000000..c311c97 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiofilter.h @@ -0,0 +1,96 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_AUDIO_FILTER_H__ +#define __GST_AUDIO_FILTER_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstAudioFilter GstAudioFilter; +typedef struct _GstAudioFilterClass GstAudioFilterClass; + +#define GST_TYPE_AUDIO_FILTER \ + (gst_audio_filter_get_type()) +#define GST_AUDIO_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_FILTER,GstAudioFilter)) +#define GST_AUDIO_FILTER_CAST(obj) \ + ((GstAudioFilter *) (obj)) +#define GST_AUDIO_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_FILTER,GstAudioFilterClass)) +#define GST_AUDIO_FILTER_CLASS_CAST(klass) \ + ((GstAudioFilterClass *) (klass)) +#define GST_IS_AUDIO_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_FILTER)) +#define GST_IS_AUDIO_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_FILTER)) + +/** + * GstAudioFilter: + * @basetransform: Element parent class + * + * Base class for audio filters with the same format for input and output. + * + * Since: 0.10.12 + */ +struct _GstAudioFilter { + GstBaseTransform basetransform; + + /*< protected >*/ + GstRingBufferSpec format; /* currently configured format */ + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstAudioFilterClass: + * @basetransformclass: parent class + * @setup: virtual function called whenever the format changes + * + * In addition to the @setup virtual function, you should also override the + * GstBaseTransform::transform and/or GstBaseTransform::transform_ip virtual + * function. + * + * Since: 0.10.12 + */ + +struct _GstAudioFilterClass { + GstBaseTransformClass basetransformclass; + + /* virtual function, called whenever the format changes */ + gboolean (*setup) (GstAudioFilter * filter, GstRingBufferSpec * format); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_filter_get_type (void); + +void gst_audio_filter_class_add_pad_templates (GstAudioFilterClass * klass, + const GstCaps * allowed_caps); + +G_END_DECLS + +#endif /* __GST_AUDIO_FILTER_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.c new file mode 100644 index 0000000..ce919af --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.c @@ -0,0 +1,619 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstaudiosink.c: simple audio sink base class + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudiosink + * @short_description: Simple base class for audio sinks + * @see_also: #GstBaseAudioSink, #GstRingBuffer, #GstAudioSink. + * + * This is the most simple base class for audio sinks that only requires + * subclasses to implement a set of simple functions: + * + * + * + * open() + * Open the device. + * + * + * prepare() + * Configure the device with the specified format. + * + * + * write() + * Write samples to the device. + * + * + * reset() + * Unblock writes and flush the device. + * + * + * delay() + * Get the number of samples written but not yet played + * by the device. + * + * + * unprepare() + * Undo operations done by prepare. + * + * + * close() + * Close the device. + * + * + * + * All scheduling of samples and timestamps is done in this base class + * together with #GstBaseAudioSink using a default implementation of a + * #GstRingBuffer that uses threads. + * + * Last reviewed on 2006-09-27 (0.10.12) + */ + +#include + +#include "gstaudiosink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_audio_sink_debug); +#define GST_CAT_DEFAULT gst_audio_sink_debug + +#define GST_TYPE_AUDIORING_BUFFER \ + (gst_audioringbuffer_get_type()) +#define GST_AUDIORING_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer)) +#define GST_AUDIORING_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass)) +#define GST_AUDIORING_BUFFER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass)) +#define GST_AUDIORING_BUFFER_CAST(obj) \ + ((GstAudioRingBuffer *)obj) +#define GST_IS_AUDIORING_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER)) +#define GST_IS_AUDIORING_BUFFER_CLASS(klass)\ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER)) + +typedef struct _GstAudioRingBuffer GstAudioRingBuffer; +typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass; + +#define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond) +#define GST_AUDIORING_BUFFER_WAIT(buf) (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf))) +#define GST_AUDIORING_BUFFER_SIGNAL(buf) (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf))) +#define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf))) + +struct _GstAudioRingBuffer +{ + GstRingBuffer object; + + gboolean running; + gint queuedseg; + + GCond *cond; +}; + +struct _GstAudioRingBufferClass +{ + GstRingBufferClass parent_class; +}; + +static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass); +static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer, + GstAudioRingBufferClass * klass); +static void gst_audioringbuffer_dispose (GObject * object); +static void gst_audioringbuffer_finalize (GObject * object); + +static GstRingBufferClass *ring_parent_class = NULL; + +static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf, + GstRingBufferSpec * spec); +static gboolean gst_audioringbuffer_release (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_start (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_pause (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf); +static guint gst_audioringbuffer_delay (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_activate (GstRingBuffer * buf, + gboolean active); + +/* ringbuffer abstract base class */ +static GType +gst_audioringbuffer_get_type (void) +{ + static GType ringbuffer_type = 0; + + if (!ringbuffer_type) { + static const GTypeInfo ringbuffer_info = { + sizeof (GstAudioRingBufferClass), + NULL, + NULL, + (GClassInitFunc) gst_audioringbuffer_class_init, + NULL, + NULL, + sizeof (GstAudioRingBuffer), + 0, + (GInstanceInitFunc) gst_audioringbuffer_init, + NULL + }; + + ringbuffer_type = + g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSinkRingBuffer", + &ringbuffer_info, 0); + } + return ringbuffer_type; +} + +static void +gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass) +{ + GObjectClass *gobject_class; + GstRingBufferClass *gstringbuffer_class; + + gobject_class = (GObjectClass *) klass; + gstringbuffer_class = (GstRingBufferClass *) klass; + + ring_parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_audioringbuffer_dispose; + gobject_class->finalize = gst_audioringbuffer_finalize; + + gstringbuffer_class->open_device = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device); + gstringbuffer_class->close_device = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device); + gstringbuffer_class->acquire = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire); + gstringbuffer_class->release = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_release); + gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); + gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_audioringbuffer_pause); + gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); + gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop); + + gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay); + gstringbuffer_class->activate = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_activate); +} + +typedef guint (*WriteFunc) (GstAudioSink * sink, gpointer data, guint length); + +/* this internal thread does nothing else but write samples to the audio device. + * It will write each segment in the ringbuffer and will update the play + * pointer. + * The start/stop methods control the thread. + */ +static void +audioringbuffer_thread_func (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER_CAST (buf); + WriteFunc writefunc; + GstMessage *message; + GValue val = { 0 }; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + GST_DEBUG_OBJECT (sink, "enter thread"); + + GST_OBJECT_LOCK (abuf); + GST_DEBUG_OBJECT (sink, "signal wait"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + GST_OBJECT_UNLOCK (abuf); + + writefunc = csink->write; + if (writefunc == NULL) + goto no_function; + + g_value_init (&val, G_TYPE_POINTER); + g_value_set_pointer (&val, sink->thread); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), + GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (sink)); + gst_message_set_stream_status_object (message, &val); + GST_DEBUG_OBJECT (sink, "posting ENTER stream status"); + gst_element_post_message (GST_ELEMENT_CAST (sink), message); + + while (TRUE) { + gint left, len; + guint8 *readptr; + gint readseg; + + /* buffer must be started */ + if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) { + gint written; + + left = len; + do { + written = writefunc (sink, readptr, left); + GST_LOG_OBJECT (sink, "transfered %d bytes of %d from segment %d", + written, left, readseg); + if (written < 0 || written > left) { + /* might not be critical, it e.g. happens when aborting playback */ + GST_WARNING_OBJECT (sink, + "error writing data in %s (reason: %s), skipping segment (left: %d, written: %d)", + GST_DEBUG_FUNCPTR_NAME (writefunc), + (errno > 1 ? g_strerror (errno) : "unknown"), left, written); + break; + } + left -= written; + readptr += written; + } while (left > 0); + + /* clear written samples */ + gst_ring_buffer_clear (buf, readseg); + + /* we wrote one segment */ + gst_ring_buffer_advance (buf, 1); + } else { + GST_OBJECT_LOCK (abuf); + if (!abuf->running) + goto stop_running; + GST_DEBUG_OBJECT (sink, "signal wait"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + GST_DEBUG_OBJECT (sink, "wait for action"); + GST_AUDIORING_BUFFER_WAIT (buf); + GST_DEBUG_OBJECT (sink, "got signal"); + if (!abuf->running) + goto stop_running; + GST_DEBUG_OBJECT (sink, "continue running"); + GST_OBJECT_UNLOCK (abuf); + } + } + + /* Will never be reached */ + g_assert_not_reached (); + return; + + /* ERROR */ +no_function: + { + GST_DEBUG_OBJECT (sink, "no write function, exit thread"); + return; + } +stop_running: + { + GST_OBJECT_UNLOCK (abuf); + GST_DEBUG_OBJECT (sink, "stop running, exit thread"); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), + GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (sink)); + gst_message_set_stream_status_object (message, &val); + GST_DEBUG_OBJECT (sink, "posting LEAVE stream status"); + gst_element_post_message (GST_ELEMENT_CAST (sink), message); + return; + } +} + +static void +gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer, + GstAudioRingBufferClass * g_class) +{ + ringbuffer->running = FALSE; + ringbuffer->queuedseg = 0; + + ringbuffer->cond = g_cond_new (); +} + +static void +gst_audioringbuffer_dispose (GObject * object) +{ + G_OBJECT_CLASS (ring_parent_class)->dispose (object); +} + +static void +gst_audioringbuffer_finalize (GObject * object) +{ + GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER_CAST (object); + + g_cond_free (ringbuffer->cond); + + G_OBJECT_CLASS (ring_parent_class)->finalize (object); +} + +static gboolean +gst_audioringbuffer_open_device (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + gboolean result = TRUE; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + if (csink->open) + result = csink->open (sink); + + if (!result) + goto could_not_open; + + return result; + +could_not_open: + { + GST_DEBUG_OBJECT (sink, "could not open device"); + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_close_device (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + gboolean result = TRUE; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + if (csink->close) + result = csink->close (sink); + + if (!result) + goto could_not_close; + + return result; + +could_not_close: + { + GST_DEBUG_OBJECT (sink, "could not close device"); + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + gboolean result = FALSE; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + if (csink->prepare) + result = csink->prepare (sink, spec); + if (!result) + goto could_not_prepare; + + /* set latency to one more segment as we need some headroom */ + spec->seglatency = spec->segtotal + 1; + + buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); + memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); + + return TRUE; + + /* ERRORS */ +could_not_prepare: + { + GST_DEBUG_OBJECT (sink, "could not prepare device"); + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_activate (GstRingBuffer * buf, gboolean active) +{ + GstAudioSink *sink; + GstAudioRingBuffer *abuf; + GError *error = NULL; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + abuf = GST_AUDIORING_BUFFER_CAST (buf); + + if (active) { + abuf->running = TRUE; + + GST_DEBUG_OBJECT (sink, "starting thread"); + sink->thread = + g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE, + &error); + if (!sink->thread || error != NULL) + goto thread_failed; + + GST_DEBUG_OBJECT (sink, "waiting for thread"); + /* the object lock is taken */ + GST_AUDIORING_BUFFER_WAIT (buf); + GST_DEBUG_OBJECT (sink, "thread is started"); + } else { + abuf->running = FALSE; + GST_DEBUG_OBJECT (sink, "signal wait"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + + GST_OBJECT_UNLOCK (buf); + + /* join the thread */ + g_thread_join (sink->thread); + + GST_OBJECT_LOCK (buf); + } + return TRUE; + + /* ERRORS */ +thread_failed: + { + if (error) + GST_ERROR_OBJECT (sink, "could not create thread %s", error->message); + else + GST_ERROR_OBJECT (sink, "could not create thread for unknown reason"); + return FALSE; + } +} + +/* function is called with LOCK */ +static gboolean +gst_audioringbuffer_release (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + gboolean result = FALSE; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + /* free the buffer */ + gst_buffer_unref (buf->data); + buf->data = NULL; + + if (csink->unprepare) + result = csink->unprepare (sink); + + if (!result) + goto could_not_unprepare; + + GST_DEBUG_OBJECT (sink, "unprepared"); + + return result; + +could_not_unprepare: + { + GST_DEBUG_OBJECT (sink, "could not unprepare device"); + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_start (GstRingBuffer * buf) +{ + GstAudioSink *sink; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + + GST_DEBUG_OBJECT (sink, "start, sending signal"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + + return TRUE; +} + +static gboolean +gst_audioringbuffer_pause (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + /* unblock any pending writes to the audio device */ + if (csink->reset) { + GST_DEBUG_OBJECT (sink, "reset..."); + csink->reset (sink); + GST_DEBUG_OBJECT (sink, "reset done"); + } + + return TRUE; +} + +static gboolean +gst_audioringbuffer_stop (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + /* unblock any pending writes to the audio device */ + if (csink->reset) { + GST_DEBUG_OBJECT (sink, "reset..."); + csink->reset (sink); + GST_DEBUG_OBJECT (sink, "reset done"); + } +#if 0 + if (abuf->running) { + GST_DEBUG_OBJECT (sink, "stop, waiting..."); + GST_AUDIORING_BUFFER_WAIT (buf); + GST_DEBUG_OBJECT (sink, "stopped"); + } +#endif + + return TRUE; +} + +static guint +gst_audioringbuffer_delay (GstRingBuffer * buf) +{ + GstAudioSink *sink; + GstAudioSinkClass *csink; + guint res = 0; + + sink = GST_AUDIO_SINK (GST_OBJECT_PARENT (buf)); + csink = GST_AUDIO_SINK_GET_CLASS (sink); + + if (csink->delay) + res = csink->delay (sink); + + return res; +} + +/* AudioSink signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, +}; + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_audio_sink_debug, "audiosink", 0, "audiosink element"); + +GST_BOILERPLATE_FULL (GstAudioSink, gst_audio_sink, GstBaseAudioSink, + GST_TYPE_BASE_AUDIO_SINK, _do_init); + +static GstRingBuffer *gst_audio_sink_create_ringbuffer (GstBaseAudioSink * + sink); + +static void +gst_audio_sink_base_init (gpointer g_class) +{ +} + +static void +gst_audio_sink_class_init (GstAudioSinkClass * klass) +{ + GstBaseAudioSinkClass *gstbaseaudiosink_class; + + gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass; + + gstbaseaudiosink_class->create_ringbuffer = + GST_DEBUG_FUNCPTR (gst_audio_sink_create_ringbuffer); + + g_type_class_ref (GST_TYPE_AUDIORING_BUFFER); +} + +static void +gst_audio_sink_init (GstAudioSink * audiosink, GstAudioSinkClass * g_class) +{ +} + +static GstRingBuffer * +gst_audio_sink_create_ringbuffer (GstBaseAudioSink * sink) +{ + GstRingBuffer *buffer; + + GST_DEBUG_OBJECT (sink, "creating ringbuffer"); + buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL); + GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer); + + return buffer; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.h new file mode 100644 index 0000000..83a4e95 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosink.h @@ -0,0 +1,102 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstaudiosink.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_SINK_H__ +#define __GST_AUDIO_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_AUDIO_SINK (gst_audio_sink_get_type()) +#define GST_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SINK,GstAudioSink)) +#define GST_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SINK,GstAudioSinkClass)) +#define GST_AUDIO_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AUDIO_SINK,GstAudioSinkClass)) +#define GST_IS_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SINK)) +#define GST_IS_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SINK)) + +typedef struct _GstAudioSink GstAudioSink; +typedef struct _GstAudioSinkClass GstAudioSinkClass; + +/** + * GstAudioSink: + * + * Opaque #GstAudioSink. + */ +struct _GstAudioSink { + GstBaseAudioSink element; + + /*< private >*/ /* with LOCK */ + GThread *thread; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstAudioSinkClass: + * @parent_class: the parent class structure. + * @open: Open the device. No configuration needs to be done at this point. + * This function is also used to check if the device is available. + * @prepare: Prepare the device to operate with the specified parameters. + * @unprepare: Undo operations done in prepare. + * @close: Close the device. + * @write: Write data to the device. + * @delay: Return how many samples are still in the device. This is used to + * drive the synchronisation. + * @reset: Returns as quickly as possible from a write and flush any pending + * samples from the device. + * + * #GstAudioSink class. Override the vmethods to implement functionality. + */ +struct _GstAudioSinkClass { + GstBaseAudioSinkClass parent_class; + + /* vtable */ + + /* open the device with given specs */ + gboolean (*open) (GstAudioSink *sink); + /* prepare resources and state to operate with the given specs */ + gboolean (*prepare) (GstAudioSink *sink, GstRingBufferSpec *spec); + /* undo anything that was done in prepare() */ + gboolean (*unprepare) (GstAudioSink *sink); + /* close the device */ + gboolean (*close) (GstAudioSink *sink); + /* write samples to the device */ + /* FIXME 0.11: change return value to gint, as most implementation use that + * already anyway */ + guint (*write) (GstAudioSink *sink, gpointer data, guint length); + /* get number of samples queued in the device */ + guint (*delay) (GstAudioSink *sink); + /* reset the audio device, unblock from a write */ + void (*reset) (GstAudioSink *sink); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_sink_get_type(void); + +G_END_DECLS + +#endif /* __GST_AUDIO_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.c new file mode 100644 index 0000000..d7a6b54 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.c @@ -0,0 +1,532 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstaudiosrc.c: simple audio src base class + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudiosrc + * @short_description: Simple base class for audio sources + * @see_also: #GstBaseAudioSrc, #GstRingBuffer, #GstAudioSrc. + * + * This is the most simple base class for audio sources that only requires + * subclasses to implement a set of simple functions: + * + * + * + * open() + * Open the device. + * + * + * prepare() + * Configure the device with the specified format. + * + * + * read() + * Read samples from the device. + * + * + * reset() + * Unblock reads and flush the device. + * + * + * delay() + * Get the number of samples in the device but not yet read. + * + * + * + * unprepare() + * Undo operations done by prepare. + * + * + * close() + * Close the device. + * + * + * + * All scheduling of samples and timestamps is done in this base class + * together with #GstBaseAudioSrc using a default implementation of a + * #GstRingBuffer that uses threads. + * + * Last reviewed on 2006-09-27 (0.10.12) + */ + +#include + +#include "gstaudiosrc.h" + +GST_DEBUG_CATEGORY_STATIC (gst_audio_src_debug); +#define GST_CAT_DEFAULT gst_audio_src_debug + +#define GST_TYPE_AUDIORING_BUFFER \ + (gst_audioringbuffer_get_type()) +#define GST_AUDIORING_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBuffer)) +#define GST_AUDIORING_BUFFER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIORING_BUFFER,GstAudioRingBufferClass)) +#define GST_AUDIORING_BUFFER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_AUDIORING_BUFFER, GstAudioRingBufferClass)) +#define GST_IS_AUDIORING_BUFFER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIORING_BUFFER)) +#define GST_IS_AUDIORING_BUFFER_CLASS(klass)\ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIORING_BUFFER)) + +typedef struct _GstAudioRingBuffer GstAudioRingBuffer; +typedef struct _GstAudioRingBufferClass GstAudioRingBufferClass; + +#define GST_AUDIORING_BUFFER_GET_COND(buf) (((GstAudioRingBuffer *)buf)->cond) +#define GST_AUDIORING_BUFFER_WAIT(buf) (g_cond_wait (GST_AUDIORING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf))) +#define GST_AUDIORING_BUFFER_SIGNAL(buf) (g_cond_signal (GST_AUDIORING_BUFFER_GET_COND (buf))) +#define GST_AUDIORING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_AUDIORING_BUFFER_GET_COND (buf))) + +struct _GstAudioRingBuffer +{ + GstRingBuffer object; + + gboolean running; + gint queuedseg; + + GCond *cond; +}; + +struct _GstAudioRingBufferClass +{ + GstRingBufferClass parent_class; +}; + +static void gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass); +static void gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer, + GstAudioRingBufferClass * klass); +static void gst_audioringbuffer_dispose (GObject * object); +static void gst_audioringbuffer_finalize (GObject * object); + +static GstRingBufferClass *ring_parent_class = NULL; + +static gboolean gst_audioringbuffer_open_device (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_close_device (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_acquire (GstRingBuffer * buf, + GstRingBufferSpec * spec); +static gboolean gst_audioringbuffer_release (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_start (GstRingBuffer * buf); +static gboolean gst_audioringbuffer_stop (GstRingBuffer * buf); +static guint gst_audioringbuffer_delay (GstRingBuffer * buf); + +/* ringbuffer abstract base class */ +static GType +gst_audioringbuffer_get_type (void) +{ + static GType ringbuffer_type = 0; + + if (!ringbuffer_type) { + static const GTypeInfo ringbuffer_info = { + sizeof (GstAudioRingBufferClass), + NULL, + NULL, + (GClassInitFunc) gst_audioringbuffer_class_init, + NULL, + NULL, + sizeof (GstAudioRingBuffer), + 0, + (GInstanceInitFunc) gst_audioringbuffer_init, + NULL + }; + + ringbuffer_type = + g_type_register_static (GST_TYPE_RING_BUFFER, "GstAudioSrcRingBuffer", + &ringbuffer_info, 0); + } + return ringbuffer_type; +} + +static void +gst_audioringbuffer_class_init (GstAudioRingBufferClass * klass) +{ + GObjectClass *gobject_class; + GstRingBufferClass *gstringbuffer_class; + + gobject_class = (GObjectClass *) klass; + gstringbuffer_class = (GstRingBufferClass *) klass; + + ring_parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_audioringbuffer_dispose; + gobject_class->finalize = gst_audioringbuffer_finalize; + + gstringbuffer_class->open_device = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_open_device); + gstringbuffer_class->close_device = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_close_device); + gstringbuffer_class->acquire = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_acquire); + gstringbuffer_class->release = + GST_DEBUG_FUNCPTR (gst_audioringbuffer_release); + gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); + gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_audioringbuffer_start); + gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_audioringbuffer_stop); + + gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_audioringbuffer_delay); +} + +typedef guint (*ReadFunc) (GstAudioSrc * src, gpointer data, guint length); + +/* this internal thread does nothing else but read samples from the audio device. + * It will read each segment in the ringbuffer and will update the play + * pointer. + * The start/stop methods control the thread. + */ +static void +audioringbuffer_thread_func (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + GstAudioRingBuffer *abuf = GST_AUDIORING_BUFFER (buf); + ReadFunc readfunc; + GstMessage *message; + GValue val = { 0 }; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + GST_DEBUG_OBJECT (src, "enter thread"); + + readfunc = csrc->read; + if (readfunc == NULL) + goto no_function; + + /* FIXME: maybe we should at least use a custom pointer type here? */ + g_value_init (&val, G_TYPE_POINTER); + g_value_set_pointer (&val, src->thread); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), + GST_STREAM_STATUS_TYPE_ENTER, GST_ELEMENT_CAST (src)); + gst_message_set_stream_status_object (message, &val); + GST_DEBUG_OBJECT (src, "posting ENTER stream status"); + gst_element_post_message (GST_ELEMENT_CAST (src), message); + + while (TRUE) { + gint left, len; + guint8 *readptr; + gint readseg; + + if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) { + gint read; + + left = len; + do { + read = readfunc (src, readptr, left); + GST_LOG_OBJECT (src, "transfered %d bytes of %d to segment %d", read, + left, readseg); + if (read < 0 || read > left) { + GST_WARNING_OBJECT (src, + "error reading data %d (reason: %s), skipping segment", read, + g_strerror (errno)); + break; + } + left -= read; + readptr += read; + } while (left > 0); + + /* we read one segment */ + gst_ring_buffer_advance (buf, 1); + } else { + GST_OBJECT_LOCK (abuf); + if (!abuf->running) + goto stop_running; + GST_DEBUG_OBJECT (src, "signal wait"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + GST_DEBUG_OBJECT (src, "wait for action"); + GST_AUDIORING_BUFFER_WAIT (buf); + GST_DEBUG_OBJECT (src, "got signal"); + if (!abuf->running) + goto stop_running; + GST_DEBUG_OBJECT (src, "continue running"); + GST_OBJECT_UNLOCK (abuf); + } + } + + /* Will never be reached */ + g_assert_not_reached (); + return; + + /* ERROR */ +no_function: + { + GST_DEBUG ("no write function, exit thread"); + return; + } +stop_running: + { + GST_OBJECT_UNLOCK (abuf); + GST_DEBUG ("stop running, exit thread"); + message = gst_message_new_stream_status (GST_OBJECT_CAST (buf), + GST_STREAM_STATUS_TYPE_LEAVE, GST_ELEMENT_CAST (src)); + gst_message_set_stream_status_object (message, &val); + GST_DEBUG_OBJECT (src, "posting LEAVE stream status"); + gst_element_post_message (GST_ELEMENT_CAST (src), message); + return; + } +} + +static void +gst_audioringbuffer_init (GstAudioRingBuffer * ringbuffer, + GstAudioRingBufferClass * g_class) +{ + ringbuffer->running = FALSE; + ringbuffer->queuedseg = 0; + + ringbuffer->cond = g_cond_new (); +} + +static void +gst_audioringbuffer_dispose (GObject * object) +{ + GstAudioRingBuffer *ringbuffer = GST_AUDIORING_BUFFER (object); + + if (ringbuffer->cond) { + g_cond_free (ringbuffer->cond); + ringbuffer->cond = NULL; + } + + G_OBJECT_CLASS (ring_parent_class)->dispose (object); +} + +static void +gst_audioringbuffer_finalize (GObject * object) +{ + G_OBJECT_CLASS (ring_parent_class)->finalize (object); +} + +static gboolean +gst_audioringbuffer_open_device (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + gboolean result = TRUE; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + if (csrc->open) + result = csrc->open (src); + + if (!result) + goto could_not_open; + + return result; + +could_not_open: + { + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_close_device (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + gboolean result = TRUE; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + if (csrc->close) + result = csrc->close (src); + + if (!result) + goto could_not_open; + + return result; + +could_not_open: + { + return FALSE; + } +} + +static gboolean +gst_audioringbuffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + GstAudioRingBuffer *abuf; + gboolean result = FALSE; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + if (csrc->prepare) + result = csrc->prepare (src, spec); + + if (!result) + goto could_not_open; + + buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); + memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); + + abuf = GST_AUDIORING_BUFFER (buf); + abuf->running = TRUE; + + src->thread = + g_thread_create ((GThreadFunc) audioringbuffer_thread_func, buf, TRUE, + NULL); + GST_AUDIORING_BUFFER_WAIT (buf); + + return result; + +could_not_open: + { + return FALSE; + } +} + +/* function is called with LOCK */ +static gboolean +gst_audioringbuffer_release (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + GstAudioRingBuffer *abuf; + gboolean result = FALSE; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + abuf = GST_AUDIORING_BUFFER (buf); + + abuf->running = FALSE; + GST_AUDIORING_BUFFER_SIGNAL (buf); + GST_OBJECT_UNLOCK (buf); + + /* join the thread */ + g_thread_join (src->thread); + + GST_OBJECT_LOCK (buf); + + /* free the buffer */ + gst_buffer_unref (buf->data); + buf->data = NULL; + + if (csrc->unprepare) + result = csrc->unprepare (src); + + return result; +} + +static gboolean +gst_audioringbuffer_start (GstRingBuffer * buf) +{ + GST_DEBUG ("start, sending signal"); + GST_AUDIORING_BUFFER_SIGNAL (buf); + + return TRUE; +} + +static gboolean +gst_audioringbuffer_stop (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + /* unblock any pending writes to the audio device */ + if (csrc->reset) { + GST_DEBUG ("reset..."); + csrc->reset (src); + GST_DEBUG ("reset done"); + } +#if 0 + GST_DEBUG ("stop, waiting..."); + GST_AUDIORING_BUFFER_WAIT (buf); + GST_DEBUG ("stoped"); +#endif + + return TRUE; +} + +static guint +gst_audioringbuffer_delay (GstRingBuffer * buf) +{ + GstAudioSrc *src; + GstAudioSrcClass *csrc; + guint res = 0; + + src = GST_AUDIO_SRC (GST_OBJECT_PARENT (buf)); + csrc = GST_AUDIO_SRC_GET_CLASS (src); + + if (csrc->delay) + res = csrc->delay (src); + + return res; +} + +/* AudioSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, +}; + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_audio_src_debug, "audiosrc", 0, "audiosrc element"); + +GST_BOILERPLATE_FULL (GstAudioSrc, gst_audio_src, GstBaseAudioSrc, + GST_TYPE_BASE_AUDIO_SRC, _do_init); + +static GstRingBuffer *gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src); + +static void +gst_audio_src_base_init (gpointer g_class) +{ +} + +static void +gst_audio_src_class_init (GstAudioSrcClass * klass) +{ + GstBaseAudioSrcClass *gstbaseaudiosrc_class; + + gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass; + + gstbaseaudiosrc_class->create_ringbuffer = + GST_DEBUG_FUNCPTR (gst_audio_src_create_ringbuffer); + + g_type_class_ref (GST_TYPE_AUDIORING_BUFFER); +} + +static void +gst_audio_src_init (GstAudioSrc * audiosrc, GstAudioSrcClass * g_class) +{ +} + +static GstRingBuffer * +gst_audio_src_create_ringbuffer (GstBaseAudioSrc * src) +{ + GstRingBuffer *buffer; + + GST_DEBUG ("creating ringbuffer"); + buffer = g_object_new (GST_TYPE_AUDIORING_BUFFER, NULL); + GST_DEBUG ("created ringbuffer @%p", buffer); + + return buffer; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.h new file mode 100644 index 0000000..d3b714d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstaudiosrc.h @@ -0,0 +1,99 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstaudiosrc.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_SRC_H__ +#define __GST_AUDIO_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_AUDIO_SRC (gst_audio_src_get_type()) +#define GST_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_SRC,GstAudioSrc)) +#define GST_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_SRC,GstAudioSrcClass)) +#define GST_AUDIO_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_AUDIO_SRC,GstAudioSrcClass)) +#define GST_IS_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_SRC)) +#define GST_IS_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_SRC)) + +typedef struct _GstAudioSrc GstAudioSrc; +typedef struct _GstAudioSrcClass GstAudioSrcClass; + +/** + * GstAudioSrc: + * @element: parent class + * + * Base class for simple audio sources. + */ +struct _GstAudioSrc { + GstBaseAudioSrc element; + + /*< private >*/ /* with LOCK */ + GThread *thread; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstAudioSrcClass: + * @parent_class: the parent class. + * @open: open the device with the specified caps + * @prepare: configure device with format + * @unprepare: undo the configuration + * @close: close the device + * @read: read samples to the audio device + * @delay: the number of samples queued in the device + * @reset: unblock a read to the device and reset. + * + * #GstAudioSrc class. Override the vmethod to implement + * functionality. + */ +struct _GstAudioSrcClass { + GstBaseAudioSrcClass parent_class; + + /* vtable */ + + /* open the device with given specs */ + gboolean (*open) (GstAudioSrc *src); + /* prepare resources and state to operate with the given specs */ + gboolean (*prepare) (GstAudioSrc *src, GstRingBufferSpec *spec); + /* undo anything that was done in prepare() */ + gboolean (*unprepare) (GstAudioSrc *src); + /* close the device */ + gboolean (*close) (GstAudioSrc *src); + /* read samples from the device */ + guint (*read) (GstAudioSrc *src, gpointer data, guint length); + /* get number of samples queued in the device */ + guint (*delay) (GstAudioSrc *src); + /* reset the audio device, unblock from a write */ + void (*reset) (GstAudioSrc *src); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_src_get_type(void); + +G_END_DECLS + +#endif /* __GST_AUDIO_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.c new file mode 100644 index 0000000..6093092 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.c @@ -0,0 +1,2015 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbaseaudiosink.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstbaseaudiosink + * @short_description: Base class for audio sinks + * @see_also: #GstAudioSink, #GstRingBuffer. + * + * This is the base class for audio sinks. Subclasses need to implement the + * ::create_ringbuffer vmethod. This base class will then take care of + * writing samples to the ringbuffer, synchronisation, clipping and flushing. + * + * Last reviewed on 2006-09-27 (0.10.12) + */ + +#include + +#include "gstbaseaudiosink.h" + +GST_DEBUG_CATEGORY_STATIC (gst_base_audio_sink_debug); +#define GST_CAT_DEFAULT gst_base_audio_sink_debug + +#define GST_BASE_AUDIO_SINK_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SINK, GstBaseAudioSinkPrivate)) + +struct _GstBaseAudioSinkPrivate +{ + /* upstream latency */ + GstClockTime us_latency; + /* the clock slaving algorithm in use */ + GstBaseAudioSinkSlaveMethod slave_method; + /* running average of clock skew */ + GstClockTimeDiff avg_skew; + /* the number of samples we aligned last time */ + gint64 last_align; + + gboolean sync_latency; + + GstClockTime eos_time; + + gboolean do_time_offset; + /* number of microseconds we alow timestamps or clock slaving to drift + * before resyncing */ + guint64 drift_tolerance; +}; + +/* BaseAudioSink signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +/* FIXME: 0.11, store the buffer_time and latency_time in nanoseconds */ +#define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND) +#define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND) +#define DEFAULT_PROVIDE_CLOCK TRUE +#define DEFAULT_SLAVE_METHOD GST_BASE_AUDIO_SINK_SLAVE_SKEW + +/* FIXME, enable pull mode when clock slaving and trick modes are figured out */ +#define DEFAULT_CAN_ACTIVATE_PULL FALSE + +/* when timestamps or clock slaving drift for more than 40ms we resync. This is + * a reasonable default */ +#define DEFAULT_DRIFT_TOLERANCE ((40 * GST_MSECOND) / GST_USECOND) + +enum +{ + PROP_0, + + PROP_BUFFER_TIME, + PROP_LATENCY_TIME, + PROP_PROVIDE_CLOCK, + PROP_SLAVE_METHOD, + PROP_CAN_ACTIVATE_PULL, + PROP_DRIFT_TOLERANCE, + + PROP_LAST +}; + +GType +gst_base_audio_sink_slave_method_get_type (void) +{ + static volatile gsize slave_method_type = 0; + static const GEnumValue slave_method[] = { + {GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE, "GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE", + "resample"}, + {GST_BASE_AUDIO_SINK_SLAVE_SKEW, "GST_BASE_AUDIO_SINK_SLAVE_SKEW", "skew"}, + {GST_BASE_AUDIO_SINK_SLAVE_NONE, "GST_BASE_AUDIO_SINK_SLAVE_NONE", "none"}, + {0, NULL, NULL}, + }; + + if (g_once_init_enter (&slave_method_type)) { + GType tmp = + g_enum_register_static ("GstBaseAudioSinkSlaveMethod", slave_method); + g_once_init_leave (&slave_method_type, tmp); + } + + return (GType) slave_method_type; +} + + +#define _do_init(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_base_audio_sink_debug, "baseaudiosink", 0, "baseaudiosink element"); + +GST_BOILERPLATE_FULL (GstBaseAudioSink, gst_base_audio_sink, GstBaseSink, + GST_TYPE_BASE_SINK, _do_init); + +static void gst_base_audio_sink_dispose (GObject * object); + +static void gst_base_audio_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_audio_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_base_audio_sink_async_play (GstBaseSink * + basesink); +static GstStateChangeReturn gst_base_audio_sink_change_state (GstElement * + element, GstStateChange transition); +static gboolean gst_base_audio_sink_activate_pull (GstBaseSink * basesink, + gboolean active); +static gboolean gst_base_audio_sink_query (GstElement * element, GstQuery * + query); + +static GstClock *gst_base_audio_sink_provide_clock (GstElement * elem); +static GstClockTime gst_base_audio_sink_get_time (GstClock * clock, + GstBaseAudioSink * sink); +static void gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, + guint len, gpointer user_data); + +static GstFlowReturn gst_base_audio_sink_preroll (GstBaseSink * bsink, + GstBuffer * buffer); +static GstFlowReturn gst_base_audio_sink_render (GstBaseSink * bsink, + GstBuffer * buffer); +static gboolean gst_base_audio_sink_event (GstBaseSink * bsink, + GstEvent * event); +static void gst_base_audio_sink_get_times (GstBaseSink * bsink, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_base_audio_sink_setcaps (GstBaseSink * bsink, + GstCaps * caps); +static void gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps); + +static gboolean gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query); + + +/* static guint gst_base_audio_sink_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_base_audio_sink_base_init (gpointer g_class) +{ +} + +static void +gst_base_audio_sink_class_init (GstBaseAudioSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + + g_type_class_add_private (klass, sizeof (GstBaseAudioSinkPrivate)); + + gobject_class->set_property = gst_base_audio_sink_set_property; + gobject_class->get_property = gst_base_audio_sink_get_property; + gobject_class->dispose = gst_base_audio_sink_dispose; + + g_object_class_install_property (gobject_class, PROP_BUFFER_TIME, + g_param_spec_int64 ("buffer-time", "Buffer Time", + "Size of audio buffer in microseconds", 1, + G_MAXINT64, DEFAULT_BUFFER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LATENCY_TIME, + g_param_spec_int64 ("latency-time", "Latency Time", + "Audio latency in microseconds", 1, + G_MAXINT64, DEFAULT_LATENCY_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK, + g_param_spec_boolean ("provide-clock", "Provide Clock", + "Provide a clock to be used as the global pipeline clock", + DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD, + g_param_spec_enum ("slave-method", "Slave Method", + "Algorithm to use to match the rate of the masterclock", + GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL, + g_param_spec_boolean ("can-activate-pull", "Allow Pull Scheduling", + "Allow pull-based scheduling", DEFAULT_CAN_ACTIVATE_PULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseAudioSink:drift-tolerance + * + * Controls the amount of time in milliseconds that timestamps or clocks are allowed + * to drift before resynchronisation happens. + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_class, PROP_DRIFT_TOLERANCE, + g_param_spec_int64 ("drift-tolerance", "Drift Tolerance", + "Tolerance for timestamp and clock drift in microseconds", 1, + G_MAXINT64, DEFAULT_DRIFT_TOLERANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_change_state); + gstelement_class->provide_clock = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_provide_clock); + gstelement_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_sink_query); + + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_sink_event); + gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_base_audio_sink_preroll); + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_base_audio_sink_render); + gstbasesink_class->get_times = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_get_times); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_sink_setcaps); + gstbasesink_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_sink_fixate); + gstbasesink_class->async_play = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_async_play); + gstbasesink_class->activate_pull = + GST_DEBUG_FUNCPTR (gst_base_audio_sink_activate_pull); + + /* ref class from a thread-safe context to work around missing bit of + * thread-safety in GObject */ + g_type_class_ref (GST_TYPE_AUDIO_CLOCK); + g_type_class_ref (GST_TYPE_RING_BUFFER); + +} + +static void +gst_base_audio_sink_init (GstBaseAudioSink * baseaudiosink, + GstBaseAudioSinkClass * g_class) +{ + GstPluginFeature *feature; + GstBaseSink *basesink; + + baseaudiosink->priv = GST_BASE_AUDIO_SINK_GET_PRIVATE (baseaudiosink); + + baseaudiosink->buffer_time = DEFAULT_BUFFER_TIME; + baseaudiosink->latency_time = DEFAULT_LATENCY_TIME; + baseaudiosink->provide_clock = DEFAULT_PROVIDE_CLOCK; + baseaudiosink->priv->slave_method = DEFAULT_SLAVE_METHOD; + baseaudiosink->priv->drift_tolerance = DEFAULT_DRIFT_TOLERANCE; + + baseaudiosink->provided_clock = gst_audio_clock_new ("GstAudioSinkClock", + (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time, baseaudiosink); + + basesink = GST_BASE_SINK_CAST (baseaudiosink); + basesink->can_activate_push = TRUE; + basesink->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; + + gst_base_sink_set_last_buffer_enabled (basesink, FALSE); + + /* install some custom pad_query functions */ + gst_pad_set_query_function (GST_BASE_SINK_PAD (baseaudiosink), + GST_DEBUG_FUNCPTR (gst_base_audio_sink_query_pad)); + + baseaudiosink->priv->do_time_offset = TRUE; + + /* check the factory, pulsesink < 0.10.17 does the timestamp offset itself so + * we should not do ourselves */ + feature = + GST_PLUGIN_FEATURE_CAST (GST_ELEMENT_CLASS (g_class)->elementfactory); + GST_DEBUG ("created from factory %p", feature); + + /* HACK for old pulsesink that did the time_offset themselves */ + if (feature) { + if (strcmp (gst_plugin_feature_get_name (feature), "pulsesink") == 0) { + if (!gst_plugin_feature_check_version (feature, 0, 10, 17)) { + /* we're dealing with an old pulsesink, we need to disable time corection */ + GST_DEBUG ("disable time offset"); + baseaudiosink->priv->do_time_offset = FALSE; + } + } + } +} + +static void +gst_base_audio_sink_dispose (GObject * object) +{ + GstBaseAudioSink *sink; + + sink = GST_BASE_AUDIO_SINK (object); + + if (sink->provided_clock) { + gst_audio_clock_invalidate (sink->provided_clock); + gst_object_unref (sink->provided_clock); + sink->provided_clock = NULL; + } + + if (sink->ringbuffer) { + gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer)); + sink->ringbuffer = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + + +static GstClock * +gst_base_audio_sink_provide_clock (GstElement * elem) +{ + GstBaseAudioSink *sink; + GstClock *clock; + + sink = GST_BASE_AUDIO_SINK (elem); + + /* we have no ringbuffer (must be NULL state) */ + if (sink->ringbuffer == NULL) + goto wrong_state; + + if (!gst_ring_buffer_is_acquired (sink->ringbuffer)) + goto wrong_state; + + GST_OBJECT_LOCK (sink); + if (!sink->provide_clock) + goto clock_disabled; + + clock = GST_CLOCK_CAST (gst_object_ref (sink->provided_clock)); + GST_OBJECT_UNLOCK (sink); + + return clock; + + /* ERRORS */ +wrong_state: + { + GST_DEBUG_OBJECT (sink, "ringbuffer not acquired"); + return NULL; + } +clock_disabled: + { + GST_DEBUG_OBJECT (sink, "clock provide disabled"); + GST_OBJECT_UNLOCK (sink); + return NULL; + } +} + +static gboolean +gst_base_audio_sink_query_pad (GstPad * pad, GstQuery * query) +{ + gboolean res = FALSE; + GstBaseAudioSink *basesink; + + basesink = GST_BASE_AUDIO_SINK (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + GST_LOG_OBJECT (pad, "query convert"); + + if (basesink->ringbuffer) { + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL); + res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val, + dest_fmt, &dest_val); + if (res) { + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + } + } + break; + } + default: + break; + } + + gst_object_unref (basesink); + + return res; +} + +static gboolean +gst_base_audio_sink_query (GstElement * element, GstQuery * query) +{ + gboolean res = FALSE; + GstBaseAudioSink *basesink; + + basesink = GST_BASE_AUDIO_SINK (element); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + gboolean live, us_live; + GstClockTime min_l, max_l; + + GST_DEBUG_OBJECT (basesink, "latency query"); + + /* ask parent first, it will do an upstream query for us. */ + if ((res = + gst_base_sink_query_latency (GST_BASE_SINK_CAST (basesink), &live, + &us_live, &min_l, &max_l))) { + GstClockTime min_latency, max_latency; + + /* we and upstream are both live, adjust the min_latency */ + if (live && us_live) { + GstRingBufferSpec *spec; + + GST_OBJECT_LOCK (basesink); + if (!basesink->ringbuffer || !basesink->ringbuffer->spec.rate) { + GST_OBJECT_UNLOCK (basesink); + + GST_DEBUG_OBJECT (basesink, + "we are not yet negotiated, can't report latency yet"); + res = FALSE; + goto done; + } + spec = &basesink->ringbuffer->spec; + + basesink->priv->us_latency = min_l; + + min_latency = + gst_util_uint64_scale_int (spec->seglatency * spec->segsize, + GST_SECOND, spec->rate * spec->bytes_per_sample); + GST_OBJECT_UNLOCK (basesink); + + /* we cannot go lower than the buffer size and the min peer latency */ + min_latency = min_latency + min_l; + /* the max latency is the max of the peer, we can delay an infinite + * amount of time. */ + max_latency = min_latency + (max_l == -1 ? 0 : max_l); + + GST_DEBUG_OBJECT (basesink, + "peer min %" GST_TIME_FORMAT ", our min latency: %" + GST_TIME_FORMAT, GST_TIME_ARGS (min_l), + GST_TIME_ARGS (min_latency)); + } else { + GST_DEBUG_OBJECT (basesink, + "peer or we are not live, don't care about latency"); + min_latency = min_l; + max_latency = max_l; + } + gst_query_set_latency (query, live, min_latency, max_latency); + } + break; + } + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + GST_LOG_OBJECT (basesink, "query convert"); + + if (basesink->ringbuffer) { + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, NULL); + res = gst_ring_buffer_convert (basesink->ringbuffer, src_fmt, src_val, + dest_fmt, &dest_val); + if (res) { + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + } + } + break; + } + default: + res = GST_ELEMENT_CLASS (parent_class)->query (element, query); + break; + } + +done: + return res; +} + + +static GstClockTime +gst_base_audio_sink_get_time (GstClock * clock, GstBaseAudioSink * sink) +{ + guint64 raw, samples; + guint delay; + GstClockTime result; + + if (sink->ringbuffer == NULL || sink->ringbuffer->spec.rate == 0) + return GST_CLOCK_TIME_NONE; + + /* our processed samples are always increasing */ + raw = samples = gst_ring_buffer_samples_done (sink->ringbuffer); + + /* the number of samples not yet processed, this is still queued in the + * device (not played for playback). */ + delay = gst_ring_buffer_delay (sink->ringbuffer); + + if (G_LIKELY (samples >= delay)) + samples -= delay; + else + samples = 0; + + result = gst_util_uint64_scale_int (samples, GST_SECOND, + sink->ringbuffer->spec.rate); + + GST_DEBUG_OBJECT (sink, + "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %" + G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, + raw, delay, samples, GST_TIME_ARGS (result)); + + return result; +} + +/** + * gst_base_audio_sink_set_provide_clock: + * @sink: a #GstBaseAudioSink + * @provide: new state + * + * Controls whether @sink will provide a clock or not. If @provide is %TRUE, + * gst_element_provide_clock() will return a clock that reflects the datarate + * of @sink. If @provide is %FALSE, gst_element_provide_clock() will return NULL. + * + * Since: 0.10.16 + */ +void +gst_base_audio_sink_set_provide_clock (GstBaseAudioSink * sink, + gboolean provide) +{ + g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->provide_clock = provide; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_audio_sink_get_provide_clock: + * @sink: a #GstBaseAudioSink + * + * Queries whether @sink will provide a clock or not. See also + * gst_base_audio_sink_set_provide_clock. + * + * Returns: %TRUE if @sink will provide a clock. + * + * Since: 0.10.16 + */ +gboolean +gst_base_audio_sink_get_provide_clock (GstBaseAudioSink * sink) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), FALSE); + + GST_OBJECT_LOCK (sink); + result = sink->provide_clock; + GST_OBJECT_UNLOCK (sink); + + return result; +} + +/** + * gst_base_audio_sink_set_slave_method: + * @sink: a #GstBaseAudioSink + * @method: the new slave method + * + * Controls how clock slaving will be performed in @sink. + * + * Since: 0.10.16 + */ +void +gst_base_audio_sink_set_slave_method (GstBaseAudioSink * sink, + GstBaseAudioSinkSlaveMethod method) +{ + g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->slave_method = method; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_audio_sink_get_slave_method: + * @sink: a #GstBaseAudioSink + * + * Get the current slave method used by @sink. + * + * Returns: The current slave method used by @sink. + * + * Since: 0.10.16 + */ +GstBaseAudioSinkSlaveMethod +gst_base_audio_sink_get_slave_method (GstBaseAudioSink * sink) +{ + GstBaseAudioSinkSlaveMethod result; + + g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1); + + GST_OBJECT_LOCK (sink); + result = sink->priv->slave_method; + GST_OBJECT_UNLOCK (sink); + + return result; +} + + +/** + * gst_base_audio_sink_set_drift_tolerance: + * @sink: a #GstBaseAudioSink + * @drift_tolerance: the new drift tolerance in microseconds + * + * Controls the sink's drift tolerance. + * + * Since: 0.10.31 + */ +void +gst_base_audio_sink_set_drift_tolerance (GstBaseAudioSink * sink, + gint64 drift_tolerance) +{ + g_return_if_fail (GST_IS_BASE_AUDIO_SINK (sink)); + + GST_OBJECT_LOCK (sink); + sink->priv->drift_tolerance = drift_tolerance; + GST_OBJECT_UNLOCK (sink); +} + +/** + * gst_base_audio_sink_get_drift_tolerance + * @sink: a #GstBaseAudioSink + * + * Get the current drift tolerance, in microseconds, used by @sink. + * + * Returns: The current drift tolerance used by @sink. + * + * Since: 0.10.31 + */ +gint64 +gst_base_audio_sink_get_drift_tolerance (GstBaseAudioSink * sink) +{ + gint64 result; + + g_return_val_if_fail (GST_IS_BASE_AUDIO_SINK (sink), -1); + + GST_OBJECT_LOCK (sink); + result = sink->priv->drift_tolerance; + GST_OBJECT_UNLOCK (sink); + + return result; +} + +static void +gst_base_audio_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseAudioSink *sink; + + sink = GST_BASE_AUDIO_SINK (object); + + switch (prop_id) { + case PROP_BUFFER_TIME: + sink->buffer_time = g_value_get_int64 (value); + break; + case PROP_LATENCY_TIME: + sink->latency_time = g_value_get_int64 (value); + break; + case PROP_PROVIDE_CLOCK: + gst_base_audio_sink_set_provide_clock (sink, g_value_get_boolean (value)); + break; + case PROP_SLAVE_METHOD: + gst_base_audio_sink_set_slave_method (sink, g_value_get_enum (value)); + break; + case PROP_CAN_ACTIVATE_PULL: + GST_BASE_SINK (sink)->can_activate_pull = g_value_get_boolean (value); + break; + case PROP_DRIFT_TOLERANCE: + gst_base_audio_sink_set_drift_tolerance (sink, g_value_get_int64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_audio_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseAudioSink *sink; + + sink = GST_BASE_AUDIO_SINK (object); + + switch (prop_id) { + case PROP_BUFFER_TIME: + g_value_set_int64 (value, sink->buffer_time); + break; + case PROP_LATENCY_TIME: + g_value_set_int64 (value, sink->latency_time); + break; + case PROP_PROVIDE_CLOCK: + g_value_set_boolean (value, gst_base_audio_sink_get_provide_clock (sink)); + break; + case PROP_SLAVE_METHOD: + g_value_set_enum (value, gst_base_audio_sink_get_slave_method (sink)); + break; + case PROP_CAN_ACTIVATE_PULL: + g_value_set_boolean (value, GST_BASE_SINK (sink)->can_activate_pull); + break; + case PROP_DRIFT_TOLERANCE: + g_value_set_int64 (value, gst_base_audio_sink_get_drift_tolerance (sink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +gst_base_audio_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) +{ + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink); + GstRingBufferSpec *spec; + GstClockTime now; + + if (!sink->ringbuffer) + return FALSE; + + spec = &sink->ringbuffer->spec; + + GST_DEBUG_OBJECT (sink, "release old ringbuffer"); + + /* get current time, updates the last_time */ + now = gst_clock_get_time (sink->provided_clock); + + GST_DEBUG_OBJECT (sink, "time was %" GST_TIME_FORMAT, GST_TIME_ARGS (now)); + + /* release old ringbuffer */ + gst_ring_buffer_pause (sink->ringbuffer); + gst_ring_buffer_activate (sink->ringbuffer, FALSE); + gst_ring_buffer_release (sink->ringbuffer); + + GST_DEBUG_OBJECT (sink, "parse caps"); + + spec->buffer_time = sink->buffer_time; + spec->latency_time = sink->latency_time; + + /* parse new caps */ + if (!gst_ring_buffer_parse_caps (spec, caps)) + goto parse_error; + + gst_ring_buffer_debug_spec_buff (spec); + + GST_DEBUG_OBJECT (sink, "acquire ringbuffer"); + if (!gst_ring_buffer_acquire (sink->ringbuffer, spec)) + goto acquire_error; + + if (bsink->pad_mode == GST_ACTIVATE_PUSH) { + GST_DEBUG_OBJECT (sink, "activate ringbuffer"); + gst_ring_buffer_activate (sink->ringbuffer, TRUE); + } + + /* calculate actual latency and buffer times. + * FIXME: In 0.11, store the latency_time internally in ns */ + spec->latency_time = gst_util_uint64_scale (spec->segsize, + (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample); + + spec->buffer_time = spec->segtotal * spec->latency_time; + + gst_ring_buffer_debug_spec_buff (spec); + + return TRUE; + + /* ERRORS */ +parse_error: + { + GST_DEBUG_OBJECT (sink, "could not parse caps"); + GST_ELEMENT_ERROR (sink, STREAM, FORMAT, + (NULL), ("cannot parse audio format.")); + return FALSE; + } +acquire_error: + { + GST_DEBUG_OBJECT (sink, "could not acquire ringbuffer"); + return FALSE; + } +} + +static void +gst_base_audio_sink_fixate (GstBaseSink * bsink, GstCaps * caps) +{ + GstStructure *s; + gint width, depth; + + s = gst_caps_get_structure (caps, 0); + + /* fields for all formats */ + gst_structure_fixate_field_nearest_int (s, "rate", 44100); + gst_structure_fixate_field_nearest_int (s, "channels", 2); + gst_structure_fixate_field_nearest_int (s, "width", 16); + + /* fields for int */ + if (gst_structure_has_field (s, "depth")) { + gst_structure_get_int (s, "width", &width); + /* round width to nearest multiple of 8 for the depth */ + depth = GST_ROUND_UP_8 (width); + gst_structure_fixate_field_nearest_int (s, "depth", depth); + } + if (gst_structure_has_field (s, "signed")) + gst_structure_fixate_field_boolean (s, "signed", TRUE); + if (gst_structure_has_field (s, "endianness")) + gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER); +} + +static void +gst_base_audio_sink_get_times (GstBaseSink * bsink, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + /* our clock sync is a bit too much for the base class to handle so + * we implement it ourselves. */ + *start = GST_CLOCK_TIME_NONE; + *end = GST_CLOCK_TIME_NONE; +} + +/* This waits for the drain to happen and can be canceled */ +static gboolean +gst_base_audio_sink_drain (GstBaseAudioSink * sink) +{ + if (!sink->ringbuffer) + return TRUE; + if (!sink->ringbuffer->spec.rate) + return TRUE; + + /* if PLAYING is interrupted, + * arrange to have clock running when going to PLAYING again */ + g_atomic_int_set (&sink->abidata.ABI.eos_rendering, 1); + + /* need to start playback before we can drain, but only when + * we have successfully negotiated a format and thus acquired the + * ringbuffer. */ + if (gst_ring_buffer_is_acquired (sink->ringbuffer)) + gst_ring_buffer_start (sink->ringbuffer); + + if (sink->priv->eos_time != -1) { + GST_DEBUG_OBJECT (sink, + "last sample time %" GST_TIME_FORMAT, + GST_TIME_ARGS (sink->priv->eos_time)); + + /* wait for the EOS time to be reached, this is the time when the last + * sample is played. */ + gst_base_sink_wait_eos (GST_BASE_SINK (sink), sink->priv->eos_time, NULL); + + GST_DEBUG_OBJECT (sink, "drained audio"); + } + g_atomic_int_set (&sink->abidata.ABI.eos_rendering, 0); + return TRUE; +} + +static gboolean +gst_base_audio_sink_event (GstBaseSink * bsink, GstEvent * event) +{ + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + if (sink->ringbuffer) + gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); + break; + case GST_EVENT_FLUSH_STOP: + /* always resync on sample after a flush */ + sink->priv->avg_skew = -1; + sink->next_sample = -1; + sink->priv->eos_time = -1; + if (sink->ringbuffer) + gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); + break; + case GST_EVENT_EOS: + /* now wait till we played everything */ + gst_base_audio_sink_drain (sink); + break; + case GST_EVENT_NEWSEGMENT: + { + gdouble rate; + + /* we only need the rate */ + gst_event_parse_new_segment_full (event, NULL, &rate, NULL, NULL, + NULL, NULL, NULL); + + GST_DEBUG_OBJECT (sink, "new segment rate of %f", rate); + break; + } + default: + break; + } + return TRUE; +} + +static GstFlowReturn +gst_base_audio_sink_preroll (GstBaseSink * bsink, GstBuffer * buffer) +{ + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (bsink); + + if (!gst_ring_buffer_is_acquired (sink->ringbuffer)) + goto wrong_state; + + /* we don't really do anything when prerolling. We could make a + * property to play this buffer to have some sort of scrubbing + * support. */ + return GST_FLOW_OK; + +wrong_state: + { + GST_DEBUG_OBJECT (sink, "ringbuffer in wrong state"); + GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL), ("sink not negotiated.")); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static guint64 +gst_base_audio_sink_get_offset (GstBaseAudioSink * sink) +{ + guint64 sample; + gint writeseg, segdone, sps; + gint diff; + + /* assume we can append to the previous sample */ + sample = sink->next_sample; + /* no previous sample, try to insert at position 0 */ + if (sample == -1) + sample = 0; + + sps = sink->ringbuffer->samples_per_seg; + + /* figure out the segment and the offset inside the segment where + * the sample should be written. */ + writeseg = sample / sps; + + /* get the currently processed segment */ + segdone = g_atomic_int_get (&sink->ringbuffer->segdone) + - sink->ringbuffer->segbase; + + /* see how far away it is from the write segment */ + diff = writeseg - segdone; + if (diff < 0) { + /* sample would be dropped, position to next playable position */ + sample = (segdone + 1) * sps; + } + + return sample; +} + +static GstClockTime +clock_convert_external (GstClockTime external, GstClockTime cinternal, + GstClockTime cexternal, GstClockTime crate_num, GstClockTime crate_denom) +{ + /* adjust for rate and speed */ + if (external >= cexternal) { + external = + gst_util_uint64_scale (external - cexternal, crate_denom, crate_num); + external += cinternal; + } else { + external = + gst_util_uint64_scale (cexternal - external, crate_denom, crate_num); + if (cinternal > external) + external = cinternal - external; + else + external = 0; + } + return external; +} + +/* algorithm to calculate sample positions that will result in resampling to + * match the clock rate of the master */ +static void +gst_base_audio_sink_resample_slaving (GstBaseAudioSink * sink, + GstClockTime render_start, GstClockTime render_stop, + GstClockTime * srender_start, GstClockTime * srender_stop) +{ + GstClockTime cinternal, cexternal; + GstClockTime crate_num, crate_denom; + + /* FIXME, we can sample and add observations here or use the timeouts on the + * clock. No idea which one is better or more stable. The timeout seems more + * arbitrary but this one seems more demanding and does not work when there is + * no data comming in to the sink. */ +#if 0 + GstClockTime etime, itime; + gdouble r_squared; + + /* sample clocks and figure out clock skew */ + etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink)); + itime = gst_audio_clock_get_time (sink->provided_clock); + + /* add new observation */ + gst_clock_add_observation (sink->provided_clock, itime, etime, &r_squared); +#endif + + /* get calibration parameters to compensate for speed and offset differences + * when we are slaved */ + gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, + &crate_num, &crate_denom); + + GST_DEBUG_OBJECT (sink, "internal %" GST_TIME_FORMAT " external %" + GST_TIME_FORMAT " %" G_GUINT64_FORMAT "/%" G_GUINT64_FORMAT " = %f", + GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal), crate_num, + crate_denom, gst_guint64_to_gdouble (crate_num) / + gst_guint64_to_gdouble (crate_denom)); + + if (crate_num == 0) + crate_denom = crate_num = 1; + + /* bring external time to internal time */ + render_start = clock_convert_external (render_start, cinternal, cexternal, + crate_num, crate_denom); + render_stop = clock_convert_external (render_stop, cinternal, cexternal, + crate_num, crate_denom); + + GST_DEBUG_OBJECT (sink, + "after slaving: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, + GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); + + *srender_start = render_start; + *srender_stop = render_stop; +} + +/* algorithm to calculate sample positions that will result in changing the + * playout pointer to match the clock rate of the master */ +static void +gst_base_audio_sink_skew_slaving (GstBaseAudioSink * sink, + GstClockTime render_start, GstClockTime render_stop, + GstClockTime * srender_start, GstClockTime * srender_stop) +{ + GstClockTime cinternal, cexternal, crate_num, crate_denom; + GstClockTime etime, itime; + GstClockTimeDiff skew, mdrift, mdrift2; + gint driftsamples; + gint64 last_align; + + /* get calibration parameters to compensate for offsets */ + gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, + &crate_num, &crate_denom); + + /* sample clocks and figure out clock skew */ + etime = gst_clock_get_time (GST_ELEMENT_CLOCK (sink)); + itime = gst_audio_clock_get_time (sink->provided_clock); + itime = gst_audio_clock_adjust (sink->provided_clock, itime); + + GST_DEBUG_OBJECT (sink, + "internal %" GST_TIME_FORMAT " external %" GST_TIME_FORMAT + " cinternal %" GST_TIME_FORMAT " cexternal %" GST_TIME_FORMAT, + GST_TIME_ARGS (itime), GST_TIME_ARGS (etime), + GST_TIME_ARGS (cinternal), GST_TIME_ARGS (cexternal)); + + /* make sure we never go below 0 */ + etime = etime > cexternal ? etime - cexternal : 0; + itime = itime > cinternal ? itime - cinternal : 0; + + /* do itime - etime. + * positive value means external clock goes slower + * negative value means external clock goes faster */ + skew = GST_CLOCK_DIFF (etime, itime); + if (sink->priv->avg_skew == -1) { + /* first observation */ + sink->priv->avg_skew = skew; + } else { + /* next observations use a moving average */ + sink->priv->avg_skew = (31 * sink->priv->avg_skew + skew) / 32; + } + + GST_DEBUG_OBJECT (sink, "internal %" GST_TIME_FORMAT " external %" + GST_TIME_FORMAT " skew %" G_GINT64_FORMAT " avg %" G_GINT64_FORMAT, + GST_TIME_ARGS (itime), GST_TIME_ARGS (etime), skew, sink->priv->avg_skew); + + /* the max drift we allow */ + mdrift = sink->priv->drift_tolerance * 1000; + mdrift2 = mdrift / 2; + + /* adjust playout pointer based on skew */ + if (sink->priv->avg_skew > mdrift2) { + /* master is running slower, move internal time forward */ + GST_WARNING_OBJECT (sink, + "correct clock skew %" G_GINT64_FORMAT " > %" G_GINT64_FORMAT, + sink->priv->avg_skew, mdrift2); + cexternal = cexternal > mdrift ? cexternal - mdrift : 0; + sink->priv->avg_skew -= mdrift; + + driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND; + last_align = sink->priv->last_align; + + /* if we were aligning in the wrong direction or we aligned more than what we + * will correct, resync */ + if (last_align < 0 || last_align > driftsamples) + sink->next_sample = -1; + + GST_DEBUG_OBJECT (sink, + "last_align %" G_GINT64_FORMAT " driftsamples %u, next %" + G_GUINT64_FORMAT, last_align, driftsamples, sink->next_sample); + + gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal, + crate_num, crate_denom); + } else if (sink->priv->avg_skew < -mdrift2) { + /* master is running faster, move external time forwards */ + GST_WARNING_OBJECT (sink, + "correct clock skew %" G_GINT64_FORMAT " < %" G_GINT64_FORMAT, + sink->priv->avg_skew, -mdrift2); + cexternal += mdrift; + sink->priv->avg_skew += mdrift; + + driftsamples = (sink->ringbuffer->spec.rate * mdrift) / GST_SECOND; + last_align = sink->priv->last_align; + + /* if we were aligning in the wrong direction or we aligned more than what we + * will correct, resync */ + if (last_align > 0 || -last_align > driftsamples) + sink->next_sample = -1; + + GST_DEBUG_OBJECT (sink, + "last_align %" G_GINT64_FORMAT " driftsamples %u, next %" + G_GUINT64_FORMAT, last_align, driftsamples, sink->next_sample); + + gst_clock_set_calibration (sink->provided_clock, cinternal, cexternal, + crate_num, crate_denom); + } + + /* convert, ignoring speed */ + render_start = clock_convert_external (render_start, cinternal, cexternal, + crate_num, crate_denom); + render_stop = clock_convert_external (render_stop, cinternal, cexternal, + crate_num, crate_denom); + + *srender_start = render_start; + *srender_stop = render_stop; +} + +/* apply the clock offset but do no slaving otherwise */ +static void +gst_base_audio_sink_none_slaving (GstBaseAudioSink * sink, + GstClockTime render_start, GstClockTime render_stop, + GstClockTime * srender_start, GstClockTime * srender_stop) +{ + GstClockTime cinternal, cexternal, crate_num, crate_denom; + + /* get calibration parameters to compensate for offsets */ + gst_clock_get_calibration (sink->provided_clock, &cinternal, &cexternal, + &crate_num, &crate_denom); + + /* convert, ignoring speed */ + render_start = clock_convert_external (render_start, cinternal, cexternal, + crate_num, crate_denom); + render_stop = clock_convert_external (render_stop, cinternal, cexternal, + crate_num, crate_denom); + + *srender_start = render_start; + *srender_stop = render_stop; +} + +/* converts render_start and render_stop to their slaved values */ +static void +gst_base_audio_sink_handle_slaving (GstBaseAudioSink * sink, + GstClockTime render_start, GstClockTime render_stop, + GstClockTime * srender_start, GstClockTime * srender_stop) +{ + switch (sink->priv->slave_method) { + case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: + gst_base_audio_sink_resample_slaving (sink, render_start, render_stop, + srender_start, srender_stop); + break; + case GST_BASE_AUDIO_SINK_SLAVE_SKEW: + gst_base_audio_sink_skew_slaving (sink, render_start, render_stop, + srender_start, srender_stop); + break; + case GST_BASE_AUDIO_SINK_SLAVE_NONE: + gst_base_audio_sink_none_slaving (sink, render_start, render_stop, + srender_start, srender_stop); + break; + default: + g_warning ("unknown slaving method %d", sink->priv->slave_method); + break; + } +} + +/* must be called with LOCK */ +static GstFlowReturn +gst_base_audio_sink_sync_latency (GstBaseSink * bsink, GstMiniObject * obj) +{ + GstClock *clock; + GstClockReturn status; + GstClockTime time, render_delay; + GstFlowReturn ret; + GstBaseAudioSink *sink; + GstClockTime itime, etime; + GstClockTime rate_num, rate_denom; + GstClockTimeDiff jitter; + + sink = GST_BASE_AUDIO_SINK (bsink); + + clock = GST_ELEMENT_CLOCK (sink); + if (G_UNLIKELY (clock == NULL)) + goto no_clock; + + /* we provided the global clock, don't need to do anything special */ + if (clock == sink->provided_clock) + goto no_slaving; + + GST_OBJECT_UNLOCK (sink); + + do { + GST_DEBUG_OBJECT (sink, "checking preroll"); + + ret = gst_base_sink_do_preroll (bsink, obj); + if (ret != GST_FLOW_OK) + goto flushing; + + GST_OBJECT_LOCK (sink); + time = sink->priv->us_latency; + GST_OBJECT_UNLOCK (sink); + + /* Renderdelay is added onto our own latency, and needs + * to be subtracted as well */ + render_delay = gst_base_sink_get_render_delay (bsink); + + if (G_LIKELY (time > render_delay)) + time -= render_delay; + else + time = 0; + + /* preroll done, we can sync since we are in PLAYING now. */ + GST_DEBUG_OBJECT (sink, "possibly waiting for clock to reach %" + GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + /* wait for the clock, this can be interrupted because we got shut down or + * we PAUSED. */ + status = gst_base_sink_wait_clock (bsink, time, &jitter); + + GST_DEBUG_OBJECT (sink, "clock returned %d %" GST_TIME_FORMAT, status, + GST_TIME_ARGS (jitter)); + + /* invalid time, no clock or sync disabled, just continue then */ + if (status == GST_CLOCK_BADTIME) + break; + + /* waiting could have been interrupted and we can be flushing now */ + if (G_UNLIKELY (bsink->flushing)) + goto flushing; + + /* retry if we got unscheduled, which means we did not reach the timeout + * yet. if some other error occures, we continue. */ + } while (status == GST_CLOCK_UNSCHEDULED); + + GST_OBJECT_LOCK (sink); + GST_DEBUG_OBJECT (sink, "latency synced"); + + /* when we prerolled in time, we can accurately set the calibration, + * our internal clock should exactly have been the latency (== the running + * time of the external clock) */ + etime = GST_ELEMENT_CAST (sink)->base_time + time; + itime = gst_audio_clock_get_time (sink->provided_clock); + itime = gst_audio_clock_adjust (sink->provided_clock, itime); + + if (status == GST_CLOCK_EARLY) { + /* when we prerolled late, we have to take into account the lateness */ + GST_DEBUG_OBJECT (sink, "late preroll, adding jitter"); + etime += jitter; + } + + /* start ringbuffer so we can start slaving right away when we need to */ + gst_ring_buffer_start (sink->ringbuffer); + + GST_DEBUG_OBJECT (sink, + "internal time: %" GST_TIME_FORMAT " external time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (itime), GST_TIME_ARGS (etime)); + + /* copy the original calibrated rate but update the internal and external + * times. */ + gst_clock_get_calibration (sink->provided_clock, NULL, NULL, &rate_num, + &rate_denom); + gst_clock_set_calibration (sink->provided_clock, itime, etime, + rate_num, rate_denom); + + switch (sink->priv->slave_method) { + case GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: + /* only set as master when we are resampling */ + GST_DEBUG_OBJECT (sink, "Setting clock as master"); + gst_clock_set_master (sink->provided_clock, clock); + break; + case GST_BASE_AUDIO_SINK_SLAVE_SKEW: + case GST_BASE_AUDIO_SINK_SLAVE_NONE: + default: + break; + } + + sink->priv->avg_skew = -1; + sink->next_sample = -1; + sink->priv->eos_time = -1; + + return GST_FLOW_OK; + + /* ERRORS */ +no_clock: + { + GST_DEBUG_OBJECT (sink, "we have no clock"); + return GST_FLOW_OK; + } +no_slaving: + { + GST_DEBUG_OBJECT (sink, "we are not slaved"); + return GST_FLOW_OK; + } +flushing: + { + GST_DEBUG_OBJECT (sink, "we are flushing"); + GST_OBJECT_LOCK (sink); + return GST_FLOW_WRONG_STATE; + } +} + +static gint64 +gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink, GstClockTime sample_offset) +{ + GstRingBuffer *ringbuf = sink->ringbuffer; + gint64 align; + gint64 diff; + gint64 maxdrift; + gint segdone = g_atomic_int_get (&ringbuf->segdone) - ringbuf->segbase; + gint64 samples_done = segdone * ringbuf->samples_per_seg; + gint64 headroom = sample_offset - samples_done; + gboolean allow_align = TRUE; + + /* now try to align the sample to the previous one, first see how big the + * difference is. */ + if (sample_offset >= sink->next_sample) + diff = sample_offset - sink->next_sample; + else + diff = sink->next_sample - sample_offset; + + /* calculate the max allowed drift in units of samples. By default this is + * 20ms and should be anough to compensate for timestamp rounding errors. */ + maxdrift = (ringbuf->spec.rate * sink->priv->drift_tolerance) / GST_MSECOND; + + /* calc align with previous sample */ + align = sink->next_sample - sample_offset; + + /* don't align if it means writing behind the read-segment */ + if (diff > headroom && align < 0) + allow_align = FALSE; + + if (G_LIKELY (diff < maxdrift && allow_align)) { + GST_DEBUG_OBJECT (sink, + "align with prev sample, ABS (%" G_GINT64_FORMAT ") < %" + G_GINT64_FORMAT, align, maxdrift); + } else { + /* calculate sample diff in seconds for error message */ + gint64 diff_s = gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate); + /* timestamps drifted apart from previous samples too much, we need to + * resync. We log this as an element warning. */ + GST_WARNING_OBJECT (sink, + "Unexpected discontinuity in audio timestamps of " + "%s%" GST_TIME_FORMAT ", resyncing", + sample_offset > sink->next_sample ? "+" : "-", + GST_TIME_ARGS (diff_s)); + align = 0; + } + + return align; +} + +static GstFlowReturn +gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf) +{ + guint64 in_offset; + GstClockTime time, stop, render_start, render_stop, sample_offset; + GstClockTimeDiff sync_offset, ts_offset; + GstBaseAudioSink *sink; + GstRingBuffer *ringbuf; + gint64 diff, align, ctime, cstop; + guint8 *data; + guint size; + guint samples, written; + gint bps; + gint accum; + gint out_samples; + GstClockTime base_time, render_delay, latency; + GstClock *clock; + gboolean sync, slaved, align_next; + GstFlowReturn ret; + GstSegment clip_seg; + gint64 time_offset; + + sink = GST_BASE_AUDIO_SINK (bsink); + + ringbuf = sink->ringbuffer; + + /* can't do anything when we don't have the device */ + if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuf))) + goto wrong_state; + + /* Wait for upstream latency before starting the ringbuffer, we do this so + * that we can align the first sample of the ringbuffer to the base_time + + * latency. */ + GST_OBJECT_LOCK (sink); + base_time = GST_ELEMENT_CAST (sink)->base_time; + if (G_UNLIKELY (sink->priv->sync_latency)) { + ret = gst_base_audio_sink_sync_latency (bsink, GST_MINI_OBJECT_CAST (buf)); + GST_OBJECT_UNLOCK (sink); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto sync_latency_failed; + /* only do this once until we are set back to PLAYING */ + sink->priv->sync_latency = FALSE; + } else { + GST_OBJECT_UNLOCK (sink); + } + + bps = ringbuf->spec.bytes_per_sample; + + size = GST_BUFFER_SIZE (buf); + if (G_UNLIKELY (size % bps) != 0) + goto wrong_size; + + samples = size / bps; + out_samples = samples; + + in_offset = GST_BUFFER_OFFSET (buf); + time = GST_BUFFER_TIMESTAMP (buf); + + GST_DEBUG_OBJECT (sink, + "time %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT ", start %" + GST_TIME_FORMAT ", samples %u", GST_TIME_ARGS (time), in_offset, + GST_TIME_ARGS (bsink->segment.start), samples); + + data = GST_BUFFER_DATA (buf); + + /* if not valid timestamp or we can't clip or sync, try to play + * sample ASAP */ + if (!GST_CLOCK_TIME_IS_VALID (time)) { + render_start = gst_base_audio_sink_get_offset (sink); + render_stop = render_start + samples; + GST_DEBUG_OBJECT (sink, + "Buffer of size %u has no time. Using render_start=%" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (buf), render_start); + /* we don't have a start so we don't know stop either */ + stop = -1; + goto no_sync; + } + + /* let's calc stop based on the number of samples in the buffer instead + * of trusting the DURATION */ + stop = time + gst_util_uint64_scale_int (samples, GST_SECOND, + ringbuf->spec.rate); + + /* prepare the clipping segment. Since we will be subtracting ts-offset and + * device-delay later we scale the start and stop with those values so that we + * can correctly clip them */ + clip_seg.format = GST_FORMAT_TIME; + clip_seg.start = bsink->segment.start; + clip_seg.stop = bsink->segment.stop; + clip_seg.duration = -1; + + /* the sync offset is the combination of ts-offset and device-delay */ + latency = gst_base_sink_get_latency (bsink); + ts_offset = gst_base_sink_get_ts_offset (bsink); + render_delay = gst_base_sink_get_render_delay (bsink); + sync_offset = ts_offset - render_delay + latency; + + GST_DEBUG_OBJECT (sink, + "sync-offset %" G_GINT64_FORMAT ", render-delay %" GST_TIME_FORMAT + ", ts-offset %" G_GINT64_FORMAT, sync_offset, + GST_TIME_ARGS (render_delay), ts_offset); + + /* compensate for ts-offset and device-delay when negative we need to + * clip. */ + if (sync_offset < 0) { + clip_seg.start += -sync_offset; + if (clip_seg.stop != -1) + clip_seg.stop += -sync_offset; + } + + /* samples should be rendered based on their timestamp. All samples + * arriving before the segment.start or after segment.stop are to be + * thrown away. All samples should also be clipped to the segment + * boundaries */ + if (!gst_segment_clip (&clip_seg, GST_FORMAT_TIME, time, stop, &ctime, + &cstop)) + goto out_of_segment; + + /* see if some clipping happened */ + diff = ctime - time; + if (diff > 0) { + /* bring clipped time to samples */ + diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND); + GST_DEBUG_OBJECT (sink, "clipping start to %" GST_TIME_FORMAT " %" + G_GUINT64_FORMAT " samples", GST_TIME_ARGS (ctime), diff); + samples -= diff; + data += diff * bps; + time = ctime; + } + diff = stop - cstop; + if (diff > 0) { + /* bring clipped time to samples */ + diff = gst_util_uint64_scale_int (diff, ringbuf->spec.rate, GST_SECOND); + GST_DEBUG_OBJECT (sink, "clipping stop to %" GST_TIME_FORMAT " %" + G_GUINT64_FORMAT " samples", GST_TIME_ARGS (cstop), diff); + samples -= diff; + stop = cstop; + } + + /* figure out how to sync */ + if ((clock = GST_ELEMENT_CLOCK (bsink))) + sync = bsink->sync; + else + sync = FALSE; + + if (!sync) { + /* no sync needed, play sample ASAP */ + render_start = gst_base_audio_sink_get_offset (sink); + render_stop = render_start + samples; + GST_DEBUG_OBJECT (sink, + "no sync needed. Using render_start=%" G_GUINT64_FORMAT, render_start); + goto no_sync; + } + + /* bring buffer start and stop times to running time */ + render_start = + gst_segment_to_running_time (&bsink->segment, GST_FORMAT_TIME, time); + render_stop = + gst_segment_to_running_time (&bsink->segment, GST_FORMAT_TIME, stop); + + GST_DEBUG_OBJECT (sink, + "running: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, + GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); + + /* store the time of the last sample, we'll use this to perform sync on the + * last sample when draining the buffer */ + if (bsink->segment.rate >= 0.0) { + sink->priv->eos_time = render_stop; + } else { + sink->priv->eos_time = render_start; + } + + /* compensate for ts-offset and delay we know this will not underflow because we + * clipped above. */ + GST_DEBUG_OBJECT (sink, + "compensating for sync-offset %" GST_TIME_FORMAT, + GST_TIME_ARGS (sync_offset)); + render_start += sync_offset; + render_stop += sync_offset; + + GST_DEBUG_OBJECT (sink, "adding base_time %" GST_TIME_FORMAT, + GST_TIME_ARGS (base_time)); + + /* add base time to sync against the clock */ + render_start += base_time; + render_stop += base_time; + + GST_DEBUG_OBJECT (sink, + "after compensation: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, + GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); + + if ((slaved = clock != sink->provided_clock)) { + /* handle clock slaving */ + gst_base_audio_sink_handle_slaving (sink, render_start, render_stop, + &render_start, &render_stop); + } else { + /* no slaving needed but we need to adapt to the clock calibration + * parameters */ + gst_base_audio_sink_none_slaving (sink, render_start, render_stop, + &render_start, &render_stop); + } + + GST_DEBUG_OBJECT (sink, + "final timestamps: start %" GST_TIME_FORMAT " - stop %" GST_TIME_FORMAT, + GST_TIME_ARGS (render_start), GST_TIME_ARGS (render_stop)); + + /* bring to position in the ringbuffer */ + if (sink->priv->do_time_offset) { + time_offset = + GST_AUDIO_CLOCK_CAST (sink->provided_clock)->abidata.ABI.time_offset; + GST_DEBUG_OBJECT (sink, + "time offset %" GST_TIME_FORMAT, GST_TIME_ARGS (time_offset)); + if (render_start > time_offset) + render_start -= time_offset; + else + render_start = 0; + if (render_stop > time_offset) + render_stop -= time_offset; + else + render_stop = 0; + } + + /* and bring the time to the rate corrected offset in the buffer */ + render_start = gst_util_uint64_scale_int (render_start, + ringbuf->spec.rate, GST_SECOND); + render_stop = gst_util_uint64_scale_int (render_stop, + ringbuf->spec.rate, GST_SECOND); + + /* positive playback rate, first sample is render_start, negative rate, first + * sample is render_stop. When no rate conversion is active, render exactly + * the amount of input samples to avoid aligning to rounding errors. */ + if (bsink->segment.rate >= 0.0) { + sample_offset = render_start; + if (bsink->segment.rate == 1.0) + render_stop = sample_offset + samples; + } else { + sample_offset = render_stop; + if (bsink->segment.rate == -1.0) + render_start = sample_offset + samples; + } + + /* always resync after a discont */ + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { + GST_DEBUG_OBJECT (sink, "resync after discont"); + goto no_align; + } + + /* resync when we don't know what to align the sample with */ + if (G_UNLIKELY (sink->next_sample == -1)) { + GST_DEBUG_OBJECT (sink, + "no align possible: no previous sample position known"); + goto no_align; + } + + align = gst_base_audio_sink_get_alignment (sink, sample_offset); + sink->priv->last_align = align; + + /* apply alignment */ + render_start += align; + + /* only align stop if we are not slaved to resample */ + if (slaved && sink->priv->slave_method == GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE) { + GST_DEBUG_OBJECT (sink, "no stop time align needed: we are slaved"); + goto no_align; + } + render_stop += align; + +no_align: + /* number of target samples is difference between start and stop */ + out_samples = render_stop - render_start; + +no_sync: + /* we render the first or last sample first, depending on the rate */ + if (bsink->segment.rate >= 0.0) + sample_offset = render_start; + else + sample_offset = render_stop; + + GST_DEBUG_OBJECT (sink, "rendering at %" G_GUINT64_FORMAT " %d/%d", + sample_offset, samples, out_samples); + + /* we need to accumulate over different runs for when we get interrupted */ + accum = 0; + align_next = TRUE; + do { + written = + gst_ring_buffer_commit_full (ringbuf, &sample_offset, data, samples, + out_samples, &accum); + + GST_DEBUG_OBJECT (sink, "wrote %u of %u", written, samples); + /* if we wrote all, we're done */ + if (written == samples) + break; + + /* else something interrupted us and we wait for preroll. */ + if ((ret = gst_base_sink_wait_preroll (bsink)) != GST_FLOW_OK) + goto stopping; + + /* if we got interrupted, we cannot assume that the next sample should + * be aligned to this one */ + align_next = FALSE; + + /* update the output samples. FIXME, this will just skip them when pausing + * during trick mode */ + if (out_samples > written) { + out_samples -= written; + accum = 0; + } else + break; + + samples -= written; + data += written * bps; + } while (TRUE); + + if (align_next) + sink->next_sample = sample_offset; + else + sink->next_sample = -1; + + GST_DEBUG_OBJECT (sink, "next sample expected at %" G_GUINT64_FORMAT, + sink->next_sample); + + if (GST_CLOCK_TIME_IS_VALID (stop) && stop >= bsink->segment.stop) { + GST_DEBUG_OBJECT (sink, + "start playback because we are at the end of segment"); + gst_ring_buffer_start (ringbuf); + } + + return GST_FLOW_OK; + + /* SPECIAL cases */ +out_of_segment: + { + GST_DEBUG_OBJECT (sink, + "dropping sample out of segment time %" GST_TIME_FORMAT ", start %" + GST_TIME_FORMAT, GST_TIME_ARGS (time), + GST_TIME_ARGS (bsink->segment.start)); + return GST_FLOW_OK; + } + /* ERRORS */ +wrong_state: + { + GST_DEBUG_OBJECT (sink, "ringbuffer not negotiated"); + GST_ELEMENT_ERROR (sink, STREAM, FORMAT, (NULL), ("sink not negotiated.")); + return GST_FLOW_NOT_NEGOTIATED; + } +wrong_size: + { + GST_DEBUG_OBJECT (sink, "wrong size"); + GST_ELEMENT_ERROR (sink, STREAM, WRONG_TYPE, + (NULL), ("sink received buffer of wrong size.")); + return GST_FLOW_ERROR; + } +stopping: + { + GST_DEBUG_OBJECT (sink, "preroll got interrupted: %d (%s)", ret, + gst_flow_get_name (ret)); + return ret; + } +sync_latency_failed: + { + GST_DEBUG_OBJECT (sink, "failed waiting for latency"); + return ret; + } +} + +/** + * gst_base_audio_sink_create_ringbuffer: + * @sink: a #GstBaseAudioSink. + * + * Create and return the #GstRingBuffer for @sink. This function will call the + * ::create_ringbuffer vmethod and will set @sink as the parent of the returned + * buffer (see gst_object_set_parent()). + * + * Returns: The new ringbuffer of @sink. + */ +GstRingBuffer * +gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink * sink) +{ + GstBaseAudioSinkClass *bclass; + GstRingBuffer *buffer = NULL; + + bclass = GST_BASE_AUDIO_SINK_GET_CLASS (sink); + if (bclass->create_ringbuffer) + buffer = bclass->create_ringbuffer (sink); + + if (buffer) + gst_object_set_parent (GST_OBJECT (buffer), GST_OBJECT (sink)); + + return buffer; +} + +static void +gst_base_audio_sink_callback (GstRingBuffer * rbuf, guint8 * data, guint len, + gpointer user_data) +{ + GstBaseSink *basesink; + GstBaseAudioSink *sink; + GstBuffer *buf; + GstFlowReturn ret; + + basesink = GST_BASE_SINK (user_data); + sink = GST_BASE_AUDIO_SINK (user_data); + + GST_PAD_STREAM_LOCK (basesink->sinkpad); + + /* would be nice to arrange for pad_alloc_buffer to return data -- as it is we + will copy twice, once into data, once into DMA */ + GST_LOG_OBJECT (basesink, "pulling %d bytes offset %" G_GUINT64_FORMAT + " to fill audio buffer", len, basesink->offset); + ret = + gst_pad_pull_range (basesink->sinkpad, basesink->segment.last_stop, len, + &buf); + + if (ret != GST_FLOW_OK) { + if (ret == GST_FLOW_UNEXPECTED) + goto eos; + else + goto error; + } + + GST_PAD_PREROLL_LOCK (basesink->sinkpad); + if (basesink->flushing) + goto flushing; + + /* complete preroll and wait for PLAYING */ + ret = gst_base_sink_do_preroll (basesink, GST_MINI_OBJECT_CAST (buf)); + if (ret != GST_FLOW_OK) + goto preroll_error; + + if (len != GST_BUFFER_SIZE (buf)) { + GST_INFO_OBJECT (basesink, + "got different size than requested from sink pad: %u != %u", len, + GST_BUFFER_SIZE (buf)); + len = MIN (GST_BUFFER_SIZE (buf), len); + } + + basesink->segment.last_stop += len; + + memcpy (data, GST_BUFFER_DATA (buf), len); + GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); + + GST_PAD_STREAM_UNLOCK (basesink->sinkpad); + + return; + +error: + { + GST_WARNING_OBJECT (basesink, "Got flow '%s' but can't return it: %d", + gst_flow_get_name (ret), ret); + gst_ring_buffer_pause (rbuf); + GST_PAD_STREAM_UNLOCK (basesink->sinkpad); + return; + } +eos: + { + /* FIXME: this is not quite correct; we'll be called endlessly until + * the sink gets shut down; maybe we should set a flag somewhere, or + * set segment.stop and segment.duration to the last sample or so */ + GST_DEBUG_OBJECT (sink, "EOS"); + gst_base_audio_sink_drain (sink); + gst_ring_buffer_pause (rbuf); + gst_element_post_message (GST_ELEMENT_CAST (sink), + gst_message_new_eos (GST_OBJECT_CAST (sink))); + GST_PAD_STREAM_UNLOCK (basesink->sinkpad); + } +flushing: + { + GST_DEBUG_OBJECT (sink, "we are flushing"); + gst_ring_buffer_pause (rbuf); + GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); + GST_PAD_STREAM_UNLOCK (basesink->sinkpad); + return; + } +preroll_error: + { + GST_DEBUG_OBJECT (sink, "error %s", gst_flow_get_name (ret)); + gst_ring_buffer_pause (rbuf); + GST_PAD_PREROLL_UNLOCK (basesink->sinkpad); + GST_PAD_STREAM_UNLOCK (basesink->sinkpad); + return; + } +} + +static gboolean +gst_base_audio_sink_activate_pull (GstBaseSink * basesink, gboolean active) +{ + gboolean ret; + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (basesink); + + if (active) { + GST_DEBUG_OBJECT (basesink, "activating pull"); + + gst_ring_buffer_set_callback (sink->ringbuffer, + gst_base_audio_sink_callback, sink); + + ret = gst_ring_buffer_activate (sink->ringbuffer, TRUE); + } else { + GST_DEBUG_OBJECT (basesink, "deactivating pull"); + gst_ring_buffer_set_callback (sink->ringbuffer, NULL, NULL); + ret = gst_ring_buffer_activate (sink->ringbuffer, FALSE); + } + + return ret; +} + +/* should be called with the LOCK */ +static GstStateChangeReturn +gst_base_audio_sink_async_play (GstBaseSink * basesink) +{ + GstBaseAudioSink *sink; + + sink = GST_BASE_AUDIO_SINK (basesink); + + GST_DEBUG_OBJECT (sink, "ringbuffer may start now"); + sink->priv->sync_latency = TRUE; + gst_ring_buffer_may_start (sink->ringbuffer, TRUE); + if (basesink->pad_mode == GST_ACTIVATE_PULL) { + /* we always start the ringbuffer in pull mode immediatly */ + gst_ring_buffer_start (sink->ringbuffer); + } + + return GST_STATE_CHANGE_SUCCESS; +} + +static GstStateChangeReturn +gst_base_audio_sink_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstBaseAudioSink *sink = GST_BASE_AUDIO_SINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (sink->ringbuffer == NULL) { + gst_audio_clock_reset (GST_AUDIO_CLOCK (sink->provided_clock), 0); + sink->ringbuffer = gst_base_audio_sink_create_ringbuffer (sink); + } + if (!gst_ring_buffer_open_device (sink->ringbuffer)) + goto open_failed; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + sink->next_sample = -1; + sink->priv->last_align = -1; + sink->priv->eos_time = -1; + gst_ring_buffer_set_flushing (sink->ringbuffer, FALSE); + gst_ring_buffer_may_start (sink->ringbuffer, FALSE); + + /* Only post clock-provide messages if this is the clock that + * we've created. If the subclass has overriden it the subclass + * should post this messages whenever necessary */ + if (sink->provided_clock && GST_IS_AUDIO_CLOCK (sink->provided_clock) && + GST_AUDIO_CLOCK_CAST (sink->provided_clock)->func == + (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time) + gst_element_post_message (element, + gst_message_new_clock_provide (GST_OBJECT_CAST (element), + sink->provided_clock, TRUE)); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + { + gboolean eos; + + GST_OBJECT_LOCK (sink); + GST_DEBUG_OBJECT (sink, "ringbuffer may start now"); + sink->priv->sync_latency = TRUE; + eos = GST_BASE_SINK (sink)->eos; + GST_OBJECT_UNLOCK (sink); + + gst_ring_buffer_may_start (sink->ringbuffer, TRUE); + if (GST_BASE_SINK_CAST (sink)->pad_mode == GST_ACTIVATE_PULL || + g_atomic_int_get (&sink->abidata.ABI.eos_rendering) || eos) { + /* we always start the ringbuffer in pull mode immediatly */ + /* sync rendering on eos needs running clock, + * and others need running clock when finished rendering eos */ + gst_ring_buffer_start (sink->ringbuffer); + } + break; + } + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* ringbuffer cannot start anymore */ + gst_ring_buffer_may_start (sink->ringbuffer, FALSE); + gst_ring_buffer_pause (sink->ringbuffer); + + GST_OBJECT_LOCK (sink); + sink->priv->sync_latency = FALSE; + GST_OBJECT_UNLOCK (sink); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* Only post clock-lost messages if this is the clock that + * we've created. If the subclass has overriden it the subclass + * should post this messages whenever necessary */ + if (sink->provided_clock && GST_IS_AUDIO_CLOCK (sink->provided_clock) && + GST_AUDIO_CLOCK_CAST (sink->provided_clock)->func == + (GstAudioClockGetTimeFunc) gst_base_audio_sink_get_time) + gst_element_post_message (element, + gst_message_new_clock_lost (GST_OBJECT_CAST (element), + sink->provided_clock)); + + /* make sure we unblock before calling the parent state change + * so it can grab the STREAM_LOCK */ + gst_ring_buffer_set_flushing (sink->ringbuffer, TRUE); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* stop slaving ourselves to the master, if any */ + gst_clock_set_master (sink->provided_clock, NULL); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_ring_buffer_activate (sink->ringbuffer, FALSE); + gst_ring_buffer_release (sink->ringbuffer); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + /* we release again here because the aqcuire happens when setting the + * caps, which happens before we commit the state to PAUSED and thus the + * PAUSED->READY state change (see above, where we release the ringbuffer) + * might not be called when we get here. */ + gst_ring_buffer_activate (sink->ringbuffer, FALSE); + gst_ring_buffer_release (sink->ringbuffer); + gst_ring_buffer_close_device (sink->ringbuffer); + GST_OBJECT_LOCK (sink); + gst_object_unparent (GST_OBJECT_CAST (sink->ringbuffer)); + sink->ringbuffer = NULL; + GST_OBJECT_UNLOCK (sink); + break; + default: + break; + } + + return ret; + + /* ERRORS */ +open_failed: + { + /* subclass must post a meaningfull error message */ + GST_DEBUG_OBJECT (sink, "open failed"); + return GST_STATE_CHANGE_FAILURE; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.h new file mode 100644 index 0000000..12a90f9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosink.h @@ -0,0 +1,177 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbaseaudiosink.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* a base class for audio sinks. + * + * It uses a ringbuffer to schedule playback of samples. This makes + * it very easy to drop or insert samples to align incoming + * buffers to the exact playback timestamp. + * + * Subclasses must provide a ringbuffer pointing to either DMA + * memory or regular memory. A subclass should also call a callback + * function when it has played N segments in the buffer. The subclass + * is free to use a thread to signal this callback, use EIO or any + * other mechanism. + * + * The base class is able to operate in push or pull mode. The chain + * mode will queue the samples in the ringbuffer as much as possible. + * The available space is calculated in the callback function. + * + * The pull mode will pull_range() a new buffer of N samples with a + * configurable latency. This allows for high-end real time + * audio processing pipelines driven by the audiosink. The callback + * function will be used to perform a pull_range() on the sinkpad. + * The thread scheduling the callback can be a real-time thread. + * + * Subclasses must implement a GstRingBuffer in addition to overriding + * the methods in GstBaseSink and this class. + */ + +#ifndef __GST_BASE_AUDIO_SINK_H__ +#define __GST_BASE_AUDIO_SINK_H__ + +#include +#include +#include "gstringbuffer.h" +#include "gstaudioclock.h" + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_AUDIO_SINK (gst_base_audio_sink_get_type()) +#define GST_BASE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_AUDIO_SINK,GstBaseAudioSink)) +#define GST_BASE_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_AUDIO_SINK,GstBaseAudioSinkClass)) +#define GST_BASE_AUDIO_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_AUDIO_SINK, GstBaseAudioSinkClass)) +#define GST_IS_BASE_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_AUDIO_SINK)) +#define GST_IS_BASE_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_AUDIO_SINK)) + +/** + * GST_BASE_AUDIO_SINK_CLOCK: + * @obj: a #GstBaseAudioSink + * + * Get the #GstClock of @obj. + */ +#define GST_BASE_AUDIO_SINK_CLOCK(obj) (GST_BASE_AUDIO_SINK (obj)->clock) +/** + * GST_BASE_AUDIO_SINK_PAD: + * @obj: a #GstBaseAudioSink + * + * Get the sink #GstPad of @obj. + */ +#define GST_BASE_AUDIO_SINK_PAD(obj) (GST_BASE_SINK (obj)->sinkpad) + +/** + * GstBaseAudioSinkSlaveMethod: + * @GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE: Resample to match the master clock + * @GST_BASE_AUDIO_SINK_SLAVE_SKEW: Adjust playout pointer when master clock + * drifts too much. + * @GST_BASE_AUDIO_SINK_SLAVE_NONE: No adjustment is done. + * + * Different possible clock slaving algorithms used when the internal audio + * clock is not selected as the pipeline master clock. + */ +typedef enum +{ + GST_BASE_AUDIO_SINK_SLAVE_RESAMPLE, + GST_BASE_AUDIO_SINK_SLAVE_SKEW, + GST_BASE_AUDIO_SINK_SLAVE_NONE +} GstBaseAudioSinkSlaveMethod; + +#define GST_TYPE_BASE_AUDIO_SINK_SLAVE_METHOD (gst_base_audio_sink_slave_method_get_type ()) + +typedef struct _GstBaseAudioSink GstBaseAudioSink; +typedef struct _GstBaseAudioSinkClass GstBaseAudioSinkClass; +typedef struct _GstBaseAudioSinkPrivate GstBaseAudioSinkPrivate; + +/** + * GstBaseAudioSink: + * + * Opaque #GstBaseAudioSink. + */ +struct _GstBaseAudioSink { + GstBaseSink element; + + /*< protected >*/ /* with LOCK */ + /* our ringbuffer */ + GstRingBuffer *ringbuffer; + + /* required buffer and latency in microseconds */ + guint64 buffer_time; + guint64 latency_time; + + /* the next sample to write */ + guint64 next_sample; + + /* clock */ + gboolean provide_clock; + GstClock *provided_clock; + + /*< private >*/ + GstBaseAudioSinkPrivate *priv; + + union { + struct { + /*< protected >*/ + /* with g_atomic_; currently rendering eos */ + gboolean eos_rendering; + } ABI; + gpointer _gst_reserved[GST_PADDING - 1]; + } abidata; +}; + +/** + * GstBaseAudioSinkClass: + * @parent_class: the parent class. + * @create_ringbuffer: create and return a #GstRingBuffer to write to. + * + * #GstBaseAudioSink class. Override the vmethod to implement + * functionality. + */ +struct _GstBaseAudioSinkClass { + GstBaseSinkClass parent_class; + + /* subclass ringbuffer allocation */ + GstRingBuffer* (*create_ringbuffer) (GstBaseAudioSink *sink); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_base_audio_sink_get_type(void); +GType gst_base_audio_sink_slave_method_get_type (void); + +GstRingBuffer *gst_base_audio_sink_create_ringbuffer (GstBaseAudioSink *sink); + +void gst_base_audio_sink_set_provide_clock (GstBaseAudioSink *sink, gboolean provide); +gboolean gst_base_audio_sink_get_provide_clock (GstBaseAudioSink *sink); + +void gst_base_audio_sink_set_slave_method (GstBaseAudioSink *sink, + GstBaseAudioSinkSlaveMethod method); +GstBaseAudioSinkSlaveMethod + gst_base_audio_sink_get_slave_method (GstBaseAudioSink *sink); + +void gst_base_audio_sink_set_drift_tolerance (GstBaseAudioSink *sink, + gint64 drift_tolerance); +gint64 gst_base_audio_sink_get_drift_tolerance (GstBaseAudioSink *sink); + +G_END_DECLS + +#endif /* __GST_BASE_AUDIO_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.c new file mode 100644 index 0000000..7c7ec93 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.c @@ -0,0 +1,1158 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbaseaudiosrc.c: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstbaseaudiosrc + * @short_description: Base class for audio sources + * @see_also: #GstAudioSrc, #GstRingBuffer. + * + * This is the base class for audio sources. Subclasses need to implement the + * ::create_ringbuffer vmethod. This base class will then take care of + * reading samples from the ringbuffer, synchronisation and flushing. + * + * Last reviewed on 2006-09-27 (0.10.12) + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "gstbaseaudiosrc.h" + +#include "gst/gst-i18n-plugin.h" + +GST_DEBUG_CATEGORY_STATIC (gst_base_audio_src_debug); +#define GST_CAT_DEFAULT gst_base_audio_src_debug + +GType +gst_base_audio_src_slave_method_get_type (void) +{ + static volatile gsize slave_method_type = 0; + /* FIXME 0.11: nick should be "retimestamp" not "re-timestamp" */ + static const GEnumValue slave_method[] = { + {GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE, + "GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE", "resample"}, + {GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP, + "GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP", "re-timestamp"}, + {GST_BASE_AUDIO_SRC_SLAVE_SKEW, "GST_BASE_AUDIO_SRC_SLAVE_SKEW", "skew"}, + {GST_BASE_AUDIO_SRC_SLAVE_NONE, "GST_BASE_AUDIO_SRC_SLAVE_NONE", "none"}, + {0, NULL, NULL}, + }; + + if (g_once_init_enter (&slave_method_type)) { + GType tmp = + g_enum_register_static ("GstBaseAudioSrcSlaveMethod", slave_method); + g_once_init_leave (&slave_method_type, tmp); + } + return (GType) slave_method_type; +} + +#define GST_BASE_AUDIO_SRC_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcPrivate)) + +struct _GstBaseAudioSrcPrivate +{ + gboolean provide_clock; + + /* the clock slaving algorithm in use */ + GstBaseAudioSrcSlaveMethod slave_method; +}; + +/* BaseAudioSrc signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_BUFFER_TIME ((200 * GST_MSECOND) / GST_USECOND) +#define DEFAULT_LATENCY_TIME ((10 * GST_MSECOND) / GST_USECOND) +#define DEFAULT_ACTUAL_BUFFER_TIME -1 +#define DEFAULT_ACTUAL_LATENCY_TIME -1 +#define DEFAULT_PROVIDE_CLOCK TRUE +#define DEFAULT_SLAVE_METHOD GST_BASE_AUDIO_SRC_SLAVE_SKEW + +enum +{ + PROP_0, + PROP_BUFFER_TIME, + PROP_LATENCY_TIME, + PROP_ACTUAL_BUFFER_TIME, + PROP_ACTUAL_LATENCY_TIME, + PROP_PROVIDE_CLOCK, + PROP_SLAVE_METHOD, + PROP_LAST +}; + +static void +_do_init (GType type) +{ + GST_DEBUG_CATEGORY_INIT (gst_base_audio_src_debug, "baseaudiosrc", 0, + "baseaudiosrc element"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ +} + +GST_BOILERPLATE_FULL (GstBaseAudioSrc, gst_base_audio_src, GstPushSrc, + GST_TYPE_PUSH_SRC, _do_init); + +static void gst_base_audio_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_base_audio_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_base_audio_src_dispose (GObject * object); + +static GstStateChangeReturn gst_base_audio_src_change_state (GstElement * + element, GstStateChange transition); + +static GstClock *gst_base_audio_src_provide_clock (GstElement * elem); +static GstClockTime gst_base_audio_src_get_time (GstClock * clock, + GstBaseAudioSrc * src); + +static GstFlowReturn gst_base_audio_src_create (GstBaseSrc * bsrc, + guint64 offset, guint length, GstBuffer ** buf); +static gboolean gst_base_audio_src_check_get_range (GstBaseSrc * bsrc); + +static gboolean gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event); +static void gst_base_audio_src_get_times (GstBaseSrc * bsrc, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps); +static gboolean gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query); +static void gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps); + +/* static guint gst_base_audio_src_signals[LAST_SIGNAL] = { 0 }; */ + +static void +gst_base_audio_src_base_init (gpointer g_class) +{ +} + +static void +gst_base_audio_src_class_init (GstBaseAudioSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSrcClass *gstbasesrc_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + + g_type_class_add_private (klass, sizeof (GstBaseAudioSrcPrivate)); + + gobject_class->set_property = gst_base_audio_src_set_property; + gobject_class->get_property = gst_base_audio_src_get_property; + gobject_class->dispose = gst_base_audio_src_dispose; + + g_object_class_install_property (gobject_class, PROP_BUFFER_TIME, + g_param_spec_int64 ("buffer-time", "Buffer Time", + "Size of audio buffer in microseconds", 1, + G_MAXINT64, DEFAULT_BUFFER_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_LATENCY_TIME, + g_param_spec_int64 ("latency-time", "Latency Time", + "Audio latency in microseconds", 1, + G_MAXINT64, DEFAULT_LATENCY_TIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBaseAudioSrc:actual-buffer-time: + * + * Actual configured size of audio buffer in microseconds. + * + * Since: 0.10.20 + **/ + g_object_class_install_property (gobject_class, PROP_ACTUAL_BUFFER_TIME, + g_param_spec_int64 ("actual-buffer-time", "Actual Buffer Time", + "Actual configured size of audio buffer in microseconds", + DEFAULT_ACTUAL_BUFFER_TIME, G_MAXINT64, DEFAULT_ACTUAL_BUFFER_TIME, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBaseAudioSrc:actual-latency-time: + * + * Actual configured audio latency in microseconds. + * + * Since: 0.10.20 + **/ + g_object_class_install_property (gobject_class, PROP_ACTUAL_LATENCY_TIME, + g_param_spec_int64 ("actual-latency-time", "Actual Latency Time", + "Actual configured audio latency in microseconds", + DEFAULT_ACTUAL_LATENCY_TIME, G_MAXINT64, DEFAULT_ACTUAL_LATENCY_TIME, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PROVIDE_CLOCK, + g_param_spec_boolean ("provide-clock", "Provide Clock", + "Provide a clock to be used as the global pipeline clock", + DEFAULT_PROVIDE_CLOCK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SLAVE_METHOD, + g_param_spec_enum ("slave-method", "Slave Method", + "Algorithm to use to match the rate of the masterclock", + GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD, DEFAULT_SLAVE_METHOD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_audio_src_change_state); + gstelement_class->provide_clock = + GST_DEBUG_FUNCPTR (gst_base_audio_src_provide_clock); + + gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_base_audio_src_setcaps); + gstbasesrc_class->event = GST_DEBUG_FUNCPTR (gst_base_audio_src_event); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_base_audio_src_query); + gstbasesrc_class->get_times = + GST_DEBUG_FUNCPTR (gst_base_audio_src_get_times); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_base_audio_src_create); + gstbasesrc_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_base_audio_src_check_get_range); + gstbasesrc_class->fixate = GST_DEBUG_FUNCPTR (gst_base_audio_src_fixate); + + /* ref class from a thread-safe context to work around missing bit of + * thread-safety in GObject */ + g_type_class_ref (GST_TYPE_AUDIO_CLOCK); + g_type_class_ref (GST_TYPE_RING_BUFFER); +} + +static void +gst_base_audio_src_init (GstBaseAudioSrc * baseaudiosrc, + GstBaseAudioSrcClass * g_class) +{ + baseaudiosrc->priv = GST_BASE_AUDIO_SRC_GET_PRIVATE (baseaudiosrc); + + baseaudiosrc->buffer_time = DEFAULT_BUFFER_TIME; + baseaudiosrc->latency_time = DEFAULT_LATENCY_TIME; + baseaudiosrc->priv->provide_clock = DEFAULT_PROVIDE_CLOCK; + baseaudiosrc->priv->slave_method = DEFAULT_SLAVE_METHOD; + /* reset blocksize we use latency time to calculate a more useful + * value based on negotiated format. */ + GST_BASE_SRC (baseaudiosrc)->blocksize = 0; + + baseaudiosrc->clock = gst_audio_clock_new ("GstAudioSrcClock", + (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time, baseaudiosrc); + + /* we are always a live source */ + gst_base_src_set_live (GST_BASE_SRC (baseaudiosrc), TRUE); + /* we operate in time */ + gst_base_src_set_format (GST_BASE_SRC (baseaudiosrc), GST_FORMAT_TIME); +} + +static void +gst_base_audio_src_dispose (GObject * object) +{ + GstBaseAudioSrc *src; + + src = GST_BASE_AUDIO_SRC (object); + + GST_OBJECT_LOCK (src); + if (src->clock) { + gst_audio_clock_invalidate (src->clock); + gst_object_unref (src->clock); + src->clock = NULL; + } + + if (src->ringbuffer) { + gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer)); + src->ringbuffer = NULL; + } + GST_OBJECT_UNLOCK (src); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static GstClock * +gst_base_audio_src_provide_clock (GstElement * elem) +{ + GstBaseAudioSrc *src; + GstClock *clock; + + src = GST_BASE_AUDIO_SRC (elem); + + /* we have no ringbuffer (must be NULL state) */ + if (src->ringbuffer == NULL) + goto wrong_state; + + if (!gst_ring_buffer_is_acquired (src->ringbuffer)) + goto wrong_state; + + GST_OBJECT_LOCK (src); + if (!src->priv->provide_clock) + goto clock_disabled; + + clock = GST_CLOCK_CAST (gst_object_ref (src->clock)); + GST_OBJECT_UNLOCK (src); + + return clock; + + /* ERRORS */ +wrong_state: + { + GST_DEBUG_OBJECT (src, "ringbuffer not acquired"); + return NULL; + } +clock_disabled: + { + GST_DEBUG_OBJECT (src, "clock provide disabled"); + GST_OBJECT_UNLOCK (src); + return NULL; + } +} + +static GstClockTime +gst_base_audio_src_get_time (GstClock * clock, GstBaseAudioSrc * src) +{ + guint64 raw, samples; + guint delay; + GstClockTime result; + + if (G_UNLIKELY (src->ringbuffer == NULL || src->ringbuffer->spec.rate == 0)) + return GST_CLOCK_TIME_NONE; + + raw = samples = gst_ring_buffer_samples_done (src->ringbuffer); + + /* the number of samples not yet processed, this is still queued in the + * device (not yet read for capture). */ + delay = gst_ring_buffer_delay (src->ringbuffer); + + samples += delay; + + result = gst_util_uint64_scale_int (samples, GST_SECOND, + src->ringbuffer->spec.rate); + + GST_DEBUG_OBJECT (src, + "processed samples: raw %" G_GUINT64_FORMAT ", delay %u, real %" + G_GUINT64_FORMAT ", time %" GST_TIME_FORMAT, raw, delay, samples, + GST_TIME_ARGS (result)); + + return result; +} + +static gboolean +gst_base_audio_src_check_get_range (GstBaseSrc * bsrc) +{ + /* we allow limited pull base operation of which the details + * will eventually exposed in an as of yet non-existing query. + * Basically pulling can be done on any number of bytes as long + * as the offset is -1 or sequentially increasing. */ + return TRUE; +} + +/** + * gst_base_audio_src_set_provide_clock: + * @src: a #GstBaseAudioSrc + * @provide: new state + * + * Controls whether @src will provide a clock or not. If @provide is %TRUE, + * gst_element_provide_clock() will return a clock that reflects the datarate + * of @src. If @provide is %FALSE, gst_element_provide_clock() will return NULL. + * + * Since: 0.10.16 + */ +void +gst_base_audio_src_set_provide_clock (GstBaseAudioSrc * src, gboolean provide) +{ + g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src)); + + GST_OBJECT_LOCK (src); + src->priv->provide_clock = provide; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_audio_src_get_provide_clock: + * @src: a #GstBaseAudioSrc + * + * Queries whether @src will provide a clock or not. See also + * gst_base_audio_src_set_provide_clock. + * + * Returns: %TRUE if @src will provide a clock. + * + * Since: 0.10.16 + */ +gboolean +gst_base_audio_src_get_provide_clock (GstBaseAudioSrc * src) +{ + gboolean result; + + g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), FALSE); + + GST_OBJECT_LOCK (src); + result = src->priv->provide_clock; + GST_OBJECT_UNLOCK (src); + + return result; +} + +/** + * gst_base_audio_src_set_slave_method: + * @src: a #GstBaseAudioSrc + * @method: the new slave method + * + * Controls how clock slaving will be performed in @src. + * + * Since: 0.10.20 + */ +void +gst_base_audio_src_set_slave_method (GstBaseAudioSrc * src, + GstBaseAudioSrcSlaveMethod method) +{ + g_return_if_fail (GST_IS_BASE_AUDIO_SRC (src)); + + GST_OBJECT_LOCK (src); + src->priv->slave_method = method; + GST_OBJECT_UNLOCK (src); +} + +/** + * gst_base_audio_src_get_slave_method: + * @src: a #GstBaseAudioSrc + * + * Get the current slave method used by @src. + * + * Returns: The current slave method used by @src. + * + * Since: 0.10.20 + */ +GstBaseAudioSrcSlaveMethod +gst_base_audio_src_get_slave_method (GstBaseAudioSrc * src) +{ + GstBaseAudioSrcSlaveMethod result; + + g_return_val_if_fail (GST_IS_BASE_AUDIO_SRC (src), -1); + + GST_OBJECT_LOCK (src); + result = src->priv->slave_method; + GST_OBJECT_UNLOCK (src); + + return result; +} + +static void +gst_base_audio_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseAudioSrc *src; + + src = GST_BASE_AUDIO_SRC (object); + + switch (prop_id) { + case PROP_BUFFER_TIME: + src->buffer_time = g_value_get_int64 (value); + break; + case PROP_LATENCY_TIME: + src->latency_time = g_value_get_int64 (value); + break; + case PROP_PROVIDE_CLOCK: + gst_base_audio_src_set_provide_clock (src, g_value_get_boolean (value)); + break; + case PROP_SLAVE_METHOD: + gst_base_audio_src_set_slave_method (src, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_audio_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseAudioSrc *src; + + src = GST_BASE_AUDIO_SRC (object); + + switch (prop_id) { + case PROP_BUFFER_TIME: + g_value_set_int64 (value, src->buffer_time); + break; + case PROP_LATENCY_TIME: + g_value_set_int64 (value, src->latency_time); + break; + case PROP_ACTUAL_BUFFER_TIME: + GST_OBJECT_LOCK (src); + if (src->ringbuffer && src->ringbuffer->acquired) + g_value_set_int64 (value, src->ringbuffer->spec.buffer_time); + else + g_value_set_int64 (value, DEFAULT_ACTUAL_BUFFER_TIME); + GST_OBJECT_UNLOCK (src); + break; + case PROP_ACTUAL_LATENCY_TIME: + GST_OBJECT_LOCK (src); + if (src->ringbuffer && src->ringbuffer->acquired) + g_value_set_int64 (value, src->ringbuffer->spec.latency_time); + else + g_value_set_int64 (value, DEFAULT_ACTUAL_LATENCY_TIME); + GST_OBJECT_UNLOCK (src); + break; + case PROP_PROVIDE_CLOCK: + g_value_set_boolean (value, gst_base_audio_src_get_provide_clock (src)); + break; + case PROP_SLAVE_METHOD: + g_value_set_enum (value, gst_base_audio_src_get_slave_method (src)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_audio_src_fixate (GstBaseSrc * bsrc, GstCaps * caps) +{ + GstStructure *s; + gint width, depth; + + s = gst_caps_get_structure (caps, 0); + + /* fields for all formats */ + gst_structure_fixate_field_nearest_int (s, "rate", 44100); + gst_structure_fixate_field_nearest_int (s, "channels", 2); + gst_structure_fixate_field_nearest_int (s, "width", 16); + + /* fields for int */ + if (gst_structure_has_field (s, "depth")) { + gst_structure_get_int (s, "width", &width); + /* round width to nearest multiple of 8 for the depth */ + depth = GST_ROUND_UP_8 (width); + gst_structure_fixate_field_nearest_int (s, "depth", depth); + } + if (gst_structure_has_field (s, "signed")) + gst_structure_fixate_field_boolean (s, "signed", TRUE); + if (gst_structure_has_field (s, "endianness")) + gst_structure_fixate_field_nearest_int (s, "endianness", G_BYTE_ORDER); +} + +static gboolean +gst_base_audio_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps) +{ + GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc); + GstRingBufferSpec *spec; + + spec = &src->ringbuffer->spec; + + spec->buffer_time = src->buffer_time; + spec->latency_time = src->latency_time; + + GST_OBJECT_LOCK (src); + if (!gst_ring_buffer_parse_caps (spec, caps)) + { + GST_OBJECT_UNLOCK (src); + goto parse_error; + } + + /* calculate suggested segsize and segtotal */ + spec->segsize = + spec->rate * spec->bytes_per_sample * spec->latency_time / GST_MSECOND; + spec->segtotal = spec->buffer_time / spec->latency_time; + + GST_OBJECT_UNLOCK (src); + + GST_DEBUG ("release old ringbuffer"); + + gst_ring_buffer_release (src->ringbuffer); + + gst_ring_buffer_debug_spec_buff (spec); + + GST_DEBUG ("acquire new ringbuffer"); + + if (!gst_ring_buffer_acquire (src->ringbuffer, spec)) + goto acquire_error; + + /* calculate actual latency and buffer times */ + spec->latency_time = + spec->segsize * GST_MSECOND / (spec->rate * spec->bytes_per_sample); + spec->buffer_time = + spec->segtotal * spec->segsize * GST_MSECOND / (spec->rate * + spec->bytes_per_sample); + + gst_ring_buffer_debug_spec_buff (spec); + + g_object_notify (G_OBJECT (src), "actual-buffer-time"); + g_object_notify (G_OBJECT (src), "actual-latency-time"); + + return TRUE; + + /* ERRORS */ +parse_error: + { + GST_DEBUG ("could not parse caps"); + return FALSE; + } +acquire_error: + { + GST_DEBUG ("could not acquire ringbuffer"); + return FALSE; + } +} + +static void +gst_base_audio_src_get_times (GstBaseSrc * bsrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + /* no need to sync to a clock here, we schedule the samples based + * on our own clock for the moment. */ + *start = GST_CLOCK_TIME_NONE; + *end = GST_CLOCK_TIME_NONE; +} + +static gboolean +gst_base_audio_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GstClockTime min_latency, max_latency; + GstRingBufferSpec *spec; + + GST_OBJECT_LOCK (src); + if (G_UNLIKELY (src->ringbuffer == NULL + || src->ringbuffer->spec.rate == 0)) { + GST_OBJECT_UNLOCK (src); + goto done; + } + + spec = &src->ringbuffer->spec; + + /* we have at least 1 segment of latency */ + min_latency = + gst_util_uint64_scale_int (spec->segsize, GST_SECOND, + spec->rate * spec->bytes_per_sample); + /* we cannot delay more than the buffersize else we lose data */ + max_latency = + gst_util_uint64_scale_int (spec->segtotal * spec->segsize, GST_SECOND, + spec->rate * spec->bytes_per_sample); + GST_OBJECT_UNLOCK (src); + + GST_DEBUG_OBJECT (src, + "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); + + /* we are always live, the min latency is 1 segment and the max latency is + * the complete buffer of segments. */ + gst_query_set_latency (query, TRUE, min_latency, max_latency); + + res = TRUE; + break; + } + default: + res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + break; + } +done: + return res; +} + +static gboolean +gst_base_audio_src_event (GstBaseSrc * bsrc, GstEvent * event) +{ + GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc); + gboolean res; + + res = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + GST_DEBUG_OBJECT (bsrc, "flush-start"); + gst_ring_buffer_pause (src->ringbuffer); + gst_ring_buffer_clear_all (src->ringbuffer); + break; + case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (bsrc, "flush-stop"); + /* always resync on sample after a flush */ + src->next_sample = -1; + gst_ring_buffer_clear_all (src->ringbuffer); + break; + case GST_EVENT_SEEK: + GST_DEBUG_OBJECT (bsrc, "refuse to seek"); + res = FALSE; + break; + default: + GST_DEBUG_OBJECT (bsrc, "dropping event %p", event); + break; + } + return res; +} + +/* get the next offset in the ringbuffer for reading samples. + * If the next sample is too far away, this function will position itself to the + * next most recent sample, creating discontinuity */ +static guint64 +gst_base_audio_src_get_offset (GstBaseAudioSrc * src) +{ + guint64 sample; + gint readseg, segdone, segtotal, sps; + gint diff; + + /* assume we can append to the previous sample */ + sample = src->next_sample; + + sps = src->ringbuffer->samples_per_seg; + segtotal = src->ringbuffer->spec.segtotal; + + /* get the currently processed segment */ + segdone = g_atomic_int_get (&src->ringbuffer->segdone) + - src->ringbuffer->segbase; + + if (sample != -1) { + GST_DEBUG_OBJECT (src, "at segment %d and sample %" G_GUINT64_FORMAT, + segdone, sample); + /* figure out the segment and the offset inside the segment where + * the sample should be read from. */ + readseg = sample / sps; + + /* see how far away it is from the read segment, normally segdone (where new + * data is written in the ringbuffer) is bigger than readseg (where we are + * reading). */ + diff = segdone - readseg; + if (diff >= segtotal) { + GST_DEBUG_OBJECT (src, "dropped, align to segment %d", segdone); + /* sample would be dropped, position to next playable position */ + sample = ((guint64) (segdone)) * sps; + } + } else { + /* no previous sample, go to the current position */ + GST_DEBUG_OBJECT (src, "first sample, align to current %d", segdone); + sample = ((guint64) (segdone)) * sps; + readseg = segdone; + } + + GST_DEBUG_OBJECT (src, + "reading from %d, we are at %d, sample %" G_GUINT64_FORMAT, readseg, + segdone, sample); + + return sample; +} + +static GstFlowReturn +gst_base_audio_src_create (GstBaseSrc * bsrc, guint64 offset, guint length, + GstBuffer ** outbuf) +{ + GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (bsrc); + GstBuffer *buf; + guchar *data; + guint samples, total_samples; + guint64 sample; + gint bps; + GstRingBuffer *ringbuffer; + GstRingBufferSpec *spec; + guint read; + GstClockTime timestamp, duration; + GstClock *clock; + + ringbuffer = src->ringbuffer; + spec = &ringbuffer->spec; + + if (G_UNLIKELY (!gst_ring_buffer_is_acquired (ringbuffer))) + goto wrong_state; + + bps = spec->bytes_per_sample; + + if ((length == 0 && bsrc->blocksize == 0) || length == -1) + /* no length given, use the default segment size */ + length = spec->segsize; + else + /* make sure we round down to an integral number of samples */ + length -= length % bps; + + /* figure out the offset in the ringbuffer */ + if (G_UNLIKELY (offset != -1)) { + sample = offset / bps; + /* if a specific offset was given it must be the next sequential + * offset we expect or we fail for now. */ + if (src->next_sample != -1 && sample != src->next_sample) + goto wrong_offset; + } else { + /* calculate the sequentially next sample we need to read. This can jump and + * create a DISCONT. */ + sample = gst_base_audio_src_get_offset (src); + } + + GST_DEBUG_OBJECT (src, "reading from sample %" G_GUINT64_FORMAT, sample); + + /* get the number of samples to read */ + total_samples = samples = length / bps; + + /* FIXME, using a bufferpool would be nice here */ + buf = gst_buffer_new_and_alloc (length); + data = GST_BUFFER_DATA (buf); + + do { + read = gst_ring_buffer_read (ringbuffer, sample, data, samples); + GST_DEBUG_OBJECT (src, "read %u of %u", read, samples); + /* if we read all, we're done */ + if (read == samples) + break; + + /* else something interrupted us and we wait for playing again. */ + GST_DEBUG_OBJECT (src, "wait playing"); + if (gst_base_src_wait_playing (bsrc) != GST_FLOW_OK) + goto stopped; + + GST_DEBUG_OBJECT (src, "continue playing"); + + /* read next samples */ + sample += read; + samples -= read; + data += read * bps; + } while (TRUE); + + /* mark discontinuity if needed */ + if (G_UNLIKELY (sample != src->next_sample) && src->next_sample != -1) { + GST_WARNING_OBJECT (src, + "create DISCONT of %" G_GUINT64_FORMAT " samples at sample %" + G_GUINT64_FORMAT, sample - src->next_sample, sample); + GST_ELEMENT_WARNING (src, CORE, CLOCK, + (_("Can't record audio fast enough")), + ("Dropped %" G_GUINT64_FORMAT " samples. This is most likely because " + "downstream can't keep up and is consuming samples too slowly.", + sample - src->next_sample)); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + } + + src->next_sample = sample + samples; + + /* get the normal timestamp to get the duration. */ + timestamp = gst_util_uint64_scale_int (sample, GST_SECOND, spec->rate); + duration = gst_util_uint64_scale_int (src->next_sample, GST_SECOND, + spec->rate) - timestamp; + + GST_OBJECT_LOCK (src); + if (!(clock = GST_ELEMENT_CLOCK (src))) + goto no_sync; + + if (clock != src->clock) { + /* we are slaved, check how to handle this */ + switch (src->priv->slave_method) { + case GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE: + /* not implemented, use skew algorithm. This algorithm should + * work on the readout pointer and produces more or less samples based + * on the clock drift */ + case GST_BASE_AUDIO_SRC_SLAVE_SKEW: + { + GstClockTime running_time; + GstClockTime base_time; + GstClockTime current_time; + guint64 running_time_sample; + gint running_time_segment; + gint last_read_segment; + gint segment_skew; + gint sps; + gint segments_written; + gint last_written_segment; + + /* get the amount of segments written from the device by now */ + segments_written = g_atomic_int_get (&ringbuffer->segdone); + + /* subtract the base to segments_written to get the number of the + last written segment in the ringbuffer (one segment written = segment 0) */ + last_written_segment = segments_written - ringbuffer->segbase - 1; + + /* samples per segment */ + sps = ringbuffer->samples_per_seg; + + /* get the current time */ + current_time = gst_clock_get_time (clock); + + /* get the basetime */ + base_time = GST_ELEMENT_CAST (src)->base_time; + + /* get the running_time */ + running_time = current_time - base_time; + + /* the running_time converted to a sample (relative to the ringbuffer) */ + running_time_sample = + gst_util_uint64_scale_int (running_time, spec->rate, GST_SECOND); + + /* the segmentnr corrensponding to running_time, round down */ + running_time_segment = running_time_sample / sps; + + /* the segment currently read from the ringbuffer */ + last_read_segment = sample / sps; + + /* the skew we have between running_time and the ringbuffertime (last written to) */ + segment_skew = running_time_segment - last_written_segment; + + GST_DEBUG_OBJECT (bsrc, + "\n running_time = %" + GST_TIME_FORMAT + "\n timestamp = %" + GST_TIME_FORMAT + "\n running_time_segment = %d" + "\n last_written_segment = %d" + "\n segment_skew (running time segment - last_written_segment) = %d" + "\n last_read_segment = %d", + GST_TIME_ARGS (running_time), GST_TIME_ARGS (timestamp), + running_time_segment, last_written_segment, segment_skew, + last_read_segment); + + /* Resync the ringbuffer if: + * + * 1. We are more than the length of the ringbuffer behind. + * The length of the ringbuffer then gets to dictate + * the threshold for what is concidered "too late" + * + * 2. If this is our first buffer. + * We know that we should catch up to running_time + * the first time we are ran. + */ + if ((segment_skew >= ringbuffer->spec.segtotal) || + (last_read_segment == 0)) { + gint new_read_segment; + gint segment_diff; + guint64 new_sample; + + /* the difference between running_time and the last written segment */ + segment_diff = running_time_segment - last_written_segment; + + /* advance the ringbuffer */ + gst_ring_buffer_advance (ringbuffer, segment_diff); + + /* we move the new read segment to the last known written segment */ + new_read_segment = + g_atomic_int_get (&ringbuffer->segdone) - ringbuffer->segbase; + + /* we calculate the new sample value */ + new_sample = ((guint64) new_read_segment) * sps; + + /* and get the relative time to this -> our new timestamp */ + timestamp = + gst_util_uint64_scale_int (new_sample, GST_SECOND, spec->rate); + + /* we update the next sample accordingly */ + src->next_sample = new_sample + samples; + + GST_DEBUG_OBJECT (bsrc, + "Timeshifted the ringbuffer with %d segments: " + "Updating the timestamp to %" GST_TIME_FORMAT ", " + "and src->next_sample to %" G_GUINT64_FORMAT, segment_diff, + GST_TIME_ARGS (timestamp), src->next_sample); + } + break; + } + case GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP: + { + GstClockTime base_time, latency; + + /* We are slaved to another clock, take running time of the pipeline clock and + * timestamp against it. Somebody else in the pipeline should figure out the + * clock drift. We keep the duration we calculated above. */ + timestamp = gst_clock_get_time (clock); + base_time = GST_ELEMENT_CAST (src)->base_time; + + if (GST_CLOCK_DIFF (timestamp, base_time) < 0) + timestamp -= base_time; + else + timestamp = 0; + + /* subtract latency */ + latency = + gst_util_uint64_scale_int (total_samples, GST_SECOND, spec->rate); + if (timestamp > latency) + timestamp -= latency; + else + timestamp = 0; + } + case GST_BASE_AUDIO_SRC_SLAVE_NONE: + break; + } + } else { + GstClockTime base_time; + + /* to get the timestamp against the clock we also need to add our offset */ + timestamp = gst_audio_clock_adjust (clock, timestamp); + + /* we are not slaved, subtract base_time */ + base_time = GST_ELEMENT_CAST (src)->base_time; + + if (GST_CLOCK_DIFF (timestamp, base_time) < 0) { + timestamp -= base_time; + GST_LOG_OBJECT (src, + "buffer timestamp %" GST_TIME_FORMAT " (base_time %" GST_TIME_FORMAT + ")", GST_TIME_ARGS (timestamp), GST_TIME_ARGS (base_time)); + } else { + GST_LOG_OBJECT (src, + "buffer timestamp 0, ts %" GST_TIME_FORMAT " <= base_time %" + GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), + GST_TIME_ARGS (base_time)); + timestamp = 0; + } + } + +no_sync: + GST_OBJECT_UNLOCK (src); + + GST_BUFFER_TIMESTAMP (buf) = timestamp; + GST_BUFFER_DURATION (buf) = duration; + GST_BUFFER_OFFSET (buf) = sample; + GST_BUFFER_OFFSET_END (buf) = sample + samples; + + *outbuf = buf; + + return GST_FLOW_OK; + + /* ERRORS */ +wrong_state: + { + GST_DEBUG_OBJECT (src, "ringbuffer in wrong state"); + return GST_FLOW_WRONG_STATE; + } +wrong_offset: + { + GST_ELEMENT_ERROR (src, RESOURCE, SEEK, + (NULL), ("resource can only be operated on sequentially but offset %" + G_GUINT64_FORMAT " was given", offset)); + return GST_FLOW_ERROR; + } +stopped: + { + gst_buffer_unref (buf); + GST_DEBUG_OBJECT (src, "ringbuffer stopped"); + return GST_FLOW_WRONG_STATE; + } +} + +/** + * gst_base_audio_src_create_ringbuffer: + * @src: a #GstBaseAudioSrc. + * + * Create and return the #GstRingBuffer for @src. This function will call the + * ::create_ringbuffer vmethod and will set @src as the parent of the returned + * buffer (see gst_object_set_parent()). + * + * Returns: The new ringbuffer of @src. + */ +GstRingBuffer * +gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc * src) +{ + GstBaseAudioSrcClass *bclass; + GstRingBuffer *buffer = NULL; + + bclass = GST_BASE_AUDIO_SRC_GET_CLASS (src); + if (bclass->create_ringbuffer) + buffer = bclass->create_ringbuffer (src); + + if (G_LIKELY (buffer)) + gst_object_set_parent (GST_OBJECT_CAST (buffer), GST_OBJECT_CAST (src)); + + return buffer; +} + +static GstStateChangeReturn +gst_base_audio_src_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstBaseAudioSrc *src = GST_BASE_AUDIO_SRC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + GST_DEBUG_OBJECT (src, "NULL->READY"); + GST_OBJECT_LOCK (src); + if (src->ringbuffer == NULL) { + gst_audio_clock_reset (GST_AUDIO_CLOCK (src->clock), 0); + src->ringbuffer = gst_base_audio_src_create_ringbuffer (src); + } + GST_OBJECT_UNLOCK (src); + if (!gst_ring_buffer_open_device (src->ringbuffer)) + goto open_failed; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT (src, "READY->PAUSED"); + src->next_sample = -1; + gst_ring_buffer_set_flushing (src->ringbuffer, FALSE); + gst_ring_buffer_may_start (src->ringbuffer, FALSE); + /* Only post clock-provide messages if this is the clock that + * we've created. If the subclass has overriden it the subclass + * should post this messages whenever necessary */ + if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) && + GST_AUDIO_CLOCK_CAST (src->clock)->func == + (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time) + gst_element_post_message (element, + gst_message_new_clock_provide (GST_OBJECT_CAST (element), + src->clock, TRUE)); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_DEBUG_OBJECT (src, "PAUSED->PLAYING"); + gst_ring_buffer_may_start (src->ringbuffer, TRUE); + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (src, "PLAYING->PAUSED"); + gst_ring_buffer_may_start (src->ringbuffer, FALSE); + gst_ring_buffer_pause (src->ringbuffer); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (src, "PAUSED->READY"); + /* Only post clock-lost messages if this is the clock that + * we've created. If the subclass has overriden it the subclass + * should post this messages whenever necessary */ + if (src->clock && GST_IS_AUDIO_CLOCK (src->clock) && + GST_AUDIO_CLOCK_CAST (src->clock)->func == + (GstAudioClockGetTimeFunc) gst_base_audio_src_get_time) + gst_element_post_message (element, + gst_message_new_clock_lost (GST_OBJECT_CAST (element), src->clock)); + gst_ring_buffer_set_flushing (src->ringbuffer, TRUE); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (src, "PAUSED->READY"); + gst_ring_buffer_release (src->ringbuffer); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + GST_DEBUG_OBJECT (src, "READY->NULL"); + gst_ring_buffer_close_device (src->ringbuffer); + GST_OBJECT_LOCK (src); + gst_object_unparent (GST_OBJECT_CAST (src->ringbuffer)); + src->ringbuffer = NULL; + GST_OBJECT_UNLOCK (src); + break; + default: + break; + } + + return ret; + + /* ERRORS */ +open_failed: + { + /* subclass must post a meaningfull error message */ + GST_DEBUG_OBJECT (src, "open failed"); + return GST_STATE_CHANGE_FAILURE; + } + +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.h new file mode 100644 index 0000000..b55ac1e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstbaseaudiosrc.h @@ -0,0 +1,146 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstbaseaudiosrc.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* a base class for audio sources. + */ + +#ifndef __GST_BASE_AUDIO_SRC_H__ +#define __GST_BASE_AUDIO_SRC_H__ + +#include +#include +#include "gstringbuffer.h" +#include "gstaudioclock.h" + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_AUDIO_SRC (gst_base_audio_src_get_type()) +#define GST_BASE_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_AUDIO_SRC,GstBaseAudioSrc)) +#define GST_BASE_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_AUDIO_SRC,GstBaseAudioSrcClass)) +#define GST_BASE_AUDIO_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_AUDIO_SRC, GstBaseAudioSrcClass)) +#define GST_IS_BASE_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_AUDIO_SRC)) +#define GST_IS_BASE_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_AUDIO_SRC)) + +/** + * GST_BASE_AUDIO_SRC_CLOCK: + * @obj: a #GstBaseAudioSrc + * + * Get the #GstClock of @obj. + */ +#define GST_BASE_AUDIO_SRC_CLOCK(obj) (GST_BASE_AUDIO_SRC (obj)->clock) +/** + * GST_BASE_AUDIO_SRC_PAD: + * @obj: a #GstBaseAudioSrc + * + * Get the source #GstPad of @obj. + */ +#define GST_BASE_AUDIO_SRC_PAD(obj) (GST_BASE_SRC (obj)->srcpad) + +typedef struct _GstBaseAudioSrc GstBaseAudioSrc; +typedef struct _GstBaseAudioSrcClass GstBaseAudioSrcClass; +typedef struct _GstBaseAudioSrcPrivate GstBaseAudioSrcPrivate; + +/** + * GstBaseAudioSrcSlaveMethod: + * @GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE: Resample to match the master clock. + * @GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP: Retimestamp output buffers with master + * clock time. + * @GST_BASE_AUDIO_SRC_SLAVE_SKEW: Adjust capture pointer when master clock + * drifts too much. + * @GST_BASE_AUDIO_SRC_SLAVE_NONE: No adjustment is done. + * + * Different possible clock slaving algorithms when the internal audio clock was + * not selected as the pipeline clock. + */ +typedef enum +{ + GST_BASE_AUDIO_SRC_SLAVE_RESAMPLE, + GST_BASE_AUDIO_SRC_SLAVE_RETIMESTAMP, + GST_BASE_AUDIO_SRC_SLAVE_SKEW, + GST_BASE_AUDIO_SRC_SLAVE_NONE +} GstBaseAudioSrcSlaveMethod; + +#define GST_TYPE_BASE_AUDIO_SRC_SLAVE_METHOD (gst_base_audio_src_slave_method_get_type ()) + +/** + * GstBaseAudioSrc: + * + * Opaque #GstBaseAudioSrc. + */ +struct _GstBaseAudioSrc { + GstPushSrc element; + + /*< protected >*/ /* with LOCK */ + /* our ringbuffer */ + GstRingBuffer *ringbuffer; + + /* required buffer and latency */ + GstClockTime buffer_time; + GstClockTime latency_time; + + /* the next sample to write */ + guint64 next_sample; + + /* clock */ + GstClock *clock; + + /*< private >*/ + GstBaseAudioSrcPrivate *priv; + + gpointer _gst_reserved[GST_PADDING - 1]; +}; + +/** + * GstBaseAudioSrcClass: + * @parent_class: the parent class. + * @create_ringbuffer: create and return a #GstRingBuffer to read from. + * + * #GstBaseAudioSrc class. Override the vmethod to implement + * functionality. + */ +struct _GstBaseAudioSrcClass { + GstPushSrcClass parent_class; + + /* subclass ringbuffer allocation */ + GstRingBuffer* (*create_ringbuffer) (GstBaseAudioSrc *src); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_base_audio_src_get_type(void); +GType gst_base_audio_src_slave_method_get_type (void); + +GstRingBuffer *gst_base_audio_src_create_ringbuffer (GstBaseAudioSrc *src); + +void gst_base_audio_src_set_provide_clock (GstBaseAudioSrc *src, gboolean provide); +gboolean gst_base_audio_src_get_provide_clock (GstBaseAudioSrc *src); + +void gst_base_audio_src_set_slave_method (GstBaseAudioSrc *src, + GstBaseAudioSrcSlaveMethod method); +GstBaseAudioSrcSlaveMethod + gst_base_audio_src_get_slave_method (GstBaseAudioSrc *src); + + +G_END_DECLS + +#endif /* __GST_BASE_AUDIO_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.c new file mode 100644 index 0000000..87d1ce2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.c @@ -0,0 +1,2060 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstringbuffer + * @short_description: Base class for audio ringbuffer implementations + * @see_also: #GstBaseAudioSink, #GstAudioSink + * + * + * + * This object is the base class for audio ringbuffers used by the base + * audio source and sink classes. + * + * + * The ringbuffer abstracts a circular buffer of data. One reader and + * one writer can operate on the data from different threads in a lockfree + * manner. The base class is sufficiently flexible to be used as an + * abstraction for DMA based ringbuffers as well as a pure software + * implementations. + * + * + * + * Last reviewed on 2006-02-02 (0.10.4) + */ + +#include + +#include "gstringbuffer.h" + +GST_DEBUG_CATEGORY_STATIC (gst_ring_buffer_debug); +#define GST_CAT_DEFAULT gst_ring_buffer_debug + +static void gst_ring_buffer_dispose (GObject * object); +static void gst_ring_buffer_finalize (GObject * object); + +static gboolean gst_ring_buffer_pause_unlocked (GstRingBuffer * buf); +static void default_clear_all (GstRingBuffer * buf); +static guint default_commit (GstRingBuffer * buf, guint64 * sample, + guchar * data, gint in_samples, gint out_samples, gint * accum); + +/* ringbuffer abstract base class */ +G_DEFINE_ABSTRACT_TYPE (GstRingBuffer, gst_ring_buffer, GST_TYPE_OBJECT); + +static void +gst_ring_buffer_class_init (GstRingBufferClass * klass) +{ + GObjectClass *gobject_class; + GstRingBufferClass *gstringbuffer_class; + + gobject_class = (GObjectClass *) klass; + gstringbuffer_class = (GstRingBufferClass *) klass; + + GST_DEBUG_CATEGORY_INIT (gst_ring_buffer_debug, "ringbuffer", 0, + "ringbuffer class"); + + gobject_class->dispose = gst_ring_buffer_dispose; + gobject_class->finalize = gst_ring_buffer_finalize; + + gstringbuffer_class->clear_all = GST_DEBUG_FUNCPTR (default_clear_all); + gstringbuffer_class->commit = GST_DEBUG_FUNCPTR (default_commit); +} + +static void +gst_ring_buffer_init (GstRingBuffer * ringbuffer) +{ + ringbuffer->open = FALSE; + ringbuffer->acquired = FALSE; + ringbuffer->state = GST_RING_BUFFER_STATE_STOPPED; + ringbuffer->cond = g_cond_new (); + ringbuffer->waiting = 0; + ringbuffer->empty_seg = NULL; + ringbuffer->abidata.ABI.flushing = TRUE; +} + +static void +gst_ring_buffer_dispose (GObject * object) +{ + GstRingBuffer *ringbuffer = GST_RING_BUFFER (object); + + gst_caps_replace (&ringbuffer->spec.caps, NULL); + + G_OBJECT_CLASS (gst_ring_buffer_parent_class)->dispose (G_OBJECT + (ringbuffer)); +} + +static void +gst_ring_buffer_finalize (GObject * object) +{ + GstRingBuffer *ringbuffer = GST_RING_BUFFER (object); + + g_cond_free (ringbuffer->cond); + g_free (ringbuffer->empty_seg); + + G_OBJECT_CLASS (gst_ring_buffer_parent_class)->finalize (G_OBJECT + (ringbuffer)); +} + +typedef struct +{ + const GstBufferFormat format; + const guint8 silence[4]; +} FormatDef; + +static const FormatDef linear_defs[4 * 2 * 2] = { + {GST_S8, {0x00, 0x00, 0x00, 0x00}}, + {GST_S8, {0x00, 0x00, 0x00, 0x00}}, + {GST_U8, {0x80, 0x80, 0x80, 0x80}}, + {GST_U8, {0x80, 0x80, 0x80, 0x80}}, + {GST_S16_LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S16_BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U16_LE, {0x00, 0x80, 0x00, 0x80}}, + {GST_U16_BE, {0x80, 0x00, 0x80, 0x00}}, + {GST_S24_LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S24_BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U24_LE, {0x00, 0x00, 0x80, 0x00}}, + {GST_U24_BE, {0x80, 0x00, 0x00, 0x00}}, + {GST_S32_LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S32_BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U32_LE, {0x00, 0x00, 0x00, 0x80}}, + {GST_U32_BE, {0x80, 0x00, 0x00, 0x00}} +}; + +static const FormatDef linear24_defs[3 * 2 * 2] = { + {GST_S24_3LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S24_3BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U24_3LE, {0x00, 0x00, 0x80, 0x00}}, + {GST_U24_3BE, {0x80, 0x00, 0x00, 0x00}}, + {GST_S20_3LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S20_3BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U20_3LE, {0x00, 0x00, 0x08, 0x00}}, + {GST_U20_3BE, {0x08, 0x00, 0x00, 0x00}}, + {GST_S18_3LE, {0x00, 0x00, 0x00, 0x00}}, + {GST_S18_3BE, {0x00, 0x00, 0x00, 0x00}}, + {GST_U18_3LE, {0x00, 0x00, 0x02, 0x00}}, + {GST_U18_3BE, {0x02, 0x00, 0x00, 0x00}} +}; + +static const FormatDef * +build_linear_format (int depth, int width, int unsignd, int big_endian) +{ + const FormatDef *formats; + + if (width == 24) { + switch (depth) { + case 24: + formats = &linear24_defs[0]; + break; + case 20: + formats = &linear24_defs[4]; + break; + case 18: + formats = &linear24_defs[8]; + break; + default: + return NULL; + } + } else { + switch (depth) { + case 8: + formats = &linear_defs[0]; + break; + case 16: + formats = &linear_defs[4]; + break; + case 24: + formats = &linear_defs[8]; + break; + case 32: + formats = &linear_defs[12]; + break; + default: + return NULL; + } + } + if (unsignd) + formats += 2; + if (big_endian) + formats += 1; + + return formats; +} + +#ifndef GST_DISABLE_GST_DEBUG +static const gchar *format_type_names[] = { + "linear", + "float", + "mu law", + "a law", + "ima adpcm", + "mpeg", + "gsm", + "iec958", + "ac3", + "eac3", + "dts" +}; + +static const gchar *format_names[] = { + "unknown", + "s8", + "u8", + "s16_le", + "s16_be", + "u16_le", + "u16_be", + "s24_le", + "s24_be", + "u24_le", + "u24_be", + "s32_le", + "s32_be", + "u32_le", + "u32_be", + "s24_3le", + "s24_3be", + "u24_3le", + "u24_3be", + "s20_3le", + "s20_3be", + "u20_3le", + "u20_3be", + "s18_3le", + "s18_3be", + "u18_3le", + "u18_3be", + "float32_le", + "float32_be", + "float64_le", + "float64_be", + "mu_law", + "a_law", + "ima_adpcm", + "mpeg", + "gsm", + "iec958", + "ac3", + "eac3", + "dts" +}; +#endif + +/** + * gst_ring_buffer_debug_spec_caps: + * @spec: the spec to debug + * + * Print debug info about the parsed caps in @spec to the debug log. + */ +void +gst_ring_buffer_debug_spec_caps (GstRingBufferSpec * spec) +{ + gint i, bytes; + + GST_DEBUG ("spec caps: %p %" GST_PTR_FORMAT, spec->caps, spec->caps); + GST_DEBUG ("parsed caps: type: %d, '%s'", spec->type, + format_type_names[spec->type]); + GST_DEBUG ("parsed caps: format: %d, '%s'", spec->format, + format_names[spec->format]); + GST_DEBUG ("parsed caps: width: %d", spec->width); + GST_DEBUG ("parsed caps: depth: %d", spec->depth); + GST_DEBUG ("parsed caps: sign: %d", spec->sign); + GST_DEBUG ("parsed caps: bigend: %d", spec->bigend); + GST_DEBUG ("parsed caps: rate: %d", spec->rate); + GST_DEBUG ("parsed caps: channels: %d", spec->channels); + GST_DEBUG ("parsed caps: sample bytes: %d", spec->bytes_per_sample); + bytes = (spec->width >> 3) * spec->channels; + for (i = 0; i < bytes; i++) { + GST_DEBUG ("silence byte %d: %02x", i, spec->silence_sample[i]); + } +} + +/** + * gst_ring_buffer_debug_spec_buff: + * @spec: the spec to debug + * + * Print debug info about the buffer sized in @spec to the debug log. + */ +void +gst_ring_buffer_debug_spec_buff (GstRingBufferSpec * spec) +{ + GST_DEBUG ("acquire ringbuffer: buffer time: %" G_GINT64_FORMAT " usec", + spec->buffer_time); + GST_DEBUG ("acquire ringbuffer: latency time: %" G_GINT64_FORMAT " usec", + spec->latency_time); + GST_DEBUG ("acquire ringbuffer: total segments: %d", spec->segtotal); + GST_DEBUG ("acquire ringbuffer: latency segments: %d", spec->seglatency); + GST_DEBUG ("acquire ringbuffer: segment size: %d bytes = %d samples", + spec->segsize, spec->segsize / spec->bytes_per_sample); + GST_DEBUG ("acquire ringbuffer: buffer size: %d bytes = %d samples", + spec->segsize * spec->segtotal, + spec->segsize * spec->segtotal / spec->bytes_per_sample); +} + +/** + * gst_ring_buffer_parse_caps: + * @spec: a spec + * @caps: a #GstCaps + * + * Parse @caps into @spec. + * + * Returns: TRUE if the caps could be parsed. + */ +gboolean +gst_ring_buffer_parse_caps (GstRingBufferSpec * spec, GstCaps * caps) +{ + const gchar *mimetype; + GstStructure *structure; + gint i; + + structure = gst_caps_get_structure (caps, 0); + + /* we have to differentiate between int and float formats */ + mimetype = gst_structure_get_name (structure); + + if (!strncmp (mimetype, "audio/x-raw-int", 15)) { + gint endianness; + const FormatDef *def; + gint j, bytes; + + spec->type = GST_BUFTYPE_LINEAR; + + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate) && + gst_structure_get_int (structure, "channels", &spec->channels) && + gst_structure_get_int (structure, "width", &spec->width) && + gst_structure_get_int (structure, "depth", &spec->depth) && + gst_structure_get_boolean (structure, "signed", &spec->sign))) + goto parse_error; + + /* extract endianness if needed */ + if (spec->width > 8) { + if (!gst_structure_get_int (structure, "endianness", &endianness)) + goto parse_error; + } else { + endianness = G_BYTE_ORDER; + } + + spec->bigend = endianness == G_LITTLE_ENDIAN ? FALSE : TRUE; + + def = build_linear_format (spec->depth, spec->width, spec->sign ? 0 : 1, + spec->bigend ? 1 : 0); + + if (def == NULL) + goto parse_error; + + spec->format = def->format; + + bytes = spec->width >> 3; + + for (i = 0; i < spec->channels; i++) { + for (j = 0; j < bytes; j++) { + spec->silence_sample[i * bytes + j] = def->silence[j]; + } + } + } else if (!strncmp (mimetype, "audio/x-raw-float", 17)) { + + spec->type = GST_BUFTYPE_FLOAT; + + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate) && + gst_structure_get_int (structure, "channels", &spec->channels) && + gst_structure_get_int (structure, "width", &spec->width))) + goto parse_error; + + /* match layout to format wrt to endianness */ + switch (spec->width) { + case 32: + spec->format = + G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT32_LE : GST_FLOAT32_BE; + break; + case 64: + spec->format = + G_BYTE_ORDER == G_LITTLE_ENDIAN ? GST_FLOAT64_LE : GST_FLOAT64_BE; + break; + default: + goto parse_error; + } + /* float silence is all zeros.. */ + memset (spec->silence_sample, 0, 32); + } else if (!strncmp (mimetype, "audio/x-alaw", 12)) { + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate) && + gst_structure_get_int (structure, "channels", &spec->channels))) + goto parse_error; + + spec->type = GST_BUFTYPE_A_LAW; + spec->format = GST_A_LAW; + spec->width = 8; + spec->depth = 8; + for (i = 0; i < spec->channels; i++) + spec->silence_sample[i] = 0xd5; + } else if (!strncmp (mimetype, "audio/x-mulaw", 13)) { + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate) && + gst_structure_get_int (structure, "channels", &spec->channels))) + goto parse_error; + + spec->type = GST_BUFTYPE_MU_LAW; + spec->format = GST_MU_LAW; + spec->width = 8; + spec->depth = 8; + for (i = 0; i < spec->channels; i++) + spec->silence_sample[i] = 0xff; + } else if (!strncmp (mimetype, "audio/x-iec958", 14)) { + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate))) + goto parse_error; + + spec->type = GST_BUFTYPE_IEC958; + spec->format = GST_IEC958; + spec->width = 16; + spec->depth = 16; + spec->channels = 2; + } else if (!strncmp (mimetype, "audio/x-ac3", 11)) { + /* extract the needed information from the cap */ + if (!(gst_structure_get_int (structure, "rate", &spec->rate))) + goto parse_error; + + spec->type = GST_BUFTYPE_AC3; + spec->format = GST_AC3; + spec->width = 16; + spec->depth = 16; + spec->channels = 2; + } else { + goto parse_error; + } + + spec->bytes_per_sample = (spec->width >> 3) * spec->channels; + + gst_caps_replace (&spec->caps, caps); + + g_return_val_if_fail (spec->latency_time != 0, FALSE); + + /* calculate suggested segsize and segtotal. segsize should be one unit + * of 'latency_time' samples, scaling for the fact that latency_time is + * currently stored in microseconds (FIXME: in 0.11) */ + spec->segsize = gst_util_uint64_scale (spec->rate * spec->bytes_per_sample, + spec->latency_time, GST_SECOND / GST_USECOND); + /* Round to an integer number of samples */ + spec->segsize -= spec->segsize % spec->bytes_per_sample; + + spec->segtotal = spec->buffer_time / spec->latency_time; + /* leave the latency undefined now, implementations can change it but if it's + * not changed, we assume the same value as segtotal */ + spec->seglatency = -1; + + gst_ring_buffer_debug_spec_caps (spec); + gst_ring_buffer_debug_spec_buff (spec); + + return TRUE; + + /* ERRORS */ +parse_error: + { + GST_DEBUG ("could not parse caps"); + return FALSE; + } +} + +/** + * gst_ring_buffer_convert: + * @buf: the #GstRingBuffer + * @src_fmt: the source format + * @src_val: the source value + * @dest_fmt: the destination format + * @dest_val: a location to store the converted value + * + * Convert @src_val in @src_fmt to the equivalent value in @dest_fmt. The result + * will be put in @dest_val. + * + * Returns: TRUE if the conversion succeeded. + * + * Since: 0.10.22. + */ +gboolean +gst_ring_buffer_convert (GstRingBuffer * buf, + GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val) +{ + gboolean res = TRUE; + gint bps, rate; + + GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)", + src_val, gst_format_get_name (src_fmt), src_fmt, + gst_format_get_name (dest_fmt), dest_fmt); + + if (src_fmt == dest_fmt || src_val == -1) { + *dest_val = src_val; + goto done; + } + + /* get important info */ + GST_OBJECT_LOCK (buf); + bps = buf->spec.bytes_per_sample; + rate = buf->spec.rate; + GST_OBJECT_UNLOCK (buf); + + if (bps == 0 || rate == 0) { + GST_DEBUG ("no rate or bps configured"); + res = FALSE; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_BYTES: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = gst_util_uint64_scale_int (src_val / bps, GST_SECOND, + rate); + break; + case GST_FORMAT_DEFAULT: + *dest_val = src_val / bps; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, rate); + break; + case GST_FORMAT_BYTES: + *dest_val = src_val * bps; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND); + break; + case GST_FORMAT_BYTES: + *dest_val = gst_util_uint64_scale_int (src_val, rate, GST_SECOND); + *dest_val *= bps; + break; + default: + res = FALSE; + break; + } + break; + default: + res = FALSE; + break; + } +done: + GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val); + + return res; +} + +/** + * gst_ring_buffer_set_callback: + * @buf: the #GstRingBuffer to set the callback on + * @cb: the callback to set + * @user_data: user data passed to the callback + * + * Sets the given callback function on the buffer. This function + * will be called every time a segment has been written to a device. + * + * MT safe. + */ +void +gst_ring_buffer_set_callback (GstRingBuffer * buf, GstRingBufferCallback cb, + gpointer user_data) +{ + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + GST_OBJECT_LOCK (buf); + buf->callback = cb; + buf->cb_data = user_data; + GST_OBJECT_UNLOCK (buf); +} + + +/** + * gst_ring_buffer_open_device: + * @buf: the #GstRingBuffer + * + * Open the audio device associated with the ring buffer. Does not perform any + * setup on the device. You must open the device before acquiring the ring + * buffer. + * + * Returns: TRUE if the device could be opened, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_open_device (GstRingBuffer * buf) +{ + gboolean res = TRUE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "opening device"); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (buf->open)) + goto was_opened; + + buf->open = TRUE; + + /* if this fails, something is wrong in this file */ + g_assert (!buf->acquired); + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->open_device)) + res = rclass->open_device (buf); + + if (G_UNLIKELY (!res)) + goto open_failed; + + GST_DEBUG_OBJECT (buf, "opened device"); + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +was_opened: + { + GST_DEBUG_OBJECT (buf, "Device for ring buffer already open"); + g_warning ("Device for ring buffer %p already open, fix your code", buf); + res = TRUE; + goto done; + } +open_failed: + { + buf->open = FALSE; + GST_DEBUG_OBJECT (buf, "failed opening device"); + goto done; + } +} + +/** + * gst_ring_buffer_close_device: + * @buf: the #GstRingBuffer + * + * Close the audio device associated with the ring buffer. The ring buffer + * should already have been released via gst_ring_buffer_release(). + * + * Returns: TRUE if the device could be closed, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_close_device (GstRingBuffer * buf) +{ + gboolean res = TRUE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "closing device"); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (!buf->open)) + goto was_closed; + + if (G_UNLIKELY (buf->acquired)) + goto was_acquired; + + buf->open = FALSE; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->close_device)) + res = rclass->close_device (buf); + + if (G_UNLIKELY (!res)) + goto close_error; + + GST_DEBUG_OBJECT (buf, "closed device"); + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +was_closed: + { + GST_DEBUG_OBJECT (buf, "Device for ring buffer already closed"); + g_warning ("Device for ring buffer %p already closed, fix your code", buf); + res = TRUE; + goto done; + } +was_acquired: + { + GST_DEBUG_OBJECT (buf, "Resources for ring buffer still acquired"); + g_critical ("Resources for ring buffer %p still acquired", buf); + res = FALSE; + goto done; + } +close_error: + { + buf->open = TRUE; + GST_DEBUG_OBJECT (buf, "error closing device"); + goto done; + } +} + +/** + * gst_ring_buffer_device_is_open: + * @buf: the #GstRingBuffer + * + * Checks the status of the device associated with the ring buffer. + * + * Returns: TRUE if the device was open, FALSE if it was closed. + * + * MT safe. + */ +gboolean +gst_ring_buffer_device_is_open (GstRingBuffer * buf) +{ + gboolean res = TRUE; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_OBJECT_LOCK (buf); + res = buf->open; + GST_OBJECT_UNLOCK (buf); + + return res; +} + +/** + * gst_ring_buffer_acquire: + * @buf: the #GstRingBuffer to acquire + * @spec: the specs of the buffer + * + * Allocate the resources for the ringbuffer. This function fills + * in the data pointer of the ring buffer with a valid #GstBuffer + * to which samples can be written. + * + * Returns: TRUE if the device could be acquired, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + gint i, j; + gint segsize, bps; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "acquiring device %p", buf); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (!buf->open)) + goto not_opened; + + if (G_UNLIKELY (buf->acquired)) + goto was_acquired; + + buf->acquired = TRUE; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->acquire)) + res = rclass->acquire (buf, spec); + + if (G_UNLIKELY (!res)) + goto acquire_failed; + + if (G_UNLIKELY ((bps = buf->spec.bytes_per_sample) == 0)) + goto invalid_bps; + + /* if the seglatency was overwritten with something else than -1, use it, else + * assume segtotal as the latency */ + if (buf->spec.seglatency == -1) + buf->spec.seglatency = buf->spec.segtotal; + + segsize = buf->spec.segsize; + + buf->samples_per_seg = segsize / bps; + + /* create an empty segment */ + g_free (buf->empty_seg); + buf->empty_seg = g_malloc (segsize); + + /* FIXME, we only have 32 silence samples, which might not be enough to + * represent silence in all channels */ + bps = MIN (bps, 32); + for (i = 0, j = 0; i < segsize; i++) { + buf->empty_seg[i] = buf->spec.silence_sample[j]; + j = (j + 1) % bps; + } + GST_DEBUG_OBJECT (buf, "acquired device"); + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +not_opened: + { + GST_DEBUG_OBJECT (buf, "device not opened"); + g_critical ("Device for %p not opened", buf); + res = FALSE; + goto done; + } +was_acquired: + { + res = TRUE; + GST_DEBUG_OBJECT (buf, "device was acquired"); + goto done; + } +acquire_failed: + { + buf->acquired = FALSE; + GST_DEBUG_OBJECT (buf, "failed to acquire device"); + goto done; + } +invalid_bps: + { + g_warning + ("invalid bytes_per_sample from acquire ringbuffer %p, fix the element", + buf); + buf->acquired = FALSE; + res = FALSE; + goto done; + } +} + +/** + * gst_ring_buffer_release: + * @buf: the #GstRingBuffer to release + * + * Free the resources of the ringbuffer. + * + * Returns: TRUE if the device could be released, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_release (GstRingBuffer * buf) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "releasing device"); + + gst_ring_buffer_stop (buf); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (!buf->acquired)) + goto was_released; + + buf->acquired = FALSE; + + /* if this fails, something is wrong in this file */ + g_assert (buf->open == TRUE); + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->release)) + res = rclass->release (buf); + + /* signal any waiters */ + GST_DEBUG_OBJECT (buf, "signal waiter"); + GST_RING_BUFFER_SIGNAL (buf); + + if (G_UNLIKELY (!res)) + goto release_failed; + + g_free (buf->empty_seg); + buf->empty_seg = NULL; + GST_DEBUG_OBJECT (buf, "released device"); + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +was_released: + { + res = TRUE; + GST_DEBUG_OBJECT (buf, "device was released"); + goto done; + } +release_failed: + { + buf->acquired = TRUE; + GST_DEBUG_OBJECT (buf, "failed to release device"); + goto done; + } +} + +/** + * gst_ring_buffer_is_acquired: + * @buf: the #GstRingBuffer to check + * + * Check if the ringbuffer is acquired and ready to use. + * + * Returns: TRUE if the ringbuffer is acquired, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_is_acquired (GstRingBuffer * buf) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_OBJECT_LOCK (buf); + res = buf->acquired; + GST_OBJECT_UNLOCK (buf); + + return res; +} + +/** + * gst_ring_buffer_activate: + * @buf: the #GstRingBuffer to activate + * @active: the new mode + * + * Activate @buf to start or stop pulling data. + * + * MT safe. + * + * Returns: TRUE if the device could be activated in the requested mode, + * FALSE on error. + * + * Since: 0.10.22. + */ +gboolean +gst_ring_buffer_activate (GstRingBuffer * buf, gboolean active) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "activate device"); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (active && !buf->acquired)) + goto not_acquired; + + if (G_UNLIKELY (buf->abidata.ABI.active == active)) + goto was_active; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + /* if there is no activate function we assume it was started/released + * in the acquire method */ + if (G_LIKELY (rclass->activate)) + res = rclass->activate (buf, active); + else + res = TRUE; + + if (G_UNLIKELY (!res)) + goto activate_failed; + + buf->abidata.ABI.active = active; + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +not_acquired: + { + GST_DEBUG_OBJECT (buf, "device not acquired"); + g_critical ("Device for %p not acquired", buf); + res = FALSE; + goto done; + } +was_active: + { + res = TRUE; + GST_DEBUG_OBJECT (buf, "device was active in mode %d", active); + goto done; + } +activate_failed: + { + GST_DEBUG_OBJECT (buf, "failed to activate device"); + goto done; + } +} + +/** + * gst_ring_buffer_is_active: + * @buf: the #GstRingBuffer + * + * Check if @buf is activated. + * + * MT safe. + * + * Returns: TRUE if the device is active. + * + * Since: 0.10.22. + */ +gboolean +gst_ring_buffer_is_active (GstRingBuffer * buf) +{ + gboolean res; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_OBJECT_LOCK (buf); + res = buf->abidata.ABI.active; + GST_OBJECT_UNLOCK (buf); + + return res; +} + + +/** + * gst_ring_buffer_set_flushing: + * @buf: the #GstRingBuffer to flush + * @flushing: the new mode + * + * Set the ringbuffer to flushing mode or normal mode. + * + * MT safe. + */ +void +gst_ring_buffer_set_flushing (GstRingBuffer * buf, gboolean flushing) +{ + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + GST_OBJECT_LOCK (buf); + buf->abidata.ABI.flushing = flushing; + + if (flushing) { + gst_ring_buffer_pause_unlocked (buf); + } else { + gst_ring_buffer_clear_all (buf); + } + GST_OBJECT_UNLOCK (buf); +} + +/** + * gst_ring_buffer_start: + * @buf: the #GstRingBuffer to start + * + * Start processing samples from the ringbuffer. + * + * Returns: TRUE if the device could be started, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_start (GstRingBuffer * buf) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + gboolean resume = FALSE; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "starting ringbuffer"); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (buf->abidata.ABI.flushing)) + goto flushing; + + if (G_UNLIKELY (!buf->acquired)) + goto not_acquired; + + if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE)) + goto may_not_start; + + /* if stopped, set to started */ + res = g_atomic_int_compare_and_exchange (&buf->state, + GST_RING_BUFFER_STATE_STOPPED, GST_RING_BUFFER_STATE_STARTED); + + if (!res) { + GST_DEBUG_OBJECT (buf, "was not stopped, try paused"); + /* was not stopped, try from paused */ + res = g_atomic_int_compare_and_exchange (&buf->state, + GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STARTED); + if (!res) { + /* was not paused either, must be started then */ + res = TRUE; + GST_DEBUG_OBJECT (buf, "was not paused, must have been started"); + goto done; + } + resume = TRUE; + GST_DEBUG_OBJECT (buf, "resuming"); + } + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (resume) { + if (G_LIKELY (rclass->resume)) + res = rclass->resume (buf); + } else { + if (G_LIKELY (rclass->start)) + res = rclass->start (buf); + } + + if (G_UNLIKELY (!res)) { + buf->state = GST_RING_BUFFER_STATE_PAUSED; + GST_DEBUG_OBJECT (buf, "failed to start"); + } else { + GST_DEBUG_OBJECT (buf, "started"); + } + +done: + GST_OBJECT_UNLOCK (buf); + + return res; + +flushing: + { + GST_DEBUG_OBJECT (buf, "we are flushing"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +not_acquired: + { + GST_DEBUG_OBJECT (buf, "we are not acquired"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +may_not_start: + { + GST_DEBUG_OBJECT (buf, "we may not start"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +} + +static gboolean +gst_ring_buffer_pause_unlocked (GstRingBuffer * buf) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + + GST_DEBUG_OBJECT (buf, "pausing ringbuffer"); + + /* if started, set to paused */ + res = g_atomic_int_compare_and_exchange (&buf->state, + GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_PAUSED); + + if (!res) + goto not_started; + + /* signal any waiters */ + GST_DEBUG_OBJECT (buf, "signal waiter"); + GST_RING_BUFFER_SIGNAL (buf); + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->pause)) + res = rclass->pause (buf); + + if (G_UNLIKELY (!res)) { + buf->state = GST_RING_BUFFER_STATE_STARTED; + GST_DEBUG_OBJECT (buf, "failed to pause"); + } else { + GST_DEBUG_OBJECT (buf, "paused"); + } + + return res; + +not_started: + { + /* was not started */ + GST_DEBUG_OBJECT (buf, "was not started"); + return TRUE; + } +} + +/** + * gst_ring_buffer_pause: + * @buf: the #GstRingBuffer to pause + * + * Pause processing samples from the ringbuffer. + * + * Returns: TRUE if the device could be paused, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_pause (GstRingBuffer * buf) +{ + gboolean res = FALSE; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (buf->abidata.ABI.flushing)) + goto flushing; + + if (G_UNLIKELY (!buf->acquired)) + goto not_acquired; + + res = gst_ring_buffer_pause_unlocked (buf); + GST_OBJECT_UNLOCK (buf); + + return res; + + /* ERRORS */ +flushing: + { + GST_DEBUG_OBJECT (buf, "we are flushing"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +not_acquired: + { + GST_DEBUG_OBJECT (buf, "not acquired"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +} + +/** + * gst_ring_buffer_stop: + * @buf: the #GstRingBuffer to stop + * + * Stop processing samples from the ringbuffer. + * + * Returns: TRUE if the device could be stopped, FALSE on error. + * + * MT safe. + */ +gboolean +gst_ring_buffer_stop (GstRingBuffer * buf) +{ + gboolean res = FALSE; + GstRingBufferClass *rclass; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + GST_DEBUG_OBJECT (buf, "stopping"); + + GST_OBJECT_LOCK (buf); + + /* if started, set to stopped */ + res = g_atomic_int_compare_and_exchange (&buf->state, + GST_RING_BUFFER_STATE_STARTED, GST_RING_BUFFER_STATE_STOPPED); + + if (!res) { + GST_DEBUG_OBJECT (buf, "was not started, try paused"); + /* was not started, try from paused */ + res = g_atomic_int_compare_and_exchange (&buf->state, + GST_RING_BUFFER_STATE_PAUSED, GST_RING_BUFFER_STATE_STOPPED); + if (!res) { + /* was not paused either, must have been stopped then */ + res = TRUE; + GST_DEBUG_OBJECT (buf, "was not paused, must have been stopped"); + goto done; + } + } + + /* signal any waiters */ + GST_DEBUG_OBJECT (buf, "signal waiter"); + GST_RING_BUFFER_SIGNAL (buf); + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->stop)) + res = rclass->stop (buf); + + if (G_UNLIKELY (!res)) { + buf->state = GST_RING_BUFFER_STATE_STARTED; + GST_DEBUG_OBJECT (buf, "failed to stop"); + } else { + GST_DEBUG_OBJECT (buf, "stopped"); + } +done: + GST_OBJECT_UNLOCK (buf); + + return res; +} + +/** + * gst_ring_buffer_delay: + * @buf: the #GstRingBuffer to query + * + * Get the number of samples queued in the audio device. This is + * usually less than the segment size but can be bigger when the + * implementation uses another internal buffer between the audio + * device. + * + * For playback ringbuffers this is the amount of samples transfered from the + * ringbuffer to the device but still not played. + * + * For capture ringbuffers this is the amount of samples in the device that are + * not yet transfered to the ringbuffer. + * + * Returns: The number of samples queued in the audio device. + * + * MT safe. + */ +guint +gst_ring_buffer_delay (GstRingBuffer * buf) +{ + GstRingBufferClass *rclass; + guint res; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0); + + /* buffer must be acquired */ + if (G_UNLIKELY (!gst_ring_buffer_is_acquired (buf))) + goto not_acquired; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + if (G_LIKELY (rclass->delay)) + res = rclass->delay (buf); + else + res = 0; + + return res; + +not_acquired: + { + GST_DEBUG_OBJECT (buf, "not acquired"); + return 0; + } +} + +/** + * gst_ring_buffer_samples_done: + * @buf: the #GstRingBuffer to query + * + * Get the number of samples that were processed by the ringbuffer + * since it was last started. This does not include the number of samples not + * yet processed (see gst_ring_buffer_delay()). + * + * Returns: The number of samples processed by the ringbuffer. + * + * MT safe. + */ +guint64 +gst_ring_buffer_samples_done (GstRingBuffer * buf) +{ + gint segdone; + guint64 samples; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), 0); + + /* get the amount of segments we processed */ + segdone = g_atomic_int_get (&buf->segdone); + + /* convert to samples */ + samples = ((guint64) segdone) * buf->samples_per_seg; + + return samples; +} + +/** + * gst_ring_buffer_set_sample: + * @buf: the #GstRingBuffer to use + * @sample: the sample number to set + * + * Make sure that the next sample written to the device is + * accounted for as being the @sample sample written to the + * device. This value will be used in reporting the current + * sample position of the ringbuffer. + * + * This function will also clear the buffer with silence. + * + * MT safe. + */ +void +gst_ring_buffer_set_sample (GstRingBuffer * buf, guint64 sample) +{ + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + if (sample == -1) + sample = 0; + + if (G_UNLIKELY (buf->samples_per_seg == 0)) + return; + + /* FIXME, we assume the ringbuffer can restart at a random + * position, round down to the beginning and keep track of + * offset when calculating the processed samples. */ + buf->segbase = buf->segdone - sample / buf->samples_per_seg; + + gst_ring_buffer_clear_all (buf); + + GST_DEBUG_OBJECT (buf, "set sample to %" G_GUINT64_FORMAT ", segbase %d", + sample, buf->segbase); +} + +static void +default_clear_all (GstRingBuffer * buf) +{ + gint i; + + /* not fatal, we just are not negotiated yet */ + if (G_UNLIKELY (buf->spec.segtotal <= 0)) + return; + + GST_DEBUG_OBJECT (buf, "clear all segments"); + + for (i = 0; i < buf->spec.segtotal; i++) { + gst_ring_buffer_clear (buf, i); + } +} + +/** + * gst_ring_buffer_clear_all: + * @buf: the #GstRingBuffer to clear + * + * Fill the ringbuffer with silence. + * + * MT safe. + */ +void +gst_ring_buffer_clear_all (GstRingBuffer * buf) +{ + GstRingBufferClass *rclass; + + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + + if (G_LIKELY (rclass->clear_all)) + rclass->clear_all (buf); +} + + +static gboolean +wait_segment (GstRingBuffer * buf) +{ + gint segments; + gboolean wait = TRUE; + + /* buffer must be started now or we deadlock since nobody is reading */ + if (G_UNLIKELY (g_atomic_int_get (&buf->state) != + GST_RING_BUFFER_STATE_STARTED)) { + /* see if we are allowed to start it */ + if (G_UNLIKELY (g_atomic_int_get (&buf->abidata.ABI.may_start) == FALSE)) + goto no_start; + + GST_DEBUG_OBJECT (buf, "start!"); + segments = g_atomic_int_get (&buf->segdone); + gst_ring_buffer_start (buf); + + /* After starting, the writer may have wrote segments already and then we + * don't need to wait anymore */ + if (G_LIKELY (g_atomic_int_get (&buf->segdone) != segments)) + wait = FALSE; + } + + /* take lock first, then update our waiting flag */ + GST_OBJECT_LOCK (buf); + if (G_UNLIKELY (buf->abidata.ABI.flushing)) + goto flushing; + + if (G_UNLIKELY (g_atomic_int_get (&buf->state) != + GST_RING_BUFFER_STATE_STARTED)) + goto not_started; + + if (G_LIKELY (wait)) { + if (g_atomic_int_compare_and_exchange (&buf->waiting, 0, 1)) { + GST_DEBUG_OBJECT (buf, "waiting.."); + GST_RING_BUFFER_WAIT (buf); + + if (G_UNLIKELY (buf->abidata.ABI.flushing)) + goto flushing; + + if (G_UNLIKELY (g_atomic_int_get (&buf->state) != + GST_RING_BUFFER_STATE_STARTED)) + goto not_started; + } + } + GST_OBJECT_UNLOCK (buf); + + return TRUE; + + /* ERROR */ +not_started: + { + g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0); + GST_DEBUG_OBJECT (buf, "stopped processing"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +flushing: + { + g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0); + GST_DEBUG_OBJECT (buf, "flushing"); + GST_OBJECT_UNLOCK (buf); + return FALSE; + } +no_start: + { + GST_DEBUG_OBJECT (buf, "not allowed to start"); + return FALSE; + } +} + +#define FWD_SAMPLES(s,se,d,de) \ +G_STMT_START { \ + /* no rate conversion */ \ + guint towrite = MIN (se + bps - s, de - d); \ + /* simple copy */ \ + if (!skip) \ + memcpy (d, s, towrite); \ + in_samples -= towrite / bps; \ + out_samples -= towrite / bps; \ + s += towrite; \ + GST_DEBUG ("copy %u bytes", towrite); \ +} G_STMT_END + +/* in_samples >= out_samples, rate > 1.0 */ +#define FWD_UP_SAMPLES(s,se,d,de) \ +G_STMT_START { \ + guint8 *sb = s, *db = d; \ + while (s <= se && d < de) { \ + if (!skip) \ + memcpy (d, s, bps); \ + s += bps; \ + *accum += outr; \ + if ((*accum << 1) >= inr) { \ + *accum -= inr; \ + d += bps; \ + } \ + } \ + in_samples -= (s - sb)/bps; \ + out_samples -= (d - db)/bps; \ + GST_DEBUG ("fwd_up end %d/%d",*accum,*toprocess); \ +} G_STMT_END + +/* out_samples > in_samples, for rates smaller than 1.0 */ +#define FWD_DOWN_SAMPLES(s,se,d,de) \ +G_STMT_START { \ + guint8 *sb = s, *db = d; \ + while (s <= se && d < de) { \ + if (!skip) \ + memcpy (d, s, bps); \ + d += bps; \ + *accum += inr; \ + if ((*accum << 1) >= outr) { \ + *accum -= outr; \ + s += bps; \ + } \ + } \ + in_samples -= (s - sb)/bps; \ + out_samples -= (d - db)/bps; \ + GST_DEBUG ("fwd_down end %d/%d",*accum,*toprocess); \ +} G_STMT_END + +#define REV_UP_SAMPLES(s,se,d,de) \ +G_STMT_START { \ + guint8 *sb = se, *db = d; \ + while (s <= se && d < de) { \ + if (!skip) \ + memcpy (d, se, bps); \ + se -= bps; \ + *accum += outr; \ + while (d < de && (*accum << 1) >= inr) { \ + *accum -= inr; \ + d += bps; \ + } \ + } \ + in_samples -= (sb - se)/bps; \ + out_samples -= (d - db)/bps; \ + GST_DEBUG ("rev_up end %d/%d",*accum,*toprocess); \ +} G_STMT_END + +#define REV_DOWN_SAMPLES(s,se,d,de) \ +G_STMT_START { \ + guint8 *sb = se, *db = d; \ + while (s <= se && d < de) { \ + if (!skip) \ + memcpy (d, se, bps); \ + d += bps; \ + *accum += inr; \ + while (s <= se && (*accum << 1) >= outr) { \ + *accum -= outr; \ + se -= bps; \ + } \ + } \ + in_samples -= (sb - se)/bps; \ + out_samples -= (d - db)/bps; \ + GST_DEBUG ("rev_down end %d/%d",*accum,*toprocess); \ +} G_STMT_END + +static guint +default_commit (GstRingBuffer * buf, guint64 * sample, + guchar * data, gint in_samples, gint out_samples, gint * accum) +{ + gint segdone; + gint segsize, segtotal, bps, sps; + guint8 *dest, *data_end; + gint writeseg, sampleoff; + gint *toprocess; + gint inr, outr; + gboolean reverse; + + g_return_val_if_fail (buf->data != NULL, -1); + g_return_val_if_fail (data != NULL, -1); + + dest = GST_BUFFER_DATA (buf->data); + segsize = buf->spec.segsize; + segtotal = buf->spec.segtotal; + bps = buf->spec.bytes_per_sample; + sps = buf->samples_per_seg; + + reverse = out_samples < 0; + out_samples = ABS (out_samples); + + if (in_samples >= out_samples) + toprocess = &in_samples; + else + toprocess = &out_samples; + + inr = in_samples - 1; + outr = out_samples - 1; + + /* data_end points to the last sample we have to write, not past it. This is + * needed to properly handle reverse playback: it points to the last sample. */ + data_end = data + (bps * inr); + + /* figure out the segment and the offset inside the segment where + * the first sample should be written. */ + writeseg = *sample / sps; + sampleoff = (*sample % sps) * bps; + + /* write out all samples */ + while (*toprocess > 0) { + gint avail; + guint8 *d, *d_end; + gint ws; + gboolean skip; + + while (TRUE) { + gint diff; + + /* get the currently processed segment */ + segdone = g_atomic_int_get (&buf->segdone) - buf->segbase; + + /* see how far away it is from the write segment */ + diff = writeseg - segdone; + + GST_DEBUG + ("pointer at %d, write to %d-%d, diff %d, segtotal %d, segsize %d, base %d", + segdone, writeseg, sampleoff, diff, segtotal, segsize, buf->segbase); + + /* segment too far ahead, writer too slow, we need to drop, hopefully UNLIKELY */ + if (G_UNLIKELY (diff < 0)) { + /* we need to drop one segment at a time, pretend we wrote a + * segment. */ + skip = TRUE; + break; + } + + /* write segment is within writable range, we can break the loop and + * start writing the data. */ + if (diff < segtotal) { + skip = FALSE; + break; + } + + /* else we need to wait for the segment to become writable. */ + if (!wait_segment (buf)) + goto not_started; + } + + /* we can write now */ + ws = writeseg % segtotal; + avail = MIN (segsize - sampleoff, bps * out_samples); + + d = dest + (ws * segsize) + sampleoff; + d_end = d + avail; + *sample += avail / bps; + + GST_DEBUG_OBJECT (buf, "write @%p seg %d, sps %d, off %d, avail %d", + dest + ws * segsize, ws, sps, sampleoff, avail); + + if (G_LIKELY (inr == outr && !reverse)) { + /* no rate conversion, simply copy samples */ + FWD_SAMPLES (data, data_end, d, d_end); + } else if (!reverse) { + if (inr >= outr) + /* forward speed up */ + FWD_UP_SAMPLES (data, data_end, d, d_end); + else + /* forward slow down */ + FWD_DOWN_SAMPLES (data, data_end, d, d_end); + } else { + if (inr >= outr) + /* reverse speed up */ + REV_UP_SAMPLES (data, data_end, d, d_end); + else + /* reverse slow down */ + REV_DOWN_SAMPLES (data, data_end, d, d_end); + } + + /* for the next iteration we write to the next segment at the beginning. */ + writeseg++; + sampleoff = 0; + } + /* we consumed all samples here */ + data = data_end + bps; + +done: + return inr - ((data_end - data) / bps); + + /* ERRORS */ +not_started: + { + GST_DEBUG_OBJECT (buf, "stopped processing"); + goto done; + } +} + +/** + * gst_ring_buffer_commit_full: + * @buf: the #GstRingBuffer to commit + * @sample: the sample position of the data + * @data: the data to commit + * @in_samples: the number of samples in the data to commit + * @out_samples: the number of samples to write to the ringbuffer + * @accum: accumulator for rate conversion. + * + * Commit @in_samples samples pointed to by @data to the ringbuffer @buf. + * + * @in_samples and @out_samples define the rate conversion to perform on the the + * samples in @data. For negative rates, @out_samples must be negative and + * @in_samples positive. + * + * When @out_samples is positive, the first sample will be written at position @sample + * in the ringbuffer. When @out_samples is negative, the last sample will be written to + * @sample in reverse order. + * + * @out_samples does not need to be a multiple of the segment size of the ringbuffer + * although it is recommended for optimal performance. + * + * @accum will hold a temporary accumulator used in rate conversion and should be + * set to 0 when this function is first called. In case the commit operation is + * interrupted, one can resume the processing by passing the previously returned + * @accum value back to this function. + * + * MT safe. + * + * Returns: The number of samples written to the ringbuffer or -1 on error. The + * number of samples written can be less than @out_samples when @buf was interrupted + * with a flush or stop. + * + * Since: 0.10.11. + */ +guint +gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 * sample, + guchar * data, gint in_samples, gint out_samples, gint * accum) +{ + GstRingBufferClass *rclass; + guint res = -1; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1); + + if (G_UNLIKELY (in_samples == 0 || out_samples == 0)) + return in_samples; + + rclass = GST_RING_BUFFER_GET_CLASS (buf); + + if (G_LIKELY (rclass->commit)) + res = rclass->commit (buf, sample, data, in_samples, out_samples, accum); + + return res; +} + +/** + * gst_ring_buffer_commit: + * @buf: the #GstRingBuffer to commit + * @sample: the sample position of the data + * @data: the data to commit + * @len: the number of samples in the data to commit + * + * Same as gst_ring_buffer_commit_full() but with a in_samples and out_samples + * equal to @len, ignoring accum. + * + * Returns: The number of samples written to the ringbuffer or -1 on + * error. + * + * MT safe. + */ +guint +gst_ring_buffer_commit (GstRingBuffer * buf, guint64 sample, guchar * data, + guint len) +{ + guint res; + guint64 samplep = sample; + + res = gst_ring_buffer_commit_full (buf, &samplep, data, len, len, NULL); + + return res; +} + +/** + * gst_ring_buffer_read: + * @buf: the #GstRingBuffer to read from + * @sample: the sample position of the data + * @data: where the data should be read + * @len: the number of samples in data to read + * + * Read @len samples from the ringbuffer into the memory pointed + * to by @data. + * The first sample should be read from position @sample in + * the ringbuffer. + * + * @len should not be a multiple of the segment size of the ringbuffer + * although it is recommended. + * + * Returns: The number of samples read from the ringbuffer or -1 on + * error. + * + * MT safe. + */ +guint +gst_ring_buffer_read (GstRingBuffer * buf, guint64 sample, guchar * data, + guint len) +{ + gint segdone; + gint segsize, segtotal, bps, sps; + guint8 *dest; + guint to_read; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), -1); + g_return_val_if_fail (buf->data != NULL, -1); + g_return_val_if_fail (data != NULL, -1); + + dest = GST_BUFFER_DATA (buf->data); + segsize = buf->spec.segsize; + segtotal = buf->spec.segtotal; + bps = buf->spec.bytes_per_sample; + sps = buf->samples_per_seg; + + to_read = len; + /* read enough samples */ + while (to_read > 0) { + gint sampleslen; + gint readseg, sampleoff; + + /* figure out the segment and the offset inside the segment where + * the sample should be read from. */ + readseg = sample / sps; + sampleoff = (sample % sps); + + while (TRUE) { + gint diff; + + /* get the currently processed segment */ + segdone = g_atomic_int_get (&buf->segdone) - buf->segbase; + + /* see how far away it is from the read segment, normally segdone (where + * the hardware is writing) is bigger than readseg (where software is + * reading) */ + diff = segdone - readseg; + + GST_DEBUG + ("pointer at %d, sample %" G_GUINT64_FORMAT + ", read from %d-%d, to_read %d, diff %d, segtotal %d, segsize %d", + segdone, sample, readseg, sampleoff, to_read, diff, segtotal, + segsize); + + /* segment too far ahead, reader too slow */ + if (G_UNLIKELY (diff >= segtotal)) { + /* pretend we read an empty segment. */ + sampleslen = MIN (sps, to_read); + memcpy (data, buf->empty_seg, sampleslen * bps); + goto next; + } + + /* read segment is within readable range, we can break the loop and + * start reading the data. */ + if (diff > 0) + break; + + /* else we need to wait for the segment to become readable. */ + if (!wait_segment (buf)) + goto not_started; + } + + /* we can read now */ + readseg = readseg % segtotal; + sampleslen = MIN (sps - sampleoff, to_read); + + GST_DEBUG_OBJECT (buf, "read @%p seg %d, off %d, sampleslen %d", + dest + readseg * segsize, readseg, sampleoff, sampleslen); + + memcpy (data, dest + (readseg * segsize) + (sampleoff * bps), + (sampleslen * bps)); + + next: + to_read -= sampleslen; + sample += sampleslen; + data += sampleslen * bps; + } + + return len - to_read; + + /* ERRORS */ +not_started: + { + GST_DEBUG_OBJECT (buf, "stopped processing"); + return len - to_read; + } +} + +/** + * gst_ring_buffer_prepare_read: + * @buf: the #GstRingBuffer to read from + * @segment: the segment to read + * @readptr: the pointer to the memory where samples can be read + * @len: the number of bytes to read + * + * Returns a pointer to memory where the data from segment @segment + * can be found. This function is mostly used by subclasses. + * + * Returns: FALSE if the buffer is not started. + * + * MT safe. + */ +gboolean +gst_ring_buffer_prepare_read (GstRingBuffer * buf, gint * segment, + guint8 ** readptr, gint * len) +{ + guint8 *data; + gint segdone; + + g_return_val_if_fail (GST_IS_RING_BUFFER (buf), FALSE); + + if (buf->callback == NULL) { + /* push mode, fail when nothing is started */ + if (g_atomic_int_get (&buf->state) != GST_RING_BUFFER_STATE_STARTED) + return FALSE; + } + + g_return_val_if_fail (buf->data != NULL, FALSE); + g_return_val_if_fail (segment != NULL, FALSE); + g_return_val_if_fail (readptr != NULL, FALSE); + g_return_val_if_fail (len != NULL, FALSE); + + data = GST_BUFFER_DATA (buf->data); + + /* get the position of the pointer */ + segdone = g_atomic_int_get (&buf->segdone); + + *segment = segdone % buf->spec.segtotal; + *len = buf->spec.segsize; + *readptr = data + *segment * *len; + + GST_LOG ("prepare read from segment %d (real %d) @%p", + *segment, segdone, *readptr); + + /* callback to fill the memory with data, for pull based + * scheduling. */ + if (buf->callback) + buf->callback (buf, *readptr, *len, buf->cb_data); + + return TRUE; +} + +/** + * gst_ring_buffer_advance: + * @buf: the #GstRingBuffer to advance + * @advance: the number of segments written + * + * Subclasses should call this function to notify the fact that + * @advance segments are now processed by the device. + * + * MT safe. + */ +void +gst_ring_buffer_advance (GstRingBuffer * buf, guint advance) +{ + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + /* update counter */ + g_atomic_int_add (&buf->segdone, advance); + + /* the lock is already taken when the waiting flag is set, + * we grab the lock as well to make sure the waiter is actually + * waiting for the signal */ + if (g_atomic_int_compare_and_exchange (&buf->waiting, 1, 0)) { + GST_OBJECT_LOCK (buf); + GST_DEBUG_OBJECT (buf, "signal waiter"); + GST_RING_BUFFER_SIGNAL (buf); + GST_OBJECT_UNLOCK (buf); + } +} + +/** + * gst_ring_buffer_clear: + * @buf: the #GstRingBuffer to clear + * @segment: the segment to clear + * + * Clear the given segment of the buffer with silence samples. + * This function is used by subclasses. + * + * MT safe. + */ +void +gst_ring_buffer_clear (GstRingBuffer * buf, gint segment) +{ + guint8 *data; + + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + /* no data means it's already cleared */ + if (G_UNLIKELY (buf->data == NULL)) + return; + + /* no empty_seg means it's not opened */ + if (G_UNLIKELY (buf->empty_seg == NULL)) + return; + + segment %= buf->spec.segtotal; + + data = GST_BUFFER_DATA (buf->data); + data += segment * buf->spec.segsize; + + GST_LOG ("clear segment %d @%p", segment, data); + + memcpy (data, buf->empty_seg, buf->spec.segsize); +} + +/** + * gst_ring_buffer_may_start: + * @buf: the #GstRingBuffer + * @allowed: the new value + * + * Tell the ringbuffer that it is allowed to start playback when + * the ringbuffer is filled with samples. + * + * MT safe. + * + * Since: 0.10.6 + */ +void +gst_ring_buffer_may_start (GstRingBuffer * buf, gboolean allowed) +{ + g_return_if_fail (GST_IS_RING_BUFFER (buf)); + + GST_LOG_OBJECT (buf, "may start: %d", allowed); + g_atomic_int_set (&buf->abidata.ABI.may_start, allowed); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.h new file mode 100644 index 0000000..1384d38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/gstringbuffer.h @@ -0,0 +1,408 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstringbuffer.h: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RING_BUFFER_H__ +#define __GST_RING_BUFFER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_RING_BUFFER (gst_ring_buffer_get_type()) +#define GST_RING_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RING_BUFFER,GstRingBuffer)) +#define GST_RING_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RING_BUFFER,GstRingBufferClass)) +#define GST_RING_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RING_BUFFER, GstRingBufferClass)) +#define GST_RING_BUFFER_CAST(obj) ((GstRingBuffer *)obj) +#define GST_IS_RING_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RING_BUFFER)) +#define GST_IS_RING_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RING_BUFFER)) + +typedef struct _GstRingBuffer GstRingBuffer; +typedef struct _GstRingBufferClass GstRingBufferClass; +typedef struct _GstRingBufferSpec GstRingBufferSpec; + +/** + * GstRingBufferCallback: + * @rbuf: a #GstRingBuffer + * @data: target to fill + * @len: amount to fill + * @user_data: user data + * + * This function is set with gst_ring_buffer_set_callback() and is + * called to fill the memory at @data with @len bytes of samples. + */ +typedef void (*GstRingBufferCallback) (GstRingBuffer *rbuf, guint8* data, guint len, gpointer user_data); + +/** + * GstRingBufferState: + * @GST_RING_BUFFER_STATE_STOPPED: The ringbuffer is stopped + * @GST_RING_BUFFER_STATE_PAUSED: The ringbuffer is paused + * @GST_RING_BUFFER_STATE_STARTED: The ringbuffer is started + * + * The state of the ringbuffer. + */ +typedef enum { + GST_RING_BUFFER_STATE_STOPPED, + GST_RING_BUFFER_STATE_PAUSED, + GST_RING_BUFFER_STATE_STARTED +} GstRingBufferState; + +/** + * GstRingBufferSegState: + * @GST_SEGSTATE_INVALID: The content of the segment is invalid + * @GST_SEGSTATE_EMPTY: The segment is empty + * @GST_SEGSTATE_FILLED: The segment contains valid data + * @GST_SEGSTATE_PARTIAL: The segment partially contains valid data + * + * The state of a segment in the ringbuffer. + */ +typedef enum { + GST_SEGSTATE_INVALID, + GST_SEGSTATE_EMPTY, + GST_SEGSTATE_FILLED, + GST_SEGSTATE_PARTIAL +} GstRingBufferSegState; + +/** + * GstBufferFormatType: + * @GST_BUFTYPE_LINEAR: samples in linear PCM + * @GST_BUFTYPE_FLOAT: samples in float + * @GST_BUFTYPE_MU_LAW: samples in mulaw + * @GST_BUFTYPE_A_LAW: samples in alaw + * @GST_BUFTYPE_IMA_ADPCM: samples in ima adpcm + * @GST_BUFTYPE_MPEG: samples in mpeg audio format + * @GST_BUFTYPE_GSM: samples in gsm format + * @GST_BUFTYPE_IEC958: samples in IEC958 frames (e.g. AC3) + * @GST_BUFTYPE_AC3: samples in AC3 format + * @GST_BUFTYPE_EAC3: samples in EAC3 format + * @GST_BUFTYPE_DTS: samples in DTS format + * + * The format of the samples in the ringbuffer. + */ +typedef enum +{ + GST_BUFTYPE_LINEAR, + GST_BUFTYPE_FLOAT, + GST_BUFTYPE_MU_LAW, + GST_BUFTYPE_A_LAW, + GST_BUFTYPE_IMA_ADPCM, + GST_BUFTYPE_MPEG, + GST_BUFTYPE_GSM, + GST_BUFTYPE_IEC958, + GST_BUFTYPE_AC3, + GST_BUFTYPE_EAC3, + GST_BUFTYPE_DTS +} GstBufferFormatType; + +typedef enum +{ + GST_UNKNOWN, + + GST_S8, + GST_U8, + + GST_S16_LE, + GST_S16_BE, + GST_U16_LE, + GST_U16_BE, + + GST_S24_LE, + GST_S24_BE, + GST_U24_LE, + GST_U24_BE, + + GST_S32_LE, + GST_S32_BE, + GST_U32_LE, + GST_U32_BE, + + GST_S24_3LE, + GST_S24_3BE, + GST_U24_3LE, + GST_U24_3BE, + GST_S20_3LE, + GST_S20_3BE, + GST_U20_3LE, + GST_U20_3BE, + GST_S18_3LE, + GST_S18_3BE, + GST_U18_3LE, + GST_U18_3BE, + + GST_FLOAT32_LE, + GST_FLOAT32_BE, + + GST_FLOAT64_LE, + GST_FLOAT64_BE, + + GST_MU_LAW, + GST_A_LAW, + GST_IMA_ADPCM, + GST_MPEG, + GST_GSM, + GST_IEC958, + GST_AC3, + GST_EAC3, + GST_DTS +} GstBufferFormat; + +/** + * GstRingBufferSpec: + * @caps: The caps that generated the Spec. + * @type: the sample type + * @format: the sample format + * @sign: the sample sign + * @bigend: the endianness of the samples + * @width: the width of the samples + * @depth: th depth of the samples + * @rate: the samplerate + * @channels: the number of channels + * @latency_time: the latency in microseconds + * @buffer_time: the total buffer size in microseconds + * @segsize: the size of one segment in bytes + * @segtotal: the total number of segments + * @bytes_per_sample: number of bytes in one sample + * @silence_sample: bytes representing one sample of silence + * @seglatency: number of segments queued in the lower level device, + * defaults to segtotal + * + * The structure containing the format specification of the ringbuffer. + */ +struct _GstRingBufferSpec +{ + /*< public >*/ + /* in */ + GstCaps *caps; /* the caps of the buffer */ + + /* in/out */ + GstBufferFormatType type; + GstBufferFormat format; + gboolean sign; + gboolean bigend; + gint width; + gint depth; + gint rate; + gint channels; + + guint64 latency_time; /* the required/actual latency time, this is the + * actual the size of one segment and the + * minimum possible latency we can achieve. */ + guint64 buffer_time; /* the required/actual time of the buffer, this is + * the total size of the buffer and maximum + * latency we can compensate for. */ + gint segsize; /* size of one buffer segment in bytes, this value + * should be chosen to match latency_time as + * well as possible. */ + gint segtotal; /* total number of segments, this value is the + * number of segments of @segsize and should be + * chosen so that it matches buffer_time as + * close as possible. */ + /* out */ + gint bytes_per_sample; /* number of bytes of one sample */ + guint8 silence_sample[32]; /* bytes representing silence */ + + /* ABI added 0.10.20 */ + gint seglatency; /* number of segments queued in the lower + * level device, defaults to segtotal. */ + + /*< private >*/ + /* gpointer _gst_reserved[GST_PADDING]; */ + guint8 _gst_reserved[(sizeof (gpointer) * GST_PADDING) - sizeof (gint)]; +}; + +#define GST_RING_BUFFER_GET_COND(buf) (((GstRingBuffer *)buf)->cond) +#define GST_RING_BUFFER_WAIT(buf) (g_cond_wait (GST_RING_BUFFER_GET_COND (buf), GST_OBJECT_GET_LOCK (buf))) +#define GST_RING_BUFFER_SIGNAL(buf) (g_cond_signal (GST_RING_BUFFER_GET_COND (buf))) +#define GST_RING_BUFFER_BROADCAST(buf)(g_cond_broadcast (GST_RING_BUFFER_GET_COND (buf))) + +/** + * GstRingBuffer: + * @cond: used to signal start/stop/pause/resume actions + * @open: boolean indicating that the ringbuffer is open + * @acquired: boolean indicating that the ringbuffer is acquired + * @data: data in the ringbuffer + * @spec: format and layout of the ringbuffer data + * @segstate: status of each segment in the ringbuffer (unused) + * @samples_per_seg: number of samples in one segment + * @empty_seg: pointer to memory holding one segment of silence samples + * @state: state of the buffer + * @segdone: readpointer in the ringbuffer + * @segbase: segment corresponding to segment 0 (unused) + * @waiting: is a reader or writer waiting for a free segment + * + * The ringbuffer base class structure. + */ +struct _GstRingBuffer { + GstObject object; + + /*< public >*/ /* with LOCK */ + GCond *cond; + gboolean open; + gboolean acquired; + GstBuffer *data; + GstRingBufferSpec spec; + GstRingBufferSegState *segstate; + gint samples_per_seg; + guint8 *empty_seg; + + /*< public >*/ /* ATOMIC */ + gint state; + gint segdone; + gint segbase; + gint waiting; + + /*< private >*/ + GstRingBufferCallback callback; + gpointer cb_data; + + /*< private >*/ + union { + struct { + gboolean flushing; + /* ATOMIC */ + gint may_start; + gboolean active; + } ABI; + /* adding + 0 to mark ABI change to be undone later */ + gpointer _gst_reserved[GST_PADDING + 0]; + } abidata; +}; + +/** + * GstRingBufferClass: + * @parent_class: parent class + * @open_device: open the device, don't set any params or allocate anything + * @acquire: allocate the resources for the ringbuffer using the given spec + * @release: free resources of the ringbuffer + * @close_device: close the device + * @start: start processing of samples + * @pause: pause processing of samples + * @resume: resume processing of samples after pause + * @stop: stop processing of samples + * @delay: get number of samples queued in device + * @activate: activate the thread that starts pulling and monitoring the + * consumed segments in the device. Since 0.10.22 + * @commit: write samples into the ringbuffer + * @clear_all: clear the entire ringbuffer Since 0.10.24 + * + * The vmethods that subclasses can override to implement the ringbuffer. + */ +struct _GstRingBufferClass { + GstObjectClass parent_class; + + /*< public >*/ + gboolean (*open_device) (GstRingBuffer *buf); + gboolean (*acquire) (GstRingBuffer *buf, GstRingBufferSpec *spec); + gboolean (*release) (GstRingBuffer *buf); + gboolean (*close_device) (GstRingBuffer *buf); + + gboolean (*start) (GstRingBuffer *buf); + gboolean (*pause) (GstRingBuffer *buf); + gboolean (*resume) (GstRingBuffer *buf); + gboolean (*stop) (GstRingBuffer *buf); + + guint (*delay) (GstRingBuffer *buf); + + /* ABI added */ + gboolean (*activate) (GstRingBuffer *buf, gboolean active); + + guint (*commit) (GstRingBuffer * buf, guint64 *sample, + guchar * data, gint in_samples, + gint out_samples, gint * accum); + + void (*clear_all) (GstRingBuffer * buf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 3]; +}; + +GType gst_ring_buffer_get_type(void); + +/* callback stuff */ +void gst_ring_buffer_set_callback (GstRingBuffer *buf, GstRingBufferCallback cb, + gpointer user_data); + +gboolean gst_ring_buffer_parse_caps (GstRingBufferSpec *spec, GstCaps *caps); +void gst_ring_buffer_debug_spec_caps (GstRingBufferSpec *spec); +void gst_ring_buffer_debug_spec_buff (GstRingBufferSpec *spec); + +gboolean gst_ring_buffer_convert (GstRingBuffer * buf, GstFormat src_fmt, + gint64 src_val, GstFormat dest_fmt, + gint64 * dest_val); + +/* device state */ +gboolean gst_ring_buffer_open_device (GstRingBuffer *buf); +gboolean gst_ring_buffer_close_device (GstRingBuffer *buf); + +gboolean gst_ring_buffer_device_is_open (GstRingBuffer *buf); + +/* allocate resources */ +gboolean gst_ring_buffer_acquire (GstRingBuffer *buf, GstRingBufferSpec *spec); +gboolean gst_ring_buffer_release (GstRingBuffer *buf); + +gboolean gst_ring_buffer_is_acquired (GstRingBuffer *buf); + +/* activating */ +gboolean gst_ring_buffer_activate (GstRingBuffer *buf, gboolean active); +gboolean gst_ring_buffer_is_active (GstRingBuffer *buf); + +/* flushing */ +void gst_ring_buffer_set_flushing (GstRingBuffer *buf, gboolean flushing); + +/* playback/pause */ +gboolean gst_ring_buffer_start (GstRingBuffer *buf); +gboolean gst_ring_buffer_pause (GstRingBuffer *buf); +gboolean gst_ring_buffer_stop (GstRingBuffer *buf); + +/* get status */ +guint gst_ring_buffer_delay (GstRingBuffer *buf); +guint64 gst_ring_buffer_samples_done (GstRingBuffer *buf); + +void gst_ring_buffer_set_sample (GstRingBuffer *buf, guint64 sample); + +/* clear all segments */ +void gst_ring_buffer_clear_all (GstRingBuffer *buf); + +/* commit samples */ +guint gst_ring_buffer_commit (GstRingBuffer *buf, guint64 sample, + guchar *data, guint len); +guint gst_ring_buffer_commit_full (GstRingBuffer * buf, guint64 *sample, + guchar * data, gint in_samples, + gint out_samples, gint * accum); + +/* read samples */ +guint gst_ring_buffer_read (GstRingBuffer *buf, guint64 sample, + guchar *data, guint len); + +/* mostly protected */ +/* not yet implemented +gboolean gst_ring_buffer_prepare_write (GstRingBuffer *buf, gint *segment, guint8 **writeptr, gint *len); +*/ +gboolean gst_ring_buffer_prepare_read (GstRingBuffer *buf, gint *segment, guint8 **readptr, gint *len); +void gst_ring_buffer_clear (GstRingBuffer *buf, gint segment); +void gst_ring_buffer_advance (GstRingBuffer *buf, guint advance); + +void gst_ring_buffer_may_start (GstRingBuffer *buf, gboolean allowed); + + +G_END_DECLS + +#endif /* __GST_RING_BUFFER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.c new file mode 100644 index 0000000..94cdde3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.c @@ -0,0 +1,246 @@ +/* GStreamer + * Copyright (C) 2003-2004 Ronald Bultje + * Copyright (C) 2005-2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstaudiomixerutils + * @short_description: utility functions to find available audio mixers + * from the plugin registry + * + * + * + * Provides some utility functions to detect available audio mixers + * on the system. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mixerutils.h" + +#include + +#include + +static void +gst_audio_mixer_filter_do_filter (GstAudioMixerFilterFunc filter_func, + GstElementFactory * factory, + GstElement ** p_element, GList ** p_collection, gpointer user_data) +{ + /* so, the element is a mixer, let's see if the caller wants it */ + if (filter_func != NULL) { + if (filter_func (GST_MIXER (*p_element), user_data) == TRUE) { + *p_collection = g_list_prepend (*p_collection, *p_element); + /* do not set state back to NULL here on purpose, caller + * might want to keep the mixer open */ + *p_element = NULL; + } + } else { + gst_element_set_state (*p_element, GST_STATE_NULL); + *p_collection = g_list_prepend (*p_collection, *p_element); + *p_element = NULL; + } + + /* create new element for further probing if the old one was cleared */ + if (*p_element == NULL) { + *p_element = gst_element_factory_create (factory, NULL); + } +} + +static gboolean +gst_audio_mixer_filter_check_element (GstElement * element) +{ + GstStateChangeReturn ret; + + /* open device (only then we can know for sure whether it is a mixer) */ + gst_element_set_state (element, GST_STATE_READY); + ret = gst_element_get_state (element, NULL, NULL, 1 * GST_SECOND); + if (ret != GST_STATE_CHANGE_SUCCESS) { + GST_DEBUG ("could not open device / set element to READY"); + gst_element_set_state (element, GST_STATE_NULL); + return FALSE; + } + + /* is this device a mixer? */ + if (!GST_IS_MIXER (element)) { + GST_DEBUG ("element is not a mixer"); + gst_element_set_state (element, GST_STATE_NULL); + return FALSE; + } + + /* any tracks? */ + if (!gst_mixer_list_tracks (GST_MIXER (element))) { + GST_DEBUG ("element is a mixer, but has no tracks"); + gst_element_set_state (element, GST_STATE_NULL); + return FALSE; + } + + GST_DEBUG ("element is a mixer with mixer tracks"); + return TRUE; +} + +static void +gst_audio_mixer_filter_probe_feature (GstAudioMixerFilterFunc filter_func, + GstElementFactory * factory, + GList ** p_collection, gboolean first, gpointer user_data) +{ + GstElement *element; + + GST_DEBUG ("probing %s ...", gst_element_factory_get_longname (factory)); + + /* create element */ + element = gst_element_factory_create (factory, NULL); + + if (element == NULL) { + GST_DEBUG ("could not create element from factory"); + return; + } + + GST_DEBUG ("created element %s (%p)", GST_ELEMENT_NAME (element), element); + + if (GST_IS_PROPERTY_PROBE (element)) { + GstPropertyProbe *probe; + const GParamSpec *devspec; + + probe = GST_PROPERTY_PROBE (element); + + GST_DEBUG ("probing available devices ..."); + if ((devspec = gst_property_probe_get_property (probe, "device"))) { + GValueArray *array; + + if ((array = gst_property_probe_probe_and_get_values (probe, devspec))) { + guint n; + + GST_DEBUG ("there are %d available devices", array->n_values); + + /* set all devices and test for mixer */ + for (n = 0; n < array->n_values; n++) { + GValue *device; + + /* set this device */ + device = g_value_array_get_nth (array, n); + g_object_set_property (G_OBJECT (element), "device", device); + + GST_DEBUG ("trying device %s ..", g_value_get_string (device)); + + if (gst_audio_mixer_filter_check_element (element)) { + gst_audio_mixer_filter_do_filter (filter_func, factory, &element, + p_collection, user_data); + + if (first && *p_collection != NULL) { + GST_DEBUG ("Stopping after first found mixer, as requested"); + break; + } + } + } + g_value_array_free (array); + } + } + } else { + GST_DEBUG ("element does not support the property probe interface"); + + if (gst_audio_mixer_filter_check_element (element)) { + gst_audio_mixer_filter_do_filter (filter_func, factory, &element, + p_collection, user_data); + } + } + + if (element) { + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + } +} + +static gint +element_factory_rank_compare_func (gconstpointer a, gconstpointer b) +{ + gint rank_a = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (a)); + gint rank_b = gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (b)); + + /* make order chosen in the end more determinable */ + if (rank_a == rank_b) { + const gchar *name_a = GST_PLUGIN_FEATURE_NAME (GST_PLUGIN_FEATURE (a)); + const gchar *name_b = GST_PLUGIN_FEATURE_NAME (GST_PLUGIN_FEATURE (b)); + + return g_ascii_strcasecmp (name_a, name_b); + } + + return rank_b - rank_a; +} + +/** + * gst_audio_default_registry_mixer_filter: + * @filter_func: filter function, or #NULL + * @first: set to #TRUE if you only want the first suitable mixer element + * @user_data: user data to pass to the filter function + * + * Utility function to find audio mixer elements. + * + * Will traverse the default plugin registry in order of plugin rank and + * find usable audio mixer elements. The caller may optionally fine-tune + * the selection by specifying a filter function. + * + * Returns: a #GList of audio mixer #GstElements. You must free each + * element in the list by setting it to NULL state and calling + * gst_object_unref(). After that the list itself should be freed + * using g_list_free(). + * + * Since: 0.10.2 + */ +GList * +gst_audio_default_registry_mixer_filter (GstAudioMixerFilterFunc filter_func, + gboolean first, gpointer data) +{ + GList *mixer_list = NULL; + GList *feature_list; + GList *walk; + + /* go through all elements of a certain class and check whether + * they implement a mixer. If so, add it to the list. */ + feature_list = gst_registry_get_feature_list (gst_registry_get_default (), + GST_TYPE_ELEMENT_FACTORY); + + feature_list = g_list_sort (feature_list, element_factory_rank_compare_func); + + for (walk = feature_list; walk != NULL; walk = walk->next) { + GstElementFactory *factory; + const gchar *klass; + + factory = GST_ELEMENT_FACTORY (walk->data); + + /* check category */ + klass = gst_element_factory_get_klass (factory); + if (strcmp (klass, "Generic/Audio") == 0) { + gst_audio_mixer_filter_probe_feature (filter_func, factory, + &mixer_list, first, data); + } + + if (first && mixer_list != NULL) { + GST_DEBUG ("Stopping after first found mixer, as requested"); + break; + } + } + + gst_plugin_feature_list_free (feature_list); + + return g_list_reverse (mixer_list); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.h new file mode 100644 index 0000000..cfda7ab --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/mixerutils.h @@ -0,0 +1,50 @@ +/* GStreamer + * Copyright (C) 2005-2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_MIXERUTILS_H__ +#define __GST_AUDIO_MIXERUTILS_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GstAudioMixerFilterFunc: + * @mixer: a #GstElement implementing the #GstMixer interface + * @user_data: user data + * + * Function that will be called by gst_audio_default_registry_mixer_filter() + * so the caller can decide which mixer elements should be kept and returned. + * When the mixer element is passed to the callback function, it is opened + * and in READY state. If you decide to keep the element, you need to set it + * back to NULL state yourself (unless you want to keep it opened of course). + * + * Returns: TRUE if the element should be kept, FALSE otherwise. + */ +typedef gboolean (*GstAudioMixerFilterFunc) (GstMixer * mixer, gpointer user_data); + + +GList * gst_audio_default_registry_mixer_filter (GstAudioMixerFilterFunc filter_func, + gboolean first, + gpointer user_data); + +G_END_DECLS + +#endif /* __GST_AUDIO_MIXERUTILS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.c new file mode 100644 index 0000000..bd26f1c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.c @@ -0,0 +1,742 @@ +/* GStreamer Multichannel-Audio helper functions + * (c) 2004 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstmultichannel + * @short_description: Support for multichannel audio elements + * + * This module contains some helper functions and a enum to work with + * multichannel audio. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "multichannel.h" + +#define GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME "channel-positions" + +/** + * gst_audio_check_channel_positions: + * @pos: An array of #GstAudioChannelPosition. + * @channels: The number of elements in @pos. + * + * This functions checks if the given channel positions are valid. Channel + * positions are valid if: + * + * No channel positions appears twice or all positions are %GST_AUDIO_CHANNEL_POSITION_NONE. + * + * Either all or none of the channel positions are %GST_AUDIO_CHANNEL_POSITION_NONE. + * + * %GST_AUDIO_CHANNEL_POSITION_FRONT_MONO and %GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT or %GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT don't appear together in the given positions. + * + * + * + * Since: 0.10.20 + * + * Returns: %TRUE if the given channel positions are valid + * and %FALSE otherwise. + */ +gboolean +gst_audio_check_channel_positions (const GstAudioChannelPosition * pos, + guint channels) +{ + gint i, n; + + const struct + { + const GstAudioChannelPosition pos1[2]; + const GstAudioChannelPosition pos2[1]; + } conf[] = { + /* front: mono <-> stereo */ + { { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID}} + }; + + g_return_val_if_fail (pos != NULL, FALSE); + g_return_val_if_fail (channels > 0, FALSE); + + /* check for invalid channel positions */ + for (n = 0; n < channels; n++) { + if (pos[n] <= GST_AUDIO_CHANNEL_POSITION_INVALID || + pos[n] >= GST_AUDIO_CHANNEL_POSITION_NUM) { + GST_WARNING ("Channel position %d for channel %d is invalid", pos[n], n); + return FALSE; + } + } + + /* either all channel positions are NONE or all are defined, + * but having only some channel positions NONE and others not + * is not allowed */ + if (pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { + for (n = 1; n < channels; ++n) { + if (pos[n] != GST_AUDIO_CHANNEL_POSITION_NONE) { + GST_WARNING ("Either all channel positions must be defined, or all " + "be set to NONE, having only some defined is not allowed"); + return FALSE; + } + } + /* all positions are NONE, we are done here */ + return TRUE; + } + + /* check for multiple position occurrences */ + for (i = GST_AUDIO_CHANNEL_POSITION_INVALID + 1; + i < GST_AUDIO_CHANNEL_POSITION_NUM; i++) { + gint count = 0; + + for (n = 0; n < channels; n++) { + if (pos[n] == i) + count++; + } + + /* NONE may not occur mixed with other channel positions */ + if (i == GST_AUDIO_CHANNEL_POSITION_NONE && count > 0) { + GST_WARNING ("Either all channel positions must be defined, or all " + "be set to NONE, having only some defined is not allowed"); + return FALSE; + } + + if (count > 1) { + GST_WARNING ("Channel position %d occurred %d times, not allowed", + i, count); + return FALSE; + } + } + + /* check for position conflicts */ + for (i = 0; conf[i].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; i++) { + gboolean found1 = FALSE, found2 = FALSE; + + for (n = 0; n < channels; n++) { + if (pos[n] == conf[i].pos1[0] || pos[n] == conf[i].pos1[1]) + found1 = TRUE; + else if (pos[n] == conf[i].pos2[0]) + found2 = TRUE; + } + + if (found1 && found2) { + GST_WARNING ("Found conflicting channel positions %d/%d and %d", + conf[i].pos1[0], conf[i].pos1[1], conf[i].pos2[0]); + return FALSE; + } + } + + return TRUE; +} + +/* FIXME: these default positions may or may not be correct. In any + * case, they are mostly just a fallback for buggy plugins, so it + * should not really matter too much */ +#define NUM_DEF_CHANS 8 +static const GstAudioChannelPosition + default_positions[NUM_DEF_CHANS][NUM_DEF_CHANS] = { + /* 1 channel */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + }, + /* 2 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + }, + /* 3 channels (2.1) */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, /* or FRONT_CENTER for 3.0? */ + }, + /* 4 channels (4.0 or 3.1?) */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + /* 5 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + }, + /* 6 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + }, + /* 7 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + }, + /* 8 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + } +}; + +/** + * gst_audio_get_channel_positions: + * @str: A #GstStructure to retrieve channel positions from. + * + * Retrieves a number of (fixed!) audio channel positions from + * the provided #GstStructure and returns it as a newly allocated + * array. The caller should g_free () this array. The caller + * should also check that the members in this #GstStructure are + * indeed "fixed" before calling this function. + * + * Returns: a newly allocated array containing the channel + * positions as provided in the given #GstStructure. Returns + * NULL on error. + */ + +GstAudioChannelPosition * +gst_audio_get_channel_positions (GstStructure * str) +{ + GstAudioChannelPosition *pos; + + gint channels, n; + + const GValue *pos_val_arr, *pos_val_entry; + + gboolean res; + + GType t; + + /* get number of channels, general type checkups */ + g_return_val_if_fail (str != NULL, NULL); + res = gst_structure_get_int (str, "channels", &channels); + g_return_val_if_fail (res, NULL); + g_return_val_if_fail (channels > 0, NULL); + pos_val_arr = gst_structure_get_value (str, + GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME); + + /* The following checks are here to retain compatibility for plugins not + * implementing this field. They expect that channels=1 implies mono + * and channels=2 implies stereo, so we follow that. */ + if (pos_val_arr == NULL) { + /* channel layouts for 1 and 2 channels are implicit, don't warn */ + if (channels > 2) { + g_warning ("Failed to retrieve channel layout from caps. This usually " + "means there is a GStreamer element that does not implement " + "multichannel audio correctly. Please file a bug."); + } + + /* just return some default channel layout if we have one */ + if (channels >= 1 && channels <= NUM_DEF_CHANS) { + const GstAudioChannelPosition *p; + + p = default_positions[channels - 1]; + return g_memdup (p, channels * sizeof (GstAudioChannelPosition)); + } + + return NULL; + } + + g_return_val_if_fail (gst_value_array_get_size (pos_val_arr) == channels, + NULL); + for (n = 0; n < channels; n++) { + t = G_VALUE_TYPE (gst_value_array_get_value (pos_val_arr, n)); + g_return_val_if_fail (t == GST_TYPE_AUDIO_CHANNEL_POSITION, NULL); + } + + /* ... and fill array */ + pos = g_new (GstAudioChannelPosition, channels); + for (n = 0; n < channels; n++) { + pos_val_entry = gst_value_array_get_value (pos_val_arr, n); + pos[n] = g_value_get_enum (pos_val_entry); + } + + if (!gst_audio_check_channel_positions (pos, channels)) { + g_free (pos); + return NULL; + } + + return pos; +} + +/** + * gst_audio_set_channel_positions: + * @str: A #GstStructure to set channel positions on. + * @pos: an array of channel positions. The number of members + * in this array should be equal to the (fixed!) number + * of the "channels" field in the given #GstStructure. + * + * Adds a "channel-positions" field to the given #GstStructure, + * which will represent the channel positions as given in the + * provided #GstAudioChannelPosition array. + */ + +void +gst_audio_set_channel_positions (GstStructure * str, + const GstAudioChannelPosition * pos) +{ + GValue pos_val_arr = { 0 }, pos_val_entry = { + 0}; + gint channels, n; + + gboolean res; + + /* get number of channels, checkups */ + g_return_if_fail (str != NULL); + g_return_if_fail (pos != NULL); + res = gst_structure_get_int (str, "channels", &channels); + g_return_if_fail (res); + g_return_if_fail (channels > 0); + if (!gst_audio_check_channel_positions (pos, channels)) + return; + + /* build gvaluearray from positions */ + g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION); + g_value_init (&pos_val_arr, GST_TYPE_ARRAY); + for (n = 0; n < channels; n++) { + g_value_set_enum (&pos_val_entry, pos[n]); + gst_value_array_append_value (&pos_val_arr, &pos_val_entry); + } + g_value_unset (&pos_val_entry); + + /* add to structure */ + gst_structure_set_value (str, + GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME, &pos_val_arr); + g_value_unset (&pos_val_arr); +} + +/** + * gst_audio_set_structure_channel_positions_list: + * @str: #GstStructure to set the list of channel positions + * on. + * @pos: the array containing one or more possible audio + * channel positions that we should add in each value + * of the array in the given structure. + * @num_positions: the number of values in pos. + * + * Sets a (possibly non-fixed) list of possible audio channel + * positions (given in pos) on the given structure. The + * structure, after this function has been called, will contain + * a "channel-positions" field with an array of the size of + * the "channels" field value in the given structure (note + * that this means that the channels field in the provided + * structure should be fixed!). Each value in the array will + * contain each of the values given in the pos array. + */ + +void +gst_audio_set_structure_channel_positions_list (GstStructure * str, + const GstAudioChannelPosition * pos, gint num_positions) +{ + gint channels, n, c; + GValue pos_val_arr = { 0 }, pos_val_list = { + 0}, pos_val_entry = { + 0}; + gboolean res; + + /* get number of channels, general type checkups */ + g_return_if_fail (str != NULL); + g_return_if_fail (num_positions > 0); + g_return_if_fail (pos != NULL); + res = gst_structure_get_int (str, "channels", &channels); + g_return_if_fail (res); + g_return_if_fail (channels > 0); + + /* create the array of lists */ + g_value_init (&pos_val_arr, GST_TYPE_ARRAY); + g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION); + for (n = 0; n < channels; n++) { + g_value_init (&pos_val_list, GST_TYPE_LIST); + for (c = 0; c < num_positions; c++) { + g_value_set_enum (&pos_val_entry, pos[c]); + gst_value_list_append_value (&pos_val_list, &pos_val_entry); + } + gst_value_array_append_value (&pos_val_arr, &pos_val_list); + g_value_unset (&pos_val_list); + } + g_value_unset (&pos_val_entry); + gst_structure_set_value (str, GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME, + &pos_val_arr); + g_value_unset (&pos_val_arr); +} + +/* + * Helper function for below. The structure will be conserved, + * but might be cut down. Any additional structures that were + * created will be stored in the returned caps. + */ + +static GstCaps * +add_list_to_struct (GstStructure * str, + const GstAudioChannelPosition * pos, gint num_positions) +{ + GstCaps *caps = gst_caps_new_empty (); + + const GValue *chan_val; + + chan_val = gst_structure_get_value (str, "channels"); + if (G_VALUE_TYPE (chan_val) == G_TYPE_INT) { + gst_audio_set_structure_channel_positions_list (str, pos, num_positions); + } else if (G_VALUE_TYPE (chan_val) == GST_TYPE_LIST) { + gint size; + + const GValue *sub_val; + + size = gst_value_list_get_size (chan_val); + sub_val = gst_value_list_get_value (chan_val, 0); + gst_structure_set_value (str, "channels", sub_val); + gst_caps_append (caps, add_list_to_struct (str, pos, num_positions)); + while (--size > 0) { + str = gst_structure_copy (str); + sub_val = gst_value_list_get_value (chan_val, size); + gst_structure_set_value (str, "channels", sub_val); + gst_caps_append (caps, add_list_to_struct (str, pos, num_positions)); + gst_caps_append_structure (caps, str); + } + } else if (G_VALUE_TYPE (chan_val) == GST_TYPE_INT_RANGE) { + gint min, max; + + min = gst_value_get_int_range_min (chan_val); + max = gst_value_get_int_range_max (chan_val); + + gst_structure_set (str, "channels", G_TYPE_INT, min, NULL); + gst_audio_set_structure_channel_positions_list (str, pos, num_positions); + for (++min; min < max; min++) { + str = gst_structure_copy (str); + gst_structure_set (str, "channels", G_TYPE_INT, min, NULL); + gst_audio_set_structure_channel_positions_list (str, pos, num_positions); + gst_caps_append_structure (caps, str); + } + } else { + g_warning ("Unexpected value type '%s' for channels field", + GST_STR_NULL (g_type_name (G_VALUE_TYPE (chan_val)))); + } + + return caps; +} + +/** + * gst_audio_set_caps_channel_positions_list: + * @caps: #GstCaps to set the list of channel positions on. + * @pos: the array containing one or more possible audio + * channel positions that we should add in each value + * of the array in the given structure. + * @num_positions: the number of values in pos. + * + * Sets a (possibly non-fixed) list of possible audio channel + * positions (given in pos) on the given caps. Each of the + * structures of the caps, after this function has been called, + * will contain a "channel-positions" field with an array. + * Each value in the array will contain each of the values given + * in the pos array. Note that the size of the caps might be + * increased by this, since each structure with a "channel- + * positions" field needs to have a fixed "channels" field. + * The input caps is not required to have this. + */ + +void +gst_audio_set_caps_channel_positions_list (GstCaps * caps, + const GstAudioChannelPosition * pos, gint num_positions) +{ + gint size, n; + + /* get number of channels, general type checkups */ + g_return_if_fail (caps != NULL); + g_return_if_fail (num_positions > 0); + g_return_if_fail (pos != NULL); + + size = gst_caps_get_size (caps); + for (n = 0; n < size; n++) { + gst_caps_append (caps, add_list_to_struct (gst_caps_get_structure (caps, + n), pos, num_positions)); + } +} + +/** + * gst_audio_fixate_channel_positions: + * @str: a #GstStructure containing a (possibly unfixed) + * "channel-positions" field. + * + * Custom fixate function. Elements that implement some sort of + * channel conversion algorithm should use this function for + * fixating on GstAudioChannelPosition properties. It will take + * care of equal channel positioning (left/right). Caller g_free()s + * the return value. The input properties may be (and are supposed + * to be) unfixed. + * Note that this function is mostly a hack because we currently + * have no way to add default fixation functions for new GTypes. + * + * Returns: fixed values that the caller could use as a fixed + * set of #GstAudioChannelPosition values. + */ + +GstAudioChannelPosition * +gst_audio_fixate_channel_positions (GstStructure * str) +{ + GstAudioChannelPosition *pos; + + gint channels, n, num_unfixed = 0, i, c; + + const GValue *pos_val_arr, *pos_val_entry, *pos_val; + + gboolean res, is_stereo = TRUE; + + GType t; + + /* + * We're going to do this cluelessly. We'll make an array of values that + * conflict with each other and, for each iteration in this array, pick + * either one until all unknown values are filled. This might not work in + * corner cases but should work OK for the general case. + */ + const struct + { + const GstAudioChannelPosition pos1[2]; + const GstAudioChannelPosition pos2[1]; + } conf[] = { + /* front: mono <-> stereo */ + { + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, { { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { + GST_AUDIO_CHANNEL_POSITION_INVALID}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, { + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}}, { { + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_INVALID}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, { + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, { + GST_AUDIO_CHANNEL_POSITION_LFE}}, { { + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_INVALID}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID, GST_AUDIO_CHANNEL_POSITION_INVALID}, { + GST_AUDIO_CHANNEL_POSITION_INVALID}} + }; + struct + { + gint num_opt[3]; + guint num_opts[3]; + gboolean is_fixed[3]; + gint choice; /* -1 is none, 0 is the two, 1 is the one */ + } opt; + + /* get number of channels, general type checkups */ + g_return_val_if_fail (str != NULL, NULL); + res = gst_structure_get_int (str, "channels", &channels); + g_return_val_if_fail (res, NULL); + g_return_val_if_fail (channels > 0, NULL); + + /* 0.8.x mono/stereo checks */ + pos_val_arr = gst_structure_get_value (str, + GST_AUDIO_CHANNEL_POSITIONS_FIELD_NAME); + if (!pos_val_arr && (channels == 1 || channels == 2)) { + pos = g_new (GstAudioChannelPosition, channels); + if (channels == 1) { + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; + } else { + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + } + return pos; + } + g_return_val_if_fail (pos_val_arr != NULL, NULL); + g_return_val_if_fail (gst_value_array_get_size (pos_val_arr) == channels, + NULL); + for (n = 0; n < channels; n++) { + t = G_VALUE_TYPE (gst_value_array_get_value (pos_val_arr, n)); + g_return_val_if_fail (t == GST_TYPE_LIST || + t == GST_TYPE_AUDIO_CHANNEL_POSITION, NULL); + } + + /* all unknown, to start with */ + pos = g_new (GstAudioChannelPosition, channels); + for (n = 0; n < channels; n++) + pos[n] = GST_AUDIO_CHANNEL_POSITION_INVALID; + num_unfixed = channels; + + /* Iterate the array of conflicting values */ + for (i = 0; conf[i].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID || + conf[i].pos2[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; i++) { + /* front/center only important if not mono (obviously) */ + if (conf[i].pos1[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER && + !is_stereo) + continue; + + /* init values */ + for (n = 0; n < 3; n++) { + opt.num_opt[n] = -1; + opt.num_opts[n] = -1; + opt.is_fixed[n] = FALSE; + } + + /* Now, we'll see for each channel if it allows for any of the values in + * the set of conflicting audio channel positions and keep scores. */ + for (n = 0; n < channels; n++) { + /* if the channel is already taken, don't bother */ + if (pos[n] != GST_AUDIO_CHANNEL_POSITION_INVALID) + continue; + + pos_val_entry = gst_value_array_get_value (pos_val_arr, n); + t = G_VALUE_TYPE (pos_val_entry); + if (t == GST_TYPE_LIST) { + /* This algorhythm is suboptimal. */ + for (c = 0; c < gst_value_list_get_size (pos_val_entry); c++) { + pos_val = gst_value_list_get_value (pos_val_entry, c); + if (g_value_get_enum (pos_val) == conf[i].pos1[0] && + opt.num_opts[0] > gst_value_list_get_size (pos_val_entry) && + !opt.is_fixed[0]) { + /* Now test if the old position of num_opt[0] also allows for + * the other channel (which was skipped previously). If so, + * keep score. */ + if (opt.num_opt[0] != -1) { + gint c1; + + pos_val_entry = gst_value_array_get_value (pos_val_arr, + opt.num_opt[0]); + if (G_VALUE_TYPE (pos_val_entry) == GST_TYPE_LIST) { + for (c1 = 0; c1 < gst_value_list_get_size (pos_val_entry); c1++) { + pos_val = gst_value_list_get_value (pos_val_entry, c1); + if (g_value_get_enum (pos_val) == conf[i].pos1[1] && + opt.num_opts[1] > opt.num_opts[0] && !opt.is_fixed[1]) { + opt.num_opts[1] = opt.num_opts[0]; + opt.num_opt[1] = opt.num_opt[0]; + } + } + pos_val = gst_value_list_get_value (pos_val_entry, c); + } + pos_val_entry = gst_value_array_get_value (pos_val_arr, n); + } + + /* and save values */ + opt.num_opts[0] = gst_value_list_get_size (pos_val_entry); + opt.num_opt[0] = n; + } else if (g_value_get_enum (pos_val) == conf[i].pos1[1] && + opt.num_opts[1] > gst_value_list_get_size (pos_val_entry) && + !opt.is_fixed[1] && n != opt.num_opt[0]) { + opt.num_opts[1] = gst_value_list_get_size (pos_val_entry); + opt.num_opt[1] = n; + } + + /* 2 goes separately, because 0/1 vs. 2 are separate */ + if (g_value_get_enum (pos_val) == conf[i].pos2[0] && + opt.num_opts[2] > gst_value_list_get_size (pos_val_entry) && + !opt.is_fixed[2]) { + opt.num_opts[2] = gst_value_list_get_size (pos_val_entry); + opt.num_opt[2] = n; + } + } + } else { + if (g_value_get_enum (pos_val_entry) == conf[i].pos1[0]) { + opt.num_opt[0] = n; + opt.is_fixed[0] = TRUE; + } else if (g_value_get_enum (pos_val_entry) == conf[i].pos1[1]) { + opt.num_opt[1] = n; + opt.is_fixed[1] = TRUE; + } else if (g_value_get_enum (pos_val_entry) == conf[i].pos2[0]) { + opt.num_opt[2] = n; + opt.is_fixed[2] = TRUE; + } + } + } + + /* check our results and choose either one */ + if ((opt.is_fixed[0] || opt.is_fixed[1]) && opt.is_fixed[2]) { + g_warning ("Pre-fixated on both %d/%d and %d - conflict!", + conf[i].pos1[0], conf[i].pos1[1], conf[i].pos2[0]); + g_free (pos); + return NULL; + } else if ((opt.is_fixed[0] && opt.num_opt[1] == -1) || + (opt.is_fixed[1] && opt.num_opt[0] == -1)) { + g_warning ("Pre-fixated one side, but other side n/a of %d/%d", + conf[i].pos1[0], conf[i].pos1[1]); + g_free (pos); + return NULL; + } else if (opt.is_fixed[0] || opt.is_fixed[1]) { + opt.choice = 0; + } else if (opt.is_fixed[2]) { + opt.choice = 1; + } else if (opt.num_opt[0] != -1 && opt.num_opt[1] != -1) { + opt.choice = 0; + } else if (opt.num_opt[2] != -1) { + opt.choice = 1; + } else { + opt.choice = -1; + } + + /* stereo? Note that we keep is_stereo to TRUE if we didn't decide on + * any arrangement. The mono/stereo channels might be handled elsewhere + * which is clearly outside the scope of this element, so we cannot + * know and expect the application to handle that then. */ + if (conf[i].pos2[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO && + opt.choice == 1) { + is_stereo = FALSE; + } + + /* now actually decide what we'll do and fixate on that */ + if (opt.choice == 0) { + g_assert (conf[i].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID && + conf[i].pos1[1] != GST_AUDIO_CHANNEL_POSITION_INVALID); + pos[opt.num_opt[0]] = conf[i].pos1[0]; + pos[opt.num_opt[1]] = conf[i].pos1[1]; + num_unfixed -= 2; + } else if (opt.choice == 1) { + g_assert (conf[i].pos2[0] != GST_AUDIO_CHANNEL_POSITION_INVALID); + pos[opt.num_opt[2]] = conf[i].pos2[0]; + num_unfixed--; + } + } + + /* safety check */ + if (num_unfixed > 0) { + g_warning ("%d unfixed channel positions left after fixation!", + num_unfixed); + g_free (pos); + return NULL; + } + + if (!gst_audio_check_channel_positions (pos, channels)) { + g_free (pos); + return NULL; + } + + return pos; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.h new file mode 100644 index 0000000..2d9685d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/multichannel.h @@ -0,0 +1,115 @@ +/* GStreamer Multichannel-Audio helper functions + * (c) 2004 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_MULTICHANNEL_H__ +#define __GST_AUDIO_MULTICHANNEL_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GstAudioChannelPosition: + * @GST_AUDIO_CHANNEL_POSITION_FRONT_MONO: front mono + * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: front left + * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: front right + * @GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: rear center + * @GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: rear left + * @GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: rear right + * @GST_AUDIO_CHANNEL_POSITION_LFE: subwoofer + * @GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: front center + * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: front left of center + * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: front right of center + * @GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: side left + * @GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: side right + * @GST_AUDIO_CHANNEL_POSITION_NONE: used for position-less channels, e.g. + * from a sound card that records 1024 channels; mutually exclusive with + * any other channel position + */ +typedef enum { + GST_AUDIO_CHANNEL_POSITION_INVALID = -1, + + /* Main front speakers. Mono and left/right are mututally exclusive! */ + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + + /* rear. Left/right and center are mututally exclusive! */ + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + + /* subwoofer/low-frequency */ + GST_AUDIO_CHANNEL_POSITION_LFE, + + /* Center front speakers. Center and left/right_of_center cannot be + * used together! */ + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + + /* sides */ + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + + /* for multi-channel input and output with more than 8 channels, + * incompatible with all other positions, either all positions + * are defined or all positions are undefined, but can't mix'n'match */ + GST_AUDIO_CHANNEL_POSITION_NONE, + + /* don't use - counter */ + GST_AUDIO_CHANNEL_POSITION_NUM +} GstAudioChannelPosition; + +/* Retrieves or sets the positions from/to a GstStructure. Only + * works with fixed caps, caller should check for that! Caller + * g_free()s result of the getter. */ +GstAudioChannelPosition * + gst_audio_get_channel_positions (GstStructure *str); +void gst_audio_set_channel_positions (GstStructure *str, + const GstAudioChannelPosition *pos); + +/* Sets a (non-fixed) list of possible audio channel positions + * on a structure (this requires the "channels" property to + * be fixed!) or on a caps (here, the "channels" property may be + * unfixed and the caps may even contain multiple structures). */ +void gst_audio_set_structure_channel_positions_list + (GstStructure *str, + const GstAudioChannelPosition *pos, + gint num_positions); +void gst_audio_set_caps_channel_positions_list + (GstCaps *caps, + const GstAudioChannelPosition *pos, + gint num_positions); + +/* Custom fixate function. Elements that implement some sort of + * channel conversion algorhithm should use this function for + * fixating on GstAudioChannelPosition properties. It will take + * care of equal channel positioning (left/right). Caller g_free()s + * the return value. The input properties may be (and are supposed + * to be) unfixed. */ +GstAudioChannelPosition * + gst_audio_fixate_channel_positions (GstStructure *str); + +gboolean gst_audio_check_channel_positions (const GstAudioChannelPosition * pos, guint channels); + +G_END_DECLS + +#endif /* __GST_AUDIO_MULTICHANNEL_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/testchannels.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/testchannels.c new file mode 100644 index 0000000..53ca51d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/audio/testchannels.c @@ -0,0 +1,49 @@ +/* GStreamer Multichannel Test + * (c) 2004 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "multichannel.c" +#include "audio-enumtypes.c" + +gint +main (gint argc, gchar * argv[]) +{ + gchar *str; + GstCaps *caps; + GstAudioChannelPosition pos[2] = { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + /* register multichannel type */ + gst_init (&argc, &argv); + gst_audio_channel_position_get_type (); + + /* test some caps-string conversions */ + caps = gst_caps_new_simple ("audio/x-raw-int", + "channels", G_TYPE_INT, 2, NULL); + str = gst_caps_to_string (caps); + g_print ("Test caps #1: %s\n", str); + g_free (str); + gst_audio_set_channel_positions (gst_caps_get_structure (caps, 0), pos); + str = gst_caps_to_string (caps); + g_print ("Test caps #2: %s\n", str); + g_free (str); + gst_caps_unref (caps); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/Makefile.am new file mode 100644 index 0000000..26706f4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/Makefile.am @@ -0,0 +1,70 @@ +lib_LTLIBRARIES = libgstcdda-@GST_MAJORMINOR@.la + +libgstcdda_@GST_MAJORMINOR@_la_SOURCES = \ + gstcddabasesrc.c + +libgstcdda_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/cdda +libgstcdda_@GST_MAJORMINOR@include_HEADERS = \ + gstcddabasesrc.h + +libgstcdda_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la +libgstcdda_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstcdda_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +# Disabled until this is fixed: +# http://bugzilla.gnome.org/show_bug.cgi?id=594209 +if FALSE +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstCdda-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstcdda_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstcdda_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/cdda/%',$(libgstcdda_@GST_MAJORMINOR@include_HEADERS)) + +GstCdda-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstcdda-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstCdda \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + --add-include-path=$(builddir)/../tag \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstcdda-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --include=GstTag-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg gstreamer-tag-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-cdda-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=$(builddir)/../tag \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif +endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.c new file mode 100644 index 0000000..e753a56 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.c @@ -0,0 +1,1665 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * Copyright (C) 2005 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* TODO: + * + * - in ::start(), we want to post a tags message with an array or a list + * of tagslists of all tracks, so that applications know at least the + * number of tracks and all track durations immediately without having + * to do any querying. We have to decide what type and name to use for + * this array of track taglists. + * + * - FIX cddb discid calculation algorithm for mixed mode CDs - do we use + * offsets and duration of ALL tracks (data + audio) for the CDDB ID + * calculation, or only audio tracks? + * + * - Do we really need properties for the TOC bias/offset stuff? Wouldn't + * environment variables make much more sense? Do we need this at all + * (does it only affect ancient hardware?) + */ + +/** + * SECTION:gstcddabasesrc + * @short_description: Base class for CD digital audio (CDDA) sources + * + * + * + * Provides a base class for CDDA sources, which handles things like seeking, + * querying, discid calculation, tags, and buffer timestamping. + * + * Using GstCddaBaseSrc-based elements in applications + * + * GstCddaBaseSrc registers two #GstFormats of its own, namely + * the "track" format and the "sector" format. Applications will usually + * only find the "track" format interesting. You can retrieve that #GstFormat + * for use in seek events or queries with gst_format_get_by_nick("track"). + * + * + * In order to query the number of tracks, for example, an application would + * set the CDDA source element to READY or PAUSED state and then query the + * the number of tracks via gst_element_query_duration() using the track + * format acquired above. Applications can query the currently playing track + * in the same way. + * + * + * Alternatively, applications may retrieve the currently playing track and + * the total number of tracks from the taglist that will posted on the bus + * whenever the CD is opened or the currently playing track changes. The + * taglist will contain GST_TAG_TRACK_NUMBER and GST_TAG_TRACK_COUNT tags. + * + * + * Applications playing back CD audio using playbin and cdda://n URIs should + * issue a seek command in track format to change between tracks, rather than + * setting a new cdda://n+1 URI on playbin (as setting a new URI on playbin + * involves closing and re-opening the CD device, which is much much slower). + * + * Tags and meta-information + * + * CDDA sources will automatically emit a number of tags, details about which + * can be found in the libgsttag documentation. Those tags are: + * #GST_TAG_CDDA_CDDB_DISCID, #GST_TAG_CDDA_CDDB_DISCID_FULL, + * #GST_TAG_CDDA_MUSICBRAINZ_DISCID, #GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL, + * among others. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include /* for strtol */ + +#include "gstcddabasesrc.h" +#include "gst/gst-i18n-plugin.h" + +GST_DEBUG_CATEGORY_STATIC (gst_cdda_base_src_debug); +#define GST_CAT_DEFAULT gst_cdda_base_src_debug + +#define DEFAULT_DEVICE "/dev/cdrom" + +#define CD_FRAMESIZE_RAW (2352) + +#define SECTORS_PER_SECOND (75) +#define SECTORS_PER_MINUTE (75*60) +#define SAMPLES_PER_SECTOR (CD_FRAMESIZE_RAW >> 2) +#define TIME_INTERVAL_FROM_SECTORS(sectors) ((SAMPLES_PER_SECTOR * sectors * GST_SECOND) / 44100) +#define SECTORS_FROM_TIME_INTERVAL(dtime) (dtime * 44100 / (SAMPLES_PER_SECTOR * GST_SECOND)) + +enum +{ + ARG_0, + ARG_MODE, + ARG_DEVICE, + ARG_TRACK, + ARG_TOC_OFFSET, + ARG_TOC_BIAS +}; + +static void gst_cdda_base_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_cdda_base_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_cdda_base_src_finalize (GObject * obj); +static const GstQueryType *gst_cdda_base_src_get_query_types (GstPad * pad); +static gboolean gst_cdda_base_src_query (GstBaseSrc * src, GstQuery * query); +static gboolean gst_cdda_base_src_handle_event (GstBaseSrc * basesrc, + GstEvent * event); +static gboolean gst_cdda_base_src_do_seek (GstBaseSrc * basesrc, + GstSegment * segment); +static void gst_cdda_base_src_setup_interfaces (GType type); +static gboolean gst_cdda_base_src_start (GstBaseSrc * basesrc); +static gboolean gst_cdda_base_src_stop (GstBaseSrc * basesrc); +static GstFlowReturn gst_cdda_base_src_create (GstPushSrc * pushsrc, + GstBuffer ** buf); +static gboolean gst_cdda_base_src_is_seekable (GstBaseSrc * basesrc); +static void gst_cdda_base_src_update_duration (GstCddaBaseSrc * src); +static void gst_cdda_base_src_set_index (GstElement * src, GstIndex * index); +static GstIndex *gst_cdda_base_src_get_index (GstElement * src); + +GST_BOILERPLATE_FULL (GstCddaBaseSrc, gst_cdda_base_src, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_cdda_base_src_setup_interfaces); + +#define SRC_CAPS \ + "audio/x-raw-int, " \ + "endianness = (int) BYTE_ORDER, " \ + "signed = (boolean) true, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "rate = (int) 44100, " \ + "channels = (int) 2" \ + +static GstStaticPadTemplate gst_cdda_base_src_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (SRC_CAPS) + ); + +/* our two formats */ +static GstFormat track_format; +static GstFormat sector_format; + +GType +gst_cdda_base_src_mode_get_type (void) +{ + static GType mode_type; /* 0 */ + static const GEnumValue modes[] = { + {GST_CDDA_BASE_SRC_MODE_NORMAL, "Stream consists of a single track", + "normal"}, + {GST_CDDA_BASE_SRC_MODE_CONTINUOUS, "Stream consists of the whole disc", + "continuous"}, + {0, NULL, NULL} + }; + + if (mode_type == 0) + mode_type = g_enum_register_static ("GstCddaBaseSrcMode", modes); + + return mode_type; +} + +static void +gst_cdda_base_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_cdda_base_src_src_template)); + + /* our very own formats */ + track_format = gst_format_register ("track", "CD track"); + sector_format = gst_format_register ("sector", "CD sector"); + + /* register CDDA tags */ + gst_tag_register_musicbrainz_tags (); + +#if 0 + ///// FIXME: what type to use here? /////// + gst_tag_register (GST_TAG_CDDA_TRACK_TAGS, GST_TAG_FLAG_META, GST_TYPE_TAG_LIST, "track-tags", "CDDA taglist for one track", gst_tag_merge_use_first); ///////////// FIXME: right function??? /////// +#endif + + GST_DEBUG_CATEGORY_INIT (gst_cdda_base_src_debug, "cddabasesrc", 0, + "CDDA Base Source"); +} + +static void +gst_cdda_base_src_class_init (GstCddaBaseSrcClass * klass) +{ + GstElementClass *element_class; + GstPushSrcClass *pushsrc_class; + GstBaseSrcClass *basesrc_class; + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + element_class = (GstElementClass *) klass; + basesrc_class = (GstBaseSrcClass *) klass; + pushsrc_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_cdda_base_src_set_property; + gobject_class->get_property = gst_cdda_base_src_get_property; + gobject_class->finalize = gst_cdda_base_src_finalize; + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DEVICE, + g_param_spec_string ("device", "Device", "CD device location", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_MODE, + g_param_spec_enum ("mode", "Mode", "Mode", GST_TYPE_CDDA_BASE_SRC_MODE, + GST_CDDA_BASE_SRC_MODE_NORMAL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TRACK, + g_param_spec_uint ("track", "Track", "Track", 1, 99, 1, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + +#if 0 + /* Do we really need this toc adjustment stuff as properties? does the user + * have a chance to set it in practice, e.g. when using sound-juicer, rb, + * totem, whatever? Shouldn't we rather use environment variables + * for this? (tpm) */ + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_OFFSET, + g_param_spec_int ("toc-offset", "Table of contents offset", + "Add sectors to the values reported", G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_TOC_BIAS, + g_param_spec_boolean ("toc-bias", "Table of contents bias", + "Assume that the beginning offset of track 1 as reported in the TOC " + "will be addressed as LBA 0. Necessary for some Toshiba drives to " + "get track boundaries", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif + + element_class->set_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_set_index); + element_class->get_index = GST_DEBUG_FUNCPTR (gst_cdda_base_src_get_index); + + basesrc_class->start = GST_DEBUG_FUNCPTR (gst_cdda_base_src_start); + basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_cdda_base_src_stop); + basesrc_class->query = GST_DEBUG_FUNCPTR (gst_cdda_base_src_query); + basesrc_class->event = GST_DEBUG_FUNCPTR (gst_cdda_base_src_handle_event); + basesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_cdda_base_src_do_seek); + basesrc_class->is_seekable = + GST_DEBUG_FUNCPTR (gst_cdda_base_src_is_seekable); + + pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_cdda_base_src_create); +} + +static void +gst_cdda_base_src_init (GstCddaBaseSrc * src, GstCddaBaseSrcClass * klass) +{ + gst_pad_set_query_type_function (GST_BASE_SRC_PAD (src), + GST_DEBUG_FUNCPTR (gst_cdda_base_src_get_query_types)); + + /* we're not live and we operate in time */ + gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (src), FALSE); + + src->device = NULL; + src->mode = GST_CDDA_BASE_SRC_MODE_NORMAL; + src->uri_track = -1; +} + +static void +gst_cdda_base_src_finalize (GObject * obj) +{ + GstCddaBaseSrc *cddasrc = GST_CDDA_BASE_SRC (obj); + + g_free (cddasrc->uri); + g_free (cddasrc->device); + + if (cddasrc->index) + gst_object_unref (cddasrc->index); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_cdda_base_src_set_device (GstCddaBaseSrc * src, const gchar * device) +{ + if (src->device) + g_free (src->device); + src->device = NULL; + + if (!device) + return; + + /* skip multiple slashes */ + while (*device == '/' && *(device + 1) == '/') + device++; + +#ifdef __sun + /* + * On Solaris, /dev/rdsk is used for accessing the CD device, but some + * applications pass in /dev/dsk, so correct. + */ + if (strncmp (device, "/dev/dsk", 8) == 0) { + gchar *rdsk_value; + rdsk_value = g_strdup_printf ("/dev/rdsk%s", device + 8); + src->device = g_strdup (rdsk_value); + g_free (rdsk_value); + } else { +#endif + src->device = g_strdup (device); +#ifdef __sun + } +#endif +} + +static void +gst_cdda_base_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case ARG_MODE:{ + src->mode = g_value_get_enum (value); + break; + } + case ARG_DEVICE:{ + const gchar *dev = g_value_get_string (value); + + gst_cdda_base_src_set_device (src, dev); + break; + } + case ARG_TRACK:{ + guint track = g_value_get_uint (value); + + if (src->num_tracks > 0 && track > src->num_tracks) { + g_warning ("Invalid track %u", track); + } else if (track > 0 && src->tracks != NULL) { + src->cur_sector = src->tracks[track - 1].start; + src->uri_track = track; + } else { + src->uri_track = track; /* seek will be done in start() */ + } + break; + } + case ARG_TOC_OFFSET:{ + src->toc_offset = g_value_get_int (value); + break; + } + case ARG_TOC_BIAS:{ + src->toc_bias = g_value_get_boolean (value); + break; + } + default:{ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + GST_OBJECT_UNLOCK (src); +} + +static void +gst_cdda_base_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstCddaBaseSrcClass *klass = GST_CDDA_BASE_SRC_GET_CLASS (object); + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (object); + + GST_OBJECT_LOCK (src); + + switch (prop_id) { + case ARG_MODE: + g_value_set_enum (value, src->mode); + break; + case ARG_DEVICE:{ + if (src->device == NULL && klass->get_default_device != NULL) { + gchar *d = klass->get_default_device (src); + + if (d != NULL) { + g_value_set_string (value, DEFAULT_DEVICE); + g_free (d); + break; + } + } + if (src->device == NULL) + g_value_set_string (value, DEFAULT_DEVICE); + else + g_value_set_string (value, src->device); + break; + } + case ARG_TRACK:{ + if (src->num_tracks <= 0 && src->uri_track > 0) { + g_value_set_uint (value, src->uri_track); + } else { + g_value_set_uint (value, src->cur_track + 1); + } + break; + } + case ARG_TOC_OFFSET: + g_value_set_int (value, src->toc_offset); + break; + case ARG_TOC_BIAS: + g_value_set_boolean (value, src->toc_bias); + break; + default:{ + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + GST_OBJECT_UNLOCK (src); +} + +static gint +gst_cdda_base_src_get_track_from_sector (GstCddaBaseSrc * src, gint sector) +{ + gint i; + + for (i = 0; i < src->num_tracks; ++i) { + if (sector >= src->tracks[i].start && sector <= src->tracks[i].end) + return i; + } + return -1; +} + +static const GstQueryType * +gst_cdda_base_src_get_query_types (GstPad * pad) +{ + static const GstQueryType src_query_types[] = { + GST_QUERY_DURATION, + GST_QUERY_POSITION, + GST_QUERY_CONVERT, + 0 + }; + + return src_query_types; +} + +static gboolean +gst_cdda_base_src_convert (GstCddaBaseSrc * src, GstFormat src_format, + gint64 src_val, GstFormat dest_format, gint64 * dest_val) +{ + gboolean started; + + GST_LOG_OBJECT (src, "converting value %" G_GINT64_FORMAT " from %s into %s", + src_val, gst_format_get_name (src_format), + gst_format_get_name (dest_format)); + + if (src_format == dest_format) { + *dest_val = src_val; + return TRUE; + } + + started = GST_OBJECT_FLAG_IS_SET (GST_BASE_SRC (src), GST_BASE_SRC_STARTED); + + if (src_format == track_format) { + if (!started) + goto not_started; + if (src_val < 0 || src_val >= src->num_tracks) { + GST_DEBUG_OBJECT (src, "track number %d out of bounds", (gint) src_val); + goto wrong_value; + } + src_format = GST_FORMAT_DEFAULT; + src_val = src->tracks[src_val].start * SAMPLES_PER_SECTOR; + } else if (src_format == sector_format) { + src_format = GST_FORMAT_DEFAULT; + src_val = src_val * SAMPLES_PER_SECTOR; + } + + if (src_format == dest_format) { + *dest_val = src_val; + goto done; + } + + switch (src_format) { + case GST_FORMAT_BYTES: + /* convert to samples (4 bytes per sample) */ + src_val = src_val >> 2; + /* fallthrough */ + case GST_FORMAT_DEFAULT:{ + switch (dest_format) { + case GST_FORMAT_BYTES:{ + if (src_val < 0) { + GST_DEBUG_OBJECT (src, "sample source value negative"); + goto wrong_value; + } + *dest_val = src_val << 2; /* 4 bytes per sample */ + break; + } + case GST_FORMAT_TIME:{ + *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, 44100); + break; + } + default:{ + gint64 sector = src_val / SAMPLES_PER_SECTOR; + + if (dest_format == sector_format) { + *dest_val = sector; + } else if (dest_format == track_format) { + if (!started) + goto not_started; + *dest_val = gst_cdda_base_src_get_track_from_sector (src, sector); + } else { + goto unknown_format; + } + break; + } + } + break; + } + case GST_FORMAT_TIME:{ + gint64 sample_offset; + + if (src_val == GST_CLOCK_TIME_NONE) { + GST_DEBUG_OBJECT (src, "source time value invalid"); + goto wrong_value; + } + + sample_offset = gst_util_uint64_scale_int (src_val, 44100, GST_SECOND); + switch (dest_format) { + case GST_FORMAT_BYTES:{ + *dest_val = sample_offset << 2; /* 4 bytes per sample */ + break; + } + case GST_FORMAT_DEFAULT:{ + *dest_val = sample_offset; + break; + } + default:{ + gint64 sector = sample_offset / SAMPLES_PER_SECTOR; + + if (dest_format == sector_format) { + *dest_val = sector; + } else if (dest_format == track_format) { + if (!started) + goto not_started; + *dest_val = gst_cdda_base_src_get_track_from_sector (src, sector); + } else { + goto unknown_format; + } + break; + } + } + break; + } + default:{ + goto unknown_format; + } + } + +done: + { + GST_LOG_OBJECT (src, "returning %" G_GINT64_FORMAT, *dest_val); + return TRUE; + } + +unknown_format: + { + GST_DEBUG_OBJECT (src, "conversion failed: %s", "unsupported format"); + return FALSE; + } + +wrong_value: + { + GST_DEBUG_OBJECT (src, "conversion failed: %s", + "source value not within allowed range"); + return FALSE; + } + +not_started: + { + GST_DEBUG_OBJECT (src, "conversion failed: %s", + "cannot do this conversion, device not open"); + return FALSE; + } +} + +static gboolean +gst_cdda_base_src_query (GstBaseSrc * basesrc, GstQuery * query) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (basesrc); + gboolean started; + + started = GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED); + + GST_LOG_OBJECT (src, "handling %s query", + gst_query_type_get_name (GST_QUERY_TYPE (query))); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION:{ + GstFormat dest_format; + gint64 dest_val; + guint sectors; + + gst_query_parse_duration (query, &dest_format, NULL); + + if (!started) + return FALSE; + + g_assert (src->tracks != NULL); + + if (dest_format == track_format) { + GST_LOG_OBJECT (src, "duration: %d tracks", src->num_tracks); + gst_query_set_duration (query, track_format, src->num_tracks); + return TRUE; + } + + if (src->cur_track < 0 || src->cur_track >= src->num_tracks) + return FALSE; + + if (src->mode == GST_CDDA_BASE_SRC_MODE_NORMAL) { + sectors = src->tracks[src->cur_track].end - + src->tracks[src->cur_track].start + 1; + } else { + sectors = src->tracks[src->num_tracks - 1].end - + src->tracks[0].start + 1; + } + + /* ... and convert into final format */ + if (!gst_cdda_base_src_convert (src, sector_format, sectors, + dest_format, &dest_val)) { + return FALSE; + } + + gst_query_set_duration (query, dest_format, dest_val); + + GST_LOG ("duration: %u sectors, %" G_GINT64_FORMAT " in format %s", + sectors, dest_val, gst_format_get_name (dest_format)); + break; + } + case GST_QUERY_POSITION:{ + GstFormat dest_format; + gint64 pos_sector; + gint64 dest_val; + + gst_query_parse_position (query, &dest_format, NULL); + + if (!started) + return FALSE; + + g_assert (src->tracks != NULL); + + if (dest_format == track_format) { + GST_LOG_OBJECT (src, "position: track %d", src->cur_track); + gst_query_set_position (query, track_format, src->cur_track); + return TRUE; + } + + if (src->cur_track < 0 || src->cur_track >= src->num_tracks) + return FALSE; + + if (src->mode == GST_CDDA_BASE_SRC_MODE_NORMAL) { + pos_sector = src->cur_sector - src->tracks[src->cur_track].start; + } else { + pos_sector = src->cur_sector - src->tracks[0].start; + } + + if (!gst_cdda_base_src_convert (src, sector_format, pos_sector, + dest_format, &dest_val)) { + return FALSE; + } + + gst_query_set_position (query, dest_format, dest_val); + + GST_LOG ("position: sector %u, %" G_GINT64_FORMAT " in format %s", + (guint) pos_sector, dest_val, gst_format_get_name (dest_format)); + break; + } + case GST_QUERY_CONVERT:{ + GstFormat src_format, dest_format; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_format, &src_val, &dest_format, + NULL); + + if (!gst_cdda_base_src_convert (src, src_format, src_val, dest_format, + &dest_val)) { + return FALSE; + } + + gst_query_set_convert (query, src_format, src_val, dest_format, dest_val); + break; + } + default:{ + GST_DEBUG_OBJECT (src, "unhandled query, chaining up to parent class"); + return GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + } + } + + return TRUE; +} + +static gboolean +gst_cdda_base_src_is_seekable (GstBaseSrc * basesrc) +{ + return TRUE; +} + +static gboolean +gst_cdda_base_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (basesrc); + gint64 seek_sector; + + GST_DEBUG_OBJECT (src, "segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (segment->start), GST_TIME_ARGS (segment->stop)); + + if (!gst_cdda_base_src_convert (src, GST_FORMAT_TIME, segment->start, + sector_format, &seek_sector)) { + GST_WARNING_OBJECT (src, "conversion failed"); + return FALSE; + } + + /* we should only really be called when open */ + g_assert (src->cur_track >= 0 && src->cur_track < src->num_tracks); + + switch (src->mode) { + case GST_CDDA_BASE_SRC_MODE_NORMAL: + seek_sector += src->tracks[src->cur_track].start; + break; + case GST_CDDA_BASE_SRC_MODE_CONTINUOUS: + seek_sector += src->tracks[0].start; + break; + default: + g_return_val_if_reached (FALSE); + } + + src->cur_sector = (gint) seek_sector; + + GST_DEBUG_OBJECT (src, "seek'd to sector %d", src->cur_sector); + + return TRUE; +} + +static gboolean +gst_cdda_base_src_handle_track_seek (GstCddaBaseSrc * src, gdouble rate, + GstSeekFlags flags, GstSeekType start_type, gint64 start, + GstSeekType stop_type, gint64 stop) +{ + GstBaseSrc *basesrc = GST_BASE_SRC (src); + GstEvent *event; + + if ((flags & GST_SEEK_FLAG_SEGMENT) == GST_SEEK_FLAG_SEGMENT) { + gint64 start_time = -1; + gint64 stop_time = -1; + + if (src->mode != GST_CDDA_BASE_SRC_MODE_CONTINUOUS) { + GST_DEBUG_OBJECT (src, "segment seek in track format is only " + "supported in CONTINUOUS mode, not in mode %d", src->mode); + return FALSE; + } + + switch (start_type) { + case GST_SEEK_TYPE_SET: + if (!gst_cdda_base_src_convert (src, track_format, start, + GST_FORMAT_TIME, &start_time)) { + GST_DEBUG_OBJECT (src, "cannot convert track %d to time", + (gint) start); + return FALSE; + } + break; + case GST_SEEK_TYPE_END: + if (!gst_cdda_base_src_convert (src, track_format, + src->num_tracks - start - 1, GST_FORMAT_TIME, &start_time)) { + GST_DEBUG_OBJECT (src, "cannot convert track %d to time", + (gint) start); + return FALSE; + } + start_type = GST_SEEK_TYPE_SET; + break; + case GST_SEEK_TYPE_NONE: + start_time = -1; + break; + default: + g_return_val_if_reached (FALSE); + } + + switch (stop_type) { + case GST_SEEK_TYPE_SET: + if (!gst_cdda_base_src_convert (src, track_format, stop, + GST_FORMAT_TIME, &stop_time)) { + GST_DEBUG_OBJECT (src, "cannot convert track %d to time", + (gint) stop); + return FALSE; + } + break; + case GST_SEEK_TYPE_END: + if (!gst_cdda_base_src_convert (src, track_format, + src->num_tracks - stop - 1, GST_FORMAT_TIME, &stop_time)) { + GST_DEBUG_OBJECT (src, "cannot convert track %d to time", + (gint) stop); + return FALSE; + } + stop_type = GST_SEEK_TYPE_SET; + break; + case GST_SEEK_TYPE_NONE: + stop_time = -1; + break; + default: + g_return_val_if_reached (FALSE); + } + + GST_LOG_OBJECT (src, "seek segment %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time), GST_TIME_ARGS (stop_time)); + + /* send fake segment seek event in TIME format to + * base class, which will hopefully handle the rest */ + + event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, start_type, + start_time, stop_type, stop_time); + + return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); + } + + /* not a segment seek */ + + if (start_type == GST_SEEK_TYPE_NONE) { + GST_LOG_OBJECT (src, "start seek type is NONE, nothing to do"); + return TRUE; + } + + if (stop_type != GST_SEEK_TYPE_NONE) { + GST_WARNING_OBJECT (src, "ignoring stop seek type (expected NONE)"); + } + + if (start < 0 || start >= src->num_tracks) { + GST_DEBUG_OBJECT (src, "invalid track %" G_GINT64_FORMAT, start); + return FALSE; + } + + GST_DEBUG_OBJECT (src, "seeking to track %" G_GINT64_FORMAT, start + 1); + + src->cur_sector = src->tracks[start].start; + GST_DEBUG_OBJECT (src, "starting at sector %d", src->cur_sector); + + if (src->cur_track != start) { + src->cur_track = (gint) start; + src->uri_track = -1; + src->prev_track = -1; + + gst_cdda_base_src_update_duration (src); + } else { + GST_DEBUG_OBJECT (src, "is current track, just seeking back to start"); + } + + /* send fake segment seek event in TIME format to + * base class (so we get a newsegment etc.) */ + event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + + return GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); +} + +static gboolean +gst_cdda_base_src_handle_event (GstBaseSrc * basesrc, GstEvent * event) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (basesrc); + gboolean ret = FALSE; + + GST_LOG_OBJECT (src, "handling %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + GstSeekType start_type, stop_type; + GstSeekFlags flags; + GstFormat format; + gdouble rate; + gint64 start, stop; + + if (!GST_OBJECT_FLAG_IS_SET (basesrc, GST_BASE_SRC_STARTED)) { + GST_DEBUG_OBJECT (src, "seek failed: device not open"); + break; + } + + gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, + &stop_type, &stop); + + if (format == sector_format) { + GST_DEBUG_OBJECT (src, "seek in sector format not supported"); + break; + } + + if (format == track_format) { + ret = gst_cdda_base_src_handle_track_seek (src, rate, flags, + start_type, start, stop_type, stop); + } else { + GST_LOG_OBJECT (src, "let base class handle seek in %s format", + gst_format_get_name (format)); + event = gst_event_ref (event); + ret = GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); + } + break; + } + default:{ + GST_LOG_OBJECT (src, "let base class handle event"); + ret = GST_BASE_SRC_CLASS (parent_class)->event (basesrc, event); + break; + } + } + + return ret; +} + +static GstURIType +gst_cdda_base_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_cdda_base_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "cdda", NULL }; + + return protocols; +} + +static const gchar * +gst_cdda_base_src_uri_get_uri (GstURIHandler * handler) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (handler); + + GST_OBJECT_LOCK (src); + + g_free (src->uri); + + if (GST_OBJECT_FLAG_IS_SET (GST_BASE_SRC (src), GST_BASE_SRC_STARTED)) { + src->uri = + g_strdup_printf ("cdda://%s#%d", src->device, + (src->uri_track > 0) ? src->uri_track : 1); + } else { + src->uri = g_strdup ("cdda://1"); + } + + GST_OBJECT_UNLOCK (src); + + return src->uri; +} + +/* Note: gst_element_make_from_uri() might call us with just 'cdda://' as + * URI and expects us to return TRUE then (and this might be in any state) */ + +/* We accept URIs of the format cdda://(device#track)|(track) */ + +static gboolean +gst_cdda_base_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (handler); + gchar *protocol; + const gchar *location; + gchar *track_number; + + GST_OBJECT_LOCK (src); + + protocol = gst_uri_get_protocol (uri); + if (!protocol || g_ascii_strcasecmp (protocol, "cdda") != 0) { + g_free (protocol); + goto failed; + } + g_free (protocol); + + location = uri + 7; + track_number = g_strrstr (location, "#"); + src->uri_track = 0; + /* FIXME 0.11: ignore URI fragments that look like device paths for + * the benefit of rhythmbox and possibly other applications. + */ + if (track_number && track_number[1] != '/') { + gchar *device, *nuri = g_strdup (uri); + + track_number = nuri + (track_number - uri); + *track_number = '\0'; + device = gst_uri_get_location (nuri); + gst_cdda_base_src_set_device (src, device); + g_free (device); + src->uri_track = strtol (track_number + 1, NULL, 10); + g_free (nuri); + } else { + if (*location == '\0') + src->uri_track = 1; + else + src->uri_track = strtol (location, NULL, 10); + } + + if (src->uri_track < 1) + goto failed; + + if (src->num_tracks > 0 + && src->tracks != NULL && src->uri_track > src->num_tracks) + goto failed; + + if (src->uri_track > 0 && src->tracks != NULL) { + GST_OBJECT_UNLOCK (src); + + gst_pad_send_event (GST_BASE_SRC_PAD (src), + gst_event_new_seek (1.0, track_format, GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, src->uri_track - 1, GST_SEEK_TYPE_NONE, -1)); + } else { + /* seek will be done in start() */ + GST_OBJECT_UNLOCK (src); + } + + GST_LOG_OBJECT (handler, "successfully handled uri '%s'", uri); + + return TRUE; + +failed: + { + GST_OBJECT_UNLOCK (src); + GST_DEBUG_OBJECT (src, "cannot handle URI '%s'", uri); + return FALSE; + } +} + +static void +gst_cdda_base_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_cdda_base_src_uri_get_type; + iface->get_uri = gst_cdda_base_src_uri_get_uri; + iface->set_uri = gst_cdda_base_src_uri_set_uri; + iface->get_protocols = gst_cdda_base_src_uri_get_protocols; +} + +static void +gst_cdda_base_src_setup_interfaces (GType type) +{ + static const GInterfaceInfo urihandler_info = { + gst_cdda_base_src_uri_handler_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &urihandler_info); +} + +/** + * gst_cdda_base_src_add_track: + * @src: a #GstCddaBaseSrc + * @track: address of #GstCddaBaseSrcTrack to add + * + * CDDA sources use this function from their start vfunc to announce the + * available data and audio tracks to the base source class. The caller + * should allocate @track on the stack, the base source will do a shallow + * copy of the structure (and take ownership of the taglist if there is one). + * + * Returns: FALSE on error, otherwise TRUE. + */ + +gboolean +gst_cdda_base_src_add_track (GstCddaBaseSrc * src, GstCddaBaseSrcTrack * track) +{ + g_return_val_if_fail (GST_IS_CDDA_BASE_SRC (src), FALSE); + g_return_val_if_fail (track != NULL, FALSE); + g_return_val_if_fail (track->num > 0, FALSE); + + GST_DEBUG_OBJECT (src, "adding track %2u (%2u) [%6u-%6u] [%5s], tags: %" + GST_PTR_FORMAT, src->num_tracks + 1, track->num, track->start, + track->end, (track->is_audio) ? "AUDIO" : "DATA ", track->tags); + + if (src->num_tracks > 0) { + guint end_of_previous_track = src->tracks[src->num_tracks - 1].end; + + if (track->start <= end_of_previous_track) { + GST_WARNING ("track %2u overlaps with previous tracks", track->num); + return FALSE; + } + } + + GST_OBJECT_LOCK (src); + + ++src->num_tracks; + src->tracks = g_renew (GstCddaBaseSrcTrack, src->tracks, src->num_tracks); + src->tracks[src->num_tracks - 1] = *track; + + GST_OBJECT_UNLOCK (src); + + return TRUE; +} + +static void +gst_cdda_base_src_update_duration (GstCddaBaseSrc * src) +{ + GstBaseSrc *basesrc; + GstFormat format; + gint64 duration; + + basesrc = GST_BASE_SRC (src); + + format = GST_FORMAT_TIME; + if (gst_pad_query_duration (GST_BASE_SRC_PAD (src), &format, &duration)) { + gst_segment_set_duration (&basesrc->segment, GST_FORMAT_TIME, duration); + } else { + gst_segment_set_duration (&basesrc->segment, GST_FORMAT_TIME, -1); + duration = GST_CLOCK_TIME_NONE; + } + + gst_element_post_message (GST_ELEMENT (src), + gst_message_new_duration (GST_OBJECT (src), GST_FORMAT_TIME, -1)); + + GST_LOG_OBJECT (src, "duration updated to %" GST_TIME_FORMAT, + GST_TIME_ARGS (duration)); +} + +#define CD_MSF_OFFSET 150 + +/* the cddb hash function */ +static guint +cddb_sum (gint n) +{ + guint ret; + + ret = 0; + while (n > 0) { + ret += (n % 10); + n /= 10; + } + return ret; +} + +static void +gst_cddabasesrc_calculate_musicbrainz_discid (GstCddaBaseSrc * src) +{ + GString *s; + GChecksum *sha; + guchar digest[20]; + gchar *ptr; + gchar tmp[9]; + gulong i; + guint leadout_sector; + gsize digest_len; + + s = g_string_new (NULL); + + leadout_sector = src->tracks[src->num_tracks - 1].end + 1 + CD_MSF_OFFSET; + + /* generate SHA digest */ + sha = g_checksum_new (G_CHECKSUM_SHA1); + g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[0].num); + g_string_append_printf (s, "%02X", src->tracks[0].num); + g_checksum_update (sha, (guchar *) tmp, 2); + + g_snprintf (tmp, sizeof (tmp), "%02X", src->tracks[src->num_tracks - 1].num); + g_string_append_printf (s, " %02X", src->tracks[src->num_tracks - 1].num); + g_checksum_update (sha, (guchar *) tmp, 2); + + g_snprintf (tmp, sizeof (tmp), "%08X", leadout_sector); + g_string_append_printf (s, " %08X", leadout_sector); + g_checksum_update (sha, (guchar *) tmp, 8); + + for (i = 0; i < 99; i++) { + if (i < src->num_tracks) { + guint frame_offset = src->tracks[i].start + CD_MSF_OFFSET; + + g_snprintf (tmp, sizeof (tmp), "%08X", frame_offset); + g_string_append_printf (s, " %08X", frame_offset); + g_checksum_update (sha, (guchar *) tmp, 8); + } else { + g_checksum_update (sha, (guchar *) "00000000", 8); + } + } + digest_len = 20; + g_checksum_get_digest (sha, (guint8 *) & digest, &digest_len); + + /* re-encode to base64 */ + ptr = g_base64_encode (digest, digest_len); + g_checksum_free (sha); + i = strlen (ptr); + + g_assert (i < sizeof (src->mb_discid) + 1); + memcpy (src->mb_discid, ptr, i); + src->mb_discid[i] = '\0'; + free (ptr); + + /* Replace '/', '+' and '=' by '_', '.' and '-' as specified on + * http://musicbrainz.org/doc/DiscIDCalculation + */ + for (ptr = src->mb_discid; *ptr != '\0'; ptr++) { + if (*ptr == '/') + *ptr = '_'; + else if (*ptr == '+') + *ptr = '.'; + else if (*ptr == '=') + *ptr = '-'; + } + + GST_DEBUG_OBJECT (src, "musicbrainz-discid = %s", src->mb_discid); + GST_DEBUG_OBJECT (src, "musicbrainz-discid-full = %s", s->str); + + gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_CDDA_MUSICBRAINZ_DISCID, src->mb_discid, + GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL, s->str, NULL); + + g_string_free (s, TRUE); +} + +static void +lba_to_msf (guint sector, guint * p_m, guint * p_s, guint * p_f, guint * p_secs) +{ + guint m, s, f; + + m = sector / SECTORS_PER_MINUTE; + sector = sector % SECTORS_PER_MINUTE; + s = sector / SECTORS_PER_SECOND; + f = sector % SECTORS_PER_SECOND; + + if (p_m) + *p_m = m; + if (p_s) + *p_s = s; + if (p_f) + *p_f = f; + if (p_secs) + *p_secs = s + (m * 60); +} + +static void +gst_cdda_base_src_calculate_cddb_id (GstCddaBaseSrc * src) +{ + GString *s; + guint first_sector = 0, last_sector = 0; + guint start_secs, end_secs, secs, len_secs; + guint total_secs, num_audio_tracks; + guint id, t, i; + + id = 0; + total_secs = 0; + num_audio_tracks = 0; + + /* FIXME: do we use offsets and duration of ALL tracks (data + audio) + * for the CDDB ID calculation, or only audio tracks? */ + for (i = 0; i < src->num_tracks; ++i) { + if (1) { /* src->tracks[i].is_audio) { */ + if (num_audio_tracks == 0) { + first_sector = src->tracks[i].start + CD_MSF_OFFSET; + } + last_sector = src->tracks[i].end + CD_MSF_OFFSET + 1; + ++num_audio_tracks; + + lba_to_msf (src->tracks[i].start + CD_MSF_OFFSET, NULL, NULL, NULL, + &secs); + + len_secs = (src->tracks[i].end - src->tracks[i].start + 1) / 75; + + GST_DEBUG_OBJECT (src, "track %02u: lsn %6u (%02u:%02u), " + "length: %u seconds (%02u:%02u)", + num_audio_tracks, src->tracks[i].start + CD_MSF_OFFSET, + secs / 60, secs % 60, len_secs, len_secs / 60, len_secs % 60); + + id += cddb_sum (secs); + total_secs += len_secs; + } + } + + /* first_sector = src->tracks[0].start + CD_MSF_OFFSET; */ + lba_to_msf (first_sector, NULL, NULL, NULL, &start_secs); + + /* last_sector = src->tracks[src->num_tracks-1].end + CD_MSF_OFFSET; */ + lba_to_msf (last_sector, NULL, NULL, NULL, &end_secs); + + GST_DEBUG_OBJECT (src, "first_sector = %u = %u secs (%02u:%02u)", + first_sector, start_secs, start_secs / 60, start_secs % 60); + GST_DEBUG_OBJECT (src, "last_sector = %u = %u secs (%02u:%02u)", + last_sector, end_secs, end_secs / 60, end_secs % 60); + + t = end_secs - start_secs; + + GST_DEBUG_OBJECT (src, "total length = %u secs (%02u:%02u), added title " + "lengths = %u seconds (%02u:%02u)", t, t / 60, t % 60, total_secs, + total_secs / 60, total_secs % 60); + + src->discid = ((id % 0xff) << 24 | t << 8 | num_audio_tracks); + + s = g_string_new (NULL); + g_string_append_printf (s, "%08x", src->discid); + + gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_CDDA_CDDB_DISCID, s->str, NULL); + + g_string_append_printf (s, " %u", src->num_tracks); + for (i = 0; i < src->num_tracks; ++i) { + g_string_append_printf (s, " %u", src->tracks[i].start + CD_MSF_OFFSET); + } + g_string_append_printf (s, " %u", t); + + gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_CDDA_CDDB_DISCID_FULL, s->str, NULL); + + GST_DEBUG_OBJECT (src, "cddb discid = %s", s->str); + + g_string_free (s, TRUE); +} + +static void +gst_cdda_base_src_add_tags (GstCddaBaseSrc * src) +{ + gint i; + + /* fill in details for each track */ + for (i = 0; i < src->num_tracks; ++i) { + gint64 duration; + guint num_sectors; + + if (src->tracks[i].tags == NULL) + src->tracks[i].tags = gst_tag_list_new (); + + num_sectors = src->tracks[i].end - src->tracks[i].start + 1; + gst_cdda_base_src_convert (src, sector_format, num_sectors, + GST_FORMAT_TIME, &duration); + + gst_tag_list_add (src->tracks[i].tags, + GST_TAG_MERGE_REPLACE, + GST_TAG_TRACK_NUMBER, i + 1, + GST_TAG_TRACK_COUNT, src->num_tracks, GST_TAG_DURATION, duration, NULL); + } + + /* now fill in per-album tags and include each track's tags + * in the album tags, so that interested parties can retrieve + * the relevant details for each track in one go */ + + /* /////////////////////////////// FIXME should we rather insert num_tracks + * tags by the name of 'track-tags' and have the caller use + * gst_tag_list_get_value_index() rather than use tag names incl. + * the track number ?? *//////////////////////////////////////// + + gst_tag_list_add (src->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_TRACK_COUNT, src->num_tracks, NULL); +#if 0 + for (i = 0; i < src->num_tracks; ++i) { + gst_tag_list_add (src->tags, GST_TAG_MERGE_APPEND, + GST_TAG_CDDA_TRACK_TAGS, src->tracks[i].tags, NULL); + } +#endif + + GST_DEBUG ("src->tags = %" GST_PTR_FORMAT, src->tags); +} + +static void +gst_cdda_base_src_add_index_associations (GstCddaBaseSrc * src) +{ + gint i; + + for (i = 0; i < src->num_tracks; i++) { + gint64 sector; + + sector = src->tracks[i].start; + gst_index_add_association (src->index, src->index_id, GST_ASSOCIATION_FLAG_KEY_UNIT, track_format, i, /* here we count from 0 */ + sector_format, sector, + GST_FORMAT_TIME, + (gint64) (((CD_FRAMESIZE_RAW >> 2) * sector * GST_SECOND) / 44100), + GST_FORMAT_BYTES, (gint64) (sector << 2), GST_FORMAT_DEFAULT, + (gint64) ((CD_FRAMESIZE_RAW >> 2) * sector), NULL); + } +} + +static void +gst_cdda_base_src_set_index (GstElement * element, GstIndex * index) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (element); + GstIndex *old; + + GST_OBJECT_LOCK (element); + old = src->index; + if (old == index) { + GST_OBJECT_UNLOCK (element); + return; + } + if (index) + gst_object_ref (index); + src->index = index; + GST_OBJECT_UNLOCK (element); + if (old) + gst_object_unref (old); + + if (index) { + gst_index_get_writer_id (index, GST_OBJECT (src), &src->index_id); + gst_index_add_format (index, src->index_id, track_format); + gst_index_add_format (index, src->index_id, sector_format); + } +} + + +static GstIndex * +gst_cdda_base_src_get_index (GstElement * element) +{ + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (element); + GstIndex *index; + + GST_OBJECT_LOCK (element); + if ((index = src->index)) + gst_object_ref (index); + GST_OBJECT_UNLOCK (element); + + return index; +} + +static gint +gst_cdda_base_src_track_sort_func (gconstpointer a, gconstpointer b, + gpointer foo) +{ + GstCddaBaseSrcTrack *track_a = ((GstCddaBaseSrcTrack *) a); + GstCddaBaseSrcTrack *track_b = ((GstCddaBaseSrcTrack *) b); + + /* sort data tracks to the end, and audio tracks by track number */ + if (track_a->is_audio == track_b->is_audio) + return (gint) track_a->num - (gint) track_b->num; + + if (track_a->is_audio) { + return -1; + } else { + return 1; + } +} + +static gboolean +gst_cdda_base_src_start (GstBaseSrc * basesrc) +{ + GstCddaBaseSrcClass *klass = GST_CDDA_BASE_SRC_GET_CLASS (basesrc); + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (basesrc); + gboolean ret; + gchar *device = NULL; + + src->discid = 0; + src->mb_discid[0] = '\0'; + + g_assert (klass->open != NULL); + + if (src->device != NULL) { + device = g_strdup (src->device); + } else if (klass->get_default_device != NULL) { + device = klass->get_default_device (src); + } + + if (device == NULL) + device = g_strdup (DEFAULT_DEVICE); + + GST_LOG_OBJECT (basesrc, "opening device %s", device); + + src->tags = gst_tag_list_new (); + + ret = klass->open (src, device); + g_free (device); + device = NULL; + + if (!ret) { + GST_DEBUG_OBJECT (basesrc, "failed to open device"); + /* subclass (should have) posted an error message with the details */ + gst_cdda_base_src_stop (basesrc); + return FALSE; + } + + if (src->num_tracks == 0 || src->tracks == NULL) { + GST_DEBUG_OBJECT (src, "no tracks"); + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("This CD has no audio tracks")), (NULL)); + gst_cdda_base_src_stop (basesrc); + return FALSE; + } + + /* need to calculate disc IDs before we ditch the data tracks */ + gst_cdda_base_src_calculate_cddb_id (src); + gst_cddabasesrc_calculate_musicbrainz_discid (src); + +#if 0 + /* adjust sector offsets if necessary */ + if (src->toc_bias) { + src->toc_offset -= src->tracks[0].start; + } + for (i = 0; i < src->num_tracks; ++i) { + src->tracks[i].start += src->toc_offset; + src->tracks[i].end += src->toc_offset; + } +#endif + + /* now that we calculated the various disc IDs, + * sort the data tracks to end and ignore them */ + src->num_all_tracks = src->num_tracks; + + g_qsort_with_data (src->tracks, src->num_tracks, + sizeof (GstCddaBaseSrcTrack), gst_cdda_base_src_track_sort_func, NULL); + + while (src->num_tracks > 0 && !src->tracks[src->num_tracks - 1].is_audio) + --src->num_tracks; + + if (src->num_tracks == 0) { + GST_DEBUG_OBJECT (src, "no audio tracks"); + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("This CD has no audio tracks")), (NULL)); + gst_cdda_base_src_stop (basesrc); + return FALSE; + } + + gst_cdda_base_src_add_tags (src); + + if (src->index && GST_INDEX_IS_WRITABLE (src->index)) + gst_cdda_base_src_add_index_associations (src); + + src->cur_track = 0; + src->prev_track = -1; + + if (src->uri_track > 0 && src->uri_track <= src->num_tracks) { + GST_LOG_OBJECT (src, "seek to track %d", src->uri_track); + src->cur_track = src->uri_track - 1; + src->uri_track = -1; + src->mode = GST_CDDA_BASE_SRC_MODE_NORMAL; + } + + src->cur_sector = src->tracks[src->cur_track].start; + GST_LOG_OBJECT (src, "starting at sector %d", src->cur_sector); + + gst_cdda_base_src_update_duration (src); + + return TRUE; +} + +static void +gst_cdda_base_src_clear_tracks (GstCddaBaseSrc * src) +{ + if (src->tracks != NULL) { + gint i; + + for (i = 0; i < src->num_all_tracks; ++i) { + if (src->tracks[i].tags) + gst_tag_list_free (src->tracks[i].tags); + } + + g_free (src->tracks); + src->tracks = NULL; + } + src->num_tracks = 0; + src->num_all_tracks = 0; +} + +static gboolean +gst_cdda_base_src_stop (GstBaseSrc * basesrc) +{ + GstCddaBaseSrcClass *klass = GST_CDDA_BASE_SRC_GET_CLASS (basesrc); + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (basesrc); + + g_assert (klass->close != NULL); + + klass->close (src); + + gst_cdda_base_src_clear_tracks (src); + + if (src->tags) { + gst_tag_list_free (src->tags); + src->tags = NULL; + } + + src->prev_track = -1; + src->cur_track = -1; + + return TRUE; +} + + +static GstFlowReturn +gst_cdda_base_src_create (GstPushSrc * pushsrc, GstBuffer ** buffer) +{ + GstCddaBaseSrcClass *klass = GST_CDDA_BASE_SRC_GET_CLASS (pushsrc); + GstCddaBaseSrc *src = GST_CDDA_BASE_SRC (pushsrc); + GstBuffer *buf; + GstFormat format; + gboolean eos; + + GstClockTime position = GST_CLOCK_TIME_NONE; + GstClockTime duration = GST_CLOCK_TIME_NONE; + gint64 qry_position; + + g_assert (klass->read_sector != NULL); + + switch (src->mode) { + case GST_CDDA_BASE_SRC_MODE_NORMAL: + eos = (src->cur_sector > src->tracks[src->cur_track].end); + break; + case GST_CDDA_BASE_SRC_MODE_CONTINUOUS: + eos = (src->cur_sector > src->tracks[src->num_tracks - 1].end); + src->cur_track = gst_cdda_base_src_get_track_from_sector (src, + src->cur_sector); + break; + default: + g_return_val_if_reached (GST_FLOW_ERROR); + } + + if (eos) { + src->prev_track = -1; + GST_DEBUG_OBJECT (src, "EOS at sector %d, cur_track=%d, mode=%d", + src->cur_sector, src->cur_track, src->mode); + /* base class will send EOS for us */ + return GST_FLOW_UNEXPECTED; + } + + if (src->prev_track != src->cur_track) { + GstTagList *tags; + + tags = gst_tag_list_merge (src->tags, src->tracks[src->cur_track].tags, + GST_TAG_MERGE_REPLACE); + GST_LOG_OBJECT (src, "announcing tags: %" GST_PTR_FORMAT, tags); + gst_element_found_tags_for_pad (GST_ELEMENT (src), + GST_BASE_SRC_PAD (src), tags); + src->prev_track = src->cur_track; + + gst_cdda_base_src_update_duration (src); + + g_object_notify (G_OBJECT (src), "track"); + } + + GST_LOG_OBJECT (src, "asking for sector %u", src->cur_sector); + + buf = klass->read_sector (src, src->cur_sector); + + if (buf == NULL) { + GST_WARNING_OBJECT (src, "failed to read sector %u", src->cur_sector); + return GST_FLOW_ERROR; + } + + if (GST_BUFFER_CAPS (buf) == NULL) { + gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); + } + + format = GST_FORMAT_TIME; + if (gst_pad_query_position (GST_BASE_SRC_PAD (src), &format, &qry_position)) { + gint64 next_ts = 0; + + position = (GstClockTime) qry_position; + + ++src->cur_sector; + if (gst_pad_query_position (GST_BASE_SRC_PAD (src), &format, &next_ts)) { + duration = (GstClockTime) (next_ts - qry_position); + } + --src->cur_sector; + } + + /* fallback duration: 4 bytes per sample, 44100 samples per second */ + if (duration == GST_CLOCK_TIME_NONE) { + duration = gst_util_uint64_scale_int (GST_BUFFER_SIZE (buf) >> 2, + GST_SECOND, 44100); + } + + GST_BUFFER_TIMESTAMP (buf) = position; + GST_BUFFER_DURATION (buf) = duration; + + GST_LOG_OBJECT (src, "pushing sector %d with timestamp %" GST_TIME_FORMAT, + src->cur_sector, GST_TIME_ARGS (position)); + + ++src->cur_sector; + + *buffer = buf; + + return GST_FLOW_OK; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.h new file mode 100644 index 0000000..b4c6f8e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/cdda/gstcddabasesrc.h @@ -0,0 +1,157 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * Copyright (C) 2005 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_CDDA_BASE_SRC_H__ +#define __GST_CDDA_BASE_SRC_H__ + +#include +#include + +/* must include this for backwards-compatibility so the + * GST_TAG_CDDA_* defines are included. Remove in 0.11 */ +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CDDA_BASE_SRC (gst_cdda_base_src_get_type()) +#define GST_CDDA_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_CDDA_BASE_SRC, GstCddaBaseSrc)) +#define GST_CDDA_BASE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_CDDA_BASE_SRC, GstCddaBaseSrcClass)) +#define GST_IS_CDDA_BASE_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_CDDA_BASE_SRC)) +#define GST_IS_CDDA_BASE_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_CDDA_BASE_SRC)) +#define GST_CDDA_BASE_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASE_SRC, GstCddaBaseSrcClass)) + +typedef struct _GstCddaBaseSrc GstCddaBaseSrc; +typedef struct _GstCddaBaseSrcClass GstCddaBaseSrcClass; +typedef struct _GstCddaBaseSrcTrack GstCddaBaseSrcTrack; + +/** + * GstCddaBaseSrcMode: + * @GST_CDDA_BASE_SRC_MODE_NORMAL : each single track is a stream + * @GST_CDDA_BASE_SRC_MODE_CONTINUOUS : the entire disc is a single stream + * + * Mode in which the CD audio source operates. Influences timestamping, + * EOS handling and seeking. + */ +typedef enum { + GST_CDDA_BASE_SRC_MODE_NORMAL, /* stream = one track */ + GST_CDDA_BASE_SRC_MODE_CONTINUOUS /* stream = whole disc */ +} GstCddaBaseSrcMode; + +#define GST_TYPE_CDDA_BASE_SRC_MODE (gst_cdda_base_src_mode_get_type ()) + +/** + * GstCddaBaseSrcTrack: + * @is_audio: Whether this is an audio track + * @num: Track number in TOC (usually starts from 1, but not always) + * @start: The first sector of this track (LBA) + * @end: The last sector of this track (LBA) + * @tags: Track-specific tags (e.g. from cd-text information), or NULL + * + * CD track abstraction to communicate TOC entries to the base class. + */ +struct _GstCddaBaseSrcTrack { + gboolean is_audio; /* TRUE if this is an audio track */ + guint num; /* real track number (usually starts from 1) */ + guint start; /* first sector of track (LBA, not LSN!) */ + guint end; /* last sector of track (LBA, not LSN!) */ + GstTagList *tags; /* NULL or tags for track (e.g. from cd-text) */ + + /*< private >*/ + guint _gst_reserved1[GST_PADDING/2]; + gpointer _gst_reserved2[GST_PADDING/2]; +}; + +struct _GstCddaBaseSrc { + GstPushSrc pushsrc; + + /*< protected >*/ /* for use by sub-classes only */ + GstTagList *tags; /* tags that apply to all tracks */ + + /*< private >*/ + GstCddaBaseSrcMode mode; + + gchar *device; + + guint num_tracks; + guint num_all_tracks; + GstCddaBaseSrcTrack *tracks; + + gint cur_track; /* current track (starting from 0) */ + gint prev_track; /* current track last time */ + gint cur_sector; /* current sector */ + gint seek_sector; /* -1 or sector to seek to */ + + gint uri_track; + gchar *uri; + + guint32 discid; /* cddb disc id (for unit test) */ + gchar mb_discid[32]; /* musicbrainz discid */ + + GstIndex *index; + gint index_id; + + gint toc_offset; + gboolean toc_bias; + + /*< private >*/ + guint _gst_reserved1[GST_PADDING/2]; + gpointer _gst_reserved2[GST_PADDING/2]; +}; + +struct _GstCddaBaseSrcClass { + GstPushSrcClass pushsrc_class; + + /* open/close the CD device */ + gboolean (*open) (GstCddaBaseSrc *src, const gchar *device); + void (*close) (GstCddaBaseSrc *src); + + /* read one sector (LBA) */ + GstBuffer * (*read_sector) (GstCddaBaseSrc *src, gint sector); + + /* return default device or NULL (optional) */ + gchar * (*get_default_device) (GstCddaBaseSrc *src); + + /* return NULL-terminated string array of CD devices, or NULL (optional) */ + gchar ** (*probe_devices) (GstCddaBaseSrc *src); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_cdda_base_src_get_type (void); +GType gst_cdda_base_src_mode_get_type (void); + +gboolean gst_cdda_base_src_add_track (GstCddaBaseSrc * src, + GstCddaBaseSrcTrack * track); + +#if 0 +/* + * GST_TAG_CDDA_TRACK_TAGS: + * + * Tag details for all available tracks + * FiXME: find out which type we want for this! + */ +#define GST_TAG_CDDA_TRACK_TAGS "track-tags" +#endif + +G_END_DECLS + +#endif /* __GST_CDDA_BASE_SRC_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/Makefile.am new file mode 100644 index 0000000..68606a5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/Makefile.am @@ -0,0 +1,103 @@ +lib_LTLIBRARIES = libgstfft-@GST_MAJORMINOR@.la + +libgstfft_@GST_MAJORMINOR@_includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/fft + +libgstfft_@GST_MAJORMINOR@_include_HEADERS = \ + gstfft.h \ + gstffts16.h \ + gstffts32.h \ + gstfftf32.h \ + gstfftf64.h + +noinst_HEADERS = \ + kiss_fft_s16.h \ + kiss_fft_s32.h \ + kiss_fft_f32.h \ + kiss_fft_f64.h \ + kiss_fftr_s16.h \ + kiss_fftr_s32.h \ + kiss_fftr_f32.h \ + kiss_fftr_f64.h \ + _kiss_fft_guts_s16.h \ + _kiss_fft_guts_s32.h \ + _kiss_fft_guts_f32.h \ + _kiss_fft_guts_f64.h + +libgstfft_@GST_MAJORMINOR@_la_SOURCES = \ + gstfft.c \ + gstffts16.c \ + gstffts32.c \ + gstfftf32.c \ + gstfftf64.c \ + kiss_fft_s16.c \ + kiss_fft_s32.c \ + kiss_fft_f32.c \ + kiss_fft_f64.c \ + kiss_fftr_s16.c \ + kiss_fftr_s32.c \ + kiss_fftr_f32.c \ + kiss_fftr_f64.c + +libgstfft_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(LIBM) +libgstfft_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS) +libgstfft_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +EXTRA_DIST = kiss_version + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstFft-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstfft_@GST_MAJORMINOR@_include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstfft_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/fft/%',$(libgstfft_@GST_MAJORMINOR@_include_HEADERS)) + +GstFft-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstfft-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstFft \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstfft-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-fft-@GST_MAJORMINOR@ \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am + androgenizer -:PROJECT libgstfft -:SHARED libgstfft-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstfft_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(libgstfft_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstfft_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstfft_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/fft \ + -:HEADERS $(libgstfftinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f32.h new file mode 100644 index 0000000..78d2e2e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f32.h @@ -0,0 +1,112 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_f32_scalar as either short or a float type + and defines + typedef struct { kiss_fft_f32_scalar r; kiss_fft_f32_scalar i; }kiss_fft_f32_cpx; */ +#include "kiss_fft_f32.h" +#include + +/* The 2*sizeof(size_t) alignment here is borrowed from + * GNU libc, so it should be good most everywhere. + * It is more conservative than is needed on some 64-bit + * platforms, but ia64 does require a 16-byte alignment. + * The SIMD extensions for x86 and ppc32 would want a + * larger alignment than this, but we don't need to + * do better than malloc. + * + * Borrowed from GLib's gobject/gtype.c + */ +#define STRUCT_ALIGNMENT (2 * sizeof (size_t)) +#define ALIGN_STRUCT(offset) \ + ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_f32_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_f32_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ + +#define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) +#define C_FIXDIV(c,div) /* NOOP */ +#define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +#define KISS_FFT_F32_COS(phase) (kiss_fft_f32_scalar) cos(phase) +#define KISS_FFT_F32_SIN(phase) (kiss_fft_f32_scalar) sin(phase) +#define HALF_OF(x) ((x)*.5) + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_F32_COS(phase);\ + (x)->i = KISS_FFT_F32_SIN(phase);\ + }while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f64.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f64.h new file mode 100644 index 0000000..4202716 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_f64.h @@ -0,0 +1,112 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_f64_scalar as either short or a float type + and defines + typedef struct { kiss_fft_f64_scalar r; kiss_fft_f64_scalar i; }kiss_fft_f64_cpx; */ +#include "kiss_fft_f64.h" +#include + +/* The 2*sizeof(size_t) alignment here is borrowed from + * GNU libc, so it should be good most everywhere. + * It is more conservative than is needed on some 64-bit + * platforms, but ia64 does require a 16-byte alignment. + * The SIMD extensions for x86 and ppc32 would want a + * larger alignment than this, but we don't need to + * do better than malloc. + * + * Borrowed from GLib's gobject/gtype.c + */ +#define STRUCT_ALIGNMENT (2 * sizeof (size_t)) +#define ALIGN_STRUCT(offset) \ + ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_f64_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_f64_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ + +#define S_MUL(a,b) ( (a)*(b) ) +#define C_MUL(m,a,b) \ + do{ (m).r = (a).r*(b).r - (a).i*(b).i;\ + (m).i = (a).r*(b).i + (a).i*(b).r; }while(0) +#define C_FIXDIV(c,div) /* NOOP */ +#define C_MULBYSCALAR( c, s ) \ + do{ (c).r *= (s);\ + (c).i *= (s); }while(0) + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +#define KISS_FFT_F64_COS(phase) (kiss_fft_f64_scalar) cos(phase) +#define KISS_FFT_F64_SIN(phase) (kiss_fft_f64_scalar) sin(phase) +#define HALF_OF(x) ((x)*.5) + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_F64_COS(phase);\ + (x)->i = KISS_FFT_F64_SIN(phase);\ + }while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s16.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s16.h new file mode 100644 index 0000000..2d8256e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s16.h @@ -0,0 +1,135 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_s16_scalar as either short or a float type + and defines + typedef struct { kiss_fft_s16_scalar r; kiss_fft_s16_scalar i; }kiss_fft_s16_cpx; */ +#include "kiss_fft_s16.h" +#include + +/* The 2*sizeof(size_t) alignment here is borrowed from + * GNU libc, so it should be good most everywhere. + * It is more conservative than is needed on some 64-bit + * platforms, but ia64 does require a 16-byte alignment. + * The SIMD extensions for x86 and ppc32 would want a + * larger alignment than this, but we don't need to + * do better than malloc. + * + * Borrowed from GLib's gobject/gtype.c + */ +#define STRUCT_ALIGNMENT (2 * sizeof (size_t)) +#define ALIGN_STRUCT(offset) \ + ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_s16_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_s16_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ +#define FRACBITS 15 +#define SAMPPROD int32_t +#define SAMP_MAX 32767 + +#define SAMP_MIN -SAMP_MAX + +#if defined(CHECK_OVERFLOW) +# define CHECK_OVERFLOW_OP(a,op,b) \ + if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ + fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } +#endif + + +# define smul(a,b) ( (SAMPPROD)(a)*(b) ) +# define sround( x ) (kiss_fft_s16_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) + +# define S_MUL(a,b) sround( smul(a,b) ) + +# define C_MUL(m,a,b) \ + do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ + (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) + +# define DIVSCALAR(x,k) \ + (x) = sround( smul( x, SAMP_MAX/k ) ) + +# define C_FIXDIV(c,div) \ + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = sround( smul( (c).r , s ) ) ;\ + (c).i = sround( smul( (c).i , s ) ) ; }while(0) + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +# define KISS_FFT_S16_COS(phase) floor(.5+SAMP_MAX * cos (phase)) +# define KISS_FFT_S16_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) +# define HALF_OF(x) ((x)>>1) + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_S16_COS(phase);\ + (x)->i = KISS_FFT_S16_SIN(phase);\ + }while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s32.h new file mode 100644 index 0000000..f0ec9c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/_kiss_fft_guts_s32.h @@ -0,0 +1,136 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* kiss_fft.h + defines kiss_fft_s32_scalar as either short or a float type + and defines + typedef struct { kiss_fft_s32_scalar r; kiss_fft_s32_scalar i; }kiss_fft_s32_cpx; */ +#include "kiss_fft_s32.h" +#include + +/* The 2*sizeof(size_t) alignment here is borrowed from + * GNU libc, so it should be good most everywhere. + * It is more conservative than is needed on some 64-bit + * platforms, but ia64 does require a 16-byte alignment. + * The SIMD extensions for x86 and ppc32 would want a + * larger alignment than this, but we don't need to + * do better than malloc. + * + * Borrowed from GLib's gobject/gtype.c + */ +#define STRUCT_ALIGNMENT (2 * sizeof (size_t)) +#define ALIGN_STRUCT(offset) \ + ((offset + (STRUCT_ALIGNMENT - 1)) & -STRUCT_ALIGNMENT) + +#define MAXFACTORS 32 +/* e.g. an fft of length 128 has 4 factors + as far as kissfft is concerned + 4*4*4*2 + */ + +struct kiss_fft_s32_state{ + int nfft; + int inverse; + int factors[2*MAXFACTORS]; + kiss_fft_s32_cpx twiddles[1]; +}; + +/* + Explanation of macros dealing with complex math: + + C_MUL(m,a,b) : m = a*b + C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise + C_SUB( res, a,b) : res = a - b + C_SUBFROM( res , a) : res -= a + C_ADDTO( res , a) : res += a + * */ + +#define FRACBITS 31 +#define SAMPPROD int64_t +#define SAMP_MAX 2147483647 + +#define SAMP_MIN -SAMP_MAX + +#if defined(CHECK_OVERFLOW) +# define CHECK_OVERFLOW_OP(a,op,b) \ + if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \ + fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); } +#endif + + +# define smul(a,b) ( (SAMPPROD)(a)*(b) ) +# define sround( x ) (kiss_fft_s32_scalar)( ( (x) + (1<<(FRACBITS-1)) ) >> FRACBITS ) + +# define S_MUL(a,b) sround( smul(a,b) ) + +# define C_MUL(m,a,b) \ + do{ (m).r = sround( smul((a).r,(b).r) - smul((a).i,(b).i) ); \ + (m).i = sround( smul((a).r,(b).i) + smul((a).i,(b).r) ); }while(0) + +# define DIVSCALAR(x,k) \ + (x) = sround( smul( x, SAMP_MAX/k ) ) + +# define C_FIXDIV(c,div) \ + do { DIVSCALAR( (c).r , div); \ + DIVSCALAR( (c).i , div); }while (0) + +# define C_MULBYSCALAR( c, s ) \ + do{ (c).r = sround( smul( (c).r , s ) ) ;\ + (c).i = sround( smul( (c).i , s ) ) ; }while(0) + +#ifndef CHECK_OVERFLOW_OP +# define CHECK_OVERFLOW_OP(a,op,b) /* noop */ +#endif + +#define C_ADD( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,+,(b).r)\ + CHECK_OVERFLOW_OP((a).i,+,(b).i)\ + (res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \ + }while(0) +#define C_SUB( res, a,b)\ + do { \ + CHECK_OVERFLOW_OP((a).r,-,(b).r)\ + CHECK_OVERFLOW_OP((a).i,-,(b).i)\ + (res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \ + }while(0) +#define C_ADDTO( res , a)\ + do { \ + CHECK_OVERFLOW_OP((res).r,+,(a).r)\ + CHECK_OVERFLOW_OP((res).i,+,(a).i)\ + (res).r += (a).r; (res).i += (a).i;\ + }while(0) + +#define C_SUBFROM( res , a)\ + do {\ + CHECK_OVERFLOW_OP((res).r,-,(a).r)\ + CHECK_OVERFLOW_OP((res).i,-,(a).i)\ + (res).r -= (a).r; (res).i -= (a).i; \ + }while(0) + + +# define KISS_FFT_S32_COS(phase) floor(.5+SAMP_MAX * cos (phase)) +# define KISS_FFT_S32_SIN(phase) floor(.5+SAMP_MAX * sin (phase)) +# define HALF_OF(x) ((x)>>1) + +#define kf_cexp(x,phase) \ + do{ \ + (x)->r = KISS_FFT_S32_COS(phase);\ + (x)->i = KISS_FFT_S32_SIN(phase);\ + }while(0) + + +/* a debugging function */ +#define pcpx(c)\ + fprintf(stderr,"%g + %gi\n",(double)((c)->r),(double)((c)->i) ) diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.c new file mode 100644 index 0000000..b1708c7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.c @@ -0,0 +1,54 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstfft + * @short_description: General FFT functions and declarations + * + * This library includes general definitions and functions, useful for + * all typed FFT classes. + */ + +#include + +#include "gstfft.h" +#include "kiss_fft_s16.h" + +/** + * gst_fft_next_fast_length: + * @n: Number for which the next fast length should be returned + * + * Returns the next number to @n that is entirely a product + * of 2, 3 and 5. Using this as the @len parameter for + * the different GstFFT types will provide the best performance. + * + * Returns: the next fast FFT length. + * + */ +gint +gst_fft_next_fast_length (gint n) +{ + gint half = (n + 1) / 2; + + /* It's the same for all data types so call the s16 + * version */ + + /* The real FFT needs an even length so calculate that */ + return 2 * kiss_fft_s16_next_fast_size (half); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.h new file mode 100644 index 0000000..fa5defe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfft.h @@ -0,0 +1,49 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#ifndef __GST_FFT_H__ +#define __GST_FFT_H__ + +/** + * GstFFTWindow: + * @GST_FFT_WINDOW_RECTANGULAR: Rectangular window + * @GST_FFT_WINDOW_HAMMING: Hamming window + * @GST_FFT_WINDOW_HANN: Hann (sometimes also called Hanning) window + * @GST_FFT_WINDOW_BARTLETT: Bartlett window + * @GST_FFT_WINDOW_BLACKMAN: Blackman window + * + * The various window functions available. + */ +typedef enum +{ + GST_FFT_WINDOW_RECTANGULAR, + GST_FFT_WINDOW_HAMMING, + GST_FFT_WINDOW_HANN, + GST_FFT_WINDOW_BARTLETT, + GST_FFT_WINDOW_BLACKMAN +} GstFFTWindow; + +/* Functions */ + +gint gst_fft_next_fast_length (gint n) G_GNUC_CONST; + +#endif /* __GST_FFT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.c new file mode 100644 index 0000000..4facb35 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.c @@ -0,0 +1,208 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "_kiss_fft_guts_f32.h" +#include "kiss_fftr_f32.h" +#include "gstfft.h" +#include "gstfftf32.h" + +/** + * SECTION:gstfftf32 + * @short_description: FFT functions for 32 bit float samples + * + * #GstFFTF32 provides a FFT implementation and related functions for + * 32 bit float samples. To use this call gst_fft_f32_new() for + * allocating a #GstFFTF32 instance with the appropiate parameters and + * then call gst_fft_f32_fft() or gst_fft_f32_inverse_fft() to perform the + * FFT or inverse FFT on a buffer of samples. + * + * After use free the #GstFFTF32 instance with gst_fft_f32_free(). + * + * For the best performance use gst_fft_next_fast_length() to get a + * number that is entirely a product of 2, 3 and 5 and use this as the + * @len parameter for gst_fft_f32_new(). + * + * The @len parameter specifies the number of samples in the time domain that + * will be processed or generated. The number of samples in the frequency domain + * is @len/2 + 1. To get n samples in the frequency domain use 2*n - 2 as @len. + * + * Before performing the FFT on time domain data it usually makes sense + * to apply a window function to it. For this gst_fft_f32_window() can comfortably + * be used. + * + * Be aware, that you can't simply run gst_fft_f32_inverse_fft() on the + * resulting frequency data of gst_fft_f32_fft() to get the original data back. + * The relation between them is iFFT (FFT (x)) = x * nfft where nfft is the + * length of the FFT. This also has to be taken into account when calculation + * the magnitude of the frequency data. + * + */ + +/** + * gst_fft_f32_new: + * @len: Length of the FFT in the time domain + * @inverse: %TRUE if the #GstFFTF32 instance should be used for the inverse FFT + * + * This returns a new #GstFFTF32 instance with the given parameters. It makes + * sense to keep one instance for several calls for speed reasons. + * + * @len must be even and to get the best performance a product of + * 2, 3 and 5. To get the next number with this characteristics use + * gst_fft_next_fast_length(). + * + * Returns: a new #GstFFTF32 instance. + */ +GstFFTF32 * +gst_fft_f32_new (gint len, gboolean inverse) +{ + GstFFTF32 *self; + gsize subsize = 0, memneeded; + + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len % 2 == 0, NULL); + + kiss_fftr_f32_alloc (len, (inverse) ? 1 : 0, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (GstFFTF32)) + subsize; + + self = (GstFFTF32 *) g_malloc0 (memneeded); + + self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTF32))); + self->cfg = kiss_fftr_f32_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize); + g_assert (self->cfg); + + self->inverse = inverse; + self->len = len; + + return self; +} + +/** + * gst_fft_f32_fft: + * @self: #GstFFTF32 instance for this call + * @timedata: Buffer of the samples in the time domain + * @freqdata: Target buffer for the samples in the frequency domain + * + * This performs the FFT on @timedata and puts the result in @freqdata. + * + * @timedata must have as many samples as specified with the @len parameter while + * allocating the #GstFFTF32 instance with gst_fft_f32_new(). + * + * @freqdata must be large enough to hold @len/2 + 1 #GstFFTF32Complex frequency + * domain samples. + * + */ +void +gst_fft_f32_fft (GstFFTF32 * self, const gfloat * timedata, + GstFFTF32Complex * freqdata) +{ + g_return_if_fail (self); + g_return_if_fail (!self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftr_f32 (self->cfg, timedata, (kiss_fft_f32_cpx *) freqdata); +} + +/** + * gst_fft_f32_inverse_fft: + * @self: #GstFFTF32 instance for this call + * @freqdata: Buffer of the samples in the frequency domain + * @timedata: Target buffer for the samples in the time domain + * + * This performs the inverse FFT on @freqdata and puts the result in @timedata. + * + * @freqdata must have @len/2 + 1 samples, where @len is the parameter specified + * while allocating the #GstFFTF32 instance with gst_fft_f32_new(). + * + * @timedata must be large enough to hold @len time domain samples. + * + */ +void +gst_fft_f32_inverse_fft (GstFFTF32 * self, const GstFFTF32Complex * freqdata, + gfloat * timedata) +{ + g_return_if_fail (self); + g_return_if_fail (self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftri_f32 (self->cfg, (kiss_fft_f32_cpx *) freqdata, timedata); +} + +/** + * gst_fft_f32_free: + * @self: #GstFFTF32 instance for this call + * + * This frees the memory allocated for @self. + * + */ +void +gst_fft_f32_free (GstFFTF32 * self) +{ + g_free (self); +} + +/** + * gst_fft_f32_window: + * @self: #GstFFTF32 instance for this call + * @timedata: Time domain samples + * @window: Window function to apply + * + * This calls the window function @window on the @timedata sample buffer. + * + */ +void +gst_fft_f32_window (GstFFTF32 * self, gfloat * timedata, GstFFTWindow window) +{ + gint i, len; + + g_return_if_fail (self); + g_return_if_fail (timedata); + + len = self->len; + + switch (window) { + case GST_FFT_WINDOW_RECTANGULAR: + /* do nothing */ + break; + case GST_FFT_WINDOW_HAMMING: + for (i = 0; i < len; i++) + timedata[i] *= (0.53836 - 0.46164 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_HANN: + for (i = 0; i < len; i++) + timedata[i] *= (0.5 - 0.5 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_BARTLETT: + for (i = 0; i < len; i++) + timedata[i] *= (1.0 - fabs ((2.0 * i - len) / len)); + break; + case GST_FFT_WINDOW_BLACKMAN: + for (i = 0; i < len; i++) + timedata[i] *= (0.42 - 0.5 * cos ((2.0 * i) / len) + + 0.08 * cos ((4.0 * i) / len)); + break; + default: + g_assert_not_reached (); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.h new file mode 100644 index 0000000..3b56b48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf32.h @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFT_F32_H__ +#define __GST_FFT_F32_H__ + +#include +#include + +#include "gstfft.h" + +typedef struct _GstFFTF32 GstFFTF32; +typedef struct _GstFFTF32Complex GstFFTF32Complex; + +/* FIXME 0.11: Move the struct definition to the sources, + * there's no reason to have it public. + */ +/** + * GstFFTF32: + * + * Instance structure for #GstFFTF32. + * + */ +struct _GstFFTF32 { + /* */ + void * cfg; + gboolean inverse; + gint len; + gpointer _padding[GST_PADDING]; +}; + +/* Copy of kiss_fft_f32_cpx for documentation reasons, + * do NOT change! */ + +/** + * GstFFTF32Complex: + * @r: Real part + * @i: Imaginary part + * + * Data type for complex numbers composed of + * 32 bit float. + * + */ +struct _GstFFTF32Complex +{ + gfloat r; + gfloat i; +}; + +/* Functions */ + +GstFFTF32 * gst_fft_f32_new (gint len, gboolean inverse); +void gst_fft_f32_fft (GstFFTF32 *self, const gfloat *timedata, GstFFTF32Complex *freqdata); +void gst_fft_f32_inverse_fft (GstFFTF32 *self, const GstFFTF32Complex *freqdata, gfloat *timedata); +void gst_fft_f32_free (GstFFTF32 *self); + +void gst_fft_f32_window (GstFFTF32 *self, gfloat *timedata, GstFFTWindow window); + +#endif /* __GST_FFT_F32_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.c new file mode 100644 index 0000000..5291f62 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.c @@ -0,0 +1,208 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "_kiss_fft_guts_f64.h" +#include "kiss_fftr_f64.h" +#include "gstfft.h" +#include "gstfftf64.h" + +/** + * SECTION:gstfftf64 + * @short_description: FFT functions for 64 bit float samples + * + * #GstFFTF64 provides a FFT implementation and related functions for + * 64 bit float samples. To use this call gst_fft_f64_new() for + * allocating a #GstFFTF64 instance with the appropiate parameters and + * then call gst_fft_f64_fft() or gst_fft_f64_inverse_fft() to perform the + * FFT or inverse FFT on a buffer of samples. + * + * After use free the #GstFFTF64 instance with gst_fft_f64_free(). + * + * For the best performance use gst_fft_next_fast_length() to get a + * number that is entirely a product of 2, 3 and 5 and use this as the + * @len parameter for gst_fft_f64_new(). + * + * The @len parameter specifies the number of samples in the time domain that + * will be processed or generated. The number of samples in the frequency domain + * is @len/2 + 1. To get n samples in the frequency domain use 2*n - 2 as @len. + * + * Before performing the FFT on time domain data it usually makes sense + * to apply a window function to it. For this gst_fft_f64_window() can comfortably + * be used. + * + * Be aware, that you can't simply run gst_fft_f32_inverse_fft() on the + * resulting frequency data of gst_fft_f32_fft() to get the original data back. + * The relation between them is iFFT (FFT (x)) = x * nfft where nfft is the + * length of the FFT. This also has to be taken into account when calculation + * the magnitude of the frequency data. + * + */ + +/** + * gst_fft_f64_new: + * @len: Length of the FFT in the time domain + * @inverse: %TRUE if the #GstFFTF64 instance should be used for the inverse FFT + * + * This returns a new #GstFFTF64 instance with the given parameters. It makes + * sense to keep one instance for several calls for speed reasons. + * + * @len must be even and to get the best performance a product of + * 2, 3 and 5. To get the next number with this characteristics use + * gst_fft_next_fast_length(). + * + * Returns: a new #GstFFTF64 instance. + */ +GstFFTF64 * +gst_fft_f64_new (gint len, gboolean inverse) +{ + GstFFTF64 *self; + gsize subsize = 0, memneeded; + + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len % 2 == 0, NULL); + + kiss_fftr_f64_alloc (len, (inverse) ? 1 : 0, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (GstFFTF64)) + subsize; + + self = (GstFFTF64 *) g_malloc0 (memneeded); + + self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTF64))); + self->cfg = kiss_fftr_f64_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize); + g_assert (self->cfg); + + self->inverse = inverse; + self->len = len; + + return self; +} + +/** + * gst_fft_f64_fft: + * @self: #GstFFTF64 instance for this call + * @timedata: Buffer of the samples in the time domain + * @freqdata: Target buffer for the samples in the frequency domain + * + * This performs the FFT on @timedata and puts the result in @freqdata. + * + * @timedata must have as many samples as specified with the @len parameter while + * allocating the #GstFFTF64 instance with gst_fft_f64_new(). + * + * @freqdata must be large enough to hold @len/2 + 1 #GstFFTF64Complex frequency + * domain samples. + * + */ +void +gst_fft_f64_fft (GstFFTF64 * self, const gdouble * timedata, + GstFFTF64Complex * freqdata) +{ + g_return_if_fail (self); + g_return_if_fail (!self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftr_f64 (self->cfg, timedata, (kiss_fft_f64_cpx *) freqdata); +} + +/** + * gst_fft_f64_inverse_fft: + * @self: #GstFFTF64 instance for this call + * @freqdata: Buffer of the samples in the frequency domain + * @timedata: Target buffer for the samples in the time domain + * + * This performs the inverse FFT on @freqdata and puts the result in @timedata. + * + * @freqdata must have @len/2 + 1 samples, where @len is the parameter specified + * while allocating the #GstFFTF64 instance with gst_fft_f64_new(). + * + * @timedata must be large enough to hold @len time domain samples. + * + */ +void +gst_fft_f64_inverse_fft (GstFFTF64 * self, const GstFFTF64Complex * freqdata, + gdouble * timedata) +{ + g_return_if_fail (self); + g_return_if_fail (self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftri_f64 (self->cfg, (kiss_fft_f64_cpx *) freqdata, timedata); +} + +/** + * gst_fft_f64_free: + * @self: #GstFFTF64 instance for this call + * + * This frees the memory allocated for @self. + * + */ +void +gst_fft_f64_free (GstFFTF64 * self) +{ + g_free (self); +} + +/** + * gst_fft_f64_window: + * @self: #GstFFTF64 instance for this call + * @timedata: Time domain samples + * @window: Window function to apply + * + * This calls the window function @window on the @timedata sample buffer. + * + */ +void +gst_fft_f64_window (GstFFTF64 * self, gdouble * timedata, GstFFTWindow window) +{ + gint i, len; + + g_return_if_fail (self); + g_return_if_fail (timedata); + + len = self->len; + + switch (window) { + case GST_FFT_WINDOW_RECTANGULAR: + /* do nothing */ + break; + case GST_FFT_WINDOW_HAMMING: + for (i = 0; i < len; i++) + timedata[i] *= (0.53836 - 0.46164 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_HANN: + for (i = 0; i < len; i++) + timedata[i] *= (0.5 - 0.5 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_BARTLETT: + for (i = 0; i < len; i++) + timedata[i] *= (1.0 - fabs ((2.0 * i - len) / len)); + break; + case GST_FFT_WINDOW_BLACKMAN: + for (i = 0; i < len; i++) + timedata[i] *= (0.42 - 0.5 * cos ((2.0 * i) / len) + + 0.08 * cos ((4.0 * i) / len)); + break; + default: + g_assert_not_reached (); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.h new file mode 100644 index 0000000..8ebbee4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstfftf64.h @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFT_F64_H__ +#define __GST_FFT_F64_H__ + +#include +#include + +#include "gstfft.h" + +typedef struct _GstFFTF64 GstFFTF64; +typedef struct _GstFFTF64Complex GstFFTF64Complex; + +/* FIXME 0.11: Move the struct definition to the sources, + * there's no reason to have it public. + */ +/** + * GstFFTF64: + * + * Instance structure for #GstFFTF64. + * + */ +struct _GstFFTF64 { + /* */ + void * cfg; + gboolean inverse; + gint len; + gpointer _padding[GST_PADDING]; +}; + +/* Copy of kiss_fft_f64_cpx for documentation reasons, + * do NOT change! */ + +/** + * GstFFTF64Complex: + * @r: Real part + * @i: Imaginary part + * + * Data type for complex numbers composed of + * 64 bit float. + * + */ +struct _GstFFTF64Complex +{ + gdouble r; + gdouble i; +}; + +/* Functions */ + +GstFFTF64 * gst_fft_f64_new (gint len, gboolean inverse); +void gst_fft_f64_fft (GstFFTF64 *self, const gdouble *timedata, GstFFTF64Complex *freqdata); +void gst_fft_f64_inverse_fft (GstFFTF64 *self, const GstFFTF64Complex *freqdata, gdouble *timedata); +void gst_fft_f64_free (GstFFTF64 *self); + +void gst_fft_f64_window (GstFFTF64 *self, gdouble *timedata, GstFFTWindow window); + +#endif /* __GST_FFT_F64_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.c new file mode 100644 index 0000000..53135d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.c @@ -0,0 +1,208 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "_kiss_fft_guts_s16.h" +#include "kiss_fftr_s16.h" +#include "gstfft.h" +#include "gstffts16.h" + +/** + * SECTION:gstffts16 + * @short_description: FFT functions for signed 16 bit integer samples + * + * #GstFFTS16 provides a FFT implementation and related functions for + * signed 16 bit integer samples. To use this call gst_fft_s16_new() for + * allocating a #GstFFTS16 instance with the appropiate parameters and + * then call gst_fft_s16_fft() or gst_fft_s16_inverse_fft() to perform the + * FFT or inverse FFT on a buffer of samples. + * + * After use free the #GstFFTS16 instance with gst_fft_s16_free(). + * + * For the best performance use gst_fft_next_fast_length() to get a + * number that is entirely a product of 2, 3 and 5 and use this as the + * @len parameter for gst_fft_s16_new(). + * + * The @len parameter specifies the number of samples in the time domain that + * will be processed or generated. The number of samples in the frequency domain + * is @len/2 + 1. To get n samples in the frequency domain use 2*n - 2 as @len. + * + * Before performing the FFT on time domain data it usually makes sense + * to apply a window function to it. For this gst_fft_s16_window() can comfortably + * be used. + * + * Be aware, that you can't simply run gst_fft_s16_inverse_fft() on the + * resulting frequency data of gst_fft_s16_fft() to get the original data back. + * The relation between them is iFFT (FFT (x)) = x / nfft where nfft is the + * length of the FFT. This also has to be taken into account when calculation + * the magnitude of the frequency data. + * + */ + +/** + * gst_fft_s16_new: + * @len: Length of the FFT in the time domain + * @inverse: %TRUE if the #GstFFTS16 instance should be used for the inverse FFT + * + * This returns a new #GstFFTS16 instance with the given parameters. It makes + * sense to keep one instance for several calls for speed reasons. + * + * @len must be even and to get the best performance a product of + * 2, 3 and 5. To get the next number with this characteristics use + * gst_fft_next_fast_length(). + * + * Returns: a new #GstFFTS16 instance. + */ +GstFFTS16 * +gst_fft_s16_new (gint len, gboolean inverse) +{ + GstFFTS16 *self; + gsize subsize = 0, memneeded; + + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len % 2 == 0, NULL); + + kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (GstFFTS16)) + subsize; + + self = (GstFFTS16 *) g_malloc0 (memneeded); + + self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTS16))); + self->cfg = kiss_fftr_s16_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize); + g_assert (self->cfg); + + self->inverse = inverse; + self->len = len; + + return self; +} + +/** + * gst_fft_s16_fft: + * @self: #GstFFTS16 instance for this call + * @timedata: Buffer of the samples in the time domain + * @freqdata: Target buffer for the samples in the frequency domain + * + * This performs the FFT on @timedata and puts the result in @freqdata. + * + * @timedata must have as many samples as specified with the @len parameter while + * allocating the #GstFFTS16 instance with gst_fft_s16_new(). + * + * @freqdata must be large enough to hold @len/2 + 1 #GstFFTS16Complex frequency + * domain samples. + * + */ +void +gst_fft_s16_fft (GstFFTS16 * self, const gint16 * timedata, + GstFFTS16Complex * freqdata) +{ + g_return_if_fail (self); + g_return_if_fail (!self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftr_s16 (self->cfg, timedata, (kiss_fft_s16_cpx *) freqdata); +} + +/** + * gst_fft_s16_inverse_fft: + * @self: #GstFFTS16 instance for this call + * @freqdata: Buffer of the samples in the frequency domain + * @timedata: Target buffer for the samples in the time domain + * + * This performs the inverse FFT on @freqdata and puts the result in @timedata. + * + * @freqdata must have @len/2 + 1 samples, where @len is the parameter specified + * while allocating the #GstFFTS16 instance with gst_fft_s16_new(). + * + * @timedata must be large enough to hold @len time domain samples. + * + */ +void +gst_fft_s16_inverse_fft (GstFFTS16 * self, const GstFFTS16Complex * freqdata, + gint16 * timedata) +{ + g_return_if_fail (self); + g_return_if_fail (self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftri_s16 (self->cfg, (kiss_fft_s16_cpx *) freqdata, timedata); +} + +/** + * gst_fft_s16_free: + * @self: #GstFFTS16 instance for this call + * + * This frees the memory allocated for @self. + * + */ +void +gst_fft_s16_free (GstFFTS16 * self) +{ + g_free (self); +} + +/** + * gst_fft_s16_window: + * @self: #GstFFTS16 instance for this call + * @timedata: Time domain samples + * @window: Window function to apply + * + * This calls the window function @window on the @timedata sample buffer. + * + */ +void +gst_fft_s16_window (GstFFTS16 * self, gint16 * timedata, GstFFTWindow window) +{ + gint i, len; + + g_return_if_fail (self); + g_return_if_fail (timedata); + + len = self->len; + + switch (window) { + case GST_FFT_WINDOW_RECTANGULAR: + /* do nothing */ + break; + case GST_FFT_WINDOW_HAMMING: + for (i = 0; i < len; i++) + timedata[i] *= (0.53836 - 0.46164 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_HANN: + for (i = 0; i < len; i++) + timedata[i] *= (0.5 - 0.5 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_BARTLETT: + for (i = 0; i < len; i++) + timedata[i] *= (1.0 - fabs ((2.0 * i - len) / len)); + break; + case GST_FFT_WINDOW_BLACKMAN: + for (i = 0; i < len; i++) + timedata[i] *= (0.42 - 0.5 * cos ((2.0 * i) / len) + + 0.08 * cos ((4.0 * i) / len)); + break; + default: + g_assert_not_reached (); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.h new file mode 100644 index 0000000..9a752f1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts16.h @@ -0,0 +1,74 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFT_S16_H__ +#define __GST_FFT_S16_H__ + +#include +#include + +#include "gstfft.h" + +typedef struct _GstFFTS16 GstFFTS16; +typedef struct _GstFFTS16Complex GstFFTS16Complex; + +/* FIXME 0.11: Move the struct definition to the sources, + * there's no reason to have it public. + */ +/** + * GstFFTS16: + * + * Instance structure for #GstFFTS16. + * + */ +struct _GstFFTS16 { + /* */ + void *cfg; + gboolean inverse; + gint len; + gpointer _padding[GST_PADDING]; +}; + +/* Copy of kiss_fft_s16_cpx for documentation reasons, + * do NOT change! */ + +/** + * GstFFTS16Complex: + * @r: Real part + * @i: Imaginary part + * + * Data type for complex numbers composed of + * signed 16 bit integers. + * + */ +struct _GstFFTS16Complex +{ + gint16 r; + gint16 i; +}; + +/* Functions */ + +GstFFTS16 * gst_fft_s16_new (gint len, gboolean inverse); +void gst_fft_s16_fft (GstFFTS16 *self, const gint16 *timedata, GstFFTS16Complex *freqdata); +void gst_fft_s16_inverse_fft (GstFFTS16 *self, const GstFFTS16Complex *freqdata, gint16 *timedata); +void gst_fft_s16_free (GstFFTS16 *self); + +void gst_fft_s16_window (GstFFTS16 *self, gint16 *timedata, GstFFTWindow window); +#endif /* __GST_FFT_S16_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.c new file mode 100644 index 0000000..2581318 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.c @@ -0,0 +1,207 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "_kiss_fft_guts_s32.h" +#include "kiss_fftr_s32.h" +#include "gstfft.h" +#include "gstffts32.h" + +/** + * SECTION:gstffts32 + * @short_description: FFT functions for signed 32 bit integer samples + * + * #GstFFTS32 provides a FFT implementation and related functions for + * signed 32 bit integer samples. To use this call gst_fft_s32_new() for + * allocating a #GstFFTS32 instance with the appropiate parameters and + * then call gst_fft_s32_fft() or gst_fft_s32_inverse_fft() to perform the + * FFT or inverse FFT on a buffer of samples. + * + * After use free the #GstFFTS32 instance with gst_fft_s32_free(). + * + * For the best performance use gst_fft_next_fast_length() to get a + * number that is entirely a product of 2, 3 and 5 and use this as the + * @len parameter for gst_fft_s32_new(). + * + * The @len parameter specifies the number of samples in the time domain that + * will be processed or generated. The number of samples in the frequency domain + * is @len/2 + 1. To get n samples in the frequency domain use 2*n - 2 as @len. + * + * Before performing the FFT on time domain data it usually makes sense + * to apply a window function to it. For this gst_fft_s32_window() can comfortably + * be used. + * + * Be aware, that you can't simply run gst_fft_s32_inverse_fft() on the + * resulting frequency data of gst_fft_s32_fft() to get the original data back. + * The relation between them is iFFT (FFT (x)) = x / nfft where nfft is the + * length of the FFT. This also has to be taken into account when calculation + * the magnitude of the frequency data. + */ + +/** + * gst_fft_s32_new: + * @len: Length of the FFT in the time domain + * @inverse: %TRUE if the #GstFFTS32 instance should be used for the inverse FFT + * + * This returns a new #GstFFTS32 instance with the given parameters. It makes + * sense to keep one instance for several calls for speed reasons. + * + * @len must be even and to get the best performance a product of + * 2, 3 and 5. To get the next number with this characteristics use + * gst_fft_next_fast_length(). + * + * Returns: a new #GstFFTS32 instance. + */ +GstFFTS32 * +gst_fft_s32_new (gint len, gboolean inverse) +{ + GstFFTS32 *self; + gsize subsize = 0, memneeded; + + g_return_val_if_fail (len > 0, NULL); + g_return_val_if_fail (len % 2 == 0, NULL); + + kiss_fftr_s32_alloc (len, (inverse) ? 1 : 0, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (GstFFTS32)) + subsize; + + self = (GstFFTS32 *) g_malloc0 (memneeded); + + self->cfg = (((guint8 *) self) + ALIGN_STRUCT (sizeof (GstFFTS32))); + self->cfg = kiss_fftr_s32_alloc (len, (inverse) ? 1 : 0, self->cfg, &subsize); + g_assert (self->cfg); + + self->inverse = inverse; + self->len = len; + + return self; +} + +/** + * gst_fft_s32_fft: + * @self: #GstFFTS32 instance for this call + * @timedata: Buffer of the samples in the time domain + * @freqdata: Target buffer for the samples in the frequency domain + * + * This performs the FFT on @timedata and puts the result in @freqdata. + * + * @timedata must have as many samples as specified with the @len parameter while + * allocating the #GstFFTS32 instance with gst_fft_s32_new(). + * + * @freqdata must be large enough to hold @len/2 + 1 #GstFFTS32Complex frequency + * domain samples. + * + */ +void +gst_fft_s32_fft (GstFFTS32 * self, const gint32 * timedata, + GstFFTS32Complex * freqdata) +{ + g_return_if_fail (self); + g_return_if_fail (!self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftr_s32 (self->cfg, timedata, (kiss_fft_s32_cpx *) freqdata); +} + +/** + * gst_fft_s32_inverse_fft: + * @self: #GstFFTS32 instance for this call + * @freqdata: Buffer of the samples in the frequency domain + * @timedata: Target buffer for the samples in the time domain + * + * This performs the inverse FFT on @freqdata and puts the result in @timedata. + * + * @freqdata must have @len/2 + 1 samples, where @len is the parameter specified + * while allocating the #GstFFTS32 instance with gst_fft_s32_new(). + * + * @timedata must be large enough to hold @len time domain samples. + * + */ +void +gst_fft_s32_inverse_fft (GstFFTS32 * self, const GstFFTS32Complex * freqdata, + gint32 * timedata) +{ + g_return_if_fail (self); + g_return_if_fail (self->inverse); + g_return_if_fail (timedata); + g_return_if_fail (freqdata); + + kiss_fftri_s32 (self->cfg, (kiss_fft_s32_cpx *) freqdata, timedata); +} + +/** + * gst_fft_s32_free: + * @self: #GstFFTS32 instance for this call + * + * This frees the memory allocated for @self. + * + */ +void +gst_fft_s32_free (GstFFTS32 * self) +{ + g_free (self); +} + +/** + * gst_fft_s32_window: + * @self: #GstFFTS32 instance for this call + * @timedata: Time domain samples + * @window: Window function to apply + * + * This calls the window function @window on the @timedata sample buffer. + * + */ +void +gst_fft_s32_window (GstFFTS32 * self, gint32 * timedata, GstFFTWindow window) +{ + gint i, len; + + g_return_if_fail (self); + g_return_if_fail (timedata); + + len = self->len; + + switch (window) { + case GST_FFT_WINDOW_RECTANGULAR: + /* do nothing */ + break; + case GST_FFT_WINDOW_HAMMING: + for (i = 0; i < len; i++) + timedata[i] *= (0.53836 - 0.46164 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_HANN: + for (i = 0; i < len; i++) + timedata[i] *= (0.5 - 0.5 * cos (2.0 * M_PI * i / len)); + break; + case GST_FFT_WINDOW_BARTLETT: + for (i = 0; i < len; i++) + timedata[i] *= (1.0 - fabs ((2.0 * i - len) / len)); + break; + case GST_FFT_WINDOW_BLACKMAN: + for (i = 0; i < len; i++) + timedata[i] *= (0.42 - 0.5 * cos ((2.0 * i) / len) + + 0.08 * cos ((4.0 * i) / len)); + break; + default: + g_assert_not_reached (); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.h new file mode 100644 index 0000000..fd3b279 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/gstffts32.h @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) <2007> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFT_S32_H__ +#define __GST_FFT_S32_H__ + +#include +#include + +#include "gstfft.h" + +typedef struct _GstFFTS32 GstFFTS32; +typedef struct _GstFFTS32Complex GstFFTS32Complex; + +/* FIXME 0.11: Move the struct definition to the sources, + * there's no reason to have it public. + */ +/** + * GstFFTS32: + * + * Instance structure for #GstFFTS32. + * + */ +struct _GstFFTS32 { + /* */ + void * cfg; + gboolean inverse; + gint len; + gpointer _padding[GST_PADDING]; +}; + +/* Copy of kiss_fft_s32_cpx for documentation reasons, + * do NOT change! */ + +/** + * GstFFTS32Complex: + * @r: Real part + * @i: Imaginary part + * + * Data type for complex numbers composed of + * signed 32 bit integers. + * + */ +struct _GstFFTS32Complex +{ + gint32 r; + gint32 i; +}; + +/* Functions */ + +GstFFTS32 * gst_fft_s32_new (gint len, gboolean inverse); +void gst_fft_s32_fft (GstFFTS32 *self, const gint32 *timedata, GstFFTS32Complex *freqdata); +void gst_fft_s32_inverse_fft (GstFFTS32 *self, const GstFFTS32Complex *freqdata, gint32 *timedata); +void gst_fft_s32_free (GstFFTS32 *self); + +void gst_fft_s32_window (GstFFTS32 *self, gint32 *timedata, GstFFTWindow window); + +#endif /* __GST_FFT_S32_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.c new file mode 100644 index 0000000..693a899 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.c @@ -0,0 +1,472 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "_kiss_fft_guts_f32.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static kiss_fft_f32_cpx *scratchbuf = NULL; +static size_t nscratchbuf = 0; +static kiss_fft_f32_cpx *tmpbuf = NULL; +static size_t ntmpbuf = 0; + +#define CHECKBUF(buf,nbuf,n) \ + do { \ + if ( nbuf < (size_t)(n) ) {\ + free(buf); \ + buf = (kiss_fft_f32_cpx*)KISS_FFT_F32_MALLOC(sizeof(kiss_fft_f32_cpx)*(n)); \ + nbuf = (size_t)(n); \ + } \ + }while(0) + + +static void +kf_bfly2 (kiss_fft_f32_cpx * Fout, + const size_t fstride, const kiss_fft_f32_cfg st, int m) +{ + kiss_fft_f32_cpx *Fout2; + kiss_fft_f32_cpx *tw1 = st->twiddles; + kiss_fft_f32_cpx t; + + Fout2 = Fout + m; + do { + C_FIXDIV (*Fout, 2); + C_FIXDIV (*Fout2, 2); + + C_MUL (t, *Fout2, *tw1); + tw1 += fstride; + C_SUB (*Fout2, *Fout, t); + C_ADDTO (*Fout, t); + ++Fout2; + ++Fout; + } while (--m); +} + +static void +kf_bfly4 (kiss_fft_f32_cpx * Fout, + const size_t fstride, const kiss_fft_f32_cfg st, const size_t m) +{ + kiss_fft_f32_cpx *tw1, *tw2, *tw3; + kiss_fft_f32_cpx scratch[6]; + size_t k = m; + const size_t m2 = 2 * m; + const size_t m3 = 3 * m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV (*Fout, 4); + C_FIXDIV (Fout[m], 4); + C_FIXDIV (Fout[m2], 4); + C_FIXDIV (Fout[m3], 4); + + C_MUL (scratch[0], Fout[m], *tw1); + C_MUL (scratch[1], Fout[m2], *tw2); + C_MUL (scratch[2], Fout[m3], *tw3); + + C_SUB (scratch[5], *Fout, scratch[1]); + C_ADDTO (*Fout, scratch[1]); + C_ADD (scratch[3], scratch[0], scratch[2]); + C_SUB (scratch[4], scratch[0], scratch[2]); + C_SUB (Fout[m2], *Fout, scratch[3]); + tw1 += fstride; + tw2 += fstride * 2; + tw3 += fstride * 3; + C_ADDTO (*Fout, scratch[3]); + + if (st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + } else { + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + } while (--k); +} + +static void +kf_bfly3 (kiss_fft_f32_cpx * Fout, + const size_t fstride, const kiss_fft_f32_cfg st, size_t m) +{ + size_t k = m; + const size_t m2 = 2 * m; + kiss_fft_f32_cpx *tw1, *tw2; + kiss_fft_f32_cpx scratch[5]; + kiss_fft_f32_cpx epi3; + + epi3 = st->twiddles[fstride * m]; + + tw1 = tw2 = st->twiddles; + + do { + C_FIXDIV (*Fout, 3); + C_FIXDIV (Fout[m], 3); + C_FIXDIV (Fout[m2], 3); + + C_MUL (scratch[1], Fout[m], *tw1); + C_MUL (scratch[2], Fout[m2], *tw2); + + C_ADD (scratch[3], scratch[1], scratch[2]); + C_SUB (scratch[0], scratch[1], scratch[2]); + tw1 += fstride; + tw2 += fstride * 2; + + Fout[m].r = Fout->r - HALF_OF (scratch[3].r); + Fout[m].i = Fout->i - HALF_OF (scratch[3].i); + + C_MULBYSCALAR (scratch[0], epi3.i); + + C_ADDTO (*Fout, scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while (--k); +} + +static void +kf_bfly5 (kiss_fft_f32_cpx * Fout, + const size_t fstride, const kiss_fft_f32_cfg st, int m) +{ + kiss_fft_f32_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4; + int u; + kiss_fft_f32_cpx scratch[13]; + kiss_fft_f32_cpx *twiddles = st->twiddles; + kiss_fft_f32_cpx *tw; + kiss_fft_f32_cpx ya, yb; + + ya = twiddles[fstride * m]; + yb = twiddles[fstride * 2 * m]; + + Fout0 = Fout; + Fout1 = Fout0 + m; + Fout2 = Fout0 + 2 * m; + Fout3 = Fout0 + 3 * m; + Fout4 = Fout0 + 4 * m; + + tw = st->twiddles; + for (u = 0; u < m; ++u) { + C_FIXDIV (*Fout0, 5); + C_FIXDIV (*Fout1, 5); + C_FIXDIV (*Fout2, 5); + C_FIXDIV (*Fout3, 5); + C_FIXDIV (*Fout4, 5); + scratch[0] = *Fout0; + + C_MUL (scratch[1], *Fout1, tw[u * fstride]); + C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]); + C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]); + C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]); + + C_ADD (scratch[7], scratch[1], scratch[4]); + C_SUB (scratch[10], scratch[1], scratch[4]); + C_ADD (scratch[8], scratch[2], scratch[3]); + C_SUB (scratch[9], scratch[2], scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = + scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r); + scratch[5].i = + scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r); + + scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i); + scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i); + + C_SUB (*Fout1, scratch[5], scratch[6]); + C_ADD (*Fout4, scratch[5], scratch[6]); + + scratch[11].r = + scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r); + scratch[11].i = + scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r); + scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i); + scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i); + + C_ADD (*Fout2, scratch[11], scratch[12]); + C_SUB (*Fout3, scratch[11], scratch[12]); + + ++Fout0; + ++Fout1; + ++Fout2; + ++Fout3; + ++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void +kf_bfly_generic (kiss_fft_f32_cpx * Fout, + const size_t fstride, const kiss_fft_f32_cfg st, int m, int p) +{ + int u, k, q1, q; + kiss_fft_f32_cpx *twiddles = st->twiddles; + kiss_fft_f32_cpx t; + int Norig = st->nfft; + + CHECKBUF (scratchbuf, nscratchbuf, p); + + for (u = 0; u < m; ++u) { + k = u; + for (q1 = 0; q1 < p; ++q1) { + scratchbuf[q1] = Fout[k]; + C_FIXDIV (scratchbuf[q1], p); + k += m; + } + + k = u; + for (q1 = 0; q1 < p; ++q1) { + int twidx = 0; + + Fout[k] = scratchbuf[0]; + for (q = 1; q < p; ++q) { + twidx += fstride * k; + if (twidx >= Norig) + twidx -= Norig; + C_MUL (t, scratchbuf[q], twiddles[twidx]); + C_ADDTO (Fout[k], t); + } + k += m; + } + } +} + +static void +kf_work (kiss_fft_f32_cpx * Fout, + const kiss_fft_f32_cpx * f, + const size_t fstride, + int in_stride, int *factors, const kiss_fft_f32_cfg st) +{ + kiss_fft_f32_cpx *Fout_beg = Fout; + const int p = *factors++; /* the radix */ + const int m = *factors++; /* stage's fft length/p */ + const kiss_fft_f32_cpx *Fout_end = Fout + p * m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride == 1) { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k = 0; k < p; ++k) + kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p, + in_stride, factors, st); + // all threads have joined by this point + + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } + return; + } +#endif + + if (m == 1) { + do { + *Fout = *f; + f += fstride * in_stride; + } while (++Fout != Fout_end); + } else { + do { + // recursive call: + // DFT of size m*p performed by doing + // p instances of smaller DFTs of size m, + // each one takes a decimated version of the input + kf_work (Fout, f, fstride * p, in_stride, factors, st); + f += fstride * in_stride; + } while ((Fout += m) != Fout_end); + } + + Fout = Fout_beg; + + // recombine the p smaller DFTs + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static void +kf_factor (int n, int *facbuf) +{ + int p = 4; + double floor_sqrt; + + floor_sqrt = floor (sqrt ((double) n)); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: + p = 2; + break; + case 2: + p = 3; + break; + default: + p += 2; + break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_f32_cfg +kiss_fft_f32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + kiss_fft_f32_cfg st = NULL; + size_t memneeded = sizeof (struct kiss_fft_f32_state) + + sizeof (kiss_fft_f32_cpx) * (nfft - 1); /* twiddle factors */ + + if (lenmem == NULL) { + st = (kiss_fft_f32_cfg) KISS_FFT_F32_MALLOC (memneeded); + } else { + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_f32_cfg) mem; + *lenmem = memneeded; + } + if (st) { + int i; + + st->nfft = nfft; + st->inverse = inverse_fft; + + for (i = 0; i < nfft; ++i) { + const double pi = + 3.141592653589793238462643383279502884197169399375105820974944; + double phase = -2 * pi * i / nfft; + + if (st->inverse) + phase *= -1; + kf_cexp (st->twiddles + i, phase); + } + + kf_factor (nfft, st->factors); + } + return st; +} + + + + +void +kiss_fft_f32_stride (kiss_fft_f32_cfg st, const kiss_fft_f32_cpx * fin, + kiss_fft_f32_cpx * fout, int in_stride) +{ + if (fin == fout) { + CHECKBUF (tmpbuf, ntmpbuf, st->nfft); + kf_work (tmpbuf, fin, 1, in_stride, st->factors, st); + memcpy (fout, tmpbuf, sizeof (kiss_fft_f32_cpx) * st->nfft); + } else { + kf_work (fout, fin, 1, in_stride, st->factors, st); + } +} + +void +kiss_fft_f32 (kiss_fft_f32_cfg cfg, const kiss_fft_f32_cpx * fin, + kiss_fft_f32_cpx * fout) +{ + kiss_fft_f32_stride (cfg, fin, fout, 1); +} + + +/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the + buffers from CHECKBUF + */ +void +kiss_fft_f32_cleanup (void) +{ + free (scratchbuf); + scratchbuf = NULL; + nscratchbuf = 0; + free (tmpbuf); + tmpbuf = NULL; + ntmpbuf = 0; +} + +int +kiss_fft_f32_next_fast_size (int n) +{ + while (1) { + int m = n; + + while ((m % 2) == 0) + m /= 2; + while ((m % 3) == 0) + m /= 3; + while ((m % 5) == 0) + m /= 5; + if (m <= 1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.h new file mode 100644 index 0000000..098b89d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f32.h @@ -0,0 +1,103 @@ +#ifndef KISS_FFT_F32_H +#define KISS_FFT_F32_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#define KISS_FFT_F32_MALLOC g_malloc +#define kiss_fft_f32_scalar float + +typedef struct { + kiss_fft_f32_scalar r; + kiss_fft_f32_scalar i; +}kiss_fft_f32_cpx; + +typedef struct kiss_fft_f32_state* kiss_fft_f32_cfg; + +/* + * kiss_fft_f32_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_f32_cfg mycfg=kiss_fft_f32_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_f32_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_f32_cfg kiss_fft_f32_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft_f32(kiss_fft_f32_cfg cfg,const kiss_fft_f32_cpx *fin,kiss_fft_f32_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_f32_stride(kiss_fft_f32_cfg cfg,const kiss_fft_f32_cpx *fin,kiss_fft_f32_cpx *fout,int fin_stride); + +/* If kiss_fft_f32_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_f32_free g_free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_f32_cleanup(void); + + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) + */ +int kiss_fft_f32_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.c new file mode 100644 index 0000000..b311711 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.c @@ -0,0 +1,472 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "_kiss_fft_guts_f64.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static kiss_fft_f64_cpx *scratchbuf = NULL; +static size_t nscratchbuf = 0; +static kiss_fft_f64_cpx *tmpbuf = NULL; +static size_t ntmpbuf = 0; + +#define CHECKBUF(buf,nbuf,n) \ + do { \ + if ( nbuf < (size_t)(n) ) {\ + free(buf); \ + buf = (kiss_fft_f64_cpx*)KISS_FFT_F64_MALLOC(sizeof(kiss_fft_f64_cpx)*(n)); \ + nbuf = (size_t)(n); \ + } \ + }while(0) + + +static void +kf_bfly2 (kiss_fft_f64_cpx * Fout, + const size_t fstride, const kiss_fft_f64_cfg st, int m) +{ + kiss_fft_f64_cpx *Fout2; + kiss_fft_f64_cpx *tw1 = st->twiddles; + kiss_fft_f64_cpx t; + + Fout2 = Fout + m; + do { + C_FIXDIV (*Fout, 2); + C_FIXDIV (*Fout2, 2); + + C_MUL (t, *Fout2, *tw1); + tw1 += fstride; + C_SUB (*Fout2, *Fout, t); + C_ADDTO (*Fout, t); + ++Fout2; + ++Fout; + } while (--m); +} + +static void +kf_bfly4 (kiss_fft_f64_cpx * Fout, + const size_t fstride, const kiss_fft_f64_cfg st, const size_t m) +{ + kiss_fft_f64_cpx *tw1, *tw2, *tw3; + kiss_fft_f64_cpx scratch[6]; + size_t k = m; + const size_t m2 = 2 * m; + const size_t m3 = 3 * m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV (*Fout, 4); + C_FIXDIV (Fout[m], 4); + C_FIXDIV (Fout[m2], 4); + C_FIXDIV (Fout[m3], 4); + + C_MUL (scratch[0], Fout[m], *tw1); + C_MUL (scratch[1], Fout[m2], *tw2); + C_MUL (scratch[2], Fout[m3], *tw3); + + C_SUB (scratch[5], *Fout, scratch[1]); + C_ADDTO (*Fout, scratch[1]); + C_ADD (scratch[3], scratch[0], scratch[2]); + C_SUB (scratch[4], scratch[0], scratch[2]); + C_SUB (Fout[m2], *Fout, scratch[3]); + tw1 += fstride; + tw2 += fstride * 2; + tw3 += fstride * 3; + C_ADDTO (*Fout, scratch[3]); + + if (st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + } else { + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + } while (--k); +} + +static void +kf_bfly3 (kiss_fft_f64_cpx * Fout, + const size_t fstride, const kiss_fft_f64_cfg st, size_t m) +{ + size_t k = m; + const size_t m2 = 2 * m; + kiss_fft_f64_cpx *tw1, *tw2; + kiss_fft_f64_cpx scratch[5]; + kiss_fft_f64_cpx epi3; + + epi3 = st->twiddles[fstride * m]; + + tw1 = tw2 = st->twiddles; + + do { + C_FIXDIV (*Fout, 3); + C_FIXDIV (Fout[m], 3); + C_FIXDIV (Fout[m2], 3); + + C_MUL (scratch[1], Fout[m], *tw1); + C_MUL (scratch[2], Fout[m2], *tw2); + + C_ADD (scratch[3], scratch[1], scratch[2]); + C_SUB (scratch[0], scratch[1], scratch[2]); + tw1 += fstride; + tw2 += fstride * 2; + + Fout[m].r = Fout->r - HALF_OF (scratch[3].r); + Fout[m].i = Fout->i - HALF_OF (scratch[3].i); + + C_MULBYSCALAR (scratch[0], epi3.i); + + C_ADDTO (*Fout, scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while (--k); +} + +static void +kf_bfly5 (kiss_fft_f64_cpx * Fout, + const size_t fstride, const kiss_fft_f64_cfg st, int m) +{ + kiss_fft_f64_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4; + int u; + kiss_fft_f64_cpx scratch[13]; + kiss_fft_f64_cpx *twiddles = st->twiddles; + kiss_fft_f64_cpx *tw; + kiss_fft_f64_cpx ya, yb; + + ya = twiddles[fstride * m]; + yb = twiddles[fstride * 2 * m]; + + Fout0 = Fout; + Fout1 = Fout0 + m; + Fout2 = Fout0 + 2 * m; + Fout3 = Fout0 + 3 * m; + Fout4 = Fout0 + 4 * m; + + tw = st->twiddles; + for (u = 0; u < m; ++u) { + C_FIXDIV (*Fout0, 5); + C_FIXDIV (*Fout1, 5); + C_FIXDIV (*Fout2, 5); + C_FIXDIV (*Fout3, 5); + C_FIXDIV (*Fout4, 5); + scratch[0] = *Fout0; + + C_MUL (scratch[1], *Fout1, tw[u * fstride]); + C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]); + C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]); + C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]); + + C_ADD (scratch[7], scratch[1], scratch[4]); + C_SUB (scratch[10], scratch[1], scratch[4]); + C_ADD (scratch[8], scratch[2], scratch[3]); + C_SUB (scratch[9], scratch[2], scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = + scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r); + scratch[5].i = + scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r); + + scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i); + scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i); + + C_SUB (*Fout1, scratch[5], scratch[6]); + C_ADD (*Fout4, scratch[5], scratch[6]); + + scratch[11].r = + scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r); + scratch[11].i = + scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r); + scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i); + scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i); + + C_ADD (*Fout2, scratch[11], scratch[12]); + C_SUB (*Fout3, scratch[11], scratch[12]); + + ++Fout0; + ++Fout1; + ++Fout2; + ++Fout3; + ++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void +kf_bfly_generic (kiss_fft_f64_cpx * Fout, + const size_t fstride, const kiss_fft_f64_cfg st, int m, int p) +{ + int u, k, q1, q; + kiss_fft_f64_cpx *twiddles = st->twiddles; + kiss_fft_f64_cpx t; + int Norig = st->nfft; + + CHECKBUF (scratchbuf, nscratchbuf, p); + + for (u = 0; u < m; ++u) { + k = u; + for (q1 = 0; q1 < p; ++q1) { + scratchbuf[q1] = Fout[k]; + C_FIXDIV (scratchbuf[q1], p); + k += m; + } + + k = u; + for (q1 = 0; q1 < p; ++q1) { + int twidx = 0; + + Fout[k] = scratchbuf[0]; + for (q = 1; q < p; ++q) { + twidx += fstride * k; + if (twidx >= Norig) + twidx -= Norig; + C_MUL (t, scratchbuf[q], twiddles[twidx]); + C_ADDTO (Fout[k], t); + } + k += m; + } + } +} + +static void +kf_work (kiss_fft_f64_cpx * Fout, + const kiss_fft_f64_cpx * f, + const size_t fstride, + int in_stride, int *factors, const kiss_fft_f64_cfg st) +{ + kiss_fft_f64_cpx *Fout_beg = Fout; + const int p = *factors++; /* the radix */ + const int m = *factors++; /* stage's fft length/p */ + const kiss_fft_f64_cpx *Fout_end = Fout + p * m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride == 1) { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k = 0; k < p; ++k) + kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p, + in_stride, factors, st); + // all threads have joined by this point + + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } + return; + } +#endif + + if (m == 1) { + do { + *Fout = *f; + f += fstride * in_stride; + } while (++Fout != Fout_end); + } else { + do { + // recursive call: + // DFT of size m*p performed by doing + // p instances of smaller DFTs of size m, + // each one takes a decimated version of the input + kf_work (Fout, f, fstride * p, in_stride, factors, st); + f += fstride * in_stride; + } while ((Fout += m) != Fout_end); + } + + Fout = Fout_beg; + + // recombine the p smaller DFTs + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static void +kf_factor (int n, int *facbuf) +{ + int p = 4; + double floor_sqrt; + + floor_sqrt = floor (sqrt ((double) n)); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: + p = 2; + break; + case 2: + p = 3; + break; + default: + p += 2; + break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_f64_cfg +kiss_fft_f64_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + kiss_fft_f64_cfg st = NULL; + const double pi = + 3.141592653589793238462643383279502884197169399375105820974944; + size_t memneeded = sizeof (struct kiss_fft_f64_state) + + sizeof (kiss_fft_f64_cpx) * (nfft - 1); /* twiddle factors */ + + if (lenmem == NULL) { + st = (kiss_fft_f64_cfg) KISS_FFT_F64_MALLOC (memneeded); + } else { + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_f64_cfg) mem; + *lenmem = memneeded; + } + if (st) { + int i; + + st->nfft = nfft; + st->inverse = inverse_fft; + + for (i = 0; i < nfft; ++i) { + double phase = -2 * pi * i / nfft; + + if (st->inverse) + phase *= -1; + kf_cexp (st->twiddles + i, phase); + } + + kf_factor (nfft, st->factors); + } + return st; +} + + + + +void +kiss_fft_f64_stride (kiss_fft_f64_cfg st, const kiss_fft_f64_cpx * fin, + kiss_fft_f64_cpx * fout, int in_stride) +{ + if (fin == fout) { + CHECKBUF (tmpbuf, ntmpbuf, st->nfft); + kf_work (tmpbuf, fin, 1, in_stride, st->factors, st); + memcpy (fout, tmpbuf, sizeof (kiss_fft_f64_cpx) * st->nfft); + } else { + kf_work (fout, fin, 1, in_stride, st->factors, st); + } +} + +void +kiss_fft_f64 (kiss_fft_f64_cfg cfg, const kiss_fft_f64_cpx * fin, + kiss_fft_f64_cpx * fout) +{ + kiss_fft_f64_stride (cfg, fin, fout, 1); +} + + +/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the + buffers from CHECKBUF + */ +void +kiss_fft_f64_cleanup (void) +{ + free (scratchbuf); + scratchbuf = NULL; + nscratchbuf = 0; + free (tmpbuf); + tmpbuf = NULL; + ntmpbuf = 0; +} + +int +kiss_fft_f64_next_fast_size (int n) +{ + while (1) { + int m = n; + + while ((m % 2) == 0) + m /= 2; + while ((m % 3) == 0) + m /= 3; + while ((m % 5) == 0) + m /= 5; + if (m <= 1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.h new file mode 100644 index 0000000..90792bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_f64.h @@ -0,0 +1,103 @@ +#ifndef KISS_FFT_F64_H +#define KISS_FFT_F64_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#define KISS_FFT_F64_MALLOC g_malloc +#define kiss_fft_f64_scalar double + +typedef struct { + kiss_fft_f64_scalar r; + kiss_fft_f64_scalar i; +}kiss_fft_f64_cpx; + +typedef struct kiss_fft_f64_state* kiss_fft_f64_cfg; + +/* + * kiss_fft_f64_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_f64_cfg mycfg=kiss_fft_f64_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_f64_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_f64_cfg kiss_fft_f64_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft_f64(kiss_fft_f64_cfg cfg,const kiss_fft_f64_cpx *fin,kiss_fft_f64_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_f64_stride(kiss_fft_f64_cfg cfg,const kiss_fft_f64_cpx *fin,kiss_fft_f64_cpx *fout,int fin_stride); + +/* If kiss_fft_f64_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_f64_free g_free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_f64_cleanup(void); + + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) + */ +int kiss_fft_f64_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.c new file mode 100644 index 0000000..ee2de4e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.c @@ -0,0 +1,472 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "_kiss_fft_guts_s16.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static kiss_fft_s16_cpx *scratchbuf = NULL; +static size_t nscratchbuf = 0; +static kiss_fft_s16_cpx *tmpbuf = NULL; +static size_t ntmpbuf = 0; + +#define CHECKBUF(buf,nbuf,n) \ + do { \ + if ( nbuf < (size_t)(n) ) {\ + free(buf); \ + buf = (kiss_fft_s16_cpx*)KISS_FFT_S16_MALLOC(sizeof(kiss_fft_s16_cpx)*(n)); \ + nbuf = (size_t)(n); \ + } \ + }while(0) + + +static void +kf_bfly2 (kiss_fft_s16_cpx * Fout, + const size_t fstride, const kiss_fft_s16_cfg st, int m) +{ + kiss_fft_s16_cpx *Fout2; + kiss_fft_s16_cpx *tw1 = st->twiddles; + kiss_fft_s16_cpx t; + + Fout2 = Fout + m; + do { + C_FIXDIV (*Fout, 2); + C_FIXDIV (*Fout2, 2); + + C_MUL (t, *Fout2, *tw1); + tw1 += fstride; + C_SUB (*Fout2, *Fout, t); + C_ADDTO (*Fout, t); + ++Fout2; + ++Fout; + } while (--m); +} + +static void +kf_bfly4 (kiss_fft_s16_cpx * Fout, + const size_t fstride, const kiss_fft_s16_cfg st, const size_t m) +{ + kiss_fft_s16_cpx *tw1, *tw2, *tw3; + kiss_fft_s16_cpx scratch[6]; + size_t k = m; + const size_t m2 = 2 * m; + const size_t m3 = 3 * m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV (*Fout, 4); + C_FIXDIV (Fout[m], 4); + C_FIXDIV (Fout[m2], 4); + C_FIXDIV (Fout[m3], 4); + + C_MUL (scratch[0], Fout[m], *tw1); + C_MUL (scratch[1], Fout[m2], *tw2); + C_MUL (scratch[2], Fout[m3], *tw3); + + C_SUB (scratch[5], *Fout, scratch[1]); + C_ADDTO (*Fout, scratch[1]); + C_ADD (scratch[3], scratch[0], scratch[2]); + C_SUB (scratch[4], scratch[0], scratch[2]); + C_SUB (Fout[m2], *Fout, scratch[3]); + tw1 += fstride; + tw2 += fstride * 2; + tw3 += fstride * 3; + C_ADDTO (*Fout, scratch[3]); + + if (st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + } else { + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + } while (--k); +} + +static void +kf_bfly3 (kiss_fft_s16_cpx * Fout, + const size_t fstride, const kiss_fft_s16_cfg st, size_t m) +{ + size_t k = m; + const size_t m2 = 2 * m; + kiss_fft_s16_cpx *tw1, *tw2; + kiss_fft_s16_cpx scratch[5]; + kiss_fft_s16_cpx epi3; + + epi3 = st->twiddles[fstride * m]; + + tw1 = tw2 = st->twiddles; + + do { + C_FIXDIV (*Fout, 3); + C_FIXDIV (Fout[m], 3); + C_FIXDIV (Fout[m2], 3); + + C_MUL (scratch[1], Fout[m], *tw1); + C_MUL (scratch[2], Fout[m2], *tw2); + + C_ADD (scratch[3], scratch[1], scratch[2]); + C_SUB (scratch[0], scratch[1], scratch[2]); + tw1 += fstride; + tw2 += fstride * 2; + + Fout[m].r = Fout->r - HALF_OF (scratch[3].r); + Fout[m].i = Fout->i - HALF_OF (scratch[3].i); + + C_MULBYSCALAR (scratch[0], epi3.i); + + C_ADDTO (*Fout, scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while (--k); +} + +static void +kf_bfly5 (kiss_fft_s16_cpx * Fout, + const size_t fstride, const kiss_fft_s16_cfg st, int m) +{ + kiss_fft_s16_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4; + int u; + kiss_fft_s16_cpx scratch[13]; + kiss_fft_s16_cpx *twiddles = st->twiddles; + kiss_fft_s16_cpx *tw; + kiss_fft_s16_cpx ya, yb; + + ya = twiddles[fstride * m]; + yb = twiddles[fstride * 2 * m]; + + Fout0 = Fout; + Fout1 = Fout0 + m; + Fout2 = Fout0 + 2 * m; + Fout3 = Fout0 + 3 * m; + Fout4 = Fout0 + 4 * m; + + tw = st->twiddles; + for (u = 0; u < m; ++u) { + C_FIXDIV (*Fout0, 5); + C_FIXDIV (*Fout1, 5); + C_FIXDIV (*Fout2, 5); + C_FIXDIV (*Fout3, 5); + C_FIXDIV (*Fout4, 5); + scratch[0] = *Fout0; + + C_MUL (scratch[1], *Fout1, tw[u * fstride]); + C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]); + C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]); + C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]); + + C_ADD (scratch[7], scratch[1], scratch[4]); + C_SUB (scratch[10], scratch[1], scratch[4]); + C_ADD (scratch[8], scratch[2], scratch[3]); + C_SUB (scratch[9], scratch[2], scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = + scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r); + scratch[5].i = + scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r); + + scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i); + scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i); + + C_SUB (*Fout1, scratch[5], scratch[6]); + C_ADD (*Fout4, scratch[5], scratch[6]); + + scratch[11].r = + scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r); + scratch[11].i = + scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r); + scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i); + scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i); + + C_ADD (*Fout2, scratch[11], scratch[12]); + C_SUB (*Fout3, scratch[11], scratch[12]); + + ++Fout0; + ++Fout1; + ++Fout2; + ++Fout3; + ++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void +kf_bfly_generic (kiss_fft_s16_cpx * Fout, + const size_t fstride, const kiss_fft_s16_cfg st, int m, int p) +{ + int u, k, q1, q; + kiss_fft_s16_cpx *twiddles = st->twiddles; + kiss_fft_s16_cpx t; + int Norig = st->nfft; + + CHECKBUF (scratchbuf, nscratchbuf, p); + + for (u = 0; u < m; ++u) { + k = u; + for (q1 = 0; q1 < p; ++q1) { + scratchbuf[q1] = Fout[k]; + C_FIXDIV (scratchbuf[q1], p); + k += m; + } + + k = u; + for (q1 = 0; q1 < p; ++q1) { + int twidx = 0; + + Fout[k] = scratchbuf[0]; + for (q = 1; q < p; ++q) { + twidx += fstride * k; + if (twidx >= Norig) + twidx -= Norig; + C_MUL (t, scratchbuf[q], twiddles[twidx]); + C_ADDTO (Fout[k], t); + } + k += m; + } + } +} + +static void +kf_work (kiss_fft_s16_cpx * Fout, + const kiss_fft_s16_cpx * f, + const size_t fstride, + int in_stride, int *factors, const kiss_fft_s16_cfg st) +{ + kiss_fft_s16_cpx *Fout_beg = Fout; + const int p = *factors++; /* the radix */ + const int m = *factors++; /* stage's fft length/p */ + const kiss_fft_s16_cpx *Fout_end = Fout + p * m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride == 1) { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k = 0; k < p; ++k) + kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p, + in_stride, factors, st); + // all threads have joined by this point + + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } + return; + } +#endif + + if (m == 1) { + do { + *Fout = *f; + f += fstride * in_stride; + } while (++Fout != Fout_end); + } else { + do { + // recursive call: + // DFT of size m*p performed by doing + // p instances of smaller DFTs of size m, + // each one takes a decimated version of the input + kf_work (Fout, f, fstride * p, in_stride, factors, st); + f += fstride * in_stride; + } while ((Fout += m) != Fout_end); + } + + Fout = Fout_beg; + + // recombine the p smaller DFTs + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static void +kf_factor (int n, int *facbuf) +{ + int p = 4; + double floor_sqrt; + + floor_sqrt = floor (sqrt ((double) n)); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: + p = 2; + break; + case 2: + p = 3; + break; + default: + p += 2; + break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_s16_cfg +kiss_fft_s16_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + kiss_fft_s16_cfg st = NULL; + size_t memneeded = sizeof (struct kiss_fft_s16_state) + + sizeof (kiss_fft_s16_cpx) * (nfft - 1); /* twiddle factors */ + + if (lenmem == NULL) { + st = (kiss_fft_s16_cfg) KISS_FFT_S16_MALLOC (memneeded); + } else { + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_s16_cfg) mem; + *lenmem = memneeded; + } + if (st) { + int i; + + st->nfft = nfft; + st->inverse = inverse_fft; + + for (i = 0; i < nfft; ++i) { + const double pi = + 3.141592653589793238462643383279502884197169399375105820974944; + double phase = -2 * pi * i / nfft; + + if (st->inverse) + phase *= -1; + kf_cexp (st->twiddles + i, phase); + } + + kf_factor (nfft, st->factors); + } + return st; +} + + + + +void +kiss_fft_s16_stride (kiss_fft_s16_cfg st, const kiss_fft_s16_cpx * fin, + kiss_fft_s16_cpx * fout, int in_stride) +{ + if (fin == fout) { + CHECKBUF (tmpbuf, ntmpbuf, st->nfft); + kf_work (tmpbuf, fin, 1, in_stride, st->factors, st); + memcpy (fout, tmpbuf, sizeof (kiss_fft_s16_cpx) * st->nfft); + } else { + kf_work (fout, fin, 1, in_stride, st->factors, st); + } +} + +void +kiss_fft_s16 (kiss_fft_s16_cfg cfg, const kiss_fft_s16_cpx * fin, + kiss_fft_s16_cpx * fout) +{ + kiss_fft_s16_stride (cfg, fin, fout, 1); +} + + +/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the + buffers from CHECKBUF + */ +void +kiss_fft_s16_cleanup (void) +{ + free (scratchbuf); + scratchbuf = NULL; + nscratchbuf = 0; + free (tmpbuf); + tmpbuf = NULL; + ntmpbuf = 0; +} + +int +kiss_fft_s16_next_fast_size (int n) +{ + while (1) { + int m = n; + + while ((m % 2) == 0) + m /= 2; + while ((m % 3) == 0) + m /= 3; + while ((m % 5) == 0) + m /= 5; + if (m <= 1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.h new file mode 100644 index 0000000..4303127 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s16.h @@ -0,0 +1,106 @@ +#ifndef KISS_FFT_S16_H +#define KISS_FFT_S16_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#define KISS_FFT_S16_MALLOC g_malloc + +#include "_stdint.h" + +#define kiss_fft_s16_scalar int16_t + +typedef struct { + kiss_fft_s16_scalar r; + kiss_fft_s16_scalar i; +}kiss_fft_s16_cpx; + +typedef struct kiss_fft_s16_state* kiss_fft_s16_cfg; + +/* + * kiss_fft_s16_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_s16_cfg mycfg=kiss_fft_s16_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_s16_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_s16_cfg kiss_fft_s16_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft_s16(kiss_fft_s16_cfg cfg,const kiss_fft_s16_cpx *fin,kiss_fft_s16_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_s16_stride(kiss_fft_s16_cfg cfg,const kiss_fft_s16_cpx *fin,kiss_fft_s16_cpx *fout,int fin_stride); + +/* If kiss_fft_s16_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_s16_free g_free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_s16_cleanup(void); + + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) + */ +int kiss_fft_s16_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.c new file mode 100644 index 0000000..5acb2ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.c @@ -0,0 +1,472 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + +#include "_kiss_fft_guts_s32.h" +/* The guts header contains all the multiplication and addition macros that are defined for + fixed or floating point complex numbers. It also delares the kf_ internal functions. + */ + +static kiss_fft_s32_cpx *scratchbuf = NULL; +static size_t nscratchbuf = 0; +static kiss_fft_s32_cpx *tmpbuf = NULL; +static size_t ntmpbuf = 0; + +#define CHECKBUF(buf,nbuf,n) \ + do { \ + if ( nbuf < (size_t)(n) ) {\ + free(buf); \ + buf = (kiss_fft_s32_cpx*)KISS_FFT_S32_MALLOC(sizeof(kiss_fft_s32_cpx)*(n)); \ + nbuf = (size_t)(n); \ + } \ + }while(0) + + +static void +kf_bfly2 (kiss_fft_s32_cpx * Fout, + const size_t fstride, const kiss_fft_s32_cfg st, int m) +{ + kiss_fft_s32_cpx *Fout2; + kiss_fft_s32_cpx *tw1 = st->twiddles; + kiss_fft_s32_cpx t; + + Fout2 = Fout + m; + do { + C_FIXDIV (*Fout, 2); + C_FIXDIV (*Fout2, 2); + + C_MUL (t, *Fout2, *tw1); + tw1 += fstride; + C_SUB (*Fout2, *Fout, t); + C_ADDTO (*Fout, t); + ++Fout2; + ++Fout; + } while (--m); +} + +static void +kf_bfly4 (kiss_fft_s32_cpx * Fout, + const size_t fstride, const kiss_fft_s32_cfg st, const size_t m) +{ + kiss_fft_s32_cpx *tw1, *tw2, *tw3; + kiss_fft_s32_cpx scratch[6]; + size_t k = m; + const size_t m2 = 2 * m; + const size_t m3 = 3 * m; + + tw3 = tw2 = tw1 = st->twiddles; + + do { + C_FIXDIV (*Fout, 4); + C_FIXDIV (Fout[m], 4); + C_FIXDIV (Fout[m2], 4); + C_FIXDIV (Fout[m3], 4); + + C_MUL (scratch[0], Fout[m], *tw1); + C_MUL (scratch[1], Fout[m2], *tw2); + C_MUL (scratch[2], Fout[m3], *tw3); + + C_SUB (scratch[5], *Fout, scratch[1]); + C_ADDTO (*Fout, scratch[1]); + C_ADD (scratch[3], scratch[0], scratch[2]); + C_SUB (scratch[4], scratch[0], scratch[2]); + C_SUB (Fout[m2], *Fout, scratch[3]); + tw1 += fstride; + tw2 += fstride * 2; + tw3 += fstride * 3; + C_ADDTO (*Fout, scratch[3]); + + if (st->inverse) { + Fout[m].r = scratch[5].r - scratch[4].i; + Fout[m].i = scratch[5].i + scratch[4].r; + Fout[m3].r = scratch[5].r + scratch[4].i; + Fout[m3].i = scratch[5].i - scratch[4].r; + } else { + Fout[m].r = scratch[5].r + scratch[4].i; + Fout[m].i = scratch[5].i - scratch[4].r; + Fout[m3].r = scratch[5].r - scratch[4].i; + Fout[m3].i = scratch[5].i + scratch[4].r; + } + ++Fout; + } while (--k); +} + +static void +kf_bfly3 (kiss_fft_s32_cpx * Fout, + const size_t fstride, const kiss_fft_s32_cfg st, size_t m) +{ + size_t k = m; + const size_t m2 = 2 * m; + kiss_fft_s32_cpx *tw1, *tw2; + kiss_fft_s32_cpx scratch[5]; + kiss_fft_s32_cpx epi3; + + epi3 = st->twiddles[fstride * m]; + + tw1 = tw2 = st->twiddles; + + do { + C_FIXDIV (*Fout, 3); + C_FIXDIV (Fout[m], 3); + C_FIXDIV (Fout[m2], 3); + + C_MUL (scratch[1], Fout[m], *tw1); + C_MUL (scratch[2], Fout[m2], *tw2); + + C_ADD (scratch[3], scratch[1], scratch[2]); + C_SUB (scratch[0], scratch[1], scratch[2]); + tw1 += fstride; + tw2 += fstride * 2; + + Fout[m].r = Fout->r - HALF_OF (scratch[3].r); + Fout[m].i = Fout->i - HALF_OF (scratch[3].i); + + C_MULBYSCALAR (scratch[0], epi3.i); + + C_ADDTO (*Fout, scratch[3]); + + Fout[m2].r = Fout[m].r + scratch[0].i; + Fout[m2].i = Fout[m].i - scratch[0].r; + + Fout[m].r -= scratch[0].i; + Fout[m].i += scratch[0].r; + + ++Fout; + } while (--k); +} + +static void +kf_bfly5 (kiss_fft_s32_cpx * Fout, + const size_t fstride, const kiss_fft_s32_cfg st, int m) +{ + kiss_fft_s32_cpx *Fout0, *Fout1, *Fout2, *Fout3, *Fout4; + int u; + kiss_fft_s32_cpx scratch[13]; + kiss_fft_s32_cpx *twiddles = st->twiddles; + kiss_fft_s32_cpx *tw; + kiss_fft_s32_cpx ya, yb; + + ya = twiddles[fstride * m]; + yb = twiddles[fstride * 2 * m]; + + Fout0 = Fout; + Fout1 = Fout0 + m; + Fout2 = Fout0 + 2 * m; + Fout3 = Fout0 + 3 * m; + Fout4 = Fout0 + 4 * m; + + tw = st->twiddles; + for (u = 0; u < m; ++u) { + C_FIXDIV (*Fout0, 5); + C_FIXDIV (*Fout1, 5); + C_FIXDIV (*Fout2, 5); + C_FIXDIV (*Fout3, 5); + C_FIXDIV (*Fout4, 5); + scratch[0] = *Fout0; + + C_MUL (scratch[1], *Fout1, tw[u * fstride]); + C_MUL (scratch[2], *Fout2, tw[2 * u * fstride]); + C_MUL (scratch[3], *Fout3, tw[3 * u * fstride]); + C_MUL (scratch[4], *Fout4, tw[4 * u * fstride]); + + C_ADD (scratch[7], scratch[1], scratch[4]); + C_SUB (scratch[10], scratch[1], scratch[4]); + C_ADD (scratch[8], scratch[2], scratch[3]); + C_SUB (scratch[9], scratch[2], scratch[3]); + + Fout0->r += scratch[7].r + scratch[8].r; + Fout0->i += scratch[7].i + scratch[8].i; + + scratch[5].r = + scratch[0].r + S_MUL (scratch[7].r, ya.r) + S_MUL (scratch[8].r, yb.r); + scratch[5].i = + scratch[0].i + S_MUL (scratch[7].i, ya.r) + S_MUL (scratch[8].i, yb.r); + + scratch[6].r = S_MUL (scratch[10].i, ya.i) + S_MUL (scratch[9].i, yb.i); + scratch[6].i = -S_MUL (scratch[10].r, ya.i) - S_MUL (scratch[9].r, yb.i); + + C_SUB (*Fout1, scratch[5], scratch[6]); + C_ADD (*Fout4, scratch[5], scratch[6]); + + scratch[11].r = + scratch[0].r + S_MUL (scratch[7].r, yb.r) + S_MUL (scratch[8].r, ya.r); + scratch[11].i = + scratch[0].i + S_MUL (scratch[7].i, yb.r) + S_MUL (scratch[8].i, ya.r); + scratch[12].r = -S_MUL (scratch[10].i, yb.i) + S_MUL (scratch[9].i, ya.i); + scratch[12].i = S_MUL (scratch[10].r, yb.i) - S_MUL (scratch[9].r, ya.i); + + C_ADD (*Fout2, scratch[11], scratch[12]); + C_SUB (*Fout3, scratch[11], scratch[12]); + + ++Fout0; + ++Fout1; + ++Fout2; + ++Fout3; + ++Fout4; + } +} + +/* perform the butterfly for one stage of a mixed radix FFT */ +static void +kf_bfly_generic (kiss_fft_s32_cpx * Fout, + const size_t fstride, const kiss_fft_s32_cfg st, int m, int p) +{ + int u, k, q1, q; + kiss_fft_s32_cpx *twiddles = st->twiddles; + kiss_fft_s32_cpx t; + int Norig = st->nfft; + + CHECKBUF (scratchbuf, nscratchbuf, p); + + for (u = 0; u < m; ++u) { + k = u; + for (q1 = 0; q1 < p; ++q1) { + scratchbuf[q1] = Fout[k]; + C_FIXDIV (scratchbuf[q1], p); + k += m; + } + + k = u; + for (q1 = 0; q1 < p; ++q1) { + int twidx = 0; + + Fout[k] = scratchbuf[0]; + for (q = 1; q < p; ++q) { + twidx += fstride * k; + if (twidx >= Norig) + twidx -= Norig; + C_MUL (t, scratchbuf[q], twiddles[twidx]); + C_ADDTO (Fout[k], t); + } + k += m; + } + } +} + +static void +kf_work (kiss_fft_s32_cpx * Fout, + const kiss_fft_s32_cpx * f, + const size_t fstride, + int in_stride, int *factors, const kiss_fft_s32_cfg st) +{ + kiss_fft_s32_cpx *Fout_beg = Fout; + const int p = *factors++; /* the radix */ + const int m = *factors++; /* stage's fft length/p */ + const kiss_fft_s32_cpx *Fout_end = Fout + p * m; + +#ifdef _OPENMP + // use openmp extensions at the + // top-level (not recursive) + if (fstride == 1) { + int k; + + // execute the p different work units in different threads +# pragma omp parallel for + for (k = 0; k < p; ++k) + kf_work (Fout + k * m, f + fstride * in_stride * k, fstride * p, + in_stride, factors, st); + // all threads have joined by this point + + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } + return; + } +#endif + + if (m == 1) { + do { + *Fout = *f; + f += fstride * in_stride; + } while (++Fout != Fout_end); + } else { + do { + // recursive call: + // DFT of size m*p performed by doing + // p instances of smaller DFTs of size m, + // each one takes a decimated version of the input + kf_work (Fout, f, fstride * p, in_stride, factors, st); + f += fstride * in_stride; + } while ((Fout += m) != Fout_end); + } + + Fout = Fout_beg; + + // recombine the p smaller DFTs + switch (p) { + case 2: + kf_bfly2 (Fout, fstride, st, m); + break; + case 3: + kf_bfly3 (Fout, fstride, st, m); + break; + case 4: + kf_bfly4 (Fout, fstride, st, m); + break; + case 5: + kf_bfly5 (Fout, fstride, st, m); + break; + default: + kf_bfly_generic (Fout, fstride, st, m, p); + break; + } +} + +/* facbuf is populated by p1,m1,p2,m2, ... + where + p[i] * m[i] = m[i-1] + m0 = n */ +static void +kf_factor (int n, int *facbuf) +{ + int p = 4; + double floor_sqrt; + + floor_sqrt = floor (sqrt ((double) n)); + + /*factor out powers of 4, powers of 2, then any remaining primes */ + do { + while (n % p) { + switch (p) { + case 4: + p = 2; + break; + case 2: + p = 3; + break; + default: + p += 2; + break; + } + if (p > floor_sqrt) + p = n; /* no more factors, skip to end */ + } + n /= p; + *facbuf++ = p; + *facbuf++ = n; + } while (n > 1); +} + +/* + * + * User-callable function to allocate all necessary storage space for the fft. + * + * The return value is a contiguous block of memory, allocated with malloc. As such, + * It can be freed with free(), rather than a kiss_fft-specific function. + * */ +kiss_fft_s32_cfg +kiss_fft_s32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + kiss_fft_s32_cfg st = NULL; + size_t memneeded = sizeof (struct kiss_fft_s32_state) + + sizeof (kiss_fft_s32_cpx) * (nfft - 1); /* twiddle factors */ + + if (lenmem == NULL) { + st = (kiss_fft_s32_cfg) KISS_FFT_S32_MALLOC (memneeded); + } else { + if (mem != NULL && *lenmem >= memneeded) + st = (kiss_fft_s32_cfg) mem; + *lenmem = memneeded; + } + if (st) { + int i; + + st->nfft = nfft; + st->inverse = inverse_fft; + + for (i = 0; i < nfft; ++i) { + const double pi = + 3.141592653589793238462643383279502884197169399375105820974944; + double phase = -2 * pi * i / nfft; + + if (st->inverse) + phase *= -1; + kf_cexp (st->twiddles + i, phase); + } + + kf_factor (nfft, st->factors); + } + return st; +} + + + + +void +kiss_fft_s32_stride (kiss_fft_s32_cfg st, const kiss_fft_s32_cpx * fin, + kiss_fft_s32_cpx * fout, int in_stride) +{ + if (fin == fout) { + CHECKBUF (tmpbuf, ntmpbuf, st->nfft); + kf_work (tmpbuf, fin, 1, in_stride, st->factors, st); + memcpy (fout, tmpbuf, sizeof (kiss_fft_s32_cpx) * st->nfft); + } else { + kf_work (fout, fin, 1, in_stride, st->factors, st); + } +} + +void +kiss_fft_s32 (kiss_fft_s32_cfg cfg, const kiss_fft_s32_cpx * fin, + kiss_fft_s32_cpx * fout) +{ + kiss_fft_s32_stride (cfg, fin, fout, 1); +} + + +/* not really necessary to call, but if someone is doing in-place ffts, they may want to free the + buffers from CHECKBUF + */ +void +kiss_fft_s32_cleanup (void) +{ + free (scratchbuf); + scratchbuf = NULL; + nscratchbuf = 0; + free (tmpbuf); + tmpbuf = NULL; + ntmpbuf = 0; +} + +int +kiss_fft_s32_next_fast_size (int n) +{ + while (1) { + int m = n; + + while ((m % 2) == 0) + m /= 2; + while ((m % 3) == 0) + m /= 3; + while ((m % 5) == 0) + m /= 5; + if (m <= 1) + break; /* n is completely factorable by twos, threes, and fives */ + n++; + } + return n; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.h new file mode 100644 index 0000000..8edd664 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fft_s32.h @@ -0,0 +1,107 @@ +#ifndef KISS_FFT_S32_H +#define KISS_FFT_S32_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + ATTENTION! + If you would like a : + -- a utility that will handle the caching of fft objects + -- real-only (no imaginary time component ) FFT + -- a multi-dimensional FFT + -- a command-line utility to perform ffts + -- a command-line utility to perform fast-convolution filtering + + Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c + in the tools/ directory. +*/ + +#define KISS_FFT_S32_MALLOC g_malloc + + +#include "_stdint.h" + +#define kiss_fft_s32_scalar int32_t + +typedef struct { + kiss_fft_s32_scalar r; + kiss_fft_s32_scalar i; +}kiss_fft_s32_cpx; + +typedef struct kiss_fft_s32_state* kiss_fft_s32_cfg; + +/* + * kiss_fft_s32_alloc + * + * Initialize a FFT (or IFFT) algorithm's cfg/state buffer. + * + * typical usage: kiss_fft_s32_cfg mycfg=kiss_fft_s32_alloc(1024,0,NULL,NULL); + * + * The return value from fft_alloc is a cfg buffer used internally + * by the fft routine or NULL. + * + * If lenmem is NULL, then kiss_fft_s32_alloc will allocate a cfg buffer using malloc. + * The returned value should be free()d when done to avoid memory leaks. + * + * The state can be placed in a user supplied buffer 'mem': + * If lenmem is not NULL and mem is not NULL and *lenmem is large enough, + * then the function places the cfg in mem and the size used in *lenmem + * and returns mem. + * + * If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough), + * then the function returns NULL and places the minimum cfg + * buffer size in *lenmem. + * */ + +kiss_fft_s32_cfg kiss_fft_s32_alloc(int nfft,int inverse_fft,void * mem,size_t * lenmem); + +/* + * kiss_fft(cfg,in_out_buf) + * + * Perform an FFT on a complex input buffer. + * for a forward FFT, + * fin should be f[0] , f[1] , ... ,f[nfft-1] + * fout will be F[0] , F[1] , ... ,F[nfft-1] + * Note that each element is complex and can be accessed like + f[k].r and f[k].i + * */ +void kiss_fft_s32(kiss_fft_s32_cfg cfg,const kiss_fft_s32_cpx *fin,kiss_fft_s32_cpx *fout); + +/* + A more generic version of the above function. It reads its input from every Nth sample. + * */ +void kiss_fft_s32_stride(kiss_fft_s32_cfg cfg,const kiss_fft_s32_cpx *fin,kiss_fft_s32_cpx *fout,int fin_stride); + +/* If kiss_fft_s32_alloc allocated a buffer, it is one contiguous + buffer and can be simply free()d when no longer needed*/ +#define kiss_fft_s32_free g_free + +/* + Cleans up some memory that gets managed internally. Not necessary to call, but it might clean up + your compiler output to call this before you exit. +*/ +void kiss_fft_s32_cleanup(void); + + +/* + * Returns the smallest integer k, such that k>=n and k has only "fast" factors (2,3,5) + */ +int kiss_fft_s32_next_fast_size(int n); + +/* for real ffts, we need an even size */ +#define kiss_fftr_next_fast_size_real(n) \ + (kiss_fft_next_fast_size( ((n)+1)>>1)<<1) + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.c new file mode 100644 index 0000000..ab11c04 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.c @@ -0,0 +1,169 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "kiss_fftr_f32.h" +#include "_kiss_fft_guts_f32.h" + +struct kiss_fftr_f32_state +{ + kiss_fft_f32_cfg substate; + kiss_fft_f32_cpx *tmpbuf; + kiss_fft_f32_cpx *super_twiddles; +#ifdef USE_SIMD + long pad; +#endif +}; + +kiss_fftr_f32_cfg +kiss_fftr_f32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + int i; + kiss_fftr_f32_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + fprintf (stderr, "Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_f32_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state)) + + ALIGN_STRUCT (subsize) + sizeof (kiss_fft_f32_cpx) * (nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_f32_cfg) KISS_FFT_F32_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_f32_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_f32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_f32_state))); /*just beyond kiss_fftr_f32_state struct */ + st->tmpbuf = + (kiss_fft_f32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize)); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_f32_alloc (nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft / 2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5); + + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles + i, phase); + } + return st; +} + +void +kiss_fftr_f32 (kiss_fftr_f32_cfg st, const kiss_fft_f32_scalar * timedata, + kiss_fft_f32_cpx * freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + kiss_fft_f32_cpx fpnk, fpk, f1k, f2k, tw, tdc; + + if (st->substate->inverse) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag */ + kiss_fft_f32 (st->substate, (const kiss_fft_f32_cpx *) timedata, st->tmpbuf); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV (tdc, 2); + CHECK_OVERFLOW_OP (tdc.r, +, tdc.i); + CHECK_OVERFLOW_OP (tdc.r, -, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for (k = 1; k <= ncfft / 2; ++k) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft - k].r; + fpnk.i = -st->tmpbuf[ncfft - k].i; + C_FIXDIV (fpk, 2); + C_FIXDIV (fpnk, 2); + + C_ADD (f1k, fpk, fpnk); + C_SUB (f2k, fpk, fpnk); + C_MUL (tw, f2k, st->super_twiddles[k - 1]); + + freqdata[k].r = HALF_OF (f1k.r + tw.r); + freqdata[k].i = HALF_OF (f1k.i + tw.i); + freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r); + freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i); + } +} + +void +kiss_fftri_f32 (kiss_fftr_f32_cfg st, const kiss_fft_f32_cpx * freqdata, + kiss_fft_f32_scalar * timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV (st->tmpbuf[0], 2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_f32_cpx fk, fnkc, fek, fok, tmp; + + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV (fk, 2); + C_FIXDIV (fnkc, 2); + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k - 1]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft_f32 (st->substate, st->tmpbuf, (kiss_fft_f32_cpx *) timedata); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.h new file mode 100644 index 0000000..91f2085 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f32.h @@ -0,0 +1,46 @@ +#ifndef KISS_FTR_F32_H +#define KISS_FTR_F32_H + +#include "kiss_fft_f32.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_f32_state *kiss_fftr_f32_cfg; + + +kiss_fftr_f32_cfg kiss_fftr_f32_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr_f32(kiss_fftr_f32_cfg cfg,const kiss_fft_f32_scalar *timedata,kiss_fft_f32_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri_f32(kiss_fftr_f32_cfg cfg,const kiss_fft_f32_cpx *freqdata,kiss_fft_f32_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_f32_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.c new file mode 100644 index 0000000..740be27 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.c @@ -0,0 +1,170 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "kiss_fftr_f64.h" +#include "_kiss_fft_guts_f64.h" + +struct kiss_fftr_f64_state +{ + kiss_fft_f64_cfg substate; + kiss_fft_f64_cpx *tmpbuf; + kiss_fft_f64_cpx *super_twiddles; +#ifdef USE_SIMD + long pad; +#endif +}; + +kiss_fftr_f64_cfg +kiss_fftr_f64_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + int i; + kiss_fftr_f64_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + fprintf (stderr, "Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_f64_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_f64_state)) + + ALIGN_STRUCT (subsize) + + sizeof (kiss_fft_f64_cpx) * (nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_f64_cfg) KISS_FFT_F64_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_f64_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_f64_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_f64_state))); /*just beyond kiss_fftr_f64_state struct */ + st->tmpbuf = + (kiss_fft_f64_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize)); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_f64_alloc (nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft / 2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5); + + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles + i, phase); + } + return st; +} + +void +kiss_fftr_f64 (kiss_fftr_f64_cfg st, const kiss_fft_f64_scalar * timedata, + kiss_fft_f64_cpx * freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + kiss_fft_f64_cpx fpnk, fpk, f1k, f2k, tw, tdc; + + if (st->substate->inverse) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag */ + kiss_fft_f64 (st->substate, (const kiss_fft_f64_cpx *) timedata, st->tmpbuf); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV (tdc, 2); + CHECK_OVERFLOW_OP (tdc.r, +, tdc.i); + CHECK_OVERFLOW_OP (tdc.r, -, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for (k = 1; k <= ncfft / 2; ++k) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft - k].r; + fpnk.i = -st->tmpbuf[ncfft - k].i; + C_FIXDIV (fpk, 2); + C_FIXDIV (fpnk, 2); + + C_ADD (f1k, fpk, fpnk); + C_SUB (f2k, fpk, fpnk); + C_MUL (tw, f2k, st->super_twiddles[k - 1]); + + freqdata[k].r = HALF_OF (f1k.r + tw.r); + freqdata[k].i = HALF_OF (f1k.i + tw.i); + freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r); + freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i); + } +} + +void +kiss_fftri_f64 (kiss_fftr_f64_cfg st, const kiss_fft_f64_cpx * freqdata, + kiss_fft_f64_scalar * timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV (st->tmpbuf[0], 2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_f64_cpx fk, fnkc, fek, fok, tmp; + + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV (fk, 2); + C_FIXDIV (fnkc, 2); + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k - 1]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft_f64 (st->substate, st->tmpbuf, (kiss_fft_f64_cpx *) timedata); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.h new file mode 100644 index 0000000..0b35cb6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_f64.h @@ -0,0 +1,46 @@ +#ifndef KISS_FTR_F64_H +#define KISS_FTR_F64_H + +#include "kiss_fft_f64.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_f64_state *kiss_fftr_f64_cfg; + + +kiss_fftr_f64_cfg kiss_fftr_f64_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr_f64(kiss_fftr_f64_cfg cfg,const kiss_fft_f64_scalar *timedata,kiss_fft_f64_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri_f64(kiss_fftr_f64_cfg cfg,const kiss_fft_f64_cpx *freqdata,kiss_fft_f64_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_f64_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.c new file mode 100644 index 0000000..f1ec990 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.c @@ -0,0 +1,170 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "kiss_fftr_s16.h" +#include "_kiss_fft_guts_s16.h" + +struct kiss_fftr_s16_state +{ + kiss_fft_s16_cfg substate; + kiss_fft_s16_cpx *tmpbuf; + kiss_fft_s16_cpx *super_twiddles; +#ifdef USE_SIMD + long pad; +#endif +}; + +kiss_fftr_s16_cfg +kiss_fftr_s16_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + int i; + kiss_fftr_s16_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + fprintf (stderr, "Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_s16_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_s16_state)) + + ALIGN_STRUCT (subsize) + + sizeof (kiss_fft_s16_cpx) * (nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_s16_cfg) KISS_FFT_S16_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_s16_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_s16_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_s16_state))); /*just beyond kiss_fftr_s16_state struct */ + st->tmpbuf = + (kiss_fft_s16_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize)); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_s16_alloc (nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft / 2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5); + + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles + i, phase); + } + return st; +} + +void +kiss_fftr_s16 (kiss_fftr_s16_cfg st, const kiss_fft_s16_scalar * timedata, + kiss_fft_s16_cpx * freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + kiss_fft_s16_cpx fpnk, fpk, f1k, f2k, tw, tdc; + + if (st->substate->inverse) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag */ + kiss_fft_s16 (st->substate, (const kiss_fft_s16_cpx *) timedata, st->tmpbuf); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV (tdc, 2); + CHECK_OVERFLOW_OP (tdc.r, +, tdc.i); + CHECK_OVERFLOW_OP (tdc.r, -, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for (k = 1; k <= ncfft / 2; ++k) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft - k].r; + fpnk.i = -st->tmpbuf[ncfft - k].i; + C_FIXDIV (fpk, 2); + C_FIXDIV (fpnk, 2); + + C_ADD (f1k, fpk, fpnk); + C_SUB (f2k, fpk, fpnk); + C_MUL (tw, f2k, st->super_twiddles[k - 1]); + + freqdata[k].r = HALF_OF (f1k.r + tw.r); + freqdata[k].i = HALF_OF (f1k.i + tw.i); + freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r); + freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i); + } +} + +void +kiss_fftri_s16 (kiss_fftr_s16_cfg st, const kiss_fft_s16_cpx * freqdata, + kiss_fft_s16_scalar * timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV (st->tmpbuf[0], 2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_s16_cpx fk, fnkc, fek, fok, tmp; + + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV (fk, 2); + C_FIXDIV (fnkc, 2); + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k - 1]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft_s16 (st->substate, st->tmpbuf, (kiss_fft_s16_cpx *) timedata); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.h new file mode 100644 index 0000000..20bc9ef --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s16.h @@ -0,0 +1,46 @@ +#ifndef KISS_FTR_S16_H +#define KISS_FTR_S16_H + +#include "kiss_fft_s16.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_s16_state *kiss_fftr_s16_cfg; + + +kiss_fftr_s16_cfg kiss_fftr_s16_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr_s16(kiss_fftr_s16_cfg cfg,const kiss_fft_s16_scalar *timedata,kiss_fft_s16_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri_s16(kiss_fftr_s16_cfg cfg,const kiss_fft_s16_cpx *freqdata,kiss_fft_s16_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_s16_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.c new file mode 100644 index 0000000..260da29 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.c @@ -0,0 +1,170 @@ +/* +Copyright (c) 2003-2004, Mark Borgerding + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + * Neither the author nor the names of any contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "kiss_fftr_s32.h" +#include "_kiss_fft_guts_s32.h" + +struct kiss_fftr_s32_state +{ + kiss_fft_s32_cfg substate; + kiss_fft_s32_cpx *tmpbuf; + kiss_fft_s32_cpx *super_twiddles; +#ifdef USE_SIMD + long pad; +#endif +}; + +kiss_fftr_s32_cfg +kiss_fftr_s32_alloc (int nfft, int inverse_fft, void *mem, size_t * lenmem) +{ + int i; + kiss_fftr_s32_cfg st = NULL; + size_t subsize, memneeded; + + if (nfft & 1) { + fprintf (stderr, "Real FFT optimization must be even.\n"); + return NULL; + } + nfft >>= 1; + + kiss_fft_s32_alloc (nfft, inverse_fft, NULL, &subsize); + memneeded = ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state)) + + ALIGN_STRUCT (subsize) + + sizeof (kiss_fft_s32_cpx) * (nfft * 3 / 2); + + if (lenmem == NULL) { + st = (kiss_fftr_s32_cfg) KISS_FFT_S32_MALLOC (memneeded); + } else { + if (*lenmem >= memneeded) + st = (kiss_fftr_s32_cfg) mem; + *lenmem = memneeded; + } + if (!st) + return NULL; + + st->substate = (kiss_fft_s32_cfg) (((char *) st) + ALIGN_STRUCT (sizeof (struct kiss_fftr_s32_state))); /*just beyond kiss_fftr_s32_state struct */ + st->tmpbuf = + (kiss_fft_s32_cpx *) (((char *) st->substate) + ALIGN_STRUCT (subsize)); + st->super_twiddles = st->tmpbuf + nfft; + kiss_fft_s32_alloc (nfft, inverse_fft, st->substate, &subsize); + + for (i = 0; i < nfft / 2; ++i) { + double phase = + -3.14159265358979323846264338327 * ((double) (i + 1) / nfft + .5); + + if (inverse_fft) + phase *= -1; + kf_cexp (st->super_twiddles + i, phase); + } + return st; +} + +void +kiss_fftr_s32 (kiss_fftr_s32_cfg st, const kiss_fft_s32_scalar * timedata, + kiss_fft_s32_cpx * freqdata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + kiss_fft_s32_cpx fpnk, fpk, f1k, f2k, tw, tdc; + + if (st->substate->inverse) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + /*perform the parallel fft of two real signals packed in real,imag */ + kiss_fft_s32 (st->substate, (const kiss_fft_s32_cpx *) timedata, st->tmpbuf); + /* The real part of the DC element of the frequency spectrum in st->tmpbuf + * contains the sum of the even-numbered elements of the input time sequence + * The imag part is the sum of the odd-numbered elements + * + * The sum of tdc.r and tdc.i is the sum of the input time sequence. + * yielding DC of input time sequence + * The difference of tdc.r - tdc.i is the sum of the input (dot product) [1,-1,1,-1... + * yielding Nyquist bin of input time sequence + */ + + tdc.r = st->tmpbuf[0].r; + tdc.i = st->tmpbuf[0].i; + C_FIXDIV (tdc, 2); + CHECK_OVERFLOW_OP (tdc.r, +, tdc.i); + CHECK_OVERFLOW_OP (tdc.r, -, tdc.i); + freqdata[0].r = tdc.r + tdc.i; + freqdata[ncfft].r = tdc.r - tdc.i; +#ifdef USE_SIMD + freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps (0); +#else + freqdata[ncfft].i = freqdata[0].i = 0; +#endif + + for (k = 1; k <= ncfft / 2; ++k) { + fpk = st->tmpbuf[k]; + fpnk.r = st->tmpbuf[ncfft - k].r; + fpnk.i = -st->tmpbuf[ncfft - k].i; + C_FIXDIV (fpk, 2); + C_FIXDIV (fpnk, 2); + + C_ADD (f1k, fpk, fpnk); + C_SUB (f2k, fpk, fpnk); + C_MUL (tw, f2k, st->super_twiddles[k - 1]); + + freqdata[k].r = HALF_OF (f1k.r + tw.r); + freqdata[k].i = HALF_OF (f1k.i + tw.i); + freqdata[ncfft - k].r = HALF_OF (f1k.r - tw.r); + freqdata[ncfft - k].i = HALF_OF (tw.i - f1k.i); + } +} + +void +kiss_fftri_s32 (kiss_fftr_s32_cfg st, const kiss_fft_s32_cpx * freqdata, + kiss_fft_s32_scalar * timedata) +{ + /* input buffer timedata is stored row-wise */ + int k, ncfft; + + if (st->substate->inverse == 0) { + fprintf (stderr, "kiss fft usage error: improper alloc\n"); + exit (1); + } + + ncfft = st->substate->nfft; + + st->tmpbuf[0].r = freqdata[0].r + freqdata[ncfft].r; + st->tmpbuf[0].i = freqdata[0].r - freqdata[ncfft].r; + C_FIXDIV (st->tmpbuf[0], 2); + + for (k = 1; k <= ncfft / 2; ++k) { + kiss_fft_s32_cpx fk, fnkc, fek, fok, tmp; + + fk = freqdata[k]; + fnkc.r = freqdata[ncfft - k].r; + fnkc.i = -freqdata[ncfft - k].i; + C_FIXDIV (fk, 2); + C_FIXDIV (fnkc, 2); + + C_ADD (fek, fk, fnkc); + C_SUB (tmp, fk, fnkc); + C_MUL (fok, tmp, st->super_twiddles[k - 1]); + C_ADD (st->tmpbuf[k], fek, fok); + C_SUB (st->tmpbuf[ncfft - k], fek, fok); +#ifdef USE_SIMD + st->tmpbuf[ncfft - k].i *= _mm_set1_ps (-1.0); +#else + st->tmpbuf[ncfft - k].i *= -1; +#endif + } + kiss_fft_s32 (st->substate, st->tmpbuf, (kiss_fft_s32_cpx *) timedata); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.h new file mode 100644 index 0000000..8e8fecb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_fftr_s32.h @@ -0,0 +1,46 @@ +#ifndef KISS_FTR_S32_H +#define KISS_FTR_S32_H + +#include "kiss_fft_s32.h" +#ifdef __cplusplus +extern "C" { +#endif + + +/* + + Real optimized version can save about 45% cpu time vs. complex fft of a real seq. + + + + */ + +typedef struct kiss_fftr_s32_state *kiss_fftr_s32_cfg; + + +kiss_fftr_s32_cfg kiss_fftr_s32_alloc(int nfft,int inverse_fft,void * mem, size_t * lenmem); +/* + nfft must be even + + If you don't care to allocate space, use mem = lenmem = NULL +*/ + + +void kiss_fftr_s32(kiss_fftr_s32_cfg cfg,const kiss_fft_s32_scalar *timedata,kiss_fft_s32_cpx *freqdata); +/* + input timedata has nfft scalar points + output freqdata has nfft/2+1 complex points +*/ + +void kiss_fftri_s32(kiss_fftr_s32_cfg cfg,const kiss_fft_s32_cpx *freqdata,kiss_fft_s32_scalar *timedata); +/* + input freqdata has nfft/2+1 complex points + output timedata has nfft scalar points +*/ + +#define kiss_fftr_s32_free free + +#ifdef __cplusplus +} +#endif +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_version b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_version new file mode 100644 index 0000000..c55188b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/fft/kiss_version @@ -0,0 +1,4 @@ +Based on Kiss FFT version 1.2.6. http://kissfft.sourceforge.net + +Only changes are limitation to one data type for each version in +kiss_fft.h and _kiss_fft_guts.h. diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/Makefile.am new file mode 100644 index 0000000..b18029c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/Makefile.am @@ -0,0 +1,2 @@ +floatcastincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/floatcast +floatcastinclude_HEADERS = floatcast.h diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/floatcast.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/floatcast.h new file mode 100644 index 0000000..279af28 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/floatcast/floatcast.h @@ -0,0 +1,102 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2002> Steve Baker + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstfloatcast + * @short_description: Floating point platform independence macros + * + * The floatcast.h header file contains a couple of convenience macros for + * floating point numbers. + * + * If you include this header, your application or library must link against + * libm (for maths.h support). + * + * For optimal results, your application's or library's build + * system should check whether the C99 functions lrint and lrintf are supported + * and define the preprocessor symbols HAVE_LRINT and HAVE_LRINTF if so. If + * you are using autoconf, you can do this by using the AC_C99_FUNC_LRINT and + * AC_C99_FUNC_LRINTF checks in your configure.ac or configure.in file and + * including your application's config.h header before you include floatcast.h. + */ + +#ifndef __FLOATCAST_H__ +#define __FLOATCAST_H__ + +#include +#include + +#if defined (_MSC_VER) && !defined (inline) +#define inline __inline +#endif + +G_BEGIN_DECLS + +/* FIXME 0.11: these gst_cast_*() functions are not used anywhere, so we could + * just as well get rid of them and move the float/double swap macros into + * gstutils.h in core */ + +/** + * gst_cast_float: + * @x: input value + * + * Casts a 32-bit floating point value (float) to an integer without bias. + */ +/** + * gst_cast_double: + * @x: input value + * + * Casts a 64-bit floating point value (double) to an integer without bias. + */ + +/* FIXME: HAVE_LRINT && HAVE_LRINTF are defined by config.h - they should + * not be used in an installed header. */ +#if defined(HAVE_LRINT) && defined(HAVE_LRINTF) + + /* These defines enable functionality introduced with the 1999 ISO C + ** standard. They must be defined before the inclusion of math.h to + ** engage them. If optimisation is enabled, these functions will be + ** inlined. With optimisation switched off, you have to link in the + ** maths library using -lm. + */ + + #define _ISOC9X_SOURCE 1 + #define _ISOC99_SOURCE 1 + + #define __USE_ISOC9X 1 + #define __USE_ISOC99 1 + + #include + + #define gst_cast_float(x) ((gint)lrintf(x)) + #define gst_cast_double(x) ((gint)lrint(x)) + +#else + #include + + /* use a standard c cast, but do rounding correctly */ + #define gst_cast_float(x) ((gint)floor((x)+0.5)) + #define gst_cast_double(x) ((gint)floor((x)+0.5)) + +#endif + +G_END_DECLS + +#endif /* __FLOATCAST_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/gettext.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/gettext.h new file mode 100644 index 0000000..727bdb0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/gettext.h @@ -0,0 +1,69 @@ +/* Convenience header for conditional use of GNU . + Copyright (C) 1995-1998, 2000-2002 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published + by the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + USA. */ + +#ifndef _LIBGETTEXT_H +#define _LIBGETTEXT_H 1 + +/* NLS can be disabled through the configure --disable-nls option. */ +#if defined (ENABLE_NLS) && ENABLE_NLS + +/* Get declarations of GNU message catalog functions. */ +# include + +#else + +/* Solaris /usr/include/locale.h includes /usr/include/libintl.h, which + chokes if dcgettext is defined as a macro. So include it now, to make + later inclusions of a NOP. We don't include + as well because people using "gettext.h" will not include , + and also including would fail on SunOS 4, whereas + is OK. */ +#if defined(__sun) +# include +#endif + +/* Disabled NLS. + The casts to 'const char *' serve the purpose of producing warnings + for invalid uses of the value returned from these functions. + On pre-ANSI systems without 'const', the config.h file is supposed to + contain "#define const". */ +# define gettext(Msgid) ((const char *) (Msgid)) +# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +# define ngettext(Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dngettext(Domainname, Msgid1, Msgid2, N) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ + ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) +# define textdomain(Domainname) ((const char *) (Domainname)) +# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) + +#endif + +/* A pseudo function call that serves as a marker for the automated + extraction of messages, but does not call gettext(). The run-time + translation is done at a different place in the code. + The argument, String, should be a literal string. Concatenated strings + and other string expressions won't work. + The macro's expansion is not parenthesized, so that it is suitable as + initializer for static 'char[]' or 'const char[]' variables. */ +#define gettext_noop(String) String + +#endif /* _LIBGETTEXT_H */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/gst-i18n-plugin.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/gst-i18n-plugin.h new file mode 100644 index 0000000..2c37a61 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/gst-i18n-plugin.h @@ -0,0 +1,37 @@ +/* GStreamer + * Copyright (C) 2004 Thomas Vander Stichele + * + * gst-i18n-plugins.h: internationalization macros for the GStreamer plugins + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_I18N_PLUGIN_H__ +#define __GST_I18N_PLUGIN_H__ + +#include /* some people need it and some people don't */ +#include "gettext.h" /* included with gettext distribution and copied */ + +#ifndef GETTEXT_PACKAGE +#error You must define GETTEXT_PACKAGE before including this header. +#endif + +/* we want to use shorthand _() for translating and N_() for marking */ +#define _(String) dgettext (GETTEXT_PACKAGE, String) +#define N_(String) gettext_noop (String) +/* FIXME: if we need it, we can add Q_ as well, like in glib */ + +#endif /* __GST_I18N_PLUGIN_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/.gitignore new file mode 100644 index 0000000..d96df0c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/.gitignore @@ -0,0 +1,5 @@ +interfaces-enumtypes.c +interfaces-enumtypes.h +interfaces-marshal.c +interfaces-marshal.h + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/Makefile.am new file mode 100644 index 0000000..a51b029 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/Makefile.am @@ -0,0 +1,137 @@ +lib_LTLIBRARIES = libgstinterfaces-@GST_MAJORMINOR@.la +libgstinterfacesincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/interfaces + +headers_interfaces = \ + colorbalance.h \ + colorbalancechannel.h \ + mixer.h \ + mixeroptions.h \ + mixertrack.h \ + navigation.h \ + propertyprobe.h \ + streamvolume.h \ + tuner.h \ + tunernorm.h \ + tunerchannel.h \ + videoorientation.h \ + xoverlay.h + +# variables used for enum/marshal generation +glib_enum_headers = $(headers_interfaces) +glib_enum_define = GST_INTERFACES +glib_gen_prefix = gst_interfaces +glib_gen_basename = interfaces + +built_sources = \ + interfaces-marshal.c \ + interfaces-enumtypes.c + +built_headers = \ + interfaces-marshal.h \ + interfaces-enumtypes.h + +libgstinterfacesinclude_HEADERS = \ + $(headers_interfaces) + +nodist_libgstinterfacesinclude_HEADERS = \ + interfaces-enumtypes.h + +libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES = \ + colorbalance.c \ + colorbalancechannel.c \ + mixer.c \ + mixeroptions.c \ + mixertrack.c \ + navigation.c \ + propertyprobe.c \ + streamvolume.c \ + tuner.c \ + tunernorm.c \ + tunerchannel.c \ + videoorientation.c \ + xoverlay.c + +nodist_libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES = \ + $(built_sources) \ + interfaces-marshal.h + +libgstinterfaces_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstinterfaces_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(LIBM) +libgstinterfaces_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +BUILT_SOURCES = \ + $(built_sources) \ + $(built_headers) + +EXTRA_DIST = interfaces-marshal.list + +CLEANFILES = $(BUILT_SOURCES) + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstInterfaces-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstinterfacesinclude_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstinterfacesinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/interfaces/%',$(libgstinterfacesinclude_HEADERS)) +gir_cincludes+=$(patsubst %,--c-include='gst/interfaces/%',$(nodist_libgstinterfacesinclude_HEADERS)) + +GstInterfaces-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstinterfaces-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstInterfaces \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstinterfaces-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-interfaces-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstinterfaces -:SHARED libgstinterfaces-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstinterfaces_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(libgstinterfaces_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstinterfaces_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstinterfaces_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/interfaces \ + -:HEADERS $(libgstinterfacesinclude_HEADERS) \ + $(nodist_libgstinterfacesinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.c new file mode 100644 index 0000000..319c1b9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.c @@ -0,0 +1,224 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalance.c: image color balance interface design + * virtual class function wrappers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "colorbalance.h" +#include "interfaces-marshal.h" + +/** + * SECTION:gstcolorbalance + * @short_description: Interface for adjusting color balance settings + * + * + * This interface is implemented by elements which can perform some color + * balance operation on video frames they process. For example, modifying + * the brightness, contrast, hue or saturation. + * + * Example elements are 'xvimagesink' and 'colorbalance' + * + * + */ + +enum +{ + VALUE_CHANGED, + LAST_SIGNAL +}; + +static void gst_color_balance_class_init (GstColorBalanceClass * klass); + +static guint gst_color_balance_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_color_balance_get_type (void) +{ + static GType gst_color_balance_type = 0; + + if (!gst_color_balance_type) { + static const GTypeInfo gst_color_balance_info = { + sizeof (GstColorBalanceClass), + (GBaseInitFunc) gst_color_balance_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_color_balance_type = g_type_register_static (G_TYPE_INTERFACE, + "GstColorBalance", &gst_color_balance_info, 0); + g_type_interface_add_prerequisite (gst_color_balance_type, + GST_TYPE_IMPLEMENTS_INTERFACE); + } + + return gst_color_balance_type; +} + +static void +gst_color_balance_class_init (GstColorBalanceClass * klass) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /** + * GstColorBalance::value-changed: + * @colorbalance: The GstColorBalance instance + * @channel: The #GstColorBalanceChannel + * @value: The new value + * + * Fired when the value of the indicated channel has changed. + */ + gst_color_balance_signals[VALUE_CHANGED] = + g_signal_new ("value-changed", + GST_TYPE_COLOR_BALANCE, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstColorBalanceClass, value_changed), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_INT, + G_TYPE_NONE, 2, GST_TYPE_COLOR_BALANCE_CHANNEL, G_TYPE_INT); + + initialized = TRUE; + } + + klass->balance_type = GST_COLOR_BALANCE_SOFTWARE; + + /* default virtual functions */ + klass->list_channels = NULL; + klass->set_value = NULL; + klass->get_value = NULL; +} + +/** + * gst_color_balance_list_channels: + * @balance: A #GstColorBalance instance + * + * Retrieve a list of the available channels. + * + * Returns: A GList containing pointers to #GstColorBalanceChannel objects. + * The list is owned by the #GstColorBalance instance and must not + * be freed. + */ +const GList * +gst_color_balance_list_channels (GstColorBalance * balance) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->list_channels) { + return klass->list_channels (balance); + } + + return NULL; +} + +/** + * gst_color_balance_set_value: + * @balance: A #GstColorBalance instance + * @channel: A #GstColorBalanceChannel instance + * @value: The new value for the channel. + * + * Sets the current value of the channel to the passed value, which must + * be between min_value and max_value. + * + * See Also: The #GstColorBalanceChannel::min_value and + * #GstColorBalanceChannel::max_value members of the + * #GstColorBalanceChannel object. + */ +void +gst_color_balance_set_value (GstColorBalance * balance, + GstColorBalanceChannel * channel, gint value) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->set_value) { + klass->set_value (balance, channel, value); + } +} + +/** + * gst_color_balance_get_value: + * @balance: A #GstColorBalance instance + * @channel: A #GstColorBalanceChannel instance + * + * Retrieve the current value of the indicated channel, between min_value + * and max_value. + * + * See Also: The #GstColorBalanceChannel::min_value and + * #GstColorBalanceChannel::max_value members of the + * #GstColorBalanceChannel object. + * + * Returns: The current value of the channel. + */ +gint +gst_color_balance_get_value (GstColorBalance * balance, + GstColorBalanceChannel * channel) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + if (klass->get_value) { + return klass->get_value (balance, channel); + } + + return channel->min_value; +} + +/** + * gst_color_balance_get_balance_type: + * @balance: The #GstColorBalance implementation + * + * Get the #GstColorBalanceType of this implementation. + * + * Returns: A the #GstColorBalanceType. + * + * Since: 0.10.24 + */ +GstColorBalanceType +gst_color_balance_get_balance_type (GstColorBalance * balance) +{ + GstColorBalanceClass *klass = GST_COLOR_BALANCE_GET_CLASS (balance); + + return klass->balance_type; +} + +/** + * gst_color_balance_value_changed: + * @balance: A #GstColorBalance instance + * @channel: A #GstColorBalanceChannel whose value has changed + * @value: The new value of the channel + * + * A helper function called by implementations of the GstColorBalance + * interface. It fires the #GstColorBalance::value-changed signal on the + * instance, and the #GstColorBalanceChannel::value-changed signal on the + * channel object. + */ +void +gst_color_balance_value_changed (GstColorBalance * balance, + GstColorBalanceChannel * channel, gint value) +{ + g_signal_emit (G_OBJECT (balance), + gst_color_balance_signals[VALUE_CHANGED], 0, channel, value); + + g_signal_emit_by_name (G_OBJECT (channel), "value_changed", value); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.h new file mode 100644 index 0000000..2be7db6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalance.h @@ -0,0 +1,112 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * color-balance.h: image color balance interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_COLOR_BALANCE_H__ +#define __GST_COLOR_BALANCE_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_COLOR_BALANCE \ + (gst_color_balance_get_type ()) +#define GST_COLOR_BALANCE(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_COLOR_BALANCE, \ + GstColorBalance)) +#define GST_COLOR_BALANCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_COLOR_BALANCE, \ + GstColorBalanceClass)) +#define GST_IS_COLOR_BALANCE(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_COLOR_BALANCE)) +#define GST_IS_COLOR_BALANCE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_COLOR_BALANCE)) +#define GST_COLOR_BALANCE_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_COLOR_BALANCE, GstColorBalanceClass)) + +#define GST_COLOR_BALANCE_TYPE(klass) (klass->balance_type) + +typedef struct _GstColorBalance GstColorBalance; +typedef struct _GstColorBalanceClass GstColorBalanceClass; + +/** + * GstColorBalanceType: + * @GST_COLOR_BALANCE_HARDWARE: Color balance is implemented with dedicated + * hardware. + * @GST_COLOR_BALANCE_SOFTWARE: Color balance is implemented via software + * processing. + * + * An enumeration indicating whether an element implements color balancing + * operations in software or in dedicated hardware. In general, dedicated + * hardware implementations (such as those provided by xvimagesink) are + * preferred. + */ +typedef enum +{ + GST_COLOR_BALANCE_HARDWARE, + GST_COLOR_BALANCE_SOFTWARE +} GstColorBalanceType; + +struct _GstColorBalanceClass { + GTypeInterface klass; + + GstColorBalanceType balance_type; + + /* virtual functions */ + const GList * (* list_channels) (GstColorBalance *balance); + + void (* set_value) (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); + gint (* get_value) (GstColorBalance *balance, + GstColorBalanceChannel *channel); + + /* signals */ + void (* value_changed) (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_color_balance_get_type (void); + +/* virtual class function wrappers */ +const GList * + gst_color_balance_list_channels (GstColorBalance *balance); +void gst_color_balance_set_value (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); +gint gst_color_balance_get_value (GstColorBalance *balance, + GstColorBalanceChannel *channel); + +GstColorBalanceType + gst_color_balance_get_balance_type (GstColorBalance *balance); + +/* trigger signal */ +void gst_color_balance_value_changed (GstColorBalance *balance, + GstColorBalanceChannel *channel, + gint value); + +G_END_DECLS + +#endif /* __GST_COLOR_BALANCE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.c new file mode 100644 index 0000000..ae22fba --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.c @@ -0,0 +1,124 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalancechannel.c: colorbalance channel object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "colorbalancechannel.h" + +/** + * SECTION:gstcolorbalancechannel + * @short_description: Object representing a channel from the #GstColorBalance + * interface. + * + * The #GstColorBalanceChannel object represents a parameter + * for modifying the color balance implemented by an element providing the + * #GstColorBalance interface. For example, Hue or Saturation. + * + */ + +enum +{ + /* FILL ME */ + SIGNAL_VALUE_CHANGED, + LAST_SIGNAL +}; + +static void gst_color_balance_channel_class_init (GstColorBalanceChannelClass * + klass); +static void gst_color_balance_channel_init (GstColorBalanceChannel * balance); +static void gst_color_balance_channel_dispose (GObject * object); + +static GObjectClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = { 0 }; + +GType +gst_color_balance_channel_get_type (void) +{ + static GType gst_color_balance_channel_type = 0; + + if (!gst_color_balance_channel_type) { + static const GTypeInfo color_balance_channel_info = { + sizeof (GstColorBalanceChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_color_balance_channel_class_init, + NULL, + NULL, + sizeof (GstColorBalanceChannel), + 0, + (GInstanceInitFunc) gst_color_balance_channel_init, + NULL + }; + + gst_color_balance_channel_type = + g_type_register_static (G_TYPE_OBJECT, + "GstColorBalanceChannel", &color_balance_channel_info, 0); + } + + return gst_color_balance_channel_type; +} + +static void +gst_color_balance_channel_class_init (GstColorBalanceChannelClass * klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + /** + * GstColorBalanceChannel::value-changed: + * @channel: The #GstColorBalanceChannel + * @value: The new value + * + * Fired when the value of the indicated channel has changed. + */ + signals[SIGNAL_VALUE_CHANGED] = + g_signal_new ("value-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstColorBalanceChannelClass, + value_changed), + NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + object_klass->dispose = gst_color_balance_channel_dispose; +} + +static void +gst_color_balance_channel_init (GstColorBalanceChannel * channel) +{ + channel->label = NULL; + channel->min_value = channel->max_value = 0; +} + +static void +gst_color_balance_channel_dispose (GObject * object) +{ + GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (object); + + if (channel->label) + g_free (channel->label); + + channel->label = NULL; + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.h new file mode 100644 index 0000000..f279f38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/colorbalancechannel.h @@ -0,0 +1,75 @@ +/* GStreamer Color Balance + * Copyright (C) 2003 Ronald Bultje + * + * colorbalancechannel.h: individual channel object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_COLOR_BALANCE_CHANNEL_H__ +#define __GST_COLOR_BALANCE_CHANNEL_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_COLOR_BALANCE_CHANNEL \ + (gst_color_balance_channel_get_type ()) +#define GST_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_COLOR_BALANCE_CHANNEL, \ + GstColorBalanceChannel)) +#define GST_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_COLOR_BALANCE_CHANNEL, \ + GstColorBalanceChannelClass)) +#define GST_IS_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_COLOR_BALANCE_CHANNEL)) +#define GST_IS_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_COLOR_BALANCE_CHANNEL)) + +typedef struct _GstColorBalanceChannel GstColorBalanceChannel; +typedef struct _GstColorBalanceChannelClass GstColorBalanceChannelClass; + +/** + * GstColorBalanceChannel: + * @label: A string containing a descriptive name for this channel + * @min_value: The minimum valid value for this channel. + * @max_value: The maximum valid value for this channel. + */ +struct _GstColorBalanceChannel { + GObject parent; + + /*< public >*/ + gchar *label; + gint min_value; + gint max_value; +}; + + +struct _GstColorBalanceChannelClass { + GObjectClass parent; + + /* signals */ + void (* value_changed) (GstColorBalanceChannel *channel, + gint value); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_color_balance_channel_get_type (void); + +G_END_DECLS + +#endif /* __GST_COLOR_BALANCE_CHANNEL_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/interfaces-marshal.list b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/interfaces-marshal.list new file mode 100644 index 0000000..cb7469c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/interfaces-marshal.list @@ -0,0 +1,5 @@ +VOID:OBJECT,BOOLEAN +VOID:OBJECT,POINTER +VOID:OBJECT,STRING +VOID:OBJECT,ULONG +VOID:OBJECT,INT diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.c new file mode 100644 index 0000000..8117d20 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.c @@ -0,0 +1,872 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixer.c: mixer design virtual class function wrappers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "mixer.h" +#include "interfaces-marshal.h" + +#define GST_MIXER_MESSAGE_NAME "gst-mixer-message" + +/** + * SECTION:gstmixer + * @short_description: Interface for elements that provide mixer operations + * @see_also: alsamixer, oss4mixer, sunaudiomixer + * + * Basic interface for hardware mixer controls. + * + * Applications rarely need to use this interface, it is provided mainly + * for system-level mixer applets and the like. Volume control in playback + * applications should be done using a volume + * element or, if available, using the volume property of + * the audio sink element used (as provided by pulsesink + * for example), or even better: just use the playbin2 + * element's volume property. + * + * Usage: In order to use the GstMixer interface, the + * element needs to be at least in READY state (so that the element has opened + * the mixer device). Once the element has been set to READY state or higher, + * it can be cast to a GstMixer using the GST_MIXER + * macro (in C) and the mixer API can be used. + */ + +#ifndef GST_DISABLE_DEPRECATED +enum +{ + SIGNAL_MUTE_TOGGLED, + SIGNAL_RECORD_TOGGLED, + SIGNAL_VOLUME_CHANGED, + SIGNAL_OPTION_CHANGED, + LAST_SIGNAL +}; + +static guint gst_mixer_signals[LAST_SIGNAL] = { 0 }; + +#endif + +static void gst_mixer_class_init (GstMixerClass * klass); + +GType +gst_mixer_get_type (void) +{ + static GType gst_mixer_type = 0; + + if (!gst_mixer_type) { + static const GTypeInfo gst_mixer_info = { + sizeof (GstMixerClass), + (GBaseInitFunc) gst_mixer_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_mixer_type = g_type_register_static (G_TYPE_INTERFACE, + "GstMixer", &gst_mixer_info, 0); + g_type_interface_add_prerequisite (gst_mixer_type, + GST_TYPE_IMPLEMENTS_INTERFACE); + } + + return gst_mixer_type; +} + +static void +gst_mixer_class_init (GstMixerClass * klass) +{ +#ifndef GST_DISABLE_DEPRECATED + static gboolean initialized = FALSE; + + /* signals (deprecated) */ + if (!initialized) { + gst_mixer_signals[SIGNAL_RECORD_TOGGLED] = + g_signal_new ("record-toggled", + GST_TYPE_MIXER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerClass, record_toggled), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, + GST_TYPE_MIXER_TRACK, G_TYPE_BOOLEAN); + gst_mixer_signals[SIGNAL_MUTE_TOGGLED] = + g_signal_new ("mute-toggled", + GST_TYPE_MIXER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerClass, mute_toggled), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, + GST_TYPE_MIXER_TRACK, G_TYPE_BOOLEAN); + gst_mixer_signals[SIGNAL_VOLUME_CHANGED] = + g_signal_new ("volume-changed", + GST_TYPE_MIXER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerClass, volume_changed), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, + GST_TYPE_MIXER_TRACK, G_TYPE_POINTER); + gst_mixer_signals[SIGNAL_OPTION_CHANGED] = + g_signal_new ("option-changed", + GST_TYPE_MIXER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerClass, option_changed), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_STRING, G_TYPE_NONE, 2, + GST_TYPE_MIXER_OPTIONS, G_TYPE_STRING); + + initialized = TRUE; + } +#endif + + klass->mixer_type = GST_MIXER_SOFTWARE; + + /* default virtual functions */ + klass->list_tracks = NULL; + klass->set_volume = NULL; + klass->get_volume = NULL; + klass->set_mute = NULL; + klass->set_record = NULL; + klass->set_option = NULL; + klass->get_option = NULL; +} + +/** + * gst_mixer_list_tracks: + * @mixer: the #GstMixer (a #GstElement) to get the tracks from. + * + * Returns a list of available tracks for this mixer/element. Note + * that it is allowed for sink (output) elements to only provide + * the output tracks in this list. Likewise, for sources (inputs), + * it is allowed to only provide input elements in this list. + * + * Returns: A #GList consisting of zero or more #GstMixerTracks. + * The list is owned by the #GstMixer instance and must not be freed + * or modified. + */ + +const GList * +gst_mixer_list_tracks (GstMixer * mixer) +{ + GstMixerClass *klass; + + g_return_val_if_fail (mixer != NULL, NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->list_tracks) { + return klass->list_tracks (mixer); + } + + return NULL; +} + +/** + * gst_mixer_set_volume: + * @mixer: The #GstMixer (a #GstElement) that owns the track. + * @track: The #GstMixerTrack to set the volume on. + * @volumes: an array of integers (of size track->num_channels) + * that gives the wanted volume for each channel in + * this track. + * + * Sets the volume on each channel in a track. Short note about + * naming: a track is defined as one separate stream owned by + * the mixer/element, such as 'Line-in' or 'Microphone'. A + * channel is said to be a mono-stream inside this track. A + * stereo track thus contains two channels. + */ + +void +gst_mixer_set_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes) +{ + GstMixerClass *klass; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (track != NULL); + g_return_if_fail (volumes != NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->set_volume) { + klass->set_volume (mixer, track, volumes); + } +} + +/** + * gst_mixer_get_volume: + * @mixer: the #GstMixer (a #GstElement) that owns the track + * @track: the GstMixerTrack to get the volume from. + * @volumes: a pre-allocated array of integers (of size + * track->num_channels) to store the current volume + * of each channel in the given track in. + * + * Get the current volume(s) on the given track. + */ + +void +gst_mixer_get_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes) +{ + GstMixerClass *klass; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (track != NULL); + g_return_if_fail (volumes != NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->get_volume) { + klass->get_volume (mixer, track, volumes); + } else { + gint i; + + for (i = 0; i < track->num_channels; i++) { + volumes[i] = 0; + } + } +} + +/** + * gst_mixer_set_mute: + * @mixer: the #GstMixer (a #GstElement) that owns the track. + * @track: the #GstMixerTrack to operate on. + * @mute: a boolean value indicating whether to turn on or off + * muting. + * + * Mutes or unmutes the given channel. To find out whether a + * track is currently muted, use GST_MIXER_TRACK_HAS_FLAG (). + */ + +void +gst_mixer_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute) +{ + GstMixerClass *klass; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (track != NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->set_mute) { + klass->set_mute (mixer, track, mute); + } +} + +/** + * gst_mixer_set_record: + * @mixer: The #GstMixer (a #GstElement) that owns the track. + * @track: the #GstMixerTrack to operate on. + * @record: a boolean value that indicates whether to turn on + * or off recording. + * + * Enables or disables recording on the given track. Note that + * this is only possible on input tracks, not on output tracks + * (see GST_MIXER_TRACK_HAS_FLAG () and the GST_MIXER_TRACK_INPUT + * flag). + */ + +void +gst_mixer_set_record (GstMixer * mixer, GstMixerTrack * track, gboolean record) +{ + GstMixerClass *klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->set_record) { + klass->set_record (mixer, track, record); + } +} + +/** + * gst_mixer_set_option: + * @mixer: The #GstMixer (a #GstElement) that owns the optionlist. + * @opts: The #GstMixerOptions that we operate on. + * @value: The requested new option value. + * + * Sets a name/value option in the mixer to the requested value. + */ + +void +gst_mixer_set_option (GstMixer * mixer, GstMixerOptions * opts, gchar * value) +{ + GstMixerClass *klass; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (opts != NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->set_option) { + klass->set_option (mixer, opts, value); + } +} + +/** + * gst_mixer_get_option: + * @mixer: The #GstMixer (a #GstElement) that owns the optionlist. + * @opts: The #GstMixerOptions that we operate on. + * + * Get the current value of a name/value option in the mixer. + * + * Returns: current value of the name/value option. + */ + +const gchar * +gst_mixer_get_option (GstMixer * mixer, GstMixerOptions * opts) +{ + GstMixerClass *klass; + + g_return_val_if_fail (mixer != NULL, NULL); + g_return_val_if_fail (opts != NULL, NULL); + + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->get_option) { + return klass->get_option (mixer, opts); + } + + return NULL; +} + +/** + * gst_mixer_get_mixer_type: + * @mixer: The #GstMixer implementation + * + * Get the #GstMixerType of this mixer implementation. + * + * Returns: A the #GstMixerType. + * + * Since: 0.10.24 + */ +GstMixerType +gst_mixer_get_mixer_type (GstMixer * mixer) +{ + GstMixerClass *klass = GST_MIXER_GET_CLASS (mixer); + + return klass->mixer_type; +} + +/** + * gst_mixer_get_mixer_flags: + * @mixer: The #GstMixer implementation + * + * Get the set of supported flags for this mixer implementation. + * + * Returns: A set of or-ed GstMixerFlags for supported features. + */ +GstMixerFlags +gst_mixer_get_mixer_flags (GstMixer * mixer) +{ + GstMixerClass *klass; + + g_return_val_if_fail (mixer != NULL, FALSE); + klass = GST_MIXER_GET_CLASS (mixer); + + if (klass->get_mixer_flags) { + return klass->get_mixer_flags (mixer); + } + return GST_MIXER_FLAG_NONE; +} + +/** + * gst_mixer_mute_toggled: + * @mixer: the #GstMixer (a #GstElement) that owns the track + * @track: the GstMixerTrack that has change mute state. + * @mute: the new state of the mute flag on the track + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the given track + * has changed mute state. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus. + */ +void +gst_mixer_mute_toggled (GstMixer * mixer, GstMixerTrack * track, gboolean mute) +{ + GstStructure *s; + GstMessage *m; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + g_return_if_fail (track != NULL); + + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "mute-toggled", + "track", GST_TYPE_MIXER_TRACK, track, "mute", G_TYPE_BOOLEAN, mute, NULL); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +/** + * gst_mixer_record_toggled: + * @mixer: the #GstMixer (a #GstElement) that owns the track + * @track: the GstMixerTrack that has changed recording state. + * @record: the new state of the record flag on the track + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the given track + * has changed recording state. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus. + */ +void +gst_mixer_record_toggled (GstMixer * mixer, + GstMixerTrack * track, gboolean record) +{ + GstStructure *s; + GstMessage *m; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + g_return_if_fail (track != NULL); + + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "record-toggled", + "track", GST_TYPE_MIXER_TRACK, track, + "record", G_TYPE_BOOLEAN, record, NULL); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +/** + * gst_mixer_volume_changed: + * @mixer: the #GstMixer (a #GstElement) that owns the track + * @track: the GstMixerTrack that has changed. + * @volumes: Array of volume values, one per channel on the mixer track. + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the volume(s) for the + * given track have changed. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus. + */ +void +gst_mixer_volume_changed (GstMixer * mixer, + GstMixerTrack * track, gint * volumes) +{ + GstStructure *s; + GstMessage *m; + GValue l = { 0, }; + GValue v = { 0, }; + gint i; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + g_return_if_fail (track != NULL); + + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "volume-changed", + "track", GST_TYPE_MIXER_TRACK, track, NULL); + + g_value_init (&l, GST_TYPE_ARRAY); + + g_value_init (&v, G_TYPE_INT); + + /* FIXME 0.11: pass track->num_channels to the function */ + for (i = 0; i < track->num_channels; ++i) { + g_value_set_int (&v, volumes[i]); + gst_value_array_append_value (&l, &v); + } + g_value_unset (&v); + + gst_structure_set_value (s, "volumes", &l); + g_value_unset (&l); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +/** + * gst_mixer_option_changed: + * @mixer: the #GstMixer (a #GstElement) that owns the options + * @opts: the GstMixerOptions that has changed value. + * @value: the new value of the GstMixerOptions. + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the given options + * object has changed state. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus. + */ +void +gst_mixer_option_changed (GstMixer * mixer, + GstMixerOptions * opts, const gchar * value) +{ + GstStructure *s; + GstMessage *m; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + g_return_if_fail (opts != NULL); + + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "option-changed", + "options", GST_TYPE_MIXER_OPTIONS, opts, + "value", G_TYPE_STRING, value, NULL); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +/** + * gst_mixer_options_list_changed: + * @mixer: the #GstMixer (a #GstElement) that owns the options + * @opts: the GstMixerOptions whose list of values has changed + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the list of possible + * options of a given options object has changed. + * + * The new options are not contained in the message on purpose. Applications + * should call gst_mixer_option_get_values() on @opts to make @opts update + * its internal state and obtain the new list of values. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus + * for this to work. + * + * Since: 0.10.18 + */ +void +gst_mixer_options_list_changed (GstMixer * mixer, GstMixerOptions * opts) +{ + GstStructure *s; + GstMessage *m; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + g_return_if_fail (opts != NULL); + g_return_if_fail (GST_IS_MIXER_OPTIONS (opts)); + + /* we do not include the new list here on purpose, so that the application + * has to use gst_mixer_options_get_values() to get the new list, which then + * allows the mixer options object to update the internal GList in a somewhat + * thread-safe way at least */ + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "options-list-changed", + "options", GST_TYPE_MIXER_OPTIONS, opts, NULL); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +/** + * gst_mixer_mixer_changed: + * @mixer: the #GstMixer (a #GstElement) which has changed + * + * This function is called by the mixer implementation to produce + * a notification message on the bus indicating that the list of available + * mixer tracks for a given mixer object has changed. Applications should + * rebuild their interface when they receive this message. + * + * This function only works for GstElements that are implementing the + * GstMixer interface, and the element needs to have been provided a bus. + * + * Since: 0.10.18 + */ +void +gst_mixer_mixer_changed (GstMixer * mixer) +{ + GstStructure *s; + GstMessage *m; + + g_return_if_fail (mixer != NULL); + g_return_if_fail (GST_IS_ELEMENT (mixer)); + + s = gst_structure_new (GST_MIXER_MESSAGE_NAME, + "type", G_TYPE_STRING, "mixer-changed", NULL); + + m = gst_message_new_element (GST_OBJECT (mixer), s); + if (gst_element_post_message (GST_ELEMENT (mixer), m) == FALSE) { + GST_WARNING ("This element has no bus, therefore no message sent!"); + } +} + +static gboolean +gst_mixer_message_is_mixer_message (GstMessage * message) +{ + const GstStructure *s; + + if (message == NULL) + return FALSE; + if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + return FALSE; + + s = gst_message_get_structure (message); + return gst_structure_has_name (s, GST_MIXER_MESSAGE_NAME); +} + +/** + * gst_mixer_message_get_type: + * @message: A GstMessage to inspect. + * + * Check a bus message to see if it is a GstMixer notification + * message and return the GstMixerMessageType identifying which + * type of notification it is. + * + * Returns: The type of the GstMixerMessage, or GST_MIXER_MESSAGE_INVALID + * if the message is not a GstMixer notification. + * + * Since: 0.10.14 + */ +GstMixerMessageType +gst_mixer_message_get_type (GstMessage * message) +{ + const GstStructure *s; + const gchar *m_type; + + if (!gst_mixer_message_is_mixer_message (message)) + return GST_MIXER_MESSAGE_INVALID; + + s = gst_message_get_structure (message); + m_type = gst_structure_get_string (s, "type"); + g_return_val_if_fail (m_type != NULL, GST_MIXER_MESSAGE_INVALID); + + if (g_str_equal (m_type, "mute-toggled")) + return GST_MIXER_MESSAGE_MUTE_TOGGLED; + else if (g_str_equal (m_type, "record-toggled")) + return GST_MIXER_MESSAGE_RECORD_TOGGLED; + else if (g_str_equal (m_type, "volume-changed")) + return GST_MIXER_MESSAGE_VOLUME_CHANGED; + else if (g_str_equal (m_type, "option-changed")) + return GST_MIXER_MESSAGE_OPTION_CHANGED; + else if (g_str_equal (m_type, "options-list-changed")) + return GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED; + else if (g_str_equal (m_type, "mixer-changed")) + return GST_MIXER_MESSAGE_MIXER_CHANGED; + + return GST_MIXER_MESSAGE_INVALID; +} + +#define GST_MIXER_MESSAGE_HAS_TYPE(msg,msg_type) \ +(gst_mixer_message_get_type (msg) == GST_MIXER_MESSAGE_ ## msg_type) + +/** + * gst_mixer_message_parse_mute_toggled: + * @message: A mute-toggled change notification message. + * @track: Pointer to hold a GstMixerTrack object, or NULL. + * @mute: A pointer to a gboolean variable, or NULL. + * + * Extracts the contents of a mute-toggled bus message. Reads + * the GstMixerTrack that has changed, and the new value of the mute + * flag. + * + * The GstMixerTrack remains valid until the message is freed. + * + * Since: 0.10.14 + */ +void +gst_mixer_message_parse_mute_toggled (GstMessage * message, + GstMixerTrack ** track, gboolean * mute) +{ + const GstStructure *s; + + g_return_if_fail (gst_mixer_message_is_mixer_message (message)); + g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, MUTE_TOGGLED)); + + s = gst_message_get_structure (message); + + if (track) { + const GValue *v = gst_structure_get_value (s, "track"); + + g_return_if_fail (v != NULL); + *track = (GstMixerTrack *) g_value_get_object (v); + g_return_if_fail (GST_IS_MIXER_TRACK (*track)); + } + + if (mute) + g_return_if_fail (gst_structure_get_boolean (s, "mute", mute)); +} + +/** + * gst_mixer_message_parse_record_toggled: + * @message: A record-toggled change notification message. + * @track: Pointer to hold a GstMixerTrack object, or NULL. + * @record: A pointer to a gboolean variable, or NULL. + * + * Extracts the contents of a record-toggled bus message. Reads + * the GstMixerTrack that has changed, and the new value of the + * recording flag. + * + * The GstMixerTrack remains valid until the message is freed. + * + * Since: 0.10.14 + */ +void +gst_mixer_message_parse_record_toggled (GstMessage * message, + GstMixerTrack ** track, gboolean * record) +{ + const GstStructure *s; + + g_return_if_fail (gst_mixer_message_is_mixer_message (message)); + g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, RECORD_TOGGLED)); + + s = gst_message_get_structure (message); + + if (track) { + const GValue *v = gst_structure_get_value (s, "track"); + + g_return_if_fail (v != NULL); + *track = (GstMixerTrack *) g_value_get_object (v); + g_return_if_fail (GST_IS_MIXER_TRACK (*track)); + } + + if (record) + g_return_if_fail (gst_structure_get_boolean (s, "record", record)); +} + +/** + * gst_mixer_message_parse_volume_changed: + * @message: A volume-changed change notification message. + * @track: Pointer to hold a GstMixerTrack object, or NULL. + * @volumes: A pointer to receive an array of gint values, or NULL. + * @num_channels: Result location to receive the number of channels, or NULL. + * + * Parses a volume-changed notification message and extracts the track object + * it refers to, as well as an array of volumes and the size of the volumes array. + * + * The track object remains valid until the message is freed. + * + * The caller must free the array returned in the volumes parameter using g_free + * when they are done with it. + * + * Since: 0.10.14 + */ +void +gst_mixer_message_parse_volume_changed (GstMessage * message, + GstMixerTrack ** track, gint ** volumes, gint * num_channels) +{ + const GstStructure *s; + + g_return_if_fail (gst_mixer_message_is_mixer_message (message)); + g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, VOLUME_CHANGED)); + + s = gst_message_get_structure (message); + + if (track) { + const GValue *v = gst_structure_get_value (s, "track"); + + g_return_if_fail (v != NULL); + *track = (GstMixerTrack *) g_value_get_object (v); + g_return_if_fail (GST_IS_MIXER_TRACK (*track)); + } + + if (volumes || num_channels) { + gint n_chans, i; + const GValue *v = gst_structure_get_value (s, "volumes"); + + g_return_if_fail (v != NULL); + g_return_if_fail (GST_VALUE_HOLDS_ARRAY (v)); + + n_chans = gst_value_array_get_size (v); + if (num_channels) + *num_channels = n_chans; + + if (volumes) { + *volumes = g_new (gint, n_chans); + for (i = 0; i < n_chans; i++) { + const GValue *e = gst_value_array_get_value (v, i); + + g_return_if_fail (e != NULL && G_VALUE_HOLDS_INT (e)); + (*volumes)[i] = g_value_get_int (e); + } + } + } +} + +/** + * gst_mixer_message_parse_option_changed: + * @message: A volume-changed change notification message. + * @options: Pointer to hold a GstMixerOptions object, or NULL. + * @value: Result location to receive the new options value, or NULL. + * + * Extracts the GstMixerOptions and new value from a option-changed bus notification + * message. + * + * The options and value returned remain valid until the message is freed. + * + * Since: 0.10.14 + */ +void +gst_mixer_message_parse_option_changed (GstMessage * message, + GstMixerOptions ** options, const gchar ** value) +{ + const GstStructure *s; + + g_return_if_fail (gst_mixer_message_is_mixer_message (message)); + g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTION_CHANGED)); + + s = gst_message_get_structure (message); + + if (options) { + const GValue *v = gst_structure_get_value (s, "options"); + + g_return_if_fail (v != NULL); + *options = (GstMixerOptions *) g_value_get_object (v); + g_return_if_fail (GST_IS_MIXER_OPTIONS (*options)); + } + + if (value) + *value = gst_structure_get_string (s, "value"); +} + +/** + * gst_mixer_message_parse_options_list_changed: + * @message: A volume-changed change notification message. + * @options: Pointer to hold a GstMixerOptions object, or NULL. + * + * Extracts the GstMixerOptions whose value list has changed from an + * options-list-changed bus notification message. + * + * The options object returned remains valid until the message is freed. You + * do not need to unref it. + * + * Since: 0.10.18 + */ +void +gst_mixer_message_parse_options_list_changed (GstMessage * message, + GstMixerOptions ** options) +{ + const GstStructure *s; + + g_return_if_fail (gst_mixer_message_is_mixer_message (message)); + g_return_if_fail (GST_MIXER_MESSAGE_HAS_TYPE (message, OPTIONS_LIST_CHANGED)); + + s = gst_message_get_structure (message); + + if (options) { + const GValue *v = gst_structure_get_value (s, "options"); + + g_return_if_fail (v != NULL); + *options = (GstMixerOptions *) g_value_get_object (v); + g_return_if_fail (GST_IS_MIXER_OPTIONS (*options)); + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.h new file mode 100644 index 0000000..ae3e830 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixer.h @@ -0,0 +1,231 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixer.h: mixer interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_MIXER_H__ +#define __GST_MIXER_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_MIXER \ + (gst_mixer_get_type ()) +#define GST_MIXER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER, GstMixer)) +#define GST_MIXER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER, GstMixerClass)) +#define GST_IS_MIXER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER)) +#define GST_IS_MIXER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER)) +#define GST_MIXER_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_MIXER, GstMixerClass)) + +#define GST_MIXER_TYPE(klass) (klass->mixer_type) + +typedef struct _GstMixer GstMixer; +typedef struct _GstMixerClass GstMixerClass; + +typedef enum +{ + GST_MIXER_HARDWARE, + GST_MIXER_SOFTWARE +} GstMixerType; + +/** + * GstMixerMessageType: + * @GST_MIXER_MESSAGE_INVALID: Not a GstMixer message + * @GST_MIXER_MESSAGE_MUTE_TOGGLED: A mute-toggled GstMixer message + * @GST_MIXER_MESSAGE_RECORD_TOGGLED: A record-toggled GstMixer message + * @GST_MIXER_MESSAGE_VOLUME_CHANGED: A volume-changed GstMixer message + * @GST_MIXER_MESSAGE_OPTION_CHANGED: An option-changed GstMixer message + * @GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED: An options-list-changed + * GstMixer message, posted when the list of available options for a + * GstMixerOptions object has changed (Since: 0.10.18) + * @GST_MIXER_MESSAGE_MIXER_CHANGED: A mixer-changed GstMixer message, posted + * when the list of available mixer tracks has changed. The application + * should re-build its interface in this case (Since: 0.10.18) + * + * An enumeration for the type of a GstMixer message received on the bus + * + * Since: 0.10.14 + */ +typedef enum +{ + GST_MIXER_MESSAGE_INVALID, + GST_MIXER_MESSAGE_MUTE_TOGGLED, + GST_MIXER_MESSAGE_RECORD_TOGGLED, + GST_MIXER_MESSAGE_VOLUME_CHANGED, + GST_MIXER_MESSAGE_OPTION_CHANGED, + GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED, + GST_MIXER_MESSAGE_MIXER_CHANGED +} GstMixerMessageType; + +/** + * GstMixerFlags: + * @GST_MIXER_FLAG_NONE: No flags + * @GST_MIXER_FLAG_AUTO_NOTIFICATIONS: The mixer implementation automatically + * sends notification messages. + * @GST_MIXER_FLAG_HAS_WHITELIST: The mixer implementation flags tracks that + * should be displayed by default (whitelisted). Since: 0.10.23 + * @GST_MIXER_FLAG_GROUPING: The mixer implementation will leave some controls + * marked without either input or output. Controls marked as input or + * output should be grouped with input & output sliders, even if they + * are options or bare switches. Since: 0.10.23 + * + * Flags indicating which optional features are supported by a mixer + * implementation. + * + * Since: 0.10.14 + */ +typedef enum +{ + GST_MIXER_FLAG_NONE = 0, + GST_MIXER_FLAG_AUTO_NOTIFICATIONS = (1<<0), + GST_MIXER_FLAG_HAS_WHITELIST = (1<<1), + GST_MIXER_FLAG_GROUPING = (1<<2), +} GstMixerFlags; + +struct _GstMixerClass { + GTypeInterface klass; + + GstMixerType mixer_type; + + /* virtual functions */ + const GList * (* list_tracks) (GstMixer *mixer); + + void (* set_volume) (GstMixer *mixer, + GstMixerTrack *track, + gint *volumes); + void (* get_volume) (GstMixer *mixer, + GstMixerTrack *track, + gint *volumes); + + void (* set_mute) (GstMixer *mixer, + GstMixerTrack *track, + gboolean mute); + void (* set_record) (GstMixer *mixer, + GstMixerTrack *track, + gboolean record); +#ifndef GST_DISABLE_DEPRECATED + /* signals (deprecated) */ + void (* mute_toggled) (GstMixer *mixer, + GstMixerTrack *channel, + gboolean mute); + void (* record_toggled) (GstMixer *mixer, + GstMixerTrack *channel, + gboolean record); + void (* volume_changed) (GstMixer *mixer, + GstMixerTrack *channel, + gint *volumes); +#else + gpointer padding1[3]; +#endif /* not GST_DISABLE_DEPRECATED */ + + void (* set_option) (GstMixer *mixer, + GstMixerOptions *opts, + gchar *value); + const gchar * (* get_option) (GstMixer *mixer, + GstMixerOptions *opts); + +#ifndef GST_DISABLE_DEPRECATED + void (* option_changed) (GstMixer *mixer, + GstMixerOptions *opts, + gchar *option); +#else + gpointer padding2; +#endif /* not GST_DISABLE_DEPRECATED */ + + GstMixerFlags (* get_mixer_flags) (GstMixer *mixer); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING-1]; +}; + +GType gst_mixer_get_type (void); + +/* virtual class function wrappers */ +const GList * gst_mixer_list_tracks (GstMixer *mixer); +void gst_mixer_set_volume (GstMixer *mixer, + GstMixerTrack *track, + gint *volumes); +void gst_mixer_get_volume (GstMixer *mixer, + GstMixerTrack *track, + gint *volumes); +void gst_mixer_set_mute (GstMixer *mixer, + GstMixerTrack *track, + gboolean mute); +void gst_mixer_set_record (GstMixer *mixer, + GstMixerTrack *track, + gboolean record); +void gst_mixer_set_option (GstMixer *mixer, + GstMixerOptions *opts, + gchar *value); +const gchar * gst_mixer_get_option (GstMixer *mixer, + GstMixerOptions *opts); + +/* trigger bus messages */ +void gst_mixer_mute_toggled (GstMixer *mixer, + GstMixerTrack *track, + gboolean mute); +void gst_mixer_record_toggled (GstMixer *mixer, + GstMixerTrack *track, + gboolean record); +void gst_mixer_volume_changed (GstMixer *mixer, + GstMixerTrack *track, + gint *volumes); +void gst_mixer_option_changed (GstMixer *mixer, + GstMixerOptions *opts, + const gchar *value); + +void gst_mixer_mixer_changed (GstMixer *mixer); + +void gst_mixer_options_list_changed (GstMixer *mixer, + GstMixerOptions *opts); + +GstMixerType gst_mixer_get_mixer_type (GstMixer *mixer); + +GstMixerFlags gst_mixer_get_mixer_flags (GstMixer *mixer); + +/* Functions for recognising and parsing GstMixerMessages on the bus */ +GstMixerMessageType gst_mixer_message_get_type (GstMessage *message); +void gst_mixer_message_parse_mute_toggled (GstMessage *message, + GstMixerTrack **track, + gboolean *mute); +void gst_mixer_message_parse_record_toggled (GstMessage *message, + GstMixerTrack **track, + gboolean *record); +void gst_mixer_message_parse_volume_changed (GstMessage *message, + GstMixerTrack **track, + gint **volumes, + gint *num_channels); +void gst_mixer_message_parse_option_changed (GstMessage *message, + GstMixerOptions **options, + const gchar **value); +void gst_mixer_message_parse_options_list_changed (GstMessage *message, + GstMixerOptions **options); + +G_END_DECLS + +#endif /* __GST_MIXER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.c new file mode 100644 index 0000000..01b75b4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.c @@ -0,0 +1,146 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixeroptions.c: mixer track options object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstmixeroptions + * @short_description: Multi-option mixer control + * @see_also: GstMixer, GstMixerTrack + * + * Mixer control object that allows switching between multiple options. + * Note that GstMixerOptions is a subclass of + * GstMixerTrack. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mixeroptions.h" + +#if 0 +enum +{ + /* FILL ME */ + SIGNAL_OPTION_CHANGED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; +#endif + +static void gst_mixer_options_class_init (GstMixerOptionsClass * klass); +static void gst_mixer_options_init (GstMixerOptions * mixer); +static void gst_mixer_options_dispose (GObject * object); + +static GObjectClass *parent_class = NULL; + +GType +gst_mixer_options_get_type (void) +{ + static GType gst_mixer_options_type = 0; + + if (!gst_mixer_options_type) { + static const GTypeInfo mixer_options_info = { + sizeof (GstMixerOptionsClass), + NULL, + NULL, + (GClassInitFunc) gst_mixer_options_class_init, + NULL, + NULL, + sizeof (GstMixerOptions), + 0, + (GInstanceInitFunc) gst_mixer_options_init, + NULL + }; + + gst_mixer_options_type = + g_type_register_static (GST_TYPE_MIXER_TRACK, + "GstMixerOptions", &mixer_options_info, 0); + } + + return gst_mixer_options_type; +} + +static void +gst_mixer_options_class_init (GstMixerOptionsClass * klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); +#if 0 + signals[SIGNAL_OPTION_CHANGED] = + g_signal_new ("option_changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerOptionsClass, option_changed), + NULL, NULL, g_cclosure_marshal_VOID__STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); +#endif + + object_klass->dispose = gst_mixer_options_dispose; +} + +static void +gst_mixer_options_init (GstMixerOptions * mixer_options) +{ + mixer_options->values = NULL; +} + +/** + * gst_mixer_options_get_values: + * @mixer_options: The #GstMixerOptions item that owns the values. + * + * Get the values for the mixer option. + * + * Returns: A list of strings with all the possible values for the mixer + * option. You must not free or modify the list or its contents, it belongs + * to the @mixer_options object. + */ +GList * +gst_mixer_options_get_values (GstMixerOptions * mixer_options) +{ + GstMixerOptionsClass *klass; + GList *ret = NULL; + + g_return_val_if_fail (GST_IS_MIXER_OPTIONS (mixer_options), NULL); + + klass = GST_MIXER_OPTIONS_GET_CLASS (mixer_options); + + if (klass->get_values != NULL) { + ret = klass->get_values (mixer_options); + } else { + ret = mixer_options->values; + } + + return ret; +} + + +static void +gst_mixer_options_dispose (GObject * object) +{ + GstMixerOptions *opts = GST_MIXER_OPTIONS (object); + + g_list_foreach (opts->values, (GFunc) g_free, NULL); + g_list_free (opts->values); + opts->values = NULL; + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.h new file mode 100644 index 0000000..2724da5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixeroptions.h @@ -0,0 +1,91 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixeroptions.h: mixer track options object + * This should be a subclass of MixerItem, along with MixerOptions, + * but that's not possible because of API/ABI in 0.8.x. FIXME. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_MIXER_OPTIONS_H__ +#define __GST_MIXER_OPTIONS_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_MIXER_OPTIONS \ + (gst_mixer_options_get_type ()) +#define GST_MIXER_OPTIONS(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER_OPTIONS, \ + GstMixerOptions)) +#define GST_MIXER_OPTIONS_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MIXER_OPTIONS, GstMixerOptionsClass)) +#define GST_MIXER_OPTIONS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER_OPTIONS, \ + GstMixerOptionsClass)) +#define GST_IS_MIXER_OPTIONS(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER_OPTIONS)) +#define GST_IS_MIXER_OPTIONS_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER_OPTIONS)) + +typedef struct _GstMixerOptions GstMixerOptions; +typedef struct _GstMixerOptionsClass GstMixerOptionsClass; + +/** + * GstMixerOptions: + * @parent: Parent object + * @values: List of option strings. Do not access this member directly, + * always use gst_mixer_options_get_values() instead. + */ +struct _GstMixerOptions { + GstMixerTrack parent; + + /* list of strings (do not access directly) (FIXME 0.11: make private) */ + GList *values; + + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstMixerOptionsClass: + * @parent: Parent class + * @get_values: Optional implementation of gst_mixer_options_get_values(). + * (Since: 0.10.18) + */ +struct _GstMixerOptionsClass { + GstMixerTrackClass parent; + +#ifdef GST_MIXER_NEED_DEPRECATED + /* signals */ + void (* option_changed) (GstMixerOptions *opts, + gchar *value); +#endif /* GST_MIXER_NEED_DEPRECATED */ + + GList * (* get_values) (GstMixerOptions *opts); + + gpointer _gst_reserved[GST_PADDING-1]; +}; + +GType gst_mixer_options_get_type (void); + +GList * gst_mixer_options_get_values (GstMixerOptions *mixer_options); + +G_END_DECLS + +#endif /* __GST_MIXER_OPTIONS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.c new file mode 100644 index 0000000..c4bef1c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.c @@ -0,0 +1,288 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixertrack.c: mixer track object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstmixertrack + * @short_description: Basic mixer control object (volume slider, switch) + * @see_also: GstMixer, GstMixerOptions + * + * Basic mixer control object (note that it is a GObject and not a GstObject). + * + * A mixer track represents a single slider control of none, one or more + * channels. A mixer track with no channels is usually interpreted as a + * on/off switch control. + * + * Note the presence of both min_volume and max_volume fields. Applications + * must not assume that min_volume is 0 or max_volume is any particular + * value. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mixertrack.h" +#if 0 +enum +{ + /* FILL ME */ + SIGNAL_VOLUME_CHANGED, + SIGNAL_RECORD_TOGGLED, + SIGNAL_MUTE_TOGGLED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = { 0 }; +#endif + +enum +{ + ARG_0, + ARG_LABEL, + ARG_UNTRANSLATED_LABEL, + ARG_INDEX, + ARG_MIN_VOLUME, + ARG_MAX_VOLUME, + ARG_FLAGS, + ARG_NUM_CHANNELS +}; + +static void gst_mixer_track_class_init (GstMixerTrackClass * klass); +static void gst_mixer_track_init (GstMixerTrack * mixer); +static void gst_mixer_track_dispose (GObject * object); + +static void gst_mixer_track_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_mixer_track_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); + +static GObjectClass *parent_class = NULL; + +GType +gst_mixer_track_get_type (void) +{ + static GType gst_mixer_track_type = 0; + + if (!gst_mixer_track_type) { + static const GTypeInfo mixer_track_info = { + sizeof (GstMixerTrackClass), + NULL, + NULL, + (GClassInitFunc) gst_mixer_track_class_init, + NULL, + NULL, + sizeof (GstMixerTrack), + 0, + (GInstanceInitFunc) gst_mixer_track_init, + NULL + }; + + gst_mixer_track_type = + g_type_register_static (G_TYPE_OBJECT, + "GstMixerTrack", &mixer_track_info, 0); + } + + return gst_mixer_track_type; +} + +static void +gst_mixer_track_class_init (GstMixerTrackClass * klass) +{ + GObjectClass *object_klass = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_klass->get_property = gst_mixer_track_get_property; + object_klass->set_property = gst_mixer_track_set_property; + + g_object_class_install_property (object_klass, ARG_LABEL, + g_param_spec_string ("label", "Track label", + "The label assigned to the track (may be translated)", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_STATIC_STRINGS)); + + /** + * GstMixerTrack:untranslated-label + * + * The untranslated label of the mixer track, if available. Mixer track + * implementations must set this at construct time. Applications may find + * this useful to determine icons for various kind of tracks. However, + * applications mustn't make any assumptions about the naming of tracks, + * the untranslated labels are purely informational and may change. + * + * Since: 0.10.13 + **/ + g_object_class_install_property (object_klass, ARG_UNTRANSLATED_LABEL, + g_param_spec_string ("untranslated-label", "Untranslated track label", + "The untranslated label assigned to the track (since 0.10.13)", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); + + /** + * GstMixerTrack:index + * + * Index of the mixer track, if available. Mixer track implementations + * must set this at construct time. This can be used to discern between + * multiple tracks with identical labels. + * + * Since: 0.10.21 + */ + g_object_class_install_property (object_klass, ARG_INDEX, + g_param_spec_uint ("index", "Index", + "Track index", 0, G_MAXUINT, + 0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property (object_klass, ARG_MIN_VOLUME, + g_param_spec_int ("min-volume", "Minimum volume level", + "The minimum possible volume level", G_MININT, G_MAXINT, + 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_klass, ARG_MAX_VOLUME, + g_param_spec_int ("max-volume", "Maximum volume level", + "The maximum possible volume level", G_MININT, G_MAXINT, + 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_klass, ARG_FLAGS, + g_param_spec_uint ("flags", "Flags", + "Flags indicating the type of mixer track", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_klass, ARG_NUM_CHANNELS, + g_param_spec_int ("num-channels", "Number of channels", + "The number of channels contained within the track", + 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + +#if 0 + signals[SIGNAL_RECORD_TOGGLED] = + g_signal_new ("record_toggled", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerTrackClass, + record_toggled), + NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + signals[SIGNAL_MUTE_TOGGLED] = + g_signal_new ("mute_toggled", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerTrackClass, + mute_toggled), + NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + signals[SIGNAL_VOLUME_CHANGED] = + g_signal_new ("volume_changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstMixerTrackClass, + volume_changed), + NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); +#endif + + object_klass->dispose = gst_mixer_track_dispose; +} + +static void +gst_mixer_track_init (GstMixerTrack * mixer_track) +{ + mixer_track->label = NULL; + mixer_track->min_volume = mixer_track->max_volume = 0; + mixer_track->flags = 0; + mixer_track->num_channels = 0; +} + +/* FIXME 0.11: move these as members into the mixer track structure */ +#define MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL "gst-mixer-track-ulabel" +#define MIXER_TRACK_OBJECT_DATA_KEY_INDEX "index" + +static void +gst_mixer_track_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstMixerTrack *mixer_track; + + mixer_track = GST_MIXER_TRACK (object); + + switch (prop_id) { + case ARG_LABEL: + g_value_set_string (value, mixer_track->label); + break; + case ARG_UNTRANSLATED_LABEL: + g_value_set_string (value, + (const gchar *) g_object_get_data (G_OBJECT (mixer_track), + MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL)); + break; + case ARG_INDEX: + g_value_set_uint (value, + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (mixer_track), + MIXER_TRACK_OBJECT_DATA_KEY_INDEX))); + break; + case ARG_MIN_VOLUME: + g_value_set_int (value, mixer_track->min_volume); + break; + case ARG_MAX_VOLUME: + g_value_set_int (value, mixer_track->max_volume); + break; + case ARG_FLAGS: + g_value_set_uint (value, (guint32) mixer_track->flags); + break; + case ARG_NUM_CHANNELS: + g_value_set_int (value, mixer_track->num_channels); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_mixer_track_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMixerTrack *mixer_track; + + mixer_track = GST_MIXER_TRACK (object); + + switch (prop_id) { + case ARG_UNTRANSLATED_LABEL: + g_object_set_data_full (G_OBJECT (mixer_track), + MIXER_TRACK_OBJECT_DATA_KEY_UNTRANSLATED_LABEL, + g_value_dup_string (value), (GDestroyNotify) g_free); + break; + case ARG_INDEX: + g_object_set_data (G_OBJECT (mixer_track), + MIXER_TRACK_OBJECT_DATA_KEY_INDEX, + GINT_TO_POINTER (g_value_get_uint (value))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_mixer_track_dispose (GObject * object) +{ + GstMixerTrack *channel = GST_MIXER_TRACK (object); + + if (channel->label) { + g_free (channel->label); + channel->label = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.h new file mode 100644 index 0000000..33296b9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/mixertrack.h @@ -0,0 +1,134 @@ +/* GStreamer Mixer + * Copyright (C) 2003 Ronald Bultje + * + * mixertrack.h: mixer track object + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_MIXER_TRACK_H__ +#define __GST_MIXER_TRACK_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_MIXER_TRACK \ + (gst_mixer_track_get_type ()) +#define GST_MIXER_TRACK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_MIXER_TRACK, \ + GstMixerTrack)) +#define GST_MIXER_TRACK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_MIXER_TRACK, \ + GstMixerTrackClass)) +#define GST_IS_MIXER_TRACK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_MIXER_TRACK)) +#define GST_IS_MIXER_TRACK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_MIXER_TRACK)) + +/* + * Naming: + * + * A track is a single input/output stream (e.g. line-in, + * microphone, etc.). Channels are then single streams + * within a track. A mono stream has one channel, a stereo + * stream has two, etc. + * + * Input tracks can have 'recording' enabled, which means + * that any input will be hearable into the speakers that + * are attached to the output. Mute is obvious. A track + * flagged as master is the master volume track on this + * mixer, which means that setting this track will change + * the hearable volume on any output. + */ +/** + * GstMixerTrackFlags: + * @GST_MIXER_TRACK_INPUT: mixer track is for input + * @GST_MIXER_TRACK_OUTPUT: mixer track is for output + * @GST_MIXER_TRACK_MUTE: input or output is muted + * @GST_MIXER_TRACK_RECORD: input is audible in speakers attached to output + * (for #GST_MIXER_TRACK_INPUT mixer tracks only) + * @GST_MIXER_TRACK_MASTER: this mixer track is likely to be the master control + * @GST_MIXER_TRACK_SOFTWARE: mixer track's' volume control is implemented + * in software (as opposed to a hardware control) + * @GST_MIXER_TRACK_NO_RECORD: input track lacks support for recordable. + * Since: 0.10.23 + * @GST_MIXER_TRACK_NO_MUTE: play track doesn't support mute. Since: 0.10.23 + * @GST_MIXER_TRACK_WHITELIST: track should be displayed "by default" in apps. + * Since: 0.10.23 + * @GST_MIXER_TRACK_READONLY: track is read-only. Since: 0.10.25 + * @GST_MIXER_TRACK_WRITEONLY: track is write-only. Since: 0.10.25 + * + * Mixer track flags. + */ +typedef enum { + GST_MIXER_TRACK_INPUT = (1<<0), + GST_MIXER_TRACK_OUTPUT = (1<<1), + GST_MIXER_TRACK_MUTE = (1<<2), + GST_MIXER_TRACK_RECORD = (1<<3), + GST_MIXER_TRACK_MASTER = (1<<4), + GST_MIXER_TRACK_SOFTWARE = (1<<5), + GST_MIXER_TRACK_NO_RECORD = (1<<6), + GST_MIXER_TRACK_NO_MUTE = (1<<7), + GST_MIXER_TRACK_WHITELIST = (1<<8), + GST_MIXER_TRACK_READONLY = (1<<9), + GST_MIXER_TRACK_WRITEONLY = (1<<10) +} GstMixerTrackFlags; + +/* FIXME 0.11: READONLY/WRITEONLY -> READABLE/WRITABLE etc. */ + +#define GST_MIXER_TRACK_HAS_FLAG(channel, flag) \ + ((channel)->flags & flag) + +typedef struct _GstMixerTrack GstMixerTrack; +typedef struct _GstMixerTrackClass GstMixerTrackClass; + +struct _GstMixerTrack { + GObject parent; + + gchar *label; + + /* FIXME 0.11: flags should be guint32 */ + GstMixerTrackFlags flags; + + gint num_channels; + gint min_volume; + gint max_volume; + + /* FIXME 0.11: add padding */ +}; + +struct _GstMixerTrackClass { + GObjectClass parent; + +#ifdef GST_MIXER_NEED_DEPRECATED + /* signals (deprecated) */ + void (* mute_toggled) (GstMixerTrack *channel, + gboolean mute); + void (* record_toggled) (GstMixerTrack *channel, + gboolean record); + void (* volume_changed) (GstMixerTrack *channel, + gint *volumes); +#endif /* GST_MIXER_NEED_DEPRECATED */ + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_mixer_track_get_type (void); + +G_END_DECLS + +#endif /* __GST_MIXER_TRACK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.c new file mode 100644 index 0000000..7203ce8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.c @@ -0,0 +1,848 @@ +/* GStreamer Navigation + * Copyright (C) 2003 Ronald Bultje + * Copyright (C) 2007-2009 Jan Schmidt + * + * navigation.c: navigation event virtual class function wrappers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstnavigation + * @short_description: Interface for creating, sending and parsing navigation + * events. + * + * The Navigation interface is used for creating and injecting navigation related + * events such as mouse button presses, cursor motion and key presses. The associated + * library also provides methods for parsing received events, and for sending and + * receiving navigation related bus events. One main usecase is DVD menu navigation. + * + * The main parts of the API are: + * + * + * + * The GstNavigation interface, implemented by elements which provide an application + * with the ability to create and inject navigation events into the pipeline. + * + * + * + * + * GstNavigation event handling API. GstNavigation events are created in response to + * calls on a GstNavigation interface implementation, and sent in the pipeline. Upstream + * elements can use the navigation event API functions to parse the contents of received + * messages. + * + * + * + * + * GstNavigation message handling API. GstNavigation messages may be sent on the message + * bus to inform applications of navigation related changes in the pipeline, such as the + * mouse moving over a clickable region, or the set of available angles changing. + * + * The GstNavigation message functions provide functions for creating and parsing + * custom bus messages for signalling GstNavigation changes. + * + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +static void gst_navigation_class_init (GstNavigationInterface * iface); + +#define GST_NAVIGATION_MESSAGE_NAME "GstNavigationMessage" +#define GST_NAVIGATION_QUERY_NAME "GstNavigationQuery" +#define GST_NAVIGATION_EVENT_NAME "application/x-gst-navigation" + +#define WARN_IF_FAIL(exp,msg) if(G_UNLIKELY(!(exp))){g_warning("%s",(msg));} + +GType +gst_navigation_get_type (void) +{ + static GType gst_navigation_type = 0; + + if (!gst_navigation_type) { + static const GTypeInfo gst_navigation_info = { + sizeof (GstNavigationInterface), + (GBaseInitFunc) gst_navigation_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_navigation_type = g_type_register_static (G_TYPE_INTERFACE, + "GstNavigation", &gst_navigation_info, 0); + } + + return gst_navigation_type; +} + +static void +gst_navigation_class_init (GstNavigationInterface * iface) +{ + /* default virtual functions */ + iface->send_event = NULL; +} + +/* The interface implementer should make sure that the object can handle + * the event. */ +void +gst_navigation_send_event (GstNavigation * navigation, GstStructure * structure) +{ + GstNavigationInterface *iface = GST_NAVIGATION_GET_IFACE (navigation); + + if (iface->send_event) { + iface->send_event (navigation, structure); + } +} + +/** + * gst_navigation_send_key_event: + * @navigation: The navigation interface instance + * @event: The type of the key event. Recognised values are "key-press" and + * "key-release" + * @key: Character representation of the key. This is typically as produced + * by XKeysymToString. + */ +void +gst_navigation_send_key_event (GstNavigation * navigation, const char *event, + const char *key) +{ + gst_navigation_send_event (navigation, + gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, + event, "key", G_TYPE_STRING, key, NULL)); +} + +/** + * gst_navigation_send_mouse_event: + * @navigation: The navigation interface instance + * @event: The type of mouse event, as a text string. Recognised values are + * "mouse-button-press", "mouse-button-release" and "mouse-move". + * @button: The button number of the button being pressed or released. Pass 0 + * for mouse-move events. + * @x: The x coordinate of the mouse event. + * @y: The y coordinate of the mouse event. + * + * Sends a mouse event to the navigation interface. Mouse event coordinates + * are sent relative to the display space of the related output area. This is + * usually the size in pixels of the window associated with the element + * implementing the #GstNavigation interface. + * + */ +void +gst_navigation_send_mouse_event (GstNavigation * navigation, const char *event, + int button, double x, double y) +{ + gst_navigation_send_event (navigation, + gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, + event, "button", G_TYPE_INT, button, "pointer_x", G_TYPE_DOUBLE, x, + "pointer_y", G_TYPE_DOUBLE, y, NULL)); +} + +/** + * gst_navigation_send_command: + * @navigation: The navigation interface instance + * @command: The command to issue + * + * Sends the indicated command to the navigation interface. + * + * Since: 0.10.23 + */ +void +gst_navigation_send_command (GstNavigation * navigation, + GstNavigationCommand command) +{ + gst_navigation_send_event (navigation, + gst_structure_new (GST_NAVIGATION_EVENT_NAME, "event", G_TYPE_STRING, + "command", "command-code", G_TYPE_UINT, (guint) command, NULL)); +} + +/* Navigation Queries */ + +#define GST_NAVIGATION_QUERY_HAS_TYPE(query,query_type) \ +(gst_navigation_query_get_type (query) == GST_NAVIGATION_QUERY_ ## query_type) + +/** + * gst_navigation_query_get_type: + * @query: The query to inspect + * + * Inspect a #GstQuery and return the #GstNavigationQueryType associated with + * it if it is a #GstNavigation query. + * + * Returns: The #GstNavigationQueryType of the query, or + * #GST_NAVIGATION_QUERY_INVALID + * Since: 0.10.23 + */ +GstNavigationQueryType +gst_navigation_query_get_type (GstQuery * query) +{ + const GstStructure *s; + const gchar *q_type; + + if (query == NULL || GST_QUERY_TYPE (query) != GST_QUERY_CUSTOM) + return GST_NAVIGATION_QUERY_INVALID; + + s = gst_query_get_structure (query); + if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_QUERY_NAME)) + return GST_NAVIGATION_QUERY_INVALID; + + q_type = gst_structure_get_string (s, "type"); + if (q_type == NULL) + return GST_NAVIGATION_QUERY_INVALID; + + if (g_str_equal (q_type, "commands")) + return GST_NAVIGATION_QUERY_COMMANDS; + else if (g_str_equal (q_type, "angles")) + return GST_NAVIGATION_QUERY_ANGLES; + + return GST_NAVIGATION_QUERY_INVALID; +} + +/** + * gst_navigation_query_new_commands: + * + * Create a new #GstNavigation commands query. When executed, it will + * query the pipeline for the set of currently available commands. + * + * Returns: The new query. + * Since: 0.10.23 + */ +GstQuery * +gst_navigation_query_new_commands (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME, + "type", G_TYPE_STRING, "commands", NULL); + query = gst_query_new_application (GST_QUERY_CUSTOM, structure); + + return query; +} + +static void +gst_query_list_add_command (GValue * list, GstNavigationCommand val) +{ + GValue item = { 0, }; + + g_value_init (&item, GST_TYPE_NAVIGATION_COMMAND); + g_value_set_enum (&item, val); + gst_value_list_append_value (list, &item); + g_value_unset (&item); +} + +/** + * gst_navigation_query_set_commands: + * @query: a #GstQuery + * @n_cmds: the number of commands to set. + * @...: A list of @GstNavigationCommand values, @n_cmds entries long. + * + * Set the #GstNavigation command query result fields in @query. The number + * of commands passed must be equal to @n_commands. + * + * Since: 0.10.23 + */ +void +gst_navigation_query_set_commands (GstQuery * query, gint n_cmds, ...) +{ + va_list ap; + GValue list = { 0, }; + GstStructure *structure; + gint i; + + g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS)); + + g_value_init (&list, GST_TYPE_LIST); + + va_start (ap, n_cmds); + for (i = 0; i < n_cmds; i++) { + GstNavigationCommand val = va_arg (ap, GstNavigationCommand); + gst_query_list_add_command (&list, val); + } + va_end (ap); + + structure = gst_query_get_structure (query); + gst_structure_set_value (structure, "commands", &list); + + g_value_unset (&list); +} + +/** + * gst_navigation_query_set_commandsv: + * @query: a #GstQuery + * @n_cmds: the number of commands to set. + * @cmds: An array containing @n_cmds @GstNavigationCommand values. + * + * Set the #GstNavigation command query result fields in @query. The number + * of commands passed must be equal to @n_commands. + * + * Since: 0.10.23 + */ +void +gst_navigation_query_set_commandsv (GstQuery * query, gint n_cmds, + GstNavigationCommand * cmds) +{ + GValue list = { 0, }; + GstStructure *structure; + gint i; + + g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS)); + + g_value_init (&list, GST_TYPE_LIST); + for (i = 0; i < n_cmds; i++) { + gst_query_list_add_command (&list, cmds[i]); + } + structure = gst_query_get_structure (query); + gst_structure_set_value (structure, "commands", &list); + + g_value_unset (&list); +} + +/** + * gst_navigation_query_parse_commands_length: + * @query: a #GstQuery + * @n_cmds: the number of commands in this query. + * + * Parse the number of commands in the #GstNavigation commands @query. + * + * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_commands_length (GstQuery * query, guint * n_cmds) +{ + GstStructure *structure; + const GValue *list; + + g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE); + + if (n_cmds == NULL) + return TRUE; + + structure = gst_query_get_structure (query); + list = gst_structure_get_value (structure, "commands"); + if (list == NULL) + *n_cmds = 0; + else + *n_cmds = gst_value_list_get_size (list); + + return TRUE; +} + +/** + * gst_navigation_query_parse_commands_nth: + * @query: a #GstQuery + * @nth: the nth command to retrieve. + * @cmd: a pointer to store the nth command into. + * + * Parse the #GstNavigation command query and retrieve the @nth command from + * it into @cmd. If the list contains less elements than @nth, @cmd will be + * set to #GST_NAVIGATION_COMMAND_INVALID. + * + * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_commands_nth (GstQuery * query, guint nth, + GstNavigationCommand * cmd) +{ + GstStructure *structure; + const GValue *list; + + g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, COMMANDS), FALSE); + + if (cmd == NULL) + return TRUE; + + structure = gst_query_get_structure (query); + list = gst_structure_get_value (structure, "commands"); + if (list == NULL) { + *cmd = GST_NAVIGATION_COMMAND_INVALID; + } else { + if (nth < gst_value_list_get_size (list)) { + *cmd = (GstNavigationCommand) + g_value_get_enum (gst_value_list_get_value (list, nth)); + } else + *cmd = GST_NAVIGATION_COMMAND_INVALID; + } + + return TRUE; +} + +/** + * gst_navigation_query_new_angles: + * + * Create a new #GstNavigation angles query. When executed, it will + * query the pipeline for the set of currently available angles, which may be + * greater than one in a multiangle video. + * + * Returns: The new query. + * Since: 0.10.23 + */ +GstQuery * +gst_navigation_query_new_angles (void) +{ + GstQuery *query; + GstStructure *structure; + + structure = gst_structure_new (GST_NAVIGATION_QUERY_NAME, + "type", G_TYPE_STRING, "angles", NULL); + query = gst_query_new_application (GST_QUERY_CUSTOM, structure); + + return query; +} + +/** + * gst_navigation_query_set_angles: + * @query: a #GstQuery + * @cur_angle: the current viewing angle to set. + * @n_angles: the number of viewing angles to set. + * + * Set the #GstNavigation angles query result field in @query. + * + * Since: 0.10.23 + */ +void +gst_navigation_query_set_angles (GstQuery * query, guint cur_angle, + guint n_angles) +{ + GstStructure *structure; + + g_return_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES)); + + structure = gst_query_get_structure (query); + gst_structure_set (structure, + "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL); +} + +/** + * gst_navigation_query_parse_angles: + * @query: a #GstQuery + * @cur_angle: Pointer to a #guint into which to store the currently selected + * angle value from the query, or NULL + * @n_angles: Pointer to a #guint into which to store the number of angles + * value from the query, or NULL + * + * Parse the current angle number in the #GstNavigation angles @query into the + * #guint pointed to by the @cur_angle variable, and the number of available + * angles into the #guint pointed to by the @n_angles variable. + * + * Returns: %TRUE if the query could be successfully parsed. %FALSE if not. + * Since: 0.10.23 + */ +gboolean +gst_navigation_query_parse_angles (GstQuery * query, guint * cur_angle, + guint * n_angles) +{ + GstStructure *structure; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_NAVIGATION_QUERY_HAS_TYPE (query, ANGLES), FALSE); + + structure = gst_query_get_structure (query); + + if (cur_angle) + ret &= gst_structure_get_uint (structure, "angle", cur_angle); + + if (n_angles) + ret &= gst_structure_get_uint (structure, "angles", n_angles); + + WARN_IF_FAIL (ret, "Couldn't extract details from angles query"); + + return ret; +} + +/* Navigation Messages */ + +#define GST_NAVIGATION_MESSAGE_HAS_TYPE(msg,msg_type) \ +(gst_navigation_message_get_type (msg) == GST_NAVIGATION_MESSAGE_ ## msg_type) + +/** + * gst_navigation_message_get_type: + * @message: A #GstMessage to inspect. + * + * Check a bus message to see if it is a #GstNavigation event, and return + * the #GstNavigationMessageType identifying the type of the message if so. + * + * Returns: The type of the #GstNavigationMessage, or + * #GST_NAVIGATION_MESSAGE_INVALID if the message is not a #GstNavigation + * notification. + * + * Since: 0.10.23 + */ +GstNavigationMessageType +gst_navigation_message_get_type (GstMessage * message) +{ + const GstStructure *s; + const gchar *m_type; + + if (message == NULL || GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + return GST_NAVIGATION_MESSAGE_INVALID; + + s = gst_message_get_structure (message); + if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_MESSAGE_NAME)) + return GST_NAVIGATION_MESSAGE_INVALID; + + m_type = gst_structure_get_string (s, "type"); + if (m_type == NULL) + return GST_NAVIGATION_MESSAGE_INVALID; + + if (g_str_equal (m_type, "mouse-over")) + return GST_NAVIGATION_MESSAGE_MOUSE_OVER; + else if (g_str_equal (m_type, "commands-changed")) + return GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED; + else if (g_str_equal (m_type, "angles-changed")) + return GST_NAVIGATION_MESSAGE_ANGLES_CHANGED; + + return GST_NAVIGATION_MESSAGE_INVALID; +} + +/** + * gst_navigation_message_new_mouse_over: + * @src: A #GstObject to set as source of the new message. + * @active: %TRUE if the mouse has entered a clickable area of the display. + * %FALSE if it over a non-clickable area. + * + * Creates a new #GstNavigation message with type + * #GST_NAVIGATION_MESSAGE_MOUSE_OVER. + * + * Returns: The new #GstMessage. + * Since: 0.10.23 + */ +GstMessage * +gst_navigation_message_new_mouse_over (GstObject * src, gboolean active) +{ + GstStructure *s; + GstMessage *m; + + s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, + "type", G_TYPE_STRING, "mouse-over", "active", G_TYPE_BOOLEAN, active, + NULL); + + m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); + + return m; +} + +/** + * gst_navigation_message_parse_mouse_over: + * @message: A #GstMessage to inspect. + * @active: A pointer to a gboolean to receive the active/inactive state, + * or NULL. + * + * Parse a #GstNavigation message of type #GST_NAVIGATION_MESSAGE_MOUSE_OVER + * and extract the active/inactive flag. If the mouse over event is marked + * active, it indicates that the mouse is over a clickable area. + * + * Returns: %TRUE if the message could be successfully parsed. %FALSE if not. + * Since: 0.10.23 + */ +gboolean +gst_navigation_message_parse_mouse_over (GstMessage * message, + gboolean * active) +{ + if (!GST_NAVIGATION_MESSAGE_HAS_TYPE (message, MOUSE_OVER)) + return FALSE; + + if (active) { + const GstStructure *s = gst_message_get_structure (message); + if (gst_structure_get_boolean (s, "active", active) == FALSE) + return FALSE; + } + + return TRUE; +} + +/** + * gst_navigation_message_new_commands_changed: + * @src: A #GstObject to set as source of the new message. + * + * Creates a new #GstNavigation message with type + * #GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED + * + * Returns: The new #GstMessage. + * Since: 0.10.23 + */ +GstMessage * +gst_navigation_message_new_commands_changed (GstObject * src) +{ + GstStructure *s; + GstMessage *m; + + s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, + "type", G_TYPE_STRING, "commands-changed", NULL); + + m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); + + return m; +} + +/** + * gst_navigation_message_new_angles_changed: + * @src: A #GstObject to set as source of the new message. + * @cur_angle: The currently selected angle. + * @n_angles: The number of viewing angles now available. + * + * Creates a new #GstNavigation message with type + * #GST_NAVIGATION_MESSAGE_ANGLES_CHANGED for notifying an application + * that the current angle, or current number of angles available in a + * multiangle video has changed. + * + * Returns: The new #GstMessage. + * Since: 0.10.23 + */ +GstMessage * +gst_navigation_message_new_angles_changed (GstObject * src, guint cur_angle, + guint n_angles) +{ + GstStructure *s; + GstMessage *m; + + s = gst_structure_new (GST_NAVIGATION_MESSAGE_NAME, + "type", G_TYPE_STRING, "angles-changed", + "angle", G_TYPE_UINT, cur_angle, "angles", G_TYPE_UINT, n_angles, NULL); + + m = gst_message_new_custom (GST_MESSAGE_ELEMENT, src, s); + + return m; +} + +/** + * gst_navigation_message_parse_angles_changed: + * @message: A #GstMessage to inspect. + * @cur_angle: A pointer to a #guint to receive the new current angle number, + * or NULL + * @n_angles: A pointer to a #guint to receive the new angle count, or NULL. + * + * Parse a #GstNavigation message of type GST_NAVIGATION_MESSAGE_ANGLES_CHANGED + * and extract the @cur_angle and @n_angles parameters. + * + * Returns: %TRUE if the message could be successfully parsed. %FALSE if not. + * Since: 0.10.23 + */ +gboolean +gst_navigation_message_parse_angles_changed (GstMessage * message, + guint * cur_angle, guint * n_angles) +{ + const GstStructure *s; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_NAVIGATION_MESSAGE_HAS_TYPE (message, + ANGLES_CHANGED), FALSE); + + s = gst_message_get_structure (message); + if (cur_angle) + ret &= gst_structure_get_uint (s, "angle", cur_angle); + + if (n_angles) + ret &= gst_structure_get_uint (s, "angles", n_angles); + + WARN_IF_FAIL (ret, "Couldn't extract details from angles-changed event"); + + return ret; +} + +#define GST_NAVIGATION_EVENT_HAS_TYPE(event,event_type) \ +(gst_navigation_event_get_type (event) == GST_NAVIGATION_EVENT_ ## event_type) + +/** + * gst_navigation_event_get_type: + * @event: A #GstEvent to inspect. + * + * Inspect a #GstEvent and return the #GstNavigationEventType of the event, or + * #GST_NAVIGATION_EVENT_INVALID if the event is not a #GstNavigation event. + * + * Since: 0.10.23 + */ +GstNavigationEventType +gst_navigation_event_get_type (GstEvent * event) +{ + const GstStructure *s; + const gchar *e_type; + + if (event == NULL || GST_EVENT_TYPE (event) != GST_EVENT_NAVIGATION) + return GST_NAVIGATION_EVENT_INVALID; + + s = gst_event_get_structure (event); + if (s == NULL || !gst_structure_has_name (s, GST_NAVIGATION_EVENT_NAME)) + return GST_NAVIGATION_EVENT_INVALID; + + e_type = gst_structure_get_string (s, "event"); + if (e_type == NULL) + return GST_NAVIGATION_EVENT_INVALID; + + if (g_str_equal (e_type, "mouse-button-press")) + return GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS; + else if (g_str_equal (e_type, "mouse-button-release")) + return GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE; + else if (g_str_equal (e_type, "mouse-move")) + return GST_NAVIGATION_EVENT_MOUSE_MOVE; + else if (g_str_equal (e_type, "key-press")) + return GST_NAVIGATION_EVENT_KEY_PRESS; + else if (g_str_equal (e_type, "key-release")) + return GST_NAVIGATION_EVENT_KEY_RELEASE; + else if (g_str_equal (e_type, "command")) + return GST_NAVIGATION_EVENT_COMMAND; + + return GST_NAVIGATION_EVENT_INVALID; +} + +/** + * gst_navigation_event_parse_key_event: + * @event: A #GstEvent to inspect. + * @key: A pointer to a location to receive the string identifying the key + * press. The returned string is owned by the event, and valid only until the + * event is unreffed. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_key_event (GstEvent * event, const gchar ** key) +{ + GstNavigationEventType e_type; + const GstStructure *s; + + e_type = gst_navigation_event_get_type (event); + g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_KEY_PRESS || + e_type == GST_NAVIGATION_EVENT_KEY_RELEASE, FALSE); + + if (key) { + s = gst_event_get_structure (event); + *key = gst_structure_get_string (s, "key"); + if (*key == NULL) + return FALSE; + } + + return TRUE; +} + +/** + * gst_navigation_event_parse_mouse_button_event: + * @event: A #GstEvent to inspect. + * @button: Pointer to a gint that will receive the button number associated + * with the event. + * @x: Pointer to a gdouble to receive the x coordinate of the mouse button + * event. + * @y: Pointer to a gdouble to receive the y coordinate of the mouse button + * event. + * + * Retrieve the details of either a #GstNavigation mouse button press event or + * a mouse button release event. Determine which type the event is using + * gst_navigation_event_get_type() to retrieve the #GstNavigationEventType. + * + * Returns: TRUE if the button number and both coordinates could be extracted, + * otherwise FALSE. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_mouse_button_event (GstEvent * event, gint * button, + gdouble * x, gdouble * y) +{ + GstNavigationEventType e_type; + const GstStructure *s; + gboolean ret = TRUE; + + e_type = gst_navigation_event_get_type (event); + g_return_val_if_fail (e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS || + e_type == GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, FALSE); + + s = gst_event_get_structure (event); + if (x) + ret &= gst_structure_get_double (s, "pointer_x", x); + if (y) + ret &= gst_structure_get_double (s, "pointer_y", y); + if (button) + ret &= gst_structure_get_int (s, "button", button); + + WARN_IF_FAIL (ret, "Couldn't extract details from mouse button event"); + + return ret; +} + +/** + * gst_navigation_event_parse_mouse_move_event: + * @event: A #GstEvent to inspect. + * @x: Pointer to a gdouble to receive the x coordinate of the mouse movement. + * @y: Pointer to a gdouble to receive the y coordinate of the mouse movement. + * + * Inspect a #GstNavigation mouse movement event and extract the coordinates + * of the event. + * + * Returns: TRUE if both coordinates could be extracted, otherwise FALSE. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_mouse_move_event (GstEvent * event, gdouble * x, + gdouble * y) +{ + const GstStructure *s; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, MOUSE_MOVE), + FALSE); + + s = gst_event_get_structure (event); + if (x) + ret &= gst_structure_get_double (s, "pointer_x", x); + if (y) + ret &= gst_structure_get_double (s, "pointer_y", y); + + WARN_IF_FAIL (ret, "Couldn't extract positions from mouse move event"); + + return ret; +} + +/** + * gst_navigation_event_parse_command: + * @event: A #GstEvent to inspect. + * @command: Pointer to GstNavigationCommand to receive the type of the + * navigation event. + * + * Inspect a #GstNavigation command event and retrieve the enum value of the + * associated command. + * + * Returns: TRUE if the navigation command could be extracted, otherwise FALSE. + * + * Since: 0.10.23 + */ +gboolean +gst_navigation_event_parse_command (GstEvent * event, + GstNavigationCommand * command) +{ + const GstStructure *s; + gboolean ret = TRUE; + + g_return_val_if_fail (GST_NAVIGATION_EVENT_HAS_TYPE (event, COMMAND), FALSE); + + if (command) { + s = gst_event_get_structure (event); + ret = gst_structure_get_uint (s, "command-code", (guint *) command); + WARN_IF_FAIL (ret, "Couldn't extract command code from command event"); + } + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.h new file mode 100644 index 0000000..cf7f7b9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/navigation.h @@ -0,0 +1,257 @@ +/* GStreamer Navigation + * Copyright (C) 2003 Ronald Bultje + * Copyright (C) 2003 David A. Schleef + * + * navigation.h: navigation interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_NAVIGATION_H__ +#define __GST_NAVIGATION_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_NAVIGATION \ + (gst_navigation_get_type ()) +#define GST_NAVIGATION(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_NAVIGATION, GstNavigation)) +#define GST_IS_NAVIGATION(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_NAVIGATION)) +#define GST_NAVIGATION_GET_IFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_NAVIGATION, GstNavigationInterface)) + +typedef struct _GstNavigation GstNavigation; +typedef struct _GstNavigationInterface GstNavigationInterface; + +struct _GstNavigationInterface { + GTypeInterface g_iface; + + /* virtual functions */ + void (*send_event) (GstNavigation *navigation, GstStructure *structure); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_navigation_get_type (void); + +/* Navigation commands */ + +/** + * GstNavigationCommand: + * @GST_NAVIGATION_COMMAND_INVALID: An invalid command entry + * @GST_NAVIGATION_COMMAND_MENU1: Execute navigation menu command 1. For DVD, + * this enters the DVD root menu, or exits back to the title from the menu. + * @GST_NAVIGATION_COMMAND_MENU2: Execute navigation menu command 2. For DVD, + * this jumps to the DVD title menu. + * @GST_NAVIGATION_COMMAND_MENU3: Execute navigation menu command 3. For DVD, + * this jumps into the DVD root menu. + * @GST_NAVIGATION_COMMAND_MENU4: Execute navigation menu command 4. For DVD, + * this jumps to the Subpicture menu. + * @GST_NAVIGATION_COMMAND_MENU5: Execute navigation menu command 5. For DVD, + * the jumps to the audio menu. + * @GST_NAVIGATION_COMMAND_MENU6: Execute navigation menu command 6. For DVD, + * this jumps to the angles menu. + * @GST_NAVIGATION_COMMAND_MENU7: Execute navigation menu command 7. For DVD, + * this jumps to the chapter menu. + * @GST_NAVIGATION_COMMAND_LEFT: Select the next button to the left in a menu, + * if such a button exists. + * @GST_NAVIGATION_COMMAND_RIGHT: Select the next button to the right in a menu, + * if such a button exists. + * @GST_NAVIGATION_COMMAND_UP: Select the button above the current one in a + * menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_DOWN: Select the button below the current one in a + * menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_ACTIVATE: Activate (click) the currently selected + * button in a menu, if such a button exists. + * @GST_NAVIGATION_COMMAND_PREV_ANGLE: Switch to the previous angle in a + * multiangle feature. + * @GST_NAVIGATION_COMMAND_NEXT_ANGLE: Switch to the next angle in a multiangle + * feature. + * + * A set of commands that may be issued to an element providing the + * #GstNavigation interface. The available commands can be queried via + * the gst_navigation_query_new_commands() query. + * + * For convenience in handling DVD navigation, the MENU commands are aliased as: + * GST_NAVIGATION_COMMAND_DVD_MENU = @GST_NAVIGATION_COMMAND_MENU1 + * GST_NAVIGATION_COMMAND_DVD_TITLE_MENU = @GST_NAVIGATION_COMMAND_MENU2 + * GST_NAVIGATION_COMMAND_DVD_ROOT_MENU = @GST_NAVIGATION_COMMAND_MENU3 + * GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU = @GST_NAVIGATION_COMMAND_MENU4 + * GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU = @GST_NAVIGATION_COMMAND_MENU5 + * GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU = @GST_NAVIGATION_COMMAND_MENU6 + * GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU = @GST_NAVIGATION_COMMAND_MENU7 + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_COMMAND_INVALID = 0, + + GST_NAVIGATION_COMMAND_MENU1 = 1, + GST_NAVIGATION_COMMAND_MENU2 = 2, + GST_NAVIGATION_COMMAND_MENU3 = 3, + GST_NAVIGATION_COMMAND_MENU4 = 4, + GST_NAVIGATION_COMMAND_MENU5 = 5, + GST_NAVIGATION_COMMAND_MENU6 = 6, + GST_NAVIGATION_COMMAND_MENU7 = 7, + + GST_NAVIGATION_COMMAND_LEFT = 20, + GST_NAVIGATION_COMMAND_RIGHT = 21, + GST_NAVIGATION_COMMAND_UP = 22, + GST_NAVIGATION_COMMAND_DOWN = 23, + GST_NAVIGATION_COMMAND_ACTIVATE = 24, + + GST_NAVIGATION_COMMAND_PREV_ANGLE = 30, + GST_NAVIGATION_COMMAND_NEXT_ANGLE = 31 +} GstNavigationCommand; + +/* Some aliases for the menu command types */ +#define GST_NAVIGATION_COMMAND_DVD_MENU GST_NAVIGATION_COMMAND_MENU1 +#define GST_NAVIGATION_COMMAND_DVD_TITLE_MENU GST_NAVIGATION_COMMAND_MENU2 +#define GST_NAVIGATION_COMMAND_DVD_ROOT_MENU GST_NAVIGATION_COMMAND_MENU3 +#define GST_NAVIGATION_COMMAND_DVD_SUBPICTURE_MENU GST_NAVIGATION_COMMAND_MENU4 +#define GST_NAVIGATION_COMMAND_DVD_AUDIO_MENU GST_NAVIGATION_COMMAND_MENU5 +#define GST_NAVIGATION_COMMAND_DVD_ANGLE_MENU GST_NAVIGATION_COMMAND_MENU6 +#define GST_NAVIGATION_COMMAND_DVD_CHAPTER_MENU GST_NAVIGATION_COMMAND_MENU7 + +/* Queries */ +typedef enum +{ + GST_NAVIGATION_QUERY_INVALID = 0, + GST_NAVIGATION_QUERY_COMMANDS = 1, + GST_NAVIGATION_QUERY_ANGLES = 2 +} GstNavigationQueryType; + +GstNavigationQueryType gst_navigation_query_get_type (GstQuery *query); + +GstQuery *gst_navigation_query_new_commands (void); +void gst_navigation_query_set_commands (GstQuery *query, gint n_cmds, ...); +void gst_navigation_query_set_commandsv (GstQuery *query, gint n_cmds, + GstNavigationCommand *cmds); +gboolean gst_navigation_query_parse_commands_length (GstQuery *query, + guint *n_cmds); +gboolean gst_navigation_query_parse_commands_nth (GstQuery *query, guint nth, + GstNavigationCommand *cmd); + +GstQuery *gst_navigation_query_new_angles (void); +void gst_navigation_query_set_angles (GstQuery *query, guint cur_angle, + guint n_angles); +gboolean gst_navigation_query_parse_angles (GstQuery *query, guint *cur_angle, + guint *n_angles); + +/* Element messages */ +/** + * GstNavigationMessageType: + * @GST_NAVIGATION_MESSAGE_INVALID: Returned from + * gst_navigation_message_get_type() when the passed message is not a + * navigation message. + * @GST_NAVIGATION_MESSAGE_MOUSE_OVER: Sent when the mouse moves over or leaves a + * clickable region of the output, such as a DVD menu button. + * @GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED: Sent when the set of available commands + * changes and should re-queried by interested applications. + * @GST_NAVIGATION_MESSAGE_ANGLES_CHANGED: Sent when display angles in a multi-angle + * feature (such as a multiangle DVD) change - either angles have appeared or + * disappeared. + * + * A set of notifications that may be received on the bus when navigation + * related status changes. + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_MESSAGE_INVALID, + GST_NAVIGATION_MESSAGE_MOUSE_OVER, + GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED, + GST_NAVIGATION_MESSAGE_ANGLES_CHANGED +} GstNavigationMessageType; + +GstNavigationMessageType gst_navigation_message_get_type (GstMessage *message); + +GstMessage *gst_navigation_message_new_mouse_over (GstObject *src, + gboolean active); +gboolean gst_navigation_message_parse_mouse_over (GstMessage *message, + gboolean *active); + +GstMessage *gst_navigation_message_new_commands_changed (GstObject *src); + +GstMessage *gst_navigation_message_new_angles_changed (GstObject *src, + guint cur_angle, + guint n_angles); +gboolean gst_navigation_message_parse_angles_changed (GstMessage *message, + guint *cur_angle, + guint *n_angles); + +/* event parsing functions */ +/** + * GstNavigationEventType: + * @GST_NAVIGATION_EVENT_INVALID: Returned from + * gst_navigation_event_get_type() when the passed event is not a navigation event. + * @GST_NAVIGATION_EVENT_KEY_PRESS: A key press event. Use + * gst_navigation_event_parse_key_event() to extract the details from the event. + * @GST_NAVIGATION_EVENT_KEY_RELEASE: A key release event. Use + * gst_navigation_event_parse_key_event() to extract the details from the event. + * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: A mouse button press event. Use + * gst_navigation_event_parse_mouse_button_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE: A mouse button release event. Use + * gst_navigation_event_parse_mouse_button_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_MOUSE_MOVE: A mouse movement event. Use + * gst_navigation_event_parse_mouse_move_event() to extract the details from the + * event. + * @GST_NAVIGATION_EVENT_COMMAND: A navigation command event. Use + * gst_navigation_event_parse_command() to extract the details from the event. + * + * Enum values for the various events that an element implementing the + * GstNavigation interface might send up the pipeline. + * + * Since: 0.10.23 + */ +typedef enum { + GST_NAVIGATION_EVENT_INVALID = 0, + GST_NAVIGATION_EVENT_KEY_PRESS = 1, + GST_NAVIGATION_EVENT_KEY_RELEASE = 2, + GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS = 3, + GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE = 4, + GST_NAVIGATION_EVENT_MOUSE_MOVE = 5, + GST_NAVIGATION_EVENT_COMMAND = 6 +} GstNavigationEventType; + +GstNavigationEventType gst_navigation_event_get_type (GstEvent *event); +gboolean gst_navigation_event_parse_key_event (GstEvent *event, + const gchar **key); +gboolean gst_navigation_event_parse_mouse_button_event (GstEvent *event, + gint *button, gdouble *x, gdouble *y); +gboolean gst_navigation_event_parse_mouse_move_event (GstEvent *event, + gdouble *x, gdouble *y); +gboolean gst_navigation_event_parse_command (GstEvent *event, + GstNavigationCommand *command); + +/* interface virtual function wrappers */ +void gst_navigation_send_event (GstNavigation *navigation, + GstStructure *structure); +void gst_navigation_send_key_event (GstNavigation *navigation, + const char *event, const char *key); +void gst_navigation_send_mouse_event (GstNavigation *navigation, + const char *event, int button, double x, double y); +void gst_navigation_send_command (GstNavigation *navigation, + GstNavigationCommand command); + +G_END_DECLS + +#endif /* __GST_NAVIGATION_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.c new file mode 100644 index 0000000..64d0d39 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.c @@ -0,0 +1,378 @@ +/* GStreamer PropertyProbe + * Copyright (C) 2003 David Schleef + * + * property_probe.c: property_probe design virtual class function wrappers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpropertyprobe + * @short_description: Interface for probing possible property values + * + * The property probe is a way to autodetect allowed values for a GObject + * property. It's primary use is to autodetect device-names in several elements. + * + * The interface is implemented by many hardware sources and sinks. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "propertyprobe.h" + +enum +{ + SIGNAL_PROBE_NEEDED, + LAST_SIGNAL +}; + +static void gst_property_probe_iface_init (GstPropertyProbeInterface * iface); + +static guint gst_property_probe_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_property_probe_get_type (void) +{ + static GType gst_property_probe_type = 0; + + if (!gst_property_probe_type) { + static const GTypeInfo gst_property_probe_info = { + sizeof (GstPropertyProbeInterface), + (GBaseInitFunc) gst_property_probe_iface_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_property_probe_type = + g_type_register_static (G_TYPE_INTERFACE, + "GstPropertyProbe", &gst_property_probe_info, 0); + } + + return gst_property_probe_type; +} + +static void +gst_property_probe_iface_init (GstPropertyProbeInterface * iface) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /** + * GstPropertyProbe::probe-needed + * @pspec: #GParamSpec that needs a probe + * + */ + /* FIXME: + * what is the purpose of this signal, I can't find any usage of it + * according to proto n *.h, it should be g_cclosure_marshal_VOID__PARAM + */ + gst_property_probe_signals[SIGNAL_PROBE_NEEDED] = + g_signal_new ("probe-needed", G_TYPE_FROM_CLASS (iface), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPropertyProbeInterface, + probe_needed), NULL, NULL, g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER); + initialized = TRUE; + } + + /* default virtual functions */ + iface->get_properties = NULL; + iface->get_values = NULL; +} + +/** + * gst_property_probe_get_properties: + * @probe: the #GstPropertyProbe to get the properties for. + * + * Get a list of properties for which probing is supported. + * + * Returns: the list of properties for which probing is supported + * by this element. + */ +const GList * +gst_property_probe_get_properties (GstPropertyProbe * probe) +{ + GstPropertyProbeInterface *iface; + + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + + iface = GST_PROPERTY_PROBE_GET_IFACE (probe); + + if (iface->get_properties) + return iface->get_properties (probe); + + return NULL; +} + +/** + * gst_property_probe_get_property: + * @probe: the #GstPropertyProbe to get the properties for. + * @name: name of the property. + * + * Get #GParamSpec for a property for which probing is supported. + * + * Returns: the #GParamSpec of %NULL. + */ +const GParamSpec * +gst_property_probe_get_property (GstPropertyProbe * probe, const gchar * name) +{ + const GList *pspecs; + + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + g_return_val_if_fail (name != NULL, NULL); + + pspecs = gst_property_probe_get_properties (probe); + + while (pspecs) { + const GParamSpec *pspec = pspecs->data; + + if (pspec) { + if (!strcmp (pspec->name, name)) + return pspec; + } else { + GST_WARNING_OBJECT (probe, "NULL paramspec in property probe list"); + } + + pspecs = pspecs->next; + } + + return NULL; +} + +/** + * gst_property_probe_probe_property: + * @probe: the #GstPropertyProbe to check. + * @pspec: #GParamSpec of the property. + * + * Runs a probe on the property specified by @pspec + */ +void +gst_property_probe_probe_property (GstPropertyProbe * probe, + const GParamSpec * pspec) +{ + GstPropertyProbeInterface *iface; + + g_return_if_fail (probe != NULL); + g_return_if_fail (GST_IS_PROPERTY_PROBE (probe)); + g_return_if_fail (pspec != NULL); + + iface = GST_PROPERTY_PROBE_GET_IFACE (probe); + + if (iface->probe_property) + iface->probe_property (probe, pspec->param_id, pspec); +} + +/** + * gst_property_probe_probe_property_name: + * @probe: the #GstPropertyProbe to check. + * @name: name of the property. + * + * Runs a probe on the property specified by @name. + */ +void +gst_property_probe_probe_property_name (GstPropertyProbe * probe, + const gchar * name) +{ + const GParamSpec *pspec; + + g_return_if_fail (probe != NULL); + g_return_if_fail (GST_IS_PROPERTY_PROBE (probe)); + g_return_if_fail (name != NULL); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name); + if (!pspec) { + g_warning ("No such property %s", name); + return; + } + + gst_property_probe_probe_property (probe, pspec); +} + +/** + * gst_property_probe_needs_probe: + * @probe: the #GstPropertyProbe object to which the given property belongs. + * @pspec: a #GParamSpec that identifies the property to check. + * + * Checks whether a property needs a probe. This might be because + * the property wasn't initialized before, or because host setup + * changed. This might be, for example, because a new device was + * added, and thus device probing needs to be refreshed to display + * the new device. + * + * Returns: TRUE if the property needs a new probe, FALSE if not. + */ +gboolean +gst_property_probe_needs_probe (GstPropertyProbe * probe, + const GParamSpec * pspec) +{ + GstPropertyProbeInterface *iface; + + g_return_val_if_fail (probe != NULL, FALSE); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), FALSE); + g_return_val_if_fail (pspec != NULL, FALSE); + + iface = GST_PROPERTY_PROBE_GET_IFACE (probe); + + if (iface->needs_probe) + return iface->needs_probe (probe, pspec->param_id, pspec); + + return FALSE; +} + +/** + * gst_property_probe_needs_probe_name: + * @probe: the #GstPropertyProbe object to which the given property belongs. + * @name: the name of the property to check. + * + * Same as gst_property_probe_needs_probe (). + * + * Returns: TRUE if the property needs a new probe, FALSE if not. + */ +gboolean +gst_property_probe_needs_probe_name (GstPropertyProbe * probe, + const gchar * name) +{ + const GParamSpec *pspec; + + g_return_val_if_fail (probe != NULL, FALSE); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name); + if (!pspec) { + g_warning ("No such property %s", name); + return FALSE; + } + + return gst_property_probe_needs_probe (probe, pspec); +} + +/** + * gst_property_probe_get_values: + * @probe: the #GstPropertyProbe object. + * @pspec: the #GParamSpec property identifier. + * + * Gets the possible (probed) values for the given property, + * requires the property to have been probed before. + * + * Returns: A list of valid values for the given property. + */ +GValueArray * +gst_property_probe_get_values (GstPropertyProbe * probe, + const GParamSpec * pspec) +{ + GstPropertyProbeInterface *iface; + + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + g_return_val_if_fail (pspec != NULL, NULL); + + iface = GST_PROPERTY_PROBE_GET_IFACE (probe); + + if (iface->get_values) + return iface->get_values (probe, pspec->param_id, pspec); + + return NULL; +} + +/** + * gst_property_probe_get_values_name: + * @probe: the #GstPropertyProbe object. + * @name: the name of the property to get values for. + * + * Same as gst_property_probe_get_values (). + * + * Returns: A list of valid values for the given property. + */ +GValueArray * +gst_property_probe_get_values_name (GstPropertyProbe * probe, + const gchar * name) +{ + const GParamSpec *pspec; + + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + g_return_val_if_fail (name != NULL, NULL); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name); + if (!pspec) { + g_warning ("No such property %s", name); + return NULL; + } + + return gst_property_probe_get_values (probe, pspec); +} + +/** + * gst_property_probe_probe_and_get_values: + * @probe: the #GstPropertyProbe object. + * @pspec: The #GParamSpec property identifier. + * + * Check whether the given property requires a new probe. If so, + * fo the probe. After that, retrieve a value list. Meant as a + * utility function that wraps the above functions. + * + * Returns: the list of valid values for this property. + */ +GValueArray * +gst_property_probe_probe_and_get_values (GstPropertyProbe * probe, + const GParamSpec * pspec) +{ + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + g_return_val_if_fail (pspec != NULL, NULL); + + if (gst_property_probe_needs_probe (probe, pspec)) + gst_property_probe_probe_property (probe, pspec); + + return gst_property_probe_get_values (probe, pspec); +} + +/** + * gst_property_probe_probe_and_get_values_name: + * @probe: the #GstPropertyProbe object. + * @name: the name of the property to get values for. + * + * Same as gst_property_probe_probe_and_get_values (). + * + * Returns: the list of valid values for this property. + */ +GValueArray * +gst_property_probe_probe_and_get_values_name (GstPropertyProbe * probe, + const gchar * name) +{ + const GParamSpec *pspec; + + g_return_val_if_fail (probe != NULL, NULL); + g_return_val_if_fail (GST_IS_PROPERTY_PROBE (probe), NULL); + g_return_val_if_fail (name != NULL, NULL); + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (probe), name); + if (!pspec) { + g_warning ("No such property %s", name); + return NULL; + } + + return gst_property_probe_probe_and_get_values (probe, pspec); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.h new file mode 100644 index 0000000..5b67af2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/propertyprobe.h @@ -0,0 +1,115 @@ +/* GStreamer PropertyProbe + * Copyright (C) 2003 David A. Schleef + * + * property_probe.h: property_probe interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PROPERTY_PROBE_H__ +#define __GST_PROPERTY_PROBE_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_PROPERTY_PROBE \ + (gst_property_probe_get_type ()) +#define GST_PROPERTY_PROBE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PROPERTY_PROBE, GstPropertyProbe)) +#define GST_IS_PROPERTY_PROBE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PROPERTY_PROBE)) +#define GST_PROPERTY_PROBE_GET_IFACE(obj) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GST_TYPE_PROPERTY_PROBE, GstPropertyProbeInterface)) + +/** + * GstPropertyProbe: + * + * Opaque #GstPropertyProbe data structure. + */ +typedef struct _GstPropertyProbe GstPropertyProbe; /* dummy typedef */ +typedef struct _GstPropertyProbeInterface GstPropertyProbeInterface; + +/** + * GstPropertyProbeInterface: + * @klass: parent interface type. + * @probe_needed: default signal handler + * @get_properties: virtual method to get list of probable properties + * @needs_probe: virtual method to tell if probe need update + * @probe_property: virtual method to probe a property + * @get_values: virtual method to get probe results for a property + * + * #GstPropertyProbe interface. + */ +struct _GstPropertyProbeInterface { + GTypeInterface klass; + + /* signals */ + void (*probe_needed) (GstPropertyProbe *probe, + const GParamSpec *pspec); + + /* virtual functions */ + const GList * (*get_properties) (GstPropertyProbe *probe); + gboolean (*needs_probe) (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec); + void (*probe_property) (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec); + GValueArray * (*get_values) (GstPropertyProbe *probe, + guint prop_id, + const GParamSpec *pspec); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_property_probe_get_type (void); + +/* virtual class function wrappers */ + +/* returns list of GParamSpecs */ +const GList * gst_property_probe_get_properties (GstPropertyProbe *probe); +const GParamSpec *gst_property_probe_get_property (GstPropertyProbe *probe, + const gchar *name); + +/* probe one property */ +void gst_property_probe_probe_property (GstPropertyProbe *probe, + const GParamSpec *pspec); +void gst_property_probe_probe_property_name (GstPropertyProbe *probe, + const gchar *name); + +/* do we need a probe? */ +gboolean gst_property_probe_needs_probe (GstPropertyProbe *probe, + const GParamSpec *pspec); +gboolean gst_property_probe_needs_probe_name (GstPropertyProbe *probe, + const gchar *name); + +/* returns list of GValues */ +GValueArray * gst_property_probe_get_values (GstPropertyProbe *probe, + const GParamSpec *pspec); +GValueArray * gst_property_probe_get_values_name (GstPropertyProbe *probe, + const gchar *name); + +/* sugar */ +GValueArray * gst_property_probe_probe_and_get_values (GstPropertyProbe *probe, + const GParamSpec *pspec); +GValueArray * gst_property_probe_probe_and_get_values_name (GstPropertyProbe *probe, + const gchar *name); + +G_END_DECLS + +#endif /* __GST_PROPERTY_PROBE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.c new file mode 100644 index 0000000..509d295 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.c @@ -0,0 +1,225 @@ +/* GStreamer Mixer + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gststreamvolume + * @short_description: Interface for elements that provide a stream volume + * + * + * + * This interface is implemented by elements that provide a stream volume. Examples for + * such elements are #volume and #playbin2. + * + * + * Applications can use this interface to get or set the current stream volume. For this + * the "volume" #GObject property can be used or the helper functions gst_stream_volume_set_volume() + * and gst_stream_volume_get_volume(). This volume is always a linear factor, i.e. 0.0 is muted + * 1.0 is 100%. For showing the volume in a GUI it might make sense to convert it to + * a different format by using gst_stream_volume_convert_volume(). Volume sliders should usually + * use a cubic volume. + * + * Separate from the volume the stream can also be muted by the "mute" #GObject property or + * gst_stream_volume_set_mute() and gst_stream_volume_get_mute(). + * + * + * Elements that provide some kind of stream volume should implement the "volume" and + * "mute" #GObject properties and handle setting and getting of them properly. + * The volume property is defined to be a linear volume factor. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "streamvolume.h" +#include + +static void +gst_stream_volume_class_init (GstStreamVolumeInterface * iface) +{ + g_object_interface_install_property (iface, + g_param_spec_double ("volume", + "Volume", + "Linear volume factor, 1.0=100%", + 0.0, G_MAXDOUBLE, 1.0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_interface_install_property (iface, + g_param_spec_boolean ("mute", + "Mute", + "Mute the audio channel without changing the volume", + FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +GType +gst_stream_volume_get_type (void) +{ + static volatile gsize type = 0; + if (g_once_init_enter (&type)) { + GType tmp; + static const GTypeInfo info = { + sizeof (GstStreamVolumeInterface), + NULL, /* base_init */ + NULL, /* base_finalize */ + (GClassInitFunc) gst_stream_volume_class_init, /* class_init */ + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, /* n_preallocs */ + NULL /* instance_init */ + }; + tmp = g_type_register_static (G_TYPE_INTERFACE, + "GstStreamVolume", &info, 0); + g_type_interface_add_prerequisite (tmp, G_TYPE_OBJECT); + + g_once_init_leave (&type, tmp); + } + return type; +} + +/** + * gst_stream_volume_get_volume: + * @volume: #GstStreamVolume that should be used + * @format: #GstStreamVolumeFormat which should be returned + * + * Returns: The current stream volume as linear factor + * + * Since: 0.10.25 + */ +gdouble +gst_stream_volume_get_volume (GstStreamVolume * volume, + GstStreamVolumeFormat format) +{ + gdouble val; + + g_return_val_if_fail (GST_IS_STREAM_VOLUME (volume), 1.0); + + g_object_get (volume, "volume", &val, NULL); + if (format != GST_STREAM_VOLUME_FORMAT_LINEAR) + val = + gst_stream_volume_convert_volume (GST_STREAM_VOLUME_FORMAT_LINEAR, + format, val); + return val; +} + +/** + * gst_stream_volume_set_volume: + * @volume: #GstStreamVolume that should be used + * @format: #GstStreamVolumeFormat of @val + * @val: Linear volume factor that should be set + * + * Since: 0.10.25 + */ +void +gst_stream_volume_set_volume (GstStreamVolume * volume, + GstStreamVolumeFormat format, gdouble val) +{ + g_return_if_fail (GST_IS_STREAM_VOLUME (volume)); + + if (format != GST_STREAM_VOLUME_FORMAT_LINEAR) + val = + gst_stream_volume_convert_volume (format, + GST_STREAM_VOLUME_FORMAT_LINEAR, val); + g_object_set (volume, "volume", val, NULL); +} + +/** + * gst_stream_volume_get_mute: + * @volume: #GstStreamVolume that should be used + * + * Returns: Returns %TRUE if the stream is muted + * + * Since: 0.10.25 + */ +gboolean +gst_stream_volume_get_mute (GstStreamVolume * volume) +{ + gboolean val; + + g_return_val_if_fail (GST_IS_STREAM_VOLUME (volume), FALSE); + + g_object_get (volume, "mute", &val, NULL); + return val; +} + +/** + * gst_stream_volume_set_mute: + * @volume: #GstStreamVolume that should be used + * @mute: Mute state that should be set + * + * Since: 0.10.25 + */ +void +gst_stream_volume_set_mute (GstStreamVolume * volume, gboolean mute) +{ + g_return_if_fail (GST_IS_STREAM_VOLUME (volume)); + + g_object_set (volume, "mute", mute, NULL); +} + +/** + * gst_stream_volume_convert_volume: + * @from: #GstStreamVolumeFormat to convert from + * @to: #GstStreamVolumeFormat to convert to + * @val: Volume in @from format that should be converted + * + * Returns: the converted volume + * + * Since: 0.10.25 + */ +gdouble +gst_stream_volume_convert_volume (GstStreamVolumeFormat from, + GstStreamVolumeFormat to, gdouble val) +{ + switch (from) { + case GST_STREAM_VOLUME_FORMAT_LINEAR: + g_return_val_if_fail (val >= 0.0, 0.0); + switch (to) { + case GST_STREAM_VOLUME_FORMAT_LINEAR: + return val; + case GST_STREAM_VOLUME_FORMAT_CUBIC: + return pow (val, 1 / 3.0); + case GST_STREAM_VOLUME_FORMAT_DB: + return 20.0 * log10 (val); + } + break; + case GST_STREAM_VOLUME_FORMAT_CUBIC: + g_return_val_if_fail (val >= 0.0, 0.0); + switch (to) { + case GST_STREAM_VOLUME_FORMAT_LINEAR: + return val * val * val; + case GST_STREAM_VOLUME_FORMAT_CUBIC: + return val; + case GST_STREAM_VOLUME_FORMAT_DB: + return 3.0 * 20.0 * log10 (val); + } + break; + case GST_STREAM_VOLUME_FORMAT_DB: + switch (to) { + case GST_STREAM_VOLUME_FORMAT_LINEAR: + return pow (10.0, val / 20.0); + case GST_STREAM_VOLUME_FORMAT_CUBIC: + return pow (10.0, val / (3.0 * 20.0)); + case GST_STREAM_VOLUME_FORMAT_DB: + return val; + } + break; + } + g_return_val_if_reached (0.0); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.h new file mode 100644 index 0000000..32a824c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/streamvolume.h @@ -0,0 +1,87 @@ +/* GStreamer StreamVolume + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAM_VOLUME_H__ +#define __GST_STREAM_VOLUME_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_VOLUME \ + (gst_stream_volume_get_type ()) +#define GST_STREAM_VOLUME(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAM_VOLUME, GstStreamVolume)) +#define GST_STREAM_VOLUME_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_CAST ((iface), GST_TYPE_STREAM_VOLUME, GstStreamVolumeInterface)) +#define GST_IS_STREAM_VOLUME(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAM_VOLUME)) +#define GST_IS_STREAM_VOLUME_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_TYPE ((iface), GST_TYPE_STREAM_VOLUME)) +#define GST_STREAM_VOLUME_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_STREAM_VOLUME, GstStreamVolumeInterface)) + +typedef struct _GstStreamVolume GstStreamVolume; +typedef struct _GstStreamVolumeInterface GstStreamVolumeInterface; + +struct _GstStreamVolumeInterface { + GTypeInterface parent; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstStreamVolumeFormat: + * @GST_STREAM_VOLUME_FORMAT_LINEAR: Linear scale factor, 1.0 = 100% + * @GST_STREAM_VOLUME_FORMAT_CUBIC: Cubic volume scale + * @GST_STREAM_VOLUME_FORMAT_DB: Logarithmic volume scale (dB, amplitude not power) + * + * Different representations of a stream volume. gst_stream_volume_convert() + * allows to convert between the different representations. + * + * Formulas to convert from a linear to a cubic or dB volume are + * cbrt(val) and 20 * log10 (val). + * + * Since: 0.10.25 + */ +typedef enum { + GST_STREAM_VOLUME_FORMAT_LINEAR = 0, + GST_STREAM_VOLUME_FORMAT_CUBIC, + GST_STREAM_VOLUME_FORMAT_DB +} GstStreamVolumeFormat; + +GType gst_stream_volume_get_type (void); +void gst_stream_volume_set_volume (GstStreamVolume *volume, + GstStreamVolumeFormat format, + gdouble val); +gdouble gst_stream_volume_get_volume (GstStreamVolume *volume, + GstStreamVolumeFormat format); + +void gst_stream_volume_set_mute (GstStreamVolume *volume, + gboolean mute); +gboolean gst_stream_volume_get_mute (GstStreamVolume *volume); + +gdouble gst_stream_volume_convert_volume (GstStreamVolumeFormat from, + GstStreamVolumeFormat to, + gdouble val) G_GNUC_CONST; + +G_END_DECLS + +#endif /* __GST_STREAM_VOLUME_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.c new file mode 100644 index 0000000..2684517 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.c @@ -0,0 +1,574 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tuner.c: tuner design virtual class function wrappers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "tuner.h" +#include "interfaces-marshal.h" + +#include + +/** + * SECTION:gsttuner + * @short_description: Interface for elements providing tuner operations + * + * + * + * The GstTuner interface is provided by elements that have the ability to + * tune into multiple input signals, for example TV or radio capture cards. + * + * The interpretation of 'tuning into' an input stream depends on the element + * implementing the interface. For v4lsrc, it might imply selection of an + * input source and/or frequency to be configured on a TV card. Another + * GstTuner implementation might be to allow selection of an active input pad + * from multiple input pads. + * + * That said, the GstTuner interface functions are biased toward the + * TV capture scenario. + * + * The general parameters provided are for configuration are: + * + * Selection of a current #GstTunerChannel. The current channel + * represents the input source (e.g. Composite, S-Video etc for TV capture). + * + * The #GstTunerNorm for the channel. The norm chooses the + * interpretation of the incoming signal for the current channel. For example, + * PAL or NTSC, or more specific variants there-of. + * + * Channel frequency. If the current channel has the ability to tune + * between multiple frequencies (if it has the GST_TUNER_CHANNEL_FREQUENCY flag) + * then the frequency can be changed/retrieved via the + * gst_tuner_set_frequency() and gst_tuner_get_frequency() methods. + * + * + * + * + * Where applicable, the signal strength can be retrieved and/or monitored + * via a signal. + * + * + */ + +enum +{ + NORM_CHANGED, + CHANNEL_CHANGED, + FREQUENCY_CHANGED, + SIGNAL_CHANGED, + LAST_SIGNAL +}; + +static void gst_tuner_class_init (GstTunerClass * klass); + +static guint gst_tuner_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_tuner_get_type (void) +{ + static GType gst_tuner_type = 0; + + if (!gst_tuner_type) { + static const GTypeInfo gst_tuner_info = { + sizeof (GstTunerClass), + (GBaseInitFunc) gst_tuner_class_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_tuner_type = g_type_register_static (G_TYPE_INTERFACE, + "GstTuner", &gst_tuner_info, 0); + g_type_interface_add_prerequisite (gst_tuner_type, + GST_TYPE_IMPLEMENTS_INTERFACE); + } + + return gst_tuner_type; +} + +static void +gst_tuner_class_init (GstTunerClass * klass) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + /** + * GstTuner::norm-changed: + * @tuner: The element providing the GstTuner interface + * @norm: The new configured norm. + * + * Reports that the current #GstTunerNorm has changed. + */ + gst_tuner_signals[NORM_CHANGED] = + g_signal_new ("norm-changed", + GST_TYPE_TUNER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerClass, norm_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_TUNER_NORM); + /** + * GstTuner::channel-changed: + * @tuner: The element providing the GstTuner interface + * @channel: The new configured channel. + * + * Reports that the current #GstTunerChannel has changed. + */ + gst_tuner_signals[CHANNEL_CHANGED] = + g_signal_new ("channel-changed", + GST_TYPE_TUNER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerClass, channel_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, G_TYPE_NONE, 1, + GST_TYPE_TUNER_CHANNEL); + /** + * GstTuner::frequency-changed: + * @tuner: The element providing the GstTuner interface + * @frequency: The new frequency (an unsigned long) + * + * Reports that the current frequency has changed. + */ + gst_tuner_signals[FREQUENCY_CHANGED] = + g_signal_new ("frequency-changed", + GST_TYPE_TUNER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerClass, frequency_changed), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_ULONG, G_TYPE_NONE, 2, + GST_TYPE_TUNER_CHANNEL, G_TYPE_ULONG); + /** + * GstTuner::signal-changed: + * @tuner: The element providing the GstTuner interface + * @channel: The current #GstTunerChannel + * @signal: The new signal strength (an integer) + * + * Reports that the signal strength has changed. + * + * See Also: gst_tuner_signal_strength() + */ + gst_tuner_signals[SIGNAL_CHANGED] = + g_signal_new ("signal-changed", + GST_TYPE_TUNER, G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerClass, signal_changed), + NULL, NULL, + gst_interfaces_marshal_VOID__OBJECT_INT, G_TYPE_NONE, 2, + GST_TYPE_TUNER_CHANNEL, G_TYPE_INT); + + initialized = TRUE; + } + + /* default virtual functions */ + klass->list_channels = NULL; + klass->set_channel = NULL; + klass->get_channel = NULL; + + klass->list_norms = NULL; + klass->set_norm = NULL; + klass->get_norm = NULL; + + klass->set_frequency = NULL; + klass->get_frequency = NULL; + klass->signal_strength = NULL; +} + +/** + * gst_tuner_list_channels: + * @tuner: the #GstTuner (a #GstElement) to get the channels from. + * + * Retrieve a #GList of #GstTunerChannels available + * (e.g. 'composite', 's-video', ...) from the given tuner object. + * + * Returns: A list of channels available on this tuner. The list is + * owned by the GstTuner and must not be freed. + */ +const GList * +gst_tuner_list_channels (GstTuner * tuner) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->list_channels) { + return klass->list_channels (tuner); + } + + return NULL; +} + +/** + * gst_tuner_set_channel: + * @tuner: the #GstTuner (a #GstElement) that owns the channel. + * @channel: the channel to tune to. + * + * Tunes the object to the given channel, which should be one of the + * channels returned by gst_tuner_list_channels(). + */ + +void +gst_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel) +{ + GstTunerClass *klass; + + g_return_if_fail (GST_IS_TUNER (tuner)); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->set_channel) { + klass->set_channel (tuner, channel); + } +} + +/** + * gst_tuner_get_channel: + * @tuner: the #GstTuner (a #GstElement) to get the current channel from. + * + * Retrieve the current channel from the tuner. + * + * Returns: the current channel of the tuner object. + */ + +GstTunerChannel * +gst_tuner_get_channel (GstTuner * tuner) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->get_channel) { + return klass->get_channel (tuner); + } + + return NULL; +} + +/** + * gst_tuner_list_norms: + * @tuner: the #GstTuner (*a #GstElement) to get the list of norms from. + * + * Retrieve a GList of available #GstTunerNorm settings for the currently + * tuned channel on the given tuner object. + * + * Returns: A list of norms available on the current channel for this + * tuner object. The list is owned by the GstTuner and must not + * be freed. + */ + +const GList * +gst_tuner_list_norms (GstTuner * tuner) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->list_norms) { + return klass->list_norms (tuner); + } + + return NULL; +} + +/** + * gst_tuner_set_norm: + * @tuner: the #GstTuner (a #GstElement) to set the norm on. + * @norm: the norm to use for the current channel. + * + * Changes the video norm on this tuner to the given norm, which should be + * one of the norms returned by gst_tuner_list_norms(). + */ + +void +gst_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm) +{ + GstTunerClass *klass; + + g_return_if_fail (GST_IS_TUNER (tuner)); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->set_norm) { + klass->set_norm (tuner, norm); + } +} + +/** + * gst_tuner_get_norm: + * @tuner: the #GstTuner (a #GstElement) to get the current norm from. + * + * Get the current video norm from the given tuner object for the + * currently selected channel. + * + * Returns: the current norm. + */ + +GstTunerNorm * +gst_tuner_get_norm (GstTuner * tuner) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->get_norm) { + return klass->get_norm (tuner); + } + + return NULL; +} + +/** + * gst_tuner_set_frequency: + * @tuner: The #GstTuner (a #GstElement) that owns the given channel. + * @channel: The #GstTunerChannel to set the frequency on. + * @frequency: The frequency to tune in to. + * + * Sets a tuning frequency on the given tuner/channel. Note that this + * requires the given channel to be a "tuning" channel, which can be + * checked using GST_TUNER_CHANNEL_HAS_FLAG (), with the proper flag + * being GST_TUNER_CHANNEL_FREQUENCY. + * + * The frequency is in Hz, with minimum steps indicated by the + * frequency_multiplicator provided in the #GstTunerChannel. The + * valid range is provided in the min_frequency and max_frequency properties + * of the #GstTunerChannel. + */ + +void +gst_tuner_set_frequency (GstTuner * tuner, + GstTunerChannel * channel, gulong frequency) +{ + GstTunerClass *klass; + + g_return_if_fail (GST_IS_TUNER (tuner)); + g_return_if_fail (GST_IS_TUNER_CHANNEL (channel)); + g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY)); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->set_frequency) { + klass->set_frequency (tuner, channel, frequency); + } +} + +/** + * gst_tuner_get_frequency: + * @tuner: The #GstTuner (a #GstElement) that owns the given channel. + * @channel: The #GstTunerChannel to retrieve the frequency from. + * + * Retrieve the current frequency from the given channel. As for + * gst_tuner_set_frequency(), the #GstTunerChannel must support frequency + * operations, as indicated by the GST_TUNER_CHANNEL_FREQUENCY flag. + * + * Returns: The current frequency, or 0 on error. + */ + +gulong +gst_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), 0); + g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + + klass = GST_TUNER_GET_CLASS (tuner); + + if (klass->get_frequency) { + return klass->get_frequency (tuner, channel); + } + + return 0; +} + +/** + * gst_tuner_signal_strength: + * @tuner: the #GstTuner (a #GstElement) that owns the given channel. + * @channel: the #GstTunerChannel to get the signal strength from. + * + * Get the strength of the signal on this channel. Note that this + * requires the current channel to be a "tuning" channel, i.e. a + * channel on which frequency can be set. This can be checked using + * GST_TUNER_CHANNEL_HAS_FLAG (), and the appropriate flag to check + * for is GST_TUNER_CHANNEL_FREQUENCY. + * + * The valid range of the signal strength is indicated in the + * min_signal and max_signal properties of the #GstTunerChannel. + * + * Returns: Signal strength, or 0 on error. + */ +gint +gst_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel) +{ + GstTunerClass *klass; + + g_return_val_if_fail (GST_IS_TUNER (tuner), 0); + g_return_val_if_fail (GST_IS_TUNER_CHANNEL (channel), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + + klass = GST_TUNER_GET_CLASS (tuner); + if (klass->signal_strength) { + return klass->signal_strength (tuner, channel); + } + + return 0; +} + +/** + * gst_tuner_find_norm_by_name: + * @tuner: A #GstTuner instance + * @norm: A string containing the name of a #GstTunerNorm + * + * Look up a #GstTunerNorm by name. + * + * Returns: A #GstTunerNorm, or NULL if no norm with the provided name + * is available. + */ +GstTunerNorm * +gst_tuner_find_norm_by_name (GstTuner * tuner, gchar * norm) +{ + GList *walk; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + g_return_val_if_fail (norm != NULL, NULL); + + walk = (GList *) gst_tuner_list_norms (tuner); + while (walk) { + if (strcmp (GST_TUNER_NORM (walk->data)->label, norm) == 0) + return GST_TUNER_NORM (walk->data); + walk = g_list_next (walk); + } + return NULL; +} + +/** + * gst_tuner_find_channel_by_name: + * @tuner: A #GstTuner instance + * @channel: A string containing the name of a #GstTunerChannel + * + * Look up a #GstTunerChannel by name. + * + * Returns: A #GstTunerChannel, or NULL if no channel with the provided name + * is available. + */ +GstTunerChannel * +gst_tuner_find_channel_by_name (GstTuner * tuner, gchar * channel) +{ + GList *walk; + + g_return_val_if_fail (GST_IS_TUNER (tuner), NULL); + g_return_val_if_fail (channel != NULL, NULL); + + walk = (GList *) gst_tuner_list_channels (tuner); + while (walk) { + if (strcmp (GST_TUNER_CHANNEL (walk->data)->label, channel) == 0) + return GST_TUNER_CHANNEL (walk->data); + walk = g_list_next (walk); + } + return NULL; +} + +/** + * gst_tuner_channel_changed: + * @tuner: A #GstTuner instance + * @channel: A #GstTunerChannel instance + * + * Called by elements implementing the #GstTuner interface when the + * current channel changes. Fires the #GstTuner::channel-changed signal. + */ +void +gst_tuner_channel_changed (GstTuner * tuner, GstTunerChannel * channel) +{ + g_return_if_fail (GST_IS_TUNER (tuner)); + g_return_if_fail (GST_IS_TUNER_CHANNEL (channel)); + + g_signal_emit (G_OBJECT (tuner), + gst_tuner_signals[CHANNEL_CHANGED], 0, channel); +} + +/** + * gst_tuner_norm_changed: + * @tuner: A #GstTuner instance + * @norm: A #GstTunerNorm instance + * + * Called by elements implementing the #GstTuner interface when the + * current norm changes. Fires the #GstTuner::norm-changed signal. + * + */ +void +gst_tuner_norm_changed (GstTuner * tuner, GstTunerNorm * norm) +{ + g_return_if_fail (GST_IS_TUNER (tuner)); + g_return_if_fail (GST_IS_TUNER_NORM (norm)); + + g_signal_emit (G_OBJECT (tuner), gst_tuner_signals[NORM_CHANGED], 0, norm); +} + +/** + * gst_tuner_frequency_changed: + * @tuner: A #GstTuner instance + * @channel: The current #GstTunerChannel + * @frequency: The new frequency setting + * + * Called by elements implementing the #GstTuner interface when the + * configured frequency changes. Fires the #GstTuner::frequency-changed + * signal on the tuner, and the #GstTunerChannel::frequency-changed signal + * on the channel. + */ +void +gst_tuner_frequency_changed (GstTuner * tuner, + GstTunerChannel * channel, gulong frequency) +{ + g_return_if_fail (GST_IS_TUNER (tuner)); + g_return_if_fail (GST_IS_TUNER_CHANNEL (channel)); + + g_signal_emit (G_OBJECT (tuner), + gst_tuner_signals[FREQUENCY_CHANGED], 0, channel, frequency); + + g_signal_emit_by_name (G_OBJECT (channel), "frequency_changed", frequency); +} + +/** + * gst_tuner_signal_changed: + * @tuner: A #GstTuner instance + * @channel: The current #GstTunerChannel + * @signal: The new signal strength + * + * Called by elements implementing the #GstTuner interface when the + * incoming signal strength changes. Fires the #GstTuner::signal-changed + * signal on the tuner and the #GstTunerChannel::signal-changed signal on + * the channel. + */ +void +gst_tuner_signal_changed (GstTuner * tuner, + GstTunerChannel * channel, gint signal) +{ + g_return_if_fail (GST_IS_TUNER (tuner)); + g_return_if_fail (GST_IS_TUNER_CHANNEL (channel)); + + g_signal_emit (G_OBJECT (tuner), + gst_tuner_signals[SIGNAL_CHANGED], 0, channel, signal); + + g_signal_emit_by_name (G_OBJECT (channel), "signal_changed", signal); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.h new file mode 100644 index 0000000..e7ca24e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tuner.h @@ -0,0 +1,128 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tuner.h: tuner interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TUNER_H__ +#define __GST_TUNER_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TUNER \ + (gst_tuner_get_type ()) +#define GST_TUNER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER, GstTuner)) +#define GST_TUNER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER, GstTunerClass)) +#define GST_IS_TUNER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER)) +#define GST_IS_TUNER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER)) +#define GST_TUNER_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TUNER, GstTunerClass)) + +typedef struct _GstTuner GstTuner; +typedef struct _GstTunerClass GstTunerClass; + +struct _GstTunerClass { + GTypeInterface klass; + + /* virtual functions */ + const GList * (* list_channels) (GstTuner *tuner); + void (* set_channel) (GstTuner *tuner, + GstTunerChannel *channel); + GstTunerChannel * + (* get_channel) (GstTuner *tuner); + + const GList * (* list_norms) (GstTuner *tuner); + void (* set_norm) (GstTuner *tuner, + GstTunerNorm *norm); + GstTunerNorm *(* get_norm) (GstTuner *tuner); + + void (* set_frequency) (GstTuner *tuner, + GstTunerChannel *channel, + gulong frequency); + gulong (* get_frequency) (GstTuner *tuner, + GstTunerChannel *channel); + gint (* signal_strength) (GstTuner *tuner, + GstTunerChannel *channel); + + /* signals */ + void (*channel_changed) (GstTuner *tuner, + GstTunerChannel *channel); + void (*norm_changed) (GstTuner *tuner, + GstTunerNorm *norm); + void (*frequency_changed) (GstTuner *tuner, + GstTunerChannel *channel, + gulong frequency); + void (*signal_changed) (GstTuner *tuner, + GstTunerChannel *channel, + gint signal); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_tuner_get_type (void); + +/* virtual class function wrappers */ +const GList * gst_tuner_list_channels (GstTuner *tuner); +void gst_tuner_set_channel (GstTuner *tuner, + GstTunerChannel *channel); +GstTunerChannel * + gst_tuner_get_channel (GstTuner *tuner); + +const GList * gst_tuner_list_norms (GstTuner *tuner); +void gst_tuner_set_norm (GstTuner *tuner, + GstTunerNorm *norm); +GstTunerNorm * gst_tuner_get_norm (GstTuner *tuner); + +void gst_tuner_set_frequency (GstTuner *tuner, + GstTunerChannel *channel, + gulong frequency); +gulong gst_tuner_get_frequency (GstTuner *tuner, + GstTunerChannel *channel); +gint gst_tuner_signal_strength (GstTuner *tuner, + GstTunerChannel *channel); + +/* helper functions */ +GstTunerNorm * gst_tuner_find_norm_by_name (GstTuner *tuner, + gchar *norm); +GstTunerChannel *gst_tuner_find_channel_by_name (GstTuner *tuner, + gchar *channel); + +/* trigger signals */ +void gst_tuner_channel_changed (GstTuner *tuner, + GstTunerChannel *channel); +void gst_tuner_norm_changed (GstTuner *tuner, + GstTunerNorm *norm); +void gst_tuner_frequency_changed (GstTuner *tuner, + GstTunerChannel *channel, + gulong frequency); +void gst_tuner_signal_changed (GstTuner *tuner, + GstTunerChannel *channel, + gint signal); + +G_END_DECLS + +#endif /* __GST_TUNER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.c new file mode 100644 index 0000000..ac2b74e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.c @@ -0,0 +1,148 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tunerchannel.c: tuner channel object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "tunerchannel.h" + +/** + * SECTION:gsttunerchannel + * @short_description: A channel from an element implementing the #GstTuner + * interface. + * + * + * The #GstTunerChannel object is provided by an element implementing + * the #GstTuner interface. + * + * + * GstTunerChannel provides a name and flags to determine the type and + * capabilities of the channel. If the GST_TUNER_CHANNEL_FREQUENCY flag is + * set, then the channel also information about the minimum and maximum + * frequency, and range of the reported signal strength. + * + * + */ + +enum +{ + /* FILL ME */ + SIGNAL_FREQUENCY_CHANGED, + SIGNAL_SIGNAL_CHANGED, + LAST_SIGNAL +}; + +static void gst_tuner_channel_class_init (GstTunerChannelClass * klass); +static void gst_tuner_channel_init (GstTunerChannel * channel); +static void gst_tuner_channel_dispose (GObject * object); + +static GObjectClass *parent_class = NULL; +static guint signals[LAST_SIGNAL] = { 0 }; + +GType +gst_tuner_channel_get_type (void) +{ + static GType gst_tuner_channel_type = 0; + + if (!gst_tuner_channel_type) { + static const GTypeInfo tuner_channel_info = { + sizeof (GstTunerChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_tuner_channel_class_init, + NULL, + NULL, + sizeof (GstTunerChannel), + 0, + (GInstanceInitFunc) gst_tuner_channel_init, + NULL + }; + + gst_tuner_channel_type = + g_type_register_static (G_TYPE_OBJECT, + "GstTunerChannel", &tuner_channel_info, 0); + } + + return gst_tuner_channel_type; +} + +static void +gst_tuner_channel_class_init (GstTunerChannelClass * klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + /** + * GstTunerChannel::frequency-changed: + * @tunerchannel: The #GstTunerChannel + * @frequency: The new frequency (an unsigned long) + * + * Reports that the current frequency has changed. + */ + signals[SIGNAL_FREQUENCY_CHANGED] = + g_signal_new ("frequency-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerChannelClass, + frequency_changed), + NULL, NULL, g_cclosure_marshal_VOID__ULONG, G_TYPE_NONE, 1, G_TYPE_ULONG); + /** + * GstTunerChannel::signal-changed: + * @tunerchannel: The #GstTunerChannel + * @signal: The new signal strength (an integer) + * + * Reports that the signal strength has changed. + * + * See Also: gst_tuner_signal_strength() + */ + signals[SIGNAL_SIGNAL_CHANGED] = + g_signal_new ("signal-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstTunerChannelClass, + signal_changed), + NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + object_klass->dispose = gst_tuner_channel_dispose; +} + +static void +gst_tuner_channel_init (GstTunerChannel * channel) +{ + channel->label = NULL; + channel->flags = 0; + channel->min_frequency = channel->max_frequency = 0; + channel->min_signal = channel->max_signal = 0; +} + +static void +gst_tuner_channel_dispose (GObject * object) +{ + GstTunerChannel *channel = GST_TUNER_CHANNEL (object); + + if (channel->label) { + g_free (channel->label); + channel->label = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.h new file mode 100644 index 0000000..45c9c3f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunerchannel.h @@ -0,0 +1,113 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tunerchannel.h: tuner channel object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TUNER_CHANNEL_H__ +#define __GST_TUNER_CHANNEL_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TUNER_CHANNEL \ + (gst_tuner_channel_get_type ()) +#define GST_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER_CHANNEL, \ + GstTunerChannel)) +#define GST_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER_CHANNEL, \ + GstTunerChannelClass)) +#define GST_IS_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER_CHANNEL)) +#define GST_IS_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_CHANNEL)) + +typedef struct _GstTunerChannel GstTunerChannel; +typedef struct _GstTunerChannelClass GstTunerChannelClass; + +/** + * GstTunerChannelFlags: + * @GST_TUNER_CHANNEL_INPUT: The channel is for input + * @GST_TUNER_CHANNEL_OUTPUT: The channel is for output + * @GST_TUNER_CHANNEL_FREQUENCY: The channel has a frequency setting + * and signal strength. + * @GST_TUNER_CHANNEL_AUDIO: The channel carries audio. + * + * An enumeration for flags indicating the available capabilities + * of a #GstTunerChannel. + */ +typedef enum { + GST_TUNER_CHANNEL_INPUT = (1<<0), + GST_TUNER_CHANNEL_OUTPUT = (1<<1), + GST_TUNER_CHANNEL_FREQUENCY = (1<<2), + GST_TUNER_CHANNEL_AUDIO = (1<<3) +} GstTunerChannelFlags; + +/** + * GST_TUNER_CHANNEL_HAS_FLAG: + * @channel: A #GstTunerChannel + * @flag: The flag to check for + * + * Macro to check if the given flag is set on a channel + */ +#define GST_TUNER_CHANNEL_HAS_FLAG(channel, flag) \ + ((channel)->flags & flag) + +/** + * GstTunerChannel: + * @label: A string containing a descriptive name for this channel + * @flags: A set of #GstTunerChannelFlags for this channel + * @freq_multiplicator: The step size (in Hz) for the frequency setting. + * @min_frequency: Minimum valid frequency setting (in Hz). + * @max_frequency: Maximum valid frequency setting (in Hz). + * @min_signal: Minimum reported signal strength value. + * @max_signal: Maximum reported signal strength value. + */ +struct _GstTunerChannel { + GObject parent; + + /*< public >*/ + gchar *label; + GstTunerChannelFlags flags; + gfloat freq_multiplicator; + gulong min_frequency; + gulong max_frequency; + gint min_signal; + gint max_signal; +}; + +struct _GstTunerChannelClass { + GObjectClass parent; + + /*< private >*/ + /* signals */ + void (*frequency_changed) (GstTunerChannel *channel, + gulong frequency); + void (*signal_changed) (GstTunerChannel *channel, + gint signal); + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_tuner_channel_get_type (void); + +G_END_DECLS + +#endif /* __GST_TUNER_CHANNEL_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.c new file mode 100644 index 0000000..47260b0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.c @@ -0,0 +1,111 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tunernorm.c: tuner norm object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "tunernorm.h" + +/** + * SECTION:gsttunernorm + * @short_description: Encapsulates information about the data format(s) + * for a #GstTunerChannel. + * + * + * The #GstTunerNorm object is created by an element implementing the + * #GstTuner interface and encapsulates the selection of a capture/output format + * for a selected #GstTunerChannel. + * + * + */ + +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +static void gst_tuner_norm_class_init (GstTunerNormClass * klass); +static void gst_tuner_norm_init (GstTunerNorm * norm); +static void gst_tuner_norm_dispose (GObject * object); + +static GObjectClass *parent_class = NULL; + +/*static guint signals[LAST_SIGNAL] = { 0 };*/ + +GType +gst_tuner_norm_get_type (void) +{ + static GType gst_tuner_norm_type = 0; + + if (!gst_tuner_norm_type) { + static const GTypeInfo tuner_norm_info = { + sizeof (GstTunerNormClass), + NULL, + NULL, + (GClassInitFunc) gst_tuner_norm_class_init, + NULL, + NULL, + sizeof (GstTunerNorm), + 0, + (GInstanceInitFunc) gst_tuner_norm_init, + NULL + }; + + gst_tuner_norm_type = + g_type_register_static (G_TYPE_OBJECT, + "GstTunerNorm", &tuner_norm_info, 0); + } + + return gst_tuner_norm_type; +} + +static void +gst_tuner_norm_class_init (GstTunerNormClass * klass) +{ + GObjectClass *object_klass = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + object_klass->dispose = gst_tuner_norm_dispose; +} + +static void +gst_tuner_norm_init (GstTunerNorm * norm) +{ + norm->label = NULL; + g_value_init (&norm->framerate, GST_TYPE_FRACTION); +} + +static void +gst_tuner_norm_dispose (GObject * object) +{ + GstTunerNorm *norm = GST_TUNER_NORM (object); + + if (norm->label) { + g_free (norm->label); + norm->label = NULL; + } + + if (parent_class->dispose) + parent_class->dispose (object); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.h new file mode 100644 index 0000000..d93cb13 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/tunernorm.h @@ -0,0 +1,67 @@ +/* GStreamer Tuner + * Copyright (C) 2003 Ronald Bultje + * + * tunernorm.h: tuner norm object design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TUNER_NORM_H__ +#define __GST_TUNER_NORM_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TUNER_NORM \ + (gst_tuner_norm_get_type ()) +#define GST_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TUNER_NORM, GstTunerNorm)) +#define GST_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_TUNER_NORM, GstTunerNormClass)) +#define GST_IS_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TUNER_NORM)) +#define GST_IS_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_TUNER_NORM)) + +typedef struct _GstTunerNorm GstTunerNorm; +typedef struct _GstTunerNormClass GstTunerNormClass; + +/** + * GstTunerNorm: + * @label: A string containing a descriptive name for the norm + * @framerate: A GValue containing the framerate associated with this norm, + * if any. (May be unset). + */ +struct _GstTunerNorm { + GObject parent; + + /*< public >*/ + gchar *label; + GValue framerate; +}; + +struct _GstTunerNormClass { + GObjectClass parent; + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_tuner_norm_get_type (void); + +G_END_DECLS + +#endif /* __GST_TUNER_NORM_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.c new file mode 100644 index 0000000..35ded69 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.c @@ -0,0 +1,270 @@ +/* GStreamer + * Copyright (C) 2006 Nokia + * + * videoorientation.c: video flipping and centering interface + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "videoorientation.h" +#include "interfaces-marshal.h" + +#include + +/** + * SECTION:gstvideoorientation + * @short_description: Interface for elements providing video orientation + * controls + * + * The interface allows unified access to control flipping and autocenter + * operation of video-sources or operators. + * + * Since: 0.10.11 + */ + +static void gst_video_orientation_iface_init (GstVideoOrientationInterface * + iface); + +GType +gst_video_orientation_get_type (void) +{ + static GType gst_video_orientation_type = 0; + + if (!gst_video_orientation_type) { + static const GTypeInfo gst_video_orientation_info = { + sizeof (GstVideoOrientationInterface), + (GBaseInitFunc) gst_video_orientation_iface_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_video_orientation_type = g_type_register_static (G_TYPE_INTERFACE, + "GstVideoOrientation", &gst_video_orientation_info, 0); + g_type_interface_add_prerequisite (gst_video_orientation_type, + GST_TYPE_IMPLEMENTS_INTERFACE); + } + + return gst_video_orientation_type; +} + +static void +gst_video_orientation_iface_init (GstVideoOrientationInterface * iface) +{ + /* default virtual functions */ + + iface->get_hflip = NULL; + iface->get_vflip = NULL; + iface->get_hcenter = NULL; + iface->get_vcenter = NULL; + + iface->set_hflip = NULL; + iface->set_vflip = NULL; + iface->set_hcenter = NULL; + iface->set_vcenter = NULL; +} + +/** + * gst_video_orientation_get_hflip: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @flip: return location for the result + * + * Get the horizontal flipping state (%TRUE for flipped) from the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports flipping + */ +gboolean +gst_video_orientation_get_hflip (GstVideoOrientation * video_orientation, + gboolean * flip) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->get_hflip) { + return iface->get_hflip (video_orientation, flip); + } + return FALSE; +} + +/** + * gst_video_orientation_get_vflip: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @flip: return location for the result + * + * Get the vertical flipping state (%TRUE for flipped) from the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports flipping + */ +gboolean +gst_video_orientation_get_vflip (GstVideoOrientation * video_orientation, + gboolean * flip) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->get_vflip) { + return iface->get_vflip (video_orientation, flip); + } + return FALSE; +} + +/** + * gst_video_orientation_get_hcenter: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @center: return location for the result + * + * Get the horizontal centering offset from the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports centering + */ +gboolean +gst_video_orientation_get_hcenter (GstVideoOrientation * video_orientation, + gint * center) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->get_hcenter) { + return iface->get_hcenter (video_orientation, center); + } + return FALSE; +} + +/** + * gst_video_orientation_get_vcenter: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @center: return location for the result + * + * Get the vertical centering offset from the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports centering + */ +gboolean +gst_video_orientation_get_vcenter (GstVideoOrientation * video_orientation, + gint * center) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->get_vcenter) { + return iface->get_vcenter (video_orientation, center); + } + return FALSE; +} + +/** + * gst_video_orientation_set_hflip: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @flip: use flipping + * + * Set the horizontal flipping state (%TRUE for flipped) for the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports flipping + */ +gboolean +gst_video_orientation_set_hflip (GstVideoOrientation * video_orientation, + gboolean flip) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->set_hflip) { + return iface->set_hflip (video_orientation, flip); + } + return FALSE; +} + +/** + * gst_video_orientation_set_vflip: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @flip: use flipping + * + * Set the vertical flipping state (%TRUE for flipped) for the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports flipping + */ +gboolean +gst_video_orientation_set_vflip (GstVideoOrientation * video_orientation, + gboolean flip) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->set_vflip) { + return iface->set_vflip (video_orientation, flip); + } + return FALSE; +} + +/** + * gst_video_orientation_set_hcenter: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @center: centering offset + * + * Set the horizontal centering offset for the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports centering + */ +gboolean +gst_video_orientation_set_hcenter (GstVideoOrientation * video_orientation, + gint center) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->set_hcenter) { + return iface->set_hcenter (video_orientation, center); + } + return FALSE; +} + +/** + * gst_video_orientation_set_vcenter: + * @video_orientation: #GstVideoOrientation interface of a #GstElement + * @center: centering offset + * + * Set the vertical centering offset for the given object. + * + * Since: 0.10.11 + * Returns: %TRUE in case the element supports centering + */ +gboolean +gst_video_orientation_set_vcenter (GstVideoOrientation * video_orientation, + gint center) +{ + GstVideoOrientationInterface *iface = + GST_VIDEO_ORIENTATION_GET_IFACE (video_orientation); + + if (iface->set_vcenter) { + return iface->set_vcenter (video_orientation, center); + } + return FALSE; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.h new file mode 100644 index 0000000..c02d08b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/videoorientation.h @@ -0,0 +1,94 @@ +/* GStreamer + * Copyright (C) 2006 Nokia +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_ORIENTATION \ + (gst_video_orientation_get_type ()) +#define GST_VIDEO_ORIENTATION(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_ORIENTATION, GstVideoOrientation)) +#define GST_IS_VIDEO_ORIENTATION(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_ORIENTATION)) +#define GST_VIDEO_ORIENTATION_GET_IFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_VIDEO_ORIENTATION, GstVideoOrientationInterface)) + +/** + * GstVideoOrientation: + * + * Opaque #GstVideoOrientation data structure. + */ +typedef struct _GstVideoOrientation GstVideoOrientation; +typedef struct _GstVideoOrientationInterface GstVideoOrientationInterface; + +/** + * GstVideoOrientationInterface: + * @parent: parent interface type. + * @get_hflip: virtual method to get horizontal flipping state + * @get_vflip: virtual method to get vertical flipping state + * @get_hcenter: virtual method to get horizontal centering state + * @get_vcenter: virtual method to get vertical centering state + * @set_hflip: virtual method to set horizontal flipping state + * @set_vflip: virtual method to set vertical flipping state + * @set_hcenter: virtual method to set horizontal centering state + * @set_vcenter: virtual method to set vertical centering state + * + * #GstVideoOrientationInterface interface. + */ +struct _GstVideoOrientationInterface { + GTypeInterface parent; + + /* virtual functions */ + gboolean (* get_hflip) (GstVideoOrientation *video_orientation, gboolean *flip); + gboolean (* get_vflip) (GstVideoOrientation *video_orientation, gboolean *flip); + gboolean (* get_hcenter) (GstVideoOrientation *video_orientation, gint *center); + gboolean (* get_vcenter) (GstVideoOrientation *video_orientation, gint *center); + + gboolean (* set_hflip) (GstVideoOrientation *video_orientation, gboolean flip); + gboolean (* set_vflip) (GstVideoOrientation *video_orientation, gboolean flip); + gboolean (* set_hcenter) (GstVideoOrientation *video_orientation, gint center); + gboolean (* set_vcenter) (GstVideoOrientation *video_orientation, gint center); + + /*< private > */ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_video_orientation_get_type (void); + +/* virtual class function wrappers */ +gboolean gst_video_orientation_get_hflip (GstVideoOrientation *video_orientation, gboolean *flip); +gboolean gst_video_orientation_get_vflip (GstVideoOrientation *video_orientation, gboolean *flip); +gboolean gst_video_orientation_get_hcenter (GstVideoOrientation *video_orientation, gint *center); +gboolean gst_video_orientation_get_vcenter (GstVideoOrientation *video_orientation, gint *center); + +gboolean gst_video_orientation_set_hflip (GstVideoOrientation *video_orientation, gboolean flip); +gboolean gst_video_orientation_set_vflip (GstVideoOrientation *video_orientation, gboolean flip); +gboolean gst_video_orientation_set_hcenter (GstVideoOrientation *video_orientation, gint center); +gboolean gst_video_orientation_set_vcenter (GstVideoOrientation *video_orientation, gint center); + +G_END_DECLS + +#endif /* __GST_VIDEO_ORIENTATION_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.c new file mode 100644 index 0000000..e7bd655 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.c @@ -0,0 +1,567 @@ +/* GStreamer X-based Overlay + * Copyright (C) 2003 Ronald Bultje + * + * x-overlay.c: X-based overlay interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstxoverlay + * @short_description: Interface for setting/getting a Window on elements + * supporting it + * + * + * + * The XOverlay interface is used for 2 main purposes : + * + * + * + * To get a grab on the Window where the video sink element is going to render. + * This is achieved by either being informed about the Window identifier that + * the video sink element generated, or by forcing the video sink element to use + * a specific Window identifier for rendering. + * + * + * + * + * To force a redrawing of the latest video frame the video sink element + * displayed on the Window. Indeed if the #GstPipeline is in #GST_STATE_PAUSED + * state, moving the Window around will damage its content. Application + * developers will want to handle the Expose events themselves and force the + * video sink element to refresh the Window's content. + * + * + * + * + * + * Using the Window created by the video sink is probably the simplest scenario, + * in some cases, though, it might not be flexible enough for application + * developers if they need to catch events such as mouse moves and button + * clicks. + * + * + * Setting a specific Window identifier on the video sink element is the most + * flexible solution but it has some issues. Indeed the application needs to set + * its Window identifier at the right time to avoid internal Window creation + * from the video sink element. To solve this issue a #GstMessage is posted on + * the bus to inform the application that it should set the Window identifier + * immediately. Here is an example on how to do that correctly: + * |[ + * static GstBusSyncReply + * create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline) + * { + * // ignore anything but 'prepare-xwindow-id' element messages + * if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + * return GST_BUS_PASS; + * + * if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) + * return GST_BUS_PASS; + * + * win = XCreateSimpleWindow (disp, root, 0, 0, 320, 240, 0, 0, 0); + * + * XSetWindowBackgroundPixmap (disp, win, None); + * + * XMapRaised (disp, win); + * + * XSync (disp, FALSE); + * + * gst_x_overlay_set_window_handle (GST_X_OVERLAY (GST_MESSAGE_SRC (message)), + * win); + * + * gst_message_unref (message); + * + * return GST_BUS_DROP; + * } + * ... + * int + * main (int argc, char **argv) + * { + * ... + * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline); + * ... + * } + * ]| + * + * + * + * Two basic usage scenarios + * + * There are two basic usage scenarios: in the simplest case, the application + * knows exactly what particular element is used for video output, which is + * usually the case when the application creates the videosink to use + * (e.g. #xvimagesink, #ximagesink, etc.) itself; in this case, the application + * can just create the videosink element, create and realize the window to + * render the video on and then call gst_x_overlay_set_window_handle() directly + * with the XID or native window handle, before starting up the pipeline. + * + * + * In the other and more common case, the application does not know in advance + * what GStreamer video sink element will be used for video output. This is + * usually the case when an element such as #autovideosink or #gconfvideosink + * is used. In this case, the video sink element itself is created + * asynchronously from a GStreamer streaming thread some time after the + * pipeline has been started up. When that happens, however, the video sink + * will need to know right then whether to render onto an already existing + * application window or whether to create its own window. This is when it + * posts a prepare-xwindow-id message, and that is also why this message needs + * to be handled in a sync bus handler which will be called from the streaming + * thread directly (because the video sink will need an answer right then). + * + * + * As response to the prepare-xwindow-id element message in the bus sync + * handler, the application may use gst_x_overlay_set_window_handle() to tell + * the video sink to render onto an existing window surface. At this point the + * application should already have obtained the window handle / XID, so it + * just needs to set it. It is generally not advisable to call any GUI toolkit + * functions or window system functions from the streaming thread in which the + * prepare-xwindow-id message is handled, because most GUI toolkits and + * windowing systems are not thread-safe at all and a lot of care would be + * required to co-ordinate the toolkit and window system calls of the + * different threads (Gtk+ users please note: prior to Gtk+ 2.18 + * GDK_WINDOW_XID() was just a simple structure access, so generally fine to do + * within the bus sync handler; this macro was changed to a function call in + * Gtk+ 2.18 and later, which is likely to cause problems when called from a + * sync handler; see below for a better approach without GDK_WINDOW_XID() + * used in the callback). + * + * + * + * GstXOverlay and Gtk+ + * + * |[ + * #include <gtk/gtk.h> + * #ifdef GDK_WINDOWING_X11 + * #include <gdk/gdkx.h> // for GDK_WINDOW_XID + * #endif + * ... + * static gulong video_window_xid = 0; + * ... + * static GstBusSyncReply + * bus_sync_handler (GstBus * bus, GstMessage * message, gpointer user_data) + * { + * // ignore anything but 'prepare-xwindow-id' element messages + * if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + * return GST_BUS_PASS; + * if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) + * return GST_BUS_PASS; + * + * if (video_window_xid != 0) { + * GstXOverlay *xoverlay; + * + * // GST_MESSAGE_SRC (message) will be the video sink element + * xoverlay = GST_X_OVERLAY (GST_MESSAGE_SRC (message)); + * gst_x_overlay_set_window_handle (xoverlay, video_window_xid); + * } else { + * g_warning ("Should have obtained video_window_xid by now!"); + * } + * + * gst_message_unref (message); + * return GST_BUS_DROP; + * } + * ... + * static void + * video_widget_realize_cb (GtkWidget * widget, gpointer data) + * { + * #if GTK_CHECK_VERSION(2,18,0) + * // This is here just for pedagogical purposes, GDK_WINDOW_XID will call + * // it as well in newer Gtk versions + * if (!gdk_window_ensure_native (widget->window)) + * g_error ("Couldn't create native window needed for GstXOverlay!"); + * #endif + * + * #ifdef GDK_WINDOWING_X11 + * video_window_xid = GDK_WINDOW_XID (video_window->window); + * #endif + * } + * ... + * int + * main (int argc, char **argv) + * { + * GtkWidget *video_window; + * GtkWidget *app_window; + * ... + * app_window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + * ... + * video_window = gtk_drawing_area_new (); + * g_signal_connect (video_window, "realize", + * G_CALLBACK (video_widget_realize_cb), NULL); + * gtk_widget_set_double_buffered (video_window, FALSE); + * ... + * // usually the video_window will not be directly embedded into the + * // application window like this, but there will be many other widgets + * // and the video window will be embedded in one of them instead + * gtk_container_add (GTK_CONTAINER (ap_window), video_window); + * ... + * // show the GUI + * gtk_widget_show_all (app_window); + * + * // realize window now so that the video window gets created and we can + * // obtain its XID before the pipeline is started up and the videosink + * // asks for the XID of the window to render onto + * gtk_widget_realize (window); + * + * // we should have the XID now + * g_assert (video_window_xid != 0); + * ... + * // set up sync handler for setting the xid once the pipeline is started + * bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + * gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, NULL); + * gst_object_unref (bus); + * ... + * gst_element_set_state (pipeline, GST_STATE_PLAYING); + * ... + * } + * ]| + * + * + * + * GstXOverlay and Qt + * + * |[ + * #include <glib.h> + * #include <gst/gst.h> + * #include <gst/interfaces/xoverlay.h> + * + * #include <QApplication> + * #include <QTimer> + * #include <QWidget> + * + * int main(int argc, char *argv[]) + * { + * if (!g_thread_supported ()) + * g_thread_init (NULL); + * + * gst_init (&argc, &argv); + * QApplication app(argc, argv); + * app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ())); + * + * // prepare the pipeline + * + * GstElement *pipeline = gst_pipeline_new ("xvoverlay"); + * GstElement *src = gst_element_factory_make ("videotestsrc", NULL); + * GstElement *sink = gst_element_factory_make ("xvimagesink", NULL); + * gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + * gst_element_link (src, sink); + * + * // prepare the ui + * + * QWidget window; + * window.resize(320, 240); + * window.show(); + * + * WId xwinid = window.winId(); + * gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid); + * + * // run the pipeline + * + * GstStateChangeReturn sret = gst_element_set_state (pipeline, + * GST_STATE_PLAYING); + * if (sret == GST_STATE_CHANGE_FAILURE) { + * gst_element_set_state (pipeline, GST_STATE_NULL); + * gst_object_unref (pipeline); + * // Exit application + * QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); + * } + * + * int ret = app.exec(); + * + * window.hide(); + * gst_element_set_state (pipeline, GST_STATE_NULL); + * gst_object_unref (pipeline); + * + * return ret; + * } + * ]| + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xoverlay.h" + +static void gst_x_overlay_base_init (gpointer g_class); + +GType +gst_x_overlay_get_type (void) +{ + static GType gst_x_overlay_type = 0; + + if (!gst_x_overlay_type) { + static const GTypeInfo gst_x_overlay_info = { + sizeof (GstXOverlayClass), + gst_x_overlay_base_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + gst_x_overlay_type = g_type_register_static (G_TYPE_INTERFACE, + "GstXOverlay", &gst_x_overlay_info, 0); + g_type_interface_add_prerequisite (gst_x_overlay_type, + GST_TYPE_IMPLEMENTS_INTERFACE); + } + + return gst_x_overlay_type; +} + +static void +gst_x_overlay_base_init (gpointer g_class) +{ + +} + +/** + * gst_x_overlay_set_xwindow_id: + * @overlay: a #GstXOverlay to set the XWindow on. + * @xwindow_id: a #XID referencing the XWindow. + * + * This will call the video overlay's set_xwindow_id method. You should + * use this method to tell to a XOverlay to display video output to a + * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to + * stop using that window and create an internal one. + * + * Deprecated: Use gst_x_overlay_set_window_handle() instead. + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +void gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id); +#endif +void +gst_x_overlay_set_xwindow_id (GstXOverlay * overlay, gulong xwindow_id) +{ + GST_WARNING_OBJECT (overlay, + "Using deprecated gst_x_overlay_set_xwindow_id()"); + gst_x_overlay_set_window_handle (overlay, xwindow_id); +} +#endif + +/** + * gst_x_overlay_set_window_handle: + * @overlay: a #GstXOverlay to set the XWindow on. + * @xwindow_id: a #XID referencing the XWindow. + * + * This will call the video overlay's set_window_handle method. You + * should use this method to tell to a XOverlay to display video output to a + * specific XWindow. Passing 0 as the xwindow_id will tell the overlay to + * stop using that window and create an internal one. + * + * Since: 0.10.31 + */ +void +gst_x_overlay_set_window_handle (GstXOverlay * overlay, guintptr handle) +{ + GstXOverlayClass *klass; + + g_return_if_fail (overlay != NULL); + g_return_if_fail (GST_IS_X_OVERLAY (overlay)); + + klass = GST_X_OVERLAY_GET_CLASS (overlay); + + if (klass->set_window_handle) { + klass->set_window_handle (overlay, handle); + } else { +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +#define set_xwindow_id set_xwindow_id_disabled +#endif + if (sizeof (guintptr) <= sizeof (gulong) && klass->set_xwindow_id) { + GST_WARNING_OBJECT (overlay, + "Calling deprecated set_xwindow_id() method"); + klass->set_xwindow_id (overlay, handle); + } else { + g_warning ("Refusing to cast guintptr to smaller gulong"); + } +#endif + } +} + +/** + * gst_x_overlay_got_xwindow_id: + * @overlay: a #GstXOverlay which got a XWindow. + * @xwindow_id: a #XID referencing the XWindow. + * + * This will post a "have-xwindow-id" element message on the bus. + * + * This function should only be used by video overlay plugin developers. + * + * Deprecated: Use gst_x_overlay_got_window_handle() instead. + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +void gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id); +#endif +void +gst_x_overlay_got_xwindow_id (GstXOverlay * overlay, gulong xwindow_id) +{ + GST_WARNING_OBJECT (overlay, + "Using deprecated gst_x_overlay_got_xwindow_id()"); + gst_x_overlay_got_window_handle (overlay, xwindow_id); +} +#endif + +/** + * gst_x_overlay_got_window_handle: + * @overlay: a #GstXOverlay which got a window + * @handle: a platform-specific handle referencing the window + * + * This will post a "have-xwindow-id" element message on the bus. + * + * This function should only be used by video overlay plugin developers. + */ +void +gst_x_overlay_got_window_handle (GstXOverlay * overlay, guintptr handle) +{ + GstStructure *s; + GstMessage *msg; + + g_return_if_fail (overlay != NULL); + g_return_if_fail (GST_IS_X_OVERLAY (overlay)); + + GST_LOG_OBJECT (GST_OBJECT (overlay), "xwindow_id = %p", (gpointer) + handle); + s = gst_structure_new ("have-xwindow-id", + "xwindow-id", G_TYPE_ULONG, (unsigned long) handle, + "window-handle", G_TYPE_UINT64, (guint64) handle, NULL); + msg = gst_message_new_element (GST_OBJECT (overlay), s); + gst_element_post_message (GST_ELEMENT (overlay), msg); +} + +/** + * gst_x_overlay_prepare_xwindow_id: + * @overlay: a #GstXOverlay which does not yet have an XWindow. + * + * This will post a "prepare-xwindow-id" element message on the bus + * to give applications an opportunity to call + * gst_x_overlay_set_xwindow_id() before a plugin creates its own + * window. + * + * This function should only be used by video overlay plugin developers. + */ +void +gst_x_overlay_prepare_xwindow_id (GstXOverlay * overlay) +{ + GstStructure *s; + GstMessage *msg; + + g_return_if_fail (overlay != NULL); + g_return_if_fail (GST_IS_X_OVERLAY (overlay)); + + GST_LOG_OBJECT (GST_OBJECT (overlay), "prepare xwindow_id"); + s = gst_structure_new ("prepare-xwindow-id", NULL); + msg = gst_message_new_element (GST_OBJECT (overlay), s); + gst_element_post_message (GST_ELEMENT (overlay), msg); +} + +/** + * gst_x_overlay_expose: + * @overlay: a #GstXOverlay to expose. + * + * Tell an overlay that it has been exposed. This will redraw the current frame + * in the drawable even if the pipeline is PAUSED. + */ +void +gst_x_overlay_expose (GstXOverlay * overlay) +{ + GstXOverlayClass *klass; + + g_return_if_fail (overlay != NULL); + g_return_if_fail (GST_IS_X_OVERLAY (overlay)); + + klass = GST_X_OVERLAY_GET_CLASS (overlay); + + if (klass->expose) { + klass->expose (overlay); + } +} + +/** + * gst_x_overlay_handle_events: + * @overlay: a #GstXOverlay to expose. + * @handle_events: a #gboolean indicating if events should be handled or not. + * + * Tell an overlay that it should handle events from the window system. These + * events are forwared upstream as navigation events. In some window system, + * events are not propagated in the window hierarchy if a client is listening + * for them. This method allows you to disable events handling completely + * from the XOverlay. + * + * Since: 0.10.12 + */ +void +gst_x_overlay_handle_events (GstXOverlay * overlay, gboolean handle_events) +{ + GstXOverlayClass *klass; + + g_return_if_fail (overlay != NULL); + g_return_if_fail (GST_IS_X_OVERLAY (overlay)); + + klass = GST_X_OVERLAY_GET_CLASS (overlay); + + if (klass->handle_events) { + klass->handle_events (overlay, handle_events); + } +} + +/** + * gst_x_overlay_set_render_rectangle: + * @overlay: a #GstXOverlay + * @x: the horizontal offset of the render area inside the window + * @y: the vertical offset of the render area inside the window + * @width: the width of the render area inside the window + * @height: the height of the render area inside the window + * + * Configure a subregion as a video target within the window set by + * gst_x_overlay_set_window_handle(). If this is not used or not supported + * the video will fill the area of the window set as the overlay to 100%. + * By specifying the rectangle, the video can be overlayed to a specific region + * of that window only. After setting the new rectangle one should call + * gst_x_overlay_expose() to force a redraw. To unset the region pass -1 for + * the @width and @height parameters. + * + * This method is needed for non fullscreen video overlay in UI toolkits that + * do not support subwindows. + * + * Returns: %FALSE if not supported by the sink. + * + * Since: 0.10.29 + */ +gboolean +gst_x_overlay_set_render_rectangle (GstXOverlay * overlay, + gint x, gint y, gint width, gint height) +{ + GstXOverlayClass *klass; + + g_return_val_if_fail (overlay != NULL, FALSE); + g_return_val_if_fail (GST_IS_X_OVERLAY (overlay), FALSE); + g_return_val_if_fail ((width == -1 && height == -1) || + (width > 0 && height > 0), FALSE); + + klass = GST_X_OVERLAY_GET_CLASS (overlay); + + if (klass->set_render_rectangle) { + klass->set_render_rectangle (overlay, x, y, width, height); + return TRUE; + } + return FALSE; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.h new file mode 100644 index 0000000..055f510 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/interfaces/xoverlay.h @@ -0,0 +1,121 @@ +/* GStreamer X-based Overlay + * Copyright (C) 2003 Ronald Bultje + * Copyright (C) 2003 Julien Moutte + * + * x-overlay.h: X-based overlay interface design + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_X_OVERLAY_H__ +#define __GST_X_OVERLAY_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_X_OVERLAY \ + (gst_x_overlay_get_type ()) +#define GST_X_OVERLAY(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_X_OVERLAY, \ + GstXOverlay)) +#define GST_X_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_X_OVERLAY, GstXOverlayClass)) +#define GST_IS_X_OVERLAY(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_X_OVERLAY)) +#define GST_IS_X_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_X_OVERLAY)) +#define GST_X_OVERLAY_GET_CLASS(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_X_OVERLAY, GstXOverlayClass)) + +/** + * GstXOverlay: + * + * Opaque #GstXOverlay data structure. + */ +typedef struct _GstXOverlay GstXOverlay; +typedef struct _GstXOverlayClass GstXOverlayClass; + +/** + * GstXOverlayClass: + * @klass: parent interface type. + * @set_xwindow_id: virtual method to configure the XWindow id + * @expose: virtual method to handle expose events + * @handle_events: virtual method to handle events + * @set_render_rectangle: virtual method to set the render rectangle (since 0.10.29) + * + * #GstXOverlay interface + */ +struct _GstXOverlayClass { + GTypeInterface klass; + + /* virtual functions */ +#ifndef GST_DISABLE_DEPRECATED + void (* set_xwindow_id) (GstXOverlay *overlay, + gulong xwindow_id); +#else + void (* set_xwindow_id_disabled) (GstXOverlay *overlay, + gulong xwindow_id); +#endif /* not GST_DISABLE_DEPRECATED */ + + void (* expose) (GstXOverlay *overlay); + + void (* handle_events) (GstXOverlay *overlay, + gboolean handle_events); + + void (* set_render_rectangle) (GstXOverlay *overlay, + gint x, gint y, + gint width, gint height); + + void (* set_window_handle) (GstXOverlay *overlay, + guintptr handle); + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 3]; +}; + +GType gst_x_overlay_get_type (void); + +/* virtual class function wrappers */ +#ifndef GST_DISABLE_DEPRECATED +void gst_x_overlay_set_xwindow_id (GstXOverlay *overlay, + gulong xwindow_id); +#endif + +gboolean gst_x_overlay_set_render_rectangle (GstXOverlay *overlay, + gint x, gint y, + gint width, gint height); + +void gst_x_overlay_expose (GstXOverlay *overlay); + +void gst_x_overlay_handle_events (GstXOverlay *overlay, + gboolean handle_events); + +void gst_x_overlay_set_window_handle (GstXOverlay *overlay, + guintptr handle); + +/* public methods to dispatch bus messages */ +#ifndef GST_DISABLE_DEPRECATED +void gst_x_overlay_got_xwindow_id (GstXOverlay *overlay, gulong xwindow_id); +#endif + +void gst_x_overlay_got_window_handle (GstXOverlay *overlay, + guintptr handle); + +void gst_x_overlay_prepare_xwindow_id (GstXOverlay *overlay); + +G_END_DECLS + +#endif /* __GST_X_OVERLAY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/Makefile.am new file mode 100644 index 0000000..086a86b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/Makefile.am @@ -0,0 +1,69 @@ +libgstnetbufferincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/netbuffer + +libgstnetbufferinclude_HEADERS = gstnetbuffer.h + +lib_LTLIBRARIES = libgstnetbuffer-@GST_MAJORMINOR@.la + +libgstnetbuffer_@GST_MAJORMINOR@_la_SOURCES = gstnetbuffer.c +libgstnetbuffer_@GST_MAJORMINOR@_la_CFLAGS = $(GST_CFLAGS) +libgstnetbuffer_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) +libgstnetbuffer_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstNetbuffer-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstnetbufferinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstnetbuffer_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/netbuffer/%',$(libgstnetbufferinclude_HEADERS)) + +GstNetbuffer-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstnetbuffer-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstNetbuffer \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstnetbuffer-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-netbuffer-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstnetbuffer -:SHARED libgstnetbuffer-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstnetbuffer_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstnetbuffer_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstnetbuffer_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstnetbuffer_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/netbuffer \ + -:HEADERS $(libgstnetbuffer_include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/README b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/README new file mode 100644 index 0000000..d55ceb1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/README @@ -0,0 +1,9 @@ +The network libraries +--------------------- + +GstNetBuffer: + + A GstBuffer subclass that can be used by network sources or sinks to + store additional to and from addresses. This is required for plugins + that operate on this data like RTP. + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.c new file mode 100644 index 0000000..6328a76 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.c @@ -0,0 +1,423 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstnetbuffer + * @short_description: Buffer for use in network sources and sinks + * + * #GstNetBuffer is a subclass of a normal #GstBuffer that contains two + * additional metadata fields of type #GstNetAddress named 'to' and 'from'. The + * buffer can be used to store additional information about the origin of the + * buffer data and is used in various network elements to track the to and from + * addresses. + * + * Last reviewed on 2006-08-21 (0.10.10) + */ + +#include + +#include "gstnetbuffer.h" + +static void gst_netbuffer_finalize (GstNetBuffer * nbuf); +static GstNetBuffer *gst_netbuffer_copy (GstNetBuffer * nbuf); + +static GstBufferClass *parent_class; + +G_DEFINE_TYPE (GstNetBuffer, gst_netbuffer, GST_TYPE_BUFFER); + +static void +gst_netbuffer_class_init (GstNetBufferClass * netbuffer_class) +{ + GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (netbuffer_class); + + parent_class = g_type_class_peek_parent (netbuffer_class); + + mo_class->copy = (GstMiniObjectCopyFunction) gst_netbuffer_copy; + mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_netbuffer_finalize; +} + +static void +gst_netbuffer_init (GstNetBuffer * instance) +{ +} + +static void +gst_netbuffer_finalize (GstNetBuffer * nbuf) +{ + GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf)); +} + +static GstNetBuffer * +gst_netbuffer_copy (GstNetBuffer * nbuf) +{ + GstNetBuffer *copy; + + copy = gst_netbuffer_new (); + + /* we simply copy everything from our parent */ + GST_BUFFER_DATA (copy) = + g_memdup (GST_BUFFER_DATA (nbuf), GST_BUFFER_SIZE (nbuf)); + /* make sure it gets freed (even if the parent is subclassed, we return a + normal buffer) */ + GST_BUFFER_MALLOCDATA (copy) = GST_BUFFER_DATA (copy); + GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (nbuf); + + memcpy (©->to, &nbuf->to, sizeof (nbuf->to)); + memcpy (©->from, &nbuf->from, sizeof (nbuf->from)); + + /* copy metadata */ + gst_buffer_copy_metadata (GST_BUFFER_CAST (copy), + GST_BUFFER_CAST (nbuf), GST_BUFFER_COPY_ALL); + + return copy; +} + +/** + * gst_netbuffer_new: + * + * Create a new network buffer. + * + * Returns: a new #GstNetBuffer. + */ +GstNetBuffer * +gst_netbuffer_new (void) +{ + GstNetBuffer *buf; + + buf = (GstNetBuffer *) gst_mini_object_new (GST_TYPE_NETBUFFER); + + return buf; +} + +/** + * gst_netaddress_set_ip4_address: + * @naddr: a network address + * @address: an IPv4 network address. + * @port: a port number to set. + * + * Set @naddr with the IPv4 @address and @port pair. + * + * Note that @port and @address must be expressed in network byte order, + * use g_htons() and g_htonl() to convert them to network byte order. + */ +void +gst_netaddress_set_ip4_address (GstNetAddress * naddr, guint32 address, + guint16 port) +{ + g_return_if_fail (naddr != NULL); + + naddr->type = GST_NET_TYPE_IP4; + naddr->address.ip4 = address; + naddr->port = port; +} + +/** + * gst_netaddress_set_ip6_address: + * @naddr: a network address + * @address: an IPv6 network address. + * @port: a port number to set. + * + * Set @naddr with the IPv6 @address and @port pair. + * + * Note that @port must be expressed in network byte order, use g_htons() to convert + * it to network byte order. + */ +void +gst_netaddress_set_ip6_address (GstNetAddress * naddr, guint8 address[16], + guint16 port) +{ + g_return_if_fail (naddr != NULL); + + naddr->type = GST_NET_TYPE_IP6; + memcpy (&naddr->address.ip6, address, 16); + naddr->port = port; +} + +/** + * gst_netaddress_get_net_type: + * @naddr: a network address + * + * Get the type of address stored in @naddr. + * + * Returns: the network type stored in @naddr. + */ +GstNetType +gst_netaddress_get_net_type (const GstNetAddress * naddr) +{ + g_return_val_if_fail (naddr != NULL, GST_NET_TYPE_UNKNOWN); + + return naddr->type; +} + +/** + * gst_netaddress_get_ip4_address: + * @naddr: a network address + * @address: a location to store the address. + * @port: a location to store the port. + * + * Get the IPv4 address stored in @naddr into @address. This function requires + * that the address type of @naddr is of type #GST_NET_TYPE_IP4. + * + * Note that @port and @address are expressed in network byte order, use + * g_ntohs() and g_ntohl() to convert them to host order. + * + * Returns: TRUE if the address could be retrieved. + */ +gboolean +gst_netaddress_get_ip4_address (const GstNetAddress * naddr, guint32 * address, + guint16 * port) +{ + g_return_val_if_fail (naddr != NULL, FALSE); + + if (naddr->type == GST_NET_TYPE_UNKNOWN || naddr->type == GST_NET_TYPE_IP6) + return FALSE; + + if (address) + *address = naddr->address.ip4; + if (port) + *port = naddr->port; + + return TRUE; +} + +/** + * gst_netaddress_get_ip6_address: + * @naddr: a network address + * @address: a location to store the result. + * @port: a location to store the port. + * + * Get the IPv6 address stored in @naddr into @address. + * + * If @naddr is of type GST_NET_TYPE_IP4, the transitional IP6 address is + * returned. + * + * Note that @port is expressed in network byte order, use g_ntohs() to convert + * it to host order. + * + * Returns: TRUE if the address could be retrieved. + */ +gboolean +gst_netaddress_get_ip6_address (const GstNetAddress * naddr, guint8 address[16], + guint16 * port) +{ + static guint8 ip4_transition[16] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF }; + g_return_val_if_fail (naddr != NULL, FALSE); + + if (naddr->type == GST_NET_TYPE_UNKNOWN) + return FALSE; + + if (address) { + if (naddr->type == GST_NET_TYPE_IP6) { + memcpy (address, naddr->address.ip6, 16); + } else { /* naddr->type == GST_NET_TYPE_IP4 */ + memcpy (address, ip4_transition, 12); + memcpy (address + 12, (guint8 *) & (naddr->address.ip4), 4); + } + } + if (port) + *port = naddr->port; + + return TRUE; +} + +/** + * gst_netaddress_get_address_bytes: + * @naddr: a network address + * @address: a location to store the result. + * @port: a location to store the port. + * + * Get just the address bytes stored in @naddr into @address. + * + * Note that @port is expressed in network byte order, use g_ntohs() to convert + * it to host order. IP4 addresses are also stored in network byte order. + * + * Returns: number of bytes actually copied + * + * Since: 0.10.22 + */ +gint +gst_netaddress_get_address_bytes (const GstNetAddress * naddr, + guint8 address[16], guint16 * port) +{ + gint ret = 0; + + g_return_val_if_fail (naddr != NULL, FALSE); + + if (naddr->type == GST_NET_TYPE_UNKNOWN) + return 0; + + if (address) { + if (naddr->type == GST_NET_TYPE_IP6) { + memcpy (address, naddr->address.ip6, 16); + ret = 16; + } else { /* naddr->type == GST_NET_TYPE_IP4 */ + memcpy (address, (guint8 *) & (naddr->address.ip4), 4); + ret = 4; + } + } + if (port) + *port = naddr->port; + + return ret; +} + +/** + * gst_netaddress_set_address_bytes: + * @naddr: a network address + * @type: the address type (IPv4 or IPV6) + * @address: a location to store the result. + * @port: a location to store the port. + * + * Set just the address bytes stored in @naddr into @address. + * + * Note that @port must be expressed in network byte order, use g_htons() to + * convert it to network byte order order. IP4 address bytes must also be + * stored in network byte order. + * + * Returns: number of bytes actually copied + * + * Since: 0.10.22 + */ +gint +gst_netaddress_set_address_bytes (GstNetAddress * naddr, GstNetType type, + guint8 address[16], guint16 port) +{ + gint len = 0; + + g_return_val_if_fail (naddr != NULL, 0); + + naddr->type = type; + switch (naddr->type) { + case GST_NET_TYPE_UNKNOWN: + case GST_NET_TYPE_IP6: + len = 16; + memcpy (naddr->address.ip6, address, 16); + break; + case GST_NET_TYPE_IP4: + len = 4; + memcpy ((guint8 *) & (naddr->address.ip4), address, 4); + break; + } + + if (port) + naddr->port = port; + + return len; +} + +/** + * gst_netaddress_equal: + * @naddr1: The first #GstNetAddress + * @naddr2: The second #GstNetAddress + * + * Compare two #GstNetAddress structures + * + * Returns: TRUE if they are identical, FALSE otherwise + * + * Since: 0.10.18 + */ +gboolean +gst_netaddress_equal (const GstNetAddress * naddr1, + const GstNetAddress * naddr2) +{ + g_return_val_if_fail (naddr1 != NULL, FALSE); + g_return_val_if_fail (naddr2 != NULL, FALSE); + + if (naddr1->type != naddr2->type) + return FALSE; + + if (naddr1->port != naddr2->port) + return FALSE; + + switch (naddr1->type) { + case GST_NET_TYPE_IP4: + if (naddr1->address.ip4 != naddr2->address.ip4) + return FALSE; + break; + case GST_NET_TYPE_IP6: + if (memcmp (naddr1->address.ip6, naddr2->address.ip6, + sizeof (naddr1->address.ip6))) + return FALSE; + break; + default: + break; + } + return TRUE; +} + +/** + * gst_netaddress_to_string: + * @naddr: a #GstNetAddress + * @dest: destination + * @len: len of @dest + * + * Copies a string representation of @naddr into @dest. Up to @len bytes are + * copied. + * + * Returns: the number of bytes which would be produced if the buffer was large + * enough + * + * Since: 0.10.24 + */ +gint +gst_netaddress_to_string (const GstNetAddress * naddr, gchar * dest, gulong len) +{ + gint result; + + g_return_val_if_fail (naddr != NULL, FALSE); + g_return_val_if_fail (dest != NULL, FALSE); + + switch (naddr->type) { + case GST_NET_TYPE_IP4: + { + guint32 address; + guint16 port; + + gst_netaddress_get_ip4_address (naddr, &address, &port); + address = g_ntohl (address); + + result = g_snprintf (dest, len, "%d.%d.%d.%d:%d", (address >> 24) & 0xff, + (address >> 16) & 0xff, (address >> 8) & 0xff, address & 0xff, + g_ntohs (port)); + break; + } + case GST_NET_TYPE_IP6: + { + guint8 address[16]; + guint16 port; + + gst_netaddress_get_ip6_address (naddr, address, &port); + + result = + g_snprintf (dest, len, "[%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x]:%d", + (address[0] << 8) | address[1], (address[2] << 8) | address[3], + (address[4] << 8) | address[5], (address[6] << 8) | address[7], + (address[8] << 8) | address[9], (address[10] << 8) | address[11], + (address[12] << 8) | address[13], (address[14] << 8) | address[15], + g_ntohs (port)); + break; + } + default: + dest[0] = 0; + result = 0; + break; + } + return result; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.h new file mode 100644 index 0000000..91770e4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/netbuffer/gstnetbuffer.h @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_NETBUFFER_H__ +#define __GST_NETBUFFER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstNetBuffer GstNetBuffer; +typedef struct _GstNetBufferClass GstNetBufferClass; +typedef struct _GstNetAddress GstNetAddress; + +#define GST_TYPE_NETBUFFER (gst_netbuffer_get_type()) +#define GST_IS_NETBUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_NETBUFFER)) +#define GST_IS_NETBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_NETBUFFER)) +#define GST_NETBUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_NETBUFFER, GstNetBufferClass)) +#define GST_NETBUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_NETBUFFER, GstNetBuffer)) +#define GST_NETBUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_NETBUFFER, GstNetBufferClass)) + +/** + * GstNetType: + * @GST_NET_TYPE_UNKNOWN: unknown address type + * @GST_NET_TYPE_IP4: an IPv4 address type + * @GST_NET_TYPE_IP6: and IPv6 address type + * + * The Address type used in #GstNetAddress. + */ +typedef enum { + GST_NET_TYPE_UNKNOWN, + GST_NET_TYPE_IP4, + GST_NET_TYPE_IP6, +} GstNetType; + +/** + * GST_NETADDRESS_MAX_LEN: + * + * The maximum length of a string representation of a GstNetAddress as produced + * by gst_netaddress_to_string(). + * + * Since: 0.10.24 + */ +#define GST_NETADDRESS_MAX_LEN 64 + +/** + * GstNetAddress: + * + * An opaque network address as used in #GstNetBuffer. + */ +struct _GstNetAddress { + /*< private >*/ + GstNetType type; + union { + guint8 ip6[16]; + guint32 ip4; + } address; + guint16 port; + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/** + * GstNetBuffer: + * @buffer: the parent #GstBuffer + * @from: the address where this buffer came from. + * @to: the address where this buffer should go to. + * + * buffer for use in network sources and sinks. + * It contains the source or destination address of the buffer. + */ +struct _GstNetBuffer { + GstBuffer buffer; + + GstNetAddress from; + GstNetAddress to; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstNetBufferClass { + GstBufferClass buffer_class; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +/* creating buffers */ +GType gst_netbuffer_get_type (void); + +GstNetBuffer* gst_netbuffer_new (void); + +/* address operations */ +void gst_netaddress_set_ip4_address (GstNetAddress *naddr, guint32 address, guint16 port); +void gst_netaddress_set_ip6_address (GstNetAddress *naddr, guint8 address[16], guint16 port); +gint gst_netaddress_set_address_bytes (GstNetAddress *naddr, GstNetType type, + guint8 address[16], guint16 port); + +GstNetType gst_netaddress_get_net_type (const GstNetAddress *naddr); +gboolean gst_netaddress_get_ip4_address (const GstNetAddress *naddr, guint32 *address, guint16 *port); +gboolean gst_netaddress_get_ip6_address (const GstNetAddress *naddr, guint8 address[16], guint16 *port); +gint gst_netaddress_get_address_bytes (const GstNetAddress *naddr, guint8 address[16], guint16 *port); + +gboolean gst_netaddress_equal (const GstNetAddress *naddr1, + const GstNetAddress *naddr2); + +gint gst_netaddress_to_string (const GstNetAddress *naddr, gchar *dest, gulong len); + +G_END_DECLS + +#endif /* __GST_NETBUFFER_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/.gitignore new file mode 100644 index 0000000..71267e4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/.gitignore @@ -0,0 +1,4 @@ +pbutils-enumtypes.c +pbutils-enumtypes.h +pbutils-marshal.c +pbutils-marshal.h diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/Makefile.am new file mode 100644 index 0000000..fab6523 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/Makefile.am @@ -0,0 +1,136 @@ +lib_LTLIBRARIES = libgstpbutils-@GST_MAJORMINOR@.la + +headers_pbutils = \ + pbutils.h \ + codec-utils.h \ + descriptions.h \ + encoding-profile.h \ + encoding-target.h \ + install-plugins.h \ + missing-plugins.h \ + gstdiscoverer.h + +# variables used for enum/marshal generation +glib_enum_headers = $(headers_pbutils) +glib_enum_define = PB_UTILS +glib_gen_prefix = pbutils +glib_gen_basename = pbutils + +built_headers_configure = \ + gstpluginsbaseversion.h + +libgstpbutils_@GST_MAJORMINOR@_la_SOURCES = \ + gstpluginsbaseversion.c \ + pbutils.c \ + codec-utils.c \ + descriptions.c \ + encoding-profile.c \ + encoding-target.c \ + install-plugins.c \ + missing-plugins.c \ + gstdiscoverer.c \ + gstdiscoverer-types.c + +nodist_libgstpbutils_@GST_MAJORMINOR@_la_SOURCES = \ + pbutils-enumtypes.c \ + pbutils-marshal.c + +libgstpbutils_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/pbutils +libgstpbutils_@GST_MAJORMINOR@include_HEADERS = \ + $(headers_pbutils) +nodist_libgstpbutils_@GST_MAJORMINOR@include_HEADERS = \ + $(built_headers_configure) \ + pbutils-enumtypes.h +noinst_HEADERS = \ + pbutils-private.h +EXTRA_DIST = pbutils-marshal.list + +libgstpbutils_@GST_MAJORMINOR@_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +libgstpbutils_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstpbutils_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +BUILT_SOURCES = \ + pbutils-enumtypes.c \ + pbutils-enumtypes.h \ + pbutils-marshal.c \ + pbutils-marshal.h + +CLEANFILES = $(BUILT_SOURCES) + +# DISTCLEANFILES is for files generated by configure +DISTCLEANFILES = $(built_headers_configure) + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstPbutils-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstpbutils_@GST_MAJORMINOR@include_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstpbutils_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstpbutils_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstpbutils_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/pbutils/%',$(libgstpbutils_@GST_MAJORMINOR@include_HEADERS)) +gir_cincludes+=$(patsubst %,--c-include='gst/pbutils/%',$(nodist_libgstpbutils_@GST_MAJORMINOR@include_HEADERS)) + +GstPbutils-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstpbutils-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstPbutils \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + --add-include-path=$(srcdir)/../video \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstpbutils-@GST_MAJORMINOR@.la \ + --library-path=`$(PKG_CONFIG) --variable=libdir gstreamer-@GST_MAJORMINOR@` \ + --library=gstreamer-@GST_MAJORMINOR@ \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-video-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-pbutils-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(srcdir)/../video \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstpbutils -:SHARED libgstpbutils-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstpbutils_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstpbutils_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstpbutils_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstpbutils_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstpbutils_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/pbutils \ + -:HEADERS $(libgstpbutils_@GST_MAJORMINOR@include_HEADERS) \ + $(nodist_libgstpbutils_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.c new file mode 100644 index 0000000..f885fe1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.c @@ -0,0 +1,767 @@ +/* GStreamer base utils library codec-specific utility functions + * Copyright (C) 2010 Arun Raghavan + * 2010 Collabora Multimedia + * 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpbutilscodecutils + * @short_description: Miscellaneous codec-specific utility functions + * + * + * + * Provides codec-specific ulility functions such as functions to provide the + * codec profile and level in human-readable string form from header data. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pbutils.h" + +#define GST_SIMPLE_CAPS_HAS_NAME(caps,name) \ + gst_structure_has_name(gst_caps_get_structure((caps),0),(name)) + +#define GST_SIMPLE_CAPS_HAS_FIELD(caps,field) \ + gst_structure_has_field(gst_caps_get_structure((caps),0),(field)) + +static const gchar * +digit_to_string (guint digit) +{ + static const char itoa[][2] = { + "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" + }; + + if (G_LIKELY (digit < 10)) + return itoa[digit]; + else + return NULL; +} + +/** + * gst_codec_utils_aac_get_sample_rate_from_index: + * @sr_idx: Sample rate index as from the AudioSpecificConfig (MPEG-4 + * container) or ADTS frame header + * + * Translates the sample rate index found in AAC headers to the actual sample + * rate. + * + * Returns: The sample rate if @sr_idx is valid, 0 otherwise. + * + * Since: 0.10.31 + */ +guint +gst_codec_utils_aac_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 (G_LIKELY (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_codec_utils_aac_get_profile: + * @audio_config: a pointer to the AudioSpecificConfig as specified in the + * Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see + * gst_codec_utils_aac_get_level() for a more details). + * @len: Length of @audio_config in bytes + * + * Returns the profile of the given AAC stream as a string. The profile is + * determined using the AudioObjectType field which is in the first 5 bits of + * @audio_config. + * + * + * HE-AAC support has not yet been implemented. + * + * + * Returns: The profile as a const string and %NULL if the profile could not be + * determined. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len) +{ + guint profile; + + if (len < 1) + return NULL; + + GST_MEMDUMP ("audio config", audio_config, len); + + profile = audio_config[0] >> 3; + switch (profile) { + case 1: + return "main"; + case 2: + return "lc"; + case 3: + return "ssr"; + case 4: + return "ltp"; + default: + break; + } + + GST_DEBUG ("Invalid profile idx: %u", profile); + return NULL; +} + +/** + * gst_codec_utils_aac_get_level: + * @audio_config: a pointer to the AudioSpecificConfig as specified in the + * Elementary Stream Descriptor (esds) in ISO/IEC 14496-1. + * @len: Length of @audio_config in bytes + * + * Determines the level of a stream as defined in ISO/IEC 14496-3. For AAC LC + * streams, the constraints from the AAC audio profile are applied. For AAC + * Main, LTP, SSR and others, the Main profile is used. + * + * The @audio_config parameter follows the following format, starting from the + * most significant bit of the first byte: + * + * + * + * Bit 0:4 contains the AudioObjectType + * + * + * Bit 5:8 contains the sample frequency index (if this is 0xf, then the + * next 24 bits define the actual sample frequency, and subsequent + * fields are appropriately shifted). + * + * + * Bit 9:12 contains the channel configuration + * + * + * + * + * HE-AAC support has not yet been implemented. + * + * + * Returns: The level as a const string and %NULL if the level could not be + * determined. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len) +{ + int profile, sr_idx, channel_config, rate; + /* Number of single channel elements, channel pair elements, low frequency + * elements, independently switched coupling channel elements, and + * dependently switched coupling channel elements. + * + * Note: The 2 CCE types are ignored for now as they require us to actually + * parse the first frame, and they are rarely found in actual streams. + */ + int num_sce = 0, num_cpe = 0, num_lfe = 0, num_cce_indep = 0, num_cce_dep = 0; + int num_channels; + /* Processor and RAM Complexity Units (calculated and "reference" for single + * channel) */ + int pcu, rcu, pcu_ref, rcu_ref; + int ret = -1; + + g_return_val_if_fail (audio_config != NULL, NULL); + + if (len < 2) + return NULL; + + GST_MEMDUMP ("audio config", audio_config, len); + + profile = audio_config[0] >> 3; + /* FIXME: add support for sr_idx = 0xf */ + sr_idx = ((audio_config[0] & 0x7) << 1) | ((audio_config[1] & 0x80) >> 7); + rate = gst_codec_utils_aac_get_sample_rate_from_index (sr_idx); + channel_config = (audio_config[1] & 0x7f) >> 3; + + if (rate == 0) + return NULL; + + switch (channel_config) { + case 0: + /* Channel config is defined in the AudioObjectType's SpecificConfig, + * which requires some amount of digging through the headers. I only see + * this done in the MPEG conformance streams - FIXME */ + GST_WARNING ("Found a stream with channel configuration in the " + "AudioSpecificConfig. Please file a bug with a link to the media if " + "possible."); + return NULL; + case 1: + /* front center */ + num_sce = 1; + break; + case 2: + /* front left and right */ + num_cpe = 1; + break; + case 3: + /* front left, right, and center */ + num_sce = 1; + num_cpe = 1; + break; + case 4: + /* front left, right, and center; rear surround */ + num_sce = 2; + num_cpe = 1; + break; + case 5: + /* front left, right, and center; rear left and right surround */ + num_sce = 1; + num_cpe = 2; + break; + case 6: + /* front left, right, center and LFE; rear left and right surround */ + num_sce = 1; + num_cpe = 2; + break; + case 7: + /* front left, right, center and LFE; outside front left and right; + * rear left and right surround */ + num_sce = 1; + num_cpe = 3; + num_lfe = 1; + break; + default: + GST_WARNING ("Unknown channel config in header: %d", channel_config); + return NULL; + } + + switch (profile) { + case 0: /* NULL */ + GST_WARNING ("profile 0 is not a valid profile"); + return NULL; + case 2: /* LC */ + pcu_ref = 3; + rcu_ref = 3; + break; + case 3: /* SSR */ + pcu_ref = 4; + rcu_ref = 3; + break; + case 4: /* LTP */ + pcu_ref = 4; + rcu_ref = 4; + break; + case 1: /* Main */ + default: + /* Other than a couple of ER profiles, Main is the worst-case */ + pcu_ref = 5; + rcu_ref = 5; + break; + } + + /* "fs_ref" is 48000 Hz for AAC Main/LC/SSR/LTP. SBR's fs_ref is defined as + * 24000/48000 (in/out), for SBR streams. Actual support is a FIXME */ + + pcu = ((float) rate / 48000) * pcu_ref * + ((2 * num_cpe) + num_sce + num_lfe + num_cce_indep + (0.3 * num_cce_dep)); + + rcu = ((float) rcu_ref) * (num_sce + (0.5 * num_lfe) + (0.5 * num_cce_indep) + + (0.4 * num_cce_dep)); + + if (num_cpe < 2) + rcu += (rcu_ref + (rcu_ref - 1)) * num_cpe; + else + rcu += (rcu_ref + (rcu_ref - 1) * ((2 * num_cpe) - 1)); + + num_channels = num_sce + (2 * num_cpe) + num_lfe; + + if (profile == 2) { + /* AAC LC => return the level as per the 'AAC Profile' */ + if (num_channels <= 2 && rate <= 24000 && pcu <= 3 && rcu <= 5) + ret = 1; + else if (num_channels <= 2 && rate <= 48000 && pcu <= 6 && rcu <= 5) + ret = 2; + /* There is no level 3 for the AAC Profile */ + else if (num_channels <= 5 && rate <= 48000 && pcu <= 19 && rcu <= 15) + ret = 4; + else if (num_channels <= 5 && rate <= 96000 && pcu <= 38 && rcu <= 15) + ret = 5; + } else { + /* Return the level as per the 'Main Profile' */ + if (pcu < 40 && rcu < 20) + ret = 1; + else if (pcu < 80 && rcu < 64) + ret = 2; + else if (pcu < 160 && rcu < 128) + ret = 3; + else if (pcu < 320 && rcu < 256) + ret = 4; + } + + if (ret == -1) { + GST_WARNING ("couldn't determine level: profile=%u, rate=%u, " + "channel_config=%u, pcu=%d,rcu=%d", profile, rate, channel_config, pcu, + rcu); + return NULL; + } else { + return digit_to_string (ret); + } +} + +/** + * gst_codec_utils_aac_caps_set_level_and_profile: + * @caps: the #GstCaps to which level and profile fields are to be added + * @audio_config: a pointer to the AudioSpecificConfig as specified in the + * Elementary Stream Descriptor (esds) in ISO/IEC 14496-1 (see + * below for a more details). + * @len: Length of @audio_config in bytes + * + * Sets the level and profile on @caps if it can be determined from + * @audio_config. See gst_codec_utils_aac_get_level() and + * gst_codec_utils_aac_get_profile() for more details on the parameters. + * @caps must be audio/mpeg caps with an "mpegversion" field of either 2 or 4. + * If mpegversion is 4, the "base-profile" field is also set in @caps. + * + * Returns: %TRUE if the level and profile could be set, %FALSE otherwise. + * + * Since: 0.10.31 + */ +gboolean +gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps, + const guint8 * audio_config, guint len) +{ + GstStructure *s; + const gchar *level, *profile; + int mpegversion = 0; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE); + g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "audio/mpeg"), FALSE); + g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_FIELD (caps, "mpegversion"), FALSE); + g_return_val_if_fail (audio_config != NULL, FALSE); + + s = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (s, "mpegversion", &mpegversion); + g_return_val_if_fail (mpegversion == 2 || mpegversion == 4, FALSE); + + level = gst_codec_utils_aac_get_level (audio_config, len); + + if (level != NULL) + gst_structure_set (s, "level", G_TYPE_STRING, level, NULL); + + profile = gst_codec_utils_aac_get_profile (audio_config, len); + + if (profile != NULL) { + if (mpegversion == 4) { + gst_structure_set (s, "base-profile", G_TYPE_STRING, profile, + "profile", G_TYPE_STRING, profile, NULL); + } else { + gst_structure_set (s, "profile", G_TYPE_STRING, profile, NULL); + } + } + + GST_LOG ("profile : %s", (profile) ? profile : "---"); + GST_LOG ("level : %s", (level) ? level : "---"); + + return (level != NULL && profile != NULL); +} + +/** + * gst_codec_utils_h264_get_profile: + * @sps: Pointer to the sequence parameter set for the stream. + * @len: Length of the data available in @sps. + * + * Converts the profile indication (profile_idc) in the stream's + * sequence parameter set into a string. The SPS is expected to have the + * following format, as defined in the H.264 specification. The SPS is viewed + * as a bitstream here, with bit 0 being the most significant bit of the first + * byte. + * + * + * Bit 0:7 - Profile indication + * Bit 8 - constraint_set0_flag + * Bit 9 - constraint_set1_flag + * Bit 10 - constraint_set2_flag + * Bit 11 - constraint_set3_flag + * Bit 12 - constraint_set3_flag + * Bit 13:15 - Reserved + * Bit 16:24 - Level indication + * + * + * Returns: The profile as a const string, or %NULL if there is an error. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_h264_get_profile (const guint8 * sps, guint len) +{ + const gchar *profile = NULL; + gint csf1, csf3; + + g_return_val_if_fail (sps != NULL, NULL); + + if (len < 2) + return NULL; + + GST_MEMDUMP ("SPS", sps, len); + + csf1 = (sps[1] & 0x40) >> 6; + csf3 = (sps[1] & 0x10) >> 4; + + switch (sps[0]) { + case 66: + if (csf1) + profile = "constrained-baseline"; + else + profile = "baseline"; + break; + case 77: + profile = "main"; + break; + case 88: + profile = "extended"; + break; + case 100: + profile = "high"; + break; + case 110: + if (csf3) + profile = "high-10-intra"; + else + profile = "high-10"; + break; + case 122: + if (csf3) + profile = "high-4:2:2-intra"; + else + profile = "high-4:2:2"; + break; + case 244: + if (csf3) + profile = "high-4:4:4-intra"; + else + profile = "high-4:4:4"; + break; + case 44: + profile = "cavlc-4:4:4-intra"; + break; + default: + return NULL; + } + + return profile; +} + +/** + * gst_codec_utils_h264_get_level: + * @sps: Pointer to the sequence parameter set for the stream. + * @len: Length of the data available in @sps. + * + * Converts the level indication (level_idc) in the stream's + * sequence parameter set into a string. The SPS is expected to have the + * same format as for gst_codec_utils_h264_get_profile(). + * + * Returns: The level as a const string, or %NULL if there is an error. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_h264_get_level (const guint8 * sps, guint len) +{ + gint csf3; + + g_return_val_if_fail (sps != NULL, NULL); + + if (len < 3) + return NULL; + + GST_MEMDUMP ("SPS", sps, len); + + csf3 = (sps[1] & 0x10) >> 4; + + if (sps[2] == 11 && csf3) + return "1b"; + else if (sps[2] % 10 == 0) + return digit_to_string (sps[2] / 10); + else { + switch (sps[2]) { + case 11: + return "1.1"; + case 12: + return "1.2"; + case 13: + return "1.3"; + case 21: + return "2.1"; + case 22: + return "2.2"; + case 31: + return "3.1"; + case 32: + return "3.2"; + case 41: + return "4.1"; + case 42: + return "4.2"; + case 51: + return "5.1"; + default: + return NULL; + } + } +} + +/** + * gst_codec_utils_h264_caps_set_level_and_profile: + * @caps: the #GstCaps to which the level and profile are to be added + * @sps: Pointer to the sequence parameter set for the stream. + * @len: Length of the data available in @sps. + * + * Sets the level and profile in @caps if it can be determined from @sps. See + * gst_codec_utils_h264_get_level() and gst_codec_utils_h264_get_profile() + * for more details on the parameters. + * + * Returns: %TRUE if the level and profile could be set, %FALSE otherwise. + * + * Since: 0.10.31 + */ +gboolean +gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps, + const guint8 * sps, guint len) +{ + const gchar *level, *profile; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE); + g_return_val_if_fail (GST_SIMPLE_CAPS_HAS_NAME (caps, "video/x-h264"), FALSE); + g_return_val_if_fail (sps != NULL, FALSE); + + level = gst_codec_utils_h264_get_level (sps, len); + + if (level != NULL) + gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL); + + profile = gst_codec_utils_h264_get_profile (sps, len); + + if (profile != NULL) + gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL); + + GST_LOG ("profile : %s", (profile) ? profile : "---"); + GST_LOG ("level : %s", (level) ? level : "---"); + + return (level != NULL && profile != NULL); +} + +/** + * gst_codec_utils_mpeg4video_get_profile: + * @vis_obj_seq: Pointer to the visual object sequence for the stream. + * @len: Length of the data available in @sps. + * + * Converts the profile indication in the stream's visual object sequence into + * a string. @vis_obj_seq is expected to be the data following the visual + * object sequence start code. Only the first byte + * (profile_and_level_indication) is used. + * + * Returns: The profile as a const string, or NULL if there is an error. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_mpeg4video_get_profile (const guint8 * vis_obj_seq, guint len) +{ + /* The profile/level codes are from 14496-2, table G-1, and the Wireshark + * sources: epan/dissectors/packet-mp4ves.c */ + + /* These are a direct mapping from the integer profile id -> string. Profiles + * 0x6, 0xe and 0xf can correspond to more than one profile depending on the + * second 4 bits of vis_obj_seq[0], so they are handled separately. */ + static const char *profiles[] = { "simple", "simple-scalable", "core", + "main", "n-bit", "scalable", NULL, "basic-animated-texture", "hybrid", + "advanced-real-time-simple", "core-scalable", "advanced-coding-efficiency", + "advanced-core", "advanced-scalable-texture", + }; + int profile_id, level_id; + + g_return_val_if_fail (vis_obj_seq != NULL, NULL); + + if (len < 1) + return NULL; + + GST_MEMDUMP ("VOS", vis_obj_seq, len); + + profile_id = vis_obj_seq[0] >> 4; + level_id = vis_obj_seq[0] & 0xf; + + GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id); + + if (profile_id != 6 && profile_id < 0xe) + return profiles[profile_id]; + + if (profile_id != 0xf && level_id == 0) + return NULL; + + switch (profile_id) { + case 0x6: + if (level_id < 3) + return "simple-face"; + else if (level_id < 5) + return "simple-fba"; + break; + + case 0xe: + if (level_id < 5) + return "simple-studio"; + else if (level_id < 9) + return "core-studio"; + break; + + case 0xf: + if (level_id < 6) + return "advanced-simple"; + else if (level_id > 7 && level_id < 0xe) + return "fine-granularity-scalable"; + break; + } + + return NULL; +} + +/** + * gst_codec_utils_mpeg4video_get_level: + * @vis_obj_seq: Pointer to the visual object sequence for the stream. + * @len: Length of the data available in @sps. + * + * Converts the level indication in the stream's visual object sequence into + * a string. @vis_obj_seq is expected to be the data following the visual + * object sequence start code. Only the first byte + * (profile_and_level_indication) is used. + * + * Returns: The level as a const string, or NULL if there is an error. + * + * Since: 0.10.31 + */ +const gchar * +gst_codec_utils_mpeg4video_get_level (const guint8 * vis_obj_seq, guint len) +{ + /* The profile/level codes are from 14496-2, table G-1, and the Wireshark + * sources: epan/dissectors/packet-mp4ves.c + * + * Each profile has a different maximum level it defines. Some of them still + * need special case handling, because not all levels start from 1, and the + * Simple profile defines an intermediate level as well. */ + static const int level_max[] = { 3, 2, 2, 4, 2, 1, 2, 2, 2, 4, 3, 4, 2, 3, 4, + 5 + }; + int profile_id, level_id; + + g_return_val_if_fail (vis_obj_seq != NULL, NULL); + + if (len < 1) + return NULL; + + GST_MEMDUMP ("VOS", vis_obj_seq, len); + + profile_id = vis_obj_seq[0] >> 4; + level_id = vis_obj_seq[0] & 0xf; + + GST_LOG ("profile_id = %d, level_id = %d", profile_id, level_id); + + if (profile_id != 0xf && level_id == 0) + return NULL; + + /* Let's do some validation of the level */ + switch (profile_id) { + case 0x3: + if (level_id == 1) + return NULL; + break; + + case 0x4: + if (level_id != 2) + return NULL; + break; + + case 0x6: + if (level_id > 5) + return NULL; + break; + + case 0xe: + if (level_id > 9) + return NULL; + break; + + case 0xf: + if (level_id == 7 && level_id > 0xd) + return NULL; + break; + } + + if (profile_id == 0 && level_id == 8) + /* Simple Profile / Level 0 */ + return "0"; + else if (profile_id == 0 && level_id == 9) + /* Simple Profile / Level 0b */ + return "0b"; + else if (level_id <= level_max[profile_id]) + /* Levels for all other cases */ + return digit_to_string (level_id); + + return NULL; +} + +/** + * gst_codec_utils_mpeg4video_caps_set_level_and_profile: + * @caps: the #GstCaps to which the level and profile are to be added + * @vis_obj_seq: Pointer to the visual object sequence for the stream. + * @len: Length of the data available in @sps. + * + * Sets the level and profile in @caps if it can be determined from + * @vis_obj_seq. See gst_codec_utils_mpeg4video_get_level() and + * gst_codec_utils_mpeg4video_get_profile() for more details on the + * parameters. + * + * Returns: %TRUE if the level and profile could be set, %FALSE otherwise. + * + * Since: 0.10.31 + */ +gboolean +gst_codec_utils_mpeg4video_caps_set_level_and_profile (GstCaps * caps, + const guint8 * vis_obj_seq, guint len) +{ + const gchar *profile, *level; + + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), FALSE); + g_return_val_if_fail (vis_obj_seq != NULL, FALSE); + + profile = gst_codec_utils_mpeg4video_get_profile (vis_obj_seq, len); + + if (profile != NULL) + gst_caps_set_simple (caps, "profile", G_TYPE_STRING, profile, NULL); + + level = gst_codec_utils_mpeg4video_get_level (vis_obj_seq, len); + + if (level != NULL) + gst_caps_set_simple (caps, "level", G_TYPE_STRING, level, NULL); + + GST_LOG ("profile : %s", (profile) ? profile : "---"); + GST_LOG ("level : %s", (level) ? level : "---"); + + return (profile != NULL && level != NULL); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.h new file mode 100644 index 0000000..ae5a68b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/codec-utils.h @@ -0,0 +1,63 @@ +/* GStreamer base utils library codec-specific utility functions + * Copyright (C) 2010 Arun Raghavan + * 2010 Collabora Multimedia + * 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PB_UTILS_CODEC_UTILS_H__ +#define __GST_PB_UTILS_CODEC_UTILS_H__ + +#include + +G_BEGIN_DECLS + +/* AAC */ + +guint gst_codec_utils_aac_get_sample_rate_from_index (guint sr_idx); + +const gchar * gst_codec_utils_aac_get_profile (const guint8 * audio_config, guint len); + +const gchar * gst_codec_utils_aac_get_level (const guint8 * audio_config, guint len); + +gboolean gst_codec_utils_aac_caps_set_level_and_profile (GstCaps * caps, + const guint8 * audio_config, + guint len); + +/* H.264 */ + +const gchar * gst_codec_utils_h264_get_profile (const guint8 * sps, guint len); + +const gchar * gst_codec_utils_h264_get_level (const guint8 * sps, guint len); + +gboolean gst_codec_utils_h264_caps_set_level_and_profile (GstCaps * caps, + const guint8 * sps, + guint len); + +/* MPEG-4 part 2 */ + +const gchar * gst_codec_utils_mpeg4video_get_profile (const guint8 * vis_obj_seq, guint len); + +const gchar * gst_codec_utils_mpeg4video_get_level (const guint8 * vis_obj_seq, guint len); + +gboolean gst_codec_utils_mpeg4video_caps_set_level_and_profile (GstCaps * caps, + const guint8 * vis_obj_seq, + guint len); + +G_END_DECLS + +#endif /* __GST_PB_UTILS_CODEC_UTILS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.c new file mode 100644 index 0000000..c32e3d9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.c @@ -0,0 +1,1013 @@ +/* GStreamer Plugins Base utils library source/sink/codec description support + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpbutilsdescriptions + * @short_description: Provides human-readable descriptions for caps/codecs + * and encoder, decoder, URI source and URI sink elements + * + * + * + * The above functions provide human-readable strings for media formats + * and decoder/demuxer/depayloader/encoder/muxer/payloader elements for use + * in error dialogs or other messages shown to users. + * + * + * gst_pb_utils_add_codec_description_to_tag_list() is a utility function + * for demuxer and decoder elements to add audio/video codec tags from a + * given (fixed) #GstCaps. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst/gst-i18n-plugin.h" + +#include "pbutils.h" +#include "pbutils-private.h" + +#include + +typedef enum +{ + FLAG_CONTAINER = (1 << 0), /* format is a container format (muxed) */ + FLAG_SYSTEMSTREAM = (1 << 1) /* match record only if caps have systemstream=true */ +} FormatFlags; + +typedef struct +{ + const gchar *type; + const gchar *desc; + FormatFlags flags; +} FormatInfo; + +static const FormatInfo formats[] = { + /* container/tag formats with static descriptions */ + {"application/gxf", "General Exchange Format (GXF)", FLAG_CONTAINER}, + {"application/ogg", "Ogg", FLAG_CONTAINER}, + {"application/mxf", "Material eXchange Format (MXF)", FLAG_CONTAINER}, + {"application/vnd.rn-realmedia", "Realmedia", FLAG_CONTAINER}, + {"application/x-annodex", "Ogg", FLAG_CONTAINER}, + {"application/x-id3", N_("ID3 tag"), FLAG_CONTAINER}, + {"application/x-ape", N_("APE tag"), FLAG_CONTAINER}, + {"application/x-apetag", N_("APE tag"), FLAG_CONTAINER}, + {"application/x-icy", N_("ICY internet radio"), FLAG_CONTAINER}, + {"application/x-3gp", "3GP", FLAG_CONTAINER}, + {"application/x-pn-realaudio", "RealAudio", FLAG_CONTAINER}, + {"application/x-yuv4mpeg", "Y4M", FLAG_CONTAINER}, + {"multipart/x-mixed-replace", "Multipart", FLAG_CONTAINER}, + {"video/x-fli", "FLI/FLC/FLX Animation", FLAG_CONTAINER}, + {"video/x-flv", "Flash", FLAG_CONTAINER}, + {"video/x-matroska", "Matroska", FLAG_CONTAINER}, + {"video/webm", "WebM", FLAG_CONTAINER}, + {"video/x-ms-asf", "Advanced Streaming Format (ASF)", FLAG_CONTAINER}, + {"video/x-msvideo", "Audio Video Interleave (AVI)", FLAG_CONTAINER}, + {"video/x-quicktime", "Quicktime", FLAG_CONTAINER}, + {"video/quicktime", "Quicktime", FLAG_CONTAINER}, + {"video/mj2", "Motion JPEG 2000", FLAG_CONTAINER}, + + /* audio formats with static descriptions */ + {"audio/x-ac3", "AC-3 (ATSC A/52)", 0}, + {"audio/ac3", "AC-3 (ATSC A/52)", 0}, + {"audio/x-private-ac3", "DVD AC-3 (ATSC A/52)", 0}, + {"audio/x-private1-ac3", "DVD AC-3 (ATSC A/52)", 0}, + {"audio/x-alaw", "A-Law", 0}, + {"audio/amr", "Adaptive Multi Rate (AMR)", 0}, + {"audio/AMR", "Adaptive Multi Rate (AMR)", 0}, + {"audio/AMR-WB", "Adaptive Multi Rate WideBand (AMR-WB)", 0}, + {"audio/iLBC-sh", "Internet Low Bitrate Codec (iLBC)", 0}, + {"audio/ms-gsm", "MS GSM", 0}, + {"audio/qcelp", "QCELP", 0}, + {"audio/aiff", "Audio Interchange File Format (AIFF)", 0}, + {"audio/x-aiff", "Audio Interchange File Format (AIFF)", 0}, + {"audio/x-alac", N_("Apple Lossless Audio (ALAC)"), 0}, + {"audio/x-amr-nb-sh", "Adaptive Multi Rate NarrowBand (AMR-NB)", 0}, + {"audio/x-amr-wb-sh", "Adaptive Multi Rate WideBand (AMR-WB)", 0}, + {"audio/x-au", "Sun .au", 0}, + {"audio/x-celt", "Constrained Energy Lapped Transform (CELT)", 0}, + {"audio/x-cinepak", "Cinepak Audio", 0}, + {"audio/x-dpcm", "DPCM", 0}, + {"audio/x-dts", "DTS", 0}, + {"audio/x-private1-dts", "DTS", 0}, + {"audio/x-dv", "DV Audio", 0}, + {"audio/x-flac", N_("Free Lossless Audio Codec (FLAC)"), 0}, + {"audio/x-gsm", "GSM", 0}, + {"audio/x-iec958", "S/PDIF IEC958", 0}, /* TODO: check description */ + {"audio/x-iLBC", "Internet Low Bitrate Codec (iLBC)", 0}, + {"audio/x-ircam", "Berkeley/IRCAM/CARL", 0}, + {"audio/x-lpcm", "LPCM", 0}, + {"audio/x-private1-lpcm", "DVD LPCM", 0}, + {"audio/x-m4a", "MPEG-4 AAC", FLAG_CONTAINER}, + {"audio/x-mod", "Module Music Format (MOD)", 0}, + {"audio/x-mulaw", "Mu-Law", 0}, + {"audio/x-musepack", "Musepack (MPC)", 0}, + {"audio/x-nellymoser", "Nellymoser Asao", 0}, + {"audio/x-nist", "Sphere NIST", 0}, + {"audio/x-nsf", "Nintendo NSF", 0}, + {"audio/x-paris", "Ensoniq PARIS", 0}, + {"audio/x-qdm", "QDesign Music (QDM)", 0}, + {"audio/x-qdm2", "QDesign Music (QDM) 2", 0}, + {"audio/x-ralf-mpeg4-generic", "Real Audio Lossless (RALF)", 0}, + {"audio/x-sds", "SDS", 0}, + {"audio/x-shorten", "Shorten Lossless", 0}, + {"audio/x-sid", "Sid", 0}, + {"audio/x-sipro", "Sipro/ACELP.NET Voice", 0}, + {"audio/x-siren", "Siren", 0}, + {"audio/x-spc", "SNES-SPC700 Sound File Data", 0}, + {"audio/x-speex", "Speex", 0}, + {"audio/x-svx", "Amiga IFF / SVX8 / SV16", 0}, + {"audio/x-tta", N_("Lossless True Audio (TTA)"), 0}, + {"audio/x-ttafile", N_("Lossless True Audio (TTA)"), 0}, + {"audio/x-vnd.sony.atrac3", "Sony ATRAC3", 0}, + {"audio/x-vorbis", "Vorbis", 0}, + {"audio/x-voc", "SoundBlaster VOC", 0}, + {"audio/x-w64", "Sonic Foundry Wave64", 0}, + {"audio/x-wav", "WAV", 0}, + {"audio/x-wavpack", "Wavpack", 0}, + {"audio/x-wavpack-correction", "Wavpack", 0}, + {"audio/x-wms", N_("Windows Media Speech"), 0}, + {"audio/x-voxware", "Voxware", 0}, + + + /* video formats with static descriptions */ + {"video/sp5x", "Sunplus JPEG 5.x", 0}, + {"video/vivo", "Vivo", 0}, + {"video/x-3ivx", "3ivx", 0}, + {"video/x-4xm", "4X Techologies Video", 0}, + {"video/x-apple-video", "Apple video", 0}, + {"video/x-aasc", "Autodesk Animator", 0}, + {"video/x-camtasia", "TechSmith Camtasia", 0}, + {"video/x-cdxa", "RIFF/CDXA (VCD)", 0}, + {"video/x-cinepak", "Cinepak Video", 0}, + {"video/x-cirrus-logic-accupak", "Cirrus Logipak AccuPak", 0}, + {"video/x-compressed-yuv", N_("CYUV Lossless"), 0}, + {"video/x-dirac", "Dirac", 0}, + {"video/x-dnxhd", "Digital Nonlinear Extensible High Definition (DNxHD)", 0}, + /* FIXME 0.11: rename to subpicture/x-dvd or so */ + {"video/x-dvd-subpicture", "DVD subpicture", 0}, + {"video/x-ffv", N_("FFMpeg v1"), 0}, + {"video/x-flash-screen", "Flash Screen Video", 0}, + {"video/x-flash-video", "Sorenson Spark Video", 0}, + {"video/x-h261", "H.261", 0}, + {"video/x-huffyuv", "Huffyuv", 0}, + {"video/x-intel-h263", "Intel H.263", 0}, + {"video/x-jpeg", "Motion JPEG", 0}, + /* { "video/x-jpeg-b", "", 0 }, does this actually exist? */ + {"video/x-loco", "LOCO Lossless", 0}, + {"video/x-mimic", "MIMIC", 0}, + {"video/x-mjpeg", "Motion-JPEG", 0}, + {"video/x-mjpeg-b", "Motion-JPEG format B", 0}, + {"video/mpegts", "MPEG-2 Transport Stream", FLAG_CONTAINER}, + {"video/x-mng", "Multiple Image Network Graphics (MNG)", 0}, + {"video/x-mszh", N_("Lossless MSZH"), 0}, + {"video/x-msvideocodec", "Microsoft Video 1", 0}, + {"video/x-mve", "Interplay MVE", FLAG_CONTAINER}, + {"video/x-nut", "NUT", FLAG_CONTAINER}, + {"video/x-nuv", "MythTV NuppelVideo (NUV)", FLAG_CONTAINER}, + {"video/x-qdrw", "Apple QuickDraw", 0}, + {"video/x-raw-gray", N_("Uncompressed Gray Image"), 0}, + {"video/x-smc", "Apple SMC", 0}, + {"video/x-smoke", "Smoke", 0}, + {"video/x-tarkin", "Tarkin", 0}, + {"video/x-theora", "Theora", 0}, + {"video/x-rle", N_("Run-length encoding"), 0}, + {"video/x-ultimotion", "IBM UltiMotion", 0}, + {"video/x-vcd", "VideoCD (VCD)", 0}, + {"video/x-vmnc", "VMWare NC", 0}, + {"video/x-vp3", "On2 VP3", 0}, + {"video/x-vp5", "On2 VP5", 0}, + {"video/x-vp6", "On2 VP6", 0}, + {"video/x-vp6-flash", "On2 VP6/Flash", 0}, + {"video/x-vp6-alpha", "On2 VP6 with alpha", 0}, + {"video/x-vp7", "On2 VP7", 0}, + {"video/x-vp8", "VP8", 0}, + {"video/x-xvid", "XVID MPEG-4", 0}, + {"video/x-zlib", "Lossless zlib video", 0}, + {"video/x-zmbv", "Zip Motion Block video", 0}, + + /* image formats with static descriptions */ + {"image/bmp", "BMP", 0}, + {"image/x-bmp", "BMP", 0}, + {"image/x-MS-bmp", "BMP", 0}, + {"image/gif", "GIF", 0}, + {"image/jpeg", "JPEG", 0}, + {"image/jng", "JPEG Network Graphics (JNG)", 0}, + {"image/png", "PNG", 0}, + {"image/pbm", "Portable BitMap (PBM)", 0}, + {"image/ppm", "Portable PixMap (PPM)", 0}, + {"image/svg+xml", "Scalable Vector Graphics (SVG)", 0}, + {"image/tiff", "TIFF", 0}, + {"image/x-cmu-raster", "CMU Raster Format", 0}, + {"image/x-degas", "DEGAS", 0}, + {"image/x-icon", "ICO", 0}, + {"image/x-j2c", "JPEG 2000", 0}, + {"image/x-jpc", "JPEG 2000", 0}, + {"image/jp2", "JPEG 2000", 0}, + {"image/x-pcx", "PCX", 0}, + {"image/x-xcf", "XFC", 0}, + {"image/x-pixmap", "XPM", 0}, + {"image/x-portable-anymap", "Portable AnyMap (PAM)", 0}, + {"image/x-portable-graymap", "Portable GrayMap (PGM)", 0}, + {"image/x-xpixmap", "XPM", 0}, + {"image/x-quicktime", "QuickTime Image Format (QTIF)", 0}, + {"image/x-sun-raster", "Sun Raster Format (RAS)", 0}, + {"image/x-tga", "TGA", 0}, + + /* subtitle formats with static descriptions */ + {"application/x-ass", "ASS", 0}, + {"application/x-subtitle-sami", N_("Sami subtitle format"), 0}, + {"application/x-subtitle-tmplayer", N_("TMPlayer subtitle format"), 0}, + {"application/x-kate", "Kate", 0}, + {"subtitle/x-kate", N_("Kate subtitle format"), 0}, + {"subpicture/x-dvb", "DVB subtitles", 0}, + /* add variant field to typefinder? { "application/x-subtitle", N_("subtitle"), 0}, */ + + /* non-audio/video/container formats */ + {"hdv/aux-v", "HDV AUX-V", 0}, + {"hdv/aux-a", "HDV AUX-A", 0}, + + /* formats with dynamic descriptions */ + {"audio/mpeg", NULL, 0}, + {"audio/x-adpcm", NULL, 0}, + {"audio/x-mace", NULL, 0}, + {"audio/x-pn-realaudio", NULL, 0}, + {"audio/x-raw-int", NULL, 0}, + {"audio/x-raw-float", NULL, 0}, + {"audio/x-wma", NULL, 0}, + {"video/mpeg", NULL, FLAG_CONTAINER | FLAG_SYSTEMSTREAM}, + {"video/mpeg", NULL, 0}, + {"video/x-asus", NULL, 0}, + {"video/x-ati-vcr", NULL, 0}, + {"video/x-divx", NULL, 0}, + {"video/x-dv", "Digital Video (DV) System Stream", + FLAG_CONTAINER | FLAG_SYSTEMSTREAM}, + {"video/x-dv", "Digital Video (DV)", 0}, + {"video/x-h263", NULL, 0}, + {"video/x-h264", NULL, 0}, + {"video/x-indeo", NULL, 0}, + {"video/x-msmpeg", NULL, 0}, + {"video/x-pn-realvideo", NULL, 0}, +#if 0 + /* do these exist? are they used anywhere? */ + {"video/x-pn-multirate-realvideo", NULL, 0}, + {"audio/x-pn-multirate-realaudio", NULL, 0}, + {"audio/x-pn-multirate-realaudio-live", NULL, 0}, +#endif + {"video/x-truemotion", NULL, 0}, + {"video/x-raw-rgb", NULL, 0}, + {"video/x-raw-yuv", NULL, 0}, + {"video/x-svq", NULL, 0}, + {"video/x-wmv", NULL, 0}, + {"video/x-xan", NULL, 0} +}; + +/* returns static descriptions and dynamic ones (such as video/x-raw-yuv), + * or NULL if caps aren't known at all */ +static gchar * +format_info_get_desc (const FormatInfo * info, const GstCaps * caps) +{ + const GstStructure *s; + + g_assert (info != NULL); + + if (info->desc != NULL) + return g_strdup (_(info->desc)); + + s = gst_caps_get_structure (caps, 0); + + if (strcmp (info->type, "video/x-raw-yuv") == 0) { + const gchar *ret = NULL; + guint32 fourcc = 0; + + gst_structure_get_fourcc (s, "format", &fourcc); + switch (fourcc) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + ret = _("Uncompressed planar YUV 4:2:0"); + break; + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + ret = _("Uncompressed planar YVU 4:2:0"); + break; + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + ret = _("Uncompressed packed YUV 4:2:2"); + break; + case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'): + ret = _("Uncompressed packed YUV 4:1:0"); + break; + case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'): + ret = _("Uncompressed packed YVU 4:1:0"); + break; + case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + ret = _("Uncompressed packed YUV 4:2:2"); + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'P'): + ret = _("Uncompressed packed YUV 4:1:1"); + break; + case GST_MAKE_FOURCC ('I', 'Y', 'U', '2'): + ret = _("Uncompressed packed YUV 4:4:4"); + break; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + ret = _("Uncompressed planar YUV 4:2:2"); + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): + ret = _("Uncompressed planar YUV 4:1:1"); + break; + case GST_MAKE_FOURCC ('Y', '8', '0', '0'): + ret = _("Uncompressed black and white Y-plane"); + break; + default: + ret = _("Uncompressed YUV"); + break; + } + return g_strdup (ret); + } else if (strcmp (info->type, "video/x-raw-rgb") == 0) { + const gchar *rgb_str; + gint depth = 0; + + gst_structure_get_int (s, "depth", &depth); + rgb_str = gst_structure_has_field (s, "alpha_mask") ? "RGBA" : "RGB"; + if (gst_structure_has_field (s, "paletted_data")) { + return g_strdup_printf (_("Uncompressed palettized %d-bit %s"), depth, + rgb_str); + } else { + return g_strdup_printf ("Uncompressed %d-bit %s", depth, rgb_str); + } + } else if (strcmp (info->type, "video/x-h263") == 0) { + const gchar *variant, *ret; + + variant = gst_structure_get_string (s, "variant"); + if (variant == NULL) + ret = "H.263"; + else if (strcmp (variant, "itu") == 0) + ret = "ITU H.26n"; /* why not ITU H.263? (tpm) */ + else if (strcmp (variant, "lead") == 0) + ret = "Lead H.263"; + else if (strcmp (variant, "microsoft") == 0) + ret = "Microsoft H.263"; + else if (strcmp (variant, "vdolive") == 0) + ret = "VDOLive"; + else if (strcmp (variant, "vivo") == 0) + ret = "Vivo H.263"; + else if (strcmp (variant, "xirlink") == 0) + ret = "Xirlink H.263"; + else { + GST_WARNING ("Unknown H263 variant '%s'", variant); + ret = "H.263"; + } + return g_strdup (ret); + } else if (strcmp (info->type, "video/x-h264") == 0) { + const gchar *variant, *ret; + + variant = gst_structure_get_string (s, "variant"); + if (variant == NULL) + ret = "H.264"; + else if (strcmp (variant, "itu") == 0) + ret = "ITU H.264"; + else if (strcmp (variant, "videosoft") == 0) + ret = "Videosoft H.264"; + else if (strcmp (variant, "lead") == 0) + ret = "Lead H.264"; + else { + GST_WARNING ("Unknown H264 variant '%s'", variant); + ret = "H.264"; + } + return g_strdup (ret); + } else if (strcmp (info->type, "video/x-divx") == 0) { + gint ver = 0; + + if (!gst_structure_get_int (s, "divxversion", &ver) || ver <= 2) { + GST_WARNING ("Unexpected DivX version in %" GST_PTR_FORMAT, caps); + return g_strdup ("DivX MPEG-4"); + } + return g_strdup_printf (_("DivX MPEG-4 Version %d"), ver); + } else if (strcmp (info->type, "video/x-msmpeg") == 0) { + gint ver = 0; + + if (!gst_structure_get_int (s, "msmpegversion", &ver) || + ver < 40 || ver > 49) { + GST_WARNING ("Unexpected msmpegversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Microsoft MPEG-4 4.x"); + } + return g_strdup_printf ("Microsoft MPEG-4 4.%d", ver % 10); + } else if (strcmp (info->type, "video/x-truemotion") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "trueversion", &ver); + switch (ver) { + case 1: + return g_strdup_printf ("Duck TrueMotion 1"); + case 2: + return g_strdup_printf ("TrueMotion 2.0"); + default: + GST_WARNING ("Unexpected trueversion in %" GST_PTR_FORMAT, caps); + break; + } + return g_strdup_printf ("TrueMotion"); + } else if (strcmp (info->type, "video/x-xan") == 0) { + gint ver = 0; + + if (!gst_structure_get_int (s, "wcversion", &ver) || ver < 1) { + GST_WARNING ("Unexpected wcversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Xan Wing Commander"); + } + return g_strdup_printf ("Xan Wing Commander %u", ver); + } else if (strcmp (info->type, "video/x-indeo") == 0) { + gint ver = 0; + + if (!gst_structure_get_int (s, "indeoversion", &ver) || ver < 2) { + GST_WARNING ("Unexpected indeoversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Intel Indeo"); + } + return g_strdup_printf ("Intel Indeo %u", ver); + } else if (strcmp (info->type, "audio/x-wma") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "wmaversion", &ver); + switch (ver) { + case 1: + case 2: + case 3: + return g_strdup_printf ("Windows Media Audio %d", ver + 6); + default: + break; + } + GST_WARNING ("Unexpected wmaversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Windows Media Audio"); + } else if (strcmp (info->type, "video/x-wmv") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "wmvversion", &ver); + switch (ver) { + case 1: + case 2: + case 3: + return g_strdup_printf ("Windows Media Video %d", ver + 6); + default: + break; + } + GST_WARNING ("Unexpected wmvversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Windows Media Video"); + } else if (strcmp (info->type, "audio/x-mace") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "maceversion", &ver); + if (ver == 3 || ver == 6) { + return g_strdup_printf ("MACE-%d", ver); + } else { + GST_WARNING ("Unexpected maceversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("MACE"); + } + } else if (strcmp (info->type, "video/x-svq") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "svqversion", &ver); + if (ver == 1 || ver == 3) { + return g_strdup_printf ("Sorensen Video %d", ver); + } else { + GST_WARNING ("Unexpected svqversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Sorensen Video"); + } + } else if (strcmp (info->type, "video/x-asus") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "asusversion", &ver); + if (ver == 1 || ver == 2) { + return g_strdup_printf ("Asus Video %d", ver); + } else { + GST_WARNING ("Unexpected asusversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("Asus Video"); + } + } else if (strcmp (info->type, "video/x-ati-vcr") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "vcrversion", &ver); + if (ver == 1 || ver == 2) { + return g_strdup_printf ("ATI VCR %d", ver); + } else { + GST_WARNING ("Unexpected acrversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("ATI VCR"); + } + } else if (strcmp (info->type, "audio/x-adpcm") == 0) { + const GValue *layout_val; + + layout_val = gst_structure_get_value (s, "layout"); + if (layout_val != NULL && G_VALUE_HOLDS_STRING (layout_val)) { + const gchar *layout; + + if ((layout = g_value_get_string (layout_val))) { + gchar *layout_upper, *ret; + + if (strcmp (layout, "swf") == 0) + return g_strdup ("Shockwave ADPCM"); + if (strcmp (layout, "microsoft") == 0) + return g_strdup ("Microsoft ADPCM"); + if (strcmp (layout, "quicktime") == 0) + return g_strdup ("Quicktime ADPCM"); + if (strcmp (layout, "westwood") == 0) + return g_strdup ("Westwood ADPCM"); + if (strcmp (layout, "yamaha") == 0) + return g_strdup ("Yamaha ADPCM"); + /* FIXME: other layouts: sbpro2, sbpro3, sbpro4, ct, g726, ea, + * adx, xa, 4xm, smjpeg, dk4, dk3, dvi */ + layout_upper = g_ascii_strup (layout, -1); + ret = g_strdup_printf ("%s ADPCM", layout_upper); + g_free (layout_upper); + return ret; + } + } + return g_strdup ("ADPCM"); + } else if (strcmp (info->type, "audio/mpeg") == 0) { + gint ver = 0, layer = 0; + + gst_structure_get_int (s, "mpegversion", &ver); + + switch (ver) { + case 1: + gst_structure_get_int (s, "layer", &layer); + switch (layer) { + case 1: + case 2: + case 3: + return g_strdup_printf ("MPEG-1 Layer %d (MP%d)", layer, layer); + default: + break; + } + GST_WARNING ("Unexpected MPEG-1 layer in %" GST_PTR_FORMAT, caps); + return g_strdup ("MPEG-1 Audio"); + case 4: + return g_strdup ("MPEG-4 AAC"); + default: + break; + } + GST_WARNING ("Unexpected audio mpegversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("MPEG Audio"); + } else if (strcmp (info->type, "audio/x-pn-realaudio") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "raversion", &ver); + switch (ver) { + case 1: + return g_strdup ("RealAudio 14k4bps"); + case 2: + return g_strdup ("RealAudio 28k8bps"); + case 8: + return g_strdup ("RealAudio G2 (Cook)"); + default: + break; + } + GST_WARNING ("Unexpected raversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("RealAudio"); + } else if (strcmp (info->type, "video/x-pn-realvideo") == 0) { + gint ver = 0; + + gst_structure_get_int (s, "rmversion", &ver); + switch (ver) { + case 1: + return g_strdup ("RealVideo 1.0"); + case 2: + return g_strdup ("RealVideo 2.0"); + case 3: + return g_strdup ("RealVideo 3.0"); + case 4: + return g_strdup ("RealVideo 4.0"); + default: + break; + } + GST_WARNING ("Unexpected rmversion in %" GST_PTR_FORMAT, caps); + return g_strdup ("RealVideo"); + } else if (strcmp (info->type, "video/mpeg") == 0) { + gboolean sysstream; + gint ver = 0; + + if (!gst_structure_get_boolean (s, "systemstream", &sysstream) || + !gst_structure_get_int (s, "mpegversion", &ver) || ver < 1 || ver > 4) { + GST_WARNING ("Missing fields in mpeg video caps %" GST_PTR_FORMAT, caps); + } else { + if (sysstream) { + return g_strdup_printf ("MPEG-%d System Stream", ver); + } else { + return g_strdup_printf ("MPEG-%d Video", ver); + } + } + return g_strdup ("MPEG Video"); + } else if (strcmp (info->type, "audio/x-raw-int") == 0) { + gint bitdepth = 0; + + /* 8-bit pcm might not have depth field (?) */ + if (!gst_structure_get_int (s, "depth", &bitdepth)) + gst_structure_get_int (s, "width", &bitdepth); + if (bitdepth != 0) + return g_strdup_printf (_("Raw %d-bit PCM audio"), bitdepth); + else + return g_strdup (_("Raw PCM audio")); + } else if (strcmp (info->type, "audio/x-raw-float") == 0) { + gint bitdepth = 0; + + gst_structure_get_int (s, "width", &bitdepth); + if (bitdepth != 0) + return g_strdup_printf (_("Raw %d-bit floating-point audio"), bitdepth); + else + return g_strdup (_("Raw floating-point audio")); + } + + return NULL; +} + +/* returns format info structure, will return NULL for dynamic media types! */ +static const FormatInfo * +find_format_info (const GstCaps * caps) +{ + const GstStructure *s; + const gchar *media_type; + guint i; + + s = gst_caps_get_structure (caps, 0); + media_type = gst_structure_get_name (s); + + for (i = 0; i < G_N_ELEMENTS (formats); ++i) { + if (strcmp (media_type, formats[i].type) == 0) { + gboolean is_sys = FALSE; + + if ((formats[i].flags & FLAG_SYSTEMSTREAM) == 0) + return &formats[i]; + + /* this record should only be matched if the systemstream field is set */ + if (gst_structure_get_boolean (s, "systemstream", &is_sys) && is_sys) + return &formats[i]; + } + } + + return NULL; +} + +static gboolean +caps_are_rtp_caps (const GstCaps * caps, const gchar * media, gchar ** format) +{ + const GstStructure *s; + const gchar *str; + + g_assert (media != NULL && format != NULL); + + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_has_name (s, "application/x-rtp")) + return FALSE; + if (!gst_structure_has_field_typed (s, "media", G_TYPE_STRING)) + return FALSE; + str = gst_structure_get_string (s, "media"); + if (str == NULL || !g_str_equal (str, media)) + return FALSE; + str = gst_structure_get_string (s, "encoding-name"); + if (str == NULL || *str == '\0') + return FALSE; + + if (strcmp (str, "X-ASF-PF") == 0) { + *format = g_strdup ("Windows Media"); + } else if (g_str_has_prefix (str, "X-")) { + *format = g_strdup (str + 2); + } else { + *format = g_strdup (str); + } + + return TRUE; +} + +/** + * gst_pb_utils_get_source_description: + * @protocol: the protocol the source element needs to handle, e.g. "http" + * + * Returns a localised string describing a source element handling the protocol + * specified in @protocol, for use in error dialogs or other messages to be + * seen by the user. Should never return NULL unless @protocol is invalid. + * + * This function is mainly for internal use, applications would typically + * use gst_missing_plugin_message_get_description() to get a description of + * a missing feature from a missing-plugin message. + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_source_description (const gchar * protocol) +{ + gchar *proto_uc, *ret; + + g_return_val_if_fail (protocol != NULL, NULL); + + if (strcmp (protocol, "cdda") == 0) + return g_strdup (_("Audio CD source")); + + if (strcmp (protocol, "dvd") == 0) + return g_strdup (_("DVD source")); + + if (strcmp (protocol, "rtsp") == 0) + return g_strdup (_("Real Time Streaming Protocol (RTSP) source")); + + /* TODO: what about mmst, mmsu, mmsh? */ + if (strcmp (protocol, "mms") == 0) + return g_strdup (_("Microsoft Media Server (MMS) protocol source")); + + /* make protocol uppercase */ + proto_uc = g_ascii_strup (protocol, -1); + + /* TODO: find out how to add a comment for translators to the source code + * (and tell them to make the first letter uppercase below if they move + * the protocol to the middle or end of the string) */ + ret = g_strdup_printf (_("%s protocol source"), proto_uc); + + g_free (proto_uc); + + return ret; +} + +/** + * gst_pb_utils_get_sink_description: + * @protocol: the protocol the sink element needs to handle, e.g. "http" + * + * Returns a localised string describing a sink element handling the protocol + * specified in @protocol, for use in error dialogs or other messages to be + * seen by the user. Should never return NULL unless @protocol is invalid. + * + * This function is mainly for internal use, applications would typically + * use gst_missing_plugin_message_get_description() to get a description of + * a missing feature from a missing-plugin message. + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_sink_description (const gchar * protocol) +{ + gchar *proto_uc, *ret; + + g_return_val_if_fail (protocol != NULL, NULL); + + /* make protocol uppercase */ + proto_uc = g_ascii_strup (protocol, -1); + + /* TODO: find out how to add a comment for translators to the source code + * (and tell them to make the first letter uppercase below if they move + * the protocol to the middle or end of the string) */ + ret = g_strdup_printf ("%s protocol sink", proto_uc); + + g_free (proto_uc); + + return ret; +} + +/** + * gst_pb_utils_get_decoder_description: + * @caps: the (fixed) #GstCaps for which an decoder description is needed + * + * Returns a localised string describing an decoder for the format specified + * in @caps, for use in error dialogs or other messages to be seen by the user. + * Should never return NULL unless @factory_name or @caps are invalid. + * + * This function is mainly for internal use, applications would typically + * use gst_missing_plugin_message_get_description() to get a description of + * a missing feature from a missing-plugin message. + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_decoder_description (const GstCaps * caps) +{ + gchar *str, *ret; + GstCaps *tmp; + + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + + tmp = copy_and_clean_caps (caps); + + g_return_val_if_fail (gst_caps_is_fixed (tmp), NULL); + + /* special-case RTP caps */ + if (caps_are_rtp_caps (tmp, "video", &str)) { + ret = g_strdup_printf (_("%s video RTP depayloader"), str); + } else if (caps_are_rtp_caps (tmp, "audio", &str)) { + ret = g_strdup_printf (_("%s audio RTP depayloader"), str); + } else if (caps_are_rtp_caps (tmp, "application", &str)) { + ret = g_strdup_printf (_("%s RTP depayloader"), str); + } else { + const FormatInfo *info; + + str = gst_pb_utils_get_codec_description (tmp); + info = find_format_info (tmp); + if (info != NULL && (info->flags & FLAG_CONTAINER) != 0) { + ret = g_strdup_printf (_("%s demuxer"), str); + } else { + ret = g_strdup_printf (_("%s decoder"), str); + } + } + + g_free (str); + gst_caps_unref (tmp); + + return ret; +} + +/** + * gst_pb_utils_get_encoder_description: + * @caps: the (fixed) #GstCaps for which an encoder description is needed + * + * Returns a localised string describing an encoder for the format specified + * in @caps, for use in error dialogs or other messages to be seen by the user. + * Should never return NULL unless @factory_name or @caps are invalid. + * + * This function is mainly for internal use, applications would typically + * use gst_missing_plugin_message_get_description() to get a description of + * a missing feature from a missing-plugin message. + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_encoder_description (const GstCaps * caps) +{ + gchar *str, *ret; + GstCaps *tmp; + + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + tmp = copy_and_clean_caps (caps); + g_return_val_if_fail (gst_caps_is_fixed (tmp), NULL); + + /* special-case RTP caps */ + if (caps_are_rtp_caps (tmp, "video", &str)) { + ret = g_strdup_printf (_("%s video RTP payloader"), str); + } else if (caps_are_rtp_caps (tmp, "audio", &str)) { + ret = g_strdup_printf (_("%s audio RTP payloader"), str); + } else if (caps_are_rtp_caps (tmp, "application", &str)) { + ret = g_strdup_printf (_("%s RTP payloader"), str); + } else { + const FormatInfo *info; + + str = gst_pb_utils_get_codec_description (tmp); + info = find_format_info (tmp); + if (info != NULL && (info->flags & FLAG_CONTAINER) != 0) { + ret = g_strdup_printf (_("%s muxer"), str); + } else { + ret = g_strdup_printf (_("%s encoder"), str); + } + } + + g_free (str); + gst_caps_unref (tmp); + + return ret; +} + +/** + * gst_pb_utils_get_element_description: + * @factory_name: the name of the element, e.g. "gnomevfssrc" + * + * Returns a localised string describing the given element, for use in + * error dialogs or other messages to be seen by the user. Should never + * return NULL unless @factory_name is invalid. + * + * This function is mainly for internal use, applications would typically + * use gst_missing_plugin_message_get_description() to get a description of + * a missing feature from a missing-plugin message. + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_element_description (const gchar * factory_name) +{ + gchar *ret; + + g_return_val_if_fail (factory_name != NULL, NULL); + + ret = g_strdup_printf (_("GStreamer element %s"), factory_name); + if (ret && g_str_has_prefix (ret, factory_name)) + *ret = g_ascii_toupper (*ret); + + return ret; +} + +/** + * gst_pb_utils_add_codec_description_to_tag_list: + * @taglist: a #GstTagList + * @codec_tag: a GStreamer codec tag such as #GST_TAG_AUDIO_CODEC, + * #GST_TAG_VIDEO_CODEC or #GST_TAG_CODEC + * @caps: the (fixed) #GstCaps for which a codec tag should be added. + * + * Adds a codec tag describing the format specified by @caps to @taglist. + * + * Returns: TRUE if a codec tag was added, FALSE otherwise. + */ +gboolean +gst_pb_utils_add_codec_description_to_tag_list (GstTagList * taglist, + const gchar * codec_tag, const GstCaps * caps) +{ + const FormatInfo *info; + gchar *desc; + + g_return_val_if_fail (taglist != NULL, FALSE); + g_return_val_if_fail (GST_IS_TAG_LIST (taglist), FALSE); + g_return_val_if_fail (codec_tag != NULL, FALSE); + g_return_val_if_fail (gst_tag_exists (codec_tag), FALSE); + g_return_val_if_fail (gst_tag_get_type (codec_tag) == G_TYPE_STRING, FALSE); + g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (GST_IS_CAPS (caps), FALSE); + + info = find_format_info (caps); + if (info == NULL) + return FALSE; + + desc = format_info_get_desc (info, caps); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, codec_tag, desc, NULL); + g_free (desc); + + return TRUE; +} + +/** + * gst_pb_utils_get_codec_description: + * @caps: the (fixed) #GstCaps for which an format description is needed + * + * Returns a localised (as far as this is possible) string describing the + * media format specified in @caps, for use in error dialogs or other messages + * to be seen by the user. Should never return NULL unless @caps is invalid. + * + * Also see the convenience function + * gst_pb_utils_add_codec_description_to_tag_list(). + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_pb_utils_get_codec_description (const GstCaps * caps) +{ + const FormatInfo *info; + gchar *str, *comma; + GstCaps *tmp; + + g_return_val_if_fail (caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (caps), NULL); + tmp = copy_and_clean_caps (caps); + g_return_val_if_fail (gst_caps_is_fixed (tmp), NULL); + + info = find_format_info (tmp); + + if (info) { + str = format_info_get_desc (info, tmp); + } else { + str = gst_caps_to_string (tmp); + + /* cut off everything after the media type, if there is anything */ + if ((comma = strchr (str, ','))) { + *comma = '\0'; + g_strchomp (str); + /* we could do something more elaborate here, like taking into account + * audio/, video/, image/ and application/ prefixes etc. */ + } + + GST_WARNING ("No description available for media type: %s", str); + } + gst_caps_unref (tmp); + + return str; +} + +#if 0 +void +gst_pb_utils_list_all (void) +{ + gint i; + + g_print ("static const gchar *caps_strings[] = { "); + + for (i = 0; i < G_N_ELEMENTS (formats); ++i) { + if (formats[i].desc != NULL) + g_print (" \"%s\", ", formats[i].type); + } + g_print ("\n#if 0\n"); + for (i = 0; i < G_N_ELEMENTS (formats); ++i) { + if (formats[i].desc == NULL) + g_print (" \"%s\", \n", formats[i].type); + } + g_print ("\n#endif\n"); +} +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.h new file mode 100644 index 0000000..5b19ecc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/descriptions.h @@ -0,0 +1,58 @@ +/* GStreamer base utils library source/sink/codec description support + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PB_UTILS_DESCRIPTIONS_H__ +#define __GST_PB_UTILS_DESCRIPTIONS_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * functions for use by demuxers or decoders to add CODEC tags to tag lists + * from caps + */ + +gboolean gst_pb_utils_add_codec_description_to_tag_list (GstTagList * taglist, + const gchar * codec_tag, + const GstCaps * caps); + +gchar * gst_pb_utils_get_codec_description (const GstCaps * caps); + +/* + * functions mainly used by the missing plugins message creation functions to + * find descriptions of what exactly is missing + */ + +gchar * gst_pb_utils_get_source_description (const gchar * protocol); + +gchar * gst_pb_utils_get_sink_description (const gchar * protocol); + +gchar * gst_pb_utils_get_decoder_description (const GstCaps * caps); + +gchar * gst_pb_utils_get_encoder_description (const GstCaps * caps); + +gchar * gst_pb_utils_get_element_description (const gchar * factory_name); + + +G_END_DECLS + +#endif /* __GST_PB_UTILS_DESCRIPTIONS_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.c new file mode 100644 index 0000000..eaa7507 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.c @@ -0,0 +1,966 @@ +/* GStreamer encoding profiles library + * Copyright (C) 2009-2010 Edward Hervey + * (C) 2009-2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:encoding-profile + * @short_description: Encoding profile library + * + * + * + * Functions to create and handle encoding profiles. + * + * + * Encoding profiles describe the media types and settings one wishes to use for + * an encoding process. The top-level profiles are commonly + * #GstEncodingContainerProfile(s) (which contains a user-readable name and + * description along with which container format to use). These, in turn, + * reference one or more #GstEncodingProfile(s) which indicate which encoding + * format should be used on each individual streams. + * + * + * #GstEncodingProfile(s) can be provided to the 'encodebin' element, which will take + * care of selecting and setting up the required elements to produce an output stream + * conforming to the specifications of the profile. + * + * + * Unlike other systems, the encoding profiles do not specify which #GstElement to use + * for the various encoding and muxing steps, but instead relies on specifying the format + * one wishes to use. + * + * + * Encoding profiles can be created at runtime by the application or loaded from (and saved + * to) file using the #GstEncodingTarget API. + * + * + * + * Example: Creating a profile + * + * |[ + * #include + * ... + * GstEncodingProfile * + * create_ogg_theora_profile(void) + *{ + * GstEncodingContainerProfile *prof; + * GstCaps *caps; + * + * caps = gst_caps_from_string("application/ogg"); + * prof = gst_encoding_container_profile_new("Ogg audio/video", + * "Standard OGG/THEORA/VORBIS", + * caps, NULL); + * gst_caps_unref (caps); + * + * caps = gst_caps_from_string("video/x-theora"); + * gst_encoding_container_profile_add_profile(prof, + * (GstEncodingProfile*) gst_encoding_video_profile_new(caps, NULL, NULL, 0)); + * gst_caps_unref (caps); + * + * caps = gst_caps_from_string("audio/x-vorbis"); + * gst_encoding_container_profile_add_profile(prof, + * (GstEncodingProfile*) gst_encoding_audio_profile_new(caps, NULL, NULL, 0)); + * gst_caps_unref (caps); + * + * return (GstEncodingProfile*) prof; + *} + * + * + * ]| + * + * + * + * Example: Listing categories, targets and profiles + * + * |[ + * #include + * ... + * GstEncodingProfile *prof; + * GList *categories, *tmpc; + * GList *targets, *tmpt; + * ... + * categories = gst_encoding_target_list_available_categories(); + * + * ... Show available categories to user ... + * + * for (tmpc = categories; tmpc; tmpc = tmpc->next) { + * gchar *category = (gchar *) tmpc->data; + * + * ... and we can list all targets within that category ... + * + * targets = gst_encoding_target_list_all (category); + * + * ... and show a list to our users ... + * + * g_list_foreach (targets, (GFunc) gst_encoding_target_unref, NULL); + * g_list_free (targets); + * } + * + * g_list_foreach (categories, (GFunc) g_free, NULL); + * g_list_free (categories); + * + * ... + * ]| + * + * + * + * Since: 0.10.32 + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "encoding-profile.h" +#include "encoding-target.h" + +/* GstEncodingProfile API */ + +struct _GstEncodingProfile +{ + GstMiniObject parent; + + /*< public > */ + gchar *name; + gchar *description; + GstCaps *format; + gchar *preset; + guint presence; + GstCaps *restriction; +}; + +static void string_to_profile_transform (const GValue * src_value, + GValue * dest_value); +static gboolean gst_encoding_profile_deserialize_valfunc (GValue * value, + const gchar * s); + +static void gst_encoding_profile_class_init (GstEncodingProfileClass * klass); +static gpointer gst_encoding_profile_parent_class = NULL; + +static void +gst_encoding_profile_class_intern_init (gpointer klass) +{ + gst_encoding_profile_parent_class = g_type_class_peek_parent (klass); + gst_encoding_profile_class_init ((GstEncodingProfileClass *) klass); +} + +GType +gst_encoding_profile_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + + if (g_once_init_enter (&g_define_type_id__volatile)) { + GType g_define_type_id = + g_type_register_static_simple (GST_TYPE_MINI_OBJECT, + g_intern_static_string ("GstEncodingProfile"), + sizeof (GstEncodingProfileClass), + (GClassInitFunc) gst_encoding_profile_class_intern_init, + sizeof (GstEncodingProfile), + NULL, + (GTypeFlags) 0); + static GstValueTable gstvtable = { + G_TYPE_NONE, + (GstValueCompareFunc) NULL, + (GstValueSerializeFunc) NULL, + (GstValueDeserializeFunc) gst_encoding_profile_deserialize_valfunc + }; + + gstvtable.type = g_define_type_id; + + /* Register a STRING=>PROFILE GValueTransformFunc */ + g_value_register_transform_func (G_TYPE_STRING, g_define_type_id, + string_to_profile_transform); + /* Register gst-specific GValue functions */ + gst_value_register (&gstvtable); + + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +static void +gst_encoding_profile_finalize (GstEncodingProfile * prof) +{ + if (prof->name) + g_free (prof->name); + if (prof->format) + gst_caps_unref (prof->format); + if (prof->preset) + g_free (prof->preset); + if (prof->description) + g_free (prof->description); + if (prof->restriction) + gst_caps_unref (prof->restriction); +} + +static void +gst_encoding_profile_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_encoding_profile_finalize; +} + +/** + * gst_encoding_profile_get_name: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: the name of the profile, can be %NULL. + */ +const gchar * +gst_encoding_profile_get_name (GstEncodingProfile * profile) +{ + return profile->name; +} + +/** + * gst_encoding_profile_get_description: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: the description of the profile, can be %NULL. + */ +const gchar * +gst_encoding_profile_get_description (GstEncodingProfile * profile) +{ + return profile->description; +} + +/** + * gst_encoding_profile_get_format: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: the #GstCaps corresponding to the media format used in the profile. + */ +const GstCaps * +gst_encoding_profile_get_format (GstEncodingProfile * profile) +{ + return profile->format; +} + +/** + * gst_encoding_profile_get_preset: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: the name of the #GstPreset to be used in the profile. + */ +const gchar * +gst_encoding_profile_get_preset (GstEncodingProfile * profile) +{ + return profile->preset; +} + +/** + * gst_encoding_profile_get_presence: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: The number of times the profile is used in its parent + * container profile. If 0, it is not a mandatory stream. + */ +guint +gst_encoding_profile_get_presence (GstEncodingProfile * profile) +{ + return profile->presence; +} + +/** + * gst_encoding_profile_get_restriction: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: The restriction #GstCaps to apply before the encoder + * that will be used in the profile. The fields present in restriction caps are + * properties of the raw stream (that is before encoding), such as height and + * width for video and depth and sampling rate for audio. Does not apply to + * #GstEncodingContainerProfile (since there is no corresponding raw stream). + * Can be %NULL. + */ +const GstCaps * +gst_encoding_profile_get_restriction (GstEncodingProfile * profile) +{ + return profile->restriction; +} + +/** + * gst_encoding_profile_set_name: + * @profile: a #GstEncodingProfile + * @name: the name to set on the profile + * + * Set @name as the given name for the @profile. A copy of @name will be made + * internally. + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_name (GstEncodingProfile * profile, const gchar * name) +{ + if (profile->name) + g_free (profile->name); + profile->name = g_strdup (name); +} + +/** + * gst_encoding_profile_set_description: + * @profile: a #GstEncodingProfile + * @description: the description to set on the profile + * + * Set @description as the given description for the @profile. A copy of @description will be made + * internally. + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_description (GstEncodingProfile * profile, + const gchar * description) +{ + if (profile->description) + g_free (profile->description); + profile->description = g_strdup (description); +} + +/** + * gst_encoding_profile_set_format: + * @profile: a #GstEncodingProfile + * @format: the media format to use in the profile. + * + * Sets the media format used in the profile. + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_format (GstEncodingProfile * profile, GstCaps * format) +{ + if (profile->format) + gst_caps_unref (profile->format); + profile->format = gst_caps_ref (format); +} + +/** + * gst_encoding_profile_set_preset: + * @profile: a #GstEncodingProfile + * @preset: the element preset to use + * + * Sets the preset to use for the profile. + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_preset (GstEncodingProfile * profile, + const gchar * preset) +{ + if (profile->preset) + g_free (profile->preset); + profile->preset = g_strdup (preset); +} + +/** + * gst_encoding_profile_set_presence: + * @profile: a #GstEncodingProfile + * @presence: the number of time the profile can be used + * + * Set the number of time the profile is used in its parent + * container profile. If 0, it is not a mandatory stream + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_presence (GstEncodingProfile * profile, guint presence) +{ + profile->presence = presence; +} + +/** + * gst_encoding_profile_set_restriction: + * @profile: a #GstEncodingProfile + * @restriction: the restriction to apply + * + * Set the restriction #GstCaps to apply before the encoder + * that will be used in the profile. See gst_encoding_profile_set_restriction() + * for more about restrictions. Does not apply to #GstEncodingContainerProfile. + * + * Since: 0.10.32 + */ +void +gst_encoding_profile_set_restriction (GstEncodingProfile * profile, + GstCaps * restriction) +{ + if (profile->restriction) + gst_caps_unref (profile->restriction); + profile->restriction = restriction; +} + +/* Container profiles */ + +struct _GstEncodingContainerProfile +{ + GstEncodingProfile parent; + + GList *encodingprofiles; +}; + +G_DEFINE_TYPE (GstEncodingContainerProfile, gst_encoding_container_profile, + GST_TYPE_ENCODING_PROFILE); + +static void +gst_encoding_container_profile_init (GstEncodingContainerProfile * prof) +{ + /* Nothing to initialize */ +} + +static void +gst_encoding_container_profile_finalize (GstEncodingContainerProfile * prof) +{ + g_list_foreach (prof->encodingprofiles, (GFunc) gst_mini_object_unref, NULL); + g_list_free (prof->encodingprofiles); + + GST_MINI_OBJECT_CLASS (gst_encoding_container_profile_parent_class)->finalize + ((GstMiniObject *) prof); +} + +static void +gst_encoding_container_profile_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_encoding_container_profile_finalize; +} + +const GList * +gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile * + profile) +{ + return profile->encodingprofiles; +} + +/* Video profiles */ + +struct _GstEncodingVideoProfile +{ + GstEncodingProfile parent; + + guint pass; + gboolean variableframerate; +}; + +G_DEFINE_TYPE (GstEncodingVideoProfile, gst_encoding_video_profile, + GST_TYPE_ENCODING_PROFILE); + +static void +gst_encoding_video_profile_init (GstEncodingVideoProfile * prof) +{ + /* Nothing to initialize */ +} + +static void +gst_encoding_video_profile_class_init (GstMiniObjectClass * klass) +{ +} + +/** + * gst_encoding_video_profile_get_pass: + * @prof: a #GstEncodingVideoProfile + * + * Since: 0.10.32 + * + * Returns: The pass number if this is part of a multi-pass profile. Starts at + * 1 for multi-pass. 0 if this is not a multi-pass profile + **/ +guint +gst_encoding_video_profile_get_pass (GstEncodingVideoProfile * prof) +{ + return prof->pass; +} + +/** + * gst_encoding_video_profile_get_variableframerate: + * @prof: a #GstEncodingVideoProfile + * + * Since: 0.10.32 + * + * Returns: Whether non-constant video framerate is allowed for encoding. + */ +gboolean +gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile * + prof) +{ + return prof->variableframerate; +} + +/** + * gst_encoding_video_profile_set_pass: + * @prof: a #GstEncodingVideoProfile + * @pass: the pass number for this profile + * + * Sets the pass number of this video profile. The first pass profile should have + * this value set to 1. If this video profile isn't part of a multi-pass profile, + * you may set it to 0 (the default value). + * + * Since: 0.10.32 + */ +void +gst_encoding_video_profile_set_pass (GstEncodingVideoProfile * prof, guint pass) +{ + prof->pass = pass; +} + +/** + * gst_encoding_video_profile_set_variableframerate: + * @prof: a #GstEncodingVideoProfile + * @variableframerate: a boolean + * + * If set to %TRUE, then the incoming streamm will be allowed to have non-constant + * framerate. If set to %FALSE (default value), then the incoming stream will + * be normalized by dropping/duplicating frames in order to produce a + * constance framerate. + * + * Since: 0.10.32 + */ +void +gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile * + prof, gboolean variableframerate) +{ + prof->variableframerate = variableframerate; +} + +/* Audio profiles */ + +struct _GstEncodingAudioProfile +{ + GstEncodingProfile parent; +}; + +G_DEFINE_TYPE (GstEncodingAudioProfile, gst_encoding_audio_profile, + GST_TYPE_ENCODING_PROFILE); + +static void +gst_encoding_audio_profile_init (GstEncodingAudioProfile * prof) +{ + /* Nothing to initialize */ +} + +static void +gst_encoding_audio_profile_class_init (GstMiniObjectClass * klass) +{ +} + +static inline gboolean +_gst_caps_is_equal_safe (GstCaps * a, GstCaps * b) +{ + if (a == b) + return TRUE; + if ((a == NULL) || (b == NULL)) + return FALSE; + return gst_caps_is_equal (a, b); +} + +static gint +_compare_container_encoding_profiles (GstEncodingContainerProfile * ca, + GstEncodingContainerProfile * cb) +{ + GList *tmp; + + if (g_list_length (ca->encodingprofiles) != + g_list_length (cb->encodingprofiles)) + return -1; + + for (tmp = ca->encodingprofiles; tmp; tmp = tmp->next) { + GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data; + if (!gst_encoding_container_profile_contains_profile (ca, prof)) + return -1; + } + + return 0; +} + +static gint +_compare_encoding_profiles (const GstEncodingProfile * a, + const GstEncodingProfile * b) +{ + if ((G_TYPE_FROM_INSTANCE (a) != G_TYPE_FROM_INSTANCE (b)) || + !_gst_caps_is_equal_safe (a->format, b->format) || + (g_strcmp0 (a->preset, b->preset) != 0) || + (g_strcmp0 (a->name, b->name) != 0) || + (g_strcmp0 (a->description, b->description) != 0)) + return -1; + + if (GST_IS_ENCODING_CONTAINER_PROFILE (a)) + return + _compare_container_encoding_profiles (GST_ENCODING_CONTAINER_PROFILE + (a), GST_ENCODING_CONTAINER_PROFILE (b)); + + if (GST_IS_ENCODING_VIDEO_PROFILE (a)) { + GstEncodingVideoProfile *va = (GstEncodingVideoProfile *) a; + GstEncodingVideoProfile *vb = (GstEncodingVideoProfile *) b; + + if ((va->pass != vb->pass) + || (va->variableframerate != vb->variableframerate)) + return -1; + } + + return 0; +} + +/** + * gst_encoding_container_profile_contains_profile: + * @container: a #GstEncodingContainerProfile + * @profile: a #GstEncodingProfile + * + * Checks if @container contains a #GstEncodingProfile identical to + * @profile. + * + * Since: 0.10.32 + * + * Returns: %TRUE if @container contains a #GstEncodingProfile identical + * to @profile, else %FALSE. + */ +gboolean +gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile * + container, GstEncodingProfile * profile) +{ + g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE); + g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE); + + return (g_list_find_custom (container->encodingprofiles, profile, + (GCompareFunc) _compare_encoding_profiles) != NULL); +} + +/** + * gst_encoding_container_profile_add_profile: + * @container: the #GstEncodingContainerProfile to use + * @profile: the #GstEncodingProfile to add. + * + * Add a #GstEncodingProfile to the list of profiles handled by @container. + * + * No copy of @profile will be made, if you wish to use it elsewhere after this + * method you should increment its reference count. + * + * Since: 0.10.32 + * + * Returns: %TRUE if the @stream was properly added, else %FALSE. + */ +gboolean +gst_encoding_container_profile_add_profile (GstEncodingContainerProfile * + container, GstEncodingProfile * profile) +{ + g_return_val_if_fail (GST_IS_ENCODING_CONTAINER_PROFILE (container), FALSE); + g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE); + + if (g_list_find_custom (container->encodingprofiles, profile, + (GCompareFunc) _compare_encoding_profiles)) { + GST_ERROR + ("Encoding profile already contains an identical GstEncodingProfile"); + return FALSE; + } + + container->encodingprofiles = + g_list_append (container->encodingprofiles, profile); + + return TRUE; +} + +static GstEncodingProfile * +common_creation (GType objtype, GstCaps * format, const gchar * preset, + const gchar * name, const gchar * description, GstCaps * restriction, + guint presence) +{ + GstEncodingProfile *prof; + + prof = (GstEncodingProfile *) gst_mini_object_new (objtype); + + if (name) + prof->name = g_strdup (name); + if (description) + prof->description = g_strdup (description); + if (preset) + prof->preset = g_strdup (preset); + if (format) + prof->format = gst_caps_ref (format); + if (restriction) + prof->restriction = gst_caps_ref (restriction); + prof->presence = presence; + + return prof; +} + +/** + * gst_encoding_container_profile_new: + * @name: The name of the container profile, can be %NULL + * @description: The description of the container profile, can be %NULL + * @format: The format to use for this profile + * @preset: The preset to use for this profile + * + * Creates a new #GstEncodingContainerProfile. + * + * Since: 0.10.32 + * + * Returns: The newly created #GstEncodingContainerProfile. + */ +GstEncodingContainerProfile * +gst_encoding_container_profile_new (const gchar * name, + const gchar * description, GstCaps * format, const gchar * preset) +{ + g_return_val_if_fail (GST_IS_CAPS (format), NULL); + + return (GstEncodingContainerProfile *) + common_creation (GST_TYPE_ENCODING_CONTAINER_PROFILE, format, preset, + name, description, NULL, 0); +} + +/** + * gst_encoding_video_profile_new: + * @format: the #GstCaps + * @preset: the preset(s) to use on the encoder, can be #NULL + * @restriction: the #GstCaps used to restrict the input to the encoder, can be + * NULL. See gst_encoding_profile_get_restriction() for more details. + * @presence: the number of time this stream must be used. 0 means any number of + * times (including never) + * + * Creates a new #GstEncodingVideoProfile + * + * All provided allocatable arguments will be internally copied, so can be + * safely freed/unreferenced after calling this method. + * + * If you wish to control the pass number (in case of multi-pass scenarios), + * please refer to the gst_encoding_video_profile_set_pass() documentation. + * + * If you wish to use/force a constant framerate please refer to the + * gst_encoding_video_profile_set_variableframerate() documentation. + * + * Since: 0.10.32 + * + * Returns: the newly created #GstEncodingVideoProfile. + */ +GstEncodingVideoProfile * +gst_encoding_video_profile_new (GstCaps * format, const gchar * preset, + GstCaps * restriction, guint presence) +{ + return (GstEncodingVideoProfile *) + common_creation (GST_TYPE_ENCODING_VIDEO_PROFILE, format, preset, NULL, + NULL, restriction, presence); +} + +/** + * gst_encoding_audio_profile_new: + * @format: the #GstCaps + * @preset: the preset(s) to use on the encoder, can be #NULL + * @restriction: the #GstCaps used to restrict the input to the encoder, can be + * NULL. See gst_encoding_profile_get_restriction() for more details. + * @presence: the number of time this stream must be used. 0 means any number of + * times (including never) + * + * Creates a new #GstEncodingAudioProfile + * + * All provided allocatable arguments will be internally copied, so can be + * safely freed/unreferenced after calling this method. + * + * Since: 0.10.32 + * + * Returns: the newly created #GstEncodingAudioProfile. + */ +GstEncodingAudioProfile * +gst_encoding_audio_profile_new (GstCaps * format, const gchar * preset, + GstCaps * restriction, guint presence) +{ + return (GstEncodingAudioProfile *) + common_creation (GST_TYPE_ENCODING_AUDIO_PROFILE, format, preset, NULL, + NULL, restriction, presence); +} + + +/** + * gst_encoding_profile_is_equal: + * @a: a #GstEncodingProfile + * @b: a #GstEncodingProfile + * + * Checks whether the two #GstEncodingProfile are equal + * + * Since: 0.10.32 + * + * Returns: %TRUE if @a and @b are equal, else %FALSE. + */ +gboolean +gst_encoding_profile_is_equal (GstEncodingProfile * a, GstEncodingProfile * b) +{ + return (_compare_encoding_profiles (a, b) == 0); +} + + +/** + * gst_encoding_profile_get_input_caps: + * @profile: a #GstEncodingProfile + * + * Computes the full output caps that this @profile will be able to consume. + * + * Since: 0.10.32 + * + * Returns: The full caps the given @profile can consume. Call gst_caps_unref() + * when you are done with the caps. + */ +GstCaps * +gst_encoding_profile_get_input_caps (GstEncodingProfile * profile) +{ + GstCaps *out, *tmp; + GList *ltmp; + GstStructure *st, *outst; + GQuark out_name; + guint i, len; + const GstCaps *fcaps; + + if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) { + GstCaps *res = gst_caps_new_empty (); + + for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles; + ltmp; ltmp = ltmp->next) { + GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data; + gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof)); + } + return res; + } + + fcaps = profile->format; + + /* fast-path */ + if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction)) + return gst_caps_copy (fcaps); + + /* Combine the format with the restriction caps */ + outst = gst_caps_get_structure (fcaps, 0); + out_name = gst_structure_get_name_id (outst); + tmp = gst_caps_new_empty (); + len = gst_caps_get_size (profile->restriction); + + for (i = 0; i < len; i++) { + st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i)); + st->name = out_name; + gst_caps_append_structure (tmp, st); + } + + out = gst_caps_intersect (tmp, fcaps); + gst_caps_unref (tmp); + + return out; +} + +/** + * gst_encoding_profile_get_type_nick: + * @profile: a #GstEncodingProfile + * + * Since: 0.10.32 + * + * Returns: the human-readable name of the type of @profile. + */ +const gchar * +gst_encoding_profile_get_type_nick (GstEncodingProfile * profile) +{ + if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) + return "container"; + if (GST_IS_ENCODING_VIDEO_PROFILE (profile)) + return "video"; + if (GST_IS_ENCODING_AUDIO_PROFILE (profile)) + return "audio"; + return NULL; +} + +/** + * gst_encoding_profile_find: + * @targetname: (transfer none): The name of the target + * @profilename: (transfer none): The name of the profile + * @category: (transfer none) (allow-none): The target category. Can be %NULL + * + * Find the #GstEncodingProfile with the specified name and category. + * + * Returns: (transfer full): The matching #GstEncodingProfile or %NULL. + * + * Since: 0.10.32 + */ +GstEncodingProfile * +gst_encoding_profile_find (const gchar * targetname, const gchar * profilename, + const gchar * category) +{ + GstEncodingProfile *res = NULL; + GstEncodingTarget *target; + + g_return_val_if_fail (targetname != NULL, NULL); + g_return_val_if_fail (profilename != NULL, NULL); + + /* FIXME : how do we handle profiles named the same in several + * categories but of which only one has the required profile ? */ + target = gst_encoding_target_load (targetname, category, NULL); + if (target) { + res = gst_encoding_target_get_profile (target, profilename); + gst_encoding_target_unref (target); + } + + return res; +} + +static GstEncodingProfile * +combo_search (const gchar * pname) +{ + GstEncodingProfile *res; + gchar **split; + + /* Splitup */ + split = g_strsplit (pname, "/", 2); + if (g_strv_length (split) != 2) + return NULL; + + res = gst_encoding_profile_find (split[0], split[1], NULL); + + g_strfreev (split); + + return res; +} + +/* GValue transform function */ +static void +string_to_profile_transform (const GValue * src_value, GValue * dest_value) +{ + const gchar *profilename; + GstEncodingProfile *profile; + + profilename = g_value_get_string (src_value); + + profile = combo_search (profilename); + + if (profile) + gst_value_take_mini_object (dest_value, (GstMiniObject *) profile); +} + +static gboolean +gst_encoding_profile_deserialize_valfunc (GValue * value, const gchar * s) +{ + GstEncodingProfile *profile; + + profile = combo_search (s); + + if (profile) { + gst_value_take_mini_object (value, (GstMiniObject *) profile); + return TRUE; + } + + return FALSE; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.h new file mode 100644 index 0000000..86becca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-profile.h @@ -0,0 +1,187 @@ +/* GStreamer encoding profiles library + * Copyright (C) 2009-2010 Edward Hervey + * (C) 2009-2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PROFILE_H__ +#define __GST_PROFILE_H__ + +#include + +G_BEGIN_DECLS + +#include + +/** + * GstEncodingProfile: + * + * The opaque base class object for all encoding profiles. This contains generic + * information like name, description, format and preset. + * + * Since: 0.10.32 + */ + +#define GST_TYPE_ENCODING_PROFILE \ + (gst_encoding_profile_get_type ()) +#define GST_ENCODING_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_PROFILE, GstEncodingProfile)) +#define GST_IS_ENCODING_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_PROFILE)) +typedef struct _GstEncodingProfile GstEncodingProfile; +typedef GstMiniObjectClass GstEncodingProfileClass; +GType gst_encoding_profile_get_type (void); + + + +/** + * GstEncodingContainerProfile: + * + * Encoding profiles for containers. Keeps track of a list of #GstEncodingProfile + * + * Since: 0.10.32 + */ +#define GST_TYPE_ENCODING_CONTAINER_PROFILE \ + (gst_encoding_container_profile_get_type ()) +#define GST_ENCODING_CONTAINER_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE, GstEncodingContainerProfile)) +#define GST_IS_ENCODING_CONTAINER_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_CONTAINER_PROFILE)) +typedef struct _GstEncodingContainerProfile GstEncodingContainerProfile; +typedef GstEncodingProfileClass GstEncodingContainerProfileClass; +GType gst_encoding_container_profile_get_type (void); + + + +/** + * GstEncodingVideoProfile: + * + * Variant of #GstEncodingProfile for video streams, allows specifying the @pass. + * + * Since: 0.10.32 + */ +#define GST_TYPE_ENCODING_VIDEO_PROFILE \ + (gst_encoding_video_profile_get_type ()) +#define GST_ENCODING_VIDEO_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_VIDEO_PROFILE, GstEncodingVideoProfile)) +#define GST_IS_ENCODING_VIDEO_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_VIDEO_PROFILE)) +typedef struct _GstEncodingVideoProfile GstEncodingVideoProfile; +typedef GstEncodingProfileClass GstEncodingVideoProfileClass; +GType gst_encoding_video_profile_get_type (void); + + + +/** + * GstEncodingAudioProfile: + * + * Variant of #GstEncodingProfile for audio streams. + * + * Since: 0.10.32 + */ +#define GST_TYPE_ENCODING_AUDIO_PROFILE \ + (gst_encoding_audio_profile_get_type ()) +#define GST_ENCODING_AUDIO_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_AUDIO_PROFILE, GstEncodingAudioProfile)) +#define GST_IS_ENCODING_AUDIO_PROFILE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_AUDIO_PROFILE)) +typedef struct _GstEncodingAudioProfile GstEncodingAudioProfile; +typedef GstEncodingProfileClass GstEncodingAudioProfileClass; +GType gst_encoding_audio_profile_get_type (void); + + + +/* GstEncodingProfile API */ + +/** + * gst_encoding_profile_unref: + * @profile: a #GstEncodingProfile + * + * Decreases the reference count of the @profile, possibly freeing the @profile. + * + * Since: 0.10.32 + */ +#define gst_encoding_profile_unref(profile) (gst_mini_object_unref ((GstMiniObject*) profile)) + +/** + * gst_encoding_profile_ref: + * @profile: a #GstEncodingProfile + * + * Increases the reference count of the @profile. + * + * Since: 0.10.32 + */ +#define gst_encoding_profile_ref(profile) (gst_mini_object_ref ((GstMiniObject*) profile)) + +const gchar * gst_encoding_profile_get_name(GstEncodingProfile *profile); +const gchar * gst_encoding_profile_get_description(GstEncodingProfile *profile); +const GstCaps * gst_encoding_profile_get_format(GstEncodingProfile *profile); +const gchar * gst_encoding_profile_get_preset(GstEncodingProfile *profile); +guint gst_encoding_profile_get_presence(GstEncodingProfile *profile); +const GstCaps * gst_encoding_profile_get_restriction(GstEncodingProfile *profile); + +void gst_encoding_profile_set_name(GstEncodingProfile *profile, const gchar *name); +void gst_encoding_profile_set_description(GstEncodingProfile *profile, const gchar *description); +void gst_encoding_profile_set_format(GstEncodingProfile *profile, GstCaps *format); +void gst_encoding_profile_set_preset(GstEncodingProfile *profile, const gchar *preset); +void gst_encoding_profile_set_restriction(GstEncodingProfile *profile, GstCaps *restriction); +void gst_encoding_profile_set_presence(GstEncodingProfile *profile, guint presence); + +gboolean gst_encoding_profile_is_equal (GstEncodingProfile *a, + GstEncodingProfile *b); +GstCaps * gst_encoding_profile_get_input_caps (GstEncodingProfile *profile); + +const gchar *gst_encoding_profile_get_type_nick (GstEncodingProfile *profile); + +GstEncodingProfile * gst_encoding_profile_find (const gchar *targetname, + const gchar *profilename, + const gchar *category); + +/* GstEncodingContainerProfile API */ +gboolean gst_encoding_container_profile_add_profile (GstEncodingContainerProfile *container, + GstEncodingProfile *profile); +gboolean gst_encoding_container_profile_contains_profile (GstEncodingContainerProfile * container, + GstEncodingProfile *profile); +const GList *gst_encoding_container_profile_get_profiles (GstEncodingContainerProfile *profile); + + +GstEncodingContainerProfile * gst_encoding_container_profile_new (const gchar *name, + const gchar *description, + GstCaps *format, + const gchar *preset); + + +/* Invidual stream encodingprofile API */ +GstEncodingVideoProfile * gst_encoding_video_profile_new (GstCaps *format, + const gchar *preset, + GstCaps *restriction, + guint presence); +GstEncodingAudioProfile * gst_encoding_audio_profile_new (GstCaps *format, + const gchar *preset, + GstCaps *restriction, + guint presence); + +guint gst_encoding_video_profile_get_pass (GstEncodingVideoProfile *prof); +gboolean gst_encoding_video_profile_get_variableframerate (GstEncodingVideoProfile *prof); + +void gst_encoding_video_profile_set_pass (GstEncodingVideoProfile *prof, + guint pass); +void gst_encoding_video_profile_set_variableframerate (GstEncodingVideoProfile *prof, + gboolean variableframerate); +G_END_DECLS + +#endif /* __GST_PROFILE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.c new file mode 100644 index 0000000..29e67d0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.c @@ -0,0 +1,1201 @@ +/* GStreamer encoding profile registry + * Copyright (C) 2010 Edward Hervey + * (C) 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include "encoding-target.h" + +/* + * File format + * + * GKeyFile style. + * + * [GStreamer Encoding Target] + * name : + * category : + * description : #translatable + * + * [profile-] + * name : + * description : #optional + * format : + * preset : + * + * [streamprofile-] + * parent : [,..] + * type : # "audio", "video", "text" + * format : + * preset : + * restriction : + * presence : + * pass : + * variableframerate : + * */ + +/* + * Location of profile files + * + * $GST_DATADIR/gstreamer-GST_MAJORMINOR/encoding-profile + * $HOME/gstreamer-GST_MAJORMINOR/encoding-profile + * + * Naming convention + * $(target.category)/$(target.name).gep + * + * Naming restrictions: + * lowercase ASCII letter for the first character + * Same for all other characters + numerics + hyphens + */ + + +#define GST_ENCODING_TARGET_HEADER "GStreamer Encoding Target" +#define GST_ENCODING_TARGET_DIRECTORY "encoding-profiles" +#define GST_ENCODING_TARGET_SUFFIX ".gep" + +struct _GstEncodingTarget +{ + GstMiniObject parent; + + gchar *name; + gchar *category; + gchar *description; + GList *profiles; + + /*< private > */ + gchar *keyfile; +}; + +G_DEFINE_TYPE (GstEncodingTarget, gst_encoding_target, GST_TYPE_MINI_OBJECT); + +static void +gst_encoding_target_init (GstEncodingTarget * target) +{ + /* Nothing to initialize */ +} + +static void +gst_encoding_target_finalize (GstEncodingTarget * target) +{ + GST_DEBUG ("Finalizing"); + + if (target->name) + g_free (target->name); + if (target->category) + g_free (target->category); + if (target->description) + g_free (target->description); + + g_list_foreach (target->profiles, (GFunc) gst_mini_object_unref, NULL); + g_list_free (target->profiles); +} + +static void +gst_encoding_target_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_encoding_target_finalize; +} + +/** + * gst_encoding_target_get_name: + * @target: a #GstEncodingTarget + * + * Since: 0.10.32 + * + * Returns: (transfer none): The name of the @target. + */ +const gchar * +gst_encoding_target_get_name (GstEncodingTarget * target) +{ + return target->name; +} + +/** + * gst_encoding_target_get_category: + * @target: a #GstEncodingTarget + * + * Since: 0.10.32 + * + * Returns: (transfer none): The category of the @target. For example: + * #GST_ENCODING_CATEGORY_DEVICE. + */ +const gchar * +gst_encoding_target_get_category (GstEncodingTarget * target) +{ + return target->category; +} + +/** + * gst_encoding_target_get_description: + * @target: a #GstEncodingTarget + * + * Since: 0.10.32 + * + * Returns: (transfer none): The description of the @target. + */ +const gchar * +gst_encoding_target_get_description (GstEncodingTarget * target) +{ + return target->description; +} + +/** + * gst_encoding_target_get_profiles: + * @target: a #GstEncodingTarget + * + * Since: 0.10.32 + * + * Returns: (transfer none) (element-type Gst.EncodingProfile): A list of + * #GstEncodingProfile(s) this @target handles. + */ +const GList * +gst_encoding_target_get_profiles (GstEncodingTarget * target) +{ + return target->profiles; +} + +/** + * gst_encoding_target_get_profile: + * @target: a #GstEncodingTarget + * @name: the name of the profile to retrieve + * + * Since: 0.10.32 + * + * Returns: (transfer full): The matching #GstEncodingProfile, or %NULL. + */ +GstEncodingProfile * +gst_encoding_target_get_profile (GstEncodingTarget * target, const gchar * name) +{ + GList *tmp; + + g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), NULL); + g_return_val_if_fail (name != NULL, NULL); + + for (tmp = target->profiles; tmp; tmp = tmp->next) { + GstEncodingProfile *tprof = (GstEncodingProfile *) tmp->data; + + if (!g_strcmp0 (gst_encoding_profile_get_name (tprof), name)) { + gst_encoding_profile_ref (tprof); + return tprof; + } + } + + return NULL; +} + +static inline gboolean +validate_name (const gchar * name) +{ + guint i, len; + + len = strlen (name); + if (len == 0) + return FALSE; + + /* First character can only be a lower case ASCII character */ + if (!g_ascii_isalpha (name[0]) || !g_ascii_islower (name[0])) + return FALSE; + + /* All following characters can only by: + * either a lower case ASCII character + * or an hyphen + * or a numeric */ + for (i = 1; i < len; i++) { + /* if uppercase ASCII letter, return */ + if (g_ascii_isupper (name[i])) + return FALSE; + /* if a digit, continue */ + if (g_ascii_isdigit (name[i])) + continue; + /* if an hyphen, continue */ + if (name[i] == '-') + continue; + /* remaining should only be ascii letters */ + if (!g_ascii_isalpha (name[i])) + return FALSE; + } + + return TRUE; +} + +/** + * gst_encoding_target_new: + * @name: The name of the target. + * @category: (transfer none): The name of the category to which this @target + * belongs. For example: #GST_ENCODING_CATEGORY_DEVICE. + * @description: (transfer none): A description of #GstEncodingTarget in the + * current locale. + * @profiles: (transfer none) (element-type Gst.EncodingProfile): A #GList of + * #GstEncodingProfile. + * + * Creates a new #GstEncodingTarget. + * + * The name and category can only consist of lowercase ASCII letters for the + * first character, followed by either lowercase ASCII letters, digits or + * hyphens ('-'). + * + * The @category should be one of the existing + * well-defined categories, like #GST_ENCODING_CATEGORY_DEVICE, but it + * can be a application or user specific category if + * needed. + * + * Since: 0.10.32 + * + * Returns: (transfer full): The newly created #GstEncodingTarget or %NULL if + * there was an error. + */ + +GstEncodingTarget * +gst_encoding_target_new (const gchar * name, const gchar * category, + const gchar * description, const GList * profiles) +{ + GstEncodingTarget *res; + + g_return_val_if_fail (name != NULL, NULL); + g_return_val_if_fail (category != NULL, NULL); + g_return_val_if_fail (description != NULL, NULL); + + /* Validate name */ + if (!validate_name (name)) + goto invalid_name; + if (!validate_name (category)) + goto invalid_category; + + res = (GstEncodingTarget *) gst_mini_object_new (GST_TYPE_ENCODING_TARGET); + res->name = g_strdup (name); + res->category = g_strdup (category); + res->description = g_strdup (description); + + while (profiles) { + GstEncodingProfile *prof = (GstEncodingProfile *) profiles->data; + + res->profiles = + g_list_append (res->profiles, gst_encoding_profile_ref (prof)); + profiles = profiles->next; + } + + return res; + +invalid_name: + { + GST_ERROR ("Invalid name for encoding target : '%s'", name); + return NULL; + } + +invalid_category: + { + GST_ERROR ("Invalid name for encoding category : '%s'", category); + return NULL; + } +} + +/** + * gst_encoding_target_add_profile: + * @target: the #GstEncodingTarget to add a profile to + * @profile: (transfer full): the #GstEncodingProfile to add + * + * Adds the given @profile to the @target. Each added profile must have + * a unique name within the profile. + * + * The @target will steal a reference to the @profile. If you wish to use + * the profile after calling this method, you should increase its reference + * count. + * + * Since: 0.10.32 + * + * Returns: %TRUE if the profile was added, else %FALSE. + **/ + +gboolean +gst_encoding_target_add_profile (GstEncodingTarget * target, + GstEncodingProfile * profile) +{ + GList *tmp; + + g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE); + g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE); + + /* Make sure profile isn't already controlled by this target */ + for (tmp = target->profiles; tmp; tmp = tmp->next) { + GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data; + + if (!g_strcmp0 (gst_encoding_profile_get_name (profile), + gst_encoding_profile_get_name (prof))) { + GST_WARNING ("Profile already present in target"); + return FALSE; + } + } + + target->profiles = g_list_append (target->profiles, profile); + + return TRUE; +} + +static gboolean +serialize_stream_profiles (GKeyFile * out, GstEncodingProfile * sprof, + const gchar * profilename, guint id) +{ + gchar *sprofgroupname; + gchar *tmpc; + const GstCaps *format, *restriction; + const gchar *preset, *name, *description; + + sprofgroupname = g_strdup_printf ("streamprofile-%s-%d", profilename, id); + + /* Write the parent profile */ + g_key_file_set_value (out, sprofgroupname, "parent", profilename); + + g_key_file_set_value (out, sprofgroupname, "type", + gst_encoding_profile_get_type_nick (sprof)); + + format = gst_encoding_profile_get_format (sprof); + if (format) { + tmpc = gst_caps_to_string (format); + g_key_file_set_value (out, sprofgroupname, "format", tmpc); + g_free (tmpc); + } + + name = gst_encoding_profile_get_name (sprof); + if (name) + g_key_file_set_string (out, sprofgroupname, "name", name); + + description = gst_encoding_profile_get_description (sprof); + if (description) + g_key_file_set_string (out, sprofgroupname, "description", description); + + preset = gst_encoding_profile_get_preset (sprof); + if (preset) + g_key_file_set_string (out, sprofgroupname, "preset", preset); + + restriction = gst_encoding_profile_get_restriction (sprof); + if (restriction) { + tmpc = gst_caps_to_string (restriction); + g_key_file_set_value (out, sprofgroupname, "restriction", tmpc); + g_free (tmpc); + } + g_key_file_set_integer (out, sprofgroupname, "presence", + gst_encoding_profile_get_presence (sprof)); + + if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) { + GstEncodingVideoProfile *vp = (GstEncodingVideoProfile *) sprof; + + g_key_file_set_integer (out, sprofgroupname, "pass", + gst_encoding_video_profile_get_pass (vp)); + g_key_file_set_boolean (out, sprofgroupname, "variableframerate", + gst_encoding_video_profile_get_variableframerate (vp)); + } + + g_free (sprofgroupname); + return TRUE; +} + +static gchar * +get_locale (void) +{ + const char *loc = NULL; + gchar *ret; + +#ifdef ENABLE_NLS +#if defined(LC_MESSAGES) + loc = setlocale (LC_MESSAGES, NULL); + GST_LOG ("LC_MESSAGES: %s", GST_STR_NULL (loc)); +#elif defined(LC_ALL) + loc = setlocale (LC_ALL, NULL); + GST_LOG ("LC_ALL: %s", GST_STR_NULL (loc)); +#else + GST_LOG ("Neither LC_ALL nor LC_MESSAGES defined"); +#endif +#else /* !ENABLE_NLS */ + GST_LOG ("i18n disabled"); +#endif + + if (loc == NULL || g_ascii_strncasecmp (loc, "en", 2) == 0) + return NULL; + + /* en_GB.UTF-8 => en */ + ret = g_ascii_strdown (loc, -1); + ret = g_strcanon (ret, "abcdefghijklmnopqrstuvwxyz", '\0'); + GST_LOG ("using locale: %s", ret); + return ret; +} + +/* Serialize the top-level profiles + * Note: They don't have to be containerprofiles */ +static gboolean +serialize_encoding_profile (GKeyFile * out, GstEncodingProfile * prof) +{ + gchar *profgroupname; + const GList *tmp; + guint i; + const gchar *profname, *profdesc, *profpreset, *proftype; + const GstCaps *profformat; + + profname = gst_encoding_profile_get_name (prof); + profdesc = gst_encoding_profile_get_description (prof); + profformat = gst_encoding_profile_get_format (prof); + profpreset = gst_encoding_profile_get_preset (prof); + proftype = gst_encoding_profile_get_type_nick (prof); + + profgroupname = g_strdup_printf ("profile-%s", profname); + + g_key_file_set_string (out, profgroupname, "name", profname); + + g_key_file_set_value (out, profgroupname, "type", proftype); + + if (profdesc) { + gchar *locale; + + locale = get_locale (); + if (locale != NULL) { + g_key_file_set_locale_string (out, profgroupname, "description", + locale, profdesc); + g_free (locale); + } else { + g_key_file_set_string (out, profgroupname, "description", profdesc); + } + } + if (profformat) { + gchar *tmpc = gst_caps_to_string (profformat); + g_key_file_set_string (out, profgroupname, "format", tmpc); + g_free (tmpc); + } + if (profpreset) + g_key_file_set_string (out, profgroupname, "preset", profpreset); + + /* stream profiles */ + if (GST_IS_ENCODING_CONTAINER_PROFILE (prof)) { + for (tmp = + gst_encoding_container_profile_get_profiles + (GST_ENCODING_CONTAINER_PROFILE (prof)), i = 0; tmp; + tmp = tmp->next, i++) { + GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data; + + if (!serialize_stream_profiles (out, sprof, profname, i)) + return FALSE; + } + } + g_free (profgroupname); + return TRUE; +} + +static gboolean +serialize_target (GKeyFile * out, GstEncodingTarget * target) +{ + GList *tmp; + + g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "name", target->name); + g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "category", + target->category); + g_key_file_set_string (out, GST_ENCODING_TARGET_HEADER, "description", + target->description); + + for (tmp = target->profiles; tmp; tmp = tmp->next) { + GstEncodingProfile *prof = (GstEncodingProfile *) tmp->data; + if (!serialize_encoding_profile (out, prof)) + return FALSE; + } + + return TRUE; +} + +/** + * parse_encoding_profile: + * @in: a #GKeyFile + * @parentprofilename: the parent profile name (including 'profile-' or 'streamprofile-' header) + * @profilename: the profile name group to parse + * @nbgroups: the number of top-level groups + * @groups: the top-level groups + */ +static GstEncodingProfile * +parse_encoding_profile (GKeyFile * in, gchar * parentprofilename, + gchar * profilename, gsize nbgroups, gchar ** groups) +{ + GstEncodingProfile *sprof = NULL; + gchar **parent; + gchar *proftype, *format, *preset, *restriction, *pname, *description; + GstCaps *formatcaps = NULL; + GstCaps *restrictioncaps = NULL; + gboolean variableframerate; + gint pass, presence; + gsize i, nbencprofiles; + + GST_DEBUG ("parentprofilename : %s , profilename : %s", + parentprofilename, profilename); + + if (parentprofilename) { + gboolean found = FALSE; + + parent = + g_key_file_get_string_list (in, profilename, "parent", + &nbencprofiles, NULL); + if (!parent || !nbencprofiles) { + return NULL; + } + + /* Check if this streamprofile is used in */ + for (i = 0; i < nbencprofiles; i++) { + if (!g_strcmp0 (parent[i], parentprofilename)) { + found = TRUE; + break; + } + } + g_strfreev (parent); + + if (!found) { + GST_DEBUG ("Stream profile '%s' isn't used in profile '%s'", + profilename, parentprofilename); + return NULL; + } + } + + pname = g_key_file_get_value (in, profilename, "name", NULL); + + /* First try to get localized description */ + { + gchar *locale; + + locale = get_locale (); + if (locale != NULL) { + /* will try to fall back to untranslated string if no translation found */ + description = g_key_file_get_locale_string (in, profilename, + "description", locale, NULL); + g_free (locale); + } else { + description = + g_key_file_get_string (in, profilename, "description", NULL); + } + } + + /* Note: a missing description is normal for non-container profiles */ + if (description == NULL) { + GST_LOG ("Missing 'description' field for streamprofile %s", profilename); + } + + /* Parse the remaining fields */ + proftype = g_key_file_get_value (in, profilename, "type", NULL); + if (!proftype) { + GST_WARNING ("Missing 'type' field for streamprofile %s", profilename); + return NULL; + } + + format = g_key_file_get_value (in, profilename, "format", NULL); + if (format) { + formatcaps = gst_caps_from_string (format); + g_free (format); + } + + preset = g_key_file_get_value (in, profilename, "preset", NULL); + + restriction = g_key_file_get_value (in, profilename, "restriction", NULL); + if (restriction) { + restrictioncaps = gst_caps_from_string (restriction); + g_free (restriction); + } + + presence = g_key_file_get_integer (in, profilename, "presence", NULL); + pass = g_key_file_get_integer (in, profilename, "pass", NULL); + variableframerate = + g_key_file_get_boolean (in, profilename, "variableframerate", NULL); + + /* Build the streamprofile ! */ + if (!g_strcmp0 (proftype, "container")) { + GstEncodingProfile *pprof; + + sprof = + (GstEncodingProfile *) gst_encoding_container_profile_new (pname, + description, formatcaps, preset); + /* Now look for the stream profiles */ + for (i = 0; i < nbgroups; i++) { + if (!g_ascii_strncasecmp (groups[i], "streamprofile-", 13)) { + pprof = parse_encoding_profile (in, pname, groups[i], nbgroups, groups); + if (pprof) { + gst_encoding_container_profile_add_profile ( + (GstEncodingContainerProfile *) sprof, pprof); + } + } + } + } else if (!g_strcmp0 (proftype, "video")) { + sprof = + (GstEncodingProfile *) gst_encoding_video_profile_new (formatcaps, + preset, restrictioncaps, presence); + gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile + *) sprof, variableframerate); + gst_encoding_video_profile_set_pass ((GstEncodingVideoProfile *) sprof, + pass); + } else if (!g_strcmp0 (proftype, "audio")) { + sprof = + (GstEncodingProfile *) gst_encoding_audio_profile_new (formatcaps, + preset, restrictioncaps, presence); + } else + GST_ERROR ("Unknown profile format '%s'", proftype); + + if (restrictioncaps) + gst_caps_unref (restrictioncaps); + if (formatcaps) + gst_caps_unref (formatcaps); + + if (pname) + g_free (pname); + if (description) + g_free (description); + if (preset) + g_free (preset); + if (proftype) + g_free (proftype); + + return sprof; +} + +static GstEncodingTarget * +parse_keyfile (GKeyFile * in, gchar * targetname, gchar * categoryname, + gchar * description) +{ + GstEncodingTarget *res = NULL; + GstEncodingProfile *prof; + gchar **groups; + gsize i, nbgroups; + + res = gst_encoding_target_new (targetname, categoryname, description, NULL); + + /* Figure out the various profiles */ + groups = g_key_file_get_groups (in, &nbgroups); + for (i = 0; i < nbgroups; i++) { + if (!g_ascii_strncasecmp (groups[i], "profile-", 8)) { + prof = parse_encoding_profile (in, NULL, groups[i], nbgroups, groups); + if (prof) + gst_encoding_target_add_profile (res, prof); + } + } + + g_strfreev (groups); + + if (targetname) + g_free (targetname); + if (categoryname) + g_free (categoryname); + if (description) + g_free (description); + + return res; +} + +static GKeyFile * +load_file_and_read_header (const gchar * path, gchar ** targetname, + gchar ** categoryname, gchar ** description, GError ** error) +{ + GKeyFile *in; + gboolean res; + GError *key_error = NULL; + + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + in = g_key_file_new (); + + GST_DEBUG ("path:%s", path); + + res = + g_key_file_load_from_file (in, path, + G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &key_error); + if (!res || key_error != NULL) + goto load_error; + + key_error = NULL; + *targetname = + g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "name", &key_error); + if (!*targetname) + goto empty_name; + + *categoryname = + g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "category", NULL); + *description = + g_key_file_get_value (in, GST_ENCODING_TARGET_HEADER, "description", + NULL); + + return in; + +load_error: + { + GST_WARNING ("Unable to read GstEncodingTarget file %s: %s", + path, key_error->message); + g_propagate_error (error, key_error); + g_key_file_free (in); + return NULL; + } + +empty_name: + { + GST_WARNING ("Wrong header in file %s: %s", path, key_error->message); + g_propagate_error (error, key_error); + g_key_file_free (in); + return NULL; + } +} + +/** + * gst_encoding_target_load_from_file: + * @filepath: The file location to load the #GstEncodingTarget from + * @error: If an error occured, this field will be filled in. + * + * Opens the provided file and returns the contained #GstEncodingTarget. + * + * Since: 0.10.32 + * + * Returns: (transfer full): The #GstEncodingTarget contained in the file, else + * %NULL + */ + +GstEncodingTarget * +gst_encoding_target_load_from_file (const gchar * filepath, GError ** error) +{ + GKeyFile *in; + gchar *targetname, *categoryname, *description; + GstEncodingTarget *res = NULL; + + in = load_file_and_read_header (filepath, &targetname, &categoryname, + &description, error); + if (!in) + goto beach; + + res = parse_keyfile (in, targetname, categoryname, description); + + g_key_file_free (in); + +beach: + return res; +} + +/* + * returned list contents must be freed + */ +static GList * +get_matching_filenames (gchar * path, gchar * filename) +{ + GList *res = NULL; + GDir *topdir; + const gchar *subdirname; + + topdir = g_dir_open (path, 0, NULL); + if (G_UNLIKELY (topdir == NULL)) + return NULL; + + while ((subdirname = g_dir_read_name (topdir))) { + gchar *ltmp = g_build_filename (path, subdirname, NULL); + + if (g_file_test (ltmp, G_FILE_TEST_IS_DIR)) { + gchar *tmp = g_build_filename (path, subdirname, filename, NULL); + /* Test to see if we have a file named like that in that directory */ + if (g_file_test (tmp, G_FILE_TEST_EXISTS)) + res = g_list_append (res, tmp); + else + g_free (tmp); + } + g_free (ltmp); + } + + g_dir_close (topdir); + + return res; +} + +static GstEncodingTarget * +gst_encoding_target_subload (gchar * path, const gchar * category, + gchar * lfilename, GError ** error) +{ + GstEncodingTarget *target = NULL; + + if (category) { + gchar *filename; + + filename = g_build_filename (path, category, lfilename, NULL); + target = gst_encoding_target_load_from_file (filename, error); + g_free (filename); + } else { + GList *tmp, *tries = get_matching_filenames (path, lfilename); + + /* Try to find a file named %s.gstprofile in any subdirectories */ + for (tmp = tries; tmp; tmp = tmp->next) { + target = gst_encoding_target_load_from_file ((gchar *) tmp->data, NULL); + if (target) + break; + } + g_list_foreach (tries, (GFunc) g_free, NULL); + if (tries) + g_list_free (tries); + } + + return target; +} + +/** + * gst_encoding_target_load: + * @name: the name of the #GstEncodingTarget to load. + * @category: (allow-none): the name of the target category, like + * #GST_ENCODING_CATEGORY_DEVICE. Can be %NULL + * @error: If an error occured, this field will be filled in. + * + * Searches for the #GstEncodingTarget with the given name, loads it + * and returns it. + * + * If the category name is specified only targets from that category will be + * searched for. + * + * Since: 0.10.32 + * + * Returns: (transfer full): The #GstEncodingTarget if available, else %NULL. + */ +GstEncodingTarget * +gst_encoding_target_load (const gchar * name, const gchar * category, + GError ** error) +{ + gchar *lfilename, *tldir; + GstEncodingTarget *target = NULL; + + g_return_val_if_fail (name != NULL, NULL); + + if (!validate_name (name)) + goto invalid_name; + + if (category && !validate_name (category)) + goto invalid_category; + + lfilename = g_strdup_printf ("%s" GST_ENCODING_TARGET_SUFFIX, name); + + /* Try from local profiles */ + tldir = + g_build_filename (g_get_home_dir (), ".gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + target = gst_encoding_target_subload (tldir, category, lfilename, error); + g_free (tldir); + + if (target == NULL) { + /* Try from system-wide profiles */ + tldir = + g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + target = gst_encoding_target_subload (tldir, category, lfilename, error); + g_free (tldir); + } + + g_free (lfilename); + + return target; + +invalid_name: + { + GST_ERROR ("Invalid name for encoding target : '%s'", name); + return NULL; + } +invalid_category: + { + GST_ERROR ("Invalid name for encoding category : '%s'", category); + return NULL; + } +} + +/** + * gst_encoding_target_save_to_file: + * @target: a #GstEncodingTarget + * @filepath: the location to store the @target at. + * @error: If an error occured, this field will be filled in. + * + * Saves the @target to the provided file location. + * + * Since: 0.10.32 + * + * Returns: %TRUE if the target was correctly saved, else %FALSE. + **/ + +gboolean +gst_encoding_target_save_to_file (GstEncodingTarget * target, + const gchar * filepath, GError ** error) +{ + GKeyFile *out; + gchar *data; + gsize data_size; + + g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE); + g_return_val_if_fail (filepath != NULL, FALSE); + + /* FIXME : Check filepath is valid and writable + * FIXME : Strip out profiles already present in system target */ + + /* Get unique name... */ + + /* Create output GKeyFile */ + out = g_key_file_new (); + + if (!serialize_target (out, target)) + goto serialize_failure; + + if (!(data = g_key_file_to_data (out, &data_size, error))) + goto convert_failed; + + if (!g_file_set_contents (filepath, data, data_size, error)) + goto write_failed; + + g_key_file_free (out); + g_free (data); + + return TRUE; + +serialize_failure: + { + GST_ERROR ("Failure serializing target"); + g_key_file_free (out); + return FALSE; + } + +convert_failed: + { + GST_ERROR ("Failure converting keyfile: %s", (*error)->message); + g_key_file_free (out); + g_free (data); + return FALSE; + } + +write_failed: + { + GST_ERROR ("Unable to write file %s: %s", filepath, (*error)->message); + g_key_file_free (out); + g_free (data); + return FALSE; + } +} + +/** + * gst_encoding_target_save: + * @target: a #GstEncodingTarget + * @error: If an error occured, this field will be filled in. + * + * Saves the @target to a default user-local directory. + * + * Since: 0.10.32 + * + * Returns: %TRUE if the target was correctly saved, else %FALSE. + **/ + +gboolean +gst_encoding_target_save (GstEncodingTarget * target, GError ** error) +{ + gchar *filename; + gchar *lfilename; + + g_return_val_if_fail (GST_IS_ENCODING_TARGET (target), FALSE); + g_return_val_if_fail (target->category != NULL, FALSE); + + lfilename = g_strdup_printf ("%s" GST_ENCODING_TARGET_SUFFIX, target->name); + filename = + g_build_filename (g_get_home_dir (), ".gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, target->category, lfilename, NULL); + g_free (lfilename); + + gst_encoding_target_save_to_file (target, filename, error); + g_free (filename); + + return TRUE; +} + +static GList * +get_categories (gchar * path) +{ + GList *res = NULL; + GDir *topdir; + const gchar *subdirname; + + topdir = g_dir_open (path, 0, NULL); + if (G_UNLIKELY (topdir == NULL)) + return NULL; + + while ((subdirname = g_dir_read_name (topdir))) { + gchar *ltmp = g_build_filename (path, subdirname, NULL); + + if (g_file_test (ltmp, G_FILE_TEST_IS_DIR)) { + res = g_list_append (res, (gpointer) g_strdup (subdirname)); + } + g_free (ltmp); + } + + g_dir_close (topdir); + + return res; +} + +/** + * gst_encoding_list_available_categories: + * + * Lists all #GstEncodingTarget categories present on disk. + * + * Returns: (transfer full) (element-type gchar*): A list + * of #GstEncodingTarget categories. + * + * Since: 0.10.32 + */ +GList * +gst_encoding_list_available_categories (void) +{ + GList *res = NULL; + GList *tmp1, *tmp2; + gchar *topdir; + + /* First try user-local categories */ + topdir = g_build_filename (g_get_home_dir (), ".gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + res = get_categories (topdir); + g_free (topdir); + + /* Extend with system-wide categories */ + topdir = g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + tmp1 = get_categories (topdir); + g_free (topdir); + + for (tmp2 = tmp1; tmp2; tmp2 = tmp2->next) { + gchar *name = (gchar *) tmp2->data; + if (!g_list_find_custom (res, name, (GCompareFunc) g_strcmp0)) + res = g_list_append (res, (gpointer) name); + else + g_free (name); + } + g_free (tmp1); + + return res; +} + +static inline GList * +sub_get_all_targets (gchar * subdir) +{ + GList *res = NULL; + const gchar *filename; + GDir *dir; + GstEncodingTarget *target; + + dir = g_dir_open (subdir, 0, NULL); + if (G_UNLIKELY (dir == NULL)) + return NULL; + + while ((filename = g_dir_read_name (dir))) { + gchar *fullname; + + /* Only try files ending with .gstprofile */ + if (!g_str_has_suffix (filename, GST_ENCODING_TARGET_SUFFIX)) + continue; + + fullname = g_build_filename (subdir, filename, NULL); + target = gst_encoding_target_load_from_file (fullname, NULL); + if (target) { + res = g_list_append (res, target); + } else + GST_WARNING ("Failed to get a target from %s", fullname); + g_free (fullname); + } + g_dir_close (dir); + + return res; +} + +static inline GList * +get_all_targets (gchar * topdir, const gchar * categoryname) +{ + GList *res = NULL; + + if (categoryname) { + gchar *subdir = g_build_filename (topdir, categoryname, NULL); + /* Try to open the directory */ + res = sub_get_all_targets (subdir); + g_free (subdir); + } else { + const gchar *subdirname; + GDir *dir = g_dir_open (topdir, 0, NULL); + + if (G_UNLIKELY (dir == NULL)) + return NULL; + + while ((subdirname = g_dir_read_name (dir))) { + gchar *ltmp = g_build_filename (topdir, subdirname, NULL); + + if (g_file_test (ltmp, G_FILE_TEST_IS_DIR)) { + res = g_list_concat (res, sub_get_all_targets (ltmp)); + } + g_free (ltmp); + } + g_dir_close (dir); + } + + return res; +} + +static guint +compare_targets (const GstEncodingTarget * ta, const GstEncodingTarget * tb) +{ + if (!g_strcmp0 (ta->name, tb->name) + && !g_strcmp0 (ta->category, tb->category)) + return -1; + + return 0; +} + +/** + * gst_encoding_list_all_targets: + * @categoryname: (allow-none): The category, for ex: #GST_ENCODING_CATEGORY_DEVICE. + * Can be %NULL. + * + * List all available #GstEncodingTarget for the specified category, or all categories + * if @categoryname is %NULL. + * + * Returns: (transfer full) (element-type GstEncodingTarget): The list of #GstEncodingTarget + * + * Since: 0.10.32 + */ +GList * +gst_encoding_list_all_targets (const gchar * categoryname) +{ + GList *res; + GList *tmp1, *tmp2; + gchar *topdir; + + /* Get user-locals */ + topdir = g_build_filename (g_get_home_dir (), ".gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + res = get_all_targets (topdir, categoryname); + g_free (topdir); + + /* Get system-wide */ + topdir = g_build_filename (GST_DATADIR, "gstreamer-" GST_MAJORMINOR, + GST_ENCODING_TARGET_DIRECTORY, NULL); + tmp1 = get_all_targets (topdir, categoryname); + g_free (topdir); + + /* Merge system-wide targets */ + /* FIXME : We should merge the system-wide profiles into the user-locals + * instead of stopping at identical target names */ + for (tmp2 = tmp1; tmp2; tmp2 = tmp2->next) { + GstEncodingTarget *target = (GstEncodingTarget *) tmp2->data; + if (g_list_find_custom (res, target, (GCompareFunc) compare_targets)) + gst_encoding_target_unref (target); + else + res = g_list_append (res, target); + } + g_list_free (tmp1); + + return res; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.h new file mode 100644 index 0000000..70c049d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/encoding-target.h @@ -0,0 +1,147 @@ +/* GStreamer encoding profile registry + * Copyright (C) 2010 Edward Hervey + * (C) 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PROFILE_REGISTRY_H__ +#define __GST_PROFILE_REGISTRY_H__ + +#include + +G_BEGIN_DECLS + + +/* FIXME/UNKNOWNS + * + * Should encoding categories be well-known strings/quarks ? + * + */ + +/** + * GST_ENCODING_CATEGORY_DEVICE: + * + * #GstEncodingTarget category for device-specific targets. + * The name of the target will usually be the contructor and model of the device, + * and that target will contain #GstEncodingProfiles suitable for that device. + */ +#define GST_ENCODING_CATEGORY_DEVICE "device" + +/** + * GST_ENCODING_CATEGORY_ONLINE_SERVICE: + * + * #GstEncodingTarget category for online-services. + * The name of the target will usually be the name of the online service + * and that target will contain #GstEncodingProfiles suitable for that online + * service. + */ + +#define GST_ENCODING_CATEGORY_ONLINE_SERVICE "online-service" + +/** + * GST_ENCODING_CATEGORY_STORAGE_EDITING: + * + * #GstEncodingTarget category for storage, archiving and editing targets. + * Those targets can be lossless and/or provide very fast random access content. + * The name of the target will usually be the container type or editing target, + * and that target will contain #GstEncodingProfiles suitable for editing or + * storage. + */ +#define GST_ENCODING_CATEGORY_STORAGE_EDITING "storage-editing" + +/** + * GST_ENCODING_CATEGORY_CAPTURE: + * + * #GstEncodingTarget category for recording and capture. + * Targets within this category are optimized for low latency encoding. + */ +#define GST_ENCODING_CATEGORY_CAPTURE "capture" + +/** + * GstEncodingTarget: + * + * Collection of #GstEncodingProfile for a specific target or use-case. + * + * When being stored/loaded, targets come from a specific category, like + * #GST_ENCODING_CATEGORY_DEVICE. + * + * Since: 0.10.32 + */ +#define GST_TYPE_ENCODING_TARGET \ + (gst_encoding_target_get_type ()) +#define GST_ENCODING_TARGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODING_TARGET, GstEncodingTarget)) +#define GST_IS_ENCODING_TARGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODING_TARGET)) + +typedef struct _GstEncodingTarget GstEncodingTarget; +typedef GstMiniObjectClass GstEncodingTargetClass; + +GType gst_encoding_target_get_type (void); + +/** + * gst_encoding_target_unref: + * @target: a #GstEncodingTarget + * + * Decreases the reference count of the @target, possibly freeing it. + * + * Since: 0.10.32 + */ +#define gst_encoding_target_unref(target) \ + (gst_mini_object_unref ((GstMiniObject*) target)) + +/** + * gst_encoding_target_ref: + * @target: a #GstEncodingTarget + * + * Increases the reference count of the @target. + * + * Since: 0.10.32 + */ +#define gst_encoding_target_ref(target) \ + (gst_mini_object_ref ((GstMiniObject*) target)) + +GstEncodingTarget * +gst_encoding_target_new (const gchar *name, const gchar *category, + const gchar *description, const GList *profiles); +const gchar *gst_encoding_target_get_name (GstEncodingTarget *target); +const gchar *gst_encoding_target_get_category (GstEncodingTarget *target); +const gchar *gst_encoding_target_get_description (GstEncodingTarget *target); +const GList *gst_encoding_target_get_profiles (GstEncodingTarget *target); +GstEncodingProfile *gst_encoding_target_get_profile (GstEncodingTarget *target, + const gchar *name); + +gboolean +gst_encoding_target_add_profile (GstEncodingTarget *target, GstEncodingProfile *profile); + +gboolean gst_encoding_target_save (GstEncodingTarget *target, + GError **error); +gboolean gst_encoding_target_save_to_file (GstEncodingTarget *target, + const gchar *filepath, + GError **error); +GstEncodingTarget *gst_encoding_target_load (const gchar *name, + const gchar *category, + GError **error); +GstEncodingTarget *gst_encoding_target_load_from_file (const gchar *filepath, + GError **error); + +GList *gst_encoding_list_available_categories (void); +GList *gst_encoding_list_all_targets (const gchar * categoryname); + +G_END_DECLS + +#endif /* __GST_PROFILE_REGISTRY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer-types.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer-types.c new file mode 100644 index 0000000..2edf8e9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer-types.c @@ -0,0 +1,983 @@ +/* GStreamer + * Copyright (C) 2010 Collabora Multimedia + * 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "pbutils.h" +#include "pbutils-private.h" + +static GstDiscovererStreamInfo + * gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info, + GHashTable * stream_map); + +static GstDiscovererContainerInfo + * gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr, + GHashTable * stream_map); + +static GstDiscovererAudioInfo + * gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr); + +static GstDiscovererVideoInfo + * gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr); + +/* Per-stream information */ + +G_DEFINE_TYPE (GstDiscovererStreamInfo, gst_discoverer_stream_info, + GST_TYPE_MINI_OBJECT); + +static void +gst_discoverer_stream_info_init (GstDiscovererStreamInfo * info) +{ + /* Nothing needs initialization */ +} + +static void +gst_discoverer_stream_info_finalize (GstDiscovererStreamInfo * info) +{ + if (info->next) + gst_mini_object_unref ((GstMiniObject *) info->next); + + if (info->caps) + gst_caps_unref (info->caps); + + if (info->tags) + gst_tag_list_free (info->tags); + + if (info->misc) + gst_structure_free (info->misc); +} + +static GstDiscovererStreamInfo * +gst_discoverer_stream_info_copy (GstDiscovererStreamInfo * info) +{ + return gst_discoverer_info_copy_int (info, NULL); +} + +static void +gst_discoverer_stream_info_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_discoverer_stream_info_finalize; + klass->copy = (GstMiniObjectCopyFunction) gst_discoverer_stream_info_copy; +} + +static GstDiscovererStreamInfo * +gst_discoverer_stream_info_new (void) +{ + return (GstDiscovererStreamInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_STREAM_INFO); +} + +static GstDiscovererStreamInfo * +gst_discoverer_info_copy_int (GstDiscovererStreamInfo * info, + GHashTable * stream_map) +{ + GstDiscovererStreamInfo *ret; + GType ltyp; + + g_return_val_if_fail (info != NULL, NULL); + + ltyp = G_TYPE_FROM_INSTANCE (info); + + if (ltyp == GST_TYPE_DISCOVERER_CONTAINER_INFO) { + ret = (GstDiscovererStreamInfo *) + gst_stream_container_info_copy_int ( + (GstDiscovererContainerInfo *) info, stream_map); + } else if (ltyp == GST_TYPE_DISCOVERER_AUDIO_INFO) { + ret = (GstDiscovererStreamInfo *) + gst_discoverer_audio_info_copy_int ((GstDiscovererAudioInfo *) info); + + } else if (ltyp == GST_TYPE_DISCOVERER_VIDEO_INFO) { + ret = (GstDiscovererStreamInfo *) + gst_discoverer_video_info_copy_int ((GstDiscovererVideoInfo *) info); + + } else + ret = gst_discoverer_stream_info_new (); + + if (info->next) { + ret->next = gst_discoverer_info_copy_int (info->next, stream_map); + ret->next->previous = ret; + } + + if (info->caps) + ret->caps = gst_caps_copy (info->caps); + + if (info->tags) + ret->tags = gst_tag_list_copy (info->tags); + + if (info->misc) + ret->misc = gst_structure_copy (info->misc); + + if (stream_map) + g_hash_table_insert (stream_map, info, ret); + + return ret; +} + +/* Container information */ +G_DEFINE_TYPE (GstDiscovererContainerInfo, gst_discoverer_container_info, + GST_TYPE_DISCOVERER_STREAM_INFO); + +static void +gst_discoverer_container_info_init (GstDiscovererContainerInfo * info) +{ + /* Nothing to initialize */ +} + +static GstDiscovererContainerInfo * +gst_discoverer_container_info_new (void) +{ + return (GstDiscovererContainerInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO); +} + +static void +gst_discoverer_container_info_finalize (GstDiscovererContainerInfo * info) +{ + GList *tmp; + + for (tmp = ((GstDiscovererContainerInfo *) info)->streams; tmp; + tmp = tmp->next) + gst_mini_object_unref ((GstMiniObject *) tmp->data); + + gst_discoverer_stream_info_list_free (info->streams); + + gst_discoverer_stream_info_finalize ((GstDiscovererStreamInfo *) info); +} + +static void +gst_discoverer_container_info_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_discoverer_container_info_finalize; +} + +static GstDiscovererContainerInfo * +gst_stream_container_info_copy_int (GstDiscovererContainerInfo * ptr, + GHashTable * stream_map) +{ + GstDiscovererContainerInfo *ret; + GList *tmp; + + g_return_val_if_fail (ptr != NULL, NULL); + + ret = gst_discoverer_container_info_new (); + + for (tmp = ((GstDiscovererContainerInfo *) ptr)->streams; tmp; + tmp = tmp->next) { + GstDiscovererStreamInfo *subtop = gst_discoverer_info_copy_int (tmp->data, + stream_map); + ret->streams = g_list_append (ret->streams, subtop); + if (stream_map) + g_hash_table_insert (stream_map, tmp->data, subtop); + } + + return ret; +} + +/* Audio information */ +G_DEFINE_TYPE (GstDiscovererAudioInfo, gst_discoverer_audio_info, + GST_TYPE_DISCOVERER_STREAM_INFO); + +static void +gst_discoverer_audio_info_class_init (GstDiscovererAudioInfoClass * klass) +{ + /* Nothing to initialize */ +} + +static void +gst_discoverer_audio_info_init (GstDiscovererAudioInfo * info) +{ + /* Nothing to initialize */ +} + +static GstDiscovererAudioInfo * +gst_discoverer_audio_info_new (void) +{ + return (GstDiscovererAudioInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO); +} + +static GstDiscovererAudioInfo * +gst_discoverer_audio_info_copy_int (GstDiscovererAudioInfo * ptr) +{ + GstDiscovererAudioInfo *ret; + + ret = gst_discoverer_audio_info_new (); + + ret->channels = ptr->channels; + ret->sample_rate = ptr->sample_rate; + ret->depth = ptr->depth; + ret->bitrate = ptr->bitrate; + ret->max_bitrate = ptr->max_bitrate; + + return ret; +} + +/* Video information */ +G_DEFINE_TYPE (GstDiscovererVideoInfo, gst_discoverer_video_info, + GST_TYPE_DISCOVERER_STREAM_INFO); + +static void +gst_discoverer_video_info_class_init (GstMiniObjectClass * klass) +{ + /* Nothing to initialize */ +} + +static void +gst_discoverer_video_info_init (GstDiscovererVideoInfo * info) +{ + /* Nothing to initialize */ +} + +static GstDiscovererVideoInfo * +gst_discoverer_video_info_new (void) +{ + return (GstDiscovererVideoInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO); +} + +static GstDiscovererVideoInfo * +gst_discoverer_video_info_copy_int (GstDiscovererVideoInfo * ptr) +{ + GstDiscovererVideoInfo *ret; + + ret = gst_discoverer_video_info_new (); + + ret->width = ptr->width; + ret->height = ptr->height; + ret->depth = ptr->depth; + ret->framerate_num = ptr->framerate_num; + ret->framerate_denom = ptr->framerate_denom; + ret->par_num = ptr->par_num; + ret->par_denom = ptr->par_denom; + ret->interlaced = ptr->interlaced; + ret->bitrate = ptr->bitrate; + ret->max_bitrate = ptr->max_bitrate; + ret->is_image = ptr->is_image; + + return ret; +} + +/* Global stream information */ +G_DEFINE_TYPE (GstDiscovererInfo, gst_discoverer_info, GST_TYPE_MINI_OBJECT); + +static void +gst_discoverer_info_init (GstDiscovererInfo * info) +{ + /* Nothing needs initialization */ +} + +static void +gst_discoverer_info_finalize (GstDiscovererInfo * info) +{ + g_free (info->uri); + + if (info->stream_info) + gst_mini_object_unref ((GstMiniObject *) info->stream_info); + + if (info->misc) + gst_structure_free (info->misc); + + g_list_free (info->stream_list); + + if (info->tags) + gst_tag_list_free (info->tags); +} + +static GstDiscovererInfo * +gst_discoverer_info_new (void) +{ + return (GstDiscovererInfo *) gst_mini_object_new (GST_TYPE_DISCOVERER_INFO); +} + +GstDiscovererInfo * +gst_discoverer_info_copy (GstDiscovererInfo * ptr) +{ + GstDiscovererInfo *ret; + GHashTable *stream_map = g_hash_table_new (g_direct_hash, NULL); + GList *tmp; + + g_return_val_if_fail (ptr != NULL, NULL); + + ret = gst_discoverer_info_new (); + + ret->uri = g_strdup (ptr->uri); + if (ptr->stream_info) { + ret->stream_info = gst_discoverer_info_copy_int (ptr->stream_info, + stream_map); + } + ret->duration = ptr->duration; + if (ptr->misc) + ret->misc = gst_structure_copy (ptr->misc); + + /* We need to set up the new list of streams to correspond to old one. The + * list just contains a set of pointers to streams in the stream_info tree, + * so we keep a map of old stream info objects to the corresponding new + * ones and use that to figure out correspondence in stream_list. */ + for (tmp = ptr->stream_list; tmp; tmp = tmp->next) { + GstDiscovererStreamInfo *old_stream = (GstDiscovererStreamInfo *) tmp->data; + GstDiscovererStreamInfo *new_stream = g_hash_table_lookup (stream_map, + old_stream); + g_assert (new_stream != NULL); + ret->stream_list = g_list_append (ret->stream_list, new_stream); + } + + if (ptr->tags) + ret->tags = gst_tag_list_copy (ptr->tags); + + g_hash_table_destroy (stream_map); + return ret; +} + +static void +gst_discoverer_info_class_init (GstMiniObjectClass * klass) +{ + klass->finalize = + (GstMiniObjectFinalizeFunction) gst_discoverer_info_finalize; + klass->copy = (GstMiniObjectCopyFunction) gst_discoverer_info_copy; +} + +/** + * gst_discoverer_stream_info_list_free: + * @infos: a #GList of #GstDiscovererStreamInfo + * + * Decrements the reference count of all contained #GstDiscovererStreamInfo + * and fress the #GList. + */ +void +gst_discoverer_stream_info_list_free (GList * infos) +{ + GList *tmp; + + for (tmp = infos; tmp; tmp = tmp->next) + gst_discoverer_stream_info_unref ((GstDiscovererStreamInfo *) tmp->data); + g_list_free (infos); +} + +/** + * gst_discoverer_info_get_streams: + * @info: a #GstDiscovererInfo + * @streamtype: a #GType derived from #GstDiscovererStreamInfo + * + * Finds the #GstDiscovererStreamInfo contained in @info that match the + * given @streamtype. + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of + * matching #GstDiscovererStreamInfo. The caller should free it with + * gst_discoverer_stream_info_list_free(). + * + * Since: 0.10.31 + */ +GList * +gst_discoverer_info_get_streams (GstDiscovererInfo * info, GType streamtype) +{ + GList *tmp, *res = NULL; + + for (tmp = info->stream_list; tmp; tmp = tmp->next) { + GstDiscovererStreamInfo *stmp = (GstDiscovererStreamInfo *) tmp->data; + + if (G_TYPE_CHECK_INSTANCE_TYPE (stmp, streamtype)) + res = g_list_append (res, gst_discoverer_stream_info_ref (stmp)); + } + + return res; +} + +/** + * gst_discoverer_info_get_audio_streams: + * @info: a #GstDiscovererInfo + * + * Finds all the #GstDiscovererAudioInfo contained in @info + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of + * matching #GstDiscovererStreamInfo. The caller should free it with + * gst_discoverer_stream_info_list_free(). + * + * Since: 0.10.31 + */ +GList * +gst_discoverer_info_get_audio_streams (GstDiscovererInfo * info) +{ + return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_AUDIO_INFO); +} + +/** + * gst_discoverer_info_get_video_streams: + * @info: a #GstDiscovererInfo + * + * Finds all the #GstDiscovererVideoInfo contained in @info + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of + * matching #GstDiscovererStreamInfo. The caller should free it with + * gst_discoverer_stream_info_list_free(). + * + * Since: 0.10.31 + */ +GList * +gst_discoverer_info_get_video_streams (GstDiscovererInfo * info) +{ + return gst_discoverer_info_get_streams (info, GST_TYPE_DISCOVERER_VIDEO_INFO); +} + +/** + * gst_discoverer_info_get_container_streams: + * @info: a #GstDiscovererInfo + * + * Finds all the #GstDiscovererContainerInfo contained in @info + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): A #GList of + * matching #GstDiscovererStreamInfo. The caller should free it with + * gst_discoverer_stream_info_list_free(). + * + * Since: 0.10.31 + */ +GList * +gst_discoverer_info_get_container_streams (GstDiscovererInfo * info) +{ + return gst_discoverer_info_get_streams (info, + GST_TYPE_DISCOVERER_CONTAINER_INFO); +} + +/** + * gst_discoverer_stream_info_get_stream_type_nick: + * @info: a #GstDiscovererStreamInfo + * + * Returns: a human readable name for the stream type of the given @info (ex : "audio", + * "container",...). + * + * Since: 0.10.31 + */ +const gchar * +gst_discoverer_stream_info_get_stream_type_nick (GstDiscovererStreamInfo * info) +{ + if (GST_IS_DISCOVERER_CONTAINER_INFO (info)) + return "container"; + if (GST_IS_DISCOVERER_AUDIO_INFO (info)) + return "audio"; + if (GST_IS_DISCOVERER_VIDEO_INFO (info)) { + if (gst_discoverer_video_info_is_image ((GstDiscovererVideoInfo *) + info)) + return "video(image)"; + else + return "video"; + } + return "unknown"; +} + +/* ACCESSORS */ + + +#define GENERIC_ACCESSOR_CODE(parent, parenttype, parentgtype, fieldname, type, failval) \ + type parent##_get_##fieldname(const parenttype info) { \ + g_return_val_if_fail(G_TYPE_CHECK_INSTANCE_TYPE((info), parentgtype), failval); \ + return (info)->fieldname; \ + } + +/** + * gst_discoverer_stream_info_get_previous: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer full): the previous #GstDiscovererStreamInfo in a chain. + * %NULL for starting points. Unref with #gst_discoverer_stream_info_unref + * after usage. + * + * Since: 0.10.31 + */ +GstDiscovererStreamInfo * +gst_discoverer_stream_info_get_previous (GstDiscovererStreamInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL); + + if (info->previous) + return gst_discoverer_stream_info_ref (info->previous); + return NULL; +} + +/** + * gst_discoverer_stream_info_get_next: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer full): the next #GstDiscovererStreamInfo in a chain. %NULL + * for final streams. + * Unref with #gst_discoverer_stream_info_unref after usage. + * + * Since: 0.10.31 + */ +GstDiscovererStreamInfo * +gst_discoverer_stream_info_get_next (GstDiscovererStreamInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL); + + if (info->next) + return gst_discoverer_stream_info_ref (info->next); + return NULL; +} + + +/** + * gst_discoverer_stream_info_get_caps: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer full): the #GstCaps of the stream. Unref with + * #gst_caps_unref after usage. + * + * Since: 0.10.31 + */ +GstCaps * +gst_discoverer_stream_info_get_caps (GstDiscovererStreamInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL); + + if (info->caps) + return gst_caps_ref (info->caps); + return NULL; +} + +/** + * gst_discoverer_stream_info_get_tags: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer none): the tags contained in this stream. If you wish to + * use the tags after the life-time of @info you will need to copy them. + * + * Since: 0.10.31 + */ + +const GstTagList * +gst_discoverer_stream_info_get_tags (GstDiscovererStreamInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL); + + return info->tags; +} + +/** + * gst_discoverer_stream_info_get_misc: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer none): additional information regarding the stream (for + * example codec version, profile, etc..). If you wish to use the #GstStructure + * after the life-time of @info you will need to copy it. + * + * Since: 0.10.31 + */ +const GstStructure * +gst_discoverer_stream_info_get_misc (GstDiscovererStreamInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_STREAM_INFO (info), NULL); + + return info->misc; +} + +/* GstDiscovererContainerInfo */ + +/** + * gst_discoverer_container_info_get_streams: + * @info: a #GstDiscovererStreamInfo + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): the list of + * #GstDiscovererStreamInfo this container stream offers. + * Free with gst_discoverer_stream_info_list_free() after usage. + * + * Since: 0.10.31 + */ + +GList * +gst_discoverer_container_info_get_streams (GstDiscovererContainerInfo * info) +{ + GList *res = NULL, *tmp; + + g_return_val_if_fail (GST_IS_DISCOVERER_CONTAINER_INFO (info), NULL); + + for (tmp = info->streams; tmp; tmp = tmp->next) + res = + g_list_append (res, + gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data)); + + return res; +} + +/* GstDiscovererAudioInfo */ + +#define AUDIO_INFO_ACCESSOR_CODE(fieldname, type, failval) \ + GENERIC_ACCESSOR_CODE(gst_discoverer_audio_info, GstDiscovererAudioInfo*, \ + GST_TYPE_DISCOVERER_AUDIO_INFO, \ + fieldname, type, failval) + +/** + * gst_discoverer_audio_info_get_channels: + * @info: a #GstDiscovererAudioInfo + * + * Returns: the number of channels in the stream. + * + * Since: 0.10.31 + */ + +AUDIO_INFO_ACCESSOR_CODE (channels, guint, 0); + +/** + * gst_discoverer_audio_info_get_sample_rate: + * @info: a #GstDiscovererAudioInfo + * + * Returns: the sample rate of the stream in Hertz. + * + * Since: 0.10.31 + */ + +AUDIO_INFO_ACCESSOR_CODE (sample_rate, guint, 0); + +/** + * gst_discoverer_audio_info_get_depth: + * @info: a #GstDiscovererAudioInfo + * + * Returns: the number of bits used per sample in each channel. + * + * Since: 0.10.31 + */ + +AUDIO_INFO_ACCESSOR_CODE (depth, guint, 0); + +/** + * gst_discoverer_audio_info_get_bitrate: + * @info: a #GstDiscovererAudioInfo + * + * Returns: the average or nominal bitrate of the stream in bits/second. + * + * Since: 0.10.31 + */ + +AUDIO_INFO_ACCESSOR_CODE (bitrate, guint, 0); + +/** + * gst_discoverer_audio_info_get_max_bitrate: + * @info: a #GstDiscovererAudioInfo + * + * Returns: the maximum bitrate of the stream in bits/second. + * + * Since: 0.10.31 + */ + +AUDIO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0); + +/* GstDiscovererVideoInfo */ + +#define VIDEO_INFO_ACCESSOR_CODE(fieldname, type, failval) \ + GENERIC_ACCESSOR_CODE(gst_discoverer_video_info, GstDiscovererVideoInfo*, \ + GST_TYPE_DISCOVERER_VIDEO_INFO, \ + fieldname, type, failval) + +/** + * gst_discoverer_video_info_get_width: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the width of the video stream in pixels. + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (width, guint, 0); + +/** + * gst_discoverer_video_info_get_height: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the height of the video stream in pixels. + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (height, guint, 0); + +/** + * gst_discoverer_video_info_get_depth: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the depth in bits of the video stream. + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (depth, guint, 0); + +/** + * gst_discoverer_video_info_get_framerate_num: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the framerate of the video stream (numerator). + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (framerate_num, guint, 0); + +/** + * gst_discoverer_video_info_get_framerate_denom: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the framerate of the video stream (denominator). + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (framerate_denom, guint, 0); + +/** + * gst_discoverer_video_info_get_par_num: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the Pixel Aspect Ratio (PAR) of the video stream (numerator). + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (par_num, guint, 0); + +/** + * gst_discoverer_video_info_get_par_denom: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the Pixel Aspect Ratio (PAR) of the video stream (denominator). + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (par_denom, guint, 0); + +/** + * gst_discoverer_video_info_is_interlaced: + * @info: a #GstDiscovererVideoInfo + * + * Returns: %TRUE if the stream is interlaced, else %FALSE. + * + * Since: 0.10.31 + */ +gboolean +gst_discoverer_video_info_is_interlaced (const GstDiscovererVideoInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE); + + return info->interlaced; +} + +/** + * gst_discoverer_video_info_get_bitrate: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the average or nominal bitrate of the video stream in bits/second. + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (bitrate, guint, 0); + +/** + * gst_discoverer_video_info_get_max_bitrate: + * @info: a #GstDiscovererVideoInfo + * + * Returns: the maximum bitrate of the video stream in bits/second. + * + * Since: 0.10.31 + */ + +VIDEO_INFO_ACCESSOR_CODE (max_bitrate, guint, 0); + +/** + * gst_discoverer_video_info_is_image: + * @info: a #GstDiscovererVideoInfo + * + * Returns: #TRUE if the video stream corresponds to an image (i.e. only contains + * one frame). + * + * Since: 0.10.31 + */ +gboolean +gst_discoverer_video_info_is_image (const GstDiscovererVideoInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_VIDEO_INFO (info), FALSE); + + return info->is_image; +} + +/* GstDiscovererInfo */ + +#define DISCOVERER_INFO_ACCESSOR_CODE(fieldname, type, failval) \ + GENERIC_ACCESSOR_CODE(gst_discoverer_info, GstDiscovererInfo*, \ + GST_TYPE_DISCOVERER_INFO, \ + fieldname, type, failval) + +/** + * gst_discoverer_info_get_uri: + * @info: a #GstDiscovererInfo + * + * Returns: (transfer none): the URI to which this information corresponds to. + * Copy it if you wish to use it after the life-time of @info. + * + * Since: 0.10.31 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (uri, const gchar *, NULL); + +/** + * gst_discoverer_info_get_result: + * @info: a #GstDiscovererInfo + * + * Returns: the result of the discovery as a #GstDiscovererResult. + * + * Since: 0.10.31 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (result, GstDiscovererResult, GST_DISCOVERER_OK); + +/** + * gst_discoverer_info_get_stream_info: + * @info: a #GstDiscovererInfo + * + * Returns: (transfer full): the structure (or topology) of the URI as a + * #GstDiscovererStreamInfo. + * This structure can be traversed to see the original hierarchy. Unref with + * gst_discoverer_stream_info_unref() after usage. + * + * Since: 0.10.31 + */ + +GstDiscovererStreamInfo * +gst_discoverer_info_get_stream_info (GstDiscovererInfo * info) +{ + g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL); + + if (info->stream_info) + return gst_discoverer_stream_info_ref (info->stream_info); + return NULL; +} + +/** + * gst_discoverer_info_get_stream_list: + * @info: a #GstDiscovererInfo + * + * Returns: (transfer full) (element-type Gst.DiscovererStreamInfo): the list of + * all streams contained in the #info. Free after usage + * with gst_discoverer_stream_info_list_free(). + * + * Since: 0.10.31 + */ +GList * +gst_discoverer_info_get_stream_list (GstDiscovererInfo * info) +{ + GList *res = NULL, *tmp; + + g_return_val_if_fail (GST_IS_DISCOVERER_INFO (info), NULL); + + for (tmp = info->stream_list; tmp; tmp = tmp->next) + res = + g_list_append (res, + gst_discoverer_stream_info_ref ((GstDiscovererStreamInfo *) tmp->data)); + + return res; +} + +/** + * gst_discoverer_info_get_duration: + * @info: a #GstDiscovererInfo + * + * Returns: the duration of the URI in #GstClockTime (nanoseconds). + * + * Since: 0.10.31 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (duration, GstClockTime, GST_CLOCK_TIME_NONE); + +/** + * gst_discoverer_info_get_seekable: + * @info: a #GstDiscovererInfo + * + * Returns: the wheter the URI is seekable. + * + * Since: 0.10.32 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (seekable, gboolean, FALSE); + +/** + * gst_discoverer_info_get_misc: + * @info: a #GstDiscovererInfo + * + * Returns: (transfer none): Miscellaneous information stored as a #GstStructure + * (for example: information about missing plugins). If you wish to use the + * #GstStructure after the life-time of @info, you will need to copy it. + * + * Since: 0.10.31 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (misc, const GstStructure *, NULL); + +/** + * gst_discoverer_info_get_tags: + * @info: a #GstDiscovererInfo + * + * Returns: (transfer none): all tags contained in the %URI. If you wish to use + * the tags after the life-time of @info, you will need to copy them. + * + * Since: 0.10.31 + */ + +DISCOVERER_INFO_ACCESSOR_CODE (tags, const GstTagList *, NULL); + +/** + * gst_discoverer_info_ref: + * @info: a #GstDiscovererInfo + * + * Increments the reference count of @info. + * + * Returns: the same #GstDiscovererInfo object + * + * Since: 0.10.31 + */ + +/** + * gst_discoverer_info_unref: + * @info: a #GstDiscovererInfo + * + * Decrements the reference count of @info. + * + * Since: 0.10.31 + */ + +/** + * gst_discoverer_stream_info_ref: + * @info: a #GstDiscovererStreamInfo + * + * Increments the reference count of @info. + * + * Returns: the same #GstDiscovererStreamInfo object + * + * Since: 0.10.31 + */ + +/** + * gst_discoverer_stream_info_unref: + * @info: a #GstDiscovererStreamInfo + * + * Decrements the reference count of @info. + * + * Since: 0.10.31 + */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.c new file mode 100644 index 0000000..58d3e52 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.c @@ -0,0 +1,1525 @@ +/* GStreamer + * Copyright (C) 2009 Edward Hervey + * 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstdiscoverer + * @short_description: Utility for discovering information on URIs. + * + * The #GstDiscoverer is a utility object which allows to get as much + * information as possible from one or many URIs. + * + * It provides two APIs, allowing usage in blocking or non-blocking mode. + * + * The blocking mode just requires calling gst_discoverer_discover_uri() + * with the URI one wishes to discover. + * + * The non-blocking mode requires a running #GMainLoop in the default + * #GMainContext, where one connects to the various signals, appends the + * URIs to be processed (through gst_discoverer_discover_uri_async()) and then + * asks for the discovery to begin (through gst_discoverer_start()). + * + * All the information is returned in a #GstDiscovererInfo structure. + * + * Since: 0.10.31 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "pbutils.h" +#include "pbutils-marshal.h" +#include "pbutils-private.h" + +GST_DEBUG_CATEGORY_STATIC (discoverer_debug); +#define GST_CAT_DEFAULT discoverer_debug + +static GQuark _CAPS_QUARK; +static GQuark _TAGS_QUARK; +static GQuark _MISSING_PLUGIN_QUARK; +static GQuark _STREAM_TOPOLOGY_QUARK; +static GQuark _TOPOLOGY_PAD_QUARK; + + +typedef struct +{ + GstDiscoverer *dc; + GstPad *pad; + GstElement *queue; + GstElement *sink; + GstTagList *tags; +} PrivateStream; + +struct _GstDiscovererPrivate +{ + gboolean async; + + /* allowed time to discover each uri in nanoseconds */ + GstClockTime timeout; + + /* list of pending URI to process (current excluded) */ + GList *pending_uris; + + GMutex *lock; + + /* TRUE if processing a URI */ + gboolean processing; + + /* TRUE if discoverer has been started */ + gboolean running; + + /* current items */ + GstDiscovererInfo *current_info; + GError *current_error; + GstStructure *current_topology; + + /* List of private streams */ + GList *streams; + + /* Global elements */ + GstBin *pipeline; + GstElement *uridecodebin; + GstBus *bus; + + GType decodebin2_type; + + /* Custom main context variables */ + GMainContext *ctx; + guint sourceid; + guint timeoutid; + + /* reusable queries */ + GstQuery *seeking_query; + + /* Handler ids for various callbacks */ + gulong pad_added_id; + gulong pad_remove_id; + gulong element_added_id; + gulong bus_cb_id; +}; + +#define DISCO_LOCK(dc) g_mutex_lock (dc->priv->lock); +#define DISCO_UNLOCK(dc) g_mutex_unlock (dc->priv->lock); + +static void +_do_init (void) +{ + GST_DEBUG_CATEGORY_INIT (discoverer_debug, "discoverer", 0, "Discoverer"); + + _CAPS_QUARK = g_quark_from_static_string ("caps"); + _TAGS_QUARK = g_quark_from_static_string ("tags"); + _MISSING_PLUGIN_QUARK = g_quark_from_static_string ("missing-plugin"); + _STREAM_TOPOLOGY_QUARK = g_quark_from_static_string ("stream-topology"); + _TOPOLOGY_PAD_QUARK = g_quark_from_static_string ("pad"); +}; + +G_DEFINE_TYPE_EXTENDED (GstDiscoverer, gst_discoverer, G_TYPE_OBJECT, 0, + _do_init ()); + +enum +{ + SIGNAL_FINISHED, + SIGNAL_STARTING, + SIGNAL_DISCOVERED, + LAST_SIGNAL +}; + +#define DEFAULT_PROP_TIMEOUT 15 * GST_SECOND + +enum +{ + PROP_0, + PROP_TIMEOUT +}; + +static guint gst_discoverer_signals[LAST_SIGNAL] = { 0 }; + +static void gst_discoverer_set_timeout (GstDiscoverer * dc, + GstClockTime timeout); +static gboolean async_timeout_cb (GstDiscoverer * dc); + +static void discoverer_bus_cb (GstBus * bus, GstMessage * msg, + GstDiscoverer * dc); +static void uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad, + GstDiscoverer * dc); +static void uridecodebin_pad_removed_cb (GstElement * uridecodebin, + GstPad * pad, GstDiscoverer * dc); + +static void gst_discoverer_dispose (GObject * dc); +static void gst_discoverer_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_discoverer_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void +gst_discoverer_class_init (GstDiscovererClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->dispose = gst_discoverer_dispose; + + gobject_class->set_property = gst_discoverer_set_property; + gobject_class->get_property = gst_discoverer_get_property; + + g_type_class_add_private (klass, sizeof (GstDiscovererPrivate)); + + /* properties */ + /** + * GstDiscoverer:timeout + * + * The duration (in nanoseconds) after which the discovery of an individual + * URI will timeout. + * + * If the discovery of a URI times out, the %GST_DISCOVERER_TIMEOUT will be + * set on the result flags. + */ + g_object_class_install_property (gobject_class, PROP_TIMEOUT, + g_param_spec_uint64 ("timeout", "timeout", "Timeout", + GST_SECOND, 3600 * GST_SECOND, DEFAULT_PROP_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + /* signals */ + /** + * GstDiscoverer::finished: + * @discoverer: the #GstDiscoverer + * + * Will be emitted when all pending URIs have been processed. + */ + gst_discoverer_signals[SIGNAL_FINISHED] = + g_signal_new ("finished", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDiscovererClass, finished), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstDiscoverer::starting: + * @discoverer: the #GstDiscoverer + * + * Will be emitted when the discover starts analyzing the pending URIs + */ + gst_discoverer_signals[SIGNAL_STARTING] = + g_signal_new ("starting", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDiscovererClass, starting), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstDiscoverer::discovered: + * @discoverer: the #GstDiscoverer + * @info: the results #GstDiscovererInfo + * @error: (type GLib.Error): #GError, which will be non-NULL if an error + * occurred during discovery + * + * Will be emitted when all information on a URI could be discovered. + */ + gst_discoverer_signals[SIGNAL_DISCOVERED] = + g_signal_new ("discovered", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDiscovererClass, discovered), + NULL, NULL, pbutils_marshal_VOID__POINTER_BOXED, + G_TYPE_NONE, 2, GST_TYPE_DISCOVERER_INFO, GST_TYPE_G_ERROR); +} + +static void +uridecodebin_element_added_cb (GstElement * uridecodebin, + GstElement * child, GstDiscoverer * dc) +{ + GST_DEBUG ("New element added to uridecodebin : %s", + GST_ELEMENT_NAME (child)); + + if (G_OBJECT_TYPE (child) == dc->priv->decodebin2_type) { + g_object_set (child, "post-stream-topology", TRUE, NULL); + } +} + +static void +gst_discoverer_init (GstDiscoverer * dc) +{ + GstElement *tmp; + GstFormat format = GST_FORMAT_TIME; + + dc->priv = G_TYPE_INSTANCE_GET_PRIVATE (dc, GST_TYPE_DISCOVERER, + GstDiscovererPrivate); + + dc->priv->timeout = DEFAULT_PROP_TIMEOUT; + dc->priv->async = FALSE; + + dc->priv->lock = g_mutex_new (); + + GST_LOG ("Creating pipeline"); + dc->priv->pipeline = (GstBin *) gst_pipeline_new ("Discoverer"); + GST_LOG_OBJECT (dc, "Creating uridecodebin"); + dc->priv->uridecodebin = + gst_element_factory_make ("uridecodebin", "discoverer-uri"); + if (G_UNLIKELY (dc->priv->uridecodebin == NULL)) { + GST_ERROR ("Can't create uridecodebin"); + return; + } + GST_LOG_OBJECT (dc, "Adding uridecodebin to pipeline"); + gst_bin_add (dc->priv->pipeline, dc->priv->uridecodebin); + + dc->priv->pad_added_id = + g_signal_connect_object (dc->priv->uridecodebin, "pad-added", + G_CALLBACK (uridecodebin_pad_added_cb), dc, 0); + dc->priv->pad_remove_id = + g_signal_connect_object (dc->priv->uridecodebin, "pad-removed", + G_CALLBACK (uridecodebin_pad_removed_cb), dc, 0); + + GST_LOG_OBJECT (dc, "Getting pipeline bus"); + dc->priv->bus = gst_pipeline_get_bus ((GstPipeline *) dc->priv->pipeline); + + dc->priv->bus_cb_id = + g_signal_connect_object (dc->priv->bus, "message", + G_CALLBACK (discoverer_bus_cb), dc, 0); + + GST_DEBUG_OBJECT (dc, "Done initializing Discoverer"); + + /* This is ugly. We get the GType of decodebin2 so we can quickly detect + * when a decodebin2 is added to uridecodebin so we can set the + * post-stream-topology setting to TRUE */ + dc->priv->element_added_id = + g_signal_connect_object (dc->priv->uridecodebin, "element-added", + G_CALLBACK (uridecodebin_element_added_cb), dc, 0); + tmp = gst_element_factory_make ("decodebin2", NULL); + dc->priv->decodebin2_type = G_OBJECT_TYPE (tmp); + gst_object_unref (tmp); + + /* create queries */ + dc->priv->seeking_query = gst_query_new_seeking (format); +} + +static void +discoverer_reset (GstDiscoverer * dc) +{ + GST_DEBUG_OBJECT (dc, "Resetting"); + + if (dc->priv->pending_uris) { + g_list_foreach (dc->priv->pending_uris, (GFunc) g_free, NULL); + g_list_free (dc->priv->pending_uris); + dc->priv->pending_uris = NULL; + } + + if (dc->priv->pipeline) + gst_element_set_state ((GstElement *) dc->priv->pipeline, GST_STATE_NULL); +} + +#define DISCONNECT_SIGNAL(o,i) G_STMT_START{ \ + if ((i) && g_signal_handler_is_connected ((o), (i))) \ + g_signal_handler_disconnect ((o), (i)); \ + (i) = 0; \ +}G_STMT_END + +static void +gst_discoverer_dispose (GObject * obj) +{ + GstDiscoverer *dc = (GstDiscoverer *) obj; + + GST_DEBUG_OBJECT (dc, "Disposing"); + + discoverer_reset (dc); + + if (G_LIKELY (dc->priv->pipeline)) { + /* Workaround for bug #118536 */ + DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->pad_added_id); + DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->pad_remove_id); + DISCONNECT_SIGNAL (dc->priv->uridecodebin, dc->priv->element_added_id); + DISCONNECT_SIGNAL (dc->priv->bus, dc->priv->bus_cb_id); + + /* pipeline was set to NULL in _reset */ + gst_object_unref (dc->priv->pipeline); + gst_object_unref (dc->priv->bus); + + dc->priv->pipeline = NULL; + dc->priv->uridecodebin = NULL; + dc->priv->bus = NULL; + } + + gst_discoverer_stop (dc); + + if (dc->priv->lock) { + g_mutex_free (dc->priv->lock); + dc->priv->lock = NULL; + } + + if (dc->priv->seeking_query) { + gst_query_unref (dc->priv->seeking_query); + dc->priv->seeking_query = NULL; + } + + G_OBJECT_CLASS (gst_discoverer_parent_class)->dispose (obj); +} + +static void +gst_discoverer_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDiscoverer *dc = (GstDiscoverer *) object; + + switch (prop_id) { + case PROP_TIMEOUT: + gst_discoverer_set_timeout (dc, g_value_get_uint64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_discoverer_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDiscoverer *dc = (GstDiscoverer *) object; + + switch (prop_id) { + case PROP_TIMEOUT: + DISCO_LOCK (dc); + g_value_set_uint64 (value, dc->priv->timeout); + DISCO_UNLOCK (dc); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_discoverer_set_timeout (GstDiscoverer * dc, GstClockTime timeout) +{ + GST_DEBUG_OBJECT (dc, "timeout : %" GST_TIME_FORMAT, GST_TIME_ARGS (timeout)); + + /* FIXME : update current pending timeout if we're running */ + DISCO_LOCK (dc); + dc->priv->timeout = timeout; + DISCO_UNLOCK (dc); +} + +static gboolean +_event_probe (GstPad * pad, GstEvent * event, PrivateStream * ps) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) { + GstTagList *tl = NULL, *tmp; + + gst_event_parse_tag (event, &tl); + GST_DEBUG_OBJECT (pad, "tags %" GST_PTR_FORMAT, tl); + DISCO_LOCK (ps->dc); + /* If preroll is complete, drop these tags - the collected information is + * possibly already being processed and adding more tags would be racy */ + if (G_LIKELY (ps->dc->priv->processing)) { + GST_DEBUG_OBJECT (pad, "private stream %p old tags %" GST_PTR_FORMAT, ps, + ps->tags); + tmp = gst_tag_list_merge (ps->tags, tl, GST_TAG_MERGE_APPEND); + if (ps->tags) + gst_tag_list_free (ps->tags); + ps->tags = tmp; + GST_DEBUG_OBJECT (pad, "private stream %p new tags %" GST_PTR_FORMAT, ps, + tmp); + } else + GST_DEBUG_OBJECT (pad, "Dropping tags since preroll is done"); + DISCO_UNLOCK (ps->dc); + } + + return TRUE; +} + +static void +uridecodebin_pad_added_cb (GstElement * uridecodebin, GstPad * pad, + GstDiscoverer * dc) +{ + PrivateStream *ps; + GstPad *sinkpad = NULL; + GstCaps *caps; + static GstCaps *subs_caps = NULL; + + if (!subs_caps) { + subs_caps = gst_caps_from_string ("text/plain; text/x-pango-markup; " + "subpicture/x-pgs; subpicture/x-dvb; application/x-subtitle-unknown; " + "application/x-ssa; application/x-ass; subtitle/x-kate; " + "video/x-dvd-subpicture; "); + } + + GST_DEBUG_OBJECT (dc, "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + ps = g_slice_new0 (PrivateStream); + + ps->dc = dc; + ps->pad = pad; + ps->queue = gst_element_factory_make ("queue", NULL); + ps->sink = gst_element_factory_make ("fakesink", NULL); + + if (G_UNLIKELY (ps->queue == NULL || ps->sink == NULL)) + goto error; + + g_object_set (ps->sink, "silent", TRUE, NULL); + g_object_set (ps->queue, "max-size-buffers", 1, "silent", TRUE, NULL); + + caps = gst_pad_get_caps_reffed (pad); + + if (gst_caps_can_intersect (caps, subs_caps)) { + /* Subtitle streams are sparse and don't provide any information - don't + * wait for data to preroll */ + g_object_set (ps->sink, "async", FALSE, NULL); + } + + gst_caps_unref (caps); + + gst_bin_add_many (dc->priv->pipeline, ps->queue, ps->sink, NULL); + + if (!gst_element_link_pads_full (ps->queue, "src", ps->sink, "sink", + GST_PAD_LINK_CHECK_NOTHING)) + goto error; + if (!gst_element_sync_state_with_parent (ps->sink)) + goto error; + if (!gst_element_sync_state_with_parent (ps->queue)) + goto error; + + sinkpad = gst_element_get_static_pad (ps->queue, "sink"); + if (sinkpad == NULL) + goto error; + if (gst_pad_link_full (pad, sinkpad, + GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK) + goto error; + gst_object_unref (sinkpad); + + /* Add an event probe */ + gst_pad_add_event_probe (pad, G_CALLBACK (_event_probe), ps); + + DISCO_LOCK (dc); + dc->priv->streams = g_list_append (dc->priv->streams, ps); + DISCO_UNLOCK (dc); + + GST_DEBUG_OBJECT (dc, "Done handling pad"); + + return; + +error: + GST_ERROR_OBJECT (dc, "Error while handling pad"); + if (sinkpad) + gst_object_unref (sinkpad); + if (ps->queue) + gst_object_unref (ps->queue); + if (ps->sink) + gst_object_unref (ps->sink); + g_slice_free (PrivateStream, ps); + return; +} + +static void +uridecodebin_pad_removed_cb (GstElement * uridecodebin, GstPad * pad, + GstDiscoverer * dc) +{ + GList *tmp; + PrivateStream *ps; + GstPad *sinkpad; + + GST_DEBUG_OBJECT (dc, "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + /* Find the PrivateStream */ + DISCO_LOCK (dc); + for (tmp = dc->priv->streams; tmp; tmp = tmp->next) { + ps = (PrivateStream *) tmp->data; + if (ps->pad == pad) + break; + } + + if (tmp == NULL) { + DISCO_UNLOCK (dc); + GST_DEBUG ("The removed pad wasn't controlled by us !"); + return; + } + + dc->priv->streams = g_list_delete_link (dc->priv->streams, tmp); + DISCO_UNLOCK (dc); + + gst_element_set_state (ps->sink, GST_STATE_NULL); + gst_element_set_state (ps->queue, GST_STATE_NULL); + gst_element_unlink (ps->queue, ps->sink); + + sinkpad = gst_element_get_static_pad (ps->queue, "sink"); + gst_pad_unlink (pad, sinkpad); + gst_object_unref (sinkpad); + + /* references removed here */ + gst_bin_remove_many (dc->priv->pipeline, ps->sink, ps->queue, NULL); + + if (ps->tags) { + gst_tag_list_free (ps->tags); + } + + g_slice_free (PrivateStream, ps); + + GST_DEBUG ("Done handling pad"); +} + +static GstStructure * +collect_stream_information (GstDiscoverer * dc, PrivateStream * ps, guint idx) +{ + GstCaps *caps; + GstStructure *st; + gchar *stname; + + stname = g_strdup_printf ("stream-%02d", idx); + st = gst_structure_empty_new (stname); + g_free (stname); + + /* Get caps */ + caps = gst_pad_get_negotiated_caps (ps->pad); + if (!caps) { + GST_WARNING ("Couldn't get negotiated caps from %s:%s", + GST_DEBUG_PAD_NAME (ps->pad)); + caps = gst_pad_get_caps (ps->pad); + } + if (caps) { + GST_DEBUG ("Got caps %" GST_PTR_FORMAT, caps); + gst_structure_id_set (st, _CAPS_QUARK, GST_TYPE_CAPS, caps, NULL); + + gst_caps_unref (caps); + } + if (ps->tags) + gst_structure_id_set (st, _TAGS_QUARK, GST_TYPE_STRUCTURE, ps->tags, NULL); + + return st; +} + +/* Parses a set of caps and tags in st and populates a GstDiscovererStreamInfo + * structure (parent, if !NULL, otherwise it allocates one) + */ +static GstDiscovererStreamInfo * +collect_information (GstDiscoverer * dc, const GstStructure * st, + GstDiscovererStreamInfo * parent) +{ + GstCaps *caps; + GstStructure *caps_st, *tags_st; + const gchar *name; + int tmp, tmp2; + guint utmp; + gboolean btmp; + + if (!st || !gst_structure_id_has_field (st, _CAPS_QUARK)) { + GST_WARNING ("Couldn't find caps !"); + if (parent) + return parent; + else + return (GstDiscovererStreamInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_STREAM_INFO); + } + + gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL); + caps_st = gst_caps_get_structure (caps, 0); + name = gst_structure_get_name (caps_st); + + if (g_str_has_prefix (name, "audio/")) { + GstDiscovererAudioInfo *info; + + if (parent) + info = (GstDiscovererAudioInfo *) parent; + else { + info = (GstDiscovererAudioInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_AUDIO_INFO); + info->parent.caps = caps; + } + + if (gst_structure_get_int (caps_st, "rate", &tmp)) + info->sample_rate = (guint) tmp; + + if (gst_structure_get_int (caps_st, "channels", &tmp)) + info->channels = (guint) tmp; + + if (gst_structure_get_int (caps_st, "depth", &tmp)) + info->depth = (guint) tmp; + + if (gst_structure_id_has_field (st, _TAGS_QUARK)) { + gst_structure_id_get (st, _TAGS_QUARK, + GST_TYPE_STRUCTURE, &tags_st, NULL); + if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp) || + gst_structure_get_uint (tags_st, GST_TAG_NOMINAL_BITRATE, &utmp)) + info->bitrate = utmp; + + if (gst_structure_get_uint (tags_st, GST_TAG_MAXIMUM_BITRATE, &utmp)) + info->max_bitrate = utmp; + + /* FIXME: Is it worth it to remove the tags we've parsed? */ + info->parent.tags = gst_tag_list_merge (info->parent.tags, + (GstTagList *) tags_st, GST_TAG_MERGE_REPLACE); + + gst_structure_free (tags_st); + } + + return (GstDiscovererStreamInfo *) info; + + } else if (g_str_has_prefix (name, "video/") || + g_str_has_prefix (name, "image/")) { + GstDiscovererVideoInfo *info; + GstVideoFormat format; + + if (parent) + info = (GstDiscovererVideoInfo *) parent; + else { + info = (GstDiscovererVideoInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_VIDEO_INFO); + info->parent.caps = caps; + } + + if (gst_video_format_parse_caps (caps, &format, &tmp, &tmp2)) { + info->width = (guint) tmp; + info->height = (guint) tmp2; + } + + if (gst_structure_get_int (caps_st, "depth", &tmp)) + info->depth = (guint) tmp; + + if (gst_video_parse_caps_pixel_aspect_ratio (caps, &tmp, &tmp2)) { + info->par_num = tmp; + info->par_denom = tmp2; + } + + if (gst_video_parse_caps_framerate (caps, &tmp, &tmp2)) { + info->framerate_num = tmp; + info->framerate_denom = tmp2; + } + + if (gst_video_format_parse_caps_interlaced (caps, &btmp)) + info->interlaced = btmp; + + if (gst_structure_id_has_field (st, _TAGS_QUARK)) { + gst_structure_id_get (st, _TAGS_QUARK, + GST_TYPE_STRUCTURE, &tags_st, NULL); + if (gst_structure_get_uint (tags_st, GST_TAG_BITRATE, &utmp) || + gst_structure_get_uint (tags_st, GST_TAG_NOMINAL_BITRATE, &utmp)) + info->bitrate = utmp; + + if (gst_structure_get_uint (tags_st, GST_TAG_MAXIMUM_BITRATE, &utmp)) + info->max_bitrate = utmp; + + /* FIXME: Is it worth it to remove the tags we've parsed? */ + info->parent.tags = gst_tag_list_merge (info->parent.tags, + (GstTagList *) tags_st, GST_TAG_MERGE_REPLACE); + gst_structure_free (tags_st); + } + + return (GstDiscovererStreamInfo *) info; + + } else { + /* None of the above - populate what information we can */ + GstDiscovererStreamInfo *info; + + if (parent) + info = parent; + else { + info = (GstDiscovererStreamInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_STREAM_INFO); + info->caps = caps; + } + + if (gst_structure_id_get (st, _TAGS_QUARK, + GST_TYPE_STRUCTURE, &tags_st, NULL)) { + info->tags = gst_tag_list_merge (info->tags, (GstTagList *) tags_st, + GST_TAG_MERGE_REPLACE); + gst_structure_free (tags_st); + } + + return info; + } + +} + +static GstStructure * +find_stream_for_node (GstDiscoverer * dc, const GstStructure * topology) +{ + GstPad *pad; + GstPad *target_pad = NULL; + GstStructure *st = NULL; + PrivateStream *ps; + guint i; + GList *tmp; + + if (!gst_structure_id_has_field (topology, _TOPOLOGY_PAD_QUARK)) { + GST_DEBUG ("Could not find pad for node %" GST_PTR_FORMAT "\n", topology); + return NULL; + } + + gst_structure_id_get (topology, _TOPOLOGY_PAD_QUARK, + GST_TYPE_PAD, &pad, NULL); + + if (!dc->priv->streams) + return NULL; + + for (i = 0, tmp = dc->priv->streams; tmp; tmp = tmp->next, i++) { + ps = (PrivateStream *) tmp->data; + + target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (ps->pad)); + gst_object_unref (target_pad); + + if (target_pad == pad) + break; + } + + if (tmp) + st = collect_stream_information (dc, ps, i); + + gst_object_unref (pad); + + return st; +} + +static gboolean +child_is_raw_stream (GstCaps * parent, GstCaps * child) +{ + GstStructure *st1, *st2; + const gchar *name1, *name2; + + st1 = gst_caps_get_structure (parent, 0); + name1 = gst_structure_get_name (st1); + st2 = gst_caps_get_structure (child, 0); + name2 = gst_structure_get_name (st2); + + if ((g_str_has_prefix (name1, "audio/") && + g_str_has_prefix (name2, "audio/x-raw")) || + ((g_str_has_prefix (name1, "video/") || + g_str_has_prefix (name1, "image/")) && + g_str_has_prefix (name2, "video/x-raw"))) { + /* child is the "raw" sub-stream corresponding to parent */ + return TRUE; + } + + return FALSE; +} + +/* If a parent is non-NULL, collected stream information will be appended to it + * (and where the information exists, it will be overriden) + */ +static GstDiscovererStreamInfo * +parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology, + GstDiscovererStreamInfo * parent) +{ + GstDiscovererStreamInfo *res = NULL; + GstCaps *caps = NULL; + const GValue *nval = NULL; + + GST_DEBUG ("parsing: %" GST_PTR_FORMAT, topology); + + nval = gst_structure_get_value (topology, "next"); + + if (nval == NULL || GST_VALUE_HOLDS_STRUCTURE (nval)) { + GstStructure *st = find_stream_for_node (dc, topology); + gboolean add_to_list = TRUE; + + if (st) { + res = collect_information (dc, st, parent); + gst_structure_free (st); + } else { + /* Didn't find a stream structure, so let's just use the caps we have */ + res = collect_information (dc, topology, parent); + } + + if (nval == NULL) { + /* FIXME : aggregate with information from main streams */ + GST_DEBUG ("Coudn't find 'next' ! might be the last entry"); + } else { + GstCaps *caps; + const GstStructure *st; + + st = gst_value_get_structure (nval); + + GST_DEBUG ("next is a structure %" GST_PTR_FORMAT, st); + + if (!parent) + parent = res; + + if (gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL)) { + if (gst_caps_can_intersect (parent->caps, caps)) { + /* We sometimes get an extra sub-stream from the parser. If this is + * the case, we just replace the parent caps with this stream's caps + * since they might contain more information */ + gst_caps_unref (parent->caps); + parent->caps = caps; + + parse_stream_topology (dc, st, parent); + add_to_list = FALSE; + + } else if (child_is_raw_stream (parent->caps, caps)) { + /* This is the "raw" stream corresponding to the parent. This + * contains more information than the parent, tags etc. */ + parse_stream_topology (dc, st, parent); + add_to_list = FALSE; + gst_caps_unref (caps); + + } else { + GstDiscovererStreamInfo *next = parse_stream_topology (dc, st, NULL); + res->next = next; + next->previous = res; + } + } + } + + if (add_to_list) { + dc->priv->current_info->stream_list = + g_list_append (dc->priv->current_info->stream_list, res); + } + + } else if (GST_VALUE_HOLDS_LIST (nval)) { + guint i, len; + GstDiscovererContainerInfo *cont; + GstTagList *tags; + + if (!gst_structure_id_get (topology, _CAPS_QUARK, + GST_TYPE_CAPS, &caps, NULL)) + GST_WARNING ("Couldn't find caps !"); + + len = gst_value_list_get_size (nval); + GST_DEBUG ("next is a list of %d entries", len); + + cont = (GstDiscovererContainerInfo *) + gst_mini_object_new (GST_TYPE_DISCOVERER_CONTAINER_INFO); + cont->parent.caps = caps; + res = (GstDiscovererStreamInfo *) cont; + + if (gst_structure_id_has_field (topology, _TAGS_QUARK)) { + GstTagList *tmp; + + gst_structure_id_get (topology, _TAGS_QUARK, + GST_TYPE_STRUCTURE, &tags, NULL); + + GST_DEBUG ("Merge tags %" GST_PTR_FORMAT, tags); + + tmp = + gst_tag_list_merge (cont->parent.tags, (GstTagList *) tags, + GST_TAG_MERGE_APPEND); + gst_tag_list_free (tags); + if (cont->parent.tags) + gst_tag_list_free (cont->parent.tags); + cont->parent.tags = tmp; + GST_DEBUG ("Container info tags %" GST_PTR_FORMAT, tmp); + } + + for (i = 0; i < len; i++) { + const GValue *subv = gst_value_list_get_value (nval, i); + const GstStructure *subst = gst_value_get_structure (subv); + GstDiscovererStreamInfo *substream; + + GST_DEBUG ("%d %" GST_PTR_FORMAT, i, subst); + + substream = parse_stream_topology (dc, subst, NULL); + + substream->previous = res; + cont->streams = + g_list_append (cont->streams, + gst_discoverer_stream_info_ref (substream)); + } + } + + return res; +} + +/* Called when pipeline is pre-rolled */ +static void +discoverer_collect (GstDiscoverer * dc) +{ + GST_DEBUG ("Collecting information"); + + /* Stop the timeout handler if present */ + if (dc->priv->timeoutid) { + g_source_remove (dc->priv->timeoutid); + dc->priv->timeoutid = 0; + } + + if (dc->priv->streams) { + /* FIXME : Make this querying optional */ + if (TRUE) { + GstElement *pipeline = (GstElement *) dc->priv->pipeline; + GstFormat format = GST_FORMAT_TIME; + gint64 dur; + + GST_DEBUG ("Attempting to query duration"); + + if (gst_element_query_duration (pipeline, &format, &dur)) { + if (format == GST_FORMAT_TIME) { + GST_DEBUG ("Got duration %" GST_TIME_FORMAT, GST_TIME_ARGS (dur)); + dc->priv->current_info->duration = (guint64) dur; + } + } + + if (dc->priv->seeking_query) { + if (gst_element_query (pipeline, dc->priv->seeking_query)) { + gboolean seekable; + + gst_query_parse_seeking (dc->priv->seeking_query, &format, + &seekable, NULL, NULL); + if (format == GST_FORMAT_TIME) { + GST_DEBUG ("Got seekable %d", seekable); + dc->priv->current_info->seekable = seekable; + } + } + } + } + + if (dc->priv->current_topology) + dc->priv->current_info->stream_info = parse_stream_topology (dc, + dc->priv->current_topology, NULL); + + /* + * Images need some special handling. They do not have a duration, have + * caps named image/ (th exception being MJPEG video which is also + * type image/jpeg), and should consist of precisely one stream (actually + * initially there are 2, the image and raw stream, but we squash these + * while parsing the stream topology). At some ponit, if we find that these + * conditions are not sufficient, we can count the number of decoders and + * parsers in the chain, and if there's more than one decoder, or any + * parser at all, we should not mark this as an image. + */ + if (dc->priv->current_info->duration == 0 && + dc->priv->current_info->stream_info != NULL && + dc->priv->current_info->stream_info->next == NULL) { + GstStructure *st = + gst_caps_get_structure (dc->priv->current_info->stream_info->caps, 0); + + if (g_str_has_prefix (gst_structure_get_name (st), "image/")) + ((GstDiscovererVideoInfo *) dc->priv->current_info-> + stream_info)->is_image = TRUE; + } + } + + if (dc->priv->async) { + GST_DEBUG ("Emitting 'discoverered'"); + g_signal_emit (dc, gst_discoverer_signals[SIGNAL_DISCOVERED], 0, + dc->priv->current_info, dc->priv->current_error); + /* Clients get a copy of current_info since it is a boxed type */ + gst_discoverer_info_unref (dc->priv->current_info); + } +} + +static void +get_async_cb (gpointer cb_data, GSource * source, GSourceFunc * func, + gpointer * data) +{ + *func = (GSourceFunc) async_timeout_cb; + *data = cb_data; +} + +/* Wrapper since GSourceCallbackFuncs don't expect a return value from ref() */ +static void +_void_g_object_ref (gpointer object) +{ + g_object_ref (G_OBJECT (object)); +} + +static void +handle_current_async (GstDiscoverer * dc) +{ + GSource *source; + static GSourceCallbackFuncs cb_funcs = { + .ref = _void_g_object_ref, + .unref = g_object_unref, + .get = get_async_cb, + }; + + /* Attach a timeout to the main context */ + source = g_timeout_source_new (dc->priv->timeout / GST_MSECOND); + g_source_set_callback_indirect (source, g_object_ref (dc), &cb_funcs); + dc->priv->timeoutid = g_source_attach (source, dc->priv->ctx); + g_source_unref (source); +} + + +/* Returns TRUE if processing should stop */ +static gboolean +handle_message (GstDiscoverer * dc, GstMessage * msg) +{ + gboolean done = FALSE; + + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "got a %s message", + GST_MESSAGE_TYPE_NAME (msg)); + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR:{ + GError *gerr; + gchar *debug; + + gst_message_parse_error (msg, &gerr, &debug); + GST_WARNING_OBJECT (GST_MESSAGE_SRC (msg), + "Got an error [debug:%s], [message:%s]", debug, gerr->message); + dc->priv->current_error = gerr; + g_free (debug); + + /* We need to stop */ + done = TRUE; + + GST_DEBUG ("Setting result to ERROR"); + dc->priv->current_info->result = GST_DISCOVERER_ERROR; + } + break; + + case GST_MESSAGE_EOS: + GST_DEBUG ("Got EOS !"); + done = TRUE; + break; + + case GST_MESSAGE_ASYNC_DONE: + if (GST_MESSAGE_SRC (msg) == (GstObject *) dc->priv->pipeline) { + GST_DEBUG ("Finished changing state asynchronously"); + done = TRUE; + + } + break; + + case GST_MESSAGE_ELEMENT: + { + GQuark sttype = gst_structure_get_name_id (msg->structure); + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), + "structure %" GST_PTR_FORMAT, msg->structure); + if (sttype == _MISSING_PLUGIN_QUARK) { + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), + "Setting result to MISSING_PLUGINS"); + dc->priv->current_info->result = GST_DISCOVERER_MISSING_PLUGINS; + dc->priv->current_info->misc = gst_structure_copy (msg->structure); + } else if (sttype == _STREAM_TOPOLOGY_QUARK) { + dc->priv->current_topology = gst_structure_copy (msg->structure); + } + } + break; + + case GST_MESSAGE_TAG: + { + GstTagList *tl, *tmp; + + gst_message_parse_tag (msg, &tl); + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Got tags %" GST_PTR_FORMAT, tl); + /* Merge with current tags */ + tmp = + gst_tag_list_merge (dc->priv->current_info->tags, tl, + GST_TAG_MERGE_APPEND); + gst_tag_list_free (tl); + if (dc->priv->current_info->tags) + gst_tag_list_free (dc->priv->current_info->tags); + dc->priv->current_info->tags = tmp; + GST_DEBUG_OBJECT (GST_MESSAGE_SRC (msg), "Current info %p, tags %" + GST_PTR_FORMAT, dc->priv->current_info, tmp); + } + break; + + default: + break; + } + + return done; +} + + +static void +handle_current_sync (GstDiscoverer * dc) +{ + GTimer *timer; + gdouble deadline = ((gdouble) dc->priv->timeout) / GST_SECOND; + GstMessage *msg; + gboolean done = FALSE; + + timer = g_timer_new (); + g_timer_start (timer); + + do { + /* poll bus with timeout */ + /* FIXME : make the timeout more fine-tuned */ + if ((msg = gst_bus_timed_pop (dc->priv->bus, GST_SECOND / 2))) { + done = handle_message (dc, msg); + gst_message_unref (msg); + } + + } while (!done && (g_timer_elapsed (timer, NULL) < deadline)); + + /* return result */ + if (!done) { + GST_DEBUG ("we timed out! Setting result to TIMEOUT"); + dc->priv->current_info->result = GST_DISCOVERER_TIMEOUT; + } + + GST_DEBUG ("Done"); + + g_timer_stop (timer); + g_timer_destroy (timer); +} + +static void +_setup_locked (GstDiscoverer * dc) +{ + GstStateChangeReturn ret; + + GST_DEBUG ("Setting up"); + + /* Pop URI off the pending URI list */ + dc->priv->current_info = + (GstDiscovererInfo *) gst_mini_object_new (GST_TYPE_DISCOVERER_INFO); + dc->priv->current_info->uri = (gchar *) dc->priv->pending_uris->data; + dc->priv->pending_uris = + g_list_delete_link (dc->priv->pending_uris, dc->priv->pending_uris); + + /* set uri on uridecodebin */ + g_object_set (dc->priv->uridecodebin, "uri", dc->priv->current_info->uri, + NULL); + + GST_DEBUG ("Current is now %s", dc->priv->current_info->uri); + + dc->priv->processing = TRUE; + + /* set pipeline to PAUSED */ + DISCO_UNLOCK (dc); + GST_DEBUG ("Setting pipeline to PAUSED"); + ret = + gst_element_set_state ((GstElement *) dc->priv->pipeline, + GST_STATE_PAUSED); + DISCO_LOCK (dc); + + GST_DEBUG_OBJECT (dc, "Pipeline going to PAUSED : %s", + gst_element_state_change_return_get_name (ret)); +} + +static void +discoverer_cleanup (GstDiscoverer * dc) +{ + GST_DEBUG ("Cleaning up"); + + gst_bus_set_flushing (dc->priv->bus, TRUE); + gst_element_set_state ((GstElement *) dc->priv->pipeline, GST_STATE_READY); + gst_bus_set_flushing (dc->priv->bus, FALSE); + + DISCO_LOCK (dc); + if (dc->priv->current_error) + g_error_free (dc->priv->current_error); + dc->priv->current_error = NULL; + if (dc->priv->current_topology) { + gst_structure_free (dc->priv->current_topology); + dc->priv->current_topology = NULL; + } + + dc->priv->current_info = NULL; + + /* Try popping the next uri */ + if (dc->priv->async) { + if (dc->priv->pending_uris != NULL) { + _setup_locked (dc); + DISCO_UNLOCK (dc); + /* Start timeout */ + handle_current_async (dc); + } else { + /* We're done ! */ + DISCO_UNLOCK (dc); + g_signal_emit (dc, gst_discoverer_signals[SIGNAL_FINISHED], 0); + } + } else + DISCO_UNLOCK (dc); + + GST_DEBUG ("out"); +} + +static void +discoverer_bus_cb (GstBus * bus, GstMessage * msg, GstDiscoverer * dc) +{ + if (dc->priv->processing) { + if (handle_message (dc, msg)) { + GST_DEBUG ("Stopping asynchronously"); + /* Serialise with _event_probe() */ + DISCO_LOCK (dc); + dc->priv->processing = FALSE; + DISCO_UNLOCK (dc); + discoverer_collect (dc); + discoverer_cleanup (dc); + } + } +} + +static gboolean +async_timeout_cb (GstDiscoverer * dc) +{ + if (!g_source_is_destroyed (g_main_current_source ())) { + dc->priv->timeoutid = 0; + GST_DEBUG ("Setting result to TIMEOUT"); + dc->priv->current_info->result = GST_DISCOVERER_TIMEOUT; + dc->priv->processing = FALSE; + discoverer_collect (dc); + discoverer_cleanup (dc); + } + return FALSE; +} + +/* If there is a pending URI, it will pop it from the list of pending + * URIs and start the discovery on it. + * + * Returns GST_DISCOVERER_OK if the next URI was popped and is processing, + * else a error flag. + */ +static GstDiscovererResult +start_discovering (GstDiscoverer * dc) +{ + GstDiscovererResult res = GST_DISCOVERER_OK; + + GST_DEBUG ("Starting"); + + DISCO_LOCK (dc); + if (dc->priv->pending_uris == NULL) { + GST_WARNING ("No URI to process"); + res = GST_DISCOVERER_URI_INVALID; + DISCO_UNLOCK (dc); + goto beach; + } + + if (dc->priv->current_info != NULL) { + GST_WARNING ("Already processing a file"); + res = GST_DISCOVERER_BUSY; + DISCO_UNLOCK (dc); + goto beach; + } + + g_signal_emit (dc, gst_discoverer_signals[SIGNAL_STARTING], 0); + + _setup_locked (dc); + + DISCO_UNLOCK (dc); + + if (dc->priv->async) + handle_current_async (dc); + else + handle_current_sync (dc); + +beach: + return res; +} + + +/** + * gst_discoverer_start: + * @discoverer: A #GstDiscoverer + * + * Allow asynchronous discovering of URIs to take place. + * A #GMainLoop must be available for #GstDiscoverer to properly work in + * asynchronous mode. + * + * Since: 0.10.31 + */ +void +gst_discoverer_start (GstDiscoverer * discoverer) +{ + GSource *source; + GMainContext *ctx = NULL; + + GST_DEBUG_OBJECT (discoverer, "Starting..."); + + if (discoverer->priv->async) { + GST_DEBUG_OBJECT (discoverer, "We were already started"); + return; + } + + discoverer->priv->async = TRUE; + discoverer->priv->running = TRUE; + + ctx = g_main_context_get_thread_default (); + + /* Connect to bus signals */ + if (ctx == NULL) + ctx = g_main_context_default (); + + source = gst_bus_create_watch (discoverer->priv->bus); + g_source_set_callback (source, (GSourceFunc) gst_bus_async_signal_func, + NULL, NULL); + discoverer->priv->sourceid = g_source_attach (source, ctx); + g_source_unref (source); + discoverer->priv->ctx = g_main_context_ref (ctx); + + start_discovering (discoverer); + GST_DEBUG_OBJECT (discoverer, "Started"); +} + +/** + * gst_discoverer_stop: + * @discoverer: A #GstDiscoverer + * + * Stop the discovery of any pending URIs and clears the list of + * pending URIS (if any). + * + * Since: 0.10.31 + */ +void +gst_discoverer_stop (GstDiscoverer * discoverer) +{ + GST_DEBUG_OBJECT (discoverer, "Stopping..."); + + if (!discoverer->priv->async) { + GST_DEBUG_OBJECT (discoverer, + "We were already stopped, or running synchronously"); + return; + } + + DISCO_LOCK (discoverer); + if (discoverer->priv->processing) { + /* We prevent any further processing by setting the bus to + * flushing and setting the pipeline to READY. + * _reset() will take care of the rest of the cleanup */ + if (discoverer->priv->bus) + gst_bus_set_flushing (discoverer->priv->bus, TRUE); + if (discoverer->priv->pipeline) + gst_element_set_state ((GstElement *) discoverer->priv->pipeline, + GST_STATE_READY); + } + discoverer->priv->running = FALSE; + DISCO_UNLOCK (discoverer); + + /* Remove timeout handler */ + if (discoverer->priv->timeoutid) { + g_source_remove (discoverer->priv->timeoutid); + discoverer->priv->timeoutid = 0; + } + /* Remove signal watch */ + if (discoverer->priv->sourceid) { + g_source_remove (discoverer->priv->sourceid); + discoverer->priv->sourceid = 0; + } + /* Unref main context */ + if (discoverer->priv->ctx) { + g_main_context_unref (discoverer->priv->ctx); + discoverer->priv->ctx = NULL; + } + discoverer_reset (discoverer); + + discoverer->priv->async = FALSE; + + GST_DEBUG_OBJECT (discoverer, "Stopped"); +} + +/** + * gst_discoverer_discover_uri_async: + * @discoverer: A #GstDiscoverer + * @uri: the URI to add. + * + * Appends the given @uri to the list of URIs to discoverer. The actual + * discovery of the @uri will only take place if gst_discoverer_start() has + * been called. + * + * A copy of @uri will be made internally, so the caller can safely g_free() + * afterwards. + * + * Returns: %TRUE if the @uri was succesfully appended to the list of pending + * uris, else %FALSE + * + * Since: 0.10.31 + */ +gboolean +gst_discoverer_discover_uri_async (GstDiscoverer * discoverer, + const gchar * uri) +{ + gboolean can_run; + + GST_DEBUG_OBJECT (discoverer, "uri : %s", uri); + + DISCO_LOCK (discoverer); + can_run = (discoverer->priv->pending_uris == NULL); + discoverer->priv->pending_uris = + g_list_append (discoverer->priv->pending_uris, g_strdup (uri)); + DISCO_UNLOCK (discoverer); + + if (can_run) + start_discovering (discoverer); + + return TRUE; +} + + +/* Synchronous mode */ +/** + * gst_discoverer_discover_uri: + * @discoverer: A #GstDiscoverer + * @uri: The URI to run on. + * @err: If an error occurred, this field will be filled in. + * + * Synchronously discovers the given @uri. + * + * A copy of @uri will be made internally, so the caller can safely g_free() + * afterwards. + * + * Returns: (transfer full): the result of the scanning. Can be %NULL if an + * error occurred. + * + * Since: 0.10.31 + */ +GstDiscovererInfo * +gst_discoverer_discover_uri (GstDiscoverer * discoverer, const gchar * uri, + GError ** err) +{ + GstDiscovererResult res = 0; + GstDiscovererInfo *info; + + GST_DEBUG_OBJECT (discoverer, "uri:%s", uri); + + DISCO_LOCK (discoverer); + if (G_UNLIKELY (discoverer->priv->current_info)) { + DISCO_UNLOCK (discoverer); + GST_WARNING_OBJECT (discoverer, "Already handling a uri"); + return NULL; + } + + discoverer->priv->pending_uris = + g_list_append (discoverer->priv->pending_uris, g_strdup (uri)); + DISCO_UNLOCK (discoverer); + + res = start_discovering (discoverer); + discoverer_collect (discoverer); + + /* Get results */ + if (discoverer->priv->current_error) + *err = g_error_copy (discoverer->priv->current_error); + else + *err = NULL; + if (res != GST_DISCOVERER_OK) { + GST_DEBUG ("Setting result to %d (was %d)", res, + discoverer->priv->current_info->result); + discoverer->priv->current_info->result = res; + } + info = discoverer->priv->current_info; + + discoverer_cleanup (discoverer); + + return info; +} + +/** + * gst_discoverer_new: + * @timeout: timeout per file, in nanoseconds. Allowed are values between + * one second (#GST_SECOND) and one hour (3600 * #GST_SECOND) + * @err: a pointer to a #GError. can be %NULL + * + * Creates a new #GstDiscoverer with the provided timeout. + * + * Returns: (transfer full): The new #GstDiscoverer. + * If an error occurred when creating the discoverer, @err will be set + * accordingly and %NULL will be returned. If @err is set, the caller must + * free it when no longer needed using g_error_free(). + * + * Since: 0.10.31 + */ +GstDiscoverer * +gst_discoverer_new (GstClockTime timeout, GError ** err) +{ + GstDiscoverer *res; + + res = g_object_new (GST_TYPE_DISCOVERER, "timeout", timeout, NULL); + if (res->priv->uridecodebin == NULL) { + if (err) + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, + "Couldn't create 'uridecodebin' element"); + gst_object_unref (res); + res = NULL; + } + return res; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.h new file mode 100644 index 0000000..671dbaa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstdiscoverer.h @@ -0,0 +1,266 @@ +/* GStreamer + * Copyright (C) 2009 Edward Hervey + * 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_DISCOVERER_H_ +#define _GST_DISCOVERER_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DISCOVERER_STREAM_INFO \ + (gst_discoverer_stream_info_get_type ()) +#define GST_DISCOVERER_STREAM_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_STREAM_INFO, GstDiscovererStreamInfo)) +#define GST_IS_DISCOVERER_STREAM_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_STREAM_INFO)) +typedef struct _GstDiscovererStreamInfo GstDiscovererStreamInfo; +typedef GstMiniObjectClass GstDiscovererStreamInfoClass; +GType gst_discoverer_stream_info_get_type (void); + +/** + * GstDiscovererStreamInfo: + * + * Base structure for information concerning a media stream. Depending on the + * stream type, one can find more media-specific information in + * #GstDiscovererAudioInfo, #GstDiscovererVideoInfo, and + * #GstDiscovererContainerInfo. + * + * The #GstDiscovererStreamInfo represents the topology of the stream. Siblings + * can be iterated over with gst_discoverer_stream_info_get_next() and + * gst_discoverer_stream_info_get_previous(). Children (sub-streams) of a + * stream can be accessed using the #GstDiscovererContainerInfo API. + * + * As a simple example, if you run #GstDiscoverer on an AVI file with one audio + * and one video stream, you will get a #GstDiscovererContainerInfo + * corresponding to the AVI container, which in turn will have a + * #GstDiscovererAudioInfo sub-stream and a #GstDiscovererVideoInfo sub-stream + * for the audio and video streams respectively. + * + * Since: 0.10.31 + */ +#define gst_discoverer_stream_info_ref(info) ((GstDiscovererStreamInfo*) gst_mini_object_ref((GstMiniObject*) info)) +#define gst_discoverer_stream_info_unref(info) (gst_mini_object_unref((GstMiniObject*) info)) + +GstDiscovererStreamInfo* gst_discoverer_stream_info_get_previous(GstDiscovererStreamInfo* info); +GstDiscovererStreamInfo* gst_discoverer_stream_info_get_next(GstDiscovererStreamInfo* info); +GstCaps* gst_discoverer_stream_info_get_caps(GstDiscovererStreamInfo* info); +const GstTagList* gst_discoverer_stream_info_get_tags(GstDiscovererStreamInfo* info); +const GstStructure* gst_discoverer_stream_info_get_misc(GstDiscovererStreamInfo* info); +const gchar * gst_discoverer_stream_info_get_stream_type_nick(GstDiscovererStreamInfo* info); + +/** + * GstDiscovererContainerInfo: + * + * #GstDiscovererStreamInfo specific to container streams. + * + * Since: 0.10.31 + */ +#define GST_TYPE_DISCOVERER_CONTAINER_INFO \ + (gst_discoverer_container_info_get_type ()) +#define GST_DISCOVERER_CONTAINER_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_CONTAINER_INFO, GstDiscovererContainerInfo)) +#define GST_IS_DISCOVERER_CONTAINER_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_CONTAINER_INFO)) +typedef struct _GstDiscovererContainerInfo GstDiscovererContainerInfo; +typedef GstMiniObjectClass GstDiscovererContainerInfoClass; + +GType gst_discoverer_container_info_get_type (void); + +GList *gst_discoverer_container_info_get_streams(GstDiscovererContainerInfo *info); + + +/** + * GstDiscovererAudioInfo: + * + * #GstDiscovererStreamInfo specific to audio streams. + * + * Since: 0.10.31 + */ +#define GST_TYPE_DISCOVERER_AUDIO_INFO \ + (gst_discoverer_audio_info_get_type ()) +#define GST_DISCOVERER_AUDIO_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_AUDIO_INFO, GstDiscovererAudioInfo)) +#define GST_IS_DISCOVERER_AUDIO_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_AUDIO_INFO)) +typedef struct _GstDiscovererAudioInfo GstDiscovererAudioInfo; +typedef GstMiniObjectClass GstDiscovererAudioInfoClass; + +GType gst_discoverer_audio_info_get_type (void); + +guint gst_discoverer_audio_info_get_channels(const GstDiscovererAudioInfo* info); +guint gst_discoverer_audio_info_get_sample_rate(const GstDiscovererAudioInfo* info); +guint gst_discoverer_audio_info_get_depth(const GstDiscovererAudioInfo* info); +guint gst_discoverer_audio_info_get_bitrate(const GstDiscovererAudioInfo* info); +guint gst_discoverer_audio_info_get_max_bitrate(const GstDiscovererAudioInfo* info); + +/** + * GstDiscovererVideoInfo: + * + * #GstDiscovererStreamInfo specific to video streams (this includes images). + * + * Since: 0.10.31 + */ +#define GST_TYPE_DISCOVERER_VIDEO_INFO \ + (gst_discoverer_video_info_get_type ()) +#define GST_DISCOVERER_VIDEO_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_VIDEO_INFO, GstDiscovererVideoInfo)) +#define GST_IS_DISCOVERER_VIDEO_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_VIDEO_INFO)) +typedef struct _GstDiscovererVideoInfo GstDiscovererVideoInfo; +typedef GstMiniObjectClass GstDiscovererVideoInfoClass; +GType gst_discoverer_video_info_get_type (void); + +guint gst_discoverer_video_info_get_width(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_height(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_depth(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_framerate_num(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_framerate_denom(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_par_num(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_par_denom(const GstDiscovererVideoInfo* info); +gboolean gst_discoverer_video_info_is_interlaced(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_bitrate(const GstDiscovererVideoInfo* info); +guint gst_discoverer_video_info_get_max_bitrate(const GstDiscovererVideoInfo* info); +gboolean gst_discoverer_video_info_is_image(const GstDiscovererVideoInfo* info); + +/** + * GstDiscovererResult: + * @GST_DISCOVERER_OK: The discovery was successful + * @GST_DISCOVERER_URI_INVALID: the URI is invalid + * @GST_DISCOVERER_ERROR: an error happened and the GError is set + * @GST_DISCOVERER_TIMEOUT: the discovery timed-out + * @GST_DISCOVERER_BUSY: the discoverer was already discovering a file + * @GST_DISCOVERER_MISSING_PLUGINS: Some plugins are missing for full discovery + * + * Result values for the discovery process. + * + * Since: 0.10.31 + */ +typedef enum { + GST_DISCOVERER_OK = 0, + GST_DISCOVERER_URI_INVALID = 1, + GST_DISCOVERER_ERROR = 2, + GST_DISCOVERER_TIMEOUT = 3, + GST_DISCOVERER_BUSY = 4, + GST_DISCOVERER_MISSING_PLUGINS = 5 +} GstDiscovererResult; + + +/** + * GstDiscovererInfo: + * + * Structure containing the information of a URI analyzed by #GstDiscoverer. + * + * Since: 0.10.31 + */ +typedef struct _GstDiscovererInfo GstDiscovererInfo; + +#define GST_TYPE_DISCOVERER_INFO \ + (gst_discoverer_info_get_type ()) +#define GST_DISCOVERER_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER_INFO, GstDiscovererInfo)) +#define GST_IS_DISCOVERER_INFO(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER_INFO)) +typedef GstMiniObjectClass GstDiscovererInfoClass; +GType gst_discoverer_info_get_type (void); + +#define gst_discoverer_info_unref(info) (gst_mini_object_unref((GstMiniObject*)info)) +#define gst_discoverer_info_ref(info) (gst_mini_object_ref((GstMiniObject*)info)) + +GstDiscovererInfo* gst_discoverer_info_copy (GstDiscovererInfo * ptr); + +const gchar* gst_discoverer_info_get_uri(const GstDiscovererInfo* info); +GstDiscovererResult gst_discoverer_info_get_result(const GstDiscovererInfo* info); +GstDiscovererStreamInfo* gst_discoverer_info_get_stream_info(GstDiscovererInfo* info); +GList* gst_discoverer_info_get_stream_list(GstDiscovererInfo* info); +GstClockTime gst_discoverer_info_get_duration(const GstDiscovererInfo* info); +gboolean gst_discoverer_info_get_seekable(const GstDiscovererInfo* info); +const GstStructure* gst_discoverer_info_get_misc(const GstDiscovererInfo* info); +const GstTagList* gst_discoverer_info_get_tags(const GstDiscovererInfo* info); + +GList * gst_discoverer_info_get_streams (GstDiscovererInfo *info, + GType streamtype); +GList * gst_discoverer_info_get_audio_streams (GstDiscovererInfo *info); +GList * gst_discoverer_info_get_video_streams (GstDiscovererInfo *info); +GList * gst_discoverer_info_get_container_streams (GstDiscovererInfo *info); + +void gst_discoverer_stream_info_list_free (GList *infos); + +#define GST_TYPE_DISCOVERER \ + (gst_discoverer_get_type()) +#define GST_DISCOVERER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DISCOVERER,GstDiscoverer)) +#define GST_DISCOVERER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DISCOVERER,GstDiscovererClass)) +#define GST_IS_DISCOVERER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DISCOVERER)) +#define GST_IS_DISCOVERER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DISCOVERER)) + +typedef struct _GstDiscoverer GstDiscoverer; +typedef struct _GstDiscovererClass GstDiscovererClass; +typedef struct _GstDiscovererPrivate GstDiscovererPrivate; + +/** + * GstDiscoverer: + * + * The #GstDiscoverer structure. + * + * Since: 0.10.31 + **/ +struct _GstDiscoverer { + GObject parent; + + GstDiscovererPrivate *priv; + + gpointer _reserved[GST_PADDING]; +}; + +struct _GstDiscovererClass { + GObjectClass parentclass; + + /*< signals >*/ + void (*finished) (GstDiscoverer *discoverer); + void (*starting) (GstDiscoverer *discoverer); + void (*discovered) (GstDiscoverer *discoverer, + GstDiscovererInfo *info, + const GError *err); + + gpointer _reserved[GST_PADDING]; +}; + +GType gst_discoverer_get_type (void); +GstDiscoverer *gst_discoverer_new (GstClockTime timeout, GError **err); + +/* Asynchronous API */ +void gst_discoverer_start (GstDiscoverer *discoverer); +void gst_discoverer_stop (GstDiscoverer *discoverer); +gboolean gst_discoverer_discover_uri_async (GstDiscoverer *discoverer, + const gchar *uri); + +/* Synchronous API */ +GstDiscovererInfo * +gst_discoverer_discover_uri (GstDiscoverer * discoverer, + const gchar * uri, + GError ** err); + +G_END_DECLS + +#endif /* _GST_DISCOVERER_H */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.c new file mode 100644 index 0000000..997a0b8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.c @@ -0,0 +1,78 @@ +/* GStreamer base plugins libraries version information + * Copyright (C) 2010 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpluginsbaseversion + * @short_description: GStreamer gst-plugins-base libraries version macros. + * + * Use the GST_PLUGINS_BASE_VERSION_* macros e.g. to check what version of + * gst-plugins-base you are building against, and gst_plugins_base_version() + * if you need to check at runtime what version of the gst-plugins-base + * libraries are being used / you are currently linked against. + * + * The version macros get defined by including . + */ + +#include "gstpluginsbaseversion.h" + +/** + * gst_plugins_base_version: + * @major: (out): pointer to a guint to store the major version number, or %NULL + * @minor: (out): pointer to a guint to store the minor version number, or %NULL + * @micro: (out): pointer to a guint to store the micro version number, or %NULL + * @nano: (out): pointer to a guint to store the nano version number, or %NULL + * + * Gets the version number of the GStreamer Plugins Base libraries. + * + * Since: 0.10.31 + */ +void +gst_plugins_base_version (guint * major, guint * minor, guint * micro, + guint * nano) +{ + if (major) + *major = GST_PLUGINS_BASE_VERSION_MAJOR; + if (minor) + *minor = GST_PLUGINS_BASE_VERSION_MINOR; + if (micro) + *micro = GST_PLUGINS_BASE_VERSION_MICRO; + if (nano) + *nano = GST_PLUGINS_BASE_VERSION_NANO; +} + +/** + * gst_plugins_base_version_string: + * + * This function returns a string that is useful for describing this version + * of GStreamer's gst-plugins-base libraries to the outside world: user agent + * strings, logging, about dialogs ... + * + * Returns: a newly allocated string describing this version of gst-plugins-base + * + * Since: 0.10.31 + */ +gchar * +gst_plugins_base_version_string (void) +{ + return g_strdup_printf ("GStreamer Base Plugins %d.%d.%d%s", + GST_PLUGINS_BASE_VERSION_MAJOR, GST_PLUGINS_BASE_VERSION_MINOR, + GST_PLUGINS_BASE_VERSION_MICRO, + ((GST_PLUGINS_BASE_VERSION_NANO == 0) ? "" : + ((GST_PLUGINS_BASE_VERSION_NANO == 1) ? " (GIT)" : " (prerelease)"))); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.h.in b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.h.in new file mode 100644 index 0000000..bd8adc9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/gstpluginsbaseversion.h.in @@ -0,0 +1,86 @@ +/* GStreamer base plugins libraries version information + * Copyright (C) 2010 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLUGINS_BASE_VERSION_H__ +#define __GST_PLUGINS_BASE_VERSION_H__ + +#include + +G_BEGIN_DECLS + +/** + * GST_PLUGINS_BASE_VERSION_MAJOR: + * + * The major version of GStreamer's gst-plugins-base libraries at compile time. + * + * Since: 0.10.31 + */ +#define GST_PLUGINS_BASE_VERSION_MAJOR (@PACKAGE_VERSION_MAJOR@) +/** + * GST_PLUGINS_BASE_VERSION_MINOR: + * + * The minor version of GStreamer's gst-plugins-base libraries at compile time. + * + * Since: 0.10.31 + */ +#define GST_PLUGINS_BASE_VERSION_MINOR (@PACKAGE_VERSION_MINOR@) +/** + * GST_PLUGINS_BASE_VERSION_MICRO: + * + * The micro version of GStreamer's gst-plugins-base libraries at compile time. + * + * Since: 0.10.31 + */ +#define GST_PLUGINS_BASE_VERSION_MICRO (@PACKAGE_VERSION_MICRO@) +/** + * GST_PLUGINS_BASE_VERSION_NANO: + * + * The nano version of GStreamer's gst-plugins-base libraries at compile time. + * Actual releases have 0, GIT versions have 1, prerelease versions have 2-... + * + * Since: 0.10.31 + */ +#define GST_PLUGINS_BASE_VERSION_NANO (@PACKAGE_VERSION_NANO@) + +/** + * GST_CHECK_PLUGIN_BASE_VERSION: + * @major: a number indicating the major version + * @minor: a number indicating the minor version + * @micro: a number indicating the micro version + * + * Check whether a GStreamer's gst-plugins-base libraries' version equal to + * or greater than major.minor.micro is present. + * + * Since: 0.10.31 + */ +#define GST_CHECK_PLUGINS_BASE_VERSION(major,minor,micro) \ + (GST_PLUGINS_BASE_VERSION_MAJOR > (major) || \ + (GST_PLUGINS_BASE_VERSION_MAJOR == (major) && GST_PLUGINS_BASE_VERSION_MINOR > (minor)) || \ + (GST_PLUGINS_BASE_VERSION_MAJOR == (major) && GST_PLUGINS_BASE_VERSION_MINOR == (minor) && \ + GST_PLUGINS_BASE_VERSION_MICRO >= (micro)) || \ + (GST_PLUGINS_BASE_VERSION_MAJOR == (major) && GST_PLUGINS_BASE_VERSION_MINOR == (minor) && \ + GST_PLUGINS_BASE_VERSION_MICRO + 1 == (micro) && GST_PLUGINS_BASE_VERSION_NANO > 0)) + +void gst_plugins_base_version (guint *major, guint *minor, guint *micro, guint *nano); + +gchar * gst_plugins_base_version_string (void); + +G_END_DECLS + +#endif /* __GST_PLUGINS_BASE_VERSION_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.c new file mode 100644 index 0000000..9b5f45e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.c @@ -0,0 +1,783 @@ +/* GStreamer base utils library plugin install support for applications + * Copyright (C) 2007 Tim-Philipp Müller + * Copyright (C) 2006 Ryan Lortie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpbutilsinstallplugins + * @short_description: Missing plugin installation support for applications + * + * + * Overview + * + * Using this API, applications can request the installation of missing + * GStreamer plugins. These may be missing decoders/demuxers or encoders/muxers + * for a certain format, sources or sinks for a certain URI protocol + * (e.g. 'http'), or certain elements known by their element factory name + * ('audioresample'). + * + * + * Whether plugin installation is supported or not depends on the operating + * system and/or distribution in question. The vendor of the operating system + * needs to make sure the necessary hooks and mechanisms are in place for + * plugin installation to work. See below for more detailed information. + * + * + * From the application perspective, plugin installation is usually triggered + * either + * + * + * when the application itself has found that it wants or needs to install a + * certain element + * + * + * when the application has been notified by an element (such as playbin or + * decodebin) that one or more plugins are missing and + * the application has decided that it wants to install one or more of those + * missing plugins + * + * + * + * Detail Strings + * + * The install functions in this section all take one or more 'detail strings'. + * These detail strings contain information about the type of plugin that + * needs to be installed (decoder, encoder, source, sink, or named element), + * and some additional information such GStreamer version used and a + * human-readable description of the component to install for user dialogs. + * + * + * Applications should not concern themselves with the composition of the + * string itself. They should regard the string as if it was a shared secret + * between GStreamer and the plugin installer application. + * + * + * Detail strings can be obtained using the function + * gst_missing_plugin_message_get_installer_detail() on a missing-plugin + * message. Such a message will either have been found by the application on + * a pipeline's #GstBus, or the application will have created it itself using + * gst_missing_element_message_new(), gst_missing_decoder_message_new(), + * gst_missing_encoder_message_new(), gst_missing_uri_sink_message_new(), or + * gst_missing_uri_source_message_new(). + * + * Plugin Installation from the Application Perspective + * + * For each GStreamer element/plugin/component that should be installed, the + * application needs one of those 'installer detail' string mentioned in the + * previous section. This string can be obtained, as already mentioned above, + * from a missing-plugin message using the function + * gst_missing_plugin_message_get_installer_detail(). The missing-plugin + * message is either posted by another element and then found on the bus + * by the application, or the application has created it itself as described + * above. + * + * + * The application will then call gst_install_plugins_async(), passing a + * NULL-terminated array of installer detail strings, and a function that + * should be called when the installation of the plugins has finished + * (successfully or not). Optionally, a #GstInstallPluginsContext created + * with gst_install_plugins_context_new() may be passed as well. This way + * additional optional arguments like the application window's XID can be + * passed to the external installer application. + * + * + * gst_install_plugins_async() will return almost immediately, with the + * return code indicating whether plugin installation was started or not. + * If the necessary hooks for plugin installation are in place and an + * external installer application has in fact been called, the passed in + * function will be called with a result code as soon as the external installer + * has finished. If the result code indicates that new plugins have been + * installed, the application will want to call gst_update_registry() so the + * run-time plugin registry is updated and the new plugins are made available + * to the application. + * + * A Gtk/GLib main loop must be running in order for the result function to + * be called when the external installer has finished. If this is not the case, + * make sure to regularly call + * + * g_main_context_iteration (NULL,FALSE); + * + * from your code. + * + * + * Plugin Installation from the Vendor/Distribution Perspective + * + * 1. Installer hook + * + * + * When GStreamer applications initiate plugin installation via + * gst_install_plugins_async() or gst_install_plugins_sync(), a pre-defined + * helper application will be called. + * + * + * The exact path of the helper application to be called is set at compile + * time, usually by the ./configure script based on the + * install prefix. For a normal package build into the /usr + * prefix, this will usually default to + * /usr/libexec/gst-install-plugins-helper or + * /usr/lib/gst-install-plugins-helper. + * + * + * Vendors/distros who want to support GStreamer plugin installation should + * either provide such a helper script/application or use the + * ./configure option + * --with-install-plugins-helper=/path/to/installer to + * make GStreamer call an installer of their own directly. + * + * + * It is strongly recommended that vendors provide a small helper application + * as interlocutor to the real installer though, even more so if command line + * argument munging is required to transform the command line arguments + * passed by GStreamer to the helper application into arguments that are + * understood by the real installer. + * + * + * The helper application path defined at compile time can be overriden at + * runtime by setting the GST_INSTALL_PLUGINS_HELPER + * environment variable. This can be useful for testing/debugging purposes. + * + * + * 2. Arguments passed to the install helper + * + * + * GStreamer will pass the following arguments to the install helper (this is + * in addition to the path of the executable itself, which is by convention + * argv[0]): + * + * + * none to many optional arguments in the form of + * --foo-bar=val. Example: + * --transient-for=XID where XID is the X Window ID of + * the main window of the calling application (so the installer can make + * itself transient to that window). Unknown optional arguments should + * be ignored by the installer. + * + * + * one 'installer detail string' argument for each plugin to be installed; + * these strings will have a gstreamer prefix; the + * exact format of the detail string is explained below + * + * + * + * + * 3. Detail string describing the missing plugin + * + * + * The string is in UTF-8 encoding and is made up of several fields, separated + * by '|' characters (but neither the first nor the last character is a '|'). + * The fields are: + * + * + * plugin system identifier, ie. "gstreamer" + * + * This identifier determines the format of the rest of the detail string. + * Automatic plugin installers should not process detail strings with + * unknown identifiers. This allows other plugin-based libraries to use + * the same mechanism for their automatic plugin installation needs, or + * for the format to be changed should it turn out to be insufficient. + * + * + * plugin system version, e.g. "0.10" + * + * This is required so that when there is a GStreamer-0.12 or GStreamer-1.0 + * at some point in future, the different major versions can still co-exist + * and use the same plugin install mechanism in the same way. + * + * + * application identifier, e.g. "totem" + * + * This may also be in the form of "pid/12345" if the program name can't + * be obtained for some reason. + * + * + * human-readable localised description of the required component, + * e.g. "Vorbis audio decoder" + * + * + * identifier string for the required component (see below for details about + * how to map this to the package/plugin that needs installing), e.g. + * + * + * urisource-$(PROTOCOL_REQUIRED), e.g. urisource-http or urisource-mms + * + * + * element-$(ELEMENT_REQUIRED), e.g. element-ffmpegcolorspace + * + * + * decoder-$(CAPS_REQUIRED), e.g. (do read below for more details!): + * + * decoder-audio/x-vorbis + * decoder-application/ogg + * decoder-audio/mpeg, mpegversion=(int)4 + * decoder-video/mpeg, systemstream=(boolean)true, mpegversion=(int)2 + + * + * + * encoder-$(CAPS_REQUIRED), e.g. encoder-audio/x-vorbis + * + * + * + * + * optional further fields not yet specified + * + * + * + * + * An entire ID string might then look like this, for example: + * + * gstreamer|0.10|totem|Vorbis audio decoder|decoder-audio/x-vorbis + * + * + * + * Plugin installers parsing this ID string should expect further fields also + * separated by '|' symbols and either ignore them, warn the user, or error + * out when encountering them. + * + * + * Those unfamiliar with the GStreamer 'caps' system should note a few things + * about the caps string used in the above decoder/encoder case: + * + * + * the first part ("video/mpeg") of the caps string is a GStreamer media + * type and not a MIME type. Wherever possible, the + * GStreamer media type will be the same as the corresponding MIME type, + * but often it is not. + * + * + * a caps string may or may not have additional comma-separated fields + * of various types (as seen in the examples above) + * + * + * the caps string of a 'required' component (as above) will always have + * fields with fixed values, whereas an introspected string (see below) + * may have fields with non-fixed values. Compare for example: + * + * + * audio/mpeg, mpegversion=(int)4 vs. + * audio/mpeg, mpegversion=(int){2, 4} + * + * + * video/mpeg, mpegversion=(int)2 vs. + * video/mpeg, systemstream=(boolean){ true, false}, mpegversion=(int)[1, 2] + * + * + * + * + * + * + * 4. Exit codes the installer should return + * + * + * The installer should return one of the following exit codes when it exits: + * + * + * 0 if all of the requested plugins could be installed + * (#GST_INSTALL_PLUGINS_SUCCESS) + * + * + * 1 if no appropriate installation candidate for any of the requested + * plugins could be found. Only return this if nothing has been installed + * (#GST_INSTALL_PLUGINS_NOT_FOUND) + * + * + * 2 if an error occured during the installation. The application will + * assume that the user will already have seen an error message by the + * installer in this case and will usually not show another one + * (#GST_INSTALL_PLUGINS_ERROR) + * + * + * 3 if some of the requested plugins could be installed, but not all + * (#GST_INSTALL_PLUGINS_PARTIAL_SUCCESS) + * + * + * 4 if the user aborted the installation (#GST_INSTALL_PLUGINS_USER_ABORT) + * + * + * + * + * 5. How to map the required detail string to packages + * + * + * It is up to the vendor to find mechanism to map required components from + * the detail string to the actual packages/plugins to install. This could + * be a hardcoded list of mappings, for example, or be part of the packaging + * system metadata. + * + * + * GStreamer plugin files can be introspected for this information. The + * gst-inspect utility has a special command line option + * that will output information similar to what is required. For example + * + * $ gst-inspect-0.10 --print-plugin-auto-install-info /path/to/libgstvorbis.so + * + * should output something along the lines of + * + * decoder-audio/x-vorbis + * element-vorbisdec + * element-vorbisenc + * element-vorbisparse + * element-vorbistag + * encoder-audio/x-vorbis + * + * Note that in the encoder and decoder case the introspected caps can be more + * complex with additional fields, e.g. + * audio/mpeg,mpegversion=(int){2,4}, so they will not + * always exactly match the caps wanted by the application. It is up to the + * installer to deal with this (either by doing proper caps intersection using + * the GStreamer #GstCaps API, or by only taking into account the media type). + * + * + * Another potential source of problems are plugins such as ladspa or + * libvisual where the list of elements depends on the installed + * ladspa/libvisual plugins at the time. This is also up to the distribution + * to handle (but usually not relevant for playback applications). + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "install-plugins.h" + +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#ifdef HAVE_SYS_WAIT_H +#include +#endif + +#include + +/* best effort to make things compile and possibly even work on win32 */ +#ifndef WEXITSTATUS +# define WEXITSTATUS(status) ((((guint)(status)) & 0xff00) >> 8) +#endif +#ifndef WIFEXITED +# define WIFEXITED(status) ((((guint)(status)) & 0x7f) == 0) +#endif + +static gboolean install_in_progress; /* FALSE */ + +/* private struct */ +struct _GstInstallPluginsContext +{ + guint xid; +}; + +/** + * gst_install_plugins_context_set_xid: + * @ctx: a #GstInstallPluginsContext + * @xid: the XWindow ID (XID) of the top-level application + * + * This function is for X11-based applications (such as most Gtk/Qt + * applications on linux/unix) only. You can use it to tell the external + * installer the XID of your main application window. That way the installer + * can make its own window transient to your application window during the + * installation. + * + * If set, the XID will be passed to the installer via a --transient-for=XID + * command line option. + * + * Gtk+/Gnome application should be able to obtain the XID of the top-level + * window like this: + * + * ##include <gtk/gtk.h> + * ##ifdef GDK_WINDOWING_X11 + * ##include <gdk/gdkx.h> + * ##endif + * ... + * ##ifdef GDK_WINDOWING_X11 + * xid = GDK_WINDOW_XWINDOW (GTK_WIDGET (application_window)->window); + * ##endif + * ... + * + * + * Since: 0.10.12 + */ +void +gst_install_plugins_context_set_xid (GstInstallPluginsContext * ctx, guint xid) +{ + g_return_if_fail (ctx != NULL); + + ctx->xid = xid; +} + +/** + * gst_install_plugins_context_new: + * + * Creates a new #GstInstallPluginsContext. + * + * Returns: a new #GstInstallPluginsContext. Free with + * gst_install_plugins_context_free() when no longer needed + * + * Since: 0.10.12 + */ +GstInstallPluginsContext * +gst_install_plugins_context_new (void) +{ + return g_new0 (GstInstallPluginsContext, 1); +} + +/** + * gst_install_plugins_context_free: + * @ctx: a #GstInstallPluginsContext + * + * Frees a #GstInstallPluginsContext. + * + * Since: 0.10.12 + */ +void +gst_install_plugins_context_free (GstInstallPluginsContext * ctx) +{ + g_return_if_fail (ctx != NULL); + + g_free (ctx); +} + +static GstInstallPluginsContext * +gst_install_plugins_context_copy (GstInstallPluginsContext * ctx) +{ + GstInstallPluginsContext *ret; + + ret = gst_install_plugins_context_new (); + ret->xid = ctx->xid; + + return ret; +} + +GType +gst_install_plugins_context_get_type (void) +{ + static GType gst_ipc_type = 0; + + if (G_UNLIKELY (gst_ipc_type == 0)) { + gst_ipc_type = g_boxed_type_register_static ("GstInstallPluginsContext", + (GBoxedCopyFunc) gst_install_plugins_context_copy, + (GBoxedFreeFunc) gst_install_plugins_context_free); + } + return gst_ipc_type; +} + +static const gchar * +gst_install_plugins_get_helper (void) +{ + const gchar *helper; + + helper = g_getenv ("GST_INSTALL_PLUGINS_HELPER"); + if (helper == NULL) + helper = GST_INSTALL_PLUGINS_HELPER; + + GST_LOG ("Using plugin install helper '%s'", helper); + return helper; +} + +static gboolean +ptr_array_contains_string (GPtrArray * arr, const gchar * s) +{ + gint i; + + for (i = 0; i < arr->len; ++i) { + if (strcmp ((const char *) g_ptr_array_index (arr, i), s) == 0) + return TRUE; + } + return FALSE; +} + +static gboolean +gst_install_plugins_spawn_child (gchar ** details, + GstInstallPluginsContext * ctx, GPid * child_pid, gint * exit_status) +{ + GPtrArray *arr; + gboolean ret; + GError *err = NULL; + gchar **argv, xid_str[64] = { 0, }; + + arr = g_ptr_array_new (); + + /* argv[0] = helper path */ + g_ptr_array_add (arr, (gchar *) gst_install_plugins_get_helper ()); + + /* add any additional command line args from the context */ + if (ctx != NULL && ctx->xid != 0) { + g_snprintf (xid_str, sizeof (xid_str), "--transient-for=%u", ctx->xid); + g_ptr_array_add (arr, xid_str); + } + + /* finally, add the detail strings, but without duplicates */ + while (details != NULL && details[0] != NULL) { + if (!ptr_array_contains_string (arr, details[0])) + g_ptr_array_add (arr, details[0]); + ++details; + } + + /* and NULL-terminate */ + g_ptr_array_add (arr, NULL); + + argv = (gchar **) arr->pdata; + + if (child_pid == NULL && exit_status != NULL) { + install_in_progress = TRUE; + ret = g_spawn_sync (NULL, argv, NULL, (GSpawnFlags) 0, NULL, NULL, + NULL, NULL, exit_status, &err); + install_in_progress = FALSE; + } else if (child_pid != NULL && exit_status == NULL) { + install_in_progress = TRUE; + ret = g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, + NULL, child_pid, &err); + } else { + g_return_val_if_reached (FALSE); + } + + if (!ret) { + GST_ERROR ("Error spawning plugin install helper: %s", err->message); + g_error_free (err); + } + + g_ptr_array_free (arr, TRUE); + return ret; +} + +static GstInstallPluginsReturn +gst_install_plugins_return_from_status (gint status) +{ + GstInstallPluginsReturn ret; + + /* did we exit cleanly? */ + if (!WIFEXITED (status)) { + ret = GST_INSTALL_PLUGINS_CRASHED; + } else { + ret = (GstInstallPluginsReturn) WEXITSTATUS (status); + + /* did the helper return an invalid status code? */ + if ((ret < 0 || ret >= GST_INSTALL_PLUGINS_STARTED_OK) && + ret != GST_INSTALL_PLUGINS_INTERNAL_FAILURE) { + ret = GST_INSTALL_PLUGINS_INVALID; + } + } + + GST_LOG ("plugin installer exited with status 0x%04x = %s", status, + gst_install_plugins_return_get_name (ret)); + + return ret; +} + +typedef struct +{ + GstInstallPluginsResultFunc func; + gpointer user_data; +} GstInstallPluginsAsyncHelper; + +static void +gst_install_plugins_installer_exited (GPid pid, gint status, gpointer data) +{ + GstInstallPluginsAsyncHelper *helper; + GstInstallPluginsReturn ret; + + install_in_progress = FALSE; + + helper = (GstInstallPluginsAsyncHelper *) data; + ret = gst_install_plugins_return_from_status (status); + + GST_LOG ("calling plugin install result function %p", helper->func); + helper->func (ret, helper->user_data); + + g_free (helper); +} + +/** + * gst_install_plugins_async: + * @details: NULL-terminated array of installer string details (see below) + * @ctx: a #GstInstallPluginsContext, or NULL + * @func: (scope async): the function to call when the installer program returns + * @user_data: (closure): the user data to pass to @func when called, or NULL + * + * Requests plugin installation without blocking. Once the plugins have been + * installed or installation has failed, @func will be called with the result + * of the installation and your provided @user_data pointer. + * + * This function requires a running GLib/Gtk main loop. If you are not + * running a GLib/Gtk main loop, make sure to regularly call + * g_main_context_iteration(NULL,FALSE). + * + * The installer strings that make up @detail are typically obtained by + * calling gst_missing_plugin_message_get_installer_detail() on missing-plugin + * messages that have been caught on a pipeline's bus or created by the + * application via the provided API, such as gst_missing_element_message_new(). + * + * It is possible to request the installation of multiple missing plugins in + * one go (as might be required if there is a demuxer for a certain format + * installed but no suitable video decoder and no suitable audio decoder). + * + * Returns: result code whether an external installer could be started + * + * Since: 0.10.12 + */ + +GstInstallPluginsReturn +gst_install_plugins_async (gchar ** details, GstInstallPluginsContext * ctx, + GstInstallPluginsResultFunc func, gpointer user_data) +{ + GstInstallPluginsAsyncHelper *helper; + GPid pid; + + g_return_val_if_fail (details != NULL, GST_INSTALL_PLUGINS_INTERNAL_FAILURE); + g_return_val_if_fail (func != NULL, GST_INSTALL_PLUGINS_INTERNAL_FAILURE); + + if (install_in_progress) + return GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS; + + /* if we can't access our helper, don't bother */ + if (!g_file_test (gst_install_plugins_get_helper (), + G_FILE_TEST_IS_EXECUTABLE)) + return GST_INSTALL_PLUGINS_HELPER_MISSING; + + if (!gst_install_plugins_spawn_child (details, ctx, &pid, NULL)) + return GST_INSTALL_PLUGINS_INTERNAL_FAILURE; + + helper = g_new (GstInstallPluginsAsyncHelper, 1); + helper->func = func; + helper->user_data = user_data; + + g_child_watch_add (pid, gst_install_plugins_installer_exited, helper); + + return GST_INSTALL_PLUGINS_STARTED_OK; +} + +/** + * gst_install_plugins_sync: + * @details: NULL-terminated array of installer string details + * @ctx: a #GstInstallPluginsContext, or NULL + * + * Requests plugin installation and block until the plugins have been + * installed or installation has failed. + * + * This function should almost never be used, it only exists for cases where + * a non-GLib main loop is running and the user wants to run it in a separate + * thread and marshal the result back asynchronously into the main thread + * using the other non-GLib main loop. You should almost always use + * gst_install_plugins_async() instead of this function. + * + * Returns: the result of the installation. + * + * Since: 0.10.12 + */ +GstInstallPluginsReturn +gst_install_plugins_sync (gchar ** details, GstInstallPluginsContext * ctx) +{ + gint status; + + g_return_val_if_fail (details != NULL, GST_INSTALL_PLUGINS_INTERNAL_FAILURE); + + if (install_in_progress) + return GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS; + + /* if we can't access our helper, don't bother */ + if (!g_file_test (gst_install_plugins_get_helper (), + G_FILE_TEST_IS_EXECUTABLE)) + return GST_INSTALL_PLUGINS_HELPER_MISSING; + + if (!gst_install_plugins_spawn_child (details, ctx, NULL, &status)) + return GST_INSTALL_PLUGINS_INTERNAL_FAILURE; + + return gst_install_plugins_return_from_status (status); +} + +/** + * gst_install_plugins_return_get_name: + * @ret: the return status code + * + * Convenience function to return the descriptive string associated + * with a status code. This function returns English strings and + * should not be used for user messages. It is here only to assist + * in debugging. + * + * Returns: a descriptive string for the status code in @ret + * + * Since: 0.10.12 + */ +const gchar * +gst_install_plugins_return_get_name (GstInstallPluginsReturn ret) +{ + switch (ret) { + case GST_INSTALL_PLUGINS_SUCCESS: + return "success"; + case GST_INSTALL_PLUGINS_NOT_FOUND: + return "not-found"; + case GST_INSTALL_PLUGINS_ERROR: + return "install-error"; + case GST_INSTALL_PLUGINS_CRASHED: + return "installer-exit-unclean"; + case GST_INSTALL_PLUGINS_PARTIAL_SUCCESS: + return "partial-success"; + case GST_INSTALL_PLUGINS_USER_ABORT: + return "user-abort"; + case GST_INSTALL_PLUGINS_STARTED_OK: + return "started-ok"; + case GST_INSTALL_PLUGINS_INTERNAL_FAILURE: + return "internal-failure"; + case GST_INSTALL_PLUGINS_HELPER_MISSING: + return "helper-missing"; + case GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS: + return "install-in-progress"; + case GST_INSTALL_PLUGINS_INVALID: + return "invalid"; + default: + break; + } + return "(UNKNOWN)"; +} + +/** + * gst_install_plugins_installation_in_progress: + * + * Checks whether plugin installation (initiated by this application only) + * is currently in progress. + * + * Returns: TRUE if plugin installation is in progress, otherwise FALSE + * + * Since: 0.10.12 + */ +gboolean +gst_install_plugins_installation_in_progress (void) +{ + return install_in_progress; +} + +/** + * gst_install_plugins_supported: + * + * Checks whether plugin installation is likely to be supported by the + * current environment. This currently only checks whether the helper script + * that is to be provided by the distribution or operating system vendor + * exists. + * + * Returns: TRUE if plugin installation is likely to be supported. + * + * Since: 0.10.15 + */ +gboolean +gst_install_plugins_supported (void) +{ + return g_file_test (gst_install_plugins_get_helper (), + G_FILE_TEST_IS_EXECUTABLE); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.h new file mode 100644 index 0000000..e57d8ac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/install-plugins.h @@ -0,0 +1,144 @@ +/* GStreamer base utils library plugin install support for applications + * Copyright (C) 2007 Tim-Philipp Müller + * Copyright (C) 2006 Ryan Lortie + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PB_UTILS_INSTALL_PLUGINS_H__ +#define __GST_PB_UTILS_INSTALL_PLUGINS_H__ + +#include + +G_BEGIN_DECLS + +/* + * functions for use by applications to initiate installation of missing plugins + */ + +/** + * GstInstallPluginsReturn: + * @GST_INSTALL_PLUGINS_SUCCESS: all of the requested plugins could be + * installed + * @GST_INSTALL_PLUGINS_NOT_FOUND: no appropriate installation candidate for + * any of the requested plugins could be found. Only return this if nothing + * has been installed. Return #GST_INSTALL_PLUGINS_PARTIAL_SUCCESS if + * some (but not all) of the requested plugins could be installed. + * @GST_INSTALL_PLUGINS_ERROR: an error occured during the installation. If + * this happens, the user has already seen an error message and another + * one should not be displayed + * @GST_INSTALL_PLUGINS_CRASHED: the installer had an unclean exit code + * (ie. death by signal) + * @GST_INSTALL_PLUGINS_PARTIAL_SUCCESS: some of the requested plugins could + * be installed, but not all + * @GST_INSTALL_PLUGINS_USER_ABORT: the user has aborted the installation + * @GST_INSTALL_PLUGINS_INVALID: the helper returned an invalid status code + * @GST_INSTALL_PLUGINS_STARTED_OK: returned by gst_install_plugins_async() to + * indicate that everything went fine so far and the provided callback + * will be called with the result of the installation later + * @GST_INSTALL_PLUGINS_INTERNAL_FAILURE: some internal failure has + * occured when trying to start the installer + * @GST_INSTALL_PLUGINS_HELPER_MISSING: the helper script to call the + * actual installer is not installed + * @GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS: a previously-started plugin + * installation is still in progress, try again later + * + * Result codes returned by gst_install_plugins_async() and + * gst_install_plugins_sync(), and also the result code passed to the + * #GstInstallPluginsResultFunc specified with gst_install_plugin_async(). + * + * These codes indicate success or failure of starting an external installer + * program and to what extent the requested plugins could be installed. + * + * Since: 0.10.12 + */ +typedef enum { + /* Return codes from the installer. Returned by gst_install_plugins_sync(), + * or passed as result code to your #GstInstallPluginsResultFunc */ + GST_INSTALL_PLUGINS_SUCCESS = 0, + GST_INSTALL_PLUGINS_NOT_FOUND = 1, + GST_INSTALL_PLUGINS_ERROR = 2, + GST_INSTALL_PLUGINS_PARTIAL_SUCCESS = 3, + GST_INSTALL_PLUGINS_USER_ABORT = 4, + + /* Returned by gst_install_plugins_sync(), or passed as result code to your + * #GstInstallPluginsResultFunc */ + GST_INSTALL_PLUGINS_CRASHED = 100, + GST_INSTALL_PLUGINS_INVALID, + + /* Return codes from starting the external helper, may be returned by both + * gst_install_plugins_sync() and gst_install_plugins_async(), but should + * never be seen by a #GstInstallPluginsResultFunc */ + GST_INSTALL_PLUGINS_STARTED_OK = 200, + GST_INSTALL_PLUGINS_INTERNAL_FAILURE, + GST_INSTALL_PLUGINS_HELPER_MISSING, + GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS +} GstInstallPluginsReturn; + +/** + * GstInstallPluginsContext: + * + * Opaque context structure for the plugin installation. Use the provided + * API to set details on it. + * + * Since: 0.10.12 + */ + +#define GST_TYPE_INSTALL_PLUGINS_CONTEXT (gst_install_plugins_context_get_type()) + +typedef struct _GstInstallPluginsContext GstInstallPluginsContext; + +GstInstallPluginsContext * gst_install_plugins_context_new (void); + +void gst_install_plugins_context_free (GstInstallPluginsContext * ctx); + +void gst_install_plugins_context_set_xid (GstInstallPluginsContext * ctx, + guint xid); + +GType gst_install_plugins_context_get_type (void); + +/** + * GstInstallPluginsResultFunc: + * @result: whether the installation of the requested plugins succeeded or not + * @user_data: the user data passed to gst_install_plugins_async() + * + * The prototype of the callback function that will be called once the + * external plugin installer program has returned. You only need to provide + * a callback function if you are using the asynchronous interface. + * + * Since: 0.10.12 + */ +typedef void (*GstInstallPluginsResultFunc) (GstInstallPluginsReturn result, + gpointer user_data); + +GstInstallPluginsReturn gst_install_plugins_async (gchar ** details, + GstInstallPluginsContext * ctx, + GstInstallPluginsResultFunc func, + gpointer user_data); + +GstInstallPluginsReturn gst_install_plugins_sync (gchar ** details, + GstInstallPluginsContext * ctx); + +const gchar * gst_install_plugins_return_get_name (GstInstallPluginsReturn ret); + +gboolean gst_install_plugins_installation_in_progress (void); + +gboolean gst_install_plugins_supported (void); + +G_END_DECLS + +#endif /* __GST_PB_UTILS_INSTALL_PLUGINS_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.c new file mode 100644 index 0000000..1b6d44b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.c @@ -0,0 +1,802 @@ +/* GStreamer base utils library missing plugins support + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpbutilsmissingplugins + * @short_description: Create, recognise and parse missing-plugins messages + * + * + * + * Functions to create, recognise and parse missing-plugins messages for + * applications and elements. + * + * + * Missing-plugin messages are posted on the bus by elements like decodebin + * or playbin if they can't find an appropriate source element or decoder + * element. The application can use these messages for two things: + * + * + * concise error/problem reporting to the user mentioning what exactly + * is missing, see gst_missing_plugin_message_get_description() + * + * + * initiate installation of missing plugins, see + * gst_missing_plugin_message_get_installer_detail() and + * gst_install_plugins_async() + * + * + * + * + * Applications may also create missing-plugin messages themselves to install + * required elements that are missing, using the install mechanism mentioned + * above. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include /* getpid on UNIX */ +#endif +#ifdef HAVE_PROCESS_H +# include /* getpid on win32 */ +#endif + +#include "gst/gst-i18n-plugin.h" + +#include "pbutils.h" +#include "pbutils-private.h" + +#include + +#define GST_DETAIL_STRING_MARKER "gstreamer" + +typedef enum +{ + GST_MISSING_TYPE_UNKNOWN = 0, + GST_MISSING_TYPE_URISOURCE, + GST_MISSING_TYPE_URISINK, + GST_MISSING_TYPE_ELEMENT, + GST_MISSING_TYPE_DECODER, + GST_MISSING_TYPE_ENCODER +} GstMissingType; + +static const struct +{ + GstMissingType type; + const gchar type_string[12]; +} missing_type_mapping[] = { + { + GST_MISSING_TYPE_URISOURCE, "urisource"}, { + GST_MISSING_TYPE_URISINK, "urisink"}, { + GST_MISSING_TYPE_ELEMENT, "element"}, { + GST_MISSING_TYPE_DECODER, "decoder"}, { + GST_MISSING_TYPE_ENCODER, "encoder"} +}; + +static GstMissingType +missing_structure_get_type (const GstStructure * s) +{ + const gchar *type; + guint i; + + type = gst_structure_get_string (s, "type"); + g_return_val_if_fail (type != NULL, GST_MISSING_TYPE_UNKNOWN); + + for (i = 0; i < G_N_ELEMENTS (missing_type_mapping); ++i) { + if (strcmp (missing_type_mapping[i].type_string, type) == 0) + return missing_type_mapping[i].type; + } + + return GST_MISSING_TYPE_UNKNOWN; +} + +GstCaps * +copy_and_clean_caps (const GstCaps * caps) +{ + GstStructure *s; + GstCaps *ret; + + ret = gst_caps_copy (caps); + + /* make caps easier to interpret, remove common fields that are likely + * to be irrelevant for determining the right plugin (ie. mostly fields + * where template caps usually have the standard MIN - MAX range as value) */ + s = gst_caps_get_structure (ret, 0); + gst_structure_remove_field (s, "codec_data"); + gst_structure_remove_field (s, "palette_data"); + gst_structure_remove_field (s, "pixel-aspect-ratio"); + gst_structure_remove_field (s, "framerate"); + gst_structure_remove_field (s, "leaf_size"); + gst_structure_remove_field (s, "packet_size"); + gst_structure_remove_field (s, "block_align"); + gst_structure_remove_field (s, "metadata-interval"); /* icy caps */ + /* decoders/encoders almost always handle the usual width/height/channel/rate + * range (and if we don't remove this then the app will have a much harder + * time blacklisting formats it has unsuccessfully tried to install before) */ + gst_structure_remove_field (s, "width"); + gst_structure_remove_field (s, "depth"); + gst_structure_remove_field (s, "height"); + gst_structure_remove_field (s, "channels"); + gst_structure_remove_field (s, "rate"); + /* rtp fields */ + gst_structure_remove_field (s, "config"); + gst_structure_remove_field (s, "clock-rate"); + gst_structure_remove_field (s, "clock-base"); + gst_structure_remove_field (s, "maxps"); + gst_structure_remove_field (s, "seqnum-base"); + gst_structure_remove_field (s, "npt-start"); + gst_structure_remove_field (s, "npt-stop"); + gst_structure_remove_field (s, "play-speed"); + gst_structure_remove_field (s, "play-scale"); + gst_structure_remove_field (s, "dynamic_range"); + + return ret; +} + +/** + * gst_missing_uri_source_message_new: + * @element: the #GstElement posting the message + * @protocol: the URI protocol the missing source needs to implement, + * e.g. "http" or "mms" + * + * Creates a missing-plugin message for @element to notify the application + * that a source element for a particular URI protocol is missing. This + * function is mainly for use in plugins. + * + * Returns: (transfer full): a new #GstMessage, or NULL on error + */ +GstMessage * +gst_missing_uri_source_message_new (GstElement * element, + const gchar * protocol) +{ + GstStructure *s; + gchar *description; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (protocol != NULL, NULL); + + description = gst_pb_utils_get_source_description (protocol); + + s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING, + "urisource", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING, + description, NULL); + + g_free (description); + return gst_message_new_element (GST_OBJECT_CAST (element), s); +} + +/** + * gst_missing_uri_sink_message_new: + * @element: the #GstElement posting the message + * @protocol: the URI protocol the missing sink needs to implement, + * e.g. "http" or "smb" + * + * Creates a missing-plugin message for @element to notify the application + * that a sink element for a particular URI protocol is missing. This + * function is mainly for use in plugins. + * + * Returns: (transfer full): a new #GstMessage, or NULL on error + */ +GstMessage * +gst_missing_uri_sink_message_new (GstElement * element, const gchar * protocol) +{ + GstStructure *s; + gchar *description; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (protocol != NULL, NULL); + + description = gst_pb_utils_get_sink_description (protocol); + + s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING, + "urisink", "detail", G_TYPE_STRING, protocol, "name", G_TYPE_STRING, + description, NULL); + + g_free (description); + return gst_message_new_element (GST_OBJECT_CAST (element), s); +} + +/** + * gst_missing_element_message_new: + * @element: the #GstElement posting the message + * @factory_name: the name of the missing element (element factory), + * e.g. "videoscale" or "cdparanoiasrc" + * + * Creates a missing-plugin message for @element to notify the application + * that a certain required element is missing. This function is mainly for + * use in plugins. + * + * Returns: (transfer full): a new #GstMessage, or NULL on error + */ +GstMessage * +gst_missing_element_message_new (GstElement * element, + const gchar * factory_name) +{ + GstStructure *s; + gchar *description; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (factory_name != NULL, NULL); + + description = gst_pb_utils_get_element_description (factory_name); + + s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING, + "element", "detail", G_TYPE_STRING, factory_name, "name", G_TYPE_STRING, + description, NULL); + + g_free (description); + return gst_message_new_element (GST_OBJECT_CAST (element), s); +} + +/** + * gst_missing_decoder_message_new: + * @element: the #GstElement posting the message + * @decode_caps: the (fixed) caps for which a decoder element is needed + * + * Creates a missing-plugin message for @element to notify the application + * that a decoder element for a particular set of (fixed) caps is missing. + * This function is mainly for use in plugins. + * + * Returns: (transfer full): a new #GstMessage, or NULL on error + */ +GstMessage * +gst_missing_decoder_message_new (GstElement * element, + const GstCaps * decode_caps) +{ + GstStructure *s; + GstCaps *caps; + gchar *description; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (decode_caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL); + g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL); + + description = gst_pb_utils_get_decoder_description (decode_caps); + caps = copy_and_clean_caps (decode_caps); + + s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING, + "decoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING, + description, NULL); + + gst_caps_unref (caps); + g_free (description); + + return gst_message_new_element (GST_OBJECT_CAST (element), s); +} + +/** + * gst_missing_encoder_message_new: + * @element: the #GstElement posting the message + * @encode_caps: the (fixed) caps for which an encoder element is needed + * + * Creates a missing-plugin message for @element to notify the application + * that an encoder element for a particular set of (fixed) caps is missing. + * This function is mainly for use in plugins. + * + * Returns: (transfer full): a new #GstMessage, or NULL on error + */ +GstMessage * +gst_missing_encoder_message_new (GstElement * element, + const GstCaps * encode_caps) +{ + GstStructure *s; + GstCaps *caps; + gchar *description; + + g_return_val_if_fail (element != NULL, NULL); + g_return_val_if_fail (GST_IS_ELEMENT (element), NULL); + g_return_val_if_fail (encode_caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL); + g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL); + + description = gst_pb_utils_get_encoder_description (encode_caps); + caps = copy_and_clean_caps (encode_caps); + + s = gst_structure_new ("missing-plugin", "type", G_TYPE_STRING, + "encoder", "detail", GST_TYPE_CAPS, caps, "name", G_TYPE_STRING, + description, NULL); + + gst_caps_unref (caps); + g_free (description); + + return gst_message_new_element (GST_OBJECT_CAST (element), s); +} + +static gboolean +missing_structure_get_string_detail (const GstStructure * s, gchar ** p_detail) +{ + const gchar *detail; + GType detail_type; + + *p_detail = NULL; + + detail_type = gst_structure_get_field_type (s, "detail"); + if (!g_type_is_a (detail_type, G_TYPE_STRING)) { + GST_WARNING ("expected 'detail' field to be of G_TYPE_STRING"); + return FALSE; + } + + detail = gst_structure_get_string (s, "detail"); + if (detail == NULL || *detail == '\0') { + GST_WARNING ("empty 'detail' field"); + return FALSE; + } + *p_detail = g_strdup (detail); + return TRUE; +} + +static gboolean +missing_structure_get_caps_detail (const GstStructure * s, GstCaps ** p_caps) +{ + const GstCaps *caps; + const GValue *val; + GType detail_type; + + *p_caps = NULL; + + detail_type = gst_structure_get_field_type (s, "detail"); + if (!g_type_is_a (detail_type, GST_TYPE_CAPS)) { + GST_WARNING ("expected 'detail' field to be of GST_TYPE_CAPS"); + return FALSE; + } + + val = gst_structure_get_value (s, "detail"); + caps = gst_value_get_caps (val); + if (gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { + GST_WARNING ("EMPTY or ANY caps not allowed"); + return FALSE; + } + + *p_caps = gst_caps_copy (caps); + return TRUE; +} + +/** + * gst_missing_plugin_message_get_installer_detail: + * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + */ +gchar * +gst_missing_plugin_message_get_installer_detail (GstMessage * msg) +{ + GstMissingType missing_type; + const gchar *progname; + const gchar *type; + GString *str = NULL; + gchar *detail = NULL; + gchar *desc; + + g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL); + + GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure); + + missing_type = missing_structure_get_type (msg->structure); + if (missing_type == GST_MISSING_TYPE_UNKNOWN) { + GST_WARNING ("couldn't parse 'type' field"); + goto error; + } + + type = gst_structure_get_string (msg->structure, "type"); + g_assert (type != NULL); /* validity already checked above */ + + /* FIXME: use gst_installer_detail_new() here too */ + str = g_string_new (GST_DETAIL_STRING_MARKER "|"); + g_string_append_printf (str, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR); + + progname = (const gchar *) g_get_prgname (); + if (progname) { + g_string_append_printf (str, "%s|", progname); + } else { + g_string_append_printf (str, "pid/%lu|", (gulong) getpid ()); + } + + desc = gst_missing_plugin_message_get_description (msg); + if (desc) { + g_strdelimit (desc, "|", '#'); + g_string_append_printf (str, "%s|", desc); + g_free (desc); + } else { + g_string_append (str, "|"); + } + + switch (missing_type) { + case GST_MISSING_TYPE_URISOURCE: + case GST_MISSING_TYPE_URISINK: + case GST_MISSING_TYPE_ELEMENT: + if (!missing_structure_get_string_detail (msg->structure, &detail)) + goto error; + break; + case GST_MISSING_TYPE_DECODER: + case GST_MISSING_TYPE_ENCODER:{ + GstCaps *caps = NULL; + + if (!missing_structure_get_caps_detail (msg->structure, &caps)) + goto error; + + detail = gst_caps_to_string (caps); + gst_caps_unref (caps); + break; + } + default: + g_return_val_if_reached (NULL); + } + + g_string_append_printf (str, "%s-%s", type, detail); + g_free (detail); + + return g_string_free (str, FALSE); + +/* ERRORS */ +error: + { + GST_WARNING ("Failed to parse missing-plugin msg: %" GST_PTR_FORMAT, msg); + if (str) + g_string_free (str, TRUE); + return NULL; + } +} + +/** + * gst_missing_plugin_message_get_description: + * @msg: a missing-plugin #GstMessage of type #GST_MESSAGE_ELEMENT + * + * Returns a localised string describing the missing feature, for use in + * error dialogs and the like. Should never return NULL unless @msg is not + * a valid missing-plugin message. + * + * This function is mainly for applications that need a human-readable string + * describing a missing plugin, given a previously collected missing-plugin + * message + * + * Returns: a newly-allocated description string, or NULL on error. Free + * string with g_free() when not needed any longer. + */ +gchar * +gst_missing_plugin_message_get_description (GstMessage * msg) +{ + GstMissingType missing_type; + const gchar *desc; + gchar *ret = NULL; + + g_return_val_if_fail (gst_is_missing_plugin_message (msg), NULL); + + GST_LOG ("Parsing missing-plugin message: %" GST_PTR_FORMAT, msg->structure); + + desc = gst_structure_get_string (msg->structure, "name"); + if (desc != NULL && *desc != '\0') { + ret = g_strdup (desc); + goto done; + } + + /* fallback #1 */ + missing_type = missing_structure_get_type (msg->structure); + + switch (missing_type) { + case GST_MISSING_TYPE_URISOURCE: + case GST_MISSING_TYPE_URISINK: + case GST_MISSING_TYPE_ELEMENT:{ + gchar *detail = NULL; + + if (missing_structure_get_string_detail (msg->structure, &detail)) { + if (missing_type == GST_MISSING_TYPE_URISOURCE) + ret = gst_pb_utils_get_source_description (detail); + else if (missing_type == GST_MISSING_TYPE_URISINK) + ret = gst_pb_utils_get_sink_description (detail); + else + ret = gst_pb_utils_get_sink_description (detail); + g_free (detail); + } + break; + } + case GST_MISSING_TYPE_DECODER: + case GST_MISSING_TYPE_ENCODER:{ + GstCaps *caps = NULL; + + if (missing_structure_get_caps_detail (msg->structure, &caps)) { + if (missing_type == GST_MISSING_TYPE_DECODER) + ret = gst_pb_utils_get_decoder_description (caps); + else + ret = gst_pb_utils_get_encoder_description (caps); + gst_caps_unref (caps); + } + break; + } + default: + break; + } + + if (ret) + goto done; + + /* fallback #2 */ + switch (missing_type) { + case GST_MISSING_TYPE_URISOURCE: + desc = _("Unknown source element"); + break; + case GST_MISSING_TYPE_URISINK: + desc = _("Unknown sink element"); + break; + case GST_MISSING_TYPE_ELEMENT: + desc = _("Unknown element"); + break; + case GST_MISSING_TYPE_DECODER: + desc = _("Unknown decoder element"); + break; + case GST_MISSING_TYPE_ENCODER: + desc = _("Unknown encoder element"); + break; + default: + /* we should really never get here, but we better still return + * something if we do */ + desc = _("Plugin or element of unknown type"); + break; + } + ret = g_strdup (desc); + +done: + + GST_LOG ("returning '%s'", ret); + return ret; +} + +/** + * gst_is_missing_plugin_message: + * @msg: a #GstMessage + * + * Checks whether @msg is a missing plugins message. + * + * Returns: %TRUE if @msg is a missing-plugins message, otherwise %FALSE. + */ +gboolean +gst_is_missing_plugin_message (GstMessage * msg) +{ + g_return_val_if_fail (msg != NULL, FALSE); + g_return_val_if_fail (GST_IS_MESSAGE (msg), FALSE); + + if (GST_MESSAGE_TYPE (msg) != GST_MESSAGE_ELEMENT || msg->structure == NULL) + return FALSE; + + return gst_structure_has_name (msg->structure, "missing-plugin"); +} + +/* takes ownership of the description */ +static gchar * +gst_installer_detail_new (gchar * description, const gchar * type, + const gchar * detail) +{ + const gchar *progname; + GString *s; + + s = g_string_new (GST_DETAIL_STRING_MARKER "|"); + g_string_append_printf (s, "%u.%u|", GST_VERSION_MAJOR, GST_VERSION_MINOR); + + progname = (const gchar *) g_get_prgname (); + if (progname) { + g_string_append_printf (s, "%s|", progname); + } else { + g_string_append_printf (s, "pid/%lu|", (gulong) getpid ()); + } + + if (description) { + g_strdelimit (description, "|", '#'); + g_string_append_printf (s, "%s|", description); + g_free (description); + } else { + g_string_append (s, "|"); + } + + g_string_append_printf (s, "%s-%s", type, detail); + + return g_string_free (s, FALSE); +} + +/** + * gst_missing_uri_source_installer_detail_new: + * @protocol: the URI protocol the missing source needs to implement, + * e.g. "http" or "mms" + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions in + * the case where the application knows exactly what kind of plugin it is + * missing. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + * + * Since: 0.10.15 + */ +gchar * +gst_missing_uri_source_installer_detail_new (const gchar * protocol) +{ + gchar *desc; + + g_return_val_if_fail (protocol != NULL, NULL); + + desc = gst_pb_utils_get_source_description (protocol); + return gst_installer_detail_new (desc, "urisource", protocol); +} + +/** + * gst_missing_uri_sink_installer_detail_new: + * @protocol: the URI protocol the missing source needs to implement, + * e.g. "http" or "mms" + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions in + * the case where the application knows exactly what kind of plugin it is + * missing. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + * + * Since: 0.10.15 + */ +gchar * +gst_missing_uri_sink_installer_detail_new (const gchar * protocol) +{ + gchar *desc; + + g_return_val_if_fail (protocol != NULL, NULL); + + desc = gst_pb_utils_get_sink_description (protocol); + return gst_installer_detail_new (desc, "urisink", protocol); +} + +/** + * gst_missing_element_installer_detail_new: + * @factory_name: the name of the missing element (element factory), + * e.g. "videoscale" or "cdparanoiasrc" + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions in + * the case where the application knows exactly what kind of plugin it is + * missing. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + * + * Since: 0.10.15 + */ +gchar * +gst_missing_element_installer_detail_new (const gchar * factory_name) +{ + gchar *desc; + + g_return_val_if_fail (factory_name != NULL, NULL); + + desc = gst_pb_utils_get_element_description (factory_name); + return gst_installer_detail_new (desc, "element", factory_name); +} + +/** + * gst_missing_decoder_installer_detail_new: + * @decode_caps: the (fixed) caps for which a decoder element is needed + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions in + * the case where the application knows exactly what kind of plugin it is + * missing. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + * + * Since: 0.10.15 + */ +gchar * +gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps) +{ + GstCaps *caps; + gchar *detail_str, *caps_str, *desc; + + g_return_val_if_fail (decode_caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (decode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_any (decode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_empty (decode_caps), NULL); + g_return_val_if_fail (gst_caps_is_fixed (decode_caps), NULL); + + desc = gst_pb_utils_get_decoder_description (decode_caps); + caps = copy_and_clean_caps (decode_caps); + caps_str = gst_caps_to_string (caps); + detail_str = gst_installer_detail_new (desc, "decoder", caps_str); + g_free (caps_str); + gst_caps_unref (caps); + + return detail_str; +} + +/** + * gst_missing_encoder_installer_detail_new: + * @encode_caps: the (fixed) caps for which an encoder element is needed + * + * Returns an opaque string containing all the details about the missing + * element to be passed to an external installer called via + * gst_install_plugins_async() or gst_install_plugins_sync(). + * + * This function is mainly for applications that call external plugin + * installation mechanisms using one of the two above-mentioned functions in + * the case where the application knows exactly what kind of plugin it is + * missing. + * + * Returns: a newly-allocated detail string, or NULL on error. Free string + * with g_free() when not needed any longer. + * + * Since: 0.10.15 + */ +gchar * +gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps) +{ + GstCaps *caps; + gchar *detail_str, *caps_str, *desc; + + g_return_val_if_fail (encode_caps != NULL, NULL); + g_return_val_if_fail (GST_IS_CAPS (encode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_any (encode_caps), NULL); + g_return_val_if_fail (!gst_caps_is_empty (encode_caps), NULL); + g_return_val_if_fail (gst_caps_is_fixed (encode_caps), NULL); + + desc = gst_pb_utils_get_encoder_description (encode_caps); + caps = copy_and_clean_caps (encode_caps); + caps_str = gst_caps_to_string (caps); + detail_str = gst_installer_detail_new (desc, "encoder", caps_str); + g_free (caps_str); + gst_caps_unref (caps); + + return detail_str; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.h new file mode 100644 index 0000000..508304e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/missing-plugins.h @@ -0,0 +1,77 @@ +/* GStreamer base utils library missing plugins support + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PB_UTILS_MISSING_PLUGINS_H__ +#define __GST_PB_UTILS_MISSING_PLUGINS_H__ + +#include +#include + +G_BEGIN_DECLS + +/* + * functions to create missing-plugin messages, for use by plugins primarily + */ + +GstMessage * gst_missing_uri_source_message_new (GstElement * element, + const gchar * protocol); + +GstMessage * gst_missing_uri_sink_message_new (GstElement * element, + const gchar * protocol); + +GstMessage * gst_missing_element_message_new (GstElement * element, + const gchar * factory_name); + +GstMessage * gst_missing_decoder_message_new (GstElement * element, + const GstCaps * decode_caps); + +GstMessage * gst_missing_encoder_message_new (GstElement * element, + const GstCaps * encode_caps); + +/* + * functions for use by applications when dealing with missing-plugin messages + */ + +gchar * gst_missing_plugin_message_get_installer_detail (GstMessage * msg); + +gchar * gst_missing_plugin_message_get_description (GstMessage * msg); + +gboolean gst_is_missing_plugin_message (GstMessage * msg); + + +/* + * functions for use by applications that know exactly what plugins they are + * missing and want to request them directly rather than just react to + * missing-plugin messages posted by elements such as playbin or decodebin + */ + +gchar * gst_missing_uri_source_installer_detail_new (const gchar * protocol); + +gchar * gst_missing_uri_sink_installer_detail_new (const gchar * protocol); + +gchar * gst_missing_element_installer_detail_new (const gchar * factory_name); + +gchar * gst_missing_decoder_installer_detail_new (const GstCaps * decode_caps); + +gchar * gst_missing_encoder_installer_detail_new (const GstCaps * encode_caps); + +G_END_DECLS + +#endif /* __GST_PB_UTILS_MISSING_PLUGINS_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-marshal.list b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-marshal.list new file mode 100644 index 0000000..f409996 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-marshal.list @@ -0,0 +1,2 @@ +# pbutils marshallers +VOID:POINTER,BOXED diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-private.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-private.h new file mode 100644 index 0000000..5031df0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils-private.h @@ -0,0 +1,86 @@ +/* GStreamer + * Copyright (C) 2010 Edward Hervey + * 2010 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +struct _GstDiscovererStreamInfo { + GstMiniObject parent; + + GstDiscovererStreamInfo *previous; /* NULL for starting points */ + GstDiscovererStreamInfo *next; /* NULL for containers */ + + GstCaps *caps; + GstTagList *tags; + GstStructure *misc; +}; + +struct _GstDiscovererContainerInfo { + GstDiscovererStreamInfo parent; + + GList *streams; +}; + +struct _GstDiscovererAudioInfo { + GstDiscovererStreamInfo parent; + + guint channels; + guint sample_rate; + guint depth; + + guint bitrate; + guint max_bitrate; +}; + +struct _GstDiscovererVideoInfo { + GstDiscovererStreamInfo parent; + + guint width; + guint height; + guint depth; + guint framerate_num; + guint framerate_denom; + guint par_num; + guint par_denom; + gboolean interlaced; + + guint bitrate; + guint max_bitrate; + + gboolean is_image; +}; + +struct _GstDiscovererInfo { + GstMiniObject parent; + + gchar *uri; + GstDiscovererResult result; + + /* Sub-streams */ + GstDiscovererStreamInfo *stream_info; + GList *stream_list; + + /* Stream global information */ + GstClockTime duration; + GstStructure *misc; + GstTagList *tags; + gboolean seekable; +}; + +/* missing-plugins.c */ + +GstCaps *copy_and_clean_caps (const GstCaps * caps); diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.c new file mode 100644 index 0000000..8accb8d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.c @@ -0,0 +1,108 @@ +/* GStreamer base utils library + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstpbutils + * @short_description: General Application and Plugin Utility Library + * + * + * + * libgstpbutils is a general utility library for plugins and applications, + * available since gst-plugins-base 0.10.12. It currently provides the + * following: + * + * + * + * + * human-readable description strings of codecs, elements, sources, decoders, + * encoders, or sinks from decoder/encoder caps, element names, or protocol + * names. + * + * + * + * + * support for applications to initiate installation of missing plugins (if + * this is supported by the distribution or operating system used) + * + * + * + * + * API for GStreamer elements to create missing-plugin messages in order to + * communicate to the application that a certain type of plugin is missing + * (decoder, encoder, URI protocol source, URI protocol sink, named element) + * + * + * + * + * API for applications to recognise and handle missing-plugin messages + * + * + * + * Linking to this library + * + * You should obtain the required CFLAGS and LIBS using pkg-config on the + * gstreamer-plugins-base-0.10 module. You will then also need to add + * '-lgstpbutils-0.10' manually to your LIBS line. + * + * Library initialisation + * + * Before using any of its functions, applications and plugins must call + * gst_pb_utils_init() to initialise the library. + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "pbutils.h" + +#include "gst/gst-i18n-plugin.h" + +/** + * gst_pb_utils_init: + * + * Initialises the base utils support library. This function is not + * thread-safe. Applications should call it after calling gst_init(), + * plugins should call it from their plugin_init function. + * + * This function may be called multiple times. It will do nothing if the + * library has already been initialised. + * + * Since: 0.10.12 + */ +void +gst_pb_utils_init (void) +{ + static gboolean inited; /* FALSE */ + + if (inited) { + GST_LOG ("already initialised"); + return; + } +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + inited = TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.h new file mode 100644 index 0000000..b9277b1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/pbutils/pbutils.h @@ -0,0 +1,42 @@ +/* GStreamer base utils library + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PB_UTILS_BASE_UTILS_H__ +#define __GST_PB_UTILS_BASE_UTILS_H__ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +void gst_pb_utils_init (void); + +G_END_DECLS + +#endif /* __GST_PB_UTILS_BASE_UTILS_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/Makefile.am new file mode 100644 index 0000000..b22fcde --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/Makefile.am @@ -0,0 +1,92 @@ +lib_LTLIBRARIES = libgstriff-@GST_MAJORMINOR@.la + +libgstriff_@GST_MAJORMINOR@_la_SOURCES = \ + riff.c \ + riff-media.c \ + riff-read.c + +libgstriff_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/riff +libgstriff_@GST_MAJORMINOR@include_HEADERS = \ + riff-ids.h \ + riff-media.h \ + riff-read.h + +libgstriff_@GST_MAJORMINOR@_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) + +libgstriff_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstriff_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstRiff-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstriff_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstriff_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/riff/%',$(libgstriff_@GST_MAJORMINOR@include_HEADERS)) + +GstRiff-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstriff-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstRiff \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + --add-include-path=$(builddir)/../tag \ + --add-include-path=$(builddir)/../audio \ + --add-include-path=$(builddir)/../interfaces \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstriff-@GST_MAJORMINOR@.la \ + --include=GstAudio-@GST_MAJORMINOR@ \ + --include=GstTag-@GST_MAJORMINOR@ \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-tag-@GST_MAJORMINOR@ \ + --pkg gstreamer-audio-@GST_MAJORMINOR@ \ + --pkg gstreamer-interfaces-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-riff-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=$(builddir)/../tag \ + --includedir=$(builddir)/../audio \ + --includedir=$(builddir)/../interfaces \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am + androgenizer -:PROJECT libgstriff -:SHARED libgstriff-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstriff_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstriff_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstriff_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstriff_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/tag \ + -:HEADERS $(libgstriff_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-ids.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-ids.h new file mode 100644 index 0000000..8771d2e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-ids.h @@ -0,0 +1,517 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff-ids.h: RIFF IDs and structs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RIFF_IDS_H__ +#define __GST_RIFF_IDS_H__ + +#include + +G_BEGIN_DECLS + +/* RIFF types */ +#define GST_RIFF_RIFF_WAVE GST_MAKE_FOURCC ('W','A','V','E') +#define GST_RIFF_RIFF_AVI GST_MAKE_FOURCC ('A','V','I',' ') +#define GST_RIFF_RIFF_CDXA GST_MAKE_FOURCC ('C','D','X','A') + +/* tags */ +#define GST_RIFF_TAG_RIFF GST_MAKE_FOURCC ('R','I','F','F') +#define GST_RIFF_TAG_AVF0 GST_MAKE_FOURCC ('A','V','F','0') +#define GST_RIFF_TAG_RIFX GST_MAKE_FOURCC ('R','I','F','X') +#define GST_RIFF_TAG_LIST GST_MAKE_FOURCC ('L','I','S','T') +#define GST_RIFF_TAG_avih GST_MAKE_FOURCC ('a','v','i','h') +#define GST_RIFF_TAG_strd GST_MAKE_FOURCC ('s','t','r','d') +#define GST_RIFF_TAG_strn GST_MAKE_FOURCC ('s','t','r','n') +#define GST_RIFF_TAG_strh GST_MAKE_FOURCC ('s','t','r','h') +#define GST_RIFF_TAG_strf GST_MAKE_FOURCC ('s','t','r','f') +#define GST_RIFF_TAG_vedt GST_MAKE_FOURCC ('v','e','d','t') +#define GST_RIFF_TAG_JUNK GST_MAKE_FOURCC ('J','U','N','K') +#define GST_RIFF_TAG_JUNQ GST_MAKE_FOURCC ('J','U','N','Q') +#define GST_RIFF_TAG_idx1 GST_MAKE_FOURCC ('i','d','x','1') +#define GST_RIFF_TAG_dmlh GST_MAKE_FOURCC ('d','m','l','h') +/* WAV stuff */ +#define GST_RIFF_TAG_fmt GST_MAKE_FOURCC ('f','m','t',' ') +#define GST_RIFF_TAG_data GST_MAKE_FOURCC ('d','a','t','a') +#define GST_RIFF_TAG_plst GST_MAKE_FOURCC ('p','l','s','t') +#define GST_RIFF_TAG_cue GST_MAKE_FOURCC ('c','u','e',' ') +#define GST_RIFF_TAG_bext GST_MAKE_FOURCC ('b','e','x','t') +#define GST_RIFF_TAG_BEXT GST_MAKE_FOURCC ('B','E','X','T') +#define GST_RIFF_TAG_fact GST_MAKE_FOURCC ('f','a','c','t') +#define GST_RIFF_TAG_acid GST_MAKE_FOURCC ('a','c','i','d') + +/* LIST types */ +#define GST_RIFF_LIST_movi GST_MAKE_FOURCC ('m','o','v','i') +#define GST_RIFF_LIST_hdrl GST_MAKE_FOURCC ('h','d','r','l') +#define GST_RIFF_LIST_odml GST_MAKE_FOURCC ('o','d','m','l') +#define GST_RIFF_LIST_strl GST_MAKE_FOURCC ('s','t','r','l') +#define GST_RIFF_LIST_INFO GST_MAKE_FOURCC ('I','N','F','O') +#define GST_RIFF_LIST_AVIX GST_MAKE_FOURCC ('A','V','I','X') +#define GST_RIFF_LIST_adtl GST_MAKE_FOURCC ('a','d','t','l') + +/* fcc types */ +#define GST_RIFF_FCC_vids GST_MAKE_FOURCC ('v','i','d','s') +#define GST_RIFF_FCC_auds GST_MAKE_FOURCC ('a','u','d','s') +#define GST_RIFF_FCC_pads GST_MAKE_FOURCC ('p','a','d','s') +#define GST_RIFF_FCC_txts GST_MAKE_FOURCC ('t','x','t','s') +#define GST_RIFF_FCC_vidc GST_MAKE_FOURCC ('v','i','d','c') +#define GST_RIFF_FCC_iavs GST_MAKE_FOURCC ('i','a','v','s') +/* fcc handlers */ +#define GST_RIFF_FCCH_RLE GST_MAKE_FOURCC ('R','L','E',' ') +#define GST_RIFF_FCCH_msvc GST_MAKE_FOURCC ('m','s','v','c') +#define GST_RIFF_FCCH_MSVC GST_MAKE_FOURCC ('M','S','V','C') + +/* INFO types - see http://www.saettler.com/RIFFMCI/riffmci.html */ +#define GST_RIFF_INFO_IARL GST_MAKE_FOURCC ('I','A','R','L') /* location */ +#define GST_RIFF_INFO_IART GST_MAKE_FOURCC ('I','A','R','T') /* artist */ +#define GST_RIFF_INFO_ICMS GST_MAKE_FOURCC ('I','C','M','S') /* commissioned */ +#define GST_RIFF_INFO_ICMT GST_MAKE_FOURCC ('I','C','M','T') /* comment */ +#define GST_RIFF_INFO_ICOP GST_MAKE_FOURCC ('I','C','O','P') /* copyright */ +#define GST_RIFF_INFO_ICRD GST_MAKE_FOURCC ('I','C','R','D') /* creation date */ +#define GST_RIFF_INFO_ICRP GST_MAKE_FOURCC ('I','C','R','P') /* cropped */ +#define GST_RIFF_INFO_IDIM GST_MAKE_FOURCC ('I','D','I','M') /* dimensions */ +#define GST_RIFF_INFO_IDPI GST_MAKE_FOURCC ('I','D','P','I') /* dots-per-inch */ +#define GST_RIFF_INFO_IENG GST_MAKE_FOURCC ('I','E','N','G') /* engineer(s) */ +#define GST_RIFF_INFO_IGNR GST_MAKE_FOURCC ('I','G','N','R') /* genre */ +#define GST_RIFF_INFO_IKEY GST_MAKE_FOURCC ('I','K','E','Y') /* keywords */ +#define GST_RIFF_INFO_ILGT GST_MAKE_FOURCC ('I','L','G','T') /* lightness */ +#define GST_RIFF_INFO_IMED GST_MAKE_FOURCC ('I','M','E','D') /* medium */ +#define GST_RIFF_INFO_INAM GST_MAKE_FOURCC ('I','N','A','M') /* name */ +#define GST_RIFF_INFO_IPLT GST_MAKE_FOURCC ('I','P','L','T') /* palette setting */ +#define GST_RIFF_INFO_IPRD GST_MAKE_FOURCC ('I','P','R','D') /* product */ +#define GST_RIFF_INFO_ISBJ GST_MAKE_FOURCC ('I','S','B','J') /* subject */ +#define GST_RIFF_INFO_ISFT GST_MAKE_FOURCC ('I','S','F','T') /* software */ +#define GST_RIFF_INFO_ISHP GST_MAKE_FOURCC ('I','S','H','P') /* sharpness */ +#define GST_RIFF_INFO_ISRC GST_MAKE_FOURCC ('I','S','R','C') /* source */ +#define GST_RIFF_INFO_ISRF GST_MAKE_FOURCC ('I','S','R','F') /* source form */ +#define GST_RIFF_INFO_ITCH GST_MAKE_FOURCC ('I','T','C','H') /* technician(s) */ + +/*********Chunk Names***************/ +#define GST_RIFF_FF00 GST_MAKE_FOURCC (0xFF,0xFF,0x00,0x00) +#define GST_RIFF_00 GST_MAKE_FOURCC ('0', '0',0x00,0x00) +#define GST_RIFF_01 GST_MAKE_FOURCC ('0', '1',0x00,0x00) +#define GST_RIFF_02 GST_MAKE_FOURCC ('0', '2',0x00,0x00) +#define GST_RIFF_03 GST_MAKE_FOURCC ('0', '3',0x00,0x00) +#define GST_RIFF_04 GST_MAKE_FOURCC ('0', '4',0x00,0x00) +#define GST_RIFF_05 GST_MAKE_FOURCC ('0', '5',0x00,0x00) +#define GST_RIFF_06 GST_MAKE_FOURCC ('0', '6',0x00,0x00) +#define GST_RIFF_07 GST_MAKE_FOURCC ('0', '7',0x00,0x00) +#define GST_RIFF_00pc GST_MAKE_FOURCC ('0', '0', 'p', 'c') +#define GST_RIFF_01pc GST_MAKE_FOURCC ('0', '1', 'p', 'c') +#define GST_RIFF_00dc GST_MAKE_FOURCC ('0', '0', 'd', 'c') +#define GST_RIFF_00dx GST_MAKE_FOURCC ('0', '0', 'd', 'x') +#define GST_RIFF_00db GST_MAKE_FOURCC ('0', '0', 'd', 'b') +#define GST_RIFF_00xx GST_MAKE_FOURCC ('0', '0', 'x', 'x') +#define GST_RIFF_00id GST_MAKE_FOURCC ('0', '0', 'i', 'd') +#define GST_RIFF_00rt GST_MAKE_FOURCC ('0', '0', 'r', 't') +#define GST_RIFF_0021 GST_MAKE_FOURCC ('0', '0', '2', '1') +#define GST_RIFF_00iv GST_MAKE_FOURCC ('0', '0', 'i', 'v') +#define GST_RIFF_0031 GST_MAKE_FOURCC ('0', '0', '3', '1') +#define GST_RIFF_0032 GST_MAKE_FOURCC ('0', '0', '3', '2') +#define GST_RIFF_00vc GST_MAKE_FOURCC ('0', '0', 'v', 'c') +#define GST_RIFF_00xm GST_MAKE_FOURCC ('0', '0', 'x', 'm') +#define GST_RIFF_01wb GST_MAKE_FOURCC ('0', '1', 'w', 'b') +#define GST_RIFF_01dc GST_MAKE_FOURCC ('0', '1', 'd', 'c') +#define GST_RIFF_00__ GST_MAKE_FOURCC ('0', '0', '_', '_') + +/*********VIDEO CODECS**************/ +#define GST_RIFF_cram GST_MAKE_FOURCC ('c', 'r', 'a', 'm') +#define GST_RIFF_CRAM GST_MAKE_FOURCC ('C', 'R', 'A', 'M') +#define GST_RIFF_wham GST_MAKE_FOURCC ('w', 'h', 'a', 'm') +#define GST_RIFF_WHAM GST_MAKE_FOURCC ('W', 'H', 'A', 'M') +#define GST_RIFF_rgb GST_MAKE_FOURCC (0x00,0x00,0x00,0x00) +#define GST_RIFF_RGB GST_MAKE_FOURCC ('R', 'G', 'B', ' ') +#define GST_RIFF_RAW GST_MAKE_FOURCC ('R', 'A', 'W', ' ') +#define GST_RIFF_DIB GST_MAKE_FOURCC ('D', 'I', 'B', ' ') +#define GST_RIFF_rle8 GST_MAKE_FOURCC (0x01,0x00,0x00,0x00) +#define GST_RIFF_RLE8 GST_MAKE_FOURCC ('R', 'L', 'E', '8') +#define GST_RIFF_rle4 GST_MAKE_FOURCC (0x02,0x00,0x00,0x00) +#define GST_RIFF_RLE4 GST_MAKE_FOURCC ('R', 'L', 'E', '4') +#define GST_RIFF_none GST_MAKE_FOURCC (0x00,0x00,0xFF,0xFF) +#define GST_RIFF_NONE GST_MAKE_FOURCC ('N', 'O', 'N', 'E') +#define GST_RIFF_pack GST_MAKE_FOURCC (0x01,0x00,0xFF,0xFF) +#define GST_RIFF_PACK GST_MAKE_FOURCC ('P', 'A', 'C', 'K') +#define GST_RIFF_tran GST_MAKE_FOURCC (0x02,0x00,0xFF,0xFF) +#define GST_RIFF_TRAN GST_MAKE_FOURCC ('T', 'R', 'A', 'N') +#define GST_RIFF_ccc GST_MAKE_FOURCC (0x03,0x00,0xFF,0xFF) +#define GST_RIFF_CCC GST_MAKE_FOURCC ('C', 'C', 'C', ' ') +#define GST_RIFF_cyuv GST_MAKE_FOURCC ('c', 'y', 'u', 'v') +#define GST_RIFF_CYUV GST_MAKE_FOURCC ('C', 'Y', 'U', 'V') +#define GST_RIFF_jpeg GST_MAKE_FOURCC (0x04,0x00,0xFF,0xFF) +#define GST_RIFF_JPEG GST_MAKE_FOURCC ('J', 'P', 'E', 'G') +#define GST_RIFF_MJPG GST_MAKE_FOURCC ('M', 'J', 'P', 'G') +#define GST_RIFF_mJPG GST_MAKE_FOURCC ('m', 'J', 'P', 'G') +#define GST_RIFF_IJPG GST_MAKE_FOURCC ('I', 'J', 'P', 'G') +#define GST_RIFF_rt21 GST_MAKE_FOURCC ('r', 't', '2', '1') +#define GST_RIFF_RT21 GST_MAKE_FOURCC ('R', 'T', '2', '1') +#define GST_RIFF_iv31 GST_MAKE_FOURCC ('i', 'v', '3', '1') +#define GST_RIFF_IV31 GST_MAKE_FOURCC ('I', 'V', '3', '1') +#define GST_RIFF_iv32 GST_MAKE_FOURCC ('i', 'v', '3', '2') +#define GST_RIFF_IV32 GST_MAKE_FOURCC ('I', 'V', '3', '2') +#define GST_RIFF_iv41 GST_MAKE_FOURCC ('i', 'v', '4', '1') +#define GST_RIFF_IV41 GST_MAKE_FOURCC ('I', 'V', '4', '1') +#define GST_RIFF_iv50 GST_MAKE_FOURCC ('i', 'v', '5', '0') +#define GST_RIFF_IV50 GST_MAKE_FOURCC ('I', 'V', '5', '0') +#define GST_RIFF_cvid GST_MAKE_FOURCC ('c', 'v', 'i', 'd') +#define GST_RIFF_CVID GST_MAKE_FOURCC ('C', 'V', 'I', 'D') +#define GST_RIFF_ULTI GST_MAKE_FOURCC ('U', 'L', 'T', 'I') +#define GST_RIFF_ulti GST_MAKE_FOURCC ('u', 'l', 't', 'i') +#define GST_RIFF_YUV9 GST_MAKE_FOURCC ('Y', 'V', 'U', '9') +#define GST_RIFF_YVU9 GST_MAKE_FOURCC ('Y', 'U', 'V', '9') +#define GST_RIFF_XMPG GST_MAKE_FOURCC ('X', 'M', 'P', 'G') +#define GST_RIFF_xmpg GST_MAKE_FOURCC ('x', 'm', 'p', 'g') +#define GST_RIFF_VDOW GST_MAKE_FOURCC ('V', 'D', 'O', 'W') +#define GST_RIFF_MVI1 GST_MAKE_FOURCC ('M', 'V', 'I', '1') +#define GST_RIFF_v422 GST_MAKE_FOURCC ('v', '4', '2', '2') +#define GST_RIFF_V422 GST_MAKE_FOURCC ('V', '4', '2', '2') +#define GST_RIFF_mvi1 GST_MAKE_FOURCC ('m', 'v', 'i', '1') +#define GST_RIFF_MPIX GST_MAKE_FOURCC (0x04,0x00, 'i', '1') /* MotionPixels munged their id */ +#define GST_RIFF_AURA GST_MAKE_FOURCC ('A', 'U', 'R', 'A') +#define GST_RIFF_DMB1 GST_MAKE_FOURCC ('D', 'M', 'B', '1') +#define GST_RIFF_dmb1 GST_MAKE_FOURCC ('d', 'm', 'b', '1') + +#define GST_RIFF_BW10 GST_MAKE_FOURCC ('B', 'W', '1', '0') +#define GST_RIFF_bw10 GST_MAKE_FOURCC ('b', 'w', '1', '0') + +#define GST_RIFF_yuy2 GST_MAKE_FOURCC ('y', 'u', 'y', '2') +#define GST_RIFF_YUY2 GST_MAKE_FOURCC ('Y', 'U', 'Y', '2') +#define GST_RIFF_YUV8 GST_MAKE_FOURCC ('Y', 'U', 'V', '8') +#define GST_RIFF_WINX GST_MAKE_FOURCC ('W', 'I', 'N', 'X') +#define GST_RIFF_WPY2 GST_MAKE_FOURCC ('W', 'P', 'Y', '2') +#define GST_RIFF_m263 GST_MAKE_FOURCC ('m', '2', '6', '3') +#define GST_RIFF_M263 GST_MAKE_FOURCC ('M', '2', '6', '3') +#define GST_RIFF_H263 GST_MAKE_FOURCC ('H', '2', '6', '3') +#define GST_RIFF_h263 GST_MAKE_FOURCC ('h', '2', '6', '3') +#define GST_RIFF_i263 GST_MAKE_FOURCC ('i', '2', '6', '3') +#define GST_RIFF_L263 GST_MAKE_FOURCC ('L', '2', '6', '3') +#define GST_RIFF_x263 GST_MAKE_FOURCC ('x', '2', '6', '3') +#define GST_RIFF_VSSH GST_MAKE_FOURCC ( 'V', 'S', 'S', 'H') /* H2.64 */ + +#define GST_RIFF_Q1_0 GST_MAKE_FOURCC ('Q', '1',0x2e, '0') +#define GST_RIFF_SFMC GST_MAKE_FOURCC ('S', 'F', 'M', 'C') + +#define GST_RIFF_y41p GST_MAKE_FOURCC ('y', '4', '1', 'p') +#define GST_RIFF_Y41P GST_MAKE_FOURCC ('Y', '4', '1', 'P') +#define GST_RIFF_yv12 GST_MAKE_FOURCC ('y', 'v', '1', '2') +#define GST_RIFF_YV12 GST_MAKE_FOURCC ('Y', 'V', '1', '2') +#define GST_RIFF_vixl GST_MAKE_FOURCC ('v', 'i', 'x', 'l') +#define GST_RIFF_VIXL GST_MAKE_FOURCC ('V', 'I', 'X', 'L') +#define GST_RIFF_iyuv GST_MAKE_FOURCC ('i', 'y', 'u', 'v') +#define GST_RIFF_IYUV GST_MAKE_FOURCC ('I', 'Y', 'U', 'V') +#define GST_RIFF_i420 GST_MAKE_FOURCC ('i', '4', '2', '0') +#define GST_RIFF_I420 GST_MAKE_FOURCC ('I', '4', '2', '0') +#define GST_RIFF_vyuy GST_MAKE_FOURCC ('v', 'y', 'u', 'y') +#define GST_RIFF_VYUY GST_MAKE_FOURCC ('V', 'Y', 'U', 'Y') + +#define GST_RIFF_DIV3 GST_MAKE_FOURCC ('D', 'I', 'V', '3') + +#define GST_RIFF_rpza GST_MAKE_FOURCC ('r', 'p', 'z', 'a') +/* And this here's the mistakes that need to be supported */ +#define GST_RIFF_azpr GST_MAKE_FOURCC ('a', 'z', 'p', 'r') /* recognize Apple's rpza mangled? */ + +/*********** FND in MJPG **********/ +#define GST_RIFF_ISFT GST_MAKE_FOURCC ('I', 'S', 'F', 'T') +#define GST_RIFF_IDIT GST_MAKE_FOURCC ('I', 'D', 'I', 'T') + +#define GST_RIFF_00AM GST_MAKE_FOURCC ('0', '0', 'A', 'M') +#define GST_RIFF_DISP GST_MAKE_FOURCC ('D', 'I', 'S', 'P') +#define GST_RIFF_ISBJ GST_MAKE_FOURCC ('I', 'S', 'B', 'J') + +#define GST_RIFF_rec GST_MAKE_FOURCC ('r', 'e', 'c', ' ') + +/* common data structures */ +typedef struct _gst_riff_strh { + guint32 type; /* stream type */ + guint32 fcc_handler; /* fcc_handler */ + guint32 flags; +/* flags values */ +#define GST_RIFF_STRH_DISABLED 0x000000001 +#define GST_RIFF_STRH_VIDEOPALCHANGES 0x000010000 + guint32 priority; + guint32 init_frames; /* initial frames (???) */ + guint32 scale; + guint32 rate; + guint32 start; + guint32 length; + guint32 bufsize; /* suggested buffer size */ + guint32 quality; + guint32 samplesize; + /* rcFrame, RECT structure(struct of 4 shorts) + gint32 left; + gint32 top; + gint32 right; + gint32 bottom; + */ +} gst_riff_strh; + +typedef struct _gst_riff_strf_vids { /* == BitMapInfoHeader */ + guint32 size; + guint32 width; + guint32 height; + guint16 planes; + guint16 bit_cnt; + guint32 compression; + guint32 image_size; + guint32 xpels_meter; + guint32 ypels_meter; + guint32 num_colors; /* used colors */ + guint32 imp_colors; /* important colors */ + /* may be more for some codecs */ +} gst_riff_strf_vids; + + +typedef struct _gst_riff_strf_auds { /* == WaveHeader (?) */ + guint16 format; +/**** from public Microsoft RIFF docs ******/ +#define GST_RIFF_WAVE_FORMAT_UNKNOWN (0x0000) +#define GST_RIFF_WAVE_FORMAT_PCM (0x0001) +#define GST_RIFF_WAVE_FORMAT_ADPCM (0x0002) +#define GST_RIFF_WAVE_FORMAT_IEEE_FLOAT (0x0003) +#define GST_RIFF_WAVE_FORMAT_VSELP (0x0004) +#define GST_RIFF_WAVE_FORMAT_IBM_CVSD (0x0005) +#define GST_RIFF_WAVE_FORMAT_ALAW (0x0006) +#define GST_RIFF_WAVE_FORMAT_MULAW (0x0007) +#define GST_RIFF_WAVE_FORMAT_WMS (0x000a) /* WMS Windows Media Audio Speech */ +#define GST_RIFF_WAVE_FORMAT_OKI_ADPCM (0x0010) +#define GST_RIFF_WAVE_FORMAT_DVI_ADPCM (0x0011) +#define GST_RIFF_WAVE_FORMAT_MEDIASPACE_ADPCM (0x0012) +#define GST_RIFF_WAVE_FORMAT_SIERRA_ADPCM (0x0013) +#define GST_RIFF_WAVE_FORMAT_G723_ADPCM (0x0014) +#define GST_RIFF_WAVE_FORMAT_DIGISTD (0x0015) +#define GST_RIFF_WAVE_FORMAT_DIGIFIX (0x0016) +#define GST_RIFF_WAVE_FORMAT_DIALOGIC_OKI_ADPCM (0x0017) +#define GST_RIFF_WAVE_FORMAT_MEDIAVISION_ADPCM (0x0018) +#define GST_RIFF_WAVE_FORMAT_CU_CODEC (0x0019) +#define GST_RIFF_WAVE_FORMAT_YAMAHA_ADPCM (0x0020) +#define GST_RIFF_WAVE_FORMAT_SONARC (0x0021) +#define GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH (0x0022) +#define GST_RIFF_WAVE_FORMAT_ECHOSC1 (0x0023) +#define GST_RIFF_WAVE_FORMAT_AUDIOFILE_AF36 (0x0024) +#define GST_RIFF_WAVE_FORMAT_APTX (0x0025) +#define GST_RIFF_WAVE_FORMAT_AUDIOFILE_AF10 (0x0026) +#define GST_RIFF_WAVE_FORMAT_PROSODY_1612 (0x0027) +#define GST_RIFF_WAVE_FORMAT_LRC (0x0028) +#define GST_RIFF_WAVE_FORMAT_DOLBY_AC2 (0x0030) +#define GST_RIFF_WAVE_FORMAT_GSM610 (0x0031) +#define GST_RIFF_WAVE_FORMAT_MSN (0x0032) +#define GST_RIFF_WAVE_FORMAT_ANTEX_ADPCME (0x0033 +#define GST_RIFF_WAVE_FORMAT_CONTROL_RES_VQLPC (0x0034) +#define GST_RIFF_WAVE_FORMAT_DIGIREAL (0x0035) +#define GST_RIFF_WAVE_FORMAT_DIGIADPCM (0x0036) +#define GST_RIFF_WAVE_FORMAT_CONTROL_RES_CR10 (0x0037) +#define GST_RIFF_WAVE_FORMAT_NMS_VBXADPCM (0x0038) +#define GST_RIFF_WAVE_FORMAT_CS_IMAADPCM (0x0039) +#define GST_RIFF_WAVE_FORMAT_ECHOSC3 (0x003A) +#define GST_RIFF_WAVE_FORMAT_ROCKWELL_ADPCM (0x003B) +#define GST_RIFF_WAVE_FORMAT_ROCKWELL_DIGITALK (0x003C) +#define GST_RIFF_WAVE_FORMAT_XEBEC (0x003D) +#define GST_RIFF_WAVE_FORMAT_ITU_G721_ADPCM (0x0040) +#define GST_RIFF_WAVE_FORMAT_G728_CELP (0x0041) +#define GST_RIFF_WAVE_FORMAT_MSG723 (0x0042) +#define GST_RIFF_WAVE_FORMAT_MPEGL12 (0x0050) +#define GST_RIFF_WAVE_FORMAT_RT24 (0x0052) +#define GST_RIFF_WAVE_FORMAT_PAC (0x0053) +#define GST_RIFF_WAVE_FORMAT_MPEGL3 (0x0055) +#define GST_RIFF_WAVE_FORMAT_AMR_NB (0x0057) +#define GST_RIFF_WAVE_FORMAT_AMR_WB (0x0058) +#define GST_RIFF_WAVE_FORMAT_LUCENT_G723 (0x0059) +#define GST_RIFF_WAVE_FORMAT_CIRRUS (0x0060) +#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4 (0x0061) /* not official */ +#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3 (0x0062) /* not official */ +/* FIXME: where are these from? are they used at all? */ +#if 0 +#define GST_RIFF_WAVE_FORMAT_ESPCM (0x0061) +#define GST_RIFF_WAVE_FORMAT_VOXWARE (0x0062) +#endif +#define GST_RIFF_WAVE_FORMAT_CANOPUS_ATRAC (0x0063) +#define GST_RIFF_WAVE_FORMAT_G726_ADPCM (0x0064) +#define GST_RIFF_WAVE_FORMAT_G722_ADPCM (0x0065) +#define GST_RIFF_WAVE_FORMAT_DSAT_DISPLAY (0x0067) +#define GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV (0x0069) +/* FIXME: where are these from? are they used at all? */ +#if 0 +#define GST_RIFF_WAVE_FORMAT_VOXWARE_BYTE_ALIGNED (0x0069) +#endif +#define GST_RIFF_WAVE_FORMAT_VOXWARE_AC8 (0x0070) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_AC10 (0x0071) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_AC16 (0x0072) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_AC20 (0x0073) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_METAVOICE (0x0074) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_METASOUND (0x0075) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_RT29HW (0x0076) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_VR12 (0x0077) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_VR18 (0x0078) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_TQ40 (0x0079) +#define GST_RIFF_WAVE_FORMAT_SOFTSOUND (0x0080) +#define GST_RIFF_WAVE_FORMAT_VOXWARE_TQ60 (0x0081) +#define GST_RIFF_WAVE_FORMAT_MSRT24 (0x0082) +#define GST_RIFF_WAVE_FORMAT_G729A (0x0083) +#define GST_RIFF_WAVE_FORMAT_MVI_MVI2 (0x0084) +#define GST_RIFF_WAVE_FORMAT_DF_G726 (0x0085) +#define GST_RIFF_WAVE_FORMAT_DF_GSM610 (0x0086) +#define GST_RIFF_WAVE_FORMAT_ISIAUDIO (0x0088) +#define GST_RIFF_WAVE_FORMAT_ONLIVE (0x0089) +#define GST_RIFF_WAVE_FORMAT_SBC24 (0x0091) +#define GST_RIFF_WAVE_FORMAT_DOLBY_AC3_SPDIF (0x0092) +#define GST_RIFF_WAVE_FORMAT_MEDIASONIC_G723 (0x0093) +#define GST_RIFF_WAVE_FORMAT_PROSODY_8KBPS (0x0094) +#define GST_RIFF_WAVE_FORMAT_ZYXEL_ADPCM (0x0097) +#define GST_RIFF_WAVE_FORMAT_PHILIPS_LPCBB (0x0098) +#define GST_RIFF_WAVE_FORMAT_PACKED (0x0099) +#define GST_RIFF_WAVE_FORMAT_MALDEN_PHONYTALK (0x00A0) +#define GST_RIFF_WAVE_FORMAT_AAC (0x00ff) +#define GST_RIFF_WAVE_FORMAT_RHETOREX_ADPCM (0x0100) +#define GST_RIFF_IBM_FORMAT_MULAW (0x0101) +#define GST_RIFF_IBM_FORMAT_ALAW (0x0102) +#define GST_RIFF_IBM_FORMAT_ADPCM (0x0103) +#define GST_RIFF_WAVE_FORMAT_VIVO_G723 (0x0111) +#define GST_RIFF_WAVE_FORMAT_VIVO_SIREN (0x0112) +#define GST_RIFF_WAVE_FORMAT_DIGITAL_G723 (0x0123) +#define GST_RIFF_WAVE_FORMAT_SANYO_LD_ADPCM (0x0125) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_ACEPLNET (0x0130) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_ACELP4800 (0x0131) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_ACELP8V3 (0x0132) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_G729 (0x0133) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_G729A (0x0134) +#define GST_RIFF_WAVE_FORMAT_SIPROLAB_KELVIN (0x0135) +#define GST_RIFF_WAVE_FORMAT_G726ADPCM (0x0140) +#define GST_RIFF_WAVE_FORMAT_QUALCOMM_PUREVOICE (0x0150) +#define GST_RIFF_WAVE_FORMAT_QUALCOMM_HALFRATE (0x0151) +#define GST_RIFF_WAVE_FORMAT_TUBGSM (0x0155) +#define GST_RIFF_WAVE_FORMAT_WMAV1 (0x0160) +#define GST_RIFF_WAVE_FORMAT_WMAV2 (0x0161) +#define GST_RIFF_WAVE_FORMAT_WMAV3 (0x0162) +#define GST_RIFF_WAVE_FORMAT_WMAV3_L (0x0163) +#define GST_RIFF_WAVE_FORMAT_CREATIVE_ADPCM (0x0200) +#define GST_RIFF_WAVE_FORMAT_CREATIVE_FASTSPEECH8 (0x0202) +#define GST_RIFF_WAVE_FORMAT_CREATIVE_FASTSPEECH10 (0x0203) +#define GST_RIFF_WAVE_FORMAT_UHER_ADPCM (0x0210) +#define GST_RIFF_WAVE_FORMAT_QUARTERDECK (0x0220) +#define GST_RIFF_WAVE_FORMAT_ILINK_VC (0x0230) +#define GST_RIFF_WAVE_FORMAT_RAW_SPORT (0x0240) +#define GST_RIFF_WAVE_FORMAT_IPI_HSX (0x0250) +#define GST_RIFF_WAVE_FORMAT_IPI_RPELP (0x0251) +#define GST_RIFF_WAVE_FORMAT_CS2 (0x0260) +#define GST_RIFF_WAVE_FORMAT_SONY_ATRAC3 (0x0270) +#define GST_RIFF_WAVE_FORMAT_SIREN (0x028E) +#define GST_RIFF_WAVE_FORMAT_FM_TOWNS_SND (0x0300) +#define GST_RIFF_WAVE_FORMAT_BTV_DIGITAL (0x0400) +#define GST_RIFF_WAVE_FORMAT_IMC (0x0401) +#define GST_RIFF_WAVE_FORMAT_QDESIGN_MUSIC (0x0450) +#define GST_RIFF_WAVE_FORMAT_VME_VMPCM (0x0680) +#define GST_RIFF_WAVE_FORMAT_TPC (0x0681) +#define GST_RIFF_WAVE_FORMAT_OLIGSM (0x1000) +#define GST_RIFF_WAVE_FORMAT_OLIADPCM (0x1001) +#define GST_RIFF_WAVE_FORMAT_OLICELP (0x1002) +#define GST_RIFF_WAVE_FORMAT_OLISBC (0x1003) +#define GST_RIFF_WAVE_FORMAT_OLIOPR (0x1004) +#define GST_RIFF_WAVE_FORMAT_LH_CODEC (0x1100) +#define GST_RIFF_WAVE_FORMAT_NORRIS (0x1400) +#define GST_RIFF_WAVE_FORMAT_SOUNDSPACE_MUSICOMPRESS (0x1500) +#define GST_RIFF_WAVE_FORMAT_A52 (0x2000) +#define GST_RIFF_WAVE_FORMAT_DTS (0x2001) +#define GST_RIFF_WAVE_FORMAT_SONIC (0x2048) +#define GST_RIFF_WAVE_FORMAT_SONIC_LS (0x2048) +#define GST_RIFF_WAVE_FORMAT_AAC_AC (0x4143) +#define GST_RIFF_WAVE_FORMAT_VORBIS1 (0x674f) +#define GST_RIFF_WAVE_FORMAT_VORBIS2 (0x6750) +#define GST_RIFF_WAVE_FORMAT_VORBIS3 (0x6751) +#define GST_RIFF_WAVE_FORMAT_VORBIS1PLUS (0x676f) +#define GST_RIFF_WAVE_FORMAT_VORBIS2PLUS (0x6770) +#define GST_RIFF_WAVE_FORMAT_VORBIS3PLUS (0x6771) +#define GST_RIFF_WAVE_FORMAT_AAC_pm (0x706d) +#define GST_RIFF_WAVE_FORMAT_GSM_AMR_CBR (0x7A21) +#define GST_RIFF_WAVE_FORMAT_GSM_AMR_VBR (0x7A22) +#define GST_RIFF_WAVE_FORMAT_FLAC (0xF1AC) +#define GST_RIFF_WAVE_FORMAT_EXTENSIBLE (0xFFFE) + guint16 channels; + guint32 rate; + guint32 av_bps; + guint16 blockalign; +#if 0 + /* missing field: */ + guint16 bits_per_sample; +#endif + guint16 size; +} gst_riff_strf_auds; + +typedef struct _gst_riff_strf_iavs { + guint32 DVAAuxSrc; + guint32 DVAAuxCtl; + guint32 DVAAuxSrc1; + guint32 DVAAuxCtl1; + guint32 DVVAuxSrc; + guint32 DVVAuxCtl; + guint32 DVReserved1; + guint32 DVReserved2; +} gst_riff_strf_iavs; + +typedef struct _gst_riff_index_entry { + guint32 id; + guint32 flags; +#define GST_RIFF_IF_LIST (0x00000001L) +#define GST_RIFF_IF_KEYFRAME (0x00000010L) +#define GST_RIFF_IF_NO_TIME (0x00000100L) +#define GST_RIFF_IF_COMPUSE (0x0FFF0000L) + guint32 offset; + guint32 size; +} gst_riff_index_entry; + +typedef struct _gst_riff_dmlh { + guint32 totalframes; +} gst_riff_dmlh; + +/* taken from libsndfile/wav.c (LGPL) */ +typedef struct _gst_riff_acid { + /* 4 bytes (int) type of file: + * this appears to be a bit mask,however some combinations + * are probably impossible and/or qualified as "errors" + * + * 0x01 On: One Shot Off: Loop + * 0x02 On: Root note is Set Off: No root + * 0x04 On: Stretch is On, Off: Strech is OFF + * 0x08 On: Disk Based Off: Ram based + * 0x10 On: ?????????? Off: ????????? (Acidizer puts that ON) + */ + guint32 loop_type; + /* 2 bytes (short) root note + * if type 0x10 is OFF : [C,C#,(...),B] -> [0x30 to 0x3B] + * if type 0x10 is ON : [C,C#,(...),B] -> [0x3C to 0x47] + * (both types fit on same MIDI pitch albeit different octaves, so who cares) + */ + guint16 root_note; + /* 2 bytes (short) ??? always set to 0x8000 + * 4 bytes (float) ??? seems to be always 0 + */ + guint16 unknown1; + gfloat unknown2; + /* 4 bytes (int) number of beats + * 2 bytes (short) meter denominator //always 4 in SF/ACID + * 2 bytes (short) meter numerator //always 4 in SF/ACID + * //are we sure about the order?? usually its num/denom + * 4 bytes (float) tempo + */ + guint32 number_of_beats; + guint16 meter_d, meter_n; + gfloat tempo; +} gst_riff_acid; + +G_END_DECLS + +#endif /* __GST_RIFF_IDS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.c new file mode 100644 index 0000000..40b2bf6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.c @@ -0,0 +1,1911 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff-media.h: RIFF-id to/from caps routines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "riff-ids.h" +#include "riff-media.h" + +#include + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (riff_debug); +#define GST_CAT_DEFAULT riff_debug + +/** + * gst_riff_create_video_caps: + * @codec_fcc: fourCC codec for this codec. + * @strh: pointer to the strh stream header structure. + * @strf: pointer to the strf stream header structure, including any + * data that is within the range of strf.size, but excluding any + * additional data withint this chunk but outside strf.size. + * @strf_data: a #GstBuffer containing the additional data in the strf + * chunk outside reach of strf.size. Ususally a palette. + * @strd_data: a #GstBuffer containing the data in the strd stream header + * chunk. Usually codec initialization data. + * @codec_name: if given, will be filled with a human-readable codec name. + */ + +GstCaps * +gst_riff_create_video_caps (guint32 codec_fcc, + gst_riff_strh * strh, gst_riff_strf_vids * strf, + GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name) +{ + GstCaps *caps = NULL; + GstBuffer *palette = NULL; + + GST_DEBUG ("video fourcc %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (codec_fcc)); + + switch (codec_fcc) { + case GST_MAKE_FOURCC ('D', 'I', 'B', ' '): /* uncompressed RGB */ + case GST_MAKE_FOURCC (0x00, 0x00, 0x00, 0x00): + case GST_MAKE_FOURCC ('R', 'G', 'B', ' '): + case GST_MAKE_FOURCC ('R', 'A', 'W', ' '): + { + gint bpp = (strf && strf->bit_cnt != 0) ? strf->bit_cnt : 8; + + if (strf) { + if (bpp == 8) { + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, 8, "depth", G_TYPE_INT, 8, + "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL); + } else if (bpp == 24) { + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "red_mask", G_TYPE_INT, 0xff, "green_mask", G_TYPE_INT, 0xff00, + "blue_mask", G_TYPE_INT, 0xff0000, NULL); + } else if (bpp == 32) { + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, 32, "depth", G_TYPE_INT, 24, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "red_mask", G_TYPE_INT, 0xff00, "green_mask", G_TYPE_INT, + 0xff0000, "blue_mask", G_TYPE_INT, 0xff000000, NULL); + } else { + GST_WARNING ("Unhandled DIB RGB depth: %d", bpp); + return NULL; + } + } else { + /* for template */ + caps = + gst_caps_from_string ("video/x-raw-rgb, bpp = (int) { 8, 24, 32 }, " + "depth = (int) { 8, 24}"); + } + + palette = strf_data; + strf_data = NULL; + if (codec_name) { + if (bpp == 8) + *codec_name = g_strdup_printf ("Palettized %d-bit RGB", bpp); + else + *codec_name = g_strdup_printf ("%d-bit RGB", bpp); + } + break; + } + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, codec_fcc, NULL); + if (codec_name) + *codec_name = g_strdup ("Uncompressed planar YUV 4:2:0"); + break; + + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + case GST_MAKE_FOURCC ('Y', 'U', 'N', 'V'): + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), + NULL); + if (codec_name) + *codec_name = g_strdup ("Uncompressed packed YUV 4:2:2"); + break; + + case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'): + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, codec_fcc, NULL); + if (codec_name) + *codec_name = g_strdup ("Uncompressed packed YVU 4:1:0"); + break; + + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'): + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), + NULL); + if (codec_name) + *codec_name = g_strdup ("Uncompressed packed YUV 4:2:2"); + break; + + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, codec_fcc, NULL); + if (codec_name) + *codec_name = g_strdup ("Uncompressed packed YVU 4:2:2"); + break; + + case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'): /* YUY2 MJPEG */ + case GST_MAKE_FOURCC ('A', 'V', 'R', 'n'): + case GST_MAKE_FOURCC ('I', 'J', 'P', 'G'): + case GST_MAKE_FOURCC ('i', 'j', 'p', 'g'): + case GST_MAKE_FOURCC ('d', 'm', 'b', '1'): + case GST_MAKE_FOURCC ('A', 'C', 'D', 'V'): + case GST_MAKE_FOURCC ('Q', 'I', 'V', 'G'): + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("Motion JPEG"); + break; + + case GST_MAKE_FOURCC ('J', 'P', 'E', 'G'): /* generic (mostly RGB) MJPEG */ + case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'): /* generic (mostly RGB) MJPEG */ + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("JPEG Still Image"); + break; + + case GST_MAKE_FOURCC ('P', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */ + case GST_MAKE_FOURCC ('V', 'I', 'X', 'L'): /* Miro/Pinnacle fourccs */ + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("Miro/Pinnacle Motion JPEG"); + break; + + case GST_MAKE_FOURCC ('C', 'J', 'P', 'G'): + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("Creative Webcam JPEG"); + break; + + case GST_MAKE_FOURCC ('S', 'L', 'M', 'J'): + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("SL Motion JPEG"); + break; + + case GST_MAKE_FOURCC ('J', 'P', 'G', 'L'): + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (codec_name) + *codec_name = g_strdup ("Pegasus Lossless JPEG"); + break; + + case GST_MAKE_FOURCC ('L', 'O', 'C', 'O'): + caps = gst_caps_new_simple ("video/x-loco", NULL); + if (codec_name) + *codec_name = g_strdup ("LOCO Lossless"); + break; + + case GST_MAKE_FOURCC ('S', 'P', '5', '3'): + case GST_MAKE_FOURCC ('S', 'P', '5', '4'): + case GST_MAKE_FOURCC ('S', 'P', '5', '5'): + case GST_MAKE_FOURCC ('S', 'P', '5', '6'): + case GST_MAKE_FOURCC ('S', 'P', '5', '7'): + case GST_MAKE_FOURCC ('S', 'P', '5', '8'): + caps = gst_caps_new_simple ("video/sp5x", NULL); + if (codec_name) + *codec_name = g_strdup ("Sp5x-like JPEG"); + break; + + case GST_MAKE_FOURCC ('Z', 'M', 'B', 'V'): + caps = gst_caps_new_simple ("video/x-zmbv", NULL); + if (codec_name) + *codec_name = g_strdup ("Zip Motion Block video"); + break; + + case GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'): + caps = gst_caps_new_simple ("video/x-huffyuv", NULL); + if (strf) { + gst_caps_set_simple (caps, "bpp", + G_TYPE_INT, (int) strf->bit_cnt, NULL); + } + if (codec_name) + *codec_name = g_strdup ("Huffman Lossless Codec"); + break; + + case GST_MAKE_FOURCC ('M', 'P', 'E', 'G'): + case GST_MAKE_FOURCC ('M', 'P', 'G', 'I'): + case GST_MAKE_FOURCC ('m', 'p', 'g', '1'): + case GST_MAKE_FOURCC ('M', 'P', 'G', '1'): + case GST_MAKE_FOURCC ('P', 'I', 'M', '1'): + case GST_MAKE_FOURCC (0x01, 0x00, 0x00, 0x10): + caps = gst_caps_new_simple ("video/mpeg", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-1 video"); + break; + + case GST_MAKE_FOURCC ('M', 'P', 'G', '2'): + case GST_MAKE_FOURCC ('m', 'p', 'g', '2'): + case GST_MAKE_FOURCC ('P', 'I', 'M', '2'): + case GST_MAKE_FOURCC ('D', 'V', 'R', ' '): + case GST_MAKE_FOURCC (0x02, 0x00, 0x00, 0x10): + caps = gst_caps_new_simple ("video/mpeg", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-2 video"); + break; + + case GST_MAKE_FOURCC ('L', 'M', 'P', '2'): + caps = gst_caps_new_simple ("video/mpeg", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("Lead MPEG-2 video"); + break; + + case GST_MAKE_FOURCC ('H', '2', '6', '3'): + case GST_MAKE_FOURCC ('h', '2', '6', '3'): + case GST_MAKE_FOURCC ('i', '2', '6', '3'): + case GST_MAKE_FOURCC ('U', '2', '6', '3'): + case GST_MAKE_FOURCC ('v', 'i', 'v', '1'): + case GST_MAKE_FOURCC ('T', '2', '6', '3'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "itu", NULL); + if (codec_name) + *codec_name = g_strdup ("ITU H.26n"); + break; + + case GST_MAKE_FOURCC ('L', '2', '6', '3'): + /* http://www.leadcodecs.com/Codecs/LEAD-H263.htm */ + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "lead", NULL); + if (codec_name) + *codec_name = g_strdup ("Lead H.263"); + break; + + case GST_MAKE_FOURCC ('M', '2', '6', '3'): + case GST_MAKE_FOURCC ('m', '2', '6', '3'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "microsoft", NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft H.263"); + break; + + case GST_MAKE_FOURCC ('V', 'D', 'O', 'W'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "vdolive", NULL); + if (codec_name) + *codec_name = g_strdup ("VDOLive"); + break; + + case GST_MAKE_FOURCC ('V', 'I', 'V', 'O'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "vivo", NULL); + if (codec_name) + *codec_name = g_strdup ("Vivo H.263"); + break; + + case GST_MAKE_FOURCC ('x', '2', '6', '3'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "xirlink", NULL); + if (codec_name) + *codec_name = g_strdup ("Xirlink H.263"); + break; + + /* apparently not standard H.263...? */ + case GST_MAKE_FOURCC ('I', '2', '6', '3'): + caps = gst_caps_new_simple ("video/x-intel-h263", + "variant", G_TYPE_STRING, "intel", NULL); + if (codec_name) + *codec_name = g_strdup ("Intel H.263"); + break; + + case GST_MAKE_FOURCC ('V', 'X', '1', 'K'): + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "lucent", NULL); + if (codec_name) + *codec_name = g_strdup ("Lucent VX1000S H.263"); + break; + + case GST_MAKE_FOURCC ('X', '2', '6', '4'): + case GST_MAKE_FOURCC ('x', '2', '6', '4'): + case GST_MAKE_FOURCC ('H', '2', '6', '4'): + case GST_MAKE_FOURCC ('h', '2', '6', '4'): + case GST_MAKE_FOURCC ('a', 'v', 'c', '1'): + case GST_MAKE_FOURCC ('A', 'V', 'C', '1'): + caps = gst_caps_new_simple ("video/x-h264", + "variant", G_TYPE_STRING, "itu", NULL); + if (codec_name) + *codec_name = g_strdup ("ITU H.264"); + break; + + case GST_MAKE_FOURCC ('V', 'S', 'S', 'H'): + caps = gst_caps_new_simple ("video/x-h264", + "variant", G_TYPE_STRING, "videosoft", NULL); + if (codec_name) + *codec_name = g_strdup ("VideoSoft H.264"); + break; + + case GST_MAKE_FOURCC ('L', '2', '6', '4'): + /* http://www.leadcodecs.com/Codecs/LEAD-H264.htm */ + caps = gst_caps_new_simple ("video/x-h264", + "variant", G_TYPE_STRING, "lead", NULL); + if (codec_name) + *codec_name = g_strdup ("Lead H.264"); + break; + + case GST_MAKE_FOURCC ('S', 'E', 'D', 'G'): + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Samsung MPEG-4"); + break; + + case GST_MAKE_FOURCC ('M', '4', 'C', 'C'): + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Divio MPEG-4"); + break; + + case GST_MAKE_FOURCC ('D', 'I', 'V', '3'): + case GST_MAKE_FOURCC ('d', 'i', 'v', '3'): + case GST_MAKE_FOURCC ('D', 'V', 'X', '3'): + case GST_MAKE_FOURCC ('d', 'v', 'x', '3'): + case GST_MAKE_FOURCC ('D', 'I', 'V', '4'): + case GST_MAKE_FOURCC ('d', 'i', 'v', '4'): + case GST_MAKE_FOURCC ('D', 'I', 'V', '5'): + case GST_MAKE_FOURCC ('d', 'i', 'v', '5'): + case GST_MAKE_FOURCC ('D', 'I', 'V', '6'): + case GST_MAKE_FOURCC ('d', 'i', 'v', '6'): + case GST_MAKE_FOURCC ('M', 'P', 'G', '3'): + case GST_MAKE_FOURCC ('m', 'p', 'g', '3'): + case GST_MAKE_FOURCC ('c', 'o', 'l', '0'): + case GST_MAKE_FOURCC ('C', 'O', 'L', '0'): + case GST_MAKE_FOURCC ('c', 'o', 'l', '1'): + case GST_MAKE_FOURCC ('C', 'O', 'L', '1'): + case GST_MAKE_FOURCC ('A', 'P', '4', '1'): + caps = gst_caps_new_simple ("video/x-divx", + "divxversion", G_TYPE_INT, 3, NULL); + if (codec_name) + *codec_name = g_strdup ("DivX MS-MPEG-4 Version 3"); + break; + + case GST_MAKE_FOURCC ('d', 'i', 'v', 'x'): + case GST_MAKE_FOURCC ('D', 'I', 'V', 'X'): + caps = gst_caps_new_simple ("video/x-divx", + "divxversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("DivX MPEG-4 Version 4"); + break; + + case GST_MAKE_FOURCC ('B', 'L', 'Z', '0'): + caps = gst_caps_new_simple ("video/x-divx", + "divxversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Blizzard DivX"); + break; + + case GST_MAKE_FOURCC ('D', 'X', '5', '0'): + caps = gst_caps_new_simple ("video/x-divx", + "divxversion", G_TYPE_INT, 5, NULL); + if (codec_name) + *codec_name = g_strdup ("DivX MPEG-4 Version 5"); + break; + + case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'): + case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'): + caps = gst_caps_new_simple ("video/x-xvid", NULL); + if (codec_name) + *codec_name = g_strdup ("XVID MPEG-4"); + break; + + case GST_MAKE_FOURCC ('R', 'M', 'P', '4'): + caps = gst_caps_new_simple ("video/x-xvid", NULL); + if (codec_name) + *codec_name = g_strdup ("Sigma-Designs MPEG-4"); + break; + + case GST_MAKE_FOURCC ('M', 'P', 'G', '4'): + case GST_MAKE_FOURCC ('M', 'P', '4', '1'): + case GST_MAKE_FOURCC ('m', 'p', '4', '1'): + caps = gst_caps_new_simple ("video/x-msmpeg", + "msmpegversion", G_TYPE_INT, 41, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft MPEG-4 4.1"); + break; + + case GST_MAKE_FOURCC ('m', 'p', '4', '2'): + case GST_MAKE_FOURCC ('M', 'P', '4', '2'): + caps = gst_caps_new_simple ("video/x-msmpeg", + "msmpegversion", G_TYPE_INT, 42, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft MPEG-4 4.2"); + break; + + case GST_MAKE_FOURCC ('m', 'p', '4', '3'): + case GST_MAKE_FOURCC ('M', 'P', '4', '3'): + caps = gst_caps_new_simple ("video/x-msmpeg", + "msmpegversion", G_TYPE_INT, 43, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft MPEG-4 4.3"); + break; + + case GST_MAKE_FOURCC ('M', 'P', '4', 'S'): + case GST_MAKE_FOURCC ('M', '4', 'S', '2'): + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft ISO MPEG-4 1.1"); + break; + + case GST_MAKE_FOURCC ('F', 'M', 'P', '4'): + case GST_MAKE_FOURCC ('U', 'M', 'P', '4'): + case GST_MAKE_FOURCC ('F', 'F', 'D', 'S'): + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("FFmpeg MPEG-4"); + break; + + case GST_MAKE_FOURCC ('E', 'M', '4', 'A'): + case GST_MAKE_FOURCC ('E', 'P', 'V', 'H'): + case GST_MAKE_FOURCC ('F', 'V', 'F', 'W'): + case GST_MAKE_FOURCC ('I', 'N', 'M', 'C'): + case GST_MAKE_FOURCC ('D', 'I', 'G', 'I'): + case GST_MAKE_FOURCC ('D', 'M', '2', 'K'): + case GST_MAKE_FOURCC ('D', 'C', 'O', 'D'): + case GST_MAKE_FOURCC ('M', 'V', 'X', 'M'): + case GST_MAKE_FOURCC ('P', 'M', '4', 'V'): + case GST_MAKE_FOURCC ('S', 'M', 'P', '4'): + case GST_MAKE_FOURCC ('D', 'X', 'G', 'M'): + case GST_MAKE_FOURCC ('V', 'I', 'D', 'M'): + case GST_MAKE_FOURCC ('M', '4', 'T', '3'): + case GST_MAKE_FOURCC ('G', 'E', 'O', 'X'): + case GST_MAKE_FOURCC ('M', 'P', '4', 'V'): + case GST_MAKE_FOURCC ('m', 'p', '4', 'v'): + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-4"); + break; + + case GST_MAKE_FOURCC ('3', 'i', 'v', 'd'): + case GST_MAKE_FOURCC ('3', 'I', 'V', 'D'): + caps = gst_caps_new_simple ("video/x-msmpeg", + "msmpegversion", G_TYPE_INT, 43, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft MPEG-4 4.3"); /* FIXME? */ + break; + + case GST_MAKE_FOURCC ('3', 'I', 'V', '1'): + case GST_MAKE_FOURCC ('3', 'I', 'V', '2'): + caps = gst_caps_new_simple ("video/x-3ivx", NULL); + if (codec_name) + *codec_name = g_strdup ("3ivx"); + break; + + case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'): + case GST_MAKE_FOURCC ('d', 'v', 's', 'd'): + case GST_MAKE_FOURCC ('d', 'v', 'c', ' '): + case GST_MAKE_FOURCC ('d', 'v', '2', '5'): + caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "dvversion", G_TYPE_INT, 25, NULL); + if (codec_name) + *codec_name = g_strdup ("Generic DV"); + break; + + case GST_MAKE_FOURCC ('C', 'D', 'V', 'C'): + case GST_MAKE_FOURCC ('c', 'd', 'v', 'c'): + caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "dvversion", G_TYPE_INT, 25, NULL); + if (codec_name) + *codec_name = g_strdup ("Canopus DV"); + break; + + case GST_MAKE_FOURCC ('D', 'V', '5', '0'): + case GST_MAKE_FOURCC ('d', 'v', '5', '0'): + caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "dvversion", G_TYPE_INT, 50, NULL); + if (codec_name) + *codec_name = g_strdup ("DVCPro50 Video"); + break; + + case GST_MAKE_FOURCC ('W', 'M', 'V', '1'): + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft Windows Media 7"); + break; + + case GST_MAKE_FOURCC ('W', 'M', 'V', '2'): + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft Windows Media 8"); + break; + + case GST_MAKE_FOURCC ('W', 'M', 'V', '3'): + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 3, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft Windows Media 9"); + break; + + case GST_MAKE_FOURCC ('W', 'M', 'V', 'A'): + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC, + codec_fcc, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft Windows Media Advanced Profile"); + break; + + case GST_MAKE_FOURCC ('W', 'V', 'C', '1'): + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 3, "format", GST_TYPE_FOURCC, + codec_fcc, NULL); + if (codec_name) + *codec_name = g_strdup ("Microsoft Windows Media VC-1"); + break; + + case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'): + caps = gst_caps_new_simple ("video/x-cinepak", NULL); + if (codec_name) + *codec_name = g_strdup ("Cinepak video"); + break; + + case GST_MAKE_FOURCC ('M', 'S', 'V', 'C'): + case GST_MAKE_FOURCC ('m', 's', 'v', 'c'): + case GST_MAKE_FOURCC ('C', 'R', 'A', 'M'): + case GST_MAKE_FOURCC ('c', 'r', 'a', 'm'): + case GST_MAKE_FOURCC ('W', 'H', 'A', 'M'): + case GST_MAKE_FOURCC ('w', 'h', 'a', 'm'): + caps = gst_caps_new_simple ("video/x-msvideocodec", + "msvideoversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("MS video v1"); + palette = strf_data; + strf_data = NULL; + break; + + case GST_MAKE_FOURCC ('R', 'L', 'E', ' '): + case GST_MAKE_FOURCC ('m', 'r', 'l', 'e'): + case GST_MAKE_FOURCC (0x1, 0x0, 0x0, 0x0): /* why, why, why? */ + case GST_MAKE_FOURCC (0x2, 0x0, 0x0, 0x0): /* why, why, why? */ + caps = gst_caps_new_simple ("video/x-rle", + "layout", G_TYPE_STRING, "microsoft", NULL); + palette = strf_data; + strf_data = NULL; + if (strf) { + gst_caps_set_simple (caps, + "depth", G_TYPE_INT, (gint) strf->bit_cnt, NULL); + } else { + gst_caps_set_simple (caps, "depth", GST_TYPE_INT_RANGE, 1, 64, NULL); + } + if (codec_name) + *codec_name = g_strdup ("Microsoft RLE"); + break; + + case GST_MAKE_FOURCC ('A', 'A', 'S', 'C'): + caps = gst_caps_new_simple ("video/x-aasc", NULL); + if (codec_name) + *codec_name = g_strdup ("Autodesk Animator"); + break; + + case GST_MAKE_FOURCC ('X', 'x', 'a', 'n'): + caps = gst_caps_new_simple ("video/x-xan", + "wcversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Xan Wing Commander 4"); + break; + + case GST_MAKE_FOURCC ('R', 'T', '2', '1'): + caps = gst_caps_new_simple ("video/x-indeo", + "indeoversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("Intel Video 2"); + break; + + case GST_MAKE_FOURCC ('I', 'V', '3', '1'): + case GST_MAKE_FOURCC ('I', 'V', '3', '2'): + case GST_MAKE_FOURCC ('i', 'v', '3', '1'): + case GST_MAKE_FOURCC ('i', 'v', '3', '2'): + caps = gst_caps_new_simple ("video/x-indeo", + "indeoversion", G_TYPE_INT, 3, NULL); + if (codec_name) + *codec_name = g_strdup ("Intel Video 3"); + break; + + case GST_MAKE_FOURCC ('I', 'V', '4', '1'): + case GST_MAKE_FOURCC ('i', 'v', '4', '1'): + caps = gst_caps_new_simple ("video/x-indeo", + "indeoversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("Intel Video 4"); + break; + + case GST_MAKE_FOURCC ('I', 'V', '5', '0'): + caps = gst_caps_new_simple ("video/x-indeo", + "indeoversion", G_TYPE_INT, 5, NULL); + if (codec_name) + *codec_name = g_strdup ("Intel Video 5"); + break; + + case GST_MAKE_FOURCC ('M', 'S', 'Z', 'H'): + caps = gst_caps_new_simple ("video/x-mszh", NULL); + if (codec_name) + *codec_name = g_strdup ("Lossless MSZH Video"); + break; + + case GST_MAKE_FOURCC ('Z', 'L', 'I', 'B'): + caps = gst_caps_new_simple ("video/x-zlib", NULL); + if (codec_name) + *codec_name = g_strdup ("Lossless zlib video"); + break; + + case GST_MAKE_FOURCC ('C', 'L', 'J', 'R'): + case GST_MAKE_FOURCC ('c', 'l', 'j', 'r'): + caps = gst_caps_new_simple ("video/x-cirrus-logic-accupak", NULL); + if (codec_name) + *codec_name = g_strdup ("Cirrus Logipak AccuPak"); + break; + + case GST_MAKE_FOURCC ('C', 'Y', 'U', 'V'): + case GST_MAKE_FOURCC ('c', 'y', 'u', 'v'): + caps = gst_caps_new_simple ("video/x-compressed-yuv", NULL); + if (codec_name) + *codec_name = g_strdup ("CYUV Lossless"); + break; + + case GST_MAKE_FOURCC ('D', 'U', 'C', 'K'): + case GST_MAKE_FOURCC ('P', 'V', 'E', 'Z'): + caps = gst_caps_new_simple ("video/x-truemotion", + "trueversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("Duck Truemotion1"); + break; + + case GST_MAKE_FOURCC ('T', 'M', '2', '0'): + caps = gst_caps_new_simple ("video/x-truemotion", + "trueversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("TrueMotion 2.0"); + break; + + case GST_MAKE_FOURCC ('V', 'P', '3', '0'): + case GST_MAKE_FOURCC ('v', 'p', '3', '0'): + case GST_MAKE_FOURCC ('V', 'P', '3', '1'): + case GST_MAKE_FOURCC ('v', 'p', '3', '1'): + case GST_MAKE_FOURCC ('V', 'P', '3', ' '): + caps = gst_caps_new_simple ("video/x-vp3", NULL); + if (codec_name) + *codec_name = g_strdup ("VP3"); + break; + + case GST_MAKE_FOURCC ('U', 'L', 'T', 'I'): + caps = gst_caps_new_simple ("video/x-ultimotion", NULL); + if (codec_name) + *codec_name = g_strdup ("IBM UltiMotion"); + break; + + case GST_MAKE_FOURCC ('T', 'S', 'C', 'C'): + case GST_MAKE_FOURCC ('t', 's', 'c', 'c'):{ + if (strf) { + gint depth = (strf->bit_cnt != 0) ? (gint) strf->bit_cnt : 24; + + caps = gst_caps_new_simple ("video/x-camtasia", "depth", G_TYPE_INT, + depth, NULL); + } else { + /* template caps */ + caps = gst_caps_new_simple ("video/x-camtasia", NULL); + } + if (codec_name) + *codec_name = g_strdup ("TechSmith Camtasia"); + break; + } + + case GST_MAKE_FOURCC ('C', 'S', 'C', 'D'): + { + if (strf) { + gint depth = (strf->bit_cnt != 0) ? (gint) strf->bit_cnt : 24; + + caps = gst_caps_new_simple ("video/x-camstudio", "depth", G_TYPE_INT, + depth, NULL); + } else { + /* template caps */ + caps = gst_caps_new_simple ("video/x-camstudio", NULL); + } + if (codec_name) + *codec_name = g_strdup ("Camstudio"); + break; + } + + case GST_MAKE_FOURCC ('V', 'C', 'R', '1'): + caps = gst_caps_new_simple ("video/x-ati-vcr", + "vcrversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("ATI VCR 1"); + break; + + case GST_MAKE_FOURCC ('V', 'C', 'R', '2'): + caps = gst_caps_new_simple ("video/x-ati-vcr", + "vcrversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("ATI VCR 2"); + break; + + case GST_MAKE_FOURCC ('A', 'S', 'V', '1'): + caps = gst_caps_new_simple ("video/x-asus", + "asusversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("Asus Video 1"); + break; + + case GST_MAKE_FOURCC ('A', 'S', 'V', '2'): + caps = gst_caps_new_simple ("video/x-asus", + "asusversion", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("Asus Video 2"); + break; + + case GST_MAKE_FOURCC ('M', 'P', 'N', 'G'): + case GST_MAKE_FOURCC ('m', 'p', 'n', 'g'): + case GST_MAKE_FOURCC ('P', 'N', 'G', ' '): + caps = gst_caps_new_simple ("image/png", NULL); + if (codec_name) + *codec_name = g_strdup ("PNG image"); + break; + + case GST_MAKE_FOURCC ('F', 'L', 'V', '1'): + caps = gst_caps_new_simple ("video/x-flash-video", + "flvversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("Flash Video 1"); + break; + + case GST_MAKE_FOURCC ('V', 'M', 'n', 'c'): + caps = gst_caps_new_simple ("video/x-vmnc", + "version", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("VMWare NC Video"); + break; + + case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'): + caps = gst_caps_new_simple ("video/x-dirac", NULL); + if (codec_name) + *codec_name = g_strdup ("Dirac"); + break; + + case GST_RIFF_rpza: + case GST_RIFF_azpr: + case GST_MAKE_FOURCC ('R', 'P', 'Z', 'A'): + caps = gst_caps_new_simple ("video/x-apple-video", NULL); + if (codec_name) + *codec_name = g_strdup ("Apple Video (RPZA)"); + break; + + + case GST_MAKE_FOURCC ('F', 'F', 'V', '1'): + caps = gst_caps_new_simple ("video/x-ffv", + "ffvversion", G_TYPE_INT, 1, NULL); + if (codec_name) + *codec_name = g_strdup ("FFmpeg lossless video codec"); + break; + + case GST_MAKE_FOURCC ('K', 'M', 'V', 'C'): + caps = gst_caps_new_simple ("video/x-kmvc", NULL); + if (codec_name) + *codec_name = g_strdup ("Karl Morton's video codec"); + break; + + case GST_MAKE_FOURCC ('v', 'p', '5', '0'): + case GST_MAKE_FOURCC ('V', 'P', '5', '0'): + caps = gst_caps_new_simple ("video/x-vp5", NULL); + if (codec_name) + *codec_name = g_strdup ("On2 VP5"); + break; + + case GST_MAKE_FOURCC ('v', 'p', '6', '0'): + case GST_MAKE_FOURCC ('V', 'P', '6', '0'): + case GST_MAKE_FOURCC ('v', 'p', '6', '1'): + case GST_MAKE_FOURCC ('V', 'P', '6', '1'): + case GST_MAKE_FOURCC ('V', 'p', '6', '2'): + case GST_MAKE_FOURCC ('V', 'P', '6', '2'): + caps = gst_caps_new_simple ("video/x-vp6", NULL); + if (codec_name) + *codec_name = g_strdup ("On2 VP6"); + break; + + case GST_MAKE_FOURCC ('V', 'P', '6', 'F'): + case GST_MAKE_FOURCC ('v', 'p', '6', 'f'): + case GST_MAKE_FOURCC ('F', 'L', 'V', '4'): + caps = gst_caps_new_simple ("video/x-vp6-flash", NULL); + if (codec_name) + *codec_name = g_strdup ("On2 VP6"); + break; + + case GST_MAKE_FOURCC ('v', 'p', '7', '0'): + case GST_MAKE_FOURCC ('V', 'P', '7', '0'): + caps = gst_caps_new_simple ("video/x-vp7", NULL); + if (codec_name) + *codec_name = g_strdup ("On2 VP7"); + break; + + case GST_MAKE_FOURCC ('V', 'P', '8', '0'): + caps = gst_caps_new_simple ("video/x-vp8", NULL); + if (codec_name) + *codec_name = g_strdup ("On2 VP8"); + break; + + case GST_MAKE_FOURCC ('L', 'M', '2', '0'): + caps = gst_caps_new_simple ("video/x-mimic", NULL); + if (codec_name) + *codec_name = g_strdup ("Mimic webcam"); + break; + + case GST_MAKE_FOURCC ('T', 'H', 'E', 'O'): + case GST_MAKE_FOURCC ('t', 'h', 'e', 'o'): + caps = gst_caps_new_simple ("video/x-theora", NULL); + if (codec_name) + *codec_name = g_strdup ("Theora video codec"); + + break; + + case GST_MAKE_FOURCC ('F', 'P', 'S', '1'): + caps = gst_caps_new_simple ("video/x-fraps", NULL); + if (codec_name) + *codec_name = g_strdup ("Fraps video"); + + break; + + default: + GST_WARNING ("Unknown video fourcc %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (codec_fcc)); + return NULL; + } + + if (strh != NULL) { + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, + strh->rate, strh->scale, NULL); + } else { + gst_caps_set_simple (caps, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + } + + if (strf != NULL) { + gst_caps_set_simple (caps, + "width", G_TYPE_INT, strf->width, + "height", G_TYPE_INT, strf->height, NULL); + } else { + gst_caps_set_simple (caps, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + } + + /* extradata */ + if (strf_data || strd_data) { + GstBuffer *codec_data; + + codec_data = strf_data ? strf_data : strd_data; + + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL); + } + + /* palette */ + if (palette) { + GstBuffer *copy; + guint num_colors; + + if (strf != NULL) + num_colors = strf->num_colors; + else + num_colors = 256; + + if (GST_BUFFER_SIZE (palette) >= (num_colors * 4)) { + /* palette is always at least 256*4 bytes */ + copy = + gst_buffer_new_and_alloc (MAX (GST_BUFFER_SIZE (palette), 256 * 4)); + memcpy (GST_BUFFER_DATA (copy), GST_BUFFER_DATA (palette), + GST_BUFFER_SIZE (palette)); + +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + { + guint8 *data = GST_BUFFER_DATA (copy); + gint n; + + /* own endianness */ + for (n = 0; n < num_colors; n++) { + GST_WRITE_UINT32_BE (data, GST_READ_UINT32_LE (data)); + data += sizeof (guint32); + } + } +#endif + gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, copy, NULL); + gst_buffer_unref (copy); + } else { + GST_WARNING ("Palette smaller than expected: broken file"); + } + } + + return caps; +} + +static const struct +{ + const guint32 ms_mask; + const GstAudioChannelPosition gst_pos; +} layout_mapping[] = { + { + 0x00001, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, { + 0x00002, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { + 0x00004, GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}, { + 0x00008, GST_AUDIO_CHANNEL_POSITION_LFE}, { + 0x00010, GST_AUDIO_CHANNEL_POSITION_REAR_LEFT}, { + 0x00020, GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { + 0x00040, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER}, { + 0x00080, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { + 0x00100, GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}, { + 0x00200, GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT}, { + 0x00400, GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT}, { + 0x00800, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_CENTER */ + { + 0x01000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_LEFT */ + { + 0x02000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_CENTER */ + { + 0x04000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_FRONT_RIGHT */ + { + 0x08000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_LEFT */ + { + 0x10000, GST_AUDIO_CHANNEL_POSITION_INVALID}, /* TOP_BACK_CENTER */ + { + 0x20000, GST_AUDIO_CHANNEL_POSITION_INVALID} /* TOP_BACK_RIGHT */ +}; + +#define MAX_CHANNEL_POSITIONS G_N_ELEMENTS (layout_mapping) + +static gboolean +gst_riff_wavext_add_channel_layout (GstCaps * caps, guint32 layout) +{ + GstAudioChannelPosition pos[MAX_CHANNEL_POSITIONS]; + GstStructure *s; + gint num_channels, i, p; + + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (s, "channels", &num_channels)) + g_return_val_if_reached (FALSE); + + /* In theory this should be done for 1 and 2 channels too but + * apparently breaks too many things currently. + */ + if (num_channels <= 2 || num_channels > MAX_CHANNEL_POSITIONS) { + GST_DEBUG ("invalid number of channels: %d", num_channels); + return FALSE; + } + + p = 0; + for (i = 0; i < MAX_CHANNEL_POSITIONS; ++i) { + if ((layout & layout_mapping[i].ms_mask) != 0) { + if (p >= num_channels) { + GST_WARNING ("More bits set in the channel layout map than there " + "are channels! Broken file"); + return FALSE; + } + if (layout_mapping[i].gst_pos == GST_AUDIO_CHANNEL_POSITION_INVALID) { + GST_WARNING ("Unsupported channel position (mask 0x%08x) in channel " + "layout map - ignoring those channels", layout_mapping[i].ms_mask); + /* what to do? just ignore it and let downstream deal with a channel + * layout that has INVALID positions in it for now ... */ + } + pos[p] = layout_mapping[i].gst_pos; + ++p; + } + } + + if (p != num_channels) { + GST_WARNING ("Only %d bits set in the channel layout map, but there are " + "supposed to be %d channels! Broken file", p, num_channels); + return FALSE; + } + + gst_audio_set_channel_positions (s, pos); + return TRUE; +} + +static gboolean +gst_riff_wave_add_default_channel_layout (GstCaps * caps) +{ + GstAudioChannelPosition pos[8] = { GST_AUDIO_CHANNEL_POSITION_NONE, }; + GstStructure *s; + gint nchannels; + + s = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (s, "channels", &nchannels)) + g_return_val_if_reached (FALSE); + + if (nchannels > 8) { + GST_DEBUG ("invalid number of channels: %d", nchannels); + return FALSE; + } + + /* This uses the default channel mapping from ALSA which + * is used in quite a few surround test files and seems to be + * the defacto standard. The channel mapping from + * WAVE_FORMAT_EXTENSIBLE doesn't seem to be used in normal + * wav files like chan-id.wav. + * http://bugzilla.gnome.org/show_bug.cgi?id=489010 + */ + switch (nchannels) { + case 1: + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_MONO; + break; + case 8: + pos[7] = GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT; + pos[6] = GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT; + /* fall through */ + case 6: + pos[5] = GST_AUDIO_CHANNEL_POSITION_LFE; + /* fall through */ + case 5: + pos[4] = GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER; + /* fall through */ + case 4: + pos[3] = GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT; + pos[2] = GST_AUDIO_CHANNEL_POSITION_REAR_LEFT; + /* fall through */ + case 2: + pos[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + pos[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + break; + default: + return FALSE; + } + + gst_audio_set_channel_positions (s, pos); + return TRUE; +} + +static guint32 +gst_riff_wavext_get_default_channel_mask (guint nchannels) +{ + guint32 channel_mask = 0; + + /* Set the default channel mask for the given number of channels. + * http://www.microsoft.com/whdc/device/audio/multichaud.mspx + */ + switch (nchannels) { + case 11: + channel_mask |= 0x00400; + channel_mask |= 0x00200; + case 9: + channel_mask |= 0x00100; + case 8: + channel_mask |= 0x00080; + channel_mask |= 0x00040; + case 6: + channel_mask |= 0x00020; + channel_mask |= 0x00010; + case 4: + channel_mask |= 0x00008; + case 3: + channel_mask |= 0x00004; + case 2: + channel_mask |= 0x00002; + channel_mask |= 0x00001; + break; + } + + return channel_mask; +} + +GstCaps * +gst_riff_create_audio_caps (guint16 codec_id, + gst_riff_strh * strh, gst_riff_strf_auds * strf, + GstBuffer * strf_data, GstBuffer * strd_data, char **codec_name) +{ + gboolean block_align = FALSE, rate_chan = TRUE; + GstCaps *caps = NULL; + gint rate_min = 1000, rate_max = 96000; + gint channels_max = 2; + + switch (codec_id) { + case GST_RIFF_WAVE_FORMAT_PCM: /* PCM */ + rate_max = 192000; + channels_max = 8; + + if (strf != NULL) { + gint ba = strf->blockalign; + gint ch = strf->channels; + gint wd, ws; + + /* If we have an empty blockalign, we take the width contained in + * strf->size */ + if (ba != 0) + wd = ba * 8 / ch; + else + wd = strf->size; + + if (strf->size > 32) { + GST_WARNING ("invalid depth (%d) of pcm audio, overwriting.", + strf->size); + strf->size = 8 * ((wd + 7) / 8); + } + + /* in riff, the depth is stored in the size field but it just means that + * the _least_ significant bits are cleared. We can therefore just play + * the sample as if it had a depth == width */ + /* For reference, the actual depth is in strf->size */ + ws = wd; + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, ch, + "width", G_TYPE_INT, wd, + "depth", G_TYPE_INT, ws, "signed", G_TYPE_BOOLEAN, wd != 8, NULL); + + /* Add default channel layout. In theory this should be done + * for 1 and 2 channels too but apparently breaks too many + * things currently. Also we know no default layout for more than + * 8 channels. */ + if (ch > 2) { + if (ch > 8) + GST_WARNING ("don't know default layout for %d channels", ch); + else if (gst_riff_wave_add_default_channel_layout (caps)) + GST_DEBUG ("using default channel layout for %d channels", ch); + else + GST_WARNING ("failed to add channel layout"); + } + } else { + /* FIXME: this is pretty useless - we need fixed caps */ + caps = gst_caps_from_string ("audio/x-raw-int, " + "endianness = (int) LITTLE_ENDIAN, " + "signed = (boolean) { true, false }, " + "width = (int) { 8, 16, 24, 32 }, " "depth = (int) [ 1, 32 ]"); + } + if (codec_name && strf) + *codec_name = g_strdup_printf ("Uncompressed %d-bit PCM audio", + strf->size); + break; + + case GST_RIFF_WAVE_FORMAT_ADPCM: + caps = gst_caps_new_simple ("audio/x-adpcm", + "layout", G_TYPE_STRING, "microsoft", NULL); + if (codec_name) + *codec_name = g_strdup ("ADPCM audio"); + block_align = TRUE; + break; + + case GST_RIFF_WAVE_FORMAT_IEEE_FLOAT: + rate_max = 192000; + channels_max = 8; + + if (strf != NULL) { + gint ba = strf->blockalign; + gint ch = strf->channels; + gint wd = ba * 8 / ch; + + caps = gst_caps_new_simple ("audio/x-raw-float", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, ch, "width", G_TYPE_INT, wd, NULL); + + /* Add default channel layout. In theory this should be done + * for 1 and 2 channels too but apparently breaks too many + * things currently. Also we know no default layout for more than + * 8 channels. */ + if (ch > 2) { + if (ch > 8) + GST_WARNING ("don't know default layout for %d channels", ch); + else if (gst_riff_wave_add_default_channel_layout (caps)) + GST_DEBUG ("using default channel layout for %d channels", ch); + else + GST_WARNING ("failed to add channel layout"); + } + } else { + /* FIXME: this is pretty useless - we need fixed caps */ + caps = gst_caps_from_string ("audio/x-raw-float, " + "endianness = (int) LITTLE_ENDIAN, " "width = (int) { 32, 64 }"); + } + if (codec_name && strf) + *codec_name = g_strdup_printf ("Uncompressed %d-bit IEEE float audio", + strf->size); + break; + + case GST_RIFF_WAVE_FORMAT_IBM_CVSD: + goto unknown; + + case GST_RIFF_WAVE_FORMAT_ALAW: + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of alaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->blockalign = (strf->size * strf->channels) / 8; + strf->av_bps = strf->blockalign * strf->rate; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of alaw audio", + strf->av_bps, strf->blockalign); + strf->blockalign = (strf->size * strf->channels) / 8; + strf->av_bps = strf->blockalign * strf->rate; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-alaw", NULL); + if (codec_name) + *codec_name = g_strdup ("A-law audio"); + break; + + case GST_RIFF_WAVE_FORMAT_WMS: + caps = gst_caps_new_simple ("audio/x-wms", NULL); + if (strf != NULL) { + gst_caps_set_simple (caps, + "bitrate", G_TYPE_INT, strf->av_bps * 8, + "width", G_TYPE_INT, strf->size, + "depth", G_TYPE_INT, strf->size, NULL); + } else { + gst_caps_set_simple (caps, + "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL); + } + if (codec_name) + *codec_name = g_strdup ("Windows Media Audio Speech"); + block_align = TRUE; + break; + + case GST_RIFF_WAVE_FORMAT_MULAW: + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of mulaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->blockalign = (strf->size * strf->channels) / 8; + strf->av_bps = strf->blockalign * strf->rate; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING ("fixing av_bps (%d) and blockalign (%d) of mulaw audio", + strf->av_bps, strf->blockalign); + strf->blockalign = (strf->size * strf->channels) / 8; + strf->av_bps = strf->blockalign * strf->rate; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-mulaw", NULL); + if (codec_name) + *codec_name = g_strdup ("Mu-law audio"); + break; + + case GST_RIFF_WAVE_FORMAT_OKI_ADPCM: + goto unknown; + + case GST_RIFF_WAVE_FORMAT_DVI_ADPCM: + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-adpcm", + "layout", G_TYPE_STRING, "dvi", NULL); + if (codec_name) + *codec_name = g_strdup ("DVI ADPCM audio"); + block_align = TRUE; + break; + + case GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH: + rate_min = 8000; + rate_max = 8000; + caps = gst_caps_new_simple ("audio/x-truespeech", NULL); + if (codec_name) + *codec_name = g_strdup ("DSP Group TrueSpeech"); + break; + + case GST_RIFF_WAVE_FORMAT_GSM610: + case GST_RIFF_WAVE_FORMAT_MSN: + rate_min = 1; + caps = gst_caps_new_simple ("audio/ms-gsm", NULL); + if (codec_name) + *codec_name = g_strdup ("MS GSM audio"); + break; + + case GST_RIFF_WAVE_FORMAT_MPEGL12: /* mp1 or mp2 */ + rate_min = 16000; + rate_max = 48000; + caps = gst_caps_new_simple ("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 2, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-1 layer 2"); + break; + + case GST_RIFF_WAVE_FORMAT_MPEGL3: /* mp3 */ + rate_min = 8000; + rate_max = 48000; + caps = gst_caps_new_simple ("audio/mpeg", + "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, 3, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-1 layer 3"); + break; + + case GST_RIFF_WAVE_FORMAT_AMR_NB: /* amr-nb */ + rate_min = 8000; + rate_max = 8000; + channels_max = 1; + caps = gst_caps_new_simple ("audio/AMR", NULL); + if (codec_name) + *codec_name = g_strdup ("AMR Narrow Band (NB)"); + break; + + case GST_RIFF_WAVE_FORMAT_AMR_WB: /* amr-wb */ + rate_min = 16000; + rate_max = 16000; + channels_max = 1; + caps = gst_caps_new_simple ("audio/AMR-WB", NULL); + if (codec_name) + *codec_name = g_strdup ("AMR Wide Band (WB)"); + break; + + case GST_RIFF_WAVE_FORMAT_VORBIS1: /* ogg/vorbis mode 1 */ + case GST_RIFF_WAVE_FORMAT_VORBIS2: /* ogg/vorbis mode 2 */ + case GST_RIFF_WAVE_FORMAT_VORBIS3: /* ogg/vorbis mode 3 */ + case GST_RIFF_WAVE_FORMAT_VORBIS1PLUS: /* ogg/vorbis mode 1+ */ + case GST_RIFF_WAVE_FORMAT_VORBIS2PLUS: /* ogg/vorbis mode 2+ */ + case GST_RIFF_WAVE_FORMAT_VORBIS3PLUS: /* ogg/vorbis mode 3+ */ + rate_max = 192000; + caps = gst_caps_new_simple ("audio/x-vorbis", NULL); + if (codec_name) + *codec_name = g_strdup ("Vorbis"); + break; + + case GST_RIFF_WAVE_FORMAT_A52: + channels_max = 6; + caps = gst_caps_new_simple ("audio/x-ac3", NULL); + if (codec_name) + *codec_name = g_strdup ("AC-3 audio"); + break; + case GST_RIFF_WAVE_FORMAT_DTS: + channels_max = 6; + caps = gst_caps_new_simple ("audio/x-dts", NULL); + if (codec_name) + *codec_name = g_strdup ("DTS audio"); + /* wavparse is not always able to specify rate/channels for DTS-in-wav */ + rate_chan = FALSE; + break; + case GST_RIFF_WAVE_FORMAT_AAC: + case GST_RIFF_WAVE_FORMAT_AAC_AC: + case GST_RIFF_WAVE_FORMAT_AAC_pm: + { + channels_max = 8; + caps = gst_caps_new_simple ("audio/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + if (codec_name) + *codec_name = g_strdup ("MPEG-4 AAC audio"); + break; + } + case GST_RIFF_WAVE_FORMAT_WMAV1: + case GST_RIFF_WAVE_FORMAT_WMAV2: + case GST_RIFF_WAVE_FORMAT_WMAV3: + case GST_RIFF_WAVE_FORMAT_WMAV3_L: + { + gint version = (codec_id - GST_RIFF_WAVE_FORMAT_WMAV1) + 1; + + channels_max = 6; + block_align = TRUE; + + caps = gst_caps_new_simple ("audio/x-wma", + "wmaversion", G_TYPE_INT, version, NULL); + + if (codec_name) { + if (codec_id == GST_RIFF_WAVE_FORMAT_WMAV3_L) + *codec_name = g_strdup ("WMA Lossless"); + else + *codec_name = g_strdup_printf ("WMA Version %d", version + 6); + } + + if (strf != NULL) { + gst_caps_set_simple (caps, + "bitrate", G_TYPE_INT, strf->av_bps * 8, + "depth", G_TYPE_INT, strf->size, NULL); + } else { + gst_caps_set_simple (caps, + "bitrate", GST_TYPE_INT_RANGE, 0, G_MAXINT, NULL); + } + break; + } + case GST_RIFF_WAVE_FORMAT_SONY_ATRAC3: + caps = gst_caps_new_simple ("audio/x-vnd.sony.atrac3", NULL); + if (codec_name) + *codec_name = g_strdup ("Sony ATRAC3"); + break; + + case GST_RIFF_WAVE_FORMAT_SIREN: + caps = gst_caps_new_simple ("audio/x-siren", NULL); + if (codec_name) + *codec_name = g_strdup ("Siren7"); + rate_chan = FALSE; + break; + + case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4: + rate_min = 8000; + rate_max = 96000; + channels_max = 2; + caps = + gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dk4", + NULL); + if (codec_name) + *codec_name = g_strdup ("IMA/DK4 ADPCM"); + break; + case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3: + rate_min = 8000; + rate_max = 96000; + channels_max = 2; + caps = + gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dk3", + NULL); + if (codec_name) + *codec_name = g_strdup ("IMA/DK3 ADPCM"); + break; + + case GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV: + rate_min = 8000; + rate_max = 96000; + channels_max = 2; + caps = + gst_caps_new_simple ("audio/x-adpcm", "layout", G_TYPE_STRING, "dvi", + NULL); + if (codec_name) + *codec_name = g_strdup ("IMA/WAV ADPCM"); + break; + case GST_RIFF_WAVE_FORMAT_EXTENSIBLE:{ + guint16 valid_bits_per_sample; + guint32 channel_mask; + guint32 subformat_guid[4]; + const guint8 *data; + + channels_max = 8; + + /* should be at least 22 bytes */ + if (strf_data == NULL || GST_BUFFER_SIZE (strf_data) < 22) { + GST_WARNING ("WAVE_FORMAT_EXTENSIBLE data size is %d (expected: 22)", + (strf_data) ? GST_BUFFER_SIZE (strf_data) : -1); + return NULL; + } + + data = GST_BUFFER_DATA (strf_data); + + valid_bits_per_sample = GST_READ_UINT16_LE (data); + channel_mask = GST_READ_UINT32_LE (data + 2); + subformat_guid[0] = GST_READ_UINT32_LE (data + 6); + subformat_guid[1] = GST_READ_UINT32_LE (data + 10); + subformat_guid[2] = GST_READ_UINT32_LE (data + 14); + subformat_guid[3] = GST_READ_UINT32_LE (data + 18); + + GST_DEBUG ("valid bps = %u", valid_bits_per_sample); + GST_DEBUG ("channel mask = 0x%08x", channel_mask); + GST_DEBUG ("GUID = %08x-%08x-%08x-%08x", subformat_guid[0], + subformat_guid[1], subformat_guid[2], subformat_guid[3]); + + if (subformat_guid[1] == 0x00100000 && + subformat_guid[2] == 0xaa000080 && subformat_guid[3] == 0x719b3800) { + if (subformat_guid[0] == 0x00000001) { + GST_DEBUG ("PCM"); + if (strf != NULL) { + gint ba = strf->blockalign; + gint wd = ba * 8 / strf->channels; + gint ws; + + /* in riff, the depth is stored in the size field but it just + * means that the _least_ significant bits are cleared. We can + * therefore just play the sample as if it had a depth == width */ + ws = wd; + + /* For reference, use this to get the actual depth: + * ws = strf->size; + * if (valid_bits_per_sample != 0) + * ws = valid_bits_per_sample; */ + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, strf->channels, + "width", G_TYPE_INT, wd, + "depth", G_TYPE_INT, ws, + "rate", G_TYPE_INT, strf->rate, + "signed", G_TYPE_BOOLEAN, wd != 8, NULL); + + /* If channel_mask == 0 and channels > 2 let's + * assume default layout as some wav files don't have the + * channel mask set. Don't set the layout for 1 or 2 + * channels as it apparently breaks too many things currently. */ + if (channel_mask == 0 && strf->channels > 2) + channel_mask = + gst_riff_wavext_get_default_channel_mask (strf->channels); + + if ((channel_mask != 0 || strf->channels > 2) && + !gst_riff_wavext_add_channel_layout (caps, channel_mask)) { + GST_WARNING ("failed to add channel layout"); + gst_caps_unref (caps); + caps = NULL; + } + rate_chan = FALSE; + + if (codec_name) { + *codec_name = g_strdup_printf ("Uncompressed %d-bit PCM audio", + strf->size); + } + } + } else if (subformat_guid[0] == 0x00000003) { + GST_DEBUG ("FLOAT"); + if (strf != NULL) { + gint ba = strf->blockalign; + gint wd = ba * 8 / strf->channels; + + caps = gst_caps_new_simple ("audio/x-raw-float", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, strf->channels, + "width", G_TYPE_INT, wd, "rate", G_TYPE_INT, strf->rate, NULL); + + /* If channel_mask == 0 and channels > 2 let's + * assume default layout as some wav files don't have the + * channel mask set. Don't set the layout for 1 or 2 + * channels as it apparently breaks too many things currently. */ + if (channel_mask == 0 && strf->channels > 2) + channel_mask = + gst_riff_wavext_get_default_channel_mask (strf->channels); + + if ((channel_mask != 0 || strf->channels > 2) && + !gst_riff_wavext_add_channel_layout (caps, channel_mask)) { + GST_WARNING ("failed to add channel layout"); + gst_caps_unref (caps); + caps = NULL; + } + rate_chan = FALSE; + + if (codec_name) { + *codec_name = + g_strdup_printf ("Uncompressed %d-bit IEEE float audio", + strf->size); + } + } + } else if (subformat_guid[0] == 00000006) { + GST_DEBUG ("ALAW"); + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of alaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->av_bps = 8; + strf->blockalign = strf->av_bps * strf->channels; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING + ("fixing av_bps (%d) and blockalign (%d) of alaw audio", + strf->av_bps, strf->blockalign); + strf->av_bps = strf->size; + strf->blockalign = strf->av_bps * strf->channels; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-alaw", NULL); + + if (codec_name) + *codec_name = g_strdup ("A-law audio"); + } else if (subformat_guid[0] == 0x00000007) { + GST_DEBUG ("MULAW"); + if (strf != NULL) { + if (strf->size != 8) { + GST_WARNING ("invalid depth (%d) of mulaw audio, overwriting.", + strf->size); + strf->size = 8; + strf->av_bps = 8; + strf->blockalign = strf->av_bps * strf->channels; + } + if (strf->av_bps == 0 || strf->blockalign == 0) { + GST_WARNING + ("fixing av_bps (%d) and blockalign (%d) of mulaw audio", + strf->av_bps, strf->blockalign); + strf->av_bps = strf->size; + strf->blockalign = strf->av_bps * strf->channels; + } + } + rate_max = 48000; + caps = gst_caps_new_simple ("audio/x-mulaw", NULL); + if (codec_name) + *codec_name = g_strdup ("Mu-law audio"); + } else if (subformat_guid[0] == 0x00000092) { + GST_DEBUG ("FIXME: handle DOLBY AC3 SPDIF format"); + } + } else if (subformat_guid[0] == 0x6ba47966 && + subformat_guid[1] == 0x41783f83 && + subformat_guid[2] == 0xf0006596 && subformat_guid[3] == 0xe59262bf) { + caps = gst_caps_new_simple ("application/x-ogg-avi", NULL); + if (codec_name) + *codec_name = g_strdup ("Ogg-AVI"); + } + + if (caps == NULL) { + GST_WARNING ("Unknown WAVE_FORMAT_EXTENSIBLE audio format"); + return NULL; + } + break; + } + /* can anything decode these? pitfdll? */ + case GST_RIFF_WAVE_FORMAT_VOXWARE_AC8: + case GST_RIFF_WAVE_FORMAT_VOXWARE_AC10: + case GST_RIFF_WAVE_FORMAT_VOXWARE_AC16: + case GST_RIFF_WAVE_FORMAT_VOXWARE_AC20: + case GST_RIFF_WAVE_FORMAT_VOXWARE_METAVOICE: + case GST_RIFF_WAVE_FORMAT_VOXWARE_METASOUND: + case GST_RIFF_WAVE_FORMAT_VOXWARE_RT29HW: + case GST_RIFF_WAVE_FORMAT_VOXWARE_VR12: + case GST_RIFF_WAVE_FORMAT_VOXWARE_VR18: + case GST_RIFF_WAVE_FORMAT_VOXWARE_TQ40: + case GST_RIFF_WAVE_FORMAT_VOXWARE_TQ60:{ + caps = gst_caps_new_simple ("audio/x-voxware", + "voxwaretype", G_TYPE_INT, (gint) codec_id, NULL); + if (codec_name) + *codec_name = g_strdup ("Voxware"); + break; + } + default: + unknown: + GST_WARNING ("Unknown audio tag 0x%04x", codec_id); + return NULL; + } + + if (strf != NULL) { + if (rate_chan) { + if (strf->channels > channels_max) + goto too_many_channels; + if (strf->rate < rate_min || strf->rate > rate_max) + goto invalid_rate; + + gst_caps_set_simple (caps, + "rate", G_TYPE_INT, strf->rate, + "channels", G_TYPE_INT, strf->channels, NULL); + } + if (block_align) { + gst_caps_set_simple (caps, + "block_align", G_TYPE_INT, strf->blockalign, NULL); + } + } else { + if (rate_chan) { + if (rate_min == rate_max) + gst_caps_set_simple (caps, "rate", G_TYPE_INT, rate_min, NULL); + else + gst_caps_set_simple (caps, + "rate", GST_TYPE_INT_RANGE, rate_min, rate_max, NULL); + if (channels_max == 1) + gst_caps_set_simple (caps, "channels", G_TYPE_INT, 1, NULL); + else + gst_caps_set_simple (caps, + "channels", GST_TYPE_INT_RANGE, 1, channels_max, NULL); + } + if (block_align) { + gst_caps_set_simple (caps, + "block_align", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + } + } + + /* extradata */ + if (strf_data || strd_data) { + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, + strf_data ? strf_data : strd_data, NULL); + } + + return caps; + + /* ERROR */ +too_many_channels: + GST_WARNING + ("Stream claims to contain %u channels, but format only supports %d", + strf->channels, channels_max); + gst_caps_unref (caps); + return NULL; +invalid_rate: + GST_WARNING + ("Stream with sample_rate %u, but format only supports %d .. %d", + strf->rate, rate_min, rate_max); + gst_caps_unref (caps); + return NULL; +} + +GstCaps * +gst_riff_create_iavs_caps (guint32 codec_fcc, + gst_riff_strh * strh, gst_riff_strf_iavs * strf, + GstBuffer * init_data, GstBuffer * extra_data, char **codec_name) +{ + GstCaps *caps = NULL; + + switch (codec_fcc) { + /* is this correct? */ + case GST_MAKE_FOURCC ('D', 'V', 'S', 'D'): + case GST_MAKE_FOURCC ('d', 'v', 's', 'd'): + caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, TRUE, NULL); + if (codec_name) + *codec_name = g_strdup ("Generic DV"); + break; + + default: + GST_WARNING ("Unknown IAVS fourcc %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (codec_fcc)); + return NULL; + } + + return caps; +} + +/* + * Functions below are for template caps. All is variable. + */ + +GstCaps * +gst_riff_create_video_template_caps (void) +{ + static const guint32 tags[] = { + GST_MAKE_FOURCC ('3', 'I', 'V', '1'), + GST_MAKE_FOURCC ('A', 'S', 'V', '1'), + GST_MAKE_FOURCC ('A', 'S', 'V', '2'), + GST_MAKE_FOURCC ('C', 'L', 'J', 'R'), + GST_MAKE_FOURCC ('C', 'S', 'C', 'D'), + GST_MAKE_FOURCC ('C', 'Y', 'U', 'V'), + GST_MAKE_FOURCC ('D', 'I', 'B', ' '), + GST_MAKE_FOURCC ('D', 'I', 'V', '3'), + GST_MAKE_FOURCC ('D', 'I', 'V', 'X'), + GST_MAKE_FOURCC ('D', 'U', 'C', 'K'), + GST_MAKE_FOURCC ('D', 'V', 'S', 'D'), + GST_MAKE_FOURCC ('D', 'V', '5', '0'), + GST_MAKE_FOURCC ('D', 'X', '5', '0'), + GST_MAKE_FOURCC ('M', '4', 'C', 'C'), + GST_MAKE_FOURCC ('F', 'L', 'V', '1'), + GST_MAKE_FOURCC ('F', 'L', 'V', '4'), + GST_MAKE_FOURCC ('H', '2', '6', '3'), + GST_MAKE_FOURCC ('V', 'X', '1', 'K'), + GST_MAKE_FOURCC ('H', '2', '6', '4'), + GST_MAKE_FOURCC ('H', 'F', 'Y', 'U'), + GST_MAKE_FOURCC ('I', '2', '6', '3'), + GST_MAKE_FOURCC ('I', '4', '2', '0'), + GST_MAKE_FOURCC ('I', 'V', '3', '2'), + GST_MAKE_FOURCC ('I', 'V', '4', '1'), + GST_MAKE_FOURCC ('I', 'V', '5', '0'), + GST_MAKE_FOURCC ('L', '2', '6', '3'), + GST_MAKE_FOURCC ('L', '2', '6', '4'), + GST_MAKE_FOURCC ('M', '2', '6', '3'), + GST_MAKE_FOURCC ('M', '4', 'S', '2'), + GST_MAKE_FOURCC ('M', 'J', 'P', 'G'), + GST_MAKE_FOURCC ('M', 'P', '4', '2'), + GST_MAKE_FOURCC ('M', 'P', '4', '3'), + GST_MAKE_FOURCC ('M', 'P', 'E', 'G'), + GST_MAKE_FOURCC ('M', 'P', 'G', '2'), + GST_MAKE_FOURCC ('M', 'P', 'G', '4'), + GST_MAKE_FOURCC ('M', 'S', 'Z', 'H'), + GST_MAKE_FOURCC ('P', 'N', 'G', ' '), + GST_MAKE_FOURCC ('R', 'L', 'E', ' '), + GST_MAKE_FOURCC ('R', 'T', '2', '1'), + GST_MAKE_FOURCC ('S', 'P', '5', '3'), + GST_MAKE_FOURCC ('T', 'M', '2', '0'), + GST_MAKE_FOURCC ('T', 'S', 'C', 'C'), + GST_MAKE_FOURCC ('U', 'L', 'T', 'I'), + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), + GST_MAKE_FOURCC ('V', 'C', 'R', '1'), + GST_MAKE_FOURCC ('V', 'C', 'R', '2'), + GST_MAKE_FOURCC ('V', 'D', 'O', 'W'), + GST_MAKE_FOURCC ('V', 'I', 'V', 'O'), + GST_MAKE_FOURCC ('V', 'M', 'n', 'c'), + GST_MAKE_FOURCC ('V', 'P', '3', ' '), + GST_MAKE_FOURCC ('V', 'S', 'S', 'H'), + GST_MAKE_FOURCC ('W', 'M', 'V', '1'), + GST_MAKE_FOURCC ('W', 'M', 'V', '2'), + GST_MAKE_FOURCC ('W', 'M', 'V', '3'), + GST_MAKE_FOURCC ('X', 'V', 'I', 'D'), + GST_MAKE_FOURCC ('X', 'x', 'a', 'n'), + GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'), + GST_MAKE_FOURCC ('Y', 'V', 'U', '9'), + GST_MAKE_FOURCC ('Z', 'L', 'I', 'B'), + GST_MAKE_FOURCC ('c', 'v', 'i', 'd'), + GST_MAKE_FOURCC ('h', '2', '6', '4'), + GST_MAKE_FOURCC ('m', 's', 'v', 'c'), + GST_MAKE_FOURCC ('x', '2', '6', '3'), + GST_MAKE_FOURCC ('d', 'r', 'a', 'c'), + GST_MAKE_FOURCC ('F', 'F', 'V', '1'), + GST_MAKE_FOURCC ('K', 'M', 'V', 'C'), + GST_MAKE_FOURCC ('V', 'P', '5', '0'), + GST_MAKE_FOURCC ('V', 'P', '6', '0'), + GST_MAKE_FOURCC ('V', 'P', '6', 'F'), + GST_MAKE_FOURCC ('V', 'P', '7', '0'), + GST_MAKE_FOURCC ('V', 'P', '8', '0'), + GST_MAKE_FOURCC ('L', 'M', '2', '0'), + GST_MAKE_FOURCC ('R', 'P', 'Z', 'A'), + GST_MAKE_FOURCC ('T', 'H', 'E', 'O'), + GST_MAKE_FOURCC ('F', 'P', 'S', '1'), + GST_MAKE_FOURCC ('A', 'A', 'S', 'C'), + GST_MAKE_FOURCC ('Y', 'V', '1', '2'), + GST_MAKE_FOURCC ('L', 'O', 'C', 'O'), + GST_MAKE_FOURCC ('Z', 'M', 'B', 'V'), + /* FILL ME */ + }; + guint i; + GstCaps *caps, *one; + + caps = gst_caps_new_empty (); + for (i = 0; i < G_N_ELEMENTS (tags); i++) { + one = gst_riff_create_video_caps (tags[i], NULL, NULL, NULL, NULL, NULL); + if (one) + gst_caps_append (caps, one); + } + + return caps; +} + +GstCaps * +gst_riff_create_audio_template_caps (void) +{ + static const guint16 tags[] = { + GST_RIFF_WAVE_FORMAT_GSM610, + GST_RIFF_WAVE_FORMAT_MPEGL3, + GST_RIFF_WAVE_FORMAT_MPEGL12, + GST_RIFF_WAVE_FORMAT_PCM, + GST_RIFF_WAVE_FORMAT_VORBIS1, + GST_RIFF_WAVE_FORMAT_A52, + GST_RIFF_WAVE_FORMAT_DTS, + GST_RIFF_WAVE_FORMAT_AAC, + GST_RIFF_WAVE_FORMAT_ALAW, + GST_RIFF_WAVE_FORMAT_MULAW, + GST_RIFF_WAVE_FORMAT_WMS, + GST_RIFF_WAVE_FORMAT_ADPCM, + GST_RIFF_WAVE_FORMAT_DVI_ADPCM, + GST_RIFF_WAVE_FORMAT_DSP_TRUESPEECH, + GST_RIFF_WAVE_FORMAT_WMAV1, + GST_RIFF_WAVE_FORMAT_WMAV2, + GST_RIFF_WAVE_FORMAT_WMAV3, + GST_RIFF_WAVE_FORMAT_SONY_ATRAC3, + GST_RIFF_WAVE_FORMAT_IEEE_FLOAT, + GST_RIFF_WAVE_FORMAT_VOXWARE_METASOUND, + GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK4, + GST_RIFF_WAVE_FORMAT_ADPCM_IMA_DK3, + GST_RIFF_WAVE_FORMAT_ADPCM_IMA_WAV, + GST_RIFF_WAVE_FORMAT_AMR_NB, + GST_RIFF_WAVE_FORMAT_AMR_WB, + GST_RIFF_WAVE_FORMAT_SIREN, + /* FILL ME */ + }; + guint i; + GstCaps *caps, *one; + + caps = gst_caps_new_empty (); + for (i = 0; i < G_N_ELEMENTS (tags); i++) { + one = gst_riff_create_audio_caps (tags[i], NULL, NULL, NULL, NULL, NULL); + if (one) + gst_caps_append (caps, one); + } + one = gst_caps_new_simple ("application/x-ogg-avi", NULL); + gst_caps_append (caps, one); + + return caps; +} + +GstCaps * +gst_riff_create_iavs_template_caps (void) +{ + static const guint32 tags[] = { + GST_MAKE_FOURCC ('D', 'V', 'S', 'D') + /* FILL ME */ + }; + guint i; + GstCaps *caps, *one; + + caps = gst_caps_new_empty (); + for (i = 0; i < G_N_ELEMENTS (tags); i++) { + one = gst_riff_create_iavs_caps (tags[i], NULL, NULL, NULL, NULL, NULL); + if (one) + gst_caps_append (caps, one); + } + + return caps; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.h new file mode 100644 index 0000000..cc09fd8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-media.h @@ -0,0 +1,65 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff-media.h: RIFF-id to/from caps routines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RIFF_MEDIA_H__ +#define __GST_RIFF_MEDIA_H__ + +#include +#include +#include "riff-ids.h" + +G_BEGIN_DECLS + +/* + * Create caos. strh/strf, strf/strd_data and codec_name can be NULL. + */ + +GstCaps * gst_riff_create_video_caps (guint32 codec_fcc, + gst_riff_strh * strh, + gst_riff_strf_vids * strf, + GstBuffer * strf_data, + GstBuffer * strd_data, + char ** codec_name); + +GstCaps * gst_riff_create_audio_caps (guint16 codec_id, + gst_riff_strh * strh, + gst_riff_strf_auds * strf, + GstBuffer * strf_data, + GstBuffer * strd_data, + char ** codec_name); + +GstCaps * gst_riff_create_iavs_caps (guint32 codec_fcc, + gst_riff_strh * strh, + gst_riff_strf_iavs * strf, + GstBuffer * strf_data, + GstBuffer * strd_data, + char ** codec_name); +/* + * Create template caps (includes all known types). + */ + +GstCaps * gst_riff_create_video_template_caps (void); +GstCaps * gst_riff_create_audio_template_caps (void); +GstCaps * gst_riff_create_iavs_template_caps (void); + +G_END_DECLS + +#endif /* __GST_RIFF_READ_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.c new file mode 100644 index 0000000..e5983be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.c @@ -0,0 +1,749 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff-read.c: RIFF input file parsing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +#include "riff-read.h" + +GST_DEBUG_CATEGORY_EXTERN (riff_debug); +#define GST_CAT_DEFAULT riff_debug + +/** + * gst_riff_read_chunk: + * @element: caller element (used for debugging). + * @pad: pad to pull data from. + * @offset: offset to pull from, incremented by this function. + * @tag: fourcc of the chunk (returned by this function). + * @chunk_data: buffer (returned by this function). + * + * Reads a single chunk of data. Since 0.10.8 'JUNK' chunks + * are skipped automatically. + * + * Returns: flow status. + */ + +GstFlowReturn +gst_riff_read_chunk (GstElement * element, + GstPad * pad, guint64 * _offset, guint32 * tag, GstBuffer ** _chunk_data) +{ + GstBuffer *buf; + GstFlowReturn res; + guint size; + guint64 offset = *_offset; + + g_return_val_if_fail (element != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (tag != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (_chunk_data != NULL, GST_FLOW_ERROR); + +skip_junk: + size = 8; + if ((res = gst_pad_pull_range (pad, offset, size, &buf)) != GST_FLOW_OK) + return res; + else if (GST_BUFFER_SIZE (buf) < size) + goto too_small; + + *tag = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf)); + size = GST_READ_UINT32_LE (GST_BUFFER_DATA (buf) + 4); + gst_buffer_unref (buf); + + GST_DEBUG_OBJECT (element, "fourcc=%" GST_FOURCC_FORMAT ", size=%u", + GST_FOURCC_ARGS (*tag), size); + + /* skip 'JUNK' chunks */ + if (*tag == GST_RIFF_TAG_JUNK || *tag == GST_RIFF_TAG_JUNQ) { + size = GST_ROUND_UP_2 (size); + *_offset += 8 + size; + offset += 8 + size; + GST_DEBUG_OBJECT (element, "skipping JUNK chunk"); + goto skip_junk; + } + + if ((res = gst_pad_pull_range (pad, offset + 8, size, &buf)) != GST_FLOW_OK) + return res; + else if (GST_BUFFER_SIZE (buf) < size) + goto too_small; + + *_chunk_data = buf; + *_offset += 8 + GST_ROUND_UP_2 (size); + + return GST_FLOW_OK; + + /* ERRORS */ +too_small: + { + /* short read, we return UNEXPECTED to mark the EOS case */ + GST_DEBUG_OBJECT (element, "not enough data (available=%u, needed=%u)", + GST_BUFFER_SIZE (buf), size); + gst_buffer_unref (buf); + return GST_FLOW_UNEXPECTED; + } +} + +/** + * gst_riff_parse_chunk: + * @element: caller element (used for debugging). + * @buf: input buffer. + * @offset: offset in the buffer in the caller. Is incremented + * by the read size by this function. + * @fourcc: fourcc (returned by this function0 of the chunk. + * @chunk_data: buffer (returned by the function) containing the + * chunk data, which may be NULL if chunksize == 0 + * + * Reads a single chunk. + * + * Returns: FALSE on error, TRUE otherwise + */ +gboolean +gst_riff_parse_chunk (GstElement * element, GstBuffer * buf, + guint * _offset, guint32 * _fourcc, GstBuffer ** chunk_data) +{ + guint size, bufsize; + guint32 fourcc; + guint8 *data; + guint offset = *_offset; + + g_return_val_if_fail (element != NULL, FALSE); + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (_offset != NULL, FALSE); + g_return_val_if_fail (_fourcc != NULL, FALSE); + g_return_val_if_fail (chunk_data != NULL, FALSE); + + *chunk_data = NULL; + *_fourcc = 0; + + bufsize = GST_BUFFER_SIZE (buf); + + if (bufsize == offset) + goto end_offset; + + if (bufsize < offset + 8) + goto too_small; + + /* read header */ + data = GST_BUFFER_DATA (buf) + offset; + fourcc = GST_READ_UINT32_LE (data); + size = GST_READ_UINT32_LE (data + 4); + + GST_DEBUG_OBJECT (element, "fourcc=%" GST_FOURCC_FORMAT ", size=%u", + GST_FOURCC_ARGS (fourcc), size); + + /* be paranoid: size may be nonsensical value here, such as (guint) -1 */ + if (G_UNLIKELY (size > G_MAXINT)) + goto bogus_size; + + if (bufsize < size + 8 + offset) { + GST_DEBUG_OBJECT (element, + "Needed chunk data (%d) is more than available (%d), shortcutting", + size, bufsize - 8 - offset); + size = bufsize - 8 - offset; + } + + if (size) + *chunk_data = gst_buffer_create_sub (buf, offset + 8, size); + else + *chunk_data = NULL; + + *_fourcc = fourcc; + *_offset += 8 + GST_ROUND_UP_2 (size); + + return TRUE; + + /* ERRORS */ +end_offset: + { + GST_DEBUG_OBJECT (element, "End of chunk (offset %d)", offset); + return FALSE; + } +too_small: + { + GST_DEBUG_OBJECT (element, + "Failed to parse chunk header (offset %d, %d available, %d needed)", + offset, bufsize, 8); + return FALSE; + } +bogus_size: + { + GST_ERROR_OBJECT (element, "Broken file: bogus chunk size %u", size); + return FALSE; + } +} + +/** + * gst_riff_parse_file_header: + * @element: caller element (used for debugging/error). + * @buf: input buffer from which the file header will be parsed, + * should be at least 12 bytes long. + * @doctype: a fourcc (returned by this function) to indicate the + * type of document (according to the header). + * + * Reads the first few bytes from the provided buffer, checks + * if this stream is a RIFF stream, and determines document type. + * This function takes ownership of @buf so it should not be used anymore + * after calling this function. + * + * Returns: FALSE if this is not a RIFF stream (in which case the + * caller should error out; we already throw an error), or TRUE + * if it is. + */ +gboolean +gst_riff_parse_file_header (GstElement * element, + GstBuffer * buf, guint32 * doctype) +{ + guint8 *data; + guint32 tag; + + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (doctype != NULL, FALSE); + + if (GST_BUFFER_SIZE (buf) < 12) + goto too_small; + + data = GST_BUFFER_DATA (buf); + tag = GST_READ_UINT32_LE (data); + if (tag != GST_RIFF_TAG_RIFF && tag != GST_RIFF_TAG_AVF0) + goto not_riff; + + *doctype = GST_READ_UINT32_LE (data + 8); + + gst_buffer_unref (buf); + + return TRUE; + + /* ERRORS */ +too_small: + { + GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL), + ("Not enough data to parse RIFF header (%d available, %d needed)", + GST_BUFFER_SIZE (buf), 12)); + gst_buffer_unref (buf); + return FALSE; + } +not_riff: + { + GST_ELEMENT_ERROR (element, STREAM, WRONG_TYPE, (NULL), + ("Stream is no RIFF stream: %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (tag))); + gst_buffer_unref (buf); + return FALSE; + } +} + +/** + * gst_riff_parse_strh: + * @element: caller element (used for debugging/error). + * @buf: input data to be used for parsing, stripped from header. + * @strh: a pointer (returned by this function) to a filled-in + * strh structure. Caller should free it. + * + * Parses a strh structure from input data. Takes ownership of @buf. + * + * Returns: TRUE if parsing succeeded, otherwise FALSE. The stream + * should be skipped on error, but it is not fatal. + */ + +gboolean +gst_riff_parse_strh (GstElement * element, + GstBuffer * buf, gst_riff_strh ** _strh) +{ + gst_riff_strh *strh; + + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (_strh != NULL, FALSE); + + if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strh)) + goto too_small; + + strh = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buf); + +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + strh->type = GUINT32_FROM_LE (strh->type); + strh->fcc_handler = GUINT32_FROM_LE (strh->fcc_handler); + strh->flags = GUINT32_FROM_LE (strh->flags); + strh->priority = GUINT32_FROM_LE (strh->priority); + strh->init_frames = GUINT32_FROM_LE (strh->init_frames); + strh->scale = GUINT32_FROM_LE (strh->scale); + strh->rate = GUINT32_FROM_LE (strh->rate); + strh->start = GUINT32_FROM_LE (strh->start); + strh->length = GUINT32_FROM_LE (strh->length); + strh->bufsize = GUINT32_FROM_LE (strh->bufsize); + strh->quality = GUINT32_FROM_LE (strh->quality); + strh->samplesize = GUINT32_FROM_LE (strh->samplesize); +#endif + + /* avoid divisions by zero */ + if (!strh->scale) + strh->scale = 1; + if (!strh->rate) + strh->rate = 1; + + /* debug */ + GST_INFO_OBJECT (element, "strh tag found:"); + GST_INFO_OBJECT (element, " type %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (strh->type)); + GST_INFO_OBJECT (element, " fcc_handler %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (strh->fcc_handler)); + GST_INFO_OBJECT (element, " flags 0x%08x", strh->flags); + GST_INFO_OBJECT (element, " priority %d", strh->priority); + GST_INFO_OBJECT (element, " init_frames %d", strh->init_frames); + GST_INFO_OBJECT (element, " scale %d", strh->scale); + GST_INFO_OBJECT (element, " rate %d", strh->rate); + GST_INFO_OBJECT (element, " start %d", strh->start); + GST_INFO_OBJECT (element, " length %d", strh->length); + GST_INFO_OBJECT (element, " bufsize %d", strh->bufsize); + GST_INFO_OBJECT (element, " quality %d", strh->quality); + GST_INFO_OBJECT (element, " samplesize %d", strh->samplesize); + + *_strh = strh; + + return TRUE; + + /* ERRORS */ +too_small: + { + GST_ERROR_OBJECT (element, + "Too small strh (%d available, %d needed)", + GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strh)); + gst_buffer_unref (buf); + return FALSE; + } +} + +/** + * gst_riff_parse_strf_vids: + * @element: caller element (used for debugging/error). + * @buf: input data to be used for parsing, stripped from header. + * @strf: a pointer (returned by this function) to a filled-in + * strf/vids structure. Caller should free it. + * @data: a pointer (returned by this function) to a buffer + * containing extradata for this particular stream (e.g. + * palette, codec initialization data). + * + * Parses a video stream´s strf structure plus optionally some + * extradata from input data. This function takes ownership of @buf. + * + * Returns: TRUE if parsing succeeded, otherwise FALSE. The stream + * should be skipped on error, but it is not fatal. + */ + +gboolean +gst_riff_parse_strf_vids (GstElement * element, + GstBuffer * buf, gst_riff_strf_vids ** _strf, GstBuffer ** data) +{ + gst_riff_strf_vids *strf; + + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (_strf != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_vids)) + goto too_small; + + strf = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + strf->size = GUINT32_FROM_LE (strf->size); + strf->width = GUINT32_FROM_LE (strf->width); + strf->height = GUINT32_FROM_LE (strf->height); + strf->planes = GUINT16_FROM_LE (strf->planes); + strf->bit_cnt = GUINT16_FROM_LE (strf->bit_cnt); + strf->compression = GUINT32_FROM_LE (strf->compression); + strf->image_size = GUINT32_FROM_LE (strf->image_size); + strf->xpels_meter = GUINT32_FROM_LE (strf->xpels_meter); + strf->ypels_meter = GUINT32_FROM_LE (strf->ypels_meter); + strf->num_colors = GUINT32_FROM_LE (strf->num_colors); + strf->imp_colors = GUINT32_FROM_LE (strf->imp_colors); +#endif + + /* size checking */ + *data = NULL; + if (strf->size > GST_BUFFER_SIZE (buf)) { + GST_WARNING_OBJECT (element, + "strf_vids header gave %d bytes data, only %d available", + strf->size, GST_BUFFER_SIZE (buf)); + strf->size = GST_BUFFER_SIZE (buf); + } + if (sizeof (gst_riff_strf_vids) < GST_BUFFER_SIZE (buf)) { + *data = gst_buffer_create_sub (buf, sizeof (gst_riff_strf_vids), + GST_BUFFER_SIZE (buf) - sizeof (gst_riff_strf_vids)); + } + + /* debug */ + GST_INFO_OBJECT (element, "strf tag found in context vids:"); + GST_INFO_OBJECT (element, " size %d", strf->size); + GST_INFO_OBJECT (element, " width %d", strf->width); + GST_INFO_OBJECT (element, " height %d", strf->height); + GST_INFO_OBJECT (element, " planes %d", strf->planes); + GST_INFO_OBJECT (element, " bit_cnt %d", strf->bit_cnt); + GST_INFO_OBJECT (element, " compression %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (strf->compression)); + GST_INFO_OBJECT (element, " image_size %d", strf->image_size); + GST_INFO_OBJECT (element, " xpels_meter %d", strf->xpels_meter); + GST_INFO_OBJECT (element, " ypels_meter %d", strf->ypels_meter); + GST_INFO_OBJECT (element, " num_colors %d", strf->num_colors); + GST_INFO_OBJECT (element, " imp_colors %d", strf->imp_colors); + if (*data) + GST_INFO_OBJECT (element, " %d bytes extradata", GST_BUFFER_SIZE (*data)); + + gst_buffer_unref (buf); + + *_strf = strf; + + return TRUE; + + /* ERRORS */ +too_small: + { + GST_ERROR_OBJECT (element, + "Too small strf_vids (%d available, %d needed)", + GST_BUFFER_SIZE (buf), (int) sizeof (gst_riff_strf_vids)); + gst_buffer_unref (buf); + return FALSE; + } +} + +/** + * gst_riff_parse_strf_auds: + * @element: caller element (used for debugging/error). + * @buf: input data to be used for parsing, stripped from header. + * @strf: a pointer (returned by this function) to a filled-in + * strf/auds structure. Caller should free it. + * @data: a pointer (returned by this function) to a buffer + * containing extradata for this particular stream (e.g. + * codec initialization data). + * + * Parses an audio stream´s strf structure plus optionally some + * extradata from input data. This function takes ownership of @buf. + * use. + * + * Returns: TRUE if parsing succeeded, otherwise FALSE. The stream + * should be skipped on error, but it is not fatal. + */ +gboolean +gst_riff_parse_strf_auds (GstElement * element, + GstBuffer * buf, gst_riff_strf_auds ** _strf, GstBuffer ** data) +{ + gst_riff_strf_auds *strf; + guint bufsize; + + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (_strf != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + bufsize = GST_BUFFER_SIZE (buf); + + if (bufsize < sizeof (gst_riff_strf_auds)) + goto too_small; + + strf = g_memdup (GST_BUFFER_DATA (buf), bufsize); + +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + strf->format = GUINT16_FROM_LE (strf->format); + strf->channels = GUINT16_FROM_LE (strf->channels); + strf->rate = GUINT32_FROM_LE (strf->rate); + strf->av_bps = GUINT32_FROM_LE (strf->av_bps); + strf->blockalign = GUINT16_FROM_LE (strf->blockalign); + strf->size = GUINT16_FROM_LE (strf->size); +#endif + + /* size checking */ + *data = NULL; + if (bufsize > sizeof (gst_riff_strf_auds) + 2) { + gint len; + + len = GST_READ_UINT16_LE (&GST_BUFFER_DATA (buf)[16]); + if (len + 2 + sizeof (gst_riff_strf_auds) > bufsize) { + GST_WARNING_OBJECT (element, + "Extradata indicated %d bytes, but only %" G_GSSIZE_FORMAT + " available", len, bufsize - 2 - sizeof (gst_riff_strf_auds)); + len = bufsize - 2 - sizeof (gst_riff_strf_auds); + } + if (len) + *data = gst_buffer_create_sub (buf, sizeof (gst_riff_strf_auds) + 2, len); + } + + /* debug */ + GST_INFO_OBJECT (element, "strf tag found in context auds:"); + GST_INFO_OBJECT (element, " format %d", strf->format); + GST_INFO_OBJECT (element, " channels %d", strf->channels); + GST_INFO_OBJECT (element, " rate %d", strf->rate); + GST_INFO_OBJECT (element, " av_bps %d", strf->av_bps); + GST_INFO_OBJECT (element, " blockalign %d", strf->blockalign); + GST_INFO_OBJECT (element, " size %d", strf->size); + if (*data) + GST_INFO_OBJECT (element, " %d bytes extradata", GST_BUFFER_SIZE (*data)); + + gst_buffer_unref (buf); + + *_strf = strf; + + return TRUE; + + /* ERROR */ +too_small: + { + GST_ERROR_OBJECT (element, + "Too small strf_auds (%d available, %" G_GSSIZE_FORMAT " needed)", + bufsize, sizeof (gst_riff_strf_auds)); + gst_buffer_unref (buf); + return FALSE; + } +} + +/** + * gst_riff_parse_strf_iavs: + * @element: caller element (used for debugging/error). + * @buf: input data to be used for parsing, stripped from header. + * @strf: a pointer (returned by this function) to a filled-in + * strf/iavs structure. Caller should free it. + * @data: a pointer (returned by this function) to a buffer + * containing extradata for this particular stream (e.g. + * codec initialization data). + * + * Parses a interleaved (also known as "complex") stream´s strf + * structure plus optionally some extradata from input data. This + * function takes ownership of @buf. + * + * Returns: TRUE if parsing succeeded, otherwise FALSE. + */ + +gboolean +gst_riff_parse_strf_iavs (GstElement * element, + GstBuffer * buf, gst_riff_strf_iavs ** _strf, GstBuffer ** data) +{ + gst_riff_strf_iavs *strf; + + g_return_val_if_fail (buf != NULL, FALSE); + g_return_val_if_fail (_strf != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + if (GST_BUFFER_SIZE (buf) < sizeof (gst_riff_strf_iavs)) + goto too_small; + + strf = g_memdup (GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_buffer_unref (buf); + +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + strf->DVAAuxSrc = GUINT32_FROM_LE (strf->DVAAuxSrc); + strf->DVAAuxCtl = GUINT32_FROM_LE (strf->DVAAuxCtl); + strf->DVAAuxSrc1 = GUINT32_FROM_LE (strf->DVAAuxSrc1); + strf->DVAAuxCtl1 = GUINT32_FROM_LE (strf->DVAAuxCtl1); + strf->DVVAuxSrc = GUINT32_FROM_LE (strf->DVVAuxSrc); + strf->DVVAuxCtl = GUINT32_FROM_LE (strf->DVVAuxCtl); + strf->DVReserved1 = GUINT32_FROM_LE (strf->DVReserved1); + strf->DVReserved2 = GUINT32_FROM_LE (strf->DVReserved2); +#endif + + /* debug */ + GST_INFO_OBJECT (element, "strf tag found in context iavs:"); + GST_INFO_OBJECT (element, " DVAAuxSrc %08x", strf->DVAAuxSrc); + GST_INFO_OBJECT (element, " DVAAuxCtl %08x", strf->DVAAuxCtl); + GST_INFO_OBJECT (element, " DVAAuxSrc1 %08x", strf->DVAAuxSrc1); + GST_INFO_OBJECT (element, " DVAAuxCtl1 %08x", strf->DVAAuxCtl1); + GST_INFO_OBJECT (element, " DVVAuxSrc %08x", strf->DVVAuxSrc); + GST_INFO_OBJECT (element, " DVVAuxCtl %08x", strf->DVVAuxCtl); + GST_INFO_OBJECT (element, " DVReserved1 %08x", strf->DVReserved1); + GST_INFO_OBJECT (element, " DVReserved2 %08x", strf->DVReserved2); + + *_strf = strf; + *data = NULL; + + return TRUE; + + /* ERRORS */ +too_small: + { + GST_ERROR_OBJECT (element, + "Too small strf_iavs (%d available, %" G_GSSIZE_FORMAT " needed)", + GST_BUFFER_SIZE (buf), sizeof (gst_riff_strf_iavs)); + gst_buffer_unref (buf); + return FALSE; + } +} + +/** + * gst_riff_parse_info: + * @element: caller element (used for debugging/error). + * @buf: input data to be used for parsing, stripped from header. + * @taglist: a pointer to a taglist (returned by this function) + * containing information about this stream. May be + * NULL if no supported tags were found. + * + * Parses stream metadata from input data. + */ +void +gst_riff_parse_info (GstElement * element, + GstBuffer * buf, GstTagList ** _taglist) +{ + guint8 *data; + guint size, tsize; + guint32 tag; + const gchar *type; + GstTagList *taglist; + + g_return_if_fail (_taglist != NULL); + g_return_if_fail (buf != NULL); + + if (!buf) { + *_taglist = NULL; + return; + } + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + taglist = gst_tag_list_new (); + + while (size > 8) { + tag = GST_READ_UINT32_LE (data); + tsize = GST_READ_UINT32_LE (data + 4); + size -= 8; + data += 8; + + GST_DEBUG ("tag %" GST_FOURCC_FORMAT ", size %u", + GST_FOURCC_ARGS (tag), tsize); + + if (tsize > size) { + GST_WARNING_OBJECT (element, + "Tagsize %d is larger than available data %d", tsize, size); + tsize = size; + } + + /* find out the type of metadata */ + switch (tag) { + case GST_RIFF_INFO_IARL: + type = GST_TAG_LOCATION; + break; + case GST_RIFF_INFO_IART: + type = GST_TAG_ARTIST; + break; + case GST_RIFF_INFO_ICMS: + type = NULL; /*"Commissioner"; */ + break; + case GST_RIFF_INFO_ICMT: + type = GST_TAG_COMMENT; + break; + case GST_RIFF_INFO_ICOP: + type = GST_TAG_COPYRIGHT; + break; + case GST_RIFF_INFO_ICRD: + type = GST_TAG_DATE; + break; + case GST_RIFF_INFO_ICRP: + type = NULL; /*"Cropped"; */ + break; + case GST_RIFF_INFO_IDIM: + type = NULL; /*"Dimensions"; */ + break; + case GST_RIFF_INFO_IDPI: + type = NULL; /*"Dots per Inch"; */ + break; + case GST_RIFF_INFO_IENG: + type = NULL; /*"Engineer"; */ + break; + case GST_RIFF_INFO_IGNR: + type = GST_TAG_GENRE; + break; + case GST_RIFF_INFO_IKEY: + type = GST_TAG_KEYWORDS; + break; + case GST_RIFF_INFO_ILGT: + type = NULL; /*"Lightness"; */ + break; + case GST_RIFF_INFO_IMED: + type = NULL; /*"Medium"; */ + break; + case GST_RIFF_INFO_INAM: + type = GST_TAG_TITLE; + break; + case GST_RIFF_INFO_IPLT: + type = NULL; /*"Palette"; */ + break; + case GST_RIFF_INFO_IPRD: + type = NULL; /*"Product"; */ + break; + case GST_RIFF_INFO_ISBJ: + type = NULL; /*"Subject"; */ + break; + case GST_RIFF_INFO_ISFT: + type = GST_TAG_ENCODER; + break; + case GST_RIFF_INFO_ISHP: + type = NULL; /*"Sharpness"; */ + break; + case GST_RIFF_INFO_ISRC: + type = GST_TAG_ISRC; + break; + case GST_RIFF_INFO_ISRF: + type = NULL; /*"Source Form"; */ + break; + case GST_RIFF_INFO_ITCH: + type = NULL; /*"Technician"; */ + break; + default: + type = NULL; + GST_WARNING_OBJECT (element, + "Unknown INFO (metadata) tag entry %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (tag)); + break; + } + + if (type != NULL && data[0] != '\0') { + static const gchar *env_vars[] = { "GST_AVI_TAG_ENCODING", + "GST_RIFF_TAG_ENCODING", "GST_TAG_ENCODING", NULL + }; + gchar *val; + + val = gst_tag_freeform_string_to_utf8 ((gchar *) data, tsize, env_vars); + + if (val) { + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL); + g_free (val); + } else { + GST_WARNING_OBJECT (element, "could not extract %s tag", type); + } + } + + if (tsize & 1) { + tsize++; + if (tsize > size) + tsize = size; + } + + data += tsize; + size -= tsize; + } + + if (!gst_tag_list_is_empty (taglist)) { + *_taglist = taglist; + } else { + *_taglist = NULL; + gst_tag_list_free (taglist); + } + + return; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.h new file mode 100644 index 0000000..cf07dda --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff-read.h @@ -0,0 +1,87 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff-read.h: function declarations for parsing a RIFF file + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_RIFF_READ_H__ +#define __GST_RIFF_READ_H__ + +#include +#include + +#include "riff-ids.h" + +G_BEGIN_DECLS + +/* + * Operate using pull_range(). + */ + +GstFlowReturn gst_riff_read_chunk (GstElement * element, + GstPad * pad, + guint64 * offset, + guint32 * tag, + GstBuffer ** chunk_data); + +/* + * These functions operate on provided data (the caller is + * supposed to strip the chunk headers). The buffer is + * provided by the caller, the strf/strh/data are filled in + * by the function. + */ + +gboolean gst_riff_parse_chunk (GstElement * element, + GstBuffer * buf, + guint * offset, + guint32 * fourcc, + GstBuffer ** chunk_data); + +gboolean gst_riff_parse_file_header (GstElement * element, + GstBuffer * buf, + guint32 * doctype); + +gboolean gst_riff_parse_strh (GstElement * element, + GstBuffer * buf, + gst_riff_strh ** strh); + +gboolean gst_riff_parse_strf_vids (GstElement * element, + GstBuffer * buf, + gst_riff_strf_vids ** strf, + GstBuffer ** data); +gboolean gst_riff_parse_strf_auds (GstElement * element, + GstBuffer * buf, + gst_riff_strf_auds ** strf, + GstBuffer ** data); +gboolean gst_riff_parse_strf_iavs (GstElement * element, + GstBuffer * buf, + gst_riff_strf_iavs ** strf, + GstBuffer ** data); + +void gst_riff_parse_info (GstElement * element, + GstBuffer * buf, + GstTagList ** taglist); + +/* + * Init. + */ +void gst_riff_init (void); + +G_END_DECLS + +#endif /* __GST_RIFF_READ_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.c new file mode 100644 index 0000000..d14b32a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.c @@ -0,0 +1,48 @@ +/* GStreamer RIFF I/O + * Copyright (C) 2003 Ronald Bultje + * + * riff.c: library initialisation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstriff + * @short_description: Riff fileformat utillity functions. + * + * A collection of functions to handle riff base files, such as avi, wav and + * asf. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "riff-read.h" + +GST_DEBUG_CATEGORY (riff_debug); + +/** + * gst_riff_init: + * + * Initialize riff library. + */ +void +gst_riff_init (void) +{ + GST_DEBUG_CATEGORY_INIT (riff_debug, "riff", 0, "RIFF I/O"); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.def b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.def new file mode 100644 index 0000000..c6ea208 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.def @@ -0,0 +1,27 @@ +EXPORTS + gst_plugin_desc + gst_riff_read_get_type + gst_riff_read_element_data + gst_riff_create_video_template_caps + gst_riff_create_video_caps + gst_riff_create_video_caps_with_data + gst_riff_create_audio_template_caps + gst_riff_create_audio_caps + gst_riff_create_audio_caps_with_data + gst_riff_create_iavs_template_caps + gst_riff_create_iavs_caps + gst_riff_read_header + gst_riff_read_data + gst_riff_read_seek + gst_riff_read_skip + gst_riff_read_info + gst_riff_read_list + gst_riff_read_ascii + gst_riff_read_strh + gst_riff_read_strf_iavs + gst_riff_read_strf_auds + gst_riff_read_strf_auds_with_data + gst_riff_read_strf_vids_with_data + gst_riff_peek_tag + gst_riff_peek_list + gst_riff_peek_head diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.vcproj b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.vcproj new file mode 100644 index 0000000..dde87c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/riff/riff.vcproj @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/Makefile.am new file mode 100644 index 0000000..5e327ae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/Makefile.am @@ -0,0 +1,85 @@ +libgstrtpincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/rtp + +libgstrtpinclude_HEADERS = gstrtpbuffer.h \ + gstrtcpbuffer.h \ + gstrtppayloads.h \ + gstbasertpaudiopayload.h \ + gstbasertppayload.h \ + gstbasertpdepayload.h + +lib_LTLIBRARIES = libgstrtp-@GST_MAJORMINOR@.la + +libgstrtp_@GST_MAJORMINOR@_la_SOURCES = gstrtpbuffer.c \ + gstrtcpbuffer.c \ + gstrtppayloads.c \ + gstbasertpaudiopayload.c \ + gstbasertppayload.c \ + gstbasertpdepayload.c + +libgstrtp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtp_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) +libgstrtp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstRtp-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstrtpinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstrtp_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/rtp/%',$(libgstrtpinclude_HEADERS)) + +GstRtp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstrtp-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstRtp \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstrtp-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-rtp-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstrtp -:SHARED libgstrtp-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstrtp_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtp_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstrtp_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstrtp_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/rtp \ + -:HEADERS $(libgstrtp_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/README b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/README new file mode 100644 index 0000000..77253b7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/README @@ -0,0 +1,66 @@ +The RTP libraries +--------------------- + + RTP Buffers + ----------- + The real time protocol as described in RFC 3550 requires the use of special + packets containing an additional RTP header of at least 12 bytes. GStreamer + provides some helper functions for creating and parsing these RTP headers. + The result is a normal #GstBuffer with an additional RTP header. + + RTP buffers are usually created with gst_rtp_buffer_new_allocate() or + gst_rtp_buffer_new_allocate_len(). These functions create buffers with a + preallocated space of memory. It will also ensure that enough memory + is allocated for the RTP header. The first function is used when the payload + size is known. gst_rtp_buffer_new_allocate_len() should be used when the size + of the whole RTP buffer (RTP header + payload) is known. + + When receiving RTP buffers from a network, gst_rtp_buffer_new_take_data() + should be used when the user would like to parse that RTP packet. (TODO Ask + Wim what the real purpose of this function is as it seems to simply create a + duplicate GstBuffer with the same data as the previous one). The + function will create a new RTP buffer with the given data as the whole RTP + packet. Alternatively, gst_rtp_buffer_new_copy_data() can be used if the user + wishes to make a copy of the data before using it in the new RTP buffer. An + important function is gst_rtp_buffer_validate() that is used to verify that + the buffer a well formed RTP buffer. + + It is now possible to use all the gst_rtp_buffer_get_*() or + gst_rtp_buffer_set_*() functions to read or write the different parts of the + RTP header such as the payload type, the sequence number or the RTP + timestamp. The use can also retreive a pointer to the actual RTP payload data + using the gst_rtp_buffer_get_payload() function. + + RTP Base Payloader Class (GstBaseRTPPayload) + -------------------------------------------- + + All RTP payloader elements (audio or video) should derive from this class. + + RTP Base Audio Payloader Class (GstBaseRTPAudioPayload) + ------------------------------------------------------- + + This base class can be tested through it's children classes. Here is an + example using the iLBC payloader (frame based). + + For 20ms mode : + + GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2 + sizemax=114 datarate=1900 ! audio/x-iLBC, mode=20 ! rtpilbcpay + max-ptime="40000000" ! fakesink + + For 30ms mode : + + GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2 + sizemax=150 datarate=1662 ! audio/x-iLBC, mode=30 ! rtpilbcpay + max-ptime="60000000" ! fakesink + + Here is an example using the uLaw payloader (sample based). + + GST_DEBUG="basertpaudiopayload:5" gst-launch-0.10 fakesrc sizetype=2 + sizemax=150 datarate=8000 ! audio/x-mulaw ! rtppcmupay max-ptime="6000000" ! + fakesink + + RTP Base Depayloader Class (GstBaseRTPDepayload) + ------------------------------------------------ + + All RTP depayloader elements (audio or video) should derive from this class. diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.c new file mode 100644 index 0000000..d8ba21b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.c @@ -0,0 +1,992 @@ +/* GStreamer + * Copyright (C) <2006> Philippe Khalaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstbasertpaudiopayload + * @short_description: Base class for audio RTP payloader + * + * + * + * Provides a base class for audio RTP payloaders for frame or sample based + * audio codecs (constant bitrate) + * + * + * This class derives from GstBaseRTPPayload. It can be used for payloading + * audio codecs. It will only work with constant bitrate codecs. It supports + * both frame based and sample based codecs. It takes care of packing up the + * audio data into RTP packets and filling up the headers accordingly. The + * payloading is done based on the maximum MTU (mtu) and the maximum time per + * packet (max-ptime). The general idea is to divide large data buffers into + * smaller RTP packets. The RTP packet size is the minimum of either the MTU, + * max-ptime (if set) or available data. The RTP packet size is always larger or + * equal to min-ptime (if set). If min-ptime is not set, any residual data is + * sent in a last RTP packet. In the case of frame based codecs, the resulting + * RTP packets always contain full frames. + * + * Usage + * + * To use this base class, your child element needs to call either + * gst_base_rtp_audio_payload_set_frame_based() or + * gst_base_rtp_audio_payload_set_sample_based(). This is usually done in the + * element's _init() function. Then, the child element must call either + * gst_base_rtp_audio_payload_set_frame_options(), + * gst_base_rtp_audio_payload_set_sample_options() or + * gst_base_rtp_audio_payload_set_samplebits_options. Since + * GstBaseRTPAudioPayload derives from GstBaseRTPPayload, the child element + * must set any variables or call/override any functions required by that base + * class. The child element does not need to override any other functions + * specific to GstBaseRTPAudioPayload. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gstbasertpaudiopayload.h" + +GST_DEBUG_CATEGORY_STATIC (basertpaudiopayload_debug); +#define GST_CAT_DEFAULT (basertpaudiopayload_debug) + +#define DEFAULT_BUFFER_LIST FALSE + +enum +{ + PROP_0, + PROP_BUFFER_LIST, + PROP_LAST +}; + +/* function to convert bytes to a time */ +typedef GstClockTime (*GetBytesToTimeFunc) (GstBaseRTPAudioPayload * payload, + guint64 bytes); +/* function to convert bytes to a RTP time */ +typedef guint32 (*GetBytesToRTPTimeFunc) (GstBaseRTPAudioPayload * payload, + guint64 bytes); +/* function to convert time to bytes */ +typedef guint64 (*GetTimeToBytesFunc) (GstBaseRTPAudioPayload * payload, + GstClockTime time); + +struct _GstBaseRTPAudioPayloadPrivate +{ + GetBytesToTimeFunc bytes_to_time; + GetBytesToRTPTimeFunc bytes_to_rtptime; + GetTimeToBytesFunc time_to_bytes; + + GstAdapter *adapter; + guint fragment_size; + GstClockTime frame_duration_ns; + gboolean discont; + guint64 offset; + GstClockTime last_timestamp; + guint32 last_rtptime; + guint align; + + guint cached_mtu; + guint cached_min_ptime; + guint cached_max_ptime; + guint cached_ptime; + guint cached_min_length; + guint cached_max_length; + guint cached_ptime_multiple; + guint cached_align; + + gboolean buffer_list; +}; + + +#define GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), GST_TYPE_BASE_RTP_AUDIO_PAYLOAD, \ + GstBaseRTPAudioPayloadPrivate)) + +static void gst_base_rtp_audio_payload_finalize (GObject * object); + +static void gst_base_rtp_audio_payload_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_base_rtp_audio_payload_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +/* bytes to time functions */ +static GstClockTime +gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload * + payload, guint64 bytes); +static GstClockTime +gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload * + payload, guint64 bytes); + +/* bytes to RTP time functions */ +static guint32 +gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload * + payload, guint64 bytes); +static guint32 +gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload * + payload, guint64 bytes); + +/* time to bytes functions */ +static guint64 +gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload * + payload, GstClockTime time); +static guint64 +gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload * + payload, GstClockTime time); + +static GstFlowReturn gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload + * payload, GstBuffer * buffer); + +static GstStateChangeReturn gst_base_rtp_payload_audio_change_state (GstElement + * element, GstStateChange transition); + +static gboolean gst_base_rtp_payload_audio_handle_event (GstPad * pad, + GstEvent * event); + +GST_BOILERPLATE (GstBaseRTPAudioPayload, gst_base_rtp_audio_payload, + GstBaseRTPPayload, GST_TYPE_BASE_RTP_PAYLOAD); + +static void +gst_base_rtp_audio_payload_base_init (gpointer klass) +{ +} + +static void +gst_base_rtp_audio_payload_class_init (GstBaseRTPAudioPayloadClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseRTPPayloadClass *gstbasertppayload_class; + + g_type_class_add_private (klass, sizeof (GstBaseRTPAudioPayloadPrivate)); + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasertppayload_class = (GstBaseRTPPayloadClass *) klass; + + gobject_class->finalize = gst_base_rtp_audio_payload_finalize; + gobject_class->set_property = gst_base_rtp_audio_payload_set_property; + gobject_class->get_property = gst_base_rtp_audio_payload_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_BUFFER_LIST, + g_param_spec_boolean ("buffer-list", "Buffer List", + "Use Buffer Lists", + DEFAULT_BUFFER_LIST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_change_state); + + gstbasertppayload_class->handle_buffer = + GST_DEBUG_FUNCPTR (gst_base_rtp_audio_payload_handle_buffer); + gstbasertppayload_class->handle_event = + GST_DEBUG_FUNCPTR (gst_base_rtp_payload_audio_handle_event); + + GST_DEBUG_CATEGORY_INIT (basertpaudiopayload_debug, "basertpaudiopayload", 0, + "base audio RTP payloader"); +} + +static void +gst_base_rtp_audio_payload_init (GstBaseRTPAudioPayload * payload, + GstBaseRTPAudioPayloadClass * klass) +{ + payload->priv = GST_BASE_RTP_AUDIO_PAYLOAD_GET_PRIVATE (payload); + + /* these need to be set by child object if frame based */ + payload->frame_size = 0; + payload->frame_duration = 0; + + /* these need to be set by child object if sample based */ + payload->sample_size = 0; + + payload->priv->adapter = gst_adapter_new (); + + payload->priv->buffer_list = DEFAULT_BUFFER_LIST; +} + +static void +gst_base_rtp_audio_payload_finalize (GObject * object) +{ + GstBaseRTPAudioPayload *payload; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD (object); + + g_object_unref (payload->priv->adapter); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_base_rtp_audio_payload_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstBaseRTPAudioPayload *payload; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD (object); + + switch (prop_id) { + case PROP_BUFFER_LIST: + payload->priv->buffer_list = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_rtp_audio_payload_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstBaseRTPAudioPayload *payload; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD (object); + + switch (prop_id) { + case PROP_BUFFER_LIST: + g_value_set_boolean (value, payload->priv->buffer_list); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/** + * gst_base_rtp_audio_payload_set_frame_based: + * @basertpaudiopayload: a pointer to the element. + * + * Tells #GstBaseRTPAudioPayload that the child element is for a frame based + * audio codec + */ +void +gst_base_rtp_audio_payload_set_frame_based (GstBaseRTPAudioPayload * + basertpaudiopayload) +{ + g_return_if_fail (basertpaudiopayload != NULL); + g_return_if_fail (basertpaudiopayload->priv->time_to_bytes == NULL); + g_return_if_fail (basertpaudiopayload->priv->bytes_to_time == NULL); + g_return_if_fail (basertpaudiopayload->priv->bytes_to_rtptime == NULL); + + basertpaudiopayload->priv->bytes_to_time = + gst_base_rtp_audio_payload_frame_bytes_to_time; + basertpaudiopayload->priv->bytes_to_rtptime = + gst_base_rtp_audio_payload_frame_bytes_to_rtptime; + basertpaudiopayload->priv->time_to_bytes = + gst_base_rtp_audio_payload_frame_time_to_bytes; +} + +/** + * gst_base_rtp_audio_payload_set_sample_based: + * @basertpaudiopayload: a pointer to the element. + * + * Tells #GstBaseRTPAudioPayload that the child element is for a sample based + * audio codec + */ +void +gst_base_rtp_audio_payload_set_sample_based (GstBaseRTPAudioPayload * + basertpaudiopayload) +{ + g_return_if_fail (basertpaudiopayload != NULL); + g_return_if_fail (basertpaudiopayload->priv->time_to_bytes == NULL); + g_return_if_fail (basertpaudiopayload->priv->bytes_to_time == NULL); + g_return_if_fail (basertpaudiopayload->priv->bytes_to_rtptime == NULL); + + basertpaudiopayload->priv->bytes_to_time = + gst_base_rtp_audio_payload_sample_bytes_to_time; + basertpaudiopayload->priv->bytes_to_rtptime = + gst_base_rtp_audio_payload_sample_bytes_to_rtptime; + basertpaudiopayload->priv->time_to_bytes = + gst_base_rtp_audio_payload_sample_time_to_bytes; +} + +/** + * gst_base_rtp_audio_payload_set_frame_options: + * @basertpaudiopayload: a pointer to the element. + * @frame_duration: The duraction of an audio frame in milliseconds. + * @frame_size: The size of an audio frame in bytes. + * + * Sets the options for frame based audio codecs. + * + */ +void +gst_base_rtp_audio_payload_set_frame_options (GstBaseRTPAudioPayload + * basertpaudiopayload, gint frame_duration, gint frame_size) +{ + GstBaseRTPAudioPayloadPrivate *priv; + + g_return_if_fail (basertpaudiopayload != NULL); + + priv = basertpaudiopayload->priv; + + basertpaudiopayload->frame_duration = frame_duration; + priv->frame_duration_ns = frame_duration * GST_MSECOND; + basertpaudiopayload->frame_size = frame_size; + priv->align = frame_size; + + gst_adapter_clear (priv->adapter); + + GST_DEBUG_OBJECT (basertpaudiopayload, "frame set to %d ms and size %d", + frame_duration, frame_size); +} + +/** + * gst_base_rtp_audio_payload_set_sample_options: + * @basertpaudiopayload: a pointer to the element. + * @sample_size: Size per sample in bytes. + * + * Sets the options for sample based audio codecs. + */ +void +gst_base_rtp_audio_payload_set_sample_options (GstBaseRTPAudioPayload + * basertpaudiopayload, gint sample_size) +{ + g_return_if_fail (basertpaudiopayload != NULL); + + /* sample_size is in bits internally */ + gst_base_rtp_audio_payload_set_samplebits_options (basertpaudiopayload, + sample_size * 8); +} + +/** + * gst_base_rtp_audio_payload_set_samplebits_options: + * @basertpaudiopayload: a pointer to the element. + * @sample_size: Size per sample in bits. + * + * Sets the options for sample based audio codecs. + * + * Since: 0.10.18 + */ +void +gst_base_rtp_audio_payload_set_samplebits_options (GstBaseRTPAudioPayload + * basertpaudiopayload, gint sample_size) +{ + guint fragment_size; + GstBaseRTPAudioPayloadPrivate *priv; + + g_return_if_fail (basertpaudiopayload != NULL); + + priv = basertpaudiopayload->priv; + + basertpaudiopayload->sample_size = sample_size; + + /* sample_size is in bits and is converted into multiple bytes */ + fragment_size = sample_size; + while ((fragment_size % 8) != 0) + fragment_size += fragment_size; + priv->fragment_size = fragment_size / 8; + priv->align = priv->fragment_size; + + gst_adapter_clear (priv->adapter); + + GST_DEBUG_OBJECT (basertpaudiopayload, + "Samplebits set to sample size %d bits", sample_size); +} + +static void +gst_base_rtp_audio_payload_set_meta (GstBaseRTPAudioPayload * payload, + GstBuffer * buffer, guint payload_len, GstClockTime timestamp) +{ + GstBaseRTPPayload *basepayload; + GstBaseRTPAudioPayloadPrivate *priv; + + basepayload = GST_BASE_RTP_PAYLOAD_CAST (payload); + priv = payload->priv; + + /* set payload type */ + gst_rtp_buffer_set_payload_type (buffer, basepayload->pt); + /* set marker bit for disconts */ + if (priv->discont) { + GST_DEBUG_OBJECT (payload, "Setting marker and DISCONT"); + gst_rtp_buffer_set_marker (buffer, TRUE); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + priv->discont = FALSE; + } + GST_BUFFER_TIMESTAMP (buffer) = timestamp; + + /* get the offset in RTP time */ + GST_BUFFER_OFFSET (buffer) = priv->bytes_to_rtptime (payload, priv->offset); + + priv->offset += payload_len; + + /* Set the duration from the size */ + GST_BUFFER_DURATION (buffer) = priv->bytes_to_time (payload, payload_len); + + /* remember the last rtptime/timestamp pair. We will use this to realign our + * RTP timestamp after a buffer discont */ + priv->last_rtptime = GST_BUFFER_OFFSET (buffer); + priv->last_timestamp = timestamp; +} + +/** + * gst_base_rtp_audio_payload_push: + * @baseaudiopayload: a #GstBaseRTPPayload + * @data: data to set as payload + * @payload_len: length of payload + * @timestamp: a #GstClockTime + * + * Create an RTP buffer and store @payload_len bytes of @data as the + * payload. Set the timestamp on the new buffer to @timestamp before pushing + * the buffer downstream. + * + * Returns: a #GstFlowReturn + * + * Since: 0.10.13 + */ +GstFlowReturn +gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload, + const guint8 * data, guint payload_len, GstClockTime timestamp) +{ + GstBaseRTPPayload *basepayload; + GstBuffer *outbuf; + guint8 *payload; + GstFlowReturn ret; + + basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload); + + GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT, + payload_len, GST_TIME_ARGS (timestamp)); + + /* create buffer to hold the payload */ + outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); + + /* copy payload */ + payload = gst_rtp_buffer_get_payload (outbuf); + memcpy (payload, data, payload_len); + + /* set metadata */ + gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len, + timestamp); + + ret = gst_basertppayload_push (basepayload, outbuf); + + return ret; +} + +static GstFlowReturn +gst_base_rtp_audio_payload_push_buffer (GstBaseRTPAudioPayload * + baseaudiopayload, GstBuffer * buffer, GstClockTime timestamp) +{ + GstBaseRTPPayload *basepayload; + GstBaseRTPAudioPayloadPrivate *priv; + GstBuffer *outbuf; + guint8 *payload; + guint payload_len; + GstFlowReturn ret; + + priv = baseaudiopayload->priv; + basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload); + + payload_len = GST_BUFFER_SIZE (buffer); + + GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT, + payload_len, GST_TIME_ARGS (timestamp)); + + if (priv->buffer_list) { + /* create just the RTP header buffer */ + outbuf = gst_rtp_buffer_new_allocate (0, 0, 0); + } else { + /* create buffer to hold the payload */ + outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); + } + + /* set metadata */ + gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len, + timestamp); + + if (priv->buffer_list) { + GstBufferList *list; + GstBufferListIterator *it; + + list = gst_buffer_list_new (); + it = gst_buffer_list_iterate (list); + + /* add both buffers to the buffer list */ + gst_buffer_list_iterator_add_group (it); + gst_buffer_list_iterator_add (it, outbuf); + gst_buffer_list_iterator_add (it, buffer); + + gst_buffer_list_iterator_free (it); + + GST_DEBUG_OBJECT (baseaudiopayload, "Pushing list %p", list); + ret = gst_basertppayload_push_list (basepayload, list); + } else { + /* copy payload */ + payload = gst_rtp_buffer_get_payload (outbuf); + memcpy (payload, GST_BUFFER_DATA (buffer), payload_len); + gst_buffer_unref (buffer); + + GST_DEBUG_OBJECT (baseaudiopayload, "Pushing buffer %p", outbuf); + ret = gst_basertppayload_push (basepayload, outbuf); + } + + return ret; +} + +/** + * gst_base_rtp_audio_payload_flush: + * @baseaudiopayload: a #GstBaseRTPPayload + * @payload_len: length of payload + * @timestamp: a #GstClockTime + * + * Create an RTP buffer and store @payload_len bytes of the adapter as the + * payload. Set the timestamp on the new buffer to @timestamp before pushing + * the buffer downstream. + * + * If @payload_len is -1, all pending bytes will be flushed. If @timestamp is + * -1, the timestamp will be calculated automatically. + * + * Returns: a #GstFlowReturn + * + * Since: 0.10.25 + */ +GstFlowReturn +gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload, + guint payload_len, GstClockTime timestamp) +{ + GstBaseRTPPayload *basepayload; + GstBaseRTPAudioPayloadPrivate *priv; + GstBuffer *outbuf; + guint8 *payload; + GstFlowReturn ret; + GstAdapter *adapter; + guint64 distance; + + priv = baseaudiopayload->priv; + adapter = priv->adapter; + + basepayload = GST_BASE_RTP_PAYLOAD (baseaudiopayload); + + if (payload_len == -1) + payload_len = gst_adapter_available (adapter); + + /* nothing to do, just return */ + if (payload_len == 0) + return GST_FLOW_OK; + + if (timestamp == -1) { + /* calculate the timestamp */ + timestamp = gst_adapter_prev_timestamp (adapter, &distance); + + GST_LOG_OBJECT (baseaudiopayload, + "last timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, + GST_TIME_ARGS (timestamp), distance); + + if (GST_CLOCK_TIME_IS_VALID (timestamp) && distance > 0) { + /* convert the number of bytes since the last timestamp to time and add to + * the last seen timestamp */ + timestamp += priv->bytes_to_time (baseaudiopayload, distance); + } + } + + GST_DEBUG_OBJECT (baseaudiopayload, "Pushing %d bytes ts %" GST_TIME_FORMAT, + payload_len, GST_TIME_ARGS (timestamp)); + + if (priv->buffer_list && gst_adapter_available_fast (adapter) >= payload_len) { + GstBuffer *buffer; + /* we can quickly take a buffer out of the adapter without having to copy + * anything. */ + buffer = gst_adapter_take_buffer (adapter, payload_len); + + ret = + gst_base_rtp_audio_payload_push_buffer (baseaudiopayload, buffer, + timestamp); + } else { + /* create buffer to hold the payload */ + outbuf = gst_rtp_buffer_new_allocate (payload_len, 0, 0); + + /* copy payload */ + payload = gst_rtp_buffer_get_payload (outbuf); + gst_adapter_copy (adapter, payload, 0, payload_len); + gst_adapter_flush (adapter, payload_len); + + /* set metadata */ + gst_base_rtp_audio_payload_set_meta (baseaudiopayload, outbuf, payload_len, + timestamp); + + ret = gst_basertppayload_push (basepayload, outbuf); + } + + return ret; +} + +#define ALIGN_DOWN(val,len) ((val) - ((val) % (len))) + +/* calculate the min and max length of a packet. This depends on the configured + * mtu and min/max_ptime values. We cache those so that we don't have to redo + * all the calculations */ +static gboolean +gst_base_rtp_audio_payload_get_lengths (GstBaseRTPPayload * + basepayload, guint * min_payload_len, guint * max_payload_len, + guint * align) +{ + GstBaseRTPAudioPayload *payload; + GstBaseRTPAudioPayloadPrivate *priv; + guint max_mtu, mtu; + guint maxptime_octets; + guint minptime_octets; + guint ptime_mult_octets; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload); + priv = payload->priv; + + if (priv->align == 0) + return FALSE; + + mtu = GST_BASE_RTP_PAYLOAD_MTU (payload); + + /* check cached values */ + if (G_LIKELY (priv->cached_mtu == mtu + && priv->cached_ptime_multiple == + basepayload->abidata.ABI.ptime_multiple + && priv->cached_ptime == basepayload->abidata.ABI.ptime + && priv->cached_max_ptime == basepayload->max_ptime + && priv->cached_min_ptime == basepayload->min_ptime)) { + /* if nothing changed, return cached values */ + *min_payload_len = priv->cached_min_length; + *max_payload_len = priv->cached_max_length; + *align = priv->cached_align; + return TRUE; + } + + ptime_mult_octets = priv->time_to_bytes (payload, + basepayload->abidata.ABI.ptime_multiple); + *align = ALIGN_DOWN (MAX (priv->align, ptime_mult_octets), priv->align); + + /* ptime max */ + if (basepayload->max_ptime != -1) { + maxptime_octets = priv->time_to_bytes (payload, basepayload->max_ptime); + } else { + maxptime_octets = G_MAXUINT; + } + /* MTU max */ + max_mtu = gst_rtp_buffer_calc_payload_len (mtu, 0, 0); + /* round down to alignment */ + max_mtu = ALIGN_DOWN (max_mtu, *align); + + /* combine max ptime and max payload length */ + *max_payload_len = MIN (max_mtu, maxptime_octets); + + /* min number of bytes based on a given ptime */ + minptime_octets = priv->time_to_bytes (payload, basepayload->min_ptime); + /* must be at least one frame size */ + *min_payload_len = MAX (minptime_octets, *align); + + if (*min_payload_len > *max_payload_len) + *min_payload_len = *max_payload_len; + + /* If the ptime is specified in the caps, tried to adhere to it exactly */ + if (basepayload->abidata.ABI.ptime) { + guint ptime_in_bytes = priv->time_to_bytes (payload, + basepayload->abidata.ABI.ptime); + + /* clip to computed min and max lengths */ + ptime_in_bytes = MAX (*min_payload_len, ptime_in_bytes); + ptime_in_bytes = MIN (*max_payload_len, ptime_in_bytes); + + *min_payload_len = *max_payload_len = ptime_in_bytes; + } + + /* cache values */ + priv->cached_mtu = mtu; + priv->cached_ptime = basepayload->abidata.ABI.ptime; + priv->cached_min_ptime = basepayload->min_ptime; + priv->cached_max_ptime = basepayload->max_ptime; + priv->cached_ptime_multiple = basepayload->abidata.ABI.ptime_multiple; + priv->cached_min_length = *min_payload_len; + priv->cached_max_length = *max_payload_len; + priv->cached_align = *align; + + return TRUE; +} + +/* frame conversions functions */ +static GstClockTime +gst_base_rtp_audio_payload_frame_bytes_to_time (GstBaseRTPAudioPayload * + payload, guint64 bytes) +{ + guint64 framecount; + + framecount = bytes / payload->frame_size; + if (G_UNLIKELY (bytes % payload->frame_size)) + framecount++; + + return framecount * payload->priv->frame_duration_ns; +} + +static guint32 +gst_base_rtp_audio_payload_frame_bytes_to_rtptime (GstBaseRTPAudioPayload * + payload, guint64 bytes) +{ + guint64 framecount; + guint64 time; + + framecount = bytes / payload->frame_size; + if (G_UNLIKELY (bytes % payload->frame_size)) + framecount++; + + time = framecount * payload->priv->frame_duration_ns; + + return gst_util_uint64_scale_int (time, + GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND); +} + +static guint64 +gst_base_rtp_audio_payload_frame_time_to_bytes (GstBaseRTPAudioPayload * + payload, GstClockTime time) +{ + return gst_util_uint64_scale (time, payload->frame_size, + payload->priv->frame_duration_ns); +} + +/* sample conversion functions */ +static GstClockTime +gst_base_rtp_audio_payload_sample_bytes_to_time (GstBaseRTPAudioPayload * + payload, guint64 bytes) +{ + guint64 rtptime; + + /* avoid division when we can */ + if (G_LIKELY (payload->sample_size != 8)) + rtptime = gst_util_uint64_scale_int (bytes, 8, payload->sample_size); + else + rtptime = bytes; + + return gst_util_uint64_scale_int (rtptime, GST_SECOND, + GST_BASE_RTP_PAYLOAD (payload)->clock_rate); +} + +static guint32 +gst_base_rtp_audio_payload_sample_bytes_to_rtptime (GstBaseRTPAudioPayload * + payload, guint64 bytes) +{ + /* avoid division when we can */ + if (G_LIKELY (payload->sample_size != 8)) + return gst_util_uint64_scale_int (bytes, 8, payload->sample_size); + else + return bytes; +} + +static guint64 +gst_base_rtp_audio_payload_sample_time_to_bytes (GstBaseRTPAudioPayload * + payload, guint64 time) +{ + guint64 samples; + + samples = gst_util_uint64_scale_int (time, + GST_BASE_RTP_PAYLOAD (payload)->clock_rate, GST_SECOND); + + /* avoid multiplication when we can */ + if (G_LIKELY (payload->sample_size != 8)) + return gst_util_uint64_scale_int (samples, payload->sample_size, 8); + else + return samples; +} + +static GstFlowReturn +gst_base_rtp_audio_payload_handle_buffer (GstBaseRTPPayload * + basepayload, GstBuffer * buffer) +{ + GstBaseRTPAudioPayload *payload; + GstBaseRTPAudioPayloadPrivate *priv; + guint payload_len; + GstFlowReturn ret; + guint available; + guint min_payload_len; + guint max_payload_len; + guint align; + guint size; + gboolean discont; + GstClockTime timestamp; + + ret = GST_FLOW_OK; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD_CAST (basepayload); + priv = payload->priv; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + discont = GST_BUFFER_IS_DISCONT (buffer); + if (discont) { + + GST_DEBUG_OBJECT (payload, "Got DISCONT"); + /* flush everything out of the adapter, mark DISCONT */ + ret = gst_base_rtp_audio_payload_flush (payload, -1, -1); + priv->discont = TRUE; + + /* get the distance between the timestamp gap and produce the same gap in + * the RTP timestamps */ + if (priv->last_timestamp != -1 && timestamp != -1) { + /* we had a last timestamp, compare it to the new timestamp and update the + * offset counter for RTP timestamps. The effect is that we will produce + * output buffers containing the same RTP timestamp gap as the gap + * between the GST timestamps. */ + if (timestamp > priv->last_timestamp) { + GstClockTime diff; + guint64 bytes; + /* we're only going to apply a positive gap, otherwise we let the marker + * bit do its thing. simply convert to bytes and add the the current + * offset */ + diff = timestamp - priv->last_timestamp; + bytes = priv->time_to_bytes (payload, diff); + priv->offset += bytes; + + GST_DEBUG_OBJECT (payload, + "elapsed time %" GST_TIME_FORMAT ", bytes %" G_GUINT64_FORMAT + ", new offset %" G_GUINT64_FORMAT, GST_TIME_ARGS (diff), bytes, + priv->offset); + } + } + } + + if (!gst_base_rtp_audio_payload_get_lengths (basepayload, &min_payload_len, + &max_payload_len, &align)) + goto config_error; + + GST_DEBUG_OBJECT (payload, + "Calculated min_payload_len %u and max_payload_len %u", + min_payload_len, max_payload_len); + + size = GST_BUFFER_SIZE (buffer); + + /* shortcut, we don't need to use the adapter when the packet can be pushed + * through directly. */ + available = gst_adapter_available (priv->adapter); + + GST_DEBUG_OBJECT (payload, "got buffer size %u, available %u", + size, available); + + if (available == 0 && (size >= min_payload_len && size <= max_payload_len) && + (size % align == 0)) { + /* If buffer fits on an RTP packet, let's just push it through + * this will check against max_ptime and max_mtu */ + GST_DEBUG_OBJECT (payload, "Fast packet push"); + ret = gst_base_rtp_audio_payload_push_buffer (payload, buffer, timestamp); + } else { + /* push the buffer in the adapter */ + gst_adapter_push (priv->adapter, buffer); + available += size; + + GST_DEBUG_OBJECT (payload, "available now %u", available); + + /* as long as we have full frames */ + while (available >= min_payload_len) { + /* get multiple of alignment */ + payload_len = MIN (max_payload_len, available); + payload_len = ALIGN_DOWN (payload_len, align); + + /* and flush out the bytes from the adapter, automatically set the + * timestamp. */ + ret = gst_base_rtp_audio_payload_flush (payload, payload_len, -1); + + available -= payload_len; + GST_DEBUG_OBJECT (payload, "available after push %u", available); + } + } + return ret; + + /* ERRORS */ +config_error: + { + GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL), + ("subclass did not configure us properly")); + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } +} + +static GstStateChangeReturn +gst_base_rtp_payload_audio_change_state (GstElement * element, + GstStateChange transition) +{ + GstBaseRTPAudioPayload *basertppayload; + GstStateChangeReturn ret; + + basertppayload = GST_BASE_RTP_AUDIO_PAYLOAD (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + basertppayload->priv->cached_mtu = -1; + basertppayload->priv->last_rtptime = -1; + basertppayload->priv->last_timestamp = -1; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_adapter_clear (basertppayload->priv->adapter); + break; + default: + break; + } + + return ret; +} + +static gboolean +gst_base_rtp_payload_audio_handle_event (GstPad * pad, GstEvent * event) +{ + GstBaseRTPAudioPayload *payload; + gboolean res = FALSE; + + payload = GST_BASE_RTP_AUDIO_PAYLOAD (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + /* flush remaining bytes in the adapter */ + gst_base_rtp_audio_payload_flush (payload, -1, -1); + break; + case GST_EVENT_FLUSH_STOP: + gst_adapter_clear (payload->priv->adapter); + break; + default: + break; + } + + gst_object_unref (payload); + + /* return FALSE to let parent handle the remainder of the event */ + return res; +} + +/** + * gst_base_rtp_audio_payload_get_adapter: + * @basertpaudiopayload: a #GstBaseRTPAudioPayload + * + * Gets the internal adapter used by the depayloader. + * + * Returns: a #GstAdapter. + * + * Since: 0.10.13 + */ +GstAdapter * +gst_base_rtp_audio_payload_get_adapter (GstBaseRTPAudioPayload + * basertpaudiopayload) +{ + GstAdapter *adapter; + + if ((adapter = basertpaudiopayload->priv->adapter)) + g_object_ref (adapter); + + return adapter; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.h new file mode 100644 index 0000000..3fdb488 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpaudiopayload.h @@ -0,0 +1,98 @@ +/* GStreamer + * Copyright (C) <2006> Philippe Khalaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_BASE_RTP_AUDIO_PAYLOAD_H__ +#define __GST_BASE_RTP_AUDIO_PAYLOAD_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstBaseRTPAudioPayload GstBaseRTPAudioPayload; +typedef struct _GstBaseRTPAudioPayloadClass GstBaseRTPAudioPayloadClass; + +typedef struct _GstBaseRTPAudioPayloadPrivate GstBaseRTPAudioPayloadPrivate; + +#define GST_TYPE_BASE_RTP_AUDIO_PAYLOAD \ + (gst_base_rtp_audio_payload_get_type()) +#define GST_BASE_RTP_AUDIO_PAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), \ + GST_TYPE_BASE_RTP_AUDIO_PAYLOAD,GstBaseRTPAudioPayload)) +#define GST_BASE_RTP_AUDIO_PAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), \ + GST_TYPE_BASE_RTP_AUDIO_PAYLOAD,GstBaseRTPAudioPayloadClass)) +#define GST_IS_BASE_RTP_AUDIO_PAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_RTP_AUDIO_PAYLOAD)) +#define GST_IS_BASE_RTP_AUDIO_PAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_RTP_AUDIO_PAYLOAD)) +#define GST_BASE_RTP_AUDIO_PAYLOAD_CAST(obj) \ + ((GstBaseRTPAudioPayload *) (obj)) + +struct _GstBaseRTPAudioPayload +{ + GstBaseRTPPayload payload; + + GstBaseRTPAudioPayloadPrivate *priv; + + GstClockTime base_ts; + gint frame_size; + gint frame_duration; + + gint sample_size; + + gpointer _gst_reserved[GST_PADDING]; +}; + +struct _GstBaseRTPAudioPayloadClass +{ + GstBaseRTPPayloadClass parent_class; + + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_base_rtp_audio_payload_get_type (void); + +/* configure frame based */ +void gst_base_rtp_audio_payload_set_frame_based (GstBaseRTPAudioPayload *basertpaudiopayload); + +void gst_base_rtp_audio_payload_set_frame_options (GstBaseRTPAudioPayload *basertpaudiopayload, + gint frame_duration, gint frame_size); + +/* configure sample based */ +void gst_base_rtp_audio_payload_set_sample_based (GstBaseRTPAudioPayload *basertpaudiopayload); +void gst_base_rtp_audio_payload_set_sample_options (GstBaseRTPAudioPayload *basertpaudiopayload, + gint sample_size); +void gst_base_rtp_audio_payload_set_samplebits_options (GstBaseRTPAudioPayload *basertpaudiopayload, + gint sample_size); + +/* get the internal adapter */ +GstAdapter* gst_base_rtp_audio_payload_get_adapter (GstBaseRTPAudioPayload *basertpaudiopayload); + +/* push and flushing data */ +GstFlowReturn gst_base_rtp_audio_payload_push (GstBaseRTPAudioPayload * baseaudiopayload, + const guint8 * data, guint payload_len, + GstClockTime timestamp); +GstFlowReturn gst_base_rtp_audio_payload_flush (GstBaseRTPAudioPayload * baseaudiopayload, + guint payload_len, GstClockTime timestamp); + +G_END_DECLS + +#endif /* __GST_BASE_RTP_AUDIO_PAYLOAD_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.c new file mode 100644 index 0000000..978a262 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.c @@ -0,0 +1,806 @@ +/* GStreamer + * Copyright (C) <2005> Philippe Khalaf + * Copyright (C) <2005> Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstbasertpdepayload + * @short_description: Base class for RTP depayloader + * + * + * + * Provides a base class for RTP depayloaders + * + * + */ + +#include "gstbasertpdepayload.h" + +#ifdef GST_DISABLE_DEPRECATED +#define QUEUE_LOCK_INIT(base) (g_static_rec_mutex_init(&base->queuelock)) +#define QUEUE_LOCK_FREE(base) (g_static_rec_mutex_free(&base->queuelock)) +#define QUEUE_LOCK(base) (g_static_rec_mutex_lock(&base->queuelock)) +#define QUEUE_UNLOCK(base) (g_static_rec_mutex_unlock(&base->queuelock)) +#else +/* otherwise it's already been defined in the header (FIXME 0.11)*/ +#endif + +GST_DEBUG_CATEGORY_STATIC (basertpdepayload_debug); +#define GST_CAT_DEFAULT (basertpdepayload_debug) + +#define GST_BASE_RTP_DEPAYLOAD_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_RTP_DEPAYLOAD, GstBaseRTPDepayloadPrivate)) + +struct _GstBaseRTPDepayloadPrivate +{ + GstClockTime npt_start; + GstClockTime npt_stop; + gdouble play_speed; + gdouble play_scale; + + gboolean discont; + GstClockTime timestamp; + GstClockTime duration; + + guint32 next_seqnum; + + gboolean negotiated; +}; + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_QUEUE_DELAY 0 + +enum +{ + PROP_0, + PROP_QUEUE_DELAY, + PROP_LAST +}; + +static void gst_base_rtp_depayload_finalize (GObject * object); +static void gst_base_rtp_depayload_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_base_rtp_depayload_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static gboolean gst_base_rtp_depayload_setcaps (GstPad * pad, GstCaps * caps); +static GstFlowReturn gst_base_rtp_depayload_chain (GstPad * pad, + GstBuffer * in); +static gboolean gst_base_rtp_depayload_handle_sink_event (GstPad * pad, + GstEvent * event); + +static GstStateChangeReturn gst_base_rtp_depayload_change_state (GstElement * + element, GstStateChange transition); + +static void gst_base_rtp_depayload_set_gst_timestamp + (GstBaseRTPDepayload * filter, guint32 rtptime, GstBuffer * buf); +static gboolean gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload * + filter, GstEvent * event); +static gboolean gst_base_rtp_depayload_handle_event (GstBaseRTPDepayload * + filter, GstEvent * event); + +GST_BOILERPLATE (GstBaseRTPDepayload, gst_base_rtp_depayload, GstElement, + GST_TYPE_ELEMENT); + +static void +gst_base_rtp_depayload_base_init (gpointer klass) +{ + /*GstElementClass *element_class = GST_ELEMENT_CLASS (klass); */ +} + +static void +gst_base_rtp_depayload_class_init (GstBaseRTPDepayloadClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = (GstElementClass *) klass; + parent_class = g_type_class_peek_parent (klass); + + g_type_class_add_private (klass, sizeof (GstBaseRTPDepayloadPrivate)); + + gobject_class->finalize = gst_base_rtp_depayload_finalize; + gobject_class->set_property = gst_base_rtp_depayload_set_property; + gobject_class->get_property = gst_base_rtp_depayload_get_property; + + /** + * GstBaseRTPDepayload::queue-delay + * + * Control the amount of packets to buffer. + * + * Deprecated: Use a jitterbuffer or RTP session manager to delay packet + * playback. This property has no effect anymore since 0.10.15. + */ +#ifndef GST_REMOVE_DEPRECATED + g_object_class_install_property (gobject_class, PROP_QUEUE_DELAY, + g_param_spec_uint ("queue-delay", "Queue Delay", + "Amount of ms to queue/buffer, deprecated", 0, G_MAXUINT, + DEFAULT_QUEUE_DELAY, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +#endif + + gstelement_class->change_state = gst_base_rtp_depayload_change_state; + + klass->set_gst_timestamp = gst_base_rtp_depayload_set_gst_timestamp; + klass->packet_lost = gst_base_rtp_depayload_packet_lost; + klass->handle_event = gst_base_rtp_depayload_handle_event; + + GST_DEBUG_CATEGORY_INIT (basertpdepayload_debug, "basertpdepayload", 0, + "Base class for RTP Depayloaders"); +} + +static void +gst_base_rtp_depayload_init (GstBaseRTPDepayload * filter, + GstBaseRTPDepayloadClass * klass) +{ + GstPadTemplate *pad_template; + GstBaseRTPDepayloadPrivate *priv; + + priv = GST_BASE_RTP_DEPAYLOAD_GET_PRIVATE (filter); + filter->priv = priv; + + GST_DEBUG_OBJECT (filter, "init"); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"); + g_return_if_fail (pad_template != NULL); + filter->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_setcaps_function (filter->sinkpad, + gst_base_rtp_depayload_setcaps); + gst_pad_set_chain_function (filter->sinkpad, gst_base_rtp_depayload_chain); + gst_pad_set_event_function (filter->sinkpad, + gst_base_rtp_depayload_handle_sink_event); + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "src"); + g_return_if_fail (pad_template != NULL); + filter->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_use_fixed_caps (filter->srcpad); + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + + filter->queue = g_queue_new (); + filter->queue_delay = DEFAULT_QUEUE_DELAY; + + gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED); +} + +static void +gst_base_rtp_depayload_finalize (GObject * object) +{ + GstBaseRTPDepayload *filter = GST_BASE_RTP_DEPAYLOAD (object); + + g_queue_free (filter->queue); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_base_rtp_depayload_setcaps (GstPad * pad, GstCaps * caps) +{ + GstBaseRTPDepayload *filter; + GstBaseRTPDepayloadClass *bclass; + GstBaseRTPDepayloadPrivate *priv; + gboolean res; + GstStructure *caps_struct; + const GValue *value; + + filter = GST_BASE_RTP_DEPAYLOAD (gst_pad_get_parent (pad)); + priv = filter->priv; + + bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + + GST_DEBUG_OBJECT (filter, "Set caps"); + + caps_struct = gst_caps_get_structure (caps, 0); + + /* get other values for newsegment */ + value = gst_structure_get_value (caps_struct, "npt-start"); + if (value && G_VALUE_HOLDS_UINT64 (value)) + priv->npt_start = g_value_get_uint64 (value); + else + priv->npt_start = 0; + GST_DEBUG_OBJECT (filter, "NPT start %" G_GUINT64_FORMAT, priv->npt_start); + + value = gst_structure_get_value (caps_struct, "npt-stop"); + if (value && G_VALUE_HOLDS_UINT64 (value)) + priv->npt_stop = g_value_get_uint64 (value); + else + priv->npt_stop = -1; + + GST_DEBUG_OBJECT (filter, "NPT stop %" G_GUINT64_FORMAT, priv->npt_stop); + + value = gst_structure_get_value (caps_struct, "play-speed"); + if (value && G_VALUE_HOLDS_DOUBLE (value)) + priv->play_speed = g_value_get_double (value); + else + priv->play_speed = 1.0; + + value = gst_structure_get_value (caps_struct, "play-scale"); + if (value && G_VALUE_HOLDS_DOUBLE (value)) + priv->play_scale = g_value_get_double (value); + else + priv->play_scale = 1.0; + + if (bclass->set_caps) { + res = bclass->set_caps (filter, caps); + if (!res) { + GST_WARNING_OBJECT (filter, "Subclass rejected caps %" GST_PTR_FORMAT, + caps); + } + } else { + res = TRUE; + } + + priv->negotiated = res; + + gst_object_unref (filter); + + return res; +} + +static GstFlowReturn +gst_base_rtp_depayload_chain (GstPad * pad, GstBuffer * in) +{ + GstBaseRTPDepayload *filter; + GstBaseRTPDepayloadPrivate *priv; + GstBaseRTPDepayloadClass *bclass; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *out_buf; + GstClockTime timestamp; + guint16 seqnum; + guint32 rtptime; + gboolean discont; + gint gap; + + filter = GST_BASE_RTP_DEPAYLOAD (GST_OBJECT_PARENT (pad)); + priv = filter->priv; + + /* we must have a setcaps first */ + if (G_UNLIKELY (!priv->negotiated)) + goto not_negotiated; + + /* we must validate, it's possible that this element is plugged right after a + * network receiver and we don't want to operate on invalid data */ + if (G_UNLIKELY (!gst_rtp_buffer_validate (in))) + goto invalid_buffer; + + if (!priv->discont) + priv->discont = GST_BUFFER_IS_DISCONT (in); + + timestamp = GST_BUFFER_TIMESTAMP (in); + /* convert to running_time and save the timestamp, this is the timestamp + * we put on outgoing buffers. */ + timestamp = gst_segment_to_running_time (&filter->segment, GST_FORMAT_TIME, + timestamp); + priv->timestamp = timestamp; + priv->duration = GST_BUFFER_DURATION (in); + + seqnum = gst_rtp_buffer_get_seq (in); + rtptime = gst_rtp_buffer_get_timestamp (in); + discont = FALSE; + + GST_LOG_OBJECT (filter, "discont %d, seqnum %u, rtptime %u, timestamp %" + GST_TIME_FORMAT, priv->discont, seqnum, rtptime, + GST_TIME_ARGS (timestamp)); + + /* Check seqnum. This is a very simple check that makes sure that the seqnums + * are striclty increasing, dropping anything that is out of the ordinary. We + * can only do this when the next_seqnum is known. */ + if (G_LIKELY (priv->next_seqnum != -1)) { + gap = gst_rtp_buffer_compare_seqnum (seqnum, priv->next_seqnum); + + /* if we have no gap, all is fine */ + if (G_UNLIKELY (gap != 0)) { + GST_LOG_OBJECT (filter, "got packet %u, expected %u, gap %d", seqnum, + priv->next_seqnum, gap); + if (gap < 0) { + /* seqnum > next_seqnum, we are missing some packets, this is always a + * DISCONT. */ + GST_LOG_OBJECT (filter, "%d missing packets", gap); + discont = TRUE; + } else { + /* seqnum < next_seqnum, we have seen this packet before or the sender + * could be restarted. If the packet is not too old, we throw it away as + * a duplicate, otherwise we mark discont and continue. 100 misordered + * packets is a good threshold. See also RFC 4737. */ + if (gap < 100) + goto dropping; + + GST_LOG_OBJECT (filter, + "%d > 100, packet too old, sender likely restarted", gap); + discont = TRUE; + } + } + } + priv->next_seqnum = (seqnum + 1) & 0xffff; + + if (G_UNLIKELY (discont && !priv->discont)) { + GST_LOG_OBJECT (filter, "mark DISCONT on input buffer"); + /* we detected a seqnum discont but the buffer was not flagged with a discont, + * set the discont flag so that the subclass can throw away old data. */ + priv->discont = TRUE; + in = gst_buffer_make_metadata_writable (in); + GST_BUFFER_FLAG_SET (in, GST_BUFFER_FLAG_DISCONT); + } + + bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + + if (G_UNLIKELY (bclass->process == NULL)) + goto no_process; + + /* let's send it out to processing */ + out_buf = bclass->process (filter, in); + if (out_buf) { + /* we pass rtptime as backward compatibility, in reality, the incomming + * buffer timestamp is always applied to the outgoing packet. */ + ret = gst_base_rtp_depayload_push_ts (filter, rtptime, out_buf); + } + gst_buffer_unref (in); + + return ret; + + /* ERRORS */ +not_negotiated: + { + /* this is not fatal but should be filtered earlier */ + if (GST_BUFFER_CAPS (in) == NULL) { + GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, + ("No RTP format was negotiated."), + ("Input buffers need to have RTP caps set on them. This is usually " + "achieved by setting the 'caps' property of the upstream source " + "element (often udpsrc or appsrc), or by putting a capsfilter " + "element before the depayloader and setting the 'caps' property " + "on that. Also see http://cgit.freedesktop.org/gstreamer/" + "gst-plugins-good/tree/gst/rtp/README")); + } else { + GST_ELEMENT_ERROR (filter, CORE, NEGOTIATION, + ("No RTP format was negotiated."), + ("RTP caps on input buffer were rejected, most likely because they " + "were incomplete or contained wrong values. Check the debug log " + "for more information.")); + } + gst_buffer_unref (in); + return GST_FLOW_NOT_NEGOTIATED; + } +invalid_buffer: + { + /* this is not fatal but should be filtered earlier */ + GST_ELEMENT_WARNING (filter, STREAM, DECODE, (NULL), + ("Received invalid RTP payload, dropping")); + gst_buffer_unref (in); + return GST_FLOW_OK; + } +dropping: + { + GST_WARNING_OBJECT (filter, "%d <= 100, dropping old packet", gap); + gst_buffer_unref (in); + return GST_FLOW_OK; + } +no_process: + { + /* this is not fatal but should be filtered earlier */ + GST_ELEMENT_ERROR (filter, STREAM, NOT_IMPLEMENTED, (NULL), + ("The subclass does not have a process method")); + gst_buffer_unref (in); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_base_rtp_depayload_handle_event (GstBaseRTPDepayload * filter, + GstEvent * event) +{ + gboolean res = TRUE; + gboolean forward = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&filter->segment, GST_FORMAT_UNDEFINED); + filter->need_newsegment = TRUE; + filter->priv->next_seqnum = -1; + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + GstFormat fmt; + gint64 start, stop, position; + + gst_event_parse_new_segment (event, &update, &rate, &fmt, &start, &stop, + &position); + + gst_segment_set_newsegment (&filter->segment, update, rate, fmt, + start, stop, position); + + /* don't pass the event downstream, we generate our own segment including + * the NTP time and other things we receive in caps */ + forward = FALSE; + break; + } + case GST_EVENT_CUSTOM_DOWNSTREAM: + { + GstBaseRTPDepayloadClass *bclass; + + bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + + if (gst_event_has_name (event, "GstRTPPacketLost")) { + /* we get this event from the jitterbuffer when it considers a packet as + * being lost. We send it to our packet_lost vmethod. The default + * implementation will make time progress by pushing out a NEWSEGMENT + * update event. Subclasses can override and to one of the following: + * - Adjust timestamp/duration to something more accurate before + * calling the parent (default) packet_lost method. + * - do some more advanced error concealing on the already received + * (fragmented) packets. + * - ignore the packet lost. + */ + if (bclass->packet_lost) + res = bclass->packet_lost (filter, event); + forward = FALSE; + } + break; + } + default: + break; + } + + if (forward) + res = gst_pad_push_event (filter->srcpad, event); + else + gst_event_unref (event); + + return res; +} + +static gboolean +gst_base_rtp_depayload_handle_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res = FALSE; + GstBaseRTPDepayload *filter; + GstBaseRTPDepayloadClass *bclass; + + filter = GST_BASE_RTP_DEPAYLOAD (gst_pad_get_parent (pad)); + if (G_UNLIKELY (filter == NULL)) { + gst_event_unref (event); + return FALSE; + } + + bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + if (bclass->handle_event) + res = bclass->handle_event (filter, event); + else + gst_event_unref (event); + + gst_object_unref (filter); + return res; +} + +static GstEvent * +create_segment_event (GstBaseRTPDepayload * filter, gboolean update, + GstClockTime position) +{ + GstEvent *event; + GstClockTime stop; + GstBaseRTPDepayloadPrivate *priv; + + priv = filter->priv; + + if (priv->npt_stop != -1) + stop = priv->npt_stop - priv->npt_start; + else + stop = -1; + + event = gst_event_new_new_segment_full (update, priv->play_speed, + priv->play_scale, GST_FORMAT_TIME, position, stop, + position + priv->npt_start); + + return event; +} + +typedef struct +{ + GstBaseRTPDepayload *depayload; + GstBaseRTPDepayloadClass *bclass; + GstCaps *caps; + gboolean do_ts; + gboolean rtptime; +} HeaderData; + +static GstBufferListItem +set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data) +{ + GstBaseRTPDepayload *depayload = data->depayload; + + *buffer = gst_buffer_make_metadata_writable (*buffer); + gst_buffer_set_caps (*buffer, data->caps); + + /* set the timestamp if we must and can */ + if (data->bclass->set_gst_timestamp && data->do_ts) + data->bclass->set_gst_timestamp (depayload, data->rtptime, *buffer); + + if (G_UNLIKELY (depayload->priv->discont)) { + GST_LOG_OBJECT (depayload, "Marking DISCONT on output buffer"); + GST_BUFFER_FLAG_SET (*buffer, GST_BUFFER_FLAG_DISCONT); + depayload->priv->discont = FALSE; + } + + return GST_BUFFER_LIST_SKIP_GROUP; +} + +static GstFlowReturn +gst_base_rtp_depayload_prepare_push (GstBaseRTPDepayload * filter, + gboolean do_ts, guint32 rtptime, gboolean is_list, gpointer obj) +{ + HeaderData data; + + data.depayload = filter; + data.caps = GST_PAD_CAPS (filter->srcpad); + data.rtptime = rtptime; + data.do_ts = do_ts; + data.bclass = GST_BASE_RTP_DEPAYLOAD_GET_CLASS (filter); + + if (is_list) { + GstBufferList **blist = obj; + gst_buffer_list_foreach (*blist, (GstBufferListFunc) set_headers, &data); + } else { + GstBuffer **buf = obj; + set_headers (buf, 0, 0, &data); + } + + /* if this is the first buffer send a NEWSEGMENT */ + if (G_UNLIKELY (filter->need_newsegment)) { + GstEvent *event; + + event = create_segment_event (filter, FALSE, 0); + + gst_pad_push_event (filter->srcpad, event); + + filter->need_newsegment = FALSE; + GST_DEBUG_OBJECT (filter, "Pushed newsegment event on this first buffer"); + } + + return GST_FLOW_OK; +} + +/** + * gst_base_rtp_depayload_push_ts: + * @filter: a #GstBaseRTPDepayload + * @timestamp: an RTP timestamp to apply + * @out_buf: a #GstBuffer + * + * Push @out_buf to the peer of @filter. This function takes ownership of + * @out_buf. + * + * Unlike gst_base_rtp_depayload_push(), this function will by default apply + * the last incomming timestamp on the outgoing buffer when it didn't have a + * timestamp already. The set_get_timestamp vmethod can be overwritten to change + * this behaviour (and take, for example, @timestamp into account). + * + * Returns: a #GstFlowReturn. + */ +GstFlowReturn +gst_base_rtp_depayload_push_ts (GstBaseRTPDepayload * filter, guint32 timestamp, + GstBuffer * out_buf) +{ + GstFlowReturn res; + + res = + gst_base_rtp_depayload_prepare_push (filter, TRUE, timestamp, FALSE, + &out_buf); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push (filter->srcpad, out_buf); + else + gst_buffer_unref (out_buf); + + return res; +} + +/** + * gst_base_rtp_depayload_push: + * @filter: a #GstBaseRTPDepayload + * @out_buf: a #GstBuffer + * + * Push @out_buf to the peer of @filter. This function takes ownership of + * @out_buf. + * + * Unlike gst_base_rtp_depayload_push_ts(), this function will not apply + * any timestamp on the outgoing buffer. Subclasses should therefore timestamp + * outgoing buffers themselves. + * + * Returns: a #GstFlowReturn. + */ +GstFlowReturn +gst_base_rtp_depayload_push (GstBaseRTPDepayload * filter, GstBuffer * out_buf) +{ + GstFlowReturn res; + + res = gst_base_rtp_depayload_prepare_push (filter, FALSE, 0, FALSE, &out_buf); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push (filter->srcpad, out_buf); + else + gst_buffer_unref (out_buf); + + return res; +} + +/** + * gst_base_rtp_depayload_push_list: + * @filter: a #GstBaseRTPDepayload + * @out_list: a #GstBufferList + * + * Push @out_list to the peer of @filter. This function takes ownership of + * @out_list. + * + * Returns: a #GstFlowReturn. + * + * Since: 0.10.32 + */ +GstFlowReturn +gst_base_rtp_depayload_push_list (GstBaseRTPDepayload * filter, + GstBufferList * out_list) +{ + GstFlowReturn res; + + res = gst_base_rtp_depayload_prepare_push (filter, TRUE, 0, TRUE, &out_list); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push_list (filter->srcpad, out_list); + else + gst_buffer_list_unref (out_list); + + return res; +} + +/* convert the PacketLost event form a jitterbuffer to a segment update. + * subclasses can override this. */ +static gboolean +gst_base_rtp_depayload_packet_lost (GstBaseRTPDepayload * filter, + GstEvent * event) +{ + GstClockTime timestamp, duration, position; + GstEvent *sevent; + const GstStructure *s; + + s = gst_event_get_structure (event); + + /* first start by parsing the timestamp and duration */ + timestamp = -1; + duration = -1; + + gst_structure_get_clock_time (s, "timestamp", ×tamp); + gst_structure_get_clock_time (s, "duration", &duration); + + position = timestamp; + if (duration != -1) + position += duration; + + /* update the current segment with the elapsed time */ + sevent = create_segment_event (filter, TRUE, position); + + return gst_pad_push_event (filter->srcpad, sevent); +} + +static void +gst_base_rtp_depayload_set_gst_timestamp (GstBaseRTPDepayload * filter, + guint32 rtptime, GstBuffer * buf) +{ + GstBaseRTPDepayloadPrivate *priv; + GstClockTime timestamp, duration; + + priv = filter->priv; + + timestamp = GST_BUFFER_TIMESTAMP (buf); + duration = GST_BUFFER_DURATION (buf); + + /* apply last incomming timestamp and duration to outgoing buffer if + * not otherwise set. */ + if (!GST_CLOCK_TIME_IS_VALID (timestamp)) + GST_BUFFER_TIMESTAMP (buf) = priv->timestamp; + if (!GST_CLOCK_TIME_IS_VALID (duration)) + GST_BUFFER_DURATION (buf) = priv->duration; +} + +static GstStateChangeReturn +gst_base_rtp_depayload_change_state (GstElement * element, + GstStateChange transition) +{ + GstBaseRTPDepayload *filter; + GstBaseRTPDepayloadPrivate *priv; + GstStateChangeReturn ret; + + filter = GST_BASE_RTP_DEPAYLOAD (element); + priv = filter->priv; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + filter->need_newsegment = TRUE; + priv->npt_start = 0; + priv->npt_stop = -1; + priv->play_speed = 1.0; + priv->play_scale = 1.0; + priv->next_seqnum = -1; + priv->negotiated = FALSE; + priv->discont = FALSE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} + +static void +gst_base_rtp_depayload_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseRTPDepayload *filter; + + filter = GST_BASE_RTP_DEPAYLOAD (object); + + switch (prop_id) { + case PROP_QUEUE_DELAY: + filter->queue_delay = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_base_rtp_depayload_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseRTPDepayload *filter; + + filter = GST_BASE_RTP_DEPAYLOAD (object); + + switch (prop_id) { + case PROP_QUEUE_DELAY: + g_value_set_uint (value, filter->queue_delay); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.h new file mode 100644 index 0000000..000c116 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertpdepayload.h @@ -0,0 +1,141 @@ +/* GStreamer + * Copyright (C) <2005> Philippe Khalaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_BASE_RTP_DEPAYLOAD_H__ +#define __GST_BASE_RTP_DEPAYLOAD_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_RTP_DEPAYLOAD (gst_base_rtp_depayload_get_type()) +#define GST_BASE_RTP_DEPAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_RTP_DEPAYLOAD,GstBaseRTPDepayload)) +#define GST_BASE_RTP_DEPAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_RTP_DEPAYLOAD,GstBaseRTPDepayloadClass)) +#define GST_BASE_RTP_DEPAYLOAD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_BASE_RTP_DEPAYLOAD,GstBaseRTPDepayloadClass)) +#define GST_IS_BASE_RTP_DEPAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_RTP_DEPAYLOAD)) +#define GST_IS_BASE_RTP_DEPAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_RTP_DEPAYLOAD)) + +#define GST_BASE_RTP_DEPAYLOAD_SINKPAD(depayload) (GST_BASE_RTP_DEPAYLOAD (depayload)->sinkpad) +#define GST_BASE_RTP_DEPAYLOAD_SRCPAD(depayload) (GST_BASE_RTP_DEPAYLOAD (depayload)->srcpad) + +#ifndef GST_DISABLE_DEPRECATED +/* this was presumably never meant to be public API, or should at least + * have been prefixed if it was. Don't use. (FIXME: remove in 0.11) */ +#define QUEUE_LOCK_INIT(base) (g_static_rec_mutex_init(&base->queuelock)) +#define QUEUE_LOCK_FREE(base) (g_static_rec_mutex_free(&base->queuelock)) +#define QUEUE_LOCK(base) (g_static_rec_mutex_lock(&base->queuelock)) +#define QUEUE_UNLOCK(base) (g_static_rec_mutex_unlock(&base->queuelock)) +#endif + +typedef struct _GstBaseRTPDepayload GstBaseRTPDepayload; +typedef struct _GstBaseRTPDepayloadClass GstBaseRTPDepayloadClass; +typedef struct _GstBaseRTPDepayloadPrivate GstBaseRTPDepayloadPrivate; + +struct _GstBaseRTPDepayload +{ + GstElement parent; + + GstPad *sinkpad, *srcpad; + +#ifndef GST_REMOVE_DEPRECATED + /* lock to protect the queue, deprecated */ + GStaticRecMutex queuelock; + + /* deprecated */ + gboolean thread_running; + /* the releaser thread, deprecated */ + GThread *thread; +#endif + + /* this attribute must be set by the child */ + guint clock_rate; + +#ifndef GST_REMOVE_DEPRECATED + /* this value can be modified by the child if needed, deprecated */ + guint queue_delay; +#endif + + /* we will queue up to RTP_QUEUEDELAY ms of packets, + * reordering them if necessary + * dropping any packets that are more than + * RTP_QUEUEDELAY ms late, deprecated */ + GQueue *queue; + + GstSegment segment; + gboolean need_newsegment; + + /*< private >*/ + GstBaseRTPDepayloadPrivate *priv; + + gpointer _gst_reserved[GST_PADDING-1]; +}; + +struct _GstBaseRTPDepayloadClass +{ + GstElementClass parent_class; + + /* virtuals, inform the subclass of the caps. */ + gboolean (*set_caps) (GstBaseRTPDepayload *filter, GstCaps *caps); + + /* non-pure function, default implementation in base class + * this does buffering, reordering and dropping, deprecated */ + GstFlowReturn (*add_to_queue) (GstBaseRTPDepayload *filter, GstBuffer *in); + + /* pure virtual function, child must use this to process incoming + * rtp packets. If the child returns a buffer without a valid timestamp, + * the timestamp of @in will be applied to the result buffer and the + * buffer will be pushed. If this function returns %NULL, nothing is + * pushed. */ + GstBuffer * (*process) (GstBaseRTPDepayload *base, GstBuffer *in); + + /* non-pure function used to convert from RTP timestamp to GST timestamp + * this function is used by the child class before gst_pad_pushing */ + void (*set_gst_timestamp) (GstBaseRTPDepayload *filter, guint32 timestamp, GstBuffer *buf); + + /* non-pure function used to to signal the depayloader about packet loss. the + * timestamp and duration are the estimated values of the lost packet. + * The default implementation of this message pushes a segment update. */ + gboolean (*packet_lost) (GstBaseRTPDepayload *filter, GstEvent *event); + + /* the default implementation does the default actions for events but + * implementation can override. + * Since: 0.10.32 */ + gboolean (*handle_event) (GstBaseRTPDepayload * filter, GstEvent * event); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING-2]; +}; + +GType gst_base_rtp_depayload_get_type (void); + +GstFlowReturn gst_base_rtp_depayload_push (GstBaseRTPDepayload *filter, GstBuffer *out_buf); +GstFlowReturn gst_base_rtp_depayload_push_ts (GstBaseRTPDepayload *filter, + guint32 timestamp, GstBuffer *out_buf); +GstFlowReturn gst_base_rtp_depayload_push_list (GstBaseRTPDepayload *filter, GstBufferList *out_list); + + +G_END_DECLS + +#endif /* __GST_BASE_RTP_DEPAYLOAD_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.c new file mode 100644 index 0000000..060e4e0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.c @@ -0,0 +1,1069 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more + */ + +/** + * SECTION:gstbasertppayload + * @short_description: Base class for RTP payloader + * + * + * + * Provides a base class for RTP payloaders + * + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include + +#include "gstbasertppayload.h" + +GST_DEBUG_CATEGORY_STATIC (basertppayload_debug); +#define GST_CAT_DEFAULT (basertppayload_debug) + +#define GST_BASE_RTP_PAYLOAD_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_RTP_PAYLOAD, GstBaseRTPPayloadPrivate)) + +struct _GstBaseRTPPayloadPrivate +{ + gboolean ts_offset_random; + gboolean seqnum_offset_random; + gboolean ssrc_random; + guint16 next_seqnum; + gboolean perfect_rtptime; + gint notified_first_timestamp; + + gint64 prop_max_ptime; + gint64 caps_max_ptime; +}; + +/* BaseRTPPayload signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +/* FIXME 0.11, a better default is the Ethernet MTU of + * 1500 - sizeof(headers) as pointed out by marcelm in IRC: + * So an Ethernet MTU of 1500, minus 60 for the max IP, minus 8 for UDP, gives + * 1432 bytes or so. And that should be adjusted downward further for other + * encapsulations like PPPoE, so 1400 at most. + */ +#define DEFAULT_MTU 1400 +#define DEFAULT_PT 96 +#define DEFAULT_SSRC -1 +#define DEFAULT_TIMESTAMP_OFFSET -1 +#define DEFAULT_SEQNUM_OFFSET -1 +#define DEFAULT_MAX_PTIME -1 +#define DEFAULT_MIN_PTIME 0 +#define DEFAULT_PERFECT_RTPTIME TRUE +#define DEFAULT_PTIME_MULTIPLE 0 + +enum +{ + PROP_0, + PROP_MTU, + PROP_PT, + PROP_SSRC, + PROP_TIMESTAMP_OFFSET, + PROP_SEQNUM_OFFSET, + PROP_MAX_PTIME, + PROP_MIN_PTIME, + PROP_TIMESTAMP, + PROP_SEQNUM, + PROP_PERFECT_RTPTIME, + PROP_PTIME_MULTIPLE, + PROP_LAST +}; + +static void gst_basertppayload_class_init (GstBaseRTPPayloadClass * klass); +static void gst_basertppayload_base_init (GstBaseRTPPayloadClass * klass); +static void gst_basertppayload_init (GstBaseRTPPayload * basertppayload, + gpointer g_class); +static void gst_basertppayload_finalize (GObject * object); + +static gboolean gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps); +static GstCaps *gst_basertppayload_sink_getcaps (GstPad * pad); +static gboolean gst_basertppayload_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_basertppayload_chain (GstPad * pad, + GstBuffer * buffer); + +static void gst_basertppayload_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_basertppayload_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_basertppayload_change_state (GstElement * + element, GstStateChange transition); + +static GstElementClass *parent_class = NULL; + +/* FIXME 0.11: API should be changed to gst_base_typ_payload_xyz */ + +GType +gst_basertppayload_get_type (void) +{ + static GType basertppayload_type = 0; + + if (!basertppayload_type) { + static const GTypeInfo basertppayload_info = { + sizeof (GstBaseRTPPayloadClass), + (GBaseInitFunc) gst_basertppayload_base_init, + NULL, + (GClassInitFunc) gst_basertppayload_class_init, + NULL, + NULL, + sizeof (GstBaseRTPPayload), + 0, + (GInstanceInitFunc) gst_basertppayload_init, + }; + + basertppayload_type = + g_type_register_static (GST_TYPE_ELEMENT, "GstBaseRTPPayload", + &basertppayload_info, G_TYPE_FLAG_ABSTRACT); + } + return basertppayload_type; +} + +static void +gst_basertppayload_base_init (GstBaseRTPPayloadClass * klass) +{ +} + +static void +gst_basertppayload_class_init (GstBaseRTPPayloadClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + g_type_class_add_private (klass, sizeof (GstBaseRTPPayloadPrivate)); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_basertppayload_finalize; + + gobject_class->set_property = gst_basertppayload_set_property; + gobject_class->get_property = gst_basertppayload_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MTU, + g_param_spec_uint ("mtu", "MTU", + "Maximum size of one packet", + 28, G_MAXUINT, DEFAULT_MTU, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PT, + g_param_spec_uint ("pt", "payload type", + "The payload type of the packets", 0, 0x80, DEFAULT_PT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SSRC, + g_param_spec_uint ("ssrc", "SSRC", + "The SSRC of the packets (default == random)", 0, G_MAXUINT32, + DEFAULT_SSRC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_TIMESTAMP_OFFSET, g_param_spec_uint ("timestamp-offset", + "Timestamp Offset", + "Offset to add to all outgoing timestamps (default = random)", 0, + G_MAXUINT32, DEFAULT_TIMESTAMP_OFFSET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM_OFFSET, + g_param_spec_int ("seqnum-offset", "Sequence number Offset", + "Offset to add to all outgoing seqnum (-1 = random)", -1, G_MAXUINT16, + DEFAULT_SEQNUM_OFFSET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MAX_PTIME, + g_param_spec_int64 ("max-ptime", "Max packet time", + "Maximum duration of the packet data in ns (-1 = unlimited up to MTU)", + -1, G_MAXINT64, DEFAULT_MAX_PTIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseRTPAudioPayload:min-ptime: + * + * Minimum duration of the packet data in ns (can't go above MTU) + * + * Since: 0.10.13 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MIN_PTIME, + g_param_spec_int64 ("min-ptime", "Min packet time", + "Minimum duration of the packet data in ns (can't go above MTU)", + 0, G_MAXINT64, DEFAULT_MIN_PTIME, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_TIMESTAMP, + g_param_spec_uint ("timestamp", "Timestamp", + "The RTP timestamp of the last processed packet", + 0, G_MAXUINT32, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SEQNUM, + g_param_spec_uint ("seqnum", "Sequence number", + "The RTP sequence number of the last processed packet", + 0, G_MAXUINT16, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstBaseRTPAudioPayload:perfect-rtptime: + * + * Try to use the offset fields to generate perfect RTP timestamps. when this + * option is disabled, RTP timestamps are generated from the GStreamer + * timestamps, which could result in RTP timestamps that don't increment with + * the amount of data in the packet. + * + * Since: 0.10.25 + */ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PERFECT_RTPTIME, + g_param_spec_boolean ("perfect-rtptime", "Perfect RTP Time", + "Generate perfect RTP timestamps when possible", + DEFAULT_PERFECT_RTPTIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstBaseRTPAudioPayload:ptime-multiple: + * + * Force buffers to be multiples of this duration in ns (0 disables) + * + * Since: 0.10.29 + **/ + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_PTIME_MULTIPLE, + g_param_spec_int64 ("ptime-multiple", "Packet time multiple", + "Force buffers to be multiples of this duration in ns (0 disables)", + 0, G_MAXINT64, DEFAULT_PTIME_MULTIPLE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = gst_basertppayload_change_state; + + GST_DEBUG_CATEGORY_INIT (basertppayload_debug, "basertppayload", 0, + "Base class for RTP Payloaders"); +} + +static void +gst_basertppayload_init (GstBaseRTPPayload * basertppayload, gpointer g_class) +{ + GstPadTemplate *templ; + GstBaseRTPPayloadPrivate *priv; + + basertppayload->priv = priv = + GST_BASE_RTP_PAYLOAD_GET_PRIVATE (basertppayload); + + templ = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "src"); + g_return_if_fail (templ != NULL); + + basertppayload->srcpad = gst_pad_new_from_template (templ, "src"); + gst_element_add_pad (GST_ELEMENT (basertppayload), basertppayload->srcpad); + + templ = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (g_class), "sink"); + g_return_if_fail (templ != NULL); + + basertppayload->sinkpad = gst_pad_new_from_template (templ, "sink"); + gst_pad_set_setcaps_function (basertppayload->sinkpad, + gst_basertppayload_sink_setcaps); + gst_pad_set_getcaps_function (basertppayload->sinkpad, + gst_basertppayload_sink_getcaps); + gst_pad_set_event_function (basertppayload->sinkpad, + gst_basertppayload_event); + gst_pad_set_chain_function (basertppayload->sinkpad, + gst_basertppayload_chain); + gst_element_add_pad (GST_ELEMENT (basertppayload), basertppayload->sinkpad); + + basertppayload->seq_rand = g_rand_new_with_seed (g_random_int ()); + basertppayload->ssrc_rand = g_rand_new_with_seed (g_random_int ()); + basertppayload->ts_rand = g_rand_new_with_seed (g_random_int ()); + + basertppayload->mtu = DEFAULT_MTU; + basertppayload->pt = DEFAULT_PT; + basertppayload->seqnum_offset = DEFAULT_SEQNUM_OFFSET; + basertppayload->ssrc = DEFAULT_SSRC; + basertppayload->ts_offset = DEFAULT_TIMESTAMP_OFFSET; + priv->seqnum_offset_random = (basertppayload->seqnum_offset == -1); + priv->ts_offset_random = (basertppayload->ts_offset == -1); + priv->ssrc_random = (basertppayload->ssrc == -1); + + basertppayload->max_ptime = DEFAULT_MAX_PTIME; + basertppayload->min_ptime = DEFAULT_MIN_PTIME; + basertppayload->priv->perfect_rtptime = DEFAULT_PERFECT_RTPTIME; + basertppayload->abidata.ABI.ptime_multiple = DEFAULT_PTIME_MULTIPLE; + + basertppayload->media = NULL; + basertppayload->encoding_name = NULL; + + basertppayload->clock_rate = 0; + + basertppayload->priv->caps_max_ptime = DEFAULT_MAX_PTIME; + basertppayload->priv->prop_max_ptime = DEFAULT_MAX_PTIME; +} + +static void +gst_basertppayload_finalize (GObject * object) +{ + GstBaseRTPPayload *basertppayload; + + basertppayload = GST_BASE_RTP_PAYLOAD (object); + + g_rand_free (basertppayload->seq_rand); + basertppayload->seq_rand = NULL; + g_rand_free (basertppayload->ssrc_rand); + basertppayload->ssrc_rand = NULL; + g_rand_free (basertppayload->ts_rand); + basertppayload->ts_rand = NULL; + + g_free (basertppayload->media); + basertppayload->media = NULL; + g_free (basertppayload->encoding_name); + basertppayload->encoding_name = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_basertppayload_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadClass *basertppayload_class; + gboolean ret = TRUE; + + GST_DEBUG_OBJECT (pad, "setting caps %" GST_PTR_FORMAT, caps); + basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad)); + basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload); + + if (basertppayload_class->set_caps) + ret = basertppayload_class->set_caps (basertppayload, caps); + + gst_object_unref (basertppayload); + + return ret; +} + +static GstCaps * +gst_basertppayload_sink_getcaps (GstPad * pad) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadClass *basertppayload_class; + GstCaps *caps = NULL; + + GST_DEBUG_OBJECT (pad, "getting caps"); + + basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad)); + basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload); + + if (basertppayload_class->get_caps) + caps = basertppayload_class->get_caps (basertppayload, pad); + + if (!caps) { + caps = GST_PAD_TEMPLATE_CAPS (GST_PAD_PAD_TEMPLATE (pad)); + GST_DEBUG_OBJECT (pad, + "using pad template %p with caps %p %" GST_PTR_FORMAT, + GST_PAD_PAD_TEMPLATE (pad), caps, caps); + + caps = gst_caps_ref (caps); + } + + gst_object_unref (basertppayload); + + return caps; +} + +static gboolean +gst_basertppayload_event (GstPad * pad, GstEvent * event) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadClass *basertppayload_class; + gboolean res; + + basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad)); + if (G_UNLIKELY (basertppayload == NULL)) { + gst_event_unref (event); + return FALSE; + } + basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload); + + if (basertppayload_class->handle_event) { + res = basertppayload_class->handle_event (pad, event); + if (res) + goto done; + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + res = gst_pad_event_default (pad, event); + break; + case GST_EVENT_FLUSH_STOP: + res = gst_pad_event_default (pad, event); + gst_segment_init (&basertppayload->segment, GST_FORMAT_UNDEFINED); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate, arate; + GstFormat fmt; + gint64 start, stop, position; + GstSegment *segment; + + segment = &basertppayload->segment; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &fmt, + &start, &stop, &position); + gst_segment_set_newsegment_full (segment, update, rate, arate, fmt, start, + stop, position); + + GST_DEBUG_OBJECT (basertppayload, + "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " + "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT ", accum %" G_GINT64_FORMAT, update, rate, arate, + segment->format, segment->start, segment->stop, segment->time, + segment->accum); + /* fallthrough */ + } + default: + res = gst_pad_event_default (pad, event); + break; + } + +done: + gst_object_unref (basertppayload); + + return res; +} + + +static GstFlowReturn +gst_basertppayload_chain (GstPad * pad, GstBuffer * buffer) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadClass *basertppayload_class; + GstFlowReturn ret; + + basertppayload = GST_BASE_RTP_PAYLOAD (gst_pad_get_parent (pad)); + basertppayload_class = GST_BASE_RTP_PAYLOAD_GET_CLASS (basertppayload); + + if (!basertppayload_class->handle_buffer) + goto no_function; + + ret = basertppayload_class->handle_buffer (basertppayload, buffer); + + gst_object_unref (basertppayload); + + return ret; + + /* ERRORS */ +no_function: + { + GST_ELEMENT_ERROR (basertppayload, STREAM, NOT_IMPLEMENTED, (NULL), + ("subclass did not implement handle_buffer function")); + gst_object_unref (basertppayload); + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } +} + +/** + * gst_basertppayload_set_options: + * @payload: a #GstBaseRTPPayload + * @media: the media type (typically "audio" or "video") + * @dynamic: if the payload type is dynamic + * @encoding_name: the encoding name + * @clock_rate: the clock rate of the media + * + * Set the rtp options of the payloader. These options will be set in the caps + * of the payloader. Subclasses must call this method before calling + * gst_basertppayload_push() or gst_basertppayload_set_outcaps(). + */ +void +gst_basertppayload_set_options (GstBaseRTPPayload * payload, + const gchar * media, gboolean dynamic, const gchar * encoding_name, + guint32 clock_rate) +{ + g_return_if_fail (payload != NULL); + g_return_if_fail (clock_rate != 0); + + g_free (payload->media); + payload->media = g_strdup (media); + payload->dynamic = dynamic; + g_free (payload->encoding_name); + payload->encoding_name = g_strdup (encoding_name); + payload->clock_rate = clock_rate; +} + +static gboolean +copy_fixed (GQuark field_id, const GValue * value, GstStructure * dest) +{ + if (gst_value_is_fixed (value)) { + gst_structure_id_set_value (dest, field_id, value); + } + return TRUE; +} + +static void +update_max_ptime (GstBaseRTPPayload * basertppayload) +{ + if (basertppayload->priv->caps_max_ptime != -1 && + basertppayload->priv->prop_max_ptime != -1) + basertppayload->max_ptime = MIN (basertppayload->priv->caps_max_ptime, + basertppayload->priv->prop_max_ptime); + else if (basertppayload->priv->caps_max_ptime != -1) + basertppayload->max_ptime = basertppayload->priv->caps_max_ptime; + else if (basertppayload->priv->prop_max_ptime != -1) + basertppayload->max_ptime = basertppayload->priv->prop_max_ptime; + else + basertppayload->max_ptime = DEFAULT_MAX_PTIME; +} + +/** + * gst_basertppayload_set_outcaps: + * @payload: a #GstBaseRTPPayload + * @fieldname: the first field name or %NULL + * @...: field values + * + * Configure the output caps with the optional parameters. + * + * Variable arguments should be in the form field name, field type + * (as a GType), value(s). The last variable argument should be NULL. + * + * Returns: %TRUE if the caps could be set. + */ +gboolean +gst_basertppayload_set_outcaps (GstBaseRTPPayload * payload, + const gchar * fieldname, ...) +{ + GstCaps *srccaps, *peercaps; + gboolean res; + + /* fill in the defaults, their properties cannot be negotiated. */ + srccaps = gst_caps_new_simple ("application/x-rtp", + "media", G_TYPE_STRING, payload->media, + "clock-rate", G_TYPE_INT, payload->clock_rate, + "encoding-name", G_TYPE_STRING, payload->encoding_name, NULL); + + GST_DEBUG_OBJECT (payload, "defaults: %" GST_PTR_FORMAT, srccaps); + + if (fieldname) { + va_list varargs; + + /* override with custom properties */ + va_start (varargs, fieldname); + gst_caps_set_simple_valist (srccaps, fieldname, varargs); + va_end (varargs); + + GST_DEBUG_OBJECT (payload, "custom added: %" GST_PTR_FORMAT, srccaps); + } + + payload->priv->caps_max_ptime = DEFAULT_MAX_PTIME; + payload->abidata.ABI.ptime = 0; + + /* the peer caps can override some of the defaults */ + peercaps = gst_pad_peer_get_caps (payload->srcpad); + if (peercaps == NULL) { + /* no peer caps, just add the other properties */ + gst_caps_set_simple (srccaps, + "payload", G_TYPE_INT, GST_BASE_RTP_PAYLOAD_PT (payload), + "ssrc", G_TYPE_UINT, payload->current_ssrc, + "clock-base", G_TYPE_UINT, payload->ts_base, + "seqnum-base", G_TYPE_UINT, payload->seqnum_base, NULL); + + GST_DEBUG_OBJECT (payload, "no peer caps: %" GST_PTR_FORMAT, srccaps); + } else { + GstCaps *temp; + GstStructure *s, *d; + const GValue *value; + gint pt; + guint max_ptime, ptime; + + /* peer provides caps we can use to fixate, intersect. This always returns a + * writable caps. */ + temp = gst_caps_intersect (srccaps, peercaps); + gst_caps_unref (srccaps); + gst_caps_unref (peercaps); + + if (gst_caps_is_empty (temp)) { + gst_caps_unref (temp); + return FALSE; + } + + /* now fixate, start by taking the first caps */ + gst_caps_truncate (temp); + + /* get first structure */ + s = gst_caps_get_structure (temp, 0); + + if (gst_structure_get_uint (s, "maxptime", &max_ptime)) + payload->priv->caps_max_ptime = max_ptime * GST_MSECOND; + + if (gst_structure_get_uint (s, "ptime", &ptime)) + payload->abidata.ABI.ptime = ptime * GST_MSECOND; + + if (gst_structure_get_int (s, "payload", &pt)) { + /* use peer pt */ + GST_BASE_RTP_PAYLOAD_PT (payload) = pt; + GST_LOG_OBJECT (payload, "using peer pt %d", pt); + } else { + if (gst_structure_has_field (s, "payload")) { + /* can only fixate if there is a field */ + gst_structure_fixate_field_nearest_int (s, "payload", + GST_BASE_RTP_PAYLOAD_PT (payload)); + gst_structure_get_int (s, "payload", &pt); + GST_LOG_OBJECT (payload, "using peer pt %d", pt); + } else { + /* no pt field, use the internal pt */ + pt = GST_BASE_RTP_PAYLOAD_PT (payload); + gst_structure_set (s, "payload", G_TYPE_INT, pt, NULL); + GST_LOG_OBJECT (payload, "using internal pt %d", pt); + } + } + + if (gst_structure_has_field_typed (s, "ssrc", G_TYPE_UINT)) { + value = gst_structure_get_value (s, "ssrc"); + payload->current_ssrc = g_value_get_uint (value); + GST_LOG_OBJECT (payload, "using peer ssrc %08x", payload->current_ssrc); + } else { + /* FIXME, fixate_nearest_uint would be even better */ + gst_structure_set (s, "ssrc", G_TYPE_UINT, payload->current_ssrc, NULL); + GST_LOG_OBJECT (payload, "using internal ssrc %08x", + payload->current_ssrc); + } + + if (gst_structure_has_field_typed (s, "clock-base", G_TYPE_UINT)) { + value = gst_structure_get_value (s, "clock-base"); + payload->ts_base = g_value_get_uint (value); + GST_LOG_OBJECT (payload, "using peer clock-base %u", payload->ts_base); + } else { + /* FIXME, fixate_nearest_uint would be even better */ + gst_structure_set (s, "clock-base", G_TYPE_UINT, payload->ts_base, NULL); + GST_LOG_OBJECT (payload, "using internal clock-base %u", + payload->ts_base); + } + if (gst_structure_has_field_typed (s, "seqnum-base", G_TYPE_UINT)) { + value = gst_structure_get_value (s, "seqnum-base"); + payload->seqnum_base = g_value_get_uint (value); + GST_LOG_OBJECT (payload, "using peer seqnum-base %u", + payload->seqnum_base); + } else { + /* FIXME, fixate_nearest_uint would be even better */ + gst_structure_set (s, "seqnum-base", G_TYPE_UINT, payload->seqnum_base, + NULL); + GST_LOG_OBJECT (payload, "using internal seqnum-base %u", + payload->seqnum_base); + } + + /* make the target caps by copying over all the fixed caps, removing the + * unfixed caps. */ + srccaps = gst_caps_new_simple (gst_structure_get_name (s), NULL); + d = gst_caps_get_structure (srccaps, 0); + + gst_structure_foreach (s, (GstStructureForeachFunc) copy_fixed, d); + + gst_caps_unref (temp); + + GST_DEBUG_OBJECT (payload, "with peer caps: %" GST_PTR_FORMAT, srccaps); + } + + update_max_ptime (payload); + + res = gst_pad_set_caps (GST_BASE_RTP_PAYLOAD_SRCPAD (payload), srccaps); + gst_caps_unref (srccaps); + + return res; +} + +/** + * gst_basertppayload_is_filled: + * @payload: a #GstBaseRTPPayload + * @size: the size of the packet + * @duration: the duration of the packet + * + * Check if the packet with @size and @duration would exceed the configured + * maximum size. + * + * Returns: %TRUE if the packet of @size and @duration would exceed the + * configured MTU or max_ptime. + */ +gboolean +gst_basertppayload_is_filled (GstBaseRTPPayload * payload, + guint size, GstClockTime duration) +{ + if (size > payload->mtu) + return TRUE; + + if (payload->max_ptime != -1 && duration >= payload->max_ptime) + return TRUE; + + return FALSE; +} + +typedef struct +{ + GstBaseRTPPayload *payload; + guint32 ssrc; + guint16 seqnum; + guint8 pt; + GstCaps *caps; + GstClockTime timestamp; + guint64 offset; + guint32 rtptime; +} HeaderData; + +static GstBufferListItem +find_timestamp (GstBuffer ** buffer, guint group, guint idx, HeaderData * data) +{ + data->timestamp = GST_BUFFER_TIMESTAMP (*buffer); + data->offset = GST_BUFFER_OFFSET (*buffer); + + /* stop when we find a timestamp. We take whatever offset is associated with + * the timestamp (if any) to do perfect timestamps when we need to. */ + if (data->timestamp != -1) + return GST_BUFFER_LIST_END; + else + return GST_BUFFER_LIST_CONTINUE; +} + +static GstBufferListItem +set_headers (GstBuffer ** buffer, guint group, guint idx, HeaderData * data) +{ + gst_rtp_buffer_set_ssrc (*buffer, data->ssrc); + gst_rtp_buffer_set_payload_type (*buffer, data->pt); + gst_rtp_buffer_set_seq (*buffer, data->seqnum); + gst_rtp_buffer_set_timestamp (*buffer, data->rtptime); + gst_buffer_set_caps (*buffer, data->caps); + /* increment the seqnum for each buffer */ + data->seqnum++; + + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/* Updates the SSRC, payload type, seqnum and timestamp of the RTP buffer + * before the buffer is pushed. */ +static GstFlowReturn +gst_basertppayload_prepare_push (GstBaseRTPPayload * payload, + gpointer obj, gboolean is_list) +{ + GstBaseRTPPayloadPrivate *priv; + HeaderData data; + + if (payload->clock_rate == 0) + goto no_rate; + + priv = payload->priv; + + /* update first, so that the property is set to the last + * seqnum pushed */ + payload->seqnum = priv->next_seqnum; + + /* fill in the fields we want to set on all headers */ + data.payload = payload; + data.seqnum = payload->seqnum; + data.ssrc = payload->current_ssrc; + data.pt = payload->pt; + data.caps = GST_PAD_CAPS (payload->srcpad); + + /* find the first buffer with a timestamp */ + if (is_list) { + data.timestamp = -1; + data.offset = GST_BUFFER_OFFSET_NONE; + gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), + (GstBufferListFunc) find_timestamp, &data); + } else { + data.timestamp = GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (obj)); + data.offset = GST_BUFFER_OFFSET (GST_BUFFER_CAST (obj)); + } + + /* convert to RTP time */ + if (priv->perfect_rtptime && data.offset != GST_BUFFER_OFFSET_NONE) { + /* if we have an offset, use that for making an RTP timestamp */ + data.rtptime = payload->ts_base + data.offset; + GST_LOG_OBJECT (payload, + "Using offset %" G_GUINT64_FORMAT " for RTP timestamp", data.offset); + } else if (GST_CLOCK_TIME_IS_VALID (data.timestamp)) { + gint64 rtime; + + /* no offset, use the gstreamer timestamp */ + rtime = gst_segment_to_running_time (&payload->segment, GST_FORMAT_TIME, + data.timestamp); + + if (rtime == -1) { + GST_LOG_OBJECT (payload, "Clipped timestamp, using base RTP timestamp"); + rtime = 0; + } else { + GST_LOG_OBJECT (payload, + "Using running_time %" GST_TIME_FORMAT " for RTP timestamp", + GST_TIME_ARGS (rtime)); + rtime = + gst_util_uint64_scale_int (rtime, payload->clock_rate, GST_SECOND); + } + /* add running_time in clock-rate units to the base timestamp */ + data.rtptime = payload->ts_base + rtime; + } else { + GST_LOG_OBJECT (payload, + "Using previous RTP timestamp %" G_GUINT32_FORMAT, payload->timestamp); + /* no timestamp to convert, take previous timestamp */ + data.rtptime = payload->timestamp; + } + + /* set ssrc, payload type, seq number, caps and rtptime */ + if (is_list) { + gst_buffer_list_foreach (GST_BUFFER_LIST_CAST (obj), + (GstBufferListFunc) set_headers, &data); + } else { + GstBuffer *buf = GST_BUFFER_CAST (obj); + set_headers (&buf, 0, 0, &data); + } + + priv->next_seqnum = data.seqnum; + payload->timestamp = data.rtptime; + + GST_LOG_OBJECT (payload, + "Preparing to push packet with size %d, seq=%d, rtptime=%u, timestamp %" + GST_TIME_FORMAT, (is_list) ? -1 : + GST_BUFFER_SIZE (GST_BUFFER (obj)), payload->seqnum, data.rtptime, + GST_TIME_ARGS (data.timestamp)); + + if (g_atomic_int_compare_and_exchange (&payload-> + priv->notified_first_timestamp, 1, 0)) { + g_object_notify (G_OBJECT (payload), "timestamp"); + g_object_notify (G_OBJECT (payload), "seqnum"); + } + + return GST_FLOW_OK; + + /* ERRORS */ +no_rate: + { + GST_ELEMENT_ERROR (payload, STREAM, NOT_IMPLEMENTED, (NULL), + ("subclass did not specify clock-rate")); + return GST_FLOW_ERROR; + } +} + +/** + * gst_basertppayload_push_list: + * @payload: a #GstBaseRTPPayload + * @list: a #GstBufferList + * + * Push @list to the peer element of the payloader. The SSRC, payload type, + * seqnum and timestamp of the RTP buffer will be updated first. + * + * This function takes ownership of @list. + * + * Returns: a #GstFlowReturn. + * + * Since: 0.10.24 + */ +GstFlowReturn +gst_basertppayload_push_list (GstBaseRTPPayload * payload, GstBufferList * list) +{ + GstFlowReturn res; + + res = gst_basertppayload_prepare_push (payload, list, TRUE); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push_list (payload->srcpad, list); + else + gst_buffer_list_unref (list); + + return res; +} + +/** + * gst_basertppayload_push: + * @payload: a #GstBaseRTPPayload + * @buffer: a #GstBuffer + * + * Push @buffer to the peer element of the payloader. The SSRC, payload type, + * seqnum and timestamp of the RTP buffer will be updated first. + * + * This function takes ownership of @buffer. + * + * Returns: a #GstFlowReturn. + */ +GstFlowReturn +gst_basertppayload_push (GstBaseRTPPayload * payload, GstBuffer * buffer) +{ + GstFlowReturn res; + + res = gst_basertppayload_prepare_push (payload, buffer, FALSE); + + if (G_LIKELY (res == GST_FLOW_OK)) + res = gst_pad_push (payload->srcpad, buffer); + else + gst_buffer_unref (buffer); + + return res; +} + +static void +gst_basertppayload_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadPrivate *priv; + gint64 val; + + basertppayload = GST_BASE_RTP_PAYLOAD (object); + priv = basertppayload->priv; + + switch (prop_id) { + case PROP_MTU: + basertppayload->mtu = g_value_get_uint (value); + break; + case PROP_PT: + basertppayload->pt = g_value_get_uint (value); + break; + case PROP_SSRC: + val = g_value_get_uint (value); + basertppayload->ssrc = val; + priv->ssrc_random = FALSE; + break; + case PROP_TIMESTAMP_OFFSET: + val = g_value_get_uint (value); + basertppayload->ts_offset = val; + priv->ts_offset_random = FALSE; + break; + case PROP_SEQNUM_OFFSET: + val = g_value_get_int (value); + basertppayload->seqnum_offset = val; + priv->seqnum_offset_random = (val == -1); + GST_DEBUG_OBJECT (basertppayload, "seqnum offset 0x%04x, random %d", + basertppayload->seqnum_offset, priv->seqnum_offset_random); + break; + case PROP_MAX_PTIME: + basertppayload->priv->prop_max_ptime = g_value_get_int64 (value); + update_max_ptime (basertppayload); + break; + case PROP_MIN_PTIME: + basertppayload->min_ptime = g_value_get_int64 (value); + break; + case PROP_PERFECT_RTPTIME: + priv->perfect_rtptime = g_value_get_boolean (value); + break; + case PROP_PTIME_MULTIPLE: + basertppayload->abidata.ABI.ptime_multiple = g_value_get_int64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_basertppayload_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadPrivate *priv; + + basertppayload = GST_BASE_RTP_PAYLOAD (object); + priv = basertppayload->priv; + + switch (prop_id) { + case PROP_MTU: + g_value_set_uint (value, basertppayload->mtu); + break; + case PROP_PT: + g_value_set_uint (value, basertppayload->pt); + break; + case PROP_SSRC: + if (priv->ssrc_random) + g_value_set_uint (value, -1); + else + g_value_set_uint (value, basertppayload->ssrc); + break; + case PROP_TIMESTAMP_OFFSET: + if (priv->ts_offset_random) + g_value_set_uint (value, -1); + else + g_value_set_uint (value, (guint32) basertppayload->ts_offset); + break; + case PROP_SEQNUM_OFFSET: + if (priv->seqnum_offset_random) + g_value_set_int (value, -1); + else + g_value_set_int (value, (guint16) basertppayload->seqnum_offset); + break; + case PROP_MAX_PTIME: + g_value_set_int64 (value, basertppayload->max_ptime); + break; + case PROP_MIN_PTIME: + g_value_set_int64 (value, basertppayload->min_ptime); + break; + case PROP_TIMESTAMP: + g_value_set_uint (value, basertppayload->timestamp); + break; + case PROP_SEQNUM: + g_value_set_uint (value, basertppayload->seqnum); + break; + case PROP_PERFECT_RTPTIME: + g_value_set_boolean (value, priv->perfect_rtptime); + break; + case PROP_PTIME_MULTIPLE: + g_value_set_int64 (value, basertppayload->abidata.ABI.ptime_multiple); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_basertppayload_change_state (GstElement * element, + GstStateChange transition) +{ + GstBaseRTPPayload *basertppayload; + GstBaseRTPPayloadPrivate *priv; + GstStateChangeReturn ret; + + basertppayload = GST_BASE_RTP_PAYLOAD (element); + priv = basertppayload->priv; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_segment_init (&basertppayload->segment, GST_FORMAT_UNDEFINED); + + if (priv->seqnum_offset_random) + basertppayload->seqnum_base = g_random_int_range (0, G_MAXUINT16); + else + basertppayload->seqnum_base = basertppayload->seqnum_offset; + priv->next_seqnum = basertppayload->seqnum_base; + basertppayload->seqnum = basertppayload->seqnum_base; + + if (priv->ssrc_random) + basertppayload->current_ssrc = g_random_int (); + else + basertppayload->current_ssrc = basertppayload->ssrc; + + if (priv->ts_offset_random) + basertppayload->ts_base = g_random_int (); + else + basertppayload->ts_base = basertppayload->ts_offset; + basertppayload->timestamp = basertppayload->ts_base; + g_atomic_int_set (&basertppayload->priv->notified_first_timestamp, 1); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + g_atomic_int_set (&basertppayload->priv->notified_first_timestamp, 1); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.h new file mode 100644 index 0000000..9707be0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstbasertppayload.h @@ -0,0 +1,162 @@ +/* GStreamer + * Copyright (C) <2005> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_BASE_RTP_PAYLOAD_H__ +#define __GST_BASE_RTP_PAYLOAD_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_RTP_PAYLOAD \ + (gst_basertppayload_get_type()) +#define GST_BASE_RTP_PAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_RTP_PAYLOAD,GstBaseRTPPayload)) +#define GST_BASE_RTP_PAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_RTP_PAYLOAD,GstBaseRTPPayloadClass)) +#define GST_BASE_RTP_PAYLOAD_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_RTP_PAYLOAD, GstBaseRTPPayloadClass)) +#define GST_IS_BASE_RTP_PAYLOAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_RTP_PAYLOAD)) +#define GST_IS_BASE_RTP_PAYLOAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_RTP_PAYLOAD)) +#define GST_BASE_RTP_PAYLOAD_CAST(obj) \ + ((GstBaseRTPPayload*)(obj)) + +typedef struct _GstBaseRTPPayload GstBaseRTPPayload; +typedef struct _GstBaseRTPPayloadPrivate GstBaseRTPPayloadPrivate; +typedef struct _GstBaseRTPPayloadClass GstBaseRTPPayloadClass; + +/** + * GST_BASE_RTP_PAYLOAD_SINKPAD: + * @payload: a #GstBaseRTPPayload + * + * Get access to the sinkpad of @payload. + */ +#define GST_BASE_RTP_PAYLOAD_SINKPAD(payload) (GST_BASE_RTP_PAYLOAD (payload)->sinkpad) +/** + * GST_BASE_RTP_PAYLOAD_SRCPAD: + * @payload: a #GstBaseRTPPayload + * + * Get access to the srcpad of @payload. + */ +#define GST_BASE_RTP_PAYLOAD_SRCPAD(payload) (GST_BASE_RTP_PAYLOAD (payload)->srcpad) + +/** + * GST_BASE_RTP_PAYLOAD_PT: + * @payload: a #GstBaseRTPPayload + * + * Get access to the configured payload type of @payload. + */ +#define GST_BASE_RTP_PAYLOAD_PT(payload) (GST_BASE_RTP_PAYLOAD (payload)->pt) +/** + * GST_BASE_RTP_PAYLOAD_MTU: + * @payload: a #GstBaseRTPPayload + * + * Get access to the configured MTU of @payload. + */ +#define GST_BASE_RTP_PAYLOAD_MTU(payload) (GST_BASE_RTP_PAYLOAD (payload)->mtu) + +struct _GstBaseRTPPayload +{ + GstElement element; + + /*< private >*/ + GstPad *sinkpad; + GstPad *srcpad; + + /* FIXME 0.11: none of these GRands are used anymore, remove them */ + GRand *seq_rand; + GRand *ssrc_rand; + GRand *ts_rand; + + guint32 ts_base; + guint16 seqnum_base; + + gchar *media; + gchar *encoding_name; + gboolean dynamic; + guint32 clock_rate; + + gint32 ts_offset; + guint32 timestamp; + gint16 seqnum_offset; + guint16 seqnum; + gint64 max_ptime; + guint pt; + guint ssrc; + guint current_ssrc; + guint mtu; + + GstSegment segment; + + guint64 min_ptime; + + /*< private >*/ + GstBaseRTPPayloadPrivate *priv; + + union { + struct { + guint64 ptime; /* in ns */ + guint64 ptime_multiple; /* in ns */ + } ABI; + gpointer _gst_reserved[GST_PADDING - (sizeof(guint64)/sizeof(gpointer)) - 1]; + } abidata; +}; + +struct _GstBaseRTPPayloadClass +{ + GstElementClass parent_class; + + /* receive caps on the sink pad, configure the payloader. */ + gboolean (*set_caps) (GstBaseRTPPayload *payload, GstCaps *caps); + /* handle a buffer, perform 0 or more gst_basertppayload_push() on + * the RTP buffers. This function takes ownership of the buffer. */ + GstFlowReturn (*handle_buffer) (GstBaseRTPPayload *payload, + GstBuffer *buffer); + gboolean (*handle_event) (GstPad * pad, GstEvent * event); + GstCaps * (*get_caps) (GstBaseRTPPayload *payload, GstPad * pad); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING-2]; +}; + +GType gst_basertppayload_get_type (void); + +void gst_basertppayload_set_options (GstBaseRTPPayload *payload, + const gchar *media, + gboolean dynamic, + const gchar *encoding_name, + guint32 clock_rate); + +gboolean gst_basertppayload_set_outcaps (GstBaseRTPPayload *payload, + const gchar *fieldname, ...); + +gboolean gst_basertppayload_is_filled (GstBaseRTPPayload *payload, + guint size, GstClockTime duration); + +GstFlowReturn gst_basertppayload_push (GstBaseRTPPayload *payload, + GstBuffer *buffer); + +GstFlowReturn gst_basertppayload_push_list (GstBaseRTPPayload *payload, + GstBufferList *list); + +G_END_DECLS + +#endif /* __GST_BASE_RTP_PAYLOAD_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.c new file mode 100644 index 0000000..3b37c6f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.c @@ -0,0 +1,2031 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * gstrtcpbuffer.h: various helper functions to manipulate buffers + * with RTCP payload. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtcpbuffer + * @short_description: Helper methods for dealing with RTCP buffers + * @see_also: #GstBaseRTPPayload, #GstBaseRTPDepayload, #gstrtpbuffer + * + * Note: The API in this module is not yet declared stable. + * + * + * + * The GstRTPCBuffer helper functions makes it easy to parse and create regular + * #GstBuffer objects that contain compound RTCP packets. These buffers are typically + * of 'application/x-rtcp' #GstCaps. + * + * + * An RTCP buffer consists of 1 or more #GstRTCPPacket structures that you can + * retrieve with gst_rtcp_buffer_get_first_packet(). #GstRTCPPacket acts as a pointer + * into the RTCP buffer; you can move to the next packet with + * gst_rtcp_packet_move_to_next(). + * + * + * + * Last reviewed on 2007-03-26 (0.10.13) + * + * Since: 0.10.13 + */ + +#include + +#include "gstrtcpbuffer.h" + +/** + * gst_rtcp_buffer_new_take_data: + * @data: data for the new buffer + * @len: the length of data + * + * Create a new buffer and set the data and size of the buffer to @data and @len + * respectively. @data will be freed when the buffer is unreffed, so this + * function transfers ownership of @data to the new buffer. + * + * Returns: A newly allocated buffer with @data and of size @len. + */ +GstBuffer * +gst_rtcp_buffer_new_take_data (gpointer data, guint len) +{ + GstBuffer *result; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + + result = gst_buffer_new (); + + GST_BUFFER_MALLOCDATA (result) = data; + GST_BUFFER_DATA (result) = data; + GST_BUFFER_SIZE (result) = len; + + return result; +} + +/** + * gst_rtcp_buffer_new_copy_data: + * @data: data for the new buffer + * @len: the length of data + * + * Create a new buffer and set the data to a copy of @len + * bytes of @data and the size to @len. The data will be freed when the buffer + * is freed. + * + * Returns: A newly allocated buffer with a copy of @data and of size @len. + */ +GstBuffer * +gst_rtcp_buffer_new_copy_data (gpointer data, guint len) +{ + return gst_rtcp_buffer_new_take_data (g_memdup (data, len), len); +} + +/** + * gst_rtcp_buffer_validate_data: + * @data: the data to validate + * @len: the length of @data to validate + * + * Check if the @data and @size point to the data of a valid RTCP (compound) + * packet. + * Use this function to validate a packet before using the other functions in + * this module. + * + * Returns: TRUE if the data points to a valid RTCP packet. + */ +gboolean +gst_rtcp_buffer_validate_data (guint8 * data, guint len) +{ + guint16 header_mask; + guint16 header_len; + guint8 version; + guint data_len; + gboolean padding; + guint8 pad_bytes; + + g_return_val_if_fail (data != NULL, FALSE); + + /* we need 4 bytes for the type and length */ + if (G_UNLIKELY (len < 4)) + goto wrong_length; + + /* first packet must be RR or SR and version must be 2 */ + header_mask = ((data[0] << 8) | data[1]) & GST_RTCP_VALID_MASK; + if (G_UNLIKELY (header_mask != GST_RTCP_VALID_VALUE)) + goto wrong_mask; + + /* no padding when mask succeeds */ + padding = FALSE; + + /* store len */ + data_len = len; + + while (TRUE) { + /* get packet length */ + header_len = (((data[2] << 8) | data[3]) + 1) << 2; + if (data_len < header_len) + goto wrong_length; + + /* move to next compount packet */ + data += header_len; + data_len -= header_len; + + /* we are at the end now */ + if (data_len < 4) + break; + + /* check version of new packet */ + version = data[0] & 0xc0; + if (version != (GST_RTCP_VERSION << 6)) + goto wrong_version; + + /* padding only allowed on last packet */ + if ((padding = data[0] & 0x20)) + break; + } + if (data_len > 0) { + /* some leftover bytes, check padding */ + if (!padding) + goto wrong_length; + + /* get padding */ + pad_bytes = data[data_len - 1]; + if (data_len != pad_bytes) + goto wrong_padding; + } + return TRUE; + + /* ERRORS */ +wrong_length: + { + GST_DEBUG ("len check failed"); + return FALSE; + } +wrong_mask: + { + GST_DEBUG ("mask check failed (%04x != %04x)", header_mask, + GST_RTCP_VALID_VALUE); + return FALSE; + } +wrong_version: + { + GST_DEBUG ("wrong version (%d < 2)", version >> 6); + return FALSE; + } +wrong_padding: + { + GST_DEBUG ("padding check failed"); + return FALSE; + } +} + +/** + * gst_rtcp_buffer_validate: + * @buffer: the buffer to validate + * + * Check if the data pointed to by @buffer is a valid RTCP packet using + * gst_rtcp_buffer_validate_data(). + * + * Returns: TRUE if @buffer is a valid RTCP packet. + */ +gboolean +gst_rtcp_buffer_validate (GstBuffer * buffer) +{ + guint8 *data; + guint len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + data = GST_BUFFER_DATA (buffer); + len = GST_BUFFER_SIZE (buffer); + + return gst_rtcp_buffer_validate_data (data, len); +} + +/** + * gst_rtcp_buffer_new: + * @mtu: the maximum mtu size. + * + * Create a new buffer for constructing RTCP packets. The packet will have a + * maximum size of @mtu. + * + * Returns: A newly allocated buffer. + */ +GstBuffer * +gst_rtcp_buffer_new (guint mtu) +{ + GstBuffer *result; + + g_return_val_if_fail (mtu > 0, NULL); + + result = gst_buffer_new (); + GST_BUFFER_MALLOCDATA (result) = g_malloc0 (mtu); + GST_BUFFER_DATA (result) = GST_BUFFER_MALLOCDATA (result); + GST_BUFFER_SIZE (result) = mtu; + + return result; +} + +/** + * gst_rtcp_buffer_end: + * @buffer: a buffer with an RTCP packet + * + * Finish @buffer after being constructured. This function is usually called + * after gst_rtcp_buffer_new() and after adding the RTCP items to the new buffer. + * + * The function adjusts the size of @buffer with the total length of all the + * added packets. + */ +void +gst_rtcp_buffer_end (GstBuffer * buffer) +{ + GstRTCPPacket packet; + + g_return_if_fail (GST_IS_BUFFER (buffer)); + + /* move to the first free space */ + if (gst_rtcp_buffer_get_first_packet (buffer, &packet)) + while (gst_rtcp_packet_move_to_next (&packet)); + + /* shrink size */ + GST_BUFFER_SIZE (buffer) = packet.offset; +} + +/** + * gst_rtcp_buffer_get_packet_count: + * @buffer: a valid RTCP buffer + * + * Get the number of RTCP packets in @buffer. + * + * Returns: the number of RTCP packets in @buffer. + */ +guint +gst_rtcp_buffer_get_packet_count (GstBuffer * buffer) +{ + GstRTCPPacket packet; + guint count; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), 0); + + count = 0; + if (gst_rtcp_buffer_get_first_packet (buffer, &packet)) { + do { + count++; + } while (gst_rtcp_packet_move_to_next (&packet)); + } + + return count; +} + +/** + * read_packet_header: + * @packet: a packet + * + * Read the packet headers for the packet pointed to by @packet. + * + * Returns: TRUE if @packet pointed to a valid header. + */ +static gboolean +read_packet_header (GstRTCPPacket * packet) +{ + guint8 *data; + guint size; + guint offset; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + data = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + + offset = packet->offset; + + /* check if we are at the end of the buffer, we add 4 because we also want to + * ensure we can read the header. */ + if (offset + 4 > size) + return FALSE; + + if ((data[offset] & 0xc0) != (GST_RTCP_VERSION << 6)) + return FALSE; + + /* read count, type and length */ + packet->padding = (data[offset] & 0x20) == 0x20; + packet->count = data[offset] & 0x1f; + packet->type = data[offset + 1]; + packet->length = (data[offset + 2] << 8) | data[offset + 3]; + packet->item_offset = 4; + packet->item_count = 0; + packet->entry_offset = 4; + + return TRUE; +} + +/** + * gst_rtcp_buffer_get_first_packet: + * @buffer: a valid RTCP buffer + * @packet: a #GstRTCPPacket + * + * Initialize a new #GstRTCPPacket pointer that points to the first packet in + * @buffer. + * + * Returns: TRUE if the packet existed in @buffer. + */ +gboolean +gst_rtcp_buffer_get_first_packet (GstBuffer * buffer, GstRTCPPacket * packet) +{ + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (packet != NULL, FALSE); + + /* init to 0 */ + packet->buffer = buffer; + packet->offset = 0; + packet->type = GST_RTCP_TYPE_INVALID; + + if (!read_packet_header (packet)) + return FALSE; + + return TRUE; +} + +/** + * gst_rtcp_packet_move_to_next: + * @packet: a #GstRTCPPacket + * + * Move the packet pointer @packet to the next packet in the payload. + * Use gst_rtcp_buffer_get_first_packet() to initialize @packet. + * + * Returns: TRUE if @packet is pointing to a valid packet after calling this + * function. + */ +gboolean +gst_rtcp_packet_move_to_next (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* if we have a padding or invalid packet, it must be the last, + * return FALSE */ + if (packet->type == GST_RTCP_TYPE_INVALID || packet->padding) + goto end; + + /* move to next packet. Add 4 because the header is not included in length */ + packet->offset += (packet->length << 2) + 4; + + /* try to read new header */ + if (!read_packet_header (packet)) + goto end; + + return TRUE; + + /* ERRORS */ +end: + { + packet->type = GST_RTCP_TYPE_INVALID; + return FALSE; + } +} + +/** + * gst_rtcp_buffer_add_packet: + * @buffer: a valid RTCP buffer + * @type: the #GstRTCPType of the new packet + * @packet: pointer to new packet + * + * Add a new packet of @type to @buffer. @packet will point to the newly created + * packet. + * + * Returns: %TRUE if the packet could be created. This function returns %FALSE + * if the max mtu is exceeded for the buffer. + */ +gboolean +gst_rtcp_buffer_add_packet (GstBuffer * buffer, GstRTCPType type, + GstRTCPPacket * packet) +{ + guint len, size; + guint8 *data; + gboolean result; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (type != GST_RTCP_TYPE_INVALID, FALSE); + g_return_val_if_fail (packet != NULL, FALSE); + + /* find free space */ + if (gst_rtcp_buffer_get_first_packet (buffer, packet)) + while (gst_rtcp_packet_move_to_next (packet)); + + size = GST_BUFFER_SIZE (buffer); + + /* packet->offset is now pointing to the next free offset in the buffer to + * start a compount packet. Next we figure out if we have enough free space in + * the buffer to continue. */ + switch (type) { + case GST_RTCP_TYPE_SR: + len = 28; + break; + case GST_RTCP_TYPE_RR: + len = 8; + break; + case GST_RTCP_TYPE_SDES: + len = 4; + break; + case GST_RTCP_TYPE_BYE: + len = 4; + break; + case GST_RTCP_TYPE_APP: + len = 12; + break; + case GST_RTCP_TYPE_RTPFB: + len = 12; + break; + case GST_RTCP_TYPE_PSFB: + len = 12; + break; + default: + goto unknown_type; + } + if (packet->offset + len >= size) + goto no_space; + + data = GST_BUFFER_DATA (buffer) + packet->offset; + + data[0] = (GST_RTCP_VERSION << 6); + data[1] = type; + /* length is stored in multiples of 32 bit words minus the length of the + * header */ + len = (len - 4) >> 2; + data[2] = len >> 8; + data[3] = len & 0xff; + + /* now try to position to the packet */ + result = read_packet_header (packet); + + return result; + + /* ERRORS */ +unknown_type: + { + g_warning ("unknown type %d", type); + return FALSE; + } +no_space: + { + return FALSE; + } +} + +/** + * gst_rtcp_packet_remove: + * @packet: a #GstRTCPPacket + * + * Removes the packet pointed to by @packet and moves pointer to the next one + * + * Returns: TRUE if @packet is pointing to a valid packet after calling this + * function. + */ +gboolean +gst_rtcp_packet_remove (GstRTCPPacket * packet) +{ + gboolean ret = FALSE; + guint offset = 0; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE); + + /* The next packet starts at offset + length + 4 (the header) */ + offset = packet->offset + (packet->length << 2) + 4; + + /* Overwrite this packet with the rest of the data */ + memmove (GST_BUFFER_DATA (packet->buffer) + packet->offset, + GST_BUFFER_DATA (packet->buffer) + offset, + GST_BUFFER_SIZE (packet->buffer) - offset); + + /* try to read next header */ + ret = read_packet_header (packet); + if (!ret) + packet->type = GST_RTCP_TYPE_INVALID; + + return ret; +} + +/** + * gst_rtcp_packet_get_padding: + * @packet: a valid #GstRTCPPacket + * + * Get the packet padding of the packet pointed to by @packet. + * + * Returns: If the packet has the padding bit set. + */ +gboolean +gst_rtcp_packet_get_padding (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, FALSE); + + return packet->padding; +} + +/** + * gst_rtcp_packet_get_type: + * @packet: a valid #GstRTCPPacket + * + * Get the packet type of the packet pointed to by @packet. + * + * Returns: The packet type or GST_RTCP_TYPE_INVALID when @packet is not + * pointing to a valid packet. + */ +GstRTCPType +gst_rtcp_packet_get_type (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, GST_RTCP_TYPE_INVALID); + + return packet->type; +} + +/** + * gst_rtcp_packet_get_count: + * @packet: a valid #GstRTCPPacket + * + * Get the count field in @packet. + * + * Returns: The count field in @packet or -1 if @packet does not point to a + * valid packet. + */ +guint8 +gst_rtcp_packet_get_count (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, -1); + g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, -1); + + return packet->count; +} + +/** + * gst_rtcp_packet_get_length: + * @packet: a valid #GstRTCPPacket + * + * Get the length field of @packet. This is the length of the packet in + * 32-bit words minus one. + * + * Returns: The length field of @packet. + */ +guint16 +gst_rtcp_packet_get_length (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type != GST_RTCP_TYPE_INVALID, 0); + + return packet->length; +} + +/** + * gst_rtcp_packet_sr_get_sender_info: + * @packet: a valid SR #GstRTCPPacket + * @ssrc: result SSRC + * @ntptime: result NTP time + * @rtptime: result RTP time + * @packet_count: result packet count + * @octet_count: result octect count + * + * Parse the SR sender info and store the values. + */ +void +gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket * packet, guint32 * ssrc, + guint64 * ntptime, guint32 * rtptime, guint32 * packet_count, + guint32 * octet_count) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_SR); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + if (ssrc) + *ssrc = GST_READ_UINT32_BE (data); + data += 4; + if (ntptime) + *ntptime = GST_READ_UINT64_BE (data); + data += 8; + if (rtptime) + *rtptime = GST_READ_UINT32_BE (data); + data += 4; + if (packet_count) + *packet_count = GST_READ_UINT32_BE (data); + data += 4; + if (octet_count) + *octet_count = GST_READ_UINT32_BE (data); +} + +/** + * gst_rtcp_packet_sr_set_sender_info: + * @packet: a valid SR #GstRTCPPacket + * @ssrc: the SSRC + * @ntptime: the NTP time + * @rtptime: the RTP time + * @packet_count: the packet count + * @octet_count: the octect count + * + * Set the given values in the SR packet @packet. + */ +void +gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket * packet, guint32 ssrc, + guint64 ntptime, guint32 rtptime, guint32 packet_count, guint32 octet_count) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_SR); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + GST_WRITE_UINT32_BE (data, ssrc); + data += 4; + GST_WRITE_UINT64_BE (data, ntptime); + data += 8; + GST_WRITE_UINT32_BE (data, rtptime); + data += 4; + GST_WRITE_UINT32_BE (data, packet_count); + data += 4; + GST_WRITE_UINT32_BE (data, octet_count); +} + +/** + * gst_rtcp_packet_rr_get_ssrc: + * @packet: a valid RR #GstRTCPPacket + * + * Get the ssrc field of the RR @packet. + * + * Returns: the ssrc. + */ +guint32 +gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket * packet) +{ + guint8 *data; + guint32 ssrc; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + ssrc = GST_READ_UINT32_BE (data); + + return ssrc; +} + +/** + * gst_rtcp_packet_rr_set_ssrc: + * @packet: a valid RR #GstRTCPPacket + * @ssrc: the SSRC to set + * + * Set the ssrc field of the RR @packet. + */ +void +gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket * packet, guint32 ssrc) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RR); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + GST_WRITE_UINT32_BE (data, ssrc); +} + +/** + * gst_rtcp_packet_get_rb_count: + * @packet: a valid SR or RR #GstRTCPPacket + * + * Get the number of report blocks in @packet. + * + * Returns: The number of report blocks in @packet. + */ +guint +gst_rtcp_packet_get_rb_count (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR || + packet->type == GST_RTCP_TYPE_SR, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + return packet->count; +} + +/** + * gst_rtcp_packet_get_rb: + * @packet: a valid SR or RR #GstRTCPPacket + * @nth: the nth report block in @packet + * @ssrc: result for data source being reported + * @fractionlost: result for fraction lost since last SR/RR + * @packetslost: result for the cumululative number of packets lost + * @exthighestseq: result for the extended last sequence number received + * @jitter: result for the interarrival jitter + * @lsr: result for the last SR packet from this source + * @dlsr: result for the delay since last SR packet + * + * Parse the values of the @nth report block in @packet and store the result in + * the values. + */ +void +gst_rtcp_packet_get_rb (GstRTCPPacket * packet, guint nth, guint32 * ssrc, + guint8 * fractionlost, gint32 * packetslost, guint32 * exthighestseq, + guint32 * jitter, guint32 * lsr, guint32 * dlsr) +{ + guint8 *data; + guint32 tmp; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RR || + packet->type == GST_RTCP_TYPE_SR); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + if (packet->type == GST_RTCP_TYPE_RR) + data += 4; + else + data += 24; + + /* move to requested index */ + data += (nth * 24); + + if (ssrc) + *ssrc = GST_READ_UINT32_BE (data); + data += 4; + tmp = GST_READ_UINT32_BE (data); + if (fractionlost) + *fractionlost = (tmp >> 24); + if (packetslost) { + /* sign extend */ + if (tmp & 0x00800000) + tmp |= 0xff000000; + else + tmp &= 0x00ffffff; + *packetslost = (gint32) tmp; + } + data += 4; + if (exthighestseq) + *exthighestseq = GST_READ_UINT32_BE (data); + data += 4; + if (jitter) + *jitter = GST_READ_UINT32_BE (data); + data += 4; + if (lsr) + *lsr = GST_READ_UINT32_BE (data); + data += 4; + if (dlsr) + *dlsr = GST_READ_UINT32_BE (data); +} + +/** + * gst_rtcp_packet_add_rb: + * @packet: a valid SR or RR #GstRTCPPacket + * @ssrc: data source being reported + * @fractionlost: fraction lost since last SR/RR + * @packetslost: the cumululative number of packets lost + * @exthighestseq: the extended last sequence number received + * @jitter: the interarrival jitter + * @lsr: the last SR packet from this source + * @dlsr: the delay since last SR packet + * + * Add a new report block to @packet with the given values. + * + * Returns: %TRUE if the packet was created. This function can return %FALSE if + * the max MTU is exceeded or the number of report blocks is greater than + * #GST_RTCP_MAX_RB_COUNT. + */ +gboolean +gst_rtcp_packet_add_rb (GstRTCPPacket * packet, guint32 ssrc, + guint8 fractionlost, gint32 packetslost, guint32 exthighestseq, + guint32 jitter, guint32 lsr, guint32 dlsr) +{ + guint8 *data; + guint size, offset; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RR || + packet->type == GST_RTCP_TYPE_SR, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + if (packet->count >= GST_RTCP_MAX_RB_COUNT) + goto no_space; + + data = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + + /* skip header */ + offset = packet->offset + 4; + if (packet->type == GST_RTCP_TYPE_RR) + offset += 4; + else + offset += 24; + + /* move to current index */ + offset += (packet->count * 24); + + /* we need 24 free bytes now */ + if (offset + 24 >= size) + goto no_space; + + /* increment packet count and length */ + packet->count++; + data[packet->offset]++; + packet->length += 6; + data[packet->offset + 2] = (packet->length) >> 8; + data[packet->offset + 3] = (packet->length) & 0xff; + + /* move to new report block offset */ + data += offset; + + GST_WRITE_UINT32_BE (data, ssrc); + data += 4; + GST_WRITE_UINT32_BE (data, (fractionlost << 24) | (packetslost & 0xffffff)); + data += 4; + GST_WRITE_UINT32_BE (data, exthighestseq); + data += 4; + GST_WRITE_UINT32_BE (data, jitter); + data += 4; + GST_WRITE_UINT32_BE (data, lsr); + data += 4; + GST_WRITE_UINT32_BE (data, dlsr); + + return TRUE; + +no_space: + { + return FALSE; + } +} + +/** + * gst_rtcp_packet_set_rb: + * @packet: a valid SR or RR #GstRTCPPacket + * @nth: the nth report block to set + * @ssrc: data source being reported + * @fractionlost: fraction lost since last SR/RR + * @packetslost: the cumululative number of packets lost + * @exthighestseq: the extended last sequence number received + * @jitter: the interarrival jitter + * @lsr: the last SR packet from this source + * @dlsr: the delay since last SR packet + * + * Set the @nth new report block in @packet with the given values. + * + * Note: Not implemented. + */ +void +gst_rtcp_packet_set_rb (GstRTCPPacket * packet, guint nth, guint32 ssrc, + guint8 fractionlost, gint32 packetslost, guint32 exthighestseq, + guint32 jitter, guint32 lsr, guint32 dlsr) +{ + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RR || + packet->type == GST_RTCP_TYPE_SR); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + g_warning ("not implemented"); +} + + +/** + * gst_rtcp_packet_sdes_get_item_count: + * @packet: a valid SDES #GstRTCPPacket + * + * Get the number of items in the SDES packet @packet. + * + * Returns: The number of items in @packet. + */ +guint +gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + return packet->count; +} + +/** + * gst_rtcp_packet_sdes_first_item: + * @packet: a valid SDES #GstRTCPPacket + * + * Move to the first SDES item in @packet. + * + * Returns: TRUE if there was a first item. + */ +gboolean +gst_rtcp_packet_sdes_first_item (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + packet->item_offset = 4; + packet->item_count = 0; + packet->entry_offset = 4; + + if (packet->count == 0) + return FALSE; + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_next_item: + * @packet: a valid SDES #GstRTCPPacket + * + * Move to the next SDES item in @packet. + * + * Returns: TRUE if there was a next item. + */ +gboolean +gst_rtcp_packet_sdes_next_item (GstRTCPPacket * packet) +{ + guint8 *data; + guint offset; + guint len; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* if we are at the last item, we are done */ + if (packet->item_count == packet->count) + return FALSE; + + /* move to SDES */ + data = GST_BUFFER_DATA (packet->buffer); + data += packet->offset; + /* move to item */ + offset = packet->item_offset; + /* skip SSRC */ + offset += 4; + + /* don't overrun */ + len = (packet->length << 2); + + while (offset < len) { + if (data[offset] == 0) { + /* end of list, round to next 32-bit word */ + offset = (offset + 4) & ~3; + break; + } + offset += data[offset + 1] + 2; + } + if (offset >= len) + return FALSE; + + packet->item_offset = offset; + packet->item_count++; + packet->entry_offset = 4; + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_get_ssrc: + * @packet: a valid SDES #GstRTCPPacket + * + * Get the SSRC of the current SDES item. + * + * Returns: the SSRC of the current item. + */ +guint32 +gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket * packet) +{ + guint32 ssrc; + guint8 *data; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + /* move to SDES */ + data = GST_BUFFER_DATA (packet->buffer); + data += packet->offset; + /* move to item */ + data += packet->item_offset; + + ssrc = GST_READ_UINT32_BE (data); + + return ssrc; +} + +/** + * gst_rtcp_packet_sdes_first_entry: + * @packet: a valid SDES #GstRTCPPacket + * + * Move to the first SDES entry in the current item. + * + * Returns: %TRUE if there was a first entry. + */ +gboolean +gst_rtcp_packet_sdes_first_entry (GstRTCPPacket * packet) +{ + guint8 *data; + guint len, offset; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* move to SDES */ + data = GST_BUFFER_DATA (packet->buffer); + data += packet->offset; + /* move to item */ + offset = packet->item_offset; + /* skip SSRC */ + offset += 4; + + packet->entry_offset = 4; + + /* don't overrun */ + len = (packet->length << 2); + if (offset >= len) + return FALSE; + + if (data[offset] == 0) + return FALSE; + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_next_entry: + * @packet: a valid SDES #GstRTCPPacket + * + * Move to the next SDES entry in the current item. + * + * Returns: %TRUE if there was a next entry. + */ +gboolean +gst_rtcp_packet_sdes_next_entry (GstRTCPPacket * packet) +{ + guint8 *data; + guint len, offset, item_len; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* move to SDES */ + data = GST_BUFFER_DATA (packet->buffer); + data += packet->offset; + /* move to item */ + offset = packet->item_offset; + /* move to entry */ + offset += packet->entry_offset; + + item_len = data[offset + 1] + 2; + /* skip item */ + offset += item_len; + + /* don't overrun */ + len = (packet->length << 2); + if (offset >= len) + return FALSE; + + packet->entry_offset += item_len; + + /* check for end of list */ + if (data[offset] == 0) + return FALSE; + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_get_entry: + * @packet: a valid SDES #GstRTCPPacket + * @type: result of the entry type + * @len: result length of the entry data + * @data: result entry data + * + * Get the data of the current SDES item entry. @type (when not NULL) will + * contain the type of the entry. @data (when not NULL) will point to @len + * bytes. + * + * When @type refers to a text item, @data will point to a UTF8 string. Note + * that this UTF8 string is NOT null-terminated. Use + * gst_rtcp_packet_sdes_copy_entry() to get a null-termined copy of the entry. + * + * Returns: %TRUE if there was valid data. + */ +gboolean +gst_rtcp_packet_sdes_get_entry (GstRTCPPacket * packet, + GstRTCPSDESType * type, guint8 * len, guint8 ** data) +{ + guint8 *bdata; + guint offset; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* move to SDES */ + bdata = GST_BUFFER_DATA (packet->buffer); + bdata += packet->offset; + /* move to item */ + offset = packet->item_offset; + /* move to entry */ + offset += packet->entry_offset; + + if (bdata[offset] == 0) + return FALSE; + + if (type) + *type = bdata[offset]; + if (len) + *len = bdata[offset + 1]; + if (data) + *data = &bdata[offset + 2]; + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_copy_entry: + * @packet: a valid SDES #GstRTCPPacket + * @type: result of the entry type + * @len: result length of the entry data + * @data: result entry data + * + * This function is like gst_rtcp_packet_sdes_get_entry() but it returns a + * null-terminated copy of the data instead. use g_free() after usage. + * + * Returns: %TRUE if there was valid data. + */ +gboolean +gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket * packet, + GstRTCPSDESType * type, guint8 * len, guint8 ** data) +{ + guint8 *tdata; + guint8 tlen; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + if (!gst_rtcp_packet_sdes_get_entry (packet, type, &tlen, &tdata)) + return FALSE; + + if (len) + *len = tlen; + if (data) + *data = (guint8 *) g_strndup ((gchar *) tdata, tlen); + + return TRUE; +} + +/** + * gst_rtcp_packet_sdes_add_item: + * @packet: a valid SDES #GstRTCPPacket + * @ssrc: the SSRC of the new item to add + * + * Add a new SDES item for @ssrc to @packet. + * + * Returns: %TRUE if the item could be added, %FALSE if the maximum amount of + * items has been exceeded for the SDES packet or the MTU has been reached. + */ +gboolean +gst_rtcp_packet_sdes_add_item (GstRTCPPacket * packet, guint32 ssrc) +{ + guint8 *data; + guint offset, size; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* increment item count when possible */ + if (packet->count >= GST_RTCP_MAX_SDES_ITEM_COUNT) + goto no_space; + + /* pretend there is a next packet for the next call */ + packet->count++; + + /* jump over current item */ + gst_rtcp_packet_sdes_next_item (packet); + + /* move to SDES */ + data = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + data += packet->offset; + /* move to current item */ + offset = packet->item_offset; + + /* we need 2 free words now */ + if (offset + 8 >= size) + goto no_next; + + /* write SSRC */ + GST_WRITE_UINT32_BE (&data[offset], ssrc); + /* write 0 entry with padding */ + GST_WRITE_UINT32_BE (&data[offset + 4], 0); + + /* update count */ + data[0] = (data[0] & 0xe0) | packet->count; + /* update length, we added 2 words */ + packet->length += 2; + data[2] = (packet->length) >> 8; + data[3] = (packet->length) & 0xff; + + return TRUE; + + /* ERRORS */ +no_space: + { + return FALSE; + } +no_next: + { + packet->count--; + return FALSE; + } +} + +/** + * gst_rtcp_packet_sdes_add_entry: + * @packet: a valid SDES #GstRTCPPacket + * @type: the #GstRTCPSDESType of the SDES entry + * @len: the data length + * @data: the data + * + * Add a new SDES entry to the current item in @packet. + * + * Returns: %TRUE if the item could be added, %FALSE if the MTU has been + * reached. + */ +gboolean +gst_rtcp_packet_sdes_add_entry (GstRTCPPacket * packet, GstRTCPSDESType type, + guint8 len, const guint8 * data) +{ + guint8 *bdata; + guint offset, size, padded; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_SDES, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + /* move to SDES */ + bdata = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + bdata += packet->offset; + /* move to item */ + offset = packet->item_offset; + /* move to entry */ + offset += packet->entry_offset; + + /* add 1 byte end and up to 3 bytes padding to fill a full 32 bit word */ + padded = (offset + 2 + len + 1 + 3) & ~3; + + /* we need enough space for type, len, data and padding */ + if (packet->offset + padded >= size) + goto no_space; + + bdata[offset] = type; + bdata[offset + 1] = len; + memcpy (&bdata[offset + 2], data, len); + bdata[offset + 2 + len] = 0; + + /* calculate new packet length */ + packet->length = (padded - 4) >> 2; + bdata[2] = (packet->length) >> 8; + bdata[3] = (packet->length) & 0xff; + + /* position to new next entry */ + packet->entry_offset += 2 + len; + + return TRUE; + + /* ERRORS */ +no_space: + { + return FALSE; + } +} + +/** + * gst_rtcp_packet_bye_get_ssrc_count: + * @packet: a valid BYE #GstRTCPPacket + * + * Get the number of SSRC fields in @packet. + * + * Returns: The number of SSRC fields in @packet. + */ +guint +gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, -1); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, -1); + + return packet->count; +} + +/** + * gst_rtcp_packet_bye_get_nth_ssrc: + * @packet: a valid BYE #GstRTCPPacket + * @nth: the nth SSRC to get + * + * Get the @nth SSRC of the BYE @packet. + * + * Returns: The @nth SSRC of @packet. + */ +guint32 +gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket * packet, guint nth) +{ + guint8 *data; + guint offset; + guint32 ssrc; + guint8 sc; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + /* get amount of sources and check that we don't read too much */ + sc = packet->count; + if (nth >= sc) + return 0; + + /* get offset in 32-bits words into packet, skip the header */ + offset = 1 + nth; + /* check that we don't go past the packet length */ + if (offset > packet->length) + return 0; + + /* scale to bytes */ + offset <<= 2; + offset += packet->offset; + + /* check if the packet is valid */ + if (offset + 4 > GST_BUFFER_SIZE (packet->buffer)) + return 0; + + data = GST_BUFFER_DATA (packet->buffer); + data += offset; + + ssrc = GST_READ_UINT32_BE (data); + + return ssrc; +} + +/** + * gst_rtcp_packet_bye_add_ssrc: + * @packet: a valid BYE #GstRTCPPacket + * @ssrc: an SSRC to add + * + * Add @ssrc to the BYE @packet. + * + * Returns: %TRUE if the ssrc was added. This function can return %FALSE if + * the max MTU is exceeded or the number of sources blocks is greater than + * #GST_RTCP_MAX_BYE_SSRC_COUNT. + */ +gboolean +gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket * packet, guint32 ssrc) +{ + guint8 *data; + guint size, offset; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + if (packet->count >= GST_RTCP_MAX_BYE_SSRC_COUNT) + goto no_space; + + data = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + + /* skip header */ + offset = packet->offset + 4; + + /* move to current index */ + offset += (packet->count * 4); + + if (offset + 4 >= size) + goto no_space; + + /* increment packet count and length */ + packet->count++; + data[packet->offset]++; + packet->length += 1; + data[packet->offset + 2] = (packet->length) >> 8; + data[packet->offset + 3] = (packet->length) & 0xff; + + /* move to new SSRC offset and write ssrc */ + data += offset; + GST_WRITE_UINT32_BE (data, ssrc); + + return TRUE; + + /* ERRORS */ +no_space: + { + return FALSE; + } +} + +/** + * gst_rtcp_packet_bye_add_ssrcs: + * @packet: a valid BYE #GstRTCPPacket + * @ssrc: an array of SSRCs to add + * @len: number of elements in @ssrc + * + * Adds @len SSRCs in @ssrc to BYE @packet. + * + * Returns: %TRUE if the all the SSRCs were added. This function can return %FALSE if + * the max MTU is exceeded or the number of sources blocks is greater than + * #GST_RTCP_MAX_BYE_SSRC_COUNT. + */ +gboolean +gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket * packet, guint32 * ssrc, + guint len) +{ + guint i; + gboolean res; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + res = TRUE; + for (i = 0; i < len && res; i++) { + res = gst_rtcp_packet_bye_add_ssrc (packet, ssrc[i]); + } + return res; +} + +/* get the offset in packet of the reason length */ +static guint +get_reason_offset (GstRTCPPacket * packet) +{ + guint offset; + + /* get amount of sources plus header */ + offset = 1 + packet->count; + + /* check that we don't go past the packet length */ + if (offset > packet->length) + return 0; + + /* scale to bytes */ + offset <<= 2; + offset += packet->offset; + + /* check if the packet is valid */ + if (offset + 1 > GST_BUFFER_SIZE (packet->buffer)) + return 0; + + return offset; +} + +/** + * gst_rtcp_packet_bye_get_reason_len: + * @packet: a valid BYE #GstRTCPPacket + * + * Get the length of the reason string. + * + * Returns: The length of the reason string or 0 when there is no reason string + * present. + */ +guint8 +gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket * packet) +{ + guint8 *data; + guint roffset; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + roffset = get_reason_offset (packet); + if (roffset == 0) + return 0; + + data = GST_BUFFER_DATA (packet->buffer); + + return data[roffset]; +} + +/** + * gst_rtcp_packet_bye_get_reason: + * @packet: a valid BYE #GstRTCPPacket + * + * Get the reason in @packet. + * + * Returns: The reason for the BYE @packet or NULL if the packet did not contain + * a reason string. The string must be freed with g_free() after usage. + */ +gchar * +gst_rtcp_packet_bye_get_reason (GstRTCPPacket * packet) +{ + guint8 *data; + guint roffset; + guint8 len; + + g_return_val_if_fail (packet != NULL, NULL); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, NULL); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), NULL); + + roffset = get_reason_offset (packet); + if (roffset == 0) + return NULL; + + data = GST_BUFFER_DATA (packet->buffer); + + /* get length of reason string */ + len = data[roffset]; + if (len == 0) + return NULL; + + /* move to string */ + roffset += 1; + + /* check if enough data to copy */ + if (roffset + len > GST_BUFFER_SIZE (packet->buffer)) + return NULL; + + return g_strndup ((gconstpointer) (data + roffset), len); +} + +/** + * gst_rtcp_packet_bye_set_reason: + * @packet: a valid BYE #GstRTCPPacket + * @reason: a reason string + * + * Set the reason string to @reason in @packet. + * + * Returns: TRUE if the string could be set. + */ +gboolean +gst_rtcp_packet_bye_set_reason (GstRTCPPacket * packet, const gchar * reason) +{ + guint8 *data; + guint roffset, size; + guint8 len, padded; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_BYE, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + if (reason == NULL) + return TRUE; + + len = strlen (reason); + if (len == 0) + return TRUE; + + /* make room for the string before we get the offset */ + packet->length++; + + roffset = get_reason_offset (packet); + if (roffset == 0) + goto no_space; + + data = GST_BUFFER_DATA (packet->buffer); + size = GST_BUFFER_SIZE (packet->buffer); + + /* we have 1 byte length and we need to pad to 4 bytes */ + padded = ((len + 1) + 3) & ~3; + + /* we need enough space for the padded length */ + if (roffset + padded >= size) + goto no_space; + + data[roffset] = len; + memcpy (&data[roffset + 1], reason, len); + + /* update packet length, we made room for 1 double word already */ + packet->length += (padded >> 2) - 1; + data[packet->offset + 2] = (packet->length) >> 8; + data[packet->offset + 3] = (packet->length) & 0xff; + + return TRUE; + + /* ERRORS */ +no_space: + { + packet->length--; + return FALSE; + } +} + +/** + * gst_rtcp_packet_fb_get_sender_ssrc: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * + * Get the sender SSRC field of the RTPFB or PSFB @packet. + * + * Returns: the sender SSRC. + * + * Since: 0.10.23 + */ +guint32 +gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket * packet) +{ + guint8 *data; + guint32 ssrc; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB), 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + ssrc = GST_READ_UINT32_BE (data); + + return ssrc; +} + +/** + * gst_rtcp_packet_fb_set_sender_ssrc: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * @ssrc: a sender SSRC + * + * Set the sender SSRC field of the RTPFB or PSFB @packet. + * + * Since: 0.10.23 + */ +void +gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket * packet, guint32 ssrc) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header */ + data += packet->offset + 4; + GST_WRITE_UINT32_BE (data, ssrc); +} + +/** + * gst_rtcp_packet_fb_get_media_ssrc: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * + * Get the media SSRC field of the RTPFB or PSFB @packet. + * + * Returns: the media SSRC. + * + * Since: 0.10.23 + */ +guint32 +gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket * packet) +{ + guint8 *data; + guint32 ssrc; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail ((packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB), 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header and sender ssrc */ + data += packet->offset + 8; + ssrc = GST_READ_UINT32_BE (data); + + return ssrc; +} + +/** + * gst_rtcp_packet_fb_set_media_ssrc: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * @ssrc: a media SSRC + * + * Set the media SSRC field of the RTPFB or PSFB @packet. + * + * Since: 0.10.23 + */ +void +gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket * packet, guint32 ssrc) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + /* skip header and sender ssrc */ + data += packet->offset + 8; + GST_WRITE_UINT32_BE (data, ssrc); +} + +/** + * gst_rtcp_packet_fb_get_type: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * + * Get the feedback message type of the FB @packet. + * + * Returns: The feedback message type. + * + * Since: 0.10.23 + */ +GstRTCPFBType +gst_rtcp_packet_fb_get_type (GstRTCPPacket * packet) +{ + g_return_val_if_fail (packet != NULL, GST_RTCP_FB_TYPE_INVALID); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB, GST_RTCP_FB_TYPE_INVALID); + + return packet->count; +} + +/** + * gst_rtcp_packet_fb_set_type: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * @type: the #GstRTCPFBType to set + * + * Set the feedback message type of the FB @packet. + * + * Since: 0.10.23 + */ +void +gst_rtcp_packet_fb_set_type (GstRTCPPacket * packet, GstRTCPFBType type) +{ + guint8 *data; + + g_return_if_fail (packet != NULL); + g_return_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB); + g_return_if_fail (GST_IS_BUFFER (packet->buffer)); + + data = GST_BUFFER_DATA (packet->buffer); + + data[packet->offset] = (data[packet->offset] & 0xe0) | type; + packet->count = type; +} + +/** + * gst_rtcp_ntp_to_unix: + * @ntptime: an NTP timestamp + * + * Converts an NTP time to UNIX nanoseconds. @ntptime can typically be + * the NTP time of an SR RTCP message and contains, in the upper 32 bits, the + * number of seconds since 1900 and, in the lower 32 bits, the fractional + * seconds. The resulting value will be the number of nanoseconds since 1970. + * + * Returns: the UNIX time for @ntptime in nanoseconds. + */ +guint64 +gst_rtcp_ntp_to_unix (guint64 ntptime) +{ + guint64 unixtime; + + /* conversion from NTP timestamp (seconds since 1900) to seconds since + * 1970. */ + unixtime = ntptime - (G_GUINT64_CONSTANT (2208988800) << 32); + /* conversion to nanoseconds */ + unixtime = + gst_util_uint64_scale (unixtime, GST_SECOND, + (G_GINT64_CONSTANT (1) << 32)); + + return unixtime; +} + +/** + * gst_rtcp_unix_to_ntp: + * @unixtime: an UNIX timestamp in nanoseconds + * + * Converts a UNIX timestamp in nanoseconds to an NTP time. The caller should + * pass a value with nanoseconds since 1970. The NTP time will, in the upper + * 32 bits, contain the number of seconds since 1900 and, in the lower 32 + * bits, the fractional seconds. The resulting value can be used as an ntptime + * for constructing SR RTCP packets. + * + * Returns: the NTP time for @unixtime. + */ +guint64 +gst_rtcp_unix_to_ntp (guint64 unixtime) +{ + guint64 ntptime; + + /* convert clock time to NTP time. upper 32 bits should contain the seconds + * and the lower 32 bits, the fractions of a second. */ + ntptime = + gst_util_uint64_scale (unixtime, (G_GINT64_CONSTANT (1) << 32), + GST_SECOND); + /* conversion from UNIX timestamp (seconds since 1970) to NTP (seconds + * since 1900). */ + ntptime += (G_GUINT64_CONSTANT (2208988800) << 32); + + return ntptime; +} + +/** + * gst_rtcp_sdes_type_to_name: + * @type: a #GstRTCPSDESType + * + * Converts @type to the string equivalent. The string is typically used as a + * key in a #GstStructure containing SDES items. + * + * Returns: the string equivalent of @type + * + * Since: 0.10.26 + */ +const gchar * +gst_rtcp_sdes_type_to_name (GstRTCPSDESType type) +{ + const gchar *result; + + switch (type) { + case GST_RTCP_SDES_CNAME: + result = "cname"; + break; + case GST_RTCP_SDES_NAME: + result = "name"; + break; + case GST_RTCP_SDES_EMAIL: + result = "email"; + break; + case GST_RTCP_SDES_PHONE: + result = "phone"; + break; + case GST_RTCP_SDES_LOC: + result = "location"; + break; + case GST_RTCP_SDES_TOOL: + result = "tool"; + break; + case GST_RTCP_SDES_NOTE: + result = "note"; + break; + case GST_RTCP_SDES_PRIV: + result = "priv"; + break; + default: + result = NULL; + break; + } + return result; +} + +/** + * gst_rtcp_sdes_name_to_type: + * @name: a SDES name + * + * Convert @name into a @GstRTCPSDESType. @name is typically a key in a + * #GstStructure containing SDES items. + * + * Returns: the #GstRTCPSDESType for @name or #GST_RTCP_SDES_PRIV when @name + * is a private sdes item. + * + * Since: 0.10.26 + */ +GstRTCPSDESType +gst_rtcp_sdes_name_to_type (const gchar * name) +{ + if (name == NULL || strlen (name) == 0) + return GST_RTCP_SDES_INVALID; + + if (strcmp ("cname", name) == 0) + return GST_RTCP_SDES_CNAME; + + if (strcmp ("name", name) == 0) + return GST_RTCP_SDES_NAME; + + if (strcmp ("email", name) == 0) + return GST_RTCP_SDES_EMAIL; + + if (strcmp ("phone", name) == 0) + return GST_RTCP_SDES_PHONE; + + if (strcmp ("location", name) == 0) + return GST_RTCP_SDES_LOC; + + if (strcmp ("tool", name) == 0) + return GST_RTCP_SDES_TOOL; + + if (strcmp ("note", name) == 0) + return GST_RTCP_SDES_NOTE; + + return GST_RTCP_SDES_PRIV; +} + +/** + * gst_rtcp_packet_fb_get_fci_length: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * + * Get the length of the Feedback Control Information attached to a + * RTPFB or PSFB @packet. + * + * Returns: The length of the FCI in 32-bit words. + * + * Since: 0.10.31 + */ +guint16 +gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket * packet) +{ + guint8 *data; + + g_return_val_if_fail (packet != NULL, 0); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB, 0); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), 0); + + data = GST_BUFFER_DATA (packet->buffer) + packet->offset + 2; + + return GST_READ_UINT16_BE (data) - 2; +} + +/** + * gst_rtcp_packet_fb_set_fci_length: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * @wordlen: Length of the FCI in 32-bit words + * + * Set the length of the Feedback Control Information attached to a + * RTPFB or PSFB @packet. + * + * Returns: %TRUE if there was enough space in the packet to add this much FCI + * + * Since: 0.10.31 + */ +gboolean +gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket * packet, guint16 wordlen) +{ + guint8 *data; + + g_return_val_if_fail (packet != NULL, FALSE); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB, FALSE); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), FALSE); + + if (GST_BUFFER_SIZE (packet->buffer) < packet->offset + ((wordlen + 3) * 4)) + return FALSE; + + data = GST_BUFFER_DATA (packet->buffer) + packet->offset + 2; + wordlen += 2; + GST_WRITE_UINT16_BE (data, wordlen); + + return TRUE; +} + +/** + * gst_rtcp_packet_fb_get_fci: + * @packet: a valid RTPFB or PSFB #GstRTCPPacket + * + * Get the Feedback Control Information attached to a RTPFB or PSFB @packet. + * + * Returns: a pointer to the FCI + * + * Since: 0.10.31 + */ +guint8 * +gst_rtcp_packet_fb_get_fci (GstRTCPPacket * packet) +{ + guint8 *data; + + g_return_val_if_fail (packet != NULL, NULL); + g_return_val_if_fail (packet->type == GST_RTCP_TYPE_RTPFB || + packet->type == GST_RTCP_TYPE_PSFB, NULL); + g_return_val_if_fail (GST_IS_BUFFER (packet->buffer), NULL); + + data = GST_BUFFER_DATA (packet->buffer) + packet->offset; + + if (GST_READ_UINT16_BE (data + 2) <= 2) + return NULL; + + return data + 12; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.h new file mode 100644 index 0000000..6f57fad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtcpbuffer.h @@ -0,0 +1,286 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * gstrtcpbuffer.h: various helper functions to manipulate buffers + * with RTCP payload. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTCPBUFFER_H__ +#define __GST_RTCPBUFFER_H__ + +#include + +G_BEGIN_DECLS + +/** + * GST_RTCP_VERSION: + * + * The supported RTCP version 2. + */ +#define GST_RTCP_VERSION 2 + +/** + * GstRTCPType: + * @GST_RTCP_TYPE_INVALID: Invalid type + * @GST_RTCP_TYPE_SR: Sender report + * @GST_RTCP_TYPE_RR: Receiver report + * @GST_RTCP_TYPE_SDES: Source description + * @GST_RTCP_TYPE_BYE: Goodbye + * @GST_RTCP_TYPE_APP: Application defined + * @GST_RTCP_TYPE_RTPFB: Transport layer feedback. Since: 0.10.23 + * @GST_RTCP_TYPE_PSFB: Payload-specific feedback. Since: 0.10.23 + * + * Different RTCP packet types. + */ +typedef enum +{ + GST_RTCP_TYPE_INVALID = 0, + GST_RTCP_TYPE_SR = 200, + GST_RTCP_TYPE_RR = 201, + GST_RTCP_TYPE_SDES = 202, + GST_RTCP_TYPE_BYE = 203, + GST_RTCP_TYPE_APP = 204, + GST_RTCP_TYPE_RTPFB = 205, + GST_RTCP_TYPE_PSFB = 206 +} GstRTCPType; + +/** + * GstRTCPFBType: + * @GST_RTCP_FB_TYPE_INVALID: Invalid type + * @GST_RTCP_RTPFB_TYPE_NACK: Generic NACK + * @GST_RTCP_PSFB_TYPE_PLI: Picture Loss Indication + * @GST_RTCP_PSFB_TYPE_SLI: Slice Loss Indication + * @GST_RTCP_PSFB_TYPE_RPSI: Reference Picture Selection Indication + * @GST_RTCP_PSFB_TYPE_AFB: Application layer Feedback + * + * Different types of feedback messages. + * + * Since: 0.10.23 + */ +typedef enum +{ + /* generic */ + GST_RTCP_FB_TYPE_INVALID = 0, + /* RTPFB types */ + GST_RTCP_RTPFB_TYPE_NACK = 1, + /* PSFB types */ + GST_RTCP_PSFB_TYPE_PLI = 1, + GST_RTCP_PSFB_TYPE_SLI = 2, + GST_RTCP_PSFB_TYPE_RPSI = 3, + GST_RTCP_PSFB_TYPE_AFB = 15 +} GstRTCPFBType; + +/** + * GstRTCPSDESType: + * @GST_RTCP_SDES_INVALID: Invalid SDES entry + * @GST_RTCP_SDES_END: End of SDES list + * @GST_RTCP_SDES_CNAME: Canonical name + * @GST_RTCP_SDES_NAME: User name + * @GST_RTCP_SDES_EMAIL: User's electronic mail address + * @GST_RTCP_SDES_PHONE: User's phone number + * @GST_RTCP_SDES_LOC: Geographic user location + * @GST_RTCP_SDES_TOOL: Name of application or tool + * @GST_RTCP_SDES_NOTE: Notice about the source + * @GST_RTCP_SDES_PRIV: Private extensions + * + * Different types of SDES content. + */ +typedef enum +{ + GST_RTCP_SDES_INVALID = -1, + GST_RTCP_SDES_END = 0, + GST_RTCP_SDES_CNAME = 1, + GST_RTCP_SDES_NAME = 2, + GST_RTCP_SDES_EMAIL = 3, + GST_RTCP_SDES_PHONE = 4, + GST_RTCP_SDES_LOC = 5, + GST_RTCP_SDES_TOOL = 6, + GST_RTCP_SDES_NOTE = 7, + GST_RTCP_SDES_PRIV = 8 +} GstRTCPSDESType; + +/** + * GST_RTCP_MAX_SDES: + * + * The maximum text length for an SDES item. + */ +#define GST_RTCP_MAX_SDES 255 + +/** + * GST_RTCP_MAX_RB_COUNT: + * + * The maximum amount of Receiver report blocks in RR and SR messages. + */ +#define GST_RTCP_MAX_RB_COUNT 31 + +/** + * GST_RTCP_MAX_SDES_ITEM_COUNT: + * + * The maximum amount of SDES items. + */ +#define GST_RTCP_MAX_SDES_ITEM_COUNT 31 + +/** + * GST_RTCP_MAX_BYE_SSRC_COUNT: + * + * The maximum amount of SSRCs in a BYE packet. + */ +#define GST_RTCP_MAX_BYE_SSRC_COUNT 31 + +/** + * GST_RTCP_VALID_MASK: + * + * Mask for version, padding bit and packet type pair + */ +#define GST_RTCP_VALID_MASK (0xc000 | 0x2000 | 0xfe) +/** + * GST_RTCP_VALID_VALUE: + * + * Valid value for the first two bytes of an RTCP packet after applying + * #GST_RTCP_VALID_MASK to them. + */ +#define GST_RTCP_VALID_VALUE ((GST_RTCP_VERSION << 14) | GST_RTCP_TYPE_SR) + +typedef struct _GstRTCPPacket GstRTCPPacket; + +/** + * GstRTCPPacket: + * @buffer: pointer to RTCP buffer + * @offset: offset of packet in buffer data + * + * Data structure that points to a packet at @offset in @buffer. + * The size of the structure is made public to allow stack allocations. + */ +struct _GstRTCPPacket +{ + GstBuffer *buffer; + guint offset; + + /*< private >*/ + gboolean padding; /* padding field of current packet */ + guint8 count; /* count field of current packet */ + GstRTCPType type; /* type of current packet */ + guint16 length; /* length of current packet in 32-bits words */ + + guint item_offset; /* current item offset for navigating SDES */ + guint item_count; /* current item count */ + guint entry_offset; /* current entry offset for navigating SDES items */ +}; + +/* creating buffers */ +GstBuffer* gst_rtcp_buffer_new_take_data (gpointer data, guint len); +GstBuffer* gst_rtcp_buffer_new_copy_data (gpointer data, guint len); + +gboolean gst_rtcp_buffer_validate_data (guint8 *data, guint len); +gboolean gst_rtcp_buffer_validate (GstBuffer *buffer); + +GstBuffer* gst_rtcp_buffer_new (guint mtu); +void gst_rtcp_buffer_end (GstBuffer *buffer); + +/* adding/retrieving packets */ +guint gst_rtcp_buffer_get_packet_count (GstBuffer *buffer); +gboolean gst_rtcp_buffer_get_first_packet (GstBuffer *buffer, GstRTCPPacket *packet); +gboolean gst_rtcp_packet_move_to_next (GstRTCPPacket *packet); + +gboolean gst_rtcp_buffer_add_packet (GstBuffer *buffer, GstRTCPType type, + GstRTCPPacket *packet); +gboolean gst_rtcp_packet_remove (GstRTCPPacket *packet); + +/* working with packets */ +gboolean gst_rtcp_packet_get_padding (GstRTCPPacket *packet); +guint8 gst_rtcp_packet_get_count (GstRTCPPacket *packet); +GstRTCPType gst_rtcp_packet_get_type (GstRTCPPacket *packet); +guint16 gst_rtcp_packet_get_length (GstRTCPPacket *packet); + + +/* sender reports */ +void gst_rtcp_packet_sr_get_sender_info (GstRTCPPacket *packet, guint32 *ssrc, + guint64 *ntptime, guint32 *rtptime, + guint32 *packet_count, guint32 *octet_count); +void gst_rtcp_packet_sr_set_sender_info (GstRTCPPacket *packet, guint32 ssrc, + guint64 ntptime, guint32 rtptime, + guint32 packet_count, guint32 octet_count); +/* receiver reports */ +guint32 gst_rtcp_packet_rr_get_ssrc (GstRTCPPacket *packet); +void gst_rtcp_packet_rr_set_ssrc (GstRTCPPacket *packet, guint32 ssrc); + + +/* report blocks for SR and RR */ +guint gst_rtcp_packet_get_rb_count (GstRTCPPacket *packet); +void gst_rtcp_packet_get_rb (GstRTCPPacket *packet, guint nth, guint32 *ssrc, + guint8 *fractionlost, gint32 *packetslost, + guint32 *exthighestseq, guint32 *jitter, + guint32 *lsr, guint32 *dlsr); +gboolean gst_rtcp_packet_add_rb (GstRTCPPacket *packet, guint32 ssrc, + guint8 fractionlost, gint32 packetslost, + guint32 exthighestseq, guint32 jitter, + guint32 lsr, guint32 dlsr); +void gst_rtcp_packet_set_rb (GstRTCPPacket *packet, guint nth, guint32 ssrc, + guint8 fractionlost, gint32 packetslost, + guint32 exthighestseq, guint32 jitter, + guint32 lsr, guint32 dlsr); + +/* source description packet */ +guint gst_rtcp_packet_sdes_get_item_count (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_sdes_first_item (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_sdes_next_item (GstRTCPPacket *packet); +guint32 gst_rtcp_packet_sdes_get_ssrc (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_sdes_first_entry (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_sdes_next_entry (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_sdes_get_entry (GstRTCPPacket *packet, + GstRTCPSDESType *type, guint8 *len, + guint8 **data); +gboolean gst_rtcp_packet_sdes_copy_entry (GstRTCPPacket *packet, + GstRTCPSDESType *type, guint8 *len, + guint8 **data); + +gboolean gst_rtcp_packet_sdes_add_item (GstRTCPPacket *packet, guint32 ssrc); +gboolean gst_rtcp_packet_sdes_add_entry (GstRTCPPacket *packet, GstRTCPSDESType type, + guint8 len, const guint8 *data); + +/* bye packet */ +guint gst_rtcp_packet_bye_get_ssrc_count (GstRTCPPacket *packet); +guint32 gst_rtcp_packet_bye_get_nth_ssrc (GstRTCPPacket *packet, guint nth); +gboolean gst_rtcp_packet_bye_add_ssrc (GstRTCPPacket *packet, guint32 ssrc); +gboolean gst_rtcp_packet_bye_add_ssrcs (GstRTCPPacket *packet, guint32 *ssrc, guint len); +guint8 gst_rtcp_packet_bye_get_reason_len (GstRTCPPacket *packet); +gchar* gst_rtcp_packet_bye_get_reason (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_bye_set_reason (GstRTCPPacket *packet, const gchar *reason); + +/* feedback packets */ +guint32 gst_rtcp_packet_fb_get_sender_ssrc (GstRTCPPacket *packet); +void gst_rtcp_packet_fb_set_sender_ssrc (GstRTCPPacket *packet, guint32 ssrc); +guint32 gst_rtcp_packet_fb_get_media_ssrc (GstRTCPPacket *packet); +void gst_rtcp_packet_fb_set_media_ssrc (GstRTCPPacket *packet, guint32 ssrc); +GstRTCPFBType gst_rtcp_packet_fb_get_type (GstRTCPPacket *packet); +void gst_rtcp_packet_fb_set_type (GstRTCPPacket *packet, GstRTCPFBType type); +guint16 gst_rtcp_packet_fb_get_fci_length (GstRTCPPacket *packet); +gboolean gst_rtcp_packet_fb_set_fci_length (GstRTCPPacket *packet, guint16 wordlen); +guint8 * gst_rtcp_packet_fb_get_fci (GstRTCPPacket *packet); + +/* helper functions */ +guint64 gst_rtcp_ntp_to_unix (guint64 ntptime); +guint64 gst_rtcp_unix_to_ntp (guint64 unixtime); + +const gchar * gst_rtcp_sdes_type_to_name (GstRTCPSDESType type); +GstRTCPSDESType gst_rtcp_sdes_name_to_type (const gchar *name); + +G_END_DECLS + +#endif /* __GST_RTCPBUFFER_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.c new file mode 100644 index 0000000..141b072 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.c @@ -0,0 +1,2059 @@ +/* GStreamer + * Copyright (C) <2005> Philippe Khalaf + * Copyright (C) <2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtpbuffer + * @short_description: Helper methods for dealing with RTP buffers + * @see_also: #GstBaseRTPPayload, #GstBaseRTPDepayload, gstrtcpbuffer + * + * + * + * The GstRTPBuffer helper functions makes it easy to parse and create regular + * #GstBuffer objects that contain RTP payloads. These buffers are typically of + * 'application/x-rtp' #GstCaps. + * + * + * + * Last reviewed on 2006-07-17 (0.10.10) + */ + +#include "gstrtpbuffer.h" + +#include +#include + +#define GST_RTP_HEADER_LEN 12 + +/* Note: we use bitfields here to make sure the compiler doesn't add padding + * between fields on certain architectures; can't assume aligned access either + */ +typedef struct _GstRTPHeader +{ +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + unsigned int csrc_count:4; /* CSRC count */ + unsigned int extension:1; /* header extension flag */ + unsigned int padding:1; /* padding flag */ + unsigned int version:2; /* protocol version */ + unsigned int payload_type:7; /* payload type */ + unsigned int marker:1; /* marker bit */ +#elif G_BYTE_ORDER == G_BIG_ENDIAN + unsigned int version:2; /* protocol version */ + unsigned int padding:1; /* padding flag */ + unsigned int extension:1; /* header extension flag */ + unsigned int csrc_count:4; /* CSRC count */ + unsigned int marker:1; /* marker bit */ + unsigned int payload_type:7; /* payload type */ +#else +#error "G_BYTE_ORDER should be big or little endian." +#endif + unsigned int seq:16; /* sequence number */ + unsigned int timestamp:32; /* timestamp */ + unsigned int ssrc:32; /* synchronization source */ + guint8 csrclist[4]; /* optional CSRC list, 32 bits each */ +} GstRTPHeader; + +#define GST_RTP_HEADER_VERSION(data) (((GstRTPHeader *)(data))->version) +#define GST_RTP_HEADER_PADDING(data) (((GstRTPHeader *)(data))->padding) +#define GST_RTP_HEADER_EXTENSION(data) (((GstRTPHeader *)(data))->extension) +#define GST_RTP_HEADER_CSRC_COUNT(data) (((GstRTPHeader *)(data))->csrc_count) +#define GST_RTP_HEADER_MARKER(data) (((GstRTPHeader *)(data))->marker) +#define GST_RTP_HEADER_PAYLOAD_TYPE(data) (((GstRTPHeader *)(data))->payload_type) +#define GST_RTP_HEADER_SEQ(data) (((GstRTPHeader *)(data))->seq) +#define GST_RTP_HEADER_TIMESTAMP(data) (((GstRTPHeader *)(data))->timestamp) +#define GST_RTP_HEADER_SSRC(data) (((GstRTPHeader *)(data))->ssrc) +#define GST_RTP_HEADER_CSRC_LIST_OFFSET(data,i) \ + data + G_STRUCT_OFFSET(GstRTPHeader, csrclist) + \ + ((i) * sizeof(guint32)) +#define GST_RTP_HEADER_CSRC_SIZE(data) (GST_RTP_HEADER_CSRC_COUNT(data) * sizeof (guint32)) + +/** + * gst_rtp_buffer_allocate_data: + * @buffer: a #GstBuffer + * @payload_len: the length of the payload + * @pad_len: the amount of padding + * @csrc_count: the number of CSRC entries + * + * Allocate enough data in @buffer to hold an RTP packet with @csrc_count CSRCs, + * a payload length of @payload_len and padding of @pad_len. + * MALLOCDATA of @buffer will be overwritten and will not be freed. + * All other RTP header fields will be set to 0/FALSE. + */ +void +gst_rtp_buffer_allocate_data (GstBuffer * buffer, guint payload_len, + guint8 pad_len, guint8 csrc_count) +{ + guint len; + guint8 *data; + + g_return_if_fail (csrc_count <= 15); + g_return_if_fail (GST_IS_BUFFER (buffer)); + + len = GST_RTP_HEADER_LEN + csrc_count * sizeof (guint32) + + payload_len + pad_len; + + data = g_malloc (len); + GST_BUFFER_MALLOCDATA (buffer) = data; + GST_BUFFER_DATA (buffer) = data; + GST_BUFFER_SIZE (buffer) = len; + + /* fill in defaults */ + GST_RTP_HEADER_VERSION (data) = GST_RTP_VERSION; + GST_RTP_HEADER_PADDING (data) = FALSE; + GST_RTP_HEADER_EXTENSION (data) = FALSE; + GST_RTP_HEADER_CSRC_COUNT (data) = csrc_count; + memset (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, 0), 0, + csrc_count * sizeof (guint32)); + GST_RTP_HEADER_MARKER (data) = FALSE; + GST_RTP_HEADER_PAYLOAD_TYPE (data) = 0; + GST_RTP_HEADER_SEQ (data) = 0; + GST_RTP_HEADER_TIMESTAMP (data) = 0; + GST_RTP_HEADER_SSRC (data) = 0; +} + +/** + * gst_rtp_buffer_new_take_data: + * @data: data for the new buffer + * @len: the length of data + * + * Create a new buffer and set the data and size of the buffer to @data and @len + * respectively. @data will be freed when the buffer is unreffed, so this + * function transfers ownership of @data to the new buffer. + * + * Returns: A newly allocated buffer with @data and of size @len. + */ +GstBuffer * +gst_rtp_buffer_new_take_data (gpointer data, guint len) +{ + GstBuffer *result; + + g_return_val_if_fail (data != NULL, NULL); + g_return_val_if_fail (len > 0, NULL); + + result = gst_buffer_new (); + + GST_BUFFER_MALLOCDATA (result) = data; + GST_BUFFER_DATA (result) = data; + GST_BUFFER_SIZE (result) = len; + + return result; +} + +/** + * gst_rtp_buffer_new_copy_data: + * @data: data for the new buffer + * @len: the length of data + * + * Create a new buffer and set the data to a copy of @len + * bytes of @data and the size to @len. The data will be freed when the buffer + * is freed. + * + * Returns: A newly allocated buffer with a copy of @data and of size @len. + */ +GstBuffer * +gst_rtp_buffer_new_copy_data (gpointer data, guint len) +{ + return gst_rtp_buffer_new_take_data (g_memdup (data, len), len); +} + +/** + * gst_rtp_buffer_new_allocate: + * @payload_len: the length of the payload + * @pad_len: the amount of padding + * @csrc_count: the number of CSRC entries + * + * Allocate a new #GstBuffer with enough data to hold an RTP packet with + * @csrc_count CSRCs, a payload length of @payload_len and padding of @pad_len. + * All other RTP header fields will be set to 0/FALSE. + * + * Returns: A newly allocated buffer that can hold an RTP packet with given + * parameters. + */ +GstBuffer * +gst_rtp_buffer_new_allocate (guint payload_len, guint8 pad_len, + guint8 csrc_count) +{ + GstBuffer *result; + + g_return_val_if_fail (csrc_count <= 15, NULL); + + result = gst_buffer_new (); + gst_rtp_buffer_allocate_data (result, payload_len, pad_len, csrc_count); + + return result; +} + +/** + * gst_rtp_buffer_new_allocate_len: + * @packet_len: the total length of the packet + * @pad_len: the amount of padding + * @csrc_count: the number of CSRC entries + * + * Create a new #GstBuffer that can hold an RTP packet that is exactly + * @packet_len long. The length of the payload depends on @pad_len and + * @csrc_count and can be calculated with gst_rtp_buffer_calc_payload_len(). + * All RTP header fields will be set to 0/FALSE. + * + * Returns: A newly allocated buffer that can hold an RTP packet of @packet_len. + */ +GstBuffer * +gst_rtp_buffer_new_allocate_len (guint packet_len, guint8 pad_len, + guint8 csrc_count) +{ + guint len; + + g_return_val_if_fail (csrc_count <= 15, NULL); + + len = gst_rtp_buffer_calc_payload_len (packet_len, pad_len, csrc_count); + + return gst_rtp_buffer_new_allocate (len, pad_len, csrc_count); +} + +/** + * gst_rtp_buffer_calc_header_len: + * @csrc_count: the number of CSRC entries + * + * Calculate the header length of an RTP packet with @csrc_count CSRC entries. + * An RTP packet can have at most 15 CSRC entries. + * + * Returns: The length of an RTP header with @csrc_count CSRC entries. + */ +guint +gst_rtp_buffer_calc_header_len (guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32)); +} + +/** + * gst_rtp_buffer_calc_packet_len: + * @payload_len: the length of the payload + * @pad_len: the amount of padding + * @csrc_count: the number of CSRC entries + * + * Calculate the total length of an RTP packet with a payload size of @payload_len, + * a padding of @pad_len and a @csrc_count CSRC entries. + * + * Returns: The total length of an RTP header with given parameters. + */ +guint +gst_rtp_buffer_calc_packet_len (guint payload_len, guint8 pad_len, + guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return payload_len + GST_RTP_HEADER_LEN + (csrc_count * sizeof (guint32)) + + pad_len; +} + +/** + * gst_rtp_buffer_calc_payload_len: + * @packet_len: the length of the total RTP packet + * @pad_len: the amount of padding + * @csrc_count: the number of CSRC entries + * + * Calculate the length of the payload of an RTP packet with size @packet_len, + * a padding of @pad_len and a @csrc_count CSRC entries. + * + * Returns: The length of the payload of an RTP packet with given parameters. + */ +guint +gst_rtp_buffer_calc_payload_len (guint packet_len, guint8 pad_len, + guint8 csrc_count) +{ + g_return_val_if_fail (csrc_count <= 15, 0); + + return packet_len - GST_RTP_HEADER_LEN - (csrc_count * sizeof (guint32)) + - pad_len; +} + +/** + * validate_data: + * @data: the data to validate + * @len: the length of @data to validate + * @payload: the payload if @data represents the header only + * @payload_len: the len of the payload + * + * Checks if @data is a valid RTP packet. + * + * Returns: TRUE if @data is a valid RTP packet + */ +static gboolean +validate_data (guint8 * data, guint len, guint8 * payload, guint payload_len) +{ + guint8 padding; + guint8 csrc_count; + guint header_len; + guint8 version; + + g_return_val_if_fail (data != NULL, FALSE); + + header_len = GST_RTP_HEADER_LEN; + if (G_UNLIKELY (len < header_len)) + goto wrong_length; + + /* check version */ + version = (data[0] & 0xc0); + if (G_UNLIKELY (version != (GST_RTP_VERSION << 6))) + goto wrong_version; + + /* calc header length with csrc */ + csrc_count = (data[0] & 0x0f); + header_len += csrc_count * sizeof (guint32); + + /* calc extension length when present. */ + if (data[0] & 0x10) { + guint8 *extpos; + guint16 extlen; + + /* this points to the extenstion bits and header length */ + extpos = &data[header_len]; + + /* skip the header and check that we have enough space */ + header_len += 4; + if (G_UNLIKELY (len < header_len)) + goto wrong_length; + + /* skip id */ + extpos += 2; + /* read length as the number of 32 bits words */ + extlen = GST_READ_UINT16_BE (extpos); + + header_len += extlen * sizeof (guint32); + } + + /* check for padding */ + if (data[0] & 0x20) { + if (payload) + padding = payload[payload_len - 1]; + else + padding = data[len - 1]; + } else { + padding = 0; + } + + /* check if padding and header not bigger than packet length */ + if (G_UNLIKELY (len < padding + header_len)) + goto wrong_padding; + + return TRUE; + + /* ERRORS */ +wrong_length: + { + GST_DEBUG ("len < header_len check failed (%d < %d)", len, header_len); + goto dump_packet; + } +wrong_version: + { + GST_DEBUG ("version check failed (%d != %d)", version, GST_RTP_VERSION); + goto dump_packet; + } +wrong_padding: + { + GST_DEBUG ("padding check failed (%d - %d < %d)", len, header_len, padding); + goto dump_packet; + } +dump_packet: + { + GST_MEMDUMP ("buffer", data, len); + return FALSE; + } +} + +/** + * gst_rtp_buffer_validate_data: + * @data: the data to validate + * @len: the length of @data to validate + * + * Check if the @data and @size point to the data of a valid RTP packet. + * This function checks the length, version and padding of the packet data. + * Use this function to validate a packet before using the other functions in + * this module. + * + * Returns: TRUE if the data points to a valid RTP packet. + */ +gboolean +gst_rtp_buffer_validate_data (guint8 * data, guint len) +{ + return validate_data (data, len, NULL, 0); +} + +/** + * gst_rtp_buffer_validate: + * @buffer: the buffer to validate + * + * Check if the data pointed to by @buffer is a valid RTP packet using + * validate_data(). + * Use this function to validate a packet before using the other functions in + * this module. + * + * Returns: TRUE if @buffer is a valid RTP packet. + */ +gboolean +gst_rtp_buffer_validate (GstBuffer * buffer) +{ + guint8 *data; + guint len; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + + data = GST_BUFFER_DATA (buffer); + len = GST_BUFFER_SIZE (buffer); + + return validate_data (data, len, NULL, 0); +} + +/** + * gst_rtp_buffer_list_validate: + * @list: the buffer list to validate + * + * Check if all RTP packets in the @list are valid using validate_data(). + * Use this function to validate an list before using the other functions in + * this module. + * + * Returns: TRUE if @list consists only of valid RTP packets. + * + * Since: 0.10.24 + */ +gboolean +gst_rtp_buffer_list_validate (GstBufferList * list) +{ + guint16 prev_seqnum = 0; + GstBufferListIterator *it; + guint i = 0; + + g_return_val_if_fail (GST_IS_BUFFER_LIST (list), FALSE); + + it = gst_buffer_list_iterate (list); + g_return_val_if_fail (it != NULL, FALSE); + + /* iterate through all the RTP packets in the list */ + while (gst_buffer_list_iterator_next_group (it)) { + GstBuffer *rtpbuf; + GstBuffer *paybuf; + guint8 *packet_header; + guint8 *packet_payload; + guint payload_size; + guint packet_size; + guint j, n_buffers; + + /* each group should consists of at least 1 buffer: The first buffer always + * contains the complete RTP header. Next buffers contain the payload */ + n_buffers = gst_buffer_list_iterator_n_buffers (it); + if (n_buffers < 1) + goto invalid_list; + + /* get the RTP header (and if n_buffers == 1 also the payload) */ + rtpbuf = gst_buffer_list_iterator_next (it); + packet_header = GST_BUFFER_DATA (rtpbuf); + if (packet_header == NULL) + goto invalid_list; + + /* check the sequence number */ + if (G_UNLIKELY (i == 0)) { + prev_seqnum = g_ntohs (GST_RTP_HEADER_SEQ (packet_header)); + i++; + } else { + if (++prev_seqnum != g_ntohs (GST_RTP_HEADER_SEQ (packet_header))) + goto invalid_list; + } + + packet_size = GST_BUFFER_SIZE (rtpbuf); + packet_payload = NULL; + payload_size = 0; + + /* get the payload buffers */ + for (j = 1; j < n_buffers; j++) { + /* get the payload */ + paybuf = gst_buffer_list_iterator_next (it); + + if ((packet_payload = GST_BUFFER_DATA (paybuf)) == NULL) + goto invalid_list; + + if ((payload_size = GST_BUFFER_SIZE (paybuf)) == 0) + goto invalid_list; + + /* the size of the RTP packet within the current group */ + packet_size += payload_size; + } + + /* validate packet */ + if (!validate_data (packet_header, packet_size, packet_payload, + payload_size)) { + goto invalid_list; + } + } + + gst_buffer_list_iterator_free (it); + + return TRUE; + + /* ERRORS */ +invalid_list: + { + gst_buffer_list_iterator_free (it); + return FALSE; + } +} + +/** + * gst_rtp_buffer_set_packet_len: + * @buffer: the buffer + * @len: the new packet length + * + * Set the total @buffer size to @len. The data in the buffer will be made + * larger if needed. Any padding will be removed from the packet. + */ +void +gst_rtp_buffer_set_packet_len (GstBuffer * buffer, guint len) +{ + guint oldlen; + guint8 *data; + + oldlen = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + if (oldlen < len) { + data = g_realloc (GST_BUFFER_MALLOCDATA (buffer), len); + GST_BUFFER_MALLOCDATA (buffer) = data; + GST_BUFFER_DATA (buffer) = data; + } + GST_BUFFER_SIZE (buffer) = len; + + /* remove any padding */ + GST_RTP_HEADER_PADDING (data) = FALSE; +} + +/** + * gst_rtp_buffer_get_packet_len: + * @buffer: the buffer + * + * Return the total length of the packet in @buffer. + * + * Returns: The total length of the packet in @buffer. + */ +guint +gst_rtp_buffer_get_packet_len (GstBuffer * buffer) +{ + return GST_BUFFER_SIZE (buffer); +} + +/** + * gst_rtp_buffer_get_header_len: + * @buffer: the buffer + * + * Return the total length of the header in @buffer. This include the length of + * the fixed header, the CSRC list and the extension header. + * + * Returns: The total length of the header in @buffer. + */ +guint +gst_rtp_buffer_get_header_len (GstBuffer * buffer) +{ + guint len; + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + + len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data); + if (GST_RTP_HEADER_EXTENSION (data)) + len += GST_READ_UINT16_BE (data + len + 2) * 4 + 4; + + return len; +} + +/** + * gst_rtp_buffer_get_version: + * @buffer: the buffer + * + * Get the version number of the RTP packet in @buffer. + * + * Returns: The version of @buffer. + */ +guint8 +gst_rtp_buffer_get_version (GstBuffer * buffer) +{ + return GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_set_version: + * @buffer: the buffer + * @version: the new version + * + * Set the version of the RTP packet in @buffer to @version. + */ +void +gst_rtp_buffer_set_version (GstBuffer * buffer, guint8 version) +{ + g_return_if_fail (version < 0x04); + + GST_RTP_HEADER_VERSION (GST_BUFFER_DATA (buffer)) = version; +} + +/** + * gst_rtp_buffer_get_padding: + * @buffer: the buffer + * + * Check if the padding bit is set on the RTP packet in @buffer. + * + * Returns: TRUE if @buffer has the padding bit set. + */ +gboolean +gst_rtp_buffer_get_padding (GstBuffer * buffer) +{ + return GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_set_padding: + * @buffer: the buffer + * @padding: the new padding + * + * Set the padding bit on the RTP packet in @buffer to @padding. + */ +void +gst_rtp_buffer_set_padding (GstBuffer * buffer, gboolean padding) +{ + GST_RTP_HEADER_PADDING (GST_BUFFER_DATA (buffer)) = padding; +} + +/** + * gst_rtp_buffer_pad_to: + * @buffer: the buffer + * @len: the new amount of padding + * + * Set the amount of padding in the RTP packet in @buffer to + * @len. If @len is 0, the padding is removed. + * + * NOTE: This function does not work correctly. + */ +void +gst_rtp_buffer_pad_to (GstBuffer * buffer, guint len) +{ + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + + if (len > 0) + GST_RTP_HEADER_PADDING (data) = TRUE; + else + GST_RTP_HEADER_PADDING (data) = FALSE; + + /* FIXME, set the padding byte at the end of the payload data */ +} + +/** + * gst_rtp_buffer_get_extension: + * @buffer: the buffer + * + * Check if the extension bit is set on the RTP packet in @buffer. + * + * Returns: TRUE if @buffer has the extension bit set. + */ +gboolean +gst_rtp_buffer_get_extension (GstBuffer * buffer) +{ + return GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_set_extension: + * @buffer: the buffer + * @extension: the new extension + * + * Set the extension bit on the RTP packet in @buffer to @extension. + */ +void +gst_rtp_buffer_set_extension (GstBuffer * buffer, gboolean extension) +{ + GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer)) = extension; +} + +/** + * gst_rtp_buffer_get_extension_data: + * @buffer: the buffer + * @bits: location for result bits + * @data: location for data + * @wordlen: location for length of @data in 32 bits words + * + * Get the extension data. @bits will contain the extension 16 bits of custom + * data. @data will point to the data in the extension and @wordlen will contain + * the length of @data in 32 bits words. + * + * If @buffer did not contain an extension, this function will return %FALSE + * with @bits, @data and @wordlen unchanged. + * + * Returns: TRUE if @buffer had the extension bit set. + * + * Since: 0.10.15 + */ +gboolean +gst_rtp_buffer_get_extension_data (GstBuffer * buffer, guint16 * bits, + gpointer * data, guint * wordlen) +{ + guint len; + guint8 *pdata; + + pdata = GST_BUFFER_DATA (buffer); + + if (!GST_RTP_HEADER_EXTENSION (pdata)) + return FALSE; + + /* move to the extension */ + len = GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (pdata); + pdata += len; + + if (bits) + *bits = GST_READ_UINT16_BE (pdata); + if (wordlen) + *wordlen = GST_READ_UINT16_BE (pdata + 2); + if (data) + *data = pdata + 4; + + return TRUE; +} + +/** + * gst_rtp_buffer_set_extension_data: + * @buffer: the buffer + * @bits: the bits specific for the extension + * @length: the length that counts the number of 32-bit words in + * the extension, excluding the extension header ( therefore zero is a valid length) + * + * Set the extension bit of the rtp buffer and fill in the @bits and @length of the + * extension header. It will refuse to set the extension data if the buffer is not + * large enough. + * + * Returns: True if done. + * + * Since: 0.10.18 + */ +gboolean +gst_rtp_buffer_set_extension_data (GstBuffer * buffer, guint16 bits, + guint16 length) +{ + guint32 min_size = 0; + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + + /* check if the buffer is big enough to hold the extension */ + min_size = + GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data) + 4 + + length * sizeof (guint32); + if (G_UNLIKELY (min_size > GST_BUFFER_SIZE (buffer))) + goto too_small; + + /* now we can set the extension bit */ + gst_rtp_buffer_set_extension (buffer, TRUE); + + data += GST_RTP_HEADER_LEN + GST_RTP_HEADER_CSRC_SIZE (data); + GST_WRITE_UINT16_BE (data, bits); + GST_WRITE_UINT16_BE (data + 2, length); + + return TRUE; + + /* ERRORS */ +too_small: + { + g_warning + ("rtp buffer too small: need more than %d bytes but only have %d bytes", + min_size, GST_BUFFER_SIZE (buffer)); + return FALSE; + } +} + +/** + * gst_rtp_buffer_get_ssrc: + * @buffer: the buffer + * + * Get the SSRC of the RTP packet in @buffer. + * + * Returns: the SSRC of @buffer in host order. + */ +guint32 +gst_rtp_buffer_get_ssrc (GstBuffer * buffer) +{ + return g_ntohl (GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer))); +} + +/** + * gst_rtp_buffer_list_get_ssrc: + * @list: the buffer list + * + * Get the SSRC of the first RTP packet in @list. + * All RTP packets within @list have the same SSRC. + * + * Returns: the SSRC of @list in host order. + * + * Since: 0.10.24 + */ +guint32 +gst_rtp_buffer_list_get_ssrc (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer))); +} + +/** + * gst_rtp_buffer_set_ssrc: + * @buffer: the buffer + * @ssrc: the new SSRC + * + * Set the SSRC on the RTP packet in @buffer to @ssrc. + */ +void +gst_rtp_buffer_set_ssrc (GstBuffer * buffer, guint32 ssrc) +{ + GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (buffer)) = g_htonl (ssrc); +} + +static GstBufferListItem +set_ssrc_header (GstBuffer ** buffer, guint group, guint idx, guint32 * ssrc) +{ + GST_RTP_HEADER_SSRC (GST_BUFFER_DATA (*buffer)) = g_htonl (*ssrc); + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_ssrc: + * @list: the buffer list + * @ssrc: the new SSRC + * + * Set the SSRC on each RTP packet in @list to @ssrc. + * + * Since: 0.10.24 + */ +void +gst_rtp_buffer_list_set_ssrc (GstBufferList * list, guint32 ssrc) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_ssrc_header, &ssrc); +} + +/** + * gst_rtp_buffer_get_csrc_count: + * @buffer: the buffer + * + * Get the CSRC count of the RTP packet in @buffer. + * + * Returns: the CSRC count of @buffer. + */ +guint8 +gst_rtp_buffer_get_csrc_count (GstBuffer * buffer) +{ + return GST_RTP_HEADER_CSRC_COUNT (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_get_csrc: + * @buffer: the buffer + * @idx: the index of the CSRC to get + * + * Get the CSRC at index @idx in @buffer. + * + * Returns: the CSRC at index @idx in host order. + */ +guint32 +gst_rtp_buffer_get_csrc (GstBuffer * buffer, guint8 idx) +{ + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + + g_return_val_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data), 0); + + return GST_READ_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx)); +} + +/** + * gst_rtp_buffer_set_csrc: + * @buffer: the buffer + * @idx: the CSRC index to set + * @csrc: the CSRC in host order to set at @idx + * + * Modify the CSRC at index @idx in @buffer to @csrc. + */ +void +gst_rtp_buffer_set_csrc (GstBuffer * buffer, guint8 idx, guint32 csrc) +{ + guint8 *data; + + data = GST_BUFFER_DATA (buffer); + + g_return_if_fail (idx < GST_RTP_HEADER_CSRC_COUNT (data)); + + GST_WRITE_UINT32_BE (GST_RTP_HEADER_CSRC_LIST_OFFSET (data, idx), csrc); +} + +/** + * gst_rtp_buffer_get_marker: + * @buffer: the buffer + * + * Check if the marker bit is set on the RTP packet in @buffer. + * + * Returns: TRUE if @buffer has the marker bit set. + */ +gboolean +gst_rtp_buffer_get_marker (GstBuffer * buffer) +{ + return GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_set_marker: + * @buffer: the buffer + * @marker: the new marker + * + * Set the marker bit on the RTP packet in @buffer to @marker. + */ +void +gst_rtp_buffer_set_marker (GstBuffer * buffer, gboolean marker) +{ + GST_RTP_HEADER_MARKER (GST_BUFFER_DATA (buffer)) = marker; +} + +/** + * gst_rtp_buffer_get_payload_type: + * @buffer: the buffer + * + * Get the payload type of the RTP packet in @buffer. + * + * Returns: The payload type. + */ +guint8 +gst_rtp_buffer_get_payload_type (GstBuffer * buffer) +{ + return GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_list_get_payload_type: + * @list: the buffer list + * + * Get the payload type of the first RTP packet in @list. + * All packets in @list should have the same payload type. + * + * Returns: The payload type. + * + * Since: 0.10.24 + */ +guint8 +gst_rtp_buffer_list_get_payload_type (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)); +} + +/** + * gst_rtp_buffer_set_payload_type: + * @buffer: the buffer + * @payload_type: the new type + * + * Set the payload type of the RTP packet in @buffer to @payload_type. + */ +void +gst_rtp_buffer_set_payload_type (GstBuffer * buffer, guint8 payload_type) +{ + g_return_if_fail (payload_type < 0x80); + + GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (buffer)) = payload_type; +} + +static GstBufferListItem +set_pt_header (GstBuffer ** buffer, guint group, guint idx, guint8 * pt) +{ + GST_RTP_HEADER_PAYLOAD_TYPE (GST_BUFFER_DATA (*buffer)) = *pt; + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_payload_type: + * @list: the buffer list + * @payload_type: the new type + * + * Set the payload type of each RTP packet in @list to @payload_type. + * + * Since: 0.10.24 + */ +void +gst_rtp_buffer_list_set_payload_type (GstBufferList * list, guint8 payload_type) +{ + g_return_if_fail (payload_type < 0x80); + + gst_buffer_list_foreach (list, (GstBufferListFunc) set_pt_header, + &payload_type); +} + +/** + * gst_rtp_buffer_get_seq: + * @buffer: the buffer + * + * Get the sequence number of the RTP packet in @buffer. + * + * Returns: The sequence number in host order. + */ +guint16 +gst_rtp_buffer_get_seq (GstBuffer * buffer) +{ + return g_ntohs (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer))); +} + +/** + * gst_rtp_buffer_set_seq: + * @buffer: the buffer + * @seq: the new sequence number + * + * Set the sequence number of the RTP packet in @buffer to @seq. + */ +void +gst_rtp_buffer_set_seq (GstBuffer * buffer, guint16 seq) +{ + GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer)) = g_htons (seq); +} + +static GstBufferListItem +set_seq_header (GstBuffer ** buffer, guint group, guint idx, guint16 * seq) +{ + GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (*buffer)) = g_htons (*seq); + (*seq)++; + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_seq: + * @list: the buffer list + * @seq: the new sequence number + * + * Set the sequence number of each RTP packet in @list to @seq. + * + * Returns: The seq number of the last packet in the list + 1. + * + * Since: 0.10.24 + */ +guint16 +gst_rtp_buffer_list_set_seq (GstBufferList * list, guint16 seq) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_seq_header, &seq); + return seq; +} + +/** + * gst_rtp_buffer_list_get_seq: + * @list: the buffer list + * + * Get the sequence number of the first RTP packet in @list. + * All packets within @list have the same sequence number. + * + * Returns: The seq number + * + * Since: 0.10.24 + */ +guint16 +gst_rtp_buffer_list_get_seq (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_SEQ (GST_BUFFER_DATA (buffer))); +} + + +/** + * gst_rtp_buffer_get_timestamp: + * @buffer: the buffer + * + * Get the timestamp of the RTP packet in @buffer. + * + * Returns: The timestamp in host order. + */ +guint32 +gst_rtp_buffer_get_timestamp (GstBuffer * buffer) +{ + return g_ntohl (GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer))); +} + +/** + * gst_rtp_buffer_list_get_timestamp: + * @list: the buffer list + * + * Get the timestamp of the first RTP packet in @list. + * All packets within @list have the same timestamp. + * + * Returns: The timestamp in host order. + * + * Since: 0.10.24 + */ +guint32 +gst_rtp_buffer_list_get_timestamp (GstBufferList * list) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (list, 0, 0); + g_return_val_if_fail (buffer != NULL, 0); + + return g_ntohl (GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer))); +} + +/** + * gst_rtp_buffer_set_timestamp: + * @buffer: the buffer + * @timestamp: the new timestamp + * + * Set the timestamp of the RTP packet in @buffer to @timestamp. + */ +void +gst_rtp_buffer_set_timestamp (GstBuffer * buffer, guint32 timestamp) +{ + GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (buffer)) = g_htonl (timestamp); +} + + +static GstBufferListItem +set_timestamp_header (GstBuffer ** buffer, guint group, guint idx, + guint32 * timestamp) +{ + GST_RTP_HEADER_TIMESTAMP (GST_BUFFER_DATA (*buffer)) = g_htonl (*timestamp); + return GST_BUFFER_LIST_SKIP_GROUP; +} + +/** + * gst_rtp_buffer_list_set_timestamp: + * @list: the buffer list + * @timestamp: the new timestamp + * + * Set the timestamp of each RTP packet in @list to @timestamp. + * + * Since: 0.10.24 + */ +void +gst_rtp_buffer_list_set_timestamp (GstBufferList * list, guint32 timestamp) +{ + gst_buffer_list_foreach (list, (GstBufferListFunc) set_timestamp_header, + ×tamp); +} + +/** + * gst_rtp_buffer_get_payload_subbuffer: + * @buffer: the buffer + * @offset: the offset in the payload + * @len: the length in the payload + * + * Create a subbuffer of the payload of the RTP packet in @buffer. @offset bytes + * are skipped in the payload and the subbuffer will be of size @len. + * If @len is -1 the total payload starting from @offset if subbuffered. + * + * Returns: A new buffer with the specified data of the payload. + * + * Since: 0.10.10 + */ +GstBuffer * +gst_rtp_buffer_get_payload_subbuffer (GstBuffer * buffer, guint offset, + guint len) +{ + guint poffset, plen; + + plen = gst_rtp_buffer_get_payload_len (buffer); + /* we can't go past the length */ + if (G_UNLIKELY (offset >= plen)) + goto wrong_offset; + + /* apply offset */ + poffset = gst_rtp_buffer_get_header_len (buffer) + offset; + plen -= offset; + + /* see if we need to shrink the buffer based on @len */ + if (len != -1 && len < plen) + plen = len; + + return gst_buffer_create_sub (buffer, poffset, plen); + + /* ERRORS */ +wrong_offset: + { + g_warning ("offset=%u should be less then plen=%u", offset, plen); + return NULL; + } +} + +/** + * gst_rtp_buffer_get_payload_buffer: + * @buffer: the buffer + * + * Create a buffer of the payload of the RTP packet in @buffer. This function + * will internally create a subbuffer of @buffer so that a memcpy can be + * avoided. + * + * Returns: A new buffer with the data of the payload. + */ +GstBuffer * +gst_rtp_buffer_get_payload_buffer (GstBuffer * buffer) +{ + return gst_rtp_buffer_get_payload_subbuffer (buffer, 0, -1); +} + +/** + * gst_rtp_buffer_get_payload_len: + * @buffer: the buffer + * + * Get the length of the payload of the RTP packet in @buffer. + * + * Returns: The length of the payload in @buffer. + */ +guint +gst_rtp_buffer_get_payload_len (GstBuffer * buffer) +{ + guint len, size; + guint8 *data; + + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + len = size - gst_rtp_buffer_get_header_len (buffer); + + if (GST_RTP_HEADER_PADDING (data)) + len -= data[size - 1]; + + return len; +} + +/** + * gst_rtp_buffer_list_get_payload_len: + * @list: the buffer list + * + * Get the length of the payload of the RTP packet in @list. + * + * Returns: The length of the payload in @list. + * + * Since: 0.10.24 + */ +guint +gst_rtp_buffer_list_get_payload_len (GstBufferList * list) +{ + guint len; + GstBufferListIterator *it; + + it = gst_buffer_list_iterate (list); + len = 0; + + while (gst_buffer_list_iterator_next_group (it)) { + guint i; + GstBuffer *buf; + + i = 0; + while ((buf = gst_buffer_list_iterator_next (it))) { + /* skip the RTP header */ + if (!i++) + continue; + /* take the size of the current buffer */ + len += GST_BUFFER_SIZE (buf); + } + } + + gst_buffer_list_iterator_free (it); + + return len; +} + +/** + * gst_rtp_buffer_get_payload: + * @buffer: the buffer + * + * Get a pointer to the payload data in @buffer. This pointer is valid as long + * as a reference to @buffer is held. + * + * Returns: A pointer to the payload data in @buffer. + */ +gpointer +gst_rtp_buffer_get_payload (GstBuffer * buffer) +{ + return GST_BUFFER_DATA (buffer) + gst_rtp_buffer_get_header_len (buffer); +} + +/** + * gst_rtp_buffer_default_clock_rate: + * @payload_type: the static payload type + * + * Get the default clock-rate for the static payload type @payload_type. + * + * Returns: the default clock rate or -1 if the payload type is not static or + * the clock-rate is undefined. + * + * Since: 0.10.13 + */ +guint32 +gst_rtp_buffer_default_clock_rate (guint8 payload_type) +{ + const GstRTPPayloadInfo *info; + guint32 res; + + info = gst_rtp_payload_info_for_pt (payload_type); + if (!info) + return -1; + + res = info->clock_rate; + /* 0 means unknown so we have to return -1 from this function */ + if (res == 0) + res = -1; + + return res; +} + +/** + * gst_rtp_buffer_compare_seqnum: + * @seqnum1: a sequence number + * @seqnum2: a sequence number + * + * Compare two sequence numbers, taking care of wraparounds. This function + * returns the difference between @seqnum1 and @seqnum2. + * + * Returns: a negative value if @seqnum1 is bigger than @seqnum2, 0 if they + * are equal or a positive value if @seqnum1 is smaller than @segnum2. + * + * Since: 0.10.15 + */ +gint +gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2) +{ + return (gint16) (seqnum2 - seqnum1); +} + +/** + * gst_rtp_buffer_ext_timestamp: + * @exttimestamp: a previous extended timestamp + * @timestamp: a new timestamp + * + * Update the @exttimestamp field with @timestamp. For the first call of the + * method, @exttimestamp should point to a location with a value of -1. + * + * This function makes sure that the returned value is a constantly increasing + * value even in the case where there is a timestamp wraparound. + * + * Returns: The extended timestamp of @timestamp. + * + * Since: 0.10.15 + */ +guint64 +gst_rtp_buffer_ext_timestamp (guint64 * exttimestamp, guint32 timestamp) +{ + guint64 result, diff, ext; + + g_return_val_if_fail (exttimestamp != NULL, -1); + + ext = *exttimestamp; + + if (ext == -1) { + result = timestamp; + } else { + /* pick wraparound counter from previous timestamp and add to new timestamp */ + result = timestamp + (ext & ~(G_GINT64_CONSTANT (0xffffffff))); + + /* check for timestamp wraparound */ + if (result < ext) + diff = ext - result; + else + diff = result - ext; + + if (diff > G_MAXINT32) { + /* timestamp went backwards more than allowed, we wrap around and get + * updated extended timestamp. */ + result += (G_GINT64_CONSTANT (1) << 32); + } + } + *exttimestamp = result; + + return result; +} + +/** + * gst_rtp_buffer_get_extension_onebyte_header: + * @buffer: the buffer + * @id: The ID of the header extension to be read (between 1 and 14). + * @nth: Read the nth extension packet with the requested ID + * @data: location for data + * @size: the size of the data in bytes + * + * Parses RFC 5285 style header extensions with a one byte header. It will + * return the nth extension with the requested id. + * + * Returns: TRUE if @buffer had the requested header extension + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_get_extension_onebyte_header (GstBuffer * buffer, guint8 id, + guint nth, gpointer * data, guint * size) +{ + guint16 bits; + guint8 *pdata; + guint wordlen; + gulong offset = 0; + guint count = 0; + + g_return_val_if_fail (id > 0 && id < 15, FALSE); + + if (!gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata, + &wordlen)) + return FALSE; + + if (bits != 0xBEDE) + return FALSE; + + for (;;) { + guint8 read_id, read_len; + + if (offset + 1 >= wordlen * 4) + break; + + read_id = GST_READ_UINT8 (pdata + offset) >> 4; + read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1; + offset += 1; + + /* ID 0 means its padding, skip */ + if (read_id == 0) + continue; + + /* ID 15 is special and means we should stop parsing */ + if (read_id == 15) + break; + + /* Ignore extension headers where the size does not fit */ + if (offset + read_len > wordlen * 4) + break; + + /* If we have the right one */ + if (id == read_id) { + if (nth == count) { + if (data) + *data = pdata + offset; + if (size) + *size = read_len; + + return TRUE; + } + + count++; + } + offset += read_len; + + if (offset >= wordlen * 4) + break; + } + + return FALSE; +} + +/** + * gst_rtp_buffer_get_extension_twobytes_header: + * @buffer: the buffer + * @appbits: Application specific bits + * @id: The ID of the header extension to be read (between 1 and 14). + * @nth: Read the nth extension packet with the requested ID + * @data: location for data + * @size: the size of the data in bytes + * + * Parses RFC 5285 style header extensions with a two bytes header. It will + * return the nth extension with the requested id. + * + * Returns: TRUE if @buffer had the requested header extension + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_get_extension_twobytes_header (GstBuffer * buffer, + guint8 * appbits, guint8 id, guint nth, gpointer * data, guint * size) +{ + guint16 bits; + guint8 *pdata; + guint wordlen; + guint bytelen; + gulong offset = 0; + guint count = 0; + + if (!gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata, + &wordlen)) + return FALSE; + + if (bits >> 4 != 0x100) + return FALSE; + + bytelen = wordlen * 4; + + for (;;) { + guint8 read_id, read_len; + + if (offset + 2 >= bytelen) + break; + + read_id = GST_READ_UINT8 (pdata + offset); + offset += 1; + + if (read_id == 0) + continue; + + read_len = GST_READ_UINT8 (pdata + offset); + offset += 1; + + /* Ignore extension headers where the size does not fit */ + if (offset + read_len > bytelen) + break; + + /* If we have the right one, return it */ + if (id == read_id) { + if (nth == count) { + if (data) + *data = pdata + offset; + if (size) + *size = read_len; + if (appbits) + *appbits = bits; + + return TRUE; + } + + count++; + } + offset += read_len; + } + + return FALSE; +} + +static guint +get_onebyte_header_end_offset (guint8 * pdata, guint wordlen) +{ + guint offset = 0; + guint bytelen = wordlen * 4; + guint paddingcount = 0; + + while (offset + 1 < bytelen) { + guint8 read_id, read_len; + + read_id = GST_READ_UINT8 (pdata + offset) >> 4; + read_len = (GST_READ_UINT8 (pdata + offset) & 0x0F) + 1; + offset += 1; + + /* ID 0 means its padding, skip */ + if (read_id == 0) { + paddingcount++; + continue; + } + + paddingcount = 0; + + /* ID 15 is special and means we should stop parsing */ + /* It also means we can't add an extra packet */ + if (read_id == 15) + return 0; + + /* Ignore extension headers where the size does not fit */ + if (offset + read_len > bytelen) + return 0; + + offset += read_len; + } + + return offset - paddingcount; +} + +/** + * gst_rtp_buffer_add_extension_onebyte_header: + * @buffer: the buffer + * @id: The ID of the header extension (between 1 and 14). + * @data: location for data + * @size: the size of the data in bytes + * + * Adds a RFC 5285 header extension with a one byte header to the end of the + * RTP header. If there is already a RFC 5285 header extension with a one byte + * header, the new extension will be appended. + * It will not work if there is already a header extension that does not follow + * the mecanism described in RFC 5285 or if there is a header extension with + * a two bytes header as described in RFC 5285. In that case, use + * gst_rtp_buffer_add_extension_twobytes_header() + * + * Returns: %TRUE if header extension could be added + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_add_extension_onebyte_header (GstBuffer * buffer, guint8 id, + gpointer data, guint size) +{ + guint16 bits; + guint8 *pdata; + guint wordlen; + gboolean has_bit; + + g_return_val_if_fail (id > 0 && id < 15, FALSE); + g_return_val_if_fail (size >= 1 && size <= 16, FALSE); + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + + has_bit = gst_rtp_buffer_get_extension_data (buffer, &bits, + (gpointer) & pdata, &wordlen); + + if (has_bit) { + gulong offset = 0; + guint8 *nextext; + guint extlen; + + if (bits != 0xBEDE) + return FALSE; + + offset = get_onebyte_header_end_offset (pdata, wordlen); + if (offset == 0) + return FALSE; + + nextext = pdata + offset; + offset = nextext - GST_BUFFER_DATA (buffer); + + /* Don't add extra header if there isn't enough space */ + if (GST_BUFFER_SIZE (buffer) < offset + size + 1) + return FALSE; + + nextext[0] = (id << 4) | (0x0F & (size - 1)); + memcpy (nextext + 1, data, size); + + extlen = nextext - pdata + size + 1; + if (extlen % 4) { + wordlen = extlen / 4 + 1; + memset (nextext + size + 1, 0, 4 - extlen % 4); + } else { + wordlen = extlen / 4; + } + + gst_rtp_buffer_set_extension_data (buffer, 0xBEDE, wordlen); + } else { + wordlen = (size + 1) / 4 + (((size + 1) % 4) ? 1 : 0); + + gst_rtp_buffer_set_extension_data (buffer, 0xBEDE, wordlen); + + gst_rtp_buffer_get_extension_data (buffer, &bits, + (gpointer) & pdata, &wordlen); + + pdata[0] = (id << 4) | (0x0F & (size - 1)); + memcpy (pdata + 1, data, size); + + if ((size + 1) % 4) + memset (pdata + size + 1, 0, 4 - ((size + 1) % 4)); + } + + return TRUE; +} + + +static guint +get_twobytes_header_end_offset (guint8 * pdata, guint wordlen) +{ + guint offset = 0; + guint bytelen = wordlen * 4; + guint paddingcount = 0; + + while (offset + 2 < bytelen) { + guint8 read_id, read_len; + + read_id = GST_READ_UINT8 (pdata + offset); + offset += 1; + + /* ID 0 means its padding, skip */ + if (read_id == 0) { + paddingcount++; + continue; + } + + paddingcount = 0; + + read_len = GST_READ_UINT8 (pdata + offset); + offset += 1; + + /* Ignore extension headers where the size does not fit */ + if (offset + read_len > bytelen) + return 0; + + offset += read_len; + } + + return offset - paddingcount; +} + +/** + * gst_rtp_buffer_add_extension_twobytes_header: + * @buffer: the buffer + * @appbits: Application specific bits + * @id: The ID of the header extension + * @data: location for data + * @size: the size of the data in bytes + * + * Adds a RFC 5285 header extension with a two bytes header to the end of the + * RTP header. If there is already a RFC 5285 header extension with a two bytes + * header, the new extension will be appended. + * It will not work if there is already a header extension that does not follow + * the mecanism described in RFC 5285 or if there is a header extension with + * a one byte header as described in RFC 5285. In that case, use + * gst_rtp_buffer_add_extension_onebyte_header() + * + * Returns: %TRUE if header extension could be added + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_add_extension_twobytes_header (GstBuffer * buffer, + guint8 appbits, guint8 id, gpointer data, guint size) +{ + guint16 bits; + guint8 *pdata; + guint wordlen; + gboolean has_bit; + + g_return_val_if_fail ((appbits & 0xF0) == 0, FALSE); + g_return_val_if_fail (size < 256, FALSE); + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + + has_bit = gst_rtp_buffer_get_extension_data (buffer, &bits, + (gpointer) & pdata, &wordlen); + + if (has_bit) { + gulong offset = 0; + guint8 *nextext; + guint extlen; + + if (bits != ((0x100 << 4) | (appbits & 0x0f))) + return FALSE; + + offset = get_twobytes_header_end_offset (pdata, wordlen); + + nextext = pdata + offset; + + offset = nextext - GST_BUFFER_DATA (buffer); + + /* Don't add extra header if there isn't enough space */ + if (GST_BUFFER_SIZE (buffer) < offset + size + 2) + return FALSE; + + nextext[0] = id; + nextext[1] = size; + memcpy (nextext + 2, data, size); + + extlen = nextext - pdata + size + 2; + if (extlen % 4) { + wordlen = extlen / 4 + 1; + memset (nextext + size + 2, 0, 4 - extlen % 4); + } else { + wordlen = extlen / 4; + } + + gst_rtp_buffer_set_extension_data (buffer, (0x100 << 4) | (appbits & 0x0F), + wordlen); + } else { + wordlen = (size + 2) / 4 + (((size + 2) % 4) ? 1 : 0); + + gst_rtp_buffer_set_extension_data (buffer, (0x100 << 4) | (appbits & 0x0F), + wordlen); + + gst_rtp_buffer_get_extension_data (buffer, &bits, + (gpointer) & pdata, &wordlen); + + pdata[0] = id; + pdata[1] = size; + memcpy (pdata + 2, data, size); + if ((size + 2) % 4) + memset (pdata + size + 2, 0, 4 - ((size + 2) % 4)); + } + + return TRUE; +} + +/** + * gst_rtp_buffer_list_get_extension_onebyte_header: + * @bufferlist: the bufferlist + * @group_idx: The index of the group in the #GstBufferList + * @id: The ID of the header extension to be read (between 1 and 14). + * @nth: Read the nth extension packet with the requested ID + * @data: location for data + * @size: the size of the data in bytes + * + * Parses RFC 5285 style header extensions with a one byte header. It will + * return the nth extension with the requested id. + * + * Returns: TRUE if @buffer had the requested header extension + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_list_get_extension_onebyte_header (GstBufferList * bufferlist, + guint group_idx, guint8 id, guint nth, gpointer * data, guint * size) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (bufferlist, group_idx, 0); + + if (!buffer) + return FALSE; + + return gst_rtp_buffer_get_extension_onebyte_header (buffer, id, nth, data, + size); +} + + +/** + * gst_rtp_buffer_list_get_extension_twobytes_header: + * @bufferlist: the bufferlist + * @group_idx: The index of the group in the #GstBufferList + * @appbits: Application specific bits + * @id: The ID of the header extension to be read (between 1 and 14). + * @nth: Read the nth extension packet with the requested ID + * @data: location for data + * @size: the size of the data in bytes + * + * Parses RFC 5285 style header extensions with a two bytes header. It will + * return the nth extension with the requested id. + * + * Returns: TRUE if @buffer had the requested header extension + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_list_get_extension_twobytes_header (GstBufferList * bufferlist, + guint group_idx, guint8 * appbits, guint8 id, guint nth, + gpointer * data, guint * size) +{ + GstBuffer *buffer; + + buffer = gst_buffer_list_get (bufferlist, group_idx, 0); + + if (!buffer) + return FALSE; + + return gst_rtp_buffer_get_extension_twobytes_header (buffer, appbits, id, + nth, data, size); +} + +/** + * gst_rtp_buffer_list_add_extension_onebyte_header: + * @it: a #GstBufferListIterator pointing right after the #GstBuffer where + * the header extension should be added + * @id: The ID of the header extension (between 1 and 14). + * @data: location for data + * @size: the size of the data in bytes + * + * Adds a RFC 5285 header extension with a one byte header to the end of the + * RTP header. If there is already a RFC 5285 header extension with a one byte + * header, the new extension will be appended. + * It will not work if there is already a header extension that does not follow + * the mecanism described in RFC 5285 or if there is a header extension with + * a two bytes header as described in RFC 5285. In that case, use + * gst_rtp_buffer_list_add_extension_twobytes_header() + * + * This function will not modify the data section of the RTP buffer, only + * the header. + * + * Returns: %TRUE if header extension could be added + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_list_add_extension_onebyte_header (GstBufferListIterator * it, + guint8 id, gpointer data, guint size) +{ + GstBuffer *buffer; + guint16 bits; + guint8 *pdata; + guint wordlen; + gboolean retval; + guint endoffset = 0; + + g_return_val_if_fail (gst_buffer_list_iterator_n_buffers (it) == 1, FALSE); + g_return_val_if_fail (id > 0 && id < 15, FALSE); + g_return_val_if_fail (size >= 1 && size <= 16, FALSE); + + buffer = gst_buffer_list_iterator_steal (it); + + if (GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer))) { + gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata, + &wordlen); + + if (bits != 0xBEDE) + return FALSE; + + endoffset = get_onebyte_header_end_offset (pdata, wordlen); + if (endoffset == 0) + return FALSE; + endoffset += pdata - GST_BUFFER_DATA (buffer); + } else { + endoffset = GST_BUFFER_SIZE (buffer) + 4; + } + + if (endoffset + size + 1 > GST_BUFFER_SIZE (buffer)) { + guint newsize; + GstBuffer *newbuffer; + + newsize = endoffset + size + 1; + if (newsize % 4) + newsize += 4 - (newsize % 4); + newbuffer = gst_buffer_new_and_alloc (newsize); + memcpy (GST_BUFFER_DATA (newbuffer), GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + gst_buffer_copy_metadata (newbuffer, buffer, GST_BUFFER_COPY_ALL); + gst_buffer_unref (buffer); + buffer = newbuffer; + } else { + buffer = gst_buffer_make_writable (buffer); + } + + retval = gst_rtp_buffer_add_extension_onebyte_header (buffer, id, data, size); + + gst_buffer_list_iterator_take (it, buffer); + + return retval; +} + +/** + * gst_rtp_buffer_list_add_extension_twobytes_header: + * @it: a #GstBufferListIterator pointing right after the #GstBuffer where + * the header extension should be added + * @appbits: Application specific bits + * @id: The ID of the header extension + * @data: location for data + * @size: the size of the data in bytes + * + * Adds a RFC 5285 header extension with a two bytes header to the end of the + * RTP header. If there is already a RFC 5285 header extension with a two bytes + * header, the new extension will be appended. + * It will not work if there is already a header extension that does not follow + * the mecanism described in RFC 5285 or if there is a header extension with + * a one byte header as described in RFC 5285. In that case, use + * gst_rtp_buffer_add_extension_onebyte_header() + * + * This function will not modify the data section of the RTP buffer, only + * the header. + * + * Returns: %TRUE if header extension could be added + * + * Since: 0.10.31 + */ + +gboolean +gst_rtp_buffer_list_add_extension_twobytes_header (GstBufferListIterator * it, + guint8 appbits, guint8 id, gpointer data, guint size) +{ + GstBuffer *buffer; + guint16 bits; + guint8 *pdata; + guint wordlen; + gboolean retval; + guint endoffset; + + g_return_val_if_fail ((appbits & 0xF0) == 0, FALSE); + g_return_val_if_fail (size < 256, FALSE); + g_return_val_if_fail (gst_buffer_list_iterator_n_buffers (it) == 1, FALSE); + + buffer = gst_buffer_list_iterator_steal (it); + + if (GST_RTP_HEADER_EXTENSION (GST_BUFFER_DATA (buffer))) { + gst_rtp_buffer_get_extension_data (buffer, &bits, (gpointer) & pdata, + &wordlen); + + if (bits != ((0x100 << 4) | (appbits & 0x0f))) + return FALSE; + + endoffset = get_twobytes_header_end_offset (pdata, wordlen); + if (endoffset == 0) + return FALSE; + endoffset += pdata - GST_BUFFER_DATA (buffer); + } else { + endoffset = GST_BUFFER_SIZE (buffer) + 4; + } + + if (endoffset + size + 2 > GST_BUFFER_SIZE (buffer)) { + guint newsize; + GstBuffer *newbuffer; + + newsize = endoffset + size + 2; + if (newsize % 4) + newsize += 4 - newsize % 4; + newbuffer = gst_buffer_new_and_alloc (newsize); + memcpy (GST_BUFFER_DATA (newbuffer), GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + gst_buffer_copy_metadata (newbuffer, buffer, GST_BUFFER_COPY_ALL); + gst_buffer_unref (buffer); + buffer = newbuffer; + } else { + buffer = gst_buffer_make_writable (buffer); + } + + retval = gst_rtp_buffer_add_extension_twobytes_header (buffer, appbits, id, + data, size); + + gst_buffer_list_iterator_take (it, buffer); + + return retval; +} + +/** + * gst_rtp_buffer_list_from_buffer: + * @buffer: a #GstBuffer containing a RTP packet + * + * Splits a #GstBuffer into a #GstBufferList containing separate + * buffers for the header and data sections. + * + * Returns: a #GstBufferList + */ + +GstBufferList * +gst_rtp_buffer_list_from_buffer (GstBuffer * buffer) +{ + GstBufferList *bufferlist; + GstBuffer *sub; + GstBufferListIterator *it; + guint8 *payload; + + bufferlist = gst_buffer_list_new (); + + it = gst_buffer_list_iterate (bufferlist); + gst_buffer_list_iterator_add_group (it); + + payload = gst_rtp_buffer_get_payload (buffer); + sub = gst_buffer_create_sub (buffer, 0, payload - GST_BUFFER_DATA (buffer)); + gst_buffer_list_iterator_add (it, sub); + + sub = gst_rtp_buffer_get_payload_buffer (buffer); + gst_buffer_list_iterator_add (it, sub); + + gst_buffer_list_iterator_free (it); + + return bufferlist; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.h new file mode 100644 index 0000000..c82fd71 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtpbuffer.h @@ -0,0 +1,166 @@ +/* GStreamer + * Copyright (C) <2005> Philippe Khalaf + * <2005> Wim Taymans + * + * gstrtpbuffer.h: various helper functions to manipulate buffers + * with RTP payload. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTPBUFFER_H__ +#define __GST_RTPBUFFER_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GST_RTP_VERSION: + * + * The supported RTP version 2. + */ +#define GST_RTP_VERSION 2 + +/* creating buffers */ +void gst_rtp_buffer_allocate_data (GstBuffer *buffer, guint payload_len, + guint8 pad_len, guint8 csrc_count); + +GstBuffer* gst_rtp_buffer_new_take_data (gpointer data, guint len); +GstBuffer* gst_rtp_buffer_new_copy_data (gpointer data, guint len); +GstBuffer* gst_rtp_buffer_new_allocate (guint payload_len, guint8 pad_len, guint8 csrc_count); +GstBuffer* gst_rtp_buffer_new_allocate_len (guint packet_len, guint8 pad_len, guint8 csrc_count); + +GstBufferList* gst_rtp_buffer_list_from_buffer (GstBuffer * buffer); + + +guint gst_rtp_buffer_calc_header_len (guint8 csrc_count); +guint gst_rtp_buffer_calc_packet_len (guint payload_len, guint8 pad_len, guint8 csrc_count); +guint gst_rtp_buffer_calc_payload_len (guint packet_len, guint8 pad_len, guint8 csrc_count); + +gboolean gst_rtp_buffer_validate_data (guint8 *data, guint len); +gboolean gst_rtp_buffer_validate (GstBuffer *buffer); +gboolean gst_rtp_buffer_list_validate (GstBufferList *list); + +void gst_rtp_buffer_set_packet_len (GstBuffer *buffer, guint len); +guint gst_rtp_buffer_get_packet_len (GstBuffer *buffer); + +guint gst_rtp_buffer_get_header_len (GstBuffer *buffer); + +guint8 gst_rtp_buffer_get_version (GstBuffer *buffer); +void gst_rtp_buffer_set_version (GstBuffer *buffer, guint8 version); + +gboolean gst_rtp_buffer_get_padding (GstBuffer *buffer); +void gst_rtp_buffer_set_padding (GstBuffer *buffer, gboolean padding); +void gst_rtp_buffer_pad_to (GstBuffer *buffer, guint len); + +gboolean gst_rtp_buffer_get_extension (GstBuffer *buffer); +void gst_rtp_buffer_set_extension (GstBuffer *buffer, gboolean extension); +gboolean gst_rtp_buffer_get_extension_data (GstBuffer *buffer, guint16 *bits, + gpointer *data, guint *wordlen); +gboolean gst_rtp_buffer_set_extension_data (GstBuffer *buffer, guint16 bits, guint16 length); + +guint32 gst_rtp_buffer_get_ssrc (GstBuffer *buffer); +guint32 gst_rtp_buffer_list_get_ssrc (GstBufferList *list); +void gst_rtp_buffer_set_ssrc (GstBuffer *buffer, guint32 ssrc); +void gst_rtp_buffer_list_set_ssrc (GstBufferList *list, guint32 ssrc); + +guint8 gst_rtp_buffer_get_csrc_count (GstBuffer *buffer); +guint32 gst_rtp_buffer_get_csrc (GstBuffer *buffer, guint8 idx); +void gst_rtp_buffer_set_csrc (GstBuffer *buffer, guint8 idx, guint32 csrc); + +gboolean gst_rtp_buffer_get_marker (GstBuffer *buffer); +void gst_rtp_buffer_set_marker (GstBuffer *buffer, gboolean marker); + +guint8 gst_rtp_buffer_get_payload_type (GstBuffer *buffer); +guint8 gst_rtp_buffer_list_get_payload_type (GstBufferList *list); +void gst_rtp_buffer_set_payload_type (GstBuffer *buffer, guint8 payload_type); +void gst_rtp_buffer_list_set_payload_type (GstBufferList *list, guint8 payload_type); + +guint16 gst_rtp_buffer_get_seq (GstBuffer *buffer); +guint16 gst_rtp_buffer_list_get_seq (GstBufferList *list); +void gst_rtp_buffer_set_seq (GstBuffer *buffer, guint16 seq); +guint16 gst_rtp_buffer_list_set_seq (GstBufferList *list, guint16 seq); + +guint32 gst_rtp_buffer_get_timestamp (GstBuffer *buffer); +guint32 gst_rtp_buffer_list_get_timestamp (GstBufferList *list); +void gst_rtp_buffer_set_timestamp (GstBuffer *buffer, guint32 timestamp); +void gst_rtp_buffer_list_set_timestamp (GstBufferList *list, guint32 timestamp); + +GstBuffer* gst_rtp_buffer_get_payload_buffer (GstBuffer *buffer); +GstBuffer* gst_rtp_buffer_get_payload_subbuffer (GstBuffer *buffer, guint offset, guint len); + +guint gst_rtp_buffer_get_payload_len (GstBuffer *buffer); +guint gst_rtp_buffer_list_get_payload_len (GstBufferList *list); +gpointer gst_rtp_buffer_get_payload (GstBuffer *buffer); + +/* some helpers */ +guint32 gst_rtp_buffer_default_clock_rate (guint8 payload_type); +gint gst_rtp_buffer_compare_seqnum (guint16 seqnum1, guint16 seqnum2); +guint64 gst_rtp_buffer_ext_timestamp (guint64 *exttimestamp, guint32 timestamp); + +gboolean gst_rtp_buffer_get_extension_onebyte_header (GstBuffer * buffer, + guint8 id, + guint nth, + gpointer * data, + guint * size); +gboolean gst_rtp_buffer_get_extension_twobytes_header (GstBuffer * buffer, + guint8 * appbits, + guint8 id, + guint nth, + gpointer * data, + guint * size); + +gboolean gst_rtp_buffer_add_extension_onebyte_header (GstBuffer * buffer, + guint8 id, + gpointer data, + guint size); +gboolean gst_rtp_buffer_add_extension_twobytes_header (GstBuffer * buffer, + guint8 appbits, + guint8 id, + gpointer data, + guint size); + +gboolean gst_rtp_buffer_list_get_extension_onebyte_header (GstBufferList * bufferlist, + guint group_idx, + guint8 id, + guint nth, + gpointer * data, + guint * size); +gboolean gst_rtp_buffer_list_get_extension_twobytes_header (GstBufferList * bufferlist, + guint group_idx, + guint8 * appbits, + guint8 id, + guint nth, + gpointer * data, + guint * size); + +gboolean gst_rtp_buffer_list_add_extension_onebyte_header (GstBufferListIterator * it, + guint8 id, + gpointer data, + guint size); +gboolean gst_rtp_buffer_list_add_extension_twobytes_header (GstBufferListIterator * it, + guint8 appbits, + guint8 id, + gpointer data, + guint size); + + +G_END_DECLS + +#endif /* __GST_RTPBUFFER_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.c new file mode 100644 index 0000000..97c0fa9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.c @@ -0,0 +1,229 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * gstrtppayloads.h: various helper functions to deal with RTP payload + * types. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtppayloads + * @short_description: Helper methods for dealing with RTP payloads + * @see_also: gstrtpbuffer + * + * + * + * The GstRTPPayloads helper functions makes it easy to deal with static and dynamic + * payloads. Its main purpose is to retrieve properties such as the default clock-rate + * and get session bandwidth information. + * + * + * + * Last reviewed on 2007-10-01 (0.10.15) + */ + +#include + +#include "gstrtppayloads.h" + +/* pt, encoding_name, media, rate, params, bitrate */ +static const GstRTPPayloadInfo info[] = { + /* static audio */ + {0, "audio", "PCMU", 8000, "1", 64000}, + /* { 1, "audio", "reserved", 0, NULL, 0 }, */ + /* { 2, "audio", "reserved", 0, NULL, 0 }, */ + {3, "audio", "GSM", 8000, "1", 0}, + {4, "audio", "G723", 8000, "1", 0}, + {5, "audio", "DVI4", 8000, "1", 32000}, + {6, "audio", "DVI4", 16000, "1", 64000}, + {7, "audio", "LPC", 8000, "1", 0}, + {8, "audio", "PCMA", 8000, "1", 64000}, + {9, "audio", "G722", 8000, "1", 64000}, + {10, "audio", "L16", 44100, "2", 1411200}, + {11, "audio", "L16", 44100, "1", 705600}, + {12, "audio", "QCELP", 8000, "1", 0}, + {13, "audio", "CN", 8000, "1", 0}, + {14, "audio", "MPA", 90000, NULL, 0}, + {15, "audio", "G728", 8000, "1", 0}, + {16, "audio", "DVI4", 11025, "1", 44100}, + {17, "audio", "DVI4", 22050, "1", 88200}, + {18, "audio", "G729", 8000, "1", 0}, + /* { 19, "audio", "reserved", 0, NULL, 0 }, */ + /* { 20, "audio", "unassigned", 0, NULL, 0 }, */ + /* { 21, "audio", "unassigned", 0, NULL, 0 }, */ + /* { 22, "audio", "unassigned", 0, NULL, 0 }, */ + /* { 23, "audio", "unassigned", 0, NULL, 0 }, */ + + /* video and video/audio */ + /* { 24, "video", "unassigned", 0, NULL, 0 }, */ + {25, "video", "CelB", 90000, NULL, 0}, + {26, "video", "JPEG", 90000, NULL, 0}, + /* { 27, "video", "unassigned", 0, NULL, 0 }, */ + {28, "video", "nv", 90000, NULL, 0}, + /* { 29, "video", "unassigned", 0, NULL, 0 }, */ + /* { 30, "video", "unassigned", 0, NULL, 0 }, */ + {31, "video", "H261", 90000, NULL, 0}, + {32, "video", "MPV", 90000, NULL, 0}, + {33, "video", "MP2T", 90000, NULL, 0}, + {34, "video", "H263", 90000, NULL, 0}, + /* { 35-71, "unassigned", 0, 0, NULL, 0 }, */ + /* { 72-76, "reserved", 0, 0, NULL, 0 }, */ + /* { 77-95, "unassigned", 0, 0, NULL, 0 }, */ + /* { 96-127, "dynamic", 0, 0, NULL, 0 }, */ + + /* dynamic stuff */ + {G_MAXUINT8, "application", "parityfec", 0, NULL, 0}, /* [RFC3009] */ + {G_MAXUINT8, "application", "rtx", 0, NULL, 0}, /* [RFC4588] */ + {G_MAXUINT8, "audio", "AMR", 8000, NULL, 0}, /* [RFC4867][RFC3267] */ + {G_MAXUINT8, "audio", "AMR-WB", 16000, NULL, 0}, /* [RFC4867][RFC3267] */ + {G_MAXUINT8, "audio", "DAT12", 0, NULL, 0}, /* [RFC3190] */ + {G_MAXUINT8, "audio", "dsr-es201108", 0, NULL, 0}, /* [RFC3557] */ + {G_MAXUINT8, "audio", "EVRC", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "EVRC0", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "EVRC1", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "EVRCB", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "EVRCB0", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "EVRCB1", 8000, "1", 0}, /* [RFC4788] */ + {G_MAXUINT8, "audio", "G7221", 16000, "1", 0}, /* [RFC3047] */ + {G_MAXUINT8, "audio", "G726-16", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "G726-24", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "G726-32", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "G726-40", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "G729D", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "G729E", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "GSM-EFR", 8000, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "L8", 0, NULL, 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "RED", 0, NULL, 0}, /* [RFC2198][RFC3555] */ + {G_MAXUINT8, "audio", "rtx", 0, NULL, 0}, /* [RFC4588] */ + {G_MAXUINT8, "audio", "VDVI", 0, "1", 0}, /* [RFC3551][RFC4856] */ + {G_MAXUINT8, "audio", "L20", 0, NULL, 0}, /* [RFC3190] */ + {G_MAXUINT8, "audio", "L24", 0, NULL, 0}, /* [RFC3190] */ + {G_MAXUINT8, "audio", "MP4A-LATM", 0, NULL, 0}, /* [RFC3016] */ + {G_MAXUINT8, "audio", "mpa-robust", 90000, NULL, 0}, /* [RFC3119] */ + {G_MAXUINT8, "audio", "parityfec", 0, NULL, 0}, /* [RFC3009] */ + {G_MAXUINT8, "audio", "SMV", 8000, "1", 0}, /* [RFC3558] */ + {G_MAXUINT8, "audio", "SMV0", 8000, "1", 0}, /* [RFC3558] */ + {G_MAXUINT8, "audio", "t140c", 0, NULL, 0}, /* [RFC4351] */ + {G_MAXUINT8, "audio", "t38", 0, NULL, 0}, /* [RFC4612] */ + {G_MAXUINT8, "audio", "telephone-event", 0, NULL, 0}, /* [RFC4733] */ + {G_MAXUINT8, "audio", "tone", 0, NULL, 0}, /* [RFC4733] */ + {G_MAXUINT8, "audio", "DVI4", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "G722", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "G723", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "G728", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "G729", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "GSM", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "L16", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "LPC", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "PCMA", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "audio", "PCMU", 0, NULL, 0}, /* [RFC4856] */ + {G_MAXUINT8, "text", "parityfec", 0, NULL, 0}, /* [RFC3009] */ + {G_MAXUINT8, "text", "red", 1000, NULL, 0}, /* [RFC4102] */ + {G_MAXUINT8, "text", "rtx", 0, NULL, 0}, /* [RFC4588] */ + {G_MAXUINT8, "text", "t140", 1000, NULL, 0}, /* [RFC4103] */ + {G_MAXUINT8, "video", "BMPEG", 90000, NULL, 0}, /* [RFC2343][RFC3555] */ + {G_MAXUINT8, "video", "BT656", 90000, NULL, 0}, /* [RFC2431][RFC3555] */ + {G_MAXUINT8, "video", "DV", 90000, NULL, 0}, /* [RFC3189] */ + {G_MAXUINT8, "video", "H263-1998", 90000, NULL, 0}, /* [RFC2429][RFC3555] */ + {G_MAXUINT8, "video", "H263-2000", 90000, NULL, 0}, /* [RFC2429][RFC3555] */ + {G_MAXUINT8, "video", "MP1S", 90000, NULL, 0}, /* [RFC2250][RFC3555] */ + {G_MAXUINT8, "video", "MP2P", 90000, NULL, 0}, /* [RFC2250][RFC3555] */ + {G_MAXUINT8, "video", "MP4V-ES", 90000, NULL, 0}, /* [RFC3016] */ + {G_MAXUINT8, "video", "parityfec", 0, NULL, 0}, /* [RFC3009] */ + {G_MAXUINT8, "video", "pointer", 90000, NULL, 0}, /* [RFC2862] */ + {G_MAXUINT8, "video", "raw", 90000, NULL, 0}, /* [RFC4175] */ + {G_MAXUINT8, "video", "rtx", 0, NULL, 0}, /* [RFC4588] */ + {G_MAXUINT8, "video", "SMPTE292M", 0, NULL, 0}, /* [RFC3497] */ + {G_MAXUINT8, "video", "vc1", 90000, NULL, 0}, /* [RFC4425] */ + + /* not in http://www.iana.org/assignments/rtp-parameters */ + {G_MAXUINT8, "audio", "AC3", 0, NULL, 0}, + {G_MAXUINT8, "audio", "ILBC", 8000, NULL, 0}, + {G_MAXUINT8, "audio", "MPEG4-GENERIC", 0, NULL, 0}, + {G_MAXUINT8, "audio", "SPEEX", 0, NULL, 0}, + + {G_MAXUINT8, "application", "MPEG4-GENERIC", 0, NULL, 0}, + + {G_MAXUINT8, "video", "H264", 90000, NULL, 0}, + {G_MAXUINT8, "video", "MPEG4-GENERIC", 90000, NULL, 0}, + {G_MAXUINT8, "video", "THEORA", 0, NULL, 0}, + {G_MAXUINT8, "video", "VORBIS", 0, NULL, 0}, + {G_MAXUINT8, "video", "X-SV3V-ES", 90000, NULL, 0}, + {G_MAXUINT8, "video", "X-SORENSON-VIDEO", 90000, NULL, 0}, + + /* real stuff */ + {G_MAXUINT8, "video", "x-pn-realvideo", 1000, NULL, 0}, + {G_MAXUINT8, "audio", "x-pn-realaudio", 1000, NULL, 0}, + {G_MAXUINT8, "application", "x-pn-realmedia", 1000, NULL, 0}, + + /* terminator */ + {G_MAXUINT8, NULL, NULL, 0, NULL, 0} +}; + +/** + * gst_rtp_payload_info_for_pt: + * @payload_type: the payload_type to find + * + * Get the #GstRTPPayloadInfo for @payload_type. This function is + * mostly used to get the default clock-rate and bandwidth for static payload + * types specified with @payload_type. + * + * Returns: a #GstRTPPayloadInfo or NULL when no info could be found. + */ +const GstRTPPayloadInfo * +gst_rtp_payload_info_for_pt (guint8 payload_type) +{ + const GstRTPPayloadInfo *result = NULL; + gint i; + + for (i = 0; info[i].media; i++) { + if (info[i].payload_type == payload_type) { + result = &info[i]; + break; + } + } + return result; +} + +/** + * gst_rtp_payload_info_for_name: + * @media: the media to find + * @encoding_name: the encoding name to find + * + * Get the #GstRTPPayloadInfo for @media and @encoding_name. This function is + * mostly used to get the default clock-rate and bandwidth for dynamic payload + * types specified with @media and @encoding name. + * + * The search for @encoding_name will be performed in a case insensitve way. + * + * Returns: a #GstRTPPayloadInfo or NULL when no info could be found. + */ +const GstRTPPayloadInfo * +gst_rtp_payload_info_for_name (const gchar * media, const gchar * encoding_name) +{ + const GstRTPPayloadInfo *result = NULL; + gint i; + + for (i = 0; info[i].media; i++) { + if (strcmp (media, info[i].media) == 0 + && g_ascii_strcasecmp (encoding_name, info[i].encoding_name) == 0) { + result = &info[i]; + break; + } + } + return result; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.h new file mode 100644 index 0000000..3563468 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtp/gstrtppayloads.h @@ -0,0 +1,193 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * gstrtppayloads.h: various helper functions to deal with RTP payload + * types. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTPPAYLOADS_H__ +#define __GST_RTPPAYLOADS_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstRTPPayload: + * @GST_RTP_PAYLOAD_PCMU: ITU-T G.711. mu-law audio (RFC 3551) + * @GST_RTP_PAYLOAD_1016: RFC 3551 says reserved + * @GST_RTP_PAYLOAD_G721: RFC 3551 says reserved + * @GST_RTP_PAYLOAD_GSM: GSM audio + * @GST_RTP_PAYLOAD_G723: ITU G.723.1 audio + * @GST_RTP_PAYLOAD_DVI4_8000: IMA ADPCM wave type (RFC 3551) + * @GST_RTP_PAYLOAD_DVI4_16000: IMA ADPCM wave type (RFC 3551) + * @GST_RTP_PAYLOAD_LPC: experimental linear predictive encoding + * @GST_RTP_PAYLOAD_PCMA: ITU-T G.711 A-law audio (RFC 3551) + * @GST_RTP_PAYLOAD_G722: ITU-T G.722 (RFC 3551) + * @GST_RTP_PAYLOAD_L16_STEREO: stereo PCM + * @GST_RTP_PAYLOAD_L16_MONO: mono PCM + * @GST_RTP_PAYLOAD_QCELP: EIA & TIA standard IS-733 + * @GST_RTP_PAYLOAD_CN: Comfort Noise (RFC 3389) + * @GST_RTP_PAYLOAD_MPA: Audio MPEG 1-3. + * @GST_RTP_PAYLOAD_G728: ITU-T G.728 Speech coder (RFC 3551) + * @GST_RTP_PAYLOAD_DVI4_11025: IMA ADPCM wave type (RFC 3551) + * @GST_RTP_PAYLOAD_DVI4_22050: IMA ADPCM wave type (RFC 3551) + * @GST_RTP_PAYLOAD_G729: ITU-T G.729 Speech coder (RFC 3551) + * @GST_RTP_PAYLOAD_CELLB: See RFC 2029 + * @GST_RTP_PAYLOAD_JPEG: ISO Standards 10918-1 and 10918-2 (RFC 2435) + * @GST_RTP_PAYLOAD_NV: nv encoding by Ron Frederick + * @GST_RTP_PAYLOAD_H261: ITU-T Recommendation H.261 (RFC 2032) + * @GST_RTP_PAYLOAD_MPV: Video MPEG 1 & 2 (RFC 2250) + * @GST_RTP_PAYLOAD_MP2T: MPEG-2 transport stream (RFC 2250) + * @GST_RTP_PAYLOAD_H263: Video H263 (RFC 2190) + * + * + * Standard predefined fixed payload types. + * + * The official list is at: + * http://www.iana.org/assignments/rtp-parameters + * + * Audio: + * reserved: 19 + * unassigned: 20-23, + * + * Video: + * unassigned: 24, 27, 29, 30, 35-71, 77-95 + * Reserved for RTCP conflict avoidance: 72-76 + */ +typedef enum +{ + /* Audio: */ + GST_RTP_PAYLOAD_PCMU = 0, + GST_RTP_PAYLOAD_1016 = 1, /* RFC 3551 says reserved */ + GST_RTP_PAYLOAD_G721 = 2, /* RFC 3551 says reserved */ + GST_RTP_PAYLOAD_GSM = 3, + GST_RTP_PAYLOAD_G723 = 4, + GST_RTP_PAYLOAD_DVI4_8000 = 5, + GST_RTP_PAYLOAD_DVI4_16000 = 6, + GST_RTP_PAYLOAD_LPC = 7, + GST_RTP_PAYLOAD_PCMA = 8, + GST_RTP_PAYLOAD_G722 = 9, + GST_RTP_PAYLOAD_L16_STEREO = 10, + GST_RTP_PAYLOAD_L16_MONO = 11, + GST_RTP_PAYLOAD_QCELP = 12, + GST_RTP_PAYLOAD_CN = 13, + GST_RTP_PAYLOAD_MPA = 14, + GST_RTP_PAYLOAD_G728 = 15, + GST_RTP_PAYLOAD_DVI4_11025 = 16, + GST_RTP_PAYLOAD_DVI4_22050 = 17, + GST_RTP_PAYLOAD_G729 = 18, + + /* Video: */ + + GST_RTP_PAYLOAD_CELLB = 25, + GST_RTP_PAYLOAD_JPEG = 26, + GST_RTP_PAYLOAD_NV = 28, + GST_RTP_PAYLOAD_H261 = 31, + GST_RTP_PAYLOAD_MPV = 32, + GST_RTP_PAYLOAD_MP2T = 33, + GST_RTP_PAYLOAD_H263 = 34, + + /* BOTH */ +} GstRTPPayload; + +/* backward compatibility */ +#define GST_RTP_PAYLOAD_G723_63 16 +#define GST_RTP_PAYLOAD_G723_53 17 +#define GST_RTP_PAYLOAD_TS48 18 +#define GST_RTP_PAYLOAD_TS41 19 + +#define GST_RTP_PAYLOAD_G723_63_STRING "16" +#define GST_RTP_PAYLOAD_G723_53_STRING "17" +#define GST_RTP_PAYLOAD_TS48_STRING "18" +#define GST_RTP_PAYLOAD_TS41_STRING "19" + +/* Defining the above as strings, to make the declaration of pad_templates + * easier. So if please keep these synchronized with the above. + */ +#define GST_RTP_PAYLOAD_PCMU_STRING "0" +#define GST_RTP_PAYLOAD_1016_STRING "1" +#define GST_RTP_PAYLOAD_G721_STRING "2" +#define GST_RTP_PAYLOAD_GSM_STRING "3" +#define GST_RTP_PAYLOAD_G723_STRING "4" +#define GST_RTP_PAYLOAD_DVI4_8000_STRING "5" +#define GST_RTP_PAYLOAD_DVI4_16000_STRING "6" +#define GST_RTP_PAYLOAD_LPC_STRING "7" +#define GST_RTP_PAYLOAD_PCMA_STRING "8" +#define GST_RTP_PAYLOAD_G722_STRING "9" +#define GST_RTP_PAYLOAD_L16_STEREO_STRING "10" +#define GST_RTP_PAYLOAD_L16_MONO_STRING "11" +#define GST_RTP_PAYLOAD_QCELP_STRING "12" +#define GST_RTP_PAYLOAD_CN_STRING "13" +#define GST_RTP_PAYLOAD_MPA_STRING "14" +#define GST_RTP_PAYLOAD_G728_STRING "15" +#define GST_RTP_PAYLOAD_DVI4_11025_STRING "16" +#define GST_RTP_PAYLOAD_DVI4_22050_STRING "17" +#define GST_RTP_PAYLOAD_G729_STRING "18" + +#define GST_RTP_PAYLOAD_CELLB_STRING "25" +#define GST_RTP_PAYLOAD_JPEG_STRING "26" +#define GST_RTP_PAYLOAD_NV_STRING "28" + +#define GST_RTP_PAYLOAD_H261_STRING "31" +#define GST_RTP_PAYLOAD_MPV_STRING "32" +#define GST_RTP_PAYLOAD_MP2T_STRING "33" +#define GST_RTP_PAYLOAD_H263_STRING "34" + +#define GST_RTP_PAYLOAD_DYNAMIC_STRING "[96, 127]" + +/** + * GST_RTP_PAYLOAD_IS_DYNAMIC: + * @pt: a payload type + * + * Check if @pt is a dynamic payload type. + */ +#define GST_RTP_PAYLOAD_IS_DYNAMIC(pt) ((pt) >= 96 && (pt) <= 127) + +typedef struct _GstRTPPayloadInfo GstRTPPayloadInfo; + +/** + * GstRTPPayloadInfo: + * @payload_type: payload type, -1 means dynamic + * @media: the media type(s), usually "audio", "video", "application", "text", + * "message". + * @encoding_name: the encoding name of @pt + * @clock_rate: default clock rate, 0 = unknown/variable + * @encoding_parameters: encoding parameters. For audio this is the number of + * channels. NULL = not applicable. + * @bitrate: the bitrate of the media. 0 = unknown/variable. + * + * Structure holding default payload type information. + */ +struct _GstRTPPayloadInfo +{ + guint8 payload_type; + const gchar *media; + const gchar *encoding_name; + guint clock_rate; + const gchar *encoding_parameters; + guint bitrate; +}; + +const GstRTPPayloadInfo * gst_rtp_payload_info_for_pt (guint8 payload_type); +const GstRTPPayloadInfo * gst_rtp_payload_info_for_name (const gchar *media, const gchar *encoding_name); + +G_END_DECLS + +#endif /* __GST_RTPPAYLOADS_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/.gitignore new file mode 100644 index 0000000..27308e6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/.gitignore @@ -0,0 +1,4 @@ +gstrtsp-enumtypes.c +gstrtsp-enumtypes.h +gstrtsp-marshal.c +gstrtsp-marshal.h diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/Makefile.am new file mode 100644 index 0000000..bd27a40 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/Makefile.am @@ -0,0 +1,120 @@ +libgstrtspincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/rtsp + +libgstrtspinclude_HEADERS = gstrtspbase64.h \ + gstrtsptransport.h \ + gstrtspurl.h \ + gstrtspmessage.h \ + gstrtspconnection.h \ + gstrtspdefs.h \ + gstrtspextension.h \ + gstrtsprange.h + +#gstrtspextreal.h +#gstrtspextwms.h + +lib_LTLIBRARIES = libgstrtsp-@GST_MAJORMINOR@.la + +built_sources = gstrtsp-marshal.c gstrtsp-enumtypes.c +built_headers = gstrtsp-marshal.h gstrtsp-enumtypes.h + +libgstrtsp_@GST_MAJORMINOR@_la_SOURCES = gstrtspbase64.c \ + gstrtsptransport.c \ + gstrtspurl.c \ + gstrtspmessage.c \ + gstrtspconnection.c \ + gstrtspdefs.c \ + gstrtspextension.c \ + gstrtsprange.c + +nodist_libgstrtsp_@GST_MAJORMINOR@_la_SOURCES = $(built_sources) +nodist_libgstrtspinclude_HEADERS = gstrtsp-enumtypes.h + +noinst_HEADERS = gstrtsp.h + +#gstrtspextwms.c +#rtspextreal.c + +libgstrtsp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtsp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(WIN32_LIBS) $(HSTRERROR_LIBS) +libgstrtsp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +BUILT_SOURCES = $(built_headers) $(built_sources) +EXTRA_DIST = gstrtsp-marshal.list +CLEANFILES = $(BUILT_SOURCES) + +glib_gen_prefix = __gst_rtsp +glib_enum_define = gst_rtsp +glib_enum_headers = gstrtspdefs.h +glib_gen_basename = gstrtsp + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstRtsp-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstrtspinclude_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstrtspinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstrtsp_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstrtsp_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/rtsp/%',$(libgstrtspinclude_HEADERS)) +gir_cincludes+=$(patsubst %,--c-include='gst/rtsp/%',$(nodist_libgstrtspinclude_HEADERS)) + +GstRtsp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstrtsp-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstRtsp \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_builddir)/gst-libs \ + -I$(top_srcdir)/gst-libs \ + --add-include-path=$(builddir)/../sdp \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstrtsp-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstSdp-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-sdp-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-rtsp-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=$(builddir)/../sdp \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstrtsp -:SHARED libgstrtsp-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstrtsp_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstrtsp_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstrtsp_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstrtsp_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstrtsp_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/rtsp \ + -:HEADERS $(libgstrtspinclude_HEADERS) \ + $(nodist_libgstrtspinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp-marshal.list b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp-marshal.list new file mode 100644 index 0000000..40b8c72 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp-marshal.list @@ -0,0 +1,2 @@ +# rtsp marshallers +ENUM:POINTER,POINTER diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp.h new file mode 100644 index 0000000..0632196 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsp.h @@ -0,0 +1,27 @@ +/* GStreamer RTSP extension + * Copyright (C) 2007 Wim Taymans + * + * rtsp.h: Generic include to pull in defs + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __RTSP_H__ +#define __RTSP_H__ + +#include +#include + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.c new file mode 100644 index 0000000..a1064d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.c @@ -0,0 +1,91 @@ +/* GStreamer + * Copyright (C) <2007> Mike Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspbase64 + * @short_description: Helper functions to handle Base64 + * + * Last reviewed on 2007-07-24 (0.10.14) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstrtspbase64.h" + +/** + * gst_rtsp_base64_encode: + * @data: the binary data to encode + * @len: the length of @data + * + * Encode a sequence of binary data into its Base-64 stringified representation. + * + * Deprecated: Use g_base64_encode() + * + * Returns: a newly allocated, zero-terminated Base-64 encoded string + * representing @data. + */ +/* This isn't efficient, but it doesn't need to be */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +gchar *gst_rtsp_base64_encode (const gchar * data, gsize len); +#endif +gchar * +gst_rtsp_base64_encode (const gchar * data, gsize len) +{ + return g_base64_encode ((const guchar *) data, len); +} +#endif + +/** + * gst_rtsp_base64_decode_ip: + * @data: the base64 encoded data + * @len: location for output length or NULL + * + * Decode the base64 string pointed to by @data in-place. When @len is not #NULL + * it will contain the length of the decoded data. + * + * Deprecated: use g_base64_decode_inplace() instead. + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +void gst_rtsp_base64_decode_ip (gchar * data, gsize * len); +#endif +void +gst_rtsp_base64_decode_ip (gchar * data, gsize * len) +{ + gint input_length, output_length, state = 0; + guint save = 0; + + g_return_if_fail (data != NULL); + + input_length = strlen (data); + + g_return_if_fail (input_length > 1); + + output_length = + g_base64_decode_step (data, input_length, (guchar *) data, &state, &save); + + if (len) + *len = output_length; +} +#endif diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.h new file mode 100644 index 0000000..1501c10 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspbase64.h @@ -0,0 +1,37 @@ +/* GStreamer + * Copyright (C) <2007> Mike Smith + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_BASE64_H__ +#define __GST_RTSP_BASE64_H__ + +#include + +G_BEGIN_DECLS + +#ifndef GST_DISABLE_DEPRECATED +gchar *gst_rtsp_base64_encode (const gchar *data, gsize len); +#endif + +#ifndef GST_DISABLE_DEPRECATED +void gst_rtsp_base64_decode_ip (gchar *data, gsize *len); +#endif + +G_END_DECLS + +#endif /* __GST_RTSP_BASE64_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.c new file mode 100644 index 0000000..0c1f22b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.c @@ -0,0 +1,3668 @@ +/* GStreamer + * Copyright (C) <2005-2009> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspconnection + * @short_description: manage RTSP connections + * @see_also: gstrtspurl + * + * This object manages the RTSP connection to the server. It provides function + * to receive and send bytes and messages. + * + * Last reviewed on 2007-07-24 (0.10.14) + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +/* we include this here to get the G_OS_* defines */ +#include +#include + +#ifdef G_OS_WIN32 +/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later. + * minwg32 headers check WINVER before allowing the use of these */ +#ifndef WINVER +#define WINVER 0x0501 +#endif +#include +#include +#define EINPROGRESS WSAEINPROGRESS +#else +#include +#include +#include +#include +#include +#endif + +#ifdef HAVE_FIONREAD_IN_SYS_FILIO +#include +#endif + +#include "gstrtspconnection.h" +#include "gstrtspbase64.h" + +union gst_sockaddr +{ + struct sockaddr sa; + struct sockaddr_in sa_in; + struct sockaddr_in6 sa_in6; + struct sockaddr_storage sa_stor; +}; + +typedef struct +{ + gint state; + guint save; + guchar out[3]; /* the size must be evenly divisible by 3 */ + guint cout; + guint coutl; +} DecodeCtx; + +#ifdef MSG_NOSIGNAL +#define SEND_FLAGS MSG_NOSIGNAL +#else +#define SEND_FLAGS 0 +#endif + +#ifdef G_OS_WIN32 +#define READ_SOCKET(fd, buf, len) recv (fd, (char *)buf, len, 0) +#define WRITE_SOCKET(fd, buf, len) send (fd, (const char *)buf, len, SEND_FLAGS) +#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, (const char *)val, len) +#define CLOSE_SOCKET(sock) closesocket (sock) +#define ERRNO_IS_EAGAIN (WSAGetLastError () == WSAEWOULDBLOCK) +#define ERRNO_IS_EINTR (WSAGetLastError () == WSAEINTR) +/* According to Microsoft's connect() documentation this one returns + * WSAEWOULDBLOCK and not WSAEINPROGRESS. */ +#define ERRNO_IS_EINPROGRESS (WSAGetLastError () == WSAEWOULDBLOCK) +#else +#define READ_SOCKET(fd, buf, len) read (fd, buf, len) +#define WRITE_SOCKET(fd, buf, len) send (fd, buf, len, SEND_FLAGS) +#define SETSOCKOPT(sock, level, name, val, len) setsockopt (sock, level, name, val, len) +#define CLOSE_SOCKET(sock) close (sock) +#define ERRNO_IS_EAGAIN (errno == EAGAIN) +#define ERRNO_IS_EINTR (errno == EINTR) +#define ERRNO_IS_EINPROGRESS (errno == EINPROGRESS) +#endif + +#define ADD_POLLFD(fdset, pfd, fd) \ +G_STMT_START { \ + (pfd)->fd = fd; \ + gst_poll_add_fd (fdset, pfd); \ +} G_STMT_END + +#define REMOVE_POLLFD(fdset, pfd) \ +G_STMT_START { \ + if ((pfd)->fd != -1) { \ + GST_DEBUG ("remove fd %d", (pfd)->fd); \ + gst_poll_remove_fd (fdset, pfd); \ + CLOSE_SOCKET ((pfd)->fd); \ + (pfd)->fd = -1; \ + } \ +} G_STMT_END + +typedef enum +{ + TUNNEL_STATE_NONE, + TUNNEL_STATE_GET, + TUNNEL_STATE_POST, + TUNNEL_STATE_COMPLETE +} GstRTSPTunnelState; + +#define TUNNELID_LEN 24 + +struct _GstRTSPConnection +{ + /*< private > */ + /* URL for the connection */ + GstRTSPUrl *url; + + /* connection state */ + GstPollFD fd0; + GstPollFD fd1; + + GstPollFD *readfd; + GstPollFD *writefd; + + gboolean manual_http; + + gchar tunnelid[TUNNELID_LEN]; + gboolean tunneled; + GstRTSPTunnelState tstate; + + GstPoll *fdset; + gchar *ip; + + gint read_ahead; + + gchar *initial_buffer; + gsize initial_buffer_offset; + + /* Session state */ + gint cseq; /* sequence number */ + gchar session_id[512]; /* session id */ + gint timeout; /* session timeout in seconds */ + GTimer *timer; /* timeout timer */ + + /* Authentication */ + GstRTSPAuthMethod auth_method; + gchar *username; + gchar *passwd; + GHashTable *auth_params; + + DecodeCtx ctx; + DecodeCtx *ctxp; + + gchar *proxy_host; + guint proxy_port; +}; + +enum +{ + STATE_START = 0, + STATE_DATA_HEADER, + STATE_DATA_BODY, + STATE_READ_LINES, + STATE_END, + STATE_LAST +}; + +enum +{ + READ_AHEAD_EOH = -1, /* end of headers */ + READ_AHEAD_CRLF = -2, + READ_AHEAD_CRLFCR = -3 +}; + +/* a structure for constructing RTSPMessages */ +typedef struct +{ + gint state; + GstRTSPResult status; + guint8 buffer[4096]; + guint offset; + + guint line; + guint8 *body_data; + glong body_len; +} GstRTSPBuilder; + +static void +build_reset (GstRTSPBuilder * builder) +{ + g_free (builder->body_data); + memset (builder, 0, sizeof (GstRTSPBuilder)); +} + +/** + * gst_rtsp_connection_create: + * @url: a #GstRTSPUrl + * @conn: storage for a #GstRTSPConnection + * + * Create a newly allocated #GstRTSPConnection from @url and store it in @conn. + * The connection will not yet attempt to connect to @url, use + * gst_rtsp_connection_connect(). + * + * A copy of @url will be made. + * + * Returns: #GST_RTSP_OK when @conn contains a valid connection. + */ +GstRTSPResult +gst_rtsp_connection_create (const GstRTSPUrl * url, GstRTSPConnection ** conn) +{ + GstRTSPConnection *newconn; +#ifdef G_OS_WIN32 + WSADATA w; + int error; +#endif + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + +#ifdef G_OS_WIN32 + error = WSAStartup (0x0202, &w); + + if (error) + goto startup_error; + + if (w.wVersion != 0x0202) + goto version_error; +#endif + + newconn = g_new0 (GstRTSPConnection, 1); + + if ((newconn->fdset = gst_poll_new (TRUE)) == NULL) + goto no_fdset; + + newconn->url = gst_rtsp_url_copy (url); + newconn->fd0.fd = -1; + newconn->fd1.fd = -1; + newconn->timer = g_timer_new (); + newconn->timeout = 60; + newconn->cseq = 1; + + newconn->auth_method = GST_RTSP_AUTH_NONE; + newconn->username = NULL; + newconn->passwd = NULL; + newconn->auth_params = NULL; + + *conn = newconn; + + return GST_RTSP_OK; + + /* ERRORS */ +#ifdef G_OS_WIN32 +startup_error: + { + g_warning ("Error %d on WSAStartup", error); + return GST_RTSP_EWSASTART; + } +version_error: + { + g_warning ("Windows sockets are not version 0x202 (current 0x%x)", + w.wVersion); + WSACleanup (); + return GST_RTSP_EWSAVERSION; + } +#endif +no_fdset: + { + g_free (newconn); +#ifdef G_OS_WIN32 + WSACleanup (); +#endif + return GST_RTSP_ESYS; + } +} + +/** + * gst_rtsp_connection_create_from_fd: + * @fd: a file descriptor + * @ip: the IP address of the other end + * @port: the port used by the other end + * @initial_buffer: data already read from @fd + * @conn: storage for a #GstRTSPConnection + * + * Create a new #GstRTSPConnection for handling communication on the existing + * file descriptor @fd. The @initial_buffer contains any data already read from + * @fd which should be used before starting to read new data. + * + * Returns: #GST_RTSP_OK when @conn contains a valid connection. + * + * Since: 0.10.25 + */ +GstRTSPResult +gst_rtsp_connection_create_from_fd (gint fd, const gchar * ip, guint16 port, + const gchar * initial_buffer, GstRTSPConnection ** conn) +{ + GstRTSPConnection *newconn = NULL; + GstRTSPUrl *url; +#ifdef G_OS_WIN32 + gulong flags = 1; +#endif + GstRTSPResult res; + + g_return_val_if_fail (fd >= 0, GST_RTSP_EINVAL); + g_return_val_if_fail (ip != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + /* set to non-blocking mode so that we can cancel the communication */ +#ifndef G_OS_WIN32 + fcntl (fd, F_SETFL, O_NONBLOCK); +#else + ioctlsocket (fd, FIONBIO, &flags); +#endif /* G_OS_WIN32 */ + + /* create a url for the client address */ + url = g_new0 (GstRTSPUrl, 1); + url->host = g_strdup (ip); + url->port = port; + + /* now create the connection object */ + GST_RTSP_CHECK (gst_rtsp_connection_create (url, &newconn), newconn_failed); + gst_rtsp_url_free (url); + + ADD_POLLFD (newconn->fdset, &newconn->fd0, fd); + + /* both read and write initially */ + newconn->readfd = &newconn->fd0; + newconn->writefd = &newconn->fd0; + + newconn->ip = g_strdup (ip); + + newconn->initial_buffer = g_strdup (initial_buffer); + + *conn = newconn; + + return GST_RTSP_OK; + + /* ERRORS */ +newconn_failed: + { + gst_rtsp_url_free (url); + return res; + } +} + +/** + * gst_rtsp_connection_accept: + * @sock: a socket + * @conn: storage for a #GstRTSPConnection + * + * Accept a new connection on @sock and create a new #GstRTSPConnection for + * handling communication on new socket. + * + * Returns: #GST_RTSP_OK when @conn contains a valid connection. + * + * Since: 0.10.23 + */ +GstRTSPResult +gst_rtsp_connection_accept (gint sock, GstRTSPConnection ** conn) +{ + int fd; + union gst_sockaddr sa; + socklen_t slen = sizeof (sa); + gchar ip[INET6_ADDRSTRLEN]; + guint16 port; + + g_return_val_if_fail (sock >= 0, GST_RTSP_EINVAL); + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + memset (&sa, 0, slen); + +#ifndef G_OS_WIN32 + fd = accept (sock, &sa.sa, &slen); +#else + fd = accept (sock, &sa.sa, (gint *) & slen); +#endif /* G_OS_WIN32 */ + if (fd == -1) + goto accept_failed; + + if (getnameinfo (&sa.sa, slen, ip, sizeof (ip), NULL, 0, NI_NUMERICHOST) != 0) + goto getnameinfo_failed; + + if (sa.sa.sa_family == AF_INET) + port = sa.sa_in.sin_port; + else if (sa.sa.sa_family == AF_INET6) + port = sa.sa_in6.sin6_port; + else + goto wrong_family; + + return gst_rtsp_connection_create_from_fd (fd, ip, port, NULL, conn); + + /* ERRORS */ +accept_failed: + { + return GST_RTSP_ESYS; + } +getnameinfo_failed: +wrong_family: + { + CLOSE_SOCKET (fd); + return GST_RTSP_ERROR; + } +} + +static gchar * +do_resolve (const gchar * host) +{ + static gchar ip[INET6_ADDRSTRLEN]; + struct addrinfo *aires, hints; + struct addrinfo *ai; + gint aierr; + + memset (&hints, 0, sizeof (struct addrinfo)); + hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ + hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */ + hints.ai_flags = AI_PASSIVE; /* For wildcard IP address */ + hints.ai_protocol = 0; /* Any protocol */ + hints.ai_canonname = NULL; + hints.ai_addr = NULL; + hints.ai_next = NULL; + + aierr = getaddrinfo (host, NULL, &hints, &aires); + if (aierr != 0) + goto no_addrinfo; + + for (ai = aires; ai; ai = ai->ai_next) { + if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { + break; + } + } + if (ai == NULL) + goto no_family; + + aierr = getnameinfo (ai->ai_addr, ai->ai_addrlen, ip, sizeof (ip), NULL, 0, + NI_NUMERICHOST | NI_NUMERICSERV); + if (aierr != 0) + goto no_address; + + freeaddrinfo (aires); + + return g_strdup (ip); + + /* ERRORS */ +no_addrinfo: + { + GST_ERROR ("no addrinfo found for %s: %s", host, gai_strerror (aierr)); + return NULL; + } +no_family: + { + GST_ERROR ("no family found for %s", host); + freeaddrinfo (aires); + return NULL; + } +no_address: + { + GST_ERROR ("no address found for %s: %s", host, gai_strerror (aierr)); + freeaddrinfo (aires); + return NULL; + } +} + +static GstRTSPResult +do_connect (const gchar * ip, guint16 port, GstPollFD * fdout, + GstPoll * fdset, GTimeVal * timeout) +{ + gint fd; + struct addrinfo hints; + struct addrinfo *aires; + struct addrinfo *ai; + gint aierr; + gchar service[NI_MAXSERV]; + gint ret; +#ifdef G_OS_WIN32 + unsigned long flags = 1; +#endif /* G_OS_WIN32 */ + GstClockTime to; + gint retval; + + memset (&hints, 0, sizeof hints); + hints.ai_flags = AI_NUMERICHOST; + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + g_snprintf (service, sizeof (service) - 1, "%hu", port); + service[sizeof (service) - 1] = '\0'; + + aierr = getaddrinfo (ip, service, &hints, &aires); + if (aierr != 0) + goto no_addrinfo; + + for (ai = aires; ai; ai = ai->ai_next) { + if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6) { + break; + } + } + if (ai == NULL) + goto no_family; + + fd = socket (ai->ai_family, SOCK_STREAM, 0); + if (fd == -1) + goto no_socket; + + /* set to non-blocking mode so that we can cancel the connect */ +#ifndef G_OS_WIN32 + fcntl (fd, F_SETFL, O_NONBLOCK); +#else + ioctlsocket (fd, FIONBIO, &flags); +#endif /* G_OS_WIN32 */ + + /* add the socket to our fdset */ + ADD_POLLFD (fdset, fdout, fd); + + /* we are going to connect ASYNC now */ + ret = connect (fd, ai->ai_addr, ai->ai_addrlen); + if (ret == 0) + goto done; + if (!ERRNO_IS_EINPROGRESS) + goto sys_error; + + /* wait for connect to complete up to the specified timeout or until we got + * interrupted. */ + gst_poll_fd_ctl_write (fdset, fdout, TRUE); + + to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; + + do { + retval = gst_poll_wait (fdset, to); + } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + + if (retval == 0) + goto timeout; + else if (retval == -1) + goto sys_error; + + /* we can still have an error connecting on windows */ + if (gst_poll_fd_has_error (fdset, fdout)) { + socklen_t len = sizeof (errno); +#ifndef G_OS_WIN32 + getsockopt (fd, SOL_SOCKET, SO_ERROR, &errno, &len); +#else + getsockopt (fd, SOL_SOCKET, SO_ERROR, (char *) &errno, &len); +#endif + goto sys_error; + } + + gst_poll_fd_ignored (fdset, fdout); + +done: + freeaddrinfo (aires); + + return GST_RTSP_OK; + + /* ERRORS */ +no_addrinfo: + { + GST_ERROR ("no addrinfo found for %s: %s", ip, gai_strerror (aierr)); + return GST_RTSP_ERROR; + } +no_family: + { + GST_ERROR ("no family found for %s", ip); + freeaddrinfo (aires); + return GST_RTSP_ERROR; + } +no_socket: + { + GST_ERROR ("no socket %d (%s)", errno, g_strerror (errno)); + freeaddrinfo (aires); + return GST_RTSP_ESYS; + } +sys_error: + { + GST_ERROR ("system error %d (%s)", errno, g_strerror (errno)); + REMOVE_POLLFD (fdset, fdout); + freeaddrinfo (aires); + return GST_RTSP_ESYS; + } +timeout: + { + GST_ERROR ("timeout"); + REMOVE_POLLFD (fdset, fdout); + freeaddrinfo (aires); + return GST_RTSP_ETIMEOUT; + } +} + +static GstRTSPResult +setup_tunneling (GstRTSPConnection * conn, GTimeVal * timeout) +{ + gint i; + GstRTSPResult res; + gchar *ip; + gchar *uri; + gchar *value; + guint16 port, url_port; + GstRTSPUrl *url; + gchar *hostparam; + GstRTSPMessage *msg; + GstRTSPMessage response; + gboolean old_http; + + memset (&response, 0, sizeof (response)); + gst_rtsp_message_init (&response); + + /* create a random sessionid */ + for (i = 0; i < TUNNELID_LEN; i++) + conn->tunnelid[i] = g_random_int_range ('a', 'z'); + conn->tunnelid[TUNNELID_LEN - 1] = '\0'; + + url = conn->url; + /* get the port from the url */ + gst_rtsp_url_get_port (url, &url_port); + + if (conn->proxy_host) { + uri = g_strdup_printf ("http://%s:%d%s%s%s", url->host, url_port, + url->abspath, url->query ? "?" : "", url->query ? url->query : ""); + hostparam = g_strdup_printf ("%s:%d", url->host, url_port); + ip = conn->proxy_host; + port = conn->proxy_port; + } else { + uri = g_strdup_printf ("%s%s%s", url->abspath, url->query ? "?" : "", + url->query ? url->query : ""); + hostparam = NULL; + ip = conn->ip; + port = url_port; + } + + /* create the GET request for the read connection */ + GST_RTSP_CHECK (gst_rtsp_message_new_request (&msg, GST_RTSP_GET, uri), + no_message); + msg->type = GST_RTSP_MESSAGE_HTTP_REQUEST; + + if (hostparam != NULL) + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_HOST, hostparam); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_X_SESSIONCOOKIE, + conn->tunnelid); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_ACCEPT, + "application/x-rtsp-tunnelled"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CACHE_CONTROL, "no-cache"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_PRAGMA, "no-cache"); + + /* we start by writing to this fd */ + conn->writefd = &conn->fd0; + + /* we need to temporarily set conn->tunneled to FALSE to prevent the HTTP + * request from being base64 encoded */ + conn->tunneled = FALSE; + GST_RTSP_CHECK (gst_rtsp_connection_send (conn, msg, timeout), write_failed); + gst_rtsp_message_free (msg); + conn->tunneled = TRUE; + + /* receive the response to the GET request */ + /* we need to temporarily set manual_http to TRUE since + * gst_rtsp_connection_receive() will treat the HTTP response as a parsing + * failure otherwise */ + old_http = conn->manual_http; + conn->manual_http = TRUE; + GST_RTSP_CHECK (gst_rtsp_connection_receive (conn, &response, timeout), + read_failed); + conn->manual_http = old_http; + + if (response.type != GST_RTSP_MESSAGE_HTTP_RESPONSE || + response.type_data.response.code != GST_RTSP_STS_OK) + goto wrong_result; + + if (gst_rtsp_message_get_header (&response, GST_RTSP_HDR_X_SERVER_IP_ADDRESS, + &value, 0) == GST_RTSP_OK) { + if (conn->proxy_host) { + /* if we use a proxy we need to change the destination url */ + g_free (url->host); + url->host = g_strdup (value); + g_free (hostparam); + hostparam = g_strdup_printf ("%s:%d", url->host, url_port); + } else { + /* and resolve the new ip address */ + if (!(ip = do_resolve (value))) + goto not_resolved; + g_free (conn->ip); + conn->ip = ip; + } + } + + /* connect to the host/port */ + res = do_connect (ip, port, &conn->fd1, conn->fdset, timeout); + if (res != GST_RTSP_OK) + goto connect_failed; + + /* this is now our writing socket */ + conn->writefd = &conn->fd1; + + /* create the POST request for the write connection */ + GST_RTSP_CHECK (gst_rtsp_message_new_request (&msg, GST_RTSP_POST, uri), + no_message); + msg->type = GST_RTSP_MESSAGE_HTTP_REQUEST; + + if (hostparam != NULL) + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_HOST, hostparam); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_X_SESSIONCOOKIE, + conn->tunnelid); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_ACCEPT, + "application/x-rtsp-tunnelled"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CACHE_CONTROL, "no-cache"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_PRAGMA, "no-cache"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_EXPIRES, + "Sun, 9 Jan 1972 00:00:00 GMT"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONTENT_LENGTH, "32767"); + + /* we need to temporarily set conn->tunneled to FALSE to prevent the HTTP + * request from being base64 encoded */ + conn->tunneled = FALSE; + GST_RTSP_CHECK (gst_rtsp_connection_send (conn, msg, timeout), write_failed); + gst_rtsp_message_free (msg); + conn->tunneled = TRUE; + +exit: + gst_rtsp_message_unset (&response); + g_free (hostparam); + g_free (uri); + + return res; + + /* ERRORS */ +no_message: + { + GST_ERROR ("failed to create request (%d)", res); + goto exit; + } +write_failed: + { + GST_ERROR ("write failed (%d)", res); + gst_rtsp_message_free (msg); + conn->tunneled = TRUE; + goto exit; + } +read_failed: + { + GST_ERROR ("read failed (%d)", res); + conn->manual_http = FALSE; + goto exit; + } +wrong_result: + { + GST_ERROR ("got failure response %d %s", response.type_data.response.code, + response.type_data.response.reason); + res = GST_RTSP_ERROR; + goto exit; + } +not_resolved: + { + GST_ERROR ("could not resolve %s", conn->ip); + res = GST_RTSP_ENET; + goto exit; + } +connect_failed: + { + GST_ERROR ("failed to connect"); + goto exit; + } +} + +/** + * gst_rtsp_connection_connect: + * @conn: a #GstRTSPConnection + * @timeout: a #GTimeVal timeout + * + * Attempt to connect to the url of @conn made with + * gst_rtsp_connection_create(). If @timeout is #NULL this function can block + * forever. If @timeout contains a valid timeout, this function will return + * #GST_RTSP_ETIMEOUT after the timeout expired. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK when a connection could be made. + */ +GstRTSPResult +gst_rtsp_connection_connect (GstRTSPConnection * conn, GTimeVal * timeout) +{ + GstRTSPResult res; + gchar *ip; + guint16 port; + GstRTSPUrl *url; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->url != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->fd0.fd < 0, GST_RTSP_EINVAL); + + url = conn->url; + + if (conn->proxy_host && conn->tunneled) { + if (!(ip = do_resolve (conn->proxy_host))) { + GST_ERROR ("could not resolve %s", conn->proxy_host); + goto not_resolved; + } + port = conn->proxy_port; + g_free (conn->proxy_host); + conn->proxy_host = ip; + } else { + if (!(ip = do_resolve (url->host))) { + GST_ERROR ("could not resolve %s", url->host); + goto not_resolved; + } + /* get the port from the url */ + gst_rtsp_url_get_port (url, &port); + + g_free (conn->ip); + conn->ip = ip; + } + + /* connect to the host/port */ + res = do_connect (ip, port, &conn->fd0, conn->fdset, timeout); + if (res != GST_RTSP_OK) + goto connect_failed; + + /* this is our read URL */ + conn->readfd = &conn->fd0; + + if (conn->tunneled) { + res = setup_tunneling (conn, timeout); + if (res != GST_RTSP_OK) + goto tunneling_failed; + } else { + conn->writefd = &conn->fd0; + } + + return GST_RTSP_OK; + +not_resolved: + { + return GST_RTSP_ENET; + } +connect_failed: + { + GST_ERROR ("failed to connect"); + return res; + } +tunneling_failed: + { + GST_ERROR ("failed to setup tunneling"); + return res; + } +} + +static void +auth_digest_compute_hex_urp (const gchar * username, + const gchar * realm, const gchar * password, gchar hex_urp[33]) +{ + GChecksum *md5_context = g_checksum_new (G_CHECKSUM_MD5); + const gchar *digest_string; + + g_checksum_update (md5_context, (const guchar *) username, strlen (username)); + g_checksum_update (md5_context, (const guchar *) ":", 1); + g_checksum_update (md5_context, (const guchar *) realm, strlen (realm)); + g_checksum_update (md5_context, (const guchar *) ":", 1); + g_checksum_update (md5_context, (const guchar *) password, strlen (password)); + digest_string = g_checksum_get_string (md5_context); + + memset (hex_urp, 0, 33); + memcpy (hex_urp, digest_string, strlen (digest_string)); + + g_checksum_free (md5_context); +} + +static void +auth_digest_compute_response (const gchar * method, + const gchar * uri, const gchar * hex_a1, const gchar * nonce, + gchar response[33]) +{ + char hex_a2[33] = { 0, }; + GChecksum *md5_context = g_checksum_new (G_CHECKSUM_MD5); + const gchar *digest_string; + + /* compute A2 */ + g_checksum_update (md5_context, (const guchar *) method, strlen (method)); + g_checksum_update (md5_context, (const guchar *) ":", 1); + g_checksum_update (md5_context, (const guchar *) uri, strlen (uri)); + digest_string = g_checksum_get_string (md5_context); + memcpy (hex_a2, digest_string, strlen (digest_string)); + + /* compute KD */ + g_checksum_reset (md5_context); + g_checksum_update (md5_context, (const guchar *) hex_a1, strlen (hex_a1)); + g_checksum_update (md5_context, (const guchar *) ":", 1); + g_checksum_update (md5_context, (const guchar *) nonce, strlen (nonce)); + g_checksum_update (md5_context, (const guchar *) ":", 1); + + g_checksum_update (md5_context, (const guchar *) hex_a2, 32); + digest_string = g_checksum_get_string (md5_context); + memset (response, 0, 33); + memcpy (response, digest_string, strlen (digest_string)); + + g_checksum_free (md5_context); +} + +static void +add_auth_header (GstRTSPConnection * conn, GstRTSPMessage * message) +{ + switch (conn->auth_method) { + case GST_RTSP_AUTH_BASIC:{ + gchar *user_pass; + gchar *user_pass64; + gchar *auth_string; + + if (conn->username == NULL || conn->passwd == NULL) + break; + + user_pass = g_strdup_printf ("%s:%s", conn->username, conn->passwd); + user_pass64 = g_base64_encode ((guchar *) user_pass, strlen (user_pass)); + auth_string = g_strdup_printf ("Basic %s", user_pass64); + + gst_rtsp_message_take_header (message, GST_RTSP_HDR_AUTHORIZATION, + auth_string); + + g_free (user_pass); + g_free (user_pass64); + break; + } + case GST_RTSP_AUTH_DIGEST:{ + gchar response[33], hex_urp[33]; + gchar *auth_string, *auth_string2; + gchar *realm; + gchar *nonce; + gchar *opaque; + const gchar *uri; + const gchar *method; + + /* we need to have some params set */ + if (conn->auth_params == NULL || conn->username == NULL || + conn->passwd == NULL) + break; + + /* we need the realm and nonce */ + realm = (gchar *) g_hash_table_lookup (conn->auth_params, "realm"); + nonce = (gchar *) g_hash_table_lookup (conn->auth_params, "nonce"); + if (realm == NULL || nonce == NULL) + break; + + auth_digest_compute_hex_urp (conn->username, realm, conn->passwd, + hex_urp); + + method = gst_rtsp_method_as_text (message->type_data.request.method); + uri = message->type_data.request.uri; + + /* Assume no qop, algorithm=md5, stale=false */ + /* For algorithm MD5, a1 = urp. */ + auth_digest_compute_response (method, uri, hex_urp, nonce, response); + auth_string = g_strdup_printf ("Digest username=\"%s\", " + "realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", + conn->username, realm, nonce, uri, response); + + opaque = (gchar *) g_hash_table_lookup (conn->auth_params, "opaque"); + if (opaque) { + auth_string2 = g_strdup_printf ("%s, opaque=\"%s\"", auth_string, + opaque); + g_free (auth_string); + auth_string = auth_string2; + } + gst_rtsp_message_take_header (message, GST_RTSP_HDR_AUTHORIZATION, + auth_string); + break; + } + default: + /* Nothing to do */ + break; + } +} + +static void +gen_date_string (gchar * date_string, guint len) +{ + static const char wkdays[7][4] = + { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; + static const char months[12][4] = + { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", + "Nov", "Dec" + }; + struct tm tm; + time_t t; + + time (&t); + +#ifdef HAVE_GMTIME_R + gmtime_r (&t, &tm); +#else + tm = *gmtime (&t); +#endif + + g_snprintf (date_string, len, "%s, %02d %s %04d %02d:%02d:%02d GMT", + wkdays[tm.tm_wday], tm.tm_mday, months[tm.tm_mon], tm.tm_year + 1900, + tm.tm_hour, tm.tm_min, tm.tm_sec); +} + +static GstRTSPResult +write_bytes (gint fd, const guint8 * buffer, guint * idx, guint size) +{ + guint left; + + if (G_UNLIKELY (*idx > size)) + return GST_RTSP_ERROR; + + left = size - *idx; + + while (left) { + gint r; + + r = WRITE_SOCKET (fd, &buffer[*idx], left); + if (G_UNLIKELY (r == 0)) { + return GST_RTSP_EINTR; + } else if (G_UNLIKELY (r < 0)) { + if (ERRNO_IS_EAGAIN) + return GST_RTSP_EINTR; + if (!ERRNO_IS_EINTR) + return GST_RTSP_ESYS; + } else { + left -= r; + *idx += r; + } + } + return GST_RTSP_OK; +} + +static gint +fill_raw_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) +{ + gint out = 0; + + if (G_UNLIKELY (conn->initial_buffer != NULL)) { + gsize left = strlen (&conn->initial_buffer[conn->initial_buffer_offset]); + + out = MIN (left, size); + memcpy (buffer, &conn->initial_buffer[conn->initial_buffer_offset], out); + + if (left == (gsize) out) { + g_free (conn->initial_buffer); + conn->initial_buffer = NULL; + conn->initial_buffer_offset = 0; + } else + conn->initial_buffer_offset += out; + } + + if (G_LIKELY (size > (guint) out)) { + gint r; + + r = READ_SOCKET (conn->readfd->fd, &buffer[out], size - out); + if (r <= 0) { + if (out == 0) + out = r; + } else + out += r; + } + + return out; +} + +static gint +fill_bytes (GstRTSPConnection * conn, guint8 * buffer, guint size) +{ + DecodeCtx *ctx = conn->ctxp; + gint out = 0; + + if (ctx) { + while (size > 0) { + guint8 in[sizeof (ctx->out) * 4 / 3]; + gint r; + + while (size > 0 && ctx->cout < ctx->coutl) { + /* we have some leftover bytes */ + *buffer++ = ctx->out[ctx->cout++]; + size--; + out++; + } + + /* got what we needed? */ + if (size == 0) + break; + + /* try to read more bytes */ + r = fill_raw_bytes (conn, in, sizeof (in)); + if (r <= 0) { + if (out == 0) + out = r; + break; + } + + ctx->cout = 0; + ctx->coutl = + g_base64_decode_step ((gchar *) in, r, ctx->out, &ctx->state, + &ctx->save); + } + } else { + out = fill_raw_bytes (conn, buffer, size); + } + + return out; +} + +static GstRTSPResult +read_bytes (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) +{ + guint left; + + if (G_UNLIKELY (*idx > size)) + return GST_RTSP_ERROR; + + left = size - *idx; + + while (left) { + gint r; + + r = fill_bytes (conn, &buffer[*idx], left); + if (G_UNLIKELY (r == 0)) { + return GST_RTSP_EEOF; + } else if (G_UNLIKELY (r < 0)) { + if (ERRNO_IS_EAGAIN) + return GST_RTSP_EINTR; + if (!ERRNO_IS_EINTR) + return GST_RTSP_ESYS; + } else { + left -= r; + *idx += r; + } + } + return GST_RTSP_OK; +} + +/* The code below tries to handle clients using \r, \n or \r\n to indicate the + * end of a line. It even does its best to handle clients which mix them (even + * though this is a really stupid idea (tm).) It also handles Line White Space + * (LWS), where a line end followed by whitespace is considered LWS. This is + * the method used in RTSP (and HTTP) to break long lines. + */ +static GstRTSPResult +read_line (GstRTSPConnection * conn, guint8 * buffer, guint * idx, guint size) +{ + while (TRUE) { + guint8 c; + gint r; + + if (conn->read_ahead == READ_AHEAD_EOH) { + /* the last call to read_line() already determined that we have reached + * the end of the headers, so convey that information now */ + conn->read_ahead = 0; + break; + } else if (conn->read_ahead == READ_AHEAD_CRLF) { + /* the last call to read_line() left off after having read \r\n */ + c = '\n'; + } else if (conn->read_ahead == READ_AHEAD_CRLFCR) { + /* the last call to read_line() left off after having read \r\n\r */ + c = '\r'; + } else if (conn->read_ahead != 0) { + /* the last call to read_line() left us with a character to start with */ + c = (guint8) conn->read_ahead; + conn->read_ahead = 0; + } else { + /* read the next character */ + r = fill_bytes (conn, &c, 1); + if (G_UNLIKELY (r == 0)) { + return GST_RTSP_EEOF; + } else if (G_UNLIKELY (r < 0)) { + if (ERRNO_IS_EAGAIN) + return GST_RTSP_EINTR; + if (!ERRNO_IS_EINTR) + return GST_RTSP_ESYS; + continue; + } + } + + /* special treatment of line endings */ + if (c == '\r' || c == '\n') { + guint8 read_ahead; + + retry: + /* need to read ahead one more character to know what to do... */ + r = fill_bytes (conn, &read_ahead, 1); + if (G_UNLIKELY (r == 0)) { + return GST_RTSP_EEOF; + } else if (G_UNLIKELY (r < 0)) { + if (ERRNO_IS_EAGAIN) { + /* remember the original character we read and try again next time */ + if (conn->read_ahead == 0) + conn->read_ahead = c; + return GST_RTSP_EINTR; + } + if (!ERRNO_IS_EINTR) + return GST_RTSP_ESYS; + goto retry; + } + + if (read_ahead == ' ' || read_ahead == '\t') { + if (conn->read_ahead == READ_AHEAD_CRLFCR) { + /* got \r\n\r followed by whitespace, treat it as a normal line + * followed by one starting with LWS */ + conn->read_ahead = read_ahead; + break; + } else { + /* got LWS, change the line ending to a space and continue */ + c = ' '; + conn->read_ahead = read_ahead; + } + } else if (conn->read_ahead == READ_AHEAD_CRLFCR) { + if (read_ahead == '\r' || read_ahead == '\n') { + /* got \r\n\r\r or \r\n\r\n, treat it as the end of the headers */ + conn->read_ahead = READ_AHEAD_EOH; + break; + } else { + /* got \r\n\r followed by something else, this is not really + * supported since we have probably just eaten the first character + * of the body or the next message, so just ignore the second \r + * and live with it... */ + conn->read_ahead = read_ahead; + break; + } + } else if (conn->read_ahead == READ_AHEAD_CRLF) { + if (read_ahead == '\r') { + /* got \r\n\r so far, need one more character... */ + conn->read_ahead = READ_AHEAD_CRLFCR; + goto retry; + } else if (read_ahead == '\n') { + /* got \r\n\n, treat it as the end of the headers */ + conn->read_ahead = READ_AHEAD_EOH; + break; + } else { + /* found the end of a line, keep read_ahead for the next line */ + conn->read_ahead = read_ahead; + break; + } + } else if (c == read_ahead) { + /* got double \r or \n, treat it as the end of the headers */ + conn->read_ahead = READ_AHEAD_EOH; + break; + } else if (c == '\r' && read_ahead == '\n') { + /* got \r\n so far, still need more to know what to do... */ + conn->read_ahead = READ_AHEAD_CRLF; + goto retry; + } else { + /* found the end of a line, keep read_ahead for the next line */ + conn->read_ahead = read_ahead; + break; + } + } + + if (G_LIKELY (*idx < size - 1)) + buffer[(*idx)++] = c; + } + buffer[*idx] = '\0'; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_write: + * @conn: a #GstRTSPConnection + * @data: the data to write + * @size: the size of @data + * @timeout: a timeout value or #NULL + * + * Attempt to write @size bytes of @data to the connected @conn, blocking up to + * the specified @timeout. @timeout can be #NULL, in which case this function + * might block forever. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, + guint size, GTimeVal * timeout) +{ + guint offset; + gint retval; + GstClockTime to; + GstRTSPResult res; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL || size == 0, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL); + + gst_poll_set_controllable (conn->fdset, TRUE); + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, TRUE); + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, FALSE); + /* clear all previous poll results */ + gst_poll_fd_ignored (conn->fdset, conn->writefd); + gst_poll_fd_ignored (conn->fdset, conn->readfd); + + to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; + + offset = 0; + + while (TRUE) { + /* try to write */ + res = write_bytes (conn->writefd->fd, data, &offset, size); + if (G_LIKELY (res == GST_RTSP_OK)) + break; + if (G_UNLIKELY (res != GST_RTSP_EINTR)) + goto write_error; + + /* not all is written, wait until we can write more */ + do { + retval = gst_poll_wait (conn->fdset, to); + } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + + if (G_UNLIKELY (retval == 0)) + goto timeout; + + if (G_UNLIKELY (retval == -1)) { + if (errno == EBUSY) + goto stopped; + else + goto select_error; + } + + /* could also be an error with read socket */ + if (gst_poll_fd_has_error (conn->fdset, conn->readfd)) + goto socket_error; + } + return GST_RTSP_OK; + + /* ERRORS */ +timeout: + { + return GST_RTSP_ETIMEOUT; + } +select_error: + { + return GST_RTSP_ESYS; + } +stopped: + { + return GST_RTSP_EINTR; + } +socket_error: + { + return GST_RTSP_ENET; + } +write_error: + { + return res; + } +} + +static GString * +message_to_string (GstRTSPConnection * conn, GstRTSPMessage * message) +{ + GString *str = NULL; + + str = g_string_new (""); + + switch (message->type) { + case GST_RTSP_MESSAGE_REQUEST: + /* create request string, add CSeq */ + g_string_append_printf (str, "%s %s RTSP/1.0\r\n" + "CSeq: %d\r\n", + gst_rtsp_method_as_text (message->type_data.request.method), + message->type_data.request.uri, conn->cseq++); + /* add session id if we have one */ + if (conn->session_id[0] != '\0') { + gst_rtsp_message_remove_header (message, GST_RTSP_HDR_SESSION, -1); + gst_rtsp_message_add_header (message, GST_RTSP_HDR_SESSION, + conn->session_id); + } + /* add any authentication headers */ + add_auth_header (conn, message); + break; + case GST_RTSP_MESSAGE_RESPONSE: + /* create response string */ + g_string_append_printf (str, "RTSP/1.0 %d %s\r\n", + message->type_data.response.code, message->type_data.response.reason); + break; + case GST_RTSP_MESSAGE_HTTP_REQUEST: + /* create request string */ + g_string_append_printf (str, "%s %s HTTP/%s\r\n", + gst_rtsp_method_as_text (message->type_data.request.method), + message->type_data.request.uri, + gst_rtsp_version_as_text (message->type_data.request.version)); + /* add any authentication headers */ + add_auth_header (conn, message); + break; + case GST_RTSP_MESSAGE_HTTP_RESPONSE: + /* create response string */ + g_string_append_printf (str, "HTTP/%s %d %s\r\n", + gst_rtsp_version_as_text (message->type_data.request.version), + message->type_data.response.code, message->type_data.response.reason); + break; + case GST_RTSP_MESSAGE_DATA: + { + guint8 data_header[4]; + + /* prepare data header */ + data_header[0] = '$'; + data_header[1] = message->type_data.data.channel; + data_header[2] = (message->body_size >> 8) & 0xff; + data_header[3] = message->body_size & 0xff; + + /* create string with header and data */ + str = g_string_append_len (str, (gchar *) data_header, 4); + str = + g_string_append_len (str, (gchar *) message->body, + message->body_size); + break; + } + default: + g_string_free (str, TRUE); + g_return_val_if_reached (NULL); + break; + } + + /* append headers and body */ + if (message->type != GST_RTSP_MESSAGE_DATA) { + gchar date_string[100]; + + gen_date_string (date_string, sizeof (date_string)); + + /* add date header */ + gst_rtsp_message_remove_header (message, GST_RTSP_HDR_DATE, -1); + gst_rtsp_message_add_header (message, GST_RTSP_HDR_DATE, date_string); + + /* append headers */ + gst_rtsp_message_append_headers (message, str); + + /* append Content-Length and body if needed */ + if (message->body != NULL && message->body_size > 0) { + gchar *len; + + len = g_strdup_printf ("%d", message->body_size); + g_string_append_printf (str, "%s: %s\r\n", + gst_rtsp_header_as_text (GST_RTSP_HDR_CONTENT_LENGTH), len); + g_free (len); + /* header ends here */ + g_string_append (str, "\r\n"); + str = + g_string_append_len (str, (gchar *) message->body, + message->body_size); + } else { + /* just end headers */ + g_string_append (str, "\r\n"); + } + } + + return str; +} + +/** + * gst_rtsp_connection_send: + * @conn: a #GstRTSPConnection + * @message: the message to send + * @timeout: a timeout value or #NULL + * + * Attempt to send @message to the connected @conn, blocking up to + * the specified @timeout. @timeout can be #NULL, in which case this function + * might block forever. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_send (GstRTSPConnection * conn, GstRTSPMessage * message, + GTimeVal * timeout) +{ + GString *string = NULL; + GstRTSPResult res; + gchar *str; + gsize len; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + + if (G_UNLIKELY (!(string = message_to_string (conn, message)))) + goto no_message; + + if (conn->tunneled) { + str = g_base64_encode ((const guchar *) string->str, string->len); + g_string_free (string, TRUE); + len = strlen (str); + } else { + str = string->str; + len = string->len; + g_string_free (string, FALSE); + } + + /* write request */ + res = gst_rtsp_connection_write (conn, (guint8 *) str, len, timeout); + + g_free (str); + + return res; + +no_message: + { + g_warning ("Wrong message"); + return GST_RTSP_EINVAL; + } +} + +static GstRTSPResult +parse_string (gchar * dest, gint size, gchar ** src) +{ + GstRTSPResult res = GST_RTSP_OK; + gint idx; + + idx = 0; + /* skip spaces */ + while (g_ascii_isspace (**src)) + (*src)++; + + while (!g_ascii_isspace (**src) && **src != '\0') { + if (idx < size - 1) + dest[idx++] = **src; + else + res = GST_RTSP_EPARSE; + (*src)++; + } + if (size > 0) + dest[idx] = '\0'; + + return res; +} + +static GstRTSPResult +parse_protocol_version (gchar * protocol, GstRTSPMsgType * type, + GstRTSPVersion * version) +{ + GstRTSPResult res = GST_RTSP_OK; + gchar *ver; + + if (G_LIKELY ((ver = strchr (protocol, '/')) != NULL)) { + guint major; + guint minor; + gchar dummychar; + + *ver++ = '\0'; + + /* the version number must be formatted as X.Y with nothing following */ + if (sscanf (ver, "%u.%u%c", &major, &minor, &dummychar) != 2) + res = GST_RTSP_EPARSE; + + if (g_ascii_strcasecmp (protocol, "RTSP") == 0) { + if (major != 1 || minor != 0) { + *version = GST_RTSP_VERSION_INVALID; + res = GST_RTSP_ERROR; + } + } else if (g_ascii_strcasecmp (protocol, "HTTP") == 0) { + if (*type == GST_RTSP_MESSAGE_REQUEST) + *type = GST_RTSP_MESSAGE_HTTP_REQUEST; + else if (*type == GST_RTSP_MESSAGE_RESPONSE) + *type = GST_RTSP_MESSAGE_HTTP_RESPONSE; + + if (major == 1 && minor == 1) { + *version = GST_RTSP_VERSION_1_1; + } else if (major != 1 || minor != 0) { + *version = GST_RTSP_VERSION_INVALID; + res = GST_RTSP_ERROR; + } + } else + res = GST_RTSP_EPARSE; + } else + res = GST_RTSP_EPARSE; + + return res; +} + +static GstRTSPResult +parse_response_status (guint8 * buffer, GstRTSPMessage * msg) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPResult res2; + gchar versionstr[20]; + gchar codestr[4]; + gint code; + gchar *bptr; + + bptr = (gchar *) buffer; + + if (parse_string (versionstr, sizeof (versionstr), &bptr) != GST_RTSP_OK) + res = GST_RTSP_EPARSE; + + if (parse_string (codestr, sizeof (codestr), &bptr) != GST_RTSP_OK) + res = GST_RTSP_EPARSE; + code = atoi (codestr); + if (G_UNLIKELY (*codestr == '\0' || code < 0 || code >= 600)) + res = GST_RTSP_EPARSE; + + while (g_ascii_isspace (*bptr)) + bptr++; + + if (G_UNLIKELY (gst_rtsp_message_init_response (msg, code, bptr, + NULL) != GST_RTSP_OK)) + res = GST_RTSP_EPARSE; + + res2 = parse_protocol_version (versionstr, &msg->type, + &msg->type_data.response.version); + if (G_LIKELY (res == GST_RTSP_OK)) + res = res2; + + return res; +} + +static GstRTSPResult +parse_request_line (guint8 * buffer, GstRTSPMessage * msg) +{ + GstRTSPResult res = GST_RTSP_OK; + GstRTSPResult res2; + gchar versionstr[20]; + gchar methodstr[20]; + gchar urlstr[4096]; + gchar *bptr; + GstRTSPMethod method; + + bptr = (gchar *) buffer; + + if (parse_string (methodstr, sizeof (methodstr), &bptr) != GST_RTSP_OK) + res = GST_RTSP_EPARSE; + method = gst_rtsp_find_method (methodstr); + + if (parse_string (urlstr, sizeof (urlstr), &bptr) != GST_RTSP_OK) + res = GST_RTSP_EPARSE; + if (G_UNLIKELY (*urlstr == '\0')) + res = GST_RTSP_EPARSE; + + if (parse_string (versionstr, sizeof (versionstr), &bptr) != GST_RTSP_OK) + res = GST_RTSP_EPARSE; + + if (G_UNLIKELY (*bptr != '\0')) + res = GST_RTSP_EPARSE; + + if (G_UNLIKELY (gst_rtsp_message_init_request (msg, method, + urlstr) != GST_RTSP_OK)) + res = GST_RTSP_EPARSE; + + res2 = parse_protocol_version (versionstr, &msg->type, + &msg->type_data.request.version); + if (G_LIKELY (res == GST_RTSP_OK)) + res = res2; + + if (G_LIKELY (msg->type == GST_RTSP_MESSAGE_REQUEST)) { + /* GET and POST are not allowed as RTSP methods */ + if (msg->type_data.request.method == GST_RTSP_GET || + msg->type_data.request.method == GST_RTSP_POST) { + msg->type_data.request.method = GST_RTSP_INVALID; + if (res == GST_RTSP_OK) + res = GST_RTSP_ERROR; + } + } else if (msg->type == GST_RTSP_MESSAGE_HTTP_REQUEST) { + /* only GET and POST are allowed as HTTP methods */ + if (msg->type_data.request.method != GST_RTSP_GET && + msg->type_data.request.method != GST_RTSP_POST) { + msg->type_data.request.method = GST_RTSP_INVALID; + if (res == GST_RTSP_OK) + res = GST_RTSP_ERROR; + } + } + + return res; +} + +/* parsing lines means reading a Key: Value pair */ +static GstRTSPResult +parse_line (guint8 * buffer, GstRTSPMessage * msg) +{ + GstRTSPHeaderField field; + gchar *line = (gchar *) buffer; + gchar *value; + + if ((value = strchr (line, ':')) == NULL || value == line) + goto parse_error; + + /* trim space before the colon */ + if (value[-1] == ' ') + value[-1] = '\0'; + + /* replace the colon with a NUL */ + *value++ = '\0'; + + /* find the header */ + field = gst_rtsp_find_header_field (line); + if (field == GST_RTSP_HDR_INVALID) + goto done; + + /* split up the value in multiple key:value pairs if it contains comma(s) */ + while (*value != '\0') { + gchar *next_value; + gchar *comma = NULL; + gboolean quoted = FALSE; + guint comment = 0; + + /* trim leading space */ + if (*value == ' ') + value++; + + /* for headers which may not appear multiple times, and thus may not + * contain multiple values on the same line, we can short-circuit the loop + * below and the entire value results in just one key:value pair*/ + if (!gst_rtsp_header_allow_multiple (field)) + next_value = value + strlen (value); + else + next_value = value; + + /* find the next value, taking special care of quotes and comments */ + while (*next_value != '\0') { + if ((quoted || comment != 0) && *next_value == '\\' && + next_value[1] != '\0') + next_value++; + else if (comment == 0 && *next_value == '"') + quoted = !quoted; + else if (!quoted && *next_value == '(') + comment++; + else if (comment != 0 && *next_value == ')') + comment--; + else if (!quoted && comment == 0) { + /* To quote RFC 2068: "User agents MUST take special care in parsing + * the WWW-Authenticate field value if it contains more than one + * challenge, or if more than one WWW-Authenticate header field is + * provided, since the contents of a challenge may itself contain a + * comma-separated list of authentication parameters." + * + * What this means is that we cannot just look for an unquoted comma + * when looking for multiple values in Proxy-Authenticate and + * WWW-Authenticate headers. Instead we need to look for the sequence + * "comma [space] token space token" before we can split after the + * comma... + */ + if (field == GST_RTSP_HDR_PROXY_AUTHENTICATE || + field == GST_RTSP_HDR_WWW_AUTHENTICATE) { + if (*next_value == ',') { + if (next_value[1] == ' ') { + /* skip any space following the comma so we do not mistake it for + * separating between two tokens */ + next_value++; + } + comma = next_value; + } else if (*next_value == ' ' && next_value[1] != ',' && + next_value[1] != '=' && comma != NULL) { + next_value = comma; + comma = NULL; + break; + } + } else if (*next_value == ',') + break; + } + + next_value++; + } + + /* trim space */ + if (value != next_value && next_value[-1] == ' ') + next_value[-1] = '\0'; + + if (*next_value != '\0') + *next_value++ = '\0'; + + /* add the key:value pair */ + if (*value != '\0') + gst_rtsp_message_add_header (msg, field, value); + + value = next_value; + } + +done: + return GST_RTSP_OK; + + /* ERRORS */ +parse_error: + { + return GST_RTSP_EPARSE; + } +} + +/* convert all consecutive whitespace to a single space */ +static void +normalize_line (guint8 * buffer) +{ + while (*buffer) { + if (g_ascii_isspace (*buffer)) { + guint8 *tmp; + + *buffer++ = ' '; + for (tmp = buffer; g_ascii_isspace (*tmp); tmp++) { + } + if (buffer != tmp) + memmove (buffer, tmp, strlen ((gchar *) tmp) + 1); + } else { + buffer++; + } + } +} + +/* returns: + * GST_RTSP_OK when a complete message was read. + * GST_RTSP_EEOF: when the read socket is closed + * GST_RTSP_EINTR: when more data is needed. + * GST_RTSP_..: some other error occured. + */ +static GstRTSPResult +build_next (GstRTSPBuilder * builder, GstRTSPMessage * message, + GstRTSPConnection * conn) +{ + GstRTSPResult res; + + while (TRUE) { + switch (builder->state) { + case STATE_START: + { + guint8 c; + + builder->offset = 0; + res = + read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 1); + if (res != GST_RTSP_OK) + goto done; + + c = builder->buffer[0]; + + /* we have 1 bytes now and we can see if this is a data message or + * not */ + if (c == '$') { + /* data message, prepare for the header */ + builder->state = STATE_DATA_HEADER; + } else if (c == '\n' || c == '\r') { + /* skip \n and \r */ + builder->offset = 0; + } else { + builder->line = 0; + builder->state = STATE_READ_LINES; + } + break; + } + case STATE_DATA_HEADER: + { + res = + read_bytes (conn, (guint8 *) builder->buffer, &builder->offset, 4); + if (res != GST_RTSP_OK) + goto done; + + gst_rtsp_message_init_data (message, builder->buffer[1]); + + builder->body_len = (builder->buffer[2] << 8) | builder->buffer[3]; + builder->body_data = g_malloc (builder->body_len + 1); + builder->body_data[builder->body_len] = '\0'; + builder->offset = 0; + builder->state = STATE_DATA_BODY; + break; + } + case STATE_DATA_BODY: + { + res = + read_bytes (conn, builder->body_data, &builder->offset, + builder->body_len); + if (res != GST_RTSP_OK) + goto done; + + /* we have the complete body now, store in the message adjusting the + * length to include the traling '\0' */ + gst_rtsp_message_take_body (message, + (guint8 *) builder->body_data, builder->body_len + 1); + builder->body_data = NULL; + builder->body_len = 0; + + builder->state = STATE_END; + break; + } + case STATE_READ_LINES: + { + res = read_line (conn, builder->buffer, &builder->offset, + sizeof (builder->buffer)); + if (res != GST_RTSP_OK) + goto done; + + /* we have a regular response */ + if (builder->buffer[0] == '\0') { + gchar *hdrval; + + /* empty line, end of message header */ + /* see if there is a Content-Length header, but ignore it if this + * is a POST request with an x-sessioncookie header */ + if (gst_rtsp_message_get_header (message, + GST_RTSP_HDR_CONTENT_LENGTH, &hdrval, 0) == GST_RTSP_OK && + (message->type != GST_RTSP_MESSAGE_HTTP_REQUEST || + message->type_data.request.method != GST_RTSP_POST || + gst_rtsp_message_get_header (message, + GST_RTSP_HDR_X_SESSIONCOOKIE, NULL, 0) != GST_RTSP_OK)) { + /* there is, prepare to read the body */ + builder->body_len = atol (hdrval); + builder->body_data = g_try_malloc (builder->body_len + 1); + /* we can't do much here, we need the length to know how many bytes + * we need to read next and when allocation fails, something is + * probably wrong with the length. */ + if (builder->body_data == NULL) + goto invalid_body_len; + + builder->body_data[builder->body_len] = '\0'; + builder->offset = 0; + builder->state = STATE_DATA_BODY; + } else { + builder->state = STATE_END; + } + break; + } + + /* we have a line */ + normalize_line (builder->buffer); + if (builder->line == 0) { + /* first line, check for response status */ + if (memcmp (builder->buffer, "RTSP", 4) == 0 || + memcmp (builder->buffer, "HTTP", 4) == 0) { + builder->status = parse_response_status (builder->buffer, message); + } else { + builder->status = parse_request_line (builder->buffer, message); + } + } else { + /* else just parse the line */ + res = parse_line (builder->buffer, message); + if (res != GST_RTSP_OK) + builder->status = res; + } + builder->line++; + builder->offset = 0; + break; + } + case STATE_END: + { + gchar *session_cookie; + gchar *session_id; + + if (message->type == GST_RTSP_MESSAGE_DATA) { + /* data messages don't have headers */ + res = GST_RTSP_OK; + goto done; + } + + /* save the tunnel session in the connection */ + if (message->type == GST_RTSP_MESSAGE_HTTP_REQUEST && + !conn->manual_http && + conn->tstate == TUNNEL_STATE_NONE && + gst_rtsp_message_get_header (message, GST_RTSP_HDR_X_SESSIONCOOKIE, + &session_cookie, 0) == GST_RTSP_OK) { + strncpy (conn->tunnelid, session_cookie, TUNNELID_LEN); + conn->tunnelid[TUNNELID_LEN - 1] = '\0'; + conn->tunneled = TRUE; + } + + /* save session id in the connection for further use */ + if (message->type == GST_RTSP_MESSAGE_RESPONSE && + gst_rtsp_message_get_header (message, GST_RTSP_HDR_SESSION, + &session_id, 0) == GST_RTSP_OK) { + gint maxlen, i; + + maxlen = sizeof (conn->session_id) - 1; + /* the sessionid can have attributes marked with ; + * Make sure we strip them */ + for (i = 0; session_id[i] != '\0'; i++) { + if (session_id[i] == ';') { + maxlen = i; + /* parse timeout */ + do { + i++; + } while (g_ascii_isspace (session_id[i])); + if (g_str_has_prefix (&session_id[i], "timeout=")) { + gint to; + + /* if we parsed something valid, configure */ + if ((to = atoi (&session_id[i + 8])) > 0) + conn->timeout = to; + } + break; + } + } + + /* make sure to not overflow */ + strncpy (conn->session_id, session_id, maxlen); + conn->session_id[maxlen] = '\0'; + } + res = builder->status; + goto done; + } + default: + res = GST_RTSP_ERROR; + break; + } + } +done: + return res; + + /* ERRORS */ +invalid_body_len: + { + GST_DEBUG ("could not allocate body"); + return GST_RTSP_ERROR; + } +} + +/** + * gst_rtsp_connection_read: + * @conn: a #GstRTSPConnection + * @data: the data to read + * @size: the size of @data + * @timeout: a timeout value or #NULL + * + * Attempt to read @size bytes into @data from the connected @conn, blocking up to + * the specified @timeout. @timeout can be #NULL, in which case this function + * might block forever. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, guint size, + GTimeVal * timeout) +{ + guint offset; + gint retval; + GstClockTime to; + GstRTSPResult res; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); + + if (G_UNLIKELY (size == 0)) + return GST_RTSP_OK; + + offset = 0; + + /* configure timeout if any */ + to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; + + gst_poll_set_controllable (conn->fdset, TRUE); + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE); + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE); + + while (TRUE) { + res = read_bytes (conn, data, &offset, size); + if (G_UNLIKELY (res == GST_RTSP_EEOF)) + goto eof; + if (G_LIKELY (res == GST_RTSP_OK)) + break; + if (G_UNLIKELY (res != GST_RTSP_EINTR)) + goto read_error; + + do { + retval = gst_poll_wait (conn->fdset, to); + } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + + /* check for timeout */ + if (G_UNLIKELY (retval == 0)) + goto select_timeout; + + if (G_UNLIKELY (retval == -1)) { + if (errno == EBUSY) + goto stopped; + else + goto select_error; + } + + /* could also be an error with write socket */ + if (gst_poll_fd_has_error (conn->fdset, conn->writefd)) + goto socket_error; + + gst_poll_set_controllable (conn->fdset, FALSE); + } + return GST_RTSP_OK; + + /* ERRORS */ +select_error: + { + return GST_RTSP_ESYS; + } +select_timeout: + { + return GST_RTSP_ETIMEOUT; + } +stopped: + { + return GST_RTSP_EINTR; + } +eof: + { + return GST_RTSP_EEOF; + } +socket_error: + { + res = GST_RTSP_ENET; + } +read_error: + { + return res; + } +} + +static GstRTSPMessage * +gen_tunnel_reply (GstRTSPConnection * conn, GstRTSPStatusCode code, + const GstRTSPMessage * request) +{ + GstRTSPMessage *msg; + GstRTSPResult res; + + if (gst_rtsp_status_as_text (code) == NULL) + code = GST_RTSP_STS_INTERNAL_SERVER_ERROR; + + GST_RTSP_CHECK (gst_rtsp_message_new_response (&msg, code, NULL, request), + no_message); + + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_SERVER, + "GStreamer RTSP Server"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONNECTION, "close"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CACHE_CONTROL, "no-store"); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_PRAGMA, "no-cache"); + + if (code == GST_RTSP_STS_OK) { + if (conn->ip) + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_X_SERVER_IP_ADDRESS, + conn->ip); + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CONTENT_TYPE, + "application/x-rtsp-tunnelled"); + } + + return msg; + + /* ERRORS */ +no_message: + { + return NULL; + } +} + +/** + * gst_rtsp_connection_receive: + * @conn: a #GstRTSPConnection + * @message: the message to read + * @timeout: a timeout value or #NULL + * + * Attempt to read into @message from the connected @conn, blocking up to + * the specified @timeout. @timeout can be #NULL, in which case this function + * might block forever. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_receive (GstRTSPConnection * conn, GstRTSPMessage * message, + GTimeVal * timeout) +{ + GstRTSPResult res; + GstRTSPBuilder builder; + gint retval; + GstClockTime to; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); + + /* configure timeout if any */ + to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; + + gst_poll_set_controllable (conn->fdset, TRUE); + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, FALSE); + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, TRUE); + + memset (&builder, 0, sizeof (GstRTSPBuilder)); + while (TRUE) { + res = build_next (&builder, message, conn); + if (G_UNLIKELY (res == GST_RTSP_EEOF)) + goto eof; + else if (G_LIKELY (res == GST_RTSP_OK)) { + if (!conn->manual_http) { + if (message->type == GST_RTSP_MESSAGE_HTTP_REQUEST) { + if (conn->tstate == TUNNEL_STATE_NONE && + message->type_data.request.method == GST_RTSP_GET) { + GstRTSPMessage *response; + + conn->tstate = TUNNEL_STATE_GET; + + /* tunnel GET request, we can reply now */ + response = gen_tunnel_reply (conn, GST_RTSP_STS_OK, message); + res = gst_rtsp_connection_send (conn, response, timeout); + gst_rtsp_message_free (response); + if (res == GST_RTSP_OK) + res = GST_RTSP_ETGET; + goto cleanup; + } else if (conn->tstate == TUNNEL_STATE_NONE && + message->type_data.request.method == GST_RTSP_POST) { + conn->tstate = TUNNEL_STATE_POST; + + /* tunnel POST request, the caller now has to link the two + * connections. */ + res = GST_RTSP_ETPOST; + goto cleanup; + } else { + res = GST_RTSP_EPARSE; + goto cleanup; + } + } else if (message->type == GST_RTSP_MESSAGE_HTTP_RESPONSE) { + res = GST_RTSP_EPARSE; + goto cleanup; + } + } + + break; + } else if (G_UNLIKELY (res != GST_RTSP_EINTR)) + goto read_error; + + do { + retval = gst_poll_wait (conn->fdset, to); + } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + + /* check for timeout */ + if (G_UNLIKELY (retval == 0)) + goto select_timeout; + + if (G_UNLIKELY (retval == -1)) { + if (errno == EBUSY) + goto stopped; + else + goto select_error; + } + + /* could also be an error with write socket */ + if (gst_poll_fd_has_error (conn->fdset, conn->writefd)) + goto socket_error; + + gst_poll_set_controllable (conn->fdset, FALSE); + } + + /* we have a message here */ + build_reset (&builder); + + return GST_RTSP_OK; + + /* ERRORS */ +select_error: + { + res = GST_RTSP_ESYS; + goto cleanup; + } +select_timeout: + { + res = GST_RTSP_ETIMEOUT; + goto cleanup; + } +stopped: + { + res = GST_RTSP_EINTR; + goto cleanup; + } +eof: + { + res = GST_RTSP_EEOF; + goto cleanup; + } +socket_error: + { + res = GST_RTSP_ENET; + goto cleanup; + } +read_error: +cleanup: + { + build_reset (&builder); + gst_rtsp_message_unset (message); + return res; + } +} + +/** + * gst_rtsp_connection_close: + * @conn: a #GstRTSPConnection + * + * Close the connected @conn. After this call, the connection is in the same + * state as when it was first created. + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_close (GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + g_free (conn->ip); + conn->ip = NULL; + + conn->read_ahead = 0; + + g_free (conn->initial_buffer); + conn->initial_buffer = NULL; + conn->initial_buffer_offset = 0; + + REMOVE_POLLFD (conn->fdset, &conn->fd0); + REMOVE_POLLFD (conn->fdset, &conn->fd1); + conn->writefd = NULL; + conn->readfd = NULL; + conn->tunneled = FALSE; + conn->tstate = TUNNEL_STATE_NONE; + conn->ctxp = NULL; + g_free (conn->username); + conn->username = NULL; + g_free (conn->passwd); + conn->passwd = NULL; + gst_rtsp_connection_clear_auth_params (conn); + conn->timeout = 60; + conn->cseq = 0; + conn->session_id[0] = '\0'; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_free: + * @conn: a #GstRTSPConnection + * + * Close and free @conn. + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_connection_free (GstRTSPConnection * conn) +{ + GstRTSPResult res; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + res = gst_rtsp_connection_close (conn); + gst_poll_free (conn->fdset); + g_timer_destroy (conn->timer); + gst_rtsp_url_free (conn->url); + g_free (conn->proxy_host); + g_free (conn); +#ifdef G_OS_WIN32 + WSACleanup (); +#endif + + return res; +} + +/** + * gst_rtsp_connection_poll: + * @conn: a #GstRTSPConnection + * @events: a bitmask of #GstRTSPEvent flags to check + * @revents: location for result flags + * @timeout: a timeout + * + * Wait up to the specified @timeout for the connection to become available for + * at least one of the operations specified in @events. When the function returns + * with #GST_RTSP_OK, @revents will contain a bitmask of available operations on + * @conn. + * + * @timeout can be #NULL, in which case this function might block forever. + * + * This function can be cancelled with gst_rtsp_connection_flush(). + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.15 + */ +GstRTSPResult +gst_rtsp_connection_poll (GstRTSPConnection * conn, GstRTSPEvent events, + GstRTSPEvent * revents, GTimeVal * timeout) +{ + GstClockTime to; + gint retval; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (events != 0, GST_RTSP_EINVAL); + g_return_val_if_fail (revents != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL); + + gst_poll_set_controllable (conn->fdset, TRUE); + + /* add fd to writer set when asked to */ + gst_poll_fd_ctl_write (conn->fdset, conn->writefd, + events & GST_RTSP_EV_WRITE); + + /* add fd to reader set when asked to */ + gst_poll_fd_ctl_read (conn->fdset, conn->readfd, events & GST_RTSP_EV_READ); + + /* configure timeout if any */ + to = timeout ? GST_TIMEVAL_TO_TIME (*timeout) : GST_CLOCK_TIME_NONE; + + do { + retval = gst_poll_wait (conn->fdset, to); + } while (retval == -1 && (errno == EINTR || errno == EAGAIN)); + + if (G_UNLIKELY (retval == 0)) + goto select_timeout; + + if (G_UNLIKELY (retval == -1)) { + if (errno == EBUSY) + goto stopped; + else + goto select_error; + } + + *revents = 0; + if (events & GST_RTSP_EV_READ) { + if (gst_poll_fd_can_read (conn->fdset, conn->readfd)) + *revents |= GST_RTSP_EV_READ; + } + if (events & GST_RTSP_EV_WRITE) { + if (gst_poll_fd_can_write (conn->fdset, conn->writefd)) + *revents |= GST_RTSP_EV_WRITE; + } + return GST_RTSP_OK; + + /* ERRORS */ +select_timeout: + { + return GST_RTSP_ETIMEOUT; + } +select_error: + { + return GST_RTSP_ESYS; + } +stopped: + { + return GST_RTSP_EINTR; + } +} + +/** + * gst_rtsp_connection_next_timeout: + * @conn: a #GstRTSPConnection + * @timeout: a timeout + * + * Calculate the next timeout for @conn, storing the result in @timeout. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_connection_next_timeout (GstRTSPConnection * conn, GTimeVal * timeout) +{ + gdouble elapsed; + glong sec; + gulong usec; + gint ctimeout; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (timeout != NULL, GST_RTSP_EINVAL); + + ctimeout = conn->timeout; + if (ctimeout >= 20) { + /* Because we should act before the timeout we timeout 5 + * seconds in advance. */ + ctimeout -= 5; + } else if (ctimeout >= 5) { + /* else timeout 20% earlier */ + ctimeout -= ctimeout / 5; + } else if (ctimeout >= 1) { + /* else timeout 1 second earlier */ + ctimeout -= 1; + } + + elapsed = g_timer_elapsed (conn->timer, &usec); + if (elapsed >= ctimeout) { + sec = 0; + usec = 0; + } else { + sec = ctimeout - elapsed; + if (usec <= G_USEC_PER_SEC) + usec = G_USEC_PER_SEC - usec; + else + usec = 0; + } + + timeout->tv_sec = sec; + timeout->tv_usec = usec; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_reset_timeout: + * @conn: a #GstRTSPConnection + * + * Reset the timeout of @conn. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_connection_reset_timeout (GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + g_timer_start (conn->timer); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_flush: + * @conn: a #GstRTSPConnection + * @flush: start or stop the flush + * + * Start or stop the flushing action on @conn. When flushing, all current + * and future actions on @conn will return #GST_RTSP_EINTR until the connection + * is set to non-flushing mode again. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_connection_flush (GstRTSPConnection * conn, gboolean flush) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + gst_poll_set_flushing (conn->fdset, flush); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_set_proxy: + * @conn: a #GstRTSPConnection + * @host: the proxy host + * @port: the proxy port + * + * Set the proxy host and port. + * + * Returns: #GST_RTSP_OK. + * + * Since: 0.10.23 + */ +GstRTSPResult +gst_rtsp_connection_set_proxy (GstRTSPConnection * conn, + const gchar * host, guint port) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + g_free (conn->proxy_host); + conn->proxy_host = g_strdup (host); + conn->proxy_port = port; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_connection_set_auth: + * @conn: a #GstRTSPConnection + * @method: authentication method + * @user: the user + * @pass: the password + * + * Configure @conn for authentication mode @method with @user and @pass as the + * user and password respectively. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_connection_set_auth (GstRTSPConnection * conn, + GstRTSPAuthMethod method, const gchar * user, const gchar * pass) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + if (method == GST_RTSP_AUTH_DIGEST && ((user == NULL || pass == NULL) + || g_strrstr (user, ":") != NULL)) + return GST_RTSP_EINVAL; + + /* Make sure the username and passwd are being set for authentication */ + if (method == GST_RTSP_AUTH_NONE && (user == NULL || pass == NULL)) + return GST_RTSP_EINVAL; + + /* ":" chars are not allowed in usernames for basic auth */ + if (method == GST_RTSP_AUTH_BASIC && g_strrstr (user, ":") != NULL) + return GST_RTSP_EINVAL; + + g_free (conn->username); + g_free (conn->passwd); + + conn->auth_method = method; + conn->username = g_strdup (user); + conn->passwd = g_strdup (pass); + + return GST_RTSP_OK; +} + +/** + * str_case_hash: + * @key: ASCII string to hash + * + * Hashes @key in a case-insensitive manner. + * + * Returns: the hash code. + **/ +static guint +str_case_hash (gconstpointer key) +{ + const char *p = key; + guint h = g_ascii_toupper (*p); + + if (h) + for (p += 1; *p != '\0'; p++) + h = (h << 5) - h + g_ascii_toupper (*p); + + return h; +} + +/** + * str_case_equal: + * @v1: an ASCII string + * @v2: another ASCII string + * + * Compares @v1 and @v2 in a case-insensitive manner + * + * Returns: %TRUE if they are equal (modulo case) + **/ +static gboolean +str_case_equal (gconstpointer v1, gconstpointer v2) +{ + const char *string1 = v1; + const char *string2 = v2; + + return g_ascii_strcasecmp (string1, string2) == 0; +} + +/** + * gst_rtsp_connection_set_auth_param: + * @conn: a #GstRTSPConnection + * @param: authentication directive + * @value: value + * + * Setup @conn with authentication directives. This is not necesary for + * methods #GST_RTSP_AUTH_NONE and #GST_RTSP_AUTH_BASIC. For + * #GST_RTSP_AUTH_DIGEST, directives should be taken from the digest challenge + * in the WWW-Authenticate response header and can include realm, domain, + * nonce, opaque, stale, algorithm, qop as per RFC2617. + * + * Since: 0.10.20 + */ +void +gst_rtsp_connection_set_auth_param (GstRTSPConnection * conn, + const gchar * param, const gchar * value) +{ + g_return_if_fail (conn != NULL); + g_return_if_fail (param != NULL); + + if (conn->auth_params == NULL) { + conn->auth_params = + g_hash_table_new_full (str_case_hash, str_case_equal, g_free, g_free); + } + g_hash_table_insert (conn->auth_params, g_strdup (param), g_strdup (value)); +} + +/** + * gst_rtsp_connection_clear_auth_params: + * @conn: a #GstRTSPConnection + * + * Clear the list of authentication directives stored in @conn. + * + * Since: 0.10.20 + */ +void +gst_rtsp_connection_clear_auth_params (GstRTSPConnection * conn) +{ + g_return_if_fail (conn != NULL); + + if (conn->auth_params != NULL) { + g_hash_table_destroy (conn->auth_params); + conn->auth_params = NULL; + } +} + +static GstRTSPResult +set_qos_dscp (gint fd, guint qos_dscp) +{ + union gst_sockaddr sa; + socklen_t slen = sizeof (sa); + gint af; + gint tos; + + if (fd == -1) + return GST_RTSP_OK; + + if (getsockname (fd, &sa.sa, &slen) < 0) + goto no_getsockname; + + af = sa.sa.sa_family; + + /* if this is an IPv4-mapped address then do IPv4 QoS */ + if (af == AF_INET6) { + if (IN6_IS_ADDR_V4MAPPED (&sa.sa_in6.sin6_addr)) + af = AF_INET; + } + + /* extract and shift 6 bits of the DSCP */ + tos = (qos_dscp & 0x3f) << 2; + + switch (af) { + case AF_INET: + if (SETSOCKOPT (fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)) < 0) + goto no_setsockopt; + break; + case AF_INET6: +#ifdef IPV6_TCLASS + if (SETSOCKOPT (fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, sizeof (tos)) < 0) + goto no_setsockopt; + break; +#endif + default: + goto wrong_family; + } + + return GST_RTSP_OK; + + /* ERRORS */ +no_getsockname: +no_setsockopt: + { + return GST_RTSP_ESYS; + } + +wrong_family: + { + return GST_RTSP_ERROR; + } +} + +/** + * gst_rtsp_connection_set_qos_dscp: + * @conn: a #GstRTSPConnection + * @qos_dscp: DSCP value + * + * Configure @conn to use the specified DSCP value. + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.20 + */ +GstRTSPResult +gst_rtsp_connection_set_qos_dscp (GstRTSPConnection * conn, guint qos_dscp) +{ + GstRTSPResult res; + + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->readfd != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (conn->writefd != NULL, GST_RTSP_EINVAL); + + res = set_qos_dscp (conn->fd0.fd, qos_dscp); + if (res == GST_RTSP_OK) + res = set_qos_dscp (conn->fd1.fd, qos_dscp); + + return res; +} + + +/** + * gst_rtsp_connection_get_url: + * @conn: a #GstRTSPConnection + * + * Retrieve the URL of the other end of @conn. + * + * Returns: The URL. This value remains valid until the + * connection is freed. + * + * Since: 0.10.23 + */ +GstRTSPUrl * +gst_rtsp_connection_get_url (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, NULL); + + return conn->url; +} + +/** + * gst_rtsp_connection_get_ip: + * @conn: a #GstRTSPConnection + * + * Retrieve the IP address of the other end of @conn. + * + * Returns: The IP address as a string. this value remains valid until the + * connection is closed. + * + * Since: 0.10.20 + */ +const gchar * +gst_rtsp_connection_get_ip (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, NULL); + + return conn->ip; +} + +/** + * gst_rtsp_connection_set_ip: + * @conn: a #GstRTSPConnection + * @ip: an ip address + * + * Set the IP address of the server. + * + * Since: 0.10.23 + */ +void +gst_rtsp_connection_set_ip (GstRTSPConnection * conn, const gchar * ip) +{ + g_return_if_fail (conn != NULL); + + g_free (conn->ip); + conn->ip = g_strdup (ip); +} + +/** + * gst_rtsp_connection_get_readfd: + * @conn: a #GstRTSPConnection + * + * Get the file descriptor for reading. + * + * Returns: the file descriptor used for reading or -1 on error. The file + * descriptor remains valid until the connection is closed. + * + * Since: 0.10.23 + */ +gint +gst_rtsp_connection_get_readfd (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, -1); + g_return_val_if_fail (conn->readfd != NULL, -1); + + return conn->readfd->fd; +} + +/** + * gst_rtsp_connection_get_writefd: + * @conn: a #GstRTSPConnection + * + * Get the file descriptor for writing. + * + * Returns: the file descriptor used for writing or -1 on error. The file + * descriptor remains valid until the connection is closed. + * + * Since: 0.10.23 + */ +gint +gst_rtsp_connection_get_writefd (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, -1); + g_return_val_if_fail (conn->writefd != NULL, -1); + + return conn->writefd->fd; +} + +/** + * gst_rtsp_connection_set_http_mode: + * @conn: a #GstRTSPConnection + * @enable: %TRUE to enable manual HTTP mode + * + * By setting the HTTP mode to %TRUE the message parsing will support HTTP + * messages in addition to the RTSP messages. It will also disable the + * automatic handling of setting up an HTTP tunnel. + * + * Since: 0.10.25 + */ +void +gst_rtsp_connection_set_http_mode (GstRTSPConnection * conn, gboolean enable) +{ + g_return_if_fail (conn != NULL); + + conn->manual_http = enable; +} + +/** + * gst_rtsp_connection_set_tunneled: + * @conn: a #GstRTSPConnection + * @tunneled: the new state + * + * Set the HTTP tunneling state of the connection. This must be configured before + * the @conn is connected. + * + * Since: 0.10.23 + */ +void +gst_rtsp_connection_set_tunneled (GstRTSPConnection * conn, gboolean tunneled) +{ + g_return_if_fail (conn != NULL); + g_return_if_fail (conn->readfd == NULL); + g_return_if_fail (conn->writefd == NULL); + + conn->tunneled = tunneled; +} + +/** + * gst_rtsp_connection_is_tunneled: + * @conn: a #GstRTSPConnection + * + * Get the tunneling state of the connection. + * + * Returns: if @conn is using HTTP tunneling. + * + * Since: 0.10.23 + */ +gboolean +gst_rtsp_connection_is_tunneled (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, FALSE); + + return conn->tunneled; +} + +/** + * gst_rtsp_connection_get_tunnelid: + * @conn: a #GstRTSPConnection + * + * Get the tunnel session id the connection. + * + * Returns: returns a non-empty string if @conn is being tunneled over HTTP. + * + * Since: 0.10.23 + */ +const gchar * +gst_rtsp_connection_get_tunnelid (const GstRTSPConnection * conn) +{ + g_return_val_if_fail (conn != NULL, NULL); + + if (!conn->tunneled) + return NULL; + + return conn->tunnelid; +} + +/** + * gst_rtsp_connection_do_tunnel: + * @conn: a #GstRTSPConnection + * @conn2: a #GstRTSPConnection or %NULL + * + * If @conn received the first tunnel connection and @conn2 received + * the second tunnel connection, link the two connections together so that + * @conn manages the tunneled connection. + * + * After this call, @conn2 cannot be used anymore and must be freed with + * gst_rtsp_connection_free(). + * + * If @conn2 is %NULL then only the base64 decoding context will be setup for + * @conn. + * + * Returns: return GST_RTSP_OK on success. + * + * Since: 0.10.23 + */ +GstRTSPResult +gst_rtsp_connection_do_tunnel (GstRTSPConnection * conn, + GstRTSPConnection * conn2) +{ + g_return_val_if_fail (conn != NULL, GST_RTSP_EINVAL); + + if (conn2 != NULL) { + g_return_val_if_fail (conn->tstate == TUNNEL_STATE_GET, GST_RTSP_EINVAL); + g_return_val_if_fail (conn2->tstate == TUNNEL_STATE_POST, GST_RTSP_EINVAL); + g_return_val_if_fail (!memcmp (conn2->tunnelid, conn->tunnelid, + TUNNELID_LEN), GST_RTSP_EINVAL); + + /* both connections have fd0 as the read/write socket. start by taking the + * socket from conn2 and set it as the socket in conn */ + conn->fd1 = conn2->fd0; + + /* clean up some of the state of conn2 */ + gst_poll_remove_fd (conn2->fdset, &conn2->fd0); + conn2->fd0.fd = -1; + conn2->readfd = conn2->writefd = NULL; + + /* We make fd0 the write socket and fd1 the read socket. */ + conn->writefd = &conn->fd0; + conn->readfd = &conn->fd1; + + conn->tstate = TUNNEL_STATE_COMPLETE; + } + + /* we need base64 decoding for the readfd */ + conn->ctx.state = 0; + conn->ctx.save = 0; + conn->ctx.cout = 0; + conn->ctx.coutl = 0; + conn->ctxp = &conn->ctx; + + return GST_RTSP_OK; +} + +#define READ_ERR (G_IO_HUP | G_IO_ERR | G_IO_NVAL) +#define READ_COND (G_IO_IN | READ_ERR) +#define WRITE_ERR (G_IO_HUP | G_IO_ERR | G_IO_NVAL) +#define WRITE_COND (G_IO_OUT | WRITE_ERR) + +typedef struct +{ + guint8 *data; + guint size; + guint id; +} GstRTSPRec; + +/* async functions */ +struct _GstRTSPWatch +{ + GSource source; + + GstRTSPConnection *conn; + + GstRTSPBuilder builder; + GstRTSPMessage message; + + GPollFD readfd; + GPollFD writefd; + + /* queued message for transmission */ + guint id; + GMutex *mutex; + GQueue *messages; + guint8 *write_data; + guint write_off; + guint write_size; + guint write_id; + + GstRTSPWatchFuncs funcs; + + gpointer user_data; + GDestroyNotify notify; +}; + +static gboolean +gst_rtsp_source_prepare (GSource * source, gint * timeout) +{ + GstRTSPWatch *watch = (GstRTSPWatch *) source; + + if (watch->conn->initial_buffer != NULL) + return TRUE; + + *timeout = (watch->conn->timeout * 1000); + + return FALSE; +} + +static gboolean +gst_rtsp_source_check (GSource * source) +{ + GstRTSPWatch *watch = (GstRTSPWatch *) source; + + if (watch->readfd.revents & READ_COND) + return TRUE; + + if (watch->writefd.revents & WRITE_COND) + return TRUE; + + return FALSE; +} + +static gboolean +gst_rtsp_source_dispatch (GSource * source, GSourceFunc callback G_GNUC_UNUSED, + gpointer user_data G_GNUC_UNUSED) +{ + GstRTSPWatch *watch = (GstRTSPWatch *) source; + GstRTSPResult res = GST_RTSP_ERROR; + gboolean keep_running = TRUE; + + /* first read as much as we can */ + if (watch->readfd.revents & READ_COND || watch->conn->initial_buffer != NULL) { + do { + if (watch->readfd.revents & READ_ERR) + goto read_error; + + res = build_next (&watch->builder, &watch->message, watch->conn); + if (res == GST_RTSP_EINTR) + break; + else if (G_UNLIKELY (res == GST_RTSP_EEOF)) { + watch->readfd.events = 0; + watch->readfd.revents = 0; + g_source_remove_poll ((GSource *) watch, &watch->readfd); + /* When we are in tunnelled mode, the read socket can be closed and we + * should be prepared for a new POST method to reopen it */ + if (watch->conn->tstate == TUNNEL_STATE_COMPLETE) { + /* remove the read connection for the tunnel */ + /* we accept a new POST request */ + watch->conn->tstate = TUNNEL_STATE_GET; + /* and signal that we lost our tunnel */ + if (watch->funcs.tunnel_lost) + res = watch->funcs.tunnel_lost (watch, watch->user_data); + goto read_done; + } else + goto eof; + } else if (G_LIKELY (res == GST_RTSP_OK)) { + if (!watch->conn->manual_http && + watch->message.type == GST_RTSP_MESSAGE_HTTP_REQUEST) { + if (watch->conn->tstate == TUNNEL_STATE_NONE && + watch->message.type_data.request.method == GST_RTSP_GET) { + GstRTSPMessage *response; + GstRTSPStatusCode code; + + watch->conn->tstate = TUNNEL_STATE_GET; + + if (watch->funcs.tunnel_start) + code = watch->funcs.tunnel_start (watch, watch->user_data); + else + code = GST_RTSP_STS_OK; + + /* queue the response */ + response = gen_tunnel_reply (watch->conn, code, &watch->message); + gst_rtsp_watch_send_message (watch, response, NULL); + gst_rtsp_message_free (response); + goto read_done; + } else if (watch->conn->tstate == TUNNEL_STATE_NONE && + watch->message.type_data.request.method == GST_RTSP_POST) { + watch->conn->tstate = TUNNEL_STATE_POST; + + /* in the callback the connection should be tunneled with the + * GET connection */ + if (watch->funcs.tunnel_complete) + watch->funcs.tunnel_complete (watch, watch->user_data); + goto read_done; + } + } + } + + if (!watch->conn->manual_http) { + /* if manual HTTP support is not enabled, then restore the message to + * what it would have looked like without the support for parsing HTTP + * messages being present */ + if (watch->message.type == GST_RTSP_MESSAGE_HTTP_REQUEST) { + watch->message.type = GST_RTSP_MESSAGE_REQUEST; + watch->message.type_data.request.method = GST_RTSP_INVALID; + if (watch->message.type_data.request.version != GST_RTSP_VERSION_1_0) + watch->message.type_data.request.version = GST_RTSP_VERSION_INVALID; + res = GST_RTSP_EPARSE; + } else if (watch->message.type == GST_RTSP_MESSAGE_HTTP_RESPONSE) { + watch->message.type = GST_RTSP_MESSAGE_RESPONSE; + if (watch->message.type_data.response.version != GST_RTSP_VERSION_1_0) + watch->message.type_data.response.version = + GST_RTSP_VERSION_INVALID; + res = GST_RTSP_EPARSE; + } + } + + if (G_LIKELY (res == GST_RTSP_OK)) { + if (watch->funcs.message_received) + watch->funcs.message_received (watch, &watch->message, + watch->user_data); + } else { + goto read_error; + } + + read_done: + gst_rtsp_message_unset (&watch->message); + build_reset (&watch->builder); + } while (FALSE); + } + + if (watch->writefd.revents & WRITE_COND) { + if (watch->writefd.revents & WRITE_ERR) + goto write_error; + + g_mutex_lock (watch->mutex); + do { + if (watch->write_data == NULL) { + GstRTSPRec *rec; + + /* get a new message from the queue */ + rec = g_queue_pop_tail (watch->messages); + if (rec == NULL) + break; + + watch->write_off = 0; + watch->write_data = rec->data; + watch->write_size = rec->size; + watch->write_id = rec->id; + + g_slice_free (GstRTSPRec, rec); + } + + res = write_bytes (watch->writefd.fd, watch->write_data, + &watch->write_off, watch->write_size); + g_mutex_unlock (watch->mutex); + + if (res == GST_RTSP_EINTR) + goto write_blocked; + else if (G_LIKELY (res == GST_RTSP_OK)) { + if (watch->funcs.message_sent) + watch->funcs.message_sent (watch, watch->write_id, watch->user_data); + } else { + goto write_error; + } + g_mutex_lock (watch->mutex); + + g_free (watch->write_data); + watch->write_data = NULL; + } while (TRUE); + + watch->writefd.events = WRITE_ERR; + + g_mutex_unlock (watch->mutex); + } + +write_blocked: + return keep_running; + + /* ERRORS */ +eof: + { + if (watch->funcs.closed) + watch->funcs.closed (watch, watch->user_data); + + /* always stop when the readfd returns EOF in non-tunneled mode */ + return FALSE; + } +read_error: + { + watch->readfd.events = 0; + watch->readfd.revents = 0; + g_source_remove_poll ((GSource *) watch, &watch->readfd); + keep_running = (watch->writefd.events != 0); + + if (keep_running) { + if (watch->funcs.error_full) + GST_RTSP_CHECK (watch->funcs.error_full (watch, res, &watch->message, + 0, watch->user_data), error); + else + goto error; + } else + goto eof; + } +write_error: + { + watch->writefd.events = 0; + watch->writefd.revents = 0; + g_source_remove_poll ((GSource *) watch, &watch->writefd); + keep_running = (watch->readfd.events != 0); + + if (keep_running) { + if (watch->funcs.error_full) + GST_RTSP_CHECK (watch->funcs.error_full (watch, res, NULL, + watch->write_id, watch->user_data), error); + else + goto error; + } else + goto eof; + } +error: + { + if (watch->funcs.error) + watch->funcs.error (watch, res, watch->user_data); + + return keep_running; + } +} + +static void +gst_rtsp_rec_free (gpointer data) +{ + GstRTSPRec *rec = data; + + g_free (rec->data); + g_slice_free (GstRTSPRec, rec); +} + +static void +gst_rtsp_source_finalize (GSource * source) +{ + GstRTSPWatch *watch = (GstRTSPWatch *) source; + + build_reset (&watch->builder); + gst_rtsp_message_unset (&watch->message); + + g_queue_foreach (watch->messages, (GFunc) gst_rtsp_rec_free, NULL); + g_queue_free (watch->messages); + watch->messages = NULL; + g_free (watch->write_data); + + g_mutex_free (watch->mutex); + + if (watch->notify) + watch->notify (watch->user_data); +} + +static GSourceFuncs gst_rtsp_source_funcs = { + gst_rtsp_source_prepare, + gst_rtsp_source_check, + gst_rtsp_source_dispatch, + gst_rtsp_source_finalize, + NULL, + NULL +}; + +/** + * gst_rtsp_watch_new: + * @conn: a #GstRTSPConnection + * @funcs: watch functions + * @user_data: user data to pass to @funcs + * @notify: notify when @user_data is not referenced anymore + * + * Create a watch object for @conn. The functions provided in @funcs will be + * called with @user_data when activity happened on the watch. + * + * The new watch is usually created so that it can be attached to a + * maincontext with gst_rtsp_watch_attach(). + * + * @conn must exist for the entire lifetime of the watch. + * + * Returns: a #GstRTSPWatch that can be used for asynchronous RTSP + * communication. Free with gst_rtsp_watch_unref () after usage. + * + * Since: 0.10.23 + */ +GstRTSPWatch * +gst_rtsp_watch_new (GstRTSPConnection * conn, + GstRTSPWatchFuncs * funcs, gpointer user_data, GDestroyNotify notify) +{ + GstRTSPWatch *result; + + g_return_val_if_fail (conn != NULL, NULL); + g_return_val_if_fail (funcs != NULL, NULL); + g_return_val_if_fail (conn->readfd != NULL, NULL); + g_return_val_if_fail (conn->writefd != NULL, NULL); + + result = (GstRTSPWatch *) g_source_new (&gst_rtsp_source_funcs, + sizeof (GstRTSPWatch)); + + result->conn = conn; + result->builder.state = STATE_START; + + result->mutex = g_mutex_new (); + result->messages = g_queue_new (); + + result->readfd.fd = -1; + result->writefd.fd = -1; + + gst_rtsp_watch_reset (result); + + result->funcs = *funcs; + result->user_data = user_data; + result->notify = notify; + + return result; +} + +/** + * gst_rtsp_watch_reset: + * @watch: a #GstRTSPWatch + * + * Reset @watch, this is usually called after gst_rtsp_connection_do_tunnel() + * when the file descriptors of the connection might have changed. + * + * Since: 0.10.23 + */ +void +gst_rtsp_watch_reset (GstRTSPWatch * watch) +{ + if (watch->readfd.fd != -1) + g_source_remove_poll ((GSource *) watch, &watch->readfd); + if (watch->writefd.fd != -1) + g_source_remove_poll ((GSource *) watch, &watch->writefd); + + watch->readfd.fd = watch->conn->readfd->fd; + watch->readfd.events = READ_COND; + watch->readfd.revents = 0; + + watch->writefd.fd = watch->conn->writefd->fd; + watch->writefd.events = WRITE_ERR; + watch->writefd.revents = 0; + + if (watch->readfd.fd != -1) + g_source_add_poll ((GSource *) watch, &watch->readfd); + if (watch->writefd.fd != -1) + g_source_add_poll ((GSource *) watch, &watch->writefd); +} + +/** + * gst_rtsp_watch_attach: + * @watch: a #GstRTSPWatch + * @context: a GMainContext (if NULL, the default context will be used) + * + * Adds a #GstRTSPWatch to a context so that it will be executed within that context. + * + * Returns: the ID (greater than 0) for the watch within the GMainContext. + * + * Since: 0.10.23 + */ +guint +gst_rtsp_watch_attach (GstRTSPWatch * watch, GMainContext * context) +{ + g_return_val_if_fail (watch != NULL, 0); + + return g_source_attach ((GSource *) watch, context); +} + +/** + * gst_rtsp_watch_unref: + * @watch: a #GstRTSPWatch + * + * Decreases the reference count of @watch by one. If the resulting reference + * count is zero the watch and associated memory will be destroyed. + * + * Since: 0.10.23 + */ +void +gst_rtsp_watch_unref (GstRTSPWatch * watch) +{ + g_return_if_fail (watch != NULL); + + g_source_unref ((GSource *) watch); +} + +/** + * gst_rtsp_watch_write_data: + * @watch: a #GstRTSPWatch + * @data: the data to queue + * @size: the size of @data + * @id: location for a message ID or %NULL + * + * Write @data using the connection of the @watch. If it cannot be sent + * immediately, it will be queued for transmission in @watch. The contents of + * @message will then be serialized and transmitted when the connection of the + * @watch becomes writable. In case the @message is queued, the ID returned in + * @id will be non-zero and used as the ID argument in the message_sent + * callback. + * + * This function will take ownership of @data and g_free() it after use. + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.25 + */ +GstRTSPResult +gst_rtsp_watch_write_data (GstRTSPWatch * watch, const guint8 * data, + guint size, guint * id) +{ + GstRTSPResult res; + GstRTSPRec *rec; + guint off = 0; + GMainContext *context = NULL; + + g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (size != 0, GST_RTSP_EINVAL); + + g_mutex_lock (watch->mutex); + + /* try to send the message synchronously first */ + if (watch->messages->length == 0) { + res = write_bytes (watch->writefd.fd, data, &off, size); + if (res != GST_RTSP_EINTR) { + if (id != NULL) + *id = 0; + g_free ((gpointer) data); + goto done; + } + } + + /* make a record with the data and id for sending async */ + rec = g_slice_new (GstRTSPRec); + if (off == 0) { + rec->data = (guint8 *) data; + rec->size = size; + } else { + rec->data = g_memdup (data + off, size - off); + rec->size = size - off; + g_free ((gpointer) data); + } + + do { + /* make sure rec->id is never 0 */ + rec->id = ++watch->id; + } while (G_UNLIKELY (rec->id == 0)); + + /* add the record to a queue. FIXME we would like to have an upper limit here */ + g_queue_push_head (watch->messages, rec); + + /* make sure the main context will now also check for writability on the + * socket */ + if (watch->writefd.events != WRITE_COND) { + watch->writefd.events = WRITE_COND; + context = ((GSource *) watch)->context; + } + + if (id != NULL) + *id = rec->id; + res = GST_RTSP_OK; + +done: + g_mutex_unlock (watch->mutex); + + if (context) + g_main_context_wakeup (context); + + return res; +} + +/** + * gst_rtsp_watch_send_message: + * @watch: a #GstRTSPWatch + * @message: a #GstRTSPMessage + * @id: location for a message ID or %NULL + * + * Send a @message using the connection of the @watch. If it cannot be sent + * immediately, it will be queued for transmission in @watch. The contents of + * @message will then be serialized and transmitted when the connection of the + * @watch becomes writable. In case the @message is queued, the ID returned in + * @id will be non-zero and used as the ID argument in the message_sent + * callback. + * + * Returns: #GST_RTSP_OK on success. + * + * Since: 0.10.25 + */ +GstRTSPResult +gst_rtsp_watch_send_message (GstRTSPWatch * watch, GstRTSPMessage * message, + guint * id) +{ + GString *str; + guint size; + + g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + + /* make a record with the message as a string and id */ + str = message_to_string (watch->conn, message); + size = str->len; + return gst_rtsp_watch_write_data (watch, + (guint8 *) g_string_free (str, FALSE), size, id); +} + +/** + * gst_rtsp_watch_queue_data: + * @watch: a #GstRTSPWatch + * @data: the data to queue + * @size: the size of @data + * + * Queue @data for transmission in @watch. It will be transmitted when the + * connection of the @watch becomes writable. + * + * This function will take ownership of @data and g_free() it after use. + * + * The return value of this function will be used as the id argument in the + * message_sent callback. + * + * Deprecated: Use gst_rtsp_watch_write_data() + * + * Returns: an id. + * + * Since: 0.10.24 + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +guint +gst_rtsp_watch_queue_data (GstRTSPWatch * watch, const guint8 * data, + guint size); +#endif +guint +gst_rtsp_watch_queue_data (GstRTSPWatch * watch, const guint8 * data, + guint size) +{ + GstRTSPRec *rec; + GMainContext *context = NULL; + + g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (size != 0, GST_RTSP_EINVAL); + + g_mutex_lock (watch->mutex); + + /* make a record with the data and id */ + rec = g_slice_new (GstRTSPRec); + rec->data = (guint8 *) data; + rec->size = size; + do { + /* make sure rec->id is never 0 */ + rec->id = ++watch->id; + } while (G_UNLIKELY (rec->id == 0)); + + /* add the record to a queue. FIXME we would like to have an upper limit here */ + g_queue_push_head (watch->messages, rec); + + /* make sure the main context will now also check for writability on the + * socket */ + if (watch->writefd.events != WRITE_COND) { + watch->writefd.events = WRITE_COND; + context = ((GSource *) watch)->context; + } + g_mutex_unlock (watch->mutex); + + if (context) + g_main_context_wakeup (context); + + return rec->id; +} +#endif /* GST_REMOVE_DEPRECATED */ + +/** + * gst_rtsp_watch_queue_message: + * @watch: a #GstRTSPWatch + * @message: a #GstRTSPMessage + * + * Queue a @message for transmission in @watch. The contents of this + * message will be serialized and transmitted when the connection of the + * @watch becomes writable. + * + * The return value of this function will be used as the id argument in the + * message_sent callback. + * + * Deprecated: Use gst_rtsp_watch_send_message() + * + * Returns: an id. + * + * Since: 0.10.23 + */ +#ifndef GST_REMOVE_DEPRECATED +#ifdef GST_DISABLE_DEPRECATED +guint +gst_rtsp_watch_queue_message (GstRTSPWatch * watch, GstRTSPMessage * message); +#endif +guint +gst_rtsp_watch_queue_message (GstRTSPWatch * watch, GstRTSPMessage * message) +{ + GString *str; + guint size; + + g_return_val_if_fail (watch != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (message != NULL, GST_RTSP_EINVAL); + + /* make a record with the message as a string and id */ + str = message_to_string (watch->conn, message); + size = str->len; + return gst_rtsp_watch_queue_data (watch, + (guint8 *) g_string_free (str, FALSE), size); +} +#endif /* GST_REMOVE_DEPRECATED */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.h new file mode 100644 index 0000000..2a34abd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspconnection.h @@ -0,0 +1,209 @@ +/* GStreamer + * Copyright (C) <2005,2009> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_CONNECTION_H__ +#define __GST_RTSP_CONNECTION_H__ + +#include + +#include +#include +#include +#include + +G_BEGIN_DECLS + +/** + * GstRTSPConnection: + * + * Opaque RTSP connection object. + */ +typedef struct _GstRTSPConnection GstRTSPConnection; + +/* opening/closing a connection */ +GstRTSPResult gst_rtsp_connection_create (const GstRTSPUrl *url, GstRTSPConnection **conn); +GstRTSPResult gst_rtsp_connection_create_from_fd (gint fd, + const gchar * ip, + guint16 port, + const gchar * initial_buffer, + GstRTSPConnection ** conn); +GstRTSPResult gst_rtsp_connection_accept (gint sock, GstRTSPConnection **conn); +GstRTSPResult gst_rtsp_connection_connect (GstRTSPConnection *conn, GTimeVal *timeout); +GstRTSPResult gst_rtsp_connection_close (GstRTSPConnection *conn); +GstRTSPResult gst_rtsp_connection_free (GstRTSPConnection *conn); + + +/* sending/receiving raw bytes */ +GstRTSPResult gst_rtsp_connection_read (GstRTSPConnection * conn, guint8 * data, + guint size, GTimeVal * timeout); +GstRTSPResult gst_rtsp_connection_write (GstRTSPConnection * conn, const guint8 * data, + guint size, GTimeVal * timeout); + +/* sending/receiving messages */ +GstRTSPResult gst_rtsp_connection_send (GstRTSPConnection *conn, GstRTSPMessage *message, + GTimeVal *timeout); +GstRTSPResult gst_rtsp_connection_receive (GstRTSPConnection *conn, GstRTSPMessage *message, + GTimeVal *timeout); + +/* status management */ +GstRTSPResult gst_rtsp_connection_poll (GstRTSPConnection *conn, GstRTSPEvent events, + GstRTSPEvent *revents, GTimeVal *timeout); + +/* reset the timeout */ +GstRTSPResult gst_rtsp_connection_next_timeout (GstRTSPConnection *conn, GTimeVal *timeout); +GstRTSPResult gst_rtsp_connection_reset_timeout (GstRTSPConnection *conn); + +/* flushing state */ +GstRTSPResult gst_rtsp_connection_flush (GstRTSPConnection *conn, gboolean flush); + +/* HTTP proxy support */ +GstRTSPResult gst_rtsp_connection_set_proxy (GstRTSPConnection *conn, + const gchar *host, guint port); + +/* configure authentication data */ +GstRTSPResult gst_rtsp_connection_set_auth (GstRTSPConnection *conn, GstRTSPAuthMethod method, + const gchar *user, const gchar *pass); + +void gst_rtsp_connection_set_auth_param (GstRTSPConnection *conn, + const gchar * param, + const gchar *value); +void gst_rtsp_connection_clear_auth_params (GstRTSPConnection *conn); + +/* configure DSCP */ +GstRTSPResult gst_rtsp_connection_set_qos_dscp (GstRTSPConnection *conn, + guint qos_dscp); + +/* accessors */ +GstRTSPUrl * gst_rtsp_connection_get_url (const GstRTSPConnection *conn); +const gchar * gst_rtsp_connection_get_ip (const GstRTSPConnection *conn); +void gst_rtsp_connection_set_ip (GstRTSPConnection *conn, const gchar *ip); + +gint gst_rtsp_connection_get_readfd (const GstRTSPConnection *conn); +gint gst_rtsp_connection_get_writefd (const GstRTSPConnection *conn); + +void gst_rtsp_connection_set_http_mode (GstRTSPConnection *conn, + gboolean enable); + +/* tunneling */ +void gst_rtsp_connection_set_tunneled (GstRTSPConnection *conn, gboolean tunneled); +gboolean gst_rtsp_connection_is_tunneled (const GstRTSPConnection *conn); + +const gchar * gst_rtsp_connection_get_tunnelid (const GstRTSPConnection *conn); +GstRTSPResult gst_rtsp_connection_do_tunnel (GstRTSPConnection *conn, GstRTSPConnection *conn2); + +/* async IO */ + +/** + * GstRTSPWatch: + * + * Opaque RTSP watch object that can be used for asynchronous RTSP + * operations. + */ +typedef struct _GstRTSPWatch GstRTSPWatch; + +/** + * GstRTSPWatchFuncs: + * @message_received: callback when a message was received + * @message_sent: callback when a message was sent + * @closed: callback when the connection is closed + * @error: callback when an error occured + * @tunnel_start: a client started a tunneled connection. The tunnelid of the + * connection must be saved. + * @tunnel_complete: a client finished a tunneled connection. In this callback + * you usually pair the tunnelid of this connection with the saved one using + * gst_rtsp_connection_do_tunnel(). + * @error_full: callback when an error occured with more information than + * the @error callback. Since 0.10.25 + * @tunnel_lost: callback when the post connection of a tunnel is closed. + * Since 0.10.29 + * + * Callback functions from a #GstRTSPWatch. + * + * Since: 0.10.23 + */ +typedef struct { + GstRTSPResult (*message_received) (GstRTSPWatch *watch, GstRTSPMessage *message, + gpointer user_data); + GstRTSPResult (*message_sent) (GstRTSPWatch *watch, guint id, + gpointer user_data); + GstRTSPResult (*closed) (GstRTSPWatch *watch, gpointer user_data); + GstRTSPResult (*error) (GstRTSPWatch *watch, GstRTSPResult result, + gpointer user_data); + GstRTSPStatusCode (*tunnel_start) (GstRTSPWatch *watch, gpointer user_data); + GstRTSPResult (*tunnel_complete) (GstRTSPWatch *watch, gpointer user_data); + GstRTSPResult (*error_full) (GstRTSPWatch *watch, GstRTSPResult result, + GstRTSPMessage *message, guint id, + gpointer user_data); + GstRTSPResult (*tunnel_lost) (GstRTSPWatch *watch, gpointer user_data); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 2]; +} GstRTSPWatchFuncs; + +GstRTSPWatch * gst_rtsp_watch_new (GstRTSPConnection *conn, + GstRTSPWatchFuncs *funcs, + gpointer user_data, + GDestroyNotify notify); +void gst_rtsp_watch_reset (GstRTSPWatch *watch); +void gst_rtsp_watch_unref (GstRTSPWatch *watch); + +guint gst_rtsp_watch_attach (GstRTSPWatch *watch, + GMainContext *context); + +GstRTSPResult gst_rtsp_watch_write_data (GstRTSPWatch *watch, + const guint8 *data, + guint size, guint *id); +GstRTSPResult gst_rtsp_watch_send_message (GstRTSPWatch *watch, + GstRTSPMessage *message, + guint *id); + +#ifndef GST_DISABLE_DEPRECATED +guint gst_rtsp_watch_queue_data (GstRTSPWatch * watch, + const guint8 * data, + guint size); +guint gst_rtsp_watch_queue_message (GstRTSPWatch *watch, + GstRTSPMessage *message); +#endif + +G_END_DECLS + +#endif /* __GST_RTSP_CONNECTION_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.c new file mode 100644 index 0000000..9935c67 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.c @@ -0,0 +1,505 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspdefs + * @short_description: common RTSP defines + * @see_also: gstrtspurl, gstrtspconnection + * + * Provides common defines for the RTSP library. + * + * Last reviewed on 2007-07-24 (0.10.14) + */ + +#include + +#include "gstrtspdefs.h" + +#ifdef G_OS_WIN32 +#include +#else +#include +#endif + +struct rtsp_header +{ + const gchar *name; + gboolean multiple; +}; + +static const gchar *rtsp_methods[] = { + "DESCRIBE", + "ANNOUNCE", + "GET_PARAMETER", + "OPTIONS", + "PAUSE", + "PLAY", + "RECORD", + "REDIRECT", + "SETUP", + "SET_PARAMETER", + "TEARDOWN", + "GET", + "POST", + NULL +}; + +static struct rtsp_header rtsp_headers[] = { + {"Accept", TRUE}, + {"Accept-Encoding", TRUE}, + {"Accept-Language", TRUE}, + {"Allow", TRUE}, + {"Authorization", FALSE}, + {"Bandwidth", FALSE}, + {"Blocksize", FALSE}, + {"Cache-Control", TRUE}, + {"Conference", FALSE}, + {"Connection", TRUE}, + {"Content-Base", FALSE}, + {"Content-Encoding", TRUE}, + {"Content-Language", TRUE}, + {"Content-Length", FALSE}, + {"Content-Location", FALSE}, + {"Content-Type", FALSE}, + {"CSeq", FALSE}, + {"Date", FALSE}, + {"Expires", FALSE}, + {"From", FALSE}, + {"If-Modified-Since", FALSE}, + {"Last-Modified", FALSE}, + {"Proxy-Authenticate", TRUE}, + {"Proxy-Require", TRUE}, + {"Public", TRUE}, + {"Range", FALSE}, + {"Referer", FALSE}, + {"Require", TRUE}, + {"Retry-After", FALSE}, + {"RTP-Info", TRUE}, + {"Scale", FALSE}, + {"Session", FALSE}, + {"Server", FALSE}, + {"Speed", FALSE}, + {"Transport", TRUE}, + {"Unsupported", FALSE}, + {"User-Agent", FALSE}, + {"Via", TRUE}, + {"WWW-Authenticate", TRUE}, + + /* Real extensions */ + {"ClientChallenge", FALSE}, + {"RealChallenge1", FALSE}, + {"RealChallenge2", FALSE}, + {"RealChallenge3", FALSE}, + {"Subscribe", FALSE}, + {"Alert", FALSE}, + {"ClientID", FALSE}, + {"CompanyID", FALSE}, + {"GUID", FALSE}, + {"RegionData", FALSE}, + {"SupportsMaximumASMBandwidth", FALSE}, + {"Language", FALSE}, + {"PlayerStarttime", FALSE}, + + /* Since 0.10.16 */ + {"Location", FALSE}, + + /* Since 0.10.23 */ + {"ETag", FALSE}, + {"If-Match", TRUE}, + + /* WM extensions [MS-RTSP] Since 0.10.23 */ + {"Accept-Charset", TRUE}, + {"Supported", TRUE}, + {"Vary", TRUE}, + {"X-Accelerate-Streaming", FALSE}, + {"X-Accept-Authentication", FALSE}, + {"X-Accept-Proxy-Authentication", FALSE}, + {"X-Broadcast-Id", FALSE}, + {"X-Burst-Streaming", FALSE}, + {"X-Notice", FALSE}, + {"X-Player-Lag-Time", FALSE}, + {"X-Playlist", FALSE}, + {"X-Playlist-Change-Notice", FALSE}, + {"X-Playlist-Gen-Id", FALSE}, + {"X-Playlist-Seek-Id", FALSE}, + {"X-Proxy-Client-Agent", FALSE}, + {"X-Proxy-Client-Verb", FALSE}, + {"X-Receding-PlaylistChange", FALSE}, + {"X-RTP-Info", FALSE}, + {"X-StartupProfile", FALSE}, + + /* Since 0.10.24 */ + {"Timestamp", FALSE}, + + /* Since 0.10.25 */ + {"Authentication-Info", FALSE}, + {"Host", FALSE}, + {"Pragma", TRUE}, + {"X-Server-IP-Address", FALSE}, + {"X-Sessioncookie", FALSE}, + + {NULL, FALSE} +}; + +#define DEF_STATUS(c, t) \ + g_hash_table_insert (statuses, GUINT_TO_POINTER(c), (gpointer) t) + +static GHashTable * +rtsp_init_status (void) +{ + GHashTable *statuses = g_hash_table_new (NULL, NULL); + + DEF_STATUS (GST_RTSP_STS_CONTINUE, "Continue"); + DEF_STATUS (GST_RTSP_STS_OK, "OK"); + DEF_STATUS (GST_RTSP_STS_CREATED, "Created"); + DEF_STATUS (GST_RTSP_STS_LOW_ON_STORAGE, "Low on Storage Space"); + DEF_STATUS (GST_RTSP_STS_MULTIPLE_CHOICES, "Multiple Choices"); + DEF_STATUS (GST_RTSP_STS_MOVED_PERMANENTLY, "Moved Permanently"); + DEF_STATUS (GST_RTSP_STS_MOVE_TEMPORARILY, "Move Temporarily"); + DEF_STATUS (GST_RTSP_STS_SEE_OTHER, "See Other"); + DEF_STATUS (GST_RTSP_STS_NOT_MODIFIED, "Not Modified"); + DEF_STATUS (GST_RTSP_STS_USE_PROXY, "Use Proxy"); + DEF_STATUS (GST_RTSP_STS_BAD_REQUEST, "Bad Request"); + DEF_STATUS (GST_RTSP_STS_UNAUTHORIZED, "Unauthorized"); + DEF_STATUS (GST_RTSP_STS_PAYMENT_REQUIRED, "Payment Required"); + DEF_STATUS (GST_RTSP_STS_FORBIDDEN, "Forbidden"); + DEF_STATUS (GST_RTSP_STS_NOT_FOUND, "Not Found"); + DEF_STATUS (GST_RTSP_STS_METHOD_NOT_ALLOWED, "Method Not Allowed"); + DEF_STATUS (GST_RTSP_STS_NOT_ACCEPTABLE, "Not Acceptable"); + DEF_STATUS (GST_RTSP_STS_PROXY_AUTH_REQUIRED, + "Proxy Authentication Required"); + DEF_STATUS (GST_RTSP_STS_REQUEST_TIMEOUT, "Request Time-out"); + DEF_STATUS (GST_RTSP_STS_GONE, "Gone"); + DEF_STATUS (GST_RTSP_STS_LENGTH_REQUIRED, "Length Required"); + DEF_STATUS (GST_RTSP_STS_PRECONDITION_FAILED, "Precondition Failed"); + DEF_STATUS (GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE, + "Request Entity Too Large"); + DEF_STATUS (GST_RTSP_STS_REQUEST_URI_TOO_LARGE, "Request-URI Too Large"); + DEF_STATUS (GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type"); + DEF_STATUS (GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD, + "Parameter Not Understood"); + DEF_STATUS (GST_RTSP_STS_CONFERENCE_NOT_FOUND, "Conference Not Found"); + DEF_STATUS (GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH, "Not Enough Bandwidth"); + DEF_STATUS (GST_RTSP_STS_SESSION_NOT_FOUND, "Session Not Found"); + DEF_STATUS (GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, + "Method Not Valid in This State"); + DEF_STATUS (GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE, + "Header Field Not Valid for Resource"); + DEF_STATUS (GST_RTSP_STS_INVALID_RANGE, "Invalid Range"); + DEF_STATUS (GST_RTSP_STS_PARAMETER_IS_READONLY, "Parameter Is Read-Only"); + DEF_STATUS (GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED, + "Aggregate operation not allowed"); + DEF_STATUS (GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, + "Only aggregate operation allowed"); + DEF_STATUS (GST_RTSP_STS_UNSUPPORTED_TRANSPORT, "Unsupported transport"); + DEF_STATUS (GST_RTSP_STS_DESTINATION_UNREACHABLE, "Destination unreachable"); + DEF_STATUS (GST_RTSP_STS_INTERNAL_SERVER_ERROR, "Internal Server Error"); + DEF_STATUS (GST_RTSP_STS_NOT_IMPLEMENTED, "Not Implemented"); + DEF_STATUS (GST_RTSP_STS_BAD_GATEWAY, "Bad Gateway"); + DEF_STATUS (GST_RTSP_STS_SERVICE_UNAVAILABLE, "Service Unavailable"); + DEF_STATUS (GST_RTSP_STS_GATEWAY_TIMEOUT, "Gateway Time-out"); + DEF_STATUS (GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED, + "RTSP Version not supported"); + DEF_STATUS (GST_RTSP_STS_OPTION_NOT_SUPPORTED, "Option not supported"); + + return statuses; +} + +/** + * gst_rtsp_strresult: + * @result: a #GstRTSPResult + * + * Convert @result in a human readable string. + * + * Returns: a newly allocated string. g_free() after usage. + */ +gchar * +gst_rtsp_strresult (GstRTSPResult result) +{ + switch (result) { + case GST_RTSP_OK: + return g_strdup ("OK"); +#ifdef G_OS_WIN32 + case GST_RTSP_ESYS: + case GST_RTSP_ENET: + { + gchar *res, *msg; + msg = g_win32_error_message (WSAGetLastError ()); + if (result == GST_RTSP_ESYS) + res = g_strdup_printf ("System error: %s", msg); + else + res = g_strdup_printf ("Network error: %s", msg); + g_free (msg); + return res; + } +#else + case GST_RTSP_ESYS: + return g_strdup_printf ("System error: %s", g_strerror (errno)); + case GST_RTSP_ENET: + return g_strdup_printf ("Network error: %s", hstrerror (h_errno)); +#endif + case GST_RTSP_ERROR: + return g_strdup ("Generic error"); + case GST_RTSP_EINVAL: + return g_strdup ("Invalid parameter specified"); + case GST_RTSP_EINTR: + return g_strdup ("Operation interrupted"); + case GST_RTSP_ENOMEM: + return g_strdup ("Out of memory"); + case GST_RTSP_ERESOLV: + return g_strdup ("Cannot resolve host"); + case GST_RTSP_ENOTIMPL: + return g_strdup ("Function not implemented"); + case GST_RTSP_EPARSE: + return g_strdup ("Parse error"); + case GST_RTSP_EWSASTART: + return g_strdup ("Error on WSAStartup"); + case GST_RTSP_EWSAVERSION: + return g_strdup ("Windows sockets are not version 0x202"); + case GST_RTSP_EEOF: + return g_strdup ("Received end-of-file"); + case GST_RTSP_ENOTIP: + return g_strdup ("Host is not a valid IP address"); + case GST_RTSP_ETIMEOUT: + return g_strdup ("Timeout while waiting for server response"); + case GST_RTSP_ETGET: + return g_strdup ("Tunnel GET request received"); + case GST_RTSP_ETPOST: + return g_strdup ("Tunnel POST request received"); + case GST_RTSP_ELAST: + default: + return g_strdup_printf ("Unknown error (%d)", result); + } +} + +/** + * gst_rtsp_method_as_text: + * @method: a #GstRTSPMethod + * + * Convert @method to a string. + * + * Returns: a string representation of @method. + */ +const gchar * +gst_rtsp_method_as_text (GstRTSPMethod method) +{ + gint i; + + if (method == GST_RTSP_INVALID) + return NULL; + + i = 0; + while ((method & 1) == 0) { + i++; + method >>= 1; + } + return rtsp_methods[i]; +} + +/** + * gst_rtsp_version_as_text: + * @version: a #GstRTSPVersion + * + * Convert @version to a string. + * + * Returns: a string representation of @version. + */ +const gchar * +gst_rtsp_version_as_text (GstRTSPVersion version) +{ + switch (version) { + case GST_RTSP_VERSION_1_0: + return "1.0"; + + case GST_RTSP_VERSION_1_1: + return "1.1"; + + default: + return "0.0"; + } +} + +/** + * gst_rtsp_header_as_text: + * @field: a #GstRTSPHeaderField + * + * Convert @field to a string. + * + * Returns: a string representation of @field. + */ +const gchar * +gst_rtsp_header_as_text (GstRTSPHeaderField field) +{ + if (field == GST_RTSP_HDR_INVALID) + return NULL; + else + return rtsp_headers[field - 1].name; +} + +/** + * gst_rtsp_status_as_text: + * @code: a #GstRTSPStatusCode + * + * Convert @code to a string. + * + * Returns: a string representation of @code. + */ +const gchar * +gst_rtsp_status_as_text (GstRTSPStatusCode code) +{ + static GHashTable *statuses; + + if (G_UNLIKELY (statuses == NULL)) + statuses = rtsp_init_status (); + + return g_hash_table_lookup (statuses, GUINT_TO_POINTER (code)); +} + +/** + * gst_rtsp_find_header_field: + * @header: a header string + * + * Convert @header to a #GstRTSPHeaderField. + * + * Returns: a #GstRTSPHeaderField for @header or #GST_RTSP_HDR_INVALID if the + * header field is unknown. + */ +GstRTSPHeaderField +gst_rtsp_find_header_field (const gchar * header) +{ + gint idx; + + for (idx = 0; rtsp_headers[idx].name; idx++) { + if (g_ascii_strcasecmp (rtsp_headers[idx].name, header) == 0) { + return idx + 1; + } + } + return GST_RTSP_HDR_INVALID; +} + +/** + * gst_rtsp_find_method: + * @method: a method + * + * Convert @method to a #GstRTSPMethod. + * + * Returns: a #GstRTSPMethod for @method or #GST_RTSP_INVALID if the + * method is unknown. + */ +GstRTSPMethod +gst_rtsp_find_method (const gchar * method) +{ + gint idx; + + for (idx = 0; rtsp_methods[idx]; idx++) { + if (g_ascii_strcasecmp (rtsp_methods[idx], method) == 0) { + return (1 << idx); + } + } + return GST_RTSP_INVALID; +} + +/** + * gst_rtsp_options_as_text: + * @options: one or more #GstRTSPMethod + * + * Convert @options to a string. + * + * Returns: a new string of @options. g_free() after usage. + * + * Since: 0.10.23 + */ +gchar * +gst_rtsp_options_as_text (GstRTSPMethod options) +{ + GString *str; + + str = g_string_new (""); + + if (options & GST_RTSP_OPTIONS) + g_string_append (str, "OPTIONS, "); + if (options & GST_RTSP_DESCRIBE) + g_string_append (str, "DESCRIBE, "); + if (options & GST_RTSP_ANNOUNCE) + g_string_append (str, "ANNOUNCE, "); + if (options & GST_RTSP_GET_PARAMETER) + g_string_append (str, "GET_PARAMETER, "); + if (options & GST_RTSP_PAUSE) + g_string_append (str, "PAUSE, "); + if (options & GST_RTSP_PLAY) + g_string_append (str, "PLAY, "); + if (options & GST_RTSP_RECORD) + g_string_append (str, "RECORD, "); + if (options & GST_RTSP_REDIRECT) + g_string_append (str, "REDIRECT, "); + if (options & GST_RTSP_SETUP) + g_string_append (str, "SETUP, "); + if (options & GST_RTSP_SET_PARAMETER) + g_string_append (str, "SET_PARAMETER, "); + if (options & GST_RTSP_TEARDOWN) + g_string_append (str, "TEARDOWN, "); + + /* remove trailing ", " if there is one */ + if (str->len > 2) + str = g_string_truncate (str, str->len - 2); + + return g_string_free (str, FALSE); +} + +/** + * gst_rtsp_header_allow_multiple: + * @field: a #GstRTSPHeaderField + * + * Check whether @field may appear multiple times in a message. + * + * Returns: %TRUE if multiple headers are allowed. + * + * Since: 0.10.25 + */ +gboolean +gst_rtsp_header_allow_multiple (GstRTSPHeaderField field) +{ + if (field == GST_RTSP_HDR_INVALID) + return FALSE; + else + return rtsp_headers[field - 1].multiple; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.h new file mode 100644 index 0000000..9652f17 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspdefs.h @@ -0,0 +1,397 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_DEFS_H__ +#define __GST_RTSP_DEFS_H__ + +#include +#include + +G_BEGIN_DECLS + +/** + * GST_RTSP_CHECK: + * @stmt: a statement + * @label: a label + * + * Macro that checks the return value of @stmt and jumps to @label when it does + * not equal #GST_RTSP_OK. + */ +#define GST_RTSP_CHECK(stmt, label) \ +G_STMT_START { \ + if (G_UNLIKELY ((res = (stmt)) != GST_RTSP_OK)) \ + goto label; \ +} G_STMT_END + +/** + * GstRTSPResult: + * @GST_RTSP_OK: no error + * @GST_RTSP_ERROR: some unspecified error occured + * @GST_RTSP_EINVAL: invalid arguments were provided to a function + * @GST_RTSP_EINTR: an operation was canceled + * @GST_RTSP_ENOMEM: no memory was available for the operation + * @GST_RTSP_ERESOLV: a host resolve error occured + * @GST_RTSP_ENOTIMPL: function not implemented + * @GST_RTSP_ESYS: a system error occured, errno contains more details + * @GST_RTSP_EPARSE: a persing error occured + * @GST_RTSP_EWSASTART: windows networking could not start + * @GST_RTSP_EWSAVERSION: windows networking stack has wrong version + * @GST_RTSP_EEOF: end-of-file was reached + * @GST_RTSP_ENET: a network problem occured, h_errno contains more details + * @GST_RTSP_ENOTIP: the host is not an IP host + * @GST_RTSP_ETIMEOUT: a timeout occured + * @GST_RTSP_ETGET: the tunnel GET request has been performed + * @GST_RTSP_ETPOST: the tunnel POST request has been performed + * @GST_RTSP_ELAST: last error + * + * Result codes from the RTSP functions. + */ +typedef enum { + GST_RTSP_OK = 0, + /* errors */ + GST_RTSP_ERROR = -1, + GST_RTSP_EINVAL = -2, + GST_RTSP_EINTR = -3, + GST_RTSP_ENOMEM = -4, + GST_RTSP_ERESOLV = -5, + GST_RTSP_ENOTIMPL = -6, + GST_RTSP_ESYS = -7, + GST_RTSP_EPARSE = -8, + GST_RTSP_EWSASTART = -9, + GST_RTSP_EWSAVERSION = -10, + GST_RTSP_EEOF = -11, + GST_RTSP_ENET = -12, + GST_RTSP_ENOTIP = -13, + GST_RTSP_ETIMEOUT = -14, + GST_RTSP_ETGET = -15, + GST_RTSP_ETPOST = -16, + + GST_RTSP_ELAST = -17 +} GstRTSPResult; + +/** + * GstRTSPEvent: + * @GST_RTSP_EV_READ: connection is readable + * @GST_RTSP_EV_WRITE: connection is writable + * + * The possible events for the connection. + */ +typedef enum { + GST_RTSP_EV_READ = (1 << 0), + GST_RTSP_EV_WRITE = (1 << 1) +} GstRTSPEvent; + +/** + * GstRTSPFamily: + * @GST_RTSP_FAM_NONE: unknown network family + * @GST_RTSP_FAM_INET: internet + * @GST_RTSP_FAM_INET6: internet V6 + * + * The possible network families. + */ +typedef enum { + GST_RTSP_FAM_NONE, + GST_RTSP_FAM_INET, + GST_RTSP_FAM_INET6 +} GstRTSPFamily; + +/** + * GstRTSPState: + * @GST_RTSP_STATE_INVALID: invalid state + * @GST_RTSP_STATE_INIT: initializing + * @GST_RTSP_STATE_READY: ready for operation + * @GST_RTSP_STATE_SEEKING: seeking in progress + * @GST_RTSP_STATE_PLAYING: playing + * @GST_RTSP_STATE_RECORDING: recording + * + * The different RTSP states. + */ +typedef enum { + GST_RTSP_STATE_INVALID, + GST_RTSP_STATE_INIT, + GST_RTSP_STATE_READY, + GST_RTSP_STATE_SEEKING, + GST_RTSP_STATE_PLAYING, + GST_RTSP_STATE_RECORDING +} GstRTSPState; + +/** + * GstRTSPVersion: + * @GST_RTSP_VERSION_INVALID: unknown/invalid version + * @GST_RTSP_VERSION_1_0: version 1.0 + * @GST_RTSP_VERSION_1_1: version 1.1. Since 0.10.25 + * + * The supported RTSP versions. + */ +typedef enum { + GST_RTSP_VERSION_INVALID = 0x00, + GST_RTSP_VERSION_1_0 = 0x10, + GST_RTSP_VERSION_1_1 = 0x11 +} GstRTSPVersion; + +/** + * GstRTSPMethod: + * @GST_RTSP_INVALID: invalid method + * @GST_RTSP_DESCRIBE: the DESCRIBE method + * @GST_RTSP_ANNOUNCE: the ANNOUNCE method + * @GST_RTSP_GET_PARAMETER: the GET_PARAMETER method + * @GST_RTSP_OPTIONS: the OPTIONS method + * @GST_RTSP_PAUSE: the PAUSE method + * @GST_RTSP_PLAY: the PLAY method + * @GST_RTSP_RECORD: the RECORD method + * @GST_RTSP_REDIRECT: the REDIRECT method + * @GST_RTSP_SETUP: the SETUP method + * @GST_RTSP_SET_PARAMETER: the SET_PARAMETER method + * @GST_RTSP_TEARDOWN: the TEARDOWN method + * @GST_RTSP_GET: the GET method (HTTP). Since 0.10.25 + * @GST_RTSP_POST: the POST method (HTTP). Since 0.10.25 + * + * The different supported RTSP methods. + */ +typedef enum { + GST_RTSP_INVALID = 0, + GST_RTSP_DESCRIBE = (1 << 0), + GST_RTSP_ANNOUNCE = (1 << 1), + GST_RTSP_GET_PARAMETER = (1 << 2), + GST_RTSP_OPTIONS = (1 << 3), + GST_RTSP_PAUSE = (1 << 4), + GST_RTSP_PLAY = (1 << 5), + GST_RTSP_RECORD = (1 << 6), + GST_RTSP_REDIRECT = (1 << 7), + GST_RTSP_SETUP = (1 << 8), + GST_RTSP_SET_PARAMETER = (1 << 9), + GST_RTSP_TEARDOWN = (1 << 10), + GST_RTSP_GET = (1 << 11), + GST_RTSP_POST = (1 << 12) +} GstRTSPMethod; + +/** + * GstRTSPAuthMethod: + * @GST_RTSP_AUTH_NONE: no authentication + * @GST_RTSP_AUTH_BASIC: basic authentication + * @GST_RTSP_AUTH_DIGEST: digest authentication + * + * Authentication methods, ordered by strength + */ +typedef enum { + GST_RTSP_AUTH_NONE = 0x00, + GST_RTSP_AUTH_BASIC = 0x01, + GST_RTSP_AUTH_DIGEST = 0x02 +} GstRTSPAuthMethod; + +/** + * GST_RTSP_AUTH_MAX: + * + * Strongest available authentication method + */ +#define GST_RTSP_AUTH_MAX GST_RTSP_AUTH_DIGEST + +typedef enum { + GST_RTSP_HDR_INVALID, + + /* + * R = Request + * r = response + * g = general + * e = entity + */ + GST_RTSP_HDR_ACCEPT, /* Accept R opt. entity */ + GST_RTSP_HDR_ACCEPT_ENCODING, /* Accept-Encoding R opt. entity */ + GST_RTSP_HDR_ACCEPT_LANGUAGE, /* Accept-Language R opt. all */ + GST_RTSP_HDR_ALLOW, /* Allow r opt. all */ + GST_RTSP_HDR_AUTHORIZATION, /* Authorization R opt. all */ + GST_RTSP_HDR_BANDWIDTH, /* Bandwidth R opt. all */ + GST_RTSP_HDR_BLOCKSIZE, /* Blocksize R opt. all but OPTIONS, TEARDOWN */ + GST_RTSP_HDR_CACHE_CONTROL, /* Cache-Control g opt. SETUP */ + GST_RTSP_HDR_CONFERENCE, /* Conference R opt. SETUP */ + GST_RTSP_HDR_CONNECTION, /* Connection g req. all */ + GST_RTSP_HDR_CONTENT_BASE, /* Content-Base e opt. entity */ + GST_RTSP_HDR_CONTENT_ENCODING, /* Content-Encoding e req. SET_PARAMETER, DESCRIBE, ANNOUNCE */ + GST_RTSP_HDR_CONTENT_LANGUAGE, /* Content-Language e req. DESCRIBE, ANNOUNCE */ + GST_RTSP_HDR_CONTENT_LENGTH, /* Content-Length e req. SET_PARAMETER, ANNOUNCE, entity */ + GST_RTSP_HDR_CONTENT_LOCATION, /* Content-Location e opt. entity */ + GST_RTSP_HDR_CONTENT_TYPE, /* Content-Type e req. SET_PARAMETER, ANNOUNCE, entity */ + GST_RTSP_HDR_CSEQ, /* CSeq g req. all */ + GST_RTSP_HDR_DATE, /* Date g opt. all */ + GST_RTSP_HDR_EXPIRES, /* Expires e opt. DESCRIBE, ANNOUNCE */ + GST_RTSP_HDR_FROM, /* From R opt. all */ + GST_RTSP_HDR_IF_MODIFIED_SINCE, /* If-Modified-Since R opt. DESCRIBE, SETUP */ + GST_RTSP_HDR_LAST_MODIFIED, /* Last-Modified e opt. entity */ + GST_RTSP_HDR_PROXY_AUTHENTICATE, /* Proxy-Authenticate */ + GST_RTSP_HDR_PROXY_REQUIRE, /* Proxy-Require R req. all */ + GST_RTSP_HDR_PUBLIC, /* Public r opt. all */ + GST_RTSP_HDR_RANGE, /* Range Rr opt. PLAY, PAUSE, RECORD */ + GST_RTSP_HDR_REFERER, /* Referer R opt. all */ + GST_RTSP_HDR_REQUIRE, /* Require R req. all */ + GST_RTSP_HDR_RETRY_AFTER, /* Retry-After r opt. all */ + GST_RTSP_HDR_RTP_INFO, /* RTP-Info r req. PLAY */ + GST_RTSP_HDR_SCALE, /* Scale Rr opt. PLAY, RECORD */ + GST_RTSP_HDR_SESSION, /* Session Rr req. all but SETUP, OPTIONS */ + GST_RTSP_HDR_SERVER, /* Server r opt. all */ + GST_RTSP_HDR_SPEED, /* Speed Rr opt. PLAY */ + GST_RTSP_HDR_TRANSPORT, /* Transport Rr req. SETUP */ + GST_RTSP_HDR_UNSUPPORTED, /* Unsupported r req. all */ + GST_RTSP_HDR_USER_AGENT, /* User-Agent R opt. all */ + GST_RTSP_HDR_VIA, /* Via g opt. all */ + GST_RTSP_HDR_WWW_AUTHENTICATE, /* WWW-Authenticate r opt. all */ + + /* Real extensions */ + GST_RTSP_HDR_CLIENT_CHALLENGE, /* ClientChallenge */ + GST_RTSP_HDR_REAL_CHALLENGE1, /* RealChallenge1 */ + GST_RTSP_HDR_REAL_CHALLENGE2, /* RealChallenge2 */ + GST_RTSP_HDR_REAL_CHALLENGE3, /* RealChallenge3 */ + GST_RTSP_HDR_SUBSCRIBE, /* Subscribe */ + GST_RTSP_HDR_ALERT, /* Alert */ + GST_RTSP_HDR_CLIENT_ID, /* ClientID */ + GST_RTSP_HDR_COMPANY_ID, /* CompanyID */ + GST_RTSP_HDR_GUID, /* GUID */ + GST_RTSP_HDR_REGION_DATA, /* RegionData */ + GST_RTSP_HDR_MAX_ASM_WIDTH, /* SupportsMaximumASMBandwidth */ + GST_RTSP_HDR_LANGUAGE, /* Language */ + GST_RTSP_HDR_PLAYER_START_TIME, /* PlayerStarttime */ + + /* Since 0.10.16 */ + GST_RTSP_HDR_LOCATION, /* Location */ + + /* Since 0.10.23 */ + GST_RTSP_HDR_ETAG, /* ETag */ + GST_RTSP_HDR_IF_MATCH, /* If-Match */ + + /* WM extensions [MS-RTSP] Since 0.10.23 */ + GST_RTSP_HDR_ACCEPT_CHARSET, /* Accept-Charset */ + GST_RTSP_HDR_SUPPORTED, /* Supported */ + GST_RTSP_HDR_VARY, /* Vary */ + GST_RTSP_HDR_X_ACCELERATE_STREAMING, /* X-Accelerate-Streaming */ + GST_RTSP_HDR_X_ACCEPT_AUTHENT, /* X-Accept-Authentication */ + GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT, /* X-Accept-Proxy-Authentication */ + GST_RTSP_HDR_X_BROADCAST_ID, /* X-Broadcast-Id */ + GST_RTSP_HDR_X_BURST_STREAMING, /* X-Burst-Streaming */ + GST_RTSP_HDR_X_NOTICE, /* X-Notice */ + GST_RTSP_HDR_X_PLAYER_LAG_TIME, /* X-Player-Lag-Time */ + GST_RTSP_HDR_X_PLAYLIST, /* X-Playlist */ + GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE, /* X-Playlist-Change-Notice */ + GST_RTSP_HDR_X_PLAYLIST_GEN_ID, /* X-Playlist-Gen-Id */ + GST_RTSP_HDR_X_PLAYLIST_SEEK_ID, /* X-Playlist-Seek-Id */ + GST_RTSP_HDR_X_PROXY_CLIENT_AGENT, /* X-Proxy-Client-Agent */ + GST_RTSP_HDR_X_PROXY_CLIENT_VERB, /* X-Proxy-Client-Verb */ + GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE, /* X-Receding-PlaylistChange */ + GST_RTSP_HDR_X_RTP_INFO, /* X-RTP-Info */ + GST_RTSP_HDR_X_STARTUPPROFILE, /* X-StartupProfile */ + + /* Since 0.10.24 */ + GST_RTSP_HDR_TIMESTAMP, /* Timestamp */ + + /* Since 0.10.25 */ + GST_RTSP_HDR_AUTHENTICATION_INFO, /* Authentication-Info */ + GST_RTSP_HDR_HOST, /* Host */ + GST_RTSP_HDR_PRAGMA, /* Pragma */ + GST_RTSP_HDR_X_SERVER_IP_ADDRESS, /* X-Server-IP-Address */ + GST_RTSP_HDR_X_SESSIONCOOKIE, /* X-Sessioncookie */ + + GST_RTSP_HDR_LAST +} GstRTSPHeaderField; + +typedef enum { + GST_RTSP_STS_INVALID = 0, + GST_RTSP_STS_CONTINUE = 100, + GST_RTSP_STS_OK = 200, + GST_RTSP_STS_CREATED = 201, + GST_RTSP_STS_LOW_ON_STORAGE = 250, + GST_RTSP_STS_MULTIPLE_CHOICES = 300, + GST_RTSP_STS_MOVED_PERMANENTLY = 301, + GST_RTSP_STS_MOVE_TEMPORARILY = 302, + GST_RTSP_STS_SEE_OTHER = 303, + GST_RTSP_STS_NOT_MODIFIED = 304, + GST_RTSP_STS_USE_PROXY = 305, + GST_RTSP_STS_BAD_REQUEST = 400, + GST_RTSP_STS_UNAUTHORIZED = 401, + GST_RTSP_STS_PAYMENT_REQUIRED = 402, + GST_RTSP_STS_FORBIDDEN = 403, + GST_RTSP_STS_NOT_FOUND = 404, + GST_RTSP_STS_METHOD_NOT_ALLOWED = 405, + GST_RTSP_STS_NOT_ACCEPTABLE = 406, + GST_RTSP_STS_PROXY_AUTH_REQUIRED = 407, + GST_RTSP_STS_REQUEST_TIMEOUT = 408, + GST_RTSP_STS_GONE = 410, + GST_RTSP_STS_LENGTH_REQUIRED = 411, + GST_RTSP_STS_PRECONDITION_FAILED = 412, + GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE = 413, + GST_RTSP_STS_REQUEST_URI_TOO_LARGE = 414, + GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE = 415, + GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD = 451, + GST_RTSP_STS_CONFERENCE_NOT_FOUND = 452, + GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH = 453, + GST_RTSP_STS_SESSION_NOT_FOUND = 454, + GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE = 455, + GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE = 456, + GST_RTSP_STS_INVALID_RANGE = 457, + GST_RTSP_STS_PARAMETER_IS_READONLY = 458, + GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED = 459, + GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED = 460, + GST_RTSP_STS_UNSUPPORTED_TRANSPORT = 461, + GST_RTSP_STS_DESTINATION_UNREACHABLE = 462, + GST_RTSP_STS_INTERNAL_SERVER_ERROR = 500, + GST_RTSP_STS_NOT_IMPLEMENTED = 501, + GST_RTSP_STS_BAD_GATEWAY = 502, + GST_RTSP_STS_SERVICE_UNAVAILABLE = 503, + GST_RTSP_STS_GATEWAY_TIMEOUT = 504, + GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED = 505, + GST_RTSP_STS_OPTION_NOT_SUPPORTED = 551 +} GstRTSPStatusCode; + +gchar* gst_rtsp_strresult (GstRTSPResult result); + +const gchar* gst_rtsp_method_as_text (GstRTSPMethod method); +const gchar* gst_rtsp_version_as_text (GstRTSPVersion version); +const gchar* gst_rtsp_header_as_text (GstRTSPHeaderField field); +const gchar* gst_rtsp_status_as_text (GstRTSPStatusCode code); + +gchar* gst_rtsp_options_as_text (GstRTSPMethod options); + +GstRTSPHeaderField gst_rtsp_find_header_field (const gchar *header); +GstRTSPMethod gst_rtsp_find_method (const gchar *method); + +gboolean gst_rtsp_header_allow_multiple (GstRTSPHeaderField field); + +G_END_DECLS + +#endif /* __GST_RTSP_DEFS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.c new file mode 100644 index 0000000..32d5d8e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.c @@ -0,0 +1,224 @@ +/* GStreamer RTSP extension + * Copyright (C) 2007 Wim Taymans + * + * gstrtspextension.c: RTSP extension mechanism + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspextension + * @short_description: Interface for extending RTSP protocols + * + * + * + * This interface is implemented e.g. by the Windows Media Streaming RTSP + * exentension (rtspwms) and the RealMedia RTSP extension (rtspreal). + * + * + * + * Last reviewed on 2007-07-25 (0.10.14) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstrtsp-marshal.h" +#include "gstrtsp-enumtypes.h" +#include "gstrtspextension.h" + +static void gst_rtsp_extension_iface_init (GstRTSPExtension * iface); + +enum +{ + SIGNAL_SEND, + LAST_SIGNAL +}; + +static guint gst_rtsp_extension_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_rtsp_extension_get_type (void) +{ + static volatile gsize gst_rtsp_extension_type = 0; + static const GTypeInfo gst_rtsp_extension_info = { + sizeof (GstRTSPExtensionInterface), + (GBaseInitFunc) gst_rtsp_extension_iface_init, + NULL, + NULL, + NULL, + NULL, + 0, + 0, + NULL, + }; + + if (g_once_init_enter (&gst_rtsp_extension_type)) { + GType tmp = g_type_register_static (G_TYPE_INTERFACE, + "GstRTSPExtension", &gst_rtsp_extension_info, 0); + g_once_init_leave (&gst_rtsp_extension_type, tmp); + } + return (GType) gst_rtsp_extension_type; +} + +static void +gst_rtsp_extension_iface_init (GstRTSPExtension * iface) +{ + static gboolean initialized = FALSE; + + if (!initialized) { + gst_rtsp_extension_signals[SIGNAL_SEND] = + g_signal_new ("send", G_TYPE_FROM_CLASS (iface), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstRTSPExtensionInterface, + send), NULL, NULL, __gst_rtsp_marshal_ENUM__POINTER_POINTER, + GST_TYPE_RTSP_RESULT, 2, G_TYPE_POINTER, G_TYPE_POINTER); + initialized = TRUE; + } +} + +gboolean +gst_rtsp_extension_detect_server (GstRTSPExtension * ext, GstRTSPMessage * resp) +{ + GstRTSPExtensionInterface *iface; + gboolean res = TRUE; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->detect_server) + res = iface->detect_server (ext, resp); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_before_send (GstRTSPExtension * ext, GstRTSPMessage * req) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->before_send) + res = iface->before_send (ext, req); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_after_send (GstRTSPExtension * ext, GstRTSPMessage * req, + GstRTSPMessage * resp) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->after_send) + res = iface->after_send (ext, req, resp); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_parse_sdp (GstRTSPExtension * ext, GstSDPMessage * sdp, + GstStructure * s) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->parse_sdp) + res = iface->parse_sdp (ext, sdp, s); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_setup_media (GstRTSPExtension * ext, GstSDPMedia * media) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->setup_media) + res = iface->setup_media (ext, media); + + return res; +} + +gboolean +gst_rtsp_extension_configure_stream (GstRTSPExtension * ext, GstCaps * caps) +{ + GstRTSPExtensionInterface *iface; + gboolean res = TRUE; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->configure_stream) + res = iface->configure_stream (ext, caps); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_get_transports (GstRTSPExtension * ext, + GstRTSPLowerTrans protocols, gchar ** transport) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->get_transports) + res = iface->get_transports (ext, protocols, transport); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_stream_select (GstRTSPExtension * ext, GstRTSPUrl * url) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_OK; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->stream_select) + res = iface->stream_select (ext, url); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_receive_request (GstRTSPExtension * ext, + GstRTSPMessage * msg) +{ + GstRTSPExtensionInterface *iface; + GstRTSPResult res = GST_RTSP_ENOTIMPL; + + iface = GST_RTSP_EXTENSION_GET_IFACE (ext); + if (iface->receive_request) + res = iface->receive_request (ext, msg); + + return res; +} + +GstRTSPResult +gst_rtsp_extension_send (GstRTSPExtension * ext, GstRTSPMessage * req, + GstRTSPMessage * resp) +{ + GstRTSPResult res = GST_RTSP_OK; + + g_signal_emit (ext, gst_rtsp_extension_signals[SIGNAL_SEND], 0, + req, resp, &res); + + return res; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.h new file mode 100644 index 0000000..a697c90 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspextension.h @@ -0,0 +1,97 @@ +/* GStreamer RTSP Extension + * Copyright (C) 2007 Wim Taymans + * + * gstrtspextension.h: RTSP Extension interface. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_EXTENSION_H__ +#define __GST_RTSP_EXTENSION_H__ + +#include + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_RTSP_EXTENSION \ + (gst_rtsp_extension_get_type ()) +#define GST_RTSP_EXTENSION(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_RTSP_EXTENSION, GstRTSPExtension)) +#define GST_IS_RTSP_EXTENSION(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_RTSP_EXTENSION)) +#define GST_RTSP_EXTENSION_GET_IFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_RTSP_EXTENSION, GstRTSPExtensionInterface)) + +typedef struct _GstRTSPExtension GstRTSPExtension; +typedef struct _GstRTSPExtensionInterface GstRTSPExtensionInterface; + +struct _GstRTSPExtensionInterface { + GTypeInterface parent; + + /* vfunctions */ + gboolean (*detect_server) (GstRTSPExtension *ext, GstRTSPMessage *resp); + + GstRTSPResult (*before_send) (GstRTSPExtension *ext, GstRTSPMessage *req); + GstRTSPResult (*after_send) (GstRTSPExtension *ext, GstRTSPMessage *req, GstRTSPMessage *resp); + + GstRTSPResult (*parse_sdp) (GstRTSPExtension *ext, GstSDPMessage *sdp, GstStructure *s); + GstRTSPResult (*setup_media) (GstRTSPExtension *ext, GstSDPMedia *media); + + gboolean (*configure_stream) (GstRTSPExtension *ext, GstCaps *caps); + + GstRTSPResult (*get_transports) (GstRTSPExtension *ext, GstRTSPLowerTrans protocols, gchar **transport); + + GstRTSPResult (*stream_select) (GstRTSPExtension *ext, GstRTSPUrl *url); + + /* signals */ + GstRTSPResult (*send) (GstRTSPExtension *ext, GstRTSPMessage *req, GstRTSPMessage *resp); + + /* ABI: more vfunctions added later */ + GstRTSPResult (*receive_request) (GstRTSPExtension *ext, GstRTSPMessage *req); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 1]; +}; + +GType gst_rtsp_extension_get_type (void); + +/* invoke vfunction on interface */ +gboolean gst_rtsp_extension_detect_server (GstRTSPExtension *ext, GstRTSPMessage *resp); + +GstRTSPResult gst_rtsp_extension_before_send (GstRTSPExtension *ext, GstRTSPMessage *req); +GstRTSPResult gst_rtsp_extension_after_send (GstRTSPExtension *ext, GstRTSPMessage *req, + GstRTSPMessage *resp); +GstRTSPResult gst_rtsp_extension_parse_sdp (GstRTSPExtension *ext, GstSDPMessage *sdp, + GstStructure *s); +GstRTSPResult gst_rtsp_extension_setup_media (GstRTSPExtension *ext, GstSDPMedia *media); +gboolean gst_rtsp_extension_configure_stream (GstRTSPExtension *ext, GstCaps *caps); +GstRTSPResult gst_rtsp_extension_get_transports (GstRTSPExtension *ext, GstRTSPLowerTrans protocols, + gchar **transport); +GstRTSPResult gst_rtsp_extension_stream_select (GstRTSPExtension *ext, GstRTSPUrl *url); +GstRTSPResult gst_rtsp_extension_receive_request (GstRTSPExtension *ext, GstRTSPMessage *req); + +/* signal emision */ +GstRTSPResult gst_rtsp_extension_send (GstRTSPExtension *ext, GstRTSPMessage *req, + GstRTSPMessage *resp); + +G_END_DECLS + +#endif /* __GST_RTSP_EXTENSION_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.c new file mode 100644 index 0000000..2b33c61 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.c @@ -0,0 +1,842 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * <2006> Lutz Mueller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspmessage + * @short_description: RTSP messages + * @see_also: gstrtspconnection + * + * Provides methods for creating and parsing request, response and data messages. + * + * Last reviewed on 2007-07-25 (0.10.14) + */ + +#include + +#include +#include "gstrtspmessage.h" + +typedef struct _RTSPKeyValue +{ + GstRTSPHeaderField field; + gchar *value; +} RTSPKeyValue; + +static void +key_value_foreach (GArray * array, GFunc func, gpointer user_data) +{ + guint i; + + g_return_if_fail (array != NULL); + + for (i = 0; i < array->len; i++) { + (*func) (&g_array_index (array, RTSPKeyValue, i), user_data); + } +} + +/** + * gst_rtsp_message_new: + * @msg: a location for the new #GstRTSPMessage + * + * Create a new initialized #GstRTSPMessage. Free with gst_rtsp_message_free(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_new (GstRTSPMessage ** msg) +{ + GstRTSPMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + newmsg = g_new0 (GstRTSPMessage, 1); + + *msg = newmsg; + + return gst_rtsp_message_init (newmsg); +} + +/** + * gst_rtsp_message_init: + * @msg: a #GstRTSPMessage + * + * Initialize @msg. This function is mostly used when @msg is allocated on the + * stack. The reverse operation of this is gst_rtsp_message_unset(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_init (GstRTSPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + gst_rtsp_message_unset (msg); + + msg->type = GST_RTSP_MESSAGE_INVALID; + msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue)); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_get_type: + * @msg: a #GstRTSPMessage + * + * Get the message type of @msg. + * + * Returns: the message type. + */ +GstRTSPMsgType +gst_rtsp_message_get_type (GstRTSPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_MESSAGE_INVALID); + + return msg->type; +} + +/** + * gst_rtsp_message_new_request: + * @msg: a location for the new #GstRTSPMessage + * @method: the request method to use + * @uri: the uri of the request + * + * Create a new #GstRTSPMessage with @method and @uri and store the result + * request message in @msg. Free with gst_rtsp_message_free(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_new_request (GstRTSPMessage ** msg, GstRTSPMethod method, + const gchar * uri) +{ + GstRTSPMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (uri != NULL, GST_RTSP_EINVAL); + + newmsg = g_new0 (GstRTSPMessage, 1); + + *msg = newmsg; + + return gst_rtsp_message_init_request (newmsg, method, uri); +} + +/** + * gst_rtsp_message_init_request: + * @msg: a #GstRTSPMessage + * @method: the request method to use + * @uri: the uri of the request + * + * Initialize @msg as a request message with @method and @uri. To clear @msg + * again, use gst_rtsp_message_unset(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_init_request (GstRTSPMessage * msg, GstRTSPMethod method, + const gchar * uri) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (uri != NULL, GST_RTSP_EINVAL); + + gst_rtsp_message_unset (msg); + + msg->type = GST_RTSP_MESSAGE_REQUEST; + msg->type_data.request.method = method; + msg->type_data.request.uri = g_strdup (uri); + msg->type_data.request.version = GST_RTSP_VERSION_1_0; + msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue)); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_parse_request: + * @msg: a #GstRTSPMessage + * @method: location to hold the method + * @uri: location to hold the uri + * @version: location to hold the version + * + * Parse the request message @msg and store the values @method, @uri and + * @version. The result locations can be #NULL if one is not interested in its + * value. + * + * @uri remains valid for as long as @msg is valid and unchanged. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_parse_request (GstRTSPMessage * msg, + GstRTSPMethod * method, const gchar ** uri, GstRTSPVersion * version) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_REQUEST || + msg->type == GST_RTSP_MESSAGE_HTTP_REQUEST, GST_RTSP_EINVAL); + + if (method) + *method = msg->type_data.request.method; + if (uri) + *uri = msg->type_data.request.uri; + if (version) + *version = msg->type_data.request.version; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_new_response: + * @msg: a location for the new #GstRTSPMessage + * @code: the status code + * @reason: the status reason or #NULL + * @request: the request that triggered the response or #NULL + * + * Create a new response #GstRTSPMessage with @code and @reason and store the + * result message in @msg. Free with gst_rtsp_message_free(). + * + * When @reason is #NULL, the default reason for @code will be used. + * + * When @request is not #NULL, the relevant headers will be copied to the new + * response message. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_new_response (GstRTSPMessage ** msg, GstRTSPStatusCode code, + const gchar * reason, const GstRTSPMessage * request) +{ + GstRTSPMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + newmsg = g_new0 (GstRTSPMessage, 1); + + *msg = newmsg; + + return gst_rtsp_message_init_response (newmsg, code, reason, request); +} + +/** + * gst_rtsp_message_init_response: + * @msg: a #GstRTSPMessage + * @code: the status code + * @reason: the status reason or #NULL + * @request: the request that triggered the response or #NULL + * + * Initialize @msg with @code and @reason. + * + * When @reason is #NULL, the default reason for @code will be used. + * + * When @request is not #NULL, the relevant headers will be copied to the new + * response message. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_init_response (GstRTSPMessage * msg, GstRTSPStatusCode code, + const gchar * reason, const GstRTSPMessage * request) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + gst_rtsp_message_unset (msg); + + if (reason == NULL) + reason = gst_rtsp_status_as_text (code); + + msg->type = GST_RTSP_MESSAGE_RESPONSE; + msg->type_data.response.code = code; + msg->type_data.response.reason = g_strdup (reason); + msg->type_data.response.version = GST_RTSP_VERSION_1_0; + msg->hdr_fields = g_array_new (FALSE, FALSE, sizeof (RTSPKeyValue)); + + if (request) { + if (request->type == GST_RTSP_MESSAGE_HTTP_REQUEST) { + msg->type = GST_RTSP_MESSAGE_HTTP_RESPONSE; + if (request->type_data.request.version != GST_RTSP_VERSION_INVALID) + msg->type_data.response.version = request->type_data.request.version; + else + msg->type_data.response.version = GST_RTSP_VERSION_1_1; + } else { + gchar *header; + + /* copy CSEQ */ + if (gst_rtsp_message_get_header (request, GST_RTSP_HDR_CSEQ, &header, + 0) == GST_RTSP_OK) { + gst_rtsp_message_add_header (msg, GST_RTSP_HDR_CSEQ, header); + } + + /* copy session id */ + if (gst_rtsp_message_get_header (request, GST_RTSP_HDR_SESSION, &header, + 0) == GST_RTSP_OK) { + char *pos; + + header = g_strdup (header); + if ((pos = strchr (header, ';'))) { + *pos = '\0'; + } + g_strchomp (header); + gst_rtsp_message_take_header (msg, GST_RTSP_HDR_SESSION, header); + } + + /* FIXME copy more headers? */ + } + } + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_parse_response: + * @msg: a #GstRTSPMessage + * @code: location to hold the status code + * @reason: location to hold the status reason + * @version: location to hold the version + * + * Parse the response message @msg and store the values @code, @reason and + * @version. The result locations can be #NULL if one is not interested in its + * value. + * + * @reason remains valid for as long as @msg is valid and unchanged. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_parse_response (GstRTSPMessage * msg, + GstRTSPStatusCode * code, const gchar ** reason, GstRTSPVersion * version) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_RESPONSE || + msg->type == GST_RTSP_MESSAGE_HTTP_RESPONSE, GST_RTSP_EINVAL); + + if (code) + *code = msg->type_data.response.code; + if (reason) + *reason = msg->type_data.response.reason; + if (version) + *version = msg->type_data.response.version; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_new_data: + * @msg: a location for the new #GstRTSPMessage + * @channel: the channel + * + * Create a new data #GstRTSPMessage with @channel and store the + * result message in @msg. Free with gst_rtsp_message_free(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_new_data (GstRTSPMessage ** msg, guint8 channel) +{ + GstRTSPMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + newmsg = g_new0 (GstRTSPMessage, 1); + + *msg = newmsg; + + return gst_rtsp_message_init_data (newmsg, channel); +} + +/** + * gst_rtsp_message_init_data: + * @msg: a #GstRTSPMessage + * @channel: a channel + * + * Initialize a new data #GstRTSPMessage for @channel. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_init_data (GstRTSPMessage * msg, guint8 channel) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + gst_rtsp_message_unset (msg); + + msg->type = GST_RTSP_MESSAGE_DATA; + msg->type_data.data.channel = channel; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_parse_data: + * @msg: a #GstRTSPMessage + * @channel: location to hold the channel + * + * Parse the data message @msg and store the channel in @channel. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_parse_data (GstRTSPMessage * msg, guint8 * channel) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (msg->type == GST_RTSP_MESSAGE_DATA, GST_RTSP_EINVAL); + + if (channel) + *channel = msg->type_data.data.channel; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_unset: + * @msg: a #GstRTSPMessage + * + * Unset the contents of @msg so that it becomes an uninitialized + * #GstRTSPMessage again. This function is mostly used in combination with + * gst_rtsp_message_init_request(), gst_rtsp_message_init_response() and + * gst_rtsp_message_init_data() on stack allocated #GstRTSPMessage structures. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_unset (GstRTSPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + switch (msg->type) { + case GST_RTSP_MESSAGE_INVALID: + break; + case GST_RTSP_MESSAGE_REQUEST: + case GST_RTSP_MESSAGE_HTTP_REQUEST: + g_free (msg->type_data.request.uri); + break; + case GST_RTSP_MESSAGE_RESPONSE: + case GST_RTSP_MESSAGE_HTTP_RESPONSE: + g_free (msg->type_data.response.reason); + break; + case GST_RTSP_MESSAGE_DATA: + break; + default: + g_return_val_if_reached (GST_RTSP_EINVAL); + } + + if (msg->hdr_fields != NULL) { + guint i; + + for (i = 0; i < msg->hdr_fields->len; i++) { + RTSPKeyValue *keyval = &g_array_index (msg->hdr_fields, RTSPKeyValue, i); + + g_free (keyval->value); + } + g_array_free (msg->hdr_fields, TRUE); + } + g_free (msg->body); + + memset (msg, 0, sizeof (GstRTSPMessage)); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_free: + * @msg: a #GstRTSPMessage + * + * Free the memory used by @msg. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_free (GstRTSPMessage * msg) +{ + GstRTSPResult res; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + res = gst_rtsp_message_unset (msg); + if (res == GST_RTSP_OK) + g_free (msg); + + return res; +} + +/** + * gst_rtsp_message_take_header: + * @msg: a #GstRTSPMessage + * @field: a #GstRTSPHeaderField + * @value: the value of the header + * + * Add a header with key @field and @value to @msg. This function takes + * ownership of @value. + * + * Returns: a #GstRTSPResult. + * + * Since: 0.10.23 + */ +GstRTSPResult +gst_rtsp_message_take_header (GstRTSPMessage * msg, GstRTSPHeaderField field, + gchar * value) +{ + RTSPKeyValue key_value; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (value != NULL, GST_RTSP_EINVAL); + + key_value.field = field; + key_value.value = value; + + g_array_append_val (msg->hdr_fields, key_value); + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_add_header: + * @msg: a #GstRTSPMessage + * @field: a #GstRTSPHeaderField + * @value: the value of the header + * + * Add a header with key @field and @value to @msg. This function takes a copy + * of @value. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_add_header (GstRTSPMessage * msg, GstRTSPHeaderField field, + const gchar * value) +{ + return gst_rtsp_message_take_header (msg, field, g_strdup (value)); +} + +/** + * gst_rtsp_message_remove_header: + * @msg: a #GstRTSPMessage + * @field: a #GstRTSPHeaderField + * @indx: the index of the header + * + * Remove the @indx header with key @field from @msg. If @indx equals -1, all + * headers will be removed. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_message_remove_header (GstRTSPMessage * msg, GstRTSPHeaderField field, + gint indx) +{ + GstRTSPResult res = GST_RTSP_ENOTIMPL; + guint i = 0; + gint cnt = 0; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + while (i < msg->hdr_fields->len) { + RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i); + + if (key_value->field == field && (indx == -1 || cnt++ == indx)) { + g_free (key_value->value); + g_array_remove_index (msg->hdr_fields, i); + res = GST_RTSP_OK; + if (indx != -1) + break; + } else { + i++; + } + } + return res; +} + +/** + * gst_rtsp_message_get_header: + * @msg: a #GstRTSPMessage + * @field: a #GstRTSPHeaderField + * @value: pointer to hold the result + * @indx: the index of the header + * + * Get the @indx header value with key @field from @msg. The result in @value + * stays valid as long as it remains present in @msg. + * + * Returns: #GST_RTSP_OK when @field was found, #GST_RTSP_ENOTIMPL if the key + * was not found. + */ +GstRTSPResult +gst_rtsp_message_get_header (const GstRTSPMessage * msg, + GstRTSPHeaderField field, gchar ** value, gint indx) +{ + guint i; + gint cnt = 0; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + /* no header initialized, there are no headers */ + if (msg->hdr_fields == NULL) + return GST_RTSP_ENOTIMPL; + + for (i = 0; i < msg->hdr_fields->len; i++) { + RTSPKeyValue *key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i); + + if (key_value->field == field && cnt++ == indx) { + if (value) + *value = key_value->value; + return GST_RTSP_OK; + } + } + + return GST_RTSP_ENOTIMPL; +} + +/** + * gst_rtsp_message_append_headers: + * @msg: a #GstRTSPMessage + * @str: a string + * + * Append the currently configured headers in @msg to the #GString @str suitable + * for transmission. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_append_headers (const GstRTSPMessage * msg, GString * str) +{ + guint i; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (str != NULL, GST_RTSP_EINVAL); + + for (i = 0; i < msg->hdr_fields->len; i++) { + RTSPKeyValue *key_value; + const gchar *keystr; + + key_value = &g_array_index (msg->hdr_fields, RTSPKeyValue, i); + keystr = gst_rtsp_header_as_text (key_value->field); + + g_string_append_printf (str, "%s: %s\r\n", keystr, key_value->value); + } + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_set_body: + * @msg: a #GstRTSPMessage + * @data: the data + * @size: the size of @data + * + * Set the body of @msg to a copy of @data. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_set_body (GstRTSPMessage * msg, const guint8 * data, + guint size) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + return gst_rtsp_message_take_body (msg, g_memdup (data, size), size); +} + +/** + * gst_rtsp_message_take_body: + * @msg: a #GstRTSPMessage + * @data: the data + * @size: the size of @data + * + * Set the body of @msg to @data and @size. This method takes ownership of + * @data. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_take_body (GstRTSPMessage * msg, guint8 * data, guint size) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL || size == 0, GST_RTSP_EINVAL); + + if (msg->body) + g_free (msg->body); + + msg->body = data; + msg->body_size = size; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_get_body: + * @msg: a #GstRTSPMessage + * @data: location for the data + * @size: location for the size of @data + * + * Get the body of @msg. @data remains valid for as long as @msg is valid and + * unchanged. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_get_body (const GstRTSPMessage * msg, guint8 ** data, + guint * size) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (size != NULL, GST_RTSP_EINVAL); + + *data = msg->body; + *size = msg->body_size; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_message_steal_body: + * @msg: a #GstRTSPMessage + * @data: location for the data + * @size: location for the size of @data + * + * Take the body of @msg and store it in @data and @size. After this method, + * the body and size of @msg will be set to #NULL and 0 respectively. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_steal_body (GstRTSPMessage * msg, guint8 ** data, guint * size) +{ + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (data != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (size != NULL, GST_RTSP_EINVAL); + + *data = msg->body; + *size = msg->body_size; + + msg->body = NULL; + msg->body_size = 0; + + return GST_RTSP_OK; +} + +static void +dump_key_value (gpointer data, gpointer user_data G_GNUC_UNUSED) +{ + RTSPKeyValue *key_value = (RTSPKeyValue *) data; + + g_print (" key: '%s', value: '%s'\n", + gst_rtsp_header_as_text (key_value->field), key_value->value); +} + +/** + * gst_rtsp_message_dump: + * @msg: a #GstRTSPMessage + * + * Dump the contents of @msg to stdout. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_message_dump (GstRTSPMessage * msg) +{ + guint8 *data; + guint size; + + g_return_val_if_fail (msg != NULL, GST_RTSP_EINVAL); + + switch (msg->type) { + case GST_RTSP_MESSAGE_REQUEST: + g_print ("RTSP request message %p\n", msg); + g_print (" request line:\n"); + g_print (" method: '%s'\n", + gst_rtsp_method_as_text (msg->type_data.request.method)); + g_print (" uri: '%s'\n", msg->type_data.request.uri); + g_print (" version: '%s'\n", + gst_rtsp_version_as_text (msg->type_data.request.version)); + g_print (" headers:\n"); + key_value_foreach (msg->hdr_fields, dump_key_value, NULL); + g_print (" body:\n"); + gst_rtsp_message_get_body (msg, &data, &size); + gst_util_dump_mem (data, size); + break; + case GST_RTSP_MESSAGE_RESPONSE: + g_print ("RTSP response message %p\n", msg); + g_print (" status line:\n"); + g_print (" code: '%d'\n", msg->type_data.response.code); + g_print (" reason: '%s'\n", msg->type_data.response.reason); + g_print (" version: '%s'\n", + gst_rtsp_version_as_text (msg->type_data.response.version)); + g_print (" headers:\n"); + key_value_foreach (msg->hdr_fields, dump_key_value, NULL); + gst_rtsp_message_get_body (msg, &data, &size); + g_print (" body: length %d\n", size); + gst_util_dump_mem (data, size); + break; + case GST_RTSP_MESSAGE_HTTP_REQUEST: + g_print ("HTTP request message %p\n", msg); + g_print (" request line:\n"); + g_print (" method: '%s'\n", + gst_rtsp_method_as_text (msg->type_data.request.method)); + g_print (" uri: '%s'\n", msg->type_data.request.uri); + g_print (" version: '%s'\n", + gst_rtsp_version_as_text (msg->type_data.request.version)); + g_print (" headers:\n"); + key_value_foreach (msg->hdr_fields, dump_key_value, NULL); + g_print (" body:\n"); + gst_rtsp_message_get_body (msg, &data, &size); + gst_util_dump_mem (data, size); + break; + case GST_RTSP_MESSAGE_HTTP_RESPONSE: + g_print ("HTTP response message %p\n", msg); + g_print (" status line:\n"); + g_print (" code: '%d'\n", msg->type_data.response.code); + g_print (" reason: '%s'\n", msg->type_data.response.reason); + g_print (" version: '%s'\n", + gst_rtsp_version_as_text (msg->type_data.response.version)); + g_print (" headers:\n"); + key_value_foreach (msg->hdr_fields, dump_key_value, NULL); + gst_rtsp_message_get_body (msg, &data, &size); + g_print (" body: length %d\n", size); + gst_util_dump_mem (data, size); + break; + case GST_RTSP_MESSAGE_DATA: + g_print ("RTSP data message %p\n", msg); + g_print (" channel: '%d'\n", msg->type_data.data.channel); + g_print (" size: '%d'\n", msg->body_size); + gst_rtsp_message_get_body (msg, &data, &size); + gst_util_dump_mem (data, size); + break; + default: + g_print ("unsupported message type %d\n", msg->type); + return GST_RTSP_EINVAL; + } + return GST_RTSP_OK; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.h new file mode 100644 index 0000000..dda1604 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspmessage.h @@ -0,0 +1,187 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_MESSAGE_H__ +#define __GST_RTSP_MESSAGE_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * GstRTSPMsgType: + * @GST_RTSP_MESSAGE_INVALID: invalid message type + * @GST_RTSP_MESSAGE_REQUEST: RTSP request message + * @GST_RTSP_MESSAGE_RESPONSE: RTSP response message + * @GST_RTSP_MESSAGE_HTTP_REQUEST: HTTP request message. Since 0.10.25 + * @GST_RTSP_MESSAGE_HTTP_RESPONSE: HTTP response message. Since 0.10.25 + * @GST_RTSP_MESSAGE_DATA: data message + * + * The type of a message. + */ +typedef enum +{ + GST_RTSP_MESSAGE_INVALID, + GST_RTSP_MESSAGE_REQUEST, + GST_RTSP_MESSAGE_RESPONSE, + GST_RTSP_MESSAGE_HTTP_REQUEST, + GST_RTSP_MESSAGE_HTTP_RESPONSE, + GST_RTSP_MESSAGE_DATA +} GstRTSPMsgType; + +typedef struct _GstRTSPMessage GstRTSPMessage; + +/** + * GstRTSPMessage: + * @type: the message type + * + * An RTSP message containing request, response or data messages. Depending on + * the @type, the appropriate structure may be accessed. + */ +struct _GstRTSPMessage +{ + GstRTSPMsgType type; + + union { + struct { + GstRTSPMethod method; + gchar *uri; + GstRTSPVersion version; + } request; + struct { + GstRTSPStatusCode code; + gchar *reason; + GstRTSPVersion version; + } response; + struct { + guint8 channel; + } data; + } type_data; + + /*< private >*/ + GArray *hdr_fields; + + guint8 *body; + guint body_size; +}; + +/* memory management */ +GstRTSPResult gst_rtsp_message_new (GstRTSPMessage **msg); +GstRTSPResult gst_rtsp_message_init (GstRTSPMessage *msg); +GstRTSPResult gst_rtsp_message_unset (GstRTSPMessage *msg); +GstRTSPResult gst_rtsp_message_free (GstRTSPMessage *msg); + +GstRTSPMsgType gst_rtsp_message_get_type (GstRTSPMessage *msg); + +/* request */ +GstRTSPResult gst_rtsp_message_new_request (GstRTSPMessage **msg, + GstRTSPMethod method, + const gchar *uri); +GstRTSPResult gst_rtsp_message_init_request (GstRTSPMessage *msg, + GstRTSPMethod method, + const gchar *uri); +GstRTSPResult gst_rtsp_message_parse_request (GstRTSPMessage *msg, + GstRTSPMethod *method, + const gchar **uri, + GstRTSPVersion *version); + +/* response */ +GstRTSPResult gst_rtsp_message_new_response (GstRTSPMessage **msg, + GstRTSPStatusCode code, + const gchar *reason, + const GstRTSPMessage *request); +GstRTSPResult gst_rtsp_message_init_response (GstRTSPMessage *msg, + GstRTSPStatusCode code, + const gchar *reason, + const GstRTSPMessage *request); +GstRTSPResult gst_rtsp_message_parse_response (GstRTSPMessage *msg, + GstRTSPStatusCode *code, + const gchar **reason, + GstRTSPVersion *version); + +/* data */ +GstRTSPResult gst_rtsp_message_new_data (GstRTSPMessage **msg, + guint8 channel); +GstRTSPResult gst_rtsp_message_init_data (GstRTSPMessage *msg, + guint8 channel); +GstRTSPResult gst_rtsp_message_parse_data (GstRTSPMessage *msg, + guint8 *channel); + +/* headers */ +GstRTSPResult gst_rtsp_message_add_header (GstRTSPMessage *msg, + GstRTSPHeaderField field, + const gchar *value); +GstRTSPResult gst_rtsp_message_take_header (GstRTSPMessage *msg, + GstRTSPHeaderField field, + gchar *value); +GstRTSPResult gst_rtsp_message_remove_header (GstRTSPMessage *msg, + GstRTSPHeaderField field, + gint indx); +GstRTSPResult gst_rtsp_message_get_header (const GstRTSPMessage *msg, + GstRTSPHeaderField field, + gchar **value, + gint indx); +GstRTSPResult gst_rtsp_message_append_headers (const GstRTSPMessage *msg, + GString *str); + +/* handling the body */ +GstRTSPResult gst_rtsp_message_set_body (GstRTSPMessage *msg, + const guint8 *data, + guint size); +GstRTSPResult gst_rtsp_message_take_body (GstRTSPMessage *msg, + guint8 *data, + guint size); +GstRTSPResult gst_rtsp_message_get_body (const GstRTSPMessage *msg, + guint8 **data, + guint *size); +GstRTSPResult gst_rtsp_message_steal_body (GstRTSPMessage *msg, + guint8 **data, + guint *size); + +/* debug */ +GstRTSPResult gst_rtsp_message_dump (GstRTSPMessage *msg); + +G_END_DECLS + +#endif /* __GST_RTSP_MESSAGE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.c new file mode 100644 index 0000000..0ad75c8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.c @@ -0,0 +1,272 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtsprange + * @short_description: dealing with time ranges + * + * Provides helper functions to deal with time ranges. + * + * Last reviewed on 2007-07-25 (0.10.14) + */ + + +#include +#include + +#include "gstrtsprange.h" + +/* npt-time = "now" | npt-sec | npt-hhmmss + * npt-sec = 1*DIGIT [ "." *DIGIT ] + * npt-hhmmss = npt-hh ":" npt-mm ":" npt-ss [ "." *DIGIT ] + * npt-hh = 1*DIGIT ; any positive number + * npt-mm = 1*2DIGIT ; 0-59 + * npt-ss = 1*2DIGIT ; 0-59 + */ +static GstRTSPResult +parse_npt_time (const gchar * str, GstRTSPTime * time) +{ + if (strncmp (str, "now", 3) == 0) { + time->type = GST_RTSP_TIME_NOW; + } else if (str[0] == '\0') { + time->type = GST_RTSP_TIME_END; + } else if (strstr (str, ":")) { + gfloat seconds; + gint hours, mins; + + sscanf (str, "%2d:%2d:%f", &hours, &mins, &seconds); + + time->type = GST_RTSP_TIME_SECONDS; + time->seconds = ((hours * 60) + mins) * 60 + seconds; + } else { + gfloat seconds; + + sscanf (str, "%f", &seconds); + + time->type = GST_RTSP_TIME_SECONDS; + time->seconds = seconds; + } + return GST_RTSP_OK; +} + +/* npt-range = ( npt-time "-" [ npt-time ] ) | ( "-" npt-time ) + */ +static GstRTSPResult +parse_npt_range (const gchar * str, GstRTSPTimeRange * range) +{ + GstRTSPResult res; + gchar *p; + + range->unit = GST_RTSP_RANGE_NPT; + + /* find '-' separator */ + p = strstr (str, "-"); + if (p == NULL) + return GST_RTSP_EINVAL; + + if ((res = parse_npt_time (str, &range->min)) != GST_RTSP_OK) + goto done; + + res = parse_npt_time (p + 1, &range->max); + +done: + return res; +} + +static GstRTSPResult +parse_clock_range (const gchar * str, GstRTSPTimeRange * range) +{ + return GST_RTSP_ENOTIMPL; +} + +static GstRTSPResult +parse_smpte_range (const gchar * str, GstRTSPTimeRange * range) +{ + return GST_RTSP_ENOTIMPL; +} + +/** + * gst_rtsp_range_parse: + * @rangestr: a range string to parse + * @range: location to hold the #GstRTSPTimeRange result + * + * Parse @rangestr to a #GstRTSPTimeRange. + * + * Returns: #GST_RTSP_OK on success. + */ +GstRTSPResult +gst_rtsp_range_parse (const gchar * rangestr, GstRTSPTimeRange ** range) +{ + GstRTSPResult ret; + GstRTSPTimeRange *res; + gchar *p; + + g_return_val_if_fail (rangestr != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (range != NULL, GST_RTSP_EINVAL); + + res = g_new0 (GstRTSPTimeRange, 1); + + p = (gchar *) rangestr; + /* first figure out the units of the range */ + if (g_str_has_prefix (p, "npt=")) { + ret = parse_npt_range (p + 4, res); + } else if (g_str_has_prefix (p, "clock=")) { + ret = parse_clock_range (p + 6, res); + } else if (g_str_has_prefix (p, "smpte=")) { + res->unit = GST_RTSP_RANGE_SMPTE; + ret = parse_smpte_range (p + 6, res); + } else if (g_str_has_prefix (p, "smpte-30-drop=")) { + res->unit = GST_RTSP_RANGE_SMPTE_30_DROP; + ret = parse_smpte_range (p + 14, res); + } else if (g_str_has_prefix (p, "smpte-25=")) { + res->unit = GST_RTSP_RANGE_SMPTE_25; + ret = parse_smpte_range (p + 9, res); + } else + goto invalid; + + if (ret != GST_RTSP_OK) + goto invalid; + + *range = res; + return ret; + + /* ERRORS */ +invalid: + { + gst_rtsp_range_free (res); + return GST_RTSP_EINVAL; + } +} + +static gboolean +npt_time_string (const GstRTSPTime * time, GString * string) +{ + gboolean res = TRUE;; + + switch (time->type) { + case GST_RTSP_TIME_SECONDS: + g_string_append_printf (string, "%f", time->seconds); + break; + case GST_RTSP_TIME_NOW: + g_string_append (string, "now"); + break; + case GST_RTSP_TIME_END: + break; + default: + res = FALSE; + break; + } + return res; +} + +static gboolean +npt_range_string (const GstRTSPTimeRange * range, GString * string) +{ + gboolean res; + + if (!(res = npt_time_string (&range->min, string))) + goto done; + + g_string_append (string, "-"); + + if (!(res = npt_time_string (&range->max, string))) + goto done; + +done: + return res; +} + +/** + * gst_rtsp_range_to_string: + * @range: a #GstRTSPTimeRange + * + * Convert @range into a string representation. + * + * Returns: The string representation of @range. g_free() after usage. + * + * Since: 0.10.23 + */ +gchar * +gst_rtsp_range_to_string (const GstRTSPTimeRange * range) +{ + gchar *result = NULL; + GString *string; + + g_return_val_if_fail (range != NULL, NULL); + + string = g_string_new (""); + + switch (range->unit) { + case GST_RTSP_RANGE_NPT: + g_string_append (string, "npt="); + if (!npt_range_string (range, string)) { + g_string_free (string, TRUE); + string = NULL; + } + break; + case GST_RTSP_RANGE_SMPTE: + case GST_RTSP_RANGE_SMPTE_30_DROP: + case GST_RTSP_RANGE_SMPTE_25: + case GST_RTSP_RANGE_CLOCK: + default: + g_warning ("time range unit not yet implemented"); + g_string_free (string, TRUE); + string = NULL; + break; + } + if (string) + result = g_string_free (string, FALSE); + + return result; +} + +/** + * gst_rtsp_range_free: + * @range: a #GstRTSPTimeRange + * + * Free the memory alocated by @range. + */ +void +gst_rtsp_range_free (GstRTSPTimeRange * range) +{ + g_free (range); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.h new file mode 100644 index 0000000..9d2c062 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsprange.h @@ -0,0 +1,121 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_RANGE_H__ +#define __GST_RTSP_RANGE_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * GstRTSPRangeUnit: + * @GST_RTSP_RANGE_SMPTE: SMPTE timecode + * @GST_RTSP_RANGE_SMPTE_30_DROP: 29.97 frames per second + * @GST_RTSP_RANGE_SMPTE_25: 25 frames per second + * @GST_RTSP_RANGE_NPT: Normal play time + * @GST_RTSP_RANGE_CLOCK: Absolute time expressed as ISO 8601 timestamps + * + * Different possible time range units. + */ +typedef enum +{ + GST_RTSP_RANGE_SMPTE, + GST_RTSP_RANGE_SMPTE_30_DROP, + GST_RTSP_RANGE_SMPTE_25, + GST_RTSP_RANGE_NPT, + GST_RTSP_RANGE_CLOCK +} GstRTSPRangeUnit; + +typedef struct _GstRTSPTimeRange GstRTSPTimeRange; +typedef struct _GstRTSPTime GstRTSPTime; + +/** + * GstRTSPTimeType: + * @GST_RTSP_TIME_SECONDS: seconds + * @GST_RTSP_TIME_NOW: now + * @GST_RTSP_TIME_END: end + * + * Possible time types. + */ +typedef enum { + GST_RTSP_TIME_SECONDS, + GST_RTSP_TIME_NOW, + GST_RTSP_TIME_END +} GstRTSPTimeType; + +/** + * GstRTSPTime: + * @type: the time of the time + * @seconds: seconds when @type is GST_RTSP_TIME_SECONDS + * + * A time indication. + */ +struct _GstRTSPTime { + GstRTSPTimeType type; + gdouble seconds; +}; + +/** + * GstRTSPTimeRange: + * @unit: the time units used + * @min: the minimum interval + * @max: the maximum interval + * + * A time range. + */ +struct _GstRTSPTimeRange { + GstRTSPRangeUnit unit; + + GstRTSPTime min; + GstRTSPTime max; +}; + +GstRTSPResult gst_rtsp_range_parse (const gchar *rangestr, GstRTSPTimeRange **range); +gchar * gst_rtsp_range_to_string (const GstRTSPTimeRange *range); +void gst_rtsp_range_free (GstRTSPTimeRange *range); + +G_END_DECLS + +#endif /* __GST_RTSP_RANGE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.c new file mode 100644 index 0000000..de3085e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.c @@ -0,0 +1,717 @@ +/* GStreamer + * Copyright (C) <2005,2006,2007> Wim Taymans + * <2007> Peter Kjellerstedt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtsptransport + * @short_description: dealing with RTSP transports + * + * Provides helper functions to deal with RTSP transport strings. + * + * Last reviewed on 2007-07-25 (0.10.14) + */ + +#include +#include + +#include "gstrtsptransport.h" + +#define MAX_MANAGERS 2 + +typedef enum +{ + RTSP_TRANSPORT_DELIVERY = 1 << 0, /* multicast | unicast */ + RTSP_TRANSPORT_DESTINATION = 1 << 1, + RTSP_TRANSPORT_SOURCE = 1 << 2, + RTSP_TRANSPORT_INTERLEAVED = 1 << 3, + RTSP_TRANSPORT_APPEND = 1 << 4, + RTSP_TRANSPORT_TTL = 1 << 5, + RTSP_TRANSPORT_LAYERS = 1 << 6, + RTSP_TRANSPORT_PORT = 1 << 7, + RTSP_TRANSPORT_CLIENT_PORT = 1 << 8, + RTSP_TRANSPORT_SERVER_PORT = 1 << 9, + RTSP_TRANSPORT_SSRC = 1 << 10, + RTSP_TRANSPORT_MODE = 1 << 11, +} RTSPTransportParameter; + +typedef struct +{ + const gchar *name; + const GstRTSPTransMode mode; + const gchar *gst_mime; + const gchar *manager[MAX_MANAGERS]; +} GstRTSPTransMap; + +static const GstRTSPTransMap transports[] = { + {"rtp", GST_RTSP_TRANS_RTP, "application/x-rtp", {"gstrtpbin", "rtpdec"}}, + {"x-real-rdt", GST_RTSP_TRANS_RDT, "application/x-rdt", {"rdtmanager", NULL}}, + {"x-pn-tng", GST_RTSP_TRANS_RDT, "application/x-rdt", {"rdtmanager", NULL}}, + {NULL, GST_RTSP_TRANS_UNKNOWN, NULL, {NULL, NULL}} +}; + +typedef struct +{ + const gchar *name; + const GstRTSPProfile profile; +} RTSPProfileMap; + +static const RTSPProfileMap profiles[] = { + {"avp", GST_RTSP_PROFILE_AVP}, + {"savp", GST_RTSP_PROFILE_SAVP}, + {NULL, GST_RTSP_PROFILE_UNKNOWN} +}; + +typedef struct +{ + const gchar *name; + const GstRTSPLowerTrans ltrans; +} RTSPLTransMap; + +static const RTSPLTransMap ltrans[] = { + {"udp", GST_RTSP_LOWER_TRANS_UDP}, + {"mcast", GST_RTSP_LOWER_TRANS_UDP_MCAST}, + {"tcp", GST_RTSP_LOWER_TRANS_TCP}, + {NULL, GST_RTSP_LOWER_TRANS_UNKNOWN} +}; + + +GType +gst_rtsp_lower_trans_get_type (void) +{ + static volatile gsize rtsp_lower_trans_type = 0; + static const GFlagsValue rtsp_lower_trans[] = { + {GST_RTSP_LOWER_TRANS_UDP, "GST_RTSP_LOWER_TRANS_UDP", "udp-unicast"}, + {GST_RTSP_LOWER_TRANS_UDP_MCAST, "GST_RTSP_LOWER_TRANS_UDP_MCAST", + "udp-multicast"}, + {GST_RTSP_LOWER_TRANS_TCP, "GST_RTSP_LOWER_TRANS_TCP", "tcp"}, + {GST_RTSP_LOWER_TRANS_HTTP, "GST_RTSP_LOWER_TRANS_HTTP", "http"}, + {0, NULL, NULL}, + }; + + if (g_once_init_enter (&rtsp_lower_trans_type)) { + GType tmp = g_flags_register_static ("GstRTSPLowerTrans", rtsp_lower_trans); + g_once_init_leave (&rtsp_lower_trans_type, tmp); + } + + return (GType) rtsp_lower_trans_type; +} + +#define RTSP_TRANSPORT_PARAMETER_IS_UNIQUE(param) \ +G_STMT_START { \ + if ((transport_params & (param)) != 0) \ + goto invalid_transport; \ + transport_params |= (param); \ +} G_STMT_END + +/** + * gst_rtsp_transport_new: + * @transport: location to hold the new #GstRTSPTransport + * + * Allocate a new initialized #GstRTSPTransport. Use gst_rtsp_transport_free() + * after usage. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_transport_new (GstRTSPTransport ** transport) +{ + GstRTSPTransport *trans; + + g_return_val_if_fail (transport != NULL, GST_RTSP_EINVAL); + + trans = g_new0 (GstRTSPTransport, 1); + + *transport = trans; + + return gst_rtsp_transport_init (trans); +} + +/** + * gst_rtsp_transport_init: + * @transport: a #GstRTSPTransport + * + * Initialize @transport so that it can be used. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_transport_init (GstRTSPTransport * transport) +{ + g_return_val_if_fail (transport != NULL, GST_RTSP_EINVAL); + + g_free (transport->destination); + g_free (transport->source); + + memset (transport, 0, sizeof (GstRTSPTransport)); + + transport->trans = GST_RTSP_TRANS_RTP; + transport->profile = GST_RTSP_PROFILE_AVP; + transport->lower_transport = GST_RTSP_LOWER_TRANS_UDP_MCAST; + transport->mode_play = TRUE; + transport->mode_record = FALSE; + transport->interleaved.min = -1; + transport->interleaved.max = -1; + transport->port.min = -1; + transport->port.max = -1; + transport->client_port.min = -1; + transport->client_port.max = -1; + transport->server_port.min = -1; + transport->server_port.max = -1; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_transport_get_mime: + * @trans: a #GstRTSPTransMode + * @mime: location to hold the result + * + * Get the mime type of the transport mode @trans. This mime type is typically + * used to generate #GstCaps on buffers. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_transport_get_mime (GstRTSPTransMode trans, const gchar ** mime) +{ + gint i; + + g_return_val_if_fail (mime != NULL, GST_RTSP_EINVAL); + + for (i = 0; transports[i].name; i++) + if (transports[i].mode == trans) + break; + *mime = transports[i].gst_mime; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_transport_get_manager: + * @trans: a #GstRTSPTransMode + * @manager: location to hold the result + * @option: option index. + * + * Get the #GStreamer element that can handle the buffers transported over + * @trans. + * + * It is possible that there are several managers available, use @option to + * selected one. + * + * @manager will contain an element name or #NULL when no manager is + * needed/available for @trans. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_transport_get_manager (GstRTSPTransMode trans, const gchar ** manager, + guint option) +{ + gint i; + + g_return_val_if_fail (manager != NULL, GST_RTSP_EINVAL); + + for (i = 0; transports[i].name; i++) + if (transports[i].mode == trans) + break; + + if (option < MAX_MANAGERS) + *manager = transports[i].manager[option]; + else + *manager = NULL; + + return GST_RTSP_OK; +} + +static void +parse_mode (GstRTSPTransport * transport, const gchar * str) +{ + transport->mode_play = (strstr (str, "play") != NULL); + transport->mode_record = (strstr (str, "record") != NULL); +} + +static gboolean +check_range (const gchar * str, gchar ** tmp, gint * range) +{ + glong range_val; + + range_val = strtol (str, tmp, 10); + if (range_val >= G_MININT && range_val <= G_MAXINT) { + *range = range_val; + return TRUE; + } else { + return FALSE; + } +} + +static gboolean +parse_range (const gchar * str, GstRTSPRange * range) +{ + gchar *minus; + gchar *tmp; + + /* even though strtol() allows white space, plus and minus in front of + * the number, we do not allow it + */ + if (g_ascii_isspace (*str) || *str == '+' || *str == '-') + goto invalid_range; + + minus = strstr (str, "-"); + if (minus) { + if (g_ascii_isspace (minus[1]) || minus[1] == '+' || minus[1] == '-') + goto invalid_range; + + if (!check_range (str, &tmp, &range->min) || str == tmp || tmp != minus) + goto invalid_range; + + if (!check_range (minus + 1, &tmp, &range->max) || (*tmp && *tmp != ';')) + goto invalid_range; + } else { + if (!check_range (str, &tmp, &range->min) || str == tmp || + (*tmp && *tmp != ';')) + goto invalid_range; + + range->max = -1; + } + + return TRUE; + +invalid_range: + { + range->min = -1; + range->max = -1; + return FALSE; + } +} + +static gchar * +range_as_text (const GstRTSPRange * range) +{ + if (range->min < 0) + return NULL; + else if (range->max < 0) + return g_strdup_printf ("%d", range->min); + else + return g_strdup_printf ("%d-%d", range->min, range->max); +} + +static const gchar * +rtsp_transport_mode_as_text (const GstRTSPTransport * transport) +{ + gint i; + + for (i = 0; transports[i].name; i++) + if (transports[i].mode == transport->trans) + return transports[i].name; + + return NULL; +} + +static const gchar * +rtsp_transport_profile_as_text (const GstRTSPTransport * transport) +{ + gint i; + + for (i = 0; profiles[i].name; i++) + if (profiles[i].profile == transport->profile) + return profiles[i].name; + + return NULL; +} + +static const gchar * +rtsp_transport_ltrans_as_text (const GstRTSPTransport * transport) +{ + gint i; + + /* need to special case GST_RTSP_LOWER_TRANS_UDP_MCAST */ + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) + return "udp"; + + for (i = 0; ltrans[i].name; i++) + if (ltrans[i].ltrans == transport->lower_transport) + return ltrans[i].name; + + return NULL; +} + +#define IS_VALID_PORT_RANGE(range) \ + (range.min >= 0 && range.min < 65536 && range.max < 65536) + +#define IS_VALID_INTERLEAVE_RANGE(range) \ + (range.min >= 0 && range.min < 256 && range.max < 256) + +/** + * gst_rtsp_transport_parse: + * @str: a transport string + * @transport: a #GstRTSPTransport + * + * Parse the RTSP transport string @str into @transport. + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_transport_parse (const gchar * str, GstRTSPTransport * transport) +{ + gchar **split, *down, **transp = NULL; + guint transport_params = 0; + gint i, count; + + g_return_val_if_fail (transport != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (str != NULL, GST_RTSP_EINVAL); + + gst_rtsp_transport_init (transport); + + /* case insensitive */ + down = g_ascii_strdown (str, -1); + + split = g_strsplit (down, ";", 0); + g_free (down); + + /* First field contains the transport/profile/lower_transport */ + if (split[0] == NULL) + goto invalid_transport; + + transp = g_strsplit (split[0], "/", 0); + + if (transp[0] == NULL || transp[1] == NULL) + goto invalid_transport; + + for (i = 0; transports[i].name; i++) + if (strcmp (transp[0], transports[i].name) == 0) + break; + transport->trans = transports[i].mode; + + if (transport->trans != GST_RTSP_TRANS_RDT) { + for (i = 0; profiles[i].name; i++) + if (strcmp (transp[1], profiles[i].name) == 0) + break; + transport->profile = profiles[i].profile; + count = 2; + } else { + /* RDT has transport/lower_transport */ + transport->profile = GST_RTSP_PROFILE_AVP; + count = 1; + } + + if (transp[count] != NULL) { + for (i = 0; ltrans[i].name; i++) + if (strcmp (transp[count], ltrans[i].name) == 0) + break; + transport->lower_transport = ltrans[i].ltrans; + } else { + /* specifying the lower transport is optional */ + if (transport->trans == GST_RTSP_TRANS_RTP && + transport->profile == GST_RTSP_PROFILE_AVP) + transport->lower_transport = GST_RTSP_LOWER_TRANS_UDP_MCAST; + else + transport->lower_transport = GST_RTSP_LOWER_TRANS_UNKNOWN; + } + + g_strfreev (transp); + transp = NULL; + + if (transport->trans == GST_RTSP_TRANS_UNKNOWN || + transport->profile == GST_RTSP_PROFILE_UNKNOWN || + transport->lower_transport == GST_RTSP_LOWER_TRANS_UNKNOWN) + goto unsupported_transport; + + i = 1; + while (split[i]) { + if (strcmp (split[i], "multicast") == 0) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_DELIVERY); + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_TCP) + goto invalid_transport; + transport->lower_transport = GST_RTSP_LOWER_TRANS_UDP_MCAST; + } else if (strcmp (split[i], "unicast") == 0) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_DELIVERY); + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) + transport->lower_transport = GST_RTSP_LOWER_TRANS_UDP; + } else if (g_str_has_prefix (split[i], "destination=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_DESTINATION); + transport->destination = g_strdup (split[i] + 12); + } else if (g_str_has_prefix (split[i], "source=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_SOURCE); + transport->source = g_strdup (split[i] + 7); + } else if (g_str_has_prefix (split[i], "layers=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_LAYERS); + transport->layers = strtoul (split[i] + 7, NULL, 10); + } else if (g_str_has_prefix (split[i], "mode=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_MODE); + parse_mode (transport, split[i] + 5); + if (!transport->mode_play && !transport->mode_record) + goto invalid_transport; + } else if (strcmp (split[i], "append") == 0) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_APPEND); + transport->append = TRUE; + } else if (g_str_has_prefix (split[i], "interleaved=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_INTERLEAVED); + parse_range (split[i] + 12, &transport->interleaved); + if (!IS_VALID_INTERLEAVE_RANGE (transport->interleaved)) + goto invalid_transport; + } else if (g_str_has_prefix (split[i], "ttl=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_TTL); + transport->ttl = strtoul (split[i] + 4, NULL, 10); + if (transport->ttl >= 256) + goto invalid_transport; + } else if (g_str_has_prefix (split[i], "port=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_PORT); + if (parse_range (split[i] + 5, &transport->port)) { + if (!IS_VALID_PORT_RANGE (transport->port)) + goto invalid_transport; + } + } else if (g_str_has_prefix (split[i], "client_port=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_CLIENT_PORT); + if (parse_range (split[i] + 12, &transport->client_port)) { + if (!IS_VALID_PORT_RANGE (transport->client_port)) + goto invalid_transport; + } + } else if (g_str_has_prefix (split[i], "server_port=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_SERVER_PORT); + if (parse_range (split[i] + 12, &transport->server_port)) { + if (!IS_VALID_PORT_RANGE (transport->server_port)) + goto invalid_transport; + } + } else if (g_str_has_prefix (split[i], "ssrc=")) { + RTSP_TRANSPORT_PARAMETER_IS_UNIQUE (RTSP_TRANSPORT_SSRC); + transport->ssrc = strtoul (split[i] + 5, NULL, 16); + } else { + /* unknown field... */ + g_warning ("unknown transport field \"%s\"", split[i]); + } + i++; + } + g_strfreev (split); + + return GST_RTSP_OK; + +unsupported_transport: + { + g_strfreev (split); + return GST_RTSP_ERROR; + } +invalid_transport: + { + g_strfreev (transp); + g_strfreev (split); + return GST_RTSP_EINVAL; + } +} + +/** + * gst_rtsp_transport_as_text: + * @transport: a #GstRTSPTransport + * + * Convert @transport into a string that can be used to signal the transport in + * an RTSP SETUP response. + * + * Returns: a string describing the RTSP transport or #NULL when the transport + * is invalid. + */ +gchar * +gst_rtsp_transport_as_text (GstRTSPTransport * transport) +{ + GPtrArray *strs; + gchar *res; + const gchar *tmp; + + g_return_val_if_fail (transport != NULL, NULL); + + strs = g_ptr_array_new (); + + /* add the transport specifier */ + if ((tmp = rtsp_transport_mode_as_text (transport)) == NULL) + goto invalid_transport; + g_ptr_array_add (strs, g_ascii_strup (tmp, -1)); + + g_ptr_array_add (strs, g_strdup ("/")); + + if ((tmp = rtsp_transport_profile_as_text (transport)) == NULL) + goto invalid_transport; + g_ptr_array_add (strs, g_ascii_strup (tmp, -1)); + + if (transport->trans != GST_RTSP_TRANS_RTP || + transport->profile != GST_RTSP_PROFILE_AVP || + transport->lower_transport == GST_RTSP_LOWER_TRANS_TCP) { + g_ptr_array_add (strs, g_strdup ("/")); + + if ((tmp = rtsp_transport_ltrans_as_text (transport)) == NULL) + goto invalid_transport; + + g_ptr_array_add (strs, g_ascii_strup (tmp, -1)); + } + + /* + * the order of the following parameters is the same as the one specified in + * RFC 2326 to please some weird RTSP clients that require it + */ + + /* add the unicast/multicast parameter */ + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST) + g_ptr_array_add (strs, g_strdup (";multicast")); + else + g_ptr_array_add (strs, g_strdup (";unicast")); + + /* add the destination parameter */ + if (transport->destination != NULL) { + g_ptr_array_add (strs, g_strdup (";destination=")); + g_ptr_array_add (strs, g_strdup (transport->destination)); + } + + /* add the source parameter */ + if (transport->source != NULL) { + g_ptr_array_add (strs, g_strdup (";source=")); + g_ptr_array_add (strs, g_strdup (transport->source)); + } + + /* add the interleaved parameter */ + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_TCP && + transport->interleaved.min >= 0) { + if (transport->interleaved.min < 256 && transport->interleaved.max < 256) { + g_ptr_array_add (strs, g_strdup (";interleaved=")); + g_ptr_array_add (strs, range_as_text (&transport->interleaved)); + } else + goto invalid_transport; + } + + /* add the append parameter */ + if (transport->mode_record && transport->append) + g_ptr_array_add (strs, g_strdup (";append")); + + /* add the ttl parameter */ + if (transport->lower_transport == GST_RTSP_LOWER_TRANS_UDP_MCAST && + transport->ttl != 0) { + if (transport->ttl < 256) { + g_ptr_array_add (strs, g_strdup (";ttl=")); + g_ptr_array_add (strs, g_strdup_printf ("%u", transport->ttl)); + } else + goto invalid_transport; + } + + /* add the layers parameter */ + if (transport->layers != 0) { + g_ptr_array_add (strs, g_strdup (";layers=")); + g_ptr_array_add (strs, g_strdup_printf ("%u", transport->layers)); + } + + /* add the port parameter */ + if (transport->lower_transport != GST_RTSP_LOWER_TRANS_TCP) { + if (transport->trans == GST_RTSP_TRANS_RTP && transport->port.min >= 0) { + if (transport->port.min < 65536 && transport->port.max < 65536) { + g_ptr_array_add (strs, g_strdup (";port=")); + g_ptr_array_add (strs, range_as_text (&transport->port)); + } else + goto invalid_transport; + } + + /* add the client_port parameter */ + if (transport->trans == GST_RTSP_TRANS_RTP + && transport->client_port.min >= 0) { + if (transport->client_port.min < 65536 + && transport->client_port.max < 65536) { + g_ptr_array_add (strs, g_strdup (";client_port=")); + g_ptr_array_add (strs, range_as_text (&transport->client_port)); + } else + goto invalid_transport; + } + + /* add the server_port parameter */ + if (transport->trans == GST_RTSP_TRANS_RTP + && transport->server_port.min >= 0) { + if (transport->server_port.min < 65536 + && transport->server_port.max < 65536) { + g_ptr_array_add (strs, g_strdup (";server_port=")); + g_ptr_array_add (strs, range_as_text (&transport->server_port)); + } else + goto invalid_transport; + } + } + + /* add the ssrc parameter */ + if (transport->lower_transport != GST_RTSP_LOWER_TRANS_UDP_MCAST && + transport->ssrc != 0) { + g_ptr_array_add (strs, g_strdup (";ssrc=")); + g_ptr_array_add (strs, g_strdup_printf ("%08X", transport->ssrc)); + } + + /* add the mode parameter */ + if (transport->mode_play && transport->mode_record) + g_ptr_array_add (strs, g_strdup (";mode=\"PLAY,RECORD\"")); + else if (transport->mode_record) + g_ptr_array_add (strs, g_strdup (";mode=\"RECORD\"")); + else if (transport->mode_play) + g_ptr_array_add (strs, g_strdup (";mode=\"PLAY\"")); + + /* add a terminating NULL */ + g_ptr_array_add (strs, NULL); + + res = g_strjoinv (NULL, (gchar **) strs->pdata); + g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE)); + + return res; + +invalid_transport: + { + g_ptr_array_add (strs, NULL); + g_strfreev ((gchar **) g_ptr_array_free (strs, FALSE)); + return NULL; + } +} + +/** + * gst_rtsp_transport_free: + * @transport: a #GstRTSPTransport + * + * Free the memory used by @transport. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_transport_free (GstRTSPTransport * transport) +{ + g_return_val_if_fail (transport != NULL, GST_RTSP_EINVAL); + + gst_rtsp_transport_init (transport); + g_free (transport); + + return GST_RTSP_OK; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.h new file mode 100644 index 0000000..995d753 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtsptransport.h @@ -0,0 +1,174 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_TRANSPORT_H__ +#define __GST_RTSP_TRANSPORT_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstRTSPTransMode: + * @GST_RTSP_TRANS_UNKNOWN: invalid tansport mode + * @GST_RTSP_TRANS_RTP: transfer RTP data + * @GST_RTSP_TRANS_RDT: transfer RDT (RealMedia) data + * + * The transfer mode to use. + */ +typedef enum { + GST_RTSP_TRANS_UNKNOWN = 0, + GST_RTSP_TRANS_RTP = (1 << 0), + GST_RTSP_TRANS_RDT = (1 << 1) +} GstRTSPTransMode; + +/** + * GstRTSPProfile: + * @GST_RTSP_PROFILE_UNKNOWN: invalid profile + * @GST_RTSP_PROFILE_AVP: the Audio/Visual profile + * @GST_RTSP_PROFILE_SAVP: the secure Audio/Visual profile + * + * The transfer profile to use. + */ +typedef enum { + GST_RTSP_PROFILE_UNKNOWN = 0, + GST_RTSP_PROFILE_AVP = (1 << 0), + GST_RTSP_PROFILE_SAVP = (1 << 1) +} GstRTSPProfile; + +/** + * GstRTSPLowerTrans: + * @GST_RTSP_LOWER_TRANS_UNKNOWN: invalid transport flag + * @GST_RTSP_LOWER_TRANS_UDP: stream data over UDP + * @GST_RTSP_LOWER_TRANS_UDP_MCAST: stream data over UDP multicast + * @GST_RTSP_LOWER_TRANS_TCP: stream data over TCP + * @GST_RTSP_LOWER_TRANS_HTTP: stream data tunneled over HTTP. Since: 0.10.23 + * + * The different transport methods. + */ +typedef enum { + GST_RTSP_LOWER_TRANS_UNKNOWN = 0, + GST_RTSP_LOWER_TRANS_UDP = (1 << 0), + GST_RTSP_LOWER_TRANS_UDP_MCAST = (1 << 1), + GST_RTSP_LOWER_TRANS_TCP = (1 << 2), + GST_RTSP_LOWER_TRANS_HTTP = (1 << 4) +} GstRTSPLowerTrans; + +#define GST_TYPE_RTSP_LOWER_TRANS (gst_rtsp_lower_trans_get_type()) +GType gst_rtsp_lower_trans_get_type (void); + +typedef struct _GstRTSPRange GstRTSPRange; +typedef struct _GstRTSPTransport GstRTSPTransport; + +/** + * GstRTSPRange: + * @min: minimum value of the range + * @max: maximum value of the range + * + * A type to specify a range. + */ + +struct _GstRTSPRange { + gint min; + gint max; +}; + +/** + * GstRTSPTransport: + * @trans: the transport mode + * @profile: the tansport profile + * @lower_transport: the lower transport + * @destination: the destination ip/hostname + * @source: the source ip/hostname + * @layers: the number of layers + * @mode_play: if play mode was selected + * @mode_record: if record mode was selected + * @append: is append mode was selected + * @interleaved: the interleave range + * @ttl: the time to live for multicast UDP + * @port: the port pair for multicast sessions + * @client_port: the client port pair for receiving data + * @server_port: the server port pair for receiving data + * @ssrc: the ssrc that the sender/receiver will use + * + * A structure holding the RTSP transport values. + */ + +struct _GstRTSPTransport { + GstRTSPTransMode trans; + GstRTSPProfile profile; + GstRTSPLowerTrans lower_transport; + + gchar *destination; + gchar *source; + guint layers; + gboolean mode_play; + gboolean mode_record; + gboolean append; + GstRTSPRange interleaved; + + /* multicast specific */ + guint ttl; + + /* UDP specific */ + GstRTSPRange port; + GstRTSPRange client_port; + GstRTSPRange server_port; + /* RTP specific */ + guint ssrc; + +}; + +GstRTSPResult gst_rtsp_transport_new (GstRTSPTransport **transport); +GstRTSPResult gst_rtsp_transport_init (GstRTSPTransport *transport); + +GstRTSPResult gst_rtsp_transport_parse (const gchar *str, GstRTSPTransport *transport); +gchar* gst_rtsp_transport_as_text (GstRTSPTransport *transport); + +GstRTSPResult gst_rtsp_transport_get_mime (GstRTSPTransMode trans, const gchar **mime); +GstRTSPResult gst_rtsp_transport_get_manager (GstRTSPTransMode trans, const gchar **manager, guint option); + +GstRTSPResult gst_rtsp_transport_free (GstRTSPTransport *transport); + +G_END_DECLS + +#endif /* __GST_RTSP_TRANSPORT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.c new file mode 100644 index 0000000..6973e09 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.c @@ -0,0 +1,416 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstrtspurl + * @short_description: handling RTSP urls + * + * Provides helper functions to handle RTSP urls. + * + * Last reviewed on 2007-07-25 (0.10.14) + */ + +#include +#include + +#include "gstrtspurl.h" + +GType +gst_rtsp_url_get_type (void) +{ + static volatile gsize url_type = 0; + + if (g_once_init_enter (&url_type)) { + GType tmp = g_boxed_type_register_static ("GstRTSPUrl", + (GBoxedCopyFunc) gst_rtsp_url_copy, (GBoxedFreeFunc) gst_rtsp_url_free); + g_once_init_leave (&url_type, tmp); + } + + return (GType) url_type; +} + +static const struct +{ + const char scheme[6]; + GstRTSPLowerTrans transports; +} rtsp_schemes_map[] = { + { + "rtsp", GST_RTSP_LOWER_TRANS_TCP | GST_RTSP_LOWER_TRANS_UDP | + GST_RTSP_LOWER_TRANS_UDP_MCAST}, { + "rtspu", GST_RTSP_LOWER_TRANS_UDP | GST_RTSP_LOWER_TRANS_UDP_MCAST}, { + "rtspt", GST_RTSP_LOWER_TRANS_TCP}, { + "rtsph", GST_RTSP_LOWER_TRANS_HTTP | GST_RTSP_LOWER_TRANS_TCP} +}; + +/* format is rtsp[u]://[user:passwd@]host[:port]/abspath[?query] where host + * is a host name, an IPv4 dotted decimal address ("aaa.bbb.ccc.ddd") or an + * [IPv6] address ("[aabb:ccdd:eeff:gghh::sstt]" note the brackets around the + * address to allow the distinction between ':' as an IPv6 hexgroup separator + * and as a host/port separator) */ + +/** + * gst_rtsp_url_parse: + * @urlstr: the url string to parse + * @url: location to hold the result. + * + * Parse the RTSP @urlstr into a newly allocated #GstRTSPUrl. Free after usage + * with gst_rtsp_url_free(). + * + * Returns: a #GstRTSPResult. + */ +GstRTSPResult +gst_rtsp_url_parse (const gchar * urlstr, GstRTSPUrl ** url) +{ + GstRTSPUrl *res; + gchar *p, *delim, *at, *col; + gchar *host_end = NULL; + guint i; + + g_return_val_if_fail (urlstr != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL); + + res = g_new0 (GstRTSPUrl, 1); + + p = (gchar *) urlstr; + + col = strstr (p, "://"); + if (col == NULL) + goto invalid; + + for (i = 0; i < G_N_ELEMENTS (rtsp_schemes_map); i++) { + if (g_ascii_strncasecmp (rtsp_schemes_map[i].scheme, p, col - p) == 0) { + res->transports = rtsp_schemes_map[i].transports; + p = col + 3; + break; + } + } + + if (res->transports == GST_RTSP_LOWER_TRANS_UNKNOWN) + goto invalid; + + delim = strpbrk (p, "/?"); + at = strchr (p, '@'); + + if (at && delim && at > delim) + at = NULL; + + if (at) { + col = strchr (p, ':'); + + /* must have a ':' and it must be before the '@' */ + if (col == NULL || col > at) + goto invalid; + + res->user = g_strndup (p, col - p); + col++; + res->passwd = g_strndup (col, at - col); + + /* move to host */ + p = at + 1; + } + + if (*p == '[') { + res->family = GST_RTSP_FAM_INET6; + + /* we have an IPv6 address in the URL, find the ending ] which must be + * before any delimiter */ + host_end = strchr (++p, ']'); + if (!host_end || (delim && host_end >= delim)) + goto invalid; + + /* a port specifier must follow the address immediately */ + col = host_end[1] == ':' ? host_end + 1 : NULL; + } else { + res->family = GST_RTSP_FAM_INET; + + col = strchr (p, ':'); + + /* we have a ':' and a delimiter but the ':' is after the delimiter, it's + * not really part of the hostname */ + if (col && delim && col >= delim) + col = NULL; + + host_end = col ? col : delim; + } + + if (!host_end) + res->host = g_strdup (p); + else { + res->host = g_strndup (p, host_end - p); + + if (col) { + res->port = strtoul (col + 1, NULL, 10); + } else { + /* no port specified, set to 0. gst_rtsp_url_get_port() will return the + * default port */ + res->port = 0; + } + } + p = delim; + + if (p && *p == '/') { + delim = strchr (p, '?'); + if (!delim) + res->abspath = g_strdup (p); + else + res->abspath = g_strndup (p, delim - p); + p = delim; + } else { + res->abspath = g_strdup ("/"); + } + + if (p && *p == '?') + res->query = g_strdup (p + 1); + + *url = res; + + return GST_RTSP_OK; + + /* ERRORS */ +invalid: + { + gst_rtsp_url_free (res); + return GST_RTSP_EINVAL; + } +} + +/** + * gst_rtsp_url_copy: + * @url: a #GstRTSPUrl + * + * Make a copy of @url. + * + * Returns: a copy of @url. Free with gst_rtsp_url_free () after usage. + * + * Since: 0.10.22 + */ +GstRTSPUrl * +gst_rtsp_url_copy (const GstRTSPUrl * url) +{ + GstRTSPUrl *res; + + g_return_val_if_fail (url != NULL, NULL); + + res = g_new0 (GstRTSPUrl, 1); + + res->transports = url->transports; + res->family = url->family; + res->user = g_strdup (url->user); + res->passwd = g_strdup (url->passwd); + res->host = g_strdup (url->host); + res->port = url->port; + res->abspath = g_strdup (url->abspath); + res->query = g_strdup (url->query); + + return res; +} + +/** + * gst_rtsp_url_free: + * @url: a #GstRTSPUrl + * + * Free the memory used by @url. + */ +void +gst_rtsp_url_free (GstRTSPUrl * url) +{ + if (url == NULL) + return; + + g_free (url->user); + g_free (url->passwd); + g_free (url->host); + g_free (url->abspath); + g_free (url->query); + g_free (url); +} + +/** + * gst_rtsp_url_set_port: + * @url: a #GstRTSPUrl + * @port: the port + * + * Set the port number in @url to @port. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_url_set_port (GstRTSPUrl * url, guint16 port) +{ + g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL); + + url->port = port; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_url_get_port: + * @url: a #GstRTSPUrl + * @port: location to hold the port + * + * Get the port number of @url. + * + * Returns: #GST_RTSP_OK. + */ +GstRTSPResult +gst_rtsp_url_get_port (const GstRTSPUrl * url, guint16 * port) +{ + g_return_val_if_fail (url != NULL, GST_RTSP_EINVAL); + g_return_val_if_fail (port != NULL, GST_RTSP_EINVAL); + + /* if a port was specified, use that else use the default port. */ + if (url->port != 0) + *port = url->port; + else + *port = GST_RTSP_DEFAULT_PORT; + + return GST_RTSP_OK; +} + +/** + * gst_rtsp_url_get_request_uri: + * @url: a #GstRTSPUrl + * + * Get a newly allocated string describing the request URI for @url. + * + * Returns: a string with the request URI. g_free() after usage. + */ +gchar * +gst_rtsp_url_get_request_uri (const GstRTSPUrl * url) +{ + gchar *uri; + const gchar *pre_host; + const gchar *post_host; + const gchar *pre_query; + const gchar *query; + + g_return_val_if_fail (url != NULL, NULL); + + pre_host = url->family == GST_RTSP_FAM_INET6 ? "[" : ""; + post_host = url->family == GST_RTSP_FAM_INET6 ? "]" : ""; + pre_query = url->query ? "?" : ""; + query = url->query ? url->query : ""; + + if (url->port != 0) { + uri = g_strdup_printf ("rtsp://%s%s%s:%u%s%s%s", pre_host, url->host, + post_host, url->port, url->abspath, pre_query, query); + } else { + uri = g_strdup_printf ("rtsp://%s%s%s%s%s%s", pre_host, url->host, + post_host, url->abspath, pre_query, query); + } + + return uri; +} + +static int +hex_to_int (gchar c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + else if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + else if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + else + return -1; +} + +static void +unescape_path_component (gchar * comp) +{ + guint len = strlen (comp); + guint i; + + for (i = 0; i + 2 < len; i++) + if (comp[i] == '%') { + int a, b; + + a = hex_to_int (comp[i + 1]); + b = hex_to_int (comp[i + 2]); + + /* The a||b check is to ensure that the byte is not '\0' */ + if (a >= 0 && b >= 0 && (a || b)) { + comp[i] = (gchar) (a * 16 + b); + memmove (comp + i + 1, comp + i + 3, len - i - 3); + len -= 2; + comp[len] = '\0'; + } + } +} + +/** + * gst_rtsp_url_decode_path_components: + * @url: a #GstRTSPUrl + * + * Splits the path of @url on '/' boundaries, decoding the resulting components, + * + * The decoding performed by this routine is "URI decoding", as defined in RFC + * 3986, commonly known as percent-decoding. For example, a string "foo%2fbar" + * will decode to "foo/bar" -- the %2f being replaced by the corresponding byte + * with hex value 0x2f. Note that there is no guarantee that the resulting byte + * sequence is valid in any given encoding. As a special case, %00 is not + * unescaped to NUL, as that would prematurely terminate the string. + * + * Also note that since paths usually start with a slash, the first component + * will usually be the empty string. + * + * Returns: a string vector. g_strfreev() after usage. + * + * Since: 0.10.32 + */ +gchar ** +gst_rtsp_url_decode_path_components (const GstRTSPUrl * url) +{ + gchar **ret; + guint i; + + g_return_val_if_fail (url != NULL, NULL); + g_return_val_if_fail (url->abspath != NULL, NULL); + + ret = g_strsplit (url->abspath, "/", -1); + + for (i = 0; ret[i]; i++) + unescape_path_component (ret[i]); + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.h new file mode 100644 index 0000000..b34ee87 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/rtsp/gstrtspurl.h @@ -0,0 +1,103 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RTSP_URL_H__ +#define __GST_RTSP_URL_H__ + +#include +#include + +#include +#include + +G_BEGIN_DECLS + +/** + * GST_RTSP_DEFAULT_PORT: + * + * The default RTSP port to connect to. + */ +#define GST_RTSP_DEFAULT_PORT 554 + +#define GST_TYPE_RTSP_URL (gst_rtsp_url_get_type()) + +typedef struct _GstRTSPUrl GstRTSPUrl; + +/** + * GstRTSPUrl: + * @transports: the transports allowed + * @family: the family + * @user: the user + * @passwd: the password + * @host: the host + * @port: the port + * @abspath: the absolute path + * @query: additional query parameters + * + * This structure contains the result of a parsed RTSP URL + */ +struct _GstRTSPUrl { + GstRTSPLowerTrans transports; + GstRTSPFamily family; + gchar *user; + gchar *passwd; + gchar *host; + guint16 port; + gchar *abspath; + gchar *query; +}; + +GType gst_rtsp_url_get_type (void); + +GstRTSPResult gst_rtsp_url_parse (const gchar *urlstr, GstRTSPUrl **url); +GstRTSPUrl* gst_rtsp_url_copy (const GstRTSPUrl *url); +void gst_rtsp_url_free (GstRTSPUrl *url); +gchar* gst_rtsp_url_get_request_uri (const GstRTSPUrl *url); +gchar** gst_rtsp_url_decode_path_components + (const GstRTSPUrl *url); + +GstRTSPResult gst_rtsp_url_set_port (GstRTSPUrl *url, guint16 port); +GstRTSPResult gst_rtsp_url_get_port (const GstRTSPUrl *url, guint16 *port); + +G_END_DECLS + +#endif /* __GST_RTSP_URL_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/Makefile.am new file mode 100644 index 0000000..5ad8080 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/Makefile.am @@ -0,0 +1,71 @@ +libgstsdpincludedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/sdp + +libgstsdpinclude_HEADERS = gstsdp.h \ + gstsdpmessage.h + +lib_LTLIBRARIES = libgstsdp-@GST_MAJORMINOR@.la + +libgstsdp_@GST_MAJORMINOR@_la_SOURCES = gstsdpmessage.c + +libgstsdp_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstsdp_@GST_MAJORMINOR@_la_LIBADD = $(GST_LIBS) $(WIN32_LIBS) +libgstsdp_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstSdp-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstsdpinclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstsdp_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/sdp/%',$(libgstsdpinclude_HEADERS)) + +GstSdp-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstsdp-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstSdp \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --library=libgstsdp-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-sdp-@GST_MAJORMINOR@ \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstsdp -:SHARED libgstsdp-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstsdp_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstsdp_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstsdp_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstsdp_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/sdp \ + -:HEADERS $(libgstsdpinclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdp.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdp.h new file mode 100644 index 0000000..3dbd86d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdp.h @@ -0,0 +1,58 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_SDP_H__ +#define __GST_SDP_H__ + +/** + * GstSDPResult: + * @GST_SDP_OK: A successful return value + * @GST_SDP_EINVAL: a function was given invalid parameters + * + * Return values for the SDP functions. + */ +typedef enum { + GST_SDP_OK = 0, + GST_SDP_EINVAL = -1 +} GstSDPResult; + +#endif /* __GST_SDP_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.c new file mode 100644 index 0000000..7d2813a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.c @@ -0,0 +1,2241 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstsdpmessage + * @short_description: Helper methods for dealing with SDP messages + * + * + * + * The GstSDPMessage helper functions makes it easy to parse and create SDP + * messages. + * + * + * + * Last reviewed on 2007-07-24 (0.10.14) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#include /* for G_OS_WIN32 */ +#include /* For GST_STR_NULL */ + +#ifdef G_OS_WIN32 +/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later. + * minwg32 headers check WINVER before allowing the use of these */ +#ifndef WINVER +#define WINVER 0x0501 +#endif +#ifdef _MSC_VER +#include +#endif +#include +#else +#include +#include +#include +#endif + +#include "gstsdpmessage.h" + +/* FIXME, is currently allocated on the stack */ +#define MAX_LINE_LEN 1024 * 16 + +#define FREE_STRING(field) g_free (field); (field) = NULL +#define REPLACE_STRING(field, val) FREE_STRING(field); (field) = g_strdup (val) + +#define INIT_ARRAY(field, type, init_func) \ +G_STMT_START { \ + if (field) { \ + guint i; \ + for(i = 0; i < (field)->len; i++) \ + init_func (&g_array_index ((field), type, i)); \ + g_array_set_size ((field), 0); \ + } \ + else \ + (field) = g_array_new (FALSE, TRUE, sizeof (type)); \ +} G_STMT_END + +#define FREE_ARRAY(field) \ +G_STMT_START { \ + if (field) \ + g_array_free ((field), TRUE); \ + (field) = NULL; \ +} G_STMT_END + +#define INIT_PTR_ARRAY(field, type, init_func) \ +G_STMT_START { \ + if (field) { \ + guint i; \ + for(i = 0; i < (field)->len; i++) \ + init_func (g_array_index ((field), type, i)); \ + g_array_set_size ((field), 0); \ + } \ + else \ + (field) = g_array_new (FALSE, TRUE, sizeof (type)); \ +} G_STMT_END + +#define FREE_PTR_ARRAY(field) FREE_ARRAY(field) + +#define DEFINE_STRING_SETTER(field) \ +GstSDPResult gst_sdp_message_set_##field (GstSDPMessage *msg, const gchar *val) { \ + g_free (msg->field); \ + msg->field = g_strdup (val); \ + return GST_SDP_OK; \ +} +#define DEFINE_STRING_GETTER(field) \ +const gchar* gst_sdp_message_get_##field (const GstSDPMessage *msg) { \ + return msg->field; \ +} + +#define DEFINE_ARRAY_LEN(field) \ +guint gst_sdp_message_##field##_len (const GstSDPMessage *msg) { \ + return msg->field->len; \ +} +#define DEFINE_ARRAY_GETTER(method, field, type) \ +type * gst_sdp_message_get_##method (const GstSDPMessage *msg, guint idx) { \ + return &g_array_index (msg->field, type, idx); \ +} + +#define DEFINE_PTR_ARRAY_LEN(field) DEFINE_ARRAY_LEN(field) +#define DEFINE_PTR_ARRAY_GETTER(method, field, type) \ +type gst_sdp_message_get_##method (const GstSDPMessage *msg, guint idx) { \ + return g_array_index (msg->field, type, idx); \ +} +#define DEFINE_PTR_ARRAY_ADDER(method, field, type, dup_method) \ +GstSDPResult gst_sdp_message_add_##method (GstSDPMessage *msg, type val) { \ + type v = dup_method (val); \ + g_array_append_val (msg->field, v); \ + return GST_SDP_OK; \ +} + +static void +gst_sdp_origin_init (GstSDPOrigin * origin) +{ + FREE_STRING (origin->username); + FREE_STRING (origin->sess_id); + FREE_STRING (origin->sess_version); + FREE_STRING (origin->nettype); + FREE_STRING (origin->addrtype); + FREE_STRING (origin->addr); +} + +static void +gst_sdp_connection_init (GstSDPConnection * connection) +{ + FREE_STRING (connection->nettype); + FREE_STRING (connection->addrtype); + FREE_STRING (connection->address); + connection->ttl = 0; + connection->addr_number = 0; +} + +static void +gst_sdp_bandwidth_init (GstSDPBandwidth * bandwidth) +{ + FREE_STRING (bandwidth->bwtype); + bandwidth->bandwidth = 0; +} + +static void +gst_sdp_time_init (GstSDPTime * t) +{ + FREE_STRING (t->start); + FREE_STRING (t->stop); + INIT_PTR_ARRAY (t->repeat, gchar *, g_free); + FREE_PTR_ARRAY (t->repeat); +} + +static void +gst_sdp_zone_init (GstSDPZone * zone) +{ + FREE_STRING (zone->time); + FREE_STRING (zone->typed_time); +} + +static void +gst_sdp_key_init (GstSDPKey * key) +{ + FREE_STRING (key->type); + FREE_STRING (key->data); +} + +static void +gst_sdp_attribute_init (GstSDPAttribute * attr) +{ + FREE_STRING (attr->key); + FREE_STRING (attr->value); +} + +/** + * gst_sdp_message_new: + * @msg: pointer to new #GstSDPMessage + * + * Allocate a new GstSDPMessage and store the result in @msg. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_new (GstSDPMessage ** msg) +{ + GstSDPMessage *newmsg; + + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + newmsg = g_new0 (GstSDPMessage, 1); + + *msg = newmsg; + + return gst_sdp_message_init (newmsg); +} + +/** + * gst_sdp_message_init: + * @msg: a #GstSDPMessage + * + * Initialize @msg so that its contents are as if it was freshly allocated + * with gst_sdp_message_new(). This function is mostly used to initialize a message + * allocated on the stack. gst_sdp_message_uninit() undoes this operation. + * + * When this function is invoked on newly allocated data (with malloc or on the + * stack), its contents should be set to 0 before calling this function. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_init (GstSDPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + FREE_STRING (msg->version); + gst_sdp_origin_init (&msg->origin); + FREE_STRING (msg->session_name); + FREE_STRING (msg->information); + FREE_STRING (msg->uri); + INIT_PTR_ARRAY (msg->emails, gchar *, g_free); + INIT_PTR_ARRAY (msg->phones, gchar *, g_free); + gst_sdp_connection_init (&msg->connection); + INIT_ARRAY (msg->bandwidths, GstSDPBandwidth, gst_sdp_bandwidth_init); + INIT_ARRAY (msg->times, GstSDPTime, gst_sdp_time_init); + INIT_ARRAY (msg->zones, GstSDPZone, gst_sdp_zone_init); + gst_sdp_key_init (&msg->key); + INIT_ARRAY (msg->attributes, GstSDPAttribute, gst_sdp_attribute_init); + INIT_ARRAY (msg->medias, GstSDPMedia, gst_sdp_media_uninit); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_uninit: + * @msg: a #GstSDPMessage + * + * Free all resources allocated in @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was allocated on the + * stack and initialized with gst_sdp_message_init(). + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_uninit (GstSDPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + gst_sdp_message_init (msg); + + FREE_PTR_ARRAY (msg->emails); + FREE_PTR_ARRAY (msg->phones); + FREE_ARRAY (msg->bandwidths); + FREE_ARRAY (msg->times); + FREE_ARRAY (msg->zones); + FREE_ARRAY (msg->attributes); + FREE_ARRAY (msg->medias); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_free: + * @msg: a #GstSDPMessage + * + * Free all resources allocated by @msg. @msg should not be used anymore after + * this function. This function should be used when @msg was dynamically + * allocated with gst_sdp_message_new(). + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_free (GstSDPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + gst_sdp_message_uninit (msg); + g_free (msg); + + return GST_SDP_OK; +} + +/** + * gst_sdp_address_is_multicast: + * @nettype: a network type + * @addrtype: an address type + * @addr: an address + * + * Check if the given @addr is a multicast address. + * + * Returns: TRUE when @addr is multicast. + * + * Since: 0.10.32 + */ +gboolean +gst_sdp_address_is_multicast (const gchar * nettype, const gchar * addrtype, + const gchar * addr) +{ + struct addrinfo hints; + struct addrinfo *ai; + struct addrinfo *res; + gboolean ret = FALSE; + + g_return_val_if_fail (addr, FALSE); + + /* we only support IN */ + if (nettype && strcmp (nettype, "IN") != 0) + return FALSE; + + memset (&hints, 0, sizeof (hints)); + hints.ai_socktype = SOCK_DGRAM; + + /* set the address type as a hint */ + if (addrtype) { + if (!strcmp (addrtype, "IP4")) + hints.ai_family = AF_INET; + else if (!strcmp (addrtype, "IP6")) + hints.ai_family = AF_INET6; + } + + if (getaddrinfo (addr, NULL, &hints, &res) < 0) + return FALSE; + + for (ai = res; !ret && ai; ai = ai->ai_next) { + if (ai->ai_family == AF_INET) + ret = + IN_MULTICAST (ntohl (((struct sockaddr_in *) ai->ai_addr)-> + sin_addr.s_addr)); + else + ret = + IN6_IS_ADDR_MULTICAST (&((struct sockaddr_in6 *) ai-> + ai_addr)->sin6_addr); + } + + freeaddrinfo (res); + + return ret; +} + +/** + * gst_sdp_message_as_text: + * @msg: a #GstSDPMessage + * + * Convert the contents of @msg to a text string. + * + * Returns: A dynamically allocated string representing the SDP description. + */ +gchar * +gst_sdp_message_as_text (const GstSDPMessage * msg) +{ + /* change all vars so they match rfc? */ + GString *lines; + guint i; + + g_return_val_if_fail (msg != NULL, NULL); + + lines = g_string_new (""); + + if (msg->version) + g_string_append_printf (lines, "v=%s\r\n", msg->version); + + if (msg->origin.sess_id && msg->origin.sess_version && msg->origin.nettype && + msg->origin.addrtype && msg->origin.addr) + g_string_append_printf (lines, "o=%s %s %s %s %s %s\r\n", + msg->origin.username ? msg->origin.username : "-", msg->origin.sess_id, + msg->origin.sess_version, msg->origin.nettype, msg->origin.addrtype, + msg->origin.addr); + + if (msg->session_name) + g_string_append_printf (lines, "s=%s\r\n", msg->session_name); + + if (msg->information) + g_string_append_printf (lines, "i=%s\r\n", msg->information); + + if (msg->uri) + g_string_append_printf (lines, "u=%s\r\n", msg->uri); + + for (i = 0; i < gst_sdp_message_emails_len (msg); i++) + g_string_append_printf (lines, "e=%s\r\n", + gst_sdp_message_get_email (msg, i)); + + for (i = 0; i < gst_sdp_message_phones_len (msg); i++) + g_string_append_printf (lines, "p=%s\r\n", + gst_sdp_message_get_phone (msg, i)); + + if (gst_sdp_message_emails_len (msg) == 0 && + gst_sdp_message_phones_len (msg) == 0) + g_string_append_printf (lines, "e=NONE\r\n"); + + if (msg->connection.nettype && msg->connection.addrtype && + msg->connection.address) { + g_string_append_printf (lines, "c=%s %s %s", msg->connection.nettype, + msg->connection.addrtype, msg->connection.address); + if (gst_sdp_address_is_multicast (msg->connection.nettype, + msg->connection.addrtype, msg->connection.address)) { + /* only add ttl for IP4 */ + if (strcmp (msg->connection.addrtype, "IP4") == 0) + g_string_append_printf (lines, "/%u", msg->connection.ttl); + if (msg->connection.addr_number > 1) + g_string_append_printf (lines, "/%u", msg->connection.addr_number); + } + g_string_append_printf (lines, "\r\n"); + } + + for (i = 0; i < gst_sdp_message_bandwidths_len (msg); i++) { + const GstSDPBandwidth *bandwidth = gst_sdp_message_get_bandwidth (msg, i); + + g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype, + bandwidth->bandwidth); + } + + for (i = 0; i < gst_sdp_message_times_len (msg); i++) { + const GstSDPTime *times = gst_sdp_message_get_time (msg, i); + + g_string_append_printf (lines, "t=%s %s\r\n", times->start, times->stop); + + if (times->repeat != NULL) { + guint j; + + g_string_append_printf (lines, "r=%s", + g_array_index (times->repeat, gchar *, 0)); + for (j = 1; j < times->repeat->len; j++) + g_string_append_printf (lines, " %s", + g_array_index (times->repeat, gchar *, j)); + g_string_append_printf (lines, "\r\n"); + } + } + + if (gst_sdp_message_zones_len (msg) > 0) { + const GstSDPZone *zone = gst_sdp_message_get_zone (msg, 0); + + g_string_append_printf (lines, "z=%s %s", zone->time, zone->typed_time); + for (i = 1; i < gst_sdp_message_zones_len (msg); i++) { + zone = gst_sdp_message_get_zone (msg, i); + g_string_append_printf (lines, " %s %s", zone->time, zone->typed_time); + } + g_string_append_printf (lines, "\r\n"); + } + + if (msg->key.type) { + g_string_append_printf (lines, "k=%s", msg->key.type); + if (msg->key.data) + g_string_append_printf (lines, ":%s", msg->key.data); + g_string_append_printf (lines, "\r\n"); + } + + for (i = 0; i < gst_sdp_message_attributes_len (msg); i++) { + const GstSDPAttribute *attr = gst_sdp_message_get_attribute (msg, i); + + if (attr->key) { + g_string_append_printf (lines, "a=%s", attr->key); + if (attr->value) + g_string_append_printf (lines, ":%s", attr->value); + g_string_append_printf (lines, "\r\n"); + } + } + + for (i = 0; i < gst_sdp_message_medias_len (msg); i++) { + const GstSDPMedia *media = gst_sdp_message_get_media (msg, i); + gchar *sdp_media_str; + + sdp_media_str = gst_sdp_media_as_text (media); + g_string_append_printf (lines, "%s", sdp_media_str); + g_free (sdp_media_str); + } + + return g_string_free (lines, FALSE); +} + +static int +hex_to_int (gchar c) +{ + return c >= '0' && c <= '9' ? c - '0' + : c >= 'A' && c <= 'F' ? c - 'A' + 10 + : c >= 'a' && c <= 'f' ? c - 'a' + 10 : 0; +} + +/** + * gst_sdp_message_parse_uri: + * @uri: the start of the uri + * @msg: the result #GstSDPMessage + * + * Parse the null-terminated @uri and store the result in @msg. + * + * The uri should be of the form: + * + * scheme://[address[:ttl=ttl][:noa=noa]]/[sessionname] + * [#type=value *[&type=value]] + * + * where value is url encoded. This looslely resembles + * http://tools.ietf.org/html/draft-fujikawa-sdp-url-01 + * + * Returns: #GST_SDP_OK on success. + * + * Since: 0.10.31 + */ +GstSDPResult +gst_sdp_message_parse_uri (const gchar * uri, GstSDPMessage * msg) +{ + GstSDPResult res; + gchar *message; + const gchar *colon, *slash, *hash, *p; + GString *lines; + + g_return_val_if_fail (uri != NULL, GST_SDP_EINVAL); + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + colon = strstr (uri, "://"); + if (!colon) + goto no_colon; + + /* FIXME connection info goes here */ + + slash = strstr (colon + 3, "/"); + if (!slash) + goto no_slash; + + /* FIXME session name goes here */ + + hash = strstr (slash + 1, "#"); + if (!hash) + goto no_hash; + + lines = g_string_new (""); + + /* unescape */ + for (p = hash + 1; *p; p++) { + if (*p == '&') + g_string_append_printf (lines, "\r\n"); + else if (*p == '+') + g_string_append_c (lines, ' '); + else if (*p == '%') { + gchar a, b; + + if ((a = p[1])) { + if ((b = p[2])) { + g_string_append_c (lines, (hex_to_int (a) << 4) | hex_to_int (b)); + p += 2; + } + } else { + p++; + } + } else + g_string_append_c (lines, *p); + } + + message = g_string_free (lines, FALSE); + res = + gst_sdp_message_parse_buffer ((const guint8 *) message, strlen (message), + msg); + g_free (message); + + return res; + + /* ERRORS */ +no_colon: + { + return GST_SDP_EINVAL; + } +no_slash: + { + return GST_SDP_EINVAL; + } +no_hash: + { + return GST_SDP_EINVAL; + } +} + +static const guchar acceptable[96] = { + /* X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF */ + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, /* 2X !"#$%&'()*+,-./ */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 3X 0123456789:;<=>? */ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 4X @ABCDEFGHIJKLMNO */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, /* 5X PQRSTUVWXYZ[\]^_ */ + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, /* 6X `abcdefghijklmno */ + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 /* 7X pqrstuvwxyz{|}~DEL */ +}; + +static const gchar hex[16] = "0123456789ABCDEF"; + +#define ACCEPTABLE_CHAR(a) (((guchar)(a))>=32 && ((guchar)(a))<128 && acceptable[(((guchar)a))-32]) + +/** + * gst_sdp_message_as_uri: + * @scheme: the uri scheme + * @msg: the #GstSDPMessage + * + * Creates a uri from @msg with the given @scheme. The uri has the format: + * + * @scheme:///[#type=value *[&type=value]] + * + * Where each value is url encoded. + * + * Returns: a uri for @msg. + * + * Since: 0.10.31 + */ +gchar * +gst_sdp_message_as_uri (const gchar * scheme, const GstSDPMessage * msg) +{ + gchar *serialized, *p; + gchar *res; + GString *lines; + gboolean first; + + g_return_val_if_fail (scheme != NULL, NULL); + g_return_val_if_fail (msg != NULL, NULL); + + p = serialized = gst_sdp_message_as_text (msg); + + lines = g_string_new (""); + g_string_append_printf (lines, "%s:///#", scheme); + + /* now escape */ + first = TRUE; + for (p = serialized; *p; p++) { + if (first) { + g_string_append_printf (lines, "%c=", *p); + if (*(p + 1)) + p++; + first = FALSE; + continue; + } + if (*p == '\r') + continue; + else if (*p == '\n') { + if (*(p + 1)) + g_string_append_c (lines, '&'); + first = TRUE; + } else if (*p == ' ') + g_string_append_c (lines, '+'); + else if (ACCEPTABLE_CHAR (*p)) + g_string_append_c (lines, *p); + else { + /* escape */ + g_string_append_printf (lines, "%%%c%c", hex[*p >> 4], hex[*p & 0xf]); + } + } + + res = g_string_free (lines, FALSE); + g_free (serialized); + + return res; +} + +/** + * gst_sdp_message_set_version: + * @msg: a #GstSDPMessage + * @version: the version + * + * Set the version in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_SETTER (version); +/** + * gst_sdp_message_get_version: + * @msg: a #GstSDPMessage + * + * Get the version in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_GETTER (version); + +/** + * gst_sdp_message_set_origin: + * @msg: a #GstSDPMessage + * @username: the user name + * @sess_id: a session id + * @sess_version: a session version + * @nettype: a network type + * @addrtype: an address type + * @addr: an address + * + * Configure the SDP origin in @msg with the given parameters. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_message_set_origin (GstSDPMessage * msg, const gchar * username, + const gchar * sess_id, const gchar * sess_version, const gchar * nettype, + const gchar * addrtype, const gchar * addr) +{ + REPLACE_STRING (msg->origin.username, username); + REPLACE_STRING (msg->origin.sess_id, sess_id); + REPLACE_STRING (msg->origin.sess_version, sess_version); + REPLACE_STRING (msg->origin.nettype, nettype); + REPLACE_STRING (msg->origin.addrtype, addrtype); + REPLACE_STRING (msg->origin.addr, addr); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_get_origin: + * @msg: a #GstSDPMessage + * + * Get the origin of @msg. + * + * Returns: a #GstSDPOrigin. The result remains valid as long as @msg is valid. + */ +const GstSDPOrigin * +gst_sdp_message_get_origin (const GstSDPMessage * msg) +{ + return &msg->origin; +} + +/** + * gst_sdp_message_set_session_name: + * @msg: a #GstSDPMessage + * @session_name: the session name + * + * Set the session name in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_SETTER (session_name); +/** + * gst_sdp_message_get_session_name: + * @msg: a #GstSDPMessage + * + * Get the session name in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_GETTER (session_name); +/** + * gst_sdp_message_set_information: + * @msg: a #GstSDPMessage + * @information: the information + * + * Set the information in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_SETTER (information); +/** + * gst_sdp_message_get_information: + * @msg: a #GstSDPMessage + * + * Get the information in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_GETTER (information); +/** + * gst_sdp_message_set_uri: + * @msg: a #GstSDPMessage + * @uri: the URI + * + * Set the URI in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_SETTER (uri); +/** + * gst_sdp_message_get_uri: + * @msg: a #GstSDPMessage + * + * Get the URI in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_STRING_GETTER (uri); + +/** + * gst_sdp_message_emails_len: + * @msg: a #GstSDPMessage + * + * Get the number of emails in @msg. + * + * Returns: the number of emails in @msg. + */ +DEFINE_ARRAY_LEN (emails); +/** + * gst_sdp_message_get_email: + * @msg: a #GstSDPMessage + * @idx: an email index + * + * Get the email with number @idx from @msg. + * + * Returns: the email at position @idx. + */ +DEFINE_PTR_ARRAY_GETTER (email, emails, const gchar *); + +/** + * gst_sdp_message_add_email: + * @msg: a #GstSDPMessage + * @email: an email + * + * Add @email to the list of emails in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_PTR_ARRAY_ADDER (email, emails, const gchar *, g_strdup); + +/** + * gst_sdp_message_phones_len: + * @msg: a #GstSDPMessage + * + * Get the number of phones in @msg. + * + * Returns: the number of phones in @msg. + */ +DEFINE_ARRAY_LEN (phones); +/** + * gst_sdp_message_get_phone: + * @msg: a #GstSDPMessage + * @idx: a phone index + * + * Get the phone with number @idx from @msg. + * + * Returns: the phone at position @idx. + */ +DEFINE_PTR_ARRAY_GETTER (phone, phones, const gchar *); + +/** + * gst_sdp_message_add_phone: + * @msg: a #GstSDPMessage + * @phone: a phone + * + * Add @phone to the list of phones in @msg. + * + * Returns: a #GstSDPResult. + */ +DEFINE_PTR_ARRAY_ADDER (phone, phones, const gchar *, g_strdup); + +/** + * gst_sdp_message_set_connection: + * @msg: a #GstSDPMessage + * @nettype: the type of network. "IN" is defined to have the meaning + * "Internet". + * @addrtype: the type of address. + * @address: the address + * @ttl: the time to live of the address + * @addr_number: the number of layers + * + * Configure the SDP connection in @msg with the given parameters. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_set_connection (GstSDPMessage * msg, const gchar * nettype, + const gchar * addrtype, const gchar * address, guint ttl, guint addr_number) +{ + REPLACE_STRING (msg->connection.nettype, nettype); + REPLACE_STRING (msg->connection.addrtype, addrtype); + REPLACE_STRING (msg->connection.address, address); + msg->connection.ttl = ttl; + msg->connection.addr_number = addr_number; + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_get_connection: + * @msg: a #GstSDPMessage + * + * Get the connection of @msg. + * + * Returns: a #GstSDPConnection. The result remains valid as long as @msg is valid. + */ +const GstSDPConnection * +gst_sdp_message_get_connection (const GstSDPMessage * msg) +{ + return &msg->connection; +} + +/** + * gst_sdp_message_bandwidths_len: + * @msg: a #GstSDPMessage + * + * Get the number of bandwidth information in @msg. + * + * Returns: the number of bandwidth information in @msg. + */ +DEFINE_ARRAY_LEN (bandwidths); +/** + * gst_sdp_message_get_bandwidth: + * @msg: a #GstSDPMessage + * @idx: the bandwidth index + * + * Get the bandwidth at index @idx from @msg. + * + * Returns: a #GstSDPBandwidth. + */ +DEFINE_ARRAY_GETTER (bandwidth, bandwidths, const GstSDPBandwidth); + +/** + * gst_sdp_message_add_bandwidth: + * @msg: a #GstSDPMessage + * @bwtype: the bandwidth modifier type + * @bandwidth: the bandwidth in kilobits per second + * + * Add the specified bandwidth information to @msg. + * + * Returns: a #GstSDPResult. + */ + +GstSDPResult +gst_sdp_message_add_bandwidth (GstSDPMessage * msg, const gchar * bwtype, + guint bandwidth) +{ + GstSDPBandwidth bw; + + bw.bwtype = g_strdup (bwtype); + bw.bandwidth = bandwidth; + + g_array_append_val (msg->bandwidths, bw); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_times_len: + * @msg: a #GstSDPMessage + * + * Get the number of time information entries in @msg. + * + * Returns: the number of time information entries in @msg. + */ +DEFINE_ARRAY_LEN (times); + +/** + * gst_sdp_message_get_time: + * @msg: a #GstSDPMessage + * @idx: the time index + * + * Get time information with index @idx from @msg. + * + * Returns: a #GstSDPTime. + */ +DEFINE_ARRAY_GETTER (time, times, const GstSDPTime); + +/** + * gst_sdp_message_add_time: + * @msg: a #GstSDPMessage + * @start: the start time + * @stop: the stop time + * @repeat: the repeat times + * + * Add time information @start and @stop to @msg. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_add_time (GstSDPMessage * msg, const gchar * start, + const gchar * stop, const gchar ** repeat) +{ + GstSDPTime times; + + times.start = g_strdup (start); + times.stop = g_strdup (stop); + if (repeat) { + times.repeat = g_array_new (FALSE, TRUE, sizeof (gchar *)); + for (; *repeat; repeat++) { + gchar *r = g_strdup (*repeat); + + g_array_append_val (times.repeat, r); + } + } else + times.repeat = NULL; + g_array_append_val (msg->times, times); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_zones_len: + * @msg: a #GstSDPMessage + * + * Get the number of time zone information entries in @msg. + * + * Returns: the number of time zone information entries in @msg. + */ +DEFINE_ARRAY_LEN (zones); +/** + * gst_sdp_message_get_zone: + * @msg: a #GstSDPMessage + * @idx: the zone index + * + * Get time zone information with index @idx from @msg. + * + * Returns: a #GstSDPZone. + */ +DEFINE_ARRAY_GETTER (zone, zones, const GstSDPZone); + +/** + * gst_sdp_message_add_zone: + * @msg: a #GstSDPMessage + * @adj_time: the NTP time that a time zone adjustment happens + * @typed_time: the offset from the time when the session was first scheduled + * + * Add time zone information to @msg. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_add_zone (GstSDPMessage * msg, const gchar * adj_time, + const gchar * typed_time) +{ + GstSDPZone zone; + + zone.time = g_strdup (adj_time); + zone.typed_time = g_strdup (typed_time); + + g_array_append_val (msg->zones, zone); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_set_key: + * @msg: a #GstSDPMessage + * @type: the encryption type + * @data: the encryption data + * + * Adds the encryption information to @msg. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_set_key (GstSDPMessage * msg, const gchar * type, + const gchar * data) +{ + REPLACE_STRING (msg->key.type, type); + REPLACE_STRING (msg->key.data, data); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_get_key: + * @msg: a #GstSDPMessage + * + * Get the encryption information from @msg. + * + * Returns: a #GstSDPKey. + */ +const GstSDPKey * +gst_sdp_message_get_key (const GstSDPMessage * msg) +{ + return &msg->key; +} + +/** + * gst_sdp_message_attributes_len: + * @msg: a #GstSDPMessage + * + * Get the number of attributes in @msg. + * + * Returns: the number of attributes in @msg. + */ +DEFINE_ARRAY_LEN (attributes); + +/** + * gst_sdp_message_get_attribute: + * @msg: a #GstSDPMessage + * @idx: the index + * + * Get the attribute at position @idx in @msg. + * + * Returns: the #GstSDPAttribute at position @idx. + */ +DEFINE_ARRAY_GETTER (attribute, attributes, const GstSDPAttribute); + +/** + * gst_sdp_message_get_attribute_val_n: + * @msg: a #GstSDPMessage + * @key: the key + * @nth: the index + * + * Get the @nth attribute with key @key in @msg. + * + * Returns: the attribute value of the @nth attribute with @key. + */ +const gchar * +gst_sdp_message_get_attribute_val_n (const GstSDPMessage * msg, + const gchar * key, guint nth) +{ + guint i; + + for (i = 0; i < msg->attributes->len; i++) { + GstSDPAttribute *attr; + + attr = &g_array_index (msg->attributes, GstSDPAttribute, i); + if (!strcmp (attr->key, key)) { + if (nth == 0) + return attr->value; + else + nth--; + } + } + return NULL; +} + +/** + * gst_sdp_message_get_attribute_val: + * @msg: a #GstSDPMessage + * @key: the key + * + * Get the first attribute with key @key in @msg. + * + * Returns: the attribute value of the first attribute with @key. + */ +const gchar * +gst_sdp_message_get_attribute_val (const GstSDPMessage * msg, const gchar * key) +{ + return gst_sdp_message_get_attribute_val_n (msg, key, 0); +} + +/** + * gst_sdp_message_add_attribute: + * @msg: a #GstSDPMessage + * @key: the key + * @value: the value + * + * Add the attribute with @key and @value to @msg. + * + * Returns: @GST_SDP_OK. + */ +GstSDPResult +gst_sdp_message_add_attribute (GstSDPMessage * msg, const gchar * key, + const gchar * value) +{ + GstSDPAttribute attr; + + attr.key = g_strdup (key); + attr.value = g_strdup (value); + + g_array_append_val (msg->attributes, attr); + + return GST_SDP_OK; +} + +/** + * gst_sdp_message_medias_len: + * @msg: a #GstSDPMessage + * + * Get the number of media descriptions in @msg. + * + * Returns: the number of media descriptions in @msg. + */ +DEFINE_ARRAY_LEN (medias); +/** + * gst_sdp_message_get_media: + * @msg: a #GstSDPMessage + * @idx: the index + * + * Get the media description at index @idx in @msg. + * + * Returns: a #GstSDPMedia. + */ +DEFINE_ARRAY_GETTER (media, medias, const GstSDPMedia); + +/** + * gst_sdp_message_add_media: + * @msg: a #GstSDPMessage + * @media: a #GstSDPMedia to add + * + * Adds @media to the array of medias in @msg. This function takes ownership of + * the contents of @media so that @media will have to be reinitialized with + * gst_media_init() before it can be used again. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_add_media (GstSDPMessage * msg, GstSDPMedia * media) +{ + guint len; + GstSDPMedia *nmedia; + + len = msg->medias->len; + g_array_set_size (msg->medias, len + 1); + nmedia = &g_array_index (msg->medias, GstSDPMedia, len); + + memcpy (nmedia, media, sizeof (GstSDPMedia)); + memset (media, 0, sizeof (GstSDPMedia)); + + return GST_SDP_OK; +} + +/* media access */ + +/** + * gst_sdp_media_new: + * @media: pointer to new #GstSDPMedia + * + * Allocate a new GstSDPMedia and store the result in @media. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_new (GstSDPMedia ** media) +{ + GstSDPMedia *newmedia; + + g_return_val_if_fail (media != NULL, GST_SDP_EINVAL); + + newmedia = g_new0 (GstSDPMedia, 1); + + *media = newmedia; + + return gst_sdp_media_init (newmedia); +} + +/** + * gst_sdp_media_init: + * @media: a #GstSDPMedia + * + * Initialize @media so that its contents are as if it was freshly allocated + * with gst_sdp_media_new(). This function is mostly used to initialize a media + * allocated on the stack. gst_sdp_media_uninit() undoes this operation. + * + * When this function is invoked on newly allocated data (with malloc or on the + * stack), its contents should be set to 0 before calling this function. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_init (GstSDPMedia * media) +{ + g_return_val_if_fail (media != NULL, GST_SDP_EINVAL); + + FREE_STRING (media->media); + media->port = 0; + media->num_ports = 0; + FREE_STRING (media->proto); + INIT_PTR_ARRAY (media->fmts, gchar *, g_free); + FREE_STRING (media->information); + INIT_ARRAY (media->connections, GstSDPConnection, gst_sdp_connection_init); + INIT_ARRAY (media->bandwidths, GstSDPBandwidth, gst_sdp_bandwidth_init); + gst_sdp_key_init (&media->key); + INIT_ARRAY (media->attributes, GstSDPAttribute, gst_sdp_attribute_init); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_uninit: + * @media: a #GstSDPMedia + * + * Free all resources allocated in @media. @media should not be used anymore after + * this function. This function should be used when @media was allocated on the + * stack and initialized with gst_sdp_media_init(). + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_uninit (GstSDPMedia * media) +{ + g_return_val_if_fail (media != NULL, GST_SDP_EINVAL); + + gst_sdp_media_init (media); + FREE_PTR_ARRAY (media->fmts); + FREE_ARRAY (media->connections); + FREE_ARRAY (media->bandwidths); + FREE_ARRAY (media->attributes); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_free: + * @media: a #GstSDPMedia + * + * Free all resources allocated by @media. @media should not be used anymore after + * this function. This function should be used when @media was dynamically + * allocated with gst_sdp_media_new(). + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_free (GstSDPMedia * media) +{ + g_return_val_if_fail (media != NULL, GST_SDP_EINVAL); + + gst_sdp_media_uninit (media); + g_free (media); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_as_text: + * @media: a #GstSDPMedia + * + * Convert the contents of @media to a text string. + * + * Returns: A dynamically allocated string representing the media. + */ +gchar * +gst_sdp_media_as_text (const GstSDPMedia * media) +{ + GString *lines; + guint i; + + g_return_val_if_fail (media != NULL, NULL); + + lines = g_string_new (""); + + if (media->media) + g_string_append_printf (lines, "m=%s", media->media); + + g_string_append_printf (lines, " %u", media->port); + + if (media->num_ports > 1) + g_string_append_printf (lines, "/%u", media->num_ports); + + g_string_append_printf (lines, " %s", media->proto); + + for (i = 0; i < gst_sdp_media_formats_len (media); i++) + g_string_append_printf (lines, " %s", gst_sdp_media_get_format (media, i)); + g_string_append_printf (lines, "\r\n"); + + if (media->information) + g_string_append_printf (lines, "i=%s", media->information); + + for (i = 0; i < gst_sdp_media_connections_len (media); i++) { + const GstSDPConnection *conn = gst_sdp_media_get_connection (media, i); + + if (conn->nettype && conn->addrtype && conn->address) { + g_string_append_printf (lines, "c=%s %s %s", conn->nettype, + conn->addrtype, conn->address); + if (gst_sdp_address_is_multicast (conn->nettype, conn->addrtype, + conn->address)) { + /* only add TTL for IP4 multicast */ + if (strcmp (conn->addrtype, "IP4") == 0) + g_string_append_printf (lines, "/%u", conn->ttl); + if (conn->addr_number > 1) + g_string_append_printf (lines, "/%u", conn->addr_number); + } + g_string_append_printf (lines, "\r\n"); + } + } + + for (i = 0; i < gst_sdp_media_bandwidths_len (media); i++) { + const GstSDPBandwidth *bandwidth = gst_sdp_media_get_bandwidth (media, i); + + g_string_append_printf (lines, "b=%s:%u\r\n", bandwidth->bwtype, + bandwidth->bandwidth); + } + + if (media->key.type) { + g_string_append_printf (lines, "k=%s", media->key.type); + if (media->key.data) + g_string_append_printf (lines, ":%s", media->key.data); + g_string_append_printf (lines, "\r\n"); + } + + for (i = 0; i < gst_sdp_media_attributes_len (media); i++) { + const GstSDPAttribute *attr = gst_sdp_media_get_attribute (media, i); + + if (attr->key) { + g_string_append_printf (lines, "a=%s", attr->key); + if (attr->value) + g_string_append_printf (lines, ":%s", attr->value); + g_string_append_printf (lines, "\r\n"); + } + } + + return g_string_free (lines, FALSE); +} + +/** + * gst_sdp_media_get_media: + * @media: a #GstSDPMedia + * + * Get the media description of @media. + * + * Returns: the media description. + */ +const gchar * +gst_sdp_media_get_media (const GstSDPMedia * media) +{ + return media->media; +} + +/** + * gst_sdp_media_set_media: + * @media: a #GstSDPMedia + * @med: the media description + * + * Set the media description of @media to @med. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_set_media (GstSDPMedia * media, const gchar * med) +{ + g_free (media->media); + media->media = g_strdup (med); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_get_port: + * @media: a #GstSDPMedia + * + * Get the port number for @media. + * + * Returns: the port number of @media. + */ +guint +gst_sdp_media_get_port (const GstSDPMedia * media) +{ + return media->port; +} + +/** + * gst_sdp_media_get_num_ports: + * @media: a #GstSDPMedia + * + * Get the number of ports for @media. + * + * Returns: the number of ports for @media. + */ +guint +gst_sdp_media_get_num_ports (const GstSDPMedia * media) +{ + return media->num_ports; +} + +/** + * gst_sdp_media_set_port_info: + * @media: a #GstSDPMedia + * @port: the port number + * @num_ports: the number of ports + * + * Set the port information in @media. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_set_port_info (GstSDPMedia * media, guint port, guint num_ports) +{ + media->port = port; + media->num_ports = num_ports; + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_get_proto: + * @media: a #GstSDPMedia + * + * Get the transport protocol of @media + * + * Returns: the transport protocol of @media. + */ +const gchar * +gst_sdp_media_get_proto (const GstSDPMedia * media) +{ + return media->proto; +} + +/** + * gst_sdp_media_set_proto: + * @media: a #GstSDPMedia + * @proto: the media transport protocol + * + * Set the media transport protocol of @media to @proto. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_set_proto (GstSDPMedia * media, const gchar * proto) +{ + g_free (media->proto); + media->proto = g_strdup (proto); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_formats_len: + * @media: a #GstSDPMedia + * + * Get the number of formats in @media. + * + * Returns: the number of formats in @media. + */ +guint +gst_sdp_media_formats_len (const GstSDPMedia * media) +{ + return media->fmts->len; +} + +/** + * gst_sdp_media_get_format: + * @media: a #GstSDPMedia + * @idx: an index + * + * Get the format information at position @idx in @media. + * + * Returns: the format at position @idx. + */ +const gchar * +gst_sdp_media_get_format (const GstSDPMedia * media, guint idx) +{ + if (idx >= media->fmts->len) + return NULL; + return g_array_index (media->fmts, gchar *, idx); +} + +/** + * gst_sdp_media_add_format: + * @media: a #GstSDPMedia + * @format: the format + * + * Add the format information to @media. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_add_format (GstSDPMedia * media, const gchar * format) +{ + gchar *fmt; + + fmt = g_strdup (format); + + g_array_append_val (media->fmts, fmt); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_get_information: + * @media: a #GstSDPMedia + * + * Get the information of @media + * + * Returns: the information of @media. + */ +const gchar * +gst_sdp_media_get_information (const GstSDPMedia * media) +{ + return media->information; +} + +/** + * gst_sdp_media_set_information: + * @media: a #GstSDPMedia + * @information: the media information + * + * Set the media information of @media to @information. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_set_information (GstSDPMedia * media, const gchar * information) +{ + g_free (media->information); + media->information = g_strdup (information); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_connections_len: + * @media: a #GstSDPMedia + * + * Get the number of connection fields in @media. + * + * Returns: the number of connections in @media. + */ +guint +gst_sdp_media_connections_len (const GstSDPMedia * media) +{ + return media->connections->len; +} + +/** + * gst_sdp_media_get_connection: + * @media: a #GstSDPMedia + * @idx: an index + * + * Get the connection at position @idx in @media. + * + * Returns: the #GstSDPConnection at position @idx. + */ +const GstSDPConnection * +gst_sdp_media_get_connection (const GstSDPMedia * media, guint idx) +{ + return &g_array_index (media->connections, GstSDPConnection, idx); +} + +/** + * gst_sdp_media_add_connection: + * @media: a #GstSDPMedia + * @nettype: the type of network. "IN" is defined to have the meaning + * "Internet". + * @addrtype: the type of address. + * @address: the address + * @ttl: the time to live of the address + * @addr_number: the number of layers + * + * Add the given connection parameters to @media. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_add_connection (GstSDPMedia * media, const gchar * nettype, + const gchar * addrtype, const gchar * address, guint ttl, guint addr_number) +{ + GstSDPConnection conn; + + conn.nettype = g_strdup (nettype); + conn.addrtype = g_strdup (addrtype); + conn.address = g_strdup (address); + conn.ttl = ttl; + conn.addr_number = addr_number; + + g_array_append_val (media->connections, conn); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_bandwidths_len: + * @media: a #GstSDPMedia + * + * Get the number of bandwidth fields in @media. + * + * Returns: the number of bandwidths in @media. + */ +guint +gst_sdp_media_bandwidths_len (const GstSDPMedia * media) +{ + return media->bandwidths->len; +} + +/** + * gst_sdp_media_get_bandwidth: + * @media: a #GstSDPMedia + * @idx: an index + * + * Get the bandwidth at position @idx in @media. + * + * Returns: the #GstSDPBandwidth at position @idx. + */ +const GstSDPBandwidth * +gst_sdp_media_get_bandwidth (const GstSDPMedia * media, guint idx) +{ + return &g_array_index (media->bandwidths, GstSDPBandwidth, idx); +} + +/** + * gst_sdp_media_add_bandwidth: + * @media: a #GstSDPMedia + * @bwtype: the bandwidth modifier type + * @bandwidth: the bandwidth in kilobits per second + * + * Add the bandwidth information with @bwtype and @bandwidth to @media. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_add_bandwidth (GstSDPMedia * media, const gchar * bwtype, + guint bandwidth) +{ + GstSDPBandwidth bw; + + bw.bwtype = g_strdup (bwtype); + bw.bandwidth = bandwidth; + + g_array_append_val (media->bandwidths, bw); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_set_key: + * @media: a #GstSDPMedia + * @type: the encryption type + * @data: the encryption data + * + * Adds the encryption information to @media. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_media_set_key (GstSDPMedia * media, const gchar * type, + const gchar * data) +{ + g_free (media->key.type); + media->key.type = g_strdup (type); + g_free (media->key.data); + media->key.data = g_strdup (data); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_get_key: + * @media: a #GstSDPMedia + * + * Get the encryption information from @media. + * + * Returns: a #GstSDPKey. + */ +const GstSDPKey * +gst_sdp_media_get_key (const GstSDPMedia * media) +{ + return &media->key; +} + +/** + * gst_sdp_media_attributes_len: + * @media: a #GstSDPMedia + * + * Get the number of attribute fields in @media. + * + * Returns: the number of attributes in @media. + */ +guint +gst_sdp_media_attributes_len (const GstSDPMedia * media) +{ + return media->attributes->len; +} + +/** + * gst_sdp_media_add_attribute: + * @media: a #GstSDPMedia + * @key: a key + * @value: a value + * + * Add the attribute with @key and @value to @media. + * + * Returns: #GST_SDP_OK. + */ +GstSDPResult +gst_sdp_media_add_attribute (GstSDPMedia * media, const gchar * key, + const gchar * value) +{ + GstSDPAttribute attr; + + attr.key = g_strdup (key); + attr.value = g_strdup (value); + + g_array_append_val (media->attributes, attr); + + return GST_SDP_OK; +} + +/** + * gst_sdp_media_get_attribute: + * @media: a #GstSDPMedia + * @idx: an index + * + * Get the attribute at position @idx in @media. + * + * Returns: the #GstSDPAttribute at position @idx. + */ +const GstSDPAttribute * +gst_sdp_media_get_attribute (const GstSDPMedia * media, guint idx) +{ + return &g_array_index (media->attributes, GstSDPAttribute, idx); +} + +/** + * gst_sdp_media_get_attribute_val_n: + * @media: a #GstSDPMedia + * @key: a key + * @nth: an index + * + * Get the @nth attribute value for @key in @media. + * + * Returns: the @nth attribute value. + */ +const gchar * +gst_sdp_media_get_attribute_val_n (const GstSDPMedia * media, const gchar * key, + guint nth) +{ + guint i; + + for (i = 0; i < media->attributes->len; i++) { + GstSDPAttribute *attr; + + attr = &g_array_index (media->attributes, GstSDPAttribute, i); + if (!strcmp (attr->key, key)) { + if (nth == 0) + return attr->value; + else + nth--; + } + } + return NULL; +} + +/** + * gst_sdp_media_get_attribute_val: + * @media: a #GstSDPMedia + * @key: a key + * + * Get the first attribute value for @key in @media. + * + * Returns: the first attribute value for @key. + */ +const gchar * +gst_sdp_media_get_attribute_val (const GstSDPMedia * media, const gchar * key) +{ + return gst_sdp_media_get_attribute_val_n (media, key, 0); +} + +static void +read_string (gchar * dest, guint size, gchar ** src) +{ + guint idx; + + idx = 0; + /* skip spaces */ + while (g_ascii_isspace (**src)) + (*src)++; + + while (!g_ascii_isspace (**src) && **src != '\0') { + if (idx < size - 1) + dest[idx++] = **src; + (*src)++; + } + if (size > 0) + dest[idx] = '\0'; +} + +static void +read_string_del (gchar * dest, guint size, gchar del, gchar ** src) +{ + guint idx; + + idx = 0; + /* skip spaces */ + while (g_ascii_isspace (**src)) + (*src)++; + + while (**src != del && **src != '\0') { + if (idx < size - 1) + dest[idx++] = **src; + (*src)++; + } + if (size > 0) + dest[idx] = '\0'; +} + +enum +{ + SDP_SESSION, + SDP_MEDIA, +}; + +typedef struct +{ + guint state; + GstSDPMessage *msg; + GstSDPMedia *media; +} SDPContext; + +static gboolean +gst_sdp_parse_line (SDPContext * c, gchar type, gchar * buffer) +{ + gchar str[8192]; + gchar *p = buffer; + +#define READ_STRING(field) read_string (str, sizeof (str), &p); REPLACE_STRING (field, str) +#define READ_UINT(field) read_string (str, sizeof (str), &p); field = strtoul (str, NULL, 10) + + switch (type) { + case 'v': + if (buffer[0] != '0') + g_warning ("wrong SDP version"); + gst_sdp_message_set_version (c->msg, buffer); + break; + case 'o': + READ_STRING (c->msg->origin.username); + READ_STRING (c->msg->origin.sess_id); + READ_STRING (c->msg->origin.sess_version); + READ_STRING (c->msg->origin.nettype); + READ_STRING (c->msg->origin.addrtype); + READ_STRING (c->msg->origin.addr); + break; + case 's': + REPLACE_STRING (c->msg->session_name, buffer); + break; + case 'i': + if (c->state == SDP_SESSION) { + REPLACE_STRING (c->msg->information, buffer); + } else { + REPLACE_STRING (c->media->information, buffer); + } + break; + case 'u': + REPLACE_STRING (c->msg->uri, buffer); + break; + case 'e': + gst_sdp_message_add_email (c->msg, buffer); + break; + case 'p': + gst_sdp_message_add_phone (c->msg, buffer); + break; + case 'c': + { + GstSDPConnection conn; + gchar *str2; + + memset (&conn, 0, sizeof (conn)); + + str2 = p; + while ((str2 = strchr (str2, '/'))) + *str2++ = ' '; + READ_STRING (conn.nettype); + READ_STRING (conn.addrtype); + READ_STRING (conn.address); + /* only read TTL for IP4 */ + if (strcmp (conn.addrtype, "IP4") == 0) + READ_UINT (conn.ttl); + READ_UINT (conn.addr_number); + + if (c->state == SDP_SESSION) { + gst_sdp_message_set_connection (c->msg, conn.nettype, conn.addrtype, + conn.address, conn.ttl, conn.addr_number); + } else { + gst_sdp_media_add_connection (c->media, conn.nettype, conn.addrtype, + conn.address, conn.ttl, conn.addr_number); + } + gst_sdp_connection_init (&conn); + break; + } + case 'b': + { + gchar str2[MAX_LINE_LEN]; + + read_string_del (str, sizeof (str), ':', &p); + if (*p != '\0') + p++; + read_string (str2, sizeof (str2), &p); + if (c->state == SDP_SESSION) + gst_sdp_message_add_bandwidth (c->msg, str, atoi (str2)); + else + gst_sdp_media_add_bandwidth (c->media, str, atoi (str2)); + break; + } + case 't': + break; + case 'k': + break; + case 'a': + read_string_del (str, sizeof (str), ':', &p); + if (*p != '\0') + p++; + if (c->state == SDP_SESSION) + gst_sdp_message_add_attribute (c->msg, str, p); + else + gst_sdp_media_add_attribute (c->media, str, p); + break; + case 'm': + { + gchar *slash; + GstSDPMedia nmedia; + + c->state = SDP_MEDIA; + memset (&nmedia, 0, sizeof (nmedia)); + gst_sdp_media_init (&nmedia); + + /* m= / ... */ + READ_STRING (nmedia.media); + read_string (str, sizeof (str), &p); + slash = g_strrstr (str, "/"); + if (slash) { + *slash = '\0'; + nmedia.port = atoi (str); + nmedia.num_ports = atoi (slash + 1); + } else { + nmedia.port = atoi (str); + nmedia.num_ports = -1; + } + READ_STRING (nmedia.proto); + do { + read_string (str, sizeof (str), &p); + gst_sdp_media_add_format (&nmedia, str); + } while (*p != '\0'); + + gst_sdp_message_add_media (c->msg, &nmedia); + c->media = + &g_array_index (c->msg->medias, GstSDPMedia, c->msg->medias->len - 1); + break; + } + default: + break; + } + return TRUE; +} + +/** + * gst_sdp_message_parse_buffer: + * @data: the start of the buffer + * @size: the size of the buffer + * @msg: the result #GstSDPMessage + * + * Parse the contents of @size bytes pointed to by @data and store the result in + * @msg. + * + * Returns: #GST_SDP_OK on success. + */ +GstSDPResult +gst_sdp_message_parse_buffer (const guint8 * data, guint size, + GstSDPMessage * msg) +{ + gchar *p; + SDPContext c; + gchar type; + gchar buffer[MAX_LINE_LEN]; + guint idx = 0; + + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + g_return_val_if_fail (data != NULL, GST_SDP_EINVAL); + g_return_val_if_fail (size != 0, GST_SDP_EINVAL); + + c.state = SDP_SESSION; + c.msg = msg; + c.media = NULL; + + p = (gchar *) data; + while (TRUE) { + while (g_ascii_isspace (*p)) + p++; + + type = *p++; + if (type == '\0') + break; + + if (*p != '=') + goto line_done; + p++; + + idx = 0; + while (*p != '\n' && *p != '\r' && *p != '\0') { + if (idx < sizeof (buffer) - 1) + buffer[idx++] = *p; + p++; + } + buffer[idx] = '\0'; + gst_sdp_parse_line (&c, type, buffer); + + line_done: + while (*p != '\n' && *p != '\0') + p++; + if (*p == '\n') + p++; + } + + return GST_SDP_OK; +} + +static void +print_media (GstSDPMedia * media) +{ + g_print (" media: '%s'\n", GST_STR_NULL (media->media)); + g_print (" port: '%u'\n", media->port); + g_print (" num_ports: '%u'\n", media->num_ports); + g_print (" proto: '%s'\n", GST_STR_NULL (media->proto)); + if (media->fmts->len > 0) { + guint i; + + g_print (" formats:\n"); + for (i = 0; i < media->fmts->len; i++) { + g_print (" format '%s'\n", g_array_index (media->fmts, gchar *, i)); + } + } + g_print (" information: '%s'\n", GST_STR_NULL (media->information)); + if (media->connections->len > 0) { + guint i; + + g_print (" connections:\n"); + for (i = 0; i < media->connections->len; i++) { + GstSDPConnection *conn = + &g_array_index (media->connections, GstSDPConnection, i); + + g_print (" nettype: '%s'\n", GST_STR_NULL (conn->nettype)); + g_print (" addrtype: '%s'\n", GST_STR_NULL (conn->addrtype)); + g_print (" address: '%s'\n", GST_STR_NULL (conn->address)); + g_print (" ttl: '%u'\n", conn->ttl); + g_print (" addr_number: '%u'\n", conn->addr_number); + } + } + if (media->bandwidths->len > 0) { + guint i; + + g_print (" bandwidths:\n"); + for (i = 0; i < media->bandwidths->len; i++) { + GstSDPBandwidth *bw = + &g_array_index (media->bandwidths, GstSDPBandwidth, i); + + g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype)); + g_print (" bandwidth: '%u'\n", bw->bandwidth); + } + } + g_print (" key:\n"); + g_print (" type: '%s'\n", GST_STR_NULL (media->key.type)); + g_print (" data: '%s'\n", GST_STR_NULL (media->key.data)); + if (media->attributes->len > 0) { + guint i; + + g_print (" attributes:\n"); + for (i = 0; i < media->attributes->len; i++) { + GstSDPAttribute *attr = + &g_array_index (media->attributes, GstSDPAttribute, i); + + g_print (" attribute '%s' : '%s'\n", attr->key, attr->value); + } + } +} + +/** + * gst_sdp_message_dump: + * @msg: a #GstSDPMessage + * + * Dump the parsed contents of @msg to stdout. + * + * Returns: a #GstSDPResult. + */ +GstSDPResult +gst_sdp_message_dump (const GstSDPMessage * msg) +{ + g_return_val_if_fail (msg != NULL, GST_SDP_EINVAL); + + g_print ("sdp packet %p:\n", msg); + g_print (" version: '%s'\n", GST_STR_NULL (msg->version)); + g_print (" origin:\n"); + g_print (" username: '%s'\n", GST_STR_NULL (msg->origin.username)); + g_print (" sess_id: '%s'\n", GST_STR_NULL (msg->origin.sess_id)); + g_print (" sess_version: '%s'\n", GST_STR_NULL (msg->origin.sess_version)); + g_print (" nettype: '%s'\n", GST_STR_NULL (msg->origin.nettype)); + g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->origin.addrtype)); + g_print (" addr: '%s'\n", GST_STR_NULL (msg->origin.addr)); + g_print (" session_name: '%s'\n", GST_STR_NULL (msg->session_name)); + g_print (" information: '%s'\n", GST_STR_NULL (msg->information)); + g_print (" uri: '%s'\n", GST_STR_NULL (msg->uri)); + + if (msg->emails->len > 0) { + guint i; + + g_print (" emails:\n"); + for (i = 0; i < msg->emails->len; i++) { + g_print (" email '%s'\n", g_array_index (msg->emails, gchar *, i)); + } + } + if (msg->phones->len > 0) { + guint i; + + g_print (" phones:\n"); + for (i = 0; i < msg->phones->len; i++) { + g_print (" phone '%s'\n", g_array_index (msg->phones, gchar *, i)); + } + } + g_print (" connection:\n"); + g_print (" nettype: '%s'\n", GST_STR_NULL (msg->connection.nettype)); + g_print (" addrtype: '%s'\n", GST_STR_NULL (msg->connection.addrtype)); + g_print (" address: '%s'\n", GST_STR_NULL (msg->connection.address)); + g_print (" ttl: '%u'\n", msg->connection.ttl); + g_print (" addr_number: '%u'\n", msg->connection.addr_number); + if (msg->bandwidths->len > 0) { + guint i; + + g_print (" bandwidths:\n"); + for (i = 0; i < msg->bandwidths->len; i++) { + GstSDPBandwidth *bw = + &g_array_index (msg->bandwidths, GstSDPBandwidth, i); + + g_print (" type: '%s'\n", GST_STR_NULL (bw->bwtype)); + g_print (" bandwidth: '%u'\n", bw->bandwidth); + } + } + g_print (" key:\n"); + g_print (" type: '%s'\n", GST_STR_NULL (msg->key.type)); + g_print (" data: '%s'\n", GST_STR_NULL (msg->key.data)); + if (msg->attributes->len > 0) { + guint i; + + g_print (" attributes:\n"); + for (i = 0; i < msg->attributes->len; i++) { + GstSDPAttribute *attr = + &g_array_index (msg->attributes, GstSDPAttribute, i); + + g_print (" attribute '%s' : '%s'\n", attr->key, attr->value); + } + } + if (msg->medias->len > 0) { + guint i; + + g_print (" medias:\n"); + for (i = 0; i < msg->medias->len; i++) { + g_print (" media %u:\n", i); + print_media (&g_array_index (msg->medias, GstSDPMedia, i)); + } + } + return GST_SDP_OK; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.h new file mode 100644 index 0000000..069eb38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/sdp/gstsdpmessage.h @@ -0,0 +1,423 @@ +/* GStreamer + * Copyright (C) <2005,2006> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_SDP_MESSAGE_H__ +#define __GST_SDP_MESSAGE_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * GstSDPOrigin: + * @username: the user's login on the originating host, or it is "-" + * if the originating host does not support the concept of user ids. + * @sess_id: is a numeric string such that the tuple of @username, @sess_id, + * @nettype, @addrtype and @addr form a globally unique identifier for the + * session. + * @sess_version: a version number for this announcement + * @nettype: the type of network. "IN" is defined to have the meaning + * "Internet". + * @addrtype: the type of @addr. + * @addr: the globally unique address of the machine from which the session was + * created. + * + * The contents of the SDP "o=" field which gives the originator of the session + * (their username and the address of the user's host) plus a session id and + * session version number. + */ +typedef struct { + gchar *username; + gchar *sess_id; + gchar *sess_version; + gchar *nettype; + gchar *addrtype; + gchar *addr; +} GstSDPOrigin; + +/** + * GstSDPConnection: + * @nettype: the type of network. "IN" is defined to have the meaning + * "Internet". + * @addrtype: the type of @address. + * @address: the address + * @ttl: the time to live of the address + * @addr_number: the number of layers + * + * The contents of the SDP "c=" field which contains connection data. + */ +typedef struct { + gchar *nettype; + gchar *addrtype; + gchar *address; + guint ttl; + guint addr_number; +} GstSDPConnection; + +/** + * GST_SDP_BWTYPE_CT: + * + * The Conference Total bandwidth modifier. + */ +#define GST_SDP_BWTYPE_CT "CT" +/** + * GST_SDP_BWTYPE_AS: + * + * The Application-Specific Maximum bandwidth modifier. + */ +#define GST_SDP_BWTYPE_AS "AS" +/** + * GST_SDP_BWTYPE_EXT_PREFIX: + * + * The extension prefix bandwidth modifier. + */ +#define GST_SDP_BWTYPE_EXT_PREFIX "X-" + +/** + * GST_SDP_BWTYPE_RS: + * + * RTCP bandwidth allocated to active data senders (RFC 3556). + * + * Since: 0.10.15 + */ +#define GST_SDP_BWTYPE_RS "RS" +/** + * GST_SDP_BWTYPE_RR: + * + * RTCP bandwidth allocated to data receivers (RFC 3556). + * + * Since: 0.10.15 + */ +#define GST_SDP_BWTYPE_RR "RR" +/** + * GST_SDP_BWTYPE_TIAS: + * + * Transport Independent Application Specific Maximum bandwidth (RFC 3890). + * + * Since: 0.10.30 + */ +#define GST_SDP_BWTYPE_TIAS "TIAS" + + +/** + * GstSDPBandwidth: + * @bwtype: the bandwidth modifier type + * @bandwidth: the bandwidth in kilobits per second + * + * The contents of the SDP "b=" field which specifies the proposed bandwidth to + * be used by the session or media. + */ +typedef struct { + gchar *bwtype; + guint bandwidth; +} GstSDPBandwidth; + +/** + * GstSDPTime: + * @start: start time for the conference. The value is the decimal + * representation of Network Time Protocol (NTP) time values in seconds + * @stop: stop time for the conference. The value is the decimal + * representation of Network Time Protocol (NTP) time values in seconds + * @repeat: repeat times for a session + * + * The contents of the SDP "t=" field which specify the start and stop times for + * a conference session. + */ +typedef struct { + gchar *start; + gchar *stop; + GArray *repeat; +} GstSDPTime; + +/** + * GstSDPZone: + * @time: the NTP time that a time zone adjustment happens + * @typed_time: the offset from the time when the session was first scheduled + * + * The contents of the SDP "z=" field which allows the sender to + * specify a list of time zone adjustments and offsets from the base + * time. + */ +typedef struct { + gchar *time; + gchar *typed_time; +} GstSDPZone; + +/** + * GstSDPKey: + * @type: the encryption type + * @data: the encryption data + * + * The contents of the SDP "k=" field which is used to convey encryption + * keys. + */ +typedef struct { + gchar *type; + gchar *data; +} GstSDPKey; + +/** + * GstSDPAttribute: + * @key: the attribute key + * @value: the attribute value or NULL when it was a property attribute + * + * The contents of the SDP "a=" field which contains a key/value pair. + */ +typedef struct { + gchar *key; + gchar *value; +} GstSDPAttribute; + +/** + * GstSDPMedia: + * @media: the media type + * @port: the transport port to which the media stream will be sent + * @num_ports: the number of ports or -1 if only one port was specified + * @proto: the transport protocol + * @fmts: an array of #gchar formats + * @information: the media title + * @connections: array of #GstSDPConnection with media connection information + * @bandwidths: array of #GstSDPBandwidth with media bandwidth information + * @key: the encryption key + * @attributes: array of #GstSDPAttribute with the additional media attributes + * + * The contents of the SDP "m=" field with all related fields. + */ +typedef struct { + gchar *media; + guint port; + guint num_ports; + gchar *proto; + GArray *fmts; + gchar *information; + GArray *connections; + GArray *bandwidths; + GstSDPKey key; + GArray *attributes; +} GstSDPMedia; + +/** + * GstSDPMessage: + * @version: the protocol version + * @origin: owner/creator and session identifier + * @session_name: session name + * @information: session information + * @uri: URI of description + * @emails: array of #gchar with email addresses + * @phones: array of #gchar with phone numbers + * @connection: connection information for the session + * @bandwidths: array of #GstSDPBandwidth with bandwidth information + * @times: array of #GstSDPTime with time descriptions + * @zones: array of #GstSDPZone with time zone adjustments + * @key: encryption key + * @attributes: array of #GstSDPAttribute with session attributes + * @medias: array of #GstSDPMedia with media descriptions + * + * The contents of the SDP message. + */ +typedef struct { + gchar *version; + GstSDPOrigin origin; + gchar *session_name; + gchar *information; + gchar *uri; + GArray *emails; + GArray *phones; + GstSDPConnection connection; + GArray *bandwidths; + GArray *times; + GArray *zones; + GstSDPKey key; + GArray *attributes; + GArray *medias; +} GstSDPMessage; + +/* Session descriptions */ +GstSDPResult gst_sdp_message_new (GstSDPMessage **msg); +GstSDPResult gst_sdp_message_init (GstSDPMessage *msg); +GstSDPResult gst_sdp_message_uninit (GstSDPMessage *msg); +GstSDPResult gst_sdp_message_free (GstSDPMessage *msg); + +GstSDPResult gst_sdp_message_parse_buffer (const guint8 *data, guint size, GstSDPMessage *msg); +gchar* gst_sdp_message_as_text (const GstSDPMessage *msg); + +/* convert from/to uri */ +GstSDPResult gst_sdp_message_parse_uri (const gchar *uri, GstSDPMessage *msg); +gchar* gst_sdp_message_as_uri (const gchar *scheme, const GstSDPMessage *msg); + +/* utils */ +gboolean gst_sdp_address_is_multicast (const gchar *nettype, const gchar *addrtype, + const gchar *addr); +/* v=.. */ +const gchar* gst_sdp_message_get_version (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_version (GstSDPMessage *msg, const gchar *version); + +/* o= */ +const GstSDPOrigin* gst_sdp_message_get_origin (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_origin (GstSDPMessage *msg, const gchar *username, + const gchar *sess_id, const gchar *sess_version, + const gchar *nettype, const gchar *addrtype, + const gchar *addr); + +/* s= */ +const gchar* gst_sdp_message_get_session_name (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_session_name (GstSDPMessage *msg, const gchar *session_name); + +/* i= */ +const gchar* gst_sdp_message_get_information (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_information (GstSDPMessage *msg, const gchar *information); + +/* u= */ +const gchar* gst_sdp_message_get_uri (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_uri (GstSDPMessage *msg, const gchar *uri); + +/* e= */ +guint gst_sdp_message_emails_len (const GstSDPMessage *msg); +const gchar* gst_sdp_message_get_email (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_email (GstSDPMessage *msg, const gchar *email); + +/* p= */ +guint gst_sdp_message_phones_len (const GstSDPMessage *msg); +const gchar* gst_sdp_message_get_phone (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_phone (GstSDPMessage *msg, const gchar *phone); + +/* c= [/][/] */ +const GstSDPConnection* gst_sdp_message_get_connection (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_connection (GstSDPMessage *msg, const gchar *nettype, + const gchar *addrtype, const gchar *address, + guint ttl, guint addr_number); +/* b=: */ +guint gst_sdp_message_bandwidths_len (const GstSDPMessage *msg); +const GstSDPBandwidth* gst_sdp_message_get_bandwidth (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_bandwidth (GstSDPMessage *msg, const gchar *bwtype, + guint bandwidth); +/* t= and + * r= */ +guint gst_sdp_message_times_len (const GstSDPMessage *msg); +const GstSDPTime* gst_sdp_message_get_time (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_time (GstSDPMessage *msg, const gchar *start, const gchar *stop, const gchar **repeat); + +/* z= .... */ +guint gst_sdp_message_zones_len (const GstSDPMessage *msg); +const GstSDPZone* gst_sdp_message_get_zone (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_zone (GstSDPMessage *msg, const gchar *adj_time, + const gchar *typed_time); + +/* k=[:] */ +const GstSDPKey* gst_sdp_message_get_key (const GstSDPMessage *msg); +GstSDPResult gst_sdp_message_set_key (GstSDPMessage *msg, const gchar *type, + const gchar *data); +/* a=... */ +guint gst_sdp_message_attributes_len (const GstSDPMessage *msg); +const GstSDPAttribute* gst_sdp_message_get_attribute (const GstSDPMessage *msg, guint idx); +const gchar* gst_sdp_message_get_attribute_val (const GstSDPMessage *msg, const gchar *key); +const gchar* gst_sdp_message_get_attribute_val_n (const GstSDPMessage *msg, const gchar *key, + guint nth); +GstSDPResult gst_sdp_message_add_attribute (GstSDPMessage *msg, const gchar *key, + const gchar *value); + +/* m=.. sections */ +guint gst_sdp_message_medias_len (const GstSDPMessage *msg); +const GstSDPMedia* gst_sdp_message_get_media (const GstSDPMessage *msg, guint idx); +GstSDPResult gst_sdp_message_add_media (GstSDPMessage *msg, GstSDPMedia *media); + +GstSDPResult gst_sdp_message_dump (const GstSDPMessage *msg); + +/* Media descriptions */ +GstSDPResult gst_sdp_media_new (GstSDPMedia **media); +GstSDPResult gst_sdp_media_init (GstSDPMedia *media); +GstSDPResult gst_sdp_media_uninit (GstSDPMedia *media); +GstSDPResult gst_sdp_media_free (GstSDPMedia *media); + +gchar* gst_sdp_media_as_text (const GstSDPMedia *media); + +/* m= / ... */ +const gchar* gst_sdp_media_get_media (const GstSDPMedia *media); +GstSDPResult gst_sdp_media_set_media (GstSDPMedia *media, const gchar *med); + +guint gst_sdp_media_get_port (const GstSDPMedia *media); +guint gst_sdp_media_get_num_ports (const GstSDPMedia *media); +GstSDPResult gst_sdp_media_set_port_info (GstSDPMedia *media, guint port, + guint num_ports); + +const gchar* gst_sdp_media_get_proto (const GstSDPMedia *media); +GstSDPResult gst_sdp_media_set_proto (GstSDPMedia *media, const gchar *proto); + +guint gst_sdp_media_formats_len (const GstSDPMedia *media); +const gchar* gst_sdp_media_get_format (const GstSDPMedia *media, guint idx); +GstSDPResult gst_sdp_media_add_format (GstSDPMedia *media, const gchar *format); + +/* i= */ +const gchar* gst_sdp_media_get_information (const GstSDPMedia *media); +GstSDPResult gst_sdp_media_set_information (GstSDPMedia *media, const gchar *information); + +/* c= [/][/] */ +guint gst_sdp_media_connections_len (const GstSDPMedia *media); +const GstSDPConnection* gst_sdp_media_get_connection (const GstSDPMedia *media, guint idx); +GstSDPResult gst_sdp_media_add_connection (GstSDPMedia *media, const gchar *nettype, + const gchar *addrtype, const gchar *address, + guint ttl, guint addr_number); + +/* b=: */ +guint gst_sdp_media_bandwidths_len (const GstSDPMedia *media); +const GstSDPBandwidth* gst_sdp_media_get_bandwidth (const GstSDPMedia *media, guint idx); +GstSDPResult gst_sdp_media_add_bandwidth (GstSDPMedia *media, const gchar *bwtype, + guint bandwidth); + +/* k=: */ +const GstSDPKey* gst_sdp_media_get_key (const GstSDPMedia *media); +GstSDPResult gst_sdp_media_set_key (GstSDPMedia *media, const gchar *type, + const gchar *data); +/* a=... */ +guint gst_sdp_media_attributes_len (const GstSDPMedia *media); +const GstSDPAttribute * gst_sdp_media_get_attribute (const GstSDPMedia *media, guint idx); +const gchar* gst_sdp_media_get_attribute_val (const GstSDPMedia *media, const gchar *key); +const gchar* gst_sdp_media_get_attribute_val_n (const GstSDPMedia *media, const gchar *key, + guint nth); +GstSDPResult gst_sdp_media_add_attribute (GstSDPMedia *media, const gchar *key, + const gchar *value); + +G_END_DECLS + +#endif /* __GST_SDP_MESSAGE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/Makefile.am new file mode 100644 index 0000000..9977d66 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/Makefile.am @@ -0,0 +1,96 @@ +libgsttagincludedir = \ + $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/tag + +libgsttaginclude_HEADERS = \ + tag.h gsttagdemux.h xmpwriter.h + +lib_LTLIBRARIES = libgsttag-@GST_MAJORMINOR@.la + +libgsttag_@GST_MAJORMINOR@_la_SOURCES = \ + gstvorbistag.c gstid3tag.c gstxmptag.c gstexiftag.c \ + lang.c tags.c gsttagdemux.c gsttageditingprivate.c xmpwriter.c +libgsttag_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgsttag_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(LIBM) +libgsttag_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +# lang-tables.dat contains generated static data and is included by lang.c +EXTRA_DIST = lang-tables.dat + +noinst_HEADERS = gsttageditingprivate.h + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstTag-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgsttaginclude_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgsttag_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/tag/%',$(libgsttaginclude_HEADERS)) + +GstTag-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgsttag-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstTag \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgsttag-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-tag-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES = $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +# little program that reads iso_639.xml and outputs tables for us as fallback +# for when iso-codes are not available (and so we don't have to read the xml +# just to map codes) +if USE_ISO_CODES +ISO_CODE_PROGS = mklangtables +mklangtables_SOURCES = mklangtables.c +mklangtables_CFLAGS = $(GST_CFLAGS) +mklangtables_LDADD = $(GST_LIBS) +else +ISO_CODE_PROGS = +endif + +noinst_PROGRAMS = $(ISO_CODE_PROGS) + +Android.mk: Makefile.am + androgenizer -:PROJECT libgsttag -:SHARED libgsttag-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgsttag_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(libgsttag_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgsttag_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgsttag_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/tag \ + -:HEADERS $(libgsttaginclude_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstexiftag.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstexiftag.c new file mode 100644 index 0000000..c97901c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstexiftag.c @@ -0,0 +1,2655 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * gstexiftag.c: library for reading / modifying exif tags + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttagexif + * @short_description: tag mappings and support functions for plugins + * dealing with exif tags + * @see_also: #GstTagList + * + * Contains utility function to parse #GstTagLists from exif + * buffers and to create exif buffers from #GstTagLists + * + * Note that next IFD fields on the created exif buffers are set to 0. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "gsttageditingprivate.h" + +#include +#include +#include +#include + +/* Some useful constants */ +#define TIFF_LITTLE_ENDIAN 0x4949 +#define TIFF_BIG_ENDIAN 0x4D4D +#define TIFF_HEADER_SIZE 8 +#define EXIF_TAG_ENTRY_SIZE (2 + 2 + 4 + 4) + +/* Exif tag types */ +#define EXIF_TYPE_BYTE 1 +#define EXIF_TYPE_ASCII 2 +#define EXIF_TYPE_SHORT 3 +#define EXIF_TYPE_LONG 4 +#define EXIF_TYPE_RATIONAL 5 +#define EXIF_TYPE_UNDEFINED 7 +#define EXIF_TYPE_SLONG 9 +#define EXIF_TYPE_SRATIONAL 10 + +typedef struct _GstExifTagMatch GstExifTagMatch; +typedef struct _GstExifWriter GstExifWriter; +typedef struct _GstExifReader GstExifReader; +typedef struct _GstExifTagData GstExifTagData; + +typedef void (*GstExifSerializationFunc) (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag); + +/* + * Function used to deserialize tags that don't follow the usual + * deserialization conversions. Usually those that have 'Ref' complementary + * tags. + * + * Those functions receive a exif tag data in the parameters, plus the taglist + * and the reader and buffer if they need to get more information to build + * its tags. There are lots of parameters, but this is needed to make it + * versatile. Explanation of them follows: + * + * exif_reader: The #GstExifReader with the reading parameter and taglist for + * results. + * reader: The #GstByteReader pointing to the start of the next tag entry in + * the ifd, useful for tags that use other complementary tags. + * the buffer start + * exiftag: The #GstExifTagMatch that contains this tag info + * tagdata: values from the already parsed tag + */ +typedef gint (*GstExifDeserializationFunc) (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata); + +#define EXIF_SERIALIZATION_FUNC(name) \ +static void serialize_ ## name (GstExifWriter * writer, \ + const GstTagList * taglist, const GstExifTagMatch * exiftag) + +#define EXIF_DESERIALIZATION_FUNC(name) \ +static gint deserialize_ ## name (GstExifReader * exif_reader, \ + GstByteReader * reader, const GstExifTagMatch * exiftag, \ + GstExifTagData * tagdata) + +#define EXIF_SERIALIZATION_DESERIALIZATION_FUNC(name) \ + EXIF_SERIALIZATION_FUNC (name); \ + EXIF_DESERIALIZATION_FUNC (name) + +/* + * A common case among serialization/deserialization routines is that + * the gstreamer tag is a string (with a predefined set of allowed values) + * and exif is an int. These macros cover these cases + */ +#define EXIF_SERIALIZATION_MAP_STRING_TO_INT_FUNC(name,funcname) \ +static void \ +serialize_ ## name (GstExifWriter * writer, const GstTagList * taglist, \ + const GstExifTagMatch * exiftag) \ +{ \ + gchar *str = NULL; \ + gint exif_value; \ +\ + if (!gst_tag_list_get_string_index (taglist, exiftag->gst_tag, 0, &str)) { \ + GST_WARNING ("No %s tag present in taglist", exiftag->gst_tag); \ + return; \ + } \ +\ + exif_value = __exif_tag_ ## funcname ## _to_exif_value (str); \ + if (exif_value == -1) { \ + g_free (str); \ + return; \ + } \ + g_free (str); \ +\ + switch (exiftag->exif_type) { \ + case EXIF_TYPE_SHORT: \ + gst_exif_writer_write_short_tag (writer, exiftag->exif_tag, exif_value); \ + break; \ + case EXIF_TYPE_LONG: \ + gst_exif_writer_write_long_tag (writer, exiftag->exif_tag, exif_value); \ + break; \ + case EXIF_TYPE_UNDEFINED: \ + { \ + guint8 data = (guint8) exif_value; \ + write_exif_undefined_tag (writer, exiftag->exif_tag, &data, 1); \ + } \ + break; \ + default: \ + g_assert_not_reached (); \ + GST_WARNING ("Unmapped serialization for type %d", exiftag->exif_type); \ + break; \ + } \ +} + +#define EXIF_DESERIALIZATION_MAP_STRING_TO_INT_FUNC(name,funcname) \ +static gint \ +deserialize_ ## name (GstExifReader * exif_reader, \ + GstByteReader * reader, const GstExifTagMatch * exiftag, \ + GstExifTagData * tagdata) \ +{ \ + const gchar *str = NULL; \ + gint value; \ +\ + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, \ + exiftag->exif_tag); \ +\ + /* validate tag */ \ + if (tagdata->count != 1) { \ + GST_WARNING ("0x%X has unexpected count", tagdata->count); \ + return 0; \ + } \ +\ + if (tagdata->tag_type == EXIF_TYPE_SHORT) { \ + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { \ + value = GST_READ_UINT16_LE (tagdata->offset_as_data); \ + } else { \ + value = GST_READ_UINT16_BE (tagdata->offset_as_data); \ + } \ + } else if (tagdata->tag_type == EXIF_TYPE_UNDEFINED) { \ + value = GST_READ_UINT8 (tagdata->offset_as_data); \ + } else { \ + GST_WARNING ("0x%X has unexpected type %d", exiftag->exif_tag, \ + tagdata->tag_type); \ + return 0; \ + } \ +\ + str = __exif_tag_## funcname ## _from_exif_value (value); \ + if (str == NULL) { \ + GST_WARNING ("Invalid value for tag 0x%X: %d", tagdata->tag, value); \ + return 0; \ + } \ + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, \ + exiftag->gst_tag, str, NULL); \ +\ + return 0; \ +} + +#define EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC(name,funcname) \ + EXIF_SERIALIZATION_MAP_STRING_TO_INT_FUNC(name,funcname); \ + EXIF_DESERIALIZATION_MAP_STRING_TO_INT_FUNC(name,funcname); + +struct _GstExifTagMatch +{ + const gchar *gst_tag; + guint16 exif_tag; + guint16 exif_type; + + /* for tags that need special handling */ + guint16 complementary_tag; + GstExifSerializationFunc serialize; + GstExifDeserializationFunc deserialize; +}; + +struct _GstExifTagData +{ + guint16 tag; + guint16 tag_type; + guint32 count; + guint32 offset; + const guint8 *offset_as_data; +}; + +/* + * Holds the info and variables necessary to write + * the exif tags properly + */ +struct _GstExifWriter +{ + GstByteWriter tagwriter; + GstByteWriter datawriter; + + gint byte_order; + guint tags_total; +}; + +struct _GstExifReader +{ + GstTagList *taglist; + const GstBuffer *buffer; + guint32 base_offset; + gint byte_order; + + /* tags waiting for their complementary tags */ + GSList *pending_tags; +}; + +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (aperture_value); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (contrast); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (exposure_program); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (exposure_mode); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (flash); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (gain_control); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (geo_coordinate); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (geo_direction); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (geo_elevation); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (metering_mode); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (orientation); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (saturation); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (scene_capture_type); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (scene_type); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (sensitivity_type); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (sharpness); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (shutter_speed); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (source); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (speed); +EXIF_SERIALIZATION_DESERIALIZATION_FUNC (white_balance); + +EXIF_DESERIALIZATION_FUNC (resolution); +EXIF_DESERIALIZATION_FUNC (add_to_pending_tags); + +/* FIXME copyright tag has a weird "artist\0editor\0" format that is + * not yet handled */ + +/* exif tag numbers */ +#define EXIF_TAG_GPS_LATITUDE_REF 0x1 +#define EXIF_TAG_GPS_LATITUDE 0x2 +#define EXIF_TAG_GPS_LONGITUDE_REF 0x3 +#define EXIF_TAG_GPS_LONGITUDE 0x4 +#define EXIF_TAG_GPS_ALTITUDE_REF 0x5 +#define EXIF_TAG_GPS_ALTITUDE 0x6 +#define EXIF_TAG_GPS_SPEED_REF 0xC +#define EXIF_TAG_GPS_SPEED 0xD +#define EXIF_TAG_GPS_TRACK_REF 0xE +#define EXIF_TAG_GPS_TRACK 0xF +#define EXIF_TAG_GPS_IMAGE_DIRECTION_REF 0x10 +#define EXIF_TAG_GPS_IMAGE_DIRECTION 0x11 +#define EXIF_TAG_GPS_HORIZONTAL_POSITIONING_ERROR 0x1F +#define EXIF_TAG_IMAGE_DESCRIPTION 0x10E +#define EXIF_TAG_MAKE 0x10F +#define EXIF_TAG_MODEL 0x110 +#define EXIF_TAG_ORIENTATION 0x112 +#define EXIF_TAG_XRESOLUTION 0x11A +#define EXIF_TAG_YRESOLUTION 0x11B +#define EXIF_TAG_RESOLUTION_UNIT 0x128 +#define EXIF_TAG_SOFTWARE 0x131 +#define EXIF_TAG_DATE_TIME 0x132 +#define EXIF_TAG_ARTIST 0x13B +#define EXIF_TAG_COPYRIGHT 0x8298 +#define EXIF_TAG_EXPOSURE_TIME 0x829A +#define EXIF_TAG_F_NUMBER 0x829D +#define EXIF_TAG_EXPOSURE_PROGRAM 0x8822 +#define EXIF_TAG_PHOTOGRAPHIC_SENSITIVITY 0x8827 +#define EXIF_TAG_SENSITIVITY_TYPE 0x8830 +#define EXIF_TAG_ISO_SPEED 0x8833 +#define EXIF_TAG_DATE_TIME_ORIGINAL 0x9003 +#define EXIF_TAG_DATE_TIME_DIGITIZED 0x9004 +#define EXIF_TAG_SHUTTER_SPEED_VALUE 0x9201 +#define EXIF_TAG_APERTURE_VALUE 0x9202 +#define EXIF_TAG_EXPOSURE_BIAS 0x9204 +#define EXIF_TAG_METERING_MODE 0x9207 +#define EXIF_TAG_FLASH 0x9209 +#define EXIF_TAG_FOCAL_LENGTH 0x920A +#define EXIF_TAG_MAKER_NOTE 0x927C +#define EXIF_TAG_FILE_SOURCE 0xA300 +#define EXIF_TAG_SCENE_TYPE 0xA301 +#define EXIF_TAG_EXPOSURE_MODE 0xA402 +#define EXIF_TAG_WHITE_BALANCE 0xA403 +#define EXIF_TAG_DIGITAL_ZOOM_RATIO 0xA404 +#define EXIF_TAG_SCENE_CAPTURE_TYPE 0xA406 +#define EXIF_TAG_GAIN_CONTROL 0xA407 +#define EXIF_TAG_CONTRAST 0xA408 +#define EXIF_TAG_SATURATION 0xA409 +#define EXIF_TAG_SHARPNESS 0xA40A + +/* IFD pointer tags */ +#define EXIF_IFD_TAG 0x8769 +#define EXIF_GPS_IFD_TAG 0x8825 + +/* version tags */ +#define EXIF_VERSION_TAG 0x9000 +#define EXIF_FLASHPIX_VERSION_TAG 0xA000 + +/* useful macros for speed tag */ +#define METERS_PER_SECOND_TO_KILOMETERS_PER_HOUR (3.6) +#define KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND (1/3.6) +#define MILES_PER_HOUR_TO_METERS_PER_SECOND (0.44704) +#define KNOTS_TO_METERS_PER_SECOND (0.514444) + +/* + * Should be kept in ascending id order + * + * {gst-tag, exif-tag, exig-type, complementary-exif-tag, serialization-func, + * deserialization-func} + */ +static const GstExifTagMatch tag_map_ifd0[] = { + {GST_TAG_IMAGE_HORIZONTAL_PPI, EXIF_TAG_XRESOLUTION, EXIF_TYPE_RATIONAL, + 0, NULL, deserialize_add_to_pending_tags}, + {GST_TAG_IMAGE_VERTICAL_PPI, EXIF_TAG_YRESOLUTION, EXIF_TYPE_RATIONAL, + 0, NULL, deserialize_add_to_pending_tags}, + {NULL, EXIF_TAG_RESOLUTION_UNIT, EXIF_TYPE_SHORT, 0, NULL, + deserialize_resolution}, + {GST_TAG_DESCRIPTION, EXIF_TAG_IMAGE_DESCRIPTION, EXIF_TYPE_ASCII, 0, NULL, + NULL}, + {GST_TAG_DEVICE_MANUFACTURER, EXIF_TAG_MAKE, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_DEVICE_MODEL, EXIF_TAG_MODEL, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_IMAGE_ORIENTATION, EXIF_TAG_ORIENTATION, EXIF_TYPE_SHORT, 0, + serialize_orientation, + deserialize_orientation}, + {GST_TAG_APPLICATION_NAME, EXIF_TAG_SOFTWARE, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_DATE_TIME, EXIF_TAG_DATE_TIME, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_ARTIST, EXIF_TAG_ARTIST, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_COPYRIGHT, EXIF_TAG_COPYRIGHT, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {NULL, EXIF_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL}, + {NULL, EXIF_GPS_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL}, + {NULL, 0, 0, 0, NULL, NULL} +}; + +static const GstExifTagMatch tag_map_exif[] = { + {GST_TAG_CAPTURING_SHUTTER_SPEED, EXIF_TAG_EXPOSURE_TIME, EXIF_TYPE_RATIONAL, + 0, + NULL, NULL}, + {GST_TAG_CAPTURING_FOCAL_RATIO, EXIF_TAG_F_NUMBER, EXIF_TYPE_RATIONAL, 0, + NULL, + NULL}, + {GST_TAG_CAPTURING_EXPOSURE_PROGRAM, EXIF_TAG_EXPOSURE_PROGRAM, + EXIF_TYPE_SHORT, 0, serialize_exposure_program, + deserialize_exposure_program}, + + /* don't need the serializer as we always write the iso speed alone */ + {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_PHOTOGRAPHIC_SENSITIVITY, + EXIF_TYPE_SHORT, 0, NULL, + deserialize_add_to_pending_tags}, + + {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_SENSITIVITY_TYPE, EXIF_TYPE_SHORT, 0, + serialize_sensitivity_type, deserialize_sensitivity_type}, + {GST_TAG_CAPTURING_ISO_SPEED, EXIF_TAG_ISO_SPEED, EXIF_TYPE_LONG, 0, NULL, + NULL}, + {NULL, EXIF_VERSION_TAG, EXIF_TYPE_UNDEFINED, 0, NULL, NULL}, + {GST_TAG_DATE_TIME, EXIF_TAG_DATE_TIME_ORIGINAL, EXIF_TYPE_ASCII, 0, NULL, + NULL}, + {GST_TAG_CAPTURING_SHUTTER_SPEED, EXIF_TAG_SHUTTER_SPEED_VALUE, + EXIF_TYPE_SRATIONAL, 0, + serialize_shutter_speed, deserialize_shutter_speed}, + {GST_TAG_CAPTURING_FOCAL_RATIO, EXIF_TAG_APERTURE_VALUE, EXIF_TYPE_RATIONAL, + 0, + serialize_aperture_value, deserialize_aperture_value}, + {GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, EXIF_TAG_EXPOSURE_BIAS, + EXIF_TYPE_SRATIONAL, 0, NULL, NULL}, + {GST_TAG_CAPTURING_METERING_MODE, EXIF_TAG_METERING_MODE, EXIF_TYPE_SHORT, 0, + serialize_metering_mode, deserialize_metering_mode}, + {GST_TAG_CAPTURING_FLASH_FIRED, EXIF_TAG_FLASH, EXIF_TYPE_SHORT, 0, + serialize_flash, deserialize_flash}, + {GST_TAG_CAPTURING_FOCAL_LENGTH, EXIF_TAG_FOCAL_LENGTH, EXIF_TYPE_RATIONAL, 0, + NULL, NULL}, + {GST_TAG_APPLICATION_DATA, EXIF_TAG_MAKER_NOTE, EXIF_TYPE_UNDEFINED, 0, NULL, + NULL}, + {NULL, EXIF_FLASHPIX_VERSION_TAG, EXIF_TYPE_UNDEFINED, 0, NULL, NULL}, + {GST_TAG_CAPTURING_SOURCE, EXIF_TAG_FILE_SOURCE, EXIF_TYPE_UNDEFINED, + 0, serialize_source, deserialize_source}, + {GST_TAG_CAPTURING_SOURCE, EXIF_TAG_SCENE_TYPE, EXIF_TYPE_UNDEFINED, + 0, serialize_scene_type, deserialize_scene_type}, + {GST_TAG_CAPTURING_EXPOSURE_MODE, EXIF_TAG_EXPOSURE_MODE, EXIF_TYPE_SHORT, + 0, serialize_exposure_mode, deserialize_exposure_mode}, + {GST_TAG_CAPTURING_WHITE_BALANCE, EXIF_TAG_WHITE_BALANCE, EXIF_TYPE_SHORT, + 0, serialize_white_balance, deserialize_white_balance}, + {GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, EXIF_TAG_DIGITAL_ZOOM_RATIO, + EXIF_TYPE_RATIONAL, 0, NULL, + NULL}, + {GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, EXIF_TAG_SCENE_CAPTURE_TYPE, + EXIF_TYPE_SHORT, 0, serialize_scene_capture_type, + deserialize_scene_capture_type}, + {GST_TAG_CAPTURING_GAIN_ADJUSTMENT, EXIF_TAG_GAIN_CONTROL, + EXIF_TYPE_SHORT, 0, serialize_gain_control, + deserialize_gain_control}, + {GST_TAG_CAPTURING_CONTRAST, EXIF_TAG_CONTRAST, EXIF_TYPE_SHORT, 0, + serialize_contrast, deserialize_contrast}, + {GST_TAG_CAPTURING_SATURATION, EXIF_TAG_SATURATION, EXIF_TYPE_SHORT, 0, + serialize_saturation, deserialize_saturation}, + {GST_TAG_CAPTURING_SHARPNESS, EXIF_TAG_SHARPNESS, EXIF_TYPE_SHORT, 0, + serialize_sharpness, deserialize_sharpness}, + {NULL, 0, 0, 0, NULL, NULL} +}; + +static const GstExifTagMatch tag_map_gps[] = { + {GST_TAG_GEO_LOCATION_LATITUDE, EXIF_TAG_GPS_LATITUDE, EXIF_TYPE_RATIONAL, + EXIF_TAG_GPS_LATITUDE_REF, + serialize_geo_coordinate, deserialize_geo_coordinate}, + {GST_TAG_GEO_LOCATION_LONGITUDE, EXIF_TAG_GPS_LONGITUDE, EXIF_TYPE_RATIONAL, + EXIF_TAG_GPS_LONGITUDE_REF, + serialize_geo_coordinate, deserialize_geo_coordinate}, + {GST_TAG_GEO_LOCATION_ELEVATION, EXIF_TAG_GPS_ALTITUDE, EXIF_TYPE_RATIONAL, + EXIF_TAG_GPS_ALTITUDE_REF, + serialize_geo_elevation, deserialize_geo_elevation}, + {GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, EXIF_TAG_GPS_SPEED, EXIF_TYPE_RATIONAL, + EXIF_TAG_GPS_SPEED_REF, + serialize_speed, deserialize_speed}, + {GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, EXIF_TAG_GPS_TRACK, + EXIF_TYPE_RATIONAL, EXIF_TAG_GPS_TRACK_REF, + serialize_geo_direction, deserialize_geo_direction}, + {GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, EXIF_TAG_GPS_IMAGE_DIRECTION, + EXIF_TYPE_RATIONAL, EXIF_TAG_GPS_IMAGE_DIRECTION_REF, + serialize_geo_direction, deserialize_geo_direction}, + {GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, + EXIF_TAG_GPS_HORIZONTAL_POSITIONING_ERROR, + EXIF_TYPE_RATIONAL, 0, NULL, NULL}, + {NULL, 0, 0, 0, NULL, NULL} +}; + +/* GstExifReader functions */ +static void +gst_exif_reader_init (GstExifReader * reader, gint byte_order, + const GstBuffer * buf, guint32 base_offset) +{ + ensure_exif_tags (); + + reader->taglist = gst_tag_list_new (); + reader->buffer = buf; + reader->base_offset = base_offset; + reader->byte_order = byte_order; + reader->pending_tags = NULL; + if (reader->byte_order != G_LITTLE_ENDIAN && + reader->byte_order != G_BIG_ENDIAN) { + GST_WARNING ("Unexpected byte order %d, using system default: %d", + reader->byte_order, G_BYTE_ORDER); + reader->byte_order = G_BYTE_ORDER; + } +} + +static void +gst_exif_reader_add_pending_tag (GstExifReader * reader, GstExifTagData * data) +{ + GstExifTagData *copy; + + copy = g_slice_new (GstExifTagData); + memcpy (copy, data, sizeof (GstExifTagData)); + + reader->pending_tags = g_slist_prepend (reader->pending_tags, copy); +} + +static GstExifTagData * +gst_exif_reader_get_pending_tag (GstExifReader * reader, gint tagid) +{ + GSList *walker; + + for (walker = reader->pending_tags; walker; walker = g_slist_next (walker)) { + GstExifTagData *data = (GstExifTagData *) walker->data; + if (data->tag == tagid) + return data; + } + + return NULL; +} + +static GstTagList * +gst_exif_reader_reset (GstExifReader * reader, gboolean return_taglist) +{ + GstTagList *ret = NULL; + GSList *walker; + + for (walker = reader->pending_tags; walker; walker = g_slist_next (walker)) { + GstExifTagData *data = (GstExifTagData *) walker->data; + + g_slice_free (GstExifTagData, data); + } + g_slist_free (reader->pending_tags); + + if (return_taglist) { + ret = reader->taglist; + reader->taglist = NULL; + } + + if (reader->taglist) { + gst_tag_list_free (reader->taglist); + } + + return ret; +} + +/* GstExifWriter functions */ + +static void +gst_exif_writer_init (GstExifWriter * writer, gint byte_order) +{ + ensure_exif_tags (); + + gst_byte_writer_init (&writer->tagwriter); + gst_byte_writer_init (&writer->datawriter); + + writer->byte_order = byte_order; + writer->tags_total = 0; + if (writer->byte_order != G_LITTLE_ENDIAN && + writer->byte_order != G_BIG_ENDIAN) { + GST_WARNING ("Unexpected byte order %d, using system default: %d", + writer->byte_order, G_BYTE_ORDER); + writer->byte_order = G_BYTE_ORDER; + } +} + +static GstBuffer * +gst_exif_writer_reset_and_get_buffer (GstExifWriter * writer) +{ + GstBuffer *header; + GstBuffer *data; + + header = gst_byte_writer_reset_and_get_buffer (&writer->tagwriter); + data = gst_byte_writer_reset_and_get_buffer (&writer->datawriter); + + return gst_buffer_join (header, data); +} + +/* + * Given the exif tag with the passed id, returns the map index of the tag + * corresponding to it. If use_complementary is true, then the complementary + * are also used in the search. + * + * Returns -1 if not found + */ +static gint +exif_tag_map_find_reverse (guint16 exif_tag, const GstExifTagMatch * tag_map, + gboolean use_complementary) +{ + gint i; + + for (i = 0; tag_map[i].exif_tag != 0; i++) { + if (exif_tag == tag_map[i].exif_tag || (use_complementary && + exif_tag == tag_map[i].complementary_tag)) { + return i; + } + } + return -1; +} + +static gboolean +gst_tag_list_has_ifd_tags (const GstTagList * taglist, + const GstExifTagMatch * tag_map) +{ + gint i; + + for (i = 0; tag_map[i].exif_tag != 0; i++) { + if (tag_map[i].gst_tag == NULL) { + if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG && + gst_tag_list_has_ifd_tags (taglist, tag_map_gps)) + return TRUE; + if (tag_map[i].exif_tag == EXIF_IFD_TAG && + gst_tag_list_has_ifd_tags (taglist, tag_map_exif)) + return TRUE; + continue; + } + + if (gst_tag_list_get_value_index (taglist, tag_map[i].gst_tag, 0)) { + return TRUE; + } + } + return FALSE; +} + +/* + * Writes the tag entry. + * + * The tag entry is the tag id, the tag type, + * the count and the offset. + * + * The offset is the on the amount of data writen so far, as one + * can't predict the total bytes that the tag entries will take. + * This means those fields requires being updated later. + */ +static void +gst_exif_writer_write_tag_header (GstExifWriter * writer, + guint16 exif_tag, guint16 exif_type, guint32 count, guint32 offset, + gboolean is_data) +{ + GST_DEBUG ("Writing tag entry: id %x, type %u, count %u, offset %u", + exif_tag, exif_type, count, offset); + + if (writer->byte_order == G_LITTLE_ENDIAN) { + gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_tag); + gst_byte_writer_put_uint16_le (&writer->tagwriter, exif_type); + gst_byte_writer_put_uint32_le (&writer->tagwriter, count); + gst_byte_writer_put_uint32_le (&writer->tagwriter, offset); + } else if (writer->byte_order == G_BIG_ENDIAN) { + gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_tag); + gst_byte_writer_put_uint16_be (&writer->tagwriter, exif_type); + gst_byte_writer_put_uint32_be (&writer->tagwriter, count); + if (is_data) { + gst_byte_writer_put_uint32_le (&writer->tagwriter, offset); + } else { + gst_byte_writer_put_uint32_be (&writer->tagwriter, offset); + } + } else { + g_assert_not_reached (); + } + + writer->tags_total++; +} + +static void +gst_exif_writer_write_rational_data (GstExifWriter * writer, guint32 frac_n, + guint32 frac_d) +{ + if (writer->byte_order == G_LITTLE_ENDIAN) { + gst_byte_writer_put_uint32_le (&writer->datawriter, frac_n); + gst_byte_writer_put_uint32_le (&writer->datawriter, frac_d); + } else { + gst_byte_writer_put_uint32_be (&writer->datawriter, frac_n); + gst_byte_writer_put_uint32_be (&writer->datawriter, frac_d); + } +} + +static void +gst_exif_writer_write_signed_rational_data (GstExifWriter * writer, + gint32 frac_n, gint32 frac_d) +{ + if (writer->byte_order == G_LITTLE_ENDIAN) { + gst_byte_writer_put_int32_le (&writer->datawriter, frac_n); + gst_byte_writer_put_int32_le (&writer->datawriter, frac_d); + } else { + gst_byte_writer_put_int32_be (&writer->datawriter, frac_n); + gst_byte_writer_put_int32_be (&writer->datawriter, frac_d); + } +} + +static void +gst_exif_writer_write_rational_tag (GstExifWriter * writer, + guint16 tag, guint32 frac_n, guint32 frac_d) +{ + guint32 offset = gst_byte_writer_get_size (&writer->datawriter); + + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_RATIONAL, + 1, offset, FALSE); + + gst_exif_writer_write_rational_data (writer, frac_n, frac_d); +} + +static void +gst_exif_writer_write_signed_rational_tag (GstExifWriter * writer, + guint16 tag, gint32 frac_n, gint32 frac_d) +{ + guint32 offset = gst_byte_writer_get_size (&writer->datawriter); + + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_SRATIONAL, + 1, offset, FALSE); + + gst_exif_writer_write_signed_rational_data (writer, frac_n, frac_d); +} + +static void +gst_exif_writer_write_rational_tag_from_double (GstExifWriter * writer, + guint16 tag, gdouble value) +{ + gint frac_n; + gint frac_d; + + gst_util_double_to_fraction (value, &frac_n, &frac_d); + + gst_exif_writer_write_rational_tag (writer, tag, frac_n, frac_d); +} + +static void +gst_exif_writer_write_signed_rational_tag_from_double (GstExifWriter * writer, + guint16 tag, gdouble value) +{ + gint frac_n; + gint frac_d; + + gst_util_double_to_fraction (value, &frac_n, &frac_d); + + gst_exif_writer_write_signed_rational_tag (writer, tag, frac_n, frac_d); +} + +static void +gst_exif_writer_write_byte_tag (GstExifWriter * writer, guint16 tag, + guint8 value) +{ + guint32 offset = 0; + + GST_WRITE_UINT8 ((guint8 *) & offset, value); + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_BYTE, + 1, offset, TRUE); +} + +static void +gst_exif_writer_write_short_tag (GstExifWriter * writer, guint16 tag, + guint16 value) +{ + guint32 offset = 0; + + if (writer->byte_order == G_LITTLE_ENDIAN) { + GST_WRITE_UINT16_LE ((guint8 *) & offset, value); + } else { + GST_WRITE_UINT16_BE ((guint8 *) & offset, value); + } + + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_SHORT, + 1, offset, TRUE); +} + +static void +gst_exif_writer_write_long_tag (GstExifWriter * writer, guint16 tag, + guint32 value) +{ + guint32 offset = 0; + if (writer->byte_order == G_LITTLE_ENDIAN) { + GST_WRITE_UINT32_LE ((guint8 *) & offset, value); + } else { + GST_WRITE_UINT32_BE ((guint8 *) & offset, value); + } + + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_LONG, + 1, offset, TRUE); +} + + +static void +write_exif_undefined_tag (GstExifWriter * writer, guint16 tag, + const guint8 * data, gint size) +{ + guint32 offset = 0; + + if (size > 4) { + /* we only use the data offset here, later we add up the + * resulting tag headers offset and the base offset */ + offset = gst_byte_writer_get_size (&writer->datawriter); + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_UNDEFINED, + size, offset, FALSE); + gst_byte_writer_put_data (&writer->datawriter, data, size); + } else { + /* small enough to go in the offset */ + memcpy ((guint8 *) & offset, data, size); + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_UNDEFINED, + size, offset, TRUE); + } +} + +static void +write_exif_ascii_tag (GstExifWriter * writer, guint16 tag, const gchar * str) +{ + gint size; + guint32 offset = 0; + + size = strlen (str) + 1; + + if (size > 4) { + /* we only use the data offset here, later we add up the + * resulting tag headers offset and the base offset */ + offset = gst_byte_writer_get_size (&writer->datawriter); + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_ASCII, + size, offset, FALSE); + gst_byte_writer_put_string (&writer->datawriter, str); + } else { + /* small enough to go in the offset */ + memcpy ((guint8 *) & offset, str, size); + gst_exif_writer_write_tag_header (writer, tag, EXIF_TYPE_ASCII, + size, offset, TRUE); + } +} + +static void +write_exif_ascii_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + gchar *str = NULL; + gboolean cleanup = FALSE; + const GValue *value; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + /* FIXME support this by serializing them with a ','? */ + GST_WARNING ("Multiple string tags not supported yet"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + str = (gchar *) g_value_get_string (value); + break; + default: + if (G_VALUE_TYPE (value) == GST_TYPE_DATE_TIME) { + GstDateTime *dt = (GstDateTime *) g_value_get_boxed (value); + + if (dt == NULL) { + GST_WARNING ("NULL datetime received"); + break; + } + + str = g_strdup_printf ("%04d:%02d:%02d %02d:%02d:%02d", + gst_date_time_get_year (dt), gst_date_time_get_month (dt), + gst_date_time_get_day (dt), gst_date_time_get_hour (dt), + gst_date_time_get_minute (dt), gst_date_time_get_second (dt)); + + cleanup = TRUE; + } else { + GST_WARNING ("Conversion from %s to ascii string not supported", + G_VALUE_TYPE_NAME (value)); + } + break; + } + + if (str == NULL) + return; + + write_exif_ascii_tag (writer, exiftag->exif_tag, str); + if (cleanup) + g_free (str); +} + +static void +write_exif_undefined_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + const GValue *value; + const guint8 *data = NULL; + gint size = 0; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + GST_WARNING ("Only the first item in the taglist will be serialized"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + data = (guint8 *) g_value_get_string (value); + size = strlen ((gchar *) data); /* no need to +1, undefined doesn't require it */ + break; + default: + if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) { + GstBuffer *buf = gst_value_get_buffer (value); + + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + } else { + GST_WARNING ("Conversion from %s to raw data not supported", + G_VALUE_TYPE_NAME (value)); + } + break; + } + + if (size == 0) + return; + + write_exif_undefined_tag (writer, exiftag->exif_tag, data, size); +} + +static void +write_exif_rational_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + const GValue *value; + gdouble num = 0; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + GST_WARNING ("Only the first item in the taglist will be serialized"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_DOUBLE: + num = g_value_get_double (value); + gst_exif_writer_write_rational_tag_from_double (writer, exiftag->exif_tag, + num); + break; + default: + if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION) { + gst_exif_writer_write_rational_tag (writer, exiftag->exif_tag, + gst_value_get_fraction_numerator (value), + gst_value_get_fraction_denominator (value)); + } else { + GST_WARNING ("Conversion from %s to rational not supported", + G_VALUE_TYPE_NAME (value)); + } + break; + } +} + +static void +write_exif_signed_rational_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + const GValue *value; + gdouble num = 0; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + GST_WARNING ("Only the first item in the taglist will be serialized"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_DOUBLE: + num = g_value_get_double (value); + gst_exif_writer_write_signed_rational_tag_from_double (writer, + exiftag->exif_tag, num); + break; + default: + if (G_VALUE_TYPE (value) == GST_TYPE_FRACTION) { + gst_exif_writer_write_signed_rational_tag (writer, exiftag->exif_tag, + gst_value_get_fraction_numerator (value), + gst_value_get_fraction_denominator (value)); + } else { + GST_WARNING ("Conversion from %s to signed rational not supported", + G_VALUE_TYPE_NAME (value)); + } + break; + } +} + +static void +write_exif_integer_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + const GValue *value; + guint32 num = 0; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + GST_WARNING ("Only the first item in the taglist will be serialized"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_INT: + num = g_value_get_int (value); + break; + default: + GST_WARNING ("Conversion from %s to int not supported", + G_VALUE_TYPE_NAME (value)); + break; + } + + switch (exiftag->exif_type) { + case EXIF_TYPE_LONG: + gst_exif_writer_write_long_tag (writer, exiftag->exif_tag, num); + break; + case EXIF_TYPE_SHORT: + gst_exif_writer_write_short_tag (writer, exiftag->exif_tag, num); + break; + default: + break; + } +} + +static void +write_exif_tag_from_taglist (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + GST_DEBUG ("Writing tag %s", exiftag->gst_tag); + + /* check for special handling */ + if (exiftag->serialize) { + exiftag->serialize (writer, taglist, exiftag); + return; + } + + switch (exiftag->exif_type) { + case EXIF_TYPE_ASCII: + write_exif_ascii_tag_from_taglist (writer, taglist, exiftag); + break; + case EXIF_TYPE_UNDEFINED: + write_exif_undefined_tag_from_taglist (writer, taglist, exiftag); + break; + case EXIF_TYPE_RATIONAL: + write_exif_rational_tag_from_taglist (writer, taglist, exiftag); + break; + case EXIF_TYPE_SRATIONAL: + write_exif_signed_rational_tag_from_taglist (writer, taglist, exiftag); + break; + case EXIF_TYPE_LONG: + case EXIF_TYPE_SHORT: + write_exif_integer_tag_from_taglist (writer, taglist, exiftag); + break; + default: + GST_WARNING ("Unhandled tag type %d", exiftag->exif_type); + } +} + +static void +tagdata_copy (GstExifTagData * to, const GstExifTagData * from) +{ + to->tag = from->tag; + to->tag_type = from->tag_type; + to->count = from->count; + to->offset = from->offset; + to->offset_as_data = from->offset_as_data; +} + +static void +gst_exif_tag_rewrite_offsets (GstByteWriter * writer, gint byte_order, + guint32 offset, gint num_tags, GstByteWriter * inner_ifds_data) +{ + GstByteReader *reader; + gint i; + guint16 aux = G_MAXUINT16; + + GST_LOG ("Rewriting tag entries offsets"); + + reader = (GstByteReader *) writer; + + if (num_tags == -1) { + if (byte_order == G_LITTLE_ENDIAN) { + gst_byte_reader_get_uint16_le (reader, &aux); + } else { + gst_byte_reader_get_uint16_be (reader, &aux); + } + if (aux == G_MAXUINT16) { + GST_WARNING ("Failed to read number of tags, won't rewrite offsets"); + return; + } + num_tags = (gint) aux; + } + + g_return_if_fail (num_tags != -1); + + GST_DEBUG ("number of tags %d", num_tags); + + for (i = 0; i < num_tags; i++) { + guint16 type = 0; + guint32 cur_offset = 0; + gint byte_size = 0; + guint32 count = 0; + guint16 tag_id = 0; + + g_assert (gst_byte_writer_get_pos (writer) < + gst_byte_writer_get_size (writer)); + + /* read the type */ + if (byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint16_le (reader, &tag_id)) + break; + if (!gst_byte_reader_get_uint16_le (reader, &type)) + break; + if (!gst_byte_reader_get_uint32_le (reader, &count)) + break; + } else { + if (!gst_byte_reader_get_uint16_be (reader, &tag_id)) + break; + if (!gst_byte_reader_get_uint16_be (reader, &type)) + break; + if (!gst_byte_reader_get_uint32_be (reader, &count)) + break; + } + + GST_LOG ("Parsed tag %x of type %u and count %u", tag_id, type, count); + + switch (type) { + case EXIF_TYPE_BYTE: + case EXIF_TYPE_ASCII: + case EXIF_TYPE_UNDEFINED: + byte_size = count; + break; + case EXIF_TYPE_SHORT: + byte_size = count * 2; /* 2 bytes */ + break; + case EXIF_TYPE_LONG: + case EXIF_TYPE_SLONG: + byte_size = count * 4; /* 4 bytes */ + break; + case EXIF_TYPE_RATIONAL: + case EXIF_TYPE_SRATIONAL: + byte_size = count * 8; /* 8 bytes */ + break; + default: + g_assert_not_reached (); + break; + } + + /* adjust the offset if needed */ + if (byte_size > 4 || tag_id == EXIF_GPS_IFD_TAG || tag_id == EXIF_IFD_TAG) { + if (byte_order == G_LITTLE_ENDIAN) { + if (gst_byte_reader_peek_uint32_le (reader, &cur_offset)) { + gst_byte_writer_put_uint32_le (writer, cur_offset + offset); + } + } else { + if (gst_byte_reader_peek_uint32_be (reader, &cur_offset)) { + gst_byte_writer_put_uint32_be (writer, cur_offset + offset); + } + } + GST_DEBUG ("Rewriting tag offset from %u to (%u + %u) %u", + cur_offset, cur_offset, offset, cur_offset + offset); + + if ((tag_id == EXIF_GPS_IFD_TAG || tag_id == EXIF_IFD_TAG) && + inner_ifds_data != NULL) { + /* needs special handling */ + if (!gst_byte_writer_set_pos (inner_ifds_data, cur_offset)) { + GST_WARNING ("Failed to position writer to rewrite inner ifd " + "offsets"); + continue; + } + + gst_exif_tag_rewrite_offsets (inner_ifds_data, byte_order, offset, -1, + NULL); + } + } else { + gst_byte_reader_skip (reader, 4); + GST_DEBUG ("No need to rewrite tag offset"); + } + } + GST_LOG ("Done rewriting offsets"); +} + +static void +parse_exif_ascii_tag (GstExifReader * reader, const GstExifTagMatch * tag, + guint32 count, guint32 offset, const guint8 * offset_as_data) +{ + GType tagtype; + gchar *str; + guint32 real_offset; + + if (count > 4) { + if (offset < reader->base_offset) { + GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset, + reader->base_offset); + return; + } + + real_offset = offset - reader->base_offset; + if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) { + GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s", + real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag); + return; + } + + str = + g_strndup ((gchar *) (GST_BUFFER_DATA (reader->buffer) + real_offset), + count); + } else { + str = g_strndup ((gchar *) offset_as_data, count); + } + + tagtype = gst_tag_get_type (tag->gst_tag); + if (tagtype == GST_TYPE_DATE_TIME) { + gint year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0; + + if (sscanf (str, "%04d:%02d:%02d %02d:%02d:%02d", &year, &month, &day, + &hour, &minute, &second) > 0) { + GstDateTime *d; + + d = gst_date_time_new_local_time (year, month, day, hour, minute, second); + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, + tag->gst_tag, d, NULL); + gst_date_time_unref (d); + } else { + GST_WARNING ("Failed to parse %s into a datetime tag", str); + } + } else if (tagtype == G_TYPE_STRING) { + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag, str, + NULL); + } else { + GST_WARNING ("No parsing function associated to %x(%s)", tag->exif_tag, + tag->gst_tag); + } + g_free (str); +} + +static void +parse_exif_long_tag (GstExifReader * reader, const GstExifTagMatch * tag, + guint32 count, guint32 offset, const guint8 * offset_as_data) +{ + GType tagtype; + + if (count > 1) { + GST_WARNING ("Long tags with more than one value are not supported"); + return; + } + + tagtype = gst_tag_get_type (tag->gst_tag); + if (tagtype == G_TYPE_INT) { + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag, + offset, NULL); + } else { + GST_WARNING ("No parsing function associated to %x(%s)", tag->exif_tag, + tag->gst_tag); + } +} + + +static void +parse_exif_undefined_tag (GstExifReader * reader, const GstExifTagMatch * tag, + guint32 count, guint32 offset, const guint8 * offset_as_data) +{ + GType tagtype; + guint8 *data; + guint32 real_offset; + + if (count > 4) { + if (offset < reader->base_offset) { + GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset, + reader->base_offset); + return; + } + + real_offset = offset - reader->base_offset; + if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) { + GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s", + real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag); + return; + } + + /* +1 because it could be a string without the \0 */ + data = malloc (sizeof (guint8) * count + 1); + memcpy (data, GST_BUFFER_DATA (reader->buffer) + real_offset, count); + data[count] = 0; + } else { + data = malloc (sizeof (guint8) * count + 1); + memcpy (data, (guint8 *) offset_as_data, count); + data[count] = 0; + } + + tagtype = gst_tag_get_type (tag->gst_tag); + if (tagtype == GST_TYPE_BUFFER) { + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = data; + GST_BUFFER_MALLOCDATA (buf) = data; + GST_BUFFER_SIZE (buf) = count; + data = NULL; + + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_APPEND, tag->gst_tag, + buf, NULL); + + gst_buffer_unref (buf); + } else if (tagtype == G_TYPE_STRING) { + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag, + data, NULL); + } else { + GST_WARNING ("No parsing function associated to %x(%s)", tag->exif_tag, + tag->gst_tag); + } + g_free (data); +} + +static gboolean +exif_reader_read_rational_tag (GstExifReader * exif_reader, + guint32 count, guint32 offset, gboolean is_signed, + gint32 * _frac_n, gint32 * _frac_d) +{ + GstByteReader data_reader; + guint32 real_offset; + gint32 frac_n = 0; + gint32 frac_d = 0; + + if (count > 1) { + GST_WARNING ("Rationals with multiple entries are not supported"); + } + if (offset < exif_reader->base_offset) { + GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset, + exif_reader->base_offset); + return FALSE; + } + + real_offset = offset - exif_reader->base_offset; + if (real_offset >= GST_BUFFER_SIZE (exif_reader->buffer)) { + GST_WARNING ("Invalid offset %u for buffer of size %u", + real_offset, GST_BUFFER_SIZE (exif_reader->buffer)); + return FALSE; + } + + gst_byte_reader_init_from_buffer (&data_reader, exif_reader->buffer); + if (!gst_byte_reader_set_pos (&data_reader, real_offset)) + goto reader_fail; + + if (!is_signed) { + guint32 aux_n = 0, aux_d = 0; + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint32_le (&data_reader, &aux_n) || + !gst_byte_reader_get_uint32_le (&data_reader, &aux_d)) + goto reader_fail; + } else { + if (!gst_byte_reader_get_uint32_be (&data_reader, &aux_n) || + !gst_byte_reader_get_uint32_be (&data_reader, &aux_d)) + goto reader_fail; + } + frac_n = (gint32) aux_n; + frac_d = (gint32) aux_d; + } else { + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_int32_le (&data_reader, &frac_n) || + !gst_byte_reader_get_int32_le (&data_reader, &frac_d)) + goto reader_fail; + } else { + if (!gst_byte_reader_get_int32_be (&data_reader, &frac_n) || + !gst_byte_reader_get_int32_be (&data_reader, &frac_d)) + goto reader_fail; + } + } + + if (_frac_n) + *_frac_n = frac_n; + if (_frac_d) + *_frac_d = frac_d; + + return TRUE; + +reader_fail: + GST_WARNING ("Failed to read from byte reader. (Buffer too short?)"); + return FALSE; +} + +static void +parse_exif_rational_tag (GstExifReader * exif_reader, + const gchar * gst_tag, guint32 count, guint32 offset, gdouble multiplier, + gboolean is_signed) +{ + GType type; + gint32 frac_n = 0; + gint32 frac_d = 1; + gdouble value; + + GST_DEBUG ("Reading fraction for tag %s...", gst_tag); + if (!exif_reader_read_rational_tag (exif_reader, count, offset, is_signed, + &frac_n, &frac_d)) + return; + GST_DEBUG ("Read fraction for tag %s: %d/%d", gst_tag, frac_n, frac_d); + + type = gst_tag_get_type (gst_tag); + switch (type) { + case G_TYPE_DOUBLE: + gst_util_fraction_to_double (frac_n, frac_d, &value); + value *= multiplier; + GST_DEBUG ("Adding %s tag: %lf", gst_tag, value); + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, gst_tag, + value, NULL); + break; + default: + if (type == GST_TYPE_FRACTION) { + GValue fraction = { 0 }; + + g_value_init (&fraction, GST_TYPE_FRACTION); + gst_value_set_fraction (&fraction, frac_n * multiplier, frac_d); + gst_tag_list_add_value (exif_reader->taglist, GST_TAG_MERGE_REPLACE, + gst_tag, &fraction); + g_value_unset (&fraction); + } else { + GST_WARNING ("Can't convert from fraction into %s", g_type_name (type)); + } + } + +} + +static GstBuffer * +write_exif_ifd (const GstTagList * taglist, gboolean byte_order, + guint32 base_offset, const GstExifTagMatch * tag_map) +{ + GstExifWriter writer; + gint i; + + GST_DEBUG ("Formatting taglist %p as exif buffer. Byte order: %d, " + "base_offset: %u", taglist, byte_order, base_offset); + + g_assert (byte_order == G_LITTLE_ENDIAN || byte_order == G_BIG_ENDIAN); + + if (!gst_tag_list_has_ifd_tags (taglist, tag_map)) { + GST_DEBUG ("No tags for this ifd"); + return NULL; + } + + gst_exif_writer_init (&writer, byte_order); + + /* write tag number as 0 */ + gst_byte_writer_put_uint16_le (&writer.tagwriter, 0); + + /* write both tag headers and data + * in ascending id order */ + + for (i = 0; tag_map[i].exif_tag != 0; i++) { + + /* special cases have NULL gst tag */ + if (tag_map[i].gst_tag == NULL) { + GstBuffer *inner_ifd = NULL; + const GstExifTagMatch *inner_tag_map = NULL; + + GST_LOG ("Inner ifd tag: %x", tag_map[i].exif_tag); + + if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG) { + inner_tag_map = tag_map_gps; + } else if (tag_map[i].exif_tag == EXIF_IFD_TAG) { + inner_tag_map = tag_map_exif; + } else if (tag_map[i].exif_tag == EXIF_VERSION_TAG) { + /* special case where we write the exif version */ + write_exif_undefined_tag (&writer, EXIF_VERSION_TAG, (guint8 *) "0230", + 4); + } else if (tag_map[i].exif_tag == EXIF_FLASHPIX_VERSION_TAG) { + /* special case where we write the flashpix version */ + write_exif_undefined_tag (&writer, EXIF_FLASHPIX_VERSION_TAG, + (guint8 *) "0100", 4); + } + + if (inner_tag_map) { + /* base offset and tagheader size are added when rewriting offset */ + inner_ifd = write_exif_ifd (taglist, byte_order, + gst_byte_writer_get_size (&writer.datawriter), inner_tag_map); + } + + if (inner_ifd) { + GST_DEBUG ("Adding inner ifd: %x", tag_map[i].exif_tag); + gst_exif_writer_write_tag_header (&writer, tag_map[i].exif_tag, + EXIF_TYPE_LONG, 1, + gst_byte_writer_get_size (&writer.datawriter), FALSE); + gst_byte_writer_put_data (&writer.datawriter, + GST_BUFFER_DATA (inner_ifd), GST_BUFFER_SIZE (inner_ifd)); + gst_buffer_unref (inner_ifd); + } + continue; + } + + GST_LOG ("Checking tag %s", tag_map[i].gst_tag); + if (gst_tag_list_get_value_index (taglist, tag_map[i].gst_tag, 0) == NULL) + continue; + + write_exif_tag_from_taglist (&writer, taglist, &tag_map[i]); + } + + /* Add the next IFD offset, we just set it to 0 because + * there is no easy way to predict what it is going to be. + * The user might rewrite the value if needed */ + gst_byte_writer_put_uint32_le (&writer.tagwriter, 0); + + /* write the number of tags */ + gst_byte_writer_set_pos (&writer.tagwriter, 0); + if (writer.byte_order == G_LITTLE_ENDIAN) + gst_byte_writer_put_uint16_le (&writer.tagwriter, writer.tags_total); + else + gst_byte_writer_put_uint16_be (&writer.tagwriter, writer.tags_total); + + GST_DEBUG ("Number of tags rewriten to %d", writer.tags_total); + + /* now that we know the tag headers size, we can add the offsets */ + gst_exif_tag_rewrite_offsets (&writer.tagwriter, writer.byte_order, + base_offset + gst_byte_writer_get_size (&writer.tagwriter), + writer.tags_total, &writer.datawriter); + + return gst_exif_writer_reset_and_get_buffer (&writer); +} + +static gboolean +parse_exif_tag_header (GstByteReader * reader, gint byte_order, + GstExifTagData * _tagdata) +{ + g_assert (_tagdata); + + /* read the fields */ + if (byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint16_le (reader, &_tagdata->tag) || + !gst_byte_reader_get_uint16_le (reader, &_tagdata->tag_type) || + !gst_byte_reader_get_uint32_le (reader, &_tagdata->count) || + !gst_byte_reader_get_data (reader, 4, &_tagdata->offset_as_data)) { + return FALSE; + } + _tagdata->offset = GST_READ_UINT32_LE (_tagdata->offset_as_data); + } else { + if (!gst_byte_reader_get_uint16_be (reader, &_tagdata->tag) || + !gst_byte_reader_get_uint16_be (reader, &_tagdata->tag_type) || + !gst_byte_reader_get_uint32_be (reader, &_tagdata->count) || + !gst_byte_reader_get_data (reader, 4, &_tagdata->offset_as_data)) { + return FALSE; + } + _tagdata->offset = GST_READ_UINT32_BE (_tagdata->offset_as_data); + } + + return TRUE; +} + +static gboolean +parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset, + const GstExifTagMatch * tag_map) +{ + GstByteReader reader; + guint16 entries = 0; + guint16 i; + + g_return_val_if_fail (exif_reader->byte_order == G_LITTLE_ENDIAN + || exif_reader->byte_order == G_BIG_ENDIAN, FALSE); + + gst_byte_reader_init_from_buffer (&reader, exif_reader->buffer); + if (!gst_byte_reader_set_pos (&reader, buf_offset)) { + GST_WARNING ("Buffer offset invalid when parsing exif ifd"); + return FALSE; + } + + /* read the IFD entries number */ + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint16_le (&reader, &entries)) + goto read_error; + } else { + if (!gst_byte_reader_get_uint16_be (&reader, &entries)) + goto read_error; + } + GST_DEBUG ("Read number of entries: %u", entries); + + /* iterate over the buffer and find the tags and stuff */ + for (i = 0; i < entries; i++) { + GstExifTagData tagdata; + gint map_index; + + GST_LOG ("Reading entry: %u", i); + + if (!parse_exif_tag_header (&reader, exif_reader->byte_order, &tagdata)) + goto read_error; + + GST_DEBUG ("Parsed tag: id 0x%x, type %u, count %u, offset %u (0x%x)" + ", buf size: %u", tagdata.tag, tagdata.tag_type, tagdata.count, + tagdata.offset, tagdata.offset, gst_byte_reader_get_size (&reader)); + + map_index = exif_tag_map_find_reverse (tagdata.tag, tag_map, TRUE); + if (map_index == -1) { + GST_WARNING ("Unmapped exif tag: 0x%x", tagdata.tag); + continue; + } + + /* + * inner ifd tags handling, errors processing those are being ignored + * and we try to continue the parsing + */ + if (tagdata.tag == EXIF_GPS_IFD_TAG) { + parse_exif_ifd (exif_reader, + tagdata.offset - exif_reader->base_offset, tag_map_gps); + + continue; + } + if (tagdata.tag == EXIF_IFD_TAG) { + parse_exif_ifd (exif_reader, + tagdata.offset - exif_reader->base_offset, tag_map_exif); + + continue; + } + if (tagdata.tag == EXIF_VERSION_TAG || + tagdata.tag == EXIF_FLASHPIX_VERSION_TAG) { + /* skip */ + continue; + } + + /* tags that need specialized deserialization */ + if (tag_map[map_index].deserialize) { + i += tag_map[map_index].deserialize (exif_reader, &reader, + &tag_map[map_index], &tagdata); + continue; + } + + switch (tagdata.tag_type) { + case EXIF_TYPE_ASCII: + parse_exif_ascii_tag (exif_reader, &tag_map[map_index], + tagdata.count, tagdata.offset, tagdata.offset_as_data); + break; + case EXIF_TYPE_RATIONAL: + parse_exif_rational_tag (exif_reader, tag_map[map_index].gst_tag, + tagdata.count, tagdata.offset, 1, FALSE); + break; + case EXIF_TYPE_SRATIONAL: + parse_exif_rational_tag (exif_reader, tag_map[map_index].gst_tag, + tagdata.count, tagdata.offset, 1, TRUE); + break; + case EXIF_TYPE_UNDEFINED: + parse_exif_undefined_tag (exif_reader, &tag_map[map_index], + tagdata.count, tagdata.offset, tagdata.offset_as_data); + case EXIF_TYPE_LONG: + parse_exif_long_tag (exif_reader, &tag_map[map_index], + tagdata.count, tagdata.offset, tagdata.offset_as_data); + break; + default: + GST_WARNING ("Unhandled tag type: %u", tagdata.tag_type); + break; + } + } + + /* check if the pending tags have something that can still be added */ + { + GSList *walker; + GstExifTagData *data; + + for (walker = exif_reader->pending_tags; walker; + walker = g_slist_next (walker)) { + data = (GstExifTagData *) walker->data; + switch (data->tag) { + case EXIF_TAG_XRESOLUTION: + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_HORIZONTAL_PPI, + data->count, data->offset, 1, FALSE); + break; + case EXIF_TAG_YRESOLUTION: + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_VERTICAL_PPI, + data->count, data->offset, 1, FALSE); + break; + default: + /* NOP */ + break; + } + } + } + + return TRUE; + +read_error: + { + GST_WARNING ("Failed to parse the exif ifd"); + return FALSE; + } +} + +/** + * gst_tag_list_to_exif_buffer: + * @taglist: The taglist + * @byte_order: byte order used in writing (G_LITTLE_ENDIAN or G_BIG_ENDIAN) + * @base_offset: Offset from the tiff header first byte + * + * Formats the tags in taglist on exif format. The resulting buffer contains + * the tags IFD and is followed by the data pointed by the tag entries. + * + * Returns: A GstBuffer containing the tag entries followed by the tag data + * + * Since: 0.10.30 + */ +GstBuffer * +gst_tag_list_to_exif_buffer (const GstTagList * taglist, gint byte_order, + guint32 base_offset) +{ + return write_exif_ifd (taglist, byte_order, base_offset, tag_map_ifd0); +} + +/** + * gst_tag_list_to_exif_buffer_with_tiff_header: + * @taglist: The taglist + * + * Formats the tags in taglist into exif structure, a tiff header + * is put in the beginning of the buffer. + * + * Returns: A GstBuffer containing the data + * + * Since: 0.10.30 + */ +GstBuffer * +gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist) +{ + GstBuffer *ifd; + GstByteWriter writer; + guint size; + + ifd = gst_tag_list_to_exif_buffer (taglist, G_BYTE_ORDER, 8); + if (ifd == NULL) { + GST_WARNING ("Failed to create exif buffer"); + return NULL; + } + size = TIFF_HEADER_SIZE + GST_BUFFER_SIZE (ifd); + + /* TODO what is the correct endianness here? */ + gst_byte_writer_init_with_size (&writer, size, FALSE); + /* TIFF header */ + if (G_BYTE_ORDER == G_LITTLE_ENDIAN) { + gst_byte_writer_put_uint16_le (&writer, TIFF_LITTLE_ENDIAN); + gst_byte_writer_put_uint16_le (&writer, 42); + gst_byte_writer_put_uint32_le (&writer, 8); + } else { + gst_byte_writer_put_uint16_be (&writer, TIFF_BIG_ENDIAN); + gst_byte_writer_put_uint16_be (&writer, 42); + gst_byte_writer_put_uint32_be (&writer, 8); + } + if (!gst_byte_writer_put_data (&writer, GST_BUFFER_DATA (ifd), + GST_BUFFER_SIZE (ifd))) { + GST_WARNING ("Byte writer size mismatch"); + /* reaching here is a programming error because we should have a buffer + * large enough */ + g_assert_not_reached (); + gst_buffer_unref (ifd); + gst_byte_writer_reset (&writer); + return NULL; + } + gst_buffer_unref (ifd); + return gst_byte_writer_reset_and_get_buffer (&writer); +} + +/** + * gst_tag_list_from_exif_buffer: + * @buffer: The exif buffer + * @byte_order: byte order of the data + * @base_offset: Offset from the tiff header to this buffer + * + * Parses the IFD and IFD tags data contained in the buffer and puts it + * on a taglist. The base_offset is used to subtract from the offset in + * the tag entries and be able to get the offset relative to the buffer + * start + * + * Returns: The parsed taglist + * + * Since: 0.10.30 + */ +GstTagList * +gst_tag_list_from_exif_buffer (const GstBuffer * buffer, gint byte_order, + guint32 base_offset) +{ + GstExifReader reader; + g_return_val_if_fail (byte_order == G_LITTLE_ENDIAN + || byte_order == G_BIG_ENDIAN, NULL); + + gst_exif_reader_init (&reader, byte_order, buffer, base_offset); + + if (!parse_exif_ifd (&reader, 0, tag_map_ifd0)) + goto read_error; + + return gst_exif_reader_reset (&reader, TRUE); + +read_error: + { + gst_exif_reader_reset (&reader, FALSE); + GST_WARNING ("Failed to parse the exif buffer"); + return NULL; + } +} + +/** + * gst_tag_list_from_exif_buffer_with_tiff_header: + * @buffer: The exif buffer + * + * Parses the exif tags starting with a tiff header structure. + * + * Returns: The taglist + * + * Since: 0.10.30 + */ +GstTagList * +gst_tag_list_from_exif_buffer_with_tiff_header (const GstBuffer * buffer) +{ + GstByteReader reader; + guint16 fortytwo = 42; + guint16 endianness = 0; + guint32 offset; + GstTagList *taglist = NULL; + GstBuffer *subbuffer; + + GST_LOG ("Parsing exif tags with tiff header of size %u", + GST_BUFFER_SIZE (buffer)); + + gst_byte_reader_init_from_buffer (&reader, buffer); + + GST_LOG ("Parsing the tiff header"); + if (!gst_byte_reader_get_uint16_be (&reader, &endianness)) { + goto byte_reader_fail; + } + + if (endianness == TIFF_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint16_le (&reader, &fortytwo) || + !gst_byte_reader_get_uint32_le (&reader, &offset)) + goto byte_reader_fail; + } else if (endianness == TIFF_BIG_ENDIAN) { + if (!gst_byte_reader_get_uint16_be (&reader, &fortytwo) || + !gst_byte_reader_get_uint32_be (&reader, &offset)) + goto byte_reader_fail; + } else { + GST_WARNING ("Invalid endianness number %u", endianness); + return NULL; + } + + if (fortytwo != 42) { + GST_WARNING ("Invalid magic number %u, should be 42", fortytwo); + return NULL; + } + + subbuffer = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buffer) - + (TIFF_HEADER_SIZE - 2)); + memcpy (GST_BUFFER_DATA (subbuffer), + GST_BUFFER_DATA (buffer) + TIFF_HEADER_SIZE, + GST_BUFFER_SIZE (buffer) - TIFF_HEADER_SIZE); + + taglist = gst_tag_list_from_exif_buffer (subbuffer, + endianness == TIFF_LITTLE_ENDIAN ? G_LITTLE_ENDIAN : G_BIG_ENDIAN, 8); + + gst_buffer_unref (subbuffer); + return taglist; + +byte_reader_fail: + { + GST_WARNING ("Failed to read values from buffer"); + return NULL; + } +} + +/* special serialization functions */ +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (contrast, + capturing_contrast); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (exposure_mode, + capturing_exposure_mode); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (exposure_program, + capturing_exposure_program); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (gain_control, + capturing_gain_adjustment); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (metering_mode, + capturing_metering_mode); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (orientation, + image_orientation); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (saturation, + capturing_saturation); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (scene_capture_type, + capturing_scene_capture_type); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (sharpness, + capturing_sharpness); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (source, + capturing_source); +EXIF_SERIALIZATION_DESERIALIZATION_MAP_STRING_TO_INT_FUNC (white_balance, + capturing_white_balance); + +static void +serialize_geo_coordinate (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gboolean latitude; + gdouble value; + gint degrees; + gint minutes; + gint seconds; + guint32 offset; + + latitude = exiftag->exif_tag == EXIF_TAG_GPS_LATITUDE; /* exif tag for latitude */ + if (!gst_tag_list_get_double (taglist, exiftag->gst_tag, &value)) { + GST_WARNING ("Failed to get double from tag list for tag: %s", + exiftag->gst_tag); + return; + } + + /* first write the Latitude or Longitude Ref */ + if (latitude) { + if (value >= 0) { + write_exif_ascii_tag (writer, exiftag->complementary_tag, "N"); + } else { + value *= -1; + write_exif_ascii_tag (writer, exiftag->complementary_tag, "S"); + } + } else { + if (value >= 0) { + write_exif_ascii_tag (writer, exiftag->complementary_tag, "E"); + } else { + value *= -1; + write_exif_ascii_tag (writer, exiftag->complementary_tag, "W"); + } + } + + /* now write the degrees stuff */ + GST_LOG ("Converting geo location %lf to degrees", value); + degrees = (gint) value; + value -= degrees; + minutes = (gint) (value * 60); + value = (value * 60) - minutes; + seconds = (gint) (value * 60); + GST_LOG ("Converted geo location to %d.%d'%d'' degrees", degrees, + minutes, seconds); + + offset = gst_byte_writer_get_size (&writer->datawriter); + gst_exif_writer_write_tag_header (writer, exiftag->exif_tag, + EXIF_TYPE_RATIONAL, 3, offset, FALSE); + gst_exif_writer_write_rational_data (writer, degrees, 1); + gst_exif_writer_write_rational_data (writer, minutes, 1); + gst_exif_writer_write_rational_data (writer, seconds, 1); +} + +static gint +deserialize_geo_coordinate (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstByteReader fractions_reader; + gint multiplier; + GstExifTagData next_tagdata; + gint ret = 0; + /* for the conversion */ + guint32 degrees_n = 0; + guint32 degrees_d = 1; + guint32 minutes_n = 0; + guint32 minutes_d = 1; + guint32 seconds_n = 0; + guint32 seconds_d = 1; + gdouble degrees; + gdouble minutes; + gdouble seconds; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (exiftag->complementary_tag != tagdata->tag) { + /* First should come the 'Ref' tags */ + GST_WARNING ("Tag %d is not the 'Ref' tag for latitude nor longitude", + tagdata->tag); + return ret; + } + + if (tagdata->offset_as_data[0] == 'N' || tagdata->offset_as_data[0] == 'E') { + multiplier = 1; + } else if (tagdata->offset_as_data[0] == 'S' + || tagdata->offset_as_data[0] == 'W') { + multiplier = -1; + } else { + GST_WARNING ("Invalid LatitudeRef or LongitudeRef %c", + tagdata->offset_as_data[0]); + return ret; + } + + /* now read the following tag that must be the latitude or longitude */ + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) + goto reader_fail; + } else { + if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) + goto reader_fail; + } + + if (exiftag->exif_tag != next_tagdata.tag) { + GST_WARNING ("This is not a geo cordinate tag"); + return ret; + } + + /* read the remaining tag entry data */ + if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { + ret = -1; + goto reader_fail; + } + + ret = 1; + + /* some checking */ + if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { + GST_WARNING ("Invalid type %d for geo coordinate (latitude/longitude)", + next_tagdata.tag_type); + return ret; + } + if (next_tagdata.count != 3) { + GST_WARNING ("Geo coordinate should use 3 fractions, we have %u", + next_tagdata.count); + return ret; + } + + /* now parse the fractions */ + gst_byte_reader_init_from_buffer (&fractions_reader, exif_reader->buffer); + if (!gst_byte_reader_set_pos (&fractions_reader, + next_tagdata.offset - exif_reader->base_offset)) + goto reader_fail; + + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_get_uint32_le (&fractions_reader, °rees_n) || + !gst_byte_reader_get_uint32_le (&fractions_reader, °rees_d) || + !gst_byte_reader_get_uint32_le (&fractions_reader, &minutes_n) || + !gst_byte_reader_get_uint32_le (&fractions_reader, &minutes_d) || + !gst_byte_reader_get_uint32_le (&fractions_reader, &seconds_n) || + !gst_byte_reader_get_uint32_le (&fractions_reader, &seconds_d)) + goto reader_fail; + } else { + if (!gst_byte_reader_get_uint32_be (&fractions_reader, °rees_n) || + !gst_byte_reader_get_uint32_be (&fractions_reader, °rees_d) || + !gst_byte_reader_get_uint32_be (&fractions_reader, &minutes_n) || + !gst_byte_reader_get_uint32_be (&fractions_reader, &minutes_d) || + !gst_byte_reader_get_uint32_be (&fractions_reader, &seconds_n) || + !gst_byte_reader_get_uint32_be (&fractions_reader, &seconds_d)) + goto reader_fail; + } + + GST_DEBUG ("Read degrees fraction for tag %s: %u/%u %u/%u %u/%u", + exiftag->gst_tag, degrees_n, degrees_d, minutes_n, minutes_d, + seconds_n, seconds_d); + + gst_util_fraction_to_double (degrees_n, degrees_d, °rees); + gst_util_fraction_to_double (minutes_n, minutes_d, &minutes); + gst_util_fraction_to_double (seconds_n, seconds_d, &seconds); + + minutes += seconds / 60; + degrees += minutes / 60; + degrees *= multiplier; + + GST_DEBUG ("Adding %s tag: %lf", exiftag->gst_tag, degrees); + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, + exiftag->gst_tag, degrees, NULL); + + return ret; + +reader_fail: + GST_WARNING ("Failed to read fields from buffer (too short?)"); + return ret; +} + + +static void +serialize_geo_direction (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gdouble value; + + if (!gst_tag_list_get_double (taglist, exiftag->gst_tag, &value)) { + GST_WARNING ("Failed to get double from tag list for tag: %s", + exiftag->gst_tag); + return; + } + + /* first write the direction ref */ + write_exif_ascii_tag (writer, exiftag->complementary_tag, "T"); + gst_exif_writer_write_rational_tag_from_double (writer, + exiftag->exif_tag, value); +} + +static gint +deserialize_geo_direction (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData next_tagdata = { 0, }; + gint ret = 0; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (exiftag->complementary_tag == tagdata->tag) { + /* First should come the 'Ref' tags */ + if (tagdata->offset_as_data[0] == 'M') { + GST_WARNING ("Magnetic direction is not supported"); + return ret; + } else if (tagdata->offset_as_data[0] == 'T') { + /* nop */ + } else { + GST_WARNING ("Invalid Ref for direction or track %c", + tagdata->offset_as_data[0]); + return ret; + } + } else { + GST_DEBUG ("No Direction Ref, using default=T"); + if (tagdata->tag == exiftag->exif_tag) { + /* this is the main tag */ + tagdata_copy (&next_tagdata, tagdata); + } + } + + if (next_tagdata.tag == 0) { + /* now read the following tag that must be the exif_tag */ + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) + goto reader_fail; + } else { + if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) + goto reader_fail; + } + + if (exiftag->exif_tag != next_tagdata.tag) { + GST_WARNING ("Unexpected tag"); + return ret; + } + + /* read the remaining tag entry data */ + if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { + ret = -1; + goto reader_fail; + } + ret = 1; + } + + /* some checking */ + if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { + GST_WARNING ("Invalid type %d for 0x%x", next_tagdata.tag_type, + next_tagdata.tag); + return ret; + } + if (next_tagdata.count != 1) { + GST_WARNING ("0x%x tag must have a single fraction, we have %u", + next_tagdata.tag_type, next_tagdata.count); + return ret; + } + + parse_exif_rational_tag (exif_reader, + exiftag->gst_tag, next_tagdata.count, next_tagdata.offset, 1, FALSE); + + return ret; + +reader_fail: + GST_WARNING ("Failed to read fields from buffer (too short?)"); + return ret; +} + + +static void +serialize_geo_elevation (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gdouble value; + + if (!gst_tag_list_get_double (taglist, exiftag->gst_tag, &value)) { + GST_WARNING ("Failed to get double from tag list for tag: %s", + exiftag->gst_tag); + return; + } + + /* first write the Ref */ + gst_exif_writer_write_byte_tag (writer, + exiftag->complementary_tag, value >= 0 ? 0 : 1); + + if (value < 0) + value *= -1; + + /* now the value */ + gst_exif_writer_write_rational_tag_from_double (writer, + exiftag->exif_tag, value); +} + +static gint +deserialize_geo_elevation (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData next_tagdata = { 0, }; + gint multiplier = 1; + gint ret = 0; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (exiftag->complementary_tag == tagdata->tag) { + if (tagdata->offset_as_data[0] == 0) { + /* NOP */ + } else if (tagdata->offset_as_data[0] == 1) { + multiplier = -1; + } else { + GST_WARNING ("Invalid GPSAltitudeRef %u", tagdata->offset_as_data[0]); + return ret; + } + } else { + GST_DEBUG ("No GPSAltitudeRef, using default=0"); + if (tagdata->tag == exiftag->exif_tag) { + tagdata_copy (&next_tagdata, tagdata); + } + } + + /* now read the following tag that must be the exif_tag */ + if (next_tagdata.tag == 0) { + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) + goto reader_fail; + } else { + if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) + goto reader_fail; + } + + if (exiftag->exif_tag != next_tagdata.tag) { + GST_WARNING ("Unexpected tag"); + return ret; + } + + /* read the remaining tag entry data */ + if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { + ret = -1; + goto reader_fail; + } + ret = 1; + } + + /* some checking */ + if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { + GST_WARNING ("Invalid type %d for 0x%x", next_tagdata.tag_type, + next_tagdata.tag); + return ret; + } + if (next_tagdata.count != 1) { + GST_WARNING ("0x%x tag must have a single fraction, we have %u", + next_tagdata.tag_type, next_tagdata.count); + return ret; + } + + parse_exif_rational_tag (exif_reader, + exiftag->gst_tag, next_tagdata.count, next_tagdata.offset, multiplier, + FALSE); + + return ret; + +reader_fail: + GST_WARNING ("Failed to read fields from buffer (too short?)"); + return ret; +} + + +static void +serialize_speed (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gdouble value; + + if (!gst_tag_list_get_double (taglist, exiftag->gst_tag, &value)) { + GST_WARNING ("Failed to get double from tag list for tag: %s", + exiftag->gst_tag); + return; + } + + /* first write the Ref */ + write_exif_ascii_tag (writer, exiftag->complementary_tag, "K"); + + /* now the value */ + gst_exif_writer_write_rational_tag_from_double (writer, + exiftag->exif_tag, value * METERS_PER_SECOND_TO_KILOMETERS_PER_HOUR); +} + +static gint +deserialize_speed (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData next_tagdata = { 0, }; + gdouble multiplier = 1; + gint ret = 0; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (exiftag->complementary_tag == tagdata->tag) { + if (tagdata->offset_as_data[0] == 'K') { + multiplier = KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND; + } else if (tagdata->offset_as_data[0] == 'M') { + multiplier = MILES_PER_HOUR_TO_METERS_PER_SECOND; + } else if (tagdata->offset_as_data[0] == 'N') { + multiplier = KNOTS_TO_METERS_PER_SECOND; + } else { + GST_WARNING ("Invalid GPSSpeedRed %c", tagdata->offset_as_data[0]); + return ret; + } + } else { + GST_DEBUG ("No GPSSpeedRef, using default=K"); + multiplier = KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND; + + if (tagdata->tag == exiftag->exif_tag) { + tagdata_copy (&next_tagdata, tagdata); + } + } + + /* now read the following tag that must be the exif_tag */ + if (next_tagdata.tag == 0) { + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) + goto reader_fail; + } else { + if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) + goto reader_fail; + } + + if (exiftag->exif_tag != next_tagdata.tag) { + GST_WARNING ("Unexpected tag"); + return ret; + } + + /* read the remaining tag entry data */ + if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { + ret = -1; + goto reader_fail; + } + ret = 1; + } + + + /* some checking */ + if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { + GST_WARNING ("Invalid type %d for 0x%x", next_tagdata.tag_type, + next_tagdata.tag); + return ret; + } + if (next_tagdata.count != 1) { + GST_WARNING ("0x%x tag must have a single fraction, we have %u", + next_tagdata.tag_type, next_tagdata.count); + return ret; + } + + parse_exif_rational_tag (exif_reader, + exiftag->gst_tag, next_tagdata.count, next_tagdata.offset, multiplier, + FALSE); + + return ret; + +reader_fail: + GST_WARNING ("Failed to read fields from buffer (too short?)"); + return ret; +} + +static void +serialize_shutter_speed (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + const GValue *value = NULL; + gdouble num; + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + if (!value) { + GST_WARNING ("Failed to get shutter speed from from tag list"); + return; + } + gst_util_fraction_to_double (gst_value_get_fraction_numerator (value), + gst_value_get_fraction_denominator (value), &num); + +#ifdef HAVE_LOG2 + num = -log2 (num); +#else + num = -log (num) / M_LN2; +#endif + + /* now the value */ + gst_exif_writer_write_signed_rational_tag_from_double (writer, + exiftag->exif_tag, num); +} + +static gint +deserialize_shutter_speed (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + gint32 frac_n, frac_d; + gdouble d; + GValue value = { 0 }; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (!exif_reader_read_rational_tag (exif_reader, tagdata->count, + tagdata->offset, TRUE, &frac_n, &frac_d)) + return 0; + + gst_util_fraction_to_double (frac_n, frac_d, &d); + d = pow (2, -d); + gst_util_double_to_fraction (d, &frac_n, &frac_d); + + g_value_init (&value, GST_TYPE_FRACTION); + gst_value_set_fraction (&value, frac_n, frac_d); + gst_tag_list_add_value (exif_reader->taglist, GST_TAG_MERGE_KEEP, + exiftag->gst_tag, &value); + g_value_unset (&value); + + return 0; +} + +static void +serialize_aperture_value (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gdouble num; + + if (!gst_tag_list_get_double_index (taglist, exiftag->gst_tag, 0, &num)) { + GST_WARNING ("Failed to get focal ratio from from tag list"); + return; + } +#ifdef HAVE_LOG2 + num = 2 * log2 (num); +#else + num = 2 * (log (num) / M_LN2); +#endif + + /* now the value */ + gst_exif_writer_write_rational_tag_from_double (writer, + exiftag->exif_tag, num); +} + +static gint +deserialize_aperture_value (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + gint32 frac_n, frac_d; + gdouble d; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (!exif_reader_read_rational_tag (exif_reader, tagdata->count, + tagdata->offset, FALSE, &frac_n, &frac_d)) + return 0; + + gst_util_fraction_to_double (frac_n, frac_d, &d); + d = pow (2, d / 2); + + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_KEEP, + exiftag->gst_tag, d, NULL); + + return 0; +} + +static void +serialize_sensitivity_type (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + /* we only support ISOSpeed as the sensitivity type (3) */ + gst_exif_writer_write_short_tag (writer, exiftag->exif_tag, 3); +} + +static gint +deserialize_sensitivity_type (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData *sensitivity = NULL; + guint16 type_data; + + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + type_data = GST_READ_UINT16_LE (tagdata->offset_as_data); + } else { + type_data = GST_READ_UINT16_BE (tagdata->offset_as_data); + } + + if (type_data != 3) { + GST_WARNING ("We only support SensitivityType=3"); + return 0; + } + + /* check the pending tags for the PhotographicSensitivity tag */ + sensitivity = + gst_exif_reader_get_pending_tag (exif_reader, + EXIF_TAG_PHOTOGRAPHIC_SENSITIVITY); + if (sensitivity == NULL) { + GST_WARNING ("PhotographicSensitivity tag not found"); + return 0; + } + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_KEEP, + GST_TAG_CAPTURING_ISO_SPEED, sensitivity->offset_as_data, NULL); + + return 0; +} + +static void +serialize_flash (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + gboolean flash_fired; + const gchar *flash_mode; + guint16 tagvalue = 0; + + if (!gst_tag_list_get_boolean_index (taglist, exiftag->gst_tag, 0, + &flash_fired)) { + GST_WARNING ("Failed to get flash fired from from tag list"); + return; + } + + if (flash_fired) + tagvalue = 1; + + if (gst_tag_list_peek_string_index (taglist, GST_TAG_CAPTURING_FLASH_MODE, 0, + &flash_mode)) { + guint16 mode = 0; + if (strcmp (flash_mode, "auto") == 0) { + mode = 3; + } else if (strcmp (flash_mode, "always") == 0) { + mode = 1; + } else if (strcmp (flash_mode, "never") == 0) { + mode = 2; + } + + tagvalue = tagvalue | (mode << 3); + } else { + GST_DEBUG ("flash-mode not available"); + } + + gst_exif_writer_write_short_tag (writer, exiftag->exif_tag, tagvalue); +} + +static gint +deserialize_flash (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + guint16 value = 0; + guint mode = 0; + const gchar *mode_str = NULL; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + value = GST_READ_UINT16_LE (tagdata->offset_as_data); + } else { + value = GST_READ_UINT16_BE (tagdata->offset_as_data); + } + + /* check flash fired */ + if (value & 0x1) { + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_CAPTURING_FLASH_FIRED, TRUE, NULL); + } else { + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_CAPTURING_FLASH_FIRED, FALSE, NULL); + } + + mode = (value >> 3) & 0x3; + if (mode == 1) { + mode_str = "always"; + } else if (mode == 2) { + mode_str = "never"; + } else if (mode == 3) { + mode_str = "auto"; + } + + if (mode_str) + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_CAPTURING_FLASH_MODE, mode_str, NULL); + + return 0; +} + +static gint +deserialize_resolution (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GstExifTagData *xres = NULL; + GstExifTagData *yres = NULL; + guint16 unit; + gdouble multiplier; + + if (exif_reader->byte_order == G_LITTLE_ENDIAN) { + unit = GST_READ_UINT16_LE (tagdata->offset_as_data); + } else { + unit = GST_READ_UINT16_BE (tagdata->offset_as_data); + } + + if (unit != 2 && unit != 3) { + GST_WARNING ("Invalid resolution unit, ignoring PPI tags"); + return 0; + } + + xres = gst_exif_reader_get_pending_tag (exif_reader, EXIF_TAG_XRESOLUTION); + yres = gst_exif_reader_get_pending_tag (exif_reader, EXIF_TAG_YRESOLUTION); + + switch (unit) { + case 2: /* inch */ + multiplier = 1; + break; + case 3: /* cm */ + multiplier = 1 / 2.54; + break; + default: + multiplier = 1; + g_assert_not_reached (); + break; + } + + if (xres) { + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_HORIZONTAL_PPI, + xres->count, xres->offset, multiplier, FALSE); + } + if (yres) { + parse_exif_rational_tag (exif_reader, GST_TAG_IMAGE_VERTICAL_PPI, + yres->count, yres->offset, multiplier, FALSE); + } + + return 0; +} + +static void +serialize_scene_type (GstExifWriter * writer, const GstTagList * taglist, + const GstExifTagMatch * exiftag) +{ + const gchar *str; + guint8 value = 0; + + if (gst_tag_list_peek_string_index (taglist, GST_TAG_CAPTURING_SOURCE, 0, + &str)) { + if (strcmp (str, "dsc") == 0) { + value = 0; + } + } + + if (value != 0) + write_exif_undefined_tag (writer, exiftag->exif_tag, &value, 1); +} + +static gint +deserialize_scene_type (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + guint8 value = 0; + + GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, + exiftag->exif_tag); + + value = GST_READ_UINT8 (tagdata->offset_as_data); + + if (value == 1) { + gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_KEEP, + GST_TAG_CAPTURING_SOURCE, "dsc", NULL); + } + + return 0; +} + +static gint +deserialize_add_to_pending_tags (GstExifReader * exif_reader, + GstByteReader * reader, const GstExifTagMatch * exiftag, + GstExifTagData * tagdata) +{ + GST_LOG ("Adding %s tag in exif 0x%x to pending tags", exiftag->gst_tag, + exiftag->exif_tag); + + /* add it to the pending tags, as we can only parse it when we find the + * SensitivityType tag */ + gst_exif_reader_add_pending_tag (exif_reader, tagdata); + return 0; +} + +#undef EXIF_SERIALIZATION_FUNC +#undef EXIF_DESERIALIZATION_FUNC +#undef EXIF_SERIALIZATION_DESERIALIZATION_FUNC diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstid3tag.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstid3tag.c new file mode 100644 index 0000000..2c3c661 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstid3tag.c @@ -0,0 +1,487 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gstid3tag.c: plugin for reading / modifying id3 tags + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttagid3 + * @short_description: tag mappings and support functions for plugins + * dealing with ID3v1 and ID3v2 tags + * @see_also: #GstTagList + * + * + * + * Contains various utility functions for plugins to parse or create + * ID3 tags and map ID3v2 identifiers to and from GStreamer identifiers. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gsttageditingprivate.h" +#include +#include + +static const gchar *genres[] = { + "Blues", + "Classic Rock", + "Country", + "Dance", + "Disco", + "Funk", + "Grunge", + "Hip-Hop", + "Jazz", + "Metal", + "New Age", + "Oldies", + "Other", + "Pop", + "R&B", + "Rap", + "Reggae", + "Rock", + "Techno", + "Industrial", + "Alternative", + "Ska", + "Death Metal", + "Pranks", + "Soundtrack", + "Euro-Techno", + "Ambient", + "Trip-Hop", + "Vocal", + "Jazz+Funk", + "Fusion", + "Trance", + "Classical", + "Instrumental", + "Acid", + "House", + "Game", + "Sound Clip", + "Gospel", + "Noise", + "Alternative Rock", + "Bass", + "Soul", + "Punk", + "Space", + "Meditative", + "Instrumental Pop", + "Instrumental Rock", + "Ethnic", + "Gothic", + "Darkwave", + "Techno-Industrial", + "Electronic", + "Pop-Folk", + "Eurodance", + "Dream", + "Southern Rock", + "Comedy", + "Cult", + "Gangsta", + "Top 40", + "Christian Rap", + "Pop/Funk", + "Jungle", + "Native American", + "Cabaret", + "New Wave", + "Psychedelic", + "Rave", + "Showtunes", + "Trailer", + "Lo-Fi", + "Tribal", + "Acid Punk", + "Acid Jazz", + "Polka", + "Retro", + "Musical", + "Rock & Roll", + "Hard Rock", + "Folk", + "Folk/Rock", + "National Folk", + "Swing", + "Fusion", + "Bebob", + "Latin", + "Revival", + "Celtic", + "Bluegrass", + "Avantgarde", + "Gothic Rock", + "Progressive Rock", + "Psychedelic Rock", + "Symphonic Rock", + "Slow Rock", + "Big Band", + "Chorus", + "Easy Listening", + "Acoustic", + "Humour", + "Speech", + "Chanson", + "Opera", + "Chamber Music", + "Sonata", + "Symphony", + "Booty Bass", + "Primus", + "Porn Groove", + "Satire", + "Slow Jam", + "Club", + "Tango", + "Samba", + "Folklore", + "Ballad", + "Power Ballad", + "Rhythmic Soul", + "Freestyle", + "Duet", + "Punk Rock", + "Drum Solo", + "A Capella", + "Euro-House", + "Dance Hall", + "Goa", + "Drum & Bass", + "Club-House", + "Hardcore", + "Terror", + "Indie", + "BritPop", + "Negerpunk", + "Polsk Punk", + "Beat", + "Christian Gangsta Rap", + "Heavy Metal", + "Black Metal", + "Crossover", + "Contemporary Christian", + "Christian Rock", + "Merengue", + "Salsa", + "Thrash Metal", + "Anime", + "Jpop", + "Synthpop" +}; + +static const GstTagEntryMatch tag_matches[] = { + {GST_TAG_TITLE, "TIT2"}, + {GST_TAG_ALBUM, "TALB"}, + {GST_TAG_TRACK_NUMBER, "TRCK"}, + {GST_TAG_ARTIST, "TPE1"}, + {GST_TAG_ALBUM_ARTIST, "TPE2"}, + {GST_TAG_COMPOSER, "TCOM"}, + {GST_TAG_COPYRIGHT, "TCOP"}, + {GST_TAG_COPYRIGHT_URI, "WCOP"}, + {GST_TAG_ENCODED_BY, "TENC"}, + {GST_TAG_GENRE, "TCON"}, + {GST_TAG_DATE, "TDRC"}, + {GST_TAG_COMMENT, "COMM"}, + {GST_TAG_ALBUM_VOLUME_NUMBER, "TPOS"}, + {GST_TAG_DURATION, "TLEN"}, + {GST_TAG_ISRC, "TSRC"}, + {GST_TAG_IMAGE, "APIC"}, + {GST_TAG_ENCODER, "TSSE"}, + {GST_TAG_BEATS_PER_MINUTE, "TBPM"}, + {GST_TAG_ARTIST_SORTNAME, "TSOP"}, + {GST_TAG_ALBUM_SORTNAME, "TSOA"}, + {GST_TAG_TITLE_SORTNAME, "TSOT"}, + {NULL, NULL} +}; + +/** + * gst_tag_from_id3_tag: + * @id3_tag: ID3v2 tag to convert to GStreamer tag + * + * Looks up the GStreamer tag for a ID3v2 tag. + * + * Returns: The corresponding GStreamer tag or NULL if none exists. + */ +G_CONST_RETURN gchar * +gst_tag_from_id3_tag (const gchar * id3_tag) +{ + int i = 0; + + g_return_val_if_fail (id3_tag != NULL, NULL); + + while (tag_matches[i].gstreamer_tag != NULL) { + if (strncmp (id3_tag, tag_matches[i].original_tag, 5) == 0) { + return tag_matches[i].gstreamer_tag; + } + i++; + } + + GST_INFO ("Cannot map ID3v2 tag '%c%c%c%c' to GStreamer tag", + id3_tag[0], id3_tag[1], id3_tag[2], id3_tag[3]); + + return NULL; +} + +static const GstTagEntryMatch user_tag_matches[] = { + /* musicbrainz identifiers being used in the real world (foobar2000) */ + {GST_TAG_MUSICBRAINZ_ARTISTID, "TXXX|musicbrainz_artistid"}, + {GST_TAG_MUSICBRAINZ_ALBUMID, "TXXX|musicbrainz_albumid"}, + {GST_TAG_MUSICBRAINZ_ALBUMARTISTID, "TXXX|musicbrainz_albumartistid"}, + {GST_TAG_MUSICBRAINZ_TRMID, "TXXX|musicbrainz_trmid"}, + {GST_TAG_CDDA_MUSICBRAINZ_DISCID, "TXXX|musicbrainz_discid"}, + /* musicbrainz identifiers according to spec no one pays + * attention to (http://musicbrainz.org/docs/specs/metadata_tags.html) */ + {GST_TAG_MUSICBRAINZ_ARTISTID, "TXXX|MusicBrainz Artist Id"}, + {GST_TAG_MUSICBRAINZ_ALBUMID, "TXXX|MusicBrainz Album Id"}, + {GST_TAG_MUSICBRAINZ_ALBUMARTISTID, "TXXX|MusicBrainz Album Artist Id"}, + {GST_TAG_MUSICBRAINZ_TRMID, "TXXX|MusicBrainz TRM Id"}, + /* according to: http://wiki.musicbrainz.org/MusicBrainzTag (yes, no space + * before 'ID' and not 'Id' either this time, yay for consistency) */ + {GST_TAG_CDDA_MUSICBRAINZ_DISCID, "TXXX|MusicBrainz DiscID"}, + /* foobar2000 uses these identifiers to store gain/peak information in + * ID3v2 tags <= v2.3.0. In v2.4.0 there's the RVA2 frame for that */ + {GST_TAG_TRACK_GAIN, "TXXX|replaygain_track_gain"}, + {GST_TAG_TRACK_PEAK, "TXXX|replaygain_track_peak"}, + {GST_TAG_ALBUM_GAIN, "TXXX|replaygain_album_gain"}, + {GST_TAG_ALBUM_PEAK, "TXXX|replaygain_album_peak"}, + /* the following two are more or less made up, there seems to be little + * evidence that any popular application is actually putting this info + * into TXXX frames; the first one comes from a musicbrainz wiki 'proposed + * tags' page, the second one is analogue to the vorbis/ape/flac tag. */ + {GST_TAG_CDDA_CDDB_DISCID, "TXXX|discid"}, + {GST_TAG_CDDA_CDDB_DISCID, "TXXX|CDDB DiscID"} +}; + +/** + * gst_tag_from_id3_user_tag: + * @type: the type of ID3v2 user tag (e.g. "TXXX" or "UDIF") + * @id3_user_tag: ID3v2 user tag to convert to GStreamer tag + * + * Looks up the GStreamer tag for an ID3v2 user tag (e.g. description in + * TXXX frame or owner in UFID frame). + * + * Returns: The corresponding GStreamer tag or NULL if none exists. + */ +G_CONST_RETURN gchar * +gst_tag_from_id3_user_tag (const gchar * type, const gchar * id3_user_tag) +{ + int i = 0; + + g_return_val_if_fail (type != NULL && strlen (type) == 4, NULL); + g_return_val_if_fail (id3_user_tag != NULL, NULL); + + for (i = 0; i < G_N_ELEMENTS (user_tag_matches); ++i) { + if (strncmp (type, user_tag_matches[i].original_tag, 4) == 0 && + g_ascii_strcasecmp (id3_user_tag, + user_tag_matches[i].original_tag + 5) == 0) { + GST_LOG ("Mapped ID3v2 user tag '%s' to GStreamer tag '%s'", + user_tag_matches[i].original_tag, user_tag_matches[i].gstreamer_tag); + return user_tag_matches[i].gstreamer_tag; + } + } + + GST_INFO ("Cannot map ID3v2 user tag '%s' of type '%s' to GStreamer tag", + id3_user_tag, type); + + return NULL; +} + +/** + * gst_tag_to_id3_tag: + * @gst_tag: GStreamer tag to convert to vorbiscomment tag + * + * Looks up the ID3v2 tag for a GStreamer tag. + * + * Returns: The corresponding ID3v2 tag or NULL if none exists. + */ +G_CONST_RETURN gchar * +gst_tag_to_id3_tag (const gchar * gst_tag) +{ + int i = 0; + + g_return_val_if_fail (gst_tag != NULL, NULL); + + while (tag_matches[i].gstreamer_tag != NULL) { + if (strcmp (gst_tag, tag_matches[i].gstreamer_tag) == 0) { + return tag_matches[i].original_tag; + } + i++; + } + return NULL; +} + +static void +gst_tag_extract_id3v1_string (GstTagList * list, const gchar * tag, + const gchar * start, const guint size) +{ + const gchar *env_vars[] = { "GST_ID3V1_TAG_ENCODING", + "GST_ID3_TAG_ENCODING", "GST_TAG_ENCODING", NULL + }; + gchar *utf8; + + utf8 = gst_tag_freeform_string_to_utf8 (start, size, env_vars); + + if (utf8 && *utf8 != '\0') { + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, tag, utf8, NULL); + } + + g_free (utf8); +} + +/** + * gst_tag_list_new_from_id3v1: + * @data: 128 bytes of data containing the ID3v1 tag + * + * Parses the data containing an ID3v1 tag and returns a #GstTagList from the + * parsed data. + * + * Returns: A new tag list or NULL if the data was not an ID3v1 tag. + */ +GstTagList * +gst_tag_list_new_from_id3v1 (const guint8 * data) +{ + guint year; + gchar *ystr; + GstTagList *list; + + g_return_val_if_fail (data != NULL, NULL); + + if (data[0] != 'T' || data[1] != 'A' || data[2] != 'G') + return NULL; + list = gst_tag_list_new (); + gst_tag_extract_id3v1_string (list, GST_TAG_TITLE, (gchar *) & data[3], 30); + gst_tag_extract_id3v1_string (list, GST_TAG_ARTIST, (gchar *) & data[33], 30); + gst_tag_extract_id3v1_string (list, GST_TAG_ALBUM, (gchar *) & data[63], 30); + ystr = g_strndup ((gchar *) & data[93], 4); + year = strtoul (ystr, NULL, 10); + g_free (ystr); + if (year > 0) { + GDate *date = g_date_new_dmy (1, 1, year); + + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_DATE, date, NULL); + g_date_free (date); + } + if (data[125] == 0 && data[126] != 0) { + gst_tag_extract_id3v1_string (list, GST_TAG_COMMENT, (gchar *) & data[97], + 28); + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_TRACK_NUMBER, + (guint) data[126], NULL); + } else { + gst_tag_extract_id3v1_string (list, GST_TAG_COMMENT, (gchar *) & data[97], + 30); + } + if (data[127] < gst_tag_id3_genre_count () && !gst_tag_list_is_empty (list)) { + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_GENRE, + gst_tag_id3_genre_get (data[127]), NULL); + } + + return list; +} + +/** + * gst_tag_id3_genre_count: + * + * Gets the number of ID3v1 genres that can be identified. Winamp genres are + * included. + * + * Returns: the number of ID3v1 genres that can be identified + */ +guint +gst_tag_id3_genre_count (void) +{ + return G_N_ELEMENTS (genres); +} + +/** + * gst_tag_id3_genre_get: + * @id: ID of genre to query + * + * Gets the ID3v1 genre name for a given ID. + * + * Returns: the genre or NULL if no genre is associated with that ID. + */ +G_CONST_RETURN gchar * +gst_tag_id3_genre_get (const guint id) +{ + if (id >= G_N_ELEMENTS (genres)) + return NULL; + return genres[id]; +} + +/** + * gst_tag_list_add_id3_image: + * @tag_list: a tag list + * @image_data: the (encoded) image + * @image_data_len: the length of the encoded image data at @image_data + * @id3_picture_type: picture type as per the ID3 (v2.4.0) specification for + * the APIC frame (0 = unknown/other) + * + * Adds an image from an ID3 APIC frame (or similar, such as used in FLAC) + * to the given tag list. Also see gst_tag_image_data_to_image_buffer() for + * more information on image tags in GStreamer. + * + * Returns: %TRUE if the image was processed, otherwise %FALSE + * + * Since: 0.10.20 + */ +gboolean +gst_tag_list_add_id3_image (GstTagList * tag_list, const guint8 * image_data, + guint image_data_len, guint id3_picture_type) +{ + GstTagImageType tag_image_type; + const gchar *tag_name; + GstBuffer *image; + + g_return_val_if_fail (GST_IS_TAG_LIST (tag_list), FALSE); + g_return_val_if_fail (image_data != NULL, FALSE); + g_return_val_if_fail (image_data_len > 0, FALSE); + + if (id3_picture_type == 0x01 || id3_picture_type == 0x02) { + /* file icon for preview. Don't add image-type to caps, since there + * is only supposed to be one of these, and the type is already indicated + * via the special tag */ + tag_name = GST_TAG_PREVIEW_IMAGE; + tag_image_type = GST_TAG_IMAGE_TYPE_NONE; + } else { + tag_name = GST_TAG_IMAGE; + + /* Remap the ID3v2 APIC type our ImageType enum */ + if (id3_picture_type >= 0x3 && id3_picture_type <= 0x14) + tag_image_type = (GstTagImageType) (id3_picture_type - 2); + else + tag_image_type = GST_TAG_IMAGE_TYPE_UNDEFINED; + } + + image = gst_tag_image_data_to_image_buffer (image_data, image_data_len, + tag_image_type); + + if (image == NULL) + return FALSE; + + gst_tag_list_add (tag_list, GST_TAG_MERGE_APPEND, tag_name, image, NULL); + gst_buffer_unref (image); + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.c new file mode 100644 index 0000000..8bb3314 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.c @@ -0,0 +1,1535 @@ +/* GStreamer Base Class for Tag Demuxing + * Copyright (C) 2005 Jan Schmidt + * Copyright (C) 2006-2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttagdemux + * @see_also: GstApeDemux, GstID3Demux + * @short_description: Base class for demuxing tags that are in chunks + * directly at the beginning or at the end of a file + * + * + * + * Provides a base class for demuxing tags at the beginning or end of a + * stream and handles things like typefinding, querying, seeking, and + * different modes of operation (chain-based, pull_range-based, and providing + * downstream elements with random access if upstream supports that). The tag + * is stripped from the output, and all offsets are adjusted for the tag + * sizes, so that to the downstream element the stream will appear as if + * there was no tag at all. Also, once the tag has been parsed, GstTagDemux + * will try to determine the media type of the resulting stream and add a + * source pad with the appropriate caps in order to facilitate auto-plugging. + * + * Deriving from GstTagDemux + * + * Subclasses have to do four things: + * + * + * In their base init function, they must add a pad template for the sink + * pad to the element class, describing the media type they can parse in + * the caps of the pad template. + * + * + * In their class init function, they must override + * GST_TAG_DEMUX_CLASS(demux_klass)->identify_tag with their own identify + * function. + * + * + * In their class init function, they must override + * GST_TAG_DEMUX_CLASS(demux_klass)->parse_tag with their own parse + * function. + * + * + * In their class init function, they must also set + * GST_TAG_DEMUX_CLASS(demux_klass)->min_start_size and/or + * GST_TAG_DEMUX_CLASS(demux_klass)->min_end_size to the minimum size required + * for the identify function to decide whether the stream has a supported tag + * or not. A class parsing ID3v1 tags, for example, would set min_end_size to + * 128 bytes. + * + * + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gsttagdemux.h" + +#include +#include +#include + +typedef enum +{ + GST_TAG_DEMUX_READ_START_TAG, + GST_TAG_DEMUX_TYPEFINDING, + GST_TAG_DEMUX_STREAMING +} GstTagDemuxState; + +struct _GstTagDemuxPrivate +{ + GstPad *srcpad; + GstPad *sinkpad; + + /* Number of bytes to remove from the + * start of file (tag at beginning) */ + guint strip_start; + + /* Number of bytes to remove from the + * end of file (tag at end) */ + guint strip_end; + + gint64 upstream_size; + + GstTagDemuxState state; + GstBuffer *collect; + GstCaps *src_caps; + + GstTagList *event_tags; + GstTagList *parsed_tags; + gboolean send_tag_event; + + GstSegment segment; + gboolean need_newseg; + gboolean newseg_update; + + GList *pending_events; +}; + +/* Require at least 8kB of data before we attempt typefind. + * Seems a decent value based on test files + * 40kB is massive overkill for the maximum, I think, but it + * doesn't do any harm (tpm: increased to 64kB after watching + * typefinding fail on a wavpack file that needed 42kB to succeed) */ +#define TYPE_FIND_MIN_SIZE 8192 +#define TYPE_FIND_MAX_SIZE 65536 + +GST_DEBUG_CATEGORY_STATIC (tagdemux_debug); +#define GST_CAT_DEFAULT (tagdemux_debug) + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("ANY") + ); + +static void gst_tag_demux_dispose (GObject * object); + +static GstFlowReturn gst_tag_demux_chain (GstPad * pad, GstBuffer * buf); +static gboolean gst_tag_demux_sink_event (GstPad * pad, GstEvent * event); + +static gboolean gst_tag_demux_src_activate_pull (GstPad * pad, gboolean active); +static GstFlowReturn gst_tag_demux_read_range (GstTagDemux * tagdemux, + guint64 offset, guint length, GstBuffer ** buffer); + +static gboolean gst_tag_demux_src_checkgetrange (GstPad * srcpad); +static GstFlowReturn gst_tag_demux_src_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer); + +static gboolean gst_tag_demux_add_srcpad (GstTagDemux * tagdemux, + GstCaps * new_caps); +static gboolean gst_tag_demux_remove_srcpad (GstTagDemux * tagdemux); + +static gboolean gst_tag_demux_srcpad_event (GstPad * pad, GstEvent * event); +static gboolean gst_tag_demux_sink_activate (GstPad * sinkpad); +static GstStateChangeReturn gst_tag_demux_change_state (GstElement * element, + GstStateChange transition); +static gboolean gst_tag_demux_pad_query (GstPad * pad, GstQuery * query); +static const GstQueryType *gst_tag_demux_get_query_types (GstPad * pad); +static gboolean gst_tag_demux_get_upstream_size (GstTagDemux * tagdemux); +static void gst_tag_demux_send_pending_events (GstTagDemux * tagdemux); +static void gst_tag_demux_send_tag_event (GstTagDemux * tagdemux); +static gboolean gst_tag_demux_send_new_segment (GstTagDemux * tagdemux); + +static void gst_tag_demux_base_init (gpointer g_class); +static void gst_tag_demux_class_init (gpointer g_class, gpointer d); +static void gst_tag_demux_init (GstTagDemux * obj, GstTagDemuxClass * klass); + +static gpointer parent_class; /* NULL */ + +GType +gst_tag_demux_result_get_type (void) +{ + static GType etype = 0; + if (etype == 0) { + static const GEnumValue values[] = { + {GST_TAG_DEMUX_RESULT_BROKEN_TAG, "GST_TAG_DEMUX_RESULT_BROKEN_TAG", + "broken-tag"}, + {GST_TAG_DEMUX_RESULT_AGAIN, "GST_TAG_DEMUX_RESULT_AGAIN", "again"}, + {GST_TAG_DEMUX_RESULT_OK, "GST_TAG_DEMUX_RESULT_OK", "ok"}, + {0, NULL, NULL} + }; + etype = g_enum_register_static ("GstTagDemuxResult", values); + } + return etype; +} + +/* Cannot use boilerplate macros here because we want the abstract flag */ +GType +gst_tag_demux_get_type (void) +{ + static GType object_type; /* 0 */ + + if (object_type == 0) { + static const GTypeInfo object_info = { + sizeof (GstTagDemuxClass), + gst_tag_demux_base_init, + NULL, /* base_finalize */ + gst_tag_demux_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GstTagDemux), + 0, /* n_preallocs */ + (GInstanceInitFunc) gst_tag_demux_init + }; + + object_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstTagDemux", &object_info, G_TYPE_FLAG_ABSTRACT); + } + + return object_type; +} + +static void +gst_tag_demux_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + + GST_DEBUG_CATEGORY_INIT (tagdemux_debug, "tagdemux", 0, + "tag demux base class"); +} + +static void +gst_tag_demux_class_init (gpointer klass, gpointer d) +{ + GstTagDemuxClass *tagdemux_class = GST_TAG_DEMUX_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_tag_demux_dispose; + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_tag_demux_change_state); + + g_type_class_add_private (klass, sizeof (GstTagDemuxPrivate)); + + /* subclasses must set at least one of these */ + tagdemux_class->min_start_size = 0; + tagdemux_class->min_end_size = 0; +} + +static void +gst_tag_demux_reset (GstTagDemux * tagdemux) +{ + GstBuffer **buffer_p = &tagdemux->priv->collect; + GstCaps **caps_p = &tagdemux->priv->src_caps; + + tagdemux->priv->strip_start = 0; + tagdemux->priv->strip_end = 0; + tagdemux->priv->upstream_size = -1; + tagdemux->priv->state = GST_TAG_DEMUX_READ_START_TAG; + tagdemux->priv->send_tag_event = FALSE; + + gst_buffer_replace (buffer_p, NULL); + gst_caps_replace (caps_p, NULL); + + gst_tag_demux_remove_srcpad (tagdemux); + + if (tagdemux->priv->event_tags) { + gst_tag_list_free (tagdemux->priv->event_tags); + tagdemux->priv->event_tags = NULL; + } + if (tagdemux->priv->parsed_tags) { + gst_tag_list_free (tagdemux->priv->parsed_tags); + tagdemux->priv->parsed_tags = NULL; + } + + gst_segment_init (&tagdemux->priv->segment, GST_FORMAT_UNDEFINED); + tagdemux->priv->need_newseg = TRUE; + tagdemux->priv->newseg_update = FALSE; + + g_list_foreach (tagdemux->priv->pending_events, + (GFunc) gst_mini_object_unref, NULL); + g_list_free (tagdemux->priv->pending_events); + tagdemux->priv->pending_events = NULL; +} + +static void +gst_tag_demux_init (GstTagDemux * demux, GstTagDemuxClass * gclass) +{ + GstElementClass *element_klass = GST_ELEMENT_CLASS (gclass); + GstPadTemplate *tmpl; + + demux->priv = g_type_instance_get_private ((GTypeInstance *) demux, + GST_TYPE_TAG_DEMUX); + + tmpl = gst_element_class_get_pad_template (element_klass, "sink"); + if (tmpl) { + demux->priv->sinkpad = gst_pad_new_from_template (tmpl, "sink"); + + gst_pad_set_activate_function (demux->priv->sinkpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_sink_activate)); + gst_pad_set_event_function (demux->priv->sinkpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_sink_event)); + gst_pad_set_chain_function (demux->priv->sinkpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_chain)); + gst_element_add_pad (GST_ELEMENT (demux), demux->priv->sinkpad); + } + + gst_tag_demux_reset (demux); +} + +static void +gst_tag_demux_dispose (GObject * object) +{ + GstTagDemux *tagdemux = GST_TAG_DEMUX (object); + + gst_tag_demux_reset (tagdemux); + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static gboolean +gst_tag_demux_add_srcpad (GstTagDemux * tagdemux, GstCaps * new_caps) +{ + if (tagdemux->priv->src_caps == NULL || + !gst_caps_is_equal (new_caps, tagdemux->priv->src_caps)) { + + gst_caps_replace (&tagdemux->priv->src_caps, new_caps); + + if (tagdemux->priv->srcpad != NULL) { + GST_DEBUG_OBJECT (tagdemux, "Changing src pad caps to %" GST_PTR_FORMAT, + tagdemux->priv->src_caps); + + gst_pad_set_caps (tagdemux->priv->srcpad, tagdemux->priv->src_caps); + } + } else { + /* Caps never changed */ + } + + if (tagdemux->priv->srcpad == NULL) { + tagdemux->priv->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template + (GST_ELEMENT_GET_CLASS (tagdemux), "src"), "src"); + g_return_val_if_fail (tagdemux->priv->srcpad != NULL, FALSE); + + gst_pad_set_query_type_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_get_query_types)); + gst_pad_set_query_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_pad_query)); + gst_pad_set_event_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_srcpad_event)); + gst_pad_set_activatepull_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_src_activate_pull)); + gst_pad_set_checkgetrange_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_src_checkgetrange)); + gst_pad_set_getrange_function (tagdemux->priv->srcpad, + GST_DEBUG_FUNCPTR (gst_tag_demux_src_getrange)); + + gst_pad_use_fixed_caps (tagdemux->priv->srcpad); + + if (tagdemux->priv->src_caps) + gst_pad_set_caps (tagdemux->priv->srcpad, tagdemux->priv->src_caps); + + GST_DEBUG_OBJECT (tagdemux, "Adding src pad with caps %" GST_PTR_FORMAT, + tagdemux->priv->src_caps); + + gst_object_ref (tagdemux->priv->srcpad); + gst_pad_set_active (tagdemux->priv->srcpad, TRUE); + if (!gst_element_add_pad (GST_ELEMENT (tagdemux), tagdemux->priv->srcpad)) + return FALSE; + gst_element_no_more_pads (GST_ELEMENT (tagdemux)); + } + + return TRUE; +} + +static gboolean +gst_tag_demux_remove_srcpad (GstTagDemux * demux) +{ + gboolean res = TRUE; + + if (demux->priv->srcpad != NULL) { + GST_DEBUG_OBJECT (demux, "Removing src pad"); + res = gst_element_remove_pad (GST_ELEMENT (demux), demux->priv->srcpad); + g_return_val_if_fail (res != FALSE, FALSE); + gst_object_unref (demux->priv->srcpad); + demux->priv->srcpad = NULL; + } + + return res; +}; + +/* will return FALSE if buffer is beyond end of data; will return TRUE + * if buffer was trimmed successfully or didn't need trimming, but may + * also return TRUE and set *buf_ref to NULL if the buffer was before + * the start of the data */ +static gboolean +gst_tag_demux_trim_buffer (GstTagDemux * tagdemux, GstBuffer ** buf_ref) +{ + GstBuffer *buf = *buf_ref; + + guint trim_start = 0; + guint out_size = GST_BUFFER_SIZE (buf); + guint64 out_offset = GST_BUFFER_OFFSET (buf); + gboolean need_sub = FALSE; + + /* Adjust offset and length */ + if (!GST_BUFFER_OFFSET_IS_VALID (buf)) { + /* Can't change anything without an offset */ + return TRUE; + } + + /* If the buffer crosses the tag at the end of file, trim it */ + if (tagdemux->priv->strip_end > 0) { + if (gst_tag_demux_get_upstream_size (tagdemux)) { + guint64 v1tag_offset = + tagdemux->priv->upstream_size - tagdemux->priv->strip_end; + + if (out_offset >= v1tag_offset) { + GST_DEBUG_OBJECT (tagdemux, "Buffer is past the end of the data"); + goto no_out_buffer_end; + } + + if (out_offset + out_size > v1tag_offset) { + out_size = v1tag_offset - out_offset; + need_sub = TRUE; + } + } + } + + if (tagdemux->priv->strip_start > 0) { + /* If the buffer crosses the tag at the start of file, trim it */ + if (out_offset <= tagdemux->priv->strip_start) { + if (out_offset + out_size <= tagdemux->priv->strip_start) { + GST_DEBUG_OBJECT (tagdemux, "Buffer is before the start of the data"); + goto no_out_buffer_start; + } + + trim_start = tagdemux->priv->strip_start - out_offset; + out_size -= trim_start; + out_offset = 0; + } else { + out_offset -= tagdemux->priv->strip_start; + } + need_sub = TRUE; + } + + if (need_sub == TRUE) { + if (out_size != GST_BUFFER_SIZE (buf) || !gst_buffer_is_writable (buf)) { + GstBuffer *sub; + + GST_DEBUG_OBJECT (tagdemux, "Sub-buffering to trim size %d offset %" + G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT, + GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset); + + sub = gst_buffer_create_sub (buf, trim_start, out_size); + g_return_val_if_fail (sub != NULL, FALSE); + gst_buffer_unref (buf); + *buf_ref = buf = sub; + } else { + GST_DEBUG_OBJECT (tagdemux, "Adjusting buffer from size %d offset %" + G_GINT64_FORMAT " to %d offset %" G_GINT64_FORMAT, + GST_BUFFER_SIZE (buf), GST_BUFFER_OFFSET (buf), out_size, out_offset); + } + + GST_BUFFER_OFFSET (buf) = out_offset; + GST_BUFFER_OFFSET_END (buf) = out_offset + out_size; + gst_buffer_set_caps (buf, tagdemux->priv->src_caps); + } + + return TRUE; + +no_out_buffer_end: + { + gst_buffer_unref (buf); + *buf_ref = NULL; + return FALSE; + } +no_out_buffer_start: + { + gst_buffer_unref (buf); + *buf_ref = NULL; + return TRUE; + } +} + +static void +gst_tag_demux_chain_parse_tag (GstTagDemux * demux, GstBuffer * collect) +{ + GstTagDemuxResult parse_ret; + GstTagDemuxClass *klass; + guint tagsize = 0; + guint available; + + g_assert (gst_buffer_is_metadata_writable (collect)); + + klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux)); + + /* If we receive a buffer that's from the middle of the file, + * we can't read tags so move to typefinding */ + if (GST_BUFFER_OFFSET_IS_VALID (collect) && GST_BUFFER_OFFSET (collect) != 0) { + GST_DEBUG_OBJECT (demux, "Received buffer from non-zero offset %" + G_GINT64_FORMAT ". Can't read tags", GST_BUFFER_OFFSET (collect)); + demux->priv->state = GST_TAG_DEMUX_TYPEFINDING; + return; + } + + g_assert (klass->identify_tag != NULL); + g_assert (klass->parse_tag != NULL); + + available = GST_BUFFER_SIZE (collect); + + if (available < klass->min_start_size) { + GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed " + "to identify tag", available, klass->min_start_size); + return; /* wait for more data */ + } + + if (!klass->identify_tag (demux, collect, TRUE, &tagsize)) { + GST_DEBUG_OBJECT (demux, "Could not identify start tag"); + demux->priv->state = GST_TAG_DEMUX_TYPEFINDING; + return; + } + + /* need to set offset of first buffer to 0 or trimming won't work */ + if (!GST_BUFFER_OFFSET_IS_VALID (collect)) { + GST_WARNING_OBJECT (demux, "Fixing up first buffer without offset"); + GST_BUFFER_OFFSET (collect) = 0; + } + + GST_DEBUG_OBJECT (demux, "Identified tag, size = %u bytes", tagsize); + + do { + GstTagList *tags = NULL; + guint newsize, saved_size; + + demux->priv->strip_start = tagsize; + + if (available < tagsize) { + GST_DEBUG_OBJECT (demux, "Only %u bytes available, but %u needed " + "to parse tag", available, tagsize); + return; /* wait for more data */ + } + + saved_size = GST_BUFFER_SIZE (collect); + GST_BUFFER_SIZE (collect) = tagsize; + newsize = tagsize; + + parse_ret = klass->parse_tag (demux, collect, TRUE, &newsize, &tags); + + GST_BUFFER_SIZE (collect) = saved_size; + + switch (parse_ret) { + case GST_TAG_DEMUX_RESULT_OK: + demux->priv->strip_start = newsize; + demux->priv->parsed_tags = tags; + GST_DEBUG_OBJECT (demux, "Read start tag of size %u", newsize); + break; + case GST_TAG_DEMUX_RESULT_BROKEN_TAG: + demux->priv->strip_start = newsize; + demux->priv->parsed_tags = tags; + GST_WARNING_OBJECT (demux, "Ignoring broken start tag of size %d", + demux->priv->strip_start); + break; + case GST_TAG_DEMUX_RESULT_AGAIN: + GST_DEBUG_OBJECT (demux, "Re-parse, this time with %u bytes", newsize); + g_assert (newsize != tagsize); + tagsize = newsize; + break; + } + } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN); + + GST_LOG_OBJECT (demux, "Parsed tag. Proceeding to typefinding"); + demux->priv->state = GST_TAG_DEMUX_TYPEFINDING; + demux->priv->send_tag_event = TRUE; +} + +static GstFlowReturn +gst_tag_demux_chain (GstPad * pad, GstBuffer * buf) +{ + GstTagDemux *demux; + + demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad)); + + /* Update our segment last_stop info */ + if (demux->priv->segment.format == GST_FORMAT_BYTES) { + if (GST_BUFFER_OFFSET_IS_VALID (buf)) + demux->priv->segment.last_stop = GST_BUFFER_OFFSET (buf); + demux->priv->segment.last_stop += GST_BUFFER_SIZE (buf); + } else if (demux->priv->segment.format == GST_FORMAT_TIME) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) + demux->priv->segment.last_stop = GST_BUFFER_TIMESTAMP (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) + demux->priv->segment.last_stop += GST_BUFFER_DURATION (buf); + } + + if (demux->priv->collect == NULL) { + demux->priv->collect = buf; + } else { + demux->priv->collect = gst_buffer_join (demux->priv->collect, buf); + } + buf = NULL; + + switch (demux->priv->state) { + case GST_TAG_DEMUX_READ_START_TAG: + demux->priv->collect = + gst_buffer_make_metadata_writable (demux->priv->collect); + gst_tag_demux_chain_parse_tag (demux, demux->priv->collect); + if (demux->priv->state != GST_TAG_DEMUX_TYPEFINDING) + break; + /* Fall-through */ + case GST_TAG_DEMUX_TYPEFINDING:{ + GstTypeFindProbability probability = 0; + GstBuffer *typefind_buf = NULL; + GstCaps *caps; + + if (GST_BUFFER_SIZE (demux->priv->collect) < + TYPE_FIND_MIN_SIZE + demux->priv->strip_start) + break; /* Go get more data first */ + + GST_DEBUG_OBJECT (demux, "Typefinding with size %d", + GST_BUFFER_SIZE (demux->priv->collect)); + + /* Trim the buffer and adjust offset for typefinding */ + typefind_buf = demux->priv->collect; + gst_buffer_ref (typefind_buf); + if (!gst_tag_demux_trim_buffer (demux, &typefind_buf)) + return GST_FLOW_UNEXPECTED; + + if (typefind_buf == NULL) + break; /* Still need more data */ + + caps = gst_type_find_helper_for_buffer (GST_OBJECT (demux), + typefind_buf, &probability); + + if (caps == NULL) { + if (GST_BUFFER_SIZE (typefind_buf) < TYPE_FIND_MAX_SIZE) { + /* Just break for more data */ + gst_buffer_unref (typefind_buf); + return GST_FLOW_OK; + } + + /* We failed typefind */ + GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL), + ("Could not detect type for contents within tag")); + gst_buffer_unref (typefind_buf); + gst_buffer_unref (demux->priv->collect); + demux->priv->collect = NULL; + return GST_FLOW_ERROR; + } + gst_buffer_unref (typefind_buf); + + GST_DEBUG_OBJECT (demux, "Found type %" GST_PTR_FORMAT " with a " + "probability of %u", caps, probability); + + if (!gst_tag_demux_add_srcpad (demux, caps)) { + GST_DEBUG_OBJECT (demux, "Failed to add srcpad"); + gst_caps_unref (caps); + goto error; + } + gst_caps_unref (caps); + + /* Move onto streaming and fall-through to push out existing + * data */ + demux->priv->state = GST_TAG_DEMUX_STREAMING; + /* fall-through */ + } + case GST_TAG_DEMUX_STREAMING:{ + GstBuffer *outbuf = NULL; + + /* Trim the buffer and adjust offset */ + if (demux->priv->collect) { + outbuf = demux->priv->collect; + demux->priv->collect = NULL; + if (!gst_tag_demux_trim_buffer (demux, &outbuf)) + return GST_FLOW_UNEXPECTED; + } + if (outbuf) { + if (G_UNLIKELY (demux->priv->srcpad == NULL)) { + gst_buffer_unref (outbuf); + return GST_FLOW_ERROR; + } + + /* Might need a new segment before the buffer */ + if (demux->priv->need_newseg) { + if (!gst_tag_demux_send_new_segment (demux)) { + GST_WARNING_OBJECT (demux, "Downstream did not handle newsegment " + "event as it should"); + } + demux->priv->need_newseg = FALSE; + } + + /* send any pending events we cached */ + gst_tag_demux_send_pending_events (demux); + + /* Send our own pending tag event */ + if (demux->priv->send_tag_event) { + gst_tag_demux_send_tag_event (demux); + demux->priv->send_tag_event = FALSE; + } + + /* Ensure the caps are set correctly */ + outbuf = gst_buffer_make_metadata_writable (outbuf); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (demux->priv->srcpad)); + + GST_LOG_OBJECT (demux, "Pushing buffer %p", outbuf); + + return gst_pad_push (demux->priv->srcpad, outbuf); + } + } + } + return GST_FLOW_OK; + +error: + GST_DEBUG_OBJECT (demux, "error in chain function"); + + return GST_FLOW_ERROR; +} + +static gboolean +gst_tag_demux_sink_event (GstPad * pad, GstEvent * event) +{ + GstTagDemux *demux; + gboolean ret; + + demux = GST_TAG_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + if (demux->priv->srcpad == NULL) { + GST_WARNING_OBJECT (demux, "EOS before we found a type"); + GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); + } + ret = gst_pad_event_default (pad, event); + break; + case GST_EVENT_NEWSEGMENT:{ + gboolean update; + gdouble rate, arate; + GstFormat format; + gint64 start, stop, position; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, + &format, &start, &stop, &position); + + gst_segment_set_newsegment_full (&demux->priv->segment, update, rate, + arate, format, start, stop, position); + demux->priv->newseg_update = update; + demux->priv->need_newseg = TRUE; + gst_event_unref (event); + ret = TRUE; + break; + } + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_FLUSH_START: + ret = gst_pad_event_default (pad, event); + break; + default: + if (demux->priv->need_newseg && GST_EVENT_IS_SERIALIZED (event)) { + /* Cache all events if we have a pending segment, so they don't get + * lost (esp. tag events) */ + GST_INFO_OBJECT (demux, "caching event: %" GST_PTR_FORMAT, event); + GST_OBJECT_LOCK (demux); + demux->priv->pending_events = + g_list_append (demux->priv->pending_events, event); + GST_OBJECT_UNLOCK (demux); + ret = TRUE; + } else { + ret = gst_pad_event_default (pad, event); + } + break; + } + + gst_object_unref (demux); + return ret; +} + +static gboolean +gst_tag_demux_get_upstream_size (GstTagDemux * tagdemux) +{ + GstFormat format; + gint64 len; + + /* Short-cut if we already queried upstream */ + if (tagdemux->priv->upstream_size > 0) + return TRUE; + + format = GST_FORMAT_BYTES; + if (!gst_pad_query_peer_duration (tagdemux->priv->sinkpad, &format, &len) || + len <= 0) { + return FALSE; + } + + tagdemux->priv->upstream_size = len; + return TRUE; +} + +static gboolean +gst_tag_demux_srcpad_event (GstPad * pad, GstEvent * event) +{ + GstTagDemux *tagdemux; + gboolean res = FALSE; + + tagdemux = GST_TAG_DEMUX (gst_pad_get_parent (pad)); + + /* Handle SEEK events, with adjusted byte offsets and sizes. */ + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + gdouble rate; + GstFormat format; + GstSeekType cur_type, stop_type; + GstSeekFlags flags; + gint64 cur, stop; + + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + if (format == GST_FORMAT_BYTES && + tagdemux->priv->state == GST_TAG_DEMUX_STREAMING && + gst_pad_is_linked (tagdemux->priv->sinkpad)) { + GstEvent *upstream; + + switch (cur_type) { + case GST_SEEK_TYPE_SET: + if (cur == -1) + cur = 0; + cur += tagdemux->priv->strip_start; + break; + case GST_SEEK_TYPE_CUR: + break; + case GST_SEEK_TYPE_END: + /* Adjust the seek to be relative to the start of any end tag + * (note: 10 bytes before end is represented by stop=-10) */ + if (cur > 0) + cur = 0; + cur -= tagdemux->priv->strip_end; + break; + case GST_SEEK_TYPE_NONE: + default: + break; + } + switch (stop_type) { + case GST_SEEK_TYPE_SET: + if (stop != -1) { + /* -1 means the end of the file, pass it upstream intact */ + stop += tagdemux->priv->strip_start; + } + break; + case GST_SEEK_TYPE_CUR: + break; + case GST_SEEK_TYPE_END: + /* Adjust the seek to be relative to the start of any end tag + * (note: 10 bytes before end is represented by stop=-10) */ + if (stop > 0) + stop = 0; + stop -= tagdemux->priv->strip_end; + break; + case GST_SEEK_TYPE_NONE: + default: + break; + } + upstream = gst_event_new_seek (rate, format, flags, + cur_type, cur, stop_type, stop); + res = gst_pad_push_event (tagdemux->priv->sinkpad, upstream); + } + break; + } + default: + res = gst_pad_push_event (tagdemux->priv->sinkpad, event); + event = NULL; + break; + } + + gst_object_unref (tagdemux); + if (event) + gst_event_unref (event); + return res; +} + +/* Read and interpret any end tag when activating in pull_range. + * Returns FALSE if pad activation should fail. */ +static gboolean +gst_tag_demux_pull_end_tag (GstTagDemux * demux, GstTagList ** tags) +{ + GstTagDemuxResult parse_ret; + GstTagDemuxClass *klass; + GstFlowReturn flow_ret; + GstTagList *new_tags = NULL; + GstBuffer *buffer = NULL; + gboolean have_tag; + gboolean res = FALSE; + guint64 offset; + guint tagsize; + + klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux)); + + g_assert (klass->identify_tag != NULL); + g_assert (klass->parse_tag != NULL); + + if (klass->min_end_size == 0) { + GST_DEBUG_OBJECT (demux, "Not looking for tag at the end"); + return TRUE; + } + + if (demux->priv->upstream_size < klass->min_end_size) { + GST_DEBUG_OBJECT (demux, "File too small"); + return TRUE; + } + + /* Pull enough to identify the tag and retrieve its total size */ + offset = demux->priv->upstream_size - klass->min_end_size; + + flow_ret = gst_pad_pull_range (demux->priv->sinkpad, offset, + klass->min_end_size, &buffer); + + if (flow_ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "Could not read tag header from end of file, " + "ret = %s", gst_flow_get_name (flow_ret)); + goto done; + } + + if (GST_BUFFER_SIZE (buffer) < klass->min_end_size) { + GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file " + "(required: %u bytes)", GST_BUFFER_SIZE (buffer), klass->min_end_size); + goto done; + } + + have_tag = klass->identify_tag (demux, buffer, FALSE, &tagsize); + + if (!have_tag) { + GST_DEBUG_OBJECT (demux, "Could not find tag at end"); + goto done; + } + + /* Now pull the entire tag */ + do { + guint newsize, saved_size; + + GST_DEBUG_OBJECT (demux, "Identified tag at end, size=%u bytes", tagsize); + + demux->priv->strip_end = tagsize; + + g_assert (tagsize >= klass->min_end_size); + + /* Get buffer that's exactly the requested size */ + if (GST_BUFFER_SIZE (buffer) != tagsize) { + gst_buffer_unref (buffer); + buffer = NULL; + + offset = demux->priv->upstream_size - tagsize; + + flow_ret = gst_pad_pull_range (demux->priv->sinkpad, offset, + tagsize, &buffer); + + if (flow_ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "Could not read data from end of file at " + "offset %" G_GUINT64_FORMAT ". ret = %s", offset, + gst_flow_get_name (flow_ret)); + goto done; + } + + if (GST_BUFFER_SIZE (buffer) < tagsize) { + GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file", + GST_BUFFER_SIZE (buffer)); + goto done; + } + } + + GST_BUFFER_OFFSET (buffer) = offset; + + saved_size = GST_BUFFER_SIZE (buffer); + GST_BUFFER_SIZE (buffer) = tagsize; + newsize = tagsize; + + parse_ret = klass->parse_tag (demux, buffer, FALSE, &newsize, &new_tags); + + GST_BUFFER_SIZE (buffer) = saved_size; + + switch (parse_ret) { + case GST_TAG_DEMUX_RESULT_OK: + res = TRUE; + demux->priv->strip_end = newsize; + GST_DEBUG_OBJECT (demux, "Read tag at end, size %d", + demux->priv->strip_end); + break; + case GST_TAG_DEMUX_RESULT_BROKEN_TAG: + res = TRUE; + demux->priv->strip_end = newsize; + GST_WARNING_OBJECT (demux, "Ignoring broken tag at end, size %d", + demux->priv->strip_end); + break; + case GST_TAG_DEMUX_RESULT_AGAIN: + GST_DEBUG_OBJECT (demux, "Re-parse, this time with %d bytes", newsize); + g_assert (newsize != tagsize); + tagsize = newsize; + break; + } + } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN); + + *tags = new_tags; + new_tags = NULL; + +done: + if (new_tags) + gst_tag_list_free (new_tags); + if (buffer) + gst_buffer_unref (buffer); + return res; +} + +/* Read and interpret any tag at the start when activating in + * pull_range. Returns FALSE if pad activation should fail. */ +static gboolean +gst_tag_demux_pull_start_tag (GstTagDemux * demux, GstTagList ** tags) +{ + GstTagDemuxResult parse_ret; + GstTagDemuxClass *klass; + GstFlowReturn flow_ret; + GstTagList *new_tags = NULL; + GstBuffer *buffer = NULL; + gboolean have_tag; + gboolean res = FALSE; + guint req, tagsize; + + klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux)); + + g_assert (klass->identify_tag != NULL); + g_assert (klass->parse_tag != NULL); + + if (klass->min_start_size == 0) { + GST_DEBUG_OBJECT (demux, "Not looking for tag at the beginning"); + return TRUE; + } + + /* Handle tag at start. Try with 4kB to start with */ + req = MAX (klass->min_start_size, 4096); + + /* Pull enough to identify the tag and retrieve its total size */ + flow_ret = gst_pad_pull_range (demux->priv->sinkpad, 0, req, &buffer); + if (flow_ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "Could not read data from start of file ret=%s", + gst_flow_get_name (flow_ret)); + goto done; + } + + if (GST_BUFFER_SIZE (buffer) < klass->min_start_size) { + GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file - " + "no tag in this file", GST_BUFFER_SIZE (buffer)); + goto done; + } + + have_tag = klass->identify_tag (demux, buffer, TRUE, &tagsize); + + if (!have_tag) { + GST_DEBUG_OBJECT (demux, "Could not find start tag"); + res = TRUE; + goto done; + } + + GST_DEBUG_OBJECT (demux, "Identified start tag, size = %u bytes", tagsize); + + do { + guint newsize, saved_size; + + demux->priv->strip_start = tagsize; + + /* Now pull the entire tag */ + g_assert (tagsize >= klass->min_start_size); + + if (GST_BUFFER_SIZE (buffer) < tagsize) { + gst_buffer_unref (buffer); + buffer = NULL; + + flow_ret = gst_pad_pull_range (demux->priv->sinkpad, 0, tagsize, &buffer); + if (flow_ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "Could not read data from start of file, " + "ret = %s", gst_flow_get_name (flow_ret)); + goto done; + } + + if (GST_BUFFER_SIZE (buffer) < tagsize) { + GST_DEBUG_OBJECT (demux, "Only managed to read %u bytes from file", + GST_BUFFER_SIZE (buffer)); + GST_ELEMENT_ERROR (demux, STREAM, DECODE, + (_("Failed to read tag: not enough data")), (NULL)); + goto done; + } + } + + saved_size = GST_BUFFER_SIZE (buffer); + GST_BUFFER_SIZE (buffer) = tagsize; + newsize = tagsize; + parse_ret = klass->parse_tag (demux, buffer, TRUE, &newsize, &new_tags); + + GST_BUFFER_SIZE (buffer) = saved_size; + + switch (parse_ret) { + case GST_TAG_DEMUX_RESULT_OK: + res = TRUE; + demux->priv->strip_start = newsize; + GST_DEBUG_OBJECT (demux, "Read start tag of size %d", newsize); + break; + case GST_TAG_DEMUX_RESULT_BROKEN_TAG: + res = TRUE; + demux->priv->strip_start = newsize; + GST_WARNING_OBJECT (demux, "Ignoring broken start tag of size %d", + demux->priv->strip_start); + break; + case GST_TAG_DEMUX_RESULT_AGAIN: + GST_DEBUG_OBJECT (demux, "Re-parse, this time with %d bytes", newsize); + g_assert (newsize != tagsize); + tagsize = newsize; + break; + } + } while (parse_ret == GST_TAG_DEMUX_RESULT_AGAIN); + + *tags = new_tags; + new_tags = NULL; + +done: + if (new_tags) + gst_tag_list_free (new_tags); + if (buffer) + gst_buffer_unref (buffer); + return res; +} + +/* This function operates similarly to gst_type_find_element_activate + * in the typefind element + * 1. try to activate in pull mode. if not, switch to push and succeed. + * 2. try to read tags in pull mode + * 3. typefind the contents + * 4. deactivate pull mode. + * 5. if we didn't find any caps, fail. + * 6. Add the srcpad + * 7. if the sink pad is activated, we are in pull mode. succeed. + * otherwise activate both pads in push mode and succeed. + */ +static gboolean +gst_tag_demux_sink_activate (GstPad * sinkpad) +{ + GstTypeFindProbability probability = 0; + GstTagDemuxClass *klass; + GstTagDemux *demux; + GstTagList *start_tags = NULL; + GstTagList *end_tags = NULL; + gboolean e_tag_ok, s_tag_ok; + gboolean ret = FALSE; + GstCaps *caps = NULL; + + demux = GST_TAG_DEMUX (GST_PAD_PARENT (sinkpad)); + klass = GST_TAG_DEMUX_CLASS (G_OBJECT_GET_CLASS (demux)); + + /* 1: */ + /* If we can activate pull_range upstream, then read any end and start + * tags, otherwise activate in push mode and the chain function will + * collect buffers, read the start tag and output a buffer to end + * preroll. + */ + if (!gst_pad_check_pull_range (sinkpad) || + !gst_pad_activate_pull (sinkpad, TRUE)) { + GST_DEBUG_OBJECT (demux, "No pull mode. Changing to push, but won't be " + "able to read end tags"); + demux->priv->state = GST_TAG_DEMUX_READ_START_TAG; + return gst_pad_activate_push (sinkpad, TRUE); + } + + /* Look for tags at start and end of file */ + GST_DEBUG_OBJECT (demux, "Activated pull mode. Looking for tags"); + if (!gst_tag_demux_get_upstream_size (demux)) + return FALSE; + + demux->priv->strip_start = 0; + demux->priv->strip_end = 0; + + s_tag_ok = gst_tag_demux_pull_start_tag (demux, &start_tags); + e_tag_ok = gst_tag_demux_pull_end_tag (demux, &end_tags); + + if (klass->merge_tags != NULL) { + demux->priv->parsed_tags = klass->merge_tags (demux, start_tags, end_tags); + } else { + /* we merge in REPLACE mode, so put the less important tags first, which + * we'll just assume is the end tag (subclasses may change this behaviour + * or make it configurable by overriding the merge_tags vfunc) */ + demux->priv->parsed_tags = + gst_tag_list_merge (end_tags, start_tags, GST_TAG_MERGE_REPLACE); + } + + if (start_tags) + gst_tag_list_free (start_tags); + if (end_tags) + gst_tag_list_free (end_tags); + + if (!e_tag_ok && !s_tag_ok) + return FALSE; + + if (demux->priv->parsed_tags != NULL) { + demux->priv->send_tag_event = TRUE; + } + + if (demux->priv->upstream_size <= + demux->priv->strip_start + demux->priv->strip_end) { + /* There was no data (probably due to a truncated file) */ + GST_DEBUG_OBJECT (demux, "No data in file"); + return FALSE; + } + + /* 3 - Do typefinding on data */ + caps = gst_type_find_helper_get_range (GST_OBJECT (demux), + (GstTypeFindHelperGetRangeFunction) gst_tag_demux_read_range, + demux->priv->upstream_size + - (demux->priv->strip_start + demux->priv->strip_end), &probability); + + GST_DEBUG_OBJECT (demux, "Found type %" GST_PTR_FORMAT " with a " + "probability of %u", caps, probability); + + /* 4 - Deactivate pull mode */ + if (!gst_pad_activate_pull (sinkpad, FALSE)) { + if (caps) + gst_caps_unref (caps); + GST_DEBUG_OBJECT (demux, "Could not deactivate sinkpad after reading tags"); + return FALSE; + } + + /* 5 - If we didn't find the caps, fail */ + if (caps == NULL) { + GST_DEBUG_OBJECT (demux, "Could not detect type of contents"); + GST_ELEMENT_ERROR (demux, STREAM, TYPE_NOT_FOUND, (NULL), (NULL)); + goto done_activate; + } + + /* tag reading and typefinding were already done, don't do them again in + * the chain function if we end up in push mode */ + demux->priv->state = GST_TAG_DEMUX_STREAMING; + + /* 6 Add the srcpad for output now we know caps. */ + if (!gst_tag_demux_add_srcpad (demux, caps)) { + GST_DEBUG_OBJECT (demux, "Could not add source pad"); + goto done_activate; + } + + /* 7 - if the sinkpad is active, it was done by downstream so we're + * done, otherwise switch to push */ + ret = TRUE; + if (!gst_pad_is_active (sinkpad)) { + ret = gst_pad_activate_push (demux->priv->srcpad, TRUE); + ret &= gst_pad_activate_push (sinkpad, TRUE); + } + +done_activate: + + if (caps) + gst_caps_unref (caps); + + return ret; +} + +static gboolean +gst_tag_demux_src_activate_pull (GstPad * pad, gboolean active) +{ + GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad)); + + return gst_pad_activate_pull (demux->priv->sinkpad, active); +} + +static gboolean +gst_tag_demux_src_checkgetrange (GstPad * srcpad) +{ + GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (srcpad)); + + return gst_pad_check_pull_range (demux->priv->sinkpad); +} + +static GstFlowReturn +gst_tag_demux_read_range (GstTagDemux * demux, + guint64 offset, guint length, GstBuffer ** buffer) +{ + GstFlowReturn ret; + guint64 in_offset; + guint in_length; + + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* Adjust offset and length of the request to trim off tag information. + * For the returned buffer, adjust the output offset to match what downstream + * should see */ + in_offset = offset + demux->priv->strip_start; + + if (!gst_tag_demux_get_upstream_size (demux)) + return GST_FLOW_ERROR; + + if (in_offset + length >= demux->priv->upstream_size - demux->priv->strip_end) { + if (in_offset + demux->priv->strip_end >= demux->priv->upstream_size) + return GST_FLOW_UNEXPECTED; + in_length = demux->priv->upstream_size - demux->priv->strip_end - in_offset; + } else { + in_length = length; + } + + ret = gst_pad_pull_range (demux->priv->sinkpad, in_offset, in_length, buffer); + + if (ret == GST_FLOW_OK && *buffer) { + if (!gst_tag_demux_trim_buffer (demux, buffer)) + goto read_beyond_end; + + /* this should only happen in streaming mode */ + g_assert (*buffer != NULL); + + gst_buffer_set_caps (*buffer, demux->priv->src_caps); + } + + return ret; + +read_beyond_end: + { + GST_DEBUG_OBJECT (demux, "attempted read beyond end of file"); + if (*buffer != NULL) { + gst_buffer_unref (*buffer); + *buffer = NULL; + } + return GST_FLOW_UNEXPECTED; + } +} + +static GstFlowReturn +gst_tag_demux_src_getrange (GstPad * srcpad, + guint64 offset, guint length, GstBuffer ** buffer) +{ + GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (srcpad)); + + /* downstream in pull mode won't miss a newsegment event, + * but it likely appreciates other (tag) events */ + if (demux->priv->need_newseg) { + gst_tag_demux_send_pending_events (demux); + demux->priv->need_newseg = FALSE; + } + + if (demux->priv->send_tag_event) { + gst_tag_demux_send_tag_event (demux); + demux->priv->send_tag_event = FALSE; + } + + return gst_tag_demux_read_range (demux, offset, length, buffer); +} + +static GstStateChangeReturn +gst_tag_demux_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstTagDemux *demux = GST_TAG_DEMUX (element); + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_tag_demux_reset (demux); + break; + default: + break; + } + return ret; +} + +static gboolean +gst_tag_demux_pad_query (GstPad * pad, GstQuery * query) +{ + /* For a position or duration query, adjust the returned + * bytes to strip off the end and start areas */ + + GstTagDemux *demux = GST_TAG_DEMUX (GST_PAD_PARENT (pad)); + GstPad *peer = NULL; + GstFormat format; + gint64 result; + + if ((peer = gst_pad_get_peer (demux->priv->sinkpad)) == NULL) + return FALSE; + + if (!gst_pad_query (peer, query)) { + gst_object_unref (peer); + return FALSE; + } + + gst_object_unref (peer); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gst_query_parse_position (query, &format, &result); + if (format == GST_FORMAT_BYTES) { + result -= demux->priv->strip_start; + gst_query_set_position (query, format, result); + } + break; + } + case GST_QUERY_DURATION: + { + gst_query_parse_duration (query, &format, &result); + if (format == GST_FORMAT_BYTES) { + result -= demux->priv->strip_start + demux->priv->strip_end; + gst_query_set_duration (query, format, result); + } + break; + } + default: + break; + } + + return TRUE; +} + +static const GstQueryType * +gst_tag_demux_get_query_types (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + 0 + }; + + return types; +} + +static void +gst_tag_demux_send_pending_events (GstTagDemux * demux) +{ + GList *events; + + /* send any pending events we cached */ + GST_OBJECT_LOCK (demux); + events = demux->priv->pending_events; + demux->priv->pending_events = NULL; + GST_OBJECT_UNLOCK (demux); + + while (events != NULL) { + GST_DEBUG_OBJECT (demux->priv->srcpad, "sending cached %s event: %" + GST_PTR_FORMAT, GST_EVENT_TYPE_NAME (events->data), events->data); + gst_pad_push_event (demux->priv->srcpad, GST_EVENT (events->data)); + events = g_list_delete_link (events, events); + } +} + +static void +gst_tag_demux_send_tag_event (GstTagDemux * demux) +{ + /* FIXME: what's the correct merge mode? Docs need to tell... */ + GstTagList *merged = gst_tag_list_merge (demux->priv->event_tags, + demux->priv->parsed_tags, GST_TAG_MERGE_KEEP); + + if (demux->priv->parsed_tags) + gst_element_post_message (GST_ELEMENT (demux), + gst_message_new_tag (GST_OBJECT (demux), + gst_tag_list_copy (demux->priv->parsed_tags))); + + if (merged) { + GstEvent *event = gst_event_new_tag (merged); + + GST_EVENT_TIMESTAMP (event) = 0; + GST_DEBUG_OBJECT (demux, "Sending tag event on src pad"); + gst_pad_push_event (demux->priv->srcpad, event); + } +} + +static gboolean +gst_tag_demux_send_new_segment (GstTagDemux * tagdemux) +{ + GstEvent *event; + gint64 start, stop, position; + GstSegment *seg = &tagdemux->priv->segment; + + if (seg->format == GST_FORMAT_UNDEFINED) { + GST_LOG_OBJECT (tagdemux, + "No new segment received before first buffer. Using default"); + gst_segment_set_newsegment (seg, FALSE, 1.0, + GST_FORMAT_BYTES, tagdemux->priv->strip_start, -1, + tagdemux->priv->strip_start); + } + + /* Can't adjust segments in non-BYTES formats */ + if (tagdemux->priv->segment.format != GST_FORMAT_BYTES) { + event = gst_event_new_new_segment_full (tagdemux->priv->newseg_update, + seg->rate, seg->applied_rate, seg->format, seg->start, + seg->stop, seg->time); + return gst_pad_push_event (tagdemux->priv->srcpad, event); + } + + start = seg->start; + stop = seg->stop; + position = seg->time; + + g_return_val_if_fail (start != -1, FALSE); + g_return_val_if_fail (position != -1, FALSE); + + if (tagdemux->priv->strip_end > 0) { + if (gst_tag_demux_get_upstream_size (tagdemux)) { + guint64 v1tag_offset = + tagdemux->priv->upstream_size - tagdemux->priv->strip_end; + + if (start >= v1tag_offset) { + /* Segment is completely within the end tag, output an open-ended + * segment, even though all the buffers will get trimmed away */ + start = v1tag_offset; + stop = -1; + } + + if (stop != -1 && stop >= v1tag_offset) { + GST_DEBUG_OBJECT (tagdemux, + "Segment crosses the end tag. Trimming end"); + stop = v1tag_offset; + } + } + } + + if (tagdemux->priv->strip_start > 0) { + if (start > tagdemux->priv->strip_start) + start -= tagdemux->priv->strip_start; + else + start = 0; + + if (position > tagdemux->priv->strip_start) + position -= tagdemux->priv->strip_start; + else + position = 0; + + if (stop != -1) { + if (stop > tagdemux->priv->strip_start) + stop -= tagdemux->priv->strip_start; + else + stop = 0; + } + } + + GST_DEBUG_OBJECT (tagdemux, + "Sending new segment update %d, rate %g, format %d, " + "start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %" + G_GINT64_FORMAT, tagdemux->priv->newseg_update, seg->rate, seg->format, + start, stop, position); + + event = gst_event_new_new_segment_full (tagdemux->priv->newseg_update, + seg->rate, seg->applied_rate, seg->format, start, stop, position); + return gst_pad_push_event (tagdemux->priv->srcpad, event); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.h new file mode 100644 index 0000000..1fbff90 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttagdemux.h @@ -0,0 +1,144 @@ +/* GStreamer Base Class for Tag Demuxing + * Copyright (C) 2005 Jan Schmidt + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TAG_DEMUX_H__ +#define __GST_TAG_DEMUX_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TAG_DEMUX (gst_tag_demux_get_type()) +#define GST_TAG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_DEMUX,GstTagDemux)) +#define GST_TAG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_DEMUX,GstTagDemuxClass)) +#define GST_IS_TAG_DEMUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_DEMUX)) +#define GST_IS_TAG_DEMUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_DEMUX)) + +typedef struct _GstTagDemux GstTagDemux; +typedef struct _GstTagDemuxClass GstTagDemuxClass; +typedef struct _GstTagDemuxPrivate GstTagDemuxPrivate; + +/** + * GstTagDemuxResult: + * @GST_TAG_DEMUX_RESULT_BROKEN_TAG: cannot parse tag, just skip it + * @GST_TAG_DEMUX_RESULT_AGAIN : call again with less or more data + * @GST_TAG_DEMUX_RESULT_OK : parsed tag successfully + * + * Result values from the parse_tag virtual function. + * + * Since: 0.10.15 + */ +typedef enum { + GST_TAG_DEMUX_RESULT_BROKEN_TAG, + GST_TAG_DEMUX_RESULT_AGAIN, + GST_TAG_DEMUX_RESULT_OK +} GstTagDemuxResult; + +GType gst_tag_demux_result_get_type (void); +#define GST_TYPE_TAG_DEMUX_RESULT (gst_tag_demux_result_get_type()) + +/** + * GstTagDemux: + * @element: parent element + * + * Opaque #GstTagDemux structure. + * + * Since: 0.10.15 + */ +struct _GstTagDemux +{ + GstElement element; + + /*< private >*/ + GstTagDemuxPrivate *priv; + + gpointer reserved[GST_PADDING]; +}; + +/** + * GstTagDemuxClass: + * @parent_class: the parent class. + * @min_start_size: minimum size required to identify a tag at the start and + * determine its total size. Set to 0 if not interested in start tags. + * Subclasses should set this in their class_init function. + * @min_end_size: minimum size required to identify a tag at the end and + * determine its total size. Set to 0 if not interested in end tags. + * Subclasses should set this in their class_init function. + * @identify_tag: identify tag and determine the size required to parse the + * tag. Buffer may be larger than the specified minimum size. + * Subclassed MUST override this vfunc in their class_init function. + * @parse_tag: parse the tag. Buffer will be exactly of the size determined by + * the identify_tag vfunc before. The parse_tag vfunc may change the size + * stored in *tag_size and return GST_TAG_DEMUX_RESULT_AGAIN to request a + * larger or smaller buffer. It is also permitted to adjust the tag_size to a + * smaller value and then return GST_TAG_DEMUX_RESULT_OK in one go. + * Subclassed MUST override the parse_tag vfunc in their class_init function. + * @merge_tags: merge start and end tags. Subclasses may want to override this + * vfunc to allow prioritising of start or end tag according to user + * preference. Note that both start_tags and end_tags may be NULL. By default + * start tags are prefered over end tags. + * + * The #GstTagDemuxClass structure. See documentation at beginning of section + * for details about what subclasses need to override and do. + * + * Since: 0.10.15 + */ +struct _GstTagDemuxClass +{ + GstElementClass parent_class; + + /* minimum size required to identify a tag at the start and determine + * its total size */ + guint min_start_size; + + /* minimum size required to identify a tag at the end and determine + * its total size */ + guint min_end_size; + + /* vtable */ + + /* identify tag and determine the size required to parse the tag */ + gboolean (*identify_tag) (GstTagDemux * demux, + GstBuffer * buffer, + gboolean start_tag, + guint * tag_size); + + /* parse the tag once it is identified and its size is known */ + GstTagDemuxResult (*parse_tag) (GstTagDemux * demux, + GstBuffer * buffer, + gboolean start_tag, + guint * tag_size, + GstTagList ** tags); + + /* merge start and end tags (optional) */ + GstTagList * (*merge_tags) (GstTagDemux * demux, + const GstTagList * start_tags, + const GstTagList * end_tags); + + /*< private >*/ + gpointer reserved[GST_PADDING]; +}; + +GType gst_tag_demux_get_type (void); + +G_END_DECLS + +#endif /* __GST_TAG_DEMUX_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.c new file mode 100644 index 0000000..0626874 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.c @@ -0,0 +1,468 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gsttageditingprivate.h" + +#include + +gint +__exif_tag_image_orientation_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "rotate-0") == 0) + return 1; + else if (strcmp (str, "flip-rotate-0") == 0) + return 2; + else if (strcmp (str, "rotate-180") == 0) + return 3; + else if (strcmp (str, "flip-rotate-180") == 0) + return 4; + else if (strcmp (str, "flip-rotate-270") == 0) + return 5; + else if (strcmp (str, "rotate-90") == 0) + return 6; + else if (strcmp (str, "flip-rotate-90") == 0) + return 7; + else if (strcmp (str, "rotate-270") == 0) + return 8; + +end: + GST_WARNING ("Invalid image orientation tag: %s", str); + return -1; +} + +const gchar * +__exif_tag_image_orientation_from_exif_value (gint value) +{ + switch (value) { + case 1: + return "rotate-0"; + case 2: + return "flip-rotate-0"; + case 3: + return "rotate-180"; + case 4: + return "flip-rotate-180"; + case 5: + return "flip-rotate-270"; + case 6: + return "rotate-90"; + case 7: + return "flip-rotate-90"; + case 8: + return "rotate-270"; + default: + GST_WARNING ("Invalid tiff orientation tag value: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_exposure_program_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "undefined") == 0) + return 0; + else if (strcmp (str, "manual") == 0) + return 1; + else if (strcmp (str, "normal") == 0) + return 2; + else if (strcmp (str, "aperture-priority") == 0) + return 3; + else if (strcmp (str, "shutter-priority") == 0) + return 4; + else if (strcmp (str, "creative") == 0) + return 5; + else if (strcmp (str, "action") == 0) + return 6; + else if (strcmp (str, "portrait") == 0) + return 7; + else if (strcmp (str, "landscape") == 0) + return 8; + +end: + GST_WARNING ("Invalid capturing exposure program tag: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_exposure_program_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "undefined"; + case 1: + return "manual"; + case 2: + return "normal"; + case 3: + return "aperture-priority"; + case 4: + return "shutter-priority"; + case 5: + return "creative"; + case 6: + return "action"; + case 7: + return "portrait"; + case 8: + return "landscape"; + default: + GST_WARNING ("Invalid exif exposure program: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_exposure_mode_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "auto-exposure") == 0) + return 0; + else if (strcmp (str, "manual-exposure") == 0) + return 1; + else if (strcmp (str, "auto-bracket") == 0) + return 2; + +end: + GST_WARNING ("Invalid capturing exposure mode tag: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_exposure_mode_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "auto-exposure"; + case 1: + return "manual-exposure"; + case 2: + return "auto-bracket"; + default: + GST_WARNING ("Invalid exif exposure mode: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_scene_capture_type_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "standard") == 0) + return 0; + else if (strcmp (str, "landscape") == 0) + return 1; + else if (strcmp (str, "portrait") == 0) + return 2; + else if (strcmp (str, "night-scene") == 0) + return 3; + +end: + GST_WARNING ("Invalid capturing scene capture type: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_scene_capture_type_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "standard"; + case 1: + return "landscape"; + case 2: + return "portrait"; + case 3: + return "night-scene"; + default: + GST_WARNING ("Invalid exif scene capture type: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_gain_adjustment_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "none") == 0) + return 0; + else if (strcmp (str, "low-gain-up") == 0) + return 1; + else if (strcmp (str, "high-gain-up") == 0) + return 2; + else if (strcmp (str, "low-gain-down") == 0) + return 3; + else if (strcmp (str, "high-gain-down") == 0) + return 4; + +end: + GST_WARNING ("Invalid capturing gain adjustment type: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_gain_adjustment_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "none"; + case 1: + return "low-gain-up"; + case 2: + return "high-gain-up"; + case 3: + return "low-gain-down"; + case 4: + return "high-gain-down"; + default: + GST_WARNING ("Invalid exif gain control type: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_white_balance_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "auto") == 0) + return 0; + else /* everything else is just manual */ + return 1; + +end: + GST_WARNING ("Invalid white balance: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_white_balance_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "auto"; + case 1: + return "manual"; + default: + GST_WARNING ("Invalid white balance type: %d", value); + return NULL; + } +} + +static gint +__exif_tag_capturing_contrast_sharpness_to_exif_value (const gchar * str, + const gchar * tag_name) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "normal") == 0) + return 0; + else if (strcmp (str, "soft") == 0) + return 1; + else if (strcmp (str, "hard") == 0) + return 2; + +end: + GST_WARNING ("Invalid %s type: %s", tag_name, str); + return -1; +} + +static const gchar * +__exif_tag_capturing_contrast_sharpness_from_exif_value (gint value, + const gchar * tag_name) +{ + switch (value) { + case 0: + return "normal"; + case 1: + return "soft"; + case 2: + return "hard"; + default: + GST_WARNING ("Invalid %s type: %d", tag_name, value); + return NULL; + } +} + +gint +__exif_tag_capturing_contrast_to_exif_value (const gchar * str) +{ + return __exif_tag_capturing_contrast_sharpness_to_exif_value (str, + "contrast"); +} + +const gchar * +__exif_tag_capturing_contrast_from_exif_value (gint value) +{ + return __exif_tag_capturing_contrast_sharpness_from_exif_value (value, + "contrast"); +} + +gint +__exif_tag_capturing_saturation_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "normal") == 0) + return 0; + else if (strcmp (str, "low-saturation") == 0) + return 1; + else if (strcmp (str, "high-saturation") == 0) + return 2; + +end: + GST_WARNING ("Invalid saturation type: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_saturation_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "normal"; + case 1: + return "low-saturation"; + case 2: + return "high-saturation"; + default: + GST_WARNING ("Invalid saturation type: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_sharpness_to_exif_value (const gchar * str) +{ + return __exif_tag_capturing_contrast_sharpness_to_exif_value (str, + "sharpness"); +} + +const gchar * +__exif_tag_capturing_sharpness_from_exif_value (gint value) +{ + return __exif_tag_capturing_contrast_sharpness_from_exif_value (value, + "sharpness"); +} + +gint +__exif_tag_capturing_metering_mode_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "unknown") == 0) + return 0; + else if (strcmp (str, "average") == 0) + return 1; + else if (strcmp (str, "center-weighted-average") == 0) + return 2; + else if (strcmp (str, "spot") == 0) + return 3; + else if (strcmp (str, "multi-spot") == 0) + return 4; + else if (strcmp (str, "pattern") == 0) + return 5; + else if (strcmp (str, "partial") == 0) + return 6; + else if (strcmp (str, "other") == 0) + return 255; + +end: + GST_WARNING ("Invalid metering mode type: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_metering_mode_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "unknown"; + case 1: + return "average"; + case 2: + return "center-weighted-average"; + case 3: + return "spot"; + case 4: + return "multi-spot"; + case 5: + return "pattern"; + case 6: + return "partial"; + case 255: + return "other"; + default: + GST_WARNING ("Invalid metering mode type: %d", value); + return NULL; + } +} + +gint +__exif_tag_capturing_source_to_exif_value (const gchar * str) +{ + if (str == NULL) + goto end; + + if (strcmp (str, "dsc") == 0) + return 3; + else if (strcmp (str, "other") == 0) + return 0; + else if (strcmp (str, "transparent-scanner") == 0) + return 1; + else if (strcmp (str, "reflex-scanner") == 0) + return 2; + +end: + GST_WARNING ("Invalid capturing source type: %s", str); + return -1; +} + +const gchar * +__exif_tag_capturing_source_from_exif_value (gint value) +{ + switch (value) { + case 0: + return "other"; + case 1: + return "transparent-scanner"; + case 2: + return "reflex-scanner"; + case 3: + return "dsc"; + default: + GST_WARNING ("Invalid capturing source type: %d", value); + return NULL; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.h new file mode 100644 index 0000000..0cc70d0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gsttageditingprivate.h @@ -0,0 +1,75 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TAG_EDIT_PRIVATE_H__ +#define __GST_TAG_EDIT_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + + +typedef struct _GstTagEntryMatch GstTagEntryMatch; +struct _GstTagEntryMatch { + const gchar * gstreamer_tag; + const gchar * original_tag; +}; + + +GType gst_vorbis_tag_get_type (void); + +gint __exif_tag_image_orientation_to_exif_value (const gchar * str); +const gchar * __exif_tag_image_orientation_from_exif_value (gint value); + +gint __exif_tag_capturing_exposure_program_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_exposure_program_from_exif_value (gint value); + +gint __exif_tag_capturing_exposure_mode_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_exposure_mode_from_exif_value (gint value); + +gint __exif_tag_capturing_scene_capture_type_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_scene_capture_type_from_exif_value (gint value); + +gint __exif_tag_capturing_gain_adjustment_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_gain_adjustment_from_exif_value (gint value); + +gint __exif_tag_capturing_white_balance_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_white_balance_from_exif_value (gint value); + +gint __exif_tag_capturing_contrast_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_contrast_from_exif_value (gint value); + +gint __exif_tag_capturing_saturation_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_saturation_from_exif_value (gint value); + +gint __exif_tag_capturing_sharpness_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_sharpness_from_exif_value (gint value); + +gint __exif_tag_capturing_metering_mode_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_metering_mode_from_exif_value (gint value); + +gint __exif_tag_capturing_source_to_exif_value (const gchar * str); +const gchar * __exif_tag_capturing_source_from_exif_value (gint value); + +#define ensure_exif_tags gst_tag_register_musicbrainz_tags + +G_END_DECLS + +#endif /* __GST_TAG_EDIT_PRIVATE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstvorbistag.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstvorbistag.c new file mode 100644 index 0000000..400118b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstvorbistag.c @@ -0,0 +1,793 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * gstvorbistag.c: library for reading / modifying vorbis tags + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttagvorbis + * @short_description: tag mappings and support functions for plugins + * dealing with vorbiscomments + * @see_also: #GstTagList + * + * + * + * Contains various utility functions for plugins to parse or create + * vorbiscomments and map them to and from #GstTagLists. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include "gsttageditingprivate.h" +#include +#include + +/* + * see http://xiph.org/ogg/vorbis/doc/v-comment.html + */ +static const GstTagEntryMatch tag_matches[] = { + {GST_TAG_TITLE, "TITLE"}, + {GST_TAG_VERSION, "VERSION"}, + {GST_TAG_ALBUM, "ALBUM"}, + {GST_TAG_TRACK_NUMBER, "TRACKNUMBER"}, + {GST_TAG_ALBUM_VOLUME_NUMBER, "DISCNUMBER"}, + {GST_TAG_TRACK_COUNT, "TRACKTOTAL"}, + {GST_TAG_ALBUM_VOLUME_COUNT, "DISCTOTAL"}, + {GST_TAG_ARTIST, "ARTIST"}, + {GST_TAG_PERFORMER, "PERFORMER"}, + {GST_TAG_COMPOSER, "COMPOSER"}, + {GST_TAG_COPYRIGHT, "COPYRIGHT"}, + {GST_TAG_LICENSE, "LICENSE"}, + {GST_TAG_LICENSE_URI, "LICENSE"}, + {GST_TAG_GEO_LOCATION_NAME, "LOCATION"}, + {GST_TAG_ORGANIZATION, "ORGANIZATION"}, + {GST_TAG_DESCRIPTION, "DESCRIPTION"}, + {GST_TAG_GENRE, "GENRE"}, + {GST_TAG_DATE, "DATE"}, + {GST_TAG_CONTACT, "CONTACT"}, + {GST_TAG_ISRC, "ISRC"}, + {GST_TAG_COMMENT, "COMMENT"}, + {GST_TAG_TRACK_GAIN, "REPLAYGAIN_TRACK_GAIN"}, + {GST_TAG_TRACK_PEAK, "REPLAYGAIN_TRACK_PEAK"}, + {GST_TAG_ALBUM_GAIN, "REPLAYGAIN_ALBUM_GAIN"}, + {GST_TAG_ALBUM_PEAK, "REPLAYGAIN_ALBUM_PEAK"}, + {GST_TAG_REFERENCE_LEVEL, "REPLAYGAIN_REFERENCE_LOUDNESS"}, + {GST_TAG_MUSICBRAINZ_TRACKID, "MUSICBRAINZ_TRACKID"}, + {GST_TAG_MUSICBRAINZ_ARTISTID, "MUSICBRAINZ_ARTISTID"}, + {GST_TAG_MUSICBRAINZ_ALBUMID, "MUSICBRAINZ_ALBUMID"}, + {GST_TAG_MUSICBRAINZ_ALBUMARTISTID, "MUSICBRAINZ_ALBUMARTISTID"}, + {GST_TAG_MUSICBRAINZ_TRMID, "MUSICBRAINZ_TRMID"}, + {GST_TAG_ARTIST_SORTNAME, "ARTISTSORT"}, + {GST_TAG_ARTIST_SORTNAME, "ARTISTSORTORDER"}, + {GST_TAG_ARTIST_SORTNAME, "MUSICBRAINZ_SORTNAME"}, + {GST_TAG_ALBUM_SORTNAME, "ALBUMSORT"}, + {GST_TAG_ALBUM_SORTNAME, "ALBUMSORTORDER"}, + {GST_TAG_TITLE_SORTNAME, "TITLESORT"}, + {GST_TAG_TITLE_SORTNAME, "TITLESORTORDER"}, + {GST_TAG_ALBUM_ARTIST, "ALBUMARTIST"}, + {GST_TAG_ALBUM_ARTIST_SORTNAME, "ALBUMARTISTSORT"}, + {GST_TAG_ALBUM_ARTIST_SORTNAME, "ALBUMARTISTSORTORDER"}, + {GST_TAG_LANGUAGE_CODE, "LANGUAGE"}, + {GST_TAG_CDDA_MUSICBRAINZ_DISCID, "MUSICBRAINZ_DISCID"}, + {GST_TAG_CDDA_CDDB_DISCID, "DISCID"}, + /* For the apparent de-facto standard for coverart in vorbis comments, see: + * http://www.hydrogenaudio.org/forums/lofiversion/index.php/t48386.html */ + {GST_TAG_PREVIEW_IMAGE, "COVERART"}, + /* some evidence that "BPM" is used elsewhere: + * http://mail.kde.org/pipermail/amarok/2006-May/000090.html + */ + {GST_TAG_BEATS_PER_MINUTE, "BPM"}, + {NULL, NULL} +}; + +/** + * gst_tag_from_vorbis_tag: + * @vorbis_tag: vorbiscomment tag to convert to GStreamer tag + * + * Looks up the GStreamer tag for a vorbiscomment tag. + * + * Returns: The corresponding GStreamer tag or NULL if none exists. + */ +G_CONST_RETURN gchar * +gst_tag_from_vorbis_tag (const gchar * vorbis_tag) +{ + int i = 0; + gchar *real_vorbis_tag; + + g_return_val_if_fail (vorbis_tag != NULL, NULL); + + gst_tag_register_musicbrainz_tags (); + + real_vorbis_tag = g_ascii_strup (vorbis_tag, -1); + while (tag_matches[i].gstreamer_tag != NULL) { + if (strcmp (real_vorbis_tag, tag_matches[i].original_tag) == 0) { + break; + } + i++; + } + g_free (real_vorbis_tag); + return tag_matches[i].gstreamer_tag; +} + +/** + * gst_tag_to_vorbis_tag: + * @gst_tag: GStreamer tag to convert to vorbiscomment tag + * + * Looks up the vorbiscomment tag for a GStreamer tag. + * + * Returns: The corresponding vorbiscomment tag or NULL if none exists. + */ +G_CONST_RETURN gchar * +gst_tag_to_vorbis_tag (const gchar * gst_tag) +{ + int i = 0; + + g_return_val_if_fail (gst_tag != NULL, NULL); + + gst_tag_register_musicbrainz_tags (); + + while (tag_matches[i].gstreamer_tag != NULL) { + if (strcmp (gst_tag, tag_matches[i].gstreamer_tag) == 0) { + return tag_matches[i].original_tag; + } + i++; + } + return NULL; +} + + +/** + * gst_vorbis_tag_add: + * @list: a #GstTagList + * @tag: a vorbiscomment tag string (key in key=value), must be valid UTF-8 + * @value: a vorbiscomment value string (value in key=value), must be valid UTF-8 + * + * Convenience function using gst_tag_from_vorbis_tag(), parsing + * a vorbis comment string into the right type and adding it to the + * given taglist @list. + * + * Unknown vorbiscomment tags will be added to the tag list in form + * of a #GST_TAG_EXTENDED_COMMENT (since 0.10.10 at least). + */ +void +gst_vorbis_tag_add (GstTagList * list, const gchar * tag, const gchar * value) +{ + const gchar *gst_tag; + GType tag_type; + + g_return_if_fail (list != NULL); + g_return_if_fail (tag != NULL); + g_return_if_fail (value != NULL); + + g_return_if_fail (g_utf8_validate (tag, -1, NULL)); + g_return_if_fail (g_utf8_validate (value, -1, NULL)); + g_return_if_fail (strchr (tag, '=') == NULL); + + gst_tag = gst_tag_from_vorbis_tag (tag); + if (gst_tag == NULL) { + gchar *ext_comment; + + ext_comment = g_strdup_printf ("%s=%s", tag, value); + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_EXTENDED_COMMENT, + ext_comment, NULL); + g_free (ext_comment); + return; + } + + tag_type = gst_tag_get_type (gst_tag); + switch (tag_type) { + case G_TYPE_UINT:{ + guint tmp; + gchar *check; + gboolean is_track_number_tag; + gboolean is_disc_number_tag; + + is_track_number_tag = (strcmp (gst_tag, GST_TAG_TRACK_NUMBER) == 0); + is_disc_number_tag = (strcmp (gst_tag, GST_TAG_ALBUM_VOLUME_NUMBER) == 0); + tmp = strtoul (value, &check, 10); + if (*check == '/' && (is_track_number_tag || is_disc_number_tag)) { + guint count; + + check++; + count = strtoul (check, &check, 10); + if (*check != '\0' || count == 0) + break; + if (is_track_number_tag) { + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, GST_TAG_TRACK_COUNT, + count, NULL); + } else { + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, + GST_TAG_ALBUM_VOLUME_COUNT, count, NULL); + } + } + if (*check == '\0') { + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag, tmp, NULL); + } + break; + } + case G_TYPE_STRING:{ + gchar *valid = NULL; + + /* specialcase for language code */ + if (strcmp (tag, "LANGUAGE") == 0) { + const gchar *s = strchr (value, '['); + + /* Accept both ISO-639-1 and ISO-639-2 codes */ + if (s && strchr (s, ']') == s + 4) { + valid = g_strndup (s + 1, 3); + } else if (s && strchr (s, ']') == s + 3) { + valid = g_strndup (s + 1, 2); + } else if (strlen (value) != 2 && strlen (value) != 3) { + GST_WARNING ("doesn't contain an ISO-639 language code: %s", value); + } + } else if (strcmp (tag, "LICENSE") == 0) { + /* license tags in vorbis comments must contain an URI representing + * the license and nothing more, at least according to: + * http://wiki.xiph.org/index.php/LICENSE_and_COPYRIGHT_tags_on_Vorbis_Comments */ + if (value && gst_uri_is_valid (value)) + gst_tag = GST_TAG_LICENSE_URI; + } + + if (!valid) { + valid = g_strdup (value); + } + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag, valid, NULL); + g_free (valid); + break; + } + case G_TYPE_DOUBLE:{ + gchar *c; + + c = g_strdup (value); + g_strdelimit (c, ",", '.'); + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag, + g_strtod (c, NULL), NULL); + g_free (c); + break; + } + default:{ + if (tag_type == GST_TYPE_DATE) { + guint y, d = 1, m = 1; + gchar *check = (gchar *) value; + + y = strtoul (check, &check, 10); + if (*check == '-') { + check++; + m = strtoul (check, &check, 10); + if (*check == '-') { + check++; + d = strtoul (check, &check, 10); + } + } + + /* accept dates like 2007-00-00 and 2007-05-00 */ + if (y != 0) { + if (m == 0 && d == 0) + m = d = 1; + else if (m != 0 && d == 0) + d = 1; + } + + /* date might be followed by a time */ + if ((*check == '\0' || g_ascii_isspace (*check)) && y != 0 && + g_date_valid_dmy (d, m, y)) { + GDate *date; + + date = g_date_new_dmy (d, m, y); + gst_tag_list_add (list, GST_TAG_MERGE_APPEND, gst_tag, date, NULL); + g_date_free (date); + } else { + GST_DEBUG ("skipping invalid date '%s' (%u,%u,%u)", value, y, m, d); + } + } else { + GST_WARNING ("Unhandled tag of type '%s' (%d)", + g_type_name (tag_type), (gint) tag_type); + } + break; + } + } +} + +static void +gst_vorbis_tag_add_coverart (GstTagList * tags, gchar * img_data_base64, + gint base64_len) +{ + GstBuffer *img; + gsize img_len; + + if (base64_len < 2) + goto not_enough_data; + + /* img_data_base64 points to a temporary copy of the base64 encoded data, so + * it's safe to do inpace decoding here + */ + g_base64_decode_inplace (img_data_base64, &img_len); + if (img_len == 0) + goto decode_failed; + + img = + gst_tag_image_data_to_image_buffer ((const guint8 *) img_data_base64, + img_len, GST_TAG_IMAGE_TYPE_NONE); + + if (img == NULL) + goto convert_failed; + + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, + GST_TAG_PREVIEW_IMAGE, img, NULL); + + gst_buffer_unref (img); + return; + +/* ERRORS */ +not_enough_data: + { + GST_WARNING ("COVERART tag with too little base64-encoded data"); + return; + } +decode_failed: + { + GST_WARNING ("Couldn't decode base64 image data from COVERART tag"); + return; + } +convert_failed: + { + GST_WARNING ("Couldn't extract image or image type from COVERART tag"); + return; + } +} + +/* Standardized way of adding pictures to vorbiscomments: + * http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE + */ +static void +gst_vorbis_tag_add_metadata_block_picture (GstTagList * tags, + gchar * value, gint value_len) +{ + GstByteReader reader; + guint32 img_len = 0, img_type = 0; + guint32 img_mimetype_len = 0, img_description_len = 0; + gsize decoded_len; + const guint8 *data = NULL; + + /* img_data_base64 points to a temporary copy of the base64 encoded data, so + * it's safe to do inpace decoding here + */ + g_base64_decode_inplace (value, &decoded_len); + if (decoded_len == 0) + goto decode_failed; + + gst_byte_reader_init (&reader, (guint8 *) value, decoded_len); + + 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; + + /* Skip width, height, color depth and number of colors for + * indexed formats */ + if (!gst_byte_reader_skip (&reader, 4 * 4)) + goto error; + + if (!gst_byte_reader_get_uint32_be (&reader, &img_len)) + goto error; + + if (!gst_byte_reader_get_data (&reader, img_len, &data)) + goto error; + + gst_tag_list_add_id3_image (tags, data, img_len, img_type); + + return; + +error: + GST_WARNING + ("Couldn't extract image or image type from METADATA_BLOCK_PICTURE tag"); + return; +decode_failed: + GST_WARNING ("Failed to decode Base64 data from METADATA_BLOCK_PICTURE tag"); + return; +} + +/** + * gst_tag_list_from_vorbiscomment_buffer: + * @buffer: buffer to convert + * @id_data: identification data at start of stream + * @id_data_length: length of identification data + * @vendor_string: pointer to a string that should take the vendor string + * of this vorbis comment or NULL if you don't need it. + * + * Creates a new tag list that contains the information parsed out of a + * vorbiscomment packet. + * + * Returns: A new #GstTagList with all tags that could be extracted from the + * given vorbiscomment buffer or NULL on error. + */ +GstTagList * +gst_tag_list_from_vorbiscomment_buffer (const GstBuffer * buffer, + const guint8 * id_data, const guint id_data_length, gchar ** vendor_string) +{ +#define ADVANCE(x) G_STMT_START{ \ + data += x; \ + size -= x; \ + if (size < 4) goto error; \ + cur_size = GST_READ_UINT32_LE (data); \ + data += 4; \ + size -= 4; \ + if (cur_size > size) goto error; \ + cur = (gchar*)data; \ +}G_STMT_END + gchar *cur, *value; + guint cur_size; + guint iterations; + guint8 *data; + guint size, value_len; + GstTagList *list; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (id_data != NULL || id_data_length == 0, NULL); + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + list = gst_tag_list_new (); + + if (size < 11 || size <= id_data_length + 4) + goto error; + + if (id_data_length > 0 && memcmp (data, id_data, id_data_length) != 0) + goto error; + + ADVANCE (id_data_length); + + if (vendor_string) + *vendor_string = g_strndup (cur, cur_size); + + ADVANCE (cur_size); + iterations = cur_size; + cur_size = 0; + + while (iterations) { + ADVANCE (cur_size); + iterations--; + cur = g_strndup (cur, cur_size); + value = strchr (cur, '='); + if (value == NULL) { + g_free (cur); + continue; + } + *value = '\0'; + value++; + value_len = strlen (value); + if (value_len == 0 || !g_utf8_validate (value, value_len, NULL)) { + g_free (cur); + continue; + } + /* we'll just ignore COVERARTMIME and typefind the image data */ + if (g_ascii_strcasecmp (cur, "COVERARTMIME") == 0) { + continue; + } else if (g_ascii_strcasecmp (cur, "COVERART") == 0) { + gst_vorbis_tag_add_coverart (list, value, value_len); + } else if (g_ascii_strcasecmp (cur, "METADATA_BLOCK_PICTURE") == 0) { + gst_vorbis_tag_add_metadata_block_picture (list, value, value_len); + } else { + gst_vorbis_tag_add (list, cur, value); + } + g_free (cur); + } + + return list; + +error: + gst_tag_list_free (list); + return NULL; +#undef ADVANCE +} + +typedef struct +{ + guint count; + guint data_count; + GList *entries; +} +MyForEach; + +static GList * +gst_tag_to_metadata_block_picture (const gchar * tag, + const GValue * image_value) +{ + gchar *comment_data, *data_result; + const gchar *mime_type; + guint mime_type_len; + GstStructure *mime_struct; + GstBuffer *buffer; + GList *l = NULL; + GstByteWriter writer; + GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; + gint width = 0, height = 0; + guint8 *metadata_block; + guint metadata_block_len; + + g_return_val_if_fail (image_value != NULL, NULL); + + buffer = gst_value_get_buffer (image_value); + g_return_val_if_fail (gst_caps_is_fixed (buffer->caps), NULL); + mime_struct = gst_caps_get_structure (buffer->caps, 0); + + mime_type = gst_structure_get_name (mime_struct); + if (strcmp (mime_type, "text/uri-list") == 0) + mime_type = "-->"; + mime_type_len = strlen (mime_type); + + gst_structure_get (mime_struct, "image-type", GST_TYPE_TAG_IMAGE_TYPE, + &image_type, "width", G_TYPE_INT, &width, "height", G_TYPE_INT, &height, + NULL); + + metadata_block_len = 32 + mime_type_len + GST_BUFFER_SIZE (buffer); + gst_byte_writer_init_with_size (&writer, metadata_block_len, TRUE); + + if (image_type == GST_TAG_IMAGE_TYPE_NONE + && strcmp (tag, GST_TAG_PREVIEW_IMAGE) == 0) { + gst_byte_writer_put_uint32_be_unchecked (&writer, 0x01); + } else { + /* Convert to ID3v2 APIC image type */ + if (image_type == GST_TAG_IMAGE_TYPE_NONE) + image_type = GST_TAG_IMAGE_TYPE_UNDEFINED; + else + image_type = image_type + 2; + gst_byte_writer_put_uint32_be_unchecked (&writer, image_type); + } + + gst_byte_writer_put_uint32_be_unchecked (&writer, mime_type_len); + gst_byte_writer_put_data_unchecked (&writer, (guint8 *) mime_type, + mime_type_len); + /* description length */ + gst_byte_writer_put_uint32_be_unchecked (&writer, 0); + gst_byte_writer_put_uint32_be_unchecked (&writer, width); + gst_byte_writer_put_uint32_be_unchecked (&writer, height); + /* color depth */ + gst_byte_writer_put_uint32_be_unchecked (&writer, 0); + /* for indexed formats the number of colors */ + gst_byte_writer_put_uint32_be_unchecked (&writer, 0); + gst_byte_writer_put_uint32_be_unchecked (&writer, GST_BUFFER_SIZE (buffer)); + gst_byte_writer_put_data_unchecked (&writer, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + g_assert (gst_byte_writer_get_pos (&writer) == metadata_block_len); + + metadata_block = gst_byte_writer_reset_and_get_data (&writer); + comment_data = g_base64_encode (metadata_block, metadata_block_len); + g_free (metadata_block); + data_result = g_strdup_printf ("METADATA_BLOCK_PICTURE=%s", comment_data); + g_free (comment_data); + + l = g_list_append (l, data_result); + + return l; +} + +/** + * gst_tag_to_vorbis_comments: + * @list: a #GstTagList + * @tag: a GStreamer tag identifier, such as #GST_TAG_ARTIST + * + * Creates a new tag list that contains the information parsed out of a + * vorbiscomment packet. + * + * Returns: A #GList of newly-allowcated key=value strings. Free with + * g_list_foreach (list, (GFunc) g_free, NULL) plus g_list_free (list) + */ +GList * +gst_tag_to_vorbis_comments (const GstTagList * list, const gchar * tag) +{ + const gchar *vorbis_tag = NULL; + GList *l = NULL; + guint i; + + g_return_val_if_fail (list != NULL, NULL); + g_return_val_if_fail (tag != NULL, NULL); + + /* Special case: cover art is split into two tags to store data and + * MIME-type. Even if the tag list contains multiple entries, there is + * no reasonable way to save more than one. + * If both, preview image and image, are present we prefer the + * image tag. + */ + if ((strcmp (tag, GST_TAG_PREVIEW_IMAGE) == 0 && + gst_tag_list_get_tag_size (list, GST_TAG_IMAGE) == 0) || + strcmp (tag, GST_TAG_IMAGE) == 0) { + return gst_tag_to_metadata_block_picture (tag, + gst_tag_list_get_value_index (list, tag, 0)); + } + + if (strcmp (tag, GST_TAG_EXTENDED_COMMENT) != 0) { + vorbis_tag = gst_tag_to_vorbis_tag (tag); + if (!vorbis_tag) + return NULL; + } + + /* FIXME: for tags that can map to multiple vorbis comment keys, add all + * of the possible keys */ + for (i = 0; i < gst_tag_list_get_tag_size (list, tag); i++) { + GType tag_type = gst_tag_get_type (tag); + gchar *result = NULL; + + switch (tag_type) { + case G_TYPE_UINT:{ + guint u; + + if (!gst_tag_list_get_uint_index (list, tag, i, &u)) + g_return_val_if_reached (NULL); + result = g_strdup_printf ("%s=%u", vorbis_tag, u); + break; + } + case G_TYPE_STRING:{ + const gchar *str = NULL; + + if (!gst_tag_list_peek_string_index (list, tag, i, &str)) + g_return_val_if_reached (NULL); + + /* special case: GST_TAG_EXTENDED_COMMENT */ + if (vorbis_tag == NULL) { + gchar *key = NULL, *val = NULL; + + if (gst_tag_parse_extended_comment (str, &key, NULL, &val, TRUE)) { + result = g_strdup_printf ("%s=%s", key, val); + g_free (key); + g_free (val); + } else { + GST_WARNING ("Not a valid extended comment string: %s", str); + continue; + } + } else { + result = g_strdup_printf ("%s=%s", vorbis_tag, str); + } + break; + } + case G_TYPE_DOUBLE:{ + gdouble value; + gchar buf[G_ASCII_DTOSTR_BUF_SIZE]; + + if (!gst_tag_list_get_double_index (list, tag, i, &value)) + g_return_val_if_reached (NULL); + g_ascii_formatd (buf, G_ASCII_DTOSTR_BUF_SIZE, "%f", value); + result = g_strconcat (vorbis_tag, "=", buf, NULL); + break; + } + default:{ + if (tag_type == GST_TYPE_DATE) { + GDate *date; + + if (!gst_tag_list_get_date_index (list, tag, i, &date)) + g_return_val_if_reached (NULL); + + /* vorbis suggests using ISO date formats */ + result = + g_strdup_printf ("%s=%04d-%02d-%02d", vorbis_tag, + (gint) g_date_get_year (date), (gint) g_date_get_month (date), + (gint) g_date_get_day (date)); + g_date_free (date); + } else { + GST_DEBUG ("Couldn't write tag %s", tag); + continue; + } + break; + } + } + l = g_list_prepend (l, result); + } + + return g_list_reverse (l); +} + +static void +write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) +{ + MyForEach *data = (MyForEach *) user_data; + GList *comments; + GList *it; + + comments = gst_tag_to_vorbis_comments (list, tag); + + for (it = comments; it != NULL; it = it->next) { + gchar *result = it->data; + + data->count++; + data->data_count += strlen (result); + data->entries = g_list_prepend (data->entries, result); + } + + g_list_free (comments); +} + +/** + * gst_tag_list_to_vorbiscomment_buffer: + * @list: tag list to convert + * @id_data: identification data at start of stream + * @id_data_length: length of identification data, may be 0 if @id_data is NULL + * @vendor_string: string that describes the vendor string or NULL + * + * Creates a new vorbiscomment buffer from a tag list. + * + * Returns: A new #GstBuffer containing a vorbiscomment buffer with all tags + * that could be converted from the given tag list. + */ +GstBuffer * +gst_tag_list_to_vorbiscomment_buffer (const GstTagList * list, + const guint8 * id_data, const guint id_data_length, + const gchar * vendor_string) +{ + GstBuffer *buffer; + guint8 *data; + guint i; + GList *l; + MyForEach my_data = { 0, 0, NULL }; + guint vendor_len; + int required_size; + + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + g_return_val_if_fail (id_data != NULL || id_data_length == 0, NULL); + + if (vendor_string == NULL) + vendor_string = "GStreamer encoded vorbiscomment"; + vendor_len = strlen (vendor_string); + required_size = id_data_length + 4 + vendor_len + 4 + 1; + gst_tag_list_foreach ((GstTagList *) list, write_one_tag, &my_data); + required_size += 4 * my_data.count + my_data.data_count; + buffer = gst_buffer_new_and_alloc (required_size); + data = GST_BUFFER_DATA (buffer); + if (id_data_length > 0) { + memcpy (data, id_data, id_data_length); + data += id_data_length; + } + GST_WRITE_UINT32_LE (data, vendor_len); + data += 4; + memcpy (data, vendor_string, vendor_len); + data += vendor_len; + l = my_data.entries = g_list_reverse (my_data.entries); + GST_WRITE_UINT32_LE (data, my_data.count); + data += 4; + for (i = 0; i < my_data.count; i++) { + guint size; + gchar *cur; + + g_assert (l != NULL); + cur = l->data; + l = g_list_next (l); + size = strlen (cur); + GST_WRITE_UINT32_LE (data, size); + data += 4; + memcpy (data, cur, size); + data += size; + } + g_list_foreach (my_data.entries, (GFunc) g_free, NULL); + g_list_free (my_data.entries); + *data = 1; + + return buffer; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstxmptag.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstxmptag.c new file mode 100644 index 0000000..ca05895 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/gstxmptag.c @@ -0,0 +1,1684 @@ +/* GStreamer + * Copyright (C) 2010 Stefan Kost + * Copyright (C) 2010 Thiago Santos + * + * gstxmptag.c: library for reading / modifying xmp tags + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttagxmp + * @short_description: tag mappings and support functions for plugins + * dealing with xmp packets + * @see_also: #GstTagList + * + * Contains various utility functions for plugins to parse or create + * xmp packets and map them to and from #GstTagLists. + * + * Please note that the xmp parser is very lightweight and not strict at all. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "tag.h" +#include +#include "gsttageditingprivate.h" +#include +#include +#include +#include +#include + +static const gchar *schema_list[] = { + "dc", + "xap", + "tiff", + "exif", + "photoshop", + "Iptc4xmpCore", + NULL +}; + +/** + * gst_tag_xmp_list_schemas: + * + * Gets the list of supported schemas in the xmp lib + * + * Returns: a %NULL terminated array of strings with the schema names + * + * Since: 0.10.33 + */ +const gchar ** +gst_tag_xmp_list_schemas (void) +{ + return schema_list; +} + +typedef struct _XmpSerializationData XmpSerializationData; +typedef struct _XmpTag XmpTag; + +/* + * Serializes a GValue into a string. + */ +typedef gchar *(*XmpSerializationFunc) (const GValue * value); + +/* + * Deserializes @str that is the gstreamer tag @gst_tag represented in + * XMP as the @xmp_tag_value and adds the result to the @taglist. + * + * @pending_tags is passed so that compound xmp tags can search for its + * complements on the list and use them. Note that used complements should + * be freed and removed from the list. + * The list is of PendingXmpTag + */ +typedef void (*XmpDeserializationFunc) (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag_value, + const gchar * str, GSList ** pending_tags); + +struct _XmpSerializationData +{ + GString *data; + const gchar **schemas; +}; + +static gboolean +xmp_serialization_data_use_schema (XmpSerializationData * serdata, + const gchar * schemaname) +{ + gint i = 0; + if (serdata->schemas == NULL) + return TRUE; + + while (serdata->schemas[i] != NULL) { + if (strcmp (serdata->schemas[i], schemaname) == 0) + return TRUE; + i++; + } + return FALSE; +} + + +#define GST_XMP_TAG_TYPE_SIMPLE 0 +#define GST_XMP_TAG_TYPE_BAG 1 +#define GST_XMP_TAG_TYPE_SEQ 2 +struct _XmpTag +{ + const gchar *tag_name; + gint type; + + XmpSerializationFunc serialize; + XmpDeserializationFunc deserialize; +}; + +static GstTagMergeMode +xmp_tag_get_merge_mode (XmpTag * xmptag) +{ + switch (xmptag->type) { + case GST_XMP_TAG_TYPE_BAG: + case GST_XMP_TAG_TYPE_SEQ: + return GST_TAG_MERGE_APPEND; + case GST_XMP_TAG_TYPE_SIMPLE: + default: + return GST_TAG_MERGE_KEEP; + } +} + +static const gchar * +xmp_tag_get_type_name (XmpTag * xmptag) +{ + switch (xmptag->type) { + case GST_XMP_TAG_TYPE_SEQ: + return "rdf:Seq"; + default: + g_assert_not_reached (); + case GST_XMP_TAG_TYPE_BAG: + return "rdf:Bag"; + } +} + +struct _PendingXmpTag +{ + const gchar *gst_tag; + XmpTag *xmp_tag; + gchar *str; +}; +typedef struct _PendingXmpTag PendingXmpTag; + + +/* + * A schema is a mapping of strings (the tag name in gstreamer) to a list of + * tags in xmp (XmpTag). We need a list because some tags are split into 2 + * when serialized into xmp. + * e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary + * tags in the exif's schema. One of them stores the absolute elevation, + * and the other one stores if it is above of below sea level. + */ +typedef GHashTable GstXmpSchema; +#define gst_xmp_schema_lookup g_hash_table_lookup +#define gst_xmp_schema_insert g_hash_table_insert +static GstXmpSchema * +gst_xmp_schema_new () +{ + return g_hash_table_new (g_direct_hash, g_direct_equal); +} + +/* + * Mappings from schema names into the schema group of tags (GstXmpSchema) + */ +static GHashTable *__xmp_schemas; + +static void +_gst_xmp_add_schema (const gchar * name, GstXmpSchema * schema) +{ + GQuark key; + + key = g_quark_from_string (name); + + if (g_hash_table_lookup (__xmp_schemas, GUINT_TO_POINTER (key))) { + GST_WARNING ("Schema %s already exists, ignoring", name); + g_assert_not_reached (); + return; + } + + g_hash_table_insert (__xmp_schemas, GUINT_TO_POINTER (key), schema); +} + +static void +_gst_xmp_schema_add_mapping (GstXmpSchema * schema, const gchar * gst_tag, + GPtrArray * array) +{ + GQuark key; + + key = g_quark_from_string (gst_tag); + + if (gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key))) { + GST_WARNING ("Tag %s already present for the schema", gst_tag); + g_assert_not_reached (); + return; + } + gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), array); +} + +static void +_gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema, + const gchar * gst_tag, const gchar * xmp_tag, gint xmp_type, + XmpSerializationFunc serialization_func, + XmpDeserializationFunc deserialization_func) +{ + XmpTag *xmpinfo; + GPtrArray *array; + + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = xmp_tag; + xmpinfo->type = xmp_type; + xmpinfo->serialize = serialization_func; + xmpinfo->deserialize = deserialization_func; + + array = g_ptr_array_sized_new (1); + g_ptr_array_add (array, xmpinfo); + + _gst_xmp_schema_add_mapping (schema, gst_tag, array); +} + +/* + * We do not return a copy here because elements are + * appended, and the API is not public, so we shouldn't + * have our lists modified during usage + */ +static GPtrArray * +_xmp_tag_get_mapping (const gchar * gst_tag, XmpSerializationData * serdata) +{ + GPtrArray *ret = NULL; + GHashTableIter iter; + GQuark key = g_quark_from_string (gst_tag); + gpointer iterkey, value; + const gchar *schemaname; + + g_hash_table_iter_init (&iter, __xmp_schemas); + while (!ret && g_hash_table_iter_next (&iter, &iterkey, &value)) { + GstXmpSchema *schema = (GstXmpSchema *) value; + + schemaname = g_quark_to_string (GPOINTER_TO_UINT (iterkey)); + if (xmp_serialization_data_use_schema (serdata, schemaname)) + ret = + (GPtrArray *) gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key)); + } + return ret; +} + +/* finds the gst tag that maps to this xmp tag in this schema */ +static const gchar * +_gst_xmp_schema_get_mapping_reverse (GstXmpSchema * schema, + const gchar * xmp_tag, XmpTag ** _xmp_tag) +{ + GHashTableIter iter; + gpointer key, value; + const gchar *ret = NULL; + gint index; + + /* Iterate over the hashtable */ + g_hash_table_iter_init (&iter, schema); + while (!ret && g_hash_table_iter_next (&iter, &key, &value)) { + GPtrArray *array = (GPtrArray *) value; + + /* each mapping might contain complementary tags */ + for (index = 0; index < array->len; index++) { + XmpTag *xmpinfo = (XmpTag *) g_ptr_array_index (array, index); + + if (strcmp (xmpinfo->tag_name, xmp_tag) == 0) { + *_xmp_tag = xmpinfo; + ret = g_quark_to_string (GPOINTER_TO_UINT (key)); + goto out; + } + } + } + +out: + return ret; +} + +/* finds the gst tag that maps to this xmp tag (searches on all schemas) */ +static const gchar * +_gst_xmp_tag_get_mapping_reverse (const gchar * xmp_tag, XmpTag ** _xmp_tag) +{ + GHashTableIter iter; + gpointer key, value; + const gchar *ret = NULL; + + /* Iterate over the hashtable */ + g_hash_table_iter_init (&iter, __xmp_schemas); + while (!ret && g_hash_table_iter_next (&iter, &key, &value)) { + ret = _gst_xmp_schema_get_mapping_reverse ((GstXmpSchema *) value, xmp_tag, + _xmp_tag); + } + return ret; +} + +/* utility functions/macros */ + +#define METERS_PER_SECOND_TO_KILOMETERS_PER_HOUR (3.6) +#define KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND (1/3.6) +#define MILES_PER_HOUR_TO_METERS_PER_SECOND (0.44704) +#define KNOTS_TO_METERS_PER_SECOND (0.514444) + +static gchar * +double_to_fraction_string (gdouble num) +{ + gint frac_n; + gint frac_d; + + gst_util_double_to_fraction (num, &frac_n, &frac_d); + return g_strdup_printf ("%d/%d", frac_n, frac_d); +} + +/* (de)serialize functions */ +static gchar * +serialize_exif_gps_coordinate (const GValue * value, gchar pos, gchar neg) +{ + gdouble num; + gchar c; + gint integer; + gchar fraction[G_ASCII_DTOSTR_BUF_SIZE]; + + g_return_val_if_fail (G_VALUE_TYPE (value) == G_TYPE_DOUBLE, NULL); + + num = g_value_get_double (value); + if (num < 0) { + c = neg; + num *= -1; + } else { + c = pos; + } + integer = (gint) num; + + g_ascii_dtostr (fraction, sizeof (fraction), (num - integer) * 60); + + /* FIXME review GPSCoordinate serialization spec for the .mm or ,ss + * decision. Couldn't understand it clearly */ + return g_strdup_printf ("%d,%s%c", integer, fraction, c); +} + +static gchar * +serialize_exif_latitude (const GValue * value) +{ + return serialize_exif_gps_coordinate (value, 'N', 'S'); +} + +static gchar * +serialize_exif_longitude (const GValue * value) +{ + return serialize_exif_gps_coordinate (value, 'E', 'W'); +} + +static void +deserialize_exif_gps_coordinate (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * str, gchar pos, gchar neg) +{ + gdouble value = 0; + gint d = 0, m = 0, s = 0; + gdouble m2 = 0; + gchar c = 0; + const gchar *current; + + /* get the degrees */ + if (sscanf (str, "%d", &d) != 1) + goto error; + + /* find the beginning of the minutes */ + current = strchr (str, ','); + if (current == NULL) + goto end; + current += 1; + + /* check if it uses ,SS or .mm */ + if (strchr (current, ',') != NULL) { + sscanf (current, "%d,%d%c", &m, &s, &c); + } else { + gchar *copy = g_strdup (current); + gint len = strlen (copy); + gint i; + + /* check the last letter */ + for (i = len - 1; len >= 0; len--) { + if (g_ascii_isspace (copy[i])) + continue; + + if (g_ascii_isalpha (copy[i])) { + /* found it */ + c = copy[i]; + copy[i] = '\0'; + break; + + } else { + /* something is wrong */ + g_free (copy); + goto error; + } + } + + /* use a copy so we can change the last letter as E can cause + * problems here */ + m2 = g_ascii_strtod (copy, NULL); + g_free (copy); + } + +end: + /* we can add them all as those that aren't parsed are 0 */ + value = d + (m / 60.0) + (s / (60.0 * 60.0)) + (m2 / 60.0); + + if (c == pos) { + //NOP + } else if (c == neg) { + value *= -1; + } else { + goto error; + } + + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), gst_tag, value, + NULL); + return; + +error: + GST_WARNING ("Failed to deserialize gps coordinate: %s", str); +} + +static void +deserialize_exif_latitude (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + deserialize_exif_gps_coordinate (xmptag, taglist, gst_tag, str, 'N', 'S'); +} + +static void +deserialize_exif_longitude (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + deserialize_exif_gps_coordinate (xmptag, taglist, gst_tag, str, 'E', 'W'); +} + +static gchar * +serialize_exif_altitude (const GValue * value) +{ + gdouble num; + + num = g_value_get_double (value); + + if (num < 0) + num *= -1; + + return double_to_fraction_string (num); +} + +static gchar * +serialize_exif_altituderef (const GValue * value) +{ + gdouble num; + + num = g_value_get_double (value); + + /* 0 means above sea level, 1 means below */ + if (num >= 0) + return g_strdup ("0"); + return g_strdup ("1"); +} + +static void +deserialize_exif_altitude (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + const gchar *altitude_str = NULL; + const gchar *altituderef_str = NULL; + gint frac_n; + gint frac_d; + gdouble value; + + GSList *entry; + PendingXmpTag *ptag = NULL; + + /* find the other missing part */ + if (strcmp (xmp_tag, "exif:GPSAltitude") == 0) { + altitude_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, "exif:GPSAltitudeRef") == 0) { + altituderef_str = ptag->str; + break; + } + } + + } else if (strcmp (xmp_tag, "exif:GPSAltitudeRef") == 0) { + altituderef_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, "exif:GPSAltitude") == 0) { + altitude_str = ptag->str; + break; + } + } + + } else { + GST_WARNING ("Unexpected xmp tag %s", xmp_tag); + return; + } + + if (!altitude_str) { + GST_WARNING ("Missing exif:GPSAltitude tag"); + return; + } + if (!altituderef_str) { + GST_WARNING ("Missing exif:GPSAltitudeRef tag"); + return; + } + + if (sscanf (altitude_str, "%d/%d", &frac_n, &frac_d) != 2) { + GST_WARNING ("Failed to parse fraction: %s", altitude_str); + return; + } + + gst_util_fraction_to_double (frac_n, frac_d, &value); + + if (altituderef_str[0] == '0') { + /* nop */ + } else if (altituderef_str[0] == '1') { + value *= -1; + } else { + GST_WARNING ("Unexpected exif:AltitudeRef value: %s", altituderef_str); + return; + } + + /* add to the taglist */ + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), + GST_TAG_GEO_LOCATION_ELEVATION, value, NULL); + + /* clean up entry */ + g_free (ptag->str); + g_slice_free (PendingXmpTag, ptag); + *pending_tags = g_slist_delete_link (*pending_tags, entry); +} + +static gchar * +serialize_exif_gps_speed (const GValue * value) +{ + return double_to_fraction_string (g_value_get_double (value) * + METERS_PER_SECOND_TO_KILOMETERS_PER_HOUR); +} + +static gchar * +serialize_exif_gps_speedref (const GValue * value) +{ + /* we always use km/h */ + return g_strdup ("K"); +} + +static void +deserialize_exif_gps_speed (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + const gchar *speed_str = NULL; + const gchar *speedref_str = NULL; + gint frac_n; + gint frac_d; + gdouble value; + + GSList *entry; + PendingXmpTag *ptag = NULL; + + /* find the other missing part */ + if (strcmp (xmp_tag, "exif:GPSSpeed") == 0) { + speed_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, "exif:GPSSpeedRef") == 0) { + speedref_str = ptag->str; + break; + } + } + + } else if (strcmp (xmp_tag, "exif:GPSSpeedRef") == 0) { + speedref_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, "exif:GPSSpeed") == 0) { + speed_str = ptag->str; + break; + } + } + + } else { + GST_WARNING ("Unexpected xmp tag %s", xmp_tag); + return; + } + + if (!speed_str) { + GST_WARNING ("Missing exif:GPSSpeed tag"); + return; + } + if (!speedref_str) { + GST_WARNING ("Missing exif:GPSSpeedRef tag"); + return; + } + + if (sscanf (speed_str, "%d/%d", &frac_n, &frac_d) != 2) { + GST_WARNING ("Failed to parse fraction: %s", speed_str); + return; + } + + gst_util_fraction_to_double (frac_n, frac_d, &value); + + if (speedref_str[0] == 'K') { + value *= KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND; + } else if (speedref_str[0] == 'M') { + value *= MILES_PER_HOUR_TO_METERS_PER_SECOND; + } else if (speedref_str[0] == 'N') { + value *= KNOTS_TO_METERS_PER_SECOND; + } else { + GST_WARNING ("Unexpected exif:SpeedRef value: %s", speedref_str); + return; + } + + /* add to the taglist */ + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), + GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, value, NULL); + + /* clean up entry */ + g_free (ptag->str); + g_slice_free (PendingXmpTag, ptag); + *pending_tags = g_slist_delete_link (*pending_tags, entry); +} + +static gchar * +serialize_exif_gps_direction (const GValue * value) +{ + return double_to_fraction_string (g_value_get_double (value)); +} + +static gchar * +serialize_exif_gps_directionref (const GValue * value) +{ + /* T for true geographic direction (M would mean magnetic) */ + return g_strdup ("T"); +} + +static void +deserialize_exif_gps_direction (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags, const gchar * direction_tag, + const gchar * directionref_tag) +{ + const gchar *dir_str = NULL; + const gchar *dirref_str = NULL; + gint frac_n; + gint frac_d; + gdouble value; + + GSList *entry; + PendingXmpTag *ptag = NULL; + + /* find the other missing part */ + if (strcmp (xmp_tag, direction_tag) == 0) { + dir_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, directionref_tag) == 0) { + dirref_str = ptag->str; + break; + } + } + + } else if (strcmp (xmp_tag, directionref_tag) == 0) { + dirref_str = str; + + for (entry = *pending_tags; entry; entry = g_slist_next (entry)) { + ptag = (PendingXmpTag *) entry->data; + + if (strcmp (ptag->xmp_tag->tag_name, direction_tag) == 0) { + dir_str = ptag->str; + break; + } + } + + } else { + GST_WARNING ("Unexpected xmp tag %s", xmp_tag); + return; + } + + if (!dir_str) { + GST_WARNING ("Missing %s tag", dir_str); + return; + } + if (!dirref_str) { + GST_WARNING ("Missing %s tag", dirref_str); + return; + } + + if (sscanf (dir_str, "%d/%d", &frac_n, &frac_d) != 2) { + GST_WARNING ("Failed to parse fraction: %s", dir_str); + return; + } + + gst_util_fraction_to_double (frac_n, frac_d, &value); + + if (dirref_str[0] == 'T') { + /* nop */ + } else if (dirref_str[0] == 'M') { + GST_WARNING ("Magnetic direction tags aren't supported yet"); + return; + } else { + GST_WARNING ("Unexpected %s value: %s", directionref_tag, dirref_str); + return; + } + + /* add to the taglist */ + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), gst_tag, value, + NULL); + + /* clean up entry */ + g_free (ptag->str); + g_slice_free (PendingXmpTag, ptag); + *pending_tags = g_slist_delete_link (*pending_tags, entry); +} + +static void +deserialize_exif_gps_track (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + deserialize_exif_gps_direction (xmptag, taglist, gst_tag, xmp_tag, str, + pending_tags, "exif:GPSTrack", "exif:GPSTrackRef"); +} + +static void +deserialize_exif_gps_img_direction (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + deserialize_exif_gps_direction (xmptag, taglist, gst_tag, xmp_tag, str, + pending_tags, "exif:GPSImgDirection", "exif:GPSImgDirectionRef"); +} + +static void +deserialize_xmp_rating (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + guint value; + + if (sscanf (str, "%u", &value) != 1) { + GST_WARNING ("Failed to parse xmp:Rating %s", str); + return; + } + + if (value < 0 || value > 100) { + GST_WARNING ("Unsupported Rating tag %u (should be from 0 to 100), " + "ignoring", value); + return; + } + + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), gst_tag, value, + NULL); +} + +static gchar * +serialize_tiff_orientation (const GValue * value) +{ + const gchar *str; + gint num; + + str = g_value_get_string (value); + if (str == NULL) { + GST_WARNING ("Failed to get image orientation tag value"); + return NULL; + } + + num = __exif_tag_image_orientation_to_exif_value (str); + if (num == -1) + return NULL; + + return g_strdup_printf ("%d", num); +} + +static void +deserialize_tiff_orientation (XmpTag * xmptag, GstTagList * taglist, + const gchar * gst_tag, const gchar * xmp_tag, const gchar * str, + GSList ** pending_tags) +{ + guint value; + const gchar *orientation = NULL; + + if (sscanf (str, "%u", &value) != 1) { + GST_WARNING ("Failed to parse tiff:Orientation %s", str); + return; + } + + if (value < 1 || value > 8) { + GST_WARNING ("Invalid tiff:Orientation tag %u (should be from 1 to 8), " + "ignoring", value); + return; + } + + orientation = __exif_tag_image_orientation_from_exif_value (value); + if (orientation == NULL) + return; + gst_tag_list_add (taglist, xmp_tag_get_merge_mode (xmptag), gst_tag, + orientation, NULL); +} + + +/* look at this page for addtional schemas + * http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/XMP.html + */ +static gpointer +_init_xmp_tag_map (gpointer user_data) +{ + GPtrArray *array; + XmpTag *xmpinfo; + GstXmpSchema *schema; + + __xmp_schemas = g_hash_table_new (g_direct_hash, g_direct_equal); + + /* add the maps */ + /* dublic code metadata + * http://dublincore.org/documents/dces/ + */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_ARTIST, + "dc:creator", GST_XMP_TAG_TYPE_SEQ, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_COPYRIGHT, + "dc:rights", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE, "dc:date", + GST_XMP_TAG_TYPE_SEQ, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DESCRIPTION, + "dc:description", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_KEYWORDS, + "dc:subject", GST_XMP_TAG_TYPE_BAG, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_TITLE, "dc:title", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + /* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */ + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_VIDEO_CODEC, + "dc:format", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_add_schema ("dc", schema); + + /* xap (xmp) schema */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING, + "xmp:Rating", GST_XMP_TAG_TYPE_SIMPLE, NULL, deserialize_xmp_rating); + _gst_xmp_add_schema ("xap", schema); + + /* tiff */ + schema = gst_xmp_schema_new (); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GST_XMP_TAG_TYPE_SIMPLE, NULL, + NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MODEL, + "tiff:Model", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_APPLICATION_NAME, + "tiff:Software", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_IMAGE_ORIENTATION, + "tiff:Orientation", GST_XMP_TAG_TYPE_SIMPLE, serialize_tiff_orientation, + deserialize_tiff_orientation); + _gst_xmp_add_schema ("tiff", schema); + + /* exif schema */ + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME, + "exif:DateTimeOriginal", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_LATITUDE, "exif:GPSLatitude", + GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_latitude, + deserialize_exif_latitude); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_LONGITUDE, + "exif:GPSLongitude", GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_longitude, + deserialize_exif_longitude); + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, "exif:ExposureBiasValue", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + + /* compound exif tags */ + array = g_ptr_array_sized_new (2); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSAltitude"; + xmpinfo->serialize = serialize_exif_altitude; + xmpinfo->deserialize = deserialize_exif_altitude; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSAltitudeRef"; + xmpinfo->serialize = serialize_exif_altituderef; + xmpinfo->deserialize = deserialize_exif_altitude; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + _gst_xmp_schema_add_mapping (schema, GST_TAG_GEO_LOCATION_ELEVATION, array); + + array = g_ptr_array_sized_new (2); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSSpeed"; + xmpinfo->serialize = serialize_exif_gps_speed; + xmpinfo->deserialize = deserialize_exif_gps_speed; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSSpeedRef"; + xmpinfo->serialize = serialize_exif_gps_speedref; + xmpinfo->deserialize = deserialize_exif_gps_speed; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + _gst_xmp_schema_add_mapping (schema, + GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, array); + + array = g_ptr_array_sized_new (2); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSTrack"; + xmpinfo->serialize = serialize_exif_gps_direction; + xmpinfo->deserialize = deserialize_exif_gps_track; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSTrackRef"; + xmpinfo->serialize = serialize_exif_gps_directionref; + xmpinfo->deserialize = deserialize_exif_gps_track; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + _gst_xmp_schema_add_mapping (schema, + GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, array); + + array = g_ptr_array_sized_new (2); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSImgDirection"; + xmpinfo->serialize = serialize_exif_gps_direction; + xmpinfo->deserialize = deserialize_exif_gps_img_direction; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + xmpinfo = g_slice_new (XmpTag); + xmpinfo->tag_name = "exif:GPSImgDirectionRef"; + xmpinfo->serialize = serialize_exif_gps_directionref; + xmpinfo->deserialize = deserialize_exif_gps_img_direction; + xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE; + g_ptr_array_add (array, xmpinfo); + _gst_xmp_schema_add_mapping (schema, + GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, array); + _gst_xmp_add_schema ("exif", schema); + + /* photoshop schema */ + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_CITY, + "photoshop:City", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_add_schema ("photoshop", schema); + + /* iptc4xmpcore schema */ + _gst_xmp_schema_add_simple_mapping (schema, + GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location", + GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL); + _gst_xmp_add_schema ("Iptc4xmpCore", schema); + + return NULL; +} + +static void +xmp_tags_initialize () +{ + static GOnce my_once = G_ONCE_INIT; + g_once (&my_once, (GThreadFunc) _init_xmp_tag_map, NULL); +} + +typedef struct _GstXmpNamespaceMatch GstXmpNamespaceMatch; +struct _GstXmpNamespaceMatch +{ + const gchar *ns_prefix; + const gchar *ns_uri; +}; + +static const GstXmpNamespaceMatch ns_match[] = { + {"dc", "http://purl.org/dc/elements/1.1/"}, + {"exif", "http://ns.adobe.com/exif/1.0/"}, + {"tiff", "http://ns.adobe.com/tiff/1.0/"}, + {"xap", "http://ns.adobe.com/xap/1.0/"}, + {"photoshop", "http://ns.adobe.com/photoshop/1.0/"}, + {"Iptc4xmpCore", "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"}, + {NULL, NULL} +}; + +typedef struct _GstXmpNamespaceMap GstXmpNamespaceMap; +struct _GstXmpNamespaceMap +{ + const gchar *original_ns; + gchar *gstreamer_ns; +}; + +/* parsing */ + +static void +read_one_tag (GstTagList * list, const gchar * tag, XmpTag * xmptag, + const gchar * v, GSList ** pending_tags) +{ + GType tag_type; + GstTagMergeMode merge_mode; + + if (xmptag && xmptag->deserialize) { + xmptag->deserialize (xmptag, list, tag, xmptag->tag_name, v, pending_tags); + return; + } + + merge_mode = xmp_tag_get_merge_mode (xmptag); + tag_type = gst_tag_get_type (tag); + + /* add gstreamer tag depending on type */ + switch (tag_type) { + case G_TYPE_STRING:{ + gst_tag_list_add (list, merge_mode, tag, v, NULL); + break; + } + case G_TYPE_DOUBLE:{ + gdouble value = 0; + gint frac_n, frac_d; + + if (sscanf (v, "%d/%d", &frac_n, &frac_d) == 2) { + gst_util_fraction_to_double (frac_n, frac_d, &value); + gst_tag_list_add (list, merge_mode, tag, value, NULL); + } else { + GST_WARNING ("Failed to parse fraction: %s", v); + } + break; + } + default: + if (tag_type == GST_TYPE_DATE_TIME) { + GstDateTime *datetime = NULL; + gint year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0; + gint usecs = 0; + gint gmt_offset_hour = -1, gmt_offset_min = -1, gmt_offset = -1; + gchar usec_str[16]; + gint ret; + gint len; + + len = strlen (v); + if (len == 0) { + GST_WARNING ("Empty string for datetime parsing"); + return; + } + + GST_DEBUG ("Parsing %s into a datetime", v); + + ret = sscanf (v, "%04d-%02d-%02dT%02d:%02d:%02d.%15s", + &year, &month, &day, &hour, &minute, &second, usec_str); + if (ret < 3) { + /* FIXME theoretically, xmp can express datetimes with only year + * or year and month, but gstdatetime doesn't support it */ + GST_WARNING ("Invalid datetime value: %s", v); + } + + /* parse the usecs */ + if (ret >= 7) { + gint num_digits = 0; + + /* find the number of digits */ + while (isdigit ((gint) usec_str[num_digits++]) && num_digits < 6); + + if (num_digits > 0) { + /* fill up to 6 digits with 0 */ + while (num_digits < 6) { + usec_str[num_digits++] = 0; + } + + g_assert (num_digits == 6); + + usec_str[num_digits] = '\0'; + usecs = atoi (usec_str); + } + } + + /* parse the timezone info */ + if (v[len - 1] == 'Z') { + GST_LOG ("UTC timezone"); + + /* Having a Z at the end means UTC */ + datetime = gst_date_time_new (0, year, month, day, hour, minute, + second + usecs / 1000000.0); + } else { + gchar *plus_pos = NULL; + gchar *neg_pos = NULL; + gchar *pos = NULL; + + GST_LOG ("Checking for timezone information"); + + /* check if there is timezone info */ + plus_pos = strrchr (v, '+'); + neg_pos = strrchr (v, '-'); + if (plus_pos) { + pos = plus_pos + 1; + } else if (neg_pos) { + pos = neg_pos + 1; + } + + if (pos) { + gint ret_tz = sscanf (pos, "%d:%d", &gmt_offset_hour, + &gmt_offset_min); + + GST_DEBUG ("Parsing timezone: %s", pos); + + if (ret_tz == 2) { + gmt_offset = gmt_offset_hour * 60 + gmt_offset_min; + if (neg_pos != NULL && neg_pos + 1 == pos) + gmt_offset *= -1; + + GST_LOG ("Timezone offset: %f (%d minutes)", gmt_offset / 60.0, + gmt_offset); + + /* no way to know if it is DST or not */ + datetime = + gst_date_time_new (gmt_offset / 60.0, + year, month, day, hour, minute, + second + usecs / ((gdouble) G_USEC_PER_SEC)); + } else { + GST_WARNING ("Failed to parse timezone information"); + } + } else { + GST_WARNING ("No timezone signal found"); + } + } + + if (datetime) { + gst_tag_list_add (list, merge_mode, tag, datetime, NULL); + gst_date_time_unref (datetime); + } + + } else if (tag_type == GST_TYPE_DATE) { + GDate *date; + gint d, m, y; + + /* this is ISO 8601 Date and Time Format + * %F Equivalent to %Y-%m-%d (the ISO 8601 date format). (C99) + * %T The time in 24-hour notation (%H:%M:%S). (SU) + * e.g. 2009-05-30T18:26:14+03:00 */ + + /* FIXME: this would be the proper way, but needs + #define _XOPEN_SOURCE before #include + + date = g_date_new (); + struct tm tm={0,}; + strptime (dts, "%FT%TZ", &tm); + g_date_set_time_t (date, mktime(&tm)); + */ + /* FIXME: this cannot parse the date + date = g_date_new (); + g_date_set_parse (date, v); + if (g_date_valid (date)) { + gst_tag_list_add (list, merge_mode, tag, + date, NULL); + } else { + GST_WARNING ("unparsable date: '%s'", v); + } + */ + /* poor mans straw */ + sscanf (v, "%04d-%02d-%02dT", &y, &m, &d); + date = g_date_new_dmy (d, m, y); + gst_tag_list_add (list, merge_mode, tag, date, NULL); + g_date_free (date); + } else { + GST_WARNING ("unhandled type for %s from xmp", tag); + } + break; + } +} + +/** + * gst_tag_list_from_xmp_buffer: + * @buffer: buffer + * + * Parse a xmp packet into a taglist. + * + * Returns: new taglist or %NULL, free the list when done + * + * Since: 0.10.29 + */ +GstTagList * +gst_tag_list_from_xmp_buffer (const GstBuffer * buffer) +{ + GstTagList *list = NULL; + const gchar *xps, *xp1, *xp2, *xpe, *ns, *ne; + guint len, max_ft_len; + gboolean in_tag; + gchar *part, *pp; + guint i; + const gchar *last_tag = NULL; + XmpTag *last_xmp_tag = NULL; + GSList *pending_tags = NULL; + + GstXmpNamespaceMap ns_map[] = { + {"dc", NULL}, + {"exif", NULL}, + {"tiff", NULL}, + {"xap", NULL}, + {"photoshop", NULL}, + {"Iptc4xmpCore", NULL}, + {NULL, NULL} + }; + + xmp_tags_initialize (); + + g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL); + g_return_val_if_fail (GST_BUFFER_SIZE (buffer) > 0, NULL); + + xps = (const gchar *) GST_BUFFER_DATA (buffer); + len = GST_BUFFER_SIZE (buffer); + xpe = &xps[len + 1]; + + /* check header and footer */ + xp1 = g_strstr_len (xps, len, "' && *xp1 != '<' && xp1 < xpe) + xp1++; + if (*xp1 != '>') + goto missing_header; + + max_ft_len = 1 + strlen ("\n"); + if (len < max_ft_len) + goto missing_footer; + + GST_DEBUG ("checking footer: [%s]", &xps[len - max_ft_len]); + xp2 = g_strstr_len (&xps[len - max_ft_len], max_ft_len, " and text until first xml-node */ + xp1++; + while (*xp1 != '<' && xp1 < xpe) + xp1++; + + /* no tag can be longer that the whole buffer */ + part = g_malloc (xp2 - xp1); + list = gst_tag_list_new (); + + /* parse data into a list of nodes */ + /* data is between xp1..xp2 */ + in_tag = TRUE; + ns = ne = xp1; + pp = part; + while (ne < xp2) { + if (in_tag) { + ne++; + while (ne < xp2 && *ne != '>' && *ne != '<') { + if (*ne == '\n' || *ne == '\t' || *ne == ' ') { + while (ne < xp2 && (*ne == '\n' || *ne == '\t' || *ne == ' ')) + ne++; + *pp++ = ' '; + } else { + *pp++ = *ne++; + } + } + *pp = '\0'; + if (*ne != '>') + goto broken_xml; + /* create node */ + /* {XML, ns, ne-ns} */ + if (ns[0] != '/') { + gchar *as = strchr (part, ' '); + /* only log start nodes */ + GST_INFO ("xml: %s", part); + + if (as) { + gchar *ae, *d; + + /* skip ' ' and scan the attributes */ + as++; + d = ae = as; + + /* split attr=value pairs */ + while (*ae != '\0') { + if (*ae == '=') { + /* attr/value delimmiter */ + d = ae; + } else if (*ae == '"') { + /* scan values */ + gchar *v; + + ae++; + while (*ae != '\0' && *ae != '"') + ae++; + + *d = *ae = '\0'; + v = &d[2]; + GST_INFO (" : [%s][%s]", as, v); + if (!strncmp (as, "xmlns:", 6)) { + i = 0; + /* we need to rewrite known namespaces to what we use in + * tag_matches */ + while (ns_match[i].ns_prefix) { + if (!strcmp (ns_match[i].ns_uri, v)) + break; + i++; + } + if (ns_match[i].ns_prefix) { + if (strcmp (ns_map[i].original_ns, &as[6])) { + ns_map[i].gstreamer_ns = g_strdup (&as[6]); + } + } + } else { + const gchar *gst_tag; + XmpTag *xmp_tag = NULL; + /* FIXME: eventualy rewrite ns + * find ':' + * check if ns before ':' is in ns_map and ns_map[i].gstreamer_ns!=NULL + * do 2 stage filter in tag_matches + */ + gst_tag = _gst_xmp_tag_get_mapping_reverse (as, &xmp_tag); + if (gst_tag) { + PendingXmpTag *ptag; + + ptag = g_slice_new (PendingXmpTag); + ptag->gst_tag = gst_tag; + ptag->xmp_tag = xmp_tag; + ptag->str = g_strdup (v); + + pending_tags = g_slist_append (pending_tags, ptag); + } + } + /* restore chars overwritten by '\0' */ + *d = '='; + *ae = '"'; + } else if (*ae == '\0' || *ae == ' ') { + /* end of attr/value pair */ + as = &ae[1]; + } + /* to next char if not eos */ + if (*ae != '\0') + ae++; + } + } else { + /* + Image + + */ + /* FIXME: eventualy rewrite ns */ + + /* skip rdf tags for now */ + if (strncmp (part, "rdf:", 4)) { + const gchar *parttag; + + parttag = _gst_xmp_tag_get_mapping_reverse (part, &last_xmp_tag); + if (parttag) { + last_tag = parttag; + } + } + } + } + /* next cycle */ + ne++; + if (ne < xp2) { + if (*ne != '<') + in_tag = FALSE; + ns = ne; + pp = part; + } + } else { + while (ne < xp2 && *ne != '<') { + *pp++ = *ne; + ne++; + } + *pp = '\0'; + /* create node */ + /* {TXT, ns, (ne-ns)-1} */ + if (ns[0] != '\n' && &ns[1] <= ne) { + /* only log non-newline nodes, we still have to parse them */ + GST_INFO ("txt: %s", part); + if (last_tag) { + PendingXmpTag *ptag; + + ptag = g_slice_new (PendingXmpTag); + ptag->gst_tag = last_tag; + ptag->xmp_tag = last_xmp_tag; + ptag->str = g_strdup (part); + + pending_tags = g_slist_append (pending_tags, ptag); + } + } + /* next cycle */ + in_tag = TRUE; + ns = ne; + pp = part; + } + } + + while (pending_tags) { + PendingXmpTag *ptag = (PendingXmpTag *) pending_tags->data; + + pending_tags = g_slist_delete_link (pending_tags, pending_tags); + + read_one_tag (list, ptag->gst_tag, ptag->xmp_tag, ptag->str, &pending_tags); + + g_free (ptag->str); + g_slice_free (PendingXmpTag, ptag); + } + + GST_INFO ("xmp packet parsed, %d entries", + gst_structure_n_fields ((GstStructure *) list)); + + /* free resources */ + i = 0; + while (ns_map[i].original_ns) { + g_free (ns_map[i].gstreamer_ns); + i++; + } + g_free (part); + + return list; + + /* Errors */ +missing_header: + GST_WARNING ("malformed xmp packet header"); + return NULL; +missing_footer: + GST_WARNING ("malformed xmp packet footer"); + return NULL; +broken_xml: + GST_WARNING ("malformed xml tag: %s", part); + return NULL; +} + + +/* formatting */ + +static void +string_open_tag (GString * string, const char *tag) +{ + g_string_append_c (string, '<'); + g_string_append (string, tag); + g_string_append_c (string, '>'); +} + +static void +string_close_tag (GString * string, const char *tag) +{ + g_string_append (string, "\n"); +} + +static char * +gst_value_serialize_xmp (const GValue * value) +{ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + return g_markup_escape_text (g_value_get_string (value), -1); + case G_TYPE_INT: + return g_strdup_printf ("%d", g_value_get_int (value)); + case G_TYPE_UINT: + return g_strdup_printf ("%u", g_value_get_uint (value)); + case G_TYPE_DOUBLE: + return double_to_fraction_string (g_value_get_double (value)); + default: + break; + } + /* put non-switchable types here */ + if (G_VALUE_TYPE (value) == GST_TYPE_DATE) { + const GDate *date = gst_value_get_date (value); + + return g_strdup_printf ("%04d-%02d-%02d", + (gint) g_date_get_year (date), (gint) g_date_get_month (date), + (gint) g_date_get_day (date)); + } else if (G_VALUE_TYPE (value) == GST_TYPE_DATE_TIME) { + gint year, month, day, hour, min, sec, microsec; + gfloat gmt_offset = 0; + gint gmt_offset_hour, gmt_offset_min; + GstDateTime *datetime = (GstDateTime *) g_value_get_boxed (value); + + year = gst_date_time_get_year (datetime); + month = gst_date_time_get_month (datetime); + day = gst_date_time_get_day (datetime); + hour = gst_date_time_get_hour (datetime); + min = gst_date_time_get_minute (datetime); + sec = gst_date_time_get_second (datetime); + microsec = gst_date_time_get_microsecond (datetime); + gmt_offset = gst_date_time_get_time_zone_offset (datetime); + if (gmt_offset == 0) { + /* UTC */ + return g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d.%06dZ", + year, month, day, hour, min, sec, microsec); + } else { + gmt_offset_hour = ABS (gmt_offset); + gmt_offset_min = (ABS (gmt_offset) - gmt_offset_hour) * 60; + + return g_strdup_printf ("%04d-%02d-%02dT%02d:%02d:%02d.%06d%c%02d:%02d", + year, month, day, hour, min, sec, microsec, + gmt_offset >= 0 ? '+' : '-', gmt_offset_hour, gmt_offset_min); + } + } else { + return NULL; + } +} + +static void +write_one_tag (const GstTagList * list, const gchar * tag, gpointer user_data) +{ + guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index; + XmpSerializationData *serialization_data = user_data; + GString *data = serialization_data->data; + GPtrArray *xmp_tag_array = NULL; + char *s; + + /* map gst-tag to xmp tag */ + xmp_tag_array = _xmp_tag_get_mapping (tag, serialization_data); + + if (!xmp_tag_array) { + GST_WARNING ("no mapping for %s to xmp", tag); + return; + } + + for (tag_index = 0; tag_index < xmp_tag_array->len; tag_index++) { + XmpTag *xmp_tag; + + xmp_tag = g_ptr_array_index (xmp_tag_array, tag_index); + string_open_tag (data, xmp_tag->tag_name); + + /* fast path for single valued tag */ + if (ct == 1 || xmp_tag->type == GST_XMP_TAG_TYPE_SIMPLE) { + if (xmp_tag->serialize) { + s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, 0)); + } else { + s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag, + 0)); + } + if (s) { + g_string_append (data, s); + g_free (s); + } else { + GST_WARNING ("unhandled type for %s to xmp", tag); + } + } else { + const gchar *typename; + + typename = xmp_tag_get_type_name (xmp_tag); + + string_open_tag (data, typename); + for (i = 0; i < ct; i++) { + GST_DEBUG ("mapping %s[%u/%u] to xmp", tag, i, ct); + if (xmp_tag->serialize) { + s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, i)); + } else { + s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag, + i)); + } + if (s) { + string_open_tag (data, "rdf:li"); + g_string_append (data, s); + string_close_tag (data, "rdf:li"); + g_free (s); + } else { + GST_WARNING ("unhandled type for %s to xmp", tag); + } + } + string_close_tag (data, typename); + } + + string_close_tag (data, xmp_tag->tag_name); + } +} + +/** + * gst_tag_list_to_xmp_buffer_full: + * @list: tags + * @read_only: does the container forbid inplace editing + * @schemas: %NULL terminated array of schemas to be used on serialization + * + * Formats a taglist as a xmp packet using only the selected + * schemas. An empty list (%NULL) means that all schemas should + * be used + * + * Returns: new buffer or %NULL, unref the buffer when done + * + * Since: 0.10.33 + */ +GstBuffer * +gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only, + const gchar ** schemas) +{ + GstBuffer *buffer = NULL; + XmpSerializationData serialization_data; + GString *data; + guint i; + + serialization_data.data = g_string_sized_new (4096); + serialization_data.schemas = schemas; + data = serialization_data.data; + + xmp_tags_initialize (); + + g_return_val_if_fail (GST_IS_TAG_LIST (list), NULL); + + /* xmp header */ + g_string_append (data, + "\n"); + g_string_append (data, + "\n"); + g_string_append (data, + "\n"); + g_string_append (data, "\n"); + + /* iterate the taglist */ + gst_tag_list_foreach (list, write_one_tag, &serialization_data); + + /* xmp footer */ + g_string_append (data, "\n"); + g_string_append (data, "\n"); + g_string_append (data, "\n"); + + if (!read_only) { + /* the xmp spec recommand to add 2-4KB padding for in-place editable xmp */ + guint i; + + for (i = 0; i < 32; i++) { + g_string_append (data, " " " " + " " " " "\n"); + } + } + g_string_append_printf (data, "\n", + (read_only ? 'r' : 'w')); + + buffer = gst_buffer_new (); + GST_BUFFER_SIZE (buffer) = data->len + 1; + GST_BUFFER_DATA (buffer) = (guint8 *) g_string_free (data, FALSE); + GST_BUFFER_MALLOCDATA (buffer) = GST_BUFFER_DATA (buffer); + + return buffer; +} + +/** + * gst_tag_list_to_xmp_buffer: + * @list: tags + * @read_only: does the container forbid inplace editing + * + * Formats a taglist as a xmp packet. + * + * Returns: new buffer or %NULL, unref the buffer when done + * + * Since: 0.10.29 + */ +GstBuffer * +gst_tag_list_to_xmp_buffer (const GstTagList * list, gboolean read_only) +{ + return gst_tag_list_to_xmp_buffer_full (list, read_only, NULL); +} + +#undef gst_xmp_schema_lookup +#undef gst_xmp_schema_insert diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang-tables.dat b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang-tables.dat new file mode 100644 index 0000000..3367f70 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang-tables.dat @@ -0,0 +1,447 @@ +/* generated by mklangtables.c iso-codes 3.15 */ + +#include + +#define ISO_639_FLAG_2T (1 << 0) +#define ISO_639_FLAG_2B (1 << 1) + +/* *INDENT-OFF* */ + +static const struct +{ + const gchar iso_639_1[3]; + const gchar iso_639_2[4]; + guint8 flags; + guint16 name_offset; +} iso_639_codes[] = { + /* Afar */ + { "aa", "aar", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 0 }, + /* Abkhazian */ + { "ab", "abk", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 5 }, + /* Avestan */ + { "ae", "ave", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 15 }, + /* Afrikaans */ + { "af", "afr", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 23 }, + /* Akan */ + { "ak", "aka", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 33 }, + /* Amharic */ + { "am", "amh", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 38 }, + /* Aragonese */ + { "an", "arg", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 46 }, + /* Arabic */ + { "ar", "ara", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 56 }, + /* Assamese */ + { "as", "asm", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 63 }, + /* Avaric */ + { "av", "ava", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 72 }, + /* Aymara */ + { "ay", "aym", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 79 }, + /* Azerbaijani */ + { "az", "aze", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 86 }, + /* Bashkir */ + { "ba", "bak", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 98 }, + /* Belarusian */ + { "be", "bel", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 106 }, + /* Bulgarian */ + { "bg", "bul", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 117 }, + /* Bihari languages */ + { "bh", "bih", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 127 }, + /* Bislama */ + { "bi", "bis", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 144 }, + /* Bambara */ + { "bm", "bam", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 152 }, + /* Bengali */ + { "bn", "ben", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 160 }, + /* Tibetan */ + { "bo", "bod", ISO_639_FLAG_2T, 168 }, + { "bo", "tib", ISO_639_FLAG_2B, 168 }, + /* Breton */ + { "br", "bre", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 176 }, + /* Bosnian */ + { "bs", "bos", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 183 }, + /* Catalan; Valencian */ + { "ca", "cat", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 191 }, + /* Chechen */ + { "ce", "che", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 210 }, + /* Chamorro */ + { "ch", "cha", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 218 }, + /* Corsican */ + { "co", "cos", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 227 }, + /* Cree */ + { "cr", "cre", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 236 }, + /* Czech */ + { "cs", "ces", ISO_639_FLAG_2T, 241 }, + { "cs", "cze", ISO_639_FLAG_2B, 241 }, + /* Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic */ + { "cu", "chu", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 247 }, + /* Chuvash */ + { "cv", "chv", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 328 }, + /* Welsh */ + { "cy", "cym", ISO_639_FLAG_2T, 336 }, + { "cy", "wel", ISO_639_FLAG_2B, 336 }, + /* Danish */ + { "da", "dan", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 342 }, + /* German */ + { "de", "deu", ISO_639_FLAG_2T, 349 }, + { "de", "ger", ISO_639_FLAG_2B, 349 }, + /* Divehi; Dhivehi; Maldivian */ + { "dv", "div", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 356 }, + /* Dzongkha */ + { "dz", "dzo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 383 }, + /* Ewe */ + { "ee", "ewe", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 392 }, + /* Greek, Modern (1453-) */ + { "el", "ell", ISO_639_FLAG_2T, 396 }, + { "el", "gre", ISO_639_FLAG_2B, 396 }, + /* English */ + { "en", "eng", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 418 }, + /* Esperanto */ + { "eo", "epo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 426 }, + /* Spanish; Castilian */ + { "es", "spa", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 436 }, + /* Estonian */ + { "et", "est", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 455 }, + /* Basque */ + { "eu", "eus", ISO_639_FLAG_2T, 464 }, + { "eu", "baq", ISO_639_FLAG_2B, 464 }, + /* Persian */ + { "fa", "fas", ISO_639_FLAG_2T, 471 }, + { "fa", "per", ISO_639_FLAG_2B, 471 }, + /* Fulah */ + { "ff", "ful", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 479 }, + /* Finnish */ + { "fi", "fin", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 485 }, + /* Fijian */ + { "fj", "fij", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 493 }, + /* Faroese */ + { "fo", "fao", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 500 }, + /* French */ + { "fr", "fra", ISO_639_FLAG_2T, 508 }, + { "fr", "fre", ISO_639_FLAG_2B, 508 }, + /* Western Frisian */ + { "fy", "fry", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 515 }, + /* Irish */ + { "ga", "gle", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 531 }, + /* Gaelic; Scottish Gaelic */ + { "gd", "gla", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 537 }, + /* Galician */ + { "gl", "glg", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 561 }, + /* Guarani */ + { "gn", "grn", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 570 }, + /* Gujarati */ + { "gu", "guj", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 578 }, + /* Manx */ + { "gv", "glv", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 587 }, + /* Hausa */ + { "ha", "hau", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 592 }, + /* Hebrew */ + { "he", "heb", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 598 }, + /* Hindi */ + { "hi", "hin", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 605 }, + /* Hiri Motu */ + { "ho", "hmo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 611 }, + /* Croatian */ + { "hr", "hrv", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 621 }, + /* Haitian; Haitian Creole */ + { "ht", "hat", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 630 }, + /* Hungarian */ + { "hu", "hun", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 654 }, + /* Armenian */ + { "hy", "hye", ISO_639_FLAG_2T, 664 }, + { "hy", "arm", ISO_639_FLAG_2B, 664 }, + /* Herero */ + { "hz", "her", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 673 }, + /* Interlingua (International Auxiliary Language Association) */ + { "ia", "ina", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 680 }, + /* Indonesian */ + { "id", "ind", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 739 }, + /* Interlingue; Occidental */ + { "ie", "ile", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 750 }, + /* Igbo */ + { "ig", "ibo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 774 }, + /* Sichuan Yi; Nuosu */ + { "ii", "iii", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 779 }, + /* Inupiaq */ + { "ik", "ipk", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 797 }, + /* Ido */ + { "io", "ido", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 805 }, + /* Icelandic */ + { "is", "isl", ISO_639_FLAG_2T, 809 }, + { "is", "ice", ISO_639_FLAG_2B, 809 }, + /* Italian */ + { "it", "ita", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 819 }, + /* Inuktitut */ + { "iu", "iku", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 827 }, + /* Japanese */ + { "ja", "jpn", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 837 }, + /* Javanese */ + { "jv", "jav", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 846 }, + /* Georgian */ + { "ka", "kat", ISO_639_FLAG_2T, 855 }, + { "ka", "geo", ISO_639_FLAG_2B, 855 }, + /* Kongo */ + { "kg", "kon", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 864 }, + /* Kikuyu; Gikuyu */ + { "ki", "kik", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 870 }, + /* Kuanyama; Kwanyama */ + { "kj", "kua", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 885 }, + /* Kazakh */ + { "kk", "kaz", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 904 }, + /* Kalaallisut; Greenlandic */ + { "kl", "kal", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 911 }, + /* Central Khmer */ + { "km", "khm", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 936 }, + /* Kannada */ + { "kn", "kan", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 950 }, + /* Korean */ + { "ko", "kor", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 958 }, + /* Kanuri */ + { "kr", "kau", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 965 }, + /* Kashmiri */ + { "ks", "kas", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 972 }, + /* Kurdish */ + { "ku", "kur", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 981 }, + /* Komi */ + { "kv", "kom", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 989 }, + /* Cornish */ + { "kw", "cor", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 994 }, + /* Kirghiz; Kyrgyz */ + { "ky", "kir", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1002 }, + /* Latin */ + { "la", "lat", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1018 }, + /* Luxembourgish; Letzeburgesch */ + { "lb", "ltz", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1024 }, + /* Ganda */ + { "lg", "lug", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1053 }, + /* Limburgan; Limburger; Limburgish */ + { "li", "lim", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1059 }, + /* Lingala */ + { "ln", "lin", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1092 }, + /* Lao */ + { "lo", "lao", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1100 }, + /* Lithuanian */ + { "lt", "lit", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1104 }, + /* Luba-Katanga */ + { "lu", "lub", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1115 }, + /* Latvian */ + { "lv", "lav", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1128 }, + /* Malagasy */ + { "mg", "mlg", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1136 }, + /* Marshallese */ + { "mh", "mah", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1145 }, + /* Maori */ + { "mi", "mri", ISO_639_FLAG_2T, 1157 }, + { "mi", "mao", ISO_639_FLAG_2B, 1157 }, + /* Macedonian */ + { "mk", "mkd", ISO_639_FLAG_2T, 1163 }, + { "mk", "mac", ISO_639_FLAG_2B, 1163 }, + /* Malayalam */ + { "ml", "mal", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1174 }, + /* Mongolian */ + { "mn", "mon", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1184 }, + /* Moldavian; Moldovan */ + { "mo", "mol", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1194 }, + /* Marathi */ + { "mr", "mar", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1214 }, + /* Malay */ + { "ms", "msa", ISO_639_FLAG_2T, 1222 }, + { "ms", "may", ISO_639_FLAG_2B, 1222 }, + /* Maltese */ + { "mt", "mlt", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1228 }, + /* Burmese */ + { "my", "mya", ISO_639_FLAG_2T, 1236 }, + { "my", "bur", ISO_639_FLAG_2B, 1236 }, + /* Nauru */ + { "na", "nau", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1244 }, + /* Bokm?l, Norwegian; Norwegian Bokm?l */ + { "nb", "nob", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1250 }, + /* Ndebele, North; North Ndebele */ + { "nd", "nde", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1288 }, + /* Nepali */ + { "ne", "nep", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1318 }, + /* Ndonga */ + { "ng", "ndo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1325 }, + /* Dutch; Flemish */ + { "nl", "nld", ISO_639_FLAG_2T, 1332 }, + { "nl", "dut", ISO_639_FLAG_2B, 1332 }, + /* Norwegian Nynorsk; Nynorsk, Norwegian */ + { "nn", "nno", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1347 }, + /* Norwegian */ + { "no", "nor", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1385 }, + /* Ndebele, South; South Ndebele */ + { "nr", "nbl", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1395 }, + /* Navajo; Navaho */ + { "nv", "nav", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1425 }, + /* Chichewa; Chewa; Nyanja */ + { "ny", "nya", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1440 }, + /* Occitan (post 1500) */ + { "oc", "oci", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1464 }, + /* Ojibwa */ + { "oj", "oji", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1484 }, + /* Oromo */ + { "om", "orm", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1491 }, + /* Oriya */ + { "or", "ori", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1497 }, + /* Ossetian; Ossetic */ + { "os", "oss", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1503 }, + /* Panjabi; Punjabi */ + { "pa", "pan", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1521 }, + /* Pali */ + { "pi", "pli", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1538 }, + /* Polish */ + { "pl", "pol", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1543 }, + /* Pushto; Pashto */ + { "ps", "pus", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1550 }, + /* Portuguese */ + { "pt", "por", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1565 }, + /* Quechua */ + { "qu", "que", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1576 }, + /* Romansh */ + { "rm", "roh", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1584 }, + /* Rundi */ + { "rn", "run", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1592 }, + /* Romanian */ + { "ro", "ron", ISO_639_FLAG_2T, 1598 }, + { "ro", "rum", ISO_639_FLAG_2B, 1598 }, + /* Russian */ + { "ru", "rus", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1607 }, + /* Kinyarwanda */ + { "rw", "kin", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1615 }, + /* Sanskrit */ + { "sa", "san", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1627 }, + /* Sardinian */ + { "sc", "srd", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1636 }, + /* Sindhi */ + { "sd", "snd", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1646 }, + /* Northern Sami */ + { "se", "sme", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1653 }, + /* Sango */ + { "sg", "sag", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1667 }, + /* Sinhala; Sinhalese */ + { "si", "sin", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1673 }, + /* Slovak */ + { "sk", "slk", ISO_639_FLAG_2T, 1692 }, + { "sk", "slo", ISO_639_FLAG_2B, 1692 }, + /* Slovenian */ + { "sl", "slv", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1699 }, + /* Samoan */ + { "sm", "smo", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1709 }, + /* Shona */ + { "sn", "sna", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1716 }, + /* Somali */ + { "so", "som", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1722 }, + /* Albanian */ + { "sq", "sqi", ISO_639_FLAG_2T, 1729 }, + { "sq", "alb", ISO_639_FLAG_2B, 1729 }, + /* Serbian */ + { "sr", "srp", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1738 }, + /* Swati */ + { "ss", "ssw", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1746 }, + /* Sotho, Southern */ + { "st", "sot", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1752 }, + /* Sundanese */ + { "su", "sun", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1768 }, + /* Swedish */ + { "sv", "swe", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1778 }, + /* Swahili */ + { "sw", "swa", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1786 }, + /* Tamil */ + { "ta", "tam", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1794 }, + /* Telugu */ + { "te", "tel", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1800 }, + /* Tajik */ + { "tg", "tgk", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1807 }, + /* Thai */ + { "th", "tha", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1813 }, + /* Tigrinya */ + { "ti", "tir", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1818 }, + /* Turkmen */ + { "tk", "tuk", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1827 }, + /* Tagalog */ + { "tl", "tgl", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1835 }, + /* Tswana */ + { "tn", "tsn", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1843 }, + /* Tonga (Tonga Islands) */ + { "to", "ton", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1850 }, + /* Turkish */ + { "tr", "tur", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1872 }, + /* Tsonga */ + { "ts", "tso", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1880 }, + /* Tatar */ + { "tt", "tat", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1887 }, + /* Twi */ + { "tw", "twi", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1893 }, + /* Tahitian */ + { "ty", "tah", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1897 }, + /* Uighur; Uyghur */ + { "ug", "uig", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1906 }, + /* Ukrainian */ + { "uk", "ukr", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1921 }, + /* Urdu */ + { "ur", "urd", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1931 }, + /* Uzbek */ + { "uz", "uzb", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1936 }, + /* Venda */ + { "ve", "ven", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1942 }, + /* Vietnamese */ + { "vi", "vie", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1948 }, + /* Volap?k */ + { "vo", "vol", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1959 }, + /* Walloon */ + { "wa", "wln", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1968 }, + /* Wolof */ + { "wo", "wol", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1976 }, + /* Xhosa */ + { "xh", "xho", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1982 }, + /* Yiddish */ + { "yi", "yid", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1988 }, + /* Yoruba */ + { "yo", "yor", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 1996 }, + /* Zhuang; Chuang */ + { "za", "zha", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 2003 }, + /* Chinese */ + { "zh", "zho", ISO_639_FLAG_2T, 2018 }, + { "zh", "chi", ISO_639_FLAG_2B, 2018 }, + /* Zulu */ + { "zu", "zul", ISO_639_FLAG_2T | ISO_639_FLAG_2B, 2026 }, +}; + +static const gchar iso_639_names[] = + "Afar\000Abkhazian\000Avestan\000Afrikaans\000Akan\000Amharic\000Aragonese" + "\000Arabic\000Assamese\000Avaric\000Aymara\000Azerbaijani\000Bashkir\000B" + "elarusian\000Bulgarian\000Bihari languages\000Bislama\000Bambara\000Benga" + "li\000Tibetan\000Breton\000Bosnian\000Catalan; Valencian\000Chechen\000Ch" + "amorro\000Corsican\000Cree\000Czech\000Church Slavic; Old Slavonic; Churc" + "h Slavonic; Old Bulgarian; Old Church Slavonic\000Chuvash\000Welsh\000Dan" + "ish\000German\000Divehi; Dhivehi; Maldivian\000Dzongkha\000Ewe\000Greek, " + "Modern (1453-)\000English\000Esperanto\000Spanish; Castilian\000Estonian" + "\000Basque\000Persian\000Fulah\000Finnish\000Fijian\000Faroese\000French" + "\000Western Frisian\000Irish\000Gaelic; Scottish Gaelic\000Galician\000Gu" + "arani\000Gujarati\000Manx\000Hausa\000Hebrew\000Hindi\000Hiri Motu\000Cro" + "atian\000Haitian; Haitian Creole\000Hungarian\000Armenian\000Herero\000In" + "terlingua (International Auxiliary Language Association)\000Indonesian" + "\000Interlingue; Occidental\000Igbo\000Sichuan Yi; Nuosu\000Inupiaq\000Id" + "o\000Icelandic\000Italian\000Inuktitut\000Japanese\000Javanese\000Georgia" + "n\000Kongo\000Kikuyu; Gikuyu\000Kuanyama; Kwanyama\000Kazakh\000Kalaallis" + "ut; Greenlandic\000Central Khmer\000Kannada\000Korean\000Kanuri\000Kashmi" + "ri\000Kurdish\000Komi\000Cornish\000Kirghiz; Kyrgyz\000Latin\000Luxembour" + "gish; Letzeburgesch\000Ganda\000Limburgan; Limburger; Limburgish\000Linga" + "la\000Lao\000Lithuanian\000Luba-Katanga\000Latvian\000Malagasy\000Marshal" + "lese\000Maori\000Macedonian\000Malayalam\000Mongolian\000Moldavian; Moldo" + "van\000Marathi\000Malay\000Maltese\000Burmese\000Nauru\000Bokm\303\245l, " + "Norwegian; Norwegian Bokm\303\245l\000Ndebele, North; North Ndebele\000Ne" + "pali\000Ndonga\000Dutch; Flemish\000Norwegian Nynorsk; Nynorsk, Norwegian" + "\000Norwegian\000Ndebele, South; South Ndebele\000Navajo; Navaho\000Chich" + "ewa; Chewa; Nyanja\000Occitan (post 1500)\000Ojibwa\000Oromo\000Oriya\000" + "Ossetian; Ossetic\000Panjabi; Punjabi\000Pali\000Polish\000Pushto; Pashto" + "\000Portuguese\000Quechua\000Romansh\000Rundi\000Romanian\000Russian\000K" + "inyarwanda\000Sanskrit\000Sardinian\000Sindhi\000Northern Sami\000Sango" + "\000Sinhala; Sinhalese\000Slovak\000Slovenian\000Samoan\000Shona\000Somal" + "i\000Albanian\000Serbian\000Swati\000Sotho, Southern\000Sundanese\000Swed" + "ish\000Swahili\000Tamil\000Telugu\000Tajik\000Thai\000Tigrinya\000Turkmen" + "\000Tagalog\000Tswana\000Tonga (Tonga Islands)\000Turkish\000Tsonga\000Ta" + "tar\000Twi\000Tahitian\000Uighur; Uyghur\000Ukrainian\000Urdu\000Uzbek" + "\000Venda\000Vietnamese\000Volap\303\274k\000Walloon\000Wolof\000Xhosa" + "\000Yiddish\000Yoruba\000Zhuang; Chuang\000Chinese\000Zulu"; + +/* *INDENT-ON* */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang.c new file mode 100644 index 0000000..3520383 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/lang.c @@ -0,0 +1,494 @@ +/* GStreamer language codes and names utility functions + * Copyright (C) 2009 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gsttaglanguagecodes + * @short_description: mappings for ISO-639 language codes and names + * @see_also: #GstTagList + * + * + * + * Provides helper functions to convert between the various ISO-639 language + * codes, and to map language codes to language names. + * + * + */ + +/* FIXME 0.11: maybe switch to ISO-639-2 everywhere incl. GST_TAG_LANGUAGE? */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#undef GETTEXT_PACKAGE +#define GETTEXT_PACKAGE "iso_639" + +#define ISO_639_XML_PATH ISO_CODES_PREFIX "/share/xml/iso-codes/iso_639.xml" +#define ISO_CODES_LOCALEDIR ISO_CODES_PREFIX "/share/locale" + +#include +#include + +#include +#include + +#include "tag.h" +#include "lang-tables.dat" + +#ifndef GST_DISABLE_GST_DEBUG + +#define GST_CAT_DEFAULT ensure_debug_category() + +static GstDebugCategory * +ensure_debug_category (void) +{ + static gsize cat_gonce = 0; + + if (g_once_init_enter (&cat_gonce)) { + gsize cat_done; + + cat_done = (gsize) _gst_debug_category_new ("tag-langcodes", 0, + "GstTag language codes and names"); + + g_once_init_leave (&cat_gonce, cat_done); + } + + return (GstDebugCategory *) cat_gonce; +} + +#else + +#define ensure_debug_category() /* NOOP */ + +#endif /* GST_DISABLE_GST_DEBUG */ + +/* ------------------------------------------------------------------------- */ + +/* Loading and initing */ + +#if defined(HAVE_ISO_CODES) +static const gchar * +get_val (const gchar ** names, const gchar ** vals, const gchar * name) +{ + while (names != NULL && *names != NULL) { + if (strcmp (*names, name) == 0) + return *vals; + ++names; + ++vals; + } + return NULL; +} + +static void +parse_start_element (GMarkupParseContext * ctx, const gchar * element_name, + const gchar ** attr_names, const gchar ** attr_vals, + gpointer user_data, GError ** error) +{ + GHashTable *ht = (GHashTable *) user_data; + const gchar *c1, *c2t, *c2b, *name, *tname; + + if (strcmp (element_name, "iso_639_entry") != 0) + return; + + c1 = get_val (attr_names, attr_vals, "iso_639_1_code"); + + /* only interested in languages with an ISO 639-1 code for now */ + if (c1 == NULL) + return; + + c2t = get_val (attr_names, attr_vals, "iso_639_2T_code"); + c2b = get_val (attr_names, attr_vals, "iso_639_2B_code"); + name = get_val (attr_names, attr_vals, "name"); + + if (c2t == NULL || c2b == NULL || name == NULL) { + GST_WARNING ("broken iso_639.xml entry: c2t=%p, c2b=%p, name=%p", c2t, + c2b, name); + return; + } + + /* translate language name */ + tname = _(name); + + /* if no translation was found, it will return the input string, which we + * we don't want to put into the hash table because it will be freed again */ + if (G_UNLIKELY (tname == name)) + tname = g_intern_string (name); + + /* now overwrite default/fallback mappings with names in locale language */ + g_hash_table_replace (ht, (gpointer) g_intern_string (c1), (gpointer) tname); + g_hash_table_replace (ht, (gpointer) g_intern_string (c2b), (gpointer) tname); + if (strcmp (c2t, c2b) != 0) { + g_hash_table_replace (ht, (gpointer) g_intern_string (c2t), + (gpointer) tname); + } + + GST_LOG ("%s %s %s : %s - %s", c1, c2t, c2b, name, tname); +} + +static void +gst_tag_load_iso_639_xml (GHashTable * ht) +{ + GMappedFile *f; + GError *err = NULL; + gchar *xml_data; + gsize xml_len; + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + ISO_CODES_LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, ISO_CODES_LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + f = g_mapped_file_new (ISO_639_XML_PATH, FALSE, NULL); + if (f != NULL) { + xml_data = (gchar *) g_mapped_file_get_contents (f); + xml_len = g_mapped_file_get_length (f); + } else { + if (!g_file_get_contents (ISO_639_XML_PATH, &xml_data, &xml_len, &err)) { + GST_WARNING ("Could not read %s: %s", ISO_639_XML_PATH, err->message); + g_error_free (err); + return; + } + } + + if (g_utf8_validate (xml_data, xml_len, NULL)) { + GMarkupParser xml_parser = { parse_start_element, NULL, NULL, NULL, NULL }; + GMarkupParseContext *ctx; + + ctx = g_markup_parse_context_new (&xml_parser, 0, ht, NULL); + if (!g_markup_parse_context_parse (ctx, xml_data, xml_len, &err)) { + GST_WARNING ("Parsing iso_639.xml failed: %s", err->message); + g_error_free (err); + } + g_markup_parse_context_free (ctx); + } else { + GST_WARNING ("iso_639.xml file is not valid UTF-8"); + GST_MEMDUMP ("iso_639.xml file", (guint8 *) xml_data, xml_len); + } + + /* ... and clean up */ + if (f != NULL) + g_mapped_file_unref (f); + else + g_free (xml_data); +} +#endif /* HAVE_ISO_CODES */ + +static GHashTable * +gst_tag_get_iso_639_ht (void) +{ + static gsize once_val = 0; + int i; + + if (g_once_init_enter (&once_val)) { + GHashTable *ht; + gsize done_val; + + GST_MEMDUMP ("iso 639 language names (internal default/fallback)", + (guint8 *) iso_639_names, sizeof (iso_639_names)); + + /* maps code -> language name; all strings are either interned strings + * or const static strings from lang-table.c */ + ht = g_hash_table_new (g_str_hash, g_str_equal); + + /* set up default/fallback mappings */ + for (i = 0; i < G_N_ELEMENTS (iso_639_codes); ++i) { + GST_LOG ("%3d %s %s %c%c 0x%04x %s", i, iso_639_codes[i].iso_639_1, + iso_639_codes[i].iso_639_2, + ((iso_639_codes[i].flags & ISO_639_FLAG_2B)) ? 'B' : '.', + ((iso_639_codes[i].flags & ISO_639_FLAG_2T)) ? 'T' : '.', + iso_639_codes[i].name_offset, + iso_639_names + iso_639_codes[i].name_offset); + +#ifdef HAVE_ISO_CODES + /* intern these in order to minimise allocations when interning strings + * read from the xml file later */ + g_intern_static_string (iso_639_codes[i].iso_639_1); + g_intern_static_string (iso_639_codes[i].iso_639_2); + g_intern_static_string (iso_639_names + iso_639_codes[i].name_offset); +#endif + + /* and add default mapping (these strings are always valid) */ + g_hash_table_insert (ht, (gpointer) iso_639_codes[i].iso_639_1, + (gpointer) (iso_639_names + iso_639_codes[i].name_offset)); + g_hash_table_insert (ht, (gpointer) iso_639_codes[i].iso_639_2, + (gpointer) (iso_639_names + iso_639_codes[i].name_offset)); + } + +#ifdef HAVE_ISO_CODES + { + GstClockTime ts = gst_util_get_timestamp (); + + gst_tag_load_iso_639_xml (ht); + + ts = gst_util_get_timestamp () - ts; + GST_INFO ("iso_639.xml loading took %.2gms", (double) ts / GST_MSECOND); + } +#else + GST_INFO ("iso-codes disabled or not available"); +#endif + + done_val = (gsize) ht; + g_once_init_leave (&once_val, done_val); + } + + return (GHashTable *) once_val; +} + +/* ------------------------------------------------------------------------- */ + +static int +qsort_strcmp_func (const void *p1, const void *p2) +{ + return strcmp (*(char *const *) p1, *(char *const *) p2); +} + +/** + * gst_tag_get_language_codes: + * + * Returns a list of known language codes (in form of two-letter ISO-639-1 + * codes). This is useful for UIs to build a list of available languages for + * tagging purposes (e.g. to tag an audio track appropriately in a video or + * audio editor). + * + * Returns: NULL-terminated string array with two-letter language codes. Free + * with g_strfreev() when no longer needed. + * + * Since: 0.10.26 + */ +gchar ** +gst_tag_get_language_codes (void) +{ + GHashTableIter iter; + GHashTable *ht; + gpointer key; + gchar **codes; + int i; + + ensure_debug_category (); + + ht = gst_tag_get_iso_639_ht (); + + /* we have at least two keys for each language (-1 code and -2 code) */ + codes = g_new (gchar *, (g_hash_table_size (ht) / 2) + 1); + + i = 0; + g_hash_table_iter_init (&iter, ht); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + const gchar *lang_code = key; + + if (strlen (lang_code) == 2) { + codes[i] = g_strdup (lang_code); + ++i; + } + } + codes[i] = NULL; + + /* be nice and sort the list */ + qsort (&codes[0], i, sizeof (gchar *), qsort_strcmp_func); + + return codes; +} + +/** + * gst_tag_get_language_name: + * @language_code: two or three-letter ISO-639 language code + * + * Returns the name of the language given an ISO-639 language code, such + * as often found in a GST_TAG_LANGUAGE tag. The name will be translated + * according to the current locale (if the library was built against the + * iso-codes package, otherwise the English name will be returned). + * + * Language codes are case-sensitive and expected to be lower case. + * + * Returns: language name in UTF-8 format, or NULL if @language_code could + * not be mapped to a language name. The returned string must not be + * modified and does not need to freed; it will stay valid until the + * application is terminated. + * + * Since: 0.10.26 + */ +const gchar * +gst_tag_get_language_name (const gchar * language_code) +{ + const gchar *lang_name; + GHashTable *ht; + + g_return_val_if_fail (language_code != NULL, NULL); + + ensure_debug_category (); + + ht = gst_tag_get_iso_639_ht (); + + lang_name = g_hash_table_lookup (ht, (gpointer) language_code); + GST_LOG ("%s -> %s", language_code, GST_STR_NULL (lang_name)); + + return lang_name; +} + +/** + * gst_tag_get_language_code_iso_639_1: + * @lang_code: ISO-639 language code (e.g. "deu" or "ger" or "de") + * + * Returns two-letter ISO-639-1 language code given a three-letter ISO-639-2 + * language code or two-letter ISO-639-1 language code (both are accepted for + * convenience). + * + * Language codes are case-sensitive and expected to be lower case. + * + * Returns: two-letter ISO-639-1 language code string that maps to @lang_code, + * or NULL if no mapping is known. The returned string must not be + * modified or freed. + * + * Since: 0.10.26 + */ +const gchar * +gst_tag_get_language_code_iso_639_1 (const gchar * lang_code) +{ + const gchar *c = NULL; + int i; + + g_return_val_if_fail (lang_code != NULL, NULL); + + ensure_debug_category (); + + /* FIXME: we are being a bit inconsistent here in the sense that will only + * map the language codes from our static table. Theoretically the iso-codes + * XML file might have had additional codes that are now in the hash table. + * We keep it simple for now and don't waste memory on additional tables. */ + for (i = 0; i < G_N_ELEMENTS (iso_639_codes); ++i) { + /* we check both codes here, so function can be used in a more versatile + * way, to convert a language tag to a two-letter language code and/or + * verify an existing code */ + if (strcmp (lang_code, iso_639_codes[i].iso_639_1) == 0 || + strcmp (lang_code, iso_639_codes[i].iso_639_2) == 0) { + c = iso_639_codes[i].iso_639_1; + break; + } + } + + GST_LOG ("%s -> %s", lang_code, GST_STR_NULL (c)); + + return c; +} + +static const gchar * +gst_tag_get_language_code_iso_639_2X (const gchar * lang_code, guint8 flags) +{ + int i; + + /* FIXME: we are being a bit inconsistent here in the sense that we will only + * map the language codes from our static table. Theoretically the iso-codes + * XML file might have had additional codes that are now in the hash table. + * We keep it simple for now and don't waste memory on additional tables. + * Also, we currently only parse the iso_639.xml file if language names or + * a list of all codes is requested, and it'd be nice to keep it like that. */ + for (i = 0; i < G_N_ELEMENTS (iso_639_codes); ++i) { + /* we check both codes here, so function can be used in a more versatile + * way, to convert a language tag to a three-letter language code and/or + * verify an existing code */ + if (strcmp (lang_code, iso_639_codes[i].iso_639_1) == 0 || + strcmp (lang_code, iso_639_codes[i].iso_639_2) == 0) { + if ((iso_639_codes[i].flags & flags) == flags) { + return iso_639_codes[i].iso_639_2; + } else if (i > 0 && (iso_639_codes[i - 1].flags & flags) == flags && + iso_639_codes[i].name_offset == iso_639_codes[i - 1].name_offset) { + return iso_639_codes[i - 1].iso_639_2; + } else if (i < G_N_ELEMENTS (iso_639_codes) && + (iso_639_codes[i + 1].flags & flags) == flags && + iso_639_codes[i].name_offset == iso_639_codes[i + 1].name_offset) { + return iso_639_codes[i + 1].iso_639_2; + } + } + } + return NULL; +} + +/** + * gst_tag_get_language_code_iso_639_2T: + * @lang_code: ISO-639 language code (e.g. "deu" or "ger" or "de") + * + * Returns three-letter ISO-639-2 "terminological" language code given a + * two-letter ISO-639-1 language code or a three-letter ISO-639-2 language + * code (both are accepted for convenience). + * + * The "terminological" code is derived from the local name of the language + * (e.g. "deu" for German instead of "ger"). In most scenarios, the + * "terminological" codes are prefered over the "bibliographic" ones. + * + * Language codes are case-sensitive and expected to be lower case. + * + * Returns: three-letter ISO-639-2 language code string that maps to @lang_code, + * or NULL if no mapping is known. The returned string must not be + * modified or freed. + * + * Since: 0.10.26 + */ +const gchar * +gst_tag_get_language_code_iso_639_2T (const gchar * lang_code) +{ + const gchar *c; + + g_return_val_if_fail (lang_code != NULL, NULL); + + ensure_debug_category (); + + c = gst_tag_get_language_code_iso_639_2X (lang_code, ISO_639_FLAG_2T); + + GST_LOG ("%s -> %s", lang_code, GST_STR_NULL (c)); + + return c; +} + +/** + * gst_tag_get_language_code_iso_639_2B: + * @lang_code: ISO-639 language code (e.g. "deu" or "ger" or "de") + * + * Returns three-letter ISO-639-2 "bibliographic" language code given a + * two-letter ISO-639-1 language code or a three-letter ISO-639-2 language + * code (both are accepted for convenience). + * + * The "bibliographic" code is derived from the English name of the language + * (e.g. "ger" for German instead of "de" or "deu"). In most scenarios, the + * "terminological" codes are prefered. + * + * Language codes are case-sensitive and expected to be lower case. + * + * Returns: three-letter ISO-639-2 language code string that maps to @lang_code, + * or NULL if no mapping is known. The returned string must not be + * modified or freed. + * + * Since: 0.10.26 + */ +const gchar * +gst_tag_get_language_code_iso_639_2B (const gchar * lang_code) +{ + const gchar *c; + + g_return_val_if_fail (lang_code != NULL, NULL); + + ensure_debug_category (); + + c = gst_tag_get_language_code_iso_639_2X (lang_code, ISO_639_FLAG_2B); + + GST_LOG ("%s -> %s", lang_code, GST_STR_NULL (c)); + + return c; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/mklangtables.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/mklangtables.c new file mode 100644 index 0000000..3a6156f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/mklangtables.c @@ -0,0 +1,239 @@ +/* GStreamer Language Tag Utility Functions + * Copyright (C) 2009 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* mklangtables.c: + * little program that reads iso_639.xml and outputs tables for us as fallback + * for when iso-codes are not available or we fail to read the file for some + * reason, and so we don't have to parse the xml file just to map codes. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#define ISO_639_XML_PATH ISO_CODES_PREFIX "/share/xml/iso-codes/iso_639.xml" + +typedef struct +{ + gchar code_1[3]; /* de */ + gchar code_2t[4]; /* deu */ + gchar code_2b[4]; /* ger */ + const gchar *name; /* German */ + guint name_offset; /* offset into string table */ +} IsoLang; + +static GArray *languages = NULL; + +static void +dump_languages (void) +{ + GString *names; + const char *s; + int i, num_escaped; + + g_assert (languages != NULL); + + names = g_string_new (""); + + g_print ("/* generated by " __FILE__ " iso-codes " ISO_CODES_VERSION " */\n"); + g_print ("\n"); + g_print ("#include \n"); + g_print ("\n"); + g_print ("#define ISO_639_FLAG_2T (1 << 0)\n"); + g_print ("#define ISO_639_FLAG_2B (1 << 1)\n"); + g_print ("\n"); + g_print ("/* *INDENT-OFF* */\n"); + g_print ("\n"); + g_print ("static const struct\n"); + g_print ("{\n"); + g_print (" const gchar iso_639_1[3];\n"); + g_print (" const gchar iso_639_2[4];\n"); + g_print (" guint8 flags;\n"); + g_print (" guint16 name_offset;\n"); + g_print ("} iso_639_codes[] = {\n"); + + for (i = 0, num_escaped = 0; i < languages->len; ++i) { + IsoLang *lang = &g_array_index (languages, IsoLang, i); + + /* For now just print those where there's both a ISO-639-1 and -2 code */ + if (lang->code_1[0] == '\0') + continue; + + /* save current offset */ + lang->name_offset = names->len; + + /* adjust for fact that \000 is 4 chars now but will take up only 1 later */ + lang->name_offset -= num_escaped * 3; + + /* append one char at a time, making sure to escape UTF-8 characters */ + for (s = lang->name; s != NULL && *s != '\0'; ++s) { + if (g_ascii_isprint (*s) && *s != '"' && *s != '\\') { + g_string_append_c (names, *s); + } else { + g_string_append_printf (names, "\\%03o", (unsigned char) *s); + ++num_escaped; + } + } + g_string_append (names, "\\000"); + ++num_escaped; + + g_print (" /* %s */\n", lang->name); + if (strcmp (lang->code_2b, lang->code_2t) == 0) { + g_print (" { \"%s\", \"%s\", ISO_639_FLAG_2T | ISO_639_FLAG_2B, %u },\n", + lang->code_1, lang->code_2t, lang->name_offset); + } else { + /* if 639-2T and 639-2B differ, put 639-2T first */ + g_print (" { \"%s\", \"%s\", ISO_639_FLAG_2T, %u },\n", + lang->code_1, lang->code_2t, lang->name_offset); + g_print (" { \"%s\", \"%s\", ISO_639_FLAG_2B, %u },\n", + lang->code_1, lang->code_2b, lang->name_offset); + } + } + + g_print ("};\n"); + g_print ("\n"); + g_print ("static const gchar iso_639_names[] =\n"); + s = names->str; + while (s != NULL && *s != '\0') { + gchar line[74], *lastesc; + guint left; + + left = strlen (s); + g_strlcpy (line, s, MIN (left, sizeof (line))); + s += sizeof (line) - 1; + /* avoid partial escaped codes at the end of a line */ + if ((lastesc = strrchr (line, '\\')) && strlen (lastesc) < 4) { + s -= strlen (lastesc); + *lastesc = '\0'; + } + g_print (" \"%s\"", line); + if (left < 74) + break; + g_print ("\n"); + } + g_print (";\n"); + g_print ("\n"); + g_print ("/* *INDENT-ON* */\n"); + + g_string_free (names, TRUE); +} + +static gboolean +copy_attribute (gchar * dest, guint dest_len, const gchar ** attr_names, + const gchar ** attr_vals, const gchar * needle) +{ + while (attr_names != NULL && *attr_names != NULL) { + if (strcmp (*attr_names, needle) == 0) { + g_strlcpy (dest, *attr_vals, dest_len); + return TRUE; + } + ++attr_names; + ++attr_vals; + } + dest[0] = '\0'; + return FALSE; +} + +static void +xml_start_element (GMarkupParseContext * ctx, const gchar * element_name, + const gchar ** attr_names, const gchar ** attr_vals, + gpointer user_data, GError ** error) +{ + gchar name[256]; + IsoLang lang; + + if (strcmp (element_name, "iso_639_entry") != 0) + return; + + copy_attribute (lang.code_1, 3, attr_names, attr_vals, "iso_639_1_code"); + copy_attribute (lang.code_2t, 4, attr_names, attr_vals, "iso_639_2T_code"); + copy_attribute (lang.code_2b, 4, attr_names, attr_vals, "iso_639_2B_code"); + + copy_attribute (name, sizeof (name), attr_names, attr_vals, "name"); + lang.name = g_intern_string (name); + + g_array_append_val (languages, lang); +} + +static void +parse_iso_639_xml (const gchar * data, gsize len) +{ + GMarkupParser xml_parser = { xml_start_element, NULL, NULL, NULL, NULL }; + GMarkupParseContext *ctx; + GError *err = NULL; + + g_return_if_fail (g_utf8_validate (data, len, NULL)); + + ctx = g_markup_parse_context_new (&xml_parser, 0, NULL, NULL); + if (!g_markup_parse_context_parse (ctx, data, len, &err)) + g_error ("Parsing failed: %s", err->message); + + g_markup_parse_context_free (ctx); +} + +static gint +languages_sort_func (IsoLang * l1, IsoLang * l2) +{ + if (l1 == l2) + return 0; + + if (l1->code_1[0] == '\0' && l2->code_1[0] != '\0') + return -1; + + return strcmp (l1->code_1, l2->code_1); +} + +int +main (int argc, char **argv) +{ + GMappedFile *f; + gchar *xml_data; + gsize xml_len; + + f = g_mapped_file_new (ISO_639_XML_PATH, FALSE, NULL); + if (f != NULL) { + xml_data = (gchar *) g_mapped_file_get_contents (f); + xml_len = g_mapped_file_get_length (f); + } else { + GError *err = NULL; + + if (!g_file_get_contents (ISO_639_XML_PATH, &xml_data, &xml_len, &err)) + g_error ("Could not read %s: %s", ISO_639_XML_PATH, err->message); + } + + languages = g_array_new (FALSE, TRUE, sizeof (IsoLang)); + + parse_iso_639_xml (xml_data, xml_len); + + g_array_sort (languages, (GCompareFunc) languages_sort_func); + + dump_languages (); + + g_array_free (languages, TRUE); + + if (f != NULL) + g_mapped_file_unref (f); + else + g_free (xml_data); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tag.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tag.h new file mode 100644 index 0000000..219fe85 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tag.h @@ -0,0 +1,549 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TAG_TAG_H__ +#define __GST_TAG_TAG_H__ + +#include + +G_BEGIN_DECLS + +/* Tag names */ + +/** + * GST_TAG_MUSICBRAINZ_TRACKID + * + * MusicBrainz track ID + */ +#define GST_TAG_MUSICBRAINZ_TRACKID "musicbrainz-trackid" +/** + * GST_TAG_MUSICBRAINZ_ARTISTID + * + * MusicBrainz artist ID + */ +#define GST_TAG_MUSICBRAINZ_ARTISTID "musicbrainz-artistid" +/** + * GST_TAG_MUSICBRAINZ_ALBUMID + * + * MusicBrainz album ID + */ +#define GST_TAG_MUSICBRAINZ_ALBUMID "musicbrainz-albumid" +/** + * GST_TAG_MUSICBRAINZ_ALBUMARTISTID + * + * MusicBrainz album artist ID + */ +#define GST_TAG_MUSICBRAINZ_ALBUMARTISTID "musicbrainz-albumartistid" +/** + * GST_TAG_MUSICBRAINZ_TRMID + * + * MusicBrainz track TRM ID + */ +#define GST_TAG_MUSICBRAINZ_TRMID "musicbrainz-trmid" + +/* FIXME 0.11: remove GST_TAG_MUSICBRAINZ_SORTNAME */ +#ifndef GST_DISABLE_DEPRECATED +/** + * GST_TAG_MUSICBRAINZ_SORTNAME + * + * MusicBrainz artist sort name + * + * Deprecated. Use GST_TAG_ARTIST_SORTNAME instead. + */ +#define GST_TAG_MUSICBRAINZ_SORTNAME GST_TAG_ARTIST_SORTNAME +#endif + +/** + * GST_TAG_CMML_STREAM + * + * Annodex CMML stream element tag + */ +#define GST_TAG_CMML_STREAM "cmml-stream" +/** + * GST_TAG_CMML_HEAD + * + * Annodex CMML head element tag + */ + +#define GST_TAG_CMML_HEAD "cmml-head" +/** + * GST_TAG_CMML_CLIP + * + * Annodex CMML clip element tag + */ +#define GST_TAG_CMML_CLIP "cmml-clip" + +/* CDDA tags */ + +/** + * GST_TAG_CDDA_CDDB_DISCID: + * + * CDDB disc id in its short form (e.g. 'aa063d0f') + */ +#define GST_TAG_CDDA_CDDB_DISCID "discid" + +/** + * GST_TAG_CDDA_CDDB_DISCID_FULL: + * + * CDDB disc id including all details + */ +#define GST_TAG_CDDA_CDDB_DISCID_FULL "discid-full" + +/** + * GST_TAG_CDDA_MUSICBRAINZ_DISCID: + * + * Musicbrainz disc id (e.g. 'ahg7JUcfR3vCYBphSDIogOOWrr0-') + */ +#define GST_TAG_CDDA_MUSICBRAINZ_DISCID "musicbrainz-discid" + +/** + * GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL: + * + * Musicbrainz disc id details + */ +#define GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL "musicbrainz-discid-full" + +/** + * GST_TAG_CAPTURING_SHUTTER_SPEED: + * + * Shutter speed used when capturing an image, in seconds. (fraction) + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_SHUTTER_SPEED "capturing-shutter-speed" + +/** + * GST_TAG_CAPTURING_FOCAL_RATIO: + * + * Focal ratio (f-number) used when capturing an image. (double) + * + * The value stored is the denominator of the focal ratio (f-number). + * For example, if this tag value is 2, the focal ratio is f/2. + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_FOCAL_RATIO "capturing-focal-ratio" + +/** + * GST_TAG_CAPTURING_FOCAL_LENGTH: + * + * Focal length used when capturing an image, in mm. (double) + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_FOCAL_LENGTH "capturing-focal-length" + +/** + * GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO: + * + * Digital zoom ratio used when capturing an image. (double) + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO "capturing-digital-zoom-ratio" + +/** + * GST_TAG_CAPTURING_ISO_SPEED: + * + * ISO speed used when capturing an image. (integer) + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_ISO_SPEED "capturing-iso-speed" + +/** + * GST_TAG_CAPTURING_EXPOSURE_PROGRAM: + * + * Type of exposure control used when capturing an image. (string) + * + * The allowed values are: + * "undefined" + * "manual" + * "normal" - automatically controlled + * "aperture-priority" - user selects aperture value + * "shutter-priority" - user selects shutter speed + * "creative" - biased towards depth of field + * "action" - biased towards fast shutter speed + * "portrait" - closeup, leaving background out of focus + * "landscape" - landscape photos, background in focus + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_EXPOSURE_PROGRAM "capturing-exposure-program" + +/** + * GST_TAG_CAPTURING_EXPOSURE_MODE: + * + * Exposure mode used when capturing an image. (string) + * + * The allowed values are: + * "auto-exposure" + * "manual-exposure" + * "auto-bracket" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_EXPOSURE_MODE "capturing-exposure-mode" + +/** + * GST_TAG_CAPTURING_EXPOSURE_COMPENSATION: + * + * Exposure compensation using when capturing an image in EV. (double) + * + * Since: 0.10.33 + */ +#define GST_TAG_CAPTURING_EXPOSURE_COMPENSATION "capturing-exposure-compensation" + +/** + * GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE: + * + * Scene mode used when capturing an image. (string) + * + * The allowed values are: + * "standard" + * "landscape" + * "portrait" + * "night-scene" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE "capturing-scene-capture-type" + +/** + * GST_TAG_CAPTURING_GAIN_ADJUSTMENT: + * + * Gain adjustment applied to an image. (string) + * + * The allowed values are: + * "none" + * "low-gain-up" + * "high-gain-up" + * "low-gain-down" + * "high-gain-down" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_GAIN_ADJUSTMENT "capturing-gain-adjustment" + +/** + * GST_TAG_CAPTURING_WHITE_BALANCE: + * + * White balance mode used when capturing an image. (string) + * + * The allowed values are: + * "auto" + * "manual" + * "daylight" + * "cloudy" + * "tungsten" + * "fluorescent" + * "fluorescent h" (newer daylight-calibrated fluorescents) + * "flash" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_WHITE_BALANCE "capturing-white-balance" + +/** + * GST_TAG_CAPTURING_CONTRAST: + * + * Direction of contrast processing applied when capturing an image. (string) + * + * The allowed values are: + * "normal" + * "soft" + * "hard" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_CONTRAST "capturing-contrast" + +/** + * GST_TAG_CAPTURING_SATURATION: + * + * Direction of saturation processing applied when capturing an image. (string) + * + * The allowed values are: + * "normal" + * "low-saturation" + * "high-saturation" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_SATURATION "capturing-saturation" + +/** + * GST_TAG_CAPTURING_SHARPNESS: + * + * Direction of sharpness processing applied when capturing an image. (string) + * + * The allowed values are: + * "normal" + * "soft" + * "hard" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_SHARPNESS "capturing-sharpness" + +/** + * GST_TAG_CAPTURING_FLASH_FIRED: + * + * If flash was fired during the capture of an image. (boolean) + * + * Note that if this tag isn't present, it should not be assumed that + * the flash did not fire. It should be treated as unknown. + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_FLASH_FIRED "capturing-flash-fired" + +/** + * GST_TAG_CAPTURING_FLASH_MODE: + * + * The flash mode selected during the capture of an image. (string) + * + * The allowed values are: + * "auto" + * "always" + * "never" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_FLASH_MODE "capturing-flash-mode" + +/** + * GST_TAG_CAPTURING_METERING_MODE: + * + * Defines the way a camera determines the exposure. (string) + * + * The allowed values are: + * "unknown" + * "average" + * "center-weighted-average" + * "spot" + * "multi-spot" + * "pattern" + * "partial" + * "other" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_METERING_MODE "capturing-metering-mode" + +/** + * GST_TAG_CAPTURING_SOURCE: + * + * Indicates the source of capture. The device/medium used to do the + * capture. (string) + * + * Allowed values are: + * "dsc" (= digital still camera) + * "transparent-scanner" + * "reflex-scanner" + * "other" + * + * Since: 0.10.31 + */ +#define GST_TAG_CAPTURING_SOURCE "capturing-source" + +/** + * GST_TAG_IMAGE_HORIZONTAL_PPI: + * + * Media (image/video) intended horizontal pixel density in ppi. (double) + * + * Since: 0.10.31 + */ +#define GST_TAG_IMAGE_HORIZONTAL_PPI "image-horizontal-ppi" +/** + * GST_TAG_IMAGE_VERTICAL_PPI: + * + * Media (image/video) intended vertical pixel density in ppi. (double) + * + * Since: 0.10.31 + */ +#define GST_TAG_IMAGE_VERTICAL_PPI "image-vertical-ppi" + + +/* additional information for image tags */ + +/** + * GstTagImageType: + * @GST_TAG_IMAGE_TYPE_NONE : No image type. Can be used to + * tell functions such as gst_tag_image_data_to_image_buffer() that no + * image type should be set. (Since: 0.10.20) + * @GST_TAG_IMAGE_TYPE_UNDEFINED : Undefined/other image type + * @GST_TAG_IMAGE_TYPE_FRONT_COVER : Cover (front) + * @GST_TAG_IMAGE_TYPE_BACK_COVER : Cover (back) + * @GST_TAG_IMAGE_TYPE_LEAFLET_PAGE : Leaflet page + * @GST_TAG_IMAGE_TYPE_MEDIUM : Medium (e.g. label side of CD) + * @GST_TAG_IMAGE_TYPE_LEAD_ARTIST : Lead artist/lead performer/soloist + * @GST_TAG_IMAGE_TYPE_ARTIST : Artist/performer + * @GST_TAG_IMAGE_TYPE_CONDUCTOR : Conductor + * @GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA : Band/orchestra + * @GST_TAG_IMAGE_TYPE_COMPOSER : Composer + * @GST_TAG_IMAGE_TYPE_LYRICIST : Lyricist/text writer + * @GST_TAG_IMAGE_TYPE_RECORDING_LOCATION : Recording location + * @GST_TAG_IMAGE_TYPE_DURING_RECORDING : During recording + * @GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE : During performance + * @GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE : Movie/video screen capture + * @GST_TAG_IMAGE_TYPE_FISH : A fish as funny as the ID3v2 spec + * @GST_TAG_IMAGE_TYPE_ILLUSTRATION : Illustration + * @GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO : Band/artist logotype + * @GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO : Publisher/studio logotype + * + * Type of image contained in an image tag (specified as field in + * the image buffer's caps structure) + * + * Since: 0.10.9 + */ +/* Note: keep in sync with register_tag_image_type_enum() */ +typedef enum { + GST_TAG_IMAGE_TYPE_NONE = -1, + GST_TAG_IMAGE_TYPE_UNDEFINED = 0, + GST_TAG_IMAGE_TYPE_FRONT_COVER, + GST_TAG_IMAGE_TYPE_BACK_COVER, + GST_TAG_IMAGE_TYPE_LEAFLET_PAGE, + GST_TAG_IMAGE_TYPE_MEDIUM, + GST_TAG_IMAGE_TYPE_LEAD_ARTIST, + GST_TAG_IMAGE_TYPE_ARTIST, + GST_TAG_IMAGE_TYPE_CONDUCTOR, + GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA, + GST_TAG_IMAGE_TYPE_COMPOSER, + GST_TAG_IMAGE_TYPE_LYRICIST, + GST_TAG_IMAGE_TYPE_RECORDING_LOCATION, + GST_TAG_IMAGE_TYPE_DURING_RECORDING, + GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE, + GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE, + GST_TAG_IMAGE_TYPE_FISH, + GST_TAG_IMAGE_TYPE_ILLUSTRATION, + GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO, + GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO +} GstTagImageType; + +#define GST_TYPE_TAG_IMAGE_TYPE (gst_tag_image_type_get_type ()) +GType gst_tag_image_type_get_type (void); + + +/* functions for vorbis comment manipulation */ + +G_CONST_RETURN gchar * gst_tag_from_vorbis_tag (const gchar * vorbis_tag); +G_CONST_RETURN gchar * gst_tag_to_vorbis_tag (const gchar * gst_tag); +void gst_vorbis_tag_add (GstTagList * list, + const gchar * tag, + const gchar * value); + +GList * gst_tag_to_vorbis_comments (const GstTagList * list, + const gchar * tag); + +/* functions to convert GstBuffers with vorbiscomment contents to GstTagLists and back */ +GstTagList * gst_tag_list_from_vorbiscomment_buffer (const GstBuffer * buffer, + const guint8 * id_data, + const guint id_data_length, + gchar ** vendor_string); +GstBuffer * gst_tag_list_to_vorbiscomment_buffer (const GstTagList * list, + const guint8 * id_data, + const guint id_data_length, + const gchar * vendor_string); + +/* functions for ID3 tag manipulation */ + +guint gst_tag_id3_genre_count (void); +G_CONST_RETURN gchar * gst_tag_id3_genre_get (const guint id); +GstTagList * gst_tag_list_new_from_id3v1 (const guint8 * data); + +G_CONST_RETURN gchar * gst_tag_from_id3_tag (const gchar * id3_tag); +G_CONST_RETURN gchar * gst_tag_from_id3_user_tag (const gchar * type, + const gchar * id3_user_tag); +G_CONST_RETURN gchar * gst_tag_to_id3_tag (const gchar * gst_tag); + +gboolean gst_tag_list_add_id3_image (GstTagList * tag_list, + const guint8 * image_data, + guint image_data_len, + guint id3_picture_type); + +/* functions to convert GstBuffers with xmp packets contents to GstTagLists and back */ +GstTagList * gst_tag_list_from_xmp_buffer (const GstBuffer * buffer); +GstBuffer * gst_tag_list_to_xmp_buffer (const GstTagList * list, + gboolean read_only); +GstBuffer * gst_tag_list_to_xmp_buffer_full (const GstTagList * list, + gboolean read_only, const gchar ** schemas); +const gchar** gst_tag_xmp_list_schemas (void); + +/* functions related to exif */ +GstBuffer * gst_tag_list_to_exif_buffer (const GstTagList * taglist, + gint byte_order, + guint32 base_offset); + +GstBuffer * gst_tag_list_to_exif_buffer_with_tiff_header (const GstTagList * taglist); + +GstTagList * gst_tag_list_from_exif_buffer (const GstBuffer * buffer, + gint byte_order, + guint32 base_offset); + +GstTagList * gst_tag_list_from_exif_buffer_with_tiff_header ( + const GstBuffer * buffer); + +/* other tag-related functions */ + +gboolean gst_tag_parse_extended_comment (const gchar * ext_comment, + gchar ** key, + gchar ** lang, + gchar ** value, + gboolean fail_if_no_key); + +gchar * gst_tag_freeform_string_to_utf8 (const gchar * data, + gint size, + const gchar ** env_vars); + +GstBuffer * gst_tag_image_data_to_image_buffer (const guint8 * image_data, + guint image_data_len, + GstTagImageType image_type); + +/* FIXME 0.11: get rid of this awkward register/init function, see tags.c */ +void gst_tag_register_musicbrainz_tags (void); + + +/* language tag related functions */ + +gchar ** gst_tag_get_language_codes (void); + +const gchar * gst_tag_get_language_name (const gchar * language_code); + +const gchar * gst_tag_get_language_code_iso_639_1 (const gchar * lang_code); + +const gchar * gst_tag_get_language_code_iso_639_2B (const gchar * lang_code); + +const gchar * gst_tag_get_language_code_iso_639_2T (const gchar * lang_code); + +/** + * gst_tag_get_language_code: + * @lang_code: ISO-639 language code (e.g. "deu" or "ger" or "de") + * + * Convenience macro wrapping gst_tag_get_language_code_iso_639_1(). + * + * Since: 0.10.26 + */ +#define gst_tag_get_language_code(lang_code) \ + gst_tag_get_language_code_iso_639_1(lang_code) + +G_END_DECLS + +#endif /* __GST_TAG_TAG_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tags.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tags.c new file mode 100644 index 0000000..51f3bc7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/tags.c @@ -0,0 +1,634 @@ +/* GStreamer non-core tag registration and tag utility functions + * Copyright (C) 2005 Ross Burton + * Copyright (C) 2006-2008 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include "tag.h" + +#include + +/** + * SECTION:gsttag + * @short_description: additional tag definitions for plugins and applications + * @see_also: #GstTagList + * + * + * + * Contains additional standardized GStreamer tag definitions for plugins + * and applications, and functions to register them with the GStreamer + * tag system. + * + * + */ + +#ifndef GST_DISABLE_GST_DEBUG +#define GST_CAT_DEFAULT gst_tag_ensure_debug_category() + +static GstDebugCategory * +gst_tag_ensure_debug_category (void) +{ + static gsize cat_gonce = 0; + + if (g_once_init_enter (&cat_gonce)) { + GstDebugCategory *cat = NULL; + + GST_DEBUG_CATEGORY_INIT (cat, "tag-tags", 0, "GstTag helper functions"); + + g_once_init_leave (&cat_gonce, (gsize) cat); + } + + return (GstDebugCategory *) cat_gonce; +} +#endif /* GST_DISABLE_GST_DEBUG */ + +static gpointer +gst_tag_register_tags_internal (gpointer unused) +{ +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif + + /* musicbrainz tags */ + gst_tag_register (GST_TAG_MUSICBRAINZ_TRACKID, GST_TAG_FLAG_META, + G_TYPE_STRING, _("track ID"), _("MusicBrainz track ID"), NULL); + gst_tag_register (GST_TAG_MUSICBRAINZ_ARTISTID, GST_TAG_FLAG_META, + G_TYPE_STRING, _("artist ID"), _("MusicBrainz artist ID"), NULL); + gst_tag_register (GST_TAG_MUSICBRAINZ_ALBUMID, GST_TAG_FLAG_META, + G_TYPE_STRING, _("album ID"), _("MusicBrainz album ID"), NULL); + gst_tag_register (GST_TAG_MUSICBRAINZ_ALBUMARTISTID, GST_TAG_FLAG_META, + G_TYPE_STRING, + _("album artist ID"), _("MusicBrainz album artist ID"), NULL); + gst_tag_register (GST_TAG_MUSICBRAINZ_TRMID, GST_TAG_FLAG_META, + G_TYPE_STRING, _("track TRM ID"), _("MusicBrainz TRM ID"), NULL); + + /* CDDA tags */ + gst_tag_register (GST_TAG_CDDA_CDDB_DISCID, GST_TAG_FLAG_META, + G_TYPE_STRING, "discid", "CDDB discid for metadata retrieval", + gst_tag_merge_use_first); + + gst_tag_register (GST_TAG_CDDA_CDDB_DISCID_FULL, GST_TAG_FLAG_META, + G_TYPE_STRING, "discid full", + "CDDB discid for metadata retrieval (full)", gst_tag_merge_use_first); + + gst_tag_register (GST_TAG_CDDA_MUSICBRAINZ_DISCID, GST_TAG_FLAG_META, + G_TYPE_STRING, "musicbrainz-discid", + "Musicbrainz discid for metadata retrieval", gst_tag_merge_use_first); + + gst_tag_register (GST_TAG_CDDA_MUSICBRAINZ_DISCID_FULL, GST_TAG_FLAG_META, + G_TYPE_STRING, "musicbrainz-discid-full", + "Musicbrainz discid for metadata retrieval (full)", + gst_tag_merge_use_first); + + /* photography tags */ + gst_tag_register (GST_TAG_CAPTURING_SHUTTER_SPEED, GST_TAG_FLAG_META, + GST_TYPE_FRACTION, _("capturing shutter speed"), + _("Shutter speed used when capturing an image, in seconds"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_FOCAL_RATIO, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("capturing focal ratio"), + _("Focal ratio (f-number) used when capturing the image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_FOCAL_LENGTH, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("capturing focal length"), + _("Focal length of the lens used capturing the image, in mm"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("capturing digital zoom ratio"), + _("Digital zoom ratio used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_ISO_SPEED, GST_TAG_FLAG_META, + G_TYPE_INT, _("capturing iso speed"), + _("The ISO speed used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing exposure program"), + _("The exposure program used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_EXPOSURE_MODE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing exposure mode"), + _("The exposure mode used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("capturing exposure compensation"), + _("The exposure compensation used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing scene capture type"), + _("The scene capture mode used when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing gain adjustment"), + _("The overall gain adjustment applied on an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_WHITE_BALANCE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing white balance"), + _("The white balance mode set when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_CONTRAST, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing contrast"), + _("The direction of contrast processing applied " + "when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_SATURATION, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing saturation"), + _("The direction of saturation processing applied when " + "capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_SHARPNESS, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing sharpness"), + _("The direction of sharpness processing applied " + "when capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_FLASH_FIRED, GST_TAG_FLAG_META, + G_TYPE_BOOLEAN, _("capturing flash fired"), + _("If the flash fired while capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_FLASH_MODE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing flash mode"), + _("The selected flash mode while capturing an image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_METERING_MODE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing metering mode"), + _("The metering mode used while determining exposure for capturing an" + " image"), NULL); + + gst_tag_register (GST_TAG_CAPTURING_SOURCE, GST_TAG_FLAG_META, + G_TYPE_STRING, _("capturing source"), + _("The source or type of device used for the capture"), NULL); + + gst_tag_register (GST_TAG_IMAGE_HORIZONTAL_PPI, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("image horizontal ppi"), + _("Media (image/video) intended horizontal pixel density in ppi"), NULL); + + gst_tag_register (GST_TAG_IMAGE_VERTICAL_PPI, GST_TAG_FLAG_META, + G_TYPE_DOUBLE, _("image vertical ppi"), + _("Media (image/video) intended vertical pixel density in ppi"), NULL); + + return NULL; +} + +/* FIXME 0.11: rename this to gst_tag_init() or gst_tag_register_tags() or + * even better: make tags auto-register themselves, either by defining them + * to a wrapper func that does the initing, or by adding tag factories so + * that the core can load+register tags automatically when needed. */ + +/** + * gst_tag_register_musicbrainz_tags + * + * Registers additional musicbrainz-specific tags with the GStreamer tag + * system. Plugins and applications that use these tags should call this + * function before using them. Can be called multiple times. + */ +void +gst_tag_register_musicbrainz_tags (void) +{ + static GOnce mb_once = G_ONCE_INIT; + + g_once (&mb_once, gst_tag_register_tags_internal, NULL); +} + +static void +register_tag_image_type_enum (GType * id) +{ + static const GEnumValue image_types[] = { + {GST_TAG_IMAGE_TYPE_NONE, "GST_TAG_IMAGE_TYPE_NONE", "none"}, + {GST_TAG_IMAGE_TYPE_UNDEFINED, "GST_TAG_IMAGE_TYPE_UNDEFINED", "undefined"}, + {GST_TAG_IMAGE_TYPE_FRONT_COVER, "GST_TAG_IMAGE_TYPE_FRONT_COVER", + "front-cover"}, + {GST_TAG_IMAGE_TYPE_BACK_COVER, "GST_TAG_IMAGE_TYPE_BACK_COVER", + "back-cover"}, + {GST_TAG_IMAGE_TYPE_LEAFLET_PAGE, "GST_TAG_IMAGE_TYPE_LEAFLET_PAGE", + "leaflet-page"}, + {GST_TAG_IMAGE_TYPE_MEDIUM, "GST_TAG_IMAGE_TYPE_MEDIUM", "medium"}, + {GST_TAG_IMAGE_TYPE_LEAD_ARTIST, "GST_TAG_IMAGE_TYPE_LEAD_ARTIST", + "lead-artist"}, + {GST_TAG_IMAGE_TYPE_ARTIST, "GST_TAG_IMAGE_TYPE_ARTIST", "artist"}, + {GST_TAG_IMAGE_TYPE_CONDUCTOR, "GST_TAG_IMAGE_TYPE_CONDUCTOR", "conductor"}, + {GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA, "GST_TAG_IMAGE_TYPE_BAND_ORCHESTRA", + "band-orchestra"}, + {GST_TAG_IMAGE_TYPE_COMPOSER, "GST_TAG_IMAGE_TYPE_COMPOSER", "composer"}, + {GST_TAG_IMAGE_TYPE_LYRICIST, "GST_TAG_IMAGE_TYPE_LYRICIST", "lyricist"}, + {GST_TAG_IMAGE_TYPE_RECORDING_LOCATION, + "GST_TAG_IMAGE_TYPE_RECORDING_LOCATION", + "recording-location"}, + {GST_TAG_IMAGE_TYPE_DURING_RECORDING, "GST_TAG_IMAGE_TYPE_DURING_RECORDING", + "during-recording"}, + {GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE, + "GST_TAG_IMAGE_TYPE_DURING_PERFORMANCE", + "during-performance"}, + {GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE, "GST_TAG_IMAGE_TYPE_VIDEO_CAPTURE", + "video-capture"}, + {GST_TAG_IMAGE_TYPE_FISH, "GST_TAG_IMAGE_TYPE_FISH", "fish"}, + {GST_TAG_IMAGE_TYPE_ILLUSTRATION, "GST_TAG_IMAGE_TYPE_ILLUSTRATION", + "illustration"}, + {GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO, "GST_TAG_IMAGE_TYPE_BAND_ARTIST_LOGO", + "artist-logo"}, + {GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO, + "GST_TAG_IMAGE_TYPE_PUBLISHER_STUDIO_LOGO", + "publisher-studio-logo"}, + {0, NULL, NULL} + }; + + *id = g_enum_register_static ("GstTagImageType", image_types); + + /* work around thread-safety issue with class creation in GLib */ + g_type_class_ref (*id); +} + +GType +gst_tag_image_type_get_type (void) +{ + static GType id; + + static GOnce once = G_ONCE_INIT; + + g_once (&once, (GThreadFunc) register_tag_image_type_enum, &id); + return id; +} + +static inline gboolean +gst_tag_image_type_is_valid (GstTagImageType type) +{ + GEnumClass *klass; + + gboolean res; + + klass = g_type_class_ref (gst_tag_image_type_get_type ()); + res = (g_enum_get_value (klass, type) != NULL); + g_type_class_unref (klass); + + return res; +} + +/** + * gst_tag_parse_extended_comment: + * @ext_comment: an extended comment string, see #GST_TAG_EXTENDED_COMMENT + * @key: return location for the comment description key, or NULL + * @lang: return location for the comment ISO-639 language code, or NULL + * @value: return location for the actual comment string, or NULL + * @fail_if_no_key: whether to fail if strings are not in key=value form + * + * Convenience function to parse a GST_TAG_EXTENDED_COMMENT string and + * separate it into its components. + * + * If successful, @key, @lang and/or @value will be set to newly allocated + * strings that you need to free with g_free() when done. @key and @lang + * may also be set to NULL by this function if there is no key or no language + * code in the extended comment string. + * + * Returns: TRUE if the string could be parsed, otherwise FALSE + * + * Since: 0.10.10 + */ +gboolean +gst_tag_parse_extended_comment (const gchar * ext_comment, gchar ** key, + gchar ** lang, gchar ** value, gboolean fail_if_no_key) +{ + const gchar *div, *bop, *bcl; + + g_return_val_if_fail (ext_comment != NULL, FALSE); + g_return_val_if_fail (g_utf8_validate (ext_comment, -1, NULL), FALSE); + + if (key) + *key = NULL; + if (lang) + *lang = NULL; + + div = strchr (ext_comment, '='); + bop = strchr (ext_comment, '['); + bcl = strchr (ext_comment, ']'); + + if (div == NULL) { + if (fail_if_no_key) + return FALSE; + if (value) + *value = g_strdup (ext_comment); + return TRUE; + } + + if (bop != NULL && bop < div) { + if (bcl < bop || bcl > div) + return FALSE; + if (key) + *key = g_strndup (ext_comment, bop - ext_comment); + if (lang) + *lang = g_strndup (bop + 1, bcl - bop - 1); + } else { + if (key) + *key = g_strndup (ext_comment, div - ext_comment); + } + + if (value) + *value = g_strdup (div + 1); + + return TRUE; +} + +/** + * gst_tag_freeform_string_to_utf8: + * @data: string data + * @size: length of string data, or -1 if the string is NUL-terminated + * @env_vars: a NULL-terminated string array of environment variable names, + * or NULL + * + * Convenience function to read a string with unknown character encoding. If + * the string is already in UTF-8 encoding, it will be returned right away. + * If not it tries to detect byte-order-mark for UTF-16/32 cases and use that. + * Otherwise, the environment will be searched for a number of environment + * variables (whose names are specified in the NULL-terminated string array + * @env_vars) containing a list of character encodings to try/use. If none + * are specified, the current locale will be tried. If that also doesn't work, + * WINDOWS-1252/ISO-8859-1 is assumed (which will almost always succeed). + * + * Returns: a newly-allocated string in UTF-8 encoding, or NULL + * + * Since: 0.10.13 + */ +gchar * +gst_tag_freeform_string_to_utf8 (const gchar * data, gint size, + const gchar ** env_vars) +{ + const gchar *cur_loc = NULL; + + gsize bytes_read; + + gchar *utf8 = NULL; + + g_return_val_if_fail (data != NULL, NULL); + + if (size < 0) + size = strlen (data); + + /* chop off trailing string terminators to make sure utf8_validate doesn't + * get to see them (since that would make the utf8 check fail) */ + while (size > 0 && data[size - 1] == '\0') + --size; + + /* Should we try the charsets specified + * via environment variables FIRST ? */ + if (g_utf8_validate (data, size, NULL)) { + utf8 = g_strndup (data, size); + GST_LOG ("String '%s' is valid UTF-8 already", utf8); + goto beach; + } + + /* check for and use byte-order-mark for UTF-16/32 cases */ + if (size >= 2) { + const gchar *c = NULL; + gint prefix, ssize; + + if (size >= 4) { + prefix = 4; + ssize = GST_ROUND_DOWN_4 (size - 4); + switch (GST_READ_UINT32_BE (data)) { + case 0x0000FEFF: + c = "UTF-32BE"; + break; + case 0xFFFE0000: + c = "UTF-32LE"; + break; + default: + break; + } + } + if (!c) { + prefix = 2; + ssize = GST_ROUND_DOWN_2 (size - 2); + switch (GST_READ_UINT16_BE (data)) { + case 0xFEFF: + c = "UTF-16BE"; + break; + case 0xFFFE: + c = "UTF-16LE"; + break; + default: + break; + } + } + if (c) { + GST_LOG ("Trying to convert freeform string to UTF-8 from '%s'", c); + if ((utf8 = + g_convert (data + prefix, ssize, "UTF-8", c, &bytes_read, NULL, + NULL))) { + if (bytes_read == ssize) + goto beach; + g_free (utf8); + utf8 = NULL; + } + } + } + + while (env_vars && *env_vars != NULL) { + const gchar *env = NULL; + + /* Try charsets specified via the environment */ + env = g_getenv (*env_vars); + if (env != NULL && *env != '\0') { + gchar **c, **csets; + + csets = g_strsplit (env, G_SEARCHPATH_SEPARATOR_S, -1); + + for (c = csets; c && *c; ++c) { + GST_LOG ("Trying to convert freeform string to UTF-8 from '%s'", *c); + if ((utf8 = + g_convert (data, size, "UTF-8", *c, &bytes_read, NULL, NULL))) { + if (bytes_read == size) { + g_strfreev (csets); + goto beach; + } + g_free (utf8); + utf8 = NULL; + } + } + + g_strfreev (csets); + } + ++env_vars; + } + + /* Try current locale (if not UTF-8) */ + if (!g_get_charset (&cur_loc)) { + GST_LOG ("Trying to convert freeform string using locale ('%s')", cur_loc); + if ((utf8 = g_locale_to_utf8 (data, size, &bytes_read, NULL, NULL))) { + if (bytes_read == size) { + goto beach; + } + g_free (utf8); + utf8 = NULL; + } + } + + /* Try Windows-1252 (which is a superset of ISO 8859-1 that uses a control + * character range in ISO 8859-1 for more printable characters) */ + { + GError *err = NULL; + + GST_LOG ("Trying to convert freeform string using Windows-1252/ISO-8859-1 " + "fallback"); + utf8 = g_convert (data, size, "UTF-8", "WINDOWS-1252", &bytes_read, NULL, + &err); + if (err != NULL) { + /* fallback in case iconv implementation doesn't support windows-1252 + * for some reason */ + if (err->code == G_CONVERT_ERROR_NO_CONVERSION) { + utf8 = g_convert (data, size, "UTF-8", "ISO-8859-1", &bytes_read, + NULL, NULL); + } + g_error_free (err); + } + + if (utf8 != NULL && bytes_read == size) + goto beach; + } + + g_free (utf8); + return NULL; + +beach: + + g_strchomp (utf8); + if (utf8 && utf8[0] != '\0') { + GST_LOG ("Returning '%s'", utf8); + return utf8; + } + + g_free (utf8); + return NULL; +} + +/** + * gst_tag_image_data_to_image_buffer: + * @image_data: the (encoded) image + * @image_data_len: the length of the encoded image data at @image_data + * @image_type: type of the image, or #GST_TAG_IMAGE_TYPE_UNDEFINED. Pass + * #GST_TAG_IMAGE_TYPE_NONE if no image type should be set at all (e.g. + * for preview images) + * + * Helper function for tag-reading plugins to create a #GstBuffer suitable to + * add to a #GstTagList as an image tag (such as #GST_TAG_IMAGE or + * #GST_TAG_PREVIEW_IMAGE) from the encoded image data and an (optional) image + * type. + * + * Background: cover art and other images in tags are usually stored as a + * blob of binary image data, often accompanied by a MIME type or some other + * content type string (e.g. 'png', 'jpeg', 'jpg'). Sometimes there is also an + * 'image type' to indicate what kind of image this is (e.g. front cover, + * back cover, artist, etc.). The image data may also be an URI to the image + * rather than the image itself. + * + * In GStreamer, image tags are #GstBuffers containing the raw image + * data, with the buffer caps describing the content type of the image + * (e.g. image/jpeg, image/png, text/uri-list). The buffer caps may contain + * an additional 'image-type' field of #GST_TYPE_TAG_IMAGE_TYPE to describe + * the type of image (front cover, back cover etc.). #GST_TAG_PREVIEW_IMAGE + * tags should not carry an image type, their type is already indicated via + * the special tag name. + * + * This function will do various checks and typefind the encoded image + * data (we can't trust the declared mime type). + * + * Returns: a newly-allocated image buffer for use in tag lists, or NULL + * + * Since: 0.10.20 + */ +GstBuffer * +gst_tag_image_data_to_image_buffer (const guint8 * image_data, + guint image_data_len, GstTagImageType image_type) +{ + const gchar *name; + + GstBuffer *image; + + GstCaps *caps; + + g_return_val_if_fail (image_data != NULL, NULL); + g_return_val_if_fail (image_data_len > 0, NULL); + g_return_val_if_fail (gst_tag_image_type_is_valid (image_type), NULL); + + GST_DEBUG ("image data len: %u bytes", image_data_len); + + /* allocate space for a NUL terminator for an uri too */ + image = gst_buffer_try_new_and_alloc (image_data_len + 1); + if (image == NULL) { + GST_WARNING ("failed to allocate buffer of %d for image", image_data_len); + return NULL; + } + + memcpy (GST_BUFFER_DATA (image), image_data, image_data_len); + GST_BUFFER_DATA (image)[image_data_len] = '\0'; + + /* Find GStreamer media type, can't trust declared type */ + caps = gst_type_find_helper_for_buffer (NULL, image, NULL); + + if (caps == NULL) + goto no_type; + + GST_DEBUG ("Found GStreamer media type: %" GST_PTR_FORMAT, caps); + + /* sanity check: make sure typefound/declared caps are either URI or image */ + name = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + + if (!g_str_has_prefix (name, "image/") && + !g_str_has_prefix (name, "video/") && + !g_str_equal (name, "text/uri-list")) { + GST_DEBUG ("Unexpected image type '%s', ignoring image frame", name); + goto error; + } + + /* Decrease size by 1 if we don't have an URI list + * to keep the original size of the image + */ + if (!g_str_equal (name, "text/uri-list")) + GST_BUFFER_SIZE (image) = image_data_len; + + if (image_type != GST_TAG_IMAGE_TYPE_NONE) { + GST_LOG ("Setting image type: %d", image_type); + caps = gst_caps_make_writable (caps); + gst_caps_set_simple (caps, "image-type", GST_TYPE_TAG_IMAGE_TYPE, + image_type, NULL); + } + + gst_buffer_set_caps (image, caps); + gst_caps_unref (caps); + return image; + +/* ERRORS */ +no_type: + { + GST_DEBUG ("Could not determine GStreamer media type, ignoring image"); + /* fall through */ + } +error: + { + if (image) + gst_buffer_unref (image); + if (caps) + gst_caps_unref (caps); + return NULL; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.c new file mode 100644 index 0000000..23282b8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.c @@ -0,0 +1,322 @@ +/* GStreamer XmpConfig + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstxmpconfig + * @short_description: Interface for elements that provide XMP serialization + * + * + * + * This interface is implemented by elements that are able to do XMP serialization. Examples for + * such elements are #jifmux and #qtmux. + * + * + * Applications can use this interface to configure which XMP schemas should be used when serializing + * tags into XMP. Schemas are represented by their names, a full list of the supported schemas can be + * obtained from gst_tag_xmp_list_schemas(). By default, all schemas are used. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "xmpwriter.h" +#include +#include + +static GQuark tag_xmp_writer_key; + +typedef struct +{ + GSList *schemas; + GStaticMutex lock; +} GstTagXmpWriterData; + +GType +gst_tag_xmp_writer_get_type (void) +{ + static volatile gsize xmp_config_type = 0; + + if (g_once_init_enter (&xmp_config_type)) { + GType _type; + static const GTypeInfo xmp_config_info = { + sizeof (GstTagXmpWriterInterface), /* class_size */ + NULL, /* base_init */ + NULL, /* base_finalize */ + NULL, + NULL, /* class_finalize */ + NULL, /* class_data */ + 0, + 0, + NULL + }; + + _type = g_type_register_static (G_TYPE_INTERFACE, "GstTagXmpWriter", + &xmp_config_info, 0); + tag_xmp_writer_key = g_quark_from_static_string ("GST_TAG_XMP_WRITER"); + g_type_interface_add_prerequisite (_type, GST_TYPE_ELEMENT); + + g_once_init_leave (&xmp_config_type, _type); + } + + return xmp_config_type; +} + +static void +gst_tag_xmp_writer_data_add_schema_unlocked (GstTagXmpWriterData * data, + const gchar * schema) +{ + if (!g_slist_find_custom (data->schemas, schema, (GCompareFunc) strcmp)) { + data->schemas = g_slist_prepend (data->schemas, g_strdup (schema)); + } +} + +static void +gst_tag_xmp_writer_data_add_all_schemas_unlocked (GstTagXmpWriterData * data) +{ + const gchar **schemas; + gint i = 0; + + /* initialize it with all schemas */ + schemas = gst_tag_xmp_list_schemas (); + while (schemas[i] != NULL) { + gst_tag_xmp_writer_data_add_schema_unlocked (data, schemas[i]); + i++; + } +} + + +static void +gst_tag_xmp_writer_data_free (gpointer p) +{ + GstTagXmpWriterData *data = (GstTagXmpWriterData *) p; + GSList *iter; + + if (data->schemas) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + g_free (iter->data); + } + g_slist_free (data->schemas); + } + + g_static_mutex_free (&data->lock); + + g_slice_free (GstTagXmpWriterData, data); +} + +static GstTagXmpWriterData * +gst_tag_xmp_writer_get_data (GstTagXmpWriter * xmpconfig) +{ + GstTagXmpWriterData *data; + + data = g_object_get_qdata (G_OBJECT (xmpconfig), tag_xmp_writer_key); + if (!data) { + static GStaticMutex create_mutex = G_STATIC_MUTEX_INIT; + + /* make sure no other thread is creating a GstTagXmpWriterData at the same time */ + g_static_mutex_lock (&create_mutex); + data = g_object_get_qdata (G_OBJECT (xmpconfig), tag_xmp_writer_key); + if (!data) { + data = g_slice_new (GstTagXmpWriterData); + g_static_mutex_init (&data->lock); + + data->schemas = NULL; + gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); + + g_object_set_qdata_full (G_OBJECT (xmpconfig), tag_xmp_writer_key, data, + gst_tag_xmp_writer_data_free); + } + g_static_mutex_unlock (&create_mutex); + } + + return data; +} + +/** + * gst_tag_xmp_writer_add_all_schemas: + * @config: a #GstTagXmpWriter + * + * Adds all available XMP schemas to the configuration. Meaning that + * all will be used. + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_add_all_schemas (GstTagXmpWriter * config) +{ + GstTagXmpWriterData *data; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + gst_tag_xmp_writer_data_add_all_schemas_unlocked (data); + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_add_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to be added + * + * Adds @schema to the list schemas + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_add_schema (GstTagXmpWriter * config, const gchar * schema) +{ + GstTagXmpWriterData *data; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + gst_tag_xmp_writer_data_add_schema_unlocked (data, schema); + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_has_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to test + * + * Checks if @schema is going to be used + * + * Returns: %TRUE if it is going to be used + * Since: 0.10.33 + */ +gboolean +gst_tag_xmp_writer_has_schema (GstTagXmpWriter * config, const gchar * schema) +{ + GstTagXmpWriterData *data; + gboolean ret = FALSE; + GSList *iter; + + g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), FALSE); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + if (strcmp ((const gchar *) iter->data, schema) == 0) { + ret = TRUE; + break; + } + } + g_static_mutex_unlock (&data->lock); + + return ret; +} + +/** + * gst_tag_xmp_writer_remove_schema: + * @config: a #GstTagXmpWriter + * @schema: the schema to remove + * + * Removes a schema from the list of schemas to use. Nothing is done if + * the schema wasn't in the list + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_remove_schema (GstTagXmpWriter * config, + const gchar * schema) +{ + GstTagXmpWriterData *data; + GSList *iter = NULL; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + if (strcmp ((const gchar *) iter->data, schema) == 0) { + g_free (iter->data); + data->schemas = g_slist_delete_link (data->schemas, iter); + break; + } + } + g_static_mutex_unlock (&data->lock); +} + +/** + * gst_tag_xmp_writer_remove_all_schemas: + * @config: a #GstTagXmpWriter + * + * Removes all schemas from the list of schemas to use. Meaning that no + * XMP will be generated. + * + * Since: 0.10.33 + */ +void +gst_tag_xmp_writer_remove_all_schemas (GstTagXmpWriter * config) +{ + GstTagXmpWriterData *data; + GSList *iter; + + g_return_if_fail (GST_IS_TAG_XMP_WRITER (config)); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + if (data->schemas) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + g_free (iter->data); + } + g_slist_free (data->schemas); + } + data->schemas = NULL; + g_static_mutex_unlock (&data->lock); +} + +GstBuffer * +gst_tag_xmp_writer_tag_list_to_xmp_buffer (GstTagXmpWriter * config, + const GstTagList * taglist, gboolean read_only) +{ + GstTagXmpWriterData *data; + GstBuffer *buf = NULL; + gint i = 0; + GSList *iter; + + g_return_val_if_fail (GST_IS_TAG_XMP_WRITER (config), NULL); + + data = gst_tag_xmp_writer_get_data (config); + + g_static_mutex_lock (&data->lock); + if (data->schemas) { + gchar **array = g_new0 (gchar *, g_slist_length (data->schemas) + 1); + if (array) { + for (iter = data->schemas; iter; iter = g_slist_next (iter)) { + array[i++] = (gchar *) iter->data; + } + buf = gst_tag_list_to_xmp_buffer_full (taglist, read_only, + (const gchar **) array); + g_free (array); + } + } + g_static_mutex_unlock (&data->lock); + + return buf; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.h new file mode 100644 index 0000000..6c89072 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/tag/xmpwriter.h @@ -0,0 +1,68 @@ +/* GStreamer XmpConfig + * Copyright (C) 2011 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __TAG_XMP_WRITER_H__ +#define __TAG_XMP_WRITER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_TAG_XMP_WRITER \ + (gst_tag_xmp_writer_get_type ()) +#define GST_TAG_XMP_WRITER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriter)) +#define GST_TAG_XMP_WRITER_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_CAST ((iface), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriterInterface)) +#define GST_IS_TAG_XMP_WRITER(obj) \ + (GST_IMPLEMENTS_INTERFACE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_TAG_XMP_WRITER)) +#define GST_IS_TAG_XMP_WRITER_INTERFACE(iface) \ + (G_TYPE_CHECK_INTERFACE_TYPE ((iface), GST_TYPE_TAG_XMP_WRITER)) +#define GST_TAG_XMP_WRITER_GET_INTERFACE(inst) \ + (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GST_TYPE_TAG_XMP_WRITER, GstTagXmpWriterInterface)) + +typedef struct _GstTagXmpWriter GstTagXmpWriter; +typedef struct _GstTagXmpWriterInterface GstTagXmpWriterInterface; + +struct _GstTagXmpWriterInterface { + GTypeInterface parent; +}; + +GType gst_tag_xmp_writer_get_type (void); + +void gst_tag_xmp_writer_add_all_schemas (GstTagXmpWriter * config); + +void gst_tag_xmp_writer_add_schema (GstTagXmpWriter * config, + const gchar * schema); + +gboolean gst_tag_xmp_writer_has_schema (GstTagXmpWriter * config, + const gchar * schema); + +void gst_tag_xmp_writer_remove_schema (GstTagXmpWriter * config, + const gchar * schema); + +void gst_tag_xmp_writer_remove_all_schemas (GstTagXmpWriter * config); + +GstBuffer* gst_tag_xmp_writer_tag_list_to_xmp_buffer (GstTagXmpWriter * config, + const GstTagList * taglist, + gboolean read_only); + +G_END_DECLS + +#endif /* __TAG_XMP_WRITER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/.gitignore b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/.gitignore new file mode 100644 index 0000000..42df1ec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/.gitignore @@ -0,0 +1,2 @@ +video-enumtypes.c +video-enumtypes.h diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/Makefile.am b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/Makefile.am new file mode 100644 index 0000000..21ce6e4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/Makefile.am @@ -0,0 +1,98 @@ +# variables used for enum/marshal generation +glib_enum_headers = video.h +glib_enum_define = GST_VIDEO +glib_gen_prefix = gst_video +glib_gen_basename = video + +built_sources = video-enumtypes.c +built_headers = video-enumtypes.h +BUILT_SOURCES = $(built_sources) $(built_headers) + +lib_LTLIBRARIES = libgstvideo-@GST_MAJORMINOR@.la + +CLEANFILES = $(BUILT_SOURCES) + +libgstvideo_@GST_MAJORMINOR@_la_SOURCES = \ + video.c gstvideosink.c gstvideofilter.c convertframe.c +nodist_libgstvideo_@GST_MAJORMINOR@_la_SOURCES = $(BUILT_SOURCES) + +libgstvideo_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/video +libgstvideo_@GST_MAJORMINOR@include_HEADERS = \ + video.h gstvideosink.h gstvideofilter.h +nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS = $(built_headers) + +libgstvideo_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstvideo_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) +libgstvideo_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + +include $(top_srcdir)/common/gst-glib-gen.mak + +if HAVE_INTROSPECTION +BUILT_GIRSOURCES = GstVideo-@GST_MAJORMINOR@.gir + +gir_headers=$(patsubst %,$(srcdir)/%, $(libgstvideo_@GST_MAJORMINOR@include_HEADERS)) +gir_headers+=$(patsubst %,$(builddir)/%, $(nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS)) +gir_sources=$(patsubst %,$(srcdir)/%, $(libgstvideo_@GST_MAJORMINOR@_la_SOURCES)) +gir_sources+=$(patsubst %,$(builddir)/%, $(nodist_libgstvideo_@GST_MAJORMINOR@_la_SOURCES)) +gir_cincludes=$(patsubst %,--c-include='gst/video/%',$(libgstvideo_@GST_MAJORMINOR@include_HEADERS)) +gir_cincludes+=$(patsubst %,--c-include='gst/video/%',$(nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS)) + +GstVideo-@GST_MAJORMINOR@.gir: $(INTROSPECTION_SCANNER) libgstvideo-@GST_MAJORMINOR@.la + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + GST_PLUGIN_SYSTEM_PATH="" GST_PLUGIN_PATH="" GST_REGISTRY_UPDATE=no \ + $(INTROSPECTION_SCANNER) -v --namespace GstVideo \ + --nsversion=@GST_MAJORMINOR@ \ + --strip-prefix=Gst \ + $(gir_cincludes) \ + -I$(top_srcdir)/gst-libs \ + -I$(top_builddir)/gst-libs \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --add-include-path=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + --library=libgstvideo-@GST_MAJORMINOR@.la \ + --include=Gst-@GST_MAJORMINOR@ \ + --include=GstBase-@GST_MAJORMINOR@ \ + --libtool="$(top_builddir)/libtool" \ + --pkg gstreamer-@GST_MAJORMINOR@ \ + --pkg gstreamer-base-@GST_MAJORMINOR@ \ + --pkg-export gstreamer-video-@GST_MAJORMINOR@ \ + --add-init-section="gst_init(NULL,NULL);" \ + --output $@ \ + $(gir_headers) \ + $(gir_sources) + +# INTROSPECTION_GIRDIR/INTROSPECTION_TYPELIBDIR aren't the right place to +# install anything - we need to install inside our prefix. +girdir = $(datadir)/gir-1.0 +gir_DATA = $(BUILT_GIRSOURCES) + +typelibsdir = $(libdir)/girepository-1.0/ + +typelibs_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +%.typelib: %.gir $(INTROSPECTION_COMPILER) + $(AM_V_GEN)PKG_CONFIG_PATH="$(GST_PKG_CONFIG_PATH)" \ + $(INTROSPECTION_COMPILER) \ + --includedir=$(srcdir) \ + --includedir=$(builddir) \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-@GST_MAJORMINOR@` \ + --includedir=`$(PKG_CONFIG) --variable=girdir gstreamer-base-@GST_MAJORMINOR@` \ + $(INTROSPECTION_COMPILER_OPTS) $< -o $(@F) + +CLEANFILES += $(BUILT_GIRSOURCES) $(typelibs_DATA) +endif + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer -:PROJECT libgstvideo -:SHARED libgstvideo-@GST_MAJORMINOR@ \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstvideo_@GST_MAJORMINOR@_la_SOURCES) \ + $(nodist_libgstvideo_@GST_MAJORMINOR@_la_SOURCES) \ + -:CFLAGS $(DEFS) $(libgstvideo_@GST_MAJORMINOR@_la_CFLAGS) \ + -:LDFLAGS $(libgstvideo_@GST_MAJORMINOR@_la_LDFLAGS) \ + $(libgstvideo_@GST_MAJORMINOR@_la_LIBADD) \ + -ldl \ + -:HEADER_TARGET gstreamer-@GST_MAJORMINOR@/gst/tag \ + -:HEADERS $(libgstvideo_@GST_MAJORMINOR@include_HEADERS) \ + $(nodist_libgstvideo_@GST_MAJORMINOR@include_HEADERS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/convertframe.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/convertframe.c new file mode 100644 index 0000000..c04f2ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/convertframe.c @@ -0,0 +1,700 @@ +/* Small helper element for format conversion + * Copyright (C) 2005 Tim-Philipp Müller + * Copyright (C) 2010 Brandon Lewis + * Copyright (C) 2010 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include "video.h" + +static gboolean +caps_are_raw (const GstCaps * caps) +{ + guint i, len; + + len = gst_caps_get_size (caps); + + for (i = 0; i < len; i++) { + GstStructure *st = gst_caps_get_structure (caps, i); + if (gst_structure_has_name (st, "video/x-raw-yuv") || + gst_structure_has_name (st, "video/x-raw-rgb")) + return TRUE; + } + + return FALSE; +} + +static gboolean +create_element (const gchar * factory_name, GstElement ** element, + GError ** err) +{ + *element = gst_element_factory_make (factory_name, NULL); + if (*element) + return TRUE; + + if (err && *err == NULL) { + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, + "cannot create element '%s' - please check your GStreamer installation", + factory_name); + } + + return FALSE; +} + +static GstElement * +get_encoder (const GstCaps * caps, GError ** err) +{ + GList *encoders = NULL; + GList *filtered = NULL; + GstElementFactory *factory = NULL; + GstElement *encoder = NULL; + + encoders = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER | + GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE, GST_RANK_NONE); + + if (encoders == NULL) { + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, + "Cannot find any image encoder"); + goto fail; + } + + GST_INFO ("got factory list %p", encoders); + gst_plugin_feature_list_debug (encoders); + + filtered = + gst_element_factory_list_filter (encoders, caps, GST_PAD_SRC, FALSE); + GST_INFO ("got filtered list %p", filtered); + + if (filtered == NULL) { + gchar *tmp = gst_caps_to_string (caps); + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_MISSING_PLUGIN, + "Cannot find any image encoder for caps %s", tmp); + g_free (tmp); + goto fail; + } + + gst_plugin_feature_list_debug (filtered); + + factory = (GstElementFactory *) filtered->data; + + GST_INFO ("got factory %p", factory); + encoder = gst_element_factory_create (factory, NULL); + + GST_INFO ("created encoder element %p, %s", encoder, + gst_element_get_name (encoder)); + +fail: + if (encoders) + gst_plugin_feature_list_free (encoders); + if (filtered) + gst_plugin_feature_list_free (filtered); + + return encoder; +} + +static GstElement * +build_convert_frame_pipeline (GstElement ** src_element, + GstElement ** sink_element, const GstCaps * from_caps, + const GstCaps * to_caps, GError ** err) +{ + GstElement *src = NULL, *csp = NULL, *vscale = NULL; + GstElement *sink = NULL, *encoder = NULL, *pipeline; + GError *error = NULL; + + /* videoscale is here to correct for the pixel-aspect-ratio for us */ + GST_DEBUG ("creating elements"); + if (!create_element ("appsrc", &src, &error) || + !create_element ("ffmpegcolorspace", &csp, &error) || + !create_element ("videoscale", &vscale, &error) || + !create_element ("appsink", &sink, &error)) + goto no_elements; + + pipeline = gst_pipeline_new ("videoconvert-pipeline"); + if (pipeline == NULL) + goto no_pipeline; + + /* Add black borders if necessary to keep the DAR */ + g_object_set (vscale, "add-borders", TRUE, NULL); + + GST_DEBUG ("adding elements"); + gst_bin_add_many (GST_BIN (pipeline), src, csp, vscale, sink, NULL); + + /* set caps */ + g_object_set (src, "caps", from_caps, NULL); + g_object_set (sink, "caps", to_caps, NULL); + + /* FIXME: linking is still way too expensive, profile this properly */ + GST_DEBUG ("linking src->csp"); + if (!gst_element_link_pads (src, "src", csp, "sink")) + goto link_failed; + + GST_DEBUG ("linking csp->vscale"); + if (!gst_element_link_pads (csp, "src", vscale, "sink")) + goto link_failed; + + if (caps_are_raw (to_caps)) { + GST_DEBUG ("linking vscale->sink"); + + if (!gst_element_link_pads (vscale, "src", sink, "sink")) + goto link_failed; + } else { + encoder = get_encoder (to_caps, &error); + if (!encoder) + goto no_encoder; + gst_bin_add (GST_BIN (pipeline), encoder); + + GST_DEBUG ("linking vscale->encoder"); + if (!gst_element_link (vscale, encoder)) + goto link_failed; + + GST_DEBUG ("linking encoder->sink"); + if (!gst_element_link_pads (encoder, "src", sink, "sink")) + goto link_failed; + } + + g_object_set (src, "emit-signals", TRUE, NULL); + g_object_set (sink, "emit-signals", TRUE, NULL); + + *src_element = src; + *sink_element = sink; + + return pipeline; + /* ERRORS */ +no_encoder: + { + gst_object_unref (pipeline); + + GST_ERROR ("could not find an encoder for provided caps"); + if (err) + *err = error; + else + g_error_free (error); + + return NULL; + } +no_elements: + { + if (src) + gst_object_unref (src); + if (csp) + gst_object_unref (csp); + if (vscale) + gst_object_unref (vscale); + if (sink) + gst_object_unref (sink); + GST_ERROR ("Could not convert video frame: %s", error->message); + if (err) + *err = error; + else + g_error_free (error); + return NULL; + } +no_pipeline: + { + gst_object_unref (src); + gst_object_unref (csp); + gst_object_unref (vscale); + gst_object_unref (sink); + + GST_ERROR ("Could not convert video frame: no pipeline (unknown error)"); + if (err) + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + "Could not convert video frame: no pipeline (unknown error)"); + return NULL; + } +link_failed: + { + gst_object_unref (pipeline); + + GST_ERROR ("Could not convert video frame: failed to link elements"); + if (err) + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, + "Could not convert video frame: failed to link elements"); + return NULL; + } +} + +/** + * gst_video_convert_frame: + * @buf: a #GstBuffer + * @to_caps: the #GstCaps to convert to + * @timeout: the maximum amount of time allowed for the processing. + * @err: pointer to a #GError. Can be %NULL. + * + * Converts a raw video buffer into the specified output caps. + * + * The output caps can be any raw video formats or any image formats (jpeg, png, ...). + * + * The width, height and pixel-aspect-ratio can also be specified in the output caps. + * + * Returns: The converted #GstBuffer, or %NULL if an error happened (in which case @err + * will point to the #GError). + * + * Since: 0.10.31 + * + */ +GstBuffer * +gst_video_convert_frame (GstBuffer * buf, const GstCaps * to_caps, + GstClockTime timeout, GError ** err) +{ + GstMessage *msg; + GstBuffer *result = NULL; + GError *error = NULL; + GstBus *bus; + GstCaps *from_caps, *to_caps_copy = NULL; + GstFlowReturn ret; + GstElement *pipeline, *src, *sink; + guint i, n; + + g_return_val_if_fail (buf != NULL, NULL); + g_return_val_if_fail (to_caps != NULL, NULL); + g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL); + + from_caps = GST_BUFFER_CAPS (buf); + + to_caps_copy = gst_caps_new_empty (); + n = gst_caps_get_size (to_caps); + for (i = 0; i < n; i++) { + GstStructure *s = gst_caps_get_structure (to_caps, i); + + s = gst_structure_copy (s); + gst_structure_remove_field (s, "framerate"); + gst_caps_append_structure (to_caps_copy, s); + } + + pipeline = + build_convert_frame_pipeline (&src, &sink, from_caps, to_caps_copy, + &error); + if (!pipeline) + goto no_pipeline; + + /* now set the pipeline to the paused state, after we push the buffer into + * appsrc, this should preroll the converted buffer in appsink */ + GST_DEBUG ("running conversion pipeline to caps %" GST_PTR_FORMAT, + to_caps_copy); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* feed buffer in appsrc */ + GST_DEBUG ("feeding buffer %p, size %u, caps %" GST_PTR_FORMAT, + buf, GST_BUFFER_SIZE (buf), from_caps); + g_signal_emit_by_name (src, "push-buffer", buf, &ret); + + /* now see what happens. We either got an error somewhere or the pipeline + * prerolled */ + bus = gst_element_get_bus (pipeline); + msg = gst_bus_timed_pop_filtered (bus, + timeout, GST_MESSAGE_ERROR | GST_MESSAGE_ASYNC_DONE); + + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ASYNC_DONE: + { + /* we're prerolled, get the frame from appsink */ + g_signal_emit_by_name (sink, "pull-preroll", &result); + + if (result) { + GST_DEBUG ("conversion successful: result = %p", result); + } else { + GST_ERROR ("prerolled but no result frame?!"); + } + break; + } + case GST_MESSAGE_ERROR:{ + gchar *dbg = NULL; + + gst_message_parse_error (msg, &error, &dbg); + if (error) { + GST_ERROR ("Could not convert video frame: %s", error->message); + GST_DEBUG ("%s [debug: %s]", error->message, GST_STR_NULL (dbg)); + if (err) + *err = error; + else + g_error_free (error); + } + g_free (dbg); + break; + } + default:{ + g_return_val_if_reached (NULL); + } + } + gst_message_unref (msg); + } else { + GST_ERROR ("Could not convert video frame: timeout during conversion"); + if (err) + *err = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + "Could not convert video frame: timeout during conversion"); + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (bus); + gst_object_unref (pipeline); + gst_caps_unref (to_caps_copy); + + return result; + + /* ERRORS */ +no_pipeline: + { + gst_caps_unref (to_caps_copy); + + if (err) + *err = error; + else + g_error_free (error); + + return NULL; + } +} + +typedef struct +{ + GMutex *mutex; + GstElement *pipeline; + GstVideoConvertFrameCallback callback; + gpointer user_data; + GDestroyNotify destroy_notify; + GMainContext *context; + GstBuffer *buffer; + gulong timeout_id; + gboolean finished; +} GstVideoConvertFrameContext; + +typedef struct +{ + GstVideoConvertFrameCallback callback; + GstBuffer *buffer; + GError *error; + gpointer user_data; + GDestroyNotify destroy_notify; + + GstVideoConvertFrameContext *context; +} GstVideoConvertFrameCallbackContext; + +static void +gst_video_convert_frame_context_free (GstVideoConvertFrameContext * ctx) +{ + /* Wait until all users of the mutex are done */ + g_mutex_lock (ctx->mutex); + g_mutex_unlock (ctx->mutex); + g_mutex_free (ctx->mutex); + if (ctx->timeout_id) + g_source_remove (ctx->timeout_id); + if (ctx->buffer) + gst_buffer_unref (ctx->buffer); + g_main_context_unref (ctx->context); + + gst_element_set_state (ctx->pipeline, GST_STATE_NULL); + gst_object_unref (ctx->pipeline); + + g_slice_free (GstVideoConvertFrameContext, ctx); +} + +static void + gst_video_convert_frame_callback_context_free + (GstVideoConvertFrameCallbackContext * ctx) +{ + if (ctx->context) + gst_video_convert_frame_context_free (ctx->context); + g_slice_free (GstVideoConvertFrameCallbackContext, ctx); +} + +static gboolean +convert_frame_dispatch_callback (GstVideoConvertFrameCallbackContext * ctx) +{ + ctx->callback (ctx->buffer, ctx->error, ctx->user_data); + + if (ctx->destroy_notify) + ctx->destroy_notify (ctx->user_data); + + return FALSE; +} + +static void +convert_frame_finish (GstVideoConvertFrameContext * context, GstBuffer * buffer, + GError * error) +{ + GSource *source; + GstVideoConvertFrameCallbackContext *ctx; + + if (context->timeout_id) + g_source_remove (context->timeout_id); + context->timeout_id = 0; + + ctx = g_slice_new (GstVideoConvertFrameCallbackContext); + ctx->callback = context->callback; + ctx->user_data = context->user_data; + ctx->destroy_notify = context->destroy_notify; + ctx->buffer = buffer; + ctx->error = error; + ctx->context = context; + + source = g_timeout_source_new (0); + g_source_set_callback (source, + (GSourceFunc) convert_frame_dispatch_callback, ctx, + (GDestroyNotify) gst_video_convert_frame_callback_context_free); + g_source_attach (source, context->context); + g_source_unref (source); + + context->finished = TRUE; +} + +static gboolean +convert_frame_timeout_callback (GstVideoConvertFrameContext * context) +{ + GError *error; + + g_mutex_lock (context->mutex); + + if (context->finished) + goto done; + + GST_ERROR ("Could not convert video frame: timeout"); + + error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + "Could not convert video frame: timeout"); + + convert_frame_finish (context, NULL, error); + +done: + g_mutex_unlock (context->mutex); + return FALSE; +} + +static gboolean +convert_frame_bus_callback (GstBus * bus, GstMessage * message, + GstVideoConvertFrameContext * context) +{ + g_mutex_lock (context->mutex); + + if (context->finished) + goto done; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *error; + gchar *dbg = NULL; + + gst_message_parse_error (message, &error, &dbg); + + GST_ERROR ("Could not convert video frame: %s", error->message); + GST_DEBUG ("%s [debug: %s]", error->message, GST_STR_NULL (dbg)); + + convert_frame_finish (context, NULL, error); + + g_free (dbg); + break; + } + default: + break; + } + +done: + g_mutex_unlock (context->mutex); + + return FALSE; +} + +static void +convert_frame_need_data_callback (GstElement * src, guint size, + GstVideoConvertFrameContext * context) +{ + GstFlowReturn ret = GST_FLOW_ERROR; + GError *error; + + g_mutex_lock (context->mutex); + + if (context->finished) + goto done; + + g_signal_emit_by_name (src, "push-buffer", context->buffer, &ret); + gst_buffer_unref (context->buffer); + context->buffer = NULL; + + if (ret != GST_FLOW_OK) { + GST_ERROR ("Could not push video frame: %s", gst_flow_get_name (ret)); + + error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + "Could not push video frame: %s", gst_flow_get_name (ret)); + + convert_frame_finish (context, NULL, error); + } + + g_signal_handlers_disconnect_by_func (src, convert_frame_need_data_callback, + context); + +done: + g_mutex_unlock (context->mutex); +} + +static void +convert_frame_new_buffer_callback (GstElement * sink, + GstVideoConvertFrameContext * context) +{ + GstBuffer *buf = NULL; + GError *error = NULL; + + g_mutex_lock (context->mutex); + + if (context->finished) + goto done; + + g_signal_emit_by_name (sink, "pull-preroll", &buf); + + if (!buf) { + error = g_error_new (GST_CORE_ERROR, GST_CORE_ERROR_FAILED, + "Could not get converted video frame"); + } + + convert_frame_finish (context, buf, error); + + g_signal_handlers_disconnect_by_func (sink, convert_frame_need_data_callback, + context); + +done: + g_mutex_unlock (context->mutex); +} + +/** + * gst_video_convert_frame_async: + * @buf: a #GstBuffer + * @to_caps: the #GstCaps to convert to + * @timeout: the maximum amount of time allowed for the processing. + * @callback: %GstVideoConvertFrameCallback that will be called after conversion. + * @destroy_notify: %GDestroyNotify to be called after @user_data is not needed anymore + * + * Converts a raw video buffer into the specified output caps. + * + * The output caps can be any raw video formats or any image formats (jpeg, png, ...). + * + * The width, height and pixel-aspect-ratio can also be specified in the output caps. + * + * @callback will be called after conversion, when an error occured or if conversion didn't + * finish after @timeout. @callback will always be called from the thread default + * %GMainContext, see g_main_context_get_thread_default(). If GLib before 2.22 is used, + * this will always be the global default main context. + * + * @destroy_notify will be called after the callback was called and @user_data is not needed + * anymore. + * + * Since: 0.10.31 + * + */ +void +gst_video_convert_frame_async (GstBuffer * buf, const GstCaps * to_caps, + GstClockTime timeout, GstVideoConvertFrameCallback callback, + gpointer user_data, GDestroyNotify destroy_notify) +{ + GMainContext *context = NULL; + GError *error = NULL; + GstBus *bus; + GstCaps *from_caps, *to_caps_copy = NULL; + GstElement *pipeline, *src, *sink; + guint i, n; + GSource *source; + GstVideoConvertFrameContext *ctx; + + g_return_if_fail (buf != NULL); + g_return_if_fail (to_caps != NULL); + g_return_if_fail (GST_BUFFER_CAPS (buf) != NULL); + g_return_if_fail (callback != NULL); + + context = g_main_context_get_thread_default (); + + if (!context) + context = g_main_context_default (); + + from_caps = GST_BUFFER_CAPS (buf); + + to_caps_copy = gst_caps_new_empty (); + n = gst_caps_get_size (to_caps); + for (i = 0; i < n; i++) { + GstStructure *s = gst_caps_get_structure (to_caps, i); + + s = gst_structure_copy (s); + gst_structure_remove_field (s, "framerate"); + gst_caps_append_structure (to_caps_copy, s); + } + + pipeline = + build_convert_frame_pipeline (&src, &sink, from_caps, to_caps_copy, + &error); + if (!pipeline) + goto no_pipeline; + + bus = gst_element_get_bus (pipeline); + + ctx = g_slice_new0 (GstVideoConvertFrameContext); + ctx->mutex = g_mutex_new (); + ctx->buffer = gst_buffer_ref (buf); + ctx->callback = callback; + ctx->user_data = user_data; + ctx->destroy_notify = destroy_notify; + ctx->context = g_main_context_ref (context); + ctx->finished = FALSE; + ctx->pipeline = pipeline; + + if (timeout != GST_CLOCK_TIME_NONE) { + source = g_timeout_source_new (timeout / GST_MSECOND); + g_source_set_callback (source, + (GSourceFunc) convert_frame_timeout_callback, ctx, NULL); + ctx->timeout_id = g_source_attach (source, context); + g_source_unref (source); + } + + g_signal_connect (src, "need-data", + G_CALLBACK (convert_frame_need_data_callback), ctx); + g_signal_connect (sink, "new-preroll", + G_CALLBACK (convert_frame_new_buffer_callback), ctx); + + source = gst_bus_create_watch (bus); + g_source_set_callback (source, (GSourceFunc) convert_frame_bus_callback, + ctx, NULL); + g_source_attach (source, context); + g_source_unref (source); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + gst_object_unref (bus); + gst_caps_unref (to_caps_copy); + + return; + /* ERRORS */ +no_pipeline: + { + GstVideoConvertFrameCallbackContext *ctx; + GSource *source; + + gst_caps_unref (to_caps_copy); + + ctx = g_slice_new0 (GstVideoConvertFrameCallbackContext); + ctx->callback = callback; + ctx->user_data = user_data; + ctx->destroy_notify = destroy_notify; + ctx->buffer = NULL; + ctx->error = error; + + source = g_timeout_source_new (0); + g_source_set_callback (source, + (GSourceFunc) convert_frame_dispatch_callback, ctx, + (GDestroyNotify) gst_video_convert_frame_callback_context_free); + g_source_attach (source, context); + g_source_unref (source); + } +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.c new file mode 100644 index 0000000..2d08a60 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.c @@ -0,0 +1,124 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2003> David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstvideofilter + * @short_description: Base class for video filters + * + * + * + * Provides useful functions and a base class for video filters. + * + * + * The videofilter will by default enable QoS on the parent GstBaseTransform + * to implement frame dropping. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvideofilter.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_video_filter_debug); +#define GST_CAT_DEFAULT gst_video_filter_debug + +static void gst_video_filter_class_init (gpointer g_class, gpointer class_data); +static void gst_video_filter_init (GTypeInstance * instance, gpointer g_class); + +static GstBaseTransformClass *parent_class = NULL; + +GType +gst_video_filter_get_type (void) +{ + static GType video_filter_type = 0; + + if (!video_filter_type) { + static const GTypeInfo video_filter_info = { + sizeof (GstVideoFilterClass), + NULL, + NULL, + gst_video_filter_class_init, + NULL, + NULL, + sizeof (GstVideoFilter), + 0, + gst_video_filter_init, + }; + + video_filter_type = g_type_register_static (GST_TYPE_BASE_TRANSFORM, + "GstVideoFilter", &video_filter_info, G_TYPE_FLAG_ABSTRACT); + } + return video_filter_type; +} + +static gboolean +gst_video_filter_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) +{ + GstVideoFormat fmt; + gint width, height; + + if (!gst_video_format_parse_caps (caps, &fmt, &width, &height)) { + GST_WARNING_OBJECT (btrans, "Failed to parse caps %" GST_PTR_FORMAT, caps); + return FALSE; + } + + *size = gst_video_format_get_size (fmt, width, height); + + GST_DEBUG_OBJECT (btrans, "Returning size %u bytes for caps %" + GST_PTR_FORMAT, *size, caps); + + return TRUE; +} + +static void +gst_video_filter_class_init (gpointer g_class, gpointer class_data) +{ + GstBaseTransformClass *trans_class; + GstVideoFilterClass *klass; + + klass = (GstVideoFilterClass *) g_class; + trans_class = (GstBaseTransformClass *) klass; + + trans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_video_filter_get_unit_size); + + parent_class = g_type_class_peek_parent (klass); + + GST_DEBUG_CATEGORY_INIT (gst_video_filter_debug, "videofilter", 0, + "videofilter"); +} + +static void +gst_video_filter_init (GTypeInstance * instance, gpointer g_class) +{ + GstVideoFilter *videofilter = GST_VIDEO_FILTER (instance); + + GST_DEBUG_OBJECT (videofilter, "gst_video_filter_init"); + + videofilter->inited = FALSE; + /* enable QoS */ + gst_base_transform_set_qos_enabled (GST_BASE_TRANSFORM (videofilter), TRUE); +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.h new file mode 100644 index 0000000..1c02061 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideofilter.h @@ -0,0 +1,58 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VIDEO_FILTER_H__ +#define __GST_VIDEO_FILTER_H__ + +#include + +G_BEGIN_DECLS + +typedef struct _GstVideoFilter GstVideoFilter; +typedef struct _GstVideoFilterClass GstVideoFilterClass; + +#define GST_TYPE_VIDEO_FILTER \ + (gst_video_filter_get_type()) +#define GST_VIDEO_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_FILTER,GstVideoFilter)) +#define GST_VIDEO_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_FILTER,GstVideoFilterClass)) +#define GST_VIDEO_FILTER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS((obj), GST_TYPE_VIDEO_FILTER, GstVideoFilterClass)) +#define GST_IS_VIDEO_FILTER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_FILTER)) +#define GST_IS_VIDEO_FILTER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_FILTER)) + +struct _GstVideoFilter { + GstBaseTransform element; + + gboolean inited; +}; + +struct _GstVideoFilterClass { + GstBaseTransformClass parent_class; +}; + +GType gst_video_filter_get_type (void); + +G_END_DECLS + +#endif /* __GST_VIDEO_FILTER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.c new file mode 100644 index 0000000..2e578d3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.c @@ -0,0 +1,288 @@ +/* GStreamer video sink base class + * Copyright (C) <2003> Julien Moutte + * Copyright (C) <2009> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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:gstvideosink + * @short_description: Base class for video sinks + * + * + * + * Provides useful functions and a base class for video sinks. + * + * + * GstVideoSink will configure the default base sink to drop frames that + * arrive later than 20ms as this is considered the default threshold for + * observing out-of-sync frames. + * + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvideosink.h" + +enum +{ + PROP_SHOW_PREROLL_FRAME = 1 +}; + +#define DEFAULT_SHOW_PREROLL_FRAME TRUE + +struct _GstVideoSinkPrivate +{ + gboolean show_preroll_frame; /* ATOMIC */ +}; + +GST_DEBUG_CATEGORY_STATIC (video_sink_debug); +#define GST_CAT_DEFAULT video_sink_debug + +static GstBaseSinkClass *parent_class = NULL; + +static void gst_video_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_video_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstFlowReturn gst_video_sink_show_preroll_frame (GstBaseSink * bsink, + GstBuffer * buf); +static GstFlowReturn gst_video_sink_show_frame (GstBaseSink * bsink, + GstBuffer * buf); + +/** + * gst_video_sink_center_rect: + * @src: the #GstVideoRectangle describing the source area + * @dst: the #GstVideoRectangle describing the destination area + * @result: a pointer to a #GstVideoRectangle which will receive the result area + * @scaling: a #gboolean indicating if scaling should be applied or not + * + * Takes @src rectangle and position it at the center of @dst rectangle with or + * without @scaling. It handles clipping if the @src rectangle is bigger than + * the @dst one and @scaling is set to FALSE. + */ +void +gst_video_sink_center_rect (GstVideoRectangle src, GstVideoRectangle dst, + GstVideoRectangle * result, gboolean scaling) +{ + g_return_if_fail (result != NULL); + + if (!scaling) { + result->w = MIN (src.w, dst.w); + result->h = MIN (src.h, dst.h); + result->x = (dst.w - result->w) / 2; + result->y = (dst.h - result->h) / 2; + } else { + gdouble src_ratio, dst_ratio; + + src_ratio = (gdouble) src.w / src.h; + dst_ratio = (gdouble) dst.w / dst.h; + + if (src_ratio > dst_ratio) { + result->w = dst.w; + result->h = dst.w / src_ratio; + result->x = 0; + result->y = (dst.h - result->h) / 2; + } else if (src_ratio < dst_ratio) { + result->w = dst.h * src_ratio; + result->h = dst.h; + result->x = (dst.w - result->w) / 2; + result->y = 0; + } else { + result->x = 0; + result->y = 0; + result->w = dst.w; + result->h = dst.h; + } + } + + GST_DEBUG ("source is %dx%d dest is %dx%d, result is %dx%d with x,y %dx%d", + src.w, src.h, dst.w, dst.h, result->w, result->h, result->x, result->y); +} + +/* Initing stuff */ + +static void +gst_video_sink_init (GstVideoSink * videosink) +{ + videosink->width = 0; + videosink->height = 0; + + /* 20ms is more than enough, 80-130ms is noticable */ + gst_base_sink_set_max_lateness (GST_BASE_SINK (videosink), 20 * GST_MSECOND); + gst_base_sink_set_qos_enabled (GST_BASE_SINK (videosink), TRUE); + + videosink->priv = G_TYPE_INSTANCE_GET_PRIVATE (videosink, + GST_TYPE_VIDEO_SINK, GstVideoSinkPrivate); +} + +static void +gst_video_sink_class_init (GstVideoSinkClass * klass) +{ + GstBaseSinkClass *basesink_class = (GstBaseSinkClass *) klass; + GObjectClass *gobject_class = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_video_sink_set_property; + gobject_class->get_property = gst_video_sink_get_property; + + /** + * GstVideoSink:show-preroll-frame + * + * Whether to show video frames during preroll. If set to #FALSE, video + * frames will only be rendered in PLAYING state. + * + * Since: 0.10.25 + */ + g_object_class_install_property (gobject_class, PROP_SHOW_PREROLL_FRAME, + g_param_spec_boolean ("show-preroll-frame", "Show preroll frame", + "Whether to render video frames during preroll", + DEFAULT_SHOW_PREROLL_FRAME, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + basesink_class->render = GST_DEBUG_FUNCPTR (gst_video_sink_show_frame); + basesink_class->preroll = + GST_DEBUG_FUNCPTR (gst_video_sink_show_preroll_frame); + + g_type_class_add_private (klass, sizeof (GstVideoSinkPrivate)); +} + +static void +gst_video_sink_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (video_sink_debug, "videosink", 0, "GstVideoSink"); +} + +static GstFlowReturn +gst_video_sink_show_preroll_frame (GstBaseSink * bsink, GstBuffer * buf) +{ + GstVideoSinkClass *klass; + GstVideoSink *vsink; + gboolean do_show; + + vsink = GST_VIDEO_SINK_CAST (bsink); + klass = GST_VIDEO_SINK_GET_CLASS (vsink); + + do_show = g_atomic_int_get (&vsink->priv->show_preroll_frame); + + if (G_UNLIKELY (!do_show)) { + GST_DEBUG_OBJECT (bsink, "not rendering frame with ts=%" GST_TIME_FORMAT + ", preroll rendering disabled", + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + } + + if (klass->show_frame == NULL || !do_show) { + if (parent_class->preroll != NULL) + return parent_class->preroll (bsink, buf); + else + return GST_FLOW_OK; + } + + GST_LOG_OBJECT (bsink, "rendering frame, ts=%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + return klass->show_frame (GST_VIDEO_SINK_CAST (bsink), buf); +} + +static GstFlowReturn +gst_video_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) +{ + GstVideoSinkClass *klass; + + klass = GST_VIDEO_SINK_GET_CLASS (bsink); + + if (klass->show_frame == NULL) { + if (parent_class->render != NULL) + return parent_class->render (bsink, buf); + else + return GST_FLOW_OK; + } + + GST_LOG_OBJECT (bsink, "rendering frame, ts=%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + return klass->show_frame (GST_VIDEO_SINK_CAST (bsink), buf); +} + +static void +gst_video_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVideoSink *vsink; + + vsink = GST_VIDEO_SINK (object); + + switch (prop_id) { + case PROP_SHOW_PREROLL_FRAME: + g_atomic_int_set (&vsink->priv->show_preroll_frame, + g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVideoSink *vsink; + + vsink = GST_VIDEO_SINK (object); + + switch (prop_id) { + case PROP_SHOW_PREROLL_FRAME: + g_value_set_boolean (value, + g_atomic_int_get (&vsink->priv->show_preroll_frame)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* Public methods */ + +GType +gst_video_sink_get_type (void) +{ + static GType videosink_type = 0; + + if (!videosink_type) { + static const GTypeInfo videosink_info = { + sizeof (GstVideoSinkClass), + gst_video_sink_base_init, + NULL, + (GClassInitFunc) gst_video_sink_class_init, + NULL, + NULL, + sizeof (GstVideoSink), + 0, + (GInstanceInitFunc) gst_video_sink_init, + }; + + videosink_type = g_type_register_static (GST_TYPE_BASE_SINK, + "GstVideoSink", &videosink_info, 0); + } + + return videosink_type; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.h new file mode 100644 index 0000000..d03a285 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/gstvideosink.h @@ -0,0 +1,132 @@ +/* GStreamer video sink base class + * Copyright (C) <2003> Julien Moutte + * Copyright (C) <2009> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* FIXME 0.11: turn this into a proper base class */ + +#ifndef __GST_VIDEO_SINK_H__ +#define __GST_VIDEO_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_SINK (gst_video_sink_get_type()) +#define GST_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VIDEO_SINK, GstVideoSink)) +#define GST_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VIDEO_SINK, GstVideoSinkClass)) +#define GST_IS_VIDEO_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VIDEO_SINK)) +#define GST_IS_VIDEO_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VIDEO_SINK)) +#define GST_VIDEO_SINK_GET_CLASS(klass) \ + (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_VIDEO_SINK, GstVideoSinkClass)) + +/** + * GST_VIDEO_SINK_CAST: + * @obj: a #GstVideoSink or derived object + * + * Cast @obj to a #GstVideoSink without runtime type check. + * + * Since: 0.10.12 + */ +#define GST_VIDEO_SINK_CAST(obj) ((GstVideoSink *) (obj)) + +/** + * GST_VIDEO_SINK_PAD: + * @obj: a #GstVideoSink + * + * Get the sink #GstPad of @obj. + */ +#define GST_VIDEO_SINK_PAD(obj) GST_BASE_SINK_PAD(obj) + +#define GST_VIDEO_SINK_WIDTH(obj) (GST_VIDEO_SINK_CAST (obj)->width) +#define GST_VIDEO_SINK_HEIGHT(obj) (GST_VIDEO_SINK_CAST (obj)->height) + +typedef struct _GstVideoSink GstVideoSink; +typedef struct _GstVideoSinkClass GstVideoSinkClass; +typedef struct _GstVideoRectangle GstVideoRectangle; +typedef struct _GstVideoSinkPrivate GstVideoSinkPrivate; + +/** + * GstVideoRectangle: + * @x: X coordinate of rectangle's top-left point + * @y: Y coordinate of rectangle's top-left point + * @w: width of the rectangle + * @h: height of the rectangle + * + * Helper structure representing a rectangular area. + */ +struct _GstVideoRectangle { + gint x; + gint y; + gint w; + gint h; +}; + +/** + * GstVideoSink: + * @element: the parent object structure (which is GstBaseSink) + * @height: video height (derived class needs to set this) + * @width: video width (derived class needs to set this) + * + * The video sink instance structure. Derived video sinks should set the + * @height and @width members. + */ +struct _GstVideoSink { + GstBaseSink element; /* FIXME 0.11: this should not be called 'element' */ + + gint width, height; + + /*< private >*/ + GstVideoSinkPrivate *priv; + + gpointer _gst_reserved[GST_PADDING - 1]; +}; + +/** + * GstVideoSinkClass: + * @parent_class: the parent class structure + * @show_frame: render a video frame. Maps to #GstBaseSink::render and + * #GstBaseSink::preroll vfuncs. Rendering during preroll will be + * suppressed if the 'show-preroll-frame' property is set to #FALSE. + * Since: 0.10.25 + * + * The video sink class structure. Derived classes should override the + * @show_frame virtual function. + */ +struct _GstVideoSinkClass { + GstBaseSinkClass parent_class; + + GstFlowReturn (*show_frame) (GstVideoSink *video_sink, GstBuffer *buf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING - 1]; +}; + +GType gst_video_sink_get_type (void); + +void gst_video_sink_center_rect (GstVideoRectangle src, GstVideoRectangle dst, + GstVideoRectangle *result, gboolean scaling); + +G_END_DECLS + +#endif /* __GST_VIDEO_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.c b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.c new file mode 100644 index 0000000..a369387 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.c @@ -0,0 +1,2295 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2002> Ronald Bultje + * Copyright (C) 2007 David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "video.h" + +/** + * SECTION:gstvideo + * @short_description: Support library for video operations + * + * + * + * This library contains some helper functions and includes the + * videosink and videofilter base classes. + * + * + */ + +static GstVideoFormat gst_video_format_from_rgb32_masks (int red_mask, + int green_mask, int blue_mask); +static GstVideoFormat gst_video_format_from_rgba32_masks (int red_mask, + int green_mask, int blue_mask, int alpha_mask); +static GstVideoFormat gst_video_format_from_rgb24_masks (int red_mask, + int green_mask, int blue_mask); +static GstVideoFormat gst_video_format_from_rgb16_masks (int red_mask, + int green_mask, int blue_mask); + + +/** + * gst_video_frame_rate: + * @pad: pointer to a #GstPad + * + * A convenience function to retrieve a GValue holding the framerate + * from the caps on a pad. + * + * The pad needs to have negotiated caps containing a framerate property. + * + * Returns: NULL if the pad has no configured caps or the configured caps + * do not contain a framerate. + * + */ +const GValue * +gst_video_frame_rate (GstPad * pad) +{ + const GValue *fps; + gchar *fps_string; + + const GstCaps *caps = NULL; + GstStructure *structure; + + /* get pad caps */ + caps = GST_PAD_CAPS (pad); + if (caps == NULL) { + g_warning ("gstvideo: failed to get caps of pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + return NULL; + } + + structure = gst_caps_get_structure (caps, 0); + if ((fps = gst_structure_get_value (structure, "framerate")) == NULL) { + g_warning ("gstvideo: failed to get framerate property of pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + return NULL; + } + if (!GST_VALUE_HOLDS_FRACTION (fps)) { + g_warning + ("gstvideo: framerate property of pad %s:%s is not of type Fraction", + GST_DEBUG_PAD_NAME (pad)); + return NULL; + } + + fps_string = gst_value_serialize (fps); + GST_DEBUG ("Framerate request on pad %s:%s: %s", + GST_DEBUG_PAD_NAME (pad), fps_string); + g_free (fps_string); + + return fps; +} + +/** + * gst_video_get_size: + * @pad: pointer to a #GstPad + * @width: pointer to integer to hold pixel width of the video frames (output) + * @height: pointer to integer to hold pixel height of the video frames (output) + * + * Inspect the caps of the provided pad and retrieve the width and height of + * the video frames it is configured for. + * + * The pad needs to have negotiated caps containing width and height properties. + * + * Returns: TRUE if the width and height could be retrieved. + * + */ +gboolean +gst_video_get_size (GstPad * pad, gint * width, gint * height) +{ + const GstCaps *caps = NULL; + GstStructure *structure; + gboolean ret; + + g_return_val_if_fail (pad != NULL, FALSE); + g_return_val_if_fail (width != NULL, FALSE); + g_return_val_if_fail (height != NULL, FALSE); + + caps = GST_PAD_CAPS (pad); + + if (caps == NULL) { + g_warning ("gstvideo: failed to get caps of pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + return FALSE; + } + + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", width); + ret &= gst_structure_get_int (structure, "height", height); + + if (!ret) { + g_warning ("gstvideo: failed to get size properties on pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + return FALSE; + } + + GST_DEBUG ("size request on pad %s:%s: %dx%d", + GST_DEBUG_PAD_NAME (pad), width ? *width : -1, height ? *height : -1); + + return TRUE; +} + +/** + * gst_video_calculate_display_ratio: + * @dar_n: Numerator of the calculated display_ratio + * @dar_d: Denominator of the calculated display_ratio + * @video_width: Width of the video frame in pixels + * @video_height: Height of the video frame in pixels + * @video_par_n: Numerator of the pixel aspect ratio of the input video. + * @video_par_d: Denominator of the pixel aspect ratio of the input video. + * @display_par_n: Numerator of the pixel aspect ratio of the display device + * @display_par_d: Denominator of the pixel aspect ratio of the display device + * + * Given the Pixel Aspect Ratio and size of an input video frame, and the + * pixel aspect ratio of the intended display device, calculates the actual + * display ratio the video will be rendered with. + * + * Returns: A boolean indicating success and a calculated Display Ratio in the + * dar_n and dar_d parameters. + * The return value is FALSE in the case of integer overflow or other error. + * + * Since: 0.10.7 + */ +gboolean +gst_video_calculate_display_ratio (guint * dar_n, guint * dar_d, + guint video_width, guint video_height, + guint video_par_n, guint video_par_d, + guint display_par_n, guint display_par_d) +{ + gint num, den; + gint tmp_n, tmp_d; + + g_return_val_if_fail (dar_n != NULL, FALSE); + g_return_val_if_fail (dar_d != NULL, FALSE); + + /* Calculate (video_width * video_par_n * display_par_d) / + * (video_height * video_par_d * display_par_n) */ + if (!gst_util_fraction_multiply (video_width, video_height, video_par_n, + video_par_d, &tmp_n, &tmp_d)) + goto error_overflow; + + if (!gst_util_fraction_multiply (tmp_n, tmp_d, display_par_d, display_par_n, + &num, &den)) + goto error_overflow; + + g_return_val_if_fail (num > 0, FALSE); + g_return_val_if_fail (den > 0, FALSE); + + *dar_n = num; + *dar_d = den; + + return TRUE; +error_overflow: + return FALSE; +} + +/** + * gst_video_format_parse_caps_interlaced: + * @caps: the fixed #GstCaps to parse + * @interlaced: whether @caps represents interlaced video or not, may be NULL (output) + * + * Extracts whether the caps represents interlaced content or not and places it + * in @interlaced. + * + * Since: 0.10.23 + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_format_parse_caps_interlaced (GstCaps * caps, gboolean * interlaced) +{ + GstStructure *structure; + + if (!gst_caps_is_fixed (caps)) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + + if (interlaced) { + if (!gst_structure_get_boolean (structure, "interlaced", interlaced)) + *interlaced = FALSE; + } + + return TRUE; +} + +/** + * gst_video_parse_caps_color_matrix: + * @caps: the fixed #GstCaps to parse + * + * Extracts the color matrix used by the caps. Possible values are + * "sdtv" for the standard definition color matrix (as specified in + * Rec. ITU-R BT.470-6) or "hdtv" for the high definition color + * matrix (as specified in Rec. ITU-R BT.709) + * + * Since: 0.10.29 + * + * Returns: a color matrix string, or NULL if no color matrix could be + * determined. + */ +const char * +gst_video_parse_caps_color_matrix (GstCaps * caps) +{ + GstStructure *structure; + const char *s; + + if (!gst_caps_is_fixed (caps)) + return NULL; + + structure = gst_caps_get_structure (caps, 0); + + s = gst_structure_get_string (structure, "color-matrix"); + if (s) + return s; + + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + return "sdtv"; + } + + return NULL; +} + +/** + * gst_video_parse_caps_chroma_site: + * @caps: the fixed #GstCaps to parse + * + * Extracts the chroma site used by the caps. Possible values are + * "mpeg2" for MPEG-2 style chroma siting (co-sited horizontally, + * halfway-sited vertically), "jpeg" for JPEG and Theora style + * chroma siting (halfway-sited both horizontally and vertically). + * Other chroma site values are possible, but uncommon. + * + * When no chroma site is specified in the caps, it should be assumed + * to be "mpeg2". + * + * Since: 0.10.29 + * + * Returns: a chroma site string, or NULL if no chroma site could be + * determined. + */ +const char * +gst_video_parse_caps_chroma_site (GstCaps * caps) +{ + GstStructure *structure; + const char *s; + + if (!gst_caps_is_fixed (caps)) + return NULL; + + structure = gst_caps_get_structure (caps, 0); + + s = gst_structure_get_string (structure, "chroma-site"); + if (s) + return s; + + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + return "mpeg2"; + } + + return NULL; +} + +/** + * gst_video_format_parse_caps: + * @caps: the #GstCaps to parse + * @format: the #GstVideoFormat of the video represented by @caps (output) + * @width: the width of the video represented by @caps, may be NULL (output) + * @height: the height of the video represented by @caps, may be NULL (output) + * + * Determines the #GstVideoFormat of @caps and places it in the location + * pointed to by @format. Extracts the size of the video and places it + * in the location pointed to by @width and @height. If @caps does not + * represent one of the raw video formats listed in #GstVideoFormat, the + * function will fail and return FALSE. + * + * Since: 0.10.16 + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_format_parse_caps (GstCaps * caps, GstVideoFormat * format, + int *width, int *height) +{ + GstStructure *structure; + gboolean ok = TRUE; + + if (!gst_caps_is_fixed (caps)) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + + if (format) { + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + guint32 fourcc; + + ok &= gst_structure_get_fourcc (structure, "format", &fourcc); + + *format = gst_video_format_from_fourcc (fourcc); + if (*format == GST_VIDEO_FORMAT_UNKNOWN) { + ok = FALSE; + } + } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) { + int depth; + int bpp; + int endianness = 0; + int red_mask = 0; + int green_mask = 0; + int blue_mask = 0; + int alpha_mask = 0; + gboolean have_alpha; + + ok &= gst_structure_get_int (structure, "depth", &depth); + ok &= gst_structure_get_int (structure, "bpp", &bpp); + + if (bpp != 8) { + ok &= gst_structure_get_int (structure, "endianness", &endianness); + ok &= gst_structure_get_int (structure, "red_mask", &red_mask); + ok &= gst_structure_get_int (structure, "green_mask", &green_mask); + ok &= gst_structure_get_int (structure, "blue_mask", &blue_mask); + } + have_alpha = gst_structure_get_int (structure, "alpha_mask", &alpha_mask); + + if (depth == 30 && bpp == 32 && endianness == G_BIG_ENDIAN) { + *format = GST_VIDEO_FORMAT_r210; + } else if (depth == 24 && bpp == 32 && endianness == G_BIG_ENDIAN) { + *format = gst_video_format_from_rgb32_masks (red_mask, green_mask, + blue_mask); + if (*format == GST_VIDEO_FORMAT_UNKNOWN) { + ok = FALSE; + } + } else if (depth == 32 && bpp == 32 && endianness == G_BIG_ENDIAN && + have_alpha) { + *format = gst_video_format_from_rgba32_masks (red_mask, green_mask, + blue_mask, alpha_mask); + if (*format == GST_VIDEO_FORMAT_UNKNOWN) { + ok = FALSE; + } + } else if (depth == 24 && bpp == 24 && endianness == G_BIG_ENDIAN) { + *format = gst_video_format_from_rgb24_masks (red_mask, green_mask, + blue_mask); + if (*format == GST_VIDEO_FORMAT_UNKNOWN) { + ok = FALSE; + } + } else if ((depth == 15 || depth == 16) && bpp == 16 && + endianness == G_BYTE_ORDER) { + *format = gst_video_format_from_rgb16_masks (red_mask, green_mask, + blue_mask); + if (*format == GST_VIDEO_FORMAT_UNKNOWN) { + ok = FALSE; + } + } else if (depth == 8 && bpp == 8) { + *format = GST_VIDEO_FORMAT_RGB8_PALETTED; + } else if (depth == 64 && bpp == 64) { + *format = gst_video_format_from_rgba32_masks (red_mask, green_mask, + blue_mask, alpha_mask); + if (*format == GST_VIDEO_FORMAT_ARGB) { + *format = GST_VIDEO_FORMAT_ARGB64; + } else { + *format = GST_VIDEO_FORMAT_UNKNOWN; + ok = FALSE; + } + } else { + ok = FALSE; + } + } else if (gst_structure_has_name (structure, "video/x-raw-gray")) { + int depth; + int bpp; + int endianness; + + ok &= gst_structure_get_int (structure, "depth", &depth); + ok &= gst_structure_get_int (structure, "bpp", &bpp); + + if (bpp > 8) + ok &= gst_structure_get_int (structure, "endianness", &endianness); + + if (depth == 8 && bpp == 8) { + *format = GST_VIDEO_FORMAT_GRAY8; + } else if (depth == 16 && bpp == 16 && endianness == G_BIG_ENDIAN) { + *format = GST_VIDEO_FORMAT_GRAY16_BE; + } else if (depth == 16 && bpp == 16 && endianness == G_LITTLE_ENDIAN) { + *format = GST_VIDEO_FORMAT_GRAY16_LE; + } else { + ok = FALSE; + } + } else { + ok = FALSE; + } + } + + if (width) { + ok &= gst_structure_get_int (structure, "width", width); + } + + if (height) { + ok &= gst_structure_get_int (structure, "height", height); + } + + return ok; +} + + +/** + * gst_video_parse_caps_framerate: + * @caps: pointer to a #GstCaps instance + * @fps_n: pointer to integer to hold numerator of frame rate (output) + * @fps_d: pointer to integer to hold denominator of frame rate (output) + * + * Extracts the frame rate from @caps and places the values in the locations + * pointed to by @fps_n and @fps_d. Returns TRUE if the values could be + * parsed correctly, FALSE if not. + * + * This function can be used with #GstCaps that have any media type; it + * is not limited to formats handled by #GstVideoFormat. + * + * Since: 0.10.16 + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_parse_caps_framerate (GstCaps * caps, int *fps_n, int *fps_d) +{ + GstStructure *structure; + + if (!gst_caps_is_fixed (caps)) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + + return gst_structure_get_fraction (structure, "framerate", fps_n, fps_d); +} + +/** + * gst_video_parse_caps_pixel_aspect_ratio: + * @caps: pointer to a #GstCaps instance + * @par_n: pointer to numerator of pixel aspect ratio (output) + * @par_d: pointer to denominator of pixel aspect ratio (output) + * + * Extracts the pixel aspect ratio from @caps and places the values in + * the locations pointed to by @par_n and @par_d. Returns TRUE if the + * values could be parsed correctly, FALSE if not. + * + * This function can be used with #GstCaps that have any media type; it + * is not limited to formats handled by #GstVideoFormat. + * + * Since: 0.10.16 + * + * Returns: TRUE if @caps was parsed correctly. + */ +gboolean +gst_video_parse_caps_pixel_aspect_ratio (GstCaps * caps, int *par_n, int *par_d) +{ + GstStructure *structure; + + if (!gst_caps_is_fixed (caps)) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_fraction (structure, "pixel-aspect-ratio", + par_n, par_d)) { + *par_n = 1; + *par_d = 1; + } + return TRUE; +} + +/** + * gst_video_format_new_caps_interlaced: + * @format: the #GstVideoFormat describing the raw video format + * @width: width of video + * @height: height of video + * @framerate_n: numerator of frame rate + * @framerate_d: denominator of frame rate + * @par_n: numerator of pixel aspect ratio + * @par_d: denominator of pixel aspect ratio + * @interlaced: #TRUE if the format is interlaced + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: 0.10.23 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps_interlaced (GstVideoFormat format, + int width, int height, int framerate_n, int framerate_d, int par_n, + int par_d, gboolean interlaced) +{ + GstCaps *res; + + res = + gst_video_format_new_caps (format, width, height, framerate_n, + framerate_d, par_n, par_d); + if (interlaced && (res != NULL)) + gst_caps_set_simple (res, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL); + + return res; +} + +static GstCaps * +gst_video_format_new_caps_raw (GstVideoFormat format) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + + if (gst_video_format_is_yuv (format)) { + return gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, gst_video_format_to_fourcc (format), NULL); + } + if (gst_video_format_is_rgb (format)) { + GstCaps *caps; + int red_mask = 0; + int blue_mask = 0; + int green_mask = 0; + int alpha_mask; + int depth; + int bpp; + gboolean have_alpha; + unsigned int mask = 0; + + switch (format) { + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + bpp = 32; + depth = 24; + have_alpha = FALSE; + break; + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + bpp = 32; + depth = 32; + have_alpha = TRUE; + break; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + bpp = 24; + depth = 24; + have_alpha = FALSE; + break; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + bpp = 16; + depth = 16; + have_alpha = FALSE; + break; + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + bpp = 16; + depth = 15; + have_alpha = FALSE; + break; + case GST_VIDEO_FORMAT_RGB8_PALETTED: + bpp = 8; + depth = 8; + have_alpha = FALSE; + break; + case GST_VIDEO_FORMAT_ARGB64: + bpp = 64; + depth = 64; + have_alpha = TRUE; + break; + case GST_VIDEO_FORMAT_r210: + bpp = 32; + depth = 30; + have_alpha = FALSE; + break; + default: + return NULL; + } + if (bpp == 32 && depth == 30) { + red_mask = 0x3ff00000; + green_mask = 0x000ffc00; + blue_mask = 0x000003ff; + have_alpha = FALSE; + } else if (bpp == 32 || bpp == 24 || bpp == 64) { + if (bpp == 32) { + mask = 0xff000000; + } else { + mask = 0xff0000; + } + red_mask = + mask >> (8 * gst_video_format_get_component_offset (format, 0, 0, 0)); + green_mask = + mask >> (8 * gst_video_format_get_component_offset (format, 1, 0, 0)); + blue_mask = + mask >> (8 * gst_video_format_get_component_offset (format, 2, 0, 0)); + } else if (bpp == 16) { + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + red_mask = GST_VIDEO_COMP1_MASK_16_INT; + green_mask = GST_VIDEO_COMP2_MASK_16_INT; + blue_mask = GST_VIDEO_COMP3_MASK_16_INT; + break; + case GST_VIDEO_FORMAT_BGR16: + red_mask = GST_VIDEO_COMP3_MASK_16_INT; + green_mask = GST_VIDEO_COMP2_MASK_16_INT; + blue_mask = GST_VIDEO_COMP1_MASK_16_INT; + break; + break; + case GST_VIDEO_FORMAT_RGB15: + red_mask = GST_VIDEO_COMP1_MASK_15_INT; + green_mask = GST_VIDEO_COMP2_MASK_15_INT; + blue_mask = GST_VIDEO_COMP3_MASK_15_INT; + break; + case GST_VIDEO_FORMAT_BGR15: + red_mask = GST_VIDEO_COMP3_MASK_15_INT; + green_mask = GST_VIDEO_COMP2_MASK_15_INT; + blue_mask = GST_VIDEO_COMP1_MASK_15_INT; + break; + default: + return NULL; + } + } else if (bpp != 8) { + return NULL; + } + + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); + + if (bpp != 8) { + gst_caps_set_simple (caps, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "red_mask", G_TYPE_INT, red_mask, + "green_mask", G_TYPE_INT, green_mask, + "blue_mask", G_TYPE_INT, blue_mask, NULL); + } + + if (have_alpha) { + alpha_mask = + mask >> (8 * gst_video_format_get_component_offset (format, 3, 0, 0)); + gst_caps_set_simple (caps, "alpha_mask", G_TYPE_INT, alpha_mask, NULL); + } + return caps; + } + + if (gst_video_format_is_gray (format)) { + GstCaps *caps; + int bpp; + int depth; + int endianness; + + switch (format) { + case GST_VIDEO_FORMAT_GRAY8: + bpp = depth = 8; + endianness = G_BIG_ENDIAN; + break; + case GST_VIDEO_FORMAT_GRAY16_BE: + bpp = depth = 16; + endianness = G_BIG_ENDIAN; + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + bpp = depth = 16; + endianness = G_LITTLE_ENDIAN; + break; + default: + return NULL; + break; + } + + if (bpp <= 8) { + caps = gst_caps_new_simple ("video/x-raw-gray", + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); + } else { + caps = gst_caps_new_simple ("video/x-raw-gray", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, endianness, NULL); + } + + return caps; + } + + return NULL; +} + +/** + * gst_video_format_new_template_caps: + * @format: the #GstVideoFormat describing the raw video format + * + * Creates a new #GstCaps object based on the parameters provided. + * Size, frame rate, and pixel aspect ratio are set to the full + * range. + * + * Since: 0.10.33 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_template_caps (GstVideoFormat format) +{ + GstCaps *caps; + GstStructure *structure; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + + caps = gst_video_format_new_caps_raw (format); + if (caps) { + GValue value = { 0 }; + GValue v = { 0 }; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_set (structure, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, + "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + g_value_init (&value, GST_TYPE_LIST); + g_value_init (&v, G_TYPE_BOOLEAN); + g_value_set_boolean (&v, TRUE); + gst_value_list_append_value (&value, &v); + g_value_set_boolean (&v, FALSE); + gst_value_list_append_value (&value, &v); + + gst_structure_set_value (structure, "interlaced", &value); + + g_value_reset (&value); + g_value_reset (&v); + } + + return caps; +} + +/** + * gst_video_format_new_caps: + * @format: the #GstVideoFormat describing the raw video format + * @width: width of video + * @height: height of video + * @framerate_n: numerator of frame rate + * @framerate_d: denominator of frame rate + * @par_n: numerator of pixel aspect ratio + * @par_d: denominator of pixel aspect ratio + * + * Creates a new #GstCaps object based on the parameters provided. + * + * Since: 0.10.16 + * + * Returns: a new #GstCaps object, or NULL if there was an error + */ +GstCaps * +gst_video_format_new_caps (GstVideoFormat format, int width, + int height, int framerate_n, int framerate_d, int par_n, int par_d) +{ + GstCaps *caps; + GstStructure *structure; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, NULL); + g_return_val_if_fail (width > 0 && height > 0, NULL); + + caps = gst_video_format_new_caps_raw (format); + if (caps) { + structure = gst_caps_get_structure (caps, 0); + + gst_structure_set (structure, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_n, framerate_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, NULL); + } + + return caps; +} + + +/** + * gst_video_format_from_fourcc: + * @fourcc: a FOURCC value representing raw YUV video + * + * Converts a FOURCC value into the corresponding #GstVideoFormat. + * If the FOURCC cannot be represented by #GstVideoFormat, + * #GST_VIDEO_FORMAT_UNKNOWN is returned. + * + * Since: 0.10.16 + * + * Returns: the #GstVideoFormat describing the FOURCC value + */ +GstVideoFormat +gst_video_format_from_fourcc (guint32 fourcc) +{ + switch (fourcc) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + return GST_VIDEO_FORMAT_I420; + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + return GST_VIDEO_FORMAT_YV12; + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + return GST_VIDEO_FORMAT_YUY2; + case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): + return GST_VIDEO_FORMAT_YVYU; + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + return GST_VIDEO_FORMAT_UYVY; + case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'): + return GST_VIDEO_FORMAT_AYUV; + case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): + return GST_VIDEO_FORMAT_Y41B; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + return GST_VIDEO_FORMAT_Y42B; + case GST_MAKE_FOURCC ('Y', '4', '4', '4'): + return GST_VIDEO_FORMAT_Y444; + case GST_MAKE_FOURCC ('v', '2', '1', '0'): + return GST_VIDEO_FORMAT_v210; + case GST_MAKE_FOURCC ('v', '2', '1', '6'): + return GST_VIDEO_FORMAT_v216; + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + return GST_VIDEO_FORMAT_NV12; + case GST_MAKE_FOURCC ('N', 'V', '2', '1'): + return GST_VIDEO_FORMAT_NV21; + case GST_MAKE_FOURCC ('v', '3', '0', '8'): + return GST_VIDEO_FORMAT_v308; + case GST_MAKE_FOURCC ('Y', '8', '0', '0'): + case GST_MAKE_FOURCC ('Y', '8', ' ', ' '): + case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'): + return GST_VIDEO_FORMAT_Y800; + case GST_MAKE_FOURCC ('Y', '1', '6', ' '): + return GST_VIDEO_FORMAT_Y16; + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'): + return GST_VIDEO_FORMAT_UYVP; + case GST_MAKE_FOURCC ('A', '4', '2', '0'): + return GST_VIDEO_FORMAT_A420; + case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'): + return GST_VIDEO_FORMAT_YUV9; + case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'): + return GST_VIDEO_FORMAT_YVU9; + case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'): + return GST_VIDEO_FORMAT_IYU1; + case GST_MAKE_FOURCC ('A', 'Y', '6', '4'): + return GST_VIDEO_FORMAT_AYUV64; + default: + return GST_VIDEO_FORMAT_UNKNOWN; + } +} + +/** + * gst_video_format_to_fourcc: + * @format: a #GstVideoFormat video format + * + * Converts a #GstVideoFormat value into the corresponding FOURCC. Only + * a few YUV formats have corresponding FOURCC values. If @format has + * no corresponding FOURCC value, 0 is returned. + * + * Since: 0.10.16 + * + * Returns: the FOURCC corresponding to @format + */ +guint32 +gst_video_format_to_fourcc (GstVideoFormat format) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + return GST_MAKE_FOURCC ('I', '4', '2', '0'); + case GST_VIDEO_FORMAT_YV12: + return GST_MAKE_FOURCC ('Y', 'V', '1', '2'); + case GST_VIDEO_FORMAT_YUY2: + return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); + case GST_VIDEO_FORMAT_YVYU: + return GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); + case GST_VIDEO_FORMAT_UYVY: + return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); + case GST_VIDEO_FORMAT_AYUV: + return GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'); + case GST_VIDEO_FORMAT_Y41B: + return GST_MAKE_FOURCC ('Y', '4', '1', 'B'); + case GST_VIDEO_FORMAT_Y42B: + return GST_MAKE_FOURCC ('Y', '4', '2', 'B'); + case GST_VIDEO_FORMAT_Y444: + return GST_MAKE_FOURCC ('Y', '4', '4', '4'); + case GST_VIDEO_FORMAT_v210: + return GST_MAKE_FOURCC ('v', '2', '1', '0'); + case GST_VIDEO_FORMAT_v216: + return GST_MAKE_FOURCC ('v', '2', '1', '6'); + case GST_VIDEO_FORMAT_NV12: + return GST_MAKE_FOURCC ('N', 'V', '1', '2'); + case GST_VIDEO_FORMAT_NV21: + return GST_MAKE_FOURCC ('N', 'V', '2', '1'); + case GST_VIDEO_FORMAT_v308: + return GST_MAKE_FOURCC ('v', '3', '0', '8'); + case GST_VIDEO_FORMAT_Y800: + return GST_MAKE_FOURCC ('Y', '8', '0', '0'); + case GST_VIDEO_FORMAT_Y16: + return GST_MAKE_FOURCC ('Y', '1', '6', ' '); + case GST_VIDEO_FORMAT_UYVP: + return GST_MAKE_FOURCC ('U', 'Y', 'V', 'P'); + case GST_VIDEO_FORMAT_A420: + return GST_MAKE_FOURCC ('A', '4', '2', '0'); + case GST_VIDEO_FORMAT_YUV9: + return GST_MAKE_FOURCC ('Y', 'U', 'V', '9'); + case GST_VIDEO_FORMAT_YVU9: + return GST_MAKE_FOURCC ('Y', 'V', 'U', '9'); + case GST_VIDEO_FORMAT_IYU1: + return GST_MAKE_FOURCC ('I', 'Y', 'U', '1'); + case GST_VIDEO_FORMAT_AYUV64: + return GST_MAKE_FOURCC ('A', 'Y', '6', '4'); + default: + return 0; + } +} + +/* + * gst_video_format_from_rgb32_masks: + * @red_mask: red bit mask + * @green_mask: green bit mask + * @blue_mask: blue bit mask + * + * Converts red, green, blue bit masks into the corresponding + * #GstVideoFormat. + * + * Since: 0.10.16 + * + * Returns: the #GstVideoFormat corresponding to the bit masks + */ +static GstVideoFormat +gst_video_format_from_rgb32_masks (int red_mask, int green_mask, int blue_mask) +{ + if (red_mask == 0xff000000 && green_mask == 0x00ff0000 && + blue_mask == 0x0000ff00) { + return GST_VIDEO_FORMAT_RGBx; + } + if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 && + blue_mask == 0xff000000) { + return GST_VIDEO_FORMAT_BGRx; + } + if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 && + blue_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_xRGB; + } + if (red_mask == 0x000000ff && green_mask == 0x0000ff00 && + blue_mask == 0x00ff0000) { + return GST_VIDEO_FORMAT_xBGR; + } + + return GST_VIDEO_FORMAT_UNKNOWN; +} + +static GstVideoFormat +gst_video_format_from_rgba32_masks (int red_mask, int green_mask, + int blue_mask, int alpha_mask) +{ + if (red_mask == 0xff000000 && green_mask == 0x00ff0000 && + blue_mask == 0x0000ff00 && alpha_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_RGBA; + } + if (red_mask == 0x0000ff00 && green_mask == 0x00ff0000 && + blue_mask == 0xff000000 && alpha_mask == 0x000000ff) { + return GST_VIDEO_FORMAT_BGRA; + } + if (red_mask == 0x00ff0000 && green_mask == 0x0000ff00 && + blue_mask == 0x000000ff && alpha_mask == 0xff000000) { + return GST_VIDEO_FORMAT_ARGB; + } + if (red_mask == 0x000000ff && green_mask == 0x0000ff00 && + blue_mask == 0x00ff0000 && alpha_mask == 0xff000000) { + return GST_VIDEO_FORMAT_ABGR; + } + + return GST_VIDEO_FORMAT_UNKNOWN; +} + +static GstVideoFormat +gst_video_format_from_rgb24_masks (int red_mask, int green_mask, int blue_mask) +{ + if (red_mask == 0xff0000 && green_mask == 0x00ff00 && blue_mask == 0x0000ff) { + return GST_VIDEO_FORMAT_RGB; + } + if (red_mask == 0x0000ff && green_mask == 0x00ff00 && blue_mask == 0xff0000) { + return GST_VIDEO_FORMAT_BGR; + } + + return GST_VIDEO_FORMAT_UNKNOWN; +} + +static GstVideoFormat +gst_video_format_from_rgb16_masks (int red_mask, int green_mask, int blue_mask) +{ + if (red_mask == GST_VIDEO_COMP1_MASK_16_INT + && green_mask == GST_VIDEO_COMP2_MASK_16_INT + && blue_mask == GST_VIDEO_COMP3_MASK_16_INT) { + return GST_VIDEO_FORMAT_RGB16; + } + if (red_mask == GST_VIDEO_COMP3_MASK_16_INT + && green_mask == GST_VIDEO_COMP2_MASK_16_INT + && blue_mask == GST_VIDEO_COMP1_MASK_16_INT) { + return GST_VIDEO_FORMAT_BGR16; + } + if (red_mask == GST_VIDEO_COMP1_MASK_15_INT + && green_mask == GST_VIDEO_COMP2_MASK_15_INT + && blue_mask == GST_VIDEO_COMP3_MASK_15_INT) { + return GST_VIDEO_FORMAT_RGB15; + } + if (red_mask == GST_VIDEO_COMP3_MASK_15_INT + && green_mask == GST_VIDEO_COMP2_MASK_15_INT + && blue_mask == GST_VIDEO_COMP1_MASK_15_INT) { + return GST_VIDEO_FORMAT_BGR15; + } + + return GST_VIDEO_FORMAT_UNKNOWN; +} + +/** + * gst_video_format_is_rgb: + * @format: a #GstVideoFormat + * + * Determine whether the video format is an RGB format. + * + * Since: 0.10.16 + * + * Returns: TRUE if @format represents RGB video + */ +gboolean +gst_video_format_is_rgb (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_UYVP: + case GST_VIDEO_FORMAT_A420: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + case GST_VIDEO_FORMAT_IYU1: + case GST_VIDEO_FORMAT_AYUV64: + return FALSE; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_r210: + return TRUE; + default: + return FALSE; + } +} + +/** + * gst_video_format_is_yuv: + * @format: a #GstVideoFormat + * + * Determine whether the video format is a YUV format. + * + * Since: 0.10.16 + * + * Returns: TRUE if @format represents YUV video + */ +gboolean +gst_video_format_is_yuv (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + case GST_VIDEO_FORMAT_UYVP: + case GST_VIDEO_FORMAT_A420: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + case GST_VIDEO_FORMAT_IYU1: + case GST_VIDEO_FORMAT_AYUV64: + return TRUE; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_r210: + return FALSE; + default: + return FALSE; + } +} + +/** + * gst_video_format_is_gray: + * @format: a #GstVideoFormat + * + * Determine whether the video format is a grayscale format. + * + * Since: 0.10.29 + * + * Returns: TRUE if @format represents grayscale video + */ +gboolean +gst_video_format_is_gray (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + return TRUE; + default: + return FALSE; + } +} + +/** + * gst_video_format_has_alpha: + * @format: a #GstVideoFormat + * + * Returns TRUE or FALSE depending on if the video format provides an + * alpha channel. + * + * Since: 0.10.16 + * + * Returns: TRUE if @format has an alpha channel + */ +gboolean +gst_video_format_has_alpha (GstVideoFormat format) +{ + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + case GST_VIDEO_FORMAT_UYVP: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + case GST_VIDEO_FORMAT_IYU1: + return FALSE; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_A420: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + return TRUE; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_r210: + return FALSE; + default: + return FALSE; + } +} + +/** + * gst_video_format_get_component_depth: + * @format: a #GstVideoFormat + * + * Returns the number of bits used to encode an individual pixel of + * a given component. Typically this is 8, although higher and lower + * values are possible for some formats. + * + * Since: 0.10.33 + * + * Returns: depth of component + */ +int +gst_video_format_get_component_depth (GstVideoFormat format, int component) +{ + if (component == 3 && !gst_video_format_has_alpha (format)) + return 0; + + switch (format) { + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + if (component == 1) + return 6; + return 5; + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + return 5; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + case GST_VIDEO_FORMAT_IYU1: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_A420: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + default: + return 8; + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_UYVP: + case GST_VIDEO_FORMAT_r210: + return 10; + case GST_VIDEO_FORMAT_Y16: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + return 16; + } + +} + +/** + * gst_video_format_get_row_stride: + * @format: a #GstVideoFormat + * @component: the component index + * @width: the width of video + * + * Calculates the row stride (number of bytes from one row of pixels to + * the next) for the video component with an index of @component. For + * YUV video, Y, U, and V have component indices of 0, 1, and 2, + * respectively. For RGB video, R, G, and B have component indicies of + * 0, 1, and 2, respectively. Alpha channels, if present, have a component + * index of 3. The @width parameter always represents the width of the + * video, not the component. + * + * Since: 0.10.16 + * + * Returns: row stride of component @component + */ +int +gst_video_format_get_row_stride (GstVideoFormat format, int component, + int width) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (component >= 0 && component <= 3, 0); + g_return_val_if_fail (width > 0, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + if (component == 0) { + return GST_ROUND_UP_4 (width); + } else { + return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); + } + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + return GST_ROUND_UP_4 (width * 2); + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_r210: + return width * 4; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + return GST_ROUND_UP_4 (width * 2); + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + return GST_ROUND_UP_4 (width * 3); + case GST_VIDEO_FORMAT_Y41B: + if (component == 0) { + return GST_ROUND_UP_4 (width); + } else { + return GST_ROUND_UP_16 (width) / 4; + } + case GST_VIDEO_FORMAT_Y42B: + if (component == 0) { + return GST_ROUND_UP_4 (width); + } else { + return GST_ROUND_UP_8 (width) / 2; + } + case GST_VIDEO_FORMAT_Y444: + return GST_ROUND_UP_4 (width); + case GST_VIDEO_FORMAT_v210: + return ((width + 47) / 48) * 128; + case GST_VIDEO_FORMAT_v216: + return GST_ROUND_UP_8 (width * 4); + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + return GST_ROUND_UP_4 (width); + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_Y800: + return GST_ROUND_UP_4 (width); + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y16: + return GST_ROUND_UP_4 (width * 2); + case GST_VIDEO_FORMAT_UYVP: + return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4); + case GST_VIDEO_FORMAT_A420: + if (component == 0 || component == 3) { + return GST_ROUND_UP_4 (width); + } else { + return GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2); + } + case GST_VIDEO_FORMAT_RGB8_PALETTED: + return GST_ROUND_UP_4 (width); + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + if (component == 0) { + return GST_ROUND_UP_4 (width); + } else { + return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4); + } + case GST_VIDEO_FORMAT_IYU1: + return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + + GST_ROUND_UP_4 (width) / 2); + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + return width * 8; + default: + return 0; + } +} + +/** + * gst_video_format_get_pixel_stride: + * @format: a #GstVideoFormat + * @component: the component index + * + * Calculates the pixel stride (number of bytes from one pixel to the + * pixel to its immediate left) for the video component with an index + * of @component. See @gst_video_format_get_row_stride for a description + * of the component index. + * + * Since: 0.10.16 + * + * Returns: pixel stride of component @component + */ +int +gst_video_format_get_pixel_stride (GstVideoFormat format, int component) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (component >= 0 && component <= 3, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_A420: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + return 1; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + if (component == 0) { + return 2; + } else { + return 4; + } + case GST_VIDEO_FORMAT_IYU1: + /* doesn't make much sense for IYU1 because it's 1 or 3 + * for luma depending on position */ + return 0; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_r210: + return 4; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + return 2; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + return 3; + case GST_VIDEO_FORMAT_v210: + /* v210 is packed at the bit level, so pixel stride doesn't make sense */ + return 0; + case GST_VIDEO_FORMAT_v216: + if (component == 0) { + return 4; + } else { + return 8; + } + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + if (component == 0) { + return 1; + } else { + return 2; + } + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_Y800: + return 1; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y16: + return 2; + case GST_VIDEO_FORMAT_UYVP: + /* UYVP is packed at the bit level, so pixel stride doesn't make sense */ + return 0; + case GST_VIDEO_FORMAT_RGB8_PALETTED: + return 1; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + return 8; + default: + return 0; + } +} + +/** + * gst_video_format_get_component_width: + * @format: a #GstVideoFormat + * @component: the component index + * @width: the width of video + * + * Calculates the width of the component. See + * @gst_video_format_get_row_stride for a description + * of the component index. + * + * Since: 0.10.16 + * + * Returns: width of component @component + */ +int +gst_video_format_get_component_width (GstVideoFormat format, + int component, int width) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (component >= 0 && component <= 3, 0); + g_return_val_if_fail (width > 0, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + case GST_VIDEO_FORMAT_UYVP: + if (component == 0) { + return width; + } else { + return GST_ROUND_UP_2 (width) / 2; + } + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + case GST_VIDEO_FORMAT_IYU1: + if (component == 0) { + return width; + } else { + return GST_ROUND_UP_4 (width) / 4; + } + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + case GST_VIDEO_FORMAT_r210: + return width; + case GST_VIDEO_FORMAT_A420: + if (component == 0 || component == 3) { + return width; + } else { + return GST_ROUND_UP_2 (width) / 2; + } + default: + return 0; + } +} + +/** + * gst_video_format_get_component_height: + * @format: a #GstVideoFormat + * @component: the component index + * @height: the height of video + * + * Calculates the height of the component. See + * @gst_video_format_get_row_stride for a description + * of the component index. + * + * Since: 0.10.16 + * + * Returns: height of component @component + */ +int +gst_video_format_get_component_height (GstVideoFormat format, + int component, int height) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (component >= 0 && component <= 3, 0); + g_return_val_if_fail (height > 0, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + if (component == 0) { + return height; + } else { + return GST_ROUND_UP_2 (height) / 2; + } + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_v216: + case GST_VIDEO_FORMAT_v308: + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + case GST_VIDEO_FORMAT_UYVP: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + case GST_VIDEO_FORMAT_IYU1: + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + case GST_VIDEO_FORMAT_r210: + return height; + case GST_VIDEO_FORMAT_A420: + if (component == 0 || component == 3) { + return height; + } else { + return GST_ROUND_UP_2 (height) / 2; + } + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + if (component == 0) { + return height; + } else { + return GST_ROUND_UP_4 (height) / 4; + } + default: + return 0; + } +} + +/** + * gst_video_format_get_component_offset: + * @format: a #GstVideoFormat + * @component: the component index + * @width: the width of video + * @height: the height of video + * + * Calculates the offset (in bytes) of the first pixel of the component + * with index @component. For packed formats, this will typically be a + * small integer (0, 1, 2, 3). For planar formats, this will be a + * (relatively) large offset to the beginning of the second or third + * component planes. See @gst_video_format_get_row_stride for a description + * of the component index. + * + * Since: 0.10.16 + * + * Returns: offset of component @component + */ +int +gst_video_format_get_component_offset (GstVideoFormat format, + int component, int width, int height) +{ + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (component >= 0 && component <= 3, 0); + g_return_val_if_fail ((!gst_video_format_is_yuv (format)) || (width > 0 + && height > 0), 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + if (component == 2) { + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + + GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2); + } + return 0; + case GST_VIDEO_FORMAT_YV12: /* same as I420, but components 1+2 swapped */ + if (component == 0) + return 0; + if (component == 2) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + if (component == 1) { + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + + GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2); + } + return 0; + case GST_VIDEO_FORMAT_YUY2: + if (component == 0) + return 0; + if (component == 1) + return 1; + if (component == 2) + return 3; + return 0; + case GST_VIDEO_FORMAT_YVYU: + if (component == 0) + return 0; + if (component == 1) + return 3; + if (component == 2) + return 1; + return 0; + case GST_VIDEO_FORMAT_UYVY: + if (component == 0) + return 1; + if (component == 1) + return 0; + if (component == 2) + return 2; + return 0; + case GST_VIDEO_FORMAT_AYUV: + if (component == 0) + return 1; + if (component == 1) + return 2; + if (component == 2) + return 3; + if (component == 3) + return 0; + return 0; + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_RGBA: + if (component == 0) + return 0; + if (component == 1) + return 1; + if (component == 2) + return 2; + if (component == 3) + return 3; + return 0; + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_BGRA: + if (component == 0) + return 2; + if (component == 1) + return 1; + if (component == 2) + return 0; + if (component == 3) + return 3; + return 0; + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_ARGB: + if (component == 0) + return 1; + if (component == 1) + return 2; + if (component == 2) + return 3; + if (component == 3) + return 0; + return 0; + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_ABGR: + if (component == 0) + return 3; + if (component == 1) + return 2; + if (component == 2) + return 1; + if (component == 3) + return 0; + return 0; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_v308: + if (component == 0) + return 0; + if (component == 1) + return 1; + if (component == 2) + return 2; + return 0; + case GST_VIDEO_FORMAT_BGR: + if (component == 0) + return 2; + if (component == 1) + return 1; + if (component == 2) + return 0; + return 0; + case GST_VIDEO_FORMAT_Y41B: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * height; + if (component == 2) + return (GST_ROUND_UP_4 (width) + + (GST_ROUND_UP_16 (width) / 4)) * height; + return 0; + case GST_VIDEO_FORMAT_Y42B: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * height; + if (component == 2) + return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_8 (width) / 2)) * height; + return 0; + case GST_VIDEO_FORMAT_Y444: + return GST_ROUND_UP_4 (width) * height * component; + case GST_VIDEO_FORMAT_v210: + case GST_VIDEO_FORMAT_r210: + /* v210 is bit-packed, so this doesn't make sense */ + return 0; + case GST_VIDEO_FORMAT_v216: + if (component == 0) + return 0; + if (component == 1) + return 2; + if (component == 2) + return 6; + return 0; + case GST_VIDEO_FORMAT_NV12: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + if (component == 2) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1; + case GST_VIDEO_FORMAT_NV21: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + 1; + if (component == 2) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_Y16: + return 0; + case GST_VIDEO_FORMAT_UYVP: + /* UYVP is bit-packed, so this doesn't make sense */ + return 0; + case GST_VIDEO_FORMAT_A420: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + if (component == 2) { + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + + GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2); + } + if (component == 3) { + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) + + 2 * GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2); + } + case GST_VIDEO_FORMAT_RGB8_PALETTED: + return 0; + case GST_VIDEO_FORMAT_YUV9: + if (component == 0) + return 0; + if (component == 1) + return GST_ROUND_UP_4 (width) * height; + if (component == 2) { + return GST_ROUND_UP_4 (width) * height + + GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) * + (GST_ROUND_UP_4 (height) / 4); + } + return 0; + case GST_VIDEO_FORMAT_YVU9: + if (component == 0) + return 0; + if (component == 1) { + return GST_ROUND_UP_4 (width) * height + + GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) * + (GST_ROUND_UP_4 (height) / 4); + } + if (component == 2) + return GST_ROUND_UP_4 (width) * height; + return 0; + case GST_VIDEO_FORMAT_IYU1: + if (component == 0) + return 1; + if (component == 1) + return 0; + if (component == 2) + return 4; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + if (component == 0) + return 2; + if (component == 1) + return 4; + if (component == 2) + return 6; + if (component == 3) + return 0; + return 0; + default: + return 0; + } +} + +/** + * gst_video_format_get_size: + * @format: a #GstVideoFormat + * @width: the width of video + * @height: the height of video + * + * Calculates the total number of bytes in the raw video format. This + * number should be used when allocating a buffer for raw video. + * + * Since: 0.10.16 + * + * Returns: size (in bytes) of raw video format + */ +int +gst_video_format_get_size (GstVideoFormat format, int width, int height) +{ + int size; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (width > 0 && height > 0, 0); + + switch (format) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + size = GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2) * 2; + return size; + case GST_VIDEO_FORMAT_IYU1: + return GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + + GST_ROUND_UP_4 (width) / 2) * height; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + return GST_ROUND_UP_4 (width * 2) * height; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_r210: + return width * 4 * height; + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_BGR16: + case GST_VIDEO_FORMAT_RGB15: + case GST_VIDEO_FORMAT_BGR15: + return GST_ROUND_UP_4 (width * 2) * height; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + return GST_ROUND_UP_4 (width * 3) * height; + case GST_VIDEO_FORMAT_Y41B: + /* simplification of ROUNDUP4(w)*h + 2*((ROUNDUP16(w)/4)*h */ + return (GST_ROUND_UP_4 (width) + (GST_ROUND_UP_16 (width) / 2)) * height; + case GST_VIDEO_FORMAT_Y42B: + /* simplification of ROUNDUP4(w)*h + 2*(ROUNDUP8(w)/2)*h */ + return (GST_ROUND_UP_4 (width) + GST_ROUND_UP_8 (width)) * height; + case GST_VIDEO_FORMAT_Y444: + return GST_ROUND_UP_4 (width) * height * 3; + case GST_VIDEO_FORMAT_v210: + return ((width + 47) / 48) * 128 * height; + case GST_VIDEO_FORMAT_v216: + return GST_ROUND_UP_8 (width * 4) * height; + case GST_VIDEO_FORMAT_NV12: + case GST_VIDEO_FORMAT_NV21: + return GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height) * 3 / 2; + case GST_VIDEO_FORMAT_GRAY8: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + return GST_ROUND_UP_4 (width) * height; + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_Y16: + return GST_ROUND_UP_4 (width * 2) * height; + case GST_VIDEO_FORMAT_UYVP: + return GST_ROUND_UP_4 ((width * 2 * 5 + 3) / 4) * height; + case GST_VIDEO_FORMAT_A420: + size = 2 * GST_ROUND_UP_4 (width) * GST_ROUND_UP_2 (height); + size += GST_ROUND_UP_4 (GST_ROUND_UP_2 (width) / 2) * + (GST_ROUND_UP_2 (height) / 2) * 2; + return size; + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + size = GST_ROUND_UP_4 (width) * height; + size += GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) / 4) * + (GST_ROUND_UP_4 (height) / 4) * 2; + return size; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + return width * 8 * height; + default: + return 0; + } +} + +/** + * gst_video_format_convert: + * @format: a #GstVideoFormat + * @width: the width of video + * @height: the height of video + * @fps_n: frame rate numerator + * @fps_d: frame rate denominator + * @src_format: #GstFormat of the @src_value + * @src_value: value to convert + * @dest_format: #GstFormat of the @dest_value + * @dest_value: pointer to destination value + * + * Converts among various #GstFormat types. This function handles + * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For + * raw video, GST_FORMAT_DEFAULT corresponds to video frames. This + * function can be to handle pad queries of the type GST_QUERY_CONVERT. + * + * Since: 0.10.16 + * + * Returns: TRUE if the conversion was successful. + */ +gboolean +gst_video_format_convert (GstVideoFormat format, int width, int height, + int fps_n, int fps_d, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value) +{ + gboolean ret = FALSE; + int size; + + g_return_val_if_fail (format != GST_VIDEO_FORMAT_UNKNOWN, 0); + g_return_val_if_fail (width > 0 && height > 0, 0); + + size = gst_video_format_get_size (format, width, height); + + GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s to %s", + src_value, gst_format_get_name (src_format), + gst_format_get_name (dest_format)); + + if (src_format == dest_format) { + *dest_value = src_value; + ret = TRUE; + goto done; + } + + if (src_value == -1) { + *dest_value = -1; + ret = TRUE; + goto done; + } + + /* bytes to frames */ + if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) { + if (size != 0) { + *dest_value = gst_util_uint64_scale_int (src_value, 1, size); + } else { + GST_ERROR ("blocksize is 0"); + *dest_value = 0; + } + ret = TRUE; + goto done; + } + + /* frames to bytes */ + if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) { + *dest_value = gst_util_uint64_scale_int (src_value, size, 1); + ret = TRUE; + goto done; + } + + /* time to frames */ + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) { + if (fps_d != 0) { + *dest_value = gst_util_uint64_scale (src_value, + fps_n, GST_SECOND * fps_d); + } else { + GST_ERROR ("framerate denominator is 0"); + *dest_value = 0; + } + ret = TRUE; + goto done; + } + + /* frames to time */ + if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) { + if (fps_n != 0) { + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * fps_d, fps_n); + } else { + GST_ERROR ("framerate numerator is 0"); + *dest_value = 0; + } + ret = TRUE; + goto done; + } + + /* time to bytes */ + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { + if (fps_d != 0) { + *dest_value = gst_util_uint64_scale (src_value, + fps_n * size, GST_SECOND * fps_d); + } else { + GST_ERROR ("framerate denominator is 0"); + *dest_value = 0; + } + ret = TRUE; + goto done; + } + + /* bytes to time */ + if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) { + if (fps_n != 0 && size != 0) { + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * fps_d, fps_n * size); + } else { + GST_ERROR ("framerate denominator and/or blocksize is 0"); + *dest_value = 0; + } + ret = TRUE; + } + +done: + + GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value); + + return ret; +} + +#define GST_VIDEO_EVENT_STILL_STATE_NAME "GstEventStillFrame" + +/** + * gst_video_event_new_still_frame: + * @in_still: boolean value for the still-frame state of the event. + * + * Creates a new Still Frame event. If @in_still is %TRUE, then the event + * represents the start of a still frame sequence. If it is %FALSE, then + * the event ends a still frame sequence. + * + * To parse an event created by gst_video_event_new_still_frame() use + * gst_video_event_parse_still_frame(). + * + * Returns: The new GstEvent + * Since: 0.10.26 + */ +GstEvent * +gst_video_event_new_still_frame (gboolean in_still) +{ + GstEvent *still_event; + GstStructure *s; + + s = gst_structure_new (GST_VIDEO_EVENT_STILL_STATE_NAME, + "still-state", G_TYPE_BOOLEAN, in_still, NULL); + still_event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, s); + + return still_event; +} + +/** + * gst_video_event_parse_still_frame: + * @event: A #GstEvent to parse + * @in_still: A boolean to receive the still-frame status from the event, or NULL + * + * Parse a #GstEvent, identify if it is a Still Frame event, and + * return the still-frame state from the event if it is. + * If the event represents the start of a still frame, the in_still + * variable will be set to TRUE, otherwise FALSE. It is OK to pass NULL for the + * in_still variable order to just check whether the event is a valid still-frame + * event. + * + * Create a still frame event using gst_video_event_new_still_frame() + * + * Returns: %TRUE if the event is a valid still-frame event. %FALSE if not + * Since: 0.10.26 + */ +gboolean +gst_video_event_parse_still_frame (GstEvent * event, gboolean * in_still) +{ + const GstStructure *s; + gboolean ev_still_state; + + g_return_val_if_fail (event != NULL, FALSE); + + if (GST_EVENT_TYPE (event) != GST_EVENT_CUSTOM_DOWNSTREAM) + return FALSE; /* Not a still frame event */ + + s = gst_event_get_structure (event); + if (s == NULL + || !gst_structure_has_name (s, GST_VIDEO_EVENT_STILL_STATE_NAME)) + return FALSE; /* Not a still frame event */ + if (!gst_structure_get_boolean (s, "still-state", &ev_still_state)) + return FALSE; /* Not a still frame event */ + if (in_still) + *in_still = ev_still_state; + return TRUE; +} + +/** + * gst_video_parse_caps_palette: + * @caps: #GstCaps to parse + * + * Returns the palette data from the caps as a #GstBuffer. For + * #GST_VIDEO_FORMAT_RGB8_PALETTED this is containing 256 #guint32 + * values, each containing ARGB colors in native endianness. + * + * Returns: a #GstBuffer containing the palette data. Unref after usage. + * Since: 0.10.32 + */ +GstBuffer * +gst_video_parse_caps_palette (GstCaps * caps) +{ + GstStructure *s; + const GValue *p_v; + GstBuffer *p; + + if (!gst_caps_is_fixed (caps)) + return NULL; + + s = gst_caps_get_structure (caps, 0); + + p_v = gst_structure_get_value (s, "palette_data"); + if (!p_v || !GST_VALUE_HOLDS_BUFFER (p_v)) + return NULL; + + p = gst_buffer_ref (gst_value_get_buffer (p_v)); + + return p; +} diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.h b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.h new file mode 100644 index 0000000..fdd6b43 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.h @@ -0,0 +1,501 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2002> Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VIDEO_H__ +#define __GST_VIDEO_H__ + +#include + +G_BEGIN_DECLS + +#include + +/** + * GstVideoFormat: + * @GST_VIDEO_FORMAT_UNKNOWN: Unknown or unset video format id + * @GST_VIDEO_FORMAT_I420: planar 4:2:0 YUV + * @GST_VIDEO_FORMAT_YV12: planar 4:2:0 YVU (like I420 but UV planes swapped) + * @GST_VIDEO_FORMAT_YUY2: packed 4:2:2 YUV (Y0-U0-Y1-V0 Y2-U2-Y3-V2 Y4 ...) + * @GST_VIDEO_FORMAT_UYVY: packed 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) + * @GST_VIDEO_FORMAT_AYUV: packed 4:4:4 YUV with alpha channel (A0-Y0-U0-V0 ...) + * @GST_VIDEO_FORMAT_RGBx: sparse rgb packed into 32 bit, space last + * @GST_VIDEO_FORMAT_BGRx: sparse reverse rgb packed into 32 bit, space last + * @GST_VIDEO_FORMAT_xRGB: sparse rgb packed into 32 bit, space first + * @GST_VIDEO_FORMAT_xBGR: sparse reverse rgb packed into 32 bit, space first + * @GST_VIDEO_FORMAT_RGBA: rgb with alpha channel last + * @GST_VIDEO_FORMAT_BGRA: reverse rgb with alpha channel last + * @GST_VIDEO_FORMAT_ARGB: rgb with alpha channel first + * @GST_VIDEO_FORMAT_ABGR: reverse rgb with alpha channel first + * @GST_VIDEO_FORMAT_RGB: rgb + * @GST_VIDEO_FORMAT_BGR: reverse rgb + * @GST_VIDEO_FORMAT_Y41B: planar 4:1:1 YUV (Since: 0.10.18) + * @GST_VIDEO_FORMAT_Y42B: planar 4:2:2 YUV (Since: 0.10.18) + * @GST_VIDEO_FORMAT_YVYU: packed 4:2:2 YUV (Y0-V0-Y1-U0 Y2-V2-Y3-U2 Y4 ...) (Since: 0.10.23) + * @GST_VIDEO_FORMAT_Y444: planar 4:4:4 YUV (Since: 0.10.24) + * @GST_VIDEO_FORMAT_v210: packed 4:2:2 10-bit YUV, complex format (Since: 0.10.24) + * @GST_VIDEO_FORMAT_v216: packed 4:2:2 16-bit YUV, Y0-U0-Y1-V1 order (Since: 0.10.24) + * @GST_VIDEO_FORMAT_NV12: planar 4:2:0 YUV with interleaved UV plane (Since: 0.10.26) + * @GST_VIDEO_FORMAT_NV21: planar 4:2:0 YUV with interleaved VU plane (Since: 0.10.26) + * @GST_VIDEO_FORMAT_GRAY8: 8-bit grayscale (Since: 0.10.29) + * @GST_VIDEO_FORMAT_GRAY16_BE: 16-bit grayscale, most significant byte first (Since: 0.10.29) + * @GST_VIDEO_FORMAT_GRAY16_LE: 16-bit grayscale, least significant byte first (Since: 0.10.29) + * @GST_VIDEO_FORMAT_v308: packed 4:4:4 YUV (Since: 0.10.29) + * @GST_VIDEO_FORMAT_Y800: same as GST_VIDEO_FORMAT_GRAY8 (Since: 0.10.30) + * @GST_VIDEO_FORMAT_Y16: same as GST_VIDEO_FORMAT_GRAY16_LE (Since: 0.10.30) + * @GST_VIDEO_FORMAT_RGB16: rgb 5-6-5 bits per component (Since: 0.10.30) + * @GST_VIDEO_FORMAT_BGR16: reverse rgb 5-6-5 bits per component (Since: 0.10.30) + * @GST_VIDEO_FORMAT_RGB15: rgb 5-5-5 bits per component (Since: 0.10.30) + * @GST_VIDEO_FORMAT_BGR15: reverse rgb 5-5-5 bits per component (Since: 0.10.30) + * @GST_VIDEO_FORMAT_UYVP: packed 10-bit 4:2:2 YUV (U0-Y0-V0-Y1 U2-Y2-V2-Y3 U4 ...) (Since: 0.10.31) + * @GST_VIDEO_FORMAT_A420: planar 4:4:2:0 AYUV (Since: 0.10.31) + * @GST_VIDEO_FORMAT_RGB8_PALETTED: 8-bit paletted RGB (Since: 0.10.32) + * @GST_VIDEO_FORMAT_YUV9: planar 4:1:0 YUV (Since: 0.10.32) + * @GST_VIDEO_FORMAT_YVU9: planar 4:1:0 YUV (like YUV9 but UV planes swapped) (Since: 0.10.32) + * @GST_VIDEO_FORMAT_IYU1: packed 4:1:1 YUV (Cb-Y0-Y1-Cr-Y2-Y3 ...) (Since: 0.10.32) + * @GST_VIDEO_FORMAT_ARGB64: rgb with alpha channel first, 16 bits per channel (Since: 0.10.33) + * @GST_VIDEO_FORMAT_AYUV64: packed 4:4:4 YUV with alpha channel, 16 bits per channel (A0-Y0-U0-V0 ...) (Since: 0.10.33) + * @GST_VIDEO_FORMAT_r210: packed 4:4:4 RGB, 10 bits per channel (Since: 0.10.33) + * + * Enum value describing the most common video formats. + */ +typedef enum { + GST_VIDEO_FORMAT_UNKNOWN, + GST_VIDEO_FORMAT_I420, + GST_VIDEO_FORMAT_YV12, + GST_VIDEO_FORMAT_YUY2, + GST_VIDEO_FORMAT_UYVY, + GST_VIDEO_FORMAT_AYUV, + GST_VIDEO_FORMAT_RGBx, + GST_VIDEO_FORMAT_BGRx, + GST_VIDEO_FORMAT_xRGB, + GST_VIDEO_FORMAT_xBGR, + GST_VIDEO_FORMAT_RGBA, + GST_VIDEO_FORMAT_BGRA, + GST_VIDEO_FORMAT_ARGB, + GST_VIDEO_FORMAT_ABGR, + GST_VIDEO_FORMAT_RGB, + GST_VIDEO_FORMAT_BGR, + GST_VIDEO_FORMAT_Y41B, + GST_VIDEO_FORMAT_Y42B, + GST_VIDEO_FORMAT_YVYU, + GST_VIDEO_FORMAT_Y444, + GST_VIDEO_FORMAT_v210, + GST_VIDEO_FORMAT_v216, + GST_VIDEO_FORMAT_NV12, + GST_VIDEO_FORMAT_NV21, + GST_VIDEO_FORMAT_GRAY8, + GST_VIDEO_FORMAT_GRAY16_BE, + GST_VIDEO_FORMAT_GRAY16_LE, + GST_VIDEO_FORMAT_v308, + GST_VIDEO_FORMAT_Y800, + GST_VIDEO_FORMAT_Y16, + GST_VIDEO_FORMAT_RGB16, + GST_VIDEO_FORMAT_BGR16, + GST_VIDEO_FORMAT_RGB15, + GST_VIDEO_FORMAT_BGR15, + GST_VIDEO_FORMAT_UYVP, + GST_VIDEO_FORMAT_A420, + GST_VIDEO_FORMAT_RGB8_PALETTED, + GST_VIDEO_FORMAT_YUV9, + GST_VIDEO_FORMAT_YVU9, + GST_VIDEO_FORMAT_IYU1, + GST_VIDEO_FORMAT_ARGB64, + GST_VIDEO_FORMAT_AYUV64, + GST_VIDEO_FORMAT_r210 +} GstVideoFormat; + +#define GST_VIDEO_BYTE1_MASK_32 "0xFF000000" +#define GST_VIDEO_BYTE2_MASK_32 "0x00FF0000" +#define GST_VIDEO_BYTE3_MASK_32 "0x0000FF00" +#define GST_VIDEO_BYTE4_MASK_32 "0x000000FF" + +#define GST_VIDEO_BYTE1_MASK_24 "0x00FF0000" +#define GST_VIDEO_BYTE2_MASK_24 "0x0000FF00" +#define GST_VIDEO_BYTE3_MASK_24 "0x000000FF" + +#define GST_VIDEO_BYTE1_MASK_32_INT 0xFF000000 +#define GST_VIDEO_BYTE2_MASK_32_INT 0x00FF0000 +#define GST_VIDEO_BYTE3_MASK_32_INT 0x0000FF00 +#define GST_VIDEO_BYTE4_MASK_32_INT 0x000000FF + +#define GST_VIDEO_BYTE1_MASK_24_INT 0x00FF0000 +#define GST_VIDEO_BYTE2_MASK_24_INT 0x0000FF00 +#define GST_VIDEO_BYTE3_MASK_24_INT 0x000000FF + +#define GST_VIDEO_COMP1_MASK_16 "0xf800" +#define GST_VIDEO_COMP2_MASK_16 "0x07e0" +#define GST_VIDEO_COMP3_MASK_16 "0x001f" + +#define GST_VIDEO_COMP1_MASK_15 "0x7c00" +#define GST_VIDEO_COMP2_MASK_15 "0x03e0" +#define GST_VIDEO_COMP3_MASK_15 "0x001f" + +#define GST_VIDEO_COMP1_MASK_16_INT 0xf800 +#define GST_VIDEO_COMP2_MASK_16_INT 0x07e0 +#define GST_VIDEO_COMP3_MASK_16_INT 0x001f + +#define GST_VIDEO_COMP1_MASK_15_INT 0x7c00 +#define GST_VIDEO_COMP2_MASK_15_INT 0x03e0 +#define GST_VIDEO_COMP3_MASK_15_INT 0x001f + +#ifndef GST_DISABLE_DEPRECATED +#define GST_VIDEO_RED_MASK_16 GST_VIDEO_COMP1_MASK_16 +#define GST_VIDEO_GREEN_MASK_16 GST_VIDEO_COMP2_MASK_16 +#define GST_VIDEO_BLUE_MASK_16 GST_VIDEO_COMP3_MASK_16 + +#define GST_VIDEO_RED_MASK_15 GST_VIDEO_COMP1_MASK_15 +#define GST_VIDEO_GREEN_MASK_15 GST_VIDEO_COMP2_MASK_15 +#define GST_VIDEO_BLUE_MASK_15 GST_VIDEO_COMP3_MASK_15 + +#define GST_VIDEO_RED_MASK_16_INT GST_VIDEO_COMP1_MASK_16_INT +#define GST_VIDEO_GREEN_MASK_16_INT GST_VIDEO_COMP2_MASK_16_INT +#define GST_VIDEO_BLUE_MASK_16_INT GST_VIDEO_COMP3_MASK_16_INT + +#define GST_VIDEO_RED_MASK_15_INT GST_VIDEO_COMP1_MASK_15_INT +#define GST_VIDEO_GREEN_MASK_15_INT GST_VIDEO_COMP2_MASK_15_INT +#define GST_VIDEO_BLUE_MASK_15_INT GST_VIDEO_COMP3_MASK_15_INT +#endif + +#define GST_VIDEO_SIZE_RANGE "(int) [ 1, max ]" +#define GST_VIDEO_FPS_RANGE "(fraction) [ 0, max ]" + +/* consider the next 2 protected */ +#define __GST_VIDEO_CAPS_MAKE_32A(R, G, B, A) \ + "video/x-raw-rgb, " \ + "bpp = (int) 32, " \ + "depth = (int) 32, " \ + "endianness = (int) BIG_ENDIAN, " \ + "red_mask = (int) " GST_VIDEO_BYTE ## R ## _MASK_32 ", " \ + "green_mask = (int) " GST_VIDEO_BYTE ## G ## _MASK_32 ", " \ + "blue_mask = (int) " GST_VIDEO_BYTE ## B ## _MASK_32 ", " \ + "alpha_mask = (int) " GST_VIDEO_BYTE ## A ## _MASK_32 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +#define __GST_VIDEO_CAPS_MAKE_32(R, G, B) \ + "video/x-raw-rgb, " \ + "bpp = (int) 32, " \ + "depth = (int) 24, " \ + "endianness = (int) BIG_ENDIAN, " \ + "red_mask = (int) " GST_VIDEO_BYTE ## R ## _MASK_32 ", " \ + "green_mask = (int) " GST_VIDEO_BYTE ## G ## _MASK_32 ", " \ + "blue_mask = (int) " GST_VIDEO_BYTE ## B ## _MASK_32 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +#define __GST_VIDEO_CAPS_MAKE_24(R, G, B) \ + "video/x-raw-rgb, " \ + "bpp = (int) 24, " \ + "depth = (int) 24, " \ + "endianness = (int) BIG_ENDIAN, " \ + "red_mask = (int) " GST_VIDEO_BYTE ## R ## _MASK_24 ", " \ + "green_mask = (int) " GST_VIDEO_BYTE ## G ## _MASK_24 ", " \ + "blue_mask = (int) " GST_VIDEO_BYTE ## B ## _MASK_24 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +#define __GST_VIDEO_CAPS_MAKE_16(R, G, B) \ + "video/x-raw-rgb, " \ + "bpp = (int) 16, " \ + "depth = (int) 16, " \ + "endianness = (int) BYTE_ORDER, " \ + "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_16 ", " \ + "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_16 ", " \ + "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_16 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +#define __GST_VIDEO_CAPS_MAKE_15(R, G, B) \ + "video/x-raw-rgb, " \ + "bpp = (int) 16, " \ + "depth = (int) 15, " \ + "endianness = (int) BYTE_ORDER, " \ + "red_mask = (int) " GST_VIDEO_COMP ## R ## _MASK_15 ", " \ + "green_mask = (int) " GST_VIDEO_COMP ## G ## _MASK_15 ", " \ + "blue_mask = (int) " GST_VIDEO_COMP ## B ## _MASK_15 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +#define __GST_VIDEO_CAPS_MAKE_64A(R, G, B, A) \ + "video/x-raw-rgb, " \ + "bpp = (int) 64, " \ + "depth = (int) 64, " \ + "endianness = (int) BIG_ENDIAN, " \ + "red_mask = (int) " GST_VIDEO_BYTE ## R ## _MASK_32 ", " \ + "green_mask = (int) " GST_VIDEO_BYTE ## G ## _MASK_32 ", " \ + "blue_mask = (int) " GST_VIDEO_BYTE ## B ## _MASK_32 ", " \ + "alpha_mask = (int) " GST_VIDEO_BYTE ## A ## _MASK_32 ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + + +/* 24 bit */ + +#define GST_VIDEO_CAPS_RGB \ + __GST_VIDEO_CAPS_MAKE_24 (1, 2, 3) + +#define GST_VIDEO_CAPS_BGR \ + __GST_VIDEO_CAPS_MAKE_24 (3, 2, 1) + +/* 32 bit */ + +#define GST_VIDEO_CAPS_RGBx \ + __GST_VIDEO_CAPS_MAKE_32 (1, 2, 3) + +#define GST_VIDEO_CAPS_xRGB \ + __GST_VIDEO_CAPS_MAKE_32 (2, 3, 4) + +#define GST_VIDEO_CAPS_BGRx \ + __GST_VIDEO_CAPS_MAKE_32 (3, 2, 1) + +#define GST_VIDEO_CAPS_xBGR \ + __GST_VIDEO_CAPS_MAKE_32 (4, 3, 2) + +/* 32 bit alpha */ + +#define GST_VIDEO_CAPS_RGBA \ + __GST_VIDEO_CAPS_MAKE_32A (1, 2, 3, 4) + +#define GST_VIDEO_CAPS_ARGB \ + __GST_VIDEO_CAPS_MAKE_32A (2, 3, 4, 1) + +#define GST_VIDEO_CAPS_BGRA \ + __GST_VIDEO_CAPS_MAKE_32A (3, 2, 1, 4) + +#define GST_VIDEO_CAPS_ABGR \ + __GST_VIDEO_CAPS_MAKE_32A (4, 3, 2, 1) + +/* note: the macro name uses the order on BE systems */ +#if G_BYTE_ORDER == G_BIG_ENDIAN + #define GST_VIDEO_CAPS_xRGB_HOST_ENDIAN \ + GST_VIDEO_CAPS_xRGB + #define GST_VIDEO_CAPS_BGRx_HOST_ENDIAN \ + GST_VIDEO_CAPS_BGRx +#else + #define GST_VIDEO_CAPS_xRGB_HOST_ENDIAN \ + GST_VIDEO_CAPS_BGRx + #define GST_VIDEO_CAPS_BGRx_HOST_ENDIAN \ + GST_VIDEO_CAPS_xRGB +#endif + +/* 15/16 bit */ + +#define GST_VIDEO_CAPS_RGB_16 \ + __GST_VIDEO_CAPS_MAKE_16 (1, 2, 3) + +#define GST_VIDEO_CAPS_BGR_16 \ + __GST_VIDEO_CAPS_MAKE_16 (3, 2, 1) + +#define GST_VIDEO_CAPS_RGB_15 \ + __GST_VIDEO_CAPS_MAKE_15 (1, 2, 3) + +#define GST_VIDEO_CAPS_BGR_15 \ + __GST_VIDEO_CAPS_MAKE_15 (3, 2, 1) + +/* 30 bit */ +#define GST_VIDEO_CAPS_r210 \ + "video/x-raw-rgb, " \ + "bpp = (int) 32, " \ + "depth = (int) 30, " \ + "endianness = (int) BIG_ENDIAN, " \ + "red_mask = (int) 0x3ff00000, " \ + "green_mask = (int) 0x000ffc00, " \ + "blue_mask = (int) 0x000003ff, " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +/* 64 bit alpha */ + +#define GST_VIDEO_CAPS_ARGB_64 \ + __GST_VIDEO_CAPS_MAKE_64A (2, 3, 4, 1) + +/** + * GST_VIDEO_CAPS_RGB8_PALETTED: + * + * Generic caps string for 8-bit paletted RGB video, for use in pad templates. + * + * Since: 0.10.32 + */ +#define GST_VIDEO_CAPS_RGB8_PALETTED \ + "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \ + "width = "GST_VIDEO_SIZE_RANGE" , " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = "GST_VIDEO_FPS_RANGE + +/** + * GST_VIDEO_CAPS_YUV: + * @fourcc: YUV fourcc format that describes the pixel layout, as string + * (e.g. "I420", "YV12", "YUY2", "AYUV", etc.) + * + * Generic caps string for YUV video, for use in pad templates. + */ +#define GST_VIDEO_CAPS_YUV(fourcc) \ + "video/x-raw-yuv, " \ + "format = (fourcc) " fourcc ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +/** + * GST_VIDEO_CAPS_GRAY8: + * + * Generic caps string for 8-bit grayscale video, for use in pad templates. + * + * Since: 0.10.29 + */ +#define GST_VIDEO_CAPS_GRAY8 \ + "video/x-raw-gray, " \ + "bpp = (int) 8, " \ + "depth = (int) 8, " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +/** + * GST_VIDEO_CAPS_GRAY16: + * @endianness: endianness as string, ie. either "1234", "4321", "BIG_ENDIAN" + * or "LITTLE_ENDIAN" + * + * Generic caps string for 16-bit grayscale video, for use in pad templates. + * + * Since: 0.10.29 + */ +#define GST_VIDEO_CAPS_GRAY16(endianness) \ + "video/x-raw-gray, " \ + "bpp = (int) 16, " \ + "depth = (int) 16, " \ + "endianness = (int) " endianness ", " \ + "width = " GST_VIDEO_SIZE_RANGE ", " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = " GST_VIDEO_FPS_RANGE + +/* buffer flags */ + +/** + * GST_VIDEO_BUFFER_TFF: + * + * If the #GstBuffer is interlaced, then the first field in the video frame is + * the top field. If unset, the bottom field is first. + * + * Since: 0.10.23 + */ +#define GST_VIDEO_BUFFER_TFF GST_BUFFER_FLAG_MEDIA1 + +/** + * GST_VIDEO_BUFFER_RFF: + * + * If the #GstBuffer is interlaced, then the first field (as defined by the + * %GST_VIDEO_BUFFER_TFF flag setting) is repeated. + * + * Since: 0.10.23 + */ +#define GST_VIDEO_BUFFER_RFF GST_BUFFER_FLAG_MEDIA2 + +/** + * GST_VIDEO_BUFFER_ONEFIELD: + * + * If the #GstBuffer is interlaced, then only the first field (as defined by the + * %GST_VIDEO_BUFFER_TFF flag setting) is to be displayed. + * + * Since: 0.10.23 + */ +#define GST_VIDEO_BUFFER_ONEFIELD GST_BUFFER_FLAG_MEDIA3 + +/** + * GST_VIDEO_BUFFER_PROGRESSIVE: + * + * If the #GstBuffer is telecined, then the buffer is progressive if the + * %GST_VIDEO_BUFFER_PROGRESSIVE flag is set, else it is telecine mixed. + * + * Since: 0.10.33 + */ +#define GST_VIDEO_BUFFER_PROGRESSIVE GST_BUFFER_FLAG_MEDIA4 + +/* functions */ +const GValue *gst_video_frame_rate (GstPad *pad); +gboolean gst_video_get_size (GstPad *pad, + gint *width, + gint *height); + +gboolean gst_video_calculate_display_ratio (guint *dar_n, guint *dar_d, + guint video_width, guint video_height, + guint video_par_n, guint video_par_d, + guint display_par_n, guint display_par_d); + +gboolean gst_video_format_parse_caps (GstCaps *caps, GstVideoFormat *format, + int *width, int *height); +gboolean gst_video_format_parse_caps_interlaced (GstCaps *caps, gboolean *interlaced); +gboolean gst_video_parse_caps_framerate (GstCaps *caps, + int *fps_n, int *fps_d); +gboolean gst_video_parse_caps_pixel_aspect_ratio (GstCaps *caps, + int *par_n, int *par_d); +const char *gst_video_parse_caps_color_matrix (GstCaps * caps); +const char *gst_video_parse_caps_chroma_site (GstCaps * caps); +GstBuffer *gst_video_parse_caps_palette (GstCaps * caps); +GstCaps * gst_video_format_new_caps (GstVideoFormat format, + int width, int height, int framerate_n, int framerate_d, + int par_n, int par_d); +GstCaps * gst_video_format_new_caps_interlaced (GstVideoFormat format, + int width, int height, int framerate_n, int framerate_d, + int par_n, int par_d, gboolean interlaced); +GstCaps * gst_video_format_new_template_caps (GstVideoFormat format); +GstVideoFormat gst_video_format_from_fourcc (guint32 fourcc); +guint32 gst_video_format_to_fourcc (GstVideoFormat format); +gboolean gst_video_format_is_rgb (GstVideoFormat format); +gboolean gst_video_format_is_yuv (GstVideoFormat format); +gboolean gst_video_format_is_gray (GstVideoFormat format); +gboolean gst_video_format_has_alpha (GstVideoFormat format); +int gst_video_format_get_component_depth (GstVideoFormat format, int component); +int gst_video_format_get_row_stride (GstVideoFormat format, int component, + int width); +int gst_video_format_get_pixel_stride (GstVideoFormat format, int component); +int gst_video_format_get_component_width (GstVideoFormat format, int component, + int width); +int gst_video_format_get_component_height (GstVideoFormat format, int component, + int height); +int gst_video_format_get_component_offset (GstVideoFormat format, int component, + int width, int height); +int gst_video_format_get_size (GstVideoFormat format, int width, int height); +gboolean gst_video_format_convert (GstVideoFormat format, int width, int height, + int fps_n, int fps_d, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value); + +GstEvent *gst_video_event_new_still_frame (gboolean in_still); +gboolean gst_video_event_parse_still_frame (GstEvent *event, gboolean *in_still); + +GstBuffer *gst_video_convert_frame(GstBuffer *buf, const GstCaps *to_caps, + GstClockTime timeout, GError **error); + +typedef void (*GstVideoConvertFrameCallback) (GstBuffer *buf, GError *error, gpointer user_data); +void gst_video_convert_frame_async(GstBuffer *buf, const GstCaps *to_caps, + GstClockTime timeout, GstVideoConvertFrameCallback callback, + gpointer user_data, GDestroyNotify destroy_notify); + +G_END_DECLS + +#endif /* __GST_VIDEO_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.vcproj b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.vcproj new file mode 100644 index 0000000..2440294 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-libs/gst/video/video.vcproj @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst-plugins-base.doap b/gst-plugins-base-subtitles0.10/gst-plugins-base.doap new file mode 100644 index 0000000..9441222 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-plugins-base.doap @@ -0,0 +1,417 @@ + + + GStreamer Base Plug-ins + gst-plugins-base + + 2005-06-17 + +a basic collection of elements + + +GStreamer Base Plug-ins is a well-groomed and well-maintained collection of +GStreamer plug-ins and elements, spanning the range of possible types of +elements one would want to write for GStreamer. It also contains helper +libraries and base classes useful for writing elements. +A wide range of video and audio decoders, encoders, and filters are included. + + + + + + C + + + + + + + + + + + + + 0.10.34 + 0.10 + Lemmings + 2011-05-13 + + + + + + + + 0.10.33 + 0.10 + Relaxing Distractions + 2011-05-10 + + + + + + + + 0.10.32 + 0.10 + Your Life You Like It Well + 2011-01-21 + + + + + + + + 0.10.31 + 0.10 + Dance Like It's 1982 + 2010-11-30 + + + + + + + + 0.10.30 + 0.10 + Difficult Birth + 2010-07-15 + + + + + + + + 0.10.29 + 0.10 + Freaks + 2010-04-27 + + + + + + + + 0.10.28 + 0.10 + Those Norwegians + 2010-03-08 + + + + + + + + 0.10.27 + 0.10 + No Mistakes Allowed + 2010-03-05 + + + + + + + + 0.10.26 + 0.10 + You will know when you get there + 2010-02-10 + + + + + + + + 0.10.25 + 0.10 + Standard disclaimers apply + 2009-10-05 + + + + + + + + 0.10.24 + 0.10 + Counting the days + 2009-08-04 + + + + + + + + 0.10.23 + 0.10 + Emergency de-stress call + 2009-05-10 + + + + + + + + 0.10.22 + 0.10 + Hidey Hidey Hidey Ho + 2009-01-19 + + + + + + + + 0.10.21 + 0.10 + We Could Be Wrong + 2008-10-02 + + + + + + + + 0.10.20 + 0.10 + Here I Go Again + 2008-06-18 + + + + + + + + 0.10.19 + 0.10 + Good Times + 2008-04-04 + + + + + + + + 0.10.18 + 0.10 + I will follow + 2008-03-21 + + + + + + + + 0.10.17 + 0.10 + Peanut Butter and Jelly + 2008-01-30 + + + + + + + + 0.10.16 + 0.10 + Scheduled Interruption + 2008-01-28 + + + + + + + + 0.10.15 + 0.10 + No need to argue + 2007-11-15 + + + + + + + + 0.10.14 + 0.10 + Light Years Ahead + 2007-08-03 + + + + + + + + 0.10.13 + 0.10 + What's going on? + 2007-06-05 + + + + + + + + 0.10.12 + 0.10 + Zombie Horde + 2007-03-07 + + + + + + + + 0.10.11 + 0.10 + Dumb things + 2006-12-06 + + + + + + + + 0.10.10 + 0.10 + Chorizo + 2006-09-14 + + + + + + + + 0.10.9 + 0.10 + I walk the line + 2006-07-14 + + + + + + + + 0.10.8 + 0.10 + Moar gij zie mij nie + 2006-06-10 + + + + + + + + 0.10.7 + 0.10 + Leave the gun + 2006-05-14 + + + + + + + + 0.10.6 + 0.10 + Chao + 2006-04-28 + + + + + + + + 0.10.5 + 0.10 + Net + 2006-03-13 + + + + + + 0.10.4 + 0.10 + Power + 2006-03-10 + + + + + + 0.10.3 + 0.10 + Under Pressure + 2006-02-09 + + + + + + 0.10.2 + 0.10 + Then the devil is six + 2006-01-16 + + + + + + 0.10.1 + 0.10 + Dobro Dedek + 2005-12-23 + + + + + + 0.10.0 + 0.10 + Mont-d'or + 2005-12-05 + + + + + + Wim Taymans + 0d93fde052812d51a05fd86de9bdbf674423daa2 + + + + diff --git a/gst-plugins-base-subtitles0.10/gst-plugins-base.spec.in b/gst-plugins-base-subtitles0.10/gst-plugins-base.spec.in new file mode 100644 index 0000000..7017af8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst-plugins-base.spec.in @@ -0,0 +1,275 @@ +%define majorminor @GST_MAJORMINOR@ +%define gstreamer gstreamer + +%define gst_minver 0.10.0 + +Name: %{gstreamer}-plugins-base +Version: @VERSION@ +Release: @PACKAGE_VERSION_RELEASE@.gst +Summary: GStreamer streaming media framework plug-ins + +Group: Applications/Multimedia +License: LGPL +URL: http://gstreamer.freedesktop.org/ +Vendor: GStreamer Backpackers Team +Source: http://gstreamer.freedesktop.org/src/gst-plugins-base/gst-plugins-base-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +Requires: %{gstreamer} >= %{gst_minver} +BuildRequires: %{gstreamer}-devel >= %{gst_minver} + +BuildRequires: gcc-c++ +BuildRequires: gtk-doc >= 1.3 +BuildRequires: orc-devel +Requires: orc + +@USE_GNOME_VFS_TRUE@Requires: gnome-vfs2 > 1.9.4.00 +@USE_GNOME_VFS_TRUE@BuildRequires: gnome-vfs2-devel > 1.9.4.00 +@USE_VORBIS_TRUE@Requires: libogg >= 1.0 +@USE_VORBIS_TRUE@Requires: libvorbis >= 1.0 +@USE_VORBIS_TRUE@BuildRequires: libogg-devel >= 1.0 +@USE_VORBIS_TRUE@BuildRequires: libvorbis-devel >= 1.0 +@USE_XVIDEO_TRUE@BuildRequires: libXv-devel +@USE_XVIDEO_TRUE@Requires: libXv-devel +@USE_ALSA_TRUE@BuildRequires: alsa-lib-devel +@USE_ALSA_TRUE@Requires: alsa-lib +@USE_CDPARANOIA_TRUE@BuildRequires: cdparanoia-devel +@USE_CDPARANOIA_TRUE@Requires: cdparanoia +@USE_LIBVISUAL_TRUE@BuildRequires: libvisual-devel +@USE_LIBVISUAL_TRUE@Requires: libvisual +@USE_PANGO_TRUE@BuildRequires: pango-devel +@USE_PANGO_TRUE@Requires: pango +@USE_THEORA_TRUE@BuildRequires: libtheora-devel >= 1.0 +@USE_THEORA_TRUE@Requires: libtheora >= 1.0 + +%description +GStreamer is a streaming media framework, based on graphs of filters which +operate on media data. Applications using this library can do anything +from real-time sound processing to playing videos, and just about anything +else media-related. Its plugin-based architecture means that new data +types or processing capabilities can be added simply by installing new +plug-ins. + +%prep +%setup -q -n gst-plugins-base-%{version} +export DOCS_ARE_INCOMPLETE_PLEASE_FIXME=0 +%build +%configure \ + --enable-gtk-doc --enable-introspection=no + +make %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT + +%makeinstall + +# Clean out files that should not be part of the rpm. +rm -f $RPM_BUILD_ROOT%{_libdir}/gstreamer-%{majorminor}/*.la +rm -f $RPM_BUILD_ROOT%{_libdir}/gstreamer-%{majorminor}/*.a +rm -f $RPM_BUILD_ROOT%{_libdir}/*.a +rm -f $RPM_BUILD_ROOT%{_libdir}/*.la + +%find_lang gst-plugins-base-%{majorminor} + +%clean +rm -rf $RPM_BUILD_ROOT + +%files -f gst-plugins-base-%{majorminor}.lang +%defattr(-, root, root) +%doc AUTHORS COPYING README REQUIREMENTS gst-plugins-base.doap + +# helper programs +%{_bindir}/gst-visualise-%{majorminor} +%{_bindir}/gst-discoverer-%{majorminor} +%{_mandir}/man1/gst-visualise-%{majorminor}* + +# libraries +%{_libdir}/libgstaudio-%{majorminor}.so.* +%{_libdir}/libgstcdda-%{majorminor}.so* +%{_libdir}/libgstinterfaces-%{majorminor}.so.* +%{_libdir}/libgstnetbuffer-%{majorminor}.so* +%{_libdir}/libgstpbutils-%{majorminor}.so* +%{_libdir}/libgstriff-%{majorminor}.so.* +%{_libdir}/libgstrtp-%{majorminor}.so* +%{_libdir}/libgsttag-%{majorminor}.so.* +%{_libdir}/libgstvideo-%{majorminor}.so.* +%{_libdir}/libgstfft-%{majorminor}.so.* +%{_libdir}/libgstrtsp-%{majorminor}.so.* +%{_libdir}/libgstsdp-%{majorminor}.so.* +%{_libdir}/libgstapp-%{majorminor}.so.* + +# base plugins without external dependencies +%{_libdir}/gstreamer-%{majorminor}/libgstadder.so +%{_libdir}/gstreamer-%{majorminor}/libgstaudioconvert.so +%{_libdir}/gstreamer-%{majorminor}/libgstffmpegcolorspace.so +%{_libdir}/gstreamer-%{majorminor}/libgstdecodebin.so +%{_libdir}/gstreamer-%{majorminor}/libgstdecodebin2.so +%{_libdir}/gstreamer-%{majorminor}/libgstplaybin.so +%{_libdir}/gstreamer-%{majorminor}/libgsttypefindfunctions.so +%{_libdir}/gstreamer-%{majorminor}/libgstvideotestsrc.so +%{_libdir}/gstreamer-%{majorminor}/libgstaudiorate.so +%{_libdir}/gstreamer-%{majorminor}/libgstsubparse.so +%{_libdir}/gstreamer-%{majorminor}/libgstvolume.so +%{_libdir}/gstreamer-%{majorminor}/libgstvideorate.so +%{_libdir}/gstreamer-%{majorminor}/libgstvideoscale.so +%{_libdir}/gstreamer-%{majorminor}/libgsttcp.so +%{_libdir}/gstreamer-%{majorminor}/libgstvideo4linux.so +%{_libdir}/gstreamer-%{majorminor}/libgstaudioresample.so +%{_libdir}/gstreamer-%{majorminor}/libgstaudiotestsrc.so +%{_libdir}/gstreamer-%{majorminor}/libgstgdp.so +%{_libdir}/gstreamer-%{majorminor}/libgstapp.so +%{_libdir}/gstreamer-%{majorminor}/libgstencodebin.so + +# Here are packages not in the base plugins package but not dependant +# on an external lib + +# @USE_GST_V4L2_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstvideo4linux2.so + +# base plugins with dependencies +@USE_ALSA_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstalsa.so +@USE_THEORA_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgsttheora.so +@USE_GNOME_VFS_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstgnomevfs.so +@USE_VORBIS_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstvorbis.so +@USE_VORBIS_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstogg.so +@USE_XVIDEO_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstximage*.so +@USE_XVIDEO_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstxvimagesink.so +@USE_LIBVISUAL_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstlibvisual.so +@USE_PANGO_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstpango.so +@USE_CDPARANOIA_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstcdparanoia.so +@USE_GIO_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstgio.so +# @USE_SCHRO_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstschro.so +%package devel +Summary: GStreamer Plugin Library Headers +Group: Development/Libraries +Requires: %{gstreamer}-plugins-base = %{version} + +%description devel +GStreamer Plugins Base library development and header files. + +%files devel +%defattr(-, root, root) +# plugin helper library headers +%{_includedir}/gstreamer-%{majorminor}/gst/audio/audio.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstaudiofilter.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/multichannel.h +%{_includedir}/gstreamer-%{majorminor}/gst/floatcast/floatcast.h +%{_includedir}/gstreamer-%{majorminor}/gst/riff/riff-ids.h +%{_includedir}/gstreamer-%{majorminor}/gst/riff/riff-media.h +%{_includedir}/gstreamer-%{majorminor}/gst/riff/riff-read.h +%{_includedir}/gstreamer-%{majorminor}/gst/video/video.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/colorbalance.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/colorbalancechannel.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/interfaces-enumtypes.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/mixer.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/mixeroptions.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/mixertrack.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/navigation.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/propertyprobe.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/tuner.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/tunerchannel.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/tunernorm.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/xoverlay.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstaudiosrc.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstbaseaudiosrc.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstbasertpaudiopayload.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstbasertpdepayload.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstrtpbuffer.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstaudioclock.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstaudiosink.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstbaseaudiosink.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/gstringbuffer.h +%{_includedir}/gstreamer-%{majorminor}/gst/tag/tag.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstbasertppayload.h +%{_includedir}/gstreamer-%{majorminor}/gst/video/gstvideofilter.h +%{_includedir}/gstreamer-%{majorminor}/gst/video/gstvideosink.h +%{_includedir}/gstreamer-%{majorminor}/gst/netbuffer/gstnetbuffer.h +%{_includedir}/gstreamer-%{majorminor}/gst/cdda/gstcddabasesrc.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/mixerutils.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/videoorientation.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/descriptions.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/install-plugins.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/missing-plugins.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/pbutils.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstrtcpbuffer.h +%{_includedir}/gstreamer-%{majorminor}/gst/fft/gstfft.h +%{_includedir}/gstreamer-%{majorminor}/gst/fft/gstfftf32.h +%{_includedir}/gstreamer-%{majorminor}/gst/fft/gstfftf64.h +%{_includedir}/gstreamer-%{majorminor}/gst/fft/gstffts16.h +%{_includedir}/gstreamer-%{majorminor}/gst/fft/gstffts32.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtsp-enumtypes.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspbase64.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspconnection.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspdefs.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspextension.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspmessage.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtsprange.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtsptransport.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtsp/gstrtspurl.h +%{_includedir}/gstreamer-%{majorminor}/gst/sdp/gstsdp.h +%{_includedir}/gstreamer-%{majorminor}/gst/sdp/gstsdpmessage.h +%{_includedir}/gstreamer-%{majorminor}/gst/rtp/gstrtppayloads.h +%{_includedir}/gstreamer-%{majorminor}/gst/tag/gsttagdemux.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/pbutils-enumtypes.h +%{_includedir}/gstreamer-%{majorminor}/gst/app/gstappbuffer.h +%{_includedir}/gstreamer-%{majorminor}/gst/app/gstappsink.h +%{_includedir}/gstreamer-%{majorminor}/gst/app/gstappsrc.h +%{_includedir}/gstreamer-%{majorminor}/gst/audio/audio-enumtypes.h +%{_includedir}/gstreamer-%{majorminor}/gst/video/video-enumtypes.h +%{_includedir}/gstreamer-%{majorminor}/gst/interfaces/streamvolume.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/codec-utils.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/encoding-profile.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/encoding-target.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/gstdiscoverer.h +%{_includedir}/gstreamer-%{majorminor}/gst/pbutils/gstpluginsbaseversion.h +%{_includedir}/gstreamer-%{majorminor}/gst/tag/xmpwriter.h + + +%{_libdir}/libgstfft-%{majorminor}.so +%{_libdir}/libgstrtsp-%{majorminor}.so +%{_libdir}/libgstsdp-%{majorminor}.so +%{_libdir}/libgstaudio-%{majorminor}.so +%{_libdir}/libgstriff-%{majorminor}.so +%{_libdir}/libgsttag-%{majorminor}.so +%{_libdir}/libgstvideo-%{majorminor}.so +%{_libdir}/libgstrtp-%{majorminor}.so +%{_libdir}/libgstinterfaces-%{majorminor}.so +%{_libdir}/libgstnetbuffer-%{majorminor}.so +%{_libdir}/libgstpbutils-%{majorminor}.so +%{_libdir}/libgstcdda-%{majorminor}.so +%{_libdir}/libgstapp-%{majorminor}.so + +# pkg-config files +%{_libdir}/pkgconfig/gstreamer-plugins-base-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-audio-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-cdda-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-fft-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-floatcast-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-interfaces-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-netbuffer-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-pbutils-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-riff-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-rtp-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-rtsp-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-sdp-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-tag-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-video-%{majorminor}.pc +%{_libdir}/pkgconfig/gstreamer-app-%{majorminor}.pc + +# gtk-doc documentation +%doc %{_datadir}/gtk-doc/html/gst-plugins-base-libs-%{majorminor} +%doc %{_datadir}/gtk-doc/html/gst-plugins-base-plugins-%{majorminor} + +%changelog +* Fri Dec 15 2006 Thomas Vander Stichele +- add doap file +- cleanups + +* Fri Sep 02 2005 Thomas Vander Stichele +- clean up a little + +* Fri May 6 2005 Christian Schaller +- Added libgstaudiorate and libgstsubparse to spec file + +* Thu May 5 2005 Christian Schaller +- first attempt at spec file for gst-plugins-base diff --git a/gst-plugins-base-subtitles0.10/gst/Makefile.am b/gst-plugins-base-subtitles0.10/gst/Makefile.am new file mode 100644 index 0000000..f25a56d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/Makefile.am @@ -0,0 +1,4 @@ +SUBDIRS = $(GST_PLUGINS_SELECTED) +DIST_SUBDIRS = $(GST_PLUGINS_ALL) + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/gst-plugins-base-subtitles0.10/gst/adder/.gitignore b/gst-plugins-base-subtitles0.10/gst/adder/.gitignore new file mode 100644 index 0000000..08f5ed3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.o +*.lo +*.la +.deps +.libs diff --git a/gst-plugins-base-subtitles0.10/gst/adder/Makefile.am b/gst-plugins-base-subtitles0.10/gst/adder/Makefile.am new file mode 100644 index 0000000..8fe5d21 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/Makefile.am @@ -0,0 +1,31 @@ +plugin_LTLIBRARIES = libgstadder.la + +ORC_SOURCE=gstadderorc +include $(top_srcdir)/common/orc.mak + + +libgstadder_la_SOURCES = gstadder.c +nodist_libgstadder_la_SOURCES = $(ORC_NODIST_SOURCES) +libgstadder_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS) +libgstadder_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstadder_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) +libgstadder_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstadder.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstadder -:SHARED libgstadder \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstadder_la_SOURCES) \ + $(nodist_libgstadder_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstadder_la_CFLAGS) \ + -:LDFLAGS $(libgstadder_la_LDFLAGS) \ + $(libgstadder_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/adder/adder.vcproj b/gst-plugins-base-subtitles0.10/gst/adder/adder.vcproj new file mode 100644 index 0000000..b2f193f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/adder.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/adder/gstadder.c b/gst-plugins-base-subtitles0.10/gst/adder/gstadder.c new file mode 100644 index 0000000..fca3eb2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/gstadder.c @@ -0,0 +1,1312 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2001 Thomas + * 2005,2006 Wim Taymans + * + * adder.c: Adder element, N in, one out, samples are added + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-adder + * + * The adder allows to mix several streams into one by adding the data. + * Mixed data is clamped to the min/max values of the data format. + * + * The adder currently mixes all data received on the sinkpads as soon as + * possible without trying to synchronize the streams. + * + * + * Example launch line + * |[ + * gst-launch audiotestsrc freq=100 ! adder name=mix ! audioconvert ! alsasink audiotestsrc freq=500 ! mix. + * ]| This pipeline produces two sine waves mixed together. + * + * + * Last reviewed on 2006-05-09 (0.10.7) + */ +/* Element-Checklist-Version: 5 */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gstadder.h" +#include +#include /* strcmp */ +#include "gstadderorc.h" + +/* highest positive/lowest negative x-bit value we can use for clamping */ +#define MAX_INT_32 ((gint32) (0x7fffffff)) +#define MAX_INT_16 ((gint16) (0x7fff)) +#define MAX_INT_8 ((gint8) (0x7f)) +#define MAX_UINT_32 ((guint32)(0xffffffff)) +#define MAX_UINT_16 ((guint16)(0xffff)) +#define MAX_UINT_8 ((guint8) (0xff)) + +#define MIN_INT_32 ((gint32) (0x80000000)) +#define MIN_INT_16 ((gint16) (0x8000)) +#define MIN_INT_8 ((gint8) (0x80)) +#define MIN_UINT_32 ((guint32)(0x00000000)) +#define MIN_UINT_16 ((guint16)(0x0000)) +#define MIN_UINT_8 ((guint8) (0x00)) + +enum +{ + PROP_0, + PROP_FILTER_CAPS +}; + +#define GST_CAT_DEFAULT gst_adder_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/* elementfactory information */ + +#define CAPS \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32, " \ + "depth = (int) 32, " \ + "signed = (boolean) { true, false } ;" \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) { true, false } ;" \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 8, " \ + "depth = (int) 8, " \ + "signed = (boolean) { true, false } ;" \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 32, 64 }" + +static GstStaticPadTemplate gst_adder_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CAPS) + ); + +static GstStaticPadTemplate gst_adder_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS (CAPS) + ); + +GST_BOILERPLATE (GstAdder, gst_adder, GstElement, GST_TYPE_ELEMENT); + +static void gst_adder_dispose (GObject * object); +static void gst_adder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_adder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_adder_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_adder_query (GstPad * pad, GstQuery * query); +static gboolean gst_adder_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_adder_sink_event (GstPad * pad, GstEvent * event); + +static GstPad *gst_adder_request_new_pad (GstElement * element, + GstPadTemplate * temp, const gchar * unused); +static void gst_adder_release_pad (GstElement * element, GstPad * pad); + +static GstStateChangeReturn gst_adder_change_state (GstElement * element, + GstStateChange transition); + +static GstBuffer *gst_adder_do_clip (GstCollectPads * pads, + GstCollectData * data, GstBuffer * buffer, gpointer user_data); +static GstFlowReturn gst_adder_collected (GstCollectPads * pads, + gpointer user_data); + +/* non-clipping versions (for float) */ +#define MAKE_FUNC_NC(name,type) \ +static void name (type *out, type *in, gint samples) { \ + gint i; \ + for (i = 0; i < samples; i++) \ + out[i] += in[i]; \ +} + +/* *INDENT-OFF* */ +MAKE_FUNC_NC (add_float64, gdouble) +/* *INDENT-ON* */ + +/* we can only accept caps that we and downstream can handle. + * if we have filtercaps set, use those to constrain the target caps. + */ +static GstCaps * +gst_adder_sink_getcaps (GstPad * pad) +{ + GstAdder *adder; + GstCaps *result, *peercaps, *sinkcaps, *filter_caps; + + adder = GST_ADDER (GST_PAD_PARENT (pad)); + + GST_OBJECT_LOCK (adder); + /* take filter */ + if ((filter_caps = adder->filter_caps)) + gst_caps_ref (filter_caps); + GST_OBJECT_UNLOCK (adder); + + /* get the downstream possible caps */ + peercaps = gst_pad_peer_get_caps (adder->srcpad); + + /* get the allowed caps on this sinkpad, we use the fixed caps function so + * that it does not call recursively in this function. */ + sinkcaps = gst_pad_get_fixed_caps_func (pad); + if (peercaps) { + /* restrict with filter-caps if any */ + if (filter_caps) { + GST_DEBUG_OBJECT (adder, "filtering peer caps"); + result = gst_caps_intersect (peercaps, filter_caps); + gst_caps_unref (peercaps); + peercaps = result; + } + /* if the peer has caps, intersect */ + GST_DEBUG_OBJECT (adder, "intersecting peer and template caps"); + result = gst_caps_intersect (peercaps, sinkcaps); + gst_caps_unref (peercaps); + gst_caps_unref (sinkcaps); + } else { + /* the peer has no caps (or there is no peer), just use the allowed caps + * of this sinkpad. */ + /* restrict with filter-caps if any */ + if (filter_caps) { + GST_DEBUG_OBJECT (adder, "no peer caps, using filtered sinkcaps"); + result = gst_caps_intersect (sinkcaps, filter_caps); + gst_caps_unref (sinkcaps); + } else { + GST_DEBUG_OBJECT (adder, "no peer caps, using sinkcaps"); + result = sinkcaps; + } + } + + if (filter_caps) + gst_caps_unref (filter_caps); + + GST_LOG_OBJECT (adder, "getting caps on pad %p,%s to %" GST_PTR_FORMAT, pad, + GST_PAD_NAME (pad), result); + + return result; +} + +/* the first caps we receive on any of the sinkpads will define the caps for all + * the other sinkpads because we can only mix streams with the same caps. + */ +static gboolean +gst_adder_setcaps (GstPad * pad, GstCaps * caps) +{ + GstAdder *adder; + GList *pads; + GstStructure *structure; + const char *media_type; + + adder = GST_ADDER (GST_PAD_PARENT (pad)); + + GST_LOG_OBJECT (adder, "setting caps on pad %p,%s to %" GST_PTR_FORMAT, pad, + GST_PAD_NAME (pad), caps); + + /* FIXME, see if the other pads can accept the format. Also lock the + * format on the other pads to this new format. */ + GST_OBJECT_LOCK (adder); + pads = GST_ELEMENT (adder)->pads; + while (pads) { + GstPad *otherpad = GST_PAD (pads->data); + + if (otherpad != pad) { + gst_caps_replace (&GST_PAD_CAPS (otherpad), caps); + } + pads = g_list_next (pads); + } + GST_OBJECT_UNLOCK (adder); + + /* parse caps now */ + structure = gst_caps_get_structure (caps, 0); + media_type = gst_structure_get_name (structure); + if (strcmp (media_type, "audio/x-raw-int") == 0) { + adder->format = GST_ADDER_FORMAT_INT; + gst_structure_get_int (structure, "width", &adder->width); + gst_structure_get_int (structure, "depth", &adder->depth); + gst_structure_get_int (structure, "endianness", &adder->endianness); + gst_structure_get_boolean (structure, "signed", &adder->is_signed); + + GST_INFO_OBJECT (pad, "parse_caps sets adder to format int, %d bit", + adder->width); + + if (adder->endianness != G_BYTE_ORDER) + goto not_supported; + + switch (adder->width) { + case 8: + adder->func = (adder->is_signed ? + (GstAdderFunction) add_int8 : (GstAdderFunction) add_uint8); + adder->sample_size = 1; + break; + case 16: + adder->func = (adder->is_signed ? + (GstAdderFunction) add_int16 : (GstAdderFunction) add_uint16); + adder->sample_size = 2; + break; + case 32: + adder->func = (adder->is_signed ? + (GstAdderFunction) add_int32 : (GstAdderFunction) add_uint32); + adder->sample_size = 4; + break; + default: + goto not_supported; + } + } else if (strcmp (media_type, "audio/x-raw-float") == 0) { + adder->format = GST_ADDER_FORMAT_FLOAT; + gst_structure_get_int (structure, "width", &adder->width); + gst_structure_get_int (structure, "endianness", &adder->endianness); + + GST_INFO_OBJECT (pad, "parse_caps sets adder to format float, %d bit", + adder->width); + + if (adder->endianness != G_BYTE_ORDER) + goto not_supported; + + switch (adder->width) { + case 32: + adder->func = (GstAdderFunction) add_float32; + adder->sample_size = 4; + break; + case 64: + adder->func = (GstAdderFunction) add_float64; + adder->sample_size = 8; + break; + default: + goto not_supported; + } + } else { + goto not_supported; + } + + gst_structure_get_int (structure, "channels", &adder->channels); + gst_structure_get_int (structure, "rate", &adder->rate); + /* precalc bps */ + adder->bps = (adder->width / 8) * adder->channels; + + return TRUE; + + /* ERRORS */ +not_supported: + { + GST_DEBUG_OBJECT (adder, "unsupported format set as caps"); + return FALSE; + } +} + +/* FIXME, the duration query should reflect how long you will produce + * data, that is the amount of stream time until you will emit EOS. + * + * For synchronized mixing this is always the max of all the durations + * of upstream since we emit EOS when all of them finished. + * + * We don't do synchronized mixing so this really depends on where the + * streams where punched in and what their relative offsets are against + * eachother which we can get from the first timestamps we see. + * + * When we add a new stream (or remove a stream) the duration might + * also become invalid again and we need to post a new DURATION + * message to notify this fact to the parent. + * For now we take the max of all the upstream elements so the simple + * cases work at least somewhat. + */ +static gboolean +gst_adder_query_duration (GstAdder * adder, GstQuery * query) +{ + gint64 max; + gboolean res; + GstFormat format; + GstIterator *it; + gboolean done; + + /* parse format */ + gst_query_parse_duration (query, &format, NULL); + + max = -1; + res = TRUE; + done = FALSE; + + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); + while (!done) { + GstIteratorResult ires; + + gpointer item; + + ires = gst_iterator_next (it, &item); + switch (ires) { + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_OK: + { + GstPad *pad = GST_PAD_CAST (item); + + gint64 duration; + + /* ask sink peer for duration */ + res &= gst_pad_query_peer_duration (pad, &format, &duration); + /* take max from all valid return values */ + if (res) { + /* valid unknown length, stop searching */ + if (duration == -1) { + max = duration; + done = TRUE; + } + /* else see if bigger than current max */ + else if (duration > max) + max = duration; + } + gst_object_unref (pad); + break; + } + case GST_ITERATOR_RESYNC: + max = -1; + res = TRUE; + gst_iterator_resync (it); + break; + default: + res = FALSE; + done = TRUE; + break; + } + } + gst_iterator_free (it); + + if (res) { + /* and store the max */ + GST_DEBUG_OBJECT (adder, "Total duration in format %s: %" + GST_TIME_FORMAT, gst_format_get_name (format), GST_TIME_ARGS (max)); + gst_query_set_duration (query, format, max); + } + + return res; +} + +static gboolean +gst_adder_query_latency (GstAdder * adder, GstQuery * query) +{ + GstClockTime min, max; + gboolean live; + gboolean res; + GstIterator *it; + gboolean done; + + res = TRUE; + done = FALSE; + + live = FALSE; + min = 0; + max = GST_CLOCK_TIME_NONE; + + /* Take maximum of all latency values */ + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); + while (!done) { + GstIteratorResult ires; + + gpointer item; + + ires = gst_iterator_next (it, &item); + switch (ires) { + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_OK: + { + GstPad *pad = GST_PAD_CAST (item); + GstQuery *peerquery; + GstClockTime min_cur, max_cur; + gboolean live_cur; + + peerquery = gst_query_new_latency (); + + /* Ask peer for latency */ + res &= gst_pad_peer_query (pad, peerquery); + + /* take max from all valid return values */ + if (res) { + gst_query_parse_latency (peerquery, &live_cur, &min_cur, &max_cur); + + if (min_cur > min) + min = min_cur; + + if (max_cur != GST_CLOCK_TIME_NONE && + ((max != GST_CLOCK_TIME_NONE && max_cur > max) || + (max == GST_CLOCK_TIME_NONE))) + max = max_cur; + + live = live || live_cur; + } + + gst_query_unref (peerquery); + gst_object_unref (pad); + break; + } + case GST_ITERATOR_RESYNC: + live = FALSE; + min = 0; + max = GST_CLOCK_TIME_NONE; + res = TRUE; + gst_iterator_resync (it); + break; + default: + res = FALSE; + done = TRUE; + break; + } + } + gst_iterator_free (it); + + if (res) { + /* store the results */ + GST_DEBUG_OBJECT (adder, "Calculated total latency: live %s, min %" + GST_TIME_FORMAT ", max %" GST_TIME_FORMAT, + (live ? "yes" : "no"), GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + gst_query_set_latency (query, live, min, max); + } + + return res; +} + +static gboolean +gst_adder_query (GstPad * pad, GstQuery * query) +{ + GstAdder *adder = GST_ADDER (gst_pad_get_parent (pad)); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + gst_query_parse_position (query, &format, NULL); + + switch (format) { + case GST_FORMAT_TIME: + /* FIXME, bring to stream time, might be tricky */ + gst_query_set_position (query, format, adder->timestamp); + res = TRUE; + break; + case GST_FORMAT_DEFAULT: + gst_query_set_position (query, format, adder->offset); + res = TRUE; + break; + default: + break; + } + break; + } + case GST_QUERY_DURATION: + res = gst_adder_query_duration (adder, query); + break; + case GST_QUERY_LATENCY: + res = gst_adder_query_latency (adder, query); + break; + default: + /* FIXME, needs a custom query handler because we have multiple + * sinkpads */ + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (adder); + return res; +} + +typedef struct +{ + GstEvent *event; + gboolean flush; +} EventData; + +static gboolean +forward_event_func (GstPad * pad, GValue * ret, EventData * data) +{ + GstEvent *event = data->event; + + gst_event_ref (event); + GST_LOG_OBJECT (pad, "About to send event %s", GST_EVENT_TYPE_NAME (event)); + if (!gst_pad_push_event (pad, event)) { + GST_WARNING_OBJECT (pad, "Sending event %p (%s) failed.", + event, GST_EVENT_TYPE_NAME (event)); + /* quick hack to unflush the pads, ideally we need a way to just unflush + * this single collect pad */ + if (data->flush) + gst_pad_send_event (pad, gst_event_new_flush_stop ()); + } else { + g_value_set_boolean (ret, TRUE); + GST_LOG_OBJECT (pad, "Sent event %p (%s).", + event, GST_EVENT_TYPE_NAME (event)); + } + gst_object_unref (pad); + + /* continue on other pads, even if one failed */ + return TRUE; +} + +/* forwards the event to all sinkpads, takes ownership of the + * event + * + * Returns: TRUE if the event could be forwarded on all + * sinkpads. + */ +static gboolean +forward_event (GstAdder * adder, GstEvent * event, gboolean flush) +{ + gboolean ret; + GstIterator *it; + GstIteratorResult ires; + GValue vret = { 0 }; + EventData data; + + GST_LOG_OBJECT (adder, "Forwarding event %p (%s)", event, + GST_EVENT_TYPE_NAME (event)); + + data.event = event; + data.flush = flush; + + g_value_init (&vret, G_TYPE_BOOLEAN); + g_value_set_boolean (&vret, FALSE); + it = gst_element_iterate_sink_pads (GST_ELEMENT_CAST (adder)); + while (TRUE) { + ires = gst_iterator_fold (it, (GstIteratorFoldFunction) forward_event_func, + &vret, &data); + switch (ires) { + case GST_ITERATOR_RESYNC: + GST_WARNING ("resync"); + gst_iterator_resync (it); + g_value_set_boolean (&vret, TRUE); + break; + case GST_ITERATOR_OK: + case GST_ITERATOR_DONE: + ret = g_value_get_boolean (&vret); + goto done; + default: + ret = FALSE; + goto done; + } + } +done: + gst_iterator_free (it); + GST_LOG_OBJECT (adder, "Forwarded event %p (%s), ret=%d", event, + GST_EVENT_TYPE_NAME (event), ret); + gst_event_unref (event); + + return ret; +} + +static gboolean +gst_adder_src_event (GstPad * pad, GstEvent * event) +{ + GstAdder *adder; + gboolean result; + + adder = GST_ADDER (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstSeekFlags flags; + GstSeekType curtype, endtype; + gint64 cur, end; + gboolean flush; + + /* parse the seek parameters */ + gst_event_parse_seek (event, &adder->segment_rate, NULL, &flags, &curtype, + &cur, &endtype, &end); + + if ((curtype != GST_SEEK_TYPE_NONE) && (curtype != GST_SEEK_TYPE_SET)) { + result = FALSE; + GST_DEBUG_OBJECT (adder, + "seeking failed, unhandled seek type for start: %d", curtype); + goto done; + } + if ((endtype != GST_SEEK_TYPE_NONE) && (endtype != GST_SEEK_TYPE_SET)) { + result = FALSE; + GST_DEBUG_OBJECT (adder, + "seeking failed, unhandled seek type for end: %d", endtype); + goto done; + } + + flush = (flags & GST_SEEK_FLAG_FLUSH) == GST_SEEK_FLAG_FLUSH; + + /* check if we are flushing */ + if (flush) { + /* make sure we accept nothing anymore and return WRONG_STATE */ + gst_collect_pads_set_flushing (adder->collect, TRUE); + + /* flushing seek, start flush downstream, the flush will be done + * when all pads received a FLUSH_STOP. */ + gst_pad_push_event (adder->srcpad, gst_event_new_flush_start ()); + + /* We can't send FLUSH_STOP here since upstream could start pushing data + * after we unlock adder->collect. + * We set flush_stop_pending to TRUE instead and send FLUSH_STOP after + * forwarding the seek upstream or from gst_adder_collected, + * whichever happens first. + */ + adder->flush_stop_pending = TRUE; + } + GST_DEBUG_OBJECT (adder, "handling seek event: %" GST_PTR_FORMAT, event); + + /* now wait for the collected to be finished and mark a new + * segment. After we have the lock, no collect function is running and no + * new collect function will be called for as long as we're flushing. */ + GST_OBJECT_LOCK (adder->collect); + if (curtype == GST_SEEK_TYPE_SET) + adder->segment_start = cur; + else + adder->segment_start = 0; + if (endtype == GST_SEEK_TYPE_SET) + adder->segment_end = end; + else + adder->segment_end = GST_CLOCK_TIME_NONE; + /* make sure we push a new segment, to inform about new basetime + * see FIXME in gst_adder_collected() */ + adder->segment_pending = TRUE; + if (flush) { + /* Yes, we need to call _set_flushing again *WHEN* the streaming threads + * have stopped so that the cookie gets properly updated. */ + gst_collect_pads_set_flushing (adder->collect, TRUE); + } + GST_OBJECT_UNLOCK (adder->collect); + GST_DEBUG_OBJECT (adder, "forwarding seek event: %" GST_PTR_FORMAT, + event); + + result = forward_event (adder, event, flush); + if (!result) { + /* seek failed. maybe source is a live source. */ + GST_DEBUG_OBJECT (adder, "seeking failed"); + } + if (g_atomic_int_compare_and_exchange (&adder->flush_stop_pending, + TRUE, FALSE)) { + GST_DEBUG_OBJECT (adder, "pending flush stop"); + gst_pad_push_event (adder->srcpad, gst_event_new_flush_stop ()); + } + break; + } + case GST_EVENT_QOS: + /* QoS might be tricky */ + result = FALSE; + break; + case GST_EVENT_NAVIGATION: + /* navigation is rather pointless. */ + result = FALSE; + break; + default: + /* just forward the rest for now */ + GST_DEBUG_OBJECT (adder, "forward unhandled event: %s", + GST_EVENT_TYPE_NAME (event)); + result = forward_event (adder, event, FALSE); + break; + } + +done: + gst_object_unref (adder); + + return result; +} + +static gboolean +gst_adder_sink_event (GstPad * pad, GstEvent * event) +{ + GstAdder *adder; + gboolean ret = TRUE; + + adder = GST_ADDER (gst_pad_get_parent (pad)); + + GST_DEBUG ("Got %s event on pad %s:%s", GST_EVENT_TYPE_NAME (event), + GST_DEBUG_PAD_NAME (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + /* we received a flush-stop. The collect_event function will push the + * event past our element. We simply forward all flush-stop events, even + * when no flush-stop was pending, this is required because collectpads + * does not provide an API to handle-but-not-forward the flush-stop. + * We unset the pending flush-stop flag so that we don't send anymore + * flush-stop from the collect function later. + */ + GST_OBJECT_LOCK (adder->collect); + adder->segment_pending = TRUE; + adder->flush_stop_pending = FALSE; + /* Clear pending tags */ + if (adder->pending_events) { + g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (adder->pending_events); + adder->pending_events = NULL; + } + GST_OBJECT_UNLOCK (adder->collect); + break; + case GST_EVENT_TAG: + GST_OBJECT_LOCK (adder->collect); + /* collect tags here so we can push them out when we collect data */ + adder->pending_events = g_list_append (adder->pending_events, event); + GST_OBJECT_UNLOCK (adder->collect); + goto beach; + default: + break; + } + + /* now GstCollectPads can take care of the rest, e.g. EOS */ + ret = adder->collect_event (pad, event); + +beach: + gst_object_unref (adder); + return ret; +} + +static void +gst_adder_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_adder_src_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_adder_sink_template)); + gst_element_class_set_details_simple (gstelement_class, "Adder", + "Generic/Audio", + "Add N audio channels together", + "Thomas Vander Stichele "); +} + +static void +gst_adder_class_init (GstAdderClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_adder_set_property; + gobject_class->get_property = gst_adder_get_property; + gobject_class->dispose = gst_adder_dispose; + + /** + * GstAdder:caps: + * + * Since: 0.10.24 + */ + g_object_class_install_property (gobject_class, PROP_FILTER_CAPS, + g_param_spec_boxed ("caps", "Target caps", + "Set target format for mixing (NULL means ANY). " + "Setting this property takes a reference to the supplied GstCaps " + "object.", GST_TYPE_CAPS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_adder_request_new_pad); + gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_adder_release_pad); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_adder_change_state); +} + +static void +gst_adder_init (GstAdder * adder, GstAdderClass * klass) +{ + GstPadTemplate *template; + + template = gst_static_pad_template_get (&gst_adder_src_template); + adder->srcpad = gst_pad_new_from_template (template, "src"); + gst_object_unref (template); + + gst_pad_set_getcaps_function (adder->srcpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); + gst_pad_set_setcaps_function (adder->srcpad, + GST_DEBUG_FUNCPTR (gst_adder_setcaps)); + gst_pad_set_query_function (adder->srcpad, + GST_DEBUG_FUNCPTR (gst_adder_query)); + gst_pad_set_event_function (adder->srcpad, + GST_DEBUG_FUNCPTR (gst_adder_src_event)); + gst_element_add_pad (GST_ELEMENT (adder), adder->srcpad); + + adder->format = GST_ADDER_FORMAT_UNSET; + adder->padcount = 0; + adder->func = NULL; + + adder->filter_caps = NULL; + + /* keep track of the sinkpads requested */ + adder->collect = gst_collect_pads_new (); + gst_collect_pads_set_function (adder->collect, + GST_DEBUG_FUNCPTR (gst_adder_collected), adder); + gst_collect_pads_set_clip_function (adder->collect, + GST_DEBUG_FUNCPTR (gst_adder_do_clip), adder); +} + +static void +gst_adder_dispose (GObject * object) +{ + GstAdder *adder = GST_ADDER (object); + + if (adder->collect) { + gst_object_unref (adder->collect); + adder->collect = NULL; + } + gst_caps_replace (&adder->filter_caps, NULL); + if (adder->pending_events) { + g_list_foreach (adder->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (adder->pending_events); + adder->pending_events = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_adder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAdder *adder = GST_ADDER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS:{ + GstCaps *new_caps = NULL; + GstCaps *old_caps; + const GstCaps *new_caps_val = gst_value_get_caps (value); + + if (new_caps_val != NULL) { + new_caps = (GstCaps *) new_caps_val; + gst_caps_ref (new_caps); + } + + GST_OBJECT_LOCK (adder); + old_caps = adder->filter_caps; + adder->filter_caps = new_caps; + GST_OBJECT_UNLOCK (adder); + + if (old_caps) + gst_caps_unref (old_caps); + + GST_DEBUG_OBJECT (adder, "set new caps %" GST_PTR_FORMAT, new_caps); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_adder_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstAdder *adder = GST_ADDER (object); + + switch (prop_id) { + case PROP_FILTER_CAPS: + GST_OBJECT_LOCK (adder); + gst_value_set_caps (value, adder->filter_caps); + GST_OBJECT_UNLOCK (adder); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static GstPad * +gst_adder_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * unused) +{ + gchar *name; + GstAdder *adder; + GstPad *newpad; + gint padcount; + + if (templ->direction != GST_PAD_SINK) + goto not_sink; + + adder = GST_ADDER (element); + + /* increment pad counter */ + padcount = g_atomic_int_exchange_and_add (&adder->padcount, 1); + + name = g_strdup_printf ("sink%d", padcount); + newpad = gst_pad_new_from_template (templ, name); + GST_DEBUG_OBJECT (adder, "request new pad %s", name); + g_free (name); + + gst_pad_set_getcaps_function (newpad, + GST_DEBUG_FUNCPTR (gst_adder_sink_getcaps)); + gst_pad_set_setcaps_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_setcaps)); + gst_collect_pads_add_pad (adder->collect, newpad, sizeof (GstCollectData)); + + /* 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 */ + adder->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad); + gst_pad_set_event_function (newpad, GST_DEBUG_FUNCPTR (gst_adder_sink_event)); + + /* takes ownership of the pad */ + if (!gst_element_add_pad (GST_ELEMENT (adder), newpad)) + goto could_not_add; + + return newpad; + + /* errors */ +not_sink: + { + g_warning ("gstadder: request new pad that is not a SINK pad\n"); + return NULL; + } +could_not_add: + { + GST_DEBUG_OBJECT (adder, "could not add pad"); + gst_collect_pads_remove_pad (adder->collect, newpad); + gst_object_unref (newpad); + return NULL; + } +} + +static void +gst_adder_release_pad (GstElement * element, GstPad * pad) +{ + GstAdder *adder; + + adder = GST_ADDER (element); + + GST_DEBUG_OBJECT (adder, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + gst_collect_pads_remove_pad (adder->collect, pad); + gst_element_remove_pad (element, pad); +} + +static GstBuffer * +gst_adder_do_clip (GstCollectPads * pads, GstCollectData * data, + GstBuffer * buffer, gpointer user_data) +{ + GstAdder *adder = GST_ADDER (user_data); + + buffer = gst_audio_buffer_clip (buffer, &data->segment, adder->rate, + adder->bps); + + return buffer; +} + +static GstFlowReturn +gst_adder_collected (GstCollectPads * pads, gpointer user_data) +{ + /* + * combine streams by adding data values + * basic algorithm : + * - this function is called when all pads have a buffer + * - get available bytes on all pads. + * - repeat for each input pad : + * - read available bytes, copy or add to target buffer + * - if there's an EOS event, remove the input channel + * - push out the output buffer + * + * todo: + * - would be nice to have a mixing mode, where instead of adding we mix + * - for float we could downscale after collect loop + * - for int we need to downscale each input to avoid clipping or + * mix into a temp (float) buffer and scale afterwards as well + */ + GstAdder *adder; + GSList *collected, *next = NULL; + GstFlowReturn ret; + GstBuffer *outbuf = NULL, *gapbuf = NULL; + gpointer outdata = NULL; + guint outsize; + gint64 next_offset; + gint64 next_timestamp; + + adder = GST_ADDER (user_data); + + /* this is fatal */ + if (G_UNLIKELY (adder->func == NULL)) + goto not_negotiated; + + if (g_atomic_int_compare_and_exchange (&adder->flush_stop_pending, + TRUE, FALSE)) { + GST_DEBUG_OBJECT (adder, "pending flush stop"); + gst_pad_push_event (adder->srcpad, gst_event_new_flush_stop ()); + } + + /* get available bytes for reading, this can be 0 which could mean empty + * buffers or EOS, which we will catch when we loop over the pads. */ + outsize = gst_collect_pads_available (pads); + /* can only happen when no pads to collect or all EOS */ + if (outsize == 0) + goto eos; + + GST_LOG_OBJECT (adder, + "starting to cycle through channels, %d bytes available (bps = %d)", + outsize, adder->bps); + + for (collected = pads->data; collected; collected = next) { + GstCollectData *collect_data; + GstBuffer *inbuf; + gboolean is_gap; + + /* take next to see if this is the last collectdata */ + next = g_slist_next (collected); + + collect_data = (GstCollectData *) collected->data; + + /* get a buffer of size bytes, if we get a buffer, it is at least outsize + * bytes big. */ + inbuf = gst_collect_pads_take_buffer (pads, collect_data, outsize); + /* NULL means EOS or an empty buffer so we still need to flush in + * case of an empty buffer. */ + if (inbuf == NULL) { + GST_LOG_OBJECT (adder, "channel %p: no bytes available", collect_data); + continue; + } + + is_gap = GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP); + + /* Try to make an output buffer */ + if (outbuf == NULL) { + /* if this is a gap buffer but we have some more pads to check, skip it. + * If we are at the last buffer, take it, regardless if it is a GAP + * buffer or not. */ + if (is_gap && next) { + GST_DEBUG_OBJECT (adder, "skipping, non-last GAP buffer"); + /* we keep the GAP buffer, if we don't have anymore buffers (all pads + * EOS, we can use this one as the output buffer. */ + if (gapbuf == NULL) + gapbuf = inbuf; + else + gst_buffer_unref (inbuf); + continue; + } + + GST_LOG_OBJECT (adder, "channel %p: preparing output buffer of %d bytes", + collect_data, outsize); + /* make data and metadata writable, can simply return the inbuf when we + * are the only one referencing this buffer. If this is the last (and + * only) GAP buffer, it will automatically copy the GAP flag. */ + outbuf = gst_buffer_make_writable (inbuf); + outdata = GST_BUFFER_DATA (outbuf); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (adder->srcpad)); + } else { + if (!is_gap) { + /* we had a previous output buffer, mix this non-GAP buffer */ + guint8 *indata; + guint insize; + + indata = GST_BUFFER_DATA (inbuf); + insize = GST_BUFFER_SIZE (inbuf); + + /* all buffers should have outsize, there are no short buffers because we + * asked for the max size above */ + g_assert (insize == outsize); + + GST_LOG_OBJECT (adder, "channel %p: mixing %d bytes from data %p", + collect_data, insize, indata); + + /* further buffers, need to add them */ + adder->func ((gpointer) outdata, (gpointer) indata, + insize / adder->sample_size); + } else { + /* skip gap buffer */ + GST_LOG_OBJECT (adder, "channel %p: skipping GAP buffer", collect_data); + } + gst_buffer_unref (inbuf); + } + } + + if (outbuf == NULL) { + /* no output buffer, reuse one of the GAP buffers then if we have one */ + if (gapbuf) { + GST_LOG_OBJECT (adder, "reusing GAP buffer %p", gapbuf); + outbuf = gapbuf; + } else + /* assume EOS otherwise, this should not happen, really */ + goto eos; + } else if (gapbuf) + /* we had an output buffer, unref the gapbuffer we kept */ + gst_buffer_unref (gapbuf); + + if (adder->segment_pending) { + GstEvent *event; + + /* FIXME, use rate/applied_rate as set on all sinkpads. + * - currently we just set rate as received from last seek-event + * + * When seeking we set the start and stop positions as given in the seek + * event. We also adjust offset & timestamp acordingly. + * This basically ignores all newsegments sent by upstream. + */ + event = gst_event_new_new_segment_full (FALSE, adder->segment_rate, + 1.0, GST_FORMAT_TIME, adder->segment_start, adder->segment_end, + adder->segment_start); + if (adder->segment_rate > 0.0) { + adder->timestamp = adder->segment_start; + } else { + adder->timestamp = adder->segment_end; + } + adder->offset = gst_util_uint64_scale (adder->timestamp, + adder->rate, GST_SECOND); + GST_INFO_OBJECT (adder, "seg_start %" G_GUINT64_FORMAT ", seg_end %" + G_GUINT64_FORMAT, adder->segment_start, adder->segment_end); + GST_INFO_OBJECT (adder, "timestamp %" G_GINT64_FORMAT ",new offset %" + G_GINT64_FORMAT, adder->timestamp, adder->offset); + + if (event) { + if (!gst_pad_push_event (adder->srcpad, event)) { + GST_WARNING_OBJECT (adder->srcpad, "Sending event %p (%s) failed.", + event, GST_EVENT_TYPE_NAME (event)); + } + adder->segment_pending = FALSE; + } else { + GST_WARNING_OBJECT (adder->srcpad, "Creating new segment event for " + "start:%" G_GINT64_FORMAT " end:%" G_GINT64_FORMAT " failed", + adder->segment_start, adder->segment_end); + } + } + + if (G_UNLIKELY (adder->pending_events)) { + GList *tmp = adder->pending_events; + + while (tmp) { + GstEvent *ev = (GstEvent *) tmp->data; + + gst_pad_push_event (adder->srcpad, ev); + tmp = g_list_next (tmp); + } + g_list_free (adder->pending_events); + adder->pending_events = NULL; + } + + /* for the next timestamp, use the sample counter, which will + * never accumulate rounding errors */ + if (adder->segment_rate > 0.0) { + next_offset = adder->offset + outsize / adder->bps; + } else { + next_offset = adder->offset - outsize / adder->bps; + } + next_timestamp = gst_util_uint64_scale (next_offset, GST_SECOND, adder->rate); + + + /* set timestamps on the output buffer */ + if (adder->segment_rate > 0.0) { + GST_BUFFER_TIMESTAMP (outbuf) = adder->timestamp; + GST_BUFFER_OFFSET (outbuf) = adder->offset; + GST_BUFFER_OFFSET_END (outbuf) = next_offset; + GST_BUFFER_DURATION (outbuf) = next_timestamp - adder->timestamp; + } else { + GST_BUFFER_TIMESTAMP (outbuf) = next_timestamp; + GST_BUFFER_OFFSET (outbuf) = next_offset; + GST_BUFFER_OFFSET_END (outbuf) = adder->offset; + GST_BUFFER_DURATION (outbuf) = adder->timestamp - next_timestamp; + } + + adder->offset = next_offset; + adder->timestamp = next_timestamp; + + /* send it out */ + GST_LOG_OBJECT (adder, "pushing outbuf %p, timestamp %" GST_TIME_FORMAT + " offset %" G_GINT64_FORMAT, outbuf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), + GST_BUFFER_OFFSET (outbuf)); + ret = gst_pad_push (adder->srcpad, outbuf); + + GST_LOG_OBJECT (adder, "pushed outbuf, result = %s", gst_flow_get_name (ret)); + + return ret; + + /* ERRORS */ +not_negotiated: + { + GST_ELEMENT_ERROR (adder, STREAM, FORMAT, (NULL), + ("Unknown data received, not negotiated")); + return GST_FLOW_NOT_NEGOTIATED; + } +eos: + { + GST_DEBUG_OBJECT (adder, "no data available, must be EOS"); + gst_pad_push_event (adder->srcpad, gst_event_new_eos ()); + return GST_FLOW_UNEXPECTED; + } +} + +static GstStateChangeReturn +gst_adder_change_state (GstElement * element, GstStateChange transition) +{ + GstAdder *adder; + GstStateChangeReturn ret; + + adder = GST_ADDER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + adder->timestamp = 0; + adder->offset = 0; + adder->flush_stop_pending = FALSE; + adder->segment_pending = TRUE; + adder->segment_start = 0; + adder->segment_end = GST_CLOCK_TIME_NONE; + adder->segment_rate = 1.0; + gst_segment_init (&adder->segment, GST_FORMAT_UNDEFINED); + gst_collect_pads_start (adder->collect); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* need to unblock the collectpads before calling the + * parent change_state so that streaming can finish */ + gst_collect_pads_stop (adder->collect); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + default: + break; + } + + return ret; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "adder", 0, + "audio channel mixing element"); + + gst_adder_orc_init (); + + if (!gst_element_register (plugin, "adder", GST_RANK_NONE, GST_TYPE_ADDER)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "adder", + "Adds multiple streams", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/adder/gstadder.h b/gst-plugins-base-subtitles0.10/gst/adder/gstadder.h new file mode 100644 index 0000000..f0151b4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/gstadder.h @@ -0,0 +1,110 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * + * gstadder.h: Header for GstAdder element + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_ADDER_H__ +#define __GST_ADDER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_ADDER (gst_adder_get_type()) +#define GST_ADDER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ADDER,GstAdder)) +#define GST_IS_ADDER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ADDER)) +#define GST_ADDER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass) ,GST_TYPE_ADDER,GstAdderClass)) +#define GST_IS_ADDER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass) ,GST_TYPE_ADDER)) +#define GST_ADDER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj) ,GST_TYPE_ADDER,GstAdderClass)) + +typedef struct _GstAdder GstAdder; +typedef struct _GstAdderClass GstAdderClass; +typedef struct _GstAdderInputChannel GstAdderInputChannel; + +typedef enum { + GST_ADDER_FORMAT_UNSET, + GST_ADDER_FORMAT_INT, + GST_ADDER_FORMAT_FLOAT +} GstAdderFormat; + +typedef void (*GstAdderFunction) (gpointer out, gpointer in, guint size); + +/** + * GstAdder: + * + * The adder object structure. + */ +struct _GstAdder { + GstElement element; + + GstPad *srcpad; + GstCollectPads *collect; + /* pad counter, used for creating unique request pads */ + gint padcount; + + /* the next are valid for both int and float */ + GstAdderFormat format; + gint rate; + gint channels; + gint width; + gint endianness; + int sample_size; + + /* the next are valid only for format == GST_ADDER_FORMAT_INT */ + gint depth; + gboolean is_signed; + + /* number of bytes per sample, actually width/8 * channels */ + gint bps; + + /* function to add samples */ + GstAdderFunction func; + + /* counters to keep track of timestamps */ + gint64 timestamp; + gint64 offset; + + /* sink event handling */ + GstPadEventFunction collect_event; + GstSegment segment; + gboolean segment_pending; + guint64 segment_start, segment_end; + gdouble segment_rate; + /* src event handling */ + gboolean flush_stop_pending; + + /* target caps */ + GstCaps *filter_caps; + + /* Pending inline events */ + GList *pending_events; +}; + +struct _GstAdderClass { + GstElementClass parent_class; +}; + +GType gst_adder_get_type (void); + +G_END_DECLS + + +#endif /* __GST_ADDER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.c b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.c new file mode 100644 index 0000000..b1850f0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.c @@ -0,0 +1,835 @@ + +/* autogenerated from gstadderorc.orc */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 + +#ifndef DISABLE_ORC +#include +#endif +void add_int32 (gint32 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, + int n); +void add_int16 (gint16 * ORC_RESTRICT d1, const gint16 * ORC_RESTRICT s1, + int n); +void add_int8 (gint8 * ORC_RESTRICT d1, const gint8 * ORC_RESTRICT s1, int n); +void add_uint32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, + int n); +void add_uint16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, + int n); +void add_uint8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, + int n); +void add_float32 (float *ORC_RESTRICT d1, const float *ORC_RESTRICT s1, int n); + +void gst_adder_orc_init (void); + + +/* begin Orc C target preamble */ +#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x))) +#define ORC_ABS(a) ((a)<0 ? -(a) : (a)) +#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define ORC_SB_MAX 127 +#define ORC_SB_MIN (-1-ORC_SB_MAX) +#define ORC_UB_MAX 255 +#define ORC_UB_MIN 0 +#define ORC_SW_MAX 32767 +#define ORC_SW_MIN (-1-ORC_SW_MAX) +#define ORC_UW_MAX 65535 +#define ORC_UW_MIN 0 +#define ORC_SL_MAX 2147483647 +#define ORC_SL_MIN (-1-ORC_SL_MAX) +#define ORC_UL_MAX 4294967295U +#define ORC_UL_MIN 0 +#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX) +#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX) +#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX) +#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX) +#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX) +#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) +#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) +#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) +#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#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 +#define ORC_RESTRICT __restrict__ +#else +#define ORC_RESTRICT +#endif +#endif +/* end Orc C target preamble */ + + + +/* add_int32 */ +#ifdef DISABLE_ORC +void +add_int32 (gint32 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addssl */ + var34.i = ORC_CLAMP_SL ((orc_int64) var32.i + (orc_int64) var33.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_int32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addssl */ + var34.i = ORC_CLAMP_SL ((orc_int64) var32.i + (orc_int64) var33.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_int32; +void +add_int32 (gint32 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_int32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_int16 */ +#ifdef DISABLE_ORC +void +add_int16 (gint16 * ORC_RESTRICT d1, const gint16 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var32; + orc_union16 var33; + orc_union16 var34; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var32 = ptr0[i]; + /* 1: loadw */ + var33 = ptr4[i]; + /* 2: addssw */ + var34.i = ORC_CLAMP_SW (var32.i + var33.i); + /* 3: storew */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_int16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var32; + orc_union16 var33; + orc_union16 var34; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var32 = ptr0[i]; + /* 1: loadw */ + var33 = ptr4[i]; + /* 2: addssw */ + var34.i = ORC_CLAMP_SW (var32.i + var33.i); + /* 3: storew */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_int16; +void +add_int16 (gint16 * ORC_RESTRICT d1, const gint16 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_int16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_int8 */ +#ifdef DISABLE_ORC +void +add_int8 (gint8 * ORC_RESTRICT d1, const gint8 * ORC_RESTRICT s1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + orc_int8 var33; + orc_int8 var34; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var32 = ptr0[i]; + /* 1: loadb */ + var33 = ptr4[i]; + /* 2: addssb */ + var34 = ORC_CLAMP_SB (var32 + var33); + /* 3: storeb */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_int8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + orc_int8 var33; + orc_int8 var34; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var32 = ptr0[i]; + /* 1: loadb */ + var33 = ptr4[i]; + /* 2: addssb */ + var34 = ORC_CLAMP_SB (var32 + var33); + /* 3: storeb */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_int8; +void +add_int8 (gint8 * ORC_RESTRICT d1, const gint8 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_int8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_uint32 */ +#ifdef DISABLE_ORC +void +add_uint32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addusl */ + var34.i = + ORC_CLAMP_UL ((orc_int64) (orc_uint32) var32.i + + (orc_int64) (orc_uint32) var33.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_uint32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addusl */ + var34.i = + ORC_CLAMP_UL ((orc_int64) (orc_uint32) var32.i + + (orc_int64) (orc_uint32) var33.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_uint32; +void +add_uint32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_uint32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_uint16 */ +#ifdef DISABLE_ORC +void +add_uint16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var32; + orc_union16 var33; + orc_union16 var34; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var32 = ptr0[i]; + /* 1: loadw */ + var33 = ptr4[i]; + /* 2: addusw */ + var34.i = ORC_CLAMP_UW ((orc_uint16) var32.i + (orc_uint16) var33.i); + /* 3: storew */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_uint16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var32; + orc_union16 var33; + orc_union16 var34; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var32 = ptr0[i]; + /* 1: loadw */ + var33 = ptr4[i]; + /* 2: addusw */ + var34.i = ORC_CLAMP_UW ((orc_uint16) var32.i + (orc_uint16) var33.i); + /* 3: storew */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_uint16; +void +add_uint16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_uint16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_uint8 */ +#ifdef DISABLE_ORC +void +add_uint8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + orc_int8 var33; + orc_int8 var34; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var32 = ptr0[i]; + /* 1: loadb */ + var33 = ptr4[i]; + /* 2: addusb */ + var34 = ORC_CLAMP_UB ((orc_uint8) var32 + (orc_uint8) var33); + /* 3: storeb */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_uint8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + orc_int8 var33; + orc_int8 var34; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var32 = ptr0[i]; + /* 1: loadb */ + var33 = ptr4[i]; + /* 2: addusb */ + var34 = ORC_CLAMP_UB ((orc_uint8) var32 + (orc_uint8) var33); + /* 3: storeb */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_uint8; +void +add_uint8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_uint8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* add_float32 */ +#ifdef DISABLE_ORC +void +add_float32 (float *ORC_RESTRICT d1, const float *ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var32.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f + _src2.f; + var34.i = ORC_DENORMAL (_dest1.i); + } + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_add_float32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 1: loadl */ + var33 = ptr4[i]; + /* 2: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var32.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f + _src2.f; + var34.i = ORC_DENORMAL (_dest1.i); + } + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_add_float32; +void +add_float32 (float *ORC_RESTRICT d1, const float *ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_add_float32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +void +gst_adder_orc_init (void) +{ +#ifndef DISABLE_ORC + { + /* add_int32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_int32"); + orc_program_set_backup_function (p, _backup_add_int32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + + orc_program_append_2 (p, "addssl", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_int32 = p; + } + { + /* add_int16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_int16"); + orc_program_set_backup_function (p, _backup_add_int16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 2, "s1"); + + orc_program_append_2 (p, "addssw", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_int16 = p; + } + { + /* add_int8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_int8"); + orc_program_set_backup_function (p, _backup_add_int8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + + orc_program_append_2 (p, "addssb", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_int8 = p; + } + { + /* add_uint32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_uint32"); + orc_program_set_backup_function (p, _backup_add_uint32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + + orc_program_append_2 (p, "addusl", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_uint32 = p; + } + { + /* add_uint16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_uint16"); + orc_program_set_backup_function (p, _backup_add_uint16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 2, "s1"); + + orc_program_append_2 (p, "addusw", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_uint16 = p; + } + { + /* add_uint8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_uint8"); + orc_program_set_backup_function (p, _backup_add_uint8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + + orc_program_append_2 (p, "addusb", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_uint8 = p; + } + { + /* add_float32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "add_float32"); + orc_program_set_backup_function (p, _backup_add_float32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + + orc_program_append_2 (p, "addf", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_add_float32 = p; + } +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.h b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.h new file mode 100644 index 0000000..31ba99e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc-dist.h @@ -0,0 +1,85 @@ + +/* autogenerated from gstadderorc.orc */ + +#ifndef _GSTADDERORC_H_ +#define _GSTADDERORC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void gst_adder_orc_init (void); + + + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 add_int32 (gint32 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n); +void add_int16 (gint16 * ORC_RESTRICT d1, const gint16 * ORC_RESTRICT s1, int n); +void add_int8 (gint8 * ORC_RESTRICT d1, const gint8 * ORC_RESTRICT s1, int n); +void add_uint32 (guint32 * ORC_RESTRICT d1, const guint32 * ORC_RESTRICT s1, int n); +void add_uint16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, int n); +void add_uint8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n); +void add_float32 (float * ORC_RESTRICT d1, const float * ORC_RESTRICT s1, int n); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc.orc b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc.orc new file mode 100644 index 0000000..f8c3caf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/adder/gstadderorc.orc @@ -0,0 +1,52 @@ + +.init gst_adder_orc_init + +.function add_int32 +.dest 4 d1 gint32 +.source 4 s1 gint32 + +addssl d1, d1, s1 + + +.function add_int16 +.dest 2 d1 gint16 +.source 2 s1 gint16 + +addssw d1, d1, s1 + + +.function add_int8 +.dest 1 d1 gint8 +.source 1 s1 gint8 + +addssb d1, d1, s1 + + +.function add_uint32 +.dest 4 d1 guint32 +.source 4 s1 guint32 + +addusl d1, d1, s1 + + +.function add_uint16 +.dest 2 d1 guint16 +.source 2 s1 guint16 + +addusw d1, d1, s1 + + +.function add_uint8 +.dest 1 d1 guint8 +.source 1 s1 guint8 + +addusb d1, d1, s1 + + +.function add_float32 +.dest 4 d1 float +.source 4 s1 float + +addf d1, d1, s1 + + diff --git a/gst-plugins-base-subtitles0.10/gst/app/Makefile.am b/gst-plugins-base-subtitles0.10/gst/app/Makefile.am new file mode 100644 index 0000000..2170623 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/app/Makefile.am @@ -0,0 +1,21 @@ +plugin_LTLIBRARIES = libgstapp.la + +libgstapp_la_SOURCES = gstapp.c +libgstapp_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstapp_la_LIBADD = $(GST_BASE_LIBS) $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la +libgstapp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstapp_la_LIBTOOLFLAGS = --tag=disable-static + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstapp -:SHARED libgstapp \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstapp_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstapp_la_CFLAGS) \ + -:LDFLAGS $(libgstapp_la_LDFLAGS) \ + $(libgstapp_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/app/gstapp.c b/gst-plugins-base-subtitles0.10/gst/app/gstapp.c new file mode 100644 index 0000000..098fbdd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/app/gstapp.c @@ -0,0 +1,42 @@ +/* GStreamer + * Copyright (C) 2007 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_element_register (plugin, "appsrc", GST_RANK_NONE, GST_TYPE_APP_SRC); + gst_element_register (plugin, "appsink", GST_RANK_NONE, GST_TYPE_APP_SINK); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "app", + "Elements used to communicate with applications", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/.gitignore b/gst-plugins-base-subtitles0.10/gst/audioconvert/.gitignore new file mode 100644 index 0000000..696560c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/.gitignore @@ -0,0 +1 @@ +channelmixtest diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/Makefile.am b/gst-plugins-base-subtitles0.10/gst/audioconvert/Makefile.am new file mode 100644 index 0000000..b8849b6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/Makefile.am @@ -0,0 +1,51 @@ +plugin_LTLIBRARIES = libgstaudioconvert.la + +ORC_SOURCE=gstaudioconvertorc +include $(top_srcdir)/common/orc.mak + +libgstaudioconvert_la_SOURCES = \ + gstaudioconvert.c \ + audioconvert.c \ + gstchannelmix.c \ + gstaudioquantize.c \ + plugin.c +nodist_libgstaudioconvert_la_SOURCES = $(ORC_NODIST_SOURCES) + +libgstaudioconvert_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS) +libgstaudioconvert_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstaudioconvert_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM) +libgstaudioconvert_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstaudioconvert.h \ + audioconvert.h \ + gstchannelmix.h \ + gstaudioquantize.h \ + gstfastrandom.h \ + plugin.h + +#TESTS = channelmixtest +#noinst_PROGRAMS = channelmixtest + +#channelmixtest_CFLAGS = $(GST_CFLAGS) +#channelmixtest_LDADD = libgstaudioconvert.la \ +# $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ +# $(GST_LIBS) + + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstaudioconvert -:SHARED libgstaudioconvert \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstaudioconvert_la_SOURCES) \ + $(nodist_libgstaudioconvert_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudioconvert_la_CFLAGS) \ + -:LDFLAGS $(libgstaudioconvert_la_LDFLAGS) \ + $(libgstaudioconvert_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.c new file mode 100644 index 0000000..524098c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.c @@ -0,0 +1,796 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * audioconvert.c: Convert audio to different audio formats automatically + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include "gstchannelmix.h" +#include "gstaudioquantize.h" +#include "audioconvert.h" +#include "gst/floatcast/floatcast.h" +#include "gstaudioconvertorc.h" + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define orc_audio_convert_unpack_u16_le orc_audio_convert_unpack_u16 +#define orc_audio_convert_unpack_u16_be orc_audio_convert_unpack_u16_swap +#define orc_audio_convert_unpack_s16_le orc_audio_convert_unpack_s16 +#define orc_audio_convert_unpack_s16_be orc_audio_convert_unpack_s16_swap +#define orc_audio_convert_unpack_u32_le orc_audio_convert_unpack_u32 +#define orc_audio_convert_unpack_u32_be orc_audio_convert_unpack_u32_swap +#define orc_audio_convert_unpack_s32_le orc_audio_convert_unpack_s32 +#define orc_audio_convert_unpack_s32_be orc_audio_convert_unpack_s32_swap +#define orc_audio_convert_unpack_float_le orc_audio_convert_unpack_float_s32 +#define orc_audio_convert_unpack_float_be orc_audio_convert_unpack_float_s32_swap +#define orc_audio_convert_unpack_double_le orc_audio_convert_unpack_double_s32 +#define orc_audio_convert_unpack_double_be orc_audio_convert_unpack_double_s32_swap +#define orc_audio_convert_unpack_float_hq_le orc_audio_convert_unpack_float_double +#define orc_audio_convert_unpack_float_hq_be orc_audio_convert_unpack_float_double_swap +#define orc_audio_convert_unpack_double_hq_le orc_audio_convert_unpack_double_double +#define orc_audio_convert_unpack_double_hq_be orc_audio_convert_unpack_double_double_swap +#define orc_audio_convert_unpack_u8_float orc_audio_convert_unpack_u8_double +#define orc_audio_convert_unpack_u16_le_float orc_audio_convert_unpack_u16_double +#define orc_audio_convert_unpack_u16_be_float orc_audio_convert_unpack_u16_double_swap +#define orc_audio_convert_unpack_u32_le_float orc_audio_convert_unpack_u32_double +#define orc_audio_convert_unpack_u32_be_float orc_audio_convert_unpack_u32_double_swap +#define orc_audio_convert_unpack_s8_float orc_audio_convert_unpack_s8_double +#define orc_audio_convert_unpack_s16_le_float orc_audio_convert_unpack_s16_double +#define orc_audio_convert_unpack_s16_be_float orc_audio_convert_unpack_s16_double_swap +#define orc_audio_convert_unpack_s32_le_float orc_audio_convert_unpack_s32_double +#define orc_audio_convert_unpack_s32_be_float orc_audio_convert_unpack_s32_double_swap +#define orc_audio_convert_pack_u8 orc_audio_convert_pack_u8 +#define orc_audio_convert_pack_u16_le orc_audio_convert_pack_u16 +#define orc_audio_convert_pack_u16_be orc_audio_convert_pack_u16_swap +#define orc_audio_convert_pack_s16_le orc_audio_convert_pack_s16 +#define orc_audio_convert_pack_s16_be orc_audio_convert_pack_s16_swap +#define orc_audio_convert_pack_u32_le orc_audio_convert_pack_u32 +#define orc_audio_convert_pack_u32_be orc_audio_convert_pack_u32_swap +#define orc_audio_convert_pack_s32_le orc_audio_convert_pack_s32 +#define orc_audio_convert_pack_s32_be orc_audio_convert_pack_s32_swap +#define orc_audio_convert_pack_float_le orc_audio_convert_pack_s32_float +#define orc_audio_convert_pack_float_be orc_audio_convert_pack_s32_float_swap +#define orc_audio_convert_pack_double_le orc_audio_convert_pack_s32_double +#define orc_audio_convert_pack_double_be orc_audio_convert_pack_s32_double_swap +#define orc_audio_convert_pack_float_hq_le orc_audio_convert_pack_double_float +#define orc_audio_convert_pack_float_hq_be orc_audio_convert_pack_double_float_swap +#define orc_audio_convert_pack_s8_float orc_audio_convert_pack_double_s8 +#define orc_audio_convert_pack_s16_le_float orc_audio_convert_pack_double_s16 +#define orc_audio_convert_pack_s16_be_float orc_audio_convert_pack_double_s16_swap +#define orc_audio_convert_pack_s32_le_float orc_audio_convert_pack_double_s32 +#define orc_audio_convert_pack_s32_be_float orc_audio_convert_pack_double_s32_swap +#define orc_audio_convert_pack_u8_float orc_audio_convert_pack_double_u8 +#define orc_audio_convert_pack_u16_le_float orc_audio_convert_pack_double_u16 +#define orc_audio_convert_pack_u16_be_float orc_audio_convert_pack_double_u16_swap +#define orc_audio_convert_pack_u32_le_float orc_audio_convert_pack_double_u32 +#define orc_audio_convert_pack_u32_be_float orc_audio_convert_pack_double_u32_swap +#else +#define orc_audio_convert_unpack_u16_be orc_audio_convert_unpack_u16 +#define orc_audio_convert_unpack_u16_le orc_audio_convert_unpack_u16_swap +#define orc_audio_convert_unpack_s16_be orc_audio_convert_unpack_s16 +#define orc_audio_convert_unpack_s16_le orc_audio_convert_unpack_s16_swap +#define orc_audio_convert_unpack_u32_be orc_audio_convert_unpack_u32 +#define orc_audio_convert_unpack_u32_le orc_audio_convert_unpack_u32_swap +#define orc_audio_convert_unpack_s32_be orc_audio_convert_unpack_s32 +#define orc_audio_convert_unpack_s32_le orc_audio_convert_unpack_s32_swap +#define orc_audio_convert_unpack_float_be orc_audio_convert_unpack_float_s32 +#define orc_audio_convert_unpack_float_le orc_audio_convert_unpack_float_s32_swap +#define orc_audio_convert_unpack_double_be orc_audio_convert_unpack_double_s32 +#define orc_audio_convert_unpack_double_le orc_audio_convert_unpack_double_s32_swap +#define orc_audio_convert_unpack_float_hq_be orc_audio_convert_unpack_float_double +#define orc_audio_convert_unpack_float_hq_le orc_audio_convert_unpack_float_double_swap +#define orc_audio_convert_unpack_double_hq_be orc_audio_convert_unpack_double_double +#define orc_audio_convert_unpack_double_hq_le orc_audio_convert_unpack_double_double_swap +#define orc_audio_convert_unpack_u8_float orc_audio_convert_unpack_u8_double +#define orc_audio_convert_unpack_u16_be_float orc_audio_convert_unpack_u16_double +#define orc_audio_convert_unpack_u16_le_float orc_audio_convert_unpack_u16_double_swap +#define orc_audio_convert_unpack_u32_be_float orc_audio_convert_unpack_u32_double +#define orc_audio_convert_unpack_u32_le_float orc_audio_convert_unpack_u32_double_swap +#define orc_audio_convert_unpack_s8_float orc_audio_convert_unpack_s8_double +#define orc_audio_convert_unpack_s16_be_float orc_audio_convert_unpack_s16_double +#define orc_audio_convert_unpack_s16_le_float orc_audio_convert_unpack_s16_double_swap +#define orc_audio_convert_unpack_s32_be_float orc_audio_convert_unpack_s32_double +#define orc_audio_convert_unpack_s32_le_float orc_audio_convert_unpack_s32_double_swap +#define orc_audio_convert_pack_u8 orc_audio_convert_pack_u8 +#define orc_audio_convert_pack_u16_be orc_audio_convert_pack_u16 +#define orc_audio_convert_pack_u16_le orc_audio_convert_pack_u16_swap +#define orc_audio_convert_pack_s16_be orc_audio_convert_pack_s16 +#define orc_audio_convert_pack_s16_le orc_audio_convert_pack_s16_swap +#define orc_audio_convert_pack_u32_be orc_audio_convert_pack_u32 +#define orc_audio_convert_pack_u32_le orc_audio_convert_pack_u32_swap +#define orc_audio_convert_pack_s32_be orc_audio_convert_pack_s32 +#define orc_audio_convert_pack_s32_le orc_audio_convert_pack_s32_swap +#define orc_audio_convert_pack_float_be orc_audio_convert_pack_s32_float +#define orc_audio_convert_pack_float_le orc_audio_convert_pack_s32_float_swap +#define orc_audio_convert_pack_double_be orc_audio_convert_pack_s32_double +#define orc_audio_convert_pack_double_le orc_audio_convert_pack_s32_double_swap +#define orc_audio_convert_pack_float_hq_be orc_audio_convert_pack_double_float +#define orc_audio_convert_pack_float_hq_le orc_audio_convert_pack_double_float_swap +#define orc_audio_convert_pack_s8_float orc_audio_convert_pack_double_s8 +#define orc_audio_convert_pack_s16_be_float orc_audio_convert_pack_double_s16 +#define orc_audio_convert_pack_s16_le_float orc_audio_convert_pack_double_s16_swap +#define orc_audio_convert_pack_s32_be_float orc_audio_convert_pack_double_s32 +#define orc_audio_convert_pack_s32_le_float orc_audio_convert_pack_double_s32_swap +#define orc_audio_convert_pack_u8_float orc_audio_convert_pack_double_u8 +#define orc_audio_convert_pack_u16_be_float orc_audio_convert_pack_double_u16 +#define orc_audio_convert_pack_u16_le_float orc_audio_convert_pack_double_u16_swap +#define orc_audio_convert_pack_u32_be_float orc_audio_convert_pack_double_u32 +#define orc_audio_convert_pack_u32_le_float orc_audio_convert_pack_double_u32_swap +#endif + +/* sign bit in the intermediate format */ +#define SIGNED (1U<<31) + +/*** + * unpack code + */ +#define MAKE_UNPACK_FUNC_NAME(name) \ +audio_convert_unpack_##name +#define MAKE_ORC_UNPACK_FUNC_NAME(name) \ +orc_audio_convert_unpack_##name + +/* unpack from integer to signed integer 32 */ +#define MAKE_UNPACK_FUNC_II(name, stride, sign, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst, \ + gint scale, gint count) \ +{ \ + for (;count; count--) { \ + *dst++ = (((gint32) READ_FUNC (src)) << scale) ^ (sign); \ + src+=stride; \ + } \ +} + +/* unpack from integer to signed integer 32 with orc */ +#define MAKE_UNPACK_FUNC_ORC_II(name, stride, sign, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gint32 *dst, \ + gint scale, gint count) \ +{ \ + MAKE_ORC_UNPACK_FUNC_NAME (name) (dst, src, scale, count); \ +} + +/* unpack from float to signed integer 32 */ +#define MAKE_UNPACK_FUNC_FI(name, type, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gint32 * dst, gint s, gint count) \ +{ \ + gdouble temp; \ + \ + for (; count; count--) { \ + /* blow up to 32 bit */ \ + temp = floor ((READ_FUNC (*src++) * 2147483647.0) + 0.5); \ + *dst++ = (gint32) CLAMP (temp, G_MININT32, G_MAXINT32); \ + } \ +} + +/* unpack from float to signed integer 32 with orc */ +#define MAKE_UNPACK_FUNC_ORC_FI(name, type, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gint32 * dst, gint s, gint count) \ +{ \ + MAKE_ORC_UNPACK_FUNC_NAME (name) ((guint32 *) dst, src, count); \ +} + +/* unpack from float to float 64 (double) */ +#define MAKE_UNPACK_FUNC_FF(name, type, FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gdouble * dst, gint s, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = (gdouble) FUNC (*src++); \ +} + +/* unpack from float to float 64 (double) with orc */ +#define MAKE_UNPACK_FUNC_ORC_FF(name, type, FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (type * src, gdouble * dst, gint s, \ + gint count) \ +{ \ + MAKE_ORC_UNPACK_FUNC_NAME (name) ((gdouble *) dst, src, count); \ +} + +/* unpack from int to float 64 (double) */ +#define MAKE_UNPACK_FUNC_IF(name, stride, sign, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (guint8 * src, gdouble * dst, gint scale, \ + gint count) \ +{ \ + gdouble tmp; \ + for (; count; count--) { \ + tmp = (gdouble) ((((gint32) READ_FUNC (src)) << scale) ^ (sign)); \ + *dst++ = tmp * (1.0 / 2147483647.0); \ + src += stride; \ + } \ +} + +#define MAKE_UNPACK_FUNC_ORC_IF(name, stride, sign, READ_FUNC) \ +static void \ +MAKE_UNPACK_FUNC_NAME (name) (guint8 *src, gdouble *dst, \ + gint scale, gint count) \ +{ \ + MAKE_ORC_UNPACK_FUNC_NAME (name) (dst, src, scale, count); \ +} + +#define READ8(p) GST_READ_UINT8(p) +#define READ16_FROM_LE(p) GST_READ_UINT16_LE (p) +#define READ16_FROM_BE(p) GST_READ_UINT16_BE (p) +#define READ24_FROM_LE(p) (p[0] | (p[1] << 8) | (p[2] << 16)) +#define READ24_FROM_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16)) +#define READ32_FROM_LE(p) GST_READ_UINT32_LE (p) +#define READ32_FROM_BE(p) GST_READ_UINT32_BE (p) + + + +MAKE_UNPACK_FUNC_ORC_II (u8, 1, SIGNED, READ8); +MAKE_UNPACK_FUNC_ORC_II (s8, 1, 0, READ8); +MAKE_UNPACK_FUNC_ORC_II (u16_le, 2, SIGNED, READ16_FROM_LE); +MAKE_UNPACK_FUNC_ORC_II (s16_le, 2, 0, READ16_FROM_LE); +MAKE_UNPACK_FUNC_ORC_II (u16_be, 2, SIGNED, READ16_FROM_BE); +MAKE_UNPACK_FUNC_ORC_II (s16_be, 2, 0, READ16_FROM_BE); +MAKE_UNPACK_FUNC_II (u24_le, 3, SIGNED, READ24_FROM_LE); +MAKE_UNPACK_FUNC_II (s24_le, 3, 0, READ24_FROM_LE); +MAKE_UNPACK_FUNC_II (u24_be, 3, SIGNED, READ24_FROM_BE); +MAKE_UNPACK_FUNC_II (s24_be, 3, 0, READ24_FROM_BE); +MAKE_UNPACK_FUNC_ORC_II (u32_le, 4, SIGNED, READ32_FROM_LE); +MAKE_UNPACK_FUNC_ORC_II (s32_le, 4, 0, READ32_FROM_LE); +MAKE_UNPACK_FUNC_ORC_II (u32_be, 4, SIGNED, READ32_FROM_BE); +MAKE_UNPACK_FUNC_ORC_II (s32_be, 4, 0, READ32_FROM_BE); +MAKE_UNPACK_FUNC_ORC_FI (float_le, gfloat, GFLOAT_FROM_LE); +MAKE_UNPACK_FUNC_ORC_FI (float_be, gfloat, GFLOAT_FROM_BE); +MAKE_UNPACK_FUNC_ORC_FI (double_le, gdouble, GDOUBLE_FROM_LE); +MAKE_UNPACK_FUNC_ORC_FI (double_be, gdouble, GDOUBLE_FROM_BE); +MAKE_UNPACK_FUNC_ORC_FF (float_hq_le, gfloat, GFLOAT_FROM_LE); +MAKE_UNPACK_FUNC_ORC_FF (float_hq_be, gfloat, GFLOAT_FROM_BE); +MAKE_UNPACK_FUNC_ORC_FF (double_hq_le, gdouble, GDOUBLE_FROM_LE); +MAKE_UNPACK_FUNC_ORC_FF (double_hq_be, gdouble, GDOUBLE_FROM_BE); +MAKE_UNPACK_FUNC_ORC_IF (u8_float, 1, SIGNED, READ8); +MAKE_UNPACK_FUNC_ORC_IF (s8_float, 1, 0, READ8); +MAKE_UNPACK_FUNC_ORC_IF (u16_le_float, 2, SIGNED, READ16_FROM_LE); +MAKE_UNPACK_FUNC_ORC_IF (s16_le_float, 2, 0, READ16_FROM_LE); +MAKE_UNPACK_FUNC_ORC_IF (u16_be_float, 2, SIGNED, READ16_FROM_BE); +MAKE_UNPACK_FUNC_ORC_IF (s16_be_float, 2, 0, READ16_FROM_BE); +MAKE_UNPACK_FUNC_IF (u24_le_float, 3, SIGNED, READ24_FROM_LE); +MAKE_UNPACK_FUNC_IF (s24_le_float, 3, 0, READ24_FROM_LE); +MAKE_UNPACK_FUNC_IF (u24_be_float, 3, SIGNED, READ24_FROM_BE); +MAKE_UNPACK_FUNC_IF (s24_be_float, 3, 0, READ24_FROM_BE); +MAKE_UNPACK_FUNC_ORC_IF (u32_le_float, 4, SIGNED, READ32_FROM_LE); +MAKE_UNPACK_FUNC_ORC_IF (s32_le_float, 4, 0, READ32_FROM_LE); +MAKE_UNPACK_FUNC_ORC_IF (u32_be_float, 4, SIGNED, READ32_FROM_BE); +MAKE_UNPACK_FUNC_ORC_IF (s32_be_float, 4, 0, READ32_FROM_BE); + +/* One of the double_hq_* functions generated above is ineffecient, but it's + * never used anyway. The same is true for one of the s32_* functions. */ + +/*** + * packing code + */ +#define MAKE_PACK_FUNC_NAME(name) \ +audio_convert_pack_##name +#define MAKE_PACK_FUNC_NAME_ORC(name) \ +orc_audio_convert_pack_##name + +/* + * These functions convert the signed 32 bit integers to the + * target format. For this to work the following steps are done: + * + * 1) If the output format is unsigned we will XOR the sign bit. This + * will do the same as if we add 1<<31. + * 2) Afterwards we shift to the target depth. It's necessary to left-shift + * on signed values here to get arithmetical shifting. + * 3) This is then written into our target array by the corresponding write + * function for the target width. + */ + +/* pack from signed integer 32 to integer using Orc */ +#define MAKE_PACK_FUNC_ORC_II(name, stride, sign, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gint32 *src, guint8 * dst, \ + gint scale, gint count) \ +{ \ + MAKE_PACK_FUNC_NAME_ORC (name) (dst, src, scale, count); \ +} + +/* pack from signed integer 32 to integer */ +#define MAKE_PACK_FUNC_II(name, stride, sign, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gint32 *src, guint8 * dst, \ + gint scale, gint count) \ +{ \ + gint32 tmp; \ + for (;count; count--) { \ + tmp = (*src++ ^ (sign)) >> scale; \ + WRITE_FUNC (dst, tmp); \ + dst += stride; \ + } \ +} + +/* pack from signed integer 32 to float using orc */ +#define MAKE_PACK_FUNC_ORC_IF(name, type, FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gint32 * src, type * dst, gint scale, \ + gint count) \ +{ \ + MAKE_PACK_FUNC_NAME_ORC (name) (dst, src, count); \ +} + +/* pack from signed integer 32 to float */ +#define MAKE_PACK_FUNC_IF(name, type, FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gint32 * src, type * dst, gint scale, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = FUNC ((type) ((*src++) * (1.0 / 2147483647.0))); \ +} + +/* pack from float 64 (double) to float */ +#define MAKE_PACK_FUNC_FF(name, type, FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, type * dst, gint s, \ + gint count) \ +{ \ + for (; count; count--) \ + *dst++ = FUNC ((type) (*src++)); \ +} + +/* pack from float 64 (double) to float with orc */ +#define MAKE_PACK_FUNC_ORC_FF(name, type, FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, type * dst, gint s, \ + gint count) \ +{ \ + MAKE_PACK_FUNC_NAME_ORC (name) (dst, src, count); \ +} + +/* pack from float 64 (double) to signed int. + * the floats are already in the correct range. Only a cast is needed. + */ +#define MAKE_PACK_FUNC_FI_S(name, stride, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale, \ + gint count) \ +{ \ + gint32 tmp; \ + for (; count; count--) { \ + tmp = (gint32) (*src); \ + WRITE_FUNC (dst, tmp); \ + src++; \ + dst += stride; \ + } \ +} + +/* pack from float 64 (double) to unsigned int. + * the floats are already in the correct range. Only a cast is needed + * and an addition of 2^(target_depth-1) to get in the correct unsigned + * range. */ +#define MAKE_PACK_FUNC_FI_U(name, stride, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale, \ + gint count) \ +{ \ + guint32 tmp; \ + gdouble limit = (1U<<(32-scale-1)); \ + for (; count; count--) { \ + tmp = (guint32) (*src + limit); \ + WRITE_FUNC (dst, tmp); \ + src++; \ + dst += stride; \ + } \ +} + +/* pack from float 64 (double) to signed int with orc. + * the floats are already in the correct range. Only a cast is needed. + */ +#define MAKE_PACK_FUNC_ORC_FI_S(name, stride, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale, \ + gint count) \ +{ \ + MAKE_PACK_FUNC_NAME_ORC (name) (dst, src, scale, count); \ +} + +/* pack from float 64 (double) to unsigned int with orc. + * the floats are already in the correct range. Only a cast is needed. + */ +#define MAKE_PACK_FUNC_ORC_FI_U(name, stride, WRITE_FUNC) \ +static void \ +MAKE_PACK_FUNC_NAME (name) (gdouble * src, guint8 * dst, gint scale, \ + gint count) \ +{ \ + MAKE_PACK_FUNC_NAME_ORC (name) (dst, src, scale, count); \ +} + +#define WRITE8(p, v) GST_WRITE_UINT8 (p, v) +#define WRITE16_TO_LE(p,v) GST_WRITE_UINT16_LE (p, (guint16)(v)) +#define WRITE16_TO_BE(p,v) GST_WRITE_UINT16_BE (p, (guint16)(v)) +#define WRITE24_TO_LE(p,v) p[0] = v & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff +#define WRITE24_TO_BE(p,v) p[2] = v & 0xff; p[1] = (v >> 8) & 0xff; p[0] = (v >> 16) & 0xff +#define WRITE32_TO_LE(p,v) GST_WRITE_UINT32_LE (p, (guint32)(v)) +#define WRITE32_TO_BE(p,v) GST_WRITE_UINT32_BE (p, (guint32)(v)) + +MAKE_PACK_FUNC_ORC_II (u8, 1, SIGNED, WRITE8); +MAKE_PACK_FUNC_ORC_II (s8, 1, 0, WRITE8); +MAKE_PACK_FUNC_ORC_II (u16_le, 2, SIGNED, WRITE16_TO_LE); +MAKE_PACK_FUNC_ORC_II (s16_le, 2, 0, WRITE16_TO_LE); +MAKE_PACK_FUNC_ORC_II (u16_be, 2, SIGNED, WRITE16_TO_BE); +MAKE_PACK_FUNC_ORC_II (s16_be, 2, 0, WRITE16_TO_BE); +MAKE_PACK_FUNC_II (u24_le, 3, SIGNED, WRITE24_TO_LE); +MAKE_PACK_FUNC_II (s24_le, 3, 0, WRITE24_TO_LE); +MAKE_PACK_FUNC_II (u24_be, 3, SIGNED, WRITE24_TO_BE); +MAKE_PACK_FUNC_II (s24_be, 3, 0, WRITE24_TO_BE); +MAKE_PACK_FUNC_ORC_II (u32_le, 4, SIGNED, WRITE32_TO_LE); +MAKE_PACK_FUNC_ORC_II (s32_le, 4, 0, WRITE32_TO_LE); +MAKE_PACK_FUNC_ORC_II (u32_be, 4, SIGNED, WRITE32_TO_BE); +MAKE_PACK_FUNC_ORC_II (s32_be, 4, 0, WRITE32_TO_BE); +MAKE_PACK_FUNC_ORC_IF (float_le, gfloat, GFLOAT_TO_LE); +MAKE_PACK_FUNC_ORC_IF (float_be, gfloat, GFLOAT_TO_BE); +MAKE_PACK_FUNC_ORC_IF (double_le, gdouble, GDOUBLE_TO_LE); +MAKE_PACK_FUNC_ORC_IF (double_be, gdouble, GDOUBLE_TO_BE); +MAKE_PACK_FUNC_ORC_FF (float_hq_le, gfloat, GFLOAT_TO_LE); +MAKE_PACK_FUNC_ORC_FF (float_hq_be, gfloat, GFLOAT_TO_BE); +MAKE_PACK_FUNC_ORC_FI_U (u8_float, 1, WRITE8); +MAKE_PACK_FUNC_ORC_FI_S (s8_float, 1, WRITE8); +MAKE_PACK_FUNC_ORC_FI_U (u16_le_float, 2, WRITE16_TO_LE); +MAKE_PACK_FUNC_ORC_FI_S (s16_le_float, 2, WRITE16_TO_LE); +MAKE_PACK_FUNC_ORC_FI_U (u16_be_float, 2, WRITE16_TO_BE); +MAKE_PACK_FUNC_ORC_FI_S (s16_be_float, 2, WRITE16_TO_BE); +MAKE_PACK_FUNC_FI_U (u24_le_float, 3, WRITE24_TO_LE); +MAKE_PACK_FUNC_FI_S (s24_le_float, 3, WRITE24_TO_LE); +MAKE_PACK_FUNC_FI_U (u24_be_float, 3, WRITE24_TO_BE); +MAKE_PACK_FUNC_FI_S (s24_be_float, 3, WRITE24_TO_BE); +MAKE_PACK_FUNC_ORC_FI_U (u32_le_float, 4, WRITE32_TO_LE); +MAKE_PACK_FUNC_ORC_FI_S (s32_le_float, 4, WRITE32_TO_LE); +MAKE_PACK_FUNC_ORC_FI_U (u32_be_float, 4, WRITE32_TO_BE); +MAKE_PACK_FUNC_ORC_FI_S (s32_be_float, 4, WRITE32_TO_BE); + +/* For double_hq, packing and unpacking is the same, so we reuse the unpacking + * functions here. */ +#define audio_convert_pack_double_hq_le MAKE_UNPACK_FUNC_NAME (double_hq_le) +#define audio_convert_pack_double_hq_be MAKE_UNPACK_FUNC_NAME (double_hq_be) + +static AudioConvertUnpack unpack_funcs[] = { + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (float_hq_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_le), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (double_hq_be), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u8_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s8_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u16_be_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s16_be_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u24_be_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s24_be_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_le_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (u32_be_float), + (AudioConvertUnpack) MAKE_UNPACK_FUNC_NAME (s32_be_float), +}; + +static AudioConvertPack pack_funcs[] = { + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (float_hq_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_le), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (double_hq_be), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u8_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s8_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u16_be_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s16_be_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u24_be_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s24_be_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_le_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (u32_be_float), + (AudioConvertPack) MAKE_PACK_FUNC_NAME (s32_be_float), +}; + +#define DOUBLE_INTERMEDIATE_FORMAT(ctx) \ + ((!ctx->in.is_int && !ctx->out.is_int) || (ctx->ns != NOISE_SHAPING_NONE)) + +static gint +audio_convert_get_func_index (AudioConvertCtx * ctx, AudioConvertFmt * fmt) +{ + gint index = 0; + + if (fmt->is_int) { + index += (fmt->width / 8 - 1) * 4; + index += fmt->endianness == G_LITTLE_ENDIAN ? 0 : 2; + index += fmt->sign ? 1 : 0; + index += (ctx->ns == NOISE_SHAPING_NONE) ? 0 : 24; + } else { + /* this is float/double */ + index = 16; + index += (fmt->width == 32) ? 0 : 2; + index += (fmt->endianness == G_LITTLE_ENDIAN) ? 0 : 1; + index += (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? 4 : 0; + } + + return index; +} + +static inline gboolean +check_default (AudioConvertCtx * ctx, AudioConvertFmt * fmt) +{ + if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) { + return (fmt->width == 32 && fmt->depth == 32 && + fmt->endianness == G_BYTE_ORDER && fmt->sign == TRUE); + } else { + return (fmt->width == 64 && fmt->endianness == G_BYTE_ORDER); + } +} + +gboolean +audio_convert_clean_fmt (AudioConvertFmt * fmt) +{ + g_return_val_if_fail (fmt != NULL, FALSE); + + g_free (fmt->pos); + fmt->pos = NULL; + + return TRUE; +} + + +gboolean +audio_convert_prepare_context (AudioConvertCtx * ctx, AudioConvertFmt * in, + AudioConvertFmt * out, GstAudioConvertDithering dither, + GstAudioConvertNoiseShaping ns) +{ + gint idx_in, idx_out; + + g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (in != NULL, FALSE); + g_return_val_if_fail (out != NULL, FALSE); + + /* first clean the existing context */ + audio_convert_clean_context (ctx); + + g_return_val_if_fail (in->unpositioned_layout == out->unpositioned_layout, + FALSE); + + ctx->in = *in; + ctx->out = *out; + + /* Don't dither or apply noise shaping if target depth is bigger than 20 bits + * as DA converters only can do a SNR up to 20 bits in reality. + * Also don't dither or apply noise shaping if target depth is larger than + * source depth. */ + if (ctx->out.depth <= 20 && (!ctx->in.is_int + || ctx->in.depth >= ctx->out.depth)) { + ctx->dither = dither; + ctx->ns = ns; + } else { + ctx->dither = DITHER_NONE; + ctx->ns = NOISE_SHAPING_NONE; + } + + /* Use simple error feedback when output sample rate is smaller than + * 32000 as the other methods might move the noise to audible ranges */ + if (ctx->ns > NOISE_SHAPING_ERROR_FEEDBACK && ctx->out.rate < 32000) + ctx->ns = NOISE_SHAPING_ERROR_FEEDBACK; + + gst_channel_mix_setup_matrix (ctx); + + idx_in = audio_convert_get_func_index (ctx, in); + ctx->unpack = unpack_funcs[idx_in]; + + idx_out = audio_convert_get_func_index (ctx, out); + ctx->pack = pack_funcs[idx_out]; + + /* if both formats are float/double or we use noise shaping use double as + * intermediate format and and switch mixing */ + if (!DOUBLE_INTERMEDIATE_FORMAT (ctx)) { + GST_INFO ("use int mixing"); + ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_int; + } else { + GST_INFO ("use float mixing"); + ctx->channel_mix = (AudioConvertMix) gst_channel_mix_mix_float; + } + GST_INFO ("unitsizes: %d -> %d", in->unit_size, out->unit_size); + + /* check if input is in default format */ + ctx->in_default = check_default (ctx, in); + /* check if channel mixer is passthrough */ + ctx->mix_passthrough = gst_channel_mix_passthrough (ctx); + /* check if output is in default format */ + ctx->out_default = check_default (ctx, out); + + GST_INFO ("in default %d, mix passthrough %d, out default %d", + ctx->in_default, ctx->mix_passthrough, ctx->out_default); + + ctx->in_scale = (in->is_int) ? (32 - in->depth) : 0; + ctx->out_scale = (out->is_int) ? (32 - out->depth) : 0; + + gst_audio_quantize_setup (ctx); + + return TRUE; +} + +gboolean +audio_convert_clean_context (AudioConvertCtx * ctx) +{ + g_return_val_if_fail (ctx != NULL, FALSE); + + gst_audio_quantize_free (ctx); + audio_convert_clean_fmt (&ctx->in); + audio_convert_clean_fmt (&ctx->out); + gst_channel_mix_unset_matrix (ctx); + + g_free (ctx->tmpbuf); + ctx->tmpbuf = NULL; + ctx->tmpbufsize = 0; + + return TRUE; +} + +gboolean +audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, gint * srcsize, + gint * dstsize) +{ + g_return_val_if_fail (ctx != NULL, FALSE); + + if (srcsize) + *srcsize = samples * ctx->in.unit_size; + if (dstsize) + *dstsize = samples * ctx->out.unit_size; + + return TRUE; +} + +gboolean +audio_convert_convert (AudioConvertCtx * ctx, gpointer src, + gpointer dst, gint samples, gboolean src_writable) +{ + guint insize, outsize, size; + gpointer outbuf, tmpbuf; + guint intemp = 0, outtemp = 0, biggest; + + g_return_val_if_fail (ctx != NULL, FALSE); + g_return_val_if_fail (src != NULL, FALSE); + g_return_val_if_fail (dst != NULL, FALSE); + g_return_val_if_fail (samples >= 0, FALSE); + + if (samples == 0) + return TRUE; + + insize = ctx->in.unit_size * samples; + outsize = ctx->out.unit_size * samples; + + /* find biggest temp buffer size */ + size = (DOUBLE_INTERMEDIATE_FORMAT (ctx)) ? sizeof (gdouble) + : sizeof (gint32); + + if (!ctx->in_default) + intemp = gst_util_uint64_scale (insize, size * 8, ctx->in.width); + if (!ctx->mix_passthrough || !ctx->out_default) + outtemp = gst_util_uint64_scale (outsize, size * 8, ctx->out.width); + biggest = MAX (intemp, outtemp); + + /* see if one of the buffers can be used as temp */ + if ((outsize >= biggest) && (ctx->out.unit_size <= size)) + tmpbuf = dst; + else if ((insize >= biggest) && src_writable && (ctx->in.unit_size >= size)) + tmpbuf = src; + else { + if (biggest > ctx->tmpbufsize) { + ctx->tmpbuf = g_realloc (ctx->tmpbuf, biggest); + ctx->tmpbufsize = biggest; + } + tmpbuf = ctx->tmpbuf; + } + + /* start conversion */ + if (!ctx->in_default) { + /* check if final conversion */ + if (!(ctx->out_default && ctx->mix_passthrough)) + outbuf = tmpbuf; + else + outbuf = dst; + + /* unpack to default format */ + ctx->unpack (src, outbuf, ctx->in_scale, samples * ctx->in.channels); + + src = outbuf; + } + + if (!ctx->mix_passthrough) { + /* check if final conversion */ + if (!ctx->out_default) + outbuf = tmpbuf; + else + outbuf = dst; + + /* convert channels */ + ctx->channel_mix (ctx, src, outbuf, samples); + + src = outbuf; + } + + /* we only need to quantize if output format is int */ + if (ctx->out.is_int) { + if (ctx->out_default) + outbuf = dst; + else + outbuf = tmpbuf; + ctx->quantize (ctx, src, outbuf, samples); + } + + if (!ctx->out_default) { + /* pack default format into dst */ + ctx->pack (src, dst, ctx->out_scale, samples * ctx->out.channels); + } + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.h new file mode 100644 index 0000000..ccc4014 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.h @@ -0,0 +1,146 @@ +/* GStreamer + * Copyright (C) 2004 Ronald Bultje + * + * audioconvert.h: audio format conversion library + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __AUDIO_CONVERT_H__ +#define __AUDIO_CONVERT_H__ + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (audio_convert_debug); +#define GST_CAT_DEFAULT (audio_convert_debug) + +/** + * GstAudioConvertDithering: + * @DITHER_NONE: No dithering + * @DITHER_RPDF: Rectangular dithering + * @DITHER_TPDF: Triangular dithering (default) + * @DITHER_TPDF_HF: High frequency triangular dithering + * + * Set of available dithering methods when converting audio. + */ +typedef enum +{ + DITHER_NONE = 0, + DITHER_RPDF, + DITHER_TPDF, + DITHER_TPDF_HF +} GstAudioConvertDithering; + +/** + * GstAudioConvertNoiseShaping: + * @NOISE_SHAPING_NONE: No noise shaping (default) + * @NOISE_SHAPING_ERROR_FEEDBACK: Error feedback + * @NOISE_SHAPING_SIMPLE: Simple 2-pole noise shaping + * @NOISE_SHAPING_MEDIUM: Medium 5-pole noise shaping + * @NOISE_SHAPING_HIGH: High 8-pole noise shaping + * + * Set of available noise shaping methods + */ +typedef enum +{ + NOISE_SHAPING_NONE = 0, + NOISE_SHAPING_ERROR_FEEDBACK, + NOISE_SHAPING_SIMPLE, + NOISE_SHAPING_MEDIUM, + NOISE_SHAPING_HIGH +} GstAudioConvertNoiseShaping; + +typedef struct _AudioConvertCtx AudioConvertCtx; +typedef struct _AudioConvertFmt AudioConvertFmt; + +struct _AudioConvertFmt +{ + /* general caps */ + gboolean is_int; + gint endianness; + gint width; + gint rate; + gint channels; + GstAudioChannelPosition *pos; + gboolean unpositioned_layout; + + /* int audio caps */ + gboolean sign; + gint depth; + + gint unit_size; +}; + +typedef void (*AudioConvertUnpack) (gpointer src, gpointer dst, gint scale, + gint count); +typedef void (*AudioConvertPack) (gpointer src, gpointer dst, gint scale, + gint count); + +typedef void (*AudioConvertMix) (AudioConvertCtx *, gpointer, gpointer, gint); +typedef void (*AudioConvertQuantize) (AudioConvertCtx * ctx, gpointer src, + gpointer dst, gint count); + +struct _AudioConvertCtx +{ + AudioConvertFmt in; + AudioConvertFmt out; + + AudioConvertUnpack unpack; + AudioConvertPack pack; + + /* channel conversion matrix, m[in_channels][out_channels]. + * If identity matrix, passthrough applies. */ + gfloat **matrix; + /* temp storage for channelmix */ + gpointer tmp; + + gboolean in_default; + gboolean mix_passthrough; + gboolean out_default; + + gpointer tmpbuf; + gint tmpbufsize; + + gint in_scale; + gint out_scale; + + AudioConvertMix channel_mix; + + AudioConvertQuantize quantize; + + GstAudioConvertDithering dither; + GstAudioConvertNoiseShaping ns; + /* last random number generated per channel for hifreq TPDF dither */ + gpointer last_random; + /* contains the past quantization errors, error[out_channels][count] */ + gdouble *error_buf; +}; + +gboolean audio_convert_clean_fmt (AudioConvertFmt * fmt); + +gboolean audio_convert_prepare_context (AudioConvertCtx * ctx, + AudioConvertFmt * in, AudioConvertFmt * out, + GstAudioConvertDithering dither, GstAudioConvertNoiseShaping ns); +gboolean audio_convert_get_sizes (AudioConvertCtx * ctx, gint samples, + gint * srcsize, gint * dstsize); + +gboolean audio_convert_clean_context (AudioConvertCtx * ctx); + +gboolean audio_convert_convert (AudioConvertCtx * ctx, gpointer src, + gpointer dst, gint samples, gboolean src_writable); + +#endif /* __AUDIO_CONVERT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.vcproj b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.vcproj new file mode 100644 index 0000000..efa1833 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/audioconvert.vcproj @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/channelmixtest.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/channelmixtest.c new file mode 100644 index 0000000..096a683 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/channelmixtest.c @@ -0,0 +1,95 @@ +/* GStreamer + * Copyright (C) 2005 Benjamin Otte + * + * channelmixtest.c: simple test of channel mixing + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstchannelmix.h" +#include "plugin.h" + +int +main (gint argc, gchar ** argv) +{ + GstElement *bin, *src, *sink; + GstAudioConvert *c; + GstCaps *caps; + guint i, j, k; + struct + { + gchar *sinkcaps; + gchar *srccaps; + gfloat matrix[6][6]; /* use a predefined matrix here, makes stuff simpler */ + } tests[] = { + /* stereo => mono */ + { + "audio/x-raw-int, channels=2", "audio/x-raw-int, channels=1", { { + 0.5,}, { + 0.5,},}}, + /* mono => stereo */ + { + "audio/x-raw-int, channels=1", "audio/x-raw-int, channels=2", { { + 1, 1,},}} + }; + + gst_init (&argc, &argv); + + for (i = 0; i < G_N_ELEMENTS (tests); i++) { + g_print ("running test %u\n", i); + bin = gst_element_factory_make ("pipeline", NULL); + c = g_object_new (GST_TYPE_AUDIO_CONVERT, NULL); + /* avoid gst being braindead */ + gst_object_set_name (GST_OBJECT (c), "shuddup"); + src = gst_element_factory_make ("fakesrc", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + gst_bin_add_many (GST_BIN (bin), src, c, sink, NULL); + caps = gst_caps_from_string (tests[i].sinkcaps); + g_assert (caps); + if (!gst_element_link_filtered (src, GST_ELEMENT (c), caps)) + g_assert_not_reached (); + gst_caps_unref (caps); + caps = gst_caps_from_string (tests[i].srccaps); + g_assert (caps); + if (!gst_element_link_filtered (GST_ELEMENT (c), sink, caps)) + g_assert_not_reached (); + gst_caps_unref (caps); + if (!gst_element_set_state (bin, GST_STATE_PLAYING)) + g_assert_not_reached (); + g_assert (c->srccaps.channels <= 6); + g_assert (c->sinkcaps.channels <= 6); + for (j = 0; j < 6; j++) { + for (k = 0; k < 6; k++) { + if (j < c->sinkcaps.channels && k < c->srccaps.channels) { + if (tests[i].matrix[j][k] != c->matrix[j][k]) { + g_printerr ("matrix[j][k] should be %g but is %g\n", + tests[i].matrix[j][k], c->matrix[j][k]); + g_assert_not_reached (); + } + } else { + g_assert (tests[i].matrix[j][k] == 0); + } + } + } + gst_object_unref (bin); + } + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.c new file mode 100644 index 0000000..2b3445a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.c @@ -0,0 +1,1176 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Wim Taymans + * + * gstaudioconvert.c: Convert audio to different audio formats automatically + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-audioconvert + * + * Audioconvert converts raw audio buffers between various possible formats. + * It supports integer to float conversion, width/depth conversion, + * signedness and endianness conversion and channel transformations. + * + * + * Example launch line + * |[ + * gst-launch -v -m audiotestsrc ! audioconvert ! audio/x-raw-int,channels=2,width=8,depth=8 ! level ! fakesink silent=TRUE + * ]| This pipeline converts audio to 8-bit. The level element shows that + * the output levels still match the one for a sine wave. + * |[ + * gst-launch -v -m audiotestsrc ! audioconvert ! vorbisenc ! fakesink silent=TRUE + * ]| The vorbis encoder takes float audio data instead of the integer data + * generated by audiotestsrc. + * + * + * Last reviewed on 2006-03-02 (0.10.4) + */ + +/* + * design decisions: + * - audioconvert converts buffers in a set of supported caps. If it supports + * a caps, it supports conversion from these caps to any other caps it + * supports. (example: if it does A=>B and A=>C, it also does B=>C) + * - audioconvert does not save state between buffers. Every incoming buffer is + * converted and the converted buffer is pushed out. + * conclusion: + * audioconvert is not supposed to be a one-element-does-anything solution for + * audio conversions. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstaudioconvert.h" +#include "gstchannelmix.h" +#include "gstaudioquantize.h" +#include "plugin.h" + +GST_DEBUG_CATEGORY (audio_convert_debug); +GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); + +/*** DEFINITIONS **************************************************************/ + +/* type functions */ +static void gst_audio_convert_dispose (GObject * obj); + +/* gstreamer functions */ +static gboolean gst_audio_convert_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size); +static GstCaps *gst_audio_convert_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static void gst_audio_convert_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); +static gboolean gst_audio_convert_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_audio_convert_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf); +static GstFlowReturn gst_audio_convert_transform_ip (GstBaseTransform * base, + GstBuffer * buf); +static void gst_audio_convert_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_audio_convert_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static gboolean structure_has_fixed_channel_positions (GstStructure * s, + gboolean * unpositioned_layout); + +/* AudioConvert signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_DITHERING, + ARG_NOISE_SHAPING, +}; + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (audio_convert_debug, "audioconvert", 0, "audio conversion element"); \ + GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); + +GST_BOILERPLATE_FULL (GstAudioConvert, gst_audio_convert, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM, DEBUG_INIT); + +/*** GSTREAMER PROTOTYPES *****************************************************/ + +#define STATIC_CAPS \ +GST_STATIC_CAPS ( \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 64;" \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 32;" \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 32, " \ + "depth = (int) [ 1, 32 ], " \ + "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 24, " \ + "depth = (int) [ 1, 24 ], " "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 16, " \ + "depth = (int) [ 1, 16 ], " \ + "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 8, " \ + "depth = (int) [ 1, 8 ], " \ + "signed = (boolean) { true, false } " \ +) + +static GstStaticPadTemplate gst_audio_convert_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + STATIC_CAPS); + +static GstStaticPadTemplate gst_audio_convert_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + STATIC_CAPS); + +#define GST_TYPE_AUDIO_CONVERT_DITHERING (gst_audio_convert_dithering_get_type ()) +static GType +gst_audio_convert_dithering_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {DITHER_NONE, "No dithering", + "none"}, + {DITHER_RPDF, "Rectangular dithering", "rpdf"}, + {DITHER_TPDF, "Triangular dithering (default)", "tpdf"}, + {DITHER_TPDF_HF, "High frequency triangular dithering", "tpdf-hf"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstAudioConvertDithering", values); + } + return gtype; +} + +#define GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING (gst_audio_convert_ns_get_type ()) +static GType +gst_audio_convert_ns_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {NOISE_SHAPING_NONE, "No noise shaping (default)", + "none"}, + {NOISE_SHAPING_ERROR_FEEDBACK, "Error feedback", "error-feedback"}, + {NOISE_SHAPING_SIMPLE, "Simple 2-pole noise shaping", "simple"}, + {NOISE_SHAPING_MEDIUM, "Medium 5-pole noise shaping", "medium"}, + {NOISE_SHAPING_HIGH, "High 8-pole noise shaping", "high"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstAudioConvertNoiseShaping", values); + } + return gtype; +} + + +/*** TYPE FUNCTIONS ***********************************************************/ + +static void +gst_audio_convert_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_audio_convert_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_audio_convert_sink_template)); + gst_element_class_set_details_simple (element_class, + "Audio converter", "Filter/Converter/Audio", + "Convert audio to different formats", "Benjamin Otte "); +} + +static void +gst_audio_convert_class_init (GstAudioConvertClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseTransformClass *basetransform_class = GST_BASE_TRANSFORM_CLASS (klass); + + gobject_class->dispose = gst_audio_convert_dispose; + gobject_class->set_property = gst_audio_convert_set_property; + gobject_class->get_property = gst_audio_convert_get_property; + + g_object_class_install_property (gobject_class, ARG_DITHERING, + g_param_spec_enum ("dithering", "Dithering", + "Selects between different dithering methods.", + GST_TYPE_AUDIO_CONVERT_DITHERING, DITHER_TPDF, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, ARG_NOISE_SHAPING, + g_param_spec_enum ("noise-shaping", "Noise shaping", + "Selects between different noise shaping methods.", + GST_TYPE_AUDIO_CONVERT_NOISE_SHAPING, NOISE_SHAPING_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + basetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_audio_convert_get_unit_size); + basetransform_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_audio_convert_transform_caps); + basetransform_class->fixate_caps = + GST_DEBUG_FUNCPTR (gst_audio_convert_fixate_caps); + basetransform_class->set_caps = + GST_DEBUG_FUNCPTR (gst_audio_convert_set_caps); + basetransform_class->transform_ip = + GST_DEBUG_FUNCPTR (gst_audio_convert_transform_ip); + basetransform_class->transform = + GST_DEBUG_FUNCPTR (gst_audio_convert_transform); + + basetransform_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_audio_convert_init (GstAudioConvert * this, GstAudioConvertClass * g_class) +{ + this->dither = DITHER_TPDF; + this->ns = NOISE_SHAPING_NONE; + memset (&this->ctx, 0, sizeof (AudioConvertCtx)); + + gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (this), TRUE); +} + +static void +gst_audio_convert_dispose (GObject * obj) +{ + GstAudioConvert *this = GST_AUDIO_CONVERT (obj); + + audio_convert_clean_context (&this->ctx); + + G_OBJECT_CLASS (parent_class)->dispose (obj); +} + +/*** GSTREAMER FUNCTIONS ******************************************************/ + +/* convert the given GstCaps to our format */ +static gboolean +gst_audio_convert_parse_caps (const GstCaps * caps, AudioConvertFmt * fmt) +{ + GstStructure *structure = gst_caps_get_structure (caps, 0); + + GST_DEBUG ("parse caps %p and %" GST_PTR_FORMAT, caps, caps); + + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + g_return_val_if_fail (fmt != NULL, FALSE); + + /* cleanup old */ + audio_convert_clean_fmt (fmt); + + fmt->endianness = G_BYTE_ORDER; + fmt->is_int = + (strcmp (gst_structure_get_name (structure), "audio/x-raw-int") == 0); + + /* parse common fields */ + if (!gst_structure_get_int (structure, "channels", &fmt->channels)) + goto no_values; + if (!(fmt->pos = gst_audio_get_channel_positions (structure))) + goto no_values; + + fmt->unpositioned_layout = FALSE; + structure_has_fixed_channel_positions (structure, &fmt->unpositioned_layout); + + if (!gst_structure_get_int (structure, "width", &fmt->width)) + goto no_values; + if (!gst_structure_get_int (structure, "rate", &fmt->rate)) + goto no_values; + /* width != 8 needs an endianness field */ + if (fmt->width != 8) { + if (!gst_structure_get_int (structure, "endianness", &fmt->endianness)) + goto no_values; + } + + if (fmt->is_int) { + /* int specific fields */ + if (!gst_structure_get_boolean (structure, "signed", &fmt->sign)) + goto no_values; + if (!gst_structure_get_int (structure, "depth", &fmt->depth)) + goto no_values; + + /* depth cannot be bigger than the width */ + if (fmt->depth > fmt->width) + goto not_allowed; + } + + fmt->unit_size = (fmt->width * fmt->channels) / 8; + + return TRUE; + + /* ERRORS */ +no_values: + { + GST_DEBUG ("could not get some values from structure"); + audio_convert_clean_fmt (fmt); + return FALSE; + } +not_allowed: + { + GST_DEBUG ("width > depth, not allowed - make us advertise correct fmt"); + audio_convert_clean_fmt (fmt); + return FALSE; + } +} + +/* BaseTransform vmethods */ +static gboolean +gst_audio_convert_get_unit_size (GstBaseTransform * base, GstCaps * caps, + guint * size) +{ + AudioConvertFmt fmt = { 0 }; + + g_assert (size); + + if (!gst_audio_convert_parse_caps (caps, &fmt)) + goto parse_error; + + GST_INFO_OBJECT (base, "unit_size = %u", fmt.unit_size); + *size = fmt.unit_size; + + audio_convert_clean_fmt (&fmt); + + return TRUE; + +parse_error: + { + GST_INFO_OBJECT (base, "failed to parse caps to get unit_size"); + return FALSE; + } +} + +/* Set widths (a list); multiples of 8 between min and max */ +static void +set_structure_widths (GstStructure * s, int min, int max) +{ + GValue list = { 0 }; + GValue val = { 0 }; + int width; + + if (min == max) { + gst_structure_set (s, "width", G_TYPE_INT, min, NULL); + return; + } + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_INT); + for (width = min; width <= max; width += 8) { + g_value_set_int (&val, width); + gst_value_list_append_value (&list, &val); + } + gst_structure_set_value (s, "width", &list); + g_value_unset (&val); + g_value_unset (&list); +} + +/* Set widths of 32 bits and 64 bits (as list) */ +static void +set_structure_widths_32_and_64 (GstStructure * s) +{ + GValue list = { 0 }; + GValue val = { 0 }; + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_INT); + g_value_set_int (&val, 32); + gst_value_list_append_value (&list, &val); + g_value_set_int (&val, 64); + gst_value_list_append_value (&list, &val); + gst_structure_set_value (s, "width", &list); + g_value_unset (&val); + g_value_unset (&list); +} + +/* Modify the structure so that things that must always have a single + * value (for float), or can always be losslessly converted (for int), have + * appropriate values. + */ +static GstStructure * +make_lossless_changes (GstStructure * s, gboolean isfloat) +{ + GValue list = { 0 }; + GValue val = { 0 }; + int i; + const gint endian[] = { G_LITTLE_ENDIAN, G_BIG_ENDIAN }; + const gboolean booleans[] = { TRUE, FALSE }; + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_INT); + for (i = 0; i < 2; i++) { + g_value_set_int (&val, endian[i]); + gst_value_list_append_value (&list, &val); + } + gst_structure_set_value (s, "endianness", &list); + g_value_unset (&val); + g_value_unset (&list); + + if (isfloat) { + /* float doesn't have a depth or signedness field and only supports + * widths of 32 and 64 bits */ + gst_structure_remove_field (s, "depth"); + gst_structure_remove_field (s, "signed"); + set_structure_widths_32_and_64 (s); + } else { + /* int supports signed and unsigned. GValues are a pain */ + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&val, G_TYPE_BOOLEAN); + for (i = 0; i < 2; i++) { + g_value_set_boolean (&val, booleans[i]); + gst_value_list_append_value (&list, &val); + } + gst_structure_set_value (s, "signed", &list); + g_value_unset (&val); + g_value_unset (&list); + } + + return s; +} + +static void +strip_width_64 (GstStructure * s) +{ + const GValue *v = gst_structure_get_value (s, "width"); + GValue widths = { 0 }; + + if (GST_VALUE_HOLDS_LIST (v)) { + int i; + int len = gst_value_list_get_size (v); + + g_value_init (&widths, GST_TYPE_LIST); + + for (i = 0; i < len; i++) { + const GValue *width = gst_value_list_get_value (v, i); + + if (g_value_get_int (width) != 64) + gst_value_list_append_value (&widths, width); + } + gst_structure_set_value (s, "width", &widths); + g_value_unset (&widths); + } +} + +/* Little utility function to create a related structure for float/int */ +static void +append_with_other_format (GstCaps * caps, GstStructure * s, gboolean isfloat) +{ + GstStructure *s2; + + if (isfloat) { + s2 = gst_structure_copy (s); + gst_structure_set_name (s2, "audio/x-raw-int"); + s = make_lossless_changes (s2, FALSE); + /* If 64 bit float was allowed; remove width 64: we don't support it for + * integer*/ + strip_width_64 (s); + gst_caps_append_structure (caps, s2); + } else { + s2 = gst_structure_copy (s); + gst_structure_set_name (s2, "audio/x-raw-float"); + s = make_lossless_changes (s2, TRUE); + gst_caps_append_structure (caps, s2); + } +} + +static gboolean +structure_has_fixed_channel_positions (GstStructure * s, + gboolean * unpositioned_layout) +{ + GstAudioChannelPosition *pos; + const GValue *val; + gint channels = 0; + + if (!gst_structure_get_int (s, "channels", &channels)) + return FALSE; /* probably a range */ + + val = gst_structure_get_value (s, "channel-positions"); + if ((val == NULL || !gst_value_is_fixed (val)) && channels <= 8) { + GST_LOG ("no or unfixed channel-positions in %" GST_PTR_FORMAT, s); + return FALSE; + } else if (val == NULL || !gst_value_is_fixed (val)) { + GST_LOG ("implicit undefined channel-positions"); + *unpositioned_layout = TRUE; + return TRUE; + } + + pos = gst_audio_get_channel_positions (s); + if (pos && pos[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { + GST_LOG ("fixed undefined channel-positions in %" GST_PTR_FORMAT, s); + *unpositioned_layout = TRUE; + } else { + GST_LOG ("fixed defined channel-positions in %" GST_PTR_FORMAT, s); + *unpositioned_layout = FALSE; + } + g_free (pos); + + return TRUE; +} + +/* Audioconvert can perform all conversions on audio except for resampling. + * However, there are some conversions we _prefer_ not to do. For example, it's + * better to convert format (float<->int, endianness, etc) than the number of + * channels, as the latter conversion is not lossless. + * + * So, we return, in order (assuming input caps have only one structure; + * which is enforced by basetransform): + * - input caps with a different format (lossless conversions). + * - input caps with a different format (slightly lossy conversions). + * - input caps with a different number of channels (very lossy!) + */ +static GstCaps * +gst_audio_convert_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) +{ + GstCaps *ret; + GstStructure *s, *structure; + gboolean isfloat, allow_mixing; + gint width, depth, channels = 0; + const gchar *fields_used[] = { + "width", "depth", "rate", "channels", "endianness", "signed" + }; + const gchar *structure_name; + int i; + + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL); + + structure = gst_caps_get_structure (caps, 0); + structure_name = gst_structure_get_name (structure); + + isfloat = strcmp (structure_name, "audio/x-raw-float") == 0; + + /* We operate on a version of the original structure with any additional + * fields absent */ + s = gst_structure_empty_new (structure_name); + for (i = 0; i < sizeof (fields_used) / sizeof (*fields_used); i++) { + if (gst_structure_has_field (structure, fields_used[i])) + gst_structure_set_value (s, fields_used[i], + gst_structure_get_value (structure, fields_used[i])); + } + + if (!isfloat) { + /* Commonly, depth is left out: set it equal to width if we have a fixed + * width, if so */ + if (!gst_structure_has_field (s, "depth") && + gst_structure_get_int (s, "width", &width)) + gst_structure_set (s, "depth", G_TYPE_INT, width, NULL); + } + + ret = gst_caps_new_empty (); + + /* All lossless conversions */ + s = make_lossless_changes (s, isfloat); + gst_caps_append_structure (ret, s); + + /* Same, plus a float<->int conversion */ + append_with_other_format (ret, s, isfloat); + GST_DEBUG_OBJECT (base, " step1: (%d) %" GST_PTR_FORMAT, + gst_caps_get_size (ret), ret); + + /* We don't mind increasing width/depth/channels, but reducing them is + * Very Bad. Only available if width, depth, channels are already fixed. */ + s = gst_structure_copy (s); + if (!isfloat) { + if (gst_structure_get_int (structure, "width", &width)) + set_structure_widths (s, width, 32); + if (gst_structure_get_int (structure, "depth", &depth)) { + if (depth == 32) + gst_structure_set (s, "depth", G_TYPE_INT, 32, NULL); + else + gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, depth, 32, NULL); + } + } + + allow_mixing = TRUE; + if (gst_structure_get_int (structure, "channels", &channels)) { + gboolean unpositioned; + + /* we don't support mixing for channels without channel positions */ + if (structure_has_fixed_channel_positions (structure, &unpositioned)) + allow_mixing = (unpositioned == FALSE); + } + + if (!allow_mixing) { + gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL); + if (gst_structure_has_field (structure, "channel-positions")) + gst_structure_set_value (s, "channel-positions", + gst_structure_get_value (structure, "channel-positions")); + } else { + if (channels == 0) + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL); + else if (channels == 11) + gst_structure_set (s, "channels", G_TYPE_INT, 11, NULL); + else + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, channels, 11, NULL); + gst_structure_remove_field (s, "channel-positions"); + } + gst_caps_append_structure (ret, s); + + /* Same, plus a float<->int conversion */ + append_with_other_format (ret, s, isfloat); + + /* We'll reduce depth if we must. We reduce as low as 16 bits (for integer); + * reducing to less than this is even worse than dropping channels. We only + * do this if we haven't already done the equivalent above. */ + if (!gst_structure_get_int (structure, "width", &width) || width > 16) { + if (isfloat) { + GstStructure *s2 = gst_structure_copy (s); + + set_structure_widths_32_and_64 (s2); + append_with_other_format (ret, s2, TRUE); + gst_structure_free (s2); + } else { + s = gst_structure_copy (s); + set_structure_widths (s, 16, 32); + gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, 16, 32, NULL); + gst_caps_append_structure (ret, s); + } + } + + /* Channel conversions to fewer channels is only done if needed - generally + * it's very bad to drop channels entirely. + */ + s = gst_structure_copy (s); + if (allow_mixing) { + gst_structure_set (s, "channels", GST_TYPE_INT_RANGE, 1, 11, NULL); + gst_structure_remove_field (s, "channel-positions"); + } else { + /* allow_mixing can only be FALSE if we got a fixed number of channels */ + gst_structure_set (s, "channels", G_TYPE_INT, channels, NULL); + if (gst_structure_has_field (structure, "channel-positions")) + gst_structure_set_value (s, "channel-positions", + gst_structure_get_value (structure, "channel-positions")); + } + gst_caps_append_structure (ret, s); + + /* Same, plus a float<->int conversion */ + append_with_other_format (ret, s, isfloat); + + /* And, finally, for integer only, we allow conversion to any width/depth we + * support: this should be equivalent to our (non-float) template caps. (the + * floating point case should be being handled just above) */ + s = gst_structure_copy (s); + set_structure_widths (s, 8, 32); + gst_structure_set (s, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL); + + if (isfloat) { + append_with_other_format (ret, s, TRUE); + gst_structure_free (s); + } else + gst_caps_append_structure (ret, s); + + GST_DEBUG_OBJECT (base, "Caps transformed to %" GST_PTR_FORMAT, ret); + + return ret; +} + +static const GstAudioChannelPosition default_positions[8][8] = { + /* 1 channel */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + }, + /* 2 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + }, + /* 3 channels (2.1) */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, /* or FRONT_CENTER for 3.0? */ + }, + /* 4 channels (4.0 or 3.1?) */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + /* 5 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + }, + /* 6 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + }, + /* 7 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + }, + /* 8 channels */ + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + } +}; + +static const GValue * +find_suitable_channel_layout (const GValue * val, guint chans) +{ + /* if output layout is fixed already and looks sane, we're done */ + if (GST_VALUE_HOLDS_ARRAY (val) && gst_value_array_get_size (val) == chans) + return val; + + /* if it's a list, go through it recursively and return the first + * sane-enough looking value we find */ + if (GST_VALUE_HOLDS_LIST (val)) { + gint i; + + for (i = 0; i < gst_value_list_get_size (val); ++i) { + const GValue *v, *ret; + + v = gst_value_list_get_value (val, i); + if ((ret = find_suitable_channel_layout (v, chans))) + return ret; + } + } + + return NULL; +} + +static void +gst_audio_convert_fixate_channels (GstBaseTransform * base, GstStructure * ins, + GstStructure * outs) +{ + const GValue *in_layout, *out_layout; + gint in_chans, out_chans; + + if (!gst_structure_get_int (ins, "channels", &in_chans)) + return; /* this shouldn't really happen, should it? */ + + if (!gst_structure_has_field (outs, "channels")) { + /* we could try to get the implied number of channels from the layout, + * but that seems overdoing it for a somewhat exotic corner case */ + gst_structure_remove_field (outs, "channel-positions"); + return; + } + + /* ok, let's fixate the channels if they are not fixated yet */ + gst_structure_fixate_field_nearest_int (outs, "channels", in_chans); + + if (!gst_structure_get_int (outs, "channels", &out_chans)) { + /* shouldn't really happen ... */ + gst_structure_remove_field (outs, "channel-positions"); + return; + } + + /* check if the output has a channel layout (or a list of layouts) */ + out_layout = gst_structure_get_value (outs, "channel-positions"); + + /* get the channel layout of the input if any */ + in_layout = gst_structure_get_value (ins, "channel-positions"); + + if (out_layout == NULL) { + if (out_chans <= 2 && (in_chans != out_chans || in_layout == NULL)) + return; /* nothing to do, default layout will be assumed */ + GST_WARNING_OBJECT (base, "downstream caps contain no channel layout"); + } + + if (in_chans == out_chans && in_layout != NULL) { + GValue res = { 0, }; + + /* same number of channels and no output layout: just use input layout */ + if (out_layout == NULL) { + gst_structure_set_value (outs, "channel-positions", in_layout); + return; + } + + /* if output layout is fixed already and looks sane, we're done */ + if (GST_VALUE_HOLDS_ARRAY (out_layout) && + gst_value_array_get_size (out_layout) == out_chans) { + return; + } + + /* if the output layout is not fixed, check if the output layout contains + * the input layout */ + if (gst_value_intersect (&res, in_layout, out_layout)) { + gst_structure_set_value (outs, "channel-positions", in_layout); + g_value_unset (&res); + return; + } + + /* output layout is not fixed and does not contain the input layout, so + * just pick the first layout in the list (it should be a list ...) */ + if ((out_layout = find_suitable_channel_layout (out_layout, out_chans))) { + gst_structure_set_value (outs, "channel-positions", out_layout); + return; + } + + /* ... else fall back to default layout (NB: out_layout is NULL here) */ + GST_WARNING_OBJECT (base, "unexpected output channel layout"); + } + + /* number of input channels != number of output channels: + * if this value contains a list of channel layouts (or even worse: a list + * with another list), just pick the first value and repeat until we find a + * channel position array or something else that's not a list; we assume + * the input if half-way sane and don't try to fall back on other list items + * if the first one is something unexpected or non-channel-pos-array-y */ + if (out_layout != NULL && GST_VALUE_HOLDS_LIST (out_layout)) + out_layout = find_suitable_channel_layout (out_layout, out_chans); + + if (out_layout != NULL) { + if (GST_VALUE_HOLDS_ARRAY (out_layout) && + gst_value_array_get_size (out_layout) == out_chans) { + /* looks sane enough, let's use it */ + gst_structure_set_value (outs, "channel-positions", out_layout); + return; + } + + /* what now?! Just ignore what we're given and use default positions */ + GST_WARNING_OBJECT (base, "invalid or unexpected channel-positions"); + } + + /* missing or invalid output layout and we can't use the input layout for + * one reason or another, so just pick a default layout (we could be smarter + * and try to add/remove channels from the input layout, or pick a default + * layout based on LFE-presence in input layout, but let's save that for + * another day) */ + if (out_chans > 0 && out_chans <= G_N_ELEMENTS (default_positions[0])) { + GST_DEBUG_OBJECT (base, "using default channel layout as fallback"); + gst_audio_set_channel_positions (outs, default_positions[out_chans - 1]); + } +} + +/* try to keep as many of the structure members the same by fixating the + * possible ranges; this way we convert the least amount of things as possible + */ +static void +gst_audio_convert_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstStructure *ins, *outs; + gint rate, endianness, depth, width; + gboolean signedness; + + g_return_if_fail (gst_caps_is_fixed (caps)); + + GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT + " based on caps %" GST_PTR_FORMAT, othercaps, caps); + + ins = gst_caps_get_structure (caps, 0); + outs = gst_caps_get_structure (othercaps, 0); + + gst_audio_convert_fixate_channels (base, ins, outs); + + if (gst_structure_get_int (ins, "rate", &rate)) { + if (gst_structure_has_field (outs, "rate")) { + gst_structure_fixate_field_nearest_int (outs, "rate", rate); + } + } + if (gst_structure_get_int (ins, "endianness", &endianness)) { + if (gst_structure_has_field (outs, "endianness")) { + gst_structure_fixate_field_nearest_int (outs, "endianness", endianness); + } + } + if (gst_structure_get_int (ins, "width", &width)) { + if (gst_structure_has_field (outs, "width")) { + gst_structure_fixate_field_nearest_int (outs, "width", width); + } + } else { + /* this is not allowed */ + } + + if (gst_structure_get_int (ins, "depth", &depth)) { + if (gst_structure_has_field (outs, "depth")) { + gst_structure_fixate_field_nearest_int (outs, "depth", depth); + } + } else { + /* set depth as width */ + if (gst_structure_has_field (outs, "depth")) { + gst_structure_fixate_field_nearest_int (outs, "depth", width); + } + } + + if (gst_structure_get_boolean (ins, "signed", &signedness)) { + if (gst_structure_has_field (outs, "signed")) { + gst_structure_fixate_field_boolean (outs, "signed", signedness); + } + } + + GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); +} + +static gboolean +gst_audio_convert_set_caps (GstBaseTransform * base, GstCaps * incaps, + GstCaps * outcaps) +{ + AudioConvertFmt in_ac_caps = { 0 }; + AudioConvertFmt out_ac_caps = { 0 }; + GstAudioConvert *this = GST_AUDIO_CONVERT (base); + + GST_DEBUG_OBJECT (base, "incaps %" GST_PTR_FORMAT ", outcaps %" + GST_PTR_FORMAT, incaps, outcaps); + + if (!gst_audio_convert_parse_caps (incaps, &in_ac_caps)) + return FALSE; + if (!gst_audio_convert_parse_caps (outcaps, &out_ac_caps)) + return FALSE; + + if (!audio_convert_prepare_context (&this->ctx, &in_ac_caps, &out_ac_caps, + this->dither, this->ns)) + goto no_converter; + + return TRUE; + +no_converter: + { + return FALSE; + } +} + +static GstFlowReturn +gst_audio_convert_transform_ip (GstBaseTransform * base, GstBuffer * buf) +{ + /* nothing to do here */ + return GST_FLOW_OK; +} + +static void +gst_audio_convert_create_silence_buffer (GstAudioConvert * this, gpointer dst, + gint size) +{ + if (this->ctx.out.is_int && !this->ctx.out.sign) { + gint i; + + switch (this->ctx.out.width) { + case 8:{ + guint8 zero = 0x80 >> (8 - this->ctx.out.depth); + + memset (dst, zero, size); + break; + } + case 16:{ + guint16 *data = (guint16 *) dst; + guint16 zero = 0x8000 >> (16 - this->ctx.out.depth); + + if (this->ctx.out.endianness == G_LITTLE_ENDIAN) + zero = GUINT16_TO_LE (zero); + else + zero = GUINT16_TO_BE (zero); + + size /= 2; + + for (i = 0; i < size; i++) + data[i] = zero; + break; + } + case 24:{ + guint32 zero = 0x800000 >> (24 - this->ctx.out.depth); + guint8 *data = (guint8 *) dst; + + if (this->ctx.out.endianness == G_LITTLE_ENDIAN) { + for (i = 0; i < size; i += 3) { + data[i] = zero & 0xff; + data[i + 1] = (zero >> 8) & 0xff; + data[i + 2] = (zero >> 16) & 0xff; + } + } else { + for (i = 0; i < size; i += 3) { + data[i + 2] = zero & 0xff; + data[i + 1] = (zero >> 8) & 0xff; + data[i] = (zero >> 16) & 0xff; + } + } + break; + } + case 32:{ + guint32 *data = (guint32 *) dst; + guint32 zero = (0x80000000 >> (32 - this->ctx.out.depth)); + + if (this->ctx.out.endianness == G_LITTLE_ENDIAN) + zero = GUINT32_TO_LE (zero); + else + zero = GUINT32_TO_BE (zero); + + size /= 4; + + for (i = 0; i < size; i++) + data[i] = zero; + break; + } + default: + memset (dst, 0, size); + g_return_if_reached (); + break; + } + } else { + memset (dst, 0, size); + } +} + +static GstFlowReturn +gst_audio_convert_transform (GstBaseTransform * base, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstAudioConvert *this = GST_AUDIO_CONVERT (base); + gint insize, outsize; + gint samples; + gpointer src, dst; + + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, base, "converting audio from %" + GST_PTR_FORMAT " to %" GST_PTR_FORMAT, GST_BUFFER_CAPS (inbuf), + GST_BUFFER_CAPS (outbuf)); + + /* get amount of samples to convert. */ + samples = GST_BUFFER_SIZE (inbuf) / this->ctx.in.unit_size; + + /* get in/output sizes, to see if the buffers we got are of correct + * sizes */ + if (!audio_convert_get_sizes (&this->ctx, samples, &insize, &outsize)) + goto error; + + if (insize == 0 || outsize == 0) + return GST_FLOW_OK; + + /* check in and outsize */ + if (GST_BUFFER_SIZE (inbuf) < insize) + goto wrong_size; + if (GST_BUFFER_SIZE (outbuf) < outsize) + goto wrong_size; + + /* get src and dst data */ + src = GST_BUFFER_DATA (inbuf); + dst = GST_BUFFER_DATA (outbuf); + + /* and convert the samples */ + if (!GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { + if (!audio_convert_convert (&this->ctx, src, dst, + samples, gst_buffer_is_writable (inbuf))) + goto convert_error; + } else { + /* Create silence buffer */ + gst_audio_convert_create_silence_buffer (this, dst, outsize); + } + + GST_BUFFER_SIZE (outbuf) = outsize; + + return GST_FLOW_OK; + + /* ERRORS */ +error: + { + GST_ELEMENT_ERROR (this, STREAM, FORMAT, + (NULL), ("cannot get input/output sizes for %d samples", samples)); + return GST_FLOW_ERROR; + } +wrong_size: + { + GST_ELEMENT_ERROR (this, STREAM, FORMAT, + (NULL), + ("input/output buffers are of wrong size in: %d < %d or out: %d < %d", + GST_BUFFER_SIZE (inbuf), insize, GST_BUFFER_SIZE (outbuf), + outsize)); + return GST_FLOW_ERROR; + } +convert_error: + { + GST_ELEMENT_ERROR (this, STREAM, FORMAT, + (NULL), ("error while converting")); + return GST_FLOW_ERROR; + } +} + +static void +gst_audio_convert_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAudioConvert *this = GST_AUDIO_CONVERT (object); + + switch (prop_id) { + case ARG_DITHERING: + this->dither = g_value_get_enum (value); + break; + case ARG_NOISE_SHAPING: + this->ns = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_audio_convert_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAudioConvert *this = GST_AUDIO_CONVERT (object); + + switch (prop_id) { + case ARG_DITHERING: + g_value_set_enum (value, this->dither); + break; + case ARG_NOISE_SHAPING: + g_value_set_enum (value, this->ns); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.h new file mode 100644 index 0000000..9370d38 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvert.h @@ -0,0 +1,60 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * + * gstaudioconvert.h: Convert audio to different audio formats automatically + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_CONVERT_H__ +#define __GST_AUDIO_CONVERT_H__ + +#include +#include +#include + +#include "audioconvert.h" + +#define GST_TYPE_AUDIO_CONVERT (gst_audio_convert_get_type()) +#define GST_AUDIO_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_CONVERT,GstAudioConvert)) +#define GST_AUDIO_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_CONVERT,GstAudioConvertClass)) +#define GST_IS_AUDIO_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_CONVERT)) +#define GST_IS_AUDIO_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_CONVERT)) + +typedef struct _GstAudioConvert GstAudioConvert; +typedef struct _GstAudioConvertClass GstAudioConvertClass; + +/** + * GstAudioConvert: + * + * The audioconvert object structure. + */ +struct _GstAudioConvert +{ + GstBaseTransform element; + + AudioConvertCtx ctx; + + GstAudioConvertDithering dither; + GstAudioConvertNoiseShaping ns; +}; + +struct _GstAudioConvertClass +{ + GstBaseTransformClass parent_class; +}; + +#endif /* __GST_AUDIO_CONVERT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.c new file mode 100644 index 0000000..4bf8e55 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.c @@ -0,0 +1,6828 @@ + +/* autogenerated from gstaudioconvertorc.orc */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 + +#ifndef DISABLE_ORC +#include +#endif +void orc_audio_convert_unpack_u8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_float_s32 (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_s32_swap (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_s32 (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_s32_swap (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_double (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_double_swap (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_double (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_double_swap (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_u8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32_float (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_float_swap (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_double (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_float (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_float_swap (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_u8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n); + +void gst_audio_convert_orc_init (void); + + +/* begin Orc C target preamble */ +#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x))) +#define ORC_ABS(a) ((a)<0 ? -(a) : (a)) +#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define ORC_SB_MAX 127 +#define ORC_SB_MIN (-1-ORC_SB_MAX) +#define ORC_UB_MAX 255 +#define ORC_UB_MIN 0 +#define ORC_SW_MAX 32767 +#define ORC_SW_MIN (-1-ORC_SW_MAX) +#define ORC_UW_MAX 65535 +#define ORC_UW_MIN 0 +#define ORC_SL_MAX 2147483647 +#define ORC_SL_MIN (-1-ORC_SL_MAX) +#define ORC_UL_MAX 4294967295U +#define ORC_UL_MIN 0 +#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX) +#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX) +#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX) +#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX) +#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX) +#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) +#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) +#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) +#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#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 +#define ORC_RESTRICT __restrict__ +#else +#define ORC_RESTRICT +#endif +#endif +/* end Orc C target preamble */ + + + +/* orc_audio_convert_unpack_u8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union32 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_int8 *) s1; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var37.i = (orc_uint8) var34; + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << p1; + /* 5: xorl */ + var36.i = var39.i ^ var35.i; + /* 6: storel */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union32 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var37.i = (orc_uint8) var34; + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << ex->params[24]; + /* 5: xorl */ + var36.i = var39.i ^ var35.i; + /* 6: storel */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u8; +void +orc_audio_convert_unpack_u8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var36.i = (orc_uint8) var34; + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var35.i = var37.i << p1; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var36.i = (orc_uint8) var34; + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var35.i = var37.i << ex->params[24]; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s8; +void +orc_audio_convert_unpack_s8 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union16 *) s1; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var36.i = (orc_uint16) var33.i; + /* 2: shll */ + var37.i = var36.i << p1; + /* 4: xorl */ + var35.i = var37.i ^ var34.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var36.i = (orc_uint16) var33.i; + /* 2: shll */ + var37.i = var36.i << ex->params[24]; + /* 4: xorl */ + var35.i = var37.i ^ var34.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u16; +void +orc_audio_convert_unpack_u16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var35.i = (orc_uint16) var33.i; + /* 2: shll */ + var34.i = var35.i << p1; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var35.i = (orc_uint16) var33.i; + /* 2: shll */ + var34.i = var35.i << ex->params[24]; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s16; +void +orc_audio_convert_unpack_s16 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union32 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union16 *) s1; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var37.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << p1; + /* 5: xorl */ + var36.i = var39.i ^ var35.i; + /* 6: storel */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union32 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var37.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << ex->params[24]; + /* 5: xorl */ + var36.i = var39.i ^ var35.i; + /* 6: storel */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u16_swap; +void +orc_audio_convert_unpack_u16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var36.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var35.i = var37.i << p1; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var36.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var35.i = var37.i << ex->params[24]; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s16_swap; +void +orc_audio_convert_unpack_s16_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var36.i = var33.i << p1; + /* 3: xorl */ + var35.i = var36.i ^ var34.i; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var36.i = var33.i << ex->params[24]; + /* 3: xorl */ + var35.i = var36.i ^ var34.i; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u32; +void +orc_audio_convert_unpack_u32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: shll */ + var33.i = var32.i << p1; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: shll */ + var33.i = var32.i << ex->params[24]; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s32; +void +orc_audio_convert_unpack_s32 (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var36.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var37.i = var36.i << p1; + /* 4: xorl */ + var35.i = var37.i ^ var34.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var36.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var37.i = var36.i << ex->params[24]; + /* 4: xorl */ + var35.i = var37.i ^ var34.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u32_swap; +void +orc_audio_convert_unpack_u32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var34.i = var35.i << p1; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var34.i = var35.i << ex->params[24]; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s32_swap; +void +orc_audio_convert_unpack_s32_swap (gint32 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_float_s32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_float_s32 (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var33.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + /* 3: loadpl */ + var34.i = (int) 0x3f000000; /* 1056964608 or 5.2221e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var36 = ptr4[i]; + /* 2: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var36.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL (_dest1.i); + } + /* 4: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var37.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f + _src2.f; + var38.i = ORC_DENORMAL (_dest1.i); + } + /* 5: convfl */ + { + int tmp; + tmp = (int) var38.f; + if (tmp == 0x80000000 && !(var38.i & 0x80000000)) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 6: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_float_s32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var33.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + /* 3: loadpl */ + var34.i = (int) 0x3f000000; /* 1056964608 or 5.2221e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var36 = ptr4[i]; + /* 2: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var36.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL (_dest1.i); + } + /* 4: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var37.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f + _src2.f; + var38.i = ORC_DENORMAL (_dest1.i); + } + /* 5: convfl */ + { + int tmp; + tmp = (int) var38.f; + if (tmp == 0x80000000 && !(var38.i & 0x80000000)) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 6: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_float_s32; +void +orc_audio_convert_unpack_float_s32 (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_float_s32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_float_s32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_float_s32_swap (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + /* 4: loadpl */ + var35.i = (int) 0x3f000000; /* 1056964608 or 5.2221e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var37.i = ORC_SWAP_L (var33.i); + /* 3: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var37.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f * _src2.f; + var38.i = ORC_DENORMAL (_dest1.i); + } + /* 5: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var38.i); + _src2.i = ORC_DENORMAL (var35.i); + _dest1.f = _src1.f + _src2.f; + var39.i = ORC_DENORMAL (_dest1.i); + } + /* 6: convfl */ + { + int tmp; + tmp = (int) var39.f; + if (tmp == 0x80000000 && !(var39.i & 0x80000000)) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 7: storel */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_float_s32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + /* 4: loadpl */ + var35.i = (int) 0x3f000000; /* 1056964608 or 5.2221e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var37.i = ORC_SWAP_L (var33.i); + /* 3: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var37.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f * _src2.f; + var38.i = ORC_DENORMAL (_dest1.i); + } + /* 5: addf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var38.i); + _src2.i = ORC_DENORMAL (var35.i); + _dest1.f = _src1.f + _src2.f; + var39.i = ORC_DENORMAL (_dest1.i); + } + /* 6: convfl */ + { + int tmp; + tmp = (int) var39.f; + if (tmp == 0x80000000 && !(var39.i & 0x80000000)) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 7: storel */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_float_s32_swap; +void +orc_audio_convert_unpack_float_s32_swap (guint32 * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_float_s32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_double_s32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_double_s32 (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union64 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + orc_union64 var38; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 1: loadpq */ + var33.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + /* 3: loadpq */ + var34.i = ORC_UINT64_C (0x3fe0000000000000); /* 0.5f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var36 = ptr4[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: addd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var37.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f + _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 5: convdl */ + { + int tmp; + tmp = var38.f; + if (tmp == 0x80000000 && !(var38.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 6: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_double_s32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union64 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + orc_union64 var38; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 1: loadpq */ + var33.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + /* 3: loadpq */ + var34.i = ORC_UINT64_C (0x3fe0000000000000); /* 0.5f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var36 = ptr4[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: addd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var37.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f + _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 5: convdl */ + { + int tmp; + tmp = var38.f; + if (tmp == 0x80000000 && !(var38.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 6: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_double_s32; +void +orc_audio_convert_unpack_double_s32 (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_double_s32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_double_s32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_double_s32_swap (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union64 var34; + orc_union64 var35; + orc_union32 var36; + orc_union64 var37; + orc_union64 var38; + orc_union64 var39; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + /* 4: loadpq */ + var35.i = ORC_UINT64_C (0x3fe0000000000000); /* 0.5f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: swapq */ + var37.i = ORC_SWAP_Q (var33.i); + /* 3: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var37.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f * _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 5: addd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var38.i); + _src2.i = ORC_DENORMAL_DOUBLE (var35.i); + _dest1.f = _src1.f + _src2.f; + var39.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 6: convdl */ + { + int tmp; + tmp = var39.f; + if (tmp == 0x80000000 && !(var39.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 7: storel */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_double_s32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union64 var34; + orc_union64 var35; + orc_union32 var36; + orc_union64 var37; + orc_union64 var38; + orc_union64 var39; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + /* 4: loadpq */ + var35.i = ORC_UINT64_C (0x3fe0000000000000); /* 0.5f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: swapq */ + var37.i = ORC_SWAP_Q (var33.i); + /* 3: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var37.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f * _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 5: addd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var38.i); + _src2.i = ORC_DENORMAL_DOUBLE (var35.i); + _dest1.f = _src1.f + _src2.f; + var39.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 6: convdl */ + { + int tmp; + tmp = var39.f; + if (tmp == 0x80000000 && !(var39.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 7: storel */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_double_s32_swap; +void +orc_audio_convert_unpack_double_s32_swap (guint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_double_s32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_float_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_float_double (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: convfd */ + { + orc_union32 _src1; + _src1.i = ORC_DENORMAL (var32.i); + var33.f = _src1.f; + } + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_float_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: convfd */ + { + orc_union32 _src1; + _src1.i = ORC_DENORMAL (var32.i); + var33.f = _src1.f; + } + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_float_double; +void +orc_audio_convert_unpack_float_double (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_float_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_float_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_float_double_swap (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: convfd */ + { + orc_union32 _src1; + _src1.i = ORC_DENORMAL (var35.i); + var34.f = _src1.f; + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_float_double_swap (OrcExecutor * + ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: convfd */ + { + orc_union32 _src1; + _src1.i = ORC_DENORMAL (var35.i); + var34.f = _src1.f; + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_float_double_swap; +void +orc_audio_convert_unpack_float_double_swap (gdouble * ORC_RESTRICT d1, + const gfloat * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_float_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_double_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_double_double (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_double_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_double_double; +void +orc_audio_convert_unpack_double_double (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_double_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_double_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_double_double_swap (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: swapq */ + var33.i = ORC_SWAP_Q (var32.i); + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_double_double_swap (OrcExecutor * + ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: swapq */ + var33.i = ORC_SWAP_Q (var32.i); + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_double_double_swap; +void +orc_audio_convert_unpack_double_double_swap (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_double_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u8_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_int8 *) s1; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var37.i = (orc_uint8) var34; + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << p1; + /* 5: xorl */ + var40.i = var39.i ^ var35.i; + /* 6: convld */ + var36.f = var40.i; + /* 7: storeq */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u8_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union32 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var37.i = (orc_uint8) var34; + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << ex->params[24]; + /* 5: xorl */ + var40.i = var39.i ^ var35.i; + /* 6: convld */ + var36.f = var40.i; + /* 7: storeq */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u8_double; +void +orc_audio_convert_unpack_u8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u8_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s8_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var36.i = (orc_uint8) var34; + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var38.i = var37.i << p1; + /* 4: convld */ + var35.f = var38.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s8_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr4[i]; + /* 1: convubw */ + var36.i = (orc_uint8) var34; + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var38.i = var37.i << ex->params[24]; + /* 4: convld */ + var35.f = var38.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s8_double; +void +orc_audio_convert_unpack_s8_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s8_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u16_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union16 *) s1; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var36.i = (orc_uint16) var33.i; + /* 2: shll */ + var37.i = var36.i << p1; + /* 4: xorl */ + var38.i = var37.i ^ var34.i; + /* 5: convld */ + var35.f = var38.i; + /* 6: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u16_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var36.i = (orc_uint16) var33.i; + /* 2: shll */ + var37.i = var36.i << ex->params[24]; + /* 4: xorl */ + var38.i = var37.i ^ var34.i; + /* 5: convld */ + var35.f = var38.i; + /* 6: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u16_double; +void +orc_audio_convert_unpack_u16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u16_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s16_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var35.i = (orc_uint16) var33.i; + /* 2: shll */ + var36.i = var35.i << p1; + /* 3: convld */ + var34.f = var36.i; + /* 4: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s16_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var33; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr4[i]; + /* 1: convuwl */ + var35.i = (orc_uint16) var33.i; + /* 2: shll */ + var36.i = var35.i << ex->params[24]; + /* 3: convld */ + var34.f = var36.i; + /* 4: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s16_double; +void +orc_audio_convert_unpack_s16_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s16_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u16_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union16 *) s1; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var37.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << p1; + /* 5: xorl */ + var40.i = var39.i ^ var35.i; + /* 6: convld */ + var36.f = var40.i; + /* 7: storeq */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u16_double_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union32 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + /* 4: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var37.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var38.i = (orc_uint16) var37.i; + /* 3: shll */ + var39.i = var38.i << ex->params[24]; + /* 5: xorl */ + var40.i = var39.i ^ var35.i; + /* 6: convld */ + var36.f = var40.i; + /* 7: storeq */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u16_double_swap; +void +orc_audio_convert_unpack_u16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u16_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s16_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var36.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var38.i = var37.i << p1; + /* 4: convld */ + var35.f = var38.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s16_double_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: swapw */ + var36.i = ORC_SWAP_W (var34.i); + /* 2: convuwl */ + var37.i = (orc_uint16) var36.i; + /* 3: shll */ + var38.i = var37.i << ex->params[24]; + /* 4: convld */ + var35.f = var38.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s16_double_swap; +void +orc_audio_convert_unpack_s16_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s16_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u32_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var36.i = var33.i << p1; + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: convld */ + var35.f = var37.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u32_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var36.i = var33.i << ex->params[24]; + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: convld */ + var35.f = var37.i; + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u32_double; +void +orc_audio_convert_unpack_u32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u32_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s32_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var35.i = var33.i << p1; + /* 2: convld */ + var34.f = var35.i; + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s32_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shll */ + var35.i = var33.i << ex->params[24]; + /* 2: convld */ + var34.f = var35.i; + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s32_double; +void +orc_audio_convert_unpack_s32_double (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s32_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_u32_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_u32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var36.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var37.i = var36.i << p1; + /* 4: xorl */ + var38.i = var37.i ^ var34.i; + /* 5: convld */ + var35.f = var38.i; + /* 6: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_u32_double_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union64 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 3: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var36.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var37.i = var36.i << ex->params[24]; + /* 4: xorl */ + var38.i = var37.i ^ var34.i; + /* 5: convld */ + var35.f = var38.i; + /* 6: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_u32_double_swap; +void +orc_audio_convert_unpack_u32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_u32_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_unpack_s32_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_unpack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var36.i = var35.i << p1; + /* 3: convld */ + var34.f = var36.i; + /* 4: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_unpack_s32_double_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: swapl */ + var35.i = ORC_SWAP_L (var33.i); + /* 2: shll */ + var36.i = var35.i << ex->params[24]; + /* 3: convld */ + var34.f = var36.i; + /* 4: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_unpack_s32_double_swap; +void +orc_audio_convert_unpack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_unpack_s32_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_u8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_u8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union32 var35; + orc_int8 var36; + orc_union32 var37; + orc_union32 var38; + orc_union16 var39; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 2: xorl */ + var37.i = var34.i ^ var35.i; + /* 3: shrul */ + var38.i = ((orc_uint32) var37.i) >> p1; + /* 4: convlw */ + var39.i = var38.i; + /* 5: convwb */ + var36 = var39.i; + /* 6: storeb */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union32 var35; + orc_int8 var36; + orc_union32 var37; + orc_union32 var38; + orc_union16 var39; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 2: xorl */ + var37.i = var34.i ^ var35.i; + /* 3: shrul */ + var38.i = ((orc_uint32) var37.i) >> ex->params[24]; + /* 4: convlw */ + var39.i = var38.i; + /* 5: convwb */ + var36 = var39.i; + /* 6: storeb */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_u8; +void +orc_audio_convert_pack_u8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_int8 var35; + orc_union32 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: shrsl */ + var36.i = var34.i >> p1; + /* 2: convlw */ + var37.i = var36.i; + /* 3: convwb */ + var35 = var37.i; + /* 4: storeb */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_int8 var35; + orc_union32 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: shrsl */ + var36.i = var34.i >> ex->params[24]; + /* 2: convlw */ + var37.i = var36.i; + /* 3: convwb */ + var35 = var37.i; + /* 4: storeb */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s8; +void +orc_audio_convert_pack_s8 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_u16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_u16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var37.i = ((orc_uint32) var36.i) >> p1; + /* 4: convlw */ + var35.i = var37.i; + /* 5: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var37.i = ((orc_uint32) var36.i) >> ex->params[24]; + /* 4: convlw */ + var35.i = var37.i; + /* 5: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_u16; +void +orc_audio_convert_pack_u16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union16 var34; + orc_union32 var35; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shrsl */ + var35.i = var33.i >> p1; + /* 2: convlw */ + var34.i = var35.i; + /* 3: storew */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union16 var34; + orc_union32 var35; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shrsl */ + var35.i = var33.i >> ex->params[24]; + /* 2: convlw */ + var34.i = var35.i; + /* 3: storew */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s16; +void +orc_audio_convert_pack_s16 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_u16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_u16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union16 var39; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 2: xorl */ + var37.i = var34.i ^ var35.i; + /* 3: shrul */ + var38.i = ((orc_uint32) var37.i) >> p1; + /* 4: convlw */ + var39.i = var38.i; + /* 5: swapw */ + var36.i = ORC_SWAP_W (var39.i); + /* 6: storew */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_u16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union16 var39; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 2: xorl */ + var37.i = var34.i ^ var35.i; + /* 3: shrul */ + var38.i = ((orc_uint32) var37.i) >> ex->params[24]; + /* 4: convlw */ + var39.i = var38.i; + /* 5: swapw */ + var36.i = ORC_SWAP_W (var39.i); + /* 6: storew */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_u16_swap; +void +orc_audio_convert_pack_u16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_u16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union16 var37; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: shrsl */ + var36.i = var34.i >> p1; + /* 2: convlw */ + var37.i = var36.i; + /* 3: swapw */ + var35.i = ORC_SWAP_W (var37.i); + /* 4: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union16 var37; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: shrsl */ + var36.i = var34.i >> ex->params[24]; + /* 2: convlw */ + var37.i = var36.i; + /* 3: swapw */ + var35.i = ORC_SWAP_W (var37.i); + /* 4: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s16_swap; +void +orc_audio_convert_pack_s16_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_u32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_u32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var35.i = ((orc_uint32) var36.i) >> p1; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var35.i = ((orc_uint32) var36.i) >> ex->params[24]; + /* 4: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_u32; +void +orc_audio_convert_pack_u32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: shrsl */ + var33.i = var32.i >> p1; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: shrsl */ + var33.i = var32.i >> ex->params[24]; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32; +void +orc_audio_convert_pack_s32 (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_u32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_u32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var37.i = ((orc_uint32) var36.i) >> p1; + /* 4: swapl */ + var35.i = ORC_SWAP_L (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_u32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 1: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 2: xorl */ + var36.i = var33.i ^ var34.i; + /* 3: shrul */ + var37.i = ((orc_uint32) var36.i) >> ex->params[24]; + /* 4: swapl */ + var35.i = ORC_SWAP_L (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_u32_swap; +void +orc_audio_convert_pack_u32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_u32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shrsl */ + var35.i = var33.i >> p1; + /* 2: swapl */ + var34.i = ORC_SWAP_L (var35.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: shrsl */ + var35.i = var33.i >> ex->params[24]; + /* 2: swapl */ + var34.i = ORC_SWAP_L (var35.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32_swap; +void +orc_audio_convert_pack_s32_swap (guint8 * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32_float */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32_float (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convlf */ + var35.f = var33.i; + /* 3: divf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f / _src2.f; + var36.i = ORC_DENORMAL (_dest1.i); + } + /* 4: storel */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32_float (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convlf */ + var35.f = var33.i; + /* 3: divf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f / _src2.f; + var36.i = ORC_DENORMAL (_dest1.i); + } + /* 4: storel */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32_float; +void +orc_audio_convert_pack_s32_float (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32_float; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32_float_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32_float_swap (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convlf */ + var36.f = var33.i; + /* 3: divf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var36.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f / _src2.f; + var37.i = ORC_DENORMAL (_dest1.i); + } + /* 4: swapl */ + var35.i = ORC_SWAP_L (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32_float_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x4f000000; /* 1325400064 or 6.54835e-315f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convlf */ + var36.f = var33.i; + /* 3: divf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var36.i); + _src2.i = ORC_DENORMAL (var34.i); + _dest1.f = _src1.f / _src2.f; + var37.i = ORC_DENORMAL (_dest1.i); + } + /* 4: swapl */ + var35.i = ORC_SWAP_L (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32_float_swap; +void +orc_audio_convert_pack_s32_float_swap (gfloat * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32_float_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32_double */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32_double (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var35.f = var33.i; + /* 3: divd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f / _src2.f; + var36.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: storeq */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32_double (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var35.f = var33.i; + /* 3: divd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f / _src2.f; + var36.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: storeq */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32_double; +void +orc_audio_convert_pack_s32_double (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32_double; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_s32_double_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var36.f = var33.i; + /* 3: divd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f / _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: swapq */ + var35.i = ORC_SWAP_Q (var37.i); + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_s32_double_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x41dfffffffc00000); /* 2.14748e+09f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var36.f = var33.i; + /* 3: divd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f / _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: swapq */ + var35.i = ORC_SWAP_Q (var37.i); + /* 5: storeq */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_s32_double_swap; +void +orc_audio_convert_pack_s32_double_swap (gdouble * ORC_RESTRICT d1, + const gint32 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_s32_double_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_float */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_float (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _dest.f = _src1.f; + var33.i = ORC_DENORMAL (_dest.i); + } + /* 2: storel */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_float (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _dest.f = _src1.f; + var33.i = ORC_DENORMAL (_dest.i); + } + /* 2: storel */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_float; +void +orc_audio_convert_pack_double_float (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_float; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_float_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_float_swap (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest.f = _src1.f; + var35.i = ORC_DENORMAL (_dest.i); + } + /* 2: swapl */ + var34.i = ORC_SWAP_L (var35.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_float_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest.f = _src1.f; + var35.i = ORC_DENORMAL (_dest.i); + } + /* 2: swapl */ + var34.i = ORC_SWAP_L (var35.i); + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_float_swap; +void +orc_audio_convert_pack_double_float_swap (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_float_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_u8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_u8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_int8 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union16 var40; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var37.i = tmp; + } + /* 3: xorl */ + var38.i = var37.i ^ var35.i; + /* 4: shrul */ + var39.i = ((orc_uint32) var38.i) >> p1; + /* 5: convlw */ + var40.i = var39.i; + /* 6: convwb */ + var36 = var40.i; + /* 7: storeb */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_int8 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union16 var40; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var37.i = tmp; + } + /* 3: xorl */ + var38.i = var37.i ^ var35.i; + /* 4: shrul */ + var39.i = ((orc_uint32) var38.i) >> ex->params[24]; + /* 5: convlw */ + var40.i = var39.i; + /* 6: convwb */ + var36 = var40.i; + /* 7: storeb */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_u8; +void +orc_audio_convert_pack_double_u8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_s8 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_s8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_int8 var35; + orc_union32 var36; + orc_union32 var37; + orc_union16 var38; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 2: shrsl */ + var37.i = var36.i >> p1; + /* 3: convlw */ + var38.i = var37.i; + /* 4: convwb */ + var35 = var38.i; + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_s8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_int8 var35; + orc_union32 var36; + orc_union32 var37; + orc_union16 var38; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 2: shrsl */ + var37.i = var36.i >> ex->params[24]; + /* 3: convlw */ + var38.i = var37.i; + /* 4: convwb */ + var35 = var38.i; + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_s8; +void +orc_audio_convert_pack_double_s8 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_s8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_u16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_u16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var38.i = ((orc_uint32) var37.i) >> p1; + /* 5: convlw */ + var35.i = var38.i; + /* 6: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var38.i = ((orc_uint32) var37.i) >> ex->params[24]; + /* 5: convlw */ + var35.i = var38.i; + /* 6: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_u16; +void +orc_audio_convert_pack_double_u16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_s16 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_s16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union16 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var36.i = var35.i >> p1; + /* 3: convlw */ + var34.i = var36.i; + /* 4: storew */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_s16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union16 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var36.i = var35.i >> ex->params[24]; + /* 3: convlw */ + var34.i = var36.i; + /* 4: storew */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_s16; +void +orc_audio_convert_pack_double_s16 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_s16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_u16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_u16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union16 var40; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var37.i = tmp; + } + /* 3: xorl */ + var38.i = var37.i ^ var35.i; + /* 4: shrul */ + var39.i = ((orc_uint32) var38.i) >> p1; + /* 5: convlw */ + var40.i = var39.i; + /* 6: swapw */ + var36.i = ORC_SWAP_W (var40.i); + /* 7: storew */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_u16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union16 var40; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpl */ + var35.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var37.i = tmp; + } + /* 3: xorl */ + var38.i = var37.i ^ var35.i; + /* 4: shrul */ + var39.i = ((orc_uint32) var38.i) >> ex->params[24]; + /* 5: convlw */ + var40.i = var39.i; + /* 6: swapw */ + var36.i = ORC_SWAP_W (var40.i); + /* 7: storew */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_u16_swap; +void +orc_audio_convert_pack_double_u16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_u16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_s16_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_s16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + orc_union16 var38; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 2: shrsl */ + var37.i = var36.i >> p1; + /* 3: convlw */ + var38.i = var37.i; + /* 4: swapw */ + var35.i = ORC_SWAP_W (var38.i); + /* 5: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_s16_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + orc_union16 var38; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var34.f; + if (tmp == 0x80000000 && !(var34.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 2: shrsl */ + var37.i = var36.i >> ex->params[24]; + /* 3: convlw */ + var38.i = var37.i; + /* 4: swapw */ + var35.i = ORC_SWAP_W (var38.i); + /* 5: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_s16_swap; +void +orc_audio_convert_pack_double_s16_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_s16_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_u32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_u32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var35.i = ((orc_uint32) var37.i) >> p1; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var35.i = ((orc_uint32) var37.i) >> ex->params[24]; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_u32; +void +orc_audio_convert_pack_double_u32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_s32 */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_s32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var34.i = var35.i >> p1; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_s32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var34.i = var35.i >> ex->params[24]; + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_s32; +void +orc_audio_convert_pack_double_s32 (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_s32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_u32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_u32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var38.i = ((orc_uint32) var37.i) >> p1; + /* 5: swapl */ + var35.i = ORC_SWAP_L (var38.i); + /* 6: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_u32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + orc_union32 var38; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + /* 2: loadpl */ + var34.i = (int) 0x80000000; /* -2147483648 or 1.061e-314f */ + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var36.i = tmp; + } + /* 3: xorl */ + var37.i = var36.i ^ var34.i; + /* 4: shrul */ + var38.i = ((orc_uint32) var37.i) >> ex->params[24]; + /* 5: swapl */ + var35.i = ORC_SWAP_L (var38.i); + /* 6: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_u32_swap; +void +orc_audio_convert_pack_double_u32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_u32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_audio_convert_pack_double_s32_swap */ +#ifdef DISABLE_ORC +void +orc_audio_convert_pack_double_s32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var36.i = var35.i >> p1; + /* 3: swapl */ + var34.i = ORC_SWAP_L (var36.i); + /* 4: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_audio_convert_pack_double_s32_swap (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdl */ + { + int tmp; + tmp = var33.f; + if (tmp == 0x80000000 && !(var33.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 2: shrsl */ + var36.i = var35.i >> ex->params[24]; + /* 3: swapl */ + var34.i = ORC_SWAP_L (var36.i); + /* 4: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_audio_convert_pack_double_s32_swap; +void +orc_audio_convert_pack_double_s32_swap (guint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_audio_convert_pack_double_s32_swap; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +void +gst_audio_convert_orc_init (void) +{ +#ifndef DISABLE_ORC + { + /* orc_audio_convert_unpack_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u8"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_u8); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_C1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u8 = p; + } + { + /* orc_audio_convert_unpack_s8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s8"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_s8); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s8 = p; + } + { + /* orc_audio_convert_unpack_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u16"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_u16); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u16 = p; + } + { + /* orc_audio_convert_unpack_s16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s16"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_s16); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s16 = p; + } + { + /* orc_audio_convert_unpack_u16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u16_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "swapw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_C1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u16_swap = p; + } + { + /* orc_audio_convert_unpack_s16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s16_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "swapw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s16_swap = p; + } + { + /* orc_audio_convert_unpack_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u32"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u32 = p; + } + { + /* orc_audio_convert_unpack_s32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s32"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_unpack_s32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + + orc_program_append_2 (p, "shll", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s32 = p; + } + { + /* orc_audio_convert_unpack_u32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u32_swap = p; + } + { + /* orc_audio_convert_unpack_s32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s32_swap = p; + } + { + /* orc_audio_convert_unpack_float_s32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_float_s32"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_float_s32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x4f000000, "c1"); + orc_program_add_constant (p, 4, 0x3f000000, "c2"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "addf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C2, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_float_s32 = p; + } + { + /* orc_audio_convert_unpack_float_s32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_float_s32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_float_s32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x4f000000, "c1"); + orc_program_add_constant (p, 4, 0x3f000000, "c2"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "addf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C2, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_float_s32_swap = p; + } + { + /* orc_audio_convert_unpack_double_s32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_double_s32"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_double_s32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant_int64 (p, 8, 0x41dfffffffc00000ULL, "c1"); + orc_program_add_constant_int64 (p, 8, 0x3fe0000000000000ULL, "c2"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "loadq", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "muld", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "addd", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C2, + ORC_VAR_D1); + orc_program_append_2 (p, "convdl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_double_s32 = p; + } + { + /* orc_audio_convert_unpack_double_s32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_double_s32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_double_s32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant_int64 (p, 8, 0x41dfffffffc00000ULL, "c1"); + orc_program_add_constant_int64 (p, 8, 0x3fe0000000000000ULL, "c2"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "swapq", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "muld", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "addd", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C2, + ORC_VAR_D1); + orc_program_append_2 (p, "convdl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_double_s32_swap = p; + } + { + /* orc_audio_convert_unpack_float_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_float_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_float_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + + orc_program_append_2 (p, "convfd", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_float_double = p; + } + { + /* orc_audio_convert_unpack_float_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_float_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_float_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convfd", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_float_double_swap = p; + } + { + /* orc_audio_convert_unpack_double_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_double_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_double_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 8, "s1"); + + orc_program_append_2 (p, "copyq", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_double_double = p; + } + { + /* orc_audio_convert_unpack_double_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_double_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_double_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 8, "s1"); + + orc_program_append_2 (p, "swapq", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_double_double_swap = p; + } + { + /* orc_audio_convert_unpack_u8_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u8_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u8_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u8_double = p; + } + { + /* orc_audio_convert_unpack_s8_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s8_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s8_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s8_double = p; + } + { + /* orc_audio_convert_unpack_u16_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u16_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u16_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u16_double = p; + } + { + /* orc_audio_convert_unpack_s16_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s16_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s16_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s16_double = p; + } + { + /* orc_audio_convert_unpack_u16_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u16_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u16_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "swapw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u16_double_swap = p; + } + { + /* orc_audio_convert_unpack_s16_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s16_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s16_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "swapw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convuwl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s16_double_swap = p; + } + { + /* orc_audio_convert_unpack_u32_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u32_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u32_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u32_double = p; + } + { + /* orc_audio_convert_unpack_s32_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s32_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s32_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s32_double = p; + } + { + /* orc_audio_convert_unpack_u32_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_u32_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_u32_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_u32_double_swap = p; + } + { + /* orc_audio_convert_unpack_s32_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_unpack_s32_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_unpack_s32_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "swapl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shll", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convld", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_unpack_s32_double_swap = p; + } + { + /* orc_audio_convert_pack_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_u8"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convwb", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_u8 = p; + } + { + /* orc_audio_convert_pack_s8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s8"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_s8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convwb", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s8 = p; + } + { + /* orc_audio_convert_pack_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_u16"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_u16 = p; + } + { + /* orc_audio_convert_pack_s16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s16"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_s16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s16 = p; + } + { + /* orc_audio_convert_pack_u16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_u16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_u16_swap); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapw", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_u16_swap = p; + } + { + /* orc_audio_convert_pack_s16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s16_swap); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapw", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s16_swap = p; + } + { + /* orc_audio_convert_pack_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_u32"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_u32 = p; + } + { + /* orc_audio_convert_pack_s32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32"); + orc_program_set_backup_function (p, _backup_orc_audio_convert_pack_s32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32 = p; + } + { + /* orc_audio_convert_pack_u32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_u32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_u32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_u32_swap = p; + } + { + /* orc_audio_convert_pack_s32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32_swap = p; + } + { + /* orc_audio_convert_pack_s32_float */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32_float"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s32_float); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x4f000000, "c1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convlf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "divf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "storel", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32_float = p; + } + { + /* orc_audio_convert_pack_s32_float_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32_float_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s32_float_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant (p, 4, 0x4f000000, "c1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convlf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "divf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32_float_swap = p; + } + { + /* orc_audio_convert_pack_s32_double */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32_double"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s32_double); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant_int64 (p, 8, 0x41dfffffffc00000ULL, "c1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "convld", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "divd", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "storeq", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32_double = p; + } + { + /* orc_audio_convert_pack_s32_double_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_s32_double_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_s32_double_swap); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant_int64 (p, 8, 0x41dfffffffc00000ULL, "c1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "convld", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "divd", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapq", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_s32_double_swap = p; + } + { + /* orc_audio_convert_pack_double_float */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_float"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_float); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + + orc_program_append_2 (p, "convdf", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_float = p; + } + { + /* orc_audio_convert_pack_double_float_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_float_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_float_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_float_swap = p; + } + { + /* orc_audio_convert_pack_double_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_u8"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convwb", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_u8 = p; + } + { + /* orc_audio_convert_pack_double_s8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_s8"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_s8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convwb", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_s8 = p; + } + { + /* orc_audio_convert_pack_double_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_u16"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_u16 = p; + } + { + /* orc_audio_convert_pack_double_s16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_s16"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_s16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_s16 = p; + } + { + /* orc_audio_convert_pack_double_u16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_u16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_u16_swap); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapw", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_u16_swap = p; + } + { + /* orc_audio_convert_pack_double_s16_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_s16_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_s16_swap); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapw", 0, ORC_VAR_D1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_s16_swap = p; + } + { + /* orc_audio_convert_pack_double_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_u32"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_u32 = p; + } + { + /* orc_audio_convert_pack_double_s32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_s32"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_s32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_s32 = p; + } + { + /* orc_audio_convert_pack_double_u32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_u32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_u32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_constant (p, 4, 0x80000000, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "xorl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_u32_swap = p; + } + { + /* orc_audio_convert_pack_double_s32_swap */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_audio_convert_pack_double_s32_swap"); + orc_program_set_backup_function (p, + _backup_orc_audio_convert_pack_double_s32_swap); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "swapl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_audio_convert_pack_double_s32_swap = p; + } +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.h new file mode 100644 index 0000000..3d74e1a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc-dist.h @@ -0,0 +1,132 @@ + +/* autogenerated from gstaudioconvertorc.orc */ + +#ifndef _GSTAUDIOCONVERTORC_H_ +#define _GSTAUDIOCONVERTORC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void gst_audio_convert_orc_init (void); + + + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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_audio_convert_unpack_u8 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s8 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_swap (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_swap (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32 (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_swap (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_swap (gint32 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_float_s32 (guint32 * ORC_RESTRICT d1, const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_s32_swap (guint32 * ORC_RESTRICT d1, const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_s32 (guint32 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_s32_swap (guint32 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_double (gdouble * ORC_RESTRICT d1, const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_float_double_swap (gdouble * ORC_RESTRICT d1, const gfloat * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_double (gdouble * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_double_double_swap (gdouble * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_unpack_u8_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s8_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u16_double_swap (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s16_double_swap (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_double (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_u32_double_swap (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_unpack_s32_double_swap (gdouble * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u8 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s8 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u16 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s16 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u16_swap (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s16_swap (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u32 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32 (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_u32_swap (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32_swap (guint8 * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_s32_float (gfloat * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_float_swap (gfloat * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_double (gdouble * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_s32_double_swap (gdouble * ORC_RESTRICT d1, const gint32 * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_float (gfloat * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_float_swap (gfloat * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_audio_convert_pack_double_u8 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s8 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u16 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s16 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u16_swap (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s16_swap (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u32 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s32 (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_u32_swap (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); +void orc_audio_convert_pack_double_s32_swap (guint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int p1, int n); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc.orc b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc.orc new file mode 100644 index 0000000..23da7fd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioconvertorc.orc @@ -0,0 +1,593 @@ + +.init gst_audio_convert_orc_init + +.function orc_audio_convert_unpack_u8 +.dest 4 d1 gint32 +.source 1 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 2 t2 +.temp 4 t3 + +convubw t2, s1 +convuwl t3, t2 +shll t3, t3, p1 +xorl d1, t3, c1 + + +.function orc_audio_convert_unpack_s8 +.dest 4 d1 gint32 +.source 1 s1 guint8 +.param 4 p1 +.temp 2 t2 +.temp 4 t3 + +convubw t2, s1 +convuwl t3, t2 +shll d1, t3, p1 + + +.function orc_audio_convert_unpack_u16 +.dest 4 d1 gint32 +.source 2 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t2 + +convuwl t2, s1 +shll t2, t2, p1 +xorl d1, t2, c1 + + +.function orc_audio_convert_unpack_s16 +.dest 4 d1 gint32 +.source 2 s1 guint8 +.param 4 p1 +.temp 4 t2 + +convuwl t2, s1 +shll d1, t2, p1 + + +.function orc_audio_convert_unpack_u16_swap +.dest 4 d1 gint32 +.source 2 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 2 t1 +.temp 4 t2 + +swapw t1, s1 +convuwl t2, t1 +shll t2, t2, p1 +xorl d1, t2, c1 + + +.function orc_audio_convert_unpack_s16_swap +.dest 4 d1 gint32 +.source 2 s1 guint8 +.param 4 p1 +.temp 2 t1 +.temp 4 t2 + +swapw t1, s1 +convuwl t2, t1 +shll d1, t2, p1 + + +.function orc_audio_convert_unpack_u32 +.dest 4 d1 gint32 +.source 4 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +shll t1, s1, p1 +xorl d1, t1, c1 + + +.function orc_audio_convert_unpack_s32 +.dest 4 d1 gint32 +.source 4 s1 guint8 +.param 4 p1 + +shll d1, s1, p1 + + +.function orc_audio_convert_unpack_u32_swap +.dest 4 d1 gint32 +.source 4 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +swapl t1, s1 +shll t1, t1, p1 +xorl d1, t1, c1 + + +.function orc_audio_convert_unpack_s32_swap +.dest 4 d1 gint32 +.source 4 s1 guint8 +.param 4 p1 +.temp 4 t1 + +swapl t1, s1 +shll d1, t1, p1 + +.function orc_audio_convert_unpack_float_s32 +.source 4 s1 gfloat +.dest 4 d1 guint32 +.temp 4 t1 + +loadl t1, s1 +# multiply with 2147483647.0 +mulf t1, t1, 0x4F000000 +# add 0.5 for rounding +addf t1, t1, 0x3F000000 +convfl d1, t1 + +.function orc_audio_convert_unpack_float_s32_swap +.source 4 s1 gfloat +.dest 4 d1 guint32 +.temp 4 t1 + +swapl t1, s1 +# multiply with 2147483647.0 +mulf t1, t1, 0x4F000000 +# add 0.5 for rounding +addf t1, t1, 0x3F000000 +convfl d1, t1 + +.function orc_audio_convert_unpack_double_s32 +.source 8 s1 gdouble +.dest 4 d1 guint32 +.temp 8 t1 + +loadq t1, s1 +# multiply with 2147483647.0 +muld t1, t1, 0x41DFFFFFFFC00000L +# add 0.5 for rounding +addd t1, t1, 0x3FE0000000000000L +convdl d1, t1 + +.function orc_audio_convert_unpack_double_s32_swap +.source 8 s1 gdouble +.dest 4 d1 guint32 +.temp 8 t1 + +swapq t1, s1 +# multiply with 2147483647.0 +muld t1, t1, 0x41DFFFFFFFC00000L +# add 0.5 for rounding +addd t1, t1, 0x3FE0000000000000L +convdl d1, t1 + +.function orc_audio_convert_unpack_float_double +.dest 8 d1 gdouble +.source 4 s1 gfloat + +convfd d1, s1 + +.function orc_audio_convert_unpack_float_double_swap +.dest 8 d1 gdouble +.source 4 s1 gfloat +.temp 4 t1 + +swapl t1, s1 +convfd d1, t1 + +.function orc_audio_convert_unpack_double_double +.dest 8 d1 gdouble +.source 8 s1 gdouble + +copyq d1, s1 + +.function orc_audio_convert_unpack_double_double_swap +.dest 8 d1 gdouble +.source 8 s1 gdouble + +swapq d1, s1 + +.function orc_audio_convert_unpack_u8_double +.dest 8 d1 gdouble +.source 1 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 2 t2 +.temp 4 t3 + +convubw t2, s1 +convuwl t3, t2 +shll t3, t3, p1 +xorl t3, t3, c1 +convld d1, t3 + +.function orc_audio_convert_unpack_s8_double +.dest 8 d1 gdouble +.source 1 s1 guint8 +.param 4 p1 +.temp 2 t2 +.temp 4 t3 + +convubw t2, s1 +convuwl t3, t2 +shll t3, t3, p1 +convld d1, t3 + +.function orc_audio_convert_unpack_u16_double +.dest 8 d1 gdouble +.source 2 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t2 + +convuwl t2, s1 +shll t2, t2, p1 +xorl t2, t2, c1 +convld d1, t2 + +.function orc_audio_convert_unpack_s16_double +.dest 8 d1 gdouble +.source 2 s1 guint8 +.param 4 p1 +.temp 4 t2 + +convuwl t2, s1 +shll t2, t2, p1 +convld d1, t2 + +.function orc_audio_convert_unpack_u16_double_swap +.dest 8 d1 gdouble +.source 2 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 2 t1 +.temp 4 t2 + +swapw t1, s1 +convuwl t2, t1 +shll t2, t2, p1 +xorl t2, t2, c1 +convld d1, t2 + +.function orc_audio_convert_unpack_s16_double_swap +.dest 8 d1 gdouble +.source 2 s1 guint8 +.param 4 p1 +.temp 2 t1 +.temp 4 t2 + +swapw t1, s1 +convuwl t2, t1 +shll t2, t2, p1 +convld d1, t2 + +.function orc_audio_convert_unpack_u32_double +.dest 8 d1 gdouble +.source 4 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +shll t1, s1, p1 +xorl t1, t1, c1 +convld d1, t1 + +.function orc_audio_convert_unpack_s32_double +.dest 8 d1 gdouble +.source 4 s1 guint8 +.param 4 p1 +.temp 4 t1 + +shll t1, s1, p1 +convld d1, t1 + +.function orc_audio_convert_unpack_u32_double_swap +.dest 8 d1 gdouble +.source 4 s1 guint8 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +swapl t1, s1 +shll t1, t1, p1 +xorl t1, t1, c1 +convld d1, t1 + +.function orc_audio_convert_unpack_s32_double_swap +.dest 8 d1 gdouble +.source 4 s1 guint8 +.param 4 p1 +.temp 4 t1 + +swapl t1, s1 +shll t1, t1, p1 +convld d1, t1 + +.function orc_audio_convert_pack_u8 +.dest 1 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 +.temp 2 t2 + +xorl t1, s1, c1 +shrul t1, t1, p1 +convlw t2, t1 +convwb d1, t2 + + +.function orc_audio_convert_pack_s8 +.dest 1 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.temp 4 t1 +.temp 2 t2 + +shrsl t1, s1, p1 +convlw t2, t1 +convwb d1, t2 + + + +.function orc_audio_convert_pack_u16 +.dest 2 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +xorl t1, s1, c1 +shrul t1, t1, p1 +convlw d1, t1 + + +.function orc_audio_convert_pack_s16 +.dest 2 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.temp 4 t1 + +shrsl t1, s1, p1 +convlw d1, t1 + + +.function orc_audio_convert_pack_u16_swap +.dest 2 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 +.temp 2 t2 + +xorl t1, s1, c1 +shrul t1, t1, p1 +convlw t2, t1 +swapw d1, t2 + + +.function orc_audio_convert_pack_s16_swap +.dest 2 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.temp 4 t1 +.temp 2 t2 + +shrsl t1, s1, p1 +convlw t2, t1 +swapw d1, t2 + + + +.function orc_audio_convert_pack_u32 +.dest 4 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +xorl t1, s1, c1 +shrul d1, t1, p1 + + +.function orc_audio_convert_pack_s32 +.dest 4 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 + +shrsl d1, s1, p1 + + +.function orc_audio_convert_pack_u32_swap +.dest 4 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +xorl t1, s1, c1 +shrul t1, t1, p1 +swapl d1, t1 + + +.function orc_audio_convert_pack_s32_swap +.dest 4 d1 guint8 +.source 4 s1 gint32 +.param 4 p1 +.temp 4 t1 + +shrsl t1, s1, p1 +swapl d1, t1 + +.function orc_audio_convert_pack_s32_float +.dest 4 d1 gfloat +.source 4 s1 gint32 +.temp 4 t1 + +convlf t1, s1 +# divide by 2147483647.0 +divf t1, t1, 0x4F000000 +storel d1, t1 + +.function orc_audio_convert_pack_s32_float_swap +.dest 4 d1 gfloat +.source 4 s1 gint32 +.temp 4 t1 + +convlf t1, s1 +# divide by 2147483647.0 +divf t1, t1, 0x4F000000 +swapl d1, t1 + +.function orc_audio_convert_pack_s32_double +.dest 8 d1 gdouble +.source 4 s1 gint32 +.temp 8 t1 + +convld t1, s1 +# divide by 2147483647.0 +divd t1, t1, 0x41DFFFFFFFC00000L +storeq d1, t1 + +.function orc_audio_convert_pack_s32_double_swap +.dest 8 d1 gdouble +.source 4 s1 gint32 +.temp 8 t1 + +convld t1, s1 +# divide by 2147483647.0 +divd t1, t1, 0x41DFFFFFFFC00000L +swapq d1, t1 + +.function orc_audio_convert_pack_double_float +.dest 4 d1 gfloat +.source 8 s1 gdouble + +convdf d1, s1 + +.function orc_audio_convert_pack_double_float_swap +.dest 4 d1 gfloat +.source 8 s1 gdouble +.temp 4 t1 + +convdf t1, s1 +swapl d1, t1 + +.function orc_audio_convert_pack_double_u8 +.dest 1 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 +.temp 2 t2 + +convdl t1, s1 +xorl t1, t1, c1 +shrul t1, t1, p1 +convlw t2, t1 +convwb d1, t2 + +.function orc_audio_convert_pack_double_s8 +.dest 1 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.temp 4 t1 +.temp 2 t2 + +convdl t1, s1 +shrsl t1, t1, p1 +convlw t2, t1 +convwb d1, t2 + +.function orc_audio_convert_pack_double_u16 +.dest 2 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +convdl t1, s1 +xorl t1, t1, c1 +shrul t1, t1, p1 +convlw d1, t1 + +.function orc_audio_convert_pack_double_s16 +.dest 2 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.temp 4 t1 + +convdl t1, s1 +shrsl t1, t1, p1 +convlw d1, t1 + +.function orc_audio_convert_pack_double_u16_swap +.dest 2 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 +.temp 2 t2 + +convdl t1, s1 +xorl t1, t1, c1 +shrul t1, t1, p1 +convlw t2, t1 +swapw d1, t2 + +.function orc_audio_convert_pack_double_s16_swap +.dest 2 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.temp 4 t1 +.temp 2 t2 + +convdl t1, s1 +shrsl t1, t1, p1 +convlw t2, t1 +swapw d1, t2 + +.function orc_audio_convert_pack_double_u32 +.dest 4 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +convdl t1, s1 +xorl t1, t1, c1 +shrul d1, t1, p1 + +.function orc_audio_convert_pack_double_s32 +.dest 4 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.temp 4 t1 + +convdl t1, s1 +shrsl d1, t1, p1 + +.function orc_audio_convert_pack_double_u32_swap +.dest 4 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.const 4 c1 0x80000000 +.temp 4 t1 + +convdl t1, s1 +xorl t1, t1, c1 +shrul t1, t1, p1 +swapl d1, t1 + +.function orc_audio_convert_pack_double_s32_swap +.dest 4 d1 guint8 +.source 8 s1 gdouble +.param 4 p1 +.temp 4 t1 + +convdl t1, s1 +shrsl t1, t1, p1 +swapl d1, t1 + diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.c new file mode 100644 index 0000000..2155397 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.c @@ -0,0 +1,503 @@ +/* GStreamer + * Copyright (C) 2007 Sebastian Dröge + * + * gstaudioquantize.c: quantizes audio to the target format and optionally + * applies dithering and noise shaping. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * FIXME: When doing dithering with int as intermediate format + * one gets audible harmonics while the noise floor is + * constant for double as intermediate format! + */ + +/* TODO: - Maybe drop 5-pole noise shaping and use coefficients + * generated by dmaker + * http://shibatch.sf.net + */ + +#include +#include +#include +#include "audioconvert.h" +#include "gstaudioquantize.h" + +#include "gstfastrandom.h" + +#define MAKE_QUANTIZE_FUNC_NAME(name) \ +gst_audio_quantize_quantize_##name + +/* Quantize functions for gint32 as intermediate format */ + +#define MAKE_QUANTIZE_FUNC_I(name, DITHER_INIT_FUNC, ADD_DITHER_FUNC, \ + ROUND_FUNC) \ +static void \ +MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gint32 *src, \ + gint32 *dst, gint count) \ +{ \ + gint scale = ctx->out_scale; \ + gint channels = ctx->out.channels; \ + gint chan_pos; \ + \ + if (scale > 0) { \ + gint32 tmp; \ + guint32 mask = 0xffffffff & (0xffffffff << scale); \ + guint32 bias = 1U << (scale - 1); \ + DITHER_INIT_FUNC() \ + \ + for (;count;count--) { \ + for (chan_pos = 0; chan_pos < channels; chan_pos++) { \ + tmp = *src++; \ + ADD_DITHER_FUNC() \ + ROUND_FUNC() \ + *dst = tmp & mask; \ + dst++; \ + } \ + } \ + } else { \ + for (;count;count--) { \ + for (chan_pos = 0; chan_pos < channels; chan_pos++) { \ + *dst = *src++; \ + dst++; \ + } \ + } \ + } \ +} + + +/* Quantize functions for gdouble as intermediate format with + * int as target */ + +#define MAKE_QUANTIZE_FUNC_F(name, DITHER_INIT_FUNC, NS_INIT_FUNC, \ + ADD_NS_FUNC, ADD_DITHER_FUNC, \ + UPDATE_ERROR_FUNC) \ +static void \ +MAKE_QUANTIZE_FUNC_NAME (name) (AudioConvertCtx *ctx, gdouble *src, \ + gdouble *dst, gint count) \ +{ \ + gint scale = ctx->out_scale; \ + gint channels = ctx->out.channels; \ + gint chan_pos; \ + gdouble factor = (1U<<(32-scale-1)) - 1; \ + \ + if (scale > 0) { \ + gdouble tmp; \ + DITHER_INIT_FUNC() \ + NS_INIT_FUNC() \ + \ + for (;count;count--) { \ + for (chan_pos = 0; chan_pos < channels; chan_pos++) { \ + tmp = *src++; \ + ADD_NS_FUNC() \ + ADD_DITHER_FUNC() \ + tmp = floor(tmp * factor + 0.5); \ + *dst = CLAMP (tmp, -factor - 1, factor); \ + UPDATE_ERROR_FUNC() \ + dst++; \ + } \ + } \ + } else { \ + for (;count;count--) { \ + for (chan_pos = 0; chan_pos < channels; chan_pos++) { \ + *dst = *src++ * 2147483647.0; \ + dst++; \ + } \ + } \ + } \ +} + +/* Rounding functions for int as intermediate format, only used when + * not using dithering. With dithering we include this offset in our + * dither noise instead. */ + +#define ROUND() \ + if (tmp > 0 && G_MAXINT32 - tmp <= bias) \ + tmp = G_MAXINT32; \ + else \ + tmp += bias; + + +#define NONE_FUNC() + +/* Dithering definitions + * See http://en.wikipedia.org/wiki/Dithering or + * http://www.cadenzarecording.com/Dither.html for explainations. + * + * We already add the rounding offset to the dither noise here + * to have only one overflow check instead of two. */ + +#define INIT_DITHER_RPDF_I() \ + gint32 rand; \ + gint32 dither = (1<<(scale)); + +#define ADD_DITHER_RPDF_I() \ + rand = gst_fast_random_int32_range (bias - dither, \ + bias + dither); \ + if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand) \ + tmp = G_MAXINT32; \ + else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand) \ + tmp = G_MININT32; \ + else \ + tmp += rand; + +#define INIT_DITHER_RPDF_F() \ + gdouble dither = 1.0/(1U<<(32 - scale - 1)); + +#define ADD_DITHER_RPDF_F() \ + tmp += gst_fast_random_double_range (- dither, dither); + +#define INIT_DITHER_TPDF_I() \ + gint32 rand; \ + gint32 dither = (1<<(scale - 1)); \ + bias = bias >> 1; + +#define ADD_DITHER_TPDF_I() \ + rand = gst_fast_random_int32_range (bias - dither, \ + bias + dither - 1) \ + + gst_fast_random_int32_range (bias - dither, \ + bias + dither - 1); \ + if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand) \ + tmp = G_MAXINT32; \ + else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand) \ + tmp = G_MININT32; \ + else \ + tmp += rand; + +#define INIT_DITHER_TPDF_F() \ + gdouble dither = 1.0/(1U<<(32 - scale)); + +#define ADD_DITHER_TPDF_F() \ + tmp += gst_fast_random_double_range (- dither, dither) \ + + gst_fast_random_double_range (- dither, dither); + +#define INIT_DITHER_TPDF_HF_I() \ + gint32 rand; \ + gint32 dither = (1<<(scale-1)); \ + gint32 *last_random = (gint32 *) ctx->last_random, tmp_rand; \ + bias = bias >> 1; + +#define ADD_DITHER_TPDF_HF_I() \ + tmp_rand = gst_fast_random_int32_range (bias - dither, \ + bias + dither); \ + rand = tmp_rand - last_random[chan_pos]; \ + last_random[chan_pos] = tmp_rand; \ + if (rand > 0 && tmp > 0 && G_MAXINT32 - tmp <= rand) \ + tmp = G_MAXINT32; \ + else if (rand < 0 && tmp < 0 && G_MININT32 - tmp >= rand) \ + tmp = G_MININT32; \ + else \ + tmp += rand; + +/* Like TPDF dither but the dither noise is oriented more to the + * higher frequencies */ + +#define INIT_DITHER_TPDF_HF_F() \ + gdouble rand; \ + gdouble dither = 1.0/(1U<<(32 - scale)); \ + gdouble *last_random = (gdouble *) ctx->last_random, tmp_rand; + +#define ADD_DITHER_TPDF_HF_F() \ + tmp_rand = gst_fast_random_double_range (- dither, dither); \ + rand = tmp_rand - last_random[chan_pos]; \ + last_random[chan_pos] = tmp_rand; \ + tmp += rand; + +/* Noise shaping definitions. + * See http://en.wikipedia.org/wiki/Noise_shaping for explanations. */ + + +/* Simple error feedback: Just accumulate the dithering and quantization + * error and remove it from each sample. */ + +#define INIT_NS_ERROR_FEEDBACK() \ + gdouble orig; \ + gdouble *errors = ctx->error_buf; + +#define ADD_NS_ERROR_FEEDBACK() \ + orig = tmp; \ + tmp -= errors[chan_pos]; + +#define UPDATE_ERROR_ERROR_FEEDBACK() \ + errors[chan_pos] += (*dst)/factor - orig; + +/* Same as error feedback but also add 1/2 of the previous error value. + * This moves the noise a bit more into the higher frequencies. */ + +#define INIT_NS_SIMPLE() \ + gdouble orig; \ + gdouble *errors = ctx->error_buf, cur_error; + +#define ADD_NS_SIMPLE() \ + cur_error = errors[chan_pos*2] - 0.5 * errors[chan_pos*2 + 1]; \ + tmp -= cur_error; \ + orig = tmp; + +#define UPDATE_ERROR_SIMPLE() \ + errors[chan_pos*2 + 1] = errors[chan_pos*2]; \ + errors[chan_pos*2] = (*dst)/factor - orig; + + +/* Noise shaping coefficients from[1], moves most power of the + * error noise into inaudible frequency ranges. + * + * [1] + * "Minimally Audible Noise Shaping", Stanley P. Lipshitz, + * John Vanderkooy, and Robert A. Wannamaker, + * J. Audio Eng. Soc., Vol. 39, No. 11, November 1991. */ + +static const gdouble ns_medium_coeffs[] = { + 2.033, -2.165, 1.959, -1.590, 0.6149 +}; + +#define INIT_NS_MEDIUM() \ + gdouble orig; \ + gdouble *errors = ctx->error_buf, cur_error; \ + int j; + +#define ADD_NS_MEDIUM() \ + cur_error = 0.0; \ + for (j = 0; j < 5; j++) \ + cur_error += errors[chan_pos*5 + j] * ns_medium_coeffs[j]; \ + tmp -= cur_error; \ + orig = tmp; + +#define UPDATE_ERROR_MEDIUM() \ + for (j = 4; j > 0; j--) \ + errors[chan_pos*5 + j] = errors[chan_pos*5 + j-1]; \ + errors[chan_pos*5] = (*dst)/factor - orig; + +/* Noise shaping coefficients by David Schleef, moves most power of the + * error noise into inaudible frequency ranges */ + +static const gdouble ns_high_coeffs[] = { + 2.08484, -2.92975, 3.27918, -3.31399, 2.61339, -1.72008, 0.876066, -0.340122 +}; + +#define INIT_NS_HIGH() \ + gdouble orig; \ + gdouble *errors = ctx->error_buf, cur_error; \ + int j; + +#define ADD_NS_HIGH() \ + cur_error = 0.0; \ + for (j = 0; j < 8; j++) \ + cur_error += errors[chan_pos + j] * ns_high_coeffs[j]; \ + tmp -= cur_error; \ + orig = tmp; + +#define UPDATE_ERROR_HIGH() \ + for (j = 7; j > 0; j--) \ + errors[chan_pos + j] = errors[chan_pos + j-1]; \ + errors[chan_pos] = (*dst)/factor - orig; + + +MAKE_QUANTIZE_FUNC_I (signed_none_none, NONE_FUNC, NONE_FUNC, ROUND); +MAKE_QUANTIZE_FUNC_I (signed_rpdf_none, INIT_DITHER_RPDF_I, ADD_DITHER_RPDF_I, + NONE_FUNC); +MAKE_QUANTIZE_FUNC_I (signed_tpdf_none, INIT_DITHER_TPDF_I, ADD_DITHER_TPDF_I, + NONE_FUNC); +MAKE_QUANTIZE_FUNC_I (signed_tpdf_hf_none, INIT_DITHER_TPDF_HF_I, + ADD_DITHER_TPDF_HF_I, NONE_FUNC); + +MAKE_QUANTIZE_FUNC_I (unsigned_none_none, NONE_FUNC, NONE_FUNC, ROUND); +MAKE_QUANTIZE_FUNC_I (unsigned_rpdf_none, INIT_DITHER_RPDF_I, ADD_DITHER_RPDF_I, + NONE_FUNC); +MAKE_QUANTIZE_FUNC_I (unsigned_tpdf_none, INIT_DITHER_TPDF_I, ADD_DITHER_TPDF_I, + NONE_FUNC); +MAKE_QUANTIZE_FUNC_I (unsigned_tpdf_hf_none, INIT_DITHER_TPDF_HF_I, + ADD_DITHER_TPDF_HF_I, NONE_FUNC); + +MAKE_QUANTIZE_FUNC_F (float_none_error_feedback, NONE_FUNC, + INIT_NS_ERROR_FEEDBACK, ADD_NS_ERROR_FEEDBACK, NONE_FUNC, + UPDATE_ERROR_ERROR_FEEDBACK); +MAKE_QUANTIZE_FUNC_F (float_none_simple, NONE_FUNC, INIT_NS_SIMPLE, + ADD_NS_SIMPLE, NONE_FUNC, UPDATE_ERROR_SIMPLE); +MAKE_QUANTIZE_FUNC_F (float_none_medium, NONE_FUNC, INIT_NS_MEDIUM, + ADD_NS_MEDIUM, NONE_FUNC, UPDATE_ERROR_MEDIUM); +MAKE_QUANTIZE_FUNC_F (float_none_high, NONE_FUNC, INIT_NS_HIGH, ADD_NS_HIGH, + NONE_FUNC, UPDATE_ERROR_HIGH); + +MAKE_QUANTIZE_FUNC_F (float_rpdf_error_feedback, INIT_DITHER_RPDF_F, + INIT_NS_ERROR_FEEDBACK, ADD_NS_ERROR_FEEDBACK, ADD_DITHER_RPDF_F, + UPDATE_ERROR_ERROR_FEEDBACK); +MAKE_QUANTIZE_FUNC_F (float_rpdf_simple, INIT_DITHER_RPDF_F, INIT_NS_SIMPLE, + ADD_NS_SIMPLE, ADD_DITHER_RPDF_F, UPDATE_ERROR_SIMPLE); +MAKE_QUANTIZE_FUNC_F (float_rpdf_medium, INIT_DITHER_RPDF_F, INIT_NS_MEDIUM, + ADD_NS_MEDIUM, ADD_DITHER_RPDF_F, UPDATE_ERROR_MEDIUM); +MAKE_QUANTIZE_FUNC_F (float_rpdf_high, INIT_DITHER_RPDF_F, INIT_NS_HIGH, + ADD_NS_HIGH, ADD_DITHER_RPDF_F, UPDATE_ERROR_HIGH); + +MAKE_QUANTIZE_FUNC_F (float_tpdf_error_feedback, INIT_DITHER_TPDF_F, + INIT_NS_ERROR_FEEDBACK, ADD_NS_ERROR_FEEDBACK, ADD_DITHER_TPDF_F, + UPDATE_ERROR_ERROR_FEEDBACK); +MAKE_QUANTIZE_FUNC_F (float_tpdf_simple, INIT_DITHER_TPDF_F, INIT_NS_SIMPLE, + ADD_NS_SIMPLE, ADD_DITHER_TPDF_F, UPDATE_ERROR_SIMPLE); +MAKE_QUANTIZE_FUNC_F (float_tpdf_medium, INIT_DITHER_TPDF_F, INIT_NS_MEDIUM, + ADD_NS_MEDIUM, ADD_DITHER_TPDF_F, UPDATE_ERROR_MEDIUM); +MAKE_QUANTIZE_FUNC_F (float_tpdf_high, INIT_DITHER_TPDF_F, INIT_NS_HIGH, + ADD_NS_HIGH, ADD_DITHER_TPDF_F, UPDATE_ERROR_HIGH); + +MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_error_feedback, INIT_DITHER_TPDF_HF_F, + INIT_NS_ERROR_FEEDBACK, ADD_NS_ERROR_FEEDBACK, ADD_DITHER_TPDF_HF_F, + UPDATE_ERROR_ERROR_FEEDBACK); +MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_simple, INIT_DITHER_TPDF_HF_F, + INIT_NS_SIMPLE, ADD_NS_SIMPLE, ADD_DITHER_TPDF_HF_F, UPDATE_ERROR_SIMPLE); +MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_medium, INIT_DITHER_TPDF_HF_F, + INIT_NS_MEDIUM, ADD_NS_MEDIUM, ADD_DITHER_TPDF_HF_F, UPDATE_ERROR_MEDIUM); +MAKE_QUANTIZE_FUNC_F (float_tpdf_hf_high, INIT_DITHER_TPDF_HF_F, INIT_NS_HIGH, + ADD_NS_HIGH, ADD_DITHER_TPDF_HF_F, UPDATE_ERROR_HIGH); + +static AudioConvertQuantize quantize_funcs[] = { + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (signed_none_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (signed_rpdf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (signed_tpdf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (signed_tpdf_hf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (unsigned_none_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (unsigned_rpdf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (unsigned_tpdf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (unsigned_tpdf_hf_none), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_error_feedback), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_simple), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_medium), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_none_high), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_error_feedback), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_simple), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_medium), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_rpdf_high), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_error_feedback), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_simple), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_medium), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_high), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_error_feedback), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_simple), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_medium), + (AudioConvertQuantize) MAKE_QUANTIZE_FUNC_NAME (float_tpdf_hf_high) +}; + +static void +gst_audio_quantize_setup_noise_shaping (AudioConvertCtx * ctx) +{ + switch (ctx->ns) { + case NOISE_SHAPING_HIGH:{ + ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 8); + break; + } + case NOISE_SHAPING_MEDIUM:{ + ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 5); + break; + } + case NOISE_SHAPING_SIMPLE:{ + ctx->error_buf = g_new0 (gdouble, ctx->out.channels * 2); + break; + } + case NOISE_SHAPING_ERROR_FEEDBACK: + ctx->error_buf = g_new0 (gdouble, ctx->out.channels); + break; + case NOISE_SHAPING_NONE: + default: + ctx->error_buf = NULL; + break; + } + return; +} + +static void +gst_audio_quantize_free_noise_shaping (AudioConvertCtx * ctx) +{ + switch (ctx->ns) { + case NOISE_SHAPING_HIGH: + case NOISE_SHAPING_MEDIUM: + case NOISE_SHAPING_SIMPLE: + case NOISE_SHAPING_ERROR_FEEDBACK: + case NOISE_SHAPING_NONE: + default: + break; + } + + g_free (ctx->error_buf); + ctx->error_buf = NULL; + return; +} + +static void +gst_audio_quantize_setup_dither (AudioConvertCtx * ctx) +{ + switch (ctx->dither) { + case DITHER_TPDF_HF: + if (ctx->out.is_int) + ctx->last_random = g_new0 (gint32, ctx->out.channels); + else + ctx->last_random = g_new0 (gdouble, ctx->out.channels); + break; + case DITHER_RPDF: + case DITHER_TPDF: + ctx->last_random = NULL; + break; + case DITHER_NONE: + default: + ctx->last_random = NULL; + break; + } + return; +} + +static void +gst_audio_quantize_free_dither (AudioConvertCtx * ctx) +{ + g_free (ctx->last_random); + + return; +} + +static void +gst_audio_quantize_setup_quantize_func (AudioConvertCtx * ctx) +{ + gint index = 0; + + if (!ctx->out.is_int) { + ctx->quantize = NULL; + return; + } + + if (ctx->ns == NOISE_SHAPING_NONE) { + index += ctx->dither; + index += (ctx->out.sign) ? 0 : 4; + } else { + index += 8 + (4 * ctx->dither); + index += ctx->ns - 1; + } + + ctx->quantize = quantize_funcs[index]; +} + +gboolean +gst_audio_quantize_setup (AudioConvertCtx * ctx) +{ + gst_audio_quantize_setup_dither (ctx); + gst_audio_quantize_setup_noise_shaping (ctx); + gst_audio_quantize_setup_quantize_func (ctx); + + return TRUE; +} + +void +gst_audio_quantize_free (AudioConvertCtx * ctx) +{ + gst_audio_quantize_free_dither (ctx); + gst_audio_quantize_free_noise_shaping (ctx); +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.h new file mode 100644 index 0000000..b7e5cce --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstaudioquantize.h @@ -0,0 +1,34 @@ +/* GStreamer + * Copyright (C) 2007 Sebastian Dröge + * + * gstaudioquantize.h: quantizes audio to the target format and optionally + * applies dithering and noise shaping. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include "audioconvert.h" + +#ifndef __GST_AUDIO_QUANTIZE_H__ +#define __GST_AUDIO_QUANTIZE_H__ + +gboolean gst_audio_quantize_setup (AudioConvertCtx * ctx); +void gst_audio_quantize_reset (AudioConvertCtx * ctx); +void gst_audio_quantize_free (AudioConvertCtx * ctx); + + +#endif /* __GST_AUDIO_QUANTIZE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.c new file mode 100644 index 0000000..055f28d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.c @@ -0,0 +1,742 @@ +/* GStreamer + * Copyright (C) 2004 Ronald Bultje + * Copyright (C) 2008 Sebastian Dröge + * + * gstchannelmix.c: setup of channel conversion matrices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +#include "gstchannelmix.h" + +/* + * Channel matrix functions. + */ + +void +gst_channel_mix_unset_matrix (AudioConvertCtx * this) +{ + gint i; + + /* don't access if nothing there */ + if (!this->matrix) + return; + + /* free */ + for (i = 0; i < this->in.channels; i++) + g_free (this->matrix[i]); + g_free (this->matrix); + + this->matrix = NULL; + g_free (this->tmp); + this->tmp = NULL; +} + +/* + * Detect and fill in identical channels. E.g. + * forward the left/right front channels in a + * 5.1 to 2.0 conversion. + */ + +static void +gst_channel_mix_fill_identical (AudioConvertCtx * this) +{ + gint ci, co; + + /* Apart from the compatible channel assignments, we can also have + * same channel assignments. This is much simpler, we simply copy + * the value from source to dest! */ + for (co = 0; co < this->out.channels; co++) { + /* find a channel in input with same position */ + for (ci = 0; ci < this->in.channels; ci++) { + if (this->in.pos[ci] == this->out.pos[co]) { + this->matrix[ci][co] = 1.0; + } + } + } +} + +/* + * Detect and fill in compatible channels. E.g. + * forward left/right front to mono (or the other + * way around) when going from 2.0 to 1.0. + */ + +static void +gst_channel_mix_fill_compatible (AudioConvertCtx * this) +{ + /* Conversions from one-channel to compatible two-channel configs */ + struct + { + GstAudioChannelPosition pos1[2]; + GstAudioChannelPosition pos2[1]; + } conv[] = { + /* front: mono <-> stereo */ + { { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}}, + /* front center: 2 <-> 1 */ + { { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER}, { + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER}}, + /* rear: 2 <-> 1 */ + { { + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT}, { + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER}}, { { + GST_AUDIO_CHANNEL_POSITION_INVALID}} + }; + gint c; + + /* conversions from compatible (but not the same) channel schemes */ + for (c = 0; conv[c].pos1[0] != GST_AUDIO_CHANNEL_POSITION_INVALID; c++) { + gint pos1_0 = -1, pos1_1 = -1, pos1_2 = -1; + gint pos2_0 = -1, pos2_1 = -1, pos2_2 = -1; + gint n; + + for (n = 0; n < this->in.channels; n++) { + if (this->in.pos[n] == conv[c].pos1[0]) + pos1_0 = n; + else if (this->in.pos[n] == conv[c].pos1[1]) + pos1_1 = n; + else if (this->in.pos[n] == conv[c].pos2[0]) + pos1_2 = n; + } + for (n = 0; n < this->out.channels; n++) { + if (this->out.pos[n] == conv[c].pos1[0]) + pos2_0 = n; + else if (this->out.pos[n] == conv[c].pos1[1]) + pos2_1 = n; + else if (this->out.pos[n] == conv[c].pos2[0]) + pos2_2 = n; + } + + /* The general idea here is to fill in channels from the same position + * as good as possible. This means mixing left<->center and right<->center. + */ + + /* left -> center */ + if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 == -1 && pos2_2 != -1) + this->matrix[pos1_0][pos2_2] = 1.0; + else if (pos1_0 != -1 && pos1_2 != -1 && pos2_0 == -1 && pos2_2 != -1) + this->matrix[pos1_0][pos2_2] = 0.5; + else if (pos1_0 != -1 && pos1_2 == -1 && pos2_0 != -1 && pos2_2 != -1) + this->matrix[pos1_0][pos2_2] = 1.0; + + /* right -> center */ + if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 == -1 && pos2_2 != -1) + this->matrix[pos1_1][pos2_2] = 1.0; + else if (pos1_1 != -1 && pos1_2 != -1 && pos2_1 == -1 && pos2_2 != -1) + this->matrix[pos1_1][pos2_2] = 0.5; + else if (pos1_1 != -1 && pos1_2 == -1 && pos2_1 != -1 && pos2_2 != -1) + this->matrix[pos1_1][pos2_2] = 1.0; + + /* center -> left */ + if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 == -1 && pos2_0 != -1) + this->matrix[pos1_2][pos2_0] = 1.0; + else if (pos1_2 != -1 && pos1_0 != -1 && pos2_2 == -1 && pos2_0 != -1) + this->matrix[pos1_2][pos2_0] = 0.5; + else if (pos1_2 != -1 && pos1_0 == -1 && pos2_2 != -1 && pos2_0 != -1) + this->matrix[pos1_2][pos2_0] = 1.0; + + /* center -> right */ + if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 == -1 && pos2_1 != -1) + this->matrix[pos1_2][pos2_1] = 1.0; + else if (pos1_2 != -1 && pos1_1 != -1 && pos2_2 == -1 && pos2_1 != -1) + this->matrix[pos1_2][pos2_1] = 0.5; + else if (pos1_2 != -1 && pos1_1 == -1 && pos2_2 != -1 && pos2_1 != -1) + this->matrix[pos1_2][pos2_1] = 1.0; + } +} + +/* + * Detect and fill in channels not handled by the + * above two, e.g. center to left/right front in + * 5.1 to 2.0 (or the other way around). + * + * Unfortunately, limited to static conversions + * for now. + */ + +static void +gst_channel_mix_detect_pos (AudioConvertFmt * caps, + gint * f, gboolean * has_f, + gint * c, gboolean * has_c, gint * r, gboolean * has_r, + gint * s, gboolean * has_s, gint * b, gboolean * has_b) +{ + gint n; + + for (n = 0; n < caps->channels; n++) { + switch (caps->pos[n]) { + case GST_AUDIO_CHANNEL_POSITION_FRONT_MONO: + f[1] = n; + *has_f = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: + f[0] = n; + *has_f = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: + f[2] = n; + *has_f = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: + c[1] = n; + *has_c = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: + c[0] = n; + *has_c = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: + c[2] = n; + *has_c = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: + r[1] = n; + *has_r = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: + r[0] = n; + *has_r = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: + r[2] = n; + *has_r = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: + s[0] = n; + *has_s = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: + s[2] = n; + *has_s = TRUE; + break; + case GST_AUDIO_CHANNEL_POSITION_LFE: + *has_b = TRUE; + b[1] = n; + break; + default: + break; + } + } +} + +static void +gst_channel_mix_fill_one_other (gfloat ** matrix, + AudioConvertFmt * from_caps, gint * from_idx, + AudioConvertFmt * to_caps, gint * to_idx, gfloat ratio) +{ + + /* src & dst have center => passthrough */ + if (from_idx[1] != -1 && to_idx[1] != -1) { + matrix[from_idx[1]][to_idx[1]] = ratio; + } + + /* src & dst have left => passthrough */ + if (from_idx[0] != -1 && to_idx[0] != -1) { + matrix[from_idx[0]][to_idx[0]] = ratio; + } + + /* src & dst have right => passthrough */ + if (from_idx[2] != -1 && to_idx[2] != -1) { + matrix[from_idx[2]][to_idx[2]] = ratio; + } + + /* src has left & dst has center => put into center */ + if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] != -1) { + matrix[from_idx[0]][to_idx[1]] = 0.5 * ratio; + } else if (from_idx[0] != -1 && to_idx[1] != -1 && from_idx[1] == -1) { + matrix[from_idx[0]][to_idx[1]] = ratio; + } + + /* src has right & dst has center => put into center */ + if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] != -1) { + matrix[from_idx[2]][to_idx[1]] = 0.5 * ratio; + } else if (from_idx[2] != -1 && to_idx[1] != -1 && from_idx[1] == -1) { + matrix[from_idx[2]][to_idx[1]] = ratio; + } + + /* src has center & dst has left => passthrough */ + if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] != -1) { + matrix[from_idx[1]][to_idx[0]] = 0.5 * ratio; + } else if (from_idx[1] != -1 && to_idx[0] != -1 && from_idx[0] == -1) { + matrix[from_idx[1]][to_idx[0]] = ratio; + } + + /* src has center & dst has right => passthrough */ + if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] != -1) { + matrix[from_idx[1]][to_idx[2]] = 0.5 * ratio; + } else if (from_idx[1] != -1 && to_idx[2] != -1 && from_idx[2] == -1) { + matrix[from_idx[1]][to_idx[2]] = ratio; + } +} + +#define RATIO_CENTER_FRONT (1.0 / sqrt (2.0)) +#define RATIO_CENTER_SIDE (1.0 / 2.0) +#define RATIO_CENTER_REAR (1.0 / sqrt (8.0)) + +#define RATIO_FRONT_CENTER (1.0 / sqrt (2.0)) +#define RATIO_FRONT_SIDE (1.0 / sqrt (2.0)) +#define RATIO_FRONT_REAR (1.0 / 2.0) + +#define RATIO_SIDE_CENTER (1.0 / 2.0) +#define RATIO_SIDE_FRONT (1.0 / sqrt (2.0)) +#define RATIO_SIDE_REAR (1.0 / sqrt (2.0)) + +#define RATIO_CENTER_BASS (1.0 / sqrt (2.0)) +#define RATIO_FRONT_BASS (1.0) +#define RATIO_SIDE_BASS (1.0 / sqrt (2.0)) +#define RATIO_REAR_BASS (1.0 / sqrt (2.0)) + +static void +gst_channel_mix_fill_others (AudioConvertCtx * this) +{ + gboolean in_has_front = FALSE, out_has_front = FALSE, + in_has_center = FALSE, out_has_center = FALSE, + in_has_rear = FALSE, out_has_rear = FALSE, + in_has_side = FALSE, out_has_side = FALSE, + in_has_bass = FALSE, out_has_bass = FALSE; + /* LEFT, RIGHT, MONO */ + gint in_f[3] = { -1, -1, -1 }; + gint out_f[3] = { -1, -1, -1 }; + /* LOC, ROC, CENTER */ + gint in_c[3] = { -1, -1, -1 }; + gint out_c[3] = { -1, -1, -1 }; + /* RLEFT, RRIGHT, RCENTER */ + gint in_r[3] = { -1, -1, -1 }; + gint out_r[3] = { -1, -1, -1 }; + /* SLEFT, INVALID, SRIGHT */ + gint in_s[3] = { -1, -1, -1 }; + gint out_s[3] = { -1, -1, -1 }; + /* INVALID, LFE, INVALID */ + gint in_b[3] = { -1, -1, -1 }; + gint out_b[3] = { -1, -1, -1 }; + + /* First see where (if at all) the various channels from/to + * which we want to convert are located in our matrix/array. */ + gst_channel_mix_detect_pos (&this->in, + in_f, &in_has_front, + in_c, &in_has_center, in_r, &in_has_rear, + in_s, &in_has_side, in_b, &in_has_bass); + gst_channel_mix_detect_pos (&this->out, + out_f, &out_has_front, + out_c, &out_has_center, out_r, &out_has_rear, + out_s, &out_has_side, out_b, &out_has_bass); + + /* The general idea here is: + * - if the source has a channel that the destination doesn't have mix + * it into the nearest available destination channel + * - if the destination has a channel that the source doesn't have mix + * the nearest source channel into the destination channel + * + * The ratio for the mixing becomes lower as the distance between the + * channels gets larger + */ + + /* center <-> front/side/rear */ + if (!in_has_center && in_has_front && out_has_center) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT); + } else if (!in_has_center && !in_has_front && in_has_side && out_has_center) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_c, RATIO_CENTER_SIDE); + } else if (!in_has_center && !in_has_front && !in_has_side && in_has_rear + && out_has_center) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, + out_c, RATIO_CENTER_REAR); + } else if (in_has_center && !out_has_center && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT); + } else if (in_has_center && !out_has_center && !out_has_front && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_c, &this->out, out_s, RATIO_CENTER_SIDE); + } else if (in_has_center && !out_has_center && !out_has_front && !out_has_side + && out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, + out_r, RATIO_CENTER_REAR); + } + + /* front <-> center/side/rear */ + if (!in_has_front && in_has_center && !in_has_side && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_c, &this->out, out_f, RATIO_CENTER_FRONT); + } else if (!in_has_front && !in_has_center && in_has_side && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE); + } else if (!in_has_front && in_has_center && in_has_side && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_c, &this->out, out_f, 0.5 * RATIO_CENTER_FRONT); + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE); + } else if (!in_has_front && !in_has_center && !in_has_side && in_has_rear + && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, + out_f, RATIO_FRONT_REAR); + } else if (in_has_front && out_has_center && !out_has_side && !out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_c, RATIO_CENTER_FRONT); + } else if (in_has_front && !out_has_center && out_has_side && !out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE); + } else if (in_has_front && out_has_center && out_has_side && !out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_c, 0.5 * RATIO_CENTER_FRONT); + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE); + } else if (in_has_front && !out_has_center && !out_has_side && !out_has_front + && out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_f, &this->out, + out_r, RATIO_FRONT_REAR); + } + + /* side <-> center/front/rear */ + if (!in_has_side && in_has_front && !in_has_rear && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_s, RATIO_FRONT_SIDE); + } else if (!in_has_side && !in_has_front && in_has_rear && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR); + } else if (!in_has_side && in_has_front && in_has_rear && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_s, 0.5 * RATIO_FRONT_SIDE); + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_r, &this->out, out_s, 0.5 * RATIO_SIDE_REAR); + } else if (!in_has_side && !in_has_front && !in_has_rear && in_has_center + && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, + out_s, RATIO_CENTER_SIDE); + } else if (in_has_side && out_has_front && !out_has_rear && !out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_f, RATIO_FRONT_SIDE); + } else if (in_has_side && !out_has_front && out_has_rear && !out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR); + } else if (in_has_side && out_has_front && out_has_rear && !out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_f, 0.5 * RATIO_FRONT_SIDE); + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_r, 0.5 * RATIO_SIDE_REAR); + } else if (in_has_side && !out_has_front && !out_has_rear && out_has_center + && !out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_s, &this->out, + out_c, RATIO_CENTER_SIDE); + } + + /* rear <-> center/front/side */ + if (!in_has_rear && in_has_side && out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_r, RATIO_SIDE_REAR); + } else if (!in_has_rear && !in_has_side && in_has_front && out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_r, RATIO_FRONT_REAR); + } else if (!in_has_rear && !in_has_side && !in_has_front && in_has_center + && out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_c, &this->out, + out_r, RATIO_CENTER_REAR); + } else if (in_has_rear && !out_has_rear && out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_r, &this->out, out_s, RATIO_SIDE_REAR); + } else if (in_has_rear && !out_has_rear && !out_has_side && out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_r, &this->out, out_f, RATIO_FRONT_REAR); + } else if (in_has_rear && !out_has_rear && !out_has_side && !out_has_front + && out_has_center) { + gst_channel_mix_fill_one_other (this->matrix, &this->in, in_r, &this->out, + out_c, RATIO_CENTER_REAR); + } + + /* bass <-> any */ + if (in_has_bass && !out_has_bass) { + if (out_has_center) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_b, &this->out, out_c, RATIO_CENTER_BASS); + } + if (out_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_b, &this->out, out_f, RATIO_FRONT_BASS); + } + if (out_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_b, &this->out, out_s, RATIO_SIDE_BASS); + } + if (out_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_b, &this->out, out_r, RATIO_REAR_BASS); + } + } else if (!in_has_bass && out_has_bass) { + if (in_has_center) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_c, &this->out, out_b, RATIO_CENTER_BASS); + } + if (in_has_front) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_f, &this->out, out_b, RATIO_FRONT_BASS); + } + if (in_has_side) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_s, &this->out, out_b, RATIO_REAR_BASS); + } + if (in_has_rear) { + gst_channel_mix_fill_one_other (this->matrix, + &this->in, in_r, &this->out, out_b, RATIO_REAR_BASS); + } + } +} + +/* + * Normalize output values. + */ + +static void +gst_channel_mix_fill_normalize (AudioConvertCtx * this) +{ + gfloat sum, top = 0; + gint i, j; + + for (j = 0; j < this->out.channels; j++) { + /* calculate sum */ + sum = 0.0; + for (i = 0; i < this->in.channels; i++) { + sum += fabs (this->matrix[i][j]); + } + if (sum > top) { + top = sum; + } + } + + /* normalize to this */ + if (top == 0.0) + return; + + for (j = 0; j < this->out.channels; j++) { + for (i = 0; i < this->in.channels; i++) { + this->matrix[i][j] /= top; + } + } +} + +static gboolean +gst_channel_mix_fill_special (AudioConvertCtx * this) +{ + AudioConvertFmt *in = &this->in, *out = &this->out; + + /* Special, standard conversions here */ + + /* Mono<->Stereo, just a fast-path */ + if (in->channels == 2 && out->channels == 1 && + ((in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT && + in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) || + (in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT && + in->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) && + out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) { + this->matrix[0][0] = 0.5; + this->matrix[1][0] = 0.5; + return TRUE; + } else if (in->channels == 1 && out->channels == 2 && + ((out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT && + out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT) || + (out->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT && + out->pos[1] == GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT)) && + in->pos[0] == GST_AUDIO_CHANNEL_POSITION_FRONT_MONO) { + this->matrix[0][0] = 1.0; + this->matrix[0][1] = 1.0; + return TRUE; + } + + /* TODO: 5.1 <-> Stereo and other standard conversions */ + + return FALSE; +} + +/* + * Automagically generate conversion matrix. + */ + +static void +gst_channel_mix_fill_matrix (AudioConvertCtx * this) +{ + if (gst_channel_mix_fill_special (this)) + return; + + gst_channel_mix_fill_identical (this); + + if (!this->in.unpositioned_layout) { + gst_channel_mix_fill_compatible (this); + gst_channel_mix_fill_others (this); + gst_channel_mix_fill_normalize (this); + } +} + +/* only call after this->out and this->in are filled in */ +void +gst_channel_mix_setup_matrix (AudioConvertCtx * this) +{ + gint i, j; + + /* don't lose memory */ + gst_channel_mix_unset_matrix (this); + + /* temp storage */ + if (this->in.is_int || this->out.is_int) { + this->tmp = (gpointer) g_new (gint32, this->out.channels); + } else { + this->tmp = (gpointer) g_new (gdouble, this->out.channels); + } + + /* allocate */ + this->matrix = g_new0 (gfloat *, this->in.channels); + for (i = 0; i < this->in.channels; i++) { + this->matrix[i] = g_new (gfloat, this->out.channels); + for (j = 0; j < this->out.channels; j++) + this->matrix[i][j] = 0.; + } + + /* setup the matrix' internal values */ + gst_channel_mix_fill_matrix (this); + +#ifndef GST_DISABLE_GST_DEBUG + /* debug */ + { + GString *s; + s = g_string_new ("Matrix for"); + g_string_append_printf (s, " %d -> %d: ", + this->in.channels, this->out.channels); + g_string_append (s, "{"); + for (i = 0; i < this->in.channels; i++) { + if (i != 0) + g_string_append (s, ","); + g_string_append (s, " {"); + for (j = 0; j < this->out.channels; j++) { + if (j != 0) + g_string_append (s, ","); + g_string_append_printf (s, " %f", this->matrix[i][j]); + } + g_string_append (s, " }"); + } + g_string_append (s, " }"); + GST_DEBUG ("%s", s->str); + g_string_free (s, TRUE); + } +#endif +} + +gboolean +gst_channel_mix_passthrough (AudioConvertCtx * this) +{ + gint i; + + /* only NxN matrices can be identities */ + if (this->in.channels != this->out.channels) + return FALSE; + + /* this assumes a normalized matrix */ + for (i = 0; i < this->in.channels; i++) + if (this->matrix[i][i] != 1.) + return FALSE; + + return TRUE; +} + +/* IMPORTANT: out_data == in_data is possible, make sure to not overwrite data + * you might need later on! */ +void +gst_channel_mix_mix_int (AudioConvertCtx * this, + gint32 * in_data, gint32 * out_data, gint samples) +{ + gint in, out, n; + gint64 res; + gboolean backwards; + gint inchannels, outchannels; + gint32 *tmp = (gint32 *) this->tmp; + + g_return_if_fail (this->matrix != NULL); + g_return_if_fail (this->tmp != NULL); + + inchannels = this->in.channels; + outchannels = this->out.channels; + backwards = outchannels > inchannels; + + /* FIXME: use liboil here? */ + for (n = (backwards ? samples - 1 : 0); n < samples && n >= 0; + backwards ? n-- : n++) { + for (out = 0; out < outchannels; out++) { + /* convert */ + res = 0; + for (in = 0; in < inchannels; in++) { + res += in_data[n * inchannels + in] * this->matrix[in][out]; + } + + /* clip (shouldn't we use doubles instead as intermediate format?) */ + if (res < G_MININT32) + res = G_MININT32; + else if (res > G_MAXINT32) + res = G_MAXINT32; + tmp[out] = res; + } + memcpy (&out_data[n * outchannels], this->tmp, + sizeof (gint32) * outchannels); + } +} + +void +gst_channel_mix_mix_float (AudioConvertCtx * this, + gdouble * in_data, gdouble * out_data, gint samples) +{ + gint in, out, n; + gdouble res; + gboolean backwards; + gint inchannels, outchannels; + gdouble *tmp = (gdouble *) this->tmp; + + g_return_if_fail (this->matrix != NULL); + g_return_if_fail (this->tmp != NULL); + + inchannels = this->in.channels; + outchannels = this->out.channels; + backwards = outchannels > inchannels; + + /* FIXME: use liboil here? */ + for (n = (backwards ? samples - 1 : 0); n < samples && n >= 0; + backwards ? n-- : n++) { + for (out = 0; out < outchannels; out++) { + /* convert */ + res = 0.0; + for (in = 0; in < inchannels; in++) { + res += in_data[n * inchannels + in] * this->matrix[in][out]; + } + + /* clip (shouldn't we use doubles instead as intermediate format?) */ + if (res < -1.0) + res = -1.0; + else if (res > 1.0) + res = 1.0; + tmp[out] = res; + } + memcpy (&out_data[n * outchannels], this->tmp, + sizeof (gdouble) * outchannels); + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.h new file mode 100644 index 0000000..e02748e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstchannelmix.h @@ -0,0 +1,56 @@ +/* GStreamer + * Copyright (C) 2004 Ronald Bultje + * + * gstchannelmix.h: setup of channel conversion matrices + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_CHANNEL_MIX_H__ +#define __GST_CHANNEL_MIX_H__ + +#include +#include "audioconvert.h" + +/* + * Delete channel mixer matrix. + */ +void gst_channel_mix_unset_matrix (AudioConvertCtx * this); + +/* + * Setup channel mixer matrix. + */ +void gst_channel_mix_setup_matrix (AudioConvertCtx * this); + +/* + * Checks for passthrough (= identity matrix). + */ +gboolean gst_channel_mix_passthrough (AudioConvertCtx * this); + +/* + * Do actual mixing. + */ +void gst_channel_mix_mix_int (AudioConvertCtx * this, + gint32 * in_data, + gint32 * out_data, + gint samples); + +void gst_channel_mix_mix_float (AudioConvertCtx * this, + gdouble * in_data, + gdouble * out_data, + gint samples); + +#endif /* __GST_CHANNEL_MIX_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/gstfastrandom.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstfastrandom.h new file mode 100644 index 0000000..022b87e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/gstfastrandom.h @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) 2008 Sebastian Dröge + * + * gstfastrandom.h: Fast, bad PNRG + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#ifndef __GST_FAST_RANDOM__ +#define __GST_FAST_RANDOM__ + +/* transform [0..2^32] -> [0..1] */ +#define GST_RAND_DOUBLE_TRANSFORM 2.3283064365386962890625e-10 + +/* This is the base function, implementing a linear congruential generator + * and returning a pseudo random number between 0 and 2^32 - 1. + */ +static inline guint32 +gst_fast_random_uint32 (void) +{ + static guint32 state = 0xdeadbeef; + + return (state = state * 1103515245 + 12345); +} + +static inline guint32 +gst_fast_random_uint32_range (gint32 start, gint32 end) +{ + guint64 tmp = gst_fast_random_uint32 (); + + tmp = (tmp * (end - start)) / G_MAXUINT32 + start; + + return (guint32) tmp; +} + +static inline gint32 +gst_fast_random_int32 (void) +{ + return (gint32) gst_fast_random_uint32 (); +} + +static inline gint32 +gst_fast_random_int32_range (gint32 start, gint32 end) +{ + gint64 tmp = gst_fast_random_uint32 (); + + tmp = (tmp * (end - start)) / G_MAXUINT32 + start; + + return (gint32) tmp; +} + +static inline gdouble +gst_fast_random_double (void) +{ + gdouble ret; + + ret = gst_fast_random_uint32 () * GST_RAND_DOUBLE_TRANSFORM; + ret = (ret + gst_fast_random_uint32 ()) * GST_RAND_DOUBLE_TRANSFORM; + + if (ret >= 1.0) + return gst_fast_random_double (); + + return ret; +} + +static inline gdouble +gst_fast_random_double_range (gdouble start, gdouble end) +{ + return gst_fast_random_double () * (end - start) + start; +} + +#undef GST_RAND_DOUBLE_TRANSFORM + +#endif /* __GST_FAST_RANDOM__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.c b/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.c new file mode 100644 index 0000000..45882dc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.c @@ -0,0 +1,51 @@ +/* GStreamer audio conversion plugin + * Copyright (C) 2004 Andy Wingo + * + * plugin.c: the stubs for the audioconvert plugin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "plugin.h" + +#include +#include "gstaudioconvertorc.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_audio_convert_orc_init (); + + /* ensure GstAudioChannelPosition type is registered */ + if (!gst_audio_channel_position_get_type ()) + return FALSE; + + if (!gst_element_register (plugin, "audioconvert", + GST_RANK_PRIMARY, gst_audio_convert_get_type ())) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "audioconvert", + "Convert audio to different formats", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.h b/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.h new file mode 100644 index 0000000..5aa3ec4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioconvert/plugin.h @@ -0,0 +1,35 @@ +/* GStreamer buffer-frames conversion plugin + * Copyright (C) 2004 Andy Wingo + * + * plugin.h: the stubs for the buffer-frames-convert plugin + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLUGIN_AUDIO_CONVERT_H__ +#define __GST_PLUGIN_AUDIO_CONVERT_H__ + + +#include + +G_BEGIN_DECLS + +GType gst_audio_convert_get_type (void); + +G_END_DECLS + +#endif /* __GST_PLUGIN_AUDIO_CONVERT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audiorate/Makefile.am b/gst-plugins-base-subtitles0.10/gst/audiorate/Makefile.am new file mode 100644 index 0000000..72c3355 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiorate/Makefile.am @@ -0,0 +1,23 @@ +noinst_HEADERS = gstaudiorate.h + +plugin_LTLIBRARIES = libgstaudiorate.la + +libgstaudiorate_la_SOURCES = gstaudiorate.c +libgstaudiorate_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstaudiorate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstaudiorate_la_LIBADD = $(GST_LIBS) +libgstaudiorate_la_LIBTOOLFLAGS = --tag=disable-static + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstaudiorate -:SHARED libgstaudiorate \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstaudiorate_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudiorate_la_CFLAGS) \ + -:LDFLAGS $(libgstaudiorate_la_LDFLAGS) \ + $(libgstaudiorate_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/audiorate/audiorate.vcproj b/gst-plugins-base-subtitles0.10/gst/audiorate/audiorate.vcproj new file mode 100644 index 0000000..22b8737 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiorate/audiorate.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.c b/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.c new file mode 100644 index 0000000..40d3467 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.c @@ -0,0 +1,877 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-audiorate + * @see_also: #GstVideoRate + * + * This element takes an incoming stream of timestamped raw audio frames and + * produces a perfect stream by inserting or dropping samples as needed. + * + * This operation may be of use to link to elements that require or otherwise + * implicitly assume a perfect stream as they do not store timestamps, + * but derive this by some means (e.g. bitrate for some AVI cases). + * + * The properties #GstAudioRate:in, #GstAudioRate:out, #GstAudioRate:add + * and #GstAudioRate:drop can be read to obtain information about number of + * input samples, output samples, dropped samples (i.e. the number of unused + * input samples) and inserted samples (i.e. the number of samples added to + * stream). + * + * When the #GstAudioRate:silent property is set to FALSE, a GObject property + * notification will be emitted whenever one of the #GstAudioRate:add or + * #GstAudioRate:drop values changes. + * This can potentially cause performance degradation. + * Note that property notification will happen from the streaming thread, so + * applications should be prepared for this. + * + * If the #GstAudioRate:tolerance property is non-zero, and an incoming buffer's + * timestamp deviates less than the property indicates from what would make a + * 'perfect time', then no samples will be added or dropped. + * Note that the output is still guaranteed to be a perfect stream, which means + * that the incoming data is then simply shifted (by less than the indicated + * tolerance) to a perfect time. + * + * + * Example pipelines + * |[ + * gst-launch -v alsasrc ! audiorate ! wavenc ! filesink location=alsa.wav + * ]| Capture audio from an ALSA device, and turn it into a perfect stream + * for saving in a raw audio file. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstaudiorate.h" + +#define GST_CAT_DEFAULT audio_rate_debug +GST_DEBUG_CATEGORY_STATIC (audio_rate_debug); + +/* GstAudioRate signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_SILENT TRUE +#define DEFAULT_TOLERANCE 0 +#define DEFAULT_SKIP_TO_FIRST FALSE + +enum +{ + ARG_0, + ARG_IN, + ARG_OUT, + ARG_ADD, + ARG_DROP, + ARG_SILENT, + ARG_TOLERANCE, + ARG_SKIP_TO_FIRST +}; + +static GstStaticPadTemplate gst_audio_rate_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS ";" + GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) + ); + +static GstStaticPadTemplate gst_audio_rate_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_AUDIO_INT_PAD_TEMPLATE_CAPS ";" + GST_AUDIO_FLOAT_PAD_TEMPLATE_CAPS) + ); + +static void gst_audio_rate_base_init (gpointer g_class); +static void gst_audio_rate_class_init (GstAudioRateClass * klass); +static void gst_audio_rate_init (GstAudioRate * audiorate); +static gboolean gst_audio_rate_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_audio_rate_src_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_audio_rate_chain (GstPad * pad, GstBuffer * buf); + +static void gst_audio_rate_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_audio_rate_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_audio_rate_change_state (GstElement * element, + GstStateChange transition); + +static GstElementClass *parent_class = NULL; + +/*static guint gst_audio_rate_signals[LAST_SIGNAL] = { 0 }; */ + +static GParamSpec *pspec_drop = NULL; +static GParamSpec *pspec_add = NULL; + +static GType +gst_audio_rate_get_type (void) +{ + static GType audio_rate_type = 0; + + if (!audio_rate_type) { + static const GTypeInfo audio_rate_info = { + sizeof (GstAudioRateClass), + gst_audio_rate_base_init, + NULL, + (GClassInitFunc) gst_audio_rate_class_init, + NULL, + NULL, + sizeof (GstAudioRate), + 0, + (GInstanceInitFunc) gst_audio_rate_init, + }; + + audio_rate_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstAudioRate", &audio_rate_info, 0); + } + + return audio_rate_type; +} + +static void +gst_audio_rate_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Audio rate adjuster", "Filter/Effect/Audio", + "Drops/duplicates/adjusts timestamps on audio samples to make a perfect stream", + "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_audio_rate_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_audio_rate_src_template)); +} + +static void +gst_audio_rate_class_init (GstAudioRateClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = gst_audio_rate_set_property; + object_class->get_property = gst_audio_rate_get_property; + + g_object_class_install_property (object_class, ARG_IN, + g_param_spec_uint64 ("in", "In", + "Number of input samples", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, ARG_OUT, + g_param_spec_uint64 ("out", "Out", "Number of output samples", 0, + G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + pspec_add = g_param_spec_uint64 ("add", "Add", "Number of added samples", + 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, ARG_ADD, pspec_add); + pspec_drop = g_param_spec_uint64 ("drop", "Drop", "Number of dropped samples", + 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, ARG_DROP, pspec_drop); + g_object_class_install_property (object_class, ARG_SILENT, + g_param_spec_boolean ("silent", "silent", + "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstAudioRate:tolerance + * + * The difference between incoming timestamp and next timestamp must exceed + * the given value for audiorate to add or drop samples. + * + * Since: 0.10.26 + **/ + g_object_class_install_property (object_class, ARG_TOLERANCE, + g_param_spec_uint64 ("tolerance", "tolerance", + "Only act if timestamp jitter/imperfection exceeds indicated tolerance (ns)", + 0, G_MAXUINT64, DEFAULT_TOLERANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstAudioRate:skip-to-first: + * + * Don't produce buffers before the first one we receive. + * + * Since: 0.10.33 + **/ + g_object_class_install_property (object_class, ARG_SKIP_TO_FIRST, + g_param_spec_boolean ("skip-to-first", "Skip to first buffer", + "Don't produce buffers before the first one we receive", + DEFAULT_SKIP_TO_FIRST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + element_class->change_state = gst_audio_rate_change_state; +} + +static void +gst_audio_rate_reset (GstAudioRate * audiorate) +{ + audiorate->next_offset = -1; + audiorate->next_ts = -1; + audiorate->discont = TRUE; + gst_segment_init (&audiorate->sink_segment, GST_FORMAT_UNDEFINED); + gst_segment_init (&audiorate->src_segment, GST_FORMAT_TIME); + + GST_DEBUG_OBJECT (audiorate, "handle reset"); +} + +static gboolean +gst_audio_rate_setcaps (GstPad * pad, GstCaps * caps) +{ + GstAudioRate *audiorate; + GstStructure *structure; + GstPad *otherpad; + gboolean ret = FALSE; + gint channels, width, rate; + + audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad)); + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "channels", &channels)) + goto wrong_caps; + if (!gst_structure_get_int (structure, "width", &width)) + goto wrong_caps; + if (!gst_structure_get_int (structure, "rate", &rate)) + goto wrong_caps; + + audiorate->bytes_per_sample = channels * (width / 8); + if (audiorate->bytes_per_sample == 0) + goto wrong_format; + + audiorate->rate = rate; + + /* the format is correct, configure caps on other pad */ + otherpad = (pad == audiorate->srcpad) ? audiorate->sinkpad : + audiorate->srcpad; + + ret = gst_pad_set_caps (otherpad, caps); + +done: + gst_object_unref (audiorate); + return ret; + + /* ERRORS */ +wrong_caps: + { + GST_DEBUG_OBJECT (audiorate, "could not get channels/width from caps"); + goto done; + } +wrong_format: + { + GST_DEBUG_OBJECT (audiorate, "bytes_per_samples gave 0"); + goto done; + } +} + +static void +gst_audio_rate_init (GstAudioRate * audiorate) +{ + audiorate->sinkpad = + gst_pad_new_from_static_template (&gst_audio_rate_sink_template, "sink"); + gst_pad_set_event_function (audiorate->sinkpad, gst_audio_rate_sink_event); + gst_pad_set_chain_function (audiorate->sinkpad, gst_audio_rate_chain); + gst_pad_set_setcaps_function (audiorate->sinkpad, gst_audio_rate_setcaps); + gst_pad_set_getcaps_function (audiorate->sinkpad, gst_pad_proxy_getcaps); + gst_element_add_pad (GST_ELEMENT (audiorate), audiorate->sinkpad); + + audiorate->srcpad = + gst_pad_new_from_static_template (&gst_audio_rate_src_template, "src"); + gst_pad_set_event_function (audiorate->srcpad, gst_audio_rate_src_event); + gst_pad_set_setcaps_function (audiorate->srcpad, gst_audio_rate_setcaps); + gst_pad_set_getcaps_function (audiorate->srcpad, gst_pad_proxy_getcaps); + gst_element_add_pad (GST_ELEMENT (audiorate), audiorate->srcpad); + + audiorate->in = 0; + audiorate->out = 0; + audiorate->drop = 0; + audiorate->add = 0; + audiorate->silent = DEFAULT_SILENT; + audiorate->tolerance = DEFAULT_TOLERANCE; +} + +static void +gst_audio_rate_fill_to_time (GstAudioRate * audiorate, GstClockTime time) +{ + GstBuffer *buf; + + GST_DEBUG_OBJECT (audiorate, "next_ts: %" GST_TIME_FORMAT + ", filling to %" GST_TIME_FORMAT, GST_TIME_ARGS (audiorate->next_ts), + GST_TIME_ARGS (time)); + + if (!GST_CLOCK_TIME_IS_VALID (time) || + !GST_CLOCK_TIME_IS_VALID (audiorate->next_ts)) + return; + + /* feed an empty buffer to chain with the given timestamp, + * it will take care of filling */ + buf = gst_buffer_new (); + GST_BUFFER_TIMESTAMP (buf) = time; + gst_audio_rate_chain (audiorate->sinkpad, buf); +} + +static gboolean +gst_audio_rate_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstAudioRate *audiorate; + + audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (audiorate, "handling FLUSH_STOP"); + gst_audio_rate_reset (audiorate); + res = gst_pad_push_event (audiorate->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + gboolean update; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + GST_DEBUG_OBJECT (audiorate, "handle NEWSEGMENT"); + /* FIXME: bad things will likely happen if rate < 0 ... */ + if (!update) { + /* a new segment starts. We need to figure out what will be the next + * sample offset. We mark the offsets as invalid so that the _chain + * function will perform this calculation. */ + gst_audio_rate_fill_to_time (audiorate, audiorate->src_segment.stop); + audiorate->next_offset = -1; + audiorate->next_ts = -1; + } else { + gst_audio_rate_fill_to_time (audiorate, audiorate->src_segment.start); + } + + /* we accept all formats */ + gst_segment_set_newsegment_full (&audiorate->sink_segment, update, rate, + arate, format, start, stop, time); + + GST_DEBUG_OBJECT (audiorate, "updated segment: %" GST_SEGMENT_FORMAT, + &audiorate->sink_segment); + + if (format == GST_FORMAT_TIME) { + /* TIME formats can be copied to src and forwarded */ + res = gst_pad_push_event (audiorate->srcpad, event); + memcpy (&audiorate->src_segment, &audiorate->sink_segment, + sizeof (GstSegment)); + } else { + /* other formats will be handled in the _chain function */ + gst_event_unref (event); + res = TRUE; + } + break; + } + case GST_EVENT_EOS: + /* Fill segment until the end */ + if (GST_CLOCK_TIME_IS_VALID (audiorate->src_segment.stop)) + gst_audio_rate_fill_to_time (audiorate, audiorate->src_segment.stop); + res = gst_pad_push_event (audiorate->srcpad, event); + break; + default: + res = gst_pad_push_event (audiorate->srcpad, event); + break; + } + + gst_object_unref (audiorate); + + return res; +} + +static gboolean +gst_audio_rate_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstAudioRate *audiorate; + + audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_push_event (audiorate->sinkpad, event); + break; + } + + gst_object_unref (audiorate); + + return res; +} + +static gboolean +gst_audio_rate_convert (GstAudioRate * audiorate, + GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val) +{ + if (src_fmt == dest_fmt) { + *dest_val = src_val; + return TRUE; + } + + switch (src_fmt) { + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_BYTES: + *dest_val = src_val * audiorate->bytes_per_sample; + break; + case GST_FORMAT_TIME: + *dest_val = + gst_util_uint64_scale_int (src_val, GST_SECOND, audiorate->rate); + break; + default: + return FALSE;; + } + break; + case GST_FORMAT_BYTES: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + *dest_val = src_val / audiorate->bytes_per_sample; + break; + case GST_FORMAT_TIME: + *dest_val = gst_util_uint64_scale_int (src_val, GST_SECOND, + audiorate->rate * audiorate->bytes_per_sample); + break; + default: + return FALSE;; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_BYTES: + *dest_val = gst_util_uint64_scale_int (src_val, + audiorate->rate * audiorate->bytes_per_sample, GST_SECOND); + break; + case GST_FORMAT_DEFAULT: + *dest_val = + gst_util_uint64_scale_int (src_val, audiorate->rate, GST_SECOND); + break; + default: + return FALSE;; + } + break; + default: + return FALSE; + } + return TRUE; +} + + +static gboolean +gst_audio_rate_convert_segments (GstAudioRate * audiorate) +{ + GstFormat src_fmt, dst_fmt; + + src_fmt = audiorate->sink_segment.format; + dst_fmt = audiorate->src_segment.format; + +#define CONVERT_VAL(field) gst_audio_rate_convert (audiorate, \ + src_fmt, audiorate->sink_segment.field, \ + dst_fmt, &audiorate->src_segment.field); + + audiorate->sink_segment.rate = audiorate->src_segment.rate; + audiorate->sink_segment.abs_rate = audiorate->src_segment.abs_rate; + audiorate->sink_segment.flags = audiorate->src_segment.flags; + audiorate->sink_segment.applied_rate = audiorate->src_segment.applied_rate; + CONVERT_VAL (start); + CONVERT_VAL (stop); + CONVERT_VAL (time); + CONVERT_VAL (accum); + CONVERT_VAL (last_stop); +#undef CONVERT_VAL + + return TRUE; +} + +static void +gst_audio_rate_notify_drop (GstAudioRate * audiorate) +{ +#if !GLIB_CHECK_VERSION(2,26,0) + g_object_notify ((GObject *) audiorate, "drop"); +#else + g_object_notify_by_pspec ((GObject *) audiorate, pspec_drop); +#endif +} + +static void +gst_audio_rate_notify_add (GstAudioRate * audiorate) +{ +#if !GLIB_CHECK_VERSION(2,26,0) + g_object_notify ((GObject *) audiorate, "add"); +#else + g_object_notify_by_pspec ((GObject *) audiorate, pspec_add); +#endif +} + +static GstFlowReturn +gst_audio_rate_chain (GstPad * pad, GstBuffer * buf) +{ + GstAudioRate *audiorate; + GstClockTime in_time; + guint64 in_offset, in_offset_end, in_samples; + guint in_size; + GstFlowReturn ret = GST_FLOW_OK; + GstClockTimeDiff diff; + + audiorate = GST_AUDIO_RATE (gst_pad_get_parent (pad)); + + /* need to be negotiated now */ + if (audiorate->bytes_per_sample == 0) + goto not_negotiated; + + /* we have a new pending segment */ + if (audiorate->next_offset == -1) { + gint64 pos; + + /* update the TIME segment */ + gst_audio_rate_convert_segments (audiorate); + + /* first buffer, we are negotiated and we have a segment, calculate the + * current expected offsets based on the segment.start, which is the first + * media time of the segment and should match the media time of the first + * buffer in that segment, which is the offset expressed in DEFAULT units. + */ + /* convert first timestamp of segment to sample position */ + pos = gst_util_uint64_scale_int (audiorate->src_segment.start, + audiorate->rate, GST_SECOND); + + GST_DEBUG_OBJECT (audiorate, "resync to offset %" G_GINT64_FORMAT, pos); + + /* resyncing is a discont */ + audiorate->discont = TRUE; + + audiorate->next_offset = pos; + audiorate->next_ts = gst_util_uint64_scale_int (audiorate->next_offset, + GST_SECOND, audiorate->rate); + + if (audiorate->skip_to_first && GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + GST_DEBUG_OBJECT (audiorate, "but skipping to first buffer instead"); + pos = gst_util_uint64_scale_int (GST_BUFFER_TIMESTAMP (buf), + audiorate->rate, GST_SECOND); + GST_DEBUG_OBJECT (audiorate, "so resync to offset %" G_GINT64_FORMAT, + pos); + audiorate->next_offset = pos; + audiorate->next_ts = GST_BUFFER_TIMESTAMP (buf); + } + } + + audiorate->in++; + + in_time = GST_BUFFER_TIMESTAMP (buf); + if (in_time == GST_CLOCK_TIME_NONE) { + GST_DEBUG_OBJECT (audiorate, "no timestamp, using expected next time"); + in_time = audiorate->next_ts; + } + + in_size = GST_BUFFER_SIZE (buf); + in_samples = in_size / audiorate->bytes_per_sample; + + /* calculate the buffer offset */ + in_offset = gst_util_uint64_scale_int_round (in_time, audiorate->rate, + GST_SECOND); + in_offset_end = in_offset + in_samples; + + GST_LOG_OBJECT (audiorate, + "in_time:%" GST_TIME_FORMAT ", in_duration:%" GST_TIME_FORMAT + ", in_size:%u, in_offset:%" G_GUINT64_FORMAT ", in_offset_end:%" + G_GUINT64_FORMAT ", ->next_offset:%" G_GUINT64_FORMAT ", ->next_ts:%" + GST_TIME_FORMAT, GST_TIME_ARGS (in_time), + GST_TIME_ARGS (GST_FRAMES_TO_CLOCK_TIME (in_samples, audiorate->rate)), + in_size, in_offset, in_offset_end, audiorate->next_offset, + GST_TIME_ARGS (audiorate->next_ts)); + + diff = in_time - audiorate->next_ts; + if (diff <= (GstClockTimeDiff) audiorate->tolerance && + diff >= (GstClockTimeDiff) - audiorate->tolerance) { + /* buffer time close enough to expected time, + * so produce a perfect stream by simply 'shifting' + * it to next ts and offset and sending */ + GST_LOG_OBJECT (audiorate, "within tolerance %" GST_TIME_FORMAT, + GST_TIME_ARGS (audiorate->tolerance)); + /* The outgoing buffer's offset will be set to ->next_offset, we also + * need to adjust the offset_end value accordingly */ + in_offset_end = audiorate->next_offset + in_samples; + goto send; + } + + /* do we need to insert samples */ + if (in_offset > audiorate->next_offset) { + GstBuffer *fill; + gint fillsize; + guint64 fillsamples; + + /* We don't want to allocate a single unreasonably huge buffer - it might + be hundreds of megabytes. So, limit each output buffer to one second of + audio */ + fillsamples = in_offset - audiorate->next_offset; + + while (fillsamples > 0) { + guint64 cursamples = MIN (fillsamples, audiorate->rate); + + fillsamples -= cursamples; + fillsize = cursamples * audiorate->bytes_per_sample; + + fill = gst_buffer_new_and_alloc (fillsize); + /* FIXME, 0 might not be the silence byte for the negotiated format. */ + memset (GST_BUFFER_DATA (fill), 0, fillsize); + + GST_DEBUG_OBJECT (audiorate, "inserting %" G_GUINT64_FORMAT " samples", + cursamples); + + GST_BUFFER_OFFSET (fill) = audiorate->next_offset; + audiorate->next_offset += cursamples; + GST_BUFFER_OFFSET_END (fill) = audiorate->next_offset; + + /* Use next timestamp, then calculate following timestamp based on + * offset to get duration. Neccesary complexity to get 'perfect' + * streams */ + GST_BUFFER_TIMESTAMP (fill) = audiorate->next_ts; + audiorate->next_ts = gst_util_uint64_scale_int (audiorate->next_offset, + GST_SECOND, audiorate->rate); + GST_BUFFER_DURATION (fill) = audiorate->next_ts - + GST_BUFFER_TIMESTAMP (fill); + + /* we created this buffer to fill a gap */ + GST_BUFFER_FLAG_SET (fill, GST_BUFFER_FLAG_GAP); + /* set discont if it's pending, this is mostly done for the first buffer + * and after a flushing seek */ + if (audiorate->discont) { + GST_BUFFER_FLAG_SET (fill, GST_BUFFER_FLAG_DISCONT); + audiorate->discont = FALSE; + } + gst_buffer_set_caps (fill, GST_PAD_CAPS (audiorate->srcpad)); + + ret = gst_pad_push (audiorate->srcpad, fill); + if (ret != GST_FLOW_OK) + goto beach; + audiorate->out++; + audiorate->add += cursamples; + + if (!audiorate->silent) + gst_audio_rate_notify_add (audiorate); + } + + } else if (in_offset < audiorate->next_offset) { + /* need to remove samples */ + if (in_offset_end <= audiorate->next_offset) { + guint64 drop = in_size / audiorate->bytes_per_sample; + + audiorate->drop += drop; + + GST_DEBUG_OBJECT (audiorate, "dropping %" G_GUINT64_FORMAT " samples", + drop); + + /* we can drop the buffer completely */ + gst_buffer_unref (buf); + buf = NULL; + + if (!audiorate->silent) + gst_audio_rate_notify_drop (audiorate); + + goto beach; + } else { + guint64 truncsamples; + guint truncsize, leftsize; + GstBuffer *trunc; + + /* truncate buffer */ + truncsamples = audiorate->next_offset - in_offset; + truncsize = truncsamples * audiorate->bytes_per_sample; + leftsize = in_size - truncsize; + + trunc = gst_buffer_create_sub (buf, truncsize, leftsize); + + gst_buffer_unref (buf); + buf = trunc; + + gst_buffer_set_caps (buf, GST_PAD_CAPS (audiorate->srcpad)); + + audiorate->drop += truncsamples; + GST_DEBUG_OBJECT (audiorate, "truncating %" G_GUINT64_FORMAT " samples", + truncsamples); + + if (!audiorate->silent) + gst_audio_rate_notify_drop (audiorate); + } + } + +send: + if (GST_BUFFER_SIZE (buf) == 0) + goto beach; + + /* Now calculate parameters for whichever buffer (either the original + * or truncated one) we're pushing. */ + GST_BUFFER_OFFSET (buf) = audiorate->next_offset; + GST_BUFFER_OFFSET_END (buf) = in_offset_end; + + GST_BUFFER_TIMESTAMP (buf) = audiorate->next_ts; + audiorate->next_ts = gst_util_uint64_scale_int (in_offset_end, + GST_SECOND, audiorate->rate); + GST_BUFFER_DURATION (buf) = audiorate->next_ts - GST_BUFFER_TIMESTAMP (buf); + + if (audiorate->discont) { + /* we need to output a discont buffer, do so now */ + GST_DEBUG_OBJECT (audiorate, "marking DISCONT on output buffer"); + buf = gst_buffer_make_metadata_writable (buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + audiorate->discont = FALSE; + } else if (GST_BUFFER_IS_DISCONT (buf)) { + /* else we make everything continuous so we can safely remove the DISCONT + * flag from the buffer if there was one */ + GST_DEBUG_OBJECT (audiorate, "removing DISCONT from buffer"); + buf = gst_buffer_make_metadata_writable (buf); + GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); + } + + /* set last_stop on segment */ + gst_segment_set_last_stop (&audiorate->src_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)); + + ret = gst_pad_push (audiorate->srcpad, buf); + buf = NULL; + audiorate->out++; + + audiorate->next_offset = in_offset_end; +beach: + + if (buf) + gst_buffer_unref (buf); + + gst_object_unref (audiorate); + + return ret; + + /* ERRORS */ +not_negotiated: + { + gst_buffer_unref (buf); + + GST_ELEMENT_ERROR (audiorate, STREAM, FORMAT, + (NULL), ("pipeline error, format was not negotiated")); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static void +gst_audio_rate_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstAudioRate *audiorate = GST_AUDIO_RATE (object); + + switch (prop_id) { + case ARG_SILENT: + audiorate->silent = g_value_get_boolean (value); + break; + case ARG_TOLERANCE: + audiorate->tolerance = g_value_get_uint64 (value); + break; + case ARG_SKIP_TO_FIRST: + audiorate->skip_to_first = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_audio_rate_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstAudioRate *audiorate = GST_AUDIO_RATE (object); + + switch (prop_id) { + case ARG_IN: + g_value_set_uint64 (value, audiorate->in); + break; + case ARG_OUT: + g_value_set_uint64 (value, audiorate->out); + break; + case ARG_ADD: + g_value_set_uint64 (value, audiorate->add); + break; + case ARG_DROP: + g_value_set_uint64 (value, audiorate->drop); + break; + case ARG_SILENT: + g_value_set_boolean (value, audiorate->silent); + break; + case ARG_TOLERANCE: + g_value_set_uint64 (value, audiorate->tolerance); + break; + case ARG_SKIP_TO_FIRST: + g_value_set_boolean (value, audiorate->skip_to_first); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_audio_rate_change_state (GstElement * element, GstStateChange transition) +{ + GstAudioRate *audiorate = GST_AUDIO_RATE (element); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + audiorate->in = 0; + audiorate->out = 0; + audiorate->drop = 0; + audiorate->bytes_per_sample = 0; + audiorate->add = 0; + gst_audio_rate_reset (audiorate); + break; + default: + break; + } + + if (parent_class->change_state) + return parent_class->change_state (element, transition); + + return GST_STATE_CHANGE_SUCCESS; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (audio_rate_debug, "audiorate", 0, + "AudioRate stream fixer"); + + return gst_element_register (plugin, "audiorate", GST_RANK_NONE, + GST_TYPE_AUDIO_RATE); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "audiorate", + "Adjusts audio frames", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.h b/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.h new file mode 100644 index 0000000..e55bbcf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiorate/gstaudiorate.h @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_RATE_H__ +#define __GST_AUDIO_RATE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_AUDIO_RATE \ + (gst_audio_rate_get_type()) +#define GST_AUDIO_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_RATE,GstAudioRate)) +#define GST_AUDIO_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_RATE,GstAudioRate)) +#define GST_IS_AUDIO_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_RATE)) +#define GST_IS_AUDIO_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_RATE)) + +typedef struct _GstAudioRate GstAudioRate; +typedef struct _GstAudioRateClass GstAudioRateClass; + +/** + * GstAudioRate: + * + * Opaque data structure. + */ +struct _GstAudioRate +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + /* audio format */ + gint bytes_per_sample; + gint rate; + + /* stats */ + guint64 in, out, add, drop; + gboolean silent; + guint64 tolerance; + gboolean skip_to_first; + + /* audio state */ + guint64 next_offset; + guint64 next_ts; + + gboolean discont; + + gboolean new_segment; + /* we accept all formats on the sink */ + GstSegment sink_segment; + /* we output TIME format on the src */ + GstSegment src_segment; +}; + +struct _GstAudioRateClass +{ + GstElementClass parent_class; +}; + +G_END_DECLS + +#endif /* __GST_AUDIO_RATE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/Makefile.am b/gst-plugins-base-subtitles0.10/gst/audioresample/Makefile.am new file mode 100644 index 0000000..3464a82 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/Makefile.am @@ -0,0 +1,57 @@ +plugin_LTLIBRARIES = libgstaudioresample.la + +# FIXME: we still link against orc if it's there, even if --disable-orc was used +if HAVE_ORC +ORC_TEST_LIBS = -lorc-test-0.4 +else +ORC_TEST_LIBS = +endif + +libgstaudioresample_la_SOURCES = \ + gstaudioresample.c \ + speex_resampler_int.c \ + speex_resampler_float.c \ + speex_resampler_double.c + +libgstaudioresample_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(GST_CFLAGS) \ + $(ORC_CFLAGS) + +libgstaudioresample_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(ORC_LIBS) $(ORC_TEST_LIBS) \ + $(LIBM) + +libgstaudioresample_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstaudioresample_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + arch.h \ + fixed_arm4.h \ + fixed_arm5e.h \ + fixed_bfin.h \ + fixed_debug.h \ + fixed_generic.h \ + gstaudioresample.h \ + resample.c \ + resample_sse.h \ + speex_resampler.h \ + speex_resampler_wrapper.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstaudioresample -:SHARED libgstaudioresample \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstaudioresample_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudioresample_la_CFLAGS) \ + -:LDFLAGS $(libgstaudioresample_la_LDFLAGS) \ + $(libgstaudioresample_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/README b/gst-plugins-base-subtitles0.10/gst/audioresample/README new file mode 100644 index 0000000..faab16f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/README @@ -0,0 +1,347 @@ + arch.h + fixed_arm4.h + fixed_arm5e.h + fixed_bfin.h + fixed_debug.h + fixed_generic.h + resample.c + speex_resampler.h + +are taken from http://git.xiph.org/speex.git/ as of 2009-11-10. + +The only changes are: + +diff -Naur old/arch.h new/arch.h +--- old/arch.h 2009-11-10 12:18:29.000000000 +0100 ++++ new/arch.h 2009-11-10 12:19:09.000000000 +0100 +@@ -78,7 +78,10 @@ + #include "../include/speex/speex_types.h" + #endif + ++#ifndef ABS + #define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ ++#endif ++ + #define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ + #define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ + #define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +@@ -134,6 +137,28 @@ + + #else + ++#ifdef DOUBLE_PRECISION ++typedef double spx_mem_t; ++typedef double spx_coef_t; ++typedef double spx_lsp_t; ++typedef double spx_sig_t; ++typedef double spx_word16_t; ++typedef double spx_word32_t; ++ ++#define Q15ONE 1.0 ++#define LPC_SCALING 1. ++#define SIG_SCALING 1. ++#define LSP_SCALING 1. ++#define GAMMA_SCALING 1. ++#define GAIN_SCALING 1. ++#define GAIN_SCALING_1 1. ++ ++ ++#define VERY_SMALL 1e-20 ++#define VERY_LARGE32 1e20 ++#define VERY_LARGE16 1e20 ++#define Q15_ONE ((spx_word16_t)1.) ++#else /* !DOUBLE_PRECISION */ + typedef float spx_mem_t; + typedef float spx_coef_t; + typedef float spx_lsp_t; +@@ -154,6 +179,7 @@ + #define VERY_LARGE32 1e15f + #define VERY_LARGE16 1e15f + #define Q15_ONE ((spx_word16_t)1.f) ++#endif /* DOUBLE_PRECISION */ + + #define QCONST16(x,bits) (x) + #define QCONST32(x,bits) (x) +diff -Naur old/resample.c new/resample.c +--- old/resample.c 2009-11-10 12:18:51.000000000 +0100 ++++ new/resample.c 2009-11-10 12:19:09.000000000 +0100 +@@ -63,22 +63,27 @@ + + #ifdef OUTSIDE_SPEEX + #include +-static void * ++ ++#include ++ ++#define EXPORT G_GNUC_INTERNAL ++ ++static inline void * + speex_alloc (int size) + { +- return calloc (size, 1); ++ return g_malloc0 (size); + } + +-static void * ++static inline void * + speex_realloc (void *ptr, int size) + { +- return realloc (ptr, size); ++ return g_realloc (ptr, size); + } + +-static void ++static inline void + speex_free (void *ptr) + { +- free (ptr); ++ g_free (ptr); + } + + #include "speex_resampler.h" +@@ -90,7 +95,6 @@ + #include "os_support.h" + #endif /* OUTSIDE_SPEEX */ + +-#include "stack_alloc.h" + #include + + #ifndef M_PI +@@ -263,10 +267,17 @@ + }; + + /*8,24,40,56,80,104,128,160,200,256,320*/ ++#ifdef DOUBLE_PRECISION ++static double ++compute_func (double x, struct FuncDef *func) ++{ ++ double y, frac; ++#else + static double + compute_func (float x, struct FuncDef *func) + { + float y, frac; ++#endif + double interp[4]; + int ind; + y = x * func->oversample; +@@ -317,11 +328,19 @@ + } + #else + /* The slow way of computing a sinc for the table. Should improve that some day */ ++#ifdef DOUBLE_PRECISION ++static spx_word16_t ++sinc (double cutoff, double x, int N, struct FuncDef *window_func) ++{ ++ /*fprintf (stderr, "%f ", x); */ ++ double xx = x * cutoff; ++#else + static spx_word16_t + sinc (float cutoff, float x, int N, struct FuncDef *window_func) + { + /*fprintf (stderr, "%f ", x); */ + float xx = x * cutoff; ++#endif + if (fabs (x) < 1e-6) + return cutoff; + else if (fabs (x) > .5 * N) +@@ -372,6 +391,7 @@ + } + #endif + ++#ifndef DOUBLE_PRECISION + static int + resampler_basic_direct_single (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, +@@ -428,6 +448,7 @@ + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; + } ++#endif + + #ifdef FIXED_POINT + #else +@@ -483,6 +504,7 @@ + } + #endif + ++#ifndef DOUBLE_PRECISION + static int + resampler_basic_interpolate_single (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, +@@ -562,6 +584,7 @@ + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; + } ++#endif + + #ifdef FIXED_POINT + #else +@@ -592,10 +615,16 @@ + PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), + st->den_rate); + #else ++#ifdef DOUBLE_PRECISION ++ const spx_word16_t frac = ++ ((double) ((samp_frac_num * st->oversample) % st->den_rate)) / ++ st->den_rate; ++#else + const spx_word16_t frac = + ((float) ((samp_frac_num * st->oversample) % st->den_rate)) / + st->den_rate; + #endif ++#endif + spx_word16_t interp[4]; + + +@@ -696,20 +725,27 @@ + spx_int32_t j; + for (j = 0; j < st->filt_len; j++) { + st->sinc_table[i * st->filt_len + j] = +- sinc (st->cutoff, +- ((j - (spx_int32_t) st->filt_len / 2 + 1) - ++ sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) - ++#ifdef DOUBLE_PRECISION ++ ((double) i) / st->den_rate), st->filt_len, ++#else + ((float) i) / st->den_rate), st->filt_len, ++#endif + quality_map[st->quality].window_func); + } + } + #ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_direct_single; + #else ++#ifdef DOUBLE_PRECISION ++ st->resampler_ptr = resampler_basic_direct_double; ++#else + if (st->quality > 8) + st->resampler_ptr = resampler_basic_direct_double; + else + st->resampler_ptr = resampler_basic_direct_single; + #endif ++#endif + /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */ + } else { + spx_int32_t i; +@@ -725,16 +761,24 @@ + } + for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++) + st->sinc_table[i + 4] = ++#ifdef DOUBLE_PRECISION ++ sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2), ++#else + sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2), ++#endif + st->filt_len, quality_map[st->quality].window_func); + #ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_interpolate_single; + #else ++#ifdef DOUBLE_PRECISION ++ st->resampler_ptr = resampler_basic_interpolate_double; ++#else + if (st->quality > 8) + st->resampler_ptr = resampler_basic_interpolate_double; + else + st->resampler_ptr = resampler_basic_interpolate_single; + #endif ++#endif + /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */ + } + st->int_advance = st->num_rate / st->den_rate; +@@ -964,11 +1008,18 @@ + spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len, + spx_int16_t * out, spx_uint32_t * out_len) + #else ++#ifdef DOUBLE_PRECISION ++EXPORT int ++speex_resampler_process_float (SpeexResamplerState * st, ++ spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len, ++ double *out, spx_uint32_t * out_len) ++#else + EXPORT int + speex_resampler_process_float (SpeexResamplerState * st, + spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len, + float *out, spx_uint32_t * out_len) + #endif ++#endif + { + int j; + spx_uint32_t ilen = *in_len; +@@ -1086,9 +1137,16 @@ + return RESAMPLER_ERR_SUCCESS; + } + ++#ifdef DOUBLE_PRECISION ++EXPORT int ++speex_resampler_process_interleaved_float (SpeexResamplerState * st, ++ const double *in, spx_uint32_t * in_len, double *out, ++ spx_uint32_t * out_len) ++#else + EXPORT int + speex_resampler_process_interleaved_float (SpeexResamplerState * st, + const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len) ++#endif + { + spx_uint32_t i; + int istride_save, ostride_save; +diff -Naur old/speex_resampler.h new/speex_resampler.h +--- old/speex_resampler.h 2009-11-10 12:18:09.000000000 +0100 ++++ new/speex_resampler.h 2009-11-10 12:19:09.000000000 +0100 +@@ -77,10 +77,10 @@ + #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem) + #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror) + +-#define spx_int16_t short +-#define spx_int32_t int +-#define spx_uint16_t unsigned short +-#define spx_uint32_t unsigned int ++#define spx_int16_t gint16 ++#define spx_int32_t gint32 ++#define spx_uint16_t guint16 ++#define spx_uint32_t guint32 + + #else /* OUTSIDE_SPEEX */ + +@@ -166,12 +166,21 @@ + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ ++#ifdef DOUBLE_PRECISION ++int speex_resampler_process_float(SpeexResamplerState *st, ++ spx_uint32_t channel_index, ++ const double *in, ++ spx_uint32_t *in_len, ++ double *out, ++ spx_uint32_t *out_len); ++#else + int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); ++#endif + + /** Resample an int array. The input and output buffers must *not* overlap. + * @param st Resampler state +@@ -199,11 +208,19 @@ + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ ++#ifdef DOUBLE_PRECISION ++int speex_resampler_process_interleaved_float(SpeexResamplerState *st, ++ const double *in, ++ spx_uint32_t *in_len, ++ double *out, ++ spx_uint32_t *out_len); ++#else + int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); ++#endif + + /** Resample an interleaved int array. The input and output buffers must *not* overlap. + * @param st Resampler state diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/arch.h b/gst-plugins-base-subtitles0.10/gst/audioresample/arch.h new file mode 100644 index 0000000..c518458 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/arch.h @@ -0,0 +1,265 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file arch.h + @brief Various architecture definitions Speex +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef ARCH_H +#define ARCH_H + +#ifndef SPEEX_VERSION +#define SPEEX_MAJOR_VERSION 1 /**< Major Speex version. */ +#define SPEEX_MINOR_VERSION 1 /**< Minor Speex version. */ +#define SPEEX_MICRO_VERSION 15 /**< Micro Speex version. */ +#define SPEEX_EXTRA_VERSION "" /**< Extra Speex version. */ +#define SPEEX_VERSION "speex-1.2beta3" /**< Speex version string. */ +#endif + +/* A couple test to catch stupid option combinations */ +#ifdef FIXED_POINT + +#ifdef FLOATING_POINT +#error You cannot compile as floating point and fixed point at the same time +#endif +#ifdef _USE_SSE +#error SSE is only for floating-point +#endif +#if ((defined (ARM4_ASM)||defined (ARM4_ASM)) && defined(BFIN_ASM)) || (defined (ARM4_ASM)&&defined(ARM5E_ASM)) +#error Make up your mind. What CPU do you have? +#endif +#ifdef VORBIS_PSYCHO +#error Vorbis-psy model currently not implemented in fixed-point +#endif + +#else + +#ifndef FLOATING_POINT +#error You now need to define either FIXED_POINT or FLOATING_POINT +#endif +#if defined (ARM4_ASM) || defined(ARM5E_ASM) || defined(BFIN_ASM) +#error I suppose you can have a [ARM4/ARM5E/Blackfin] that has float instructions? +#endif +#ifdef FIXED_POINT_DEBUG +#error "Don't you think enabling fixed-point is a good thing to do if you want to debug that?" +#endif + + +#endif + +#ifndef OUTSIDE_SPEEX +#include "../include/speex/speex_types.h" +#endif + +#ifndef ABS +#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */ +#endif + +#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */ +#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */ +#define ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-bit value. */ +#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Maximum 32-bit value. */ +#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */ + +#ifdef FIXED_POINT + +typedef spx_int16_t spx_word16_t; +typedef spx_int32_t spx_word32_t; +typedef spx_word32_t spx_mem_t; +typedef spx_word16_t spx_coef_t; +typedef spx_word16_t spx_lsp_t; +typedef spx_word32_t spx_sig_t; + +#define Q15ONE 32767 + +#define LPC_SCALING 8192 +#define SIG_SCALING 16384 +#define LSP_SCALING 8192. +#define GAMMA_SCALING 32768. +#define GAIN_SCALING 64 +#define GAIN_SCALING_1 0.015625 + +#define LPC_SHIFT 13 +#define LSP_SHIFT 13 +#define SIG_SHIFT 14 +#define GAIN_SHIFT 6 + +#define VERY_SMALL 0 +#define VERY_LARGE32 ((spx_word32_t)2147483647) +#define VERY_LARGE16 ((spx_word16_t)32767) +#define Q15_ONE ((spx_word16_t)32767) + + +#ifdef FIXED_DEBUG +#include "fixed_debug.h" +#else + +#include "fixed_generic.h" + +#ifdef ARM5E_ASM +#include "fixed_arm5e.h" +#elif defined (ARM4_ASM) +#include "fixed_arm4.h" +#elif defined (BFIN_ASM) +#include "fixed_bfin.h" +#endif + +#endif + + +#else + +#ifdef DOUBLE_PRECISION +typedef double spx_mem_t; +typedef double spx_coef_t; +typedef double spx_lsp_t; +typedef double spx_sig_t; +typedef double spx_word16_t; +typedef double spx_word32_t; + +#define Q15ONE 1.0 +#define LPC_SCALING 1. +#define SIG_SCALING 1. +#define LSP_SCALING 1. +#define GAMMA_SCALING 1. +#define GAIN_SCALING 1. +#define GAIN_SCALING_1 1. + + +#define VERY_SMALL 1e-20 +#define VERY_LARGE32 1e20 +#define VERY_LARGE16 1e20 +#define Q15_ONE ((spx_word16_t)1.) +#else /* !DOUBLE_PRECISION */ +typedef float spx_mem_t; +typedef float spx_coef_t; +typedef float spx_lsp_t; +typedef float spx_sig_t; +typedef float spx_word16_t; +typedef float spx_word32_t; + +#define Q15ONE 1.0f +#define LPC_SCALING 1.f +#define SIG_SCALING 1.f +#define LSP_SCALING 1.f +#define GAMMA_SCALING 1.f +#define GAIN_SCALING 1.f +#define GAIN_SCALING_1 1.f + + +#define VERY_SMALL 1e-15f +#define VERY_LARGE32 1e15f +#define VERY_LARGE16 1e15f +#define Q15_ONE ((spx_word16_t)1.f) +#endif /* DOUBLE_PRECISION */ + +#define QCONST16(x,bits) (x) +#define QCONST32(x,bits) (x) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) (x) +#define EXTEND32(x) (x) +#define SHR16(a,shift) (a) +#define SHL16(a,shift) (a) +#define SHR32(a,shift) (a) +#define SHL32(a,shift) (a) +#define PSHR16(a,shift) (a) +#define PSHR32(a,shift) (a) +#define VSHR32(a,shift) (a) +#define SATURATE16(x,a) (x) +#define SATURATE32(x,a) (x) + +#define PSHR(a,shift) (a) +#define SHR(a,shift) (a) +#define SHL(a,shift) (a) +#define SATURATE(x,a) (x) + +#define ADD16(a,b) ((a)+(b)) +#define SUB16(a,b) ((a)-(b)) +#define ADD32(a,b) ((a)+(b)) +#define SUB32(a,b) ((a)-(b)) +#define MULT16_16_16(a,b) ((a)*(b)) +#define MULT16_16(a,b) ((spx_word32_t)(a)*(spx_word32_t)(b)) +#define MAC16_16(c,a,b) ((c)+(spx_word32_t)(a)*(spx_word32_t)(b)) + +#define MULT16_32_Q11(a,b) ((a)*(b)) +#define MULT16_32_Q13(a,b) ((a)*(b)) +#define MULT16_32_Q14(a,b) ((a)*(b)) +#define MULT16_32_Q15(a,b) ((a)*(b)) +#define MULT16_32_P15(a,b) ((a)*(b)) + +#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b)) +#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b)) + +#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b)) +#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b)) +#define MAC16_16_P13(c,a,b) ((c)+(a)*(b)) +#define MULT16_16_Q11_32(a,b) ((a)*(b)) +#define MULT16_16_Q13(a,b) ((a)*(b)) +#define MULT16_16_Q14(a,b) ((a)*(b)) +#define MULT16_16_Q15(a,b) ((a)*(b)) +#define MULT16_16_P15(a,b) ((a)*(b)) +#define MULT16_16_P13(a,b) ((a)*(b)) +#define MULT16_16_P14(a,b) ((a)*(b)) + +#define DIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define PDIV32_16(a,b) (((spx_word32_t)(a))/(spx_word16_t)(b)) +#define DIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) +#define PDIV32(a,b) (((spx_word32_t)(a))/(spx_word32_t)(b)) + + +#endif + + +#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X) + +/* 2 on TI C5x DSP */ +#define BYTES_PER_CHAR 2 +#define BITS_PER_CHAR 16 +#define LOG2_BITS_PER_CHAR 4 + +#else + +#define BYTES_PER_CHAR 1 +#define BITS_PER_CHAR 8 +#define LOG2_BITS_PER_CHAR 3 + +#endif + + + +#ifdef FIXED_DEBUG +extern long long spx_mips; +#endif + + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm4.h b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm4.h new file mode 100644 index 0000000..b6981ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm4.h @@ -0,0 +1,148 @@ +/* Copyright (C) 2004 Jean-Marc Valin */ +/** + @file fixed_arm4.h + @brief ARM4 fixed-point operations +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_ARM4_H +#define FIXED_ARM4_H + +#undef MULT16_32_Q14 +static inline spx_word32_t MULT16_32_Q14(spx_word16_t x, spx_word32_t y) { + int res; + int dummy; + asm ( + "smull %0,%1,%2,%3 \n\t" + "mov %0, %0, lsr #14 \n\t" + "add %0, %0, %1, lsl #18 \n\t" + : "=&r"(res), "=&r" (dummy) + : "r"(y),"r"((int)x)); + return(res); +} + +#undef MULT16_32_Q15 +static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { + int res; + int dummy; + asm ( + "smull %0,%1,%2,%3 \n\t" + "mov %0, %0, lsr #15 \n\t" + "add %0, %0, %1, lsl #17 \n\t" + : "=&r"(res), "=&r" (dummy) + : "r"(y),"r"((int)x)); + return(res); +} + +#undef DIV32_16 +static inline short DIV32_16(int a, int b) +{ + int res=0; + int dead1, dead2, dead3, dead4, dead5; + __asm__ __volatile__ ( + "\teor %5, %0, %1\n" + "\tmovs %4, %0\n" + "\trsbmi %0, %0, #0 \n" + "\tmovs %4, %1\n" + "\trsbmi %1, %1, #0 \n" + "\tmov %4, #1\n" + + "\tsubs %3, %0, %1, asl #14 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #14 \n" + + "\tsubs %3, %0, %1, asl #13 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #13 \n" + + "\tsubs %3, %0, %1, asl #12 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #12 \n" + + "\tsubs %3, %0, %1, asl #11 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #11 \n" + + "\tsubs %3, %0, %1, asl #10 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #10 \n" + + "\tsubs %3, %0, %1, asl #9 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #9 \n" + + "\tsubs %3, %0, %1, asl #8 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #8 \n" + + "\tsubs %3, %0, %1, asl #7 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #7 \n" + + "\tsubs %3, %0, %1, asl #6 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #6 \n" + + "\tsubs %3, %0, %1, asl #5 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #5 \n" + + "\tsubs %3, %0, %1, asl #4 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #4 \n" + + "\tsubs %3, %0, %1, asl #3 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #3 \n" + + "\tsubs %3, %0, %1, asl #2 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #2 \n" + + "\tsubs %3, %0, %1, asl #1 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4, asl #1 \n" + + "\tsubs %3, %0, %1 \n" + "\tmovpl %0, %3 \n" + "\torrpl %2, %2, %4 \n" + + "\tmovs %5, %5, lsr #31 \n" + "\trsbne %2, %2, #0 \n" + : "=r" (dead1), "=r" (dead2), "=r" (res), + "=r" (dead3), "=r" (dead4), "=r" (dead5) + : "0" (a), "1" (b), "2" (res) + : "cc" + ); + return res; +} + + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm5e.h b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm5e.h new file mode 100644 index 0000000..9b4861c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_arm5e.h @@ -0,0 +1,178 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_arm5e.h + @brief ARM-tuned fixed-point operations +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_ARM5E_H +#define FIXED_ARM5E_H + +#undef MULT16_16 +static inline spx_word32_t MULT16_16(spx_word16_t x, spx_word16_t y) { + int res; + asm ("smulbb %0,%1,%2;\n" + : "=&r"(res) + : "%r"(x),"r"(y)); + return(res); +} + +#undef MAC16_16 +static inline spx_word32_t MAC16_16(spx_word32_t a, spx_word16_t x, spx_word32_t y) { + int res; + asm ("smlabb %0,%1,%2,%3;\n" + : "=&r"(res) + : "%r"(x),"r"(y),"r"(a)); + return(res); +} + +#undef MULT16_32_Q15 +static inline spx_word32_t MULT16_32_Q15(spx_word16_t x, spx_word32_t y) { + int res; + asm ("smulwb %0,%1,%2;\n" + : "=&r"(res) + : "%r"(y<<1),"r"(x)); + return(res); +} + +#undef MAC16_32_Q15 +static inline spx_word32_t MAC16_32_Q15(spx_word32_t a, spx_word16_t x, spx_word32_t y) { + int res; + asm ("smlawb %0,%1,%2,%3;\n" + : "=&r"(res) + : "%r"(y<<1),"r"(x),"r"(a)); + return(res); +} + +#undef MULT16_32_Q11 +static inline spx_word32_t MULT16_32_Q11(spx_word16_t x, spx_word32_t y) { + int res; + asm ("smulwb %0,%1,%2;\n" + : "=&r"(res) + : "%r"(y<<5),"r"(x)); + return(res); +} + +#undef MAC16_32_Q11 +static inline spx_word32_t MAC16_32_Q11(spx_word32_t a, spx_word16_t x, spx_word32_t y) { + int res; + asm ("smlawb %0,%1,%2,%3;\n" + : "=&r"(res) + : "%r"(y<<5),"r"(x),"r"(a)); + return(res); +} + +#undef DIV32_16 +static inline short DIV32_16(int a, int b) +{ + int res=0; + int dead1, dead2, dead3, dead4, dead5; + __asm__ __volatile__ ( + "\teor %5, %0, %1\n" + "\tmovs %4, %0\n" + "\trsbmi %0, %0, #0 \n" + "\tmovs %4, %1\n" + "\trsbmi %1, %1, #0 \n" + "\tmov %4, #1\n" + + "\tsubs %3, %0, %1, asl #14 \n" + "\torrpl %2, %2, %4, asl #14 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #13 \n" + "\torrpl %2, %2, %4, asl #13 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #12 \n" + "\torrpl %2, %2, %4, asl #12 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #11 \n" + "\torrpl %2, %2, %4, asl #11 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #10 \n" + "\torrpl %2, %2, %4, asl #10 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #9 \n" + "\torrpl %2, %2, %4, asl #9 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #8 \n" + "\torrpl %2, %2, %4, asl #8 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #7 \n" + "\torrpl %2, %2, %4, asl #7 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #6 \n" + "\torrpl %2, %2, %4, asl #6 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #5 \n" + "\torrpl %2, %2, %4, asl #5 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #4 \n" + "\torrpl %2, %2, %4, asl #4 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #3 \n" + "\torrpl %2, %2, %4, asl #3 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #2 \n" + "\torrpl %2, %2, %4, asl #2 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1, asl #1 \n" + "\torrpl %2, %2, %4, asl #1 \n" + "\tmovpl %0, %3 \n" + + "\tsubs %3, %0, %1 \n" + "\torrpl %2, %2, %4 \n" + "\tmovpl %0, %3 \n" + + "\tmovs %5, %5, lsr #31 \n" + "\trsbne %2, %2, #0 \n" + : "=r" (dead1), "=r" (dead2), "=r" (res), + "=r" (dead3), "=r" (dead4), "=r" (dead5) + : "0" (a), "1" (b), "2" (res) + : "memory", "cc" + ); + return res; +} + + + + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_bfin.h b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_bfin.h new file mode 100644 index 0000000..9eb21e3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_bfin.h @@ -0,0 +1,176 @@ +/* Copyright (C) 2005 Analog Devices + Author: Jean-Marc Valin */ +/** + @file fixed_bfin.h + @brief Blackfin fixed-point operations +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_BFIN_H +#define FIXED_BFIN_H + +#include "bfin.h" + +#undef PDIV32_16 +static inline spx_word16_t PDIV32_16(spx_word32_t a, spx_word16_t b) +{ + spx_word32_t res, bb; + bb = b; + a += b>>1; + __asm__ ( + "P0 = 15;\n\t" + "R0 = %1;\n\t" + "R1 = %2;\n\t" + //"R0 = R0 + R1;\n\t" + "R0 <<= 1;\n\t" + "DIVS (R0, R1);\n\t" + "LOOP divide%= LC0 = P0;\n\t" + "LOOP_BEGIN divide%=;\n\t" + "DIVQ (R0, R1);\n\t" + "LOOP_END divide%=;\n\t" + "R0 = R0.L;\n\t" + "%0 = R0;\n\t" + : "=m" (res) + : "m" (a), "m" (bb) + : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); + return res; +} + +#undef DIV32_16 +static inline spx_word16_t DIV32_16(spx_word32_t a, spx_word16_t b) +{ + spx_word32_t res, bb; + bb = b; + /* Make the roundinf consistent with the C version + (do we need to do that?)*/ + if (a<0) + a += (b-1); + __asm__ ( + "P0 = 15;\n\t" + "R0 = %1;\n\t" + "R1 = %2;\n\t" + "R0 <<= 1;\n\t" + "DIVS (R0, R1);\n\t" + "LOOP divide%= LC0 = P0;\n\t" + "LOOP_BEGIN divide%=;\n\t" + "DIVQ (R0, R1);\n\t" + "LOOP_END divide%=;\n\t" + "R0 = R0.L;\n\t" + "%0 = R0;\n\t" + : "=m" (res) + : "m" (a), "m" (bb) + : "P0", "R0", "R1", "ASTAT" BFIN_HWLOOP0_REGS); + return res; +} + +#undef MAX16 +static inline spx_word16_t MAX16(spx_word16_t a, spx_word16_t b) +{ + spx_word32_t res; + __asm__ ( + "%1 = %1.L (X);\n\t" + "%2 = %2.L (X);\n\t" + "%0 = MAX(%1,%2);" + : "=d" (res) + : "%d" (a), "d" (b) + : "ASTAT" + ); + return res; +} + +#undef MULT16_32_Q15 +static inline spx_word32_t MULT16_32_Q15(spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H) ;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b) + : "A1", "ASTAT" + ); + return res; +} + +#undef MAC16_32_Q15 +static inline spx_word32_t MAC16_32_Q15(spx_word32_t c, spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H);\n\t" + "%0 = %0 + %4;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b), "d" (c) + : "A1", "ASTAT" + ); + return res; +} + +#undef MULT16_32_Q14 +static inline spx_word32_t MULT16_32_Q14(spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "%2 <<= 1;\n\t" + "A1 = %1.L*%2.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %1.L*%2.H);\n\t" + : "=W" (res), "=d" (a), "=d" (b) + : "1" (a), "2" (b) + : "A1", "ASTAT" + ); + return res; +} + +#undef MAC16_32_Q14 +static inline spx_word32_t MAC16_32_Q14(spx_word32_t c, spx_word16_t a, spx_word32_t b) +{ + spx_word32_t res; + __asm__ + ( + "%1 <<= 1;\n\t" + "A1 = %2.L*%1.L (M);\n\t" + "A1 = A1 >>> 15;\n\t" + "%0 = (A1 += %2.L*%1.H);\n\t" + "%0 = %0 + %4;\n\t" + : "=&W" (res), "=&d" (b) + : "d" (a), "1" (b), "d" (c) + : "A1", "ASTAT" + ); + return res; +} + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_debug.h b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_debug.h new file mode 100644 index 0000000..54f3866 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_debug.h @@ -0,0 +1,487 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_debug.h + @brief Fixed-point operations with debugging +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_DEBUG_H +#define FIXED_DEBUG_H + +#include + +extern long long spx_mips; +#define MIPS_INC spx_mips++, + +#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) + + +#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768) +#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL) + +static inline short NEG16(int x) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "NEG16: input is not short: %d\n", (int)x); + } + res = -x; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "NEG16: output is not short: %d\n", (int)res); + spx_mips++; + return res; +} +static inline int NEG32(long long x) +{ + long long res; + if (!VERIFY_INT(x)) + { + fprintf (stderr, "NEG16: input is not int: %d\n", (int)x); + } + res = -x; + if (!VERIFY_INT(res)) + fprintf (stderr, "NEG16: output is not int: %d\n", (int)res); + spx_mips++; + return res; +} + +#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__) +static inline short _EXTRACT16(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line); + } + res = x; + spx_mips++; + return res; +} + +#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__) +static inline int _EXTEND32(int x, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(x)) + { + fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line); + } + res = x; + spx_mips++; + return res; +} + +#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__) +static inline short _SHR16(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line); + } + res = a>>shift; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line); + spx_mips++; + return res; +} +#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__) +static inline short _SHL16(int a, int shift, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line); + } + res = a<>shift; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "SHR32: output is not int: %d\n", (int)res); + } + spx_mips++; + return res; +} +static inline int SHL32(long long a, int shift) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_SHORT(shift)) + { + fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift); + } + res = a<>1))),shift)) +#define PSHR32(a,shift) (SHR32(ADD32((a),((EXTEND32(1)<<((shift))>>1))),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) + +#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) +#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +//#define SHR(a,shift) ((a) >> (shift)) +//#define SHL(a,shift) ((a) << (shift)) + +#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__) +static inline short _ADD16(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = a+b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line); + } + spx_mips++; + return res; +} + +#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__) +static inline short _SUB16(int a, int b, char *file, int line) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = a-b; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line); + spx_mips++; + return res; +} + +#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__) +static inline int _ADD32(long long a, long long b, char *file, int line) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a+b; + if (!VERIFY_INT(res)) + { + fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line); + } + spx_mips++; + return res; +} + +static inline int SUB32(long long a, long long b) +{ + long long res; + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "SUB32: inputs are not int: %d %d\n", (int)a, (int)b); + } + res = a-b; + if (!VERIFY_INT(res)) + fprintf (stderr, "SUB32: output is not int: %d\n", (int)res); + spx_mips++; + return res; +} + +#define ADD64(a,b) (MIPS_INC(a)+(b)) + +/* result fits in 16 bits */ +static inline short MULT16_16_16(int a, int b) +{ + int res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b); + } + res = a*b; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res); + spx_mips++; + return res; +} + +#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__) +static inline int _MULT16_16(int a, int b, char *file, int line) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line); + } + res = ((long long)a)*b; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line); + spx_mips++; + return res; +} + +#define MAC16_16(c,a,b) (spx_mips--,ADD32((c),MULT16_16((a),(b)))) +#define MAC16_16_Q11(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))) +#define MAC16_16_Q13(c,a,b) (EXTRACT16(ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))) +#define MAC16_16_P13(c,a,b) (EXTRACT16(ADD32((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))) + + +#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__) +static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); + } + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line); + res = (((long long)a)*(long long)b) >> Q; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line); + spx_mips+=5; + return res; +} + +static inline int MULT16_32_PX(int a, long long b, int Q) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b); + } + if (ABS32(b)>=(EXTEND32(1)<<(15+Q))) + fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b); + res = ((((long long)a)*(long long)b) + ((EXTEND32(1)<>1))>> Q; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res); + spx_mips+=5; + return res; +} + + +#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11) +#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b))) +#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12) +#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13) +#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14) +#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15) +#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15) +#define MAC16_32_Q15(c,a,b) ADD32((c),MULT16_32_Q15((a),(b))) + +static inline int SATURATE(int a, int b) +{ + if (a>b) + a=b; + if (a<-b) + a = -b; + return a; +} + +static inline int MULT16_16_Q11_32(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 11; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q13(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 13; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q14(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 14; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res); + spx_mips+=3; + return res; +} +static inline short MULT16_16_Q15(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res >>= 15; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "MULT16_16_Q15: output is not short: %d\n", (int)res); + } + spx_mips+=3; + return res; +} + +static inline short MULT16_16_P13(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 4096; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 13; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} +static inline short MULT16_16_P14(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 8192; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 14; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} +static inline short MULT16_16_P15(int a, int b) +{ + long long res; + if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b); + } + res = ((long long)a)*b; + res += 16384; + if (!VERIFY_INT(res)) + fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res); + res >>= 15; + if (!VERIFY_SHORT(res)) + fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res); + spx_mips+=4; + return res; +} + +#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__) + +static inline int _DIV32_16(long long a, long long b, char *file, int line) +{ + long long res; + if (b==0) + { + fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); + return 0; + } + if (!VERIFY_INT(a) || !VERIFY_SHORT(b)) + { + fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a/b; + if (!VERIFY_SHORT(res)) + { + fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line); + if (res>32767) + res = 32767; + if (res<-32768) + res = -32768; + } + spx_mips+=20; + return res; +} + +#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__) +static inline int _DIV32(long long a, long long b, char *file, int line) +{ + long long res; + if (b==0) + { + fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line); + return 0; + } + + if (!VERIFY_INT(a) || !VERIFY_INT(b)) + { + fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line); + } + res = a/b; + if (!VERIFY_INT(res)) + fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line); + spx_mips+=36; + return res; +} +#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b) +#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b) + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_generic.h b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_generic.h new file mode 100644 index 0000000..3fb096e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/fixed_generic.h @@ -0,0 +1,106 @@ +/* Copyright (C) 2003 Jean-Marc Valin */ +/** + @file fixed_generic.h + @brief Generic fixed-point operations +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#ifndef FIXED_GENERIC_H +#define FIXED_GENERIC_H + +#define QCONST16(x,bits) ((spx_word16_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) +#define QCONST32(x,bits) ((spx_word32_t)(.5+(x)*(((spx_word32_t)1)<<(bits)))) + +#define NEG16(x) (-(x)) +#define NEG32(x) (-(x)) +#define EXTRACT16(x) ((spx_word16_t)(x)) +#define EXTEND32(x) ((spx_word32_t)(x)) +#define SHR16(a,shift) ((a) >> (shift)) +#define SHL16(a,shift) ((a) << (shift)) +#define SHR32(a,shift) ((a) >> (shift)) +#define SHL32(a,shift) ((a) << (shift)) +#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),shift)) +#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift))) +#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) +#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + +#define SHR(a,shift) ((a) >> (shift)) +#define SHL(a,shift) ((spx_word32_t)(a) << (shift)) +#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift)) +#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x))) + + +#define ADD16(a,b) ((spx_word16_t)((spx_word16_t)(a)+(spx_word16_t)(b))) +#define SUB16(a,b) ((spx_word16_t)(a)-(spx_word16_t)(b)) +#define ADD32(a,b) ((spx_word32_t)(a)+(spx_word32_t)(b)) +#define SUB32(a,b) ((spx_word32_t)(a)-(spx_word32_t)(b)) + + +/* result fits in 16 bits */ +#define MULT16_16_16(a,b) ((((spx_word16_t)(a))*((spx_word16_t)(b)))) + +/* (spx_word32_t)(spx_word16_t) gives TI compiler a hint that it's 16x16->32 multiply */ +#define MULT16_16(a,b) (((spx_word32_t)(spx_word16_t)(a))*((spx_word32_t)(spx_word16_t)(b))) + +#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b)))) +#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12)) +#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13)) +#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14)) + +#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)) +#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))) + +#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MULT16_32_Q15(a,b) ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)) +#define MAC16_32_Q15(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15))) + + +#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11))) +#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13))) +#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13))) + +#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11)) +#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13)) +#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14)) +#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15)) + +#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13)) +#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14)) +#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15)) + +#define MUL_16_32_R15(a,bh,bl) ADD32(MULT16_16((a),(bh)), SHR(MULT16_16((a),(bl)),15)) + +#define DIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a))/((spx_word16_t)(b)))) +#define PDIV32_16(a,b) ((spx_word16_t)(((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word16_t)(b)))) +#define DIV32(a,b) (((spx_word32_t)(a))/((spx_word32_t)(b))) +#define PDIV32(a,b) (((spx_word32_t)(a)+((spx_word16_t)(b)>>1))/((spx_word32_t)(b))) + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.c b/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.c new file mode 100644 index 0000000..9364a86 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.c @@ -0,0 +1,1604 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * Copyright (C) 2003,2004 David A. Schleef + * Copyright (C) 2007-2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-audioresample + * + * audioresample resamples raw audio buffers to different sample rates using + * a configurable windowing function to enhance quality. + * + * + * Example launch line + * |[ + * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw-int, rate=8000 ! alsasink + * ]| Decode an Ogg/Vorbis downsample to 8Khz and play sound through alsa. + * To create the Ogg/Vorbis file refer to the documentation of vorbisenc. + * + */ + +/* TODO: + * - Enable SSE/ARM optimizations and select at runtime + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstaudioresample.h" +#include +#include +#include + +#ifndef DISABLE_ORC +#include +#include +#include +#endif + +GST_DEBUG_CATEGORY (audio_resample_debug); +#define GST_CAT_DEFAULT audio_resample_debug + +enum +{ + PROP_0, + PROP_QUALITY, + PROP_FILTER_LENGTH +}; + +#define SUPPORTED_CAPS \ +GST_STATIC_CAPS ( \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 32, 64 }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32, " \ + "depth = (int) 32, " \ + "signed = (boolean) true; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 24, " \ + "depth = (int) 24, " \ + "signed = (boolean) true; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) true; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 8, " \ + "depth = (int) 8, " \ + "signed = (boolean) true" \ +) + +/* If TRUE integer arithmetic resampling is faster and will be used if appropiate */ +#if defined AUDIORESAMPLE_FORMAT_INT +static gboolean gst_audio_resample_use_int = TRUE; +#elif defined AUDIORESAMPLE_FORMAT_FLOAT +static gboolean gst_audio_resample_use_int = FALSE; +#else +static gboolean gst_audio_resample_use_int = FALSE; +#endif + +static GstStaticPadTemplate gst_audio_resample_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS); + +static GstStaticPadTemplate gst_audio_resample_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, SUPPORTED_CAPS); + +static void gst_audio_resample_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_audio_resample_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +/* vmethods */ +static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base, + GstCaps * caps, guint * size); +static GstCaps *gst_audio_resample_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps); +static void gst_audio_resample_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); +static gboolean gst_audio_resample_transform_size (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * incaps, guint insize, + GstCaps * outcaps, guint * outsize); +static gboolean gst_audio_resample_set_caps (GstBaseTransform * base, + GstCaps * incaps, GstCaps * outcaps); +static GstFlowReturn gst_audio_resample_transform (GstBaseTransform * base, + GstBuffer * inbuf, GstBuffer * outbuf); +static gboolean gst_audio_resample_event (GstBaseTransform * base, + GstEvent * event); +static gboolean gst_audio_resample_start (GstBaseTransform * base); +static gboolean gst_audio_resample_stop (GstBaseTransform * base); +static gboolean gst_audio_resample_query (GstPad * pad, GstQuery * query); +static const GstQueryType *gst_audio_resample_query_type (GstPad * pad); + +GST_BOILERPLATE (GstAudioResample, gst_audio_resample, GstBaseTransform, + GST_TYPE_BASE_TRANSFORM); + +static void +gst_audio_resample_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_audio_resample_src_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_audio_resample_sink_template)); + + gst_element_class_set_details_simple (gstelement_class, "Audio resampler", + "Filter/Converter/Audio", "Resamples audio", + "Sebastian Dröge "); +} + +static void +gst_audio_resample_class_init (GstAudioResampleClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + + gobject_class->set_property = gst_audio_resample_set_property; + gobject_class->get_property = gst_audio_resample_get_property; + + g_object_class_install_property (gobject_class, PROP_QUALITY, + g_param_spec_int ("quality", "Quality", "Resample quality with 0 being " + "the lowest and 10 being the best", + SPEEX_RESAMPLER_QUALITY_MIN, SPEEX_RESAMPLER_QUALITY_MAX, + SPEEX_RESAMPLER_QUALITY_DEFAULT, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + /* FIXME 0.11: Remove this property, it's just for compatibility + * with old audioresample + */ + /** + * GstAudioResample:filter-length: + * + * Length of the resample filter + * + * Deprectated: Use #GstAudioResample:quality property instead + */ + g_object_class_install_property (gobject_class, PROP_FILTER_LENGTH, + g_param_spec_int ("filter-length", "Filter length", + "Length of the resample filter", 0, G_MAXINT, 64, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + GST_BASE_TRANSFORM_CLASS (klass)->start = + GST_DEBUG_FUNCPTR (gst_audio_resample_start); + GST_BASE_TRANSFORM_CLASS (klass)->stop = + GST_DEBUG_FUNCPTR (gst_audio_resample_stop); + GST_BASE_TRANSFORM_CLASS (klass)->transform_size = + GST_DEBUG_FUNCPTR (gst_audio_resample_transform_size); + GST_BASE_TRANSFORM_CLASS (klass)->get_unit_size = + GST_DEBUG_FUNCPTR (gst_audio_resample_get_unit_size); + GST_BASE_TRANSFORM_CLASS (klass)->transform_caps = + GST_DEBUG_FUNCPTR (gst_audio_resample_transform_caps); + GST_BASE_TRANSFORM_CLASS (klass)->fixate_caps = + GST_DEBUG_FUNCPTR (gst_audio_resample_fixate_caps); + GST_BASE_TRANSFORM_CLASS (klass)->set_caps = + GST_DEBUG_FUNCPTR (gst_audio_resample_set_caps); + GST_BASE_TRANSFORM_CLASS (klass)->transform = + GST_DEBUG_FUNCPTR (gst_audio_resample_transform); + GST_BASE_TRANSFORM_CLASS (klass)->event = + GST_DEBUG_FUNCPTR (gst_audio_resample_event); + + GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE; +} + +static void +gst_audio_resample_init (GstAudioResample * resample, + GstAudioResampleClass * klass) +{ + GstBaseTransform *trans = GST_BASE_TRANSFORM (resample); + + resample->quality = SPEEX_RESAMPLER_QUALITY_DEFAULT; + + gst_base_transform_set_gap_aware (trans, TRUE); + gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query); + gst_pad_set_query_type_function (trans->srcpad, + gst_audio_resample_query_type); +} + +/* vmethods */ +static gboolean +gst_audio_resample_start (GstBaseTransform * base) +{ + GstAudioResample *resample = GST_AUDIO_RESAMPLE (base); + + resample->need_discont = TRUE; + + resample->num_gap_samples = 0; + resample->num_nongap_samples = 0; + resample->t0 = GST_CLOCK_TIME_NONE; + resample->in_offset0 = GST_BUFFER_OFFSET_NONE; + resample->out_offset0 = GST_BUFFER_OFFSET_NONE; + resample->samples_in = 0; + resample->samples_out = 0; + + resample->tmp_in = NULL; + resample->tmp_in_size = 0; + resample->tmp_out = NULL; + resample->tmp_out_size = 0; + + return TRUE; +} + +static gboolean +gst_audio_resample_stop (GstBaseTransform * base) +{ + GstAudioResample *resample = GST_AUDIO_RESAMPLE (base); + + if (resample->state) { + resample->funcs->destroy (resample->state); + resample->state = NULL; + } + + resample->funcs = NULL; + + g_free (resample->tmp_in); + resample->tmp_in = NULL; + resample->tmp_in_size = 0; + + g_free (resample->tmp_out); + resample->tmp_out = NULL; + resample->tmp_out_size = 0; + + gst_caps_replace (&resample->sinkcaps, NULL); + gst_caps_replace (&resample->srccaps, NULL); + + return TRUE; +} + +static gboolean +gst_audio_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps, + guint * size) +{ + gint width, channels; + GstStructure *structure; + gboolean ret; + + g_return_val_if_fail (size != NULL, FALSE); + + /* this works for both float and int */ + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", &width); + ret &= gst_structure_get_int (structure, "channels", &channels); + + if (G_UNLIKELY (!ret)) + return FALSE; + + *size = (width / 8) * channels; + + return TRUE; +} + +static GstCaps * +gst_audio_resample_transform_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps) +{ + const GValue *val; + GstStructure *s; + GstCaps *res; + + /* transform single caps into input_caps + input_caps with the rate + * field set to our supported range. This ensures that upstream knows + * about downstream's prefered rate(s) and can negotiate accordingly. */ + res = gst_caps_copy (caps); + + /* first, however, check if the caps contain a range for the rate field, in + * which case that side isn't going to care much about the exact sample rate + * chosen and we should just assume things will get fixated to something sane + * and we may just as well offer our full range instead of the range in the + * caps. If the rate is not an int range value, it's likely to express a + * real preference or limitation and we should maintain that structure as + * preference by putting it first into the transformed caps, and only add + * our full rate range as second option */ + s = gst_caps_get_structure (res, 0); + val = gst_structure_get_value (s, "rate"); + if (val == NULL || GST_VALUE_HOLDS_INT_RANGE (val)) { + /* overwrite existing range, or add field if it doesn't exist yet */ + gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + } else { + /* append caps with full range to existing caps with non-range rate field */ + s = gst_structure_copy (s); + gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + gst_caps_append_structure (res, s); + } + + return res; +} + +/* Fixate rate to the allowed rate that has the smallest difference */ +static void +gst_audio_resample_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps) +{ + GstStructure *s; + gint rate; + + s = gst_caps_get_structure (caps, 0); + if (G_UNLIKELY (!gst_structure_get_int (s, "rate", &rate))) + return; + + s = gst_caps_get_structure (othercaps, 0); + gst_structure_fixate_field_nearest_int (s, "rate", rate); +} + +static const SpeexResampleFuncs * +gst_audio_resample_get_funcs (gint width, gboolean fp) +{ + const SpeexResampleFuncs *funcs = NULL; + + if (gst_audio_resample_use_int && (width == 8 || width == 16) && !fp) + funcs = &int_funcs; + else if ((!gst_audio_resample_use_int && (width == 8 || width == 16) && !fp) + || (width == 32 && fp)) + funcs = &float_funcs; + else if ((width == 64 && fp) || ((width == 32 || width == 24) && !fp)) + funcs = &double_funcs; + else + g_assert_not_reached (); + + return funcs; +} + +static SpeexResamplerState * +gst_audio_resample_init_state (GstAudioResample * resample, gint width, + gint channels, gint inrate, gint outrate, gint quality, gboolean fp) +{ + SpeexResamplerState *ret = NULL; + gint err = RESAMPLER_ERR_SUCCESS; + const SpeexResampleFuncs *funcs = gst_audio_resample_get_funcs (width, fp); + + ret = funcs->init (channels, inrate, outrate, quality, &err); + + if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { + GST_ERROR_OBJECT (resample, "Failed to create resampler state: %s", + funcs->strerror (err)); + return NULL; + } + + funcs->skip_zeros (ret); + + return ret; +} + +static gboolean +gst_audio_resample_update_state (GstAudioResample * resample, gint width, + gint channels, gint inrate, gint outrate, gint quality, gboolean fp) +{ + gboolean ret = TRUE; + gboolean updated_latency = FALSE; + + updated_latency = (resample->inrate != inrate + || quality != resample->quality) && resample->state != NULL; + + if (resample->state == NULL) { + ret = TRUE; + } else if (resample->channels != channels || fp != resample->fp + || width != resample->width) { + resample->funcs->destroy (resample->state); + resample->state = + gst_audio_resample_init_state (resample, width, channels, inrate, + outrate, quality, fp); + + resample->funcs = gst_audio_resample_get_funcs (width, fp); + ret = (resample->state != NULL); + } else if (resample->inrate != inrate || resample->outrate != outrate) { + gint err = RESAMPLER_ERR_SUCCESS; + + err = resample->funcs->set_rate (resample->state, inrate, outrate); + + if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) + GST_ERROR_OBJECT (resample, "Failed to update rate: %s", + resample->funcs->strerror (err)); + + ret = (err == RESAMPLER_ERR_SUCCESS); + } else if (quality != resample->quality) { + gint err = RESAMPLER_ERR_SUCCESS; + + err = resample->funcs->set_quality (resample->state, quality); + + if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) + GST_ERROR_OBJECT (resample, "Failed to update quality: %s", + resample->funcs->strerror (err)); + + ret = (err == RESAMPLER_ERR_SUCCESS); + } + + resample->width = width; + resample->channels = channels; + resample->fp = fp; + resample->quality = quality; + resample->inrate = inrate; + resample->outrate = outrate; + + if (updated_latency) + gst_element_post_message (GST_ELEMENT (resample), + gst_message_new_latency (GST_OBJECT (resample))); + + return ret; +} + +static void +gst_audio_resample_reset_state (GstAudioResample * resample) +{ + if (resample->state) + resample->funcs->reset_mem (resample->state); +} + +static gboolean +gst_audio_resample_parse_caps (GstCaps * incaps, + GstCaps * outcaps, gint * width, gint * channels, gint * inrate, + gint * outrate, gboolean * fp) +{ + GstStructure *structure; + gboolean ret; + gint mywidth, myinrate, myoutrate, mychannels; + gboolean myfp; + + GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %" + GST_PTR_FORMAT, incaps, outcaps); + + structure = gst_caps_get_structure (incaps, 0); + + if (gst_structure_has_name (structure, "audio/x-raw-float")) + myfp = TRUE; + else + myfp = FALSE; + + ret = gst_structure_get_int (structure, "rate", &myinrate); + ret &= gst_structure_get_int (structure, "channels", &mychannels); + ret &= gst_structure_get_int (structure, "width", &mywidth); + if (G_UNLIKELY (!ret)) + goto no_in_rate_channels; + + structure = gst_caps_get_structure (outcaps, 0); + ret = gst_structure_get_int (structure, "rate", &myoutrate); + if (G_UNLIKELY (!ret)) + goto no_out_rate; + + if (channels) + *channels = mychannels; + if (inrate) + *inrate = myinrate; + if (outrate) + *outrate = myoutrate; + if (width) + *width = mywidth; + if (fp) + *fp = myfp; + + return TRUE; + + /* ERRORS */ +no_in_rate_channels: + { + GST_DEBUG ("could not get input rate and channels"); + return FALSE; + } +no_out_rate: + { + GST_DEBUG ("could not get output rate"); + return FALSE; + } +} + +static gint +_gcd (gint a, gint b) +{ + while (b != 0) { + int temp = a; + + a = b; + b = temp % b; + } + + return ABS (a); +} + +static gboolean +gst_audio_resample_transform_size (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps, + guint * othersize) +{ + gboolean ret = TRUE; + guint32 ratio_den, ratio_num; + gint inrate, outrate, gcd; + gint bytes_per_samp, channels; + + GST_LOG_OBJECT (base, "asked to transform size %d in direction %s", + size, direction == GST_PAD_SINK ? "SINK" : "SRC"); + + /* Get sample width -> bytes_per_samp, channels, inrate, outrate */ + ret = + gst_audio_resample_parse_caps (caps, othercaps, &bytes_per_samp, + &channels, &inrate, &outrate, NULL); + if (G_UNLIKELY (!ret)) { + GST_ERROR_OBJECT (base, "Wrong caps"); + return FALSE; + } + /* Number of samples in either buffer is size / (width*channels) -> + * calculate the factor */ + bytes_per_samp = bytes_per_samp * channels / 8; + /* Convert source buffer size to samples */ + size /= bytes_per_samp; + + /* Simplify the conversion ratio factors */ + gcd = _gcd (inrate, outrate); + ratio_num = inrate / gcd; + ratio_den = outrate / gcd; + + if (direction == GST_PAD_SINK) { + /* asked to convert size of an incoming buffer. Round up the output size */ + *othersize = gst_util_uint64_scale_int_ceil (size, ratio_den, ratio_num); + *othersize *= bytes_per_samp; + } else { + /* asked to convert size of an outgoing buffer. Round down the input size */ + *othersize = gst_util_uint64_scale_int (size, ratio_num, ratio_den); + *othersize *= bytes_per_samp; + } + + GST_LOG_OBJECT (base, "transformed size %d to %d", size * bytes_per_samp, + *othersize); + + return ret; +} + +static gboolean +gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps, + GstCaps * outcaps) +{ + gboolean ret; + gint width = 0, inrate = 0, outrate = 0, channels = 0; + gboolean fp; + GstAudioResample *resample = GST_AUDIO_RESAMPLE (base); + + GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %" + GST_PTR_FORMAT, incaps, outcaps); + + ret = gst_audio_resample_parse_caps (incaps, outcaps, + &width, &channels, &inrate, &outrate, &fp); + + if (G_UNLIKELY (!ret)) + return FALSE; + + ret = + gst_audio_resample_update_state (resample, width, channels, inrate, + outrate, resample->quality, fp); + + if (G_UNLIKELY (!ret)) + return FALSE; + + /* save caps so we can short-circuit in the size_transform if the caps + * are the same */ + gst_caps_replace (&resample->sinkcaps, incaps); + gst_caps_replace (&resample->srccaps, outcaps); + + return TRUE; +} + +#define GST_MAXINT24 (8388607) +#define GST_MININT24 (-8388608) + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +#define GST_READ_UINT24 GST_READ_UINT24_LE +#define GST_WRITE_UINT24 GST_WRITE_UINT24_LE +#else +#define GST_READ_UINT24 GST_READ_UINT24_BE +#define GST_WRITE_UINT24 GST_WRITE_UINT24_BE +#endif + +static void +gst_audio_resample_convert_buffer (GstAudioResample * resample, + const guint8 * in, guint8 * out, guint len, gboolean inverse) +{ + len *= resample->channels; + + if (inverse) { + if (gst_audio_resample_use_int && resample->width == 8 && !resample->fp) { + gint8 *o = (gint8 *) out; + gint16 *i = (gint16 *) in; + gint32 tmp; + + while (len) { + tmp = *i + (G_MAXINT8 >> 1); + *o = CLAMP (tmp >> 8, G_MININT8, G_MAXINT8); + o++; + i++; + len--; + } + } else if (!gst_audio_resample_use_int && resample->width == 8 + && !resample->fp) { + gint8 *o = (gint8 *) out; + gfloat *i = (gfloat *) in; + gfloat tmp; + + while (len) { + tmp = *i; + *o = (gint8) CLAMP (tmp * G_MAXINT8 + 0.5, G_MININT8, G_MAXINT8); + o++; + i++; + len--; + } + } else if (!gst_audio_resample_use_int && resample->width == 16 + && !resample->fp) { + gint16 *o = (gint16 *) out; + gfloat *i = (gfloat *) in; + gfloat tmp; + + while (len) { + tmp = *i; + *o = (gint16) CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16); + o++; + i++; + len--; + } + } else if (resample->width == 24 && !resample->fp) { + guint8 *o = (guint8 *) out; + gdouble *i = (gdouble *) in; + gdouble tmp; + + while (len) { + tmp = *i; + GST_WRITE_UINT24 (o, (gint32) CLAMP (tmp * GST_MAXINT24 + 0.5, + GST_MININT24, GST_MAXINT24)); + o += 3; + i++; + len--; + } + } else if (resample->width == 32 && !resample->fp) { + gint32 *o = (gint32 *) out; + gdouble *i = (gdouble *) in; + gdouble tmp; + + while (len) { + tmp = *i; + *o = (gint32) CLAMP (tmp * G_MAXINT32 + 0.5, G_MININT32, G_MAXINT32); + o++; + i++; + len--; + } + } else { + g_assert_not_reached (); + } + } else { + if (gst_audio_resample_use_int && resample->width == 8 && !resample->fp) { + gint8 *i = (gint8 *) in; + gint16 *o = (gint16 *) out; + gint32 tmp; + + while (len) { + tmp = *i; + *o = tmp << 8; + o++; + i++; + len--; + } + } else if (!gst_audio_resample_use_int && resample->width == 8 + && !resample->fp) { + gint8 *i = (gint8 *) in; + gfloat *o = (gfloat *) out; + gfloat tmp; + + while (len) { + tmp = *i; + *o = tmp / G_MAXINT8; + o++; + i++; + len--; + } + } else if (!gst_audio_resample_use_int && resample->width == 16 + && !resample->fp) { + gint16 *i = (gint16 *) in; + gfloat *o = (gfloat *) out; + gfloat tmp; + + while (len) { + tmp = *i; + *o = tmp / G_MAXINT16; + o++; + i++; + len--; + } + } else if (resample->width == 24 && !resample->fp) { + guint8 *i = (guint8 *) in; + gdouble *o = (gdouble *) out; + gdouble tmp; + guint32 tmp2; + + while (len) { + tmp2 = GST_READ_UINT24 (i); + if (tmp2 & 0x00800000) + tmp2 |= 0xff000000; + tmp = (gint32) tmp2; + *o = tmp / GST_MAXINT24; + o++; + i += 3; + len--; + } + } else if (resample->width == 32 && !resample->fp) { + gint32 *i = (gint32 *) in; + gdouble *o = (gdouble *) out; + gdouble tmp; + + while (len) { + tmp = *i; + *o = tmp / G_MAXINT32; + o++; + i++; + len--; + } + } else { + g_assert_not_reached (); + } + } +} + +static guint8 * +gst_audio_resample_workspace_realloc (guint8 ** workspace, guint * size, + guint new_size) +{ + guint8 *new; + if (new_size <= *size) + /* no need to resize */ + return *workspace; + new = g_realloc (*workspace, new_size); + if (!new) + /* failure (re)allocating memeory */ + return NULL; + /* success */ + *workspace = new; + *size = new_size; + return *workspace; +} + +/* Push history_len zeros into the filter, but discard the output. */ +static void +gst_audio_resample_dump_drain (GstAudioResample * resample, guint history_len) +{ + gint outsize; + guint in_len, in_processed; + guint out_len, out_processed; + guint num, den; + gpointer buf; + + g_assert (resample->state != NULL); + + resample->funcs->get_ratio (resample->state, &num, &den); + + in_len = in_processed = history_len; + out_processed = out_len = + gst_util_uint64_scale_int_ceil (history_len, den, num); + outsize = out_len * resample->channels * (resample->funcs->width / 8); + + if (out_len == 0) + return; + + buf = g_malloc (outsize); + resample->funcs->process (resample->state, NULL, &in_processed, buf, + &out_processed); + g_free (buf); + + g_assert (in_len == in_processed); +} + +static void +gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len) +{ + GstBuffer *outbuf; + GstFlowReturn res; + gint outsize; + guint in_len, in_processed; + guint out_len, out_processed; + gint err; + guint num, den; + + g_assert (resample->state != NULL); + + /* Don't drain samples if we were reset. */ + if (!GST_CLOCK_TIME_IS_VALID (resample->t0)) + return; + + resample->funcs->get_ratio (resample->state, &num, &den); + + in_len = in_processed = history_len; + out_len = out_processed = + gst_util_uint64_scale_int_ceil (history_len, den, num); + outsize = out_len * resample->channels * (resample->width / 8); + + if (out_len == 0) + return; + + res = + gst_pad_alloc_buffer_and_set_caps (GST_BASE_TRANSFORM_SRC_PAD (resample), + GST_BUFFER_OFFSET_NONE, outsize, + GST_PAD_CAPS (GST_BASE_TRANSFORM_SRC_PAD (resample)), &outbuf); + if (G_UNLIKELY (res != GST_FLOW_OK)) { + GST_WARNING_OBJECT (resample, "failed allocating buffer of %d bytes", + outsize); + return; + } + + if (resample->funcs->width != resample->width) { + /* need to convert data format; allocate workspace */ + if (!gst_audio_resample_workspace_realloc (&resample->tmp_out, + &resample->tmp_out_size, (resample->funcs->width / 8) * out_len * + resample->channels)) { + GST_ERROR_OBJECT (resample, "failed to allocate workspace"); + return; + } + + /* process */ + err = resample->funcs->process (resample->state, NULL, &in_processed, + resample->tmp_out, &out_processed); + + /* convert output format */ + gst_audio_resample_convert_buffer (resample, resample->tmp_out, + GST_BUFFER_DATA (outbuf), out_processed, TRUE); + } else { + /* don't need to convert data format; process */ + err = resample->funcs->process (resample->state, NULL, &in_processed, + GST_BUFFER_DATA (outbuf), &out_processed); + } + + /* If we wrote more than allocated something is really wrong now + * and we should better abort immediately */ + g_assert (out_len >= out_processed); + + if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { + GST_WARNING_OBJECT (resample, "Failed to process drain: %s", + resample->funcs->strerror (err)); + gst_buffer_unref (outbuf); + return; + } + + /* time */ + if (GST_CLOCK_TIME_IS_VALID (resample->t0)) { + GST_BUFFER_TIMESTAMP (outbuf) = resample->t0 + + gst_util_uint64_scale_int_round (resample->samples_out, GST_SECOND, + resample->outrate); + GST_BUFFER_DURATION (outbuf) = resample->t0 + + gst_util_uint64_scale_int_round (resample->samples_out + out_processed, + GST_SECOND, resample->outrate) - GST_BUFFER_TIMESTAMP (outbuf); + } else { + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; + } + /* offset */ + if (resample->out_offset0 != GST_BUFFER_OFFSET_NONE) { + GST_BUFFER_OFFSET (outbuf) = resample->out_offset0 + resample->samples_out; + GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET (outbuf) + out_processed; + } else { + GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE; + } + /* move along */ + resample->samples_out += out_processed; + resample->samples_in += history_len; + + if (G_UNLIKELY (out_processed == 0 && in_len * den > num)) { + GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer"); + gst_buffer_unref (outbuf); + return; + } + + GST_BUFFER_SIZE (outbuf) = + out_processed * resample->channels * (resample->width / 8); + + GST_LOG_OBJECT (resample, + "Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT + " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %" + G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf), + GST_BUFFER_OFFSET_END (outbuf)); + + res = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (resample), outbuf); + + if (G_UNLIKELY (res != GST_FLOW_OK)) + GST_WARNING_OBJECT (resample, "Failed to push drain: %s", + gst_flow_get_name (res)); + + return; +} + +static gboolean +gst_audio_resample_event (GstBaseTransform * base, GstEvent * event) +{ + GstAudioResample *resample = GST_AUDIO_RESAMPLE (base); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_audio_resample_reset_state (resample); + if (resample->state) + resample->funcs->skip_zeros (resample->state); + resample->num_gap_samples = 0; + resample->num_nongap_samples = 0; + resample->t0 = GST_CLOCK_TIME_NONE; + resample->in_offset0 = GST_BUFFER_OFFSET_NONE; + resample->out_offset0 = GST_BUFFER_OFFSET_NONE; + resample->samples_in = 0; + resample->samples_out = 0; + resample->need_discont = TRUE; + break; + case GST_EVENT_NEWSEGMENT: + if (resample->state) { + guint latency = resample->funcs->get_input_latency (resample->state); + gst_audio_resample_push_drain (resample, latency); + } + gst_audio_resample_reset_state (resample); + if (resample->state) + resample->funcs->skip_zeros (resample->state); + resample->num_gap_samples = 0; + resample->num_nongap_samples = 0; + resample->t0 = GST_CLOCK_TIME_NONE; + resample->in_offset0 = GST_BUFFER_OFFSET_NONE; + resample->out_offset0 = GST_BUFFER_OFFSET_NONE; + resample->samples_in = 0; + resample->samples_out = 0; + resample->need_discont = TRUE; + break; + case GST_EVENT_EOS: + if (resample->state) { + guint latency = resample->funcs->get_input_latency (resample->state); + gst_audio_resample_push_drain (resample, latency); + } + gst_audio_resample_reset_state (resample); + break; + default: + break; + } + + return parent_class->event (base, event); +} + +static gboolean +gst_audio_resample_check_discont (GstAudioResample * resample, GstBuffer * buf) +{ + guint64 offset; + guint64 delta; + + /* is the incoming buffer a discontinuity? */ + if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) + return TRUE; + + /* no valid timestamps or offsets to compare --> no discontinuity */ + if (G_UNLIKELY (!(GST_BUFFER_TIMESTAMP_IS_VALID (buf) && + GST_CLOCK_TIME_IS_VALID (resample->t0)))) + return FALSE; + + /* convert the inbound timestamp to an offset. */ + offset = + gst_util_uint64_scale_int_round (GST_BUFFER_TIMESTAMP (buf) - + resample->t0, resample->inrate, GST_SECOND); + + /* many elements generate imperfect streams due to rounding errors, so we + * permit a small error (up to one sample) without triggering a filter + * flush/restart (if triggered incorrectly, this will be audible) */ + /* allow even up to more samples, since sink is not so strict anyway, + * so give that one a chance to handle this as configured */ + delta = ABS ((gint64) (offset - resample->samples_in)); + if (delta <= (resample->inrate >> 5)) + return FALSE; + + GST_WARNING_OBJECT (resample, + "encountered timestamp discontinuity of %" G_GUINT64_FORMAT " samples = %" + GST_TIME_FORMAT, delta, + GST_TIME_ARGS (gst_util_uint64_scale_int_round (delta, GST_SECOND, + resample->inrate))); + return TRUE; +} + +static GstFlowReturn +gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + guint32 in_len, in_processed; + guint32 out_len, out_processed; + guint filt_len = resample->funcs->get_filt_len (resample->state); + + in_len = GST_BUFFER_SIZE (inbuf) / resample->channels; + out_len = GST_BUFFER_SIZE (outbuf) / resample->channels; + + in_len /= (resample->width / 8); + out_len /= (resample->width / 8); + + in_processed = in_len; + out_processed = out_len; + + if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) { + resample->num_nongap_samples = 0; + if (resample->num_gap_samples < filt_len) { + guint zeros_to_push; + if (in_len >= filt_len - resample->num_gap_samples) + zeros_to_push = filt_len - resample->num_gap_samples; + else + zeros_to_push = in_len; + + gst_audio_resample_push_drain (resample, zeros_to_push); + in_len -= zeros_to_push; + resample->num_gap_samples += zeros_to_push; + } + + { + guint num, den; + resample->funcs->get_ratio (resample->state, &num, &den); + if (resample->samples_in + in_len >= filt_len / 2) + out_processed = + gst_util_uint64_scale_int_ceil (resample->samples_in + in_len - + filt_len / 2, den, num) - resample->samples_out; + else + out_processed = 0; + + memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf)); + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); + resample->num_gap_samples += in_len; + in_processed = in_len; + } + } else { /* not a gap */ + + gint err; + + if (resample->num_gap_samples > filt_len) { + /* push in enough zeros to restore the filter to the right offset */ + guint num, den; + resample->funcs->get_ratio (resample->state, &num, &den); + gst_audio_resample_dump_drain (resample, + (resample->num_gap_samples - filt_len) % num); + } + resample->num_gap_samples = 0; + if (resample->num_nongap_samples < filt_len) { + resample->num_nongap_samples += in_len; + if (resample->num_nongap_samples > filt_len) + resample->num_nongap_samples = filt_len; + } + + if (resample->funcs->width != resample->width) { + /* need to convert data format for processing; ensure we have enough + * workspace available */ + if (!gst_audio_resample_workspace_realloc (&resample->tmp_in, + &resample->tmp_in_size, in_len * resample->channels * + (resample->funcs->width / 8)) || + !gst_audio_resample_workspace_realloc (&resample->tmp_out, + &resample->tmp_out_size, out_len * resample->channels * + (resample->funcs->width / 8))) { + GST_ERROR_OBJECT (resample, "failed to allocate workspace"); + return GST_FLOW_ERROR; + } + + /* convert input */ + gst_audio_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf), + resample->tmp_in, in_len, FALSE); + + /* process */ + err = resample->funcs->process (resample->state, + resample->tmp_in, &in_processed, resample->tmp_out, &out_processed); + + /* convert output */ + gst_audio_resample_convert_buffer (resample, resample->tmp_out, + GST_BUFFER_DATA (outbuf), out_processed, TRUE); + } else { + /* no format conversion required; process */ + err = resample->funcs->process (resample->state, + GST_BUFFER_DATA (inbuf), &in_processed, + GST_BUFFER_DATA (outbuf), &out_processed); + } + + if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) { + GST_ERROR_OBJECT (resample, "Failed to convert data: %s", + resample->funcs->strerror (err)); + return GST_FLOW_ERROR; + } + } + + /* If we wrote more than allocated something is really wrong now and we + * should better abort immediately */ + g_assert (out_len >= out_processed); + + if (G_UNLIKELY (in_len != in_processed)) { + GST_WARNING_OBJECT (resample, "converted %d of %d input samples", + in_processed, in_len); + } + + /* time */ + if (GST_CLOCK_TIME_IS_VALID (resample->t0)) { + GST_BUFFER_TIMESTAMP (outbuf) = resample->t0 + + gst_util_uint64_scale_int_round (resample->samples_out, GST_SECOND, + resample->outrate); + GST_BUFFER_DURATION (outbuf) = resample->t0 + + gst_util_uint64_scale_int_round (resample->samples_out + out_processed, + GST_SECOND, resample->outrate) - GST_BUFFER_TIMESTAMP (outbuf); + } else { + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; + } + /* offset */ + if (resample->out_offset0 != GST_BUFFER_OFFSET_NONE) { + GST_BUFFER_OFFSET (outbuf) = resample->out_offset0 + resample->samples_out; + GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET (outbuf) + out_processed; + } else { + GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE; + } + /* move along */ + resample->samples_out += out_processed; + resample->samples_in += in_len; + + GST_BUFFER_SIZE (outbuf) = + out_processed * resample->channels * (resample->width / 8); + + GST_LOG_OBJECT (resample, + "Converted to buffer of %" G_GUINT32_FORMAT + " samples (%u bytes) with timestamp %" GST_TIME_FORMAT ", duration %" + GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT ", offset_end %" + G_GUINT64_FORMAT, out_processed, GST_BUFFER_SIZE (outbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), + GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf)); + + if (out_processed == 0) { + GST_DEBUG_OBJECT (resample, "buffer dropped"); + return GST_BASE_TRANSFORM_FLOW_DROPPED; + } + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstAudioResample *resample = GST_AUDIO_RESAMPLE (base); + gulong size; + GstFlowReturn ret; + + if (resample->state == NULL) { + if (G_UNLIKELY (!(resample->state = + gst_audio_resample_init_state (resample, resample->width, + resample->channels, resample->inrate, resample->outrate, + resample->quality, resample->fp)))) + return GST_FLOW_ERROR; + + resample->funcs = + gst_audio_resample_get_funcs (resample->width, resample->fp); + } + + size = GST_BUFFER_SIZE (inbuf); + + GST_LOG_OBJECT (resample, "transforming buffer of %ld bytes, ts %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %" + G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, + size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)), + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf)); + + /* check for timestamp discontinuities; flush/reset if needed, and set + * flag to resync timestamp and offset counters and send event + * downstream */ + if (G_UNLIKELY (gst_audio_resample_check_discont (resample, inbuf))) { + gst_audio_resample_reset_state (resample); + resample->need_discont = TRUE; + } + + /* handle discontinuity */ + if (G_UNLIKELY (resample->need_discont)) { + resample->funcs->skip_zeros (resample->state); + resample->num_gap_samples = 0; + resample->num_nongap_samples = 0; + /* reset */ + resample->samples_in = 0; + resample->samples_out = 0; + GST_DEBUG_OBJECT (resample, "found discontinuity; resyncing"); + /* resync the timestamp and offset counters if possible */ + if (GST_BUFFER_TIMESTAMP_IS_VALID (inbuf)) { + resample->t0 = GST_BUFFER_TIMESTAMP (inbuf); + } else { + GST_DEBUG_OBJECT (resample, "... but new timestamp is invalid"); + resample->t0 = GST_CLOCK_TIME_NONE; + } + if (GST_BUFFER_OFFSET_IS_VALID (inbuf)) { + resample->in_offset0 = GST_BUFFER_OFFSET (inbuf); + resample->out_offset0 = + gst_util_uint64_scale_int_round (resample->in_offset0, + resample->outrate, resample->inrate); + } else { + GST_DEBUG_OBJECT (resample, "... but new offset is invalid"); + resample->in_offset0 = GST_BUFFER_OFFSET_NONE; + resample->out_offset0 = GST_BUFFER_OFFSET_NONE; + } + /* set DISCONT flag on output buffer */ + GST_DEBUG_OBJECT (resample, "marking this buffer with the DISCONT flag"); + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + resample->need_discont = FALSE; + } + + ret = gst_audio_resample_process (resample, inbuf, outbuf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + return ret; + + GST_DEBUG_OBJECT (resample, "input = samples [%" G_GUINT64_FORMAT ", %" + G_GUINT64_FORMAT ") = [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT + ") ns; output = samples [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT + ") = [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ") ns", + GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf), + GST_BUFFER_TIMESTAMP (inbuf), GST_BUFFER_TIMESTAMP (inbuf) + + GST_BUFFER_DURATION (inbuf), GST_BUFFER_OFFSET (outbuf), + GST_BUFFER_OFFSET_END (outbuf), GST_BUFFER_TIMESTAMP (outbuf), + GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf)); + + return GST_FLOW_OK; +} + +static gboolean +gst_audio_resample_query (GstPad * pad, GstQuery * query) +{ + GstAudioResample *resample = GST_AUDIO_RESAMPLE (gst_pad_get_parent (pad)); + GstBaseTransform *trans; + gboolean res = TRUE; + if (G_UNLIKELY (resample == NULL)) + return FALSE; + + trans = GST_BASE_TRANSFORM (resample); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GstClockTime min, max; + gboolean live; + guint64 latency; + GstPad *peer; + gint rate = resample->inrate; + gint resampler_latency; + + if (resample->state) + resampler_latency = + resample->funcs->get_input_latency (resample->state); + else + resampler_latency = 0; + + if (gst_base_transform_is_passthrough (trans)) + resampler_latency = 0; + + if ((peer = gst_pad_get_peer (GST_BASE_TRANSFORM_SINK_PAD (trans)))) { + if ((res = gst_pad_query (peer, query))) { + gst_query_parse_latency (query, &live, &min, &max); + + GST_DEBUG_OBJECT (resample, "Peer latency: min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + /* add our own latency */ + if (rate != 0 && resampler_latency != 0) + latency = gst_util_uint64_scale_round (resampler_latency, + GST_SECOND, rate); + else + latency = 0; + + GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT, + GST_TIME_ARGS (latency)); + + min += latency; + if (GST_CLOCK_TIME_IS_VALID (max)) + max += latency; + + GST_DEBUG_OBJECT (resample, "Calculated total latency : min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + gst_query_set_latency (query, live, min, max); + } + gst_object_unref (peer); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + gst_object_unref (resample); + return res; +} + +static const GstQueryType * +gst_audio_resample_query_type (GstPad * pad) +{ + static const GstQueryType types[] = { + GST_QUERY_LATENCY, + 0 + }; + + return types; +} + +static void +gst_audio_resample_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAudioResample *resample; + + resample = GST_AUDIO_RESAMPLE (object); + + switch (prop_id) { + case PROP_QUALITY: + GST_BASE_TRANSFORM_LOCK (resample); + resample->quality = g_value_get_int (value); + GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); + + gst_audio_resample_update_state (resample, resample->width, + resample->channels, resample->inrate, resample->outrate, + resample->quality, resample->fp); + GST_BASE_TRANSFORM_UNLOCK (resample); + break; + case PROP_FILTER_LENGTH:{ + gint filter_length = g_value_get_int (value); + + GST_BASE_TRANSFORM_LOCK (resample); + if (filter_length <= 8) + resample->quality = 0; + else if (filter_length <= 16) + resample->quality = 1; + else if (filter_length <= 32) + resample->quality = 2; + else if (filter_length <= 48) + resample->quality = 3; + else if (filter_length <= 64) + resample->quality = 4; + else if (filter_length <= 80) + resample->quality = 5; + else if (filter_length <= 96) + resample->quality = 6; + else if (filter_length <= 128) + resample->quality = 7; + else if (filter_length <= 160) + resample->quality = 8; + else if (filter_length <= 192) + resample->quality = 9; + else + resample->quality = 10; + + GST_DEBUG_OBJECT (resample, "new quality %d", resample->quality); + + gst_audio_resample_update_state (resample, resample->width, + resample->channels, resample->inrate, resample->outrate, + resample->quality, resample->fp); + GST_BASE_TRANSFORM_UNLOCK (resample); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_audio_resample_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAudioResample *resample; + + resample = GST_AUDIO_RESAMPLE (object); + + switch (prop_id) { + case PROP_QUALITY: + g_value_set_int (value, resample->quality); + break; + case PROP_FILTER_LENGTH: + switch (resample->quality) { + case 0: + g_value_set_int (value, 8); + break; + case 1: + g_value_set_int (value, 16); + break; + case 2: + g_value_set_int (value, 32); + break; + case 3: + g_value_set_int (value, 48); + break; + case 4: + g_value_set_int (value, 64); + break; + case 5: + g_value_set_int (value, 80); + break; + case 6: + g_value_set_int (value, 96); + break; + case 7: + g_value_set_int (value, 128); + break; + case 8: + g_value_set_int (value, 160); + break; + case 9: + g_value_set_int (value, 192); + break; + case 10: + g_value_set_int (value, 256); + break; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* FIXME: should have a benchmark fallback for the case where orc is disabled */ +#if defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC) + +#define BENCHMARK_SIZE 512 + +static gboolean +_benchmark_int_float (SpeexResamplerState * st) +{ + gint16 in[BENCHMARK_SIZE] = { 0, }, G_GNUC_UNUSED out[BENCHMARK_SIZE / 2]; + gfloat in_tmp[BENCHMARK_SIZE], out_tmp[BENCHMARK_SIZE / 2]; + gint i; + guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2; + + for (i = 0; i < BENCHMARK_SIZE; i++) { + gfloat tmp = in[i]; + in_tmp[i] = tmp / G_MAXINT16; + } + + resample_float_resampler_process_interleaved_float (st, + (const guint8 *) in_tmp, &inlen, (guint8 *) out_tmp, &outlen); + + if (outlen == 0) { + GST_ERROR ("Failed to use float resampler"); + return FALSE; + } + + for (i = 0; i < outlen; i++) { + gfloat tmp = out_tmp[i]; + out[i] = CLAMP (tmp * G_MAXINT16 + 0.5, G_MININT16, G_MAXINT16); + } + + return TRUE; +} + +static gboolean +_benchmark_int_int (SpeexResamplerState * st) +{ + gint16 in[BENCHMARK_SIZE] = { 0, }, out[BENCHMARK_SIZE / 2]; + guint32 inlen = BENCHMARK_SIZE, outlen = BENCHMARK_SIZE / 2; + + resample_int_resampler_process_interleaved_int (st, (const guint8 *) in, + &inlen, (guint8 *) out, &outlen); + + if (outlen == 0) { + GST_ERROR ("Failed to use int resampler"); + return FALSE; + } + + return TRUE; +} + +static gboolean +_benchmark_integer_resampling (void) +{ + OrcProfile a, b; + gdouble av, bv; + SpeexResamplerState *sta, *stb; + int i; + + orc_profile_init (&a); + orc_profile_init (&b); + + sta = resample_float_resampler_init (1, 48000, 24000, 4, NULL); + if (sta == NULL) { + GST_ERROR ("Failed to create float resampler state"); + return FALSE; + } + + stb = resample_int_resampler_init (1, 48000, 24000, 4, NULL); + if (stb == NULL) { + resample_float_resampler_destroy (sta); + GST_ERROR ("Failed to create int resampler state"); + return FALSE; + } + + /* Benchmark */ + for (i = 0; i < 10; i++) { + orc_profile_start (&a); + if (!_benchmark_int_float (sta)) + goto error; + orc_profile_stop (&a); + } + + /* Benchmark */ + for (i = 0; i < 10; i++) { + orc_profile_start (&b); + if (!_benchmark_int_int (stb)) + goto error; + orc_profile_stop (&b); + } + + /* Handle results */ + orc_profile_get_ave_std (&a, &av, NULL); + orc_profile_get_ave_std (&b, &bv, NULL); + + /* Remember benchmark result in global variable */ + gst_audio_resample_use_int = (av > bv); + resample_float_resampler_destroy (sta); + resample_int_resampler_destroy (stb); + + if (av > bv) + GST_INFO ("Using integer resampler if appropiate: %lf < %lf", bv, av); + else + GST_INFO ("Using float resampler for everything: %lf <= %lf", av, bv); + + return TRUE; + +error: + resample_float_resampler_destroy (sta); + resample_int_resampler_destroy (stb); + + return FALSE; +} +#endif /* defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC) */ + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (audio_resample_debug, "audioresample", 0, + "audio resampling element"); + +#if defined(AUDIORESAMPLE_FORMAT_AUTO) && !defined(DISABLE_ORC) + if (!_benchmark_integer_resampling ()) + return FALSE; +#else + GST_WARNING ("Orc disabled, can't benchmark int vs. float resampler"); + { + GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); + GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); + GST_CAT_WARNING (GST_CAT_PERFORMANCE, "orc disabled, no benchmarking done"); + } +#endif + + if (!gst_element_register (plugin, "audioresample", GST_RANK_PRIMARY, + GST_TYPE_AUDIO_RESAMPLE)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "audioresample", + "Resamples audio", plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN); diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.h b/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.h new file mode 100644 index 0000000..f5f7464 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/gstaudioresample.h @@ -0,0 +1,95 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2007-2008> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __AUDIO_RESAMPLE_H__ +#define __AUDIO_RESAMPLE_H__ + +#include +#include +#include + +#include "speex_resampler_wrapper.h" + +G_BEGIN_DECLS + +#define GST_TYPE_AUDIO_RESAMPLE \ + (gst_audio_resample_get_type()) +#define GST_AUDIO_RESAMPLE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_RESAMPLE,GstAudioResample)) +#define GST_AUDIO_RESAMPLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_RESAMPLE,GstAudioResampleClass)) +#define GST_IS_AUDIO_RESAMPLE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_RESAMPLE)) +#define GST_IS_AUDIO_RESAMPLE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_RESAMPLE)) + +typedef struct _GstAudioResample GstAudioResample; +typedef struct _GstAudioResampleClass GstAudioResampleClass; + +/** + * GstAudioResample: + * + * Opaque data structure. + */ +struct _GstAudioResample { + GstBaseTransform element; + + /* */ + + GstCaps *srccaps, *sinkcaps; + + gboolean need_discont; + + GstClockTime t0; + guint64 in_offset0; + guint64 out_offset0; + guint64 samples_in; + guint64 samples_out; + + guint64 num_gap_samples; + guint64 num_nongap_samples; + + gint channels; + gint inrate; + gint outrate; + gint quality; + gint width; + gboolean fp; + + guint8 *tmp_in; + guint tmp_in_size; + + guint8 *tmp_out; + guint tmp_out_size; + + SpeexResamplerState *state; + const SpeexResampleFuncs *funcs; +}; + +struct _GstAudioResampleClass { + GstBaseTransformClass parent_class; +}; + +GType gst_audio_resample_get_type(void); + +G_END_DECLS + +#endif /* __AUDIO_RESAMPLE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/resample.c b/gst-plugins-base-subtitles0.10/gst/audioresample/resample.c new file mode 100644 index 0000000..7d42f0e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/resample.c @@ -0,0 +1,1354 @@ +/* Copyright (C) 2007-2008 Jean-Marc Valin + Copyright (C) 2008 Thorvald Natvig + + File: resample.c + Arbitrary resampling code + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +/* + The design goals of this code are: + - Very fast algorithm + - SIMD-friendly algorithm + - Low memory requirement + - Good *perceptual* quality (and not best SNR) + + Warning: This resampler is relatively new. Although I think I got rid of + all the major bugs and I don't expect the API to change anymore, there + may be something I've missed. So use with caution. + + This algorithm is based on this original resampling algorithm: + Smith, Julius O. Digital Audio Resampling Home Page + Center for Computer Research in Music and Acoustics (CCRMA), + Stanford University, 2007. + Web published at http://www-ccrma.stanford.edu/~jos/resample/. + + There is one main difference, though. This resampler uses cubic + interpolation instead of linear interpolation in the above paper. This + makes the table much smaller and makes it possible to compute that table + on a per-stream basis. In turn, being able to tweak the table for each + stream makes it possible to both reduce complexity on simple ratios + (e.g. 2/3), and get rid of the rounding operations in the inner loop. + The latter both reduces CPU time and makes the algorithm more SIMD-friendly. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef OUTSIDE_SPEEX +#include + +#include + +#define EXPORT G_GNUC_INTERNAL + +static inline void * +speex_alloc (int size) +{ + return g_malloc0 (size); +} + +static inline void * +speex_realloc (void *ptr, int size) +{ + return g_realloc (ptr, size); +} + +static inline void +speex_free (void *ptr) +{ + g_free (ptr); +} + +#include "speex_resampler.h" +#include "arch.h" +#else /* OUTSIDE_SPEEX */ + +#include "../include/speex/speex_resampler.h" +#include "arch.h" +#include "os_support.h" +#endif /* OUTSIDE_SPEEX */ + +#include + +#ifndef M_PI +#define M_PI 3.14159263 +#endif + +#ifdef FIXED_POINT +#define WORD2INT(x) ((x) < -32767 ? -32768 : ((x) > 32766 ? 32767 : (x))) +#else +#define WORD2INT(x) ((x) < -32767.5f ? -32768 : ((x) > 32766.5f ? 32767 : floor(.5+(x)))) +#endif + +#define IMAX(a,b) ((a) > (b) ? (a) : (b)) +#define IMIN(a,b) ((a) < (b) ? (a) : (b)) + +#ifndef NULL +#define NULL 0 +#endif + +#ifdef _USE_SSE +#include "resample_sse.h" +#endif + +/* Numer of elements to allocate on the stack */ +#ifdef VAR_ARRAYS +#define FIXED_STACK_ALLOC 8192 +#else +#define FIXED_STACK_ALLOC 1024 +#endif + +typedef int (*resampler_basic_func) (SpeexResamplerState *, spx_uint32_t, + const spx_word16_t *, spx_uint32_t *, spx_word16_t *, spx_uint32_t *); + +struct SpeexResamplerState_ +{ + spx_uint32_t in_rate; + spx_uint32_t out_rate; + spx_uint32_t num_rate; + spx_uint32_t den_rate; + + int quality; + spx_uint32_t nb_channels; + spx_uint32_t filt_len; + spx_uint32_t mem_alloc_size; + spx_uint32_t buffer_size; + int int_advance; + int frac_advance; + float cutoff; + spx_uint32_t oversample; + int initialised; + int started; + + /* These are per-channel */ + spx_int32_t *last_sample; + spx_uint32_t *samp_frac_num; + spx_uint32_t *magic_samples; + + spx_word16_t *mem; + spx_word16_t *sinc_table; + spx_uint32_t sinc_table_length; + resampler_basic_func resampler_ptr; + + int in_stride; + int out_stride; +}; + +static double kaiser12_table[68] = { + 0.99859849, 1.00000000, 0.99859849, 0.99440475, 0.98745105, 0.97779076, + 0.96549770, 0.95066529, 0.93340547, 0.91384741, 0.89213598, 0.86843014, + 0.84290116, 0.81573067, 0.78710866, 0.75723148, 0.72629970, 0.69451601, + 0.66208321, 0.62920216, 0.59606986, 0.56287762, 0.52980938, 0.49704014, + 0.46473455, 0.43304576, 0.40211431, 0.37206735, 0.34301800, 0.31506490, + 0.28829195, 0.26276832, 0.23854851, 0.21567274, 0.19416736, 0.17404546, + 0.15530766, 0.13794294, 0.12192957, 0.10723616, 0.09382272, 0.08164178, + 0.07063950, 0.06075685, 0.05193064, 0.04409466, 0.03718069, 0.03111947, + 0.02584161, 0.02127838, 0.01736250, 0.01402878, 0.01121463, 0.00886058, + 0.00691064, 0.00531256, 0.00401805, 0.00298291, 0.00216702, 0.00153438, + 0.00105297, 0.00069463, 0.00043489, 0.00025272, 0.00013031, 0.0000527734, + 0.00001000, 0.00000000 +}; + +/* +static double kaiser12_table[36] = { + 0.99440475, 1.00000000, 0.99440475, 0.97779076, 0.95066529, 0.91384741, + 0.86843014, 0.81573067, 0.75723148, 0.69451601, 0.62920216, 0.56287762, + 0.49704014, 0.43304576, 0.37206735, 0.31506490, 0.26276832, 0.21567274, + 0.17404546, 0.13794294, 0.10723616, 0.08164178, 0.06075685, 0.04409466, + 0.03111947, 0.02127838, 0.01402878, 0.00886058, 0.00531256, 0.00298291, + 0.00153438, 0.00069463, 0.00025272, 0.0000527734, 0.00000500, 0.00000000}; +*/ +static double kaiser10_table[36] = { + 0.99537781, 1.00000000, 0.99537781, 0.98162644, 0.95908712, 0.92831446, + 0.89005583, 0.84522401, 0.79486424, 0.74011713, 0.68217934, 0.62226347, + 0.56155915, 0.50119680, 0.44221549, 0.38553619, 0.33194107, 0.28205962, + 0.23636152, 0.19515633, 0.15859932, 0.12670280, 0.09935205, 0.07632451, + 0.05731132, 0.04193980, 0.02979584, 0.02044510, 0.01345224, 0.00839739, + 0.00488951, 0.00257636, 0.00115101, 0.00035515, 0.00000000, 0.00000000 +}; + +static double kaiser8_table[36] = { + 0.99635258, 1.00000000, 0.99635258, 0.98548012, 0.96759014, 0.94302200, + 0.91223751, 0.87580811, 0.83439927, 0.78875245, 0.73966538, 0.68797126, + 0.63451750, 0.58014482, 0.52566725, 0.47185369, 0.41941150, 0.36897272, + 0.32108304, 0.27619388, 0.23465776, 0.19672670, 0.16255380, 0.13219758, + 0.10562887, 0.08273982, 0.06335451, 0.04724088, 0.03412321, 0.02369490, + 0.01563093, 0.00959968, 0.00527363, 0.00233883, 0.00050000, 0.00000000 +}; + +static double kaiser6_table[36] = { + 0.99733006, 1.00000000, 0.99733006, 0.98935595, 0.97618418, 0.95799003, + 0.93501423, 0.90755855, 0.87598009, 0.84068475, 0.80211977, 0.76076565, + 0.71712752, 0.67172623, 0.62508937, 0.57774224, 0.53019925, 0.48295561, + 0.43647969, 0.39120616, 0.34752997, 0.30580127, 0.26632152, 0.22934058, + 0.19505503, 0.16360756, 0.13508755, 0.10953262, 0.08693120, 0.06722600, + 0.05031820, 0.03607231, 0.02432151, 0.01487334, 0.00752000, 0.00000000 +}; + +struct FuncDef +{ + double *table; + int oversample; +}; + +static struct FuncDef _KAISER12 = { kaiser12_table, 64 }; + +#define KAISER12 (&_KAISER12) +/*static struct FuncDef _KAISER12 = {kaiser12_table, 32}; +#define KAISER12 (&_KAISER12)*/ +static struct FuncDef _KAISER10 = { kaiser10_table, 32 }; + +#define KAISER10 (&_KAISER10) +static struct FuncDef _KAISER8 = { kaiser8_table, 32 }; + +#define KAISER8 (&_KAISER8) +static struct FuncDef _KAISER6 = { kaiser6_table, 32 }; + +#define KAISER6 (&_KAISER6) + +struct QualityMapping +{ + int base_length; + int oversample; + float downsample_bandwidth; + float upsample_bandwidth; + struct FuncDef *window_func; +}; + + +/* This table maps conversion quality to internal parameters. There are two + reasons that explain why the up-sampling bandwidth is larger than the + down-sampling bandwidth: + 1) When up-sampling, we can assume that the spectrum is already attenuated + close to the Nyquist rate (from an A/D or a previous resampling filter) + 2) Any aliasing that occurs very close to the Nyquist rate will be masked + by the sinusoids/noise just below the Nyquist rate (guaranteed only for + up-sampling). +*/ +static const struct QualityMapping quality_map[11] = { + {8, 4, 0.830f, 0.860f, KAISER6}, /* Q0 */ + {16, 4, 0.850f, 0.880f, KAISER6}, /* Q1 */ + {32, 4, 0.882f, 0.910f, KAISER6}, /* Q2 *//* 82.3% cutoff ( ~60 dB stop) 6 */ + {48, 8, 0.895f, 0.917f, KAISER8}, /* Q3 *//* 84.9% cutoff ( ~80 dB stop) 8 */ + {64, 8, 0.921f, 0.940f, KAISER8}, /* Q4 *//* 88.7% cutoff ( ~80 dB stop) 8 */ + {80, 16, 0.922f, 0.940f, KAISER10}, /* Q5 *//* 89.1% cutoff (~100 dB stop) 10 */ + {96, 16, 0.940f, 0.945f, KAISER10}, /* Q6 *//* 91.5% cutoff (~100 dB stop) 10 */ + {128, 16, 0.950f, 0.950f, KAISER10}, /* Q7 *//* 93.1% cutoff (~100 dB stop) 10 */ + {160, 16, 0.960f, 0.960f, KAISER10}, /* Q8 *//* 94.5% cutoff (~100 dB stop) 10 */ + {192, 32, 0.968f, 0.968f, KAISER12}, /* Q9 *//* 95.5% cutoff (~100 dB stop) 10 */ + {256, 32, 0.975f, 0.975f, KAISER12}, /* Q10 *//* 96.6% cutoff (~100 dB stop) 10 */ +}; + +/*8,24,40,56,80,104,128,160,200,256,320*/ +#ifdef DOUBLE_PRECISION +static double +compute_func (double x, struct FuncDef *func) +{ + double y, frac; +#else +static double +compute_func (float x, struct FuncDef *func) +{ + float y, frac; +#endif + double interp[4]; + int ind; + y = x * func->oversample; + ind = (int) floor (y); + frac = (y - ind); + /* CSE with handle the repeated powers */ + interp[3] = -0.1666666667 * frac + 0.1666666667 * (frac * frac * frac); + interp[2] = frac + 0.5 * (frac * frac) - 0.5 * (frac * frac * frac); + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */ + interp[0] = + -0.3333333333 * frac + 0.5 * (frac * frac) - + 0.1666666667 * (frac * frac * frac); + /* Just to make sure we don't have rounding problems */ + interp[1] = 1.f - interp[3] - interp[2] - interp[0]; + + /*sum = frac*accum[1] + (1-frac)*accum[2]; */ + return interp[0] * func->table[ind] + interp[1] * func->table[ind + 1] + + interp[2] * func->table[ind + 2] + interp[3] * func->table[ind + 3]; +} + +#if 0 +#include +int +main (int argc, char **argv) +{ + int i; + for (i = 0; i < 256; i++) { + printf ("%f\n", compute_func (i / 256., KAISER12)); + } + return 0; +} +#endif + +#ifdef FIXED_POINT +/* The slow way of computing a sinc for the table. Should improve that some day */ +static spx_word16_t +sinc (float cutoff, float x, int N, struct FuncDef *window_func) +{ + /*fprintf (stderr, "%f ", x); */ + float xx = x * cutoff; + if (fabs (x) < 1e-6f) + return WORD2INT (32768. * cutoff); + else if (fabs (x) > .5f * N) + return 0; + /*FIXME: Can it really be any slower than this? */ + return WORD2INT (32768. * cutoff * sin (M_PI * xx) / (M_PI * xx) * + compute_func (fabs (2. * x / N), window_func)); +} +#else +/* The slow way of computing a sinc for the table. Should improve that some day */ +#ifdef DOUBLE_PRECISION +static spx_word16_t +sinc (double cutoff, double x, int N, struct FuncDef *window_func) +{ + /*fprintf (stderr, "%f ", x); */ + double xx = x * cutoff; +#else +static spx_word16_t +sinc (float cutoff, float x, int N, struct FuncDef *window_func) +{ + /*fprintf (stderr, "%f ", x); */ + float xx = x * cutoff; +#endif + if (fabs (x) < 1e-6) + return cutoff; + else if (fabs (x) > .5 * N) + return 0; + /*FIXME: Can it really be any slower than this? */ + return cutoff * sin (M_PI * xx) / (M_PI * xx) * compute_func (fabs (2. * x / + N), window_func); +} +#endif + +#ifdef FIXED_POINT +static void +cubic_coef (spx_word16_t x, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + spx_word16_t x2, x3; + x2 = MULT16_16_P15 (x, x); + x3 = MULT16_16_P15 (x, x2); + interp[0] = + PSHR32 (MULT16_16 (QCONST16 (-0.16667f, 15), + x) + MULT16_16 (QCONST16 (0.16667f, 15), x3), 15); + interp[1] = + EXTRACT16 (EXTEND32 (x) + SHR32 (SUB32 (EXTEND32 (x2), EXTEND32 (x3)), + 1)); + interp[3] = + PSHR32 (MULT16_16 (QCONST16 (-0.33333f, 15), + x) + MULT16_16 (QCONST16 (.5f, 15), + x2) - MULT16_16 (QCONST16 (0.16667f, 15), x3), 15); + /* Just to make sure we don't have rounding problems */ + interp[2] = Q15_ONE - interp[0] - interp[1] - interp[3]; + if (interp[2] < 32767) + interp[2] += 1; +} +#else +static void +cubic_coef (spx_word16_t frac, spx_word16_t interp[4]) +{ + /* Compute interpolation coefficients. I'm not sure whether this corresponds to cubic interpolation + but I know it's MMSE-optimal on a sinc */ + interp[0] = -0.16667f * frac + 0.16667f * frac * frac * frac; + interp[1] = frac + 0.5f * frac * frac - 0.5f * frac * frac * frac; + /*interp[2] = 1.f - 0.5f*frac - frac*frac + 0.5f*frac*frac*frac; */ + interp[3] = + -0.33333f * frac + 0.5f * frac * frac - 0.16667f * frac * frac * frac; + /* Just to make sure we don't have rounding problems */ + interp[2] = 1. - interp[0] - interp[1] - interp[3]; +} +#endif + +#ifndef DOUBLE_PRECISION +static int +resampler_basic_direct_single (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, + spx_word16_t * out, spx_uint32_t * out_len) +{ + const int N = st->filt_len; + int out_sample = 0; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + const spx_word16_t *sinc_table = st->sinc_table; + const int out_stride = st->out_stride; + const int int_advance = st->int_advance; + const int frac_advance = st->frac_advance; + const spx_uint32_t den_rate = st->den_rate; + spx_word32_t sum; + int j; + + while (!(last_sample >= (spx_int32_t) * in_len + || out_sample >= (spx_int32_t) * out_len)) { + const spx_word16_t *sinc = &sinc_table[samp_frac_num * N]; + const spx_word16_t *iptr = &in[last_sample]; + +#ifndef OVERRIDE_INNER_PRODUCT_SINGLE + sum = 0; + for (j = 0; j < N; j++) + sum += MULT16_16 (sinc[j], iptr[j]); + +/* This code is slower on most DSPs which have only 2 accumulators. + Plus this this forces truncation to 32 bits and you lose the HW guard bits. + I think we can trust the compiler and let it vectorize and/or unroll itself. + spx_word32_t accum[4] = {0,0,0,0}; + for(j=0;j= den_rate) { + samp_frac_num -= den_rate; + last_sample++; + } + } + + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +static int +resampler_basic_direct_double (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, + spx_word16_t * out, spx_uint32_t * out_len) +{ + const int N = st->filt_len; + int out_sample = 0; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + const spx_word16_t *sinc_table = st->sinc_table; + const int out_stride = st->out_stride; + const int int_advance = st->int_advance; + const int frac_advance = st->frac_advance; + const spx_uint32_t den_rate = st->den_rate; + double sum; + int j; + + while (!(last_sample >= (spx_int32_t) * in_len + || out_sample >= (spx_int32_t) * out_len)) { + const spx_word16_t *sinc = &sinc_table[samp_frac_num * N]; + const spx_word16_t *iptr = &in[last_sample]; + +#ifndef OVERRIDE_INNER_PRODUCT_DOUBLE + double accum[4] = { 0, 0, 0, 0 }; + + for (j = 0; j < N; j += 4) { + accum[0] += sinc[j] * iptr[j]; + accum[1] += sinc[j + 1] * iptr[j + 1]; + accum[2] += sinc[j + 2] * iptr[j + 2]; + accum[3] += sinc[j + 3] * iptr[j + 3]; + } + sum = accum[0] + accum[1] + accum[2] + accum[3]; +#else + sum = inner_product_double (sinc, iptr, N); +#endif + + out[out_stride * out_sample++] = PSHR32 (sum, 15); + last_sample += int_advance; + samp_frac_num += frac_advance; + if (samp_frac_num >= den_rate) { + samp_frac_num -= den_rate; + last_sample++; + } + } + + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +#ifndef DOUBLE_PRECISION +static int +resampler_basic_interpolate_single (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, + spx_word16_t * out, spx_uint32_t * out_len) +{ + const int N = st->filt_len; + int out_sample = 0; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + const int out_stride = st->out_stride; + const int int_advance = st->int_advance; + const int frac_advance = st->frac_advance; + const spx_uint32_t den_rate = st->den_rate; + int j; + spx_word32_t sum; + + while (!(last_sample >= (spx_int32_t) * in_len + || out_sample >= (spx_int32_t) * out_len)) { + const spx_word16_t *iptr = &in[last_sample]; + + const int offset = samp_frac_num * st->oversample / st->den_rate; +#ifdef FIXED_POINT + const spx_word16_t frac = + PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), + st->den_rate); +#else + const spx_word16_t frac = + ((float) ((samp_frac_num * st->oversample) % st->den_rate)) / + st->den_rate; +#endif + spx_word16_t interp[4]; + + +#ifndef OVERRIDE_INTERPOLATE_PRODUCT_SINGLE + spx_word32_t accum[4] = { 0, 0, 0, 0 }; + + for (j = 0; j < N; j++) { + const spx_word16_t curr_in = iptr[j]; + accum[0] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); + accum[1] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); + accum[2] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset]); + accum[3] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); + } + + cubic_coef (frac, interp); + sum = + MULT16_32_Q15 (interp[0], SHR32 (accum[0], + 1)) + MULT16_32_Q15 (interp[1], SHR32 (accum[1], + 1)) + MULT16_32_Q15 (interp[2], SHR32 (accum[2], + 1)) + MULT16_32_Q15 (interp[3], SHR32 (accum[3], 1)); +#else + cubic_coef (frac, interp); + sum = + interpolate_product_single (iptr, + st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, + interp); +#endif + + out[out_stride * out_sample++] = SATURATE32 (PSHR32 (sum, 14), 32767); + last_sample += int_advance; + samp_frac_num += frac_advance; + if (samp_frac_num >= den_rate) { + samp_frac_num -= den_rate; + last_sample++; + } + } + + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +#ifdef FIXED_POINT +#else +/* This is the same as the previous function, except with a double-precision accumulator */ +static int +resampler_basic_interpolate_double (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_word16_t * in, spx_uint32_t * in_len, + spx_word16_t * out, spx_uint32_t * out_len) +{ + const int N = st->filt_len; + int out_sample = 0; + int last_sample = st->last_sample[channel_index]; + spx_uint32_t samp_frac_num = st->samp_frac_num[channel_index]; + const int out_stride = st->out_stride; + const int int_advance = st->int_advance; + const int frac_advance = st->frac_advance; + const spx_uint32_t den_rate = st->den_rate; + int j; + spx_word32_t sum; + + while (!(last_sample >= (spx_int32_t) * in_len + || out_sample >= (spx_int32_t) * out_len)) { + const spx_word16_t *iptr = &in[last_sample]; + + const int offset = samp_frac_num * st->oversample / st->den_rate; +#ifdef FIXED_POINT + const spx_word16_t frac = + PDIV32 (SHL32 ((samp_frac_num * st->oversample) % st->den_rate, 15), + st->den_rate); +#else +#ifdef DOUBLE_PRECISION + const spx_word16_t frac = + ((double) ((samp_frac_num * st->oversample) % st->den_rate)) / + st->den_rate; +#else + const spx_word16_t frac = + ((float) ((samp_frac_num * st->oversample) % st->den_rate)) / + st->den_rate; +#endif +#endif + spx_word16_t interp[4]; + + +#ifndef OVERRIDE_INTERPOLATE_PRODUCT_DOUBLE + double accum[4] = { 0, 0, 0, 0 }; + + for (j = 0; j < N; j++) { + const double curr_in = iptr[j]; + accum[0] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 2]); + accum[1] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset - 1]); + accum[2] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset]); + accum[3] += + MULT16_16 (curr_in, + st->sinc_table[4 + (j + 1) * st->oversample - offset + 1]); + } + + cubic_coef (frac, interp); + sum = + MULT16_32_Q15 (interp[0], accum[0]) + MULT16_32_Q15 (interp[1], + accum[1]) + MULT16_32_Q15 (interp[2], + accum[2]) + MULT16_32_Q15 (interp[3], accum[3]); +#else + cubic_coef (frac, interp); + sum = + interpolate_product_double (iptr, + st->sinc_table + st->oversample + 4 - offset - 2, N, st->oversample, + interp); +#endif + + out[out_stride * out_sample++] = PSHR32 (sum, 15); + last_sample += int_advance; + samp_frac_num += frac_advance; + if (samp_frac_num >= den_rate) { + samp_frac_num -= den_rate; + last_sample++; + } + } + + st->last_sample[channel_index] = last_sample; + st->samp_frac_num[channel_index] = samp_frac_num; + return out_sample; +} +#endif + +static void +update_filter (SpeexResamplerState * st) +{ + spx_uint32_t old_length; + + old_length = st->filt_len; + st->oversample = quality_map[st->quality].oversample; + st->filt_len = quality_map[st->quality].base_length; + + if (st->num_rate > st->den_rate) { + /* down-sampling */ + st->cutoff = + quality_map[st->quality].downsample_bandwidth * st->den_rate / + st->num_rate; + /* FIXME: divide the numerator and denominator by a certain amount if they're too large */ + st->filt_len = st->filt_len * st->num_rate / st->den_rate; + /* Round down to make sure we have a multiple of 4 */ + st->filt_len &= (~0x3); + if (2 * st->den_rate < st->num_rate) + st->oversample >>= 1; + if (4 * st->den_rate < st->num_rate) + st->oversample >>= 1; + if (8 * st->den_rate < st->num_rate) + st->oversample >>= 1; + if (16 * st->den_rate < st->num_rate) + st->oversample >>= 1; + if (st->oversample < 1) + st->oversample = 1; + } else { + /* up-sampling */ + st->cutoff = quality_map[st->quality].upsample_bandwidth; + } + + /* Choose the resampling type that requires the least amount of memory */ + if (st->den_rate <= st->oversample) { + spx_uint32_t i; + if (!st->sinc_table) + st->sinc_table = + (spx_word16_t *) speex_alloc (st->filt_len * st->den_rate * + sizeof (spx_word16_t)); + else if (st->sinc_table_length < st->filt_len * st->den_rate) { + st->sinc_table = + (spx_word16_t *) speex_realloc (st->sinc_table, + st->filt_len * st->den_rate * sizeof (spx_word16_t)); + st->sinc_table_length = st->filt_len * st->den_rate; + } + for (i = 0; i < st->den_rate; i++) { + spx_int32_t j; + for (j = 0; j < st->filt_len; j++) { + st->sinc_table[i * st->filt_len + j] = + sinc (st->cutoff, ((j - (spx_int32_t) st->filt_len / 2 + 1) - +#ifdef DOUBLE_PRECISION + ((double) i) / st->den_rate), st->filt_len, +#else + ((float) i) / st->den_rate), st->filt_len, +#endif + quality_map[st->quality].window_func); + } + } +#ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_direct_single; +#else +#ifdef DOUBLE_PRECISION + st->resampler_ptr = resampler_basic_direct_double; +#else + if (st->quality > 8) + st->resampler_ptr = resampler_basic_direct_double; + else + st->resampler_ptr = resampler_basic_direct_single; +#endif +#endif + /*fprintf (stderr, "resampler uses direct sinc table and normalised cutoff %f\n", cutoff); */ + } else { + spx_int32_t i; + if (!st->sinc_table) + st->sinc_table = + (spx_word16_t *) speex_alloc ((st->filt_len * st->oversample + + 8) * sizeof (spx_word16_t)); + else if (st->sinc_table_length < st->filt_len * st->oversample + 8) { + st->sinc_table = + (spx_word16_t *) speex_realloc (st->sinc_table, + (st->filt_len * st->oversample + 8) * sizeof (spx_word16_t)); + st->sinc_table_length = st->filt_len * st->oversample + 8; + } + for (i = -4; i < (spx_int32_t) (st->oversample * st->filt_len + 4); i++) + st->sinc_table[i + 4] = +#ifdef DOUBLE_PRECISION + sinc (st->cutoff, (i / (double) st->oversample - st->filt_len / 2), +#else + sinc (st->cutoff, (i / (float) st->oversample - st->filt_len / 2), +#endif + st->filt_len, quality_map[st->quality].window_func); +#ifdef FIXED_POINT + st->resampler_ptr = resampler_basic_interpolate_single; +#else +#ifdef DOUBLE_PRECISION + st->resampler_ptr = resampler_basic_interpolate_double; +#else + if (st->quality > 8) + st->resampler_ptr = resampler_basic_interpolate_double; + else + st->resampler_ptr = resampler_basic_interpolate_single; +#endif +#endif + /*fprintf (stderr, "resampler uses interpolated sinc table and normalised cutoff %f\n", cutoff); */ + } + st->int_advance = st->num_rate / st->den_rate; + st->frac_advance = st->num_rate % st->den_rate; + + + /* Here's the place where we update the filter memory to take into account + the change in filter length. It's probably the messiest part of the code + due to handling of lots of corner cases. */ + if (!st->mem) { + spx_uint32_t i; + st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + st->mem = + (spx_word16_t *) speex_alloc (st->nb_channels * st->mem_alloc_size * + sizeof (spx_word16_t)); + for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++) + st->mem[i] = 0; + /*speex_warning("init filter"); */ + } else if (!st->started) { + spx_uint32_t i; + st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + st->mem = + (spx_word16_t *) speex_realloc (st->mem, + st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t)); + for (i = 0; i < st->nb_channels * st->mem_alloc_size; i++) + st->mem[i] = 0; + /*speex_warning("reinit filter"); */ + } else if (st->filt_len > old_length) { + spx_int32_t i; + /* Increase the filter length */ + /*speex_warning("increase filter size"); */ + int old_alloc_size = st->mem_alloc_size; + if ((st->filt_len - 1 + st->buffer_size) > st->mem_alloc_size) { + st->mem_alloc_size = st->filt_len - 1 + st->buffer_size; + st->mem = + (spx_word16_t *) speex_realloc (st->mem, + st->nb_channels * st->mem_alloc_size * sizeof (spx_word16_t)); + } + for (i = st->nb_channels - 1; i >= 0; i--) { + spx_int32_t j; + spx_uint32_t olen = old_length; + /*if (st->magic_samples[i]) */ + { + /* Try and remove the magic samples as if nothing had happened */ + + /* FIXME: This is wrong but for now we need it to avoid going over the array bounds */ + olen = old_length + 2 * st->magic_samples[i]; + for (j = old_length - 2 + st->magic_samples[i]; j >= 0; j--) + st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]] = + st->mem[i * old_alloc_size + j]; + for (j = 0; j < st->magic_samples[i]; j++) + st->mem[i * st->mem_alloc_size + j] = 0; + st->magic_samples[i] = 0; + } + if (st->filt_len > olen) { + /* If the new filter length is still bigger than the "augmented" length */ + /* Copy data going backward */ + for (j = 0; j < olen - 1; j++) + st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = + st->mem[i * st->mem_alloc_size + (olen - 2 - j)]; + /* Then put zeros for lack of anything better */ + for (; j < st->filt_len - 1; j++) + st->mem[i * st->mem_alloc_size + (st->filt_len - 2 - j)] = 0; + /* Adjust last_sample */ + st->last_sample[i] += (st->filt_len - olen) / 2; + } else { + /* Put back some of the magic! */ + st->magic_samples[i] = (olen - st->filt_len) / 2; + for (j = 0; j < st->filt_len - 1 + st->magic_samples[i]; j++) + st->mem[i * st->mem_alloc_size + j] = + st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]]; + } + } + } else if (st->filt_len < old_length) { + spx_uint32_t i; + /* Reduce filter length, this a bit tricky. We need to store some of the memory as "magic" + samples so they can be used directly as input the next time(s) */ + for (i = 0; i < st->nb_channels; i++) { + spx_uint32_t j; + spx_uint32_t old_magic = st->magic_samples[i]; + st->magic_samples[i] = (old_length - st->filt_len) / 2; + /* We must copy some of the memory that's no longer used */ + /* Copy data going backward */ + for (j = 0; j < st->filt_len - 1 + st->magic_samples[i] + old_magic; j++) + st->mem[i * st->mem_alloc_size + j] = + st->mem[i * st->mem_alloc_size + j + st->magic_samples[i]]; + st->magic_samples[i] += old_magic; + } + } + +} + +EXPORT SpeexResamplerState * +speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate, + spx_uint32_t out_rate, int quality, int *err) +{ + return speex_resampler_init_frac (nb_channels, in_rate, out_rate, in_rate, + out_rate, quality, err); +} + +EXPORT SpeexResamplerState * +speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, + spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate, + int quality, int *err) +{ + spx_uint32_t i; + SpeexResamplerState *st; + if (quality > 10 || quality < 0) { + if (err) + *err = RESAMPLER_ERR_INVALID_ARG; + return NULL; + } + st = (SpeexResamplerState *) speex_alloc (sizeof (SpeexResamplerState)); + st->initialised = 0; + st->started = 0; + st->in_rate = 0; + st->out_rate = 0; + st->num_rate = 0; + st->den_rate = 0; + st->quality = -1; + st->sinc_table_length = 0; + st->mem_alloc_size = 0; + st->filt_len = 0; + st->mem = 0; + st->resampler_ptr = 0; + + st->cutoff = 1.f; + st->nb_channels = nb_channels; + st->in_stride = 1; + st->out_stride = 1; + +#ifdef FIXED_POINT + st->buffer_size = 160; +#else + st->buffer_size = 160; +#endif + + /* Per channel data */ + st->last_sample = (spx_int32_t *) speex_alloc (nb_channels * sizeof (int)); + st->magic_samples = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int)); + st->samp_frac_num = (spx_uint32_t *) speex_alloc (nb_channels * sizeof (int)); + for (i = 0; i < nb_channels; i++) { + st->last_sample[i] = 0; + st->magic_samples[i] = 0; + st->samp_frac_num[i] = 0; + } + + speex_resampler_set_quality (st, quality); + speex_resampler_set_rate_frac (st, ratio_num, ratio_den, in_rate, out_rate); + + + update_filter (st); + + st->initialised = 1; + if (err) + *err = RESAMPLER_ERR_SUCCESS; + + return st; +} + +EXPORT void +speex_resampler_destroy (SpeexResamplerState * st) +{ + speex_free (st->mem); + speex_free (st->sinc_table); + speex_free (st->last_sample); + speex_free (st->magic_samples); + speex_free (st->samp_frac_num); + speex_free (st); +} + +static int +speex_resampler_process_native (SpeexResamplerState * st, + spx_uint32_t channel_index, spx_uint32_t * in_len, spx_word16_t * out, + spx_uint32_t * out_len) +{ + int j = 0; + const int N = st->filt_len; + int out_sample = 0; + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; + spx_uint32_t ilen; + + st->started = 1; + + /* Call the right resampler through the function ptr */ + out_sample = st->resampler_ptr (st, channel_index, mem, in_len, out, out_len); + + if (st->last_sample[channel_index] < (spx_int32_t) * in_len) + *in_len = st->last_sample[channel_index]; + *out_len = out_sample; + st->last_sample[channel_index] -= *in_len; + + ilen = *in_len; + + for (j = 0; j < N - 1; ++j) + mem[j] = mem[j + ilen]; + + return RESAMPLER_ERR_SUCCESS; +} + +static int +speex_resampler_magic (SpeexResamplerState * st, spx_uint32_t channel_index, + spx_word16_t ** out, spx_uint32_t out_len) +{ + spx_uint32_t tmp_in_len = st->magic_samples[channel_index]; + spx_word16_t *mem = st->mem + channel_index * st->mem_alloc_size; + const int N = st->filt_len; + + speex_resampler_process_native (st, channel_index, &tmp_in_len, *out, + &out_len); + + st->magic_samples[channel_index] -= tmp_in_len; + + /* If we couldn't process all "magic" input samples, save the rest for next time */ + if (st->magic_samples[channel_index]) { + spx_uint32_t i; + for (i = 0; i < st->magic_samples[channel_index]; i++) + mem[N - 1 + i] = mem[N - 1 + i + tmp_in_len]; + } + *out += out_len * st->out_stride; + return out_len; +} + +#ifdef FIXED_POINT +EXPORT int +speex_resampler_process_int (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len, + spx_int16_t * out, spx_uint32_t * out_len) +#else +#ifdef DOUBLE_PRECISION +EXPORT int +speex_resampler_process_float (SpeexResamplerState * st, + spx_uint32_t channel_index, const double *in, spx_uint32_t * in_len, + double *out, spx_uint32_t * out_len) +#else +EXPORT int +speex_resampler_process_float (SpeexResamplerState * st, + spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len, + float *out, spx_uint32_t * out_len) +#endif +#endif +{ + int j; + spx_uint32_t ilen = *in_len; + spx_uint32_t olen = *out_len; + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; + const int filt_offs = st->filt_len - 1; + const spx_uint32_t xlen = st->mem_alloc_size - filt_offs; + const int istride = st->in_stride; + + if (st->magic_samples[channel_index]) + olen -= speex_resampler_magic (st, channel_index, &out, olen); + if (!st->magic_samples[channel_index]) { + while (ilen && olen) { + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; + spx_uint32_t ochunk = olen; + + if (in) { + for (j = 0; j < ichunk; ++j) + x[j + filt_offs] = in[j * istride]; + } else { + for (j = 0; j < ichunk; ++j) + x[j + filt_offs] = 0; + } + speex_resampler_process_native (st, channel_index, &ichunk, out, &ochunk); + ilen -= ichunk; + olen -= ochunk; + out += ochunk * st->out_stride; + if (in) + in += ichunk * istride; + } + } + *in_len -= ilen; + *out_len -= olen; + return RESAMPLER_ERR_SUCCESS; +} + +#ifdef FIXED_POINT +EXPORT int +speex_resampler_process_float (SpeexResamplerState * st, + spx_uint32_t channel_index, const float *in, spx_uint32_t * in_len, + float *out, spx_uint32_t * out_len) +#else +EXPORT int +speex_resampler_process_int (SpeexResamplerState * st, + spx_uint32_t channel_index, const spx_int16_t * in, spx_uint32_t * in_len, + spx_int16_t * out, spx_uint32_t * out_len) +#endif +{ + int j; + const int istride_save = st->in_stride; + const int ostride_save = st->out_stride; + spx_uint32_t ilen = *in_len; + spx_uint32_t olen = *out_len; + spx_word16_t *x = st->mem + channel_index * st->mem_alloc_size; + const spx_uint32_t xlen = st->mem_alloc_size - (st->filt_len - 1); +#ifdef VAR_ARRAYS + const unsigned int ylen = + (olen < FIXED_STACK_ALLOC) ? olen : FIXED_STACK_ALLOC; + VARDECL (spx_word16_t * ystack); + ALLOC (ystack, ylen, spx_word16_t); +#else + const unsigned int ylen = FIXED_STACK_ALLOC; + spx_word16_t ystack[FIXED_STACK_ALLOC]; +#endif + + st->out_stride = 1; + + while (ilen && olen) { + spx_word16_t *y = ystack; + spx_uint32_t ichunk = (ilen > xlen) ? xlen : ilen; + spx_uint32_t ochunk = (olen > ylen) ? ylen : olen; + spx_uint32_t omagic = 0; + + if (st->magic_samples[channel_index]) { + omagic = speex_resampler_magic (st, channel_index, &y, ochunk); + ochunk -= omagic; + olen -= omagic; + } + if (!st->magic_samples[channel_index]) { + if (in) { + for (j = 0; j < ichunk; ++j) +#ifdef FIXED_POINT + x[j + st->filt_len - 1] = WORD2INT (in[j * istride_save]); +#else + x[j + st->filt_len - 1] = in[j * istride_save]; +#endif + } else { + for (j = 0; j < ichunk; ++j) + x[j + st->filt_len - 1] = 0; + } + + speex_resampler_process_native (st, channel_index, &ichunk, y, &ochunk); + } else { + ichunk = 0; + ochunk = 0; + } + + for (j = 0; j < ochunk + omagic; ++j) +#ifdef FIXED_POINT + out[j * ostride_save] = ystack[j]; +#else + out[j * ostride_save] = WORD2INT (ystack[j]); +#endif + + ilen -= ichunk; + olen -= ochunk; + out += (ochunk + omagic) * ostride_save; + if (in) + in += ichunk * istride_save; + } + st->out_stride = ostride_save; + *in_len -= ilen; + *out_len -= olen; + + return RESAMPLER_ERR_SUCCESS; +} + +#ifdef DOUBLE_PRECISION +EXPORT int +speex_resampler_process_interleaved_float (SpeexResamplerState * st, + const double *in, spx_uint32_t * in_len, double *out, + spx_uint32_t * out_len) +#else +EXPORT int +speex_resampler_process_interleaved_float (SpeexResamplerState * st, + const float *in, spx_uint32_t * in_len, float *out, spx_uint32_t * out_len) +#endif +{ + spx_uint32_t i; + int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + st->in_stride = st->out_stride = st->nb_channels; + for (i = 0; i < st->nb_channels; i++) { + *out_len = bak_len; + if (in != NULL) + speex_resampler_process_float (st, i, in + i, in_len, out + i, out_len); + else + speex_resampler_process_float (st, i, NULL, in_len, out + i, out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT int +speex_resampler_process_interleaved_int (SpeexResamplerState * st, + const spx_int16_t * in, spx_uint32_t * in_len, spx_int16_t * out, + spx_uint32_t * out_len) +{ + spx_uint32_t i; + int istride_save, ostride_save; + spx_uint32_t bak_len = *out_len; + istride_save = st->in_stride; + ostride_save = st->out_stride; + st->in_stride = st->out_stride = st->nb_channels; + for (i = 0; i < st->nb_channels; i++) { + *out_len = bak_len; + if (in != NULL) + speex_resampler_process_int (st, i, in + i, in_len, out + i, out_len); + else + speex_resampler_process_int (st, i, NULL, in_len, out + i, out_len); + } + st->in_stride = istride_save; + st->out_stride = ostride_save; + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT int +speex_resampler_set_rate (SpeexResamplerState * st, spx_uint32_t in_rate, + spx_uint32_t out_rate) +{ + return speex_resampler_set_rate_frac (st, in_rate, out_rate, in_rate, + out_rate); +} + +EXPORT void +speex_resampler_get_rate (SpeexResamplerState * st, spx_uint32_t * in_rate, + spx_uint32_t * out_rate) +{ + *in_rate = st->in_rate; + *out_rate = st->out_rate; +} + +EXPORT int +speex_resampler_set_rate_frac (SpeexResamplerState * st, spx_uint32_t ratio_num, + spx_uint32_t ratio_den, spx_uint32_t in_rate, spx_uint32_t out_rate) +{ + spx_uint32_t fact; + spx_uint32_t old_den; + spx_uint32_t i; + if (st->in_rate == in_rate && st->out_rate == out_rate + && st->num_rate == ratio_num && st->den_rate == ratio_den) + return RESAMPLER_ERR_SUCCESS; + + old_den = st->den_rate; + st->in_rate = in_rate; + st->out_rate = out_rate; + st->num_rate = ratio_num; + st->den_rate = ratio_den; + /* FIXME: This is terribly inefficient, but who cares (at least for now)? */ + for (fact = 2; fact <= IMIN (st->num_rate, st->den_rate); fact++) { + while ((st->num_rate % fact == 0) && (st->den_rate % fact == 0)) { + st->num_rate /= fact; + st->den_rate /= fact; + } + } + + if (old_den > 0) { + for (i = 0; i < st->nb_channels; i++) { + st->samp_frac_num[i] = st->samp_frac_num[i] * st->den_rate / old_den; + /* Safety net */ + if (st->samp_frac_num[i] >= st->den_rate) + st->samp_frac_num[i] = st->den_rate - 1; + } + } + + if (st->initialised) + update_filter (st); + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT void +speex_resampler_get_ratio (SpeexResamplerState * st, spx_uint32_t * ratio_num, + spx_uint32_t * ratio_den) +{ + *ratio_num = st->num_rate; + *ratio_den = st->den_rate; +} + +EXPORT int +speex_resampler_set_quality (SpeexResamplerState * st, int quality) +{ + if (quality > 10 || quality < 0) + return RESAMPLER_ERR_INVALID_ARG; + if (st->quality == quality) + return RESAMPLER_ERR_SUCCESS; + st->quality = quality; + if (st->initialised) + update_filter (st); + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT void +speex_resampler_get_quality (SpeexResamplerState * st, int *quality) +{ + *quality = st->quality; +} + +EXPORT void +speex_resampler_set_input_stride (SpeexResamplerState * st, spx_uint32_t stride) +{ + st->in_stride = stride; +} + +EXPORT void +speex_resampler_get_input_stride (SpeexResamplerState * st, + spx_uint32_t * stride) +{ + *stride = st->in_stride; +} + +EXPORT void +speex_resampler_set_output_stride (SpeexResamplerState * st, + spx_uint32_t stride) +{ + st->out_stride = stride; +} + +EXPORT void +speex_resampler_get_output_stride (SpeexResamplerState * st, + spx_uint32_t * stride) +{ + *stride = st->out_stride; +} + +EXPORT int +speex_resampler_get_input_latency (SpeexResamplerState * st) +{ + return st->filt_len / 2; +} + +EXPORT int +speex_resampler_get_output_latency (SpeexResamplerState * st) +{ + return ((st->filt_len / 2) * st->den_rate + + (st->num_rate >> 1)) / st->num_rate; +} + +EXPORT int +speex_resampler_get_filt_len (SpeexResamplerState * st) +{ + return st->filt_len; +} + +EXPORT int +speex_resampler_skip_zeros (SpeexResamplerState * st) +{ + spx_uint32_t i; + for (i = 0; i < st->nb_channels; i++) + st->last_sample[i] = st->filt_len / 2; + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT int +speex_resampler_reset_mem (SpeexResamplerState * st) +{ + spx_uint32_t i; + for (i = 0; i < st->nb_channels * (st->filt_len - 1); i++) + st->mem[i] = 0; + return RESAMPLER_ERR_SUCCESS; +} + +EXPORT const char * +speex_resampler_strerror (int err) +{ + switch (err) { + case RESAMPLER_ERR_SUCCESS: + return "Success."; + case RESAMPLER_ERR_ALLOC_FAILED: + return "Memory allocation failed."; + case RESAMPLER_ERR_BAD_STATE: + return "Bad resampler state."; + case RESAMPLER_ERR_INVALID_ARG: + return "Invalid argument."; + case RESAMPLER_ERR_PTR_OVERLAP: + return "Input and output buffers overlap."; + default: + return "Unknown error. Bad error code or strange version mismatch."; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/resample_sse.h b/gst-plugins-base-subtitles0.10/gst/audioresample/resample_sse.h new file mode 100644 index 0000000..64be8a1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/resample_sse.h @@ -0,0 +1,128 @@ +/* Copyright (C) 2007-2008 Jean-Marc Valin + * Copyright (C) 2008 Thorvald Natvig + */ +/** + @file resample_sse.h + @brief Resampler functions (SSE version) +*/ +/* + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + - Neither the name of the Xiph.org Foundation nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include + +#define OVERRIDE_INNER_PRODUCT_SINGLE +static inline float inner_product_single(const float *a, const float *b, unsigned int len) +{ + int i; + float ret; + __m128 sum = _mm_setzero_ps(); + for (i=0;i +#define OVERRIDE_INNER_PRODUCT_DOUBLE + +static inline double inner_product_double(const float *a, const float *b, unsigned int len) +{ + int i; + double ret; + __m128d sum = _mm_setzero_pd(); + __m128 t; + for (i=0;i +#endif + +#endif /* OUTSIDE_SPEEX */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPEEX_RESAMPLER_QUALITY_MAX 10 +#define SPEEX_RESAMPLER_QUALITY_MIN 0 +#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 +#define SPEEX_RESAMPLER_QUALITY_VOIP 3 +#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum { + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + + RESAMPLER_ERR_MAX_ERROR +}; + +struct SpeexResamplerState_; +typedef struct SpeexResamplerState_ SpeexResamplerState; + +/** Create a new resampler with integer input and output rates. + * @param nb_channels Number of channels to be processed + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Create a new resampler with fractional input/output rates. The sampling + * rate ratio is an arbitrary rational number with both the numerator and + * denominator being 32-bit integers. + * @param nb_channels Number of channels to be processed + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + * @param quality Resampling quality between 0 and 10, where 0 has poor quality + * and 10 has very high quality. + * @return Newly created resampler state + * @retval NULL Error: not enough memory + */ +SpeexResamplerState *speex_resampler_init_frac(spx_uint32_t nb_channels, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate, + int quality, + int *err); + +/** Destroy a resampler state. + * @param st Resampler state + */ +void speex_resampler_destroy(SpeexResamplerState *st); + +/** Resample a float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the + * number of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +#ifdef DOUBLE_PRECISION +int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const double *in, + spx_uint32_t *in_len, + double *out, + spx_uint32_t *out_len); +#else +int speex_resampler_process_float(SpeexResamplerState *st, + spx_uint32_t channel_index, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); +#endif + +/** Resample an int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param channel_index Index of the channel to process for the multi-channel + * base (0 otherwise) + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written + */ +int speex_resampler_process_int(SpeexResamplerState *st, + spx_uint32_t channel_index, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Resample an interleaved float array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +#ifdef DOUBLE_PRECISION +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const double *in, + spx_uint32_t *in_len, + double *out, + spx_uint32_t *out_len); +#else +int speex_resampler_process_interleaved_float(SpeexResamplerState *st, + const float *in, + spx_uint32_t *in_len, + float *out, + spx_uint32_t *out_len); +#endif + +/** Resample an interleaved int array. The input and output buffers must *not* overlap. + * @param st Resampler state + * @param in Input buffer + * @param in_len Number of input samples in the input buffer. Returns the number + * of samples processed. This is all per-channel. + * @param out Output buffer + * @param out_len Size of the output buffer. Returns the number of samples written. + * This is all per-channel. + */ +int speex_resampler_process_interleaved_int(SpeexResamplerState *st, + const spx_int16_t *in, + spx_uint32_t *in_len, + spx_int16_t *out, + spx_uint32_t *out_len); + +/** Set (change) the input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz). + * @param out_rate Output sampling rate (integer number of Hz). + */ +int speex_resampler_set_rate(SpeexResamplerState *st, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current input/output sampling rates (integer value). + * @param st Resampler state + * @param in_rate Input sampling rate (integer number of Hz) copied. + * @param out_rate Output sampling rate (integer number of Hz) copied. + */ +void speex_resampler_get_rate(SpeexResamplerState *st, + spx_uint32_t *in_rate, + spx_uint32_t *out_rate); + +/** Set (change) the input/output sampling rates and resampling ratio + * (fractional values in Hz supported). + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio + * @param ratio_den Denominator of the sampling rate ratio + * @param in_rate Input sampling rate rounded to the nearest integer (in Hz). + * @param out_rate Output sampling rate rounded to the nearest integer (in Hz). + */ +int speex_resampler_set_rate_frac(SpeexResamplerState *st, + spx_uint32_t ratio_num, + spx_uint32_t ratio_den, + spx_uint32_t in_rate, + spx_uint32_t out_rate); + +/** Get the current resampling ratio. This will be reduced to the least + * common denominator. + * @param st Resampler state + * @param ratio_num Numerator of the sampling rate ratio copied + * @param ratio_den Denominator of the sampling rate ratio copied + */ +void speex_resampler_get_ratio(SpeexResamplerState *st, + spx_uint32_t *ratio_num, + spx_uint32_t *ratio_den); + +/** Set (change) the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +int speex_resampler_set_quality(SpeexResamplerState *st, + int quality); + +/** Get the conversion quality. + * @param st Resampler state + * @param quality Resampling quality between 0 and 10, where 0 has poor + * quality and 10 has very high quality. + */ +void speex_resampler_get_quality(SpeexResamplerState *st, + int *quality); + +/** Set (change) the input stride. + * @param st Resampler state + * @param stride Input stride + */ +void speex_resampler_set_input_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the input stride. + * @param st Resampler state + * @param stride Input stride copied + */ +void speex_resampler_get_input_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Set (change) the output stride. + * @param st Resampler state + * @param stride Output stride + */ +void speex_resampler_set_output_stride(SpeexResamplerState *st, + spx_uint32_t stride); + +/** Get the output stride. + * @param st Resampler state copied + * @param stride Output stride + */ +void speex_resampler_get_output_stride(SpeexResamplerState *st, + spx_uint32_t *stride); + +/** Get the latency introduced by the resampler measured in input samples. + * @param st Resampler state + */ +int speex_resampler_get_input_latency(SpeexResamplerState *st); + +/** Get the latency introduced by the resampler measured in output samples. + * @param st Resampler state + */ +int speex_resampler_get_output_latency(SpeexResamplerState *st); + +/** Get the length of the filter in input samples. + * @param st Resampler state + */ +int speex_resampler_get_filt_len(SpeexResamplerState *st); + +/** Make sure that the first samples to go out of the resamplers don't have + * leading zeros. This is only useful before starting to use a newly created + * resampler. It is recommended to use that when resampling an audio file, as + * it will generate a file with the same length. For real-time processing, + * it is probably easier not to use this call (so that the output duration + * is the same for the first frame). + * @param st Resampler state + */ +int speex_resampler_skip_zeros(SpeexResamplerState *st); + +/** Reset a resampler so a new (unrelated) stream can be processed. + * @param st Resampler state + */ +int speex_resampler_reset_mem(SpeexResamplerState *st); + +/** Returns the English meaning for an error code + * @param err Error code + * @return English string + */ +const char *speex_resampler_strerror(int err); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_double.c b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_double.c new file mode 100644 index 0000000..e5a2571 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_double.c @@ -0,0 +1,25 @@ +/* GStreamer + * Copyright (C) 2007-2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define FLOATING_POINT +#define DOUBLE_PRECISION +#define OUTSIDE_SPEEX +#define RANDOM_PREFIX resample_double + +#include "resample.c" diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_float.c b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_float.c new file mode 100644 index 0000000..f13f60c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_float.c @@ -0,0 +1,24 @@ +/* GStreamer + * Copyright (C) 2007-2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define FLOATING_POINT +#define OUTSIDE_SPEEX +#define RANDOM_PREFIX resample_float + +#include "resample.c" diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_int.c b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_int.c new file mode 100644 index 0000000..6b85860 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_int.c @@ -0,0 +1,24 @@ +/* GStreamer + * Copyright (C) 2007-2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#define FIXED_POINT 1 +#define OUTSIDE_SPEEX 1 +#define RANDOM_PREFIX resample_int + +#include "resample.c" diff --git a/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_wrapper.h b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_wrapper.h new file mode 100644 index 0000000..08a82bc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audioresample/speex_resampler_wrapper.h @@ -0,0 +1,168 @@ +/* GStreamer + * Copyright (C) 2007-2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __SPEEX_RESAMPLER_WRAPPER_H__ +#define __SPEEX_RESAMPLER_WRAPPER_H__ + +#define SPEEX_RESAMPLER_QUALITY_MAX 10 +#define SPEEX_RESAMPLER_QUALITY_MIN 0 +#define SPEEX_RESAMPLER_QUALITY_DEFAULT 4 +#define SPEEX_RESAMPLER_QUALITY_VOIP 3 +#define SPEEX_RESAMPLER_QUALITY_DESKTOP 5 + +enum +{ + RESAMPLER_ERR_SUCCESS = 0, + RESAMPLER_ERR_ALLOC_FAILED = 1, + RESAMPLER_ERR_BAD_STATE = 2, + RESAMPLER_ERR_INVALID_ARG = 3, + RESAMPLER_ERR_PTR_OVERLAP = 4, + + RESAMPLER_ERR_MAX_ERROR +}; + +typedef struct SpeexResamplerState_ SpeexResamplerState; + +typedef struct { + SpeexResamplerState *(*init) (guint32 nb_channels, + guint32 in_rate, guint32 out_rate, gint quality, gint * err); + void (*destroy) (SpeexResamplerState * st); + int (*process) (SpeexResamplerState * + st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); + int (*set_rate) (SpeexResamplerState * st, + guint32 in_rate, guint32 out_rate); + void (*get_rate) (SpeexResamplerState * st, + guint32 * in_rate, guint32 * out_rate); + void (*get_ratio) (SpeexResamplerState * st, + guint32 * ratio_num, guint32 * ratio_den); + int (*get_input_latency) (SpeexResamplerState * st); + int (*get_filt_len) (SpeexResamplerState * st); + int (*set_quality) (SpeexResamplerState * st, gint quality); + int (*reset_mem) (SpeexResamplerState * st); + int (*skip_zeros) (SpeexResamplerState * st); + const char * (*strerror) (gint err); + unsigned int width; +} SpeexResampleFuncs; + +SpeexResamplerState *resample_float_resampler_init (guint32 nb_channels, + guint32 in_rate, guint32 out_rate, gint quality, gint * err); +void resample_float_resampler_destroy (SpeexResamplerState * st); +int resample_float_resampler_process_interleaved_float (SpeexResamplerState * + st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); +int resample_float_resampler_set_rate (SpeexResamplerState * st, + guint32 in_rate, guint32 out_rate); +void resample_float_resampler_get_rate (SpeexResamplerState * st, + guint32 * in_rate, guint32 * out_rate); +void resample_float_resampler_get_ratio (SpeexResamplerState * st, + guint32 * ratio_num, guint32 * ratio_den); +int resample_float_resampler_get_input_latency (SpeexResamplerState * st); +int resample_float_resampler_get_filt_len (SpeexResamplerState * st); +int resample_float_resampler_set_quality (SpeexResamplerState * st, gint quality); +int resample_float_resampler_reset_mem (SpeexResamplerState * st); +int resample_float_resampler_skip_zeros (SpeexResamplerState * st); +const char * resample_float_resampler_strerror (gint err); + +static const SpeexResampleFuncs float_funcs = +{ + resample_float_resampler_init, + resample_float_resampler_destroy, + resample_float_resampler_process_interleaved_float, + resample_float_resampler_set_rate, + resample_float_resampler_get_rate, + resample_float_resampler_get_ratio, + resample_float_resampler_get_input_latency, + resample_float_resampler_get_filt_len, + resample_float_resampler_set_quality, + resample_float_resampler_reset_mem, + resample_float_resampler_skip_zeros, + resample_float_resampler_strerror, + 32 +}; + +SpeexResamplerState *resample_double_resampler_init (guint32 nb_channels, + guint32 in_rate, guint32 out_rate, gint quality, gint * err); +void resample_double_resampler_destroy (SpeexResamplerState * st); +int resample_double_resampler_process_interleaved_float (SpeexResamplerState * + st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); +int resample_double_resampler_set_rate (SpeexResamplerState * st, + guint32 in_rate, guint32 out_rate); +void resample_double_resampler_get_rate (SpeexResamplerState * st, + guint32 * in_rate, guint32 * out_rate); +void resample_double_resampler_get_ratio (SpeexResamplerState * st, + guint32 * ratio_num, guint32 * ratio_den); +int resample_double_resampler_get_input_latency (SpeexResamplerState * st); +int resample_double_resampler_get_filt_len (SpeexResamplerState * st); +int resample_double_resampler_set_quality (SpeexResamplerState * st, gint quality); +int resample_double_resampler_reset_mem (SpeexResamplerState * st); +int resample_double_resampler_skip_zeros (SpeexResamplerState * st); +const char * resample_double_resampler_strerror (gint err); + +static const SpeexResampleFuncs double_funcs = +{ + resample_double_resampler_init, + resample_double_resampler_destroy, + resample_double_resampler_process_interleaved_float, + resample_double_resampler_set_rate, + resample_double_resampler_get_rate, + resample_double_resampler_get_ratio, + resample_double_resampler_get_input_latency, + resample_double_resampler_get_filt_len, + resample_double_resampler_set_quality, + resample_double_resampler_reset_mem, + resample_double_resampler_skip_zeros, + resample_double_resampler_strerror, + 64 +}; + +SpeexResamplerState *resample_int_resampler_init (guint32 nb_channels, + guint32 in_rate, guint32 out_rate, gint quality, gint * err); +void resample_int_resampler_destroy (SpeexResamplerState * st); +int resample_int_resampler_process_interleaved_int (SpeexResamplerState * + st, const guint8 * in, guint32 * in_len, guint8 * out, guint32 * out_len); +int resample_int_resampler_set_rate (SpeexResamplerState * st, + guint32 in_rate, guint32 out_rate); +void resample_int_resampler_get_rate (SpeexResamplerState * st, + guint32 * in_rate, guint32 * out_rate); +void resample_int_resampler_get_ratio (SpeexResamplerState * st, + guint32 * ratio_num, guint32 * ratio_den); +int resample_int_resampler_get_input_latency (SpeexResamplerState * st); +int resample_int_resampler_get_filt_len (SpeexResamplerState * st); +int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality); +int resample_int_resampler_reset_mem (SpeexResamplerState * st); +int resample_int_resampler_skip_zeros (SpeexResamplerState * st); +const char * resample_int_resampler_strerror (gint err); + +static const SpeexResampleFuncs int_funcs = +{ + resample_int_resampler_init, + resample_int_resampler_destroy, + resample_int_resampler_process_interleaved_int, + resample_int_resampler_set_rate, + resample_int_resampler_get_rate, + resample_int_resampler_get_ratio, + resample_int_resampler_get_input_latency, + resample_int_resampler_get_filt_len, + resample_int_resampler_set_quality, + resample_int_resampler_reset_mem, + resample_int_resampler_skip_zeros, + resample_int_resampler_strerror, + 16 +}; + +#endif /* __SPEEX_RESAMPLER_WRAPPER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/audiotestsrc/Makefile.am b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/Makefile.am new file mode 100644 index 0000000..67a2c0b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/Makefile.am @@ -0,0 +1,23 @@ +plugin_LTLIBRARIES = libgstaudiotestsrc.la + +libgstaudiotestsrc_la_SOURCES = gstaudiotestsrc.c +libgstaudiotestsrc_la_CFLAGS = $(GST_CFLAGS) $(GST_CONTROLLER_CFLAGS) +libgstaudiotestsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstaudiotestsrc_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(GST_CONTROLLER_LIBS) $(LIBM) +libgstaudiotestsrc_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstaudiotestsrc.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstaudiotestsrc -:SHARED libgstaudiotestsrc \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstaudiotestsrc_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstaudiotestsrc_la_CFLAGS) \ + -:LDFLAGS $(libgstaudiotestsrc_la_LDFLAGS) \ + $(libgstaudiotestsrc_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.c b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.c new file mode 100644 index 0000000..ecbb2fb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.c @@ -0,0 +1,1238 @@ +/* GStreamer + * Copyright (C) 2005 Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-audiotestsrc + * + * AudioTestSrc can be used to generate basic audio signals. It support several + * different waveforms and allows to set the base frequency and volume. + * + * + * Example launch line + * |[ + * gst-launch audiotestsrc ! audioconvert ! alsasink + * ]| This pipeline produces a sine with default frequency, 440 Hz, and the + * default volume, 0.8 (relative to a maximum 1.0). + * |[ + * gst-launch audiotestsrc wave=2 freq=200 ! audioconvert ! tee name=t ! queue ! alsasink t. ! queue ! libvisual_lv_scope ! ffmpegcolorspace ! xvimagesink + * ]| In this example a saw wave is generated. The wave is shown using a + * scope visualizer from libvisual, allowing you to visually verify that + * the saw wave is correct. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include "gstaudiotestsrc.h" + + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +#ifndef M_PI_2 +#define M_PI_2 1.57079632679489661923 +#endif + +#define M_PI_M2 ( M_PI + M_PI ) + +GST_DEBUG_CATEGORY_STATIC (audio_test_src_debug); +#define GST_CAT_DEFAULT audio_test_src_debug + +#define DEFAULT_SAMPLES_PER_BUFFER 1024 +#define DEFAULT_WAVE GST_AUDIO_TEST_SRC_WAVE_SINE +#define DEFAULT_FREQ 440.0 +#define DEFAULT_VOLUME 0.8 +#define DEFAULT_IS_LIVE FALSE +#define DEFAULT_TIMESTAMP_OFFSET G_GINT64_CONSTANT (0) +#define DEFAULT_CAN_ACTIVATE_PUSH TRUE +#define DEFAULT_CAN_ACTIVATE_PULL FALSE + +enum +{ + PROP_0, + PROP_SAMPLES_PER_BUFFER, + PROP_WAVE, + PROP_FREQ, + PROP_VOLUME, + PROP_IS_LIVE, + PROP_TIMESTAMP_OFFSET, + PROP_CAN_ACTIVATE_PUSH, + PROP_CAN_ACTIVATE_PULL, + PROP_LAST +}; + + +static GstStaticPadTemplate gst_audio_test_src_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "endianness = (int) BYTE_ORDER, " + "signed = (boolean) true, " + "width = (int) 16, " + "depth = (int) 16, " + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, 2 ]; " + "audio/x-raw-int, " + "endianness = (int) BYTE_ORDER, " + "signed = (boolean) true, " + "width = (int) 32, " + "depth = (int) 32," + "rate = (int) [ 1, MAX ], " + "channels = (int) [ 1, 2 ]; " + "audio/x-raw-float, " + "endianness = (int) BYTE_ORDER, " + "width = (int) { 32, 64 }, " + "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, 2 ]") + ); + + +GST_BOILERPLATE (GstAudioTestSrc, gst_audio_test_src, GstBaseSrc, + GST_TYPE_BASE_SRC); + +#define GST_TYPE_AUDIO_TEST_SRC_WAVE (gst_audiostestsrc_wave_get_type()) +static GType +gst_audiostestsrc_wave_get_type (void) +{ + static GType audiostestsrc_wave_type = 0; + static const GEnumValue audiostestsrc_waves[] = { + {GST_AUDIO_TEST_SRC_WAVE_SINE, "Sine", "sine"}, + {GST_AUDIO_TEST_SRC_WAVE_SQUARE, "Square", "square"}, + {GST_AUDIO_TEST_SRC_WAVE_SAW, "Saw", "saw"}, + {GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, "Triangle", "triangle"}, + {GST_AUDIO_TEST_SRC_WAVE_SILENCE, "Silence", "silence"}, + {GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, "White uniform noise", "white-noise"}, + {GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, "Pink noise", "pink-noise"}, + {GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, "Sine table", "sine-table"}, + {GST_AUDIO_TEST_SRC_WAVE_TICKS, "Periodic Ticks", "ticks"}, + {GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE, "White Gaussian noise", + "gaussian-noise"}, + {0, NULL, NULL}, + }; + + if (G_UNLIKELY (audiostestsrc_wave_type == 0)) { + audiostestsrc_wave_type = g_enum_register_static ("GstAudioTestSrcWave", + audiostestsrc_waves); + } + return audiostestsrc_wave_type; +} + +static void gst_audio_test_src_finalize (GObject * object); + +static void gst_audio_test_src_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_audio_test_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static gboolean gst_audio_test_src_setcaps (GstBaseSrc * basesrc, + GstCaps * caps); +static void gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps); + +static gboolean gst_audio_test_src_is_seekable (GstBaseSrc * basesrc); +static gboolean gst_audio_test_src_check_get_range (GstBaseSrc * basesrc); +static gboolean gst_audio_test_src_do_seek (GstBaseSrc * basesrc, + GstSegment * segment); +static gboolean gst_audio_test_src_query (GstBaseSrc * basesrc, + GstQuery * query); + +static void gst_audio_test_src_change_wave (GstAudioTestSrc * src); + +static void gst_audio_test_src_get_times (GstBaseSrc * basesrc, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static gboolean gst_audio_test_src_start (GstBaseSrc * basesrc); +static gboolean gst_audio_test_src_stop (GstBaseSrc * basesrc); +static GstFlowReturn gst_audio_test_src_create (GstBaseSrc * basesrc, + guint64 offset, guint length, GstBuffer ** buffer); + + +static void +gst_audio_test_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_audio_test_src_src_template)); + gst_element_class_set_details_simple (element_class, + "Audio test source", "Source/Audio", + "Creates audio test signals of given frequency and volume", + "Stefan Kost "); +} + +static void +gst_audio_test_src_class_init (GstAudioTestSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + + gobject_class = (GObjectClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + + gobject_class->set_property = gst_audio_test_src_set_property; + gobject_class->get_property = gst_audio_test_src_get_property; + gobject_class->finalize = gst_audio_test_src_finalize; + + g_object_class_install_property (gobject_class, PROP_SAMPLES_PER_BUFFER, + g_param_spec_int ("samplesperbuffer", "Samples per buffer", + "Number of samples in each outgoing buffer", + 1, G_MAXINT, DEFAULT_SAMPLES_PER_BUFFER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_WAVE, + g_param_spec_enum ("wave", "Waveform", "Oscillator waveform", + GST_TYPE_AUDIO_TEST_SRC_WAVE, GST_AUDIO_TEST_SRC_WAVE_SINE, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FREQ, + g_param_spec_double ("freq", "Frequency", "Frequency of test signal", + 0.0, 20000.0, DEFAULT_FREQ, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_VOLUME, + g_param_spec_double ("volume", "Volume", "Volume of test signal", 0.0, + 1.0, DEFAULT_VOLUME, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_IS_LIVE, + g_param_spec_boolean ("is-live", "Is Live", + "Whether to act as a live source", DEFAULT_IS_LIVE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", + "Timestamp offset", + "An offset added to timestamps set on buffers (in ns)", G_MININT64, + G_MAXINT64, DEFAULT_TIMESTAMP_OFFSET, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PUSH, + g_param_spec_boolean ("can-activate-push", "Can activate push", + "Can activate in push mode", DEFAULT_CAN_ACTIVATE_PUSH, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CAN_ACTIVATE_PULL, + g_param_spec_boolean ("can-activate-pull", "Can activate pull", + "Can activate in pull mode", DEFAULT_CAN_ACTIVATE_PULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->set_caps = GST_DEBUG_FUNCPTR (gst_audio_test_src_setcaps); + gstbasesrc_class->is_seekable = + GST_DEBUG_FUNCPTR (gst_audio_test_src_is_seekable); + gstbasesrc_class->check_get_range = + GST_DEBUG_FUNCPTR (gst_audio_test_src_check_get_range); + gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_audio_test_src_do_seek); + gstbasesrc_class->query = GST_DEBUG_FUNCPTR (gst_audio_test_src_query); + gstbasesrc_class->get_times = + GST_DEBUG_FUNCPTR (gst_audio_test_src_get_times); + gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_audio_test_src_start); + gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_audio_test_src_stop); + gstbasesrc_class->create = GST_DEBUG_FUNCPTR (gst_audio_test_src_create); +} + +static void +gst_audio_test_src_init (GstAudioTestSrc * src, GstAudioTestSrcClass * g_class) +{ + GstPad *pad = GST_BASE_SRC_PAD (src); + + gst_pad_set_fixatecaps_function (pad, gst_audio_test_src_src_fixate); + + src->samplerate = 44100; + src->format = GST_AUDIO_TEST_SRC_FORMAT_NONE; + + src->volume = DEFAULT_VOLUME; + src->freq = DEFAULT_FREQ; + + /* we operate in time */ + gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE); + + src->samples_per_buffer = DEFAULT_SAMPLES_PER_BUFFER; + src->generate_samples_per_buffer = src->samples_per_buffer; + src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET; + src->can_activate_pull = DEFAULT_CAN_ACTIVATE_PULL; + + src->gen = NULL; + + src->wave = DEFAULT_WAVE; + gst_base_src_set_blocksize (GST_BASE_SRC (src), -1); +} + +static void +gst_audio_test_src_finalize (GObject * object) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object); + + if (src->gen) + g_rand_free (src->gen); + src->gen = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_audio_test_src_src_fixate (GstPad * pad, GstCaps * caps) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (GST_PAD_PARENT (pad)); + const gchar *name; + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + GST_DEBUG_OBJECT (src, "fixating samplerate to %d", src->samplerate); + + gst_structure_fixate_field_nearest_int (structure, "rate", src->samplerate); + + name = gst_structure_get_name (structure); + if (strcmp (name, "audio/x-raw-int") == 0) + gst_structure_fixate_field_nearest_int (structure, "width", 32); + else if (strcmp (name, "audio/x-raw-float") == 0) + gst_structure_fixate_field_nearest_int (structure, "width", 64); + + /* fixate to mono unless downstream requires stereo, for backwards compat */ + gst_structure_fixate_field_nearest_int (structure, "channels", 1); +} + +static gboolean +gst_audio_test_src_setcaps (GstBaseSrc * basesrc, GstCaps * caps) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc); + const GstStructure *structure; + const gchar *name; + gint width; + gboolean ret; + + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "rate", &src->samplerate); + + GST_DEBUG_OBJECT (src, "negotiated to samplerate %d", src->samplerate); + + name = gst_structure_get_name (structure); + if (strcmp (name, "audio/x-raw-int") == 0) { + ret &= gst_structure_get_int (structure, "width", &width); + src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_S32 : + GST_AUDIO_TEST_SRC_FORMAT_S16; + } else { + ret &= gst_structure_get_int (structure, "width", &width); + src->format = (width == 32) ? GST_AUDIO_TEST_SRC_FORMAT_F32 : + GST_AUDIO_TEST_SRC_FORMAT_F64; + } + + /* allocate a new buffer suitable for this pad */ + switch (src->format) { + case GST_AUDIO_TEST_SRC_FORMAT_S16: + src->sample_size = sizeof (gint16); + break; + case GST_AUDIO_TEST_SRC_FORMAT_S32: + src->sample_size = sizeof (gint32); + break; + case GST_AUDIO_TEST_SRC_FORMAT_F32: + src->sample_size = sizeof (gfloat); + break; + case GST_AUDIO_TEST_SRC_FORMAT_F64: + src->sample_size = sizeof (gdouble); + break; + default: + /* can't really happen */ + ret = FALSE; + break; + } + + ret &= gst_structure_get_int (structure, "channels", &src->channels); + GST_DEBUG_OBJECT (src, "negotiated to %d channels", src->channels); + + gst_audio_test_src_change_wave (src); + + return ret; +} + +static gboolean +gst_audio_test_src_query (GstBaseSrc * basesrc, GstQuery * query) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (src_fmt == dest_fmt) { + dest_val = src_val; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + /* samples to time */ + dest_val = + gst_util_uint64_scale_int (src_val, GST_SECOND, + src->samplerate); + break; + default: + goto error; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + /* time to samples */ + dest_val = + gst_util_uint64_scale_int (src_val, src->samplerate, + GST_SECOND); + break; + default: + goto error; + } + break; + default: + goto error; + } + done: + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + res = TRUE; + break; + } + default: + res = GST_BASE_SRC_CLASS (parent_class)->query (basesrc, query); + break; + } + + return res; + /* ERROR */ +error: + { + GST_DEBUG_OBJECT (src, "query failed"); + return FALSE; + } +} + +#define DEFINE_SINE(type,scale) \ +static void \ +gst_audio_test_src_create_sine_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, amp; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + amp = src->volume * scale; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + for (c = 0; c < src->channels; ++c) { \ + samples[i++] = (g##type) (sin (src->accumulator) * amp); \ + } \ + } \ +} + +DEFINE_SINE (int16, 32767.0); +DEFINE_SINE (int32, 2147483647.0); +DEFINE_SINE (float, 1.0); +DEFINE_SINE (double, 1.0); + +static const ProcessFunc sine_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_sine_int16, + (ProcessFunc) gst_audio_test_src_create_sine_int32, + (ProcessFunc) gst_audio_test_src_create_sine_float, + (ProcessFunc) gst_audio_test_src_create_sine_double +}; + +#define DEFINE_SQUARE(type,scale) \ +static void \ +gst_audio_test_src_create_square_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, amp; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + amp = src->volume * scale; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + for (c = 0; c < src->channels; ++c) { \ + samples[i++] = (g##type) ((src->accumulator < M_PI) ? amp : -amp); \ + } \ + } \ +} + +DEFINE_SQUARE (int16, 32767.0); +DEFINE_SQUARE (int32, 2147483647.0); +DEFINE_SQUARE (float, 1.0); +DEFINE_SQUARE (double, 1.0); + +static const ProcessFunc square_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_square_int16, + (ProcessFunc) gst_audio_test_src_create_square_int32, + (ProcessFunc) gst_audio_test_src_create_square_float, + (ProcessFunc) gst_audio_test_src_create_square_double +}; + +#define DEFINE_SAW(type,scale) \ +static void \ +gst_audio_test_src_create_saw_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, amp; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + amp = (src->volume * scale) / M_PI; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + if (src->accumulator < M_PI) { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) (src->accumulator * amp); \ + } else { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ + } \ + } \ +} + +DEFINE_SAW (int16, 32767.0); +DEFINE_SAW (int32, 2147483647.0); +DEFINE_SAW (float, 1.0); +DEFINE_SAW (double, 1.0); + +static const ProcessFunc saw_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_saw_int16, + (ProcessFunc) gst_audio_test_src_create_saw_int32, + (ProcessFunc) gst_audio_test_src_create_saw_float, + (ProcessFunc) gst_audio_test_src_create_saw_double +}; + +#define DEFINE_TRIANGLE(type,scale) \ +static void \ +gst_audio_test_src_create_triangle_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, amp; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + amp = (src->volume * scale) / M_PI_2; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + if (src->accumulator < (M_PI * 0.5)) { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) (src->accumulator * amp); \ + } else if (src->accumulator < (M_PI * 1.5)) { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) ((src->accumulator - M_PI) * -amp); \ + } else { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) ((M_PI_M2 - src->accumulator) * -amp); \ + } \ + } \ +} + +DEFINE_TRIANGLE (int16, 32767.0); +DEFINE_TRIANGLE (int32, 2147483647.0); +DEFINE_TRIANGLE (float, 1.0); +DEFINE_TRIANGLE (double, 1.0); + +static const ProcessFunc triangle_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_triangle_int16, + (ProcessFunc) gst_audio_test_src_create_triangle_int32, + (ProcessFunc) gst_audio_test_src_create_triangle_float, + (ProcessFunc) gst_audio_test_src_create_triangle_double +}; + +#define DEFINE_SILENCE(type) \ +static void \ +gst_audio_test_src_create_silence_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + memset (samples, 0, src->generate_samples_per_buffer * sizeof (g##type) * src->channels); \ +} + +DEFINE_SILENCE (int16); +DEFINE_SILENCE (int32); +DEFINE_SILENCE (float); +DEFINE_SILENCE (double); + +static const ProcessFunc silence_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_silence_int16, + (ProcessFunc) gst_audio_test_src_create_silence_int32, + (ProcessFunc) gst_audio_test_src_create_silence_float, + (ProcessFunc) gst_audio_test_src_create_silence_double +}; + +#define DEFINE_WHITE_NOISE(type,scale) \ +static void \ +gst_audio_test_src_create_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble amp = (src->volume * scale); \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) (amp * g_rand_double_range (src->gen, -1.0, 1.0)); \ + } \ +} + +DEFINE_WHITE_NOISE (int16, 32767.0); +DEFINE_WHITE_NOISE (int32, 2147483647.0); +DEFINE_WHITE_NOISE (float, 1.0); +DEFINE_WHITE_NOISE (double, 1.0); + +static const ProcessFunc white_noise_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_white_noise_int16, + (ProcessFunc) gst_audio_test_src_create_white_noise_int32, + (ProcessFunc) gst_audio_test_src_create_white_noise_float, + (ProcessFunc) gst_audio_test_src_create_white_noise_double +}; + +/* pink noise calculation is based on + * http://www.firstpr.com.au/dsp/pink-noise/phil_burk_19990905_patest_pink.c + * which has been released under public domain + * Many thanks Phil! + */ +static void +gst_audio_test_src_init_pink_noise (GstAudioTestSrc * src) +{ + gint i; + gint num_rows = 12; /* arbitrary: 1 .. PINK_MAX_RANDOM_ROWS */ + glong pmax; + + src->pink.index = 0; + src->pink.index_mask = (1 << num_rows) - 1; + /* calculate maximum possible signed random value. + * Extra 1 for white noise always added. */ + pmax = (num_rows + 1) * (1 << (PINK_RANDOM_BITS - 1)); + src->pink.scalar = 1.0f / pmax; + /* Initialize rows. */ + for (i = 0; i < num_rows; i++) + src->pink.rows[i] = 0; + src->pink.running_sum = 0; +} + +/* Generate Pink noise values between -1.0 and +1.0 */ +static gdouble +gst_audio_test_src_generate_pink_noise_value (GstAudioTestSrc * src) +{ + GstPinkNoise *pink = &src->pink; + glong new_random; + glong sum; + + /* Increment and mask index. */ + pink->index = (pink->index + 1) & pink->index_mask; + + /* If index is zero, don't update any random values. */ + if (pink->index != 0) { + /* Determine how many trailing zeros in PinkIndex. */ + /* This algorithm will hang if n==0 so test first. */ + gint num_zeros = 0; + gint n = pink->index; + + while ((n & 1) == 0) { + n = n >> 1; + num_zeros++; + } + + /* Replace the indexed ROWS random value. + * Subtract and add back to RunningSum instead of adding all the random + * values together. Only one changes each time. + */ + pink->running_sum -= pink->rows[num_zeros]; + new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen) + / (G_MAXUINT32 + 1.0)); + pink->running_sum += new_random; + pink->rows[num_zeros] = new_random; + } + + /* Add extra white noise value. */ + new_random = 32768.0 - (65536.0 * (gulong) g_rand_int (src->gen) + / (G_MAXUINT32 + 1.0)); + sum = pink->running_sum + new_random; + + /* Scale to range of -1.0 to 0.9999. */ + return (pink->scalar * sum); +} + +#define DEFINE_PINK(type, scale) \ +static void \ +gst_audio_test_src_create_pink_noise_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble amp; \ + \ + amp = src->volume * scale; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + for (c = 0; c < src->channels; ++c) { \ + samples[i++] = \ + (g##type) (gst_audio_test_src_generate_pink_noise_value (src) * \ + amp); \ + } \ + } \ +} + +DEFINE_PINK (int16, 32767.0); +DEFINE_PINK (int32, 2147483647.0); +DEFINE_PINK (float, 1.0); +DEFINE_PINK (double, 1.0); + +static const ProcessFunc pink_noise_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_pink_noise_int16, + (ProcessFunc) gst_audio_test_src_create_pink_noise_int32, + (ProcessFunc) gst_audio_test_src_create_pink_noise_float, + (ProcessFunc) gst_audio_test_src_create_pink_noise_double +}; + +static void +gst_audio_test_src_init_sine_table (GstAudioTestSrc * src) +{ + gint i; + gdouble ang = 0.0; + gdouble step = M_PI_M2 / 1024.0; + gdouble amp = src->volume; + + for (i = 0; i < 1024; i++) { + src->wave_table[i] = sin (ang) * amp; + ang += step; + } +} + +#define DEFINE_SINE_TABLE(type,scale) \ +static void \ +gst_audio_test_src_create_sine_table_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, scl; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + scl = 1024.0 / M_PI_M2; \ + \ + i = 0; \ + while (i < (src->generate_samples_per_buffer * src->channels)) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + for (c = 0; c < src->channels; ++c) \ + samples[i++] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \ + } \ +} + +DEFINE_SINE_TABLE (int16, 32767.0); +DEFINE_SINE_TABLE (int32, 2147483647.0); +DEFINE_SINE_TABLE (float, 1.0); +DEFINE_SINE_TABLE (double, 1.0); + +static const ProcessFunc sine_table_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_sine_table_int16, + (ProcessFunc) gst_audio_test_src_create_sine_table_int32, + (ProcessFunc) gst_audio_test_src_create_sine_table_float, + (ProcessFunc) gst_audio_test_src_create_sine_table_double +}; + +#define DEFINE_TICKS(type,scale) \ +static void \ +gst_audio_test_src_create_tick_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble step, scl; \ + \ + step = M_PI_M2 * src->freq / src->samplerate; \ + scl = 1024.0 / M_PI_M2; \ + \ + for (i = 0; i < src->generate_samples_per_buffer; i++) { \ + src->accumulator += step; \ + if (src->accumulator >= M_PI_M2) \ + src->accumulator -= M_PI_M2; \ + \ + if ((src->next_sample + i)%src->samplerate < 1600) { \ + for (c = 0; c < src->channels; ++c) \ + samples[(i * src->channels) + c] = (g##type) scale * src->wave_table[(gint) (src->accumulator * scl)]; \ + } else { \ + for (c = 0; c < src->channels; ++c) \ + samples[(i * src->channels) + c] = 0; \ + } \ + } \ +} + +DEFINE_TICKS (int16, 32767.0); +DEFINE_TICKS (int32, 2147483647.0); +DEFINE_TICKS (float, 1.0); +DEFINE_TICKS (double, 1.0); + +static const ProcessFunc tick_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_tick_int16, + (ProcessFunc) gst_audio_test_src_create_tick_int32, + (ProcessFunc) gst_audio_test_src_create_tick_float, + (ProcessFunc) gst_audio_test_src_create_tick_double +}; + +/* Gaussian white noise using Box-Muller algorithm. unit variance + * normally-distributed random numbers are generated in pairs as the real + * and imaginary parts of a compex random variable with + * uniformly-distributed argument and \chi^{2}-distributed modulus. + */ + +#define DEFINE_GAUSSIAN_WHITE_NOISE(type,scale) \ +static void \ +gst_audio_test_src_create_gaussian_white_noise_##type (GstAudioTestSrc * src, g##type * samples) \ +{ \ + gint i, c; \ + gdouble amp = (src->volume * scale); \ + \ + for (i = 0; i < src->generate_samples_per_buffer * src->channels; ) { \ + for (c = 0; c < src->channels; ++c) { \ + gdouble mag = sqrt (-2 * log (1.0 - g_rand_double (src->gen))); \ + gdouble phs = g_rand_double_range (src->gen, 0.0, M_PI_M2); \ + \ + samples[i++] = (g##type) (amp * mag * cos (phs)); \ + if (++c >= src->channels) \ + break; \ + samples[i++] = (g##type) (amp * mag * sin (phs)); \ + } \ + } \ +} + +DEFINE_GAUSSIAN_WHITE_NOISE (int16, 32767.0); +DEFINE_GAUSSIAN_WHITE_NOISE (int32, 2147483647.0); +DEFINE_GAUSSIAN_WHITE_NOISE (float, 1.0); +DEFINE_GAUSSIAN_WHITE_NOISE (double, 1.0); + +static const ProcessFunc gaussian_white_noise_funcs[] = { + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int16, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_int32, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_float, + (ProcessFunc) gst_audio_test_src_create_gaussian_white_noise_double +}; + +/* + * gst_audio_test_src_change_wave: + * Assign function pointer of wave genrator. + */ +static void +gst_audio_test_src_change_wave (GstAudioTestSrc * src) +{ + if (src->format == -1) { + src->process = NULL; + return; + } + + switch (src->wave) { + case GST_AUDIO_TEST_SRC_WAVE_SINE: + src->process = sine_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_SQUARE: + src->process = square_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_SAW: + src->process = saw_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_TRIANGLE: + src->process = triangle_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_SILENCE: + src->process = silence_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: + if (!(src->gen)) + src->gen = g_rand_new (); + src->process = white_noise_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE: + if (!(src->gen)) + src->gen = g_rand_new (); + gst_audio_test_src_init_pink_noise (src); + src->process = pink_noise_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB: + gst_audio_test_src_init_sine_table (src); + src->process = sine_table_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_TICKS: + gst_audio_test_src_init_sine_table (src); + src->process = tick_funcs[src->format]; + break; + case GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: + if (!(src->gen)) + src->gen = g_rand_new (); + src->process = gaussian_white_noise_funcs[src->format]; + break; + default: + GST_ERROR ("invalid wave-form"); + break; + } +} + +/* + * gst_audio_test_src_change_volume: + * Recalc wave tables for precalculated waves. + */ +static void +gst_audio_test_src_change_volume (GstAudioTestSrc * src) +{ + switch (src->wave) { + case GST_AUDIO_TEST_SRC_WAVE_SINE_TAB: + gst_audio_test_src_init_sine_table (src); + break; + default: + break; + } +} + +static void +gst_audio_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + /* for live sources, sync on the timestamp of the buffer */ + if (gst_base_src_is_live (basesrc)) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + GstClockTime duration = GST_BUFFER_DURATION (buffer); + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } + } else { + *start = -1; + *end = -1; + } +} + +static gboolean +gst_audio_test_src_start (GstBaseSrc * basesrc) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc); + + src->next_sample = 0; + src->next_byte = 0; + src->next_time = 0; + src->check_seek_stop = FALSE; + src->eos_reached = FALSE; + src->tags_pushed = FALSE; + src->accumulator = 0; + + return TRUE; +} + +static gboolean +gst_audio_test_src_stop (GstBaseSrc * basesrc) +{ + return TRUE; +} + +/* seek to time, will be called when we operate in push mode. In pull mode we + * get the requested byte offset. */ +static gboolean +gst_audio_test_src_do_seek (GstBaseSrc * basesrc, GstSegment * segment) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (basesrc); + GstClockTime time; + + GST_DEBUG_OBJECT (src, "seeking %" GST_SEGMENT_FORMAT, segment); + + time = segment->last_stop; + src->reverse = (segment->rate < 0.0); + + /* now move to the time indicated */ + src->next_sample = + gst_util_uint64_scale_int (time, src->samplerate, GST_SECOND); + src->next_byte = src->next_sample * src->sample_size * src->channels; + src->next_time = + gst_util_uint64_scale_int (src->next_sample, GST_SECOND, src->samplerate); + + GST_DEBUG_OBJECT (src, "seeking next_sample=%" G_GINT64_FORMAT + " next_time=%" GST_TIME_FORMAT, src->next_sample, + GST_TIME_ARGS (src->next_time)); + + g_assert (src->next_time <= time); + + if (!src->reverse) { + if (GST_CLOCK_TIME_IS_VALID (segment->start)) { + segment->time = segment->start; + } + } else { + if (GST_CLOCK_TIME_IS_VALID (segment->stop)) { + segment->time = segment->stop; + } + } + + if (GST_CLOCK_TIME_IS_VALID (segment->stop)) { + time = segment->stop; + src->sample_stop = gst_util_uint64_scale_int (time, src->samplerate, + GST_SECOND); + src->check_seek_stop = TRUE; + } else { + src->check_seek_stop = FALSE; + } + src->eos_reached = FALSE; + + return TRUE; +} + +static gboolean +gst_audio_test_src_is_seekable (GstBaseSrc * basesrc) +{ + /* we're seekable... */ + return TRUE; +} + +static gboolean +gst_audio_test_src_check_get_range (GstBaseSrc * basesrc) +{ + GstAudioTestSrc *src; + + src = GST_AUDIO_TEST_SRC (basesrc); + + /* if we can operate in pull mode */ + return src->can_activate_pull; +} + +static GstFlowReturn +gst_audio_test_src_create (GstBaseSrc * basesrc, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstFlowReturn res; + GstAudioTestSrc *src; + GstBuffer *buf; + GstClockTime next_time; + gint64 next_sample, next_byte; + gint bytes, samples; + GstElementClass *eclass; + + src = GST_AUDIO_TEST_SRC (basesrc); + + /* example for tagging generated data */ + if (!src->tags_pushed) { + GstTagList *taglist; + + taglist = gst_tag_list_new (); + + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, + GST_TAG_DESCRIPTION, "audiotest wave", NULL); + + eclass = GST_ELEMENT_CLASS (parent_class); + if (eclass->send_event) + eclass->send_event (GST_ELEMENT_CAST (basesrc), + gst_event_new_tag (taglist)); + src->tags_pushed = TRUE; + } + + if (src->eos_reached) { + GST_INFO_OBJECT (src, "eos"); + return GST_FLOW_UNEXPECTED; + } + + /* if no length was given, use our default length in samples otherwise convert + * the length in bytes to samples. */ + if (length == -1) + samples = src->samples_per_buffer; + else + samples = length / (src->sample_size * src->channels); + + /* if no offset was given, use our next logical byte */ + if (offset == -1) + offset = src->next_byte; + + /* now see if we are at the byteoffset we think we are */ + if (offset != src->next_byte) { + GST_DEBUG_OBJECT (src, "seek to new offset %" G_GUINT64_FORMAT, offset); + /* we have a discont in the expected sample offset, do a 'seek' */ + src->next_sample = offset / (src->sample_size * src->channels); + src->next_time = + gst_util_uint64_scale_int (src->next_sample, GST_SECOND, + src->samplerate); + src->next_byte = offset; + } + + /* check for eos */ + if (src->check_seek_stop && + (src->sample_stop > src->next_sample) && + (src->sample_stop < src->next_sample + samples) + ) { + /* calculate only partial buffer */ + src->generate_samples_per_buffer = src->sample_stop - src->next_sample; + next_sample = src->sample_stop; + src->eos_reached = TRUE; + } else { + /* calculate full buffer */ + src->generate_samples_per_buffer = samples; + next_sample = src->next_sample + (src->reverse ? (-samples) : samples); + } + + bytes = src->generate_samples_per_buffer * src->sample_size * src->channels; + + if ((res = gst_pad_alloc_buffer (basesrc->srcpad, src->next_sample, + bytes, GST_PAD_CAPS (basesrc->srcpad), &buf)) != GST_FLOW_OK) { + return res; + } + + next_byte = src->next_byte + (src->reverse ? (-bytes) : bytes); + next_time = gst_util_uint64_scale_int (next_sample, GST_SECOND, + src->samplerate); + + GST_LOG_OBJECT (src, "samplerate %d", src->samplerate); + GST_LOG_OBJECT (src, "next_sample %" G_GINT64_FORMAT ", ts %" GST_TIME_FORMAT, + next_sample, GST_TIME_ARGS (next_time)); + + GST_BUFFER_OFFSET (buf) = src->next_sample; + GST_BUFFER_OFFSET_END (buf) = next_sample; + if (!src->reverse) { + GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + src->next_time; + GST_BUFFER_DURATION (buf) = next_time - src->next_time; + } else { + GST_BUFFER_TIMESTAMP (buf) = src->timestamp_offset + next_time; + GST_BUFFER_DURATION (buf) = src->next_time - next_time; + } + + gst_object_sync_values (G_OBJECT (src), GST_BUFFER_TIMESTAMP (buf)); + + src->next_time = next_time; + src->next_sample = next_sample; + src->next_byte = next_byte; + + GST_LOG_OBJECT (src, "generating %u samples at ts %" GST_TIME_FORMAT, + src->generate_samples_per_buffer, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + src->process (src, GST_BUFFER_DATA (buf)); + + if (G_UNLIKELY ((src->wave == GST_AUDIO_TEST_SRC_WAVE_SILENCE) + || (src->volume == 0.0))) { + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_GAP); + } + + *buffer = buf; + + return GST_FLOW_OK; +} + +static void +gst_audio_test_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object); + + switch (prop_id) { + case PROP_SAMPLES_PER_BUFFER: + src->samples_per_buffer = g_value_get_int (value); + break; + case PROP_WAVE: + src->wave = g_value_get_enum (value); + gst_audio_test_src_change_wave (src); + break; + case PROP_FREQ: + src->freq = g_value_get_double (value); + break; + case PROP_VOLUME: + src->volume = g_value_get_double (value); + gst_audio_test_src_change_volume (src); + break; + case PROP_IS_LIVE: + gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); + break; + case PROP_TIMESTAMP_OFFSET: + src->timestamp_offset = g_value_get_int64 (value); + break; + case PROP_CAN_ACTIVATE_PUSH: + GST_BASE_SRC (src)->can_activate_push = g_value_get_boolean (value); + break; + case PROP_CAN_ACTIVATE_PULL: + src->can_activate_pull = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_audio_test_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstAudioTestSrc *src = GST_AUDIO_TEST_SRC (object); + + switch (prop_id) { + case PROP_SAMPLES_PER_BUFFER: + g_value_set_int (value, src->samples_per_buffer); + break; + case PROP_WAVE: + g_value_set_enum (value, src->wave); + break; + case PROP_FREQ: + g_value_set_double (value, src->freq); + break; + case PROP_VOLUME: + g_value_set_double (value, src->volume); + break; + case PROP_IS_LIVE: + g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); + break; + case PROP_TIMESTAMP_OFFSET: + g_value_set_int64 (value, src->timestamp_offset); + break; + case PROP_CAN_ACTIVATE_PUSH: + g_value_set_boolean (value, GST_BASE_SRC (src)->can_activate_push); + break; + case PROP_CAN_ACTIVATE_PULL: + g_value_set_boolean (value, src->can_activate_pull); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + /* initialize gst controller library */ + gst_controller_init (NULL, NULL); + + GST_DEBUG_CATEGORY_INIT (audio_test_src_debug, "audiotestsrc", 0, + "Audio Test Source"); + + return gst_element_register (plugin, "audiotestsrc", + GST_RANK_NONE, GST_TYPE_AUDIO_TEST_SRC); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "audiotestsrc", + "Creates audio test signals of given frequency and volume", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.h b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.h new file mode 100644 index 0000000..8c76594 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/audiotestsrc/gstaudiotestsrc.h @@ -0,0 +1,144 @@ +/* GStreamer + * Copyright (C) 2005 Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_TEST_SRC_H__ +#define __GST_AUDIO_TEST_SRC_H__ + + +#include +#include + +G_BEGIN_DECLS + + +#define GST_TYPE_AUDIO_TEST_SRC \ + (gst_audio_test_src_get_type()) +#define GST_AUDIO_TEST_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_TEST_SRC,GstAudioTestSrc)) +#define GST_AUDIO_TEST_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_TEST_SRC,GstAudioTestSrcClass)) +#define GST_IS_AUDIO_TEST_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_TEST_SRC)) +#define GST_IS_AUDIO_TEST_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_TEST_SRC)) + +/** + * GstAudioTestSrcWave: + * @GST_AUDIO_TEST_SRC_WAVE_SINE: a sine wave + * @GST_AUDIO_TEST_SRC_WAVE_SQUARE: a square wave + * @GST_AUDIO_TEST_SRC_WAVE_SAW: a saw wave + * @GST_AUDIO_TEST_SRC_WAVE_TRIANGLE: a tringle wave + * @GST_AUDIO_TEST_SRC_WAVE_SILENCE: silence + * @GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE: white uniform noise + * @GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE: pink noise + * @GST_AUDIO_TEST_SRC_WAVE_SINE_TAB: sine wave using a table + * @GST_AUDIO_TEST_SRC_WAVE_TICKS: periodic ticks + * @GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE: white (zero mean) Gaussian noise; volume sets the standard deviation of the noise in units of the range of values of the sample type, e.g. volume=0.1 produces noise with a standard deviation of 0.1*32767=3277 with 16-bit integer samples, or 0.1*1.0=0.1 with floating-point samples. + * + * Different types of supported sound waves. + */ +typedef enum { + GST_AUDIO_TEST_SRC_WAVE_SINE, + GST_AUDIO_TEST_SRC_WAVE_SQUARE, + GST_AUDIO_TEST_SRC_WAVE_SAW, + GST_AUDIO_TEST_SRC_WAVE_TRIANGLE, + GST_AUDIO_TEST_SRC_WAVE_SILENCE, + GST_AUDIO_TEST_SRC_WAVE_WHITE_NOISE, + GST_AUDIO_TEST_SRC_WAVE_PINK_NOISE, + GST_AUDIO_TEST_SRC_WAVE_SINE_TAB, + GST_AUDIO_TEST_SRC_WAVE_TICKS, + GST_AUDIO_TEST_SRC_WAVE_GAUSSIAN_WHITE_NOISE +} GstAudioTestSrcWave; + +#define PINK_MAX_RANDOM_ROWS (30) +#define PINK_RANDOM_BITS (16) +#define PINK_RANDOM_SHIFT ((sizeof(long)*8)-PINK_RANDOM_BITS) + +typedef struct { + glong rows[PINK_MAX_RANDOM_ROWS]; + glong running_sum; /* Used to optimize summing of generators. */ + gint index; /* Incremented each sample. */ + gint index_mask; /* Index wrapped by ANDing with this mask. */ + gdouble scalar; /* Used to scale within range of -1.0 to +1.0 */ +} GstPinkNoise; + +typedef enum { + GST_AUDIO_TEST_SRC_FORMAT_NONE = -1, + GST_AUDIO_TEST_SRC_FORMAT_S16 = 0, + GST_AUDIO_TEST_SRC_FORMAT_S32, + GST_AUDIO_TEST_SRC_FORMAT_F32, + GST_AUDIO_TEST_SRC_FORMAT_F64 +} GstAudioTestSrcFormat; + +typedef struct _GstAudioTestSrc GstAudioTestSrc; +typedef struct _GstAudioTestSrcClass GstAudioTestSrcClass; + +typedef void (*ProcessFunc) (GstAudioTestSrc*, guint8 *); + +/** + * GstAudioTestSrc: + * + * audiotestsrc object structure. + */ +struct _GstAudioTestSrc { + GstBaseSrc parent; + + ProcessFunc process; + + /* parameters */ + GstAudioTestSrcWave wave; + gdouble volume; + gdouble freq; + + /* audio parameters */ + gint channels; + gint samplerate; + gint samples_per_buffer; + gint sample_size; + GstAudioTestSrcFormat format; + + /*< private >*/ + gboolean tags_pushed; /* send tags just once ? */ + GstClockTimeDiff timestamp_offset; /* base offset */ + GstClockTime next_time; /* next timestamp */ + gint64 next_sample; /* next sample to send */ + gint64 next_byte; /* next byte to send */ + gint64 sample_stop; + gboolean check_seek_stop; + gboolean eos_reached; + gint generate_samples_per_buffer; /* used to generate a partial buffer */ + gboolean can_activate_pull; + gboolean reverse; /* play backwards */ + + /* waveform specific context data */ + GRand *gen; /* random number generator */ + gdouble accumulator; /* phase angle */ + GstPinkNoise pink; + gdouble wave_table[1024]; +}; + +struct _GstAudioTestSrcClass { + GstBaseSrcClass parent_class; +}; + +GType gst_audio_test_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_AUDIO_TEST_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/.gitignore b/gst-plugins-base-subtitles0.10/gst/encoding/.gitignore new file mode 100644 index 0000000..ff44545 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/.gitignore @@ -0,0 +1 @@ +gstencode-marshal.[ch] diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/Makefile.am b/gst-plugins-base-subtitles0.10/gst/encoding/Makefile.am new file mode 100644 index 0000000..dace539 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/Makefile.am @@ -0,0 +1,53 @@ +# variables used for enum/marshal generation +glib_enum_define = GST_ENCODE +glib_gen_prefix = gst_encode +glib_gen_basename = gstencode + +built_sources = gstencode-marshal.c +built_headers = gstencode-marshal.h + +plugin_LTLIBRARIES = libgstencodebin.la + +libgstencodebin_la_SOURCES = \ + gstencodebin.c \ + gstsmartencoder.c \ + gststreamcombiner.c \ + gststreamsplitter.c + +nodist_libgstencodebin_la_SOURCES = $(built_sources) +libgstencodebin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstencodebin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstencodebin_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +libgstencodebin_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstencodebin.h \ + gststreamcombiner.h \ + gststreamsplitter.h \ + gstsmartencoder.h + + +BUILT_SOURCES = $(built_headers) $(built_sources) + +EXTRA_DIST = gstencode-marshal.list + +CLEANFILES = $(BUILT_SOURCES) + +include $(top_srcdir)/common/gst-glib-gen.mak + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstencodebin -:SHARED libgstencodebin \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstencodebin_la_SOURCES) \ + $(nodist_libgstencodebin_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstencodebin_la_CFLAGS) \ + -:LDFLAGS $(libgstencodebin_la_LDFLAGS) \ + $(libgstencodebin_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gstencode-marshal.list b/gst-plugins-base-subtitles0.10/gst/encoding/gstencode-marshal.list new file mode 100644 index 0000000..00f26ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gstencode-marshal.list @@ -0,0 +1 @@ +OBJECT:BOXED diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.c b/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.c new file mode 100644 index 0000000..4aeb09b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.c @@ -0,0 +1,1796 @@ +/* GStreamer encoding bin + * Copyright (C) 2009 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include "gstencodebin.h" +#include "gstsmartencoder.h" +#include "gststreamsplitter.h" +#include "gststreamcombiner.h" +#include + +/** + * SECTION:element-encodebin + * + * EncodeBin provides a bin for encoding/muxing various streams according to + * a specified #GstEncodingProfile. + * + * Based on the profile that was set (via the #GstEncodeBin:profile property), + * EncodeBin will internally select and configure the required elements + * (encoders, muxers, but also audio and video converters) so that you can + * provide it raw or pre-encoded streams of data in input and have your + * encoded/muxed/converted stream in output. + * + * + * Features + * + * + * Automatic encoder and muxer selection based on elements available on the + * system. + * + * + * Conversion of raw audio/video streams (scaling, framerate conversion, + * colorspace conversion, samplerate conversion) to conform to the profile + * output format. + * + * + * Variable number of streams. If the presence property for a stream encoding + * profile is 0, you can request any number of sink pads for it via the + * standard request pad gstreamer API or the #GstEncodeBin::request-pad action + * signal. + * + * + * Avoid reencoding (passthrough). If the input stream is already encoded and is + * compatible with what the #GstEncodingProfile expects, then the stream won't + * be re-encoded but just passed through downstream to the muxer or the output. + * + * + * Mix pre-encoded and raw streams as input. In addition to the passthrough + * feature above, you can feed both raw audio/video *AND* already-encoded data + * to a pad. #GstEncodeBin will take care of passing through the compatible + * segments and re-encoding the segments of media that need encoding. + * + * + * Standard behaviour is to use a #GstEncodingContainerProfile to have both + * encoding and muxing performed. But you can also provide a single stream + * profile (like #GstEncodingAudioProfile) to only have the encoding done and + * handle the encoded output yourself. + * + * + * Audio imperfection corrections. Incoming audio streams can have non perfect + * timestamps (jitter), like the streams coming from ASF files. #GstEncodeBin + * will automatically fix those imperfections for you. See + * #GstEncodeBin:audio-jitter-tolerance for more details. + * + * + * Variable or Constant video framerate. If your #GstEncodingVideoProfile has + * the variableframerate property deactivated (default), then the incoming + * raw video stream will be retimestampped in order to produce a constant + * framerate. + * + * + * Cross-boundary re-encoding. When feeding compatible pre-encoded streams that + * fall on segment boundaries, and for supported formats (right now only H263), + * the GOP will be decoded/reencoded when needed to produce an encoded output + * that fits exactly within the request GstSegment. + * + * + * Missing plugin support. If a #GstElement is missing to encode/mux to the + * request profile formats, a missing-plugin #GstMessage will be posted on the + * #GstBus, allowing systems that support the missing-plugin system to offer the + * user a way to install the missing element. + * + * + * + */ + + +/* TODO/FIXME + * + * Handling mp3!xing!idv3 and theora!ogg tagsetting scenarios: + * Once we have chosen a muxer: + * When a new stream is requested: + * If muxer is 'Formatter' OR doesn't have a TagSetter interface: + * Find a Formatter for the given stream (preferably with TagSetter) + * Insert that before muxer + **/ + +#define fast_pad_link(a,b) gst_pad_link_full((a),(b),GST_PAD_LINK_CHECK_NOTHING) +#define fast_element_link(a,b) gst_element_link_pads_full((a),"src",(b),"sink",GST_PAD_LINK_CHECK_NOTHING) + +/* generic templates */ +static GstStaticPadTemplate muxer_src_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate video_sink_template = +GST_STATIC_PAD_TEMPLATE ("video_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate audio_sink_template = +GST_STATIC_PAD_TEMPLATE ("audio_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +/* static GstStaticPadTemplate text_sink_template = */ +/* GST_STATIC_PAD_TEMPLATE ("text_%d", */ +/* GST_PAD_SINK, */ +/* GST_PAD_REQUEST, */ +/* GST_STATIC_CAPS_ANY); */ +static GstStaticPadTemplate private_sink_template = +GST_STATIC_PAD_TEMPLATE ("private_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +struct _GstEncodeBin +{ + GstBin parent; + + /* the profile field is only valid if it could be entirely setup */ + GstEncodingProfile *profile; + + GList *streams; /* List of StreamGroup, not sorted */ + + GstElement *muxer; + /* Ghostpad with changing target */ + GstPad *srcpad; + + /* TRUE if in PAUSED/PLAYING */ + gboolean active; + + /* available muxers, encoders and parsers */ + GList *muxers; + GList *encoders; + GList *parsers; + + /* Increasing counter for unique pad name */ + guint last_pad_id; + + /* Cached caps for identification */ + GstCaps *raw_video_caps; + GstCaps *raw_audio_caps; + /* GstCaps *raw_text_caps; */ + + guint queue_buffers_max; + guint queue_bytes_max; + guint64 queue_time_max; + + guint64 tolerance; + gboolean avoid_reencoding; +}; + +struct _GstEncodeBinClass +{ + GstBinClass parent; + + /* Action Signals */ + GstPad *(*request_pad) (GstEncodeBin * encodebin, GstCaps * caps); +}; + +typedef struct _StreamGroup StreamGroup; + +struct _StreamGroup +{ + GstEncodeBin *ebin; + GstEncodingProfile *profile; + GstPad *ghostpad; /* Sink ghostpad */ + GstElement *inqueue; /* Queue just after the ghostpad */ + GstElement *splitter; + GList *converters; /* List of conversion GstElement */ + GstElement *capsfilter; /* profile->restriction (if non-NULL/ANY) */ + GstElement *encoder; /* Encoder (can be NULL) */ + GstElement *combiner; + GstElement *parser; + GstElement *smartencoder; + GstElement *outfilter; /* Output capsfilter (streamprofile.format) */ + GstElement *outqueue; /* Queue just before the muxer */ +}; + +/* Default for queues (same defaults as queue element) */ +#define DEFAULT_QUEUE_BUFFERS_MAX 200 +#define DEFAULT_QUEUE_BYTES_MAX 10 * 1024 * 1024 +#define DEFAULT_QUEUE_TIME_MAX GST_SECOND +#define DEFAULT_AUDIO_JITTER_TOLERANCE 20 * GST_MSECOND +#define DEFAULT_AVOID_REENCODING FALSE + +#define DEFAULT_RAW_CAPS \ + "video/x-raw-yuv; " \ + "video/x-raw-rgb; " \ + "video/x-raw-gray; " \ + "audio/x-raw-int; " \ + "audio/x-raw-float; " \ + "text/plain; " \ + "text/x-pango-markup; " \ + "video/x-dvd-subpicture; " \ + "subpicture/x-pgs" + +/* Properties */ +enum +{ + PROP_0, + PROP_PROFILE, + PROP_QUEUE_BUFFERS_MAX, + PROP_QUEUE_BYTES_MAX, + PROP_QUEUE_TIME_MAX, + PROP_AUDIO_JITTER_TOLERANCE, + PROP_AVOID_REENCODING, + PROP_LAST +}; + +/* Signals */ +enum +{ + SIGNAL_REQUEST_PAD, + LAST_SIGNAL +}; + +static guint gst_encode_bin_signals[LAST_SIGNAL] = { 0 }; + +static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS); + +GST_DEBUG_CATEGORY_STATIC (gst_encode_bin_debug); +#define GST_CAT_DEFAULT gst_encode_bin_debug + +G_DEFINE_TYPE (GstEncodeBin, gst_encode_bin, GST_TYPE_BIN); + +static void gst_encode_bin_dispose (GObject * object); +static void gst_encode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_encode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static GstStateChangeReturn gst_encode_bin_change_state (GstElement * element, + GstStateChange transition); + +static GstPad *gst_encode_bin_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps); +static void gst_encode_bin_release_pad (GstElement * element, GstPad * pad); + +static gboolean +gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile); +static void gst_encode_bin_tear_down_profile (GstEncodeBin * ebin); +static gboolean gst_encode_bin_setup_profile (GstEncodeBin * ebin, + GstEncodingProfile * profile); + +static StreamGroup *_create_stream_group (GstEncodeBin * ebin, + GstEncodingProfile * sprof, const gchar * sinkpadname, GstCaps * sinkcaps); +static void stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup); +static GstPad *gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, + GstCaps * caps); + +static void +gst_encode_bin_class_init (GstEncodeBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + gobject_klass->dispose = gst_encode_bin_dispose; + gobject_klass->set_property = gst_encode_bin_set_property; + gobject_klass->get_property = gst_encode_bin_get_property; + + /* Properties */ + + /** + * GstEncodeBin:profile: + * + * The #GstEncodingProfile to use. This property must be set before going + * to %GST_STATE_PAUSED or higher. + */ + g_object_class_install_property (gobject_klass, PROP_PROFILE, + gst_param_spec_mini_object ("profile", "Profile", + "The GstEncodingProfile to use", GST_TYPE_ENCODING_PROFILE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_QUEUE_BUFFERS_MAX, + g_param_spec_uint ("queue-bytes-max", "Max. size (kB)", + "Max. amount of data in the queue (bytes, 0=disable)", + 0, G_MAXUINT, DEFAULT_QUEUE_BYTES_MAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_QUEUE_BYTES_MAX, + g_param_spec_uint ("queue-buffers-max", "Max. size (buffers)", + "Max. number of buffers in the queue (0=disable)", 0, G_MAXUINT, + DEFAULT_QUEUE_BUFFERS_MAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_QUEUE_TIME_MAX, + g_param_spec_uint64 ("queue-time-max", "Max. size (ns)", + "Max. amount of data in the queue (in ns, 0=disable)", 0, G_MAXUINT64, + DEFAULT_QUEUE_TIME_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_AUDIO_JITTER_TOLERANCE, + g_param_spec_uint64 ("audio-jitter-tolerance", "Audio jitter tolerance", + "Amount of timestamp jitter/imperfection to allow on audio streams before inserting/dropping samples (ns)", + 0, G_MAXUINT64, DEFAULT_AUDIO_JITTER_TOLERANCE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_AVOID_REENCODING, + g_param_spec_boolean ("avoid-reencoding", "Avoid re-encoding", + "Whether to re-encode portions of compatible video streams that lay on segment boundaries", + DEFAULT_AVOID_REENCODING, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* Signals */ + /** + * GstEncodeBin::request-pad + * @encodebin: a #GstEncodeBin instance + * @caps: a #GstCaps + * + * Use this method to request an unused sink request #GstPad that can take the + * provided @caps as input. You must release the pad with + * gst_element_release_request_pad() when you are done with it. + * + * Returns: A compatible #GstPad, or %NULL if no compatible #GstPad could be + * created or is available. + */ + gst_encode_bin_signals[SIGNAL_REQUEST_PAD] = + g_signal_new ("request-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstEncodeBinClass, + request_pad), NULL, NULL, gst_encode_marshal_OBJECT__BOXED, + GST_TYPE_PAD, 1, GST_TYPE_CAPS); + + klass->request_pad = gst_encode_bin_request_pad_signal; + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&muxer_src_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&video_sink_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&audio_sink_template)); + /* gst_element_class_add_pad_template (gstelement_klass, */ + /* gst_static_pad_template_get (&text_sink_template)); */ + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&private_sink_template)); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_encode_bin_change_state); + gstelement_klass->request_new_pad_full = + GST_DEBUG_FUNCPTR (gst_encode_bin_request_new_pad); + gstelement_klass->release_pad = + GST_DEBUG_FUNCPTR (gst_encode_bin_release_pad); + + gst_element_class_set_details_simple (gstelement_klass, + "Encoder Bin", + "Generic/Bin/Encoder", + "Convenience encoding/muxing element", + "Edward Hervey "); +} + +static void +gst_encode_bin_dispose (GObject * object) +{ + GstEncodeBin *ebin = (GstEncodeBin *) object; + + if (ebin->muxers) + gst_plugin_feature_list_free (ebin->muxers); + + if (ebin->encoders) + gst_plugin_feature_list_free (ebin->encoders); + + if (ebin->parsers) + gst_plugin_feature_list_free (ebin->parsers); + + gst_encode_bin_tear_down_profile (ebin); + + if (ebin->raw_video_caps) + gst_caps_unref (ebin->raw_video_caps); + if (ebin->raw_audio_caps) + gst_caps_unref (ebin->raw_audio_caps); + /* if (ebin->raw_text_caps) */ + /* gst_caps_unref (ebin->raw_text_caps); */ + + G_OBJECT_CLASS (gst_encode_bin_parent_class)->dispose (object); +} + +static void +gst_encode_bin_init (GstEncodeBin * encode_bin) +{ + GstPadTemplate *tmpl; + GList *formatters; + + encode_bin->muxers = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER, + GST_RANK_MARGINAL); + formatters = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_FORMATTER, + GST_RANK_SECONDARY); + encode_bin->muxers = g_list_concat (encode_bin->muxers, formatters); + + encode_bin->encoders = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, + GST_RANK_MARGINAL); + + encode_bin->parsers = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_PARSER, + GST_RANK_MARGINAL); + + encode_bin->raw_video_caps = + gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb;video/x-raw-gray"); + encode_bin->raw_audio_caps = + gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float"); + /* encode_bin->raw_text_caps = */ + /* gst_caps_from_string ("text/plain;text/x-pango-markup"); */ + + encode_bin->queue_buffers_max = DEFAULT_QUEUE_BUFFERS_MAX; + encode_bin->queue_bytes_max = DEFAULT_QUEUE_BYTES_MAX; + encode_bin->queue_time_max = DEFAULT_QUEUE_TIME_MAX; + encode_bin->tolerance = DEFAULT_AUDIO_JITTER_TOLERANCE; + encode_bin->avoid_reencoding = DEFAULT_AVOID_REENCODING; + + tmpl = gst_static_pad_template_get (&muxer_src_template); + encode_bin->srcpad = gst_ghost_pad_new_no_target_from_template ("src", tmpl); + gst_object_unref (tmpl); + gst_element_add_pad (GST_ELEMENT_CAST (encode_bin), encode_bin->srcpad); +} + +static void +gst_encode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstEncodeBin *ebin = (GstEncodeBin *) object; + + switch (prop_id) { + case PROP_PROFILE: + gst_encode_bin_set_profile (ebin, + (GstEncodingProfile *) gst_value_get_mini_object (value)); + break; + case PROP_QUEUE_BUFFERS_MAX: + ebin->queue_buffers_max = g_value_get_uint (value); + break; + case PROP_QUEUE_BYTES_MAX: + ebin->queue_bytes_max = g_value_get_uint (value); + break; + case PROP_QUEUE_TIME_MAX: + ebin->queue_time_max = g_value_get_uint64 (value); + break; + case PROP_AUDIO_JITTER_TOLERANCE: + ebin->tolerance = g_value_get_uint64 (value); + break; + case PROP_AVOID_REENCODING: + ebin->avoid_reencoding = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_encode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstEncodeBin *ebin = (GstEncodeBin *) object; + + switch (prop_id) { + case PROP_PROFILE: + gst_value_set_mini_object (value, (GstMiniObject *) ebin->profile); + break; + case PROP_QUEUE_BUFFERS_MAX: + g_value_set_uint (value, ebin->queue_buffers_max); + break; + case PROP_QUEUE_BYTES_MAX: + g_value_set_uint (value, ebin->queue_bytes_max); + break; + case PROP_QUEUE_TIME_MAX: + g_value_set_uint64 (value, ebin->queue_time_max); + break; + case PROP_AUDIO_JITTER_TOLERANCE: + g_value_set_uint64 (value, ebin->tolerance); + break; + case PROP_AVOID_REENCODING: + g_value_set_boolean (value, ebin->avoid_reencoding); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static inline gboolean +are_raw_caps (const GstCaps * caps) +{ + GstCaps *raw = gst_static_caps_get (&default_raw_caps); + + if (gst_caps_can_intersect (caps, raw)) { + gst_caps_unref (raw); + return TRUE; + } + gst_caps_unref (raw); + return FALSE; +} + +/* Returns the number of time a given stream profile is currently used + * in encodebin */ +static inline guint +stream_profile_used_count (GstEncodeBin * ebin, GstEncodingProfile * sprof) +{ + guint nbprofused = 0; + GList *tmp; + + for (tmp = ebin->streams; tmp; tmp = tmp->next) { + StreamGroup *sgroup = (StreamGroup *) tmp->data; + + if (sgroup->profile == sprof) + nbprofused++; + } + + return nbprofused; +} + +static inline GstEncodingProfile * +next_unused_stream_profile (GstEncodeBin * ebin, GType ptype, GstCaps * caps) +{ + GST_DEBUG_OBJECT (ebin, "ptype:%s, caps:%" GST_PTR_FORMAT, + g_type_name (ptype), caps); + + if (G_UNLIKELY (ptype == G_TYPE_NONE && caps != NULL)) { + /* Identify the profile type based on raw caps */ + if (gst_caps_can_intersect (ebin->raw_video_caps, caps)) + ptype = GST_TYPE_ENCODING_VIDEO_PROFILE; + else if (gst_caps_can_intersect (ebin->raw_audio_caps, caps)) + ptype = GST_TYPE_ENCODING_AUDIO_PROFILE; + /* else if (gst_caps_can_intersect (ebin->raw_text_caps, caps)) */ + /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */ + GST_DEBUG_OBJECT (ebin, "Detected profile type as being %s", + g_type_name (ptype)); + } + + if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) { + const GList *tmp; + + for (tmp = + gst_encoding_container_profile_get_profiles + (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); tmp; + tmp = tmp->next) { + GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data; + + /* Pick an available Stream profile for which: + * * either it is of the compatibly raw type, + * * OR we can pass it through directly without encoding + */ + if (G_TYPE_FROM_INSTANCE (sprof) == ptype) { + guint presence = gst_encoding_profile_get_presence (sprof); + GST_DEBUG ("Found a stream profile with the same type"); + if ((presence == 0) + || (presence > stream_profile_used_count (ebin, sprof))) + return sprof; + } else if ((caps != NULL) && (ptype == G_TYPE_NONE)) { + GstCaps *outcaps; + gboolean res; + + outcaps = gst_encoding_profile_get_input_caps (sprof); + GST_DEBUG ("Unknown stream, seeing if it's compatible with %" + GST_PTR_FORMAT, outcaps); + res = gst_caps_can_intersect (outcaps, caps); + gst_caps_unref (outcaps); + + if (res) + return sprof; + } + } + } + + return NULL; +} + +static GstPad * +request_pad_for_stream (GstEncodeBin * encodebin, GType ptype, + const gchar * name, GstCaps * caps) +{ + StreamGroup *sgroup; + GstEncodingProfile *sprof; + + GST_DEBUG_OBJECT (encodebin, "name:%s caps:%" GST_PTR_FORMAT, name, caps); + + /* Figure out if we have a unused GstEncodingProfile we can use for + * these caps */ + sprof = next_unused_stream_profile (encodebin, ptype, caps); + + if (G_UNLIKELY (sprof == NULL)) + goto no_stream_profile; + + sgroup = _create_stream_group (encodebin, sprof, name, caps); + if (G_UNLIKELY (sgroup == NULL)) + goto no_stream_group; + + return sgroup->ghostpad; + +no_stream_profile: + { + GST_WARNING_OBJECT (encodebin, "Couldn't find a compatible stream profile"); + return NULL; + } + +no_stream_group: + { + GST_WARNING_OBJECT (encodebin, "Couldn't create a StreamGroup"); + return NULL; + } +} + +static GstPad * +gst_encode_bin_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name, const GstCaps * caps) +{ + GstEncodeBin *ebin = (GstEncodeBin *) element; + GstPad *res = NULL; + + GST_DEBUG_OBJECT (element, "templ:%s, name:%s", templ->name_template, name); + + /* Identify the stream group */ + if (caps != NULL) { + res = request_pad_for_stream (ebin, G_TYPE_NONE, name, (GstCaps *) caps); + } + + if (res == NULL) { + GType ptype = G_TYPE_NONE; + + if (!strcmp (templ->name_template, "video_%d")) + ptype = GST_TYPE_ENCODING_VIDEO_PROFILE; + else if (!strcmp (templ->name_template, "audio_%d")) + ptype = GST_TYPE_ENCODING_AUDIO_PROFILE; + /* else if (!strcmp (templ->name_template, "text_%d")) */ + /* ptype = GST_TYPE_ENCODING_TEXT_PROFILE; */ + + /* FIXME : Check uniqueness of pad */ + /* FIXME : Check that the requested number is the last one, and if not, + * update the last_pad_id variable so that we don't create a pad with + * the same name/number in the future */ + + res = request_pad_for_stream (ebin, ptype, name, NULL); + } + + return res; +} + +static GstPad * +gst_encode_bin_request_pad_signal (GstEncodeBin * encodebin, GstCaps * caps) +{ + GstPad *pad = request_pad_for_stream (encodebin, G_TYPE_NONE, NULL, caps); + + return pad ? GST_PAD_CAST (gst_object_ref (pad)) : NULL; +} + +static inline StreamGroup * +find_stream_group_from_pad (GstEncodeBin * ebin, GstPad * pad) +{ + GList *tmp; + + for (tmp = ebin->streams; tmp; tmp = tmp->next) { + StreamGroup *sgroup = (StreamGroup *) tmp->data; + if (G_UNLIKELY (sgroup->ghostpad == pad)) + return sgroup; + } + + return NULL; +} + +static void +gst_encode_bin_release_pad (GstElement * element, GstPad * pad) +{ + GstEncodeBin *ebin = (GstEncodeBin *) element; + StreamGroup *sgroup; + + /* Find the associated StreamGroup */ + + sgroup = find_stream_group_from_pad (ebin, pad); + if (G_UNLIKELY (sgroup == NULL)) + goto no_stream_group; + + /* Release objects/data associated with the StreamGroup */ + stream_group_remove (ebin, sgroup); + + return; + +no_stream_group: + { + GST_WARNING_OBJECT (ebin, "Couldn't find corresponding StreamGroup"); + return; + } +} + +/* Create a parser for the given stream profile */ +static inline GstElement * +_get_parser (GstEncodeBin * ebin, GstEncodingProfile * sprof) +{ + GList *parsers1, *parsers, *tmp; + GstElement *parser = NULL; + GstElementFactory *parserfact = NULL; + const GstCaps *format; + + format = gst_encoding_profile_get_format (sprof); + + GST_DEBUG ("Getting list of parsers for format %" GST_PTR_FORMAT, format); + + /* FIXME : requesting twice the parsers twice is a bit ugly, we should + * have a method to request on more than one condition */ + parsers1 = + gst_element_factory_list_filter (ebin->parsers, format, + GST_PAD_SRC, FALSE); + parsers = + gst_element_factory_list_filter (parsers1, format, GST_PAD_SINK, FALSE); + gst_plugin_feature_list_free (parsers1); + + if (G_UNLIKELY (parsers == NULL)) { + GST_DEBUG ("Couldn't find any compatible parsers"); + return NULL; + } + + for (tmp = parsers; tmp; tmp = tmp->next) { + /* FIXME : We're only picking the first one so far */ + /* FIXME : signal the user if he wants this */ + parserfact = (GstElementFactory *) tmp->data; + break; + } + + if (parserfact) + parser = gst_element_factory_create (parserfact, NULL); + + gst_plugin_feature_list_free (parsers); + + return parser; +} + +static GstElement * +_create_element_and_set_preset (GstElementFactory * factory, + const gchar * preset, const gchar * name) +{ + GstElement *res = NULL; + + GST_DEBUG ("Creating element from factory %s", + GST_PLUGIN_FEATURE_NAME (factory)); + res = gst_element_factory_create (factory, name); + if (preset && GST_IS_PRESET (res) && + !gst_preset_load_preset (GST_PRESET (res), preset)) { + GST_WARNING ("Couldn't set preset [%s] on element [%s]", + preset, GST_PLUGIN_FEATURE_NAME (factory)); + gst_object_unref (res); + res = NULL; + } + + return res; +} + +/* Create the encoder for the given stream profile */ +static inline GstElement * +_get_encoder (GstEncodeBin * ebin, GstEncodingProfile * sprof) +{ + GList *encoders, *tmp; + GstElement *encoder = NULL; + GstElementFactory *encoderfact = NULL; + const GstCaps *format; + const gchar *preset; + + format = gst_encoding_profile_get_format (sprof); + preset = gst_encoding_profile_get_preset (sprof); + + GST_DEBUG ("Getting list of encoders for format %" GST_PTR_FORMAT, format); + + /* If stream caps are raw, return identity */ + if (G_UNLIKELY (are_raw_caps (format))) { + GST_DEBUG ("Stream format is raw, returning identity as the encoder"); + encoder = gst_element_factory_make ("identity", NULL); + goto beach; + } + + encoders = + gst_element_factory_list_filter (ebin->encoders, format, + GST_PAD_SRC, FALSE); + + if (G_UNLIKELY (encoders == NULL)) { + GST_DEBUG ("Couldn't find any compatible encoders"); + goto beach; + } + + for (tmp = encoders; tmp; tmp = tmp->next) { + encoderfact = (GstElementFactory *) tmp->data; + if ((encoder = _create_element_and_set_preset (encoderfact, preset, NULL))) + break; + } + + gst_plugin_feature_list_free (encoders); + +beach: + return encoder; +} + +static GstPad * +local_element_request_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name) +{ + GstPad *newpad = NULL; + GstElementClass *oclass; + + oclass = GST_ELEMENT_GET_CLASS (element); + + if (oclass->request_new_pad) + newpad = (oclass->request_new_pad) (element, templ, name); + + if (newpad) + gst_object_ref (newpad); + + return newpad; +} + +static GstPad * +gst_element_get_pad_from_template (GstElement * element, GstPadTemplate * templ) +{ + GstPad *ret = NULL; + GstPadPresence presence; + + /* If this function is ever exported, we need check the validity of `element' + * and `templ', and to make sure the template actually belongs to the + * element. */ + + presence = GST_PAD_TEMPLATE_PRESENCE (templ); + + switch (presence) { + case GST_PAD_ALWAYS: + case GST_PAD_SOMETIMES: + ret = gst_element_get_static_pad (element, templ->name_template); + if (!ret && presence == GST_PAD_ALWAYS) + g_warning + ("Element %s has an ALWAYS template %s, but no pad of the same name", + GST_OBJECT_NAME (element), templ->name_template); + break; + + case GST_PAD_REQUEST: + ret = gst_element_request_pad (element, templ, NULL, NULL); + break; + } + + return ret; +} + +/* FIXME : Improve algorithm for finding compatible muxer sink pad */ +static inline GstPad * +get_compatible_muxer_sink_pad (GstEncodeBin * ebin, GstElement * encoder, + const GstCaps * sinkcaps) +{ + GstPad *sinkpad; + GstPadTemplate *srctempl = NULL; + GstPadTemplate *sinktempl; + + if (encoder) { + GstPad *srcpad; + srcpad = gst_element_get_static_pad (encoder, "src"); + + srctempl = gst_pad_get_pad_template (srcpad); + + GST_DEBUG_OBJECT (ebin, + "Attempting to find pad from muxer %s compatible with %s:%s", + GST_ELEMENT_NAME (ebin->muxer), GST_DEBUG_PAD_NAME (srcpad)); + + gst_object_unref (srcpad); + sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl); + } else { + srctempl = + gst_pad_template_new ("whatever", GST_PAD_SRC, GST_PAD_ALWAYS, + gst_caps_copy (sinkcaps)); + g_assert (srctempl != NULL); + sinktempl = gst_element_get_compatible_pad_template (ebin->muxer, srctempl); + g_object_unref (srctempl); + } + + if (G_UNLIKELY (sinktempl == NULL)) + goto no_template; + + sinkpad = gst_element_get_pad_from_template (ebin->muxer, sinktempl); + + return sinkpad; + +no_template: + { + GST_WARNING_OBJECT (ebin, "No compatible pad available on muxer"); + return NULL; + } +} + +/* FIXME : Add handling of streams that don't need encoding */ +/* FIXME : Add handling of streams that don't require conversion elements */ +/* + * Create the elements, StreamGroup, add the sink pad, link it to the muxer + * + * sinkpadname: If non-NULL, that name will be assigned to the sink ghost pad + * sinkcaps: If non-NULL will be used to figure out how to setup the group */ +static StreamGroup * +_create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof, + const gchar * sinkpadname, GstCaps * sinkcaps) +{ + StreamGroup *sgroup = NULL; + GstPad *sinkpad, *srcpad, *muxerpad = NULL; + /* Element we will link to the encoder */ + GstElement *last = NULL; + GList *tmp, *tosync = NULL; + const GstCaps *format; + const GstCaps *restriction; + + format = gst_encoding_profile_get_format (sprof); + restriction = gst_encoding_profile_get_restriction (sprof); + + GST_DEBUG ("Creating group. format %" GST_PTR_FORMAT ", for caps %" + GST_PTR_FORMAT, format, sinkcaps); + GST_DEBUG ("avoid_reencoding:%d", ebin->avoid_reencoding); + + sgroup = g_slice_new0 (StreamGroup); + sgroup->ebin = ebin; + sgroup->profile = sprof; + + /* NOTE for people reading this code: + * + * We construct the group starting by the furthest downstream element + * and making our way up adding/syncing/linking as we go. + * + * There are two parallel paths: + * * One for raw data which goes through converters and encoders + * * One for already encoded data + */ + + /* Exception to the rule above: + * We check if we have an available encoder so we can abort early */ + /* FIXME : What if we only want to do passthrough ??? */ + GST_LOG ("Checking for encoder availability"); + sgroup->encoder = _get_encoder (ebin, sprof); + if (G_UNLIKELY (sgroup->encoder == NULL)) + goto no_encoder; + + /* Muxer. + * If we are handling a container profile, figure out if the muxer has a + * sinkpad compatible with the selected profile */ + if (ebin->muxer) { + muxerpad = get_compatible_muxer_sink_pad (ebin, NULL, format); + if (G_UNLIKELY (muxerpad == NULL)) + goto no_muxer_pad; + } + + /* Output Queue. + * We only use a 1buffer long queue here, the actual queueing will be done + * in the intput queue */ + last = sgroup->outqueue = gst_element_factory_make ("queue", NULL); + g_object_set (sgroup->outqueue, "max-size-buffers", (guint32) 1, + "max-size-bytes", (guint32) 0, "max-size-time", (guint64) 0, NULL); + + gst_bin_add (GST_BIN (ebin), sgroup->outqueue); + tosync = g_list_append (tosync, sgroup->outqueue); + srcpad = gst_element_get_static_pad (sgroup->outqueue, "src"); + if (muxerpad) { + if (G_UNLIKELY (fast_pad_link (srcpad, muxerpad) != GST_PAD_LINK_OK)) { + goto muxer_link_failure; + } + gst_object_unref (muxerpad); + } else { + gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), srcpad); + } + gst_object_unref (srcpad); + + /* Output capsfilter + * This will receive the format caps from the streamprofile */ + GST_DEBUG ("Adding output capsfilter for %" GST_PTR_FORMAT, format); + sgroup->outfilter = gst_element_factory_make ("capsfilter", NULL); + g_object_set (sgroup->outfilter, "caps", format, NULL); + + gst_bin_add (GST_BIN (ebin), sgroup->outfilter); + tosync = g_list_append (tosync, sgroup->outfilter); + if (G_UNLIKELY (!fast_element_link (sgroup->outfilter, last))) + goto outfilter_link_failure; + last = sgroup->outfilter; + + + /* FIXME : + * + * The usage of parsers in encoding/muxing scenarios is + * just too undefined to just use as-is. + * + * Take the use-case where you want to re-mux a stream of type + * "my/media". You create a StreamEncodingProfile with that type + * as the target (as-is). And you use decodebin2/uridecodebin + * upstream. + * + * * demuxer exposes "my/media" + * * a parser is available for "my/media" which has a source pad + * caps of "my/media,parsed=True" + * * decodebin2/uridecodebin exposes a new pad with the parsed caps + * * You request a new stream from encodebin, which will match the + * streamprofile and creates a group (i.e. going through this method) + * There is a matching parser (the same used in the decoder) whose + * source pad caps intersects with the stream profile caps, you + * therefore use it... + * * ... but that parser has a "my/media,parsed=False" sink pad caps + * * ... and you can't link your decodebin pad to encodebin. + * + * In the end, it comes down to parsers only taking into account the + * decoding use-cases. + * + * One way to solve that might be to : + * * Make parsers sink pad caps be "framed={False,True}" and the + * source pad caps be "framed=True" + * * Modify decodebin2 accordingly to avoid looping and chaining + * an infinite number of parsers + * + * Another way would be to have "well-known" caps properties to specify + * whether a stream has been parsed or not. + * * currently we fail. aacparse uses 'framed' and mp3parse uses 'parsed' + */ + /* FIXME : Re-enable once parser situation is un-$#*@(%$#ed */ +#if 0 + /* Parser. + * FIXME : identify smart parsers (used for re-encoding) */ + sgroup->parser = _get_parser (ebin, sprof); + + if (sgroup->parser != NULL) { + GST_DEBUG ("Got a parser %s", GST_ELEMENT_NAME (sgroup->parser)); + gst_bin_add (GST_BIN (ebin), sgroup->parser); + tosync = g_list_append (tosync, sgroup->parser); + if (G_UNLIKELY (!gst_element_link (sgroup->parser, last))) + goto parser_link_failure; + last = sgroup->parser; + } +#endif + + /* Stream combiner */ + sgroup->combiner = g_object_new (GST_TYPE_STREAM_COMBINER, NULL); + + gst_bin_add (GST_BIN (ebin), sgroup->combiner); + tosync = g_list_append (tosync, sgroup->combiner); + if (G_UNLIKELY (!fast_element_link (sgroup->combiner, last))) + goto combiner_link_failure; + + + /* Stream splitter */ + sgroup->splitter = g_object_new (GST_TYPE_STREAM_SPLITTER, NULL); + + gst_bin_add (GST_BIN (ebin), sgroup->splitter); + tosync = g_list_append (tosync, sgroup->splitter); + + /* Input queue + * FIXME : figure out what max-size to use for the input queue */ + sgroup->inqueue = gst_element_factory_make ("queue", NULL); + g_object_set (sgroup->inqueue, "max-size-buffers", + (guint32) ebin->queue_buffers_max, "max-size-bytes", + (guint32) ebin->queue_bytes_max, "max-size-time", + (guint64) ebin->queue_time_max, NULL); + + gst_bin_add (GST_BIN (ebin), sgroup->inqueue); + tosync = g_list_append (tosync, sgroup->inqueue); + if (G_UNLIKELY (!fast_element_link (sgroup->inqueue, sgroup->splitter))) + goto splitter_link_failure; + + /* Expose input queue sink pad as ghostpad */ + sinkpad = gst_element_get_static_pad (sgroup->inqueue, "sink"); + if (sinkpadname == NULL) { + gchar *pname = + g_strdup_printf ("%s_%d", gst_encoding_profile_get_type_nick (sprof), + ebin->last_pad_id++); + GST_DEBUG ("Adding ghost pad %s", pname); + sgroup->ghostpad = gst_ghost_pad_new (pname, sinkpad); + g_free (pname); + } else + sgroup->ghostpad = gst_ghost_pad_new (sinkpadname, sinkpad); + gst_object_unref (sinkpad); + + + /* Path 1 : Already-encoded data */ + sinkpad = + local_element_request_pad (sgroup->combiner, NULL, "passthroughsink"); + if (G_UNLIKELY (sinkpad == NULL)) + goto no_combiner_sinkpad; + + if (ebin->avoid_reencoding) { + GstCaps *tmpcaps; + + GST_DEBUG ("Asked to use Smart Encoder"); + sgroup->smartencoder = g_object_new (GST_TYPE_SMART_ENCODER, NULL); + + /* Check if stream format is compatible */ + srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src"); + tmpcaps = gst_pad_get_caps (srcpad); + if (!gst_caps_can_intersect (tmpcaps, format)) { + GST_DEBUG ("We don't have a smart encoder for the stream format"); + gst_object_unref (sgroup->smartencoder); + sgroup->smartencoder = NULL; + } else { + gst_bin_add ((GstBin *) ebin, sgroup->smartencoder); + fast_pad_link (srcpad, sinkpad); + tosync = g_list_append (tosync, sgroup->smartencoder); + sinkpad = gst_element_get_static_pad (sgroup->smartencoder, "sink"); + } + gst_caps_unref (tmpcaps); + g_object_unref (srcpad); + } + + srcpad = local_element_request_pad (sgroup->splitter, NULL, "passthroughsrc"); + if (G_UNLIKELY (srcpad == NULL)) + goto no_splitter_srcpad; + + /* Go straight to splitter */ + if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)) + goto passthrough_link_failure; + g_object_unref (sinkpad); + g_object_unref (srcpad); + + + /* Path 2 : Conversion / Encoding */ + + /* 1. Create the encoder */ + GST_LOG ("Adding encoder"); + last = sgroup->encoder; + gst_bin_add ((GstBin *) ebin, sgroup->encoder); + tosync = g_list_append (tosync, sgroup->encoder); + + sinkpad = local_element_request_pad (sgroup->combiner, NULL, "encodingsink"); + if (G_UNLIKELY (sinkpad == NULL)) + goto no_combiner_sinkpad; + srcpad = gst_element_get_static_pad (sgroup->encoder, "src"); + if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)) + goto encoder_link_failure; + g_object_unref (sinkpad); + g_object_unref (srcpad); + + + /* 3. Create the conversion/restriction elements */ + /* 3.1. capsfilter */ + if (restriction && !gst_caps_is_any (restriction)) { + GST_LOG ("Adding capsfilter for restriction caps : %" GST_PTR_FORMAT, + restriction); + + last = sgroup->capsfilter = gst_element_factory_make ("capsfilter", NULL); + g_object_set (sgroup->capsfilter, "caps", restriction, NULL); + gst_bin_add ((GstBin *) ebin, sgroup->capsfilter); + tosync = g_list_append (tosync, sgroup->capsfilter); + fast_element_link (sgroup->capsfilter, sgroup->encoder); + } + + /* 3.2. restriction elements */ + /* FIXME : Once we have properties for specific converters, use those */ + if (GST_IS_ENCODING_VIDEO_PROFILE (sprof)) { + GstElement *cspace, *scale, *vrate, *cspace2; + + GST_LOG ("Adding conversion elements for video stream"); + + cspace = gst_element_factory_make ("ffmpegcolorspace", NULL); + scale = gst_element_factory_make ("videoscale", NULL); + /* 4-tap scaling and black borders */ + g_object_set (scale, "method", 2, "add-borders", TRUE, NULL); + cspace2 = gst_element_factory_make ("ffmpegcolorspace", NULL); + + gst_bin_add_many ((GstBin *) ebin, cspace, scale, cspace2, NULL); + tosync = g_list_append (tosync, cspace); + tosync = g_list_append (tosync, scale); + tosync = g_list_append (tosync, cspace2); + + sgroup->converters = g_list_prepend (sgroup->converters, cspace); + sgroup->converters = g_list_prepend (sgroup->converters, scale); + sgroup->converters = g_list_prepend (sgroup->converters, cspace2); + + if (!fast_element_link (cspace, scale) || + !fast_element_link (scale, cspace2)) + goto converter_link_failure; + + if (!gst_encoding_video_profile_get_variableframerate + (GST_ENCODING_VIDEO_PROFILE (sprof))) { + vrate = gst_element_factory_make ("videorate", NULL); + gst_bin_add ((GstBin *) ebin, vrate); + tosync = g_list_prepend (tosync, vrate); + sgroup->converters = g_list_prepend (sgroup->converters, vrate); + if (!fast_element_link (cspace2, vrate) || + !fast_element_link (vrate, last)) + goto converter_link_failure; + } else if (!fast_element_link (cspace2, last)) + goto converter_link_failure; + + last = cspace; + + } else if (GST_IS_ENCODING_AUDIO_PROFILE (sprof)) { + GstElement *aconv, *ares, *arate, *aconv2; + + GST_LOG ("Adding conversion elements for audio stream"); + + arate = gst_element_factory_make ("audiorate", NULL); + g_object_set (arate, "tolerance", (guint64) ebin->tolerance, NULL); + aconv = gst_element_factory_make ("audioconvert", NULL); + aconv2 = gst_element_factory_make ("audioconvert", NULL); + ares = gst_element_factory_make ("audioresample", NULL); + + gst_bin_add_many ((GstBin *) ebin, arate, aconv, ares, aconv2, NULL); + tosync = g_list_append (tosync, arate); + tosync = g_list_append (tosync, aconv); + tosync = g_list_append (tosync, ares); + tosync = g_list_append (tosync, aconv2); + if (!fast_element_link (arate, aconv) || + !fast_element_link (aconv, ares) || + !fast_element_link (ares, aconv2) || !fast_element_link (aconv2, last)) + goto converter_link_failure; + + sgroup->converters = g_list_prepend (sgroup->converters, arate); + sgroup->converters = g_list_prepend (sgroup->converters, aconv); + sgroup->converters = g_list_prepend (sgroup->converters, ares); + sgroup->converters = g_list_prepend (sgroup->converters, aconv2); + + last = arate; + } + + /* Link to stream splitter */ + sinkpad = gst_element_get_static_pad (last, "sink"); + srcpad = local_element_request_pad (sgroup->splitter, NULL, "encodingsrc"); + if (G_UNLIKELY (srcpad == NULL)) + goto no_splitter_srcpad; + if (G_UNLIKELY (fast_pad_link (srcpad, sinkpad) != GST_PAD_LINK_OK)) + goto splitter_encoding_failure; + g_object_unref (sinkpad); + g_object_unref (srcpad); + + /* End of Stream 2 setup */ + + /* Sync all elements to parent state */ + for (tmp = tosync; tmp; tmp = tmp->next) + gst_element_sync_state_with_parent ((GstElement *) tmp->data); + g_list_free (tosync); + + /* Add ghostpad */ + GST_DEBUG ("Adding ghostpad %s:%s", GST_DEBUG_PAD_NAME (sgroup->ghostpad)); + gst_pad_set_active (sgroup->ghostpad, TRUE); + gst_element_add_pad ((GstElement *) ebin, sgroup->ghostpad); + + /* Add StreamGroup to our list of streams */ + + GST_DEBUG + ("Done creating elements, adding StreamGroup to our controlled stream list"); + + ebin->streams = g_list_prepend (ebin->streams, sgroup); + + return sgroup; + +splitter_encoding_failure: + GST_ERROR_OBJECT (ebin, "Error linking splitter to encoding stream"); + goto cleanup; + +no_encoder: + GST_ERROR_OBJECT (ebin, "Couldn't create encoder for format %" GST_PTR_FORMAT, + format); + /* missing plugin support */ + gst_element_post_message (GST_ELEMENT_CAST (ebin), + gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), format)); + GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL), + ("Couldn't create encoder for format %" GST_PTR_FORMAT, format)); + goto cleanup; + +no_muxer_pad: + GST_ERROR_OBJECT (ebin, + "Couldn't find a compatible muxer pad to link encoder to"); + goto cleanup; + +encoder_link_failure: + GST_ERROR_OBJECT (ebin, "Failed to link the encoder"); + goto cleanup; + +muxer_link_failure: + GST_ERROR_OBJECT (ebin, "Couldn't link encoder to muxer"); + goto cleanup; + +outfilter_link_failure: + GST_ERROR_OBJECT (ebin, "Couldn't link output filter to output queue"); + goto cleanup; + +passthrough_link_failure: + GST_ERROR_OBJECT (ebin, "Failed linking splitter in passthrough mode"); + goto cleanup; + +no_splitter_srcpad: + GST_ERROR_OBJECT (ebin, "Couldn't get a source pad from the splitter"); + goto cleanup; + +no_combiner_sinkpad: + GST_ERROR_OBJECT (ebin, "Couldn't get a sink pad from the combiner"); + goto cleanup; + +splitter_link_failure: + GST_ERROR_OBJECT (ebin, "Failure linking to the splitter"); + goto cleanup; + +combiner_link_failure: + GST_ERROR_OBJECT (ebin, "Failure linking to the combiner"); + goto cleanup; + +#if 0 +parser_link_failure: + GST_ERROR_OBJECT (ebin, "Failure linking the parser"); + goto cleanup; +#endif + +converter_link_failure: + GST_ERROR_OBJECT (ebin, "Failure linking the video converters"); + goto cleanup; + +cleanup: + /* FIXME : Actually properly cleanup everything */ + g_slice_free (StreamGroup, sgroup); + return NULL; +} + +static gboolean +_factory_can_sink_caps (GstElementFactory * factory, const GstCaps * caps) +{ + GList *templates = factory->staticpadtemplates; + + while (templates) { + GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data; + + if (template->direction == GST_PAD_SINK) { + GstCaps *tmp = gst_static_caps_get (&template->static_caps); + + if (gst_caps_can_intersect (tmp, caps)) { + gst_caps_unref (tmp); + return TRUE; + } + gst_caps_unref (tmp); + } + templates = g_list_next (templates); + } + + return FALSE; +} + +static inline GstElement * +_get_muxer (GstEncodeBin * ebin) +{ + GList *muxers, *tmpmux; + GstElement *muxer = NULL; + GstElementFactory *muxerfact = NULL; + const GList *tmp; + const GstCaps *format; + const gchar *preset; + + format = gst_encoding_profile_get_format (ebin->profile); + preset = gst_encoding_profile_get_preset (ebin->profile); + + GST_DEBUG ("Getting list of muxers for format %" GST_PTR_FORMAT, format); + + muxers = + gst_element_factory_list_filter (ebin->muxers, format, GST_PAD_SRC, TRUE); + + if (muxers == NULL) + goto beach; + + /* FIXME : signal the user if he wants this */ + for (tmpmux = muxers; tmpmux; tmpmux = tmpmux->next) { + gboolean cansinkstreams = TRUE; + const GList *profiles = + gst_encoding_container_profile_get_profiles + (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); + + muxerfact = (GstElementFactory *) tmpmux->data; + + GST_DEBUG ("Trying muxer %s", GST_PLUGIN_FEATURE_NAME (muxerfact)); + + /* See if the muxer can sink all of our stream profile caps */ + for (tmp = profiles; tmp; tmp = tmp->next) { + GstEncodingProfile *sprof = (GstEncodingProfile *) tmp->data; + + if (!_factory_can_sink_caps (muxerfact, + gst_encoding_profile_get_format (sprof))) { + GST_DEBUG ("Skipping muxer because it can't sink caps %" GST_PTR_FORMAT, + gst_encoding_profile_get_format (sprof)); + cansinkstreams = FALSE; + break; + } + } + + /* Only use a muxer than can use all streams and than can accept the + * preset (which may be present or not) */ + if (cansinkstreams && (muxer = + _create_element_and_set_preset (muxerfact, preset, "muxer"))) + break; + } + + gst_plugin_feature_list_free (muxers); + +beach: + return muxer; +} + +static gboolean +create_elements_and_pads (GstEncodeBin * ebin) +{ + gboolean ret = TRUE; + GstElement *muxer = NULL; + GstPad *muxerpad; + const GList *tmp, *profiles; + GstEncodingProfile *sprof; + + GST_DEBUG ("Current profile : %s", + gst_encoding_profile_get_name (ebin->profile)); + + if (GST_IS_ENCODING_CONTAINER_PROFILE (ebin->profile)) { + /* 1. Get the compatible muxer */ + muxer = _get_muxer (ebin); + if (G_UNLIKELY (muxer == NULL)) + goto no_muxer; + + /* Record the muxer */ + ebin->muxer = muxer; + gst_bin_add ((GstBin *) ebin, muxer); + + /* 2. Ghost the muxer source pad */ + + /* FIXME : We should figure out if it's a static/request/dyamic pad, + * but for the time being let's assume it's a static pad :) */ + muxerpad = gst_element_get_static_pad (muxer, "src"); + if (G_UNLIKELY (muxerpad == NULL)) + goto no_muxer_pad; + + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), muxerpad)) + goto no_muxer_ghost_pad; + + gst_object_unref (muxerpad); + /* 3. Activate fixed presence streams */ + profiles = + gst_encoding_container_profile_get_profiles + (GST_ENCODING_CONTAINER_PROFILE (ebin->profile)); + for (tmp = profiles; tmp; tmp = tmp->next) { + sprof = (GstEncodingProfile *) tmp->data; + + GST_DEBUG ("Trying stream profile with presence %d", + gst_encoding_profile_get_presence (sprof)); + + if (gst_encoding_profile_get_presence (sprof) != 0) { + if (G_UNLIKELY (_create_stream_group (ebin, sprof, NULL, NULL) == NULL)) + goto stream_error; + } + } + } else { + if (G_UNLIKELY (_create_stream_group (ebin, ebin->profile, NULL, + NULL) == NULL)) + goto stream_error; + } + + return ret; + +no_muxer: + { + GST_WARNING ("No available muxer for %" GST_PTR_FORMAT, + gst_encoding_profile_get_format (ebin->profile)); + /* missing plugin support */ + gst_element_post_message (GST_ELEMENT_CAST (ebin), + gst_missing_encoder_message_new (GST_ELEMENT_CAST (ebin), + gst_encoding_profile_get_format (ebin->profile))); + GST_ELEMENT_ERROR (ebin, CORE, MISSING_PLUGIN, (NULL), + ("No available muxer for format %" GST_PTR_FORMAT, + gst_encoding_profile_get_format (ebin->profile))); + return FALSE; + } + +no_muxer_pad: + { + GST_WARNING ("Can't get source pad from muxer (%s)", + GST_ELEMENT_NAME (muxer)); + gst_bin_remove (GST_BIN (ebin), muxer); + return FALSE; + } + +no_muxer_ghost_pad: + { + GST_WARNING ("Couldn't set %s:%s as source ghostpad target", + GST_DEBUG_PAD_NAME (muxerpad)); + gst_bin_remove (GST_BIN (ebin), muxer); + gst_object_unref (muxerpad); + return FALSE; + } + +stream_error: + { + GST_WARNING ("Could not create Streams"); + if (muxer) + gst_bin_remove (GST_BIN (ebin), muxer); + ebin->muxer = NULL; + return FALSE; + } +} + +static void +release_pads (GstPad * pad, GstElement * elt) +{ + GstPad *peer = NULL; + + GST_DEBUG_OBJECT (elt, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + /* Unlink from its peer pad */ + if ((peer = gst_pad_get_peer (pad))) { + if (GST_PAD_DIRECTION (peer) == GST_PAD_SRC) + gst_pad_unlink (peer, pad); + else + gst_pad_unlink (pad, peer); + gst_object_unref (peer); + } + + /* Release it from the object */ + gst_element_release_request_pad (elt, pad); + + /* And remove the reference added by the iterator */ + gst_object_unref (pad); +} + +static void inline +stream_group_free (GstEncodeBin * ebin, StreamGroup * sgroup) +{ + GList *tmp; + GstPad *tmppad; + GstPad *pad; + + GST_DEBUG_OBJECT (ebin, "Freeing StreamGroup %p", sgroup); + + if (ebin->muxer) { + /* outqueue - Muxer */ + tmppad = gst_element_get_static_pad (sgroup->outqueue, "src"); + pad = gst_pad_get_peer (tmppad); + + /* Remove muxer request sink pad */ + gst_pad_unlink (tmppad, pad); + gst_element_release_request_pad (ebin->muxer, pad); + gst_object_unref (tmppad); + gst_object_unref (pad); + } + if (sgroup->outqueue) + gst_element_set_state (sgroup->outqueue, GST_STATE_NULL); + + /* Capsfilter - outqueue */ + gst_element_set_state (sgroup->outfilter, GST_STATE_NULL); + gst_element_unlink (sgroup->outfilter, sgroup->outqueue); + gst_element_set_state (sgroup->outqueue, GST_STATE_NULL); + gst_bin_remove (GST_BIN (ebin), sgroup->outqueue); + + /* streamcombiner - parser - capsfilter */ + if (sgroup->parser) { + gst_element_set_state (sgroup->parser, GST_STATE_NULL); + gst_element_unlink (sgroup->parser, sgroup->outfilter); + gst_element_unlink (sgroup->combiner, sgroup->parser); + gst_bin_remove ((GstBin *) ebin, sgroup->parser); + } + + /* Sink Ghostpad */ + if (sgroup->ghostpad) + gst_element_remove_pad (GST_ELEMENT_CAST (ebin), sgroup->ghostpad); + + if (sgroup->inqueue) + gst_element_set_state (sgroup->inqueue, GST_STATE_NULL); + + if (sgroup->encoder) + gst_element_set_state (sgroup->encoder, GST_STATE_NULL); + if (sgroup->outfilter) + gst_element_set_state (sgroup->outfilter, GST_STATE_NULL); + if (sgroup->smartencoder) + gst_element_set_state (sgroup->smartencoder, GST_STATE_NULL); + + if (sgroup->capsfilter) { + gst_element_set_state (sgroup->capsfilter, GST_STATE_NULL); + gst_element_unlink (sgroup->capsfilter, sgroup->encoder); + gst_bin_remove ((GstBin *) ebin, sgroup->capsfilter); + } + + for (tmp = sgroup->converters; tmp; tmp = tmp->next) { + GstElement *elt = (GstElement *) tmp->data; + + gst_element_set_state (elt, GST_STATE_NULL); + gst_bin_remove ((GstBin *) ebin, elt); + } + if (sgroup->converters) + g_list_free (sgroup->converters); + + if (sgroup->combiner) { + GstIterator *it = gst_element_iterate_sink_pads (sgroup->combiner); + GstIteratorResult itret = GST_ITERATOR_OK; + + while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) { + itret = gst_iterator_foreach (it, (GFunc) release_pads, sgroup->combiner); + gst_iterator_resync (it); + } + gst_iterator_free (it); + gst_element_set_state (sgroup->combiner, GST_STATE_NULL); + gst_bin_remove ((GstBin *) ebin, sgroup->combiner); + } + + if (sgroup->splitter) { + GstIterator *it = gst_element_iterate_src_pads (sgroup->splitter); + GstIteratorResult itret = GST_ITERATOR_OK; + while (itret == GST_ITERATOR_OK || itret == GST_ITERATOR_RESYNC) { + itret = gst_iterator_foreach (it, (GFunc) release_pads, sgroup->splitter); + gst_iterator_resync (it); + } + gst_iterator_free (it); + + gst_element_set_state (sgroup->splitter, GST_STATE_NULL); + gst_bin_remove ((GstBin *) ebin, sgroup->splitter); + } + + if (sgroup->inqueue) + gst_bin_remove ((GstBin *) ebin, sgroup->inqueue); + + if (sgroup->encoder) + gst_bin_remove ((GstBin *) ebin, sgroup->encoder); + + if (sgroup->smartencoder) + gst_bin_remove ((GstBin *) ebin, sgroup->smartencoder); + + if (sgroup->outfilter) + gst_bin_remove ((GstBin *) ebin, sgroup->outfilter); + + g_slice_free (StreamGroup, sgroup); +} + +static void +stream_group_remove (GstEncodeBin * ebin, StreamGroup * sgroup) +{ + ebin->streams = g_list_remove (ebin->streams, sgroup); + + stream_group_free (ebin, sgroup); +} + +static void +gst_encode_bin_tear_down_profile (GstEncodeBin * ebin) +{ + if (G_UNLIKELY (ebin->profile == NULL)) + return; + + GST_DEBUG ("Tearing down profile %s", + gst_encoding_profile_get_name (ebin->profile)); + + while (ebin->streams) + stream_group_remove (ebin, (StreamGroup *) ebin->streams->data); + + /* Set ghostpad target to NULL */ + gst_ghost_pad_set_target (GST_GHOST_PAD (ebin->srcpad), NULL); + + /* Remove muxer if present */ + if (ebin->muxer) { + gst_element_set_state (ebin->muxer, GST_STATE_NULL); + gst_bin_remove (GST_BIN (ebin), ebin->muxer); + ebin->muxer = NULL; + } + + /* free/clear profile */ + gst_encoding_profile_unref (ebin->profile); + ebin->profile = NULL; +} + +static gboolean +gst_encode_bin_setup_profile (GstEncodeBin * ebin, GstEncodingProfile * profile) +{ + gboolean res; + + g_return_val_if_fail (ebin->profile == NULL, FALSE); + + GST_DEBUG ("Setting up profile %s (type:%s)", + gst_encoding_profile_get_name (profile), + gst_encoding_profile_get_type_nick (profile)); + + ebin->profile = profile; + gst_mini_object_ref ((GstMiniObject *) ebin->profile); + + /* Create elements */ + res = create_elements_and_pads (ebin); + if (res == FALSE) + gst_encode_bin_tear_down_profile (ebin); + + return res; +} + +static gboolean +gst_encode_bin_set_profile (GstEncodeBin * ebin, GstEncodingProfile * profile) +{ + g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), FALSE); + + GST_DEBUG_OBJECT (ebin, "profile : %s", + gst_encoding_profile_get_name (profile)); + + if (G_UNLIKELY (ebin->active)) { + GST_WARNING_OBJECT (ebin, "Element already active, can't change profile"); + return FALSE; + } + + /* If we're not active, we can deactivate the previous profile */ + if (ebin->profile) { + gst_encode_bin_tear_down_profile (ebin); + } + + return gst_encode_bin_setup_profile (ebin, profile); +} + +static inline gboolean +gst_encode_bin_activate (GstEncodeBin * ebin) +{ + ebin->active = ebin->profile != NULL; + return ebin->active; +} + +static void +gst_encode_bin_deactivate (GstEncodeBin * ebin) +{ + ebin->active = FALSE; +} + +static GstStateChangeReturn +gst_encode_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstEncodeBin *ebin = (GstEncodeBin *) element; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + if (!gst_encode_bin_activate (ebin)) { + ret = GST_STATE_CHANGE_FAILURE; + goto beach; + } + break; + default: + break; + } + + ret = + GST_ELEMENT_CLASS (gst_encode_bin_parent_class)->change_state (element, + transition); + if (ret == GST_STATE_CHANGE_FAILURE) + goto beach; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_encode_bin_deactivate (ebin); + break; + default: + break; + } + +beach: + return ret; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean res; + + GST_DEBUG_CATEGORY_INIT (gst_encode_bin_debug, "encodebin", 0, "encoder bin"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + + res = gst_element_register (plugin, "encodebin", GST_RANK_NONE, + GST_TYPE_ENCODE_BIN); + + return res; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "encoding", + "various encoding-related elements", plugin_init, VERSION, GST_LICENSE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.h b/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.h new file mode 100644 index 0000000..2d594b0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gstencodebin.h @@ -0,0 +1,39 @@ +/* GStreamer encoding bin + * Copyright (C) 2009 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_ENCODEBIN_H__ +#define __GST_ENCODEBIN_H__ + +#include +#include +#include "gstencode-marshal.h" + +#define GST_TYPE_ENCODE_BIN (gst_encode_bin_get_type()) +#define GST_ENCODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_ENCODE_BIN,GstEncodeBin)) +#define GST_ENCODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_ENCODE_BIN,GstEncodeBinClass)) +#define GST_IS_ENCODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_ENCODE_BIN)) +#define GST_IS_ENCODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_ENCODE_BIN)) + +typedef struct _GstEncodeBin GstEncodeBin; +typedef struct _GstEncodeBinClass GstEncodeBinClass; + +GType gst_encode_bin_get_type(void); + +#endif /* __GST_ENCODEBIN_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.c b/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.c new file mode 100644 index 0000000..ed0e42b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.c @@ -0,0 +1,701 @@ +/* GStreamer Smart Video Encoder element + * Copyright (C) <2010> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* TODO: + * * Implement get_caps/set_caps (store/forward caps) + * * Adjust template caps to the formats we can support + **/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gstsmartencoder.h" + +GST_DEBUG_CATEGORY_STATIC (smart_encoder_debug); +#define GST_CAT_DEFAULT smart_encoder_debug + +/* FIXME : Update this with new caps */ +/* WARNING : We can only allow formats with closed-GOP */ +#define ALLOWED_CAPS "video/x-h263;video/x-intel-h263;"\ + "video/mpeg,mpegversion=(int)1,systemstream=(boolean)false;"\ + "video/mpeg,mpegversion=(int)2,systemstream=(boolean)false;" + +static GstStaticPadTemplate src_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (ALLOWED_CAPS) + ); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (ALLOWED_CAPS) + ); + +static GQuark INTERNAL_ELEMENT; + +/* GstSmartEncoder signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0 + /* FILL ME */ +}; + +static void +_do_init (void) +{ + INTERNAL_ELEMENT = g_quark_from_string ("internal-element"); +}; + +G_DEFINE_TYPE_EXTENDED (GstSmartEncoder, gst_smart_encoder, GST_TYPE_ELEMENT, 0, + _do_init ()); + +static void gst_smart_encoder_dispose (GObject * object); + +static gboolean setup_recoder_pipeline (GstSmartEncoder * smart_encoder); + +static GstFlowReturn gst_smart_encoder_chain (GstPad * pad, GstBuffer * buf); +static gboolean smart_encoder_sink_event (GstPad * pad, GstEvent * event); +static GstCaps *smart_encoder_sink_getcaps (GstPad * pad); +static GstStateChangeReturn +gst_smart_encoder_change_state (GstElement * element, + GstStateChange transition); + +static void +gst_smart_encoder_class_init (GstSmartEncoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + + element_class = (GstElementClass *) klass; + gobject_class = G_OBJECT_CLASS (klass); + + gst_smart_encoder_parent_class = g_type_class_peek_parent (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_set_details_simple (element_class, "Smart Video Encoder", + "Codec/Recoder/Video", + "Re-encodes portions of Video that lay on segment boundaries", + "Edward Hervey "); + + gobject_class->dispose = (GObjectFinalizeFunc) (gst_smart_encoder_dispose); + element_class->change_state = gst_smart_encoder_change_state; + + GST_DEBUG_CATEGORY_INIT (smart_encoder_debug, "smartencoder", 0, + "Smart Encoder"); +} + +static void +smart_encoder_reset (GstSmartEncoder * smart_encoder) +{ + gst_segment_init (smart_encoder->segment, GST_FORMAT_UNDEFINED); + + if (smart_encoder->encoder) { + /* Clean up/remove elements */ + gst_element_set_state (smart_encoder->encoder, GST_STATE_NULL); + gst_element_set_state (smart_encoder->decoder, GST_STATE_NULL); + gst_element_set_bus (smart_encoder->encoder, NULL); + gst_element_set_bus (smart_encoder->decoder, NULL); + gst_pad_set_active (smart_encoder->internal_srcpad, FALSE); + gst_pad_set_active (smart_encoder->internal_sinkpad, FALSE); + gst_object_unref (smart_encoder->encoder); + gst_object_unref (smart_encoder->decoder); + gst_object_unref (smart_encoder->internal_srcpad); + gst_object_unref (smart_encoder->internal_sinkpad); + + smart_encoder->encoder = NULL; + smart_encoder->decoder = NULL; + smart_encoder->internal_sinkpad = NULL; + smart_encoder->internal_srcpad = NULL; + } + + if (smart_encoder->newsegment) { + gst_event_unref (smart_encoder->newsegment); + smart_encoder->newsegment = NULL; + } +} + + +static void +gst_smart_encoder_init (GstSmartEncoder * smart_encoder) +{ + smart_encoder->sinkpad = + gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_chain_function (smart_encoder->sinkpad, gst_smart_encoder_chain); + gst_pad_set_event_function (smart_encoder->sinkpad, smart_encoder_sink_event); + gst_pad_set_getcaps_function (smart_encoder->sinkpad, + smart_encoder_sink_getcaps); + gst_element_add_pad (GST_ELEMENT (smart_encoder), smart_encoder->sinkpad); + + smart_encoder->srcpad = + gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_use_fixed_caps (smart_encoder->srcpad); + gst_element_add_pad (GST_ELEMENT (smart_encoder), smart_encoder->srcpad); + + smart_encoder->segment = gst_segment_new (); + + smart_encoder_reset (smart_encoder); +} + +void +gst_smart_encoder_dispose (GObject * object) +{ + GstSmartEncoder *smart_encoder = (GstSmartEncoder *) object; + + if (smart_encoder->segment) + gst_segment_free (smart_encoder->segment); + smart_encoder->segment = NULL; + if (smart_encoder->available_caps) + gst_caps_unref (smart_encoder->available_caps); + smart_encoder->available_caps = NULL; + G_OBJECT_CLASS (gst_smart_encoder_parent_class)->dispose (object); +} + +static GstFlowReturn +gst_smart_encoder_reencode_gop (GstSmartEncoder * smart_encoder) +{ + GstFlowReturn res = GST_FLOW_OK; + GList *tmp; + + if (smart_encoder->encoder == NULL) { + if (!setup_recoder_pipeline (smart_encoder)) + return GST_FLOW_ERROR; + } + + /* Activate elements */ + /* Set elements to PAUSED */ + gst_element_set_state (smart_encoder->encoder, GST_STATE_PAUSED); + gst_element_set_state (smart_encoder->decoder, GST_STATE_PAUSED); + + GST_INFO ("Pushing Flush start/stop to clean decoder/encoder"); + gst_pad_push_event (smart_encoder->internal_srcpad, + gst_event_new_flush_start ()); + gst_pad_push_event (smart_encoder->internal_srcpad, + gst_event_new_flush_stop ()); + + /* push newsegment */ + GST_INFO ("Pushing newsegment %" GST_PTR_FORMAT, smart_encoder->newsegment); + gst_pad_push_event (smart_encoder->internal_srcpad, + gst_event_ref (smart_encoder->newsegment)); + + /* Push buffers through our pads */ + GST_DEBUG ("Pushing pending buffers"); + + for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) { + GstBuffer *buf = (GstBuffer *) tmp->data; + + res = gst_pad_push (smart_encoder->internal_srcpad, buf); + if (G_UNLIKELY (res != GST_FLOW_OK)) + break; + } + + if (G_UNLIKELY (res != GST_FLOW_OK)) { + GST_WARNING ("Error pushing pending buffers : %s", gst_flow_get_name (res)); + /* Remove pending bfufers */ + for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) { + gst_buffer_unref ((GstBuffer *) tmp->data); + } + } else { + GST_INFO ("Pushing out EOS to flush out decoder/encoder"); + gst_pad_push_event (smart_encoder->internal_srcpad, gst_event_new_eos ()); + } + + /* Activate elements */ + /* Set elements to PAUSED */ + gst_element_set_state (smart_encoder->encoder, GST_STATE_NULL); + gst_element_set_state (smart_encoder->decoder, GST_STATE_NULL); + + g_list_free (smart_encoder->pending_gop); + smart_encoder->pending_gop = NULL; + + return res; +} + +static GstFlowReturn +gst_smart_encoder_push_pending_gop (GstSmartEncoder * smart_encoder) +{ + gint64 cstart, cstop; + GList *tmp; + GstFlowReturn res = GST_FLOW_OK; + + GST_DEBUG ("Pushing pending GOP (%" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT + ")", GST_TIME_ARGS (smart_encoder->gop_start), + GST_TIME_ARGS (smart_encoder->gop_stop)); + + /* If GOP is entirely within segment, just push downstream */ + if (gst_segment_clip (smart_encoder->segment, GST_FORMAT_TIME, + smart_encoder->gop_start, smart_encoder->gop_stop, &cstart, &cstop)) { + if ((cstart != smart_encoder->gop_start) + || (cstop != smart_encoder->gop_stop)) { + GST_DEBUG ("GOP needs to be re-encoded from %" GST_TIME_FORMAT " to %" + GST_TIME_FORMAT, GST_TIME_ARGS (cstart), GST_TIME_ARGS (cstop)); + res = gst_smart_encoder_reencode_gop (smart_encoder); + } else { + /* The whole GOP is within the segment, push all pending buffers downstream */ + GST_DEBUG ("GOP doesn't need to be modified, pushing downstream"); + for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) { + GstBuffer *buf = (GstBuffer *) tmp->data; + res = gst_pad_push (smart_encoder->srcpad, buf); + if (G_UNLIKELY (res != GST_FLOW_OK)) + break; + } + } + } else { + /* The whole GOP is outside the segment, there's most likely + * a bug somewhere. */ + GST_WARNING + ("GOP is entirely outside of the segment, upstream gave us too much data"); + for (tmp = smart_encoder->pending_gop; tmp; tmp = tmp->next) { + gst_buffer_unref ((GstBuffer *) tmp->data); + } + } + + if (smart_encoder->pending_gop) { + g_list_free (smart_encoder->pending_gop); + smart_encoder->pending_gop = NULL; + } + smart_encoder->gop_start = GST_CLOCK_TIME_NONE; + smart_encoder->gop_stop = GST_CLOCK_TIME_NONE; + + return res; +} + +static GstFlowReturn +gst_smart_encoder_chain (GstPad * pad, GstBuffer * buf) +{ + GstSmartEncoder *smart_encoder; + GstFlowReturn res = GST_FLOW_OK; + gboolean discont, keyframe; + + smart_encoder = GST_SMART_ENCODER (gst_object_get_parent (GST_OBJECT (pad))); + + discont = GST_BUFFER_IS_DISCONT (buf); + keyframe = !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + + GST_DEBUG ("New buffer %s %s %" GST_TIME_FORMAT, + discont ? "discont" : "", + keyframe ? "keyframe" : "", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + + if (keyframe) { + GST_DEBUG ("Got a keyframe"); + + /* If there's a pending GOP, flush it out */ + if (smart_encoder->pending_gop) { + /* Mark gop_stop */ + smart_encoder->gop_stop = GST_BUFFER_TIMESTAMP (buf); + + /* flush pending */ + res = gst_smart_encoder_push_pending_gop (smart_encoder); + if (G_UNLIKELY (res != GST_FLOW_OK)) + goto beach; + } + + /* Mark gop_start for new gop */ + smart_encoder->gop_start = GST_BUFFER_TIMESTAMP (buf); + } + + /* Store buffer */ + smart_encoder->pending_gop = g_list_append (smart_encoder->pending_gop, buf); + /* Update GOP stop position */ + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + smart_encoder->gop_stop = GST_BUFFER_TIMESTAMP (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) + smart_encoder->gop_stop += GST_BUFFER_DURATION (buf); + } + + GST_DEBUG ("Buffer stored , Current GOP : %" GST_TIME_FORMAT " -- %" + GST_TIME_FORMAT, GST_TIME_ARGS (smart_encoder->gop_start), + GST_TIME_ARGS (smart_encoder->gop_stop)); + +beach: + gst_object_unref (smart_encoder); + return res; +} + +static gboolean +smart_encoder_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + GstSmartEncoder *smart_encoder = GST_SMART_ENCODER (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + smart_encoder_reset (smart_encoder); + break; + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + gboolean update; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + GST_DEBUG_OBJECT (smart_encoder, + "newsegment: update %d, rate %g, arate %g, start %" GST_TIME_FORMAT + ", stop %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT, + update, rate, arate, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), + GST_TIME_ARGS (time)); + if (format != GST_FORMAT_TIME) + GST_ERROR + ("smart_encoder can not handle streams not specified in GST_FORMAT_TIME"); + + /* now configure the values */ + gst_segment_set_newsegment_full (smart_encoder->segment, update, + rate, arate, format, start, stop, time); + + /* And keep a copy for further usage */ + if (smart_encoder->newsegment) + gst_event_unref (smart_encoder->newsegment); + smart_encoder->newsegment = gst_event_ref (event); + } + break; + case GST_EVENT_EOS: + GST_DEBUG ("Eos, flushing remaining data"); + gst_smart_encoder_push_pending_gop (smart_encoder); + break; + default: + break; + } + + res = gst_pad_push_event (smart_encoder->srcpad, event); + + gst_object_unref (smart_encoder); + return res; +} + +static GstCaps * +smart_encoder_sink_getcaps (GstPad * pad) +{ + GstCaps *peer, *tmpl, *res; + GstSmartEncoder *smart_encoder = GST_SMART_ENCODER (gst_pad_get_parent (pad)); + + /* Try getting it from downstream */ + peer = gst_pad_peer_get_caps_reffed (smart_encoder->srcpad); + + /* Use computed caps */ + if (smart_encoder->available_caps) + tmpl = gst_caps_ref (smart_encoder->available_caps); + else + tmpl = gst_static_pad_template_get_caps (&src_template); + + if (peer == NULL) { + res = tmpl; + } else { + res = gst_caps_intersect (peer, tmpl); + gst_caps_unref (peer); + gst_caps_unref (tmpl); + } + + gst_object_unref (smart_encoder); + return res; +} + +/***************************************** + * Internal encoder/decoder pipeline * + ******************************************/ + +static GstElementFactory * +get_decoder_factory (GstCaps * caps) +{ + GstElementFactory *fact = NULL; + GList *decoders, *tmp; + + tmp = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECODER, + GST_RANK_MARGINAL); + decoders = gst_element_factory_list_filter (tmp, caps, GST_PAD_SINK, FALSE); + gst_plugin_feature_list_free (tmp); + + for (tmp = decoders; tmp; tmp = tmp->next) { + /* We just pick the first one */ + fact = (GstElementFactory *) tmp->data; + gst_object_ref (fact); + break; + } + + gst_plugin_feature_list_free (decoders); + + return fact; +} + +static GstElementFactory * +get_encoder_factory (GstCaps * caps) +{ + GstElementFactory *fact = NULL; + GList *encoders, *tmp; + + tmp = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, + GST_RANK_MARGINAL); + encoders = gst_element_factory_list_filter (tmp, caps, GST_PAD_SRC, FALSE); + gst_plugin_feature_list_free (tmp); + + for (tmp = encoders; tmp; tmp = tmp->next) { + /* We just pick the first one */ + fact = (GstElementFactory *) tmp->data; + gst_object_ref (fact); + break; + } + + gst_plugin_feature_list_free (encoders); + + return fact; +} + +static GstElement * +get_decoder (GstCaps * caps) +{ + GstElementFactory *fact = get_decoder_factory (caps); + GstElement *res = NULL; + + if (fact) { + res = gst_element_factory_create (fact, "internal-decoder"); + gst_object_unref (fact); + } + return res; +} + +static GstElement * +get_encoder (GstCaps * caps) +{ + GstElementFactory *fact = get_encoder_factory (caps); + GstElement *res = NULL; + + if (fact) { + res = gst_element_factory_create (fact, "internal-encoder"); + gst_object_unref (fact); + } + return res; +} + +static GstFlowReturn +internal_chain (GstPad * pad, GstBuffer * buf) +{ + GstSmartEncoder *smart_encoder = + g_object_get_qdata ((GObject *) pad, INTERNAL_ELEMENT); + + return gst_pad_push (smart_encoder->srcpad, buf); +} + +static gboolean +setup_recoder_pipeline (GstSmartEncoder * smart_encoder) +{ + GstPad *tmppad; + + /* Fast path */ + if (G_UNLIKELY (smart_encoder->encoder)) + return TRUE; + + GST_DEBUG ("Creating internal decoder and encoder"); + + /* Create decoder/encoder */ + smart_encoder->decoder = get_decoder (GST_PAD_CAPS (smart_encoder->sinkpad)); + if (G_UNLIKELY (smart_encoder->decoder == NULL)) + goto no_decoder; + gst_element_set_bus (smart_encoder->decoder, GST_ELEMENT_BUS (smart_encoder)); + + smart_encoder->encoder = get_encoder (GST_PAD_CAPS (smart_encoder->sinkpad)); + if (G_UNLIKELY (smart_encoder->encoder == NULL)) + goto no_encoder; + gst_element_set_bus (smart_encoder->encoder, GST_ELEMENT_BUS (smart_encoder)); + + GST_DEBUG ("Creating internal pads"); + + /* Create internal pads */ + + /* Source pad which we'll use to feed data to decoders */ + smart_encoder->internal_srcpad = gst_pad_new ("internal_src", GST_PAD_SRC); + g_object_set_qdata ((GObject *) smart_encoder->internal_srcpad, + INTERNAL_ELEMENT, smart_encoder); + gst_pad_set_caps (smart_encoder->internal_srcpad, + GST_PAD_CAPS (smart_encoder->sinkpad)); + gst_pad_set_active (smart_encoder->internal_srcpad, TRUE); + + /* Sink pad which will get the buffers from the encoder. + * Note: We don't need an event function since we'll be discarding all + * of them. */ + smart_encoder->internal_sinkpad = gst_pad_new ("internal_sink", GST_PAD_SINK); + g_object_set_qdata ((GObject *) smart_encoder->internal_sinkpad, + INTERNAL_ELEMENT, smart_encoder); + gst_pad_set_caps (smart_encoder->internal_sinkpad, + GST_PAD_CAPS (smart_encoder->sinkpad)); + gst_pad_set_chain_function (smart_encoder->internal_sinkpad, internal_chain); + gst_pad_set_active (smart_encoder->internal_sinkpad, TRUE); + + GST_DEBUG ("Linking pads to elements"); + + /* Link everything */ + tmppad = gst_element_get_static_pad (smart_encoder->encoder, "src"); + if (GST_PAD_LINK_FAILED (gst_pad_link (tmppad, + smart_encoder->internal_sinkpad))) + goto sinkpad_link_fail; + gst_object_unref (tmppad); + + if (!gst_element_link (smart_encoder->decoder, smart_encoder->encoder)) + goto encoder_decoder_link_fail; + + tmppad = gst_element_get_static_pad (smart_encoder->decoder, "sink"); + if (GST_PAD_LINK_FAILED (gst_pad_link (smart_encoder->internal_srcpad, + tmppad))) + goto srcpad_link_fail; + gst_object_unref (tmppad); + + GST_DEBUG ("Done creating internal elements/pads"); + + return TRUE; + +no_decoder: + { + GST_WARNING ("Couldn't find a decoder for %" GST_PTR_FORMAT, + GST_PAD_CAPS (smart_encoder->sinkpad)); + return FALSE; + } + +no_encoder: + { + GST_WARNING ("Couldn't find an encoder for %" GST_PTR_FORMAT, + GST_PAD_CAPS (smart_encoder->sinkpad)); + return FALSE; + } + +srcpad_link_fail: + { + gst_object_unref (tmppad); + GST_WARNING ("Couldn't link internal srcpad to decoder"); + return FALSE; + } + +sinkpad_link_fail: + { + gst_object_unref (tmppad); + GST_WARNING ("Couldn't link encoder to internal sinkpad"); + return FALSE; + } + +encoder_decoder_link_fail: + { + GST_WARNING ("Couldn't link decoder to encoder"); + return FALSE; + } +} + +static GstStateChangeReturn +gst_smart_encoder_find_elements (GstSmartEncoder * smart_encoder) +{ + guint i, n; + GstCaps *tmpl, *st, *res; + GstElementFactory *dec, *enc; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + if (G_UNLIKELY (smart_encoder->available_caps)) + goto beach; + + /* Iterate over all pad template caps and see if we have both an + * encoder and a decoder for those media types */ + tmpl = gst_static_pad_template_get_caps (&src_template); + res = gst_caps_new_empty (); + n = gst_caps_get_size (tmpl); + + for (i = 0; i < n; i++) { + st = gst_caps_copy_nth (tmpl, i); + GST_DEBUG_OBJECT (smart_encoder, + "Checking for available decoder and encoder for %" GST_PTR_FORMAT, st); + if (!(dec = get_decoder_factory (st))) { + gst_caps_unref (st); + continue; + } + gst_object_unref (dec); + if (!(enc = get_encoder_factory (st))) { + gst_caps_unref (st); + continue; + } + gst_object_unref (enc); + GST_DEBUG_OBJECT (smart_encoder, "OK"); + gst_caps_append (res, st); + } + + gst_caps_unref (tmpl); + + if (gst_caps_is_empty (res)) + ret = GST_STATE_CHANGE_FAILURE; + else + smart_encoder->available_caps = res; + + GST_DEBUG_OBJECT (smart_encoder, "Done, available_caps:%" GST_PTR_FORMAT, + smart_encoder->available_caps); + +beach: + return ret; +} + +/****************************************** + * GstElement vmethod implementations * + ******************************************/ + +static GstStateChangeReturn +gst_smart_encoder_change_state (GstElement * element, GstStateChange transition) +{ + GstSmartEncoder *smart_encoder; + GstStateChangeReturn ret; + + g_return_val_if_fail (GST_IS_SMART_ENCODER (element), + GST_STATE_CHANGE_FAILURE); + + smart_encoder = GST_SMART_ENCODER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + /* Figure out which elements are available */ + if ((ret = + gst_smart_encoder_find_elements (smart_encoder)) == + GST_STATE_CHANGE_FAILURE) + goto beach; + break; + default: + break; + } + + ret = + GST_ELEMENT_CLASS (gst_smart_encoder_parent_class)->change_state (element, + transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + smart_encoder_reset (smart_encoder); + break; + default: + break; + } + +beach: + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.h b/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.h new file mode 100644 index 0000000..1536626 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gstsmartencoder.h @@ -0,0 +1,71 @@ +/* GStreamer video re-encoder element + * Copyright (C) <2010> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __SMART_ENCODER_H__ +#define __SMART_ENCODER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_SMART_ENCODER \ + (gst_smart_encoder_get_type()) +#define GST_SMART_ENCODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SMART_ENCODER,GstSmartEncoder)) +#define GST_SMART_ENCODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SMART_ENCODER,GstSmartEncoderClass)) +#define GST_IS_SMART_ENCODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SMART_ENCODER)) +#define GST_IS_SMART_ENCODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SMART_ENCODER)) + +typedef struct _GstSmartEncoder GstSmartEncoder; +typedef struct _GstSmartEncoderClass GstSmartEncoderClass; + +struct _GstSmartEncoder { + GstElement element; + + GstPad *sinkpad, *srcpad; + + GstSegment *segment; + GstEvent *newsegment; + + /* Pending GOP to be checked */ + GList *pending_gop; + guint64 gop_start; /* GOP start in running time */ + guint64 gop_stop; /* GOP end in running time */ + + /* Internal recoding elements */ + GstPad *internal_sinkpad; + GstPad *internal_srcpad; + GstElement *decoder; + GstElement *encoder; + + /* Available caps at runtime */ + GstCaps *available_caps; +}; + +struct _GstSmartEncoderClass { + GstElementClass parent_class; +}; + +GType gst_smart_encoder_get_type(void); + +G_END_DECLS + +#endif /* __SMART_ENCODER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.c b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.c new file mode 100644 index 0000000..72d40fe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.c @@ -0,0 +1,276 @@ +/* GStreamer Stream Combiner + * Copyright (C) 2010 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gststreamcombiner.h" + +static GstStaticPadTemplate src_template = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_stream_combiner_debug); +#define GST_CAT_DEFAULT gst_stream_combiner_debug + +G_DEFINE_TYPE (GstStreamCombiner, gst_stream_combiner, GST_TYPE_ELEMENT); + +#define STREAMS_LOCK(obj) (g_mutex_lock(obj->lock)) +#define STREAMS_UNLOCK(obj) (g_mutex_unlock(obj->lock)) + +static void gst_stream_combiner_dispose (GObject * object); + +static GstPad *gst_stream_combiner_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_stream_combiner_release_pad (GstElement * element, + GstPad * pad); + +static void +gst_stream_combiner_class_init (GstStreamCombinerClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + gobject_klass->dispose = gst_stream_combiner_dispose; + + GST_DEBUG_CATEGORY_INIT (gst_stream_combiner_debug, "streamcombiner", 0, + "Stream Combiner"); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&sink_template)); + + gstelement_klass->request_new_pad = + GST_DEBUG_FUNCPTR (gst_stream_combiner_request_new_pad); + gstelement_klass->release_pad = + GST_DEBUG_FUNCPTR (gst_stream_combiner_release_pad); + + gst_element_class_set_details_simple (gstelement_klass, + "streamcombiner", "Generic", + "Recombines streams splitted by the streamsplitter element", + "Edward Hervey "); +} + +static void +gst_stream_combiner_dispose (GObject * object) +{ + GstStreamCombiner *stream_combiner = (GstStreamCombiner *) object; + + if (stream_combiner->lock) { + g_mutex_free (stream_combiner->lock); + stream_combiner->lock = NULL; + } + + G_OBJECT_CLASS (gst_stream_combiner_parent_class)->dispose (object); +} + +static GstFlowReturn +gst_stream_combiner_chain (GstPad * pad, GstBuffer * buf) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + /* FIXME : IMPLEMENT */ + + /* with lock taken, check if we're the active stream, if not drop */ + return gst_pad_push (stream_combiner->srcpad, buf); +} + +static gboolean +gst_stream_combiner_sink_event (GstPad * pad, GstEvent * event) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + /* FIXME : IMPLEMENT */ + + GST_DEBUG_OBJECT (pad, "Got event %s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_CUSTOM_DOWNSTREAM: + if (gst_event_has_name (event, "stream-switching-eos")) { + gst_event_unref (event); + event = gst_event_new_eos (); + } + break; + default: + break; + } + + /* NEW_SEGMENT : lock, wait for other stream to EOS, select stream, unlock, push */ + /* EOS : lock, mark pad as unused, unlock , drop event */ + /* CUSTOM_REAL_EOS : push EOS downstream */ + /* FLUSH_START : lock, mark as flushing, unlock. if wasn't flushing forward */ + /* FLUSH_STOP : lock, unmark as flushing, unlock, if was flushing forward */ + /* OTHER : if selected pad forward */ + return gst_pad_push_event (stream_combiner->srcpad, event); +} + +static GstCaps * +gst_stream_combiner_sink_getcaps (GstPad * pad) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + + return gst_pad_peer_get_caps_reffed (stream_combiner->srcpad); +} + +static gboolean +gst_stream_combiner_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + GstPad *peer; + gboolean res = FALSE; + + GST_DEBUG_OBJECT (pad, "caps:%" GST_PTR_FORMAT, caps); + + peer = gst_pad_get_peer (stream_combiner->srcpad); + if (peer) { + GST_DEBUG_OBJECT (peer, "Setting caps"); + res = gst_pad_set_caps (peer, caps); + gst_object_unref (peer); + } else + GST_WARNING_OBJECT (stream_combiner, "sourcepad has no peer !"); + return res; +} + +static gboolean +gst_stream_combiner_src_event (GstPad * pad, GstEvent * event) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + GstPad *sinkpad = NULL; + + STREAMS_LOCK (stream_combiner); + if (stream_combiner->current) + sinkpad = stream_combiner->current; + else if (stream_combiner->sinkpads) + sinkpad = (GstPad *) stream_combiner->sinkpads->data; + STREAMS_UNLOCK (stream_combiner); + + if (sinkpad) + /* Forward upstream as is */ + return gst_pad_push_event (sinkpad, event); + return FALSE; +} + +static gboolean +gst_stream_combiner_src_query (GstPad * pad, GstQuery * query) +{ + GstStreamCombiner *stream_combiner = + (GstStreamCombiner *) GST_PAD_PARENT (pad); + + GstPad *sinkpad = NULL; + + STREAMS_LOCK (stream_combiner); + if (stream_combiner->current) + sinkpad = stream_combiner->current; + else if (stream_combiner->sinkpads) + sinkpad = (GstPad *) stream_combiner->sinkpads->data; + STREAMS_UNLOCK (stream_combiner); + + if (sinkpad) + /* Forward upstream as is */ + return gst_pad_peer_query (sinkpad, query); + return FALSE; +} + +static void +gst_stream_combiner_init (GstStreamCombiner * stream_combiner) +{ + stream_combiner->srcpad = + gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_event_function (stream_combiner->srcpad, + gst_stream_combiner_src_event); + gst_pad_set_query_function (stream_combiner->srcpad, + gst_stream_combiner_src_query); + gst_element_add_pad (GST_ELEMENT (stream_combiner), stream_combiner->srcpad); + + stream_combiner->lock = g_mutex_new (); +} + +static GstPad * +gst_stream_combiner_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name) +{ + GstStreamCombiner *stream_combiner = (GstStreamCombiner *) element; + GstPad *sinkpad; + + GST_DEBUG_OBJECT (element, "templ:%p, name:%s", templ, name); + + sinkpad = gst_pad_new_from_static_template (&sink_template, name); + /* FIXME : No buffer alloc for the time being, it will resort to the fallback */ + /* gst_pad_set_bufferalloc_function (sinkpad, gst_stream_combiner_buffer_alloc); */ + gst_pad_set_chain_function (sinkpad, gst_stream_combiner_chain); + gst_pad_set_event_function (sinkpad, gst_stream_combiner_sink_event); + gst_pad_set_getcaps_function (sinkpad, gst_stream_combiner_sink_getcaps); + gst_pad_set_setcaps_function (sinkpad, gst_stream_combiner_sink_setcaps); + + STREAMS_LOCK (stream_combiner); + stream_combiner->sinkpads = + g_list_append (stream_combiner->sinkpads, sinkpad); + gst_pad_set_active (sinkpad, TRUE); + gst_element_add_pad (element, sinkpad); + stream_combiner->cookie++; + STREAMS_UNLOCK (stream_combiner); + + GST_DEBUG_OBJECT (element, "Returning pad %p", sinkpad); + + return sinkpad; +} + +static void +gst_stream_combiner_release_pad (GstElement * element, GstPad * pad) +{ + GstStreamCombiner *stream_combiner = (GstStreamCombiner *) element; + GList *tmp; + + GST_DEBUG_OBJECT (element, "pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + STREAMS_LOCK (stream_combiner); + tmp = g_list_find (stream_combiner->sinkpads, pad); + if (tmp) { + GstPad *pad = (GstPad *) tmp->data; + + stream_combiner->sinkpads = + g_list_delete_link (stream_combiner->sinkpads, tmp); + stream_combiner->cookie++; + + if (pad == stream_combiner->current) { + /* Deactivate current flow */ + GST_DEBUG_OBJECT (element, "Removed pad was the current one"); + stream_combiner->current = NULL; + } + GST_DEBUG_OBJECT (element, "Removing pad from ourself"); + gst_element_remove_pad (element, pad); + } + STREAMS_UNLOCK (stream_combiner); + + return; +} diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.h b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.h new file mode 100644 index 0000000..ce67277 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamcombiner.h @@ -0,0 +1,60 @@ +/* GStreamer Stream Combiner + * Copyright (C) 2010 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAMCOMBINER_H__ +#define __GST_STREAMCOMBINER_H__ + +#include + +#define GST_TYPE_STREAM_COMBINER (gst_stream_combiner_get_type()) +#define GST_STREAM_COMBINER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STREAM_COMBINER,GstStreamCombiner)) +#define GST_STREAM_COMBINER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STREAM_COMBINER,GstStreamCombinerClass)) +#define GST_IS_STREAM_COMBINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STREAM_COMBINER)) +#define GST_IS_STREAM_COMBINER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STREAM_COMBINER)) + +typedef struct _GstStreamCombiner GstStreamCombiner; +typedef struct _GstStreamCombinerClass GstStreamCombinerClass; + +struct _GstStreamCombiner { + GstElement parent; + + GstPad *srcpad; + + /* lock protects: + * * the current pad + * * the list of srcpads + */ + GMutex *lock; + /* Currently activated srcpad */ + GstPad *current; + GList *sinkpads; + guint32 cookie; + +}; + +struct _GstStreamCombinerClass { + GstElementClass parent; +}; + +GType gst_stream_combiner_get_type(void); + +GstElement *gst_stream_combiner_new (gchar *name); + +#endif /* __GST_STREAMCOMBINER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.c b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.c new file mode 100644 index 0000000..c473386 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.c @@ -0,0 +1,435 @@ +/* GStreamer Stream Splitter + * Copyright (C) 2010 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gststreamsplitter.h" + +static GstStaticPadTemplate src_template = +GST_STATIC_PAD_TEMPLATE ("src_%d", GST_PAD_SRC, GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_stream_splitter_debug); +#define GST_CAT_DEFAULT gst_stream_splitter_debug + +G_DEFINE_TYPE (GstStreamSplitter, gst_stream_splitter, GST_TYPE_ELEMENT); + +#define STREAMS_LOCK(obj) (g_mutex_lock(obj->lock)) +#define STREAMS_UNLOCK(obj) (g_mutex_unlock(obj->lock)) + +static void gst_stream_splitter_dispose (GObject * object); + +static GstPad *gst_stream_splitter_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_stream_splitter_release_pad (GstElement * element, + GstPad * pad); + +static void +gst_stream_splitter_class_init (GstStreamSplitterClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + gobject_klass->dispose = gst_stream_splitter_dispose; + + GST_DEBUG_CATEGORY_INIT (gst_stream_splitter_debug, "streamsplitter", 0, + "Stream Splitter"); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&sink_template)); + + gstelement_klass->request_new_pad = + GST_DEBUG_FUNCPTR (gst_stream_splitter_request_new_pad); + gstelement_klass->release_pad = + GST_DEBUG_FUNCPTR (gst_stream_splitter_release_pad); + + gst_element_class_set_details_simple (gstelement_klass, + "streamsplitter", "Generic", + "Splits streams based on their media type", + "Edward Hervey "); +} + +static void +gst_stream_splitter_dispose (GObject * object) +{ + GstStreamSplitter *stream_splitter = (GstStreamSplitter *) object; + + if (stream_splitter->lock) { + g_mutex_free (stream_splitter->lock); + stream_splitter->lock = NULL; + } + + g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref, + NULL); + g_list_free (stream_splitter->pending_events); + stream_splitter->pending_events = NULL; + + G_OBJECT_CLASS (gst_stream_splitter_parent_class)->dispose (object); +} + +static GstFlowReturn +gst_stream_splitter_chain (GstPad * pad, GstBuffer * buf) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + GstFlowReturn res; + GstPad *srcpad = NULL; + + STREAMS_LOCK (stream_splitter); + if (stream_splitter->current) + srcpad = gst_object_ref (stream_splitter->current); + STREAMS_UNLOCK (stream_splitter); + + if (G_UNLIKELY (srcpad == NULL)) + goto nopad; + + if (G_UNLIKELY (stream_splitter->pending_events)) { + GList *tmp; + GST_DEBUG_OBJECT (srcpad, "Pushing out pending events"); + + for (tmp = stream_splitter->pending_events; tmp; tmp = tmp->next) { + GstEvent *event = (GstEvent *) tmp->data; + gst_pad_push_event (srcpad, event); + } + g_list_free (stream_splitter->pending_events); + stream_splitter->pending_events = NULL; + } + + /* Forward to currently activated stream */ + res = gst_pad_push (srcpad, buf); + gst_object_unref (srcpad); + + return res; + +nopad: + GST_WARNING_OBJECT (stream_splitter, "No output pad was configured"); + return GST_FLOW_ERROR; +} + +static gboolean +gst_stream_splitter_sink_event (GstPad * pad, GstEvent * event) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + gboolean res = TRUE; + gboolean toall = FALSE; + gboolean store = FALSE; + gboolean eos = FALSE; + gboolean flushpending = FALSE; + + /* FLUSH_START/STOP : forward to all + * EOS : transform to CUSTOM_REAL_EOS and forward to all + * INBAND events : store to send in chain function to selected chain + * OUT_OF_BAND events : send to all + */ + + GST_DEBUG_OBJECT (stream_splitter, "Got event %s", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + flushpending = TRUE; + toall = TRUE; + break; + case GST_EVENT_FLUSH_START: + toall = TRUE; + break; + case GST_EVENT_EOS: + /* Replace with our custom eos event */ + gst_event_unref (event); + event = + gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, + gst_structure_empty_new ("stream-switching-eos")); + toall = TRUE; + eos = TRUE; + break; + default: + if (GST_EVENT_TYPE (event) & GST_EVENT_TYPE_SERIALIZED) + store = TRUE; + } + + if (flushpending) { + g_list_foreach (stream_splitter->pending_events, (GFunc) gst_event_unref, + NULL); + g_list_free (stream_splitter->pending_events); + stream_splitter->pending_events = NULL; + } + + if (store) { + stream_splitter->pending_events = + g_list_append (stream_splitter->pending_events, event); + } else if (toall || eos) { + GList *tmp; + guint32 cookie; + + /* Send to all pads */ + STREAMS_LOCK (stream_splitter); + resync: + if (G_UNLIKELY (stream_splitter->srcpads == NULL)) { + STREAMS_UNLOCK (stream_splitter); + /* No source pads */ + gst_event_unref (event); + res = FALSE; + goto beach; + } + tmp = stream_splitter->srcpads; + cookie = stream_splitter->cookie; + while (tmp) { + GstPad *srcpad = (GstPad *) tmp->data; + STREAMS_UNLOCK (stream_splitter); + /* In case of EOS, we first push out the real one to flush out + * each streams (but which will be discarded in the streamcombiner) + * before our custom one (which will be converted back to and EOS + * in the streamcombiner) */ + if (eos) + gst_pad_push_event (srcpad, gst_event_new_eos ()); + gst_event_ref (event); + res = gst_pad_push_event (srcpad, event); + STREAMS_LOCK (stream_splitter); + if (G_UNLIKELY (cookie != stream_splitter->cookie)) + goto resync; + tmp = tmp->next; + } + STREAMS_UNLOCK (stream_splitter); + gst_event_unref (event); + } else { + GstPad *pad; + + /* Only send to current pad */ + + STREAMS_LOCK (stream_splitter); + pad = stream_splitter->current; + STREAMS_UNLOCK (stream_splitter); + if (pad) + res = gst_pad_push_event (pad, event); + else { + gst_event_unref (event); + res = FALSE; + } + } + +beach: + return res; +} + +static GstCaps * +gst_stream_splitter_sink_getcaps (GstPad * pad) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + guint32 cookie; + GList *tmp; + GstCaps *res = NULL; + + /* Return the combination of all downstream caps */ + + STREAMS_LOCK (stream_splitter); + +resync: + if (G_UNLIKELY (stream_splitter->srcpads == NULL)) { + res = gst_caps_new_any (); + goto beach; + } + + res = NULL; + cookie = stream_splitter->cookie; + tmp = stream_splitter->srcpads; + + while (tmp) { + GstPad *srcpad = (GstPad *) tmp->data; + + STREAMS_UNLOCK (stream_splitter); + if (res) + gst_caps_merge (res, gst_pad_peer_get_caps_reffed (srcpad)); + else + res = gst_pad_peer_get_caps (srcpad); + STREAMS_LOCK (stream_splitter); + + if (G_UNLIKELY (cookie != stream_splitter->cookie)) { + if (res) + gst_caps_unref (res); + goto resync; + } + tmp = tmp->next; + } + +beach: + STREAMS_UNLOCK (stream_splitter); + return res; +} + +static gboolean +gst_stream_splitter_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + guint32 cookie; + GList *tmp; + gboolean res; + + GST_DEBUG_OBJECT (stream_splitter, "caps %" GST_PTR_FORMAT, caps); + + /* Try on all pads, choose the one that succeeds as the current stream */ + STREAMS_LOCK (stream_splitter); + +resync: + if (G_UNLIKELY (stream_splitter->srcpads == NULL)) { + res = FALSE; + goto beach; + } + + res = FALSE; + tmp = stream_splitter->srcpads; + cookie = stream_splitter->cookie; + + while (tmp) { + GstPad *srcpad = (GstPad *) tmp->data; + GstCaps *peercaps; + + STREAMS_UNLOCK (stream_splitter); + peercaps = gst_pad_peer_get_caps_reffed (srcpad); + if (peercaps) { + res = gst_caps_can_intersect (caps, peercaps); + gst_caps_unref (peercaps); + } + STREAMS_LOCK (stream_splitter); + + if (G_UNLIKELY (cookie != stream_splitter->cookie)) + goto resync; + + if (res) { + /* FIXME : we need to switch properly */ + GST_DEBUG_OBJECT (srcpad, "Setting caps on this pad was succesfull"); + stream_splitter->current = srcpad; + goto beach; + } + tmp = tmp->next; + } + +beach: + STREAMS_UNLOCK (stream_splitter); + return res; +} + +static gboolean +gst_stream_splitter_src_event (GstPad * pad, GstEvent * event) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + + GST_DEBUG_OBJECT (pad, "%s", GST_EVENT_TYPE_NAME (event)); + + /* Forward upstream as is */ + return gst_pad_push_event (stream_splitter->sinkpad, event); +} + +static gboolean +gst_stream_splitter_src_query (GstPad * pad, GstQuery * query) +{ + GstStreamSplitter *stream_splitter = + (GstStreamSplitter *) GST_PAD_PARENT (pad); + + GST_DEBUG_OBJECT (pad, "%s", GST_QUERY_TYPE_NAME (query)); + + /* Forward upstream as is */ + return gst_pad_peer_query (stream_splitter->sinkpad, query); +} + +static void +gst_stream_splitter_init (GstStreamSplitter * stream_splitter) +{ + stream_splitter->sinkpad = + gst_pad_new_from_static_template (&sink_template, "sink"); + /* FIXME : No buffer alloc for the time being, it will resort to the fallback */ + /* gst_pad_set_bufferalloc_function (stream_splitter->sinkpad, */ + /* gst_stream_splitter_buffer_alloc); */ + gst_pad_set_chain_function (stream_splitter->sinkpad, + gst_stream_splitter_chain); + gst_pad_set_event_function (stream_splitter->sinkpad, + gst_stream_splitter_sink_event); + gst_pad_set_getcaps_function (stream_splitter->sinkpad, + gst_stream_splitter_sink_getcaps); + gst_pad_set_setcaps_function (stream_splitter->sinkpad, + gst_stream_splitter_sink_setcaps); + gst_element_add_pad (GST_ELEMENT (stream_splitter), stream_splitter->sinkpad); + + stream_splitter->lock = g_mutex_new (); +} + +static GstPad * +gst_stream_splitter_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name) +{ + GstStreamSplitter *stream_splitter = (GstStreamSplitter *) element; + GstPad *srcpad; + + srcpad = gst_pad_new_from_static_template (&src_template, name); + gst_pad_set_event_function (srcpad, gst_stream_splitter_src_event); + gst_pad_set_query_function (srcpad, gst_stream_splitter_src_query); + + STREAMS_LOCK (stream_splitter); + stream_splitter->srcpads = g_list_append (stream_splitter->srcpads, srcpad); + gst_pad_set_active (srcpad, TRUE); + gst_element_add_pad (element, srcpad); + stream_splitter->cookie++; + STREAMS_UNLOCK (stream_splitter); + + return srcpad; +} + +static void +gst_stream_splitter_release_pad (GstElement * element, GstPad * pad) +{ + GstStreamSplitter *stream_splitter = (GstStreamSplitter *) element; + GList *tmp; + + STREAMS_LOCK (stream_splitter); + tmp = g_list_find (stream_splitter->srcpads, pad); + if (tmp) { + GstPad *pad = (GstPad *) tmp->data; + + stream_splitter->srcpads = + g_list_delete_link (stream_splitter->srcpads, tmp); + stream_splitter->cookie++; + + if (pad == stream_splitter->current) { + /* Deactivate current flow */ + GST_DEBUG_OBJECT (element, "Removed pad was the current one"); + stream_splitter->current = NULL; + } + + gst_element_remove_pad (element, pad); + } + STREAMS_UNLOCK (stream_splitter); + + return; +} diff --git a/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.h b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.h new file mode 100644 index 0000000..b503c00 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/encoding/gststreamsplitter.h @@ -0,0 +1,62 @@ +/* GStreamer Stream Splitter + * Copyright (C) 2010 Edward Hervey + * (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAMSPLITTER_H__ +#define __GST_STREAMSPLITTER_H__ + +#include + +#define GST_TYPE_STREAM_SPLITTER (gst_stream_splitter_get_type()) +#define GST_STREAM_SPLITTER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STREAM_SPLITTER,GstStreamSplitter)) +#define GST_STREAM_SPLITTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STREAM_SPLITTER,GstStreamSplitterClass)) +#define GST_IS_STREAM_SPLITTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STREAM_SPLITTER)) +#define GST_IS_STREAM_SPLITTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STREAM_SPLITTER)) + +typedef struct _GstStreamSplitter GstStreamSplitter; +typedef struct _GstStreamSplitterClass GstStreamSplitterClass; + +struct _GstStreamSplitter { + GstElement parent; + + GstPad *sinkpad; + + /* lock protects: + * * the current pad + * * the list of srcpads + */ + GMutex *lock; + /* Currently activated srcpad */ + GstPad *current; + GList *srcpads; + guint32 cookie; + + /* List of pending in-band events */ + GList *pending_events; +}; + +struct _GstStreamSplitterClass { + GstElementClass parent; +}; + +GType gst_stream_splitter_get_type(void); + +GstElement *gst_stream_splitter_new (gchar *name); + +#endif /* __GST_STREAMSPLITTER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/Makefile.am b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/Makefile.am new file mode 100644 index 0000000..2ada4c9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/Makefile.am @@ -0,0 +1,37 @@ +plugin_LTLIBRARIES = libgstffmpegcolorspace.la + +libgstffmpegcolorspace_la_SOURCES = \ + gstffmpegcolorspace.c \ + gstffmpegcodecmap.c \ + dsputil.c \ + mem.c \ + utils.c \ + imgconvert.c + +libgstffmpegcolorspace_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstffmpegcolorspace_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstffmpegcolorspace_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) $(GST_LIBS) +libgstffmpegcolorspace_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstffmpegcolorspace.h \ + gstffmpegcodecmap.h \ + imgconvert_template.h \ + dsputil.h \ + avcodec.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstffmpegcolorspace -:SHARED libgstffmpegcolorspace \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstffmpegcolorspace_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstffmpegcolorspace_la_CFLAGS) \ + -:LDFLAGS $(libgstffmpegcolorspace_la_LDFLAGS) \ + $(libgstffmpegcolorspace_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/avcodec.h b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/avcodec.h new file mode 100644 index 0000000..57f551c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/avcodec.h @@ -0,0 +1,285 @@ +#ifndef AVCODEC_H +#define AVCODEC_H + +/** + * @file avcodec.h + * external api header. + */ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "_stdint.h" + +#include /* size_t */ + +#define FFMPEG_VERSION_INT 0x000409 +#define FFMPEG_VERSION "0.4.9-pre1" +#define LIBAVCODEC_BUILD 4728 + +#define LIBAVCODEC_VERSION_INT FFMPEG_VERSION_INT +#define LIBAVCODEC_VERSION FFMPEG_VERSION + +#define AV_STRINGIFY(s) AV_TOSTRING(s) +#define AV_TOSTRING(s) #s +#define LIBAVCODEC_IDENT "FFmpeg" LIBAVCODEC_VERSION "b" AV_STRINGIFY(LIBAVCODEC_BUILD) + +enum CodecType { + CODEC_TYPE_UNKNOWN = -1, + CODEC_TYPE_VIDEO, + CODEC_TYPE_AUDIO, + CODEC_TYPE_DATA, +}; + +/* + * Pixel format. Notes: + * + * PIX_FMT_RGBA32 is handled in an endian-specific manner. A RGBA + * color is put together as: + * (A << 24) | (R << 16) | (G << 8) | B + * This is stored as BGRA on little endian CPU architectures and ARGB on + * big endian CPUs. + * + * When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized + * image data is stored in AVFrame.data[0]. The palette is transported in + * AVFrame.data[1] and, is 1024 bytes long (256 4-byte entries) and is + * formatted the same as in PIX_FMT_RGBA32 described above (i.e., it is + * also endian-specific). Note also that the individual RGB palette + * components stored in AVFrame.data[1] should be in the range 0..255. + * This is important as many custom PAL8 video codecs that were designed + * to run on the IBM VGA graphics adapter use 6-bit palette components. + */ +enum PixelFormat { + PIX_FMT_YUV420P, ///< Planar YUV 4:2:0 (1 Cr & Cb sample per 2x2 Y samples) (I420) + PIX_FMT_NV12, ///< Packed YUV 4:2:0 (separate Y plane, interleaved Cb & Cr planes) + PIX_FMT_NV21, ///< Packed YUV 4:2:0 (separate Y plane, interleaved Cb & Cr planes) + PIX_FMT_YVU420P, ///< Planar YUV 4:2:0 (1 Cb & Cr sample per 2x2 Y samples) (YV12) + PIX_FMT_YUV422, ///< Packed pixel, Y0 Cb Y1 Cr + PIX_FMT_RGB24, ///< Packed pixel, 3 bytes per pixel, RGBRGB... + PIX_FMT_BGR24, ///< Packed pixel, 3 bytes per pixel, BGRBGR... + PIX_FMT_YUV422P, ///< Planar YUV 4:2:2 (1 Cr & Cb sample per 2x1 Y samples) + PIX_FMT_YUV444P, ///< Planar YUV 4:4:4 (1 Cr & Cb sample per 1x1 Y samples) + PIX_FMT_RGBA32, ///< Packed pixel, 4 bytes per pixel, BGRABGRA..., stored in cpu endianness + PIX_FMT_BGRA32, ///< Packed pixel, 4 bytes per pixel, ARGBARGB... + PIX_FMT_ARGB32, ///< Packed pixel, 4 bytes per pixel, ABGRABGR..., stored in cpu endianness + PIX_FMT_ABGR32, ///< Packed pixel, 4 bytes per pixel, RGBARGBA... + PIX_FMT_RGB32, ///< Packed pixel, 4 bytes per pixel, BGRxBGRx..., stored in cpu endianness + PIX_FMT_xRGB32, ///< Packed pixel, 4 bytes per pixel, xBGRxBGR..., stored in cpu endianness + PIX_FMT_BGR32, ///< Packed pixel, 4 bytes per pixel, xRGBxRGB... + PIX_FMT_BGRx32, ///< Packed pixel, 4 bytes per pixel, RGBxRGBx... + PIX_FMT_YUV410P, ///< Planar YUV 4:1:0 (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YVU410P, ///< Planar YVU 4:1:0 (1 Cr & Cb sample per 4x4 Y samples) + PIX_FMT_YUV411P, ///< Planar YUV 4:1:1 (1 Cr & Cb sample per 4x1 Y samples) + PIX_FMT_Y800, ///< 8 bit Y plane (range [16-235]) + PIX_FMT_Y16, ///< 16 bit Y plane (little endian) + PIX_FMT_RGB565, ///< always stored in cpu endianness + PIX_FMT_RGB555, ///< always stored in cpu endianness, most significant bit to 1 + PIX_FMT_GRAY8, + PIX_FMT_GRAY16_L, + PIX_FMT_GRAY16_B, + PIX_FMT_MONOWHITE, ///< 0 is white + PIX_FMT_MONOBLACK, ///< 0 is black + PIX_FMT_PAL8, ///< 8 bit with RGBA palette + PIX_FMT_YUVJ420P, ///< Planar YUV 4:2:0 full scale (jpeg) + PIX_FMT_YUVJ422P, ///< Planar YUV 4:2:2 full scale (jpeg) + PIX_FMT_YUVJ444P, ///< Planar YUV 4:4:4 full scale (jpeg) + PIX_FMT_XVMC_MPEG2_MC,///< XVideo Motion Acceleration via common packet passing(xvmc_render.h) + PIX_FMT_XVMC_MPEG2_IDCT, + PIX_FMT_UYVY422, ///< Packed pixel, Cb Y0 Cr Y1 + PIX_FMT_YVYU422, ///< Packed pixel, Y0 Cr Y1 Cb + PIX_FMT_UYVY411, ///< Packed pixel, Cb Y0 Y1 Cr Y2 Y3 + PIX_FMT_V308, ///< Packed pixel, Y0 Cb Cr + + PIX_FMT_AYUV4444, ///< Packed pixel, A0 Y0 Cb Cr + PIX_FMT_YUVA420P, ///< Planar YUV 4:4:2:0 (1 Cr & Cb sample per 2x2 Y & A samples) (A420) + PIX_FMT_NB +}; + +/* currently unused, may be used if 24/32 bits samples ever supported */ +enum SampleFormat { + SAMPLE_FMT_S16 = 0, ///< signed 16 bits +}; + +/* thomas: extracted from imgconvert.c since it's also used in + * gstffmpegcodecmap.c */ + +/* start of extract */ + +#define FF_COLOR_RGB 0 /* RGB color space */ +#define FF_COLOR_GRAY 1 /* gray color space */ +#define FF_COLOR_YUV 2 /* YUV color space. 16 <= Y <= 235, 16 <= U, V <= 240 */ +#define FF_COLOR_YUV_JPEG 3 /* YUV color space. 0 <= Y <= 255, 0 <= U, V <= 255 */ + +#define FF_PIXEL_PLANAR 0 /* each channel has one component in AVPicture */ +#define FF_PIXEL_PACKED 1 /* only one components containing all the channels */ +#define FF_PIXEL_PALETTE 2 /* one components containing indexes for a palette */ + +typedef struct PixFmtInfo +{ + enum PixelFormat format; + const char *name; + uint8_t nb_channels; /* number of channels (including alpha) */ + uint8_t color_type; /* color type (see FF_COLOR_xxx constants) */ + uint8_t pixel_type; /* pixel storage type (see FF_PIXEL_xxx constants) */ + uint8_t is_alpha:1; /* true if alpha can be specified */ + uint8_t x_chroma_shift; /* X chroma subsampling factor is 2 ^ shift */ + uint8_t y_chroma_shift; /* Y chroma subsampling factor is 2 ^ shift */ + uint8_t depth; /* bit depth of the color components */ +} PixFmtInfo; + +PixFmtInfo * get_pix_fmt_info (enum PixelFormat format); +/* end of extract */ + +/** + * main external api structure. + */ +typedef struct AVCodecContext { + /* video only */ + /** + * frames per sec multiplied by frame_rate_base. + * for variable fps this is the precission, so if the timestamps + * can be specified in msec precssion then this is 1000*frame_rate_base + * - encoding: MUST be set by user + * - decoding: set by lavc. 0 or the frame_rate if available + */ + int frame_rate; + + /** + * frame_rate_base. + * for variable fps this is 1 + * - encoding: set by user. + * - decoding: set by lavc. + */ + + int frame_rate_base; + /** + * picture width / height. + * - encoding: MUST be set by user. + * - decoding: set by lavc. + * Note, for compatibility its possible to set this instead of + * coded_width/height before decoding + */ + int width, height; + + /** + * pixel format, see PIX_FMT_xxx. + * - encoding: FIXME: used by ffmpeg to decide whether an pix_fmt + * conversion is in order. This only works for + * codecs with one supported pix_fmt, we should + * do something for a generic case as well. + * - decoding: set by lavc. + */ + enum PixelFormat pix_fmt; + + /* audio only */ + int sample_rate; ///< samples per sec + int channels; + int sample_fmt; ///< sample format, currenly unused + + /** + * Palette control structure + * - encoding: ??? (no palette-enabled encoder yet) + * - decoding: set by user. + */ + struct AVPaletteControl *palctrl; +} AVCodecContext; + +/** + * four components are given, that's all. + * the last component is alpha + */ +typedef struct AVPicture { + uint8_t *data[4]; + int linesize[4]; ///< number of bytes per line + int interlaced; +} AVPicture; + +/** + * AVPaletteControl + * This structure defines a method for communicating palette changes + * between and demuxer and a decoder. + */ +#define AVPALETTE_SIZE 1024 +#define AVPALETTE_COUNT 256 +typedef struct AVPaletteControl { + + /* demuxer sets this to 1 to indicate the palette has changed; + * decoder resets to 0 */ + int palette_changed; + + /* 4-byte ARGB palette entries, stored in native byte order; note that + * the individual palette components should be on a 8-bit scale; if + * the palette data comes from a IBM VGA native format, the component + * data is probably 6 bits in size and needs to be scaled */ + unsigned int palette[AVPALETTE_COUNT]; + +} AVPaletteControl; + +int avpicture_get_size(int pix_fmt, int width, int height); + +void avcodec_get_chroma_sub_sample(int pix_fmt, int *h_shift, int *v_shift); +const char *avcodec_get_pix_fmt_name(int pix_fmt); +void avcodec_set_dimensions(AVCodecContext *s, int width, int height); +enum PixelFormat avcodec_get_pix_fmt(const char* name); + +#define FF_LOSS_RESOLUTION 0x0001 /* loss due to resolution change */ +#define FF_LOSS_DEPTH 0x0002 /* loss due to color depth change */ +#define FF_LOSS_COLORSPACE 0x0004 /* loss due to color space conversion */ +#define FF_LOSS_ALPHA 0x0008 /* loss of alpha bits */ +#define FF_LOSS_COLORQUANT 0x0010 /* loss due to color quantization */ +#define FF_LOSS_CHROMA 0x0020 /* loss of chroma (e.g. rgb to gray conversion) */ + +int avcodec_get_pix_fmt_loss(int dst_pix_fmt, int src_pix_fmt, + int has_alpha); +int avcodec_find_best_pix_fmt(int pix_fmt_mask, int src_pix_fmt, + int has_alpha, int *loss_ptr); + +#define FF_ALPHA_TRANSP 0x0001 /* image has some totally transparent pixels */ +#define FF_ALPHA_SEMI_TRANSP 0x0002 /* image has some transparent pixels */ +int img_get_alpha_info(const AVPicture *src, + int pix_fmt, int width, int height); + +/* convert among pixel formats */ +int img_convert(AVPicture *dst, int dst_pix_fmt, + const AVPicture *src, int pix_fmt, + int width, int height); + +void avcodec_init(void); + +void avcodec_get_context_defaults(AVCodecContext *s); +AVCodecContext *avcodec_alloc_context(void); + +/* memory */ +void *av_malloc(unsigned int size); +void *av_mallocz(unsigned int size); +void *av_realloc(void *ptr, unsigned int size); +void av_free(void *ptr); +char *av_strdup(const char *s); +void av_freep(void *ptr); +void *av_fast_realloc(void *ptr, unsigned int *size, unsigned int min_size); +/* for static data only */ +/* call av_free_static to release all staticaly allocated tables */ +void av_free_static(void); +void *av_mallocz_static(unsigned int size); + +/* endian macros */ +#if !defined(BE_16) || !defined(BE_32) || !defined(LE_16) || !defined(LE_32) +#define BE_16(x) ((((uint8_t*)(x))[0] << 8) | ((uint8_t*)(x))[1]) +#define BE_32(x) ((((uint8_t*)(x))[0] << 24) | \ + (((uint8_t*)(x))[1] << 16) | \ + (((uint8_t*)(x))[2] << 8) | \ + ((uint8_t*)(x))[3]) +#define LE_16(x) ((((uint8_t*)(x))[1] << 8) | ((uint8_t*)(x))[0]) +#define LE_32(x) ((((uint8_t*)(x))[3] << 24) | \ + (((uint8_t*)(x))[2] << 16) | \ + (((uint8_t*)(x))[1] << 8) | \ + ((uint8_t*)(x))[0]) +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* AVCODEC_H */ diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.c new file mode 100644 index 0000000..f5689c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.c @@ -0,0 +1,45 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * gmc & q-pel & 32/64 bit based MC by Michael Niedermayer + */ + +/** + * @file dsputil.c + * DSP utils + */ + +#include "avcodec.h" +#include "dsputil.h" + +uint8_t cropTbl[256 + 2 * MAX_NEG_CROP] = { 0, }; + +/* init static data */ +void +dsputil_static_init (void) +{ + int i; + + for (i = 0; i < 256; i++) + cropTbl[i + MAX_NEG_CROP] = i; + for (i = 0; i < MAX_NEG_CROP; i++) { + cropTbl[i] = 0; + cropTbl[i + MAX_NEG_CROP + 256] = 255; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.h b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.h new file mode 100644 index 0000000..69475a3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/dsputil.h @@ -0,0 +1,39 @@ +/* + * DSP utils + * Copyright (c) 2000, 2001, 2002 Fabrice Bellard. + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file dsputil.h + * DSP utils. + * note, many functions in here may use MMX which trashes the FPU state, it is + * absolutely necessary to call emms_c() between dsp & float/double code + */ + +#ifndef DSPUTIL_H +#define DSPUTIL_H + +/* pixel operations */ +#define MAX_NEG_CROP 1024 + +/* temporary */ +extern uint8_t cropTbl[256 + 2 * MAX_NEG_CROP]; + +void dsputil_static_init(void); + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/ffmpegcolorspace.vcproj b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/ffmpegcolorspace.vcproj new file mode 100644 index 0000000..fc5e7c6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/ffmpegcolorspace.vcproj @@ -0,0 +1,181 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.c new file mode 100644 index 0000000..318a90e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.c @@ -0,0 +1,1016 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * This file: + * Copyright (c) 2002-2004 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include "avcodec.h" +#include "gstffmpegcodecmap.h" + +GST_DEBUG_CATEGORY_EXTERN (ffmpegcolorspace_debug); +#define GST_CAT_DEFAULT ffmpegcolorspace_debug + +static GstCaps * +gst_ff_vid_caps_new (AVCodecContext * context, + const char *mimetype, const char *fieldname, ...) + G_GNUC_NULL_TERMINATED; + static GstCaps *gst_ff_aud_caps_new (AVCodecContext * context, + const char *mimetype, const char *fieldname, ...) G_GNUC_NULL_TERMINATED; + +/* + * Read a palette from a caps. + */ + + static void + gst_ffmpeg_get_palette (const GstCaps * caps, AVCodecContext * context) +{ + GstStructure *str = gst_caps_get_structure (caps, 0); + const GValue *palette_v; + + /* do we have a palette? */ + if ((palette_v = gst_structure_get_value (str, "palette_data")) && context) { + const GstBuffer *palette; + + palette = gst_value_get_buffer (palette_v); + if (palette && GST_BUFFER_SIZE (palette) >= 256 * 4) { + if (context->palctrl) + av_free (context->palctrl); + context->palctrl = av_malloc (sizeof (AVPaletteControl)); + context->palctrl->palette_changed = 1; + memcpy (context->palctrl->palette, GST_BUFFER_DATA (palette), + AVPALETTE_SIZE); + } + } +} + +static void +gst_ffmpeg_set_palette (GstCaps * caps, AVCodecContext * context) +{ + if (context->palctrl) { + GstBuffer *palette = gst_buffer_new_and_alloc (256 * 4); + + memcpy (GST_BUFFER_DATA (palette), context->palctrl->palette, + AVPALETTE_SIZE); + gst_caps_set_simple (caps, "palette_data", GST_TYPE_BUFFER, palette, NULL); + gst_buffer_unref (palette); + } +} + +/* this function creates caps with fixed or unfixed width/height + * properties depending on whether we've got a context. + * + * See below for why we use this. + * + * We should actually do this stuff at the end, like in riff-media.c, + * but I'm too lazy today. Maybe later. + */ + +static GstCaps * +gst_ff_vid_caps_new (AVCodecContext * context, const char *mimetype, + const char *fieldname, ...) +{ + GstStructure *structure = NULL; + GstCaps *caps = NULL; + va_list var_args; + + if (context != NULL) { + caps = gst_caps_new_simple (mimetype, + "width", G_TYPE_INT, context->width, + "height", G_TYPE_INT, context->height, + "framerate", GST_TYPE_FRACTION, + (gint) context->frame_rate, (gint) context->frame_rate_base, NULL); + } else { + caps = gst_caps_new_simple (mimetype, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + } + + structure = gst_caps_get_structure (caps, 0); + + if (structure) { + va_start (var_args, fieldname); + gst_structure_set_valist (structure, fieldname, var_args); + va_end (var_args); + } + + return caps; +} + +/* same for audio - now with channels/sample rate + */ + +static GstCaps * +gst_ff_aud_caps_new (AVCodecContext * context, const char *mimetype, + const char *fieldname, ...) +{ + GstCaps *caps = NULL; + GstStructure *structure = NULL; + va_list var_args; + + if (context != NULL) { + caps = gst_caps_new_simple (mimetype, + "rate", G_TYPE_INT, context->sample_rate, + "channels", G_TYPE_INT, context->channels, NULL); + } else { + caps = gst_caps_new_simple (mimetype, NULL); + } + + structure = gst_caps_get_structure (caps, 0); + + if (structure) { + va_start (var_args, fieldname); + gst_structure_set_valist (structure, fieldname, var_args); + va_end (var_args); + } + + return caps; +} + +/* Convert a FFMPEG Pixel Format and optional AVCodecContext + * to a GstCaps. If the context is ommitted, no fixed values + * for video/audio size will be included in the GstCaps + * + * See below for usefulness + */ + +static GstCaps * +gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context) +{ + GstCaps *caps = NULL; + + int bpp = 0, depth = 0, endianness = 0; + gulong g_mask = 0, r_mask = 0, b_mask = 0, a_mask = 0; + guint32 fmt = 0; + + switch (pix_fmt) { + case PIX_FMT_YUV420P: + fmt = GST_MAKE_FOURCC ('I', '4', '2', '0'); + break; + case PIX_FMT_YUVA420P: + fmt = GST_MAKE_FOURCC ('A', '4', '2', '0'); + break; + case PIX_FMT_NV12: + fmt = GST_MAKE_FOURCC ('N', 'V', '1', '2'); + break; + case PIX_FMT_NV21: + fmt = GST_MAKE_FOURCC ('N', 'V', '2', '1'); + break; + case PIX_FMT_YVU420P: + fmt = GST_MAKE_FOURCC ('Y', 'V', '1', '2'); + break; + case PIX_FMT_YUV422: + fmt = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); + break; + case PIX_FMT_UYVY422: + fmt = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); + break; + case PIX_FMT_YVYU422: + fmt = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'); + break; + case PIX_FMT_UYVY411: + fmt = GST_MAKE_FOURCC ('I', 'Y', 'U', '1'); + break; + case PIX_FMT_RGB24: + bpp = depth = 24; + endianness = G_BIG_ENDIAN; + r_mask = 0xff0000; + g_mask = 0x00ff00; + b_mask = 0x0000ff; + break; + case PIX_FMT_BGR24: + bpp = depth = 24; + endianness = G_BIG_ENDIAN; + r_mask = 0x0000ff; + g_mask = 0x00ff00; + b_mask = 0xff0000; + break; + case PIX_FMT_YUV422P: + fmt = GST_MAKE_FOURCC ('Y', '4', '2', 'B'); + break; + case PIX_FMT_YUV444P: + fmt = GST_MAKE_FOURCC ('Y', '4', '4', '4'); + break; + case PIX_FMT_RGB32: + bpp = 32; + depth = 24; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x00ff0000; + g_mask = 0x0000ff00; + b_mask = 0x000000ff; +#else + r_mask = 0x0000ff00; + g_mask = 0x00ff0000; + b_mask = 0xff000000; +#endif + break; + case PIX_FMT_BGR32: + bpp = 32; + depth = 24; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x0000ff00; + g_mask = 0x00ff0000; + b_mask = 0xff000000; +#else + r_mask = 0x00ff0000; + g_mask = 0x0000ff00; + b_mask = 0x000000ff; +#endif + break; + case PIX_FMT_xRGB32: + bpp = 32; + depth = 24; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; +#else + r_mask = 0x000000ff; + g_mask = 0x0000ff00; + b_mask = 0x00ff0000; +#endif + break; + case PIX_FMT_BGRx32: + bpp = 32; + depth = 24; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x000000ff; + g_mask = 0x0000ff00; + b_mask = 0x00ff0000; +#else + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; +#endif + break; + case PIX_FMT_RGBA32: + bpp = 32; + depth = 32; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x00ff0000; + g_mask = 0x0000ff00; + b_mask = 0x000000ff; + a_mask = 0xff000000; +#else + r_mask = 0x0000ff00; + g_mask = 0x00ff0000; + b_mask = 0xff000000; + a_mask = 0x000000ff; +#endif + break; + case PIX_FMT_BGRA32: + bpp = 32; + depth = 32; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x0000ff00; + g_mask = 0x00ff0000; + b_mask = 0xff000000; + a_mask = 0x000000ff; +#else + r_mask = 0x00ff0000; + g_mask = 0x0000ff00; + b_mask = 0x000000ff; + a_mask = 0xff000000; +#endif + break; + case PIX_FMT_ARGB32: + bpp = 32; + depth = 32; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; + a_mask = 0x000000ff; +#else + r_mask = 0x000000ff; + g_mask = 0x0000ff00; + b_mask = 0x00ff0000; + a_mask = 0xff000000; +#endif + break; + case PIX_FMT_ABGR32: + bpp = 32; + depth = 32; + endianness = G_BIG_ENDIAN; +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + r_mask = 0x000000ff; + g_mask = 0x0000ff00; + b_mask = 0x00ff0000; + a_mask = 0xff000000; +#else + r_mask = 0xff000000; + g_mask = 0x00ff0000; + b_mask = 0x0000ff00; + a_mask = 0x000000ff; +#endif + break; + case PIX_FMT_YUV410P: + fmt = GST_MAKE_FOURCC ('Y', 'U', 'V', '9'); + break; + case PIX_FMT_YVU410P: + fmt = GST_MAKE_FOURCC ('Y', 'V', 'U', '9'); + break; + case PIX_FMT_YUV411P: + fmt = GST_MAKE_FOURCC ('Y', '4', '1', 'B'); + break; + case PIX_FMT_Y800:{ + GstCaps *tmp; + + caps = gst_ff_vid_caps_new (context, "video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', '8', '0', '0'), + NULL); + tmp = + gst_ff_vid_caps_new (context, "video/x-raw-yuv", "format", + GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', '8', ' ', ' '), NULL); + gst_caps_append (caps, tmp); + tmp = gst_ff_vid_caps_new (context, "video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'), + NULL); + gst_caps_append (caps, tmp); + break; + } + case PIX_FMT_Y16: + fmt = GST_MAKE_FOURCC ('Y', '1', '6', ' '); + break; + case PIX_FMT_RGB565: + bpp = depth = 16; + endianness = G_BYTE_ORDER; + r_mask = 0xf800; + g_mask = 0x07e0; + b_mask = 0x001f; + break; + case PIX_FMT_RGB555: + bpp = 16; + depth = 15; + endianness = G_BYTE_ORDER; + r_mask = 0x7c00; + g_mask = 0x03e0; + b_mask = 0x001f; + break; + case PIX_FMT_PAL8: + bpp = depth = 8; + endianness = G_BYTE_ORDER; + break; + case PIX_FMT_V308: + fmt = GST_MAKE_FOURCC ('v', '3', '0', '8'); + break; + case PIX_FMT_AYUV4444: + fmt = GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'); + break; + case PIX_FMT_GRAY8: + bpp = depth = 8; + caps = gst_ff_vid_caps_new (context, "video/x-raw-gray", + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, NULL); + break; + case PIX_FMT_GRAY16_L: + bpp = depth = 16; + caps = gst_ff_vid_caps_new (context, "video/x-raw-gray", + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL); + break; + case PIX_FMT_GRAY16_B: + bpp = depth = 16; + caps = gst_ff_vid_caps_new (context, "video/x-raw-gray", + "bpp", G_TYPE_INT, bpp, "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL); + break; + default: + /* give up ... */ + break; + } + + if (caps == NULL) { + if (bpp != 0) { + if (a_mask != 0) { + caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "red_mask", G_TYPE_INT, r_mask, + "green_mask", G_TYPE_INT, g_mask, + "blue_mask", G_TYPE_INT, b_mask, + "alpha_mask", G_TYPE_INT, a_mask, + "endianness", G_TYPE_INT, endianness, NULL); + } else if (r_mask != 0) { + caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "red_mask", G_TYPE_INT, r_mask, + "green_mask", G_TYPE_INT, g_mask, + "blue_mask", G_TYPE_INT, b_mask, + "endianness", G_TYPE_INT, endianness, NULL); + } else { + caps = gst_ff_vid_caps_new (context, "video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, endianness, NULL); + if (context && context->pix_fmt == PIX_FMT_PAL8) { + gst_ffmpeg_set_palette (caps, context); + } + } + } else if (fmt) { + caps = gst_ff_vid_caps_new (context, "video/x-raw-yuv", + "format", GST_TYPE_FOURCC, fmt, NULL); + } + } + + if (caps != NULL) { + GST_DEBUG ("caps for pix_fmt=%d: %" GST_PTR_FORMAT, pix_fmt, caps); + } else { + GST_LOG ("No caps found for pix_fmt=%d", pix_fmt); + } + + return caps; +} + +/* Convert a FFMPEG Sample Format and optional AVCodecContext + * to a GstCaps. If the context is ommitted, no fixed values + * for video/audio size will be included in the GstCaps + * + * See below for usefulness + */ + +static GstCaps * +gst_ffmpeg_smpfmt_to_caps (enum SampleFormat sample_fmt, + AVCodecContext * context) +{ + GstCaps *caps = NULL; + + int bpp = 0; + gboolean signedness = FALSE; + + switch (sample_fmt) { + case SAMPLE_FMT_S16: + signedness = TRUE; + bpp = 16; + break; + + default: + /* .. */ + break; + } + + if (bpp) { + caps = gst_ff_aud_caps_new (context, "audio/x-raw-int", + "signed", G_TYPE_BOOLEAN, signedness, + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "width", G_TYPE_INT, bpp, "depth", G_TYPE_INT, bpp, NULL); + } + + if (caps != NULL) { + GST_DEBUG ("caps for sample_fmt=%d: %" GST_PTR_FORMAT, sample_fmt, caps); + } else { + GST_LOG ("No caps found for sample_fmt=%d", sample_fmt); + } + + return caps; +} + +/* Convert a FFMPEG codec Type and optional AVCodecContext + * to a GstCaps. If the context is ommitted, no fixed values + * for video/audio size will be included in the GstCaps + * + * CodecType is primarily meant for uncompressed data GstCaps! + */ + +GstCaps * +gst_ffmpegcsp_codectype_to_caps (enum CodecType codec_type, + AVCodecContext * context) +{ + GstCaps *caps; + + switch (codec_type) { + case CODEC_TYPE_VIDEO: + if (context) { + caps = gst_ffmpeg_pixfmt_to_caps (context->pix_fmt, + context->width == -1 ? NULL : context); + } else { + GstCaps *temp; + enum PixelFormat i; + + caps = gst_caps_new_empty (); + for (i = 0; i < PIX_FMT_NB; i++) { + temp = gst_ffmpeg_pixfmt_to_caps (i, NULL); + if (temp != NULL) { + gst_caps_append (caps, temp); + } + } + } + break; + + case CODEC_TYPE_AUDIO: + if (context) { + caps = gst_ffmpeg_smpfmt_to_caps (context->sample_fmt, context); + } else { + GstCaps *temp; + enum SampleFormat i; + + caps = gst_caps_new_empty (); + for (i = 0; i <= SAMPLE_FMT_S16; i++) { + temp = gst_ffmpeg_smpfmt_to_caps (i, NULL); + if (temp != NULL) { + gst_caps_append (caps, temp); + } + } + } + break; + + default: + /* .. */ + caps = NULL; + break; + } + + return caps; +} + +/* Convert a GstCaps (audio/raw) to a FFMPEG SampleFmt + * and other audio properties in a AVCodecContext. + * + * For usefulness, see below + */ + +static void +gst_ffmpeg_caps_to_smpfmt (const GstCaps * caps, + AVCodecContext * context, gboolean raw) +{ + GstStructure *structure; + gint depth = 0, width = 0, endianness = 0; + gboolean signedness = FALSE; + + g_return_if_fail (gst_caps_get_size (caps) == 1); + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "channels", &context->channels); + gst_structure_get_int (structure, "rate", &context->sample_rate); + + if (!raw) + return; + + if (gst_structure_get_int (structure, "width", &width) && + gst_structure_get_int (structure, "depth", &depth) && + gst_structure_get_boolean (structure, "signed", &signedness) && + gst_structure_get_int (structure, "endianness", &endianness)) { + if (width == 16 && depth == 16 && + endianness == G_BYTE_ORDER && signedness == TRUE) { + context->sample_fmt = SAMPLE_FMT_S16; + } + } +} + + +/* Convert a GstCaps (video/raw) to a FFMPEG PixFmt + * and other video properties in a AVCodecContext. + * + * For usefulness, see below + */ + +static void +gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps, + AVCodecContext * context, gboolean raw) +{ + GstStructure *structure; + const GValue *fps; + gboolean ret; + + g_return_if_fail (gst_caps_get_size (caps) == 1); + structure = gst_caps_get_structure (caps, 0); + + ret = gst_structure_get_int (structure, "width", &context->width); + ret &= gst_structure_get_int (structure, "height", &context->height); + g_return_if_fail (ret == TRUE); + + fps = gst_structure_get_value (structure, "framerate"); + g_return_if_fail (GST_VALUE_HOLDS_FRACTION (fps)); + + /* framerate does not really matter */ + context->frame_rate = gst_value_get_fraction_numerator (fps); + context->frame_rate_base = gst_value_get_fraction_denominator (fps); + + if (!raw) + return; + + if (gst_structure_has_name (structure, "video/x-raw-yuv")) { + guint32 fourcc; + + if (gst_structure_get_fourcc (structure, "format", &fourcc)) { + switch (fourcc) { + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + context->pix_fmt = PIX_FMT_YUV422; + break; + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + context->pix_fmt = PIX_FMT_UYVY422; + break; + case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'): + context->pix_fmt = PIX_FMT_YVYU422; + break; + case GST_MAKE_FOURCC ('I', 'Y', 'U', '1'): + context->pix_fmt = PIX_FMT_UYVY411; + break; + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + context->pix_fmt = PIX_FMT_YUV420P; + break; + case GST_MAKE_FOURCC ('A', '4', '2', '0'): + context->pix_fmt = PIX_FMT_YUVA420P; + break; + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + context->pix_fmt = PIX_FMT_NV12; + break; + case GST_MAKE_FOURCC ('N', 'V', '2', '1'): + context->pix_fmt = PIX_FMT_NV21; + break; + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + context->pix_fmt = PIX_FMT_YVU420P; + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): + context->pix_fmt = PIX_FMT_YUV411P; + break; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + context->pix_fmt = PIX_FMT_YUV422P; + break; + case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'): + context->pix_fmt = PIX_FMT_YUV410P; + break; + case GST_MAKE_FOURCC ('Y', 'V', 'U', '9'): + context->pix_fmt = PIX_FMT_YVU410P; + break; + case GST_MAKE_FOURCC ('v', '3', '0', '8'): + context->pix_fmt = PIX_FMT_V308; + break; + case GST_MAKE_FOURCC ('A', 'Y', 'U', 'V'): + context->pix_fmt = PIX_FMT_AYUV4444; + break; + case GST_MAKE_FOURCC ('Y', '4', '4', '4'): + context->pix_fmt = PIX_FMT_YUV444P; + break; + case GST_MAKE_FOURCC ('Y', '8', '0', '0'): + case GST_MAKE_FOURCC ('Y', '8', ' ', ' '): + case GST_MAKE_FOURCC ('G', 'R', 'E', 'Y'): + context->pix_fmt = PIX_FMT_Y800; + break; + case GST_MAKE_FOURCC ('Y', '1', '6', ' '): + context->pix_fmt = PIX_FMT_Y16; + break; + } + } + } else if (gst_structure_has_name (structure, "video/x-raw-rgb")) { + gint bpp = 0, rmask = 0, endianness = 0, amask = 0, depth = 0; + + if (gst_structure_get_int (structure, "bpp", &bpp) && + gst_structure_get_int (structure, "endianness", &endianness)) { + if (gst_structure_get_int (structure, "red_mask", &rmask)) { + switch (bpp) { + case 32: + if (gst_structure_get_int (structure, "alpha_mask", &amask)) { +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + if (rmask == 0x0000ff00) + context->pix_fmt = PIX_FMT_BGRA32; + else if (rmask == 0x00ff0000) + context->pix_fmt = PIX_FMT_RGBA32; + else if (rmask == 0xff000000) + context->pix_fmt = PIX_FMT_ARGB32; + else // if (r_mask = 0x000000ff) + context->pix_fmt = PIX_FMT_ABGR32; +#else + if (rmask == 0x00ff0000) + context->pix_fmt = PIX_FMT_BGRA32; + else if (rmask == 0x0000ff00) + context->pix_fmt = PIX_FMT_RGBA32; + else if (rmask == 0x000000ff) + context->pix_fmt = PIX_FMT_ARGB32; + else // if (rmask == 0xff000000) + context->pix_fmt = PIX_FMT_ABGR32; +#endif + } else { +#if (G_BYTE_ORDER == G_BIG_ENDIAN) + if (rmask == 0x00ff0000) + context->pix_fmt = PIX_FMT_RGB32; + else if (rmask == 0x0000ff00) + context->pix_fmt = PIX_FMT_BGR32; + else if (rmask == 0xff000000) + context->pix_fmt = PIX_FMT_xRGB32; + else // if (rmask == 0x000000ff) + context->pix_fmt = PIX_FMT_BGRx32; +#else + if (rmask == 0x0000ff00) + context->pix_fmt = PIX_FMT_RGB32; + else if (rmask == 0x00ff0000) + context->pix_fmt = PIX_FMT_BGR32; + else if (rmask == 0x000000ff) + context->pix_fmt = PIX_FMT_xRGB32; + else // if (rmask == 0xff000000) + context->pix_fmt = PIX_FMT_BGRx32; +#endif + } + break; + case 24: + if (rmask == 0x0000FF) + context->pix_fmt = PIX_FMT_BGR24; + else + context->pix_fmt = PIX_FMT_RGB24; + break; + case 16: + if (endianness == G_BYTE_ORDER) { + context->pix_fmt = PIX_FMT_RGB565; + if (gst_structure_get_int (structure, "depth", &depth)) { + if (depth == 15) + context->pix_fmt = PIX_FMT_RGB555; + } + } + break; + case 15: + if (endianness == G_BYTE_ORDER) + context->pix_fmt = PIX_FMT_RGB555; + break; + default: + /* nothing */ + break; + } + } else { + if (bpp == 8) { + context->pix_fmt = PIX_FMT_PAL8; + gst_ffmpeg_get_palette (caps, context); + } + } + } + } else if (gst_structure_has_name (structure, "video/x-raw-gray")) { + gint bpp = 0; + + if (gst_structure_get_int (structure, "bpp", &bpp)) { + switch (bpp) { + case 8: + context->pix_fmt = PIX_FMT_GRAY8; + break; + case 16:{ + gint endianness = 0; + + if (gst_structure_get_int (structure, "endianness", &endianness)) { + if (endianness == G_LITTLE_ENDIAN) + context->pix_fmt = PIX_FMT_GRAY16_L; + else if (endianness == G_BIG_ENDIAN) + context->pix_fmt = PIX_FMT_GRAY16_B; + } + } + break; + } + } + } +} + +/* Convert a GstCaps and a FFMPEG codec Type to a + * AVCodecContext. If the context is ommitted, no fixed values + * for video/audio size will be included in the context + * + * CodecType is primarily meant for uncompressed data GstCaps! + */ + +void +gst_ffmpegcsp_caps_with_codectype (enum CodecType type, + const GstCaps * caps, AVCodecContext * context) +{ + if (context == NULL) + return; + + switch (type) { + case CODEC_TYPE_VIDEO: + gst_ffmpeg_caps_to_pixfmt (caps, context, TRUE); + break; + + case CODEC_TYPE_AUDIO: + gst_ffmpeg_caps_to_smpfmt (caps, context, TRUE); + break; + + default: + /* unknown */ + break; + } +} + +#define GEN_MASK(x) ((1<<(x))-1) +#define ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x)) +#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x)) + +/* + * Fill in pointers to memory in a AVPicture, where + * everything is aligned by 4 (as required by X). + * This is mostly a copy from imgconvert.c with some + * small changes. + */ +int +gst_ffmpegcsp_avpicture_fill (AVPicture * picture, + uint8_t * ptr, enum PixelFormat pix_fmt, int width, int height, + int interlaced) +{ + int size, w2, h2, size2; + int stride, stride2; + PixFmtInfo *pinfo; + + pinfo = get_pix_fmt_info (pix_fmt); + + picture->interlaced = interlaced; + + switch (pix_fmt) { + case PIX_FMT_YUV420P: + case PIX_FMT_YUV422P: + case PIX_FMT_YUV444P: + case PIX_FMT_YUV410P: + case PIX_FMT_YUV411P: + case PIX_FMT_YUVJ420P: + case PIX_FMT_YUVJ422P: + case PIX_FMT_YUVJ444P: + stride = GST_ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = GST_ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + return size + 2 * size2; + /* PIX_FMT_YVU420P = YV12: same as PIX_FMT_YUV420P, but + * with U and V plane swapped. Strides as in videotestsrc */ + case PIX_FMT_YUVA420P: + stride = GST_ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = GST_ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = picture->data[1] + size2; + picture->data[3] = picture->data[2] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + picture->linesize[3] = stride; + return 2 * size + 2 * size2; + case PIX_FMT_YVU410P: + case PIX_FMT_YVU420P: + stride = GST_ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = GST_ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + picture->data[0] = ptr; + picture->data[2] = picture->data[0] + size; + picture->data[1] = picture->data[2] + size2; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = stride2; + return size + 2 * size2; + case PIX_FMT_NV12: + case PIX_FMT_NV21: + stride = GST_ROUND_UP_4 (width); + h2 = ROUND_UP_X (height, pinfo->y_chroma_shift); + size = stride * h2; + w2 = 2 * DIV_ROUND_UP_X (width, pinfo->x_chroma_shift); + stride2 = GST_ROUND_UP_4 (w2); + h2 = DIV_ROUND_UP_X (height, pinfo->y_chroma_shift); + size2 = stride2 * h2; + picture->data[0] = ptr; + picture->data[1] = picture->data[0] + size; + picture->data[2] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = stride2; + picture->linesize[2] = 0; + return size + size2; + case PIX_FMT_RGB24: + case PIX_FMT_BGR24: + stride = GST_ROUND_UP_4 (width * 3); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_AYUV4444: + case PIX_FMT_RGB32: + case PIX_FMT_RGBA32: + case PIX_FMT_ARGB32: + case PIX_FMT_BGR32: + case PIX_FMT_BGRA32: + case PIX_FMT_ABGR32: + case PIX_FMT_xRGB32: + case PIX_FMT_BGRx32: + stride = width * 4; + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_RGB555: + case PIX_FMT_RGB565: + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YVYU422: + stride = GST_ROUND_UP_4 (width * 2); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_V308: + stride = GST_ROUND_UP_4 (width * 3); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_UYVY411: + stride = + GST_ROUND_UP_4 (GST_ROUND_UP_4 (width) + GST_ROUND_UP_4 (width) / 2); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_Y800: + case PIX_FMT_GRAY8: + stride = GST_ROUND_UP_4 (width); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_Y16: + case PIX_FMT_GRAY16_L: + case PIX_FMT_GRAY16_B: + stride = GST_ROUND_UP_4 (width * 2); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_MONOWHITE: + case PIX_FMT_MONOBLACK: + stride = GST_ROUND_UP_4 ((width + 7) >> 3); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->linesize[0] = stride; + return size; + case PIX_FMT_PAL8: + /* already forced to be with stride, so same result as other function */ + stride = GST_ROUND_UP_4 (width); + size = stride * height; + picture->data[0] = ptr; + picture->data[1] = ptr + size; /* palette is stored here as 256 32 bit words */ + picture->data[2] = NULL; + picture->linesize[0] = stride; + picture->linesize[1] = 4; + return size + 256 * 4; + default: + picture->data[0] = NULL; + picture->data[1] = NULL; + picture->data[2] = NULL; + picture->data[3] = NULL; + return -1; + } + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.h b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.h new file mode 100644 index 0000000..077fe3f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcodecmap.h @@ -0,0 +1,58 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFMPEG_CODECMAP_H__ +#define __GST_FFMPEG_CODECMAP_H__ + +#include "avcodec.h" +#include + +/* + * _codectype_to_caps () gets the GstCaps that belongs to + * a certain CodecType for a pad with uncompressed data. + */ + +GstCaps * +gst_ffmpegcsp_codectype_to_caps (enum CodecType codec_type, + AVCodecContext *context); + +/* + * caps_with_codectype () transforms a GstCaps that belongs to + * a pad for uncompressed data to a filled-in context. + */ + +void +gst_ffmpegcsp_caps_with_codectype (enum CodecType type, + const GstCaps *caps, + AVCodecContext *context); + +/* + * Fill in pointers in an AVPicture, aligned by 4 (required by X). + */ + +int +gst_ffmpegcsp_avpicture_fill (AVPicture * picture, + uint8_t * ptr, + enum PixelFormat pix_fmt, + int width, + int height, + int interlaced); + +#endif /* __GST_FFMPEG_CODECMAP_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.c new file mode 100644 index 0000000..4ba0204 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.c @@ -0,0 +1,517 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * This file: + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-ffmpegcolorspace + * + * Convert video frames between a great variety of colorspace formats. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc ! video/x-raw-yuv,format=\(fourcc\)YUY2 ! ffmpegcolorspace ! ximagesink + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstffmpegcolorspace.h" +#include "gstffmpegcodecmap.h" +#include + +GST_DEBUG_CATEGORY (ffmpegcolorspace_debug); +#define GST_CAT_DEFAULT ffmpegcolorspace_debug +GST_DEBUG_CATEGORY (ffmpegcolorspace_performance); + +#define FFMPEGCSP_VIDEO_CAPS \ + "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ + "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ + "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, A420} ;" \ + GST_VIDEO_CAPS_RGB";" \ + GST_VIDEO_CAPS_BGR";" \ + GST_VIDEO_CAPS_RGBx";" \ + GST_VIDEO_CAPS_xRGB";" \ + GST_VIDEO_CAPS_BGRx";" \ + GST_VIDEO_CAPS_xBGR";" \ + GST_VIDEO_CAPS_RGBA";" \ + GST_VIDEO_CAPS_ARGB";" \ + GST_VIDEO_CAPS_BGRA";" \ + GST_VIDEO_CAPS_ABGR";" \ + GST_VIDEO_CAPS_RGB_16";" \ + GST_VIDEO_CAPS_RGB_15";" \ + "video/x-raw-rgb, bpp = (int)8, depth = (int)8, " \ + "width = "GST_VIDEO_SIZE_RANGE" , " \ + "height = " GST_VIDEO_SIZE_RANGE ", " \ + "framerate = "GST_VIDEO_FPS_RANGE ";" \ + GST_VIDEO_CAPS_GRAY8";" \ + GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \ + GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" + +static GstStaticPadTemplate gst_ffmpegcsp_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (FFMPEGCSP_VIDEO_CAPS) + ); + +static GstStaticPadTemplate gst_ffmpegcsp_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (FFMPEGCSP_VIDEO_CAPS) + ); + +GType gst_ffmpegcsp_get_type (void); + +static gboolean gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, + GstCaps * incaps, GstCaps * outcaps); +static gboolean gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, + GstCaps * caps, guint * size); +static GstFlowReturn gst_ffmpegcsp_transform (GstBaseTransform * btrans, + GstBuffer * inbuf, GstBuffer * outbuf); + +static GQuark _QRAWRGB; /* "video/x-raw-rgb" */ +static GQuark _QRAWYUV; /* "video/x-raw-yuv" */ +static GQuark _QALPHAMASK; /* "alpha_mask" */ + +/* copies the given caps */ +static GstCaps * +gst_ffmpegcsp_caps_remove_format_info (GstCaps * caps) +{ + GstStructure *yuvst, *rgbst, *grayst; + + /* We know there's only one structure since we're given simple caps */ + caps = gst_caps_copy (caps); + + yuvst = gst_caps_get_structure (caps, 0); + + gst_structure_set_name (yuvst, "video/x-raw-yuv"); + gst_structure_remove_fields (yuvst, "format", "endianness", "depth", + "bpp", "red_mask", "green_mask", "blue_mask", "alpha_mask", + "palette_data", NULL); + + rgbst = gst_structure_copy (yuvst); + gst_structure_set_name (rgbst, "video/x-raw-rgb"); + gst_structure_remove_fields (rgbst, "color-matrix", "chroma-site", NULL); + + grayst = gst_structure_copy (rgbst); + gst_structure_set_name (grayst, "video/x-raw-gray"); + + gst_caps_append_structure (caps, rgbst); + gst_caps_append_structure (caps, grayst); + + return caps; +} + + +static gboolean +gst_ffmpegcsp_structure_is_alpha (GstStructure * s) +{ + GQuark name; + + name = gst_structure_get_name_id (s); + + if (name == _QRAWRGB) { + return gst_structure_id_has_field (s, _QALPHAMASK); + } else if (name == _QRAWYUV) { + guint32 fourcc; + + if (!gst_structure_get_fourcc (s, "format", &fourcc)) + return FALSE; + + return (fourcc == GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')); + } + + return FALSE; +} + +/* The caps can be transformed into any other caps with format info removed. + * However, we should prefer passthrough, so if passthrough is possible, + * put it first in the list. */ +static GstCaps * +gst_ffmpegcsp_transform_caps (GstBaseTransform * btrans, + GstPadDirection direction, GstCaps * caps) +{ + GstCaps *template; + GstCaps *tmp, *tmp2; + GstCaps *result; + GstStructure *s; + GstCaps *alpha, *non_alpha; + + template = gst_static_pad_template_get_caps (&gst_ffmpegcsp_src_template); + result = gst_caps_copy (caps); + + /* Get all possible caps that we can transform to */ + tmp = gst_ffmpegcsp_caps_remove_format_info (caps); + tmp2 = gst_caps_intersect (tmp, template); + gst_caps_unref (tmp); + tmp = tmp2; + + /* Now move alpha formats to the beginning if caps is an alpha format + * or at the end if caps is no alpha format */ + alpha = gst_caps_new_empty (); + non_alpha = gst_caps_new_empty (); + + while ((s = gst_caps_steal_structure (tmp, 0))) { + if (gst_ffmpegcsp_structure_is_alpha (s)) + gst_caps_append_structure (alpha, s); + else + gst_caps_append_structure (non_alpha, s); + } + + s = gst_caps_get_structure (caps, 0); + gst_caps_unref (tmp); + + if (gst_ffmpegcsp_structure_is_alpha (s)) { + gst_caps_append (alpha, non_alpha); + tmp = alpha; + } else { + gst_caps_append (non_alpha, alpha); + tmp = non_alpha; + } + + gst_caps_append (result, tmp); + + GST_DEBUG_OBJECT (btrans, "transformed %" GST_PTR_FORMAT " into %" + GST_PTR_FORMAT, caps, result); + + return result; +} + +static gboolean +gst_ffmpegcsp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, + GstCaps * outcaps) +{ + GstFFMpegCsp *space; + GstStructure *structure; + gint in_height, in_width; + gint out_height, out_width; + const GValue *in_framerate = NULL; + const GValue *out_framerate = NULL; + const GValue *in_par = NULL; + const GValue *out_par = NULL; + AVCodecContext *ctx; + gboolean res; + + space = GST_FFMPEGCSP (btrans); + + /* parse in and output values */ + structure = gst_caps_get_structure (incaps, 0); + + /* we have to have width and height */ + res = gst_structure_get_int (structure, "width", &in_width); + res &= gst_structure_get_int (structure, "height", &in_height); + if (!res) + goto no_width_height; + + /* and framerate */ + in_framerate = gst_structure_get_value (structure, "framerate"); + if (in_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (in_framerate)) + goto no_framerate; + + /* this is optional */ + in_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + + structure = gst_caps_get_structure (outcaps, 0); + + /* we have to have width and height */ + res = gst_structure_get_int (structure, "width", &out_width); + res &= gst_structure_get_int (structure, "height", &out_height); + if (!res) + goto no_width_height; + + /* and framerate */ + out_framerate = gst_structure_get_value (structure, "framerate"); + if (out_framerate == NULL || !GST_VALUE_HOLDS_FRACTION (out_framerate)) + goto no_framerate; + + /* this is optional */ + out_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + + /* these must match */ + if (in_width != out_width || in_height != out_height || + gst_value_compare (in_framerate, out_framerate) != GST_VALUE_EQUAL) + goto format_mismatch; + + /* if present, these must match too */ + if (in_par && out_par + && gst_value_compare (in_par, out_par) != GST_VALUE_EQUAL) + goto format_mismatch; + + ctx = avcodec_alloc_context (); + + space->width = ctx->width = in_width; + space->height = ctx->height = in_height; + + space->interlaced = FALSE; + gst_structure_get_boolean (structure, "interlaced", &space->interlaced); + + /* get from format */ + ctx->pix_fmt = PIX_FMT_NB; + gst_ffmpegcsp_caps_with_codectype (CODEC_TYPE_VIDEO, incaps, ctx); + if (ctx->pix_fmt == PIX_FMT_NB) + goto invalid_in_caps; + space->from_pixfmt = ctx->pix_fmt; + + /* palette, only for from data */ + if (space->palette) + av_free (space->palette); + space->palette = ctx->palctrl; + ctx->palctrl = NULL; + + /* get to format */ + ctx->pix_fmt = PIX_FMT_NB; + gst_ffmpegcsp_caps_with_codectype (CODEC_TYPE_VIDEO, outcaps, ctx); + if (ctx->pix_fmt == PIX_FMT_NB) + goto invalid_out_caps; + space->to_pixfmt = ctx->pix_fmt; + + GST_DEBUG ("reconfigured %d %d", space->from_pixfmt, space->to_pixfmt); + + av_free (ctx); + + return TRUE; + + /* ERRORS */ +no_width_height: + { + GST_DEBUG_OBJECT (space, "did not specify width or height"); + space->from_pixfmt = PIX_FMT_NB; + space->to_pixfmt = PIX_FMT_NB; + return FALSE; + } +no_framerate: + { + GST_DEBUG_OBJECT (space, "did not specify framerate"); + space->from_pixfmt = PIX_FMT_NB; + space->to_pixfmt = PIX_FMT_NB; + return FALSE; + } +format_mismatch: + { + GST_DEBUG_OBJECT (space, "input and output formats do not match"); + space->from_pixfmt = PIX_FMT_NB; + space->to_pixfmt = PIX_FMT_NB; + return FALSE; + } +invalid_in_caps: + { + GST_DEBUG_OBJECT (space, "could not configure context for input format"); + av_free (ctx); + space->from_pixfmt = PIX_FMT_NB; + space->to_pixfmt = PIX_FMT_NB; + return FALSE; + } +invalid_out_caps: + { + GST_DEBUG_OBJECT (space, "could not configure context for output format"); + av_free (ctx); + space->from_pixfmt = PIX_FMT_NB; + space->to_pixfmt = PIX_FMT_NB; + return FALSE; + } +} + +GST_BOILERPLATE (GstFFMpegCsp, gst_ffmpegcsp, GstVideoFilter, + GST_TYPE_VIDEO_FILTER); + +static void +gst_ffmpegcsp_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ffmpegcsp_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ffmpegcsp_sink_template)); + + gst_element_class_set_details_simple (element_class, + "FFMPEG Colorspace converter", "Filter/Converter/Video", + "Converts video from one colorspace to another", + "GStreamer maintainers "); + + _QRAWRGB = g_quark_from_string ("video/x-raw-rgb"); + _QRAWYUV = g_quark_from_string ("video/x-raw-yuv"); + _QALPHAMASK = g_quark_from_string ("alpha_mask"); +} + +static void +gst_ffmpegcsp_finalize (GObject * obj) +{ + GstFFMpegCsp *space = GST_FFMPEGCSP (obj); + + if (space->palette) + av_free (space->palette); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_ffmpegcsp_class_init (GstFFMpegCspClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseTransformClass *gstbasetransform_class = + (GstBaseTransformClass *) klass; + + gobject_class->finalize = gst_ffmpegcsp_finalize; + + gstbasetransform_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_ffmpegcsp_transform_caps); + gstbasetransform_class->set_caps = GST_DEBUG_FUNCPTR (gst_ffmpegcsp_set_caps); + gstbasetransform_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_ffmpegcsp_get_unit_size); + gstbasetransform_class->transform = + GST_DEBUG_FUNCPTR (gst_ffmpegcsp_transform); + + gstbasetransform_class->passthrough_on_same_caps = TRUE; +} + +static void +gst_ffmpegcsp_init (GstFFMpegCsp * space, GstFFMpegCspClass * klass) +{ + space->from_pixfmt = space->to_pixfmt = PIX_FMT_NB; + space->palette = NULL; +} + +static gboolean +gst_ffmpegcsp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, + guint * size) +{ + GstStructure *structure = NULL; + AVCodecContext *ctx = NULL; + gboolean ret = TRUE; + gint width, height; + + g_assert (size); + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + + ctx = avcodec_alloc_context (); + + g_assert (ctx != NULL); + + ctx->pix_fmt = PIX_FMT_NB; + + gst_ffmpegcsp_caps_with_codectype (CODEC_TYPE_VIDEO, caps, ctx); + + if (G_UNLIKELY (ctx->pix_fmt == PIX_FMT_NB)) { + ret = FALSE; + goto beach; + } + + *size = avpicture_get_size (ctx->pix_fmt, width, height); + + /* ffmpeg frames have the palette after the frame data, whereas + * GStreamer currently puts it into the caps as 'palette_data' field, + * so for paletted data the frame size avpicture_get_size() returns is + * 1024 bytes larger than what GStreamer expects. */ + if (gst_structure_has_field (structure, "palette_data") && + ctx->pix_fmt == PIX_FMT_PAL8) { + *size -= 4 * 256; /* = AVPALETTE_SIZE */ + } + +beach: + + if (ctx->palctrl) + av_free (ctx->palctrl); + av_free (ctx); + + return ret; +} + +static GstFlowReturn +gst_ffmpegcsp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, + GstBuffer * outbuf) +{ + GstFFMpegCsp *space; + gint result; + + space = GST_FFMPEGCSP (btrans); + + GST_DEBUG ("from %d -> to %d", space->from_pixfmt, space->to_pixfmt); + + if (G_UNLIKELY (space->from_pixfmt == PIX_FMT_NB || + space->to_pixfmt == PIX_FMT_NB)) + goto unknown_format; + + /* fill from with source data */ + gst_ffmpegcsp_avpicture_fill (&space->from_frame, + GST_BUFFER_DATA (inbuf), space->from_pixfmt, space->width, space->height, + space->interlaced); + + /* fill optional palette */ + if (space->palette) + space->from_frame.data[1] = (uint8_t *) space->palette->palette; + + /* fill target frame */ + gst_ffmpegcsp_avpicture_fill (&space->to_frame, + GST_BUFFER_DATA (outbuf), space->to_pixfmt, space->width, space->height, + space->interlaced); + + /* and convert */ + result = img_convert (&space->to_frame, space->to_pixfmt, + &space->from_frame, space->from_pixfmt, space->width, space->height); + if (result == -1) + goto not_supported; + + /* baseclass copies timestamps */ + GST_DEBUG ("from %d -> to %d done", space->from_pixfmt, space->to_pixfmt); + + return GST_FLOW_OK; + + /* ERRORS */ +unknown_format: + { + GST_ELEMENT_ERROR (space, CORE, NOT_IMPLEMENTED, (NULL), + ("attempting to convert colorspaces between unknown formats")); + return GST_FLOW_NOT_NEGOTIATED; + } +not_supported: + { + GST_ELEMENT_ERROR (space, CORE, NOT_IMPLEMENTED, (NULL), + ("cannot convert between formats")); + return GST_FLOW_NOT_SUPPORTED; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (ffmpegcolorspace_debug, "ffmpegcolorspace", 0, + "FFMPEG-based colorspace converter"); + GST_DEBUG_CATEGORY_GET (ffmpegcolorspace_performance, "GST_PERFORMANCE"); + + avcodec_init (); + + return gst_element_register (plugin, "ffmpegcolorspace", + GST_RANK_NONE, GST_TYPE_FFMPEGCSP); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "ffmpegcolorspace", + "colorspace conversion copied from FFMpeg " FFMPEG_VERSION, + plugin_init, VERSION, "LGPL", "FFMpeg", "http://ffmpeg.sourceforge.net/") diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.h b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.h new file mode 100644 index 0000000..198ab8a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/gstffmpegcolorspace.h @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * This file: + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_FFMPEGCOLORSPACE_H__ +#define __GST_FFMPEGCOLORSPACE_H__ + +#include +#include +#include "avcodec.h" + +G_BEGIN_DECLS + +#define GST_TYPE_FFMPEGCSP (gst_ffmpegcsp_get_type()) +#define GST_FFMPEGCSP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FFMPEGCSP,GstFFMpegCsp)) +#define GST_FFMPEGCSP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FFMPEGCSP,GstFFMpegCspClass)) +#define GST_IS_FFMPEGCSP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FFMPEGCSP)) +#define GST_IS_FFMPEGCSP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FFMPEGCSP)) + +typedef struct _GstFFMpegCsp GstFFMpegCsp; +typedef struct _GstFFMpegCspClass GstFFMpegCspClass; + +/** + * GstFFMpegCsp: + * + * Opaque object data structure. + */ +struct _GstFFMpegCsp { + GstVideoFilter element; + + gint width, height; + gboolean interlaced; + gfloat fps; + enum PixelFormat from_pixfmt, to_pixfmt; + AVPicture from_frame, to_frame; + AVPaletteControl *palette; +}; + +struct _GstFFMpegCspClass +{ + GstVideoFilterClass parent_class; +}; + +G_END_DECLS + +#endif /* __GST_FFMPEGCOLORSPACE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c new file mode 100644 index 0000000..cb145bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert.c @@ -0,0 +1,4126 @@ +/* + * Misc image convertion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file imgconvert.c + * Misc image convertion routines. + */ + +/* TODO: + * - write 'ffimg' program to test all the image related stuff + * - move all api to slice based system + * - integrate deinterlacing, postprocessing and scaling in the conversion process + */ + +#include "avcodec.h" +#include "dsputil.h" +#include "gstffmpegcodecmap.h" + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (ffmpegcolorspace_performance); + +#define xglue(x, y) x ## y +#define glue(x, y) xglue(x, y) + +/* this table gives more information about formats */ +/* FIXME, this table is also in ffmpegcodecmap */ +static PixFmtInfo pix_fmt_info[PIX_FMT_NB] = { + /* YUV formats */ + /* [PIX_FMT_YUV420P] = */ { + /* .format = */ PIX_FMT_YUV420P, + /* .name = */ "yuv420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVU420P] = */ { + /* .format = */ PIX_FMT_YVU420P, + /* .name = */ "yvu420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_NV12] = */ { + /* .format = */ PIX_FMT_NV12, + /* .name = */ "nv12", + /* .nb_channels = */ 2, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_NV21] = */ { + /* .format = */ PIX_FMT_NV21, + /* .name = */ "nv21", + /* .nb_channels = */ 2, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV422P] = */ { + /* .format = */ PIX_FMT_YUV422P, + /* .name = */ "yuv422p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV444P] = */ { + /* .format = */ PIX_FMT_YUV444P, + /* .name = */ "yuv444p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV422] = */ { + /* .format = */ PIX_FMT_YUV422, + /* .name = */ "yuv422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_UYVY422] = */ { + /* .format = */ PIX_FMT_UYVY422, + /* .name = */ "uyvy422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVYU422] = */ { + /* .format = */ PIX_FMT_YVYU422, + /* .name = */ "yvyu422", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_V308] = */ { + /* .format = */ PIX_FMT_V308, + /* .name = */ "v308", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV410P] = */ { + /* .format = */ PIX_FMT_YUV410P, + /* .name = */ "yuv410p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 2, + /* .depth = */ 8, + }, + /* [PIX_FMT_YVU410P] = */ { + /* .format = */ PIX_FMT_YVU410P, + /* .name = */ "yvu410p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 2, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUV411P] = */ { + /* .format = */ PIX_FMT_YUV411P, + /* .name = */ "yuv411p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_Y800] = */ { + /* .format = */ PIX_FMT_Y800, + /* .name = */ "y800", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_Y16] = */ { + /* .format = */ PIX_FMT_Y16, + /* .name = */ "y16", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + + /* JPEG YUV */ + /* [PIX_FMT_YUVJ420P] = */ { + /* .format = */ PIX_FMT_YUVJ420P, + /* .name = */ "yuvj420p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUVJ422P] = */ { + /* .format = */ PIX_FMT_YUVJ422P, + /* .name = */ "yuvj422p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_YUVJ444P] = */ { + /* .format = */ PIX_FMT_YUVJ444P, + /* .name = */ "yuvj444p", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_YUV_JPEG, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + + /* RGB formats */ + /* [PIX_FMT_RGB24] = */ { + /* .format = */ PIX_FMT_RGB24, + /* .name = */ "rgb24", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR24] = */ { + /* .format = */ PIX_FMT_BGR24, + /* .name = */ "bgr24", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB32] = */ { + /* .format = */ PIX_FMT_RGB32, + /* .name = */ "rgb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR32] = */ { + /* .format = */ PIX_FMT_BGR32, + /* .name = */ "bgr32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB32] = */ { + /* .format = */ PIX_FMT_xRGB32, + /* .name = */ "xrgb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGR32] = */ { + /* .format = */ PIX_FMT_BGRx32, + /* .name = */ "bgrx32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGBA32] = */ { + /* .format = */ PIX_FMT_RGBA32, + /* .name = */ "rgba32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_BGRA32] = */ { + /* .format = */ PIX_FMT_BGRA32, + /* .name = */ "bgra32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_ARGB32] = */ { + /* .format = */ PIX_FMT_ARGB32, + /* .name = */ "argb32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_ABGR32] = */ { + /* .format = */ PIX_FMT_ABGR32, + /* .name = */ "abgr32", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_RGB565] = */ { + /* .format = */ PIX_FMT_RGB565, + /* .name = */ "rgb565", + /* .nb_channels = */ 3, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 5, + }, + /* [PIX_FMT_RGB555] = */ { + /* .format = */ PIX_FMT_RGB555, + /* .name = */ "rgb555", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 5, + }, + + /* gray / mono formats */ + /* [PIX_FMT_GRAY8] = */ { + /* .format = */ PIX_FMT_GRAY8, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_GRAY16_L] = */ { + /* .format = */ PIX_FMT_GRAY16_L, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + /* [PIX_FMT_GRAY16_B] = */ { + /* .format = */ PIX_FMT_GRAY16_B, + /* .name = */ "gray", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 16, + }, + /* [PIX_FMT_MONOWHITE] = */ { + /* .format = */ PIX_FMT_MONOWHITE, + /* .name = */ "monow", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 1, + }, + /* [PIX_FMT_MONOBLACK] = */ { + /* .format = */ PIX_FMT_MONOBLACK, + /* .name = */ "monob", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_GRAY, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 1, + }, + + /* paletted formats */ + /* [PIX_FMT_PAL8] = */ { + /* .format = */ PIX_FMT_PAL8, + /* .name = */ "pal8", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_RGB, + /* .pixel_type = */ FF_PIXEL_PALETTE, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_XVMC_MPEG2_MC] = */ { + /* .format = */ PIX_FMT_XVMC_MPEG2_MC, + /* .name = */ "xvmcmc", + }, + /* [PIX_FMT_XVMC_MPEG2_IDCT] = */ { + /* .format = */ PIX_FMT_XVMC_MPEG2_IDCT, + /* .name = */ "xvmcidct", + }, + /* [PIX_FMT_UYVY411] = */ { + /* .format = */ PIX_FMT_UYVY411, + /* .name = */ "uyvy411", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 0, + /* .x_chroma_shift = */ 2, + /* .y_chroma_shift = */ 0, + /* .depth = */ 8, + }, + /* [PIX_FMT_AYUV4444] = */ { + /* .format = */ PIX_FMT_AYUV4444, + /* .name = */ "ayuv4444", + /* .nb_channels = */ 1, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PACKED, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 0, + /* .y_chroma_shift = */ 0, + /*.depth = */ 8 + }, + /* [PIX_FMT_YUVA420P] = */ { + /* .format = */ PIX_FMT_YUVA420P, + /* .name = */ "yuva420p", + /* .nb_channels = */ 4, + /* .color_type = */ FF_COLOR_YUV, + /* .pixel_type = */ FF_PIXEL_PLANAR, + /* .is_alpha = */ 1, + /* .x_chroma_shift = */ 1, + /* .y_chroma_shift = */ 1, + /* .depth = */ 8, + } +}; + +/* returns NULL if not found */ +/* undid static since this is also used in gstffmpegcodecmap.c */ +PixFmtInfo * +get_pix_fmt_info (enum PixelFormat format) +{ + int i; + + for (i = 0; i < sizeof (pix_fmt_info) / sizeof (pix_fmt_info[0]); i++) { + if (pix_fmt_info[i].format == format) { + return pix_fmt_info + i; + } + } + + /* since this doesn't get checked *anywhere*, we might as well warn + here if we return NULL so you have *some* idea what's going on */ + g_warning + ("Could not find info for pixel format %d out of %d known pixel formats. One segfault coming up", + format, PIX_FMT_NB); + return NULL; +} + +void +avcodec_get_chroma_sub_sample (int pix_fmt, int *h_shift, int *v_shift) +{ + *h_shift = get_pix_fmt_info (pix_fmt)->x_chroma_shift; + *v_shift = get_pix_fmt_info (pix_fmt)->y_chroma_shift; +} + +const char * +avcodec_get_pix_fmt_name (int pix_fmt) +{ + if (pix_fmt < 0 || pix_fmt >= PIX_FMT_NB) + return "???"; + else + return get_pix_fmt_info (pix_fmt)->name; +} + +enum PixelFormat +avcodec_get_pix_fmt (const char *name) +{ + int i; + + for (i = 0; i < PIX_FMT_NB; i++) + if (!strcmp (pix_fmt_info[i].name, name)) + break; + return pix_fmt_info[i].format; +} + +#if 0 +static int +avpicture_layout (const AVPicture * src, int pix_fmt, int width, int height, + unsigned char *dest, int dest_size) +{ + PixFmtInfo *pf = get_pix_fmt_info (pix_fmt); + int i, j, w, h, data_planes; + const unsigned char *s; + int size = avpicture_get_size (pix_fmt, width, height); + + if (size > dest_size) + return -1; + + if (pf->pixel_type == FF_PIXEL_PACKED || pf->pixel_type == FF_PIXEL_PALETTE) { + if (pix_fmt == PIX_FMT_YUV422 || + pix_fmt == PIX_FMT_UYVY422 || + pix_fmt == PIX_FMT_RGB565 || pix_fmt == PIX_FMT_RGB555) + w = width * 2; + else if (pix_fmt == PIX_FMT_UYVY411) + w = width + width / 2; + else if (pix_fmt == PIX_FMT_PAL8) + w = width; + else + w = width * (pf->depth * pf->nb_channels / 8); + + data_planes = 1; + h = height; + } else { + data_planes = pf->nb_channels; + w = (width * pf->depth + 7) / 8; + h = height; + } + + for (i = 0; i < data_planes; i++) { + if (i == 1) { + w = width >> pf->x_chroma_shift; + h = height >> pf->y_chroma_shift; + } + s = src->data[i]; + for (j = 0; j < h; j++) { + memcpy (dest, s, w); + dest += w; + s += src->linesize[i]; + } + } + + if (pf->pixel_type == FF_PIXEL_PALETTE) + memcpy ((unsigned char *) (((size_t) dest + 3) & ~3), src->data[1], + 256 * 4); + + return size; +} +#endif + +int +avpicture_get_size (int pix_fmt, int width, int height) +{ + AVPicture dummy_pict; + + return gst_ffmpegcsp_avpicture_fill (&dummy_pict, NULL, pix_fmt, width, + height, FALSE); +} + +/** + * compute the loss when converting from a pixel format to another + */ +int +avcodec_get_pix_fmt_loss (int dst_pix_fmt, int src_pix_fmt, int has_alpha) +{ + const PixFmtInfo *pf, *ps; + int loss; + + ps = get_pix_fmt_info (src_pix_fmt); + pf = get_pix_fmt_info (dst_pix_fmt); + + /* compute loss */ + loss = 0; + if (pf->depth < ps->depth || + (dst_pix_fmt == PIX_FMT_RGB555 && src_pix_fmt == PIX_FMT_RGB565)) + loss |= FF_LOSS_DEPTH; + if (pf->x_chroma_shift > ps->x_chroma_shift || + pf->y_chroma_shift > ps->y_chroma_shift) + loss |= FF_LOSS_RESOLUTION; + switch (pf->color_type) { + case FF_COLOR_RGB: + if (ps->color_type != FF_COLOR_RGB && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_GRAY: + if (ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV: + if (ps->color_type != FF_COLOR_YUV) + loss |= FF_LOSS_COLORSPACE; + break; + case FF_COLOR_YUV_JPEG: + if (ps->color_type != FF_COLOR_YUV_JPEG && + ps->color_type != FF_COLOR_YUV && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_COLORSPACE; + break; + default: + /* fail safe test */ + if (ps->color_type != pf->color_type) + loss |= FF_LOSS_COLORSPACE; + break; + } + if (pf->color_type == FF_COLOR_GRAY && ps->color_type != FF_COLOR_GRAY) + loss |= FF_LOSS_CHROMA; + if (!pf->is_alpha && (ps->is_alpha && has_alpha)) + loss |= FF_LOSS_ALPHA; + if (pf->pixel_type == FF_PIXEL_PALETTE && + (ps->pixel_type != FF_PIXEL_PALETTE && ps->color_type != FF_COLOR_GRAY)) + loss |= FF_LOSS_COLORQUANT; + return loss; +} + +static int +avg_bits_per_pixel (int pix_fmt) +{ + int bits; + const PixFmtInfo *pf; + + pf = get_pix_fmt_info (pix_fmt); + switch (pf->pixel_type) { + case FF_PIXEL_PACKED: + switch (pix_fmt) { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YVYU422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth * pf->nb_channels; + break; + } + break; + case FF_PIXEL_PLANAR: + if (pf->x_chroma_shift == 0 && pf->y_chroma_shift == 0) { + bits = pf->depth * pf->nb_channels; + } else { + bits = pf->depth + ((2 * pf->depth) >> + (pf->x_chroma_shift + pf->y_chroma_shift)); + } + break; + case FF_PIXEL_PALETTE: + bits = 8; + break; + default: + bits = -1; + break; + } + return bits; +} + +static int +avcodec_find_best_pix_fmt1 (int pix_fmt_mask, + int src_pix_fmt, int has_alpha, int loss_mask) +{ + int dist, i, loss, min_dist, dst_pix_fmt; + + /* find exact color match with smallest size */ + dst_pix_fmt = -1; + min_dist = 0x7fffffff; + for (i = 0; i < PIX_FMT_NB; i++) { + if (pix_fmt_mask & (1 << i)) { + loss = avcodec_get_pix_fmt_loss (i, src_pix_fmt, has_alpha) & loss_mask; + if (loss == 0) { + dist = avg_bits_per_pixel (i); + if (dist < min_dist) { + min_dist = dist; + dst_pix_fmt = i; + } + } + } + } + return dst_pix_fmt; +} + +/** + * find best pixel format to convert to. Return -1 if none found + */ +int +avcodec_find_best_pix_fmt (int pix_fmt_mask, int src_pix_fmt, + int has_alpha, int *loss_ptr) +{ + int dst_pix_fmt, loss_mask, i; + static const int loss_mask_order[] = { + ~0, /* no loss first */ + ~FF_LOSS_ALPHA, + ~FF_LOSS_RESOLUTION, + ~(FF_LOSS_COLORSPACE | FF_LOSS_RESOLUTION), + ~FF_LOSS_COLORQUANT, + ~FF_LOSS_DEPTH, + 0, + }; + + /* try with successive loss */ + i = 0; + for (;;) { + loss_mask = loss_mask_order[i++]; + dst_pix_fmt = avcodec_find_best_pix_fmt1 (pix_fmt_mask, src_pix_fmt, + has_alpha, loss_mask); + if (dst_pix_fmt >= 0) + goto found; + if (loss_mask == 0) + break; + } + return -1; +found: + if (loss_ptr) + *loss_ptr = avcodec_get_pix_fmt_loss (dst_pix_fmt, src_pix_fmt, has_alpha); + return dst_pix_fmt; +} + +static void +img_copy_plane (uint8_t * dst, int dst_wrap, + const uint8_t * src, int src_wrap, int width, int height) +{ + for (; height > 0; height--) { + memcpy (dst, src, width); + dst += dst_wrap; + src += src_wrap; + } +} + +/** + * Copy image 'src' to 'dst'. + */ +static void +img_copy (AVPicture * dst, const AVPicture * src, + int pix_fmt, int width, int height) +{ + int bwidth, bits, i; + const PixFmtInfo *pf; + + pf = get_pix_fmt_info (pix_fmt); + switch (pf->pixel_type) { + case FF_PIXEL_PACKED: + switch (pix_fmt) { + case PIX_FMT_YUV422: + case PIX_FMT_UYVY422: + case PIX_FMT_YVYU422: + case PIX_FMT_RGB565: + case PIX_FMT_RGB555: + bits = 16; + break; + case PIX_FMT_UYVY411: + bits = 12; + break; + default: + bits = pf->depth * pf->nb_channels; + break; + } + bwidth = (width * bits + 7) >> 3; + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], bwidth, height); + break; + case FF_PIXEL_PLANAR: + for (i = 0; i < pf->nb_channels; i++) { + int w, h; + + w = width; + h = height; + if (i == 1 || i == 2) { + w >>= pf->x_chroma_shift; + h >>= pf->y_chroma_shift; + } + bwidth = (w * pf->depth + 7) >> 3; + img_copy_plane (dst->data[i], dst->linesize[i], + src->data[i], src->linesize[i], bwidth, h); + } + break; + case FF_PIXEL_PALETTE: + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], width, height); + /* copy the palette */ + img_copy_plane (dst->data[1], dst->linesize[1], + src->data[1], src->linesize[1], 4, 256); + break; + } +} + +/* XXX: totally non optimized */ + +static void +yuv422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[1]; + cr[0] = p[3]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +uyvy422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *lum1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + lum[1] = p[3]; + p += 4; + lum += 2; + } + + if (w) + lum[0] = p[1]; + + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } +} + + +static void +uyvy422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[1]; + cb[0] = p[0]; + cr[0] = p[2]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + lum[1] = p[3]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + + +static void +uyvy422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[1]; + cb[0] = p[0]; + lum[1] = p[3]; + cr[0] = p[2]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[1]; + cb[0] = p[0]; + cr[0] = p[2]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yvyu422_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *lum1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + + if (w) + lum[0] = p[0]; + + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } +} + +static void +yvyu422_to_yuv420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + + for (; height >= 1; height -= 2) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[3]; + lum[1] = p[2]; + cr[0] = p[1]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[3]; + cr[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + if (height > 1) { + p = p1; + lum = lum1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + lum[1] = p[2]; + p += 4; + lum += 2; + } + if (w) { + lum[0] = p[0]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + } + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yvyu422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[3]; + lum[1] = p[2]; + cr[0] = p[1]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[3]; + cr[0] = p[1]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv422_to_yuv422p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + lum[0] = p[0]; + cb[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + lum[0] = p[0]; + cb[0] = p[1]; + cr[0] = p[3]; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv422p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[0] = lum[0]; + p[1] = cb[0]; + p[2] = lum[1]; + p[3] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[0] = lum[0]; + p[1] = cb[0]; + p[3] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv422p_to_uyvy422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[1] = lum[0]; + p[0] = cb[0]; + p[3] = lum[1]; + p[2] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[1] = lum[0]; + p[0] = cb[0]; + p[2] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv422p_to_yvyu422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 2; w -= 2) { + p[0] = lum[0]; + p[3] = cb[0]; + p[2] = lum[1]; + p[1] = cr[0]; + p += 4; + lum += 2; + cb++; + cr++; + } + if (w) { + p[0] = lum[0]; + p[3] = cb[0]; + p[1] = cr[0]; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +uyvy411_to_yuv411p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *p, *p1; + uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = src->data[0]; + lum1 = dst->data[0]; + cb1 = dst->data[1]; + cr1 = dst->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 4; w -= 4) { + cb[0] = p[0]; + lum[0] = p[1]; + lum[1] = p[2]; + cr[0] = p[3]; + lum[2] = p[4]; + lum[3] = p[5]; + p += 6; + lum += 4; + cb++; + cr++; + } + p1 += src->linesize[0]; + lum1 += dst->linesize[0]; + cb1 += dst->linesize[1]; + cr1 += dst->linesize[2]; + } +} + +static void +yuv411p_to_uyvy411 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *p, *p1; + const uint8_t *lum, *cr, *cb, *lum1, *cr1, *cb1; + int w; + + p1 = dst->data[0]; + lum1 = src->data[0]; + cb1 = src->data[1]; + cr1 = src->data[2]; + for (; height > 0; height--) { + p = p1; + lum = lum1; + cb = cb1; + cr = cr1; + for (w = width; w >= 4; w -= 4) { + p[0] = cb[0]; + p[1] = lum[0]; + p[2] = lum[1]; + p[3] = cr[0]; + p[4] = lum[2]; + p[5] = lum[3]; + p += 6; + lum += 4; + cb++; + cr++; + } + p1 += dst->linesize[0]; + lum1 += src->linesize[0]; + cb1 += src->linesize[1]; + cr1 += src->linesize[2]; + } +} + +static void +yuv420p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + } + + linesrc += dst->linesize[0] * 2; + lumsrc += src->linesize[0] * 2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } + /* odd height */ + if (height % 2 != 0) { + line1 = linesrc; + lum1 = lumsrc; + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line1++ = *cb1++; + *line1++ = *lum1++; + *line1++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line1++ = *cb1++; + } + } +} + +static void +nv12_to_nv21 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *s_c_ptr; + uint8_t *d_c_ptr; + int w, c_wrap; + + memcpy (dst->data[0], src->data[0], src->linesize[0] * height); + + s_c_ptr = src->data[1]; + d_c_ptr = dst->data[1]; + c_wrap = src->linesize[1] - ((width + 1) & ~0x01); + + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + + /* handle odd width */ + if (w) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + s_c_ptr += c_wrap; + d_c_ptr += c_wrap; + } + + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + + /* handle odd width */ + if (w) { + d_c_ptr[0] = s_c_ptr[1]; + d_c_ptr[1] = s_c_ptr[0]; + s_c_ptr += 2; + d_c_ptr += 2; + } + } +} + +static void +nv12_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int w, h; + uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0]; + uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1]; + uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2]; + uint8_t *lum1, *lum2, *src_lum_line = src->data[0]; + uint8_t *src_c1, *src_c_line = src->data[1]; + uint8_t cb, cr; + + for (h = height / 2; h--;) { + dst_lum1 = dst_line; + dst_lum2 = dst_line + dst->linesize[0]; + + dst_cb1 = dst_cb_line; + dst_cb2 = dst_cb_line + dst->linesize[1]; + dst_cr1 = dst_cr_line; + dst_cr2 = dst_cr_line + dst->linesize[2]; + + lum1 = src_lum_line; + lum2 = src_lum_line + src->linesize[0]; + + src_c1 = src_c_line; + + for (w = width / 2; w--;) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = *src_c1++; + *dst_cr1++ = *dst_cr2++ = *src_c1++; + } + + dst_line += dst->linesize[0] * 2; + dst_cb_line += dst->linesize[1] * 2; + dst_cr_line += dst->linesize[2] * 2; + src_lum_line += src->linesize[0] * 2; + src_c_line += src->linesize[1]; + } + + /* odd height */ + if (height % 2 != 0) { + dst_lum1 = dst_line; + lum1 = src_lum_line; + src_c1 = src_c_line; + dst_cb1 = dst_cb_line; + dst_cr1 = dst_cr_line; + + for (w = width / 2; w--;) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cb = *src_c1++; + cr = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + } +} + +#define nv21_to_nv12 nv12_to_nv21 + +static void +nv21_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int w, h; + uint8_t *dst_lum1, *dst_lum2, *dst_line = dst->data[0]; + uint8_t *dst_cb1, *dst_cb2, *dst_cb_line = dst->data[1]; + uint8_t *dst_cr1, *dst_cr2, *dst_cr_line = dst->data[2]; + uint8_t *lum1, *lum2, *src_lum_line = src->data[0]; + uint8_t *src_c1, *src_c_line = src->data[1]; + uint8_t cb, cr; + + for (h = height / 2; h--;) { + dst_lum1 = dst_line; + dst_lum2 = dst_line + dst->linesize[0]; + + dst_cb1 = dst_cb_line; + dst_cb2 = dst_cb_line + dst->linesize[1]; + dst_cr1 = dst_cr_line; + dst_cr2 = dst_cr_line + dst->linesize[2]; + + lum1 = src_lum_line; + lum2 = src_lum_line + src->linesize[0]; + + src_c1 = src_c_line; + + for (w = width / 2; w--;) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = cb; + *dst_cr1++ = *dst_cr2++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_lum2++ = *lum2++; + *dst_cb1++ = *dst_cb2++ = *src_c1++; + *dst_cr1++ = *dst_cr2++ = *src_c1++; + } + + dst_line += dst->linesize[0] * 2; + dst_cb_line += dst->linesize[1] * 2; + dst_cr_line += dst->linesize[2] * 2; + src_lum_line += src->linesize[0] * 2; + src_c_line += src->linesize[1]; + } + + /* odd height */ + if (height % 2 != 0) { + dst_lum1 = dst_line; + lum1 = src_lum_line; + src_c1 = src_c_line; + + dst_cb1 = dst_cb_line; + dst_cr1 = dst_cr_line; + + for (w = width / 2; w--;) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + /* odd width */ + if (width % 2 != 0) { + cr = *src_c1++; + cb = *src_c1++; + *dst_lum1++ = *lum1++; + *dst_cb1++ = cb; + *dst_cr1++ = cr; + } + } +} + +static void +yuva420p_to_yuv420p (AVPicture * dst, const AVPicture * src, int width, + int height) +{ + memcpy (dst->data[0], src->data[0], dst->linesize[0] * height); + memcpy (dst->data[1], src->data[1], dst->linesize[1] * ((height + 1) / 2)); + memcpy (dst->data[2], src->data[2], dst->linesize[2] * ((height + 1) / 2)); +} + +static void +yuva420p_to_yuv422 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int w, h; + uint8_t *line1, *line2, *linesrc = dst->data[0]; + uint8_t *lum1, *lum2, *lumsrc = src->data[0]; + uint8_t *cb1, *cb2 = src->data[1]; + uint8_t *cr1, *cr2 = src->data[2]; + + for (h = height / 2; h--;) { + line1 = linesrc; + line2 = linesrc + dst->linesize[0]; + + lum1 = lumsrc; + lum2 = lumsrc + src->linesize[0]; + + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line2++ = *lum2++; + *line1++ = *line2++ = *cb1++; + } + + linesrc += dst->linesize[0] * 2; + lumsrc += src->linesize[0] * 2; + cb2 += src->linesize[1]; + cr2 += src->linesize[2]; + } + /* odd height */ + if (height % 2 != 0) { + line1 = linesrc; + lum1 = lumsrc; + cb1 = cb2; + cr1 = cr2; + + for (w = width / 2; w--;) { + *line1++ = *lum1++; + *line1++ = *cb1++; + *line1++ = *lum1++; + *line1++ = *cr1++; + } + /* odd width */ + if (width % 2 != 0) { + *line1++ = *lum1++; + *line1++ = *cb1++; + } + } +} + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define YUV_TO_RGB1(cb1, cr1)\ +{\ + cb = (cb1) - 128;\ + cr = (cr1) - 128;\ + r_add = FIX(1.40200) * cr + ONE_HALF;\ + g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ + b_add = FIX(1.77200) * cb + ONE_HALF;\ +} + +#define YUV_TO_RGB2(r, g, b, y1)\ +{\ + y = (y1) << SCALEBITS;\ + r = cm[(y + r_add) >> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define Y_CCIR_TO_JPEG(y)\ + cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] + +#define Y_JPEG_TO_CCIR(y)\ + (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define C_CCIR_TO_JPEG(y)\ + cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] + +/* NOTE: the clamp is really necessary! */ +static inline int +C_JPEG_TO_CCIR (int y) +{ + y = (((y - 128) * FIX (112.0 / 127.0) + (ONE_HALF + + (128 << SCALEBITS))) >> SCALEBITS); + if (y < 16) + y = 16; + return y; +} + + +#define RGB_TO_Y(r, g, b) \ +((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ + FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ +(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ +(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ +((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ +(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +static uint8_t y_ccir_to_jpeg[256]; +static uint8_t y_jpeg_to_ccir[256]; +static uint8_t c_ccir_to_jpeg[256]; +static uint8_t c_jpeg_to_ccir[256]; + +/* init various conversion tables */ +static void +img_convert_init (void) +{ + int i; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + + for (i = 0; i < 256; i++) { + y_ccir_to_jpeg[i] = Y_CCIR_TO_JPEG (i); + y_jpeg_to_ccir[i] = Y_JPEG_TO_CCIR (i); + c_ccir_to_jpeg[i] = C_CCIR_TO_JPEG (i); + c_jpeg_to_ccir[i] = C_JPEG_TO_CCIR (i); + } +} + +/* apply to each pixel the given table */ +static void +img_apply_table (uint8_t * dst, int dst_wrap, + const uint8_t * src, int src_wrap, + int width, int height, const uint8_t * table1) +{ + int n; + const uint8_t *s; + uint8_t *d; + const uint8_t *table; + + table = table1; + for (; height > 0; height--) { + s = src; + d = dst; + n = width; + while (n >= 4) { + d[0] = table[s[0]]; + d[1] = table[s[1]]; + d[2] = table[s[2]]; + d[3] = table[s[3]]; + d += 4; + s += 4; + n -= 4; + } + while (n > 0) { + d[0] = table[s[0]]; + d++; + s++; + n--; + } + dst += dst_wrap; + src += src_wrap; + } +} + +/* XXX: use generic filter ? */ +/* XXX: in most cases, the sampling position is incorrect */ + +static void +img_copy_plane_resize (uint8_t * dst, int dst_wrap, int dst_width, + int dst_height, const uint8_t * src, int src_wrap, int src_width, + int src_height) +{ + img_copy_plane (dst, dst_wrap, src, src_wrap, dst_width, dst_height); +} + +/* 4x1 -> 1x1 */ +static void +shrink41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s; + uint8_t *d; + + for (; dst_height > 0; dst_height--) { + s = src; + d = dst; + for (s_w = src_width, w = dst_width; w > 0 && s_w > 3; w--, s_w -= 4) { + d[0] = (s[0] + s[1] + s[2] + s[3] + 2) >> 2; + s += 4; + d++; + } + + if (w) { + if (s_w == 3) + d[0] = (s[0] + s[1] + s[2]) / 3; + else if (s_w == 2) + d[0] = (s[0] + s[1]) / 2; + else /* s_w == 1 */ + d[0] = s[0]; + } + + src += src_wrap; + dst += dst_wrap; + } +} + +/* 2x1 -> 1x1 */ +static void +shrink21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s; + uint8_t *d; + + for (; dst_height > 0; dst_height--) { + s = src; + d = dst; + for (s_w = src_width, w = dst_width; w > 0 && s_w > 1; w--, s_w -= 2) { + d[0] = (s[0] + s[1]) >> 1; + s += 2; + d++; + } + + if (w) /* s_w == 1 */ + d[0] = s[0]; + + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 1x1 */ +static void +shrink12 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w; + uint8_t *d; + const uint8_t *s1, *s2; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + d = dst; + for (w = dst_width; w >= 4; w -= 4) { + d[0] = (s1[0] + s2[0]) >> 1; + d[1] = (s1[1] + s2[1]) >> 1; + d[2] = (s1[2] + s2[2]) >> 1; + d[3] = (s1[3] + s2[3]) >> 1; + s1 += 4; + s2 += 4; + d += 4; + } + for (; w > 0; w--) { + d[0] = (s1[0] + s2[0]) >> 1; + s1++; + s2++; + d++; + } + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 2x2 -> 1x1 */ +static void +shrink22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, s_w; + const uint8_t *s1, *s2; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + d = dst; + for (s_w = src_width, w = dst_width; w >= 4; w -= 4, s_w -= 8) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + d[1] = (s1[2] + s1[3] + s2[2] + s2[3] + 2) >> 2; + d[2] = (s1[4] + s1[5] + s2[4] + s2[5] + 2) >> 2; + d[3] = (s1[6] + s1[7] + s2[6] + s2[7] + 2) >> 2; + s1 += 8; + s2 += 8; + d += 4; + } + for (; w > 0 && s_w > 1; w--, s_w -= 2) { + d[0] = (s1[0] + s1[1] + s2[0] + s2[1] + 2) >> 2; + s1 += 2; + s2 += 2; + d++; + } + + if (w) + d[0] = (s1[0] + s2[0] + 1) >> 1; + + src += 2 * src_wrap; + dst += dst_wrap; + } +} + +/* 4x4 -> 1x1 */ +static void +shrink44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int s_w, w; + const uint8_t *s1, *s2, *s3, *s4; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 4) { + s1 = src; + s2 = s1 + (src_height > 1 ? src_wrap : 0); + s3 = s2 + (src_height > 2 ? src_wrap : 0); + s4 = s3 + (src_height > 3 ? src_wrap : 0); + d = dst; + for (s_w = src_width, w = dst_width; s_w > 3 && w > 0; w--, s_w -= 4) { + d[0] = (s1[0] + s1[1] + s1[2] + s1[3] + + s2[0] + s2[1] + s2[2] + s2[3] + + s3[0] + s3[1] + s3[2] + s3[3] + + s4[0] + s4[1] + s4[2] + s4[3] + 8) >> 4; + s1 += 4; + s2 += 4; + s3 += 4; + s4 += 4; + d++; + } + + if (w) { + if (s_w == 3) + d[0] = (s1[0] + s1[1] + s1[2] + + s2[0] + s2[1] + s2[2] + + s3[0] + s3[1] + s3[2] + s4[0] + s4[1] + s4[2]) / 12; + else if (s_w == 2) + d[0] = (s1[0] + s1[1] + + s2[0] + s2[1] + s3[0] + s3[1] + s4[0] + s4[1]) / 8; + else /* s_w == 1 */ + d[0] = (s1[0] + s2[0] + s3[0] + s4[0]) / 4; + } + + src += 4 * src_wrap; + dst += dst_wrap; + } +} + +static void +grow21_line (uint8_t * dst, const uint8_t * src, int width) +{ + int w; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) { + d[1] = d[0] = s1[0]; + d[3] = d[2] = s1[1]; + s1 += 2; + d += 4; + } + for (; w >= 2; w -= 2) { + d[1] = d[0] = s1[0]; + s1++; + d += 2; + } + /* only needed if width is not a multiple of two */ + if (w) { + d[0] = s1[0]; + } +} + +static void +grow41_line (uint8_t * dst, const uint8_t * src, int width) +{ + int w, v; + const uint8_t *s1; + uint8_t *d; + + s1 = src; + d = dst; + for (w = width; w >= 4; w -= 4) { + v = s1[0]; + d[0] = v; + d[1] = v; + d[2] = v; + d[3] = v; + s1++; + d += 4; + } + for (; w > 0; w--) { + d[0] = s1[0]; + d++; + } +} + +/* 1x1 -> 2x1 */ +static void +grow21 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow21_line (dst, src, dst_width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 2x2 */ +static void +grow22 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow21_line (dst, src, dst_width); + if (dst_height % 2) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x1 */ +static void +grow41 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow41_line (dst, src, dst_width); + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x1 -> 4x4 */ +static void +grow44 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + for (; dst_height > 0; dst_height--) { + grow41_line (dst, src, dst_width); + if ((dst_height & 3) == 1) + src += src_wrap; + dst += dst_wrap; + } +} + +/* 1x2 -> 2x1 */ +static void +conv411 (uint8_t * dst, int dst_wrap, int dst_width, int dst_height, + const uint8_t * src, int src_wrap, int src_width, int src_height) +{ + int w, c; + const uint8_t *s1, *s2; + uint8_t *d; + + for (; dst_height > 0; dst_height--, src_height -= 2) { + s1 = src; + s2 = src + (src_height > 1 ? src_wrap : 0); + d = dst; + for (w = dst_width; w > 1; w -= 2) { + c = (s1[0] + s2[0]) >> 1; + d[0] = c; + d[1] = c; + s1++; + s2++; + d += 2; + } + + if (w) { + d[0] = (s1[0] + s2[0]) >> 1; + } + + src += src_wrap * 2; + dst += dst_wrap; + } +} + +/* XXX: add jpeg quantize code */ + +#define TRANSP_INDEX (6*6*6) + +/* this is maybe slow, but allows for extensions */ +static inline unsigned char +gif_clut_index (uint8_t r, uint8_t g, uint8_t b) +{ + return ((((r) / 47) % 6) * 6 * 6 + (((g) / 47) % 6) * 6 + (((b) / 47) % 6)); +} + +static void +build_rgb_palette (uint8_t * palette, int has_alpha) +{ + uint32_t *pal; + static const uint8_t pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; + int i, r, g, b; + + pal = (uint32_t *) palette; + i = 0; + for (r = 0; r < 6; r++) { + for (g = 0; g < 6; g++) { + for (b = 0; b < 6; b++) { + pal[i++] = (0xffU << 24) | (pal_value[r] << 16) | + (pal_value[g] << 8) | pal_value[b]; + } + } + } + if (has_alpha) + pal[i++] = 0; + while (i < 256) + pal[i++] = 0xff000000; +} + +/* copy bit n to bits 0 ... n - 1 */ +static inline unsigned int +bitcopy_n (unsigned int a, int n) +{ + int mask; + + mask = (1 << n) - 1; + return (a & (0xff & ~mask)) | ((-((a >> n) & 1)) & mask); +} + +/* rgb555 handling */ + +#define RGB_NAME rgb555 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (10 - 3), 3);\ + g = bitcopy_n(v >> (5 - 3), 3);\ + b = bitcopy_n(v << 3, 3);\ + a = (-(v >> 15)) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3) | \ + ((a << 8) & 0x8000);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* rgb565 handling */ + +#define RGB_NAME rgb565 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint16_t *)(s))[0];\ + r = bitcopy_n(v >> (11 - 3), 3);\ + g = bitcopy_n(v >> (5 - 2), 2);\ + b = bitcopy_n(v << 3, 3);\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + ((uint16_t *)(d))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);\ +} + +#define BPP 2 + +#include "imgconvert_template.h" + +/* bgr24 handling */ + +#define RGB_NAME bgr24 + +#define RGB_IN(r, g, b, s)\ +{\ + b = (s)[0];\ + g = (s)[1];\ + r = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = b;\ + (d)[1] = g;\ + (d)[2] = r;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +#undef RGB_IN +#undef RGB_OUT +#undef BPP + +/* rgb24 handling */ + +#define RGB_NAME rgb24 +#define FMT_RGB24 + +#define RGB_IN(r, g, b, s)\ +{\ + r = (s)[0];\ + g = (s)[1];\ + b = (s)[2];\ +} + +#define RGB_OUT(d, r, g, b)\ +{\ + (d)[0] = r;\ + (d)[1] = g;\ + (d)[2] = b;\ +} + +#define BPP 3 + +#include "imgconvert_template.h" + +/* rgb32 handling */ + +#define RGB_NAME rgb32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgr32 handling */ + +#define RGB_NAME bgr32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24);\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* xrgb32 handling */ + +#define RGB_NAME xrgb32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgrx32 handling */ + +#define RGB_NAME bgrx32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = 0xff;\ + r = (v) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24);\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* rgba32 handling */ + +#define RGB_NAME rgba32 +#define FMT_RGBA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = (v >> 24) & 0xff;\ + r = (v >> 16) & 0xff;\ + g = (v >> 8) & 0xff;\ + b = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (a << 24) | (r << 16) | (g << 8) | b;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* bgra32 handling */ + +#define RGB_NAME bgra32 +#define FMT_BGRA32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + a = v & 0xff;\ + r = (v >> 8) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = a | (r << 8) | (g << 16) | (b << 24 );\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* argb32 handling */ + +#define RGB_NAME argb32 +#define FMT_ARGB32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = (v >> 24) & 0xff;\ + g = (v >> 16) & 0xff;\ + b = (v >> 8) & 0xff;\ + a = v & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = (r << 24) | (g << 16) | (b << 8) | a;\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +/* abgr32 handling */ + +#define RGB_NAME abgr32 +#define FMT_ABGR32 + +#define RGB_IN(r, g, b, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = v & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ +} + +#define RGBA_IN(r, g, b, a, s)\ +{\ + unsigned int v = ((const uint32_t *)(s))[0];\ + r = v & 0xff;\ + g = (v >> 8) & 0xff;\ + b = (v >> 16) & 0xff;\ + a = (v >> 24) & 0xff;\ +} + +#define RGBA_OUT(d, r, g, b, a)\ +{\ + ((uint32_t *)(d))[0] = r | (g << 8) | (b << 16) | (a << 24 );\ +} + +#define BPP 4 + +#include "imgconvert_template.h" + +static void +gray_to_gray16_l (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_LE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray_to_gray16_b (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_BE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_l_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_LE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_b_to_gray (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_BE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +gray16_b_to_gray16_l (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = p[1]; + q[1] = p[0]; + q += 2; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +mono_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height, int xor_mask) +{ + const unsigned char *p; + unsigned char *q; + int v, dst_wrap, src_wrap; + int y, w; + + p = src->data[0]; + src_wrap = src->linesize[0] - ((width + 7) >> 3); + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + for (y = 0; y < height; y++) { + w = width; + while (w >= 8) { + v = *p++ ^ xor_mask; + q[0] = -(v >> 7); + q[1] = -((v >> 6) & 1); + q[2] = -((v >> 5) & 1); + q[3] = -((v >> 4) & 1); + q[4] = -((v >> 3) & 1); + q[5] = -((v >> 2) & 1); + q[6] = -((v >> 1) & 1); + q[7] = -((v >> 0) & 1); + w -= 8; + q += 8; + } + if (w > 0) { + v = *p++ ^ xor_mask; + do { + q[0] = -((v >> 7) & 1); + q++; + v <<= 1; + } while (--w); + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +monowhite_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + mono_to_gray (dst, src, width, height, 0xff); +} + +static void +monoblack_to_gray (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + mono_to_gray (dst, src, width, height, 0x00); +} + +static void +gray_to_mono (AVPicture * dst, const AVPicture * src, + int width, int height, int xor_mask) +{ + int n; + const uint8_t *s; + uint8_t *d; + int j, b, v, n1, src_wrap, dst_wrap, y; + + s = src->data[0]; + src_wrap = src->linesize[0] - width; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - ((width + 7) >> 3); + + for (y = 0; y < height; y++) { + n = width; + while (n >= 8) { + v = 0; + for (j = 0; j < 8; j++) { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + } + d[0] = v ^ xor_mask; + d++; + n -= 8; + } + if (n > 0) { + n1 = n; + v = 0; + while (n > 0) { + b = s[0]; + s++; + v = (v << 1) | (b >> 7); + n--; + } + d[0] = (v << (8 - (n1 & 7))) ^ xor_mask; + d++; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void +gray_to_monowhite (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + gray_to_mono (dst, src, width, height, 0xff); +} + +static void +gray_to_monoblack (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + gray_to_mono (dst, src, width, height, 0x00); +} + +static void +y800_to_y16 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + GST_WRITE_UINT16_LE (q, (*p << 8)); + q += 2; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +y16_to_y800 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + q[0] = GST_READ_UINT16_LE (p) >> 8; + q++; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void +yuva420p_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *a1_ptr, *a2_ptr; + uint8_t *d, *d1, *d2; + int w, width2; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + a1_ptr = src->data[3]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + a2_ptr = a1_ptr + src->linesize[3]; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d2[4 + 0] = a2_ptr[1]; + d2[4 + 1] = y2_ptr[1]; + d2[4 + 2] = cb_ptr[0]; + d2[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + d2 += 2 * 4; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + a2_ptr += 2; + } + /* handle odd width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d2[0] = a2_ptr[0]; + d2[1] = y2_ptr[0]; + d2[2] = cb_ptr[0]; + d2[3] = cr_ptr[0]; + + d1 += 4; + d2 += 4; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + a2_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + a1_ptr += 2 * src->linesize[3] - width; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + + d1[4 + 0] = a1_ptr[1]; + d1[4 + 1] = y1_ptr[1]; + d1[4 + 2] = cb_ptr[0]; + d1[4 + 3] = cr_ptr[0]; + + d1 += 2 * 4; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + } + /* handle width */ + if (w) { + d1[0] = a1_ptr[0]; + d1[1] = y1_ptr[0]; + d1[2] = cb_ptr[0]; + d1[3] = cr_ptr[0]; + d1 += 4; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + } + } +} + +static void +ayuv4444_to_yuva420p (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int u1, v1, w; + uint8_t *lum, *cb, *cr, *a; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + a = dst->data[3]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + + cb[0] = u1 >> 2; + cr[0] = v1 >> 2; + + cb++; + cr++; + p += -wrap3 + 2 * 4; + lum += -wrap + 2; + a += -wrap + 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + p += wrap3; + lum += wrap; + a += wrap; + + a[0] = p[0]; + lum[0] = p[1]; + u1 += p[2]; + v1 += p[3]; + + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += -wrap3 + 4; + lum += -wrap + 1; + a += -wrap + 1; + } + p += wrap3 + (wrap3 - width * 4); + lum += wrap + (wrap - width); + a += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + a[0] = p[0]; + lum[0] = p[1]; + u1 = p[2]; + v1 = p[3]; + + a[1] = p[4 + 0]; + lum[1] = p[4 + 1]; + u1 += p[4 + 2]; + v1 += p[4 + 3]; + cb[0] = u1 >> 1; + cr[0] = v1 >> 1; + cb++; + cr++; + p += 2 * 4; + lum += 2; + a += 2; + } + if (w) { + a[0] = p[0]; + lum[0] = p[1]; + cb[0] = p[2]; + cr[0] = p[3]; + } + } +} + +typedef struct ConvertEntry +{ + enum PixelFormat src; + enum PixelFormat dest; + void (*convert) (AVPicture * dst, + const AVPicture * src, int width, int height); +} ConvertEntry; + +/* Add each new convertion function in this table. In order to be able + to convert from any format to any format, the following constraints + must be satisfied: + + - all FF_COLOR_RGB formats must convert to and from PIX_FMT_RGB24 + + - all FF_COLOR_GRAY formats must convert to and from PIX_FMT_GRAY8 + + - all FF_COLOR_RGB formats with alpha must convert to and from PIX_FMT_RGBA32 + + - PIX_FMT_YUV444P and PIX_FMT_YUVJ444P must convert to and from + PIX_FMT_RGB24. + + - PIX_FMT_422 must convert to and from PIX_FMT_422P. + + The other conversion functions are just optimisations for common cases. +*/ +static ConvertEntry convert_table[] = { + {PIX_FMT_YUV420P, PIX_FMT_YUV422, yuv420p_to_yuv422}, + {PIX_FMT_YUV420P, PIX_FMT_RGB555, yuv420p_to_rgb555}, + {PIX_FMT_YUV420P, PIX_FMT_RGB565, yuv420p_to_rgb565}, + {PIX_FMT_YUV420P, PIX_FMT_BGR24, yuv420p_to_bgr24}, + {PIX_FMT_YUV420P, PIX_FMT_RGB24, yuv420p_to_rgb24}, + {PIX_FMT_YUV420P, PIX_FMT_RGB32, yuv420p_to_rgb32}, + {PIX_FMT_YUV420P, PIX_FMT_BGR32, yuv420p_to_bgr32}, + {PIX_FMT_YUV420P, PIX_FMT_xRGB32, yuv420p_to_xrgb32}, + {PIX_FMT_YUV420P, PIX_FMT_BGRx32, yuv420p_to_bgrx32}, + {PIX_FMT_YUV420P, PIX_FMT_RGBA32, yuv420p_to_rgba32}, + {PIX_FMT_YUV420P, PIX_FMT_BGRA32, yuv420p_to_bgra32}, + {PIX_FMT_YUV420P, PIX_FMT_ARGB32, yuv420p_to_argb32}, + {PIX_FMT_YUV420P, PIX_FMT_ABGR32, yuv420p_to_abgr32}, + + {PIX_FMT_NV12, PIX_FMT_RGB555, nv12_to_rgb555}, + {PIX_FMT_NV12, PIX_FMT_RGB565, nv12_to_rgb565}, + {PIX_FMT_NV12, PIX_FMT_BGR24, nv12_to_bgr24}, + {PIX_FMT_NV12, PIX_FMT_RGB24, nv12_to_rgb24}, + {PIX_FMT_NV12, PIX_FMT_RGB32, nv12_to_rgb32}, + {PIX_FMT_NV12, PIX_FMT_BGR32, nv12_to_bgr32}, + {PIX_FMT_NV12, PIX_FMT_xRGB32, nv12_to_xrgb32}, + {PIX_FMT_NV12, PIX_FMT_BGRx32, nv12_to_bgrx32}, + {PIX_FMT_NV12, PIX_FMT_RGBA32, nv12_to_rgba32}, + {PIX_FMT_NV12, PIX_FMT_BGRA32, nv12_to_bgra32}, + {PIX_FMT_NV12, PIX_FMT_ARGB32, nv12_to_argb32}, + {PIX_FMT_NV12, PIX_FMT_ABGR32, nv12_to_abgr32}, + {PIX_FMT_NV12, PIX_FMT_NV21, nv12_to_nv21}, + {PIX_FMT_NV12, PIX_FMT_YUV444P, nv12_to_yuv444p}, + + {PIX_FMT_NV21, PIX_FMT_RGB555, nv21_to_rgb555}, + {PIX_FMT_NV21, PIX_FMT_RGB565, nv21_to_rgb565}, + {PIX_FMT_NV21, PIX_FMT_BGR24, nv21_to_bgr24}, + {PIX_FMT_NV21, PIX_FMT_RGB24, nv21_to_rgb24}, + {PIX_FMT_NV21, PIX_FMT_RGB32, nv21_to_rgb32}, + {PIX_FMT_NV21, PIX_FMT_BGR32, nv21_to_bgr32}, + {PIX_FMT_NV21, PIX_FMT_xRGB32, nv21_to_xrgb32}, + {PIX_FMT_NV21, PIX_FMT_BGRx32, nv21_to_bgrx32}, + {PIX_FMT_NV21, PIX_FMT_RGBA32, nv21_to_rgba32}, + {PIX_FMT_NV21, PIX_FMT_BGRA32, nv21_to_bgra32}, + {PIX_FMT_NV21, PIX_FMT_ARGB32, nv21_to_argb32}, + {PIX_FMT_NV21, PIX_FMT_ABGR32, nv21_to_abgr32}, + {PIX_FMT_NV21, PIX_FMT_YUV444P, nv21_to_yuv444p}, + {PIX_FMT_NV21, PIX_FMT_NV12, nv21_to_nv12}, + + {PIX_FMT_YUV422P, PIX_FMT_YUV422, yuv422p_to_yuv422}, + {PIX_FMT_YUV422P, PIX_FMT_UYVY422, yuv422p_to_uyvy422}, + {PIX_FMT_YUV422P, PIX_FMT_YVYU422, yuv422p_to_yvyu422}, + + {PIX_FMT_YUV444P, PIX_FMT_RGB24, yuv444p_to_rgb24}, + + {PIX_FMT_YUVJ420P, PIX_FMT_RGB555, yuvj420p_to_rgb555}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB565, yuvj420p_to_rgb565}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR24, yuvj420p_to_bgr24}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB24, yuvj420p_to_rgb24}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_rgb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgr32}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGB32, yuvj420p_to_xrgb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGR32, yuvj420p_to_bgrx32}, + {PIX_FMT_YUVJ420P, PIX_FMT_RGBA32, yuvj420p_to_rgba32}, + {PIX_FMT_YUVJ420P, PIX_FMT_BGRA32, yuvj420p_to_bgra32}, + {PIX_FMT_YUVJ420P, PIX_FMT_ARGB32, yuvj420p_to_argb32}, + {PIX_FMT_YUVJ420P, PIX_FMT_ABGR32, yuvj420p_to_abgr32}, + + {PIX_FMT_YUVJ444P, PIX_FMT_RGB24, yuvj444p_to_rgb24}, + + {PIX_FMT_YUV422, PIX_FMT_YUV420P, yuv422_to_yuv420p}, + {PIX_FMT_YUV422, PIX_FMT_YUV422P, yuv422_to_yuv422p}, + {PIX_FMT_YUV422, PIX_FMT_GRAY8, yvyu422_to_gray}, + {PIX_FMT_YUV422, PIX_FMT_RGB555, yuv422_to_rgb555}, + {PIX_FMT_YUV422, PIX_FMT_RGB565, yuv422_to_rgb565}, + {PIX_FMT_YUV422, PIX_FMT_BGR24, yuv422_to_bgr24}, + {PIX_FMT_YUV422, PIX_FMT_RGB24, yuv422_to_rgb24}, + {PIX_FMT_YUV422, PIX_FMT_BGR32, yuv422_to_bgr32}, + {PIX_FMT_YUV422, PIX_FMT_RGB32, yuv422_to_rgb32}, + {PIX_FMT_YUV422, PIX_FMT_xRGB32, yuv422_to_xrgb32}, + {PIX_FMT_YUV422, PIX_FMT_BGRx32, yuv422_to_bgrx32}, + {PIX_FMT_YUV422, PIX_FMT_BGRA32, yuv422_to_bgra32}, + {PIX_FMT_YUV422, PIX_FMT_RGBA32, yuv422_to_rgba32}, + {PIX_FMT_YUV422, PIX_FMT_ABGR32, yuv422_to_abgr32}, + {PIX_FMT_YUV422, PIX_FMT_ARGB32, yuv422_to_argb32}, + + {PIX_FMT_UYVY422, PIX_FMT_YUV420P, uyvy422_to_yuv420p}, + {PIX_FMT_UYVY422, PIX_FMT_YUV422P, uyvy422_to_yuv422p}, + {PIX_FMT_UYVY422, PIX_FMT_GRAY8, uyvy422_to_gray}, + {PIX_FMT_UYVY422, PIX_FMT_RGB555, uyvy422_to_rgb555}, + {PIX_FMT_UYVY422, PIX_FMT_RGB565, uyvy422_to_rgb565}, + {PIX_FMT_UYVY422, PIX_FMT_BGR24, uyvy422_to_bgr24}, + {PIX_FMT_UYVY422, PIX_FMT_RGB24, uyvy422_to_rgb24}, + {PIX_FMT_UYVY422, PIX_FMT_RGB32, uyvy422_to_rgb32}, + {PIX_FMT_UYVY422, PIX_FMT_BGR32, uyvy422_to_bgr32}, + {PIX_FMT_UYVY422, PIX_FMT_xRGB32, uyvy422_to_xrgb32}, + {PIX_FMT_UYVY422, PIX_FMT_BGRx32, uyvy422_to_bgrx32}, + {PIX_FMT_UYVY422, PIX_FMT_RGBA32, uyvy422_to_rgba32}, + {PIX_FMT_UYVY422, PIX_FMT_BGRA32, uyvy422_to_bgra32}, + {PIX_FMT_UYVY422, PIX_FMT_ARGB32, uyvy422_to_argb32}, + {PIX_FMT_UYVY422, PIX_FMT_ABGR32, uyvy422_to_abgr32}, + + {PIX_FMT_YVYU422, PIX_FMT_YUV420P, yvyu422_to_yuv420p}, + {PIX_FMT_YVYU422, PIX_FMT_YUV422P, yvyu422_to_yuv422p}, + {PIX_FMT_YVYU422, PIX_FMT_GRAY8, yvyu422_to_gray}, + {PIX_FMT_YVYU422, PIX_FMT_RGB555, yvyu422_to_rgb555}, + {PIX_FMT_YVYU422, PIX_FMT_RGB565, yvyu422_to_rgb565}, + {PIX_FMT_YVYU422, PIX_FMT_BGR24, yvyu422_to_bgr24}, + {PIX_FMT_YVYU422, PIX_FMT_RGB24, yvyu422_to_rgb24}, + {PIX_FMT_YVYU422, PIX_FMT_BGR32, yvyu422_to_bgr32}, + {PIX_FMT_YVYU422, PIX_FMT_RGB32, yvyu422_to_rgb32}, + {PIX_FMT_YVYU422, PIX_FMT_xRGB32, yvyu422_to_xrgb32}, + {PIX_FMT_YVYU422, PIX_FMT_BGRx32, yvyu422_to_bgrx32}, + {PIX_FMT_YVYU422, PIX_FMT_BGRA32, yvyu422_to_bgra32}, + {PIX_FMT_YVYU422, PIX_FMT_RGBA32, yvyu422_to_rgba32}, + {PIX_FMT_YVYU422, PIX_FMT_ABGR32, yvyu422_to_abgr32}, + {PIX_FMT_YVYU422, PIX_FMT_ARGB32, yvyu422_to_argb32}, + + {PIX_FMT_RGB24, PIX_FMT_YUV420P, rgb24_to_yuv420p}, + {PIX_FMT_RGB24, PIX_FMT_YUVA420P, rgb24_to_yuva420p}, + {PIX_FMT_RGB24, PIX_FMT_NV12, rgb24_to_nv12}, + {PIX_FMT_RGB24, PIX_FMT_NV21, rgb24_to_nv21}, + {PIX_FMT_RGB24, PIX_FMT_RGB565, rgb24_to_rgb565}, + {PIX_FMT_RGB24, PIX_FMT_RGB555, rgb24_to_rgb555}, + {PIX_FMT_RGB24, PIX_FMT_RGB32, rgb24_to_rgb32}, + {PIX_FMT_RGB24, PIX_FMT_BGR32, rgb24_to_bgr32}, + {PIX_FMT_RGB24, PIX_FMT_xRGB32, rgb24_to_xrgb32}, + {PIX_FMT_RGB24, PIX_FMT_BGRx32, rgb24_to_bgrx32}, + {PIX_FMT_RGB24, PIX_FMT_RGBA32, rgb24_to_rgba32}, + {PIX_FMT_RGB24, PIX_FMT_BGR24, rgb24_to_bgr24}, + {PIX_FMT_RGB24, PIX_FMT_BGRA32, rgb24_to_bgra32}, + {PIX_FMT_RGB24, PIX_FMT_ARGB32, rgb24_to_argb32}, + {PIX_FMT_RGB24, PIX_FMT_ABGR32, rgb24_to_abgr32}, + {PIX_FMT_RGB24, PIX_FMT_Y800, rgb24_to_y800}, + {PIX_FMT_RGB24, PIX_FMT_Y16, rgb24_to_y16}, + {PIX_FMT_RGB24, PIX_FMT_GRAY8, rgb24_to_gray}, + {PIX_FMT_RGB24, PIX_FMT_GRAY16_L, rgb24_to_gray16_l}, + {PIX_FMT_RGB24, PIX_FMT_GRAY16_B, rgb24_to_gray16_b}, + {PIX_FMT_RGB24, PIX_FMT_PAL8, rgb24_to_pal8}, + {PIX_FMT_RGB24, PIX_FMT_YUV444P, rgb24_to_yuv444p}, + {PIX_FMT_RGB24, PIX_FMT_YUVJ420P, rgb24_to_yuvj420p}, + {PIX_FMT_RGB24, PIX_FMT_YUVJ444P, rgb24_to_yuvj444p}, + {PIX_FMT_RGB24, PIX_FMT_AYUV4444, rgb24_to_ayuv4444}, + {PIX_FMT_RGB24, PIX_FMT_V308, rgb24_to_v308}, + + {PIX_FMT_RGB32, PIX_FMT_RGB24, rgb32_to_rgb24}, + {PIX_FMT_RGB32, PIX_FMT_RGB555, rgba32_to_rgb555}, + {PIX_FMT_RGB32, PIX_FMT_PAL8, rgb32_to_pal8}, + {PIX_FMT_RGB32, PIX_FMT_YUV420P, rgb32_to_yuv420p}, + {PIX_FMT_RGB32, PIX_FMT_YUVA420P, rgb32_to_yuva420p}, + {PIX_FMT_RGB32, PIX_FMT_NV12, rgb32_to_nv12}, + {PIX_FMT_RGB32, PIX_FMT_NV21, rgb32_to_nv21}, + {PIX_FMT_RGB32, PIX_FMT_Y800, rgb32_to_y800}, + {PIX_FMT_RGB32, PIX_FMT_Y16, rgb32_to_y16}, + {PIX_FMT_RGB32, PIX_FMT_GRAY8, rgb32_to_gray}, + {PIX_FMT_RGB32, PIX_FMT_GRAY16_L, rgb32_to_gray16_l}, + {PIX_FMT_RGB32, PIX_FMT_GRAY16_B, rgb32_to_gray16_b}, + + {PIX_FMT_xRGB32, PIX_FMT_RGB24, xrgb32_to_rgb24}, + {PIX_FMT_xRGB32, PIX_FMT_PAL8, xrgb32_to_pal8}, + {PIX_FMT_xRGB32, PIX_FMT_YUV420P, xrgb32_to_yuv420p}, + {PIX_FMT_xRGB32, PIX_FMT_YUVA420P, xrgb32_to_yuva420p}, + {PIX_FMT_xRGB32, PIX_FMT_NV12, xrgb32_to_nv12}, + {PIX_FMT_xRGB32, PIX_FMT_NV21, xrgb32_to_nv21}, + {PIX_FMT_xRGB32, PIX_FMT_Y800, xrgb32_to_y800}, + {PIX_FMT_xRGB32, PIX_FMT_Y16, xrgb32_to_y16}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY8, xrgb32_to_gray}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY16_L, xrgb32_to_gray16_l}, + {PIX_FMT_xRGB32, PIX_FMT_GRAY16_B, xrgb32_to_gray16_b}, + + {PIX_FMT_RGBA32, PIX_FMT_BGRA32, rgba32_to_bgra32}, + {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32}, + {PIX_FMT_RGBA32, PIX_FMT_ARGB32, rgba32_to_argb32}, + {PIX_FMT_RGBA32, PIX_FMT_BGR32, rgba32_to_bgr32}, + {PIX_FMT_RGBA32, PIX_FMT_BGRx32, rgba32_to_bgrx32}, + {PIX_FMT_RGBA32, PIX_FMT_ABGR32, rgba32_to_abgr32}, + {PIX_FMT_RGBA32, PIX_FMT_RGB24, rgba32_to_rgb24}, + {PIX_FMT_RGBA32, PIX_FMT_RGB555, rgba32_to_rgb555}, + {PIX_FMT_RGBA32, PIX_FMT_PAL8, rgba32_to_pal8}, + {PIX_FMT_RGBA32, PIX_FMT_YUV420P, rgba32_to_yuv420p}, + {PIX_FMT_RGBA32, PIX_FMT_YUVA420P, rgba32_to_yuva420p}, + {PIX_FMT_RGBA32, PIX_FMT_NV12, rgba32_to_nv12}, + {PIX_FMT_RGBA32, PIX_FMT_NV21, rgba32_to_nv21}, + {PIX_FMT_RGBA32, PIX_FMT_Y800, rgba32_to_y800}, + {PIX_FMT_RGBA32, PIX_FMT_Y16, rgba32_to_y16}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY8, rgba32_to_gray}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY16_L, rgba32_to_gray16_l}, + {PIX_FMT_RGBA32, PIX_FMT_GRAY16_B, rgba32_to_gray16_b}, + {PIX_FMT_RGBA32, PIX_FMT_AYUV4444, rgba32_to_ayuv4444}, + + {PIX_FMT_BGR24, PIX_FMT_RGB24, bgr24_to_rgb24}, + {PIX_FMT_BGR24, PIX_FMT_YUV420P, bgr24_to_yuv420p}, + {PIX_FMT_BGR24, PIX_FMT_YUVA420P, bgr24_to_yuva420p}, + {PIX_FMT_BGR24, PIX_FMT_NV12, bgr24_to_nv12}, + {PIX_FMT_BGR24, PIX_FMT_NV21, bgr24_to_nv21}, + {PIX_FMT_BGR24, PIX_FMT_Y800, bgr24_to_y800}, + {PIX_FMT_BGR24, PIX_FMT_Y16, bgr24_to_y16}, + {PIX_FMT_BGR24, PIX_FMT_GRAY8, bgr24_to_gray}, + {PIX_FMT_BGR24, PIX_FMT_GRAY16_L, bgr24_to_gray16_l}, + {PIX_FMT_BGR24, PIX_FMT_GRAY16_B, bgr24_to_gray16_b}, + + {PIX_FMT_BGR32, PIX_FMT_RGB24, bgr32_to_rgb24}, + {PIX_FMT_BGR32, PIX_FMT_RGBA32, bgr32_to_rgba32}, + {PIX_FMT_BGR32, PIX_FMT_YUV420P, bgr32_to_yuv420p}, + {PIX_FMT_BGR32, PIX_FMT_YUVA420P, bgr32_to_yuva420p}, + {PIX_FMT_BGR32, PIX_FMT_NV12, bgr32_to_nv12}, + {PIX_FMT_BGR32, PIX_FMT_NV21, bgr32_to_nv21}, + {PIX_FMT_BGR32, PIX_FMT_Y800, bgr32_to_y800}, + {PIX_FMT_BGR32, PIX_FMT_Y16, bgr32_to_y16}, + {PIX_FMT_BGR32, PIX_FMT_GRAY8, bgr32_to_gray}, + {PIX_FMT_BGR32, PIX_FMT_GRAY16_L, bgr32_to_gray16_l}, + {PIX_FMT_BGR32, PIX_FMT_GRAY16_B, bgr32_to_gray16_b}, + + {PIX_FMT_BGRx32, PIX_FMT_RGB24, bgrx32_to_rgb24}, + {PIX_FMT_BGRx32, PIX_FMT_RGBA32, bgrx32_to_rgba32}, + {PIX_FMT_BGRx32, PIX_FMT_YUV420P, bgrx32_to_yuv420p}, + {PIX_FMT_BGRx32, PIX_FMT_YUVA420P, bgrx32_to_yuva420p}, + {PIX_FMT_BGRx32, PIX_FMT_NV12, bgrx32_to_nv12}, + {PIX_FMT_BGRx32, PIX_FMT_NV21, bgrx32_to_nv21}, + {PIX_FMT_BGRx32, PIX_FMT_Y800, bgrx32_to_y800}, + {PIX_FMT_BGRx32, PIX_FMT_Y16, bgrx32_to_y16}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY8, bgrx32_to_gray}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY16_L, bgrx32_to_gray16_l}, + {PIX_FMT_BGRx32, PIX_FMT_GRAY16_B, bgrx32_to_gray16_b}, + + {PIX_FMT_BGRA32, PIX_FMT_RGB24, bgra32_to_rgb24}, + {PIX_FMT_BGRA32, PIX_FMT_RGBA32, bgra32_to_rgba32}, + {PIX_FMT_BGRA32, PIX_FMT_YUV420P, bgra32_to_yuv420p}, + {PIX_FMT_BGRA32, PIX_FMT_YUVA420P, bgra32_to_yuva420p}, + {PIX_FMT_BGRA32, PIX_FMT_NV12, bgra32_to_nv12}, + {PIX_FMT_BGRA32, PIX_FMT_NV21, bgra32_to_nv21}, + {PIX_FMT_BGRA32, PIX_FMT_Y800, bgra32_to_y800}, + {PIX_FMT_BGRA32, PIX_FMT_Y16, bgra32_to_y16}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY8, bgra32_to_gray}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY16_L, bgra32_to_gray16_l}, + {PIX_FMT_BGRA32, PIX_FMT_GRAY16_B, bgra32_to_gray16_b}, + {PIX_FMT_BGRA32, PIX_FMT_AYUV4444, bgra32_to_ayuv4444}, + + {PIX_FMT_ABGR32, PIX_FMT_RGB24, abgr32_to_rgb24}, + {PIX_FMT_ABGR32, PIX_FMT_RGBA32, abgr32_to_rgba32}, + {PIX_FMT_ABGR32, PIX_FMT_YUV420P, abgr32_to_yuv420p}, + {PIX_FMT_ABGR32, PIX_FMT_YUVA420P, abgr32_to_yuva420p}, + {PIX_FMT_ABGR32, PIX_FMT_NV12, abgr32_to_nv12}, + {PIX_FMT_ABGR32, PIX_FMT_NV21, abgr32_to_nv21}, + {PIX_FMT_ABGR32, PIX_FMT_Y800, abgr32_to_y800}, + {PIX_FMT_ABGR32, PIX_FMT_Y16, abgr32_to_y16}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY8, abgr32_to_gray}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY16_L, abgr32_to_gray16_l}, + {PIX_FMT_ABGR32, PIX_FMT_GRAY16_B, abgr32_to_gray16_b}, + {PIX_FMT_ABGR32, PIX_FMT_AYUV4444, abgr32_to_ayuv4444}, + + {PIX_FMT_ARGB32, PIX_FMT_RGB24, argb32_to_rgb24}, + {PIX_FMT_ARGB32, PIX_FMT_RGBA32, argb32_to_rgba32}, + {PIX_FMT_ARGB32, PIX_FMT_YUV420P, argb32_to_yuv420p}, + {PIX_FMT_ARGB32, PIX_FMT_YUVA420P, argb32_to_yuva420p}, + {PIX_FMT_ARGB32, PIX_FMT_NV12, argb32_to_nv12}, + {PIX_FMT_ARGB32, PIX_FMT_NV21, argb32_to_nv21}, + {PIX_FMT_ARGB32, PIX_FMT_Y800, argb32_to_y800}, + {PIX_FMT_ARGB32, PIX_FMT_Y16, argb32_to_y16}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY8, argb32_to_gray}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY16_L, argb32_to_gray16_l}, + {PIX_FMT_ARGB32, PIX_FMT_GRAY16_B, argb32_to_gray16_b}, + {PIX_FMT_ARGB32, PIX_FMT_AYUV4444, argb32_to_ayuv4444}, + + {PIX_FMT_RGB555, PIX_FMT_RGB24, rgb555_to_rgb24}, + {PIX_FMT_RGB555, PIX_FMT_RGB32, rgb555_to_rgba32}, + {PIX_FMT_RGB555, PIX_FMT_RGBA32, rgb555_to_rgba32}, + {PIX_FMT_RGB555, PIX_FMT_YUV420P, rgb555_to_yuv420p}, + {PIX_FMT_RGB555, PIX_FMT_YUVA420P, rgb555_to_yuva420p}, + {PIX_FMT_RGB555, PIX_FMT_NV12, rgb555_to_nv12}, + {PIX_FMT_RGB555, PIX_FMT_NV21, rgb555_to_nv21}, + {PIX_FMT_RGB555, PIX_FMT_Y800, rgb555_to_y800}, + {PIX_FMT_RGB555, PIX_FMT_Y16, rgb555_to_y16}, + {PIX_FMT_RGB555, PIX_FMT_GRAY8, rgb555_to_gray}, + {PIX_FMT_RGB555, PIX_FMT_GRAY16_L, rgb555_to_gray16_l}, + {PIX_FMT_RGB555, PIX_FMT_GRAY16_B, rgb555_to_gray16_b}, + + {PIX_FMT_RGB565, PIX_FMT_RGB24, rgb565_to_rgb24}, + {PIX_FMT_RGB565, PIX_FMT_YUV420P, rgb565_to_yuv420p}, + {PIX_FMT_RGB565, PIX_FMT_YUVA420P, rgb565_to_yuva420p}, + {PIX_FMT_RGB565, PIX_FMT_NV12, rgb565_to_nv12}, + {PIX_FMT_RGB565, PIX_FMT_NV21, rgb565_to_nv21}, + {PIX_FMT_RGB565, PIX_FMT_Y800, rgb565_to_y800}, + {PIX_FMT_RGB565, PIX_FMT_Y16, rgb565_to_y16}, + {PIX_FMT_RGB565, PIX_FMT_GRAY8, rgb565_to_gray}, + {PIX_FMT_RGB565, PIX_FMT_GRAY16_L, rgb565_to_gray16_l}, + {PIX_FMT_RGB565, PIX_FMT_GRAY16_B, rgb565_to_gray16_b}, + + {PIX_FMT_Y800, PIX_FMT_RGB555, y800_to_rgb555}, + {PIX_FMT_Y800, PIX_FMT_RGB565, y800_to_rgb565}, + {PIX_FMT_Y800, PIX_FMT_BGR24, y800_to_bgr24}, + {PIX_FMT_Y800, PIX_FMT_RGB24, y800_to_rgb24}, + {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_rgb32}, + {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgr32}, + {PIX_FMT_Y800, PIX_FMT_RGB32, y800_to_xrgb32}, + {PIX_FMT_Y800, PIX_FMT_BGR32, y800_to_bgrx32}, + {PIX_FMT_Y800, PIX_FMT_RGBA32, y800_to_rgba32}, + {PIX_FMT_Y800, PIX_FMT_BGRA32, y800_to_bgra32}, + {PIX_FMT_Y800, PIX_FMT_ARGB32, y800_to_argb32}, + {PIX_FMT_Y800, PIX_FMT_ABGR32, y800_to_abgr32}, + {PIX_FMT_Y800, PIX_FMT_Y16, y800_to_y16}, + + {PIX_FMT_Y16, PIX_FMT_RGB555, y16_to_rgb555}, + {PIX_FMT_Y16, PIX_FMT_RGB565, y16_to_rgb565}, + {PIX_FMT_Y16, PIX_FMT_BGR24, y16_to_bgr24}, + {PIX_FMT_Y16, PIX_FMT_RGB24, y16_to_rgb24}, + {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_rgb32}, + {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgr32}, + {PIX_FMT_Y16, PIX_FMT_RGB32, y16_to_xrgb32}, + {PIX_FMT_Y16, PIX_FMT_BGR32, y16_to_bgrx32}, + {PIX_FMT_Y16, PIX_FMT_RGBA32, y16_to_rgba32}, + {PIX_FMT_Y16, PIX_FMT_BGRA32, y16_to_bgra32}, + {PIX_FMT_Y16, PIX_FMT_ARGB32, y16_to_argb32}, + {PIX_FMT_Y16, PIX_FMT_ABGR32, y16_to_abgr32}, + {PIX_FMT_Y16, PIX_FMT_Y800, y16_to_y800}, + + {PIX_FMT_GRAY8, PIX_FMT_RGB555, gray_to_rgb555}, + {PIX_FMT_GRAY8, PIX_FMT_RGB565, gray_to_rgb565}, + {PIX_FMT_GRAY8, PIX_FMT_RGB24, gray_to_rgb24}, + {PIX_FMT_GRAY8, PIX_FMT_BGR24, gray_to_bgr24}, + {PIX_FMT_GRAY8, PIX_FMT_RGB32, gray_to_rgb32}, + {PIX_FMT_GRAY8, PIX_FMT_BGR32, gray_to_bgr32}, + {PIX_FMT_GRAY8, PIX_FMT_xRGB32, gray_to_xrgb32}, + {PIX_FMT_GRAY8, PIX_FMT_BGRx32, gray_to_bgrx32}, + {PIX_FMT_GRAY8, PIX_FMT_RGBA32, gray_to_rgba32}, + {PIX_FMT_GRAY8, PIX_FMT_BGRA32, gray_to_bgra32}, + {PIX_FMT_GRAY8, PIX_FMT_ARGB32, gray_to_argb32}, + {PIX_FMT_GRAY8, PIX_FMT_ABGR32, gray_to_abgr32}, + {PIX_FMT_GRAY8, PIX_FMT_MONOWHITE, gray_to_monowhite}, + {PIX_FMT_GRAY8, PIX_FMT_MONOBLACK, gray_to_monoblack}, + {PIX_FMT_GRAY8, PIX_FMT_GRAY16_L, gray_to_gray16_l}, + {PIX_FMT_GRAY8, PIX_FMT_GRAY16_B, gray_to_gray16_b}, + + {PIX_FMT_MONOWHITE, PIX_FMT_GRAY8, monowhite_to_gray}, + + {PIX_FMT_MONOBLACK, PIX_FMT_GRAY8, monoblack_to_gray}, + + {PIX_FMT_GRAY16_L, PIX_FMT_GRAY8, gray16_l_to_gray}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB555, gray16_l_to_rgb555}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB565, gray16_l_to_rgb565}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGR24, gray16_l_to_bgr24}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB24, gray16_l_to_rgb24}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGR32, gray16_l_to_bgr32}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGB32, gray16_l_to_rgb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_xRGB32, gray16_l_to_xrgb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGRx32, gray16_l_to_bgrx32}, + {PIX_FMT_GRAY16_L, PIX_FMT_ABGR32, gray16_l_to_abgr32}, + {PIX_FMT_GRAY16_L, PIX_FMT_ARGB32, gray16_l_to_argb32}, + {PIX_FMT_GRAY16_L, PIX_FMT_BGRA32, gray16_l_to_bgra32}, + {PIX_FMT_GRAY16_L, PIX_FMT_RGBA32, gray16_l_to_rgba32}, + {PIX_FMT_GRAY16_L, PIX_FMT_GRAY16_B, gray16_b_to_gray16_l}, + + {PIX_FMT_GRAY16_B, PIX_FMT_GRAY8, gray16_b_to_gray}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB555, gray16_b_to_rgb555}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB565, gray16_b_to_rgb565}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGR24, gray16_b_to_bgr24}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB24, gray16_b_to_rgb24}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGR32, gray16_b_to_bgr32}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGB32, gray16_b_to_rgb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_xRGB32, gray16_b_to_xrgb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGRx32, gray16_b_to_bgrx32}, + {PIX_FMT_GRAY16_B, PIX_FMT_ABGR32, gray16_b_to_abgr32}, + {PIX_FMT_GRAY16_B, PIX_FMT_ARGB32, gray16_b_to_argb32}, + {PIX_FMT_GRAY16_B, PIX_FMT_BGRA32, gray16_b_to_bgra32}, + {PIX_FMT_GRAY16_B, PIX_FMT_RGBA32, gray16_b_to_rgba32}, + {PIX_FMT_GRAY16_B, PIX_FMT_GRAY16_L, gray16_b_to_gray16_l}, + + {PIX_FMT_PAL8, PIX_FMT_RGB555, pal8_to_rgb555}, + {PIX_FMT_PAL8, PIX_FMT_RGB565, pal8_to_rgb565}, + {PIX_FMT_PAL8, PIX_FMT_BGR24, pal8_to_bgr24}, + {PIX_FMT_PAL8, PIX_FMT_RGB24, pal8_to_rgb24}, + {PIX_FMT_PAL8, PIX_FMT_RGB32, pal8_to_rgb32}, + {PIX_FMT_PAL8, PIX_FMT_BGR32, pal8_to_bgr32}, + {PIX_FMT_PAL8, PIX_FMT_xRGB32, pal8_to_xrgb32}, + {PIX_FMT_PAL8, PIX_FMT_BGRx32, pal8_to_bgrx32}, + {PIX_FMT_PAL8, PIX_FMT_RGBA32, pal8_to_rgba32}, + {PIX_FMT_PAL8, PIX_FMT_BGRA32, pal8_to_bgra32}, + {PIX_FMT_PAL8, PIX_FMT_ARGB32, pal8_to_argb32}, + {PIX_FMT_PAL8, PIX_FMT_ABGR32, pal8_to_abgr32}, + + {PIX_FMT_UYVY411, PIX_FMT_YUV411P, uyvy411_to_yuv411p}, + {PIX_FMT_YUV411P, PIX_FMT_UYVY411, yuv411p_to_uyvy411}, + + {PIX_FMT_V308, PIX_FMT_RGB24, v308_to_rgb24}, + + {PIX_FMT_AYUV4444, PIX_FMT_RGBA32, ayuv4444_to_rgba32}, + {PIX_FMT_AYUV4444, PIX_FMT_ARGB32, ayuv4444_to_argb32}, + {PIX_FMT_AYUV4444, PIX_FMT_BGRA32, ayuv4444_to_bgra32}, + {PIX_FMT_AYUV4444, PIX_FMT_ABGR32, ayuv4444_to_abgr32}, + {PIX_FMT_AYUV4444, PIX_FMT_RGB24, ayuv4444_to_rgb24}, + {PIX_FMT_AYUV4444, PIX_FMT_YUVA420P, ayuv4444_to_yuva420p}, + + {PIX_FMT_YUVA420P, PIX_FMT_YUV420P, yuva420p_to_yuv420p}, + {PIX_FMT_YUVA420P, PIX_FMT_YUV422, yuva420p_to_yuv422}, + {PIX_FMT_YUVA420P, PIX_FMT_AYUV4444, yuva420p_to_ayuv4444}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB555, yuva420p_to_rgb555}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB565, yuva420p_to_rgb565}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR24, yuva420p_to_bgr24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB24, yuva420p_to_rgb24}, + {PIX_FMT_YUVA420P, PIX_FMT_RGB32, yuva420p_to_rgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGR32, yuva420p_to_bgr32}, + {PIX_FMT_YUVA420P, PIX_FMT_xRGB32, yuva420p_to_xrgb32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRx32, yuva420p_to_bgrx32}, + {PIX_FMT_YUVA420P, PIX_FMT_RGBA32, yuva420p_to_rgba32}, + {PIX_FMT_YUVA420P, PIX_FMT_BGRA32, yuva420p_to_bgra32}, + {PIX_FMT_YUVA420P, PIX_FMT_ARGB32, yuva420p_to_argb32}, + {PIX_FMT_YUVA420P, PIX_FMT_ABGR32, yuva420p_to_abgr32}, +}; + +static ConvertEntry * +get_convert_table_entry (int src_pix_fmt, int dst_pix_fmt) +{ + int i; + + for (i = 0; i < sizeof (convert_table) / sizeof (convert_table[0]); i++) { + if (convert_table[i].src == src_pix_fmt && + convert_table[i].dest == dst_pix_fmt) { + return convert_table + i; + } + } + + return NULL; +} + +static int +avpicture_alloc (AVPicture * picture, int pix_fmt, int width, int height, + int interlaced) +{ + unsigned int size; + void *ptr; + + size = avpicture_get_size (pix_fmt, width, height); + ptr = av_malloc (size); + if (!ptr) + goto fail; + gst_ffmpegcsp_avpicture_fill (picture, ptr, pix_fmt, width, height, + interlaced); + return 0; +fail: + memset (picture, 0, sizeof (AVPicture)); + return -1; +} + +static void +avpicture_free (AVPicture * picture) +{ + av_free (picture->data[0]); +} + +/* return true if yuv planar */ +static inline int +is_yuv_planar (PixFmtInfo * ps) +{ + return (ps->color_type == FF_COLOR_YUV || + ps->color_type == FF_COLOR_YUV_JPEG) && ps->pixel_type == FF_PIXEL_PLANAR; +} + +/* XXX: always use linesize. Return -1 if not supported */ +int +img_convert (AVPicture * dst, int dst_pix_fmt, + const AVPicture * src, int src_pix_fmt, int src_width, int src_height) +{ + static int inited; + int i, ret, dst_width, dst_height, int_pix_fmt; + PixFmtInfo *src_pix, *dst_pix; + ConvertEntry *ce; + AVPicture tmp1, *tmp = &tmp1; + + if (G_UNLIKELY (src_width <= 0 || src_height <= 0)) + return 0; + + if (G_UNLIKELY (!inited)) { + inited = 1; + img_convert_init (); + } + + dst_width = src_width; + dst_height = src_height; + + dst_pix = get_pix_fmt_info (dst_pix_fmt); + src_pix = get_pix_fmt_info (src_pix_fmt); + if (G_UNLIKELY (src_pix_fmt == dst_pix_fmt)) { + /* no conversion needed: just copy */ + img_copy (dst, src, dst_pix_fmt, dst_width, dst_height); + return 0; + } + + ce = get_convert_table_entry (src_pix_fmt, dst_pix_fmt); + if (ce && ce->convert) { + /* specific conversion routine */ + ce->convert (dst, src, dst_width, dst_height); + return 0; + } + + /* gray to YUV */ + if (is_yuv_planar (dst_pix) && dst_pix_fmt != PIX_FMT_Y16 + && src_pix_fmt == PIX_FMT_GRAY8) { + int w, h, y; + uint8_t *d; + + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) { + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + } else { + img_apply_table (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], + dst_width, dst_height, y_jpeg_to_ccir); + } + /* fill U and V with 128 */ + w = dst_width; + h = dst_height; + w >>= dst_pix->x_chroma_shift; + h >>= dst_pix->y_chroma_shift; + for (i = 1; i <= 2; i++) { + d = dst->data[i]; + if (!d) + continue; + for (y = 0; y < h; y++) { + memset (d, 128, w); + d += dst->linesize[i]; + } + } + return 0; + } + + /* YUV to gray */ + if (is_yuv_planar (src_pix) && src_pix_fmt != PIX_FMT_Y16 + && dst_pix_fmt == PIX_FMT_GRAY8) { + if (src_pix->color_type == FF_COLOR_YUV_JPEG) { + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + } else { + img_apply_table (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], + dst_width, dst_height, y_ccir_to_jpeg); + } + return 0; + } + + /* YUV to YUV planar */ + if (is_yuv_planar (dst_pix) && is_yuv_planar (src_pix) && + dst_pix->depth == src_pix->depth) { + int x_shift, y_shift, xy_shift; + void (*resize_func) (uint8_t * dst, int dst_wrap, int dst_width, + int dst_height, const uint8_t * src, int src_wrap, int src_width, + int src_height); + + x_shift = (dst_pix->x_chroma_shift - src_pix->x_chroma_shift); + y_shift = (dst_pix->y_chroma_shift - src_pix->y_chroma_shift); + xy_shift = ((x_shift & 0xf) << 4) | (y_shift & 0xf); + + /* there must be filters for conversion at least from and to + YUV444 format */ + switch (xy_shift) { + case 0x00: + resize_func = img_copy_plane_resize; + break; + case 0x10: + resize_func = shrink21; + break; + case 0x20: + resize_func = shrink41; + break; + case 0x01: + resize_func = shrink12; + break; + case 0x11: + resize_func = shrink22; + break; + case 0x22: + resize_func = shrink44; + break; + case 0xf0: + resize_func = grow21; + break; + case 0xe0: + resize_func = grow41; + break; + case 0xff: + resize_func = grow22; + break; + case 0xee: + resize_func = grow44; + break; + case 0xf1: + resize_func = conv411; + break; + default: + /* currently not handled */ + goto no_chroma_filter; + } + + img_copy_plane (dst->data[0], dst->linesize[0], + src->data[0], src->linesize[0], dst_width, dst_height); + +#define GEN_MASK(x) ((1<<(x))-1) +#define DIV_ROUND_UP_X(v,x) (((v) + GEN_MASK(x)) >> (x)) + + for (i = 1; i <= 2; i++) { + gint w, h; + gint s_w, s_h; + + w = DIV_ROUND_UP_X (dst_width, dst_pix->x_chroma_shift); + h = DIV_ROUND_UP_X (dst_height, dst_pix->y_chroma_shift); + + s_w = DIV_ROUND_UP_X (src_width, src_pix->x_chroma_shift); + s_h = DIV_ROUND_UP_X (src_height, src_pix->y_chroma_shift); + + if (src->data[i] != NULL && dst->data[i] != NULL) { + resize_func (dst->data[i], dst->linesize[i], w, h, + src->data[i], src->linesize[i], s_w, s_h); + } else if (dst->data[i] != NULL) { + memset (dst->data[i], 128, dst->linesize[i] * h); + } + } + /* if yuv color space conversion is needed, we do it here on + the destination image */ + if (dst_pix->color_type != src_pix->color_type) { + const uint8_t *y_table, *c_table; + + if (dst_pix->color_type == FF_COLOR_YUV) { + y_table = y_jpeg_to_ccir; + c_table = c_jpeg_to_ccir; + } else { + y_table = y_ccir_to_jpeg; + c_table = c_ccir_to_jpeg; + } + img_apply_table (dst->data[0], dst->linesize[0], + dst->data[0], dst->linesize[0], dst_width, dst_height, y_table); + + for (i = 1; i <= 2; i++) + img_apply_table (dst->data[i], dst->linesize[i], + dst->data[i], dst->linesize[i], + dst_width >> dst_pix->x_chroma_shift, + dst_height >> dst_pix->y_chroma_shift, c_table); + } + return 0; + } +no_chroma_filter: + GST_CAT_INFO (ffmpegcolorspace_performance, + "no direct path to convert colorspace from %s -> %s", src_pix->name, + dst_pix->name); + + /* try to use an intermediate format */ + if (src_pix_fmt == PIX_FMT_YUV422 || dst_pix_fmt == PIX_FMT_YUV422) { + /* specific case: convert to YUV422P first */ + int_pix_fmt = PIX_FMT_YUV422P; + } else if (src_pix_fmt == PIX_FMT_UYVY422 || dst_pix_fmt == PIX_FMT_UYVY422 || + src_pix_fmt == PIX_FMT_YVYU422 || dst_pix_fmt == PIX_FMT_YVYU422) { + /* specific case: convert to YUV422P first */ + int_pix_fmt = PIX_FMT_YUV422P; + } else if (src_pix_fmt == PIX_FMT_UYVY411 || dst_pix_fmt == PIX_FMT_UYVY411) { + /* specific case: convert to YUV411P first */ + int_pix_fmt = PIX_FMT_YUV411P; + } else if ((src_pix->color_type == FF_COLOR_GRAY && + src_pix_fmt != PIX_FMT_GRAY8) || + (dst_pix->color_type == FF_COLOR_GRAY && dst_pix_fmt != PIX_FMT_GRAY8)) { + /* gray8 is the normalized format */ + int_pix_fmt = PIX_FMT_GRAY8; + } else if (src_pix_fmt == PIX_FMT_Y16 || dst_pix_fmt == PIX_FMT_Y16) { + /* y800 is the normalized format */ + int_pix_fmt = PIX_FMT_Y800; + } else if ((is_yuv_planar (src_pix) && + src_pix_fmt != PIX_FMT_YUV444P && src_pix_fmt != PIX_FMT_YUVJ444P)) { + /* yuv444 is the normalized format */ + if (src_pix->color_type == FF_COLOR_YUV_JPEG) + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } else if ((is_yuv_planar (dst_pix) && + dst_pix_fmt != PIX_FMT_YUV444P && dst_pix_fmt != PIX_FMT_YUVJ444P)) { + /* yuv444 is the normalized format */ + if (dst_pix->color_type == FF_COLOR_YUV_JPEG) + int_pix_fmt = PIX_FMT_YUVJ444P; + else + int_pix_fmt = PIX_FMT_YUV444P; + } else { + /* the two formats are rgb or gray8 or yuv[j]444p */ + if (src_pix->is_alpha && dst_pix->is_alpha) + int_pix_fmt = PIX_FMT_RGBA32; + else + int_pix_fmt = PIX_FMT_RGB24; + } + if (avpicture_alloc (tmp, int_pix_fmt, dst_width, dst_height, + dst->interlaced) < 0) + return -1; + ret = -1; + if (img_convert (tmp, int_pix_fmt, + src, src_pix_fmt, src_width, src_height) < 0) + goto fail1; + + if (img_convert (dst, dst_pix_fmt, + tmp, int_pix_fmt, dst_width, dst_height) < 0) + goto fail1; + ret = 0; +fail1: + avpicture_free (tmp); + return ret; +} + +/* NOTE: we scan all the pixels to have an exact information */ +static int +get_alpha_info_pal8 (const AVPicture * src, int width, int height) +{ + const unsigned char *p; + int src_wrap, ret, x, y; + unsigned int a; + uint32_t *palette = (uint32_t *) src->data[1]; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + ret = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + a = palette[p[0]] >> 24; + if (a == 0x00) { + ret |= FF_ALPHA_TRANSP; + } else if (a != 0xff) { + ret |= FF_ALPHA_SEMI_TRANSP; + } + p++; + } + p += src_wrap; + } + return ret; +} + +/** + * Tell if an image really has transparent alpha values. + * @return ored mask of FF_ALPHA_xxx constants + */ +int +img_get_alpha_info (const AVPicture * src, int pix_fmt, int width, int height) +{ + const PixFmtInfo *pf; + int ret; + + pf = get_pix_fmt_info (pix_fmt); + /* no alpha can be represented in format */ + if (!pf->is_alpha) + return 0; + switch (pix_fmt) { + case PIX_FMT_RGB32: + ret = get_alpha_info_rgb32 (src, width, height); + break; + case PIX_FMT_BGR32: + ret = get_alpha_info_bgr32 (src, width, height); + break; + case PIX_FMT_xRGB32: + ret = get_alpha_info_xrgb32 (src, width, height); + break; + case PIX_FMT_BGRx32: + ret = get_alpha_info_bgrx32 (src, width, height); + break; + case PIX_FMT_RGBA32: + ret = get_alpha_info_rgba32 (src, width, height); + break; + case PIX_FMT_BGRA32: + ret = get_alpha_info_bgra32 (src, width, height); + break; + case PIX_FMT_ARGB32: + ret = get_alpha_info_argb32 (src, width, height); + break; + case PIX_FMT_ABGR32: + ret = get_alpha_info_abgr32 (src, width, height); + break; + case PIX_FMT_RGB555: + ret = get_alpha_info_rgb555 (src, width, height); + break; + case PIX_FMT_PAL8: + ret = get_alpha_info_pal8 (src, width, height); + break; + default: + /* we do not know, so everything is indicated */ + ret = FF_ALPHA_TRANSP | FF_ALPHA_SEMI_TRANSP; + break; + } + return ret; +} + +#ifdef HAVE_MMX +#define DEINT_INPLACE_LINE_LUM \ + movd_m2r(lum_m4[0],mm0);\ + movd_m2r(lum_m3[0],mm1);\ + movd_m2r(lum_m2[0],mm2);\ + movd_m2r(lum_m1[0],mm3);\ + movd_m2r(lum[0],mm4);\ + punpcklbw_r2r(mm7,mm0);\ + movd_r2m(mm2,lum_m4[0]);\ + punpcklbw_r2r(mm7,mm1);\ + punpcklbw_r2r(mm7,mm2);\ + punpcklbw_r2r(mm7,mm3);\ + punpcklbw_r2r(mm7,mm4);\ + paddw_r2r(mm3,mm1);\ + psllw_i2r(1,mm2);\ + paddw_r2r(mm4,mm0);\ + psllw_i2r(2,mm1);\ + paddw_r2r(mm6,mm2);\ + paddw_r2r(mm2,mm1);\ + psubusw_r2r(mm0,mm1);\ + psrlw_i2r(3,mm1);\ + packuswb_r2r(mm7,mm1);\ + movd_r2m(mm1,lum_m2[0]); + +#define DEINT_LINE_LUM \ + movd_m2r(lum_m4[0],mm0);\ + movd_m2r(lum_m3[0],mm1);\ + movd_m2r(lum_m2[0],mm2);\ + movd_m2r(lum_m1[0],mm3);\ + movd_m2r(lum[0],mm4);\ + punpcklbw_r2r(mm7,mm0);\ + punpcklbw_r2r(mm7,mm1);\ + punpcklbw_r2r(mm7,mm2);\ + punpcklbw_r2r(mm7,mm3);\ + punpcklbw_r2r(mm7,mm4);\ + paddw_r2r(mm3,mm1);\ + psllw_i2r(1,mm2);\ + paddw_r2r(mm4,mm0);\ + psllw_i2r(2,mm1);\ + paddw_r2r(mm6,mm2);\ + paddw_r2r(mm2,mm1);\ + psubusw_r2r(mm0,mm1);\ + psrlw_i2r(3,mm1);\ + packuswb_r2r(mm7,mm1);\ + movd_r2m(mm1,dst[0]); +#endif + +/* filter parameters: [-1 4 2 4 -1] // 8 */ +#if 0 +static void +deinterlace_line (uint8_t * dst, + const uint8_t * lum_m4, const uint8_t * lum_m3, + const uint8_t * lum_m2, const uint8_t * lum_m1, + const uint8_t * lum, int size) +{ +#ifndef HAVE_MMX + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int sum; + + for (; size > 0; size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + sum += lum_m1[0] << 2; + sum += -lum[0]; + dst[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + dst++; + } +#else + + { + mmx_t rounder; + + rounder.uw[0] = 4; + rounder.uw[1] = 4; + rounder.uw[2] = 4; + rounder.uw[3] = 4; + pxor_r2r (mm7, mm7); + movq_m2r (rounder, mm6); + } + for (; size > 3; size -= 4) { + DEINT_LINE_LUM lum_m4 += 4; + + lum_m3 += 4; + lum_m2 += 4; + lum_m1 += 4; + lum += 4; + dst += 4; + } +#endif +} + +static void +deinterlace_line_inplace (uint8_t * lum_m4, uint8_t * lum_m3, uint8_t * lum_m2, + uint8_t * lum_m1, uint8_t * lum, int size) +{ +#ifndef HAVE_MMX + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int sum; + + for (; size > 0; size--) { + sum = -lum_m4[0]; + sum += lum_m3[0] << 2; + sum += lum_m2[0] << 1; + lum_m4[0] = lum_m2[0]; + sum += lum_m1[0] << 2; + sum += -lum[0]; + lum_m2[0] = cm[(sum + 4) >> 3]; + lum_m4++; + lum_m3++; + lum_m2++; + lum_m1++; + lum++; + } +#else + + { + mmx_t rounder; + + rounder.uw[0] = 4; + rounder.uw[1] = 4; + rounder.uw[2] = 4; + rounder.uw[3] = 4; + pxor_r2r (mm7, mm7); + movq_m2r (rounder, mm6); + } + for (; size > 3; size -= 4) { + DEINT_INPLACE_LINE_LUM lum_m4 += 4; + + lum_m3 += 4; + lum_m2 += 4; + lum_m1 += 4; + lum += 4; + } +#endif +} +#endif + +/* deinterlacing : 2 temporal taps, 3 spatial taps linear filter. The + top field is copied as is, but the bottom field is deinterlaced + against the top field. */ +#if 0 +static void +deinterlace_bottom_field (uint8_t * dst, int dst_wrap, + const uint8_t * src1, int src_wrap, int width, int height) +{ + const uint8_t *src_m2, *src_m1, *src_0, *src_p1, *src_p2; + int y; + + src_m2 = src1; + src_m1 = src1; + src_0 = &src_m1[src_wrap]; + src_p1 = &src_0[src_wrap]; + src_p2 = &src_p1[src_wrap]; + for (y = 0; y < (height - 2); y += 2) { + memcpy (dst, src_m1, width); + dst += dst_wrap; + deinterlace_line (dst, src_m2, src_m1, src_0, src_p1, src_p2, width); + src_m2 = src_0; + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2 * src_wrap; + src_p2 += 2 * src_wrap; + dst += dst_wrap; + } + memcpy (dst, src_m1, width); + dst += dst_wrap; + /* do last line */ + deinterlace_line (dst, src_m2, src_m1, src_0, src_0, src_0, width); +} + +static void +deinterlace_bottom_field_inplace (uint8_t * src1, int src_wrap, + int width, int height) +{ + uint8_t *src_m1, *src_0, *src_p1, *src_p2; + int y; + uint8_t *buf; + + buf = (uint8_t *) av_malloc (width); + + src_m1 = src1; + memcpy (buf, src_m1, width); + src_0 = &src_m1[src_wrap]; + src_p1 = &src_0[src_wrap]; + src_p2 = &src_p1[src_wrap]; + for (y = 0; y < (height - 2); y += 2) { + deinterlace_line_inplace (buf, src_m1, src_0, src_p1, src_p2, width); + src_m1 = src_p1; + src_0 = src_p2; + src_p1 += 2 * src_wrap; + src_p2 += 2 * src_wrap; + } + /* do last line */ + deinterlace_line_inplace (buf, src_m1, src_0, src_0, src_0, width); + av_free (buf); +} +#endif + +/* deinterlace - if not supported return -1 */ +#if 0 +static int +avpicture_deinterlace (AVPicture * dst, const AVPicture * src, + int pix_fmt, int width, int height) +{ + int i; + + if (pix_fmt != PIX_FMT_YUV420P && + pix_fmt != PIX_FMT_YUV422P && + pix_fmt != PIX_FMT_YUV444P && pix_fmt != PIX_FMT_YUV411P) + return -1; + if ((width & 3) != 0 || (height & 3) != 0) + return -1; + + for (i = 0; i < 3; i++) { + if (i == 1) { + switch (pix_fmt) { + case PIX_FMT_YUV420P: + width >>= 1; + height >>= 1; + break; + case PIX_FMT_YUV422P: + width >>= 1; + break; + case PIX_FMT_YUV411P: + width >>= 2; + break; + default: + break; + } + } + if (src == dst) { + deinterlace_bottom_field_inplace (dst->data[i], dst->linesize[i], + width, height); + } else { + deinterlace_bottom_field (dst->data[i], dst->linesize[i], + src->data[i], src->linesize[i], width, height); + } + } +#ifdef HAVE_MMX + emms (); +#endif + return 0; +} +#endif + +#undef FIX diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert_template.h b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert_template.h new file mode 100644 index 0000000..3b287e7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/imgconvert_template.h @@ -0,0 +1,2188 @@ +/* + * Templates for image convertion routines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef RGB_OUT +#define RGB_OUT(d, r, g, b) RGBA_OUT(d, r, g, b, 0xffU) +#endif + +static void glue (uyvy422_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + s = src->data[0]; + for(;height > 0; height --) { + d1 = d; + s1 = s; + for(w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR(s1[0], s1[2]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[1]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + YUV_TO_RGB2_CCIR(r, g, b, s1[3]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + s1 += 4; + } + + if (w) { + YUV_TO_RGB1_CCIR(s1[0], s1[2]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[1]); + RGB_OUT(d1, r, g, b); + } + + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void glue (yuv422_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + s = src->data[0]; + for(;height > 0; height --) { + d1 = d; + s1 = s; + for(w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR(s1[1], s1[3]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[0]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + YUV_TO_RGB2_CCIR(r, g, b, s1[2]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + s1 += 4; + } + + if (w) { + YUV_TO_RGB1_CCIR(s1[1], s1[3]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[0]); + RGB_OUT(d1, r, g, b); + } + + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void glue (yvyu422_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + s = src->data[0]; + for(;height > 0; height --) { + d1 = d; + s1 = s; + for(w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR(s1[3], s1[1]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[0]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + YUV_TO_RGB2_CCIR(r, g, b, s1[2]); + RGB_OUT(d1, r, g, b); + d1 += BPP; + + s1 += 4; + } + + if (w) { + YUV_TO_RGB1_CCIR(s1[3], s1[1]); + + YUV_TO_RGB2_CCIR(r, g, b, s1[0]); + RGB_OUT(d1, r, g, b); + } + + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void glue (yuv420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 4 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[1]); + RGB_OUT (d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + } + /* handle width */ + if (w) { + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixel */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + } +} + +#ifndef RGBA_OUT +#define RGBA_OUT_(d, r, g, b, a) RGB_OUT(d, r, g, b) +#define YUVA_TO_A(d, a) +#else +#define RGBA_OUT_(d, r, g, b, a) RGBA_OUT(d, r, g, b, a) +#define YUVA_TO_A(d, a) do { d = a; } while (0); +#endif + +static void glue (yuva420p_to_, RGB_NAME)(AVPicture *dst, const AVPicture *src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr, *a1_ptr, *a2_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; +#ifdef RGBA_OUT + unsigned int a = 0; +#endif + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + a1_ptr = src->data[3]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + a2_ptr = a1_ptr + src->linesize[3]; + for (w = width; w >= 2; w -= 2) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 4 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a1_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGBA_OUT_ (d1 + BPP, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGBA_OUT_ (d2, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[1]); + RGBA_OUT_ (d2 + BPP, r, g, b, a); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + a2_ptr += 2; + } + /* handle odd width */ + if (w) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a2_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGBA_OUT_ (d2, r, g, b, a); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + a2_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + a1_ptr += 2 * src->linesize[3] - width; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + + YUVA_TO_A (a, a1_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGBA_OUT_ (d1 + BPP, r, g, b, a); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + a1_ptr += 2; + } + /* handle width */ + if (w) { + YUVA_TO_A (a, a1_ptr[0]); + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + /* output 2 pixel */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGBA_OUT_ (d1, r, g, b, a); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + a1_ptr++; + } + } +} + +static void glue (nv12_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *c_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + int c_wrap = src->linesize[1] - ((width + 1) & ~0x01); + + d = dst->data[0]; + y1_ptr = src->data[0]; + c_ptr = src->data[1]; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (c_ptr[0], c_ptr[1]); + /* output 4 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[1]); + RGB_OUT (d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + c_ptr += 2; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1_CCIR (c_ptr[0], c_ptr[1]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + c_ptr += 2; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + c_ptr += c_wrap; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (c_ptr[0], c_ptr[1]); + /* output 2 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + c_ptr += 2; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1_CCIR (c_ptr[0], c_ptr[1]); + /* output 1 pixel */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + c_ptr += 2; + } + } +} + +static void glue (nv21_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *c_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + int c_wrap = src->linesize[1] - ((width + 1) & ~0x01); + + d = dst->data[0]; + y1_ptr = src->data[0]; + c_ptr = src->data[1]; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (c_ptr[1], c_ptr[0]); + /* output 4 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[1]); + RGB_OUT (d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + c_ptr += 2; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1_CCIR (c_ptr[1], c_ptr[0]); + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + c_ptr += 2; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + c_ptr += c_wrap; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1_CCIR (c_ptr[1], c_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + c_ptr += 2; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1_CCIR (c_ptr[1], c_ptr[0]); + /* output 1 pixel */ + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + c_ptr += 2; + } + } +} + +static void glue (yuvj420p_to_, RGB_NAME) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const uint8_t *y1_ptr, *y2_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1, *d2; + int w, y, cb, cr, r_add, g_add, b_add, width2; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + width2 = (width + 1) >> 1; + for (; height >= 2; height -= 2) { + d1 = d; + d2 = d + dst->linesize[0]; + y2_ptr = y1_ptr + src->linesize[0]; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1 (cb_ptr[0], cr_ptr[0]); + /* output 4 pixels */ + YUV_TO_RGB2 (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2 (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + YUV_TO_RGB2 (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + + YUV_TO_RGB2 (r, g, b, y2_ptr[1]); + RGB_OUT (d2 + BPP, r, g, b); + + d1 += 2 * BPP; + d2 += 2 * BPP; + + y1_ptr += 2; + y2_ptr += 2; + cb_ptr++; + cr_ptr++; + } + /* handle odd width */ + if (w) { + YUV_TO_RGB1 (cb_ptr[0], cr_ptr[0]); + YUV_TO_RGB2 (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2 (r, g, b, y2_ptr[0]); + RGB_OUT (d2, r, g, b); + d1 += BPP; + d2 += BPP; + y1_ptr++; + y2_ptr++; + cb_ptr++; + cr_ptr++; + } + d += 2 * dst->linesize[0]; + y1_ptr += 2 * src->linesize[0] - width; + cb_ptr += src->linesize[1] - width2; + cr_ptr += src->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + d1 = d; + for (w = width; w >= 2; w -= 2) { + YUV_TO_RGB1 (cb_ptr[0], cr_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2 (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + + YUV_TO_RGB2 (r, g, b, y1_ptr[1]); + RGB_OUT (d1 + BPP, r, g, b); + + d1 += 2 * BPP; + + y1_ptr += 2; + cb_ptr++; + cr_ptr++; + } + /* handle width */ + if (w) { + YUV_TO_RGB1 (cb_ptr[0], cr_ptr[0]); + /* output 2 pixels */ + YUV_TO_RGB2 (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + } +} + +static void glue (y800_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = Y_CCIR_TO_JPEG (p[0]); + RGB_OUT (q, r, r, r); + q += BPP; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (y16_to_, RGB_NAME) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = Y_CCIR_TO_JPEG (GST_READ_UINT16_LE (p) >> 8); + RGB_OUT (q, r, r, r); + q += BPP; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_yuv420p) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 2); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 2); + + + cb++; + cr++; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + } + if (w) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += -wrap3 + BPP; + lum += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + } + if (w) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + cb[0] = RGB_TO_U_CCIR (r, g, b, 0); + cr[0] = RGB_TO_V_CCIR (r, g, b, 0); + } + } +} + +#ifndef RGBA_IN +#define RGBA_IN_(r, g, b, a, p) RGB_IN(r, g, b, p) +#else +#define RGBA_IN_(r, g, b, a, p) RGBA_IN(r, g, b, a, p) +#endif + +static void glue (RGB_NAME, _to_yuva420p) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w, ra = 255; + uint8_t *lum, *cb, *cr, *a; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + a = dst->data[3]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + p += wrap3; + lum += wrap; + a += wrap; + + RGBA_IN_ (r, g, b, ra, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 2); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 2); + + cb++; + cr++; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + a += -wrap + 2; + } + if (w) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + p += wrap3; + lum += wrap; + a += wrap; + RGBA_IN_ (r, g, b, ra, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += -wrap3 + BPP; + lum += -wrap + 1; + a += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + a += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGBA_IN_ (r, g, b, ra, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + + RGBA_IN_ (r, g, b, ra, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + a[1] = ra; + cb[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + cr[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + a += 2; + } + if (w) { + RGBA_IN_ (r, g, b, ra, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + a[0] = ra; + cb[0] = RGB_TO_U_CCIR (r, g, b, 0); + cr[0] = RGB_TO_V_CCIR (r, g, b, 0); + } + } +} + +static void glue (RGB_NAME, _to_nv12) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int wrap, wrap3; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *c; + const uint8_t *p; + + lum = dst->data[0]; + c = dst->data[1]; + + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + + c[0] = RGB_TO_U_CCIR (r1, g1, b1, 2); + c[1] = RGB_TO_V_CCIR (r1, g1, b1, 2); + + + c += 2; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + } + /* handle odd width */ + if (w) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + c[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + c[1] = RGB_TO_V_CCIR (r1, g1, b1, 1); + p += -wrap3 + BPP; + lum += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + c += dst->linesize[1] - (width & ~1); + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + c[0] = RGB_TO_U_CCIR (r1, g1, b1, 1); + c[1] = RGB_TO_V_CCIR (r1, g1, b1, 1); + c += 2; + p += 2 * BPP; + lum += 2; + } + /* handle odd width */ + if (w) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + c[0] = RGB_TO_U_CCIR (r, g, b, 0); + c[1] = RGB_TO_V_CCIR (r, g, b, 0); + } + } +} + +static void glue (RGB_NAME, _to_nv21) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int wrap, wrap3; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *c; + const uint8_t *p; + + lum = dst->data[0]; + c = dst->data[1]; + + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + + c[1] = RGB_TO_U_CCIR (r1, g1, b1, 2); + c[0] = RGB_TO_V_CCIR (r1, g1, b1, 2); + + + c += 2; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + } + /* handle odd width */ + if (w) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + p += wrap3; + lum += wrap; + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + c[1] = RGB_TO_U_CCIR (r1, g1, b1, 1); + c[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + p += -wrap3 + BPP; + lum += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + c += dst->linesize[1] - (width & ~1); + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y_CCIR (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y_CCIR (r, g, b); + c[1] = RGB_TO_U_CCIR (r1, g1, b1, 1); + c[0] = RGB_TO_V_CCIR (r1, g1, b1, 1); + c += 2; + p += 2 * BPP; + lum += 2; + } + /* handle odd width */ + if (w) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + c[1] = RGB_TO_U_CCIR (r, g, b, 0); + c[0] = RGB_TO_V_CCIR (r, g, b, 0); + } + } +} + +static void glue (RGB_NAME, _to_gray) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + q[0] = RGB_TO_Y (r, g, b); + q++; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_y800) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + q[0] = RGB_TO_Y_CCIR (r, g, b); + q++; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_y16) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + GST_WRITE_UINT16_LE (q, RGB_TO_Y_CCIR (r, g, b) << 8); + q += 2; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (gray_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = p[0]; + RGB_OUT (q, r, r, r); + q += BPP; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_gray16_l) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + GST_WRITE_UINT16_LE (q, RGB_TO_Y (r, g, b) << 8); + q += 2; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (gray16_l_to_, RGB_NAME) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = GST_READ_UINT16_LE (p) >> 8; + RGB_OUT (q, r, r, r); + q += BPP; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_gray16_b) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - 2 * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + GST_WRITE_UINT16_BE (q, RGB_TO_Y (r, g, b) << 8); + q += 2; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (gray16_b_to_, RGB_NAME) (AVPicture * dst, + const AVPicture * src, int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, dst_wrap, src_wrap; + int x, y; + + p = src->data[0]; + src_wrap = src->linesize[0] - 2 * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + r = GST_READ_UINT16_BE (p) >> 8; + RGB_OUT (q, r, r, r); + q += BPP; + p += 2; + } + p += src_wrap; + q += dst_wrap; + } +} + +static void glue (pal8_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int r, g, b, dst_wrap, src_wrap; + int x, y; + uint32_t v; + const uint32_t *palette; + + p = src->data[0]; + src_wrap = src->linesize[0] - width; + palette = (uint32_t *) src->data[1]; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - BPP * width; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + v = palette[p[0]]; + r = (v >> 16) & 0xff; + g = (v >> 8) & 0xff; + b = (v) & 0xff; +#ifdef RGBA_OUT + { + int a; + a = (v >> 24) & 0xff; + RGBA_OUT (q, r, g, b, a); + } +#else + RGB_OUT (q, r, g, b); +#endif + q += BPP; + p++; + } + p += src_wrap; + q += dst_wrap; + } +} + +#if !defined(FMT_RGBA32) && defined(RGBA_OUT) +/* alpha support */ + +static void glue (rgba32_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int v, r, g, b, a; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * 4; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * BPP; + + for (y = 0; y < height; y++) { + for (j = 0; j < width; j++) { + v = ((const uint32_t *) (s))[0]; + a = (v >> 24) & 0xff; + r = (v >> 16) & 0xff; + g = (v >> 8) & 0xff; + b = v & 0xff; + RGBA_OUT (d, r, g, b, a); + s += 4; + d += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_rgba32) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b, a; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * BPP; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * 4; + + for (y = 0; y < height; y++) { + for (j = 0; j < width; j++) { + RGBA_IN (r, g, b, a, s); + ((uint32_t *) (d))[0] = (a << 24) | (r << 16) | (g << 8) | b; + d += 4; + s += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} +#endif /* !defined(FMT_RGBA32) && defined(RGBA_OUT) */ + +#if defined(FMT_RGBA32) + +#if !defined(rgba32_fcts_done) +#define rgba32_fcts_done + +static void +ayuv4444_to_rgba32 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b, a; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + a = s1[0]; + YUV_TO_RGB1_CCIR (s1[2], s1[3]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[1]); + RGBA_OUT (d1, r, g, b, a); + d1 += BPP; + s1 += 4; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void +rgba32_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b, a; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 4; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGBA_IN (r, g, b, a, p); + d[0] = a; + d[1] = RGB_TO_Y_CCIR (r, g, b); + d[2] = RGB_TO_U_CCIR (r, g, b, 0); + d[3] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 4; + } + p += src_wrap; + d += dst_wrap; + } +} + +#endif /* !defined(rgba32_fcts_done) */ + +#endif /* defined(FMT_RGBA32) */ + +#if defined(FMT_BGRA32) +#if !defined(bgra32_fcts_done) +#define bgra32_fcts_done + +static void +bgra32_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b, a; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 4; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGBA_IN (r, g, b, a, p); + d[0] = a; + d[1] = RGB_TO_Y_CCIR (r, g, b); + d[2] = RGB_TO_U_CCIR (r, g, b, 0); + d[3] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 4; + } + p += src_wrap; + d += dst_wrap; + } +} + +static void +ayuv4444_to_bgra32 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b, a; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + a = s1[0]; + YUV_TO_RGB1_CCIR (s1[2], s1[3]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[1]); + RGBA_OUT (d1, r, g, b, a); + d1 += BPP; + s1 += 4; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +#endif /* !defined(bgra32_fcts_done) */ + +#endif /* defined(FMT_BGRA32) */ + +#if defined(FMT_ARGB32) + +#if !defined(argb32_fcts_done) +#define argb32_fcts_done + +static void +ayuv4444_to_argb32 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b, a; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + a = s1[0]; + YUV_TO_RGB1_CCIR (s1[2], s1[3]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[1]); + RGBA_OUT (d1, r, g, b, a); + d1 += BPP; + s1 += 4; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void +argb32_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b, a; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 4; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGBA_IN (r, g, b, a, p); + d[0] = a; + d[1] = RGB_TO_Y_CCIR (r, g, b); + d[2] = RGB_TO_U_CCIR (r, g, b, 0); + d[3] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 4; + } + p += src_wrap; + d += dst_wrap; + } +} + +#endif /* !defined(argb32_fcts_done) */ + +#endif /* defined(FMT_ARGB32) */ + +#if defined(FMT_ABGR32) +#if !defined(abgr32_fcts_done) +#define abgr32_fcts_done + +static void +abgr32_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b, a; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 4; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGBA_IN (r, g, b, a, p); + d[0] = a; + d[1] = RGB_TO_Y_CCIR (r, g, b); + d[2] = RGB_TO_U_CCIR (r, g, b, 0); + d[3] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 4; + } + p += src_wrap; + d += dst_wrap; + } +} + +static void +ayuv4444_to_abgr32 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b, a; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + a = s1[0]; + YUV_TO_RGB1_CCIR (s1[2], s1[3]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[1]); + RGBA_OUT (d1, r, g, b, a); + d1 += BPP; + s1 += 4; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +#endif /* !defined(abgr32_fcts_done) */ + +#endif /* defined(FMT_ABGR32) */ + +#ifndef FMT_RGB24 + +static void glue (rgb24_to_, RGB_NAME) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * 3; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * BPP; + + for (y = 0; y < height; y++) { + for (j = 0; j < width; j++) { + r = s[0]; + g = s[1]; + b = s[2]; + RGB_OUT (d, r, g, b); + s += 3; + d += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +static void glue (RGB_NAME, _to_rgb24) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *s; + uint8_t *d; + int src_wrap, dst_wrap, j, y; + unsigned int r, g, b; + + s = src->data[0]; + src_wrap = src->linesize[0] - width * BPP; + + d = dst->data[0]; + dst_wrap = dst->linesize[0] - width * 3; + + for (y = 0; y < height; y++) { + for (j = 0; j < width; j++) { + RGB_IN (r, g, b, s) + d[0] = r; + d[1] = g; + d[2] = b; + d += 3; + s += BPP; + } + s += src_wrap; + d += dst_wrap; + } +} + +#endif /* !FMT_RGB24 */ + +#ifdef FMT_RGB24 + +static void +yuv444p_to_rgb24 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + const uint8_t *y1_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + for (; height > 0; height--) { + d1 = d; + for (w = width; w > 0; w--) { + YUV_TO_RGB1_CCIR (cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2_CCIR (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + d += dst->linesize[0]; + y1_ptr += src->linesize[0] - width; + cb_ptr += src->linesize[1] - width; + cr_ptr += src->linesize[2] - width; + } +} + +static void +yuvj444p_to_rgb24 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const uint8_t *y1_ptr, *cb_ptr, *cr_ptr; + uint8_t *d, *d1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + y1_ptr = src->data[0]; + cb_ptr = src->data[1]; + cr_ptr = src->data[2]; + for (; height > 0; height--) { + d1 = d; + for (w = width; w > 0; w--) { + YUV_TO_RGB1 (cb_ptr[0], cr_ptr[0]); + + YUV_TO_RGB2 (r, g, b, y1_ptr[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + + y1_ptr++; + cb_ptr++; + cr_ptr++; + } + d += dst->linesize[0]; + y1_ptr += src->linesize[0] - width; + cb_ptr += src->linesize[1] - width; + cr_ptr += src->linesize[2] - width; + } +} + +static void +rgb24_to_yuv444p (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int src_wrap, x, y; + int r, g, b; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + src_wrap = src->linesize[0] - width * BPP; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y_CCIR (r, g, b); + cb[0] = RGB_TO_U_CCIR (r, g, b, 0); + cr[0] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + cb++; + cr++; + lum++; + } + p += src_wrap; + lum += dst->linesize[0] - width; + cb += dst->linesize[1] - width; + cr += dst->linesize[2] - width; + } +} + +static void +rgb24_to_yuvj420p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int wrap, wrap3, width2; + int r, g, b, r1, g1, b1, w; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + width2 = (width + 1) >> 1; + wrap = dst->linesize[0]; + wrap3 = src->linesize[0]; + p = src->data[0]; + for (; height >= 2; height -= 2) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y (r, g, b); + p += wrap3; + lum += wrap; + + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y (r, g, b); + + cb[0] = RGB_TO_U (r1, g1, b1, 2); + cr[0] = RGB_TO_V (r1, g1, b1, 2); + + cb++; + cr++; + p += -wrap3 + 2 * BPP; + lum += -wrap + 2; + } + if (w) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y (r, g, b); + p += wrap3; + lum += wrap; + RGB_IN (r, g, b, p); + r1 += r; + g1 += g; + b1 += b; + lum[0] = RGB_TO_Y (r, g, b); + cb[0] = RGB_TO_U (r1, g1, b1, 1); + cr[0] = RGB_TO_V (r1, g1, b1, 1); + cb++; + cr++; + p += -wrap3 + BPP; + lum += -wrap + 1; + } + p += wrap3 + (wrap3 - width * BPP); + lum += wrap + (wrap - width); + cb += dst->linesize[1] - width2; + cr += dst->linesize[2] - width2; + } + /* handle odd height */ + if (height) { + for (w = width; w >= 2; w -= 2) { + RGB_IN (r, g, b, p); + r1 = r; + g1 = g; + b1 = b; + lum[0] = RGB_TO_Y (r, g, b); + + RGB_IN (r, g, b, p + BPP); + r1 += r; + g1 += g; + b1 += b; + lum[1] = RGB_TO_Y (r, g, b); + cb[0] = RGB_TO_U (r1, g1, b1, 1); + cr[0] = RGB_TO_V (r1, g1, b1, 1); + cb++; + cr++; + p += 2 * BPP; + lum += 2; + } + if (w) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y (r, g, b); + cb[0] = RGB_TO_U (r, g, b, 0); + cr[0] = RGB_TO_V (r, g, b, 0); + } + } +} + +static void +rgb24_to_yuvj444p (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, x, y; + int r, g, b; + uint8_t *lum, *cb, *cr; + const uint8_t *p; + + lum = dst->data[0]; + cb = dst->data[1]; + cr = dst->data[2]; + + src_wrap = src->linesize[0] - width * BPP; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + lum[0] = RGB_TO_Y (r, g, b); + cb[0] = RGB_TO_U (r, g, b, 0); + cr[0] = RGB_TO_V (r, g, b, 0); + p += BPP; + cb++; + cr++; + lum++; + } + p += src_wrap; + lum += dst->linesize[0] - width; + cb += dst->linesize[1] - width; + cr += dst->linesize[2] - width; + } +} + +static void +ayuv4444_to_rgb24 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + YUV_TO_RGB1_CCIR (s1[2], s1[3]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[1]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + s1 += 4; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void +rgb24_to_ayuv4444 (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 4; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + d[0] = 0xff; + d[1] = RGB_TO_Y_CCIR (r, g, b); + d[2] = RGB_TO_U_CCIR (r, g, b, 0); + d[3] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 4; + } + p += src_wrap; + d += dst_wrap; + } +} + +static void +v308_to_rgb24 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + uint8_t *s, *d, *d1, *s1; + int w, y, cb, cr, r_add, g_add, b_add; + uint8_t *cm = cropTbl + MAX_NEG_CROP; + unsigned int r, g, b; + + d = dst->data[0]; + s = src->data[0]; + for (; height > 0; height--) { + d1 = d; + s1 = s; + for (w = width; w > 0; w--) { + YUV_TO_RGB1_CCIR (s1[1], s1[2]); + + YUV_TO_RGB2_CCIR (r, g, b, s1[0]); + RGB_OUT (d1, r, g, b); + d1 += BPP; + s1 += 3; + } + d += dst->linesize[0]; + s += src->linesize[0]; + } +} + +static void +rgb24_to_v308 (AVPicture * dst, const AVPicture * src, int width, int height) +{ + int src_wrap, dst_wrap, x, y; + int r, g, b; + uint8_t *d; + const uint8_t *p; + + src_wrap = src->linesize[0] - width * BPP; + dst_wrap = dst->linesize[0] - width * 3; + d = dst->data[0]; + p = src->data[0]; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGB_IN (r, g, b, p); + d[0] = RGB_TO_Y_CCIR (r, g, b); + d[1] = RGB_TO_U_CCIR (r, g, b, 0); + d[2] = RGB_TO_V_CCIR (r, g, b, 0); + p += BPP; + d += 3; + } + p += src_wrap; + d += dst_wrap; + } +} +#endif /* FMT_RGB24 */ + +#if defined(FMT_RGB24) || defined(FMT_RGBA32) + +static void glue (RGB_NAME, _to_pal8) (AVPicture * dst, const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + unsigned char *q; + int dst_wrap, src_wrap; + int x, y, has_alpha; + unsigned int r, g, b; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + + q = dst->data[0]; + dst_wrap = dst->linesize[0] - width; + has_alpha = 0; + + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { +#ifdef RGBA_IN + { + unsigned int a; + RGBA_IN (r, g, b, a, p); + /* crude approximation for alpha ! */ + if (a < 0x80) { + has_alpha = 1; + q[0] = TRANSP_INDEX; + } else { + q[0] = gif_clut_index (r, g, b); + } + } +#else + RGB_IN (r, g, b, p); + q[0] = gif_clut_index (r, g, b); +#endif + q++; + p += BPP; + } + p += src_wrap; + q += dst_wrap; + } + + build_rgb_palette (dst->data[1], has_alpha); +} + +#endif /* defined(FMT_RGB24) || defined(FMT_RGBA32) */ + +#ifdef RGBA_IN + +static int glue (get_alpha_info_, RGB_NAME) (const AVPicture * src, + int width, int height) +{ + const unsigned char *p; + int src_wrap, ret, x, y; + unsigned int G_GNUC_UNUSED r, G_GNUC_UNUSED g, G_GNUC_UNUSED b, a; + + p = src->data[0]; + src_wrap = src->linesize[0] - BPP * width; + ret = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + RGBA_IN (r, g, b, a, p); + if (a == 0x00) { + ret |= FF_ALPHA_TRANSP; + } else if (a != 0xff) { + ret |= FF_ALPHA_SEMI_TRANSP; + } + p += BPP; + } + p += src_wrap; + } + return ret; +} + +#endif /* RGBA_IN */ + +#undef RGB_IN +#undef RGBA_IN +#undef RGB_OUT +#undef RGBA_OUT +#undef BPP +#undef RGB_NAME +#undef FMT_RGB24 +#undef FMT_RGBA32 +#undef YUVA_TO_A +#undef RGBA_OUT_ +#undef RGBA_IN_ diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/mem.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/mem.c new file mode 100644 index 0000000..5c3a8a3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/mem.c @@ -0,0 +1,125 @@ +/* + * default memory allocator for libavcodec + * Copyright (c) 2002 Fabrice Bellard. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file mem.c + * default memory allocator for libavcodec. + */ + +#include "avcodec.h" + +/* here we can use OS dependant allocation functions */ +#undef malloc +#undef free +#undef realloc + +#include + +#ifdef HAVE_MALLOC_H +#include +#endif + +/* you can redefine av_malloc and av_free in your project to use your + memory allocator. You do not need to suppress this file because the + linker will do it automatically */ + +/** + * Memory allocation of size byte with alignment suitable for all + * memory accesses (including vectors if available on the + * CPU). av_malloc(0) must return a non NULL pointer. + */ +void * +av_malloc (unsigned int size) +{ + void *ptr; + +#ifdef MEMALIGN_HACK + int diff; + + ptr = malloc (size + 16 + 1); + diff = ((-(int) ptr - 1) & 15) + 1; + ptr += diff; + ((char *) ptr)[-1] = diff; +#elif defined (HAVE_MEMALIGN) + ptr = memalign (16, size); + /* Why 64? + Indeed, we should align it: + on 4 for 386 + on 16 for 486 + on 32 for 586, PPro - k6-III + on 64 for K7 (maybe for P3 too). + Because L1 and L2 caches are aligned on those values. + But I don't want to code such logic here! + */ + /* Why 16? + because some cpus need alignment, for example SSE2 on P4, & most RISC cpus + it will just trigger an exception and the unaligned load will be done in the + exception handler or it will just segfault (SSE2 on P4) + Why not larger? because i didnt see a difference in benchmarks ... + */ + /* benchmarks with p3 + memalign(64)+1 3071,3051,3032 + memalign(64)+2 3051,3032,3041 + memalign(64)+4 2911,2896,2915 + memalign(64)+8 2545,2554,2550 + memalign(64)+16 2543,2572,2563 + memalign(64)+32 2546,2545,2571 + memalign(64)+64 2570,2533,2558 + + btw, malloc seems to do 8 byte alignment by default here + */ +#else + ptr = malloc (size); +#endif + return ptr; +} + +/** + * av_realloc semantics (same as glibc): if ptr is NULL and size > 0, + * identical to malloc(size). If size is zero, it is identical to + * free(ptr) and NULL is returned. + */ +void * +av_realloc (void *ptr, unsigned int size) +{ +#ifdef MEMALIGN_HACK + //FIXME this isnt aligned correctly though it probably isnt needed + int diff; + + if (!ptr) + return av_malloc (size); + diff = ((char *) ptr)[-1]; + return realloc (ptr - diff, size + diff) + diff; +#else + return realloc (ptr, size); +#endif +} + +/* NOTE: ptr = NULL is explicetly allowed */ +void +av_free (void *ptr) +{ + /* XXX: this test should not be needed on most libcs */ + if (ptr) +#ifdef MEMALIGN_HACK + free (ptr - ((char *) ptr)[-1]); +#else + free (ptr); +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/utils.c b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/utils.c new file mode 100644 index 0000000..49d86e7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/ffmpegcolorspace/utils.c @@ -0,0 +1,159 @@ +/* + * utils for libavcodec + * Copyright (c) 2001 Fabrice Bellard. + * Copyright (c) 2003 Michel Bardiaux for the av_log API + * Copyright (c) 2002-2004 Michael Niedermayer + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/** + * @file utils.c + * utils. + */ + +#include "avcodec.h" +#include "dsputil.h" +#include +#include +#include +#include + +void * +av_mallocz (unsigned int size) +{ + void *ptr; + + ptr = av_malloc (size); + if (!ptr) + return NULL; + memset (ptr, 0, size); + return ptr; +} + +char * +av_strdup (const char *s) +{ + char *ptr; + int len; + + len = strlen (s) + 1; + ptr = av_malloc (len); + if (!ptr) + return NULL; + memcpy (ptr, s, len); + return ptr; +} + +/** + * realloc which does nothing if the block is large enough + */ +void * +av_fast_realloc (void *ptr, unsigned int *size, unsigned int min_size) +{ + if (min_size < *size) + return ptr; + + *size = 17 * min_size / 16 + 32; + + return av_realloc (ptr, *size); +} + + +static unsigned int last_static = 0; +static unsigned int allocated_static = 0; +static void **array_static = NULL; + +/** + * allocation of static arrays - do not use for normal allocation. + */ +void * +av_mallocz_static (unsigned int size) +{ + void *ptr = av_mallocz (size); + + if (ptr) { + array_static = + av_fast_realloc (array_static, &allocated_static, + sizeof (void *) * (last_static + 1)); + array_static[last_static++] = ptr; + } + + return ptr; +} + +/** + * free all static arrays and reset pointers to 0. + */ +void +av_free_static (void) +{ + while (last_static) { + av_freep (&array_static[--last_static]); + } + av_freep (&array_static); +} + +/** + * Frees memory and sets the pointer to NULL. + * @param arg pointer to the pointer which should be freed + */ +void +av_freep (void *arg) +{ + void **ptr = (void **) arg; + + av_free (*ptr); + *ptr = NULL; +} + +void +avcodec_get_context_defaults (AVCodecContext * s) +{ + memset (s, 0, sizeof (AVCodecContext)); + + s->frame_rate_base = 1; + s->frame_rate = 25; +} + +/** + * allocates a AVCodecContext and set it to defaults. + * this can be deallocated by simply calling free() + */ +AVCodecContext * +avcodec_alloc_context (void) +{ + AVCodecContext *avctx = av_malloc (sizeof (AVCodecContext)); + + if (avctx == NULL) + return NULL; + + avcodec_get_context_defaults (avctx); + + return avctx; +} + +/* must be called before any other functions */ +void +avcodec_init (void) +{ + static int inited = 0; + + if (inited != 0) + return; + inited = 1; + + dsputil_static_init (); +} diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/Makefile.am b/gst-plugins-base-subtitles0.10/gst/gdp/Makefile.am new file mode 100644 index 0000000..a8aba8b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/Makefile.am @@ -0,0 +1,29 @@ +plugin_LTLIBRARIES = libgstgdp.la + +libgstgdp_la_SOURCES = \ + gstgdp.c \ + gstgdppay.c \ + gstgdpdepay.c + +libgstgdp_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstgdp_la_LIBADD = $(GST_BASE_LIBS) $(GST_GDP_LIBS) +libgstgdp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstgdp_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstgdppay.h \ + gstgdpdepay.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstgdp -:SHARED libgstgdp \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstgdp_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstgdp_la_CFLAGS) \ + -:LDFLAGS $(libgstgdp_la_LDFLAGS) \ + $(libgstgdp_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/README b/gst-plugins-base-subtitles0.10/gst/gdp/README new file mode 100644 index 0000000..6b84afc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/README @@ -0,0 +1,22 @@ +Sample pipelines: +- replacing tcpserversink protocol=gdp with gdppay ! tcpserversink: + - raw audio: + - server: + gst-launch -v audiotestsrc ! gdppay version=0.2 ! tcpserversink + - client: + gst-launch -v tcpclientsrc protocol=gdp ! alsasink sync=FALSE + + - vorbis packets: + - server: + gst-launch -v audiotestsrc ! audioconvert ! vorbisenc ! gdppay version=0.2 ! tcpserversink + - client: + gst-launch -v tcpclientsrc protocol=gdp ! vorbisdec ! audioconvert ! alsasink sync=FALSE + + - ogg packets: + - server: + gst-launch -v audiotestsrc ! audioconvert ! vorbisenc ! oggmux ! gdppay version=0.2 ! tcpserversink + - client: + gst-launch -v tcpclientsrc protocol=gdp ! oggdemux ! vorbisdec ! audioconvert ! alsasink sync=FALSE + + In all the client pipelines, tcpclientsrc protocol=gdp can be replaced with + tcpclientsrc ! gdpdepay diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/gstgdp.c b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdp.c new file mode 100644 index 0000000..31d3259 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdp.c @@ -0,0 +1,46 @@ +/* GStreamer + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include + +#include "gstgdppay.h" +#include "gstgdpdepay.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_dp_init (); + + if (!gst_gdp_depay_plugin_init (plugin)) + return FALSE; + + if (!gst_gdp_pay_plugin_init (plugin)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, + "gdp", + "Payload/depayload GDP packets", plugin_init, + VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.c b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.c new file mode 100644 index 0000000..702e63f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.c @@ -0,0 +1,478 @@ +/* GStreamer + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-gdpdepay + * @see_also: gdppay + * + * This element depayloads GStreamer Data Protocol buffers back to deserialized + * buffers and events. + * + * + * |[ + * gst-launch -v -m filesrc location=test.gdp ! gdpdepay ! xvimagesink + * ]| This pipeline plays back a serialized video stream as created in the + * example for gdppay. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include "gstgdpdepay.h" + +enum +{ + PROP_0, +}; + +static GstStaticPadTemplate gdp_depay_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gdp")); + +static GstStaticPadTemplate gdp_depay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_gdp_depay_debug); +#define GST_CAT_DEFAULT gst_gdp_depay_debug + +#define _do_init(x) \ + GST_DEBUG_CATEGORY_INIT (gst_gdp_depay_debug, "gdpdepay", 0, \ + "GDP depayloader"); + +GST_BOILERPLATE_FULL (GstGDPDepay, gst_gdp_depay, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static gboolean gst_gdp_depay_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_gdp_depay_src_event (GstPad * pad, GstEvent * event); + +static GstFlowReturn gst_gdp_depay_chain (GstPad * pad, GstBuffer * buffer); + +static GstStateChangeReturn gst_gdp_depay_change_state (GstElement * + element, GstStateChange transition); + +static void gst_gdp_depay_finalize (GObject * object); + +static void +gst_gdp_depay_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "GDP Depayloader", "GDP/Depayloader", + "Depayloads GStreamer Data Protocol buffers", + "Thomas Vander Stichele "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gdp_depay_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gdp_depay_src_template)); +} + +static void +gst_gdp_depay_class_init (GstGDPDepayClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_gdp_depay_change_state); + gobject_class->finalize = gst_gdp_depay_finalize; +} + +static void +gst_gdp_depay_init (GstGDPDepay * gdpdepay, GstGDPDepayClass * g_class) +{ + gdpdepay->sinkpad = + gst_pad_new_from_static_template (&gdp_depay_sink_template, "sink"); + gst_pad_set_chain_function (gdpdepay->sinkpad, + GST_DEBUG_FUNCPTR (gst_gdp_depay_chain)); + gst_pad_set_event_function (gdpdepay->sinkpad, + GST_DEBUG_FUNCPTR (gst_gdp_depay_sink_event)); + gst_element_add_pad (GST_ELEMENT (gdpdepay), gdpdepay->sinkpad); + + gdpdepay->srcpad = + gst_pad_new_from_static_template (&gdp_depay_src_template, "src"); + gst_pad_set_event_function (gdpdepay->srcpad, + GST_DEBUG_FUNCPTR (gst_gdp_depay_src_event)); + /* our caps will always be decided by the incoming GDP caps buffers */ + gst_pad_use_fixed_caps (gdpdepay->srcpad); + gst_element_add_pad (GST_ELEMENT (gdpdepay), gdpdepay->srcpad); + + gdpdepay->adapter = gst_adapter_new (); +} + +static void +gst_gdp_depay_finalize (GObject * gobject) +{ + GstGDPDepay *this; + + this = GST_GDP_DEPAY (gobject); + if (this->caps) + gst_caps_unref (this->caps); + g_free (this->header); + gst_adapter_clear (this->adapter); + g_object_unref (this->adapter); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (gobject)); +} + +static gboolean +gst_gdp_depay_sink_event (GstPad * pad, GstEvent * event) +{ + GstGDPDepay *this; + gboolean res = TRUE; + + this = GST_GDP_DEPAY (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + /* forward flush start */ + res = gst_pad_push_event (this->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + /* clear adapter on flush */ + gst_adapter_clear (this->adapter); + /* forward flush stop */ + res = gst_pad_push_event (this->srcpad, event); + break; + case GST_EVENT_EOS: + /* after EOS, we don't expect to output anything anymore */ + res = gst_pad_push_event (this->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_TAG: + case GST_EVENT_BUFFERSIZE: + default: + /* we unref most events as we take them from the datastream */ + gst_event_unref (event); + break; + } + gst_object_unref (this); + + return res; +} + +static gboolean +gst_gdp_depay_src_event (GstPad * pad, GstEvent * event) +{ + GstGDPDepay *this; + gboolean res = TRUE; + + this = GST_GDP_DEPAY (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* we refuse seek for now. */ + gst_event_unref (event); + res = FALSE; + break; + case GST_EVENT_QOS: + case GST_EVENT_NAVIGATION: + default: + /* everything else is passed */ + res = gst_pad_push_event (this->sinkpad, event); + break; + } + gst_object_unref (this); + + return res; +} + +static GstFlowReturn +gst_gdp_depay_chain (GstPad * pad, GstBuffer * buffer) +{ + GstGDPDepay *this; + GstFlowReturn ret = GST_FLOW_OK; + GstCaps *caps; + GstBuffer *buf; + GstEvent *event; + guint available; + + this = GST_GDP_DEPAY (gst_pad_get_parent (pad)); + + /* On DISCONT, get rid of accumulated data. We assume a buffer after the + * DISCONT contains (part of) a new valid header, if not we error because we + * lost sync */ + if (GST_BUFFER_IS_DISCONT (buffer)) { + gst_adapter_clear (this->adapter); + this->state = GST_GDP_DEPAY_STATE_HEADER; + } + gst_adapter_push (this->adapter, buffer); + + while (TRUE) { + switch (this->state) { + case GST_GDP_DEPAY_STATE_HEADER: + { + guint8 *header; + + /* collect a complete header, validate and store the header. Figure out + * the payload length and switch to the PAYLOAD state */ + available = gst_adapter_available (this->adapter); + if (available < GST_DP_HEADER_LENGTH) + goto done; + + GST_LOG_OBJECT (this, "reading GDP header from adapter"); + header = gst_adapter_take (this->adapter, GST_DP_HEADER_LENGTH); + if (!gst_dp_validate_header (GST_DP_HEADER_LENGTH, header)) { + g_free (header); + goto header_validate_error; + } + + /* store types and payload length. Also store the header, which we need + * to make the payload. */ + this->payload_length = gst_dp_header_payload_length (header); + this->payload_type = gst_dp_header_payload_type (header); + /* free previous header and store new one. */ + g_free (this->header); + this->header = header; + + GST_LOG_OBJECT (this, + "read GDP header, payload size %d, payload type %d, switching to state PAYLOAD", + this->payload_length, this->payload_type); + this->state = GST_GDP_DEPAY_STATE_PAYLOAD; + break; + } + case GST_GDP_DEPAY_STATE_PAYLOAD: + { + /* in this state we wait for all the payload data to be available in the + * adapter. Then we switch to the state where we actually process the + * payload. */ + available = gst_adapter_available (this->adapter); + if (available < this->payload_length) + goto done; + + /* change state based on type */ + if (this->payload_type == GST_DP_PAYLOAD_BUFFER) { + GST_LOG_OBJECT (this, "switching to state BUFFER"); + this->state = GST_GDP_DEPAY_STATE_BUFFER; + } else if (this->payload_type == GST_DP_PAYLOAD_CAPS) { + GST_LOG_OBJECT (this, "switching to state CAPS"); + this->state = GST_GDP_DEPAY_STATE_CAPS; + } else if (this->payload_type >= GST_DP_PAYLOAD_EVENT_NONE) { + GST_LOG_OBJECT (this, "switching to state EVENT"); + this->state = GST_GDP_DEPAY_STATE_EVENT; + } else { + goto wrong_type; + } + + if (this->payload_length + && (!gst_dp_validate_payload (GST_DP_HEADER_LENGTH, this->header, + gst_adapter_peek (this->adapter, this->payload_length)))) { + goto payload_validate_error; + } + + break; + } + case GST_GDP_DEPAY_STATE_BUFFER: + { + + /* if we receive a buffer without caps first, we error out */ + if (!this->caps) + goto no_caps; + + GST_LOG_OBJECT (this, "reading GDP buffer from adapter"); + buf = gst_dp_buffer_from_header (GST_DP_HEADER_LENGTH, this->header); + if (!buf) + goto buffer_failed; + + /* now take the payload if there is any */ + if (this->payload_length > 0) { + guint8 *payload; + + payload = gst_adapter_take (this->adapter, this->payload_length); + memcpy (GST_BUFFER_DATA (buf), payload, this->payload_length); + g_free (payload); + } + + /* set caps and push */ + gst_buffer_set_caps (buf, this->caps); + GST_LOG_OBJECT (this, "deserialized buffer %p, pushing, timestamp %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT + ", size %d, flags 0x%x", + buf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf), + GST_BUFFER_SIZE (buf), GST_BUFFER_FLAGS (buf)); + ret = gst_pad_push (this->srcpad, buf); + if (ret != GST_FLOW_OK) + goto push_error; + + GST_LOG_OBJECT (this, "switching to state HEADER"); + this->state = GST_GDP_DEPAY_STATE_HEADER; + break; + } + case GST_GDP_DEPAY_STATE_CAPS: + { + guint8 *payload; + + /* take the payload of the caps */ + GST_LOG_OBJECT (this, "reading GDP caps from adapter"); + payload = gst_adapter_take (this->adapter, this->payload_length); + caps = gst_dp_caps_from_packet (GST_DP_HEADER_LENGTH, this->header, + payload); + g_free (payload); + if (!caps) + goto caps_failed; + + GST_DEBUG_OBJECT (this, "deserialized caps %" GST_PTR_FORMAT, caps); + gst_caps_replace (&(this->caps), caps); + gst_pad_set_caps (this->srcpad, caps); + /* drop the creation ref we still have */ + gst_caps_unref (caps); + + GST_LOG_OBJECT (this, "switching to state HEADER"); + this->state = GST_GDP_DEPAY_STATE_HEADER; + break; + } + case GST_GDP_DEPAY_STATE_EVENT: + { + guint8 *payload; + + GST_LOG_OBJECT (this, "reading GDP event from adapter"); + + /* adapter doesn't like 0 length payload */ + if (this->payload_length > 0) + payload = gst_adapter_take (this->adapter, this->payload_length); + else + payload = NULL; + event = gst_dp_event_from_packet (GST_DP_HEADER_LENGTH, this->header, + payload); + g_free (payload); + if (!event) + goto event_failed; + + GST_DEBUG_OBJECT (this, "deserialized event %p of type %s, pushing", + event, gst_event_type_get_name (event->type)); + gst_pad_push_event (this->srcpad, event); + + GST_LOG_OBJECT (this, "switching to state HEADER"); + this->state = GST_GDP_DEPAY_STATE_HEADER; + break; + } + } + } + +done: + gst_object_unref (this); + return ret; + + /* ERRORS */ +header_validate_error: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("GDP packet header does not validate")); + ret = GST_FLOW_ERROR; + goto done; + } +payload_validate_error: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("GDP packet payload does not validate")); + ret = GST_FLOW_ERROR; + goto done; + } +wrong_type: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("GDP packet header is of wrong type")); + ret = GST_FLOW_ERROR; + goto done; + } +no_caps: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("Received a buffer without first receiving caps")); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } +buffer_failed: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("could not create buffer from GDP packet")); + ret = GST_FLOW_ERROR; + goto done; + } +push_error: + { + GST_WARNING_OBJECT (this, "pushing depayloaded buffer returned %d", ret); + goto done; + } +caps_failed: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("could not create caps from GDP packet")); + ret = GST_FLOW_ERROR; + goto done; + } +event_failed: + { + GST_ELEMENT_ERROR (this, STREAM, DECODE, (NULL), + ("could not create event from GDP packet")); + ret = GST_FLOW_ERROR; + goto done; + } +} + +static GstStateChangeReturn +gst_gdp_depay_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstGDPDepay *this = GST_GDP_DEPAY (element); + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (this->caps) { + gst_caps_unref (this->caps); + this->caps = NULL; + } + gst_adapter_clear (this->adapter); + break; + default: + break; + } + return ret; +} + +gboolean +gst_gdp_depay_plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "gdpdepay", GST_RANK_NONE, + GST_TYPE_GDP_DEPAY)) + return FALSE; + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.h b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.h new file mode 100644 index 0000000..64b7db2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdpdepay.h @@ -0,0 +1,82 @@ +/* GStreamer + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_GDP_DEPAY_H__ +#define __GST_GDP_DEPAY_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GDP_DEPAY \ + (gst_gdp_depay_get_type()) +#define GST_GDP_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GDP_DEPAY,GstGDPDepay)) +#define GST_GDP_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GDP_DEPAY,GstGDPDepayClass)) +#define GST_IS_GDP_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GDP_DEPAY)) +#define GST_IS_GDP_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GDP_DEPAY)) + +typedef enum { + GST_GDP_DEPAY_STATE_HEADER = 0, + GST_GDP_DEPAY_STATE_PAYLOAD, + GST_GDP_DEPAY_STATE_BUFFER, + GST_GDP_DEPAY_STATE_CAPS, + GST_GDP_DEPAY_STATE_EVENT, +} GstGDPDepayState; + + +typedef struct _GstGDPDepay GstGDPDepay; +typedef struct _GstGDPDepayClass GstGDPDepayClass; + +/** + * GstGDPDepay: + * + * Private gdpdepay element structure. + */ +struct _GstGDPDepay +{ + GstElement element; + GstPad *sinkpad; + GstPad *srcpad; + + GstAdapter *adapter; + GstGDPDepayState state; + GstCaps *caps; + + guint8 *header; + guint32 payload_length; + GstDPPayloadType payload_type; +}; + +struct _GstGDPDepayClass +{ + GstElementClass parent_class; +}; + +gboolean gst_gdp_depay_plugin_init (GstPlugin * plugin); + +GType gst_gdp_depay_get_type (void); + +G_END_DECLS + +#endif /* __GST_GDP_DEPAY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.c b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.c new file mode 100644 index 0000000..6da4967 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.c @@ -0,0 +1,898 @@ +/* GStreamer + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-gdppay + * @see_also: gdpdepay + * + * This element payloads GStreamer buffers and events using the + * GStreamer Data Protocol. + * + * + * |[ + * gst-launch -v -m videotestsrc num-buffers=50 ! gdppay ! filesink location=test.gdp + * ]| This pipeline creates a serialized video stream that can be played back + * with the example shown in gdpdepay. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstgdppay.h" + +static GstStaticPadTemplate gdp_pay_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gdp_pay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gdp")); + +GST_DEBUG_CATEGORY_STATIC (gst_gdp_pay_debug); +#define GST_CAT_DEFAULT gst_gdp_pay_debug + +#define DEFAULT_CRC_HEADER TRUE +#define DEFAULT_CRC_PAYLOAD FALSE +#define DEFAULT_VERSION GST_DP_VERSION_1_0 + +enum +{ + PROP_0, + PROP_CRC_HEADER, + PROP_CRC_PAYLOAD, + PROP_VERSION, +}; + +#define _do_init(x) \ + GST_DEBUG_CATEGORY_INIT (gst_gdp_pay_debug, "gdppay", 0, \ + "GDP payloader"); + +GST_BOILERPLATE_FULL (GstGDPPay, gst_gdp_pay, GstElement, + GST_TYPE_ELEMENT, _do_init); + +static void gst_gdp_pay_reset (GstGDPPay * this); + +static GstFlowReturn gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer); + +static gboolean gst_gdp_pay_src_event (GstPad * pad, GstEvent * event); + +static gboolean gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event); + +static GstStateChangeReturn gst_gdp_pay_change_state (GstElement * + element, GstStateChange transition); + +static void gst_gdp_pay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_gdp_pay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_gdp_pay_finalize (GObject * gobject); + +static void +gst_gdp_pay_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "GDP Payloader", "GDP/Payloader", + "Payloads GStreamer Data Protocol buffers", + "Thomas Vander Stichele "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gdp_pay_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gdp_pay_src_template)); +} + +static void +gst_gdp_pay_class_init (GstGDPPayClass * klass) +{ + GObjectClass *gobject_class; + + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_gdp_pay_set_property; + gobject_class->get_property = gst_gdp_pay_get_property; + gobject_class->finalize = gst_gdp_pay_finalize; + + g_object_class_install_property (gobject_class, PROP_CRC_HEADER, + g_param_spec_boolean ("crc-header", "CRC Header", + "Calculate and store a CRC checksum on the header", + DEFAULT_CRC_HEADER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CRC_PAYLOAD, + g_param_spec_boolean ("crc-payload", "CRC Payload", + "Calculate and store a CRC checksum on the payload", + DEFAULT_CRC_PAYLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_VERSION, + g_param_spec_enum ("version", "Version", + "Version of the GStreamer Data Protocol", + GST_TYPE_DP_VERSION, DEFAULT_VERSION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_gdp_pay_change_state); +} + +static void +gst_gdp_pay_init (GstGDPPay * gdppay, GstGDPPayClass * g_class) +{ + gdppay->sinkpad = + gst_pad_new_from_static_template (&gdp_pay_sink_template, "sink"); + gst_pad_set_chain_function (gdppay->sinkpad, + GST_DEBUG_FUNCPTR (gst_gdp_pay_chain)); + gst_pad_set_event_function (gdppay->sinkpad, + GST_DEBUG_FUNCPTR (gst_gdp_pay_sink_event)); + gst_element_add_pad (GST_ELEMENT (gdppay), gdppay->sinkpad); + + gdppay->srcpad = + gst_pad_new_from_static_template (&gdp_pay_src_template, "src"); + gst_pad_set_event_function (gdppay->srcpad, + GST_DEBUG_FUNCPTR (gst_gdp_pay_src_event)); + gst_element_add_pad (GST_ELEMENT (gdppay), gdppay->srcpad); + + gdppay->crc_header = DEFAULT_CRC_HEADER; + gdppay->crc_payload = DEFAULT_CRC_PAYLOAD; + gdppay->header_flag = gdppay->crc_header | gdppay->crc_payload; + gdppay->version = DEFAULT_VERSION; + gdppay->offset = 0; + + gdppay->packetizer = gst_dp_packetizer_new (gdppay->version); +} + +static void +gst_gdp_pay_finalize (GObject * gobject) +{ + GstGDPPay *this = GST_GDP_PAY (gobject); + + gst_gdp_pay_reset (this); + gst_dp_packetizer_free (this->packetizer); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (gobject)); +} + +static void +gst_gdp_pay_reset (GstGDPPay * this) +{ + GST_DEBUG_OBJECT (this, "Resetting GDP object"); + /* clear the queued buffers */ + while (this->queue) { + GstBuffer *buffer; + + buffer = GST_BUFFER_CAST (this->queue->data); + + /* delete buffer from queue now */ + this->queue = g_list_delete_link (this->queue, this->queue); + + gst_buffer_unref (buffer); + } + if (this->caps) { + gst_caps_unref (this->caps); + this->caps = NULL; + } + if (this->caps_buf) { + gst_buffer_unref (this->caps_buf); + this->caps_buf = NULL; + } + if (this->tag_buf) { + gst_buffer_unref (this->tag_buf); + this->tag_buf = NULL; + } + if (this->new_segment_buf) { + gst_buffer_unref (this->new_segment_buf); + this->new_segment_buf = NULL; + } + this->sent_streamheader = FALSE; + this->offset = 0; +} + +/* set OFFSET and OFFSET_END with running count */ +static void +gst_gdp_stamp_buffer (GstGDPPay * this, GstBuffer * buffer) +{ + GST_BUFFER_OFFSET (buffer) = this->offset; + GST_BUFFER_OFFSET_END (buffer) = this->offset + GST_BUFFER_SIZE (buffer); + this->offset = GST_BUFFER_OFFSET_END (buffer); +} + +static GstBuffer * +gst_gdp_buffer_from_caps (GstGDPPay * this, GstCaps * caps) +{ + GstBuffer *headerbuf; + + GstBuffer *payloadbuf; + + guint8 *header, *payload; + + guint len; + + if (!this->packetizer->packet_from_caps (caps, this->header_flag, &len, + &header, &payload)) + goto packet_failed; + + GST_LOG_OBJECT (this, "creating GDP header and payload buffer from caps"); + headerbuf = gst_buffer_new (); + gst_buffer_set_data (headerbuf, header, len); + GST_BUFFER_MALLOCDATA (headerbuf) = header; + + payloadbuf = gst_buffer_new (); + gst_buffer_set_data (payloadbuf, payload, + gst_dp_header_payload_length (header)); + GST_BUFFER_MALLOCDATA (payloadbuf) = payload; + + return gst_buffer_join (headerbuf, payloadbuf); + + /* ERRORS */ +packet_failed: + { + GST_WARNING_OBJECT (this, "could not create GDP header from caps"); + return NULL; + } +} + +static GstBuffer * +gst_gdp_pay_buffer_from_buffer (GstGDPPay * this, GstBuffer * buffer) +{ + GstBuffer *headerbuf; + + guint8 *header; + + guint len; + + if (!this->packetizer->header_from_buffer (buffer, this->header_flag, &len, + &header)) + goto no_buffer; + + GST_LOG_OBJECT (this, "creating GDP header and payload buffer from buffer"); + headerbuf = gst_buffer_new (); + gst_buffer_set_data (headerbuf, header, len); + GST_BUFFER_MALLOCDATA (headerbuf) = header; + + /* we do not want to lose the ref on the incoming buffer */ + gst_buffer_ref (buffer); + + return gst_buffer_join (headerbuf, buffer); + + /* ERRORS */ +no_buffer: + { + GST_WARNING_OBJECT (this, "could not create GDP header from buffer"); + return NULL; + } +} + +static GstBuffer * +gst_gdp_buffer_from_event (GstGDPPay * this, GstEvent * event) +{ + GstBuffer *headerbuf; + + GstBuffer *payloadbuf; + + guint8 *header, *payload; + + guint len; + + gboolean ret; + + ret = + this->packetizer->packet_from_event (event, this->header_flag, &len, + &header, &payload); + if (!ret) + goto no_event; + + GST_LOG_OBJECT (this, "creating GDP header and payload buffer from event"); + headerbuf = gst_buffer_new (); + gst_buffer_set_data (headerbuf, header, len); + GST_BUFFER_MALLOCDATA (headerbuf) = header; + + payloadbuf = gst_buffer_new (); + gst_buffer_set_data (payloadbuf, payload, + gst_dp_header_payload_length (header)); + GST_BUFFER_MALLOCDATA (payloadbuf) = payload; + + return gst_buffer_join (headerbuf, payloadbuf); + + /* ERRORS */ +no_event: + { + GST_WARNING_OBJECT (this, "could not create GDP header from event %s (%d)", + gst_event_type_get_name (event->type), event->type); + return NULL; + } +} + + +/* set our caps with streamheader, based on the latest newsegment and caps, + * and (possibly) GDP-serialized buffers of the streamheaders on the src pad */ +static GstFlowReturn +gst_gdp_pay_reset_streamheader (GstGDPPay * this) +{ + GstCaps *caps; + + /* We use copies of these to avoid circular refcounts */ + GstBuffer *new_segment_buf, *caps_buf, *tag_buf; + + GstStructure *structure; + + GstFlowReturn r = GST_FLOW_OK; + + gboolean version_one_zero = TRUE; + + GValue array = { 0 }; + GValue value = { 0 }; + + GST_DEBUG_OBJECT (this, "start"); + /* In version 0.2, we didn't need or send new segment or tags */ + if (this->version == GST_DP_VERSION_0_2) + version_one_zero = FALSE; + + if (version_one_zero) { + if (!this->new_segment_buf || !this->caps_buf) { + GST_DEBUG_OBJECT (this, "1.0, missing new_segment or caps, returning"); + return GST_FLOW_OK; + } + } else { + if (!this->caps_buf) { + GST_DEBUG_OBJECT (this, "0.2, missing caps, returning"); + return GST_FLOW_OK; + } + } + + /* put copies of the buffers in a fixed list + * Stamp the buffers with offset and offset_end as well. + * We do this here so the offsets match the order the buffers go out in */ + g_value_init (&array, GST_TYPE_ARRAY); + + if (version_one_zero) { + gst_gdp_stamp_buffer (this, this->new_segment_buf); + GST_DEBUG_OBJECT (this, "1.0, appending copy of new segment buffer %p", + this->new_segment_buf); + new_segment_buf = gst_buffer_copy (this->new_segment_buf); + gst_buffer_set_caps (new_segment_buf, NULL); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, new_segment_buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + gst_buffer_unref (new_segment_buf); + + if (this->tag_buf) { + gst_gdp_stamp_buffer (this, this->tag_buf); + GST_DEBUG_OBJECT (this, "1.0, appending current tags buffer %p", + this->tag_buf); + tag_buf = this->tag_buf; + this->tag_buf = NULL; + + gst_buffer_set_caps (tag_buf, NULL); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, tag_buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + gst_buffer_unref (tag_buf); + } + } + + gst_gdp_stamp_buffer (this, this->caps_buf); + GST_DEBUG_OBJECT (this, "appending copy of caps buffer %p", this->caps_buf); + caps_buf = gst_buffer_copy (this->caps_buf); + gst_buffer_set_caps (caps_buf, NULL); + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, caps_buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + gst_buffer_unref (caps_buf); + + /* we also need to add GDP serializations of the streamheaders of the + * incoming caps */ + structure = gst_caps_get_structure (this->caps, 0); + if (gst_structure_has_field (structure, "streamheader")) { + const GValue *sh; + + GArray *buffers; + + GstBuffer *buffer; + + int i; + + sh = gst_structure_get_value (structure, "streamheader"); + buffers = g_value_peek_pointer (sh); + GST_DEBUG_OBJECT (this, + "Need to serialize %d incoming streamheader buffers on ours", + buffers->len); + for (i = 0; i < buffers->len; ++i) { + GValue *bufval; + + GstBuffer *outbuffer; + + bufval = &g_array_index (buffers, GValue, i); + buffer = g_value_peek_pointer (bufval); + /* this buffer is deserialized by gdpdepay as a regular buffer, + it needs IN_CAPS, because it's a streamheader - otherwise it + is mixed with regular data buffers */ + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_OFFSET (buffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE; + + outbuffer = gst_gdp_pay_buffer_from_buffer (this, buffer); + if (!outbuffer) { + g_value_unset (&array); + goto no_buffer; + } + + /* Setting IN_CAPS as other GDP event buffers */ + GST_DEBUG_OBJECT (this, + "Setting IN_CAPS flag on outgoing buffer %" GST_PTR_FORMAT, + outbuffer); + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + GST_BUFFER_OFFSET (outbuffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (outbuffer) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_TIMESTAMP (outbuffer) = GST_CLOCK_TIME_NONE; + + g_value_init (&value, GST_TYPE_BUFFER); + gst_value_set_buffer (&value, outbuffer); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + + gst_buffer_unref (outbuffer); + } + } else { + GST_DEBUG_OBJECT (this, "no streamheader to serialize"); + } + + GST_DEBUG_OBJECT (this, "%d serialized buffers on streamheaders", + gst_value_array_get_size (&array)); + caps = gst_caps_from_string ("application/x-gdp"); + structure = gst_caps_get_structure (caps, 0); + + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + + GST_DEBUG_OBJECT (this, "Setting caps on src pad %" GST_PTR_FORMAT, caps); + gst_pad_set_caps (this->srcpad, caps); + this->caps_buf = gst_buffer_make_metadata_writable (this->caps_buf); + gst_buffer_set_caps (this->caps_buf, caps); + this->new_segment_buf = + gst_buffer_make_metadata_writable (this->new_segment_buf); + gst_buffer_set_caps (this->new_segment_buf, caps); + + /* if these are our first ever buffers, send out new_segment first */ + if (!this->sent_streamheader) { + GstEvent *event = + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, -1, 0); + GST_DEBUG_OBJECT (this, "Sending out new_segment event %p", event); + if (!gst_pad_push_event (this->srcpad, event)) { + GST_WARNING_OBJECT (this, "pushing new segment failed"); + r = GST_FLOW_ERROR; + goto done; + } + } + + /* push out these streamheader buffers, then flush our internal queue */ + GST_DEBUG_OBJECT (this, "Pushing GDP new_segment buffer %p with offset %" + G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, this->new_segment_buf, + GST_BUFFER_OFFSET (this->new_segment_buf), + GST_BUFFER_OFFSET_END (this->new_segment_buf)); + /* we stored these bufs with refcount 1, so make sure we keep a ref */ + r = gst_pad_push (this->srcpad, gst_buffer_ref (this->new_segment_buf)); + if (r != GST_FLOW_OK) { + GST_WARNING_OBJECT (this, "pushing GDP newsegment buffer returned %d", r); + goto done; + } + if (this->tag_buf) { + gst_buffer_set_caps (this->tag_buf, caps); + GST_DEBUG_OBJECT (this, "Pushing GDP tag buffer %p", this->tag_buf); + /* we stored these bufs with refcount 1, so make sure we keep a ref */ + r = gst_pad_push (this->srcpad, gst_buffer_ref (this->tag_buf)); + if (r != GST_FLOW_OK) { + GST_WARNING_OBJECT (this, "pushing GDP tag buffer returned %d", r); + goto done; + } + } + GST_DEBUG_OBJECT (this, "Pushing GDP caps buffer %p", this->caps_buf); + r = gst_pad_push (this->srcpad, gst_buffer_ref (this->caps_buf)); + if (r != GST_FLOW_OK) { + GST_WARNING_OBJECT (this, "pushing GDP caps buffer returned %d", r); + goto done; + } + this->sent_streamheader = TRUE; + GST_DEBUG_OBJECT (this, "need to push %d queued buffers", + g_list_length (this->queue)); + while (this->queue) { + GstBuffer *buffer; + + buffer = GST_BUFFER_CAST (this->queue->data); + GST_DEBUG_OBJECT (this, "Pushing queued GDP buffer %p", buffer); + + /* delete buffer from queue now */ + this->queue = g_list_delete_link (this->queue, this->queue); + + /* set caps and push */ + gst_buffer_set_caps (buffer, caps); + r = gst_pad_push (this->srcpad, buffer); + if (r != GST_FLOW_OK) { + GST_WARNING_OBJECT (this, "pushing queued GDP buffer returned %d", r); + goto done; + } + } + +done: + gst_caps_unref (caps); + GST_DEBUG_OBJECT (this, "stop"); + return r; + + /* ERRORS */ +no_buffer: + { + GST_ELEMENT_ERROR (this, STREAM, FORMAT, (NULL), + ("failed to create GDP buffer from streamheader")); + return GST_FLOW_ERROR; + } +} + +/* queue a buffer internally if we haven't sent streamheader buffers yet; + * otherwise, just push on, this takes ownership of the buffer. */ +static GstFlowReturn +gst_gdp_queue_buffer (GstGDPPay * this, GstBuffer * buffer) +{ + if (this->sent_streamheader) { + GST_LOG_OBJECT (this, "Pushing GDP buffer %p, caps %" GST_PTR_FORMAT, + buffer, this->caps); + gst_buffer_set_caps (buffer, GST_PAD_CAPS (this->srcpad)); + return gst_pad_push (this->srcpad, buffer); + } + + /* store it on an internal queue. buffer remains reffed. */ + this->queue = g_list_append (this->queue, buffer); + GST_DEBUG_OBJECT (this, "streamheader not sent yet, " + "queued buffer %p, now %d buffers queued", + buffer, g_list_length (this->queue)); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_gdp_pay_chain (GstPad * pad, GstBuffer * buffer) +{ + GstGDPPay *this; + + GstCaps *caps; + + GstBuffer *outbuffer; + + GstFlowReturn ret; + + this = GST_GDP_PAY (gst_pad_get_parent (pad)); + + /* we should have received a new_segment before, otherwise it's a bug. + * fake one in that case */ + if (!this->new_segment_buf) { + GstEvent *event; + + GST_WARNING_OBJECT (this, + "did not receive new-segment before first buffer"); + event = gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 0, -1, 0); + outbuffer = gst_gdp_buffer_from_event (this, event); + gst_event_unref (event); + + /* GDP 0.2 doesn't know about new-segment, so this is not fatal */ + if (!outbuffer) { + GST_ELEMENT_WARNING (this, STREAM, ENCODE, (NULL), + ("Could not create GDP buffer from new segment event")); + } else { + GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_DURATION (outbuffer) = 0; + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + GST_DEBUG_OBJECT (this, "Storing buffer %p as new_segment_buf", + outbuffer); + this->new_segment_buf = outbuffer; + } + } + + /* make sure we've received caps before */ + caps = gst_buffer_get_caps (buffer); + if (!this->caps && !caps) + goto no_caps; + + /* if the caps have changed, process caps first */ + if (caps && !gst_caps_is_equal (this->caps, caps)) { + GST_LOG_OBJECT (this, "caps changed to %p, %" GST_PTR_FORMAT, caps, caps); + gst_caps_replace (&(this->caps), caps); + outbuffer = gst_gdp_buffer_from_caps (this, caps); + if (!outbuffer) + goto no_caps_buffer; + + GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_DURATION (outbuffer) = 0; + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + + if (this->caps_buf) + gst_buffer_unref (this->caps_buf); + this->caps_buf = outbuffer; + gst_gdp_pay_reset_streamheader (this); + } + + if (caps) + gst_caps_unref (caps); + + /* create a GDP header packet, + * then create a GST buffer of the header packet and the buffer contents */ + outbuffer = gst_gdp_pay_buffer_from_buffer (this, buffer); + if (!outbuffer) + goto no_buffer; + + /* If the incoming buffer is IN_CAPS, that means we have it on the caps + * as streamheader, and we have serialized a GDP version of it and put it + * on our caps */ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) { + GST_DEBUG_OBJECT (this, "Setting IN_CAPS flag on outgoing buffer %p", + outbuffer); + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + } + + gst_gdp_stamp_buffer (this, outbuffer); + GST_BUFFER_TIMESTAMP (outbuffer) = GST_BUFFER_TIMESTAMP (buffer); + GST_BUFFER_DURATION (outbuffer) = GST_BUFFER_DURATION (buffer); + + ret = gst_gdp_queue_buffer (this, outbuffer); + +done: + gst_buffer_unref (buffer); + gst_object_unref (this); + return ret; + + /* ERRORS */ +no_caps: + { + /* when returning a fatal error as a GstFlowReturn we must post an error + * message */ + GST_ELEMENT_ERROR (this, STREAM, FORMAT, (NULL), + ("first received buffer does not have caps set")); + if (caps) + gst_caps_unref (caps); + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; + } +no_caps_buffer: + { + GST_ELEMENT_ERROR (this, STREAM, ENCODE, (NULL), + ("Could not create GDP buffer from caps %" GST_PTR_FORMAT, caps)); + gst_caps_unref (caps); + ret = GST_FLOW_ERROR; + goto done; + } +no_buffer: + { + GST_ELEMENT_ERROR (this, STREAM, ENCODE, (NULL), + ("Could not create GDP buffer from buffer")); + ret = GST_FLOW_ERROR; + goto done; + } +} + +static gboolean +gst_gdp_pay_sink_event (GstPad * pad, GstEvent * event) +{ + GstBuffer *outbuffer; + + GstGDPPay *this = GST_GDP_PAY (gst_pad_get_parent (pad)); + + GstFlowReturn flowret; + + gboolean ret = TRUE; + + GST_DEBUG_OBJECT (this, "received event %p of type %s (%d)", + event, gst_event_type_get_name (event->type), event->type); + + /* now turn the event into a buffer */ + outbuffer = gst_gdp_buffer_from_event (this, event); + if (!outbuffer) + goto no_outbuffer; + + GST_BUFFER_TIMESTAMP (outbuffer) = GST_EVENT_TIMESTAMP (event); + GST_BUFFER_DURATION (outbuffer) = 0; + + /* if we got a new segment or tag event, we should put it on our streamheader, + * and not send it on */ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + GST_DEBUG_OBJECT (this, "Storing in caps buffer %p as new_segment_buf", + outbuffer); + + if (this->new_segment_buf) + gst_buffer_unref (this->new_segment_buf); + this->new_segment_buf = outbuffer; + + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + gst_gdp_pay_reset_streamheader (this); + break; + case GST_EVENT_TAG: + GST_DEBUG_OBJECT (this, "Storing in caps buffer %p as tag_buf", + outbuffer); + + if (this->tag_buf) + gst_buffer_unref (this->tag_buf); + this->tag_buf = outbuffer; + + GST_BUFFER_FLAG_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS); + gst_gdp_pay_reset_streamheader (this); + break; + default: + GST_DEBUG_OBJECT (this, "queuing GDP buffer %p of event %p", outbuffer, + event); + flowret = gst_gdp_queue_buffer (this, outbuffer); + if (flowret != GST_FLOW_OK) + goto push_error; + break; + } + + /* if we have EOS, we should send on EOS ourselves */ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GST_DEBUG_OBJECT (this, "Sending on EOS event %p", event); + /* ref, we unref later again */ + ret = gst_pad_push_event (this->srcpad, gst_event_ref (event)); + } + +done: + gst_event_unref (event); + gst_object_unref (this); + + return ret; + + /* ERRORS */ +no_outbuffer: + { + GST_ELEMENT_WARNING (this, STREAM, ENCODE, (NULL), + ("Could not create GDP buffer from received event (type %s)", + gst_event_type_get_name (event->type))); + ret = FALSE; + goto done; + } +push_error: + { + GST_WARNING_OBJECT (this, "queueing GDP event buffer returned %d", flowret); + ret = FALSE; + goto done; + } +} + +static gboolean +gst_gdp_pay_src_event (GstPad * pad, GstEvent * event) +{ + GstGDPPay *this; + + gboolean res = TRUE; + + this = GST_GDP_PAY (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + /* we refuse seek for now. */ + gst_event_unref (event); + res = FALSE; + break; + case GST_EVENT_QOS: + case GST_EVENT_NAVIGATION: + default: + /* everything else is passed */ + res = gst_pad_push_event (this->sinkpad, event); + break; + } + gst_object_unref (this); + + return res; +} + +static void +gst_gdp_pay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstGDPPay *this; + + g_return_if_fail (GST_IS_GDP_PAY (object)); + this = GST_GDP_PAY (object); + + switch (prop_id) { + case PROP_CRC_HEADER: + this->crc_header = + g_value_get_boolean (value) ? GST_DP_HEADER_FLAG_CRC_HEADER : 0; + this->header_flag = this->crc_header | this->crc_payload; + break; + case PROP_CRC_PAYLOAD: + this->crc_payload = + g_value_get_boolean (value) ? GST_DP_HEADER_FLAG_CRC_PAYLOAD : 0; + this->header_flag = this->crc_header | this->crc_payload; + break; + case PROP_VERSION: + this->version = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_gdp_pay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstGDPPay *this; + + g_return_if_fail (GST_IS_GDP_PAY (object)); + this = GST_GDP_PAY (object); + + switch (prop_id) { + case PROP_CRC_HEADER: + g_value_set_boolean (value, this->crc_header); + break; + case PROP_CRC_PAYLOAD: + g_value_set_boolean (value, this->crc_payload); + break; + case PROP_VERSION: + g_value_set_enum (value, this->version); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_gdp_pay_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + + GstGDPPay *this = GST_GDP_PAY (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_gdp_pay_reset (this); + break; + default: + break; + } + + return ret; +} + +gboolean +gst_gdp_pay_plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "gdppay", GST_RANK_NONE, GST_TYPE_GDP_PAY)) + return FALSE; + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.h b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.h new file mode 100644 index 0000000..3e280b5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/gdp/gstgdppay.h @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_GDP_PAY_H__ +#define __GST_GDP_PAY_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_GDP_PAY \ + (gst_gdp_pay_get_type()) +#define GST_GDP_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GDP_PAY,GstGDPPay)) +#define GST_GDP_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GDP_PAY,GstGDPPayClass)) +#define GST_IS_GDP_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GDP_PAY)) +#define GST_IS_GDP_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GDP_PAY)) + +typedef struct _GstGDPPay GstGDPPay; +typedef struct _GstGDPPayClass GstGDPPayClass; + +/** + * GstGDPPay: + * + * Private gdppay element structure. + */ +struct _GstGDPPay +{ + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + GstCaps *caps; /* incoming caps */ + + GstBuffer *caps_buf; + GstBuffer *new_segment_buf; + GstBuffer *tag_buf; + + gboolean sent_streamheader; /* TRUE after the first streamheaders are sent */ + GList *queue; /* list of queued buffers before streamheaders are sent */ + guint64 offset; + + gboolean crc_header; + gboolean crc_payload; + GstDPHeaderFlag header_flag; + GstDPVersion version; + GstDPPacketizer *packetizer; +}; + +struct _GstGDPPayClass +{ + GstElementClass parent_class; +}; + +gboolean gst_gdp_pay_plugin_init (GstPlugin * plugin); + +GType gst_gdp_pay_get_type (void); + +G_END_DECLS + +#endif /* __GST_GDP_PAY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/.gitignore b/gst-plugins-base-subtitles0.10/gst/playback/.gitignore new file mode 100644 index 0000000..091c64d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/.gitignore @@ -0,0 +1,3 @@ +gstplay-marshal.c +gstplay-marshal.h + diff --git a/gst-plugins-base-subtitles0.10/gst/playback/Makefile.am b/gst-plugins-base-subtitles0.10/gst/playback/Makefile.am new file mode 100644 index 0000000..3adb56d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/Makefile.am @@ -0,0 +1,107 @@ +# variables used for enum/marshal generation +glib_enum_define = GST_PLAY +glib_gen_prefix = gst_play +glib_gen_basename = gstplay + +built_sources = gstplay-marshal.c +built_headers = gstplay-marshal.h + +plugin_LTLIBRARIES = libgstplaybin.la libgstdecodebin.la libgstdecodebin2.la + +libgstplaybin_la_SOURCES = \ + gstplayback.c \ + gstplaybin.c \ + gstplaybin2.c \ + gstplaysink.c \ + gstplaybasebin.c \ + gstplay-enum.c \ + gststreaminfo.c \ + gststreamselector.c \ + gstsubtitleoverlay.c \ + gststreamsynchronizer.c + +nodist_libgstplaybin_la_SOURCES = $(built_sources) +libgstplaybin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstplaybin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstplaybin_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +libgstplaybin_la_LIBTOOLFLAGS = --tag=disable-static + +libgstdecodebin_la_SOURCES = gstdecodebin.c +nodist_libgstdecodebin_la_SOURCES = $(built_sources) +libgstdecodebin_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstdecodebin_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstdecodebin_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +libgstdecodebin_la_LIBTOOLFLAGS = --tag=disable-static + +libgstdecodebin2_la_SOURCES = gstdecodebin2.c gsturidecodebin.c gstplay-enum.c +nodist_libgstdecodebin2_la_SOURCES = $(built_sources) +libgstdecodebin2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstdecodebin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstdecodebin2_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +libgstdecodebin2_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstplayback.h \ + gstplaybasebin.h \ + gstplaysink.h \ + gststreaminfo.h \ + gstplay-enum.h \ + gststreamselector.h \ + gstrawcaps.h \ + gstsubtitleoverlay.h \ + gststreamsynchronizer.h + +BUILT_SOURCES = $(built_headers) $(built_sources) + +EXTRA_DIST = gstplay-marshal.list + +CLEANFILES = $(BUILT_SOURCES) + +include $(top_srcdir)/common/gst-glib-gen.mak + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstdecodebin -:SHARED libgstdecodebin \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstdecodebin_la_SOURCES) \ + $(nodist_libgstdecodebin_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstdecodebin_la_CFLAGS) \ + -:LDFLAGS $(libgstdecodebin_la_LDFLAGS) \ + $(libgstdecodebin_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + \ + -:PROJECT libgstdecodebin2 -:SHARED libgstdecodebin2 \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstdecodebin2_la_SOURCES) \ + $(nodist_libgstdecodebin2_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstdecodebin2_la_CFLAGS) \ + -:LDFLAGS $(libgstdecodebin2_la_LDFLAGS) \ + $(libgstdecodebin2_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + \ + -:PROJECT libgstplaybin -:SHARED libgstplaybin \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstplaybin_la_SOURCES) \ + $(nodist_libgstplaybin_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstplaybin_la_CFLAGS) \ + -:LDFLAGS $(libgstplaybin_la_LDFLAGS) \ + $(libgstplaybin_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/README b/gst-plugins-base-subtitles0.10/gst/playback/README new file mode 100644 index 0000000..286e49f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/README @@ -0,0 +1,91 @@ +decodebin: + + A bin with a sinkpad that decodes the data into raw formats. It works by sending + the input data through a typefind element and then recursively autoplugs elements + from the registry until a raw format is obtained. It will then create a new ghostpad + on itself to signal the app of the new pad. + + Decodebin will also remove pads when they are removed from the stream. + + TODO + - reuse of decoderbin, cleanup in READY state + - threading after demuxing? + - new_media events should be handled. + - caching of elements. + - abstract more elements, pads (typefind, ...); + + The autoplugging happens as follows: + + 1) typefind is added internally to the bin. + 2) the have_type signal is connected to typefind. + 3) in the have_type callback the close_pad_link function is called + 4) close_pad_link checks the type on the pad, if it is raw, a ghostpad + is created and autoplugging for that pad stops. + 5) if the type of the pad is not raw, a list of possible elements that + can connect to this type is generated in find_compatibles. + 6) try_to_link_1 with the element list is called. The function will loop + over the element list and will try to connect one of the elements to + the pad. If the link works, a call is made to close_link. + 7) close_link loops over all the source pads of the element and + recursively calls 4) for any ALWAYS pad. For elements with + a SOMETIMES pad, a structure is set up and is passed to the callback + of the new_pad signal. + 8) in the new_pad callback, 4) is called to try to autoplug the + new pad. + + +playbasebin: + + A bin with an uri property. It will find the right source element from the registry + and connect a decoderbin to it. When going to the PAUSED state, it will iterate the + decoderbin and listen for new pad signals from it. It will connect a queue to each + new pad and will iterate the decoderbin until one of the queues is filled. It is + assumed that by that time all the streams will be found so that when leaving the + PAUSED state, one can query the number of streams in the media file with the given + uri. + + Playbasebin internally groups related streams together in a GstPlayBaseGroup. This + is particulary important for chained oggs. Initially, a new group is created in + the 'building' state. All new streams will be added to the building group until + no-more-pads is signaled or one of the preroll queues overflows. When this happens, + the group is commited to a list of groups ready for playback. PlaybaseBin will then + attach a padprobe to each stream to figure out when it finished. It will remove + the current group and install the next playable group, then. + + Before going to the PLAYING state, it is possible to connect a custom element to + each of the streams. To do that, you have to add the element to the bin and then + connect the pad(s) from the stream(s). You do not have to add the elements in + a thread, the bin will take care of then when it's needed. You are allowed to use + threads inside the elements, of course. + The bin tries to be smart and doesn't add a queue when there is only one possible + stream. + + + TODO + - reuse, cleanup in ready state + - when the first pad is closed, it's possible that another dynamic element is + added somewhere so that we need a queue for the first pad as well. + + +playbin: + + Extends playbasebin, sets up default audiosink and videosink for first audio/video + stream detected. implements seeking and querying on the configured sinks. + + It also waits for new notifications from playbasebin about any new groups that are + becomming active. It then disconnects the sinks and reconnects them to the new + pads in the group. + + TODO + - reuse, refcounting, cleanup in READY state + - be smarter about replugging the sinks instead of removing them and readding them. + - Do not crap out when the audio device is in use. + + +general + + TODO + - playlist support. maybe use a playlist bin that streams the contents of the + playlist on a pad, interleaved with new_media events. Also add a tuner + interface while we're at it. + diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin.c b/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin.c new file mode 100644 index 0000000..854a28d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin.c @@ -0,0 +1,2059 @@ +/* GStreamer + * Copyright (C) <2004> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-decodebin + * + * #GstBin that auto-magically constructs a decoding pipeline using available + * decoders and demuxers via auto-plugging. + * + * When using decodebin in your application, connect a signal handler to + * #GstDecodeBin::new-decoded-pad and connect your sinks from within the + * callback function. + * + * + * This element is deprecated and no longer supported. You should use the + * #uridecodebin or #decodebin2 element instead (or, even better: #playbin2). + * + * + * Deprecated: use uridecodebin or decodebin2 instead. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#include "gstplay-marshal.h" + +/* generic templates */ +static GstStaticPadTemplate decoder_bin_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate decoder_bin_src_template = +GST_STATIC_PAD_TEMPLATE ("src%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug); +#define GST_CAT_DEFAULT gst_decode_bin_debug + +#define GST_TYPE_DECODE_BIN (gst_decode_bin_get_type()) +#define GST_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin)) +#define GST_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass)) +#define GST_IS_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN)) +#define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN)) + +typedef struct _GstDecodeBin GstDecodeBin; +typedef struct _GstDecodeBinClass GstDecodeBinClass; + +/** + * GstDecodeBin: + * + * Auto-plugging decoder element structure + */ +struct _GstDecodeBin +{ + GstBin bin; /* we extend GstBin */ + + GstElement *typefind; /* this holds the typefind object */ + GstElement *fakesink; + + GList *dynamics; /* list of dynamic connections */ + + GList *queues; /* list of demuxer-decoder queues */ + + GList *probes; /* list of PadProbeData */ + + GList *factories; /* factories we can use for selecting elements */ + gint numpads; + gint numwaiting; + + gboolean have_type; + guint have_type_id; /* signal id for the typefind element */ + + gboolean shutting_down; /* stop pluggin if we're shutting down */ + + GType queue_type; /* store the GType of queues, to aid in recognising them */ + + GMutex *cb_mutex; /* Mutex for multi-threaded callbacks, such as removing the fakesink */ +}; + +struct _GstDecodeBinClass +{ + GstBinClass parent_class; + + /* signal we fire when a new pad has been decoded into raw audio/video */ + void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last); + /* signal we fire when a pad has been removed */ + void (*removed_decoded_pad) (GstElement * element, GstPad * pad); + /* signal fired when we found a pad that we cannot decode */ + void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps); +}; + +/* signals */ +enum +{ + SIGNAL_NEW_DECODED_PAD, + SIGNAL_REMOVED_DECODED_PAD, + SIGNAL_UNKNOWN_TYPE, + SIGNAL_REDIRECT, + LAST_SIGNAL +}; + +/* Properties */ +enum +{ + PROP_0, + PROP_SINK_CAPS, +}; + + +typedef struct +{ + GstPad *pad; + gulong sigid; + gboolean done; +} PadProbeData; + +/* this structure is created for all dynamic pads that could get created + * at runtime */ +typedef struct +{ + GstDecodeBin *decode_bin; /* pointer to ourself */ + + GstElement *element; /* the element sending the signal */ + gint np_sig_id; /* signal id of new_pad */ + gint nmp_sig_id; /* signal id of no_more_pads */ + + GstPad *pad; /* the pad sending the signal */ + gint caps_sig_id; /* signal id of caps */ +} +GstDynamic; + +static void gst_decode_bin_class_init (GstDecodeBinClass * klass); +static void gst_decode_bin_init (GstDecodeBin * decode_bin); +static void gst_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_decode_bin_dispose (GObject * object); +static void gst_decode_bin_finalize (GObject * object); + +static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, + GstStateChange transition); + +static gboolean add_fakesink (GstDecodeBin * decode_bin); +static void remove_fakesink (GstDecodeBin * decode_bin); + +static void dynamic_free (GstDynamic * dyn); +static void free_dynamics (GstDecodeBin * decode_bin); +static void type_found (GstElement * typefind, guint probability, + GstCaps * caps, GstDecodeBin * decode_bin); +static GstElement *try_to_link_1 (GstDecodeBin * decode_bin, + GstElement * origelement, GstPad * pad, GList * factories); +static void close_link (GstElement * element, GstDecodeBin * decode_bin); +static void close_pad_link (GstElement * element, GstPad * pad, + GstCaps * caps, GstDecodeBin * decode_bin, gboolean more); +static void unlinked (GstPad * pad, GstPad * peerpad, + GstDecodeBin * decode_bin); +static void new_pad (GstElement * element, GstPad * pad, GstDynamic * dynamic); +static void no_more_pads (GstElement * element, GstDynamic * dynamic); +static void new_caps (GstPad * pad, GParamSpec * unused, GstDynamic * dynamic); + +static void queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin); +static void queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin); + +static gboolean is_demuxer_element (GstElement * srcelement); + +static GstElementClass *parent_class; +static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 }; + + +static GType +gst_decode_bin_get_type (void) +{ + static GType gst_decode_bin_type = 0; + + if (!gst_decode_bin_type) { + static const GTypeInfo gst_decode_bin_info = { + sizeof (GstDecodeBinClass), + NULL, + NULL, + (GClassInitFunc) gst_decode_bin_class_init, + NULL, + NULL, + sizeof (GstDecodeBin), + 0, + (GInstanceInitFunc) gst_decode_bin_init, + NULL + }; + + gst_decode_bin_type = + g_type_register_static (GST_TYPE_BIN, "GstDecodeBin", + &gst_decode_bin_info, 0); + } + + return gst_decode_bin_type; +} + +static void +gst_decode_bin_class_init (GstDecodeBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_decode_bin_set_property; + gobject_klass->get_property = gst_decode_bin_get_property; + gobject_klass->dispose = gst_decode_bin_dispose; + gobject_klass->finalize = gst_decode_bin_finalize; + + /** + * GstDecodeBin::new-decoded-pad: + * @bin: The decodebin + * @pad: The newly created pad + * @islast: #TRUE if this is the last pad to be added. Deprecated. + * + * This signal gets emitted as soon as a new pad of the same type as one of + * the valid 'raw' types is added. + */ + gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] = + g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL, + gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD, + G_TYPE_BOOLEAN); + /** + * GstDecodeBin::removed-decoded-pad: + * @bin: The decodebin + * @pad: The pad that was removed + * + * This signal is emitted when a 'final' caps pad has been removed. + */ + gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] = + g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); + /** + * GstDecodeBin::unknown-type: + * @bin: The decodebin + * @pad: The new pad containing caps that cannot be resolved to a 'final' + * stream type. + * @caps: The #GstCaps of the pad that cannot be resolved. + * + * This signal is emitted when a pad for which there is no further possible + * decoding is added to the decodebin. + */ + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = + g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), + NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); + + g_object_class_install_property (gobject_klass, PROP_SINK_CAPS, + g_param_spec_boxed ("sink-caps", "Sink Caps", + "The caps of the input data. (NULL = use typefind element)", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&decoder_bin_sink_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&decoder_bin_src_template)); + + gst_element_class_set_details_simple (gstelement_klass, + "Decoder Bin", "Generic/Bin/Decoder", + "Autoplug and decode to raw media", + "Wim Taymans "); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_decode_bin_change_state); +} + +/* check if the bin is dynamic. + * + * If there are no outstanding dynamic connections, the bin is + * considered to be non-dynamic. + */ +static gboolean +gst_decode_bin_is_dynamic (GstDecodeBin * decode_bin) +{ + return decode_bin->dynamics != NULL; +} + +/* the filter function for selecting the elements we can use in + * autoplugging */ +static gboolean +gst_decode_bin_factory_filter (GstPluginFeature * feature, + GstDecodeBin * decode_bin) +{ + guint rank; + const gchar *klass; + + /* we only care about element factories */ + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + + klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY (feature)); + /* only demuxers, decoders and parsers can play */ + if (strstr (klass, "Demux") == NULL && + strstr (klass, "Decoder") == NULL && strstr (klass, "Parse") == NULL && + strstr (klass, "Depayloader") == NULL) { + return FALSE; + } + + /* only select elements with autoplugging rank */ + rank = gst_plugin_feature_get_rank (feature); + if (rank < GST_RANK_MARGINAL) + return FALSE; + + return TRUE; +} + +/* function used to sort element features */ +static gint +compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2) +{ + gint diff; + const gchar *rname1, *rname2; + + diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); + if (diff != 0) + return diff; + + rname1 = gst_plugin_feature_get_name (f1); + rname2 = gst_plugin_feature_get_name (f2); + + diff = strcmp (rname2, rname1); + + return diff; +} + +static void +print_feature (GstPluginFeature * feature) +{ + const gchar *rname; + + rname = gst_plugin_feature_get_name (feature); + + GST_DEBUG ("%s", rname); +} + +static void +gst_decode_bin_init (GstDecodeBin * decode_bin) +{ + GList *factories; + + decode_bin->cb_mutex = g_mutex_new (); + + /* first filter out the interesting element factories */ + factories = gst_default_registry_feature_filter ( + (GstPluginFeatureFilter) gst_decode_bin_factory_filter, + FALSE, decode_bin); + + /* sort them according to their ranks */ + decode_bin->factories = g_list_sort (factories, (GCompareFunc) compare_ranks); + /* do some debugging */ + g_list_foreach (decode_bin->factories, (GFunc) print_feature, NULL); + + /* we create the typefind element only once */ + decode_bin->typefind = gst_element_factory_make ("typefind", "typefind"); + if (!decode_bin->typefind) { + g_warning ("can't find typefind element, decodebin will not work"); + } else { + GstPad *pad, *gpad; + GstPadTemplate *pad_tmpl; + + /* add the typefind element */ + if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) { + g_warning ("Could not add typefind element, decodebin will not work"); + gst_object_unref (decode_bin->typefind); + decode_bin->typefind = NULL; + } + + /* get the sinkpad */ + pad = gst_element_get_static_pad (decode_bin->typefind, "sink"); + + /* get the pad template */ + pad_tmpl = gst_static_pad_template_get (&decoder_bin_sink_template); + + /* ghost the sink pad to ourself */ + gpad = gst_ghost_pad_new_from_template ("sink", pad, pad_tmpl); + gst_pad_set_active (gpad, TRUE); + gst_element_add_pad (GST_ELEMENT (decode_bin), gpad); + + gst_object_unref (pad_tmpl); + gst_object_unref (pad); + + /* connect a signal to find out when the typefind element found + * a type */ + decode_bin->have_type_id = + g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type", + G_CALLBACK (type_found), decode_bin); + } + add_fakesink (decode_bin); + + decode_bin->dynamics = NULL; + decode_bin->queues = NULL; + decode_bin->probes = NULL; +} + +static void +gst_decode_bin_dispose (GObject * object) +{ + GstDecodeBin *decode_bin; + + decode_bin = GST_DECODE_BIN (object); + + if (decode_bin->factories) + gst_plugin_feature_list_free (decode_bin->factories); + decode_bin->factories = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); + + /* our parent dispose might trigger new signals when pads are unlinked + * etc. clean up the mess here. */ + /* FIXME do proper cleanup when going to NULL */ + free_dynamics (decode_bin); +} + +static void +gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps) +{ + GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); + + g_object_set (dbin->typefind, "force-caps", caps, NULL); +} + +static GstCaps * +gst_decode_bin_get_sink_caps (GstDecodeBin * dbin) +{ + GstCaps *caps; + + GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); + + g_object_get (dbin->typefind, "force-caps", &caps, NULL); + + return caps; +} + +static void +gst_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDecodeBin *dbin; + + dbin = GST_DECODE_BIN (object); + + switch (prop_id) { + case PROP_SINK_CAPS: + gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDecodeBin *dbin; + + dbin = GST_DECODE_BIN (object); + switch (prop_id) { + case PROP_SINK_CAPS: + g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_decode_bin_finalize (GObject * object) +{ + GstDecodeBin *decode_bin = GST_DECODE_BIN (object); + + g_mutex_free (decode_bin->cb_mutex); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +struct DynFind +{ + GstElement *elem; + GstPad *pad; +}; + +static gint +find_dynamic (GstDynamic * dyn, struct DynFind *info) +{ + if (dyn->element == info->elem && dyn->pad == info->pad) + return 0; + return 1; +} + +/* Add either an element (for dynamic pads/pad-added watching) or a + * pad (for delayed caps/notify::caps watching) to the dynamic list, + * taking care to ignore repeat entries so we don't end up handling a + * pad twice, for example */ +static void +dynamic_add (GstElement * element, GstPad * pad, GstDecodeBin * decode_bin) +{ + GstDynamic *dyn; + struct DynFind find_info; + GList *found; + + g_return_if_fail (element != NULL); + + /* do a search that this entry doesn't already exist */ + find_info.elem = element; + find_info.pad = pad; + found = g_list_find_custom (decode_bin->dynamics, &find_info, + (GCompareFunc) find_dynamic); + if (found != NULL) + goto exit; + + /* take refs */ + dyn = g_new0 (GstDynamic, 1); + dyn->element = gst_object_ref (element); + dyn->decode_bin = gst_object_ref (decode_bin); + if (pad) { + dyn->pad = gst_object_ref (pad); + GST_DEBUG_OBJECT (decode_bin, "dynamic create for pad %" GST_PTR_FORMAT, + pad); + dyn->caps_sig_id = g_signal_connect (G_OBJECT (pad), "notify::caps", + G_CALLBACK (new_caps), dyn); + } else { + GST_DEBUG_OBJECT (decode_bin, "dynamic create for element %" + GST_PTR_FORMAT, element); + dyn->np_sig_id = g_signal_connect (G_OBJECT (element), "pad-added", + G_CALLBACK (new_pad), dyn); + dyn->nmp_sig_id = g_signal_connect (G_OBJECT (element), "no-more-pads", + G_CALLBACK (no_more_pads), dyn); + } + + /* and add this element to the dynamic elements */ + decode_bin->dynamics = g_list_prepend (decode_bin->dynamics, dyn); + + return; +exit: + if (element) { + GST_DEBUG_OBJECT (decode_bin, "Dynamic element already added: %" + GST_PTR_FORMAT, element); + } else { + GST_DEBUG_OBJECT (decode_bin, "Dynamic pad already added: %" + GST_PTR_FORMAT, pad); + } +} + +static void +dynamic_free (GstDynamic * dyn) +{ + GST_DEBUG_OBJECT (dyn->decode_bin, "dynamic free"); + + /* disconnect signals */ + if (dyn->np_sig_id) + g_signal_handler_disconnect (G_OBJECT (dyn->element), dyn->np_sig_id); + if (dyn->nmp_sig_id) + g_signal_handler_disconnect (G_OBJECT (dyn->element), dyn->nmp_sig_id); + if (dyn->caps_sig_id) + g_signal_handler_disconnect (G_OBJECT (dyn->pad), dyn->caps_sig_id); + + if (dyn->pad) + gst_object_unref (dyn->pad); + dyn->pad = NULL; + if (dyn->element) + gst_object_unref (dyn->element); + dyn->element = NULL; + + gst_object_unref (dyn->decode_bin); + dyn->decode_bin = NULL; + + g_free (dyn); +} + +static void +free_dynamics (GstDecodeBin * decode_bin) +{ + GList *dyns; + + for (dyns = decode_bin->dynamics; dyns; dyns = g_list_next (dyns)) { + GstDynamic *dynamic = (GstDynamic *) dyns->data; + + dynamic_free (dynamic); + } + g_list_free (decode_bin->dynamics); + decode_bin->dynamics = NULL; +} + +/* this function runs through the element factories and returns a list + * of all elements that are able to sink the given caps + */ +static GList * +find_compatibles (GstDecodeBin * decode_bin, const GstCaps * caps) +{ + GList *factories; + GList *to_try = NULL; + + /* loop over all the factories */ + for (factories = decode_bin->factories; factories; + factories = g_list_next (factories)) { + GstElementFactory *factory = GST_ELEMENT_FACTORY (factories->data); + const GList *templates; + GList *walk; + + /* get the templates from the element factory */ + templates = gst_element_factory_get_static_pad_templates (factory); + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + + /* we only care about the sink templates */ + if (templ->direction == GST_PAD_SINK) { + gboolean can_intersect; + GstCaps *tmpl_caps; + + /* try to intersect the caps with the caps of the template */ + tmpl_caps = gst_static_caps_get (&templ->static_caps); + + can_intersect = gst_caps_can_intersect (caps, tmpl_caps); + gst_caps_unref (tmpl_caps); + + /* check if the intersection is empty */ + if (can_intersect) { + /* non empty intersection, we can use this element */ + to_try = g_list_prepend (to_try, factory); + break; + } + } + } + } + to_try = g_list_reverse (to_try); + + return to_try; +} + +static gboolean +mimetype_is_raw (const gchar * mimetype) +{ + return g_str_has_prefix (mimetype, "video/x-raw") || + g_str_has_prefix (mimetype, "audio/x-raw") || + g_str_has_prefix (mimetype, "text/plain") || + g_str_has_prefix (mimetype, "text/x-pango-markup"); +} + +static void +free_pad_probes (GstDecodeBin * decode_bin) +{ + GList *tmp; + + /* Remove pad probes */ + for (tmp = decode_bin->probes; tmp; tmp = g_list_next (tmp)) { + PadProbeData *data = (PadProbeData *) tmp->data; + + gst_pad_remove_data_probe (data->pad, data->sigid); + g_free (data); + } + g_list_free (decode_bin->probes); + decode_bin->probes = NULL; +} + +/* used when we need to remove a probe because the decoder we plugged failed + * to activate */ +static void +free_pad_probe_for_element (GstDecodeBin * decode_bin, GstElement * element) +{ + GList *l; + + for (l = decode_bin->probes; l != NULL; l = g_list_next (l)) { + PadProbeData *data = (PadProbeData *) l->data; + + if (GST_ELEMENT_CAST (GST_PAD_PARENT (data->pad)) == element) { + gst_pad_remove_data_probe (data->pad, data->sigid); + decode_bin->probes = g_list_delete_link (decode_bin->probes, l); + g_free (data); + return; + } + } +} + +static gboolean +add_fakesink (GstDecodeBin * decode_bin) +{ + if (decode_bin->fakesink != NULL) + return TRUE; + + g_mutex_lock (decode_bin->cb_mutex); + + decode_bin->fakesink = gst_element_factory_make ("fakesink", "fakesink"); + if (!decode_bin->fakesink) + goto no_fakesink; + + /* hacky, remove sink flag, we don't want our decodebin to become a sink + * just because we add a fakesink element to make us ASYNC */ + GST_OBJECT_FLAG_UNSET (decode_bin->fakesink, GST_ELEMENT_IS_SINK); + + /* takes ownership */ + if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->fakesink)) { + g_warning ("Could not add fakesink element, decodebin will not work"); + gst_object_unref (decode_bin->fakesink); + decode_bin->fakesink = NULL; + } + g_mutex_unlock (decode_bin->cb_mutex); + return TRUE; + + /* ERRORS */ +no_fakesink: + { + g_warning ("can't find fakesink element, decodebin will not work"); + g_mutex_unlock (decode_bin->cb_mutex); + return FALSE; + } +} + +static void +remove_fakesink (GstDecodeBin * decode_bin) +{ + gboolean removed_fakesink = FALSE; + + if (decode_bin->fakesink == NULL) + return; + + g_mutex_lock (decode_bin->cb_mutex); + if (decode_bin->fakesink) { + GST_DEBUG_OBJECT (decode_bin, "Removing fakesink and marking state dirty"); + + /* Lock the state to prevent it from changing state to non-NULL + * before it's removed */ + gst_element_set_locked_state (decode_bin->fakesink, TRUE); + /* setting the state to NULL is never async */ + gst_element_set_state (decode_bin->fakesink, GST_STATE_NULL); + gst_bin_remove (GST_BIN (decode_bin), decode_bin->fakesink); + decode_bin->fakesink = NULL; + + removed_fakesink = TRUE; + } + g_mutex_unlock (decode_bin->cb_mutex); + + if (removed_fakesink) { + free_pad_probes (decode_bin); + } +} + +/* this should be implemented with _pad_block() */ +static gboolean +pad_probe (GstPad * pad, GstMiniObject * data, GstDecodeBin * decode_bin) +{ + GList *tmp; + gboolean alldone = TRUE; + + for (tmp = decode_bin->probes; tmp; tmp = g_list_next (tmp)) { + PadProbeData *pdata = (PadProbeData *) tmp->data; + + if (pdata->pad == pad) { + if (GST_IS_BUFFER (data)) { + if (!pdata->done) + decode_bin->numwaiting--; + pdata->done = TRUE; + } else if (GST_IS_EVENT (data) && + ((GST_EVENT_TYPE (data) == GST_EVENT_EOS) || + (GST_EVENT_TYPE (data) == GST_EVENT_TAG) || + (GST_EVENT_TYPE (data) == GST_EVENT_FLUSH_START))) { + /* FIXME, what about NEWSEGMENT? really, use _pad_block()... */ + if (!pdata->done) + decode_bin->numwaiting--; + pdata->done = TRUE; + } + } + + if (!(pdata->done)) { + GST_LOG_OBJECT (decode_bin, "Pad probe on pad %" GST_PTR_FORMAT + " but pad %" GST_PTR_FORMAT " still needs data.", pad, pdata->pad); + alldone = FALSE; + } + } + if (alldone) + remove_fakesink (decode_bin); + return TRUE; +} + +/* FIXME: this should be somehow merged with the queue code in + * try_to_link_1() to reduce code duplication */ +static GstPad * +add_raw_queue (GstDecodeBin * decode_bin, GstPad * pad) +{ + GstElement *queue = NULL; + GstPad *queuesinkpad = NULL, *queuesrcpad = NULL; + + queue = gst_element_factory_make ("queue", NULL); + decode_bin->queue_type = G_OBJECT_TYPE (queue); + + g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); + g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), NULL); + g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); + gst_bin_add (GST_BIN (decode_bin), queue); + gst_element_set_state (queue, GST_STATE_READY); + queuesinkpad = gst_element_get_static_pad (queue, "sink"); + queuesrcpad = gst_element_get_static_pad (queue, "src"); + + if (gst_pad_link (pad, queuesinkpad) != GST_PAD_LINK_OK) { + GST_WARNING_OBJECT (decode_bin, + "Linking queue failed, trying without queue"); + gst_element_set_state (queue, GST_STATE_NULL); + gst_object_unref (queuesrcpad); + gst_object_unref (queuesinkpad); + gst_bin_remove (GST_BIN (decode_bin), queue); + return gst_object_ref (pad); + } + + decode_bin->queues = g_list_append (decode_bin->queues, queue); + g_signal_connect (G_OBJECT (queue), + "overrun", G_CALLBACK (queue_filled_cb), decode_bin); + g_signal_connect (G_OBJECT (queue), + "underrun", G_CALLBACK (queue_underrun_cb), decode_bin); + + gst_element_set_state (queue, GST_STATE_PAUSED); + gst_object_unref (queuesinkpad); + + return queuesrcpad; +} + +/* given a pad and a caps from an element, find the list of elements + * that could connect to the pad + * + * If the pad has a raw format, this function will create a ghostpad + * for the pad onto the decodebin. + * + * If no compatible elements could be found, this function will signal + * the unknown_type signal. + */ +static void +close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps, + GstDecodeBin * decode_bin, gboolean more) +{ + GstStructure *structure; + const gchar *mimetype; + gchar *padname; + gint diff; + + padname = gst_pad_get_name (pad); + diff = strncmp (padname, "current_", 8); + g_free (padname); + + /* hack.. ignore current pads */ + if (!diff) + return; + + /* the caps is empty, this means the pad has no type, we can only + * decide to fire the unknown_type signal. */ + if (caps == NULL || gst_caps_is_empty (caps)) + goto unknown_type; + + /* the caps is any, this means the pad can be anything and + * we don't know yet */ + if (gst_caps_is_any (caps)) + goto dont_know_yet; + + GST_LOG_OBJECT (element, "trying to close %" GST_PTR_FORMAT, caps); + + /* FIXME, iterate over more structures? I guess it is possible that + * this pad has some encoded and some raw pads. This code will fail + * then if the first structure is not the raw type... */ + structure = gst_caps_get_structure (caps, 0); + mimetype = gst_structure_get_name (structure); + + /* first see if this is raw. If the type is raw, we can + * create a ghostpad for this pad. It's possible that the caps are not + * fixed. */ + if (mimetype_is_raw (mimetype)) { + GstPadTemplate *tmpl; + gchar *padname; + GstPad *ghost; + PadProbeData *data; + + /* If we're at a demuxer element but have raw data already + * we have to add a queue here. For non-raw data this is done + * in try_to_link_1() */ + if (is_demuxer_element (element)) { + GST_DEBUG_OBJECT (decode_bin, + "Element %s is a demuxer, inserting a queue", + GST_OBJECT_NAME (element)); + + pad = add_raw_queue (decode_bin, pad); + } + + /* make a unique name for this new pad */ + padname = g_strdup_printf ("src%d", decode_bin->numpads); + decode_bin->numpads++; + + /* make it a ghostpad */ + tmpl = gst_static_pad_template_get (&decoder_bin_src_template); + ghost = gst_ghost_pad_new_from_template (padname, pad, tmpl); + gst_object_unref (tmpl); + + gst_pad_set_active (ghost, TRUE); + gst_element_add_pad (GST_ELEMENT (decode_bin), ghost); + + data = g_new0 (PadProbeData, 1); + data->pad = pad; + data->done = FALSE; + + /* FIXME, use _pad_block() */ + data->sigid = gst_pad_add_data_probe (pad, G_CALLBACK (pad_probe), + decode_bin); + decode_bin->numwaiting++; + + decode_bin->probes = g_list_append (decode_bin->probes, data); + + GST_LOG_OBJECT (element, "closed pad %s", padname); + + /* our own signal with an extra flag that this is the only pad */ + GST_DEBUG_OBJECT (decode_bin, "emitting new-decoded-pad"); + g_signal_emit (G_OBJECT (decode_bin), + gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, ghost, !more); + GST_DEBUG_OBJECT (decode_bin, "emitted new-decoded-pad"); + + g_free (padname); + + /* If we're at a demuxer element pad was set to a queue's + * srcpad and must be unref'd here */ + if (is_demuxer_element (element)) + gst_object_unref (pad); + } else { + GList *to_try; + + /* if the caps has many types, we need to delay */ + if (!gst_caps_is_fixed (caps)) + goto many_types; + + /* continue plugging, first find all compatible elements */ + to_try = find_compatibles (decode_bin, caps); + if (to_try == NULL) + /* no compatible elements, we cannot go on */ + goto unknown_type; + + if (try_to_link_1 (decode_bin, element, pad, to_try) == NULL) { + g_list_free (to_try); + GST_LOG_OBJECT (pad, "none of the allegedly available elements usable"); + goto unknown_type; + } + + /* can free the list again now */ + g_list_free (to_try); + } + return; + + /* ERRORS */ +unknown_type: + { + GST_LOG_OBJECT (pad, "unknown type found, fire signal"); + g_signal_emit (G_OBJECT (decode_bin), + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); + + gst_element_post_message (GST_ELEMENT_CAST (decode_bin), + gst_missing_decoder_message_new (GST_ELEMENT_CAST (decode_bin), caps)); + + if (element == decode_bin->typefind) { + gchar *desc; + + desc = gst_pb_utils_get_decoder_description (caps); + GST_ELEMENT_ERROR (decode_bin, STREAM, CODEC_NOT_FOUND, + (_("A %s plugin is required to play this stream, but not installed."), + desc), + ("No decoder to handle media type '%s'", + gst_structure_get_name (gst_caps_get_structure (caps, 0)))); + g_free (desc); + } + + return; + } +dont_know_yet: + { + GST_LOG_OBJECT (pad, "type is not known yet"); + goto setup_caps_delay; + } +many_types: + { + GST_LOG_OBJECT (pad, "many possible types"); + goto setup_caps_delay; + } +setup_caps_delay: + { + GST_LOG_OBJECT (pad, "setting up a delayed link"); + dynamic_add (element, pad, decode_bin); + return; + } +} + +/* Decide whether an element is a demuxer based on the + * klass and number/type of src pad templates it has */ +static gboolean +is_demuxer_element (GstElement * srcelement) +{ + GstElementFactory *srcfactory; + GstElementClass *elemclass; + GList *walk; + const gchar *klass; + gint potential_src_pads = 0; + + srcfactory = gst_element_get_factory (srcelement); + klass = gst_element_factory_get_klass (srcfactory); + + /* Can't be a demuxer unless it has Demux in the klass name */ + if (klass == NULL || !strstr (klass, "Demux")) + return FALSE; + + /* Walk the src pad templates and count how many the element + * might produce */ + elemclass = GST_ELEMENT_GET_CLASS (srcelement); + + walk = gst_element_class_get_pad_template_list (elemclass); + while (walk != NULL) { + GstPadTemplate *templ; + + templ = (GstPadTemplate *) walk->data; + if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_ALWAYS: + case GST_PAD_SOMETIMES: + if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%")) + potential_src_pads += 2; /* Might make multiple pads */ + else + potential_src_pads += 1; + break; + case GST_PAD_REQUEST: + potential_src_pads += 2; + break; + } + } + walk = g_list_next (walk); + } + + if (potential_src_pads < 2) + return FALSE; + + return TRUE; +} + +/* + * given a list of element factories, try to link one of the factories + * to the given pad. + * + * The function returns the element that was successfully linked to the + * pad. + */ +static GstElement * +try_to_link_1 (GstDecodeBin * decode_bin, GstElement * srcelement, GstPad * pad, + GList * factories) +{ + GList *walk; + GstElement *result = NULL; + gboolean isdemux = FALSE; + GstPad *queuesinkpad = NULL, *queuesrcpad = NULL; + GstElement *queue = NULL; + GstPad *usedsrcpad = pad; + + /* Check if the parent of the src pad is a demuxer */ + isdemux = is_demuxer_element (srcelement); + + if (isdemux && factories != NULL) { + GstPadLinkReturn dqlink; + + /* Insert a queue between demuxer and decoder */ + GST_DEBUG_OBJECT (decode_bin, + "Element %s is a demuxer, inserting a queue", + GST_OBJECT_NAME (srcelement)); + queue = gst_element_factory_make ("queue", NULL); + decode_bin->queue_type = G_OBJECT_TYPE (queue); + + g_object_set (G_OBJECT (queue), "max-size-buffers", 0, NULL); + g_object_set (G_OBJECT (queue), "max-size-time", G_GINT64_CONSTANT (0), + NULL); + g_object_set (G_OBJECT (queue), "max-size-bytes", 8192, NULL); + gst_bin_add (GST_BIN (decode_bin), queue); + gst_element_set_state (queue, GST_STATE_READY); + queuesinkpad = gst_element_get_static_pad (queue, "sink"); + usedsrcpad = queuesrcpad = gst_element_get_static_pad (queue, "src"); + + dqlink = gst_pad_link (pad, queuesinkpad); + g_return_val_if_fail (dqlink == GST_PAD_LINK_OK, NULL); + } + + /* loop over the factories */ + for (walk = factories; walk; walk = g_list_next (walk)) { + GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data); + GstElement *element; + GstPadLinkReturn ret; + GstPad *sinkpad; + + GST_DEBUG_OBJECT (decode_bin, "trying to link %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + + /* make an element from the factory first */ + if ((element = gst_element_factory_create (factory, NULL)) == NULL) { + /* hmm, strange. Like with all things in life, let's move on.. */ + GST_WARNING_OBJECT (decode_bin, "could not create an element from %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + continue; + } + + /* try to link the given pad to a sinkpad */ + /* FIXME, find the sinkpad by looping over the pads instead of + * looking it up by name */ + if ((sinkpad = gst_element_get_static_pad (element, "sink")) == NULL) { + /* if no pad is found we can't do anything */ + GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element"); + continue; + } + + /* now add the element to the bin first */ + GST_DEBUG_OBJECT (decode_bin, "adding %s", GST_OBJECT_NAME (element)); + gst_bin_add (GST_BIN (decode_bin), element); + + /* set to READY first so it is ready, duh. */ + if (gst_element_set_state (element, + GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { + GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to READY", + GST_ELEMENT_NAME (element)); + /* get rid of the sinkpad */ + gst_object_unref (sinkpad); + /* this element did not work, remove it again and continue trying + * other elements, the element will be disposed. */ + /* FIXME: shouldn't we do this before adding it to the bin so that no + * error messages get through to the app? (tpm) */ + gst_bin_remove (GST_BIN (decode_bin), element); + continue; + } + + if ((ret = gst_pad_link (usedsrcpad, sinkpad)) != GST_PAD_LINK_OK) { + GST_DEBUG_OBJECT (decode_bin, "link failed on pad %s:%s, reason %d", + GST_DEBUG_PAD_NAME (pad), ret); + /* get rid of the sinkpad */ + gst_object_unref (sinkpad); + /* this element did not work, remove it again and continue trying + * other elements, the element will be disposed. */ + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN (decode_bin), element); + } else { + GST_DEBUG_OBJECT (decode_bin, "linked on pad %s:%s", + GST_DEBUG_PAD_NAME (usedsrcpad)); + + /* configure the queue some more */ + if (queue != NULL) { + decode_bin->queues = g_list_append (decode_bin->queues, queue); + g_signal_connect (G_OBJECT (queue), + "overrun", G_CALLBACK (queue_filled_cb), decode_bin); + g_signal_connect (G_OBJECT (queue), + "underrun", G_CALLBACK (queue_underrun_cb), decode_bin); + } + + /* The link worked, now figure out what it was that we connected */ + + /* make sure we catch unlink signals */ + g_signal_connect (G_OBJECT (pad), "unlinked", + G_CALLBACK (unlinked), decode_bin); + + /* now that we added the element we can try to continue autoplugging + * on it until we have a raw type */ + close_link (element, decode_bin); + + /* change the state of the element to that of the parent */ + if ((gst_element_set_state (element, + GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { + GST_WARNING_OBJECT (decode_bin, "Couldn't set %s to PAUSED", + GST_ELEMENT_NAME (element)); + /* close_link -> close_pad_link -> might have set up a pad probe */ + free_pad_probe_for_element (decode_bin, element); + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN (decode_bin), element); + continue; + } + + result = element; + + /* get rid of the sinkpad now */ + gst_object_unref (sinkpad); + + /* Set the queue to paused and set the pointer to NULL so we don't + * remove it below */ + if (queue != NULL) { + gst_element_set_state (queue, GST_STATE_PAUSED); + queue = NULL; + gst_object_unref (queuesrcpad); + gst_object_unref (queuesinkpad); + } + + /* and exit */ + goto done; + } + } +done: + if (queue != NULL) { + /* We didn't successfully connect to the queue */ + gst_pad_unlink (pad, queuesinkpad); + gst_element_set_state (queue, GST_STATE_NULL); + gst_object_unref (queuesrcpad); + gst_object_unref (queuesinkpad); + gst_bin_remove (GST_BIN (decode_bin), queue); + } + return result; +} + +static GstPad * +get_our_ghost_pad (GstDecodeBin * decode_bin, GstPad * pad) +{ + GstIterator *pad_it = NULL; + GstPad *db_pad = NULL; + gboolean done = FALSE; + + if (pad == NULL || !GST_PAD_IS_SRC (pad)) { + GST_DEBUG_OBJECT (decode_bin, "pad NULL or not SRC pad"); + return NULL; + } + + /* our ghostpads are the sourcepads */ + pad_it = gst_element_iterate_src_pads (GST_ELEMENT (decode_bin)); + while (!done) { + db_pad = NULL; + switch (gst_iterator_next (pad_it, (gpointer) & db_pad)) { + case GST_ITERATOR_OK: + GST_DEBUG_OBJECT (decode_bin, "looking at pad %s:%s", + GST_DEBUG_PAD_NAME (db_pad)); + if (GST_IS_GHOST_PAD (db_pad)) { + GstPad *target_pad = NULL; + + target_pad = gst_ghost_pad_get_target (GST_GHOST_PAD (db_pad)); + done = (target_pad == pad); + if (target_pad) + gst_object_unref (target_pad); + + if (done) { + /* Found our ghost pad */ + GST_DEBUG_OBJECT (decode_bin, "found ghostpad %s:%s for pad %s:%s", + GST_DEBUG_PAD_NAME (db_pad), GST_DEBUG_PAD_NAME (pad)); + break; + } + } + /* Not the right one */ + gst_object_unref (db_pad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pad_it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (pad_it); + + return db_pad; +} + +/* remove all downstream elements starting from the given pad. + * Also make sure to remove the ghostpad we created for the raw + * decoded stream. + */ +static void +remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) +{ + GstIterator *iter; + gboolean done = FALSE; + gpointer item; + GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad)); + + while (GST_OBJECT_PARENT (elem) && + GST_OBJECT_PARENT (elem) != GST_OBJECT (decode_bin)) + elem = GST_ELEMENT (GST_OBJECT_PARENT (elem)); + + if (G_OBJECT_TYPE (elem) == decode_bin->queue_type) { + GST_DEBUG_OBJECT (decode_bin, + "Encountered demuxer output queue while removing element chain"); + decode_bin->queues = g_list_remove (decode_bin->queues, elem); + } + + GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad)); + iter = gst_pad_iterate_internal_links (pad); + if (!iter) + goto no_iter; + + /* remove all elements linked to this pad up to the ghostpad + * that we created for this stream */ + while (!done) { + switch (gst_iterator_next (iter, &item)) { + case GST_ITERATOR_OK:{ + GstPad *pad; + GstPad *ghostpad; + GstPad *peer; + + pad = GST_PAD (item); + GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + ghostpad = get_our_ghost_pad (decode_bin, pad); + if (ghostpad) { + GST_DEBUG_OBJECT (decode_bin, "found our ghost pad %s:%s for %s:%s", + GST_DEBUG_PAD_NAME (ghostpad), GST_DEBUG_PAD_NAME (pad)); + + g_signal_emit (G_OBJECT (decode_bin), + gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, ghostpad); + + gst_element_remove_pad (GST_ELEMENT (decode_bin), ghostpad); + gst_object_unref (ghostpad); + continue; + } else { + GST_DEBUG_OBJECT (decode_bin, "not one of our ghostpads"); + } + + peer = gst_pad_get_peer (pad); + if (peer) { + GstObject *parent = gst_pad_get_parent (peer); + + GST_DEBUG_OBJECT (decode_bin, + "internal pad %s:%s linked to pad %s:%s", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)); + + if (parent) { + GstObject *grandparent = gst_object_get_parent (parent); + + if (grandparent != NULL) { + if (GST_ELEMENT (grandparent) != GST_ELEMENT (decode_bin)) { + GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s parent %s", + GST_DEBUG_PAD_NAME (peer), GST_OBJECT_NAME (grandparent)); + } else { + GST_DEBUG_OBJECT (decode_bin, + "recursing element %s on pad %s:%s", + GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad)); + remove_element_chain (decode_bin, peer); + } + gst_object_unref (grandparent); + } + gst_object_unref (parent); + } + gst_object_unref (peer); + } + gst_object_unref (item); + } + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_ERROR_OBJECT (pad, "Could not iterate over internally linked pads"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem)); + + gst_iterator_free (iter); + +no_iter: + gst_element_set_state (elem, GST_STATE_NULL); + gst_bin_remove (GST_BIN (decode_bin), elem); +} + +/* there are @bytes bytes in @queue, enlarge it + * + * Returns: new max number of bytes in @queue + */ +static guint +queue_enlarge (GstElement * queue, guint bytes, GstDecodeBin * decode_bin) +{ + /* Increase the queue size by 1Mbyte if it is over 1Mb, else double its current limit + */ + if (bytes > 1024 * 1024) + bytes += 1024 * 1024; + else + bytes *= 2; + + GST_DEBUG_OBJECT (decode_bin, + "increasing queue %s max-size-bytes to %d", GST_ELEMENT_NAME (queue), + bytes); + g_object_set (G_OBJECT (queue), "max-size-bytes", bytes, NULL); + + return bytes; +} + +/* this callback is called when our queues fills up or are empty + * We then check the status of all other queues to make sure we + * never have an empty and full queue at the same time since that + * would block dataflow. In the case of a filled queue, we make + * it larger. + */ +static void +queue_underrun_cb (GstElement * queue, GstDecodeBin * decode_bin) +{ + /* FIXME: we don't really do anything here for now. Ideally we should + * see if some of the queues are filled and increase their values + * in that case. + * Note: be very carefull with thread safety here as this underrun + * signal is done from the streaming thread of queue srcpad which + * is different from the pad_added (where we add the queue to the + * list) and the overrun signals that are signalled from the + * demuxer thread. + */ + GST_DEBUG_OBJECT (decode_bin, "got underrun"); +} + +/* Make sure we don't have a full queue and empty queue situation */ +static void +queue_filled_cb (GstElement * queue, GstDecodeBin * decode_bin) +{ + GList *tmp; + gboolean increase = FALSE; + guint bytes; + + /* get current byte level from the queue that is filled */ + g_object_get (G_OBJECT (queue), "current-level-bytes", &bytes, NULL); + GST_DEBUG_OBJECT (decode_bin, "One of the queues is full at %d bytes", bytes); + + /* we do not buffer more than 20Mb */ + if (bytes > (20 * 1024 * 1024)) + goto too_large; + + /* check all other queue to see if one is empty, in that case + * we need to enlarge @queue */ + for (tmp = decode_bin->queues; tmp; tmp = g_list_next (tmp)) { + GstElement *aqueue = GST_ELEMENT (tmp->data); + guint levelbytes = 0; + + if (aqueue != queue) { + g_object_get (G_OBJECT (aqueue), "current-level-bytes", &levelbytes, + NULL); + if (levelbytes == 0) { + /* yup, found an empty queue, we can stop the search and + * need to enlarge the queue */ + increase = TRUE; + break; + } + } + } + + if (increase) { + /* enlarge @queue */ + queue_enlarge (queue, bytes, decode_bin); + } else { + GST_DEBUG_OBJECT (decode_bin, + "Queue is full but other queues are not empty, not doing anything"); + } + return; + + /* errors */ +too_large: + { + GST_WARNING_OBJECT (decode_bin, + "Queue is bigger than 20Mbytes, something else is going wrong"); + return; + } +} + +/* This function will be called when a dynamic pad is created on an element. + * We try to continue autoplugging on this new pad. */ +static void +new_pad (GstElement * element, GstPad * pad, GstDynamic * dynamic) +{ + GstDecodeBin *decode_bin = dynamic->decode_bin; + GstCaps *caps; + gboolean more; + + GST_OBJECT_LOCK (decode_bin); + if (decode_bin->shutting_down) + goto shutting_down1; + GST_OBJECT_UNLOCK (decode_bin); + + GST_STATE_LOCK (decode_bin); + if (decode_bin->shutting_down) + goto shutting_down2; + + /* see if any more pending dynamic connections exist */ + more = gst_decode_bin_is_dynamic (decode_bin); + + caps = gst_pad_get_caps (pad); + close_pad_link (element, pad, caps, decode_bin, more); + if (caps) + gst_caps_unref (caps); + GST_STATE_UNLOCK (decode_bin); + + return; + +shutting_down1: + { + GST_DEBUG_OBJECT (decode_bin, "we are shutting down"); + GST_OBJECT_UNLOCK (decode_bin); + return; + } +shutting_down2: + { + GST_DEBUG_OBJECT (decode_bin, "we are shutting down"); + GST_STATE_UNLOCK (decode_bin); + return; + } +} + +static void +dynamic_remove (GstDynamic * dynamic) +{ + GstDecodeBin *decode_bin = dynamic->decode_bin; + + /* remove the dynamic from the list of dynamics */ + decode_bin->dynamics = g_list_remove (decode_bin->dynamics, dynamic); + dynamic_free (dynamic); + + /* if we have no more dynamic elements, we have no chance of creating + * more pads, so we fire the no_more_pads signal */ + if (decode_bin->dynamics == NULL) { + if (decode_bin->numwaiting == 0) { + GST_DEBUG_OBJECT (decode_bin, + "no more dynamic elements, removing fakesink"); + remove_fakesink (decode_bin); + } + GST_DEBUG_OBJECT (decode_bin, + "no more dynamic elements, signaling no_more_pads"); + gst_element_no_more_pads (GST_ELEMENT (decode_bin)); + } else { + GST_DEBUG_OBJECT (decode_bin, "we have more dynamic elements"); + } +} + +/* this signal is fired when an element signals the no_more_pads signal. + * This means that the element will not generate more dynamic pads and + * we can remove the element from the list of dynamic elements. When we + * have no more dynamic elements in the pipeline, we can fire a no_more_pads + * signal ourselves. */ +static void +no_more_pads (GstElement * element, GstDynamic * dynamic) +{ + GST_DEBUG_OBJECT (dynamic->decode_bin, "no more pads on element %s", + GST_ELEMENT_NAME (element)); + + dynamic_remove (dynamic); +} + +static void +new_caps (GstPad * pad, GParamSpec * unused, GstDynamic * dynamic) +{ + GST_DEBUG_OBJECT (dynamic->decode_bin, "delayed link triggered"); + + new_pad (dynamic->element, pad, dynamic); + + /* assume it worked and remove the dynamic */ + dynamic_remove (dynamic); + + return; +} + +static gboolean +is_our_kid (GstElement * e, GstDecodeBin * decode_bin) +{ + gboolean ret; + GstElement *parent; + + parent = (GstElement *) gst_object_get_parent ((GstObject *) e); + ret = (parent == (GstElement *) decode_bin); + + if (parent) + gst_object_unref ((GstObject *) parent); + + return ret; +} + +static gboolean +elem_is_dynamic (GstElement * element, GstDecodeBin * decode_bin) +{ + GList *pads; + + /* loop over all the padtemplates */ + for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads; + pads = g_list_next (pads)) { + GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data); + const gchar *templ_name; + + /* we are only interested in source pads */ + if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC) + continue; + + templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); + GST_DEBUG_OBJECT (decode_bin, "got a source pad template %s", templ_name); + + /* figure out what kind of pad this is */ + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_SOMETIMES: + { + /* try to get the pad to see if it is already created or + * not */ + GstPad *pad = gst_element_get_static_pad (element, templ_name); + + if (pad) { + GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", + templ_name); + gst_object_unref (pad); + } else { + GST_DEBUG_OBJECT (decode_bin, + "did not get the sometimes pad of template %s", templ_name); + /* we have an element that will create dynamic pads */ + return TRUE; + } + break; + } + default: + /* Don't care about ALWAYS or REQUEST pads */ + break; + } + } + return FALSE; +} + +/* This function will be called when a pad is disconnected for some reason */ +static void +unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin) +{ + GstElement *element, *peer; + + /* inactivate pad */ + gst_pad_set_active (pad, GST_ACTIVATE_NONE); + + peer = gst_pad_get_parent_element (peerpad); + + if (!is_our_kid (peer, decode_bin)) + goto exit; + + GST_DEBUG_OBJECT (decode_bin, "pad %s:%s removal while alive - chained?", + GST_DEBUG_PAD_NAME (pad)); + + /* remove all elements linked to the peerpad */ + remove_element_chain (decode_bin, peerpad); + + /* Re-add as a dynamic element if needed, via close_link */ + element = gst_pad_get_parent_element (pad); + if (element) { + if (elem_is_dynamic (element, decode_bin)) + dynamic_add (element, NULL, decode_bin); + + gst_object_unref (element); + } + +exit: + gst_object_unref (peer); +} + +/* this function inspects the given element and tries to connect something + * on the srcpads. If there are dynamic pads, it sets up a signal handler to + * continue autoplugging when they become available */ +static void +close_link (GstElement * element, GstDecodeBin * decode_bin) +{ + GList *pads; + gboolean dynamic = FALSE; + GList *to_connect = NULL; + gboolean more; + + GST_DEBUG_OBJECT (decode_bin, "closing links with element %s", + GST_ELEMENT_NAME (element)); + + /* loop over all the padtemplates */ + for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads; + pads = g_list_next (pads)) { + GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data); + const gchar *templ_name; + + /* we are only interested in source pads */ + if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC) + continue; + + templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); + GST_DEBUG_OBJECT (decode_bin, "got a source pad template %s", templ_name); + + /* figure out what kind of pad this is */ + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_ALWAYS: + { + /* get the pad that we need to autoplug */ + GstPad *pad = gst_element_get_static_pad (element, templ_name); + + if (pad) { + GST_DEBUG_OBJECT (decode_bin, "got the pad for always template %s", + templ_name); + /* here is the pad, we need to autoplug it */ + to_connect = g_list_prepend (to_connect, pad); + } else { + /* strange, pad is marked as always but it's not + * there. Fix the element */ + GST_WARNING_OBJECT (decode_bin, + "could not get the pad for always template %s", templ_name); + } + break; + } + case GST_PAD_SOMETIMES: + { + /* try to get the pad to see if it is already created or + * not */ + GstPad *pad = gst_element_get_static_pad (element, templ_name); + + if (pad) { + GST_DEBUG_OBJECT (decode_bin, "got the pad for sometimes template %s", + templ_name); + /* the pad is created, we need to autoplug it */ + to_connect = g_list_prepend (to_connect, pad); + } else { + GST_DEBUG_OBJECT (decode_bin, + "did not get the sometimes pad of template %s", templ_name); + /* we have an element that will create dynamic pads */ + dynamic = TRUE; + } + break; + } + case GST_PAD_REQUEST: + /* ignore request pads */ + GST_DEBUG_OBJECT (decode_bin, "ignoring request padtemplate %s", + templ_name); + break; + } + } + if (dynamic) { + GST_DEBUG_OBJECT (decode_bin, "got a dynamic element here"); + /* ok, this element has dynamic pads, set up the signal handlers to be + * notified of them */ + + dynamic_add (element, NULL, decode_bin); + } + + /* Check if this is an element with more than 1 pad. If this element + * has more than 1 pad, we need to be carefull not to signal the + * no_more_pads signal after connecting the first pad. */ + more = g_list_length (to_connect) > 1; + + /* now loop over all the pads we need to connect */ + for (pads = to_connect; pads; pads = g_list_next (pads)) { + GstPad *pad = GST_PAD_CAST (pads->data); + GstCaps *caps; + + /* we have more pads if we have more than 1 pad to connect or + * dynamics. If we have only 1 pad and no dynamics, more will be + * set to FALSE and the no-more-pads signal will be fired. Note + * that this can change after the close_pad_link call. */ + more |= gst_decode_bin_is_dynamic (decode_bin); + + GST_DEBUG_OBJECT (decode_bin, "closing pad link for %s", + GST_OBJECT_NAME (pad)); + + /* continue autoplugging on the pads */ + caps = gst_pad_get_caps (pad); + close_pad_link (element, pad, caps, decode_bin, more); + if (caps) + gst_caps_unref (caps); + + gst_object_unref (pad); + } + g_list_free (to_connect); +} + +/* this is the signal handler for the typefind element have_type signal. + * It tries to continue autoplugging on the typefind src pad */ +static void +type_found (GstElement * typefind, guint probability, GstCaps * caps, + GstDecodeBin * decode_bin) +{ + gboolean dynamic; + GstPad *pad; + + GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps); + + GST_OBJECT_LOCK (decode_bin); + if (decode_bin->shutting_down) + goto shutting_down; + GST_OBJECT_UNLOCK (decode_bin); + + GST_STATE_LOCK (decode_bin); + if (decode_bin->shutting_down) + goto exit; + + /* don't need the typefind anymore if we already found a type, we're not going + * to be able to do anything with it anyway except for generating errors */ + if (decode_bin->have_type) + goto exit; + + decode_bin->have_type = TRUE; + + /* special-case text/plain: we only want to accept it as a raw type if it + * comes from a subtitle parser element or a demuxer, but not if it is the + * type of the entire stream, in which case we just want to error out */ + if (typefind == decode_bin->typefind && + gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) { + gst_element_no_more_pads (GST_ELEMENT (decode_bin)); + /* we can't handle this type of stream */ + GST_ELEMENT_ERROR (decode_bin, STREAM, WRONG_TYPE, + (_("This appears to be a text file")), + ("decodebin cannot decode plain text files")); + goto exit; + } + + /* autoplug the new pad with the caps that the signal gave us. */ + pad = gst_element_get_static_pad (typefind, "src"); + close_pad_link (typefind, pad, caps, decode_bin, FALSE); + gst_object_unref (pad); + + dynamic = gst_decode_bin_is_dynamic (decode_bin); + if (dynamic == FALSE) { + GST_DEBUG_OBJECT (decode_bin, "we have no dynamic elements anymore"); + /* if we have no dynamic elements, we know that no new pads + * will be created and we can signal out no_more_pads signal */ + gst_element_no_more_pads (GST_ELEMENT (decode_bin)); + } else { + /* more dynamic elements exist that could create new pads */ + GST_DEBUG_OBJECT (decode_bin, "we have more dynamic elements"); + } + +exit: + GST_STATE_UNLOCK (decode_bin); + return; + +shutting_down: + { + GST_DEBUG_OBJECT (decode_bin, "we are shutting down"); + GST_OBJECT_UNLOCK (decode_bin); + return; + } +} + +static void +disconnect_unlinked_signals (GstDecodeBin * decode_bin, GstElement * element) +{ + GstIterator *pad_it = NULL; + gboolean done = FALSE; + + pad_it = gst_element_iterate_src_pads (element); + while (!done) { + GstPad *pad = NULL; + + switch (gst_iterator_next (pad_it, (gpointer) & pad)) { + case GST_ITERATOR_OK: + g_signal_handlers_disconnect_by_func (pad, (gpointer) unlinked, + decode_bin); + gst_object_unref (pad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (pad_it); + break; + default: + done = TRUE; + break; + } + } + gst_iterator_free (pad_it); +} + + +static void +cleanup_decodebin (GstDecodeBin * decode_bin) +{ + GstIterator *elem_it = NULL, *gpad_it = NULL; + GstPad *typefind_pad = NULL; + gboolean done = FALSE; + + g_return_if_fail (GST_IS_DECODE_BIN (decode_bin)); + + GST_DEBUG_OBJECT (decode_bin, "cleaning up decodebin"); + + typefind_pad = gst_element_get_static_pad (decode_bin->typefind, "src"); + if (GST_IS_PAD (typefind_pad)) { + g_signal_handlers_block_by_func (typefind_pad, (gpointer) unlinked, + decode_bin); + } + + elem_it = gst_bin_iterate_elements (GST_BIN (decode_bin)); + while (!done) { + GstElement *element = NULL; + + switch (gst_iterator_next (elem_it, (gpointer) & element)) { + case GST_ITERATOR_OK: + if (element != decode_bin->typefind && element != decode_bin->fakesink) { + GST_DEBUG_OBJECT (element, "removing autoplugged element"); + disconnect_unlinked_signals (decode_bin, element); + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN (decode_bin), element); + } + gst_object_unref (element); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (elem_it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (elem_it); + + done = FALSE; + gpad_it = gst_element_iterate_pads (GST_ELEMENT (decode_bin)); + while (!done) { + GstPad *pad = NULL; + + switch (gst_iterator_next (gpad_it, (gpointer) & pad)) { + case GST_ITERATOR_OK: + GST_DEBUG_OBJECT (pad, "inspecting pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + if (GST_IS_GHOST_PAD (pad) && GST_PAD_IS_SRC (pad)) { + GST_DEBUG_OBJECT (pad, "removing ghost pad"); + gst_element_remove_pad (GST_ELEMENT (decode_bin), pad); + } + gst_object_unref (pad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (gpad_it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (gpad_it); + + if (GST_IS_PAD (typefind_pad)) { + g_signal_handlers_unblock_by_func (typefind_pad, (gpointer) unlinked, + decode_bin); + g_signal_handlers_disconnect_by_func (typefind_pad, (gpointer) unlinked, + decode_bin); + gst_object_unref (typefind_pad); + } +} + +static GstStateChangeReturn +gst_decode_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstDecodeBin *decode_bin; + + decode_bin = GST_DECODE_BIN (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + decode_bin->numpads = 0; + decode_bin->numwaiting = 0; + decode_bin->dynamics = NULL; + if (decode_bin->typefind == NULL) + goto missing_typefind; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_OBJECT_LOCK (decode_bin); + decode_bin->shutting_down = FALSE; + decode_bin->have_type = FALSE; + GST_OBJECT_UNLOCK (decode_bin); + + if (!add_fakesink (decode_bin)) + goto missing_fakesink; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_OBJECT_LOCK (decode_bin); + decode_bin->shutting_down = TRUE; + GST_OBJECT_UNLOCK (decode_bin); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + free_dynamics (decode_bin); + free_pad_probes (decode_bin); + cleanup_decodebin (decode_bin); + break; + default: + break; + } + + return ret; +/* ERRORS */ +missing_typefind: + { + gst_element_post_message (element, + gst_missing_element_message_new (element, "typefind")); + GST_ELEMENT_ERROR (element, CORE, MISSING_PLUGIN, (NULL), ("no typefind!")); + return GST_STATE_CHANGE_FAILURE; + } +missing_fakesink: + { + gst_element_post_message (element, + gst_missing_element_message_new (element, "fakesink")); + GST_ELEMENT_ERROR (element, CORE, MISSING_PLUGIN, (NULL), ("no fakesink!")); + return GST_STATE_CHANGE_FAILURE; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin", 0, "decoder bin"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + return gst_element_register (plugin, "decodebin", GST_RANK_NONE, + GST_TYPE_DECODE_BIN); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "decodebin", + "decoder bin", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin2.c b/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin2.c new file mode 100644 index 0000000..31b5ebb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstdecodebin2.c @@ -0,0 +1,3738 @@ +/* GStreamer + * Copyright (C) <2006> Edward Hervey + * Copyright (C) <2009> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-decodebin2 + * + * #GstBin that auto-magically constructs a decoding pipeline using available + * decoders and demuxers via auto-plugging. + * + * decodebin2 is considered stable now and replaces the old #decodebin element. + * #uridecodebin uses decodebin2 internally and is often more convenient to + * use, as it creates a suitable source element as well. + */ + +/* Implementation notes: + * + * The following section describes how decodebin2 works internally. + * + * The first part of decodebin2 is its typefind element, which tries + * to determine the media type of the input stream. If the type is found + * autoplugging starts. + * + * decodebin2 internally organizes the elements it autoplugged into GstDecodeChains + * and GstDecodeGroups. A decode chain is a single chain of decoding, this + * means that if decodebin2 every autoplugs an element with two+ srcpads + * (e.g. a demuxer) this will end the chain and everything following this + * demuxer will be put into decode groups below the chain. Otherwise, + * if an element has a single srcpad that outputs raw data the decode chain + * is ended too and a GstDecodePad is stored and blocked. + * + * A decode group combines a number of chains that are created by a + * demuxer element. All those chains are connected through a multiqueue to + * the demuxer. A new group for the same demuxer is only created if the + * demuxer has signaled no-more-pads, in which case all following pads + * create a new chain in the new group. + * + * This continues until the top-level decode chain is complete. A decode + * chain is complete if it either ends with a blocked endpad, if autoplugging + * stopped because no suitable plugins could be found or if the active group + * is complete. A decode group on the other hand is complete if all child + * chains are complete. + * + * If this happens at some point, all endpads of all active groups are exposed. + * For this decodebin2 adds the endpads, signals no-more-pads and then unblocks + * them. Now playback starts. + * + * If one of the chains that end on a endpad receives EOS decodebin2 checks + * if all chains and groups are drained. In that case everything goes into EOS. + * If there is a chain where the active group is drained but there exist next + * groups, the active group is hidden (endpads are removed) and the next group + * is exposed. This means that in some cases more pads may be created even + * after the initial no-more-pads signal. This happens for example with + * so-called "chained oggs", most commonly found among ogg/vorbis internet + * radio streams. + * + * Note 1: If we're talking about blocked endpads this really means that the + * *target* pads of the endpads are blocked. Pads that are exposed to the outside + * should never ever be blocked! + * + * Note 2: If a group is complete and the parent's chain demuxer adds new pads + * but never signaled no-more-pads this additional pads will be ignored! + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include + +#include "gstplay-marshal.h" +#include "gstplay-enum.h" +#include "gstplayback.h" +#include "gstrawcaps.h" + +/* generic templates */ +static GstStaticPadTemplate decoder_bin_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate decoder_bin_src_template = +GST_STATIC_PAD_TEMPLATE ("src%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (gst_decode_bin_debug); +#define GST_CAT_DEFAULT gst_decode_bin_debug + +typedef struct _GstPendingPad GstPendingPad; +typedef struct _GstDecodeChain GstDecodeChain; +typedef struct _GstDecodeGroup GstDecodeGroup; +typedef struct _GstDecodePad GstDecodePad; +typedef GstGhostPadClass GstDecodePadClass; +typedef struct _GstDecodeBin GstDecodeBin; +typedef struct _GstDecodeBin GstDecodeBin2; +typedef struct _GstDecodeBinClass GstDecodeBinClass; + +#define GST_TYPE_DECODE_BIN (gst_decode_bin_get_type()) +#define GST_DECODE_BIN_CAST(obj) ((GstDecodeBin*)(obj)) +#define GST_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_BIN,GstDecodeBin)) +#define GST_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DECODE_BIN,GstDecodeBinClass)) +#define GST_IS_DECODE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DECODE_BIN)) +#define GST_IS_DECODE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DECODE_BIN)) + +/** + * GstDecodeBin2: + * + * The opaque #DecodeBin2 data structure + */ +struct _GstDecodeBin +{ + GstBin bin; /* we extend GstBin */ + + /* properties */ + GstCaps *caps; /* caps on which to stop decoding */ + gchar *encoding; /* encoding of subtitles */ + gboolean use_buffering; /* configure buffering on multiqueues */ + gint low_percent; + gint high_percent; + guint max_size_bytes; + guint max_size_buffers; + guint64 max_size_time; + gboolean post_stream_topology; + + GstElement *typefind; /* this holds the typefind object */ + + GMutex *expose_lock; /* Protects exposal and removal of groups */ + GstDecodeChain *decode_chain; /* Top level decode chain */ + gint nbpads; /* unique identifier for source pads */ + + GMutex *factories_lock; + guint32 factories_cookie; /* Cookie from last time when factories was updated */ + GList *factories; /* factories we can use for selecting elements */ + + GMutex *subtitle_lock; /* Protects changes to subtitles and encoding */ + GList *subtitles; /* List of elements with subtitle-encoding, + * protected by above mutex! */ + + gboolean have_type; /* if we received the have_type signal */ + guint have_type_id; /* signal id for have-type from typefind */ + + gboolean async_pending; /* async-start has been emited */ + + GMutex *dyn_lock; /* lock protecting pad blocking */ + gboolean shutdown; /* if we are shutting down */ + GList *blocked_pads; /* pads that have set to block */ + + gboolean expose_allstreams; /* Whether to expose unknow type streams or not */ +}; + +struct _GstDecodeBinClass +{ + GstBinClass parent_class; + + /* signal we fire when a new pad has been decoded into raw audio/video */ + void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last); + /* signal we fire when a pad has been removed */ + void (*removed_decoded_pad) (GstElement * element, GstPad * pad); + /* signal fired when we found a pad that we cannot decode */ + void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps); + + /* signal fired to know if we continue trying to decode the given caps */ + gboolean (*autoplug_continue) (GstElement * element, GstPad * pad, + GstCaps * caps); + /* signal fired to get a list of factories to try to autoplug */ + GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad, + GstCaps * caps); + /* signal fired to sort the factories */ + GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad, + GstCaps * caps, GValueArray * factories); + /* signal fired to select from the proposed list of factories */ + GstAutoplugSelectResult (*autoplug_select) (GstElement * element, + GstPad * pad, GstCaps * caps, GstElementFactory * factory); + + /* fired when the last group is drained */ + void (*drained) (GstElement * element); +}; + +/* signals */ +enum +{ + SIGNAL_NEW_DECODED_PAD, + SIGNAL_REMOVED_DECODED_PAD, + SIGNAL_UNKNOWN_TYPE, + SIGNAL_AUTOPLUG_CONTINUE, + SIGNAL_AUTOPLUG_FACTORIES, + SIGNAL_AUTOPLUG_SELECT, + SIGNAL_AUTOPLUG_SORT, + SIGNAL_DRAINED, + LAST_SIGNAL +}; + +/* automatic sizes, while prerolling we buffer up to 2MB, we ignore time + * and buffers in this case. */ +#define AUTO_PREROLL_SIZE_BYTES 2 * 1024 * 1024 +#define AUTO_PREROLL_SIZE_BUFFERS 0 +#define AUTO_PREROLL_SIZE_TIME 0 + +/* whan playing, keep a max of 2MB of data but try to keep the number of buffers + * as low as possible (try to aim for 5 buffers) */ +#define AUTO_PLAY_SIZE_BYTES 2 * 1024 * 1024 +#define AUTO_PLAY_SIZE_BUFFERS 5 +#define AUTO_PLAY_SIZE_TIME 0 + +#define DEFAULT_SUBTITLE_ENCODING NULL +#define DEFAULT_USE_BUFFERING FALSE +#define DEFAULT_LOW_PERCENT 10 +#define DEFAULT_HIGH_PERCENT 99 +/* by default we use the automatic values above */ +#define DEFAULT_MAX_SIZE_BYTES 0 +#define DEFAULT_MAX_SIZE_BUFFERS 0 +#define DEFAULT_MAX_SIZE_TIME 0 +#define DEFAULT_POST_STREAM_TOPOLOGY FALSE +#define DEFAULT_EXPOSE_ALL_STREAMS TRUE + +/* Properties */ +enum +{ + PROP_0, + PROP_CAPS, + PROP_SUBTITLE_ENCODING, + PROP_SINK_CAPS, + PROP_USE_BUFFERING, + PROP_LOW_PERCENT, + PROP_HIGH_PERCENT, + PROP_MAX_SIZE_BYTES, + PROP_MAX_SIZE_BUFFERS, + PROP_MAX_SIZE_TIME, + PROP_POST_STREAM_TOPOLOGY, + PROP_EXPOSE_ALL_STREAMS, + PROP_LAST +}; + +static GstBinClass *parent_class; +static guint gst_decode_bin_signals[LAST_SIGNAL] = { 0 }; + +static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS); + +static void do_async_start (GstDecodeBin * dbin); +static void do_async_done (GstDecodeBin * dbin); + +static void type_found (GstElement * typefind, guint probability, + GstCaps * caps, GstDecodeBin * decode_bin); + +static void decodebin_set_queue_size (GstDecodeBin * dbin, + GstElement * multiqueue, gboolean preroll); + +static gboolean gst_decode_bin_autoplug_continue (GstElement * element, + GstPad * pad, GstCaps * caps); +static GValueArray *gst_decode_bin_autoplug_factories (GstElement * + element, GstPad * pad, GstCaps * caps); +static GValueArray *gst_decode_bin_autoplug_sort (GstElement * element, + GstPad * pad, GstCaps * caps, GValueArray * factories); +static GstAutoplugSelectResult gst_decode_bin_autoplug_select (GstElement * + element, GstPad * pad, GstCaps * caps, GstElementFactory * factory); + +static void gst_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps); +static GstCaps *gst_decode_bin_get_caps (GstDecodeBin * dbin); +static void caps_notify_cb (GstPad * pad, GParamSpec * unused, + GstDecodeChain * chain); + +static GstPad *find_sink_pad (GstElement * element); +static GstStateChangeReturn gst_decode_bin_change_state (GstElement * element, + GstStateChange transition); + +#define EXPOSE_LOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "expose locking from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->expose_lock); \ + GST_LOG_OBJECT (dbin, \ + "expose locked from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define EXPOSE_UNLOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "expose unlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->expose_lock); \ +} G_STMT_END + +#define DYN_LOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "dynlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->dyn_lock); \ + GST_LOG_OBJECT (dbin, \ + "dynlocked from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define DYN_UNLOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "dynunlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->dyn_lock); \ +} G_STMT_END + +#define SUBTITLE_LOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "subtitle locking from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (GST_DECODE_BIN_CAST(dbin)->subtitle_lock); \ + GST_LOG_OBJECT (dbin, \ + "subtitle lock from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define SUBTITLE_UNLOCK(dbin) G_STMT_START { \ + GST_LOG_OBJECT (dbin, \ + "subtitle unlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (GST_DECODE_BIN_CAST(dbin)->subtitle_lock); \ +} G_STMT_END + +struct _GstPendingPad +{ + GstPad *pad; + GstDecodeChain *chain; + gulong event_probe_id; +}; + +/* GstDecodeGroup + * + * Streams belonging to the same group/chain of a media file + * + * When changing something here lock the parent chain! + */ +struct _GstDecodeGroup +{ + GstDecodeBin *dbin; + GstDecodeChain *parent; + + GstElement *multiqueue; /* Used for linking all child chains */ + gulong overrunsig; /* the overrun signal for multiqueue */ + + gboolean overrun; /* TRUE if the multiqueue signaled overrun. This + * means that we should really expose the group */ + + gboolean no_more_pads; /* TRUE if the demuxer signaled no-more-pads */ + gboolean drained; /* TRUE if the all children are drained */ + + GList *children; /* List of GstDecodeChains in this group */ + + GList *reqpads; /* List of RequestPads for multiqueue, there is + * exactly one RequestPad per child chain */ +}; + +struct _GstDecodeChain +{ + GstDecodeGroup *parent; + GstDecodeBin *dbin; + + GMutex *lock; /* Protects this chain and its groups */ + + GstPad *pad; /* srcpad that caused creation of this chain */ + + gboolean demuxer; /* TRUE if elements->data is a demuxer */ + GList *elements; /* All elements in this group, first + is the latest and most downstream element */ + + /* Note: there are only groups if the last element of this chain + * is a demuxer, otherwise the chain will end with an endpad. + * The other way around this means, that endpad only exists if this + * chain doesn't end with a demuxer! */ + + GstDecodeGroup *active_group; /* Currently active group */ + GList *next_groups; /* head is newest group, tail is next group. + a new group will be created only if the head + group had no-more-pads. If it's only exposed + all new pads will be ignored! */ + GList *pending_pads; /* Pads that have no fixed caps yet */ + + GstDecodePad *endpad; /* Pad of this chain that could be exposed */ + gboolean deadend; /* This chain is incomplete and can't be completed, + e.g. no suitable decoder could be found + e.g. stream got EOS without buffers + */ + GstCaps *endcaps; /* Caps that were used when linking to the endpad + or that resulted in the deadend + */ + + /* FIXME: This should be done directly via a thread! */ + GList *old_groups; /* Groups that should be freed later */ +}; + +static void gst_decode_chain_free (GstDecodeChain * chain); +static GstDecodeChain *gst_decode_chain_new (GstDecodeBin * dbin, + GstDecodeGroup * group, GstPad * pad); +static void gst_decode_group_hide (GstDecodeGroup * group); +static void gst_decode_group_free (GstDecodeGroup * group); +static GstDecodeGroup *gst_decode_group_new (GstDecodeBin * dbin, + GstDecodeChain * chain); +static gboolean gst_decode_chain_is_complete (GstDecodeChain * chain); +static void gst_decode_chain_handle_eos (GstDecodeChain * chain); +static gboolean gst_decode_chain_expose (GstDecodeChain * chain, + GList ** endpads, gboolean * missing_plugin); +static gboolean gst_decode_chain_is_drained (GstDecodeChain * chain); +static gboolean gst_decode_group_is_complete (GstDecodeGroup * group); +static GstPad *gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, + GstPad * pad); +static gboolean gst_decode_group_is_drained (GstDecodeGroup * group); + +static gboolean gst_decode_bin_expose (GstDecodeBin * dbin); + +#define CHAIN_MUTEX_LOCK(chain) G_STMT_START { \ + GST_LOG_OBJECT (chain->dbin, \ + "locking chain %p from thread %p", \ + chain, g_thread_self ()); \ + g_mutex_lock (chain->lock); \ + GST_LOG_OBJECT (chain->dbin, \ + "locked chain %p from thread %p", \ + chain, g_thread_self ()); \ +} G_STMT_END + +#define CHAIN_MUTEX_UNLOCK(chain) G_STMT_START { \ + GST_LOG_OBJECT (chain->dbin, \ + "unlocking chain %p from thread %p", \ + chain, g_thread_self ()); \ + g_mutex_unlock (chain->lock); \ +} G_STMT_END + +/* GstDecodePad + * + * GstPad private used for source pads of chains + */ +struct _GstDecodePad +{ + GstGhostPad parent; + GstDecodeBin *dbin; + GstDecodeChain *chain; + + gboolean blocked; /* the *target* pad is blocked */ + gboolean exposed; /* the pad is exposed */ + gboolean drained; /* an EOS has been seen on the pad */ +}; + +GType gst_decode_pad_get_type (void); +G_DEFINE_TYPE (GstDecodePad, gst_decode_pad, GST_TYPE_GHOST_PAD); +#define GST_TYPE_DECODE_PAD (gst_decode_pad_get_type ()) +#define GST_DECODE_PAD(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DECODE_PAD,GstDecodePad)) + +static GstDecodePad *gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, + GstDecodeChain * chain); +static void gst_decode_pad_activate (GstDecodePad * dpad, + GstDecodeChain * chain); +static void gst_decode_pad_unblock (GstDecodePad * dpad); +static void gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked); + +static void gst_pending_pad_free (GstPendingPad * ppad); +static gboolean pad_event_cb (GstPad * pad, GstEvent * event, gpointer data); + +/******************************** + * Standard GObject boilerplate * + ********************************/ + +static void gst_decode_bin_class_init (GstDecodeBinClass * klass); +static void gst_decode_bin_init (GstDecodeBin * decode_bin); +static void gst_decode_bin_dispose (GObject * object); +static void gst_decode_bin_finalize (GObject * object); + +static GType +gst_decode_bin_get_type (void) +{ + static GType gst_decode_bin_type = 0; + + if (!gst_decode_bin_type) { + static const GTypeInfo gst_decode_bin_info = { + sizeof (GstDecodeBinClass), + NULL, + NULL, + (GClassInitFunc) gst_decode_bin_class_init, + NULL, + NULL, + sizeof (GstDecodeBin), + 0, + (GInstanceInitFunc) gst_decode_bin_init, + NULL + }; + + gst_decode_bin_type = + g_type_register_static (GST_TYPE_BIN, "GstDecodeBin2", + &gst_decode_bin_info, 0); + } + + return gst_decode_bin_type; +} + +static gboolean +_gst_boolean_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gboolean myboolean; + + myboolean = g_value_get_boolean (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boolean (return_accu, myboolean); + + /* stop emission if FALSE */ + return myboolean; +} + +/* we collect the first result */ +static gboolean +_gst_array_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boxed (return_accu, array); + + return FALSE; +} + +static gboolean +_gst_select_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + GstAutoplugSelectResult res; + + res = g_value_get_enum (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_enum (return_accu, res); + + return FALSE; +} + +static gboolean +_gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boxed (return_accu, array); + + if (array != NULL) + return FALSE; + + return TRUE; +} + +static void +gst_decode_bin_class_init (GstDecodeBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->dispose = gst_decode_bin_dispose; + gobject_klass->finalize = gst_decode_bin_finalize; + gobject_klass->set_property = gst_decode_bin_set_property; + gobject_klass->get_property = gst_decode_bin_get_property; + + /** + * GstDecodeBin2::new-decoded-pad: + * @bin: The decodebin. + * @pad: The newly created pad. + * @islast: #TRUE if this is the last pad to be added. Deprecated. + * + * This signal gets emitted as soon as a new pad of the same type as one of + * the valid 'raw' types is added. + * + * Deprecated: Use GstElement::pad-added instead of this signal. + * + */ + gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD] = + g_signal_new ("new-decoded-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDecodeBinClass, new_decoded_pad), NULL, NULL, + gst_play_marshal_VOID__OBJECT_BOOLEAN, G_TYPE_NONE, 2, GST_TYPE_PAD, + G_TYPE_BOOLEAN); + + /** + * GstDecodeBin2::removed-decoded-pad: + * @bin: The decodebin. + * @pad: The pad that was removed. + * + * This signal is emitted when a 'final' caps pad has been removed. + * + * Deprecated: Use GstElement::pad-removed instead of this signal. + * + */ + gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD] = + g_signal_new ("removed-decoded-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstDecodeBinClass, removed_decoded_pad), NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_PAD); + + /** + * GstDecodeBin2::unknown-type: + * @bin: The decodebin. + * @pad: The new pad containing caps that cannot be resolved to a 'final' + * stream type. + * @caps: The #GstCaps of the pad that cannot be resolved. + * + * This signal is emitted when a pad for which there is no further possible + * decoding is added to the decodebin. + */ + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = + g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), + NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); + + /** + * GstDecodeBin2::autoplug-continue: + * @bin: The decodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps found. + * + * This signal is emitted whenever decodebin2 finds a new stream. It is + * emitted before looking for any elements that can handle that stream. + * + * + * Invocation of signal handlers stops after the first signal handler + * returns #FALSE. Signal handlers are invoked in the order they were + * connected in. + * + * + * Returns: #TRUE if you wish decodebin2 to look for elements that can + * handle the given @caps. If #FALSE, those caps will be considered as + * final and the pad will be exposed as such (see 'new-decoded-pad' + * signal). + */ + gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] = + g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_continue), + _gst_boolean_accumulator, NULL, gst_play_marshal_BOOLEAN__OBJECT_BOXED, + G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, GST_TYPE_CAPS); + + /** + * GstDecodeBin2::autoplug-factories: + * @bin: The decodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps found. + * + * This function is emited when an array of possible factories for @caps on + * @pad is needed. Decodebin2 will by default return an array with all + * compatible factories, sorted by rank. + * + * If this function returns NULL, @pad will be exposed as a final caps. + * + * If this function returns an empty array, the pad will be considered as + * having an unhandled type media type. + * + * + * Only the signal handler that is connected first will ever by invoked. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: a #GValueArray* with a list of factories to try. The factories are + * by default tried in the returned order or based on the index returned by + * "autoplug-select". + */ + gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] = + g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, + autoplug_factories), _gst_array_accumulator, NULL, + gst_play_marshal_BOXED__OBJECT_BOXED, G_TYPE_VALUE_ARRAY, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); + + /** + * GstDecodeBin2::autoplug-sort: + * @bin: The decodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps. + * @factories: A #GValueArray of possible #GstElementFactory to use. + * + * Once decodebin2 has found the possible #GstElementFactory objects to try + * for @caps on @pad, this signal is emited. The purpose of the signal is for + * the application to perform additional sorting or filtering on the element + * factory array. + * + * The callee should copy and modify @factories or return #NULL if the + * order should not change. + * + * + * Invocation of signal handlers stops after one signal handler has + * returned something else than #NULL. Signal handlers are invoked in + * the order they were connected in. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: A new sorted array of #GstElementFactory objects. + */ + gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] = + g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_sort), + _gst_array_hasvalue_accumulator, NULL, + gst_play_marshal_BOXED__OBJECT_BOXED_BOXED, G_TYPE_VALUE_ARRAY, 3, + GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY); + + /** + * GstDecodeBin2::autoplug-select: + * @bin: The decodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps. + * @factory: A #GstElementFactory to use. + * + * This signal is emitted once decodebin2 has found all the possible + * #GstElementFactory that can be used to handle the given @caps. For each of + * those factories, this signal is emited. + * + * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum + * value indicating what decodebin2 should do next. + * + * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from + * @factory. + * + * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging + * any element to it. + * + * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the + * next factory. + * + * + * Only the signal handler that is connected first will ever by invoked. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required + * operation. the default handler will always return + * #GST_AUTOPLUG_SELECT_TRY. + */ + gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = + g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, autoplug_select), + _gst_select_accumulator, NULL, + gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT, + GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, + GST_TYPE_ELEMENT_FACTORY); + + /** + * GstDecodeBin2::drained + * @bin: The decodebin + * + * This signal is emitted once decodebin2 has finished decoding all the data. + * + * Since: 0.10.16 + */ + gst_decode_bin_signals[SIGNAL_DRAINED] = + g_signal_new ("drained", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, drained), + NULL, NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + g_object_class_install_property (gobject_klass, PROP_CAPS, + g_param_spec_boxed ("caps", "Caps", "The caps on which to stop decoding.", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_SINK_CAPS, + g_param_spec_boxed ("sink-caps", "Sink Caps", + "The caps of the input data. (NULL = use typefind element)", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDecodeBin2::use-buffering + * + * Activate buffering in decodebin2. This will instruct the multiqueues behind + * decoders to emit BUFFERING messages. + + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_USE_BUFFERING, + g_param_spec_boolean ("use-buffering", "Use Buffering", + "Emit GST_MESSAGE_BUFFERING based on low-/high-percent thresholds", + DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDecodebin2:low-percent + * + * Low threshold percent for buffering to start. + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_LOW_PERCENT, + g_param_spec_int ("low-percent", "Low percent", + "Low threshold for buffering to start", 0, 100, + DEFAULT_LOW_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstDecodebin2:high-percent + * + * High threshold percent for buffering to finish. + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_HIGH_PERCENT, + g_param_spec_int ("high-percent", "High percent", + "High threshold for buffering to finish", 0, 100, + DEFAULT_HIGH_PERCENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDecodebin2:max-size-bytes + * + * Max amount amount of bytes in the queue (0=automatic). + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_BYTES, + g_param_spec_uint ("max-size-bytes", "Max. size (bytes)", + "Max. amount of bytes in the queue (0=automatic)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BYTES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstDecodebin2:max-size-buffers + * + * Max amount amount of buffers in the queue (0=automatic). + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_BUFFERS, + g_param_spec_uint ("max-size-buffers", "Max. size (buffers)", + "Max. number of buffers in the queue (0=automatic)", + 0, G_MAXUINT, DEFAULT_MAX_SIZE_BUFFERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstDecodebin2:max-size-time + * + * Max amount amount of time in the queue (in ns, 0=automatic). + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_MAX_SIZE_TIME, + g_param_spec_uint64 ("max-size-time", "Max. size (ns)", + "Max. amount of data in the queue (in ns, 0=automatic)", + 0, G_MAXUINT64, + DEFAULT_MAX_SIZE_TIME, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDecodeBin2::post-stream-topology + * + * Post stream-topology messages on the bus every time the topology changes. + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_klass, PROP_POST_STREAM_TOPOLOGY, + g_param_spec_boolean ("post-stream-topology", "Post Stream Topology", + "Post stream-topology messages", + DEFAULT_POST_STREAM_TOPOLOGY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstDecodeBin2::expose-all-streams + * + * Expose streams of unknown type. + * + * If set to %FALSE, then only the streams that can be decoded to the final + * caps (see 'caps' property) will have a pad exposed. Streams that do not + * match those caps but could have been decoded will not have decoder plugged + * in internally and will not have a pad exposed. + * + * Since: 0.10.30 + */ + g_object_class_install_property (gobject_klass, PROP_EXPOSE_ALL_STREAMS, + g_param_spec_boolean ("expose-all-streams", "Expose All Streams", + "Expose all streams, including those of unknown type or that don't match the 'caps' property", + DEFAULT_EXPOSE_ALL_STREAMS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + + + klass->autoplug_continue = + GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_continue); + klass->autoplug_factories = + GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_factories); + klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_sort); + klass->autoplug_select = GST_DEBUG_FUNCPTR (gst_decode_bin_autoplug_select); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&decoder_bin_sink_template)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&decoder_bin_src_template)); + + gst_element_class_set_details_simple (gstelement_klass, + "Decoder Bin", "Generic/Bin/Decoder", + "Autoplug and decode to raw media", + "Edward Hervey , " + "Sebastian Dröge "); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_decode_bin_change_state); +} + +/* Must be called with factories lock! */ +static void +gst_decode_bin_update_factories_list (GstDecodeBin * dbin) +{ + if (!dbin->factories + || dbin->factories_cookie != + gst_default_registry_get_feature_list_cookie ()) { + if (dbin->factories) + gst_plugin_feature_list_free (dbin->factories); + dbin->factories = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL); + dbin->factories_cookie = gst_default_registry_get_feature_list_cookie (); + } +} + +static void +gst_decode_bin_init (GstDecodeBin * decode_bin) +{ + /* first filter out the interesting element factories */ + decode_bin->factories_lock = g_mutex_new (); + + /* we create the typefind element only once */ + decode_bin->typefind = gst_element_factory_make ("typefind", "typefind"); + if (!decode_bin->typefind) { + g_warning ("can't find typefind element, decodebin will not work"); + } else { + GstPad *pad; + GstPad *gpad; + GstPadTemplate *pad_tmpl; + + /* add the typefind element */ + if (!gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind)) { + g_warning ("Could not add typefind element, decodebin will not work"); + gst_object_unref (decode_bin->typefind); + decode_bin->typefind = NULL; + } + + /* get the sinkpad */ + pad = gst_element_get_static_pad (decode_bin->typefind, "sink"); + + /* get the pad template */ + pad_tmpl = gst_static_pad_template_get (&decoder_bin_sink_template); + + /* ghost the sink pad to ourself */ + gpad = gst_ghost_pad_new_from_template ("sink", pad, pad_tmpl); + gst_pad_set_active (gpad, TRUE); + gst_element_add_pad (GST_ELEMENT (decode_bin), gpad); + + gst_object_unref (pad_tmpl); + gst_object_unref (pad); + + /* connect a signal to find out when the typefind element found + * a type */ + decode_bin->have_type_id = + g_signal_connect (G_OBJECT (decode_bin->typefind), "have-type", + G_CALLBACK (type_found), decode_bin); + } + + decode_bin->expose_lock = g_mutex_new (); + decode_bin->decode_chain = NULL; + + decode_bin->dyn_lock = g_mutex_new (); + decode_bin->shutdown = FALSE; + decode_bin->blocked_pads = NULL; + + decode_bin->subtitle_lock = g_mutex_new (); + + decode_bin->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING); + decode_bin->caps = gst_static_caps_get (&default_raw_caps); + decode_bin->use_buffering = DEFAULT_USE_BUFFERING; + decode_bin->low_percent = DEFAULT_LOW_PERCENT; + decode_bin->high_percent = DEFAULT_HIGH_PERCENT; + + decode_bin->max_size_bytes = DEFAULT_MAX_SIZE_BYTES; + decode_bin->max_size_buffers = DEFAULT_MAX_SIZE_BUFFERS; + decode_bin->max_size_time = DEFAULT_MAX_SIZE_TIME; + + decode_bin->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS; +} + +static void +gst_decode_bin_dispose (GObject * object) +{ + GstDecodeBin *decode_bin; + + decode_bin = GST_DECODE_BIN (object); + + if (decode_bin->factories) + gst_plugin_feature_list_free (decode_bin->factories); + decode_bin->factories = NULL; + + if (decode_bin->decode_chain) + gst_decode_chain_free (decode_bin->decode_chain); + decode_bin->decode_chain = NULL; + + if (decode_bin->caps) + gst_caps_unref (decode_bin->caps); + decode_bin->caps = NULL; + + g_free (decode_bin->encoding); + decode_bin->encoding = NULL; + + g_list_free (decode_bin->subtitles); + decode_bin->subtitles = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_decode_bin_finalize (GObject * object) +{ + GstDecodeBin *decode_bin; + + decode_bin = GST_DECODE_BIN (object); + + if (decode_bin->expose_lock) { + g_mutex_free (decode_bin->expose_lock); + decode_bin->expose_lock = NULL; + } + + if (decode_bin->dyn_lock) { + g_mutex_free (decode_bin->dyn_lock); + decode_bin->dyn_lock = NULL; + } + + if (decode_bin->subtitle_lock) { + g_mutex_free (decode_bin->subtitle_lock); + decode_bin->subtitle_lock = NULL; + } + + if (decode_bin->factories_lock) { + g_mutex_free (decode_bin->factories_lock); + decode_bin->factories_lock = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* _set_caps + * Changes the caps on which decodebin will stop decoding. + * Will unref the previously set one. The refcount of the given caps will be + * increased. + * @caps can be NULL. + * + * MT-safe + */ +static void +gst_decode_bin_set_caps (GstDecodeBin * dbin, GstCaps * caps) +{ + GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); + + GST_OBJECT_LOCK (dbin); + gst_caps_replace (&dbin->caps, caps); + GST_OBJECT_UNLOCK (dbin); +} + +/* _get_caps + * Returns the currently configured caps on which decodebin will stop decoding. + * The returned caps (if not NULL), will have its refcount incremented. + * + * MT-safe + */ +static GstCaps * +gst_decode_bin_get_caps (GstDecodeBin * dbin) +{ + GstCaps *caps; + + GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); + + GST_OBJECT_LOCK (dbin); + caps = dbin->caps; + if (caps) + gst_caps_ref (caps); + GST_OBJECT_UNLOCK (dbin); + + return caps; +} + +static void +gst_decode_bin_set_sink_caps (GstDecodeBin * dbin, GstCaps * caps) +{ + GST_DEBUG_OBJECT (dbin, "Setting new caps: %" GST_PTR_FORMAT, caps); + + g_object_set (dbin->typefind, "force-caps", caps, NULL); +} + +static GstCaps * +gst_decode_bin_get_sink_caps (GstDecodeBin * dbin) +{ + GstCaps *caps; + + GST_DEBUG_OBJECT (dbin, "Getting currently set caps"); + + g_object_get (dbin->typefind, "force-caps", &caps, NULL); + + return caps; +} + +static void +gst_decode_bin_set_subs_encoding (GstDecodeBin * dbin, const gchar * encoding) +{ + GList *walk; + + GST_DEBUG_OBJECT (dbin, "Setting new encoding: %s", GST_STR_NULL (encoding)); + + SUBTITLE_LOCK (dbin); + g_free (dbin->encoding); + dbin->encoding = g_strdup (encoding); + + /* set the subtitle encoding on all added elements */ + for (walk = dbin->subtitles; walk; walk = g_list_next (walk)) { + g_object_set (G_OBJECT (walk->data), "subtitle-encoding", dbin->encoding, + NULL); + } + SUBTITLE_UNLOCK (dbin); +} + +static gchar * +gst_decode_bin_get_subs_encoding (GstDecodeBin * dbin) +{ + gchar *encoding; + + GST_DEBUG_OBJECT (dbin, "Getting currently set encoding"); + + SUBTITLE_LOCK (dbin); + encoding = g_strdup (dbin->encoding); + SUBTITLE_UNLOCK (dbin); + + return encoding; +} + +static void +gst_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDecodeBin *dbin; + + dbin = GST_DECODE_BIN (object); + + switch (prop_id) { + case PROP_CAPS: + gst_decode_bin_set_caps (dbin, g_value_get_boxed (value)); + break; + case PROP_SUBTITLE_ENCODING: + gst_decode_bin_set_subs_encoding (dbin, g_value_get_string (value)); + break; + case PROP_SINK_CAPS: + gst_decode_bin_set_sink_caps (dbin, g_value_get_boxed (value)); + break; + case PROP_USE_BUFFERING: + dbin->use_buffering = g_value_get_boolean (value); + break; + case PROP_LOW_PERCENT: + dbin->low_percent = g_value_get_int (value); + break; + case PROP_HIGH_PERCENT: + dbin->high_percent = g_value_get_int (value); + break; + case PROP_MAX_SIZE_BYTES: + dbin->max_size_bytes = g_value_get_uint (value); + break; + case PROP_MAX_SIZE_BUFFERS: + dbin->max_size_buffers = g_value_get_uint (value); + break; + case PROP_MAX_SIZE_TIME: + dbin->max_size_time = g_value_get_uint64 (value); + break; + case PROP_POST_STREAM_TOPOLOGY: + dbin->post_stream_topology = g_value_get_boolean (value); + break; + case PROP_EXPOSE_ALL_STREAMS: + dbin->expose_allstreams = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDecodeBin *dbin; + + dbin = GST_DECODE_BIN (object); + switch (prop_id) { + case PROP_CAPS: + g_value_take_boxed (value, gst_decode_bin_get_caps (dbin)); + break; + case PROP_SUBTITLE_ENCODING: + g_value_take_string (value, gst_decode_bin_get_subs_encoding (dbin)); + break; + case PROP_SINK_CAPS: + g_value_take_boxed (value, gst_decode_bin_get_sink_caps (dbin)); + break; + case PROP_USE_BUFFERING: + g_value_set_boolean (value, dbin->use_buffering); + break; + case PROP_LOW_PERCENT: + g_value_set_int (value, dbin->low_percent); + break; + case PROP_HIGH_PERCENT: + g_value_set_int (value, dbin->high_percent); + break; + case PROP_MAX_SIZE_BYTES: + g_value_set_uint (value, dbin->max_size_bytes); + break; + case PROP_MAX_SIZE_BUFFERS: + g_value_set_uint (value, dbin->max_size_buffers); + break; + case PROP_MAX_SIZE_TIME: + g_value_set_uint64 (value, dbin->max_size_time); + break; + case PROP_POST_STREAM_TOPOLOGY: + g_value_set_boolean (value, dbin->post_stream_topology); + break; + case PROP_EXPOSE_ALL_STREAMS: + g_value_set_boolean (value, dbin->expose_allstreams); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/***** + * Default autoplug signal handlers + *****/ +static gboolean +gst_decode_bin_autoplug_continue (GstElement * element, GstPad * pad, + GstCaps * caps) +{ + GST_DEBUG_OBJECT (element, "autoplug-continue returns TRUE"); + + /* by default we always continue */ + return TRUE; +} + +static GValueArray * +gst_decode_bin_autoplug_factories (GstElement * element, GstPad * pad, + GstCaps * caps) +{ + GList *list, *tmp; + GValueArray *result; + GstDecodeBin *dbin = GST_DECODE_BIN_CAST (element); + + GST_DEBUG_OBJECT (element, "finding factories"); + + /* return all compatible factories for caps */ + g_mutex_lock (dbin->factories_lock); + gst_decode_bin_update_factories_list (dbin); + list = + gst_element_factory_list_filter (dbin->factories, caps, GST_PAD_SINK, + FALSE); + g_mutex_unlock (dbin->factories_lock); + + result = g_value_array_new (g_list_length (list)); + for (tmp = list; tmp; tmp = tmp->next) { + GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data); + GValue val = { 0, }; + + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_append (result, &val); + g_value_unset (&val); + } + gst_plugin_feature_list_free (list); + + GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result); + + return result; +} + +static GValueArray * +gst_decode_bin_autoplug_sort (GstElement * element, GstPad * pad, + GstCaps * caps, GValueArray * factories) +{ + return NULL; +} + +static GstAutoplugSelectResult +gst_decode_bin_autoplug_select (GstElement * element, GstPad * pad, + GstCaps * caps, GstElementFactory * factory) +{ + GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY"); + + /* Try factory. */ + return GST_AUTOPLUG_SELECT_TRY; +} + +/******** + * Discovery methods + *****/ + +static gboolean are_final_caps (GstDecodeBin * dbin, GstCaps * caps); +static gboolean is_demuxer_element (GstElement * srcelement); + +static gboolean connect_pad (GstDecodeBin * dbin, GstElement * src, + GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GValueArray * factories, + GstDecodeChain * chain); +static gboolean connect_element (GstDecodeBin * dbin, GstElement * element, + GstDecodeChain * chain); +static void expose_pad (GstDecodeBin * dbin, GstElement * src, + GstDecodePad * dpad, GstPad * pad, GstCaps * caps, GstDecodeChain * chain); + +static void pad_added_cb (GstElement * element, GstPad * pad, + GstDecodeChain * chain); +static void pad_removed_cb (GstElement * element, GstPad * pad, + GstDecodeChain * chain); +static void no_more_pads_cb (GstElement * element, GstDecodeChain * chain); + +static GstDecodeGroup *gst_decode_chain_get_current_group (GstDecodeChain * + chain); + +/* called when a new pad is discovered. It will perform some basic actions + * before trying to link something to it. + * + * - Check the caps, don't do anything when there are no caps or when they have + * no good type. + * - signal AUTOPLUG_CONTINUE to check if we need to continue autoplugging this + * pad. + * - if the caps are non-fixed, setup a handler to continue autoplugging when + * the caps become fixed (connect to notify::caps). + * - get list of factories to autoplug. + * - continue autoplugging to one of the factories. + */ +static void +analyze_new_pad (GstDecodeBin * dbin, GstElement * src, GstPad * pad, + GstCaps * caps, GstDecodeChain * chain) +{ + gboolean apcontinue = TRUE; + GValueArray *factories = NULL, *result = NULL; + GstDecodePad *dpad; + + GST_DEBUG_OBJECT (dbin, "Pad %s:%s caps:%" GST_PTR_FORMAT, + GST_DEBUG_PAD_NAME (pad), caps); + + if (chain->elements && src != chain->elements->data) { + GST_ERROR_OBJECT (dbin, "New pad from not the last element in this chain"); + return; + } + + if (chain->endpad) { + GST_ERROR_OBJECT (dbin, "New pad in a chain that is already complete"); + return; + } + + if (chain->demuxer) { + GstDecodeGroup *group; + GstDecodeChain *oldchain = chain; + + /* we are adding a new pad for a demuxer (see is_demuxer_element(), + * start a new chain for it */ + CHAIN_MUTEX_LOCK (oldchain); + group = gst_decode_chain_get_current_group (chain); + if (group) { + chain = gst_decode_chain_new (dbin, group, pad); + group->children = g_list_prepend (group->children, chain); + } + CHAIN_MUTEX_UNLOCK (oldchain); + if (!group) { + GST_WARNING_OBJECT (dbin, "No current group"); + return; + } + } + + if ((caps == NULL) || gst_caps_is_empty (caps)) + goto unknown_type; + + if (gst_caps_is_any (caps)) + goto any_caps; + + dpad = gst_decode_pad_new (dbin, pad, chain); + + /* 1. Emit 'autoplug-continue' the result will tell us if this pads needs + * further autoplugging. */ + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, caps, + &apcontinue); + + /* 1.a if autoplug-continue is FALSE or caps is a raw format, goto pad_is_final */ + if ((!apcontinue) || are_final_caps (dbin, caps)) + goto expose_pad; + + /* 1.b when the caps are not fixed yet, we can't be sure what element to + * connect. We delay autoplugging until the caps are fixed */ + if (!gst_caps_is_fixed (caps)) + goto non_fixed; + + /* 1.c else get the factories and if there's no compatible factory goto + * unknown_type */ + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, dpad, caps, + &factories); + + /* NULL means that we can expose the pad */ + if (factories == NULL) + goto expose_pad; + + /* if the array is empty, we have a type for which we have no decoder */ + if (factories->n_values == 0) { + if (!dbin->expose_allstreams) { + GstCaps *raw = gst_static_caps_get (&default_raw_caps); + + /* If the caps are raw, this just means we don't want to expose them */ + if (gst_caps_can_intersect (raw, caps)) { + gst_caps_unref (raw); + gst_object_unref (dpad); + goto discarded_type; + } + gst_caps_unref (raw); + } + + /* if not we have a unhandled type with no compatible factories */ + g_value_array_free (factories); + gst_object_unref (dpad); + goto unknown_type; + } + + /* 1.d sort some more. */ + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, dpad, caps, factories, + &result); + if (result) { + g_value_array_free (factories); + factories = result; + } + + /* At this point we have a potential decoder, but we might not need it + * if it doesn't match the output caps */ + if (!dbin->expose_allstreams) { + guint i; + const GList *tmps; + gboolean dontuse = FALSE; + + GST_DEBUG ("Checking if we can abort early"); + + /* 1.e Do an early check to see if the candidates are potential decoders, but + * due to the fact that they decode to a mediatype that is not final we don't + * need them */ + + for (i = 0; i < factories->n_values && !dontuse; i++) { + GstElementFactory *factory = + g_value_get_object (g_value_array_get_nth (factories, 0)); + GstCaps *tcaps; + + /* We are only interested in skipping decoders */ + if (strstr (gst_element_factory_get_klass (factory), "Decoder")) { + + GST_DEBUG ("Trying factory %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + + /* Check the source pad template caps to see if they match raw caps but don't match + * our final caps*/ + for (tmps = gst_element_factory_get_static_pad_templates (factory); + tmps && !dontuse; tmps = tmps->next) { + GstStaticPadTemplate *st = (GstStaticPadTemplate *) tmps->data; + if (st->direction != GST_PAD_SRC) + continue; + tcaps = gst_static_pad_template_get_caps (st); + + apcontinue = TRUE; + + /* Emit autoplug-continue to see if the caps are considered to be raw caps */ + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, dpad, tcaps, + &apcontinue); + + /* If autoplug-continue returns TRUE and the caps are not final, don't use them */ + if (apcontinue && !are_final_caps (dbin, tcaps)) + dontuse = TRUE; + gst_caps_unref (tcaps); + } + } + } + + if (dontuse) { + gst_object_unref (dpad); + goto discarded_type; + } + } + + /* 1.f else continue autoplugging something from the list. */ + GST_LOG_OBJECT (pad, "Let's continue discovery on this pad"); + connect_pad (dbin, src, dpad, pad, caps, factories, chain); + + gst_object_unref (dpad); + g_value_array_free (factories); + + return; + +expose_pad: + { + GST_LOG_OBJECT (dbin, "Pad is final. autoplug-continue:%d", apcontinue); + expose_pad (dbin, src, dpad, pad, caps, chain); + gst_object_unref (dpad); + return; + } + +discarded_type: + { + GST_LOG_OBJECT (pad, "Known type, but discarded because not final caps"); + chain->deadend = TRUE; + chain->endcaps = gst_caps_ref (caps); + + /* Try to expose anything */ + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + gst_decode_bin_expose (dbin); + } + EXPOSE_UNLOCK (dbin); + do_async_done (dbin); + + return; + } + +unknown_type: + { + GST_LOG_OBJECT (pad, "Unknown type, posting message and firing signal"); + + chain->deadend = TRUE; + chain->endcaps = gst_caps_ref (caps); + + gst_element_post_message (GST_ELEMENT_CAST (dbin), + gst_missing_decoder_message_new (GST_ELEMENT_CAST (dbin), caps)); + + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); + + /* Try to expose anything */ + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + gst_decode_bin_expose (dbin); + } + EXPOSE_UNLOCK (dbin); + + if (src == dbin->typefind) { + gchar *desc; + + if (caps && !gst_caps_is_empty (caps)) { + desc = gst_pb_utils_get_decoder_description (caps); + GST_ELEMENT_ERROR (dbin, STREAM, CODEC_NOT_FOUND, + (_("A %s plugin is required to play this stream, " + "but not installed."), desc), + ("No decoder to handle media type '%s'", + gst_structure_get_name (gst_caps_get_structure (caps, 0)))); + g_free (desc); + } else { + GST_ELEMENT_ERROR (dbin, STREAM, TYPE_NOT_FOUND, + (_("Could not determine type of stream")), + ("Stream caps %" GST_PTR_FORMAT, caps)); + } + do_async_done (dbin); + } + return; + } +non_fixed: + { + GST_DEBUG_OBJECT (pad, "pad has non-fixed caps delay autoplugging"); + gst_object_unref (dpad); + goto setup_caps_delay; + } +any_caps: + { + GST_WARNING_OBJECT (pad, + "pad has ANY caps, not able to autoplug to anything"); + goto setup_caps_delay; + } +setup_caps_delay: + { + GstPendingPad *ppad; + + /* connect to caps notification */ + CHAIN_MUTEX_LOCK (chain); + GST_LOG_OBJECT (dbin, "Chain %p has now %d dynamic pads", chain, + g_list_length (chain->pending_pads)); + ppad = g_slice_new0 (GstPendingPad); + ppad->pad = gst_object_ref (pad); + ppad->chain = chain; + ppad->event_probe_id = + gst_pad_add_event_probe (pad, (GCallback) pad_event_cb, ppad); + chain->pending_pads = g_list_prepend (chain->pending_pads, ppad); + CHAIN_MUTEX_UNLOCK (chain); + g_signal_connect (G_OBJECT (pad), "notify::caps", + G_CALLBACK (caps_notify_cb), chain); + return; + } +} + + +/* connect_pad: + * + * Try to connect the given pad to an element created from one of the factories, + * and recursively. + * + * Note that dpad is ghosting pad, and so pad is linked; be sure to unset dpad's + * target before trying to link pad. + * + * Returns TRUE if an element was properly created and linked + */ +static gboolean +connect_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, + GstPad * pad, GstCaps * caps, GValueArray * factories, + GstDecodeChain * chain) +{ + gboolean res = FALSE; + GstPad *mqpad = NULL; + gboolean is_demuxer = chain->parent && !chain->elements; /* First pad after the demuxer */ + + g_return_val_if_fail (factories != NULL, FALSE); + g_return_val_if_fail (factories->n_values > 0, FALSE); + + GST_DEBUG_OBJECT (dbin, "pad %s:%s , chain:%p", + GST_DEBUG_PAD_NAME (pad), chain); + + /* 1. is element demuxer or parser */ + if (is_demuxer) { + GST_LOG_OBJECT (src, + "is a demuxer, connecting the pad through multiqueue '%s'", + GST_OBJECT_NAME (chain->parent->multiqueue)); + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); + if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad))) + goto beach; + src = chain->parent->multiqueue; + pad = mqpad; + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); + } + + /* 2. Try to create an element and link to it */ + while (factories->n_values > 0) { + GstAutoplugSelectResult ret; + GstElementFactory *factory; + GstElement *element; + GstPad *sinkpad; + gboolean subtitle; + + /* Set dpad target to pad again, it might've been unset + * below but we came back here because something failed + */ + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); + + /* take first factory */ + factory = g_value_get_object (g_value_array_get_nth (factories, 0)); + /* Remove selected factory from the list. */ + g_value_array_remove (factories, 0); + + /* If the factory is for a parser we first check if the factory + * was already used for the current chain. If it was used already + * we would otherwise create an infinite loop here because the + * parser apparently accepts its own output as input. + * This is only done for parsers because it's perfectly valid + * to have other element classes after each other because a + * parser is the only one that does not change the data. A + * valid example for this would be multiple id3demux in a row. + */ + if (strstr (gst_element_factory_get_klass (factory), "Parser")) { + gboolean skip = FALSE; + GList *l; + + CHAIN_MUTEX_LOCK (chain); + for (l = chain->elements; l; l = l->next) { + GstElement *otherelement = GST_ELEMENT_CAST (l->data); + + if (gst_element_get_factory (otherelement) == factory) { + skip = TRUE; + break; + } + } + CHAIN_MUTEX_UNLOCK (chain); + if (skip) { + GST_DEBUG_OBJECT (dbin, + "Skipping factory '%s' because it was already used in this chain", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory))); + continue; + } + } + + /* emit autoplug-select to see what we should do with it. */ + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], + 0, dpad, caps, factory, &ret); + + switch (ret) { + case GST_AUTOPLUG_SELECT_TRY: + GST_DEBUG_OBJECT (dbin, "autoplug select requested try"); + break; + case GST_AUTOPLUG_SELECT_EXPOSE: + GST_DEBUG_OBJECT (dbin, "autoplug select requested expose"); + /* expose the pad, we don't have the source element */ + expose_pad (dbin, src, dpad, pad, caps, chain); + res = TRUE; + goto beach; + case GST_AUTOPLUG_SELECT_SKIP: + GST_DEBUG_OBJECT (dbin, "autoplug select requested skip"); + continue; + default: + GST_WARNING_OBJECT (dbin, "autoplug select returned unhandled %d", ret); + break; + } + + /* 2.0. Unlink pad */ + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); + + /* 2.1. Try to create an element */ + if ((element = gst_element_factory_create (factory, NULL)) == NULL) { + GST_WARNING_OBJECT (dbin, "Could not create an element from %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + continue; + } + + /* ... activate it ... We do this before adding it to the bin so that we + * don't accidentally make it post error messages that will stop + * everything. */ + if ((gst_element_set_state (element, + GST_STATE_READY)) == GST_STATE_CHANGE_FAILURE) { + GST_WARNING_OBJECT (dbin, "Couldn't set %s to READY", + GST_ELEMENT_NAME (element)); + gst_object_unref (element); + continue; + } + + /* 2.3. Find its sink pad, this should work after activating it. */ + if (!(sinkpad = find_sink_pad (element))) { + GST_WARNING_OBJECT (dbin, "Element %s doesn't have a sink pad", + GST_ELEMENT_NAME (element)); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + continue; + } + + /* 2.4 add it ... */ + if (!(gst_bin_add (GST_BIN_CAST (dbin), element))) { + GST_WARNING_OBJECT (dbin, "Couldn't add %s to the bin", + GST_ELEMENT_NAME (element)); + gst_object_unref (sinkpad); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + continue; + } + + /* 2.5 ...and try to link */ + if ((gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) { + GST_WARNING_OBJECT (dbin, "Link failed on pad %s:%s", + GST_DEBUG_PAD_NAME (sinkpad)); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (sinkpad); + gst_bin_remove (GST_BIN (dbin), element); + continue; + } + gst_object_unref (sinkpad); + GST_LOG_OBJECT (dbin, "linked on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + CHAIN_MUTEX_LOCK (chain); + chain->elements = + g_list_prepend (chain->elements, gst_object_ref (element)); + chain->demuxer = is_demuxer_element (element); + CHAIN_MUTEX_UNLOCK (chain); + + /* link this element further */ + connect_element (dbin, element, chain); + + /* try to configure the subtitle encoding property when we can */ + if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "subtitle-encoding")) { + SUBTITLE_LOCK (dbin); + GST_DEBUG_OBJECT (dbin, + "setting subtitle-encoding=%s to element", dbin->encoding); + g_object_set (G_OBJECT (element), "subtitle-encoding", dbin->encoding, + NULL); + SUBTITLE_UNLOCK (dbin); + subtitle = TRUE; + } else + subtitle = FALSE; + + /* Bring the element to the state of the parent */ + if ((gst_element_set_state (element, + GST_STATE_PAUSED)) == GST_STATE_CHANGE_FAILURE) { + GstElement *tmp = NULL; + + GST_WARNING_OBJECT (dbin, "Couldn't set %s to PAUSED", + GST_ELEMENT_NAME (element)); + + /* Remove all elements in this chain that were just added. No + * other thread could've added elements in the meantime */ + CHAIN_MUTEX_LOCK (chain); + do { + GList *l; + + tmp = chain->elements->data; + + /* Disconnect any signal handlers that might be connected + * in connect_element() or analyze_pad() */ + g_signal_handlers_disconnect_by_func (tmp, pad_added_cb, chain); + g_signal_handlers_disconnect_by_func (tmp, pad_removed_cb, chain); + g_signal_handlers_disconnect_by_func (tmp, no_more_pads_cb, chain); + + for (l = chain->pending_pads; l;) { + GstPendingPad *pp = l->data; + GList *n; + + if (GST_PAD_PARENT (pp->pad) != tmp) { + l = l->next; + continue; + } + + g_signal_handlers_disconnect_by_func (pp->pad, caps_notify_cb, chain); + gst_pad_remove_event_probe (pp->pad, pp->event_probe_id); + gst_object_unref (pp->pad); + g_slice_free (GstPendingPad, pp); + + /* Remove element from the list, update list head and go to the + * next element in the list */ + n = l->next; + chain->pending_pads = g_list_delete_link (chain->pending_pads, l); + l = n; + } + + gst_bin_remove (GST_BIN (dbin), tmp); + gst_element_set_state (tmp, GST_STATE_NULL); + + gst_object_unref (tmp); + chain->elements = g_list_delete_link (chain->elements, chain->elements); + } while (tmp != element); + CHAIN_MUTEX_UNLOCK (chain); + + continue; + } + if (subtitle) { + SUBTITLE_LOCK (dbin); + /* we added the element now, add it to the list of subtitle-encoding + * elements when we can set the property */ + dbin->subtitles = g_list_prepend (dbin->subtitles, element); + SUBTITLE_UNLOCK (dbin); + } + + res = TRUE; + break; + } + +beach: + if (mqpad) + gst_object_unref (mqpad); + + return res; +} + +static GstCaps * +get_pad_caps (GstPad * pad) +{ + GstCaps *caps; + + /* first check the pad caps, if this is set, we are positively sure it is + * fixed and exactly what the element will produce. */ + GST_OBJECT_LOCK (pad); + if ((caps = GST_PAD_CAPS (pad))) + gst_caps_ref (caps); + GST_OBJECT_UNLOCK (pad); + + /* then use the getcaps function if we don't have caps. These caps might not + * be fixed in some cases, in which case analyze_new_pad will set up a + * notify::caps signal to continue autoplugging. */ + if (caps == NULL) + caps = gst_pad_get_caps_reffed (pad); + + return caps; +} + +static gboolean +connect_element (GstDecodeBin * dbin, GstElement * element, + GstDecodeChain * chain) +{ + GList *pads; + gboolean res = TRUE; + gboolean dynamic = FALSE; + GList *to_connect = NULL; + + GST_DEBUG_OBJECT (dbin, "Attempting to connect element %s [chain:%p] further", + GST_ELEMENT_NAME (element), chain); + + /* 1. Loop over pad templates, grabbing existing pads along the way */ + for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads; + pads = g_list_next (pads)) { + GstPadTemplate *templ = GST_PAD_TEMPLATE (pads->data); + const gchar *templ_name; + + /* we are only interested in source pads */ + if (GST_PAD_TEMPLATE_DIRECTION (templ) != GST_PAD_SRC) + continue; + + templ_name = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); + GST_DEBUG_OBJECT (dbin, "got a source pad template %s", templ_name); + + /* figure out what kind of pad this is */ + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_ALWAYS: + { + /* get the pad that we need to autoplug */ + GstPad *pad = gst_element_get_static_pad (element, templ_name); + + if (pad) { + GST_DEBUG_OBJECT (dbin, "got the pad for always template %s", + templ_name); + /* here is the pad, we need to autoplug it */ + to_connect = g_list_prepend (to_connect, pad); + } else { + /* strange, pad is marked as always but it's not + * there. Fix the element */ + GST_WARNING_OBJECT (dbin, + "could not get the pad for always template %s", templ_name); + } + break; + } + case GST_PAD_SOMETIMES: + { + /* try to get the pad to see if it is already created or + * not */ + GstPad *pad = gst_element_get_static_pad (element, templ_name); + + if (pad) { + GST_DEBUG_OBJECT (dbin, "got the pad for sometimes template %s", + templ_name); + /* the pad is created, we need to autoplug it */ + to_connect = g_list_prepend (to_connect, pad); + } else { + GST_DEBUG_OBJECT (dbin, + "did not get the sometimes pad of template %s", templ_name); + /* we have an element that will create dynamic pads */ + dynamic = TRUE; + } + break; + } + case GST_PAD_REQUEST: + /* ignore request pads */ + GST_DEBUG_OBJECT (dbin, "ignoring request padtemplate %s", templ_name); + break; + } + } + + /* 2. if there are more potential pads, connect to relevant signals */ + if (dynamic) { + GST_LOG_OBJECT (dbin, "Adding signals to element %s in chain %p", + GST_ELEMENT_NAME (element), chain); + g_signal_connect (G_OBJECT (element), "pad-added", + G_CALLBACK (pad_added_cb), chain); + g_signal_connect (G_OBJECT (element), "pad-removed", + G_CALLBACK (pad_removed_cb), chain); + g_signal_connect (G_OBJECT (element), "no-more-pads", + G_CALLBACK (no_more_pads_cb), chain); + } + + /* 3. for every available pad, connect it */ + for (pads = to_connect; pads; pads = g_list_next (pads)) { + GstPad *pad = GST_PAD_CAST (pads->data); + GstCaps *caps; + + caps = get_pad_caps (pad); + analyze_new_pad (dbin, element, pad, caps, chain); + if (caps) + gst_caps_unref (caps); + + gst_object_unref (pad); + } + g_list_free (to_connect); + + return res; +} + +/* expose_pad: + * + * Expose the given pad on the chain as a decoded pad. + */ +static void +expose_pad (GstDecodeBin * dbin, GstElement * src, GstDecodePad * dpad, + GstPad * pad, GstCaps * caps, GstDecodeChain * chain) +{ + GstPad *mqpad = NULL; + + GST_DEBUG_OBJECT (dbin, "pad %s:%s, chain:%p", + GST_DEBUG_PAD_NAME (pad), chain); + + /* If this is the first pad for this chain, there are no other elements + * and the source element is not the multiqueue we must link through the + * multiqueue. + * + * This is the case if a demuxer directly exposed a raw pad. + */ + if (chain->parent && !chain->elements && src != chain->parent->multiqueue) { + GST_LOG_OBJECT (src, "connecting the pad through multiqueue"); + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), NULL); + if (!(mqpad = gst_decode_group_control_demuxer_pad (chain->parent, pad))) + goto beach; + pad = mqpad; + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); + } + + gst_decode_pad_activate (dpad, chain); + chain->endpad = gst_object_ref (dpad); + chain->endcaps = gst_caps_ref (caps); + + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + gst_decode_bin_expose (dbin); + } + EXPOSE_UNLOCK (dbin); + + if (mqpad) + gst_object_unref (mqpad); + +beach: + return; +} + +static void +type_found (GstElement * typefind, guint probability, + GstCaps * caps, GstDecodeBin * decode_bin) +{ + GstPad *pad, *sink_pad; + + GST_DEBUG_OBJECT (decode_bin, "typefind found caps %" GST_PTR_FORMAT, caps); + + /* If the typefinder (but not something else) finds text/plain - i.e. that's + * the top-level type of the file - then error out. + */ + if (gst_structure_has_name (gst_caps_get_structure (caps, 0), "text/plain")) { + GST_ELEMENT_ERROR (decode_bin, STREAM, WRONG_TYPE, + (_("This appears to be a text file")), + ("decodebin2 cannot decode plain text files")); + goto exit; + } + + /* FIXME: we can only deal with one type, we don't yet support dynamically changing + * caps from the typefind element */ + if (decode_bin->have_type || decode_bin->decode_chain) + goto exit; + + decode_bin->have_type = TRUE; + + pad = gst_element_get_static_pad (typefind, "src"); + sink_pad = gst_element_get_static_pad (typefind, "sink"); + + /* need some lock here to prevent race with shutdown state change + * which might yank away e.g. decode_chain while building stuff here. + * In typical cases, STREAM_LOCK is held and handles that, it need not + * be held (if called from a proxied setcaps), so grab it anyway */ + GST_PAD_STREAM_LOCK (sink_pad); + decode_bin->decode_chain = gst_decode_chain_new (decode_bin, NULL, pad); + analyze_new_pad (decode_bin, typefind, pad, caps, decode_bin->decode_chain); + GST_PAD_STREAM_UNLOCK (sink_pad); + + gst_object_unref (sink_pad); + gst_object_unref (pad); + +exit: + return; +} + +static gboolean +pad_event_cb (GstPad * pad, GstEvent * event, gpointer data) +{ + GstPendingPad *ppad = (GstPendingPad *) data; + GstDecodeChain *chain = ppad->chain; + GstDecodeBin *dbin = chain->dbin; + + g_assert (ppad); + g_assert (chain); + g_assert (dbin); + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_DEBUG_OBJECT (dbin, "Received EOS on a non final pad, this stream " + "ended too early"); + chain->deadend = TRUE; + /* we don't set the endcaps because NULL endcaps means early EOS */ + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) + gst_decode_bin_expose (dbin); + EXPOSE_UNLOCK (dbin); + break; + default: + break; + } + return TRUE; +} + +static void +pad_added_cb (GstElement * element, GstPad * pad, GstDecodeChain * chain) +{ + GstCaps *caps; + GstDecodeBin *dbin; + + dbin = chain->dbin; + + GST_DEBUG_OBJECT (pad, "pad added, chain:%p", chain); + + caps = get_pad_caps (pad); + analyze_new_pad (dbin, element, pad, caps, chain); + if (caps) + gst_caps_unref (caps); + + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + GST_LOG_OBJECT (dbin, + "That was the last dynamic object, now attempting to expose the group"); + if (!gst_decode_bin_expose (dbin)) + GST_WARNING_OBJECT (dbin, "Couldn't expose group"); + } + EXPOSE_UNLOCK (dbin); +} + +static void +pad_removed_cb (GstElement * element, GstPad * pad, GstDecodeChain * chain) +{ + GList *l; + + GST_LOG_OBJECT (pad, "pad removed, chain:%p", chain); + + /* In fact, we don't have to do anything here, the active group will be + * removed when the group's multiqueue is drained */ + CHAIN_MUTEX_LOCK (chain); + for (l = chain->pending_pads; l; l = l->next) { + GstPendingPad *ppad = l->data; + GstPad *opad = ppad->pad; + + if (pad == opad) { + g_signal_handlers_disconnect_by_func (pad, caps_notify_cb, chain); + gst_pending_pad_free (ppad); + chain->pending_pads = g_list_delete_link (chain->pending_pads, l); + break; + } + } + CHAIN_MUTEX_UNLOCK (chain); +} + +static void +no_more_pads_cb (GstElement * element, GstDecodeChain * chain) +{ + GstDecodeGroup *group = NULL; + + GST_LOG_OBJECT (element, "got no more pads"); + + CHAIN_MUTEX_LOCK (chain); + if (!chain->elements || (GstElement *) chain->elements->data != element) { + GST_LOG_OBJECT (chain->dbin, "no-more-pads from old chain element '%s'", + GST_OBJECT_NAME (element)); + CHAIN_MUTEX_UNLOCK (chain); + return; + } else if (!chain->demuxer) { + GST_LOG_OBJECT (chain->dbin, "no-more-pads from a non-demuxer element '%s'", + GST_OBJECT_NAME (element)); + CHAIN_MUTEX_UNLOCK (chain); + return; + } + + /* when we received no_more_pads, we can complete the pads of the chain */ + if (!chain->next_groups && chain->active_group) { + group = chain->active_group; + } else if (chain->next_groups) { + group = chain->next_groups->data; + } + if (!group) { + GST_ERROR_OBJECT (chain->dbin, "can't find group for element"); + CHAIN_MUTEX_UNLOCK (chain); + return; + } + + GST_DEBUG_OBJECT (element, "Setting group %p to complete", group); + + group->no_more_pads = TRUE; + /* this group has prerolled enough to not need more pads, + * we can probably set its buffering state to playing now */ + GST_DEBUG_OBJECT (group->dbin, "Setting group %p multiqueue to " + "'playing' buffering mode", group); + decodebin_set_queue_size (group->dbin, group->multiqueue, FALSE); + CHAIN_MUTEX_UNLOCK (chain); + + EXPOSE_LOCK (chain->dbin); + if (gst_decode_chain_is_complete (chain->dbin->decode_chain)) { + gst_decode_bin_expose (chain->dbin); + } + EXPOSE_UNLOCK (chain->dbin); +} + +static void +caps_notify_cb (GstPad * pad, GParamSpec * unused, GstDecodeChain * chain) +{ + GstElement *element; + GList *l; + + GST_LOG_OBJECT (pad, "Notified caps for pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + /* Disconnect this; if we still need it, we'll reconnect to this in + * analyze_new_pad */ + g_signal_handlers_disconnect_by_func (pad, caps_notify_cb, chain); + + element = GST_ELEMENT_CAST (gst_pad_get_parent (pad)); + + CHAIN_MUTEX_LOCK (chain); + for (l = chain->pending_pads; l; l = l->next) { + GstPendingPad *ppad = l->data; + if (ppad->pad == pad) { + gst_pending_pad_free (ppad); + chain->pending_pads = g_list_delete_link (chain->pending_pads, l); + break; + } + } + CHAIN_MUTEX_UNLOCK (chain); + + pad_added_cb (element, pad, chain); + + gst_object_unref (element); +} + +/* Decide whether an element is a demuxer based on the + * klass and number/type of src pad templates it has */ +static gboolean +is_demuxer_element (GstElement * srcelement) +{ + GstElementFactory *srcfactory; + GstElementClass *elemclass; + GList *walk; + const gchar *klass; + gint potential_src_pads = 0; + + srcfactory = gst_element_get_factory (srcelement); + klass = gst_element_factory_get_klass (srcfactory); + + /* Can't be a demuxer unless it has Demux in the klass name */ + if (!strstr (klass, "Demux")) + return FALSE; + + /* Walk the src pad templates and count how many the element + * might produce */ + elemclass = GST_ELEMENT_GET_CLASS (srcelement); + + walk = gst_element_class_get_pad_template_list (elemclass); + while (walk != NULL) { + GstPadTemplate *templ; + + templ = (GstPadTemplate *) walk->data; + if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { + switch (GST_PAD_TEMPLATE_PRESENCE (templ)) { + case GST_PAD_ALWAYS: + case GST_PAD_SOMETIMES: + if (strstr (GST_PAD_TEMPLATE_NAME_TEMPLATE (templ), "%")) + potential_src_pads += 2; /* Might make multiple pads */ + else + potential_src_pads += 1; + break; + case GST_PAD_REQUEST: + potential_src_pads += 2; + break; + } + } + walk = g_list_next (walk); + } + + if (potential_src_pads < 2) + return FALSE; + + return TRUE; +} + +/* Returns TRUE if the caps are compatible with the caps specified in the 'caps' + * property (which by default are the raw caps) + * + * The decodebin_lock should be taken ! + */ +static gboolean +are_final_caps (GstDecodeBin * dbin, GstCaps * caps) +{ + gboolean res; + + GST_LOG_OBJECT (dbin, "Checking with caps %" GST_PTR_FORMAT, caps); + + /* lock for getting the caps */ + GST_OBJECT_LOCK (dbin); + res = gst_caps_can_intersect (dbin->caps, caps); + GST_OBJECT_UNLOCK (dbin); + + GST_LOG_OBJECT (dbin, "Caps are %sfinal caps", res ? "" : "not "); + + return res; +} + +/**** + * GstDecodeChain functions + ****/ + +/* gst_decode_chain_get_current_group: + * + * Returns the current group of this chain, to which + * new chains should be attached or NULL if the last + * group didn't have no-more-pads. + * + * Not MT-safe: Call with parent chain lock! + */ +static GstDecodeGroup * +gst_decode_chain_get_current_group (GstDecodeChain * chain) +{ + GstDecodeGroup *group; + + if (!chain->next_groups && chain->active_group + && chain->active_group->overrun && !chain->active_group->no_more_pads) { + GST_WARNING_OBJECT (chain->dbin, + "Currently active group %p is exposed" + " and wants to add a new pad without having signaled no-more-pads", + chain->active_group); + return NULL; + } + + if (chain->next_groups && (group = chain->next_groups->data) && group->overrun + && !group->no_more_pads) { + GST_WARNING_OBJECT (chain->dbin, + "Currently newest pending group %p " + "had overflow but didn't signal no-more-pads", group); + return NULL; + } + + /* Now we know that we can really return something useful */ + if (!chain->active_group) { + chain->active_group = group = gst_decode_group_new (chain->dbin, chain); + } else if (!chain->active_group->overrun + && !chain->active_group->no_more_pads) { + group = chain->active_group; + } else if (chain->next_groups && (group = chain->next_groups->data) + && !group->overrun && !group->no_more_pads) { + /* group = chain->next_groups->data */ + } else { + group = gst_decode_group_new (chain->dbin, chain); + chain->next_groups = g_list_prepend (chain->next_groups, group); + } + + return group; +} + +static void gst_decode_group_free_internal (GstDecodeGroup * group, + gboolean hide); + +static void +gst_decode_chain_free_internal (GstDecodeChain * chain, gboolean hide) +{ + GList *l; + + CHAIN_MUTEX_LOCK (chain); + + GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hiding" : "Freeing"), + chain); + + if (chain->active_group) { + gst_decode_group_free_internal (chain->active_group, hide); + if (!hide) + chain->active_group = NULL; + } + + for (l = chain->next_groups; l; l = l->next) { + gst_decode_group_free_internal ((GstDecodeGroup *) l->data, hide); + if (!hide) + l->data = NULL; + } + if (!hide) { + g_list_free (chain->next_groups); + chain->next_groups = NULL; + } + + if (!hide) { + for (l = chain->old_groups; l; l = l->next) { + GstDecodeGroup *group = l->data; + + gst_decode_group_free (group); + } + g_list_free (chain->old_groups); + chain->old_groups = NULL; + } + + for (l = chain->pending_pads; l; l = l->next) { + GstPendingPad *ppad = l->data; + GstPad *pad = ppad->pad; + + g_signal_handlers_disconnect_by_func (pad, caps_notify_cb, chain); + gst_pending_pad_free (ppad); + l->data = NULL; + } + g_list_free (chain->pending_pads); + chain->pending_pads = NULL; + + for (l = chain->elements; l; l = l->next) { + GstElement *element = GST_ELEMENT (l->data); + + g_signal_handlers_disconnect_by_func (element, pad_added_cb, chain); + g_signal_handlers_disconnect_by_func (element, pad_removed_cb, chain); + g_signal_handlers_disconnect_by_func (element, no_more_pads_cb, chain); + + if (GST_OBJECT_PARENT (element) == GST_OBJECT_CAST (chain->dbin)) + gst_bin_remove (GST_BIN_CAST (chain->dbin), element); + if (!hide) { + gst_element_set_state (element, GST_STATE_NULL); + } + + SUBTITLE_LOCK (chain->dbin); + /* remove possible subtitle element */ + chain->dbin->subtitles = g_list_remove (chain->dbin->subtitles, element); + SUBTITLE_UNLOCK (chain->dbin); + + if (!hide) { + gst_object_unref (element); + l->data = NULL; + } + } + if (!hide) { + g_list_free (chain->elements); + chain->elements = NULL; + } + + if (chain->endpad) { + if (chain->endpad->exposed) { + gst_element_remove_pad (GST_ELEMENT_CAST (chain->dbin), + GST_PAD_CAST (chain->endpad)); + g_signal_emit (G_OBJECT (chain->dbin), + gst_decode_bin_signals[SIGNAL_REMOVED_DECODED_PAD], 0, chain->endpad); + } + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->endpad), NULL); + chain->endpad->exposed = FALSE; + if (!hide) { + gst_object_unref (chain->endpad); + chain->endpad = NULL; + } + } + + if (chain->pad) { + gst_object_unref (chain->pad); + chain->pad = NULL; + } + + if (chain->endcaps) { + gst_caps_unref (chain->endcaps); + chain->endcaps = NULL; + } + + GST_DEBUG_OBJECT (chain->dbin, "%s chain %p", (hide ? "Hidden" : "Freed"), + chain); + CHAIN_MUTEX_UNLOCK (chain); + if (!hide) { + g_mutex_free (chain->lock); + g_slice_free (GstDecodeChain, chain); + } +} + +/* gst_decode_chain_free: + * + * Completely frees and removes the chain and all + * child groups from decodebin2. + * + * MT-safe, don't hold the chain lock or any child chain's lock + * when calling this! + */ +static void +gst_decode_chain_free (GstDecodeChain * chain) +{ + gst_decode_chain_free_internal (chain, FALSE); +} + +/* gst_decode_chain_new: + * + * Creates a new decode chain and initializes it. + * + * It's up to the caller to add it to the list of child chains of + * a group! + */ +static GstDecodeChain * +gst_decode_chain_new (GstDecodeBin * dbin, GstDecodeGroup * parent, + GstPad * pad) +{ + GstDecodeChain *chain = g_slice_new0 (GstDecodeChain); + + GST_DEBUG_OBJECT (dbin, "Creating new chain %p with parent group %p", chain, + parent); + + chain->dbin = dbin; + chain->parent = parent; + chain->lock = g_mutex_new (); + chain->pad = gst_object_ref (pad); + + return chain; +} + +/**** + * GstDecodeGroup functions + ****/ + +/* The overrun callback is used to expose groups that have not yet had their + * no_more_pads called while the (large) multiqueue overflowed. When this + * happens we must assume that the no_more_pads will not arrive anymore and we + * must expose the pads that we have. + */ +static void +multi_queue_overrun_cb (GstElement * queue, GstDecodeGroup * group) +{ + GstDecodeBin *dbin; + + dbin = group->dbin; + + GST_LOG_OBJECT (dbin, "multiqueue '%s' (%p) is full", GST_OBJECT_NAME (queue), + queue); + + group->overrun = TRUE; + + /* FIXME: We should make sure that everything gets exposed now + * even if child chains are not complete because the will never + * be complete! Ignore any non-complete chains when exposing + * and never expose them later + */ + + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + if (!gst_decode_bin_expose (dbin)) + GST_WARNING_OBJECT (dbin, "Couldn't expose group"); + } + EXPOSE_UNLOCK (group->dbin); +} + +static void +gst_decode_group_free_internal (GstDecodeGroup * group, gboolean hide) +{ + GList *l; + + GST_DEBUG_OBJECT (group->dbin, "%s group %p", (hide ? "Hiding" : "Freeing"), + group); + for (l = group->children; l; l = l->next) { + GstDecodeChain *chain = (GstDecodeChain *) l->data; + + gst_decode_chain_free_internal (chain, hide); + if (!hide) + l->data = NULL; + } + if (!hide) { + g_list_free (group->children); + group->children = NULL; + } + + if (!hide) { + for (l = group->reqpads; l; l = l->next) { + GstPad *pad = l->data; + + gst_element_release_request_pad (group->multiqueue, pad); + gst_object_unref (pad); + l->data = NULL; + } + g_list_free (group->reqpads); + group->reqpads = NULL; + } + + if (group->multiqueue) { + if (group->overrunsig) { + g_signal_handler_disconnect (group->multiqueue, group->overrunsig); + group->overrunsig = 0; + } + + if (GST_OBJECT_PARENT (group->multiqueue) == GST_OBJECT_CAST (group->dbin)) + gst_bin_remove (GST_BIN_CAST (group->dbin), group->multiqueue); + if (!hide) { + gst_element_set_state (group->multiqueue, GST_STATE_NULL); + gst_object_unref (group->multiqueue); + group->multiqueue = NULL; + } + } + + GST_DEBUG_OBJECT (group->dbin, "%s group %p", (hide ? "Hided" : "Freed"), + group); + if (!hide) + g_slice_free (GstDecodeGroup, group); +} + +/* gst_decode_group_free: + * + * Completely frees and removes the decode group and all + * it's children. + * + * Never call this from any streaming thread! + * + * Not MT-safe, call with parent's chain lock! + */ +static void +gst_decode_group_free (GstDecodeGroup * group) +{ + gst_decode_group_free_internal (group, FALSE); +} + +/* gst_decode_group_hide: + * + * Hide the decode group only, this means that + * all child endpads are removed from decodebin2 + * and all signals are unconnected. + * + * No element is set to NULL state and completely + * unrefed here. + * + * Can be called from streaming threads. + * + * Not MT-safe, call with parent's chain lock! + */ +static void +gst_decode_group_hide (GstDecodeGroup * group) +{ + gst_decode_group_free_internal (group, TRUE); +} + +/* configure queue sizes, this depends on the buffering method and if we are + * playing or prerolling. */ +static void +decodebin_set_queue_size (GstDecodeBin * dbin, GstElement * multiqueue, + gboolean preroll) +{ + guint max_bytes, max_buffers; + guint64 max_time; + + if (preroll || dbin->use_buffering) { + /* takes queue limits, initially we only queue up up to the max bytes limit, + * with a default of 2MB. we use the same values for buffering mode. */ + if ((max_bytes = dbin->max_size_bytes) == 0) + max_bytes = AUTO_PREROLL_SIZE_BYTES; + if ((max_buffers = dbin->max_size_buffers) == 0) + max_buffers = AUTO_PREROLL_SIZE_BUFFERS; + if ((max_time = dbin->max_size_time) == 0) + max_time = AUTO_PREROLL_SIZE_TIME; + } else { + /* update runtime limits. At runtime, we try to keep the amount of buffers + * in the queues as low as possible (but at least 5 buffers). */ + if ((max_bytes = dbin->max_size_bytes) == 0) + max_bytes = AUTO_PLAY_SIZE_BYTES; + if ((max_buffers = dbin->max_size_buffers) == 0) + max_buffers = AUTO_PLAY_SIZE_BUFFERS; + if ((max_time = dbin->max_size_time) == 0) + max_time = AUTO_PLAY_SIZE_TIME; + } + + g_object_set (multiqueue, + "max-size-bytes", max_bytes, "max-size-time", max_time, + "max-size-buffers", max_buffers, NULL); +} + +/* gst_decode_group_new: + * @dbin: Parent decodebin + * @parent: Parent chain or %NULL + * + * Creates a new GstDecodeGroup. It is up to the caller to add it to the list + * of groups. + */ +static GstDecodeGroup * +gst_decode_group_new (GstDecodeBin * dbin, GstDecodeChain * parent) +{ + GstDecodeGroup *group = g_slice_new0 (GstDecodeGroup); + GstElement *mq; + + GST_DEBUG_OBJECT (dbin, "Creating new group %p with parent chain %p", group, + parent); + + group->dbin = dbin; + group->parent = parent; + + mq = group->multiqueue = gst_element_factory_make ("multiqueue", NULL); + if (G_UNLIKELY (!group->multiqueue)) + goto missing_multiqueue; + + /* default is for use-buffering is FALSE */ + if (dbin->use_buffering) { + g_object_set (mq, + "use-buffering", TRUE, + "low-percent", dbin->low_percent, + "high-percent", dbin->high_percent, NULL); + } + + /* configure queue sizes for preroll */ + decodebin_set_queue_size (dbin, mq, TRUE); + + group->overrunsig = g_signal_connect (G_OBJECT (mq), "overrun", + G_CALLBACK (multi_queue_overrun_cb), group); + + gst_bin_add (GST_BIN (dbin), gst_object_ref (mq)); + gst_element_set_state (mq, GST_STATE_PAUSED); + + return group; + + /* ERRORS */ +missing_multiqueue: + { + gst_element_post_message (GST_ELEMENT_CAST (dbin), + gst_missing_element_message_new (GST_ELEMENT_CAST (dbin), + "multiqueue")); + GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no multiqueue!")); + g_slice_free (GstDecodeGroup, group); + return NULL; + } +} + +/* gst_decode_group_control_demuxer_pad + * + * Adds a new demuxer srcpad to the given group. + * + * Returns the srcpad of the multiqueue corresponding the given pad. + * Returns NULL if there was an error. + */ +static GstPad * +gst_decode_group_control_demuxer_pad (GstDecodeGroup * group, GstPad * pad) +{ + GstDecodeBin *dbin; + GstPad *srcpad, *sinkpad; + GstIterator *it = NULL; + + dbin = group->dbin; + + GST_LOG_OBJECT (dbin, "group:%p pad %s:%s", group, GST_DEBUG_PAD_NAME (pad)); + + srcpad = NULL; + + if (G_UNLIKELY (!group->multiqueue)) + return NULL; + + if (!(sinkpad = gst_element_get_request_pad (group->multiqueue, "sink%d"))) { + GST_ERROR_OBJECT (dbin, "Couldn't get sinkpad from multiqueue"); + return NULL; + } + + if ((gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { + GST_ERROR_OBJECT (dbin, "Couldn't link demuxer and multiqueue"); + goto error; + } + + it = gst_pad_iterate_internal_links (sinkpad); + + if (!it || (gst_iterator_next (it, (gpointer) & srcpad)) != GST_ITERATOR_OK + || srcpad == NULL) { + GST_ERROR_OBJECT (dbin, + "Couldn't get srcpad from multiqueue for sinkpad %" GST_PTR_FORMAT, + sinkpad); + goto error; + } + + CHAIN_MUTEX_LOCK (group->parent); + group->reqpads = g_list_prepend (group->reqpads, gst_object_ref (sinkpad)); + CHAIN_MUTEX_UNLOCK (group->parent); + +beach: + if (it) + gst_iterator_free (it); + gst_object_unref (sinkpad); + return srcpad; + +error: + gst_element_release_request_pad (group->multiqueue, sinkpad); + goto beach; +} + +/* gst_decode_group_is_complete: + * + * Checks if the group is complete, this means that + * a) overrun of the multiqueue or no-more-pads happened + * b) all child chains are complete + * + * Not MT-safe, always call with decodebin expose lock + */ +static gboolean +gst_decode_group_is_complete (GstDecodeGroup * group) +{ + GList *l; + gboolean complete = TRUE; + + if (!group->overrun && !group->no_more_pads) { + complete = FALSE; + goto out; + } + + for (l = group->children; l; l = l->next) { + GstDecodeChain *chain = l->data; + + if (!gst_decode_chain_is_complete (chain)) { + complete = FALSE; + goto out; + } + } + +out: + GST_DEBUG_OBJECT (group->dbin, "Group %p is complete: %d", group, complete); + return complete; +} + +/* gst_decode_chain_is_complete: + * + * Returns TRUE if the chain is complete, this means either + * a) This chain is a dead end, i.e. we have no suitable plugins + * b) This chain ends in an endpad and this is blocked or exposed + * + * Not MT-safe, always call with decodebin expose lock + */ +static gboolean +gst_decode_chain_is_complete (GstDecodeChain * chain) +{ + gboolean complete = FALSE; + + CHAIN_MUTEX_LOCK (chain); + if (chain->deadend) { + complete = TRUE; + goto out; + } + + if (chain->endpad && (chain->endpad->blocked || chain->endpad->exposed)) { + complete = TRUE; + goto out; + } + + if (chain->demuxer) { + if (chain->active_group + && gst_decode_group_is_complete (chain->active_group)) { + complete = TRUE; + goto out; + } + } + +out: + CHAIN_MUTEX_UNLOCK (chain); + GST_DEBUG_OBJECT (chain->dbin, "Chain %p is complete: %d", chain, complete); + return complete; +} + +/* check if the group is drained, meaning all pads have seen an EOS + * event. */ +static void +gst_decode_pad_handle_eos (GstDecodePad * pad) +{ + GstDecodeChain *chain = pad->chain; + + GST_LOG_OBJECT (pad->dbin, "chain : %p, pad %p", chain, pad); + pad->drained = TRUE; + gst_decode_chain_handle_eos (chain); +} + +/* gst_decode_chain_handle_eos: + * + * Checks if there are next groups in any parent chain + * to which we can switch or if everything is drained. + * + * If there are groups to switch to, hide the current active + * one and expose the new one. + * + * MT-safe, don't call with chain lock! + */ +static void +gst_decode_chain_handle_eos (GstDecodeChain * eos_chain) +{ + GstDecodeBin *dbin = eos_chain->dbin; + GstDecodeGroup *group; + GstDecodeChain *chain = eos_chain; + gboolean drained; + + g_return_if_fail (eos_chain->endpad); + + CHAIN_MUTEX_LOCK (chain); + while ((group = chain->parent)) { + CHAIN_MUTEX_UNLOCK (chain); + chain = group->parent; + CHAIN_MUTEX_LOCK (chain); + + if (gst_decode_group_is_drained (group)) { + continue; + } + break; + } + + drained = chain->active_group ? + gst_decode_group_is_drained (chain->active_group) : TRUE; + + /* Now either group == NULL and chain == dbin->decode_chain + * or chain is the lowest chain that has a non-drained group */ + if (chain->active_group && drained && chain->next_groups) { + GST_DEBUG_OBJECT (dbin, "Hiding current group %p", chain->active_group); + gst_decode_group_hide (chain->active_group); + chain->old_groups = g_list_prepend (chain->old_groups, chain->active_group); + GST_DEBUG_OBJECT (dbin, "Switching to next group %p", + chain->next_groups->data); + chain->active_group = chain->next_groups->data; + chain->next_groups = + g_list_delete_link (chain->next_groups, chain->next_groups); + CHAIN_MUTEX_UNLOCK (chain); + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) + gst_decode_bin_expose (dbin); + EXPOSE_UNLOCK (dbin); + } else if (!chain->active_group || drained) { + g_assert (chain == dbin->decode_chain); + CHAIN_MUTEX_UNLOCK (chain); + + GST_LOG_OBJECT (dbin, "all groups drained, fire signal"); + g_signal_emit (G_OBJECT (dbin), gst_decode_bin_signals[SIGNAL_DRAINED], 0, + NULL); + } else { + CHAIN_MUTEX_UNLOCK (chain); + GST_DEBUG_OBJECT (dbin, + "Current active group in chain %p is not drained yet", chain); + } +} + +/* gst_decode_group_is_drained: + * + * Check is this group is drained and cache this result. + * The group is drained if all child chains are drained. + * + * Not MT-safe, call with group->parent's lock */ +static gboolean +gst_decode_group_is_drained (GstDecodeGroup * group) +{ + GList *l; + gboolean drained = TRUE; + + if (group->drained) { + drained = TRUE; + goto out; + } + + for (l = group->children; l; l = l->next) { + GstDecodeChain *chain = l->data; + + CHAIN_MUTEX_LOCK (chain); + if (!gst_decode_chain_is_drained (chain)) + drained = FALSE; + CHAIN_MUTEX_UNLOCK (chain); + if (!drained) + goto out; + } + group->drained = drained; + +out: + GST_DEBUG_OBJECT (group->dbin, "Group %p is drained: %d", group, drained); + return drained; +} + +/* gst_decode_chain_is_drained: + * + * Check is the chain is drained, which means that + * either + * + * a) it's endpad is drained + * b) there are no pending pads, the active group is drained + * and there are no next groups + * + * Not MT-safe, call with chain lock + */ +static gboolean +gst_decode_chain_is_drained (GstDecodeChain * chain) +{ + gboolean drained = FALSE; + + if (chain->endpad) { + drained = chain->endpad->drained; + goto out; + } + + if (chain->pending_pads) { + drained = FALSE; + goto out; + } + + if (chain->active_group && gst_decode_group_is_drained (chain->active_group) + && !chain->next_groups) { + drained = TRUE; + goto out; + } + +out: + GST_DEBUG_OBJECT (chain->dbin, "Chain %p is drained: %d", chain, drained); + return drained; +} + +/* sort_end_pads: + * GCompareFunc to use with lists of GstPad. + * Sorts pads by mime type. + * First video (raw, then non-raw), then audio (raw, then non-raw), + * then others. + * + * Return: negative if ab + */ +static gint +sort_end_pads (GstDecodePad * da, GstDecodePad * db) +{ + gint va, vb; + GstCaps *capsa, *capsb; + GstStructure *sa, *sb; + const gchar *namea, *nameb; + + capsa = get_pad_caps (GST_PAD_CAST (da)); + capsb = get_pad_caps (GST_PAD_CAST (db)); + + sa = gst_caps_get_structure ((const GstCaps *) capsa, 0); + sb = gst_caps_get_structure ((const GstCaps *) capsb, 0); + + namea = gst_structure_get_name (sa); + nameb = gst_structure_get_name (sb); + + if (g_strrstr (namea, "video/x-raw-")) + va = 0; + else if (g_strrstr (namea, "video/")) + va = 1; + else if (g_strrstr (namea, "audio/x-raw")) + va = 2; + else if (g_strrstr (namea, "audio/")) + va = 3; + else + va = 4; + + if (g_strrstr (nameb, "video/x-raw-")) + vb = 0; + else if (g_strrstr (nameb, "video/")) + vb = 1; + else if (g_strrstr (nameb, "audio/x-raw")) + vb = 2; + else if (g_strrstr (nameb, "audio/")) + vb = 3; + else + vb = 4; + + gst_caps_unref (capsa); + gst_caps_unref (capsb); + + return va - vb; +} + +static GstCaps * +_gst_element_get_linked_caps (GstElement * src, GstElement * sink) +{ + GstIterator *it; + GstElement *parent; + GstPad *pad, *peer; + gboolean done = FALSE; + GstCaps *caps = NULL; + + it = gst_element_iterate_src_pads (src); + while (!done) { + switch (gst_iterator_next (it, (gpointer) & pad)) { + case GST_ITERATOR_OK: + peer = gst_pad_get_peer (pad); + if (peer) { + parent = gst_pad_get_parent_element (peer); + if (parent == sink) { + caps = gst_pad_get_negotiated_caps (pad); + done = TRUE; + } + + if (parent) + gst_object_unref (parent); + gst_object_unref (peer); + } + gst_object_unref (pad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + + gst_iterator_free (it); + + return caps; +} + +static GQuark topology_structure_name = 0; +static GQuark topology_caps = 0; +static GQuark topology_next = 0; +static GQuark topology_pad = 0; + +/* FIXME: Invent gst_structure_take_structure() to prevent all the + * structure copying for nothing + */ +static GstStructure * +gst_decode_chain_get_topology (GstDecodeChain * chain) +{ + GstStructure *s, *u; + GList *l; + GstCaps *caps; + + if (G_UNLIKELY ((chain->endpad || chain->deadend) + && (chain->endcaps == NULL))) { + GST_WARNING ("End chain without valid caps !"); + return NULL; + } + + u = gst_structure_id_empty_new (topology_structure_name); + + /* Now at the last element */ + if (chain->elements && (chain->endpad || chain->deadend)) { + s = gst_structure_id_empty_new (topology_structure_name); + gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, chain->endcaps, + NULL); + + if (chain->endpad) + gst_structure_id_set (u, topology_pad, GST_TYPE_PAD, chain->endpad, NULL); + gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL); + gst_structure_free (u); + u = s; + } else if (chain->active_group) { + GValue list = { 0, }; + GValue item = { 0, }; + + g_value_init (&list, GST_TYPE_LIST); + g_value_init (&item, GST_TYPE_STRUCTURE); + for (l = chain->active_group->children; l; l = l->next) { + s = gst_decode_chain_get_topology (l->data); + if (s) { + gst_value_set_structure (&item, s); + gst_value_list_append_value (&list, &item); + g_value_reset (&item); + gst_structure_free (s); + } + } + gst_structure_id_set_value (u, topology_next, &list); + g_value_unset (&list); + g_value_unset (&item); + } + + /* Get caps between all elements in this chain */ + l = (chain->elements && chain->elements->next) ? chain->elements : NULL; + for (; l && l->next; l = l->next) { + GstCaps *caps = _gst_element_get_linked_caps (l->next->data, l->data); + + if (caps) { + s = gst_structure_id_empty_new (topology_structure_name); + gst_structure_id_set (u, topology_caps, GST_TYPE_CAPS, caps, NULL); + gst_caps_unref (caps); + + gst_structure_id_set (s, topology_next, GST_TYPE_STRUCTURE, u, NULL); + gst_structure_free (u); + u = s; + } + } + + /* Caps that resulted in this chain */ + caps = gst_pad_get_negotiated_caps (chain->pad); + if (!caps) { + caps = get_pad_caps (chain->pad); + if (G_UNLIKELY (!gst_caps_is_fixed (caps))) { + GST_ERROR_OBJECT (chain->pad, + "Couldn't get fixed caps, got %" GST_PTR_FORMAT, caps); + gst_caps_unref (caps); + caps = NULL; + } + } + gst_structure_set (u, "caps", GST_TYPE_CAPS, caps, NULL); + gst_caps_unref (caps); + + return u; +} + +static void +gst_decode_bin_post_topology_message (GstDecodeBin * dbin) +{ + GstStructure *s; + GstMessage *msg; + + s = gst_decode_chain_get_topology (dbin->decode_chain); + + msg = gst_message_new_element (GST_OBJECT (dbin), s); + gst_element_post_message (GST_ELEMENT (dbin), msg); +} + +/* Must only be called if the toplevel chain is complete and blocked! */ +/* Not MT-safe, call with decodebin expose lock! */ +static gboolean +gst_decode_bin_expose (GstDecodeBin * dbin) +{ + GList *tmp, *endpads = NULL; + gboolean missing_plugin = FALSE; + gboolean already_exposed = TRUE; + + GST_DEBUG_OBJECT (dbin, "Exposing currently active chains/groups"); + + /* Don't expose if we're currently shutting down */ + DYN_LOCK (dbin); + if (G_UNLIKELY (dbin->shutdown == TRUE)) { + GST_WARNING_OBJECT (dbin, "Currently, shutting down, aborting exposing"); + DYN_UNLOCK (dbin); + return FALSE; + } + DYN_UNLOCK (dbin); + + /* Get the pads that we're going to expose and mark things as exposed */ + if (!gst_decode_chain_expose (dbin->decode_chain, &endpads, &missing_plugin)) { + g_list_foreach (endpads, (GFunc) gst_object_unref, NULL); + g_list_free (endpads); + GST_ERROR_OBJECT (dbin, "Broken chain/group tree"); + g_return_val_if_reached (FALSE); + return FALSE; + } + if (endpads == NULL) { + if (missing_plugin) { + GST_WARNING_OBJECT (dbin, "No suitable plugins found"); + GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), + ("no suitable plugins found")); + } else { + /* in this case, the stream ended without buffers, + * just post a warning */ + GST_WARNING_OBJECT (dbin, "All streams finished without buffers"); + GST_ELEMENT_ERROR (dbin, STREAM, FAILED, (NULL), + ("all streams without buffers")); + } + return FALSE; + } + + /* Check if this was called when everything was exposed already */ + for (tmp = endpads; tmp && already_exposed; tmp = tmp->next) { + GstDecodePad *dpad = tmp->data; + + already_exposed &= dpad->exposed; + if (!already_exposed) + break; + } + if (already_exposed) { + GST_DEBUG_OBJECT (dbin, "Everything was exposed already!"); + g_list_foreach (endpads, (GFunc) gst_object_unref, NULL); + g_list_free (endpads); + return TRUE; + } + + /* Set all already exposed pads to blocked */ + for (tmp = endpads; tmp; tmp = tmp->next) { + GstDecodePad *dpad = tmp->data; + + if (dpad->exposed) { + GST_DEBUG_OBJECT (dpad, "blocking exposed pad"); + gst_decode_pad_set_blocked (dpad, TRUE); + } + } + + /* re-order pads : video, then audio, then others */ + endpads = g_list_sort (endpads, (GCompareFunc) sort_end_pads); + + /* Expose pads */ + for (tmp = endpads; tmp; tmp = tmp->next) { + GstDecodePad *dpad = (GstDecodePad *) tmp->data; + gchar *padname; + + /* 1. rewrite name */ + padname = g_strdup_printf ("src%d", dbin->nbpads); + dbin->nbpads++; + GST_DEBUG_OBJECT (dbin, "About to expose dpad %s as %s", + GST_OBJECT_NAME (dpad), padname); + gst_object_set_name (GST_OBJECT (dpad), padname); + g_free (padname); + + /* 2. activate and add */ + if (!dpad->exposed + && !gst_element_add_pad (GST_ELEMENT (dbin), GST_PAD_CAST (dpad))) { + /* not really fatal, we can try to add the other pads */ + g_warning ("error adding pad to decodebin2"); + continue; + } + dpad->exposed = TRUE; + + /* 3. emit signal */ + GST_DEBUG_OBJECT (dbin, "emitting new-decoded-pad"); + g_signal_emit (G_OBJECT (dbin), + gst_decode_bin_signals[SIGNAL_NEW_DECODED_PAD], 0, dpad, + (tmp->next == NULL)); + GST_DEBUG_OBJECT (dbin, "emitted new-decoded-pad"); + } + + /* 4. Signal no-more-pads. This allows the application to hook stuff to the + * exposed pads */ + GST_LOG_OBJECT (dbin, "signalling no-more-pads"); + gst_element_no_more_pads (GST_ELEMENT (dbin)); + + /* 5. Send a custom element message with the stream topology */ + if (dbin->post_stream_topology) + gst_decode_bin_post_topology_message (dbin); + + /* 6. Unblock internal pads. The application should have connected stuff now + * so that streaming can continue. */ + for (tmp = endpads; tmp; tmp = tmp->next) { + GstDecodePad *dpad = (GstDecodePad *) tmp->data; + + GST_DEBUG_OBJECT (dpad, "unblocking"); + gst_decode_pad_unblock (dpad); + GST_DEBUG_OBJECT (dpad, "unblocked"); + gst_object_unref (dpad); + } + g_list_free (endpads); + + do_async_done (dbin); + GST_DEBUG_OBJECT (dbin, "Exposed everything"); + return TRUE; +} + +/* gst_decode_chain_expose: + * + * Check if the chain can be exposed and add all endpads + * to the endpads list. + * + * Also update the active group's multiqueue to the + * runtime limits. + * + * Not MT-safe, call with decodebin expose lock! * + */ +static gboolean +gst_decode_chain_expose (GstDecodeChain * chain, GList ** endpads, + gboolean * missing_plugin) +{ + GstDecodeGroup *group; + GList *l; + GstDecodeBin *dbin; + + if (chain->deadend) { + if (chain->endcaps) + *missing_plugin = TRUE; + return TRUE; + } + + if (chain->endpad) { + if (!chain->endpad->blocked && !chain->endpad->exposed) + return FALSE; + *endpads = g_list_prepend (*endpads, gst_object_ref (chain->endpad)); + return TRUE; + } + + group = chain->active_group; + if (!group) + return FALSE; + if (!group->no_more_pads && !group->overrun) + return FALSE; + + dbin = group->dbin; + + /* configure queues for playback */ + decodebin_set_queue_size (dbin, group->multiqueue, FALSE); + + /* we can now disconnect any overrun signal, which is used to expose the + * group. */ + if (group->overrunsig) { + GST_LOG_OBJECT (dbin, "Disconnecting overrun"); + g_signal_handler_disconnect (group->multiqueue, group->overrunsig); + group->overrunsig = 0; + } + + for (l = group->children; l; l = l->next) { + GstDecodeChain *childchain = l->data; + + if (!gst_decode_chain_expose (childchain, endpads, missing_plugin)) + return FALSE; + } + + return TRUE; +} + +/************************* + * GstDecodePad functions + *************************/ + +static void +gst_decode_pad_class_init (GstDecodePadClass * klass) +{ +} + +static void +gst_decode_pad_init (GstDecodePad * pad) +{ + pad->chain = NULL; + pad->blocked = FALSE; + pad->exposed = FALSE; + pad->drained = FALSE; + gst_object_ref (pad); + gst_object_sink (pad); +} + +static void +source_pad_blocked_cb (GstPad * pad, gboolean blocked, GstDecodePad * dpad) +{ + GstDecodeChain *chain; + GstDecodeBin *dbin; + + chain = dpad->chain; + dbin = chain->dbin; + + GST_LOG_OBJECT (dpad, "blocked:%d, dpad->chain:%p", blocked, chain); + + dpad->blocked = blocked; + + if (dpad->blocked) { + EXPOSE_LOCK (dbin); + if (gst_decode_chain_is_complete (dbin->decode_chain)) { + if (!gst_decode_bin_expose (dbin)) + GST_WARNING_OBJECT (dbin, "Couldn't expose group"); + } + EXPOSE_UNLOCK (dbin); + } +} + +static gboolean +source_pad_event_probe (GstPad * pad, GstEvent * event, GstDecodePad * dpad) +{ + GST_LOG_OBJECT (pad, "%s dpad:%p", GST_EVENT_TYPE_NAME (event), dpad); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GST_DEBUG_OBJECT (pad, "we received EOS"); + + /* Check if all pads are drained. If there is a next group to expose, we + * will remove the ghostpad of the current group first, which unlinks the + * peer and so drops the EOS. */ + gst_decode_pad_handle_eos (dpad); + } + /* never drop events */ + return TRUE; +} + +static void +gst_decode_pad_set_blocked (GstDecodePad * dpad, gboolean blocked) +{ + GstDecodeBin *dbin = dpad->dbin; + GstPad *opad; + + DYN_LOCK (dbin); + + GST_DEBUG_OBJECT (dpad, "blocking pad: %d", blocked); + + opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad)); + if (!opad) + goto out; + + /* do not block if shutting down. + * we do not consider/expect it blocked further below, but use other trick */ + if (!blocked || !dbin->shutdown) + gst_pad_set_blocked_async_full (opad, blocked, + (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad), + (GDestroyNotify) gst_object_unref); + + if (blocked) { + if (dbin->shutdown) { + /* deactivate to force flushing state to prevent NOT_LINKED errors */ + gst_pad_set_active (GST_PAD_CAST (dpad), FALSE); + /* note that deactivating the target pad would have no effect here, + * since elements are typically connected first (and pads exposed), + * and only then brought to PAUSED state (so pads activated) */ + } else { + gst_object_ref (dpad); + dbin->blocked_pads = g_list_prepend (dbin->blocked_pads, dpad); + } + } else { + GList *l; + + if ((l = g_list_find (dbin->blocked_pads, dpad))) { + gst_object_unref (dpad); + dbin->blocked_pads = g_list_delete_link (dbin->blocked_pads, l); + } + } + gst_object_unref (opad); +out: + DYN_UNLOCK (dbin); +} + +static void +gst_decode_pad_add_drained_check (GstDecodePad * dpad) +{ + gst_pad_add_event_probe (GST_PAD_CAST (dpad), + G_CALLBACK (source_pad_event_probe), dpad); +} + +static void +gst_decode_pad_activate (GstDecodePad * dpad, GstDecodeChain * chain) +{ + g_return_if_fail (chain != NULL); + + dpad->chain = chain; + gst_pad_set_active (GST_PAD_CAST (dpad), TRUE); + gst_decode_pad_set_blocked (dpad, TRUE); + gst_decode_pad_add_drained_check (dpad); +} + +static void +gst_decode_pad_unblock (GstDecodePad * dpad) +{ + gst_decode_pad_set_blocked (dpad, FALSE); +} + +/*gst_decode_pad_new: + * + * Creates a new GstDecodePad for the given pad. + */ +static GstDecodePad * +gst_decode_pad_new (GstDecodeBin * dbin, GstPad * pad, GstDecodeChain * chain) +{ + GstDecodePad *dpad; + GstPadTemplate *pad_tmpl; + + GST_DEBUG_OBJECT (dbin, "making new decodepad"); + pad_tmpl = gst_static_pad_template_get (&decoder_bin_src_template); + dpad = + g_object_new (GST_TYPE_DECODE_PAD, "direction", GST_PAD_DIRECTION (pad), + "template", pad_tmpl, NULL); + gst_ghost_pad_construct (GST_GHOST_PAD_CAST (dpad)); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (dpad), pad); + dpad->chain = chain; + dpad->dbin = dbin; + gst_object_unref (pad_tmpl); + + return dpad; +} + +static void +gst_pending_pad_free (GstPendingPad * ppad) +{ + g_assert (ppad); + g_assert (ppad->pad); + + if (ppad->event_probe_id != 0) + gst_pad_remove_event_probe (ppad->pad, ppad->event_probe_id); + gst_object_unref (ppad->pad); + g_slice_free (GstPendingPad, ppad); +} + +/***** + * Element add/remove + *****/ + +static void +do_async_start (GstDecodeBin * dbin) +{ + GstMessage *message; + + dbin->async_pending = TRUE; + + message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE); + parent_class->handle_message (GST_BIN_CAST (dbin), message); +} + +static void +do_async_done (GstDecodeBin * dbin) +{ + GstMessage *message; + + if (dbin->async_pending) { + message = gst_message_new_async_done (GST_OBJECT_CAST (dbin)); + parent_class->handle_message (GST_BIN_CAST (dbin), message); + + dbin->async_pending = FALSE; + } +} + +/***** + * convenience functions + *****/ + +/* find_sink_pad + * + * Returns the first sink pad of the given element, or NULL if it doesn't have + * any. + */ + +static GstPad * +find_sink_pad (GstElement * element) +{ + GstIterator *it; + GstPad *pad = NULL; + gpointer point; + + it = gst_element_iterate_sink_pads (element); + + if ((gst_iterator_next (it, &point)) == GST_ITERATOR_OK) + pad = (GstPad *) point; + + gst_iterator_free (it); + + return pad; +} + +/* call with dyn_lock held */ +static void +unblock_pads (GstDecodeBin * dbin) +{ + GList *tmp; + + GST_LOG_OBJECT (dbin, "unblocking pads"); + + for (tmp = dbin->blocked_pads; tmp; tmp = tmp->next) { + GstDecodePad *dpad = (GstDecodePad *) tmp->data; + GstPad *opad; + + opad = gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (dpad)); + if (!opad) + continue; + + GST_DEBUG_OBJECT (dpad, "unblocking"); + gst_pad_set_blocked_async_full (opad, FALSE, + (GstPadBlockCallback) source_pad_blocked_cb, gst_object_ref (dpad), + (GDestroyNotify) gst_object_unref); + /* make flushing, prevent NOT_LINKED */ + GST_PAD_SET_FLUSHING (GST_PAD_CAST (dpad)); + gst_object_unref (dpad); + gst_object_unref (opad); + GST_DEBUG_OBJECT (dpad, "unblocked"); + } + + /* clear, no more blocked pads */ + g_list_free (dbin->blocked_pads); + dbin->blocked_pads = NULL; +} + +static GstStateChangeReturn +gst_decode_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstDecodeBin *dbin = GST_DECODE_BIN (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (dbin->typefind == NULL) + goto missing_typefind; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* Make sure we've cleared all existing chains */ + if (dbin->decode_chain) { + gst_decode_chain_free (dbin->decode_chain); + dbin->decode_chain = NULL; + } + DYN_LOCK (dbin); + GST_LOG_OBJECT (dbin, "clearing shutdown flag"); + dbin->shutdown = FALSE; + DYN_UNLOCK (dbin); + dbin->have_type = FALSE; + ret = GST_STATE_CHANGE_ASYNC; + do_async_start (dbin); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + DYN_LOCK (dbin); + GST_LOG_OBJECT (dbin, "setting shutdown flag"); + dbin->shutdown = TRUE; + unblock_pads (dbin); + DYN_UNLOCK (dbin); + default: + break; + } + + { + GstStateChangeReturn bret; + + bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE)) + goto activate_failed; + else if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) { + do_async_done (dbin); + ret = bret; + } + } + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + do_async_done (dbin); + if (dbin->decode_chain) { + gst_decode_chain_free (dbin->decode_chain); + dbin->decode_chain = NULL; + } + break; + case GST_STATE_CHANGE_READY_TO_NULL: + default: + break; + } + + return ret; + +/* ERRORS */ +missing_typefind: + { + gst_element_post_message (element, + gst_missing_element_message_new (element, "typefind")); + GST_ELEMENT_ERROR (dbin, CORE, MISSING_PLUGIN, (NULL), ("no typefind!")); + return GST_STATE_CHANGE_FAILURE; + } +activate_failed: + { + GST_DEBUG_OBJECT (element, + "element failed to change states -- activation problem?"); + return GST_STATE_CHANGE_FAILURE; + } +} + +gboolean +gst_decode_bin_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_decode_bin_debug, "decodebin2", 0, + "decoder bin"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + /* Register some quarks here for the stream topology message */ + topology_structure_name = g_quark_from_static_string ("stream-topology"); + topology_caps = g_quark_from_static_string ("caps"); + topology_next = g_quark_from_static_string ("next"); + topology_pad = g_quark_from_static_string ("pad"); + + return gst_element_register (plugin, "decodebin2", GST_RANK_NONE, + GST_TYPE_DECODE_BIN); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.c new file mode 100644 index 0000000..e337fdf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.c @@ -0,0 +1,81 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstplay-enum.h" + +#define C_ENUM(v) ((gint) v) +#define C_FLAGS(v) ((guint) v) + +GType +gst_autoplug_select_result_get_type (void) +{ + static const GEnumValue values[] = { + {C_ENUM (GST_AUTOPLUG_SELECT_TRY), "GST_AUTOPLUG_SELECT_TRY", "try"}, + {C_ENUM (GST_AUTOPLUG_SELECT_EXPOSE), "GST_AUTOPLUG_SELECT_EXPOSE", + "expose"}, + {C_ENUM (GST_AUTOPLUG_SELECT_SKIP), "GST_AUTOPLUG_SELECT_SKIP", "skip"}, + {0, NULL, NULL} + }; + static volatile GType id = 0; + + if (g_once_init_enter ((gsize *) & id)) { + GType _id; + + _id = g_enum_register_static ("GstAutoplugSelectResult", values); + + g_once_init_leave ((gsize *) & id, _id); + } + + return id; +} + +GType +gst_play_flags_get_type (void) +{ + static const GFlagsValue values[] = { + {C_FLAGS (GST_PLAY_FLAG_VIDEO), "Render the video stream", "video"}, + {C_FLAGS (GST_PLAY_FLAG_AUDIO), "Render the audio stream", "audio"}, + {C_FLAGS (GST_PLAY_FLAG_TEXT), "Render subtitles", "text"}, + {C_FLAGS (GST_PLAY_FLAG_VIS), + "Render visualisation when no video is present", "vis"}, + {C_FLAGS (GST_PLAY_FLAG_SOFT_VOLUME), "Use software volume", "soft-volume"}, + {C_FLAGS (GST_PLAY_FLAG_NATIVE_AUDIO), "Only use native audio formats", + "native-audio"}, + {C_FLAGS (GST_PLAY_FLAG_NATIVE_VIDEO), "Only use native video formats", + "native-video"}, + {C_FLAGS (GST_PLAY_FLAG_DOWNLOAD), "Attempt progressive download buffering", + "download"}, + {C_FLAGS (GST_PLAY_FLAG_BUFFERING), "Buffer demuxed/parsed data", + "buffering"}, + {C_FLAGS (GST_PLAY_FLAG_DEINTERLACE), "Deinterlace video if necessary", + "deinterlace"}, + {0, NULL, NULL} + }; + static volatile GType id = 0; + + if (g_once_init_enter ((gsize *) & id)) { + GType _id; + + _id = g_flags_register_static ("GstPlayFlags", values); + + g_once_init_leave ((gsize *) & id, _id); + } + + return id; +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.h b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.h new file mode 100644 index 0000000..1e33f06 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-enum.h @@ -0,0 +1,80 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLAY_ENUM_H__ +#define __GST_PLAY_ENUM_H__ + +#include + +G_BEGIN_DECLS + +/** + * GstAutoplugSelectResult: + * @GST_AUTOPLUG_SELECT_TRY: try to autoplug the current factory + * @GST_AUTOPLUG_SELECT_EXPOSE: expose the pad as a raw stream + * @GST_AUTOPLUG_SELECT_SKIP: skip the current factory + * + * return values for the autoplug-select signal. + */ +typedef enum { + GST_AUTOPLUG_SELECT_TRY, + GST_AUTOPLUG_SELECT_EXPOSE, + GST_AUTOPLUG_SELECT_SKIP +} GstAutoplugSelectResult; + +#define GST_TYPE_AUTOPLUG_SELECT_RESULT (gst_autoplug_select_result_get_type()) +GType gst_autoplug_select_result_get_type (void); + +/** + * GstPlayFlags: + * @GST_PLAY_FLAG_VIDEO: Enable rendering of the video stream + * @GST_PLAY_FLAG_AUDIO: Enable rendering of the audio stream + * @GST_PLAY_FLAG_TEXT: Enable rendering of subtitles + * @GST_PLAY_FLAG_VIS: Enable rendering of visualisations when there is + * no video stream. + * @GST_PLAY_FLAG_SOFT_VOLUME: Use software volume + * @GST_PLAY_FLAG_NATIVE_AUDIO: only allow native audio formats, this omits + * configuration of audioconvert and audioresample. + * @GST_PLAY_FLAG_NATIVE_VIDEO: only allow native video formats, this omits + * configuration of ffmpegcolorspace and videoscale. + * @GST_PLAY_FLAG_DOWNLOAD: enable progressice download buffering for selected + * formats. + * @GST_PLAY_FLAG_BUFFERING: enable buffering of the demuxed or parsed data. + * + * Extra flags to configure the behaviour of the sinks. + */ +typedef enum { + GST_PLAY_FLAG_VIDEO = (1 << 0), + GST_PLAY_FLAG_AUDIO = (1 << 1), + GST_PLAY_FLAG_TEXT = (1 << 2), + GST_PLAY_FLAG_VIS = (1 << 3), + GST_PLAY_FLAG_SOFT_VOLUME = (1 << 4), + GST_PLAY_FLAG_NATIVE_AUDIO = (1 << 5), + GST_PLAY_FLAG_NATIVE_VIDEO = (1 << 6), + GST_PLAY_FLAG_DOWNLOAD = (1 << 7), + GST_PLAY_FLAG_BUFFERING = (1 << 8), + GST_PLAY_FLAG_DEINTERLACE = (1 << 9) +} GstPlayFlags; + +#define GST_TYPE_PLAY_FLAGS (gst_play_flags_get_type()) +GType gst_play_flags_get_type (void); + +G_END_DECLS + +#endif /* __GST_PLAY_ENUM_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplay-marshal.list b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-marshal.list new file mode 100644 index 0000000..d7eddf4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplay-marshal.list @@ -0,0 +1,10 @@ +BOOLEAN:OBJECT,BOXED +BOOLEAN:OBJECT,OBJECT,OBJECT +BOXED:OBJECT,BOXED +VOID:OBJECT,BOOLEAN +ENUM:OBJECT,OBJECT,BOXED +ENUM:OBJECT,BOXED,OBJECT +BOXED:OBJECT,BOXED,BOXED +BOXED:INT +OBJECT:BOXED +OBJECT:INT diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.c new file mode 100644 index 0000000..a83fee1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.c @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include + +#include "gstplayback.h" +#include "gstplaysink.h" +#include "gststreamselector.h" +#include "gststreaminfo.h" +#include "gstsubtitleoverlay.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean res; + + gst_pb_utils_init (); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + /* ref class from a thread-safe context to work around missing bit of + * thread-safety in GObject */ + g_type_class_ref (GST_TYPE_STREAM_INFO); + g_type_class_ref (GST_TYPE_STREAM_SELECTOR); + + res = gst_play_bin_plugin_init (plugin); + res &= gst_play_bin2_plugin_init (plugin); + res &= gst_play_sink_plugin_init (plugin); + res &= gst_subtitle_overlay_plugin_init (plugin); + + return res; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "playback", + "various playback elements", plugin_init, VERSION, GST_LICENSE, + GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.h b/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.h new file mode 100644 index 0000000..4be121c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplayback.h @@ -0,0 +1,31 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLAY_BACK_H__ +#define __GST_PLAY_BACK_H__ + + +#include + +gboolean gst_decode_bin_plugin_init (GstPlugin * plugin); +gboolean gst_play_bin_plugin_init (GstPlugin * plugin); +gboolean gst_play_bin2_plugin_init (GstPlugin * plugin); + + +#endif /* __GST_PLAY_BACK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.c new file mode 100644 index 0000000..847e12f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.c @@ -0,0 +1,2811 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include "gstplaybasebin.h" +#include "gststreamselector.h" +#include "gstplay-marshal.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_play_base_bin_debug); +#define GST_CAT_DEFAULT gst_play_base_bin_debug + +#define DEFAULT_QUEUE_SIZE (3 * GST_SECOND) +#define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100) +#define DEFAULT_QUEUE_THRESHOLD ((DEFAULT_QUEUE_SIZE * 95) / 100) +#define DEFAULT_CONNECTION_SPEED 0 + +#define GROUP_LOCK(pbb) g_mutex_lock (pbb->group_lock) +#define GROUP_UNLOCK(pbb) g_mutex_unlock (pbb->group_lock) +#define GROUP_WAIT(pbb) g_cond_wait (pbb->group_cond, pbb->group_lock) +#define GROUP_SIGNAL(pbb) g_cond_signal (pbb->group_cond) + +/* props */ +enum +{ + ARG_0, + ARG_URI, + ARG_SUBURI, + ARG_QUEUE_SIZE, + ARG_QUEUE_THRESHOLD, + ARG_QUEUE_MIN_THRESHOLD, + ARG_NSTREAMS, + ARG_STREAMINFO, + ARG_STREAMINFO_VALUES, + ARG_SOURCE, + ARG_VIDEO, + ARG_AUDIO, + ARG_TEXT, + ARG_SUBTITLE_ENCODING, + ARG_CONNECTION_SPEED +}; + +static void gst_play_base_bin_class_init (GstPlayBaseBinClass * klass); +static void gst_play_base_bin_init (GstPlayBaseBin * play_base_bin); +static void gst_play_base_bin_dispose (GObject * object); +static void gst_play_base_bin_finalize (GObject * object); + +static void gst_play_base_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_play_base_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); +static void gst_play_base_bin_handle_message_func (GstBin * bin, + GstMessage * msg); + +static GstStateChangeReturn gst_play_base_bin_change_state (GstElement * + element, GstStateChange transition); + +static const GList *gst_play_base_bin_get_streaminfo (GstPlayBaseBin * bin); +static GValueArray *gst_play_base_bin_get_streaminfo_value_array (GstPlayBaseBin + * play_base_bin); +static void preroll_remove_overrun (GstElement * element, + GstPlayBaseBin * play_base_bin); +static void queue_remove_probe (GstElement * queue, GstPlayBaseBin + * play_base_bin); + +static GstElement *make_decoder (GstPlayBaseBin * play_base_bin); +static gboolean has_all_raw_caps (GstPad * pad, gboolean * all_raw); + +static gboolean prepare_output (GstPlayBaseBin * play_base_bin); +static void set_active_source (GstPlayBaseBin * play_base_bin, + GstStreamType type, gint source_num); +static gboolean probe_triggered (GstPad * pad, GstEvent * event, + gpointer user_data); +static void setup_substreams (GstPlayBaseBin * play_base_bin); + +static GstPipelineClass *parent_class; + +/* + * GObject playbasebin wrappers. + */ + +GType +gst_play_base_bin_get_type (void) +{ + static GType gst_play_base_bin_type = 0; + + if (!gst_play_base_bin_type) { + static const GTypeInfo gst_play_base_bin_info = { + sizeof (GstPlayBaseBinClass), + NULL, + NULL, + (GClassInitFunc) gst_play_base_bin_class_init, + NULL, + NULL, + sizeof (GstPlayBaseBin), + 0, + (GInstanceInitFunc) gst_play_base_bin_init, + NULL + }; + + gst_play_base_bin_type = g_type_register_static (GST_TYPE_PIPELINE, + "GstPlayBaseBin", &gst_play_base_bin_info, 0); + } + + return gst_play_base_bin_type; +} + +static void +gst_play_base_bin_class_init (GstPlayBaseBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + GstBinClass *gstbin_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + gstbin_klass = (GstBinClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_play_base_bin_set_property; + gobject_klass->get_property = gst_play_base_bin_get_property; + + g_object_class_install_property (gobject_klass, ARG_URI, + g_param_spec_string ("uri", "URI", "URI of the media to play", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_SUBURI, + g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, ARG_QUEUE_SIZE, + g_param_spec_uint64 ("queue-size", "Queue size", + "Size of internal queues in nanoseconds", 0, G_MAXINT64, + DEFAULT_QUEUE_SIZE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_QUEUE_THRESHOLD, + g_param_spec_uint64 ("queue-threshold", "Queue threshold", + "Buffering threshold of internal queues in nanoseconds", 0, + G_MAXINT64, DEFAULT_QUEUE_THRESHOLD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_QUEUE_MIN_THRESHOLD, + g_param_spec_uint64 ("queue-min-threshold", "Queue min threshold", + "Buffering low threshold of internal queues in nanoseconds", 0, + G_MAXINT64, DEFAULT_QUEUE_MIN_THRESHOLD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, ARG_NSTREAMS, + g_param_spec_int ("nstreams", "NStreams", "number of streams", + 0, G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_STREAMINFO, + g_param_spec_pointer ("stream-info", "Stream info", "List of streaminfo", + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_STREAMINFO_VALUES, + g_param_spec_value_array ("stream-info-value-array", + "StreamInfo GValueArray", "value array of streaminfo", + g_param_spec_object ("streaminfo", "StreamInfo", "Streaminfo object", + GST_TYPE_STREAM_INFO, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS), + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_SOURCE, + g_param_spec_object ("source", "Source", "Source element", + GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, ARG_VIDEO, + g_param_spec_int ("current-video", "Current video", + "Currently playing video stream (-1 = none)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_AUDIO, + g_param_spec_int ("current-audio", "Current audio", + "Currently playing audio stream (-1 = none)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_TEXT, + g_param_spec_int ("current-text", "Current text", + "Currently playing text stream (-1 = none)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBaseBin:connection-speed + * + * Network connection speed in kbps (0 = unknown) + * + * Since version 0.10.10 in #GstPlayBin, at 0.10.15 moved to #GstPlayBaseBin + * + * + * Since: 0.10.10 + */ + g_object_class_install_property (gobject_klass, ARG_CONNECTION_SPEED, + g_param_spec_uint ("connection-speed", "Connection Speed", + "Network connection speed in kbps (0 = unknown)", + 0, G_MAXUINT, DEFAULT_CONNECTION_SPEED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0, + "playbasebin"); + + gobject_klass->dispose = gst_play_base_bin_dispose; + gobject_klass->finalize = gst_play_base_bin_finalize; + + gstbin_klass->handle_message = + GST_DEBUG_FUNCPTR (gst_play_base_bin_handle_message_func); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_play_base_bin_change_state); +} + +static void +gst_play_base_bin_init (GstPlayBaseBin * play_base_bin) +{ + play_base_bin->uri = NULL; + play_base_bin->suburi = NULL; + play_base_bin->need_rebuild = TRUE; + play_base_bin->is_stream = FALSE; + play_base_bin->source = NULL; + play_base_bin->decoders = NULL; + play_base_bin->subtitle = NULL; + play_base_bin->subencoding = NULL; + play_base_bin->subtitle_elements = NULL; + play_base_bin->sub_lock = g_mutex_new (); + + play_base_bin->group_lock = g_mutex_new (); + play_base_bin->group_cond = g_cond_new (); + + play_base_bin->building_group = NULL; + play_base_bin->queued_groups = NULL; + + play_base_bin->queue_size = DEFAULT_QUEUE_SIZE; + play_base_bin->queue_threshold = DEFAULT_QUEUE_THRESHOLD; + play_base_bin->queue_min_threshold = DEFAULT_QUEUE_MIN_THRESHOLD; + play_base_bin->connection_speed = DEFAULT_CONNECTION_SPEED; +} + +static void +gst_play_base_bin_dispose (GObject * object) +{ + GstPlayBaseBin *play_base_bin; + + play_base_bin = GST_PLAY_BASE_BIN (object); + g_free (play_base_bin->uri); + play_base_bin->uri = NULL; + g_free (play_base_bin->suburi); + play_base_bin->suburi = NULL; + g_free (play_base_bin->subencoding); + play_base_bin->subencoding = NULL; + if (play_base_bin->subtitle_elements) { + g_slist_free (play_base_bin->subtitle_elements); + play_base_bin->subtitle_elements = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_play_base_bin_finalize (GObject * object) +{ + GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (object); + + g_mutex_free (play_base_bin->group_lock); + g_cond_free (play_base_bin->group_cond); + + g_mutex_free (play_base_bin->sub_lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* + * playbasebingroup stuff. + */ + +static GstPlayBaseGroup * +group_create (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group; + + group = g_new0 (GstPlayBaseGroup, 1); + group->bin = play_base_bin; + group->streaminfo_value_array = g_value_array_new (0); + + GST_DEBUG_OBJECT (play_base_bin, "created new group %p", group); + + return group; +} + +/* + * Gets the currently playing group. + * + * Callers must have group-lock held when calling this. + */ + +static GstPlayBaseGroup * +get_active_group (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group = NULL; + + if (play_base_bin->queued_groups) + group = play_base_bin->queued_groups->data; + + return group; +} + +/* + * get the group used for discovering the different streams. + * This function creates a group is there is none. + * + * Callers must have group-lock held when calling this. + */ +static GstPlayBaseGroup * +get_building_group (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group; + + group = play_base_bin->building_group; + if (group == NULL) { + group = group_create (play_base_bin); + play_base_bin->building_group = group; + } + + return group; +} + +/* + * Callers must have lock held when calling this! + */ + +static void +group_destroy (GstPlayBaseGroup * group) +{ + GstPlayBaseBin *play_base_bin = group->bin; + gint n; + + GST_LOG ("removing group %p", group); + + /* remove the preroll queues */ + for (n = 0; n < NUM_TYPES; n++) { + GstElement *element = group->type[n].preroll; + GstElement *fakesrc; + GstElement *sel; + const GList *item; + + if (!element) + continue; + + sel = group->type[n].selector; + + /* remove any fakesrc elements for this preroll element */ + for (item = sel->pads; item != NULL; item = item->next) { + GstPad *pad = GST_PAD (item->data); + guint sig_id; + + if (GST_PAD_DIRECTION (pad) != GST_PAD_SINK) + continue; + + sig_id = + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "unlinked_id")); + + if (sig_id != 0) { + GST_LOG ("removing unlink signal %s:%s", GST_DEBUG_PAD_NAME (pad)); + g_signal_handler_disconnect (G_OBJECT (pad), sig_id); + g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (0)); + } + + fakesrc = (GstElement *) g_object_get_data (G_OBJECT (pad), "fakesrc"); + if (fakesrc != NULL) { + GST_LOG ("removing fakesrc from %s:%s", + GST_PAD_NAME (pad), GST_ELEMENT_NAME (GST_PAD_PARENT (pad))); + gst_element_set_state (fakesrc, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_base_bin), fakesrc); + } + } + + /* if the group is currently being played, we have to remove the element + * from the thread */ + gst_element_set_state (element, GST_STATE_NULL); + gst_element_set_state (group->type[n].selector, GST_STATE_NULL); + + GST_LOG ("removing preroll element %s", GST_ELEMENT_NAME (element)); + + gst_bin_remove (group->type[n].bin, element); + gst_bin_remove (group->type[n].bin, group->type[n].selector); + + group->type[n].preroll = NULL; + group->type[n].selector = NULL; + group->type[n].bin = NULL; + } + + /* free the streaminfo too */ + g_list_foreach (group->streaminfo, (GFunc) g_object_unref, NULL); + g_list_free (group->streaminfo); + g_value_array_free (group->streaminfo_value_array); + g_free (group); +} + +/* + * is called when the current building group is completely finished + * and ready for playback + * + * This function grabs lock, so take care when calling. + */ +static void +group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle) +{ + GstPlayBaseGroup *group; + gboolean had_active_group; + + GROUP_LOCK (play_base_bin); + group = play_base_bin->building_group; + had_active_group = (get_active_group (play_base_bin) != NULL); + + GST_DEBUG_OBJECT (play_base_bin, "commit group %p, had active %d", + group, had_active_group); + + /* if an element signalled a no-more-pads after we stopped due + * to preroll, the group is NULL. This is not an error */ + if (group == NULL) { + if (!fatal) { + GROUP_UNLOCK (play_base_bin); + return; + } else { + GST_DEBUG_OBJECT (play_base_bin, "Group loading failed, bailing out"); + } + } else { + if (!subtitle) { + gint n; + + GST_DEBUG_OBJECT (play_base_bin, "group %p done", group); + + play_base_bin->queued_groups = + g_list_append (play_base_bin->queued_groups, group); + + play_base_bin->building_group = NULL; + + /* remove signals. We don't want anymore signals from the preroll + * elements at this stage. */ + for (n = 0; n < NUM_TYPES; n++) { + GstElement *element = group->type[n].preroll; + + if (!element) + continue; + + preroll_remove_overrun (element, play_base_bin); + /* if overrun is removed, probe alse has to be removed */ + queue_remove_probe (element, play_base_bin); + } + } else { + /* this is a special subtitle bin, we don't commit the group but + * mark the subtitles as detected before we signal. */ + GST_DEBUG_OBJECT (play_base_bin, "marking subtitle bin as complete"); + play_base_bin->subtitle_done = TRUE; + } + } + + GST_DEBUG_OBJECT (play_base_bin, "signal group done"); + GROUP_SIGNAL (play_base_bin); + GST_DEBUG_OBJECT (play_base_bin, "signaled group done"); + + if (!subtitle && !had_active_group) { + if (!prepare_output (play_base_bin)) { + GROUP_UNLOCK (play_base_bin); + return; + } + + setup_substreams (play_base_bin); + GST_DEBUG_OBJECT (play_base_bin, "Emitting signal"); + GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->setup_output_pads + (play_base_bin, group); + GST_DEBUG_OBJECT (play_base_bin, "done"); + + GROUP_UNLOCK (play_base_bin); + + g_object_notify (G_OBJECT (play_base_bin), "stream-info"); + } else { + GROUP_UNLOCK (play_base_bin); + } +} + +/* + * check if there are streams in the group that are not muted + * + * Callers must have group-lock held when calling this. + */ +static gboolean +group_is_muted (GstPlayBaseGroup * group) +{ + gint n; + + for (n = 0; n < NUM_TYPES; n++) { + if (group->type[n].preroll && !group->type[n].done) + return FALSE; + } + + return TRUE; +} + +/* + * Buffer/cache checking. + */ + +static inline void +fill_buffer (GstPlayBaseBin * play_base_bin, gint percent) +{ + GST_DEBUG_OBJECT (play_base_bin, "buffering %d", percent); + gst_element_post_message (GST_ELEMENT_CAST (play_base_bin), + gst_message_new_buffering (GST_OBJECT_CAST (play_base_bin), percent)); +} + +static gboolean +check_queue_event (GstPad * pad, GstEvent * event, gpointer user_data) +{ + GstElement *queue = GST_ELEMENT_CAST (user_data); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_DEBUG ("EOS event, mark EOS"); + g_object_set_data (G_OBJECT (queue), "eos", GINT_TO_POINTER (1)); + break; + case GST_EVENT_FLUSH_STOP: + GST_DEBUG ("FLUSH_STOP event, remove EOS"); + g_object_set_data (G_OBJECT (queue), "eos", NULL); + break; + default: + GST_DEBUG ("uninteresting event %s", GST_EVENT_TYPE_NAME (event)); + break; + } + return TRUE; +} + +static gboolean +check_queue (GstPad * pad, GstBuffer * data, gpointer user_data) +{ + GstElement *queue = GST_ELEMENT_CAST (user_data); + GstPlayBaseBin *play_base_bin = g_object_get_data (G_OBJECT (queue), "pbb"); + guint64 level = 0; + + GST_DEBUG_OBJECT (queue, "check queue triggered"); + + g_object_get (G_OBJECT (queue), "current-level-time", &level, NULL); + GST_DEBUG_OBJECT (play_base_bin, "Queue size: %" GST_TIME_FORMAT, + GST_TIME_ARGS (level)); + + if (play_base_bin->queue_threshold > 0) { + level = level * 99 / play_base_bin->queue_threshold; + if (level > 99) + level = 99; + } else + level = 99; + + fill_buffer (play_base_bin, level); + + /* continue! */ + return TRUE; +} + +/* If a queue overruns and we are buffer in streaming mode (we have a min-time) + * we can potentially create a deadlock when: + * + * 1) the max-bytes is hit and + * 2) the min-time is not hit. + * + * We recover from this situation in this callback by + * setting the max-bytes to unlimited if we see that there is + * a current-time-level (which means some sort of timestamping is + * done). + */ +static void +queue_deadlock_check (GstElement * queue, GstPlayBaseBin * play_base_bin) +{ + guint64 time, min_time; + guint bytes; + + GST_DEBUG_OBJECT (play_base_bin, "overrun signal received from queue %s", + GST_ELEMENT_NAME (queue)); + + /* figure out where we are */ + g_object_get (G_OBJECT (queue), "current-level-time", &time, + "current-level-bytes", &bytes, "min-threshold-time", &min_time, NULL); + + GST_DEBUG_OBJECT (play_base_bin, "streaming mode, queue %s current %" + GST_TIME_FORMAT ", min %" GST_TIME_FORMAT + ", bytes %d", GST_ELEMENT_NAME (queue), + GST_TIME_ARGS (time), GST_TIME_ARGS (min_time), bytes); + + /* if the bytes in the queue represent time, we disable bytes + * overrun checking to not cause deadlocks. + */ + if (bytes && time != 0 && time < min_time) { + GST_DEBUG_OBJECT (play_base_bin, + "possible deadlock found, removing byte limit"); + + /* queue knows about time but is filled with bytes that do + * not represent min-threshold time, disable bytes checking so + * the queue can grow some more. */ + g_object_set (G_OBJECT (queue), "max-size-bytes", 0, NULL); + + /* bytes limit is removed, we cannot deadlock anymore */ + g_signal_handlers_disconnect_by_func (queue, + (gpointer) queue_deadlock_check, play_base_bin); + } else { + GST_DEBUG_OBJECT (play_base_bin, "no deadlock"); + } +} + +static void +queue_remove_probe (GstElement * queue, GstPlayBaseBin * play_base_bin) +{ + gpointer data; + GstPad *sinkpad; + + data = g_object_get_data (G_OBJECT (queue), "probe"); + sinkpad = gst_element_get_static_pad (queue, "sink"); + + if (data) { + GST_DEBUG_OBJECT (play_base_bin, + "Removing buffer probe from pad %s:%s (%p)", + GST_DEBUG_PAD_NAME (sinkpad), sinkpad); + + g_object_set_data (G_OBJECT (queue), "probe", NULL); + gst_pad_remove_buffer_probe (sinkpad, GPOINTER_TO_INT (data)); + } else { + GST_DEBUG_OBJECT (play_base_bin, + "No buffer probe to remove from %s:%s (%p)", + GST_DEBUG_PAD_NAME (sinkpad), sinkpad); + } + gst_object_unref (sinkpad); +} + +/* Used for time-based buffering in streaming mode and is called when a queue + * emits the running signal. This means that the high watermark threshold is + * reached and the buffering is completed. */ +static void +queue_threshold_reached (GstElement * queue, GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group; + gint n; + + GST_DEBUG_OBJECT (play_base_bin, "running signal received from queue %s", + GST_ELEMENT_NAME (queue)); + + /* we disconnect the signal so that we don't get called for every buffer. */ + g_signal_handlers_disconnect_by_func (queue, + (gpointer) queue_threshold_reached, play_base_bin); + + if (g_object_get_data (G_OBJECT (queue), "eos")) { + GST_DEBUG_OBJECT (play_base_bin, "disable min threshold time, we are EOS"); + g_object_set (queue, "min-threshold-time", (guint64) 0, NULL); + } else { + /* now place the limits at the low threshold. When we hit this limit, the + * underrun signal will be called. The underrun signal is always connected. */ + GST_DEBUG_OBJECT (play_base_bin, + "setting min threshold time to %" G_GUINT64_FORMAT, + play_base_bin->queue_min_threshold); + g_object_set (queue, "min-threshold-time", + play_base_bin->queue_min_threshold, NULL); + } + + GROUP_LOCK (play_base_bin); + group = get_active_group (play_base_bin); + if (!group) { + GROUP_UNLOCK (play_base_bin); + return; + } + + /* we remove the probe now because we don't need it anymore to give progress + * about the buffering. */ + for (n = 0; n < NUM_TYPES; n++) { + GstElement *element = group->type[n].preroll; + + if (!element) + continue; + + queue_remove_probe (element, play_base_bin); + } + + GROUP_UNLOCK (play_base_bin); + + /* we post a 100% buffering message to notify the app that buffering is + * completed and playback can start/continue */ + if (play_base_bin->is_stream) + fill_buffer (play_base_bin, 100); +} + +/* this signal will be fired when one of the queues with raw + * data is filled. This means that the group building stage is over + * and playback of the new queued group should start. This is a rather unusual + * situation because normally the group is commited when the "no_more_pads" + * signal is fired. + */ +static void +queue_overrun (GstElement * queue, GstPlayBaseBin * play_base_bin) +{ + GST_DEBUG_OBJECT (play_base_bin, "queue %s overrun", + GST_ELEMENT_NAME (queue)); + + preroll_remove_overrun (queue, play_base_bin); + + group_commit (play_base_bin, FALSE, + GST_OBJECT_PARENT (GST_OBJECT_CAST (queue)) == + GST_OBJECT_CAST (play_base_bin->subtitle)); + + /* notify end of buffering */ + queue_threshold_reached (queue, play_base_bin); +} + +/* this signal is only added when in streaming mode to catch underruns + */ +static void +queue_out_of_data (GstElement * queue, GstPlayBaseBin * play_base_bin) +{ + GST_DEBUG_OBJECT (play_base_bin, "underrun signal received from queue %s", + GST_ELEMENT_NAME (queue)); + + /* On underrun, we want to temoprarily pause playback, set a "min-size" + * threshold and wait for the running signal and then play again. + * + * This signal could never be called because the queue max-size limits are set + * too low. We take care of this possible deadlock in the the overrun signal + * handler. */ + g_signal_connect (G_OBJECT (queue), "pushing", + G_CALLBACK (queue_threshold_reached), play_base_bin); + GST_DEBUG_OBJECT (play_base_bin, + "setting min threshold time to %" G_GUINT64_FORMAT, + (guint64) play_base_bin->queue_threshold); + g_object_set (queue, "min-threshold-time", + (guint64) play_base_bin->queue_threshold, NULL); + + /* re-connect probe, this will fire feedback about the percentage that we + * buffered and is posted in the BUFFERING message. */ + if (!g_object_get_data (G_OBJECT (queue), "probe")) { + GstPad *sinkpad; + guint id; + + sinkpad = gst_element_get_static_pad (queue, "sink"); + id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), queue); + g_object_set_data (G_OBJECT (queue), "probe", GINT_TO_POINTER (id)); + GST_DEBUG_OBJECT (play_base_bin, + "Re-attaching buffering probe to pad %s:%s %p", + GST_DEBUG_PAD_NAME (sinkpad), sinkpad); + gst_object_unref (sinkpad); + + fill_buffer (play_base_bin, 0); + } +} + +/* + * generate a preroll element which is simply a queue. While there + * are still dynamic elements in the pipeline, we wait for one + * of the queues to fill. The assumption is that all the dynamic + * streams will be detected by that time. + * + * Callers must have the group-lock held when calling this. + */ +static void +gen_preroll_element (GstPlayBaseBin * play_base_bin, + GstPlayBaseGroup * group, GstStreamType type, GstPad * pad, + GstStreamInfo * info) +{ + GstElement *selector, *preroll; + gchar *name, *padname; + const gchar *prename; + guint overrun_sig; + GstPad *preroll_pad; + GstBin *target; + GstState state; + + if (type == GST_STREAM_TYPE_VIDEO) + prename = "video"; + else if (type == GST_STREAM_TYPE_TEXT) + prename = "text"; + else if (type == GST_STREAM_TYPE_AUDIO) + prename = "audio"; + else if (type == GST_STREAM_TYPE_SUBPICTURE) + prename = "subpicture"; + else + g_return_if_reached (); + + /* create stream selector */ + selector = g_object_new (GST_TYPE_STREAM_SELECTOR, NULL); + padname = gst_pad_get_name (pad); + name = g_strdup_printf ("selector_%s_%s", prename, padname); + gst_object_set_name (GST_OBJECT_CAST (selector), name); + g_free (name); + + /* create preroll queue */ + name = g_strdup_printf ("preroll_%s_%s", prename, padname); + preroll = gst_element_factory_make ("queue", name); + g_free (name); + g_free (padname); + + /* for buffering of raw data we ideally want to buffer a + * very small amount of buffers since the memory used by + * this raw data can be enormously huge. + * + * We use an upper limit of typically a few seconds here but + * cap in case no timestamps are set on the raw data (bad!). + * + * FIXME: we abuse this buffer to do network buffering since + * we can then easily do time-based buffering. The better + * solution would be to add a specific network queue right + * after the source that measures the datarate and scales this + * queue of encoded data instead. + */ + if (play_base_bin->raw_decoding_mode) { + if (type == GST_STREAM_TYPE_VIDEO) { + g_object_set (G_OBJECT (preroll), + "max-size-buffers", 2, "max-size-bytes", 0, + "max-size-time", (guint64) 0, NULL); + } else { + g_object_set (G_OBJECT (preroll), + "max-size-buffers", 0, "max-size-bytes", + 2 * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL); + } + } else { + g_object_set (G_OBJECT (preroll), + "max-size-buffers", 0, "max-size-bytes", + ((type == GST_STREAM_TYPE_VIDEO) ? 25 : 2) * 1024 * 1024, + "max-size-time", play_base_bin->queue_size, NULL); + } + + /* the overrun signal is always attached and serves two purposes: + * + * 1) when we are building a group and the overrun is called, we commit the + * group. The reason being that if we fill the entire queue without a + * normal group commit (with _no_more_pads()) we can assume the + * audio/video is completely wacked or the element just does not know when + * it is ready with all the pads (mpeg). + * 2) When we are doing network buffering, we keep track of low/high + * watermarks in the queue. It is possible that we set the high watermark + * higher than the max-size limits to trigger an overrun. In this case we + * will never get a running signal but we can use the overrun signal to + * detect this deadlock and correct it. + */ + overrun_sig = g_signal_connect (G_OBJECT (preroll), "overrun", + G_CALLBACK (queue_overrun), play_base_bin); + + /* keep a ref to the signal id so that we can disconnect the signal callback + * when we are done with the preroll */ + g_object_set_data (G_OBJECT (preroll), "overrun_signal_id", + GINT_TO_POINTER (overrun_sig)); + + if (play_base_bin->is_stream && + ((type == GST_STREAM_TYPE_VIDEO && + group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) || + (type == GST_STREAM_TYPE_AUDIO && + group->type[GST_STREAM_TYPE_VIDEO - 1].npads == 0))) { + GstPad *sinkpad; + guint id; + + /* catch deadlocks when we are network buffering in time but the max-limit + * in bytes is hit. */ + g_signal_connect (G_OBJECT (preroll), "overrun", + G_CALLBACK (queue_deadlock_check), play_base_bin); + + /* attach pointer to playbasebin */ + g_object_set_data (G_OBJECT (preroll), "pbb", play_base_bin); + + /* give updates on queue size */ + sinkpad = gst_element_get_static_pad (preroll, "sink"); + id = gst_pad_add_buffer_probe (sinkpad, G_CALLBACK (check_queue), preroll); + GST_DEBUG_OBJECT (play_base_bin, "Attaching probe to pad %s:%s (%p)", + GST_DEBUG_PAD_NAME (sinkpad), sinkpad); + g_object_set_data (G_OBJECT (preroll), "probe", GINT_TO_POINTER (id)); + + /* catch eos and flush events so that we can ignore underruns */ + id = gst_pad_add_event_probe (sinkpad, G_CALLBACK (check_queue_event), + preroll); + g_object_set_data (G_OBJECT (preroll), "eos_probe", GINT_TO_POINTER (id)); + + gst_object_unref (sinkpad); + + /* When we connect this queue, it will start running and immediatly + * fire an underrun. */ + g_signal_connect (G_OBJECT (preroll), "underrun", + G_CALLBACK (queue_out_of_data), play_base_bin); + /* configure threshold and callbacks */ + queue_out_of_data (preroll, play_base_bin); + } + + /* listen for EOS so we can switch groups when one ended. */ + preroll_pad = gst_element_get_static_pad (preroll, "src"); + gst_pad_add_event_probe (preroll_pad, G_CALLBACK (probe_triggered), info); + gst_object_unref (preroll_pad); + + /* add to group list */ + group->type[type - 1].selector = selector; + group->type[type - 1].preroll = preroll; + + /* figure out where the preroll element should go */ + if (type == GST_STREAM_TYPE_TEXT && play_base_bin->subtitle) + target = GST_BIN_CAST (play_base_bin->subtitle); + else + target = GST_BIN_CAST (play_base_bin); + + group->type[type - 1].bin = target; + gst_bin_add (target, selector); + gst_bin_add (target, preroll); + + gst_element_link (selector, preroll); + + /* figure out target state and set */ + state = (GST_STATE (play_base_bin) == GST_STATE_PLAYING ? + GST_STATE_PLAYING : GST_STATE_PAUSED); + + gst_element_set_state (selector, state); + gst_element_set_state (preroll, state); +} + +static void +preroll_remove_overrun (GstElement * element, GstPlayBaseBin * play_base_bin) +{ + guint overrun_sig; + GObject *obj = G_OBJECT (element); + + overrun_sig = GPOINTER_TO_INT (g_object_get_data (obj, "overrun_signal_id")); + if (overrun_sig) { + GST_LOG_OBJECT (play_base_bin, "removing preroll signal %s", + GST_ELEMENT_NAME (element)); + g_signal_handler_disconnect (obj, overrun_sig); + /* We have disconnected this signal, remove the signal_id from the object + * data */ + g_object_set_data (obj, "overrun_signal_id", NULL); + } +} + +static void +remove_groups (GstPlayBaseBin * play_base_bin) +{ + GROUP_LOCK (play_base_bin); + + /* first destroy the group we were building if any */ + if (play_base_bin->building_group) { + group_destroy (play_base_bin->building_group); + play_base_bin->building_group = NULL; + } + + /* remove the queued groups */ + g_list_foreach (play_base_bin->queued_groups, (GFunc) group_destroy, NULL); + g_list_free (play_base_bin->queued_groups); + play_base_bin->queued_groups = NULL; + + /* clear subs */ + if (play_base_bin->subtitle) { + gst_element_set_state (play_base_bin->subtitle, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle); + play_base_bin->subtitle = NULL; + } + + GROUP_UNLOCK (play_base_bin); +} + +/* + * Add/remove a single stream to current building group. + * + * Must be called with group-lock held. + */ +static void +add_stream (GstPlayBaseGroup * group, GstStreamInfo * info) +{ + GValue v = { 0, }; + GST_DEBUG ("add stream to group %p", group); + + /* keep ref to the group */ + g_object_set_data (G_OBJECT (info), "group", group); + + g_value_init (&v, G_TYPE_OBJECT); + g_value_set_object (&v, info); + g_value_array_append (group->streaminfo_value_array, &v); + g_value_unset (&v); + group->streaminfo = g_list_append (group->streaminfo, info); + if (info->type > 0 && info->type <= NUM_TYPES) { + group->type[info->type - 1].npads++; + } +} + +static gboolean +string_arr_has_str (const gchar * values[], const gchar * value) +{ + if (values && value) { + while (*values != NULL) { + if (strcmp (value, *values) == 0) + return TRUE; + ++values; + } + } + return FALSE; +} + +/* mime types we are not handling on purpose right now, don't post a + * missing-plugin message for these */ +static const gchar *blacklisted_mimes[] = { + "video/x-dvd-subpicture", NULL +}; + +#define IS_BLACKLISTED_MIME(type) (string_arr_has_str(blacklisted_mimes,type)) + +static void +gst_play_base_bin_handle_message_func (GstBin * bin, GstMessage * msg) +{ + if (gst_is_missing_plugin_message (msg)) { + gchar *detail; + guint i; + + detail = gst_missing_plugin_message_get_installer_detail (msg); + for (i = 0; detail != NULL && blacklisted_mimes[i] != NULL; ++i) { + if (strstr (detail, "|decoder-") && strstr (detail, blacklisted_mimes[i])) { + GST_LOG_OBJECT (bin, "suppressing message %" GST_PTR_FORMAT, msg); + gst_message_unref (msg); + g_free (detail); + return; + } + } + g_free (detail); + } + GST_BIN_CLASS (parent_class)->handle_message (bin, msg); +} + +/* + * signal fired when an unknown stream is found. We create a new + * UNKNOWN streaminfo object. + */ +static void +unknown_type (GstElement * element, GstPad * pad, GstCaps * caps, + GstPlayBaseBin * play_base_bin) +{ + const gchar *type_name; + GstStreamInfo *info; + GstPlayBaseGroup *group; + + type_name = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + if (type_name && !IS_BLACKLISTED_MIME (type_name)) { + gchar *capsstr; + + capsstr = gst_caps_to_string (caps); + GST_DEBUG_OBJECT (play_base_bin, "don't know how to handle %s", capsstr); + /* FIXME, g_message() ? */ + g_message ("don't know how to handle %s", capsstr); + g_free (capsstr); + } else { + /* don't spew stuff to the terminal or send message if it's blacklisted */ + GST_DEBUG_OBJECT (play_base_bin, "media type %s not handled on purpose, " + "not posting a missing-plugin message on the bus", type_name); + } + + GROUP_LOCK (play_base_bin); + + group = get_building_group (play_base_bin); + + /* add the stream to the list */ + info = gst_stream_info_new (GST_OBJECT_CAST (pad), GST_STREAM_TYPE_UNKNOWN, + NULL, caps); + info->origin = GST_OBJECT_CAST (pad); + add_stream (group, info); + + GROUP_UNLOCK (play_base_bin); +} + +/* add a streaminfo that indicates that the stream is handled by the + * given element. This usually means that a stream without actual data is + * produced but one that is sunken by an element. Examples of this are: + * cdaudio, a hardware decoder/sink, dvd meta bins etc... + */ +static void +add_element_stream (GstElement * element, GstPlayBaseBin * play_base_bin) +{ + GstStreamInfo *info; + GstPlayBaseGroup *group; + + GROUP_LOCK (play_base_bin); + + group = get_building_group (play_base_bin); + + /* add the stream to the list */ + info = + gst_stream_info_new (GST_OBJECT_CAST (element), GST_STREAM_TYPE_ELEMENT, + NULL, NULL); + info->origin = GST_OBJECT_CAST (element); + add_stream (group, info); + + GROUP_UNLOCK (play_base_bin); +} + +/* when the decoder element signals that no more pads will be generated, we + * can commit the current group. + */ +static void +no_more_pads_full (GstElement * element, gboolean subs, + GstPlayBaseBin * play_base_bin) +{ + /* setup phase */ + GST_DEBUG_OBJECT (element, "no more pads, %d pending", + play_base_bin->pending); + + /* nothing pending, we can exit */ + if (play_base_bin->pending == 0) + return; + + /* the object has no pending no_more_pads */ + if (!g_object_get_data (G_OBJECT (element), "pending")) + return; + + g_object_set_data (G_OBJECT (element), "pending", NULL); + + play_base_bin->pending--; + + GST_DEBUG_OBJECT (element, "remove pending, now %d pending", + play_base_bin->pending); + + if (play_base_bin->pending == 0) { + /* we can commit this group for playback now */ + group_commit (play_base_bin, play_base_bin->is_stream, subs); + } +} + +static void +no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin) +{ + no_more_pads_full (element, FALSE, play_base_bin); +} + +static void +sub_no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin) +{ + no_more_pads_full (element, TRUE, play_base_bin); +} + +static void +source_no_more_pads (GstElement * element, GstPlayBaseBin * bin) +{ + GST_DEBUG_OBJECT (bin, "No more pads in source element %s.", + GST_ELEMENT_NAME (element)); + + g_signal_handler_disconnect (G_OBJECT (element), bin->src_np_sig_id); + bin->src_np_sig_id = 0; + g_signal_handler_disconnect (G_OBJECT (element), bin->src_nmp_sig_id); + bin->src_nmp_sig_id = 0; + + no_more_pads_full (element, FALSE, bin); +} + +static gboolean +probe_triggered (GstPad * pad, GstEvent * event, gpointer user_data) +{ + GstPlayBaseGroup *group; + GstPlayBaseBin *play_base_bin; + GstStreamInfo *info; + GstEventType type; + + type = GST_EVENT_TYPE (event); + + GST_LOG ("probe triggered, (%d) %s", type, gst_event_type_get_name (type)); + + /* we only care about EOS */ + if (type != GST_EVENT_EOS) + return TRUE; + + info = GST_STREAM_INFO (user_data); + group = (GstPlayBaseGroup *) g_object_get_data (G_OBJECT (info), "group"); + play_base_bin = group->bin; + + if (type == GST_EVENT_EOS) { + gint num_groups = 0; + gboolean have_left; + + GST_DEBUG_OBJECT (play_base_bin, "probe got EOS in group %p", group); + + GROUP_LOCK (play_base_bin); + + /* mute this stream */ + g_object_set (G_OBJECT (info), "mute", TRUE, NULL); + if (info->type > 0 && info->type <= NUM_TYPES) + group->type[info->type - 1].done = TRUE; + + /* see if we have some more groups left to play */ + num_groups = g_list_length (play_base_bin->queued_groups); + if (play_base_bin->building_group) + num_groups++; + have_left = (num_groups > 1); + + /* see if the complete group is muted */ + if (!group_is_muted (group)) { + /* group is not completely muted, we remove the EOS event + * and continue, eventually the other streams will be EOSed and + * we can switch out this group. */ + GST_DEBUG ("group %p not completely muted", group); + + GROUP_UNLOCK (play_base_bin); + + /* remove the EOS if we have something left */ + return !have_left; + } + + if (have_left) { + /* ok, get rid of the current group then */ + //group_destroy (group); + /* removing the current group brings the next group + * active */ + play_base_bin->queued_groups = + g_list_remove (play_base_bin->queued_groups, group); + /* and wait for the next one to be ready */ + while (!play_base_bin->queued_groups) { + GROUP_WAIT (play_base_bin); + } + group = play_base_bin->queued_groups->data; + + /* now activate the next one */ + setup_substreams (play_base_bin); + GST_DEBUG ("switching to next group %p - emitting signal", group); + /* and signal the new group */ + GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin)->setup_output_pads + (play_base_bin, group); + + GROUP_UNLOCK (play_base_bin); + + g_object_notify (G_OBJECT (play_base_bin), "stream-info"); + + /* get rid of the EOS event */ + return FALSE; + } else { + GROUP_UNLOCK (play_base_bin); + GST_LOG ("Last group done, EOS"); + } + } + + return TRUE; +} + +/* This function will be called when the sinkpad of the preroll element + * is unlinked, we have to connect something to the sinkpad or else the + * state change will fail.. + */ +static void +preroll_unlinked (GstPad * pad, GstPad * peerpad, + GstPlayBaseBin * play_base_bin) +{ + GstElement *fakesrc; + guint sig_id; + GstPad *srcpad; + + /* make a fakesrc that will just emit one EOS */ + fakesrc = gst_element_factory_make ("fakesrc", NULL); + g_object_set (G_OBJECT (fakesrc), "num-buffers", 0, NULL); + + GST_DEBUG ("patching unlinked pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + srcpad = gst_element_get_static_pad (fakesrc, "src"); + gst_bin_add (GST_BIN_CAST (play_base_bin), fakesrc); + gst_pad_link (srcpad, pad); + gst_object_unref (srcpad); + + /* keep track of these patch elements */ + g_object_set_data (G_OBJECT (pad), "fakesrc", fakesrc); + + /* now unlink the unlinked signal so that it is not called again when + * we destroy the queue */ + sig_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "unlinked_id")); + if (sig_id != 0) { + g_signal_handler_disconnect (G_OBJECT (pad), sig_id); + g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (0)); + } +} + +/* Mute stream on first data - for header-is-in-stream-stuff + * (vorbis, ogmtext). */ +static gboolean +mute_stream (GstPad * pad, GstBuffer * buf, gpointer data) +{ + GstStreamInfo *info = GST_STREAM_INFO (data); + guint id; + + GST_DEBUG ("mute stream triggered"); + + g_object_set (G_OBJECT (info), "mute", TRUE, NULL); + id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), "mute_probe")); + g_object_set_data (G_OBJECT (info), "mute_probe", NULL); + if (id > 0) + gst_pad_remove_buffer_probe (GST_PAD_CAST (info->object), id); + + /* no data */ + return FALSE; +} + +/* Eat data. */ +static gboolean +silence_stream (GstPad * pad, GstMiniObject * data, gpointer user_data) +{ + GST_DEBUG ("silence stream triggered"); + + /* no data */ + return FALSE; +} + +/* Called by the signal handlers when a decodebin (main or subtitle) has + * found a new raw pad. We create a preroll element if needed and the + * appropriate streaminfo. Commits the group if there will be no more pads + * from decodebin */ +static void +new_decoded_pad_full (GstElement * element, GstPad * pad, gboolean last, + GstPlayBaseBin * play_base_bin, gboolean is_subs) +{ + GstStructure *structure; + const gchar *mimetype; + GstCaps *caps; + GstStreamInfo *info; + GstStreamType type = GST_STREAM_TYPE_UNKNOWN; + GstPad *sinkpad; + GstPlayBaseGroup *group; + guint sig; + GstObject *parent; + gboolean first_pad; + + GST_DEBUG ("play base: new decoded pad. Last: %d", last); + + /* first see if this pad has interesting caps */ + caps = gst_pad_get_caps (pad); + if (caps == NULL || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) + goto no_type; + + /* get the mime type */ + structure = gst_caps_get_structure (caps, 0); + mimetype = gst_structure_get_name (structure); + + GROUP_LOCK (play_base_bin); + + group = get_building_group (play_base_bin); + + group->nstreams++; + + parent = gst_object_get_parent (GST_OBJECT_CAST (element)); + if (g_str_has_prefix (mimetype, "audio/") && + parent != GST_OBJECT_CAST (play_base_bin->subtitle)) { + type = GST_STREAM_TYPE_AUDIO; + } else if (g_str_has_prefix (mimetype, "video/x-dvd-subpicture") && + parent != GST_OBJECT_CAST (play_base_bin->subtitle)) { + type = GST_STREAM_TYPE_SUBPICTURE; + } else if (g_str_has_prefix (mimetype, "video/") && + parent != GST_OBJECT_CAST (play_base_bin->subtitle)) { + type = GST_STREAM_TYPE_VIDEO; + } else if (g_str_has_prefix (mimetype, "text/")) { + type = GST_STREAM_TYPE_TEXT; + } + gst_object_unref (parent); + + info = gst_stream_info_new (GST_OBJECT_CAST (pad), type, NULL, caps); + gst_caps_unref (caps); + + if (type == GST_STREAM_TYPE_UNKNOWN) { + /* Unknown streams get added to the group, but the data + * just gets ignored */ + add_stream (group, info); + + GROUP_UNLOCK (play_base_bin); + + /* signal the no more pads after adding the stream */ + if (last) + no_more_pads_full (element, is_subs, play_base_bin); + + return; + } + + /* first pad of each type gets a selector + preroll queue */ + first_pad = (group->type[type - 1].npads == 0); + + if (first_pad) { + GST_DEBUG ("play base: pad needs new preroll"); + gen_preroll_element (play_base_bin, group, type, pad, info); + } + + /* add to stream selector */ + sinkpad = + gst_element_get_request_pad (group->type[type - 1].selector, "sink%d"); + + /* make sure we catch unlink signals */ + sig = g_signal_connect (G_OBJECT (sinkpad), "unlinked", + G_CALLBACK (preroll_unlinked), play_base_bin); + /* keep a ref to the signal id so that we can disconnect the signal callback */ + g_object_set_data (G_OBJECT (sinkpad), "unlinked_id", GINT_TO_POINTER (sig)); + /* Store a pointer to the stream selector pad for this stream */ + g_object_set_data (G_OBJECT (pad), "pb_sel_pad", sinkpad); + + gst_pad_link (pad, sinkpad); + gst_object_unref (sinkpad); + + /* select 1st for now - we'll select a preferred one after preroll */ + if (!first_pad) { + guint id; + + GST_DEBUG ("Adding silence_stream data probe on type %d (npads %d)", type, + group->type[type - 1].npads); + + id = gst_pad_add_data_probe (GST_PAD_CAST (pad), + G_CALLBACK (silence_stream), info); + g_object_set_data (G_OBJECT (pad), "eat_probe", GINT_TO_POINTER (id)); + } + + /* add the stream to the list */ + add_stream (group, info); + + GROUP_UNLOCK (play_base_bin); + + /* signal the no more pads after adding the stream */ + if (last) + no_more_pads_full (element, is_subs, play_base_bin); + + return; + + /* ERRORS */ +no_type: + { + g_warning ("no type on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + if (caps) + gst_caps_unref (caps); + return; + } +} + +static void +new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, + GstPlayBaseBin * play_base_bin) +{ + new_decoded_pad_full (element, pad, last, play_base_bin, FALSE); +} + +static void +subs_new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, + GstPlayBaseBin * play_base_bin) +{ + new_decoded_pad_full (element, pad, last, play_base_bin, TRUE); +} + +static void +set_encoding_element (GstElement * element, gchar * encoding) +{ + GST_DEBUG_OBJECT (element, "setting encoding to %s", GST_STR_NULL (encoding)); + g_object_set (G_OBJECT (element), "subtitle-encoding", encoding, NULL); +} + + +static void +decodebin_element_added_cb (GstBin * decodebin, GstElement * element, + gpointer data) +{ + GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data); + gchar *encoding; + + if (!g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "subtitle-encoding")) { + return; + } + + g_mutex_lock (play_base_bin->sub_lock); + play_base_bin->subtitle_elements = + g_slist_append (play_base_bin->subtitle_elements, element); + encoding = g_strdup (play_base_bin->subencoding); + g_mutex_unlock (play_base_bin->sub_lock); + + set_encoding_element (element, encoding); + g_free (encoding); +} + +static void +decodebin_element_removed_cb (GstBin * decodebin, GstElement * element, + gpointer data) +{ + GstPlayBaseBin *play_base_bin = GST_PLAY_BASE_BIN (data); + + g_mutex_lock (play_base_bin->sub_lock); + play_base_bin->subtitle_elements = + g_slist_remove (play_base_bin->subtitle_elements, element); + g_mutex_unlock (play_base_bin->sub_lock); +} + + +/* + * Generate source ! subparse bins. + */ + +static GstElement * +setup_subtitle (GstPlayBaseBin * play_base_bin, gchar * sub_uri) +{ + GstElement *source, *subdecodebin, *subbin; + + if (!gst_uri_is_valid (sub_uri)) + goto invalid_uri; + + source = gst_element_make_from_uri (GST_URI_SRC, sub_uri, NULL); + if (!source) + goto unknown_uri; + + if (g_getenv ("USE_DECODEBIN2")) + subdecodebin = gst_element_factory_make ("decodebin2", "subtitle-decoder"); + else + subdecodebin = gst_element_factory_make ("decodebin", "subtitle-decoder"); + g_signal_connect (subdecodebin, "element-added", + G_CALLBACK (decodebin_element_added_cb), play_base_bin); + g_signal_connect (subdecodebin, "element-removed", + G_CALLBACK (decodebin_element_removed_cb), play_base_bin); + subbin = gst_bin_new ("subtitle-bin"); + gst_bin_add_many (GST_BIN_CAST (subbin), source, subdecodebin, NULL); + + gst_element_link (source, subdecodebin); + + /* return the subtitle GstElement object */ + return subbin; + + /* WARNINGS */ +invalid_uri: + { + GST_ELEMENT_WARNING (play_base_bin, RESOURCE, NOT_FOUND, + (_("Invalid subtitle URI \"%s\", subtitles disabled."), sub_uri), + (NULL)); + return NULL; + } +unknown_uri: + { + gchar *prot = gst_uri_get_protocol (sub_uri); + + if (prot) { + gchar *desc; + + gst_element_post_message (GST_ELEMENT (play_base_bin), + gst_missing_uri_source_message_new (GST_ELEMENT (play_base_bin), + prot)); + + desc = gst_pb_utils_get_source_description (prot); + GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN, + (_("A %s plugin is required to play this stream, but not installed."), + desc), ("No URI handler to handle sub_uri: %s", sub_uri)); + g_free (desc); + g_free (prot); + } else + goto invalid_uri; + + return NULL; + } +} + +/* helper function to lookup stuff in lists */ +static gboolean +array_has_value (const gchar * values[], const gchar * value) +{ + gint i; + + for (i = 0; values[i]; i++) { + if (g_str_has_prefix (value, values[i])) + return TRUE; + } + return FALSE; +} + +/* list of URIs that we consider to be streams and that need buffering. + * We have no mechanism yet to figure this out with a query. */ +static const gchar *stream_uris[] = { "http://", "mms://", "mmsh://", + "mmsu://", "mmst://", "myth://", NULL +}; + +/* blacklisted URIs, we know they will always fail. */ +static const gchar *blacklisted_uris[] = { NULL }; + +/* mime types that we don't consider to be media types */ +static const gchar *no_media_mimes[] = { + "application/x-executable", "application/x-bzip", "application/x-gzip", + "application/zip", "application/x-compress", NULL +}; + +/* mime types we consider raw media */ +static const gchar *raw_mimes[] = { + "audio/x-raw", "video/x-raw", "video/x-dvd-subpicture", NULL +}; + +#define IS_STREAM_URI(uri) (array_has_value (stream_uris, uri)) +#define IS_BLACKLISTED_URI(uri) (array_has_value (blacklisted_uris, uri)) +#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime)) +#define IS_RAW_MIME(mime) (array_has_value (raw_mimes, mime)) + +/* + * Generate and configure a source element. + */ +static GstElement * +gen_source_element (GstPlayBaseBin * play_base_bin, GstElement ** subbin) +{ + GstElement *source; + + if (!play_base_bin->uri) + goto no_uri; + + if (!gst_uri_is_valid (play_base_bin->uri)) + goto invalid_uri; + + if (IS_BLACKLISTED_URI (play_base_bin->uri)) + goto uri_blacklisted; + + if (play_base_bin->suburi) { + GST_LOG_OBJECT (play_base_bin, "Creating decoder for subtitles URI %s", + play_base_bin->suburi); + /* subtitle specified */ + *subbin = setup_subtitle (play_base_bin, play_base_bin->suburi); + } else { + /* no subtitle specified */ + *subbin = NULL; + } + + source = gst_element_make_from_uri (GST_URI_SRC, play_base_bin->uri, + "source"); + if (!source) + goto no_source; + + play_base_bin->is_stream = IS_STREAM_URI (play_base_bin->uri); + + /* make HTTP sources send extra headers so we get icecast + * metadata in case the stream is an icecast stream */ + if (!strncmp (play_base_bin->uri, "http://", 7) && + g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "iradio-mode")) { + g_object_set (source, "iradio-mode", TRUE, NULL); + } + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "connection-speed")) { + GST_DEBUG_OBJECT (play_base_bin, + "setting connection-speed=%d to source element", + play_base_bin->connection_speed / 1000); + g_object_set (source, "connection-speed", + play_base_bin->connection_speed / 1000, NULL); + } + + return source; + + /* ERRORS */ +no_uri: + { + GST_ELEMENT_ERROR (play_base_bin, RESOURCE, NOT_FOUND, + (_("No URI specified to play from.")), (NULL)); + return NULL; + } +invalid_uri: + { + GST_ELEMENT_ERROR (play_base_bin, RESOURCE, NOT_FOUND, + (_("Invalid URI \"%s\"."), play_base_bin->uri), (NULL)); + return NULL; + } +uri_blacklisted: + { + GST_ELEMENT_ERROR (play_base_bin, RESOURCE, FAILED, + (_("RTSP streams cannot be played yet.")), (NULL)); + return NULL; + } +no_source: + { + gchar *prot = gst_uri_get_protocol (play_base_bin->uri); + + /* whoops, could not create the source element, dig a little deeper to + * figure out what might be wrong. */ + if (prot) { + gchar *desc; + + gst_element_post_message (GST_ELEMENT (play_base_bin), + gst_missing_uri_source_message_new (GST_ELEMENT (play_base_bin), + prot)); + + desc = gst_pb_utils_get_source_description (prot); + GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN, + (_("A %s plugin is required to play this stream, but not installed."), + desc), ("No URI handler for %s", prot)); + g_free (desc); + g_free (prot); + } else + goto invalid_uri; + + return NULL; + } +} + +/* is called when a dynamic source element created a new pad. */ +static void +source_new_pad (GstElement * element, GstPad * pad, GstPlayBaseBin * bin) +{ + GstElement *decoder; + gboolean is_raw; + + GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s", + GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element)); + + /* if this is a pad with all raw caps, we can expose it */ + if (has_all_raw_caps (pad, &is_raw) && is_raw) { + bin->raw_decoding_mode = TRUE; + /* it's all raw, create output pads. */ + new_decoded_pad_full (element, pad, FALSE, bin, FALSE); + return; + } + + /* not raw, create decoder */ + decoder = make_decoder (bin); + if (!decoder) + goto no_decodebin; + + /* and link to decoder */ + if (!gst_element_link (bin->source, decoder)) + goto could_not_link; + + gst_element_set_state (decoder, GST_STATE_PAUSED); + + return; + + /* ERRORS */ +no_decodebin: + { + /* error was posted */ + return; + } +could_not_link: + { + GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, + (NULL), ("Can't link source to decoder element")); + return; + } +} + +/* + * Setup the substreams (is called right after group_commit () when + * loading a new group, or after switching groups). + * + * Should be called with group-lock held. + */ +static void +setup_substreams (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group; + gint n; + const GList *item; + + GST_DEBUG_OBJECT (play_base_bin, "setting up substreams"); + + /* Remove the eat probes */ + group = get_active_group (play_base_bin); + for (item = group->streaminfo; item; item = item->next) { + GstStreamInfo *info = item->data; + gpointer data; + + data = g_object_get_data (G_OBJECT (info->object), "eat_probe"); + if (data) { + gst_pad_remove_data_probe (GST_PAD_CAST (info->object), + GPOINTER_TO_INT (data)); + g_object_set_data (G_OBJECT (info->object), "eat_probe", NULL); + } + + /* now remove unknown pads */ + if (info->type == GST_STREAM_TYPE_UNKNOWN) { + guint id; + + id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (info), "mute_probe")); + if (id == 0) { + id = gst_pad_add_buffer_probe (GST_PAD_CAST (info->object), + G_CALLBACK (mute_stream), info); + g_object_set_data (G_OBJECT (info), "mute_probe", GINT_TO_POINTER (id)); + } + } + } + + /* now check if the requested current streams exist. If + * current >= num_streams, decrease current so at least + * we have output. Always keep it enabled. */ + for (n = 0; n < NUM_TYPES; n++) { + if (play_base_bin->current[n] >= group->type[n].npads) { + GST_DEBUG_OBJECT (play_base_bin, "reset type %d to current 0", n); + play_base_bin->current[n] = 0; + } + } + + /* now activate the right sources. Don't forget that during preroll, + * we set the first source to forwarding and ignored the rest. */ + for (n = 0; n < NUM_TYPES; n++) { + GST_DEBUG_OBJECT (play_base_bin, "setting type %d to current %d", n, + play_base_bin->current[n]); + set_active_source (play_base_bin, n + 1, play_base_bin->current[n]); + } +} + +/** + * has_all_raw_caps: + * @pad: a #GstPad + * @all_raw: pointer to hold the result + * + * check if the caps of the pad are all raw. The caps are all raw if + * all of its structures contain audio/x-raw or video/x-raw. + * + * Returns: %FALSE @pad has no caps. Else TRUE and @all_raw set t the result. + */ +static gboolean +has_all_raw_caps (GstPad * pad, gboolean * all_raw) +{ + GstCaps *caps; + gint capssize; + guint i, num_raw = 0; + gboolean res = FALSE; + + caps = gst_pad_get_caps (pad); + if (caps == NULL) + return FALSE; + + capssize = gst_caps_get_size (caps); + /* no caps, skip and move to the next pad */ + if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) + goto done; + + /* count the number of raw formats in the caps */ + for (i = 0; i < capssize; ++i) { + GstStructure *s; + const gchar *mime_type; + + s = gst_caps_get_structure (caps, i); + mime_type = gst_structure_get_name (s); + + if (IS_RAW_MIME (mime_type)) + ++num_raw; + } + + *all_raw = (num_raw == capssize); + res = TRUE; + +done: + gst_caps_unref (caps); + return res; +} + +/** + * analyse_source: + * @play_base_bin: a #GstPlayBaseBin + * @is_raw: are all pads raw data + * @have_out: does the source have output + * @is_dynamic: is this a dynamic source + * + * Check the source of @play_base_bin and collect information about it. + * + * @is_raw will be set to TRUE if the source only produces raw pads. When this + * function returns, all of the raw pad of the source will be added + * to @play_base_bin. + * + * @have_out: will be set to TRUE if the source has output pads. + * + * @is_dynamic: TRUE if the element will create (more) pads dynamically later + * on. + * + * Returns: FALSE if a fatal error occured while scanning. + */ +static gboolean +analyse_source (GstPlayBaseBin * play_base_bin, gboolean * is_raw, + gboolean * have_out, gboolean * is_dynamic) +{ + GstIterator *pads_iter; + gboolean done = FALSE; + gboolean res = TRUE; + + *have_out = FALSE; + *is_raw = FALSE; + *is_dynamic = FALSE; + + pads_iter = gst_element_iterate_src_pads (play_base_bin->source); + while (!done) { + GstPad *pad = NULL; + + switch (gst_iterator_next (pads_iter, (gpointer) & pad)) { + case GST_ITERATOR_ERROR: + res = FALSE; + /* FALLTROUGH */ + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + /* reset results and resync */ + *have_out = FALSE; + *is_raw = FALSE; + *is_dynamic = FALSE; + gst_iterator_resync (pads_iter); + break; + case GST_ITERATOR_OK: + /* we now officially have an ouput pad */ + *have_out = TRUE; + + /* if FALSE, this pad has no caps and we continue with the next pad. */ + if (!has_all_raw_caps (pad, is_raw)) { + gst_object_unref (pad); + break; + } + + /* caps on source pad are all raw, we can add the pad */ + if (*is_raw) { + new_decoded_pad_full (play_base_bin->source, pad, FALSE, + play_base_bin, FALSE); + } + + gst_object_unref (pad); + break; + } + } + gst_iterator_free (pads_iter); + + if (!*have_out) { + GstElementClass *elemclass; + GList *walk; + + /* element has no output pads, check for padtemplates that list SOMETIMES + * pads. */ + elemclass = GST_ELEMENT_GET_CLASS (play_base_bin->source); + + walk = gst_element_class_get_pad_template_list (elemclass); + while (walk != NULL) { + GstPadTemplate *templ; + + templ = (GstPadTemplate *) walk->data; + if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { + if (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES) { + *is_dynamic = TRUE; + break; /* only break out if we found a sometimes src pad + continue walking through if say a request src pad is found + elements such as mpegtsparse and dvbbasebin have request + and sometimes src pads */ + } + } + walk = g_list_next (walk); + } + } + + return res; +} + +static void +remove_decoders (GstPlayBaseBin * bin) +{ + GSList *walk; + + for (walk = bin->decoders; walk; walk = g_slist_next (walk)) { + GstElement *decoder = GST_ELEMENT_CAST (walk->data); + + GST_DEBUG_OBJECT (bin, "removing old decoder element"); + /* Disconnect all the signal handlers we attached to the decodebin before + * we dispose of it */ + g_signal_handlers_disconnect_by_func (decoder, + (gpointer) (decodebin_element_added_cb), bin); + g_signal_handlers_disconnect_by_func (decoder, + (gpointer) (decodebin_element_removed_cb), bin); + g_signal_handlers_disconnect_by_func (decoder, + (gpointer) (new_decoded_pad), bin); + g_signal_handlers_disconnect_by_func (decoder, + (gpointer) (no_more_pads), bin); + g_signal_handlers_disconnect_by_func (decoder, + (gpointer) (unknown_type), bin); + + gst_element_set_state (decoder, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), decoder); + } + g_slist_free (bin->decoders); + bin->decoders = NULL; +} + +static GstElement * +make_decoder (GstPlayBaseBin * play_base_bin) +{ + GstElement *decoder; + + /* now create the decoder element */ + if (g_getenv ("USE_DECODEBIN2")) + decoder = gst_element_factory_make ("decodebin2", NULL); + else + decoder = gst_element_factory_make ("decodebin", NULL); + if (!decoder) + goto no_decodebin; + + g_signal_connect (decoder, "element-added", + G_CALLBACK (decodebin_element_added_cb), play_base_bin); + g_signal_connect (decoder, "element-removed", + G_CALLBACK (decodebin_element_removed_cb), play_base_bin); + + gst_bin_add (GST_BIN_CAST (play_base_bin), decoder); + + /* set up callbacks to create the links between decoded data + * and video/audio/subtitle rendering/output. */ + g_signal_connect (G_OBJECT (decoder), + "new-decoded-pad", G_CALLBACK (new_decoded_pad), play_base_bin); + g_signal_connect (G_OBJECT (decoder), "no-more-pads", + G_CALLBACK (no_more_pads), play_base_bin); + g_signal_connect (G_OBJECT (decoder), + "unknown-type", G_CALLBACK (unknown_type), play_base_bin); + g_object_set_data (G_OBJECT (decoder), "pending", GINT_TO_POINTER (1)); + play_base_bin->pending++; + + GST_DEBUG_OBJECT (play_base_bin, "created decodebin, %d pending", + play_base_bin->pending); + + play_base_bin->decoders = g_slist_prepend (play_base_bin->decoders, decoder); + + return decoder; + + /* ERRORS */ +no_decodebin: + { + GST_ELEMENT_ERROR (play_base_bin, CORE, MISSING_PLUGIN, + (_("Could not create \"decodebin\" element.")), (NULL)); + return NULL; + } +} + +static void +remove_source (GstPlayBaseBin * bin) +{ + GstElement *source = bin->source; + + if (source) { + GST_DEBUG_OBJECT (bin, "removing old src element"); + gst_element_set_state (source, GST_STATE_NULL); + + if (bin->src_np_sig_id) { + g_signal_handler_disconnect (G_OBJECT (source), bin->src_np_sig_id); + bin->src_np_sig_id = 0; + } + if (bin->src_nmp_sig_id) { + g_signal_handler_disconnect (G_OBJECT (source), bin->src_nmp_sig_id); + bin->src_nmp_sig_id = 0; + } + gst_bin_remove (GST_BIN_CAST (bin), source); + bin->source = NULL; + } +} + +static GstBusSyncReply +subbin_startup_sync_msg (GstBus * bus, GstMessage * msg, gpointer user_data) +{ + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { + GstPlayBaseBin *play_base_bin; + + play_base_bin = GST_PLAY_BASE_BIN (user_data); + if (!play_base_bin->subtitle_done) { + GST_WARNING_OBJECT (play_base_bin, "error starting up subtitle bin: %" + GST_PTR_FORMAT, msg); + play_base_bin->subtitle_done = TRUE; + GST_DEBUG_OBJECT (play_base_bin, "signal group done"); + GROUP_SIGNAL (play_base_bin); + GST_DEBUG_OBJECT (play_base_bin, "signaled group done"); + } + } + return GST_BUS_PASS; +} + +/* construct and run the source and decoder elements until we found + * all the streams or until a preroll queue has been filled. +*/ +static gboolean +setup_source (GstPlayBaseBin * play_base_bin) +{ + GstElement *subbin = NULL; + gboolean is_raw, have_out, is_dynamic; + + if (!play_base_bin->need_rebuild) + return TRUE; + play_base_bin->raw_decoding_mode = FALSE; + + GST_DEBUG_OBJECT (play_base_bin, "setup source"); + + /* delete old src */ + remove_source (play_base_bin); + + /* create and configure an element that can handle the uri */ + if (!(play_base_bin->source = gen_source_element (play_base_bin, &subbin))) + goto no_source; + + /* state will be merged later - if file is not found, error will be + * handled by the application right after. */ + gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->source); + g_object_notify (G_OBJECT (play_base_bin), "source"); + + /* remove the old decoders now, if any */ + remove_decoders (play_base_bin); + + /* remove our previous preroll queues */ + remove_groups (play_base_bin); + + /* clear pending dynamic elements */ + play_base_bin->pending = 0; + + /* do subs */ + if (subbin) { + GstElement *db; + GstBus *bus; + + play_base_bin->subtitle = subbin; + db = gst_bin_get_by_name (GST_BIN_CAST (subbin), "subtitle-decoder"); + + /* do type detection, without adding (so no preroll) */ + g_signal_connect (G_OBJECT (db), "new-decoded-pad", + G_CALLBACK (subs_new_decoded_pad), play_base_bin); + g_signal_connect (G_OBJECT (db), "no-more-pads", + G_CALLBACK (sub_no_more_pads), play_base_bin); + g_signal_connect (G_OBJECT (db), "unknown-type", + G_CALLBACK (unknown_type), play_base_bin); + g_object_set_data (G_OBJECT (db), "pending", GINT_TO_POINTER (1)); + play_base_bin->pending++; + + GST_DEBUG_OBJECT (play_base_bin, "we have subtitles, %d pending", + play_base_bin->pending); + + if (!play_base_bin->is_stream) { + GstStateChangeReturn sret; + + /* either when the queues are filled or when the decoder element + * has no more dynamic streams, the cond is unlocked. We can remove + * the signal handlers then + */ + GST_DEBUG_OBJECT (play_base_bin, "starting subtitle bin"); + + /* for subtitles in a separate bin we will not commit the + * current building group since we need to add the other + * audio/video streams to the group. We check if we managed + * to commit the subtitle group using an extra flag. */ + play_base_bin->subtitle_done = FALSE; + + /* since subbin is still a stand-alone bin, we need to add a custom bus + * to intercept error messages, so we can stop waiting and continue */ + bus = gst_bus_new (); + gst_element_set_bus (subbin, bus); + gst_bus_set_sync_handler (bus, subbin_startup_sync_msg, play_base_bin); + + sret = gst_element_set_state (subbin, GST_STATE_PAUSED); + if (sret != GST_STATE_CHANGE_FAILURE) { + GROUP_LOCK (play_base_bin); + GST_DEBUG ("waiting for subtitle to complete..."); + while (!play_base_bin->subtitle_done) + GROUP_WAIT (play_base_bin); + GST_DEBUG ("group done !"); + GROUP_UNLOCK (play_base_bin); + + if (!play_base_bin->building_group || + play_base_bin->building_group->type[GST_STREAM_TYPE_TEXT - + 1].npads == 0) { + + GST_DEBUG ("No subtitle found - ignoring"); + gst_element_set_state (subbin, GST_STATE_NULL); + gst_object_unref (play_base_bin->subtitle); + play_base_bin->subtitle = NULL; + } else { + GST_DEBUG_OBJECT (play_base_bin, "Subtitle set-up successful"); + } + } else { + GST_WARNING_OBJECT (play_base_bin, "Failed to start subtitle bin"); + gst_element_set_state (subbin, GST_STATE_NULL); + gst_object_unref (play_base_bin->subtitle); + play_base_bin->subtitle = NULL; + } + + gst_bus_set_sync_handler (bus, NULL, NULL); + gst_element_set_bus (subbin, NULL); + gst_object_unref (bus); + } + gst_object_unref (db); + } + /* see if the source element emits raw audio/video all by itself, + * if so, we can create streams for the pads and be done with it. + * Also check that is has source pads, if not, we assume it will + * do everything itself. */ + if (!analyse_source (play_base_bin, &is_raw, &have_out, &is_dynamic)) + goto invalid_source; + + if (is_raw) { + GST_DEBUG_OBJECT (play_base_bin, "Source provides all raw data"); + /* source provides raw data, we added the pads and we can now signal a + * no_more pads because we are done. */ + group_commit (play_base_bin, play_base_bin->is_stream, FALSE); + return TRUE; + } + if (!have_out && !is_dynamic) { + GST_DEBUG_OBJECT (play_base_bin, "Source has no output pads"); + /* create a stream to indicate that this uri is handled by a self + * contained element. We are now done. */ + add_element_stream (play_base_bin->source, play_base_bin); + group_commit (play_base_bin, play_base_bin->is_stream, FALSE); + return TRUE; + } + if (is_dynamic) { + /* connect a handler for the new-pad signal */ + play_base_bin->src_np_sig_id = + g_signal_connect (G_OBJECT (play_base_bin->source), "pad-added", + G_CALLBACK (source_new_pad), play_base_bin); + play_base_bin->src_nmp_sig_id = + g_signal_connect (G_OBJECT (play_base_bin->source), "no-more-pads", + G_CALLBACK (source_no_more_pads), play_base_bin); + g_object_set_data (G_OBJECT (play_base_bin->source), "pending", + GINT_TO_POINTER (1)); + play_base_bin->pending++; + GST_DEBUG_OBJECT (play_base_bin, + "Source has dynamic output pads, %d pending", play_base_bin->pending); + } else { + GstElement *decoder; + + /* no dynamic source, we can link now */ + decoder = make_decoder (play_base_bin); + if (!decoder) + goto no_decodebin; + + if (!gst_element_link (play_base_bin->source, decoder)) + goto could_not_link; + } + + if (play_base_bin->subtitle) + gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle); + + play_base_bin->need_rebuild = FALSE; + + return TRUE; + + /* ERRORS */ +no_source: + { + /* error message was already posted */ + return FALSE; + } +invalid_source: + { + GST_ELEMENT_ERROR (play_base_bin, CORE, FAILED, + (_("Source element is invalid.")), (NULL)); + return FALSE; + } +no_decodebin: + { + /* message was posted */ + return FALSE; + } +could_not_link: + { + GST_ELEMENT_ERROR (play_base_bin, CORE, NEGOTIATION, + (NULL), ("Can't link source to decoder element")); + return FALSE; + } +} + +static void +finish_source (GstPlayBaseBin * play_base_bin) +{ + /* FIXME: no need to grab the group lock here? (tpm) */ + if (get_active_group (play_base_bin) != NULL) { + if (play_base_bin->subtitle) { + /* make subs iterate from now on */ + gst_bin_add (GST_BIN_CAST (play_base_bin), play_base_bin->subtitle); + } + } +} + +/* + * Caller must have group-lock held. + * + * We iterate over all detected streams in the streaminfo and try to find + * impossible cases, like subtitles without video. + */ +static gboolean +prepare_output (GstPlayBaseBin * play_base_bin) +{ + const GList *item; + gboolean stream_found = FALSE, no_media = FALSE; + gboolean got_video = FALSE, got_subtitle = FALSE; + GstPlayBaseGroup *group; + + group = get_active_group (play_base_bin); + + /* check if we found any supported stream... if not, then + * we detected stream type (or the above would've failed), + * but linking/decoding failed - plugin probably missing. */ + for (item = group ? group->streaminfo : NULL; item != NULL; item = item->next) { + GstStreamInfo *info = GST_STREAM_INFO (item->data); + + if (info->type == GST_STREAM_TYPE_VIDEO) { + stream_found = TRUE; + got_video = TRUE; + break; + } else if (info->type == GST_STREAM_TYPE_ELEMENT) { + stream_found = TRUE; + } else if (info->type == GST_STREAM_TYPE_AUDIO) { + stream_found = TRUE; + } else if (info->type == GST_STREAM_TYPE_TEXT || + info->type == GST_STREAM_TYPE_SUBPICTURE) { + got_subtitle = TRUE; + } else if (!item->prev && !item->next) { + /* We're no audio/video and the only stream... We could + * be something not-media that's detected because then our + * typefind doesn't mess up with mp3 (bz2, gz, elf, ...) */ + if (info->caps && !gst_caps_is_empty (info->caps)) { + const gchar *mime = + gst_structure_get_name (gst_caps_get_structure (info->caps, 0)); + + no_media = IS_NO_MEDIA_MIME (mime); + } + } + } + + if (!stream_found) { + if (got_subtitle) { + GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE, + (_("Only a subtitle stream was detected. " + "Either you are loading a subtitle file or some other type of " + "text file, or the media file was not recognized.")), (NULL)); + } else if (!no_media) { + GST_ELEMENT_ERROR (play_base_bin, STREAM, CODEC_NOT_FOUND, + (_("You do not have a decoder installed to handle this file. " + "You might need to install the necessary plugins.")), (NULL)); + } else { + GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE, + (_("This is not a media file")), (NULL)); + } + return FALSE; + } else if (got_subtitle && !got_video) { + GST_ELEMENT_ERROR (play_base_bin, STREAM, WRONG_TYPE, + (_("A subtitle stream was detected, but no video stream.")), (NULL)); + return FALSE; + } + + return TRUE; +} + +/* + * Multi-stream management. -1 = none. + * + * Caller has group-lock held. + */ +static gint +get_active_source (GstPlayBaseBin * play_base_bin, GstStreamType type) +{ + GstPlayBaseGroup *group; + GList *s; + gint num = 0; + + group = get_active_group (play_base_bin); + if (!group) + return -1; + + for (s = group->streaminfo; s; s = s->next) { + GstStreamInfo *info = s->data; + + if (info->type == type) { + if (!info->mute && !g_object_get_data (G_OBJECT (info), "mute_probe")) { + return num; + } else { + num++; + } + } + } + + return -1; +} + +/* Kill pad reactivation on state change. */ + +#if 0 +static void muted_group_change_state (GstElement * element, + gint old_state, gint new_state, gpointer data); +#endif + +static void +mute_group_type (GstPlayBaseGroup * group, GstStreamType type, gboolean mute) +{ + gboolean active = !mute; + GstPad *pad; + + pad = gst_element_get_static_pad (group->type[type - 1].preroll, "src"); + gst_pad_set_active (pad, active); + gst_object_unref (pad); + pad = gst_element_get_static_pad (group->type[type - 1].preroll, "sink"); + gst_pad_set_active (pad, active); + gst_object_unref (pad); + pad = gst_element_get_static_pad (group->type[type - 1].selector, "src"); + gst_pad_set_active (pad, active); + gst_object_unref (pad); + +#if 0 + if (mute) { + g_signal_connect (group->type[type - 1].preroll, "state-changed", + G_CALLBACK (muted_group_change_state), group); + } else { + g_signal_handlers_disconnect_by_func (group->type[type - 1].preroll, + G_CALLBACK (muted_group_change_state), group); + } +#endif +} + +#if 0 +static void +muted_group_change_state (GstElement * element, + gint old_state, gint new_state, gpointer data) +{ + GstPlayBaseGroup *group = data; + + GROUP_LOCK (group->bin); + + if (new_state == GST_STATE_PLAYING) { + gint n; + + for (n = 0; n < NUM_TYPES; n++) { + if (group->type[n].selector == element) { + mute_group_type (group, n + 1, TRUE); + } + } + } + + GROUP_UNLOCK (group->bin); +} +#endif + +static void +set_subtitles_visible (GstPlayBaseBin * play_base_bin, gboolean visible) +{ + GstPlayBaseBinClass *klass = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin); + + /* we use a vfunc for this since we don't have a reference to the + * textoverlay element, but playbin does */ + if (klass != NULL && klass->set_subtitles_visible != NULL) + klass->set_subtitles_visible (play_base_bin, visible); +} + +static void +set_audio_mute (GstPlayBaseBin * play_base_bin, gboolean mute) +{ + GstPlayBaseBinClass *klass = GST_PLAY_BASE_BIN_GET_CLASS (play_base_bin); + + /* we use a vfunc for this since we don't have a reference to the + * textoverlay element, but playbin does */ + if (klass != NULL && klass->set_audio_mute != NULL) + klass->set_audio_mute (play_base_bin, mute); +} + +/* + * Caller has group-lock held. + */ + +static void +set_active_source (GstPlayBaseBin * play_base_bin, + GstStreamType type, gint source_num) +{ + GstPlayBaseGroup *group; + GList *s; + gint num = 0; + gboolean have_active = FALSE; + GstElement *sel; + + GST_LOG ("Changing active source of type %d to %d", type, source_num); + play_base_bin->current[type - 1] = source_num; + + group = get_active_group (play_base_bin); + if (!group || !group->type[type - 1].preroll) { + GST_LOG ("No active group, or group for type %d has no preroll", type); + return; + } + + /* HACK: instead of unlinking the subtitle input (= lots of hassle, + * especially if subtitles come from an external source), just tell + * textoverlay not to render them */ + if (type == GST_STREAM_TYPE_TEXT) { + gboolean visible = (source_num != -1); + + set_subtitles_visible (play_base_bin, visible); + if (!visible) + return; + } else if (type == GST_STREAM_TYPE_AUDIO) { + gboolean mute = (source_num == -1); + + set_audio_mute (play_base_bin, mute); + + if (mute) + return; + } + + sel = group->type[type - 1].selector; + + for (s = group->streaminfo; s; s = s->next) { + GstStreamInfo *info = s->data; + + if (info->type == type) { + if (num == source_num) { + GstPad *sel_pad; + + GST_LOG ("Unmuting (if already muted) source %d of type %d", source_num, + type); + g_object_set (info, "mute", FALSE, NULL); + + /* Tell the stream selector which pad to accept */ + sel_pad = GST_PAD_CAST (g_object_get_data (G_OBJECT (info->object), + "pb_sel_pad")); + + if (sel && sel_pad != NULL) { + g_object_set (G_OBJECT (sel), "active-pad", sel_pad, NULL); + } + + have_active = TRUE; + } else { + guint id; + + GST_LOG_OBJECT (info->object, "Muting source %d of type %d", num, type); + + id = gst_pad_add_buffer_probe (GST_PAD_CAST (info->object), + G_CALLBACK (mute_stream), info); + g_object_set_data (G_OBJECT (info), "mute_probe", GINT_TO_POINTER (id)); + } + num++; + } + } + + if (!have_active) { + GST_LOG ("Muting group type: %d", type); + g_object_set (sel, "active-pad", NULL, NULL); + } else { + GST_LOG ("Unmuting group type: %d", type); + } + mute_group_type (group, type, !have_active); +} + +static void +gst_play_base_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPlayBaseBin *play_base_bin; + + g_return_if_fail (GST_IS_PLAY_BASE_BIN (object)); + + play_base_bin = GST_PLAY_BASE_BIN (object); + + switch (prop_id) { + case ARG_URI: + { + const gchar *uri = g_value_get_string (value); + + if (uri == NULL) { + g_warning ("cannot set NULL uri"); + return; + } + /* if we have no previous uri, or the new uri is different from the + * old one, replug */ + if (play_base_bin->uri == NULL || strcmp (play_base_bin->uri, uri) != 0) { + g_free (play_base_bin->uri); + play_base_bin->uri = g_strdup (uri); + + GST_DEBUG ("setting new uri to %s", uri); + + play_base_bin->need_rebuild = TRUE; + } + break; + } + case ARG_SUBURI:{ + const gchar *suburi = g_value_get_string (value); + + if ((!suburi && !play_base_bin->suburi) || + (suburi && play_base_bin->suburi && + !strcmp (play_base_bin->suburi, suburi))) + return; + g_free (play_base_bin->suburi); + play_base_bin->suburi = g_strdup (suburi); + GST_DEBUG ("setting new .sub uri to %s", suburi); + play_base_bin->need_rebuild = TRUE; + break; + } + case ARG_QUEUE_SIZE: + play_base_bin->queue_size = g_value_get_uint64 (value); + break; + case ARG_QUEUE_THRESHOLD: + play_base_bin->queue_threshold = g_value_get_uint64 (value); + break; + case ARG_QUEUE_MIN_THRESHOLD: + play_base_bin->queue_min_threshold = g_value_get_uint64 (value); + break; + case ARG_CONNECTION_SPEED: + play_base_bin->connection_speed = g_value_get_uint (value) * 1000; + break; + case ARG_VIDEO: + GROUP_LOCK (play_base_bin); + set_active_source (play_base_bin, + GST_STREAM_TYPE_VIDEO, g_value_get_int (value)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_AUDIO: + GROUP_LOCK (play_base_bin); + set_active_source (play_base_bin, + GST_STREAM_TYPE_AUDIO, g_value_get_int (value)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_TEXT: + GROUP_LOCK (play_base_bin); + set_active_source (play_base_bin, + GST_STREAM_TYPE_TEXT, g_value_get_int (value)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_SUBTITLE_ENCODING: + { + const gchar *encoding; + GSList *list; + + encoding = g_value_get_string (value); + if (encoding && play_base_bin->subencoding && + !strcmp (play_base_bin->subencoding, encoding)) { + return; + } + if (encoding == NULL && play_base_bin->subencoding == NULL) + return; + + g_mutex_lock (play_base_bin->sub_lock); + g_free (play_base_bin->subencoding); + play_base_bin->subencoding = g_strdup (encoding); + list = g_slist_copy (play_base_bin->subtitle_elements); + g_slist_foreach (list, (GFunc) gst_object_ref, NULL); + g_mutex_unlock (play_base_bin->sub_lock); + + /* we can't hold a lock when calling g_object_set() on a child, since + * the notify event will trigger GstObject to send a deep-notify event + * which will try to take the lock ... */ + g_slist_foreach (list, (GFunc) set_encoding_element, (gpointer) encoding); + g_slist_foreach (list, (GFunc) gst_object_unref, NULL); + g_slist_free (list); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstPlayBaseBin *play_base_bin; + + g_return_if_fail (GST_IS_PLAY_BASE_BIN (object)); + + play_base_bin = GST_PLAY_BASE_BIN (object); + + switch (prop_id) { + case ARG_URI: + g_value_set_string (value, play_base_bin->uri); + break; + case ARG_SUBURI: + g_value_set_string (value, play_base_bin->suburi); + break; + case ARG_NSTREAMS: + { + GstPlayBaseGroup *group; + + GROUP_LOCK (play_base_bin); + group = get_active_group (play_base_bin); + if (group) { + g_value_set_int (value, group->nstreams); + } else { + g_value_set_int (value, 0); + } + GROUP_UNLOCK (play_base_bin); + break; + } + case ARG_QUEUE_SIZE: + g_value_set_uint64 (value, play_base_bin->queue_size); + break; + case ARG_QUEUE_THRESHOLD: + g_value_set_uint64 (value, play_base_bin->queue_threshold); + break; + case ARG_QUEUE_MIN_THRESHOLD: + g_value_set_uint64 (value, play_base_bin->queue_min_threshold); + break; + case ARG_CONNECTION_SPEED: + g_value_set_uint (value, play_base_bin->connection_speed / 1000); + break; + case ARG_STREAMINFO: + /* FIXME: hold some kind of lock here, use iterator */ + g_value_set_pointer (value, + (gpointer) gst_play_base_bin_get_streaminfo (play_base_bin)); + break; + case ARG_STREAMINFO_VALUES:{ + GValueArray *copy; + + copy = gst_play_base_bin_get_streaminfo_value_array (play_base_bin); + g_value_take_boxed (value, copy); + break; + } + case ARG_SOURCE: + g_value_set_object (value, play_base_bin->source); + break; + case ARG_VIDEO: + GROUP_LOCK (play_base_bin); + g_value_set_int (value, get_active_source (play_base_bin, + GST_STREAM_TYPE_VIDEO)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_AUDIO: + GROUP_LOCK (play_base_bin); + g_value_set_int (value, get_active_source (play_base_bin, + GST_STREAM_TYPE_AUDIO)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_TEXT: + GROUP_LOCK (play_base_bin); + g_value_set_int (value, get_active_source (play_base_bin, + GST_STREAM_TYPE_TEXT)); + GROUP_UNLOCK (play_base_bin); + break; + case ARG_SUBTITLE_ENCODING: + GST_OBJECT_LOCK (play_base_bin); + g_value_set_string (value, play_base_bin->subencoding); + GST_OBJECT_UNLOCK (play_base_bin); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_play_base_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstPlayBaseBin *play_base_bin; + + play_base_bin = GST_PLAY_BASE_BIN (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!setup_source (play_base_bin)) + goto source_failed; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (ret == GST_STATE_CHANGE_FAILURE) + goto cleanup_groups; + + finish_source (play_base_bin); + break; + /* clean-up in both cases, READY=>NULL clean-up is if there was an error */ + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + play_base_bin->need_rebuild = TRUE; + remove_decoders (play_base_bin); + remove_groups (play_base_bin); + remove_source (play_base_bin); + break; + default: + break; + } + return ret; + + /* ERRORS */ +source_failed: + { + play_base_bin->need_rebuild = TRUE; + + return GST_STATE_CHANGE_FAILURE; + } +cleanup_groups: + { + /* clean up leftover groups */ + remove_groups (play_base_bin); + play_base_bin->need_rebuild = TRUE; + + return GST_STATE_CHANGE_FAILURE; + } +} + +static const GList * +gst_play_base_bin_get_streaminfo (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group = get_active_group (play_base_bin); + GList *info = NULL; + + if (group) { + info = group->streaminfo; + } + return info; +} + +static GValueArray * +gst_play_base_bin_get_streaminfo_value_array (GstPlayBaseBin * play_base_bin) +{ + GstPlayBaseGroup *group; + GValueArray *array = NULL; + + GROUP_LOCK (play_base_bin); + group = get_active_group (play_base_bin); + if (group) { + array = g_value_array_copy (group->streaminfo_value_array); + } else { + array = g_value_array_new (0); + } + GROUP_UNLOCK (play_base_bin); + + return array; +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.h b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.h new file mode 100644 index 0000000..c8c8649 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybasebin.h @@ -0,0 +1,126 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLAYBASEBIN_H__ +#define __GST_PLAYBASEBIN_H__ + +#include +#include "gststreaminfo.h" + +G_BEGIN_DECLS + +#define GST_TYPE_PLAY_BASE_BIN (gst_play_base_bin_get_type()) +#define GST_PLAY_BASE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BASE_BIN,GstPlayBaseBin)) +#define GST_PLAY_BASE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BASE_BIN,GstPlayBaseBinClass)) +#define GST_IS_PLAY_BASE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BASE_BIN)) +#define GST_IS_PLAY_BASE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BASE_BIN)) +#define GST_PLAY_BASE_BIN_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_PLAY_BASE_BIN, \ + GstPlayBaseBinClass)) + +typedef struct _GstPlayBaseBin GstPlayBaseBin; +typedef struct _GstPlayBaseBinClass GstPlayBaseBinClass; + +/* a GstPlayBaseGroup is a group of pads and streaminfo that together + * make up a playable stream. A new group is created from the current + * set of pads that are alive when the preroll elements are filled or + * when the no-more-pads signal is fired. + * + * We have to queue the groups as they can be created while the preroll + * queues are still playing the old group. We monitor the EOS signals + * on the preroll queues and when all the streams in the current group + * have EOSed, we switch to the next queued group. + */ +typedef struct +{ + GstPlayBaseBin *bin; /* ref to the owner */ + + gint nstreams; + GList *streaminfo; + GValueArray *streaminfo_value_array; + + /* contained decoded elementary streams */ + struct { + gint npads; + GstBin *bin; + GstElement *preroll; + GstElement *selector; + gboolean done; +#define NUM_TYPES 4 + } type[NUM_TYPES]; /* AUDIO, VIDEO, TEXT, SUBPIC */ +} GstPlayBaseGroup; + +struct _GstPlayBaseBin { + GstPipeline pipeline; + + /* properties */ + guint64 queue_size; + guint64 queue_threshold; + guint64 queue_min_threshold; + /* connection speed in bits/sec (0 = unknown) */ + guint connection_speed; + + + /* currently loaded media */ + gint current[NUM_TYPES]; + gchar *uri, *suburi; + gboolean is_stream; + GstElement *source; + GSList *decoders; + GstElement *subtitle; /* additional filesrc ! subparse bin */ + gboolean subtitle_done; + gboolean need_rebuild; + gboolean raw_decoding_mode; /* Use smaller queues when source outputs raw data */ + + GSList *subtitle_elements; /* subtitle elements that have 'subtitle-encoding' property */ + gchar *subencoding; /* encoding to propagate to the above subtitle elements */ + GMutex *sub_lock; /* protecting subtitle_elements and subencoding members */ + + /* group management - using own lock */ + GMutex *group_lock; /* lock and mutex to signal availability of new group */ + GCond *group_cond; + GstPlayBaseGroup *building_group; /* the group that we are constructing */ + GList *queued_groups; /* the constructed groups, head is the active one */ + + /* for dynamic sources */ + guint src_np_sig_id; /* new-pad signal id */ + guint src_nmp_sig_id; /* no-more-pads signal id */ + gint pending; +}; + +struct _GstPlayBaseBinClass { + GstPipelineClass parent_class; + + /* virtual fuctions */ + gboolean (*setup_output_pads) (GstPlayBaseBin *play_base_bin, + GstPlayBaseGroup *group); + + void (*set_subtitles_visible) (GstPlayBaseBin *play_base_bin, + gboolean visible); + void (*set_audio_mute) (GstPlayBaseBin *play_base_bin, + gboolean mute); +}; + +GType gst_play_base_bin_get_type (void); + +G_END_DECLS + +#endif /* __GST_PLAYBASEBIN_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin.c new file mode 100644 index 0000000..57b5dbe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin.c @@ -0,0 +1,1990 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-playbin + * + * Playbin provides a stand-alone everything-in-one abstraction for an + * audio and/or video player. + * + * + * This element is deprecated and no longer supported. You should use + * the #playbin2 element instead. + * + * + * It can handle both audio and video files and features + * + * + * automatic file type recognition and based on that automatic + * selection and usage of the right audio/video/subtitle demuxers/decoders + * + * + * visualisations for audio files + * + * + * subtitle support for video files + * + * + * stream selection between different audio/subtitles streams + * + * + * meta info (tag) extraction + * + * + * easy access to the last video frame + * + * + * buffering when playing streams over a network + * + * + * volume control + * + * + * + * + * Usage + * + * A playbin element can be created just like any other element using + * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin:uri + * property. This must be an absolute URI, relative file paths are not allowed. + * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg + * + * Playbin is a #GstPipeline. It will notify the application of everything + * that's happening (errors, end of stream, tags found, state changes, etc.) + * by posting messages on its #GstBus. The application needs to watch the + * bus. + * + * Playback can be initiated by setting the element to PLAYING state using + * gst_element_set_state(). Note that the state change will take place in + * the background in a separate thread, when the function returns playback + * is probably not happening yet and any errors might not have occured yet. + * Applications using playbin should ideally be written to deal with things + * completely asynchroneous. + * + * When playback has finished (an EOS message has been received on the bus) + * or an error has occured (an ERROR message has been received on the bus) or + * the user wants to play a different track, playbin should be set back to + * READY or NULL state, then the #GstPlayBin:uri property should be set to the + * new location and then playbin be set to PLAYING state again. + * + * Seeking can be done using gst_element_seek_simple() or gst_element_seek() + * on the playbin element. Again, the seek will not be executed + * instantaneously, but will be done in a background thread. When the seek + * call returns the seek will most likely still be in process. An application + * may wait for the seek to finish (or fail) using gst_element_get_state() with + * -1 as the timeout, but this will block the user interface and is not + * recommended at all. + * + * Applications may query the current position and duration of the stream + * via gst_element_query_position() and gst_element_query_duration() and + * setting the format passed to GST_FORMAT_TIME. If the query was successful, + * the duration or position will have been returned in units of nanoseconds. + * + * + * + * Advanced Usage: specifying the audio and video sink + * + * By default, if no audio sink or video sink has been specified via the + * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property, playbin will use + * the autoaudiosink and autovideosink elements to find the first-best + * available output method. + * This should work in most cases, but is not always desirable. Often either + * the user or application might want to specify more explicitly what to use + * for audio and video output. + * + * If the application wants more control over how audio or video should be + * output, it may create the audio/video sink elements itself (for example + * using gst_element_factory_make()) and provide them to playbin using the + * #GstPlayBin:audio-sink or #GstPlayBin:video-sink property. + * + * GNOME-based applications, for example, will usually want to create + * gconfaudiosink and gconfvideosink elements and make playbin use those, + * so that output happens to whatever the user has configured in the GNOME + * Multimedia System Selector confinguration dialog. + * + * The sink elements do not necessarily need to be ready-made sinks. It is + * possible to create container elements that look like a sink to playbin, + * but in reality contain a number of custom elements linked together. This + * can be achieved by creating a #GstBin and putting elements in there and + * linking them, and then creating a sink #GstGhostPad for the bin and pointing + * it to the sink pad of the first element within the bin. This can be used + * for a number of purposes, for example to force output to a particular + * format or to modify or observe the data before it is output. + * + * It is also possible to 'suppress' audio and/or video output by using + * 'fakesink' elements (or capture it from there using the fakesink element's + * "handoff" signal, which, nota bene, is fired from the streaming thread!). + * + * + * + * Retrieving Tags and Other Meta Data + * + * Most of the common meta data (artist, title, etc.) can be retrieved by + * watching for TAG messages on the pipeline's bus (see above). + * + * Other more specific meta information like width/height/framerate of video + * streams or samplerate/number of channels of audio streams can be obtained + * using the #GstPlayBaseBin:stream-info property, which will return a GList of + * stream info objects, one for each stream. These are opaque objects that can + * only be accessed via the standard GObject property interface, ie. g_object_get(). + * Each stream info object has the following properties: + * + * "object" (GstObject) (the decoder source pad usually) + * "type" (enum) (if this is an audio/video/subtitle stream) + * "decoder" (string) (name of decoder used to decode this stream) + * "mute" (boolean) (to mute or unmute this stream) + * "caps" (GstCaps) (caps of the decoded stream) + * "language-code" (string) (ISO-639 language code for this stream, mostly used for audio/subtitle streams) + * "codec" (string) (format this stream was encoded in) + * + * Stream information from the #GstPlayBaseBin:stream-info property is best queried once + * playbin has changed into PAUSED or PLAYING state (which can be detected + * via a state-changed message on the #GstBus where old_state=READY and + * new_state=PAUSED), since before that the list might not be complete yet or + * not contain all available information (like language-codes). + * + * + * + * Buffering + * Playbin handles buffering automatically for the most part, but applications + * need to handle parts of the buffering process as well. Whenever playbin is + * buffering, it will post BUFFERING messages on the bus with a percentage + * value that shows the progress of the buffering process. Applications need + * to set playbin to PLAYING or PAUSED state in response to these messages. + * They may also want to convey the buffering progress to the user in some + * way. Here is how to extract the percentage information from the message + * (requires GStreamer >= 0.10.11): + * |[ + * switch (GST_MESSAGE_TYPE (msg)) { + * case GST_MESSAGE_BUFFERING: { + * gint percent = 0; + * gst_message_parse_buffering (msg, &percent); + * g_print ("Buffering (%%u percent done)", percent); + * break; + * } + * ... + * } + * ]| + * Note that applications should keep/set the pipeline in the PAUSED state when + * a BUFFERING message is received with a buffer percent value < 100 and set + * the pipeline back to PLAYING state when a BUFFERING message with a value + * of 100 percent is received (if PLAYING is the desired state, that is). + * + * + * Embedding the video window in your application + * By default, playbin (or rather the video sinks used) will create their own + * window. Applications will usually want to force output to a window of their + * own, however. This can be done using the #GstXOverlay interface, which most + * video sinks implement. See the documentation there for more details. + * + * + * Specifying which CD/DVD device to use + * The device to use for CDs/DVDs needs to be set on the source element + * playbin creates before it is opened. The only way to do this at the moment + * is to connect to playbin's "notify::source" signal, which will be emitted + * by playbin when it has created the source element for a particular URI. + * In the signal callback you can check if the source element has a "device" + * property and set it appropriately. In future ways might be added to specify + * the device as part of the URI, but at the time of writing this is not + * possible yet. + * + * + * Examples + * |[ + * gst-launch -v playbin uri=file:///path/to/somefile.avi + * ]| This will play back the given AVI video file, given that the video and + * audio decoders required to decode the content are installed. Since no + * special audio sink or video sink is supplied (not possible via gst-launch), + * playbin will try to find a suitable audio and video sink automatically + * using the autoaudiosink and autovideosink elements. + * |[ + * gst-launch -v playbin uri=cdda://4 + * ]| This will play back track 4 on an audio CD in your disc drive (assuming + * the drive is detected automatically by the plugin). + * |[ + * gst-launch -v playbin uri=dvd://1 + * ]| This will play back title 1 of a DVD in your disc drive (assuming + * the drive is detected automatically by the plugin). + * + * + * Deprecated: use playbin2 instead + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include + +#include "gstplaybasebin.h" +#include "gstplayback.h" + +GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug); +#define GST_CAT_DEFAULT gst_play_bin_debug + +#define GST_TYPE_PLAY_BIN (gst_play_bin_get_type()) +#define GST_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin)) +#define GST_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BIN,GstPlayBinClass)) +#define GST_IS_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BIN)) +#define GST_IS_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN)) + +#define VOLUME_MAX_DOUBLE 10.0 + +typedef struct _GstPlayBin GstPlayBin; +typedef struct _GstPlayBinClass GstPlayBinClass; + +/** + * GstPlayBin: + * + * High-level player element + */ +struct _GstPlayBin +{ + GstPlayBaseBin parent; + + /* the configurable elements */ + GstElement *fakesink; + GstElement *audio_sink; + GstElement *video_sink; + GstElement *visualisation; + GstElement *pending_visualisation; + GstElement *volume_element; + GstElement *textoverlay_element; + GstElement *spu_element; + gfloat volume; + + /* these are the currently active sinks */ + GList *sinks; + + /* the last captured frame for snapshots */ + GstBuffer *frame; + + /* our cache for the sinks */ + GHashTable *cache; + + /* font description */ + gchar *font_desc; + + /* indication if the pipeline is live */ + gboolean is_live; +}; + +struct _GstPlayBinClass +{ + GstPlayBaseBinClass parent_class; +}; + +/* props */ +enum +{ + ARG_0, + ARG_AUDIO_SINK, + ARG_VIDEO_SINK, + ARG_VIS_PLUGIN, + ARG_VOLUME, + ARG_FRAME, + ARG_FONT_DESC +}; + +/* signals */ +enum +{ + LAST_SIGNAL +}; + +static void gst_play_bin_class_init (GstPlayBinClass * klass); +static void gst_play_bin_init (GstPlayBin * play_bin); +static void gst_play_bin_dispose (GObject * object); + +static gboolean setup_sinks (GstPlayBaseBin * play_base_bin, + GstPlayBaseGroup * group); +static void remove_sinks (GstPlayBin * play_bin); +static void playbin_set_subtitles_visible (GstPlayBaseBin * play_base_bin, + gboolean visible); +static void playbin_set_audio_mute (GstPlayBaseBin * play_base_bin, + gboolean mute); + +static void gst_play_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_play_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); + +static gboolean gst_play_bin_send_event (GstElement * element, + GstEvent * event); +static GstStateChangeReturn gst_play_bin_change_state (GstElement * element, + GstStateChange transition); + +static void gst_play_bin_handle_message (GstBin * bin, GstMessage * message); + +static GstElementClass *parent_class; + +//static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 }; + +static GType +gst_play_bin_get_type (void) +{ + static GType gst_play_bin_type = 0; + + if (!gst_play_bin_type) { + static const GTypeInfo gst_play_bin_info = { + sizeof (GstPlayBinClass), + NULL, + NULL, + (GClassInitFunc) gst_play_bin_class_init, + NULL, + NULL, + sizeof (GstPlayBin), + 0, + (GInstanceInitFunc) gst_play_bin_init, + NULL + }; + + gst_play_bin_type = g_type_register_static (GST_TYPE_PLAY_BASE_BIN, + "GstPlayBin", &gst_play_bin_info, 0); + } + + return gst_play_bin_type; +} + +static void +gst_play_bin_class_init (GstPlayBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + GstBinClass *gstbin_klass; + GstPlayBaseBinClass *playbasebin_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + gstbin_klass = (GstBinClass *) klass; + playbasebin_klass = (GstPlayBaseBinClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_play_bin_set_property; + gobject_klass->get_property = gst_play_bin_get_property; + + g_object_class_install_property (gobject_klass, ARG_VIDEO_SINK, + g_param_spec_object ("video-sink", "Video Sink", + "the video output element to use (NULL = default sink)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_AUDIO_SINK, + g_param_spec_object ("audio-sink", "Audio Sink", + "the audio output element to use (NULL = default sink)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_VIS_PLUGIN, + g_param_spec_object ("vis-plugin", "Vis plugin", + "the visualization element to use (NULL = none)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin:volume: + * + * Get or set the current audio stream volume. 1.0 means 100%, + * 0.0 means mute. This uses a linear volume scale. + * + */ + g_object_class_install_property (gobject_klass, ARG_VOLUME, + g_param_spec_double ("volume", "volume", "volume", + 0.0, VOLUME_MAX_DOUBLE, 1.0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_FRAME, + gst_param_spec_mini_object ("frame", "Frame", + "The last frame (NULL = no video available)", GST_TYPE_BUFFER, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_FONT_DESC, + g_param_spec_string ("subtitle-font-desc", "Subtitle font description", + "Pango font description of font " "to be used for subtitle rendering", + NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + gobject_klass->dispose = gst_play_bin_dispose; + + gst_element_class_set_details_simple (gstelement_klass, + "Player Bin", "Generic/Bin/Player", + "Autoplug and play media from an uri", + "Wim Taymans "); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_play_bin_change_state); + gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_play_bin_send_event); + + gstbin_klass->handle_message = + GST_DEBUG_FUNCPTR (gst_play_bin_handle_message); + + playbasebin_klass->setup_output_pads = setup_sinks; + playbasebin_klass->set_subtitles_visible = playbin_set_subtitles_visible; + playbasebin_klass->set_audio_mute = playbin_set_audio_mute; +} + +static void +gst_play_bin_init (GstPlayBin * play_bin) +{ + play_bin->video_sink = NULL; + play_bin->audio_sink = NULL; + play_bin->visualisation = NULL; + play_bin->pending_visualisation = NULL; + play_bin->volume_element = NULL; + play_bin->textoverlay_element = NULL; + play_bin->spu_element = NULL; + play_bin->volume = 1.0; + play_bin->sinks = NULL; + play_bin->frame = NULL; + play_bin->font_desc = NULL; + play_bin->cache = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, (GDestroyNotify) gst_object_unref); +} + +static void +gst_play_bin_dispose (GObject * object) +{ + GstPlayBin *play_bin; + + play_bin = GST_PLAY_BIN (object); + + if (play_bin->cache != NULL) { + remove_sinks (play_bin); + g_hash_table_destroy (play_bin->cache); + play_bin->cache = NULL; + } + + if (play_bin->audio_sink != NULL) { + gst_element_set_state (play_bin->audio_sink, GST_STATE_NULL); + gst_object_unref (play_bin->audio_sink); + play_bin->audio_sink = NULL; + } + if (play_bin->video_sink != NULL) { + gst_element_set_state (play_bin->video_sink, GST_STATE_NULL); + gst_object_unref (play_bin->video_sink); + play_bin->video_sink = NULL; + } + if (play_bin->visualisation != NULL) { + gst_element_set_state (play_bin->visualisation, GST_STATE_NULL); + gst_object_unref (play_bin->visualisation); + play_bin->visualisation = NULL; + } + if (play_bin->pending_visualisation != NULL) { + gst_element_set_state (play_bin->pending_visualisation, GST_STATE_NULL); + gst_object_unref (play_bin->pending_visualisation); + play_bin->pending_visualisation = NULL; + } + if (play_bin->textoverlay_element != NULL) { + gst_object_unref (play_bin->textoverlay_element); + play_bin->textoverlay_element = NULL; + } + if (play_bin->volume_element) { + gst_object_unref (play_bin->volume_element); + play_bin->volume_element = NULL; + } + if (play_bin->spu_element != NULL) { + gst_object_unref (play_bin->spu_element); + play_bin->spu_element = NULL; + } + g_free (play_bin->font_desc); + play_bin->font_desc = NULL; + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_play_bin_vis_unblocked (GstPad * tee_pad, gboolean blocked, + gpointer user_data) +{ + GstPlayBin *play_bin = GST_PLAY_BIN (user_data); + + if (play_bin->pending_visualisation) + gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_bin_vis_unblocked, + play_bin); +} + +static void +gst_play_bin_vis_blocked (GstPad * tee_pad, gboolean blocked, + gpointer user_data) +{ + GstPlayBin *play_bin = GST_PLAY_BIN (user_data); + GstBin *vis_bin = NULL; + GstPad *vis_sink_pad = NULL, *vis_src_pad = NULL, *vqueue_pad = NULL; + GstState bin_state; + GstElement *pending_visualisation; + + GST_OBJECT_LOCK (play_bin); + pending_visualisation = play_bin->pending_visualisation; + play_bin->pending_visualisation = NULL; + GST_OBJECT_UNLOCK (play_bin); + + /* We want to disable visualisation */ + if (!GST_IS_ELEMENT (pending_visualisation)) { + /* Set visualisation element to READY */ + gst_element_set_state (play_bin->visualisation, GST_STATE_READY); + goto beach; + } + + vis_bin = + GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST + (play_bin->visualisation))); + + if (!GST_IS_BIN (vis_bin) || !GST_IS_PAD (tee_pad)) { + goto beach; + } + + vis_src_pad = gst_element_get_static_pad (play_bin->visualisation, "src"); + vis_sink_pad = gst_pad_get_peer (tee_pad); + + /* Can be fakesink */ + if (GST_IS_PAD (vis_src_pad)) { + vqueue_pad = gst_pad_get_peer (vis_src_pad); + } + + if (!GST_IS_PAD (vis_sink_pad)) { + goto beach; + } + + /* Check the bin's state */ + GST_OBJECT_LOCK (vis_bin); + bin_state = GST_STATE (vis_bin); + GST_OBJECT_UNLOCK (vis_bin); + + /* Unlink */ + gst_pad_unlink (tee_pad, vis_sink_pad); + gst_object_unref (vis_sink_pad); + vis_sink_pad = NULL; + + if (GST_IS_PAD (vqueue_pad)) { + gst_pad_unlink (vis_src_pad, vqueue_pad); + gst_object_unref (vis_src_pad); + vis_src_pad = NULL; + } + + /* Remove from vis_bin */ + gst_bin_remove (vis_bin, play_bin->visualisation); + /* Set state to NULL */ + gst_element_set_state (play_bin->visualisation, GST_STATE_NULL); + /* And loose our ref */ + gst_object_unref (play_bin->visualisation); + + if (pending_visualisation) { + /* Ref this new visualisation element before adding to the bin */ + gst_object_ref (pending_visualisation); + /* Add the new one */ + gst_bin_add (vis_bin, pending_visualisation); + /* Synchronizing state */ + gst_element_set_state (pending_visualisation, bin_state); + + vis_sink_pad = gst_element_get_static_pad (pending_visualisation, "sink"); + vis_src_pad = gst_element_get_static_pad (pending_visualisation, "src"); + + if (!GST_IS_PAD (vis_sink_pad) || !GST_IS_PAD (vis_src_pad)) { + goto beach; + } + + /* Link */ + gst_pad_link (tee_pad, vis_sink_pad); + gst_pad_link (vis_src_pad, vqueue_pad); + } + + /* We are done */ + gst_object_unref (play_bin->visualisation); + play_bin->visualisation = pending_visualisation; + +beach: + if (vis_sink_pad) { + gst_object_unref (vis_sink_pad); + } + if (vis_src_pad) { + gst_object_unref (vis_src_pad); + } + if (vqueue_pad) { + gst_object_unref (vqueue_pad); + } + if (vis_bin) { + gst_object_unref (vis_bin); + } + + /* Unblock the pad */ + gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_bin_vis_unblocked, + play_bin); +} + +static void +gst_play_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPlayBin *play_bin; + + play_bin = GST_PLAY_BIN (object); + + switch (prop_id) { + case ARG_VIDEO_SINK: + if (play_bin->video_sink != NULL) { + gst_object_unref (play_bin->video_sink); + } + play_bin->video_sink = g_value_get_object (value); + if (play_bin->video_sink != NULL) { + gst_object_ref (play_bin->video_sink); + gst_object_sink (GST_OBJECT_CAST (play_bin->video_sink)); + } + /* when changing the videosink, we just remove the + * video pipeline from the cache so that it will be + * regenerated with the new sink element */ + g_hash_table_remove (play_bin->cache, "vbin"); + break; + case ARG_AUDIO_SINK: + if (play_bin->audio_sink != NULL) { + gst_object_unref (play_bin->audio_sink); + } + if (play_bin->volume_element != NULL) { + gst_object_unref (play_bin->volume_element); + play_bin->volume_element = NULL; + } + play_bin->audio_sink = g_value_get_object (value); + if (play_bin->audio_sink != NULL) { + gst_object_ref (play_bin->audio_sink); + gst_object_sink (GST_OBJECT_CAST (play_bin->audio_sink)); + } + g_hash_table_remove (play_bin->cache, "abin"); + break; + case ARG_VIS_PLUGIN: + { + GstElement *pending_visualisation = + GST_ELEMENT_CAST (g_value_get_object (value)); + + /* Take ownership */ + if (pending_visualisation) { + gst_object_ref (pending_visualisation); + gst_object_sink (pending_visualisation); + } + + /* Do we already have a visualisation change pending ? */ + GST_OBJECT_LOCK (play_bin); + if (play_bin->pending_visualisation) { + gst_object_unref (play_bin->pending_visualisation); + play_bin->pending_visualisation = pending_visualisation; + GST_OBJECT_UNLOCK (play_bin); + } else { + GST_OBJECT_UNLOCK (play_bin); + /* Was there a visualisation already set ? */ + if (play_bin->visualisation != NULL) { + GstBin *vis_bin = NULL; + + vis_bin = + GST_BIN_CAST (gst_object_get_parent (GST_OBJECT_CAST + (play_bin->visualisation))); + + /* Check if the visualisation is already in a bin */ + if (GST_IS_BIN (vis_bin)) { + GstPad *vis_sink_pad = NULL, *tee_pad = NULL; + + /* Now get tee pad and block it async */ + vis_sink_pad = gst_element_get_static_pad (play_bin->visualisation, + "sink"); + if (!GST_IS_PAD (vis_sink_pad)) { + goto beach; + } + tee_pad = gst_pad_get_peer (vis_sink_pad); + if (!GST_IS_PAD (tee_pad)) { + goto beach; + } + + play_bin->pending_visualisation = pending_visualisation; + /* Block with callback */ + gst_pad_set_blocked_async (tee_pad, TRUE, gst_play_bin_vis_blocked, + play_bin); + beach: + if (vis_sink_pad) { + gst_object_unref (vis_sink_pad); + } + if (tee_pad) { + gst_object_unref (tee_pad); + } + gst_object_unref (vis_bin); + } else { + play_bin->visualisation = pending_visualisation; + } + } else { + play_bin->visualisation = pending_visualisation; + } + } + break; + } + case ARG_VOLUME: + play_bin->volume = g_value_get_double (value); + if (play_bin->volume_element) { + g_object_set (G_OBJECT (play_bin->volume_element), "volume", + play_bin->volume, NULL); + } + break; + case ARG_FONT_DESC: + g_free (play_bin->font_desc); + play_bin->font_desc = g_strdup (g_value_get_string (value)); + if (play_bin->textoverlay_element) { + g_object_set (G_OBJECT (play_bin->textoverlay_element), + "font-desc", g_value_get_string (value), NULL); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstPlayBin *play_bin; + + play_bin = GST_PLAY_BIN (object); + + switch (prop_id) { + case ARG_VIDEO_SINK: + g_value_set_object (value, play_bin->video_sink); + break; + case ARG_AUDIO_SINK: + g_value_set_object (value, play_bin->audio_sink); + break; + case ARG_VIS_PLUGIN: + g_value_set_object (value, play_bin->visualisation); + break; + case ARG_VOLUME: + g_value_set_double (value, play_bin->volume); + break; + case ARG_FRAME:{ + GstBuffer *cur_frame = NULL; + + gst_buffer_replace (&cur_frame, play_bin->frame); + gst_value_take_buffer (value, cur_frame); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* signal fired when the identity has received a new buffer. This is used for + * making screenshots. + */ +static void +handoff (GstElement * identity, GstBuffer * frame, gpointer data) +{ + GstPlayBin *play_bin = GST_PLAY_BIN (data); + + /* applications need to know the buffer caps, + * make sure they are always set on the frame */ + if (GST_BUFFER_CAPS (frame) == NULL) { + GstPad *pad; + + if ((pad = gst_element_get_static_pad (identity, "sink"))) { + gst_buffer_set_caps (frame, GST_PAD_CAPS (pad)); + gst_object_unref (pad); + } + } + + gst_buffer_replace (&play_bin->frame, frame); +} + +static void +post_missing_element_message (GstPlayBin * playbin, const gchar * name) +{ + GstMessage *msg; + + msg = gst_missing_element_message_new (GST_ELEMENT_CAST (playbin), name); + gst_element_post_message (GST_ELEMENT_CAST (playbin), msg); +} + +/* make the element (bin) that contains the elements needed to perform + * video display. We connect a handoff signal to identity so that we + * can grab snapshots. Identity's sinkpad is ghosted to vbin. + * + * +-------------------------------------------------------------+ + * | vbin | + * | +--------+ +----------+ +----------+ +---------+ | + * | |identity| |colorspace| |videoscale| |videosink| | + * | +-sink src-sink src-sink src-sink | | + * | | +---+----+ +----------+ +----------+ +---------+ | + * sink-+ | | + * +----------|--------------------------------------------------+ + * handoff + */ +static GstElement * +gen_video_element (GstPlayBin * play_bin) +{ + GstElement *element; + GstElement *conv; + + GstElement *scale; + GstElement *sink; + GstElement *identity; + GstPad *pad; + + /* first see if we have it in the cache */ + element = g_hash_table_lookup (play_bin->cache, "vbin"); + if (element != NULL) { + return element; + } + + if (play_bin->video_sink) { + sink = play_bin->video_sink; + } else { + sink = gst_element_factory_make ("autovideosink", "videosink"); + if (sink == NULL) { + sink = gst_element_factory_make ("xvimagesink", "videosink"); + } + if (sink == NULL) + goto no_sinks; + } + gst_object_ref (sink); + g_hash_table_insert (play_bin->cache, (gpointer) "video_sink", sink); + + /* create a bin to hold objects, as we create them we add them to this bin so + * that when something goes wrong we only need to unref the bin */ + element = gst_bin_new ("vbin"); + gst_bin_add (GST_BIN_CAST (element), sink); + + conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); + if (conv == NULL) + goto no_colorspace; + gst_bin_add (GST_BIN_CAST (element), conv); + + scale = gst_element_factory_make ("videoscale", "vscale"); + if (scale == NULL) + goto no_videoscale; + gst_bin_add (GST_BIN_CAST (element), scale); + + identity = gst_element_factory_make ("identity", "id"); + g_object_set (identity, "silent", TRUE, NULL); + g_signal_connect (identity, "handoff", G_CALLBACK (handoff), play_bin); + gst_bin_add (GST_BIN_CAST (element), identity); + + gst_element_link_pads (identity, "src", conv, "sink"); + gst_element_link_pads (conv, "src", scale, "sink"); + /* be more careful with the pad from the custom sink element, it might not + * be named 'sink' */ + if (!gst_element_link_pads (scale, "src", sink, NULL)) + goto link_failed; + + pad = gst_element_get_static_pad (identity, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + gst_element_set_state (element, GST_STATE_READY); + + /* since we're gonna add it to a bin but don't want to lose it, + * we keep a reference. */ + gst_object_ref (element); + g_hash_table_insert (play_bin->cache, (gpointer) "vbin", element); + + return element; + + /* ERRORS */ +no_sinks: + { + post_missing_element_message (play_bin, "autovideosink"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Both autovideosink and xvimagesink elements are missing.")), + (NULL)); + return NULL; + } +no_colorspace: + { + post_missing_element_message (play_bin, "ffmpegcolorspace"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "ffmpegcolorspace"), (NULL)); + gst_object_unref (element); + return NULL; + } + +no_videoscale: + { + post_missing_element_message (play_bin, "videoscale"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "videoscale"), ("possibly a liboil version mismatch?")); + gst_object_unref (element); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (play_bin, CORE, PAD, + (NULL), ("Failed to configure the video sink.")); + gst_object_unref (element); + return NULL; + } +} + +/* make an element for playback of video with subtitles embedded. + * + * +--------------------------------------------------+ + * | tbin +-------------+ | + * | +-----+ | textoverlay | +------+ | + * | | csp | +--video_sink | | vbin | | + * video_sink-sink src+ +-text_sink src---sink | | + * | +-----+ | +-------------+ +------+ | + * text_sink-------------+ | + * +--------------------------------------------------+ + * + * If there is no subtitle renderer this function will simply return the + * videosink without the text_sink pad. + */ +static GstElement * +add_text_element (GstPlayBin * play_bin, GstElement * vbin) +{ + GstElement *element, *csp, *overlay; + GstPad *pad; + + /* Text overlay */ + overlay = gst_element_factory_make ("textoverlay", "overlay"); + + /* If no overlay return the video bin without subtitle support. */ + if (!overlay) + goto no_overlay; + + /* Create our bin */ + element = gst_bin_new ("textbin"); + + /* Set some parameters */ + g_object_set (G_OBJECT (overlay), + "halign", "center", "valign", "bottom", NULL); + if (play_bin->font_desc) { + g_object_set (G_OBJECT (overlay), "font-desc", play_bin->font_desc, NULL); + } + + /* Take a ref */ + play_bin->textoverlay_element = GST_ELEMENT_CAST (gst_object_ref (overlay)); + + /* we know this will succeed, as the video bin already created one before */ + csp = gst_element_factory_make ("ffmpegcolorspace", "subtitlecsp"); + + /* Add our elements */ + gst_bin_add_many (GST_BIN_CAST (element), csp, overlay, vbin, NULL); + + /* Link */ + gst_element_link_pads (csp, "src", overlay, "video_sink"); + gst_element_link_pads (overlay, "src", vbin, "sink"); + + /* Add ghost pads on the subtitle bin */ + pad = gst_element_get_static_pad (overlay, "text_sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("text_sink", pad)); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (csp, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + /* If the vbin provides a subpicture sink pad, ghost it too */ + pad = gst_element_get_static_pad (vbin, "subpicture_sink"); + if (pad) { + gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad)); + gst_object_unref (pad); + } + + /* Set state to READY */ + gst_element_set_state (element, GST_STATE_READY); + + return element; + + /* ERRORS */ +no_overlay: + { + post_missing_element_message (play_bin, "textoverlay"); + GST_WARNING_OBJECT (play_bin, + "No overlay (pango) element, subtitles disabled"); + return vbin; + } +} + +/* make an element for rendering DVD subpictures onto output video + * + * +---------------------------------------------+ + * | tbin +--------+ | + * | +-----+ | | +------+ | + * | | csp | src-videosink | | vbin | | + * video_sink-sink src+ | src-sink | | + * | +-----+ +subpicture | +------+ | + * subpicture_pad--------+ +--------+ | + * +---------- ----------------------------------+ + * + */ +static GstElement * +add_spu_element (GstPlayBin * play_bin, GstElement * vbin) +{ + GstElement *element, *csp, *overlay; + GstPad *pad; + + /* DVD spu overlay */ + GST_DEBUG_OBJECT (play_bin, "Attempting to insert DVD SPU element"); + + overlay = gst_element_factory_make ("dvdspu", "overlay"); + + /* If no overlay return the video bin without subpicture support. */ + if (!overlay) + goto no_overlay; + + /* Create our bin */ + element = gst_bin_new ("spubin"); + + /* Take a ref */ + play_bin->spu_element = GST_ELEMENT_CAST (gst_object_ref (overlay)); + + /* we know this will succeed, as the video bin already created one before */ + csp = gst_element_factory_make ("ffmpegcolorspace", "spucsp"); + + /* Add our elements */ + gst_bin_add_many (GST_BIN_CAST (element), csp, overlay, vbin, NULL); + + /* Link */ + gst_element_link_pads (csp, "src", overlay, "video"); + gst_element_link_pads (overlay, "src", vbin, "sink"); + + /* Add ghost pad on the subpicture bin so it looks like vbin */ + pad = gst_element_get_static_pad (csp, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (overlay, "subpicture"); + gst_element_add_pad (element, gst_ghost_pad_new ("subpicture_sink", pad)); + gst_object_unref (pad); + + /* Set state to READY */ + gst_element_set_state (element, GST_STATE_READY); + + return element; + + /* ERRORS */ +no_overlay: + { + post_missing_element_message (play_bin, "dvdspu"); + GST_WARNING_OBJECT (play_bin, + "No DVD overlay (dvdspu) element. " + "menu highlight/subtitles unavailable"); + return vbin; + } +} + +/* make the element (bin) that contains the elements needed to perform + * audio playback. + * + * +-------------------------------------------------------------+ + * | abin | + * | +---------+ +----------+ +---------+ +---------+ | + * | |audioconv| |audioscale| | volume | |audiosink| | + * | +-sink src-sink src-sink src-sink | | + * | | +---------+ +----------+ +---------+ +---------+ | + * sink-+ | + * +-------------------------------------------------------------+ + */ +static GstElement * +gen_audio_element (GstPlayBin * play_bin) +{ + gboolean res; + GstElement *element; + GstElement *conv; + GstElement *scale; + GstElement *sink; + GstElement *volume; + GstPad *pad; + + element = g_hash_table_lookup (play_bin->cache, "abin"); + if (element != NULL) + return element; + + if (play_bin->audio_sink) { + sink = play_bin->audio_sink; + } else { + sink = gst_element_factory_make ("autoaudiosink", "audiosink"); + if (sink == NULL) { + sink = gst_element_factory_make ("alsasink", "audiosink"); + } + if (sink == NULL) + goto no_sinks; + + play_bin->audio_sink = GST_ELEMENT_CAST (gst_object_ref (sink)); + } + + gst_object_ref (sink); + g_hash_table_insert (play_bin->cache, (gpointer) "audio_sink", sink); + + element = gst_bin_new ("abin"); + gst_bin_add (GST_BIN_CAST (element), sink); + + conv = gst_element_factory_make ("audioconvert", "aconv"); + if (conv == NULL) + goto no_audioconvert; + gst_bin_add (GST_BIN_CAST (element), conv); + + scale = gst_element_factory_make ("audioresample", "aresample"); + if (scale == NULL) + goto no_audioresample; + gst_bin_add (GST_BIN_CAST (element), scale); + + volume = gst_element_factory_make ("volume", "volume"); + if (volume == NULL) + goto no_volume; + g_object_set (G_OBJECT (volume), "volume", play_bin->volume, NULL); + play_bin->volume_element = GST_ELEMENT_CAST (gst_object_ref (volume)); + gst_bin_add (GST_BIN_CAST (element), volume); + + res = gst_element_link_pads (conv, "src", scale, "sink"); + res &= gst_element_link_pads (scale, "src", volume, "sink"); + res &= gst_element_link_pads (volume, "src", sink, NULL); + if (!res) + goto link_failed; + + pad = gst_element_get_static_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + gst_element_set_state (element, GST_STATE_READY); + + /* since we're gonna add it to a bin but don't want to lose it, + * we keep a reference. */ + gst_object_ref (element); + g_hash_table_insert (play_bin->cache, (gpointer) "abin", element); + + return element; + + /* ERRORS */ +no_sinks: + { + post_missing_element_message (play_bin, "autoaudiosink"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Both autoaudiosink and alsasink elements are missing.")), (NULL)); + return NULL; + } +no_audioconvert: + { + post_missing_element_message (play_bin, "audioconvert"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioconvert"), ("possibly a liboil version mismatch?")); + gst_object_unref (element); + return NULL; + } +no_audioresample: + { + post_missing_element_message (play_bin, "audioresample"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioresample"), ("possibly a liboil version mismatch?")); + gst_object_unref (element); + return NULL; + } +no_volume: + { + post_missing_element_message (play_bin, "volume"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "volume"), ("possibly a liboil version mismatch?")); + gst_object_unref (element); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (play_bin, CORE, PAD, + (NULL), ("Failed to configure the audio sink.")); + gst_object_unref (element); + return NULL; + } +} + +/* make the element (bin) that contains the elements needed to perform + * visualisation ouput. The idea is to split the audio using tee, then + * sending the output to the regular audio bin and the other output to + * the vis plugin that transforms it into a video that is rendered with the + * normal video bin. The video and audio bins are run in threads to make sure + * they don't block eachother. + * + * +-----------------------------------------------------------------------+ + * | visbin | + * | +------+ +--------+ +----------------+ | + * | | tee | | aqueue | | abin ... | | + * | +-sink src-sink src-sink | | + * | | | | +--------+ +----------------+ | + * | | | | | + * | | | | +------+ +------------+ +------+ +-----------+ | + * | | | | |vqueue| | audioconv | | vis | | vbin ... | | + * | | | src-sink src-sink + samp src-sink src-sink | | + * | | | | +------+ +------------+ +------+ +-----------+ | + * | | | | | + * | | +------+ | + * sink-+ | + * +-----------------------------------------------------------------------+ + */ +static GstElement * +gen_vis_element (GstPlayBin * play_bin) +{ + gboolean res; + GstElement *element; + GstElement *tee; + GstElement *asink; + GstElement *vsink; + GstElement *conv; + GstElement *resamp; + GstElement *conv2; + GstElement *vis; + GstElement *vqueue, *aqueue; + GstPad *pad, *rpad; + + /* errors are already posted when these fail. */ + asink = gen_audio_element (play_bin); + if (!asink) + return NULL; + vsink = gen_video_element (play_bin); + if (!vsink) { + gst_object_unref (asink); + return NULL; + } + + element = gst_bin_new ("visbin"); + tee = gst_element_factory_make ("tee", "tee"); + + vqueue = gst_element_factory_make ("queue", "vqueue"); + aqueue = gst_element_factory_make ("queue", "aqueue"); + + gst_bin_add (GST_BIN_CAST (element), asink); + gst_bin_add (GST_BIN_CAST (element), vqueue); + gst_bin_add (GST_BIN_CAST (element), aqueue); + gst_bin_add (GST_BIN_CAST (element), vsink); + gst_bin_add (GST_BIN_CAST (element), tee); + + conv = gst_element_factory_make ("audioconvert", "aconv"); + if (conv == NULL) + goto no_audioconvert; + gst_bin_add (GST_BIN_CAST (element), conv); + + resamp = gst_element_factory_make ("audioresample", "aresamp"); + if (resamp == NULL) + goto no_audioresample; + gst_bin_add (GST_BIN_CAST (element), resamp); + + conv2 = gst_element_factory_make ("audioconvert", "aconv2"); + if (conv2 == NULL) + goto no_audioconvert; + gst_bin_add (GST_BIN_CAST (element), conv2); + + if (play_bin->visualisation) { + gst_object_ref (play_bin->visualisation); + vis = play_bin->visualisation; + } else { + vis = gst_element_factory_make ("goom", "vis"); + if (!vis) + goto no_goom; + } + gst_bin_add (GST_BIN_CAST (element), vis); + + res = gst_element_link_pads (vqueue, "src", conv, "sink"); + res &= gst_element_link_pads (conv, "src", resamp, "sink"); + res &= gst_element_link_pads (resamp, "src", conv2, "sink"); + res &= gst_element_link_pads (conv2, "src", vis, "sink"); + res &= gst_element_link_pads (vis, "src", vsink, "sink"); + if (!res) + goto link_failed; + + pad = gst_element_get_static_pad (aqueue, "sink"); + rpad = gst_element_get_request_pad (tee, "src%d"); + gst_pad_link (rpad, pad); + gst_object_unref (rpad); + gst_object_unref (pad); + gst_element_link_pads (aqueue, "src", asink, "sink"); + + pad = gst_element_get_static_pad (vqueue, "sink"); + rpad = gst_element_get_request_pad (tee, "src%d"); + gst_pad_link (rpad, pad); + gst_object_unref (rpad); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (tee, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + return element; + + /* ERRORS */ +no_audioconvert: + { + post_missing_element_message (play_bin, "audioconvert"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioconvert"), ("possibly a liboil version mismatch?")); + gst_object_unref (element); + return NULL; + } +no_audioresample: + { + post_missing_element_message (play_bin, "audioresample"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioresample"), (NULL)); + gst_object_unref (element); + return NULL; + } +no_goom: + { + post_missing_element_message (play_bin, "goom"); + GST_ELEMENT_ERROR (play_bin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "goom"), (NULL)); + gst_object_unref (element); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (play_bin, CORE, PAD, + (NULL), ("Failed to configure the visualisation element.")); + gst_object_unref (element); + return NULL; + } +} + +/* get rid of all installed sinks */ +static void +remove_sinks (GstPlayBin * play_bin) +{ + GList *sinks; + GstObject *parent; + GstElement *element; + GstPad *pad, *peer; + + if (play_bin->cache == NULL) + return; + + GST_DEBUG ("removesinks"); + element = g_hash_table_lookup (play_bin->cache, "abin"); + if (element != NULL) { + parent = gst_element_get_parent (element); + if (parent != NULL) { + /* we remove the element from the parent so that + * there is no unwanted state change when the parent + * is disposed */ + play_bin->sinks = g_list_remove (play_bin->sinks, element); + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (parent), element); + gst_object_unref (parent); + } + pad = gst_element_get_static_pad (element, "sink"); + if (pad != NULL) { + peer = gst_pad_get_peer (pad); + if (peer != NULL) { + gst_pad_unlink (peer, pad); + gst_object_unref (peer); + } + gst_object_unref (pad); + } + } + element = g_hash_table_lookup (play_bin->cache, "vbin"); + if (element != NULL) { + parent = gst_element_get_parent (element); + if (parent != NULL) { + play_bin->sinks = g_list_remove (play_bin->sinks, element); + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (parent), element); + gst_object_unref (parent); + } + pad = gst_element_get_static_pad (element, "sink"); + if (pad != NULL) { + peer = gst_pad_get_peer (pad); + if (peer != NULL) { + gst_pad_unlink (peer, pad); + gst_object_unref (peer); + } + gst_object_unref (pad); + } + } + + for (sinks = play_bin->sinks; sinks; sinks = g_list_next (sinks)) { + GstElement *element = GST_ELEMENT_CAST (sinks->data); + GstPad *pad; + GstPad *peer; + + pad = gst_element_get_static_pad (element, "sink"); + + GST_LOG ("removing sink %p", element); + + peer = gst_pad_get_peer (pad); + if (peer) { + gst_pad_unlink (peer, pad); + gst_object_unref (peer); + } + gst_object_unref (pad); + + gst_element_set_state (element, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_bin), element); + } + g_list_free (play_bin->sinks); + play_bin->sinks = NULL; + + if (play_bin->visualisation) { + GstElement *vis_bin; + + vis_bin = + GST_ELEMENT_CAST (gst_element_get_parent (play_bin->visualisation)); + + gst_element_set_state (play_bin->visualisation, GST_STATE_NULL); + + if (vis_bin) { + gst_bin_remove (GST_BIN_CAST (vis_bin), play_bin->visualisation); + gst_object_unref (vis_bin); + } + } + + if (play_bin->frame) { + gst_buffer_unref (play_bin->frame); + play_bin->frame = NULL; + } + + if (play_bin->textoverlay_element) { + gst_object_unref (play_bin->textoverlay_element); + play_bin->textoverlay_element = NULL; + } +} + +/* loop over the streams and set up the pipeline to play this + * media file. First we count the number of audio and video streams. + * If there is no video stream but there exists an audio stream, + * we install a visualisation pipeline. + * + * Also make sure to only connect the first audio and video pad. FIXME + * this should eventually be handled with a tuner interface so that + * one can switch the streams. + * + * This function takes ownership of @sink.* + */ +static gboolean +add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad, + GstPad * subtitle_pad) +{ + GstPad *sinkpad; + GstPadLinkReturn linkres; + GstElement *parent; + GstStateChangeReturn stateret; + GstState state; + + g_return_val_if_fail (sink != NULL, FALSE); + + state = GST_STATE_PAUSED; + + /* this is only for debugging */ + parent = gst_pad_get_parent_element (srcpad); + if (parent) { + GST_DEBUG ("Adding sink %" GST_PTR_FORMAT + " with state %d (parent: %d, peer: %d)", sink, + GST_STATE (sink), GST_STATE (play_bin), GST_STATE (parent)); + gst_object_unref (parent); + } + gst_bin_add (GST_BIN_CAST (play_bin), sink); + + /* bring it to the required state so we can link to the peer without + * breaking the flow */ + stateret = gst_element_set_state (sink, state); + if (stateret == GST_STATE_CHANGE_FAILURE) + goto state_failed; + + /* we found a sink for this stream, now try to install it */ + sinkpad = gst_element_get_static_pad (sink, "sink"); + linkres = gst_pad_link (srcpad, sinkpad); + gst_object_unref (sinkpad); + + /* try to link the pad of the sink to the stream */ + if (GST_PAD_LINK_FAILED (linkres)) + goto link_failed; + + if (GST_IS_PAD (subtitle_pad)) { + sinkpad = gst_element_get_static_pad (sink, "text_sink"); + linkres = gst_pad_link (subtitle_pad, sinkpad); + gst_object_unref (sinkpad); + } + + /* try to link the subtitle pad of the sink to the stream, this is not + * fatal. */ + if (GST_PAD_LINK_FAILED (linkres)) + goto subtitle_failed; + +done: + /* we got the sink succesfully linked, now keep the sink + * in our internal list */ + play_bin->sinks = g_list_prepend (play_bin->sinks, sink); + + return TRUE; + + /* ERRORS */ +state_failed: + { + gst_element_set_state (sink, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_bin), sink); + GST_DEBUG_OBJECT (play_bin, "state change failure when adding sink"); + return FALSE; + } +link_failed: + { + gchar *capsstr; + GstCaps *caps; + + /* could not link this stream */ + caps = gst_pad_get_caps (srcpad); + capsstr = gst_caps_to_string (caps); + g_warning ("could not link %s: %d", capsstr, linkres); + GST_DEBUG_OBJECT (play_bin, + "link failed when adding sink, caps %s, reason %d", capsstr, linkres); + g_free (capsstr); + gst_caps_unref (caps); + + gst_element_set_state (sink, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_bin), sink); + return FALSE; + } +subtitle_failed: + { + GstCaps *caps; + + /* could not link this stream */ + caps = gst_pad_get_caps (subtitle_pad); + GST_WARNING_OBJECT (play_bin, "subtitle link failed when adding sink, " + "caps = %" GST_PTR_FORMAT ", reason %d", caps, linkres); + gst_caps_unref (caps); + + /* not fatal */ + goto done; + } +} + +static void +dummy_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data) +{ +} + +static gboolean +setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group) +{ + GstPlayBin *play_bin = GST_PLAY_BIN (play_base_bin); + gboolean have_video = FALSE; + gboolean need_vis = FALSE; + gboolean need_text = FALSE; + gboolean need_spu = FALSE; + GstPad *textsrcpad = NULL, *pad = NULL, *origtextsrcpad = NULL; + GstElement *sink; + gboolean res = TRUE; + + /* get rid of existing sinks */ + if (play_bin->sinks) { + remove_sinks (play_bin); + } + GST_DEBUG_OBJECT (play_base_bin, "setupsinks"); + + /* find out what to do */ + have_video = (group->type[GST_STREAM_TYPE_VIDEO - 1].npads > 0); + need_spu = (group->type[GST_STREAM_TYPE_SUBPICTURE - 1].npads != 0); + + if (have_video && group->type[GST_STREAM_TYPE_TEXT - 1].npads > 0) { + need_text = TRUE; + } else if (!have_video && + group->type[GST_STREAM_TYPE_AUDIO - 1].npads > 0 && + play_bin->visualisation != NULL) { + need_vis = TRUE; + } + + /* now actually connect everything */ + + /* link audio */ + if (group->type[GST_STREAM_TYPE_AUDIO - 1].npads > 0) { + if (need_vis) { + sink = gen_vis_element (play_bin); + } else { + sink = gen_audio_element (play_bin); + } + if (!sink) + return FALSE; + + pad = + gst_element_get_static_pad (group->type[GST_STREAM_TYPE_AUDIO - + 1].preroll, "src"); + res = add_sink (play_bin, sink, pad, NULL); + gst_object_unref (pad); + } + + /* link video */ + if (have_video) { + /* Create the video rendering bin, error is posted when this fails. */ + sink = gen_video_element (play_bin); + if (!sink) + return FALSE; + if (need_spu) { + sink = add_spu_element (play_bin, sink); + } + + if (need_text) { + GstObject *parent = NULL, *grandparent = NULL; + GstPad *ghost = NULL; + + /* Add the subtitle overlay element into the video sink */ + sink = add_text_element (play_bin, sink); + + /* Link the incoming subtitle stream into the output bin */ + textsrcpad = + gst_element_get_static_pad (group->type[GST_STREAM_TYPE_TEXT - + 1].preroll, "src"); + + /* This pad is from subtitle-bin, we need to create a ghost pad to have + common grandparents */ + parent = gst_object_get_parent (GST_OBJECT_CAST (textsrcpad)); + if (!parent) { + GST_WARNING_OBJECT (textsrcpad, "subtitle pad has no parent !"); + gst_object_unref (textsrcpad); + textsrcpad = NULL; + goto beach; + } + + grandparent = gst_object_get_parent (parent); + if (!grandparent) { + GST_WARNING_OBJECT (textsrcpad, "subtitle pad has no grandparent !"); + gst_object_unref (parent); + gst_object_unref (textsrcpad); + textsrcpad = NULL; + goto beach; + } + + /* We ghost the pad on subtitle_bin only, if the text pad is from the + media demuxer we keep it as it is */ + if (!GST_IS_PLAY_BIN (grandparent)) { + GST_DEBUG_OBJECT (textsrcpad, "this subtitle pad is from a subtitle " + "file, ghosting to a suitable hierarchy"); + /* Block the pad first, because as soon as we add a ghostpad, the queue + * will try and start pushing */ + gst_pad_set_blocked_async (textsrcpad, TRUE, dummy_blocked_cb, NULL); + origtextsrcpad = gst_object_ref (textsrcpad); + + ghost = gst_ghost_pad_new ("text_src", textsrcpad); + if (!GST_IS_PAD (ghost)) { + GST_WARNING_OBJECT (textsrcpad, "failed creating ghost pad for " + "subtitle-bin"); + gst_object_unref (parent); + gst_object_unref (grandparent); + gst_object_unref (textsrcpad); + textsrcpad = NULL; + goto beach; + } + + gst_pad_set_active (ghost, TRUE); + if (gst_element_add_pad (GST_ELEMENT_CAST (grandparent), ghost)) { + gst_object_unref (textsrcpad); + textsrcpad = gst_object_ref (ghost); + } else { + GST_WARNING_OBJECT (ghost, "failed adding ghost pad on subtitle-bin"); + gst_pad_set_active (ghost, FALSE); + gst_object_unref (ghost); + gst_object_unref (textsrcpad); + textsrcpad = NULL; + } + } else { + GST_DEBUG_OBJECT (textsrcpad, "this subtitle pad is from the demuxer " + "no changes to hierarchy needed"); + } + + gst_object_unref (parent); + gst_object_unref (grandparent); + } + beach: + if (!sink) + return FALSE; + pad = + gst_element_get_static_pad (group->type[GST_STREAM_TYPE_VIDEO - + 1].preroll, "src"); + res = add_sink (play_bin, sink, pad, textsrcpad); + gst_object_unref (pad); + if (textsrcpad) + gst_object_unref (textsrcpad); + if (origtextsrcpad) { + gst_pad_set_blocked_async (origtextsrcpad, FALSE, dummy_blocked_cb, NULL); + gst_object_unref (origtextsrcpad); + } + + /* If we have a DVD subpicture stream, link it to the SPU now */ + if (need_spu) { + GstPad *subpic_pad; + GstPad *spu_sink_pad; + + subpic_pad = + gst_element_get_static_pad (group->type[GST_STREAM_TYPE_SUBPICTURE + - 1].preroll, "src"); + spu_sink_pad = gst_element_get_static_pad (sink, "subpicture_sink"); + if (subpic_pad && spu_sink_pad) { + GST_LOG_OBJECT (play_bin, "Linking DVD subpicture stream onto SPU"); + gst_pad_set_blocked_async (subpic_pad, TRUE, dummy_blocked_cb, NULL); + if (gst_pad_link (subpic_pad, spu_sink_pad) != GST_PAD_LINK_OK) { + GST_WARNING_OBJECT (play_bin, + "Failed to link DVD subpicture stream onto SPU"); + } + gst_pad_set_blocked_async (subpic_pad, FALSE, dummy_blocked_cb, NULL); + } + if (subpic_pad) + gst_object_unref (subpic_pad); + if (spu_sink_pad) + gst_object_unref (spu_sink_pad); + } + } + + /* remove the sinks now, pipeline get_state will now wait for the + * sinks to preroll */ + if (play_bin->fakesink) { + gst_element_set_state (play_bin->fakesink, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_bin), play_bin->fakesink); + play_bin->fakesink = NULL; + } + + return res; +} + +static void +playbin_set_subtitles_visible (GstPlayBaseBin * play_base_bin, gboolean visible) +{ + GstPlayBin *playbin = GST_PLAY_BIN (play_base_bin); + + /* we're ignoring the case of someone setting the 'current-text' property + * before textoverlay is set up (which is probably okay, since playbasebin + * will just select the first subtitle stream as active stream regardless) */ + if (playbin->textoverlay_element != NULL) { + GST_LOG_OBJECT (playbin, "setting subtitle visibility to %d", visible); + g_object_set (playbin->textoverlay_element, "silent", !visible, NULL); + } +} + +static void +playbin_set_audio_mute (GstPlayBaseBin * play_base_bin, gboolean mute) +{ + GstPlayBin *playbin = GST_PLAY_BIN (play_base_bin); + + if (playbin->volume_element) { + g_object_set (G_OBJECT (playbin->volume_element), "mute", mute, NULL); + } +} + +/* Send an event to our sinks until one of them works; don't then send to the + * remaining sinks (unlike GstBin) + */ +static gboolean +gst_play_bin_send_event_to_sink (GstPlayBin * play_bin, GstEvent * event) +{ + GList *sinks = play_bin->sinks; + gboolean res = TRUE; + + while (sinks) { + GstElement *sink = GST_ELEMENT_CAST (sinks->data); + + gst_event_ref (event); + if ((res = gst_element_send_event (sink, event))) { + GST_DEBUG_OBJECT (play_bin, + "Sent event succesfully to sink %" GST_PTR_FORMAT, sink); + break; + } + GST_DEBUG_OBJECT (play_bin, + "Event failed when sent to sink %" GST_PTR_FORMAT, sink); + + sinks = g_list_next (sinks); + } + + gst_event_unref (event); + + return res; +} + +/* We only want to send the event to a single sink (overriding GstBin's + * behaviour), but we want to keep GstPipeline's behaviour - wrapping seek + * events appropriately. So, this is a messy duplication of code. */ +static gboolean +gst_play_bin_send_event (GstElement * element, GstEvent * event) +{ + gboolean res = FALSE; + GstEventType event_type = GST_EVENT_TYPE (event); + + switch (event_type) { + case GST_EVENT_SEEK: + GST_DEBUG_OBJECT (element, "Sending seek event to a sink"); + res = gst_play_bin_send_event_to_sink (GST_PLAY_BIN (element), event); + break; + default: + res = parent_class->send_event (element, event); + break; + } + + return res; +} + +static void +value_list_append_structure_list (GValue * list_val, GstStructure ** first, + GList * structure_list) +{ + GList *l; + + for (l = structure_list; l != NULL; l = l->next) { + GValue val = { 0, }; + + if (*first == NULL) + *first = gst_structure_copy ((GstStructure *) l->data); + + g_value_init (&val, GST_TYPE_STRUCTURE); + g_value_take_boxed (&val, gst_structure_copy ((GstStructure *) l->data)); + gst_value_list_append_value (list_val, &val); + g_value_unset (&val); + } +} + +/* if it's a redirect message with multiple redirect locations we might + * want to pick a different 'best' location depending on the required + * bitrates and the connection speed */ +static GstMessage * +gst_play_bin_handle_redirect_message (GstPlayBin * playbin, GstMessage * msg) +{ + const GValue *locations_list, *location_val; + GstMessage *new_msg; + GstStructure *new_structure = NULL; + GList *l_good = NULL, *l_neutral = NULL, *l_bad = NULL; + GValue new_list = { 0, }; + guint size, i; + GstPlayBaseBin *playbasebin = GST_PLAY_BASE_BIN (playbin); + guint connection_speed = playbasebin->connection_speed; + + GST_DEBUG_OBJECT (playbin, "redirect message: %" GST_PTR_FORMAT, msg); + GST_DEBUG_OBJECT (playbin, "connection speed: %u", connection_speed); + + if (connection_speed == 0 || msg->structure == NULL) + return msg; + + locations_list = gst_structure_get_value (msg->structure, "locations"); + if (locations_list == NULL) + return msg; + + size = gst_value_list_get_size (locations_list); + if (size < 2) + return msg; + + /* maintain existing order as much as possible, just sort references + * with too high a bitrate to the end (the assumption being that if + * bitrates are given they are given for all interesting streams and + * that the you-need-at-least-version-xyz redirect has the same bitrate + * as the lowest referenced redirect alternative) */ + for (i = 0; i < size; ++i) { + const GstStructure *s; + gint bitrate = 0; + + location_val = gst_value_list_get_value (locations_list, i); + s = (const GstStructure *) g_value_get_boxed (location_val); + if (!gst_structure_get_int (s, "minimum-bitrate", &bitrate) || bitrate <= 0) { + GST_DEBUG_OBJECT (playbin, "no bitrate: %" GST_PTR_FORMAT, s); + l_neutral = g_list_append (l_neutral, (gpointer) s); + } else if (bitrate > connection_speed) { + GST_DEBUG_OBJECT (playbin, "bitrate too high: %" GST_PTR_FORMAT, s); + l_bad = g_list_append (l_bad, (gpointer) s); + } else if (bitrate <= connection_speed) { + GST_DEBUG_OBJECT (playbin, "bitrate OK: %" GST_PTR_FORMAT, s); + l_good = g_list_append (l_good, (gpointer) s); + } + } + + g_value_init (&new_list, GST_TYPE_LIST); + value_list_append_structure_list (&new_list, &new_structure, l_good); + value_list_append_structure_list (&new_list, &new_structure, l_neutral); + value_list_append_structure_list (&new_list, &new_structure, l_bad); + gst_structure_set_value (new_structure, "locations", &new_list); + g_value_unset (&new_list); + + g_list_free (l_good); + g_list_free (l_neutral); + g_list_free (l_bad); + + new_msg = gst_message_new_element (msg->src, new_structure); + gst_message_unref (msg); + + GST_DEBUG_OBJECT (playbin, "new redirect message: %" GST_PTR_FORMAT, new_msg); + return new_msg; +} + +static void +gst_play_bin_handle_message (GstBin * bin, GstMessage * msg) +{ + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT && msg->structure != NULL + && gst_structure_has_name (msg->structure, "redirect")) { + msg = gst_play_bin_handle_redirect_message (GST_PLAY_BIN (bin), msg); + } + + GST_BIN_CLASS (parent_class)->handle_message (bin, msg); +} + +static GstStateChangeReturn +gst_play_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstPlayBin *play_bin; + + play_bin = GST_PLAY_BIN (element); + + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* this really is the easiest way to make the state change return + * ASYNC until we added the sinks */ + if (!play_bin->fakesink) { + play_bin->fakesink = gst_element_factory_make ("fakesink", "test"); + gst_bin_add (GST_BIN_CAST (play_bin), play_bin->fakesink); + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* remember us being a live pipeline */ + play_bin->is_live = (ret == GST_STATE_CHANGE_NO_PREROLL); + GST_DEBUG_OBJECT (play_bin, "is live: %d", play_bin->is_live); + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* FIXME Release audio device when we implement that */ + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + /* remove sinks we added */ + remove_sinks (play_bin); + /* and there might be a fakesink we need to clean up now */ + if (play_bin->fakesink) { + gst_element_set_state (play_bin->fakesink, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (play_bin), play_bin->fakesink); + play_bin->fakesink = NULL; + } + break; + default: + break; + } + + return ret; +} + +gboolean +gst_play_bin_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin", 0, "play bin"); + + return gst_element_register (plugin, "playbin", GST_RANK_NONE, + GST_TYPE_PLAY_BIN); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin2.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin2.c new file mode 100644 index 0000000..5f0f964 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaybin2.c @@ -0,0 +1,3786 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-playbin2 + * + * Playbin2 provides a stand-alone everything-in-one abstraction for an + * audio and/or video player. + * + * playbin2 is considered stable now. It is the prefered playback API now, + * and replaces the old #playbin element, which is no longer supported. + * + * It can handle both audio and video files and features + * + * + * automatic file type recognition and based on that automatic + * selection and usage of the right audio/video/subtitle demuxers/decoders + * + * + * visualisations for audio files + * + * + * subtitle support for video files. Subtitles can be store in external + * files. + * + * + * stream selection between different video/audio/subtitles streams + * + * + * meta info (tag) extraction + * + * + * easy access to the last video frame + * + * + * buffering when playing streams over a network + * + * + * volume control with mute option + * + * + * + * + * Usage + * + * A playbin2 element can be created just like any other element using + * gst_element_factory_make(). The file/URI to play should be set via the #GstPlayBin2:uri + * property. This must be an absolute URI, relative file paths are not allowed. + * Example URIs are file:///home/joe/movie.avi or http://www.joedoe.com/foo.ogg + * + * Playbin is a #GstPipeline. It will notify the application of everything + * that's happening (errors, end of stream, tags found, state changes, etc.) + * by posting messages on its #GstBus. The application needs to watch the + * bus. + * + * Playback can be initiated by setting the element to PLAYING state using + * gst_element_set_state(). Note that the state change will take place in + * the background in a separate thread, when the function returns playback + * is probably not happening yet and any errors might not have occured yet. + * Applications using playbin should ideally be written to deal with things + * completely asynchroneous. + * + * When playback has finished (an EOS message has been received on the bus) + * or an error has occured (an ERROR message has been received on the bus) or + * the user wants to play a different track, playbin should be set back to + * READY or NULL state, then the #GstPlayBin2:uri property should be set to the + * new location and then playbin be set to PLAYING state again. + * + * Seeking can be done using gst_element_seek_simple() or gst_element_seek() + * on the playbin element. Again, the seek will not be executed + * instantaneously, but will be done in a background thread. When the seek + * call returns the seek will most likely still be in process. An application + * may wait for the seek to finish (or fail) using gst_element_get_state() with + * -1 as the timeout, but this will block the user interface and is not + * recommended at all. + * + * Applications may query the current position and duration of the stream + * via gst_element_query_position() and gst_element_query_duration() and + * setting the format passed to GST_FORMAT_TIME. If the query was successful, + * the duration or position will have been returned in units of nanoseconds. + * + * + * + * Advanced Usage: specifying the audio and video sink + * + * By default, if no audio sink or video sink has been specified via the + * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property, playbin will use the autoaudiosink + * and autovideosink elements to find the first-best available output method. + * This should work in most cases, but is not always desirable. Often either + * the user or application might want to specify more explicitly what to use + * for audio and video output. + * + * If the application wants more control over how audio or video should be + * output, it may create the audio/video sink elements itself (for example + * using gst_element_factory_make()) and provide them to playbin using the + * #GstPlayBin2:audio-sink or #GstPlayBin2:video-sink property. + * + * GNOME-based applications, for example, will usually want to create + * gconfaudiosink and gconfvideosink elements and make playbin use those, + * so that output happens to whatever the user has configured in the GNOME + * Multimedia System Selector configuration dialog. + * + * The sink elements do not necessarily need to be ready-made sinks. It is + * possible to create container elements that look like a sink to playbin, + * but in reality contain a number of custom elements linked together. This + * can be achieved by creating a #GstBin and putting elements in there and + * linking them, and then creating a sink #GstGhostPad for the bin and pointing + * it to the sink pad of the first element within the bin. This can be used + * for a number of purposes, for example to force output to a particular + * format or to modify or observe the data before it is output. + * + * It is also possible to 'suppress' audio and/or video output by using + * 'fakesink' elements (or capture it from there using the fakesink element's + * "handoff" signal, which, nota bene, is fired from the streaming thread!). + * + * + * + * Retrieving Tags and Other Meta Data + * + * Most of the common meta data (artist, title, etc.) can be retrieved by + * watching for TAG messages on the pipeline's bus (see above). + * + * Other more specific meta information like width/height/framerate of video + * streams or samplerate/number of channels of audio streams can be obtained + * from the negotiated caps on the sink pads of the sinks. + * + * + * + * Buffering + * Playbin handles buffering automatically for the most part, but applications + * need to handle parts of the buffering process as well. Whenever playbin is + * buffering, it will post BUFFERING messages on the bus with a percentage + * value that shows the progress of the buffering process. Applications need + * to set playbin to PLAYING or PAUSED state in response to these messages. + * They may also want to convey the buffering progress to the user in some + * way. Here is how to extract the percentage information from the message + * (requires GStreamer >= 0.10.11): + * |[ + * switch (GST_MESSAGE_TYPE (msg)) { + * case GST_MESSAGE_BUFFERING: { + * gint percent = 0; + * gst_message_parse_buffering (msg, &percent); + * g_print ("Buffering (%%u percent done)", percent); + * break; + * } + * ... + * } + * ]| + * Note that applications should keep/set the pipeline in the PAUSED state when + * a BUFFERING message is received with a buffer percent value < 100 and set + * the pipeline back to PLAYING state when a BUFFERING message with a value + * of 100 percent is received (if PLAYING is the desired state, that is). + * + * + * Embedding the video window in your application + * By default, playbin (or rather the video sinks used) will create their own + * window. Applications will usually want to force output to a window of their + * own, however. This can be done using the #GstXOverlay interface, which most + * video sinks implement. See the documentation there for more details. + * + * + * Specifying which CD/DVD device to use + * The device to use for CDs/DVDs needs to be set on the source element + * playbin creates before it is opened. The only way to do this at the moment + * is to connect to playbin's "notify::source" signal, which will be emitted + * by playbin when it has created the source element for a particular URI. + * In the signal callback you can check if the source element has a "device" + * property and set it appropriately. In future ways might be added to specify + * the device as part of the URI, but at the time of writing this is not + * possible yet. + * + * + * Handling redirects + * + * Some elements may post 'redirect' messages on the bus to tell the + * application to open another location. These are element messages containing + * a structure named 'redirect' along with a 'new-location' field of string + * type. The new location may be a relative or an absolute URI. Examples + * for such redirects can be found in many quicktime movie trailers. + * + * + * + * Examples + * |[ + * gst-launch -v playbin uri=file:///path/to/somefile.avi + * ]| This will play back the given AVI video file, given that the video and + * audio decoders required to decode the content are installed. Since no + * special audio sink or video sink is supplied (not possible via gst-launch), + * playbin will try to find a suitable audio and video sink automatically + * using the autoaudiosink and autovideosink elements. + * |[ + * gst-launch -v playbin uri=cdda://4 + * ]| This will play back track 4 on an audio CD in your disc drive (assuming + * the drive is detected automatically by the plugin). + * |[ + * gst-launch -v playbin uri=dvd://1 + * ]| This will play back title 1 of a DVD in your disc drive (assuming + * the drive is detected automatically by the plugin). + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include + +#include "gstplay-enum.h" +#include "gstplay-marshal.h" +#include "gstplayback.h" +#include "gstplaysink.h" +#include "gstsubtitleoverlay.h" + +GST_DEBUG_CATEGORY_STATIC (gst_play_bin_debug); +#define GST_CAT_DEFAULT gst_play_bin_debug + +#define GST_TYPE_PLAY_BIN (gst_play_bin_get_type()) +#define GST_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_PLAY_BIN,GstPlayBin)) +#define GST_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_PLAY_BIN,GstPlayBinClass)) +#define GST_IS_PLAY_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_PLAY_BIN)) +#define GST_IS_PLAY_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_PLAY_BIN)) + +#define VOLUME_MAX_DOUBLE 10.0 + +typedef struct _GstPlayBin GstPlayBin; +typedef struct _GstPlayBinClass GstPlayBinClass; +typedef struct _GstSourceGroup GstSourceGroup; +typedef struct _GstSourceSelect GstSourceSelect; + +typedef GstCaps *(*SourceSelectGetMediaCapsFunc) (void); + +/* has the info for a selector and provides the link to the sink */ +struct _GstSourceSelect +{ + const gchar *media_list[8]; /* the media types for the selector */ + SourceSelectGetMediaCapsFunc get_media_caps; /* more complex caps for the selector */ + GstPlaySinkType type; /* the sink pad type of the selector */ + + GstElement *selector; /* the selector */ + GPtrArray *channels; + GstPad *srcpad; /* the source pad of the selector */ + GstPad *sinkpad; /* the sinkpad of the sink when the selector + * is linked + */ + GstEvent *sinkpad_delayed_event; + gulong sinkpad_data_probe; +}; + +#define GST_SOURCE_GROUP_GET_LOCK(group) (((GstSourceGroup*)(group))->lock) +#define GST_SOURCE_GROUP_LOCK(group) (g_mutex_lock (GST_SOURCE_GROUP_GET_LOCK(group))) +#define GST_SOURCE_GROUP_UNLOCK(group) (g_mutex_unlock (GST_SOURCE_GROUP_GET_LOCK(group))) + +/* a structure to hold the objects for decoding a uri and the subtitle uri + */ +struct _GstSourceGroup +{ + GstPlayBin *playbin; + + GMutex *lock; + + gboolean valid; /* the group has valid info to start playback */ + gboolean active; /* the group is active */ + + /* properties */ + gchar *uri; + gchar *suburi; + GValueArray *streaminfo; + GstElement *source; + + GPtrArray *video_channels; /* links to selector pads */ + GPtrArray *audio_channels; /* links to selector pads */ + GPtrArray *text_channels; /* links to selector pads */ + + GstElement *audio_sink; /* autoplugged audio and video sinks */ + GstElement *video_sink; + + /* uridecodebins for uri and subtitle uri */ + GstElement *uridecodebin; + GstElement *suburidecodebin; + gint pending; + gboolean sub_pending; + + gulong pad_added_id; + gulong pad_removed_id; + gulong no_more_pads_id; + gulong notify_source_id; + gulong drained_id; + gulong autoplug_factories_id; + gulong autoplug_select_id; + gulong autoplug_continue_id; + + gulong sub_pad_added_id; + gulong sub_pad_removed_id; + gulong sub_no_more_pads_id; + gulong sub_autoplug_continue_id; + + GMutex *stream_changed_pending_lock; + GList *stream_changed_pending; + + /* selectors for different streams */ + GstSourceSelect selector[GST_PLAY_SINK_TYPE_LAST]; +}; + +#define GST_PLAY_BIN_GET_LOCK(bin) (&((GstPlayBin*)(bin))->lock) +#define GST_PLAY_BIN_LOCK(bin) (g_static_rec_mutex_lock (GST_PLAY_BIN_GET_LOCK(bin))) +#define GST_PLAY_BIN_UNLOCK(bin) (g_static_rec_mutex_unlock (GST_PLAY_BIN_GET_LOCK(bin))) + +/* lock to protect dynamic callbacks, like no-more-pads */ +#define GST_PLAY_BIN_DYN_LOCK(bin) g_mutex_lock ((bin)->dyn_lock) +#define GST_PLAY_BIN_DYN_UNLOCK(bin) g_mutex_unlock ((bin)->dyn_lock) + +/* lock for shutdown */ +#define GST_PLAY_BIN_SHUTDOWN_LOCK(bin,label) \ +G_STMT_START { \ + if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) \ + goto label; \ + GST_PLAY_BIN_DYN_LOCK (bin); \ + if (G_UNLIKELY (g_atomic_int_get (&bin->shutdown))) { \ + GST_PLAY_BIN_DYN_UNLOCK (bin); \ + goto label; \ + } \ +} G_STMT_END + +/* unlock for shutdown */ +#define GST_PLAY_BIN_SHUTDOWN_UNLOCK(bin) \ + GST_PLAY_BIN_DYN_UNLOCK (bin); \ + +/** + * GstPlayBin2: + * + * playbin element structure + */ +struct _GstPlayBin +{ + GstPipeline parent; + + GStaticRecMutex lock; /* to protect group switching */ + + /* the groups, we use a double buffer to switch between current and next */ + GstSourceGroup groups[2]; /* array with group info */ + GstSourceGroup *curr_group; /* pointer to the currently playing group */ + GstSourceGroup *next_group; /* pointer to the next group */ + + /* properties */ + guint connection_speed; /* connection speed in bits/sec (0 = unknown) */ + gint current_video; /* the currently selected stream */ + gint current_audio; /* the currently selected stream */ + gint current_text; /* the currently selected stream */ + + guint64 buffer_duration; /* When buffering, the max buffer duration (ns) */ + guint buffer_size; /* When buffering, the max buffer size (bytes) */ + + /* our play sink */ + GstPlaySink *playsink; + + /* the last activated source */ + GstElement *source; + + /* lock protecting dynamic adding/removing */ + GMutex *dyn_lock; + /* if we are shutting down or not */ + gint shutdown; + + GMutex *elements_lock; + guint32 elements_cookie; + GList *elements; /* factories we can use for selecting elements */ + + gboolean have_selector; /* set to FALSE when we fail to create an + * input-selector, so that we only post a + * warning once */ + + GstElement *audio_sink; /* configured audio sink, or NULL */ + GstElement *video_sink; /* configured video sink, or NULL */ + GstElement *text_sink; /* configured text sink, or NULL */ + + struct + { + gboolean valid; + GstFormat format; + gint64 duration; + } duration[5]; /* cached durations */ + + guint64 ring_buffer_max_size; /* 0 means disabled */ +}; + +struct _GstPlayBinClass +{ + GstPipelineClass parent_class; + + /* notify app that the current uri finished decoding and it is possible to + * queue a new one for gapless playback */ + void (*about_to_finish) (GstPlayBin * playbin); + + /* notify app that number of audio/video/text streams changed */ + void (*video_changed) (GstPlayBin * playbin); + void (*audio_changed) (GstPlayBin * playbin); + void (*text_changed) (GstPlayBin * playbin); + + /* notify app that the tags of audio/video/text streams changed */ + void (*video_tags_changed) (GstPlayBin * playbin, gint stream); + void (*audio_tags_changed) (GstPlayBin * playbin, gint stream); + void (*text_tags_changed) (GstPlayBin * playbin, gint stream); + + /* get audio/video/text tags for a stream */ + GstTagList *(*get_video_tags) (GstPlayBin * playbin, gint stream); + GstTagList *(*get_audio_tags) (GstPlayBin * playbin, gint stream); + GstTagList *(*get_text_tags) (GstPlayBin * playbin, gint stream); + + /* get the last video frame and convert it to the given caps */ + GstBuffer *(*convert_frame) (GstPlayBin * playbin, GstCaps * caps); + + /* get audio/video/text pad for a stream */ + GstPad *(*get_video_pad) (GstPlayBin * playbin, gint stream); + GstPad *(*get_audio_pad) (GstPlayBin * playbin, gint stream); + GstPad *(*get_text_pad) (GstPlayBin * playbin, gint stream); +}; + +/* props */ +#define DEFAULT_URI NULL +#define DEFAULT_SUBURI NULL +#define DEFAULT_SOURCE NULL +#define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \ + GST_PLAY_FLAG_SOFT_VOLUME +#define DEFAULT_N_VIDEO 0 +#define DEFAULT_CURRENT_VIDEO -1 +#define DEFAULT_N_AUDIO 0 +#define DEFAULT_CURRENT_AUDIO -1 +#define DEFAULT_N_TEXT 0 +#define DEFAULT_CURRENT_TEXT -1 +#define DEFAULT_SUBTITLE_ENCODING NULL +#define DEFAULT_AUDIO_SINK NULL +#define DEFAULT_VIDEO_SINK NULL +#define DEFAULT_VIS_PLUGIN NULL +#define DEFAULT_TEXT_SINK NULL +#define DEFAULT_VOLUME 1.0 +#define DEFAULT_MUTE FALSE +#define DEFAULT_FRAME NULL +#define DEFAULT_FONT_DESC NULL +#define DEFAULT_CONNECTION_SPEED 0 +#define DEFAULT_BUFFER_DURATION -1 +#define DEFAULT_BUFFER_SIZE -1 +#define DEFAULT_RING_BUFFER_MAX_SIZE 0 + +enum +{ + PROP_0, + PROP_URI, + PROP_SUBURI, + PROP_SOURCE, + PROP_FLAGS, + PROP_N_VIDEO, + PROP_CURRENT_VIDEO, + PROP_N_AUDIO, + PROP_CURRENT_AUDIO, + PROP_N_TEXT, + PROP_CURRENT_TEXT, + PROP_SUBTITLE_ENCODING, + PROP_AUDIO_SINK, + PROP_VIDEO_SINK, + PROP_VIS_PLUGIN, + PROP_TEXT_SINK, + PROP_VOLUME, + PROP_MUTE, + PROP_FRAME, + PROP_FONT_DESC, + PROP_CONNECTION_SPEED, + PROP_BUFFER_SIZE, + PROP_BUFFER_DURATION, + PROP_AV_OFFSET, + PROP_RING_BUFFER_MAX_SIZE, + PROP_LAST +}; + +/* signals */ +enum +{ + SIGNAL_ABOUT_TO_FINISH, + SIGNAL_CONVERT_FRAME, + SIGNAL_VIDEO_CHANGED, + SIGNAL_AUDIO_CHANGED, + SIGNAL_TEXT_CHANGED, + SIGNAL_VIDEO_TAGS_CHANGED, + SIGNAL_AUDIO_TAGS_CHANGED, + SIGNAL_TEXT_TAGS_CHANGED, + SIGNAL_GET_VIDEO_TAGS, + SIGNAL_GET_AUDIO_TAGS, + SIGNAL_GET_TEXT_TAGS, + SIGNAL_GET_VIDEO_PAD, + SIGNAL_GET_AUDIO_PAD, + SIGNAL_GET_TEXT_PAD, + SIGNAL_SOURCE_SETUP, + LAST_SIGNAL +}; + +static void gst_play_bin_class_init (GstPlayBinClass * klass); +static void gst_play_bin_init (GstPlayBin * playbin); +static void gst_play_bin_finalize (GObject * object); + +static void gst_play_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_play_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); + +static GstStateChangeReturn gst_play_bin_change_state (GstElement * element, + GstStateChange transition); + +static void gst_play_bin_handle_message (GstBin * bin, GstMessage * message); +static gboolean gst_play_bin_query (GstElement * element, GstQuery * query); + +static GstTagList *gst_play_bin_get_video_tags (GstPlayBin * playbin, + gint stream); +static GstTagList *gst_play_bin_get_audio_tags (GstPlayBin * playbin, + gint stream); +static GstTagList *gst_play_bin_get_text_tags (GstPlayBin * playbin, + gint stream); + +static GstBuffer *gst_play_bin_convert_frame (GstPlayBin * playbin, + GstCaps * caps); + +static GstPad *gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream); +static GstPad *gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream); +static GstPad *gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream); + +static gboolean setup_next_source (GstPlayBin * playbin, GstState target); + +static void no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group); +static void pad_removed_cb (GstElement * decodebin, GstPad * pad, + GstSourceGroup * group); + +static void gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin, + gboolean block); +static void gst_play_bin_suburidecodebin_seek_to_start (GstElement * + suburidecodebin); + +static GstElementClass *parent_class; + +static guint gst_play_bin_signals[LAST_SIGNAL] = { 0 }; + +#define REMOVE_SIGNAL(obj,id) \ +if (id) { \ + g_signal_handler_disconnect (obj, id); \ + id = 0; \ +} + +static GType +gst_play_bin_get_type (void) +{ + static GType gst_play_bin_type = 0; + + if (!gst_play_bin_type) { + static const GTypeInfo gst_play_bin_info = { + sizeof (GstPlayBinClass), + NULL, + NULL, + (GClassInitFunc) gst_play_bin_class_init, + NULL, + NULL, + sizeof (GstPlayBin), + 0, + (GInstanceInitFunc) gst_play_bin_init, + NULL + }; + static const GInterfaceInfo svol_info = { + NULL, NULL, NULL + }; + + gst_play_bin_type = g_type_register_static (GST_TYPE_PIPELINE, + "GstPlayBin2", &gst_play_bin_info, 0); + + g_type_add_interface_static (gst_play_bin_type, GST_TYPE_STREAM_VOLUME, + &svol_info); + } + + return gst_play_bin_type; +} + +static void +gst_play_bin_class_init (GstPlayBinClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + GstBinClass *gstbin_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + gstbin_klass = (GstBinClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_play_bin_set_property; + gobject_klass->get_property = gst_play_bin_get_property; + + gobject_klass->finalize = gst_play_bin_finalize; + + /** + * GstPlayBin2:uri + * + * Set the next URI that playbin will play. This property can be set from the + * about-to-finish signal to queue the next media file. + */ + g_object_class_install_property (gobject_klass, PROP_URI, + g_param_spec_string ("uri", "URI", "URI of the media to play", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2:suburi + * + * Set the next subtitle URI that playbin will play. This property can be + * set from the about-to-finish signal to queue the next subtitle media file. + */ + g_object_class_install_property (gobject_klass, PROP_SUBURI, + g_param_spec_string ("suburi", ".sub-URI", "Optional URI of a subtitle", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_SOURCE, + g_param_spec_object ("source", "Source", "Source element", + GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2:flags + * + * Control the behaviour of playbin. + */ + g_object_class_install_property (gobject_klass, PROP_FLAGS, + g_param_spec_flags ("flags", "Flags", "Flags to control behaviour", + GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2:n-video + * + * Get the total number of available video streams. + */ + g_object_class_install_property (gobject_klass, PROP_N_VIDEO, + g_param_spec_int ("n-video", "Number Video", + "Total number of video streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:current-video + * + * Get or set the currently playing video stream. By default the first video + * stream with data is played. + */ + g_object_class_install_property (gobject_klass, PROP_CURRENT_VIDEO, + g_param_spec_int ("current-video", "Current Video", + "Currently playing video stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:n-audio + * + * Get the total number of available audio streams. + */ + g_object_class_install_property (gobject_klass, PROP_N_AUDIO, + g_param_spec_int ("n-audio", "Number Audio", + "Total number of audio streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:current-audio + * + * Get or set the currently playing audio stream. By default the first audio + * stream with data is played. + */ + g_object_class_install_property (gobject_klass, PROP_CURRENT_AUDIO, + g_param_spec_int ("current-audio", "Current audio", + "Currently playing audio stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:n-text + * + * Get the total number of available subtitle streams. + */ + g_object_class_install_property (gobject_klass, PROP_N_TEXT, + g_param_spec_int ("n-text", "Number Text", + "Total number of text streams", 0, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:current-text: + * + * Get or set the currently playing subtitle stream. By default the first + * subtitle stream with data is played. + */ + g_object_class_install_property (gobject_klass, PROP_CURRENT_TEXT, + g_param_spec_int ("current-text", "Current Text", + "Currently playing text stream (-1 = auto)", + -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK, + g_param_spec_object ("video-sink", "Video Sink", + "the video output element to use (NULL = default sink)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_AUDIO_SINK, + g_param_spec_object ("audio-sink", "Audio Sink", + "the audio output element to use (NULL = default sink)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN, + g_param_spec_object ("vis-plugin", "Vis plugin", + "the visualization element to use (NULL = default)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_TEXT_SINK, + g_param_spec_object ("text-sink", "Text plugin", + "the text output element to use (NULL = default textoverlay)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2:volume: + * + * Get or set the current audio stream volume. 1.0 means 100%, + * 0.0 means mute. This uses a linear volume scale. + * + */ + g_object_class_install_property (gobject_klass, PROP_VOLUME, + g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%", + 0.0, VOLUME_MAX_DOUBLE, 1.0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", + "Mute the audio channel without changing the volume", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2:frame: + * @playbin: a #GstPlayBin2 + * + * Get the currently rendered or prerolled frame in the video sink. + * The #GstCaps on the buffer will describe the format of the buffer. + */ + g_object_class_install_property (gobject_klass, PROP_FRAME, + gst_param_spec_mini_object ("frame", "Frame", + "The last frame (NULL = no video available)", + GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_FONT_DESC, + g_param_spec_string ("subtitle-font-desc", + "Subtitle font description", + "Pango font description of font " + "to be used for subtitle rendering", NULL, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_CONNECTION_SPEED, + g_param_spec_uint ("connection-speed", "Connection Speed", + "Network connection speed in kbps (0 = unknown)", + 0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_klass, PROP_BUFFER_SIZE, + g_param_spec_int ("buffer-size", "Buffer size (bytes)", + "Buffer size when buffering network streams", + -1, G_MAXINT, DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_BUFFER_DURATION, + g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)", + "Buffer duration when buffering network streams", + -1, G_MAXINT64, DEFAULT_BUFFER_DURATION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlayBin2:av-offset: + * + * Control the synchronisation offset between the audio and video streams. + * Positive values make the audio ahead of the video and negative values make + * the audio go behind the video. + * + * Since: 0.10.30 + */ + g_object_class_install_property (gobject_klass, PROP_AV_OFFSET, + g_param_spec_int64 ("av-offset", "AV Offset", + "The synchronisation offset between audio and video in nanoseconds", + G_MININT64, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstQueue2:ring-buffer-max-size + * + * The maximum size of the ring buffer in bytes. If set to 0, the ring + * buffer is disabled. Default 0. + * + * Since: 0.10.31 + */ + g_object_class_install_property (gobject_klass, PROP_RING_BUFFER_MAX_SIZE, + g_param_spec_uint64 ("ring-buffer-max-size", + "Max. ring buffer size (bytes)", + "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)", + 0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlayBin2::about-to-finish + * @playbin: a #GstPlayBin2 + * + * This signal is emitted when the current uri is about to finish. You can + * set the uri and suburi to make sure that playback continues. + */ + gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH] = + g_signal_new ("about-to-finish", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, about_to_finish), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstPlayBin2::video-changed + * @playbin: a #GstPlayBin2 + * + * This signal is emitted whenever the number or order of the video + * streams has changed. The application will most likely want to select + * a new video stream. + */ + gst_play_bin_signals[SIGNAL_VIDEO_CHANGED] = + g_signal_new ("video-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, video_changed), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstPlayBin2::audio-changed + * @playbin: a #GstPlayBin2 + * + * This signal is emitted whenever the number or order of the audio + * streams has changed. The application will most likely want to select + * a new audio stream. + */ + gst_play_bin_signals[SIGNAL_AUDIO_CHANGED] = + g_signal_new ("audio-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, audio_changed), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + /** + * GstPlayBin2::text-changed + * @playbin: a #GstPlayBin2 + * + * This signal is emitted whenever the number or order of the text + * streams has changed. The application will most likely want to select + * a new text stream. + */ + gst_play_bin_signals[SIGNAL_TEXT_CHANGED] = + g_signal_new ("text-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, text_changed), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstPlayBin2::video-tags-changed + * @playbin: a #GstPlayBin2 + * @stream: stream index with changed tags + * + * This signal is emitted whenever the tags of a video stream have changed. + * The application will most likely want to get the new tags. + * + * Since: 0.10.24 + */ + gst_play_bin_signals[SIGNAL_VIDEO_TAGS_CHANGED] = + g_signal_new ("video-tags-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, video_tags_changed), NULL, NULL, + gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + /** + * GstPlayBin2::audio-tags-changed + * @playbin: a #GstPlayBin2 + * @stream: stream index with changed tags + * + * This signal is emitted whenever the tags of an audio stream have changed. + * The application will most likely want to get the new tags. + * + * Since: 0.10.24 + */ + gst_play_bin_signals[SIGNAL_AUDIO_TAGS_CHANGED] = + g_signal_new ("audio-tags-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, audio_tags_changed), NULL, NULL, + gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + /** + * GstPlayBin2::text-tags-changed + * @playbin: a #GstPlayBin2 + * @stream: stream index with changed tags + * + * This signal is emitted whenever the tags of a text stream have changed. + * The application will most likely want to get the new tags. + * + * Since: 0.10.24 + */ + gst_play_bin_signals[SIGNAL_TEXT_TAGS_CHANGED] = + g_signal_new ("text-tags-changed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstPlayBinClass, text_tags_changed), NULL, NULL, + gst_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + /** + * GstPlayBin2::source-setup: + * @playbin: a #GstPlayBin2 + * @source: source element + * + * This signal is emitted after the source element has been created, so + * it can be configured by setting additional properties (e.g. set a + * proxy server for an http source, or set the device and read speed for + * an audio cd source). This is functionally equivalent to connecting to + * the notify::source signal, but more convenient. + * + * Since: 0.10.33 + */ + gst_play_bin_signals[SIGNAL_SOURCE_SETUP] = + g_signal_new ("source-setup", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + + /** + * GstPlayBin2::get-video-tags + * @playbin: a #GstPlayBin2 + * @stream: a video stream number + * + * Action signal to retrieve the tags of a specific video stream number. + * This information can be used to select a stream. + * + * Returns: a GstTagList with tags or NULL when the stream number does not + * exist. + */ + gst_play_bin_signals[SIGNAL_GET_VIDEO_TAGS] = + g_signal_new ("get-video-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_video_tags), NULL, NULL, + gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); + /** + * GstPlayBin2::get-audio-tags + * @playbin: a #GstPlayBin2 + * @stream: an audio stream number + * + * Action signal to retrieve the tags of a specific audio stream number. + * This information can be used to select a stream. + * + * Returns: a GstTagList with tags or NULL when the stream number does not + * exist. + */ + gst_play_bin_signals[SIGNAL_GET_AUDIO_TAGS] = + g_signal_new ("get-audio-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_audio_tags), NULL, NULL, + gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); + /** + * GstPlayBin2::get-text-tags + * @playbin: a #GstPlayBin2 + * @stream: a text stream number + * + * Action signal to retrieve the tags of a specific text stream number. + * This information can be used to select a stream. + * + * Returns: a GstTagList with tags or NULL when the stream number does not + * exist. + */ + gst_play_bin_signals[SIGNAL_GET_TEXT_TAGS] = + g_signal_new ("get-text-tags", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_text_tags), NULL, NULL, + gst_play_marshal_BOXED__INT, GST_TYPE_TAG_LIST, 1, G_TYPE_INT); + /** + * GstPlayBin2::convert-frame + * @playbin: a #GstPlayBin2 + * @caps: the target format of the frame + * + * Action signal to retrieve the currently playing video frame in the format + * specified by @caps. + * If @caps is %NULL, no conversion will be performed and this function is + * equivalent to the #GstPlayBin::frame property. + * + * Returns: a #GstBuffer of the current video frame converted to #caps. + * The caps on the buffer will describe the final layout of the buffer data. + * %NULL is returned when no current buffer can be retrieved or when the + * conversion failed. + */ + gst_play_bin_signals[SIGNAL_CONVERT_FRAME] = + g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, convert_frame), NULL, NULL, + gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS); + + /** + * GstPlayBin2::get-video-pad + * @playbin: a #GstPlayBin2 + * @stream: a video stream number + * + * Action signal to retrieve the stream-selector sinkpad for a specific + * video stream. + * This pad can be used for notifications of caps changes, stream-specific + * queries, etc. + * + * Returns: a #GstPad, or NULL when the stream number does not exist. + */ + gst_play_bin_signals[SIGNAL_GET_VIDEO_PAD] = + g_signal_new ("get-video-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_video_pad), NULL, NULL, + gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT); + /** + * GstPlayBin2::get-audio-pad + * @playbin: a #GstPlayBin2 + * @stream: an audio stream number + * + * Action signal to retrieve the stream-selector sinkpad for a specific + * audio stream. + * This pad can be used for notifications of caps changes, stream-specific + * queries, etc. + * + * Returns: a #GstPad, or NULL when the stream number does not exist. + */ + gst_play_bin_signals[SIGNAL_GET_AUDIO_PAD] = + g_signal_new ("get-audio-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_audio_pad), NULL, NULL, + gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT); + /** + * GstPlayBin2::get-text-pad + * @playbin: a #GstPlayBin2 + * @stream: a text stream number + * + * Action signal to retrieve the stream-selector sinkpad for a specific + * text stream. + * This pad can be used for notifications of caps changes, stream-specific + * queries, etc. + * + * Returns: a #GstPad, or NULL when the stream number does not exist. + */ + gst_play_bin_signals[SIGNAL_GET_TEXT_PAD] = + g_signal_new ("get-text-pad", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlayBinClass, get_text_pad), NULL, NULL, + gst_play_marshal_OBJECT__INT, GST_TYPE_PAD, 1, G_TYPE_INT); + + klass->get_video_tags = gst_play_bin_get_video_tags; + klass->get_audio_tags = gst_play_bin_get_audio_tags; + klass->get_text_tags = gst_play_bin_get_text_tags; + + klass->convert_frame = gst_play_bin_convert_frame; + + klass->get_video_pad = gst_play_bin_get_video_pad; + klass->get_audio_pad = gst_play_bin_get_audio_pad; + klass->get_text_pad = gst_play_bin_get_text_pad; + + gst_element_class_set_details_simple (gstelement_klass, + "Player Bin 2", "Generic/Bin/Player", + "Autoplug and play media from an uri", + "Wim Taymans "); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_play_bin_change_state); + gstelement_klass->query = GST_DEBUG_FUNCPTR (gst_play_bin_query); + + gstbin_klass->handle_message = + GST_DEBUG_FUNCPTR (gst_play_bin_handle_message); +} + +static void +init_group (GstPlayBin * playbin, GstSourceGroup * group) +{ + int n; + + /* store the array for the different channels */ + group->video_channels = g_ptr_array_new (); + group->audio_channels = g_ptr_array_new (); + group->text_channels = g_ptr_array_new (); + group->lock = g_mutex_new (); + /* init selectors. The selector is found by finding the first prefix that + * matches the media. */ + group->playbin = playbin; + /* If you add any items to these lists, check that media_list[] is defined + * above to be large enough to hold MAX(items)+1, so as to accomodate a + * NULL terminator (set when the memory is zeroed on allocation) */ + group->selector[0].media_list[0] = "audio/x-raw-"; + group->selector[0].type = GST_PLAY_SINK_TYPE_AUDIO_RAW; + group->selector[0].channels = group->audio_channels; + group->selector[1].media_list[0] = "audio/"; + group->selector[1].type = GST_PLAY_SINK_TYPE_AUDIO; + group->selector[1].channels = group->audio_channels; + group->selector[2].media_list[0] = "text/"; + group->selector[2].media_list[1] = "application/x-subtitle"; + group->selector[2].media_list[2] = "application/x-ssa"; + group->selector[2].media_list[3] = "application/x-ass"; + group->selector[2].media_list[4] = "video/x-dvd-subpicture"; + group->selector[2].media_list[5] = "subpicture/"; + group->selector[2].media_list[6] = "subtitle/"; + group->selector[2].get_media_caps = gst_subtitle_overlay_create_factory_caps; + group->selector[2].type = GST_PLAY_SINK_TYPE_TEXT; + group->selector[2].channels = group->text_channels; + group->selector[3].media_list[0] = "video/x-raw-"; + group->selector[3].type = GST_PLAY_SINK_TYPE_VIDEO_RAW; + group->selector[3].channels = group->video_channels; + group->selector[4].media_list[0] = "video/"; + group->selector[4].type = GST_PLAY_SINK_TYPE_VIDEO; + group->selector[4].channels = group->video_channels; + + for (n = 0; n < GST_PLAY_SINK_TYPE_LAST; n++) { + GstSourceSelect *select = &group->selector[n]; + select->sinkpad_delayed_event = NULL; + select->sinkpad_data_probe = 0; + } +} + +static void +free_group (GstPlayBin * playbin, GstSourceGroup * group) +{ + int n; + + for (n = 0; n < GST_PLAY_SINK_TYPE_LAST; n++) { + GstSourceSelect *select = &group->selector[n]; + if (select->sinkpad && select->sinkpad_data_probe) + gst_pad_remove_data_probe (select->sinkpad, select->sinkpad_data_probe); + if (select->sinkpad_delayed_event) + gst_event_unref (select->sinkpad_delayed_event); + } + + g_free (group->uri); + g_free (group->suburi); + g_ptr_array_free (group->video_channels, TRUE); + g_ptr_array_free (group->audio_channels, TRUE); + g_ptr_array_free (group->text_channels, TRUE); + + g_mutex_free (group->lock); + if (group->audio_sink) { + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + + g_list_free (group->stream_changed_pending); + group->stream_changed_pending = NULL; + + if (group->stream_changed_pending_lock) + g_mutex_free (group->stream_changed_pending_lock); + group->stream_changed_pending_lock = NULL; +} + +static void +notify_volume_cb (GObject * selector, GParamSpec * pspec, GstPlayBin * playbin) +{ + g_object_notify (G_OBJECT (playbin), "volume"); +} + +static void +notify_mute_cb (GObject * selector, GParamSpec * pspec, GstPlayBin * playbin) +{ + g_object_notify (G_OBJECT (playbin), "mute"); +} + +/* Must be called with elements lock! */ +static void +gst_play_bin_update_elements_list (GstPlayBin * playbin) +{ + GList *res, *tmp; + + if (!playbin->elements || + playbin->elements_cookie != + gst_default_registry_get_feature_list_cookie ()) { + if (playbin->elements) + gst_plugin_feature_list_free (playbin->elements); + res = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL); + tmp = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_AUDIOVIDEO_SINKS, GST_RANK_MARGINAL); + playbin->elements = g_list_concat (res, tmp); + playbin->elements = + g_list_sort (playbin->elements, gst_plugin_feature_rank_compare_func); + playbin->elements_cookie = gst_default_registry_get_feature_list_cookie (); + } +} + +static void +gst_play_bin_init (GstPlayBin * playbin) +{ + g_static_rec_mutex_init (&playbin->lock); + playbin->dyn_lock = g_mutex_new (); + + /* assume we can create a selector */ + playbin->have_selector = TRUE; + + /* init groups */ + playbin->curr_group = &playbin->groups[0]; + playbin->next_group = &playbin->groups[1]; + init_group (playbin, &playbin->groups[0]); + init_group (playbin, &playbin->groups[1]); + + /* first filter out the interesting element factories */ + playbin->elements_lock = g_mutex_new (); + + /* add sink */ + playbin->playsink = g_object_new (GST_TYPE_PLAY_SINK, NULL); + gst_bin_add (GST_BIN_CAST (playbin), GST_ELEMENT_CAST (playbin->playsink)); + gst_play_sink_set_flags (playbin->playsink, DEFAULT_FLAGS); + /* Connect to notify::volume and notify::mute signals for proxying */ + g_signal_connect (playbin->playsink, "notify::volume", + G_CALLBACK (notify_volume_cb), playbin); + g_signal_connect (playbin->playsink, "notify::mute", + G_CALLBACK (notify_mute_cb), playbin); + + playbin->current_video = DEFAULT_CURRENT_VIDEO; + playbin->current_audio = DEFAULT_CURRENT_AUDIO; + playbin->current_text = DEFAULT_CURRENT_TEXT; + + playbin->buffer_duration = DEFAULT_BUFFER_DURATION; + playbin->buffer_size = DEFAULT_BUFFER_SIZE; + playbin->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE; +} + +static void +gst_play_bin_finalize (GObject * object) +{ + GstPlayBin *playbin; + + playbin = GST_PLAY_BIN (object); + + free_group (playbin, &playbin->groups[0]); + free_group (playbin, &playbin->groups[1]); + + if (playbin->source) + gst_object_unref (playbin->source); + if (playbin->video_sink) { + gst_element_set_state (playbin->video_sink, GST_STATE_NULL); + gst_object_unref (playbin->video_sink); + } + if (playbin->audio_sink) { + gst_element_set_state (playbin->audio_sink, GST_STATE_NULL); + gst_object_unref (playbin->audio_sink); + } + if (playbin->text_sink) { + gst_element_set_state (playbin->text_sink, GST_STATE_NULL); + gst_object_unref (playbin->text_sink); + } + + if (playbin->elements) + gst_plugin_feature_list_free (playbin->elements); + + g_static_rec_mutex_free (&playbin->lock); + g_mutex_free (playbin->dyn_lock); + g_mutex_free (playbin->elements_lock); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_play_bin_set_uri (GstPlayBin * playbin, const gchar * uri) +{ + GstSourceGroup *group; + + if (uri == NULL) { + g_warning ("cannot set NULL uri"); + return; + } + + GST_PLAY_BIN_LOCK (playbin); + group = playbin->next_group; + + GST_SOURCE_GROUP_LOCK (group); + /* store the uri in the next group we will play */ + g_free (group->uri); + group->uri = g_strdup (uri); + group->valid = TRUE; + GST_SOURCE_GROUP_UNLOCK (group); + + GST_DEBUG ("set new uri to %s", uri); + GST_PLAY_BIN_UNLOCK (playbin); +} + +static void +gst_play_bin_set_suburi (GstPlayBin * playbin, const gchar * suburi) +{ + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = playbin->next_group; + + GST_SOURCE_GROUP_LOCK (group); + g_free (group->suburi); + group->suburi = g_strdup (suburi); + GST_SOURCE_GROUP_UNLOCK (group); + + GST_DEBUG ("setting new .sub uri to %s", suburi); + + GST_PLAY_BIN_UNLOCK (playbin); +} + +static void +gst_play_bin_set_flags (GstPlayBin * playbin, GstPlayFlags flags) +{ + gst_play_sink_set_flags (playbin->playsink, flags); + gst_play_sink_reconfigure (playbin->playsink); +} + +static GstPlayFlags +gst_play_bin_get_flags (GstPlayBin * playbin) +{ + GstPlayFlags flags; + + flags = gst_play_sink_get_flags (playbin->playsink); + + return flags; +} + +/* get the currently playing group or if nothing is playing, the next + * group. Must be called with the PLAY_BIN_LOCK. */ +static GstSourceGroup * +get_group (GstPlayBin * playbin) +{ + GstSourceGroup *result; + + if (!(result = playbin->curr_group)) + result = playbin->next_group; + + return result; +} + +static GstPad * +gst_play_bin_get_video_pad (GstPlayBin * playbin, gint stream) +{ + GstPad *sinkpad = NULL; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (stream < group->video_channels->len) { + sinkpad = g_ptr_array_index (group->video_channels, stream); + gst_object_ref (sinkpad); + } + GST_PLAY_BIN_UNLOCK (playbin); + + return sinkpad; +} + +static GstPad * +gst_play_bin_get_audio_pad (GstPlayBin * playbin, gint stream) +{ + GstPad *sinkpad = NULL; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (stream < group->audio_channels->len) { + sinkpad = g_ptr_array_index (group->audio_channels, stream); + gst_object_ref (sinkpad); + } + GST_PLAY_BIN_UNLOCK (playbin); + + return sinkpad; +} + +static GstPad * +gst_play_bin_get_text_pad (GstPlayBin * playbin, gint stream) +{ + GstPad *sinkpad = NULL; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (stream < group->text_channels->len) { + sinkpad = g_ptr_array_index (group->text_channels, stream); + gst_object_ref (sinkpad); + } + GST_PLAY_BIN_UNLOCK (playbin); + + return sinkpad; +} + + +static GstTagList * +get_tags (GstPlayBin * playbin, GPtrArray * channels, gint stream) +{ + GstTagList *result; + GstPad *sinkpad; + + if (!channels || stream >= channels->len) + return NULL; + + sinkpad = g_ptr_array_index (channels, stream); + g_object_get (sinkpad, "tags", &result, NULL); + + return result; +} + +static GstTagList * +gst_play_bin_get_video_tags (GstPlayBin * playbin, gint stream) +{ + GstTagList *result; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + result = get_tags (playbin, group->video_channels, stream); + GST_PLAY_BIN_UNLOCK (playbin); + + return result; +} + +static GstTagList * +gst_play_bin_get_audio_tags (GstPlayBin * playbin, gint stream) +{ + GstTagList *result; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + result = get_tags (playbin, group->audio_channels, stream); + GST_PLAY_BIN_UNLOCK (playbin); + + return result; +} + +static GstTagList * +gst_play_bin_get_text_tags (GstPlayBin * playbin, gint stream) +{ + GstTagList *result; + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + result = get_tags (playbin, group->text_channels, stream); + GST_PLAY_BIN_UNLOCK (playbin); + + return result; +} + +static GstBuffer * +gst_play_bin_convert_frame (GstPlayBin * playbin, GstCaps * caps) +{ + return gst_play_sink_convert_frame (playbin->playsink, caps); +} + +/* Returns current stream number, or -1 if none has been selected yet */ +static int +get_current_stream_number (GstPlayBin * playbin, GPtrArray * channels) +{ + /* Internal API cleanup would make this easier... */ + int i; + GstPad *pad, *current; + GstObject *selector = NULL; + int ret = -1; + + for (i = 0; i < channels->len; i++) { + pad = g_ptr_array_index (channels, i); + if ((selector = gst_pad_get_parent (pad))) { + g_object_get (selector, "active-pad", ¤t, NULL); + gst_object_unref (selector); + + if (pad == current) { + gst_object_unref (current); + ret = i; + break; + } + + if (current) + gst_object_unref (current); + } + } + + return ret; +} + +static gboolean +gst_play_bin_set_current_video_stream (GstPlayBin * playbin, gint stream) +{ + GstSourceGroup *group; + GPtrArray *channels; + GstPad *sinkpad; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (!(channels = group->video_channels)) + goto no_channels; + + if (stream == -1 || channels->len <= stream) { + sinkpad = NULL; + } else { + /* take channel from selected stream */ + sinkpad = g_ptr_array_index (channels, stream); + } + + if (sinkpad) + gst_object_ref (sinkpad); + GST_PLAY_BIN_UNLOCK (playbin); + + if (sinkpad) { + GstObject *selector; + + if ((selector = gst_pad_get_parent (sinkpad))) { + /* activate the selected pad */ + g_object_set (selector, "active-pad", sinkpad, NULL); + gst_object_unref (selector); + } + gst_object_unref (sinkpad); + } + return TRUE; + +no_channels: + { + GST_PLAY_BIN_UNLOCK (playbin); + GST_DEBUG_OBJECT (playbin, "can't switch video, we have no channels"); + return FALSE; + } +} + +static gboolean +gst_play_bin_set_current_audio_stream (GstPlayBin * playbin, gint stream) +{ + GstSourceGroup *group; + GPtrArray *channels; + GstPad *sinkpad; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (!(channels = group->audio_channels)) + goto no_channels; + + if (stream == -1 || channels->len <= stream) { + sinkpad = NULL; + } else { + /* take channel from selected stream */ + sinkpad = g_ptr_array_index (channels, stream); + } + + if (sinkpad) + gst_object_ref (sinkpad); + GST_PLAY_BIN_UNLOCK (playbin); + + if (sinkpad) { + GstObject *selector; + + if ((selector = gst_pad_get_parent (sinkpad))) { + /* activate the selected pad */ + g_object_set (selector, "active-pad", sinkpad, NULL); + gst_object_unref (selector); + } + gst_object_unref (sinkpad); + } + return TRUE; + +no_channels: + { + GST_PLAY_BIN_UNLOCK (playbin); + GST_DEBUG_OBJECT (playbin, "can't switch audio, we have no channels"); + return FALSE; + } +} + +static void +_suburidecodebin_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data) +{ + GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked); +} + +static void +gst_play_bin_suburidecodebin_seek_to_start (GstElement * suburidecodebin) +{ + GstIterator *it = gst_element_iterate_src_pads (suburidecodebin); + GstPad *sinkpad; + + if (it && gst_iterator_next (it, (gpointer) & sinkpad) == GST_ITERATOR_OK + && sinkpad) { + GstEvent *event; + + event = + gst_event_new_seek (1.0, GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + if (!gst_pad_send_event (sinkpad, event)) { + event = + gst_event_new_seek (1.0, GST_FORMAT_TIME, GST_SEEK_FLAG_NONE, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1); + if (!gst_pad_send_event (sinkpad, event)) + GST_DEBUG_OBJECT (suburidecodebin, "Seeking to the beginning failed!"); + } + + gst_object_unref (sinkpad); + } + + if (it) + gst_iterator_free (it); +} + +static void +gst_play_bin_suburidecodebin_block (GstElement * suburidecodebin, + gboolean block) +{ + GstIterator *it = gst_element_iterate_src_pads (suburidecodebin); + gboolean done = FALSE; + + GST_DEBUG_OBJECT (suburidecodebin, "Blocking suburidecodebin: %d", block); + + if (!it) + return; + while (!done) { + GstPad *sinkpad; + + switch (gst_iterator_next (it, (gpointer) & sinkpad)) { + case GST_ITERATOR_OK: + gst_pad_set_blocked_async (sinkpad, block, _suburidecodebin_blocked_cb, + NULL); + gst_object_unref (sinkpad); + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + } + } + gst_iterator_free (it); +} + +static gboolean +gst_play_bin_set_current_text_stream (GstPlayBin * playbin, gint stream) +{ + GstSourceGroup *group; + GPtrArray *channels; + GstPad *sinkpad; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + if (!(channels = group->text_channels)) + goto no_channels; + + if (stream == -1 || channels->len <= stream) { + sinkpad = NULL; + } else { + /* take channel from selected stream */ + sinkpad = g_ptr_array_index (channels, stream); + } + + if (sinkpad) + gst_object_ref (sinkpad); + GST_PLAY_BIN_UNLOCK (playbin); + + if (sinkpad) { + GstObject *selector; + + if ((selector = gst_pad_get_parent (sinkpad))) { + GstPad *old_sinkpad; + + g_object_get (selector, "active-pad", &old_sinkpad, NULL); + + if (old_sinkpad != sinkpad) { + gboolean need_unblock, need_block, need_seek; + GstPad *src, *peer = NULL, *oldpeer = NULL; + GstElement *parent_element = NULL, *old_parent_element = NULL; + + /* Now check if we need to seek the suburidecodebin to the beginning + * or if we need to block all suburidecodebin sinkpads or if we need + * to unblock all suburidecodebin sinkpads + */ + if (sinkpad) + peer = gst_pad_get_peer (sinkpad); + if (old_sinkpad) + oldpeer = gst_pad_get_peer (old_sinkpad); + + if (peer) + parent_element = gst_pad_get_parent_element (peer); + if (oldpeer) + old_parent_element = gst_pad_get_parent_element (oldpeer); + + need_block = (old_parent_element == group->suburidecodebin + && parent_element != old_parent_element); + need_unblock = (parent_element == group->suburidecodebin + && parent_element != old_parent_element); + need_seek = (parent_element == group->suburidecodebin); + + if (peer) + gst_object_unref (peer); + if (oldpeer) + gst_object_unref (oldpeer); + if (parent_element) + gst_object_unref (parent_element); + if (old_parent_element) + gst_object_unref (old_parent_element); + + /* Block all suburidecodebin sinkpads */ + if (need_block) + gst_play_bin_suburidecodebin_block (group->suburidecodebin, TRUE); + + /* activate the selected pad */ + g_object_set (selector, "active-pad", sinkpad, NULL); + + src = gst_element_get_static_pad (GST_ELEMENT_CAST (selector), "src"); + peer = gst_pad_get_peer (src); + if (peer) { + GstStructure *s; + GstEvent *event; + /* Flush the subtitle renderer to remove any + * currently displayed subtitles. This event will + * never travel outside subtitleoverlay! + */ + s = gst_structure_empty_new ("subtitleoverlay-flush-subtitle"); + event = gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM_OOB, s); + gst_pad_send_event (peer, event); + gst_object_unref (peer); + } + gst_object_unref (src); + + /* Unblock pads if necessary */ + if (need_unblock) + gst_play_bin_suburidecodebin_block (group->suburidecodebin, FALSE); + + /* seek to the beginning */ + if (need_seek) + gst_play_bin_suburidecodebin_seek_to_start (group->suburidecodebin); + } + gst_object_unref (selector); + + if (old_sinkpad) + gst_object_unref (old_sinkpad); + } + gst_object_unref (sinkpad); + } + return TRUE; + +no_channels: + { + GST_PLAY_BIN_UNLOCK (playbin); + return FALSE; + } +} + +static void +gst_play_bin_set_sink (GstPlayBin * playbin, GstElement ** elem, + const gchar * dbg, GstElement * sink) +{ + GST_INFO_OBJECT (playbin, "Setting %s sink to %" GST_PTR_FORMAT, dbg, sink); + + GST_PLAY_BIN_LOCK (playbin); + if (*elem != sink) { + GstElement *old; + + old = *elem; + if (sink) + gst_object_ref_sink (sink); + + *elem = sink; + if (old) + gst_object_unref (old); + } + GST_LOG_OBJECT (playbin, "%s sink now %" GST_PTR_FORMAT, dbg, *elem); + GST_PLAY_BIN_UNLOCK (playbin); +} + +static void +gst_play_bin_set_encoding (GstPlayBin * playbin, const gchar * encoding) +{ + GstElement *elem; + + GST_PLAY_BIN_LOCK (playbin); + + /* set subtitles on all current and next decodebins. */ + if ((elem = playbin->groups[0].uridecodebin)) + g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL); + if ((elem = playbin->groups[0].suburidecodebin)) + g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL); + if ((elem = playbin->groups[1].uridecodebin)) + g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL); + if ((elem = playbin->groups[1].suburidecodebin)) + g_object_set (G_OBJECT (elem), "subtitle-encoding", encoding, NULL); + + gst_play_sink_set_subtitle_encoding (playbin->playsink, encoding); + GST_PLAY_BIN_UNLOCK (playbin); +} + +static void +gst_play_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstPlayBin *playbin = GST_PLAY_BIN (object); + + switch (prop_id) { + case PROP_URI: + gst_play_bin_set_uri (playbin, g_value_get_string (value)); + break; + case PROP_SUBURI: + gst_play_bin_set_suburi (playbin, g_value_get_string (value)); + break; + case PROP_FLAGS: + gst_play_bin_set_flags (playbin, g_value_get_flags (value)); + break; + case PROP_CURRENT_VIDEO: + gst_play_bin_set_current_video_stream (playbin, g_value_get_int (value)); + break; + case PROP_CURRENT_AUDIO: + gst_play_bin_set_current_audio_stream (playbin, g_value_get_int (value)); + break; + case PROP_CURRENT_TEXT: + gst_play_bin_set_current_text_stream (playbin, g_value_get_int (value)); + break; + case PROP_SUBTITLE_ENCODING: + gst_play_bin_set_encoding (playbin, g_value_get_string (value)); + break; + case PROP_VIDEO_SINK: + gst_play_bin_set_sink (playbin, &playbin->video_sink, "video", + g_value_get_object (value)); + break; + case PROP_AUDIO_SINK: + gst_play_bin_set_sink (playbin, &playbin->audio_sink, "audio", + g_value_get_object (value)); + break; + case PROP_VIS_PLUGIN: + gst_play_sink_set_vis_plugin (playbin->playsink, + g_value_get_object (value)); + break; + case PROP_TEXT_SINK: + gst_play_bin_set_sink (playbin, &playbin->text_sink, "text", + g_value_get_object (value)); + break; + case PROP_VOLUME: + gst_play_sink_set_volume (playbin->playsink, g_value_get_double (value)); + break; + case PROP_MUTE: + gst_play_sink_set_mute (playbin->playsink, g_value_get_boolean (value)); + break; + case PROP_FONT_DESC: + gst_play_sink_set_font_desc (playbin->playsink, + g_value_get_string (value)); + break; + case PROP_CONNECTION_SPEED: + GST_PLAY_BIN_LOCK (playbin); + playbin->connection_speed = g_value_get_uint (value) * 1000; + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_BUFFER_SIZE: + playbin->buffer_size = g_value_get_int (value); + break; + case PROP_BUFFER_DURATION: + playbin->buffer_duration = g_value_get_int64 (value); + break; + case PROP_AV_OFFSET: + gst_play_sink_set_av_offset (playbin->playsink, + g_value_get_int64 (value)); + break; + case PROP_RING_BUFFER_MAX_SIZE: + playbin->ring_buffer_max_size = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstElement * +gst_play_bin_get_current_sink (GstPlayBin * playbin, GstElement ** elem, + const gchar * dbg, GstPlaySinkType type) +{ + GstElement *sink = gst_play_sink_get_sink (playbin->playsink, type); + + GST_LOG_OBJECT (playbin, "play_sink_get_sink() returned %s sink %" + GST_PTR_FORMAT ", the originally set %s sink is %" GST_PTR_FORMAT, + dbg, sink, dbg, *elem); + + if (sink == NULL) { + GST_PLAY_BIN_LOCK (playbin); + if ((sink = *elem)) + gst_object_ref (sink); + GST_PLAY_BIN_UNLOCK (playbin); + } + + return sink; +} + +static void +gst_play_bin_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstPlayBin *playbin = GST_PLAY_BIN (object); + + switch (prop_id) { + case PROP_URI: + { + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + g_value_set_string (value, group->uri); + GST_PLAY_BIN_UNLOCK (playbin); + break; + } + case PROP_SUBURI: + { + GstSourceGroup *group; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + g_value_set_string (value, group->suburi); + GST_PLAY_BIN_UNLOCK (playbin); + break; + } + case PROP_SOURCE: + { + GST_OBJECT_LOCK (playbin); + g_value_set_object (value, playbin->source); + GST_OBJECT_UNLOCK (playbin); + break; + } + case PROP_FLAGS: + g_value_set_flags (value, gst_play_bin_get_flags (playbin)); + break; + case PROP_N_VIDEO: + { + GstSourceGroup *group; + gint n_video; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + n_video = (group->video_channels ? group->video_channels->len : 0); + g_value_set_int (value, n_video); + GST_PLAY_BIN_UNLOCK (playbin); + break; + } + case PROP_CURRENT_VIDEO: + GST_PLAY_BIN_LOCK (playbin); + g_value_set_int (value, playbin->current_video); + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_N_AUDIO: + { + GstSourceGroup *group; + gint n_audio; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + n_audio = (group->audio_channels ? group->audio_channels->len : 0); + g_value_set_int (value, n_audio); + GST_PLAY_BIN_UNLOCK (playbin); + break; + } + case PROP_CURRENT_AUDIO: + GST_PLAY_BIN_LOCK (playbin); + g_value_set_int (value, playbin->current_audio); + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_N_TEXT: + { + GstSourceGroup *group; + gint n_text; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + n_text = (group->text_channels ? group->text_channels->len : 0); + g_value_set_int (value, n_text); + GST_PLAY_BIN_UNLOCK (playbin); + break; + } + case PROP_CURRENT_TEXT: + GST_PLAY_BIN_LOCK (playbin); + g_value_set_int (value, playbin->current_text); + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_SUBTITLE_ENCODING: + GST_PLAY_BIN_LOCK (playbin); + g_value_take_string (value, + gst_play_sink_get_subtitle_encoding (playbin->playsink)); + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_VIDEO_SINK: + g_value_take_object (value, + gst_play_bin_get_current_sink (playbin, &playbin->video_sink, + "video", GST_PLAY_SINK_TYPE_VIDEO)); + break; + case PROP_AUDIO_SINK: + g_value_take_object (value, + gst_play_bin_get_current_sink (playbin, &playbin->audio_sink, + "audio", GST_PLAY_SINK_TYPE_AUDIO)); + break; + case PROP_VIS_PLUGIN: + g_value_take_object (value, + gst_play_sink_get_vis_plugin (playbin->playsink)); + break; + case PROP_TEXT_SINK: + g_value_take_object (value, + gst_play_bin_get_current_sink (playbin, &playbin->text_sink, + "text", GST_PLAY_SINK_TYPE_TEXT)); + break; + case PROP_VOLUME: + g_value_set_double (value, gst_play_sink_get_volume (playbin->playsink)); + break; + case PROP_MUTE: + g_value_set_boolean (value, gst_play_sink_get_mute (playbin->playsink)); + break; + case PROP_FRAME: + gst_value_take_buffer (value, + gst_play_sink_get_last_frame (playbin->playsink)); + break; + case PROP_FONT_DESC: + g_value_take_string (value, + gst_play_sink_get_font_desc (playbin->playsink)); + break; + case PROP_CONNECTION_SPEED: + GST_PLAY_BIN_LOCK (playbin); + g_value_set_uint (value, playbin->connection_speed / 1000); + GST_PLAY_BIN_UNLOCK (playbin); + break; + case PROP_BUFFER_SIZE: + GST_OBJECT_LOCK (playbin); + g_value_set_int (value, playbin->buffer_size); + GST_OBJECT_UNLOCK (playbin); + break; + case PROP_BUFFER_DURATION: + GST_OBJECT_LOCK (playbin); + g_value_set_int64 (value, playbin->buffer_duration); + GST_OBJECT_UNLOCK (playbin); + break; + case PROP_AV_OFFSET: + g_value_set_int64 (value, + gst_play_sink_get_av_offset (playbin->playsink)); + break; + case PROP_RING_BUFFER_MAX_SIZE: + g_value_set_uint64 (value, playbin->ring_buffer_max_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_play_bin_update_cached_duration_from_query (GstPlayBin * playbin, + gboolean valid, GstQuery * query) +{ + GstFormat fmt; + gint64 duration; + gint i; + + GST_DEBUG_OBJECT (playbin, "Updating cached duration from query"); + gst_query_parse_duration (query, &fmt, &duration); + + for (i = 0; i < G_N_ELEMENTS (playbin->duration); i++) { + if (playbin->duration[i].format == 0 || fmt == playbin->duration[i].format) { + playbin->duration[i].valid = valid; + playbin->duration[i].format = fmt; + playbin->duration[i].duration = valid ? duration : -1; + break; + } + } +} + +static void +gst_play_bin_update_cached_duration (GstPlayBin * playbin) +{ + const GstFormat formats[] = + { GST_FORMAT_TIME, GST_FORMAT_BYTES, GST_FORMAT_DEFAULT }; + gboolean ret; + GstQuery *query; + gint i; + + GST_DEBUG_OBJECT (playbin, "Updating cached durations before group switch"); + for (i = 0; i < G_N_ELEMENTS (formats); i++) { + query = gst_query_new_duration (formats[i]); + ret = + GST_ELEMENT_CLASS (parent_class)->query (GST_ELEMENT_CAST (playbin), + query); + gst_play_bin_update_cached_duration_from_query (playbin, ret, query); + gst_query_unref (query); + } +} + +static gboolean +gst_play_bin_query (GstElement * element, GstQuery * query) +{ + GstPlayBin *playbin = GST_PLAY_BIN (element); + gboolean ret; + + /* During a group switch we shouldn't allow duration queries + * because it's not clear if the old or new group's duration + * is returned and if the sinks are already playing new data + * or old data. See bug #585969 + * + * While we're at it, also don't do any other queries during + * a group switch or any other event that causes topology changes + * by taking the playbin lock in any case. + */ + GST_PLAY_BIN_LOCK (playbin); + + if (GST_QUERY_TYPE (query) == GST_QUERY_DURATION) { + GstSourceGroup *group = playbin->curr_group; + gboolean pending; + + GST_SOURCE_GROUP_LOCK (group); + if (group->stream_changed_pending_lock) { + g_mutex_lock (group->stream_changed_pending_lock); + pending = group->pending || group->stream_changed_pending; + g_mutex_unlock (group->stream_changed_pending_lock); + } else { + pending = group->pending; + } + if (pending) { + GstFormat fmt; + gint i; + + ret = FALSE; + gst_query_parse_duration (query, &fmt, NULL); + for (i = 0; i < G_N_ELEMENTS (playbin->duration); i++) { + if (fmt == playbin->duration[i].format) { + ret = playbin->duration[i].valid; + gst_query_set_duration (query, fmt, + (ret ? playbin->duration[i].duration : -1)); + break; + } + } + /* if nothing cached yet, we might as well request duration, + * such as during initial startup */ + if (ret) { + GST_DEBUG_OBJECT (playbin, + "Taking cached duration because of pending group switch: %d", ret); + GST_SOURCE_GROUP_UNLOCK (group); + GST_PLAY_BIN_UNLOCK (playbin); + return ret; + } + } + GST_SOURCE_GROUP_UNLOCK (group); + } + + ret = GST_ELEMENT_CLASS (parent_class)->query (element, query); + + if (GST_QUERY_TYPE (query) == GST_QUERY_DURATION) + gst_play_bin_update_cached_duration_from_query (playbin, ret, query); + GST_PLAY_BIN_UNLOCK (playbin); + + return ret; +} + +/* mime types we are not handling on purpose right now, don't post a + * missing-plugin message for these */ +static const gchar *blacklisted_mimes[] = { + NULL +}; + +static void +gst_play_bin_handle_message (GstBin * bin, GstMessage * msg) +{ + GstPlayBin *playbin = GST_PLAY_BIN (bin); + GstSourceGroup *group; + + if (gst_is_missing_plugin_message (msg)) { + gchar *detail; + guint i; + + detail = gst_missing_plugin_message_get_installer_detail (msg); + for (i = 0; detail != NULL && blacklisted_mimes[i] != NULL; ++i) { + if (strstr (detail, "|decoder-") && strstr (detail, blacklisted_mimes[i])) { + GST_LOG_OBJECT (bin, "suppressing message %" GST_PTR_FORMAT, msg); + gst_message_unref (msg); + g_free (detail); + return; + } + } + g_free (detail); + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT) { + const GstStructure *s = gst_message_get_structure (msg); + + /* Drop all stream-changed messages except the last one */ + if (strcmp ("playbin2-stream-changed", gst_structure_get_name (s)) == 0) { + guint32 seqnum = gst_message_get_seqnum (msg); + GList *l, *l_prev; + + group = playbin->curr_group; + g_mutex_lock (group->stream_changed_pending_lock); + for (l = group->stream_changed_pending; l;) { + guint32 l_seqnum = GPOINTER_TO_UINT (l->data); + + if (l_seqnum == seqnum) { + l_prev = l; + l = l->next; + group->stream_changed_pending = + g_list_delete_link (group->stream_changed_pending, l_prev); + if (group->stream_changed_pending) { + gst_message_unref (msg); + msg = NULL; + break; + } + } else { + l = l->next; + } + } + g_mutex_unlock (group->stream_changed_pending_lock); + } + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_START || + GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ASYNC_DONE) { + GstObject *src = GST_OBJECT_CAST (msg->src); + + /* Ignore async state changes from the uridecodebin children, + * see bug #602000. */ + group = playbin->curr_group; + if (src && (group = playbin->curr_group) && + ((group->uridecodebin && src == GST_OBJECT_CAST (group->uridecodebin)) + || (group->suburidecodebin + && src == GST_OBJECT_CAST (group->suburidecodebin)))) { + GST_DEBUG_OBJECT (playbin, + "Ignoring async state change of uridecodebin: %s", + GST_OBJECT_NAME (src)); + gst_message_unref (msg); + msg = NULL; + } + } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { + /* If we get an error of the subtitle uridecodebin transform + * them into warnings and disable the subtitles */ + group = playbin->curr_group; + if (group && group->suburidecodebin) { + if (G_UNLIKELY (gst_object_has_ancestor (msg->src, GST_OBJECT_CAST + (group->suburidecodebin)))) { + GError *err; + gchar *debug = NULL; + GstMessage *new_msg; + GstIterator *it; + gboolean done = FALSE; + + gst_message_parse_error (msg, &err, &debug); + new_msg = gst_message_new_warning (msg->src, err, debug); + + gst_message_unref (msg); + g_error_free (err); + g_free (debug); + msg = new_msg; + + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id); + + it = gst_element_iterate_src_pads (group->suburidecodebin); + while (it && !done) { + GstPad *p = NULL; + GstIteratorResult res; + + res = gst_iterator_next (it, (gpointer) & p); + + switch (res) { + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_OK: + pad_removed_cb (NULL, p, group); + gst_object_unref (p); + break; + + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + } + } + if (it) + gst_iterator_free (it); + + gst_object_ref (group->suburidecodebin); + gst_bin_remove (bin, group->suburidecodebin); + gst_element_set_locked_state (group->suburidecodebin, FALSE); + + if (group->sub_pending) { + group->sub_pending = FALSE; + no_more_pads_cb (NULL, group); + } + } + } + } + + if (msg) + GST_BIN_CLASS (parent_class)->handle_message (bin, msg); +} + +static void +selector_active_pad_changed (GObject * selector, GParamSpec * pspec, + GstPlayBin * playbin) +{ + const gchar *property; + GstSourceGroup *group; + GstSourceSelect *select = NULL; + int i; + + GST_PLAY_BIN_LOCK (playbin); + group = get_group (playbin); + + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + if (selector == G_OBJECT (group->selector[i].selector)) { + select = &group->selector[i]; + } + } + + /* We got a pad-change after our group got switched out; no need to notify */ + if (!select) { + GST_PLAY_BIN_UNLOCK (playbin); + return; + } + + switch (select->type) { + case GST_PLAY_SINK_TYPE_VIDEO: + case GST_PLAY_SINK_TYPE_VIDEO_RAW: + property = "current-video"; + playbin->current_video = get_current_stream_number (playbin, + group->video_channels); + break; + case GST_PLAY_SINK_TYPE_AUDIO: + case GST_PLAY_SINK_TYPE_AUDIO_RAW: + property = "current-audio"; + playbin->current_audio = get_current_stream_number (playbin, + group->audio_channels); + break; + case GST_PLAY_SINK_TYPE_TEXT: + property = "current-text"; + playbin->current_text = get_current_stream_number (playbin, + group->text_channels); + break; + default: + property = NULL; + } + GST_PLAY_BIN_UNLOCK (playbin); + + if (property) + g_object_notify (G_OBJECT (playbin), property); +} + +static void +selector_blocked (GstPad * pad, gboolean blocked, gpointer user_data) +{ + /* no nothing */ + GST_DEBUG_OBJECT (pad, "blocked callback, blocked: %d", blocked); +} + +/* this callback sends a delayed event once the pad becomes unblocked */ +static gboolean +stream_changed_data_probe (GstPad * pad, GstMiniObject * object, gpointer data) +{ + GstSourceSelect *select = (GstSourceSelect *) data; + GstEvent *e; + + /* we need do this just once, so cleanup first */ + gst_pad_remove_data_probe (pad, select->sinkpad_data_probe); + select->sinkpad_data_probe = 0; + e = select->sinkpad_delayed_event; + select->sinkpad_delayed_event = NULL; + + /* really, this should not happen */ + if (!e) { + GST_WARNING ("Data probed called, but no delayed event"); + return TRUE; + } + + if (GST_IS_EVENT (object) + && GST_EVENT_TYPE (GST_EVENT_CAST (object)) == GST_EVENT_NEWSEGMENT) { + /* push the event first, then send the delayed one */ + gst_event_ref (GST_EVENT_CAST (object)); + gst_pad_send_event (pad, GST_EVENT_CAST (object)); + gst_pad_send_event (pad, e); + return FALSE; + } else { + /* send delayed event, then allow the caller to go on */ + gst_pad_send_event (pad, e); + return TRUE; + } +} + +/* helper function to lookup stuff in lists */ +static gboolean +array_has_value (const gchar * values[], const gchar * value) +{ + gint i; + + for (i = 0; values[i]; i++) { + if (g_str_has_prefix (value, values[i])) + return TRUE; + } + return FALSE; +} + +typedef struct +{ + GstPlayBin *playbin; + gint stream_id; + GstPlaySinkType type; +} NotifyTagsData; + +static void +notify_tags_cb (GObject * object, GParamSpec * pspec, gpointer user_data) +{ + NotifyTagsData *ntdata = (NotifyTagsData *) user_data; + gint signal; + + GST_DEBUG_OBJECT (ntdata->playbin, "Tags on pad %" GST_PTR_FORMAT + " with stream id %d and type %d have changed", + object, ntdata->stream_id, ntdata->type); + + switch (ntdata->type) { + case GST_PLAY_SINK_TYPE_VIDEO: + case GST_PLAY_SINK_TYPE_VIDEO_RAW: + signal = SIGNAL_VIDEO_TAGS_CHANGED; + break; + case GST_PLAY_SINK_TYPE_AUDIO: + case GST_PLAY_SINK_TYPE_AUDIO_RAW: + signal = SIGNAL_AUDIO_TAGS_CHANGED; + break; + case GST_PLAY_SINK_TYPE_TEXT: + signal = SIGNAL_TEXT_TAGS_CHANGED; + break; + default: + signal = -1; + break; + } + + if (signal >= 0) + g_signal_emit (G_OBJECT (ntdata->playbin), gst_play_bin_signals[signal], 0, + ntdata->stream_id); +} + +/* this function is called when a new pad is added to decodebin. We check the + * type of the pad and add it to the selector element of the group. + */ +static void +pad_added_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) +{ + GstPlayBin *playbin; + GstCaps *caps; + const GstStructure *s; + const gchar *name; + GstPad *sinkpad; + GstPadLinkReturn res; + GstSourceSelect *select = NULL; + gint i; + gboolean changed = FALSE; + + playbin = group->playbin; + + caps = gst_pad_get_caps_reffed (pad); + s = gst_caps_get_structure (caps, 0); + name = gst_structure_get_name (s); + + GST_DEBUG_OBJECT (playbin, + "pad %s:%s with caps %" GST_PTR_FORMAT " added in group %p", + GST_DEBUG_PAD_NAME (pad), caps, group); + + /* major type of the pad, this determines the selector to use */ + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + if (array_has_value (group->selector[i].media_list, name)) { + select = &group->selector[i]; + break; + } else if (group->selector[i].get_media_caps) { + GstCaps *media_caps = group->selector[i].get_media_caps (); + + if (media_caps && gst_caps_can_intersect (media_caps, caps)) { + select = &group->selector[i]; + gst_caps_unref (media_caps); + break; + } + gst_caps_unref (media_caps); + } + } + /* no selector found for the media type, don't bother linking it to a + * selector. This will leave the pad unlinked and thus ignored. */ + if (select == NULL) + goto unknown_type; + + GST_SOURCE_GROUP_LOCK (group); + if (select->selector == NULL && playbin->have_selector) { + /* no selector, create one */ + GST_DEBUG_OBJECT (playbin, "creating new input selector"); + select->selector = gst_element_factory_make ("input-selector", NULL); + if (select->selector == NULL) { + /* post the missing selector message only once */ + playbin->have_selector = FALSE; + gst_element_post_message (GST_ELEMENT_CAST (playbin), + gst_missing_element_message_new (GST_ELEMENT_CAST (playbin), + "input-selector")); + GST_ELEMENT_WARNING (playbin, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "input-selector"), (NULL)); + } else { + g_signal_connect (select->selector, "notify::active-pad", + G_CALLBACK (selector_active_pad_changed), playbin); + + GST_DEBUG_OBJECT (playbin, "adding new selector %p", select->selector); + gst_bin_add (GST_BIN_CAST (playbin), select->selector); + gst_element_set_state (select->selector, GST_STATE_PAUSED); + } + } + + if (select->srcpad == NULL) { + if (select->selector) { + /* save source pad of the selector */ + select->srcpad = gst_element_get_static_pad (select->selector, "src"); + } else { + /* no selector, use the pad as the source pad then */ + select->srcpad = gst_object_ref (pad); + } + + /* block the selector srcpad. It's possible that multiple decodebins start + * pushing data into the selectors before we have a chance to collect all + * streams and connect the sinks, resulting in not-linked errors. After we + * configured the sinks we will unblock them all. */ + GST_DEBUG_OBJECT (playbin, "blocking %" GST_PTR_FORMAT, select->srcpad); + gst_pad_set_blocked_async (select->srcpad, TRUE, selector_blocked, NULL); + } + + /* get sinkpad for the new stream */ + if (select->selector) { + if ((sinkpad = gst_element_get_request_pad (select->selector, "sink%d"))) { + gulong notify_tags_handler = 0; + NotifyTagsData *ntdata; + + GST_DEBUG_OBJECT (playbin, "got pad %s:%s from selector", + GST_DEBUG_PAD_NAME (sinkpad)); + + /* store the selector for the pad */ + g_object_set_data (G_OBJECT (sinkpad), "playbin2.select", select); + + /* connect to the notify::tags signal for our + * own *-tags-changed signals + */ + ntdata = g_new0 (NotifyTagsData, 1); + ntdata->playbin = playbin; + ntdata->stream_id = select->channels->len; + ntdata->type = select->type; + + notify_tags_handler = + g_signal_connect_data (G_OBJECT (sinkpad), "notify::tags", + G_CALLBACK (notify_tags_cb), ntdata, (GClosureNotify) g_free, + (GConnectFlags) 0); + g_object_set_data (G_OBJECT (sinkpad), "playbin2.notify_tags_handler", + (gpointer) notify_tags_handler); + + /* store the pad in the array */ + GST_DEBUG_OBJECT (playbin, "pad %p added to array", sinkpad); + g_ptr_array_add (select->channels, sinkpad); + + res = gst_pad_link (pad, sinkpad); + if (GST_PAD_LINK_FAILED (res)) + goto link_failed; + + /* store selector pad so we can release it */ + g_object_set_data (G_OBJECT (pad), "playbin2.sinkpad", sinkpad); + + changed = TRUE; + GST_DEBUG_OBJECT (playbin, "linked pad %s:%s to selector %p", + GST_DEBUG_PAD_NAME (pad), select->selector); + } + } else { + /* no selector, don't configure anything, we'll link the new pad directly to + * the sink. */ + changed = FALSE; + sinkpad = NULL; + } + GST_SOURCE_GROUP_UNLOCK (group); + + if (changed) { + int signal; + gboolean always_ok = (decodebin == group->suburidecodebin); + + switch (select->type) { + case GST_PLAY_SINK_TYPE_VIDEO: + case GST_PLAY_SINK_TYPE_VIDEO_RAW: + /* we want to return NOT_LINKED for unselected pads but only for pads + * from the normal uridecodebin. This makes sure that subtitle streams + * are not raced past audio/video from decodebin2's multiqueue. + * For pads from suburidecodebin OK should always be returned, otherwise + * it will most likely stop. */ + g_object_set (sinkpad, "always-ok", always_ok, NULL); + signal = SIGNAL_VIDEO_CHANGED; + break; + case GST_PLAY_SINK_TYPE_AUDIO: + case GST_PLAY_SINK_TYPE_AUDIO_RAW: + g_object_set (sinkpad, "always-ok", always_ok, NULL); + signal = SIGNAL_AUDIO_CHANGED; + break; + case GST_PLAY_SINK_TYPE_TEXT: + g_object_set (sinkpad, "always-ok", always_ok, NULL); + signal = SIGNAL_TEXT_CHANGED; + break; + default: + signal = -1; + } + + if (signal >= 0) + g_signal_emit (G_OBJECT (playbin), gst_play_bin_signals[signal], 0, NULL); + } + +done: + gst_caps_unref (caps); + return; + + /* ERRORS */ +unknown_type: + { + GST_ERROR_OBJECT (playbin, "unknown type %s for pad %s:%s", + name, GST_DEBUG_PAD_NAME (pad)); + goto done; + } +link_failed: + { + GST_ERROR_OBJECT (playbin, + "failed to link pad %s:%s to selector, reason %d", + GST_DEBUG_PAD_NAME (pad), res); + GST_SOURCE_GROUP_UNLOCK (group); + goto done; + } +} + +/* called when a pad is removed from the uridecodebin. We unlink the pad from + * the selector. This will make the selector select a new pad. */ +static void +pad_removed_cb (GstElement * decodebin, GstPad * pad, GstSourceGroup * group) +{ + GstPlayBin *playbin; + GstPad *peer; + GstElement *selector; + GstSourceSelect *select; + + playbin = group->playbin; + + GST_DEBUG_OBJECT (playbin, + "pad %s:%s removed from group %p", GST_DEBUG_PAD_NAME (pad), group); + + GST_SOURCE_GROUP_LOCK (group); + /* get the selector sinkpad */ + if (!(peer = g_object_get_data (G_OBJECT (pad), "playbin2.sinkpad"))) + goto not_linked; + + if ((select = g_object_get_data (G_OBJECT (peer), "playbin2.select"))) { + gulong notify_tags_handler; + + notify_tags_handler = + (gulong) g_object_get_data (G_OBJECT (peer), + "playbin2.notify_tags_handler"); + if (notify_tags_handler != 0) + g_signal_handler_disconnect (G_OBJECT (peer), notify_tags_handler); + g_object_set_data (G_OBJECT (peer), "playbin2.notify_tags_handler", NULL); + + /* remove the pad from the array */ + g_ptr_array_remove (select->channels, peer); + GST_DEBUG_OBJECT (playbin, "pad %p removed from array", peer); + } + + /* unlink the pad now (can fail, the pad is unlinked before it's removed) */ + gst_pad_unlink (pad, peer); + + /* get selector, this can be NULL when the element is removing the pads + * because it's being disposed. */ + selector = GST_ELEMENT_CAST (gst_pad_get_parent (peer)); + if (!selector) { + gst_object_unref (peer); + goto no_selector; + } + + /* release the pad to the selector, this will make the selector choose a new + * pad. */ + gst_element_release_request_pad (selector, peer); + gst_object_unref (peer); + + gst_object_unref (selector); + GST_SOURCE_GROUP_UNLOCK (group); + + return; + + /* ERRORS */ +not_linked: + { + GST_DEBUG_OBJECT (playbin, "pad not linked"); + GST_SOURCE_GROUP_UNLOCK (group); + return; + } +no_selector: + { + GST_DEBUG_OBJECT (playbin, "selector not found"); + GST_SOURCE_GROUP_UNLOCK (group); + return; + } +} + +/* we get called when all pads are available and we must connect the sinks to + * them. + * The main purpose of the code is to see if we have video/audio and subtitles + * and pick the right pipelines to display them. + * + * The selectors installed on the group tell us about the presence of + * audio/video and subtitle streams. This allows us to see if we need + * visualisation, video or/and audio. + */ +static void +no_more_pads_cb (GstElement * decodebin, GstSourceGroup * group) +{ + GstPlayBin *playbin; + GstPadLinkReturn res; + gint i; + gboolean configure; + + playbin = group->playbin; + + GST_DEBUG_OBJECT (playbin, "no more pads in group %p", group); + + GST_PLAY_BIN_SHUTDOWN_LOCK (playbin, shutdown); + + GST_SOURCE_GROUP_LOCK (group); + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + GstSourceSelect *select = &group->selector[i]; + + /* check if the specific media type was detected and thus has a selector + * created for it. If there is the media type, get a sinkpad from the sink + * and link it. We only do this if we have not yet requested the sinkpad + * before. */ + if (select->srcpad && select->sinkpad == NULL) { + GST_DEBUG_OBJECT (playbin, "requesting new sink pad %d", select->type); + select->sinkpad = + gst_play_sink_request_pad (playbin->playsink, select->type); + + res = gst_pad_link (select->srcpad, select->sinkpad); + GST_DEBUG_OBJECT (playbin, "linked type %s, result: %d", + select->media_list[0], res); + if (res != GST_PAD_LINK_OK) { + GST_ELEMENT_ERROR (playbin, CORE, PAD, + ("Internal playbin error."), + ("Failed to link selector to sink. Error %d", res)); + } + } + } + GST_DEBUG_OBJECT (playbin, "pending %d > %d", group->pending, + group->pending - 1); + + if (group->pending > 0) + group->pending--; + + if (group->suburidecodebin == decodebin) + group->sub_pending = FALSE; + + if (group->pending == 0) { + /* we are the last group to complete, we will configure the output and then + * signal the other waiters. */ + GST_LOG_OBJECT (playbin, "last group complete"); + configure = TRUE; + } else { + GST_LOG_OBJECT (playbin, "have more pending groups"); + configure = FALSE; + } + GST_SOURCE_GROUP_UNLOCK (group); + + if (configure) { + /* if we have custom sinks, configure them now */ + GST_SOURCE_GROUP_LOCK (group); + + GST_INFO_OBJECT (playbin, "setting custom audio sink %" GST_PTR_FORMAT, + group->audio_sink); + gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_AUDIO, + group->audio_sink); + + GST_INFO_OBJECT (playbin, "setting custom video sink %" GST_PTR_FORMAT, + group->video_sink); + gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_VIDEO, + group->video_sink); + + GST_INFO_OBJECT (playbin, "setting custom text sink %" GST_PTR_FORMAT, + playbin->text_sink); + gst_play_sink_set_sink (playbin->playsink, GST_PLAY_SINK_TYPE_TEXT, + playbin->text_sink); + + GST_SOURCE_GROUP_UNLOCK (group); + + GST_LOG_OBJECT (playbin, "reconfigure sink"); + /* we configure the modes if we were the last decodebin to complete. */ + gst_play_sink_reconfigure (playbin->playsink); + + /* signal the other decodebins that they can continue now. */ + GST_SOURCE_GROUP_LOCK (group); + /* unblock all selectors */ + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + GstSourceSelect *select = &group->selector[i]; + + /* All streamsynchronizer streams should see stream-changed message, + * to arrange for blocking unblocking. */ + if (select->sinkpad) { + GstStructure *s; + GstMessage *msg; + GstEvent *event; + guint32 seqnum; + + s = gst_structure_new ("playbin2-stream-changed", "uri", G_TYPE_STRING, + group->uri, NULL); + if (group->suburi) + gst_structure_set (s, "suburi", G_TYPE_STRING, group->suburi, NULL); + msg = gst_message_new_element (GST_OBJECT_CAST (playbin), s); + seqnum = gst_message_get_seqnum (msg); + event = gst_event_new_sink_message (msg); + g_mutex_lock (group->stream_changed_pending_lock); + group->stream_changed_pending = + g_list_prepend (group->stream_changed_pending, + GUINT_TO_POINTER (seqnum)); + + /* remove any data probe we might have, and replace */ + if (select->sinkpad_delayed_event) + gst_event_unref (select->sinkpad_delayed_event); + select->sinkpad_delayed_event = event; + if (select->sinkpad_data_probe) + gst_pad_remove_data_probe (select->sinkpad, + select->sinkpad_data_probe); + + /* we go to the trouble of setting a probe on the pad to send + the playbin2-stream-changed event as sending it here might + find that the pad is blocked, so we'd block here, and the + pad might not be linked yet. Additionally, sending it here + apparently would be on the wrong thread */ + select->sinkpad_data_probe = + gst_pad_add_data_probe (select->sinkpad, + (GCallback) stream_changed_data_probe, (gpointer) select); + + g_mutex_unlock (group->stream_changed_pending_lock); + gst_message_unref (msg); + } + + if (select->srcpad) { + GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT, + select->srcpad); + gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked, + NULL); + } + } + GST_SOURCE_GROUP_UNLOCK (group); + } + + GST_PLAY_BIN_SHUTDOWN_UNLOCK (playbin); + + return; + +shutdown: + { + GST_DEBUG ("ignoring, we are shutting down"); + /* Request a flushing pad from playsink that we then link to the selector. + * Then we unblock the selectors so that they stop with a WRONG_STATE + * instead of a NOT_LINKED error. + */ + GST_SOURCE_GROUP_LOCK (group); + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + GstSourceSelect *select = &group->selector[i]; + + if (select->srcpad) { + if (select->sinkpad == NULL) { + GST_DEBUG_OBJECT (playbin, "requesting new flushing sink pad"); + select->sinkpad = + gst_play_sink_request_pad (playbin->playsink, + GST_PLAY_SINK_TYPE_FLUSHING); + res = gst_pad_link (select->srcpad, select->sinkpad); + GST_DEBUG_OBJECT (playbin, "linked flushing, result: %d", res); + } + GST_DEBUG_OBJECT (playbin, "unblocking %" GST_PTR_FORMAT, + select->srcpad); + gst_pad_set_blocked_async (select->srcpad, FALSE, selector_blocked, + NULL); + } + } + GST_SOURCE_GROUP_UNLOCK (group); + return; + } +} + +static void +drained_cb (GstElement * decodebin, GstSourceGroup * group) +{ + GstPlayBin *playbin; + + playbin = group->playbin; + + GST_DEBUG_OBJECT (playbin, "about to finish in group %p", group); + + /* after this call, we should have a next group to activate or we EOS */ + g_signal_emit (G_OBJECT (playbin), + gst_play_bin_signals[SIGNAL_ABOUT_TO_FINISH], 0, NULL); + + /* now activate the next group. If the app did not set a uri, this will + * fail and we can do EOS */ + setup_next_source (playbin, GST_STATE_PAUSED); +} + +/* Called when we must provide a list of factories to plug to @pad with @caps. + * We first check if we have a sink that can handle the format and if we do, we + * return NULL, to expose the pad. If we have no sink (or the sink does not + * work), we return the list of elements that can connect. */ +static GValueArray * +autoplug_factories_cb (GstElement * decodebin, GstPad * pad, + GstCaps * caps, GstSourceGroup * group) +{ + GstPlayBin *playbin; + GList *mylist, *tmp; + GValueArray *result; + + playbin = group->playbin; + + GST_DEBUG_OBJECT (playbin, "factories group %p for %s:%s, %" GST_PTR_FORMAT, + group, GST_DEBUG_PAD_NAME (pad), caps); + + /* filter out the elements based on the caps. */ + g_mutex_lock (playbin->elements_lock); + gst_play_bin_update_elements_list (playbin); + mylist = + gst_element_factory_list_filter (playbin->elements, caps, GST_PAD_SINK, + FALSE); + g_mutex_unlock (playbin->elements_lock); + + GST_DEBUG_OBJECT (playbin, "found factories %p", mylist); + GST_PLUGIN_FEATURE_LIST_DEBUG (mylist); + + result = g_value_array_new (g_list_length (mylist)); + + for (tmp = mylist; tmp; tmp = tmp->next) { + GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data); + GValue val = { 0, }; + + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_append (result, &val); + g_value_unset (&val); + } + gst_plugin_feature_list_free (mylist); + + return result; +} + +/* autoplug-continue decides, if a pad has raw caps that can be exposed + * directly or if further decoding is necessary. We use this to expose + * supported subtitles directly */ + +/* FIXME 0.11: Remove the checks for ANY caps, a sink should specify + * explicitely the caps it supports and if it claims to support ANY + * caps it really should support everything */ +static gboolean +autoplug_continue_cb (GstElement * element, GstPad * pad, GstCaps * caps, + GstSourceGroup * group) +{ + gboolean ret = TRUE; + GstElement *sink; + GstPad *sinkpad = NULL; + + GST_PLAY_BIN_LOCK (group->playbin); + GST_SOURCE_GROUP_LOCK (group); + + if ((sink = group->playbin->text_sink)) + sinkpad = gst_element_get_static_pad (sink, "sink"); + if (sinkpad) { + GstCaps *sinkcaps; + + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + + sinkcaps = gst_pad_get_caps_reffed (sinkpad); + if (!gst_caps_is_any (sinkcaps)) + ret = !gst_pad_accept_caps (sinkpad, caps); + gst_caps_unref (sinkcaps); + gst_object_unref (sinkpad); + } else { + GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps (); + ret = !gst_caps_can_intersect (caps, subcaps); + gst_caps_unref (subcaps); + } + /* If autoplugging can stop don't do additional checks */ + if (!ret) + goto done; + + /* If this is from the subtitle uridecodebin we don't need to + * check the audio and video sink */ + if (group->suburidecodebin + && gst_object_has_ancestor (GST_OBJECT_CAST (element), + GST_OBJECT_CAST (group->suburidecodebin))) + goto done; + + if ((sink = group->audio_sink)) { + sinkpad = gst_element_get_static_pad (sink, "sink"); + if (sinkpad) { + GstCaps *sinkcaps; + + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + + sinkcaps = gst_pad_get_caps_reffed (sinkpad); + if (!gst_caps_is_any (sinkcaps)) + ret = !gst_pad_accept_caps (sinkpad, caps); + gst_caps_unref (sinkcaps); + gst_object_unref (sinkpad); + } + } + if (!ret) + goto done; + + if ((sink = group->video_sink)) { + sinkpad = gst_element_get_static_pad (sink, "sink"); + if (sinkpad) { + GstCaps *sinkcaps; + + /* Ignore errors here, if a custom sink fails to go + * to READY things are wrong and will error out later + */ + if (GST_STATE (sink) < GST_STATE_READY) + gst_element_set_state (sink, GST_STATE_READY); + + sinkcaps = gst_pad_get_caps_reffed (sinkpad); + if (!gst_caps_is_any (sinkcaps)) + ret = !gst_pad_accept_caps (sinkpad, caps); + gst_caps_unref (sinkcaps); + gst_object_unref (sinkpad); + } + } + +done: + GST_SOURCE_GROUP_UNLOCK (group); + GST_PLAY_BIN_UNLOCK (group->playbin); + + GST_DEBUG_OBJECT (group->playbin, + "continue autoplugging group %p for %s:%s, %" GST_PTR_FORMAT ": %d", + group, GST_DEBUG_PAD_NAME (pad), caps, ret); + + return ret; +} + +static gboolean +sink_accepts_caps (GstElement * sink, GstCaps * caps) +{ + GstPad *sinkpad; + + /* ... activate it ... We do this before adding it to the bin so that we + * don't accidentally make it post error messages that will stop + * everything. */ + if (GST_STATE (sink) < GST_STATE_READY && + gst_element_set_state (sink, + GST_STATE_READY) == GST_STATE_CHANGE_FAILURE) { + return FALSE; + } + + if ((sinkpad = gst_element_get_static_pad (sink, "sink"))) { + /* Got the sink pad, now let's see if the element actually does accept the + * caps that we have */ + if (!gst_pad_accept_caps (sinkpad, caps)) { + gst_object_unref (sinkpad); + return FALSE; + } + gst_object_unref (sinkpad); + } + + return TRUE; +} + +/* We are asked to select an element. See if the next element to check + * is a sink. If this is the case, we see if the sink works by setting it to + * READY. If the sink works, we return SELECT_EXPOSE to make decodebin + * expose the raw pad so that we can setup the mixers. */ +static GstAutoplugSelectResult +autoplug_select_cb (GstElement * decodebin, GstPad * pad, + GstCaps * caps, GstElementFactory * factory, GstSourceGroup * group) +{ + GstPlayBin *playbin; + GstElement *element; + const gchar *klass; + GstPlaySinkType type; + GstElement **sinkp; + + playbin = group->playbin; + + GST_DEBUG_OBJECT (playbin, "select group %p for %s:%s, %" GST_PTR_FORMAT, + group, GST_DEBUG_PAD_NAME (pad), caps); + + GST_DEBUG_OBJECT (playbin, "checking factory %s", + GST_PLUGIN_FEATURE_NAME (factory)); + + /* if it's not a sink, we just make decodebin try it */ + if (!gst_element_factory_list_is_type (factory, + GST_ELEMENT_FACTORY_TYPE_SINK)) + return GST_AUTOPLUG_SELECT_TRY; + + /* it's a sink, see if an instance of it actually works */ + GST_DEBUG_OBJECT (playbin, "we found a sink"); + + klass = gst_element_factory_get_klass (factory); + + /* figure out the klass */ + if (strstr (klass, "Audio")) { + GST_DEBUG_OBJECT (playbin, "we found an audio sink"); + type = GST_PLAY_SINK_TYPE_AUDIO; + sinkp = &group->audio_sink; + } else if (strstr (klass, "Video")) { + GST_DEBUG_OBJECT (playbin, "we found a video sink"); + type = GST_PLAY_SINK_TYPE_VIDEO; + sinkp = &group->video_sink; + } else { + /* unknown klass, skip this element */ + GST_WARNING_OBJECT (playbin, "unknown sink klass %s found", klass); + return GST_AUTOPLUG_SELECT_SKIP; + } + + /* if we are asked to do visualisations and it's an audio sink, skip the + * element. We can only do visualisations with raw sinks */ + if (gst_play_sink_get_flags (playbin->playsink) & GST_PLAY_FLAG_VIS) { + if (type == GST_PLAY_SINK_TYPE_AUDIO) { + GST_DEBUG_OBJECT (playbin, "skip audio sink because of vis"); + return GST_AUTOPLUG_SELECT_SKIP; + } + } + + /* now see if we already have a sink element */ + GST_SOURCE_GROUP_LOCK (group); + if (*sinkp) { + GstElement *sink = gst_object_ref (*sinkp); + + if (sink_accepts_caps (sink, caps)) { + GST_DEBUG_OBJECT (playbin, + "Existing sink '%s' accepts caps: %" GST_PTR_FORMAT, + GST_ELEMENT_NAME (sink), caps); + gst_object_unref (sink); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_EXPOSE; + } else { + GST_DEBUG_OBJECT (playbin, + "Existing sink '%s' does not accept caps: %" GST_PTR_FORMAT, + GST_ELEMENT_NAME (sink), caps); + gst_object_unref (sink); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_SKIP; + } + } + GST_DEBUG_OBJECT (playbin, "we have no pending sink, try to create one"); + + if ((element = gst_element_factory_create (factory, NULL)) == NULL) { + GST_WARNING_OBJECT (playbin, "Could not create an element from %s", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_SKIP; + } + + /* Check if the selected sink actually supports the + * caps and can be set to READY*/ + if (!sink_accepts_caps (element, caps)) { + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + GST_SOURCE_GROUP_UNLOCK (group); + return GST_AUTOPLUG_SELECT_SKIP; + } + + /* remember the sink in the group now, the element is floating, we take + * ownership now + * + * store the sink in the group, we will configure it later when we + * reconfigure the sink */ + GST_DEBUG_OBJECT (playbin, "remember sink"); + gst_object_ref_sink (element); + *sinkp = element; + GST_SOURCE_GROUP_UNLOCK (group); + + /* tell decodebin to expose the pad because we are going to use this + * sink */ + GST_DEBUG_OBJECT (playbin, "we found a working sink, expose pad"); + + return GST_AUTOPLUG_SELECT_EXPOSE; +} + +static void +notify_source_cb (GstElement * uridecodebin, GParamSpec * pspec, + GstSourceGroup * group) +{ + GstPlayBin *playbin; + GstElement *source; + + playbin = group->playbin; + + g_object_get (group->uridecodebin, "source", &source, NULL); + + GST_OBJECT_LOCK (playbin); + if (playbin->source) + gst_object_unref (playbin->source); + playbin->source = source; + GST_OBJECT_UNLOCK (playbin); + + g_object_notify (G_OBJECT (playbin), "source"); + + g_signal_emit (playbin, gst_play_bin_signals[SIGNAL_SOURCE_SETUP], + 0, playbin->source); +} + +/* must be called with the group lock */ +static gboolean +group_set_locked_state_unlocked (GstPlayBin * playbin, GstSourceGroup * group, + gboolean locked) +{ + GST_DEBUG_OBJECT (playbin, "locked_state %d on group %p", locked, group); + + if (group->uridecodebin) + gst_element_set_locked_state (group->uridecodebin, locked); + if (group->suburidecodebin) + gst_element_set_locked_state (group->suburidecodebin, locked); + + return TRUE; +} + +/* must be called with PLAY_BIN_LOCK */ +static gboolean +activate_group (GstPlayBin * playbin, GstSourceGroup * group, GstState target) +{ + GstElement *uridecodebin; + GstElement *suburidecodebin = NULL; + GstPlayFlags flags; + + g_return_val_if_fail (group->valid, FALSE); + g_return_val_if_fail (!group->active, FALSE); + + GST_DEBUG_OBJECT (playbin, "activating group %p", group); + + GST_SOURCE_GROUP_LOCK (group); + + /* First set up the custom sources */ + if (playbin->audio_sink) + group->audio_sink = gst_object_ref (playbin->audio_sink); + if (playbin->video_sink) + group->video_sink = gst_object_ref (playbin->video_sink); + + g_list_free (group->stream_changed_pending); + group->stream_changed_pending = NULL; + if (!group->stream_changed_pending_lock) + group->stream_changed_pending_lock = g_mutex_new (); + + if (group->uridecodebin) { + GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin"); + uridecodebin = group->uridecodebin; + gst_element_set_state (uridecodebin, GST_STATE_READY); + gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (uridecodebin)); + } else { + GST_DEBUG_OBJECT (playbin, "making new uridecodebin"); + uridecodebin = gst_element_factory_make ("uridecodebin", NULL); + if (!uridecodebin) + goto no_decodebin; + gst_bin_add (GST_BIN_CAST (playbin), uridecodebin); + group->uridecodebin = gst_object_ref (uridecodebin); + } + + flags = gst_play_sink_get_flags (playbin->playsink); + + g_object_set (uridecodebin, + /* configure connection speed */ + "connection-speed", playbin->connection_speed / 1000, + /* configure uri */ + "uri", group->uri, + /* configure download buffering */ + "download", ((flags & GST_PLAY_FLAG_DOWNLOAD) != 0), + /* configure buffering of demuxed/parsed data */ + "use-buffering", ((flags & GST_PLAY_FLAG_BUFFERING) != 0), + /* configure buffering parameters */ + "buffer-duration", playbin->buffer_duration, + "buffer-size", playbin->buffer_size, + "ring-buffer-max-size", playbin->ring_buffer_max_size, NULL); + + /* connect pads and other things */ + group->pad_added_id = g_signal_connect (uridecodebin, "pad-added", + G_CALLBACK (pad_added_cb), group); + group->pad_removed_id = g_signal_connect (uridecodebin, "pad-removed", + G_CALLBACK (pad_removed_cb), group); + group->no_more_pads_id = g_signal_connect (uridecodebin, "no-more-pads", + G_CALLBACK (no_more_pads_cb), group); + group->notify_source_id = g_signal_connect (uridecodebin, "notify::source", + G_CALLBACK (notify_source_cb), group); + + /* we have 1 pending no-more-pads */ + group->pending = 1; + + /* is called when the uridecodebin is out of data and we can switch to the + * next uri */ + group->drained_id = + g_signal_connect (uridecodebin, "drained", G_CALLBACK (drained_cb), + group); + + /* will be called when a new media type is found. We return a list of decoders + * including sinks for decodebin to try */ + group->autoplug_factories_id = + g_signal_connect (uridecodebin, "autoplug-factories", + G_CALLBACK (autoplug_factories_cb), group); + group->autoplug_select_id = + g_signal_connect (uridecodebin, "autoplug-select", + G_CALLBACK (autoplug_select_cb), group); + group->autoplug_continue_id = + g_signal_connect (uridecodebin, "autoplug-continue", + G_CALLBACK (autoplug_continue_cb), group); + + if (group->suburi) { + /* subtitles */ + if (group->suburidecodebin) { + GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin"); + suburidecodebin = group->suburidecodebin; + gst_element_set_state (suburidecodebin, GST_STATE_READY); + gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (suburidecodebin)); + } else { + GST_DEBUG_OBJECT (playbin, "making new suburidecodebin"); + suburidecodebin = gst_element_factory_make ("uridecodebin", NULL); + if (!suburidecodebin) + goto no_decodebin; + + gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin); + group->suburidecodebin = gst_object_ref (suburidecodebin); + } + + g_object_set (suburidecodebin, + /* configure connection speed */ + "connection-speed", playbin->connection_speed, + /* configure uri */ + "uri", group->suburi, NULL); + + /* connect pads and other things */ + group->sub_pad_added_id = g_signal_connect (suburidecodebin, "pad-added", + G_CALLBACK (pad_added_cb), group); + group->sub_pad_removed_id = g_signal_connect (suburidecodebin, + "pad-removed", G_CALLBACK (pad_removed_cb), group); + group->sub_no_more_pads_id = g_signal_connect (suburidecodebin, + "no-more-pads", G_CALLBACK (no_more_pads_cb), group); + + group->sub_autoplug_continue_id = + g_signal_connect (suburidecodebin, "autoplug-continue", + G_CALLBACK (autoplug_continue_cb), group); + + /* we have 2 pending no-more-pads */ + group->pending = 2; + group->sub_pending = TRUE; + } else { + group->sub_pending = FALSE; + } + + /* release the group lock before setting the state of the decodebins, they + * might fire signals in this thread that we need to handle with the + * group_lock taken. */ + GST_SOURCE_GROUP_UNLOCK (group); + + if (suburidecodebin) { + if (gst_element_set_state (suburidecodebin, + target) == GST_STATE_CHANGE_FAILURE) { + GST_DEBUG_OBJECT (playbin, + "failed state change of subtitle uridecodebin"); + GST_SOURCE_GROUP_LOCK (group); + + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id); + /* Might already be removed because of an error message */ + if (GST_OBJECT_PARENT (suburidecodebin) == GST_OBJECT_CAST (playbin)) + gst_bin_remove (GST_BIN_CAST (playbin), suburidecodebin); + if (group->sub_pending) { + group->pending--; + group->sub_pending = FALSE; + } + gst_element_set_state (suburidecodebin, GST_STATE_READY); + GST_SOURCE_GROUP_UNLOCK (group); + } + } + if (gst_element_set_state (uridecodebin, target) == GST_STATE_CHANGE_FAILURE) + goto uridecodebin_failure; + + GST_SOURCE_GROUP_LOCK (group); + /* alow state changes of the playbin2 affect the group elements now */ + group_set_locked_state_unlocked (playbin, group, FALSE); + group->active = TRUE; + GST_SOURCE_GROUP_UNLOCK (group); + + return TRUE; + + /* ERRORS */ +no_decodebin: + { + GstMessage *msg; + + /* delete any custom sinks we might have */ + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + + GST_SOURCE_GROUP_UNLOCK (group); + msg = + gst_missing_element_message_new (GST_ELEMENT_CAST (playbin), + "uridecodebin"); + gst_element_post_message (GST_ELEMENT_CAST (playbin), msg); + + GST_ELEMENT_ERROR (playbin, CORE, MISSING_PLUGIN, + (_("Could not create \"uridecodebin\" element.")), (NULL)); + return FALSE; + } +uridecodebin_failure: + { + /* delete any custom sinks we might have */ + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + + GST_DEBUG_OBJECT (playbin, "failed state change of uridecodebin"); + return FALSE; + } +} + +/* unlink a group of uridecodebins from the sink. + * must be called with PLAY_BIN_LOCK */ +static gboolean +deactivate_group (GstPlayBin * playbin, GstSourceGroup * group) +{ + gint i; + + g_return_val_if_fail (group->valid, FALSE); + g_return_val_if_fail (group->active, FALSE); + + GST_DEBUG_OBJECT (playbin, "unlinking group %p", group); + + GST_SOURCE_GROUP_LOCK (group); + group->active = FALSE; + for (i = 0; i < GST_PLAY_SINK_TYPE_LAST; i++) { + GstSourceSelect *select = &group->selector[i]; + + GST_DEBUG_OBJECT (playbin, "unlinking selector %s", select->media_list[0]); + + if (select->srcpad) { + if (select->sinkpad) { + GST_LOG_OBJECT (playbin, "unlinking from sink"); + gst_pad_unlink (select->srcpad, select->sinkpad); + + /* release back */ + GST_LOG_OBJECT (playbin, "release sink pad"); + gst_play_sink_release_pad (playbin->playsink, select->sinkpad); + select->sinkpad = NULL; + } + + gst_object_unref (select->srcpad); + select->srcpad = NULL; + } + + if (select->selector) { + gint n; + + /* release and unref requests pad from the selector */ + for (n = 0; n < select->channels->len; n++) { + GstPad *sinkpad = g_ptr_array_index (select->channels, n); + + gst_element_release_request_pad (select->selector, sinkpad); + gst_object_unref (sinkpad); + } + g_ptr_array_set_size (select->channels, 0); + + gst_element_set_state (select->selector, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (playbin), select->selector); + select->selector = NULL; + } + } + /* delete any custom sinks we might have */ + if (group->audio_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->audio_sink != playbin->audio_sink) + gst_element_set_state (group->audio_sink, GST_STATE_NULL); + gst_object_unref (group->audio_sink); + } + group->audio_sink = NULL; + if (group->video_sink) { + /* If this is a automatically created sink set it to NULL */ + if (group->video_sink != playbin->video_sink) + gst_element_set_state (group->video_sink, GST_STATE_NULL); + gst_object_unref (group->video_sink); + } + group->video_sink = NULL; + + if (group->uridecodebin) { + REMOVE_SIGNAL (group->uridecodebin, group->pad_added_id); + REMOVE_SIGNAL (group->uridecodebin, group->pad_removed_id); + REMOVE_SIGNAL (group->uridecodebin, group->no_more_pads_id); + REMOVE_SIGNAL (group->uridecodebin, group->notify_source_id); + REMOVE_SIGNAL (group->uridecodebin, group->drained_id); + REMOVE_SIGNAL (group->uridecodebin, group->autoplug_factories_id); + REMOVE_SIGNAL (group->uridecodebin, group->autoplug_select_id); + REMOVE_SIGNAL (group->uridecodebin, group->autoplug_continue_id); + gst_bin_remove (GST_BIN_CAST (playbin), group->uridecodebin); + } + + if (group->suburidecodebin) { + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_added_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_pad_removed_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_no_more_pads_id); + REMOVE_SIGNAL (group->suburidecodebin, group->sub_autoplug_continue_id); + + /* Might already be removed because of errors */ + if (GST_OBJECT_PARENT (group->suburidecodebin) == GST_OBJECT_CAST (playbin)) + gst_bin_remove (GST_BIN_CAST (playbin), group->suburidecodebin); + } + + GST_SOURCE_GROUP_UNLOCK (group); + + return TRUE; +} + +/* setup the next group to play, this assumes the next_group is valid and + * configured. It swaps out the current_group and activates the valid + * next_group. */ +static gboolean +setup_next_source (GstPlayBin * playbin, GstState target) +{ + GstSourceGroup *new_group, *old_group; + + GST_DEBUG_OBJECT (playbin, "setup sources"); + + /* see if there is a next group */ + GST_PLAY_BIN_LOCK (playbin); + new_group = playbin->next_group; + if (!new_group || !new_group->valid) + goto no_next_group; + + /* first unlink the current source, if any */ + old_group = playbin->curr_group; + if (old_group && old_group->valid && old_group->active) { + gst_play_bin_update_cached_duration (playbin); + /* unlink our pads with the sink */ + deactivate_group (playbin, old_group); + old_group->valid = FALSE; + } + + /* swap old and new */ + playbin->curr_group = new_group; + playbin->next_group = old_group; + + /* activate the new group */ + if (!activate_group (playbin, new_group, target)) + goto activate_failed; + + GST_PLAY_BIN_UNLOCK (playbin); + + return TRUE; + + /* ERRORS */ +no_next_group: + { + GST_DEBUG_OBJECT (playbin, "no next group"); + if (target == GST_STATE_READY && new_group && new_group->uri == NULL) + GST_ELEMENT_ERROR (playbin, RESOURCE, NOT_FOUND, ("No URI set"), (NULL)); + GST_PLAY_BIN_UNLOCK (playbin); + return FALSE; + } +activate_failed: + { + GST_DEBUG_OBJECT (playbin, "activate failed"); + GST_PLAY_BIN_UNLOCK (playbin); + return FALSE; + } +} + +/* The group that is currently playing is copied again to the + * next_group so that it will start playing the next time. + */ +static gboolean +save_current_group (GstPlayBin * playbin) +{ + GstSourceGroup *curr_group; + + GST_DEBUG_OBJECT (playbin, "save current group"); + + /* see if there is a current group */ + GST_PLAY_BIN_LOCK (playbin); + curr_group = playbin->curr_group; + if (curr_group && curr_group->valid) { + /* unlink our pads with the sink */ + deactivate_group (playbin, curr_group); + } + /* swap old and new */ + playbin->curr_group = playbin->next_group; + playbin->next_group = curr_group; + GST_PLAY_BIN_UNLOCK (playbin); + + return TRUE; +} + +/* clear the locked state from all groups. This function is called before a + * state change to NULL is performed on them. */ +static gboolean +groups_set_locked_state (GstPlayBin * playbin, gboolean locked) +{ + GST_DEBUG_OBJECT (playbin, "setting locked state to %d on all groups", + locked); + + GST_PLAY_BIN_LOCK (playbin); + GST_SOURCE_GROUP_LOCK (playbin->curr_group); + group_set_locked_state_unlocked (playbin, playbin->curr_group, locked); + GST_SOURCE_GROUP_UNLOCK (playbin->curr_group); + GST_SOURCE_GROUP_LOCK (playbin->next_group); + group_set_locked_state_unlocked (playbin, playbin->next_group, locked); + GST_SOURCE_GROUP_UNLOCK (playbin->next_group); + GST_PLAY_BIN_UNLOCK (playbin); + + return TRUE; +} + +static GstStateChangeReturn +gst_play_bin_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstPlayBin *playbin; + gboolean do_save = FALSE; + + playbin = GST_PLAY_BIN (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + memset (&playbin->duration, 0, sizeof (playbin->duration)); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_LOG_OBJECT (playbin, "clearing shutdown flag"); + memset (&playbin->duration, 0, sizeof (playbin->duration)); + g_atomic_int_set (&playbin->shutdown, 0); + + if (!setup_next_source (playbin, GST_STATE_READY)) { + ret = GST_STATE_CHANGE_FAILURE; + goto failure; + } + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + async_down: + /* FIXME unlock our waiting groups */ + GST_LOG_OBJECT (playbin, "setting shutdown flag"); + g_atomic_int_set (&playbin->shutdown, 1); + memset (&playbin->duration, 0, sizeof (playbin->duration)); + + /* wait for all callbacks to end by taking the lock. + * No dynamic (critical) new callbacks will + * be able to happen as we set the shutdown flag. */ + GST_PLAY_BIN_DYN_LOCK (playbin); + GST_LOG_OBJECT (playbin, "dynamic lock taken, we can continue shutdown"); + GST_PLAY_BIN_DYN_UNLOCK (playbin); + if (!do_save) + break; + case GST_STATE_CHANGE_READY_TO_NULL: + /* we go async to PAUSED, so if that fails, we never make it to PAUSED + * an no state change PAUSED to READY passes here, + * though it is a nice-to-have ... */ + if (!g_atomic_int_get (&playbin->shutdown)) { + do_save = TRUE; + goto async_down; + } + memset (&playbin->duration, 0, sizeof (playbin->duration)); + + /* unlock so that all groups go to NULL */ + groups_set_locked_state (playbin, FALSE); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + goto failure; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* FIXME Release audio device when we implement that */ + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + save_current_group (playbin); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + { + guint i; + + /* also do missed state change down to READY */ + if (do_save) + save_current_group (playbin); + /* Deactive the groups, set the uridecodebins to NULL + * and unref them. + */ + for (i = 0; i < 2; i++) { + if (playbin->groups[i].active && playbin->groups[i].valid) { + deactivate_group (playbin, &playbin->groups[i]); + playbin->groups[i].valid = FALSE; + } + + if (playbin->groups[i].uridecodebin) { + gst_element_set_state (playbin->groups[i].uridecodebin, + GST_STATE_NULL); + gst_object_unref (playbin->groups[i].uridecodebin); + playbin->groups[i].uridecodebin = NULL; + } + + if (playbin->groups[i].suburidecodebin) { + gst_element_set_state (playbin->groups[i].suburidecodebin, + GST_STATE_NULL); + gst_object_unref (playbin->groups[i].suburidecodebin); + playbin->groups[i].suburidecodebin = NULL; + } + } + + /* Set our sinks back to NULL, they might not be child of playbin */ + if (playbin->audio_sink) + gst_element_set_state (playbin->audio_sink, GST_STATE_NULL); + if (playbin->video_sink) + gst_element_set_state (playbin->video_sink, GST_STATE_NULL); + if (playbin->text_sink) + gst_element_set_state (playbin->text_sink, GST_STATE_NULL); + + /* make sure the groups don't perform a state change anymore until we + * enable them again */ + groups_set_locked_state (playbin, TRUE); + break; + } + default: + break; + } + + return ret; + + /* ERRORS */ +failure: + { + if (transition == GST_STATE_CHANGE_READY_TO_PAUSED) { + GstSourceGroup *curr_group; + + curr_group = playbin->curr_group; + if (curr_group && curr_group->active && curr_group->valid) { + /* unlink our pads with the sink */ + deactivate_group (playbin, curr_group); + curr_group->valid = FALSE; + } + + /* Swap current and next group back */ + playbin->curr_group = playbin->next_group; + playbin->next_group = curr_group; + } + return ret; + } +} + +gboolean +gst_play_bin2_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_play_bin_debug, "playbin2", 0, "play bin"); + + return gst_element_register (plugin, "playbin2", GST_RANK_NONE, + GST_TYPE_PLAY_BIN); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.c b/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.c new file mode 100644 index 0000000..326baa6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.c @@ -0,0 +1,3431 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include + +#include "gstplaysink.h" +#include "gststreamsynchronizer.h" + +GST_DEBUG_CATEGORY_STATIC (gst_play_sink_debug); +#define GST_CAT_DEFAULT gst_play_sink_debug + +#define VOLUME_MAX_DOUBLE 10.0 + +#define DEFAULT_FLAGS GST_PLAY_FLAG_AUDIO | GST_PLAY_FLAG_VIDEO | GST_PLAY_FLAG_TEXT | \ + GST_PLAY_FLAG_SOFT_VOLUME + +#define GST_PLAY_CHAIN(c) ((GstPlayChain *)(c)) + +/* holds the common data fields for the audio and video pipelines. We keep them + * in a structure to more easily have all the info available. */ +typedef struct +{ + GstPlaySink *playsink; + GstElement *bin; + gboolean added; + gboolean activated; + gboolean raw; +} GstPlayChain; + +typedef struct +{ + GstPlayChain chain; + GstPad *sinkpad; + GstElement *queue; + GstElement *conv; + GstElement *resample; + GstElement *volume; /* element with the volume property */ + gboolean sink_volume; /* if the volume was provided by the sink */ + GstElement *mute; /* element with the mute property */ + GstElement *sink; + GstElement *ts_offset; +} GstPlayAudioChain; + +typedef struct +{ + GstPlayChain chain; + GstPad *sinkpad, *srcpad; + GstElement *conv; + GstElement *deinterlace; +} GstPlayVideoDeinterlaceChain; + +typedef struct +{ + GstPlayChain chain; + GstPad *sinkpad; + GstElement *queue; + GstElement *conv; + GstElement *scale; + GstElement *sink; + gboolean async; + GstElement *ts_offset; +} GstPlayVideoChain; + +typedef struct +{ + GstPlayChain chain; + GstPad *sinkpad; + GstElement *queue; + GstElement *conv; + GstElement *resample; + GstPad *blockpad; /* srcpad of resample, used for switching the vis */ + GstPad *vissinkpad; /* visualisation sinkpad, */ + GstElement *vis; + GstPad *vissrcpad; /* visualisation srcpad, */ + GstPad *srcpad; /* outgoing srcpad, used to connect to the next + * chain */ +} GstPlayVisChain; + +typedef struct +{ + GstPlayChain chain; + GstPad *sinkpad; + GstElement *queue; + GstElement *identity; + GstElement *overlay; + GstPad *videosinkpad; + GstPad *textsinkpad; + GstPad *srcpad; /* outgoing srcpad, used to connect to the next + * chain */ + GstElement *sink; /* custom sink to receive subtitle buffers */ +} GstPlayTextChain; + +#define GST_PLAY_SINK_GET_LOCK(playsink) (&((GstPlaySink *)playsink)->lock) +#define GST_PLAY_SINK_LOCK(playsink) G_STMT_START { \ + GST_LOG_OBJECT (playsink, "locking from thread %p", g_thread_self ()); \ + g_static_rec_mutex_lock (GST_PLAY_SINK_GET_LOCK (playsink)); \ + GST_LOG_OBJECT (playsink, "locked from thread %p", g_thread_self ()); \ +} G_STMT_END +#define GST_PLAY_SINK_UNLOCK(playsink) G_STMT_START { \ + GST_LOG_OBJECT (playsink, "unlocking from thread %p", g_thread_self ()); \ + g_static_rec_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)); \ +} G_STMT_END + +struct _GstPlaySink +{ + GstBin bin; + + GStaticRecMutex lock; + + gboolean async_pending; + gboolean need_async_start; + + GstPlayFlags flags; + + GstStreamSynchronizer *stream_synchronizer; + + /* chains */ + GstPlayAudioChain *audiochain; + GstPlayVideoDeinterlaceChain *videodeinterlacechain; + GstPlayVideoChain *videochain; + GstPlayVisChain *vischain; + GstPlayTextChain *textchain; + + /* audio */ + GstPad *audio_pad; + gboolean audio_pad_raw; + GstPad *audio_srcpad_stream_synchronizer; + GstPad *audio_sinkpad_stream_synchronizer; + /* audio tee */ + GstElement *audio_tee; + GstPad *audio_tee_sink; + GstPad *audio_tee_asrc; + GstPad *audio_tee_vissrc; + /* video */ + GstPad *video_pad; + gboolean video_pad_raw; + GstPad *video_srcpad_stream_synchronizer; + GstPad *video_sinkpad_stream_synchronizer; + /* text */ + GstPad *text_pad; + GstPad *text_srcpad_stream_synchronizer; + GstPad *text_sinkpad_stream_synchronizer; + + /* properties */ + GstElement *audio_sink; + GstElement *video_sink; + GstElement *visualisation; + GstElement *text_sink; + gdouble volume; + gboolean mute; + gchar *font_desc; /* font description */ + gchar *subtitle_encoding; /* subtitle encoding */ + guint connection_speed; /* connection speed in bits/sec (0 = unknown) */ + gint count; + gboolean volume_changed; /* volume/mute changed while no audiochain */ + gboolean mute_changed; /* ... has been created yet */ + gint64 av_offset; +}; + +struct _GstPlaySinkClass +{ + GstBinClass parent_class; + + gboolean (*reconfigure) (GstPlaySink * playsink); + + GstBuffer *(*convert_frame) (GstPlaySink * playsink, GstCaps * caps); +}; + +static GstStaticPadTemplate audiorawtemplate = +GST_STATIC_PAD_TEMPLATE ("audio_raw_sink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate audiotemplate = +GST_STATIC_PAD_TEMPLATE ("audio_sink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate videorawtemplate = +GST_STATIC_PAD_TEMPLATE ("video_raw_sink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate videotemplate = +GST_STATIC_PAD_TEMPLATE ("video_sink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate texttemplate = GST_STATIC_PAD_TEMPLATE ("text_sink", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +/* props */ +enum +{ + PROP_0, + PROP_FLAGS, + PROP_MUTE, + PROP_VOLUME, + PROP_FONT_DESC, + PROP_SUBTITLE_ENCODING, + PROP_VIS_PLUGIN, + PROP_FRAME, + PROP_AV_OFFSET, + PROP_LAST +}; + +/* signals */ +enum +{ + LAST_SIGNAL +}; + +static void gst_play_sink_dispose (GObject * object); +static void gst_play_sink_finalize (GObject * object); +static void gst_play_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_play_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); + +static GstPad *gst_play_sink_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void gst_play_sink_release_request_pad (GstElement * element, + GstPad * pad); +static gboolean gst_play_sink_send_event (GstElement * element, + GstEvent * event); +static GstStateChangeReturn gst_play_sink_change_state (GstElement * element, + GstStateChange transition); + +static void gst_play_sink_handle_message (GstBin * bin, GstMessage * message); + +static void notify_volume_cb (GObject * object, GParamSpec * pspec, + GstPlaySink * playsink); +static void notify_mute_cb (GObject * object, GParamSpec * pspec, + GstPlaySink * playsink); + +static void update_av_offset (GstPlaySink * playsink); + +void +gst_play_marshal_BUFFER__BOXED (GClosure * closure, + GValue * return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue * param_values, + gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data) +{ + typedef GstBuffer *(*GMarshalFunc_OBJECT__BOXED) (gpointer data1, + gpointer arg_1, gpointer data2); + register GMarshalFunc_OBJECT__BOXED callback; + register GCClosure *cc = (GCClosure *) closure; + register gpointer data1, data2; + GstBuffer *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__BOXED) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, g_value_get_boxed (param_values + 1), data2); + + gst_value_take_buffer (return_value, v_return); +} + +/* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */ + +G_DEFINE_TYPE (GstPlaySink, gst_play_sink, GST_TYPE_BIN); + +static void +gst_play_sink_class_init (GstPlaySinkClass * klass) +{ + GObjectClass *gobject_klass; + GstElementClass *gstelement_klass; + GstBinClass *gstbin_klass; + + gobject_klass = (GObjectClass *) klass; + gstelement_klass = (GstElementClass *) klass; + gstbin_klass = (GstBinClass *) klass; + + gobject_klass->dispose = gst_play_sink_dispose; + gobject_klass->finalize = gst_play_sink_finalize; + gobject_klass->set_property = gst_play_sink_set_property; + gobject_klass->get_property = gst_play_sink_get_property; + + + /** + * GstPlaySink:flags + * + * Control the behaviour of playsink. + */ + g_object_class_install_property (gobject_klass, PROP_FLAGS, + g_param_spec_flags ("flags", "Flags", "Flags to control behaviour", + GST_TYPE_PLAY_FLAGS, DEFAULT_FLAGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstPlaySink:volume: + * + * Get or set the current audio stream volume. 1.0 means 100%, + * 0.0 means mute. This uses a linear volume scale. + * + */ + g_object_class_install_property (gobject_klass, PROP_VOLUME, + g_param_spec_double ("volume", "Volume", "The audio volume, 1.0=100%", + 0.0, VOLUME_MAX_DOUBLE, 1.0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", + "Mute the audio channel without changing the volume", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_FONT_DESC, + g_param_spec_string ("subtitle-font-desc", + "Subtitle font description", + "Pango font description of font " + "to be used for subtitle rendering", NULL, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, PROP_VIS_PLUGIN, + g_param_spec_object ("vis-plugin", "Vis plugin", + "the visualization element to use (NULL = default)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlaySink:frame: + * + * Get the currently rendered or prerolled frame in the video sink. + * The #GstCaps on the buffer will describe the format of the buffer. + * + * Since: 0.10.30 + */ + g_object_class_install_property (gobject_klass, PROP_FRAME, + gst_param_spec_mini_object ("frame", "Frame", + "The last frame (NULL = no video available)", + GST_TYPE_BUFFER, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstPlaySink:av-offset: + * + * Control the synchronisation offset between the audio and video streams. + * Positive values make the audio ahead of the video and negative values make + * the audio go behind the video. + * + * Since: 0.10.30 + */ + g_object_class_install_property (gobject_klass, PROP_AV_OFFSET, + g_param_spec_int64 ("av-offset", "AV Offset", + "The synchronisation offset between audio and video in nanoseconds", + G_MININT64, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_signal_new ("reconfigure", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstPlaySinkClass, + reconfigure), NULL, NULL, gst_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, + 0, G_TYPE_NONE); + /** + * GstPlaySink::convert-frame + * @playsink: a #GstPlaySink + * @caps: the target format of the frame + * + * Action signal to retrieve the currently playing video frame in the format + * specified by @caps. + * If @caps is %NULL, no conversion will be performed and this function is + * equivalent to the #GstPlaySink::frame property. + * + * Returns: a #GstBuffer of the current video frame converted to #caps. + * The caps on the buffer will describe the final layout of the buffer data. + * %NULL is returned when no current buffer can be retrieved or when the + * conversion failed. + * + * Since: 0.10.30 + */ + g_signal_new ("convert-frame", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstPlaySinkClass, convert_frame), NULL, NULL, + gst_play_marshal_BUFFER__BOXED, GST_TYPE_BUFFER, 1, GST_TYPE_CAPS); + + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&audiorawtemplate)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&audiotemplate)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&videorawtemplate)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&videotemplate)); + gst_element_class_add_pad_template (gstelement_klass, + gst_static_pad_template_get (&texttemplate)); + gst_element_class_set_details_simple (gstelement_klass, "Player Sink", + "Generic/Bin/Sink", + "Convenience sink for multiple streams", + "Wim Taymans "); + + gstelement_klass->change_state = + GST_DEBUG_FUNCPTR (gst_play_sink_change_state); + gstelement_klass->send_event = GST_DEBUG_FUNCPTR (gst_play_sink_send_event); + gstelement_klass->request_new_pad = + GST_DEBUG_FUNCPTR (gst_play_sink_request_new_pad); + gstelement_klass->release_pad = + GST_DEBUG_FUNCPTR (gst_play_sink_release_request_pad); + + gstbin_klass->handle_message = + GST_DEBUG_FUNCPTR (gst_play_sink_handle_message); + + klass->reconfigure = GST_DEBUG_FUNCPTR (gst_play_sink_reconfigure); + klass->convert_frame = GST_DEBUG_FUNCPTR (gst_play_sink_convert_frame); +} + +static void +gst_play_sink_init (GstPlaySink * playsink) +{ + /* init groups */ + playsink->video_sink = NULL; + playsink->audio_sink = NULL; + playsink->visualisation = NULL; + playsink->text_sink = NULL; + playsink->volume = 1.0; + playsink->font_desc = NULL; + playsink->subtitle_encoding = NULL; + playsink->flags = DEFAULT_FLAGS; + + playsink->stream_synchronizer = + g_object_new (GST_TYPE_STREAM_SYNCHRONIZER, NULL); + gst_bin_add (GST_BIN_CAST (playsink), + GST_ELEMENT_CAST (playsink->stream_synchronizer)); + + g_static_rec_mutex_init (&playsink->lock); + GST_OBJECT_FLAG_SET (playsink, GST_ELEMENT_IS_SINK); +} + +static void +disconnect_chain (GstPlayAudioChain * chain, GstPlaySink * playsink) +{ + if (chain) { + if (chain->volume) + g_signal_handlers_disconnect_by_func (chain->volume, notify_volume_cb, + playsink); + if (chain->mute) + g_signal_handlers_disconnect_by_func (chain->mute, notify_mute_cb, + playsink); + } +} + +static void +free_chain (GstPlayChain * chain) +{ + if (chain) { + if (chain->bin) + gst_object_unref (chain->bin); + g_free (chain); + } +} + +static void +gst_play_sink_dispose (GObject * object) +{ + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK (object); + + if (playsink->audio_sink != NULL) { + gst_element_set_state (playsink->audio_sink, GST_STATE_NULL); + gst_object_unref (playsink->audio_sink); + playsink->audio_sink = NULL; + } + if (playsink->video_sink != NULL) { + gst_element_set_state (playsink->video_sink, GST_STATE_NULL); + gst_object_unref (playsink->video_sink); + playsink->video_sink = NULL; + } + if (playsink->visualisation != NULL) { + gst_element_set_state (playsink->visualisation, GST_STATE_NULL); + gst_object_unref (playsink->visualisation); + playsink->visualisation = NULL; + } + if (playsink->text_sink != NULL) { + gst_element_set_state (playsink->text_sink, GST_STATE_NULL); + gst_object_unref (playsink->text_sink); + playsink->text_sink = NULL; + } + + free_chain ((GstPlayChain *) playsink->videodeinterlacechain); + playsink->videodeinterlacechain = NULL; + free_chain ((GstPlayChain *) playsink->videochain); + playsink->videochain = NULL; + free_chain ((GstPlayChain *) playsink->audiochain); + playsink->audiochain = NULL; + free_chain ((GstPlayChain *) playsink->vischain); + playsink->vischain = NULL; + free_chain ((GstPlayChain *) playsink->textchain); + playsink->textchain = NULL; + + if (playsink->audio_tee_sink) { + gst_object_unref (playsink->audio_tee_sink); + playsink->audio_tee_sink = NULL; + } + + if (playsink->audio_tee_vissrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_vissrc); + gst_object_unref (playsink->audio_tee_vissrc); + playsink->audio_tee_vissrc = NULL; + } + + if (playsink->audio_tee_asrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_asrc); + gst_object_unref (playsink->audio_tee_asrc); + playsink->audio_tee_asrc = NULL; + } + + g_free (playsink->font_desc); + playsink->font_desc = NULL; + + g_free (playsink->subtitle_encoding); + playsink->subtitle_encoding = NULL; + + playsink->stream_synchronizer = NULL; + + G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object); +} + +static void +gst_play_sink_finalize (GObject * object) +{ + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK (object); + + g_static_rec_mutex_free (&playsink->lock); + + G_OBJECT_CLASS (gst_play_sink_parent_class)->finalize (object); +} + +void +gst_play_sink_set_sink (GstPlaySink * playsink, GstPlaySinkType type, + GstElement * sink) +{ + GstElement **elem = NULL, *old = NULL; + + GST_LOG ("Setting sink %" GST_PTR_FORMAT " as sink type %d", sink, type); + + GST_PLAY_SINK_LOCK (playsink); + switch (type) { + case GST_PLAY_SINK_TYPE_AUDIO: + case GST_PLAY_SINK_TYPE_AUDIO_RAW: + elem = &playsink->audio_sink; + break; + case GST_PLAY_SINK_TYPE_VIDEO: + case GST_PLAY_SINK_TYPE_VIDEO_RAW: + elem = &playsink->video_sink; + break; + case GST_PLAY_SINK_TYPE_TEXT: + elem = &playsink->text_sink; + break; + default: + break; + } + if (elem) { + old = *elem; + if (sink) + gst_object_ref (sink); + *elem = sink; + } + GST_PLAY_SINK_UNLOCK (playsink); + + if (old) { + if (old != sink) + gst_element_set_state (old, GST_STATE_NULL); + gst_object_unref (old); + } +} + +GstElement * +gst_play_sink_get_sink (GstPlaySink * playsink, GstPlaySinkType type) +{ + GstElement *result = NULL; + GstElement *elem = NULL, *chainp = NULL; + + GST_PLAY_SINK_LOCK (playsink); + switch (type) { + case GST_PLAY_SINK_TYPE_AUDIO: + { + GstPlayAudioChain *chain; + if ((chain = (GstPlayAudioChain *) playsink->audiochain)) + chainp = chain->sink; + elem = playsink->audio_sink; + break; + } + case GST_PLAY_SINK_TYPE_VIDEO: + { + GstPlayVideoChain *chain; + if ((chain = (GstPlayVideoChain *) playsink->videochain)) + chainp = chain->sink; + elem = playsink->video_sink; + break; + } + case GST_PLAY_SINK_TYPE_TEXT: + { + GstPlayTextChain *chain; + if ((chain = (GstPlayTextChain *) playsink->textchain)) + chainp = chain->sink; + elem = playsink->text_sink; + break; + } + default: + break; + } + if (chainp) { + /* we have an active chain with a sink, get the sink */ + result = gst_object_ref (chainp); + } + /* nothing found, return last configured sink */ + if (result == NULL && elem) + result = gst_object_ref (elem); + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +static void +gst_play_sink_vis_unblocked (GstPad * tee_pad, gboolean blocked, + gpointer user_data) +{ + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK (user_data); + /* nothing to do here, we need a dummy callback here to make the async call + * non-blocking. */ + GST_DEBUG_OBJECT (playsink, "vis pad unblocked"); +} + +static void +gst_play_sink_vis_blocked (GstPad * tee_pad, gboolean blocked, + gpointer user_data) +{ + GstPlaySink *playsink; + GstPlayVisChain *chain; + + playsink = GST_PLAY_SINK (user_data); + + GST_PLAY_SINK_LOCK (playsink); + GST_DEBUG_OBJECT (playsink, "vis pad blocked"); + /* now try to change the plugin in the running vis chain */ + if (!(chain = (GstPlayVisChain *) playsink->vischain)) + goto done; + + /* unlink the old plugin and unghost the pad */ + gst_pad_unlink (chain->blockpad, chain->vissinkpad); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->srcpad), NULL); + + /* set the old plugin to NULL and remove */ + gst_element_set_state (chain->vis, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (chain->chain.bin), chain->vis); + + /* add new plugin and set state to playing */ + chain->vis = playsink->visualisation; + gst_bin_add (GST_BIN_CAST (chain->chain.bin), chain->vis); + gst_element_set_state (chain->vis, GST_STATE_PLAYING); + + /* get pads */ + chain->vissinkpad = gst_element_get_static_pad (chain->vis, "sink"); + chain->vissrcpad = gst_element_get_static_pad (chain->vis, "src"); + + /* link pads */ + gst_pad_link_full (chain->blockpad, chain->vissinkpad, + GST_PAD_LINK_CHECK_NOTHING); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (chain->srcpad), + chain->vissrcpad); + +done: + /* Unblock the pad */ + gst_pad_set_blocked_async (tee_pad, FALSE, gst_play_sink_vis_unblocked, + playsink); + GST_PLAY_SINK_UNLOCK (playsink); +} + +void +gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis) +{ + GstPlayVisChain *chain; + + /* setting NULL means creating the default vis plugin */ + if (vis == NULL) + vis = gst_element_factory_make ("goom", "vis"); + + /* simply return if we don't have a vis plugin here */ + if (vis == NULL) + return; + + GST_PLAY_SINK_LOCK (playsink); + /* first store the new vis */ + if (playsink->visualisation) + gst_object_unref (playsink->visualisation); + /* take ownership */ + gst_object_ref_sink (vis); + playsink->visualisation = vis; + + /* now try to change the plugin in the running vis chain, if we have no chain, + * we don't bother, any future vis chain will be created with the new vis + * plugin. */ + if (!(chain = (GstPlayVisChain *) playsink->vischain)) + goto done; + + /* block the pad, the next time the callback is called we can change the + * visualisation. It's possible that this never happens or that the pad was + * already blocked. If the callback never happens, we don't have new data so + * we don't need the new vis plugin. If the pad was already blocked, the + * function returns FALSE but the previous pad block will do the right thing + * anyway. */ + GST_DEBUG_OBJECT (playsink, "blocking vis pad"); + gst_pad_set_blocked_async (chain->blockpad, TRUE, gst_play_sink_vis_blocked, + playsink); +done: + GST_PLAY_SINK_UNLOCK (playsink); + + return; +} + +GstElement * +gst_play_sink_get_vis_plugin (GstPlaySink * playsink) +{ + GstElement *result = NULL; + GstPlayVisChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + if ((chain = (GstPlayVisChain *) playsink->vischain)) { + /* we have an active chain, get the sink */ + if (chain->vis) + result = gst_object_ref (chain->vis); + } + /* nothing found, return last configured sink */ + if (result == NULL && playsink->visualisation) + result = gst_object_ref (playsink->visualisation); + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +void +gst_play_sink_set_volume (GstPlaySink * playsink, gdouble volume) +{ + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + playsink->volume = volume; + chain = (GstPlayAudioChain *) playsink->audiochain; + if (chain && chain->volume) { + GST_LOG_OBJECT (playsink, "elements: volume=%" GST_PTR_FORMAT ", mute=%" + GST_PTR_FORMAT "; new volume=%.03f, mute=%d", chain->volume, + chain->mute, volume, playsink->mute); + /* if there is a mute element or we are not muted, set the volume */ + if (chain->mute || !playsink->mute) + g_object_set (chain->volume, "volume", volume, NULL); + } else { + GST_LOG_OBJECT (playsink, "no volume element"); + playsink->volume_changed = TRUE; + } + GST_PLAY_SINK_UNLOCK (playsink); +} + +gdouble +gst_play_sink_get_volume (GstPlaySink * playsink) +{ + gdouble result; + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayAudioChain *) playsink->audiochain; + result = playsink->volume; + if (chain && chain->volume) { + if (chain->mute || !playsink->mute) { + g_object_get (chain->volume, "volume", &result, NULL); + playsink->volume = result; + } + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +void +gst_play_sink_set_mute (GstPlaySink * playsink, gboolean mute) +{ + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + playsink->mute = mute; + chain = (GstPlayAudioChain *) playsink->audiochain; + if (chain) { + if (chain->mute) { + g_object_set (chain->mute, "mute", mute, NULL); + } else if (chain->volume) { + if (mute) + g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL); + else + g_object_set (chain->volume, "volume", (gdouble) playsink->volume, + NULL); + } + } else { + playsink->mute_changed = TRUE; + } + GST_PLAY_SINK_UNLOCK (playsink); +} + +gboolean +gst_play_sink_get_mute (GstPlaySink * playsink) +{ + gboolean result; + GstPlayAudioChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayAudioChain *) playsink->audiochain; + if (chain && chain->mute) { + g_object_get (chain->mute, "mute", &result, NULL); + playsink->mute = result; + } else { + result = playsink->mute; + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +static void +post_missing_element_message (GstPlaySink * playsink, const gchar * name) +{ + GstMessage *msg; + + msg = gst_missing_element_message_new (GST_ELEMENT_CAST (playsink), name); + gst_element_post_message (GST_ELEMENT_CAST (playsink), msg); +} + +static gboolean +add_chain (GstPlayChain * chain, gboolean add) +{ + if (chain->added == add) + return TRUE; + + if (add) + gst_bin_add (GST_BIN_CAST (chain->playsink), chain->bin); + else { + gst_bin_remove (GST_BIN_CAST (chain->playsink), chain->bin); + /* we don't want to lose our sink status */ + GST_OBJECT_FLAG_SET (chain->playsink, GST_ELEMENT_IS_SINK); + } + + chain->added = add; + + return TRUE; +} + +static gboolean +activate_chain (GstPlayChain * chain, gboolean activate) +{ + GstState state; + + if (chain->activated == activate) + return TRUE; + + GST_OBJECT_LOCK (chain->playsink); + state = GST_STATE_TARGET (chain->playsink); + GST_OBJECT_UNLOCK (chain->playsink); + + if (activate) + gst_element_set_state (chain->bin, state); + else + gst_element_set_state (chain->bin, GST_STATE_NULL); + + chain->activated = activate; + + return TRUE; +} + +static gboolean +element_is_sink (GstElement * element) +{ + gboolean is_sink; + + GST_OBJECT_LOCK (element); + is_sink = GST_OBJECT_FLAG_IS_SET (element, GST_ELEMENT_IS_SINK); + GST_OBJECT_UNLOCK (element); + + GST_DEBUG_OBJECT (element, "is a sink: %s", (is_sink) ? "yes" : "no"); + return is_sink; +} + +static gboolean +element_has_property (GstElement * element, const gchar * pname, GType type) +{ + GParamSpec *pspec; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), pname); + + if (pspec == NULL) { + GST_DEBUG_OBJECT (element, "no %s property", pname); + return FALSE; + } + + if (type == G_TYPE_INVALID || type == pspec->value_type || + g_type_is_a (pspec->value_type, type)) { + GST_DEBUG_OBJECT (element, "has %s property of type %s", pname, + (type == G_TYPE_INVALID) ? "any type" : g_type_name (type)); + return TRUE; + } + + GST_WARNING_OBJECT (element, "has %s property, but property is of type %s " + "and we expected it to be of type %s", pname, + g_type_name (pspec->value_type), g_type_name (type)); + + return FALSE; +} + +typedef struct +{ + const gchar *prop_name; + GType prop_type; + gboolean need_sink; +} FindPropertyHelper; + +static gint +find_property (GstElement * element, FindPropertyHelper * helper) +{ + if (helper->need_sink && !element_is_sink (element)) { + gst_object_unref (element); + return 1; + } + + if (!element_has_property (element, helper->prop_name, helper->prop_type)) { + gst_object_unref (element); + return 1; + } + + GST_INFO_OBJECT (element, "found %s with %s property", helper->prop_name, + (helper->need_sink) ? "sink" : "element"); + return 0; /* keep it */ +} + +/* FIXME: why not move these functions into core? */ +/* find a sink in the hierarchy with a property named @name. This function does + * not increase the refcount of the returned object and thus remains valid as + * long as the bin is valid. */ +static GstElement * +gst_play_sink_find_property_sinks (GstPlaySink * playsink, GstElement * obj, + const gchar * name, GType expected_type) +{ + GstElement *result = NULL; + GstIterator *it; + + if (element_has_property (obj, name, expected_type)) { + result = obj; + } else if (GST_IS_BIN (obj)) { + FindPropertyHelper helper = { name, expected_type, TRUE }; + + it = gst_bin_iterate_recurse (GST_BIN_CAST (obj)); + result = gst_iterator_find_custom (it, + (GCompareFunc) find_property, &helper); + gst_iterator_free (it); + /* we don't need the extra ref */ + if (result) + gst_object_unref (result); + } + return result; +} + +/* find an object in the hierarchy with a property named @name */ +static GstElement * +gst_play_sink_find_property (GstPlaySink * playsink, GstElement * obj, + const gchar * name, GType expected_type) +{ + GstElement *result = NULL; + GstIterator *it; + + if (GST_IS_BIN (obj)) { + FindPropertyHelper helper = { name, expected_type, FALSE }; + + it = gst_bin_iterate_recurse (GST_BIN_CAST (obj)); + result = gst_iterator_find_custom (it, + (GCompareFunc) find_property, &helper); + gst_iterator_free (it); + } else { + if (element_has_property (obj, name, expected_type)) { + result = obj; + gst_object_ref (obj); + } + } + return result; +} + +static void +do_async_start (GstPlaySink * playsink) +{ + GstMessage *message; + + if (!playsink->need_async_start) { + GST_INFO_OBJECT (playsink, "no async_start needed"); + return; + } + + playsink->async_pending = TRUE; + + GST_INFO_OBJECT (playsink, "Sending async_start message"); + message = gst_message_new_async_start (GST_OBJECT_CAST (playsink), FALSE); + GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST + (playsink), message); +} + +static void +do_async_done (GstPlaySink * playsink) +{ + GstMessage *message; + + if (playsink->async_pending) { + GST_INFO_OBJECT (playsink, "Sending async_done message"); + message = gst_message_new_async_done (GST_OBJECT_CAST (playsink)); + GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (GST_BIN_CAST + (playsink), message); + + playsink->async_pending = FALSE; + } + + playsink->need_async_start = FALSE; +} + +/* try to change the state of an element. This function returns the element when + * the state change could be performed. When this function returns NULL an error + * occured and the element is unreffed if @unref is TRUE. */ +static GstElement * +try_element (GstPlaySink * playsink, GstElement * element, gboolean unref) +{ + GstStateChangeReturn ret; + + if (element) { + ret = gst_element_set_state (element, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) { + GST_DEBUG_OBJECT (playsink, "failed state change.."); + gst_element_set_state (element, GST_STATE_NULL); + if (unref) + gst_object_unref (element); + element = NULL; + } + } + return element; +} + +/* make the element (bin) that contains the elements needed to perform + * video display. + * + * +------------------------------------------------------------+ + * | vbin | + * | +-------+ +----------+ +----------+ +---------+ | + * | | queue | |colorspace| |videoscale| |videosink| | + * | +-sink src-sink src-sink src-sink | | + * | | +-------+ +----------+ +----------+ +---------+ | + * sink-+ | + * +------------------------------------------------------------+ + * + */ +static GstPlayVideoDeinterlaceChain * +gen_video_deinterlace_chain (GstPlaySink * playsink) +{ + GstPlayVideoDeinterlaceChain *chain; + GstBin *bin; + GstPad *pad; + GstElement *head = NULL, *prev = NULL; + + chain = g_new0 (GstPlayVideoDeinterlaceChain, 1); + chain->chain.playsink = playsink; + + GST_DEBUG_OBJECT (playsink, "making video deinterlace chain %p", chain); + + /* create a bin to hold objects, as we create them we add them to this bin so + * that when something goes wrong we only need to unref the bin */ + chain->chain.bin = gst_bin_new ("vdbin"); + bin = GST_BIN_CAST (chain->chain.bin); + gst_object_ref_sink (bin); + + GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace"); + chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vdconv"); + if (chain->conv == NULL) { + post_missing_element_message (playsink, "ffmpegcolorspace"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "ffmpegcolorspace"), ("video rendering might fail")); + } else { + gst_bin_add (bin, chain->conv); + head = chain->conv; + prev = chain->conv; + } + + GST_DEBUG_OBJECT (playsink, "creating deinterlace"); + chain->deinterlace = gst_element_factory_make ("deinterlace", "deinterlace"); + if (chain->deinterlace == NULL) { + post_missing_element_message (playsink, "deinterlace"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "deinterlace"), ("deinterlacing won't work")); + } else { + gst_bin_add (bin, chain->deinterlace); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->deinterlace, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->deinterlace; + } + prev = chain->deinterlace; + } + + if (head) { + pad = gst_element_get_static_pad (head, "sink"); + chain->sinkpad = gst_ghost_pad_new ("sink", pad); + gst_object_unref (pad); + } else { + chain->sinkpad = gst_ghost_pad_new_no_target ("sink", GST_PAD_SINK); + } + + if (prev) { + pad = gst_element_get_static_pad (prev, "src"); + chain->srcpad = gst_ghost_pad_new ("src", pad); + gst_object_unref (pad); + } else { + chain->srcpad = gst_ghost_pad_new ("src", chain->sinkpad); + } + + gst_element_add_pad (chain->chain.bin, chain->sinkpad); + gst_element_add_pad (chain->chain.bin, chain->srcpad); + + return chain; + +link_failed: + { + GST_ELEMENT_ERROR (playsink, CORE, PAD, + (NULL), ("Failed to configure the video deinterlace chain.")); + free_chain ((GstPlayChain *) chain); + return NULL; + } +} + +/* make the element (bin) that contains the elements needed to perform + * video display. + * + * +------------------------------------------------------------+ + * | vbin | + * | +-------+ +----------+ +----------+ +---------+ | + * | | queue | |colorspace| |videoscale| |videosink| | + * | +-sink src-sink src-sink src-sink | | + * | | +-------+ +----------+ +----------+ +---------+ | + * sink-+ | + * +------------------------------------------------------------+ + * + */ +static GstPlayVideoChain * +gen_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) +{ + GstPlayVideoChain *chain; + GstBin *bin; + GstPad *pad; + GstElement *head = NULL, *prev = NULL, *elem = NULL; + + chain = g_new0 (GstPlayVideoChain, 1); + chain->chain.playsink = playsink; + chain->chain.raw = raw; + + GST_DEBUG_OBJECT (playsink, "making video chain %p", chain); + + if (playsink->video_sink) { + GST_DEBUG_OBJECT (playsink, "trying configured videosink"); + chain->sink = try_element (playsink, playsink->video_sink, FALSE); + } else { + /* only try fallback if no specific sink was chosen */ + if (chain->sink == NULL) { + GST_DEBUG_OBJECT (playsink, "trying autovideosink"); + elem = gst_element_factory_make ("autovideosink", "videosink"); + chain->sink = try_element (playsink, elem, TRUE); + } + if (chain->sink == NULL) { + /* if default sink from config.h is different then try it too */ + if (strcmp (DEFAULT_VIDEOSINK, "autovideosink")) { + GST_DEBUG_OBJECT (playsink, "trying " DEFAULT_VIDEOSINK); + elem = gst_element_factory_make (DEFAULT_VIDEOSINK, "videosink"); + chain->sink = try_element (playsink, elem, TRUE); + } + } + if (chain->sink) + playsink->video_sink = gst_object_ref (chain->sink); + } + if (chain->sink == NULL) + goto no_sinks; + head = chain->sink; + + /* if we can disable async behaviour of the sink, we can avoid adding a + * queue for the audio chain. */ + elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, "async", + G_TYPE_BOOLEAN); + if (elem) { + GST_DEBUG_OBJECT (playsink, "setting async property to %d on element %s", + async, GST_ELEMENT_NAME (elem)); + g_object_set (elem, "async", async, NULL); + chain->async = async; + } else { + GST_DEBUG_OBJECT (playsink, "no async property on the sink"); + chain->async = TRUE; + } + + /* find ts-offset element */ + chain->ts_offset = + gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset", + G_TYPE_INT64); + + /* create a bin to hold objects, as we create them we add them to this bin so + * that when something goes wrong we only need to unref the bin */ + chain->chain.bin = gst_bin_new ("vbin"); + bin = GST_BIN_CAST (chain->chain.bin); + gst_object_ref_sink (bin); + gst_bin_add (bin, chain->sink); + + /* decouple decoder from sink, this improves playback quite a lot since the + * decoder can continue while the sink blocks for synchronisation. We don't + * need a lot of buffers as this consumes a lot of memory and we don't want + * too little because else we would be context switching too quickly. */ + chain->queue = gst_element_factory_make ("queue", "vqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("video rendering might be suboptimal")); + head = chain->sink; + prev = NULL; + } else { + g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3, + "max-size-bytes", 0, "max-size-time", (gint64) 0, "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + head = prev = chain->queue; + } + + if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { + GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace"); + chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); + if (chain->conv == NULL) { + post_missing_element_message (playsink, "ffmpegcolorspace"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "ffmpegcolorspace"), ("video rendering might fail")); + } else { + gst_bin_add (bin, chain->conv); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->conv; + } + prev = chain->conv; + } + + GST_DEBUG_OBJECT (playsink, "creating videoscale"); + chain->scale = gst_element_factory_make ("videoscale", "vscale"); + if (chain->scale == NULL) { + post_missing_element_message (playsink, "videoscale"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "videoscale"), ("possibly a liboil version mismatch?")); + } else { + /* Add black borders if necessary to keep the DAR */ + g_object_set (chain->scale, "add-borders", TRUE, NULL); + gst_bin_add (bin, chain->scale); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->scale, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->scale; + } + prev = chain->scale; + } + } + + if (prev) { + GST_DEBUG_OBJECT (playsink, "linking to sink"); + if (!gst_element_link_pads_full (prev, "src", chain->sink, NULL, + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } + + pad = gst_element_get_static_pad (head, "sink"); + chain->sinkpad = gst_ghost_pad_new ("sink", pad); + gst_object_unref (pad); + + gst_element_add_pad (chain->chain.bin, chain->sinkpad); + + return chain; + + /* ERRORS */ +no_sinks: + { + if (!elem && !playsink->video_sink) { + post_missing_element_message (playsink, "autovideosink"); + if (strcmp (DEFAULT_VIDEOSINK, "autovideosink")) { + post_missing_element_message (playsink, DEFAULT_VIDEOSINK); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Both autovideosink and %s elements are missing."), + DEFAULT_VIDEOSINK), (NULL)); + } else { + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("The autovideosink element is missing.")), (NULL)); + } + } else { + if (playsink->video_sink) { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("Configured videosink %s is not working."), + GST_ELEMENT_NAME (playsink->video_sink)), (NULL)); + } else if (strcmp (DEFAULT_VIDEOSINK, "autovideosink")) { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("Both autovideosink and %s elements are not working."), + DEFAULT_VIDEOSINK), (NULL)); + } else { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("The autovideosink element is not working.")), (NULL)); + } + } + free_chain ((GstPlayChain *) chain); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (playsink, CORE, PAD, + (NULL), ("Failed to configure the video sink.")); + /* checking sink made it READY */ + gst_element_set_state (chain->sink, GST_STATE_NULL); + /* Remove chain from the bin to allow reuse later */ + gst_bin_remove (bin, chain->sink); + free_chain ((GstPlayChain *) chain); + return NULL; + } +} + +static gboolean +setup_video_chain (GstPlaySink * playsink, gboolean raw, gboolean async) +{ + GstElement *elem; + GstPlayVideoChain *chain; + GstStateChangeReturn ret; + + chain = playsink->videochain; + + /* if the chain was active we don't do anything */ + if (GST_PLAY_CHAIN (chain)->activated == TRUE) + return TRUE; + + if (chain->chain.raw != raw) + return FALSE; + + /* try to set the sink element to READY again */ + ret = gst_element_set_state (chain->sink, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) + return FALSE; + + /* find ts-offset element */ + chain->ts_offset = + gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset", + G_TYPE_INT64); + + /* if we can disable async behaviour of the sink, we can avoid adding a + * queue for the audio chain. */ + elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, "async", + G_TYPE_BOOLEAN); + if (elem) { + GST_DEBUG_OBJECT (playsink, "setting async property to %d on element %s", + async, GST_ELEMENT_NAME (elem)); + g_object_set (elem, "async", async, NULL); + chain->async = async; + } else { + GST_DEBUG_OBJECT (playsink, "no async property on the sink"); + chain->async = TRUE; + } + return TRUE; +} + +/* make an element for playback of video with subtitles embedded. + * + * +--------------------------------------------+ + * | tbin | + * | +--------+ +-----------------+ | + * | | queue | | subtitleoverlay | | + * video--src sink---video_sink | | + * | +--------+ | src--src + * text------------------text_sink | | + * | +-----------------+ | + * +--------------------------------------------+ + * + */ +static GstPlayTextChain * +gen_text_chain (GstPlaySink * playsink) +{ + GstPlayTextChain *chain; + GstBin *bin; + GstElement *elem; + GstPad *videosinkpad, *textsinkpad, *srcpad; + + chain = g_new0 (GstPlayTextChain, 1); + chain->chain.playsink = playsink; + + GST_DEBUG_OBJECT (playsink, "making text chain %p", chain); + + chain->chain.bin = gst_bin_new ("tbin"); + bin = GST_BIN_CAST (chain->chain.bin); + gst_object_ref_sink (bin); + + videosinkpad = textsinkpad = srcpad = NULL; + + /* first try to hook the text pad to the custom sink */ + if (playsink->text_sink) { + GST_DEBUG_OBJECT (playsink, "trying configured textsink"); + chain->sink = try_element (playsink, playsink->text_sink, FALSE); + if (chain->sink) { + elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, "async", + G_TYPE_BOOLEAN); + if (elem) { + /* make sure the sparse subtitles don't participate in the preroll */ + g_object_set (elem, "async", FALSE, NULL); + GST_DEBUG_OBJECT (playsink, "adding custom text sink"); + gst_bin_add (bin, chain->sink); + /* NOTE streamsynchronizer needs streams decoupled */ + /* make a little queue */ + chain->queue = gst_element_factory_make ("queue", "subqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("rendering might be suboptimal")); + } else { + g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3, + "max-size-bytes", 0, "max-size-time", (gint64) 0, + "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + } + /* we have a custom sink, this will be our textsinkpad */ + if (gst_element_link_pads_full (chain->queue, "src", chain->sink, + "sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) { + /* we're all fine now and we can add the sink to the chain */ + GST_DEBUG_OBJECT (playsink, "using custom text sink"); + textsinkpad = gst_element_get_static_pad (chain->queue, "sink"); + } else { + GST_WARNING_OBJECT (playsink, + "can't find a sink pad on custom text sink"); + gst_bin_remove (bin, chain->sink); + gst_bin_remove (bin, chain->queue); + chain->sink = NULL; + chain->queue = NULL; + } + /* try to set sync to true but it's no biggie when we can't */ + if ((elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, + "sync", G_TYPE_BOOLEAN))) + g_object_set (elem, "sync", TRUE, NULL); + + if (!textsinkpad) + gst_bin_remove (bin, chain->sink); + } else { + GST_WARNING_OBJECT (playsink, + "can't find async property in custom text sink"); + } + } + if (textsinkpad == NULL) { + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Custom text sink element is not usable.")), + ("fallback to default textoverlay")); + } + } + + if (textsinkpad == NULL) { + if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_VIDEO)) { + /* make a little queue */ + chain->queue = gst_element_factory_make ("queue", "vqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("video rendering might be suboptimal")); + } else { + g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3, + "max-size-bytes", 0, "max-size-time", (gint64) 0, + "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + videosinkpad = gst_element_get_static_pad (chain->queue, "sink"); + } + + chain->overlay = + gst_element_factory_make ("subtitleoverlay", "suboverlay"); + if (chain->overlay == NULL) { + post_missing_element_message (playsink, "subtitleoverlay"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "subtitleoverlay"), ("subtitle rendering disabled")); + } else { + GstElement *element; + + gst_bin_add (bin, chain->overlay); + + g_object_set (G_OBJECT (chain->overlay), "silent", FALSE, NULL); + if (playsink->font_desc) { + g_object_set (G_OBJECT (chain->overlay), "font-desc", + playsink->font_desc, NULL); + } + if (playsink->subtitle_encoding) { + g_object_set (G_OBJECT (chain->overlay), "subtitle-encoding", + playsink->subtitle_encoding, NULL); + } + + gst_element_link_pads_full (chain->queue, "src", chain->overlay, + "video_sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS); + + /* make another little queue to decouple streams */ + element = gst_element_factory_make ("queue", "subqueue"); + if (element == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("rendering might be suboptimal")); + } else { + g_object_set (G_OBJECT (element), "max-size-buffers", 3, + "max-size-bytes", 0, "max-size-time", (gint64) 0, + "silent", TRUE, NULL); + gst_bin_add (bin, element); + gst_element_link_pads_full (element, "src", chain->overlay, + "subtitle_sink", GST_PAD_LINK_CHECK_TEMPLATE_CAPS); + textsinkpad = gst_element_get_static_pad (element, "sink"); + srcpad = gst_element_get_static_pad (chain->overlay, "src"); + } + } + } + } + + if (videosinkpad == NULL) { + /* if we still don't have a videosink, we don't have an overlay. the only + * thing we can do is insert an identity and ghost the src + * and sink pads. */ + chain->identity = gst_element_factory_make ("identity", "tidentity"); + if (chain->identity == NULL) { + post_missing_element_message (playsink, "identity"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "identity"), (NULL)); + } else { + g_object_set (chain->identity, "signal-handoffs", FALSE, NULL); + g_object_set (chain->identity, "silent", TRUE, NULL); + gst_bin_add (bin, chain->identity); + srcpad = gst_element_get_static_pad (chain->identity, "src"); + videosinkpad = gst_element_get_static_pad (chain->identity, "sink"); + } + } + + /* expose the ghostpads */ + if (videosinkpad) { + chain->videosinkpad = gst_ghost_pad_new ("sink", videosinkpad); + gst_object_unref (videosinkpad); + gst_element_add_pad (chain->chain.bin, chain->videosinkpad); + } + if (textsinkpad) { + chain->textsinkpad = gst_ghost_pad_new ("text_sink", textsinkpad); + gst_object_unref (textsinkpad); + gst_element_add_pad (chain->chain.bin, chain->textsinkpad); + } + if (srcpad) { + chain->srcpad = gst_ghost_pad_new ("src", srcpad); + gst_object_unref (srcpad); + gst_element_add_pad (chain->chain.bin, chain->srcpad); + } + + return chain; +} + +static void +notify_volume_cb (GObject * object, GParamSpec * pspec, GstPlaySink * playsink) +{ + gdouble vol; + + g_object_get (object, "volume", &vol, NULL); + playsink->volume = vol; + + g_object_notify (G_OBJECT (playsink), "volume"); +} + +static void +notify_mute_cb (GObject * object, GParamSpec * pspec, GstPlaySink * playsink) +{ + gboolean mute; + + g_object_get (object, "mute", &mute, NULL); + playsink->mute = mute; + + g_object_notify (G_OBJECT (playsink), "mute"); +} + +/* make the chain that contains the elements needed to perform + * audio playback. + * + * We add a tee as the first element so that we can link the visualisation chain + * to it when requested. + * + * +-------------------------------------------------------------+ + * | abin | + * | +---------+ +----------+ +---------+ +---------+ | + * | |audioconv| |audioscale| | volume | |audiosink| | + * | +-srck src-sink src-sink src-sink | | + * | | +---------+ +----------+ +---------+ +---------+ | + * sink-+ | + * +-------------------------------------------------------------+ + */ +static GstPlayAudioChain * +gen_audio_chain (GstPlaySink * playsink, gboolean raw) +{ + GstPlayAudioChain *chain; + GstBin *bin; + gboolean have_volume; + GstPad *pad; + GstElement *head, *prev, *elem = NULL; + + chain = g_new0 (GstPlayAudioChain, 1); + chain->chain.playsink = playsink; + chain->chain.raw = raw; + + GST_DEBUG_OBJECT (playsink, "making audio chain %p", chain); + + if (playsink->audio_sink) { + GST_DEBUG_OBJECT (playsink, "trying configured audiosink %" GST_PTR_FORMAT, + playsink->audio_sink); + chain->sink = try_element (playsink, playsink->audio_sink, FALSE); + } else { + /* only try fallback if no specific sink was chosen */ + if (chain->sink == NULL) { + GST_DEBUG_OBJECT (playsink, "trying autoaudiosink"); + elem = gst_element_factory_make ("autoaudiosink", "audiosink"); + chain->sink = try_element (playsink, elem, TRUE); + } + if (chain->sink == NULL) { + /* if default sink from config.h is different then try it too */ + if (strcmp (DEFAULT_AUDIOSINK, "autoaudiosink")) { + GST_DEBUG_OBJECT (playsink, "trying " DEFAULT_AUDIOSINK); + elem = gst_element_factory_make (DEFAULT_AUDIOSINK, "audiosink"); + chain->sink = try_element (playsink, elem, TRUE); + } + } + if (chain->sink) + playsink->audio_sink = gst_object_ref (chain->sink); + } + if (chain->sink == NULL) + goto no_sinks; + + chain->chain.bin = gst_bin_new ("abin"); + bin = GST_BIN_CAST (chain->chain.bin); + gst_object_ref_sink (bin); + gst_bin_add (bin, chain->sink); + + /* we have to add a queue when we need to decouple for the video sink in + * visualisations and for streamsynchronizer */ + GST_DEBUG_OBJECT (playsink, "adding audio queue"); + chain->queue = gst_element_factory_make ("queue", "aqueue"); + if (chain->queue == NULL) { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), ("audio playback and visualizations might not work")); + head = chain->sink; + prev = NULL; + } else { + g_object_set (chain->queue, "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + prev = head = chain->queue; + } + + /* find ts-offset element */ + chain->ts_offset = + gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset", + G_TYPE_INT64); + + /* check if the sink, or something within the sink, has the volume property. + * If it does we don't need to add a volume element. */ + elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", + G_TYPE_DOUBLE); + if (elem) { + chain->volume = elem; + + g_signal_connect (chain->volume, "notify::volume", + G_CALLBACK (notify_volume_cb), playsink); + + GST_DEBUG_OBJECT (playsink, "the sink has a volume property"); + have_volume = TRUE; + chain->sink_volume = TRUE; + /* if the sink also has a mute property we can use this as well. We'll only + * use the mute property if there is a volume property. We can simulate the + * mute with the volume otherwise. */ + chain->mute = + gst_play_sink_find_property_sinks (playsink, chain->sink, "mute", + G_TYPE_BOOLEAN); + if (chain->mute) { + GST_DEBUG_OBJECT (playsink, "the sink has a mute property"); + g_signal_connect (chain->mute, "notify::mute", + G_CALLBACK (notify_mute_cb), playsink); + } + /* use the sink to control the volume and mute */ + if (playsink->volume_changed) { + g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); + playsink->volume_changed = FALSE; + } + if (playsink->mute_changed) { + if (chain->mute) { + g_object_set (chain->mute, "mute", playsink->mute, NULL); + } else { + if (playsink->mute) + g_object_set (chain->volume, "volume", (gdouble) 0.0, NULL); + } + playsink->mute_changed = FALSE; + } + } else { + /* no volume, we need to add a volume element when we can */ + GST_DEBUG_OBJECT (playsink, "the sink has no volume property"); + have_volume = FALSE; + chain->sink_volume = FALSE; + } + + if (raw && !(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO)) { + GST_DEBUG_OBJECT (playsink, "creating audioconvert"); + chain->conv = gst_element_factory_make ("audioconvert", "aconv"); + if (chain->conv == NULL) { + post_missing_element_message (playsink, "audioconvert"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioconvert"), ("possibly a liboil version mismatch?")); + } else { + gst_bin_add (bin, chain->conv); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->conv; + } + prev = chain->conv; + } + + GST_DEBUG_OBJECT (playsink, "creating audioresample"); + chain->resample = gst_element_factory_make ("audioresample", "aresample"); + if (chain->resample == NULL) { + post_missing_element_message (playsink, "audioresample"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioresample"), ("possibly a liboil version mismatch?")); + } else { + gst_bin_add (bin, chain->resample); + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->resample, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->resample; + } + prev = chain->resample; + } + + if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) { + GST_DEBUG_OBJECT (playsink, "creating volume"); + chain->volume = gst_element_factory_make ("volume", "volume"); + if (chain->volume == NULL) { + post_missing_element_message (playsink, "volume"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "volume"), ("possibly a liboil version mismatch?")); + } else { + have_volume = TRUE; + + g_signal_connect (chain->volume, "notify::volume", + G_CALLBACK (notify_volume_cb), playsink); + + /* volume also has the mute property */ + chain->mute = chain->volume; + g_signal_connect (chain->mute, "notify::mute", + G_CALLBACK (notify_mute_cb), playsink); + + /* configure with the latest volume and mute */ + g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, + NULL); + g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL); + gst_bin_add (bin, chain->volume); + + if (prev) { + if (!gst_element_link_pads_full (prev, "src", chain->volume, "sink", + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } else { + head = chain->volume; + } + prev = chain->volume; + } + } + } + + if (prev) { + /* we only have to link to the previous element if we have something in + * front of the sink */ + GST_DEBUG_OBJECT (playsink, "linking to sink"); + if (!gst_element_link_pads_full (prev, "src", chain->sink, NULL, + GST_PAD_LINK_CHECK_TEMPLATE_CAPS)) + goto link_failed; + } + + /* post a warning if we have no way to configure the volume */ + if (!have_volume) { + GST_ELEMENT_WARNING (playsink, STREAM, NOT_IMPLEMENTED, + (_("No volume control found")), ("Volume/mute is not available")); + } + + /* and ghost the sinkpad of the headmost element */ + GST_DEBUG_OBJECT (playsink, "ghosting sink pad"); + pad = gst_element_get_static_pad (head, "sink"); + chain->sinkpad = gst_ghost_pad_new ("sink", pad); + gst_object_unref (pad); + gst_element_add_pad (chain->chain.bin, chain->sinkpad); + + return chain; + + /* ERRORS */ +no_sinks: + { + if (!elem && !playsink->audio_sink) { + post_missing_element_message (playsink, "autoaudiosink"); + if (strcmp (DEFAULT_AUDIOSINK, "autoaudiosink")) { + post_missing_element_message (playsink, DEFAULT_AUDIOSINK); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Both autoaudiosink and %s elements are missing."), + DEFAULT_AUDIOSINK), (NULL)); + } else { + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("The autoaudiosink element is missing.")), (NULL)); + } + } else { + if (playsink->audio_sink) { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("Configured audiosink %s is not working."), + GST_ELEMENT_NAME (playsink->audio_sink)), (NULL)); + } else if (strcmp (DEFAULT_AUDIOSINK, "autoaudiosink")) { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("Both autoaudiosink and %s elements are not working."), + DEFAULT_AUDIOSINK), (NULL)); + } else { + GST_ELEMENT_ERROR (playsink, CORE, STATE_CHANGE, + (_("The autoaudiosink element is not working.")), (NULL)); + } + } + free_chain ((GstPlayChain *) chain); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (playsink, CORE, PAD, + (NULL), ("Failed to configure the audio sink.")); + /* checking sink made it READY */ + gst_element_set_state (chain->sink, GST_STATE_NULL); + /* Remove chain from the bin to allow reuse later */ + gst_bin_remove (bin, chain->sink); + free_chain ((GstPlayChain *) chain); + return NULL; + } +} + +static gboolean +setup_audio_chain (GstPlaySink * playsink, gboolean raw) +{ + GstElement *elem; + GstPlayAudioChain *chain; + GstStateChangeReturn ret; + + chain = playsink->audiochain; + + /* if the chain was active we don't do anything */ + if (GST_PLAY_CHAIN (chain)->activated == TRUE) + return TRUE; + + if (chain->chain.raw != raw) + return FALSE; + + /* try to set the sink element to READY again */ + ret = gst_element_set_state (chain->sink, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) + return FALSE; + + /* find ts-offset element */ + chain->ts_offset = + gst_play_sink_find_property_sinks (playsink, chain->sink, "ts-offset", + G_TYPE_INT64); + + /* check if the sink, or something within the sink, has the volume property. + * If it does we don't need to add a volume element. */ + elem = + gst_play_sink_find_property_sinks (playsink, chain->sink, "volume", + G_TYPE_DOUBLE); + if (elem) { + chain->volume = elem; + + if (playsink->volume_changed) { + GST_DEBUG_OBJECT (playsink, "the sink has a volume property, setting %f", + playsink->volume); + /* use the sink to control the volume */ + g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); + playsink->volume_changed = FALSE; + } + + g_signal_connect (chain->volume, "notify::volume", + G_CALLBACK (notify_volume_cb), playsink); + /* if the sink also has a mute property we can use this as well. We'll only + * use the mute property if there is a volume property. We can simulate the + * mute with the volume otherwise. */ + chain->mute = + gst_play_sink_find_property_sinks (playsink, chain->sink, "mute", + G_TYPE_BOOLEAN); + if (chain->mute) { + GST_DEBUG_OBJECT (playsink, "the sink has a mute property"); + g_signal_connect (chain->mute, "notify::mute", + G_CALLBACK (notify_mute_cb), playsink); + } + } else { + /* no volume, we need to add a volume element when we can */ + GST_DEBUG_OBJECT (playsink, "the sink has no volume property"); + if (!raw) { + GST_LOG_OBJECT (playsink, "non-raw format, can't do soft volume control"); + + disconnect_chain (chain, playsink); + chain->volume = NULL; + chain->mute = NULL; + } else { + /* both last and current chain are raw audio, there should be a volume + * element already, unless the sink changed from one with a volume + * property to one that hasn't got a volume property, in which case we + * re-generate the chain */ + if (chain->volume == NULL) { + GST_DEBUG_OBJECT (playsink, "no existing volume element to re-use"); + /* undo background state change done earlier */ + gst_element_set_state (chain->sink, GST_STATE_NULL); + return FALSE; + } + + GST_DEBUG_OBJECT (playsink, "reusing existing volume element"); + } + } + return TRUE; +} + +/* + * +-------------------------------------------------------------------+ + * | visbin | + * | +----------+ +------------+ +----------+ +-------+ | + * | | visqueue | | audioconv | | audiores | | vis | | + * | +-sink src-sink + samp src-sink src-sink src-+ | + * | | +----------+ +------------+ +----------+ +-------+ | | + * sink-+ +-src + * +-------------------------------------------------------------------+ + * + */ +static GstPlayVisChain * +gen_vis_chain (GstPlaySink * playsink) +{ + GstPlayVisChain *chain; + GstBin *bin; + gboolean res; + GstPad *pad; + GstElement *elem; + + chain = g_new0 (GstPlayVisChain, 1); + chain->chain.playsink = playsink; + + GST_DEBUG_OBJECT (playsink, "making vis chain %p", chain); + + chain->chain.bin = gst_bin_new ("visbin"); + bin = GST_BIN_CAST (chain->chain.bin); + gst_object_ref_sink (bin); + + /* we're queuing raw audio here, we can remove this queue when we can disable + * async behaviour in the video sink. */ + chain->queue = gst_element_factory_make ("queue", "visqueue"); + if (chain->queue == NULL) + goto no_queue; + g_object_set (chain->queue, "silent", TRUE, NULL); + gst_bin_add (bin, chain->queue); + + chain->conv = gst_element_factory_make ("audioconvert", "aconv"); + if (chain->conv == NULL) + goto no_audioconvert; + gst_bin_add (bin, chain->conv); + + chain->resample = gst_element_factory_make ("audioresample", "aresample"); + if (chain->resample == NULL) + goto no_audioresample; + gst_bin_add (bin, chain->resample); + + /* this pad will be used for blocking the dataflow and switching the vis + * plugin */ + chain->blockpad = gst_element_get_static_pad (chain->resample, "src"); + + if (playsink->visualisation) { + GST_DEBUG_OBJECT (playsink, "trying configure vis"); + chain->vis = try_element (playsink, playsink->visualisation, FALSE); + } + if (chain->vis == NULL) { + GST_DEBUG_OBJECT (playsink, "trying goom"); + elem = gst_element_factory_make ("goom", "vis"); + chain->vis = try_element (playsink, elem, TRUE); + } + if (chain->vis == NULL) + goto no_goom; + + gst_bin_add (bin, chain->vis); + + res = gst_element_link_pads_full (chain->queue, "src", chain->conv, "sink", + GST_PAD_LINK_CHECK_NOTHING); + res &= + gst_element_link_pads_full (chain->conv, "src", chain->resample, "sink", + GST_PAD_LINK_CHECK_NOTHING); + res &= + gst_element_link_pads_full (chain->resample, "src", chain->vis, "sink", + GST_PAD_LINK_CHECK_NOTHING); + if (!res) + goto link_failed; + + chain->vissinkpad = gst_element_get_static_pad (chain->vis, "sink"); + chain->vissrcpad = gst_element_get_static_pad (chain->vis, "src"); + + pad = gst_element_get_static_pad (chain->queue, "sink"); + chain->sinkpad = gst_ghost_pad_new ("sink", pad); + gst_object_unref (pad); + gst_element_add_pad (chain->chain.bin, chain->sinkpad); + + chain->srcpad = gst_ghost_pad_new ("src", chain->vissrcpad); + gst_element_add_pad (chain->chain.bin, chain->srcpad); + + return chain; + + /* ERRORS */ +no_queue: + { + post_missing_element_message (playsink, "queue"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "queue"), (NULL)); + free_chain ((GstPlayChain *) chain); + return NULL; + } +no_audioconvert: + { + post_missing_element_message (playsink, "audioconvert"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioconvert"), ("possibly a liboil version mismatch?")); + free_chain ((GstPlayChain *) chain); + return NULL; + } +no_audioresample: + { + post_missing_element_message (playsink, "audioresample"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "audioresample"), (NULL)); + free_chain ((GstPlayChain *) chain); + return NULL; + } +no_goom: + { + post_missing_element_message (playsink, "goom"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "goom"), (NULL)); + free_chain ((GstPlayChain *) chain); + return NULL; + } +link_failed: + { + GST_ELEMENT_ERROR (playsink, CORE, PAD, + (NULL), ("Failed to configure the visualisation element.")); + /* element made it to READY */ + gst_element_set_state (chain->vis, GST_STATE_NULL); + free_chain ((GstPlayChain *) chain); + return NULL; + } +} + +/* this function is called when all the request pads are requested and when we + * have to construct the final pipeline. Based on the flags we construct the + * final output pipelines. + */ +gboolean +gst_play_sink_reconfigure (GstPlaySink * playsink) +{ + GstPlayFlags flags; + gboolean need_audio, need_video, need_deinterlace, need_vis, need_text; + + GST_DEBUG_OBJECT (playsink, "reconfiguring"); + + /* assume we need nothing */ + need_audio = need_video = need_deinterlace = need_vis = need_text = FALSE; + + GST_PLAY_SINK_LOCK (playsink); + GST_OBJECT_LOCK (playsink); + /* get flags, there are protected with the object lock */ + flags = playsink->flags; + GST_OBJECT_UNLOCK (playsink); + + /* figure out which components we need */ + if (flags & GST_PLAY_FLAG_TEXT && playsink->text_pad) { + /* we have subtitles and we are requested to show it */ + need_text = TRUE; + } + + if (((flags & GST_PLAY_FLAG_VIDEO) + || (flags & GST_PLAY_FLAG_NATIVE_VIDEO)) && playsink->video_pad) { + /* we have video and we are requested to show it */ + need_video = TRUE; + + /* we only deinterlace if native video is not requested and + * we have raw video */ + if ((flags & GST_PLAY_FLAG_DEINTERLACE) + && !(flags & GST_PLAY_FLAG_NATIVE_VIDEO) && playsink->video_pad_raw) + need_deinterlace = TRUE; + } + + if (playsink->audio_pad) { + if ((flags & GST_PLAY_FLAG_AUDIO) || (flags & GST_PLAY_FLAG_NATIVE_AUDIO)) { + need_audio = TRUE; + } + if (playsink->audio_pad_raw) { + /* only can do vis with raw uncompressed audio */ + if (flags & GST_PLAY_FLAG_VIS && !need_video) { + /* also add video when we add visualisation */ + need_video = TRUE; + need_vis = TRUE; + } + } + } + + /* we have a text_pad and we need text rendering, in this case we need a + * video_pad to combine the video with the text or visualizations */ + if (need_text && !need_video) { + if (playsink->video_pad) { + need_video = TRUE; + } else if (need_audio) { + GST_ELEMENT_WARNING (playsink, STREAM, FORMAT, + (_("Can't play a text file without video or visualizations.")), + ("Have text pad but no video pad or visualizations")); + need_text = FALSE; + } else { + GST_ELEMENT_ERROR (playsink, STREAM, FORMAT, + (_("Can't play a text file without video or visualizations.")), + ("Have text pad but no video pad or visualizations")); + GST_PLAY_SINK_UNLOCK (playsink); + return FALSE; + } + } + + GST_DEBUG_OBJECT (playsink, "audio:%d, video:%d, vis:%d, text:%d", need_audio, + need_video, need_vis, need_text); + + /* set up video pipeline */ + if (need_video) { + gboolean raw, async; + + /* we need a raw sink when we do vis or when we have a raw pad */ + raw = need_vis ? TRUE : playsink->video_pad_raw; + /* we try to set the sink async=FALSE when we need vis, this way we can + * avoid a queue in the audio chain. */ + async = !need_vis; + + GST_DEBUG_OBJECT (playsink, "adding video, raw %d", + playsink->video_pad_raw); + + if (playsink->videochain) { + /* try to reactivate the chain */ + if (!setup_video_chain (playsink, raw, async)) { + if (playsink->video_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->video_sinkpad_stream_synchronizer); + gst_object_unref (playsink->video_sinkpad_stream_synchronizer); + playsink->video_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->video_srcpad_stream_synchronizer); + playsink->video_srcpad_stream_synchronizer = NULL; + } + + add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + + /* Remove the sink from the bin to keep its state + * and unparent it to allow reuse */ + if (playsink->videochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->videochain->chain.bin), + playsink->videochain->sink); + + activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + free_chain ((GstPlayChain *) playsink->videochain); + playsink->videochain = NULL; + } + } + + if (!playsink->videochain) + playsink->videochain = gen_video_chain (playsink, raw, async); + if (!playsink->videochain) + goto no_chain; + + if (!playsink->video_sinkpad_stream_synchronizer) { + GstIterator *it; + + playsink->video_sinkpad_stream_synchronizer = + gst_element_get_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), "sink_%d"); + it = gst_pad_iterate_internal_links + (playsink->video_sinkpad_stream_synchronizer); + g_assert (it); + gst_iterator_next (it, + (gpointer *) & playsink->video_srcpad_stream_synchronizer); + g_assert (playsink->video_srcpad_stream_synchronizer); + gst_iterator_free (it); + } + + if (playsink->video_pad) + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), + playsink->video_sinkpad_stream_synchronizer); + + if (need_deinterlace) { + if (!playsink->videodeinterlacechain) + playsink->videodeinterlacechain = + gen_video_deinterlace_chain (playsink); + if (!playsink->videodeinterlacechain) + goto no_chain; + + GST_DEBUG_OBJECT (playsink, "adding video deinterlace chain"); + + GST_DEBUG_OBJECT (playsink, "setting up deinterlacing chain"); + + add_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), TRUE); + activate_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), TRUE); + + gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + playsink->videodeinterlacechain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + } else { + if (playsink->videodeinterlacechain) { + add_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), + FALSE); + } + } + + GST_DEBUG_OBJECT (playsink, "adding video chain"); + add_chain (GST_PLAY_CHAIN (playsink->videochain), TRUE); + activate_chain (GST_PLAY_CHAIN (playsink->videochain), TRUE); + /* if we are not part of vis or subtitles, set the ghostpad target */ + if (!need_vis && !need_text && (!playsink->textchain + || !playsink->text_pad)) { + GST_DEBUG_OBJECT (playsink, "ghosting video sinkpad"); + if (need_deinterlace) + gst_pad_link_full (playsink->videodeinterlacechain->srcpad, + playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + else + gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + } + } else { + GST_DEBUG_OBJECT (playsink, "no video needed"); + if (playsink->videochain) { + GST_DEBUG_OBJECT (playsink, "removing video chain"); + if (playsink->vischain) { + GstPad *srcpad; + + GST_DEBUG_OBJECT (playsink, "unlinking vis chain"); + + /* also had visualisation, release the tee srcpad before we then + * unlink the video from it */ + if (playsink->audio_tee_vissrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_vissrc); + gst_object_unref (playsink->audio_tee_vissrc); + playsink->audio_tee_vissrc = NULL; + } + srcpad = + gst_element_get_static_pad (playsink->vischain->chain.bin, "src"); + gst_pad_unlink (srcpad, playsink->videochain->sinkpad); + } + + if (playsink->video_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->video_sinkpad_stream_synchronizer); + gst_object_unref (playsink->video_sinkpad_stream_synchronizer); + playsink->video_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->video_srcpad_stream_synchronizer); + playsink->video_srcpad_stream_synchronizer = NULL; + } + + add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + playsink->videochain->ts_offset = NULL; + } + + if (playsink->videodeinterlacechain) { + add_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), FALSE); + } + + if (playsink->video_pad) + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL); + } + + if (need_audio) { + gboolean raw; + + GST_DEBUG_OBJECT (playsink, "adding audio"); + + /* get a raw sink if we are asked for a raw pad */ + raw = playsink->audio_pad_raw; + + if (playsink->audiochain) { + /* try to reactivate the chain */ + if (!setup_audio_chain (playsink, raw)) { + GST_DEBUG_OBJECT (playsink, "removing current audio chain"); + if (playsink->audio_tee_asrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_asrc); + gst_object_unref (playsink->audio_tee_asrc); + playsink->audio_tee_asrc = NULL; + } + + if (playsink->audio_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->audio_sinkpad_stream_synchronizer); + gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); + playsink->audio_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->audio_srcpad_stream_synchronizer); + playsink->audio_srcpad_stream_synchronizer = NULL; + } + + add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + + /* Remove the sink from the bin to keep its state + * and unparent it to allow reuse */ + if (playsink->audiochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->audiochain->chain.bin), + playsink->audiochain->sink); + + activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + disconnect_chain (playsink->audiochain, playsink); + playsink->audiochain->volume = NULL; + playsink->audiochain->mute = NULL; + playsink->audiochain->ts_offset = NULL; + free_chain ((GstPlayChain *) playsink->audiochain); + playsink->audiochain = NULL; + playsink->volume_changed = playsink->mute_changed = FALSE; + } + } + + if (!playsink->audiochain) { + GST_DEBUG_OBJECT (playsink, "creating new audio chain"); + playsink->audiochain = gen_audio_chain (playsink, raw); + } + + if (!playsink->audio_sinkpad_stream_synchronizer) { + GstIterator *it; + + playsink->audio_sinkpad_stream_synchronizer = + gst_element_get_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), "sink_%d"); + it = gst_pad_iterate_internal_links + (playsink->audio_sinkpad_stream_synchronizer); + g_assert (it); + gst_iterator_next (it, + (gpointer *) & playsink->audio_srcpad_stream_synchronizer); + g_assert (playsink->audio_srcpad_stream_synchronizer); + gst_iterator_free (it); + } + + if (playsink->audiochain) { + GST_DEBUG_OBJECT (playsink, "adding audio chain"); + if (playsink->audio_tee_asrc == NULL) { + playsink->audio_tee_asrc = + gst_element_get_request_pad (playsink->audio_tee, "src%d"); + } + add_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE); + activate_chain (GST_PLAY_CHAIN (playsink->audiochain), TRUE); + gst_pad_link_full (playsink->audio_tee_asrc, + playsink->audio_sinkpad_stream_synchronizer, + GST_PAD_LINK_CHECK_NOTHING); + gst_pad_link_full (playsink->audio_srcpad_stream_synchronizer, + playsink->audiochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + } + } else { + GST_DEBUG_OBJECT (playsink, "no audio needed"); + /* we have no audio or we are requested to not play audio */ + if (playsink->audiochain) { + GST_DEBUG_OBJECT (playsink, "removing audio chain"); + /* release the audio pad */ + if (playsink->audio_tee_asrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_asrc); + gst_object_unref (playsink->audio_tee_asrc); + playsink->audio_tee_asrc = NULL; + } + + if (playsink->audio_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->audio_sinkpad_stream_synchronizer); + gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); + playsink->audio_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->audio_srcpad_stream_synchronizer); + playsink->audio_srcpad_stream_synchronizer = NULL; + } + + if (playsink->audiochain->sink_volume) { + disconnect_chain (playsink->audiochain, playsink); + playsink->audiochain->volume = NULL; + playsink->audiochain->mute = NULL; + playsink->audiochain->ts_offset = NULL; + } + add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + } + } + + if (need_vis) { + GstPad *srcpad; + + if (!playsink->vischain) + playsink->vischain = gen_vis_chain (playsink); + + GST_DEBUG_OBJECT (playsink, "adding visualisation"); + + if (playsink->vischain) { + GST_DEBUG_OBJECT (playsink, "setting up vis chain"); + srcpad = + gst_element_get_static_pad (playsink->vischain->chain.bin, "src"); + add_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE); + activate_chain (GST_PLAY_CHAIN (playsink->vischain), TRUE); + if (playsink->audio_tee_vissrc == NULL) { + playsink->audio_tee_vissrc = + gst_element_get_request_pad (playsink->audio_tee, "src%d"); + } + gst_pad_link_full (playsink->audio_tee_vissrc, + playsink->vischain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + gst_pad_link_full (srcpad, playsink->video_sinkpad_stream_synchronizer, + GST_PAD_LINK_CHECK_NOTHING); + gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + gst_object_unref (srcpad); + } + } else { + GST_DEBUG_OBJECT (playsink, "no vis needed"); + if (playsink->vischain) { + if (playsink->audio_tee_vissrc) { + gst_element_release_request_pad (playsink->audio_tee, + playsink->audio_tee_vissrc); + gst_object_unref (playsink->audio_tee_vissrc); + playsink->audio_tee_vissrc = NULL; + } + GST_DEBUG_OBJECT (playsink, "removing vis chain"); + add_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE); + } + } + + if (need_text) { + GST_DEBUG_OBJECT (playsink, "adding text"); + if (!playsink->textchain) { + GST_DEBUG_OBJECT (playsink, "creating text chain"); + playsink->textchain = gen_text_chain (playsink); + } + if (playsink->textchain) { + GstIterator *it; + + GST_DEBUG_OBJECT (playsink, "adding text chain"); + if (playsink->textchain->overlay) + g_object_set (G_OBJECT (playsink->textchain->overlay), "silent", FALSE, + NULL); + add_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE); + + if (!playsink->text_sinkpad_stream_synchronizer) { + playsink->text_sinkpad_stream_synchronizer = + gst_element_get_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), "sink_%d"); + it = gst_pad_iterate_internal_links + (playsink->text_sinkpad_stream_synchronizer); + g_assert (it); + gst_iterator_next (it, + (gpointer *) & playsink->text_srcpad_stream_synchronizer); + g_assert (playsink->text_srcpad_stream_synchronizer); + gst_iterator_free (it); + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->text_pad), + playsink->text_sinkpad_stream_synchronizer); + gst_pad_link_full (playsink->text_srcpad_stream_synchronizer, + playsink->textchain->textsinkpad, GST_PAD_LINK_CHECK_NOTHING); + } + + if (need_vis) { + GstPad *srcpad; + + srcpad = + gst_element_get_static_pad (playsink->vischain->chain.bin, "src"); + gst_pad_unlink (srcpad, playsink->videochain->sinkpad); + gst_pad_link_full (srcpad, playsink->textchain->videosinkpad, + GST_PAD_LINK_CHECK_NOTHING); + gst_object_unref (srcpad); + } else { + if (need_deinterlace) + gst_pad_link_full (playsink->videodeinterlacechain->srcpad, + playsink->textchain->videosinkpad, GST_PAD_LINK_CHECK_NOTHING); + else + gst_pad_link_full (playsink->video_srcpad_stream_synchronizer, + playsink->textchain->videosinkpad, GST_PAD_LINK_CHECK_NOTHING); + } + gst_pad_link_full (playsink->textchain->srcpad, + playsink->videochain->sinkpad, GST_PAD_LINK_CHECK_NOTHING); + + activate_chain (GST_PLAY_CHAIN (playsink->textchain), TRUE); + } + } else { + GST_DEBUG_OBJECT (playsink, "no text needed"); + /* we have no subtitles/text or we are requested to not show them */ + + if (playsink->text_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->text_sinkpad_stream_synchronizer); + gst_object_unref (playsink->text_sinkpad_stream_synchronizer); + playsink->text_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->text_srcpad_stream_synchronizer); + playsink->text_srcpad_stream_synchronizer = NULL; + } + + if (playsink->textchain) { + if (playsink->text_pad == NULL) { + /* no text pad, remove the chain entirely */ + GST_DEBUG_OBJECT (playsink, "removing text chain"); + add_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE); + activate_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE); + } else { + /* we have a chain and a textpad, turn the subtitles off */ + GST_DEBUG_OBJECT (playsink, "turning off the text"); + if (playsink->textchain->overlay) + g_object_set (G_OBJECT (playsink->textchain->overlay), "silent", TRUE, + NULL); + } + } + if (!need_video && playsink->video_pad) { + if (playsink->video_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->video_sinkpad_stream_synchronizer); + gst_object_unref (playsink->video_sinkpad_stream_synchronizer); + playsink->video_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->video_srcpad_stream_synchronizer); + playsink->video_srcpad_stream_synchronizer = NULL; + } + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->video_pad), NULL); + } + + if (playsink->text_pad && !playsink->textchain) + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (playsink->text_pad), NULL); + } + update_av_offset (playsink); + do_async_done (playsink); + GST_PLAY_SINK_UNLOCK (playsink); + + return TRUE; + + /* ERRORS */ +no_chain: + { + /* gen_ chain already posted error */ + GST_DEBUG_OBJECT (playsink, "failed to setup chain"); + GST_PLAY_SINK_UNLOCK (playsink); + return FALSE; + } +} + +/** + * gst_play_sink_set_flags: + * @playsink: a #GstPlaySink + * @flags: #GstPlayFlags + * + * Configure @flags on @playsink. The flags control the behaviour of @playsink + * when constructing the sink pipelins. + * + * Returns: TRUE if the flags could be configured. + */ +gboolean +gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags) +{ + g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), FALSE); + + GST_OBJECT_LOCK (playsink); + playsink->flags = flags; + GST_OBJECT_UNLOCK (playsink); + + return TRUE; +} + +/** + * gst_play_sink_get_flags: + * @playsink: a #GstPlaySink + * + * Get the flags of @playsink. That flags control the behaviour of the sink when + * it constructs the sink pipelines. + * + * Returns: the currently configured #GstPlayFlags. + */ +GstPlayFlags +gst_play_sink_get_flags (GstPlaySink * playsink) +{ + GstPlayFlags res; + + g_return_val_if_fail (GST_IS_PLAY_SINK (playsink), 0); + + GST_OBJECT_LOCK (playsink); + res = playsink->flags; + GST_OBJECT_UNLOCK (playsink); + + return res; +} + +void +gst_play_sink_set_font_desc (GstPlaySink * playsink, const gchar * desc) +{ + GstPlayTextChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayTextChain *) playsink->textchain; + g_free (playsink->font_desc); + playsink->font_desc = g_strdup (desc); + if (chain && chain->overlay) { + g_object_set (chain->overlay, "font-desc", desc, NULL); + } + GST_PLAY_SINK_UNLOCK (playsink); +} + +gchar * +gst_play_sink_get_font_desc (GstPlaySink * playsink) +{ + gchar *result = NULL; + GstPlayTextChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayTextChain *) playsink->textchain; + if (chain && chain->overlay) { + g_object_get (chain->overlay, "font-desc", &result, NULL); + playsink->font_desc = g_strdup (result); + } else { + result = g_strdup (playsink->font_desc); + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +void +gst_play_sink_set_subtitle_encoding (GstPlaySink * playsink, + const gchar * encoding) +{ + GstPlayTextChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayTextChain *) playsink->textchain; + g_free (playsink->subtitle_encoding); + playsink->subtitle_encoding = g_strdup (encoding); + if (chain && chain->overlay) { + g_object_set (chain->overlay, "subtitle-encoding", encoding, NULL); + } + GST_PLAY_SINK_UNLOCK (playsink); +} + +gchar * +gst_play_sink_get_subtitle_encoding (GstPlaySink * playsink) +{ + gchar *result = NULL; + GstPlayTextChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + chain = (GstPlayTextChain *) playsink->textchain; + if (chain && chain->overlay) { + g_object_get (chain->overlay, "subtitle-encoding", &result, NULL); + playsink->subtitle_encoding = g_strdup (result); + } else { + result = g_strdup (playsink->subtitle_encoding); + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +static void +update_av_offset (GstPlaySink * playsink) +{ + gint64 av_offset; + GstPlayAudioChain *achain; + GstPlayVideoChain *vchain; + + av_offset = playsink->av_offset; + achain = (GstPlayAudioChain *) playsink->audiochain; + vchain = (GstPlayVideoChain *) playsink->videochain; + + if (achain && vchain && achain->ts_offset && vchain->ts_offset) { + g_object_set (achain->ts_offset, "ts-offset", MAX (0, -av_offset), NULL); + g_object_set (vchain->ts_offset, "ts-offset", MAX (0, av_offset), NULL); + } else { + GST_LOG_OBJECT (playsink, "no ts_offset elements"); + } +} + +void +gst_play_sink_set_av_offset (GstPlaySink * playsink, gint64 av_offset) +{ + GST_PLAY_SINK_LOCK (playsink); + playsink->av_offset = av_offset; + update_av_offset (playsink); + GST_PLAY_SINK_UNLOCK (playsink); +} + +gint64 +gst_play_sink_get_av_offset (GstPlaySink * playsink) +{ + gint64 result; + + GST_PLAY_SINK_LOCK (playsink); + result = playsink->av_offset; + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +/** + * gst_play_sink_get_last_frame: + * @playsink: a #GstPlaySink + * + * Get the last displayed frame from @playsink. This frame is in the native + * format of the sink element, the caps on the result buffer contain the format + * of the frame data. + * + * Returns: a #GstBuffer with the frame data or %NULL when no video frame is + * available. + */ +GstBuffer * +gst_play_sink_get_last_frame (GstPlaySink * playsink) +{ + GstBuffer *result = NULL; + GstPlayVideoChain *chain; + + GST_PLAY_SINK_LOCK (playsink); + GST_DEBUG_OBJECT (playsink, "taking last frame"); + /* get the video chain if we can */ + if ((chain = (GstPlayVideoChain *) playsink->videochain)) { + GST_DEBUG_OBJECT (playsink, "found video chain"); + /* see if the chain is active */ + if (chain->chain.activated && chain->sink) { + GstElement *elem; + + GST_DEBUG_OBJECT (playsink, "video chain active and has a sink"); + + /* find and get the last-buffer property now */ + if ((elem = + gst_play_sink_find_property (playsink, chain->sink, + "last-buffer", GST_TYPE_BUFFER))) { + GST_DEBUG_OBJECT (playsink, "getting last-buffer property"); + g_object_get (elem, "last-buffer", &result, NULL); + gst_object_unref (elem); + } + } + } + GST_PLAY_SINK_UNLOCK (playsink); + + return result; +} + +/** + * gst_play_sink_convert_frame: + * @playsink: a #GstPlaySink + * @caps: a #GstCaps + * + * Get the last displayed frame from @playsink. If caps is %NULL, the video will + * be in the native format of the sink element and the caps on the buffer + * describe the format of the frame. If @caps is not %NULL, the video + * frame will be converted to the format of the caps. + * + * Returns: a #GstBuffer with the frame data or %NULL when no video frame is + * available or when the conversion failed. + */ +GstBuffer * +gst_play_sink_convert_frame (GstPlaySink * playsink, GstCaps * caps) +{ + GstBuffer *result; + + result = gst_play_sink_get_last_frame (playsink); + if (result != NULL && caps != NULL) { + GstBuffer *temp; + GError *err = NULL; + + temp = gst_video_convert_frame (result, caps, 25 * GST_SECOND, &err); + gst_buffer_unref (result); + if (temp == NULL && err) { + /* I'm really uncertain whether we should make playsink post an error + * on the bus or not. It's not like it's a critical issue regarding + * playsink behaviour. */ + GST_ERROR ("Error converting frame: %s", err->message); + } + result = temp; + } + return result; +} + +/** + * gst_play_sink_request_pad + * @playsink: a #GstPlaySink + * @type: a #GstPlaySinkType + * + * Create or return a pad of @type. + * + * Returns: a #GstPad of @type or %NULL when the pad could not be created. + */ +GstPad * +gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) +{ + GstPad *res = NULL; + gboolean created = FALSE; + gboolean raw = FALSE; + gboolean activate = TRUE; + const gchar *pad_name = NULL; + + GST_DEBUG_OBJECT (playsink, "request pad type %d", type); + + GST_PLAY_SINK_LOCK (playsink); + switch (type) { + case GST_PLAY_SINK_TYPE_AUDIO_RAW: + pad_name = "audio_raw_sink"; + raw = TRUE; + case GST_PLAY_SINK_TYPE_AUDIO: + if (pad_name == NULL) + pad_name = "audio_sink"; + if (!playsink->audio_tee) { + GST_LOG_OBJECT (playsink, "creating tee"); + /* create tee when needed. This element will feed the audio sink chain + * and the vis chain. */ + playsink->audio_tee = gst_element_factory_make ("tee", "audiotee"); + if (playsink->audio_tee == NULL) { + post_missing_element_message (playsink, "tee"); + GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "tee"), (NULL)); + res = NULL; + break; + } else { + playsink->audio_tee_sink = + gst_element_get_static_pad (playsink->audio_tee, "sink"); + gst_bin_add (GST_BIN_CAST (playsink), playsink->audio_tee); + gst_element_set_state (playsink->audio_tee, GST_STATE_PAUSED); + } + } else { + gst_element_set_state (playsink->audio_tee, GST_STATE_PAUSED); + } + if (!playsink->audio_pad) { + GST_LOG_OBJECT (playsink, "ghosting tee sinkpad"); + playsink->audio_pad = + gst_ghost_pad_new (pad_name, playsink->audio_tee_sink); + created = TRUE; + } + playsink->audio_pad_raw = raw; + res = playsink->audio_pad; + break; + case GST_PLAY_SINK_TYPE_VIDEO_RAW: + pad_name = "video_raw_sink"; + raw = TRUE; + case GST_PLAY_SINK_TYPE_VIDEO: + if (pad_name == NULL) + pad_name = "video_sink"; + if (!playsink->video_pad) { + GST_LOG_OBJECT (playsink, "ghosting videosink"); + playsink->video_pad = + gst_ghost_pad_new_no_target (pad_name, GST_PAD_SINK); + created = TRUE; + } + playsink->video_pad_raw = raw; + res = playsink->video_pad; + break; + case GST_PLAY_SINK_TYPE_TEXT: + GST_LOG_OBJECT (playsink, "ghosting text"); + if (!playsink->text_pad) { + playsink->text_pad = + gst_ghost_pad_new_no_target ("text_sink", GST_PAD_SINK); + created = TRUE; + } + res = playsink->text_pad; + break; + case GST_PLAY_SINK_TYPE_FLUSHING: + { + gchar *padname; + + /* we need a unique padname for the flushing pad. */ + padname = g_strdup_printf ("flushing_%d", playsink->count); + res = gst_ghost_pad_new_no_target (padname, GST_PAD_SINK); + g_free (padname); + playsink->count++; + activate = FALSE; + created = TRUE; + break; + } + default: + res = NULL; + break; + } + GST_PLAY_SINK_UNLOCK (playsink); + + if (created && res) { + /* we have to add the pad when it's active or we get an error when the + * element is 'running' */ + gst_pad_set_active (res, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (playsink), res); + if (!activate) + gst_pad_set_active (res, activate); + } + + return res; +} + +static GstPad * +gst_play_sink_request_new_pad (GstElement * element, GstPadTemplate * templ, + const gchar * name) +{ + GstPlaySink *psink; + GstPad *pad; + GstPlaySinkType type; + const gchar *tplname; + + g_return_val_if_fail (templ != NULL, NULL); + + GST_DEBUG_OBJECT (element, "name:%s", name); + + psink = GST_PLAY_SINK (element); + tplname = GST_PAD_TEMPLATE_NAME_TEMPLATE (templ); + + /* Figure out the GstPlaySinkType based on the template */ + if (!strcmp (tplname, "audio_sink")) + type = GST_PLAY_SINK_TYPE_AUDIO; + else if (!strcmp (tplname, "audio_raw_sink")) + type = GST_PLAY_SINK_TYPE_AUDIO_RAW; + else if (!strcmp (tplname, "video_sink")) + type = GST_PLAY_SINK_TYPE_VIDEO; + else if (!strcmp (tplname, "video_raw_sink")) + type = GST_PLAY_SINK_TYPE_VIDEO_RAW; + else if (!strcmp (tplname, "text_sink")) + type = GST_PLAY_SINK_TYPE_TEXT; + else + goto unknown_template; + + pad = gst_play_sink_request_pad (psink, type); + return pad; + +unknown_template: + GST_WARNING_OBJECT (element, "Unknown pad template"); + return NULL; +} + +void +gst_play_sink_release_pad (GstPlaySink * playsink, GstPad * pad) +{ + GstPad **res = NULL; + gboolean untarget = TRUE; + + GST_DEBUG_OBJECT (playsink, "release pad %" GST_PTR_FORMAT, pad); + + GST_PLAY_SINK_LOCK (playsink); + if (pad == playsink->video_pad) { + res = &playsink->video_pad; + } else if (pad == playsink->audio_pad) { + res = &playsink->audio_pad; + } else if (pad == playsink->text_pad) { + res = &playsink->text_pad; + } else { + /* try to release the given pad anyway, these could be the FLUSHING pads. */ + res = &pad; + untarget = FALSE; + } + GST_PLAY_SINK_UNLOCK (playsink); + + if (*res) { + GST_DEBUG_OBJECT (playsink, "deactivate pad %" GST_PTR_FORMAT, *res); + gst_pad_set_active (*res, FALSE); + if (untarget) { + GST_DEBUG_OBJECT (playsink, "untargeting pad %" GST_PTR_FORMAT, *res); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (*res), NULL); + } + GST_DEBUG_OBJECT (playsink, "remove pad %" GST_PTR_FORMAT, *res); + gst_element_remove_pad (GST_ELEMENT_CAST (playsink), *res); + *res = NULL; + } +} + +static void +gst_play_sink_release_request_pad (GstElement * element, GstPad * pad) +{ + GstPlaySink *psink = GST_PLAY_SINK (element); + + gst_play_sink_release_pad (psink, pad); +} + +static void +gst_play_sink_handle_message (GstBin * bin, GstMessage * message) +{ + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK_CAST (bin); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_STEP_DONE: + { + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush, intermediate, eos; + guint64 duration; + + GST_INFO_OBJECT (playsink, "Handling step-done message"); + gst_message_parse_step_done (message, &format, &amount, &rate, &flush, + &intermediate, &duration, &eos); + + if (format == GST_FORMAT_BUFFERS) { + /* for the buffer format, we align the other streams */ + if (playsink->audiochain) { + GstEvent *event; + + event = + gst_event_new_step (GST_FORMAT_TIME, duration, rate, flush, + intermediate); + + if (!gst_element_send_event (playsink->audiochain->chain.bin, event)) { + GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink"); + } + } + } + GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message); + break; + } + default: + GST_BIN_CLASS (gst_play_sink_parent_class)->handle_message (bin, message); + break; + } +} + +/* Send an event to our sinks until one of them works; don't then send to the + * remaining sinks (unlike GstBin) + * Special case: If a text sink is set we need to send the event + * to them in case it's source is different from the a/v stream's source. + */ +static gboolean +gst_play_sink_send_event_to_sink (GstPlaySink * playsink, GstEvent * event) +{ + gboolean res = TRUE; + + if (playsink->textchain && playsink->textchain->sink) { + gst_event_ref (event); + if ((res = gst_element_send_event (playsink->textchain->chain.bin, event))) { + GST_DEBUG_OBJECT (playsink, "Sent event succesfully to text sink"); + } else { + GST_DEBUG_OBJECT (playsink, "Event failed when sent to text sink"); + } + } + + if (playsink->videochain) { + gst_event_ref (event); + if ((res = gst_element_send_event (playsink->videochain->chain.bin, event))) { + GST_DEBUG_OBJECT (playsink, "Sent event succesfully to video sink"); + goto done; + } + GST_DEBUG_OBJECT (playsink, "Event failed when sent to video sink"); + } + if (playsink->audiochain) { + gst_event_ref (event); + if ((res = gst_element_send_event (playsink->audiochain->chain.bin, event))) { + GST_DEBUG_OBJECT (playsink, "Sent event succesfully to audio sink"); + goto done; + } + GST_DEBUG_OBJECT (playsink, "Event failed when sent to audio sink"); + } + +done: + gst_event_unref (event); + return res; +} + +/* We only want to send the event to a single sink (overriding GstBin's + * behaviour), but we want to keep GstPipeline's behaviour - wrapping seek + * events appropriately. So, this is a messy duplication of code. */ +static gboolean +gst_play_sink_send_event (GstElement * element, GstEvent * event) +{ + gboolean res = FALSE; + GstEventType event_type = GST_EVENT_TYPE (event); + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK_CAST (element); + + switch (event_type) { + case GST_EVENT_SEEK: + GST_DEBUG_OBJECT (element, "Sending event to a sink"); + res = gst_play_sink_send_event_to_sink (playsink, event); + break; + case GST_EVENT_STEP: + { + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush, intermediate; + + gst_event_parse_step (event, &format, &amount, &rate, &flush, + &intermediate); + + if (format == GST_FORMAT_BUFFERS) { + /* for buffers, we will try to step video frames, for other formats we + * send the step to all sinks */ + res = gst_play_sink_send_event_to_sink (playsink, event); + } else { + res = + GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element, + event); + } + break; + } + default: + res = + GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element, + event); + break; + } + return res; +} + +static GstStateChangeReturn +gst_play_sink_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstStateChangeReturn bret; + + GstPlaySink *playsink; + + playsink = GST_PLAY_SINK (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + playsink->need_async_start = TRUE; + /* we want to go async to PAUSED until we managed to configure and add the + * sinks */ + do_async_start (playsink); + ret = GST_STATE_CHANGE_ASYNC; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + case GST_STATE_CHANGE_READY_TO_NULL: + if (playsink->audiochain && playsink->audiochain->sink_volume) { + /* remove our links to the mute and volume elements when they were + * provided by a sink */ + disconnect_chain (playsink->audiochain, playsink); + playsink->audiochain->volume = NULL; + playsink->audiochain->mute = NULL; + playsink->audiochain->ts_offset = NULL; + } + ret = GST_STATE_CHANGE_SUCCESS; + break; + default: + /* all other state changes return SUCCESS by default, this value can be + * overridden by the result of the children */ + ret = GST_STATE_CHANGE_SUCCESS; + break; + } + + /* do the state change of the children */ + bret = + GST_ELEMENT_CLASS (gst_play_sink_parent_class)->change_state (element, + transition); + /* now look at the result of our children and adjust the return value */ + switch (bret) { + case GST_STATE_CHANGE_FAILURE: + /* failure, we stop */ + goto activate_failed; + case GST_STATE_CHANGE_NO_PREROLL: + /* some child returned NO_PREROLL. This is strange but we never know. We + * commit our async state change (if any) and return the NO_PREROLL */ + do_async_done (playsink); + ret = bret; + break; + case GST_STATE_CHANGE_ASYNC: + /* some child was async, return this */ + ret = bret; + break; + default: + /* return our previously configured return value */ + break; + } + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* FIXME Release audio device when we implement that */ + playsink->need_async_start = TRUE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY:{ + if (playsink->video_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->video_sinkpad_stream_synchronizer); + gst_object_unref (playsink->video_sinkpad_stream_synchronizer); + playsink->video_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->video_srcpad_stream_synchronizer); + playsink->video_srcpad_stream_synchronizer = NULL; + } + if (playsink->audio_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->audio_sinkpad_stream_synchronizer); + gst_object_unref (playsink->audio_sinkpad_stream_synchronizer); + playsink->audio_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->audio_srcpad_stream_synchronizer); + playsink->audio_srcpad_stream_synchronizer = NULL; + } + if (playsink->text_sinkpad_stream_synchronizer) { + gst_element_release_request_pad (GST_ELEMENT_CAST + (playsink->stream_synchronizer), + playsink->text_sinkpad_stream_synchronizer); + gst_object_unref (playsink->text_sinkpad_stream_synchronizer); + playsink->text_sinkpad_stream_synchronizer = NULL; + gst_object_unref (playsink->text_srcpad_stream_synchronizer); + playsink->text_srcpad_stream_synchronizer = NULL; + } + } + /* fall through */ + case GST_STATE_CHANGE_READY_TO_NULL: + /* remove sinks we added */ + if (playsink->videodeinterlacechain) { + activate_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), + FALSE); + add_chain (GST_PLAY_CHAIN (playsink->videodeinterlacechain), FALSE); + } + if (playsink->videochain) { + activate_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + add_chain (GST_PLAY_CHAIN (playsink->videochain), FALSE); + } + if (playsink->audiochain) { + activate_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + add_chain (GST_PLAY_CHAIN (playsink->audiochain), FALSE); + } + if (playsink->vischain) { + activate_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE); + add_chain (GST_PLAY_CHAIN (playsink->vischain), FALSE); + } + if (playsink->textchain) { + activate_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE); + add_chain (GST_PLAY_CHAIN (playsink->textchain), FALSE); + } + do_async_done (playsink); + /* when going to READY, keep elements around as long as possible, + * so they may be re-used faster next time/url around. + * when really going to NULL, clean up everything completely. */ + if (transition == GST_STATE_CHANGE_READY_TO_NULL) { + + /* Unparent the sinks to allow reuse */ + if (playsink->videochain && playsink->videochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->videochain->chain.bin), + playsink->videochain->sink); + if (playsink->audiochain && playsink->audiochain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->audiochain->chain.bin), + playsink->audiochain->sink); + if (playsink->textchain && playsink->textchain->sink) + gst_bin_remove (GST_BIN_CAST (playsink->textchain->chain.bin), + playsink->textchain->sink); + + if (playsink->audio_sink != NULL) + gst_element_set_state (playsink->audio_sink, GST_STATE_NULL); + if (playsink->video_sink != NULL) + gst_element_set_state (playsink->video_sink, GST_STATE_NULL); + if (playsink->visualisation != NULL) + gst_element_set_state (playsink->visualisation, GST_STATE_NULL); + if (playsink->text_sink != NULL) + gst_element_set_state (playsink->text_sink, GST_STATE_NULL); + + free_chain ((GstPlayChain *) playsink->videodeinterlacechain); + playsink->videodeinterlacechain = NULL; + free_chain ((GstPlayChain *) playsink->videochain); + playsink->videochain = NULL; + free_chain ((GstPlayChain *) playsink->audiochain); + playsink->audiochain = NULL; + free_chain ((GstPlayChain *) playsink->vischain); + playsink->vischain = NULL; + free_chain ((GstPlayChain *) playsink->textchain); + playsink->textchain = NULL; + } + break; + default: + break; + } + return ret; + + /* ERRORS */ +activate_failed: + { + GST_DEBUG_OBJECT (element, + "element failed to change states -- activation problem?"); + return GST_STATE_CHANGE_FAILURE; + } +} + +static void +gst_play_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec) +{ + GstPlaySink *playsink = GST_PLAY_SINK (object); + + switch (prop_id) { + case PROP_FLAGS: + gst_play_sink_set_flags (playsink, g_value_get_flags (value)); + break; + case PROP_VOLUME: + gst_play_sink_set_volume (playsink, g_value_get_double (value)); + break; + case PROP_MUTE: + gst_play_sink_set_mute (playsink, g_value_get_boolean (value)); + break; + case PROP_FONT_DESC: + gst_play_sink_set_font_desc (playsink, g_value_get_string (value)); + break; + case PROP_SUBTITLE_ENCODING: + gst_play_sink_set_subtitle_encoding (playsink, + g_value_get_string (value)); + break; + case PROP_VIS_PLUGIN: + gst_play_sink_set_vis_plugin (playsink, g_value_get_object (value)); + break; + case PROP_AV_OFFSET: + gst_play_sink_set_av_offset (playsink, g_value_get_int64 (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec); + break; + } +} + +static void +gst_play_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec) +{ + GstPlaySink *playsink = GST_PLAY_SINK (object); + + switch (prop_id) { + case PROP_FLAGS: + g_value_set_flags (value, gst_play_sink_get_flags (playsink)); + break; + case PROP_VOLUME: + g_value_set_double (value, gst_play_sink_get_volume (playsink)); + break; + case PROP_MUTE: + g_value_set_boolean (value, gst_play_sink_get_mute (playsink)); + break; + case PROP_FONT_DESC: + g_value_take_string (value, gst_play_sink_get_font_desc (playsink)); + break; + case PROP_SUBTITLE_ENCODING: + g_value_take_string (value, + gst_play_sink_get_subtitle_encoding (playsink)); + break; + case PROP_VIS_PLUGIN: + g_value_take_object (value, gst_play_sink_get_vis_plugin (playsink)); + break; + case PROP_FRAME: + gst_value_take_buffer (value, gst_play_sink_get_last_frame (playsink)); + break; + case PROP_AV_OFFSET: + g_value_set_int64 (value, gst_play_sink_get_av_offset (playsink)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, spec); + break; + } +} + + +gboolean +gst_play_sink_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_play_sink_debug, "playsink", 0, "play bin"); + + return gst_element_register (plugin, "playsink", GST_RANK_NONE, + GST_TYPE_PLAY_SINK); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.h b/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.h new file mode 100644 index 0000000..3ca96d3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstplaysink.h @@ -0,0 +1,113 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_PLAY_SINK_H__ +#define __GST_PLAY_SINK_H__ + +#include + +#include "gstplay-enum.h" + +G_BEGIN_DECLS + +#define GST_TYPE_PLAY_SINK \ + (gst_play_sink_get_type()) +#define GST_PLAY_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_PLAY_SINK, GstPlaySink)) +#define GST_PLAY_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_PLAY_SINK, GstPlaySinkClass)) +#define GST_IS_PLAY_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK)) +#define GST_IS_PLAY_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK)) +#define GST_PLAY_SINK_CAST(obj) \ + ((GstPlaySink*)(obj)) + +/** + * GstPlaySinkType: + * @GST_PLAY_SINK_TYPE_AUDIO: A non-raw audio pad + * @GST_PLAY_SINK_TYPE_AUDIO_RAW: a raw audio pad + * @GST_PLAY_SINK_TYPE_VIDEO: a non-raw video pad + * @GST_PLAY_SINK_TYPE_VIDEO_RAW: a raw video pad + * @GST_PLAY_SINK_TYPE_TEXT: a raw text pad + * @GST_PLAY_SINK_TYPE_LAST: the last type + * @GST_PLAY_SINK_TYPE_FLUSHING: a flushing pad, used when shutting down + * + * Types of pads that can be requested from the sinks. + */ +typedef enum { + GST_PLAY_SINK_TYPE_AUDIO = 0, + GST_PLAY_SINK_TYPE_AUDIO_RAW = 1, + GST_PLAY_SINK_TYPE_VIDEO = 2, + GST_PLAY_SINK_TYPE_VIDEO_RAW = 3, + GST_PLAY_SINK_TYPE_TEXT = 4, + GST_PLAY_SINK_TYPE_LAST = 5, + + /* this is a dummy pad */ + GST_PLAY_SINK_TYPE_FLUSHING = 6 +} GstPlaySinkType; + +typedef struct _GstPlaySink GstPlaySink; +typedef struct _GstPlaySinkClass GstPlaySinkClass; + +GType gst_play_sink_get_type (void); + +GstPad * gst_play_sink_request_pad (GstPlaySink *playsink, GstPlaySinkType type); +void gst_play_sink_release_pad (GstPlaySink *playsink, GstPad *pad); + +void gst_play_sink_set_sink (GstPlaySink * playsink, GstPlaySinkType type, GstElement * sink); +GstElement * gst_play_sink_get_sink (GstPlaySink * playsink, GstPlaySinkType type); + +void gst_play_sink_set_vis_plugin (GstPlaySink * playsink, GstElement * vis); +GstElement * gst_play_sink_get_vis_plugin (GstPlaySink * playsink); + +void gst_play_sink_set_volume (GstPlaySink *playsink, gdouble volume); +gdouble gst_play_sink_get_volume (GstPlaySink *playsink); + +void gst_play_sink_set_mute (GstPlaySink *playsink, gboolean mute); +gboolean gst_play_sink_get_mute (GstPlaySink *playsink); + +gboolean gst_play_sink_set_flags (GstPlaySink * playsink, GstPlayFlags flags); +GstPlayFlags gst_play_sink_get_flags (GstPlaySink * playsink); + +void gst_play_sink_set_font_desc (GstPlaySink *playsink, const gchar * desc); +gchar * gst_play_sink_get_font_desc (GstPlaySink *playsink); +void gst_play_sink_set_subtitle_encoding (GstPlaySink *playsink, const gchar * encoding); +gchar * gst_play_sink_get_subtitle_encoding (GstPlaySink *playsink); + +void gst_play_sink_set_av_offset (GstPlaySink *playsink, gint64 av_offset); +gint64 gst_play_sink_get_av_offset (GstPlaySink *playsink); + +GstBuffer * gst_play_sink_get_last_frame (GstPlaySink * playsink); +GstBuffer * gst_play_sink_convert_frame (GstPlaySink * playsink, GstCaps * caps); + +gboolean gst_play_sink_reconfigure (GstPlaySink * playsink); + +gboolean gst_play_sink_plugin_init (GstPlugin * plugin); + +void +gst_play_marshal_BUFFER__BOXED (GClosure * closure, + GValue * return_value G_GNUC_UNUSED, + guint n_param_values, + const GValue * param_values, + gpointer invocation_hint G_GNUC_UNUSED, gpointer marshal_data); + +G_END_DECLS + +#endif /* __GST_PLAY_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstrawcaps.h b/gst-plugins-base-subtitles0.10/gst/playback/gstrawcaps.h new file mode 100644 index 0000000..0297e33 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstrawcaps.h @@ -0,0 +1,42 @@ +/* GStreamer + * Copyright (C) <2009> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_RAW_CAPS_H__ +#define __GST_RAW_CAPS_H__ + +#include + +G_BEGIN_DECLS + +#define DEFAULT_RAW_CAPS \ + "video/x-raw-yuv; " \ + "video/x-raw-rgb; " \ + "video/x-raw-gray; " \ + "audio/x-raw-int; " \ + "audio/x-raw-float; " \ + "text/plain; " \ + "text/x-pango-markup; " \ + "video/x-dvd-subpicture; " \ + "subpicture/x-pgs" + +G_END_DECLS + +#endif /* __GST_RAW_CAPS__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.c b/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.c new file mode 100644 index 0000000..86ec58a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.c @@ -0,0 +1,402 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include "gststreaminfo.h" + +GST_DEBUG_CATEGORY_STATIC (gst_streaminfo_debug); +#define GST_CAT_DEFAULT gst_streaminfo_debug + +/* props */ +enum +{ + ARG_0, + ARG_PAD, + ARG_TYPE, + ARG_DECODER, + ARG_MUTE, + ARG_CAPS, + ARG_LANG_CODE, + ARG_CODEC +}; + +/* signals */ +enum +{ + SIGNAL_MUTED, + LAST_SIGNAL +}; + +static guint gst_stream_info_signals[LAST_SIGNAL] = { 0 }; + +#define GST_TYPE_STREAM_TYPE (gst_stream_type_get_type()) +static GType +gst_stream_type_get_type (void) +{ + static GType stream_type_type = 0; + static const GEnumValue stream_type[] = { + {GST_STREAM_TYPE_UNKNOWN, "Unknown stream", "unknown"}, + {GST_STREAM_TYPE_AUDIO, "Audio stream", "audio"}, + {GST_STREAM_TYPE_VIDEO, "Video stream", "video"}, + {GST_STREAM_TYPE_TEXT, "Text stream", "text"}, + {GST_STREAM_TYPE_SUBPICTURE, "Subpicture stream", "subpicture"}, + {GST_STREAM_TYPE_ELEMENT, + "Stream handled by element", "element"}, + {0, NULL, NULL}, + }; + + if (!stream_type_type) { + stream_type_type = g_enum_register_static ("GstStreamType", stream_type); + } + return stream_type_type; +} + +static void gst_stream_info_class_init (GstStreamInfoClass * klass); +static void gst_stream_info_init (GstStreamInfo * stream_info); +static void gst_stream_info_dispose (GObject * object); + +static void stream_info_change_state (GstElement * element, + gint old_state, gint new_state, gpointer data); + +static void gst_stream_info_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_stream_info_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); + +static GObjectClass *parent_class; + +//static guint gst_stream_info_signals[LAST_SIGNAL] = { 0 }; + +GType +gst_stream_info_get_type (void) +{ + static GType gst_stream_info_type = 0; + + if (!gst_stream_info_type) { + static const GTypeInfo gst_stream_info_info = { + sizeof (GstStreamInfoClass), + NULL, + NULL, + (GClassInitFunc) gst_stream_info_class_init, + NULL, + NULL, + sizeof (GstStreamInfo), + 0, + (GInstanceInitFunc) gst_stream_info_init, + NULL + }; + gst_stream_info_type = g_type_register_static (G_TYPE_OBJECT, + "GstStreamInfo", &gst_stream_info_info, 0); + } + + return gst_stream_info_type; +} + +static void +gst_stream_info_class_init (GstStreamInfoClass * klass) +{ + GObjectClass *gobject_klass; + + gobject_klass = (GObjectClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_klass->set_property = gst_stream_info_set_property; + gobject_klass->get_property = gst_stream_info_get_property; + + g_object_class_install_property (gobject_klass, ARG_PAD, + g_param_spec_object ("object", "object", + "Source Pad or object of the stream", GST_TYPE_OBJECT, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_TYPE, + g_param_spec_enum ("type", "Type", "Type of the stream", + GST_TYPE_STREAM_TYPE, GST_STREAM_TYPE_UNKNOWN, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_DECODER, + g_param_spec_string ("decoder", "Decoder", + "The decoder used to decode the stream", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_MUTE, + g_param_spec_boolean ("mute", "Mute", "Mute or unmute this stream", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_CAPS, + g_param_spec_boxed ("caps", "Capabilities", + "Capabilities (or type) of this stream", GST_TYPE_CAPS, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_LANG_CODE, + g_param_spec_string ("language-code", "Language code", + "Language code for this stream, conforming to ISO-639-1", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_klass, ARG_CODEC, + g_param_spec_string ("codec", "Codec", "Codec used to encode the stream", + NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gst_stream_info_signals[SIGNAL_MUTED] = + g_signal_new ("muted", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstStreamInfoClass, muted), NULL, NULL, + gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + gobject_klass->dispose = gst_stream_info_dispose; + + GST_DEBUG_CATEGORY_INIT (gst_streaminfo_debug, "streaminfo", 0, + "Playbin Stream Info"); +} + + +static void +gst_stream_info_init (GstStreamInfo * stream_info) +{ + stream_info->object = NULL; + stream_info->origin = NULL; + stream_info->type = GST_STREAM_TYPE_UNKNOWN; + stream_info->decoder = NULL; + stream_info->mute = FALSE; + stream_info->caps = NULL; +} + +static gboolean +cb_probe (GstPad * pad, GstEvent * e, gpointer user_data) +{ + GstStreamInfo *info = user_data; + + if (GST_EVENT_TYPE (e) == GST_EVENT_TAG) { + gchar *codec, *lang; + GstTagList *list; + + gst_event_parse_tag (e, &list); + + if (info->type != GST_STREAM_TYPE_AUDIO && + gst_tag_list_get_string (list, GST_TAG_VIDEO_CODEC, &codec)) { + g_free (info->codec); + info->codec = codec; + GST_LOG_OBJECT (pad, "codec = %s (video)", codec); + g_object_notify (G_OBJECT (info), "codec"); + } else if (info->type != GST_STREAM_TYPE_VIDEO && + gst_tag_list_get_string (list, GST_TAG_AUDIO_CODEC, &codec)) { + g_free (info->codec); + info->codec = codec; + GST_LOG_OBJECT (pad, "codec = %s (audio)", codec); + g_object_notify (G_OBJECT (info), "codec"); + } else if (gst_tag_list_get_string (list, GST_TAG_CODEC, &codec)) { + g_free (info->codec); + info->codec = codec; + GST_LOG_OBJECT (pad, "codec = %s (generic)", codec); + g_object_notify (G_OBJECT (info), "codec"); + } + if (gst_tag_list_get_string (list, GST_TAG_LANGUAGE_CODE, &lang)) { + g_free (info->langcode); + info->langcode = lang; + GST_LOG_OBJECT (pad, "language-code = %s", lang); + g_object_notify (G_OBJECT (info), "language-code"); + } + } + + return TRUE; +} + +GstStreamInfo * +gst_stream_info_new (GstObject * object, + GstStreamType type, const gchar * decoder, const GstCaps * caps) +{ + GstStreamInfo *info; + + info = g_object_new (GST_TYPE_STREAM_INFO, NULL); + + gst_object_ref (object); + if (GST_IS_PAD (object)) { + gst_pad_add_event_probe (GST_PAD_CAST (object), + G_CALLBACK (cb_probe), info); + } + info->object = object; + info->type = type; + info->decoder = g_strdup (decoder); + info->origin = object; + if (caps) { + info->caps = gst_caps_copy (caps); + } + + return info; +} + +static void +gst_stream_info_dispose (GObject * object) +{ + GstStreamInfo *stream_info; + + stream_info = GST_STREAM_INFO (object); + + if (stream_info->object) { + GstElement *parent; + + parent = gst_pad_get_parent_element ((GstPad *) + GST_PAD_CAST (stream_info->object)); + if (parent != NULL) { + g_signal_handlers_disconnect_by_func (parent, + (gpointer) stream_info_change_state, stream_info); + gst_object_unref (parent); + } + + gst_object_unref (stream_info->object); + stream_info->object = NULL; + } + stream_info->origin = NULL; + stream_info->type = GST_STREAM_TYPE_UNKNOWN; + g_free (stream_info->decoder); + stream_info->decoder = NULL; + g_free (stream_info->langcode); + stream_info->langcode = NULL; + g_free (stream_info->codec); + stream_info->codec = NULL; + if (stream_info->caps) { + gst_caps_unref (stream_info->caps); + stream_info->caps = NULL; + } + + if (G_OBJECT_CLASS (parent_class)->dispose) { + G_OBJECT_CLASS (parent_class)->dispose (object); + } +} + +static void +stream_info_change_state (GstElement * element, + gint old_state, gint new_state, gpointer data) +{ + GstStreamInfo *stream_info = data; + + if (new_state == GST_STATE_PLAYING) { + /* state change will annoy us */ + g_return_if_fail (stream_info->mute == TRUE); + GST_DEBUG_OBJECT (stream_info, "Re-muting pads after state-change"); + //gst_pad_set_active_recursive (GST_PAD (stream_info->object), FALSE); + g_warning ("FIXME"); + } +} + +gboolean +gst_stream_info_set_mute (GstStreamInfo * stream_info, gboolean mute) +{ + g_return_val_if_fail (GST_IS_STREAM_INFO (stream_info), FALSE); + + if (stream_info->type == GST_STREAM_TYPE_ELEMENT) { + g_warning ("cannot mute element stream"); + return FALSE; + } + + if (mute != stream_info->mute) { + /* nothing really happens here. it looks like gstplaybasebin installs a + * buffer probe hat drops buffers when muting. but the this removes it self + * after first call. + */ + + stream_info->mute = mute; +#if 0 + gst_pad_set_active ((GstPad *) GST_PAD_CAST (stream_info->object), !mute); +#endif +#if 0 + { + GstElement *element; + + element = gst_pad_get_parent_element ((GstPad *) + GST_PAD_CAST (stream_info->object)); + if (element) { + if (mute) { + g_signal_connect (element, "state-changed", + G_CALLBACK (stream_info_change_state), stream_info); + } else { + g_signal_handlers_disconnect_by_func (element, + G_CALLBACK (stream_info_change_state), stream_info); + } + gst_object_unref (element); + } + } +#endif + } + return TRUE; +} + +gboolean +gst_stream_info_is_mute (GstStreamInfo * stream_info) +{ + g_return_val_if_fail (GST_IS_STREAM_INFO (stream_info), TRUE); + + return stream_info->mute; +} + +static void +gst_stream_info_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamInfo *stream_info; + + g_return_if_fail (GST_IS_STREAM_INFO (object)); + + stream_info = GST_STREAM_INFO (object); + + switch (prop_id) { + case ARG_MUTE: + gst_stream_info_set_mute (stream_info, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stream_info_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstStreamInfo *stream_info; + + g_return_if_fail (GST_IS_STREAM_INFO (object)); + + stream_info = GST_STREAM_INFO (object); + + switch (prop_id) { + case ARG_PAD: + g_value_set_object (value, stream_info->object); + break; + case ARG_TYPE: + g_value_set_enum (value, stream_info->type); + break; + case ARG_DECODER: + g_value_set_string (value, stream_info->decoder); + break; + case ARG_MUTE: + g_value_set_boolean (value, stream_info->mute); + break; + case ARG_CAPS: + g_value_set_boxed (value, stream_info->caps); + break; + case ARG_LANG_CODE: + g_value_set_string (value, stream_info->langcode); + break; + case ARG_CODEC: + g_value_set_string (value, stream_info->codec); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.h b/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.h new file mode 100644 index 0000000..b4157ea --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreaminfo.h @@ -0,0 +1,86 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAMINFO_H__ +#define __GST_STREAMINFO_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_INFO (gst_stream_info_get_type()) +#define GST_STREAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_STREAM_INFO,GstStreamInfo)) +#define GST_STREAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_STREAM_INFO,GstStreamInfoClass)) +#define GST_IS_STREAM_INFO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_STREAM_INFO)) +#define GST_IS_STREAM_INFO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_STREAM_INFO)) + +typedef struct _GstStreamInfo GstStreamInfo; +typedef struct _GstStreamInfoClass GstStreamInfoClass; + +typedef enum { + GST_STREAM_TYPE_UNKNOWN = 0, + GST_STREAM_TYPE_AUDIO = 1, /* an audio stream */ + GST_STREAM_TYPE_VIDEO = 2, /* a video stream */ + GST_STREAM_TYPE_TEXT = 3, /* a subtitle/text stream */ + GST_STREAM_TYPE_SUBPICTURE = 4, /* a subtitle in picture-form */ + GST_STREAM_TYPE_ELEMENT = 5 /* stream handled by an element */ +} GstStreamType; + +struct _GstStreamInfo { + GObject parent; + + GstObject *object; /* pad/element providing/handling this stream */ + GstStreamType type; /* the type of the provided stream */ + gchar *decoder; /* string describing the decoder */ + gboolean mute; /* is the stream muted or not */ + GstObject *origin; /* the real object providing this stream, this can + be different from the object as the object can be + a queue pad, inserted for preroll. */ + GstCaps *caps; /* the caps of the stream */ + + /* this is tream information cached here because the streaminfo may be + * created before the app can know about it. */ + gchar *langcode, + *codec; +}; + +struct _GstStreamInfoClass { + GObjectClass parent_class; + + /* signals */ + void (*muted) (GstStreamInfo *info, gboolean mute); +}; + +GType gst_stream_info_get_type (void); + +GstStreamInfo* gst_stream_info_new (GstObject *object, + GstStreamType type, + const gchar *decoder, + const GstCaps *caps); + +gboolean gst_stream_info_set_mute (GstStreamInfo *stream_info, + gboolean mute); +gboolean gst_stream_info_is_mute (GstStreamInfo *stream_info); + + +G_END_DECLS + +#endif /* __GST_STREAMINFO_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.c b/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.c new file mode 100644 index 0000000..294eac4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.c @@ -0,0 +1,749 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2005 Jan Schmidt + * Copyright (C) 2007 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include "gststreamselector.h" + +GST_DEBUG_CATEGORY_STATIC (stream_selector_debug); +#define GST_CAT_DEFAULT stream_selector_debug + +static GstStaticPadTemplate gst_stream_selector_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_stream_selector_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_N_PADS, + PROP_ACTIVE_PAD, + PROP_LAST +}; + +static gboolean gst_stream_selector_is_active_sinkpad (GstStreamSelector * sel, + GstPad * pad); +static GstPad *gst_stream_selector_activate_sinkpad (GstStreamSelector * sel, + GstPad * pad); +static GstPad *gst_stream_selector_get_linked_pad (GstPad * pad, + gboolean strict); + +#define GST_TYPE_SELECTOR_PAD \ + (gst_selector_pad_get_type()) +#define GST_SELECTOR_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SELECTOR_PAD, GstSelectorPad)) +#define GST_SELECTOR_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SELECTOR_PAD, GstSelectorPadClass)) +#define GST_IS_SELECTOR_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SELECTOR_PAD)) +#define GST_IS_SELECTOR_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SELECTOR_PAD)) +#define GST_SELECTOR_PAD_CAST(obj) \ + ((GstSelectorPad *)(obj)) + +typedef struct _GstSelectorPad GstSelectorPad; +typedef struct _GstSelectorPadClass GstSelectorPadClass; + +struct _GstSelectorPad +{ + GstPad parent; + + gboolean active; + gboolean eos; + gboolean segment_pending; + GstSegment segment; + GstTagList *tags; +}; + +struct _GstSelectorPadClass +{ + GstPadClass parent; +}; + +static void gst_selector_pad_class_init (GstSelectorPadClass * klass); +static void gst_selector_pad_init (GstSelectorPad * pad); +static void gst_selector_pad_finalize (GObject * object); + +static void gst_selector_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPadClass *selector_pad_parent_class = NULL; + +static void gst_selector_pad_reset (GstSelectorPad * pad); +static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); +static GstCaps *gst_selector_pad_getcaps (GstPad * pad); +static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); +static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); + +enum +{ + PROP_PAD_0, + PROP_PAD_TAGS, + PROP_PAD_ACTIVE, + PROP_PAD_LAST +}; + +static GType +gst_selector_pad_get_type (void) +{ + static GType selector_pad_type = 0; + + if (!selector_pad_type) { + static const GTypeInfo selector_pad_info = { + sizeof (GstSelectorPadClass), + NULL, + NULL, + (GClassInitFunc) gst_selector_pad_class_init, + NULL, + NULL, + sizeof (GstSelectorPad), + 0, + (GInstanceInitFunc) gst_selector_pad_init, + }; + + selector_pad_type = + g_type_register_static (GST_TYPE_PAD, "GstPlaybinSelectorPad", + &selector_pad_info, 0); + } + return selector_pad_type; +} + +static void +gst_selector_pad_class_init (GstSelectorPadClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + selector_pad_parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_selector_pad_finalize; + gobject_class->get_property = gst_selector_pad_get_property; + + g_object_class_install_property (gobject_class, PROP_PAD_TAGS, + g_param_spec_boxed ("tags", "Tags", + "The currently active tags on the pad", GST_TYPE_TAG_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE, + g_param_spec_boolean ("active", "Active", + "If the pad is currently active", FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_selector_pad_init (GstSelectorPad * pad) +{ + gst_selector_pad_reset (pad); +} + +static void +gst_selector_pad_finalize (GObject * object) +{ + GstSelectorPad *pad; + + pad = GST_SELECTOR_PAD_CAST (object); + + if (pad->tags) + gst_tag_list_free (pad->tags); + + G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object); +} + +static void +gst_selector_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstSelectorPad *pad; + + pad = GST_SELECTOR_PAD (object); + + switch (prop_id) { + case PROP_PAD_TAGS: + GST_OBJECT_LOCK (object); + g_value_set_boxed (value, pad->tags); + GST_OBJECT_UNLOCK (object); + break; + case PROP_PAD_ACTIVE: + { + GstStreamSelector *sel; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + g_value_set_boolean (value, gst_stream_selector_is_active_sinkpad (sel, + GST_PAD_CAST (pad))); + gst_object_unref (sel); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_selector_pad_reset (GstSelectorPad * pad) +{ + pad->active = FALSE; + pad->eos = FALSE; + gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED); +} + +static gboolean +gst_selector_pad_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + gboolean forward = TRUE; + GstStreamSelector *sel; + GstSelectorPad *selpad; + GstPad *active_sinkpad; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + selpad = GST_SELECTOR_PAD_CAST (pad); + + /* only forward if we are dealing with the active sinkpad */ + active_sinkpad = gst_stream_selector_activate_sinkpad (sel, pad); + forward = (active_sinkpad == pad); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + gst_selector_pad_reset (selpad); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + GST_DEBUG_OBJECT (selpad, + "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " + "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, update, rate, arate, format, start, stop, time); + + gst_segment_set_newsegment_full (&selpad->segment, update, + rate, arate, format, start, stop, time); + /* if we are not going to forward the segment, mark the segment as + * pending */ + if (!forward) + selpad->segment_pending = TRUE; + break; + } + case GST_EVENT_TAG: + { + GstTagList *tags; + + GST_OBJECT_LOCK (selpad); + if (selpad->tags) + gst_tag_list_free (selpad->tags); + gst_event_parse_tag (event, &tags); + if (tags) + tags = gst_tag_list_copy (tags); + selpad->tags = tags; + GST_DEBUG_OBJECT (sel, "received tags %" GST_PTR_FORMAT, selpad->tags); + GST_OBJECT_UNLOCK (selpad); + break; + } + case GST_EVENT_EOS: + selpad->eos = TRUE; + break; + default: + break; + } + if (forward) + res = gst_pad_push_event (sel->srcpad, event); + else + gst_event_unref (event); + + gst_object_unref (sel); + + return res; +} + +static GstCaps * +gst_selector_pad_getcaps (GstPad * pad) +{ + GstStreamSelector *sel; + GstCaps *caps; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer"); + caps = gst_pad_peer_get_caps (sel->srcpad); + if (caps == NULL) + caps = gst_caps_new_any (); + + gst_object_unref (sel); + + return caps; +} + +static GstFlowReturn +gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstStreamSelector *sel; + GstFlowReturn result; + GstPad *active_sinkpad; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + + active_sinkpad = gst_stream_selector_activate_sinkpad (sel, pad); + + /* Fallback allocation for buffers from pads except the selected one */ + if (pad != active_sinkpad) { + GST_DEBUG_OBJECT (sel, + "Pad %s:%s is not selected. Performing fallback allocation", + GST_DEBUG_PAD_NAME (pad)); + + *buf = NULL; + result = GST_FLOW_OK; + } else { + result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf); + + /* FIXME: HACK. If buffer alloc returns not-linked, perform a fallback + * allocation. This should NOT be necessary, because playbin should + * properly block the source pad from running until it's finished hooking + * everything up, but playbin needs refactoring first. */ + if (result == GST_FLOW_NOT_LINKED) { + GST_DEBUG_OBJECT (sel, + "No peer pad yet - performing fallback allocation for pad %s:%s", + GST_DEBUG_PAD_NAME (pad)); + + *buf = NULL; + result = GST_FLOW_OK; + } + } + + gst_object_unref (sel); + + return result; +} + +static GstFlowReturn +gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) +{ + GstStreamSelector *sel; + GstFlowReturn res; + GstPad *active_sinkpad; + GstSelectorPad *selpad; + GstClockTime timestamp; + GstSegment *seg; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + selpad = GST_SELECTOR_PAD_CAST (pad); + seg = &selpad->segment; + + active_sinkpad = gst_stream_selector_activate_sinkpad (sel, pad); + + timestamp = GST_BUFFER_TIMESTAMP (buf); + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + GST_DEBUG_OBJECT (sel, "received timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); + gst_segment_set_last_stop (seg, seg->format, timestamp); + } + + /* Ignore buffers from pads except the selected one */ + if (pad != active_sinkpad) + goto ignore; + + /* if we have a pending segment, push it out now */ + if (selpad->segment_pending) { + gst_pad_push_event (sel->srcpad, gst_event_new_new_segment_full (FALSE, + seg->rate, seg->applied_rate, seg->format, seg->start, seg->stop, + seg->time)); + + selpad->segment_pending = FALSE; + } + + /* forward */ + GST_DEBUG_OBJECT (sel, "Forwarding buffer %p from pad %s:%s", buf, + GST_DEBUG_PAD_NAME (pad)); + res = gst_pad_push (sel->srcpad, buf); +done: + gst_object_unref (sel); + return res; + /* dropped buffers */ +ignore: + { + GST_DEBUG_OBJECT (sel, "Ignoring buffer %p from pad %s:%s", + buf, GST_DEBUG_PAD_NAME (pad)); + gst_buffer_unref (buf); + res = GST_FLOW_NOT_LINKED; + goto done; + } +} + +static void gst_stream_selector_dispose (GObject * object); + +static void gst_stream_selector_init (GstStreamSelector * sel); +static void gst_stream_selector_base_init (GstStreamSelectorClass * klass); +static void gst_stream_selector_class_init (GstStreamSelectorClass * klass); + +static void gst_stream_selector_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_stream_selector_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPad *gst_stream_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused); +static void gst_stream_selector_release_pad (GstElement * element, + GstPad * pad); +static GstIterator *gst_stream_selector_pad_iterate_linked_pads (GstPad * pad); +static GstCaps *gst_stream_selector_getcaps (GstPad * pad); + +static GstElementClass *parent_class = NULL; + +GType +gst_stream_selector_get_type (void) +{ + static GType stream_selector_type = 0; + + if (!stream_selector_type) { + static const GTypeInfo stream_selector_info = { + sizeof (GstStreamSelectorClass), + (GBaseInitFunc) gst_stream_selector_base_init, + NULL, + (GClassInitFunc) gst_stream_selector_class_init, + NULL, + NULL, + sizeof (GstStreamSelector), + 0, + (GInstanceInitFunc) gst_stream_selector_init, + }; + stream_selector_type = + g_type_register_static (GST_TYPE_ELEMENT, + "GstStreamSelector", &stream_selector_info, 0); + GST_DEBUG_CATEGORY_INIT (stream_selector_debug, + "streamselector", 0, "A stream-selector element"); + } + + return stream_selector_type; +} + +static void +gst_stream_selector_base_init (GstStreamSelectorClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "StreamSelector", "Generic", + "N-to-1 input stream_selectoring", + "Julien Moutte , " + "Jan Schmidt , " + "Wim Taymans "); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_stream_selector_sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_stream_selector_src_factory)); +} + +static void +gst_stream_selector_class_init (GstStreamSelectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_stream_selector_dispose; + + gobject_class->set_property = gst_stream_selector_set_property; + gobject_class->get_property = gst_stream_selector_get_property; + + g_object_class_install_property (gobject_class, PROP_N_PADS, + g_param_spec_uint ("n-pads", "Number of Pads", + "The number of sink pads", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, + g_param_spec_object ("active-pad", "Active Pad", + "The currently active sink pad", GST_TYPE_PAD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->request_new_pad = gst_stream_selector_request_new_pad; + gstelement_class->release_pad = gst_stream_selector_release_pad; +} + +static void +gst_stream_selector_init (GstStreamSelector * sel) +{ + sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_iterate_internal_links_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_selector_pad_iterate_linked_pads)); + gst_pad_set_getcaps_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_selector_getcaps)); + gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); + /* sinkpad management */ + sel->padcount = 0; + sel->active_sinkpad = NULL; + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); +} + +static void +gst_stream_selector_dispose (GObject * object) +{ + GstStreamSelector *sel = GST_STREAM_SELECTOR (object); + + if (sel->active_sinkpad) { + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_stream_selector_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstStreamSelector *sel = GST_STREAM_SELECTOR (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + { + GstPad *pad = NULL; + GstPad **active_pad_p; + + pad = g_value_get_object (value); + + GST_OBJECT_LOCK (object); + if (pad != sel->active_sinkpad) { + GstSelectorPad *selpad; + + selpad = GST_SELECTOR_PAD_CAST (pad); + /* we can only activate pads that have data received */ + if (selpad && !selpad->active) { + GST_DEBUG_OBJECT (sel, "No data received on pad %" GST_PTR_FORMAT, + pad); + } else { + active_pad_p = &sel->active_sinkpad; + gst_object_replace ((GstObject **) active_pad_p, + GST_OBJECT_CAST (pad)); + GST_DEBUG_OBJECT (sel, "New active pad is %" GST_PTR_FORMAT, + sel->active_sinkpad); + } + } + GST_OBJECT_UNLOCK (object); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_stream_selector_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstStreamSelector *sel = GST_STREAM_SELECTOR (object); + + switch (prop_id) { + case PROP_N_PADS: + GST_OBJECT_LOCK (object); + g_value_set_uint (value, sel->n_pads); + GST_OBJECT_UNLOCK (object); + break; + case PROP_ACTIVE_PAD:{ + GST_OBJECT_LOCK (object); + g_value_set_object (value, sel->active_sinkpad); + GST_OBJECT_UNLOCK (object); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_stream_selector_get_linked_pad (GstPad * pad, gboolean strict) +{ + GstStreamSelector *sel; + GstPad *otherpad = NULL; + + sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + + GST_OBJECT_LOCK (sel); + if (pad == sel->srcpad) + otherpad = sel->active_sinkpad; + else if (pad == sel->active_sinkpad || !strict) + otherpad = sel->srcpad; + if (otherpad) + gst_object_ref (otherpad); + GST_OBJECT_UNLOCK (sel); + gst_object_unref (sel); + return otherpad; +} + +static GstCaps * +gst_stream_selector_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstObject *parent; + GstCaps *caps; + + otherpad = gst_stream_selector_get_linked_pad (pad, FALSE); + parent = gst_object_get_parent (GST_OBJECT (pad)); + if (!otherpad) { + GST_DEBUG_OBJECT (parent, + "Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad)); + caps = gst_caps_new_any (); + } else { + GST_DEBUG_OBJECT (parent, + "Pad %s:%s is linked (to %s:%s), returning peer caps", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (otherpad)); + /* if the peer has caps, use those. If the pad is not linked, this function + * returns NULL and we return ANY */ + if (!(caps = gst_pad_peer_get_caps (otherpad))) + caps = gst_caps_new_any (); + gst_object_unref (otherpad); + } + + gst_object_unref (parent); + return caps; +} + +/* check if the pad is the active sinkpad */ +static gboolean +gst_stream_selector_is_active_sinkpad (GstStreamSelector * sel, GstPad * pad) +{ + gboolean res; + + GST_OBJECT_LOCK (sel); + res = (pad == sel->active_sinkpad); + GST_OBJECT_UNLOCK (sel); + + return res; +} + +/* Get or create the active sinkpad */ +static GstPad * +gst_stream_selector_activate_sinkpad (GstStreamSelector * sel, GstPad * pad) +{ + GstPad *active_sinkpad; + GstSelectorPad *selpad; + + selpad = GST_SELECTOR_PAD_CAST (pad); + + GST_OBJECT_LOCK (sel); + selpad->active = TRUE; + active_sinkpad = sel->active_sinkpad; + if (active_sinkpad == NULL) { + /* first pad we get an alloc on becomes the activated pad by default */ + active_sinkpad = sel->active_sinkpad = gst_object_ref (pad); + GST_DEBUG_OBJECT (sel, "Activating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + } + GST_OBJECT_UNLOCK (sel); + + return active_sinkpad; +} + +static GstIterator * +gst_stream_selector_pad_iterate_linked_pads (GstPad * pad) +{ + GstStreamSelector *sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstIterator *ret; + + otherpad = gst_stream_selector_get_linked_pad (pad, TRUE); + ret = + gst_iterator_new_single (GST_TYPE_PAD, otherpad, + (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref); + + if (otherpad) + gst_object_unref (otherpad); + gst_object_unref (sel); + + return ret; +} + +static GstPad * +gst_stream_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused) +{ + GstStreamSelector *sel; + gchar *name = NULL; + GstPad *sinkpad = NULL; + + sel = GST_STREAM_SELECTOR (element); + g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL); + GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount); + GST_OBJECT_LOCK (sel); + name = g_strdup_printf ("sink%d", sel->padcount++); + sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, + "name", name, "direction", templ->direction, "template", templ, NULL); + g_free (name); + sel->n_pads++; + GST_OBJECT_UNLOCK (sel); + + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_event)); + gst_pad_set_getcaps_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps)); + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_chain)); + gst_pad_set_iterate_internal_links_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_selector_pad_iterate_linked_pads)); + gst_pad_set_bufferalloc_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_bufferalloc)); + + gst_pad_set_active (sinkpad, TRUE); + gst_element_add_pad (GST_ELEMENT (sel), sinkpad); + return sinkpad; +} + +static void +gst_stream_selector_release_pad (GstElement * element, GstPad * pad) +{ + GstStreamSelector *sel; + + sel = GST_STREAM_SELECTOR (element); + GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + GST_OBJECT_LOCK (sel); + /* if the pad was the active pad, makes us select a new one */ + if (sel->active_sinkpad == pad) { + GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + sel->active_sinkpad = NULL; + } + sel->n_pads--; + GST_OBJECT_UNLOCK (sel); + + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT (sel), pad); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.h b/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.h new file mode 100644 index 0000000..5200a0b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreamselector.h @@ -0,0 +1,62 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAM_SELECTOR_H__ +#define __GST_STREAM_SELECTOR_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_SELECTOR \ + (gst_stream_selector_get_type()) +#define GST_STREAM_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAM_SELECTOR, GstStreamSelector)) +#define GST_STREAM_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_STREAM_SELECTOR, GstStreamSelectorClass)) +#define GST_IS_STREAM_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAM_SELECTOR)) +#define GST_IS_STREAM_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_STREAM_SELECTOR)) + +typedef struct _GstStreamSelector GstStreamSelector; +typedef struct _GstStreamSelectorClass GstStreamSelectorClass; + +struct _GstStreamSelector { + GstElement element; + + GstPad *srcpad; + + GstPad *active_sinkpad; + guint n_pads; + guint padcount; + + GstSegment segment; +}; + +struct _GstStreamSelectorClass { + GstElementClass parent_class; +}; + +GType gst_stream_selector_get_type (void); + +G_END_DECLS + +#endif /* __GST_STREAM_SELECTOR_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.c b/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.c new file mode 100644 index 0000000..9a48ab0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.c @@ -0,0 +1,986 @@ +/* GStreamer + * Copyright (C) 2010 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gststreamsynchronizer.h" + +GST_DEBUG_CATEGORY_STATIC (stream_synchronizer_debug); +#define GST_CAT_DEFAULT stream_synchronizer_debug + +#define GST_STREAM_SYNCHRONIZER_LOCK(obj) G_STMT_START { \ + GST_LOG_OBJECT (obj, \ + "locking from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (GST_STREAM_SYNCHRONIZER_CAST(obj)->lock); \ + GST_LOG_OBJECT (obj, \ + "locked from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define GST_STREAM_SYNCHRONIZER_UNLOCK(obj) G_STMT_START { \ + GST_LOG_OBJECT (obj, \ + "unlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (GST_STREAM_SYNCHRONIZER_CAST(obj)->lock); \ +} G_STMT_END + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src_%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink_%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static const gboolean passthrough = TRUE; + +GST_BOILERPLATE (GstStreamSynchronizer, gst_stream_synchronizer, + GstElement, GST_TYPE_ELEMENT); + +typedef struct +{ + GstStreamSynchronizer *transform; + guint stream_number; + GstPad *srcpad; + GstPad *sinkpad; + GstSegment segment; + + gboolean wait; + gboolean new_stream; + gboolean drop_discont; + gboolean is_eos; + gboolean seen_data; + + gint64 running_time_diff; +} GstStream; + +/* Must be called with lock! */ +static GstPad * +gst_stream_get_other_pad (GstStream * stream, GstPad * pad) +{ + if (stream->sinkpad == pad) + return gst_object_ref (stream->srcpad); + else if (stream->srcpad == pad) + return gst_object_ref (stream->sinkpad); + + return NULL; +} + +static GstPad * +gst_stream_get_other_pad_from_pad (GstPad * pad) +{ + GstStreamSynchronizer *self = + GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad)); + GstStream *stream; + GstPad *opad = NULL; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (!stream) + goto out; + + opad = gst_stream_get_other_pad (stream, pad); + +out: + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + gst_object_unref (self); + + if (!opad) + GST_WARNING_OBJECT (pad, "Trying to get other pad after releasing"); + + return opad; +} + +/* Generic pad functions */ +static GstIterator * +gst_stream_synchronizer_iterate_internal_links (GstPad * pad) +{ + GstIterator *it = NULL; + GstPad *opad; + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + it = gst_iterator_new_single (GST_TYPE_PAD, opad, + (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref); + gst_object_unref (opad); + } + + return it; +} + +static gboolean +gst_stream_synchronizer_query (GstPad * pad, GstQuery * query) +{ + GstPad *opad; + gboolean ret = FALSE; + + GST_LOG_OBJECT (pad, "Handling query %s", GST_QUERY_TYPE_NAME (query)); + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_peer_query (opad, query); + gst_object_unref (opad); + } + + return ret; +} + +static GstCaps * +gst_stream_synchronizer_getcaps (GstPad * pad) +{ + GstPad *opad; + GstCaps *ret = NULL; + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_peer_get_caps (opad); + gst_object_unref (opad); + } + + if (ret == NULL) + ret = gst_caps_new_any (); + + GST_LOG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_stream_synchronizer_acceptcaps (GstPad * pad, GstCaps * caps) +{ + GstPad *opad; + gboolean ret = FALSE; + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_peer_accept_caps (opad, caps); + gst_object_unref (opad); + } + + GST_LOG_OBJECT (pad, "Caps%s accepted: %" GST_PTR_FORMAT, (ret ? "" : " not"), + caps); + + return ret; +} + +/* srcpad functions */ +static gboolean +gst_stream_synchronizer_src_event (GstPad * pad, GstEvent * event) +{ + GstStreamSynchronizer *self = + GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad)); + GstPad *opad; + gboolean ret = FALSE; + + if (passthrough) + goto skip_adjustments; + + GST_LOG_OBJECT (pad, "Handling event %s: %" GST_PTR_FORMAT, + GST_EVENT_TYPE_NAME (event), event->structure); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_QOS:{ + gdouble proportion; + GstClockTimeDiff diff; + GstClockTime timestamp; + gint64 running_time_diff; + GstStream *stream; + + gst_event_parse_qos (event, &proportion, &diff, ×tamp); + gst_event_unref (event); + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) + running_time_diff = stream->running_time_diff; + else + running_time_diff = -1; + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + + if (running_time_diff == -1) { + GST_WARNING_OBJECT (pad, "QOS event before group start"); + goto out; + } else if (timestamp < running_time_diff) { + GST_DEBUG_OBJECT (pad, "QOS event from previous group"); + goto out; + } + + GST_LOG_OBJECT (pad, + "Adjusting QOS event: %" GST_TIME_FORMAT " - %" GST_TIME_FORMAT " = %" + GST_TIME_FORMAT, GST_TIME_ARGS (timestamp), + GST_TIME_ARGS (running_time_diff), + GST_TIME_ARGS (timestamp - running_time_diff)); + + timestamp -= running_time_diff; + + /* That case is invalid for QoS events */ + if (diff < 0 && -diff > timestamp) { + GST_DEBUG_OBJECT (pad, "QOS event from previous group"); + ret = TRUE; + goto out; + } + + event = gst_event_new_qos (proportion, diff, timestamp); + break; + } + default: + break; + } + +skip_adjustments: + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_push_event (opad, event); + gst_object_unref (opad); + } + +out: + gst_object_unref (self); + + return ret; +} + +/* sinkpad functions */ +static gboolean +gst_stream_synchronizer_sink_event (GstPad * pad, GstEvent * event) +{ + GstStreamSynchronizer *self = + GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad)); + GstPad *opad; + gboolean ret = FALSE; + + if (passthrough) + goto skip_adjustments; + + GST_LOG_OBJECT (pad, "Handling event %s: %" GST_PTR_FORMAT, + GST_EVENT_TYPE_NAME (event), event->structure); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SINK_MESSAGE:{ + GstMessage *message; + + gst_event_parse_sink_message (event, &message); + if (message->structure + && gst_structure_has_name (message->structure, + "playbin2-stream-changed")) { + GstStream *stream; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) { + GList *l; + gboolean all_wait = TRUE; + + GST_DEBUG_OBJECT (pad, "Stream %d changed", stream->stream_number); + + stream->is_eos = FALSE; + stream->wait = TRUE; + stream->new_stream = TRUE; + + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + + all_wait = all_wait && ostream->wait; + if (!all_wait) + break; + } + if (all_wait) { + gint64 last_stop = 0; + + GST_DEBUG_OBJECT (self, "All streams have changed -- unblocking"); + + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + gint64 stop_running_time; + gint64 last_stop_running_time; + + ostream->wait = FALSE; + + stop_running_time = + gst_segment_to_running_time (&ostream->segment, + GST_FORMAT_TIME, ostream->segment.stop); + last_stop_running_time = + gst_segment_to_running_time (&ostream->segment, + GST_FORMAT_TIME, ostream->segment.last_stop); + last_stop = + MAX (last_stop, MAX (stop_running_time, + last_stop_running_time)); + } + last_stop = MAX (0, last_stop); + self->group_start_time = MAX (self->group_start_time, last_stop); + + GST_DEBUG_OBJECT (self, "New group start time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (self->group_start_time)); + + g_cond_broadcast (self->stream_finish_cond); + } + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + } + gst_message_unref (message); + break; + } + case GST_EVENT_NEWSEGMENT:{ + GstStream *stream; + gboolean update; + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, position; + + gst_event_parse_new_segment_full (event, + &update, &rate, &applied_rate, &format, &start, &stop, &position); + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) { + if (stream->wait) { + GST_DEBUG_OBJECT (pad, "Stream %d is waiting", stream->stream_number); + g_cond_wait (self->stream_finish_cond, self->lock); + stream = gst_pad_get_element_private (pad); + if (stream) + stream->wait = FALSE; + } + } + + if (self->shutdown) { + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + gst_event_unref (event); + goto done; + } + + if (stream && format == GST_FORMAT_TIME) { + if (stream->new_stream) { + gint64 last_stop_running_time = 0; + gint64 stop_running_time = 0; + + if (stream->segment.format == GST_FORMAT_TIME) { + last_stop_running_time = + gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME, + stream->segment.last_stop); + last_stop_running_time = MAX (last_stop_running_time, 0); + stop_running_time = + gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME, + stream->segment.stop); + stop_running_time = MAX (last_stop_running_time, 0); + + if (stop_running_time != last_stop_running_time) { + GST_WARNING_OBJECT (pad, + "Gap between last_stop and segment stop: %" GST_TIME_FORMAT + " != %" GST_TIME_FORMAT, GST_TIME_ARGS (stop_running_time), + GST_TIME_ARGS (last_stop_running_time)); + } + + if (stop_running_time < last_stop_running_time) { + GST_DEBUG_OBJECT (pad, "Updating stop position"); + gst_pad_push_event (stream->srcpad, + gst_event_new_new_segment_full (TRUE, stream->segment.rate, + stream->segment.applied_rate, GST_FORMAT_TIME, + stream->segment.start, stream->segment.last_stop, + stream->segment.time)); + gst_segment_set_newsegment_full (&stream->segment, TRUE, + stream->segment.rate, stream->segment.applied_rate, + GST_FORMAT_TIME, stream->segment.start, + stream->segment.last_stop, stream->segment.time); + } + stop_running_time = MAX (stop_running_time, last_stop_running_time); + GST_DEBUG_OBJECT (pad, + "Stop running time of last group: %" GST_TIME_FORMAT, + GST_TIME_ARGS (stop_running_time)); + } + stream->new_stream = FALSE; + stream->drop_discont = TRUE; + + if (stop_running_time < self->group_start_time) { + gint64 diff = self->group_start_time - stop_running_time; + + GST_DEBUG_OBJECT (pad, + "Advancing running time for other streams by: %" + GST_TIME_FORMAT, GST_TIME_ARGS (diff)); + gst_pad_push_event (stream->srcpad, + gst_event_new_new_segment_full (FALSE, 1.0, 1.0, + GST_FORMAT_TIME, 0, diff, 0)); + gst_segment_set_newsegment_full (&stream->segment, FALSE, 1.0, 1.0, + GST_FORMAT_TIME, 0, diff, 0); + } + } + + GST_DEBUG_OBJECT (pad, "Segment was: %" GST_SEGMENT_FORMAT, + &stream->segment); + gst_segment_set_newsegment_full (&stream->segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "Segment now is: %" GST_SEGMENT_FORMAT, + &stream->segment); + + GST_DEBUG_OBJECT (pad, "Stream start running time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->segment.accum)); + stream->running_time_diff = stream->segment.accum; + } else if (stream) { + GST_WARNING_OBJECT (pad, "Non-TIME segment: %s", + gst_format_get_name (format)); + gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + break; + } + case GST_EVENT_FLUSH_STOP:{ + GstStream *stream; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) { + GST_DEBUG_OBJECT (pad, "Resetting segment for stream %d", + stream->stream_number); + gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); + + stream->is_eos = FALSE; + stream->wait = FALSE; + stream->new_stream = FALSE; + stream->drop_discont = FALSE; + stream->seen_data = FALSE; + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + break; + } + case GST_EVENT_EOS:{ + GstStream *stream; + GList *l; + gboolean all_eos = TRUE; + gboolean seen_data; + GSList *pads = NULL; + GstPad *srcpad; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (!stream) { + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + GST_WARNING_OBJECT (pad, "EOS for unknown stream"); + break; + } + + GST_DEBUG_OBJECT (pad, "Have EOS for stream %d", stream->stream_number); + stream->is_eos = TRUE; + + seen_data = stream->seen_data; + srcpad = gst_object_ref (stream->srcpad); + + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + + all_eos = all_eos && ostream->is_eos; + if (!all_eos) + break; + } + + if (all_eos) { + GST_DEBUG_OBJECT (self, "All streams are EOS -- forwarding"); + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + /* local snapshot of current pads */ + gst_object_ref (ostream->srcpad); + pads = g_slist_prepend (pads, ostream->srcpad); + } + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + /* drop lock when sending eos, which may block in e.g. preroll */ + if (pads) { + GstPad *pad; + GSList *epad; + + ret = TRUE; + epad = pads; + while (epad) { + pad = epad->data; + GST_DEBUG_OBJECT (pad, "Pushing EOS"); + ret = ret && gst_pad_push_event (pad, gst_event_new_eos ()); + gst_object_unref (pad); + epad = g_slist_next (epad); + } + g_slist_free (pads); + } else { + /* if EOS, but no data has passed, then send something to replace EOS + * for preroll purposes */ + if (!seen_data) { + GstBuffer *buf = gst_buffer_new (); + + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_PREROLL); + gst_pad_push (srcpad, buf); + } + } + gst_object_unref (srcpad); + goto done; + break; + } + default: + break; + } + +skip_adjustments: + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_push_event (opad, event); + gst_object_unref (opad); + } + +done: + gst_object_unref (self); + + return ret; +} + +static GstFlowReturn +gst_stream_synchronizer_sink_bufferalloc (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstPad *opad; + GstFlowReturn ret = GST_FLOW_ERROR; + + GST_LOG_OBJECT (pad, "Allocating buffer: size=%u", size); + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_alloc_buffer (opad, offset, size, caps, buf); + gst_object_unref (opad); + } + + GST_LOG_OBJECT (pad, "Allocation: %s", gst_flow_get_name (ret)); + + return ret; +} + +static GstFlowReturn +gst_stream_synchronizer_sink_chain (GstPad * pad, GstBuffer * buffer) +{ + GstStreamSynchronizer *self = + GST_STREAM_SYNCHRONIZER (gst_pad_get_parent (pad)); + GstPad *opad; + GstFlowReturn ret = GST_FLOW_ERROR; + GstStream *stream; + GstClockTime timestamp = GST_CLOCK_TIME_NONE; + GstClockTime timestamp_end = GST_CLOCK_TIME_NONE; + + if (passthrough) { + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_push (opad, buffer); + gst_object_unref (opad); + } + goto done; + } + + GST_LOG_OBJECT (pad, "Handling buffer %p: size=%u, timestamp=%" + GST_TIME_FORMAT " duration=%" GST_TIME_FORMAT + " offset=%" G_GUINT64_FORMAT " offset_end=%" G_GUINT64_FORMAT, + buffer, GST_BUFFER_SIZE (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), + GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer)); + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) + && GST_BUFFER_DURATION_IS_VALID (buffer)) + timestamp_end = timestamp + GST_BUFFER_DURATION (buffer); + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + + stream->seen_data = TRUE; + if (stream && stream->drop_discont) { + buffer = gst_buffer_make_metadata_writable (buffer); + GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT); + stream->drop_discont = FALSE; + } + + if (stream && stream->segment.format == GST_FORMAT_TIME + && GST_CLOCK_TIME_IS_VALID (timestamp)) { + GST_LOG_OBJECT (pad, + "Updating last-stop from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->segment.last_stop), GST_TIME_ARGS (timestamp)); + gst_segment_set_last_stop (&stream->segment, GST_FORMAT_TIME, timestamp); + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + + opad = gst_stream_get_other_pad_from_pad (pad); + if (opad) { + ret = gst_pad_push (opad, buffer); + gst_object_unref (opad); + } + + GST_LOG_OBJECT (pad, "Push returned: %s", gst_flow_get_name (ret)); + if (ret == GST_FLOW_OK) { + GList *l; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream && stream->segment.format == GST_FORMAT_TIME + && GST_CLOCK_TIME_IS_VALID (timestamp_end)) { + GST_LOG_OBJECT (pad, + "Updating last-stop from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, + GST_TIME_ARGS (stream->segment.last_stop), + GST_TIME_ARGS (timestamp_end)); + gst_segment_set_last_stop (&stream->segment, GST_FORMAT_TIME, + timestamp_end); + } + + /* Advance EOS streams if necessary. For non-EOS + * streams the demuxers should already do this! */ + for (l = self->streams; l; l = l->next) { + GstStream *ostream = l->data; + gint64 last_stop; + + if (!ostream->is_eos || ostream->segment.format != GST_FORMAT_TIME) + continue; + + if (ostream->segment.last_stop != -1) + last_stop = ostream->segment.last_stop; + else + last_stop = ostream->segment.start; + + /* Is there a 1 second lag? */ + if (last_stop != -1 && last_stop + GST_SECOND < timestamp_end) { + gint64 new_start, new_stop; + + new_start = timestamp_end - GST_SECOND; + if (ostream->segment.stop == -1) + new_stop = -1; + else + new_stop = MAX (new_start, ostream->segment.stop); + + GST_DEBUG_OBJECT (ostream->sinkpad, + "Advancing stream %u from %" GST_TIME_FORMAT " to %" + GST_TIME_FORMAT, ostream->stream_number, GST_TIME_ARGS (last_stop), + GST_TIME_ARGS (new_start)); + + gst_pad_push_event (ostream->srcpad, + gst_event_new_new_segment_full (TRUE, ostream->segment.rate, + ostream->segment.applied_rate, ostream->segment.format, + new_start, new_stop, new_start)); + gst_segment_set_newsegment_full (&ostream->segment, TRUE, + ostream->segment.rate, ostream->segment.applied_rate, + ostream->segment.format, new_start, new_stop, new_start); + gst_segment_set_last_stop (&ostream->segment, GST_FORMAT_TIME, + new_start); + } + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + } + +done: + + gst_object_unref (self); + + return ret; +} + +/* GstElement vfuncs */ +static GstPad * +gst_stream_synchronizer_request_new_pad (GstElement * element, + GstPadTemplate * temp, const gchar * name) +{ + GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (element); + GstStream *stream; + gchar *tmp; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + GST_DEBUG_OBJECT (self, "Requesting new pad for stream %d", + self->current_stream_number); + + stream = g_slice_new0 (GstStream); + stream->transform = self; + stream->stream_number = self->current_stream_number; + + tmp = g_strdup_printf ("sink_%d", self->current_stream_number); + stream->sinkpad = gst_pad_new_from_static_template (&sinktemplate, tmp); + g_free (tmp); + gst_pad_set_element_private (stream->sinkpad, stream); + gst_pad_set_iterate_internal_links_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links)); + gst_pad_set_query_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query)); + gst_pad_set_getcaps_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_getcaps)); + gst_pad_set_acceptcaps_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_acceptcaps)); + gst_pad_set_event_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_event)); + gst_pad_set_chain_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_chain)); + gst_pad_set_bufferalloc_function (stream->sinkpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_sink_bufferalloc)); + + tmp = g_strdup_printf ("src_%d", self->current_stream_number); + stream->srcpad = gst_pad_new_from_static_template (&srctemplate, tmp); + g_free (tmp); + gst_pad_set_element_private (stream->srcpad, stream); + gst_pad_set_iterate_internal_links_function (stream->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_iterate_internal_links)); + gst_pad_set_query_function (stream->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_query)); + gst_pad_set_getcaps_function (stream->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_getcaps)); + gst_pad_set_acceptcaps_function (stream->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_acceptcaps)); + gst_pad_set_event_function (stream->srcpad, + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_src_event)); + + gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); + + self->streams = g_list_prepend (self->streams, stream); + self->current_stream_number++; + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + + /* Add pads and activate unless we're going to NULL */ + g_static_rec_mutex_lock (GST_STATE_GET_LOCK (self)); + if (GST_STATE_TARGET (self) != GST_STATE_NULL) { + gst_pad_set_active (stream->srcpad, TRUE); + gst_pad_set_active (stream->sinkpad, TRUE); + } + gst_element_add_pad (GST_ELEMENT_CAST (self), stream->srcpad); + gst_element_add_pad (GST_ELEMENT_CAST (self), stream->sinkpad); + g_static_rec_mutex_unlock (GST_STATE_GET_LOCK (self)); + + return stream->sinkpad; +} + +/* Must be called with lock! */ +static void +gst_stream_synchronizer_release_stream (GstStreamSynchronizer * self, + GstStream * stream) +{ + GList *l; + + GST_DEBUG_OBJECT (self, "Releasing stream %d", stream->stream_number); + + for (l = self->streams; l; l = l->next) { + if (l->data == stream) { + self->streams = g_list_delete_link (self->streams, l); + break; + } + } + g_assert (l != NULL); + + /* we can drop the lock, since stream exists now only local. + * Moreover, we should drop, to prevent deadlock with STREAM_LOCK + * (due to reverse lock order) when deactivating pads */ + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + + gst_pad_set_element_private (stream->srcpad, NULL); + gst_pad_set_element_private (stream->sinkpad, NULL); + gst_pad_set_active (stream->srcpad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (self), stream->srcpad); + gst_pad_set_active (stream->sinkpad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (self), stream->sinkpad); + + if (stream->segment.format == GST_FORMAT_TIME) { + gint64 stop_running_time; + gint64 last_stop_running_time; + + stop_running_time = + gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME, + stream->segment.stop); + last_stop_running_time = + gst_segment_to_running_time (&stream->segment, GST_FORMAT_TIME, + stream->segment.last_stop); + stop_running_time = MAX (stop_running_time, last_stop_running_time); + + GST_DEBUG_OBJECT (stream->sinkpad, + "Stop running time was: %" GST_TIME_FORMAT, + GST_TIME_ARGS (stop_running_time)); + + self->group_start_time = MAX (self->group_start_time, stop_running_time); + } + + g_slice_free (GstStream, stream); + + /* NOTE: In theory we have to check here if all streams + * are EOS but the one that was removed wasn't and then + * send EOS downstream. But due to the way how playsink + * works this is not necessary and will only cause problems + * for gapless playback. playsink will only add/remove pads + * when it's reconfigured, which happens when the streams + * change + */ + + /* lock for good measure, since the caller had it */ + GST_STREAM_SYNCHRONIZER_LOCK (self); +} + +static void +gst_stream_synchronizer_release_pad (GstElement * element, GstPad * pad) +{ + GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (element); + GstStream *stream; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + stream = gst_pad_get_element_private (pad); + if (stream) { + g_assert (stream->sinkpad == pad); + + gst_stream_synchronizer_release_stream (self, stream); + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); +} + +static GstStateChangeReturn +gst_stream_synchronizer_change_state (GstElement * element, + GstStateChange transition) +{ + GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (element); + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + GST_DEBUG_OBJECT (self, "State change NULL->READY"); + self->shutdown = FALSE; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT (self, "State change READY->PAUSED"); + self->group_start_time = 0; + self->shutdown = FALSE; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_DEBUG_OBJECT (self, "State change PAUSED->PLAYING"); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (self, "State change READY->NULL"); + + GST_STREAM_SYNCHRONIZER_LOCK (self); + g_cond_broadcast (self->stream_finish_cond); + self->shutdown = TRUE; + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + default: + break; + } + + { + GstStateChangeReturn bret; + + bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + GST_DEBUG_OBJECT (self, "Base class state changed returned: %d", bret); + if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE)) + return ret; + } + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (self, "State change PLAYING->PAUSED"); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY:{ + GList *l; + + GST_DEBUG_OBJECT (self, "State change PAUSED->READY"); + self->group_start_time = 0; + + GST_STREAM_SYNCHRONIZER_LOCK (self); + for (l = self->streams; l; l = l->next) { + GstStream *stream = l->data; + + gst_segment_init (&stream->segment, GST_FORMAT_UNDEFINED); + stream->wait = FALSE; + stream->new_stream = FALSE; + stream->drop_discont = FALSE; + stream->is_eos = FALSE; + } + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + break; + } + case GST_STATE_CHANGE_READY_TO_NULL:{ + GST_DEBUG_OBJECT (self, "State change READY->NULL"); + + GST_STREAM_SYNCHRONIZER_LOCK (self); + while (self->streams) + gst_stream_synchronizer_release_stream (self, self->streams->data); + self->current_stream_number = 0; + GST_STREAM_SYNCHRONIZER_UNLOCK (self); + break; + } + default: + break; + } + + return ret; +} + +/* GObject vfuncs */ +static void +gst_stream_synchronizer_finalize (GObject * object) +{ + GstStreamSynchronizer *self = GST_STREAM_SYNCHRONIZER (object); + + if (self->lock) { + g_mutex_free (self->lock); + self->lock = NULL; + } + + if (self->stream_finish_cond) { + g_cond_free (self->stream_finish_cond); + self->stream_finish_cond = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +/* GObject type initialization */ +static void +gst_stream_synchronizer_init (GstStreamSynchronizer * self, + GstStreamSynchronizerClass * klass) +{ + self->lock = g_mutex_new (); + self->stream_finish_cond = g_cond_new (); +} + +static void +gst_stream_synchronizer_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (gstelement_class, + "Stream Synchronizer", "Generic", + "Synchronizes a group of streams to have equal durations and starting points", + "Sebastian Dröge "); +} + +static void +gst_stream_synchronizer_class_init (GstStreamSynchronizerClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *element_class = (GstElementClass *) klass; + + GST_DEBUG_CATEGORY_INIT (stream_synchronizer_debug, + "streamsynchronizer", 0, "Stream Synchronizer"); + + gobject_class->finalize = gst_stream_synchronizer_finalize; + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_change_state); + element_class->request_new_pad = + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_request_new_pad); + element_class->release_pad = + GST_DEBUG_FUNCPTR (gst_stream_synchronizer_release_pad); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.h b/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.h new file mode 100644 index 0000000..e2379ae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gststreamsynchronizer.h @@ -0,0 +1,67 @@ +/* GStreamer + * Copyright (C) 2010 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STREAM_SYNCHRONIZER_H__ +#define __GST_STREAM_SYNCHRONIZER_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_STREAM_SYNCHRONIZER \ + (gst_stream_synchronizer_get_type()) +#define GST_STREAM_SYNCHRONIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_STREAM_SYNCHRONIZER, GstStreamSynchronizer)) +#define GST_STREAM_SYNCHRONIZER_CAST(obj) \ + ((GstStreamSynchronizer *) obj) +#define GST_STREAM_SYNCHRONIZER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_STREAM_SYNCHRONIZER, GstStreamSynchronizerClass)) +#define GST_IS_STREAM_SYNCHRONIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_STREAM_SYNCHRONIZER)) +#define GST_IS_STREAM_SYNCHRONIZER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_STREAM_SYNCHRONIZER)) + +typedef struct _GstStreamSynchronizer GstStreamSynchronizer; +typedef struct _GstStreamSynchronizerClass GstStreamSynchronizerClass; + +struct _GstStreamSynchronizer +{ + GstElement parent; + + /* < private > */ + GMutex *lock; + GCond *stream_finish_cond; + gboolean shutdown; + + GList *streams; + guint current_stream_number; + + GstClockTime group_start_time; +}; + +struct _GstStreamSynchronizerClass +{ + GstElementClass parent; +}; + +GType gst_stream_synchronizer_get_type (void); + +G_END_DECLS + +#endif /* __GST_STREAM_SYNCHRONIZER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.c b/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.c new file mode 100644 index 0000000..98fe15d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.c @@ -0,0 +1,2140 @@ +/* + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-subtitleoverlay + * + * #GstBin that auto-magically overlays a video stream with subtitles by + * autoplugging the required elements. + * + * It supports raw, timestamped text, different textual subtitle formats and + * DVD subpicture subtitles. + * + * + * Examples + * |[ + * gst-launch -v filesrc location=test.mkv ! matroskademux name=demux ! "video/x-h264" ! queue2 ! decodebin2 ! subtitleoverlay name=overlay ! ffmpegcolorspace ! autovideosink demux. ! "video/x-dvd-subpicture" ! queue2 ! overlay. + * ]| This will play back the given Matroska file with h264 video and subpicture subtitles. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstsubtitleoverlay.h" + +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (subtitle_overlay_debug); +#define GST_CAT_DEFAULT subtitle_overlay_debug + +#define IS_SUBTITLE_CHAIN_IGNORE_ERROR(flow) \ + G_UNLIKELY (flow == GST_FLOW_ERROR || flow == GST_FLOW_NOT_NEGOTIATED) + +#define IS_VIDEO_CHAIN_IGNORE_ERROR(flow) \ + G_UNLIKELY (flow == GST_FLOW_ERROR) + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate video_sinktemplate = +GST_STATIC_PAD_TEMPLATE ("video_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate subtitle_sinktemplate = +GST_STATIC_PAD_TEMPLATE ("subtitle_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_SILENT, + PROP_FONT_DESC, + PROP_SUBTITLE_ENCODING +}; + +GST_BOILERPLATE (GstSubtitleOverlay, gst_subtitle_overlay, GstBin, + GST_TYPE_BIN); + +static void _pad_blocked_cb (GstPad * pad, gboolean blocked, + gpointer user_data); + +static GQuark _subtitle_overlay_event_marker_id = 0; + +static void +do_async_start (GstSubtitleOverlay * self) +{ + if (!self->do_async) { + GstMessage *msg = + gst_message_new_async_start (GST_OBJECT_CAST (self), FALSE); + + GST_DEBUG_OBJECT (self, "Posting async-start"); + parent_class->handle_message (GST_BIN_CAST (self), msg); + self->do_async = TRUE; + } +} + +static void +do_async_done (GstSubtitleOverlay * self) +{ + if (self->do_async) { + GstMessage *msg = gst_message_new_async_done (GST_OBJECT_CAST (self)); + + GST_DEBUG_OBJECT (self, "Posting async-done"); + parent_class->handle_message (GST_BIN_CAST (self), msg); + self->do_async = FALSE; + } +} + +static void +gst_subtitle_overlay_finalize (GObject * object) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (object); + + if (self->lock) { + g_mutex_free (self->lock); + self->lock = NULL; + } + + if (self->factories_lock) { + g_mutex_free (self->factories_lock); + self->factories_lock = NULL; + } + + if (self->factories) + gst_plugin_feature_list_free (self->factories); + self->factories = NULL; + gst_caps_replace (&self->factory_caps, NULL); + + if (self->font_desc) { + g_free (self->font_desc); + self->font_desc = NULL; + } + + if (self->encoding) { + g_free (self->encoding); + self->encoding = NULL; + } + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +_is_renderer (GstElementFactory * factory) +{ + const gchar *klass, *name; + + klass = gst_element_factory_get_klass (factory); + name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)); + + if (strstr (klass, "Overlay/Subtitle") != NULL || + strstr (klass, "Overlay/SubPicture") != NULL) + return TRUE; + if (strcmp (name, "textoverlay") == 0) + return TRUE; + return FALSE; +} + +static gboolean +_is_parser (GstElementFactory * factory) +{ + const gchar *klass; + + klass = gst_element_factory_get_klass (factory); + + if (strstr (klass, "Parser/Subtitle") != NULL) + return TRUE; + return FALSE; +} + +static const gchar *_sub_pad_names[] = { "subpicture", "subpicture_sink", + "text", "text_sink", + "subtitle_sink", "subtitle" +}; + +static GstCaps * +_get_sub_caps (GstElementFactory * factory) +{ + const GList *templates; + GList *walk; + gboolean is_parser = _is_parser (factory); + + templates = gst_element_factory_get_static_pad_templates (factory); + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + + if (templ->direction == GST_PAD_SINK && templ->presence == GST_PAD_ALWAYS) { + gboolean found = FALSE; + + if (is_parser) { + found = TRUE; + } else { + guint i; + + for (i = 0; i < G_N_ELEMENTS (_sub_pad_names); i++) { + if (strcmp (templ->name_template, _sub_pad_names[i]) == 0) { + found = TRUE; + break; + } + } + } + if (found) + return gst_static_caps_get (&templ->static_caps); + } + } + return NULL; +} + +static gboolean +_factory_filter (GstPluginFeature * feature, GstCaps ** subcaps) +{ + GstElementFactory *factory; + guint rank; + const gchar *name; + const GList *templates; + GList *walk; + gboolean is_renderer; + GstCaps *templ_caps = NULL; + gboolean have_video_sink = FALSE; + + /* we only care about element factories */ + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + + factory = GST_ELEMENT_FACTORY_CAST (feature); + + /* only select elements with autoplugging rank or textoverlay */ + name = gst_plugin_feature_get_name (feature); + rank = gst_plugin_feature_get_rank (feature); + if (strcmp ("textoverlay", name) != 0 && rank < GST_RANK_MARGINAL) + return FALSE; + + /* Check if it's a renderer or a parser */ + if (_is_renderer (factory)) { + is_renderer = TRUE; + } else if (_is_parser (factory)) { + is_renderer = FALSE; + } else { + return FALSE; + } + + /* Check if there's a video sink in case of a renderer */ + if (is_renderer) { + templates = gst_element_factory_get_static_pad_templates (factory); + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + + /* we only care about the always-sink templates */ + if (templ->direction == GST_PAD_SINK && templ->presence == GST_PAD_ALWAYS) { + if (strcmp (templ->name_template, "video") == 0 || + strcmp (templ->name_template, "video_sink") == 0) { + have_video_sink = TRUE; + } + } + } + } + templ_caps = _get_sub_caps (factory); + + if (is_renderer && have_video_sink && templ_caps) { + GstCaps *tmp; + + GST_DEBUG ("Found renderer element %s (%s) with caps %" GST_PTR_FORMAT, + gst_element_factory_get_longname (factory), + gst_plugin_feature_get_name (feature), templ_caps); + tmp = gst_caps_union (*subcaps, templ_caps); + gst_caps_unref (templ_caps); + gst_caps_replace (subcaps, tmp); + gst_caps_unref (tmp); + return TRUE; + } else if (!is_renderer && !have_video_sink && templ_caps) { + GstCaps *tmp; + + GST_DEBUG ("Found parser element %s (%s) with caps %" GST_PTR_FORMAT, + gst_element_factory_get_longname (factory), + gst_plugin_feature_get_name (feature), templ_caps); + tmp = gst_caps_union (*subcaps, templ_caps); + gst_caps_unref (templ_caps); + gst_caps_replace (subcaps, tmp); + gst_caps_unref (tmp); + return TRUE; + } else { + if (templ_caps) + gst_caps_unref (templ_caps); + return FALSE; + } +} + +/* Call with factories_lock! */ +static gboolean +gst_subtitle_overlay_update_factory_list (GstSubtitleOverlay * self) +{ + if (!self->factories + || self->factories_cookie != + gst_default_registry_get_feature_list_cookie ()) { + GstCaps *subcaps; + GList *factories; + + subcaps = gst_caps_new_empty (); + + factories = gst_default_registry_feature_filter ( + (GstPluginFeatureFilter) _factory_filter, FALSE, &subcaps); + GST_DEBUG_OBJECT (self, "Created factory caps: %" GST_PTR_FORMAT, subcaps); + gst_caps_replace (&self->factory_caps, subcaps); + gst_caps_unref (subcaps); + if (self->factories) + gst_plugin_feature_list_free (self->factories); + self->factories = factories; + self->factories_cookie = gst_default_registry_get_feature_list_cookie (); + } + + return (self->factories != NULL); +} + +G_LOCK_DEFINE_STATIC (_factory_caps); +static GstCaps *_factory_caps = NULL; +static guint32 _factory_caps_cookie = 0; + +GstCaps * +gst_subtitle_overlay_create_factory_caps (void) +{ + GList *factories; + GstCaps *subcaps = NULL; + + G_LOCK (_factory_caps); + if (!_factory_caps + || _factory_caps_cookie != + gst_default_registry_get_feature_list_cookie ()) { + if (_factory_caps) + gst_caps_unref (_factory_caps); + _factory_caps = gst_caps_new_empty (); + + factories = gst_default_registry_feature_filter ( + (GstPluginFeatureFilter) _factory_filter, FALSE, &_factory_caps); + GST_DEBUG ("Created factory caps: %" GST_PTR_FORMAT, _factory_caps); + gst_plugin_feature_list_free (factories); + _factory_caps_cookie = gst_default_registry_get_feature_list_cookie (); + } + subcaps = gst_caps_ref (_factory_caps); + G_UNLOCK (_factory_caps); + + return subcaps; +} + +static gboolean +_filter_factories_for_caps (GstElementFactory * factory, const GstCaps * caps) +{ + GstCaps *fcaps = _get_sub_caps (factory); + gboolean ret = (fcaps) ? gst_caps_can_intersect (fcaps, caps) : FALSE; + + if (fcaps) + gst_caps_unref (fcaps); + + if (ret) + gst_object_ref (factory); + return ret; +} + +static gint +_sort_by_ranks (GstPluginFeature * f1, GstPluginFeature * f2) +{ + gint diff; + const gchar *rname1, *rname2; + + diff = gst_plugin_feature_get_rank (f2) - gst_plugin_feature_get_rank (f1); + if (diff != 0) + return diff; + + /* If the ranks are the same sort by name to get deterministic results */ + rname1 = gst_plugin_feature_get_name (f1); + rname2 = gst_plugin_feature_get_name (f2); + + diff = strcmp (rname1, rname2); + + return diff; +} + +static GstPad * +_get_sub_pad (GstElement * element) +{ + GstPad *pad; + guint i; + + for (i = 0; i < G_N_ELEMENTS (_sub_pad_names); i++) { + pad = gst_element_get_static_pad (element, _sub_pad_names[i]); + if (pad) + return pad; + } + return NULL; +} + +static GstPad * +_get_video_pad (GstElement * element) +{ + static const gchar *pad_names[] = { "video", "video_sink" }; + GstPad *pad; + guint i; + + for (i = 0; i < G_N_ELEMENTS (pad_names); i++) { + pad = gst_element_get_static_pad (element, pad_names[i]); + if (pad) + return pad; + } + return NULL; +} + +static gboolean +_create_element (GstSubtitleOverlay * self, GstElement ** element, + const gchar * factory_name, GstElementFactory * factory, + const gchar * element_name, gboolean mandatory) +{ + GstElement *elt; + + g_assert (!factory || !factory_name); + + if (factory_name) { + elt = gst_element_factory_make (factory_name, element_name); + } else { + factory_name = + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)); + elt = gst_element_factory_create (factory, element_name); + } + + if (G_UNLIKELY (!elt)) { + if (!factory) { + GstMessage *msg; + + msg = + gst_missing_element_message_new (GST_ELEMENT_CAST (self), + factory_name); + gst_element_post_message (GST_ELEMENT_CAST (self), msg); + + if (mandatory) + GST_ELEMENT_ERROR (self, CORE, MISSING_PLUGIN, (NULL), + ("no '%s' plugin found", factory_name)); + else + GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (NULL), + ("no '%s' plugin found", factory_name)); + } else { + if (mandatory) { + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("can't instantiate '%s'", factory_name)); + } else { + GST_ELEMENT_WARNING (self, CORE, FAILED, (NULL), + ("can't instantiate '%s'", factory_name)); + } + } + + return FALSE; + } + + if (G_UNLIKELY (gst_element_set_state (elt, + GST_STATE_READY) != GST_STATE_CHANGE_SUCCESS)) { + gst_object_unref (elt); + if (mandatory) { + GST_ELEMENT_ERROR (self, CORE, STATE_CHANGE, (NULL), + ("failed to set '%s' to READY", factory_name)); + } else { + GST_WARNING_OBJECT (self, "Failed to set '%s' to READY", factory_name); + } + return FALSE; + } + + if (G_UNLIKELY (!gst_bin_add (GST_BIN_CAST (self), gst_object_ref (elt)))) { + gst_element_set_state (elt, GST_STATE_NULL); + gst_object_unref (elt); + if (mandatory) { + GST_ELEMENT_ERROR (self, CORE, FAILED, (NULL), + ("failed to add '%s' to subtitleoverlay", factory_name)); + } else { + GST_WARNING_OBJECT (self, "Failed to add '%s' to subtitleoverlay", + factory_name); + } + return FALSE; + } + + gst_element_sync_state_with_parent (elt); + *element = elt; + return TRUE; +} + +static void +_remove_element (GstSubtitleOverlay * self, GstElement ** element) +{ + if (*element) { + gst_bin_remove (GST_BIN_CAST (self), *element); + gst_element_set_state (*element, GST_STATE_NULL); + gst_object_unref (*element); + *element = NULL; + } +} + +static void +_generate_update_newsegment_event (GstSegment * segment, GstEvent ** event1, + GstEvent ** event2) +{ + GstEvent *event; + + *event1 = NULL; + *event2 = NULL; + + event = gst_event_new_new_segment_full (FALSE, segment->rate, + segment->applied_rate, segment->format, 0, segment->accum, 0); + gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, + G_TYPE_BOOLEAN, TRUE, NULL); + *event1 = event; + + event = gst_event_new_new_segment_full (FALSE, segment->rate, + segment->applied_rate, segment->format, + segment->start, segment->stop, segment->time); + gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, + G_TYPE_BOOLEAN, TRUE, NULL); + *event2 = event; +} + +static gboolean +_setup_passthrough (GstSubtitleOverlay * self) +{ + GstPad *src, *sink; + GstElement *identity; + + GST_DEBUG_OBJECT (self, "Doing video passthrough"); + + if (self->passthrough_identity) { + GST_DEBUG_OBJECT (self, "Already in passthrough mode"); + goto out; + } + + /* Unlink & destroy everything */ + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->video_sinkpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad), NULL); + self->silent_property = NULL; + _remove_element (self, &self->post_colorspace); + _remove_element (self, &self->overlay); + _remove_element (self, &self->parser); + _remove_element (self, &self->renderer); + _remove_element (self, &self->pre_colorspace); + _remove_element (self, &self->passthrough_identity); + + if (G_UNLIKELY (!_create_element (self, &self->passthrough_identity, + "identity", NULL, "passthrough-identity", TRUE))) { + return FALSE; + } + + identity = self->passthrough_identity; + g_object_set (G_OBJECT (identity), "silent", TRUE, "signal-handoffs", FALSE, + NULL); + + /* Set src ghostpad target */ + src = gst_element_get_static_pad (self->passthrough_identity, "src"); + if (G_UNLIKELY (!src)) { + GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), + ("Failed to get srcpad from identity")); + return FALSE; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), + src))) { + GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), + ("Failed to set srcpad target")); + gst_object_unref (src); + return FALSE; + } + gst_object_unref (src); + + sink = gst_element_get_static_pad (self->passthrough_identity, "sink"); + if (G_UNLIKELY (!sink)) { + GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), + ("Failed to get sinkpad from identity")); + return FALSE; + } + + /* Send segment to the identity. This is dropped because identity + * is not linked downstream yet */ + if (self->video_segment.format != GST_FORMAT_UNDEFINED) { + GstEvent *event1, *event2; + + _generate_update_newsegment_event (&self->video_segment, &event1, &event2); + GST_DEBUG_OBJECT (self, + "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT, + event1->structure); + GST_DEBUG_OBJECT (self, + "Pushing video update newsegment event: %" GST_PTR_FORMAT, + event2->structure); + gst_pad_send_event (sink, event1); + gst_pad_send_event (sink, event2); + } + + /* Link sink ghostpads to identity */ + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->video_sinkpad), sink))) { + GST_ELEMENT_ERROR (self, CORE, PAD, (NULL), + ("Failed to set video sinkpad target")); + gst_object_unref (sink); + return FALSE; + } + gst_object_unref (sink); + + GST_DEBUG_OBJECT (self, "Video passthrough setup successfully"); + +out: + /* Unblock pads */ + gst_pad_set_blocked_async_full (self->video_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + if (self->subtitle_sink_blocked) + gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + return TRUE; +} + +/* Must be called with subtitleoverlay lock! */ +static void +gst_subtitle_overlay_set_fps (GstSubtitleOverlay * self) +{ + GObjectClass *gobject_class; + GParamSpec *pspec; + + if (!self->parser || self->fps_d == 0) + return; + + gobject_class = G_OBJECT_GET_CLASS (self->parser); + pspec = g_object_class_find_property (gobject_class, "video-fps"); + if (!pspec || pspec->value_type != GST_TYPE_FRACTION) + return; + + GST_DEBUG_OBJECT (self, "Updating video-fps property in parser"); + g_object_set (self->parser, "video-fps", self->fps_n, self->fps_d, NULL); +} + +static const gchar * +_get_silent_property (GstElement * element, gboolean * invert) +{ + static const struct + { + const gchar *name; + gboolean invert; + } properties[] = { { + "silent", FALSE}, { + "enable", TRUE}}; + GObjectClass *gobject_class; + GParamSpec *pspec; + guint i; + + gobject_class = G_OBJECT_GET_CLASS (element); + + for (i = 0; i < G_N_ELEMENTS (properties); i++) { + pspec = g_object_class_find_property (gobject_class, properties[i].name); + if (pspec && pspec->value_type == G_TYPE_BOOLEAN) { + *invert = properties[i].invert; + return properties[i].name; + } + } + return NULL; +} + +static gboolean +_has_subtitle_encoding_property (GstElement * element) +{ + GParamSpec *pspec; + + pspec = + g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "subtitle-encoding"); + return (pspec && pspec->value_type == G_TYPE_STRING); +} + +static gboolean +_has_font_desc_property (GstElement * element) +{ + GParamSpec *pspec; + + pspec = + g_object_class_find_property (G_OBJECT_GET_CLASS (element), "font-desc"); + return (pspec && pspec->value_type == G_TYPE_STRING); +} + +static void +_pad_blocked_cb (GstPad * pad, gboolean blocked, gpointer user_data) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (user_data); + GstCaps *subcaps; + GList *l, *factories = NULL; + + GST_DEBUG_OBJECT (pad, "Pad blocked: %d", blocked); + + GST_SUBTITLE_OVERLAY_LOCK (self); + if (pad == self->video_block_pad) + self->video_sink_blocked = blocked; + else if (pad == self->subtitle_block_pad) + self->subtitle_sink_blocked = blocked; + + if (!blocked) { + GST_SUBTITLE_OVERLAY_UNLOCK (self); + return; + } + + /* Now either both or the video sink are blocked */ + + /* Get current subtitle caps */ + subcaps = self->subcaps; + if (!subcaps) { + GstPad *peer; + + peer = gst_pad_get_peer (self->subtitle_sinkpad); + if (peer) { + subcaps = gst_pad_get_negotiated_caps (peer); + if (!subcaps) { + subcaps = gst_pad_get_caps_reffed (peer); + if (!gst_caps_is_fixed (subcaps)) { + gst_caps_unref (subcaps); + subcaps = NULL; + } + } + gst_object_unref (peer); + } + gst_caps_replace (&self->subcaps, subcaps); + if (subcaps) + gst_caps_unref (subcaps); + } + GST_DEBUG_OBJECT (self, "Current subtitle caps: %" GST_PTR_FORMAT, subcaps); + + /* If there are no subcaps but the subtitle sink is blocked upstream + * must behave wrong as there are no fixed caps set for the first + * buffer or in-order event */ + if (G_UNLIKELY (!subcaps && self->subtitle_sink_blocked)) { + GST_ELEMENT_WARNING (self, CORE, NEGOTIATION, (NULL), + ("Subtitle sink is blocked but we have no subtitle caps")); + subcaps = NULL; + } + + if (self->subtitle_error || (self->silent && !self->silent_property)) { + _setup_passthrough (self); + do_async_done (self); + goto out; + } + + /* Now do something with the caps */ + if (subcaps && !self->subtitle_flush) { + GstPad *target = + gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad)); + + if (target && gst_pad_accept_caps (target, subcaps)) { + GST_DEBUG_OBJECT (pad, "Target accepts caps"); + + gst_object_unref (target); + + /* Unblock pads */ + gst_pad_set_blocked_async_full (self->video_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + if (self->subtitle_sink_blocked) + gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + goto out; + } else if (target) { + gst_object_unref (target); + } + } + + if (self->subtitle_sink_blocked && !self->video_sink_blocked) { + GST_DEBUG_OBJECT (self, "Subtitle sink blocked but video not blocked"); + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + goto out; + } + + self->subtitle_flush = FALSE; + + /* Find our factories */ + g_mutex_lock (self->factories_lock); + gst_subtitle_overlay_update_factory_list (self); + if (subcaps) { + factories = gst_filter_run (self->factories, + (GstFilterFunc) _filter_factories_for_caps, FALSE, subcaps); + if (!factories) { + GstMessage *msg; + + msg = gst_missing_decoder_message_new (GST_ELEMENT_CAST (self), subcaps); + gst_element_post_message (GST_ELEMENT_CAST (self), msg); + GST_ELEMENT_WARNING (self, CORE, MISSING_PLUGIN, (NULL), + ("no suitable subtitle plugin found")); + subcaps = NULL; + self->subtitle_error = TRUE; + } + } + g_mutex_unlock (self->factories_lock); + + if (!subcaps) { + _setup_passthrough (self); + do_async_done (self); + goto out; + } + + /* Now the interesting parts are done: subtitle overlaying! */ + + /* Sort the factories by rank */ + factories = g_list_sort (factories, (GCompareFunc) _sort_by_ranks); + + for (l = factories; l; l = l->next) { + GstElementFactory *factory = l->data; + gboolean is_renderer = _is_renderer (factory); + GstElement *element; + GstPad *sink, *src; + + /* Unlink & destroy everything */ + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->video_sinkpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad), + NULL); + self->silent_property = NULL; + _remove_element (self, &self->post_colorspace); + _remove_element (self, &self->overlay); + _remove_element (self, &self->parser); + _remove_element (self, &self->renderer); + _remove_element (self, &self->pre_colorspace); + _remove_element (self, &self->passthrough_identity); + + GST_DEBUG_OBJECT (self, "Trying factory '%s'", + GST_STR_NULL (gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST + (factory)))); + + if (G_UNLIKELY ((is_renderer + && !_create_element (self, &self->renderer, NULL, factory, + "renderer", FALSE)) || (!is_renderer + && !_create_element (self, &self->parser, NULL, factory, + "parser", FALSE)))) + continue; + + element = is_renderer ? self->renderer : self->parser; + + /* If this is a parser, create textoverlay and link video and the parser to it + * Else link the renderer to the output colorspace */ + if (!is_renderer) { + GstElement *overlay; + GstPad *video_peer; + + /* Try to get the latest video framerate */ + video_peer = gst_pad_get_peer (self->video_sinkpad); + if (video_peer) { + GstCaps *video_caps; + gint fps_n, fps_d; + + video_caps = gst_pad_get_negotiated_caps (video_peer); + if (!video_caps) { + video_caps = gst_pad_get_caps_reffed (video_peer); + if (!gst_caps_is_fixed (video_caps)) { + gst_caps_unref (video_caps); + video_caps = NULL; + } + } + + if (video_caps + && gst_video_parse_caps_framerate (video_caps, &fps_n, &fps_d)) { + if (self->fps_n != fps_n || self->fps_d != fps_d) { + GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d); + self->fps_n = fps_n; + self->fps_d = fps_d; + } + } + + if (video_caps) + gst_caps_unref (video_caps); + gst_object_unref (video_peer); + } + + if (_has_subtitle_encoding_property (self->parser)) + g_object_set (self->parser, "subtitle-encoding", self->encoding, NULL); + + /* Try to set video fps on the parser */ + gst_subtitle_overlay_set_fps (self); + + /* First link everything internally */ + if (G_UNLIKELY (!_create_element (self, &self->overlay, "textoverlay", + NULL, "overlay", FALSE))) { + continue; + } + overlay = self->overlay; + self->silent_property = "silent"; + self->silent_property_invert = FALSE; + + /* Set some properties */ + g_object_set (G_OBJECT (overlay), + "halign", "center", "valign", "bottom", "wait-text", FALSE, NULL); + if (self->font_desc) + g_object_set (G_OBJECT (overlay), "font-desc", self->font_desc, NULL); + + src = gst_element_get_static_pad (element, "src"); + if (G_UNLIKELY (!src)) { + continue; + } + + sink = gst_element_get_static_pad (overlay, "text_sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get text sink from textoverlay"); + gst_object_unref (src); + continue; + } + + if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { + GST_WARNING_OBJECT (self, "Can't link parser to textoverlay"); + gst_object_unref (sink); + gst_object_unref (src); + continue; + } + gst_object_unref (sink); + gst_object_unref (src); + + if (G_UNLIKELY (!_create_element (self, &self->post_colorspace, + "ffmpegcolorspace", NULL, "post-colorspace", FALSE))) { + continue; + } + + src = gst_element_get_static_pad (overlay, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get src pad from overlay"); + continue; + } + + sink = gst_element_get_static_pad (self->post_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + gst_object_unref (src); + continue; + } + + if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { + GST_WARNING_OBJECT (self, "Can't link overlay with ffmpegcolorspace"); + gst_object_unref (src); + gst_object_unref (sink); + continue; + } + gst_object_unref (src); + gst_object_unref (sink); + + if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace, + "ffmpegcolorspace", NULL, "pre-colorspace", FALSE))) { + continue; + } + + sink = gst_element_get_static_pad (overlay, "video_sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get video sink from textoverlay"); + continue; + } + + src = gst_element_get_static_pad (self->pre_colorspace, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get srcpad from ffmpegcolorspace"); + gst_object_unref (sink); + continue; + } + + if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { + GST_WARNING_OBJECT (self, "Can't link ffmpegcolorspace to textoverlay"); + gst_object_unref (src); + gst_object_unref (sink); + continue; + } + gst_object_unref (src); + gst_object_unref (sink); + + /* Set src ghostpad target */ + src = gst_element_get_static_pad (self->post_colorspace, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get src pad from ffmpegcolorspace"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->srcpad), src))) { + GST_WARNING_OBJECT (self, "Can't set srcpad target"); + gst_object_unref (src); + continue; + } + gst_object_unref (src); + + /* Send segments to the parser/overlay if necessary. These are not sent + * outside this element because of the proxy pad event function */ + if (self->video_segment.format != GST_FORMAT_UNDEFINED) { + GstEvent *event1, *event2; + + sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + continue; + } + + _generate_update_newsegment_event (&self->video_segment, &event1, + &event2); + GST_DEBUG_OBJECT (self, + "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT, + event1->structure); + GST_DEBUG_OBJECT (self, + "Pushing video update newsegment event: %" GST_PTR_FORMAT, + event2->structure); + gst_pad_send_event (sink, event1); + gst_pad_send_event (sink, event2); + + gst_object_unref (sink); + } + + if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) { + GstEvent *event1, *event2; + + sink = gst_element_get_static_pad (element, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Failed to get subpad"); + continue; + } + + _generate_update_newsegment_event (&self->subtitle_segment, &event1, + &event2); + GST_DEBUG_OBJECT (self, + "Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT, + event1->structure); + GST_DEBUG_OBJECT (self, + "Pushing subtitle update newsegment event: %" GST_PTR_FORMAT, + event2->structure); + gst_pad_send_event (sink, event1); + gst_pad_send_event (sink, event2); + + gst_object_unref (sink); + } + + /* Set the sink ghostpad targets */ + sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->video_sinkpad), sink))) { + GST_WARNING_OBJECT (self, "Can't set video sinkpad target"); + gst_object_unref (sink); + continue; + } + gst_object_unref (sink); + + /* Link subtitle identity to subtitle pad of our element */ + sink = gst_element_get_static_pad (element, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Failed to get subpad"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->subtitle_sinkpad), sink))) { + GST_WARNING_OBJECT (self, "Failed to set subtitle sink target"); + gst_object_unref (sink); + continue; + } + gst_object_unref (sink); + } else { + const gchar *name = + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (factory)); + + if (strcmp (name, "textoverlay") == 0) { + /* Set some textoverlay specific properties */ + g_object_set (G_OBJECT (element), + "halign", "center", "valign", "bottom", "wait-text", FALSE, NULL); + if (self->font_desc) + g_object_set (G_OBJECT (element), "font-desc", self->font_desc, NULL); + self->silent_property = "silent"; + self->silent_property_invert = FALSE; + } else { + self->silent_property = + _get_silent_property (element, &self->silent_property_invert); + if (_has_subtitle_encoding_property (self->renderer)) + g_object_set (self->renderer, "subtitle-encoding", self->encoding, + NULL); + if (_has_font_desc_property (self->renderer)) + g_object_set (self->renderer, "font-desc", self->font_desc, NULL); + } + + /* First link everything internally */ + if (G_UNLIKELY (!_create_element (self, &self->post_colorspace, + "ffmpegcolorspace", NULL, "post-colorspace", FALSE))) { + continue; + } + + src = gst_element_get_static_pad (element, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get src pad from renderer"); + continue; + } + + sink = gst_element_get_static_pad (self->post_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + gst_object_unref (src); + continue; + } + + if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { + GST_WARNING_OBJECT (self, "Can't link renderer with ffmpegcolorspace"); + gst_object_unref (src); + gst_object_unref (sink); + continue; + } + gst_object_unref (src); + gst_object_unref (sink); + + if (G_UNLIKELY (!_create_element (self, &self->pre_colorspace, + "ffmpegcolorspace", NULL, "pre-colorspace", FALSE))) { + continue; + } + + sink = _get_video_pad (element); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get video sink from renderer"); + continue; + } + + src = gst_element_get_static_pad (self->pre_colorspace, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get srcpad from ffmpegcolorspace"); + gst_object_unref (sink); + continue; + } + + if (G_UNLIKELY (gst_pad_link (src, sink) != GST_PAD_LINK_OK)) { + GST_WARNING_OBJECT (self, "Can't link ffmpegcolorspace to renderer"); + gst_object_unref (src); + gst_object_unref (sink); + continue; + } + gst_object_unref (src); + gst_object_unref (sink); + + /* Set src ghostpad target */ + src = gst_element_get_static_pad (self->post_colorspace, "src"); + if (G_UNLIKELY (!src)) { + GST_WARNING_OBJECT (self, "Can't get src pad from ffmpegcolorspace"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->srcpad), src))) { + GST_WARNING_OBJECT (self, "Can't set srcpad target"); + gst_object_unref (src); + continue; + } + gst_object_unref (src); + + /* Send segments to the renderer if necessary. These are not sent + * outside this element because of the proxy pad event handler */ + if (self->video_segment.format != GST_FORMAT_UNDEFINED) { + GstEvent *event1, *event2; + + sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + continue; + } + + _generate_update_newsegment_event (&self->video_segment, &event1, + &event2); + GST_DEBUG_OBJECT (self, + "Pushing video accumulate newsegment event: %" GST_PTR_FORMAT, + event1->structure); + GST_DEBUG_OBJECT (self, + "Pushing video update newsegment event: %" GST_PTR_FORMAT, + event2->structure); + gst_pad_send_event (sink, event1); + gst_pad_send_event (sink, event2); + gst_object_unref (sink); + } + + if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED) { + GstEvent *event1, *event2; + + sink = _get_sub_pad (element); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Failed to get subpad"); + continue; + } + + _generate_update_newsegment_event (&self->subtitle_segment, &event1, + &event2); + GST_DEBUG_OBJECT (self, + "Pushing subtitle accumulate newsegment event: %" GST_PTR_FORMAT, + event1->structure); + GST_DEBUG_OBJECT (self, + "Pushing subtitle update newsegment event: %" GST_PTR_FORMAT, + event2->structure); + gst_pad_send_event (sink, event1); + gst_pad_send_event (sink, event2); + gst_object_unref (sink); + } + + /* Set the sink ghostpad targets */ + sink = gst_element_get_static_pad (self->pre_colorspace, "sink"); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Can't get sink pad from ffmpegcolorspace"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->video_sinkpad), sink))) { + GST_WARNING_OBJECT (self, "Can't set video sinkpad target"); + gst_object_unref (sink); + continue; + } + gst_object_unref (sink); + + sink = _get_sub_pad (element); + if (G_UNLIKELY (!sink)) { + GST_WARNING_OBJECT (self, "Failed to get subpad"); + continue; + } + + if (G_UNLIKELY (!gst_ghost_pad_set_target (GST_GHOST_PAD_CAST + (self->subtitle_sinkpad), sink))) { + GST_WARNING_OBJECT (self, "Failed to set subtitle sink target"); + gst_object_unref (sink); + continue; + } + gst_object_unref (sink); + } + + break; + } + + if (G_UNLIKELY (l == NULL)) { + GST_ELEMENT_WARNING (self, CORE, FAILED, (NULL), + ("Failed to find any usable factories")); + self->subtitle_error = TRUE; + _setup_passthrough (self); + do_async_done (self); + } else { + GST_DEBUG_OBJECT (self, "Everything worked, unblocking pads"); + gst_pad_set_blocked_async_full (self->video_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + gst_pad_set_blocked_async_full (self->subtitle_block_pad, FALSE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + do_async_done (self); + } + +out: + if (factories) + gst_plugin_feature_list_free (factories); + GST_SUBTITLE_OVERLAY_UNLOCK (self); +} + +static GstStateChangeReturn +gst_subtitle_overlay_change_state (GstElement * element, + GstStateChange transition) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (element); + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + GST_DEBUG_OBJECT (self, "State change NULL->READY"); + g_mutex_lock (self->factories_lock); + if (G_UNLIKELY (!gst_subtitle_overlay_update_factory_list (self))) { + g_mutex_unlock (self->factories_lock); + return GST_STATE_CHANGE_FAILURE; + } + g_mutex_unlock (self->factories_lock); + + GST_SUBTITLE_OVERLAY_LOCK (self); + /* Set the internal pads to blocking */ + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG_OBJECT (self, "State change READY->PAUSED"); + gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED); + gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED); + + self->fps_n = self->fps_d = 0; + + self->subtitle_flush = FALSE; + self->subtitle_error = FALSE; + + self->downstream_chain_error = FALSE; + + do_async_start (self); + ret = GST_STATE_CHANGE_ASYNC; + + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + GST_DEBUG_OBJECT (self, "State change PAUSED->PLAYING"); + default: + break; + } + + { + GstStateChangeReturn bret; + + bret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + GST_DEBUG_OBJECT (self, "Base class state changed returned: %d", bret); + if (G_UNLIKELY (bret == GST_STATE_CHANGE_FAILURE)) + return ret; + else if (bret == GST_STATE_CHANGE_ASYNC) + ret = bret; + else if (G_UNLIKELY (bret == GST_STATE_CHANGE_NO_PREROLL)) { + do_async_done (self); + ret = bret; + } + } + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + GST_DEBUG_OBJECT (self, "State change PLAYING->PAUSED"); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG_OBJECT (self, "State change PAUSED->READY"); + do_async_done (self); + + break; + case GST_STATE_CHANGE_READY_TO_NULL:{ + GstPad *pad; + + GST_DEBUG_OBJECT (self, "State change READY->NULL"); + + GST_SUBTITLE_OVERLAY_LOCK (self); + gst_caps_replace (&self->subcaps, NULL); + + /* Unlink ghost pads */ + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->video_sinkpad), NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad), + NULL); + + /* Unblock pads */ + if (self->video_block_pad) { + pad = self->video_block_pad; + gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb, + gst_object_ref (self), (GDestroyNotify) gst_object_unref); + } + + if (self->subtitle_block_pad) { + pad = self->subtitle_block_pad; + gst_pad_set_blocked_async_full (pad, FALSE, _pad_blocked_cb, + gst_object_ref (self), (GDestroyNotify) gst_object_unref); + } + + /* Remove elements */ + self->silent_property = NULL; + _remove_element (self, &self->post_colorspace); + _remove_element (self, &self->overlay); + _remove_element (self, &self->parser); + _remove_element (self, &self->renderer); + _remove_element (self, &self->pre_colorspace); + _remove_element (self, &self->passthrough_identity); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + break; + } + default: + break; + } + + return ret; +} + +static void +gst_subtitle_overlay_handle_message (GstBin * bin, GstMessage * message) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (bin); + + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ERROR) { + GstObject *src = GST_MESSAGE_SRC (message); + + /* Convert error messages from the subtitle pipeline to + * warnings and switch to passthrough mode */ + if (src && ( + (self->overlay + && gst_object_has_ancestor (src, + GST_OBJECT_CAST (self->overlay))) || (self->parser + && gst_object_has_ancestor (src, + GST_OBJECT_CAST (self->parser))) || (self->renderer + && gst_object_has_ancestor (src, + GST_OBJECT_CAST (self->renderer))))) { + GError *err = NULL; + gchar *debug = NULL; + GstMessage *wmsg; + + gst_message_parse_error (message, &err, &debug); + GST_DEBUG_OBJECT (self, + "Got error message from subtitle element %s: %s (%s)", + GST_MESSAGE_SRC_NAME (message), GST_STR_NULL (err->message), + GST_STR_NULL (debug)); + + wmsg = gst_message_new_warning (src, err, debug); + gst_message_unref (message); + g_error_free (err); + g_free (debug); + message = wmsg; + + GST_SUBTITLE_OVERLAY_LOCK (self); + self->subtitle_error = TRUE; + + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + } + } + + GST_BIN_CLASS (parent_class)->handle_message (bin, message); +} + +static void +gst_subtitle_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, self->silent); + break; + case PROP_FONT_DESC: + GST_SUBTITLE_OVERLAY_LOCK (self); + g_value_set_string (value, self->font_desc); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + case PROP_SUBTITLE_ENCODING: + GST_SUBTITLE_OVERLAY_LOCK (self); + g_value_set_string (value, self->encoding); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_subtitle_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY_CAST (object); + + switch (prop_id) { + case PROP_SILENT: + GST_SUBTITLE_OVERLAY_LOCK (self); + self->silent = g_value_get_boolean (value); + if (self->silent_property) { + gboolean silent = self->silent; + + if (self->silent_property_invert) + silent = !silent; + + if (self->overlay) + g_object_set (self->overlay, self->silent_property, silent, NULL); + else if (self->renderer) + g_object_set (self->renderer, self->silent_property, silent, NULL); + } else { + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + } + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + case PROP_FONT_DESC: + GST_SUBTITLE_OVERLAY_LOCK (self); + g_free (self->font_desc); + self->font_desc = g_value_dup_string (value); + if (self->overlay) + g_object_set (self->overlay, "font-desc", self->font_desc, NULL); + else if (self->renderer && _has_font_desc_property (self->renderer)) + g_object_set (self->renderer, "font-desc", self->font_desc, NULL); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + case PROP_SUBTITLE_ENCODING: + GST_SUBTITLE_OVERLAY_LOCK (self); + g_free (self->encoding); + self->encoding = g_value_dup_string (value); + if (self->renderer && _has_subtitle_encoding_property (self->renderer)) + g_object_set (self->renderer, "subtitle-encoding", self->encoding, + NULL); + if (self->parser && _has_subtitle_encoding_property (self->parser)) + g_object_set (self->parser, "subtitle-encoding", self->encoding, NULL); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_subtitle_overlay_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&video_sinktemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&subtitle_sinktemplate)); + + gst_element_class_set_details_simple (gstelement_class, "Subtitle Overlay", + "Video/Overlay/Subtitle", + "Overlays a video stream with subtitles", + "Sebastian Dröge "); +} + +static void +gst_subtitle_overlay_class_init (GstSubtitleOverlayClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *element_class = (GstElementClass *) klass; + GstBinClass *bin_class = (GstBinClass *) klass; + + gobject_class->finalize = gst_subtitle_overlay_finalize; + gobject_class->set_property = gst_subtitle_overlay_set_property; + gobject_class->get_property = gst_subtitle_overlay_get_property; + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", + "Silent", + "Whether to show subtitles", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_FONT_DESC, + g_param_spec_string ("font-desc", + "Subtitle font description", + "Pango font description of font " + "to be used for subtitle rendering", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_change_state); + + bin_class->handle_message = + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_handle_message); +} + +static GstFlowReturn +gst_subtitle_overlay_src_proxy_chain (GstPad * proxypad, GstBuffer * buffer) +{ + GstPad *ghostpad; + GstSubtitleOverlay *self; + GstFlowReturn ret; + + ghostpad = GST_PAD_CAST (gst_pad_get_parent (proxypad)); + if (G_UNLIKELY (!ghostpad)) { + gst_buffer_unref (buffer); + return GST_FLOW_ERROR; + } + self = GST_SUBTITLE_OVERLAY_CAST (gst_pad_get_parent (ghostpad)); + if (G_UNLIKELY (!self || self->srcpad != ghostpad)) { + gst_buffer_unref (buffer); + gst_object_unref (ghostpad); + return GST_FLOW_ERROR; + } + + ret = self->src_proxy_chain (proxypad, buffer); + + if (IS_VIDEO_CHAIN_IGNORE_ERROR (ret)) { + GST_ERROR_OBJECT (self, "Downstream chain error: %s", + gst_flow_get_name (ret)); + self->downstream_chain_error = TRUE; + } + + gst_object_unref (self); + gst_object_unref (ghostpad); + + return ret; +} + +static gboolean +gst_subtitle_overlay_src_proxy_event (GstPad * proxypad, GstEvent * event) +{ + GstPad *ghostpad = NULL; + GstSubtitleOverlay *self = NULL; + gboolean ret = FALSE; + const GstStructure *s; + + ghostpad = GST_PAD_CAST (gst_pad_get_parent (proxypad)); + if (G_UNLIKELY (!ghostpad)) + goto out; + self = GST_SUBTITLE_OVERLAY_CAST (gst_pad_get_parent (ghostpad)); + if (G_UNLIKELY (!self || self->srcpad != ghostpad)) + goto out; + + s = gst_event_get_structure (event); + if (s && gst_structure_id_has_field (s, _subtitle_overlay_event_marker_id)) { + GST_DEBUG_OBJECT (ghostpad, "Dropping event with marker: %" GST_PTR_FORMAT, + event->structure); + gst_event_unref (event); + event = NULL; + ret = TRUE; + } else { + ret = self->src_proxy_event (proxypad, event); + event = NULL; + } + +out: + if (event) + gst_event_unref (event); + if (self) + gst_object_unref (self); + if (ghostpad) + gst_object_unref (ghostpad); + return ret; +} + +static gboolean +gst_subtitle_overlay_video_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret = TRUE; + gint fps_n, fps_d; + + GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps); + + if (!gst_video_parse_caps_framerate (caps, &fps_n, &fps_d)) { + GST_ERROR_OBJECT (pad, "Failed to parse framerate from caps"); + ret = FALSE; + goto out; + } + + GST_SUBTITLE_OVERLAY_LOCK (self); + if (self->fps_n != fps_n || self->fps_d != fps_d) { + GST_DEBUG_OBJECT (self, "New video fps: %d/%d", fps_n, fps_d); + self->fps_n = fps_n; + self->fps_d = fps_d; + gst_subtitle_overlay_set_fps (self); + } + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + ret = self->video_sink_setcaps (pad, caps); + +out: + gst_object_unref (self); + return ret; +} + +static gboolean +gst_subtitle_overlay_video_sink_event (GstPad * pad, GstEvent * event) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret; + + if (GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + GST_DEBUG_OBJECT (pad, + "Resetting video segment because of flush-stop event"); + gst_segment_init (&self->video_segment, GST_FORMAT_UNDEFINED); + self->fps_n = self->fps_d = 0; + } + + ret = self->video_sink_event (pad, gst_event_ref (event)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gboolean update; + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, position; + + GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, + event->structure); + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + + if (format != GST_FORMAT_TIME) { + GST_ERROR_OBJECT (pad, "Newsegment event in non-time format: %s", + gst_format_get_name (format)); + gst_object_unref (event); + gst_object_unref (self); + return FALSE; + } + + GST_DEBUG_OBJECT (pad, "Old video segment: %" GST_SEGMENT_FORMAT, + &self->video_segment); + gst_segment_set_newsegment_full (&self->video_segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "New video segment: %" GST_SEGMENT_FORMAT, + &self->video_segment); + } + + gst_event_unref (event); + gst_object_unref (self); + return ret; +} + +static GstFlowReturn +gst_subtitle_overlay_video_sink_chain (GstPad * pad, GstBuffer * buffer) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (GST_PAD_PARENT (pad)); + GstFlowReturn ret = self->video_sink_chain (pad, buffer); + + if (G_UNLIKELY (self->downstream_chain_error) || self->passthrough_identity) { + return ret; + } else if (IS_VIDEO_CHAIN_IGNORE_ERROR (ret)) { + GST_DEBUG_OBJECT (self, "Subtitle renderer produced chain error: %s", + gst_flow_get_name (ret)); + GST_SUBTITLE_OVERLAY_LOCK (self); + self->subtitle_error = TRUE; + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + return GST_FLOW_OK; + } + + return ret; +} + +static GstFlowReturn +gst_subtitle_overlay_subtitle_sink_chain (GstPad * pad, GstBuffer * buffer) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (GST_PAD_PARENT (pad)); + + if (self->subtitle_error) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } else { + GstFlowReturn ret = self->subtitle_sink_chain (pad, buffer); + + if (IS_SUBTITLE_CHAIN_IGNORE_ERROR (ret)) { + GST_DEBUG_OBJECT (self, "Subtitle chain error: %s", + gst_flow_get_name (ret)); + GST_SUBTITLE_OVERLAY_LOCK (self); + self->subtitle_error = TRUE; + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + return GST_FLOW_OK; + } + + return ret; + } +} + +static GstCaps * +gst_subtitle_overlay_subtitle_sink_getcaps (GstPad * pad) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + GstCaps *ret; + + g_mutex_lock (self->factories_lock); + if (G_UNLIKELY (!gst_subtitle_overlay_update_factory_list (self))) + ret = GST_CAPS_NONE; + else + ret = gst_caps_ref (self->factory_caps); + g_mutex_unlock (self->factories_lock); + + GST_DEBUG_OBJECT (pad, "Returning subtitle caps %" GST_PTR_FORMAT, ret); + + gst_object_unref (self); + + return ret; +} + +static gboolean +gst_subtitle_overlay_subtitle_sink_acceptcaps (GstPad * pad, GstCaps * caps) +{ + GstCaps *othercaps = gst_subtitle_overlay_subtitle_sink_getcaps (pad); + gboolean ret = gst_caps_can_intersect (caps, othercaps); + + gst_caps_unref (othercaps); + + return ret; +} + +static gboolean +gst_subtitle_overlay_subtitle_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret = TRUE; + GstPad *target = NULL;; + + GST_DEBUG_OBJECT (pad, "Setting caps: %" GST_PTR_FORMAT, caps); + + target = + gst_ghost_pad_get_target (GST_GHOST_PAD_CAST (self->subtitle_sinkpad)); + + GST_SUBTITLE_OVERLAY_LOCK (self); + gst_caps_replace (&self->subcaps, caps); + + if (target && gst_pad_accept_caps (target, caps)) { + GST_DEBUG_OBJECT (pad, "Target accepts caps"); + ret = self->subtitle_sink_setcaps (pad, caps); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + goto out; + } + + GST_DEBUG_OBJECT (pad, "Target did not accept caps"); + + self->subtitle_error = FALSE; + + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + +out: + if (target) + gst_object_unref (target); + gst_object_unref (self); + return ret; +} + +static GstPadLinkReturn +gst_subtitle_overlay_subtitle_sink_link (GstPad * pad, GstPad * peer) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + GstPadLinkReturn ret; + GstCaps *caps; + + GST_DEBUG_OBJECT (pad, "Linking pad to peer %" GST_PTR_FORMAT, peer); + + caps = gst_pad_get_negotiated_caps (peer); + if (!caps) { + caps = gst_pad_get_caps_reffed (peer); + if (!gst_caps_is_fixed (caps)) { + gst_caps_unref (caps); + caps = NULL; + } + } + + if (caps) { + GST_SUBTITLE_OVERLAY_LOCK (self); + GST_DEBUG_OBJECT (pad, "Have fixed peer caps: %" GST_PTR_FORMAT, caps); + gst_caps_replace (&self->subcaps, caps); + + self->subtitle_error = FALSE; + + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + gst_caps_unref (caps); + } + + ret = self->subtitle_sink_link (pad, peer); + + gst_object_unref (self); + return ret; +} + +static void +gst_subtitle_overlay_subtitle_sink_unlink (GstPad * pad) +{ + GstSubtitleOverlay *self = + GST_SUBTITLE_OVERLAY (gst_object_ref (GST_PAD_PARENT (pad))); + + /* FIXME: Can't use gst_pad_get_parent() here because this is called with + * the object lock from state changes + */ + + GST_DEBUG_OBJECT (pad, "Pad unlinking"); + gst_caps_replace (&self->subcaps, NULL); + + self->subtitle_sink_unlink (pad); + + GST_SUBTITLE_OVERLAY_LOCK (self); + self->subtitle_error = FALSE; + + if (self->subtitle_block_pad) + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + + if (self->video_block_pad) + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + gst_object_unref (self); +} + +static gboolean +gst_subtitle_overlay_subtitle_sink_event (GstPad * pad, GstEvent * event) +{ + GstSubtitleOverlay *self = GST_SUBTITLE_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret; + GstFormat format; + + if (GST_EVENT_TYPE (event) == GST_EVENT_CUSTOM_DOWNSTREAM_OOB && + event->structure + && strcmp (gst_structure_get_name (event->structure), + "subtitleoverlay-flush-subtitle") == 0) { + GST_DEBUG_OBJECT (pad, "Custom subtitle flush event"); + GST_SUBTITLE_OVERLAY_LOCK (self); + self->subtitle_flush = TRUE; + self->subtitle_error = FALSE; + if (self->subtitle_block_pad) + gst_pad_set_blocked_async_full (self->subtitle_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + if (self->video_block_pad) + gst_pad_set_blocked_async_full (self->video_block_pad, TRUE, + _pad_blocked_cb, gst_object_ref (self), + (GDestroyNotify) gst_object_unref); + GST_SUBTITLE_OVERLAY_UNLOCK (self); + + gst_event_unref (event); + event = NULL; + ret = TRUE; + goto out; + } else if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gst_event_parse_new_segment_full (event, NULL, NULL, NULL, + &format, NULL, NULL, NULL); + if (self->subtitle_segment.format != GST_FORMAT_UNDEFINED && + self->subtitle_segment.format != format) { + GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", + gst_format_get_name (self->subtitle_segment.format), + gst_format_get_name (format)); + gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED); + } + } + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (pad, + "Resetting subtitle segment because of flush-stop"); + gst_segment_init (&self->subtitle_segment, GST_FORMAT_UNDEFINED); + /* fall through */ + case GST_EVENT_FLUSH_START: + case GST_EVENT_NEWSEGMENT: + case GST_EVENT_EOS: + /* Add our event marker to make sure no events from here go ever outside + * the element, they're only interesting for our internal elements */ + event = + GST_EVENT_CAST (gst_mini_object_make_writable (GST_MINI_OBJECT_CAST + (event))); + if (!event->structure) { + event->structure = + gst_structure_id_empty_new (_subtitle_overlay_event_marker_id); + gst_structure_set_parent_refcount (event->structure, + &event->mini_object.refcount); + } + gst_structure_id_set (event->structure, _subtitle_overlay_event_marker_id, + G_TYPE_BOOLEAN, TRUE, NULL); + break; + default: + break; + } + + ret = self->subtitle_sink_event (pad, gst_event_ref (event)); + + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { + gboolean update; + gdouble rate, applied_rate; + gint64 start, stop, position; + + GST_DEBUG_OBJECT (pad, "Newsegment event: %" GST_PTR_FORMAT, + event->structure); + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &position); + + GST_DEBUG_OBJECT (pad, "Old subtitle segment: %" GST_SEGMENT_FORMAT, + &self->subtitle_segment); + if (self->subtitle_segment.format != format) { + GST_DEBUG_OBJECT (pad, "Subtitle segment format changed: %s -> %s", + gst_format_get_name (self->subtitle_segment.format), + gst_format_get_name (format)); + gst_segment_init (&self->subtitle_segment, format); + } + + gst_segment_set_newsegment_full (&self->subtitle_segment, update, rate, + applied_rate, format, start, stop, position); + GST_DEBUG_OBJECT (pad, "New subtitle segment: %" GST_SEGMENT_FORMAT, + &self->subtitle_segment); + } + gst_event_unref (event); + +out: + gst_object_unref (self); + return ret; +} + +static void +gst_subtitle_overlay_init (GstSubtitleOverlay * self, + GstSubtitleOverlayClass * klass) +{ + GstPadTemplate *templ; + GstIterator *it; + GstPad *proxypad = NULL; + + self->lock = g_mutex_new (); + self->factories_lock = g_mutex_new (); + + templ = gst_static_pad_template_get (&srctemplate); + self->srcpad = gst_ghost_pad_new_no_target_from_template ("src", templ); + it = gst_pad_iterate_internal_links (self->srcpad); + if (G_UNLIKELY (!it + || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK + || proxypad == NULL)) { + GST_ERROR_OBJECT (self, "Failed to get proxypad of srcpad"); + } else { + self->src_proxy_event = GST_PAD_EVENTFUNC (proxypad); + gst_pad_set_event_function (proxypad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_event)); + self->src_proxy_chain = GST_PAD_CHAINFUNC (proxypad); + gst_pad_set_chain_function (proxypad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_src_proxy_chain)); + gst_object_unref (proxypad); + } + if (it) + gst_iterator_free (it); + + gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); + + templ = gst_static_pad_template_get (&video_sinktemplate); + self->video_sinkpad = + gst_ghost_pad_new_no_target_from_template ("video_sink", templ); + self->video_sink_event = GST_PAD_EVENTFUNC (self->video_sinkpad); + gst_pad_set_event_function (self->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_event)); + self->video_sink_setcaps = GST_PAD_SETCAPSFUNC (self->video_sinkpad); + gst_pad_set_setcaps_function (self->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_setcaps)); + self->video_sink_chain = GST_PAD_CHAINFUNC (self->video_sinkpad); + gst_pad_set_chain_function (self->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_video_sink_chain)); + + proxypad = NULL; + it = gst_pad_iterate_internal_links (self->video_sinkpad); + if (G_UNLIKELY (!it + || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK + || proxypad == NULL)) { + GST_ERROR_OBJECT (self, + "Failed to get internally linked pad from video sinkpad"); + } + if (it) + gst_iterator_free (it); + self->video_block_pad = proxypad; + gst_element_add_pad (GST_ELEMENT_CAST (self), self->video_sinkpad); + + templ = gst_static_pad_template_get (&subtitle_sinktemplate); + self->subtitle_sinkpad = + gst_ghost_pad_new_no_target_from_template ("subtitle_sink", templ); + self->subtitle_sink_link = GST_PAD_LINKFUNC (self->subtitle_sinkpad); + gst_pad_set_link_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_link)); + self->subtitle_sink_unlink = GST_PAD_UNLINKFUNC (self->subtitle_sinkpad); + gst_pad_set_unlink_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_unlink)); + self->subtitle_sink_event = GST_PAD_EVENTFUNC (self->subtitle_sinkpad); + gst_pad_set_event_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_event)); + self->subtitle_sink_setcaps = GST_PAD_SETCAPSFUNC (self->subtitle_sinkpad); + gst_pad_set_setcaps_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_setcaps)); + self->subtitle_sink_chain = GST_PAD_CHAINFUNC (self->subtitle_sinkpad); + gst_pad_set_chain_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_chain)); + gst_pad_set_getcaps_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_getcaps)); + gst_pad_set_acceptcaps_function (self->subtitle_sinkpad, + GST_DEBUG_FUNCPTR (gst_subtitle_overlay_subtitle_sink_acceptcaps)); + gst_pad_set_bufferalloc_function (self->subtitle_sinkpad, NULL); + + proxypad = NULL; + it = gst_pad_iterate_internal_links (self->subtitle_sinkpad); + if (G_UNLIKELY (!it + || gst_iterator_next (it, (gpointer) & proxypad) != GST_ITERATOR_OK + || proxypad == NULL)) { + GST_ERROR_OBJECT (self, + "Failed to get internally linked pad from subtitle sinkpad"); + } + if (it) + gst_iterator_free (it); + self->subtitle_block_pad = proxypad; + + gst_element_add_pad (GST_ELEMENT_CAST (self), self->subtitle_sinkpad); + + self->fps_n = 0; + self->fps_d = 0; +} + +gboolean +gst_subtitle_overlay_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (subtitle_overlay_debug, "subtitleoverlay", 0, + "Subtitle Overlay"); + + _subtitle_overlay_event_marker_id = + g_quark_from_static_string ("gst-subtitle-overlay-event-marker"); + + return gst_element_register (plugin, "subtitleoverlay", GST_RANK_NONE, + GST_TYPE_SUBTITLE_OVERLAY); +} diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.h b/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.h new file mode 100644 index 0000000..eee5c78 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gstsubtitleoverlay.h @@ -0,0 +1,129 @@ +/* GStreamer + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_SUBTITLE_OVERLAY_H__ +#define __GST_SUBTITLE_OVERLAY_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_SUBTITLE_OVERLAY \ + (gst_subtitle_overlay_get_type()) +#define GST_SUBTITLE_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SUBTITLE_OVERLAY, GstSubtitleOverlay)) +#define GST_SUBTITLE_OVERLAY_CAST(obj) \ + ((GstSubtitleOverlay *) obj) +#define GST_SUBTITLE_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SUBTITLE_OVERLAY, GstSubtitleOverlayClass)) +#define GST_IS_SUBTITLE_OVERLAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SUBTITLE_OVERLAY)) +#define GST_IS_SUBTITLE_OVERLAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SUBTITLE_OVERLAY)) + +#define GST_SUBTITLE_OVERLAY_LOCK(obj) G_STMT_START { \ + GST_LOG_OBJECT (obj, \ + "locking from thread %p", \ + g_thread_self ()); \ + g_mutex_lock (GST_SUBTITLE_OVERLAY_CAST(obj)->lock); \ + GST_LOG_OBJECT (obj, \ + "locked from thread %p", \ + g_thread_self ()); \ +} G_STMT_END + +#define GST_SUBTITLE_OVERLAY_UNLOCK(obj) G_STMT_START { \ + GST_LOG_OBJECT (obj, \ + "unlocking from thread %p", \ + g_thread_self ()); \ + g_mutex_unlock (GST_SUBTITLE_OVERLAY_CAST(obj)->lock); \ +} G_STMT_END + +typedef struct _GstSubtitleOverlay GstSubtitleOverlay; +typedef struct _GstSubtitleOverlayClass GstSubtitleOverlayClass; + +struct _GstSubtitleOverlay +{ + GstBin parent; + + gboolean silent; + gchar *font_desc; + gchar *encoding; + + /* < private > */ + gboolean do_async; + + GstPad *srcpad; + GstPadEventFunction src_proxy_event; + GstPadChainFunction src_proxy_chain; + gboolean downstream_chain_error; + + GstPad *video_sinkpad; + GstPad *video_block_pad; + GstPadSetCapsFunction video_sink_setcaps; + GstPadEventFunction video_sink_event; + GstPadChainFunction video_sink_chain; + gboolean video_sink_blocked; + GstSegment video_segment; + gint fps_n, fps_d; + + GstPad *subtitle_sinkpad; + GstPad *subtitle_block_pad; + GstPadLinkFunction subtitle_sink_link; + GstPadUnlinkFunction subtitle_sink_unlink; + GstPadEventFunction subtitle_sink_event; + GstPadChainFunction subtitle_sink_chain; + GstPadSetCapsFunction subtitle_sink_setcaps; + gboolean subtitle_sink_blocked; + GstSegment subtitle_segment; + gboolean subtitle_flush; + gboolean subtitle_error; + + GMutex *factories_lock; + GList *factories; + guint32 factories_cookie; + GstCaps *factory_caps; + + GMutex *lock; + GstCaps *subcaps; + + GstElement *passthrough_identity; + + GstElement *pre_colorspace; + GstElement *post_colorspace; + + GstElement *parser; + GstElement *overlay; + + GstElement *renderer; + + const gchar *silent_property; + gboolean silent_property_invert; +}; + +struct _GstSubtitleOverlayClass +{ + GstBinClass parent; +}; + +GType gst_subtitle_overlay_get_type (void); +gboolean gst_subtitle_overlay_plugin_init (GstPlugin * plugin); + +GstCaps *gst_subtitle_overlay_create_factory_caps (void); + +G_END_DECLS +#endif /* __GST_SUBTITLE_OVERLAY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/playback/gsturidecodebin.c b/gst-plugins-base-subtitles0.10/gst/playback/gsturidecodebin.c new file mode 100644 index 0000000..bf10583 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/playback/gsturidecodebin.c @@ -0,0 +1,2467 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-uridecodebin + * + * Decodes data from a URI into raw media. It selects a source element that can + * handle the given #GstURIDecodeBin:uri scheme and connects it to a decodebin2. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include +#include +#include + +#include "gstplay-marshal.h" +#include "gstplay-enum.h" +#include "gstrawcaps.h" + +#define GST_TYPE_URI_DECODE_BIN \ + (gst_uri_decode_bin_get_type()) +#define GST_URI_DECODE_BIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_URI_DECODE_BIN,GstURIDecodeBin)) +#define GST_URI_DECODE_BIN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_URI_DECODE_BIN,GstURIDecodeBinClass)) +#define GST_IS_URI_DECODE_BIN(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_URI_DECODE_BIN)) +#define GST_IS_URI_DECODE_BIN_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_URI_DECODE_BIN)) +#define GST_URI_DECODE_BIN_CAST(obj) ((GstURIDecodeBin *) (obj)) + +typedef struct _GstURIDecodeBin GstURIDecodeBin; +typedef struct _GstURIDecodeBinClass GstURIDecodeBinClass; + +#define GST_URI_DECODE_BIN_GET_LOCK(dec) (((GstURIDecodeBin*)(dec))->lock) +#define GST_URI_DECODE_BIN_LOCK(dec) (g_mutex_lock(GST_URI_DECODE_BIN_GET_LOCK(dec))) +#define GST_URI_DECODE_BIN_UNLOCK(dec) (g_mutex_unlock(GST_URI_DECODE_BIN_GET_LOCK(dec))) + +/** + * GstURIDecodeBin + * + * uridecodebin element struct + */ +struct _GstURIDecodeBin +{ + GstBin parent_instance; + + GMutex *lock; /* lock for constructing */ + + GMutex *factories_lock; + guint32 factories_cookie; + GList *factories; /* factories we can use for selecting elements */ + + gchar *uri; + guint connection_speed; + GstCaps *caps; + gchar *encoding; + + gboolean is_stream; + gboolean is_download; + gboolean need_queue; + guint64 buffer_duration; /* When buffering, buffer duration (ns) */ + guint buffer_size; /* When buffering, buffer size (bytes) */ + gboolean download; + gboolean use_buffering; + + GstElement *source; + GstElement *queue; + GstElement *typefind; + guint have_type_id; /* have-type signal id from typefind */ + GSList *decodebins; + GSList *pending_decodebins; + GSList *srcpads; + gint numpads; + + /* for dynamic sources */ + guint src_np_sig_id; /* new-pad signal id */ + guint src_nmp_sig_id; /* no-more-pads signal id */ + gint pending; + + gboolean async_pending; /* async-start has been emited */ + + gboolean expose_allstreams; /* Whether to expose unknow type streams or not */ + + guint64 ring_buffer_max_size; /* 0 means disabled */ +}; + +struct _GstURIDecodeBinClass +{ + GstBinClass parent_class; + + /* signal fired when we found a pad that we cannot decode */ + void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps); + + /* signal fired to know if we continue trying to decode the given caps */ + gboolean (*autoplug_continue) (GstElement * element, GstPad * pad, + GstCaps * caps); + /* signal fired to get a list of factories to try to autoplug */ + GValueArray *(*autoplug_factories) (GstElement * element, GstPad * pad, + GstCaps * caps); + /* signal fired to sort the factories */ + GValueArray *(*autoplug_sort) (GstElement * element, GstPad * pad, + GstCaps * caps, GValueArray * factories); + /* signal fired to select from the proposed list of factories */ + GstAutoplugSelectResult (*autoplug_select) (GstElement * element, + GstPad * pad, GstCaps * caps, GstElementFactory * factory); + + /* emited when all data is decoded */ + void (*drained) (GstElement * element); +}; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src%d", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +static GstStaticCaps default_raw_caps = GST_STATIC_CAPS (DEFAULT_RAW_CAPS); + +GST_DEBUG_CATEGORY_STATIC (gst_uri_decode_bin_debug); +#define GST_CAT_DEFAULT gst_uri_decode_bin_debug + +/* signals */ +enum +{ + SIGNAL_UNKNOWN_TYPE, + SIGNAL_AUTOPLUG_CONTINUE, + SIGNAL_AUTOPLUG_FACTORIES, + SIGNAL_AUTOPLUG_SELECT, + SIGNAL_DRAINED, + SIGNAL_AUTOPLUG_SORT, + SIGNAL_SOURCE_SETUP, + LAST_SIGNAL +}; + +/* properties */ +#define DEFAULT_PROP_URI NULL +#define DEFAULT_PROP_SOURCE NULL +#define DEFAULT_CONNECTION_SPEED 0 +#define DEFAULT_CAPS (gst_static_caps_get (&default_raw_caps)) +#define DEFAULT_SUBTITLE_ENCODING NULL +#define DEFAULT_BUFFER_DURATION -1 +#define DEFAULT_BUFFER_SIZE -1 +#define DEFAULT_DOWNLOAD FALSE +#define DEFAULT_USE_BUFFERING FALSE +#define DEFAULT_EXPOSE_ALL_STREAMS TRUE +#define DEFAULT_RING_BUFFER_MAX_SIZE 0 + +enum +{ + PROP_0, + PROP_URI, + PROP_SOURCE, + PROP_CONNECTION_SPEED, + PROP_CAPS, + PROP_SUBTITLE_ENCODING, + PROP_BUFFER_SIZE, + PROP_BUFFER_DURATION, + PROP_DOWNLOAD, + PROP_USE_BUFFERING, + PROP_EXPOSE_ALL_STREAMS, + PROP_RING_BUFFER_MAX_SIZE, + PROP_LAST +}; + +static guint gst_uri_decode_bin_signals[LAST_SIGNAL] = { 0 }; + +GType gst_uri_decode_bin_get_type (void); +GST_BOILERPLATE (GstURIDecodeBin, gst_uri_decode_bin, GstBin, GST_TYPE_BIN); + +static void remove_decoders (GstURIDecodeBin * bin, gboolean force); +static void gst_uri_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_uri_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_uri_decode_bin_finalize (GObject * obj); + +static void handle_message (GstBin * bin, GstMessage * msg); + +static gboolean gst_uri_decode_bin_query (GstElement * element, + GstQuery * query); +static GstStateChangeReturn gst_uri_decode_bin_change_state (GstElement * + element, GstStateChange transition); + +static void +gst_uri_decode_bin_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_set_details_simple (gstelement_class, + "URI Decoder", "Generic/Bin/Decoder", + "Autoplug and decode an URI to raw media", + "Wim Taymans "); +} + +static gboolean +_gst_boolean_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gboolean myboolean; + + myboolean = g_value_get_boolean (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boolean (return_accu, myboolean); + + /* stop emission if FALSE */ + return myboolean; +} + +static gboolean +_gst_array_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boxed (return_accu, array); + + return FALSE; +} + +static gboolean +_gst_select_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + GstAutoplugSelectResult res; + + res = g_value_get_enum (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_enum (return_accu, res); + + return FALSE; +} + +static gboolean +_gst_array_hasvalue_accumulator (GSignalInvocationHint * ihint, + GValue * return_accu, const GValue * handler_return, gpointer dummy) +{ + gpointer array; + + array = g_value_get_boxed (handler_return); + if (!(ihint->run_type & G_SIGNAL_RUN_CLEANUP)) + g_value_set_boxed (return_accu, array); + + if (array != NULL) + return FALSE; + + return TRUE; +} + +static gboolean +gst_uri_decode_bin_autoplug_continue (GstElement * element, GstPad * pad, + GstCaps * caps) +{ + /* by default we always continue */ + return TRUE; +} + +/* Must be called with factories lock! */ +static void +gst_uri_decode_bin_update_factories_list (GstURIDecodeBin * dec) +{ + if (!dec->factories || + dec->factories_cookie != + gst_default_registry_get_feature_list_cookie ()) { + if (dec->factories) + gst_plugin_feature_list_free (dec->factories); + dec->factories = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_DECODABLE, GST_RANK_MARGINAL); + dec->factories_cookie = gst_default_registry_get_feature_list_cookie (); + } +} + +static GValueArray * +gst_uri_decode_bin_autoplug_factories (GstElement * element, GstPad * pad, + GstCaps * caps) +{ + GList *list, *tmp; + GValueArray *result; + GstURIDecodeBin *dec = GST_URI_DECODE_BIN_CAST (element); + + GST_DEBUG_OBJECT (element, "finding factories"); + + /* return all compatible factories for caps */ + g_mutex_lock (dec->factories_lock); + gst_uri_decode_bin_update_factories_list (dec); + list = + gst_element_factory_list_filter (dec->factories, caps, GST_PAD_SINK, + FALSE); + g_mutex_unlock (dec->factories_lock); + + result = g_value_array_new (g_list_length (list)); + for (tmp = list; tmp; tmp = tmp->next) { + GstElementFactory *factory = GST_ELEMENT_FACTORY_CAST (tmp->data); + GValue val = { 0, }; + + g_value_init (&val, G_TYPE_OBJECT); + g_value_set_object (&val, factory); + g_value_array_append (result, &val); + g_value_unset (&val); + } + gst_plugin_feature_list_free (list); + + GST_DEBUG_OBJECT (element, "autoplug-factories returns %p", result); + + return result; +} + +static GValueArray * +gst_uri_decode_bin_autoplug_sort (GstElement * element, GstPad * pad, + GstCaps * caps, GValueArray * factories) +{ + return NULL; +} + +static GstAutoplugSelectResult +gst_uri_decode_bin_autoplug_select (GstElement * element, GstPad * pad, + GstCaps * caps, GstElementFactory * factory) +{ + GST_DEBUG_OBJECT (element, "default autoplug-select returns TRY"); + + /* Try factory. */ + return GST_AUTOPLUG_SELECT_TRY; +} + +static void +gst_uri_decode_bin_class_init (GstURIDecodeBinClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBinClass *gstbin_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbin_class = GST_BIN_CLASS (klass); + + gobject_class->set_property = gst_uri_decode_bin_set_property; + gobject_class->get_property = gst_uri_decode_bin_get_property; + gobject_class->finalize = gst_uri_decode_bin_finalize; + + g_object_class_install_property (gobject_class, PROP_URI, + g_param_spec_string ("uri", "URI", "URI to decode", + DEFAULT_PROP_URI, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SOURCE, + g_param_spec_object ("source", "Source", "Source object used", + GST_TYPE_ELEMENT, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CONNECTION_SPEED, + g_param_spec_uint ("connection-speed", "Connection Speed", + "Network connection speed in kbps (0 = unknown)", + 0, G_MAXUINT / 1000, DEFAULT_CONNECTION_SPEED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CAPS, + g_param_spec_boxed ("caps", "Caps", + "The caps on which to stop decoding. (NULL = default)", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SUBTITLE_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle encoding", + "Encoding to assume if input subtitles are not in UTF-8 encoding. " + "If not set, the GST_SUBTITLE_ENCODING environment variable will " + "be checked for an encoding to use. If that is not set either, " + "ISO-8859-15 will be assumed.", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFER_SIZE, + g_param_spec_int ("buffer-size", "Buffer size (bytes)", + "Buffer size when buffering streams (-1 default value)", + -1, G_MAXINT, DEFAULT_BUFFER_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BUFFER_DURATION, + g_param_spec_int64 ("buffer-duration", "Buffer duration (ns)", + "Buffer duration when buffering streams (-1 default value)", + -1, G_MAXINT64, DEFAULT_BUFFER_DURATION, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstURIDecodeBin::download: + * + * For certain media type, enable download buffering. + */ + g_object_class_install_property (gobject_class, PROP_DOWNLOAD, + g_param_spec_boolean ("download", "Download", + "Attempt download buffering when buffering network streams", + DEFAULT_DOWNLOAD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstURIDecodeBin::use-buffering: + * + * Emit BUFFERING messages based on low-/high-percent thresholds of the + * demuxed or parsed data. + * When download buffering is activated and used for the current media + * type, this property does nothing. Otherwise perform buffering on the + * demuxed or parsed media. + * + * Since: 0.10.26 + */ + g_object_class_install_property (gobject_class, PROP_USE_BUFFERING, + g_param_spec_boolean ("use-buffering", "Use Buffering", + "Perform buffering on demuxed/parsed media", + DEFAULT_USE_BUFFERING, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstURIDecodeBin::expose-all-streams + * + * Expose streams of unknown type. + * + * If set to %FALSE, then only the streams that can be decoded to the final + * caps (see 'caps' property) will have a pad exposed. Streams that do not + * match those caps but could have been decoded will not have decoder plugged + * in internally and will not have a pad exposed. + * + * Since: 0.10.30 + */ + g_object_class_install_property (gobject_class, PROP_EXPOSE_ALL_STREAMS, + g_param_spec_boolean ("expose-all-streams", "Expose All Streams", + "Expose all streams, including those of unknown type or that don't match the 'caps' property", + DEFAULT_EXPOSE_ALL_STREAMS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstURIDecodeBin::ring-buffer-max-size + * + * The maximum size of the ring buffer in kilobytes. If set to 0, the ring + * buffer is disabled. Default is 0. + * + * Since: 0.10.31 + */ + g_object_class_install_property (gobject_class, PROP_RING_BUFFER_MAX_SIZE, + g_param_spec_uint64 ("ring-buffer-max-size", + "Max. ring buffer size (bytes)", + "Max. amount of data in the ring buffer (bytes, 0 = ring buffer disabled)", + 0, G_MAXUINT, DEFAULT_RING_BUFFER_MAX_SIZE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstURIDecodeBin::unknown-type: + * @bin: The uridecodebin. + * @pad: the new pad containing caps that cannot be resolved to a 'final'. + * stream type. + * @caps: the #GstCaps of the pad that cannot be resolved. + * + * This signal is emitted when a pad for which there is no further possible + * decoding is added to the uridecodebin. + */ + gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = + g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, unknown_type), + NULL, NULL, gst_marshal_VOID__OBJECT_BOXED, G_TYPE_NONE, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); + + /** + * GstURIDecodeBin::autoplug-continue: + * @bin: The uridecodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps found. + * + * This signal is emitted whenever uridecodebin finds a new stream. It is + * emitted before looking for any elements that can handle that stream. + * + * + * Invocation of signal handlers stops after the first signal handler + * returns #FALSE. Signal handlers are invoked in the order they were + * connected in. + * + * + * Returns: #TRUE if you wish uridecodebin to look for elements that can + * handle the given @caps. If #FALSE, those caps will be considered as + * final and the pad will be exposed as such (see 'new-decoded-pad' + * signal). + */ + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE] = + g_signal_new ("autoplug-continue", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, + autoplug_continue), _gst_boolean_accumulator, NULL, + gst_play_marshal_BOOLEAN__OBJECT_BOXED, G_TYPE_BOOLEAN, 2, GST_TYPE_PAD, + GST_TYPE_CAPS); + + /** + * GstURIDecodeBin::autoplug-factories: + * @bin: The uridecodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps found. + * + * This function is emited when an array of possible factories for @caps on + * @pad is needed. Uridecodebin will by default return an array with all + * compatible factories, sorted by rank. + * + * If this function returns NULL, @pad will be exposed as a final caps. + * + * If this function returns an empty array, the pad will be considered as + * having an unhandled type media type. + * + * + * Only the signal handler that is connected first will ever by invoked. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: a #GValueArray* with a list of factories to try. The factories are + * by default tried in the returned order or based on the index returned by + * "autoplug-select". + */ + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES] = + g_signal_new ("autoplug-factories", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, + autoplug_factories), _gst_array_accumulator, NULL, + gst_play_marshal_BOXED__OBJECT_BOXED, G_TYPE_VALUE_ARRAY, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); + + /** + * GstURIDecodeBin::autoplug-sort: + * @bin: The uridecodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps. + * @factories: A #GValueArray of possible #GstElementFactory to use. + * + * Once decodebin2 has found the possible #GstElementFactory objects to try + * for @caps on @pad, this signal is emited. The purpose of the signal is for + * the application to perform additional sorting or filtering on the element + * factory array. + * + * The callee should copy and modify @factories or return #NULL if the + * order should not change. + * + * + * Invocation of signal handlers stops after one signal handler has + * returned something else than #NULL. Signal handlers are invoked in + * the order they were connected in. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: A new sorted array of #GstElementFactory objects. + * + * Since: 0.10.33 + */ + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SORT] = + g_signal_new ("autoplug-sort", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, autoplug_sort), + _gst_array_hasvalue_accumulator, NULL, + gst_play_marshal_BOXED__OBJECT_BOXED_BOXED, G_TYPE_VALUE_ARRAY, 3, + GST_TYPE_PAD, GST_TYPE_CAPS, G_TYPE_VALUE_ARRAY); + + /** + * GstURIDecodeBin::autoplug-select: + * @bin: The uridecodebin. + * @pad: The #GstPad. + * @caps: The #GstCaps. + * @factory: A #GstElementFactory to use. + * + * This signal is emitted once uridecodebin has found all the possible + * #GstElementFactory that can be used to handle the given @caps. For each of + * those factories, this signal is emited. + * + * The signal handler should return a #GST_TYPE_AUTOPLUG_SELECT_RESULT enum + * value indicating what decodebin2 should do next. + * + * A value of #GST_AUTOPLUG_SELECT_TRY will try to autoplug an element from + * @factory. + * + * A value of #GST_AUTOPLUG_SELECT_EXPOSE will expose @pad without plugging + * any element to it. + * + * A value of #GST_AUTOPLUG_SELECT_SKIP will skip @factory and move to the + * next factory. + * + * + * Only the signal handler that is connected first will ever by invoked. + * Don't connect signal handlers with the #G_CONNECT_AFTER flag to this + * signal, they will never be invoked! + * + * + * Returns: a #GST_TYPE_AUTOPLUG_SELECT_RESULT that indicates the required + * operation. The default handler will always return + * #GST_AUTOPLUG_SELECT_TRY. + */ + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT] = + g_signal_new ("autoplug-select", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstURIDecodeBinClass, + autoplug_select), _gst_select_accumulator, NULL, + gst_play_marshal_ENUM__OBJECT_BOXED_OBJECT, + GST_TYPE_AUTOPLUG_SELECT_RESULT, 3, GST_TYPE_PAD, GST_TYPE_CAPS, + GST_TYPE_ELEMENT_FACTORY); + + /** + * GstURIDecodeBin::drained: + * + * This signal is emitted when the data for the current uri is played. + */ + gst_uri_decode_bin_signals[SIGNAL_DRAINED] = + g_signal_new ("drained", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstURIDecodeBinClass, drained), NULL, NULL, + gst_marshal_VOID__VOID, G_TYPE_NONE, 0, G_TYPE_NONE); + + /** + * GstURIDecodeBin::source-setup: + * @bin: the uridecodebin. + * @source: source element + * + * This signal is emitted after the source element has been created, so + * it can be configured by setting additional properties (e.g. set a + * proxy server for an http source, or set the device and read speed for + * an audio cd source). This is functionally equivalent to connecting to + * the notify::source signal, but more convenient. + * + * Since: 0.10.33 + */ + gst_uri_decode_bin_signals[SIGNAL_SOURCE_SETUP] = + g_signal_new ("source-setup", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, 0, NULL, NULL, + gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_ELEMENT); + + gstelement_class->query = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_query); + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_uri_decode_bin_change_state); + + gstbin_class->handle_message = GST_DEBUG_FUNCPTR (handle_message); + + klass->autoplug_continue = + GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_continue); + klass->autoplug_factories = + GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_factories); + klass->autoplug_sort = GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_sort); + klass->autoplug_select = + GST_DEBUG_FUNCPTR (gst_uri_decode_bin_autoplug_select); +} + +static void +gst_uri_decode_bin_init (GstURIDecodeBin * dec, GstURIDecodeBinClass * klass) +{ + /* first filter out the interesting element factories */ + dec->factories_lock = g_mutex_new (); + + dec->lock = g_mutex_new (); + + dec->uri = g_strdup (DEFAULT_PROP_URI); + dec->connection_speed = DEFAULT_CONNECTION_SPEED; + dec->caps = DEFAULT_CAPS; + dec->encoding = g_strdup (DEFAULT_SUBTITLE_ENCODING); + + dec->buffer_duration = DEFAULT_BUFFER_DURATION; + dec->buffer_size = DEFAULT_BUFFER_SIZE; + dec->download = DEFAULT_DOWNLOAD; + dec->use_buffering = DEFAULT_USE_BUFFERING; + dec->expose_allstreams = DEFAULT_EXPOSE_ALL_STREAMS; + dec->ring_buffer_max_size = DEFAULT_RING_BUFFER_MAX_SIZE; + + GST_OBJECT_FLAG_SET (dec, GST_ELEMENT_IS_SOURCE); +} + +static void +gst_uri_decode_bin_finalize (GObject * obj) +{ + GstURIDecodeBin *dec = GST_URI_DECODE_BIN (obj); + + remove_decoders (dec, TRUE); + g_mutex_free (dec->lock); + g_mutex_free (dec->factories_lock); + g_free (dec->uri); + g_free (dec->encoding); + if (dec->factories) + gst_plugin_feature_list_free (dec->factories); + if (dec->caps) + gst_caps_unref (dec->caps); + + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void +gst_uri_decode_bin_set_encoding (GstURIDecodeBin * dec, const gchar * encoding) +{ + GSList *walk; + + GST_URI_DECODE_BIN_LOCK (dec); + + /* set property first */ + GST_OBJECT_LOCK (dec); + g_free (dec->encoding); + dec->encoding = g_strdup (encoding); + GST_OBJECT_UNLOCK (dec); + + /* set the property on all decodebins now */ + for (walk = dec->decodebins; walk; walk = g_slist_next (walk)) { + GObject *decodebin = G_OBJECT (walk->data); + + g_object_set (decodebin, "subtitle-encoding", encoding, NULL); + } + GST_URI_DECODE_BIN_UNLOCK (dec); +} + +static void +gst_uri_decode_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstURIDecodeBin *dec = GST_URI_DECODE_BIN (object); + + switch (prop_id) { + case PROP_URI: + GST_OBJECT_LOCK (dec); + g_free (dec->uri); + dec->uri = g_value_dup_string (value); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_CONNECTION_SPEED: + GST_OBJECT_LOCK (dec); + dec->connection_speed = g_value_get_uint (value) * 1000; + GST_OBJECT_UNLOCK (dec); + break; + case PROP_CAPS: + GST_OBJECT_LOCK (dec); + if (dec->caps) + gst_caps_unref (dec->caps); + dec->caps = g_value_dup_boxed (value); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_SUBTITLE_ENCODING: + gst_uri_decode_bin_set_encoding (dec, g_value_get_string (value)); + break; + case PROP_BUFFER_SIZE: + dec->buffer_size = g_value_get_int (value); + break; + case PROP_BUFFER_DURATION: + dec->buffer_duration = g_value_get_int64 (value); + break; + case PROP_DOWNLOAD: + dec->download = g_value_get_boolean (value); + break; + case PROP_USE_BUFFERING: + dec->use_buffering = g_value_get_boolean (value); + break; + case PROP_EXPOSE_ALL_STREAMS: + dec->expose_allstreams = g_value_get_boolean (value); + break; + case PROP_RING_BUFFER_MAX_SIZE: + dec->ring_buffer_max_size = g_value_get_uint64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_uri_decode_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstURIDecodeBin *dec = GST_URI_DECODE_BIN (object); + + switch (prop_id) { + case PROP_URI: + GST_OBJECT_LOCK (dec); + g_value_set_string (value, dec->uri); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_SOURCE: + GST_OBJECT_LOCK (dec); + g_value_set_object (value, dec->source); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_CONNECTION_SPEED: + GST_OBJECT_LOCK (dec); + g_value_set_uint (value, dec->connection_speed / 1000); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_CAPS: + GST_OBJECT_LOCK (dec); + g_value_set_boxed (value, dec->caps); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_SUBTITLE_ENCODING: + GST_OBJECT_LOCK (dec); + g_value_set_string (value, dec->encoding); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_BUFFER_SIZE: + GST_OBJECT_LOCK (dec); + g_value_set_int (value, dec->buffer_size); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_BUFFER_DURATION: + GST_OBJECT_LOCK (dec); + g_value_set_int64 (value, dec->buffer_duration); + GST_OBJECT_UNLOCK (dec); + break; + case PROP_DOWNLOAD: + g_value_set_boolean (value, dec->download); + break; + case PROP_USE_BUFFERING: + g_value_set_boolean (value, dec->use_buffering); + break; + case PROP_EXPOSE_ALL_STREAMS: + g_value_set_boolean (value, dec->expose_allstreams); + break; + case PROP_RING_BUFFER_MAX_SIZE: + g_value_set_uint64 (value, dec->ring_buffer_max_size); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +do_async_start (GstURIDecodeBin * dbin) +{ + GstMessage *message; + + dbin->async_pending = TRUE; + + message = gst_message_new_async_start (GST_OBJECT_CAST (dbin), FALSE); + parent_class->handle_message (GST_BIN_CAST (dbin), message); +} + +static void +do_async_done (GstURIDecodeBin * dbin) +{ + GstMessage *message; + + if (dbin->async_pending) { + GST_DEBUG_OBJECT (dbin, "posting ASYNC_DONE"); + message = gst_message_new_async_done (GST_OBJECT_CAST (dbin)); + parent_class->handle_message (GST_BIN_CAST (dbin), message); + + dbin->async_pending = FALSE; + } +} + +#define DEFAULT_QUEUE_SIZE (3 * GST_SECOND) +#define DEFAULT_QUEUE_MIN_THRESHOLD ((DEFAULT_QUEUE_SIZE * 30) / 100) +#define DEFAULT_QUEUE_THRESHOLD ((DEFAULT_QUEUE_SIZE * 95) / 100) + +static void +unknown_type_cb (GstElement * element, GstPad * pad, GstCaps * caps, + GstURIDecodeBin * decoder) +{ + gchar *capsstr; + + capsstr = gst_caps_to_string (caps); + GST_ELEMENT_WARNING (decoder, STREAM, CODEC_NOT_FOUND, + (_("No decoder available for type \'%s\'."), capsstr), (NULL)); + g_free (capsstr); +} + +/* add a streaminfo that indicates that the stream is handled by the + * given element. This usually means that a stream without actual data is + * produced but one that is sunken by an element. Examples of this are: + * cdaudio, a hardware decoder/sink, dvd meta bins etc... + */ +static void +add_element_stream (GstElement * element, GstURIDecodeBin * decoder) +{ + g_warning ("add element stream"); +} + +/* when the decoder element signals that no more pads will be generated, we + * can commit the current group. + */ +static void +no_more_pads_full (GstElement * element, gboolean subs, + GstURIDecodeBin * decoder) +{ + gboolean final; + + /* setup phase */ + GST_DEBUG_OBJECT (element, "no more pads, %d pending", decoder->pending); + + GST_URI_DECODE_BIN_LOCK (decoder); + final = (decoder->pending == 0); + + /* nothing pending, we can exit */ + if (final) + goto done; + + /* the object has no pending no_more_pads */ + if (!g_object_get_data (G_OBJECT (element), "pending")) + goto done; + g_object_set_data (G_OBJECT (element), "pending", NULL); + + decoder->pending--; + final = (decoder->pending == 0); + +done: + GST_URI_DECODE_BIN_UNLOCK (decoder); + + if (final) + gst_element_no_more_pads (GST_ELEMENT_CAST (decoder)); + + return; +} + +static void +no_more_pads (GstElement * element, GstURIDecodeBin * decoder) +{ + no_more_pads_full (element, FALSE, decoder); +} + +static void +source_no_more_pads (GstElement * element, GstURIDecodeBin * bin) +{ + GST_DEBUG_OBJECT (bin, "No more pads in source element %s.", + GST_ELEMENT_NAME (element)); + + g_signal_handler_disconnect (element, bin->src_np_sig_id); + bin->src_np_sig_id = 0; + g_signal_handler_disconnect (element, bin->src_nmp_sig_id); + bin->src_nmp_sig_id = 0; + + no_more_pads_full (element, FALSE, bin); +} + +/* Called by the signal handlers when a decodebin has + * found a new raw pad. + */ +static void +new_decoded_pad_cb (GstElement * element, GstPad * pad, gboolean last, + GstURIDecodeBin * decoder) +{ + GstPad *newpad; + GstPadTemplate *pad_tmpl; + gchar *padname; + + GST_DEBUG_OBJECT (element, "new decoded pad, name: <%s>. Last: %d", + GST_PAD_NAME (pad), last); + + GST_URI_DECODE_BIN_LOCK (decoder); + padname = g_strdup_printf ("src%d", decoder->numpads); + decoder->numpads++; + GST_URI_DECODE_BIN_UNLOCK (decoder); + + pad_tmpl = gst_static_pad_template_get (&srctemplate); + newpad = gst_ghost_pad_new_from_template (padname, pad, pad_tmpl); + gst_object_unref (pad_tmpl); + g_free (padname); + + /* store ref to the ghostpad so we can remove it */ + g_object_set_data (G_OBJECT (pad), "uridecodebin.ghostpad", newpad); + + gst_pad_set_active (newpad, TRUE); + gst_element_add_pad (GST_ELEMENT_CAST (decoder), newpad); +} + + +static gboolean +source_pad_event_probe (GstPad * pad, GstEvent * event, + GstURIDecodeBin * decoder) +{ + GST_LOG_OBJECT (pad, "%s, decoder %p", GST_EVENT_TYPE_NAME (event), decoder); + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + GST_DEBUG_OBJECT (pad, "we received EOS"); + + g_signal_emit (decoder, + gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL); + } + /* never drop events */ + return TRUE; +} + +/* called when we found a raw pad on the source element. We need to set up a + * padprobe to detect EOS before exposing the pad. */ +static void +expose_decoded_pad (GstElement * element, GstPad * pad, + GstURIDecodeBin * decoder) +{ + gst_pad_add_event_probe (pad, G_CALLBACK (source_pad_event_probe), decoder); + + new_decoded_pad_cb (element, pad, FALSE, decoder); +} + +static void +pad_removed_cb (GstElement * element, GstPad * pad, GstURIDecodeBin * decoder) +{ + GstPad *ghost; + + GST_DEBUG_OBJECT (element, "pad removed name: <%s:%s>", + GST_DEBUG_PAD_NAME (pad)); + + /* we only care about srcpads */ + if (!GST_PAD_IS_SRC (pad)) + return; + + if (!(ghost = g_object_get_data (G_OBJECT (pad), "uridecodebin.ghostpad"))) + goto no_ghost; + + /* unghost the pad */ + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghost), NULL); + + /* deactivate and remove */ + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (decoder), ghost); + + return; + + /* ERRORS */ +no_ghost: + { + GST_WARNING_OBJECT (element, "no ghost pad found"); + return; + } +} + +/* helper function to lookup stuff in lists */ +static gboolean +array_has_value (const gchar * values[], const gchar * value) +{ + gint i; + + for (i = 0; values[i]; i++) { + if (g_str_has_prefix (value, values[i])) + return TRUE; + } + return FALSE; +} + +static gboolean +array_has_uri_value (const gchar * values[], const gchar * value) +{ + gint i; + + for (i = 0; values[i]; i++) { + if (!g_ascii_strncasecmp (value, values[i], strlen (values[i]))) + return TRUE; + } + return FALSE; +} + +/* list of URIs that we consider to be streams and that need buffering. + * We have no mechanism yet to figure this out with a query. */ +static const gchar *stream_uris[] = { "http://", "https://", "mms://", + "mmsh://", "mmsu://", "mmst://", "fd://", "myth://", "ssh://", + "ftp://", "sftp://", + NULL +}; + +/* list of URIs that need a queue because they are pretty bursty */ +static const gchar *queue_uris[] = { "cdda://", NULL }; + +/* blacklisted URIs, we know they will always fail. */ +static const gchar *blacklisted_uris[] = { NULL }; + +/* mime types that we don't consider to be media types */ +#if 0 +static const gchar *no_media_mimes[] = { + "application/x-executable", "application/x-bzip", "application/x-gzip", + "application/zip", "application/x-compress", NULL +}; +#endif + +/* media types we can download */ +static const gchar *download_media[] = { + "video/quicktime", "video/mj2", "audio/x-m4a", "application/x-3gp", + "video/x-flv", "video/x-msvideo", "video/webm", NULL +}; + +#define IS_STREAM_URI(uri) (array_has_uri_value (stream_uris, uri)) +#define IS_QUEUE_URI(uri) (array_has_uri_value (queue_uris, uri)) +#define IS_BLACKLISTED_URI(uri) (array_has_uri_value (blacklisted_uris, uri)) +#define IS_NO_MEDIA_MIME(mime) (array_has_value (no_media_mimes, mime)) +#define IS_DOWNLOAD_MEDIA(media) (array_has_value (download_media, media)) + +/* + * Generate and configure a source element. + */ +static GstElement * +gen_source_element (GstURIDecodeBin * decoder) +{ + GstElement *source; + + if (!decoder->uri) + goto no_uri; + + GST_LOG_OBJECT (decoder, "finding source for %s", decoder->uri); + + if (!gst_uri_is_valid (decoder->uri)) + goto invalid_uri; + + if (IS_BLACKLISTED_URI (decoder->uri)) + goto uri_blacklisted; + + source = gst_element_make_from_uri (GST_URI_SRC, decoder->uri, "source"); + if (!source) + goto no_source; + + GST_LOG_OBJECT (decoder, "found source type %s", G_OBJECT_TYPE_NAME (source)); + + decoder->is_stream = IS_STREAM_URI (decoder->uri); + GST_LOG_OBJECT (decoder, "source is stream: %d", decoder->is_stream); + + decoder->need_queue = IS_QUEUE_URI (decoder->uri); + GST_LOG_OBJECT (decoder, "source needs queue: %d", decoder->need_queue); + + /* make HTTP sources send extra headers so we get icecast + * metadata in case the stream is an icecast stream */ + if (!strncmp (decoder->uri, "http://", 7) && + g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "iradio-mode")) { + GST_LOG_OBJECT (decoder, "configuring iradio-mode"); + g_object_set (source, "iradio-mode", TRUE, NULL); + } + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "connection-speed")) { + GST_DEBUG_OBJECT (decoder, + "setting connection-speed=%d to source element", + decoder->connection_speed / 1000); + g_object_set (source, "connection-speed", + decoder->connection_speed / 1000, NULL); + } + if (g_object_class_find_property (G_OBJECT_GET_CLASS (source), + "subtitle-encoding")) { + GST_DEBUG_OBJECT (decoder, + "setting subtitle-encoding=%s to source element", decoder->encoding); + g_object_set (source, "subtitle-encoding", decoder->encoding, NULL); + } + return source; + + /* ERRORS */ +no_uri: + { + GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND, + (_("No URI specified to play from.")), (NULL)); + return NULL; + } +invalid_uri: + { + GST_ELEMENT_ERROR (decoder, RESOURCE, NOT_FOUND, + (_("Invalid URI \"%s\"."), decoder->uri), (NULL)); + return NULL; + } +uri_blacklisted: + { + GST_ELEMENT_ERROR (decoder, RESOURCE, FAILED, + (_("This stream type cannot be played yet.")), (NULL)); + return NULL; + } +no_source: + { + gchar *prot = gst_uri_get_protocol (decoder->uri); + + /* whoops, could not create the source element, dig a little deeper to + * figure out what might be wrong. */ + if (prot) { + GstMessage *msg; + + msg = + gst_missing_uri_source_message_new (GST_ELEMENT_CAST (decoder), prot); + gst_element_post_message (GST_ELEMENT_CAST (decoder), msg); + + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, + (_("No URI handler implemented for \"%s\"."), prot), (NULL)); + g_free (prot); + } else + goto invalid_uri; + + return NULL; + } +} + +/** + * has_all_raw_caps: + * @pad: a #GstPad + * @all_raw: pointer to hold the result + * + * check if the caps of the pad are all raw. The caps are all raw if + * all of its structures contain audio/x-raw or video/x-raw. + * + * Returns: %FALSE @pad has no caps. Else TRUE and @all_raw set t the result. + */ +static gboolean +has_all_raw_caps (GstPad * pad, GstCaps * rawcaps, gboolean * all_raw) +{ + GstCaps *caps, *intersection; + gint capssize; + gboolean res = FALSE; + + caps = gst_pad_get_caps_reffed (pad); + if (caps == NULL) + return FALSE; + + GST_DEBUG_OBJECT (pad, "have caps %" GST_PTR_FORMAT, caps); + + capssize = gst_caps_get_size (caps); + /* no caps, skip and move to the next pad */ + if (capssize == 0 || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) + goto done; + + intersection = gst_caps_intersect (caps, rawcaps); + *all_raw = !gst_caps_is_empty (intersection) + && (gst_caps_get_size (intersection) == capssize); + gst_caps_unref (intersection); + + res = TRUE; + +done: + gst_caps_unref (caps); + return res; +} + +static void +post_missing_plugin_error (GstElement * dec, const gchar * element_name) +{ + GstMessage *msg; + + msg = gst_missing_element_message_new (dec, element_name); + gst_element_post_message (dec, msg); + + GST_ELEMENT_ERROR (dec, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + element_name), (NULL)); +} + +/** + * analyse_source: + * @decoder: a #GstURIDecodeBin + * @is_raw: are all pads raw data + * @have_out: does the source have output + * @is_dynamic: is this a dynamic source + * @use_queue: put a queue before raw output pads + * + * Check the source of @decoder and collect information about it. + * + * @is_raw will be set to TRUE if the source only produces raw pads. When this + * function returns, all of the raw pad of the source will be added + * to @decoder. + * + * @have_out: will be set to TRUE if the source has output pads. + * + * @is_dynamic: TRUE if the element will create (more) pads dynamically later + * on. + * + * Returns: FALSE if a fatal error occured while scanning. + */ +static gboolean +analyse_source (GstURIDecodeBin * decoder, gboolean * is_raw, + gboolean * have_out, gboolean * is_dynamic, gboolean use_queue) +{ + GstIterator *pads_iter; + gboolean done = FALSE; + gboolean res = TRUE; + GstCaps *rawcaps; + GstPad *pad; + + *have_out = FALSE; + *is_raw = FALSE; + *is_dynamic = FALSE; + + g_object_get (decoder, "caps", &rawcaps, NULL); + if (!rawcaps) + rawcaps = DEFAULT_CAPS; + + pads_iter = gst_element_iterate_src_pads (decoder->source); + while (!done) { + switch (gst_iterator_next (pads_iter, (gpointer) & pad)) { + case GST_ITERATOR_ERROR: + res = FALSE; + /* FALLTROUGH */ + case GST_ITERATOR_DONE: + done = TRUE; + break; + case GST_ITERATOR_RESYNC: + /* reset results and resync */ + *have_out = FALSE; + *is_raw = FALSE; + *is_dynamic = FALSE; + gst_iterator_resync (pads_iter); + break; + case GST_ITERATOR_OK: + /* we now officially have an ouput pad */ + *have_out = TRUE; + + /* if FALSE, this pad has no caps and we continue with the next pad. */ + if (!has_all_raw_caps (pad, rawcaps, is_raw)) { + gst_object_unref (pad); + break; + } + + /* caps on source pad are all raw, we can add the pad */ + if (*is_raw) { + GstElement *outelem; + + if (use_queue) { + GstPad *sinkpad; + + /* insert a queue element right before the raw pad */ + outelem = gst_element_factory_make ("queue2", NULL); + if (!outelem) + goto no_queue2; + + gst_bin_add (GST_BIN_CAST (decoder), outelem); + + sinkpad = gst_element_get_static_pad (outelem, "sink"); + gst_pad_link (pad, sinkpad); + gst_object_unref (sinkpad); + gst_object_unref (pad); + + /* save queue pointer so we can remove it later */ + decoder->queue = outelem; + + /* get the new raw srcpad */ + pad = gst_element_get_static_pad (outelem, "src"); + } else { + outelem = decoder->source; + } + expose_decoded_pad (outelem, pad, decoder); + } + gst_object_unref (pad); + break; + } + } + gst_iterator_free (pads_iter); + gst_caps_unref (rawcaps); + + if (!*have_out) { + GstElementClass *elemclass; + GList *walk; + + /* element has no output pads, check for padtemplates that list SOMETIMES + * pads. */ + elemclass = GST_ELEMENT_GET_CLASS (decoder->source); + + walk = gst_element_class_get_pad_template_list (elemclass); + while (walk != NULL) { + GstPadTemplate *templ; + + templ = (GstPadTemplate *) walk->data; + if (GST_PAD_TEMPLATE_DIRECTION (templ) == GST_PAD_SRC) { + if (GST_PAD_TEMPLATE_PRESENCE (templ) == GST_PAD_SOMETIMES) + *is_dynamic = TRUE; + break; + } + walk = g_list_next (walk); + } + } + + return res; +no_queue2: + { + post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "queue2"); + + gst_object_unref (pad); + gst_iterator_free (pads_iter); + gst_caps_unref (rawcaps); + + return FALSE; + } +} + +/* Remove all decodebin2 from ourself + * If force is FALSE, then the decodebin2 instances will be stored in + * pending_decodebins for re-use later on. + * If force is TRUE, then all decodebin2 instances will be unreferenced + * and cleared, including the pending ones. */ +static void +remove_decoders (GstURIDecodeBin * bin, gboolean force) +{ + GSList *walk; + + for (walk = bin->decodebins; walk; walk = g_slist_next (walk)) { + GstElement *decoder = GST_ELEMENT_CAST (walk->data); + + GST_DEBUG_OBJECT (bin, "removing old decoder element"); + if (force) { + gst_element_set_state (decoder, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), decoder); + } else { + GstCaps *caps; + + gst_element_set_state (decoder, GST_STATE_READY); + /* add it to our list of pending decodebins */ + g_object_ref (decoder); + gst_bin_remove (GST_BIN_CAST (bin), decoder); + /* restore some properties we might have changed */ + g_object_set (decoder, "sink-caps", NULL, NULL); + caps = DEFAULT_CAPS; + g_object_set (decoder, "caps", caps, NULL); + gst_caps_unref (caps); + + bin->pending_decodebins = + g_slist_prepend (bin->pending_decodebins, decoder); + } + } + g_slist_free (bin->decodebins); + bin->decodebins = NULL; + if (force) { + GSList *tmp; + + for (tmp = bin->pending_decodebins; tmp; tmp = tmp->next) { + gst_element_set_state ((GstElement *) tmp->data, GST_STATE_NULL); + gst_object_unref ((GstElement *) tmp->data); + } + g_slist_free (bin->pending_decodebins); + bin->pending_decodebins = NULL; + + } + + /* Don't loose the SOURCE flag */ + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE); +} + +static void +remove_pads (GstURIDecodeBin * bin) +{ + GSList *walk; + + for (walk = bin->srcpads; walk; walk = g_slist_next (walk)) { + GstPad *pad = GST_PAD_CAST (walk->data); + + GST_DEBUG_OBJECT (bin, "removing old pad"); + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT_CAST (bin), pad); + } + g_slist_free (bin->srcpads); + bin->srcpads = NULL; +} + +static void +proxy_unknown_type_signal (GstElement * element, GstPad * pad, GstCaps * caps, + GstURIDecodeBin * dec) +{ + GST_DEBUG_OBJECT (dec, "unknown-type signaled"); + + g_signal_emit (dec, + gst_uri_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); +} + +static gboolean +proxy_autoplug_continue_signal (GstElement * element, GstPad * pad, + GstCaps * caps, GstURIDecodeBin * dec) +{ + gboolean result; + + g_signal_emit (dec, + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_CONTINUE], 0, pad, caps, + &result); + + GST_DEBUG_OBJECT (dec, "autoplug-continue returned %d", result); + + return result; +} + +static GValueArray * +proxy_autoplug_factories_signal (GstElement * element, GstPad * pad, + GstCaps * caps, GstURIDecodeBin * dec) +{ + GValueArray *result; + + g_signal_emit (dec, + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_FACTORIES], 0, pad, caps, + &result); + + GST_DEBUG_OBJECT (dec, "autoplug-factories returned %p", result); + + return result; +} + +static GValueArray * +proxy_autoplug_sort_signal (GstElement * element, GstPad * pad, + GstCaps * caps, GValueArray * factories, GstURIDecodeBin * dec) +{ + GValueArray *result; + + g_signal_emit (dec, + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SORT], 0, pad, caps, + factories, &result); + + GST_DEBUG_OBJECT (dec, "autoplug-sort returned %p", result); + + return result; +} + +static GstAutoplugSelectResult +proxy_autoplug_select_signal (GstElement * element, GstPad * pad, + GstCaps * caps, GstElementFactory * factory, GstURIDecodeBin * dec) +{ + GstAutoplugSelectResult result; + + g_signal_emit (dec, + gst_uri_decode_bin_signals[SIGNAL_AUTOPLUG_SELECT], 0, pad, caps, factory, + &result); + + GST_DEBUG_OBJECT (dec, "autoplug-select returned %d", result); + + return result; +} + +static void +proxy_drained_signal (GstElement * element, GstURIDecodeBin * dec) +{ + GST_DEBUG_OBJECT (dec, "drained signaled"); + + g_signal_emit (dec, gst_uri_decode_bin_signals[SIGNAL_DRAINED], 0, NULL); +} + +/* make a decodebin and connect to all the signals */ +static GstElement * +make_decoder (GstURIDecodeBin * decoder) +{ + GstElement *decodebin; + + /* re-use pending decodebin2 */ + if (decoder->pending_decodebins) { + GSList *first = decoder->pending_decodebins; + GST_LOG_OBJECT (decoder, "re-using pending decodebin2"); + decodebin = (GstElement *) first->data; + decoder->pending_decodebins = + g_slist_delete_link (decoder->pending_decodebins, first); + } else { + GST_LOG_OBJECT (decoder, "making new decodebin2"); + + /* now create the decoder element */ + decodebin = gst_element_factory_make ("decodebin2", NULL); + + if (!decodebin) + goto no_decodebin; + + /* sanity check */ + if (decodebin->numsinkpads == 0) + goto no_typefind; + + /* connect signals to proxy */ + g_signal_connect (decodebin, "unknown-type", + G_CALLBACK (proxy_unknown_type_signal), decoder); + g_signal_connect (decodebin, "autoplug-continue", + G_CALLBACK (proxy_autoplug_continue_signal), decoder); + g_signal_connect (decodebin, "autoplug-factories", + G_CALLBACK (proxy_autoplug_factories_signal), decoder); + g_signal_connect (decodebin, "autoplug-sort", + G_CALLBACK (proxy_autoplug_sort_signal), decoder); + g_signal_connect (decodebin, "autoplug-select", + G_CALLBACK (proxy_autoplug_select_signal), decoder); + g_signal_connect (decodebin, "drained", + G_CALLBACK (proxy_drained_signal), decoder); + + /* set up callbacks to create the links between decoded data + * and video/audio/subtitle rendering/output. */ + g_signal_connect (decodebin, + "new-decoded-pad", G_CALLBACK (new_decoded_pad_cb), decoder); + g_signal_connect (decodebin, + "pad-removed", G_CALLBACK (pad_removed_cb), decoder); + g_signal_connect (decodebin, "no-more-pads", + G_CALLBACK (no_more_pads), decoder); + g_signal_connect (decodebin, + "unknown-type", G_CALLBACK (unknown_type_cb), decoder); + } + + /* configure caps if we have any */ + if (decoder->caps) + g_object_set (decodebin, "caps", decoder->caps, NULL); + + /* Propagate expose-all-streams property */ + g_object_set (decodebin, "expose-all-streams", decoder->expose_allstreams, + NULL); + + if (!decoder->is_stream) { + /* propagate the use-buffering property but only when we are not already + * doing stream buffering with queue2. FIXME, we might want to do stream + * buffering with the multiqueue buffering instead of queue2. */ + g_object_set (decodebin, "use-buffering", decoder->use_buffering, NULL); + + if (decoder->use_buffering) { + guint max_bytes; + guint64 max_time; + + /* configure sizes when buffering */ + if ((max_bytes = decoder->buffer_size) == -1) + max_bytes = 2 * 1024 * 1024; + if ((max_time = decoder->buffer_duration) == -1) + max_time = 2 * GST_SECOND; + + g_object_set (decodebin, "max-size-bytes", max_bytes, "max-size-buffers", + (guint) 0, "max-size-time", max_time, NULL); + } + } + + g_object_set_data (G_OBJECT (decodebin), "pending", GINT_TO_POINTER (1)); + g_object_set (decodebin, "subtitle-encoding", decoder->encoding, NULL); + decoder->pending++; + GST_LOG_OBJECT (decoder, "have %d pending dynamic objects", decoder->pending); + + gst_bin_add (GST_BIN_CAST (decoder), decodebin); + + decoder->decodebins = g_slist_prepend (decoder->decodebins, decodebin); + + return decodebin; + + /* ERRORS */ +no_decodebin: + { + post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "decodebin2"); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No decodebin2 element, check your installation")); + return NULL; + } +no_typefind: + { + gst_object_unref (decodebin); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No typefind element, decodebin2 is unusable, check your installation")); + return NULL; + } +} + +/* signaled when we have a stream and we need to configure the download + * buffering or regular buffering */ +static void +type_found (GstElement * typefind, guint probability, + GstCaps * caps, GstURIDecodeBin * decoder) +{ + GstElement *dec_elem, *queue; + GstStructure *s; + const gchar *media_type; + + GST_DEBUG_OBJECT (decoder, "typefind found caps %" GST_PTR_FORMAT, caps); + + s = gst_caps_get_structure (caps, 0); + media_type = gst_structure_get_name (s); + + /* remember if we need download buffering */ + decoder->is_download = IS_DOWNLOAD_MEDIA (media_type) && decoder->download; + /* only enable download buffering if the upstream duration is known */ + if (decoder->is_download) { + GstFormat fmt = GST_FORMAT_BYTES; + gint64 dur; + + decoder->is_download = (gst_element_query_duration (typefind, &fmt, &dur) + && fmt == GST_FORMAT_BYTES && dur != -1); + } + + dec_elem = make_decoder (decoder); + if (!dec_elem) + goto no_decodebin; + + queue = gst_element_factory_make ("queue2", NULL); + if (!queue) + goto no_queue2; + + g_object_set (queue, "use-buffering", TRUE, NULL); + g_object_set (queue, "ring-buffer-max-size", decoder->ring_buffer_max_size, + NULL); + + GST_DEBUG_OBJECT (decoder, "check media-type %s, %d", media_type, + decoder->download); + + if (decoder->is_download) { + gchar *temp_template, *filename; + const gchar *tmp_dir, *prgname; + + tmp_dir = g_get_tmp_dir (); + prgname = g_get_prgname (); + if (prgname == NULL) + prgname = "GStreamer"; + + filename = g_strdup_printf ("%s-XXXXXX", prgname); + + /* build our filename */ + temp_template = g_build_filename (tmp_dir, filename, NULL); + + GST_DEBUG_OBJECT (decoder, "enable download buffering in %s (%s, %s, %s)", + temp_template, tmp_dir, prgname, filename); + + /* configure progressive download for selected media types */ + g_object_set (queue, "temp-template", temp_template, NULL); + + g_free (filename); + g_free (temp_template); + } + + /* Disable max-size-buffers */ + g_object_set (queue, "max-size-buffers", 0, NULL); + + /* If buffer size or duration are set, set them on the queue2 element */ + if (decoder->buffer_size != -1) + g_object_set (queue, "max-size-bytes", decoder->buffer_size, NULL); + if (decoder->buffer_duration != -1) + g_object_set (queue, "max-size-time", decoder->buffer_duration, NULL); + + gst_bin_add (GST_BIN_CAST (decoder), queue); + + if (!gst_element_link_pads (typefind, "src", queue, "sink")) + goto could_not_link; + + /* to force caps on the decodebin element and avoid reparsing stuff by + * typefind. It also avoids a deadlock in the way typefind activates pads in + * the state change */ + g_object_set (dec_elem, "sink-caps", caps, NULL); + + if (!gst_element_link_pads (queue, "src", dec_elem, "sink")) + goto could_not_link; + + /* PLAYING in one go might fail (see bug #632782) */ + gst_element_set_state (dec_elem, GST_STATE_PAUSED); + gst_element_set_state (dec_elem, GST_STATE_PLAYING); + gst_element_set_state (queue, GST_STATE_PLAYING); + + do_async_done (decoder); + + return; + + /* ERRORS */ +no_decodebin: + { + /* error was posted */ + return; + } +could_not_link: + { + GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, + (NULL), ("Can't link typefind to decodebin2 element")); + return; + } +no_queue2: + { + post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "queue2"); + return; + } +} + +/* setup a streaming source. This will first plug a typefind element to the + * source. After we find the type, we decide to plug a queue2 and continue to + * plug a decodebin2 starting from the found caps */ +static gboolean +setup_streaming (GstURIDecodeBin * decoder) +{ + GstElement *typefind; + + /* now create the decoder element */ + typefind = gst_element_factory_make ("typefind", NULL); + if (!typefind) + goto no_typefind; + + gst_bin_add (GST_BIN_CAST (decoder), typefind); + + if (!gst_element_link_pads (decoder->source, NULL, typefind, "sink")) + goto could_not_link; + + decoder->typefind = typefind; + + /* connect a signal to find out when the typefind element found + * a type */ + decoder->have_type_id = + g_signal_connect (decoder->typefind, "have-type", + G_CALLBACK (type_found), decoder); + + do_async_start (decoder); + + return TRUE; + + /* ERRORS */ +no_typefind: + { + post_missing_plugin_error (GST_ELEMENT_CAST (decoder), "typefind"); + GST_ELEMENT_ERROR (decoder, CORE, MISSING_PLUGIN, (NULL), + ("No typefind element, check your installation")); + return FALSE; + } +could_not_link: + { + GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, + (NULL), ("Can't link source to typefind element")); + gst_bin_remove (GST_BIN_CAST (decoder), typefind); + /* Don't loose the SOURCE flag */ + GST_OBJECT_FLAG_SET (decoder, GST_ELEMENT_IS_SOURCE); + return FALSE; + } +} + +/* remove source and all related elements */ +static void +remove_source (GstURIDecodeBin * bin) +{ + GstElement *source = bin->source; + + if (source) { + GST_DEBUG_OBJECT (bin, "removing old src element"); + gst_element_set_state (source, GST_STATE_NULL); + + if (bin->src_np_sig_id) { + g_signal_handler_disconnect (source, bin->src_np_sig_id); + bin->src_np_sig_id = 0; + } + if (bin->src_nmp_sig_id) { + g_signal_handler_disconnect (source, bin->src_nmp_sig_id); + bin->src_nmp_sig_id = 0; + } + gst_bin_remove (GST_BIN_CAST (bin), source); + bin->source = NULL; + } + if (bin->queue) { + GST_DEBUG_OBJECT (bin, "removing old queue element"); + gst_element_set_state (bin->queue, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), bin->queue); + bin->queue = NULL; + } + if (bin->typefind) { + GST_DEBUG_OBJECT (bin, "removing old typefind element"); + gst_element_set_state (bin->typefind, GST_STATE_NULL); + gst_bin_remove (GST_BIN_CAST (bin), bin->typefind); + bin->typefind = NULL; + } + /* Don't loose the SOURCE flag */ + GST_OBJECT_FLAG_SET (bin, GST_ELEMENT_IS_SOURCE); +} + +/* is called when a dynamic source element created a new pad. */ +static void +source_new_pad (GstElement * element, GstPad * pad, GstURIDecodeBin * bin) +{ + GstElement *decoder; + gboolean is_raw; + GstCaps *rawcaps; + + GST_URI_DECODE_BIN_LOCK (bin); + GST_DEBUG_OBJECT (bin, "Found new pad %s.%s in source element %s", + GST_DEBUG_PAD_NAME (pad), GST_ELEMENT_NAME (element)); + + g_object_get (bin, "caps", &rawcaps, NULL); + if (!rawcaps) + rawcaps = DEFAULT_CAPS; + + /* if this is a pad with all raw caps, we can expose it */ + if (has_all_raw_caps (pad, rawcaps, &is_raw) && is_raw) { + /* it's all raw, create output pads. */ + GST_URI_DECODE_BIN_UNLOCK (bin); + gst_caps_unref (rawcaps); + expose_decoded_pad (element, pad, bin); + return; + } + gst_caps_unref (rawcaps); + + /* not raw, create decoder */ + decoder = make_decoder (bin); + if (!decoder) + goto no_decodebin; + + /* and link to decoder */ + if (!gst_element_link_pads (bin->source, NULL, decoder, "sink")) + goto could_not_link; + + GST_DEBUG_OBJECT (bin, "linked decoder to new pad"); + + gst_element_set_state (decoder, GST_STATE_PLAYING); + GST_URI_DECODE_BIN_UNLOCK (bin); + + return; + + /* ERRORS */ +no_decodebin: + { + /* error was posted */ + GST_URI_DECODE_BIN_UNLOCK (bin); + return; + } +could_not_link: + { + GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, + (NULL), ("Can't link source to decoder element")); + GST_URI_DECODE_BIN_UNLOCK (bin); + return; + } +} + +/* construct and run the source and decoder elements until we found + * all the streams or until a preroll queue has been filled. +*/ +static gboolean +setup_source (GstURIDecodeBin * decoder) +{ + gboolean is_raw, have_out, is_dynamic; + + GST_DEBUG_OBJECT (decoder, "setup source"); + + /* delete old src */ + remove_source (decoder); + + decoder->pending = 0; + + /* create and configure an element that can handle the uri */ + if (!(decoder->source = gen_source_element (decoder))) + goto no_source; + + /* state will be merged later - if file is not found, error will be + * handled by the application right after. */ + gst_bin_add (GST_BIN_CAST (decoder), decoder->source); + + /* notify of the new source used */ + g_object_notify (G_OBJECT (decoder), "source"); + + g_signal_emit (decoder, gst_uri_decode_bin_signals[SIGNAL_SOURCE_SETUP], + 0, decoder->source); + + /* remove the old decoders now, if any */ + remove_decoders (decoder, FALSE); + + /* see if the source element emits raw audio/video all by itself, + * if so, we can create streams for the pads and be done with it. + * Also check that is has source pads, if not, we assume it will + * do everything itself. */ + if (!analyse_source (decoder, &is_raw, &have_out, &is_dynamic, + decoder->need_queue)) + goto invalid_source; + + if (is_raw) { + GST_DEBUG_OBJECT (decoder, "Source provides all raw data"); + /* source provides raw data, we added the pads and we can now signal a + * no_more pads because we are done. */ + gst_element_no_more_pads (GST_ELEMENT_CAST (decoder)); + return TRUE; + } + if (!have_out && !is_dynamic) { + GST_DEBUG_OBJECT (decoder, "Source has no output pads"); + /* create a stream to indicate that this uri is handled by a self + * contained element. We are now done. */ + add_element_stream (decoder->source, decoder); + return TRUE; + } + if (is_dynamic) { + GST_DEBUG_OBJECT (decoder, "Source has dynamic output pads"); + /* connect a handler for the new-pad signal */ + decoder->src_np_sig_id = + g_signal_connect (decoder->source, "pad-added", + G_CALLBACK (source_new_pad), decoder); + decoder->src_nmp_sig_id = + g_signal_connect (decoder->source, "no-more-pads", + G_CALLBACK (source_no_more_pads), decoder); + g_object_set_data (G_OBJECT (decoder->source), "pending", + GINT_TO_POINTER (1)); + decoder->pending++; + } else { + if (decoder->is_stream) { + GST_DEBUG_OBJECT (decoder, "Setting up streaming"); + /* do the stream things here */ + if (!setup_streaming (decoder)) + goto streaming_failed; + } else { + GstElement *dec_elem; + + /* no streaming source, we can link now */ + GST_DEBUG_OBJECT (decoder, "Plugging decodebin to source"); + + dec_elem = make_decoder (decoder); + if (!dec_elem) + goto no_decoder; + + if (!gst_element_link_pads (decoder->source, NULL, dec_elem, "sink")) + goto could_not_link; + } + } + return TRUE; + + /* ERRORS */ +no_source: + { + /* error message was already posted */ + return FALSE; + } +invalid_source: + { + GST_ELEMENT_ERROR (decoder, CORE, FAILED, + (_("Source element is invalid.")), (NULL)); + return FALSE; + } +no_decoder: + { + /* message was posted */ + return FALSE; + } +streaming_failed: + { + /* message was posted */ + return FALSE; + } +could_not_link: + { + GST_ELEMENT_ERROR (decoder, CORE, NEGOTIATION, + (NULL), ("Can't link source to decoder element")); + return FALSE; + } +} + +static void +value_list_append_structure_list (GValue * list_val, GstStructure ** first, + GList * structure_list) +{ + GList *l; + + for (l = structure_list; l != NULL; l = l->next) { + GValue val = { 0, }; + + if (*first == NULL) + *first = gst_structure_copy ((GstStructure *) l->data); + + g_value_init (&val, GST_TYPE_STRUCTURE); + g_value_take_boxed (&val, gst_structure_copy ((GstStructure *) l->data)); + gst_value_list_append_value (list_val, &val); + g_value_unset (&val); + } +} + +/* if it's a redirect message with multiple redirect locations we might + * want to pick a different 'best' location depending on the required + * bitrates and the connection speed */ +static GstMessage * +handle_redirect_message (GstURIDecodeBin * dec, GstMessage * msg) +{ + const GValue *locations_list, *location_val; + GstMessage *new_msg; + GstStructure *new_structure = NULL; + GList *l_good = NULL, *l_neutral = NULL, *l_bad = NULL; + GValue new_list = { 0, }; + guint size, i; + + GST_DEBUG_OBJECT (dec, "redirect message: %" GST_PTR_FORMAT, msg); + GST_DEBUG_OBJECT (dec, "connection speed: %u", dec->connection_speed); + + if (dec->connection_speed == 0 || msg->structure == NULL) + return msg; + + locations_list = gst_structure_get_value (msg->structure, "locations"); + if (locations_list == NULL) + return msg; + + size = gst_value_list_get_size (locations_list); + if (size < 2) + return msg; + + /* maintain existing order as much as possible, just sort references + * with too high a bitrate to the end (the assumption being that if + * bitrates are given they are given for all interesting streams and + * that the you-need-at-least-version-xyz redirect has the same bitrate + * as the lowest referenced redirect alternative) */ + for (i = 0; i < size; ++i) { + const GstStructure *s; + gint bitrate = 0; + + location_val = gst_value_list_get_value (locations_list, i); + s = (const GstStructure *) g_value_get_boxed (location_val); + if (!gst_structure_get_int (s, "minimum-bitrate", &bitrate) || bitrate <= 0) { + GST_DEBUG_OBJECT (dec, "no bitrate: %" GST_PTR_FORMAT, s); + l_neutral = g_list_append (l_neutral, (gpointer) s); + } else if (bitrate > dec->connection_speed) { + GST_DEBUG_OBJECT (dec, "bitrate too high: %" GST_PTR_FORMAT, s); + l_bad = g_list_append (l_bad, (gpointer) s); + } else if (bitrate <= dec->connection_speed) { + GST_DEBUG_OBJECT (dec, "bitrate OK: %" GST_PTR_FORMAT, s); + l_good = g_list_append (l_good, (gpointer) s); + } + } + + g_value_init (&new_list, GST_TYPE_LIST); + value_list_append_structure_list (&new_list, &new_structure, l_good); + value_list_append_structure_list (&new_list, &new_structure, l_neutral); + value_list_append_structure_list (&new_list, &new_structure, l_bad); + gst_structure_set_value (new_structure, "locations", &new_list); + g_value_unset (&new_list); + + g_list_free (l_good); + g_list_free (l_neutral); + g_list_free (l_bad); + + new_msg = gst_message_new_element (msg->src, new_structure); + gst_message_unref (msg); + + GST_DEBUG_OBJECT (dec, "new redirect message: %" GST_PTR_FORMAT, new_msg); + return new_msg; +} + +static void +handle_message (GstBin * bin, GstMessage * msg) +{ + if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ELEMENT && msg->structure != NULL + && gst_structure_has_name (msg->structure, "redirect")) { + /* sort redirect messages based on the connection speed. This simplifies + * the user of this element as it can in most cases just pick the first item + * of the sorted list as a good redirection candidate. It can of course + * choose something else from the list if it has a better way. */ + msg = handle_redirect_message (GST_URI_DECODE_BIN (bin), msg); + } + GST_BIN_CLASS (parent_class)->handle_message (bin, msg); +} + +/* generic struct passed to all query fold methods + * FIXME, move to core. + */ +typedef struct +{ + GstQuery *query; + gint64 min; + gint64 max; + gboolean seekable; + gboolean live; +} QueryFold; + +typedef void (*QueryInitFunction) (GstURIDecodeBin * dec, QueryFold * fold); +typedef void (*QueryDoneFunction) (GstURIDecodeBin * dec, QueryFold * fold); + +/* for duration/position we collect all durations/positions and take + * the MAX of all valid results */ +static void +decoder_query_init (GstURIDecodeBin * dec, QueryFold * fold) +{ + fold->min = 0; + fold->max = -1; + fold->seekable = TRUE; + fold->live = 0; +} + +static gboolean +decoder_query_duration_fold (GstPad * item, GValue * ret, QueryFold * fold) +{ + if (gst_pad_query (item, fold->query)) { + gint64 duration; + + g_value_set_boolean (ret, TRUE); + + gst_query_parse_duration (fold->query, NULL, &duration); + + GST_DEBUG_OBJECT (item, "got duration %" G_GINT64_FORMAT, duration); + + if (duration > fold->max) + fold->max = duration; + } + gst_object_unref (item); + return TRUE; +} + +static void +decoder_query_duration_done (GstURIDecodeBin * dec, QueryFold * fold) +{ + GstFormat format; + + gst_query_parse_duration (fold->query, &format, NULL); + /* store max in query result */ + gst_query_set_duration (fold->query, format, fold->max); + + GST_DEBUG ("max duration %" G_GINT64_FORMAT, fold->max); +} + +static gboolean +decoder_query_position_fold (GstPad * item, GValue * ret, QueryFold * fold) +{ + if (gst_pad_query (item, fold->query)) { + gint64 position; + + g_value_set_boolean (ret, TRUE); + + gst_query_parse_position (fold->query, NULL, &position); + + GST_DEBUG_OBJECT (item, "got position %" G_GINT64_FORMAT, position); + + if (position > fold->max) + fold->max = position; + } + + gst_object_unref (item); + return TRUE; +} + +static void +decoder_query_position_done (GstURIDecodeBin * dec, QueryFold * fold) +{ + GstFormat format; + + gst_query_parse_position (fold->query, &format, NULL); + /* store max in query result */ + gst_query_set_position (fold->query, format, fold->max); + + GST_DEBUG_OBJECT (dec, "max position %" G_GINT64_FORMAT, fold->max); +} + +static gboolean +decoder_query_latency_fold (GstPad * item, GValue * ret, QueryFold * fold) +{ + if (gst_pad_query (item, fold->query)) { + GstClockTime min, max; + gboolean live; + + g_value_set_boolean (ret, TRUE); + + gst_query_parse_latency (fold->query, &live, &min, &max); + + GST_DEBUG_OBJECT (item, + "got latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT + ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live); + + /* for the combined latency we collect the MAX of all min latencies and + * the MIN of all max latencies */ + if (min > fold->min) + fold->min = min; + if (fold->max == -1) + fold->max = max; + else if (max < fold->max) + fold->max = max; + if (fold->live == FALSE) + fold->live = live; + } + + gst_object_unref (item); + return TRUE; +} + +static void +decoder_query_latency_done (GstURIDecodeBin * dec, QueryFold * fold) +{ + /* store max in query result */ + gst_query_set_latency (fold->query, fold->live, fold->min, fold->max); + + GST_DEBUG_OBJECT (dec, + "latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT + ", live %d", GST_TIME_ARGS (fold->min), GST_TIME_ARGS (fold->max), + fold->live); +} + +/* we are seekable if all srcpads are seekable */ +static gboolean +decoder_query_seeking_fold (GstPad * item, GValue * ret, QueryFold * fold) +{ + if (gst_pad_query (item, fold->query)) { + gboolean seekable; + + g_value_set_boolean (ret, TRUE); + gst_query_parse_seeking (fold->query, NULL, &seekable, NULL, NULL); + + GST_DEBUG_OBJECT (item, "got seekable %d", seekable); + + if (fold->seekable == TRUE) + fold->seekable = seekable; + } + gst_object_unref (item); + + return TRUE; +} + +static void +decoder_query_seeking_done (GstURIDecodeBin * dec, QueryFold * fold) +{ + GstFormat format; + + gst_query_parse_seeking (fold->query, &format, NULL, NULL, NULL); + gst_query_set_seeking (fold->query, format, fold->seekable, 0, -1); + + GST_DEBUG_OBJECT (dec, "seekable %d", fold->seekable); +} + +/* generic fold, return first valid result */ +static gboolean +decoder_query_generic_fold (GstPad * item, GValue * ret, QueryFold * fold) +{ + gboolean res; + + if ((res = gst_pad_query (item, fold->query))) { + g_value_set_boolean (ret, TRUE); + GST_DEBUG_OBJECT (item, "answered query %p", fold->query); + } + + gst_object_unref (item); + + /* and stop as soon as we have a valid result */ + return !res; +} + + +/* we're a bin, the default query handler iterates sink elements, which we don't + * have normally. We should just query all source pads. + */ +static gboolean +gst_uri_decode_bin_query (GstElement * element, GstQuery * query) +{ + GstURIDecodeBin *decoder; + gboolean res = FALSE; + GstIterator *iter; + GstIteratorFoldFunction fold_func; + QueryInitFunction fold_init = NULL; + QueryDoneFunction fold_done = NULL; + QueryFold fold_data; + GValue ret = { 0 }; + + decoder = GST_URI_DECODE_BIN (element); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION: + /* iterate and collect durations */ + fold_func = (GstIteratorFoldFunction) decoder_query_duration_fold; + fold_init = decoder_query_init; + fold_done = decoder_query_duration_done; + break; + case GST_QUERY_POSITION: + /* iterate and collect durations */ + fold_func = (GstIteratorFoldFunction) decoder_query_position_fold; + fold_init = decoder_query_init; + fold_done = decoder_query_position_done; + break; + case GST_QUERY_LATENCY: + /* iterate and collect durations */ + fold_func = (GstIteratorFoldFunction) decoder_query_latency_fold; + fold_init = decoder_query_init; + fold_done = decoder_query_latency_done; + break; + case GST_QUERY_SEEKING: + /* iterate and collect durations */ + fold_func = (GstIteratorFoldFunction) decoder_query_seeking_fold; + fold_init = decoder_query_init; + fold_done = decoder_query_seeking_done; + break; + default: + fold_func = (GstIteratorFoldFunction) decoder_query_generic_fold; + break; + } + + fold_data.query = query; + + g_value_init (&ret, G_TYPE_BOOLEAN); + g_value_set_boolean (&ret, FALSE); + + iter = gst_element_iterate_src_pads (element); + GST_DEBUG_OBJECT (element, "Sending query %p (type %d) to src pads", + query, GST_QUERY_TYPE (query)); + + if (fold_init) + fold_init (decoder, &fold_data); + + while (TRUE) { + GstIteratorResult ires; + + ires = gst_iterator_fold (iter, fold_func, &ret, &fold_data); + + switch (ires) { + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + if (fold_init) + fold_init (decoder, &fold_data); + g_value_set_boolean (&ret, FALSE); + break; + case GST_ITERATOR_OK: + case GST_ITERATOR_DONE: + res = g_value_get_boolean (&ret); + if (fold_done != NULL && res) + fold_done (decoder, &fold_data); + goto done; + default: + res = FALSE; + goto done; + } + } +done: + gst_iterator_free (iter); + + return res; +} + +static GstStateChangeReturn +gst_uri_decode_bin_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret; + GstURIDecodeBin *decoder; + + decoder = GST_URI_DECODE_BIN (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!setup_source (decoder)) + goto source_failed; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_DEBUG ("ready to paused"); + if (ret == GST_STATE_CHANGE_FAILURE) + goto setup_failed; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + GST_DEBUG ("paused to ready"); + remove_decoders (decoder, FALSE); + remove_pads (decoder); + remove_source (decoder); + do_async_done (decoder); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + GST_DEBUG ("ready to null"); + remove_decoders (decoder, TRUE); + remove_pads (decoder); + remove_source (decoder); + break; + default: + break; + } + return ret; + + /* ERRORS */ +source_failed: + { + return GST_STATE_CHANGE_FAILURE; + } +setup_failed: + { + /* clean up leftover groups */ + return GST_STATE_CHANGE_FAILURE; + } +} + +gboolean gst_decode_bin_plugin_init (GstPlugin * plugin); + +static gboolean +gst_uri_decode_bin_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_uri_decode_bin_debug, "uridecodebin", 0, + "URI decoder element"); + +#ifdef ENABLE_NLS + GST_DEBUG ("binding text domain %s to locale dir %s", GETTEXT_PACKAGE, + LOCALEDIR); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + return gst_element_register (plugin, "uridecodebin", GST_RANK_NONE, + GST_TYPE_URI_DECODE_BIN); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_decode_bin_plugin_init (plugin)) + return FALSE; + if (!gst_uri_decode_bin_plugin_init (plugin)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "uridecodebin", + "URI Decoder bin", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/Makefile.am b/gst-plugins-base-subtitles0.10/gst/subparse/Makefile.am new file mode 100644 index 0000000..4a33bd4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/Makefile.am @@ -0,0 +1,33 @@ +plugin_LTLIBRARIES = libgstsubparse.la + +if USE_XML +SAMIPARSE_SOURCES = samiparse.c samiparse.h +else +SAMIPARSE_SOURCES = +endif + +libgstsubparse_la_SOURCES = \ + gstssaparse.c \ + gstssaparse.h \ + gstsubparse.c \ + gstsubparse.h \ + $(SAMIPARSE_SOURCES) \ + tmplayerparse.c \ + tmplayerparse.h \ + mpl2parse.c \ + mpl2parse.h \ + qttextparse.c \ + qttextparse.h + +libgstsubparse_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) +libgstsubparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstsubparse_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstsubparse_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstssaparse.h \ + gstsubparse.h \ + samiparse.h \ + tmplayerparse.h \ + mpl2parse.h \ + qttextparse.h diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.c b/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.c new file mode 100644 index 0000000..5aa68e3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.c @@ -0,0 +1,381 @@ +/* GStreamer SSA subtitle parser + * Copyright (c) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Super-primitive SSA parser - we just want the text and ignore + * everything else like styles and timing codes etc. for now */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* atoi() */ +#include + +#include "gstssaparse.h" + +GST_DEBUG_CATEGORY_STATIC (ssa_parse_debug); +#define GST_CAT_DEFAULT ssa_parse_debug + +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-ssa; application/x-ass") + ); + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/x-pango-markup") + ); + +GST_BOILERPLATE (GstSsaParse, gst_ssa_parse, GstElement, GST_TYPE_ELEMENT); + +static GstStateChangeReturn gst_ssa_parse_change_state (GstElement * + element, GstStateChange transition); +static gboolean gst_ssa_parse_setcaps (GstPad * sinkpad, GstCaps * caps); +static gboolean gst_ssa_parse_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_ssa_parse_sink_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_ssa_parse_chain (GstPad * sinkpad, GstBuffer * buf); + +static void +gst_ssa_parse_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "SSA Subtitle Parser", "Codec/Parser/Subtitle", + "Parses SSA subtitle streams", + "Tim-Philipp Müller "); + + GST_DEBUG_CATEGORY_INIT (ssa_parse_debug, "ssaparse", 0, + "SSA subtitle parser"); +} + +static void +gst_ssa_parse_dispose (GObject * object) +{ + GstSsaParse *parse = GST_SSA_PARSE (object); + + g_free (parse->ini); + parse->ini = NULL; + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); +} + +static void +gst_ssa_parse_init (GstSsaParse * parse, GstSsaParseClass * klass) +{ + parse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); + gst_pad_set_setcaps_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_ssa_parse_setcaps)); + gst_pad_set_chain_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_ssa_parse_chain)); + gst_pad_set_event_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_ssa_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + parse->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); + gst_pad_set_event_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_ssa_parse_src_event)); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); + gst_pad_use_fixed_caps (parse->srcpad); + gst_pad_set_caps (parse->srcpad, + gst_static_pad_template_get_caps (&src_templ)); + + parse->ini = NULL; + parse->framed = FALSE; + parse->send_tags = FALSE; +} + +static void +gst_ssa_parse_class_init (GstSsaParseClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + object_class->dispose = gst_ssa_parse_dispose; + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_ssa_parse_change_state); +} + +static gboolean +gst_ssa_parse_src_event (GstPad * pad, GstEvent * event) +{ + return gst_pad_event_default (pad, event); +} + +static gboolean +gst_ssa_parse_sink_event (GstPad * pad, GstEvent * event) +{ + return gst_pad_event_default (pad, event); +} + +static gboolean +gst_ssa_parse_setcaps (GstPad * sinkpad, GstCaps * caps) +{ + GstSsaParse *parse = GST_SSA_PARSE (GST_PAD_PARENT (sinkpad)); + const GValue *val; + GstStructure *s; + const guchar bom_utf8[] = { 0xEF, 0xBB, 0xBF }; + GstBuffer *priv; + gchar *data; + guint size; + + s = gst_caps_get_structure (caps, 0); + val = gst_structure_get_value (s, "codec_data"); + if (val == NULL) { + parse->framed = FALSE; + GST_ERROR ("Only SSA subtitles embedded in containers are supported"); + return FALSE; + } + + parse->framed = TRUE; + parse->send_tags = TRUE; + + priv = (GstBuffer *) gst_value_get_mini_object (val); + g_return_val_if_fail (priv != NULL, FALSE); + + gst_buffer_ref (priv); + + data = (gchar *) GST_BUFFER_DATA (priv); + size = GST_BUFFER_SIZE (priv); + /* skip UTF-8 BOM */ + if (size >= 3 && memcmp (data, bom_utf8, 3) == 0) { + data += 3; + size -= 3; + } + + if (!strstr (data, "[Script Info]")) { + GST_WARNING_OBJECT (parse, "Invalid Init section - no Script Info header"); + gst_buffer_unref (priv); + return FALSE; + } + + if (!g_utf8_validate (data, size, NULL)) { + GST_WARNING_OBJECT (parse, "Init section is not valid UTF-8"); + gst_buffer_unref (priv); + return FALSE; + } + + /* FIXME: parse initial section */ + parse->ini = g_strndup (data, size); + GST_LOG_OBJECT (parse, "Init section:\n%s", parse->ini); + + gst_buffer_unref (priv); + + return TRUE; +} + +static gboolean +gst_ssa_parse_remove_override_codes (GstSsaParse * parse, gchar * txt) +{ + gchar *t, *end; + gboolean removed_any = FALSE; + + while ((t = strchr (txt, '{'))) { + end = strchr (txt, '}'); + if (end == NULL) { + GST_WARNING_OBJECT (parse, "Missing { for style override code"); + return removed_any; + } + /* move terminating NUL character forward as well */ + g_memmove (t, end + 1, strlen (end + 1) + 1); + removed_any = TRUE; + } + + /* these may occur outside of curly brackets. We don't handle the different + * wrapping modes yet, so just remove these markers from the text for now */ + while ((t = strstr (txt, "\\n"))) { + t[0] = ' '; + t[1] = '\n'; + } + while ((t = strstr (txt, "\\N"))) { + t[0] = ' '; + t[1] = '\n'; + } + while ((t = strstr (txt, "\\h"))) { + t[0] = ' '; + t[1] = ' '; + } + + return removed_any; +} + +/** + * gst_ssa_parse_push_line: + * @parse: caller element + * @txt: text to push + * @start: timestamp for the buffer + * @duration: duration for the buffer + * + * Parse the text in a buffer with the given properties and + * push it to the srcpad of the @parse element + * + * Returns: result of the push of the created buffer + */ +static GstFlowReturn +gst_ssa_parse_push_line (GstSsaParse * parse, gchar * txt, + GstClockTime start, GstClockTime duration) +{ + GstFlowReturn ret; + GstBuffer *buf; + gchar *t, *escaped; + gint num, i, len; + + num = atoi (txt); + GST_LOG_OBJECT (parse, "Parsing line #%d at %" GST_TIME_FORMAT, + num, GST_TIME_ARGS (start)); + + /* skip all non-text fields before the actual text */ + t = txt; + for (i = 0; i < 8; ++i) { + t = strchr (t, ','); + if (t == NULL) + return GST_FLOW_ERROR; + ++t; + } + + GST_LOG_OBJECT (parse, "Text : %s", t); + + if (gst_ssa_parse_remove_override_codes (parse, t)) { + GST_LOG_OBJECT (parse, "Clean: %s", t); + } + + /* we claim to output pango markup, so we must escape the + * text even if we don't actually use any pango markup yet */ + escaped = g_markup_printf_escaped ("%s", t); + + len = strlen (escaped); + + /* allocate enough for a terminating NUL, but don't include it in buf size */ + buf = gst_buffer_new_and_alloc (len + 1); + memcpy (GST_BUFFER_DATA (buf), escaped, len + 1); + GST_BUFFER_SIZE (buf) = len; + g_free (escaped); + + GST_BUFFER_TIMESTAMP (buf) = start; + GST_BUFFER_DURATION (buf) = duration; + + gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad)); + + GST_LOG_OBJECT (parse, "Pushing buffer with timestamp %" GST_TIME_FORMAT + " and duration %" GST_TIME_FORMAT, GST_TIME_ARGS (start), + GST_TIME_ARGS (duration)); + + ret = gst_pad_push (parse->srcpad, buf); + + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (parse, "Push of text '%s' returned flow %s", txt, + gst_flow_get_name (ret)); + } + + return ret; +} + +static GstFlowReturn +gst_ssa_parse_chain (GstPad * sinkpad, GstBuffer * buf) +{ + GstFlowReturn ret; + GstSsaParse *parse = GST_SSA_PARSE (GST_PAD_PARENT (sinkpad)); + GstClockTime ts; + gchar *txt; + + if (G_UNLIKELY (!parse->framed)) + goto not_framed; + + if (G_UNLIKELY (parse->send_tags)) { + GstTagList *tags; + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_SUBTITLE_CODEC, + "SubStation Alpha", NULL); + gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad, tags); + parse->send_tags = FALSE; + } + + /* make double-sure it's 0-terminated and all */ + txt = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + if (txt == NULL) + goto empty_text; + + ts = GST_BUFFER_TIMESTAMP (buf); + ret = gst_ssa_parse_push_line (parse, txt, ts, GST_BUFFER_DURATION (buf)); + + if (ret != GST_FLOW_OK && GST_CLOCK_TIME_IS_VALID (ts)) { + /* just advance time without sending anything */ + gst_pad_push_event (parse->srcpad, + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, ts, -1, ts)); + ret = GST_FLOW_OK; + } + + gst_buffer_unref (buf); + g_free (txt); + + return ret; + +/* ERRORS */ +not_framed: + { + GST_ELEMENT_ERROR (parse, STREAM, FORMAT, (NULL), + ("Only SSA subtitles embedded in containers are supported")); + gst_buffer_unref (buf); + return GST_FLOW_NOT_NEGOTIATED; + } +empty_text: + { + GST_ELEMENT_WARNING (parse, STREAM, FORMAT, (NULL), + ("Received empty subtitle")); + gst_buffer_unref (buf); + return GST_FLOW_OK; + } +} + +static GstStateChangeReturn +gst_ssa_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstSsaParse *parse = GST_SSA_PARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_free (parse->ini); + parse->ini = NULL; + parse->framed = FALSE; + break; + default: + break; + } + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.h b/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.h new file mode 100644 index 0000000..518c3cd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/gstssaparse.h @@ -0,0 +1,57 @@ +/* GStreamer SSA subtitle parser + * Copyright (c) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_SSA_PARSE_H__ +#define __GST_SSA_PARSE_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_SSA_PARSE (gst_ssa_parse_get_type ()) +#define GST_SSA_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SSA_PARSE, GstSsaParse)) +#define GST_SSA_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SSA_PARSE, GstSsaParseClass)) +#define GST_IS_SSA_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SSA_PARSE)) +#define GST_IS_SSA_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SSA_PARSE)) + +typedef struct _GstSsaParse GstSsaParse; +typedef struct _GstSsaParseClass GstSsaParseClass; + +struct _GstSsaParse { + GstElement element; + + GstPad *sinkpad; + GstPad *srcpad; + + gboolean framed; + gboolean send_tags; + + gchar *ini; +}; + +struct _GstSsaParseClass { + GstElementClass parent_class; +}; + +GType gst_ssa_parse_get_type (void); + +G_END_DECLS + +#endif /* __GST_SSA_PARSE_H__ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.c b/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.c new file mode 100644 index 0000000..7bf0f2d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.c @@ -0,0 +1,1886 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2004 Ronald S. Bultje + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include +#include + +#include "gstsubparse.h" +#include "gstssaparse.h" +#include "samiparse.h" +#include "tmplayerparse.h" +#include "mpl2parse.h" +#include "qttextparse.h" + +GST_DEBUG_CATEGORY (sub_parse_debug); + +#define DEFAULT_ENCODING NULL + +enum +{ + PROP_0, + PROP_ENCODING, + PROP_VIDEOFPS +}; + +static void +gst_sub_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void +gst_sub_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + + +#ifndef GST_DISABLE_XML +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-subtitle; application/x-subtitle-sami; " + "application/x-subtitle-tmplayer; application/x-subtitle-mpl2; " + "application/x-subtitle-dks; application/x-subtitle-qttext") + ); +#else +static GstStaticPadTemplate sink_templ = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-subtitle; application/x-subtitle-dks; " + "application/x-subtitle-tmplayer; application/x-subtitle-mpl2; " + "application/x-subtitle-qttext") + ); +#endif + +static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/plain; text/x-pango-markup") + ); + +static void gst_sub_parse_base_init (GstSubParseClass * klass); +static void gst_sub_parse_class_init (GstSubParseClass * klass); +static void gst_sub_parse_init (GstSubParse * subparse); + +static gboolean gst_sub_parse_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_sub_parse_src_query (GstPad * pad, GstQuery * query); +static gboolean gst_sub_parse_sink_event (GstPad * pad, GstEvent * event); + +static GstStateChangeReturn gst_sub_parse_change_state (GstElement * element, + GstStateChange transition); + +static GstFlowReturn gst_sub_parse_chain (GstPad * sinkpad, GstBuffer * buf); + +static GstElementClass *parent_class = NULL; + +GType +gst_sub_parse_get_type (void) +{ + static GType sub_parse_type = 0; + + if (!sub_parse_type) { + static const GTypeInfo sub_parse_info = { + sizeof (GstSubParseClass), + (GBaseInitFunc) gst_sub_parse_base_init, + NULL, + (GClassInitFunc) gst_sub_parse_class_init, + NULL, + NULL, + sizeof (GstSubParse), + 0, + (GInstanceInitFunc) gst_sub_parse_init, + }; + + sub_parse_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstSubParse", &sub_parse_info, 0); + } + + return sub_parse_type; +} + +static void +gst_sub_parse_base_init (GstSubParseClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_templ)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "Subtitle parser", "Codec/Parser/Subtitle", + "Parses subtitle (.sub) files into text streams", + "Gustavo J. A. M. Carneiro , " + "GStreamer maintainers "); +} + +static void +gst_sub_parse_dispose (GObject * object) +{ + GstSubParse *subparse = GST_SUBPARSE (object); + + GST_DEBUG_OBJECT (subparse, "cleaning up subtitle parser"); + + switch (subparse->parser_type) { + case GST_SUB_PARSE_FORMAT_QTTEXT: + qttext_context_deinit (&subparse->state); + break; +#ifndef GST_DISABLE_XML + case GST_SUB_PARSE_FORMAT_SAMI: + sami_context_deinit (&subparse->state); + break; +#endif + default: + break; + } + + if (subparse->encoding) { + g_free (subparse->encoding); + subparse->encoding = NULL; + } + + if (subparse->detected_encoding) { + g_free (subparse->detected_encoding); + subparse->detected_encoding = NULL; + } + + if (subparse->adapter) { + g_object_unref (subparse->adapter); + subparse->adapter = NULL; + } + + if (subparse->textbuf) { + g_string_free (subparse->textbuf, TRUE); + subparse->textbuf = NULL; + } + + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); +} + +static void +gst_sub_parse_class_init (GstSubParseClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->dispose = gst_sub_parse_dispose; + object_class->set_property = gst_sub_parse_set_property; + object_class->get_property = gst_sub_parse_get_property; + + element_class->change_state = gst_sub_parse_change_state; + + g_object_class_install_property (object_class, PROP_ENCODING, + g_param_spec_string ("subtitle-encoding", "subtitle charset encoding", + "Encoding to assume if input subtitles are not in UTF-8 or any other " + "Unicode encoding. If not set, the GST_SUBTITLE_ENCODING environment " + "variable will be checked for an encoding to use. If that is not set " + "either, ISO-8859-15 will be assumed.", DEFAULT_ENCODING, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_VIDEOFPS, + gst_param_spec_fraction ("video-fps", "Video framerate", + "Framerate of the video stream. This is needed by some subtitle " + "formats to synchronize subtitles and video properly. If not set " + "and the subtitle format requires it subtitles may be out of sync.", + 0, 1, G_MAXINT, 1, 24000, 1001, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_sub_parse_init (GstSubParse * subparse) +{ + subparse->sinkpad = gst_pad_new_from_static_template (&sink_templ, "sink"); + gst_pad_set_chain_function (subparse->sinkpad, + GST_DEBUG_FUNCPTR (gst_sub_parse_chain)); + gst_pad_set_event_function (subparse->sinkpad, + GST_DEBUG_FUNCPTR (gst_sub_parse_sink_event)); + gst_element_add_pad (GST_ELEMENT (subparse), subparse->sinkpad); + + subparse->srcpad = gst_pad_new_from_static_template (&src_templ, "src"); + gst_pad_set_event_function (subparse->srcpad, + GST_DEBUG_FUNCPTR (gst_sub_parse_src_event)); + gst_pad_set_query_function (subparse->srcpad, + GST_DEBUG_FUNCPTR (gst_sub_parse_src_query)); + gst_element_add_pad (GST_ELEMENT (subparse), subparse->srcpad); + + subparse->textbuf = g_string_new (NULL); + subparse->parser_type = GST_SUB_PARSE_FORMAT_UNKNOWN; + subparse->flushing = FALSE; + gst_segment_init (&subparse->segment, GST_FORMAT_TIME); + subparse->need_segment = TRUE; + subparse->encoding = g_strdup (DEFAULT_ENCODING); + subparse->detected_encoding = NULL; + subparse->adapter = gst_adapter_new (); + + subparse->fps_n = 24000; + subparse->fps_d = 1001; +} + +/* + * Source pad functions. + */ + +static gboolean +gst_sub_parse_src_query (GstPad * pad, GstQuery * query) +{ + GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad)); + gboolean ret = FALSE; + + GST_DEBUG ("Handling %s query", GST_QUERY_TYPE_NAME (query)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION:{ + GstFormat fmt; + + gst_query_parse_position (query, &fmt, NULL); + if (fmt != GST_FORMAT_TIME) { + ret = gst_pad_peer_query (self->sinkpad, query); + } else { + ret = TRUE; + gst_query_set_position (query, GST_FORMAT_TIME, + self->segment.last_stop); + } + } + case GST_QUERY_SEEKING: + { + GstFormat fmt; + gboolean seekable = FALSE; + + ret = TRUE; + + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + if (fmt == GST_FORMAT_TIME) { + GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); + + seekable = gst_pad_peer_query (self->sinkpad, peerquery); + if (seekable) + gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); + gst_query_unref (peerquery); + } + + gst_query_set_seeking (query, fmt, seekable, seekable ? 0 : -1, -1); + + break; + } + default: + ret = gst_pad_peer_query (self->sinkpad, query); + break; + } + + gst_object_unref (self); + + return ret; +} + +static gboolean +gst_sub_parse_src_event (GstPad * pad, GstEvent * event) +{ + GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad)); + gboolean ret = FALSE; + + GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + GstFormat format; + GstSeekType start_type, stop_type; + gint64 start, stop; + gdouble rate; + gboolean update; + + gst_event_parse_seek (event, &rate, &format, &self->segment_flags, + &start_type, &start, &stop_type, &stop); + + if (format != GST_FORMAT_TIME) { + GST_WARNING_OBJECT (self, "we only support seeking in TIME format"); + gst_event_unref (event); + goto beach; + } + + /* Convert that seek to a seeking in bytes at position 0, + FIXME: could use an index */ + ret = gst_pad_push_event (self->sinkpad, + gst_event_new_seek (rate, GST_FORMAT_BYTES, self->segment_flags, + GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, 0)); + + if (ret) { + /* Apply the seek to our segment */ + gst_segment_set_seek (&self->segment, rate, format, self->segment_flags, + start_type, start, stop_type, stop, &update); + + GST_DEBUG_OBJECT (self, "segment after seek: %" GST_SEGMENT_FORMAT, + &self->segment); + + self->next_offset = 0; + + self->need_segment = TRUE; + } else { + GST_WARNING_OBJECT (self, "seek to 0 bytes failed"); + } + + gst_event_unref (event); + break; + } + default: + ret = gst_pad_event_default (pad, event); + break; + } + +beach: + gst_object_unref (self); + + return ret; +} + +static void +gst_sub_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstSubParse *subparse = GST_SUBPARSE (object); + + GST_OBJECT_LOCK (subparse); + switch (prop_id) { + case PROP_ENCODING: + g_free (subparse->encoding); + subparse->encoding = g_value_dup_string (value); + GST_LOG_OBJECT (object, "subtitle encoding set to %s", + GST_STR_NULL (subparse->encoding)); + break; + case PROP_VIDEOFPS: + { + subparse->fps_n = gst_value_get_fraction_numerator (value); + subparse->fps_d = gst_value_get_fraction_denominator (value); + GST_DEBUG_OBJECT (object, "video framerate set to %d/%d", subparse->fps_n, + subparse->fps_d); + + if (!subparse->state.have_internal_fps) { + subparse->state.fps_n = subparse->fps_n; + subparse->state.fps_d = subparse->fps_d; + } + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (subparse); +} + +static void +gst_sub_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstSubParse *subparse = GST_SUBPARSE (object); + + GST_OBJECT_LOCK (subparse); + switch (prop_id) { + case PROP_ENCODING: + g_value_set_string (value, subparse->encoding); + break; + case PROP_VIDEOFPS: + gst_value_set_fraction (value, subparse->fps_n, subparse->fps_d); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + GST_OBJECT_UNLOCK (subparse); +} + +static const gchar * +gst_sub_parse_get_format_description (GstSubParseFormat format) +{ + switch (format) { + case GST_SUB_PARSE_FORMAT_MDVDSUB: + return "MicroDVD"; + case GST_SUB_PARSE_FORMAT_SUBRIP: + return "SubRip"; + case GST_SUB_PARSE_FORMAT_MPSUB: + return "MPSub"; + case GST_SUB_PARSE_FORMAT_SAMI: + return "SAMI"; + case GST_SUB_PARSE_FORMAT_TMPLAYER: + return "TMPlayer"; + case GST_SUB_PARSE_FORMAT_MPL2: + return "MPL2"; + case GST_SUB_PARSE_FORMAT_SUBVIEWER: + return "SubViewer"; + case GST_SUB_PARSE_FORMAT_DKS: + return "DKS"; + case GST_SUB_PARSE_FORMAT_QTTEXT: + return "QTtext"; + default: + case GST_SUB_PARSE_FORMAT_UNKNOWN: + break; + } + return NULL; +} + +static gchar * +gst_convert_to_utf8 (const gchar * str, gsize len, const gchar * encoding, + gsize * consumed, GError ** err) +{ + gchar *ret = NULL; + + *consumed = 0; + /* The char cast is necessary in glib < 2.24 */ + ret = + g_convert_with_fallback (str, len, "UTF-8", encoding, (char *) "*", + consumed, NULL, err); + if (ret == NULL) + return ret; + + /* + 3 to skip UTF-8 BOM if it was added */ + len = strlen (ret); + if (len >= 3 && (guint8) ret[0] == 0xEF && (guint8) ret[1] == 0xBB + && (guint8) ret[2] == 0xBF) + g_memmove (ret, ret + 3, len + 1 - 3); + + return ret; +} + +static gchar * +detect_encoding (const gchar * str, gsize len) +{ + if (len >= 3 && (guint8) str[0] == 0xEF && (guint8) str[1] == 0xBB + && (guint8) str[2] == 0xBF) + return g_strdup ("UTF-8"); + + if (len >= 2 && (guint8) str[0] == 0xFE && (guint8) str[1] == 0xFF) + return g_strdup ("UTF-16BE"); + + if (len >= 2 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE) + return g_strdup ("UTF-16LE"); + + if (len >= 4 && (guint8) str[0] == 0x00 && (guint8) str[1] == 0x00 + && (guint8) str[2] == 0xFE && (guint8) str[3] == 0xFF) + return g_strdup ("UTF-32BE"); + + if (len >= 4 && (guint8) str[0] == 0xFF && (guint8) str[1] == 0xFE + && (guint8) str[2] == 0x00 && (guint8) str[3] == 0x00) + return g_strdup ("UTF-32LE"); + + return NULL; +} + +static gchar * +convert_encoding (GstSubParse * self, const gchar * str, gsize len, + gsize * consumed) +{ + const gchar *encoding; + GError *err = NULL; + gchar *ret = NULL; + + *consumed = 0; + + /* First try any detected encoding */ + if (self->detected_encoding) { + ret = + gst_convert_to_utf8 (str, len, self->detected_encoding, consumed, &err); + + if (!err) + return ret; + + GST_WARNING_OBJECT (self, "could not convert string from '%s' to UTF-8: %s", + self->detected_encoding, err->message); + g_free (self->detected_encoding); + self->detected_encoding = NULL; + g_error_free (err); + } + + /* Otherwise check if it's UTF8 */ + if (self->valid_utf8) { + if (g_utf8_validate (str, len, NULL)) { + GST_LOG_OBJECT (self, "valid UTF-8, no conversion needed"); + *consumed = len; + return g_strndup (str, len); + } + GST_INFO_OBJECT (self, "invalid UTF-8!"); + self->valid_utf8 = FALSE; + } + + /* Else try fallback */ + encoding = self->encoding; + if (encoding == NULL || *encoding == '\0') { + encoding = g_getenv ("GST_SUBTITLE_ENCODING"); + } + if (encoding == NULL || *encoding == '\0') { + /* if local encoding is UTF-8 and no encoding specified + * via the environment variable, assume ISO-8859-15 */ + if (g_get_charset (&encoding)) { + encoding = "ISO-8859-15"; + } + } + + ret = gst_convert_to_utf8 (str, len, encoding, consumed, &err); + + if (err) { + GST_WARNING_OBJECT (self, "could not convert string from '%s' to UTF-8: %s", + encoding, err->message); + g_error_free (err); + + /* invalid input encoding, fall back to ISO-8859-15 (always succeeds) */ + ret = gst_convert_to_utf8 (str, len, "ISO-8859-15", consumed, NULL); + } + + GST_LOG_OBJECT (self, + "successfully converted %" G_GSIZE_FORMAT " characters from %s to UTF-8" + "%s", len, encoding, (err) ? " , using ISO-8859-15 as fallback" : ""); + + return ret; +} + +static gchar * +get_next_line (GstSubParse * self) +{ + char *line = NULL; + const char *line_end; + int line_len; + gboolean have_r = FALSE; + + line_end = strchr (self->textbuf->str, '\n'); + + if (!line_end) { + /* end-of-line not found; return for more data */ + return NULL; + } + + /* get rid of '\r' */ + if (line_end != self->textbuf->str && *(line_end - 1) == '\r') { + line_end--; + have_r = TRUE; + } + + line_len = line_end - self->textbuf->str; + line = g_strndup (self->textbuf->str, line_len); + self->textbuf = g_string_erase (self->textbuf, 0, + line_len + (have_r ? 2 : 1)); + return line; +} + +static gchar * +parse_mdvdsub (ParserState * state, const gchar * line) +{ + const gchar *line_split; + gchar *line_chunk; + guint start_frame, end_frame; + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg = FALSE; + GString *markup; + gchar *ret; + + /* style variables */ + gboolean italic; + gboolean bold; + guint fontsize; + gdouble fps = 0.0; + + if (sscanf (line, "{%u}{%u}", &start_frame, &end_frame) != 2) { + g_warning ("Parse of the following line, assumed to be in microdvd .sub" + " format, failed:\n%s", line); + return NULL; + } + + /* skip the {%u}{%u} part */ + line = strchr (line, '}') + 1; + line = strchr (line, '}') + 1; + + /* see if there's a first line with a framerate */ + if (start_frame == 1 && end_frame == 1) { + gchar *rest, *end = NULL; + + rest = g_strdup (line); + g_strdelimit (rest, ",", '.'); + fps = g_ascii_strtod (rest, &end); + if (end != rest) { + gst_util_double_to_fraction (fps, &state->fps_n, &state->fps_d); + GST_INFO ("framerate from file: %d/%d ('%s')", state->fps_n, + state->fps_d, rest); + } + g_free (rest); + return NULL; + } + + state->start_time = + gst_util_uint64_scale (start_frame, GST_SECOND * state->fps_d, + state->fps_n); + state->duration = + gst_util_uint64_scale (end_frame - start_frame, GST_SECOND * state->fps_d, + state->fps_n); + + /* Check our segment start/stop */ + in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME, + state->start_time, state->start_time + state->duration, &clip_start, + &clip_stop); + + /* No need to parse that text if it's out of segment */ + if (in_seg) { + state->start_time = clip_start; + state->duration = clip_stop - clip_start; + } else { + return NULL; + } + + markup = g_string_new (NULL); + while (1) { + italic = FALSE; + bold = FALSE; + fontsize = 0; + /* parse style markup */ + if (strncmp (line, "{y:i}", 5) == 0) { + italic = TRUE; + line = strchr (line, '}') + 1; + } + if (strncmp (line, "{y:b}", 5) == 0) { + bold = TRUE; + line = strchr (line, '}') + 1; + } + if (sscanf (line, "{s:%u}", &fontsize) == 1) { + line = strchr (line, '}') + 1; + } + /* forward slashes at beginning/end signify italics too */ + if (g_str_has_prefix (line, "/")) { + italic = TRUE; + ++line; + } + if ((line_split = strchr (line, '|'))) + line_chunk = g_markup_escape_text (line, line_split - line); + else + line_chunk = g_markup_escape_text (line, strlen (line)); + + /* Remove italics markers at end of line/stanza (CHECKME: are end slashes + * always at the end of a line or can they span multiple lines?) */ + if (g_str_has_suffix (line_chunk, "/")) { + line_chunk[strlen (line_chunk) - 1] = '\0'; + } + + markup = g_string_append (markup, "%s", line_chunk); + g_free (line_chunk); + if (line_split) { + g_string_append (markup, "\n"); + line = line_split + 1; + } else { + break; + } + } + ret = markup->str; + g_string_free (markup, FALSE); + GST_DEBUG ("parse_mdvdsub returning (%f+%f): %s", + state->start_time / (double) GST_SECOND, + state->duration / (double) GST_SECOND, ret); + return ret; +} + +static void +strip_trailing_newlines (gchar * txt) +{ + if (txt) { + guint len; + + len = strlen (txt); + while (len > 1 && txt[len - 1] == '\n') { + txt[len - 1] = '\0'; + --len; + } + } +} + +/* we want to escape text in general, but retain basic markup like + * , , and . The easiest and safest way is to + * just unescape a white list of allowed markups again after + * escaping everything (the text between these simple markers isn't + * necessarily escaped, so it seems best to do it like this) */ +static void +subrip_unescape_formatting (gchar * txt) +{ + gchar *pos; + + for (pos = txt; pos != NULL && *pos != '\0'; ++pos) { + if (g_ascii_strncasecmp (pos, "<u>", 9) == 0 || + g_ascii_strncasecmp (pos, "<i>", 9) == 0 || + g_ascii_strncasecmp (pos, "<b>", 9) == 0) { + pos[0] = '<'; + pos[1] = g_ascii_tolower (pos[4]); + pos[2] = '>'; + /* move NUL terminator as well */ + g_memmove (pos + 3, pos + 9, strlen (pos + 9) + 1); + pos += 2; + } + } + + for (pos = txt; pos != NULL && *pos != '\0'; ++pos) { + if (g_ascii_strncasecmp (pos, "</u>", 10) == 0 || + g_ascii_strncasecmp (pos, "</i>", 10) == 0 || + g_ascii_strncasecmp (pos, "</b>", 10) == 0) { + pos[0] = '<'; + pos[1] = '/'; + pos[2] = g_ascii_tolower (pos[5]); + pos[3] = '>'; + /* move NUL terminator as well */ + g_memmove (pos + 4, pos + 10, strlen (pos + 10) + 1); + pos += 3; + } + } +} + + +static gboolean +subrip_remove_unhandled_tag (gchar * start, gchar * stop) +{ + gchar *tag, saved; + + tag = start + strlen ("<"); + if (*tag == '/') + ++tag; + + if (g_ascii_tolower (*tag) < 'a' || g_ascii_tolower (*tag) > 'z') + return FALSE; + + saved = *stop; + *stop = '\0'; + GST_LOG ("removing unhandled tag '%s'", start); + *stop = saved; + g_memmove (start, stop, strlen (stop) + 1); + return TRUE; +} + +/* remove tags we haven't explicitly allowed earlier on, like font tags + * for example */ +static void +subrip_remove_unhandled_tags (gchar * txt) +{ + gchar *pos, *gt; + + for (pos = txt; pos != NULL && *pos != '\0'; ++pos) { + if (strncmp (pos, "<", 4) == 0 && (gt = strstr (pos + 4, ">"))) { + if (subrip_remove_unhandled_tag (pos, gt + strlen (">"))) + --pos; + } + } +} + +/* we only allow , and , so let's take a simple approach. This code + * assumes the input has been escaped and subrip_unescape_formatting() has then + * been run over the input! This function adds missing closing markup tags and + * removes broken closing tags for tags that have never been opened. */ +static void +subrip_fix_up_markup (gchar ** p_txt) +{ + gchar *cur, *next_tag; + gchar open_tags[32]; + guint num_open_tags = 0; + + g_assert (*p_txt != NULL); + + cur = *p_txt; + while (*cur != '\0') { + next_tag = strchr (cur, '<'); + if (next_tag == NULL) + break; + ++next_tag; + switch (*next_tag) { + case '/':{ + ++next_tag; + if (num_open_tags == 0 || open_tags[num_open_tags - 1] != *next_tag) { + GST_LOG ("broken input, closing tag '%c' is not open", *next_tag); + g_memmove (next_tag - 2, next_tag + 2, strlen (next_tag + 2) + 1); + next_tag -= 2; + } else { + /* it's all good, closing tag which is open */ + --num_open_tags; + } + break; + } + case 'i': + case 'b': + case 'u': + if (num_open_tags == G_N_ELEMENTS (open_tags)) + return; /* something dodgy is going on, stop parsing */ + open_tags[num_open_tags] = *next_tag; + ++num_open_tags; + break; + default: + GST_ERROR ("unexpected tag '%c' (%s)", *next_tag, next_tag); + g_assert_not_reached (); + break; + } + cur = next_tag; + } + + if (num_open_tags > 0) { + GString *s; + + s = g_string_new (*p_txt); + while (num_open_tags > 0) { + GST_LOG ("adding missing closing tag '%c'", open_tags[num_open_tags - 1]); + g_string_append_c (s, '<'); + g_string_append_c (s, '/'); + g_string_append_c (s, open_tags[num_open_tags - 1]); + g_string_append_c (s, '>'); + --num_open_tags; + } + g_free (*p_txt); + *p_txt = g_string_free (s, FALSE); + } +} + +static gboolean +parse_subrip_time (const gchar * ts_string, GstClockTime * t) +{ + gchar s[128] = { '\0', }; + gchar *end, *p; + guint hour, min, sec, msec, len; + + while (*ts_string == ' ') + ++ts_string; + + g_strlcpy (s, ts_string, sizeof (s)); + if ((end = strstr (s, "-->"))) + *end = '\0'; + g_strchomp (s); + + /* ms may be in these formats: + * hh:mm:ss,500 = 500ms + * hh:mm:ss, 5 = 5ms + * hh:mm:ss, 5 = 50ms + * hh:mm:ss, 50 = 50ms + * hh:mm:ss,5 = 500ms + * and the same with . instead of ,. + * sscanf() doesn't differentiate between ' 5' and '5' so munge + * the white spaces within the timestamp to '0' (I'm sure there's a + * way to make sscanf() do this for us, but how?) + */ + g_strdelimit (s, " ", '0'); + g_strdelimit (s, ".", ','); + + /* make sure we have exactly three digits after he comma */ + p = strchr (s, ','); + g_assert (p != NULL); + ++p; + len = strlen (p); + if (len > 3) { + p[3] = '\0'; + } else + while (len < 3) { + g_strlcat (&p[len], "0", 2); + ++len; + } + + GST_LOG ("parsing timestamp '%s'", s); + if (sscanf (s, "%u:%u:%u,%u", &hour, &min, &sec, &msec) != 4) { + GST_WARNING ("failed to parse subrip timestamp string '%s'", s); + return FALSE; + } + + *t = ((hour * 3600) + (min * 60) + sec) * GST_SECOND + msec * GST_MSECOND; + return TRUE; +} + +static gchar * +parse_subrip (ParserState * state, const gchar * line) +{ + int subnum; + gchar *ret; + + switch (state->state) { + case 0: + /* looking for a single integer */ + if (sscanf (line, "%u", &subnum) == 1) + state->state = 1; + return NULL; + case 1: + { + GstClockTime ts_start, ts_end; + gchar *end_time; + + /* looking for start_time --> end_time */ + if ((end_time = strstr (line, " --> ")) && + parse_subrip_time (line, &ts_start) && + parse_subrip_time (end_time + strlen (" --> "), &ts_end) && + state->start_time <= ts_end) { + state->state = 2; + state->start_time = ts_start; + state->duration = ts_end - ts_start; + } else { + GST_DEBUG ("error parsing subrip time line '%s'", line); + state->state = 0; + } + return NULL; + } + case 2: + { + /* No need to parse that text if it's out of segment */ + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg = FALSE; + + /* Check our segment start/stop */ + in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME, + state->start_time, state->start_time + state->duration, + &clip_start, &clip_stop); + + if (in_seg) { + state->start_time = clip_start; + state->duration = clip_stop - clip_start; + } else { + state->state = 0; + return NULL; + } + } + /* looking for subtitle text; empty line ends this subtitle entry */ + if (state->buf->len) + g_string_append_c (state->buf, '\n'); + g_string_append (state->buf, line); + if (strlen (line) == 0) { + ret = g_markup_escape_text (state->buf->str, state->buf->len); + g_string_truncate (state->buf, 0); + state->state = 0; + subrip_unescape_formatting (ret); + subrip_remove_unhandled_tags (ret); + strip_trailing_newlines (ret); + subrip_fix_up_markup (&ret); + return ret; + } + return NULL; + default: + g_return_val_if_reached (NULL); + } +} + +static void +unescape_newlines_br (gchar * read) +{ + gchar *write = read; + + /* Replace all occurences of '[br]' with a newline as version 2 + * of the subviewer format uses this for newlines */ + + if (read[0] == '\0' || read[1] == '\0' || read[2] == '\0' || read[3] == '\0') + return; + + do { + if (strncmp (read, "[br]", 4) == 0) { + *write = '\n'; + read += 4; + } else { + *write = *read; + read++; + } + write++; + } while (*read); + + *write = '\0'; +} + +static gchar * +parse_subviewer (ParserState * state, const gchar * line) +{ + guint h1, m1, s1, ms1; + guint h2, m2, s2, ms2; + gchar *ret; + + /* TODO: Maybe also parse the fields in the header, especially DELAY. + * For examples see the unit test or + * http://www.doom9.org/index.html?/sub.htm */ + + switch (state->state) { + case 0: + /* looking for start_time,end_time */ + if (sscanf (line, "%u:%u:%u.%u,%u:%u:%u.%u", + &h1, &m1, &s1, &ms1, &h2, &m2, &s2, &ms2) == 8) { + state->state = 1; + state->start_time = + (((guint64) h1) * 3600 + m1 * 60 + s1) * GST_SECOND + + ms1 * GST_MSECOND; + state->duration = + (((guint64) h2) * 3600 + m2 * 60 + s2) * GST_SECOND + + ms2 * GST_MSECOND - state->start_time; + } + return NULL; + case 1: + { + /* No need to parse that text if it's out of segment */ + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg = FALSE; + + /* Check our segment start/stop */ + in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME, + state->start_time, state->start_time + state->duration, + &clip_start, &clip_stop); + + if (in_seg) { + state->start_time = clip_start; + state->duration = clip_stop - clip_start; + } else { + state->state = 0; + return NULL; + } + } + /* looking for subtitle text; empty line ends this subtitle entry */ + if (state->buf->len) + g_string_append_c (state->buf, '\n'); + g_string_append (state->buf, line); + if (strlen (line) == 0) { + ret = g_strdup (state->buf->str); + unescape_newlines_br (ret); + strip_trailing_newlines (ret); + g_string_truncate (state->buf, 0); + state->state = 0; + return ret; + } + return NULL; + default: + g_assert_not_reached (); + return NULL; + } +} + +static gchar * +parse_mpsub (ParserState * state, const gchar * line) +{ + gchar *ret; + float t1, t2; + + switch (state->state) { + case 0: + /* looking for two floats (offset, duration) */ + if (sscanf (line, "%f %f", &t1, &t2) == 2) { + state->state = 1; + state->start_time += state->duration + GST_SECOND * t1; + state->duration = GST_SECOND * t2; + } + return NULL; + case 1: + { /* No need to parse that text if it's out of segment */ + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg = FALSE; + + /* Check our segment start/stop */ + in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME, + state->start_time, state->start_time + state->duration, + &clip_start, &clip_stop); + + if (in_seg) { + state->start_time = clip_start; + state->duration = clip_stop - clip_start; + } else { + state->state = 0; + return NULL; + } + } + /* looking for subtitle text; empty line ends this + * subtitle entry */ + if (state->buf->len) + g_string_append_c (state->buf, '\n'); + g_string_append (state->buf, line); + if (strlen (line) == 0) { + ret = g_strdup (state->buf->str); + g_string_truncate (state->buf, 0); + state->state = 0; + return ret; + } + return NULL; + default: + g_assert_not_reached (); + return NULL; + } +} + +static const gchar * +dks_skip_timestamp (const gchar * line) +{ + while (*line && *line != ']') + line++; + if (*line == ']') + line++; + return line; +} + +static gchar * +parse_dks (ParserState * state, const gchar * line) +{ + guint h, m, s; + + switch (state->state) { + case 0: + /* Looking for the start time and text */ + if (sscanf (line, "[%u:%u:%u]", &h, &m, &s) == 3) { + const gchar *text; + state->start_time = (((guint64) h) * 3600 + m * 60 + s) * GST_SECOND; + text = dks_skip_timestamp (line); + if (*text) { + state->state = 1; + g_string_append (state->buf, text); + } + } + return NULL; + case 1: + { + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg; + gchar *ret; + + /* Looking for the end time */ + if (sscanf (line, "[%u:%u:%u]", &h, &m, &s) == 3) { + state->state = 0; + state->duration = (((guint64) h) * 3600 + m * 60 + s) * GST_SECOND - + state->start_time; + } else { + GST_WARNING ("Failed to parse subtitle end time"); + return NULL; + } + + /* Check if this subtitle is out of the current segment */ + in_seg = gst_segment_clip (state->segment, GST_FORMAT_TIME, + state->start_time, state->start_time + state->duration, + &clip_start, &clip_stop); + + if (!in_seg) { + return NULL; + } + + state->start_time = clip_start; + state->duration = clip_stop - clip_start; + + ret = g_strdup (state->buf->str); + g_string_truncate (state->buf, 0); + unescape_newlines_br (ret); + return ret; + } + default: + g_assert_not_reached (); + return NULL; + } +} + +static void +parser_state_init (ParserState * state) +{ + GST_DEBUG ("initialising parser"); + + if (state->buf) { + g_string_truncate (state->buf, 0); + } else { + state->buf = g_string_new (NULL); + } + + state->start_time = 0; + state->duration = 0; + state->max_duration = 0; /* no limit */ + state->state = 0; + state->segment = NULL; +} + +static void +parser_state_dispose (GstSubParse * self, ParserState * state) +{ + if (state->buf) { + g_string_free (state->buf, TRUE); + state->buf = NULL; + } + if (state->user_data) { + switch (self->parser_type) { +#ifndef GST_DISABLE_XML + case GST_SUB_PARSE_FORMAT_SAMI: + sami_context_reset (state); + break; +#endif + default: + break; + } + } +} + +/* regex type enum */ +typedef enum +{ + GST_SUB_PARSE_REGEX_UNKNOWN = 0, + GST_SUB_PARSE_REGEX_MDVDSUB = 1, + GST_SUB_PARSE_REGEX_SUBRIP = 2, + GST_SUB_PARSE_REGEX_DKS = 3, +} GstSubParseRegex; + +static gpointer +gst_sub_parse_data_format_autodetect_regex_once (GstSubParseRegex regtype) +{ + gpointer result = NULL; + GError *gerr = NULL; + switch (regtype) { + case GST_SUB_PARSE_REGEX_MDVDSUB: + result = + (gpointer) g_regex_new ("^\\{[0-9]+\\}\\{[0-9]+\\}", 0, 0, &gerr); + if (result == NULL) { + g_warning ("Compilation of mdvd regex failed: %s", gerr->message); + g_error_free (gerr); + } + break; + case GST_SUB_PARSE_REGEX_SUBRIP: + result = (gpointer) g_regex_new ("^([ 0-9]){0,3}[0-9]\\s*(\x0d)?\x0a" + "[ 0-9][0-9]:[ 0-9][0-9]:[ 0-9][0-9][,.][ 0-9]{0,2}[0-9]" + " +--> +([ 0-9])?[0-9]:[ 0-9][0-9]:[ 0-9][0-9][,.][ 0-9]{0,2}[0-9]", + 0, 0, &gerr); + if (result == NULL) { + g_warning ("Compilation of subrip regex failed: %s", gerr->message); + g_error_free (gerr); + } + break; + case GST_SUB_PARSE_REGEX_DKS: + result = (gpointer) g_regex_new ("^\\[[0-9]+:[0-9]+:[0-9]+\\].*", + 0, 0, &gerr); + if (result == NULL) { + g_warning ("Compilation of dks regex failed: %s", gerr->message); + g_error_free (gerr); + } + break; + default: + GST_WARNING ("Trying to allocate regex of unknown type %u", regtype); + } + return result; +} + +/* + * FIXME: maybe we should pass along a second argument, the preceding + * text buffer, because that is how this originally worked, even though + * I don't really see the use of that. + */ + +static GstSubParseFormat +gst_sub_parse_data_format_autodetect (gchar * match_str) +{ + guint n1, n2, n3; + + static GOnce mdvd_rx_once = G_ONCE_INIT; + static GOnce subrip_rx_once = G_ONCE_INIT; + static GOnce dks_rx_once = G_ONCE_INIT; + + GRegex *mdvd_grx; + GRegex *subrip_grx; + GRegex *dks_grx; + + g_once (&mdvd_rx_once, + (GThreadFunc) gst_sub_parse_data_format_autodetect_regex_once, + (gpointer) GST_SUB_PARSE_REGEX_MDVDSUB); + g_once (&subrip_rx_once, + (GThreadFunc) gst_sub_parse_data_format_autodetect_regex_once, + (gpointer) GST_SUB_PARSE_REGEX_SUBRIP); + g_once (&dks_rx_once, + (GThreadFunc) gst_sub_parse_data_format_autodetect_regex_once, + (gpointer) GST_SUB_PARSE_REGEX_DKS); + + mdvd_grx = (GRegex *) mdvd_rx_once.retval; + subrip_grx = (GRegex *) subrip_rx_once.retval; + dks_grx = (GRegex *) dks_rx_once.retval; + + if (g_regex_match (mdvd_grx, match_str, 0, NULL) == TRUE) { + GST_LOG ("MicroDVD (frame based) format detected"); + return GST_SUB_PARSE_FORMAT_MDVDSUB; + } + if (g_regex_match (subrip_grx, match_str, 0, NULL) == TRUE) { + GST_LOG ("SubRip (time based) format detected"); + return GST_SUB_PARSE_FORMAT_SUBRIP; + } + if (g_regex_match (dks_grx, match_str, 0, NULL) == TRUE) { + GST_LOG ("DKS (time based) format detected"); + return GST_SUB_PARSE_FORMAT_DKS; + } + + if (!strncmp (match_str, "FORMAT=TIME", 11)) { + GST_LOG ("MPSub (time based) format detected"); + return GST_SUB_PARSE_FORMAT_MPSUB; + } +#ifndef GST_DISABLE_XML + if (strstr (match_str, "") != NULL || + strstr (match_str, "") != NULL) { + GST_LOG ("SAMI (time based) format detected"); + return GST_SUB_PARSE_FORMAT_SAMI; + } +#endif + /* we're boldly assuming the first subtitle appears within the first hour */ + if (sscanf (match_str, "0:%02u:%02u:", &n1, &n2) == 2 || + sscanf (match_str, "0:%02u:%02u=", &n1, &n2) == 2 || + sscanf (match_str, "00:%02u:%02u:", &n1, &n2) == 2 || + sscanf (match_str, "00:%02u:%02u=", &n1, &n2) == 2 || + sscanf (match_str, "00:%02u:%02u,%u=", &n1, &n2, &n3) == 3) { + GST_LOG ("TMPlayer (time based) format detected"); + return GST_SUB_PARSE_FORMAT_TMPLAYER; + } + if (sscanf (match_str, "[%u][%u]", &n1, &n2) == 2) { + GST_LOG ("MPL2 (time based) format detected"); + return GST_SUB_PARSE_FORMAT_MPL2; + } + if (strstr (match_str, "[INFORMATION]") != NULL) { + GST_LOG ("SubViewer (time based) format detected"); + return GST_SUB_PARSE_FORMAT_SUBVIEWER; + } + if (strstr (match_str, "{QTtext}") != NULL) { + GST_LOG ("QTtext (time based) format detected"); + return GST_SUB_PARSE_FORMAT_QTTEXT; + } + + GST_DEBUG ("no subtitle format detected"); + return GST_SUB_PARSE_FORMAT_UNKNOWN; +} + +static GstCaps * +gst_sub_parse_format_autodetect (GstSubParse * self) +{ + gchar *data; + GstSubParseFormat format; + + if (strlen (self->textbuf->str) < 30) { + GST_DEBUG ("File too small to be a subtitles file"); + return NULL; + } + + data = g_strndup (self->textbuf->str, 35); + format = gst_sub_parse_data_format_autodetect (data); + g_free (data); + + self->parser_type = format; + self->subtitle_codec = gst_sub_parse_get_format_description (format); + parser_state_init (&self->state); + + switch (format) { + case GST_SUB_PARSE_FORMAT_MDVDSUB: + self->parse_line = parse_mdvdsub; + return gst_caps_new_simple ("text/x-pango-markup", NULL); + case GST_SUB_PARSE_FORMAT_SUBRIP: + self->parse_line = parse_subrip; + return gst_caps_new_simple ("text/x-pango-markup", NULL); + case GST_SUB_PARSE_FORMAT_MPSUB: + self->parse_line = parse_mpsub; + return gst_caps_new_simple ("text/plain", NULL); +#ifndef GST_DISABLE_XML + case GST_SUB_PARSE_FORMAT_SAMI: + self->parse_line = parse_sami; + sami_context_init (&self->state); + return gst_caps_new_simple ("text/x-pango-markup", NULL); +#endif + case GST_SUB_PARSE_FORMAT_TMPLAYER: + self->parse_line = parse_tmplayer; + self->state.max_duration = 5 * GST_SECOND; + return gst_caps_new_simple ("text/plain", NULL); + case GST_SUB_PARSE_FORMAT_MPL2: + self->parse_line = parse_mpl2; + return gst_caps_new_simple ("text/x-pango-markup", NULL); + case GST_SUB_PARSE_FORMAT_DKS: + self->parse_line = parse_dks; + return gst_caps_new_simple ("text/plain", NULL); + case GST_SUB_PARSE_FORMAT_SUBVIEWER: + self->parse_line = parse_subviewer; + return gst_caps_new_simple ("text/plain", NULL); + case GST_SUB_PARSE_FORMAT_QTTEXT: + self->parse_line = parse_qttext; + qttext_context_init (&self->state); + return gst_caps_new_simple ("text/x-pango-markup", NULL); + case GST_SUB_PARSE_FORMAT_UNKNOWN: + default: + GST_DEBUG ("no subtitle format detected"); + GST_ELEMENT_ERROR (self, STREAM, WRONG_TYPE, + ("The input is not a valid/supported subtitle file"), (NULL)); + return NULL; + } +} + +static void +feed_textbuf (GstSubParse * self, GstBuffer * buf) +{ + gboolean discont; + gsize consumed; + gchar *input = NULL; + + discont = GST_BUFFER_IS_DISCONT (buf); + + if (GST_BUFFER_OFFSET_IS_VALID (buf) && + GST_BUFFER_OFFSET (buf) != self->offset) { + self->offset = GST_BUFFER_OFFSET (buf); + discont = TRUE; + } + + if (discont) { + GST_INFO ("discontinuity"); + /* flush the parser state */ + parser_state_init (&self->state); + g_string_truncate (self->textbuf, 0); + gst_adapter_clear (self->adapter); +#ifndef GST_DISABLE_XML + if (self->parser_type == GST_SUB_PARSE_FORMAT_SAMI) + sami_context_reset (&self->state); +#endif + /* we could set a flag to make sure that the next buffer we push out also + * has the DISCONT flag set, but there's no point really given that it's + * subtitles which are discontinuous by nature. */ + } + + self->offset = GST_BUFFER_OFFSET (buf) + GST_BUFFER_SIZE (buf); + self->next_offset = self->offset; + + gst_adapter_push (self->adapter, buf); + + input = + convert_encoding (self, (const gchar *) gst_adapter_peek (self->adapter, + gst_adapter_available (self->adapter)), + (gsize) gst_adapter_available (self->adapter), &consumed); + + if (input && consumed > 0) { + self->textbuf = g_string_append (self->textbuf, input); + gst_adapter_flush (self->adapter, consumed); + } + + g_free (input); +} + +static GstFlowReturn +handle_buffer (GstSubParse * self, GstBuffer * buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstCaps *caps = NULL; + gchar *line, *subtitle; + + if (self->first_buffer) { + self->detected_encoding = + detect_encoding ((gchar *) GST_BUFFER_DATA (buf), + GST_BUFFER_SIZE (buf)); + self->first_buffer = FALSE; + self->state.fps_n = self->fps_n; + self->state.fps_d = self->fps_d; + } + + feed_textbuf (self, buf); + + /* make sure we know the format */ + if (G_UNLIKELY (self->parser_type == GST_SUB_PARSE_FORMAT_UNKNOWN)) { + if (!(caps = gst_sub_parse_format_autodetect (self))) { + return GST_FLOW_UNEXPECTED; + } + if (!gst_pad_set_caps (self->srcpad, caps)) { + gst_caps_unref (caps); + return GST_FLOW_UNEXPECTED; + } + gst_caps_unref (caps); + + /* push tags */ + if (self->subtitle_codec != NULL) { + GstTagList *tags; + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_APPEND, GST_TAG_SUBTITLE_CODEC, + self->subtitle_codec, NULL); + gst_element_found_tags_for_pad (GST_ELEMENT (self), self->srcpad, tags); + } + } + + while (!self->flushing && (line = get_next_line (self))) { + guint offset = 0; + + /* Set segment on our parser state machine */ + self->state.segment = &self->segment; + /* Now parse the line, out of segment lines will just return NULL */ + GST_LOG_OBJECT (self, "Parsing line '%s'", line + offset); + subtitle = self->parse_line (&self->state, line + offset); + g_free (line); + + if (subtitle) { + guint subtitle_len = strlen (subtitle); + + /* +1 for terminating NUL character */ + ret = gst_pad_alloc_buffer_and_set_caps (self->srcpad, + GST_BUFFER_OFFSET_NONE, subtitle_len + 1, + GST_PAD_CAPS (self->srcpad), &buf); + + if (ret == GST_FLOW_OK) { + /* copy terminating NUL character as well */ + memcpy (GST_BUFFER_DATA (buf), subtitle, subtitle_len + 1); + GST_BUFFER_SIZE (buf) = subtitle_len; + GST_BUFFER_TIMESTAMP (buf) = self->state.start_time; + GST_BUFFER_DURATION (buf) = self->state.duration; + + /* in some cases (e.g. tmplayer) we can only determine the duration + * of a text chunk from the timestamp of the next text chunk; in those + * cases, we probably want to limit the duration to something + * reasonable, so we don't end up showing some text for e.g. 40 seconds + * just because nothing else is being said during that time */ + if (self->state.max_duration > 0 && GST_BUFFER_DURATION_IS_VALID (buf)) { + if (GST_BUFFER_DURATION (buf) > self->state.max_duration) + GST_BUFFER_DURATION (buf) = self->state.max_duration; + } + + gst_segment_set_last_stop (&self->segment, GST_FORMAT_TIME, + self->state.start_time); + + GST_DEBUG_OBJECT (self, "Sending text '%s', %" GST_TIME_FORMAT " + %" + GST_TIME_FORMAT, subtitle, GST_TIME_ARGS (self->state.start_time), + GST_TIME_ARGS (self->state.duration)); + + ret = gst_pad_push (self->srcpad, buf); + } + + /* move this forward (the tmplayer parser needs this) */ + if (self->state.duration != GST_CLOCK_TIME_NONE) + self->state.start_time += self->state.duration; + + g_free (subtitle); + subtitle = NULL; + + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (self, "flow: %s", gst_flow_get_name (ret)); + break; + } + } + } + + return ret; +} + +static GstFlowReturn +gst_sub_parse_chain (GstPad * sinkpad, GstBuffer * buf) +{ + GstFlowReturn ret; + GstSubParse *self; + + self = GST_SUBPARSE (GST_PAD_PARENT (sinkpad)); + + /* Push newsegment if needed */ + if (self->need_segment) { + GST_LOG_OBJECT (self, "pushing newsegment event with %" GST_SEGMENT_FORMAT, + &self->segment); + + gst_pad_push_event (self->srcpad, gst_event_new_new_segment (FALSE, + self->segment.rate, self->segment.format, + self->segment.last_stop, self->segment.stop, self->segment.time)); + self->need_segment = FALSE; + } + + ret = handle_buffer (self, buf); + + return ret; +} + +static gboolean +gst_sub_parse_sink_event (GstPad * pad, GstEvent * event) +{ + GstSubParse *self = GST_SUBPARSE (gst_pad_get_parent (pad)); + gboolean ret = FALSE; + + GST_DEBUG ("Handling %s event", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS:{ + /* Make sure the last subrip chunk is pushed out even + * if the file does not have an empty line at the end */ + if (self->parser_type == GST_SUB_PARSE_FORMAT_SUBRIP || + self->parser_type == GST_SUB_PARSE_FORMAT_TMPLAYER || + self->parser_type == GST_SUB_PARSE_FORMAT_MPL2 || + self->parser_type == GST_SUB_PARSE_FORMAT_QTTEXT) { + GstBuffer *buf = gst_buffer_new_and_alloc (2 + 1); + + GST_DEBUG ("EOS. Pushing remaining text (if any)"); + GST_BUFFER_DATA (buf)[0] = '\n'; + GST_BUFFER_DATA (buf)[1] = '\n'; + GST_BUFFER_DATA (buf)[2] = '\0'; /* play it safe */ + GST_BUFFER_SIZE (buf) = 2; + GST_BUFFER_OFFSET (buf) = self->offset; + gst_sub_parse_chain (pad, buf); + } + ret = gst_pad_event_default (pad, event); + break; + } + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate; + gint64 start, stop, time; + gboolean update; + + gst_event_parse_new_segment (event, &update, &rate, &format, &start, + &stop, &time); + + GST_DEBUG_OBJECT (self, "newsegment (%s)", gst_format_get_name (format)); + + if (format == GST_FORMAT_TIME) { + gst_segment_set_newsegment (&self->segment, update, rate, format, + start, stop, time); + } else { + /* if not time format, we'll either start with a 0 timestamp anyway or + * it's following a seek in which case we'll have saved the requested + * seek segment and don't want to overwrite it (remember that on a seek + * we always just seek back to the start in BYTES format and just throw + * away all text that's before the requested position; if the subtitles + * come from an upstream demuxer, it won't be able to handle our BYTES + * seek request and instead send us a newsegment from the seek request + * it received via its video pads instead, so all is fine then too) */ + } + + ret = TRUE; + gst_event_unref (event); + break; + } + case GST_EVENT_FLUSH_START: + { + self->flushing = TRUE; + + ret = gst_pad_event_default (pad, event); + break; + } + case GST_EVENT_FLUSH_STOP: + { + self->flushing = FALSE; + + ret = gst_pad_event_default (pad, event); + break; + } + default: + ret = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (self); + + return ret; +} + + +static GstStateChangeReturn +gst_sub_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstSubParse *self = GST_SUBPARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* format detection will init the parser state */ + self->offset = 0; + self->next_offset = 0; + self->parser_type = GST_SUB_PARSE_FORMAT_UNKNOWN; + self->valid_utf8 = TRUE; + self->first_buffer = TRUE; + g_free (self->detected_encoding); + self->detected_encoding = NULL; + g_string_truncate (self->textbuf, 0); + gst_adapter_clear (self->adapter); + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + parser_state_dispose (self, &self->state); + self->parser_type = GST_SUB_PARSE_FORMAT_UNKNOWN; + break; + default: + break; + } + + return ret; +} + +/* + * Typefind support. + */ + +/* FIXME 0.11: these caps are ugly, use app/x-subtitle + type field or so; + * also, give different subtitle formats really different types */ +static GstStaticCaps mpl2_caps = +GST_STATIC_CAPS ("application/x-subtitle-mpl2"); +#define SUB_CAPS (gst_static_caps_get (&sub_caps)) + +static GstStaticCaps tmp_caps = +GST_STATIC_CAPS ("application/x-subtitle-tmplayer"); +#define TMP_CAPS (gst_static_caps_get (&tmp_caps)) + +static GstStaticCaps sub_caps = GST_STATIC_CAPS ("application/x-subtitle"); +#define MPL2_CAPS (gst_static_caps_get (&mpl2_caps)) + +#ifndef GST_DISABLE_XML +static GstStaticCaps smi_caps = GST_STATIC_CAPS ("application/x-subtitle-sami"); +#define SAMI_CAPS (gst_static_caps_get (&smi_caps)) +#endif + +static GstStaticCaps dks_caps = GST_STATIC_CAPS ("application/x-subtitle-dks"); +#define DKS_CAPS (gst_static_caps_get (&dks_caps)) + +static GstStaticCaps qttext_caps = +GST_STATIC_CAPS ("application/x-subtitle-qttext"); +#define QTTEXT_CAPS (gst_static_caps_get (&qttext_caps)) + +static void +gst_subparse_type_find (GstTypeFind * tf, gpointer private) +{ + GstSubParseFormat format; + const guint8 *data; + GstCaps *caps; + gchar *str; + gchar *encoding = NULL; + const gchar *end; + + if (!(data = gst_type_find_peek (tf, 0, 129))) + return; + + /* make sure string passed to _autodetect() is NUL-terminated */ + str = g_malloc0 (129); + memcpy (str, data, 128); + + if ((encoding = detect_encoding (str, 128)) != NULL) { + gchar *converted_str; + GError *err = NULL; + gsize tmp; + + converted_str = gst_convert_to_utf8 (str, 128, encoding, &tmp, &err); + if (converted_str == NULL) { + GST_DEBUG ("Encoding '%s' detected but conversion failed: %s", encoding, + err->message); + g_error_free (err); + g_free (encoding); + } else { + g_free (str); + str = converted_str; + g_free (encoding); + } + } + + /* Check if at least the first 120 chars are valid UTF8, + * otherwise convert as always */ + if (!g_utf8_validate (str, 128, &end) && (end - str) < 120) { + gchar *converted_str; + GError *err = NULL; + gsize tmp; + const gchar *enc; + + enc = g_getenv ("GST_SUBTITLE_ENCODING"); + if (enc == NULL || *enc == '\0') { + /* if local encoding is UTF-8 and no encoding specified + * via the environment variable, assume ISO-8859-15 */ + if (g_get_charset (&enc)) { + enc = "ISO-8859-15"; + } + } + converted_str = gst_convert_to_utf8 (str, 128, enc, &tmp, &err); + if (converted_str == NULL) { + GST_DEBUG ("Charset conversion failed: %s", err->message); + g_error_free (err); + g_free (str); + return; + } else { + g_free (str); + str = converted_str; + } + } + + format = gst_sub_parse_data_format_autodetect (str); + g_free (str); + + switch (format) { + case GST_SUB_PARSE_FORMAT_MDVDSUB: + GST_DEBUG ("MicroDVD format detected"); + caps = SUB_CAPS; + break; + case GST_SUB_PARSE_FORMAT_SUBRIP: + GST_DEBUG ("SubRip format detected"); + caps = SUB_CAPS; + break; + case GST_SUB_PARSE_FORMAT_MPSUB: + GST_DEBUG ("MPSub format detected"); + caps = SUB_CAPS; + break; +#ifndef GST_DISABLE_XML + case GST_SUB_PARSE_FORMAT_SAMI: + GST_DEBUG ("SAMI (time-based) format detected"); + caps = SAMI_CAPS; + break; +#endif + case GST_SUB_PARSE_FORMAT_TMPLAYER: + GST_DEBUG ("TMPlayer (time based) format detected"); + caps = TMP_CAPS; + break; + /* FIXME: our MPL2 typefinding is not really good enough to warrant + * returning a high probability (however, since we registered our + * typefinder here with a rank of MARGINAL we should pretty much only + * be called if most other typefinders have already run */ + case GST_SUB_PARSE_FORMAT_MPL2: + GST_DEBUG ("MPL2 (time based) format detected"); + caps = MPL2_CAPS; + break; + case GST_SUB_PARSE_FORMAT_SUBVIEWER: + GST_DEBUG ("SubViewer format detected"); + caps = SUB_CAPS; + break; + case GST_SUB_PARSE_FORMAT_DKS: + GST_DEBUG ("DKS format detected"); + caps = DKS_CAPS; + break; + case GST_SUB_PARSE_FORMAT_QTTEXT: + GST_DEBUG ("QTtext format detected"); + caps = QTTEXT_CAPS; + break; + default: + case GST_SUB_PARSE_FORMAT_UNKNOWN: + GST_DEBUG ("no subtitle format detected"); + return; + } + + /* if we're here, it's ok */ + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, caps); +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + static const gchar *sub_exts[] = + { "srt", "sub", "mpsub", "mdvd", "smi", "txt", "dks", NULL }; + + GST_DEBUG_CATEGORY_INIT (sub_parse_debug, "subparse", 0, ".sub parser"); + + if (!gst_type_find_register (plugin, "subparse_typefind", GST_RANK_MARGINAL, + gst_subparse_type_find, (gchar **) sub_exts, SUB_CAPS, NULL, NULL)) + return FALSE; + + if (!gst_element_register (plugin, "subparse", + GST_RANK_PRIMARY, GST_TYPE_SUBPARSE) || + !gst_element_register (plugin, "ssaparse", + GST_RANK_PRIMARY, GST_TYPE_SSA_PARSE)) { + return FALSE; + } + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "subparse", + "Subtitle parsing", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.h b/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.h new file mode 100644 index 0000000..5731d91 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/gstsubparse.h @@ -0,0 +1,120 @@ +/* GStreamer + * Copyright (C) <2002> David A. Schleef + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_SUBPARSE_H__ +#define __GST_SUBPARSE_H__ + +#include +#include + +GST_DEBUG_CATEGORY_EXTERN (sub_parse_debug); +#define GST_CAT_DEFAULT sub_parse_debug + +G_BEGIN_DECLS + +#define GST_TYPE_SUBPARSE \ + (gst_sub_parse_get_type ()) +#define GST_SUBPARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SUBPARSE, GstSubParse)) +#define GST_SUBPARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SUBPARSE, GstSubParseClass)) +#define GST_IS_SUBPARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SUBPARSE)) +#define GST_IS_SUBPARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SUBPARSE)) + +typedef struct _GstSubParse GstSubParse; +typedef struct _GstSubParseClass GstSubParseClass; + +/* format enum */ +typedef enum +{ + GST_SUB_PARSE_FORMAT_UNKNOWN = 0, + GST_SUB_PARSE_FORMAT_MDVDSUB = 1, + GST_SUB_PARSE_FORMAT_SUBRIP = 2, + GST_SUB_PARSE_FORMAT_MPSUB = 3, + GST_SUB_PARSE_FORMAT_SAMI = 4, + GST_SUB_PARSE_FORMAT_TMPLAYER = 5, + GST_SUB_PARSE_FORMAT_MPL2 = 6, + GST_SUB_PARSE_FORMAT_SUBVIEWER = 7, + GST_SUB_PARSE_FORMAT_DKS = 8, + GST_SUB_PARSE_FORMAT_QTTEXT = 9 +} GstSubParseFormat; + +typedef struct { + int state; + GString *buf; + guint64 start_time; + guint64 duration; + guint64 max_duration; /* to clamp duration, 0 = no limit (used by tmplayer parser) */ + GstSegment *segment; + gpointer user_data; + gboolean have_internal_fps; /* If TRUE don't overwrite fps by property */ + gint fps_n, fps_d; /* used by frame based parsers */ +} ParserState; + +typedef gchar* (*Parser) (ParserState *state, const gchar *line); + +struct _GstSubParse { + GstElement element; + + GstPad *sinkpad,*srcpad; + + /* contains the input in the input encoding */ + GstAdapter *adapter; + /* contains the UTF-8 decoded input */ + GString *textbuf; + + GstSubParseFormat parser_type; + gboolean parser_detected; + const gchar *subtitle_codec; + + Parser parse_line; + ParserState state; + + /* seek */ + guint64 offset; + guint64 next_offset; + + /* Segment */ + GstSegment segment; + GstSeekFlags segment_flags; + gboolean need_segment; + + gboolean flushing; + gboolean valid_utf8; + gchar *detected_encoding; + gchar *encoding; + + gboolean first_buffer; + + /* used by frame based parsers */ + gint fps_n, fps_d; +}; + +struct _GstSubParseClass { + GstElementClass parent_class; +}; + +GType gst_sub_parse_get_type (void); + +G_END_DECLS + +#endif /* __GST_SUBPARSE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.c b/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.c new file mode 100644 index 0000000..b043064 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.c @@ -0,0 +1,107 @@ +/* GStreamer mpl2 format subtitle parser + * Copyright (C) 2006 Kamil Pawlowski + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "mpl2parse.h" + +#include +#include + +/* From http://lists.mplayerhq.hu/pipermail/mplayer-users/2003-February/030222.html + * + * [123][456] Sample subtitle + * [1234][5678] Line 1|Line 2 + * [12345][67890] /Italic|Normal + * [12345][67890] /Italic|/Italic + * [12345][67890] Normal|/Italic + * + * (The space between the last ']' bracket and the text appears to be optional) + */ + +static gchar * +mpl2_parse_line (ParserState * state, const gchar * line, guint line_num) +{ + GString *markup; + gint dc_start, dc_stop; + + /* parse subtitle file line */ + if (sscanf (line, "[%u][%u]", &dc_start, &dc_stop) != 2) { + GST_WARNING ("failed to extract timestamps for line '%s'", line); + return NULL; + } + + GST_LOG ("line format %u %u", dc_start, dc_stop); + state->start_time = GST_SECOND / 10 * dc_start; + state->duration = (GST_SECOND / 10 * dc_stop) - state->start_time; + + /* skip brackets with timestamps */ + line = strchr (line, ']') + 1; + line = strchr (line, ']') + 1; + + markup = g_string_new (NULL); + + while (1) { + const gchar *sep; + gchar *line_chunk_escaped; + gboolean italics; + + /* skip leading white spaces */ + while (*line == ' ' || *line == '\t') + ++line; + + /* a '/' at the beginning indicates italics */ + if (*line == '/') { + italics = TRUE; + g_string_append (markup, ""); + ++line; + } else { + italics = FALSE; + } + + if ((sep = strchr (line, '|'))) + line_chunk_escaped = g_markup_escape_text (line, sep - line); + else + line_chunk_escaped = g_markup_escape_text (line, -1); + + GST_LOG ("escaped line: %s", line_chunk_escaped); + g_string_append (markup, line_chunk_escaped); + + g_free (line_chunk_escaped); + + if (italics) + g_string_append (markup, ""); + if (sep == NULL) + break; + + /* move after the '|' and append another line */ + g_string_append (markup, "\n"); + line = sep + 1; + } + + return g_strstrip (g_string_free (markup, FALSE)); +} + +gchar * +parse_mpl2 (ParserState * state, const gchar * line) +{ + gchar *ret; + + ret = mpl2_parse_line (state, line, state->state); + ++state->state; + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.h b/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.h new file mode 100644 index 0000000..aed62c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/mpl2parse.h @@ -0,0 +1,32 @@ +/* GStreamer mpl2 format subtitle parser + * Copyright (C) 2006 Kamil Pawlowski + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 _MPL2_PARSE_H_ +#define _MPL2_PARSE_H_ + +#include "gstsubparse.h" + +G_BEGIN_DECLS + +gchar * parse_mpl2 (ParserState * state, const gchar * line); + +G_END_DECLS + +#endif /* _MPL2_PARSE_H_ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.c b/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.c new file mode 100644 index 0000000..b48daf9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.c @@ -0,0 +1,453 @@ +/* GStreamer QTtext subtitle parser + * Copyright (c) 2009 Thiago Santos > + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* References: + * http://www.apple.com/quicktime/tutorials/texttracks.html + * http://www.apple.com/quicktime/tutorials/textdescriptors.html + */ + +#include "qttextparse.h" + +#include +#include +#include + +#define MIN_TO_NSEC (60 * GST_SECOND) +#define HOUR_TO_NSEC (60 * MIN_TO_NSEC) + +#define GST_QTTEXT_CONTEXT(state) ((GstQTTextContext *) (state)->user_data) + +typedef struct _GstQTTextContext GstQTTextContext; + +struct _GstQTTextContext +{ + /* timing variables */ + gint timescale; + gboolean absolute; + guint64 start_time; + + gboolean markup_open; + gboolean need_markup; + + gchar *font; + gint font_size; + gchar *bg_color; + gchar *fg_color; + + gboolean bold; + gboolean italic; +}; + +void +qttext_context_init (ParserState * state) +{ + GstQTTextContext *context; + + state->user_data = g_new0 (GstQTTextContext, 1); + + context = GST_QTTEXT_CONTEXT (state); + + /* we use 1000 as a default */ + context->timescale = 1000; + context->absolute = TRUE; + + context->markup_open = FALSE; + context->need_markup = FALSE; + + context->font_size = 12; +} + +void +qttext_context_deinit (ParserState * state) +{ + if (state->user_data != NULL) { + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + g_free (context->font); + g_free (context->bg_color); + g_free (context->fg_color); + + g_free (state->user_data); + state->user_data = NULL; + } +} + +/* + * Reads the string right after the ':' + */ +static gchar * +read_str (const gchar * line, const gchar * end) +{ + gint index = 0; + + while (line[index] != ':' && line[index] != '}') { + index++; + } + if (line[index] != ':') + return NULL; + index++; + while (line[index] == ' ') + index++; + + return g_strndup (line + index, (end - (line + index))); +} + +/* search for the ':' and parse the number right after it */ +static gint +read_int (const gchar * line) +{ + gint index = 0; + while (line[index] != ':' && line[index] != '}') { + index++; + } + if (line[index] != ':') + return 0; + index++; + return atoi (line + index); +} + +/* skip the ':' and then match the following string + * with 'match', but only if it before 'upto' */ +static gboolean +string_match (const gchar * line, const gchar * match, const gchar * upto) +{ + gchar *result = strstr (line, match); + return (result < upto); +} + +/* + * Reads the color values and stores them in r, g and b. + */ +static gboolean +read_color (const gchar * line, gint * r, gint * g, gint * b) +{ + gint index = 0; + while (line[index] != ':' && line[index] != '}') { + index++; + } + if (line[index] != ':') + return FALSE; + index++; + + *r = atoi (line + index); + + while (line[index] != '}' && line[index] != ',') { + index++; + } + if (line[index] != ',') + return FALSE; + index++; + + *g = atoi (line + index); + + while (line[index] != '}' && line[index] != ',') { + index++; + } + if (line[index] != ',') + return FALSE; + index++; + + *b = atoi (line + index); + + return TRUE; +} + +static gchar * +make_color (gint r, gint g, gint b) +{ + /* qttext goes up to 65535, while pango goes to 255 */ + r /= 256; + g /= 256; + b /= 256; + return g_strdup_printf ("#%02X%02X%02X", r, g, b); +} + +static gboolean +qttext_parse_tag (ParserState * state, const gchar * line, gint * index) +{ + gchar *next; + gint next_index; + gint aux; + gchar *str; + gint r, g, b; + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + + g_assert (line[*index] == '{'); + + next = strchr (line + *index, '}'); + if (next == NULL) { + goto error_out; + } else { + next_index = 1 + (next - line); + } + g_assert (line[next_index - 1] == '}'); + + *index = *index + 1; /* skip the { */ + + /* now identify our tag */ + /* FIXME: those should be case unsensitive */ + /* TODO: there are other tags that could be added here */ + if (strncmp (line + *index, "QTtext", 6) == 0) { + /* NOP */ + + } else if (strncmp (line + *index, "font", 4) == 0) { + str = read_str (line + *index + 4, line + next_index - 1); + if (str) { + g_free (context->font); + context->font = str; + context->need_markup = TRUE; + GST_DEBUG ("Setting qttext font to %s", str); + } else { + GST_WARNING ("Failed to parse qttext font at line: %s", line); + } + + } else if (strncmp (line + *index, "size", 4) == 0) { + aux = read_int (line + *index + 4); + if (aux == 0) { + GST_WARNING ("Invalid size at line %s, using 12", line); + context->font_size = 12; + } else { + GST_DEBUG ("Setting qttext font-size to: %d", aux); + context->font_size = aux; + } + context->need_markup = TRUE; + + } else if (strncmp (line + *index, "textColor", 9) == 0) { + if (read_color (line + *index + 9, &r, &g, &b)) { + context->fg_color = make_color (r, g, b); + GST_DEBUG ("Setting qttext fg color to %s", context->fg_color); + } else { + GST_WARNING ("Failed to read textColor at line %s", line); + } + context->need_markup = TRUE; + + } else if (strncmp (line + *index, "backColor", 9) == 0) { + if (read_color (line + *index + 9, &r, &g, &b)) { + context->bg_color = make_color (r, g, b); + GST_DEBUG ("Setting qttext bg color to %s", context->bg_color); + } else { + GST_WARNING ("Failed to read backColor at line %s, disabling", line); + g_free (context->bg_color); + context->bg_color = NULL; + } + context->need_markup = TRUE; + + } else if (strncmp (line + *index, "plain", 5) == 0) { + context->bold = FALSE; + context->italic = FALSE; + context->need_markup = TRUE; + GST_DEBUG ("Setting qttext style to plain"); + + } else if (strncmp (line + *index, "bold", 4) == 0) { + context->bold = TRUE; + context->italic = FALSE; + context->need_markup = TRUE; + GST_DEBUG ("Setting qttext style to bold"); + + } else if (strncmp (line + *index, "italic", 6) == 0) { + context->bold = FALSE; + context->italic = TRUE; + context->need_markup = TRUE; + GST_DEBUG ("Setting qttext style to italic"); + + } else if (strncmp (line + *index, "timescale", 9) == 0) { + aux = read_int (line + *index + 9); + if (aux == 0) { + GST_WARNING ("Couldn't interpret timescale at line %s, using 1000", line); + context->timescale = 1000; + } else { + GST_DEBUG ("Setting qttext timescale to: %d", aux); + context->timescale = aux; + } + + } else if (strncmp (line + *index, "timestamps", 10) == 0) { + if (string_match (line + *index + 10, "relative", line + next_index)) { + GST_DEBUG ("Setting qttext timestamps to relative"); + context->absolute = FALSE; + } else { + /* call it absolute otherwise */ + GST_DEBUG ("Setting qttext timestamps to absolute"); + context->absolute = TRUE; + } + + } else { + GST_WARNING ("Unused qttext tag starting at: %s", line + *index); + } + + *index = next_index; + return TRUE; + +error_out: + { + GST_WARNING ("Failed to parse qttext tag at line %s", line); + return FALSE; + } +} + +static guint64 +qttext_parse_timestamp (ParserState * state, const gchar * line, gint index) +{ + int ret; + gint hour, min, sec, dec; + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + + ret = sscanf (line + index, "[%d:%d:%d.%d]", &hour, &min, &sec, &dec); + if (ret != 3 && ret != 4) { + /* bad timestamp */ + GST_WARNING ("Bad qttext timestamp found: %s", line); + return 0; + } + + if (ret == 3) { + /* be forgiving for missing decimal part */ + dec = 0; + } + + /* parse the decimal part according to the timescale */ + g_assert (context->timescale != 0); + dec = (GST_SECOND * dec) / context->timescale; + + /* return the result */ + return hour * HOUR_TO_NSEC + min * MIN_TO_NSEC + sec * GST_SECOND + dec; +} + +static void +qttext_open_markup (ParserState * state) +{ + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + + g_string_append (state->buf, "font) + g_string_append_printf (state->buf, " font='%s %d'", context->font, + context->font_size); + else + g_string_append_printf (state->buf, " font='%d'", context->font_size); + + if (context->bg_color) + g_string_append_printf (state->buf, " bgcolor='%s'", context->bg_color); + if (context->fg_color) + g_string_append_printf (state->buf, " color='%s'", context->fg_color); + + if (context->bold) + g_string_append (state->buf, " weight='bold'"); + if (context->italic) + g_string_append (state->buf, " style='italic'"); + + g_string_append (state->buf, ">"); +} + +static void +qttext_prepare_text (ParserState * state) +{ + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + if (state->buf == NULL) { + state->buf = g_string_sized_new (256); /* this should be enough */ + } else { + g_string_append (state->buf, "\n"); + } + + /* if needed, add pango markup */ + if (context->need_markup) { + if (context->markup_open) { + g_string_append (state->buf, ""); + } + qttext_open_markup (state); + context->markup_open = TRUE; + } +} + +static void +qttext_parse_text (ParserState * state, const gchar * line, gint index) +{ + qttext_prepare_text (state); + g_string_append (state->buf, line + index); +} + +static gchar * +qttext_get_text (ParserState * state) +{ + gchar *ret; + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + if (state->buf == NULL) + return NULL; + + if (context->markup_open) { + g_string_append (state->buf, ""); + } + ret = g_string_free (state->buf, FALSE); + state->buf = NULL; + context->markup_open = FALSE; + return ret; +} + +gchar * +parse_qttext (ParserState * state, const gchar * line) +{ + gint i; + guint64 ts; + gchar *ret = NULL; + GstQTTextContext *context = GST_QTTEXT_CONTEXT (state); + + i = 0; + while (line[i] != '\0') { + /* find first interesting character from 'i' onwards */ + + if (line[i] == '{') { + /* this is a tag, parse it */ + if (!qttext_parse_tag (state, line, &i)) { + break; + } + } else if (line[i] == '[') { + /* this is a time, convert it to a timestamp */ + ts = qttext_parse_timestamp (state, line, i); + + /* check if we have pending text to send, in case we prepare it */ + if (state->buf) { + ret = qttext_get_text (state); + if (context->absolute) + state->duration = ts - context->start_time; + else + state->duration = ts; + state->start_time = context->start_time; + } + state->buf = NULL; + + if (ts == 0) { + /* this is an error */ + } else { + if (context->absolute) + context->start_time = ts; + else + context->start_time += ts; + } + + /* we assume there is nothing else on this line */ + break; + + } else if (line[i] == ' ' || line[i] == '\t') { + i++; /* NOP */ + } else { + /* this is the actual text, output the rest of the line as it */ + qttext_parse_text (state, line, i); + break; + } + } + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.h b/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.h new file mode 100644 index 0000000..6d4f393 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/qttextparse.h @@ -0,0 +1,36 @@ +/* GStreamer QTtext subtitle parser + * Copyright (c) 2009 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 _QTTEXT_PARSE_H_ +#define _QTTEXT_PARSE_H_ + +#include "gstsubparse.h" + +G_BEGIN_DECLS + +gchar * parse_qttext (ParserState * state, const gchar * line); + +void qttext_context_init (ParserState * state); + +void qttext_context_deinit (ParserState * state); + +G_END_DECLS + +#endif /* _QTTEXT_PARSE_H_ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.c b/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.c new file mode 100644 index 0000000..135748a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.c @@ -0,0 +1,474 @@ +/* GStreamer SAMI subtitle parser + * Copyright (c) 2006 Young-Ho Cha + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "samiparse.h" + +#include +#include + +#define ITALIC_TAG 'i' +#define SPAN_TAG 's' +#define RUBY_TAG 'r' +#define RT_TAG 't' +#define CLEAR_TAG '0' + +typedef struct _GstSamiContext GstSamiContext; + +struct _GstSamiContext +{ + GString *buf; /* buffer to collect content */ + GString *rubybuf; /* buffer to collect ruby content */ + GString *resultbuf; /* when opening the next 'sync' tag, move + * from 'buf' to avoid to append following + * content */ + GString *state; /* in many sami files there are tags that + * are not closed, so for each open tag the + * parser will append a tag flag here so + * that tags can be closed properly on + * 'sync' tags. See _context_push_state() + * and _context_pop_state(). */ + htmlParserCtxtPtr htmlctxt; /* html parser context */ + gboolean has_result; /* set when ready to push out result */ + gboolean in_sync; /* flag to avoid appending anything except the + * content of the sync elements to buf */ + guint64 time1; /* previous start attribute in sync tag */ + guint64 time2; /* current start attribute in sync tag */ +}; + +static gchar * +has_tag (GString * str, const gchar tag) +{ + return strrchr (str->str, tag); +} + +static void +sami_context_push_state (GstSamiContext * sctx, char state) +{ + GST_LOG ("state %c", state); + g_string_append_c (sctx->state, state); +} + +static void +sami_context_pop_state (GstSamiContext * sctx, char state) +{ + GString *str = g_string_new (""); + GString *context_state = sctx->state; + int i; + + GST_LOG ("state %c", state); + for (i = context_state->len - 1; i >= 0; i--) { + switch (context_state->str[i]) { + case ITALIC_TAG: /* */ + { + g_string_append (str, ""); + break; + } + case SPAN_TAG: /* */ + { + g_string_append (str, ""); + break; + } + case RUBY_TAG: /* -- ruby */ + { + break; + } + case RT_TAG: /* ruby */ + { + /* FIXME: support for furigana/ruby once implemented in pango */ + g_string_append (sctx->rubybuf, ""); + if (has_tag (context_state, ITALIC_TAG)) { + g_string_append (sctx->rubybuf, ""); + } + + break; + } + default: + break; + } + if (context_state->str[i] == state) { + g_string_append (sctx->buf, str->str); + g_string_free (str, TRUE); + g_string_truncate (context_state, i); + return; + } + } + if (state == CLEAR_TAG) { + g_string_append (sctx->buf, str->str); + g_string_truncate (context_state, 0); + } + g_string_free (str, TRUE); +} + +static void +handle_start_sync (GstSamiContext * sctx, const xmlChar ** atts) +{ + int i; + + sami_context_pop_state (sctx, CLEAR_TAG); + if (atts != NULL) { + for (i = 0; (atts[i] != NULL); i += 2) { + const xmlChar *key, *value; + + key = atts[i]; + value = atts[i + 1]; + + if (!value) + continue; + if (!xmlStrncmp ((const xmlChar *) "start", key, 5)) { + /* Only set a new start time if we don't have text pending */ + if (sctx->resultbuf->len == 0) + sctx->time1 = sctx->time2; + + sctx->time2 = atoi ((const char *) value) * GST_MSECOND; + g_string_append (sctx->resultbuf, sctx->buf->str); + sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE; + g_string_truncate (sctx->buf, 0); + } + } + } +} + +static void +handle_start_font (GstSamiContext * sctx, const xmlChar ** atts) +{ + int i; + + sami_context_pop_state (sctx, SPAN_TAG); + if (atts != NULL) { + g_string_append (sctx->buf, "= 0 && + ((xmlChar *) r == (value + 6) && len == 6)) { + sharp = "#"; + } + } + /* some colours can be found in many sami files, but X RGB database + * doesn't contain a colour by this name, so map explicitly */ + if (!xmlStrncasecmp (value, (const xmlChar *) "aqua", len)) { + value = (const xmlChar *) "#00ffff"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "crimson", len)) { + value = (const xmlChar *) "#dc143c"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "fuchsia", len)) { + value = (const xmlChar *) "#ff00ff"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "indigo", len)) { + value = (const xmlChar *) "#4b0082"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "lime", len)) { + value = (const xmlChar *) "#00ff00"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "olive", len)) { + value = (const xmlChar *) "#808000"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "silver", len)) { + value = (const xmlChar *) "#c0c0c0"; + } else if (!xmlStrncasecmp (value, (const xmlChar *) "teal", len)) { + value = (const xmlChar *) "#008080"; + } + g_string_append_printf (sctx->buf, " foreground=\"%s%s\"", sharp, + value); + } else if (!xmlStrncasecmp ((const xmlChar *) "face", key, 4)) { + g_string_append_printf (sctx->buf, " font_family=\"%s\"", value); + } + } + g_string_append_c (sctx->buf, '>'); + sami_context_push_state (sctx, SPAN_TAG); + } +} + +static void +start_sami_element (void *ctx, const xmlChar * name, const xmlChar ** atts) +{ + GstSamiContext *sctx = (GstSamiContext *) ctx; + + GST_LOG ("name:%s", name); + + if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) { + handle_start_sync (sctx, atts); + sctx->in_sync = TRUE; + } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) { + handle_start_font (sctx, atts); + } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) { + sami_context_push_state (sctx, RUBY_TAG); + } else if (!xmlStrncmp ((const xmlChar *) "br", name, 2)) { + g_string_append_c (sctx->buf, '\n'); + /* FIXME: support for furigana/ruby once implemented in pango */ + } else if (!xmlStrncmp ((const xmlChar *) "rt", name, 2)) { + if (has_tag (sctx->state, ITALIC_TAG)) { + g_string_append (sctx->rubybuf, ""); + } + g_string_append (sctx->rubybuf, ""); + sami_context_push_state (sctx, RT_TAG); + } else if (!xmlStrncmp ((const xmlChar *) "p", name, 1)) { + } else if (!xmlStrncmp ((const xmlChar *) "i", name, 1)) { + g_string_append (sctx->buf, ""); + sami_context_push_state (sctx, ITALIC_TAG); + } +} + +static void +end_sami_element (void *ctx, const xmlChar * name) +{ + GstSamiContext *sctx = (GstSamiContext *) ctx; + + GST_LOG ("name:%s", name); + + if (!xmlStrncmp ((const xmlChar *) "sync", name, 4)) { + sctx->in_sync = FALSE; + } else if ((!xmlStrncmp ((const xmlChar *) "body", name, 4)) || + (!xmlStrncmp ((const xmlChar *) "sami", name, 4))) { + /* We will usually have one buffer left when the body is closed + * as we need the next sync to actually send it */ + if (sctx->buf->len != 0) { + /* Only set a new start time if we don't have text pending */ + if (sctx->resultbuf->len == 0) + sctx->time1 = sctx->time2; + + sctx->time2 = GST_CLOCK_TIME_NONE; + g_string_append (sctx->resultbuf, sctx->buf->str); + sctx->has_result = (sctx->resultbuf->len != 0) ? TRUE : FALSE; + g_string_truncate (sctx->buf, 0); + } + } else if (!xmlStrncmp ((const xmlChar *) "font", name, 4)) { + sami_context_pop_state (sctx, SPAN_TAG); + } else if (!xmlStrncmp ((const xmlChar *) "ruby", name, 4)) { + sami_context_pop_state (sctx, RUBY_TAG); + } else if (!xmlStrncmp ((const xmlChar *) "i", name, 1)) { + sami_context_pop_state (sctx, ITALIC_TAG); + } +} + +static void +characters_sami (void *ctx, const xmlChar * ch, int len) +{ + GstSamiContext *sctx = (GstSamiContext *) ctx; + gchar *escaped; + gchar *tmp; + gint i; + + /* Skip everything except content of the sync elements */ + if (!sctx->in_sync) + return; + + escaped = g_markup_escape_text ((const gchar *) ch, len); + g_strstrip (escaped); + + /* Remove double spaces forom the string as those are + * usually added by newlines and indention */ + tmp = escaped; + for (i = 0; i <= strlen (escaped); i++) { + escaped[i] = *tmp; + if (*tmp != ' ') { + tmp++; + continue; + } + while (*tmp == ' ') + tmp++; + } + + if (has_tag (sctx->state, RT_TAG)) { + g_string_append_c (sctx->rubybuf, ' '); + g_string_append (sctx->rubybuf, escaped); + g_string_append_c (sctx->rubybuf, ' '); + } else { + g_string_append (sctx->buf, escaped); + } + g_free (escaped); +} + +static xmlSAXHandler samiSAXHandlerStruct = { + NULL, /* internalSubset */ + NULL, /* isStandalone */ + NULL, /* hasInternalSubset */ + NULL, /* hasExternalSubset */ + NULL, /* resolveEntity */ + NULL, /* getEntity */ + NULL, /* entityDecl */ + NULL, /* notationDecl */ + NULL, /* attributeDecl */ + NULL, /* elementDecl */ + NULL, /* unparsedEntityDecl */ + NULL, /* setDocumentLocator */ + NULL, /* startDocument */ + NULL, /* endDocument */ + start_sami_element, /* startElement */ + end_sami_element, /* endElement */ + NULL, /* reference */ + characters_sami, /* characters */ + NULL, /* ignorableWhitespace */ + NULL, /* processingInstruction */ + NULL, /* comment */ + NULL, /* xmlParserWarning */ + NULL, /* xmlParserError */ + NULL, /* xmlParserError */ + NULL, /* getParameterEntity */ + NULL, /* cdataBlock */ + NULL, /* externalSubset */ + 1, /* initialized */ + NULL, /* private */ + NULL, /* startElementNsSAX2Func */ + NULL, /* endElementNsSAX2Func */ + NULL /* xmlStructuredErrorFunc */ +}; + +static xmlSAXHandlerPtr samiSAXHandler = &samiSAXHandlerStruct; + +void +sami_context_init (ParserState * state) +{ + GstSamiContext *context; + + g_assert (state->user_data == NULL); + state->user_data = (gpointer) g_new0 (GstSamiContext, 1); + context = (GstSamiContext *) state->user_data; + + context->htmlctxt = htmlCreatePushParserCtxt (samiSAXHandler, context, + "", 0, NULL, XML_CHAR_ENCODING_UTF8); + context->buf = g_string_new (""); + context->rubybuf = g_string_new (""); + context->resultbuf = g_string_new (""); + context->state = g_string_new (""); +} + +void +sami_context_deinit (ParserState * state) +{ + GstSamiContext *context = (GstSamiContext *) state->user_data; + + if (context) { + htmlParserCtxtPtr htmlctxt = context->htmlctxt; + + /* destroy sax context */ + htmlDocPtr doc; + + htmlParseChunk (htmlctxt, "", 0, 1); + doc = htmlctxt->myDoc; + htmlFreeParserCtxt (htmlctxt); + context->htmlctxt = NULL; + if (doc) + xmlFreeDoc (doc); + g_string_free (context->buf, TRUE); + g_string_free (context->rubybuf, TRUE); + g_string_free (context->resultbuf, TRUE); + g_string_free (context->state, TRUE); + g_free (context); + state->user_data = NULL; + } +} + +void +sami_context_reset (ParserState * state) +{ + GstSamiContext *context = (GstSamiContext *) state->user_data; + + if (context) { + g_string_truncate (context->buf, 0); + g_string_truncate (context->rubybuf, 0); + g_string_truncate (context->resultbuf, 0); + g_string_truncate (context->state, 0); + context->has_result = FALSE; + context->in_sync = FALSE; + context->time1 = 0; + context->time2 = 0; + } +} + +static gchar * +fix_invalid_entities (const gchar * line) +{ + const gchar *cp, *pp; /* current pointer, previous pointer */ + gssize size; + GString *ret = g_string_new (NULL); + + pp = line; + cp = strchr (line, '&'); + while (cp) { + size = cp - pp; + ret = g_string_append_len (ret, pp, size); + cp++; + if (g_ascii_strncasecmp (cp, "nbsp;", 5) + && (!g_ascii_strncasecmp (cp, "nbsp", 4))) { + /* translate " " to " " */ + ret = g_string_append_len (ret, " ", 6); + cp += 4; + } else if (g_ascii_strncasecmp (cp, "quot;", 5) + && g_ascii_strncasecmp (cp, "amp;", 4) + && g_ascii_strncasecmp (cp, "apos;", 5) + && g_ascii_strncasecmp (cp, "lt;", 3) + && g_ascii_strncasecmp (cp, "gt;", 3) + && g_ascii_strncasecmp (cp, "nbsp;", 5) + && cp[0] != '#') { + /* translate "&" to "&" */ + ret = g_string_append_len (ret, "&", 5); + } else { + /* do not translate */ + ret = g_string_append_c (ret, '&'); + } + + pp = cp; + cp = strchr (pp, '&'); + } + ret = g_string_append (ret, pp); + return g_string_free (ret, FALSE); +} + +gchar * +parse_sami (ParserState * state, const gchar * line) +{ + gchar *fixed_line; + GstSamiContext *context = (GstSamiContext *) state->user_data; + + fixed_line = fix_invalid_entities (line); + htmlParseChunk (context->htmlctxt, fixed_line, strlen (fixed_line), 0); + g_free (fixed_line); + + if (context->has_result) { + gchar *r; + + if (context->rubybuf->len) { + context->rubybuf = g_string_append_c (context->rubybuf, '\n'); + g_string_prepend (context->resultbuf, context->rubybuf->str); + context->rubybuf = g_string_truncate (context->rubybuf, 0); + } + + r = g_string_free (context->resultbuf, FALSE); + context->resultbuf = g_string_new (""); + state->start_time = context->time1; + state->duration = context->time2 - context->time1; + context->has_result = FALSE; + return r; + } + return NULL; +} diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.h b/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.h new file mode 100644 index 0000000..a45de01 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/samiparse.h @@ -0,0 +1,38 @@ +/* GStreamer SAMI subtitle parser + * Copyright (c) 2006 Young-Ho Cha + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 _SAMI_PARSE_H_ +#define _SAMI_PARSE_H_ + +#include "gstsubparse.h" + +G_BEGIN_DECLS + +gchar * parse_sami (ParserState * state, const gchar * line); + +void sami_context_init (ParserState * state); + +void sami_context_deinit (ParserState * state); + +void sami_context_reset (ParserState * state); + +G_END_DECLS + +#endif /* _SAMI_PARSE_H_ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.c b/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.c new file mode 100644 index 0000000..3937de6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.c @@ -0,0 +1,154 @@ +/* GStreamer tmplayer format subtitle parser + * Copyright (C) 2006-2008 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "tmplayerparse.h" + +#include +#include + +/* From http://forum.doom9.org/archive/index.php/t-81059.html: + * + * TMPlayer format, which comes in five varieties: + * + * time-base 00:00:00: + * 00:00:50:This is the Earth at a time|when the dinosaurs roamed... + * 00:00:53: + * 00:00:54:a lush and fertile planet. + * 00:00:56: + * + * time-base 0:00:00: + * 0:00:50:This is the Earth at a time|when the dinosaurs roamed... + * 0:00:53: + * 0:00:54:a lush and fertile planet. + * 0:00:56: + * + * time-base 00:00:00= + * 00:00:50=This is the Earth at a time|when the dinosaurs roamed... + * 00:00:53= + * 00:00:54=a lush and fertile planet. + * 00:00:56= + * + * time-base 0:00:00= + * 0:00:50=This is the Earth at a time|when the dinosaurs roamed... + * 0:00:53= + * 0:00:54=a lush and fertile planet. + * 0:00:56= + * + * and multiline time-base 00:00:00,1= + * 00:00:50,1=This is the Earth at a time + * 00:00:50,2=when the dinosaurs roamed... + * 00:00:53,1= + * 00:00:54,1=a lush and fertile planet. + * 00:00:56,1= + * + * -------------------------------------------------------------------------- + * + * And another variety (which is 'time-base 0:00:00:' but without empty lines): + * + * 00:00:01:This is the Earth at a time|when the dinosaurs roamed... + * 00:00:03:a lush and fertile planet. + * 00:00:06:More text here + * 00:00:12:Yet another line + * + */ + +static gchar * +tmplayer_process_buffer (ParserState * state) +{ + gchar *ret; + + ret = g_strndup (state->buf->str, state->buf->len); + g_strdelimit (ret, "|", '\n'); + g_string_truncate (state->buf, 0); + return ret; +} + +static gchar * +tmplayer_parse_line (ParserState * state, const gchar * line, guint line_num) +{ + GstClockTime ts = GST_CLOCK_TIME_NONE; + const gchar *text_start = NULL; + gchar *ret = NULL; + gchar divc = '\0'; + guint h, m, s, l = 1; + + if (sscanf (line, "%u:%02u:%02u,%u%c", &h, &m, &s, &l, &divc) == 5 && + (divc == '=')) { + GST_LOG ("multiline format %u %u %u %u", h, m, s, l); + ts = GST_SECOND * ((((h * 60) + m) * 60) + s); + text_start = strchr (line, '='); + } else if (sscanf (line, "%u:%02u:%02u%c", &h, &m, &s, &divc) == 4 && + (divc == '=' || divc == ':')) { + GST_LOG ("single line format %u %u %u %u %c", h, m, s, l, divc); + ts = GST_SECOND * ((((h * 60) + m) * 60) + s); + text_start = strchr (line + 6, divc); + } else if (line[0] == '\0' && state->buf->len > 0 && + GST_CLOCK_TIME_IS_VALID (state->start_time)) { + /* if we get an empty line (could be the end of the file, but doesn't have + * to be), just push whatever is still in the buffer without a duration */ + GST_LOG ("empty line, and there's still text in the buffer"); + ret = tmplayer_process_buffer (state); + state->duration = GST_CLOCK_TIME_NONE; + return ret; + } else { + GST_WARNING ("failed to parse line: '%s'", line); + return NULL; + } + + /* if this is a line without text, or the first line in a multiline file, + * process and return the data in the buffer, which is the previous line(s) */ + if (text_start == NULL || text_start[1] == '\0' || + (l == 1 && state->buf->len > 0)) { + + if (GST_CLOCK_TIME_IS_VALID (state->start_time) && + state->start_time < ts && line_num > 0) { + ret = tmplayer_process_buffer (state); + state->duration = ts - state->start_time; + /* ..and append current line's text (if there is any) for the next round. + * We don't have to store ts as pending_start_time, since we deduce the + * durations from the start times anyway, so as long as the parser just + * forwards state->start_time by duration after it pushes the line we + * are about to return it will all be good. */ + g_string_append (state->buf, text_start + 1); + } else if (line_num > 0) { + GST_WARNING ("end of subtitle unit but no valid start time?!"); + } + } else { + if (l > 1) + g_string_append_c (state->buf, '\n'); + g_string_append (state->buf, text_start + 1); + state->start_time = ts; + } + + GST_LOG ("returning: '%s'", GST_STR_NULL (ret)); + return ret; +} + +gchar * +parse_tmplayer (ParserState * state, const gchar * line) +{ + gchar *ret; + + /* GST_LOG ("Parsing: %s", line); */ + + ret = tmplayer_parse_line (state, line, state->state); + ++state->state; + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.h b/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.h new file mode 100644 index 0000000..a0001af --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/subparse/tmplayerparse.h @@ -0,0 +1,32 @@ +/* GStreamer tmplayer format subtitle parser + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 _TMPLAYER_PARSE_H_ +#define _TMPLAYER_PARSE_H_ + +#include "gstsubparse.h" + +G_BEGIN_DECLS + +gchar * parse_tmplayer (ParserState * state, const gchar * line); + +G_END_DECLS + +#endif /* _TMPLAYER_PARSE_H_ */ + diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/.gitignore b/gst-plugins-base-subtitles0.10/gst/tcp/.gitignore new file mode 100644 index 0000000..45ededd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/.gitignore @@ -0,0 +1,5 @@ +gsttcp-enumtypes.c +gsttcp-enumtypes.h +gsttcp-marshal.c +gsttcp-marshal.h +fdsetstress diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/Makefile.am b/gst-plugins-base-subtitles0.10/gst/tcp/Makefile.am new file mode 100644 index 0000000..a970a2b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/Makefile.am @@ -0,0 +1,56 @@ +plugin_LTLIBRARIES = libgsttcp.la + +# variables used for enum/marshal generation +glib_enum_headers = gsttcp.h +glib_enum_define = GST_TCP +glib_gen_prefix = gst_tcp +glib_gen_basename = gsttcp + +include $(top_srcdir)/common/gst-glib-gen.mak + +built_sources = gsttcp-enumtypes.c gsttcp-marshal.c +built_headers = gsttcp-enumtypes.h gsttcp-marshal.h + +BUILT_SOURCES = $(built_sources) $(built_headers) + +libgsttcp_la_SOURCES = \ + gsttcpplugin.c \ + gsttcp.c \ + gstmultifdsink.c \ + gsttcpclientsrc.c gsttcpclientsink.c \ + gsttcpserversrc.c gsttcpserversink.c + +nodist_libgsttcp_la_SOURCES = \ + $(built_sources) + +# remove ENABLE_NEW when dataprotocol is stable +libgsttcp_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_GDP_CFLAGS) $(GST_CFLAGS) -DGST_ENABLE_NEW +libgsttcp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgsttcp_la_LIBADD = $(GST_BASE_LIBS) $(GST_GDP_LIBS) $(GST_LIBS) +libgsttcp_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gsttcpplugin.h \ + gsttcp.h \ + gstmultifdsink.h \ + gsttcpclientsrc.h gsttcpclientsink.h \ + gsttcpserversrc.h gsttcpserversink.h + +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = gsttcp-marshal.list + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgsttcp -:SHARED libgsttcp \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgsttcp_la_SOURCES) \ + $(nodist_libgsttcp_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsttcp_la_CFLAGS) \ + -:LDFLAGS $(libgsttcp_la_LDFLAGS) \ + $(libgsttcp_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/README b/gst-plugins-base-subtitles0.10/gst/tcp/README new file mode 100644 index 0000000..47e4894 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/README @@ -0,0 +1,53 @@ +This part of the documentation is for the new tcp elements: +- tcpclientsrc +- tcpclientsink +- tcpserversrc +- tcpserversink + +TESTS +----- +Use these tests to test functionality of the various tcp plugins + +* server: nc -l -p 3000 + client: nc localhost 3000 + everything you type in the server is shown on the client + everything you type in the client is shown on the server + +* server: nc -l -p 3000 + client: gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2 + everything you type in the server is shown on the client + +* server: nc -l -p 3000 + client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000 + everything you type in the client is shown on the server + +* server: gst-launch tcpserversrc protocol=none port=3000 ! fdsink fd=2 + client: gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000 + +* server: gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000 + client: gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2 + -> Received first buffer without caps set + +TODO +---- +- implement DNS resolution + +multifdsink +----------- +- operation: + - client fd gets added when "add" signal gets emitted on multifdsink + - signal handler creates a GstTCPClient structure, adds it to ->clients, + and adds the fd to ->fd_hash, then emits client-added + - client + + - when a buffer comes in: + - the _render vmethod puts the buffer on the global queue + - and increases bytes_to_serve + - (currently it sets streamheaders, but since this is treated globally + this is wrong - clients can be at different positions in the stream) + + - when a client issues a write (ie requests data): + - when using GDP, if no caps sent yet, send caps first, then set caps_sent + - if streamheader buffers, and we haven't sent yet to this client, + send current streamheader buffers, then set streamheader_sent + - send out buffers diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.c b/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.c new file mode 100644 index 0000000..98c62d7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.c @@ -0,0 +1,3016 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * Copyright (C) 2006 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-multifdsink + * @see_also: tcpserversink + * + * This plugin writes incoming data to a set of file descriptors. The + * file descriptors can be added to multifdsink by emitting the #GstMultiFdSink::add signal. + * For each descriptor added, the #GstMultiFdSink::client-added signal will be called. + * + * As of version 0.10.8, a client can also be added with the #GstMultiFdSink::add-full signal + * that allows for more control over what and how much data a client + * initially receives. + * + * Clients can be removed from multifdsink by emitting the #GstMultiFdSink::remove signal. For + * each descriptor removed, the #GstMultiFdSink::client-removed signal will be called. The + * #GstMultiFdSink::client-removed signal can also be fired when multifdsink decides that a + * client is not active anymore or, depending on the value of the + * #GstMultiFdSink:recover-policy property, if the client is reading too slowly. + * In all cases, multifdsink will never close a file descriptor itself. + * The user of multifdsink is responsible for closing all file descriptors. + * This can for example be done in response to the #GstMultiFdSink::client-fd-removed signal. + * Note that multifdsink still has a reference to the file descriptor when the + * #GstMultiFdSink::client-removed signal is emitted, so that "get-stats" can be performed on + * the descriptor; it is therefore not safe to close the file descriptor in + * the #GstMultiFdSink::client-removed signal handler, and you should use the + * #GstMultiFdSink::client-fd-removed signal to safely close the fd. + * + * Multifdsink internally keeps a queue of the incoming buffers and uses a + * separate thread to send the buffers to the clients. This ensures that no + * client write can block the pipeline and that clients can read with different + * speeds. + * + * When adding a client to multifdsink, the #GstMultiFdSink:sync-method property will define + * which buffer in the queued buffers will be sent first to the client. Clients + * can be sent the most recent buffer (which might not be decodable by the + * client if it is not a keyframe), the next keyframe received in + * multifdsink (which can take some time depending on the keyframe rate), or the + * last received keyframe (which will cause a simple burst-on-connect). + * Multifdsink will always keep at least one keyframe in its internal buffers + * when the sync-mode is set to latest-keyframe. + * + * As of version 0.10.8, there are additional values for the #GstMultiFdSink:sync-method + * property to allow finer control over burst-on-connect behaviour. By selecting + * the 'burst' method a minimum burst size can be chosen, 'burst-keyframe' + * additionally requires that the burst begin with a keyframe, and + * 'burst-with-keyframe' attempts to burst beginning with a keyframe, but will + * prefer a minimum burst size even if it requires not starting with a keyframe. + * + * Multifdsink can be instructed to keep at least a minimum amount of data + * expressed in time or byte units in its internal queues with the the + * #GstMultiFdSink:time-min and #GstMultiFdSink:bytes-min properties respectively. + * These properties are useful if the application adds clients with the + * #GstMultiFdSink::add-full signal to make sure that a burst connect can + * actually be honored. + * + * When streaming data, clients are allowed to read at a different rate than + * the rate at which multifdsink receives data. If the client is reading too + * fast, no data will be send to the client until multifdsink receives more + * data. If the client, however, reads too slowly, data for that client will be + * queued up in multifdsink. Two properties control the amount of data + * (buffers) that is queued in multifdsink: #GstMultiFdSink:buffers-max and + * #GstMultiFdSink:buffers-soft-max. A client that falls behind by + * #GstMultiFdSink:buffers-max is removed from multifdsink forcibly. + * + * A client with a lag of at least #GstMultiFdSink:buffers-soft-max enters the recovery + * procedure which is controlled with the #GstMultiFdSink:recover-policy property. + * A recover policy of NONE will do nothing, RESYNC_LATEST will send the most recently + * received buffer as the next buffer for the client, RESYNC_SOFT_LIMIT + * positions the client to the soft limit in the buffer queue and + * RESYNC_KEYFRAME positions the client at the most recent keyframe in the + * buffer queue. + * + * multifdsink will by default synchronize on the clock before serving the + * buffers to the clients. This behaviour can be disabled by setting the sync + * property to FALSE. Multifdsink will by default not do QoS and will never + * drop late buffers. + * + * Last reviewed on 2006-09-12 (0.10.10) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#include + +#ifdef HAVE_UNISTD_H +#include +#endif + +#include +#include +#include +#include +#include + +#ifdef HAVE_FIONREAD_IN_SYS_FILIO +#include +#endif + +#include "gstmultifdsink.h" +#include "gsttcp-marshal.h" + +#define NOT_IMPLEMENTED 0 + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +GST_DEBUG_CATEGORY_STATIC (multifdsink_debug); +#define GST_CAT_DEFAULT (multifdsink_debug) + +/* MultiFdSink signals and args */ +enum +{ + /* methods */ + SIGNAL_ADD, + SIGNAL_ADD_BURST, + SIGNAL_REMOVE, + SIGNAL_REMOVE_FLUSH, + SIGNAL_CLEAR, + SIGNAL_GET_STATS, + + /* signals */ + SIGNAL_CLIENT_ADDED, + SIGNAL_CLIENT_REMOVED, + SIGNAL_CLIENT_FD_REMOVED, + + LAST_SIGNAL +}; + + +/* this is really arbitrarily chosen */ +#define DEFAULT_PROTOCOL GST_TCP_PROTOCOL_NONE +#define DEFAULT_MODE 1 +#define DEFAULT_BUFFERS_MAX -1 +#define DEFAULT_BUFFERS_SOFT_MAX -1 +#define DEFAULT_TIME_MIN -1 +#define DEFAULT_BYTES_MIN -1 +#define DEFAULT_BUFFERS_MIN -1 +#define DEFAULT_UNIT_TYPE GST_TCP_UNIT_TYPE_BUFFERS +#define DEFAULT_UNITS_MAX -1 +#define DEFAULT_UNITS_SOFT_MAX -1 +#define DEFAULT_RECOVER_POLICY GST_RECOVER_POLICY_NONE +#define DEFAULT_TIMEOUT 0 +#define DEFAULT_SYNC_METHOD GST_SYNC_METHOD_LATEST + +#define DEFAULT_BURST_UNIT GST_TCP_UNIT_TYPE_UNDEFINED +#define DEFAULT_BURST_VALUE 0 + +#define DEFAULT_QOS_DSCP -1 +#define DEFAULT_HANDLE_READ TRUE + +#define DEFAULT_RESEND_STREAMHEADER TRUE + +enum +{ + PROP_0, + PROP_PROTOCOL, + PROP_MODE, + PROP_BUFFERS_QUEUED, + PROP_BYTES_QUEUED, + PROP_TIME_QUEUED, + + PROP_UNIT_TYPE, + PROP_UNITS_MAX, + PROP_UNITS_SOFT_MAX, + + PROP_BUFFERS_MAX, + PROP_BUFFERS_SOFT_MAX, + + PROP_TIME_MIN, + PROP_BYTES_MIN, + PROP_BUFFERS_MIN, + + PROP_RECOVER_POLICY, + PROP_TIMEOUT, + PROP_SYNC_METHOD, + PROP_BYTES_TO_SERVE, + PROP_BYTES_SERVED, + + PROP_BURST_UNIT, + PROP_BURST_VALUE, + + PROP_QOS_DSCP, + + PROP_HANDLE_READ, + + PROP_RESEND_STREAMHEADER, + + PROP_NUM_FDS, + + PROP_LAST +}; + +/* For backward compat, we can't really select the poll mode anymore with + * GstPoll. */ +#define GST_TYPE_FDSET_MODE (gst_fdset_mode_get_type()) +static GType +gst_fdset_mode_get_type (void) +{ + static GType fdset_mode_type = 0; + static const GEnumValue fdset_mode[] = { + {0, "Select", "select"}, + {1, "Poll", "poll"}, + {2, "EPoll", "epoll"}, + {0, NULL, NULL}, + }; + + if (!fdset_mode_type) { + fdset_mode_type = g_enum_register_static ("GstFDSetMode", fdset_mode); + } + return fdset_mode_type; +} + +#define GST_TYPE_RECOVER_POLICY (gst_recover_policy_get_type()) +static GType +gst_recover_policy_get_type (void) +{ + static GType recover_policy_type = 0; + static const GEnumValue recover_policy[] = { + {GST_RECOVER_POLICY_NONE, + "Do not try to recover", "none"}, + {GST_RECOVER_POLICY_RESYNC_LATEST, + "Resync client to latest buffer", "latest"}, + {GST_RECOVER_POLICY_RESYNC_SOFT_LIMIT, + "Resync client to soft limit", "soft-limit"}, + {GST_RECOVER_POLICY_RESYNC_KEYFRAME, + "Resync client to most recent keyframe", "keyframe"}, + {0, NULL, NULL}, + }; + + if (!recover_policy_type) { + recover_policy_type = + g_enum_register_static ("GstRecoverPolicy", recover_policy); + } + return recover_policy_type; +} + +#define GST_TYPE_SYNC_METHOD (gst_sync_method_get_type()) +static GType +gst_sync_method_get_type (void) +{ + static GType sync_method_type = 0; + static const GEnumValue sync_method[] = { + {GST_SYNC_METHOD_LATEST, + "Serve starting from the latest buffer", "latest"}, + {GST_SYNC_METHOD_NEXT_KEYFRAME, + "Serve starting from the next keyframe", "next-keyframe"}, + {GST_SYNC_METHOD_LATEST_KEYFRAME, + "Serve everything since the latest keyframe (burst)", + "latest-keyframe"}, + {GST_SYNC_METHOD_BURST, "Serve burst-value data to client", "burst"}, + {GST_SYNC_METHOD_BURST_KEYFRAME, + "Serve burst-value data starting on a keyframe", + "burst-keyframe"}, + {GST_SYNC_METHOD_BURST_WITH_KEYFRAME, + "Serve burst-value data preferably starting on a keyframe", + "burst-with-keyframe"}, + {0, NULL, NULL}, + }; + + if (!sync_method_type) { + sync_method_type = g_enum_register_static ("GstSyncMethod", sync_method); + } + return sync_method_type; +} + +#define GST_TYPE_UNIT_TYPE (gst_unit_type_get_type()) +static GType +gst_unit_type_get_type (void) +{ + static GType unit_type_type = 0; + static const GEnumValue unit_type[] = { + {GST_TCP_UNIT_TYPE_UNDEFINED, "Undefined", "undefined"}, + {GST_TCP_UNIT_TYPE_BUFFERS, "Buffers", "buffers"}, + {GST_TCP_UNIT_TYPE_BYTES, "Bytes", "bytes"}, + {GST_TCP_UNIT_TYPE_TIME, "Time", "time"}, + {0, NULL, NULL}, + }; + + if (!unit_type_type) { + unit_type_type = g_enum_register_static ("GstTCPUnitType", unit_type); + } + return unit_type_type; +} + +#define GST_TYPE_CLIENT_STATUS (gst_client_status_get_type()) +static GType +gst_client_status_get_type (void) +{ + static GType client_status_type = 0; + static const GEnumValue client_status[] = { + {GST_CLIENT_STATUS_OK, "ok", "ok"}, + {GST_CLIENT_STATUS_CLOSED, "Closed", "closed"}, + {GST_CLIENT_STATUS_REMOVED, "Removed", "removed"}, + {GST_CLIENT_STATUS_SLOW, "Too slow", "slow"}, + {GST_CLIENT_STATUS_ERROR, "Error", "error"}, + {GST_CLIENT_STATUS_DUPLICATE, "Duplicate", "duplicate"}, + {GST_CLIENT_STATUS_FLUSHING, "Flushing", "flushing"}, + {0, NULL, NULL}, + }; + + if (!client_status_type) { + client_status_type = + g_enum_register_static ("GstClientStatus", client_status); + } + return client_status_type; +} + +static void gst_multi_fd_sink_finalize (GObject * object); + +static void gst_multi_fd_sink_remove_client_link (GstMultiFdSink * sink, + GList * link); + +static GstFlowReturn gst_multi_fd_sink_render (GstBaseSink * bsink, + GstBuffer * buf); +static GstStateChangeReturn gst_multi_fd_sink_change_state (GstElement * + element, GstStateChange transition); + +static void gst_multi_fd_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_multi_fd_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GST_BOILERPLATE (GstMultiFdSink, gst_multi_fd_sink, GstBaseSink, + GST_TYPE_BASE_SINK); + +static guint gst_multi_fd_sink_signals[LAST_SIGNAL] = { 0 }; + +static void +gst_multi_fd_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (element_class, + "Multi filedescriptor sink", "Sink/Network", + "Send data to multiple filedescriptors", + "Thomas Vander Stichele , " + "Wim Taymans "); +} + +static void +gst_multi_fd_sink_class_init (GstMultiFdSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + + gobject_class->set_property = gst_multi_fd_sink_set_property; + gobject_class->get_property = gst_multi_fd_sink_get_property; + gobject_class->finalize = gst_multi_fd_sink_finalize; + + g_object_class_install_property (gobject_class, PROP_PROTOCOL, + g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in" + ". GDP protocol here is deprecated. Please use gdppay element.", + GST_TYPE_TCP_PROTOCOL, DEFAULT_PROTOCOL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstMultiFdSink::mode + * + * The mode for selecting activity on the fds. + * + * This property is deprecated since 0.10.18, if will now automatically + * select and use the most optimal method. + */ + g_object_class_install_property (gobject_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", + "The mode for selecting activity on the fds (deprecated)", + GST_TYPE_FDSET_MODE, DEFAULT_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFERS_MAX, + g_param_spec_int ("buffers-max", "Buffers max", + "max number of buffers to queue for a client (-1 = no limit)", -1, + G_MAXINT, DEFAULT_BUFFERS_MAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BUFFERS_SOFT_MAX, + g_param_spec_int ("buffers-soft-max", "Buffers soft max", + "Recover client when going over this limit (-1 = no limit)", -1, + G_MAXINT, DEFAULT_BUFFERS_SOFT_MAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BYTES_MIN, + g_param_spec_int ("bytes-min", "Bytes min", + "min number of bytes to queue (-1 = as little as possible)", -1, + G_MAXINT, DEFAULT_BYTES_MIN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TIME_MIN, + g_param_spec_int64 ("time-min", "Time min", + "min number of time to queue (-1 = as little as possible)", -1, + G_MAXINT64, DEFAULT_TIME_MIN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BUFFERS_MIN, + g_param_spec_int ("buffers-min", "Buffers min", + "min number of buffers to queue (-1 = as few as possible)", -1, + G_MAXINT, DEFAULT_BUFFERS_MIN, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_UNIT_TYPE, + g_param_spec_enum ("unit-type", "Units type", + "The unit to measure the max/soft-max/queued properties", + GST_TYPE_UNIT_TYPE, DEFAULT_UNIT_TYPE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_UNITS_MAX, + g_param_spec_int64 ("units-max", "Units max", + "max number of units to queue (-1 = no limit)", -1, G_MAXINT64, + DEFAULT_UNITS_MAX, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_UNITS_SOFT_MAX, + g_param_spec_int64 ("units-soft-max", "Units soft max", + "Recover client when going over this limit (-1 = no limit)", -1, + G_MAXINT64, DEFAULT_UNITS_SOFT_MAX, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BUFFERS_QUEUED, + g_param_spec_uint ("buffers-queued", "Buffers queued", + "Number of buffers currently queued", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +#if NOT_IMPLEMENTED + g_object_class_install_property (gobject_class, PROP_BYTES_QUEUED, + g_param_spec_uint ("bytes-queued", "Bytes queued", + "Number of bytes currently queued", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TIME_QUEUED, + g_param_spec_uint64 ("time-queued", "Time queued", + "Number of time currently queued", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); +#endif + + g_object_class_install_property (gobject_class, PROP_RECOVER_POLICY, + g_param_spec_enum ("recover-policy", "Recover Policy", + "How to recover when client reaches the soft max", + GST_TYPE_RECOVER_POLICY, DEFAULT_RECOVER_POLICY, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TIMEOUT, + g_param_spec_uint64 ("timeout", "Timeout", + "Maximum inactivity timeout in nanoseconds for a client (0 = no limit)", + 0, G_MAXUINT64, DEFAULT_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SYNC_METHOD, + g_param_spec_enum ("sync-method", "Sync Method", + "How to sync new clients to the stream", GST_TYPE_SYNC_METHOD, + DEFAULT_SYNC_METHOD, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BYTES_TO_SERVE, + g_param_spec_uint64 ("bytes-to-serve", "Bytes to serve", + "Number of bytes received to serve to clients", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BYTES_SERVED, + g_param_spec_uint64 ("bytes-served", "Bytes served", + "Total number of bytes send to all clients", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_BURST_UNIT, + g_param_spec_enum ("burst-unit", "Burst unit", + "The format of the burst units (when sync-method is burst[[-with]-keyframe])", + GST_TYPE_UNIT_TYPE, DEFAULT_BURST_UNIT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BURST_VALUE, + g_param_spec_uint64 ("burst-value", "Burst value", + "The amount of burst expressed in burst-unit", 0, G_MAXUINT64, + DEFAULT_BURST_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_QOS_DSCP, + g_param_spec_int ("qos-dscp", "QoS diff srv code point", + "Quality of Service, differentiated services code point (-1 default)", + -1, 63, DEFAULT_QOS_DSCP, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstMultiFdSink::handle-read + * + * Handle read requests from clients and discard the data. + * + * Since: 0.10.23 + */ + g_object_class_install_property (gobject_class, PROP_HANDLE_READ, + g_param_spec_boolean ("handle-read", "Handle Read", + "Handle client reads and discard the data", + DEFAULT_HANDLE_READ, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstMultiFdSink::resend-streamheader + * + * Resend the streamheaders to existing clients when they change. + * + * Since: 0.10.23 + */ + g_object_class_install_property (gobject_class, PROP_RESEND_STREAMHEADER, + g_param_spec_boolean ("resend-streamheader", "Resend streamheader", + "Resend the streamheader if it changes in the caps", + DEFAULT_RESEND_STREAMHEADER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_NUM_FDS, + g_param_spec_uint ("num-fds", "Number of fds", + "The current number of client file descriptors.", + 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstMultiFdSink::add: + * @gstmultifdsink: the multifdsink element to emit this signal on + * @fd: the file descriptor to add to multifdsink + * + * Hand the given open file descriptor to multifdsink to write to. + */ + gst_multi_fd_sink_signals[SIGNAL_ADD] = + g_signal_new ("add", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + add), NULL, NULL, g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, + G_TYPE_INT); + /** + * GstMultiFdSink::add-full: + * @gstmultifdsink: the multifdsink element to emit this signal on + * @fd: the file descriptor to add to multifdsink + * @sync: the sync method to use + * @unit_type_min: the unit-type of @value_min + * @value_min: the minimum amount of data to burst expressed in + * @unit_type_min units. + * @unit_type_max: the unit-type of @value_max + * @value_max: the maximum amount of data to burst expressed in + * @unit_type_max units. + * + * Hand the given open file descriptor to multifdsink to write to and + * specify the burst parameters for the new connection. + */ + gst_multi_fd_sink_signals[SIGNAL_ADD_BURST] = + g_signal_new ("add-full", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + add_full), NULL, NULL, + gst_tcp_marshal_VOID__INT_ENUM_INT_UINT64_INT_UINT64, G_TYPE_NONE, 6, + G_TYPE_INT, GST_TYPE_SYNC_METHOD, GST_TYPE_UNIT_TYPE, G_TYPE_UINT64, + GST_TYPE_UNIT_TYPE, G_TYPE_UINT64); + /** + * GstMultiFdSink::remove: + * @gstmultifdsink: the multifdsink element to emit this signal on + * @fd: the file descriptor to remove from multifdsink + * + * Remove the given open file descriptor from multifdsink. + */ + gst_multi_fd_sink_signals[SIGNAL_REMOVE] = + g_signal_new ("remove", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + remove), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, + G_TYPE_INT); + /** + * GstMultiFdSink::remove-flush: + * @gstmultifdsink: the multifdsink element to emit this signal on + * @fd: the file descriptor to remove from multifdsink + * + * Remove the given open file descriptor from multifdsink after flushing all + * the pending data to the fd. + */ + gst_multi_fd_sink_signals[SIGNAL_REMOVE_FLUSH] = + g_signal_new ("remove-flush", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + remove_flush), NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, + G_TYPE_INT); + /** + * GstMultiFdSink::clear: + * @gstmultifdsink: the multifdsink element to emit this signal on + * + * Remove all file descriptors from multifdsink. Since multifdsink did not + * open fd's itself, it does not explicitly close the fd. The application + * should do so by connecting to the client-fd-removed callback. + */ + gst_multi_fd_sink_signals[SIGNAL_CLEAR] = + g_signal_new ("clear", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + clear), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GstMultiFdSink::get-stats: + * @gstmultifdsink: the multifdsink element to emit this signal on + * @fd: the file descriptor to get stats of from multifdsink + * + * Get statistics about @fd. This function returns a GValueArray to ease + * automatic wrapping for bindings. + * + * Returns: a GValueArray with the statistics. The array contains guint64 + * values that represent respectively: total number of bytes sent, time + * when the client was added, time when the client was + * disconnected/removed, time the client is/was active, last activity + * time (in epoch seconds), number of buffers dropped. + * All times are expressed in nanoseconds (GstClockTime). + * The array can be 0-length if the client was not found. + */ + gst_multi_fd_sink_signals[SIGNAL_GET_STATS] = + g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, G_STRUCT_OFFSET (GstMultiFdSinkClass, + get_stats), NULL, NULL, gst_tcp_marshal_BOXED__INT, + G_TYPE_VALUE_ARRAY, 1, G_TYPE_INT); + + /** + * GstMultiFdSink::client-added: + * @gstmultifdsink: the multifdsink element that emitted this signal + * @fd: the file descriptor that was added to multifdsink + * + * The given file descriptor was added to multifdsink. This signal will + * be emitted from the streaming thread so application should be prepared + * for that. + */ + gst_multi_fd_sink_signals[SIGNAL_CLIENT_ADDED] = + g_signal_new ("client-added", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiFdSinkClass, client_added), + NULL, NULL, gst_tcp_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + /** + * GstMultiFdSink::client-removed: + * @gstmultifdsink: the multifdsink element that emitted this signal + * @fd: the file descriptor that is to be removed from multifdsink + * @status: the reason why the client was removed + * + * The given file descriptor is about to be removed from multifdsink. This + * signal will be emitted from the streaming thread so applications should + * be prepared for that. + * + * @gstmultifdsink still holds a handle to @fd so it is possible to call + * the get-stats signal from this callback. For the same reason it is + * not safe to close() and reuse @fd in this callback. + */ + gst_multi_fd_sink_signals[SIGNAL_CLIENT_REMOVED] = + g_signal_new ("client-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiFdSinkClass, + client_removed), NULL, NULL, gst_tcp_marshal_VOID__INT_BOXED, + G_TYPE_NONE, 2, G_TYPE_INT, GST_TYPE_CLIENT_STATUS); + /** + * GstMultiFdSink::client-fd-removed: + * @gstmultifdsink: the multifdsink element that emitted this signal + * @fd: the file descriptor that was removed from multifdsink + * + * The given file descriptor was removed from multifdsink. This signal will + * be emitted from the streaming thread so applications should be prepared + * for that. + * + * In this callback, @gstmultifdsink has removed all the information + * associated with @fd and it is therefore not possible to call get-stats + * with @fd. It is however safe to close() and reuse @fd in the callback. + * + * Since: 0.10.7 + */ + gst_multi_fd_sink_signals[SIGNAL_CLIENT_FD_REMOVED] = + g_signal_new ("client-fd-removed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstMultiFdSinkClass, + client_fd_removed), NULL, NULL, gst_tcp_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_multi_fd_sink_change_state); + + gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_render); + + klass->add = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_add); + klass->add_full = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_add_full); + klass->remove = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_remove); + klass->remove_flush = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_remove_flush); + klass->clear = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_clear); + klass->get_stats = GST_DEBUG_FUNCPTR (gst_multi_fd_sink_get_stats); + + GST_DEBUG_CATEGORY_INIT (multifdsink_debug, "multifdsink", 0, "FD sink"); +} + +static void +gst_multi_fd_sink_init (GstMultiFdSink * this, GstMultiFdSinkClass * klass) +{ + GST_OBJECT_FLAG_UNSET (this, GST_MULTI_FD_SINK_OPEN); + + this->protocol = DEFAULT_PROTOCOL; + this->mode = DEFAULT_MODE; + + CLIENTS_LOCK_INIT (this); + this->clients = NULL; + this->fd_hash = g_hash_table_new (g_int_hash, g_int_equal); + + this->bufqueue = g_array_new (FALSE, TRUE, sizeof (GstBuffer *)); + this->unit_type = DEFAULT_UNIT_TYPE; + this->units_max = DEFAULT_UNITS_MAX; + this->units_soft_max = DEFAULT_UNITS_SOFT_MAX; + this->time_min = DEFAULT_TIME_MIN; + this->bytes_min = DEFAULT_BYTES_MIN; + this->buffers_min = DEFAULT_BUFFERS_MIN; + this->recover_policy = DEFAULT_RECOVER_POLICY; + + this->timeout = DEFAULT_TIMEOUT; + this->def_sync_method = DEFAULT_SYNC_METHOD; + this->def_burst_unit = DEFAULT_BURST_UNIT; + this->def_burst_value = DEFAULT_BURST_VALUE; + + this->qos_dscp = DEFAULT_QOS_DSCP; + this->handle_read = DEFAULT_HANDLE_READ; + + this->resend_streamheader = DEFAULT_RESEND_STREAMHEADER; + + this->header_flags = 0; +} + +static void +gst_multi_fd_sink_finalize (GObject * object) +{ + GstMultiFdSink *this; + + this = GST_MULTI_FD_SINK (object); + + CLIENTS_LOCK_FREE (this); + g_hash_table_destroy (this->fd_hash); + g_array_free (this->bufqueue, TRUE); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gint +setup_dscp_client (GstMultiFdSink * sink, GstTCPClient * client) +{ + gint tos; + gint ret; + union gst_sockaddr + { + struct sockaddr sa; + struct sockaddr_in6 sa_in6; + struct sockaddr_storage sa_stor; + } sa; + socklen_t slen = sizeof (sa); + gint af; + + /* don't touch */ + if (sink->qos_dscp < 0) + return 0; + + if ((ret = getsockname (client->fd.fd, &sa.sa, &slen)) < 0) { + GST_DEBUG_OBJECT (sink, "could not get sockname: %s", g_strerror (errno)); + return ret; + } + + af = sa.sa.sa_family; + + /* if this is an IPv4-mapped address then do IPv4 QoS */ + if (af == AF_INET6) { + + GST_DEBUG_OBJECT (sink, "check IP6 socket"); + if (IN6_IS_ADDR_V4MAPPED (&(sa.sa_in6.sin6_addr))) { + GST_DEBUG_OBJECT (sink, "mapped to IPV4"); + af = AF_INET; + } + } + + /* extract and shift 6 bits of the DSCP */ + tos = (sink->qos_dscp & 0x3f) << 2; + + switch (af) { + case AF_INET: + ret = setsockopt (client->fd.fd, IPPROTO_IP, IP_TOS, &tos, sizeof (tos)); + break; + case AF_INET6: +#ifdef IPV6_TCLASS + ret = + setsockopt (client->fd.fd, IPPROTO_IPV6, IPV6_TCLASS, &tos, + sizeof (tos)); + break; +#endif + default: + ret = 0; + GST_ERROR_OBJECT (sink, "unsupported AF"); + break; + } + if (ret) + GST_DEBUG_OBJECT (sink, "could not set DSCP: %s", g_strerror (errno)); + + return ret; +} + + +static void +setup_dscp (GstMultiFdSink * sink) +{ + GList *clients, *next; + + CLIENTS_LOCK (sink); + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + setup_dscp_client (sink, client); + } + CLIENTS_UNLOCK (sink); +} + +/* "add-full" signal implementation */ +void +gst_multi_fd_sink_add_full (GstMultiFdSink * sink, int fd, + GstSyncMethod sync_method, GstTCPUnitType min_unit, guint64 min_value, + GstTCPUnitType max_unit, guint64 max_value) +{ + GstTCPClient *client; + GList *clink; + GTimeVal now; + gint flags; + struct stat statbuf; + + GST_DEBUG_OBJECT (sink, "[fd %5d] adding client, sync_method %d, " + "min_unit %d, min_value %" G_GUINT64_FORMAT + ", max_unit %d, max_value %" G_GUINT64_FORMAT, fd, sync_method, + min_unit, min_value, max_unit, max_value); + + /* do limits check if we can */ + if (min_unit == max_unit) { + if (max_value != -1 && min_value != -1 && max_value < min_value) + goto wrong_limits; + } + + /* create client datastructure */ + client = g_new0 (GstTCPClient, 1); + client->fd.fd = fd; + client->status = GST_CLIENT_STATUS_OK; + client->bufpos = -1; + client->flushcount = -1; + client->bufoffset = 0; + client->sending = NULL; + client->bytes_sent = 0; + client->dropped_buffers = 0; + client->avg_queue_size = 0; + client->first_buffer_ts = GST_CLOCK_TIME_NONE; + client->last_buffer_ts = GST_CLOCK_TIME_NONE; + client->new_connection = TRUE; + client->burst_min_unit = min_unit; + client->burst_min_value = min_value; + client->burst_max_unit = max_unit; + client->burst_max_value = max_value; + client->sync_method = sync_method; + client->currently_removing = FALSE; + + /* update start time */ + g_get_current_time (&now); + client->connect_time = GST_TIMEVAL_TO_TIME (now); + client->disconnect_time = 0; + /* set last activity time to connect time */ + client->last_activity_time = client->connect_time; + + CLIENTS_LOCK (sink); + + /* check the hash to find a duplicate fd */ + clink = g_hash_table_lookup (sink->fd_hash, &client->fd.fd); + if (clink != NULL) + goto duplicate; + + /* we can add the fd now */ + clink = sink->clients = g_list_prepend (sink->clients, client); + g_hash_table_insert (sink->fd_hash, &client->fd.fd, clink); + sink->clients_cookie++; + + /* set the socket to non blocking */ + if (fcntl (fd, F_SETFL, O_NONBLOCK) < 0) { + GST_ERROR_OBJECT (sink, "failed to make socket %d non-blocking: %s", fd, + g_strerror (errno)); + } + + /* we always read from a client */ + gst_poll_add_fd (sink->fdset, &client->fd); + + /* we don't try to read from write only fds */ + if (sink->handle_read) { + flags = fcntl (fd, F_GETFL, 0); + if ((flags & O_ACCMODE) != O_WRONLY) { + gst_poll_fd_ctl_read (sink->fdset, &client->fd, TRUE); + } + } + /* figure out the mode, can't use send() for non sockets */ + if (fstat (fd, &statbuf) == 0 && S_ISSOCK (statbuf.st_mode)) { + client->is_socket = TRUE; + setup_dscp_client (sink, client); + } + + gst_poll_restart (sink->fdset); + + CLIENTS_UNLOCK (sink); + + g_signal_emit (G_OBJECT (sink), + gst_multi_fd_sink_signals[SIGNAL_CLIENT_ADDED], 0, fd); + + return; + + /* errors */ +wrong_limits: + { + GST_WARNING_OBJECT (sink, + "[fd %5d] wrong values min =%" G_GUINT64_FORMAT ", max=%" + G_GUINT64_FORMAT ", unit %d specified when adding client", fd, + min_value, max_value, min_unit); + return; + } +duplicate: + { + client->status = GST_CLIENT_STATUS_DUPLICATE; + CLIENTS_UNLOCK (sink); + GST_WARNING_OBJECT (sink, "[fd %5d] duplicate client found, refusing", fd); + g_signal_emit (G_OBJECT (sink), + gst_multi_fd_sink_signals[SIGNAL_CLIENT_REMOVED], 0, fd, + client->status); + g_free (client); + return; + } +} + +/* "add" signal implemntation */ +void +gst_multi_fd_sink_add (GstMultiFdSink * sink, int fd) +{ + gst_multi_fd_sink_add_full (sink, fd, sink->def_sync_method, + sink->def_burst_unit, sink->def_burst_value, sink->def_burst_unit, -1); +} + +/* "remove" signal implementation */ +void +gst_multi_fd_sink_remove (GstMultiFdSink * sink, int fd) +{ + GList *clink; + + GST_DEBUG_OBJECT (sink, "[fd %5d] removing client", fd); + + CLIENTS_LOCK (sink); + clink = g_hash_table_lookup (sink->fd_hash, &fd); + if (clink != NULL) { + GstTCPClient *client = (GstTCPClient *) clink->data; + + if (client->status != GST_CLIENT_STATUS_OK) { + GST_INFO_OBJECT (sink, + "[fd %5d] Client already disconnecting with status %d", + fd, client->status); + goto done; + } + + client->status = GST_CLIENT_STATUS_REMOVED; + gst_multi_fd_sink_remove_client_link (sink, clink); + gst_poll_restart (sink->fdset); + } else { + GST_WARNING_OBJECT (sink, "[fd %5d] no client with this fd found!", fd); + } + +done: + CLIENTS_UNLOCK (sink); +} + +/* "remove-flush" signal implementation */ +void +gst_multi_fd_sink_remove_flush (GstMultiFdSink * sink, int fd) +{ + GList *clink; + + GST_DEBUG_OBJECT (sink, "[fd %5d] flushing client", fd); + + CLIENTS_LOCK (sink); + clink = g_hash_table_lookup (sink->fd_hash, &fd); + if (clink != NULL) { + GstTCPClient *client = (GstTCPClient *) clink->data; + + if (client->status != GST_CLIENT_STATUS_OK) { + GST_INFO_OBJECT (sink, + "[fd %5d] Client already disconnecting with status %d", + fd, client->status); + goto done; + } + + /* take the position of the client as the number of buffers left to flush. + * If the client was at position -1, we flush 0 buffers, 0 == flush 1 + * buffer, etc... */ + client->flushcount = client->bufpos + 1; + /* mark client as flushing. We can not remove the client right away because + * it might have some buffers to flush in the ->sending queue. */ + client->status = GST_CLIENT_STATUS_FLUSHING; + } else { + GST_WARNING_OBJECT (sink, "[fd %5d] no client with this fd found!", fd); + } +done: + CLIENTS_UNLOCK (sink); +} + +/* can be called both through the signal (i.e. from any thread) or when + * stopping, after the writing thread has shut down */ +void +gst_multi_fd_sink_clear (GstMultiFdSink * sink) +{ + GList *clients, *next; + guint32 cookie; + + GST_DEBUG_OBJECT (sink, "clearing all clients"); + + CLIENTS_LOCK (sink); +restart: + cookie = sink->clients_cookie; + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + if (cookie != sink->clients_cookie) { + GST_DEBUG_OBJECT (sink, "cookie changed while removing all clients"); + goto restart; + } + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + client->status = GST_CLIENT_STATUS_REMOVED; + gst_multi_fd_sink_remove_client_link (sink, clients); + } + gst_poll_restart (sink->fdset); + CLIENTS_UNLOCK (sink); +} + +/* "get-stats" signal implementation + * the array returned contains: + * + * guint64 : bytes_sent + * guint64 : connect time (in nanoseconds, since Epoch) + * guint64 : disconnect time (in nanoseconds, since Epoch) + * guint64 : time the client is/was connected (in nanoseconds) + * guint64 : last activity time (in nanoseconds, since Epoch) + * guint64 : buffers dropped due to recovery + * guint64 : timestamp of the first buffer sent (in nanoseconds) + * guint64 : timestamp of the last buffer sent (in nanoseconds) + */ +GValueArray * +gst_multi_fd_sink_get_stats (GstMultiFdSink * sink, int fd) +{ + GstTCPClient *client; + GValueArray *result = NULL; + GList *clink; + + CLIENTS_LOCK (sink); + clink = g_hash_table_lookup (sink->fd_hash, &fd); + if (clink == NULL) + goto noclient; + + client = (GstTCPClient *) clink->data; + if (client != NULL) { + GValue value = { 0 }; + guint64 interval; + + result = g_value_array_new (7); + + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->bytes_sent); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->connect_time); + result = g_value_array_append (result, &value); + g_value_unset (&value); + if (client->disconnect_time == 0) { + GTimeVal nowtv; + + g_get_current_time (&nowtv); + + interval = GST_TIMEVAL_TO_TIME (nowtv) - client->connect_time; + } else { + interval = client->disconnect_time - client->connect_time; + } + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->disconnect_time); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, interval); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->last_activity_time); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->dropped_buffers); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->first_buffer_ts); + result = g_value_array_append (result, &value); + g_value_unset (&value); + g_value_init (&value, G_TYPE_UINT64); + g_value_set_uint64 (&value, client->last_buffer_ts); + result = g_value_array_append (result, &value); + } + +noclient: + CLIENTS_UNLOCK (sink); + + /* python doesn't like a NULL pointer yet */ + if (result == NULL) { + GST_WARNING_OBJECT (sink, "[fd %5d] no client with this found!", fd); + result = g_value_array_new (0); + } + + return result; +} + +/* should be called with the clientslock helt. + * Note that we don't close the fd as we didn't open it in the first + * place. An application should connect to the client-fd-removed signal and + * close the fd itself. + */ +static void +gst_multi_fd_sink_remove_client_link (GstMultiFdSink * sink, GList * link) +{ + int fd; + GTimeVal now; + GstTCPClient *client = (GstTCPClient *) link->data; + GstMultiFdSinkClass *fclass; + + fclass = GST_MULTI_FD_SINK_GET_CLASS (sink); + + fd = client->fd.fd; + + if (client->currently_removing) { + GST_WARNING_OBJECT (sink, "[fd %5d] client is already being removed", fd); + return; + } else { + client->currently_removing = TRUE; + } + + /* FIXME: if we keep track of ip we can log it here and signal */ + switch (client->status) { + case GST_CLIENT_STATUS_OK: + GST_WARNING_OBJECT (sink, "[fd %5d] removing client %p for no reason", + fd, client); + break; + case GST_CLIENT_STATUS_CLOSED: + GST_DEBUG_OBJECT (sink, "[fd %5d] removing client %p because of close", + fd, client); + break; + case GST_CLIENT_STATUS_REMOVED: + GST_DEBUG_OBJECT (sink, + "[fd %5d] removing client %p because the app removed it", fd, client); + break; + case GST_CLIENT_STATUS_SLOW: + GST_INFO_OBJECT (sink, + "[fd %5d] removing client %p because it was too slow", fd, client); + break; + case GST_CLIENT_STATUS_ERROR: + GST_WARNING_OBJECT (sink, + "[fd %5d] removing client %p because of error", fd, client); + break; + case GST_CLIENT_STATUS_FLUSHING: + default: + GST_WARNING_OBJECT (sink, + "[fd %5d] removing client %p with invalid reason %d", fd, client, + client->status); + break; + } + + gst_poll_remove_fd (sink->fdset, &client->fd); + + g_get_current_time (&now); + client->disconnect_time = GST_TIMEVAL_TO_TIME (now); + + /* free client buffers */ + g_slist_foreach (client->sending, (GFunc) gst_mini_object_unref, NULL); + g_slist_free (client->sending); + client->sending = NULL; + + if (client->caps) + gst_caps_unref (client->caps); + client->caps = NULL; + + /* unlock the mutex before signaling because the signal handler + * might query some properties */ + CLIENTS_UNLOCK (sink); + + g_signal_emit (G_OBJECT (sink), + gst_multi_fd_sink_signals[SIGNAL_CLIENT_REMOVED], 0, fd, client->status); + + /* lock again before we remove the client completely */ + CLIENTS_LOCK (sink); + + /* fd cannot be reused in the above signal callback so we can safely + * remove it from the hashtable here */ + if (!g_hash_table_remove (sink->fd_hash, &client->fd.fd)) { + GST_WARNING_OBJECT (sink, + "[fd %5d] error removing client %p from hash", client->fd.fd, client); + } + /* after releasing the lock above, the link could be invalid, more + * precisely, the next and prev pointers could point to invalid list + * links. One optimisation could be to add a cookie to the linked list + * and take a shortcut when it did not change between unlocking and locking + * our mutex. For now we just walk the list again. */ + sink->clients = g_list_remove (sink->clients, client); + sink->clients_cookie++; + + if (fclass->removed) + fclass->removed (sink, client->fd.fd); + + g_free (client); + CLIENTS_UNLOCK (sink); + + /* and the fd is really gone now */ + g_signal_emit (G_OBJECT (sink), + gst_multi_fd_sink_signals[SIGNAL_CLIENT_FD_REMOVED], 0, fd); + + CLIENTS_LOCK (sink); +} + +/* handle a read on a client fd, + * which either indicates a close or should be ignored + * returns FALSE if some error occured or the client closed. */ +static gboolean +gst_multi_fd_sink_handle_client_read (GstMultiFdSink * sink, + GstTCPClient * client) +{ + int avail, fd; + gboolean ret; + + fd = client->fd.fd; + + if (ioctl (fd, FIONREAD, &avail) < 0) + goto ioctl_failed; + + GST_DEBUG_OBJECT (sink, "[fd %5d] select reports client read of %d bytes", + fd, avail); + + ret = TRUE; + + if (avail == 0) { + /* client sent close, so remove it */ + GST_DEBUG_OBJECT (sink, "[fd %5d] client asked for close, removing", fd); + client->status = GST_CLIENT_STATUS_CLOSED; + ret = FALSE; + } else if (avail < 0) { + GST_WARNING_OBJECT (sink, "[fd %5d] avail < 0, removing", fd); + client->status = GST_CLIENT_STATUS_ERROR; + ret = FALSE; + } else { + guint8 dummy[512]; + gint nread; + + /* just Read 'n' Drop, could also just drop the client as it's not supposed + * to write to us except for closing the socket, I guess it's because we + * like to listen to our customers. */ + do { + /* this is the maximum we can read */ + gint to_read = MIN (avail, 512); + + GST_DEBUG_OBJECT (sink, "[fd %5d] client wants us to read %d bytes", + fd, to_read); + + nread = read (fd, dummy, to_read); + if (nread < -1) { + GST_WARNING_OBJECT (sink, "[fd %5d] could not read %d bytes: %s (%d)", + fd, to_read, g_strerror (errno), errno); + client->status = GST_CLIENT_STATUS_ERROR; + ret = FALSE; + break; + } else if (nread == 0) { + GST_WARNING_OBJECT (sink, "[fd %5d] 0 bytes in read, removing", fd); + client->status = GST_CLIENT_STATUS_ERROR; + ret = FALSE; + break; + } + avail -= nread; + } + while (avail > 0); + } + return ret; + + /* ERRORS */ +ioctl_failed: + { + GST_WARNING_OBJECT (sink, "[fd %5d] ioctl failed: %s (%d)", + fd, g_strerror (errno), errno); + client->status = GST_CLIENT_STATUS_ERROR; + return FALSE; + } +} + +/* Queue raw data for this client, creating a new buffer. + * This takes ownership of the data by + * setting it as GST_BUFFER_MALLOCDATA() on the created buffer so + * be sure to pass g_free()-able @data. + */ +static gboolean +gst_multi_fd_sink_client_queue_data (GstMultiFdSink * sink, + GstTCPClient * client, gchar * data, gint len) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) data; + GST_BUFFER_MALLOCDATA (buf) = (guint8 *) data; + GST_BUFFER_SIZE (buf) = len; + + GST_LOG_OBJECT (sink, "[fd %5d] queueing data of length %d", + client->fd.fd, len); + + client->sending = g_slist_append (client->sending, buf); + + return TRUE; +} + +/* GDP-encode given caps and queue them for sending */ +static gboolean +gst_multi_fd_sink_client_queue_caps (GstMultiFdSink * sink, + GstTCPClient * client, const GstCaps * caps) +{ + guint8 *header; + guint8 *payload; + guint length; + gchar *string; + + g_return_val_if_fail (caps != NULL, FALSE); + + string = gst_caps_to_string (caps); + GST_DEBUG_OBJECT (sink, "[fd %5d] Queueing caps %s through GDP", + client->fd.fd, string); + g_free (string); + + if (!gst_dp_packet_from_caps (caps, sink->header_flags, &length, &header, + &payload)) { + GST_DEBUG_OBJECT (sink, "Could not create GDP packet from caps"); + return FALSE; + } + gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header, length); + + length = gst_dp_header_payload_length (header); + gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) payload, length); + + return TRUE; +} + +static gboolean +is_sync_frame (GstMultiFdSink * sink, GstBuffer * buffer) +{ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT)) { + return FALSE; + } else if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) { + return TRUE; + } + + return FALSE; +} + +/* queue the given buffer for the given client, possibly adding the GDP + * header if GDP is being used */ +static gboolean +gst_multi_fd_sink_client_queue_buffer (GstMultiFdSink * sink, + GstTCPClient * client, GstBuffer * buffer) +{ + GstCaps *caps; + + /* TRUE: send them if the new caps have them */ + gboolean send_streamheader = FALSE; + GstStructure *s; + + /* before we queue the buffer, we check if we need to queue streamheader + * buffers (because it's a new client, or because they changed) */ + caps = gst_buffer_get_caps (buffer); /* cleaned up after streamheader */ + if (!client->caps) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] no previous caps for this client, send streamheader", + client->fd.fd); + send_streamheader = TRUE; + client->caps = gst_caps_ref (caps); + } else { + /* there were previous caps recorded, so compare */ + if (!gst_caps_is_equal (caps, client->caps)) { + const GValue *sh1, *sh2; + + /* caps are not equal, but could still have the same streamheader */ + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_has_field (s, "streamheader")) { + /* no new streamheader, so nothing new to send */ + GST_DEBUG_OBJECT (sink, + "[fd %5d] new caps do not have streamheader, not sending", + client->fd.fd); + } else { + /* there is a new streamheader */ + s = gst_caps_get_structure (client->caps, 0); + if (!gst_structure_has_field (s, "streamheader")) { + /* no previous streamheader, so send the new one */ + GST_DEBUG_OBJECT (sink, + "[fd %5d] previous caps did not have streamheader, sending", + client->fd.fd); + send_streamheader = TRUE; + } else { + /* both old and new caps have streamheader set */ + if (!sink->resend_streamheader) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] asked to not resend the streamheader, not sending", + client->fd.fd); + send_streamheader = FALSE; + } else { + sh1 = gst_structure_get_value (s, "streamheader"); + s = gst_caps_get_structure (caps, 0); + sh2 = gst_structure_get_value (s, "streamheader"); + if (gst_value_compare (sh1, sh2) != GST_VALUE_EQUAL) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] new streamheader different from old, sending", + client->fd.fd); + send_streamheader = TRUE; + } + } + } + } + } + /* Replace the old caps */ + gst_caps_unref (client->caps); + client->caps = gst_caps_ref (caps); + } + + if (G_UNLIKELY (send_streamheader)) { + const GValue *sh; + GArray *buffers; + int i; + + GST_LOG_OBJECT (sink, + "[fd %5d] sending streamheader from caps %" GST_PTR_FORMAT, + client->fd.fd, caps); + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_has_field (s, "streamheader")) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] no new streamheader, so nothing to send", client->fd.fd); + } else { + GST_LOG_OBJECT (sink, + "[fd %5d] sending streamheader from caps %" GST_PTR_FORMAT, + client->fd.fd, caps); + sh = gst_structure_get_value (s, "streamheader"); + g_assert (G_VALUE_TYPE (sh) == GST_TYPE_ARRAY); + buffers = g_value_peek_pointer (sh); + GST_DEBUG_OBJECT (sink, "%d streamheader buffers", buffers->len); + for (i = 0; i < buffers->len; ++i) { + GValue *bufval; + GstBuffer *buffer; + + bufval = &g_array_index (buffers, GValue, i); + g_assert (G_VALUE_TYPE (bufval) == GST_TYPE_BUFFER); + buffer = g_value_peek_pointer (bufval); + GST_DEBUG_OBJECT (sink, + "[fd %5d] queueing streamheader buffer of length %d", + client->fd.fd, GST_BUFFER_SIZE (buffer)); + gst_buffer_ref (buffer); + + if (sink->protocol == GST_TCP_PROTOCOL_GDP) { + guint8 *header; + guint len; + + if (!gst_dp_header_from_buffer (buffer, sink->header_flags, &len, + &header)) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] could not create header, removing client", + client->fd.fd); + return FALSE; + } + gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header, + len); + } + + client->sending = g_slist_append (client->sending, buffer); + } + } + } + + gst_caps_unref (caps); + caps = NULL; + /* now we can send the buffer, possibly sending a GDP header first */ + if (sink->protocol == GST_TCP_PROTOCOL_GDP) { + guint8 *header; + guint len; + + if (!gst_dp_header_from_buffer (buffer, sink->header_flags, &len, &header)) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] could not create header, removing client", client->fd.fd); + return FALSE; + } + gst_multi_fd_sink_client_queue_data (sink, client, (gchar *) header, len); + } + + GST_LOG_OBJECT (sink, "[fd %5d] queueing buffer of length %d", + client->fd.fd, GST_BUFFER_SIZE (buffer)); + + gst_buffer_ref (buffer); + client->sending = g_slist_append (client->sending, buffer); + + return TRUE; +} + +/* find the keyframe in the list of buffers starting the + * search from @idx. @direction as -1 will search backwards, + * 1 will search forwards. + * Returns: the index or -1 if there is no keyframe after idx. + */ +static gint +find_syncframe (GstMultiFdSink * sink, gint idx, gint direction) +{ + gint i, len, result; + + /* take length of queued buffers */ + len = sink->bufqueue->len; + + /* assume we don't find a keyframe */ + result = -1; + + /* then loop over all buffers to find the first keyframe */ + for (i = idx; i >= 0 && i < len; i += direction) { + GstBuffer *buf; + + buf = g_array_index (sink->bufqueue, GstBuffer *, i); + if (is_sync_frame (sink, buf)) { + GST_LOG_OBJECT (sink, "found keyframe at %d from %d, direction %d", + i, idx, direction); + result = i; + break; + } + } + return result; +} + +#define find_next_syncframe(s,i) find_syncframe(s,i,1) +#define find_prev_syncframe(s,i) find_syncframe(s,i,-1) + +/* Get the number of buffers from the buffer queue needed to satisfy + * the maximum max in the configured units. + * If units are not BUFFERS, and there are insufficient buffers in the + * queue to satify the limit, return len(queue) + 1 */ +static gint +get_buffers_max (GstMultiFdSink * sink, gint64 max) +{ + switch (sink->unit_type) { + case GST_TCP_UNIT_TYPE_BUFFERS: + return max; + case GST_TCP_UNIT_TYPE_TIME: + { + GstBuffer *buf; + int i; + int len; + gint64 diff; + GstClockTime first = GST_CLOCK_TIME_NONE; + + len = sink->bufqueue->len; + + for (i = 0; i < len; i++) { + buf = g_array_index (sink->bufqueue, GstBuffer *, i); + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + if (first == -1) + first = GST_BUFFER_TIMESTAMP (buf); + + diff = first - GST_BUFFER_TIMESTAMP (buf); + + if (diff > max) + return i + 1; + } + } + return len + 1; + } + case GST_TCP_UNIT_TYPE_BYTES: + { + GstBuffer *buf; + int i; + int len; + gint acc = 0; + + len = sink->bufqueue->len; + + for (i = 0; i < len; i++) { + buf = g_array_index (sink->bufqueue, GstBuffer *, i); + acc += GST_BUFFER_SIZE (buf); + + if (acc > max) + return i + 1; + } + return len + 1; + } + default: + return max; + } +} + +/* find the positions in the buffer queue where *_min and *_max + * is satisfied + */ +/* count the amount of data in the buffers and return the index + * that satifies the given limits. + * + * Returns: index @idx in the buffer queue so that the given limits are + * satisfied. TRUE if all the limits could be satisfied, FALSE if not + * enough data was in the queue. + * + * FIXME, this code might now work if any of the units is in buffers... + */ +static gboolean +find_limits (GstMultiFdSink * sink, + gint * min_idx, gint bytes_min, gint buffers_min, gint64 time_min, + gint * max_idx, gint bytes_max, gint buffers_max, gint64 time_max) +{ + GstClockTime first, time; + gint i, len, bytes; + gboolean result, max_hit; + + /* take length of queue */ + len = sink->bufqueue->len; + + /* this must hold */ + g_assert (len > 0); + + GST_LOG_OBJECT (sink, + "bytes_min %d, buffers_min %d, time_min %" GST_TIME_FORMAT + ", bytes_max %d, buffers_max %d, time_max %" GST_TIME_FORMAT, bytes_min, + buffers_min, GST_TIME_ARGS (time_min), bytes_max, buffers_max, + GST_TIME_ARGS (time_max)); + + /* do the trivial buffer limit test */ + if (buffers_min != -1 && len < buffers_min) { + *min_idx = len - 1; + *max_idx = len - 1; + return FALSE; + } + + result = FALSE; + /* else count bytes and time */ + first = -1; + bytes = 0; + /* unset limits */ + *min_idx = -1; + *max_idx = -1; + max_hit = FALSE; + + i = 0; + /* loop through the buffers, when a limit is ok, mark it + * as -1, we have at least one buffer in the queue. */ + do { + GstBuffer *buf; + + /* if we checked all min limits, update result */ + if (bytes_min == -1 && time_min == -1 && *min_idx == -1) { + /* don't go below 0 */ + *min_idx = MAX (i - 1, 0); + } + /* if we reached one max limit break out */ + if (max_hit) { + /* i > 0 when we get here, we subtract one to get the position + * of the previous buffer. */ + *max_idx = i - 1; + /* we have valid complete result if we found a min_idx too */ + result = *min_idx != -1; + break; + } + buf = g_array_index (sink->bufqueue, GstBuffer *, i); + + bytes += GST_BUFFER_SIZE (buf); + + /* take timestamp and save for the base first timestamp */ + if ((time = GST_BUFFER_TIMESTAMP (buf)) != -1) { + GST_LOG_OBJECT (sink, "Ts %" GST_TIME_FORMAT " on buffer", + GST_TIME_ARGS (time)); + if (first == -1) + first = time; + + /* increase max usage if we did not fill enough. Note that + * buffers are sorted from new to old, so the first timestamp is + * bigger than the next one. */ + if (time_min != -1 && first - time >= time_min) + time_min = -1; + if (time_max != -1 && first - time >= time_max) + max_hit = TRUE; + } else { + GST_LOG_OBJECT (sink, "No timestamp on buffer"); + } + /* time is OK or unknown, check and increase if not enough bytes */ + if (bytes_min != -1) { + if (bytes >= bytes_min) + bytes_min = -1; + } + if (bytes_max != -1) { + if (bytes >= bytes_max) { + max_hit = TRUE; + } + } + i++; + } + while (i < len); + + /* if we did not hit the max or min limit, set to buffer size */ + if (*max_idx == -1) + *max_idx = len - 1; + /* make sure min does not exceed max */ + if (*min_idx == -1) + *min_idx = *max_idx; + + return result; +} + +/* parse the unit/value pair and assign it to the result value of the + * right type, leave the other values untouched + * + * Returns: FALSE if the unit is unknown or undefined. TRUE otherwise. + */ +static gboolean +assign_value (GstTCPUnitType unit, guint64 value, gint * bytes, gint * buffers, + GstClockTime * time) +{ + gboolean res = TRUE; + + /* set only the limit of the given format to the given value */ + switch (unit) { + case GST_TCP_UNIT_TYPE_BUFFERS: + *buffers = (gint) value; + break; + case GST_TCP_UNIT_TYPE_TIME: + *time = value; + break; + case GST_TCP_UNIT_TYPE_BYTES: + *bytes = (gint) value; + break; + case GST_TCP_UNIT_TYPE_UNDEFINED: + default: + res = FALSE; + break; + } + return res; +} + +/* count the index in the buffer queue to satisfy the given unit + * and value pair starting from buffer at index 0. + * + * Returns: TRUE if there was enough data in the queue to satisfy the + * burst values. @idx contains the index in the buffer that contains enough + * data to satisfy the limits or the last buffer in the queue when the + * function returns FALSE. + */ +static gboolean +count_burst_unit (GstMultiFdSink * sink, gint * min_idx, + GstTCPUnitType min_unit, guint64 min_value, gint * max_idx, + GstTCPUnitType max_unit, guint64 max_value) +{ + gint bytes_min = -1, buffers_min = -1; + gint bytes_max = -1, buffers_max = -1; + GstClockTime time_min = GST_CLOCK_TIME_NONE, time_max = GST_CLOCK_TIME_NONE; + + assign_value (min_unit, min_value, &bytes_min, &buffers_min, &time_min); + assign_value (max_unit, max_value, &bytes_max, &buffers_max, &time_max); + + return find_limits (sink, min_idx, bytes_min, buffers_min, time_min, + max_idx, bytes_max, buffers_max, time_max); +} + +/* decide where in the current buffer queue this new client should start + * receiving buffers from. + * This function is called whenever a client is connected and has not yet + * received a buffer. + * If this returns -1, it means that we haven't found a good point to + * start streaming from yet, and this function should be called again later + * when more buffers have arrived. + */ +static gint +gst_multi_fd_sink_new_client (GstMultiFdSink * sink, GstTCPClient * client) +{ + gint result; + + GST_DEBUG_OBJECT (sink, + "[fd %5d] new client, deciding where to start in queue", client->fd.fd); + GST_DEBUG_OBJECT (sink, "queue is currently %d buffers long", + sink->bufqueue->len); + switch (client->sync_method) { + case GST_SYNC_METHOD_LATEST: + /* no syncing, we are happy with whatever the client is going to get */ + result = client->bufpos; + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_LATEST, position %d", client->fd.fd, result); + break; + case GST_SYNC_METHOD_NEXT_KEYFRAME: + { + /* if one of the new buffers (between client->bufpos and 0) in the queue + * is a sync point, we can proceed, otherwise we need to keep waiting */ + GST_LOG_OBJECT (sink, + "[fd %5d] new client, bufpos %d, waiting for keyframe", client->fd.fd, + client->bufpos); + + result = find_prev_syncframe (sink, client->bufpos); + if (result != -1) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_NEXT_KEYFRAME: result %d", + client->fd.fd, result); + break; + } + + /* client is not on a syncbuffer, need to skip these buffers and + * wait some more */ + GST_LOG_OBJECT (sink, + "[fd %5d] new client, skipping buffer(s), no syncpoint found", + client->fd.fd); + client->bufpos = -1; + break; + } + case GST_SYNC_METHOD_LATEST_KEYFRAME: + { + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_LATEST_KEYFRAME", client->fd.fd); + + /* for new clients we initially scan the complete buffer queue for + * a sync point when a buffer is added. If we don't find a keyframe, + * we need to wait for the next keyframe and so we change the client's + * sync method to GST_SYNC_METHOD_NEXT_KEYFRAME. + */ + result = find_next_syncframe (sink, 0); + if (result != -1) { + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_LATEST_KEYFRAME: result %d", client->fd.fd, + result); + break; + } + + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_LATEST_KEYFRAME: no keyframe found, " + "switching to SYNC_METHOD_NEXT_KEYFRAME", client->fd.fd); + /* throw client to the waiting state */ + client->bufpos = -1; + /* and make client sync to next keyframe */ + client->sync_method = GST_SYNC_METHOD_NEXT_KEYFRAME; + break; + } + case GST_SYNC_METHOD_BURST: + { + gboolean ok; + gint max; + + /* move to the position where we satisfy the client's burst + * parameters. If we could not satisfy the parameters because there + * is not enough data, we just send what we have (which is in result). + * We use the max value to limit the search + */ + ok = count_burst_unit (sink, &result, client->burst_min_unit, + client->burst_min_value, &max, client->burst_max_unit, + client->burst_max_value); + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_BURST: burst_unit returned %d, result %d", + client->fd.fd, ok, result); + + GST_LOG_OBJECT (sink, "min %d, max %d", result, max); + + /* we hit the max and it is below the min, use that then */ + if (max != -1 && max <= result) { + result = MAX (max - 1, 0); + GST_DEBUG_OBJECT (sink, + "[fd %5d] SYNC_METHOD_BURST: result above max, taken down to %d", + client->fd.fd, result); + } + break; + } + case GST_SYNC_METHOD_BURST_KEYFRAME: + { + gint min_idx, max_idx; + gint next_syncframe, prev_syncframe; + + /* BURST_KEYFRAME: + * + * _always_ start sending a keyframe to the client. We first search + * a keyframe between min/max limits. If there is none, we send it the + * last keyframe before min. If there is none, the behaviour is like + * NEXT_KEYFRAME. + */ + /* gather burst limits */ + count_burst_unit (sink, &min_idx, client->burst_min_unit, + client->burst_min_value, &max_idx, client->burst_max_unit, + client->burst_max_value); + + GST_LOG_OBJECT (sink, "min %d, max %d", min_idx, max_idx); + + /* first find a keyframe after min_idx */ + next_syncframe = find_next_syncframe (sink, min_idx); + if (next_syncframe != -1 && next_syncframe < max_idx) { + /* we have a valid keyframe and it's below the max */ + GST_LOG_OBJECT (sink, "found keyframe in min/max limits"); + result = next_syncframe; + break; + } + + /* no valid keyframe, try to find one below min */ + prev_syncframe = find_prev_syncframe (sink, min_idx); + if (prev_syncframe != -1) { + GST_WARNING_OBJECT (sink, + "using keyframe below min in BURST_KEYFRAME sync mode"); + result = prev_syncframe; + break; + } + + /* no prev keyframe or not enough data */ + GST_WARNING_OBJECT (sink, + "no prev keyframe found in BURST_KEYFRAME sync mode, waiting for next"); + + /* throw client to the waiting state */ + client->bufpos = -1; + /* and make client sync to next keyframe */ + client->sync_method = GST_SYNC_METHOD_NEXT_KEYFRAME; + result = -1; + break; + } + case GST_SYNC_METHOD_BURST_WITH_KEYFRAME: + { + gint min_idx, max_idx; + gint next_syncframe; + + /* BURST_WITH_KEYFRAME: + * + * try to start sending a keyframe to the client. We first search + * a keyframe between min/max limits. If there is none, we send it the + * amount of data up 'till min. + */ + /* gather enough data to burst */ + count_burst_unit (sink, &min_idx, client->burst_min_unit, + client->burst_min_value, &max_idx, client->burst_max_unit, + client->burst_max_value); + + GST_LOG_OBJECT (sink, "min %d, max %d", min_idx, max_idx); + + /* first find a keyframe after min_idx */ + next_syncframe = find_next_syncframe (sink, min_idx); + if (next_syncframe != -1 && next_syncframe < max_idx) { + /* we have a valid keyframe and it's below the max */ + GST_LOG_OBJECT (sink, "found keyframe in min/max limits"); + result = next_syncframe; + break; + } + + /* no keyframe, send data from min_idx */ + GST_WARNING_OBJECT (sink, "using min in BURST_WITH_KEYFRAME sync mode"); + + /* make sure we don't go over the max limit */ + if (max_idx != -1 && max_idx <= min_idx) { + result = MAX (max_idx - 1, 0); + } else { + result = min_idx; + } + + break; + } + default: + g_warning ("unknown sync method %d", client->sync_method); + result = client->bufpos; + break; + } + return result; +} + +/* Handle a write on a client, + * which indicates a read request from a client. + * + * For each client we maintain a queue of GstBuffers that contain the raw bytes + * we need to send to the client. In the case of the GDP protocol, we create + * buffers out of the header bytes so that we can focus only on sending + * buffers. + * + * We first check to see if we need to send caps (in GDP) and streamheaders. + * If so, we queue them. + * + * Then we run into the main loop that tries to send as many buffers as + * possible. It will first exhaust the client->sending queue and if the queue + * is empty, it will pick a buffer from the global queue. + * + * Sending the buffers from the client->sending queue is basically writing + * the bytes to the socket and maintaining a count of the bytes that were + * sent. When the buffer is completely sent, it is removed from the + * client->sending queue and we try to pick a new buffer for sending. + * + * When the sending returns a partial buffer we stop sending more data as + * the next send operation could block. + * + * This functions returns FALSE if some error occured. + */ +static gboolean +gst_multi_fd_sink_handle_client_write (GstMultiFdSink * sink, + GstTCPClient * client) +{ + int fd = client->fd.fd; + gboolean more; + gboolean res; + gboolean flushing; + GstClockTime now; + GTimeVal nowtv; + + g_get_current_time (&nowtv); + now = GST_TIMEVAL_TO_TIME (nowtv); + + flushing = client->status == GST_CLIENT_STATUS_FLUSHING; + + /* when using GDP, first check if we have queued caps yet */ + if (sink->protocol == GST_TCP_PROTOCOL_GDP) { + /* don't need to do anything when the client is flushing */ + if (!client->caps_sent && !flushing) { + GstPad *peer; + GstCaps *caps; + + peer = gst_pad_get_peer (GST_BASE_SINK_PAD (sink)); + if (!peer) { + GST_WARNING_OBJECT (sink, "pad has no peer"); + return FALSE; + } + gst_object_unref (peer); + + caps = gst_pad_get_negotiated_caps (GST_BASE_SINK_PAD (sink)); + if (!caps) { + GST_WARNING_OBJECT (sink, "pad caps not yet negotiated"); + return FALSE; + } + + /* queue caps for sending */ + res = gst_multi_fd_sink_client_queue_caps (sink, client, caps); + + gst_caps_unref (caps); + + if (!res) { + GST_DEBUG_OBJECT (sink, "Failed queueing caps, removing client"); + return FALSE; + } + client->caps_sent = TRUE; + } + } + + more = TRUE; + do { + gint maxsize; + + if (!client->sending) { + /* client is not working on a buffer */ + if (client->bufpos == -1) { + /* client is too fast, remove from write queue until new buffer is + * available */ + gst_poll_fd_ctl_write (sink->fdset, &client->fd, FALSE); + /* if we flushed out all of the client buffers, we can stop */ + if (client->flushcount == 0) + goto flushed; + + return TRUE; + } else { + /* client can pick a buffer from the global queue */ + GstBuffer *buf; + GstClockTime timestamp; + + /* for new connections, we need to find a good spot in the + * bufqueue to start streaming from */ + if (client->new_connection && !flushing) { + gint position = gst_multi_fd_sink_new_client (sink, client); + + if (position >= 0) { + /* we got a valid spot in the queue */ + client->new_connection = FALSE; + client->bufpos = position; + } else { + /* cannot send data to this client yet */ + gst_poll_fd_ctl_write (sink->fdset, &client->fd, FALSE); + return TRUE; + } + } + + /* we flushed all remaining buffers, no need to get a new one */ + if (client->flushcount == 0) + goto flushed; + + /* grab buffer */ + buf = g_array_index (sink->bufqueue, GstBuffer *, client->bufpos); + client->bufpos--; + + /* update stats */ + timestamp = GST_BUFFER_TIMESTAMP (buf); + if (client->first_buffer_ts == GST_CLOCK_TIME_NONE) + client->first_buffer_ts = timestamp; + if (timestamp != -1) + client->last_buffer_ts = timestamp; + + /* decrease flushcount */ + if (client->flushcount != -1) + client->flushcount--; + + GST_LOG_OBJECT (sink, "[fd %5d] client %p at position %d", + fd, client, client->bufpos); + + /* queueing a buffer will ref it */ + gst_multi_fd_sink_client_queue_buffer (sink, client, buf); + + /* need to start from the first byte for this new buffer */ + client->bufoffset = 0; + } + } + + /* see if we need to send something */ + if (client->sending) { + ssize_t wrote; + GstBuffer *head; + + /* pick first buffer from list */ + head = GST_BUFFER (client->sending->data); + maxsize = GST_BUFFER_SIZE (head) - client->bufoffset; + + /* try to write the complete buffer */ +#ifdef MSG_NOSIGNAL +#define FLAGS MSG_NOSIGNAL +#else +#define FLAGS 0 +#endif + if (client->is_socket) { + wrote = + send (fd, GST_BUFFER_DATA (head) + client->bufoffset, maxsize, + FLAGS); + } else { + wrote = write (fd, GST_BUFFER_DATA (head) + client->bufoffset, maxsize); + } + + if (wrote < 0) { + /* hmm error.. */ + if (errno == EAGAIN) { + /* nothing serious, resource was unavailable, try again later */ + more = FALSE; + } else if (errno == ECONNRESET) { + goto connection_reset; + } else { + goto write_error; + } + } else { + if (wrote < maxsize) { + /* partial write means that the client cannot read more and we should + * stop sending more */ + GST_LOG_OBJECT (sink, + "partial write on %d of %" G_GSSIZE_FORMAT " bytes", fd, wrote); + client->bufoffset += wrote; + more = FALSE; + } else { + /* complete buffer was written, we can proceed to the next one */ + client->sending = g_slist_remove (client->sending, head); + gst_buffer_unref (head); + /* make sure we start from byte 0 for the next buffer */ + client->bufoffset = 0; + } + /* update stats */ + client->bytes_sent += wrote; + client->last_activity_time = now; + sink->bytes_served += wrote; + } + } + } while (more); + + return TRUE; + + /* ERRORS */ +flushed: + { + GST_DEBUG_OBJECT (sink, "[fd %5d] flushed, removing", fd); + client->status = GST_CLIENT_STATUS_REMOVED; + return FALSE; + } +connection_reset: + { + GST_DEBUG_OBJECT (sink, "[fd %5d] connection reset by peer, removing", fd); + client->status = GST_CLIENT_STATUS_CLOSED; + return FALSE; + } +write_error: + { + GST_WARNING_OBJECT (sink, + "[fd %5d] could not write, removing client: %s (%d)", fd, + g_strerror (errno), errno); + client->status = GST_CLIENT_STATUS_ERROR; + return FALSE; + } +} + +/* calculate the new position for a client after recovery. This function + * does not update the client position but merely returns the required + * position. + */ +static gint +gst_multi_fd_sink_recover_client (GstMultiFdSink * sink, GstTCPClient * client) +{ + gint newbufpos; + + GST_WARNING_OBJECT (sink, + "[fd %5d] client %p is lagging at %d, recover using policy %d", + client->fd.fd, client, client->bufpos, sink->recover_policy); + + switch (sink->recover_policy) { + case GST_RECOVER_POLICY_NONE: + /* do nothing, client will catch up or get kicked out when it reaches + * the hard max */ + newbufpos = client->bufpos; + break; + case GST_RECOVER_POLICY_RESYNC_LATEST: + /* move to beginning of queue */ + newbufpos = -1; + break; + case GST_RECOVER_POLICY_RESYNC_SOFT_LIMIT: + /* move to beginning of soft max */ + newbufpos = get_buffers_max (sink, sink->units_soft_max); + break; + case GST_RECOVER_POLICY_RESYNC_KEYFRAME: + /* find keyframe in buffers, we search backwards to find the + * closest keyframe relative to what this client already received. */ + newbufpos = MIN (sink->bufqueue->len - 1, + get_buffers_max (sink, sink->units_soft_max) - 1); + + while (newbufpos >= 0) { + GstBuffer *buf; + + buf = g_array_index (sink->bufqueue, GstBuffer *, newbufpos); + if (is_sync_frame (sink, buf)) { + /* found a buffer that is not a delta unit */ + break; + } + newbufpos--; + } + break; + default: + /* unknown recovery procedure */ + newbufpos = get_buffers_max (sink, sink->units_soft_max); + break; + } + return newbufpos; +} + +/* Queue a buffer on the global queue. + * + * This function adds the buffer to the front of a GArray. It removes the + * tail buffer if the max queue size is exceeded, unreffing the queued buffer. + * Note that unreffing the buffer is not a problem as clients who + * started writing out this buffer will still have a reference to it in the + * client->sending queue. + * + * After adding the buffer, we update all client positions in the queue. If + * a client moves over the soft max, we start the recovery procedure for this + * slow client. If it goes over the hard max, it is put into the slow list + * and removed. + * + * Special care is taken of clients that were waiting for a new buffer (they + * had a position of -1) because they can proceed after adding this new buffer. + * This is done by adding the client back into the write fd_set and signalling + * the select thread that the fd_set changed. + */ +static void +gst_multi_fd_sink_queue_buffer (GstMultiFdSink * sink, GstBuffer * buf) +{ + GList *clients, *next; + gint queuelen; + gboolean need_signal = FALSE; + gint max_buffer_usage; + gint i; + GTimeVal nowtv; + GstClockTime now; + gint max_buffers, soft_max_buffers; + guint cookie; + + g_get_current_time (&nowtv); + now = GST_TIMEVAL_TO_TIME (nowtv); + + CLIENTS_LOCK (sink); + /* add buffer to queue */ + g_array_prepend_val (sink->bufqueue, buf); + queuelen = sink->bufqueue->len; + + if (sink->units_max > 0) + max_buffers = get_buffers_max (sink, sink->units_max); + else + max_buffers = -1; + + if (sink->units_soft_max > 0) + soft_max_buffers = get_buffers_max (sink, sink->units_soft_max); + else + soft_max_buffers = -1; + GST_LOG_OBJECT (sink, "Using max %d, softmax %d", max_buffers, + soft_max_buffers); + + /* then loop over the clients and update the positions */ + max_buffer_usage = 0; + +restart: + cookie = sink->clients_cookie; + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + if (cookie != sink->clients_cookie) { + GST_DEBUG_OBJECT (sink, "Clients cookie outdated, restarting"); + goto restart; + } + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + client->bufpos++; + GST_LOG_OBJECT (sink, "[fd %5d] client %p at position %d", + client->fd.fd, client, client->bufpos); + /* check soft max if needed, recover client */ + if (soft_max_buffers > 0 && client->bufpos >= soft_max_buffers) { + gint newpos; + + newpos = gst_multi_fd_sink_recover_client (sink, client); + if (newpos != client->bufpos) { + client->dropped_buffers += client->bufpos - newpos; + client->bufpos = newpos; + client->discont = TRUE; + GST_INFO_OBJECT (sink, "[fd %5d] client %p position reset to %d", + client->fd.fd, client, client->bufpos); + } else { + GST_INFO_OBJECT (sink, + "[fd %5d] client %p not recovering position", + client->fd.fd, client); + } + } + /* check hard max and timeout, remove client */ + if ((max_buffers > 0 && client->bufpos >= max_buffers) || + (sink->timeout > 0 + && now - client->last_activity_time > sink->timeout)) { + /* remove client */ + GST_WARNING_OBJECT (sink, "[fd %5d] client %p is too slow, removing", + client->fd.fd, client); + /* remove the client, the fd set will be cleared and the select thread + * will be signaled */ + client->status = GST_CLIENT_STATUS_SLOW; + /* set client to invalid position while being removed */ + client->bufpos = -1; + gst_multi_fd_sink_remove_client_link (sink, clients); + need_signal = TRUE; + continue; + } else if (client->bufpos == 0 || client->new_connection) { + /* can send data to this client now. need to signal the select thread that + * the fd_set changed */ + gst_poll_fd_ctl_write (sink->fdset, &client->fd, TRUE); + need_signal = TRUE; + } + /* keep track of maximum buffer usage */ + if (client->bufpos > max_buffer_usage) { + max_buffer_usage = client->bufpos; + } + } + + /* make sure we respect bytes-min, buffers-min and time-min when they are set */ + { + gint usage, max; + + GST_LOG_OBJECT (sink, + "extending queue %d to respect time_min %" GST_TIME_FORMAT + ", bytes_min %d, buffers_min %d", max_buffer_usage, + GST_TIME_ARGS (sink->time_min), sink->bytes_min, sink->buffers_min); + + /* get index where the limits are ok, we don't really care if all limits + * are ok, we just queue as much as we need. We also don't compare against + * the max limits. */ + find_limits (sink, &usage, sink->bytes_min, sink->buffers_min, + sink->time_min, &max, -1, -1, -1); + + max_buffer_usage = MAX (max_buffer_usage, usage + 1); + GST_LOG_OBJECT (sink, "extended queue to %d", max_buffer_usage); + } + + /* now look for sync points and make sure there is at least one + * sync point in the queue. We only do this if the LATEST_KEYFRAME or + * BURST_KEYFRAME mode is selected */ + if (sink->def_sync_method == GST_SYNC_METHOD_LATEST_KEYFRAME || + sink->def_sync_method == GST_SYNC_METHOD_BURST_KEYFRAME) { + /* no point in searching beyond the queue length */ + gint limit = queuelen; + GstBuffer *buf; + + /* no point in searching beyond the soft-max if any. */ + if (soft_max_buffers > 0) { + limit = MIN (limit, soft_max_buffers); + } + GST_LOG_OBJECT (sink, + "extending queue to include sync point, now at %d, limit is %d", + max_buffer_usage, limit); + for (i = 0; i < limit; i++) { + buf = g_array_index (sink->bufqueue, GstBuffer *, i); + if (is_sync_frame (sink, buf)) { + /* found a sync frame, now extend the buffer usage to + * include at least this frame. */ + max_buffer_usage = MAX (max_buffer_usage, i); + break; + } + } + GST_LOG_OBJECT (sink, "max buffer usage is now %d", max_buffer_usage); + } + + GST_LOG_OBJECT (sink, "len %d, usage %d", queuelen, max_buffer_usage); + + /* nobody is referencing units after max_buffer_usage so we can + * remove them from the queue. We remove them in reverse order as + * this is the most optimal for GArray. */ + for (i = queuelen - 1; i > max_buffer_usage; i--) { + GstBuffer *old; + + /* queue exceeded max size */ + queuelen--; + old = g_array_index (sink->bufqueue, GstBuffer *, i); + sink->bufqueue = g_array_remove_index (sink->bufqueue, i); + + /* unref tail buffer */ + gst_buffer_unref (old); + } + /* save for stats */ + sink->buffers_queued = max_buffer_usage; + CLIENTS_UNLOCK (sink); + + /* and send a signal to thread if fd_set changed */ + if (need_signal) { + gst_poll_restart (sink->fdset); + } +} + +/* Handle the clients. Basically does a blocking select for one + * of the client fds to become read or writable. We also have a + * filedescriptor to receive commands on that we need to check. + * + * After going out of the select call, we read and write to all + * clients that can do so. Badly behaving clients are put on a + * garbage list and removed. + */ +static void +gst_multi_fd_sink_handle_clients (GstMultiFdSink * sink) +{ + int result; + GList *clients, *next; + gboolean try_again; + GstMultiFdSinkClass *fclass; + guint cookie; + + fclass = GST_MULTI_FD_SINK_GET_CLASS (sink); + + do { + try_again = FALSE; + + /* check for: + * - server socket input (ie, new client connections) + * - client socket input (ie, clients saying goodbye) + * - client socket output (ie, client reads) */ + GST_LOG_OBJECT (sink, "waiting on action on fdset"); + + result = gst_poll_wait (sink->fdset, sink->timeout != 0 ? sink->timeout : + GST_CLOCK_TIME_NONE); + + /* Handle the special case in which the sink is not receiving more buffers + * and will not disconnect innactive client in the streaming thread. */ + if (G_UNLIKELY (result == 0)) { + GstClockTime now; + GTimeVal nowtv; + + g_get_current_time (&nowtv); + now = GST_TIMEVAL_TO_TIME (nowtv); + + CLIENTS_LOCK (sink); + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + if (sink->timeout > 0 + && now - client->last_activity_time > sink->timeout) { + client->status = GST_CLIENT_STATUS_SLOW; + gst_multi_fd_sink_remove_client_link (sink, clients); + } + } + CLIENTS_UNLOCK (sink); + return; + } else if (result < 0) { + GST_WARNING_OBJECT (sink, "wait failed: %s (%d)", g_strerror (errno), + errno); + if (errno == EBADF) { + /* ok, so one or more of the fds is invalid. We loop over them to find + * the ones that give an error to the F_GETFL fcntl. */ + CLIENTS_LOCK (sink); + restart: + cookie = sink->clients_cookie; + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + int fd; + long flags; + int res; + + if (cookie != sink->clients_cookie) { + GST_DEBUG_OBJECT (sink, "Cookie changed finding bad fd"); + goto restart; + } + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + fd = client->fd.fd; + + res = fcntl (fd, F_GETFL, &flags); + if (res == -1) { + GST_WARNING_OBJECT (sink, "fnctl failed for %d, removing: %s (%d)", + fd, g_strerror (errno), errno); + if (errno == EBADF) { + client->status = GST_CLIENT_STATUS_ERROR; + /* releases the CLIENTS lock */ + gst_multi_fd_sink_remove_client_link (sink, clients); + } + } + } + CLIENTS_UNLOCK (sink); + /* after this, go back in the select loop as the read/writefds + * are not valid */ + try_again = TRUE; + } else if (errno == EINTR) { + /* interrupted system call, just redo the wait */ + try_again = TRUE; + } else if (errno == EBUSY) { + /* the call to gst_poll_wait() was flushed */ + return; + } else { + /* this is quite bad... */ + GST_ELEMENT_ERROR (sink, RESOURCE, READ, (NULL), + ("select failed: %s (%d)", g_strerror (errno), errno)); + return; + } + } else { + GST_LOG_OBJECT (sink, "wait done: %d sockets with events", result); + } + } while (try_again); + + /* subclasses can check fdset with this virtual function */ + if (fclass->wait) + fclass->wait (sink, sink->fdset); + + /* Check the clients */ + CLIENTS_LOCK (sink); + +restart2: + cookie = sink->clients_cookie; + for (clients = sink->clients; clients; clients = next) { + GstTCPClient *client; + + if (sink->clients_cookie != cookie) { + GST_DEBUG_OBJECT (sink, "Restarting loop, cookie out of date"); + goto restart2; + } + + client = (GstTCPClient *) clients->data; + next = g_list_next (clients); + + if (client->status != GST_CLIENT_STATUS_FLUSHING + && client->status != GST_CLIENT_STATUS_OK) { + gst_multi_fd_sink_remove_client_link (sink, clients); + continue; + } + + if (gst_poll_fd_has_closed (sink->fdset, &client->fd)) { + client->status = GST_CLIENT_STATUS_CLOSED; + gst_multi_fd_sink_remove_client_link (sink, clients); + continue; + } + if (gst_poll_fd_has_error (sink->fdset, &client->fd)) { + GST_WARNING_OBJECT (sink, "gst_poll_fd_has_error for %d", client->fd.fd); + client->status = GST_CLIENT_STATUS_ERROR; + gst_multi_fd_sink_remove_client_link (sink, clients); + continue; + } + if (gst_poll_fd_can_read (sink->fdset, &client->fd)) { + /* handle client read */ + if (!gst_multi_fd_sink_handle_client_read (sink, client)) { + gst_multi_fd_sink_remove_client_link (sink, clients); + continue; + } + } + if (gst_poll_fd_can_write (sink->fdset, &client->fd)) { + /* handle client write */ + if (!gst_multi_fd_sink_handle_client_write (sink, client)) { + gst_multi_fd_sink_remove_client_link (sink, clients); + continue; + } + } + } + CLIENTS_UNLOCK (sink); +} + +/* we handle the client communication in another thread so that we do not block + * the gstreamer thread while we select() on the client fds */ +static gpointer +gst_multi_fd_sink_thread (GstMultiFdSink * sink) +{ + while (sink->running) { + gst_multi_fd_sink_handle_clients (sink); + } + return NULL; +} + +static GstFlowReturn +gst_multi_fd_sink_render (GstBaseSink * bsink, GstBuffer * buf) +{ + GstMultiFdSink *sink; + gboolean in_caps; + GstCaps *bufcaps, *padcaps; + + sink = GST_MULTI_FD_SINK (bsink); + + g_return_val_if_fail (GST_OBJECT_FLAG_IS_SET (sink, GST_MULTI_FD_SINK_OPEN), + GST_FLOW_WRONG_STATE); + + /* since we check every buffer for streamheader caps, we need to make + * sure every buffer has caps set */ + bufcaps = gst_buffer_get_caps (buf); + padcaps = GST_PAD_CAPS (GST_BASE_SINK_PAD (bsink)); + + /* make sure we have caps on the pad */ + if (!padcaps && !bufcaps) + goto no_caps; + + /* get IN_CAPS first, code below might mess with the flags */ + in_caps = GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_IN_CAPS); + + /* stamp the buffer with previous caps if no caps set */ + if (!bufcaps) { + if (!gst_buffer_is_metadata_writable (buf)) { + /* metadata is not writable, copy will be made and original buffer + * will be unreffed so we need to ref so that we don't lose the + * buffer in the render method. */ + gst_buffer_ref (buf); + /* the new buffer is ours only, we keep it out of the scope of this + * function */ + buf = gst_buffer_make_metadata_writable (buf); + } else { + /* else the metadata is writable, we ref because we keep the buffer + * out of the scope of this method */ + gst_buffer_ref (buf); + } + /* buffer metadata is writable now, set the caps */ + gst_buffer_set_caps (buf, padcaps); + } else { + gst_caps_unref (bufcaps); + + /* since we keep this buffer out of the scope of this method */ + gst_buffer_ref (buf); + } + + GST_LOG_OBJECT (sink, "received buffer %p, in_caps: %s, offset %" + G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT + ", timestamp %" GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, + buf, in_caps ? "yes" : "no", GST_BUFFER_OFFSET (buf), + GST_BUFFER_OFFSET_END (buf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + + /* if we get IN_CAPS buffers, but the previous buffer was not IN_CAPS, + * it means we're getting new streamheader buffers, and we should clear + * the old ones */ + if (in_caps && sink->previous_buffer_in_caps == FALSE) { + GST_DEBUG_OBJECT (sink, + "receiving new IN_CAPS buffers, clearing old streamheader"); + g_slist_foreach (sink->streamheader, (GFunc) gst_mini_object_unref, NULL); + g_slist_free (sink->streamheader); + sink->streamheader = NULL; + } + + /* save the current in_caps */ + sink->previous_buffer_in_caps = in_caps; + + /* if the incoming buffer is marked as IN CAPS, then we assume for now + * it's a streamheader that needs to be sent to each new client, so we + * put it on our internal list of streamheader buffers. + * FIXME: we could check if the buffer's contents are in fact part of the + * current streamheader. + * + * We don't send the buffer to the client, since streamheaders are sent + * separately when necessary. */ + if (in_caps) { + GST_DEBUG_OBJECT (sink, + "appending IN_CAPS buffer with length %d to streamheader", + GST_BUFFER_SIZE (buf)); + sink->streamheader = g_slist_append (sink->streamheader, buf); + } else { + /* queue the buffer, this is a regular data buffer. */ + gst_multi_fd_sink_queue_buffer (sink, buf); + + sink->bytes_to_serve += GST_BUFFER_SIZE (buf); + } + return GST_FLOW_OK; + + /* ERRORS */ +no_caps: + { + GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL), + ("Received first buffer without caps set")); + return GST_FLOW_NOT_NEGOTIATED; + } +} + +static void +gst_multi_fd_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMultiFdSink *multifdsink; + + multifdsink = GST_MULTI_FD_SINK (object); + + switch (prop_id) { + case PROP_PROTOCOL: + multifdsink->protocol = g_value_get_enum (value); + break; + case PROP_MODE: + multifdsink->mode = g_value_get_enum (value); + break; + case PROP_BUFFERS_MAX: + multifdsink->units_max = g_value_get_int (value); + break; + case PROP_BUFFERS_SOFT_MAX: + multifdsink->units_soft_max = g_value_get_int (value); + break; + case PROP_TIME_MIN: + multifdsink->time_min = g_value_get_int64 (value); + break; + case PROP_BYTES_MIN: + multifdsink->bytes_min = g_value_get_int (value); + break; + case PROP_BUFFERS_MIN: + multifdsink->buffers_min = g_value_get_int (value); + break; + case PROP_UNIT_TYPE: + multifdsink->unit_type = g_value_get_enum (value); + break; + case PROP_UNITS_MAX: + multifdsink->units_max = g_value_get_int64 (value); + break; + case PROP_UNITS_SOFT_MAX: + multifdsink->units_soft_max = g_value_get_int64 (value); + break; + case PROP_RECOVER_POLICY: + multifdsink->recover_policy = g_value_get_enum (value); + break; + case PROP_TIMEOUT: + multifdsink->timeout = g_value_get_uint64 (value); + break; + case PROP_SYNC_METHOD: + multifdsink->def_sync_method = g_value_get_enum (value); + break; + case PROP_BURST_UNIT: + multifdsink->def_burst_unit = g_value_get_enum (value); + break; + case PROP_BURST_VALUE: + multifdsink->def_burst_value = g_value_get_uint64 (value); + break; + case PROP_QOS_DSCP: + multifdsink->qos_dscp = g_value_get_int (value); + setup_dscp (multifdsink); + break; + case PROP_HANDLE_READ: + multifdsink->handle_read = g_value_get_boolean (value); + break; + case PROP_RESEND_STREAMHEADER: + multifdsink->resend_streamheader = g_value_get_boolean (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_multi_fd_sink_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstMultiFdSink *multifdsink; + + multifdsink = GST_MULTI_FD_SINK (object); + + switch (prop_id) { + case PROP_PROTOCOL: + g_value_set_enum (value, multifdsink->protocol); + break; + case PROP_MODE: + g_value_set_enum (value, multifdsink->mode); + break; + case PROP_BUFFERS_MAX: + g_value_set_int (value, multifdsink->units_max); + break; + case PROP_BUFFERS_SOFT_MAX: + g_value_set_int (value, multifdsink->units_soft_max); + break; + case PROP_TIME_MIN: + g_value_set_int64 (value, multifdsink->time_min); + break; + case PROP_BYTES_MIN: + g_value_set_int (value, multifdsink->bytes_min); + break; + case PROP_BUFFERS_MIN: + g_value_set_int (value, multifdsink->buffers_min); + break; + case PROP_BUFFERS_QUEUED: + g_value_set_uint (value, multifdsink->buffers_queued); + break; + case PROP_BYTES_QUEUED: + g_value_set_uint (value, multifdsink->bytes_queued); + break; + case PROP_TIME_QUEUED: + g_value_set_uint64 (value, multifdsink->time_queued); + break; + case PROP_UNIT_TYPE: + g_value_set_enum (value, multifdsink->unit_type); + break; + case PROP_UNITS_MAX: + g_value_set_int64 (value, multifdsink->units_max); + break; + case PROP_UNITS_SOFT_MAX: + g_value_set_int64 (value, multifdsink->units_soft_max); + break; + case PROP_RECOVER_POLICY: + g_value_set_enum (value, multifdsink->recover_policy); + break; + case PROP_TIMEOUT: + g_value_set_uint64 (value, multifdsink->timeout); + break; + case PROP_SYNC_METHOD: + g_value_set_enum (value, multifdsink->def_sync_method); + break; + case PROP_BYTES_TO_SERVE: + g_value_set_uint64 (value, multifdsink->bytes_to_serve); + break; + case PROP_BYTES_SERVED: + g_value_set_uint64 (value, multifdsink->bytes_served); + break; + case PROP_BURST_UNIT: + g_value_set_enum (value, multifdsink->def_burst_unit); + break; + case PROP_BURST_VALUE: + g_value_set_uint64 (value, multifdsink->def_burst_value); + break; + case PROP_QOS_DSCP: + g_value_set_int (value, multifdsink->qos_dscp); + break; + case PROP_HANDLE_READ: + g_value_set_boolean (value, multifdsink->handle_read); + break; + case PROP_RESEND_STREAMHEADER: + g_value_set_boolean (value, multifdsink->resend_streamheader); + break; + case PROP_NUM_FDS: + g_value_set_uint (value, g_hash_table_size (multifdsink->fd_hash)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/* create a socket for sending to remote machine */ +static gboolean +gst_multi_fd_sink_start (GstBaseSink * bsink) +{ + GstMultiFdSinkClass *fclass; + GstMultiFdSink *this; + + if (GST_OBJECT_FLAG_IS_SET (bsink, GST_MULTI_FD_SINK_OPEN)) + return TRUE; + + this = GST_MULTI_FD_SINK (bsink); + fclass = GST_MULTI_FD_SINK_GET_CLASS (this); + + GST_INFO_OBJECT (this, "starting in mode %d", this->mode); + if ((this->fdset = gst_poll_new (TRUE)) == NULL) + goto socket_pair; + + this->streamheader = NULL; + this->bytes_to_serve = 0; + this->bytes_served = 0; + + if (fclass->init) { + fclass->init (this); + } + + this->running = TRUE; + this->thread = g_thread_create ((GThreadFunc) gst_multi_fd_sink_thread, + this, TRUE, NULL); + + GST_OBJECT_FLAG_SET (this, GST_MULTI_FD_SINK_OPEN); + + return TRUE; + + /* ERRORS */ +socket_pair: + { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ_WRITE, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } +} + +static gboolean +multifdsink_hash_remove (gpointer key, gpointer value, gpointer data) +{ + return TRUE; +} + +static gboolean +gst_multi_fd_sink_stop (GstBaseSink * bsink) +{ + GstMultiFdSinkClass *fclass; + GstMultiFdSink *this; + GstBuffer *buf; + int i; + + this = GST_MULTI_FD_SINK (bsink); + fclass = GST_MULTI_FD_SINK_GET_CLASS (this); + + if (!GST_OBJECT_FLAG_IS_SET (bsink, GST_MULTI_FD_SINK_OPEN)) + return TRUE; + + this->running = FALSE; + + gst_poll_set_flushing (this->fdset, TRUE); + if (this->thread) { + GST_DEBUG_OBJECT (this, "joining thread"); + g_thread_join (this->thread); + GST_DEBUG_OBJECT (this, "joined thread"); + this->thread = NULL; + } + + /* free the clients */ + gst_multi_fd_sink_clear (this); + + if (this->streamheader) { + g_slist_foreach (this->streamheader, (GFunc) gst_mini_object_unref, NULL); + g_slist_free (this->streamheader); + this->streamheader = NULL; + } + + if (fclass->close) + fclass->close (this); + + if (this->fdset) { + gst_poll_free (this->fdset); + this->fdset = NULL; + } + g_hash_table_foreach_remove (this->fd_hash, multifdsink_hash_remove, this); + + /* remove all queued buffers */ + if (this->bufqueue) { + GST_DEBUG_OBJECT (this, "Emptying bufqueue with %d buffers", + this->bufqueue->len); + for (i = this->bufqueue->len - 1; i >= 0; --i) { + buf = g_array_index (this->bufqueue, GstBuffer *, i); + GST_LOG_OBJECT (this, "Removing buffer %p (%d) with refcount %d", buf, i, + GST_MINI_OBJECT_REFCOUNT (buf)); + gst_buffer_unref (buf); + this->bufqueue = g_array_remove_index (this->bufqueue, i); + } + /* freeing the array is done in _finalize */ + } + GST_OBJECT_FLAG_UNSET (this, GST_MULTI_FD_SINK_OPEN); + + return TRUE; +} + +static GstStateChangeReturn +gst_multi_fd_sink_change_state (GstElement * element, GstStateChange transition) +{ + GstMultiFdSink *sink; + GstStateChangeReturn ret; + + sink = GST_MULTI_FD_SINK (element); + + /* we disallow changing the state from the streaming thread */ + if (g_thread_self () == sink->thread) + return GST_STATE_CHANGE_FAILURE; + + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_multi_fd_sink_start (GST_BASE_SINK (sink))) + goto start_failed; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_multi_fd_sink_stop (GST_BASE_SINK (sink)); + break; + default: + break; + } + return ret; + + /* ERRORS */ +start_failed: + { + /* error message was posted */ + return GST_STATE_CHANGE_FAILURE; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.h b/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.h new file mode 100644 index 0000000..0ee7888 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gstmultifdsink.h @@ -0,0 +1,288 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_MULTI_FD_SINK_H__ +#define __GST_MULTI_FD_SINK_H__ + +#include +#include + +G_BEGIN_DECLS + +#include "gsttcp.h" + +#define GST_TYPE_MULTI_FD_SINK \ + (gst_multi_fd_sink_get_type()) +#define GST_MULTI_FD_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MULTI_FD_SINK,GstMultiFdSink)) +#define GST_MULTI_FD_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MULTI_FD_SINK,GstMultiFdSinkClass)) +#define GST_IS_MULTI_FD_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MULTI_FD_SINK)) +#define GST_IS_MULTI_FD_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MULTI_FD_SINK)) +#define GST_MULTI_FD_SINK_GET_CLASS(klass) \ + (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_MULTI_FD_SINK, GstMultiFdSinkClass)) + + +typedef struct _GstMultiFdSink GstMultiFdSink; +typedef struct _GstMultiFdSinkClass GstMultiFdSinkClass; + +typedef enum { + GST_MULTI_FD_SINK_OPEN = (GST_ELEMENT_FLAG_LAST << 0), + + GST_MULTI_FD_SINK_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2) +} GstMultiFdSinkFlags; + +/** + * GstRecoverPolicy: + * @GST_RECOVER_POLICY_NONE : no recovering is done + * @GST_RECOVER_POLICY_RESYNC_LATEST : client is moved to last buffer + * @GST_RECOVER_POLICY_RESYNC_SOFT_LIMIT: client is moved to the soft limit + * @GST_RECOVER_POLICY_RESYNC_KEYFRAME : client is moved to latest keyframe + * + * Possible values for the recovery procedure to use when a client consumes + * data too slow and has a backlag of more that soft-limit buffers. + */ +typedef enum +{ + GST_RECOVER_POLICY_NONE, + GST_RECOVER_POLICY_RESYNC_LATEST, + GST_RECOVER_POLICY_RESYNC_SOFT_LIMIT, + GST_RECOVER_POLICY_RESYNC_KEYFRAME +} GstRecoverPolicy; + +/** + * GstSyncMethod: + * @GST_SYNC_METHOD_LATEST : client receives most recent buffer + * @GST_SYNC_METHOD_NEXT_KEYFRAME : client receives next keyframe + * @GST_SYNC_METHOD_LATEST_KEYFRAME : client receives latest keyframe (burst) + * @GST_SYNC_METHOD_BURST : client receives specific amount of data + * @GST_SYNC_METHOD_BURST_KEYFRAME : client receives specific amount of data + * starting from latest keyframe + * @GST_SYNC_METHOD_BURST_WITH_KEYFRAME : client receives specific amount of data from + * a keyframe, or if there is not enough data after + * the keyframe, starting before the keyframe + * + * This enum defines the selection of the first buffer that is sent + * to a new client. + */ +typedef enum +{ + GST_SYNC_METHOD_LATEST, + GST_SYNC_METHOD_NEXT_KEYFRAME, + GST_SYNC_METHOD_LATEST_KEYFRAME, + GST_SYNC_METHOD_BURST, + GST_SYNC_METHOD_BURST_KEYFRAME, + GST_SYNC_METHOD_BURST_WITH_KEYFRAME +} GstSyncMethod; + +/** + * GstTCPUnitType: + * @GST_TCP_UNIT_TYPE_UNDEFINED: undefined + * @GST_TCP_UNIT_TYPE_BUFFERS : buffers + * @GST_TCP_UNIT_TYPE_TIME : timeunits (in nanoseconds) + * @GST_TCP_UNIT_TYPE_BYTES : bytes + * + * The units used to specify limits. + */ +typedef enum +{ + GST_TCP_UNIT_TYPE_UNDEFINED, + GST_TCP_UNIT_TYPE_BUFFERS, + GST_TCP_UNIT_TYPE_TIME, + GST_TCP_UNIT_TYPE_BYTES +} GstTCPUnitType; + +/** + * GstClientStatus: + * @GST_CLIENT_STATUS_OK : client is ok + * @GST_CLIENT_STATUS_CLOSED : client closed the socket + * @GST_CLIENT_STATUS_REMOVED : client is removed + * @GST_CLIENT_STATUS_SLOW : client is too slow + * @GST_CLIENT_STATUS_ERROR : client is in error + * @GST_CLIENT_STATUS_DUPLICATE: same client added twice + * @GST_CLIENT_STATUS_FLUSHING : client is flushing out the remaining buffers. + * + * This specifies the reason why a client was removed from + * multifdsink and is received in the "client-removed" signal. + */ +typedef enum +{ + GST_CLIENT_STATUS_OK = 0, + GST_CLIENT_STATUS_CLOSED = 1, + GST_CLIENT_STATUS_REMOVED = 2, + GST_CLIENT_STATUS_SLOW = 3, + GST_CLIENT_STATUS_ERROR = 4, + GST_CLIENT_STATUS_DUPLICATE = 5, + GST_CLIENT_STATUS_FLUSHING = 6 +} GstClientStatus; + +/* structure for a client + */ +typedef struct { + GstPollFD fd; + + gint bufpos; /* position of this client in the global queue */ + gint flushcount; /* the remaining number of buffers to flush out or -1 if the + client is not flushing. */ + + GstClientStatus status; + gboolean is_socket; + + GSList *sending; /* the buffers we need to send */ + gint bufoffset; /* offset in the first buffer */ + + gboolean discont; + + GstTCPProtocol protocol; + + gboolean caps_sent; + gboolean new_connection; + + gboolean currently_removing; + + /* method to sync client when connecting */ + GstSyncMethod sync_method; + GstTCPUnitType burst_min_unit; + guint64 burst_min_value; + GstTCPUnitType burst_max_unit; + guint64 burst_max_value; + + GstCaps *caps; /* caps of last queued buffer */ + + /* stats */ + guint64 bytes_sent; + guint64 connect_time; + guint64 disconnect_time; + guint64 last_activity_time; + guint64 dropped_buffers; + guint64 avg_queue_size; + guint64 first_buffer_ts; + guint64 last_buffer_ts; +} GstTCPClient; + +#define CLIENTS_LOCK_INIT(fdsink) (g_static_rec_mutex_init(&fdsink->clientslock)) +#define CLIENTS_LOCK_FREE(fdsink) (g_static_rec_mutex_free(&fdsink->clientslock)) +#define CLIENTS_LOCK(fdsink) (g_static_rec_mutex_lock(&fdsink->clientslock)) +#define CLIENTS_UNLOCK(fdsink) (g_static_rec_mutex_unlock(&fdsink->clientslock)) + +/** + * GstMultiFdSink: + * + * The multifdsink object structure. + */ +struct _GstMultiFdSink { + GstBaseSink element; + + /*< private >*/ + guint64 bytes_to_serve; /* how much bytes we must serve */ + guint64 bytes_served; /* how much bytes have we served */ + + GStaticRecMutex clientslock; /* lock to protect the clients list */ + GList *clients; /* list of clients we are serving */ + GHashTable *fd_hash; /* index on fd to client */ + guint clients_cookie; /* Cookie to detect changes to the clients list */ + + gint mode; + GstPoll *fdset; + + GSList *streamheader; /* GSList of GstBuffers to use as streamheader */ + gboolean previous_buffer_in_caps; + + GstTCPProtocol protocol; + guint mtu; + gint qos_dscp; + gboolean handle_read; + + GArray *bufqueue; /* global queue of buffers */ + + gboolean running; /* the thread state */ + GThread *thread; /* the sender thread */ + + /* these values are used to check if a client is reading fast + * enough and to control receovery */ + GstTCPUnitType unit_type;/* the type of the units */ + gint64 units_max; /* max units to queue for a client */ + gint64 units_soft_max; /* max units a client can lag before recovery starts */ + GstRecoverPolicy recover_policy; + GstClockTime timeout; /* max amount of nanoseconds to remain idle */ + + GstSyncMethod def_sync_method; /* what method to use for connecting clients */ + GstTCPUnitType def_burst_unit; + guint64 def_burst_value; + + /* these values are used to control the amount of data + * kept in the queues. It allows clients to perform a burst + * on connect. */ + gint bytes_min; /* min number of bytes to queue */ + gint64 time_min; /* min time to queue */ + gint buffers_min; /* min number of buffers to queue */ + + gboolean resend_streamheader; /* resend streamheader if it changes */ + + /* stats */ + gint buffers_queued; /* number of queued buffers */ + gint bytes_queued; /* number of queued bytes */ + gint time_queued; /* number of queued time */ + + guint8 header_flags; +}; + +struct _GstMultiFdSinkClass { + GstBaseSinkClass parent_class; + + /* element methods */ + void (*add) (GstMultiFdSink *sink, int fd); + void (*add_full) (GstMultiFdSink *sink, int fd, GstSyncMethod sync, + GstTCPUnitType format, guint64 value, + GstTCPUnitType max_unit, guint64 max_value); + void (*remove) (GstMultiFdSink *sink, int fd); + void (*remove_flush) (GstMultiFdSink *sink, int fd); + void (*clear) (GstMultiFdSink *sink); + GValueArray* (*get_stats) (GstMultiFdSink *sink, int fd); + + /* vtable */ + gboolean (*init) (GstMultiFdSink *sink); + gboolean (*wait) (GstMultiFdSink *sink, GstPoll *set); + gboolean (*close) (GstMultiFdSink *sink); + void (*removed) (GstMultiFdSink *sink, int fd); + + /* signals */ + void (*client_added) (GstElement *element, gint fd); + void (*client_removed) (GstElement *element, gint fd, GstClientStatus status); + void (*client_fd_removed) (GstElement *element, gint fd); +}; + +GType gst_multi_fd_sink_get_type (void); + +void gst_multi_fd_sink_add (GstMultiFdSink *sink, int fd); +void gst_multi_fd_sink_add_full (GstMultiFdSink *sink, int fd, GstSyncMethod sync, + GstTCPUnitType min_unit, guint64 min_value, + GstTCPUnitType max_unit, guint64 max_value); +void gst_multi_fd_sink_remove (GstMultiFdSink *sink, int fd); +void gst_multi_fd_sink_remove_flush (GstMultiFdSink *sink, int fd); +void gst_multi_fd_sink_clear (GstMultiFdSink *sink); +GValueArray* gst_multi_fd_sink_get_stats (GstMultiFdSink *sink, int fd); + +G_END_DECLS + +#endif /* __GST_MULTI_FD_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp-marshal.list b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp-marshal.list new file mode 100644 index 0000000..0d7208e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp-marshal.list @@ -0,0 +1,5 @@ +VOID:STRING,UINT +VOID:INT +VOID:INT,BOXED +VOID:INT,ENUM,INT,UINT64,INT,UINT64 +BOXED:INT diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.c new file mode 100644 index 0000000..894fcb8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.c @@ -0,0 +1,569 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * gsttcp.c: TCP functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_FIONREAD_IN_SYS_FILIO +#include +#endif + +#include "gsttcp.h" +#include + +GST_DEBUG_CATEGORY_EXTERN (tcp_debug); +#define GST_CAT_DEFAULT tcp_debug + +#ifndef MSG_NOSIGNAL +#define MSG_NOSIGNAL 0 +#endif + +/* resolve host to IP address, throwing errors if it fails */ +/* host can already be an IP address */ +/* returns a newly allocated gchar * with the dotted ip address, + or NULL, in which case it already fired an error. */ +gchar * +gst_tcp_host_to_ip (GstElement * element, const gchar * host) +{ + struct hostent *hostinfo; + char **addrs; + gchar *ip; + struct in_addr addr; + + GST_DEBUG_OBJECT (element, "resolving host %s", host); + + /* first check if it already is an IP address */ + if (inet_aton (host, &addr)) { + ip = g_strdup (host); + goto beach; + } + /* FIXME: could do a localhost check here */ + + /* perform a name lookup */ + if (!(hostinfo = gethostbyname (host))) + goto resolve_error; + + if (hostinfo->h_addrtype != AF_INET) + goto not_ip; + + addrs = hostinfo->h_addr_list; + + /* There could be more than one IP address, but we just return the first */ + ip = g_strdup (inet_ntoa (*(struct in_addr *) *addrs)); + +beach: + GST_DEBUG_OBJECT (element, "resolved to IP %s", ip); + return ip; + +resolve_error: + { + GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL), + ("Could not find IP address for host \"%s\".", host)); + return NULL; + } +not_ip: + { + GST_ELEMENT_ERROR (element, RESOURCE, NOT_FOUND, (NULL), + ("host \"%s\" is not an IP host", host)); + return NULL; + } +} + +/* write buffer to given socket incrementally. + * Returns number of bytes written. + */ +gint +gst_tcp_socket_write (int socket, const void *buf, size_t count) +{ + size_t bytes_written = 0; + + while (bytes_written < count) { + ssize_t wrote = send (socket, (const char *) buf + bytes_written, + count - bytes_written, MSG_NOSIGNAL); + + if (wrote <= 0) { + GST_WARNING ("error while writing"); + return bytes_written; + } + bytes_written += wrote; + } + + GST_LOG ("wrote %" G_GSIZE_FORMAT " bytes succesfully", bytes_written); + return bytes_written; +} + +/* atomically read count bytes into buf, cancellable. return val of GST_FLOW_OK + * indicates success, anything else is failure. + */ +static GstFlowReturn +gst_tcp_socket_read (GstElement * this, int socket, void *buf, size_t count, + GstPoll * fdset) +{ + ssize_t n; + size_t bytes_read; + int num_to_read; + int ret; + + bytes_read = 0; + + while (bytes_read < count) { + /* do a blocking select on the socket */ + /* no action (0) is an error too in our case */ + if ((ret = gst_poll_wait (fdset, GST_CLOCK_TIME_NONE)) <= 0) { + if (ret == -1 && errno == EBUSY) + goto cancelled; + else + goto select_error; + } + + /* ask how much is available for reading on the socket */ + if (ioctl (socket, FIONREAD, &num_to_read) < 0) + goto ioctl_error; + + if (num_to_read == 0) + goto got_eos; + + /* sizeof(ssize_t) >= sizeof(int), so I know num_to_read <= SSIZE_MAX */ + + num_to_read = MIN (num_to_read, count - bytes_read); + + n = read (socket, ((guint8 *) buf) + bytes_read, num_to_read); + + if (n < 0) + goto read_error; + + if (n < num_to_read) + goto short_read; + + bytes_read += num_to_read; + } + + return GST_FLOW_OK; + + /* ERRORS */ +select_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("select failed: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +cancelled: + { + GST_DEBUG_OBJECT (this, "Select was cancelled"); + return GST_FLOW_WRONG_STATE; + } +ioctl_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("ioctl failed: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +got_eos: + { + GST_DEBUG_OBJECT (this, "Got EOS on socket stream"); + return GST_FLOW_UNEXPECTED; + } +read_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("read failed: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +short_read: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("short read: wanted %d bytes, got %" G_GSSIZE_FORMAT, num_to_read, n)); + return GST_FLOW_ERROR; + } +} + +/* close the socket and reset the fd. Used to clean up after errors. */ +void +gst_tcp_socket_close (GstPollFD * socket) +{ + if (socket->fd >= 0) { + close (socket->fd); + socket->fd = -1; + } +} + +/* read a buffer from the given socket + * returns: + * - a GstBuffer in which data should be read + * - NULL, indicating a connection close or an error, to be handled with + * EOS + */ +GstFlowReturn +gst_tcp_read_buffer (GstElement * this, int socket, GstPoll * fdset, + GstBuffer ** buf) +{ + int ret; + ssize_t bytes_read; + int readsize; + + *buf = NULL; + + /* do a blocking select on the socket */ + /* no action (0) is an error too in our case */ + if ((ret = gst_poll_wait (fdset, GST_CLOCK_TIME_NONE)) <= 0) { + if (ret == -1 && errno == EBUSY) + goto cancelled; + else + goto select_error; + } + + /* ask how much is available for reading on the socket */ + if (ioctl (socket, FIONREAD, &readsize) < 0) + goto ioctl_error; + + if (readsize == 0) + goto got_eos; + + /* sizeof(ssize_t) >= sizeof(int), so I know readsize <= SSIZE_MAX */ + + *buf = gst_buffer_new_and_alloc (readsize); + + bytes_read = read (socket, GST_BUFFER_DATA (*buf), readsize); + + if (bytes_read < 0) + goto read_error; + + if (bytes_read < readsize) + /* but mom, you promised to give me readsize bytes! */ + goto short_read; + + GST_LOG_OBJECT (this, "returning buffer of size %d", GST_BUFFER_SIZE (*buf)); + return GST_FLOW_OK; + + /* ERRORS */ +select_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("select failed: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +cancelled: + { + GST_DEBUG_OBJECT (this, "Select was cancelled"); + return GST_FLOW_WRONG_STATE; + } +ioctl_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("ioctl failed: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +got_eos: + { + GST_DEBUG_OBJECT (this, "Got EOS on socket stream"); + return GST_FLOW_UNEXPECTED; + } +read_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("read failed: %s", g_strerror (errno))); + gst_buffer_unref (*buf); + *buf = NULL; + return GST_FLOW_ERROR; + } +short_read: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("short read: wanted %d bytes, got %" G_GSSIZE_FORMAT, readsize, + bytes_read)); + gst_buffer_unref (*buf); + *buf = NULL; + return GST_FLOW_ERROR; + } +} + +/* read a buffer from the given socket + * returns: + * - a GstBuffer in which data should be read + * - NULL, indicating a connection close or an error, to be handled with + * EOS + */ +GstFlowReturn +gst_tcp_gdp_read_buffer (GstElement * this, int socket, GstPoll * fdset, + GstBuffer ** buf) +{ + GstFlowReturn ret; + guint8 *header = NULL; + + GST_LOG_OBJECT (this, "Reading %d bytes for buffer packet header", + GST_DP_HEADER_LENGTH); + + *buf = NULL; + header = g_malloc (GST_DP_HEADER_LENGTH); + + ret = gst_tcp_socket_read (this, socket, header, GST_DP_HEADER_LENGTH, fdset); + + if (ret != GST_FLOW_OK) + goto header_read_error; + + if (!gst_dp_validate_header (GST_DP_HEADER_LENGTH, header)) + goto validate_error; + + if (gst_dp_header_payload_type (header) != GST_DP_PAYLOAD_BUFFER) + goto is_not_buffer; + + GST_LOG_OBJECT (this, "validated buffer packet header"); + + *buf = gst_dp_buffer_from_header (GST_DP_HEADER_LENGTH, header); + + g_free (header); + + ret = gst_tcp_socket_read (this, socket, GST_BUFFER_DATA (*buf), + GST_BUFFER_SIZE (*buf), fdset); + + if (ret != GST_FLOW_OK) + goto data_read_error; + + return GST_FLOW_OK; + + /* ERRORS */ +header_read_error: + { + g_free (header); + return ret; + } +validate_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("GDP buffer packet header does not validate")); + g_free (header); + return GST_FLOW_ERROR; + } +is_not_buffer: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("GDP packet contains something that is not a buffer (type %d)", + gst_dp_header_payload_type (header))); + g_free (header); + return GST_FLOW_ERROR; + } +data_read_error: + { + gst_buffer_unref (*buf); + *buf = NULL; + return ret; + } +} + +GstFlowReturn +gst_tcp_gdp_read_caps (GstElement * this, int socket, GstPoll * fdset, + GstCaps ** caps) +{ + GstFlowReturn ret; + guint8 *header = NULL; + guint8 *payload = NULL; + size_t payload_length; + + GST_LOG_OBJECT (this, "Reading %d bytes for caps packet header", + GST_DP_HEADER_LENGTH); + + *caps = NULL; + header = g_malloc (GST_DP_HEADER_LENGTH); + + ret = gst_tcp_socket_read (this, socket, header, GST_DP_HEADER_LENGTH, fdset); + + if (ret != GST_FLOW_OK) + goto header_read_error; + + if (!gst_dp_validate_header (GST_DP_HEADER_LENGTH, header)) + goto header_validate_error; + + if (gst_dp_header_payload_type (header) != GST_DP_PAYLOAD_CAPS) + goto is_not_caps; + + GST_LOG_OBJECT (this, "validated caps packet header"); + + payload_length = gst_dp_header_payload_length (header); + payload = g_malloc (payload_length); + + GST_LOG_OBJECT (this, + "Reading %" G_GSIZE_FORMAT " bytes for caps packet payload", + payload_length); + + ret = gst_tcp_socket_read (this, socket, payload, payload_length, fdset); + + if (ret != GST_FLOW_OK) + goto payload_read_error; + + if (!gst_dp_validate_payload (GST_DP_HEADER_LENGTH, header, payload)) + goto payload_validate_error; + + *caps = gst_dp_caps_from_packet (GST_DP_HEADER_LENGTH, header, payload); + + GST_DEBUG_OBJECT (this, "Got caps over GDP: %" GST_PTR_FORMAT, *caps); + + g_free (header); + g_free (payload); + + return GST_FLOW_OK; + + /* ERRORS */ +header_read_error: + { + g_free (header); + return ret; + } +header_validate_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("GDP caps packet header does not validate")); + g_free (header); + return GST_FLOW_ERROR; + } +is_not_caps: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("GDP packet contains something that is not a caps (type %d)", + gst_dp_header_payload_type (header))); + g_free (header); + return GST_FLOW_ERROR; + } +payload_read_error: + { + g_free (header); + g_free (payload); + return ret; + } +payload_validate_error: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("GDP caps packet payload does not validate")); + g_free (header); + g_free (payload); + return GST_FLOW_ERROR; + } +} + +/* write a GDP header to the socket. Return false if fails. */ +gboolean +gst_tcp_gdp_write_buffer (GstElement * this, int socket, GstBuffer * buffer, + gboolean fatal, const gchar * host, int port) +{ + guint length; + guint8 *header; + size_t wrote; + + if (!gst_dp_header_from_buffer (buffer, 0, &length, &header)) + goto create_error; + + GST_LOG_OBJECT (this, "writing %d bytes for GDP buffer header", length); + wrote = gst_tcp_socket_write (socket, header, length); + g_free (header); + + if (wrote != length) + goto write_error; + + return TRUE; + + /* ERRORS */ +create_error: + { + if (fatal) + GST_ELEMENT_ERROR (this, CORE, TOO_LAZY, (NULL), + ("Could not create GDP header from buffer")); + return FALSE; + } +write_error: + { + if (fatal) + GST_ELEMENT_ERROR (this, RESOURCE, WRITE, + (_("Error while sending data to \"%s:%d\"."), host, port), + ("Only %" G_GSIZE_FORMAT " of %u bytes written: %s", + wrote, GST_BUFFER_SIZE (buffer), g_strerror (errno))); + return FALSE; + } +} + +/* write GDP header and payload to the given socket for the given caps. + * Return false if fails. */ +gboolean +gst_tcp_gdp_write_caps (GstElement * this, int socket, const GstCaps * caps, + gboolean fatal, const char *host, int port) +{ + guint length; + guint8 *header; + guint8 *payload; + size_t wrote; + + if (!gst_dp_packet_from_caps (caps, 0, &length, &header, &payload)) + goto create_error; + + GST_LOG_OBJECT (this, "writing %d bytes for GDP caps header", length); + wrote = gst_tcp_socket_write (socket, header, length); + if (wrote != length) + goto write_header_error; + + length = gst_dp_header_payload_length (header); + g_free (header); + + GST_LOG_OBJECT (this, "writing %d bytes for GDP caps payload", length); + wrote = gst_tcp_socket_write (socket, payload, length); + g_free (payload); + + if (wrote != length) + goto write_payload_error; + + return TRUE; + + /* ERRORS */ +create_error: + { + if (fatal) + GST_ELEMENT_ERROR (this, CORE, TOO_LAZY, (NULL), + ("Could not create GDP packet from caps")); + return FALSE; + } +write_header_error: + { + g_free (header); + g_free (payload); + if (fatal) + GST_ELEMENT_ERROR (this, RESOURCE, WRITE, + (_("Error while sending gdp header data to \"%s:%d\"."), host, port), + ("Only %" G_GSIZE_FORMAT " of %u bytes written: %s", + wrote, length, g_strerror (errno))); + return FALSE; + } +write_payload_error: + { + if (fatal) + GST_ELEMENT_ERROR (this, RESOURCE, WRITE, + (_("Error while sending gdp payload data to \"%s:%d\"."), host, port), + ("Only %" G_GSIZE_FORMAT " of %u bytes written: %s", + wrote, length, g_strerror (errno))); + return FALSE; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.h new file mode 100644 index 0000000..533c162 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcp.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * gsttcp.h: helper functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_TCP_HELP_H__ +#define __GST_TCP_HELP_H__ + +#include "gsttcp-enumtypes.h" +#include +#undef GST_DISABLE_DEPRECATED +#include + +#define TCP_HIGHEST_PORT 65535 +#define TCP_DEFAULT_HOST "localhost" +#define TCP_DEFAULT_PORT 4953 + +G_BEGIN_DECLS + +/** + * GstTCPProtocol: + * @GST_TCP_PROTOCOL_NONE: Raw data transmission + * @GST_TCP_PROTOCOL_GDP: #GstBuffers are wrapped and sent/received using the + * GDP protocol. + * + * This enum is provided by the tcp/multifd elements to configure the format of + * data transmission/reception. + * + * The GDP protocol wraps data buffers in a header that also carries format + * information and timestamps. The None value indicates the data is + * sent/received as-is. In that case, format information and timestamping + * must be transmitted separately, or implicit in the bytestream itself. + */ +typedef enum +{ + GST_TCP_PROTOCOL_NONE, + GST_TCP_PROTOCOL_GDP +} GstTCPProtocol; + +gchar * gst_tcp_host_to_ip (GstElement *element, const gchar *host); + +gint gst_tcp_socket_write (int socket, const void *buf, size_t count); + +void gst_tcp_socket_close (GstPollFD *socket); + +GstFlowReturn gst_tcp_read_buffer (GstElement * this, int socket, GstPoll * fdset, GstBuffer **buf); + +GstFlowReturn gst_tcp_gdp_read_buffer (GstElement * this, int socket, GstPoll * fdset, GstBuffer **buf); +GstFlowReturn gst_tcp_gdp_read_caps (GstElement * this, int socket, GstPoll * fdset, GstCaps **caps); + +GstEvent * gst_tcp_gdp_read_event (GstElement *elem, int socket, GstPoll * fdset); + +gboolean gst_tcp_gdp_write_buffer (GstElement *elem, int socket, GstBuffer *buffer, gboolean fatal, const gchar *host, int port); +gboolean gst_tcp_gdp_write_event (GstElement *elem, int socket, GstEvent *event, gboolean fatal, const gchar *host, int port); +gboolean gst_tcp_gdp_write_caps (GstElement *elem, int socket, const GstCaps *caps, gboolean fatal, const gchar *host, int port); + +G_END_DECLS + +#endif /* __GST_TCP_HELP_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.c new file mode 100644 index 0000000..ca60578 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.c @@ -0,0 +1,460 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-tcpclientsink + * @see_also: #tcpclientsrc + * + * + * Example launch line + * |[ + * # server: + * nc -l -p 3000 + * # client: + * gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000 + * ]| everything you type in the client is shown on the server + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include "gsttcp.h" +#include "gsttcpclientsink.h" +#include /* memset */ + +/* TCPClientSink signals and args */ +enum +{ + FRAME_ENCODED, + /* FILL ME */ + LAST_SIGNAL +}; + +GST_DEBUG_CATEGORY_STATIC (tcpclientsink_debug); +#define GST_CAT_DEFAULT (tcpclientsink_debug) + +enum +{ + ARG_0, + ARG_HOST, + ARG_PORT, + ARG_PROTOCOL + /* FILL ME */ +}; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static void gst_tcp_client_sink_base_init (gpointer g_class); +static void gst_tcp_client_sink_class_init (GstTCPClientSink * klass); +static void gst_tcp_client_sink_init (GstTCPClientSink * tcpclientsink); +static void gst_tcp_client_sink_finalize (GObject * gobject); + +static gboolean gst_tcp_client_sink_setcaps (GstBaseSink * bsink, + GstCaps * caps); +static GstFlowReturn gst_tcp_client_sink_render (GstBaseSink * bsink, + GstBuffer * buf); +static GstStateChangeReturn gst_tcp_client_sink_change_state (GstElement * + element, GstStateChange transition); + +static void gst_tcp_client_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tcp_client_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + + +static GstElementClass *parent_class = NULL; + +/*static guint gst_tcp_client_sink_signals[LAST_SIGNAL] = { 0 }; */ + +GType +gst_tcp_client_sink_get_type (void) +{ + static GType tcpclientsink_type = 0; + + + if (!tcpclientsink_type) { + static const GTypeInfo tcpclientsink_info = { + sizeof (GstTCPClientSinkClass), + gst_tcp_client_sink_base_init, + NULL, + (GClassInitFunc) gst_tcp_client_sink_class_init, + NULL, + NULL, + sizeof (GstTCPClientSink), + 0, + (GInstanceInitFunc) gst_tcp_client_sink_init, + NULL + }; + + tcpclientsink_type = + g_type_register_static (GST_TYPE_BASE_SINK, "GstTCPClientSink", + &tcpclientsink_info, 0); + } + return tcpclientsink_type; +} + +static void +gst_tcp_client_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (element_class, + "TCP client sink", "Sink/Network", + "Send data as a client over the network via TCP", + "Thomas Vander Stichele "); +} + +static void +gst_tcp_client_sink_class_init (GstTCPClientSink * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_tcp_client_sink_set_property; + gobject_class->get_property = gst_tcp_client_sink_get_property; + gobject_class->finalize = gst_tcp_client_sink_finalize; + + g_object_class_install_property (gobject_class, ARG_HOST, + g_param_spec_string ("host", "Host", "The host/IP to send the packets to", + TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_PORT, + g_param_spec_int ("port", "Port", "The port to send the packets to", + 0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_PROTOCOL, + g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", + GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = gst_tcp_client_sink_change_state; + + gstbasesink_class->set_caps = gst_tcp_client_sink_setcaps; + gstbasesink_class->render = gst_tcp_client_sink_render; + + GST_DEBUG_CATEGORY_INIT (tcpclientsink_debug, "tcpclientsink", 0, "TCP sink"); +} + +static void +gst_tcp_client_sink_init (GstTCPClientSink * this) +{ + this->host = g_strdup (TCP_DEFAULT_HOST); + this->port = TCP_DEFAULT_PORT; + + this->sock_fd.fd = -1; + this->protocol = GST_TCP_PROTOCOL_NONE; + GST_OBJECT_FLAG_UNSET (this, GST_TCP_CLIENT_SINK_OPEN); +} + +static void +gst_tcp_client_sink_finalize (GObject * gobject) +{ + GstTCPClientSink *this = GST_TCP_CLIENT_SINK (gobject); + + g_free (this->host); + + G_OBJECT_CLASS (parent_class)->finalize (gobject); +} + +static gboolean +gst_tcp_client_sink_setcaps (GstBaseSink * bsink, GstCaps * caps) +{ + GstTCPClientSink *sink; + + sink = GST_TCP_CLIENT_SINK (bsink); + + /* write the buffer header if we have one */ + switch (sink->protocol) { + case GST_TCP_PROTOCOL_NONE: + break; + + case GST_TCP_PROTOCOL_GDP: + /* if we haven't send caps yet, send them first */ + if (!sink->caps_sent) { + const GstCaps *caps; + gchar *string; + + caps = GST_PAD_CAPS (GST_PAD_PEER (GST_BASE_SINK_PAD (bsink))); + string = gst_caps_to_string (caps); + GST_DEBUG_OBJECT (sink, "Sending caps %s through GDP", string); + g_free (string); + + if (!gst_tcp_gdp_write_caps (GST_ELEMENT (sink), sink->sock_fd.fd, + caps, TRUE, sink->host, sink->port)) + goto gdp_write_error; + + sink->caps_sent = TRUE; + } + break; + default: + g_warning ("Unhandled protocol type"); + break; + } + + return TRUE; + + /* ERRORS */ +gdp_write_error: + { + return FALSE; + } +} + +static GstFlowReturn +gst_tcp_client_sink_render (GstBaseSink * bsink, GstBuffer * buf) +{ + size_t wrote = 0; + GstTCPClientSink *sink; + gint size; + + sink = GST_TCP_CLIENT_SINK (bsink); + + g_return_val_if_fail (GST_OBJECT_FLAG_IS_SET (sink, GST_TCP_CLIENT_SINK_OPEN), + GST_FLOW_WRONG_STATE); + + size = GST_BUFFER_SIZE (buf); + + GST_LOG_OBJECT (sink, "writing %d bytes for buffer data", size); + + /* write the buffer header if we have one */ + switch (sink->protocol) { + case GST_TCP_PROTOCOL_NONE: + break; + case GST_TCP_PROTOCOL_GDP: + GST_LOG_OBJECT (sink, "Sending buffer header through GDP"); + if (!gst_tcp_gdp_write_buffer (GST_ELEMENT (sink), sink->sock_fd.fd, buf, + TRUE, sink->host, sink->port)) + goto gdp_write_error; + break; + default: + break; + } + + /* write buffer data */ + wrote = gst_tcp_socket_write (sink->sock_fd.fd, GST_BUFFER_DATA (buf), size); + + if (wrote < size) + goto write_error; + + sink->data_written += wrote; + + return GST_FLOW_OK; + + /* ERRORS */ +gdp_write_error: + { + return FALSE; + } +write_error: + { + GST_ELEMENT_ERROR (sink, RESOURCE, WRITE, + (_("Error while sending data to \"%s:%d\"."), sink->host, sink->port), + ("Only %" G_GSIZE_FORMAT " of %u bytes written: %s", + wrote, GST_BUFFER_SIZE (buf), g_strerror (errno))); + return GST_FLOW_ERROR; + } +} + +static void +gst_tcp_client_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTCPClientSink *tcpclientsink; + + g_return_if_fail (GST_IS_TCP_CLIENT_SINK (object)); + tcpclientsink = GST_TCP_CLIENT_SINK (object); + + switch (prop_id) { + case ARG_HOST: + if (!g_value_get_string (value)) { + g_warning ("host property cannot be NULL"); + break; + } + g_free (tcpclientsink->host); + tcpclientsink->host = g_strdup (g_value_get_string (value)); + break; + case ARG_PORT: + tcpclientsink->port = g_value_get_int (value); + break; + case ARG_PROTOCOL: + tcpclientsink->protocol = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tcp_client_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTCPClientSink *tcpclientsink; + + g_return_if_fail (GST_IS_TCP_CLIENT_SINK (object)); + tcpclientsink = GST_TCP_CLIENT_SINK (object); + + switch (prop_id) { + case ARG_HOST: + g_value_set_string (value, tcpclientsink->host); + break; + case ARG_PORT: + g_value_set_int (value, tcpclientsink->port); + break; + case ARG_PROTOCOL: + g_value_set_enum (value, tcpclientsink->protocol); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/* create a socket for sending to remote machine */ +static gboolean +gst_tcp_client_sink_start (GstTCPClientSink * this) +{ + int ret; + gchar *ip; + + if (GST_OBJECT_FLAG_IS_SET (this, GST_TCP_CLIENT_SINK_OPEN)) + return TRUE; + + /* reset caps_sent flag */ + this->caps_sent = FALSE; + + /* create sending client socket */ + GST_DEBUG_OBJECT (this, "opening sending client socket to %s:%d", this->host, + this->port); + if ((this->sock_fd.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + GST_DEBUG_OBJECT (this, "opened sending client socket with fd %d", + this->sock_fd.fd); + + /* look up name if we need to */ + ip = gst_tcp_host_to_ip (GST_ELEMENT (this), this->host); + if (!ip) { + gst_tcp_socket_close (&this->sock_fd); + return FALSE; + } + GST_DEBUG_OBJECT (this, "IP address for host %s is %s", this->host, ip); + + /* connect to server */ + memset (&this->server_sin, 0, sizeof (this->server_sin)); + this->server_sin.sin_family = AF_INET; /* network socket */ + this->server_sin.sin_port = htons (this->port); /* on port */ + this->server_sin.sin_addr.s_addr = inet_addr (ip); /* on host ip */ + g_free (ip); + + GST_DEBUG_OBJECT (this, "connecting to server"); + ret = connect (this->sock_fd.fd, (struct sockaddr *) &this->server_sin, + sizeof (this->server_sin)); + + if (ret) { + gst_tcp_socket_close (&this->sock_fd); + switch (errno) { + case ECONNREFUSED: + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, + (_("Connection to %s:%d refused."), this->host, this->port), + (NULL)); + return FALSE; + break; + default: + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("connect to %s:%d failed: %s", this->host, this->port, + g_strerror (errno))); + return FALSE; + break; + } + } + + GST_OBJECT_FLAG_SET (this, GST_TCP_CLIENT_SINK_OPEN); + + this->data_written = 0; + + return TRUE; +} + +static gboolean +gst_tcp_client_sink_stop (GstTCPClientSink * this) +{ + if (!GST_OBJECT_FLAG_IS_SET (this, GST_TCP_CLIENT_SINK_OPEN)) + return TRUE; + + gst_tcp_socket_close (&this->sock_fd); + + GST_OBJECT_FLAG_UNSET (this, GST_TCP_CLIENT_SINK_OPEN); + + return TRUE; +} + +static GstStateChangeReturn +gst_tcp_client_sink_change_state (GstElement * element, + GstStateChange transition) +{ + GstTCPClientSink *sink; + GstStateChangeReturn res; + + sink = GST_TCP_CLIENT_SINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!gst_tcp_client_sink_start (sink)) + goto start_failure; + break; + default: + break; + } + res = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + gst_tcp_client_sink_stop (sink); + default: + break; + } + return res; + +start_failure: + { + return GST_STATE_CHANGE_FAILURE; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.h new file mode 100644 index 0000000..4399870 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsink.h @@ -0,0 +1,91 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TCP_CLIENT_SINK_H__ +#define __GST_TCP_CLIENT_SINK_H__ + + +#include +#include + +#include "gsttcp.h" + +G_BEGIN_DECLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gsttcp.h" + +#define GST_TYPE_TCP_CLIENT_SINK \ + (gst_tcp_client_sink_get_type()) +#define GST_TCP_CLIENT_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCP_CLIENT_SINK,GstTCPClientSink)) +#define GST_TCP_CLIENT_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCP_CLIENT_SINK,GstTCPClientSinkClass)) +#define GST_IS_TCP_CLIENT_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCP_CLIENT_SINK)) +#define GST_IS_TCP_CLIENT_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCP_CLIENT_SINK)) + +typedef struct _GstTCPClientSink GstTCPClientSink; +typedef struct _GstTCPClientSinkClass GstTCPClientSinkClass; + +typedef enum { + GST_TCP_CLIENT_SINK_OPEN = (GST_ELEMENT_FLAG_LAST << 0), + + GST_TCP_CLIENT_SINK_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2), +} GstTCPClientSinkFlags; + +struct _GstTCPClientSink { + GstBaseSink element; + + /* server information */ + int port; + gchar *host; + struct sockaddr_in server_sin; + + /* socket */ + GstPollFD sock_fd; + + size_t data_written; /* how much bytes have we written ? */ + GstTCPProtocol protocol; /* used with the protocol enum */ + gboolean caps_sent; /* whether or not we sent caps already */ +}; + +struct _GstTCPClientSinkClass { + GstBaseSinkClass parent_class; +}; + +GType gst_tcp_client_sink_get_type(void); + +G_END_DECLS + +#endif /* __GST_TCP_CLIENT_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.c new file mode 100644 index 0000000..b8ac849 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.c @@ -0,0 +1,441 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-tcpclientsrc + * @see_also: #tcpclientsink + * + * + * Example launch line + * |[ + * # server: + * nc -l -p 3000 + * # client: + * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2 + * ]| everything you type in the server is shown on the client + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gsttcp.h" +#include "gsttcpclientsrc.h" +#include /* memset */ +#include +#include +#include + + +GST_DEBUG_CATEGORY_STATIC (tcpclientsrc_debug); +#define GST_CAT_DEFAULT tcpclientsrc_debug + +#define MAX_READ_SIZE 4 * 1024 + + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +enum +{ + PROP_0, + PROP_HOST, + PROP_PORT, + PROP_PROTOCOL +}; + + +GST_BOILERPLATE (GstTCPClientSrc, gst_tcp_client_src, GstPushSrc, + GST_TYPE_PUSH_SRC); + + +static void gst_tcp_client_src_finalize (GObject * gobject); + +static GstCaps *gst_tcp_client_src_getcaps (GstBaseSrc * psrc); + +static GstFlowReturn gst_tcp_client_src_create (GstPushSrc * psrc, + GstBuffer ** outbuf); +static gboolean gst_tcp_client_src_stop (GstBaseSrc * bsrc); +static gboolean gst_tcp_client_src_start (GstBaseSrc * bsrc); +static gboolean gst_tcp_client_src_unlock (GstBaseSrc * bsrc); +static gboolean gst_tcp_client_src_unlock_stop (GstBaseSrc * bsrc); + +static void gst_tcp_client_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tcp_client_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + + +static void +gst_tcp_client_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + + gst_element_class_set_details_simple (element_class, + "TCP client source", "Source/Network", + "Receive data as a client over the network via TCP", + "Thomas Vander Stichele "); +} + +static void +gst_tcp_client_src_class_init (GstTCPClientSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpush_src_class; + + gobject_class = (GObjectClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstpush_src_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_tcp_client_src_set_property; + gobject_class->get_property = gst_tcp_client_src_get_property; + gobject_class->finalize = gst_tcp_client_src_finalize; + + g_object_class_install_property (gobject_class, PROP_HOST, + g_param_spec_string ("host", "Host", + "The host IP address to receive packets from", TCP_DEFAULT_HOST, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_int ("port", "Port", "The port to receive packets from", 0, + TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PROTOCOL, + g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", + GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->get_caps = gst_tcp_client_src_getcaps; + gstbasesrc_class->start = gst_tcp_client_src_start; + gstbasesrc_class->stop = gst_tcp_client_src_stop; + gstbasesrc_class->unlock = gst_tcp_client_src_unlock; + gstbasesrc_class->unlock_stop = gst_tcp_client_src_unlock_stop; + + gstpush_src_class->create = gst_tcp_client_src_create; + + GST_DEBUG_CATEGORY_INIT (tcpclientsrc_debug, "tcpclientsrc", 0, + "TCP Client Source"); +} + +static void +gst_tcp_client_src_init (GstTCPClientSrc * this, GstTCPClientSrcClass * g_class) +{ + this->port = TCP_DEFAULT_PORT; + this->host = g_strdup (TCP_DEFAULT_HOST); + this->sock_fd.fd = -1; + this->protocol = GST_TCP_PROTOCOL_NONE; + this->caps = NULL; + + GST_OBJECT_FLAG_UNSET (this, GST_TCP_CLIENT_SRC_OPEN); +} + +static void +gst_tcp_client_src_finalize (GObject * gobject) +{ + GstTCPClientSrc *this = GST_TCP_CLIENT_SRC (gobject); + + g_free (this->host); + + G_OBJECT_CLASS (parent_class)->finalize (gobject); +} + +static GstCaps * +gst_tcp_client_src_getcaps (GstBaseSrc * bsrc) +{ + GstTCPClientSrc *src; + GstCaps *caps = NULL; + + src = GST_TCP_CLIENT_SRC (bsrc); + + if (!GST_OBJECT_FLAG_IS_SET (src, GST_TCP_CLIENT_SRC_OPEN)) + caps = gst_caps_new_any (); + else if (src->caps) + caps = gst_caps_copy (src->caps); + else + caps = gst_caps_new_any (); + GST_DEBUG_OBJECT (src, "returning caps %" GST_PTR_FORMAT, caps); + g_assert (GST_IS_CAPS (caps)); + return caps; +} + +static GstFlowReturn +gst_tcp_client_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) +{ + GstTCPClientSrc *src; + GstFlowReturn ret = GST_FLOW_OK; + + src = GST_TCP_CLIENT_SRC (psrc); + + if (!GST_OBJECT_FLAG_IS_SET (src, GST_TCP_CLIENT_SRC_OPEN)) + goto wrong_state; + + GST_LOG_OBJECT (src, "asked for a buffer"); + + /* read the buffer header if we're using a protocol */ + switch (src->protocol) { + case GST_TCP_PROTOCOL_NONE: + ret = gst_tcp_read_buffer (GST_ELEMENT (src), src->sock_fd.fd, + src->fdset, outbuf); + break; + + case GST_TCP_PROTOCOL_GDP: + /* get the caps if we're using GDP */ + if (!src->caps_received) { + GstCaps *caps; + + GST_DEBUG_OBJECT (src, "getting caps through GDP"); + ret = gst_tcp_gdp_read_caps (GST_ELEMENT (src), src->sock_fd.fd, + src->fdset, &caps); + + if (ret != GST_FLOW_OK) + goto no_caps; + + src->caps_received = TRUE; + src->caps = caps; + } + + ret = gst_tcp_gdp_read_buffer (GST_ELEMENT (src), src->sock_fd.fd, + src->fdset, outbuf); + break; + default: + /* need to assert as buf == NULL */ + g_assert ("Unhandled protocol type"); + break; + } + + if (ret == GST_FLOW_OK) { + GST_LOG_OBJECT (src, + "Returning buffer from _get of size %d, ts %" + GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, + GST_BUFFER_SIZE (*outbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*outbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (*outbuf)), + GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf)); + + gst_buffer_set_caps (*outbuf, src->caps); + } + + return ret; + +wrong_state: + { + GST_DEBUG_OBJECT (src, "connection to closed, cannot read data"); + return GST_FLOW_WRONG_STATE; + } +no_caps: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Could not read caps through GDP")); + return ret; + } +} + +static void +gst_tcp_client_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTCPClientSrc *tcpclientsrc = GST_TCP_CLIENT_SRC (object); + + switch (prop_id) { + case PROP_HOST: + if (!g_value_get_string (value)) { + g_warning ("host property cannot be NULL"); + break; + } + g_free (tcpclientsrc->host); + tcpclientsrc->host = g_strdup (g_value_get_string (value)); + break; + case PROP_PORT: + tcpclientsrc->port = g_value_get_int (value); + break; + case PROP_PROTOCOL: + tcpclientsrc->protocol = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tcp_client_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTCPClientSrc *tcpclientsrc = GST_TCP_CLIENT_SRC (object); + + switch (prop_id) { + case PROP_HOST: + g_value_set_string (value, tcpclientsrc->host); + break; + case PROP_PORT: + g_value_set_int (value, tcpclientsrc->port); + break; + case PROP_PROTOCOL: + g_value_set_enum (value, tcpclientsrc->protocol); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* create a socket for connecting to remote server */ +static gboolean +gst_tcp_client_src_start (GstBaseSrc * bsrc) +{ + int ret; + gchar *ip; + GstTCPClientSrc *src = GST_TCP_CLIENT_SRC (bsrc); + + if ((src->fdset = gst_poll_new (TRUE)) == NULL) + goto socket_pair; + + /* create receiving client socket */ + GST_DEBUG_OBJECT (src, "opening receiving client socket to %s:%d", + src->host, src->port); + + if ((src->sock_fd.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + goto no_socket; + + GST_DEBUG_OBJECT (src, "opened receiving client socket with fd %d", + src->sock_fd.fd); + GST_OBJECT_FLAG_SET (src, GST_TCP_CLIENT_SRC_OPEN); + + /* look up name if we need to */ + if (!(ip = gst_tcp_host_to_ip (GST_ELEMENT (src), src->host))) + goto name_resolv; + + GST_DEBUG_OBJECT (src, "IP address for host %s is %s", src->host, ip); + + /* connect to server */ + memset (&src->server_sin, 0, sizeof (src->server_sin)); + src->server_sin.sin_family = AF_INET; /* network socket */ + src->server_sin.sin_port = htons (src->port); /* on port */ + src->server_sin.sin_addr.s_addr = inet_addr (ip); /* on host ip */ + g_free (ip); + + GST_DEBUG_OBJECT (src, "connecting to server"); + ret = connect (src->sock_fd.fd, (struct sockaddr *) &src->server_sin, + sizeof (src->server_sin)); + if (ret) + goto connect_failed; + + /* add the socket to the poll */ + gst_poll_add_fd (src->fdset, &src->sock_fd); + gst_poll_fd_ctl_read (src->fdset, &src->sock_fd, TRUE); + + return TRUE; + +socket_pair: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } +no_socket: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } +name_resolv: + { + gst_tcp_client_src_stop (GST_BASE_SRC (src)); + return FALSE; + } +connect_failed: + { + gst_tcp_client_src_stop (GST_BASE_SRC (src)); + switch (errno) { + case ECONNREFUSED: + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, + (_("Connection to %s:%d refused."), src->host, src->port), (NULL)); + break; + default: + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("connect to %s:%d failed: %s", src->host, src->port, + g_strerror (errno))); + break; + } + return FALSE; + } +} + +/* close the socket and associated resources + * unset OPEN flag + * used both to recover from errors and go to NULL state */ +static gboolean +gst_tcp_client_src_stop (GstBaseSrc * bsrc) +{ + GstTCPClientSrc *src; + + src = GST_TCP_CLIENT_SRC (bsrc); + + GST_DEBUG_OBJECT (src, "closing socket"); + + if (src->fdset != NULL) { + gst_poll_free (src->fdset); + src->fdset = NULL; + } + + gst_tcp_socket_close (&src->sock_fd); + src->caps_received = FALSE; + if (src->caps) { + gst_caps_unref (src->caps); + src->caps = NULL; + } + GST_OBJECT_FLAG_UNSET (src, GST_TCP_CLIENT_SRC_OPEN); + + return TRUE; +} + +/* will be called only between calls to start() and stop() */ +static gboolean +gst_tcp_client_src_unlock (GstBaseSrc * bsrc) +{ + GstTCPClientSrc *src = GST_TCP_CLIENT_SRC (bsrc); + + GST_DEBUG_OBJECT (src, "set to flushing"); + gst_poll_set_flushing (src->fdset, TRUE); + + return TRUE; +} + +/* will be called only between calls to start() and stop() */ +static gboolean +gst_tcp_client_src_unlock_stop (GstBaseSrc * bsrc) +{ + GstTCPClientSrc *src = GST_TCP_CLIENT_SRC (bsrc); + + GST_DEBUG_OBJECT (src, "unset flushing"); + gst_poll_set_flushing (src->fdset, FALSE); + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.h new file mode 100644 index 0000000..24d31e8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpclientsrc.h @@ -0,0 +1,83 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TCP_CLIENT_SRC_H__ +#define __GST_TCP_CLIENT_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +#include /* sockaddr_in */ +#include +#include +#include /* sockaddr_in */ +#include + +#include "gsttcp.h" + +#define GST_TYPE_TCP_CLIENT_SRC \ + (gst_tcp_client_src_get_type()) +#define GST_TCP_CLIENT_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCP_CLIENT_SRC,GstTCPClientSrc)) +#define GST_TCP_CLIENT_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCP_CLIENT_SRC,GstTCPClientSrcClass)) +#define GST_IS_TCP_CLIENT_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCP_CLIENT_SRC)) +#define GST_IS_TCP_CLIENT_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCP_CLIENT_SRC)) + +typedef struct _GstTCPClientSrc GstTCPClientSrc; +typedef struct _GstTCPClientSrcClass GstTCPClientSrcClass; + +typedef enum { + GST_TCP_CLIENT_SRC_OPEN = (GST_ELEMENT_FLAG_LAST << 0), + + GST_TCP_CLIENT_SRC_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2) +} GstTCPClientSrcFlags; + +struct _GstTCPClientSrc { + GstPushSrc element; + + /* server information */ + int port; + gchar *host; + struct sockaddr_in server_sin; + + /* socket */ + GstPollFD sock_fd; + GstPoll *fdset; + + GstTCPProtocol protocol; /* protocol used for reading data */ + gboolean caps_received; /* if we have received caps yet */ + GstCaps *caps; +}; + +struct _GstTCPClientSrcClass { + GstPushSrcClass parent_class; +}; + +GType gst_tcp_client_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_TCP_CLIENT_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.c new file mode 100644 index 0000000..bb2cf48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.c @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include "gsttcpclientsrc.h" +#include "gsttcpclientsink.h" +#include "gsttcpserversrc.h" +#include "gsttcpserversink.h" +#include "gstmultifdsink.h" + +GST_DEBUG_CATEGORY (tcp_debug); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_dp_init (); + + if (!gst_element_register (plugin, "tcpclientsink", GST_RANK_NONE, + GST_TYPE_TCP_CLIENT_SINK)) + return FALSE; + if (!gst_element_register (plugin, "tcpclientsrc", GST_RANK_NONE, + GST_TYPE_TCP_CLIENT_SRC)) + return FALSE; + if (!gst_element_register (plugin, "tcpserversink", GST_RANK_NONE, + GST_TYPE_TCP_SERVER_SINK)) + return FALSE; + if (!gst_element_register (plugin, "tcpserversrc", GST_RANK_NONE, + GST_TYPE_TCP_SERVER_SRC)) + return FALSE; + if (!gst_element_register (plugin, "multifdsink", GST_RANK_NONE, + GST_TYPE_MULTI_FD_SINK)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (tcp_debug, "tcp", 0, "TCP calls"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "tcp", + "transfer data over the network via TCP", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.h new file mode 100644 index 0000000..38b91be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpplugin.h @@ -0,0 +1,40 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TCP_H__ +#define __GST_TCP_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + + typedef enum + { + CONTROL_ZERO, + CONTROL_NONE, + CONTROL_TCP + } Gst_TCP_Control; + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __GST_TCP_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.c new file mode 100644 index 0000000..fdca0ec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.c @@ -0,0 +1,378 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-tcpserversink + * @see_also: #multifdsink + * + * + * Example launch line + * |[ + * # server: + * gst-launch fdsrc fd=1 ! tcpserversink protocol=none port=3000 + * # client: + * gst-launch tcpclientsrc protocol=none port=3000 ! fdsink fd=2 + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include /* memset */ + +#include + +#ifdef HAVE_FIONREAD_IN_SYS_FILIO +#include +#endif + +#include "gsttcp.h" +#include "gsttcpserversink.h" +#include "gsttcp-marshal.h" + +#define TCP_BACKLOG 5 + +GST_DEBUG_CATEGORY_STATIC (tcpserversink_debug); +#define GST_CAT_DEFAULT (tcpserversink_debug) + +enum +{ + ARG_0, + ARG_HOST, + ARG_PORT, +}; + +static void gst_tcp_server_sink_finalize (GObject * gobject); + +static gboolean gst_tcp_server_sink_handle_wait (GstMultiFdSink * sink, + GstPoll * set); +static gboolean gst_tcp_server_sink_init_send (GstMultiFdSink * this); +static gboolean gst_tcp_server_sink_close (GstMultiFdSink * this); +static void gst_tcp_server_sink_removed (GstMultiFdSink * sink, int fd); + +static void gst_tcp_server_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tcp_server_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + + +GST_BOILERPLATE (GstTCPServerSink, gst_tcp_server_sink, GstMultiFdSink, + GST_TYPE_MULTI_FD_SINK); + + +static void +gst_tcp_server_sink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "TCP server sink", "Sink/Network", + "Send data as a server over the network via TCP", + "Thomas Vander Stichele "); +} + +static void +gst_tcp_server_sink_class_init (GstTCPServerSinkClass * klass) +{ + GObjectClass *gobject_class; + GstMultiFdSinkClass *gstmultifdsink_class; + + gobject_class = (GObjectClass *) klass; + gstmultifdsink_class = (GstMultiFdSinkClass *) klass; + + gobject_class->set_property = gst_tcp_server_sink_set_property; + gobject_class->get_property = gst_tcp_server_sink_get_property; + gobject_class->finalize = gst_tcp_server_sink_finalize; + + g_object_class_install_property (gobject_class, ARG_HOST, + g_param_spec_string ("host", "host", "The host/IP to send the packets to", + TCP_DEFAULT_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, ARG_PORT, + g_param_spec_int ("port", "port", "The port to send the packets to", + 0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstmultifdsink_class->init = gst_tcp_server_sink_init_send; + gstmultifdsink_class->wait = gst_tcp_server_sink_handle_wait; + gstmultifdsink_class->close = gst_tcp_server_sink_close; + gstmultifdsink_class->removed = gst_tcp_server_sink_removed; + + GST_DEBUG_CATEGORY_INIT (tcpserversink_debug, "tcpserversink", 0, "TCP sink"); +} + +static void +gst_tcp_server_sink_init (GstTCPServerSink * this, + GstTCPServerSinkClass * klass) +{ + this->server_port = TCP_DEFAULT_PORT; + /* should support as minimum 576 for IPV4 and 1500 for IPV6 */ + /* this->mtu = 1500; */ + this->host = g_strdup (TCP_DEFAULT_HOST); + + this->server_sock.fd = -1; +} + +static void +gst_tcp_server_sink_finalize (GObject * gobject) +{ + GstTCPServerSink *this = GST_TCP_SERVER_SINK (gobject); + + g_free (this->host); + + G_OBJECT_CLASS (parent_class)->finalize (gobject); +} + +/* handle a read request on the server, + * which indicates a new client connection */ +static gboolean +gst_tcp_server_sink_handle_server_read (GstTCPServerSink * sink) +{ + /* new client */ + int client_sock_fd; + struct sockaddr_in client_address; + socklen_t client_address_len; + + /* For some stupid reason, client_address and client_address_len has to be + * zeroed */ + memset (&client_address, 0, sizeof (client_address)); + client_address_len = 0; + + client_sock_fd = + accept (sink->server_sock.fd, (struct sockaddr *) &client_address, + &client_address_len); + if (client_sock_fd == -1) + goto accept_failed; + + gst_multi_fd_sink_add (GST_MULTI_FD_SINK (sink), client_sock_fd); + + GST_DEBUG_OBJECT (sink, "added new client ip %s with fd %d", + inet_ntoa (client_address.sin_addr), client_sock_fd); + + return TRUE; + + /* ERRORS */ +accept_failed: + { + GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL), + ("Could not accept client on server socket %d: %s (%d)", + sink->server_sock.fd, g_strerror (errno), errno)); + return FALSE; + } +} + +static void +gst_tcp_server_sink_removed (GstMultiFdSink * sink, int fd) +{ +#ifndef GST_DISABLE_GST_DEBUG + GstTCPServerSink *this = GST_TCP_SERVER_SINK (sink); +#endif + + GST_LOG_OBJECT (this, "closing fd %d", fd); + if (close (fd) < 0) { + GST_WARNING_OBJECT (this, "error closing fd %d: %s", fd, + g_strerror (errno)); + } +} + +static gboolean +gst_tcp_server_sink_handle_wait (GstMultiFdSink * sink, GstPoll * set) +{ + GstTCPServerSink *this = GST_TCP_SERVER_SINK (sink); + + if (gst_poll_fd_can_read (set, &this->server_sock)) { + /* handle new client connection on server socket */ + if (!gst_tcp_server_sink_handle_server_read (this)) + goto connection_failed; + } + return TRUE; + + /* ERRORS */ +connection_failed: + { + GST_ELEMENT_ERROR (this, RESOURCE, READ, (NULL), + ("client connection failed: %s", g_strerror (errno))); + return FALSE; + } +} + +static void +gst_tcp_server_sink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTCPServerSink *sink; + + g_return_if_fail (GST_IS_TCP_SERVER_SINK (object)); + sink = GST_TCP_SERVER_SINK (object); + + switch (prop_id) { + case ARG_HOST: + if (!g_value_get_string (value)) { + g_warning ("host property cannot be NULL"); + break; + } + g_free (sink->host); + sink->host = g_strdup (g_value_get_string (value)); + break; + case ARG_PORT: + sink->server_port = g_value_get_int (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tcp_server_sink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTCPServerSink *sink; + + g_return_if_fail (GST_IS_TCP_SERVER_SINK (object)); + sink = GST_TCP_SERVER_SINK (object); + + switch (prop_id) { + case ARG_HOST: + g_value_set_string (value, sink->host); + break; + case ARG_PORT: + g_value_set_int (value, sink->server_port); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +/* create a socket for sending to remote machine */ +static gboolean +gst_tcp_server_sink_init_send (GstMultiFdSink * parent) +{ + int ret; + GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent); + + /* create sending server socket */ + if ((this->server_sock.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + goto no_socket; + + GST_DEBUG_OBJECT (this, "opened sending server socket with fd %d", + this->server_sock.fd); + + /* make address reusable */ + ret = 1; + if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_REUSEADDR, + (void *) &ret, sizeof (ret)) < 0) + goto reuse_failed; + + /* keep connection alive; avoids SIGPIPE during write */ + ret = 1; + if (setsockopt (this->server_sock.fd, SOL_SOCKET, SO_KEEPALIVE, + (void *) &ret, sizeof (ret)) < 0) + goto keepalive_failed; + + /* name the socket */ + memset (&this->server_sin, 0, sizeof (this->server_sin)); + this->server_sin.sin_family = AF_INET; /* network socket */ + this->server_sin.sin_port = htons (this->server_port); /* on port */ + this->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); /* for hosts */ + + /* bind it */ + GST_DEBUG_OBJECT (this, "binding server socket to address"); + ret = bind (this->server_sock.fd, (struct sockaddr *) &this->server_sin, + sizeof (this->server_sin)); + if (ret) + goto bind_failed; + + /* set the server socket to nonblocking */ + fcntl (this->server_sock.fd, F_SETFL, O_NONBLOCK); + + GST_DEBUG_OBJECT (this, "listening on server socket %d with queue of %d", + this->server_sock.fd, TCP_BACKLOG); + if (listen (this->server_sock.fd, TCP_BACKLOG) == -1) + goto listen_failed; + + GST_DEBUG_OBJECT (this, + "listened on server socket %d, returning from connection setup", + this->server_sock.fd); + + gst_poll_add_fd (parent->fdset, &this->server_sock); + gst_poll_fd_ctl_read (parent->fdset, &this->server_sock, TRUE); + + return TRUE; + + /* ERRORS */ +no_socket: + { + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_WRITE, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } +reuse_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), + ("Could not setsockopt: %s", g_strerror (errno))); + return FALSE; + } +keepalive_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, SETTINGS, (NULL), + ("Could not setsockopt: %s", g_strerror (errno))); + return FALSE; + } +listen_failed: + { + gst_tcp_socket_close (&this->server_sock); + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("Could not listen on server socket: %s", g_strerror (errno))); + return FALSE; + } +bind_failed: + { + gst_tcp_socket_close (&this->server_sock); + switch (errno) { + default: + GST_ELEMENT_ERROR (this, RESOURCE, OPEN_READ, (NULL), + ("bind on port %d failed: %s", this->server_port, + g_strerror (errno))); + break; + } + return FALSE; + } +} + +static gboolean +gst_tcp_server_sink_close (GstMultiFdSink * parent) +{ + GstTCPServerSink *this = GST_TCP_SERVER_SINK (parent); + + if (this->server_sock.fd != -1) { + gst_poll_remove_fd (parent->fdset, &this->server_sock); + + close (this->server_sock.fd); + this->server_sock.fd = -1; + } + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.h new file mode 100644 index 0000000..ac8846d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversink.h @@ -0,0 +1,90 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TCP_SERVER_SINK_H__ +#define __GST_TCP_SERVER_SINK_H__ + + +#include + +G_BEGIN_DECLS + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "gstmultifdsink.h" + +#define GST_TYPE_TCP_SERVER_SINK \ + (gst_tcp_server_sink_get_type()) +#define GST_TCP_SERVER_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCP_SERVER_SINK,GstTCPServerSink)) +#define GST_TCP_SERVER_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCP_SERVER_SINK,GstTCPServerSinkClass)) +#define GST_IS_TCP_SERVER_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCP_SERVER_SINK)) +#define GST_IS_TCP_SERVER_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCP_SERVER_SINK)) + +typedef struct _GstTCPServerSink GstTCPServerSink; +typedef struct _GstTCPServerSinkClass GstTCPServerSinkClass; + +typedef enum { + GST_TCP_SERVER_SINK_OPEN = (GST_ELEMENT_FLAG_LAST << 0), + + GST_TCP_SERVER_SINK_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2) +} GstTCPServerSinkFlags; + +/** + * GstTCPServerSink: + * + * Opaque data structure. + */ +struct _GstTCPServerSink { + GstMultiFdSink element; + + /* server information */ + int server_port; + gchar *host; + struct sockaddr_in server_sin; + + /* socket */ + GstPollFD server_sock; +}; + +struct _GstTCPServerSinkClass { + GstMultiFdSinkClass parent_class; +}; + +GType gst_tcp_server_sink_get_type (void); + +G_END_DECLS + +#endif /* __GST_TCP_SERVER_SINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.c b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.c new file mode 100644 index 0000000..c4244da --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.c @@ -0,0 +1,483 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-tcpserversrc + * @see_also: #tcpserversink + * + * + * Example launch line + * |[ + * # server: + * gst-launch tcpserversrc protocol=none port=3000 ! fdsink fd=2 + * # client: + * gst-launch fdsrc fd=1 ! tcpclientsink protocol=none port=3000 + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "gsttcp.h" +#include "gsttcpserversrc.h" +#include /* memset */ +#include +#include +#include + + +GST_DEBUG_CATEGORY_STATIC (tcpserversrc_debug); +#define GST_CAT_DEFAULT tcpserversrc_debug + +#define TCP_DEFAULT_LISTEN_HOST NULL /* listen on all interfaces */ +#define TCP_BACKLOG 1 /* client connection queue */ + + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +enum +{ + PROP_0, + PROP_HOST, + PROP_PORT, + PROP_PROTOCOL +}; + + +GST_BOILERPLATE (GstTCPServerSrc, gst_tcp_server_src, GstPushSrc, + GST_TYPE_PUSH_SRC); + + +static void gst_tcp_server_src_finalize (GObject * gobject); + +static gboolean gst_tcp_server_src_start (GstBaseSrc * bsrc); +static gboolean gst_tcp_server_src_stop (GstBaseSrc * bsrc); +static gboolean gst_tcp_server_src_unlock (GstBaseSrc * bsrc); +static GstFlowReturn gst_tcp_server_src_create (GstPushSrc * psrc, + GstBuffer ** buf); + +static void gst_tcp_server_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_tcp_server_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + + +static void +gst_tcp_server_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + + gst_element_class_set_details_simple (element_class, + "TCP server source", "Source/Network", + "Receive data as a server over the network via TCP", + "Thomas Vander Stichele "); +} + +static void +gst_tcp_server_src_class_init (GstTCPServerSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpush_src_class; + + gobject_class = (GObjectClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstpush_src_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_tcp_server_src_set_property; + gobject_class->get_property = gst_tcp_server_src_get_property; + gobject_class->finalize = gst_tcp_server_src_finalize; + + g_object_class_install_property (gobject_class, PROP_HOST, + g_param_spec_string ("host", "Host", "The hostname to listen as", + TCP_DEFAULT_LISTEN_HOST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PORT, + g_param_spec_int ("port", "Port", "The port to listen to", + 0, TCP_HIGHEST_PORT, TCP_DEFAULT_PORT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PROTOCOL, + g_param_spec_enum ("protocol", "Protocol", "The protocol to wrap data in", + GST_TYPE_TCP_PROTOCOL, GST_TCP_PROTOCOL_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->start = gst_tcp_server_src_start; + gstbasesrc_class->stop = gst_tcp_server_src_stop; + gstbasesrc_class->unlock = gst_tcp_server_src_unlock; + + gstpush_src_class->create = gst_tcp_server_src_create; + + GST_DEBUG_CATEGORY_INIT (tcpserversrc_debug, "tcpserversrc", 0, + "TCP Server Source"); +} + +static void +gst_tcp_server_src_init (GstTCPServerSrc * src, GstTCPServerSrcClass * g_class) +{ + src->server_port = TCP_DEFAULT_PORT; + src->host = g_strdup (TCP_DEFAULT_HOST); + src->server_sock_fd.fd = -1; + src->client_sock_fd.fd = -1; + src->protocol = GST_TCP_PROTOCOL_NONE; + + GST_OBJECT_FLAG_UNSET (src, GST_TCP_SERVER_SRC_OPEN); +} + +static void +gst_tcp_server_src_finalize (GObject * gobject) +{ + GstTCPServerSrc *src = GST_TCP_SERVER_SRC (gobject); + + g_free (src->host); + + G_OBJECT_CLASS (parent_class)->finalize (gobject); +} + +static GstFlowReturn +gst_tcp_server_src_create (GstPushSrc * psrc, GstBuffer ** outbuf) +{ + GstTCPServerSrc *src; + GstFlowReturn ret = GST_FLOW_OK; + + src = GST_TCP_SERVER_SRC (psrc); + + if (!GST_OBJECT_FLAG_IS_SET (src, GST_TCP_SERVER_SRC_OPEN)) + goto wrong_state; + +restart: + if (src->client_sock_fd.fd >= 0) { + /* if we have a client, wait for read */ + gst_poll_fd_ctl_read (src->fdset, &src->server_sock_fd, FALSE); + gst_poll_fd_ctl_read (src->fdset, &src->client_sock_fd, TRUE); + } else { + /* else wait on server socket for connections */ + gst_poll_fd_ctl_read (src->fdset, &src->server_sock_fd, TRUE); + } + + /* no action (0) is an error too in our case */ + if ((ret = gst_poll_wait (src->fdset, GST_CLOCK_TIME_NONE)) <= 0) { + if (ret == -1 && errno == EBUSY) + goto select_cancelled; + else + goto select_error; + } + + /* if we have no client socket we can accept one now */ + if (src->client_sock_fd.fd < 0) { + if (gst_poll_fd_can_read (src->fdset, &src->server_sock_fd)) { + if ((src->client_sock_fd.fd = + accept (src->server_sock_fd.fd, + (struct sockaddr *) &src->client_sin, + &src->client_sin_len)) == -1) + goto accept_error; + + gst_poll_add_fd (src->fdset, &src->client_sock_fd); + } + /* and restart now to poll the socket. */ + goto restart; + } + + GST_LOG_OBJECT (src, "asked for a buffer"); + + switch (src->protocol) { + case GST_TCP_PROTOCOL_NONE: + ret = gst_tcp_read_buffer (GST_ELEMENT (src), src->client_sock_fd.fd, + src->fdset, outbuf); + break; + + case GST_TCP_PROTOCOL_GDP: + if (!src->caps_received) { + GstCaps *caps; + gchar *string; + + ret = gst_tcp_gdp_read_caps (GST_ELEMENT (src), src->client_sock_fd.fd, + src->fdset, &caps); + + if (ret == GST_FLOW_WRONG_STATE) + goto gdp_cancelled; + + if (ret != GST_FLOW_OK) + goto gdp_caps_read_error; + + src->caps_received = TRUE; + string = gst_caps_to_string (caps); + GST_DEBUG_OBJECT (src, "Received caps through GDP: %s", string); + g_free (string); + + gst_pad_set_caps (GST_BASE_SRC_PAD (psrc), caps); + } + + ret = gst_tcp_gdp_read_buffer (GST_ELEMENT (src), src->client_sock_fd.fd, + src->fdset, outbuf); + + if (ret == GST_FLOW_OK) + gst_buffer_set_caps (*outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (src))); + + break; + + default: + /* need to assert as buf == NULL */ + g_assert ("Unhandled protocol type"); + break; + } + + if (ret == GST_FLOW_OK) { + GST_LOG_OBJECT (src, + "Returning buffer from _get of size %d, ts %" + GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT, + GST_BUFFER_SIZE (*outbuf), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (*outbuf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (*outbuf)), + GST_BUFFER_OFFSET (*outbuf), GST_BUFFER_OFFSET_END (*outbuf)); + } + + return ret; + +wrong_state: + { + GST_DEBUG_OBJECT (src, "connection to closed, cannot read data"); + return GST_FLOW_WRONG_STATE; + } +select_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Select error: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +select_cancelled: + { + GST_DEBUG_OBJECT (src, "select canceled"); + return GST_FLOW_WRONG_STATE; + } +accept_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Could not accept client on server socket: %s", g_strerror (errno))); + return GST_FLOW_ERROR; + } +gdp_cancelled: + { + GST_DEBUG_OBJECT (src, "reading gdp canceled"); + return GST_FLOW_WRONG_STATE; + } +gdp_caps_read_error: + { + /* if we did not get canceled, report an error */ + if (ret != GST_FLOW_WRONG_STATE) { + GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), + ("Could not read caps through GDP")); + } + return ret; + } +} + +static void +gst_tcp_server_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTCPServerSrc *tcpserversrc = GST_TCP_SERVER_SRC (object); + + switch (prop_id) { + case PROP_HOST: + if (!g_value_get_string (value)) { + g_warning ("host property cannot be NULL"); + break; + } + g_free (tcpserversrc->host); + tcpserversrc->host = g_strdup (g_value_get_string (value)); + break; + case PROP_PORT: + tcpserversrc->server_port = g_value_get_int (value); + break; + case PROP_PROTOCOL: + tcpserversrc->protocol = g_value_get_enum (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_tcp_server_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTCPServerSrc *tcpserversrc = GST_TCP_SERVER_SRC (object); + + switch (prop_id) { + case PROP_HOST: + g_value_set_string (value, tcpserversrc->host); + break; + case PROP_PORT: + g_value_set_int (value, tcpserversrc->server_port); + break; + case PROP_PROTOCOL: + g_value_set_enum (value, tcpserversrc->protocol); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* set up server */ +static gboolean +gst_tcp_server_src_start (GstBaseSrc * bsrc) +{ + int ret; + GstTCPServerSrc *src = GST_TCP_SERVER_SRC (bsrc); + + /* reset caps_received flag */ + src->caps_received = FALSE; + + /* create the server listener socket */ + if ((src->server_sock_fd.fd = socket (AF_INET, SOCK_STREAM, 0)) == -1) + goto socket_error; + + GST_DEBUG_OBJECT (src, "opened receiving server socket with fd %d", + src->server_sock_fd.fd); + + /* make address reusable */ + ret = 1; + if (setsockopt (src->server_sock_fd.fd, SOL_SOCKET, SO_REUSEADDR, &ret, + sizeof (int)) < 0) + goto sock_opt; + + /* name the socket */ + memset (&src->server_sin, 0, sizeof (src->server_sin)); + src->server_sin.sin_family = AF_INET; /* network socket */ + src->server_sin.sin_port = htons (src->server_port); /* on port */ + if (src->host) { + gchar *host; + + if (!(host = gst_tcp_host_to_ip (GST_ELEMENT (src), src->host))) + goto host_error; + src->server_sin.sin_addr.s_addr = inet_addr (host); + g_free (host); + } else + src->server_sin.sin_addr.s_addr = htonl (INADDR_ANY); + + /* bind it */ + GST_DEBUG_OBJECT (src, "binding server socket to address"); + if ((ret = bind (src->server_sock_fd.fd, (struct sockaddr *) &src->server_sin, + sizeof (src->server_sin))) < 0) + goto bind_error; + + GST_DEBUG_OBJECT (src, "listening on server socket %d with queue of %d", + src->server_sock_fd.fd, TCP_BACKLOG); + + if (listen (src->server_sock_fd.fd, TCP_BACKLOG) == -1) + goto listen_error; + + /* create an fdset to keep track of our file descriptors */ + if ((src->fdset = gst_poll_new (TRUE)) == NULL) + goto socket_pair; + + gst_poll_add_fd (src->fdset, &src->server_sock_fd); + + GST_DEBUG_OBJECT (src, "received client"); + + GST_OBJECT_FLAG_SET (src, GST_TCP_SERVER_SRC_OPEN); + + return TRUE; + + /* ERRORS */ +socket_error: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } +sock_opt: + { + GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), + ("Could not setsockopt: %s", g_strerror (errno))); + gst_tcp_socket_close (&src->server_sock_fd); + return FALSE; + } +host_error: + { + gst_tcp_socket_close (&src->server_sock_fd); + return FALSE; + } +bind_error: + { + gst_tcp_socket_close (&src->server_sock_fd); + switch (errno) { + default: + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("bind failed: %s", g_strerror (errno))); + break; + } + return FALSE; + } +listen_error: + { + gst_tcp_socket_close (&src->server_sock_fd); + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ, (NULL), + ("Could not listen on server socket: %s", g_strerror (errno))); + return FALSE; + } +socket_pair: + { + GST_ELEMENT_ERROR (src, RESOURCE, OPEN_READ_WRITE, (NULL), + GST_ERROR_SYSTEM); + gst_tcp_socket_close (&src->server_sock_fd); + return FALSE; + } +} + +static gboolean +gst_tcp_server_src_stop (GstBaseSrc * bsrc) +{ + GstTCPServerSrc *src = GST_TCP_SERVER_SRC (bsrc); + + gst_poll_free (src->fdset); + src->fdset = NULL; + + gst_tcp_socket_close (&src->server_sock_fd); + gst_tcp_socket_close (&src->client_sock_fd); + + GST_OBJECT_FLAG_UNSET (src, GST_TCP_SERVER_SRC_OPEN); + + return TRUE; +} + +/* will be called only between calls to start() and stop() */ +static gboolean +gst_tcp_server_src_unlock (GstBaseSrc * bsrc) +{ + GstTCPServerSrc *src = GST_TCP_SERVER_SRC (bsrc); + + gst_poll_set_flushing (src->fdset, TRUE); + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.h b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.h new file mode 100644 index 0000000..22c7afe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/gsttcpserversrc.h @@ -0,0 +1,89 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_TCP_SERVER_SRC_H__ +#define __GST_TCP_SERVER_SRC_H__ + +#include +#include + +G_END_DECLS + +#include +#include +#include +#include +#include +#include +#include +#include "gsttcp.h" + +#include + +#define GST_TYPE_TCP_SERVER_SRC \ + (gst_tcp_server_src_get_type()) +#define GST_TCP_SERVER_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TCP_SERVER_SRC,GstTCPServerSrc)) +#define GST_TCP_SERVER_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TCP_SERVER_SRC,GstTCPServerSrcClass)) +#define GST_IS_TCP_SERVER_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TCP_SERVER_SRC)) +#define GST_IS_TCP_SERVER_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TCP_SERVER_SRC)) + +typedef struct _GstTCPServerSrc GstTCPServerSrc; +typedef struct _GstTCPServerSrcClass GstTCPServerSrcClass; + +typedef enum { + GST_TCP_SERVER_SRC_OPEN = (GST_ELEMENT_FLAG_LAST << 0), + + GST_TCP_SERVER_SRC_FLAG_LAST = (GST_ELEMENT_FLAG_LAST << 2) +} GstTCPServerSrcFlags; + +struct _GstTCPServerSrc { + GstPushSrc element; + + /* server information */ + int server_port; + gchar *host; + struct sockaddr_in server_sin; + GstPollFD server_sock_fd; + + /* client information */ + struct sockaddr_in client_sin; + socklen_t client_sin_len; + GstPollFD client_sock_fd; + + GstPoll *fdset; + + GstTCPProtocol protocol; /* protocol used for reading data */ + gboolean caps_received; /* if we have received caps yet */ +}; + +struct _GstTCPServerSrcClass { + GstPushSrcClass parent_class; +}; + +GType gst_tcp_server_src_get_type (void); + +G_BEGIN_DECLS + +#endif /* __GST_TCP_SERVER_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/tcp/tcp.vcproj b/gst-plugins-base-subtitles0.10/gst/tcp/tcp.vcproj new file mode 100644 index 0000000..4573f33 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/tcp/tcp.vcproj @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/typefind/Makefile.am b/gst-plugins-base-subtitles0.10/gst/typefind/Makefile.am new file mode 100644 index 0000000..3258b15 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/typefind/Makefile.am @@ -0,0 +1,26 @@ +plugin_LTLIBRARIES = libgsttypefindfunctions.la + +libgsttypefindfunctions_la_SOURCES = gsttypefindfunctions.c +libgsttypefindfunctions_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CFLAGS) $(GIO_CFLAGS) +libgsttypefindfunctions_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgsttypefindfunctions_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) $(GIO_LIBS) + +libgsttypefindfunctions_la_LIBTOOLFLAGS = --tag=disable-static + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgsttypefindfunctions -:SHARED libgsttypefindfunctions \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgsttypefindfunctions_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgsttypefindfunctions_la_CFLAGS) \ + -:LDFLAGS $(libgsttypefindfunctions_la_LDFLAGS) \ + $(libgsttypefindfunctions_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/typefind/gsttypefindfunctions.c b/gst-plugins-base-subtitles0.10/gst/typefind/gsttypefindfunctions.c new file mode 100644 index 0000000..98dbade --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/typefind/gsttypefindfunctions.c @@ -0,0 +1,4545 @@ +/* GStreamer + * Copyright (C) 2003 Benjamin Otte + * Copyright (C) 2005-2009 Tim-Philipp Müller + * Copyright (C) 2009 Sebastian Dröge + * + * gsttypefindfunctions.c: collection of various typefind functions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +/* don't want to add gio xdgmime typefinder if gio was disabled via configure */ +#ifdef HAVE_GIO +#include +#define USE_GIO +#endif + +#include + +#include +#include +#include + +#include + +GST_DEBUG_CATEGORY_STATIC (type_find_debug); +#define GST_CAT_DEFAULT type_find_debug + +/* DataScanCtx: helper for typefind functions that scan through data + * step-by-step, to avoid doing a peek at each and every offset */ + +#define DATA_SCAN_CTX_CHUNK_SIZE 4096 + +typedef struct +{ + guint64 offset; + const guint8 *data; + gint size; +} DataScanCtx; + +static inline void +data_scan_ctx_advance (GstTypeFind * tf, DataScanCtx * c, guint bytes_to_skip) +{ + c->offset += bytes_to_skip; + if (G_LIKELY (c->size > bytes_to_skip)) { + c->size -= bytes_to_skip; + c->data += bytes_to_skip; + } else { + c->data += c->size; + c->size = 0; + } +} + +static inline gboolean +data_scan_ctx_ensure_data (GstTypeFind * tf, DataScanCtx * c, gint min_len) +{ + const guint8 *data; + guint64 len; + guint chunk_len = MAX (DATA_SCAN_CTX_CHUNK_SIZE, min_len); + + if (G_LIKELY (c->size >= min_len)) + return TRUE; + + data = gst_type_find_peek (tf, c->offset, chunk_len); + if (G_LIKELY (data != NULL)) { + c->data = data; + c->size = chunk_len; + return TRUE; + } + + /* if there's less than our chunk size, try to get as much as we can, but + * always at least min_len bytes (we might be typefinding the first buffer + * of the stream and not have as much data available as we'd like) */ + len = gst_type_find_get_length (tf); + if (len > 0) { + len = CLAMP (len - c->offset, min_len, chunk_len); + } else { + len = min_len; + } + + data = gst_type_find_peek (tf, c->offset, len); + if (data != NULL) { + c->data = data; + c->size = len; + return TRUE; + } + + return FALSE; +} + +static inline gboolean +data_scan_ctx_memcmp (GstTypeFind * tf, DataScanCtx * c, guint offset, + const gchar * data, guint len) +{ + if (!data_scan_ctx_ensure_data (tf, c, offset + len)) + return FALSE; + + return (memcmp (c->data + offset, data, len) == 0); +} + +/*** text/plain ***/ +static gboolean xml_check_first_element (GstTypeFind * tf, + const gchar * element, guint elen, gboolean strict); +static gboolean sdp_check_header (GstTypeFind * tf); + +static GstStaticCaps utf8_caps = GST_STATIC_CAPS ("text/plain"); + +#define UTF8_CAPS gst_static_caps_get(&utf8_caps) + +static gboolean +utf8_type_find_have_valid_utf8_at_offset (GstTypeFind * tf, guint64 offset, + GstTypeFindProbability * prob) +{ + guint8 *data; + + /* randomly decided values */ + guint min_size = 16; /* minimum size */ + guint size = 32 * 1024; /* starting size */ + guint probability = 95; /* starting probability */ + guint step = 10; /* how much we reduce probability in each + * iteration */ + + while (probability > step && size > min_size) { + data = gst_type_find_peek (tf, offset, size); + if (data) { + gchar *end; + gchar *start = (gchar *) data; + + if (g_utf8_validate (start, size, (const gchar **) &end) || (end - start + 4 > size)) { /* allow last char to be cut off */ + *prob = probability; + return TRUE; + } + *prob = 0; + return FALSE; + } + size /= 2; + probability -= step; + } + *prob = 0; + return FALSE; +} + +static void +utf8_type_find (GstTypeFind * tf, gpointer unused) +{ + GstTypeFindProbability start_prob, mid_prob; + guint64 length; + + /* leave xml to the xml typefinders */ + if (xml_check_first_element (tf, "", 0, TRUE)) + return; + + /* leave sdp to the sdp typefinders */ + if (sdp_check_header (tf)) + return; + + /* check beginning of stream */ + if (!utf8_type_find_have_valid_utf8_at_offset (tf, 0, &start_prob)) + return; + + GST_LOG ("start is plain text with probability of %u", start_prob); + + /* POSSIBLE is the highest probability we ever return if we can't + * probe into the middle of the file and don't know its length */ + + length = gst_type_find_get_length (tf); + if (length == 0 || length == (guint64) - 1) { + gst_type_find_suggest (tf, MIN (start_prob, GST_TYPE_FIND_POSSIBLE), + UTF8_CAPS); + return; + } + + if (length < 64 * 1024) { + gst_type_find_suggest (tf, start_prob, UTF8_CAPS); + return; + } + + /* check middle of stream */ + if (!utf8_type_find_have_valid_utf8_at_offset (tf, length / 2, &mid_prob)) + return; + + GST_LOG ("middle is plain text with probability of %u", mid_prob); + gst_type_find_suggest (tf, (start_prob + mid_prob) / 2, UTF8_CAPS); +} + +/*** text/uri-list ***/ + +static GstStaticCaps uri_caps = GST_STATIC_CAPS ("text/uri-list"); + +#define URI_CAPS (gst_static_caps_get(&uri_caps)) +#define BUFFER_SIZE 16 /* If the string is < 16 bytes we're screwed */ +#define INC_BUFFER { \ + pos++; \ + if (pos == BUFFER_SIZE) { \ + pos = 0; \ + offset += BUFFER_SIZE; \ + data = gst_type_find_peek (tf, offset, BUFFER_SIZE); \ + if (data == NULL) return; \ + } else { \ + data++; \ + } \ +} +static void +uri_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, BUFFER_SIZE); + guint pos = 0; + guint offset = 0; + + if (data) { + /* Search for # comment lines */ + while (*data == '#') { + /* Goto end of line */ + while (*data != '\n') { + INC_BUFFER; + } + + INC_BUFFER; + } + + if (!g_ascii_isalpha (*data)) { + /* Had a non alpha char - can't be uri-list */ + return; + } + + INC_BUFFER; + + while (g_ascii_isalnum (*data)) { + INC_BUFFER; + } + + if (*data != ':') { + /* First non alpha char is not a : */ + return; + } + + /* Get the next 2 bytes as well */ + data = gst_type_find_peek (tf, offset + pos, 3); + if (data == NULL) + return; + + if (data[1] != '/' && data[2] != '/') { + return; + } + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, URI_CAPS); + } +} + +/*** application/x-hls ***/ + +static GstStaticCaps hls_caps = GST_STATIC_CAPS ("application/x-hls"); +#define HLS_CAPS (gst_static_caps_get(&hls_caps)) + +/* See http://tools.ietf.org/html/draft-pantos-http-live-streaming-05 */ +static void +hls_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 7))) + return; + + if (memcmp (c.data, "#EXTM3U", 7)) + return; + + data_scan_ctx_advance (tf, &c, 7); + + /* Check only the first 256 bytes */ + while (c.offset < 256) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 21))) + return; + + /* Search for # comment lines */ + if (c.data[0] == '#' && (memcmp (c.data, "#EXT-X-TARGETDURATION", 21) == 0 + || memcmp (c.data, "#EXT-X-STREAM-INF", 17) == 0)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HLS_CAPS); + return; + } + + data_scan_ctx_advance (tf, &c, 1); + } +} + + +/*** application/xml **********************************************************/ + +#define XML_BUFFER_SIZE 16 +#define XML_INC_BUFFER { \ + pos++; \ + if (pos == XML_BUFFER_SIZE) { \ + pos = 0; \ + offset += XML_BUFFER_SIZE; \ + data = gst_type_find_peek (tf, offset, XML_BUFFER_SIZE); \ + if (data == NULL) return FALSE; \ + } else { \ + data++; \ + } \ +} + +static gboolean +xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen, + gboolean strict) +{ + gboolean got_xmldec; + guint8 *data; + guint offset = 0; + guint pos = 0; + + data = gst_type_find_peek (tf, 0, XML_BUFFER_SIZE); + if (!data) + return FALSE; + + /* look for the XMLDec + * see XML spec 2.8, Prolog and Document Type Declaration + * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-prolog-dtd */ + got_xmldec = (memcmp (data, "", 6) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS); + } + } +} + +/*** audio/midi ***/ + +static GstStaticCaps mid_caps = GST_STATIC_CAPS ("audio/midi"); + +#define MID_CAPS gst_static_caps_get(&mid_caps) +static void +mid_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + /* http://jedi.ks.uiuc.edu/~johns/links/music/midifile.html */ + if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h' + && data[3] == 'd') + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MID_CAPS); +} + +/*** audio/mobile-xmf ***/ + +static GstStaticCaps mxmf_caps = GST_STATIC_CAPS ("audio/mobile-xmf"); + +#define MXMF_CAPS gst_static_caps_get(&mxmf_caps) +static void +mxmf_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = NULL; + + /* Search FileId "XMF_" 4 bytes */ + data = gst_type_find_peek (tf, 0, 4); + if (data && data[0] == 'X' && data[1] == 'M' && data[2] == 'F' + && data[3] == '_') { + /* Search Format version "2.00" 4 bytes */ + data = gst_type_find_peek (tf, 4, 4); + if (data && data[0] == '2' && data[1] == '.' && data[2] == '0' + && data[3] == '0') { + /* Search TypeId 2 1 byte */ + data = gst_type_find_peek (tf, 11, 1); + if (data && data[0] == 2) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXMF_CAPS); + } + } + } +} + + +/*** video/x-fli ***/ + +static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli"); + +#define FLX_CAPS gst_static_caps_get(&flx_caps) +static void +flx_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 134); + + if (data) { + /* check magic and the frame type of the first frame */ + if ((data[4] == 0x11 || data[4] == 0x12 || + data[4] == 0x30 || data[4] == 0x44) && + data[5] == 0xaf && + ((data[132] == 0x00 || data[132] == 0xfa) && data[133] == 0xf1)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLX_CAPS); + } + return; + } + data = gst_type_find_peek (tf, 0, 6); + if (data) { + /* check magic only */ + if ((data[4] == 0x11 || data[4] == 0x12 || + data[4] == 0x30 || data[4] == 0x44) && data[5] == 0xaf) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, FLX_CAPS); + } + return; + } +} + +/*** application/x-id3 ***/ + +static GstStaticCaps id3_caps = GST_STATIC_CAPS ("application/x-id3"); + +#define ID3_CAPS gst_static_caps_get(&id3_caps) +static void +id3v2_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 10); + + if (data && memcmp (data, "ID3", 3) == 0 && + data[3] != 0xFF && data[4] != 0xFF && + (data[6] & 0x80) == 0 && (data[7] & 0x80) == 0 && + (data[8] & 0x80) == 0 && (data[9] & 0x80) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS); + } +} + +static void +id3v1_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, -128, 3); + + if (data && memcmp (data, "TAG", 3) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS); + } +} + +/*** application/x-ape ***/ + +static GstStaticCaps apetag_caps = GST_STATIC_CAPS ("application/x-apetag"); + +#define APETAG_CAPS gst_static_caps_get(&apetag_caps) +static void +apetag_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data; + + /* APEv1/2 at start of file */ + data = gst_type_find_peek (tf, 0, 8); + if (data && !memcmp (data, "APETAGEX", 8)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS); + return; + } + + /* APEv1/2 at end of file */ + data = gst_type_find_peek (tf, -32, 8); + if (data && !memcmp (data, "APETAGEX", 8)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, APETAG_CAPS); + return; + } +} + +/*** audio/x-ttafile ***/ + +static GstStaticCaps tta_caps = GST_STATIC_CAPS ("audio/x-ttafile"); + +#define TTA_CAPS gst_static_caps_get(&tta_caps) +static void +tta_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 3); + + if (data) { + if (memcmp (data, "TTA", 3) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TTA_CAPS); + return; + } + } +} + +/*** audio/x-flac ***/ +static GstStaticCaps flac_caps = GST_STATIC_CAPS ("audio/x-flac"); + +#define FLAC_CAPS (gst_static_caps_get(&flac_caps)) + +static void +flac_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4))) + return; + + /* standard flac (also old/broken flac-in-ogg with an initial 4-byte marker + * packet and without the usual packet framing) */ + if (memcmp (c.data, "fLaC", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS); + return; + } + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6))) + return; + + /* flac-in-ogg, see http://flac.sourceforge.net/ogg_mapping.html */ + if (memcmp (c.data, "\177FLAC\001", 6) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, FLAC_CAPS); + return; + } + +/* disabled because it happily typefinds /dev/urandom as audio/x-flac, and + * because I yet have to see header-less flac in the wild */ +#if 0 + /* flac without headers (subset format) */ + /* 64K should be enough */ + while (c.offset < (64 * 1024)) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4))) + break; + + /* look for frame header, + * http://flac.sourceforge.net/format.html#frame_header + */ + if (c.data[0] == 0xff && (c.data[1] >> 2) == 0x3e) { + /* bit 15 in the header must be 0 */ + if (((c.data[1] >> 1) & 0x01) == 0x01) + goto advance; + + /* blocksize must be != 0x00 */ + if ((c.data[2] >> 4) == 0x00) + goto advance; + + /* samplerate must be != 0x0f */ + if ((c.data[2] & 0x0f) == 0x0f) + goto advance; + /* also 0 is invalid, as it means get the info from the header and we + * don't have headers if we are here */ + if ((c.data[2] & 0x0f) == 0x00) + goto advance; + + /* channel assignment must be < 11 */ + if ((c.data[3] >> 4) >= 11) + goto advance; + + /* sample size must be != 0x07 and != 0x05 */ + if (((c.data[3] >> 1) & 0x07) == 0x07) + goto advance; + if (((c.data[3] >> 1) & 0x07) == 0x05) + goto advance; + /* also 0 is invalid, as it means get the info from the header and we + * don't have headers if we are here */ + if (((c.data[3] >> 1) & 0x07) == 0x00) + goto advance; + + /* next bit must be 0 */ + if ((c.data[3] & 0x01) == 0x01) + goto advance; + + /* FIXME: shouldn't we include the crc check ? */ + + GST_DEBUG ("Found flac without headers at %d", (gint) c.offset); + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, FLAC_CAPS); + return; + } + advance: + data_scan_ctx_advance (tf, &c, 1); + } +#endif +} + +/*** audio/mpeg version 2, 4 ***/ + +static GstStaticCaps aac_caps = GST_STATIC_CAPS ("audio/mpeg, " + "mpegversion = (int) { 2, 4 }, framed = (bool) false"); +#define AAC_CAPS (gst_static_caps_get(&aac_caps)) +#define AAC_AMOUNT (4096) +static void +aac_type_find (GstTypeFind * tf, gpointer unused) +{ + /* LUT to convert the AudioObjectType from the ADTS header to a string */ + DataScanCtx c = { 0, NULL, 0 }; + + while (c.offset < AAC_AMOUNT) { + guint snc, len; + + /* detect adts header or adif header. + * The ADIF header is 4 bytes, that should be OK. The ADTS header, on + * the other hand, is 14 bits only, so we require one valid frame with + * again a valid syncpoint on the next one (28 bits) for certainty. We + * require 4 kB, which is quite a lot, since frames are generally 200-400 + * bytes. + * LOAS has 2 possible syncwords, which are 11 bits and 16 bits long. + * The following stream syntax depends on which one is found. + */ + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 6))) + break; + + snc = GST_READ_UINT16_BE (c.data); + if (G_UNLIKELY ((snc & 0xfff6) == 0xfff0)) { + /* ADTS header - find frame length */ + GST_DEBUG ("Found one ADTS syncpoint at offset 0x%" G_GINT64_MODIFIER + "x, tracing next...", c.offset); + len = ((c.data[3] & 0x03) << 11) | + (c.data[4] << 3) | ((c.data[5] & 0xe0) >> 5); + + if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) { + GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len); + goto next; + } + + /* check if there's a second ADTS frame */ + snc = GST_READ_UINT16_BE (c.data + len); + if ((snc & 0xfff6) == 0xfff0) { + GstCaps *caps; + guint mpegversion, sample_freq_idx, channel_config, profile_idx, rate; + guint8 audio_config[2]; + + mpegversion = (c.data[1] & 0x08) ? 2 : 4; + profile_idx = c.data[2] >> 6; + sample_freq_idx = ((c.data[2] & 0x3c) >> 2); + channel_config = ((c.data[2] & 0x01) << 2) + (c.data[3] >> 6); + + GST_DEBUG ("Found second ADTS-%d syncpoint at offset 0x%" + G_GINT64_MODIFIER "x, framelen %u", mpegversion, c.offset, len); + + /* 0xd and 0xe are reserved. 0xf means the sample frequency is directly + * specified in the header, but that's not allowed for ADTS */ + if (sample_freq_idx > 0xc) { + GST_DEBUG ("Unexpected sample frequency index %d or wrong sync", + sample_freq_idx); + goto next; + } + + rate = gst_codec_utils_aac_get_sample_rate_from_index (sample_freq_idx); + GST_LOG ("ADTS: profile=%u, rate=%u", profile_idx, rate); + + /* The ADTS frame header is slightly different from the + * AudioSpecificConfig defined for the MPEG-4 container, so we just + * construct enough of it for getting the level here. */ + /* ADTS counts profiles from 0 instead of 1 to save bits */ + audio_config[0] = (profile_idx + 1) << 3; + audio_config[0] |= (sample_freq_idx >> 1) & 0x7; + audio_config[1] = (sample_freq_idx & 0x1) << 7; + audio_config[1] |= (channel_config & 0xf) << 3; + + caps = gst_caps_new_simple ("audio/mpeg", + "framed", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, mpegversion, + "stream-format", G_TYPE_STRING, "adts", NULL); + + gst_codec_utils_aac_caps_set_level_and_profile (caps, audio_config, 2); + + /* add rate and number of channels if we can */ + if (channel_config != 0 && channel_config <= 7) { + const guint channels_map[] = { 0, 1, 2, 3, 4, 5, 6, 8 }; + + gst_caps_set_simple (caps, "channels", G_TYPE_INT, + channels_map[channel_config], "rate", G_TYPE_INT, rate, NULL); + } + + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, caps); + gst_caps_unref (caps); + break; + } + + GST_DEBUG ("No next frame found... (should have been at 0x%x)", len); + } else if (G_UNLIKELY (((snc & 0xffe0) == 0x56e0) || (snc == 0x4de1))) { + /* LOAS frame */ + + GST_DEBUG ("Found one LOAS syncword at offset 0x%" G_GINT64_MODIFIER + "x, tracing next...", c.offset); + + /* check length of frame for each type of detectable LOAS streams */ + if (snc == 0x4de1) { + /* EPAudioSyncStream */ + len = ((c.data[2] & 0x0f) << 9) | (c.data[3] << 1) | + ((c.data[4] & 0x80) >> 7); + /* add size of EP sync stream header */ + len += 7; + } else { + /* AudioSyncStream */ + len = ((c.data[1] & 0x1f) << 8) | c.data[2]; + /* add size of sync stream header */ + len += 3; + } + + if (len == 0 || !data_scan_ctx_ensure_data (tf, &c, len + 2)) { + GST_DEBUG ("Wrong sync or next frame not within reach, len=%u", len); + goto next; + } + + /* check if there's a second LOAS frame */ + snc = GST_READ_UINT16_BE (c.data + len); + if (((snc & 0xffe0) == 0x56e0) || (snc == 0x4de1)) { + GST_DEBUG ("Found second LOAS syncword at offset 0x%" + G_GINT64_MODIFIER "x, framelen %u", c.offset, len); + + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg", + "framed", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "loas", NULL); + break; + } + + GST_DEBUG ("No next frame found... (should have been at 0x%x)", len); + } else if (!memcmp (c.data, "ADIF", 4)) { + /* ADIF header */ + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, "audio/mpeg", + "framed", G_TYPE_BOOLEAN, FALSE, "mpegversion", G_TYPE_INT, 4, + "stream-format", G_TYPE_STRING, "adif", NULL); + break; + } + + next: + + data_scan_ctx_advance (tf, &c, 1); + } +} + +/*** audio/mpeg version 1 ***/ + +/* + * The chance that random data is identified as a valid mp3 header is 63 / 2^18 + * (0.024%) per try. This makes the function for calculating false positives + * 1 - (1 - ((63 / 2 ^18) ^ GST_MP3_TYPEFIND_MIN_HEADERS)) ^ buffersize) + * This has the following probabilities of false positives: + * datasize MIN_HEADERS + * (bytes) 1 2 3 4 + * 4096 62.6% 0.02% 0% 0% + * 16384 98% 0.09% 0% 0% + * 1 MiB 100% 5.88% 0% 0% + * 1 GiB 100% 100% 1.44% 0% + * 1 TiB 100% 100% 100% 0.35% + * This means that the current choice (3 headers by most of the time 4096 byte + * buffers is pretty safe for now. + * + * The max. size of each frame is 1440 bytes, which means that for N frames to + * be detected, we need 1440 * GST_MP3_TYPEFIND_MIN_HEADERS + 3 bytes of data. + * Assuming we step into the stream right after the frame header, this + * means we need 1440 * (GST_MP3_TYPEFIND_MIN_HEADERS + 1) - 1 + 3 bytes + * of data (5762) to always detect any mp3. + */ + +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] = { {11025, 12000, 8000}, +{22050, 24000, 16000}, +{44100, 48000, 32000} +}; + +static inline guint +mp3_type_frame_length_from_header (guint32 header, guint * put_layer, + guint * put_channels, guint * put_bitrate, guint * put_samplerate, + gboolean * may_be_free_format, gint possible_free_framelen) +{ + guint bitrate, layer, length, mode, samplerate, version, channels; + + if ((header & 0xffe00000) != 0xffe00000) + return 0; + + /* we don't need extension, copyright, original or + * emphasis for the frame length */ + header >>= 6; + + /* mode */ + mode = header & 0x3; + header >>= 3; + + /* padding */ + length = header & 0x1; + header >>= 1; + + /* sampling frequency */ + samplerate = header & 0x3; + if (samplerate == 3) + return 0; + header >>= 2; + + /* bitrate index */ + bitrate = header & 0xF; + if (bitrate == 0 && possible_free_framelen == -1) { + GST_LOG ("Possibly a free format mp3 - signalling"); + *may_be_free_format = TRUE; + } + if (bitrate == 15 || (bitrate == 0 && possible_free_framelen == -1)) + return 0; + + /* ignore error correction, too */ + header >>= 5; + + /* layer */ + layer = 4 - (header & 0x3); + if (layer == 4) + return 0; + header >>= 2; + + /* version 0=MPEG2.5; 2=MPEG2; 3=MPEG1 */ + version = header & 0x3; + if (version == 1) + return 0; + + /* lookup */ + channels = (mode == 3) ? 1 : 2; + samplerate = mp3types_freqs[version > 0 ? version - 1 : 0][samplerate]; + if (bitrate == 0) { + if (layer == 1) { + length *= 4; + length += possible_free_framelen; + bitrate = length * samplerate / 48000; + } else { + length += possible_free_framelen; + bitrate = length * samplerate / + ((layer == 3 && version != 3) ? 72000 : 144000); + } + } else { + /* calculating */ + bitrate = mp3types_bitrates[version == 3 ? 0 : 1][layer - 1][bitrate]; + if (layer == 1) { + length = ((12000 * bitrate / samplerate) + length) * 4; + } else { + length += ((layer == 3 + && version != 3) ? 72000 : 144000) * bitrate / samplerate; + } + } + + GST_LOG ("mp3typefind: calculated mp3 frame length of %u bytes", length); + GST_LOG + ("mp3typefind: samplerate = %u - bitrate = %u - layer = %u - version = %u" + " - channels = %u", samplerate, bitrate, layer, version, channels); + + if (put_layer) + *put_layer = layer; + if (put_channels) + *put_channels = channels; + if (put_bitrate) + *put_bitrate = bitrate; + if (put_samplerate) + *put_samplerate = samplerate; + + return length; +} + + +static GstStaticCaps mp3_caps = GST_STATIC_CAPS ("audio/mpeg, " + "mpegversion = (int) 1, layer = (int) [ 1, 3 ]"); +#define MP3_CAPS (gst_static_caps_get(&mp3_caps)) +/* + * random values for typefinding + * if no more data is available, we will return a probability of + * (found_headers/TRY_HEADERS) * (MAXIMUM * (TRY_SYNC - bytes_skipped) + * / TRY_SYNC) + * if found_headers >= MIN_HEADERS + */ +#define GST_MP3_TYPEFIND_MIN_HEADERS (2) +#define GST_MP3_TYPEFIND_TRY_HEADERS (5) +#define GST_MP3_TYPEFIND_TRY_SYNC (GST_TYPE_FIND_MAXIMUM * 100) /* 10kB */ +#define GST_MP3_TYPEFIND_SYNC_SIZE (2048) +#define GST_MP3_WRONG_HEADER (10) + +static void +mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off, + guint * found_layer, GstTypeFindProbability * found_prob) +{ + guint8 *data = NULL; + guint8 *data_end = NULL; + guint size; + guint64 skipped; + gint last_free_offset = -1; + gint last_free_framelen = -1; + gboolean headerstart = TRUE; + + *found_layer = 0; + *found_prob = 0; + + size = 0; + skipped = 0; + while (skipped < GST_MP3_TYPEFIND_TRY_SYNC) { + if (size <= 0) { + size = GST_MP3_TYPEFIND_SYNC_SIZE * 2; + do { + size /= 2; + data = gst_type_find_peek (tf, skipped + start_off, size); + } while (size > 10 && !data); + if (!data) + break; + data_end = data + size; + } + if (*data == 0xFF) { + guint8 *head_data = NULL; + guint layer = 0, bitrate, samplerate, channels; + guint found = 0; /* number of valid headers found */ + guint64 offset = skipped; + + while (found < GST_MP3_TYPEFIND_TRY_HEADERS) { + guint32 head; + guint length; + guint prev_layer = 0; + guint prev_channels = 0, prev_samplerate = 0; + gboolean free = FALSE; + + if ((gint64) (offset - skipped + 4) >= 0 && + data + offset - skipped + 4 < data_end) { + head_data = data + offset - skipped; + } else { + head_data = gst_type_find_peek (tf, offset + start_off, 4); + } + if (!head_data) + break; + head = GST_READ_UINT32_BE (head_data); + if (!(length = mp3_type_frame_length_from_header (head, &layer, + &channels, &bitrate, &samplerate, &free, + last_free_framelen))) { + if (free) { + if (last_free_offset == -1) + last_free_offset = offset; + else { + last_free_framelen = offset - last_free_offset; + offset = last_free_offset; + continue; + } + } else { + last_free_framelen = -1; + } + + /* Mark the fact that we didn't find a valid header at the beginning */ + if (found == 0) + headerstart = FALSE; + + GST_LOG ("%d. header at offset %" G_GUINT64_FORMAT + " (0x%" G_GINT64_MODIFIER "x) was not an mp3 header " + "(possibly-free: %s)", found + 1, start_off + offset, + start_off + offset, free ? "yes" : "no"); + break; + } + if ((prev_layer && prev_layer != layer) || + /* (prev_bitrate && prev_bitrate != bitrate) || <-- VBR */ + (prev_samplerate && prev_samplerate != samplerate) || + (prev_channels && prev_channels != channels)) { + /* this means an invalid property, or a change, which might mean + * that this is not a mp3 but just a random bytestream. It could + * be a freaking funky encoded mp3 though. We'll just not count + * this header*/ + prev_layer = layer; + prev_channels = channels; + prev_samplerate = samplerate; + } else { + found++; + GST_LOG ("found %d. header at offset %" G_GUINT64_FORMAT " (0x%" + G_GINT64_MODIFIER "X)", found, start_off + offset, + start_off + offset); + } + offset += length; + } + g_assert (found <= GST_MP3_TYPEFIND_TRY_HEADERS); + if (head_data == NULL && + gst_type_find_peek (tf, offset + start_off - 1, 1) == NULL) + /* Incomplete last frame - don't count it. */ + found--; + if (found == GST_MP3_TYPEFIND_TRY_HEADERS || + (found >= GST_MP3_TYPEFIND_MIN_HEADERS && head_data == NULL)) { + /* we can make a valid guess */ + guint probability = found * GST_TYPE_FIND_MAXIMUM * + (GST_MP3_TYPEFIND_TRY_SYNC - skipped) / + GST_MP3_TYPEFIND_TRY_HEADERS / GST_MP3_TYPEFIND_TRY_SYNC; + + if (!headerstart + && probability > (GST_TYPE_FIND_MINIMUM + GST_MP3_WRONG_HEADER)) + probability -= GST_MP3_WRONG_HEADER; + if (probability < GST_TYPE_FIND_MINIMUM) + probability = GST_TYPE_FIND_MINIMUM; + if (start_off > 0) + probability /= 2; + + GST_INFO + ("audio/mpeg calculated %u = %u * %u / %u * (%u - %" + G_GUINT64_FORMAT ") / %u", probability, GST_TYPE_FIND_MAXIMUM, + found, GST_MP3_TYPEFIND_TRY_HEADERS, GST_MP3_TYPEFIND_TRY_SYNC, + (guint64) skipped, GST_MP3_TYPEFIND_TRY_SYNC); + /* make sure we're not id3 tagged */ + head_data = gst_type_find_peek (tf, -128, 3); + if (head_data && (memcmp (head_data, "TAG", 3) == 0)) { + probability = 0; + } + g_assert (probability <= GST_TYPE_FIND_MAXIMUM); + + *found_prob = probability; + if (probability > 0) + *found_layer = layer; + return; + } + } + data++; + skipped++; + size--; + } +} + +static void +mp3_type_find (GstTypeFind * tf, gpointer unused) +{ + GstTypeFindProbability prob, mid_prob; + guint8 *data; + guint layer, mid_layer; + guint64 length; + + mp3_type_find_at_offset (tf, 0, &layer, &prob); + length = gst_type_find_get_length (tf); + + if (length == 0 || length == (guint64) - 1) { + if (prob != 0) + goto suggest; + return; + } + + /* if we're pretty certain already, skip the additional check */ + if (prob >= GST_TYPE_FIND_LIKELY) + goto suggest; + + mp3_type_find_at_offset (tf, length / 2, &mid_layer, &mid_prob); + + if (mid_prob > 0) { + if (prob == 0) { + GST_LOG ("detected audio/mpeg only in the middle (p=%u)", mid_prob); + layer = mid_layer; + prob = mid_prob; + goto suggest; + } + + if (layer != mid_layer) { + GST_WARNING ("audio/mpeg layer discrepancy: %u vs. %u", layer, mid_layer); + return; /* FIXME: or should we just go with the one in the middle? */ + } + + /* detected mpeg audio both in middle of the file and at the start */ + prob = (prob + mid_prob) / 2; + goto suggest; + } + + /* let's see if there's a valid header right at the start */ + data = gst_type_find_peek (tf, 0, 4); /* use min. frame size? */ + if (data && mp3_type_frame_length_from_header (GST_READ_UINT32_BE (data), + &layer, NULL, NULL, NULL, NULL, 0) != 0) { + if (prob == 0) + prob = GST_TYPE_FIND_POSSIBLE - 10; + else + prob = MAX (GST_TYPE_FIND_POSSIBLE - 10, prob + 10); + } + + if (prob > 0) + goto suggest; + + return; + +suggest: + { + g_return_if_fail (layer >= 1 && layer <= 3); + + gst_type_find_suggest_simple (tf, prob, "audio/mpeg", + "mpegversion", G_TYPE_INT, 1, "layer", G_TYPE_INT, layer, NULL); + } +} + +/*** audio/x-musepack ***/ + +static GstStaticCaps musepack_caps = +GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }"); + +#define MUSEPACK_CAPS (gst_static_caps_get(&musepack_caps)) +static void +musepack_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM; + gint streamversion = -1; + + if (data && memcmp (data, "MP+", 3) == 0) { + streamversion = 7; + if ((data[3] & 0x7f) == 7) { + prop = GST_TYPE_FIND_MAXIMUM; + } else { + prop = GST_TYPE_FIND_LIKELY + 10; + } + } else if (data && memcmp (data, "MPCK", 4) == 0) { + streamversion = 8; + prop = GST_TYPE_FIND_MAXIMUM; + } + + if (streamversion != -1) { + gst_type_find_suggest_simple (tf, prop, "audio/x-musepack", + "streamversion", G_TYPE_INT, streamversion, NULL); + } +} + +/*** audio/x-ac3 ***/ +/* FIXME 0.11: should be audio/ac3, but isn't for backwards compatibility */ +static GstStaticCaps ac3_caps = GST_STATIC_CAPS ("audio/x-ac3"); + +#define AC3_CAPS (gst_static_caps_get(&ac3_caps)) + +static GstStaticCaps eac3_caps = GST_STATIC_CAPS ("audio/x-eac3"); + +#define EAC3_CAPS (gst_static_caps_get(&eac3_caps)) + +struct ac3_frmsize +{ + unsigned short bit_rate; + unsigned short frm_size[3]; +}; + +static const struct ac3_frmsize ac3_frmsizecod_tbl[] = { + {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 void +ac3_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + + /* Search for an ac3 frame; not neccesarily right at the start, but give it + * a lower probability if not found right at the start. Check that the + * frame is followed by a second frame at the expected offset. + * We could also check the two ac3 CRCs, but we don't do that right now */ + while (c.offset < 1024) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 5))) + break; + + if (c.data[0] == 0x0b && c.data[1] == 0x77) { + guint bsid = c.data[5] >> 3; + + if (bsid <= 8) { + /* ac3 */ + guint fscod = c.data[4] >> 6; + guint frmsizecod = c.data[4] & 0x3f; + + if (fscod < 3 && frmsizecod < 38) { + DataScanCtx c_next = c; + guint frame_size; + + frame_size = ac3_frmsizecod_tbl[frmsizecod].frm_size[fscod]; + GST_LOG ("possible AC3 frame sync at offset %" + G_GUINT64_FORMAT ", size=%u", c.offset, frame_size); + if (data_scan_ctx_ensure_data (tf, &c_next, (frame_size * 2) + 5)) { + data_scan_ctx_advance (tf, &c_next, frame_size * 2); + + if (c_next.data[0] == 0x0b && c_next.data[1] == 0x77) { + fscod = c_next.data[4] >> 6; + frmsizecod = c_next.data[4] & 0x3f; + + if (fscod < 3 && frmsizecod < 38) { + GstTypeFindProbability prob; + + GST_LOG ("found second AC3 frame (size=%u), looks good", + ac3_frmsizecod_tbl[frmsizecod].frm_size[fscod]); + if (c.offset == 0) + prob = GST_TYPE_FIND_MAXIMUM; + else + prob = GST_TYPE_FIND_NEARLY_CERTAIN; + + gst_type_find_suggest (tf, prob, AC3_CAPS); + return; + } + } else { + GST_LOG ("no second AC3 frame found, false sync"); + } + } + } + } else if (bsid <= 16 && bsid > 10) { + /* eac3 */ + DataScanCtx c_next = c; + guint frame_size; + + frame_size = (((c.data[2] & 0x07) << 8) + c.data[3]) + 1; + GST_LOG ("possible E-AC3 frame sync at offset %" + G_GUINT64_FORMAT ", size=%u", c.offset, frame_size); + if (data_scan_ctx_ensure_data (tf, &c_next, (frame_size * 2) + 5)) { + data_scan_ctx_advance (tf, &c_next, frame_size * 2); + + if (c_next.data[0] == 0x0b && c_next.data[1] == 0x77) { + GstTypeFindProbability prob; + + GST_LOG ("found second E-AC3 frame, looks good"); + if (c.offset == 0) + prob = GST_TYPE_FIND_MAXIMUM; + else + prob = GST_TYPE_FIND_NEARLY_CERTAIN; + + gst_type_find_suggest (tf, prob, EAC3_CAPS); + return; + } else { + GST_LOG ("no second E-AC3 frame found, false sync"); + } + } + } else { + GST_LOG ("invalid AC3 BSID: %u", bsid); + } + } + data_scan_ctx_advance (tf, &c, 1); + } +} + +/*** audio/x-dts ***/ +static GstStaticCaps dts_caps = GST_STATIC_CAPS ("audio/x-dts"); +#define DTS_CAPS (gst_static_caps_get (&dts_caps)) +#define DTS_MIN_FRAMESIZE 96 +#define DTS_MAX_FRAMESIZE 18725 /* 16384*16/14 */ + +static gboolean +dts_parse_frame_header (DataScanCtx * c, guint * frame_size, + guint * sample_rate, guint * channels, guint * depth, guint * endianness) +{ + 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 + }; + guint16 hdr[8]; + guint32 marker; + guint num_blocks, chans, lfe, i; + + marker = GST_READ_UINT32_BE (c->data); + + /* raw big endian or 14-bit big endian */ + if (marker == 0x7FFE8001 || marker == 0x1FFFE800) { + *endianness = G_BIG_ENDIAN; + for (i = 0; i < G_N_ELEMENTS (hdr); ++i) + hdr[i] = GST_READ_UINT16_BE (c->data + (i * sizeof (guint16))); + } else + /* raw little endian or 14-bit little endian */ + if (marker == 0xFE7F0180 || marker == 0xFF1F00E8) { + *endianness = G_LITTLE_ENDIAN; + for (i = 0; i < G_N_ELEMENTS (hdr); ++i) + hdr[i] = GST_READ_UINT16_LE (c->data + (i * sizeof (guint16))); + } else { + return FALSE; + } + + GST_LOG ("dts sync marker 0x%08x at offset %u", marker, (guint) c->offset); + + /* 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); + *depth = 14; + } else { + *depth = 16; + } + + GST_LOG ("frame header: %04x%04x%04x%04x", hdr[2], hdr[3], hdr[4], hdr[5]); + + num_blocks = (hdr[2] >> 2) & 0x7F; + *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; + + if (num_blocks < 5 || *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; + + return TRUE; +} + +static void +dts_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + + /* Search for an dts frame; not neccesarily right at the start, but give it + * a lower probability if not found right at the start. Check that the + * frame is followed by a second frame at the expected offset. */ + while (c.offset <= DTS_MAX_FRAMESIZE) { + guint frame_size = 0, rate = 0, chans = 0, depth = 0, endianness = 0; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, DTS_MIN_FRAMESIZE))) + return; + + if (G_UNLIKELY (dts_parse_frame_header (&c, &frame_size, &rate, &chans, + &depth, &endianness))) { + GstTypeFindProbability prob; + DataScanCtx next_c; + + prob = (c.offset == 0) ? GST_TYPE_FIND_LIKELY : GST_TYPE_FIND_POSSIBLE; + + /* check for second frame sync */ + next_c = c; + data_scan_ctx_advance (tf, &next_c, frame_size); + if (data_scan_ctx_ensure_data (tf, &next_c, 4)) { + GST_LOG ("frame size: %u 0x%04x", frame_size, frame_size); + GST_MEMDUMP ("second frame sync", next_c.data, 4); + if (GST_READ_UINT32_BE (c.data) == GST_READ_UINT32_BE (next_c.data)) + prob = GST_TYPE_FIND_MAXIMUM; + } + + if (chans > 0) { + gst_type_find_suggest_simple (tf, prob, "audio/x-dts", + "rate", G_TYPE_INT, rate, "channels", G_TYPE_INT, chans, + "depth", G_TYPE_INT, depth, "endianness", G_TYPE_INT, endianness, + "framed", G_TYPE_BOOLEAN, FALSE, NULL); + } else { + gst_type_find_suggest_simple (tf, prob, "audio/x-dts", + "rate", G_TYPE_INT, rate, "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, endianness, + "framed", G_TYPE_BOOLEAN, FALSE, NULL); + } + + return; + } + + data_scan_ctx_advance (tf, &c, 1); + } +} + +/*** gsm ***/ + +/* can only be detected by using the extension, in which case we use the default + * GSM properties */ +static GstStaticCaps gsm_caps = +GST_STATIC_CAPS ("audio/x-gsm, rate=8000, channels=1"); + +#define GSM_CAPS (gst_static_caps_get(&gsm_caps)) + +/*** wavpack ***/ + +static GstStaticCaps wavpack_caps = +GST_STATIC_CAPS ("audio/x-wavpack, framed = (boolean) false"); + +#define WAVPACK_CAPS (gst_static_caps_get(&wavpack_caps)) + +static GstStaticCaps wavpack_correction_caps = +GST_STATIC_CAPS ("audio/x-wavpack-correction, framed = (boolean) false"); + +#define WAVPACK_CORRECTION_CAPS (gst_static_caps_get(&wavpack_correction_caps)) + +static void +wavpack_type_find (GstTypeFind * tf, gpointer unused) +{ + guint64 offset; + guint32 blocksize; + guint8 *data; + + data = gst_type_find_peek (tf, 0, 32); + if (!data) + return; + + if (data[0] != 'w' || data[1] != 'v' || data[2] != 'p' || data[3] != 'k') + return; + + /* Note: wavpack blocks can be fairly large (easily 60-110k), possibly + * larger than the max. limits imposed by certain typefinding elements + * like id3demux or apedemux, so typefinding is most likely only going to + * work in pull-mode */ + blocksize = GST_READ_UINT32_LE (data + 4); + GST_LOG ("wavpack header, blocksize=0x%04x", blocksize); + offset = 32; + while (offset < 32 + blocksize) { + guint32 sublen; + + /* get chunk header */ + GST_LOG ("peeking at chunk at offset 0x%04x", (guint) offset); + data = gst_type_find_peek (tf, offset, 4); + if (data == NULL) + break; + sublen = ((guint32) data[1]) << 1; + if (data[0] & 0x80) { + sublen |= (((guint32) data[2]) << 9) | (((guint32) data[3]) << 17); + sublen += 1 + 3; /* id + length */ + } else { + sublen += 1 + 1; /* id + length */ + } + if (sublen > blocksize - offset + 32) { + GST_LOG ("chunk length too big (%u > %" G_GUINT64_FORMAT ")", sublen, + blocksize - offset); + break; + } + if ((data[0] & 0x20) == 0) { + switch (data[0] & 0x0f) { + case 0xa: /* ID_WV_BITSTREAM */ + case 0xc: /* ID_WVX_BITSTREAM */ + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, WAVPACK_CAPS); + return; + case 0xb: /* ID_WVC_BITSTREAM */ + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, + WAVPACK_CORRECTION_CAPS); + return; + default: + break; + } + } + offset += sublen; + } +} + +/*** application/postscrip ***/ +static GstStaticCaps postscript_caps = +GST_STATIC_CAPS ("application/postscript"); + +#define POSTSCRIPT_CAPS (gst_static_caps_get(&postscript_caps)) + +static void +postscript_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 3); + if (!data) + return; + + if (data[0] == 0x04) + data++; + if (data[0] == '%' && data[1] == '!') + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, POSTSCRIPT_CAPS); + +} + +/*** image/svg+xml ***/ +static GstStaticCaps svg_caps = GST_STATIC_CAPS ("image/svg+xml"); + +#define SVG_CAPS (gst_static_caps_get(&svg_caps)) + +static void +svg_type_find (GstTypeFind * tf, gpointer unused) +{ + static const gchar svg_doctype[] = "!DOCTYPE svg"; + static const gchar svg_tag[] = "--[\r]\n + * [\r]\nContent-type:[\r]\n */ +static void +multipart_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data; + guint8 *x; + +#define MULTIPART_MAX_BOUNDARY_OFFSET 16 + data = gst_type_find_peek (tf, 0, MULTIPART_MAX_BOUNDARY_OFFSET); + if (!data) + return; + + for (x = data; + x - data < MULTIPART_MAX_BOUNDARY_OFFSET - 2 && g_ascii_isspace (*x); + x++); + if (x[0] != '-' || x[1] != '-') + return; + + /* Could be okay, peek what should be enough for a complete header */ +#define MULTIPART_MAX_HEADER_SIZE 256 + data = gst_type_find_peek (tf, 0, MULTIPART_MAX_HEADER_SIZE); + if (!data) + return; + + for (x = data; x - data < MULTIPART_MAX_HEADER_SIZE - 14; x++) { + if (!isascii (*x)) { + return; + } + if (*x == '\n' && + !g_ascii_strncasecmp ("content-type:", (gchar *) x + 1, 13)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MULTIPART_CAPS); + return; + } + } +} + +/*** video/mpeg systemstream ***/ +static GstStaticCaps mpeg_sys_caps = GST_STATIC_CAPS ("video/mpeg, " + "systemstream = (boolean) true, mpegversion = (int) [ 1, 2 ]"); + +#define MPEG_SYS_CAPS gst_static_caps_get(&mpeg_sys_caps) +#define IS_MPEG_HEADER(data) (G_UNLIKELY((((guint8 *)(data))[0] == 0x00) && \ + (((guint8 *)(data))[1] == 0x00) && \ + (((guint8 *)(data))[2] == 0x01))) + +#define IS_MPEG_PACK_CODE(b) ((b) == 0xBA) +#define IS_MPEG_SYS_CODE(b) ((b) == 0xBB) +#define IS_MPEG_PACK_HEADER(data) (IS_MPEG_HEADER (data) && \ + IS_MPEG_PACK_CODE (((guint8 *)(data))[3])) + +#define IS_MPEG_PES_CODE(b) (((b) & 0xF0) == 0xE0 || ((b) & 0xF0) == 0xC0 || \ + (b) >= 0xBD) +#define IS_MPEG_PES_HEADER(data) (IS_MPEG_HEADER (data) && \ + IS_MPEG_PES_CODE (((guint8 *)(data))[3])) + +#define MPEG2_MAX_PROBE_LENGTH (128 * 1024) /* 128kB should be 64 packs of the + * most common 2kB pack size. */ + +#define MPEG2_MIN_SYS_HEADERS 2 +#define MPEG2_MAX_SYS_HEADERS 5 + +static gboolean +mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len, + guint * pack_size) +{ + /* Check the pack header @ offset for validity, assuming that the 4 byte header + * itself has already been checked. */ + guint8 stuff_len; + + if (len < 12) + return FALSE; + + /* Check marker bits */ + if ((data[4] & 0xC4) == 0x44) { + /* MPEG-2 PACK */ + if (len < 14) + return FALSE; + + if ((data[6] & 0x04) != 0x04 || + (data[8] & 0x04) != 0x04 || + (data[9] & 0x01) != 0x01 || (data[12] & 0x03) != 0x03) + return FALSE; + + stuff_len = data[13] & 0x07; + + /* Check the following header bytes, if we can */ + if ((14 + stuff_len + 4) <= len) { + if (!IS_MPEG_HEADER (data + 14 + stuff_len)) + return FALSE; + } + if (pack_size) + *pack_size = 14 + stuff_len; + return TRUE; + } else if ((data[4] & 0xF1) == 0x21) { + /* MPEG-1 PACK */ + if ((data[6] & 0x01) != 0x01 || + (data[8] & 0x01) != 0x01 || + (data[9] & 0x80) != 0x80 || (data[11] & 0x01) != 0x01) + return FALSE; + + /* Check the following header bytes, if we can */ + if ((12 + 4) <= len) { + if (!IS_MPEG_HEADER (data + 12)) + return FALSE; + } + if (pack_size) + *pack_size = 12; + return TRUE; + } + + return FALSE; +} + +static gboolean +mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len, + guint * pack_size) +{ + guint pes_packet_len; + + /* Check the PES header at the given position, assuming the header code itself + * was already checked */ + if (len < 6) + return FALSE; + + /* For MPEG Program streams, unbounded PES is not allowed, so we must have a + * valid length present */ + pes_packet_len = GST_READ_UINT16_BE (data + 4); + if (pes_packet_len == 0) + return FALSE; + + /* Check the following header, if we can */ + if (6 + pes_packet_len + 4 <= len) { + if (!IS_MPEG_HEADER (data + 6 + pes_packet_len)) + return FALSE; + } + + if (pack_size) + *pack_size = 6 + pes_packet_len; + return TRUE; +} + +static gboolean +mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len, + guint * pack_size) +{ + guint sys_hdr_len; + + /* Check the System header at the given position, assuming the header code itself + * was already checked */ + if (len < 6) + return FALSE; + sys_hdr_len = GST_READ_UINT16_BE (data + 4); + if (sys_hdr_len < 6) + return FALSE; + + /* Check the following header, if we can */ + if (6 + sys_hdr_len + 4 <= len) { + if (!IS_MPEG_HEADER (data + 6 + sys_hdr_len)) + return FALSE; + } + + if (pack_size) + *pack_size = 6 + sys_hdr_len; + + return TRUE; +} + +/* calculation of possibility to identify random data as mpeg systemstream: + * bits that must match in header detection: 32 (or more) + * chance that random data is identifed: 1/2^32 + * chance that MPEG2_MIN_PACK_HEADERS headers are identified: + * 1/2^(32*MPEG2_MIN_PACK_HEADERS) + * chance that this happens in MPEG2_MAX_PROBE_LENGTH bytes: + * 1-(1+1/2^(32*MPEG2_MIN_PACK_HEADERS)^MPEG2_MAX_PROBE_LENGTH) + * for current values: + * 1-(1+1/2^(32*4)^101024) + * = + * Since we also check marker bits and pes packet lengths, this probability is a + * very coarse upper bound. + */ +static void +mpeg_sys_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data, *data0, *first_sync, *end; + gint mpegversion = 0; + guint pack_headers = 0; + guint pes_headers = 0; + guint pack_size; + guint since_last_sync = 0; + guint32 sync_word = 0xffffffff; + + G_STMT_START { + gint len; + + len = MPEG2_MAX_PROBE_LENGTH; + do { + len = len / 2; + data = gst_type_find_peek (tf, 0, 5 + len); + } while (data == NULL && len >= 32); + + if (!data) + return; + + end = data + len; + } + G_STMT_END; + + data0 = data; + first_sync = NULL; + + while (data < end) { + sync_word <<= 8; + if (sync_word == 0x00000100) { + /* Found potential sync word */ + if (first_sync == NULL) + first_sync = data - 3; + + if (since_last_sync > 4) { + /* If more than 4 bytes since the last sync word, reset our counters, + * as we're only interested in counting contiguous packets */ + pes_headers = pack_headers = 0; + } + pack_size = 0; + + if (IS_MPEG_PACK_CODE (data[0])) { + if ((data[1] & 0xC0) == 0x40) { + /* MPEG-2 */ + mpegversion = 2; + } else if ((data[1] & 0xF0) == 0x20) { + mpegversion = 1; + } + if (mpegversion != 0 && + mpeg_sys_is_valid_pack (tf, data - 3, end - data + 3, &pack_size)) { + pack_headers++; + } + } else if (IS_MPEG_PES_CODE (data[0])) { + /* PES stream */ + if (mpeg_sys_is_valid_pes (tf, data - 3, end - data + 3, &pack_size)) { + pes_headers++; + if (mpegversion == 0) + mpegversion = 2; + } + } else if (IS_MPEG_SYS_CODE (data[0])) { + if (mpeg_sys_is_valid_sys (tf, data - 3, end - data + 3, &pack_size)) { + pack_headers++; + } + } + + /* If we found a packet with a known size, skip the bytes in it and loop + * around to check the next packet. */ + if (pack_size != 0) { + data += pack_size - 3; + sync_word = 0xffffffff; + since_last_sync = 0; + continue; + } + } + + sync_word |= data[0]; + since_last_sync++; + data++; + + /* If we have found MAX headers, and *some* were pes headers (pack headers + * are optional in an mpeg system stream) then return our high-probability + * result */ + if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MAX_SYS_HEADERS) + goto suggest; + } + + /* If we at least saw MIN headers, and *some* were pes headers (pack headers + * are optional in an mpeg system stream) then return a lower-probability + * result */ + if (pes_headers > 0 && (pack_headers + pes_headers) > MPEG2_MIN_SYS_HEADERS) + goto suggest; + + return; +suggest: + { + guint prob; + + prob = GST_TYPE_FIND_POSSIBLE + (10 * (pack_headers + pes_headers)); + prob = MIN (prob, GST_TYPE_FIND_MAXIMUM); + + /* lower probability if the first packet wasn't right at the start */ + if (data0 != first_sync && prob >= 10) + prob -= 10; + + GST_LOG ("Suggesting MPEG %d system stream, %d packs, %d pes, prob %u%%\n", + mpegversion, pack_headers, pes_headers, prob); + + gst_type_find_suggest_simple (tf, prob, "video/mpeg", + "systemstream", G_TYPE_BOOLEAN, TRUE, + "mpegversion", G_TYPE_INT, mpegversion, NULL); + } +}; + +/*** video/mpegts Transport Stream ***/ +static GstStaticCaps mpegts_caps = GST_STATIC_CAPS ("video/mpegts, " + "systemstream = (boolean) true, packetsize = (int) [ 188, 208 ]"); +#define MPEGTS_CAPS gst_static_caps_get(&mpegts_caps) + +#define GST_MPEGTS_TYPEFIND_MIN_HEADERS 4 +#define GST_MPEGTS_TYPEFIND_MAX_HEADERS 10 +#define GST_MPEGTS_MAX_PACKET_SIZE 208 +#define GST_MPEGTS_TYPEFIND_SYNC_SIZE \ + (GST_MPEGTS_TYPEFIND_MIN_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE) +#define GST_MPEGTS_TYPEFIND_MAX_SYNC \ + (GST_MPEGTS_TYPEFIND_MAX_HEADERS * GST_MPEGTS_MAX_PACKET_SIZE) +#define GST_MPEGTS_TYPEFIND_SCAN_LENGTH \ + (GST_MPEGTS_TYPEFIND_MAX_SYNC * 4) + +#define MPEGTS_HDR_SIZE 4 +/* Check for sync byte, error_indicator == 0 and packet has payload */ +#define IS_MPEGTS_HEADER(data) (((data)[0] == 0x47) && \ + (((data)[1] & 0x80) == 0x00) && \ + (((data)[3] & 0x30) != 0x00)) + +/* Helper function to search ahead at intervals of packet_size for mpegts + * headers */ +static gint +mpeg_ts_probe_headers (GstTypeFind * tf, guint64 offset, gint packet_size) +{ + /* We always enter this function having found at least one header already */ + gint found = 1; + guint8 *data = NULL; + + GST_LOG ("looking for mpeg-ts packets of size %u", packet_size); + while (found < GST_MPEGTS_TYPEFIND_MAX_HEADERS) { + offset += packet_size; + + data = gst_type_find_peek (tf, offset, MPEGTS_HDR_SIZE); + if (data == NULL || !IS_MPEGTS_HEADER (data)) + return found; + + found++; + GST_LOG ("mpeg-ts sync #%2d at offset %" G_GUINT64_FORMAT, found, offset); + } + + return found; +} + +/* Try and detect at least 4 packets in at most 10 packets worth of + * data. Need to try several possible packet sizes */ +static void +mpeg_ts_type_find (GstTypeFind * tf, gpointer unused) +{ + /* TS packet sizes to test: normal, DVHS packet size and + * FEC with 16 or 20 byte codes packet size. */ + const gint pack_sizes[] = { 188, 192, 204, 208 }; + + guint8 *data = NULL; + guint size = 0; + guint64 skipped = 0; + + while (skipped < GST_MPEGTS_TYPEFIND_SCAN_LENGTH) { + if (size < MPEGTS_HDR_SIZE) { + data = gst_type_find_peek (tf, skipped, GST_MPEGTS_TYPEFIND_SYNC_SIZE); + if (!data) + break; + size = GST_MPEGTS_TYPEFIND_SYNC_SIZE; + } + + /* Have at least MPEGTS_HDR_SIZE bytes at this point */ + if (IS_MPEGTS_HEADER (data)) { + gint p; + + GST_LOG ("possible mpeg-ts sync at offset %" G_GUINT64_FORMAT, skipped); + + for (p = 0; p < G_N_ELEMENTS (pack_sizes); p++) { + gint found; + + /* Probe ahead at size pack_sizes[p] */ + found = mpeg_ts_probe_headers (tf, skipped, pack_sizes[p]); + if (found >= GST_MPEGTS_TYPEFIND_MIN_HEADERS) { + gint probability; + + /* found at least 4 headers. 10 headers = MAXIMUM probability. + * Arbitrarily, I assigned 10% probability for each header we + * found, 40% -> 100% */ + probability = MIN (10 * found, GST_TYPE_FIND_MAXIMUM); + + gst_type_find_suggest_simple (tf, probability, "video/mpegts", + "systemstream", G_TYPE_BOOLEAN, TRUE, + "packetsize", G_TYPE_INT, pack_sizes[p], NULL); + return; + } + } + } + data++; + skipped++; + size--; + } +} + +#define GST_MPEGVID_TYPEFIND_TRY_PICTURES 6 +#define GST_MPEGVID_TYPEFIND_TRY_SYNC (100 * 1024) /* 100 kB */ + +/* Scan ahead a maximum of max_extra_offset bytes until the next IS_MPEG_HEADER + * offset. After the call, offset will be after the 0x000001, i.e. at the 4th + * byte of the MPEG header. Returns TRUE if a header was found, FALSE if not. + */ +static gboolean +mpeg_find_next_header (GstTypeFind * tf, DataScanCtx * c, + guint64 max_extra_offset) +{ + guint64 extra_offset; + + for (extra_offset = 0; extra_offset <= max_extra_offset; ++extra_offset) { + if (!data_scan_ctx_ensure_data (tf, c, 4)) + return FALSE; + if (IS_MPEG_HEADER (c->data)) { + data_scan_ctx_advance (tf, c, 3); + return TRUE; + } + data_scan_ctx_advance (tf, c, 1); + } + return FALSE; +} + +/*** video/mpeg MPEG-4 elementary video stream ***/ + +static GstStaticCaps mpeg4_video_caps = GST_STATIC_CAPS ("video/mpeg, " + "systemstream=(boolean)false, mpegversion=4, parsed=(boolean)false"); +#define MPEG4_VIDEO_CAPS gst_static_caps_get(&mpeg4_video_caps) + +/* + * This typefind is based on the elementary video header defined in + * http://xhelmboyx.tripod.com/formats/mpeg-layout.txt + * In addition, it allows the visual object sequence header to be + * absent, and even the VOS header to be absent. In the latter case, + * a number of VOPs have to be present. + */ +static void +mpeg4_video_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + gboolean seen_vios_at_0 = FALSE; + gboolean seen_vios = FALSE; + gboolean seen_vos = FALSE; + gboolean seen_vol = FALSE; + guint num_vop_headers = 0; + guint8 sc; + + while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) { + if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) + break; + + if (!mpeg_find_next_header (tf, &c, + GST_MPEGVID_TYPEFIND_TRY_SYNC - c.offset)) + break; + + sc = c.data[0]; + + /* visual_object_sequence_start_code */ + if (sc == 0xB0) { + if (seen_vios) + break; /* Terminate at second vios */ + if (c.offset == 0) + seen_vios_at_0 = TRUE; + seen_vios = TRUE; + data_scan_ctx_advance (tf, &c, 2); + if (!mpeg_find_next_header (tf, &c, 0)) + break; + + sc = c.data[0]; + + /* Optional metadata */ + if (sc == 0xB2) + if (!mpeg_find_next_header (tf, &c, 24)) + break; + } + + /* visual_object_start_code (consider it optional) */ + if (sc == 0xB5) { + data_scan_ctx_advance (tf, &c, 2); + /* may contain ID marker and YUV clamping */ + if (!mpeg_find_next_header (tf, &c, 7)) + break; + + sc = c.data[0]; + } + + /* video_object_start_code */ + if (sc <= 0x1F) { + if (seen_vos) + break; /* Terminate at second vos */ + seen_vos = TRUE; + data_scan_ctx_advance (tf, &c, 2); + continue; + } + + /* video_object_layer_start_code */ + if (sc >= 0x20 && sc <= 0x2F) { + seen_vol = TRUE; + data_scan_ctx_advance (tf, &c, 5); + continue; + } + + /* video_object_plane_start_code */ + if (sc == 0xB6) { + num_vop_headers++; + data_scan_ctx_advance (tf, &c, 2); + continue; + } + + /* Unknown start code. */ + } + + if (num_vop_headers > 0 || seen_vol) { + GstTypeFindProbability probability = 0; + + GST_LOG ("Found %d pictures, vios: %d, vos:%d, vol:%d", num_vop_headers, + seen_vios, seen_vos, seen_vol); + + if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vios_at_0 + && seen_vos && seen_vol) + probability = GST_TYPE_FIND_MAXIMUM - 1; + else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vios + && seen_vos && seen_vol) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1; + else if (seen_vios_at_0 && seen_vos && seen_vol) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 6; + else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vos + && seen_vol) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 6; + else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_vol) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9; + else if (num_vop_headers >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) + probability = GST_TYPE_FIND_LIKELY - 1; + else if (num_vop_headers > 2 && seen_vios && seen_vos && seen_vol) + probability = GST_TYPE_FIND_LIKELY - 9; + else if (seen_vios && seen_vos && seen_vol) + probability = GST_TYPE_FIND_LIKELY - 20; + else if (num_vop_headers > 0 && seen_vos && seen_vol) + probability = GST_TYPE_FIND_POSSIBLE; + else if (num_vop_headers > 0) + probability = GST_TYPE_FIND_POSSIBLE - 10; + else if (seen_vos && seen_vol) + probability = GST_TYPE_FIND_POSSIBLE - 20; + + gst_type_find_suggest (tf, probability, MPEG4_VIDEO_CAPS); + } +} + +/*** video/x-h263 H263 video stream ***/ +static GstStaticCaps h263_video_caps = GST_STATIC_CAPS ("video/x-h263"); + +#define H263_VIDEO_CAPS gst_static_caps_get(&h263_video_caps) + +#define H263_MAX_PROBE_LENGTH (128 * 1024) + +static void +h263_video_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + guint64 data = 0; + guint64 psc = 0; + guint8 tr = 0; + guint format; + guint good = 0; + guint bad = 0; + + while (c.offset < H263_MAX_PROBE_LENGTH) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4))) + break; + + /* Find the picture start code */ + data = (data << 8) + c.data[0]; + psc = data & G_GUINT64_CONSTANT (0xfffffc0000); + if (psc == 0x800000) { + /* Found PSC */ + /* TR */ + tr = (data & 0x3fc) >> 2; + /* Source Format */ + format = tr & 0x07; + + /* Now that we have a Valid PSC, check if we also have a valid PTYPE and + the Source Format, which should range between 1 and 5 */ + if (((tr >> 6) == 0x2) && (format > 0 && format < 6)) + good++; + else + bad++; + + /* FIXME: maybe bail out early if we get mostly bad syncs ? */ + } + + data_scan_ctx_advance (tf, &c, 1); + } + + if (good > 0 && bad == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H263_VIDEO_CAPS); + else if (good > 2 * bad) + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H263_VIDEO_CAPS); + + return; +} + +/*** video/x-h264 H264 elementary video stream ***/ + +static GstStaticCaps h264_video_caps = +GST_STATIC_CAPS ("video/x-h264,stream-format=byte-stream"); + +#define H264_VIDEO_CAPS gst_static_caps_get(&h264_video_caps) + +#define H264_MAX_PROBE_LENGTH (128 * 1024) /* 128kB for HD should be enough. */ + +static void +h264_video_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + + /* Stream consists of: a series of sync codes (00 00 00 01) followed + * by NALs + */ + int nut, ref; + int good = 0; + int bad = 0; + + while (c.offset < H264_MAX_PROBE_LENGTH) { + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 4))) + break; + + if (IS_MPEG_HEADER (c.data)) { + nut = c.data[3] & 0x9f; /* forbiden_zero_bit | nal_unit_type */ + ref = c.data[3] & 0x60; /* nal_ref_idc */ + + /* if forbiden bit is different to 0 won't be h264 */ + if (nut > 0x1f) { + bad++; + break; + } + + /* collect statistics about the NAL types */ + if ((nut >= 1 && nut <= 13) || nut == 19) { + if ((nut == 5 && ref == 0) || + ((nut == 6 || (nut >= 9 && nut <= 12)) && ref != 0)) { + bad++; + } else { + good++; + } + } else if (nut >= 14 && nut <= 33) { + /* reserved */ + /* Theoretically these are good, since if they exist in the + stream it merely means that a newer backwards-compatible + h.264 stream. But we should be identifying that separately. */ + bad++; + } else { + /* unspecified, application specific */ + /* don't consider these bad */ + } + + GST_DEBUG ("good %d bad %d", good, bad); + + if (good >= 10 && bad < 4) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, H264_VIDEO_CAPS); + return; + } + + data_scan_ctx_advance (tf, &c, 4); + } + data_scan_ctx_advance (tf, &c, 1); + } + + if (good >= 2 && bad < 1) { + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, H264_VIDEO_CAPS); + return; + } +} + +/*** video/mpeg video stream ***/ + +static GstStaticCaps mpeg_video_caps = GST_STATIC_CAPS ("video/mpeg, " + "systemstream = (boolean) false"); +#define MPEG_VIDEO_CAPS gst_static_caps_get(&mpeg_video_caps) + +/* + * Idea is the same as MPEG system stream typefinding: We check each + * byte of the stream to see if - from that point on - the stream + * matches a predefined set of marker bits as defined in the MPEG + * video specs. + * + * I'm sure someone will do a chance calculation here too. + */ + +static void +mpeg_video_stream_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + gboolean seen_seq_at_0 = FALSE; + gboolean seen_seq = FALSE; + gboolean seen_gop = FALSE; + guint64 last_pic_offset = 0; + guint num_pic_headers = 0; + gint found = 0; + + while (c.offset < GST_MPEGVID_TYPEFIND_TRY_SYNC) { + if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) + break; + + if (!data_scan_ctx_ensure_data (tf, &c, 5)) + break; + + if (!IS_MPEG_HEADER (c.data)) + goto next; + + /* a pack header indicates that this isn't an elementary stream */ + if (c.data[3] == 0xBA && mpeg_sys_is_valid_pack (tf, c.data, c.size, NULL)) + return; + + /* do we have a sequence header? */ + if (c.data[3] == 0xB3) { + seen_seq_at_0 = seen_seq_at_0 || (c.offset == 0); + seen_seq = TRUE; + data_scan_ctx_advance (tf, &c, 4 + 8); + continue; + } + + /* or a GOP header */ + if (c.data[3] == 0xB8) { + seen_gop = TRUE; + data_scan_ctx_advance (tf, &c, 8); + continue; + } + + /* but what we'd really like to see is a picture header */ + if (c.data[3] == 0x00) { + ++num_pic_headers; + last_pic_offset = c.offset; + data_scan_ctx_advance (tf, &c, 8); + continue; + } + + /* ... each followed by a slice header with slice_vertical_pos=1 that's + * not too far away from the previously seen picture header. */ + if (c.data[3] == 0x01 && num_pic_headers > found && + (c.offset - last_pic_offset) >= 4 && + (c.offset - last_pic_offset) <= 64) { + data_scan_ctx_advance (tf, &c, 4); + found += 1; + continue; + } + + next: + + data_scan_ctx_advance (tf, &c, 1); + } + + if (found > 0 || seen_seq) { + GstTypeFindProbability probability = 0; + + GST_LOG ("Found %d pictures, seq:%d, gop:%d", found, seen_seq, seen_gop); + + if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq && seen_gop) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 1; + else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES && seen_seq) + probability = GST_TYPE_FIND_NEARLY_CERTAIN - 9; + else if (found >= GST_MPEGVID_TYPEFIND_TRY_PICTURES) + probability = GST_TYPE_FIND_LIKELY; + else if (seen_seq_at_0 && seen_gop && found > 2) + probability = GST_TYPE_FIND_LIKELY - 10; + else if (seen_seq && seen_gop && found > 2) + probability = GST_TYPE_FIND_LIKELY - 20; + else if (seen_seq_at_0 && found > 0) + probability = GST_TYPE_FIND_POSSIBLE; + else if (seen_seq && found > 0) + probability = GST_TYPE_FIND_POSSIBLE - 5; + else if (found > 0) + probability = GST_TYPE_FIND_POSSIBLE - 10; + else if (seen_seq) + probability = GST_TYPE_FIND_POSSIBLE - 20; + + gst_type_find_suggest_simple (tf, probability, "video/mpeg", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "mpegversion", G_TYPE_INT, 1, NULL); + } +} + +/*** audio/x-aiff ***/ + +static GstStaticCaps aiff_caps = GST_STATIC_CAPS ("audio/x-aiff"); + +#define AIFF_CAPS gst_static_caps_get(&aiff_caps) +static void +aiff_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data && memcmp (data, "FORM", 4) == 0) { + data += 8; + if (memcmp (data, "AIFF", 4) == 0 || memcmp (data, "AIFC", 4) == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AIFF_CAPS); + } +} + +/*** audio/x-svx ***/ + +static GstStaticCaps svx_caps = GST_STATIC_CAPS ("audio/x-svx"); + +#define SVX_CAPS gst_static_caps_get(&svx_caps) +static void +svx_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data && memcmp (data, "FORM", 4) == 0) { + data += 8; + if (memcmp (data, "8SVX", 4) == 0 || memcmp (data, "16SV", 4) == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SVX_CAPS); + } +} + +/*** audio/x-shorten ***/ + +static GstStaticCaps shn_caps = GST_STATIC_CAPS ("audio/x-shorten"); + +#define SHN_CAPS gst_static_caps_get(&shn_caps) +static void +shn_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data && memcmp (data, "ajkg", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS); + } + data = gst_type_find_peek (tf, -8, 8); + if (data && memcmp (data, "SHNAMPSK", 8) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS); + } +} + +/*** application/x-ape ***/ + +static GstStaticCaps ape_caps = GST_STATIC_CAPS ("application/x-ape"); + +#define APE_CAPS gst_static_caps_get(&ape_caps) +static void +ape_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data && memcmp (data, "MAC ", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, APE_CAPS); + } +} + +/*** ISO FORMATS ***/ + +/*** audio/x-m4a ***/ + +static GstStaticCaps m4a_caps = GST_STATIC_CAPS ("audio/x-m4a"); + +#define M4A_CAPS (gst_static_caps_get(&m4a_caps)) +static void +m4a_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 4, 8); + + if (data && (memcmp (data, "ftypM4A ", 8) == 0)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M4A_CAPS); + } +} + +/*** application/x-3gp ***/ + +/* The Q is there because variables can't start with a number. */ +static GstStaticCaps q3gp_caps = GST_STATIC_CAPS ("application/x-3gp"); +#define Q3GP_CAPS (gst_static_caps_get(&q3gp_caps)) + +static const gchar * +q3gp_type_find_get_profile (const guint8 * data) +{ + switch (GST_MAKE_FOURCC (data[0], data[1], data[2], 0)) { + case GST_MAKE_FOURCC ('3', 'g', 'g', 0): + return "general"; + case GST_MAKE_FOURCC ('3', 'g', 'p', 0): + return "basic"; + case GST_MAKE_FOURCC ('3', 'g', 's', 0): + return "streaming-server"; + case GST_MAKE_FOURCC ('3', 'g', 'r', 0): + return "progressive-download"; + default: + break; + } + return NULL; +} + +static void +q3gp_type_find (GstTypeFind * tf, gpointer unused) +{ + const gchar *profile; + guint32 ftyp_size = 0; + gint offset = 0; + guint8 *data = NULL; + + if ((data = gst_type_find_peek (tf, 0, 12)) == NULL) { + return; + } + + data += 4; + if (memcmp (data, "ftyp", 4) != 0) { + return; + } + + /* check major brand */ + data += 4; + if ((profile = q3gp_type_find_get_profile (data))) { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, + "application/x-3gp", "profile", G_TYPE_STRING, profile, NULL); + return; + } + + /* check compatible brands */ + if ((data = gst_type_find_peek (tf, 0, 4)) != NULL) { + ftyp_size = GST_READ_UINT32_BE (data); + } + for (offset = 16; offset < ftyp_size; offset += 4) { + if ((data = gst_type_find_peek (tf, offset, 3)) == NULL) { + break; + } + if ((profile = q3gp_type_find_get_profile (data))) { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, + "application/x-3gp", "profile", G_TYPE_STRING, profile, NULL); + return; + } + } + + return; + +} + +/*** video/mj2 and image/jp2 ***/ +static GstStaticCaps mj2_caps = GST_STATIC_CAPS ("video/mj2"); + +#define MJ2_CAPS gst_static_caps_get(&mj2_caps) + +static GstStaticCaps jp2_caps = GST_STATIC_CAPS ("image/jp2"); + +#define JP2_CAPS gst_static_caps_get(&jp2_caps) + +static void +jp2_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data; + + data = gst_type_find_peek (tf, 0, 24); + if (!data) + return; + + /* jp2 signature */ + if (memcmp (data, "\000\000\000\014jP \015\012\207\012", 12) != 0) + return; + + /* check ftyp box */ + data += 12; + if (memcmp (data + 4, "ftyp", 4) == 0) { + if (memcmp (data + 8, "jp2 ", 4) == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, JP2_CAPS); + else if (memcmp (data + 8, "mjp2", 4) == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MJ2_CAPS); + } +} + +/*** video/quicktime ***/ + +static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime"); + +#define QT_CAPS gst_static_caps_get(&qt_caps) +#define STRNCMP(x,y,z) (strncmp ((char*)(x), (char*)(y), z)) + +/* FIXME 0.11: go through http://www.ftyps.com/ */ +static void +qt_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data; + guint tip = 0; + guint64 offset = 0; + guint64 size; + const gchar *variant = NULL; + + while ((data = gst_type_find_peek (tf, offset, 12)) != NULL) { + guint64 new_offset; + + if (STRNCMP (&data[4], "ftypqt ", 8) == 0) { + tip = GST_TYPE_FIND_MAXIMUM; + break; + } + + if (STRNCMP (&data[4], "ftypisom", 8) == 0 || + STRNCMP (&data[4], "ftypavc1", 8) == 0 || + STRNCMP (&data[4], "ftypmp42", 8) == 0) { + tip = GST_TYPE_FIND_MAXIMUM; + variant = "iso"; + break; + } + + /* box/atom types that are in common with ISO base media file format */ + if (STRNCMP (&data[4], "moov", 4) == 0 || + STRNCMP (&data[4], "mdat", 4) == 0 || + STRNCMP (&data[4], "ftyp", 4) == 0 || + STRNCMP (&data[4], "free", 4) == 0 || + STRNCMP (&data[4], "uuid", 4) == 0 || + STRNCMP (&data[4], "skip", 4) == 0) { + if (tip == 0) { + tip = GST_TYPE_FIND_LIKELY; + } else { + tip = GST_TYPE_FIND_NEARLY_CERTAIN; + } + } + /* other box/atom types, apparently quicktime specific */ + else if (STRNCMP (&data[4], "pnot", 4) == 0 || + STRNCMP (&data[4], "PICT", 4) == 0 || + STRNCMP (&data[4], "wide", 4) == 0 || + STRNCMP (&data[4], "prfl", 4) == 0) { + tip = GST_TYPE_FIND_MAXIMUM; + break; + } else { + tip = 0; + break; + } + + size = GST_READ_UINT32_BE (data); + /* check compatible brands rather than ever expaning major brands above */ + if ((STRNCMP (&data[4], "ftyp", 4) == 0) && (size >= 16)) { + new_offset = offset + 12; + while (new_offset + 4 <= offset + size) { + data = gst_type_find_peek (tf, new_offset, 4); + if (data == NULL) + goto done; + if (STRNCMP (&data[4], "isom", 4) == 0 || + STRNCMP (&data[4], "avc1", 4) == 0 || + STRNCMP (&data[4], "mp41", 4) == 0 || + STRNCMP (&data[4], "mp42", 4) == 0) { + tip = GST_TYPE_FIND_MAXIMUM; + variant = "iso"; + goto done; + } + new_offset += 4; + } + } + if (size == 1) { + guint8 *sizedata; + + sizedata = gst_type_find_peek (tf, offset + 8, 8); + if (sizedata == NULL) + break; + + size = GST_READ_UINT64_BE (sizedata); + } else { + if (size < 8) + break; + } + new_offset = offset + size; + if (new_offset <= offset) + break; + offset = new_offset; + } + +done: + if (tip > 0) { + if (variant) { + GstCaps *caps = gst_caps_copy (QT_CAPS); + + gst_caps_set_simple (caps, "variant", G_TYPE_STRING, variant, NULL); + gst_type_find_suggest (tf, tip, caps); + gst_caps_unref (caps); + } else { + gst_type_find_suggest (tf, tip, QT_CAPS); + } + } +}; + + +/*** image/x-quicktime ***/ + +static GstStaticCaps qtif_caps = GST_STATIC_CAPS ("image/x-quicktime"); + +#define QTIF_CAPS gst_static_caps_get(&qtif_caps) + +/* how many atoms we check before we give up */ +#define QTIF_MAXROUNDS 25 + +static void +qtif_type_find (GstTypeFind * tf, gpointer unused) +{ + const guint8 *data; + gboolean found_idsc = FALSE; + gboolean found_idat = FALSE; + guint64 offset = 0; + guint rounds = 0; + + while ((data = gst_type_find_peek (tf, offset, 8)) != NULL) { + guint64 size; + + size = GST_READ_UINT32_BE (data); + if (size == 1) { + const guint8 *sizedata; + + sizedata = gst_type_find_peek (tf, offset + 8, 8); + if (sizedata == NULL) + break; + + size = GST_READ_UINT64_BE (sizedata); + } + if (size < 8) + break; + + if (STRNCMP (data + 4, "idsc", 4) == 0) + found_idsc = TRUE; + if (STRNCMP (data + 4, "idat", 4) == 0) + found_idat = TRUE; + + if (found_idsc && found_idat) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, QTIF_CAPS); + return; + } + + offset += size; + if (++rounds > QTIF_MAXROUNDS) + break; + } + + if (found_idsc || found_idat) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, QTIF_CAPS); + return; + } +}; + +/*** audio/x-mod ***/ + +static GstStaticCaps mod_caps = GST_STATIC_CAPS ("audio/x-mod"); + +#define MOD_CAPS gst_static_caps_get(&mod_caps) +/* FIXME: M15 CheckType to do */ +static void +mod_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data; + + /* MOD */ + if ((data = gst_type_find_peek (tf, 1080, 4)) != NULL) { + /* Protracker and variants */ + if ((memcmp (data, "M.K.", 4) == 0) || (memcmp (data, "M!K!", 4) == 0) || + /* Star Tracker */ + (memcmp (data, "FLT", 3) == 0 && isdigit (data[3])) || + (memcmp (data, "EXO", 3) == 0 && isdigit (data[3])) || + /* Oktalyzer (Amiga) */ + (memcmp (data, "OKTA", 4) == 0) || + /* Oktalyser (Atari) */ + (memcmp (data, "CD81", 4) == 0) || + /* Fasttracker */ + (memcmp (data + 1, "CHN", 3) == 0 && isdigit (data[0])) || + /* Fasttracker or Taketracker */ + (memcmp (data + 2, "CH", 2) == 0 && isdigit (data[0]) + && isdigit (data[1])) || (memcmp (data + 2, "CN", 2) == 0 + && isdigit (data[0]) && isdigit (data[1]))) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + /* XM */ + if ((data = gst_type_find_peek (tf, 0, 38)) != NULL) { + if (memcmp (data, "Extended Module: ", 17) == 0 && data[37] == 0x1A) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + /* OKT */ + if (data || (data = gst_type_find_peek (tf, 0, 8)) != NULL) { + if (memcmp (data, "OKTASONG", 8) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + if (data || (data = gst_type_find_peek (tf, 0, 4)) != NULL) { + /* 669 */ + if ((memcmp (data, "if", 2) == 0) || (memcmp (data, "JN", 2) == 0)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS); + return; + } + /* AMF */ + if ((memcmp (data, "AMF", 3) == 0 && data[3] > 10 && data[3] < 14) || + /* IT */ + (memcmp (data, "IMPM", 4) == 0) || + /* MED */ + (memcmp (data, "MMD0", 4) == 0) || (memcmp (data, "MMD1", 4) == 0) || + /* MTM */ + (memcmp (data, "MTM", 3) == 0)) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + /* DSM */ + if (memcmp (data, "RIFF", 4) == 0) { + guint8 *data2 = gst_type_find_peek (tf, 8, 4); + + if (data2) { + if (memcmp (data2, "DSMF", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + } + /* FAM */ + if (memcmp (data, "FAM\xFE", 4) == 0) { + guint8 *data2 = gst_type_find_peek (tf, 44, 3); + + if (data2) { + if (memcmp (data2, "compare", 3) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } else { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS); + return; + } + } + /* GDM */ + if (memcmp (data, "GDM\xFE", 4) == 0) { + guint8 *data2 = gst_type_find_peek (tf, 71, 4); + + if (data2) { + if (memcmp (data2, "GMFS", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } else { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MOD_CAPS); + return; + } + } + } + /* IMF */ + if ((data = gst_type_find_peek (tf, 60, 4)) != NULL) { + if (memcmp (data, "IM10", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + /* S3M */ + if ((data = gst_type_find_peek (tf, 44, 4)) != NULL) { + if (memcmp (data, "SCRM", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } + /* STM */ + if ((data = gst_type_find_peek (tf, 20, 8)) != NULL) { + if (g_ascii_strncasecmp ((gchar *) data, "!Scream!", 8) == 0 || + g_ascii_strncasecmp ((gchar *) data, "BMOD2STM", 8) == 0) { + guint8 *id, *stmtype; + + if ((id = gst_type_find_peek (tf, 28, 1)) == NULL) + return; + if ((stmtype = gst_type_find_peek (tf, 29, 1)) == NULL) + return; + if (*id == 0x1A && *stmtype == 2) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MOD_CAPS); + return; + } + } +} + +/*** application/x-shockwave-flash ***/ + +static GstStaticCaps swf_caps = +GST_STATIC_CAPS ("application/x-shockwave-flash"); +#define SWF_CAPS (gst_static_caps_get(&swf_caps)) +static void +swf_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data && (data[0] == 'F' || data[0] == 'C') && + data[1] == 'W' && data[2] == 'S') { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SWF_CAPS); + } +} + +/*** image/jpeg ***/ + +#define JPEG_MARKER_IS_START_OF_FRAME(x) \ + ((x)>=0xc0 && (x) <= 0xcf && (x)!=0xc4 && (x)!=0xc8 && (x)!=0xcc) + +static GstStaticCaps jpeg_caps = GST_STATIC_CAPS ("image/jpeg"); + +#define JPEG_CAPS (gst_static_caps_get(&jpeg_caps)) +static void +jpeg_type_find (GstTypeFind * tf, gpointer unused) +{ + GstTypeFindProbability prob = GST_TYPE_FIND_POSSIBLE; + DataScanCtx c = { 0, NULL, 0 }; + GstCaps *caps; + guint num_markers; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 2))) + return; + + if (c.data[0] != 0xff || c.data[1] != 0xd8) + return; + + num_markers = 1; + data_scan_ctx_advance (tf, &c, 2); + + caps = gst_caps_copy (JPEG_CAPS); + + while (data_scan_ctx_ensure_data (tf, &c, 4) && c.offset < (200 * 1024)) { + guint16 len; + guint8 marker; + + if (c.data[0] != 0xff) + break; + + marker = c.data[1]; + if (G_UNLIKELY (marker == 0xff)) { + data_scan_ctx_advance (tf, &c, 1); + continue; + } + + data_scan_ctx_advance (tf, &c, 2); + + /* we assume all markers we'll see before SOF have a payload length; if + * that's not the case we'll just detect a false sync and bail out, but + * still report POSSIBLE probability */ + len = GST_READ_UINT16_BE (c.data); + + GST_LOG ("possible JPEG marker 0x%02x (@0x%04x), segment length %u", + marker, (guint) c.offset, len); + + if (!data_scan_ctx_ensure_data (tf, &c, len)) + break; + + if (marker == 0xc4 || /* DEFINE_HUFFMAN_TABLES */ + marker == 0xcc || /* DEFINE_ARITHMETIC_CONDITIONING */ + marker == 0xdb || /* DEFINE_QUANTIZATION_TABLES */ + marker == 0xdd || /* DEFINE_RESTART_INTERVAL */ + marker == 0xfe) { /* COMMENT */ + data_scan_ctx_advance (tf, &c, len); + ++num_markers; + } else if (marker == 0xe0 && len >= (2 + 4) && /* APP0 */ + data_scan_ctx_memcmp (tf, &c, 2, "JFIF", 4)) { + GST_LOG ("found JFIF tag"); + prob = GST_TYPE_FIND_MAXIMUM; + data_scan_ctx_advance (tf, &c, len); + ++num_markers; + /* we continue until we find a start of frame marker */ + } else if (marker == 0xe1 && len >= (2 + 4) && /* APP1 */ + data_scan_ctx_memcmp (tf, &c, 2, "Exif", 4)) { + GST_LOG ("found Exif tag"); + prob = GST_TYPE_FIND_MAXIMUM; + data_scan_ctx_advance (tf, &c, len); + ++num_markers; + /* we continue until we find a start of frame marker */ + } else if (marker >= 0xe0 && marker <= 0xef) { /* APPn */ + data_scan_ctx_advance (tf, &c, len); + ++num_markers; + } else if (JPEG_MARKER_IS_START_OF_FRAME (marker) && len >= (2 + 8)) { + int h, w; + + h = GST_READ_UINT16_BE (c.data + 2 + 1); + w = GST_READ_UINT16_BE (c.data + 2 + 1 + 2); + if (h == 0 || w == 0) { + GST_WARNING ("bad width %u and/or height %u in SOF header", w, h); + break; + } + + GST_LOG ("SOF at offset %" G_GUINT64_FORMAT ", num_markers=%d, " + "WxH=%dx%d", c.offset - 2, num_markers, w, h); + + if (num_markers >= 5 || prob == GST_TYPE_FIND_MAXIMUM) + prob = GST_TYPE_FIND_MAXIMUM; + else + prob = GST_TYPE_FIND_LIKELY; + + gst_caps_set_simple (caps, "width", G_TYPE_INT, w, + "height", G_TYPE_INT, h, NULL); + break; + } else { + GST_WARNING ("bad length or unexpected JPEG marker 0xff 0x%02x", marker); + break; + } + } + + gst_type_find_suggest (tf, prob, caps); + gst_caps_unref (caps); +} + +/*** image/bmp ***/ + +static GstStaticCaps bmp_caps = GST_STATIC_CAPS ("image/bmp"); + +#define BMP_CAPS (gst_static_caps_get(&bmp_caps)) +static void +bmp_type_find (GstTypeFind * tf, gpointer unused) +{ + DataScanCtx c = { 0, NULL, 0 }; + guint32 struct_size, w, h, planes, bpp; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 54))) + return; + + if (c.data[0] != 'B' || c.data[1] != 'M') + return; + + /* skip marker + size */ + data_scan_ctx_advance (tf, &c, 2 + 4); + + /* reserved, must be 0 */ + if (c.data[0] != 0 || c.data[1] != 0 || c.data[2] != 0 || c.data[3] != 0) + return; + + data_scan_ctx_advance (tf, &c, 2 + 2); + + /* offset to start of image data in bytes (check for sanity) */ + GST_LOG ("offset=%u", GST_READ_UINT32_LE (c.data)); + if (GST_READ_UINT32_LE (c.data) > (10 * 1024 * 1024)) + return; + + struct_size = GST_READ_UINT32_LE (c.data + 4); + GST_LOG ("struct_size=%u", struct_size); + + data_scan_ctx_advance (tf, &c, 4 + 4); + + if (struct_size == 0x0C) { + w = GST_READ_UINT16_LE (c.data); + h = GST_READ_UINT16_LE (c.data + 2); + planes = GST_READ_UINT16_LE (c.data + 2 + 2); + bpp = GST_READ_UINT16_LE (c.data + 2 + 2 + 2); + } else if (struct_size == 40 || struct_size == 64 || struct_size == 108 + || struct_size == 124 || struct_size == 0xF0) { + w = GST_READ_UINT32_LE (c.data); + h = GST_READ_UINT32_LE (c.data + 4); + planes = GST_READ_UINT16_LE (c.data + 4 + 4); + bpp = GST_READ_UINT16_LE (c.data + 4 + 4 + 2); + } else { + return; + } + + /* image sizes sanity check */ + GST_LOG ("w=%u, h=%u, planes=%u, bpp=%u", w, h, planes, bpp); + if (w == 0 || w > 0xfffff || h == 0 || h > 0xfffff || planes != 1 || + (bpp != 1 && bpp != 4 && bpp != 8 && bpp != 16 && bpp != 24 && bpp != 32)) + return; + + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "image/bmp", + "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, "bpp", G_TYPE_INT, bpp, + NULL); +} + +/*** image/tiff ***/ +static GstStaticCaps tiff_caps = GST_STATIC_CAPS ("image/tiff, " + "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }"); +#define TIFF_CAPS (gst_static_caps_get(&tiff_caps)) +static GstStaticCaps tiff_be_caps = GST_STATIC_CAPS ("image/tiff, " + "endianness = (int) BIG_ENDIAN"); +#define TIFF_BE_CAPS (gst_static_caps_get(&tiff_be_caps)) +static GstStaticCaps tiff_le_caps = GST_STATIC_CAPS ("image/tiff, " + "endianness = (int) LITTLE_ENDIAN"); +#define TIFF_LE_CAPS (gst_static_caps_get(&tiff_le_caps)) +static void +tiff_type_find (GstTypeFind * tf, gpointer ununsed) +{ + guint8 *data = gst_type_find_peek (tf, 0, 8); + guint8 le_header[4] = { 0x49, 0x49, 0x2A, 0x00 }; + guint8 be_header[4] = { 0x4D, 0x4D, 0x00, 0x2A }; + + if (data) { + if (memcmp (data, le_header, 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_LE_CAPS); + } else if (memcmp (data, be_header, 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, TIFF_BE_CAPS); + } + } +} + +/*** PNM ***/ + +static GstStaticCaps pnm_caps = GST_STATIC_CAPS ("image/x-portable-bitmap; " + "image/x-portable-graymap; image/x-portable-pixmap; " + "image/x-portable-anymap"); + +#define PNM_CAPS (gst_static_caps_get(&pnm_caps)) + +#define IS_PNM_WHITESPACE(c) \ + ((c) == ' ' || (c) == '\r' || (c) == '\n' || (c) == 't') + +static void +pnm_type_find (GstTypeFind * tf, gpointer ununsed) +{ + const gchar *media_type = NULL; + DataScanCtx c = { 0, NULL, 0 }; + guint h = 0, w = 0; + + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 16))) + return; + + /* see http://en.wikipedia.org/wiki/Netpbm_format */ + if (c.data[0] != 'P' || c.data[1] < '1' || c.data[1] > '7' || + !IS_PNM_WHITESPACE (c.data[2]) || + (c.data[3] != '#' && c.data[3] < '0' && c.data[3] > '9')) + return; + + switch (c.data[1]) { + case '1': + media_type = "image/x-portable-bitmap"; /* ASCII */ + break; + case '2': + media_type = "image/x-portable-graymap"; /* ASCII */ + break; + case '3': + media_type = "image/x-portable-pixmap"; /* ASCII */ + break; + case '4': + media_type = "image/x-portable-bitmap"; /* Raw */ + break; + case '5': + media_type = "image/x-portable-graymap"; /* Raw */ + break; + case '6': + media_type = "image/x-portable-pixmap"; /* Raw */ + break; + case '7': + media_type = "image/x-portable-anymap"; + break; + default: + g_return_if_reached (); + } + + /* try to extract width and height as well */ + if (c.data[1] != '7') { + gchar s[64] = { 0, } + , sep1, sep2; + + /* need to skip any comment lines first */ + data_scan_ctx_advance (tf, &c, 3); + while (c.data[0] == '#') { /* we know there's still data left */ + data_scan_ctx_advance (tf, &c, 1); + while (c.data[0] != '\n' && c.data[0] != '\r') { + if (!data_scan_ctx_ensure_data (tf, &c, 4)) + return; + data_scan_ctx_advance (tf, &c, 1); + } + data_scan_ctx_advance (tf, &c, 1); + GST_LOG ("skipped comment line in PNM header"); + } + + if (!data_scan_ctx_ensure_data (tf, &c, 32) && + !data_scan_ctx_ensure_data (tf, &c, 4)) { + return; + } + + /* need to NUL-terminate data for sscanf */ + memcpy (s, c.data, MIN (sizeof (s) - 1, c.size)); + if (sscanf (s, "%u%c%u%c", &w, &sep1, &h, &sep2) == 4 && + IS_PNM_WHITESPACE (sep1) && IS_PNM_WHITESPACE (sep2) && + w > 0 && w < G_MAXINT && h > 0 && h < G_MAXINT) { + GST_LOG ("extracted PNM width and height: %dx%d", w, h); + } else { + w = 0; + h = 0; + } + } else { + /* FIXME: extract width + height for anymaps too */ + } + + if (w > 0 && h > 0) { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, media_type, + "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, NULL); + } else { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_LIKELY, media_type, NULL); + } +} + +static GstStaticCaps sds_caps = GST_STATIC_CAPS ("audio/x-sds"); + +#define SDS_CAPS (gst_static_caps_get(&sds_caps)) +static void +sds_type_find (GstTypeFind * tf, gpointer ununsed) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + guint8 mask[4] = { 0xFF, 0xFF, 0x80, 0xFF }; + guint8 match[4] = { 0xF0, 0x7E, 0, 0x01 }; + gint x; + + if (data) { + for (x = 0; x < 4; x++) { + if ((data[x] & mask[x]) != match[x]) { + return; + } + } + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SDS_CAPS); + } +} + +static GstStaticCaps ircam_caps = GST_STATIC_CAPS ("audio/x-ircam"); + +#define IRCAM_CAPS (gst_static_caps_get(&ircam_caps)) +static void +ircam_type_find (GstTypeFind * tf, gpointer ununsed) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + guint8 mask[4] = { 0xFF, 0xFF, 0xF8, 0xFF }; + guint8 match[4] = { 0x64, 0xA3, 0x00, 0x00 }; + gint x; + gboolean matched = TRUE; + + if (!data) { + return; + } + for (x = 0; x < 4; x++) { + if ((data[x] & mask[x]) != match[x]) { + matched = FALSE; + } + } + if (matched) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, IRCAM_CAPS); + return; + } + /* now try the reverse version */ + matched = TRUE; + for (x = 0; x < 4; x++) { + if ((data[x] & mask[3 - x]) != match[3 - x]) { + matched = FALSE; + } + } +} + +/* EBML typefind helper */ +static gboolean +ebml_check_header (GstTypeFind * tf, const gchar * doctype, int doctype_len) +{ + /* 4 bytes for EBML ID, 1 byte for header length identifier */ + guint8 *data = gst_type_find_peek (tf, 0, 4 + 1); + gint len_mask = 0x80, size = 1, n = 1, total; + + if (!data) + return FALSE; + + /* ebml header? */ + if (data[0] != 0x1A || data[1] != 0x45 || data[2] != 0xDF || data[3] != 0xA3) + return FALSE; + + /* length of header */ + total = data[4]; + while (size <= 8 && !(total & len_mask)) { + size++; + len_mask >>= 1; + } + if (size > 8) + return FALSE; + total &= (len_mask - 1); + while (n < size) + total = (total << 8) | data[4 + n++]; + + /* get new data for full header, 4 bytes for EBML ID, + * EBML length tag and the actual header */ + data = gst_type_find_peek (tf, 0, 4 + size + total); + if (!data) + return FALSE; + + /* only check doctype if asked to do so */ + if (doctype == NULL || doctype_len == 0) + return TRUE; + + /* the header must contain the doctype. For now, we don't parse the + * whole header but simply check for the availability of that array + * of characters inside the header. Not fully fool-proof, but good + * enough. */ + for (n = 4 + size; n <= 4 + size + total - doctype_len; n++) + if (!memcmp (&data[n], doctype, doctype_len)) + return TRUE; + + return FALSE; +} + +/*** video/x-matroska ***/ +static GstStaticCaps matroska_caps = GST_STATIC_CAPS ("video/x-matroska"); + +#define MATROSKA_CAPS (gst_static_caps_get(&matroska_caps)) +static void +matroska_type_find (GstTypeFind * tf, gpointer ununsed) +{ + if (ebml_check_header (tf, "matroska", 8)) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MATROSKA_CAPS); + else if (ebml_check_header (tf, NULL, 0)) + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MATROSKA_CAPS); +} + +/*** video/webm ***/ +static GstStaticCaps webm_caps = GST_STATIC_CAPS ("video/webm"); + +#define WEBM_CAPS (gst_static_caps_get(&webm_caps)) +static void +webm_type_find (GstTypeFind * tf, gpointer ununsed) +{ + if (ebml_check_header (tf, "webm", 4)) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, WEBM_CAPS); +} + +/*** application/mxf ***/ +static GstStaticCaps mxf_caps = GST_STATIC_CAPS ("application/mxf"); + +#define MXF_MAX_PROBE_LENGTH (1024 * 64) +#define MXF_CAPS (gst_static_caps_get(&mxf_caps)) + +/* + * MXF files start with a header partition pack key of 16 bytes which is defined + * at SMPTE-377M 6.1. Before this there can be up to 64K of run-in which _must_ + * not contain the partition pack key. + */ +static void +mxf_type_find (GstTypeFind * tf, gpointer ununsed) +{ + static const guint8 partition_pack_key[] = + { 0x06, 0x0e, 0x2b, 0x34, 0x02, 0x05, 0x01, 0x01, 0x0d, 0x01, 0x02, 0x01, + 0x01 + }; + DataScanCtx c = { 0, NULL, 0 }; + + while (c.offset <= MXF_MAX_PROBE_LENGTH) { + guint i; + if (G_UNLIKELY (!data_scan_ctx_ensure_data (tf, &c, 1024))) + break; + + /* look over in chunks of 1kbytes to avoid too much overhead */ + + for (i = 0; i < 1024 - 16; i++) { + /* Check first byte before calling more expensive memcmp function */ + if (G_UNLIKELY (c.data[i] == 0x06 + && memcmp (c.data + i, partition_pack_key, 13) == 0)) { + /* Header partition pack? */ + if (c.data[i + 13] != 0x02) + goto advance; + + /* Partition status */ + if (c.data[i + 14] >= 0x05) + goto advance; + + /* Reserved, must be 0x00 */ + if (c.data[i + 15] != 0x00) + goto advance; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, MXF_CAPS); + return; + } + } + + advance: + data_scan_ctx_advance (tf, &c, 1024 - 16); + } +} + +/*** video/x-dv ***/ + +static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, " + "systemstream = (boolean) true"); +#define DV_CAPS (gst_static_caps_get(&dv_caps)) +static void +dv_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data; + + data = gst_type_find_peek (tf, 0, 5); + + /* check for DIF and DV flag */ + if (data && (data[0] == 0x1f) && (data[1] == 0x07) && (data[2] == 0x00)) { + const gchar *format; + + if (data[3] & 0x80) { + format = "PAL"; + } else { + format = "NTSC"; + } + + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, "video/x-dv", + "systemstream", G_TYPE_BOOLEAN, TRUE, + "format", G_TYPE_STRING, format, NULL); + } +} + + +/*** application/ogg and application/x-annodex ***/ +static GstStaticCaps ogg_caps = GST_STATIC_CAPS ("application/ogg"); +static GstStaticCaps annodex_caps = GST_STATIC_CAPS ("application/x-annodex"); +static GstStaticCaps ogg_annodex_caps = + GST_STATIC_CAPS ("application/ogg;application/x-annodex"); + +#define OGGANX_CAPS (gst_static_caps_get(&ogg_annodex_caps)) + +static void +ogganx_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) { + + /* Check for an annodex fishbone header */ + data = gst_type_find_peek (tf, 28, 8); + if (data && memcmp (data, "fishead\0", 8) == 0) + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, + gst_static_caps_get (&annodex_caps)); + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, + gst_static_caps_get (&ogg_caps)); + } +} + +/*** audio/x-vorbis ***/ +static GstStaticCaps vorbis_caps = GST_STATIC_CAPS ("audio/x-vorbis"); + +#define VORBIS_CAPS (gst_static_caps_get(&vorbis_caps)) +static void +vorbis_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 30); + + if (data) { + guint blocksize_0; + guint blocksize_1; + + /* 1 byte packet type (identification=0x01) + 6 byte string "vorbis" + 4 byte vorbis version */ + if (memcmp (data, "\001vorbis\000\000\000\000", 11) != 0) + return; + data += 11; + /* 1 byte channels must be != 0 */ + if (data[0] == 0) + return; + data++; + /* 4 byte samplerate must be != 0 */ + if (GST_READ_UINT32_LE (data) == 0) + return; + data += 16; + /* blocksize checks */ + blocksize_0 = data[0] & 0x0F; + blocksize_1 = (data[0] & 0xF0) >> 4; + if (blocksize_0 > blocksize_1) + return; + if (blocksize_0 < 6 || blocksize_0 > 13) + return; + if (blocksize_1 < 6 || blocksize_1 > 13) + return; + data++; + /* framing bit */ + if ((data[0] & 0x01) != 1) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VORBIS_CAPS); + } +} + +/*** video/x-theora ***/ + +static GstStaticCaps theora_caps = GST_STATIC_CAPS ("video/x-theora"); + +#define THEORA_CAPS (gst_static_caps_get(&theora_caps)) +static void +theora_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 7); //42); + + if (data) { + if (data[0] != 0x80) + return; + if (memcmp (&data[1], "theora", 6) != 0) + return; + /* FIXME: make this more reliable when specs are out */ + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, THEORA_CAPS); + } +} + +/*** kate ***/ +static void +kate_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 64); + gchar category[16] = { 0, }; + + if (G_UNLIKELY (data == NULL)) + return; + + /* see: http://wiki.xiph.org/index.php/OggKate#Format_specification */ + if (G_LIKELY (memcmp (data, "\200kate\0\0\0", 8) != 0)) + return; + + /* make sure we always have a NUL-terminated string */ + memcpy (category, data + 48, 15); + GST_LOG ("kate category: %s", category); + /* canonical categories for subtitles: subtitles, spu-subtitles, SUB, K-SPU */ + if (strcmp (category, "subtitles") == 0 || strcmp (category, "SUB") == 0 || + strcmp (category, "spu-subtitles") == 0 || + strcmp (category, "K-SPU") == 0) { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, + "subtitle/x-kate", NULL); + } else { + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_MAXIMUM, + "application/x-kate", NULL); + } +} + +/*** application/x-ogm-video or audio***/ + +static GstStaticCaps ogmvideo_caps = +GST_STATIC_CAPS ("application/x-ogm-video"); +#define OGMVIDEO_CAPS (gst_static_caps_get(&ogmvideo_caps)) +static void +ogmvideo_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 9); + + if (data) { + if (memcmp (data, "\001video\000\000\000", 9) != 0) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMVIDEO_CAPS); + } +} + +static GstStaticCaps ogmaudio_caps = +GST_STATIC_CAPS ("application/x-ogm-audio"); +#define OGMAUDIO_CAPS (gst_static_caps_get(&ogmaudio_caps)) +static void +ogmaudio_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 9); + + if (data) { + if (memcmp (data, "\001audio\000\000\000", 9) != 0) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMAUDIO_CAPS); + } +} + +static GstStaticCaps ogmtext_caps = GST_STATIC_CAPS ("application/x-ogm-text"); + +#define OGMTEXT_CAPS (gst_static_caps_get(&ogmtext_caps)) +static void +ogmtext_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 9); + + if (data) { + if (memcmp (data, "\001text\000\000\000\000", 9) != 0) + return; + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGMTEXT_CAPS); + } +} + +/*** audio/x-speex ***/ + +static GstStaticCaps speex_caps = GST_STATIC_CAPS ("audio/x-speex"); + +#define SPEEX_CAPS (gst_static_caps_get(&speex_caps)) +static void +speex_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 80); + + if (data) { + /* 8 byte string "Speex " + 24 byte speex version string + int */ + if (memcmp (data, "Speex ", 8) != 0) + return; + data += 32; + + /* 4 byte header size >= 80 */ + if (GST_READ_UINT32_LE (data) < 80) + return; + data += 4; + + /* 4 byte sample rate <= 48000 */ + if (GST_READ_UINT32_LE (data) > 48000) + return; + data += 4; + + /* currently there are only 3 speex modes. */ + if (GST_READ_UINT32_LE (data) > 3) + return; + data += 12; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SPEEX_CAPS); + } +} + +/*** audio/x-celt ***/ + +static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt"); + +#define CELT_CAPS (gst_static_caps_get(&celt_caps)) +static void +celt_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + /* 8 byte string "CELT " */ + if (memcmp (data, "CELT ", 8) != 0) + return; + + /* TODO: Check other values of the CELT header */ + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CELT_CAPS); + } +} + +/*** application/x-ogg-skeleton ***/ +static GstStaticCaps ogg_skeleton_caps = +GST_STATIC_CAPS ("application/x-ogg-skeleton, parsed=(boolean)FALSE"); +#define OGG_SKELETON_CAPS (gst_static_caps_get(&ogg_skeleton_caps)) +static void +oggskel_type_find (GstTypeFind * tf, gpointer private) +{ + guint8 *data = gst_type_find_peek (tf, 0, 12); + + if (data) { + /* 8 byte string "fishead\0" for the ogg skeleton stream */ + if (memcmp (data, "fishead\0", 8) != 0) + return; + data += 8; + + /* Require that the header contains version 3.0 */ + if (GST_READ_UINT16_LE (data) != 3) + return; + data += 2; + if (GST_READ_UINT16_LE (data) != 0) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, OGG_SKELETON_CAPS); + } +} + +static GstStaticCaps cmml_caps = GST_STATIC_CAPS ("text/x-cmml"); + +#define CMML_CAPS (gst_static_caps_get(&cmml_caps)) +static void +cmml_type_find (GstTypeFind * tf, gpointer private) +{ + /* Header is 12 bytes minimum (though we don't check the minor version */ + guint8 *data = gst_type_find_peek (tf, 0, 12); + + if (data) { + + /* 8 byte string "CMML\0\0\0\0" for the magic number */ + if (memcmp (data, "CMML\0\0\0\0", 8) != 0) + return; + data += 8; + + /* Require that the header contains at least version 2.0 */ + if (GST_READ_UINT16_LE (data) < 2) + return; + + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, CMML_CAPS); + } +} + +/*** application/x-tar ***/ + +static GstStaticCaps tar_caps = GST_STATIC_CAPS ("application/x-tar"); + +#define TAR_CAPS (gst_static_caps_get(&tar_caps)) +#define OLDGNU_MAGIC "ustar " /* 7 chars and a NUL */ +#define NEWGNU_MAGIC "ustar" /* 5 chars and a NUL */ +static void +tar_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 257, 8); + + /* of course we are not certain, but we don't want other typefind funcs + * to detect formats of files within the tar archive, e.g. mp3s */ + if (data) { + if (memcmp (data, OLDGNU_MAGIC, 8) == 0) { /* sic */ + gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS); + } else if (memcmp (data, NEWGNU_MAGIC, 6) == 0 && /* sic */ + g_ascii_isdigit (data[6]) && g_ascii_isdigit (data[7])) { + gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, TAR_CAPS); + } + } +} + +/*** application/x-ar ***/ + +static GstStaticCaps ar_caps = GST_STATIC_CAPS ("application/x-ar"); + +#define AR_CAPS (gst_static_caps_get(&ar_caps)) +static void +ar_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 24); + + if (data && memcmp (data, "!", 7) == 0) { + gint i; + + for (i = 7; i < 24; ++i) { + if (!g_ascii_isprint (data[i]) && data[i] != '\n') { + gst_type_find_suggest (tf, GST_TYPE_FIND_POSSIBLE, AR_CAPS); + } + } + + gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, AR_CAPS); + } +} + +/*** audio/x-au ***/ + +/* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH, + * as it is only possible to register one typefind factory per 'name' + * (which is in this case the caps), and the first one would be replaced by + * the second one. */ +static GstStaticCaps au_caps = GST_STATIC_CAPS ("audio/x-au"); + +#define AU_CAPS (gst_static_caps_get(&au_caps)) +static void +au_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data) { + if (memcmp (data, ".snd", 4) == 0 || memcmp (data, "dns.", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, AU_CAPS); + } + } +} + + +/*** video/x-nuv ***/ + +/* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH, + * as it is only possible to register one typefind factory per 'name' + * (which is in this case the caps), and the first one would be replaced by + * the second one. */ +static GstStaticCaps nuv_caps = GST_STATIC_CAPS ("video/x-nuv"); + +#define NUV_CAPS (gst_static_caps_get(&nuv_caps)) +static void +nuv_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 11); + + if (data) { + if (memcmp (data, "MythTVVideo", 11) == 0 + || memcmp (data, "NuppelVideo", 11) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, NUV_CAPS); + } + } +} + +/*** audio/x-paris ***/ +/* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */ +static GstStaticCaps paris_caps = GST_STATIC_CAPS ("audio/x-paris"); + +#define PARIS_CAPS (gst_static_caps_get(&paris_caps)) +static void +paris_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 4); + + if (data) { + if (memcmp (data, " paf", 4) == 0 || memcmp (data, "fap ", 4) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, PARIS_CAPS); + } + } +} + +/*** audio/iLBC-sh ***/ +/* NOTE: do not replace this function with two TYPE_FIND_REGISTER_START_WITH */ +static GstStaticCaps ilbc_caps = GST_STATIC_CAPS ("audio/iLBC-sh"); + +#define ILBC_CAPS (gst_static_caps_get(&ilbc_caps)) +static void +ilbc_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + if (memcmp (data, "#!iLBC30", 8) == 0 || memcmp (data, "#!iLBC20", 8) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, ILBC_CAPS); + } + } +} + +/*** application/x-ms-dos-executable ***/ + +static GstStaticCaps msdos_caps = +GST_STATIC_CAPS ("application/x-ms-dos-executable"); +#define MSDOS_CAPS (gst_static_caps_get(&msdos_caps)) +/* see http://www.madchat.org/vxdevl/papers/winsys/pefile/pefile.htm */ +static void +msdos_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 64); + + if (data && data[0] == 'M' && data[1] == 'Z' && + GST_READ_UINT16_LE (data + 8) == 4) { + guint32 pe_offset = GST_READ_UINT32_LE (data + 60); + + data = gst_type_find_peek (tf, pe_offset, 2); + if (data && data[0] == 'P' && data[1] == 'E') { + gst_type_find_suggest (tf, GST_TYPE_FIND_NEARLY_CERTAIN, MSDOS_CAPS); + } + } +} + +/*** application/x-mmsh ***/ + +static GstStaticCaps mmsh_caps = GST_STATIC_CAPS ("application/x-mmsh"); + +#define MMSH_CAPS gst_static_caps_get(&mmsh_caps) + +/* This is to recognise mssh-over-http */ +static void +mmsh_type_find (GstTypeFind * tf, gpointer unused) +{ + static const guint8 asf_marker[16] = { 0x30, 0x26, 0xb2, 0x75, 0x8e, 0x66, + 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c + }; + + guint8 *data; + + data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16); + if (data && data[0] == 0x24 && data[1] == 0x48 && + GST_READ_UINT16_LE (data + 2) > 2 + 2 + 4 + 2 + 2 + 16 && + memcmp (data + 2 + 2 + 4 + 2 + 2, asf_marker, 16) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY, MMSH_CAPS); + } +} + +/*** video/x-dirac ***/ + +/* NOTE: we cannot replace this function with TYPE_FIND_REGISTER_START_WITH, + * as it is only possible to register one typefind factory per 'name' + * (which is in this case the caps), and the first one would be replaced by + * the second one. */ +static GstStaticCaps dirac_caps = GST_STATIC_CAPS ("video/x-dirac"); + +#define DIRAC_CAPS (gst_static_caps_get(&dirac_caps)) +static void +dirac_type_find (GstTypeFind * tf, gpointer unused) +{ + guint8 *data = gst_type_find_peek (tf, 0, 8); + + if (data) { + if (memcmp (data, "BBCD", 4) == 0 || memcmp (data, "KW-DIRAC", 8) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, DIRAC_CAPS); + } + } +} + +/*** video/vivo ***/ + +static GstStaticCaps vivo_caps = GST_STATIC_CAPS ("video/vivo"); + +#define VIVO_CAPS gst_static_caps_get(&vivo_caps) + +static void +vivo_type_find (GstTypeFind * tf, gpointer unused) +{ + static const guint8 vivo_marker[] = { 'V', 'e', 'r', 's', 'i', 'o', 'n', + ':', 'V', 'i', 'v', 'o', '/' + }; + guint8 *data; + guint hdr_len, pos; + + data = gst_type_find_peek (tf, 0, 1024); + if (data == NULL || data[0] != 0x00) + return; + + if ((data[1] & 0x80)) { + if ((data[2] & 0x80)) + return; + hdr_len = ((guint) (data[1] & 0x7f)) << 7; + hdr_len += data[2]; + if (hdr_len > 2048) + return; + pos = 3; + } else { + hdr_len = data[1]; + pos = 2; + } + + /* 1008 = 1022 - strlen ("Version:Vivo/") - 1 */ + while (pos < 1008 && data[pos] == '\r' && data[pos + 1] == '\n') + pos += 2; + + if (memcmp (data + pos, vivo_marker, sizeof (vivo_marker)) == 0) { + gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, VIVO_CAPS); + } +} + +/*** XDG MIME typefinder (to avoid false positives mostly) ***/ + +#ifdef USE_GIO +static void +xdgmime_typefind (GstTypeFind * find, gpointer user_data) +{ + gchar *mimetype; + gsize length = 16384; + guint64 tf_length; + guint8 *data; + gchar *tmp; + + if ((tf_length = gst_type_find_get_length (find)) > 0) + length = MIN (length, tf_length); + + if ((data = gst_type_find_peek (find, 0, length)) == NULL) + return; + + tmp = g_content_type_guess (NULL, data, length, NULL); + if (tmp == NULL || g_content_type_is_unknown (tmp)) { + g_free (tmp); + return; + } + + mimetype = g_content_type_get_mime_type (tmp); + g_free (tmp); + + if (mimetype == NULL) + return; + + GST_DEBUG ("Got mimetype '%s'", mimetype); + + /* Ignore audio/video types: + * - our own typefinders in -base are likely to be better at this + * (and if they're not, we really want to fix them, that's why we don't + * report xdg-detected audio/video types at all, not even with a low + * probability) + * - we want to detect GStreamer media types and not MIME types + * - the purpose of this xdg mime finder is mainly to prevent false + * positives of non-media formats, not to typefind audio/video formats */ + if (g_str_has_prefix (mimetype, "audio/") || + g_str_has_prefix (mimetype, "video/")) { + GST_LOG ("Ignoring audio/video mime type"); + g_free (mimetype); + return; + } + + /* Again, we mainly want the xdg typefinding to prevent false-positives on + * non-media formats, so suggest the type with a probability that trumps + * uncertain results of our typefinders, but not more than that. */ + GST_LOG ("Suggesting '%s' with probability POSSIBLE", mimetype); + gst_type_find_suggest_simple (find, GST_TYPE_FIND_POSSIBLE, mimetype, NULL); + g_free (mimetype); +} +#endif /* USE_GIO */ + +/*** Windows icon typefinder (to avoid false positives mostly) ***/ + +static void +windows_icon_typefind (GstTypeFind * find, gpointer user_data) +{ + guint8 *data; + gint64 datalen; + guint16 type, nimages; + gint32 size, offset; + + datalen = gst_type_find_get_length (find); + if ((data = gst_type_find_peek (find, 0, 6)) == NULL) + return; + + /* header - simple and not enough to rely on it alone */ + if (GST_READ_UINT16_LE (data) != 0) + return; + type = GST_READ_UINT16_LE (data + 2); + if (type != 1 && type != 2) + return; + nimages = GST_READ_UINT16_LE (data + 4); + if (nimages == 0) /* we can assume we can't have an empty image file ? */ + return; + + /* first image */ + if (data[6 + 3] != 0) + return; + if (type == 1) { + guint16 planes = GST_READ_UINT16_LE (data + 6 + 4); + if (planes > 1) + return; + } + size = GST_READ_UINT32_LE (data + 6 + 8); + offset = GST_READ_UINT32_LE (data + 6 + 12); + if (offset < 0 || size <= 0 || size >= datalen || offset >= datalen + || size + offset > datalen) + return; + + gst_type_find_suggest_simple (find, GST_TYPE_FIND_NEARLY_CERTAIN, + "image/x-icon", NULL); +} + + +/*** DEGAS Atari images (also to avoid false positives, see #625129) ***/ +static void +degas_type_find (GstTypeFind * tf, gpointer private) +{ + /* No magic, but it should have a fixed size and a few invalid values */ + /* http://www.fileformat.info/format/atari/spec/6ecf9f6eb5be494284a47feb8a214687/view.htm */ + gint64 len; + const guint8 *data; + guint16 resolution; + int n; + + len = gst_type_find_get_length (tf); + if (len < 34) /* smallest header of the lot */ + return; + data = gst_type_find_peek (tf, 0, 4); + resolution = GST_READ_UINT16_BE (data); + if (len == 32034) { + /* could be DEGAS */ + if (resolution <= 2) + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_POSSIBLE + 5, + "image/x-degas", NULL); + } else if (len == 32066) { + /* could be DEGAS Elite */ + if (resolution <= 2) { + data = gst_type_find_peek (tf, len - 16, 8); + for (n = 0; n < 4; n++) { + if (GST_READ_UINT16_BE (data + n * 2) > 2) + return; + } + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_POSSIBLE + 5, + "image/x-degas", NULL); + } + } else if (len >= 66 && len < 32066) { + /* could be compressed DEGAS Elite, but it's compressed and so we can't rely on size, + it does have 4 16 bytes values near the end that are 0-2 though. */ + if ((resolution & 0x8000) && (resolution & 0x7fff) <= 2) { + data = gst_type_find_peek (tf, len - 16, 8); + for (n = 0; n < 4; n++) { + if (GST_READ_UINT16_BE (data + n * 2) > 2) + return; + } + gst_type_find_suggest_simple (tf, GST_TYPE_FIND_POSSIBLE + 5, + "image/x-degas", NULL); + } + } +} + +/*** generic typefind for streams that have some data at a specific position***/ +typedef struct +{ + const guint8 *data; + guint size; + guint probability; + GstCaps *caps; +} +GstTypeFindData; + +static void +start_with_type_find (GstTypeFind * tf, gpointer private) +{ + GstTypeFindData *start_with = (GstTypeFindData *) private; + guint8 *data; + + GST_LOG ("trying to find mime type %s with the first %u bytes of data", + gst_structure_get_name (gst_caps_get_structure (start_with->caps, 0)), + start_with->size); + data = gst_type_find_peek (tf, 0, start_with->size); + if (data && memcmp (data, start_with->data, start_with->size) == 0) { + gst_type_find_suggest (tf, start_with->probability, start_with->caps); + } +} + +static void +sw_data_destroy (GstTypeFindData * sw_data) +{ + if (G_LIKELY (sw_data->caps != NULL)) + gst_caps_unref (sw_data->caps); + g_free (sw_data); +} + +#define TYPE_FIND_REGISTER_START_WITH(plugin,name,rank,ext,_data,_size,_probability)\ +G_BEGIN_DECLS{ \ + GstTypeFindData *sw_data = g_new (GstTypeFindData, 1); \ + sw_data->data = (const guint8 *)_data; \ + sw_data->size = _size; \ + sw_data->probability = _probability; \ + sw_data->caps = gst_caps_new_simple (name, NULL); \ + if (!gst_type_find_register (plugin, name, rank, start_with_type_find,\ + (char **) ext, sw_data->caps, sw_data, \ + (GDestroyNotify) (sw_data_destroy))) { \ + gst_caps_unref (sw_data->caps); \ + g_free (sw_data); \ + } \ +}G_END_DECLS + +/*** same for riff types ***/ + +static void +riff_type_find (GstTypeFind * tf, gpointer private) +{ + GstTypeFindData *riff_data = (GstTypeFindData *) private; + guint8 *data = gst_type_find_peek (tf, 0, 12); + + if (data && (memcmp (data, "RIFF", 4) == 0 || memcmp (data, "AVF0", 4) == 0)) { + data += 8; + if (memcmp (data, riff_data->data, 4) == 0) + gst_type_find_suggest (tf, riff_data->probability, riff_data->caps); + } +} + +#define TYPE_FIND_REGISTER_RIFF(plugin,name,rank,ext,_data) \ +G_BEGIN_DECLS{ \ + GstTypeFindData *sw_data = g_new (GstTypeFindData, 1); \ + sw_data->data = (gpointer)_data; \ + sw_data->size = 4; \ + sw_data->probability = GST_TYPE_FIND_MAXIMUM; \ + sw_data->caps = gst_caps_new_simple (name, NULL); \ + if (!gst_type_find_register (plugin, name, rank, riff_type_find, \ + (char **) ext, sw_data->caps, sw_data, \ + (GDestroyNotify) (sw_data_destroy))) { \ + gst_caps_unref (sw_data->caps); \ + g_free (sw_data); \ + } \ +}G_END_DECLS + + +/*** plugin initialization ***/ + +#define TYPE_FIND_REGISTER(plugin,name,rank,func,ext,caps,priv,notify) \ +G_BEGIN_DECLS{\ + if (!gst_type_find_register (plugin, name, rank, func, (char **) ext, caps, priv, notify))\ + return FALSE; \ +}G_END_DECLS + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + /* can't initialize this via a struct as caps can't be statically initialized */ + + /* note: asx/wax/wmx are XML files, asf doesn't handle them */ + /* FIXME-0.11: these should be const, + this requires gstreamer/gst/gsttypefind::gst_type_find_register() + to have define the parameter as const + */ + static const gchar *asf_exts[] = { "asf", "wm", "wma", "wmv", NULL }; + static const gchar *au_exts[] = { "au", "snd", NULL }; + static const gchar *avi_exts[] = { "avi", NULL }; + static const gchar *qcp_exts[] = { "qcp", NULL }; + static const gchar *cdxa_exts[] = { "dat", NULL }; + static const gchar *flac_exts[] = { "flac", NULL }; + static const gchar *flx_exts[] = { "flc", "fli", NULL }; + static const gchar *id3_exts[] = + { "mp3", "mp2", "mp1", "mpga", "ogg", "flac", "tta", NULL }; + static const gchar *apetag_exts[] = { "mp3", "ape", "mpc", "wv", NULL }; + static const gchar *tta_exts[] = { "tta", NULL }; + static const gchar *mod_exts[] = { "669", "amf", "dsm", "gdm", "far", "imf", + "it", "med", "mod", "mtm", "okt", "sam", + "s3m", "stm", "stx", "ult", "xm", NULL + }; + static const gchar *mp3_exts[] = { "mp3", "mp2", "mp1", "mpga", NULL }; + static const gchar *ac3_exts[] = { "ac3", "eac3", NULL }; + static const gchar *dts_exts[] = { "dts", NULL }; + static const gchar *gsm_exts[] = { "gsm", NULL }; + static const gchar *musepack_exts[] = { "mpc", "mpp", "mp+", NULL }; + static const gchar *mpeg_sys_exts[] = { "mpe", "mpeg", "mpg", NULL }; + static const gchar *mpeg_video_exts[] = { "mpv", "mpeg", "mpg", NULL }; + static const gchar *mpeg_ts_exts[] = { "ts", "mts", NULL }; + static const gchar *ogg_exts[] = { "anx", "ogg", "ogm", NULL }; + static const gchar *qt_exts[] = { "mov", NULL }; + static const gchar *qtif_exts[] = { "qif", "qtif", "qti", NULL }; + static const gchar *mj2_exts[] = { "mj2", NULL }; + static const gchar *jp2_exts[] = { "jp2", NULL }; + static const gchar *rm_exts[] = { "ra", "ram", "rm", "rmvb", NULL }; + static const gchar *swf_exts[] = { "swf", "swfl", NULL }; + static const gchar *utf8_exts[] = { "txt", NULL }; + static const gchar *wav_exts[] = { "wav", NULL }; + static const gchar *aiff_exts[] = { "aiff", "aif", "aifc", NULL }; + static const gchar *svx_exts[] = { "iff", "svx", NULL }; + static const gchar *paris_exts[] = { "paf", NULL }; + static const gchar *nist_exts[] = { "nist", NULL }; + static const gchar *voc_exts[] = { "voc", NULL }; + static const gchar *sds_exts[] = { "sds", NULL }; + static const gchar *ircam_exts[] = { "sf", NULL }; + static const gchar *w64_exts[] = { "w64", NULL }; + static const gchar *shn_exts[] = { "shn", NULL }; + static const gchar *ape_exts[] = { "ape", NULL }; + static const gchar *uri_exts[] = { "ram", NULL }; + static const gchar *hls_exts[] = { "m3u8", NULL }; + static const gchar *sdp_exts[] = { "sdp", NULL }; + static const gchar *smil_exts[] = { "smil", NULL }; + static const gchar *html_exts[] = { "htm", "html", NULL }; + static const gchar *xml_exts[] = { "xml", NULL }; + static const gchar *jpeg_exts[] = { "jpg", "jpe", "jpeg", NULL }; + static const gchar *gif_exts[] = { "gif", NULL }; + static const gchar *png_exts[] = { "png", NULL }; + static const gchar *bmp_exts[] = { "bmp", NULL }; + static const gchar *tiff_exts[] = { "tif", "tiff", NULL }; + static const gchar *matroska_exts[] = { "mkv", "mka", NULL }; + static const gchar *webm_exts[] = { "webm", NULL }; + static const gchar *mve_exts[] = { "mve", NULL }; + static const gchar *dv_exts[] = { "dv", "dif", NULL }; + static const gchar *amr_exts[] = { "amr", NULL }; + static const gchar *ilbc_exts[] = { "ilbc", NULL }; + static const gchar *sid_exts[] = { "sid", NULL }; + static const gchar *xcf_exts[] = { "xcf", NULL }; + static const gchar *mng_exts[] = { "mng", NULL }; + static const gchar *jng_exts[] = { "jng", NULL }; + static const gchar *xpm_exts[] = { "xpm", NULL }; + static const gchar *pnm_exts[] = { "pnm", "ppm", "pgm", "pbm", NULL }; + static const gchar *ras_exts[] = { "ras", NULL }; + static const gchar *bz2_exts[] = { "bz2", NULL }; + static const gchar *gz_exts[] = { "gz", NULL }; + static const gchar *zip_exts[] = { "zip", NULL }; + static const gchar *compress_exts[] = { "Z", NULL }; + static const gchar *m4a_exts[] = { "m4a", NULL }; + static const gchar *q3gp_exts[] = { "3gp", NULL }; + static const gchar *aac_exts[] = { "aac", "adts", "adif", "loas", NULL }; + static const gchar *spc_exts[] = { "spc", NULL }; + static const gchar *wavpack_exts[] = { "wv", "wvp", NULL }; + static const gchar *wavpack_correction_exts[] = { "wvc", NULL }; + static const gchar *rar_exts[] = { "rar", NULL }; + static const gchar *tar_exts[] = { "tar", NULL }; + static const gchar *ar_exts[] = { "a", NULL }; + static const gchar *msdos_exts[] = { "dll", "exe", "ocx", "sys", "scr", + "msstyles", "cpl", NULL + }; + static const gchar *flv_exts[] = { "flv", NULL }; + static const gchar *m4v_exts[] = { "m4v", NULL }; + static const gchar *h263_exts[] = { "h263", "263", NULL }; + static const gchar *h264_exts[] = { "h264", "x264", "264", NULL }; + static const gchar *nuv_exts[] = { "nuv", NULL }; + static const gchar *vivo_exts[] = { "viv", NULL }; + static const gchar *nsf_exts[] = { "nsf", NULL }; + static const gchar *gym_exts[] = { "gym", NULL }; + static const gchar *ay_exts[] = { "ay", NULL }; + static const gchar *gbs_exts[] = { "gbs", NULL }; + static const gchar *kss_exts[] = { "kss", NULL }; + static const gchar *sap_exts[] = { "sap", NULL }; + static const gchar *vgm_exts[] = { "vgm", NULL }; + static const gchar *mid_exts[] = { "mid", "midi", NULL }; + static const gchar *mxmf_exts[] = { "mxmf", NULL }; + static const gchar *imelody_exts[] = { "imy", "ime", "imelody", NULL }; + static const gchar *pdf_exts[] = { "pdf", NULL }; + static const gchar *ps_exts[] = { "ps", NULL }; + static const gchar *svg_exts[] = { "svg", NULL }; + static const gchar *mxf_exts[] = { "mxf", NULL }; + static const gchar *ivf_exts[] = { "ivf", NULL }; + static const gchar *msword_exts[] = { "doc", NULL }; + static const gchar *dsstore_exts[] = { "DS_Store", NULL }; + static const gchar *psd_exts[] = { "psd", NULL }; + static const gchar *y4m_exts[] = { "y4m", NULL }; + + GST_DEBUG_CATEGORY_INIT (type_find_debug, "typefindfunctions", + GST_DEBUG_FG_GREEN | GST_DEBUG_BG_RED, "generic type find functions"); + + /* must use strings, macros don't accept initializers */ + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-ms-asf", GST_RANK_SECONDARY, + asf_exts, + "\060\046\262\165\216\146\317\021\246\331\000\252\000\142\316\154", 16, + GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/x-musepack", GST_RANK_PRIMARY, + musepack_type_find, musepack_exts, MUSEPACK_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-au", GST_RANK_MARGINAL, + au_type_find, au_exts, AU_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_RIFF (plugin, "video/x-msvideo", GST_RANK_PRIMARY, + avi_exts, "AVI "); + TYPE_FIND_REGISTER_RIFF (plugin, "audio/qcelp", GST_RANK_PRIMARY, + qcp_exts, "QLCM"); + TYPE_FIND_REGISTER_RIFF (plugin, "video/x-cdxa", GST_RANK_PRIMARY, + cdxa_exts, "CDXA"); + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-vcd", GST_RANK_PRIMARY, + cdxa_exts, "\000\377\377\377\377\377\377\377\377\377\377\000", 12, + GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-imelody", GST_RANK_PRIMARY, + imelody_exts, "BEGIN:IMELODY", 13, GST_TYPE_FIND_MAXIMUM); +#if 0 + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-smoke", GST_RANK_PRIMARY, + NULL, "\x80smoke\x00\x01\x00", 6, GST_TYPE_FIND_MAXIMUM); +#endif + TYPE_FIND_REGISTER (plugin, "audio/midi", GST_RANK_PRIMARY, mid_type_find, + mid_exts, MID_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_RIFF (plugin, "audio/riff-midi", GST_RANK_PRIMARY, + mid_exts, "RMID"); + TYPE_FIND_REGISTER (plugin, "audio/mobile-xmf", GST_RANK_PRIMARY, + mxmf_type_find, mxmf_exts, MXMF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-fli", GST_RANK_MARGINAL, flx_type_find, + flx_exts, FLX_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-id3v2", GST_RANK_PRIMARY + 103, + id3v2_type_find, id3_exts, ID3_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-id3v1", GST_RANK_PRIMARY + 101, + id3v1_type_find, id3_exts, ID3_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-apetag", GST_RANK_PRIMARY + 102, + apetag_type_find, apetag_exts, APETAG_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-ttafile", GST_RANK_PRIMARY, + tta_type_find, tta_exts, TTA_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-mod", GST_RANK_SECONDARY, mod_type_find, + mod_exts, MOD_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/mpeg", GST_RANK_PRIMARY, mp3_type_find, + mp3_exts, MP3_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-ac3", GST_RANK_PRIMARY, ac3_type_find, + ac3_exts, AC3_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-dts", GST_RANK_SECONDARY, dts_type_find, + dts_exts, DTS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-gsm", GST_RANK_PRIMARY, NULL, gsm_exts, + GSM_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/mpeg-sys", GST_RANK_PRIMARY, + mpeg_sys_type_find, mpeg_sys_exts, MPEG_SYS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/mpegts", GST_RANK_PRIMARY, + mpeg_ts_type_find, mpeg_ts_exts, MPEGTS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/ogg", GST_RANK_PRIMARY, + ogganx_type_find, ogg_exts, OGGANX_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/mpeg-elementary", GST_RANK_MARGINAL, + mpeg_video_stream_type_find, mpeg_video_exts, MPEG_VIDEO_CAPS, NULL, + NULL); + TYPE_FIND_REGISTER (plugin, "video/mpeg4", GST_RANK_PRIMARY, + mpeg4_video_type_find, m4v_exts, MPEG_VIDEO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-h263", GST_RANK_SECONDARY, + h263_video_type_find, h263_exts, H263_VIDEO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-h264", GST_RANK_PRIMARY, + h264_video_type_find, h264_exts, H264_VIDEO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-nuv", GST_RANK_SECONDARY, nuv_type_find, + nuv_exts, NUV_CAPS, NULL, NULL); + + /* ISO formats */ + TYPE_FIND_REGISTER (plugin, "audio/x-m4a", GST_RANK_PRIMARY, m4a_type_find, + m4a_exts, M4A_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-3gp", GST_RANK_PRIMARY, + q3gp_type_find, q3gp_exts, Q3GP_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/quicktime", GST_RANK_SECONDARY, + qt_type_find, qt_exts, QT_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/x-quicktime", GST_RANK_SECONDARY, + qtif_type_find, qtif_exts, QTIF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/jp2", GST_RANK_PRIMARY, + jp2_type_find, jp2_exts, JP2_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/mj2", GST_RANK_PRIMARY, + jp2_type_find, mj2_exts, MJ2_CAPS, NULL, NULL); + + TYPE_FIND_REGISTER (plugin, "text/html", GST_RANK_SECONDARY, html_type_find, + html_exts, HTML_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/vnd.rn-realmedia", + GST_RANK_SECONDARY, rm_exts, ".RMF", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-pn-realaudio", + GST_RANK_SECONDARY, rm_exts, ".ra\375", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "application/x-shockwave-flash", + GST_RANK_SECONDARY, swf_type_find, swf_exts, SWF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-flv", GST_RANK_SECONDARY, + flv_exts, "FLV", 3, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "text/plain", GST_RANK_MARGINAL, utf8_type_find, + utf8_exts, UTF8_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "text/uri-list", GST_RANK_MARGINAL, uri_type_find, + uri_exts, URI_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-hls", GST_RANK_MARGINAL, + hls_type_find, hls_exts, HLS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/sdp", GST_RANK_SECONDARY, + sdp_type_find, sdp_exts, SDP_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/smil", GST_RANK_SECONDARY, + smil_type_find, smil_exts, SMIL_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/xml", GST_RANK_MARGINAL, + xml_type_find, xml_exts, GENERIC_XML_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_RIFF (plugin, "audio/x-wav", GST_RANK_PRIMARY, wav_exts, + "WAVE"); + TYPE_FIND_REGISTER (plugin, "audio/x-aiff", GST_RANK_SECONDARY, + aiff_type_find, aiff_exts, AIFF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-svx", GST_RANK_SECONDARY, svx_type_find, + svx_exts, SVX_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-paris", GST_RANK_SECONDARY, + paris_type_find, paris_exts, PARIS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nist", GST_RANK_SECONDARY, + nist_exts, "NIST", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-voc", GST_RANK_SECONDARY, + voc_exts, "Creative", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/x-sds", GST_RANK_SECONDARY, sds_type_find, + sds_exts, SDS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-ircam", GST_RANK_SECONDARY, + ircam_type_find, ircam_exts, IRCAM_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-w64", GST_RANK_SECONDARY, + w64_exts, "riff", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/x-shorten", GST_RANK_SECONDARY, + shn_type_find, shn_exts, SHN_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ape", GST_RANK_SECONDARY, + ape_type_find, ape_exts, APE_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/jpeg", GST_RANK_PRIMARY + 15, + jpeg_type_find, jpeg_exts, JPEG_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/gif", GST_RANK_PRIMARY, + gif_exts, "GIF8", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/png", GST_RANK_PRIMARY + 14, + png_exts, "\211PNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "image/bmp", GST_RANK_PRIMARY, bmp_type_find, + bmp_exts, BMP_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/tiff", GST_RANK_PRIMARY, tiff_type_find, + tiff_exts, TIFF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/x-portable-pixmap", GST_RANK_SECONDARY, + pnm_type_find, pnm_exts, PNM_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-matroska", GST_RANK_PRIMARY, + matroska_type_find, matroska_exts, MATROSKA_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/webm", GST_RANK_PRIMARY, + webm_type_find, webm_exts, WEBM_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/mxf", GST_RANK_PRIMARY, + mxf_type_find, mxf_exts, MXF_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mve", GST_RANK_SECONDARY, + mve_exts, "Interplay MVE File\032\000\032\000\000\001\063\021", 26, + GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "video/x-dv", GST_RANK_SECONDARY, dv_type_find, + dv_exts, DV_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-nb-sh", GST_RANK_PRIMARY, + amr_exts, "#!AMR", 5, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-amr-wb-sh", GST_RANK_PRIMARY, + amr_exts, "#!AMR-WB", 7, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/iLBC-sh", GST_RANK_PRIMARY, + ilbc_type_find, ilbc_exts, ILBC_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-sid", GST_RANK_MARGINAL, + sid_exts, "PSID", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xcf", GST_RANK_SECONDARY, + xcf_exts, "gimp xcf", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-mng", GST_RANK_SECONDARY, + mng_exts, "\212MNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-jng", GST_RANK_SECONDARY, + jng_exts, "\213JNG\015\012\032\012", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-xpixmap", GST_RANK_SECONDARY, + xpm_exts, "/* XPM */", 9, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/x-sun-raster", + GST_RANK_SECONDARY, ras_exts, "\131\246\152\225", 4, + GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-bzip", + GST_RANK_SECONDARY, bz2_exts, "BZh", 3, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-gzip", + GST_RANK_SECONDARY, gz_exts, "\037\213", 2, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/zip", GST_RANK_SECONDARY, + zip_exts, "PK\003\004", 4, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-compress", + GST_RANK_SECONDARY, compress_exts, "\037\235", 2, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER (plugin, "subtitle/x-kate", GST_RANK_MARGINAL, + kate_type_find, NULL, NULL, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-flac", GST_RANK_PRIMARY, + flac_type_find, flac_exts, FLAC_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-vorbis", GST_RANK_PRIMARY, + vorbis_type_find, NULL, VORBIS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-theora", GST_RANK_PRIMARY, + theora_type_find, NULL, THEORA_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ogm-video", GST_RANK_PRIMARY, + ogmvideo_type_find, NULL, OGMVIDEO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ogm-audio", GST_RANK_PRIMARY, + ogmaudio_type_find, NULL, OGMAUDIO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ogm-text", GST_RANK_PRIMARY, + ogmtext_type_find, NULL, OGMTEXT_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-speex", GST_RANK_PRIMARY, + speex_type_find, NULL, SPEEX_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-celt", GST_RANK_PRIMARY, + celt_type_find, NULL, CELT_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ogg-skeleton", GST_RANK_PRIMARY, + oggskel_type_find, NULL, OGG_SKELETON_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "text/x-cmml", GST_RANK_PRIMARY, cmml_type_find, + NULL, CMML_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-executable", + GST_RANK_MARGINAL, NULL, "\177ELF", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/aac", GST_RANK_SECONDARY, + aac_type_find, aac_exts, AAC_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-spc", GST_RANK_SECONDARY, + spc_exts, "SNES-SPC700 Sound File Data", 27, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER (plugin, "audio/x-wavpack", GST_RANK_SECONDARY, + wavpack_type_find, wavpack_exts, WAVPACK_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "audio/x-wavpack-correction", GST_RANK_SECONDARY, + wavpack_type_find, wavpack_correction_exts, WAVPACK_CORRECTION_CAPS, NULL, + NULL); + TYPE_FIND_REGISTER (plugin, "application/postscript", GST_RANK_SECONDARY, + postscript_type_find, ps_exts, POSTSCRIPT_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "image/svg+xml", GST_RANK_SECONDARY, + svg_type_find, svg_exts, SVG_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-rar", + GST_RANK_SECONDARY, rar_exts, "Rar!", 4, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER (plugin, "application/x-tar", GST_RANK_SECONDARY, + tar_type_find, tar_exts, TAR_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ar", GST_RANK_SECONDARY, + ar_type_find, ar_exts, AR_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-ms-dos-executable", + GST_RANK_SECONDARY, msdos_type_find, msdos_exts, MSDOS_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/x-dirac", GST_RANK_PRIMARY, + dirac_type_find, NULL, DIRAC_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "multipart/x-mixed-replace", GST_RANK_SECONDARY, + multipart_type_find, NULL, MULTIPART_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "application/x-mmsh", GST_RANK_SECONDARY, + mmsh_type_find, NULL, MMSH_CAPS, NULL, NULL); + TYPE_FIND_REGISTER (plugin, "video/vivo", GST_RANK_SECONDARY, + vivo_type_find, vivo_exts, VIVO_CAPS, NULL, NULL); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-nsf", + GST_RANK_SECONDARY, nsf_exts, "NESM\x1a", 5, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-gym", + GST_RANK_SECONDARY, gym_exts, "GYMX", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-ay", + GST_RANK_SECONDARY, ay_exts, "ZXAYEMUL", 8, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-gbs", + GST_RANK_SECONDARY, gbs_exts, "GBS\x01", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-vgm", + GST_RANK_SECONDARY, vgm_exts, "Vgm\x20", 4, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-sap", + GST_RANK_SECONDARY, sap_exts, "SAP\x0d\x0aAUTHOR\x20", 12, + GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "video/x-ivf", GST_RANK_SECONDARY, + ivf_exts, "DKIF", 4, GST_TYPE_FIND_NEARLY_CERTAIN); + TYPE_FIND_REGISTER_START_WITH (plugin, "audio/x-kss", GST_RANK_SECONDARY, + kss_exts, "KSSX\0", 5, GST_TYPE_FIND_MAXIMUM); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/pdf", GST_RANK_SECONDARY, + pdf_exts, "%PDF-", 5, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/msword", + GST_RANK_SECONDARY, msword_exts, "\320\317\021\340\241\261\032\341", 8, + GST_TYPE_FIND_LIKELY); + /* Mac OS X .DS_Store files tend to be taken for video/mpeg */ + TYPE_FIND_REGISTER_START_WITH (plugin, "application/octet-stream", + GST_RANK_SECONDARY, dsstore_exts, "\000\000\000\001Bud1", 8, + GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "image/vnd.adobe.photoshop", + GST_RANK_SECONDARY, psd_exts, "8BPS\000\001\000\000\000\000", 10, + GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER_START_WITH (plugin, "application/x-yuv4mpeg", + GST_RANK_SECONDARY, y4m_exts, "YUV4MPEG2 ", 10, GST_TYPE_FIND_LIKELY); + TYPE_FIND_REGISTER (plugin, "image/x-icon", GST_RANK_MARGINAL, + windows_icon_typefind, NULL, NULL, NULL, NULL); + +#ifdef USE_GIO + TYPE_FIND_REGISTER (plugin, "xdgmime-base", GST_RANK_MARGINAL, + xdgmime_typefind, NULL, NULL, NULL, NULL); +#endif + + TYPE_FIND_REGISTER (plugin, "image/x-degas", GST_RANK_MARGINAL, + degas_type_find, NULL, NULL, NULL, NULL); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "typefindfunctions", + "default typefind functions", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/typefind/typefindfunctions.vcproj b/gst-plugins-base-subtitles0.10/gst/typefind/typefindfunctions.vcproj new file mode 100644 index 0000000..0a8922c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/typefind/typefindfunctions.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/videorate/Makefile.am b/gst-plugins-base-subtitles0.10/gst/videorate/Makefile.am new file mode 100644 index 0000000..fe9b996 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videorate/Makefile.am @@ -0,0 +1,23 @@ +noinst_HEADERS = gstvideorate.h + +plugin_LTLIBRARIES = libgstvideorate.la + +libgstvideorate_la_SOURCES = gstvideorate.c +libgstvideorate_la_CFLAGS = $(GST_CFLAGS) +libgstvideorate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideorate_la_LIBADD = $(GST_LIBS) +libgstvideorate_la_LIBTOOLFLAGS = --tag=disable-static + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstvideorate -:SHARED libgstvideorate \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstvideorate_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideorate_la_CFLAGS) \ + -:LDFLAGS $(libgstvideorate_la_LDFLAGS) \ + $(libgstvideorate_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.c b/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.c new file mode 100644 index 0000000..4f53c81 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.c @@ -0,0 +1,1024 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-videorate + * + * This element takes an incoming stream of timestamped video frames. + * It will produce a perfect stream that matches the source pad's framerate. + * + * The correction is performed by dropping and duplicating frames, no fancy + * algorithm is used to interpolate frames (yet). + * + * By default the element will simply negotiate the same framerate on its + * source and sink pad. + * + * This operation is useful to link to elements that require a perfect stream. + * Typical examples are formats that do not store timestamps for video frames, + * but only store a framerate, like Ogg and AVI. + * + * A conversion to a specific framerate can be forced by using filtered caps on + * the source pad. + * + * The properties #GstVideoRate:in, #GstVideoRate:out, #GstVideoRate:duplicate + * and #GstVideoRate:drop can be read to obtain information about number of + * input frames, output frames, dropped frames (i.e. the number of unused input + * frames) and duplicated frames (i.e. the number of times an input frame was + * duplicated, beside being used normally). + * + * An input stream that needs no adjustments will thus never have dropped or + * duplicated frames. + * + * When the #GstVideoRate:silent property is set to FALSE, a GObject property + * notification will be emitted whenever one of the #GstVideoRate:duplicate or + * #GstVideoRate:drop values changes. + * This can potentially cause performance degradation. + * Note that property notification will happen from the streaming thread, so + * applications should be prepared for this. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videorate ! video/x-raw-yuv,framerate=15/1 ! xvimagesink + * ]| Decode an Ogg/Theora file and adjust the framerate to 15 fps before playing. + * To create the test Ogg/Theora file refer to the documentation of theoraenc. + * |[ + * gst-launch -v v4lsrc ! videorate ! video/x-raw-yuv,framerate=25/2 ! theoraenc ! oggmux ! filesink location=v4l.ogg + * ]| Capture video from a V4L device, and adjust the stream to 12.5 fps before + * encoding to Ogg/Theora. + * + * + * Last reviewed on 2006-09-02 (0.10.11) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvideorate.h" + +GST_DEBUG_CATEGORY_STATIC (video_rate_debug); +#define GST_CAT_DEFAULT video_rate_debug + +/* GstVideoRate signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_SILENT TRUE +#define DEFAULT_NEW_PREF 1.0 +#define DEFAULT_SKIP_TO_FIRST FALSE + +enum +{ + ARG_0, + ARG_IN, + ARG_OUT, + ARG_DUP, + ARG_DROP, + ARG_SILENT, + ARG_NEW_PREF, + ARG_SKIP_TO_FIRST + /* FILL ME */ +}; + +static GstStaticPadTemplate gst_video_rate_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv;" + "video/x-raw-rgb;" "video/x-raw-gray;" "image/jpeg;" "image/png") + ); + +static GstStaticPadTemplate gst_video_rate_sink_template = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv;" + "video/x-raw-rgb;" "video/x-raw-gray;" "image/jpeg;" "image/png") + ); + +static void gst_video_rate_swap_prev (GstVideoRate * videorate, + GstBuffer * buffer, gint64 time); +static gboolean gst_video_rate_event (GstPad * pad, GstEvent * event); +static gboolean gst_video_rate_query (GstPad * pad, GstQuery * query); +static GstFlowReturn gst_video_rate_chain (GstPad * pad, GstBuffer * buffer); + +static void gst_video_rate_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_video_rate_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_video_rate_change_state (GstElement * element, + GstStateChange transition); + +/*static guint gst_video_rate_signals[LAST_SIGNAL] = { 0 }; */ + +static GParamSpec *pspec_drop = NULL; +static GParamSpec *pspec_duplicate = NULL; + +GST_BOILERPLATE (GstVideoRate, gst_video_rate, GstElement, GST_TYPE_ELEMENT); + +static void +gst_video_rate_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Video rate adjuster", "Filter/Effect/Video", + "Drops/duplicates/adjusts timestamps on video frames to make a perfect stream", + "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_video_rate_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_video_rate_src_template)); +} + +static void +gst_video_rate_class_init (GstVideoRateClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + object_class->set_property = gst_video_rate_set_property; + object_class->get_property = gst_video_rate_get_property; + + g_object_class_install_property (object_class, ARG_IN, + g_param_spec_uint64 ("in", "In", + "Number of input frames", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, ARG_OUT, + g_param_spec_uint64 ("out", "Out", "Number of output frames", 0, + G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + pspec_duplicate = g_param_spec_uint64 ("duplicate", "Duplicate", + "Number of duplicated frames", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, ARG_DUP, pspec_duplicate); + pspec_drop = g_param_spec_uint64 ("drop", "Drop", "Number of dropped frames", + 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, ARG_DROP, pspec_drop); + g_object_class_install_property (object_class, ARG_SILENT, + g_param_spec_boolean ("silent", "silent", + "Don't emit notify for dropped and duplicated frames", DEFAULT_SILENT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, ARG_NEW_PREF, + g_param_spec_double ("new-pref", "New Pref", + "Value indicating how much to prefer new frames (unused)", 0.0, 1.0, + DEFAULT_NEW_PREF, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstVideoRate:skip-to-first: + * + * Don't produce buffers before the first one we receive. + * + * Since: 0.10.25 + */ + g_object_class_install_property (object_class, ARG_SKIP_TO_FIRST, + g_param_spec_boolean ("skip-to-first", "Skip to first buffer", + "Don't produce buffers before the first one we receive", + DEFAULT_SKIP_TO_FIRST, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_video_rate_change_state); +} + +/* return the caps that can be used on out_pad given in_caps on in_pad */ +static gboolean +gst_video_rate_transformcaps (GstPad * in_pad, GstCaps * in_caps, + GstPad * out_pad, GstCaps ** out_caps) +{ + GstCaps *intersect; + const GstCaps *in_templ; + gint i; + GSList *extra_structures = NULL; + GSList *iter; + + in_templ = gst_pad_get_pad_template_caps (in_pad); + intersect = gst_caps_intersect (in_caps, in_templ); + + /* all possible framerates are allowed */ + for (i = 0; i < gst_caps_get_size (intersect); i++) { + GstStructure *structure; + + structure = gst_caps_get_structure (intersect, i); + + if (gst_structure_has_field (structure, "framerate")) { + GstStructure *copy_structure; + + copy_structure = gst_structure_copy (structure); + gst_structure_set (copy_structure, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + extra_structures = g_slist_append (extra_structures, copy_structure); + } + } + + /* append the extra structures */ + for (iter = extra_structures; iter != NULL; iter = g_slist_next (iter)) { + gst_caps_append_structure (intersect, (GstStructure *) iter->data); + } + g_slist_free (extra_structures); + + *out_caps = intersect; + + return TRUE; +} + +static GstCaps * +gst_video_rate_getcaps (GstPad * pad) +{ + GstVideoRate *videorate; + GstPad *otherpad; + GstCaps *caps; + + videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad)); + + otherpad = (pad == videorate->srcpad) ? videorate->sinkpad : + videorate->srcpad; + + /* we can do what the peer can */ + caps = gst_pad_peer_get_caps (otherpad); + if (caps) { + GstCaps *transform; + + gst_video_rate_transformcaps (otherpad, caps, pad, &transform); + gst_caps_unref (caps); + caps = transform; + } else { + /* no peer, our padtemplate is enough then */ + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + return caps; +} + +static gboolean +gst_video_rate_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVideoRate *videorate; + GstStructure *structure; + gboolean ret = TRUE; + GstPad *otherpad, *opeer; + gint rate_numerator, rate_denominator; + + videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "setcaps called %" GST_PTR_FORMAT, caps); + + structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_fraction (structure, "framerate", + &rate_numerator, &rate_denominator)) + goto no_framerate; + + if (pad == videorate->srcpad) { + /* out_frame_count is scaled by the frame rate caps when calculating next_ts. + * when the frame rate caps change, we must update base_ts and reset + * out_frame_count */ + if (videorate->to_rate_numerator) { + videorate->base_ts += + gst_util_uint64_scale (videorate->out_frame_count, + videorate->to_rate_denominator * GST_SECOND, + videorate->to_rate_numerator); + } + videorate->out_frame_count = 0; + videorate->to_rate_numerator = rate_numerator; + videorate->to_rate_denominator = rate_denominator; + otherpad = videorate->sinkpad; + } else { + videorate->from_rate_numerator = rate_numerator; + videorate->from_rate_denominator = rate_denominator; + otherpad = videorate->srcpad; + } + + /* now try to find something for the peer */ + opeer = gst_pad_get_peer (otherpad); + if (opeer) { + if (gst_pad_accept_caps (opeer, caps)) { + /* the peer accepts the caps as they are */ + gst_pad_set_caps (otherpad, caps); + + ret = TRUE; + } else { + GstCaps *peercaps; + GstCaps *transform = NULL; + + ret = FALSE; + + /* see how we can transform the input caps */ + if (!gst_video_rate_transformcaps (pad, caps, otherpad, &transform)) + goto no_transform; + + /* see what the peer can do */ + peercaps = gst_pad_get_caps (opeer); + + GST_DEBUG_OBJECT (opeer, "icaps %" GST_PTR_FORMAT, peercaps); + GST_DEBUG_OBJECT (videorate, "transform %" GST_PTR_FORMAT, transform); + + /* filter against our possibilities */ + caps = gst_caps_intersect (peercaps, transform); + gst_caps_unref (peercaps); + gst_caps_unref (transform); + + GST_DEBUG_OBJECT (videorate, "intersect %" GST_PTR_FORMAT, caps); + + /* could turn up empty, due to e.g. colorspace etc */ + if (gst_caps_get_size (caps) == 0) { + gst_caps_unref (caps); + goto no_transform; + } + + /* take first possibility */ + gst_caps_truncate (caps); + structure = gst_caps_get_structure (caps, 0); + + /* and fixate */ + gst_structure_fixate_field_nearest_fraction (structure, "framerate", + rate_numerator, rate_denominator); + + gst_structure_get_fraction (structure, "framerate", + &rate_numerator, &rate_denominator); + + if (otherpad == videorate->srcpad) { + videorate->to_rate_numerator = rate_numerator; + videorate->to_rate_denominator = rate_denominator; + } else { + videorate->from_rate_numerator = rate_numerator; + videorate->from_rate_denominator = rate_denominator; + } + + if (gst_structure_has_field (structure, "interlaced")) + gst_structure_fixate_field_boolean (structure, "interlaced", FALSE); + if (gst_structure_has_field (structure, "color-matrix")) + gst_structure_fixate_field_string (structure, "color-matrix", "sdtv"); + if (gst_structure_has_field (structure, "chroma-site")) + gst_structure_fixate_field_string (structure, "chroma-site", "mpeg2"); + if (gst_structure_has_field (structure, "pixel-aspect-ratio")) + gst_structure_fixate_field_nearest_fraction (structure, + "pixel-aspect-ratio", 1, 1); + + gst_pad_set_caps (otherpad, caps); + gst_caps_unref (caps); + ret = TRUE; + } + gst_object_unref (opeer); + } +done: + /* After a setcaps, our caps may have changed. In that case, we can't use + * the old buffer, if there was one (it might have different dimensions) */ + GST_DEBUG_OBJECT (videorate, "swapping old buffers"); + gst_video_rate_swap_prev (videorate, NULL, GST_CLOCK_TIME_NONE); + + gst_object_unref (videorate); + return ret; + +no_framerate: + { + GST_DEBUG_OBJECT (videorate, "no framerate specified"); + goto done; + } +no_transform: + { + GST_DEBUG_OBJECT (videorate, "no framerate transform possible"); + ret = FALSE; + goto done; + } +} + +static void +gst_video_rate_reset (GstVideoRate * videorate) +{ + GST_DEBUG_OBJECT (videorate, "resetting internal variables"); + + videorate->in = 0; + videorate->out = 0; + videorate->base_ts = 0; + videorate->out_frame_count = 0; + videorate->drop = 0; + videorate->dup = 0; + videorate->next_ts = GST_CLOCK_TIME_NONE; + videorate->last_ts = GST_CLOCK_TIME_NONE; + videorate->discont = TRUE; + gst_video_rate_swap_prev (videorate, NULL, 0); + + gst_segment_init (&videorate->segment, GST_FORMAT_TIME); +} + +static void +gst_video_rate_init (GstVideoRate * videorate, GstVideoRateClass * klass) +{ + videorate->sinkpad = + gst_pad_new_from_static_template (&gst_video_rate_sink_template, "sink"); + gst_pad_set_event_function (videorate->sinkpad, + GST_DEBUG_FUNCPTR (gst_video_rate_event)); + gst_pad_set_chain_function (videorate->sinkpad, + GST_DEBUG_FUNCPTR (gst_video_rate_chain)); + gst_pad_set_getcaps_function (videorate->sinkpad, + GST_DEBUG_FUNCPTR (gst_video_rate_getcaps)); + gst_pad_set_setcaps_function (videorate->sinkpad, + GST_DEBUG_FUNCPTR (gst_video_rate_setcaps)); + gst_element_add_pad (GST_ELEMENT (videorate), videorate->sinkpad); + + videorate->srcpad = + gst_pad_new_from_static_template (&gst_video_rate_src_template, "src"); + gst_pad_set_query_function (videorate->srcpad, + GST_DEBUG_FUNCPTR (gst_video_rate_query)); + gst_pad_set_getcaps_function (videorate->srcpad, + GST_DEBUG_FUNCPTR (gst_video_rate_getcaps)); + gst_pad_set_setcaps_function (videorate->srcpad, + GST_DEBUG_FUNCPTR (gst_video_rate_setcaps)); + gst_element_add_pad (GST_ELEMENT (videorate), videorate->srcpad); + + gst_video_rate_reset (videorate); + videorate->silent = DEFAULT_SILENT; + videorate->new_pref = DEFAULT_NEW_PREF; + + videorate->from_rate_numerator = 0; + videorate->from_rate_denominator = 0; + videorate->to_rate_numerator = 0; + videorate->to_rate_denominator = 0; +} + +/* flush the oldest buffer */ +static GstFlowReturn +gst_video_rate_flush_prev (GstVideoRate * videorate, gboolean duplicate) +{ + GstFlowReturn res; + GstBuffer *outbuf; + GstClockTime push_ts; + + if (!videorate->prevbuf) + goto eos_before_buffers; + + /* make sure we can write to the metadata */ + outbuf = gst_buffer_make_metadata_writable + (gst_buffer_ref (videorate->prevbuf)); + + GST_BUFFER_OFFSET (outbuf) = videorate->out; + GST_BUFFER_OFFSET_END (outbuf) = videorate->out + 1; + + if (videorate->discont) { + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT); + videorate->discont = FALSE; + } else + GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DISCONT); + + if (duplicate) + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); + else + GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_GAP); + + /* this is the timestamp we put on the buffer */ + push_ts = videorate->next_ts; + + videorate->out++; + videorate->out_frame_count++; + if (videorate->to_rate_numerator) { + /* interpolate next expected timestamp in the segment */ + videorate->next_ts = + videorate->segment.accum + videorate->segment.start + + videorate->base_ts + gst_util_uint64_scale (videorate->out_frame_count, + videorate->to_rate_denominator * GST_SECOND, + videorate->to_rate_numerator); + GST_BUFFER_DURATION (outbuf) = videorate->next_ts - push_ts; + } + + /* adapt for looping, bring back to time in current segment. */ + GST_BUFFER_TIMESTAMP (outbuf) = push_ts - videorate->segment.accum; + + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (videorate->srcpad)); + + GST_LOG_OBJECT (videorate, + "old is best, dup, pushing buffer outgoing ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (push_ts)); + + res = gst_pad_push (videorate->srcpad, outbuf); + + return res; + + /* WARNINGS */ +eos_before_buffers: + { + GST_INFO_OBJECT (videorate, "got EOS before any buffer was received"); + return GST_FLOW_OK; + } +} + +static void +gst_video_rate_swap_prev (GstVideoRate * videorate, GstBuffer * buffer, + gint64 time) +{ + GST_LOG_OBJECT (videorate, "swap_prev: storing buffer %p in prev", buffer); + if (videorate->prevbuf) + gst_buffer_unref (videorate->prevbuf); + videorate->prevbuf = buffer; + videorate->prev_ts = time; +} + +static void +gst_video_rate_notify_drop (GstVideoRate * videorate) +{ +#if !GLIB_CHECK_VERSION(2,26,0) + g_object_notify ((GObject *) videorate, "drop"); +#else + g_object_notify_by_pspec ((GObject *) videorate, pspec_drop); +#endif +} + +static void +gst_video_rate_notify_duplicate (GstVideoRate * videorate) +{ +#if !GLIB_CHECK_VERSION(2,26,0) + g_object_notify ((GObject *) videorate, "duplicate"); +#else + g_object_notify_by_pspec ((GObject *) videorate, pspec_duplicate); +#endif +} + +#define MAGIC_LIMIT 25 +static gboolean +gst_video_rate_event (GstPad * pad, GstEvent * event) +{ + GstVideoRate *videorate; + gboolean ret; + + videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + gint64 start, stop, time; + gdouble rate, arate; + gboolean update; + GstFormat format; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + if (format != GST_FORMAT_TIME) + goto format_error; + + GST_DEBUG_OBJECT (videorate, "handle NEWSEGMENT"); + + /* close up the previous segment, if appropriate */ + if (!update && videorate->prevbuf) { + gint count = 0; + GstFlowReturn res; + + res = GST_FLOW_OK; + /* fill up to the end of current segment, + * or only send out the stored buffer if there is no specific stop. + * regardless, prevent going loopy in strange cases */ + while (res == GST_FLOW_OK && count <= MAGIC_LIMIT && + ((GST_CLOCK_TIME_IS_VALID (videorate->segment.stop) && + videorate->next_ts - videorate->segment.accum + < videorate->segment.stop) + || count < 1)) { + res = gst_video_rate_flush_prev (videorate, count > 0); + count++; + } + if (count > 1) { + videorate->dup += count - 1; + if (!videorate->silent) + gst_video_rate_notify_duplicate (videorate); + } else if (count == 0) { + videorate->drop++; + if (!videorate->silent) + gst_video_rate_notify_drop (videorate); + } + /* clean up for the new one; _chain will resume from the new start */ + videorate->base_ts = 0; + videorate->out_frame_count = 0; + gst_video_rate_swap_prev (videorate, NULL, 0); + videorate->next_ts = GST_CLOCK_TIME_NONE; + } + + /* We just want to update the accumulated stream_time */ + gst_segment_set_newsegment_full (&videorate->segment, update, rate, arate, + format, start, stop, time); + + GST_DEBUG_OBJECT (videorate, "updated segment: %" GST_SEGMENT_FORMAT, + &videorate->segment); + break; + } + case GST_EVENT_EOS:{ + gint count = 0; + GstFlowReturn res = GST_FLOW_OK; + + GST_DEBUG_OBJECT (videorate, "Got EOS"); + + /* If the segment has a stop position, fill the segment */ + if (GST_CLOCK_TIME_IS_VALID (videorate->segment.stop)) { + /* fill up to the end of current segment, + * or only send out the stored buffer if there is no specific stop. + * regardless, prevent going loopy in strange cases */ + while (res == GST_FLOW_OK && count <= MAGIC_LIMIT && + ((videorate->next_ts - videorate->segment.accum < + videorate->segment.stop) + || count < 1)) { + res = gst_video_rate_flush_prev (videorate, count > 0); + count++; + } + } else if (videorate->prevbuf) { + /* Output at least one frame but if the buffer duration is valid, output + * enough frames to use the complete buffer duration */ + if (GST_BUFFER_DURATION_IS_VALID (videorate->prevbuf)) { + GstClockTime end_ts = + videorate->next_ts + GST_BUFFER_DURATION (videorate->prevbuf); + + while (res == GST_FLOW_OK && count <= MAGIC_LIMIT && + ((videorate->next_ts - videorate->segment.accum < end_ts) + || count < 1)) { + res = gst_video_rate_flush_prev (videorate, count > 0); + count++; + } + } else { + res = gst_video_rate_flush_prev (videorate, FALSE); + count = 1; + } + } + + if (count > 1) { + videorate->dup += count - 1; + if (!videorate->silent) + gst_video_rate_notify_duplicate (videorate); + } else if (count == 0) { + videorate->drop++; + if (!videorate->silent) + gst_video_rate_notify_drop (videorate); + } + + break; + } + case GST_EVENT_FLUSH_STOP: + /* also resets the segment */ + GST_DEBUG_OBJECT (videorate, "Got FLUSH_STOP"); + gst_video_rate_reset (videorate); + break; + default: + break; + } + + ret = gst_pad_push_event (videorate->srcpad, event); + +done: + gst_object_unref (videorate); + + return ret; + + /* ERRORS */ +format_error: + { + GST_WARNING_OBJECT (videorate, + "Got segment but doesn't have GST_FORMAT_TIME value"); + gst_event_unref (event); + ret = FALSE; + goto done; + } +} + +static gboolean +gst_video_rate_query (GstPad * pad, GstQuery * query) +{ + GstVideoRate *videorate; + gboolean res = FALSE; + + videorate = GST_VIDEO_RATE (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GstClockTime min, max; + gboolean live; + guint64 latency; + GstPad *peer; + + if ((peer = gst_pad_get_peer (videorate->sinkpad))) { + if ((res = gst_pad_query (peer, query))) { + gst_query_parse_latency (query, &live, &min, &max); + + GST_DEBUG_OBJECT (videorate, "Peer latency: min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + if (videorate->from_rate_numerator != 0) { + /* add latency. We don't really know since we hold on to the frames + * until we get a next frame, which can be anything. We assume + * however that this will take from_rate time. */ + latency = gst_util_uint64_scale (GST_SECOND, + videorate->from_rate_denominator, + videorate->from_rate_numerator); + } else { + /* no input framerate, we don't know */ + latency = 0; + } + + GST_DEBUG_OBJECT (videorate, "Our latency: %" + GST_TIME_FORMAT, GST_TIME_ARGS (latency)); + + min += latency; + if (max != -1) + max += latency; + + GST_DEBUG_OBJECT (videorate, "Calculated total latency : min %" + GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min), GST_TIME_ARGS (max)); + + gst_query_set_latency (query, live, min, max); + } + gst_object_unref (peer); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + gst_object_unref (videorate); + + return res; +} + +static GstFlowReturn +gst_video_rate_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVideoRate *videorate; + GstFlowReturn res = GST_FLOW_OK; + GstClockTime intime, in_ts, in_dur; + + videorate = GST_VIDEO_RATE (GST_PAD_PARENT (pad)); + + /* make sure the denominators are not 0 */ + if (videorate->from_rate_denominator == 0 || + videorate->to_rate_denominator == 0) + goto not_negotiated; + + in_ts = GST_BUFFER_TIMESTAMP (buffer); + in_dur = GST_BUFFER_DURATION (buffer); + + if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) { + in_ts = videorate->last_ts; + if (G_UNLIKELY (in_ts == GST_CLOCK_TIME_NONE)) + goto invalid_buffer; + } + + /* get the time of the next expected buffer timestamp, we use this when the + * next buffer has -1 as a timestamp */ + videorate->last_ts = in_ts; + if (in_dur != GST_CLOCK_TIME_NONE) + videorate->last_ts += in_dur; + + GST_DEBUG_OBJECT (videorate, "got buffer with timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (in_ts)); + + /* the input time is the time in the segment + all previously accumulated + * segments */ + intime = in_ts + videorate->segment.accum; + + /* we need to have two buffers to compare */ + if (videorate->prevbuf == NULL) { + gst_video_rate_swap_prev (videorate, buffer, intime); + videorate->in++; + if (!GST_CLOCK_TIME_IS_VALID (videorate->next_ts)) { + /* new buffer, we expect to output a buffer that matches the first + * timestamp in the segment */ + if (videorate->skip_to_first) { + videorate->next_ts = intime; + videorate->base_ts = in_ts - videorate->segment.start; + videorate->out_frame_count = 0; + } else { + videorate->next_ts = + videorate->segment.start + videorate->segment.accum; + } + } + } else { + GstClockTime prevtime; + gint count = 0; + gint64 diff1, diff2; + + prevtime = videorate->prev_ts; + + GST_LOG_OBJECT (videorate, + "BEGINNING prev buf %" GST_TIME_FORMAT " new buf %" GST_TIME_FORMAT + " outgoing ts %" GST_TIME_FORMAT, GST_TIME_ARGS (prevtime), + GST_TIME_ARGS (intime), GST_TIME_ARGS (videorate->next_ts)); + + videorate->in++; + + /* drop new buffer if it's before previous one */ + if (intime < prevtime) { + GST_DEBUG_OBJECT (videorate, + "The new buffer (%" GST_TIME_FORMAT + ") is before the previous buffer (%" + GST_TIME_FORMAT "). Dropping new buffer.", + GST_TIME_ARGS (intime), GST_TIME_ARGS (prevtime)); + videorate->drop++; + if (!videorate->silent) + gst_video_rate_notify_drop (videorate); + gst_buffer_unref (buffer); + goto done; + } + + /* got 2 buffers, see which one is the best */ + do { + + diff1 = prevtime - videorate->next_ts; + diff2 = intime - videorate->next_ts; + + /* take absolute values, beware: abs and ABS don't work for gint64 */ + if (diff1 < 0) + diff1 = -diff1; + if (diff2 < 0) + diff2 = -diff2; + + GST_LOG_OBJECT (videorate, + "diff with prev %" GST_TIME_FORMAT " diff with new %" + GST_TIME_FORMAT " outgoing ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (diff1), GST_TIME_ARGS (diff2), + GST_TIME_ARGS (videorate->next_ts)); + + /* output first one when its the best */ + if (diff1 <= diff2) { + count++; + + /* on error the _flush function posted a warning already */ + if ((res = + gst_video_rate_flush_prev (videorate, + count > 1)) != GST_FLOW_OK) { + gst_buffer_unref (buffer); + goto done; + } + } + /* continue while the first one was the best, if they were equal avoid + * going into an infinite loop */ + } + while (diff1 < diff2); + + /* if we outputed the first buffer more then once, we have dups */ + if (count > 1) { + videorate->dup += count - 1; + if (!videorate->silent) + gst_video_rate_notify_duplicate (videorate); + } + /* if we didn't output the first buffer, we have a drop */ + else if (count == 0) { + videorate->drop++; + + if (!videorate->silent) + gst_video_rate_notify_drop (videorate); + + GST_LOG_OBJECT (videorate, + "new is best, old never used, drop, outgoing ts %" + GST_TIME_FORMAT, GST_TIME_ARGS (videorate->next_ts)); + } + GST_LOG_OBJECT (videorate, + "END, putting new in old, diff1 %" GST_TIME_FORMAT + ", diff2 %" GST_TIME_FORMAT ", next_ts %" GST_TIME_FORMAT + ", in %" G_GUINT64_FORMAT ", out %" G_GUINT64_FORMAT ", drop %" + G_GUINT64_FORMAT ", dup %" G_GUINT64_FORMAT, GST_TIME_ARGS (diff1), + GST_TIME_ARGS (diff2), GST_TIME_ARGS (videorate->next_ts), + videorate->in, videorate->out, videorate->drop, videorate->dup); + + /* swap in new one when it's the best */ + gst_video_rate_swap_prev (videorate, buffer, intime); + } +done: + return res; + + /* ERRORS */ +not_negotiated: + { + GST_WARNING_OBJECT (videorate, "no framerate negotiated"); + gst_buffer_unref (buffer); + res = GST_FLOW_NOT_NEGOTIATED; + goto done; + } + +invalid_buffer: + { + GST_WARNING_OBJECT (videorate, + "Got buffer with GST_CLOCK_TIME_NONE timestamp, discarding it"); + gst_buffer_unref (buffer); + goto done; + } +} + +static void +gst_video_rate_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstVideoRate *videorate = GST_VIDEO_RATE (object); + + switch (prop_id) { + case ARG_SILENT: + videorate->silent = g_value_get_boolean (value); + break; + case ARG_NEW_PREF: + videorate->new_pref = g_value_get_double (value); + break; + case ARG_SKIP_TO_FIRST: + videorate->skip_to_first = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_rate_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstVideoRate *videorate = GST_VIDEO_RATE (object); + + switch (prop_id) { + case ARG_IN: + g_value_set_uint64 (value, videorate->in); + break; + case ARG_OUT: + g_value_set_uint64 (value, videorate->out); + break; + case ARG_DUP: + g_value_set_uint64 (value, videorate->dup); + break; + case ARG_DROP: + g_value_set_uint64 (value, videorate->drop); + break; + case ARG_SILENT: + g_value_set_boolean (value, videorate->silent); + break; + case ARG_NEW_PREF: + g_value_set_double (value, videorate->new_pref); + break; + case ARG_SKIP_TO_FIRST: + g_value_set_boolean (value, videorate->skip_to_first); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_video_rate_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret; + GstVideoRate *videorate; + + videorate = GST_VIDEO_RATE (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + videorate->discont = TRUE; + videorate->last_ts = -1; + break; + default: + break; + } + + ret = parent_class->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_video_rate_reset (videorate); + break; + default: + break; + } + + return ret; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (video_rate_debug, "videorate", 0, + "VideoRate stream fixer"); + + return gst_element_register (plugin, "videorate", GST_RANK_NONE, + GST_TYPE_VIDEO_RATE); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videorate", + "Adjusts video frames", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.h b/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.h new file mode 100644 index 0000000..23e2056 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videorate/gstvideorate.h @@ -0,0 +1,85 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VIDEO_RATE_H__ +#define __GST_VIDEO_RATE_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_RATE \ + (gst_video_rate_get_type()) +#define GST_VIDEO_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_RATE,GstVideoRate)) +#define GST_VIDEO_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_RATE,GstVideoRateClass)) +#define GST_IS_VIDEO_RATE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_RATE)) +#define GST_IS_VIDEO_RATE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_RATE)) + +typedef struct _GstVideoRate GstVideoRate; +typedef struct _GstVideoRateClass GstVideoRateClass; + +/** + * GstVideoRate: + * + * Opaque data structure. + */ +struct _GstVideoRate +{ + GstElement element; + + GstPad *sinkpad, *srcpad; + + /* video state */ + gint from_rate_numerator, from_rate_denominator; + gint to_rate_numerator, to_rate_denominator; + guint64 next_ts; /* Timestamp of next buffer to output */ + GstBuffer *prevbuf; + guint64 prev_ts; /* Previous buffer timestamp */ + guint64 out_frame_count; /* number of frames output since the beginning + * of the segment or the last frame rate caps + * change, whichever was later */ + guint64 base_ts; /* used in next_ts calculation after a + * frame rate caps change */ + gboolean discont; + guint64 last_ts; /* Timestamp of last input buffer */ + + /* segment handling */ + GstSegment segment; + + /* properties */ + guint64 in, out, dup, drop; + gboolean silent; + gdouble new_pref; + gboolean skip_to_first; +}; + +struct _GstVideoRateClass +{ + GstElementClass parent_class; +}; + +GType gst_video_rate_get_type (void); + +G_END_DECLS + +#endif /* __GST_VIDEO_RATE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/videorate/videorate.vcproj b/gst-plugins-base-subtitles0.10/gst/videorate/videorate.vcproj new file mode 100644 index 0000000..d42d9ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videorate/videorate.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/.gitignore b/gst-plugins-base-subtitles0.10/gst/videoscale/.gitignore new file mode 100644 index 0000000..08f5ed3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.o +*.lo +*.la +.deps +.libs diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/Makefile.am b/gst-plugins-base-subtitles0.10/gst/videoscale/Makefile.am new file mode 100644 index 0000000..79d2cb4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/Makefile.am @@ -0,0 +1,42 @@ +plugin_LTLIBRARIES = libgstvideoscale.la + +ORC_SOURCE=gstvideoscaleorc +include $(top_srcdir)/common/orc.mak + +libgstvideoscale_la_SOURCES = \ + gstvideoscale.c \ + vs_image.c \ + vs_scanline.c \ + vs_4tap.c \ + vs_fill_borders.c + +nodist_libgstvideoscale_la_SOURCES = $(ORC_NODIST_SOURCES) + +libgstvideoscale_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS) +libgstvideoscale_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideoscale_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM) +libgstvideoscale_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstvideoscale.h \ + vs_image.h \ + vs_scanline.h \ + vs_4tap.h \ + vs_fill_borders.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstvideoscale -:SHARED libgstvideoscale \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstvideoscale_la_SOURCES) \ + $(nodist_libgstvideoscale_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideoscale_la_CFLAGS) \ + -:LDFLAGS $(libgstvideoscale_la_LDFLAGS) \ + $(libgstvideoscale_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/README b/gst-plugins-base-subtitles0.10/gst/videoscale/README new file mode 100644 index 0000000..3e08f4e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/README @@ -0,0 +1,5 @@ +- test different strides using +gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=328,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=324,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=322,height=240 ! xvimagesink +gst-launch -v videotestsrc ! video/x-raw-yuv,width=320,height=240,format=\(fourcc\)UYVY ! videoscale ! video/x-raw-yuv,width=321,height=240 ! xvimagesink diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.c b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.c new file mode 100644 index 0000000..b941ed0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.c @@ -0,0 +1,1339 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2005 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-videoscale + * @see_also: videorate, ffmpegcolorspace + * + * This element resizes video frames. By default the element will try to + * negotiate to the same size on the source and sinkpad so that no scaling + * is needed. It is therefore safe to insert this element in a pipeline to + * get more robust behaviour without any cost if no scaling is needed. + * + * This element supports a wide range of color spaces including various YUV and + * RGB formats and is therefore generally able to operate anywhere in a + * pipeline. + * + * + * Example pipelines + * |[ + * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! ffmpegcolorspace ! videoscale ! ximagesink + * ]| Decode an Ogg/Theora and display the video using ximagesink. Since + * ximagesink cannot perform scaling, the video scaling will be performed by + * videoscale when you resize the video window. + * To create the test Ogg/Theora file refer to the documentation of theoraenc. + * |[ + * gst-launch -v filesrc location=videotestsrc.ogg ! oggdemux ! theoradec ! videoscale ! video/x-raw-yuv, width=50 ! xvimagesink + * ]| Decode an Ogg/Theora and display the video using xvimagesink with a width + * of 50. + * + * + * Last reviewed on 2006-03-02 (0.10.4) + */ + +/* + * Formulas for PAR, DAR, width and height relations: + * + * dar_n w par_n + * ----- = - * ----- + * dar_d h par_d + * + * par_n h dar_n + * ----- = - * ----- + * par_d w dar_d + * + * dar_n par_d + * w = h * ----- * ----- + * dar_d par_n + * + * dar_d par_n + * h = w * ----- * ----- + * dar_n par_d + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include + +#include "gstvideoscale.h" +#include "gstvideoscaleorc.h" +#include "vs_image.h" +#include "vs_4tap.h" +#include "vs_fill_borders.h" + +/* debug variable definition */ +GST_DEBUG_CATEGORY (video_scale_debug); + +#define DEFAULT_PROP_METHOD GST_VIDEO_SCALE_BILINEAR +#define DEFAULT_PROP_ADD_BORDERS FALSE + +enum +{ + PROP_0, + PROP_METHOD, + PROP_ADD_BORDERS + /* FILL ME */ +}; + +#undef GST_VIDEO_SIZE_RANGE +#define GST_VIDEO_SIZE_RANGE "(int) [ 1, 32767]" + +static GstStaticCaps gst_video_scale_format_caps[] = { + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA), + GST_STATIC_CAPS (GST_VIDEO_CAPS_ARGB), + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRA), + GST_STATIC_CAPS (GST_VIDEO_CAPS_ABGR), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBx), + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB), + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGRx), + GST_STATIC_CAPS (GST_VIDEO_CAPS_xBGR), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y444")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("v308")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB), + GST_STATIC_CAPS (GST_VIDEO_CAPS_BGR), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y42B")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YUY2")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YVYU")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("UYVY")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("YV12")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y41B")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_16), + GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB_15), + GST_STATIC_CAPS (GST_VIDEO_CAPS_GRAY16 ("BYTE_ORDER")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y16 ")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_GRAY8), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y800")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("Y8 ")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("GREY")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AY64")), + GST_STATIC_CAPS (GST_VIDEO_CAPS_ARGB_64) +}; + +#define GST_TYPE_VIDEO_SCALE_METHOD (gst_video_scale_method_get_type()) +static GType +gst_video_scale_method_get_type (void) +{ + static GType video_scale_method_type = 0; + + static const GEnumValue video_scale_methods[] = { + {GST_VIDEO_SCALE_NEAREST, "Nearest Neighbour", "nearest-neighbour"}, + {GST_VIDEO_SCALE_BILINEAR, "Bilinear", "bilinear"}, + {GST_VIDEO_SCALE_4TAP, "4-tap", "4-tap"}, + {0, NULL, NULL}, + }; + + if (!video_scale_method_type) { + video_scale_method_type = + g_enum_register_static ("GstVideoScaleMethod", video_scale_methods); + } + return video_scale_method_type; +} + +static GstCaps * +gst_video_scale_get_capslist (void) +{ + static GstCaps *caps = NULL; + static volatile gsize inited = 0; + + if (g_once_init_enter (&inited)) { + gint i; + + g_assert (caps == NULL); + + caps = gst_caps_new_empty (); + for (i = 0; i < G_N_ELEMENTS (gst_video_scale_format_caps); i++) + gst_caps_append (caps, + gst_caps_make_writable + (gst_static_caps_get (&gst_video_scale_format_caps[i]))); + g_once_init_leave (&inited, 1); + } + + return caps; +} + +static GstPadTemplate * +gst_video_scale_src_template_factory (void) +{ + return gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + gst_caps_ref (gst_video_scale_get_capslist ())); +} + +static GstPadTemplate * +gst_video_scale_sink_template_factory (void) +{ + return gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, + gst_caps_ref (gst_video_scale_get_capslist ())); +} + + +static void gst_video_scale_finalize (GstVideoScale * videoscale); +static gboolean gst_video_scale_src_event (GstBaseTransform * trans, + GstEvent * event); + +/* base transform vmethods */ +static GstCaps *gst_video_scale_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps); +static gboolean gst_video_scale_set_caps (GstBaseTransform * trans, + GstCaps * in, GstCaps * out); +static gboolean gst_video_scale_get_unit_size (GstBaseTransform * trans, + GstCaps * caps, guint * size); +static GstFlowReturn gst_video_scale_transform (GstBaseTransform * trans, + GstBuffer * in, GstBuffer * out); +static void gst_video_scale_fixate_caps (GstBaseTransform * base, + GstPadDirection direction, GstCaps * caps, GstCaps * othercaps); + +static void gst_video_scale_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_video_scale_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GST_BOILERPLATE (GstVideoScale, gst_video_scale, GstVideoFilter, + GST_TYPE_VIDEO_FILTER); + +static void +gst_video_scale_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Video scaler", "Filter/Converter/Video/Scaler", + "Resizes video", "Wim Taymans "); + + gst_element_class_add_pad_template (element_class, + gst_video_scale_sink_template_factory ()); + gst_element_class_add_pad_template (element_class, + gst_video_scale_src_template_factory ()); +} + +static void +gst_video_scale_class_init (GstVideoScaleClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass; + + gobject_class->finalize = (GObjectFinalizeFunc) gst_video_scale_finalize; + gobject_class->set_property = gst_video_scale_set_property; + gobject_class->get_property = gst_video_scale_get_property; + + g_object_class_install_property (gobject_class, PROP_METHOD, + g_param_spec_enum ("method", "method", "method", + GST_TYPE_VIDEO_SCALE_METHOD, DEFAULT_PROP_METHOD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ADD_BORDERS, + g_param_spec_boolean ("add-borders", "Add Borders", + "Add black borders if necessary to keep the display aspect ratio", + DEFAULT_PROP_ADD_BORDERS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + trans_class->transform_caps = + GST_DEBUG_FUNCPTR (gst_video_scale_transform_caps); + trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_scale_set_caps); + trans_class->get_unit_size = + GST_DEBUG_FUNCPTR (gst_video_scale_get_unit_size); + trans_class->transform = GST_DEBUG_FUNCPTR (gst_video_scale_transform); + trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_video_scale_fixate_caps); + trans_class->src_event = GST_DEBUG_FUNCPTR (gst_video_scale_src_event); +} + +static void +gst_video_scale_init (GstVideoScale * videoscale, GstVideoScaleClass * klass) +{ + videoscale->tmp_buf = NULL; + videoscale->method = DEFAULT_PROP_METHOD; + videoscale->add_borders = DEFAULT_PROP_ADD_BORDERS; +} + +static void +gst_video_scale_finalize (GstVideoScale * videoscale) +{ + if (videoscale->tmp_buf) + g_free (videoscale->tmp_buf); + + G_OBJECT_CLASS (parent_class)->finalize (G_OBJECT (videoscale)); +} + +static void +gst_video_scale_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVideoScale *vscale = GST_VIDEO_SCALE (object); + + switch (prop_id) { + case PROP_METHOD: + GST_OBJECT_LOCK (vscale); + vscale->method = g_value_get_enum (value); + GST_OBJECT_UNLOCK (vscale); + break; + case PROP_ADD_BORDERS: + GST_OBJECT_LOCK (vscale); + vscale->add_borders = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (vscale); + gst_base_transform_reconfigure (GST_BASE_TRANSFORM_CAST (vscale)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_scale_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVideoScale *vscale = GST_VIDEO_SCALE (object); + + switch (prop_id) { + case PROP_METHOD: + GST_OBJECT_LOCK (vscale); + g_value_set_enum (value, vscale->method); + GST_OBJECT_UNLOCK (vscale); + break; + case PROP_ADD_BORDERS: + GST_OBJECT_LOCK (vscale); + g_value_set_boolean (value, vscale->add_borders); + GST_OBJECT_UNLOCK (vscale); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstCaps * +gst_video_scale_transform_caps (GstBaseTransform * trans, + GstPadDirection direction, GstCaps * caps) +{ + GstCaps *ret; + GstStructure *structure; + + /* this function is always called with a simple caps */ + g_return_val_if_fail (GST_CAPS_IS_SIMPLE (caps), NULL); + + GST_DEBUG_OBJECT (trans, + "Transforming caps %" GST_PTR_FORMAT " in direction %s", caps, + (direction == GST_PAD_SINK) ? "sink" : "src"); + + ret = gst_caps_copy (caps); + structure = gst_structure_copy (gst_caps_get_structure (ret, 0)); + + gst_structure_set (structure, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL); + + /* if pixel aspect ratio, make a range of it */ + if (gst_structure_has_field (structure, "pixel-aspect-ratio")) { + gst_structure_set (structure, "pixel-aspect-ratio", GST_TYPE_FRACTION_RANGE, + 1, G_MAXINT, G_MAXINT, 1, NULL); + } + gst_caps_append_structure (ret, structure); + + GST_DEBUG_OBJECT (trans, "returning caps: %" GST_PTR_FORMAT, ret); + + return ret; +} + +static gboolean +gst_video_scale_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) +{ + GstVideoScale *videoscale = GST_VIDEO_SCALE (trans); + gboolean ret; + gint from_dar_n, from_dar_d, to_dar_n, to_dar_d; + gint from_par_n, from_par_d, to_par_n, to_par_d; + + ret = + gst_video_format_parse_caps (in, &videoscale->format, + &videoscale->from_width, &videoscale->from_height); + ret &= + gst_video_format_parse_caps (out, NULL, &videoscale->to_width, + &videoscale->to_height); + if (!ret) + goto done; + + videoscale->src_size = gst_video_format_get_size (videoscale->format, + videoscale->from_width, videoscale->from_height); + videoscale->dest_size = gst_video_format_get_size (videoscale->format, + videoscale->to_width, videoscale->to_height); + + if (!gst_video_parse_caps_pixel_aspect_ratio (in, &from_par_n, &from_par_d)) + from_par_n = from_par_d = 1; + if (!gst_video_parse_caps_pixel_aspect_ratio (out, &to_par_n, &to_par_d)) + to_par_n = to_par_d = 1; + + if (!gst_util_fraction_multiply (videoscale->from_width, + videoscale->from_height, from_par_n, from_par_d, &from_dar_n, + &from_dar_d)) { + from_dar_n = from_dar_d = -1; + } + + if (!gst_util_fraction_multiply (videoscale->to_width, + videoscale->to_height, to_par_n, to_par_d, &to_dar_n, &to_dar_d)) { + to_dar_n = to_dar_d = -1; + } + + videoscale->borders_w = videoscale->borders_h = 0; + if (to_dar_n != from_dar_n || to_dar_d != from_dar_d) { + if (videoscale->add_borders) { + gint n, d, to_h, to_w; + + if (from_dar_n != -1 && from_dar_d != -1 + && gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n, + to_par_d, &n, &d)) { + to_h = gst_util_uint64_scale_int (videoscale->to_width, d, n); + if (to_h <= videoscale->to_height) { + videoscale->borders_h = videoscale->to_height - to_h; + videoscale->borders_w = 0; + } else { + to_w = gst_util_uint64_scale_int (videoscale->to_height, n, d); + g_assert (to_w <= videoscale->to_width); + videoscale->borders_h = 0; + videoscale->borders_w = videoscale->to_width - to_w; + } + } else { + GST_WARNING_OBJECT (videoscale, "Can't calculate borders"); + } + } else { + GST_WARNING_OBJECT (videoscale, "Can't keep DAR!"); + } + } + + if (videoscale->tmp_buf) + g_free (videoscale->tmp_buf); + videoscale->tmp_buf = g_malloc (videoscale->to_width * 8 * 4); + + gst_base_transform_set_passthrough (trans, + (videoscale->from_width == videoscale->to_width + && videoscale->from_height == videoscale->to_height)); + + GST_DEBUG_OBJECT (videoscale, "from=%dx%d (par=%d/%d dar=%d/%d), size %d " + "-> to=%dx%d (par=%d/%d dar=%d/%d borders=%d:%d), size %d", + videoscale->from_width, videoscale->from_height, from_par_n, from_par_d, + from_dar_n, from_dar_d, videoscale->src_size, videoscale->to_width, + videoscale->to_height, to_par_n, to_par_d, to_dar_n, to_dar_d, + videoscale->borders_w, videoscale->borders_h, videoscale->dest_size); + +done: + return ret; +} + +static gboolean +gst_video_scale_get_unit_size (GstBaseTransform * trans, GstCaps * caps, + guint * size) +{ + GstVideoFormat format; + gint width, height; + + if (!gst_video_format_parse_caps (caps, &format, &width, &height)) + return FALSE; + + *size = gst_video_format_get_size (format, width, height); + + return TRUE; +} + +static void +gst_video_scale_fixate_caps (GstBaseTransform * base, GstPadDirection direction, + GstCaps * caps, GstCaps * othercaps) +{ + GstStructure *ins, *outs; + const GValue *from_par, *to_par; + GValue fpar = { 0, }, tpar = { + 0,}; + + g_return_if_fail (gst_caps_is_fixed (caps)); + + GST_DEBUG_OBJECT (base, "trying to fixate othercaps %" GST_PTR_FORMAT + " based on caps %" GST_PTR_FORMAT, othercaps, caps); + + ins = gst_caps_get_structure (caps, 0); + outs = gst_caps_get_structure (othercaps, 0); + + from_par = gst_structure_get_value (ins, "pixel-aspect-ratio"); + to_par = gst_structure_get_value (outs, "pixel-aspect-ratio"); + + /* If we're fixating from the sinkpad we always set the PAR and + * assume that missing PAR on the sinkpad means 1/1 and + * missing PAR on the srcpad means undefined + */ + if (direction == GST_PAD_SINK) { + if (!from_par) { + g_value_init (&fpar, GST_TYPE_FRACTION); + gst_value_set_fraction (&fpar, 1, 1); + from_par = &fpar; + } + if (!to_par) { + g_value_init (&tpar, GST_TYPE_FRACTION_RANGE); + gst_value_set_fraction_range_full (&tpar, 1, G_MAXINT, G_MAXINT, 1); + to_par = &tpar; + } + } else { + if (!to_par) { + g_value_init (&tpar, GST_TYPE_FRACTION); + gst_value_set_fraction (&tpar, 1, 1); + to_par = &tpar; + + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + NULL); + } + if (!from_par) { + g_value_init (&fpar, GST_TYPE_FRACTION); + gst_value_set_fraction (&fpar, 1, 1); + from_par = &fpar; + } + } + + /* we have both PAR but they might not be fixated */ + { + gint from_w, from_h, from_par_n, from_par_d, to_par_n, to_par_d; + gint w = 0, h = 0; + gint from_dar_n, from_dar_d; + gint num, den; + + /* from_par should be fixed */ + g_return_if_fail (gst_value_is_fixed (from_par)); + + from_par_n = gst_value_get_fraction_numerator (from_par); + from_par_d = gst_value_get_fraction_denominator (from_par); + + gst_structure_get_int (ins, "width", &from_w); + gst_structure_get_int (ins, "height", &from_h); + + gst_structure_get_int (outs, "width", &w); + gst_structure_get_int (outs, "height", &h); + + /* if both width and height are already fixed, we can't do anything + * about it anymore */ + if (w && h) { + guint n, d; + + GST_DEBUG_OBJECT (base, "dimensions already set to %dx%d, not fixating", + w, h); + if (!gst_value_is_fixed (to_par)) { + if (gst_video_calculate_display_ratio (&n, &d, from_w, from_h, + from_par_n, from_par_d, w, h)) { + GST_DEBUG_OBJECT (base, "fixating to_par to %dx%d", n, d); + if (gst_structure_has_field (outs, "pixel-aspect-ratio")) + gst_structure_fixate_field_nearest_fraction (outs, + "pixel-aspect-ratio", n, d); + else if (n != d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + n, d, NULL); + } + } + goto done; + } + + /* Calculate input DAR */ + if (!gst_util_fraction_multiply (from_w, from_h, from_par_n, from_par_d, + &from_dar_n, &from_dar_d)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + GST_DEBUG_OBJECT (base, "Input DAR is %d/%d", from_dar_n, from_dar_d); + + /* If either width or height are fixed there's not much we + * can do either except choosing a height or width and PAR + * that matches the DAR as good as possible + */ + if (h) { + GstStructure *tmp; + gint set_w, set_par_n, set_par_d; + + GST_DEBUG_OBJECT (base, "height is fixed (%d)", h); + + /* If the PAR is fixed too, there's not much to do + * except choosing the width that is nearest to the + * width with the same DAR */ + if (gst_value_is_fixed (to_par)) { + to_par_n = gst_value_get_fraction_numerator (to_par); + to_par_d = gst_value_get_fraction_denominator (to_par); + + GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d); + + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d, + to_par_n, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + w = (guint) gst_util_uint64_scale_int (h, num, den); + gst_structure_fixate_field_nearest_int (outs, "width", w); + + goto done; + } + + /* The PAR is not fixed and it's quite likely that we can set + * an arbitrary PAR. */ + + /* Check if we can keep the input width */ + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "width", from_w); + gst_structure_get_int (tmp, "width", &set_w); + + /* Might have failed but try to keep the DAR nonetheless by + * adjusting the PAR */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, h, set_w, + &to_par_n, &to_par_d)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + gst_structure_free (tmp); + goto done; + } + + if (!gst_structure_has_field (tmp, "pixel-aspect-ratio")) + gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par); + gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio", + to_par_n, to_par_d); + gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n, + &set_par_d); + gst_structure_free (tmp); + + /* Check if the adjusted PAR is accepted */ + if (set_par_n == to_par_n && set_par_d == to_par_d) { + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "width", G_TYPE_INT, set_w, + "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d, + NULL); + goto done; + } + + /* Otherwise scale the width to the new PAR and check if the + * adjusted with is accepted. If all that fails we can't keep + * the DAR */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d, + set_par_n, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + w = (guint) gst_util_uint64_scale_int (h, num, den); + gst_structure_fixate_field_nearest_int (outs, "width", w); + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + + goto done; + } else if (w) { + GstStructure *tmp; + gint set_h, set_par_n, set_par_d; + + GST_DEBUG_OBJECT (base, "width is fixed (%d)", w); + + /* If the PAR is fixed too, there's not much to do + * except choosing the height that is nearest to the + * height with the same DAR */ + if (gst_value_is_fixed (to_par)) { + to_par_n = gst_value_get_fraction_numerator (to_par); + to_par_d = gst_value_get_fraction_denominator (to_par); + + GST_DEBUG_OBJECT (base, "PAR is fixed %d/%d", to_par_n, to_par_d); + + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_d, + to_par_n, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + h = (guint) gst_util_uint64_scale_int (w, den, num); + gst_structure_fixate_field_nearest_int (outs, "height", h); + + goto done; + } + + /* The PAR is not fixed and it's quite likely that we can set + * an arbitrary PAR. */ + + /* Check if we can keep the input height */ + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "height", from_h); + gst_structure_get_int (tmp, "height", &set_h); + + /* Might have failed but try to keep the DAR nonetheless by + * adjusting the PAR */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, w, + &to_par_n, &to_par_d)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + gst_structure_free (tmp); + goto done; + } + if (!gst_structure_has_field (tmp, "pixel-aspect-ratio")) + gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par); + gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio", + to_par_n, to_par_d); + gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n, + &set_par_d); + gst_structure_free (tmp); + + /* Check if the adjusted PAR is accepted */ + if (set_par_n == to_par_n && set_par_d == to_par_d) { + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "height", G_TYPE_INT, set_h, + "pixel-aspect-ratio", GST_TYPE_FRACTION, set_par_n, set_par_d, + NULL); + goto done; + } + + /* Otherwise scale the height to the new PAR and check if the + * adjusted with is accepted. If all that fails we can't keep + * the DAR */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d, + set_par_n, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + h = (guint) gst_util_uint64_scale_int (w, den, num); + gst_structure_fixate_field_nearest_int (outs, "height", h); + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + + goto done; + } else if (gst_value_is_fixed (to_par)) { + GstStructure *tmp; + gint set_h, set_w, f_h, f_w; + + to_par_n = gst_value_get_fraction_numerator (to_par); + to_par_d = gst_value_get_fraction_denominator (to_par); + + /* Calculate scale factor for the PAR change */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, to_par_n, + to_par_d, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + /* Try to keep the input height (because of interlacing) */ + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "height", from_h); + gst_structure_get_int (tmp, "height", &set_h); + + /* This might have failed but try to scale the width + * to keep the DAR nonetheless */ + w = (guint) gst_util_uint64_scale_int (set_h, num, den); + gst_structure_fixate_field_nearest_int (tmp, "width", w); + gst_structure_get_int (tmp, "width", &set_w); + gst_structure_free (tmp); + + /* We kept the DAR and the height is nearest to the original height */ + if (set_w == w) { + gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height", + G_TYPE_INT, set_h, NULL); + goto done; + } + + f_h = set_h; + f_w = set_w; + + /* If the former failed, try to keep the input width at least */ + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "width", from_w); + gst_structure_get_int (tmp, "width", &set_w); + + /* This might have failed but try to scale the width + * to keep the DAR nonetheless */ + h = (guint) gst_util_uint64_scale_int (set_w, den, num); + gst_structure_fixate_field_nearest_int (tmp, "height", h); + gst_structure_get_int (tmp, "height", &set_h); + gst_structure_free (tmp); + + /* We kept the DAR and the width is nearest to the original width */ + if (set_h == h) { + gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height", + G_TYPE_INT, set_h, NULL); + goto done; + } + + /* If all this failed, keep the height that was nearest to the orignal + * height and the nearest possible width. This changes the DAR but + * there's not much else to do here. + */ + gst_structure_set (outs, "width", G_TYPE_INT, f_w, "height", G_TYPE_INT, + f_h, NULL); + goto done; + } else { + GstStructure *tmp; + gint set_h, set_w, set_par_n, set_par_d, tmp2; + + /* width, height and PAR are not fixed but passthrough is not possible */ + + /* First try to keep the height and width as good as possible + * and scale PAR */ + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "height", from_h); + gst_structure_get_int (tmp, "height", &set_h); + gst_structure_fixate_field_nearest_int (tmp, "width", from_w); + gst_structure_get_int (tmp, "width", &set_w); + + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_h, set_w, + &to_par_n, &to_par_d)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + if (!gst_structure_has_field (tmp, "pixel-aspect-ratio")) + gst_structure_set_value (tmp, "pixel-aspect-ratio", to_par); + gst_structure_fixate_field_nearest_fraction (tmp, "pixel-aspect-ratio", + to_par_n, to_par_d); + gst_structure_get_fraction (tmp, "pixel-aspect-ratio", &set_par_n, + &set_par_d); + gst_structure_free (tmp); + + if (set_par_n == to_par_n && set_par_d == to_par_d) { + gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height", + G_TYPE_INT, set_h, NULL); + + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + goto done; + } + + /* Otherwise try to scale width to keep the DAR with the set + * PAR and height */ + if (!gst_util_fraction_multiply (from_dar_n, from_dar_d, set_par_d, + set_par_n, &num, &den)) { + GST_ELEMENT_ERROR (base, CORE, NEGOTIATION, (NULL), + ("Error calculating the output scaled size - integer overflow")); + goto done; + } + + w = (guint) gst_util_uint64_scale_int (set_h, num, den); + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "width", w); + gst_structure_get_int (tmp, "width", &tmp2); + gst_structure_free (tmp); + + if (tmp2 == w) { + gst_structure_set (outs, "width", G_TYPE_INT, tmp2, "height", + G_TYPE_INT, set_h, NULL); + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + goto done; + } + + /* ... or try the same with the height */ + h = (guint) gst_util_uint64_scale_int (set_w, den, num); + tmp = gst_structure_copy (outs); + gst_structure_fixate_field_nearest_int (tmp, "height", h); + gst_structure_get_int (tmp, "height", &tmp2); + gst_structure_free (tmp); + + if (tmp2 == h) { + gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height", + G_TYPE_INT, tmp2, NULL); + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + goto done; + } + + /* If all fails we can't keep the DAR and take the nearest values + * for everything from the first try */ + gst_structure_set (outs, "width", G_TYPE_INT, set_w, "height", + G_TYPE_INT, set_h, NULL); + if (gst_structure_has_field (outs, "pixel-aspect-ratio") || + set_par_n != set_par_d) + gst_structure_set (outs, "pixel-aspect-ratio", GST_TYPE_FRACTION, + set_par_n, set_par_d, NULL); + } + } + +done: + GST_DEBUG_OBJECT (base, "fixated othercaps to %" GST_PTR_FORMAT, othercaps); + + if (from_par == &fpar) + g_value_unset (&fpar); + if (to_par == &tpar) + g_value_unset (&tpar); +} + +static void +gst_video_scale_setup_vs_image (VSImage * image, GstVideoFormat format, + gint component, gint width, gint height, gint b_w, gint b_h, uint8_t * data) +{ + image->real_width = + gst_video_format_get_component_width (format, component, width); + image->real_height = + gst_video_format_get_component_height (format, component, height); + image->width = + gst_video_format_get_component_width (format, component, MAX (1, + width - b_w)); + image->height = + gst_video_format_get_component_height (format, component, MAX (1, + height - b_h)); + image->stride = gst_video_format_get_row_stride (format, component, width); + + image->border_top = (image->real_height - image->height) / 2; + image->border_bottom = image->real_height - image->height - image->border_top; + + if (format == GST_VIDEO_FORMAT_YUY2 || format == GST_VIDEO_FORMAT_YVYU + || format == GST_VIDEO_FORMAT_UYVY) { + g_assert (component == 0); + + image->border_left = (image->real_width - image->width) / 2; + + if (image->border_left % 2 == 1) + image->border_left--; + image->border_right = image->real_width - image->width - image->border_left; + } else { + image->border_left = (image->real_width - image->width) / 2; + image->border_right = image->real_width - image->width - image->border_left; + } + + if (format == GST_VIDEO_FORMAT_I420 + || format == GST_VIDEO_FORMAT_YV12 + || format == GST_VIDEO_FORMAT_Y444 + || format == GST_VIDEO_FORMAT_Y42B || format == GST_VIDEO_FORMAT_Y41B) { + image->real_pixels = data + gst_video_format_get_component_offset (format, + component, width, height); + } else { + g_assert (component == 0); + image->real_pixels = data; + } + + image->pixels = + image->real_pixels + image->border_top * image->stride + + image->border_left * gst_video_format_get_pixel_stride (format, + component); +} + +static const guint8 * +_get_black_for_format (GstVideoFormat format) +{ + static const guint8 black[][4] = { + {255, 0, 0, 0}, /* 0 = ARGB, ABGR, xRGB, xBGR */ + {0, 0, 0, 255}, /* 1 = RGBA, BGRA, RGBx, BGRx */ + {255, 16, 128, 128}, /* 2 = AYUV */ + {0, 0, 0, 0}, /* 3 = RGB and BGR */ + {16, 128, 128, 0}, /* 4 = v301 */ + {16, 128, 16, 128}, /* 5 = YUY2, YUYV */ + {128, 16, 128, 16}, /* 6 = UYVY */ + {16, 0, 0, 0}, /* 7 = Y */ + {0, 0, 0, 0} /* 8 = RGB565, RGB666 */ + }; + + switch (format) { + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_ARGB64: + return black[0]; + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + return black[1]; + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_AYUV64: + return black[2]; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + return black[3]; + case GST_VIDEO_FORMAT_v308: + return black[4]; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + return black[5]; + case GST_VIDEO_FORMAT_UYVY: + return black[6]; + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_GRAY8: + return black[7]; + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_Y16: + return NULL; /* Handled by the caller */ + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y41B: + return black[4]; /* Y, U, V, 0 */ + case GST_VIDEO_FORMAT_RGB16: + case GST_VIDEO_FORMAT_RGB15: + return black[8]; + default: + return NULL; + } +} + +static GstFlowReturn +gst_video_scale_transform (GstBaseTransform * trans, GstBuffer * in, + GstBuffer * out) +{ + GstVideoScale *videoscale = GST_VIDEO_SCALE (trans); + GstFlowReturn ret = GST_FLOW_OK; + VSImage dest = { NULL, }; + VSImage src = { NULL, }; + VSImage dest_u = { NULL, }; + VSImage dest_v = { NULL, }; + VSImage src_u = { NULL, }; + VSImage src_v = { NULL, }; + gint method; + const guint8 *black = _get_black_for_format (videoscale->format); + gboolean add_borders; + + GST_OBJECT_LOCK (videoscale); + method = videoscale->method; + add_borders = videoscale->add_borders; + GST_OBJECT_UNLOCK (videoscale); + + if (videoscale->from_width == 1) { + method = GST_VIDEO_SCALE_NEAREST; + } + if (method == GST_VIDEO_SCALE_4TAP && + (videoscale->from_width < 4 || videoscale->from_height < 4)) { + method = GST_VIDEO_SCALE_BILINEAR; + } + + gst_video_scale_setup_vs_image (&src, videoscale->format, 0, + videoscale->from_width, videoscale->from_height, 0, 0, + GST_BUFFER_DATA (in)); + gst_video_scale_setup_vs_image (&dest, videoscale->format, 0, + videoscale->to_width, videoscale->to_height, videoscale->borders_w, + videoscale->borders_h, GST_BUFFER_DATA (out)); + + if (videoscale->format == GST_VIDEO_FORMAT_I420 + || videoscale->format == GST_VIDEO_FORMAT_YV12 + || videoscale->format == GST_VIDEO_FORMAT_Y444 + || videoscale->format == GST_VIDEO_FORMAT_Y42B + || videoscale->format == GST_VIDEO_FORMAT_Y41B) { + gst_video_scale_setup_vs_image (&src_u, videoscale->format, 1, + videoscale->from_width, videoscale->from_height, 0, 0, + GST_BUFFER_DATA (in)); + gst_video_scale_setup_vs_image (&src_v, videoscale->format, 2, + videoscale->from_width, videoscale->from_height, 0, 0, + GST_BUFFER_DATA (in)); + gst_video_scale_setup_vs_image (&dest_u, videoscale->format, 1, + videoscale->to_width, videoscale->to_height, videoscale->borders_w, + videoscale->borders_h, GST_BUFFER_DATA (out)); + gst_video_scale_setup_vs_image (&dest_v, videoscale->format, 2, + videoscale->to_width, videoscale->to_height, videoscale->borders_w, + videoscale->borders_h, GST_BUFFER_DATA (out)); + } + + switch (videoscale->format) { + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_AYUV: + if (add_borders) + vs_fill_borders_RGBA (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_RGBA (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_RGBA (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_RGBA (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_ARGB64: + case GST_VIDEO_FORMAT_AYUV64: + if (add_borders) + vs_fill_borders_AYUV64 (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_AYUV64 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_AYUV64 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_AYUV64 (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_v308: + if (add_borders) + vs_fill_borders_RGB (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_RGB (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_RGB (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_RGB (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + if (add_borders) + vs_fill_borders_YUYV (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_YUYV (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_YUYV (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_YUYV (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_UYVY: + if (add_borders) + vs_fill_borders_UYVY (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_UYVY (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_UYVY (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_UYVY (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_GRAY8: + if (add_borders) + vs_fill_borders_Y (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_GRAY16_LE: + case GST_VIDEO_FORMAT_GRAY16_BE: + case GST_VIDEO_FORMAT_Y16: + if (add_borders) + vs_fill_borders_Y16 (&dest, 0); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_Y16 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_Y16 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_Y16 (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y444: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y41B: + if (add_borders) { + vs_fill_borders_Y (&dest, black); + vs_fill_borders_Y (&dest_u, black + 1); + vs_fill_borders_Y (&dest_v, black + 2); + } + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_Y (&dest, &src, videoscale->tmp_buf); + vs_image_scale_nearest_Y (&dest_u, &src_u, videoscale->tmp_buf); + vs_image_scale_nearest_Y (&dest_v, &src_v, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_Y (&dest, &src, videoscale->tmp_buf); + vs_image_scale_linear_Y (&dest_u, &src_u, videoscale->tmp_buf); + vs_image_scale_linear_Y (&dest_v, &src_v, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_Y (&dest, &src, videoscale->tmp_buf); + vs_image_scale_4tap_Y (&dest_u, &src_u, videoscale->tmp_buf); + vs_image_scale_4tap_Y (&dest_v, &src_v, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_RGB16: + if (add_borders) + vs_fill_borders_RGB565 (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_RGB565 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_RGB565 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_RGB565 (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + case GST_VIDEO_FORMAT_RGB15: + if (add_borders) + vs_fill_borders_RGB555 (&dest, black); + switch (method) { + case GST_VIDEO_SCALE_NEAREST: + vs_image_scale_nearest_RGB555 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_BILINEAR: + vs_image_scale_linear_RGB555 (&dest, &src, videoscale->tmp_buf); + break; + case GST_VIDEO_SCALE_4TAP: + vs_image_scale_4tap_RGB555 (&dest, &src, videoscale->tmp_buf); + break; + default: + goto unknown_mode; + } + break; + default: + goto unsupported; + } + + GST_LOG_OBJECT (videoscale, "pushing buffer of %d bytes", + GST_BUFFER_SIZE (out)); + + return ret; + + /* ERRORS */ +unsupported: + { + GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL), + ("Unsupported format %d for scaling method %d", + videoscale->format, method)); + return GST_FLOW_ERROR; + } +unknown_mode: + { + GST_ELEMENT_ERROR (videoscale, STREAM, NOT_IMPLEMENTED, (NULL), + ("Unknown scaling method %d", videoscale->method)); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_video_scale_src_event (GstBaseTransform * trans, GstEvent * event) +{ + GstVideoScale *videoscale = GST_VIDEO_SCALE (trans); + gboolean ret; + gdouble a; + GstStructure *structure; + + GST_DEBUG_OBJECT (videoscale, "handling %s event", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NAVIGATION: + event = + GST_EVENT (gst_mini_object_make_writable (GST_MINI_OBJECT (event))); + + structure = (GstStructure *) gst_event_get_structure (event); + if (gst_structure_get_double (structure, "pointer_x", &a)) { + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, + a * videoscale->from_width / videoscale->to_width, NULL); + } + if (gst_structure_get_double (structure, "pointer_y", &a)) { + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, + a * videoscale->from_height / videoscale->to_height, NULL); + } + break; + default: + break; + } + + ret = GST_BASE_TRANSFORM_CLASS (parent_class)->src_event (trans, event); + + return ret; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_videoscale_orc_init (); + + if (!gst_element_register (plugin, "videoscale", GST_RANK_NONE, + GST_TYPE_VIDEO_SCALE)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (video_scale_debug, "videoscale", 0, + "videoscale element"); + + vs_4tap_init (); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videoscale", + "Resizes video", plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, + GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.h b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.h new file mode 100644 index 0000000..a09d769 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscale.h @@ -0,0 +1,97 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VIDEO_SCALE_H__ +#define __GST_VIDEO_SCALE_H__ + +#include +#include +#include + +#include "vs_image.h" + +G_BEGIN_DECLS + +GST_DEBUG_CATEGORY_EXTERN (video_scale_debug); +#define GST_CAT_DEFAULT video_scale_debug + +#define GST_TYPE_VIDEO_SCALE \ + (gst_video_scale_get_type()) +#define GST_VIDEO_SCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_SCALE,GstVideoScale)) +#define GST_VIDEO_SCALE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_SCALE,GstVideoScaleClass)) +#define GST_IS_VIDEO_SCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_SCALE)) +#define GST_IS_VIDEO_SCALE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_SCALE)) + +/** + * GstVideoScaleMethod: + * @GST_VIDEO_SCALE_NEAREST: use nearest neighbour scaling (fast and ugly) + * @GST_VIDEO_SCALE_BILINEAR: use bilinear scaling (slower but prettier). + * @GST_VIDEO_SCALE_4TAP: use a 4-tap filter for scaling (slow). + * + * The videoscale method to use. + */ +typedef enum { + GST_VIDEO_SCALE_NEAREST, + GST_VIDEO_SCALE_BILINEAR, + GST_VIDEO_SCALE_4TAP +} GstVideoScaleMethod; + +typedef struct _GstVideoScale GstVideoScale; +typedef struct _GstVideoScaleClass GstVideoScaleClass; + +/** + * GstVideoScale: + * + * Opaque data structure + */ +struct _GstVideoScale { + GstVideoFilter element; + + GstVideoScaleMethod method; + gboolean add_borders; + + /* negotiated stuff */ + GstVideoFormat format; + gint to_width; + gint to_height; + gint from_width; + gint from_height; + guint src_size; + guint dest_size; + + gint borders_h; + gint borders_w; + + /*< private >*/ + guint8 *tmp_buf; +}; + +struct _GstVideoScaleClass { + GstVideoFilterClass parent_class; +}; + +GType gst_video_scale_get_type(void); + +G_END_DECLS + +#endif /* __GST_VIDEO_SCALE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.c b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.c new file mode 100644 index 0000000..034baf5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.c @@ -0,0 +1,2264 @@ + +/* autogenerated from gstvideoscaleorc.orc */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 + +#ifndef DISABLE_ORC +#include +#endif +void orc_merge_linear_u8 (orc_uint8 * ORC_RESTRICT d1, + const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2, + int p1, int n); +void orc_merge_linear_u16 (orc_uint16 * ORC_RESTRICT d1, + const orc_uint16 * ORC_RESTRICT s1, const orc_uint16 * ORC_RESTRICT s2, + int p1, int p2, int n); +void orc_splat_u16 (orc_uint16 * ORC_RESTRICT d1, int p1, int n); +void orc_splat_u32 (orc_uint32 * ORC_RESTRICT d1, int p1, int n); +void orc_splat_u64 (orc_uint64 * ORC_RESTRICT d1, orc_int64 p1, int n); +void orc_downsample_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n); +void orc_downsample_u16 (guint16 * ORC_RESTRICT d1, + const guint16 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_downsample_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_downsample_yuyv (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_resample_nearest_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_bilinear_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_nearest_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_bilinear_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_merge_bilinear_u32 (guint8 * ORC_RESTRICT d1, + guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, + const guint8 * ORC_RESTRICT s2, int p1, int p2, int p3, int n); +void gst_videoscale_orc_merge_bicubic_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, + const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, int p1, + int p2, int p3, int p4, int n); + +void gst_videoscale_orc_init (void); + + +/* begin Orc C target preamble */ +#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x))) +#define ORC_ABS(a) ((a)<0 ? -(a) : (a)) +#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define ORC_SB_MAX 127 +#define ORC_SB_MIN (-1-ORC_SB_MAX) +#define ORC_UB_MAX 255 +#define ORC_UB_MIN 0 +#define ORC_SW_MAX 32767 +#define ORC_SW_MIN (-1-ORC_SW_MAX) +#define ORC_UW_MAX 65535 +#define ORC_UW_MIN 0 +#define ORC_SL_MAX 2147483647 +#define ORC_SL_MIN (-1-ORC_SL_MAX) +#define ORC_UL_MAX 4294967295U +#define ORC_UL_MIN 0 +#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX) +#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX) +#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX) +#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX) +#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX) +#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) +#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) +#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) +#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#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 +#define ORC_RESTRICT __restrict__ +#else +#define ORC_RESTRICT +#endif +#endif +/* end Orc C target preamble */ + + + +/* orc_merge_linear_u8 */ +#ifdef DISABLE_ORC +void +orc_merge_linear_u8 (orc_uint8 * ORC_RESTRICT d1, + const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2, + int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + const orc_int8 *ORC_RESTRICT ptr5; + orc_int8 var36; + orc_int8 var37; + orc_union16 var38; + orc_union16 var39; + orc_int8 var40; + orc_int8 var41; + orc_union16 var42; + orc_union16 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_int8 var47; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + ptr5 = (orc_int8 *) s2; + + /* 6: loadpw */ + var38.i = p1; + /* 8: loadpw */ + var39.i = (int) 0x00000080; /* 128 or 6.32404e-322f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var41 = ptr4[i]; + /* 1: loadb */ + var36 = ptr4[i]; + /* 2: convubw */ + var42.i = (orc_uint8) var36; + /* 3: loadb */ + var37 = ptr5[i]; + /* 4: convubw */ + var43.i = (orc_uint8) var37; + /* 5: subw */ + var44.i = var43.i - var42.i; + /* 7: mullw */ + var45.i = (var44.i * var38.i) & 0xffff; + /* 9: addw */ + var46.i = var45.i + var39.i; + /* 10: convhwb */ + var47 = ((orc_uint16) var46.i) >> 8; + /* 11: addb */ + var40 = var47 + var41; + /* 12: storeb */ + ptr0[i] = var40; + } + +} + +#else +static void +_backup_orc_merge_linear_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + const orc_int8 *ORC_RESTRICT ptr5; + orc_int8 var36; + orc_int8 var37; + orc_union16 var38; + orc_union16 var39; + orc_int8 var40; + orc_int8 var41; + orc_union16 var42; + orc_union16 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_int8 var47; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + ptr5 = (orc_int8 *) ex->arrays[5]; + + /* 6: loadpw */ + var38.i = ex->params[24]; + /* 8: loadpw */ + var39.i = (int) 0x00000080; /* 128 or 6.32404e-322f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var41 = ptr4[i]; + /* 1: loadb */ + var36 = ptr4[i]; + /* 2: convubw */ + var42.i = (orc_uint8) var36; + /* 3: loadb */ + var37 = ptr5[i]; + /* 4: convubw */ + var43.i = (orc_uint8) var37; + /* 5: subw */ + var44.i = var43.i - var42.i; + /* 7: mullw */ + var45.i = (var44.i * var38.i) & 0xffff; + /* 9: addw */ + var46.i = var45.i + var39.i; + /* 10: convhwb */ + var47 = ((orc_uint16) var46.i) >> 8; + /* 11: addb */ + var40 = var47 + var41; + /* 12: storeb */ + ptr0[i] = var40; + } + +} + +static OrcProgram *_orc_program_orc_merge_linear_u8; +void +orc_merge_linear_u8 (orc_uint8 * ORC_RESTRICT d1, + const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2, + int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_merge_linear_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->arrays[ORC_VAR_S2] = (void *) s2; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_merge_linear_u16 */ +#ifdef DISABLE_ORC +void +orc_merge_linear_u16 (orc_uint16 * ORC_RESTRICT d1, + const orc_uint16 * ORC_RESTRICT s1, const orc_uint16 * ORC_RESTRICT s2, + int p1, int p2, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + const orc_union16 *ORC_RESTRICT ptr5; + orc_union16 var34; + orc_union16 var35; + orc_union16 var36; + orc_union16 var37; + orc_union16 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union32 var42; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union16 *) s1; + ptr5 = (orc_union16 *) s2; + + /* 1: loadpw */ + var35.i = p1; + /* 4: loadpw */ + var37.i = p2; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 2: muluwl */ + var39.i = ((orc_uint16) var34.i) * ((orc_uint16) var35.i); + /* 3: loadw */ + var36 = ptr5[i]; + /* 5: muluwl */ + var40.i = ((orc_uint16) var36.i) * ((orc_uint16) var37.i); + /* 6: addl */ + var41.i = var39.i + var40.i; + /* 7: shrul */ + var42.i = ((orc_uint32) var41.i) >> 16; + /* 8: convlw */ + var38.i = var42.i; + /* 9: storew */ + ptr0[i] = var38; + } + +} + +#else +static void +_backup_orc_merge_linear_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + const orc_union16 *ORC_RESTRICT ptr5; + orc_union16 var34; + orc_union16 var35; + orc_union16 var36; + orc_union16 var37; + orc_union16 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union32 var42; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + ptr5 = (orc_union16 *) ex->arrays[5]; + + /* 1: loadpw */ + var35.i = ex->params[24]; + /* 4: loadpw */ + var37.i = ex->params[25]; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 2: muluwl */ + var39.i = ((orc_uint16) var34.i) * ((orc_uint16) var35.i); + /* 3: loadw */ + var36 = ptr5[i]; + /* 5: muluwl */ + var40.i = ((orc_uint16) var36.i) * ((orc_uint16) var37.i); + /* 6: addl */ + var41.i = var39.i + var40.i; + /* 7: shrul */ + var42.i = ((orc_uint32) var41.i) >> 16; + /* 8: convlw */ + var38.i = var42.i; + /* 9: storew */ + ptr0[i] = var38; + } + +} + +static OrcProgram *_orc_program_orc_merge_linear_u16; +void +orc_merge_linear_u16 (orc_uint16 * ORC_RESTRICT d1, + const orc_uint16 * ORC_RESTRICT s1, const orc_uint16 * ORC_RESTRICT s2, + int p1, int p2, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_merge_linear_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->arrays[ORC_VAR_S2] = (void *) s2; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_splat_u16 */ +#ifdef DISABLE_ORC +void +orc_splat_u16 (orc_uint16 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) d1; + + /* 0: loadpw */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_splat_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) ex->arrays[0]; + + /* 0: loadpw */ + var32.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_splat_u16; +void +orc_splat_u16 (orc_uint16 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_splat_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_splat_u32 */ +#ifdef DISABLE_ORC +void +orc_splat_u32 (orc_uint32 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) d1; + + /* 0: loadpl */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyl */ + var33.i = var32.i; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_splat_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) ex->arrays[0]; + + /* 0: loadpl */ + var32.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyl */ + var33.i = var32.i; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_splat_u32; +void +orc_splat_u32 (orc_uint32 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_splat_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_splat_u64 */ +#ifdef DISABLE_ORC +void +orc_splat_u64 (orc_uint64 * ORC_RESTRICT d1, orc_int64 p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) d1; + + /* 0: loadpq */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_splat_u64 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) ex->arrays[0]; + + /* 0: loadpq */ + var32.i = + (ex->params[24] & 0xffffffff) | ((orc_uint64) (ex->params[24 + + (ORC_VAR_T1 - ORC_VAR_P1)]) << 32); + + for (i = 0; i < n; i++) { + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_splat_u64; +void +orc_splat_u64 (orc_uint64 * ORC_RESTRICT d1, orc_int64 p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_splat_u64; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + { + orc_union64 tmp; + tmp.i = p1; + ex->params[ORC_VAR_P1] = tmp.x2[0]; + ex->params[ORC_VAR_T1] = tmp.x2[1]; + } + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_downsample_u8 */ +#ifdef DISABLE_ORC +void +orc_downsample_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, + int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_int8 var35; + orc_int8 var36; + orc_int8 var37; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union16 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: splitwb */ + { + orc_union16 _src; + _src.i = var34.i; + var36 = _src.x2[1]; + var37 = _src.x2[0]; + } + /* 2: avgub */ + var35 = ((orc_uint8) var36 + (orc_uint8) var37 + 1) >> 1; + /* 3: storeb */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_downsample_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union16 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_int8 var35; + orc_int8 var36; + orc_int8 var37; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union16 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr4[i]; + /* 1: splitwb */ + { + orc_union16 _src; + _src.i = var34.i; + var36 = _src.x2[1]; + var37 = _src.x2[0]; + } + /* 2: avgub */ + var35 = ((orc_uint8) var36 + (orc_uint8) var37 + 1) >> 1; + /* 3: storeb */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_downsample_u8; +void +orc_downsample_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, + int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_downsample_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_downsample_u16 */ +#ifdef DISABLE_ORC +void +orc_downsample_u16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, + int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union16 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: splitlw */ + { + orc_union32 _src; + _src.i = var34.i; + var36.i = _src.x2[1]; + var37.i = _src.x2[0]; + } + /* 2: avguw */ + var35.i = ((orc_uint16) var36.i + (orc_uint16) var37.i + 1) >> 1; + /* 3: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_downsample_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var34; + orc_union16 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var34 = ptr4[i]; + /* 1: splitlw */ + { + orc_union32 _src; + _src.i = var34.i; + var36.i = _src.x2[1]; + var37.i = _src.x2[0]; + } + /* 2: avguw */ + var35.i = ((orc_uint16) var36.i + (orc_uint16) var37.i + 1) >> 1; + /* 3: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_downsample_u16; +void +orc_downsample_u16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, + int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_downsample_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_downsample_u32 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_downsample_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: splitql */ + { + orc_union64 _src; + _src.i = var34.i; + var36.i = _src.x2[1]; + var37.i = _src.x2[0]; + } + /* 2: avgub */ + var35.x4[0] = ((orc_uint8) var36.x4[0] + (orc_uint8) var37.x4[0] + 1) >> 1; + var35.x4[1] = ((orc_uint8) var36.x4[1] + (orc_uint8) var37.x4[1] + 1) >> 1; + var35.x4[2] = ((orc_uint8) var36.x4[2] + (orc_uint8) var37.x4[2] + 1) >> 1; + var35.x4[3] = ((orc_uint8) var36.x4[3] + (orc_uint8) var37.x4[3] + 1) >> 1; + /* 3: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_gst_videoscale_orc_downsample_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union32 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: splitql */ + { + orc_union64 _src; + _src.i = var34.i; + var36.i = _src.x2[1]; + var37.i = _src.x2[0]; + } + /* 2: avgub */ + var35.x4[0] = ((orc_uint8) var36.x4[0] + (orc_uint8) var37.x4[0] + 1) >> 1; + var35.x4[1] = ((orc_uint8) var36.x4[1] + (orc_uint8) var37.x4[1] + 1) >> 1; + var35.x4[2] = ((orc_uint8) var36.x4[2] + (orc_uint8) var37.x4[2] + 1) >> 1; + var35.x4[3] = ((orc_uint8) var36.x4[3] + (orc_uint8) var37.x4[3] + 1) >> 1; + /* 3: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_downsample_u32; +void +gst_videoscale_orc_downsample_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_downsample_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_downsample_yuyv */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_downsample_yuyv (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union16 var42; + orc_union16 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_union16 var47; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var38 = ptr4[i]; + /* 1: splitwb */ + { + orc_union16 _src; + _src.i = var38.x4[0]; + var40.x4[0] = _src.x2[1]; + var41.x4[0] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[1]; + var40.x4[1] = _src.x2[1]; + var41.x4[1] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[2]; + var40.x4[2] = _src.x2[1]; + var41.x4[2] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[3]; + var40.x4[3] = _src.x2[1]; + var41.x4[3] = _src.x2[0]; + } + /* 2: splitwb */ + { + orc_union16 _src; + _src.i = var40.x2[0]; + var42.x2[0] = _src.x2[1]; + var43.x2[0] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var40.x2[1]; + var42.x2[1] = _src.x2[1]; + var43.x2[1] = _src.x2[0]; + } + /* 3: avgub */ + var44.x2[0] = ((orc_uint8) var42.x2[0] + (orc_uint8) var43.x2[0] + 1) >> 1; + var44.x2[1] = ((orc_uint8) var42.x2[1] + (orc_uint8) var43.x2[1] + 1) >> 1; + /* 4: splitlw */ + { + orc_union32 _src; + _src.i = var41.i; + var45.i = _src.x2[1]; + var46.i = _src.x2[0]; + } + /* 5: avgub */ + var47.x2[0] = ((orc_uint8) var45.x2[0] + (orc_uint8) var46.x2[0] + 1) >> 1; + var47.x2[1] = ((orc_uint8) var45.x2[1] + (orc_uint8) var46.x2[1] + 1) >> 1; + /* 6: mergebw */ + { + orc_union16 _dest; + _dest.x2[0] = var44.x2[0]; + _dest.x2[1] = var47.x2[0]; + var39.x2[0] = _dest.i; + } + { + orc_union16 _dest; + _dest.x2[0] = var44.x2[1]; + _dest.x2[1] = var47.x2[1]; + var39.x2[1] = _dest.i; + } + /* 7: storel */ + ptr0[i] = var39; + } + +} + +#else +static void +_backup_gst_videoscale_orc_downsample_yuyv (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union16 var42; + orc_union16 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_union16 var47; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var38 = ptr4[i]; + /* 1: splitwb */ + { + orc_union16 _src; + _src.i = var38.x4[0]; + var40.x4[0] = _src.x2[1]; + var41.x4[0] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[1]; + var40.x4[1] = _src.x2[1]; + var41.x4[1] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[2]; + var40.x4[2] = _src.x2[1]; + var41.x4[2] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var38.x4[3]; + var40.x4[3] = _src.x2[1]; + var41.x4[3] = _src.x2[0]; + } + /* 2: splitwb */ + { + orc_union16 _src; + _src.i = var40.x2[0]; + var42.x2[0] = _src.x2[1]; + var43.x2[0] = _src.x2[0]; + } + { + orc_union16 _src; + _src.i = var40.x2[1]; + var42.x2[1] = _src.x2[1]; + var43.x2[1] = _src.x2[0]; + } + /* 3: avgub */ + var44.x2[0] = ((orc_uint8) var42.x2[0] + (orc_uint8) var43.x2[0] + 1) >> 1; + var44.x2[1] = ((orc_uint8) var42.x2[1] + (orc_uint8) var43.x2[1] + 1) >> 1; + /* 4: splitlw */ + { + orc_union32 _src; + _src.i = var41.i; + var45.i = _src.x2[1]; + var46.i = _src.x2[0]; + } + /* 5: avgub */ + var47.x2[0] = ((orc_uint8) var45.x2[0] + (orc_uint8) var46.x2[0] + 1) >> 1; + var47.x2[1] = ((orc_uint8) var45.x2[1] + (orc_uint8) var46.x2[1] + 1) >> 1; + /* 6: mergebw */ + { + orc_union16 _dest; + _dest.x2[0] = var44.x2[0]; + _dest.x2[1] = var47.x2[0]; + var39.x2[0] = _dest.i; + } + { + orc_union16 _dest; + _dest.x2[0] = var44.x2[1]; + _dest.x2[1] = var47.x2[1]; + var39.x2[1] = _dest.i; + } + /* 7: storel */ + ptr0[i] = var39; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_downsample_yuyv; +void +gst_videoscale_orc_downsample_yuyv (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_downsample_yuyv; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_resample_nearest_u8 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_resample_nearest_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: ldresnearb */ + var32 = ptr4[(p1 + i * p2) >> 16]; + /* 1: storeb */ + ptr0[i] = var32; + } + +} + +#else +static void +_backup_gst_videoscale_orc_resample_nearest_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: ldresnearb */ + var32 = ptr4[(ex->params[24] + i * ex->params[25]) >> 16]; + /* 1: storeb */ + ptr0[i] = var32; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_resample_nearest_u8; +void +gst_videoscale_orc_resample_nearest_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_resample_nearest_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_resample_bilinear_u8 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_resample_bilinear_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: ldreslinb */ + { + int tmp = p1 + i * p2; + var32 = + ((orc_uint8) ptr4[tmp >> 16] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) ptr4[(tmp >> 16) + 1] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storeb */ + ptr0[i] = var32; + } + +} + +#else +static void +_backup_gst_videoscale_orc_resample_bilinear_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + orc_int8 var32; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: ldreslinb */ + { + int tmp = ex->params[24] + i * ex->params[25]; + var32 = + ((orc_uint8) ptr4[tmp >> 16] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) ptr4[(tmp >> 16) + 1] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storeb */ + ptr0[i] = var32; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_resample_bilinear_u8; +void +gst_videoscale_orc_resample_bilinear_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_resample_bilinear_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_resample_nearest_u32 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_resample_nearest_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: ldresnearl */ + var32 = ptr4[(p1 + i * p2) >> 16]; + /* 1: storel */ + ptr0[i] = var32; + } + +} + +#else +static void +_backup_gst_videoscale_orc_resample_nearest_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: ldresnearl */ + var32 = ptr4[(ex->params[24] + i * ex->params[25]) >> 16]; + /* 1: storel */ + ptr0[i] = var32; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_resample_nearest_u32; +void +gst_videoscale_orc_resample_nearest_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_resample_nearest_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_resample_bilinear_u32 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_resample_bilinear_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union32 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: ldreslinl */ + { + int tmp = p1 + i * p2; + orc_union32 a = ptr4[tmp >> 16]; + orc_union32 b = ptr4[(tmp >> 16) + 1]; + var32.x4[0] = + ((orc_uint8) a.x4[0] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[0] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[1] = + ((orc_uint8) a.x4[1] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[1] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[2] = + ((orc_uint8) a.x4[2] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[2] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[3] = + ((orc_uint8) a.x4[3] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[3] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storel */ + ptr0[i] = var32; + } + +} + +#else +static void +_backup_gst_videoscale_orc_resample_bilinear_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var32; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: ldreslinl */ + { + int tmp = ex->params[24] + i * ex->params[25]; + orc_union32 a = ptr4[tmp >> 16]; + orc_union32 b = ptr4[(tmp >> 16) + 1]; + var32.x4[0] = + ((orc_uint8) a.x4[0] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[0] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[1] = + ((orc_uint8) a.x4[1] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[1] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[2] = + ((orc_uint8) a.x4[2] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[2] * ((tmp >> 8) & 0xff)) >> 8; + var32.x4[3] = + ((orc_uint8) a.x4[3] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[3] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storel */ + ptr0[i] = var32; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_resample_bilinear_u32; +void +gst_videoscale_orc_resample_bilinear_u32 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, int p1, int p2, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_resample_bilinear_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_resample_merge_bilinear_u32 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_resample_merge_bilinear_u32 (guint8 * ORC_RESTRICT d1, + guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, + const guint8 * ORC_RESTRICT s2, int p1, int p2, int p3, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 *ORC_RESTRICT ptr1; + const orc_union32 *ORC_RESTRICT ptr4; + const orc_union32 *ORC_RESTRICT ptr5; + orc_union64 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + orc_union64 var41; + orc_union64 var42; + orc_union64 var43; + orc_union64 var44; + orc_union32 var45; + + ptr0 = (orc_union32 *) d1; + ptr1 = (orc_union32 *) d2; + ptr4 = (orc_union32 *) s1; + ptr5 = (orc_union32 *) s2; + + /* 6: loadpw */ + var37.x4[0] = p1; + var37.x4[1] = p1; + var37.x4[2] = p1; + var37.x4[3] = p1; + + for (i = 0; i < n; i++) { + /* 0: ldreslinl */ + { + int tmp = p2 + i * p3; + orc_union32 a = ptr5[tmp >> 16]; + orc_union32 b = ptr5[(tmp >> 16) + 1]; + var39.x4[0] = + ((orc_uint8) a.x4[0] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[0] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[1] = + ((orc_uint8) a.x4[1] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[1] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[2] = + ((orc_uint8) a.x4[2] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[2] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[3] = + ((orc_uint8) a.x4[3] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[3] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storel */ + ptr1[i] = var39; + /* 2: loadl */ + var40 = ptr4[i]; + /* 3: convubw */ + var41.x4[0] = (orc_uint8) var40.x4[0]; + var41.x4[1] = (orc_uint8) var40.x4[1]; + var41.x4[2] = (orc_uint8) var40.x4[2]; + var41.x4[3] = (orc_uint8) var40.x4[3]; + /* 4: convubw */ + var42.x4[0] = (orc_uint8) var39.x4[0]; + var42.x4[1] = (orc_uint8) var39.x4[1]; + var42.x4[2] = (orc_uint8) var39.x4[2]; + var42.x4[3] = (orc_uint8) var39.x4[3]; + /* 5: subw */ + var43.x4[0] = var42.x4[0] - var41.x4[0]; + var43.x4[1] = var42.x4[1] - var41.x4[1]; + var43.x4[2] = var42.x4[2] - var41.x4[2]; + var43.x4[3] = var42.x4[3] - var41.x4[3]; + /* 7: mullw */ + var44.x4[0] = (var43.x4[0] * var37.x4[0]) & 0xffff; + var44.x4[1] = (var43.x4[1] * var37.x4[1]) & 0xffff; + var44.x4[2] = (var43.x4[2] * var37.x4[2]) & 0xffff; + var44.x4[3] = (var43.x4[3] * var37.x4[3]) & 0xffff; + /* 8: convhwb */ + var45.x4[0] = ((orc_uint16) var44.x4[0]) >> 8; + var45.x4[1] = ((orc_uint16) var44.x4[1]) >> 8; + var45.x4[2] = ((orc_uint16) var44.x4[2]) >> 8; + var45.x4[3] = ((orc_uint16) var44.x4[3]) >> 8; + /* 9: addb */ + var38.x4[0] = var45.x4[0] + var40.x4[0]; + var38.x4[1] = var45.x4[1] + var40.x4[1]; + var38.x4[2] = var45.x4[2] + var40.x4[2]; + var38.x4[3] = var45.x4[3] + var40.x4[3]; + /* 10: storel */ + ptr0[i] = var38; + } + +} + +#else +static void +_backup_gst_videoscale_orc_resample_merge_bilinear_u32 (OrcExecutor * + ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 *ORC_RESTRICT ptr1; + const orc_union32 *ORC_RESTRICT ptr4; + const orc_union32 *ORC_RESTRICT ptr5; + orc_union64 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + orc_union64 var41; + orc_union64 var42; + orc_union64 var43; + orc_union64 var44; + orc_union32 var45; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr1 = (orc_union32 *) ex->arrays[1]; + ptr4 = (orc_union32 *) ex->arrays[4]; + ptr5 = (orc_union32 *) ex->arrays[5]; + + /* 6: loadpw */ + var37.x4[0] = ex->params[24]; + var37.x4[1] = ex->params[24]; + var37.x4[2] = ex->params[24]; + var37.x4[3] = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: ldreslinl */ + { + int tmp = ex->params[25] + i * ex->params[26]; + orc_union32 a = ptr5[tmp >> 16]; + orc_union32 b = ptr5[(tmp >> 16) + 1]; + var39.x4[0] = + ((orc_uint8) a.x4[0] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[0] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[1] = + ((orc_uint8) a.x4[1] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[1] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[2] = + ((orc_uint8) a.x4[2] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[2] * ((tmp >> 8) & 0xff)) >> 8; + var39.x4[3] = + ((orc_uint8) a.x4[3] * (256 - ((tmp >> 8) & 0xff)) + + (orc_uint8) b.x4[3] * ((tmp >> 8) & 0xff)) >> 8; + } + /* 1: storel */ + ptr1[i] = var39; + /* 2: loadl */ + var40 = ptr4[i]; + /* 3: convubw */ + var41.x4[0] = (orc_uint8) var40.x4[0]; + var41.x4[1] = (orc_uint8) var40.x4[1]; + var41.x4[2] = (orc_uint8) var40.x4[2]; + var41.x4[3] = (orc_uint8) var40.x4[3]; + /* 4: convubw */ + var42.x4[0] = (orc_uint8) var39.x4[0]; + var42.x4[1] = (orc_uint8) var39.x4[1]; + var42.x4[2] = (orc_uint8) var39.x4[2]; + var42.x4[3] = (orc_uint8) var39.x4[3]; + /* 5: subw */ + var43.x4[0] = var42.x4[0] - var41.x4[0]; + var43.x4[1] = var42.x4[1] - var41.x4[1]; + var43.x4[2] = var42.x4[2] - var41.x4[2]; + var43.x4[3] = var42.x4[3] - var41.x4[3]; + /* 7: mullw */ + var44.x4[0] = (var43.x4[0] * var37.x4[0]) & 0xffff; + var44.x4[1] = (var43.x4[1] * var37.x4[1]) & 0xffff; + var44.x4[2] = (var43.x4[2] * var37.x4[2]) & 0xffff; + var44.x4[3] = (var43.x4[3] * var37.x4[3]) & 0xffff; + /* 8: convhwb */ + var45.x4[0] = ((orc_uint16) var44.x4[0]) >> 8; + var45.x4[1] = ((orc_uint16) var44.x4[1]) >> 8; + var45.x4[2] = ((orc_uint16) var44.x4[2]) >> 8; + var45.x4[3] = ((orc_uint16) var44.x4[3]) >> 8; + /* 9: addb */ + var38.x4[0] = var45.x4[0] + var40.x4[0]; + var38.x4[1] = var45.x4[1] + var40.x4[1]; + var38.x4[2] = var45.x4[2] + var40.x4[2]; + var38.x4[3] = var45.x4[3] + var40.x4[3]; + /* 10: storel */ + ptr0[i] = var38; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_resample_merge_bilinear_u32; +void +gst_videoscale_orc_resample_merge_bilinear_u32 (guint8 * ORC_RESTRICT d1, + guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, + const guint8 * ORC_RESTRICT s2, int p1, int p2, int p3, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_resample_merge_bilinear_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_D2] = d2; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->arrays[ORC_VAR_S2] = (void *) s2; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + ex->params[ORC_VAR_P3] = p3; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_videoscale_orc_merge_bicubic_u8 */ +#ifdef DISABLE_ORC +void +gst_videoscale_orc_merge_bicubic_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, + const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, int p1, + int p2, int p3, int p4, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + const orc_int8 *ORC_RESTRICT ptr5; + const orc_int8 *ORC_RESTRICT ptr6; + const orc_int8 *ORC_RESTRICT ptr7; + orc_int8 var34; + orc_int8 var35; + orc_int8 var36; + orc_int8 var37; + orc_int8 var38; + orc_int8 var39; + orc_int8 var40; + orc_int8 var41; + orc_union16 var42; + orc_int8 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_union16 var47; + orc_union16 var48; + orc_union16 var49; + orc_union16 var50; + orc_union16 var51; + orc_union16 var52; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_int8 *) s1; + ptr5 = (orc_int8 *) s2; + ptr6 = (orc_int8 *) s3; + ptr7 = (orc_int8 *) s4; + + /* 1: loadpb */ + var35 = p2; + /* 4: loadpb */ + var37 = p3; + /* 8: loadpb */ + var39 = p1; + /* 12: loadpb */ + var41 = p4; + /* 15: loadpw */ + var42.i = (int) 0x00000020; /* 32 or 1.58101e-322f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr5[i]; + /* 2: mulubw */ + var44.i = ((orc_uint8) var34) * ((orc_uint8) var35); + /* 3: loadb */ + var36 = ptr6[i]; + /* 5: mulubw */ + var45.i = ((orc_uint8) var36) * ((orc_uint8) var37); + /* 6: addw */ + var46.i = var44.i + var45.i; + /* 7: loadb */ + var38 = ptr4[i]; + /* 9: mulubw */ + var47.i = ((orc_uint8) var38) * ((orc_uint8) var39); + /* 10: subw */ + var48.i = var46.i - var47.i; + /* 11: loadb */ + var40 = ptr7[i]; + /* 13: mulubw */ + var49.i = ((orc_uint8) var40) * ((orc_uint8) var41); + /* 14: subw */ + var50.i = var48.i - var49.i; + /* 16: addw */ + var51.i = var50.i + var42.i; + /* 17: shrsw */ + var52.i = var51.i >> 6; + /* 18: convsuswb */ + var43 = ORC_CLAMP_UB (var52.i); + /* 19: storeb */ + ptr0[i] = var43; + } + +} + +#else +static void +_backup_gst_videoscale_orc_merge_bicubic_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_int8 *ORC_RESTRICT ptr4; + const orc_int8 *ORC_RESTRICT ptr5; + const orc_int8 *ORC_RESTRICT ptr6; + const orc_int8 *ORC_RESTRICT ptr7; + orc_int8 var34; + orc_int8 var35; + orc_int8 var36; + orc_int8 var37; + orc_int8 var38; + orc_int8 var39; + orc_int8 var40; + orc_int8 var41; + orc_union16 var42; + orc_int8 var43; + orc_union16 var44; + orc_union16 var45; + orc_union16 var46; + orc_union16 var47; + orc_union16 var48; + orc_union16 var49; + orc_union16 var50; + orc_union16 var51; + orc_union16 var52; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_int8 *) ex->arrays[4]; + ptr5 = (orc_int8 *) ex->arrays[5]; + ptr6 = (orc_int8 *) ex->arrays[6]; + ptr7 = (orc_int8 *) ex->arrays[7]; + + /* 1: loadpb */ + var35 = ex->params[25]; + /* 4: loadpb */ + var37 = ex->params[26]; + /* 8: loadpb */ + var39 = ex->params[24]; + /* 12: loadpb */ + var41 = ex->params[27]; + /* 15: loadpw */ + var42.i = (int) 0x00000020; /* 32 or 1.58101e-322f */ + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var34 = ptr5[i]; + /* 2: mulubw */ + var44.i = ((orc_uint8) var34) * ((orc_uint8) var35); + /* 3: loadb */ + var36 = ptr6[i]; + /* 5: mulubw */ + var45.i = ((orc_uint8) var36) * ((orc_uint8) var37); + /* 6: addw */ + var46.i = var44.i + var45.i; + /* 7: loadb */ + var38 = ptr4[i]; + /* 9: mulubw */ + var47.i = ((orc_uint8) var38) * ((orc_uint8) var39); + /* 10: subw */ + var48.i = var46.i - var47.i; + /* 11: loadb */ + var40 = ptr7[i]; + /* 13: mulubw */ + var49.i = ((orc_uint8) var40) * ((orc_uint8) var41); + /* 14: subw */ + var50.i = var48.i - var49.i; + /* 16: addw */ + var51.i = var50.i + var42.i; + /* 17: shrsw */ + var52.i = var51.i >> 6; + /* 18: convsuswb */ + var43 = ORC_CLAMP_UB (var52.i); + /* 19: storeb */ + ptr0[i] = var43; + } + +} + +static OrcProgram *_orc_program_gst_videoscale_orc_merge_bicubic_u8; +void +gst_videoscale_orc_merge_bicubic_u8 (guint8 * ORC_RESTRICT d1, + const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, + const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, int p1, + int p2, int p3, int p4, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_videoscale_orc_merge_bicubic_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + ex->arrays[ORC_VAR_S2] = (void *) s2; + ex->arrays[ORC_VAR_S3] = (void *) s3; + ex->arrays[ORC_VAR_S4] = (void *) s4; + ex->params[ORC_VAR_P1] = p1; + ex->params[ORC_VAR_P2] = p2; + ex->params[ORC_VAR_P3] = p3; + ex->params[ORC_VAR_P4] = p4; + + func = p->code_exec; + func (ex); +} +#endif + + +void +gst_videoscale_orc_init (void) +{ +#ifndef DISABLE_ORC + { + /* orc_merge_linear_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_merge_linear_u8"); + orc_program_set_backup_function (p, _backup_orc_merge_linear_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_source (p, 1, "s2"); + orc_program_add_constant (p, 4, 0x00000080, "c1"); + orc_program_add_parameter (p, 1, "p1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 2, "t2"); + orc_program_add_temporary (p, 1, "t3"); + orc_program_add_temporary (p, 1, "t4"); + + orc_program_append_2 (p, "loadb", 0, ORC_VAR_T3, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convubw", 0, ORC_VAR_T2, ORC_VAR_S2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "subw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "mullw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "addw", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convhwb", 0, ORC_VAR_T4, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "addb", 0, ORC_VAR_D1, ORC_VAR_T4, ORC_VAR_T3, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_merge_linear_u8 = p; + } + { + /* orc_merge_linear_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_merge_linear_u16"); + orc_program_set_backup_function (p, _backup_orc_merge_linear_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_source (p, 2, "s2"); + orc_program_add_constant (p, 4, 0x00000010, "c1"); + orc_program_add_parameter (p, 2, "p1"); + orc_program_add_parameter (p, 2, "p2"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "muluwl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "muluwl", 0, ORC_VAR_T2, ORC_VAR_S2, ORC_VAR_P2, + ORC_VAR_D1); + orc_program_append_2 (p, "addl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "shrul", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_merge_linear_u16 = p; + } + { + /* orc_splat_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_splat_u16"); + orc_program_set_backup_function (p, _backup_orc_splat_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_parameter (p, 2, "p1"); + + orc_program_append_2 (p, "copyw", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_splat_u16 = p; + } + { + /* orc_splat_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_splat_u32"); + orc_program_set_backup_function (p, _backup_orc_splat_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_parameter (p, 4, "p1"); + + orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_splat_u32 = p; + } + { + /* orc_splat_u64 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_splat_u64"); + orc_program_set_backup_function (p, _backup_orc_splat_u64); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_parameter_int64 (p, 8, "p1"); + + orc_program_append_2 (p, "copyq", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_splat_u64 = p; + } + { + /* orc_downsample_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_downsample_u8"); + orc_program_set_backup_function (p, _backup_orc_downsample_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 2, "s1"); + orc_program_add_temporary (p, 1, "t1"); + orc_program_add_temporary (p, 1, "t2"); + + orc_program_append_2 (p, "splitwb", 0, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_S1, + ORC_VAR_D1); + orc_program_append_2 (p, "avgub", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_downsample_u8 = p; + } + { + /* orc_downsample_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_downsample_u16"); + orc_program_set_backup_function (p, _backup_orc_downsample_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "splitlw", 0, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_S1, + ORC_VAR_D1); + orc_program_append_2 (p, "avguw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_downsample_u16 = p; + } + { + /* gst_videoscale_orc_downsample_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_downsample_u32"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_downsample_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "splitql", 0, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_S1, + ORC_VAR_D1); + orc_program_append_2 (p, "avgub", 2, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_downsample_u32 = p; + } + { + /* gst_videoscale_orc_downsample_yuyv */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_downsample_yuyv"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_downsample_yuyv); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 4, "t2"); + orc_program_add_temporary (p, 2, "t3"); + orc_program_add_temporary (p, 2, "t4"); + orc_program_add_temporary (p, 2, "t5"); + orc_program_add_temporary (p, 2, "t6"); + + orc_program_append_2 (p, "splitwb", 2, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_S1, + ORC_VAR_D1); + orc_program_append_2 (p, "splitwb", 1, ORC_VAR_T3, ORC_VAR_T4, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "avgub", 1, ORC_VAR_T5, ORC_VAR_T3, ORC_VAR_T4, + ORC_VAR_D1); + orc_program_append_2 (p, "splitlw", 0, ORC_VAR_T3, ORC_VAR_T4, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "avgub", 1, ORC_VAR_T6, ORC_VAR_T3, ORC_VAR_T4, + ORC_VAR_D1); + orc_program_append_2 (p, "mergebw", 1, ORC_VAR_D1, ORC_VAR_T5, ORC_VAR_T6, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_downsample_yuyv = p; + } + { + /* gst_videoscale_orc_resample_nearest_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_resample_nearest_u8"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_resample_nearest_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + + orc_program_append_2 (p, "ldresnearb", 0, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_P1, ORC_VAR_P2); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_resample_nearest_u8 = p; + } + { + /* gst_videoscale_orc_resample_bilinear_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_resample_bilinear_u8"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_resample_bilinear_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + + orc_program_append_2 (p, "ldreslinb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_P2); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_resample_bilinear_u8 = p; + } + { + /* gst_videoscale_orc_resample_nearest_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_resample_nearest_u32"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_resample_nearest_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + + orc_program_append_2 (p, "ldresnearl", 0, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_P1, ORC_VAR_P2); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_resample_nearest_u32 = p; + } + { + /* gst_videoscale_orc_resample_bilinear_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_resample_bilinear_u32"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_resample_bilinear_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + + orc_program_append_2 (p, "ldreslinl", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_P2); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_resample_bilinear_u32 = p; + } + { + /* gst_videoscale_orc_resample_merge_bilinear_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_resample_merge_bilinear_u32"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_resample_merge_bilinear_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_destination (p, 4, "d2"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_source (p, 4, "s2"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + orc_program_add_parameter (p, 4, "p3"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 4, "t2"); + orc_program_add_temporary (p, 4, "t3"); + orc_program_add_temporary (p, 8, "t4"); + orc_program_add_temporary (p, 8, "t5"); + + orc_program_append_2 (p, "ldreslinl", 0, ORC_VAR_T2, ORC_VAR_S2, ORC_VAR_P2, + ORC_VAR_P3); + orc_program_append_2 (p, "storel", 0, ORC_VAR_D2, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "loadl", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convubw", 2, ORC_VAR_T4, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convubw", 2, ORC_VAR_T5, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "subw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_T4, + ORC_VAR_D1); + orc_program_append_2 (p, "mullw", 2, ORC_VAR_T5, ORC_VAR_T5, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "convhwb", 2, ORC_VAR_T3, ORC_VAR_T5, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "addb", 2, ORC_VAR_D1, ORC_VAR_T3, ORC_VAR_T1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_resample_merge_bilinear_u32 = p; + } + { + /* gst_videoscale_orc_merge_bicubic_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_videoscale_orc_merge_bicubic_u8"); + orc_program_set_backup_function (p, + _backup_gst_videoscale_orc_merge_bicubic_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 1, "s1"); + orc_program_add_source (p, 1, "s2"); + orc_program_add_source (p, 1, "s3"); + orc_program_add_source (p, 1, "s4"); + orc_program_add_constant (p, 4, 0x00000020, "c1"); + orc_program_add_constant (p, 4, 0x00000006, "c2"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_parameter (p, 4, "p2"); + orc_program_add_parameter (p, 4, "p3"); + orc_program_add_parameter (p, 4, "p4"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 2, "t2"); + + orc_program_append_2 (p, "mulubw", 0, ORC_VAR_T1, ORC_VAR_S2, ORC_VAR_P2, + ORC_VAR_D1); + orc_program_append_2 (p, "mulubw", 0, ORC_VAR_T2, ORC_VAR_S3, ORC_VAR_P3, + ORC_VAR_D1); + orc_program_append_2 (p, "addw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "mulubw", 0, ORC_VAR_T2, ORC_VAR_S1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "subw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "mulubw", 0, ORC_VAR_T2, ORC_VAR_S4, ORC_VAR_P4, + ORC_VAR_D1); + orc_program_append_2 (p, "subw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "addw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C2, + ORC_VAR_D1); + orc_program_append_2 (p, "convsuswb", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_videoscale_orc_merge_bicubic_u8 = p; + } +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.h b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.h new file mode 100644 index 0000000..214b72f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc-dist.h @@ -0,0 +1,93 @@ + +/* autogenerated from gstvideoscaleorc.orc */ + +#ifndef _GSTVIDEOSCALEORC_H_ +#define _GSTVIDEOSCALEORC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void gst_videoscale_orc_init (void); + + + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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_merge_linear_u8 (orc_uint8 * ORC_RESTRICT d1, const orc_uint8 * ORC_RESTRICT s1, const orc_uint8 * ORC_RESTRICT s2, int p1, int n); +void orc_merge_linear_u16 (orc_uint16 * ORC_RESTRICT d1, const orc_uint16 * ORC_RESTRICT s1, const orc_uint16 * ORC_RESTRICT s2, int p1, int p2, int n); +void orc_splat_u16 (orc_uint16 * ORC_RESTRICT d1, int p1, int n); +void orc_splat_u32 (orc_uint32 * ORC_RESTRICT d1, int p1, int n); +void orc_splat_u64 (orc_uint64 * ORC_RESTRICT d1, orc_int64 p1, int n); +void orc_downsample_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n); +void orc_downsample_u16 (guint16 * ORC_RESTRICT d1, const guint16 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_downsample_u32 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_downsample_yuyv (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int n); +void gst_videoscale_orc_resample_nearest_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_bilinear_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_nearest_u32 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_bilinear_u32 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, int p1, int p2, int n); +void gst_videoscale_orc_resample_merge_bilinear_u32 (guint8 * ORC_RESTRICT d1, guint8 * ORC_RESTRICT d2, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, int p1, int p2, int p3, int n); +void gst_videoscale_orc_merge_bicubic_u8 (guint8 * ORC_RESTRICT d1, const guint8 * ORC_RESTRICT s1, const guint8 * ORC_RESTRICT s2, const guint8 * ORC_RESTRICT s3, const guint8 * ORC_RESTRICT s4, int p1, int p2, int p3, int p4, int n); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc.orc b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc.orc new file mode 100644 index 0000000..81623e2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/gstvideoscaleorc.orc @@ -0,0 +1,199 @@ + +.init gst_videoscale_orc_init + +.function orc_merge_linear_u8 +.dest 1 d1 +.source 1 s1 +.source 1 s2 +.param 1 p1 +.temp 2 t1 +.temp 2 t2 +.temp 1 a +.temp 1 t + +loadb a, s1 +convubw t1, s1 +convubw t2, s2 +subw t2, t2, t1 +mullw t2, t2, p1 +addw t2, t2, 128 +convhwb t, t2 +addb d1, t, a + + + +.function orc_merge_linear_u16 +.dest 2 d1 +.source 2 s1 +.source 2 s2 +.param 2 p1 +.param 2 p2 +.temp 4 t1 +.temp 4 t2 + +# This is slightly different thatn the u8 case, since muluwl +# tends to be much faster than mulll +muluwl t1, s1, p1 +muluwl t2, s2, p2 +addl t1, t1, t2 +shrul t1, t1, 16 +convlw d1, t1 + + +.function orc_splat_u16 +.dest 2 d1 +.param 2 p1 + +copyw d1, p1 + + +.function orc_splat_u32 +.dest 4 d1 +.param 4 p1 + +copyl d1, p1 + + +.function orc_splat_u64 +.dest 8 d1 +.longparam 8 p1 + +copyq d1, p1 + + +.function orc_downsample_u8 +.dest 1 d1 guint8 +.source 2 s1 guint8 +.temp 1 t1 +.temp 1 t2 + +splitwb t1, t2, s1 +avgub d1, t1, t2 + + +.function orc_downsample_u16 +.dest 2 d1 guint16 +.source 4 s1 guint16 +.temp 2 t1 +.temp 2 t2 + +splitlw t1, t2, s1 +avguw d1, t1, t2 + + +.function gst_videoscale_orc_downsample_u32 +.dest 4 d1 guint8 +.source 8 s1 guint8 +.temp 4 t1 +.temp 4 t2 + +splitql t1, t2, s1 +x4 avgub d1, t1, t2 + + +.function gst_videoscale_orc_downsample_yuyv +.dest 4 d1 guint8 +.source 8 s1 guint8 +.temp 4 yyyy +.temp 4 uvuv +.temp 2 t1 +.temp 2 t2 +.temp 2 yy +.temp 2 uv + +x4 splitwb yyyy, uvuv, s1 +x2 splitwb t1, t2, yyyy +x2 avgub yy, t1, t2 +splitlw t1, t2, uvuv +x2 avgub uv, t1, t2 +x2 mergebw d1, yy, uv + + + +.function gst_videoscale_orc_resample_nearest_u8 +.dest 1 d1 guint8 +.source 1 s1 guint8 +.param 4 p1 +.param 4 p2 + +ldresnearb d1, s1, p1, p2 + + +.function gst_videoscale_orc_resample_bilinear_u8 +.dest 1 d1 guint8 +.source 1 s1 guint8 +.param 4 p1 +.param 4 p2 + +ldreslinb d1, s1, p1, p2 + + +.function gst_videoscale_orc_resample_nearest_u32 +.dest 4 d1 guint8 +.source 4 s1 guint8 +.param 4 p1 +.param 4 p2 + +ldresnearl d1, s1, p1, p2 + + +.function gst_videoscale_orc_resample_bilinear_u32 +.dest 4 d1 guint8 +.source 4 s1 guint8 +.param 4 p1 +.param 4 p2 + +ldreslinl d1, s1, p1, p2 + + +.function gst_videoscale_orc_resample_merge_bilinear_u32 +.dest 4 d1 guint8 +.dest 4 d2 guint8 +.source 4 s1 guint8 +.source 4 s2 guint8 +.temp 4 a +.temp 4 b +.temp 4 t +.temp 8 t1 +.temp 8 t2 +.param 4 p1 +.param 4 p2 +.param 4 p3 + +ldreslinl b, s2, p2, p3 +storel d2, b +loadl a, s1 +x4 convubw t1, a +x4 convubw t2, b +x4 subw t2, t2, t1 +x4 mullw t2, t2, p1 +x4 convhwb t, t2 +x4 addb d1, t, a + + + +.function gst_videoscale_orc_merge_bicubic_u8 +.dest 1 d1 guint8 +.source 1 s1 guint8 +.source 1 s2 guint8 +.source 1 s3 guint8 +.source 1 s4 guint8 +.param 4 p1 +.param 4 p2 +.param 4 p3 +.param 4 p4 +.temp 2 t1 +.temp 2 t2 + +mulubw t1, s2, p2 +mulubw t2, s3, p3 +addw t1, t1, t2 +mulubw t2, s1, p1 +subw t1, t1, t2 +mulubw t2, s4, p4 +subw t1, t1, t2 +addw t1, t1, 32 +shrsw t1, t1, 6 +convsuswb d1, t1 + + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/videoscale.vcproj b/gst-plugins-base-subtitles0.10/gst/videoscale/videoscale.vcproj new file mode 100644 index 0000000..9388f67 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/videoscale.vcproj @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.c b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.c new file mode 100644 index 0000000..f983df2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.c @@ -0,0 +1,1451 @@ +/* + * Image Scaling Functions (4 tap) + * Copyright (c) 2005 David A. Schleef + * Copyright (c) 2009 Sebastian Dröge + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vs_image.h" +#include "vs_scanline.h" + +#include "vs_4tap.h" + +#include + +#define SHIFT 10 + +static int16_t vs_4tap_taps[256][4]; + +static double +vs_4tap_func (double x) +{ +#if 0 + if (x < -1) + return 0; + if (x > 1) + return 0; + if (x < 0) + return 1 + x; + return 1 - x; +#endif +#if 0 + if (x == 0) + return 1; + return sin (M_PI * x) / (M_PI * x) * (1 - 0.25 * x * x); +#endif +#if 1 + if (x == 0) + return 1; + return sin (M_PI * x) / (M_PI * x); +#endif +} + +void +vs_4tap_init (void) +{ + int i; + double a, b, c, d; + double sum; + + for (i = 0; i < 256; i++) { + a = vs_4tap_func (-1 - i / 256.0); + b = vs_4tap_func (0 - i / 256.0); + c = vs_4tap_func (1 - i / 256.0); + d = vs_4tap_func (2 - i / 256.0); + sum = a + b + c + d; + + vs_4tap_taps[i][0] = rint ((1 << SHIFT) * (a / sum)); + vs_4tap_taps[i][1] = rint ((1 << SHIFT) * (b / sum)); + vs_4tap_taps[i][2] = rint ((1 << SHIFT) * (c / sum)); + vs_4tap_taps[i][3] = rint ((1 << SHIFT) * (d / sum)); + } +} + + +void +vs_scanline_resample_4tap_Y (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xff00) >> 8; + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j - 1, 0)]; + y += vs_4tap_taps[x][1] * src[j]; + y += vs_4tap_taps[x][2] * src[j + 1]; + y += vs_4tap_taps[x][3] * src[j + 2]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j - 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j, 0, src_width - 1)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j + 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j + 2, 0, src_width - 1)]; + } + y += (1 << (SHIFT - 1)); + dest[i] = CLAMP (y >> SHIFT, 0, 255); + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int a, b, c, d; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + y = a * src1[i]; + y += b * src2[i]; + y += c * src3[i]; + y += d * src4[i]; + y += (1 << (SHIFT - 1)); + dest[i] = CLAMP (y >> SHIFT, 0, 255); + } +} + + +void +vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_Y (tmpbuf + i * dest->width, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_Y (tmpbuf + ((k + 3) & 3) * dest->width, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->width; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->width; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->width; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->width; + vs_scanline_merge_4tap_Y (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_Y16 (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xff00) >> 8; + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * s[MAX (j - 1, 0)]; + y += vs_4tap_taps[x][1] * s[j]; + y += vs_4tap_taps[x][2] * s[j + 1]; + y += vs_4tap_taps[x][3] * s[j + 2]; + } else { + y = vs_4tap_taps[x][0] * s[CLAMP (j - 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][1] * s[CLAMP (j, 0, src_width - 1)]; + y += vs_4tap_taps[x][2] * s[CLAMP (j + 1, 0, src_width - 1)]; + y += vs_4tap_taps[x][3] * s[CLAMP (j + 2, 0, src_width - 1)]; + } + y += (1 << (SHIFT - 1)); + d[i] = CLAMP (y >> SHIFT, 0, 65535); + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int a, b, c, d; + uint16_t *de = (uint16_t *) dest, *s1 = (uint16_t *) src1; + uint16_t *s2 = (uint16_t *) src2, *s3 = (uint16_t *) src3; + uint16_t *s4 = (uint16_t *) src4; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + y = a * s1[i]; + y += b * s2[i]; + y += c * s3[i]; + y += d * s4[i]; + y += (1 << (SHIFT - 1)); + de[i] = CLAMP (y >> SHIFT, 0, 65535); + } +} + + +void +vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_Y16 (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_Y16 (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_Y16 (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_RGBA (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + int off; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + for (off = 0; off < 4; off++) { + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)]; + y += vs_4tap_taps[x][1] * src[j * 4 + off]; + y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off]; + y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off]; + } else { + y = vs_4tap_taps[x][0] * + src[CLAMP ((j - 1), 0, src_width - 1) * 4 + off]; + y += vs_4tap_taps[x][1] * + src[CLAMP ((j + 0), 0, src_width - 1) * 4 + off]; + y += vs_4tap_taps[x][2] * + src[CLAMP ((j + 1), 0, src_width - 1) * 4 + off]; + y += vs_4tap_taps[x][3] * + src[CLAMP ((j + 2), 0, src_width - 1) * 4 + off]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255); + } + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int off; + int a, b, c, d; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + for (off = 0; off < 4; off++) { + y = a * src1[i * 4 + off]; + y += b * src2[i * 4 + off]; + y += c * src3[i * 4 + off]; + y += d * src4[i * 4 + off]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255); + } + } +} + +void +vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_RGBA (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_RGBA (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_RGBA (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_RGB (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + int off; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + for (off = 0; off < 3; off++) { + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 3 + off, 0)]; + y += vs_4tap_taps[x][1] * src[j * 3 + off]; + y += vs_4tap_taps[x][2] * src[(j + 1) * 3 + off]; + y += vs_4tap_taps[x][3] * src[(j + 2) * 3 + off]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 3 + off, 0, + 3 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 3 + off, 0, + 3 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 3 + off, 0, + 3 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 3 + off, 0, + 3 * (src_width - 1) + off)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255); + } + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int off; + int a, b, c, d; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + for (off = 0; off < 3; off++) { + y = a * src1[i * 3 + off]; + y += b * src2[i * 3 + off]; + y += c * src3[i * 3 + off]; + y += d * src4[i * 3 + off]; + y += (1 << (SHIFT - 1)); + dest[i * 3 + off] = CLAMP (y >> SHIFT, 0, 255); + } + } +} + +void +vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_RGB (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_RGB (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_RGB (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_YUYV (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + int quads = (n + 1) / 2; + int last_y = 2 * (src_width - 1); + int last_u = + MAX ((2 * (src_width - 1) % 4 == + 0) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1); + int last_v = + MAX ((2 * (src_width - 1) % 4 == + 2) ? 2 * (src_width - 1) + 1 : 2 * (src_width - 1) - 1, 1); + + acc = *xacc; + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)]; + y += vs_4tap_taps[x][1] * src[j * 2 + 0]; + y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2]; + y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255); + + j = acc >> 17; + x = (acc & 0x1ffff) >> 9; + + if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 1 - 4, 1)]; + y += vs_4tap_taps[x][1] * src[j * 4 + 1]; + y += vs_4tap_taps[x][2] * src[j * 4 + 1 + 4]; + y += vs_4tap_taps[x][3] * src[j * 4 + 1 + 8]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 1 - 4, 1, last_u)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 1, 1, last_u)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 1 + 4, 1, last_u)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 1 + 8, 1, last_u)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255); + + if (2 * i + 1 < n) { + if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 3 - 4, 3)]; + y += vs_4tap_taps[x][1] * src[j * 4 + 3]; + y += vs_4tap_taps[x][2] * src[j * 4 + 3 + 4]; + y += vs_4tap_taps[x][3] * src[j * 4 + 3 + 8]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 3 - 4, 3, last_v)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 3, 3, last_v)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 3 + 4, 3, last_v)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 3 + 8, 3, last_v)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255); + } + + acc += increment; + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + if (2 * i + 1 < n) { + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 0 - 2, 0)]; + y += vs_4tap_taps[x][1] * src[j * 2 + 0]; + y += vs_4tap_taps[x][2] * src[j * 2 + 0 + 2]; + y += vs_4tap_taps[x][3] * src[j * 2 + 0 + 4]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 0 - 2, 0, last_y)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 0, 0, last_y)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 0 + 2, 0, last_y)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 0 + 4, 0, last_y)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255); + acc += increment; + } + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int a, b, c, d; + int quads = (n + 1) / 2; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < quads; i++) { + y = a * src1[i * 4 + 0]; + y += b * src2[i * 4 + 0]; + y += c * src3[i * 4 + 0]; + y += d * src4[i * 4 + 0]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255); + + y = a * src1[i * 4 + 1]; + y += b * src2[i * 4 + 1]; + y += c * src3[i * 4 + 1]; + y += d * src4[i * 4 + 1]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255); + + if (2 * i + 1 < n) { + y = a * src1[i * 4 + 2]; + y += b * src2[i * 4 + 2]; + y += c * src3[i * 4 + 2]; + y += d * src4[i * 4 + 2]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255); + + y = a * src1[i * 4 + 3]; + y += b * src2[i * 4 + 3]; + y += c * src3[i * 4 + 3]; + y += d * src4[i * 4 + 3]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255); + } + } +} + +void +vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_YUYV (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_YUYV (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_YUYV (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_UYVY (uint8_t * dest, uint8_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + int quads = (n + 1) / 2; + int last_y = 2 * (src_width - 1) + 1; + int last_u = + MAX ((2 * (src_width - 1) % 4 == + 0) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0); + int last_v = + MAX ((2 * (src_width - 1) % 4 == + 2) ? 2 * (src_width - 1) : 2 * (src_width - 1) - 2, 0); + + acc = *xacc; + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 1)]; + y += vs_4tap_taps[x][1] * src[j * 2 + 1]; + y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2]; + y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255); + + j = acc >> 17; + x = (acc & 0x1ffff) >> 9; + + if (2 * j - 2 >= 0 && 2 * j + 4 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 0 - 4, 0)]; + y += vs_4tap_taps[x][1] * src[j * 4 + 0]; + y += vs_4tap_taps[x][2] * src[j * 4 + 0 + 4]; + y += vs_4tap_taps[x][3] * src[j * 4 + 0 + 8]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 0 - 4, 0, last_u)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 0, 0, last_u)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 0 + 4, 0, last_u)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 0 + 8, 0, last_u)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255); + + if (2 * i + 1 < n) { + if (2 * j - 1 >= 0 && 2 * j + 4 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 4 + 2 - 4, 2)]; + y += vs_4tap_taps[x][1] * src[j * 4 + 2]; + y += vs_4tap_taps[x][2] * src[j * 4 + 2 + 4]; + y += vs_4tap_taps[x][3] * src[j * 4 + 2 + 8]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 4 + 2 - 4, 2, last_v)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + 2, 2, last_v)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 4 + 2 + 4, 2, last_v)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 4 + 2 + 8, 2, last_v)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255); + } + + acc += increment; + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + if (2 * i + 1 < n) { + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX (j * 2 + 1 - 2, 0)]; + y += vs_4tap_taps[x][1] * src[j * 2 + 1]; + y += vs_4tap_taps[x][2] * src[j * 2 + 1 + 2]; + y += vs_4tap_taps[x][3] * src[j * 2 + 1 + 4]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP (j * 2 + 1 - 2, 1, last_y)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 2 + 1, 1, last_y)]; + y += vs_4tap_taps[x][2] * src[CLAMP (j * 2 + 1 + 2, 1, last_y)]; + y += vs_4tap_taps[x][3] * src[CLAMP (j * 2 + 1 + 4, 1, last_y)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255); + acc += increment; + } + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_UYVY (uint8_t * dest, uint8_t * src1, uint8_t * src2, + uint8_t * src3, uint8_t * src4, int n, int acc) +{ + int i; + int y; + int a, b, c, d; + int quads = (n + 1) / 2; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < quads; i++) { + y = a * src1[i * 4 + 0]; + y += b * src2[i * 4 + 0]; + y += c * src3[i * 4 + 0]; + y += d * src4[i * 4 + 0]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 0] = CLAMP (y >> SHIFT, 0, 255); + + y = a * src1[i * 4 + 1]; + y += b * src2[i * 4 + 1]; + y += c * src3[i * 4 + 1]; + y += d * src4[i * 4 + 1]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 1] = CLAMP (y >> SHIFT, 0, 255); + + if (2 * i + 1 < n) { + y = a * src1[i * 4 + 2]; + y += b * src2[i * 4 + 2]; + y += c * src3[i * 4 + 2]; + y += d * src4[i * 4 + 2]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 2] = CLAMP (y >> SHIFT, 0, 255); + + y = a * src1[i * 4 + 3]; + y += b * src2[i * 4 + 3]; + y += c * src3[i * 4 + 3]; + y += d * src4[i * 4 + 3]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + 3] = CLAMP (y >> SHIFT, 0, 255); + } + } +} + +void +vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_UYVY (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_UYVY (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_UYVY (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +/* note that src and dest are uint16_t, and thus endian dependent */ + +#define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13) +#define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9) +#define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2) + +#define RGB565(r,g,b) \ + ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f)) + +void +vs_scanline_resample_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y, y_r, y_b, y_g; + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff >> 8; + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB565_R (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB565_R (src[j]); + y += vs_4tap_taps[x][2] * RGB565_R (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB565_R (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB565_R (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB565_R (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB565_R (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB565_R (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_r = CLAMP (y >> SHIFT, 0, 255); + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB565_G (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB565_G (src[j]); + y += vs_4tap_taps[x][2] * RGB565_G (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB565_G (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB565_G (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB565_G (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB565_G (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB565_G (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_g = CLAMP (y >> SHIFT, 0, 255); + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB565_B (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB565_B (src[j]); + y += vs_4tap_taps[x][2] * RGB565_B (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB565_B (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB565_B (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB565_B (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB565_B (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB565_B (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_b = CLAMP (y >> SHIFT, 0, 255); + + dest[i] = RGB565 (y_r, y_b, y_g); + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8, + uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc) +{ + int i; + int y, y_r, y_b, y_g; + int a, b, c, d; + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src1 = (uint16_t *) src1_u8; + uint16_t *src2 = (uint16_t *) src2_u8; + uint16_t *src3 = (uint16_t *) src3_u8; + uint16_t *src4 = (uint16_t *) src4_u8; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + + for (i = 0; i < n; i++) { + y = a * RGB565_R (src1[i]); + y += b * RGB565_R (src2[i]); + y += c * RGB565_R (src3[i]); + y += d * RGB565_R (src4[i]); + y += (1 << (SHIFT - 1)); + y_r = CLAMP (y >> SHIFT, 0, 255); + + y = a * RGB565_G (src1[i]); + y += b * RGB565_G (src2[i]); + y += c * RGB565_G (src3[i]); + y += d * RGB565_G (src4[i]); + y += (1 << (SHIFT - 1)); + y_g = CLAMP (y >> SHIFT, 0, 255); + + y = a * RGB565_B (src1[i]); + y += b * RGB565_B (src2[i]); + y += c * RGB565_B (src3[i]); + y += d * RGB565_B (src4[i]); + y += (1 << (SHIFT - 1)); + y_b = CLAMP (y >> SHIFT, 0, 255); + + dest[i] = RGB565 (y_r, y_b, y_g); + } +} + +void +vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_RGB565 (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_RGB565 (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_RGB565 (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +/* note that src and dest are uint16_t, and thus endian dependent */ + +#define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13) +#define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9) +#define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2) + +#define RGB555(r,g,b) \ + ((((r)<<7)&0x7c00) | (((g)<<2)&0x03e0) | (((b)>>3)&0x001f)) + +void +vs_scanline_resample_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y, y_r, y_b, y_g; + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff >> 8; + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB555_R (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB555_R (src[j]); + y += vs_4tap_taps[x][2] * RGB555_R (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB555_R (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB555_R (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB555_R (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB555_R (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB555_R (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_r = CLAMP (y >> SHIFT, 0, 255); + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB555_G (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB555_G (src[j]); + y += vs_4tap_taps[x][2] * RGB555_G (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB555_G (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB555_G (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB555_G (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB555_G (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB555_G (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_g = CLAMP (y >> SHIFT, 0, 255); + + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * RGB555_B (src[MAX ((j - 1), 0)]); + y += vs_4tap_taps[x][1] * RGB555_B (src[j]); + y += vs_4tap_taps[x][2] * RGB555_B (src[(j + 1)]); + y += vs_4tap_taps[x][3] * RGB555_B (src[(j + 2)]); + } else { + y = vs_4tap_taps[x][0] * RGB555_B (src[CLAMP ((j - 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][1] * RGB555_B (src[CLAMP (j, 0, src_width - 1)]); + y += vs_4tap_taps[x][2] * RGB555_B (src[CLAMP ((j + 1), 0, + src_width - 1)]); + y += vs_4tap_taps[x][3] * RGB555_B (src[CLAMP ((j + 2), 0, + src_width - 1)]); + } + y += (1 << (SHIFT - 1)); + y_b = CLAMP (y >> SHIFT, 0, 255); + + dest[i] = RGB555 (y_r, y_b, y_g); + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8, + uint8_t * src2_u8, uint8_t * src3_u8, uint8_t * src4_u8, int n, int acc) +{ + int i; + int y, y_r, y_b, y_g; + int a, b, c, d; + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src1 = (uint16_t *) src1_u8; + uint16_t *src2 = (uint16_t *) src2_u8; + uint16_t *src3 = (uint16_t *) src3_u8; + uint16_t *src4 = (uint16_t *) src4_u8; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + + for (i = 0; i < n; i++) { + y = a * RGB555_R (src1[i]); + y += b * RGB555_R (src2[i]); + y += c * RGB555_R (src3[i]); + y += d * RGB555_R (src4[i]); + y += (1 << (SHIFT - 1)); + y_r = CLAMP (y >> SHIFT, 0, 255); + + y = a * RGB555_G (src1[i]); + y += b * RGB555_G (src2[i]); + y += c * RGB555_G (src3[i]); + y += d * RGB555_G (src4[i]); + y += (1 << (SHIFT - 1)); + y_g = CLAMP (y >> SHIFT, 0, 255); + + y = a * RGB555_B (src1[i]); + y += b * RGB555_B (src2[i]); + y += c * RGB555_B (src3[i]); + y += d * RGB555_B (src4[i]); + y += (1 << (SHIFT - 1)); + y_b = CLAMP (y >> SHIFT, 0, 255); + + dest[i] = RGB555 (y_r, y_b, y_g); + } +} + +void +vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_RGB555 (tmpbuf + i * dest->stride, + src->pixels + CLAMP (i, 0, src->height - 1) * src->stride, dest->width, + src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint8_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_RGB555 (tmpbuf + ((k + 3) & 3) * dest->stride, + src->pixels + (k + 3) * src->stride, + dest->width, src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_RGB555 (dest->pixels + i * dest->stride, + t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} + +void +vs_scanline_resample_4tap_AYUV64 (uint16_t * dest, uint16_t * src, + int n, int src_width, int *xacc, int increment) +{ + int i; + int j; + int acc; + int x; + int y; + int off; + + acc = *xacc; + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 8; + + for (off = 0; off < 4; off++) { + if (j - 1 >= 0 && j + 2 < src_width) { + y = vs_4tap_taps[x][0] * src[MAX ((j - 1) * 4 + off, 0)]; + y += vs_4tap_taps[x][1] * src[j * 4 + off]; + y += vs_4tap_taps[x][2] * src[(j + 1) * 4 + off]; + y += vs_4tap_taps[x][3] * src[(j + 2) * 4 + off]; + } else { + y = vs_4tap_taps[x][0] * src[CLAMP ((j - 1) * 4 + off, 0, + 4 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][1] * src[CLAMP (j * 4 + off, 0, + 4 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][2] * src[CLAMP ((j + 1) * 4 + off, 0, + 4 * (src_width - 1) + off)]; + y += vs_4tap_taps[x][3] * src[CLAMP ((j + 2) * 4 + off, 0, + 4 * (src_width - 1) + off)]; + } + y += (1 << (SHIFT - 1)); + dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 255); + } + acc += increment; + } + *xacc = acc; +} + +void +vs_scanline_merge_4tap_AYUV64 (uint16_t * dest, uint16_t * src1, + uint16_t * src2, uint16_t * src3, uint16_t * src4, int n, int acc) +{ + int i; + int y; + int off; + int a, b, c, d; + + acc = (acc >> 8) & 0xff; + a = vs_4tap_taps[acc][0]; + b = vs_4tap_taps[acc][1]; + c = vs_4tap_taps[acc][2]; + d = vs_4tap_taps[acc][3]; + for (i = 0; i < n; i++) { + for (off = 0; off < 4; off++) { + y = a * src1[i * 4 + off]; + y += b * src2[i * 4 + off]; + y += c * src3[i * 4 + off]; + y += d * src4[i * 4 + off]; + y += (1 << (SHIFT - 1)); + dest[i * 4 + off] = CLAMP (y >> SHIFT, 0, 65535); + } + } +} + +void +vs_image_scale_4tap_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf8) +{ + int yacc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + int k; + guint16 *tmpbuf = (guint16 *) tmpbuf8; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + k = 0; + for (i = 0; i < 4; i++) { + xacc = 0; + vs_scanline_resample_4tap_AYUV64 ((guint16 *) (tmpbuf + i * dest->stride), + (guint16 *) (src->pixels + CLAMP (i, 0, src->height - 1) * src->stride), + dest->width, src->width, &xacc, x_increment); + } + + yacc = 0; + for (i = 0; i < dest->height; i++) { + uint16_t *t0, *t1, *t2, *t3; + + j = yacc >> 16; + + while (j > k) { + k++; + if (k + 3 < src->height) { + xacc = 0; + vs_scanline_resample_4tap_AYUV64 ((guint16 *) (tmpbuf + ((k + + 3) & 3) * dest->stride), + (guint16 *) (src->pixels + (k + 3) * src->stride), dest->width, + src->width, &xacc, x_increment); + } + } + + t0 = tmpbuf + (CLAMP (j - 1, 0, src->height - 1) & 3) * dest->stride; + t1 = tmpbuf + (CLAMP (j, 0, src->height - 1) & 3) * dest->stride; + t2 = tmpbuf + (CLAMP (j + 1, 0, src->height - 1) & 3) * dest->stride; + t3 = tmpbuf + (CLAMP (j + 2, 0, src->height - 1) & 3) * dest->stride; + vs_scanline_merge_4tap_AYUV64 ((guint16 *) (dest->pixels + + i * dest->stride), t0, t1, t2, t3, dest->width, yacc & 0xffff); + + yacc += y_increment; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.h b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.h new file mode 100644 index 0000000..6b51b52 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_4tap.h @@ -0,0 +1,99 @@ +/* + * Image Scaling Functions (4 tap) + * Copyright (c) 2005 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _VS_4TAP_H_ +#define _VS_4TAP_H_ + +#include "vs_image.h" + + +void vs_4tap_init (void); +void vs_scanline_resample_4tap_Y (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_Y (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_RGBA (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_RGBA (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_RGBA (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_RGB (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_RGB (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_RGB (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_YUYV (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_YUYV (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_YUYV (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_UYVY (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_UYVY (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_RGB565 (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_RGB565 (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_RGB565 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_RGB555 (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_RGB555 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_Y16 (uint8_t *dest, uint8_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2, + uint8_t *src3, uint8_t *src4, int n, int acc); +void vs_image_scale_4tap_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +void vs_scanline_resample_4tap_AYUV64 (uint16_t *dest, uint16_t *src, + int n, int src_width, int *xacc, int increment); +void vs_scanline_merge_4tap_AYUV64 (uint16_t *dest, uint16_t *src1, uint16_t *src2, + uint16_t *src3, uint16_t *src4, int n, int acc); +void vs_image_scale_4tap_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf); + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.c b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.c new file mode 100644 index 0000000..160e137 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.c @@ -0,0 +1,422 @@ +/* + * Image Scaling Functions + * Copyright (c) 2010 Sebastian Dröge + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "vs_fill_borders.h" +#include "gstvideoscaleorc.h" + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define READ_UINT32(ptr) GST_READ_UINT32_LE(ptr) +#define READ_UINT16(ptr) GST_READ_UINT16_LE(ptr) +#else +#define READ_UINT32(ptr) GST_READ_UINT32_BE(ptr) +#define READ_UINT16(ptr) GST_READ_UINT16_BE(ptr) +#endif + +void +vs_fill_borders_RGBA (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + uint32_t v = READ_UINT32 (val); + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + orc_splat_u32 ((uint32_t *) data, v, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 4; + for (i = 0; i < tmp; i++) { + orc_splat_u32 ((uint32_t *) data, v, left); + orc_splat_u32 ((uint32_t *) (data + tmp2), v, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + orc_splat_u32 ((uint32_t *) data, v, real_width); + data += stride; + } +} + +static void +_memset_u24 (uint8_t * data, uint8_t val1, uint8_t val2, uint8_t val3, + unsigned int n) +{ + unsigned int i; + + for (i = 0; i < n; i++) { + data[0] = val1; + data[1] = val2; + data[2] = val3; + data += 3; + } +} + +void +vs_fill_borders_RGB (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + _memset_u24 (data, val[0], val[1], val[2], real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 3; + for (i = 0; i < tmp; i++) { + _memset_u24 (data, val[0], val[1], val[2], left); + _memset_u24 (data + tmp2, val[0], val[1], val[2], right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + _memset_u24 (data, val[0], val[1], val[2], real_width); + data += stride; + } +} + +void +vs_fill_borders_YUYV (const VSImage * dest, const uint8_t * val) +{ + int i, j; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + for (j = 0; j < real_width; j++) { + data[2 * j] = val[0]; + data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3]; + } + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 2; + for (i = 0; i < tmp; i++) { + for (j = 0; j < left; j++) { + data[2 * j] = val[0]; + data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3]; + } + for (j = 0; j < right; j++) { + data[tmp2 + 2 * j] = val[0]; + data[tmp2 + 2 * j + 1] = (j % 2 == 0) ? val[1] : val[3]; + } + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + for (j = 0; j < real_width; j++) { + data[2 * j] = val[0]; + data[2 * j + 1] = (j % 2 == 0) ? val[1] : val[3]; + } + data += stride; + } +} + +void +vs_fill_borders_UYVY (const VSImage * dest, const uint8_t * val) +{ + int i, j; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + for (j = 0; j < real_width; j++) { + data[2 * j] = (j % 2 == 0) ? val[0] : val[2]; + data[2 * j + 1] = val[1]; + } + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 2; + for (i = 0; i < tmp; i++) { + for (j = 0; j < left; j++) { + data[2 * j] = (j % 2 == 0) ? val[0] : val[2]; + data[2 * j + 1] = val[1]; + } + for (j = 0; j < right; j++) { + data[tmp2 + 2 * j] = (j % 2 == 0) ? val[0] : val[2]; + data[tmp2 + 2 * j + 1] = val[1]; + } + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + for (j = 0; j < real_width; j++) { + data[2 * j] = (j % 2 == 0) ? val[0] : val[2]; + data[2 * j + 1] = val[1]; + } + data += stride; + } +} + +void +vs_fill_borders_Y (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + memset (data, *val, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = left + width; + for (i = 0; i < tmp; i++) { + memset (data, *val, left); + memset (data + tmp2, *val, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + memset (data, *val, real_width); + data += stride; + } +} + +void +vs_fill_borders_Y16 (const VSImage * dest, const uint16_t val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + orc_splat_u16 ((uint16_t *) data, val, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 2; + for (i = 0; i < tmp; i++) { + orc_splat_u16 ((uint16_t *) data, val, left); + orc_splat_u16 ((uint16_t *) (data + tmp2), val, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + orc_splat_u16 ((uint16_t *) data, val, real_width); + data += stride; + } +} + +void +vs_fill_borders_RGB565 (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + uint16_t v = READ_UINT16 (val); + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + orc_splat_u16 ((uint16_t *) data, v, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 2; + for (i = 0; i < tmp; i++) { + orc_splat_u16 ((uint16_t *) data, v, left); + orc_splat_u16 ((uint16_t *) (data + tmp2), v, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + orc_splat_u16 ((uint16_t *) data, v, real_width); + data += stride; + } +} + +void +vs_fill_borders_RGB555 (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + uint16_t v = READ_UINT16 (val); + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + orc_splat_u16 ((uint16_t *) data, v, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 2; + for (i = 0; i < tmp; i++) { + orc_splat_u16 ((uint16_t *) data, v, left); + orc_splat_u16 ((uint16_t *) (data + tmp2), v, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + orc_splat_u16 ((uint16_t *) data, v, real_width); + data += stride; + } +} + +void +vs_fill_borders_AYUV64 (const VSImage * dest, const uint8_t * val) +{ + int i; + int top = dest->border_top, bottom = dest->border_bottom; + int left = dest->border_left, right = dest->border_right; + int width = dest->width; + int height = dest->height; + int real_width = dest->real_width; + int stride = dest->stride; + int tmp, tmp2; + uint8_t *data; + uint64_t v; + + v = (val[0] << 8) | (val[1] << 24) | (((guint64) val[2]) << 40) | (((guint64) + val[3]) << 56); + + data = dest->real_pixels; + for (i = 0; i < top; i++) { + orc_splat_u64 ((uint64_t *) data, v, real_width); + data += stride; + } + + if (left || right) { + tmp = height; + tmp2 = (left + width) * 8; + for (i = 0; i < tmp; i++) { + orc_splat_u64 ((uint64_t *) data, v, left); + orc_splat_u64 ((uint64_t *) (data + tmp2), v, right); + data += stride; + } + } else { + data += stride * height; + } + + for (i = 0; i < bottom; i++) { + orc_splat_u64 ((uint64_t *) data, v, real_width); + data += stride; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.h b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.h new file mode 100644 index 0000000..faf00db --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_fill_borders.h @@ -0,0 +1,44 @@ +/* + * Image Scaling Functions + * Copyright (c) 2010 Sebastian Dröge + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VS_FILL_BORDERS_H__ +#define __VS_FILL_BORDERS_H__ + +#include <_stdint.h> +#include "vs_image.h" + +void vs_fill_borders_RGBA (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_RGB (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_YUYV (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_UYVY (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_Y (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_Y16 (const VSImage *dest, const uint16_t val); +void vs_fill_borders_RGB565 (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_RGB555 (const VSImage *dest, const uint8_t *val); +void vs_fill_borders_AYUV64 (const VSImage *dest, const uint8_t *val); + +#endif /* __VS_FILL_BORDERS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.c b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.c new file mode 100644 index 0000000..c28b0d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.c @@ -0,0 +1,1155 @@ +/* + * Image Scaling Functions + * Copyright (c) 2005 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include "vs_scanline.h" +#include "vs_image.h" + +#include "gstvideoscaleorc.h" +#include + +#define ROUND_UP_2(x) (((x)+1)&~1) +#define ROUND_UP_4(x) (((x)+3)&~3) +#define ROUND_UP_8(x) (((x)+7)&~7) + +void +vs_image_scale_nearest_RGBA (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int prev_j; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + + acc = 0; + prev_j = -1; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + if (j == prev_j) { + memcpy (dest->pixels + i * dest->stride, + dest->pixels + (i - 1) * dest->stride, dest->width * 4); + } else { + gst_videoscale_orc_resample_nearest_u32 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, 0, x_increment, dest->width); + } + + prev_j = j; + acc += y_increment; + } +} + +void +vs_image_scale_linear_RGBA (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int y1; + int i; + int j; + int x; + int dest_size; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width * 4; + +#define LINE(x) ((tmpbuf) + (dest_size)*((x)&1)) + + acc = 0; + gst_videoscale_orc_resample_bilinear_u32 (LINE (0), src->pixels, + 0, x_increment, dest->width); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size); + } else { + if (j > y1) { + gst_videoscale_orc_resample_bilinear_u32 (LINE (j), + src->pixels + j * src->stride, 0, x_increment, dest->width); + y1++; + } + if (j >= y1) { + gst_videoscale_orc_resample_bilinear_u32 (LINE (j + 1), + src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width); + y1++; + } + orc_merge_linear_u8 (dest->pixels + i * dest->stride, + LINE (j), LINE (j + 1), (x >> 8), dest->width * 4); + } + + acc += y_increment; + } +} + + +void +vs_image_scale_nearest_RGB (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_RGB (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_RGB (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width * 3; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_RGB (tmp1, src->pixels, src->width, dest->width, + &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_RGB (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_RGB (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_RGB (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_RGB (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +/* YUYV */ + +void +vs_image_scale_nearest_YUYV (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_YUYV (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_YUYV (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = ROUND_UP_4 (dest->width * 2); + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_YUYV (tmp1, src->pixels, src->width, dest->width, + &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_YUYV (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_YUYV (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_YUYV (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_YUYV (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_YUYV (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +/* UYVY */ + +void +vs_image_scale_nearest_UYVY (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_UYVY (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_UYVY (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = ROUND_UP_4 (dest->width * 2); + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_UYVY (tmp1, src->pixels, src->width, dest->width, + &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_UYVY (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_UYVY (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_UYVY (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_UYVY (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_UYVY (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +/* greyscale */ + +void +vs_image_scale_nearest_Y (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + gst_videoscale_orc_resample_nearest_u8 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, 0, x_increment, dest->width); + acc += y_increment; + } +} + +void +vs_image_scale_linear_Y (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + y2 = -1; + gst_videoscale_orc_resample_bilinear_u8 (tmp1, src->pixels, + 0, x_increment, dest->width); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + gst_videoscale_orc_resample_bilinear_u8 (tmp1, + src->pixels + j * src->stride, 0, x_increment, dest->width); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + gst_videoscale_orc_resample_bilinear_u8 (tmp2, + src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width); + y2 = j + 1; + } + if ((x >> 8) == 0) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest->width); + } else { + orc_merge_linear_u8 (dest->pixels + i * dest->stride, + tmp1, tmp2, (x >> 8), dest->width); + } + } else if (j == y2) { + if (j + 1 != y1) { + gst_videoscale_orc_resample_bilinear_u8 (tmp1, + src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width); + y1 = j + 1; + } + if ((x >> 8) == 0) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest->width); + } else { + orc_merge_linear_u8 (dest->pixels + i * dest->stride, + tmp2, tmp1, (x >> 8), dest->width); + } + } else { + gst_videoscale_orc_resample_bilinear_u8 (tmp1, + src->pixels + j * src->stride, 0, x_increment, dest->width); + y1 = j; + gst_videoscale_orc_resample_bilinear_u8 (tmp2, + src->pixels + (j + 1) * src->stride, 0, x_increment, dest->width); + y2 = (j + 1); + if ((x >> 8) == 0) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest->width); + } else { + orc_merge_linear_u8 (dest->pixels + i * dest->stride, + tmp1, tmp2, (x >> 8), dest->width); + } + } + } + + acc += y_increment; + } +} + +void +vs_image_scale_nearest_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_Y16 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_Y16 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = 2 * dest->width; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels, src->width, dest->width, + &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_Y16 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_Y16 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +/* RGB565 */ + +void +vs_image_scale_nearest_RGB565 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_RGB565 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_RGB565 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width * 2; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_RGB565 (tmp1, src->pixels, src->width, + dest->width, &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_RGB565 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_RGB565 (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB565 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_RGB565 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_RGB565 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +/* RGB555 */ + +void +vs_image_scale_nearest_RGB555 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + acc = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + xacc = 0; + vs_scanline_resample_nearest_RGB555 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + + acc += y_increment; + } +} + +void +vs_image_scale_linear_RGB555 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + uint8_t *tmp1; + uint8_t *tmp2; + int y1; + int y2; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width * 2; + + tmp1 = tmpbuf; + tmp2 = tmpbuf + dest_size; + + acc = 0; + xacc = 0; + y2 = -1; + vs_scanline_resample_linear_RGB555 (tmp1, src->pixels, src->width, + dest->width, &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + if (j == y1) { + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } else if (j == y2) { + memcpy (dest->pixels + i * dest->stride, tmp2, dest_size); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + memcpy (dest->pixels + i * dest->stride, tmp1, dest_size); + } + } else { + if (j == y1) { + if (j + 1 != y2) { + xacc = 0; + vs_scanline_resample_linear_RGB555 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y2 = j + 1; + } + vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } else if (j == y2) { + if (j + 1 != y1) { + xacc = 0; + vs_scanline_resample_linear_RGB555 (tmp1, + src->pixels + (j + 1) * src->stride, src->width, dest->width, + &xacc, x_increment); + y1 = j + 1; + } + vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride, + tmp2, tmp1, dest->width, x); + } else { + xacc = 0; + vs_scanline_resample_linear_RGB555 (tmp1, src->pixels + j * src->stride, + src->width, dest->width, &xacc, x_increment); + y1 = j; + xacc = 0; + vs_scanline_resample_linear_RGB555 (tmp2, + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + y2 = (j + 1); + vs_scanline_merge_linear_RGB555 (dest->pixels + i * dest->stride, + tmp1, tmp2, dest->width, x); + } + } + + acc += y_increment; + } +} + +void +vs_image_scale_nearest_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf8) +{ + int acc; + int y_increment; + int x_increment; + int i; + int j; + int prev_j; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1); + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1); + + + acc = 0; + prev_j = -1; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + + if (j == prev_j) { + memcpy (dest->pixels + i * dest->stride, + dest->pixels + (i - 1) * dest->stride, dest->width * 8); + } else { + int xacc = 0; + vs_scanline_resample_nearest_AYUV64 (dest->pixels + i * dest->stride, + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + } + + prev_j = j; + acc += y_increment; + } +} + +void +vs_image_scale_linear_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf) +{ + int acc; + int y_increment; + int x_increment; + int y1; + int i; + int j; + int x; + int dest_size; + int xacc; + + if (dest->height == 1) + y_increment = 0; + else + y_increment = ((src->height - 1) << 16) / (dest->height - 1) - 1; + + if (dest->width == 1) + x_increment = 0; + else + x_increment = ((src->width - 1) << 16) / (dest->width - 1) - 1; + + dest_size = dest->width * 8; + +#undef LINE +#define LINE(x) ((guint16 *)((tmpbuf) + (dest_size)*((x)&1))) + + acc = 0; + //gst_videoscale_orc_resample_bilinear_u64 (LINE (0), src->pixels, + // 0, x_increment, dest->width); + xacc = 0; + vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (0), + src->pixels, src->width, dest->width, &xacc, x_increment); + y1 = 0; + for (i = 0; i < dest->height; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (x == 0) { + memcpy (dest->pixels + i * dest->stride, LINE (j), dest_size); + } else { + if (j > y1) { + xacc = 0; + vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j), + src->pixels + j * src->stride, src->width, dest->width, &xacc, + x_increment); + //gst_videoscale_orc_resample_bilinear_u64 (LINE (j), + // src->pixels + j * src->stride, 0, x_increment, dest->width); + y1++; + } + if (j >= y1) { + xacc = 0; + vs_scanline_resample_linear_AYUV64 ((guint8 *) LINE (j + 1), + src->pixels + (j + 1) * src->stride, src->width, dest->width, &xacc, + x_increment); + orc_merge_linear_u16 ((guint16 *) (dest->pixels + i * dest->stride), + LINE (j), LINE (j + 1), 65536 - x, x, dest->width * 4); + //gst_videoscale_orc_resample_merge_bilinear_u64 (dest->pixels + + // i * dest->stride, LINE (j + 1), LINE (j), + // src->pixels + (j + 1) * src->stride, (x >> 8), 0, x_increment, + // dest->width); + y1++; + } else { + orc_merge_linear_u16 ((guint16 *) (dest->pixels + i * dest->stride), + LINE (j), LINE (j + 1), 65536 - x, x, dest->width * 4); + } + } + + acc += y_increment; + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.h b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.h new file mode 100644 index 0000000..3a23dd4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_image.h @@ -0,0 +1,98 @@ +/* + * Image Scaling Functions + * Copyright (c) 2005 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VS_IMAGE_H__ +#define __VS_IMAGE_H__ + +#include <_stdint.h> + +typedef struct _VSImage VSImage; + +struct _VSImage { + uint8_t *real_pixels; + int real_width; + int real_height; + int border_left, border_right; + int border_top, border_bottom; + uint8_t *pixels; + int width; + int height; + int stride; +}; + +void vs_image_scale_nearest_RGBA (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_RGBA (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_RGB (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_RGB (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_YUYV (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_YUYV (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_UYVY (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_UYVY (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_Y (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_Y (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_RGB565 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_RGB565 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_RGB555 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_RGB555 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_Y16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_Y16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_AYUV16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); +void vs_image_scale_linear_AYUV16 (const VSImage *dest, const VSImage *src, + uint8_t *tmpbuf); + +void vs_image_scale_nearest_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf8); +void vs_image_scale_linear_AYUV64 (const VSImage * dest, const VSImage * src, + uint8_t * tmpbuf8); + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.c b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.c new file mode 100644 index 0000000..822a6b6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.c @@ -0,0 +1,781 @@ +/* + * Image Scaling Functions + * Copyright (c) 2005 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "vs_scanline.h" + +#include "gstvideoscaleorc.h" +#include + +#include + +/* greyscale, i.e., single componenet */ + +void +vs_scanline_downsample_Y (uint8_t * dest, uint8_t * src, int n) +{ + orc_downsample_u8 (dest, src, n); +} + +void +vs_scanline_resample_nearest_Y (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + gst_videoscale_orc_resample_nearest_u8 (dest, src, + *accumulator, increment, n); + + *accumulator += n * increment; +} + +#include +void +vs_scanline_resample_linear_Y (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + gst_videoscale_orc_resample_bilinear_u8 (dest, src, + *accumulator, increment, n); + + *accumulator += n * increment; +} + +void +vs_scanline_merge_linear_Y (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + uint32_t value = x >> 8; + + if (value == 0) { + memcpy (dest, src1, n); + } else { + orc_merge_linear_u8 (dest, src1, src2, value, n); + } +} + +void +vs_scanline_downsample_Y16 (uint8_t * dest, uint8_t * src, int n) +{ + orc_downsample_u16 ((uint16_t *) dest, (uint16_t *) src, n); +} + +void +vs_scanline_resample_nearest_Y16 (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + d[i] = (x < 32768 || j + 1 >= src_width) ? s[j] : s[j + 1]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_Y16 (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + uint16_t *d = (uint16_t *) dest, *s = (uint16_t *) src; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) + d[i] = (s[j] * (65536 - x) + s[j + 1] * x) >> 16; + else + d[i] = s[j]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_Y16 (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + uint16_t *d = (uint16_t *) dest; + const uint16_t *s1 = (const uint16_t *) src1; + const uint16_t *s2 = (const uint16_t *) src2; + + if (x == 0) { + memcpy (d, s1, n * 2); + } else { + orc_merge_linear_u16 (d, s1, s2, 65536 - x, x, n); + } +} + +/* RGBA */ + +void +vs_scanline_downsample_RGBA (uint8_t * dest, uint8_t * src, int n) +{ + gst_videoscale_orc_downsample_u32 (dest, src, n); +} + +void +vs_scanline_resample_nearest_RGBA (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + gst_videoscale_orc_resample_nearest_u32 (dest, src, + *accumulator, increment, n); + + *accumulator += n * increment; +} + +void +vs_scanline_resample_linear_RGBA (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + gst_videoscale_orc_resample_bilinear_u32 (dest, src, + *accumulator, increment, n); + + *accumulator += n * increment; +} + +void +vs_scanline_merge_linear_RGBA (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + uint32_t value = x >> 8; + + if (value == 0) { + memcpy (dest, src1, n * 4); + } else { + orc_merge_linear_u8 (dest, src1, src2, value, n * 4); + } +} + + +/* RGB */ + +void +vs_scanline_downsample_RGB (uint8_t * dest, uint8_t * src, int n) +{ + int i; + + for (i = 0; i < n; i++) { + dest[i * 3 + 0] = (src[i * 6 + 0] + src[i * 6 + 3]) / 2; + dest[i * 3 + 1] = (src[i * 6 + 1] + src[i * 6 + 4]) / 2; + dest[i * 3 + 2] = (src[i * 6 + 2] + src[i * 6 + 5]) / 2; + } +} + +void +vs_scanline_resample_nearest_RGB (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + dest[i * 3 + 0] = (x < 32768 + || j + 1 >= src_width) ? src[j * 3 + 0] : src[j * 3 + 3]; + dest[i * 3 + 1] = (x < 32768 + || j + 1 >= src_width) ? src[j * 3 + 1] : src[j * 3 + 4]; + dest[i * 3 + 2] = (x < 32768 + || j + 1 >= src_width) ? src[j * 3 + 2] : src[j * 3 + 5]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_RGB (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) { + dest[i * 3 + 0] = + (src[j * 3 + 0] * (65536 - x) + src[j * 3 + 3] * x) >> 16; + dest[i * 3 + 1] = + (src[j * 3 + 1] * (65536 - x) + src[j * 3 + 4] * x) >> 16; + dest[i * 3 + 2] = + (src[j * 3 + 2] * (65536 - x) + src[j * 3 + 5] * x) >> 16; + } else { + dest[i * 3 + 0] = src[j * 3 + 0]; + dest[i * 3 + 1] = src[j * 3 + 1]; + dest[i * 3 + 2] = src[j * 3 + 2]; + } + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_RGB (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + uint32_t value = x >> 8; + + if (value == 0) { + memcpy (dest, src1, n * 3); + } else { + orc_merge_linear_u8 (dest, src1, src2, value, n * 3); + } +} + + +/* YUYV */ + +/* n is the number of pixels */ +/* increment is per Y pixel */ + +void +vs_scanline_downsample_YUYV (uint8_t * dest, uint8_t * src, int n) +{ + gst_videoscale_orc_downsample_yuyv (dest, src, n); +} + +void +vs_scanline_resample_nearest_YUYV (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + int quads = (n + 1) / 2; + + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = acc & 0xffff; + dest[i * 4 + 0] = (x < 32768 + || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2]; + + j = acc >> 17; + x = acc & 0x1ffff; + dest[i * 4 + 1] = (x < 65536 + || 2 * j + 2 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5]; + + if (2 * i + 1 < n && 2 * j + 1 < src_width) + dest[i * 4 + 3] = (x < 65536 + || 2 * j + 3 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7]; + + acc += increment; + + j = acc >> 16; + x = acc & 0xffff; + + if (2 * i + 1 < n && j < src_width) { + dest[i * 4 + 2] = (x < 32768 + || j + 1 >= src_width) ? src[j * 2 + 0] : src[j * 2 + 2]; + acc += increment; + } + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_YUYV (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + int quads = (n + 1) / 2; + + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) + dest[i * 4 + 0] = + (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16; + else + dest[i * 4 + 0] = src[j * 2 + 0]; + + j = acc >> 17; + x = acc & 0x1ffff; + + if (2 * j + 2 < src_width) + dest[i * 4 + 1] = + (src[j * 4 + 1] * (131072 - x) + src[j * 4 + 5] * x) >> 17; + else + dest[i * 4 + 1] = src[j * 4 + 1]; + + if (2 * i + 1 < n && 2 * j + 1 < src_width) { + if (2 * j + 3 < src_width) + dest[i * 4 + 3] = + (src[j * 4 + 3] * (131072 - x) + src[j * 4 + 7] * x) >> 17; + else + dest[i * 4 + 3] = src[j * 4 + 3]; + } + + acc += increment; + + j = acc >> 16; + x = acc & 0xffff; + + if (2 * i + 1 < n && j < src_width) { + if (j + 1 < src_width) + dest[i * 4 + 2] = + (src[j * 2 + 0] * (65536 - x) + src[j * 2 + 2] * x) >> 16; + else + dest[i * 4 + 2] = src[j * 2 + 0]; + acc += increment; + } + } + + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_YUYV (uint8_t * dest, uint8_t * src1, uint8_t * src2, + int n, int x) +{ + int quads = (n + 1) / 2; + uint32_t value = x >> 8; + + if (value == 0) { + memcpy (dest, src1, quads * 4); + } else { + orc_merge_linear_u8 (dest, src1, src2, value, quads * 4); + } +} + + +/* UYVY */ + +/* n is the number of bi-pixels */ +/* increment is per Y pixel */ + +void +vs_scanline_downsample_UYVY (uint8_t * dest, uint8_t * src, int n) +{ + int i; + + for (i = 0; i < n; i++) { + dest[i * 4 + 0] = (src[i * 8 + 0] + src[i * 8 + 4]) / 2; + dest[i * 4 + 1] = (src[i * 8 + 1] + src[i * 8 + 3]) / 2; + dest[i * 4 + 2] = (src[i * 8 + 2] + src[i * 8 + 6]) / 2; + dest[i * 4 + 3] = (src[i * 8 + 5] + src[i * 8 + 7]) / 2; + } +} + +void +vs_scanline_resample_nearest_UYVY (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + int quads = (n + 1) / 2; + + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = acc & 0xffff; + + dest[i * 4 + 1] = (x < 32768 + || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3]; + + j = acc >> 17; + x = acc & 0x1ffff; + + dest[i * 4 + 0] = (x < 65536 + || 2 * j + 2 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4]; + + if (2 * i + 1 < n && 2 * j + 1 < src_width) + dest[i * 4 + 2] = (x < 65536 + || 2 * j + 3 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6]; + + acc += increment; + + j = acc >> 16; + x = acc & 0xffff; + + if (2 * i + 1 < n && j < src_width) { + dest[i * 4 + 3] = (x < 32768 + || j + 1 >= src_width) ? src[j * 2 + 1] : src[j * 2 + 3]; + acc += increment; + } + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_UYVY (uint8_t * dest, uint8_t * src, int src_width, + int n, int *accumulator, int increment) +{ + int acc = *accumulator; + int i; + int j; + int x; + int quads = (n + 1) / 2; + + for (i = 0; i < quads; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) + dest[i * 4 + 1] = + (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16; + else + dest[i * 4 + 1] = src[j * 2 + 1]; + + j = acc >> 17; + x = acc & 0x1ffff; + if (2 * j + 2 < src_width) + dest[i * 4 + 0] = + (src[j * 4 + 0] * (131072 - x) + src[j * 4 + 4] * x) >> 17; + else + dest[i * 4 + 0] = src[j * 4 + 0]; + + if (i * 2 + 1 < n && 2 * j + 1 < src_width) { + if (2 * j + 3 < src_width) + dest[i * 4 + 2] = + (src[j * 4 + 2] * (131072 - x) + src[j * 4 + 6] * x) >> 17; + else + dest[i * 4 + 2] = src[j * 4 + 2]; + } + + acc += increment; + + j = acc >> 16; + x = acc & 0xffff; + + if (2 * i + 1 < n && j < src_width) { + if (j + 1 < src_width) + dest[i * 4 + 3] = + (src[j * 2 + 1] * (65536 - x) + src[j * 2 + 3] * x) >> 16; + else + dest[i * 4 + 3] = src[j * 2 + 1]; + acc += increment; + } + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_UYVY (uint8_t * dest, uint8_t * src1, + uint8_t * src2, int n, int x) +{ + int quads = (n + 1) / 2; + uint32_t value = x >> 8; + + if (value == 0) { + memcpy (dest, src1, quads * 4); + } else { + orc_merge_linear_u8 (dest, src1, src2, value, quads * 4); + } +} + + +/* RGB565 */ + +/* note that src and dest are uint16_t, and thus endian dependent */ + +#define RGB565_R(x) (((x)&0xf800)>>8 | ((x)&0xf800)>>13) +#define RGB565_G(x) (((x)&0x07e0)>>3 | ((x)&0x07e0)>>9) +#define RGB565_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2) + +#define RGB565(r,g,b) \ + ((((r)<<8)&0xf800) | (((g)<<3)&0x07e0) | (((b)>>3)&0x001f)) + + +void +vs_scanline_downsample_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, int n) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int i; + + for (i = 0; i < n; i++) { + dest[i] = RGB565 ( + (RGB565_R (src[i * 2]) + RGB565_R (src[i * 2 + 1])) / 2, + (RGB565_G (src[i * 2]) + RGB565_G (src[i * 2 + 1])) / 2, + (RGB565_B (src[i * 2]) + RGB565_B (src[i * 2 + 1])) / 2); + } +} + +void +vs_scanline_resample_nearest_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, + int src_width, int n, int *accumulator, int increment) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_RGB565 (uint8_t * dest_u8, uint8_t * src_u8, + int src_width, int n, int *accumulator, int increment) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) { + dest[i] = RGB565 ( + (RGB565_R (src[j]) * (65536 - x) + RGB565_R (src[j + 1]) * x) >> 16, + (RGB565_G (src[j]) * (65536 - x) + RGB565_G (src[j + 1]) * x) >> 16, + (RGB565_B (src[j]) * (65536 - x) + RGB565_B (src[j + 1]) * x) >> 16); + } else { + dest[i] = RGB565 (RGB565_R (src[j]), + RGB565_G (src[j]), RGB565_B (src[j])); + } + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_RGB565 (uint8_t * dest_u8, uint8_t * src1_u8, + uint8_t * src2_u8, int n, int x) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src1 = (uint16_t *) src1_u8; + uint16_t *src2 = (uint16_t *) src2_u8; + int i; + + for (i = 0; i < n; i++) { + dest[i] = RGB565 ( + (RGB565_R (src1[i]) * (65536 - x) + RGB565_R (src2[i]) * x) >> 16, + (RGB565_G (src1[i]) * (65536 - x) + RGB565_G (src2[i]) * x) >> 16, + (RGB565_B (src1[i]) * (65536 - x) + RGB565_B (src2[i]) * x) >> 16); + } +} + + +/* RGB555 */ + +/* note that src and dest are uint16_t, and thus endian dependent */ + +#define RGB555_R(x) (((x)&0x7c00)>>8 | ((x)&0x7c00)>>13) +#define RGB555_G(x) (((x)&0x03e0)>>3 | ((x)&0x03e0)>>9) +#define RGB555_B(x) (((x)&0x001f)<<3 | ((x)&0x001f)>>2) + +#define RGB555(r,g,b) \ + ((((r)<<7)&0x7c00) | (((g)<<3)&0x03e0) | (((b)>>3)&0x001f)) + + +void +vs_scanline_downsample_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, int n) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int i; + + for (i = 0; i < n; i++) { + dest[i] = RGB555 ( + (RGB555_R (src[i * 2]) + RGB555_R (src[i * 2 + 1])) / 2, + (RGB555_G (src[i * 2]) + RGB555_G (src[i * 2 + 1])) / 2, + (RGB555_B (src[i * 2]) + RGB555_B (src[i * 2 + 1])) / 2); + } +} + +void +vs_scanline_resample_nearest_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, + int src_width, int n, int *accumulator, int increment) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + dest[i] = (x < 32768 || j + 1 >= src_width) ? src[j] : src[j + 1]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_RGB555 (uint8_t * dest_u8, uint8_t * src_u8, + int src_width, int n, int *accumulator, int increment) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src = (uint16_t *) src_u8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + + if (j + 1 < src_width) { + dest[i] = RGB555 ( + (RGB555_R (src[j]) * (65536 - x) + RGB555_R (src[j + 1]) * x) >> 16, + (RGB555_G (src[j]) * (65536 - x) + RGB555_G (src[j + 1]) * x) >> 16, + (RGB555_B (src[j]) * (65536 - x) + RGB555_B (src[j + 1]) * x) >> 16); + } else { + dest[i] = RGB555 (RGB555_R (src[j]), + RGB555_G (src[j]), RGB555_B (src[j])); + } + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_merge_linear_RGB555 (uint8_t * dest_u8, uint8_t * src1_u8, + uint8_t * src2_u8, int n, int x) +{ + uint16_t *dest = (uint16_t *) dest_u8; + uint16_t *src1 = (uint16_t *) src1_u8; + uint16_t *src2 = (uint16_t *) src2_u8; + int i; + + for (i = 0; i < n; i++) { + dest[i] = RGB555 ( + (RGB555_R (src1[i]) * (65536 - x) + RGB555_R (src2[i]) * x) >> 16, + (RGB555_G (src1[i]) * (65536 - x) + RGB555_G (src2[i]) * x) >> 16, + (RGB555_B (src1[i]) * (65536 - x) + RGB555_B (src2[i]) * x) >> 16); + } +} + +void +vs_scanline_resample_nearest_AYUV64 (uint8_t * dest8, uint8_t * src8, + int src_width, int n, int *accumulator, int increment) +{ + guint16 *dest = (guint16 *) dest8; + guint16 *src = (guint16 *) src8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = acc & 0xffff; + dest[i * 4 + 0] = (x < 32768 + || j + 1 >= src_width) ? src[j * 4 + 0] : src[j * 4 + 4]; + dest[i * 4 + 1] = (x < 32768 + || j + 1 >= src_width) ? src[j * 4 + 1] : src[j * 4 + 5]; + dest[i * 4 + 2] = (x < 32768 + || j + 1 >= src_width) ? src[j * 4 + 2] : src[j * 4 + 6]; + dest[i * 4 + 3] = (x < 32768 + || j + 1 >= src_width) ? src[j * 4 + 3] : src[j * 4 + 7]; + + acc += increment; + } + + *accumulator = acc; +} + +void +vs_scanline_resample_linear_AYUV64 (uint8_t * dest8, uint8_t * src8, + int src_width, int n, int *accumulator, int increment) +{ + guint16 *dest = (guint16 *) dest8; + guint16 *src = (guint16 *) src8; + int acc = *accumulator; + int i; + int j; + int x; + + for (i = 0; i < n; i++) { + j = acc >> 16; + x = (acc & 0xffff) >> 1; + + if (j + 1 < src_width) { + dest[i * 4 + 0] = + (src[j * 3 + 0] * (32768 - x) + src[j * 4 + 4] * x) >> 15; + dest[i * 4 + 1] = + (src[j * 4 + 1] * (32768 - x) + src[j * 4 + 5] * x) >> 15; + dest[i * 4 + 2] = + (src[j * 4 + 2] * (32768 - x) + src[j * 4 + 6] * x) >> 15; + dest[i * 4 + 3] = + (src[j * 4 + 3] * (32768 - x) + src[j * 4 + 7] * x) >> 15; + } else { + dest[i * 4 + 0] = src[j * 4 + 0]; + dest[i * 4 + 1] = src[j * 4 + 1]; + dest[i * 4 + 2] = src[j * 4 + 2]; + dest[i * 4 + 3] = src[j * 4 + 3]; + } + + acc += increment; + } + + *accumulator = acc; +} diff --git a/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.h b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.h new file mode 100644 index 0000000..387fc95 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videoscale/vs_scanline.h @@ -0,0 +1,79 @@ +/* + * Image Scaling Functions + * Copyright (c) 2005 David A. Schleef + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __VS_SCANLINE_H__ +#define __VS_SCANLINE_H__ + +#include <_stdint.h> + +void vs_scanline_downsample_Y (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_Y (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_resample_linear_Y (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_merge_linear_Y (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_RGBA (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_RGBA (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_RGBA (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_RGBA (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_RGB (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_RGB (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_RGB (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_RGB (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_YUYV (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_YUYV (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_YUYV (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_YUYV (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_UYVY (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_UYVY (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_UYVY (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_RGB565 (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_RGB565 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_RGB565 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_RGB555 (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_RGB555 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_RGB555 (uint8_t *dest, uint8_t *src, int src_width, int n, int *accumulator, int increment); +void vs_scanline_merge_linear_RGB555 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_downsample_Y16 (uint8_t *dest, uint8_t *src, int n); +void vs_scanline_resample_nearest_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_resample_linear_Y16 (uint8_t *dest, uint8_t *src, int n, int src_width, int *accumulator, int increment); +void vs_scanline_merge_linear_Y16 (uint8_t *dest, uint8_t *src1, uint8_t *src2, int n, int x); + +void vs_scanline_resample_nearest_AYUV64 (uint8_t * dest, uint8_t * src, + int src_width, int n, int *accumulator, int increment); +void vs_scanline_resample_linear_AYUV64 (uint8_t * dest, uint8_t * src, + int src_width, int n, int *accumulator, int increment); + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/.gitignore b/gst-plugins-base-subtitles0.10/gst/videotestsrc/.gitignore new file mode 100644 index 0000000..24c1bf2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/.gitignore @@ -0,0 +1 @@ +generate_sine_table diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/Makefile.am b/gst-plugins-base-subtitles0.10/gst/videotestsrc/Makefile.am new file mode 100644 index 0000000..814899f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/Makefile.am @@ -0,0 +1,37 @@ +plugin_LTLIBRARIES = libgstvideotestsrc.la + +ORC_SOURCE=gstvideotestsrcorc +include $(top_srcdir)/common/orc.mak + +libgstvideotestsrc_la_SOURCES = \ + gstvideotestsrc.c \ + videotestsrc.c +nodist_libgstvideotestsrc_la_SOURCES = $(ORC_NODIST_SOURCES) + +libgstvideotestsrc_la_CFLAGS = $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS) +libgstvideotestsrc_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideotestsrc_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) $(ORC_LIBS) $(LIBM) +libgstvideotestsrc_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstvideotestsrc.h videotestsrc.h + +noinst_PROGRAMS = generate_sine_table + +generate_sine_table_SOURCES = generate_sine_table.c +generate_sine_table_CFLAGS = $(GST_CFLAGS) +generate_sine_table_LDADD = $(LIBM) + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstvideotestsrc -:SHARED libgstvideotestsrc \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstvideotestsrc_la_SOURCES) \ + $(nodist_libgstvideotestsrc_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvideotestsrc_la_CFLAGS) \ + -:LDFLAGS $(libgstvideotestsrc_la_LDFLAGS) \ + $(libgstvideotestsrc_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/generate_sine_table.c b/gst-plugins-base-subtitles0.10/gst/videotestsrc/generate_sine_table.c new file mode 100644 index 0000000..432e1a5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/generate_sine_table.c @@ -0,0 +1,43 @@ + +#include +#include + + +static int +get_value (int i) +{ + int x; + + x = floor (256 * (0.5 + 0.5 * sin (i * 2 * M_PI / 256))); + if (x > 255) + x = 255; + return x; +} + +int +main (int argc, char *argv[]) +{ + int i; + int j; + + printf ("static const guint8\n"); + printf ("sine_table[256] = {\n"); + for (i = 0; i < 256; i += 8) { + printf (" "); + for (j = 0; j < 8; j++) { + printf ("%3d", get_value (i + j)); + if (j != 7) { + printf (", "); + } else { + if (i + j != 255) { + printf (",\n"); + } else { + printf ("\n"); + } + } + } + } + printf ("};\n"); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.c b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.c new file mode 100644 index 0000000..227e0a9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.c @@ -0,0 +1,955 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2002> David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-videotestsrc + * + * The videotestsrc element is used to produce test video data in a wide variaty + * of formats. The video test data produced can be controlled with the "pattern" + * property. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc pattern=snow ! ximagesink + * ]| Shows random noise in an X window. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "gstvideotestsrc.h" +#include "gstvideotestsrcorc.h" +#include "videotestsrc.h" + +#include +#include + +GST_DEBUG_CATEGORY_STATIC (video_test_src_debug); +#define GST_CAT_DEFAULT video_test_src_debug + +#define DEFAULT_PATTERN GST_VIDEO_TEST_SRC_SMPTE +#define DEFAULT_TIMESTAMP_OFFSET 0 +#define DEFAULT_IS_LIVE FALSE +#define DEFAULT_PEER_ALLOC TRUE +#define DEFAULT_COLOR_SPEC GST_VIDEO_TEST_SRC_BT601 +#define DEFAULT_FOREGROUND_COLOR 0xffffffff +#define DEFAULT_BACKGROUND_COLOR 0xff000000 +#define DEFAULT_HORIZONTAL_SPEED 0 + +enum +{ + PROP_0, + PROP_PATTERN, + PROP_TIMESTAMP_OFFSET, + PROP_IS_LIVE, + PROP_PEER_ALLOC, + PROP_COLOR_SPEC, + PROP_K0, + PROP_KX, + PROP_KY, + PROP_KT, + PROP_KXT, + PROP_KYT, + PROP_KXY, + PROP_KX2, + PROP_KY2, + PROP_KT2, + PROP_XOFFSET, + PROP_YOFFSET, + PROP_FOREGROUND_COLOR, + PROP_BACKGROUND_COLOR, + PROP_HORIZONTAL_SPEED, + PROP_LAST +}; + + +GST_BOILERPLATE (GstVideoTestSrc, gst_video_test_src, GstPushSrc, + GST_TYPE_PUSH_SRC); + + +static void gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc, + int pattern_type); +static void gst_video_test_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_video_test_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstCaps *gst_video_test_src_getcaps (GstBaseSrc * bsrc); +static gboolean gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps); +static void gst_video_test_src_src_fixate (GstPad * pad, GstCaps * caps); + +static gboolean gst_video_test_src_is_seekable (GstBaseSrc * psrc); +static gboolean gst_video_test_src_do_seek (GstBaseSrc * bsrc, + GstSegment * segment); +static gboolean gst_video_test_src_query (GstBaseSrc * bsrc, GstQuery * query); + +static void gst_video_test_src_get_times (GstBaseSrc * basesrc, + GstBuffer * buffer, GstClockTime * start, GstClockTime * end); +static GstFlowReturn gst_video_test_src_create (GstPushSrc * psrc, + GstBuffer ** buffer); +static gboolean gst_video_test_src_start (GstBaseSrc * basesrc); + +#define GST_TYPE_VIDEO_TEST_SRC_PATTERN (gst_video_test_src_pattern_get_type ()) +static GType +gst_video_test_src_pattern_get_type (void) +{ + static GType video_test_src_pattern_type = 0; + static const GEnumValue pattern_types[] = { + {GST_VIDEO_TEST_SRC_SMPTE, "SMPTE 100% color bars", "smpte"}, + {GST_VIDEO_TEST_SRC_SNOW, "Random (television snow)", "snow"}, + {GST_VIDEO_TEST_SRC_BLACK, "100% Black", "black"}, + {GST_VIDEO_TEST_SRC_WHITE, "100% White", "white"}, + {GST_VIDEO_TEST_SRC_RED, "Red", "red"}, + {GST_VIDEO_TEST_SRC_GREEN, "Green", "green"}, + {GST_VIDEO_TEST_SRC_BLUE, "Blue", "blue"}, + {GST_VIDEO_TEST_SRC_CHECKERS1, "Checkers 1px", "checkers-1"}, + {GST_VIDEO_TEST_SRC_CHECKERS2, "Checkers 2px", "checkers-2"}, + {GST_VIDEO_TEST_SRC_CHECKERS4, "Checkers 4px", "checkers-4"}, + {GST_VIDEO_TEST_SRC_CHECKERS8, "Checkers 8px", "checkers-8"}, + {GST_VIDEO_TEST_SRC_CIRCULAR, "Circular", "circular"}, + {GST_VIDEO_TEST_SRC_BLINK, "Blink", "blink"}, + {GST_VIDEO_TEST_SRC_SMPTE75, "SMPTE 75% color bars", "smpte75"}, + {GST_VIDEO_TEST_SRC_ZONE_PLATE, "Zone plate", "zone-plate"}, + {GST_VIDEO_TEST_SRC_GAMUT, "Gamut checkers", "gamut"}, + {GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE, "Chroma zone plate", + "chroma-zone-plate"}, + {GST_VIDEO_TEST_SRC_SOLID, "Solid color", "solid-color"}, + {GST_VIDEO_TEST_SRC_BALL, "Moving ball", "ball"}, + {GST_VIDEO_TEST_SRC_SMPTE100, "SMPTE 100% color bars", "smpte100"}, + {GST_VIDEO_TEST_SRC_BAR, "Bar", "bar"}, + {0, NULL, NULL} + }; + + if (!video_test_src_pattern_type) { + video_test_src_pattern_type = + g_enum_register_static ("GstVideoTestSrcPattern", pattern_types); + } + return video_test_src_pattern_type; +} + +#define GST_TYPE_VIDEO_TEST_SRC_COLOR_SPEC (gst_video_test_src_color_spec_get_type ()) +static GType +gst_video_test_src_color_spec_get_type (void) +{ + static GType video_test_src_color_spec_type = 0; + static const GEnumValue color_spec_types[] = { + {GST_VIDEO_TEST_SRC_BT601, "ITU-R Rec. BT.601", "bt601"}, + {GST_VIDEO_TEST_SRC_BT709, "ITU-R Rec. BT.709", "bt709"}, + {0, NULL, NULL} + }; + + if (!video_test_src_color_spec_type) { + video_test_src_color_spec_type = + g_enum_register_static ("GstVideoTestSrcColorSpec", color_spec_types); + } + return video_test_src_color_spec_type; +} + +static void +gst_video_test_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Video test source", "Source/Video", + "Creates a test video stream", "David A. Schleef "); + + gst_element_class_add_pad_template (element_class, + gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, + gst_video_test_src_getcaps (NULL))); +} + +static void +gst_video_test_src_class_init (GstVideoTestSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *gstbasesrc_class; + GstPushSrcClass *gstpushsrc_class; + + gobject_class = (GObjectClass *) klass; + gstbasesrc_class = (GstBaseSrcClass *) klass; + gstpushsrc_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_video_test_src_set_property; + gobject_class->get_property = gst_video_test_src_get_property; + + g_object_class_install_property (gobject_class, PROP_PATTERN, + g_param_spec_enum ("pattern", "Pattern", + "Type of test pattern to generate", GST_TYPE_VIDEO_TEST_SRC_PATTERN, + DEFAULT_PATTERN, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_TIMESTAMP_OFFSET, + g_param_spec_int64 ("timestamp-offset", "Timestamp offset", + "An offset added to timestamps set on buffers (in ns)", G_MININT64, + G_MAXINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_IS_LIVE, + g_param_spec_boolean ("is-live", "Is Live", + "Whether to act as a live source", DEFAULT_IS_LIVE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PEER_ALLOC, + g_param_spec_boolean ("peer-alloc", "Peer Alloc", + "Ask the peer to allocate an output buffer", DEFAULT_PEER_ALLOC, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_COLOR_SPEC, + g_param_spec_enum ("colorspec", "Color Specification", + "Generate video in the given color specification (Deprecated: " + "use a caps filter with video/x-raw-yuv,color-matrix=\"sdtv\" or " + "\"hdtv\" instead)", + GST_TYPE_VIDEO_TEST_SRC_COLOR_SPEC, + DEFAULT_COLOR_SPEC, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_K0, + g_param_spec_int ("k0", "Zoneplate zero order phase", + "Zoneplate zero order phase, for generating plain fields or phase offsets", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KX, + g_param_spec_int ("kx", "Zoneplate 1st order x phase", + "Zoneplate 1st order x phase, for generating constant horizontal frequencies", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KY, + g_param_spec_int ("ky", "Zoneplate 1st order y phase", + "Zoneplate 1st order y phase, for generating contant vertical frequencies", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KT, + g_param_spec_int ("kt", "Zoneplate 1st order t phase", + "Zoneplate 1st order t phase, for generating phase rotation as a function of time", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KXT, + g_param_spec_int ("kxt", "Zoneplate x*t product phase", + "Zoneplate x*t product phase, normalised to kxy/256 cycles per vertical pixel at width/2 from origin", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KYT, + g_param_spec_int ("kyt", "Zoneplate y*t product phase", + "Zoneplate y*t product phase", G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KXY, + g_param_spec_int ("kxy", "Zoneplate x*y product phase", + "Zoneplate x*y product phase", G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KX2, + g_param_spec_int ("kx2", "Zoneplate 2nd order x phase", + "Zoneplate 2nd order x phase, normalised to kx2/256 cycles per horizontal pixel at width/2 from origin", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KY2, + g_param_spec_int ("ky2", "Zoneplate 2nd order y phase", + "Zoneplate 2nd order y phase, normailsed to ky2/256 cycles per vertical pixel at height/2 from origin", + G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_KT2, + g_param_spec_int ("kt2", "Zoneplate 2nd order t phase", + "Zoneplate 2nd order t phase, t*t/256 cycles per picture", G_MININT32, + G_MAXINT32, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_XOFFSET, + g_param_spec_int ("xoffset", "Zoneplate 2nd order products x offset", + "Zoneplate 2nd order products x offset", G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_YOFFSET, + g_param_spec_int ("yoffset", "Zoneplate 2nd order products y offset", + "Zoneplate 2nd order products y offset", G_MININT32, G_MAXINT32, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVideoTestSrc:foreground-color + * + * Color to use for solid-color pattern and foreground color of other + * patterns. Default is white (0xffffffff). + * + * Since: 0.10.31 + **/ + g_object_class_install_property (gobject_class, PROP_FOREGROUND_COLOR, + g_param_spec_uint ("foreground-color", "Foreground Color", + "Foreground color to use (big-endian ARGB)", 0, G_MAXUINT32, + DEFAULT_FOREGROUND_COLOR, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstVideoTestSrc:background-color + * + * Color to use for background color of some patterns. Default is + * black (0xff000000). + * + * Since: 0.10.31 + **/ + g_object_class_install_property (gobject_class, PROP_BACKGROUND_COLOR, + g_param_spec_uint ("background-color", "Background Color", + "Background color to use (big-endian ARGB)", 0, G_MAXUINT32, + DEFAULT_BACKGROUND_COLOR, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_HORIZONTAL_SPEED, + g_param_spec_int ("horizontal-speed", "Horizontal Speed", + "Scroll image number of pixels per frame (positive is scroll to the left)", + G_MININT32, G_MAXINT32, DEFAULT_HORIZONTAL_SPEED, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstbasesrc_class->get_caps = gst_video_test_src_getcaps; + gstbasesrc_class->set_caps = gst_video_test_src_setcaps; + gstbasesrc_class->is_seekable = gst_video_test_src_is_seekable; + gstbasesrc_class->do_seek = gst_video_test_src_do_seek; + gstbasesrc_class->query = gst_video_test_src_query; + gstbasesrc_class->get_times = gst_video_test_src_get_times; + gstbasesrc_class->start = gst_video_test_src_start; + + gstpushsrc_class->create = gst_video_test_src_create; +} + +static void +gst_video_test_src_init (GstVideoTestSrc * src, GstVideoTestSrcClass * g_class) +{ + GstPad *pad = GST_BASE_SRC_PAD (src); + + gst_pad_set_fixatecaps_function (pad, gst_video_test_src_src_fixate); + + gst_video_test_src_set_pattern (src, DEFAULT_PATTERN); + + src->timestamp_offset = DEFAULT_TIMESTAMP_OFFSET; + src->foreground_color = DEFAULT_FOREGROUND_COLOR; + src->background_color = DEFAULT_BACKGROUND_COLOR; + src->horizontal_speed = DEFAULT_HORIZONTAL_SPEED; + + /* we operate in time */ + gst_base_src_set_format (GST_BASE_SRC (src), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (src), DEFAULT_IS_LIVE); + src->peer_alloc = DEFAULT_PEER_ALLOC; +} + +static void +gst_video_test_src_src_fixate (GstPad * pad, GstCaps * caps) +{ + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_fixate_field_nearest_int (structure, "width", 320); + gst_structure_fixate_field_nearest_int (structure, "height", 240); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", 30, 1); + if (gst_structure_has_field (structure, "pixel-aspect-ratio")) + gst_structure_fixate_field_nearest_fraction (structure, + "pixel-aspect-ratio", 1, 1); + if (gst_structure_has_field (structure, "color-matrix")) + gst_structure_fixate_field_string (structure, "color-matrix", "sdtv"); + if (gst_structure_has_field (structure, "chroma-site")) + gst_structure_fixate_field_string (structure, "chroma-site", "mpeg2"); + + if (gst_structure_has_field (structure, "interlaced")) + gst_structure_fixate_field_boolean (structure, "interlaced", FALSE); +} + +static void +gst_video_test_src_set_pattern (GstVideoTestSrc * videotestsrc, + int pattern_type) +{ + videotestsrc->pattern_type = pattern_type; + + GST_DEBUG_OBJECT (videotestsrc, "setting pattern to %d", pattern_type); + + switch (pattern_type) { + case GST_VIDEO_TEST_SRC_SMPTE: + videotestsrc->make_image = gst_video_test_src_smpte; + break; + case GST_VIDEO_TEST_SRC_SNOW: + videotestsrc->make_image = gst_video_test_src_snow; + break; + case GST_VIDEO_TEST_SRC_BLACK: + videotestsrc->make_image = gst_video_test_src_black; + break; + case GST_VIDEO_TEST_SRC_WHITE: + videotestsrc->make_image = gst_video_test_src_white; + break; + case GST_VIDEO_TEST_SRC_RED: + videotestsrc->make_image = gst_video_test_src_red; + break; + case GST_VIDEO_TEST_SRC_GREEN: + videotestsrc->make_image = gst_video_test_src_green; + break; + case GST_VIDEO_TEST_SRC_BLUE: + videotestsrc->make_image = gst_video_test_src_blue; + break; + case GST_VIDEO_TEST_SRC_CHECKERS1: + videotestsrc->make_image = gst_video_test_src_checkers1; + break; + case GST_VIDEO_TEST_SRC_CHECKERS2: + videotestsrc->make_image = gst_video_test_src_checkers2; + break; + case GST_VIDEO_TEST_SRC_CHECKERS4: + videotestsrc->make_image = gst_video_test_src_checkers4; + break; + case GST_VIDEO_TEST_SRC_CHECKERS8: + videotestsrc->make_image = gst_video_test_src_checkers8; + break; + case GST_VIDEO_TEST_SRC_CIRCULAR: + videotestsrc->make_image = gst_video_test_src_circular; + break; + case GST_VIDEO_TEST_SRC_BLINK: + videotestsrc->make_image = gst_video_test_src_blink; + break; + case GST_VIDEO_TEST_SRC_SMPTE75: + videotestsrc->make_image = gst_video_test_src_smpte75; + break; + case GST_VIDEO_TEST_SRC_ZONE_PLATE: + videotestsrc->make_image = gst_video_test_src_zoneplate; + break; + case GST_VIDEO_TEST_SRC_GAMUT: + videotestsrc->make_image = gst_video_test_src_gamut; + break; + case GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE: + videotestsrc->make_image = gst_video_test_src_chromazoneplate; + break; + case GST_VIDEO_TEST_SRC_SOLID: + videotestsrc->make_image = gst_video_test_src_solid; + break; + case GST_VIDEO_TEST_SRC_BALL: + videotestsrc->make_image = gst_video_test_src_ball; + break; + case GST_VIDEO_TEST_SRC_SMPTE100: + videotestsrc->make_image = gst_video_test_src_smpte100; + break; + case GST_VIDEO_TEST_SRC_BAR: + videotestsrc->make_image = gst_video_test_src_bar; + break; + default: + g_assert_not_reached (); + } +} + +static void +gst_video_test_src_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); + + switch (prop_id) { + case PROP_PATTERN: + gst_video_test_src_set_pattern (src, g_value_get_enum (value)); + break; + case PROP_TIMESTAMP_OFFSET: + src->timestamp_offset = g_value_get_int64 (value); + break; + case PROP_IS_LIVE: + gst_base_src_set_live (GST_BASE_SRC (src), g_value_get_boolean (value)); + break; + case PROP_PEER_ALLOC: + src->peer_alloc = g_value_get_boolean (value); + break; + case PROP_COLOR_SPEC: + break; + case PROP_K0: + src->k0 = g_value_get_int (value); + break; + case PROP_KX: + src->kx = g_value_get_int (value); + break; + case PROP_KY: + src->ky = g_value_get_int (value); + break; + case PROP_KT: + src->kt = g_value_get_int (value); + break; + case PROP_KXT: + src->kxt = g_value_get_int (value); + break; + case PROP_KYT: + src->kyt = g_value_get_int (value); + break; + case PROP_KXY: + src->kxy = g_value_get_int (value); + break; + case PROP_KX2: + src->kx2 = g_value_get_int (value); + break; + case PROP_KY2: + src->ky2 = g_value_get_int (value); + break; + case PROP_KT2: + src->kt2 = g_value_get_int (value); + break; + case PROP_XOFFSET: + src->xoffset = g_value_get_int (value); + break; + case PROP_YOFFSET: + src->yoffset = g_value_get_int (value); + break; + case PROP_FOREGROUND_COLOR: + src->foreground_color = g_value_get_uint (value); + break; + case PROP_BACKGROUND_COLOR: + src->background_color = g_value_get_uint (value); + break; + case PROP_HORIZONTAL_SPEED: + src->horizontal_speed = g_value_get_int (value); + default: + break; + } +} + +static void +gst_video_test_src_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (object); + + switch (prop_id) { + case PROP_PATTERN: + g_value_set_enum (value, src->pattern_type); + break; + case PROP_TIMESTAMP_OFFSET: + g_value_set_int64 (value, src->timestamp_offset); + break; + case PROP_IS_LIVE: + g_value_set_boolean (value, gst_base_src_is_live (GST_BASE_SRC (src))); + break; + case PROP_PEER_ALLOC: + g_value_set_boolean (value, src->peer_alloc); + break; + case PROP_COLOR_SPEC: + break; + case PROP_K0: + g_value_set_int (value, src->k0); + break; + case PROP_KX: + g_value_set_int (value, src->kx); + break; + case PROP_KY: + g_value_set_int (value, src->ky); + break; + case PROP_KT: + g_value_set_int (value, src->kt); + break; + case PROP_KXT: + g_value_set_int (value, src->kxt); + break; + case PROP_KYT: + g_value_set_int (value, src->kyt); + break; + case PROP_KXY: + g_value_set_int (value, src->kxy); + break; + case PROP_KX2: + g_value_set_int (value, src->kx2); + break; + case PROP_KY2: + g_value_set_int (value, src->ky2); + break; + case PROP_KT2: + g_value_set_int (value, src->kt2); + break; + case PROP_XOFFSET: + g_value_set_int (value, src->xoffset); + break; + case PROP_YOFFSET: + g_value_set_int (value, src->yoffset); + break; + case PROP_FOREGROUND_COLOR: + g_value_set_uint (value, src->foreground_color); + break; + case PROP_BACKGROUND_COLOR: + g_value_set_uint (value, src->background_color); + break; + case PROP_HORIZONTAL_SPEED: + g_value_set_int (value, src->horizontal_speed); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* threadsafe because this gets called as the plugin is loaded */ +static GstCaps * +gst_video_test_src_getcaps (GstBaseSrc * bsrc) +{ + static GstCaps *capslist = NULL; + + if (!capslist) { + GstCaps *caps; + GstStructure *structure; + int i; + + caps = gst_caps_new_empty (); + for (i = 0; i < n_fourccs; i++) { + structure = paint_get_structure (fourcc_list + i); + gst_structure_set (structure, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append_structure (caps, structure); + } + + capslist = caps; + } + + return gst_caps_copy (capslist); +} + +static gboolean +gst_video_test_src_parse_caps (const GstCaps * caps, + gint * width, gint * height, gint * rate_numerator, gint * rate_denominator, + struct fourcc_list_struct **fourcc, GstVideoTestSrcColorSpec * color_spec) +{ + const GstStructure *structure; + GstPadLinkReturn ret; + const GValue *framerate; + const char *csp; + + GST_DEBUG ("parsing caps"); + + if (gst_caps_get_size (caps) < 1) + return FALSE; + + structure = gst_caps_get_structure (caps, 0); + + if (!(*fourcc = paintinfo_find_by_structure (structure))) + goto unknown_format; + + ret = gst_structure_get_int (structure, "width", width); + ret &= gst_structure_get_int (structure, "height", height); + framerate = gst_structure_get_value (structure, "framerate"); + + if (framerate) { + *rate_numerator = gst_value_get_fraction_numerator (framerate); + *rate_denominator = gst_value_get_fraction_denominator (framerate); + } else + goto no_framerate; + + csp = gst_structure_get_string (structure, "color-matrix"); + if (csp) { + if (strcmp (csp, "sdtv") == 0) { + *color_spec = GST_VIDEO_TEST_SRC_BT601; + } else if (strcmp (csp, "hdtv") == 0) { + *color_spec = GST_VIDEO_TEST_SRC_BT709; + } else { + GST_DEBUG ("unknown color-matrix"); + return FALSE; + } + } else { + *color_spec = GST_VIDEO_TEST_SRC_BT601; + } + + return ret; + + /* ERRORS */ +unknown_format: + { + GST_DEBUG ("videotestsrc format not found"); + return FALSE; + } +no_framerate: + { + GST_DEBUG ("videotestsrc no framerate given"); + return FALSE; + } +} + +static gboolean +gst_video_test_src_setcaps (GstBaseSrc * bsrc, GstCaps * caps) +{ + gboolean res; + gint width, height, rate_denominator, rate_numerator; + struct fourcc_list_struct *fourcc; + GstVideoTestSrc *videotestsrc; + GstVideoTestSrcColorSpec color_spec; + + videotestsrc = GST_VIDEO_TEST_SRC (bsrc); + + res = gst_video_test_src_parse_caps (caps, &width, &height, + &rate_numerator, &rate_denominator, &fourcc, &color_spec); + if (res) { + /* looks ok here */ + videotestsrc->fourcc = fourcc; + videotestsrc->width = width; + videotestsrc->height = height; + videotestsrc->rate_numerator = rate_numerator; + videotestsrc->rate_denominator = rate_denominator; + videotestsrc->bpp = videotestsrc->fourcc->bitspp; + videotestsrc->color_spec = color_spec; + + GST_DEBUG_OBJECT (videotestsrc, "size %dx%d, %d/%d fps", + videotestsrc->width, videotestsrc->height, + videotestsrc->rate_numerator, videotestsrc->rate_denominator); + } + return res; +} + +static gboolean +gst_video_test_src_query (GstBaseSrc * bsrc, GstQuery * query) +{ + gboolean res; + GstVideoTestSrc *src; + + src = GST_VIDEO_TEST_SRC (bsrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_CONVERT: + { + GstFormat src_fmt, dest_fmt; + gint64 src_val, dest_val; + + gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); + if (src_fmt == dest_fmt) { + dest_val = src_val; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + /* frames to time */ + if (src->rate_numerator) { + dest_val = gst_util_uint64_scale (src_val, + src->rate_denominator * GST_SECOND, src->rate_numerator); + } else { + dest_val = 0; + } + break; + default: + goto error; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + /* time to frames */ + if (src->rate_numerator) { + dest_val = gst_util_uint64_scale (src_val, + src->rate_numerator, src->rate_denominator * GST_SECOND); + } else { + dest_val = 0; + } + break; + default: + goto error; + } + break; + default: + goto error; + } + done: + gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); + res = TRUE; + break; + } + default: + res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + } + return res; + + /* ERROR */ +error: + { + GST_DEBUG_OBJECT (src, "query failed"); + return FALSE; + } +} + +static void +gst_video_test_src_get_times (GstBaseSrc * basesrc, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + /* for live sources, sync on the timestamp of the buffer */ + if (gst_base_src_is_live (basesrc)) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) { + /* get duration to calculate end time */ + GstClockTime duration = GST_BUFFER_DURATION (buffer); + + if (GST_CLOCK_TIME_IS_VALID (duration)) { + *end = timestamp + duration; + } + *start = timestamp; + } + } else { + *start = -1; + *end = -1; + } +} + +static gboolean +gst_video_test_src_do_seek (GstBaseSrc * bsrc, GstSegment * segment) +{ + GstClockTime time; + GstVideoTestSrc *src; + + src = GST_VIDEO_TEST_SRC (bsrc); + + segment->time = segment->start; + time = segment->last_stop; + + /* now move to the time indicated */ + if (src->rate_numerator) { + src->n_frames = gst_util_uint64_scale (time, + src->rate_numerator, src->rate_denominator * GST_SECOND); + } else { + src->n_frames = 0; + } + if (src->rate_numerator) { + src->running_time = gst_util_uint64_scale (src->n_frames, + src->rate_denominator * GST_SECOND, src->rate_numerator); + } else { + /* FIXME : Not sure what to set here */ + src->running_time = 0; + } + + g_assert (src->running_time <= time); + + return TRUE; +} + +static gboolean +gst_video_test_src_is_seekable (GstBaseSrc * psrc) +{ + /* we're seekable... */ + return TRUE; +} + +static GstFlowReturn +gst_video_test_src_create (GstPushSrc * psrc, GstBuffer ** buffer) +{ + GstVideoTestSrc *src; + gulong newsize, size; + GstBuffer *outbuf = NULL; + GstFlowReturn res; + GstClockTime next_time; + + src = GST_VIDEO_TEST_SRC (psrc); + + if (G_UNLIKELY (src->fourcc == NULL)) + goto not_negotiated; + + /* 0 framerate and we are at the second frame, eos */ + if (G_UNLIKELY (src->rate_numerator == 0 && src->n_frames == 1)) + goto eos; + + newsize = gst_video_test_src_get_size (src, src->width, src->height); + + g_return_val_if_fail (newsize > 0, GST_FLOW_ERROR); + + GST_LOG_OBJECT (src, + "creating buffer of %lu bytes with %dx%d image for frame %d", newsize, + src->width, src->height, (gint) src->n_frames); + + if (src->peer_alloc) { + res = + gst_pad_alloc_buffer_and_set_caps (GST_BASE_SRC_PAD (psrc), + GST_BUFFER_OFFSET_NONE, newsize, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc)), + &outbuf); + if (res != GST_FLOW_OK) + goto no_buffer; + + /* the buffer could have renegotiated, we need to discard any buffers of the + * wrong size. */ + size = GST_BUFFER_SIZE (outbuf); + newsize = gst_video_test_src_get_size (src, src->width, src->height); + + if (size != newsize) { + gst_buffer_unref (outbuf); + outbuf = NULL; + } + } + + if (outbuf == NULL) { + outbuf = gst_buffer_new_and_alloc (newsize); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (GST_BASE_SRC_PAD (psrc))); + } + + memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf)); + src->tmpline_u8 = g_malloc (src->width + 8); + src->tmpline = g_malloc ((src->width + 8) * 4); + src->tmpline2 = g_malloc ((src->width + 8) * 4); + + src->make_image (src, (void *) GST_BUFFER_DATA (outbuf), + src->width, src->height); + + g_free (src->tmpline); + g_free (src->tmpline2); + g_free (src->tmpline_u8); + + GST_BUFFER_TIMESTAMP (outbuf) = src->timestamp_offset + src->running_time; + GST_BUFFER_OFFSET (outbuf) = src->n_frames; + src->n_frames++; + GST_BUFFER_OFFSET_END (outbuf) = src->n_frames; + if (src->rate_numerator) { + next_time = gst_util_uint64_scale_int (src->n_frames * GST_SECOND, + src->rate_denominator, src->rate_numerator); + GST_BUFFER_DURATION (outbuf) = next_time - src->running_time; + } else { + next_time = src->timestamp_offset; + /* NONE means forever */ + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; + } + + src->running_time = next_time; + + *buffer = outbuf; + + return GST_FLOW_OK; + +not_negotiated: + { + GST_ELEMENT_ERROR (src, CORE, NEGOTIATION, (NULL), + ("format wasn't negotiated before get function")); + return GST_FLOW_NOT_NEGOTIATED; + } +eos: + { + GST_DEBUG_OBJECT (src, "eos: 0 framerate, frame %d", (gint) src->n_frames); + return GST_FLOW_UNEXPECTED; + } +no_buffer: + { + GST_DEBUG_OBJECT (src, "could not allocate buffer, reason %s", + gst_flow_get_name (res)); + return res; + } +} + +static gboolean +gst_video_test_src_start (GstBaseSrc * basesrc) +{ + GstVideoTestSrc *src = GST_VIDEO_TEST_SRC (basesrc); + + src->running_time = 0; + src->n_frames = 0; + + return TRUE; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_videotestsrc_orc_init (); + + GST_DEBUG_CATEGORY_INIT (video_test_src_debug, "videotestsrc", 0, + "Video Test Source"); + + return gst_element_register (plugin, "videotestsrc", GST_RANK_NONE, + GST_TYPE_VIDEO_TEST_SRC); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videotestsrc", + "Creates a test video stream", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.h b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.h new file mode 100644 index 0000000..ae63281 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrc.h @@ -0,0 +1,190 @@ +/* GStreamer + * Copyright (C) <2002> David A. Schleef + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VIDEO_TEST_SRC_H__ +#define __GST_VIDEO_TEST_SRC_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_TEST_SRC \ + (gst_video_test_src_get_type()) +#define GST_VIDEO_TEST_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_TEST_SRC,GstVideoTestSrc)) +#define GST_VIDEO_TEST_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_TEST_SRC,GstVideoTestSrcClass)) +#define GST_IS_VIDEO_TEST_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_TEST_SRC)) +#define GST_IS_VIDEO_TEST_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_TEST_SRC)) + +/** + * GstVideoTestSrcPattern: + * @GST_VIDEO_TEST_SRC_SMPTE: A standard SMPTE test pattern + * @GST_VIDEO_TEST_SRC_SNOW: Random noise + * @GST_VIDEO_TEST_SRC_BLACK: A black image + * @GST_VIDEO_TEST_SRC_WHITE: A white image + * @GST_VIDEO_TEST_SRC_RED: A red image + * @GST_VIDEO_TEST_SRC_GREEN: A green image + * @GST_VIDEO_TEST_SRC_BLUE: A blue image + * @GST_VIDEO_TEST_SRC_CHECKERS1: Checkers pattern (1px) + * @GST_VIDEO_TEST_SRC_CHECKERS2: Checkers pattern (2px) + * @GST_VIDEO_TEST_SRC_CHECKERS4: Checkers pattern (4px) + * @GST_VIDEO_TEST_SRC_CHECKERS8: Checkers pattern (8px) + * @GST_VIDEO_TEST_SRC_CIRCULAR: Circular pattern + * @GST_VIDEO_TEST_SRC_BLINK: Alternate between black and white + * @GST_VIDEO_TEST_SRC_SMPTE75: SMPTE test pattern (75% color bars) + * @GST_VIDEO_TEST_SRC_ZONE_PLATE: Zone plate + * @GST_VIDEO_TEST_SRC_GAMUT: Gamut checking pattern + * @GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE: Chroma zone plate + * @GST_VIDEO_TEST_SRC_BALL: Moving ball + * @GST_VIDEO_TEST_SRC_SMPTE100: SMPTE test pattern (100% color bars) + * @GST_VIDEO_TEST_SRC_BAR: Bar with foreground color + * + * The test pattern to produce. + * + * The Gamut pattern creates a checkerboard pattern of colors at the + * edge of the YCbCr gamut and nearby colors that are out of gamut. + * The pattern is divided into 4 regions: black, white, red, and blue. + * After conversion to RGB, the out-of-gamut colors should be converted + * to the same value as their in-gamut neighbors. If the checkerboard + * pattern is still visible after conversion, this indicates a faulty + * conversion. Image manipulation, such as adjusting contrast or + * brightness, can also cause the pattern to be visible. + * + * The Zone Plate pattern is based on BBC R&D Report 1978/23, and can + * be used to test spatial frequency response of a system. This + * pattern generator is controlled by the xoffset and yoffset parameters + * and also by all the parameters starting with 'k'. The default + * parameters produce a grey pattern. Try 'videotestsrc + * pattern=zone-plate kx2=20 ky2=20 kt=1' to produce something + * interesting. + */ +typedef enum { + GST_VIDEO_TEST_SRC_SMPTE, + GST_VIDEO_TEST_SRC_SNOW, + GST_VIDEO_TEST_SRC_BLACK, + GST_VIDEO_TEST_SRC_WHITE, + GST_VIDEO_TEST_SRC_RED, + GST_VIDEO_TEST_SRC_GREEN, + GST_VIDEO_TEST_SRC_BLUE, + GST_VIDEO_TEST_SRC_CHECKERS1, + GST_VIDEO_TEST_SRC_CHECKERS2, + GST_VIDEO_TEST_SRC_CHECKERS4, + GST_VIDEO_TEST_SRC_CHECKERS8, + GST_VIDEO_TEST_SRC_CIRCULAR, + GST_VIDEO_TEST_SRC_BLINK, + GST_VIDEO_TEST_SRC_SMPTE75, + GST_VIDEO_TEST_SRC_ZONE_PLATE, + GST_VIDEO_TEST_SRC_GAMUT, + GST_VIDEO_TEST_SRC_CHROMA_ZONE_PLATE, + GST_VIDEO_TEST_SRC_SOLID, + GST_VIDEO_TEST_SRC_BALL, + GST_VIDEO_TEST_SRC_SMPTE100, + GST_VIDEO_TEST_SRC_BAR +} GstVideoTestSrcPattern; + +/** + * GstVideoTestSrcColorSpec: + * @GST_VIDEO_TEST_SRC_BT601: ITU-R Rec. BT.601/BT.470 (SD) + * @GST_VIDEO_TEST_SRC_BT709: ITU-R Rec. BT.709 (HD) + * + * The color specification to use. + */ +typedef enum { + GST_VIDEO_TEST_SRC_BT601, + GST_VIDEO_TEST_SRC_BT709 +} GstVideoTestSrcColorSpec; + +typedef struct _GstVideoTestSrc GstVideoTestSrc; +typedef struct _GstVideoTestSrcClass GstVideoTestSrcClass; + +/** + * GstVideoTestSrc: + * + * Opaque data structure. + */ +struct _GstVideoTestSrc { + GstPushSrc element; + + /*< private >*/ + + /* type of output */ + GstVideoTestSrcPattern pattern_type; + + /* Color spec of output */ + GstVideoTestSrcColorSpec color_spec; + + /* video state */ + char *format_name; + gint width; + gint height; + struct fourcc_list_struct *fourcc; + gint bpp; + gint rate_numerator; + gint rate_denominator; + + /* private */ + gint64 timestamp_offset; /* base offset */ + GstClockTime running_time; /* total running time */ + gint64 n_frames; /* total frames sent */ + gboolean peer_alloc; + + /* zoneplate */ + gint k0; + gint kx; + gint ky; + gint kt; + gint kxt; + gint kyt; + gint kxy; + gint kx2; + gint ky2; + gint kt2; + gint xoffset; + gint yoffset; + + /* solid color */ + guint foreground_color; + guint background_color; + + /* moving color bars */ + gint horizontal_offset; + gint horizontal_speed; + + void (*make_image) (GstVideoTestSrc *v, unsigned char *dest, int w, int h); + + /* temporary AYUV/ARGB scanline */ + guint8 *tmpline_u8; + guint8 *tmpline; + guint8 *tmpline2; +}; + +struct _GstVideoTestSrcClass { + GstPushSrcClass parent_class; +}; + +GType gst_video_test_src_get_type (void); + +G_END_DECLS + +#endif /* __GST_VIDEO_TEST_SRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.c b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.c new file mode 100644 index 0000000..2f6c588 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.c @@ -0,0 +1,482 @@ + +/* autogenerated from gstvideotestsrcorc.orc */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 + +#ifndef DISABLE_ORC +#include +#endif +void gst_orc_splat_u8 (guint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_s16 (gint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_u16 (guint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_u32 (guint8 * ORC_RESTRICT d1, int p1, int n); + +void gst_videotestsrc_orc_init (void); + + +/* begin Orc C target preamble */ +#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x))) +#define ORC_ABS(a) ((a)<0 ? -(a) : (a)) +#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define ORC_SB_MAX 127 +#define ORC_SB_MIN (-1-ORC_SB_MAX) +#define ORC_UB_MAX 255 +#define ORC_UB_MIN 0 +#define ORC_SW_MAX 32767 +#define ORC_SW_MIN (-1-ORC_SW_MAX) +#define ORC_UW_MAX 65535 +#define ORC_UW_MIN 0 +#define ORC_SL_MAX 2147483647 +#define ORC_SL_MIN (-1-ORC_SL_MAX) +#define ORC_UL_MAX 4294967295U +#define ORC_UL_MIN 0 +#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX) +#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX) +#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX) +#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX) +#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX) +#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) +#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) +#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) +#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#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 +#define ORC_RESTRICT __restrict__ +#else +#define ORC_RESTRICT +#endif +#endif +/* end Orc C target preamble */ + + + +/* gst_orc_splat_u8 */ +#ifdef DISABLE_ORC +void +gst_orc_splat_u8 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var32; + orc_int8 var33; + + ptr0 = (orc_int8 *) d1; + + /* 0: loadpb */ + var32 = p1; + + for (i = 0; i < n; i++) { + /* 1: copyb */ + var33 = var32; + /* 2: storeb */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_gst_orc_splat_u8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var32; + orc_int8 var33; + + ptr0 = (orc_int8 *) ex->arrays[0]; + + /* 0: loadpb */ + var32 = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyb */ + var33 = var32; + /* 2: storeb */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_gst_orc_splat_u8; +void +gst_orc_splat_u8 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_orc_splat_u8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_orc_splat_s16 */ +#ifdef DISABLE_ORC +void +gst_orc_splat_s16 (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) d1; + + /* 0: loadpw */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_gst_orc_splat_s16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) ex->arrays[0]; + + /* 0: loadpw */ + var32.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_gst_orc_splat_s16; +void +gst_orc_splat_s16 (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_orc_splat_s16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_orc_splat_u16 */ +#ifdef DISABLE_ORC +void +gst_orc_splat_u16 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) d1; + + /* 0: loadpw */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_gst_orc_splat_u16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var32; + orc_union16 var33; + + ptr0 = (orc_union16 *) ex->arrays[0]; + + /* 0: loadpw */ + var32.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyw */ + var33.i = var32.i; + /* 2: storew */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_gst_orc_splat_u16; +void +gst_orc_splat_u16 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_orc_splat_u16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* gst_orc_splat_u32 */ +#ifdef DISABLE_ORC +void +gst_orc_splat_u32 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) d1; + + /* 0: loadpl */ + var32.i = p1; + + for (i = 0; i < n; i++) { + /* 1: copyl */ + var33.i = var32.i; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_gst_orc_splat_u32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + + ptr0 = (orc_union32 *) ex->arrays[0]; + + /* 0: loadpl */ + var32.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 1: copyl */ + var33.i = var32.i; + /* 2: storel */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_gst_orc_splat_u32; +void +gst_orc_splat_u32 (guint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_gst_orc_splat_u32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +void +gst_videotestsrc_orc_init (void) +{ +#ifndef DISABLE_ORC + { + /* gst_orc_splat_u8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_orc_splat_u8"); + orc_program_set_backup_function (p, _backup_gst_orc_splat_u8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_parameter (p, 1, "p1"); + + orc_program_append_2 (p, "copyb", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_orc_splat_u8 = p; + } + { + /* gst_orc_splat_s16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_orc_splat_s16"); + orc_program_set_backup_function (p, _backup_gst_orc_splat_s16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_parameter (p, 2, "p1"); + + orc_program_append_2 (p, "copyw", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_orc_splat_s16 = p; + } + { + /* gst_orc_splat_u16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_orc_splat_u16"); + orc_program_set_backup_function (p, _backup_gst_orc_splat_u16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_parameter (p, 2, "p1"); + + orc_program_append_2 (p, "copyw", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_orc_splat_u16 = p; + } + { + /* gst_orc_splat_u32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "gst_orc_splat_u32"); + orc_program_set_backup_function (p, _backup_gst_orc_splat_u32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_parameter (p, 4, "p1"); + + orc_program_append_2 (p, "copyl", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_gst_orc_splat_u32 = p; + } +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.h b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.h new file mode 100644 index 0000000..9c7ba64 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc-dist.h @@ -0,0 +1,82 @@ + +/* autogenerated from gstvideotestsrcorc.orc */ + +#ifndef _GSTVIDEOTESTSRCORC_H_ +#define _GSTVIDEOTESTSRCORC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void gst_videotestsrc_orc_init (void); + + + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 gst_orc_splat_u8 (guint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_s16 (gint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_u16 (guint8 * ORC_RESTRICT d1, int p1, int n); +void gst_orc_splat_u32 (guint8 * ORC_RESTRICT d1, int p1, int n); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc.orc b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc.orc new file mode 100644 index 0000000..a2fc80b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/gstvideotestsrcorc.orc @@ -0,0 +1,31 @@ + +.init gst_videotestsrc_orc_init + +.function gst_orc_splat_u8 +.dest 1 d1 guint8 +.param 1 p1 + +copyb d1, p1 + + +.function gst_orc_splat_s16 +.dest 2 d1 gint8 +.param 2 p1 + +copyw d1, p1 + + +.function gst_orc_splat_u16 +.dest 2 d1 guint8 +.param 2 p1 + +copyw d1, p1 + + +.function gst_orc_splat_u32 +.dest 4 d1 guint8 +.param 4 p1 + +copyl d1, p1 + + diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.c b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.c new file mode 100644 index 0000000..9973507 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.c @@ -0,0 +1,2593 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +/* non-GST-specific stuff */ + +#include "gstvideotestsrc.h" +#include "videotestsrc.h" +#include "gstvideotestsrcorc.h" + +#include + +#include +#include + +#define TO_16(x) (((x)<<8) | (x)) +#define TO_10(x) (((x)<<2) | ((x)>>6)) + +static void paint_tmpline_ARGB (paintinfo * p, int x, int w); +static void paint_tmpline_AYUV (paintinfo * p, int x, int w); + +static unsigned char +random_char (void) +{ + static unsigned int state; + + state *= 1103515245; + state += 12345; + return (state >> 16) & 0xff; +} + +enum +{ + COLOR_WHITE = 0, + COLOR_YELLOW, + COLOR_CYAN, + COLOR_GREEN, + COLOR_MAGENTA, + COLOR_RED, + COLOR_BLUE, + COLOR_BLACK, + COLOR_NEG_I, + COLOR_POS_Q, + COLOR_SUPER_BLACK, + COLOR_DARK_GREY +}; + +static const struct vts_color_struct vts_colors_bt709_ycbcr_100[] = { + {235, 128, 128, 255, 255, 255, 255, (235 << 8)}, + {219, 16, 138, 255, 255, 255, 0, (219 << 8)}, + {188, 154, 16, 255, 0, 255, 255, (188 < 8)}, + {173, 42, 26, 255, 0, 255, 0, (173 << 8)}, + {78, 214, 230, 255, 255, 0, 255, (78 << 8)}, + {63, 102, 240, 255, 255, 0, 0, (64 << 8)}, + {32, 240, 118, 255, 0, 0, 255, (32 << 8)}, + {16, 128, 128, 255, 0, 0, 0, (16 << 8)}, + {16, 198, 21, 255, 0, 0, 128, (16 << 8)}, /* -I ? */ + {16, 235, 198, 255, 0, 128, 255, (16 << 8)}, /* +Q ? */ + {0, 128, 128, 255, 0, 0, 0, 0}, + {32, 128, 128, 255, 19, 19, 19, (32 << 8)}, +}; + +static const struct vts_color_struct vts_colors_bt709_ycbcr_75[] = { + {180, 128, 128, 255, 191, 191, 191, (180 << 8)}, + {168, 44, 136, 255, 191, 191, 0, (168 << 8)}, + {145, 147, 44, 255, 0, 191, 191, (145 << 8)}, + {133, 63, 52, 255, 0, 191, 0, (133 << 8)}, + {63, 193, 204, 255, 191, 0, 191, (63 << 8)}, + {51, 109, 212, 255, 191, 0, 0, (51 << 8)}, + {28, 212, 120, 255, 0, 0, 191, (28 << 8)}, + {16, 128, 128, 255, 0, 0, 0, (16 << 8)}, + {16, 198, 21, 255, 0, 0, 128, (16 << 8)}, /* -I ? */ + {16, 235, 198, 255, 0, 128, 255, (16 << 8)}, /* +Q ? */ + {0, 128, 128, 255, 0, 0, 0, 0}, + {32, 128, 128, 255, 19, 19, 19, (32 << 8)}, +}; + +static const struct vts_color_struct vts_colors_bt601_ycbcr_100[] = { + {235, 128, 128, 255, 255, 255, 255, (235 << 8)}, + {210, 16, 146, 255, 255, 255, 0, (219 << 8)}, + {170, 166, 16, 255, 0, 255, 255, (188 < 8)}, + {145, 54, 34, 255, 0, 255, 0, (173 << 8)}, + {106, 202, 222, 255, 255, 0, 255, (78 << 8)}, + {81, 90, 240, 255, 255, 0, 0, (64 << 8)}, + {41, 240, 110, 255, 0, 0, 255, (32 << 8)}, + {16, 128, 128, 255, 0, 0, 0, (16 << 8)}, + {16, 198, 21, 255, 0, 0, 128, (16 << 8)}, /* -I ? */ + {16, 235, 198, 255, 0, 128, 255, (16 << 8)}, /* +Q ? */ + {-0, 128, 128, 255, 0, 0, 0, 0}, + {32, 128, 128, 255, 19, 19, 19, (32 << 8)}, +}; + +static const struct vts_color_struct vts_colors_bt601_ycbcr_75[] = { + {180, 128, 128, 255, 191, 191, 191, (180 << 8)}, + {162, 44, 142, 255, 191, 191, 0, (168 << 8)}, + {131, 156, 44, 255, 0, 191, 191, (145 << 8)}, + {112, 72, 58, 255, 0, 191, 0, (133 << 8)}, + {84, 184, 198, 255, 191, 0, 191, (63 << 8)}, + {65, 100, 212, 255, 191, 0, 0, (51 << 8)}, + {35, 212, 114, 255, 0, 0, 191, (28 << 8)}, + {16, 128, 128, 255, 0, 0, 0, (16 << 8)}, + {16, 198, 21, 255, 0, 0, 128, (16 << 8)}, /* -I ? */ + {16, 235, 198, 255, 0, 128, 255, (16 << 8)}, /* +Q ? */ + {-0, 128, 128, 255, 0, 0, 0, 0}, + {32, 128, 128, 255, 19, 19, 19, (32 << 8)}, +}; + + +static void paint_setup_I420 (paintinfo * p, unsigned char *dest); +static void paint_setup_YV12 (paintinfo * p, unsigned char *dest); +static void paint_setup_YUY2 (paintinfo * p, unsigned char *dest); +static void paint_setup_UYVY (paintinfo * p, unsigned char *dest); +static void paint_setup_YVYU (paintinfo * p, unsigned char *dest); +#ifdef disabled +static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest); +#endif +static void paint_setup_Y41B (paintinfo * p, unsigned char *dest); +static void paint_setup_Y42B (paintinfo * p, unsigned char *dest); +static void paint_setup_Y444 (paintinfo * p, unsigned char *dest); +static void paint_setup_Y800 (paintinfo * p, unsigned char *dest); +static void paint_setup_AYUV (paintinfo * p, unsigned char *dest); +static void paint_setup_v308 (paintinfo * p, unsigned char *dest); +static void paint_setup_NV12 (paintinfo * p, unsigned char *dest); +static void paint_setup_NV21 (paintinfo * p, unsigned char *dest); +#ifdef disabled +static void paint_setup_v410 (paintinfo * p, unsigned char *dest); +#endif +static void paint_setup_v216 (paintinfo * p, unsigned char *dest); +static void paint_setup_v210 (paintinfo * p, unsigned char *dest); +static void paint_setup_UYVP (paintinfo * p, unsigned char *dest); +static void paint_setup_AY64 (paintinfo * p, unsigned char *dest); + +static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest); +static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest); +static void paint_setup_ARGB8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_ABGR8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_RGBA8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_BGRA8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_xRGB8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_xBGR8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_RGBx8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_BGRx8888 (paintinfo * p, unsigned char *dest); +static void paint_setup_RGB888 (paintinfo * p, unsigned char *dest); +static void paint_setup_BGR888 (paintinfo * p, unsigned char *dest); +static void paint_setup_RGB565 (paintinfo * p, unsigned char *dest); +static void paint_setup_xRGB1555 (paintinfo * p, unsigned char *dest); +static void paint_setup_ARGB64 (paintinfo * p, unsigned char *dest); + +static void paint_setup_bayer_bggr (paintinfo * p, unsigned char *dest); +static void paint_setup_bayer_rggb (paintinfo * p, unsigned char *dest); +static void paint_setup_bayer_gbrg (paintinfo * p, unsigned char *dest); +static void paint_setup_bayer_grbg (paintinfo * p, unsigned char *dest); + +static void convert_hline_I420 (paintinfo * p, int y); +static void convert_hline_NV12 (paintinfo * p, int y); +static void convert_hline_NV21 (paintinfo * p, int y); +static void convert_hline_YUY2 (paintinfo * p, int y); +#ifdef disabled +static void convert_hline_IYU2 (paintinfo * p, int y); +#endif +static void convert_hline_Y41B (paintinfo * p, int y); +static void convert_hline_Y42B (paintinfo * p, int y); +static void convert_hline_Y444 (paintinfo * p, int y); +static void convert_hline_Y800 (paintinfo * p, int y); +static void convert_hline_v308 (paintinfo * p, int y); +static void convert_hline_AYUV (paintinfo * p, int y); +#ifdef disabled +static void convert_hline_v410 (paintinfo * p, int y); +#endif +static void convert_hline_v216 (paintinfo * p, int y); +static void convert_hline_v210 (paintinfo * p, int y); +static void convert_hline_UYVP (paintinfo * p, int y); +static void convert_hline_AY64 (paintinfo * p, int y); + +static void convert_hline_YUV9 (paintinfo * p, int y); +static void convert_hline_astr4 (paintinfo * p, int y); +static void convert_hline_astr8 (paintinfo * p, int y); +static void convert_hline_str4 (paintinfo * p, int y); +static void convert_hline_str3 (paintinfo * p, int y); +static void convert_hline_RGB565 (paintinfo * p, int y); +static void convert_hline_xRGB1555 (paintinfo * p, int y); + +static void convert_hline_bayer (paintinfo * p, int y); + +static void paint_setup_GRAY8 (paintinfo * p, unsigned char *dest); +static void paint_setup_GRAY16 (paintinfo * p, unsigned char *dest); +static void convert_hline_GRAY8 (paintinfo * p, int y); +static void convert_hline_GRAY16 (paintinfo * p, int y); + +struct fourcc_list_struct fourcc_list[] = { +/* packed */ + {VTS_YUV, "YUY2", "YUY2", 16, paint_setup_YUY2, convert_hline_YUY2}, + {VTS_YUV, "UYVY", "UYVY", 16, paint_setup_UYVY, convert_hline_YUY2}, +#ifdef disabled + {VTS_YUV, "Y422", "Y422", 16, paint_setup_UYVY, convert_hline_YUY2}, + {VTS_YUV, "UYNV", "UYNV", 16, paint_setup_UYVY, convert_hline_YUY2}, /* FIXME: UYNV? */ +#endif + {VTS_YUV, "YVYU", "YVYU", 16, paint_setup_YVYU, convert_hline_YUY2}, + {VTS_YUV, "v308", "v308", 24, paint_setup_v308, convert_hline_v308}, + {VTS_YUV, "AYUV", "AYUV", 32, paint_setup_AYUV, convert_hline_AYUV}, +#ifdef disabled + {VTS_YUV, "v410", "v410", 32, paint_setup_v410, convert_hline_v410}, +#endif + {VTS_YUV, "v210", "v210", 21, paint_setup_v210, convert_hline_v210}, + {VTS_YUV, "v216", "v216", 32, paint_setup_v216, convert_hline_v216}, + {VTS_YUV, "UYVP", "UYVP", 20, paint_setup_UYVP, convert_hline_UYVP}, + {VTS_YUV, "AY64", "AY64", 64, paint_setup_AY64, convert_hline_AY64}, + +#ifdef disabled + {VTS_YUV, "IYU2", "IYU2", 24, paint_setup_IYU2, convert_hline_IYU2}, +#endif + +/* planar */ + /* YVU9 */ + {VTS_YUV, "YVU9", "YVU9", 9, paint_setup_YVU9, convert_hline_YUV9}, + /* YUV9 */ + {VTS_YUV, "YUV9", "YUV9", 9, paint_setup_YUV9, convert_hline_YUV9}, + /* IF09 */ + /* YV12 */ + {VTS_YUV, "YV12", "YV12", 12, paint_setup_YV12, convert_hline_I420}, + /* I420 */ + {VTS_YUV, "I420", "I420", 12, paint_setup_I420, convert_hline_I420}, + /* NV12 */ + {VTS_YUV, "NV12", "NV12", 12, paint_setup_NV12, convert_hline_NV12}, + /* NV21 */ + {VTS_YUV, "NV21", "NV21", 12, paint_setup_NV21, convert_hline_NV21}, + /* CLPL */ + /* Y41B */ + {VTS_YUV, "Y41B", "Y41B", 12, paint_setup_Y41B, convert_hline_Y41B}, + /* Y42B */ + {VTS_YUV, "Y42B", "Y42B", 16, paint_setup_Y42B, convert_hline_Y42B}, + /* Y444 */ + {VTS_YUV, "Y444", "Y444", 24, paint_setup_Y444, convert_hline_Y444}, + /* Y800 grayscale */ + {VTS_YUV, "Y800", "Y800", 8, paint_setup_Y800, convert_hline_Y800}, + + /* Not exactly YUV but it's the same as above */ + {VTS_GRAY, "GRAY8", "GRAY8", 8, paint_setup_GRAY8, convert_hline_GRAY8}, + {VTS_GRAY, "GRAY16", "GRAY16", 16, paint_setup_GRAY16, convert_hline_GRAY16}, + + {VTS_RGB, "RGB ", "xRGB8888", 32, paint_setup_xRGB8888, convert_hline_str4, + 24, + 0x00ff0000, 0x0000ff00, 0x000000ff}, + {VTS_RGB, "RGB ", "xBGR8888", 32, paint_setup_xBGR8888, convert_hline_str4, + 24, + 0x000000ff, 0x0000ff00, 0x00ff0000}, + {VTS_RGB, "RGB ", "RGBx8888", 32, paint_setup_RGBx8888, convert_hline_str4, + 24, + 0xff000000, 0x00ff0000, 0x0000ff00}, + {VTS_RGB, "RGB ", "BGRx8888", 32, paint_setup_BGRx8888, convert_hline_str4, + 24, + 0x0000ff00, 0x00ff0000, 0xff000000}, + {VTS_RGB, "RGB ", "ARGB8888", 32, paint_setup_ARGB8888, convert_hline_astr4, + 32, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, + {VTS_RGB, "RGB ", "ABGR8888", 32, paint_setup_ABGR8888, convert_hline_astr4, + 32, + 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, + {VTS_RGB, "RGB ", "RGBA8888", 32, paint_setup_RGBA8888, convert_hline_astr4, + 32, + 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff}, + {VTS_RGB, "RGB ", "BGRA8888", 32, paint_setup_BGRA8888, convert_hline_astr4, + 32, + 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff}, + {VTS_RGB, "RGB ", "RGB888", 24, paint_setup_RGB888, convert_hline_str3, 24, + 0x00ff0000, 0x0000ff00, 0x000000ff}, + {VTS_RGB, "RGB ", "BGR888", 24, paint_setup_BGR888, convert_hline_str3, 24, + 0x000000ff, 0x0000ff00, 0x00ff0000}, + {VTS_RGB, "RGB ", "RGB565", 16, paint_setup_RGB565, convert_hline_RGB565, 16, + 0x0000f800, 0x000007e0, 0x0000001f}, + {VTS_RGB, "RGB ", "xRGB1555", 16, paint_setup_xRGB1555, + convert_hline_xRGB1555, + 15, + 0x00007c00, 0x000003e0, 0x0000001f}, + {VTS_RGB, "RGB ", "ARGB8888", 64, paint_setup_ARGB64, convert_hline_astr8, + 64, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, + + {VTS_BAYER, "bggr", "Bayer", 8, paint_setup_bayer_bggr, convert_hline_bayer}, + {VTS_BAYER, "rggb", "Bayer", 8, paint_setup_bayer_rggb, convert_hline_bayer}, + {VTS_BAYER, "grbg", "Bayer", 8, paint_setup_bayer_grbg, convert_hline_bayer}, + {VTS_BAYER, "gbrg", "Bayer", 8, paint_setup_bayer_gbrg, convert_hline_bayer} +}; + +int n_fourccs = G_N_ELEMENTS (fourcc_list); + +struct fourcc_list_struct * +paintinfo_find_by_structure (const GstStructure * structure) +{ + int i; + const char *media_type = gst_structure_get_name (structure); + int ret; + + g_return_val_if_fail (structure, NULL); + + if (strcmp (media_type, "video/x-raw-gray") == 0) { + gint bpp, depth, endianness = 0; + + ret = gst_structure_get_int (structure, "bpp", &bpp) && + gst_structure_get_int (structure, "depth", &depth); + if (!ret || bpp != depth || (depth != 8 && depth != 16)) + return NULL; + + ret = gst_structure_get_int (structure, "endianness", &endianness); + if ((!ret || endianness != G_BYTE_ORDER) && bpp == 16) + return NULL; + + for (i = 0; i < n_fourccs; i++) { + if (fourcc_list[i].type == VTS_GRAY && fourcc_list[i].bitspp == bpp) { + return fourcc_list + i; + } + } + } else if (strcmp (media_type, "video/x-raw-yuv") == 0) { + const char *s; + int fourcc; + guint32 format; + + ret = gst_structure_get_fourcc (structure, "format", &format); + if (!ret) + return NULL; + for (i = 0; i < n_fourccs; i++) { + s = fourcc_list[i].fourcc; + /* g_print("testing %" GST_FOURCC_FORMAT " and %s\n", GST_FOURCC_ARGS(format), s); */ + fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]); + if (fourcc_list[i].type == VTS_YUV && fourcc == format) { + return fourcc_list + i; + } + } + } else if (strcmp (media_type, "video/x-raw-rgb") == 0) { + int red_mask; + int green_mask; + int blue_mask; + int alpha_mask; + int depth; + int bpp; + + ret = gst_structure_get_int (structure, "red_mask", &red_mask); + ret &= gst_structure_get_int (structure, "green_mask", &green_mask); + ret &= gst_structure_get_int (structure, "blue_mask", &blue_mask); + ret &= gst_structure_get_int (structure, "depth", &depth); + ret &= gst_structure_get_int (structure, "bpp", &bpp); + + if (depth == 32) { + ret &= gst_structure_get_int (structure, "alpha_mask", &alpha_mask); + ret &= (alpha_mask != 0); + } else { + alpha_mask = 0; + } + + if (!ret) { + GST_WARNING ("incomplete caps structure: %" GST_PTR_FORMAT, structure); + return NULL; + } + + for (i = 0; i < n_fourccs; i++) { + if (fourcc_list[i].type == VTS_RGB && + fourcc_list[i].red_mask == red_mask && + fourcc_list[i].green_mask == green_mask && + fourcc_list[i].blue_mask == blue_mask && + (alpha_mask == 0 || fourcc_list[i].alpha_mask == alpha_mask) && + fourcc_list[i].depth == depth && fourcc_list[i].bitspp == bpp) { + return fourcc_list + i; + } + } + return NULL; + } else if (strcmp (media_type, "video/x-raw-bayer") == 0) { + const gchar *format; + + format = gst_structure_get_string (structure, "format"); + if (!format) { + GST_WARNING ("incomplete caps structure: %" GST_PTR_FORMAT, structure); + return NULL; + } + + for (i = 0; i < n_fourccs; i++) { + if (fourcc_list[i].type == VTS_BAYER && + g_str_equal (format, fourcc_list[i].fourcc)) { + return fourcc_list + i; + } + } + return NULL; + } + + g_critical ("format not found for media type %s", media_type); + + return NULL; +} + +struct fourcc_list_struct * +paintrect_find_fourcc (int find_fourcc) +{ + int i; + + for (i = 0; i < n_fourccs; i++) { + const char *s; + int fourcc; + + s = fourcc_list[i].fourcc; + fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]); + if (find_fourcc == fourcc) { + /* If YUV format, it's good */ + if (!fourcc_list[i].type == VTS_YUV) { + return fourcc_list + i; + } + + return fourcc_list + i; + } + } + return NULL; +} + +struct fourcc_list_struct * +paintrect_find_name (const char *name) +{ + int i; + + for (i = 0; i < n_fourccs; i++) { + if (strcmp (name, fourcc_list[i].name) == 0) { + return fourcc_list + i; + } + } + return NULL; +} + + +GstStructure * +paint_get_structure (struct fourcc_list_struct * format) +{ + GstStructure *structure = NULL; + unsigned int fourcc; + int endianness; + + g_return_val_if_fail (format, NULL); + + fourcc = + GST_MAKE_FOURCC (format->fourcc[0], format->fourcc[1], format->fourcc[2], + format->fourcc[3]); + + switch (format->type) { + case VTS_RGB: + if (format->bitspp == 16) { + endianness = G_BYTE_ORDER; + } else { + endianness = G_BIG_ENDIAN; + } + structure = gst_structure_new ("video/x-raw-rgb", + "bpp", G_TYPE_INT, format->bitspp, + "endianness", G_TYPE_INT, endianness, + "depth", G_TYPE_INT, format->depth, + "red_mask", G_TYPE_INT, format->red_mask, + "green_mask", G_TYPE_INT, format->green_mask, + "blue_mask", G_TYPE_INT, format->blue_mask, NULL); + if (format->depth == 32 && format->alpha_mask > 0) { + gst_structure_set (structure, "alpha_mask", G_TYPE_INT, + format->alpha_mask, NULL); + } + break; + case VTS_GRAY: + structure = gst_structure_new ("video/x-raw-gray", + "bpp", G_TYPE_INT, format->bitspp, "depth", G_TYPE_INT, + format->bitspp, NULL); + if (format->bitspp == 16) + gst_structure_set (structure, "endianness", G_TYPE_INT, G_BYTE_ORDER, + NULL); + break; + case VTS_YUV: + { + GValue value_list = { 0 }; + GValue value = { 0 }; + + structure = gst_structure_new ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, fourcc, NULL); + + if (fourcc != GST_STR_FOURCC ("Y800")) { + g_value_init (&value_list, GST_TYPE_LIST); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, "sdtv"); + gst_value_list_append_value (&value_list, &value); + + g_value_set_static_string (&value, "hdtv"); + gst_value_list_append_value (&value_list, &value); + + gst_structure_set_value (structure, "color-matrix", &value_list); + g_value_reset (&value_list); + + if (fourcc != GST_STR_FOURCC ("AYUV") && + fourcc != GST_STR_FOURCC ("v308") && + fourcc != GST_STR_FOURCC ("v410") && + fourcc != GST_STR_FOURCC ("Y444")) { + g_value_set_static_string (&value, "mpeg2"); + gst_value_list_append_value (&value_list, &value); + + g_value_set_static_string (&value, "jpeg"); + gst_value_list_append_value (&value_list, &value); + + gst_structure_set_value (structure, "chroma-site", &value_list); + } + g_value_unset (&value_list); + } + } + break; + case VTS_BAYER: + structure = gst_structure_new ("video/x-raw-bayer", + "format", G_TYPE_STRING, format->fourcc, NULL); + break; + default: + g_assert_not_reached (); + break; + } + return structure; +} + +/* returns the size in bytes for one video frame of the given dimensions + * given the fourcc in GstVideoTestSrc */ +int +gst_video_test_src_get_size (GstVideoTestSrc * v, int w, int h) +{ + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + p->width = w; + p->height = h; + fourcc = v->fourcc; + if (fourcc == NULL) + return 0; + + fourcc->paint_setup (p, NULL); + + return (unsigned long) p->endptr; +} + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ +(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ +(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ +((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ +(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR_709(r, g, b) \ +((FIX(0.212600*219.0/255.0) * (r) + FIX(0.715200*219.0/255.0) * (g) + \ + FIX(0.072200*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR_709(r1, g1, b1, shift)\ +(((- FIX(0.114572*224.0/255.0) * r1 - FIX(0.385427*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR_709(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.454153*224.0/255.0) * g1 - \ + FIX(0.045847*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +static void +videotestsrc_setup_paintinfo (GstVideoTestSrc * v, paintinfo * p, int w, int h) +{ + int a, r, g, b; + + if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) { + p->colors = vts_colors_bt601_ycbcr_100; + } else { + p->colors = vts_colors_bt709_ycbcr_100; + } + p->width = w; + p->height = h; + + p->convert_tmpline = v->fourcc->convert_hline; + if (v->fourcc->type == VTS_RGB || v->fourcc->type == VTS_BAYER) { + p->paint_tmpline = paint_tmpline_ARGB; + } else { + p->paint_tmpline = paint_tmpline_AYUV; + } + p->tmpline = v->tmpline; + p->tmpline2 = v->tmpline2; + p->tmpline_u8 = v->tmpline_u8; + p->x_offset = (v->horizontal_speed * v->n_frames) % p->width; + if (p->x_offset < 0) + p->x_offset += p->width; + + a = (v->foreground_color >> 24) & 0xff; + r = (v->foreground_color >> 16) & 0xff; + g = (v->foreground_color >> 8) & 0xff; + b = (v->foreground_color >> 0) & 0xff; + p->foreground_color.A = a; + p->foreground_color.R = r; + p->foreground_color.G = g; + p->foreground_color.B = b; + if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) { + p->foreground_color.Y = RGB_TO_Y_CCIR (r, g, b); + p->foreground_color.U = RGB_TO_U_CCIR (r, g, b, 0); + p->foreground_color.V = RGB_TO_V_CCIR (r, g, b, 0); + } else { + p->foreground_color.Y = RGB_TO_Y_CCIR_709 (r, g, b); + p->foreground_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0); + p->foreground_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0); + } + p->foreground_color.gray = RGB_TO_Y (r, g, b); + + a = (v->background_color >> 24) & 0xff; + r = (v->background_color >> 16) & 0xff; + g = (v->background_color >> 8) & 0xff; + b = (v->background_color >> 0) & 0xff; + p->background_color.A = a; + p->background_color.R = r; + p->background_color.G = g; + p->background_color.B = b; + if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) { + p->background_color.Y = RGB_TO_Y_CCIR (r, g, b); + p->background_color.U = RGB_TO_U_CCIR (r, g, b, 0); + p->background_color.V = RGB_TO_V_CCIR (r, g, b, 0); + } else { + p->background_color.Y = RGB_TO_Y_CCIR_709 (r, g, b); + p->background_color.U = RGB_TO_U_CCIR_709 (r, g, b, 0); + p->background_color.V = RGB_TO_V_CCIR_709 (r, g, b, 0); + } + p->background_color.gray = RGB_TO_Y (r, g, b); + +} + +static void +videotestsrc_convert_tmpline (paintinfo * p, int j) +{ + int x = p->x_offset; + int i; + + if (x != 0) { + memcpy (p->tmpline2, p->tmpline, p->width * 4); + memcpy (p->tmpline, p->tmpline2 + x * 4, (p->width - x) * 4); + memcpy (p->tmpline + (p->width - x) * 4, p->tmpline2, x * 4); + } + + for (i = p->width; i < p->width + 5; i++) { + p->tmpline[4 * i + 0] = p->tmpline[4 * (p->width - 1) + 0]; + p->tmpline[4 * i + 1] = p->tmpline[4 * (p->width - 1) + 1]; + p->tmpline[4 * i + 2] = p->tmpline[4 * (p->width - 1) + 2]; + p->tmpline[4 * i + 3] = p->tmpline[4 * (p->width - 1) + 3]; + } + + p->convert_tmpline (p, j); +} + +#define BLEND1(a,b,x) ((a)*(x) + (b)*(255-(x))) +#define DIV255(x) (((x) + (((x)+128)>>8) + 128)>>8) +#define BLEND(a,b,x) DIV255(BLEND1(a,b,x)) + +#ifdef unused +static void +videotestsrc_blend_color (struct vts_color_struct *dest, + struct vts_color_struct *a, struct vts_color_struct *b, int x) +{ + dest->Y = BLEND (a->Y, b->Y, x); + dest->U = BLEND (a->U, b->U, x); + dest->V = BLEND (a->V, b->V, x); + dest->R = BLEND (a->R, b->R, x); + dest->G = BLEND (a->G, b->G, x); + dest->B = BLEND (a->B, b->B, x); + dest->gray = BLEND (a->gray, b->gray, x); + +} +#endif + +static void +videotestsrc_blend_line (GstVideoTestSrc * v, guint8 * dest, guint8 * src, + struct vts_color_struct *a, struct vts_color_struct *b, int n) +{ + int i; + if (v->fourcc->type == VTS_RGB || v->fourcc->type == VTS_BAYER) { + for (i = 0; i < n; i++) { + dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]); + dest[i * 4 + 1] = BLEND (a->R, b->R, src[i]); + dest[i * 4 + 2] = BLEND (a->G, b->G, src[i]); + dest[i * 4 + 3] = BLEND (a->B, b->B, src[i]); + } + } else { + for (i = 0; i < n; i++) { + dest[i * 4 + 0] = BLEND (a->A, b->A, src[i]); + dest[i * 4 + 1] = BLEND (a->Y, b->Y, src[i]); + dest[i * 4 + 2] = BLEND (a->U, b->U, src[i]); + dest[i * 4 + 3] = BLEND (a->V, b->V, src[i]); + } + } +#undef BLEND +} + +void +gst_video_test_src_smpte (GstVideoTestSrc * v, unsigned char *dest, int w, + int h) +{ + int i; + int y1, y2; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + y1 = 2 * h / 3; + y2 = h * 0.75; + + /* color bars */ + for (j = 0; j < y1; j++) { + for (i = 0; i < 7; i++) { + int x1 = i * w / 7; + int x2 = (i + 1) * w / 7; + + p->color = p->colors + i; + p->paint_tmpline (p, x1, (x2 - x1)); + } + videotestsrc_convert_tmpline (p, j); + } + + /* inverse blue bars */ + for (j = y1; j < y2; j++) { + for (i = 0; i < 7; i++) { + int x1 = i * w / 7; + int x2 = (i + 1) * w / 7; + int k; + + if (i & 1) { + k = 7; + } else { + k = 6 - i; + } + p->color = p->colors + k; + p->paint_tmpline (p, x1, (x2 - x1)); + } + videotestsrc_convert_tmpline (p, j); + } + + for (j = y2; j < h; j++) { + /* -I, white, Q regions */ + for (i = 0; i < 3; i++) { + int x1 = i * w / 6; + int x2 = (i + 1) * w / 6; + int k; + + if (i == 0) { + k = 8; + } else if (i == 1) { + k = 0; + } else + k = 9; + + p->color = p->colors + k; + p->paint_tmpline (p, x1, (x2 - x1)); + } + + /* superblack, black, dark grey */ + for (i = 0; i < 3; i++) { + int x1 = w / 2 + i * w / 12; + int x2 = w / 2 + (i + 1) * w / 12; + int k; + + if (i == 0) { + k = COLOR_SUPER_BLACK; + } else if (i == 1) { + k = COLOR_BLACK; + } else + k = COLOR_DARK_GREY; + + p->color = p->colors + k; + p->paint_tmpline (p, x1, (x2 - x1)); + } + + { + int x1 = w * 3 / 4; + struct vts_color_struct color; + + color = p->colors[COLOR_BLACK]; + p->color = &color; + + for (i = x1; i < w; i++) { + int y = random_char (); + p->tmpline_u8[i] = y; + } + videotestsrc_blend_line (v, p->tmpline + x1 * 4, p->tmpline_u8 + x1, + &p->foreground_color, &p->background_color, w - x1); + + } + videotestsrc_convert_tmpline (p, j); + + } +} + +void +gst_video_test_src_smpte75 (GstVideoTestSrc * v, unsigned char *dest, int w, + int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + if (v->color_spec == GST_VIDEO_TEST_SRC_BT601) { + p->colors = vts_colors_bt601_ycbcr_75; + } else { + p->colors = vts_colors_bt709_ycbcr_75; + } + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + /* color bars */ + for (j = 0; j < h; j++) { + for (i = 0; i < 7; i++) { + int x1 = i * w / 7; + int x2 = (i + 1) * w / 7; + + p->color = p->colors + i; + p->paint_tmpline (p, x1, (x2 - x1)); + } + videotestsrc_convert_tmpline (p, j); + } +} + +void +gst_video_test_src_smpte100 (GstVideoTestSrc * v, unsigned char *dest, int w, + int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + /* color bars */ + for (j = 0; j < h; j++) { + for (i = 0; i < 7; i++) { + int x1 = i * w / 7; + int x2 = (i + 1) * w / 7; + + p->color = p->colors + i; + p->paint_tmpline (p, x1, (x2 - x1)); + } + videotestsrc_convert_tmpline (p, j); + } +} + +void +gst_video_test_src_bar (GstVideoTestSrc * v, unsigned char *dest, int w, int h) +{ + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (j = 0; j < h; j++) { + /* use fixed size for now */ + int x2 = w / 7; + + p->color = &p->foreground_color; + p->paint_tmpline (p, 0, x2); + p->color = &p->background_color; + p->paint_tmpline (p, x2, (w - x2)); + videotestsrc_convert_tmpline (p, j); + } +} + +void +gst_video_test_src_snow (GstVideoTestSrc * v, unsigned char *dest, int w, int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct color; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + color = p->colors[COLOR_BLACK]; + p->color = &color; + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + int y = random_char (); + p->tmpline_u8[i] = y; + } + videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8, + &p->foreground_color, &p->background_color, p->width); + videotestsrc_convert_tmpline (p, j); + } +} + +static void +gst_video_test_src_unicolor (GstVideoTestSrc * v, unsigned char *dest, int w, + int h, int color_index) +{ + int i; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + p->color = p->colors + color_index; + if (color_index == COLOR_BLACK) { + p->color = &p->background_color; + } + if (color_index == COLOR_WHITE) { + p->color = &p->foreground_color; + } + + for (i = 0; i < h; i++) { + p->paint_tmpline (p, 0, w); + videotestsrc_convert_tmpline (p, i); + } +} + +void +gst_video_test_src_black (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + gst_video_test_src_unicolor (v, dest, w, h, COLOR_BLACK); +} + +void +gst_video_test_src_white (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + gst_video_test_src_unicolor (v, dest, w, h, COLOR_WHITE); +} + +void +gst_video_test_src_red (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + gst_video_test_src_unicolor (v, dest, w, h, COLOR_RED); +} + +void +gst_video_test_src_green (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + gst_video_test_src_unicolor (v, dest, w, h, COLOR_GREEN); +} + +void +gst_video_test_src_blue (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + gst_video_test_src_unicolor (v, dest, w, h, COLOR_BLUE); +} + +void +gst_video_test_src_blink (GstVideoTestSrc * v, unsigned char *dest, int w, + int h) +{ + int i; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + if (v->n_frames & 1) { + p->color = &p->foreground_color; + } else { + p->color = &p->background_color; + } + + for (i = 0; i < h; i++) { + p->paint_tmpline (p, 0, w); + videotestsrc_convert_tmpline (p, i); + } +} + +void +gst_video_test_src_solid (GstVideoTestSrc * v, unsigned char *dest, int w, + int h) +{ + int i; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + p->color = &p->foreground_color; + + for (i = 0; i < h; i++) { + p->paint_tmpline (p, 0, w); + videotestsrc_convert_tmpline (p, i); + } +} + +void +gst_video_test_src_checkers1 (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++) { + if ((x ^ y) & 1) { + p->color = p->colors + COLOR_GREEN; + } else { + p->color = p->colors + COLOR_RED; + } + p->paint_tmpline (p, x, 1); + } + videotestsrc_convert_tmpline (p, y); + } +} + +void +gst_video_test_src_checkers2 (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x += 2) { + guint len = MIN (2, w - x); + + if ((x ^ y) & 2) { + p->color = p->colors + COLOR_GREEN; + } else { + p->color = p->colors + COLOR_RED; + } + p->paint_tmpline (p, x, len); + } + videotestsrc_convert_tmpline (p, y); + } +} + +void +gst_video_test_src_checkers4 (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x += 4) { + guint len = MIN (4, w - x); + + if ((x ^ y) & 4) { + p->color = p->colors + COLOR_GREEN; + } else { + p->color = p->colors + COLOR_RED; + } + p->paint_tmpline (p, x, len); + } + videotestsrc_convert_tmpline (p, y); + } +} + +void +gst_video_test_src_checkers8 (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x += 8) { + guint len = MIN (8, w - x); + + if ((x ^ y) & 8) { + p->color = p->colors + COLOR_GREEN; + } else { + p->color = p->colors + COLOR_RED; + } + p->paint_tmpline (p, x, len); + } + videotestsrc_convert_tmpline (p, y); + } +} + +static const guint8 sine_table[256] = { + 128, 131, 134, 137, 140, 143, 146, 149, + 152, 156, 159, 162, 165, 168, 171, 174, + 176, 179, 182, 185, 188, 191, 193, 196, + 199, 201, 204, 206, 209, 211, 213, 216, + 218, 220, 222, 224, 226, 228, 230, 232, + 234, 236, 237, 239, 240, 242, 243, 245, + 246, 247, 248, 249, 250, 251, 252, 252, + 253, 254, 254, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 254, 254, + 253, 252, 252, 251, 250, 249, 248, 247, + 246, 245, 243, 242, 240, 239, 237, 236, + 234, 232, 230, 228, 226, 224, 222, 220, + 218, 216, 213, 211, 209, 206, 204, 201, + 199, 196, 193, 191, 188, 185, 182, 179, + 176, 174, 171, 168, 165, 162, 159, 156, + 152, 149, 146, 143, 140, 137, 134, 131, + 128, 124, 121, 118, 115, 112, 109, 106, + 103, 99, 96, 93, 90, 87, 84, 81, + 79, 76, 73, 70, 67, 64, 62, 59, + 56, 54, 51, 49, 46, 44, 42, 39, + 37, 35, 33, 31, 29, 27, 25, 23, + 21, 19, 18, 16, 15, 13, 12, 10, + 9, 8, 7, 6, 5, 4, 3, 3, + 2, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 1, + 2, 3, 3, 4, 5, 6, 7, 8, + 9, 10, 12, 13, 15, 16, 18, 19, + 21, 23, 25, 27, 29, 31, 33, 35, + 37, 39, 42, 44, 46, 49, 51, 54, + 56, 59, 62, 64, 67, 70, 73, 76, + 79, 81, 84, 87, 90, 93, 96, 99, + 103, 106, 109, 112, 115, 118, 121, 124 +}; + + +void +gst_video_test_src_zoneplate (GstVideoTestSrc * v, unsigned char *dest, + int w, int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct color; + int t = v->n_frames; + int xreset = -(w / 2) - v->xoffset; /* starting values for x^2 and y^2, centering the ellipse */ + int yreset = -(h / 2) - v->yoffset; + + int x, y; + int accum_kx; + int accum_kxt; + int accum_ky; + int accum_kyt; + int accum_kxy; + int kt; + int kt2; + int ky2; + int delta_kxt = v->kxt * t; + int delta_kxy; + int scale_kxy = 0xffff / (w / 2); + int scale_kx2 = 0xffff / w; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + color = p->colors[COLOR_BLACK]; + p->color = &color; + + /* Zoneplate equation: + * + * phase = k0 + kx*x + ky*y + kt*t + * + kxt*x*t + kyt*y*t + kxy*x*y + * + kx2*x*x + ky2*y*y + Kt2*t*t + */ + +#if 0 + for (j = 0, y = yreset; j < h; j++, y++) { + for (i = 0, x = xreset; i < w; i++, x++) { + + /* zero order */ + int phase = v->k0; + + /* first order */ + phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); + + /* cross term */ + /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */ + /* phase = phase + (v->kxy * x * y) / (w/2); */ + + /*second order */ + /*normalise x/y terms to rate of change of phase at the picture edge */ + phase = + phase + ((v->kx2 * x * x) / w) + ((v->ky2 * y * y) / h) + + ((v->kt2 * t * t) >> 1); + + color.Y = sine_table[phase & 0xff]; + + color.R = color.Y; + color.G = color.Y; + color.B = color.Y; + p->paint_tmpline (p, i, 1); + } + } +#endif + + /* optimised version, with original code shown in comments */ + accum_ky = 0; + accum_kyt = 0; + kt = v->kt * t; + kt2 = v->kt2 * t * t; + for (j = 0, y = yreset; j < h; j++, y++) { + accum_kx = 0; + accum_kxt = 0; + accum_ky += v->ky; + accum_kyt += v->kyt * t; + delta_kxy = v->kxy * y * scale_kxy; + accum_kxy = delta_kxy * xreset; + ky2 = (v->ky2 * y * y) / h; + for (i = 0, x = xreset; i < w; i++, x++) { + + /* zero order */ + int phase = v->k0; + + /* first order */ + accum_kx += v->kx; + /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */ + phase = phase + accum_kx + accum_ky + kt; + + /* cross term */ + accum_kxt += delta_kxt; + accum_kxy += delta_kxy; + /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */ + phase = phase + accum_kxt + accum_kyt; + + /* phase = phase + (v->kxy * x * y) / (w/2); */ + /* phase = phase + accum_kxy / (w/2); */ + phase = phase + (accum_kxy >> 16); + + /*second order */ + /*normalise x/y terms to rate of change of phase at the picture edge */ + /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */ + phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1); + + p->tmpline_u8[i] = sine_table[phase & 0xff]; + } + videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8, + &p->foreground_color, &p->background_color, p->width); + videotestsrc_convert_tmpline (p, j); + } +} + +void +gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, unsigned char *dest, + int w, int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct color; + int t = v->n_frames; + + int xreset = -(w / 2) - v->xoffset; /* starting values for x^2 and y^2, centering the ellipse */ + int yreset = -(h / 2) - v->yoffset; + + int x, y; + int accum_kx; + int accum_kxt; + int accum_ky; + int accum_kyt; + int accum_kxy; + int kt; + int kt2; + int ky2; + int delta_kxt = v->kxt * t; + int delta_kxy; + int scale_kxy = 0xffff / (w / 2); + int scale_kx2 = 0xffff / w; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + color = p->colors[COLOR_BLACK]; + p->color = &color; + + /* Zoneplate equation: + * + * phase = k0 + kx*x + ky*y + kt*t + * + kxt*x*t + kyt*y*t + kxy*x*y + * + kx2*x*x + ky2*y*y + Kt2*t*t + */ + + /* optimised version, with original code shown in comments */ + accum_ky = 0; + accum_kyt = 0; + kt = v->kt * t; + kt2 = v->kt2 * t * t; + for (j = 0, y = yreset; j < h; j++, y++) { + accum_kx = 0; + accum_kxt = 0; + accum_ky += v->ky; + accum_kyt += v->kyt * t; + delta_kxy = v->kxy * y * scale_kxy; + accum_kxy = delta_kxy * xreset; + ky2 = (v->ky2 * y * y) / h; + for (i = 0, x = xreset; i < w; i++, x++) { + + /* zero order */ + int phase = v->k0; + + /* first order */ + accum_kx += v->kx; + /* phase = phase + (v->kx * i) + (v->ky * j) + (v->kt * t); */ + phase = phase + accum_kx + accum_ky + kt; + + /* cross term */ + accum_kxt += delta_kxt; + accum_kxy += delta_kxy; + /* phase = phase + (v->kxt * i * t) + (v->kyt * j * t); */ + phase = phase + accum_kxt + accum_kyt; + + /* phase = phase + (v->kxy * x * y) / (w/2); */ + /* phase = phase + accum_kxy / (w/2); */ + phase = phase + (accum_kxy >> 16); + + /*second order */ + /*normalise x/y terms to rate of change of phase at the picture edge */ + /*phase = phase + ((v->kx2 * x * x)/w) + ((v->ky2 * y * y)/h) + ((v->kt2 * t * t)>>1); */ + phase = phase + ((v->kx2 * x * x * scale_kx2) >> 16) + ky2 + (kt2 >> 1); + + color.Y = 128; + color.U = sine_table[phase & 0xff]; + color.V = sine_table[phase & 0xff]; + + color.R = 128; + color.G = 128; + color.B = color.V; + + color.gray = color.Y << 8; + p->paint_tmpline (p, i, 1); + } + videotestsrc_convert_tmpline (p, j); + } +} + +#undef SCALE_AMPLITUDE +void +gst_video_test_src_circular (GstVideoTestSrc * v, unsigned char *dest, + int w, int h) +{ + int i; + int j; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + double freq[8]; + + int d; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (i = 1; i < 8; i++) { + freq[i] = 200 * pow (2.0, -(i - 1) / 4.0); + } + + for (j = 0; j < h; j++) { + for (i = 0; i < w; i++) { + double dist; + int seg; + + dist = + sqrt ((2 * i - w) * (2 * i - w) + (2 * j - h) * (2 * j - + h)) / (2 * w); + seg = floor (dist * 16); + if (seg == 0 || seg >= 8) { + p->tmpline_u8[i] = 0; + } else { + d = floor (256 * dist * freq[seg] + 0.5); + p->tmpline_u8[i] = sine_table[d & 0xff]; + } + } + videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8, + &p->foreground_color, &p->background_color, p->width); + videotestsrc_convert_tmpline (p, j); + } +} + +void +gst_video_test_src_gamut (GstVideoTestSrc * v, guchar * dest, int w, int h) +{ + int x, y; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + struct vts_color_struct yuv_primary; + struct vts_color_struct yuv_secondary; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + for (y = 0; y < h; y++) { + int region = (y * 4) / h; + + switch (region) { + case 0: /* black */ + yuv_primary = p->colors[COLOR_BLACK]; + yuv_secondary = p->colors[COLOR_BLACK]; + yuv_secondary.Y = 0; + break; + case 1: + yuv_primary = p->colors[COLOR_WHITE]; + yuv_secondary = p->colors[COLOR_WHITE]; + yuv_secondary.Y = 255; + break; + case 2: + yuv_primary = p->colors[COLOR_RED]; + yuv_secondary = p->colors[COLOR_RED]; + yuv_secondary.V = 255; + break; + case 3: + yuv_primary = p->colors[COLOR_BLUE]; + yuv_secondary = p->colors[COLOR_BLUE]; + yuv_secondary.U = 255; + break; + } + + for (x = 0; x < w; x += 8) { + int len = MIN (8, w - x); + + if ((x ^ y) & (1 << 4)) { + p->color = &yuv_primary; + } else { + p->color = &yuv_secondary; + } + p->paint_tmpline (p, x, len); + } + videotestsrc_convert_tmpline (p, y); + } +} + +void +gst_video_test_src_ball (GstVideoTestSrc * v, unsigned char *dest, int w, int h) +{ + int i; + paintinfo pi = { NULL, }; + paintinfo *p = π + struct fourcc_list_struct *fourcc; + int t = v->n_frames; + double x, y; + int radius = 20; + + videotestsrc_setup_paintinfo (v, p, w, h); + fourcc = v->fourcc; + if (fourcc == NULL) + return; + + fourcc->paint_setup (p, dest); + + x = radius + (0.5 + 0.5 * sin (2 * M_PI * t / 200)) * (w - 2 * radius); + y = radius + (0.5 + 0.5 * sin (2 * M_PI * sqrt (2) * t / 200)) * (h - + 2 * radius); + + for (i = 0; i < h; i++) { + if (i < y - radius || i > y + radius) { + memset (p->tmpline_u8, 0, w); + } else { + int r = rint (sqrt (radius * radius - (i - y) * (i - y))); + int x1, x2; + int j; + + x1 = 0; + x2 = MAX (0, x - r); + for (j = x1; j < x2; j++) { + p->tmpline_u8[j] = 0; + } + + x1 = MAX (0, x - r); + x2 = MIN (w, x + r + 1); + for (j = x1; j < x2; j++) { + double rr = radius - sqrt ((j - x) * (j - x) + (i - y) * (i - y)); + + rr *= 0.5; + p->tmpline_u8[j] = CLAMP ((int) floor (256 * rr), 0, 255); + } + + x1 = MIN (w, x + r + 1); + x2 = w; + for (j = x1; j < x2; j++) { + p->tmpline_u8[j] = 0; + } + } + videotestsrc_blend_line (v, p->tmpline, p->tmpline_u8, + &p->foreground_color, &p->background_color, p->width); + videotestsrc_convert_tmpline (p, i); + } +} + +static void +paint_tmpline_ARGB (paintinfo * p, int x, int w) +{ + int offset; + guint32 value; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + value = (p->color->A << 0) | (p->color->R << 8) | + (p->color->G << 16) | (p->color->B << 24); +#else + value = (p->color->A << 24) | (p->color->R << 16) | + (p->color->G << 8) | (p->color->B << 0); +#endif + + offset = (x * 4); + gst_orc_splat_u32 (p->tmpline + offset, value, w); +} + +static void +paint_tmpline_AYUV (paintinfo * p, int x, int w) +{ + int offset; + guint32 value; + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + value = (p->color->A << 0) | (p->color->Y << 8) | + (p->color->U << 16) | (p->color->V << 24); +#else + value = (p->color->A << 24) | (p->color->Y << 16) | + (p->color->U << 8) | (p->color->V << 0); +#endif + + offset = (x * 4); + gst_orc_splat_u32 (p->tmpline + offset, value, w); +} + + +static void +paint_setup_I420 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->ustride = GST_ROUND_UP_8 (p->width) / 2; + p->vp = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2; + p->vstride = GST_ROUND_UP_8 (p->ystride) / 2; + p->endptr = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2; +} + +static void +paint_setup_NV12 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->vp = p->up + 1; + p->ustride = p->ystride; + p->vstride = p->ystride; + p->endptr = p->up + (p->ystride * GST_ROUND_UP_2 (p->height)) / 2; +} + +static void +paint_setup_NV21 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->up = p->vp + 1; + p->ustride = p->ystride; + p->vstride = p->ystride; + p->endptr = p->vp + (p->ystride * GST_ROUND_UP_2 (p->height)) / 2; +} + +static void +convert_hline_I420 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + (y / 2) * p->ustride; + guint8 *V = p->vp + (y / 2) * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 1) / 2; i++) { + U[i] = (ayuv[4 * (i * 2) + 2] + ayuv[4 * (i * 2 + 1) + 2] + 1) >> 1; + V[i] = (ayuv[4 * (i * 2) + 3] + ayuv[4 * (i * 2 + 1) + 3] + 1) >> 1; + } +} + +static void +convert_hline_NV12 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + (y / 2) * p->ustride; + guint8 *V = p->vp + (y / 2) * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 1) / 2; i++) { + U[i * 2] = (ayuv[4 * (i * 2) + 2] + ayuv[4 * (i * 2 + 1) + 2] + 1) >> 1; + V[i * 2] = (ayuv[4 * (i * 2) + 3] + ayuv[4 * (i * 2 + 1) + 3] + 1) >> 1; + } +} + +static void +convert_hline_NV21 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + (y / 2) * p->ustride; + guint8 *V = p->vp + (y / 2) * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 1) / 2; i++) { + U[i * 2] = (ayuv[4 * (i * 2) + 2] + ayuv[4 * (i * 2 + 1) + 2] + 1) >> 1; + V[i * 2] = (ayuv[4 * (i * 2) + 3] + ayuv[4 * (i * 2 + 1) + 3] + 1) >> 1; + } +} + + +static void +paint_setup_YV12 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->vstride = GST_ROUND_UP_8 (p->ystride) / 2; + p->up = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2; + p->ustride = GST_ROUND_UP_8 (p->ystride) / 2; + p->endptr = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2; +} + +static void +paint_setup_v308 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + 1; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_4 (p->width * 3); + p->ustride = GST_ROUND_UP_4 (p->width * 3); + p->vstride = GST_ROUND_UP_4 (p->width * 3); + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_AYUV (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 1; + p->up = dest + 2; + p->vp = dest + 3; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = dest + p->ystride * p->height; +} + +#ifdef disabled +static void +paint_setup_v410 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 0; + p->up = dest + 0; + p->vp = dest + 0; + p->ystride = p->width * 4; + p->endptr = dest + p->ystride * p->height; +} +#endif + +static void +paint_setup_v216 (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 2; + p->up = dest + 0; + p->vp = dest + 4; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_v210 (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 0; + p->up = dest + 0; + p->vp = dest + 0; + p->ystride = ((p->width + 47) / 48) * 128; /* no, really. */ + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_UYVP (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 0; + p->up = dest + 0; + p->vp = dest + 0; + p->ystride = GST_ROUND_UP_4 ((p->width * 2 * 5 + 3) / 4); + GST_ERROR ("stride %d", p->ystride); + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_YUY2 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + 1; + p->vp = dest + 3; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->ustride = GST_ROUND_UP_2 (p->width) * 2; + p->vstride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_UYVY (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 1; + p->up = dest; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->ustride = GST_ROUND_UP_2 (p->width) * 2; + p->vstride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_YVYU (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + 3; + p->vp = dest + 1; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->ustride = GST_ROUND_UP_2 (p->width) * 2; + p->vstride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_AY64 (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 2; + p->up = dest + 4; + p->vp = dest + 6; + p->ystride = p->width * 8; + p->ustride = p->width * 8; + p->vstride = p->width * 8; + p->endptr = dest + p->ystride * p->height; +} + +static void +convert_hline_v308 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i * 3] = ayuv[4 * i + 1]; + U[i * 3] = ayuv[4 * i + 2]; + V[i * 3] = ayuv[4 * i + 3]; + } +} + +static void +convert_hline_AYUV (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *A = p->ap + y * p->ystride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + A[i * 4] = ayuv[4 * i + 0]; + Y[i * 4] = ayuv[4 * i + 1]; + U[i * 4] = ayuv[4 * i + 2]; + V[i * 4] = ayuv[4 * i + 3]; + } +} + +static void +convert_hline_v216 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + GST_WRITE_UINT16_LE (Y + i * 4, TO_16 (ayuv[4 * i + 1])); + } + for (i = 0; i < (p->width + 1) / 2; i++) { + GST_WRITE_UINT16_LE (U + i * 8, TO_16 (ayuv[4 * (i * 2) + 2])); + GST_WRITE_UINT16_LE (V + i * 8, TO_16 (ayuv[4 * (i * 2) + 3])); + } +} + +#ifdef disabled +static void +convert_hline_v410 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + guint32 a; + + a = (TO_10 (ayuv[4 * i + 2]) << 22) | + (TO_10 (ayuv[4 * i + 1]) << 12) | (TO_10 (ayuv[4 * i + 3]) << 2); + GST_WRITE_UINT32_LE (Y + i * 4, a); + } +} +#endif + +static void +convert_hline_v210 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width + 5; i += 6) { + guint32 a0, a1, a2, a3; + guint16 y0, y1, y2, y3, y4, y5; + guint16 u0, u1, u2; + guint16 v0, v1, v2; + + y0 = ayuv[4 * (i + 0) + 1]; + y1 = ayuv[4 * (i + 1) + 1]; + y2 = ayuv[4 * (i + 2) + 1]; + y3 = ayuv[4 * (i + 3) + 1]; + y4 = ayuv[4 * (i + 4) + 1]; + y5 = ayuv[4 * (i + 5) + 1]; + + u0 = (ayuv[4 * (i + 0) + 2] + ayuv[4 * (i + 1) + 2] + 1) >> 1; + u1 = (ayuv[4 * (i + 2) + 2] + ayuv[4 * (i + 3) + 2] + 1) >> 1; + u2 = (ayuv[4 * (i + 4) + 2] + ayuv[4 * (i + 5) + 2] + 1) >> 1; + + v0 = (ayuv[4 * (i + 0) + 3] + ayuv[4 * (i + 1) + 3] + 1) >> 1; + v1 = (ayuv[4 * (i + 2) + 3] + ayuv[4 * (i + 3) + 3] + 1) >> 1; + v2 = (ayuv[4 * (i + 4) + 3] + ayuv[4 * (i + 5) + 3] + 1) >> 1; + +#if 0 + a0 = TO_10 (ayuv[4 * (i + 0) + 2]) | (TO_10 (ayuv[4 * (i + 0) + 1]) << 10) + | (TO_10 (ayuv[4 * (i + 0) + 3]) << 20); + a1 = TO_10 (ayuv[4 * (i + 1) + 1]) | (TO_10 (ayuv[4 * (i + 2) + 2]) << 10) + | (TO_10 (ayuv[4 * (i + 2) + 1]) << 20); + a2 = TO_10 (ayuv[4 * (i + 2) + 3]) | (TO_10 (ayuv[4 * (i + 3) + 1]) << 10) + | (TO_10 (ayuv[4 * (i + 4) + 2]) << 20); + a3 = TO_10 (ayuv[4 * (i + 4) + 1]) | (TO_10 (ayuv[4 * (i + 4) + 3]) << 10) + | (TO_10 (ayuv[4 * (i + 5) + 1]) << 20); +#endif + + a0 = TO_10 (u0) | (TO_10 (y0) << 10) | (TO_10 (v0) << 20); + a1 = TO_10 (y1) | (TO_10 (u1) << 10) | (TO_10 (y2) << 20); + a2 = TO_10 (v1) | (TO_10 (y3) << 10) | (TO_10 (u2) << 20); + a3 = TO_10 (y4) | (TO_10 (v2) << 10) | (TO_10 (y5) << 20); + + GST_WRITE_UINT32_LE (Y + (i / 6) * 16 + 0, a0); + GST_WRITE_UINT32_LE (Y + (i / 6) * 16 + 4, a1); + GST_WRITE_UINT32_LE (Y + (i / 6) * 16 + 8, a2); + GST_WRITE_UINT32_LE (Y + (i / 6) * 16 + 12, a3); + } +} + +static void +convert_hline_UYVP (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i += 2) { + guint16 y0, y1; + guint16 u0; + guint16 v0; + + y0 = ayuv[4 * (i + 0) + 1]; + y1 = ayuv[4 * (i + 1) + 1]; + u0 = (ayuv[4 * (i + 0) + 2] + ayuv[4 * (i + 1) + 2] + 1) >> 1; + v0 = (ayuv[4 * (i + 0) + 3] + ayuv[4 * (i + 1) + 3] + 1) >> 1; + + Y[(i / 2) * 5 + 0] = u0; + Y[(i / 2) * 5 + 1] = y0 >> 2; + Y[(i / 2) * 5 + 2] = (y0 << 6) | (v0 >> 4); + Y[(i / 2) * 5 + 3] = (v0 << 4) | (y1 >> 2); + Y[(i / 2) * 5 + 4] = (y1 << 2); + } +} + +static void +convert_hline_YUY2 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i * 2] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 1) / 2; i++) { + U[4 * i] = (ayuv[4 * (i * 2) + 2] + ayuv[4 * (i * 2 + 1) + 2] + 1) >> 1; + V[4 * i] = (ayuv[4 * (i * 2) + 3] + ayuv[4 * (i * 2 + 1) + 3] + 1) >> 1; + } +} + +static void +convert_hline_AY64 (paintinfo * p, int y) +{ + int i; + guint16 *ayuv16 = (guint16 *) (p->ap + y * p->ystride); + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + GST_WRITE_UINT16_LE (ayuv16 + i * 4 + 0, TO_16 (ayuv[4 * i + 0])); + GST_WRITE_UINT16_LE (ayuv16 + i * 4 + 1, TO_16 (ayuv[4 * i + 1])); + GST_WRITE_UINT16_LE (ayuv16 + i * 4 + 2, TO_16 (ayuv[4 * i + 2])); + GST_WRITE_UINT16_LE (ayuv16 + i * 4 + 3, TO_16 (ayuv[4 * i + 3])); + } +} + +#ifdef disabled +static void +paint_setup_IYU2 (paintinfo * p, unsigned char *dest) +{ + /* untested */ + p->yp = dest + 1; + p->up = dest + 0; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_4 (p->width * 3); + p->endptr = dest + p->ystride * p->height; +} + +static void +convert_hline_IYU2 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i * 3] = ayuv[4 * i + 1]; + U[i * 3] = ayuv[4 * i + 2]; + V[i * 3] = ayuv[4 * i + 3]; + } +} +#endif + +static void +paint_setup_Y41B (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->ustride = GST_ROUND_UP_16 (p->width) / 4; + p->vp = p->up + p->ustride * p->height; + p->vstride = GST_ROUND_UP_16 (p->width) / 4; + p->endptr = p->vp + p->vstride * p->height; +} + +static void +convert_hline_Y41B (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 3) / 4; i++) { + U[i] = (ayuv[4 * (i * 4) + 2] + ayuv[4 * (i * 4 + 1) + 2] + + ayuv[4 * (i * 4 + 2) + 2] + ayuv[4 * (i * 4 + 3) + 2] + 2) >> 2; + V[i] = (ayuv[4 * (i * 4) + 3] + ayuv[4 * (i * 4 + 1) + 3] + + ayuv[4 * (i * 4 + 2) + 3] + ayuv[4 * (i * 4 + 3) + 3] + 2) >> 2; + } +} + +static void +paint_setup_Y42B (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->ustride = GST_ROUND_UP_8 (p->width) / 2; + p->vp = p->up + p->ustride * p->height; + p->vstride = GST_ROUND_UP_8 (p->width) / 2; + p->endptr = p->vp + p->vstride * p->height; +} + +static void +convert_hline_Y42B (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 1) / 2; i++) { + U[i] = (ayuv[4 * (i * 2) + 2] + ayuv[4 * (i * 2 + 1) + 2] + 1) >> 1; + V[i] = (ayuv[4 * (i * 2) + 3] + ayuv[4 * (i * 2 + 1) + 3] + 1) >> 1; + } +} + +static void +paint_setup_Y444 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->ustride = GST_ROUND_UP_4 (p->width); + p->vstride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->vp = p->up + p->ystride * p->height; + p->endptr = p->vp + p->ystride * p->height; +} + +static void +convert_hline_Y444 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + y * p->ustride; + guint8 *V = p->vp + y * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + U[i] = ayuv[4 * i + 2]; + V[i] = ayuv[4 * i + 3]; + } +} + +static void +paint_setup_Y800 (paintinfo * p, unsigned char *dest) +{ + /* untested */ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->endptr = dest + p->ystride * p->height; +} + +static void +convert_hline_Y800 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } +} + +static void +paint_setup_YVU9 (paintinfo * p, unsigned char *dest) +{ + int h = GST_ROUND_UP_4 (p->height); + + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->vp = p->yp + p->ystride * h; + p->vstride = GST_ROUND_UP_4 (p->ystride / 4); + p->up = p->vp + p->vstride * h / 4; + p->ustride = GST_ROUND_UP_4 (p->ystride / 4); + p->endptr = p->up + p->ustride * h / 4; +} + +static void +paint_setup_YUV9 (paintinfo * p, unsigned char *dest) +{ + /* untested */ + int h = GST_ROUND_UP_4 (p->height); + + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * h; + p->ustride = GST_ROUND_UP_4 (p->ystride / 4); + p->vp = p->up + p->ustride * h / 4; + p->vstride = GST_ROUND_UP_4 (p->ystride / 4); + p->endptr = p->vp + p->vstride * h / 4; +} + +static void +convert_hline_YUV9 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *U = p->up + (y / 4) * p->ustride; + guint8 *V = p->vp + (y / 4) * p->vstride; + guint8 *ayuv = p->tmpline; + + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } + for (i = 0; i < (p->width + 3) / 4; i++) { + U[i] = (ayuv[4 * (i * 4) + 2] + ayuv[4 * (i * 4 + 1) + 2] + + ayuv[4 * (i * 4 + 2) + 2] + ayuv[4 * (i * 4 + 3) + 2] + 2) >> 2; + V[i] = (ayuv[4 * (i * 4) + 3] + ayuv[4 * (i * 4 + 1) + 3] + + ayuv[4 * (i * 4 + 2) + 3] + ayuv[4 * (i * 4 + 3) + 3] + 2) >> 2; + } +} + +static void +paint_setup_ARGB8888 (paintinfo * p, unsigned char *dest) +{ + paint_setup_xRGB8888 (p, dest); +} + +static void +paint_setup_ABGR8888 (paintinfo * p, unsigned char *dest) +{ + paint_setup_xBGR8888 (p, dest); +} + +static void +paint_setup_RGBA8888 (paintinfo * p, unsigned char *dest) +{ + paint_setup_RGBx8888 (p, dest); +} + +static void +paint_setup_BGRA8888 (paintinfo * p, unsigned char *dest) +{ + paint_setup_BGRx8888 (p, dest); +} + +static void +paint_setup_xRGB8888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 1; + p->up = dest + 2; + p->vp = dest + 3; + p->ap = dest; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_xBGR8888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 3; + p->up = dest + 2; + p->vp = dest + 1; + p->ap = dest; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_RGBx8888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 0; + p->up = dest + 1; + p->vp = dest + 2; + p->ap = dest + 3; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_BGRx8888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 2; + p->up = dest + 1; + p->vp = dest + 0; + p->ap = dest + 3; + p->ystride = p->width * 4; + p->ustride = p->width * 4; + p->vstride = p->width * 4; + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_RGB888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 0; + p->up = dest + 1; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_4 (p->width * 3); + p->ustride = GST_ROUND_UP_4 (p->width * 3); + p->vstride = GST_ROUND_UP_4 (p->width * 3); + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_BGR888 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 2; + p->up = dest + 1; + p->vp = dest + 0; + p->ystride = GST_ROUND_UP_4 (p->width * 3); + p->ustride = GST_ROUND_UP_4 (p->width * 3); + p->vstride = GST_ROUND_UP_4 (p->width * 3); + p->endptr = p->dest + p->ystride * p->height; +} + +static void +paint_setup_ARGB64 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 2; + p->up = dest + 4; + p->vp = dest + 6; + p->ap = dest; + p->ystride = p->width * 8; + p->ustride = p->width * 8; + p->vstride = p->width * 8; + p->endptr = p->dest + p->ystride * p->height; +} + +static void +convert_hline_str4 (paintinfo * p, int y) +{ + int i; + guint8 *A = p->ap + y * p->ystride; + guint8 *R = p->yp + y * p->ystride; + guint8 *G = p->up + y * p->ustride; + guint8 *B = p->vp + y * p->vstride; + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + A[4 * i] = 0xff; + R[4 * i] = argb[4 * i + 1]; + G[4 * i] = argb[4 * i + 2]; + B[4 * i] = argb[4 * i + 3]; + } +} + +static void +convert_hline_astr4 (paintinfo * p, int y) +{ + int i; + guint8 *A = p->ap + y * p->ystride; + guint8 *R = p->yp + y * p->ystride; + guint8 *G = p->up + y * p->ustride; + guint8 *B = p->vp + y * p->vstride; + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + A[4 * i] = argb[4 * i + 0]; + R[4 * i] = argb[4 * i + 1]; + G[4 * i] = argb[4 * i + 2]; + B[4 * i] = argb[4 * i + 3]; + } +} + +static void +convert_hline_astr8 (paintinfo * p, int y) +{ + int i; + guint16 *A = (guint16 *) (p->ap + y * p->ystride); + guint16 *R = (guint16 *) (p->yp + y * p->ystride); + guint16 *G = (guint16 *) (p->up + y * p->ustride); + guint16 *B = (guint16 *) (p->vp + y * p->vstride); + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + A[4 * i] = TO_16 (argb[4 * i + 0]); + R[4 * i] = TO_16 (argb[4 * i + 1]); + G[4 * i] = TO_16 (argb[4 * i + 2]); + B[4 * i] = TO_16 (argb[4 * i + 3]); + } +} + +static void +convert_hline_str3 (paintinfo * p, int y) +{ + int i; + guint8 *R = p->yp + y * p->ystride; + guint8 *G = p->up + y * p->ustride; + guint8 *B = p->vp + y * p->vstride; + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + R[3 * i] = argb[4 * i + 1]; + G[3 * i] = argb[4 * i + 2]; + B[3 * i] = argb[4 * i + 3]; + } +} + +static void +paint_setup_RGB565 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width * 2); + p->ustride = GST_ROUND_UP_4 (p->width * 2); + p->vstride = GST_ROUND_UP_4 (p->width * 2); + p->endptr = p->dest + p->ystride * p->height; +} + +static void +convert_hline_RGB565 (paintinfo * p, int y) +{ + int i; + guint8 *R = p->yp + y * p->ystride; + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + guint16 value = ((argb[4 * i + 1] & 0xf8) << 8) | + ((argb[4 * i + 2] & 0xfc) << 3) | ((argb[4 * i + 3] & 0xf8) >> 3); +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + GST_WRITE_UINT16_LE (R + 2 * i, value); +#else + GST_WRITE_UINT16_BE (R + 2 * i, value); +#endif + } +} + +static void +convert_hline_xRGB1555 (paintinfo * p, int y) +{ + int i; + guint8 *R = p->yp + y * p->ystride; + guint8 *argb = p->tmpline; + + for (i = 0; i < p->width; i++) { + guint16 value = ((argb[4 * i + 1] & 0xf8) << 7) | + ((argb[4 * i + 2] & 0xf8) << 2) | ((argb[4 * i + 3] & 0xf8) >> 3); +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + GST_WRITE_UINT16_LE (R + 2 * i, value); +#else + GST_WRITE_UINT16_BE (R + 2 * i, value); +#endif + } +} + +static void +paint_setup_xRGB1555 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width * 2); + p->ustride = GST_ROUND_UP_4 (p->width * 2); + p->vstride = GST_ROUND_UP_4 (p->width * 2); + p->endptr = p->dest + p->ystride * p->height; +} + + +static void +paint_setup_bayer_bggr (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->ustride = GST_ROUND_UP_4 (p->width); + p->vstride = GST_ROUND_UP_4 (p->width); + p->endptr = p->dest + p->ystride * p->height; + p->bayer_x_invert = 0; + p->bayer_y_invert = 0; +} + +static void +paint_setup_bayer_rggb (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->ustride = GST_ROUND_UP_4 (p->width); + p->vstride = GST_ROUND_UP_4 (p->width); + p->endptr = p->dest + p->ystride * p->height; + p->bayer_x_invert = 1; + p->bayer_y_invert = 1; +} + +static void +paint_setup_bayer_grbg (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->ustride = GST_ROUND_UP_4 (p->width); + p->vstride = GST_ROUND_UP_4 (p->width); + p->endptr = p->dest + p->ystride * p->height; + p->bayer_x_invert = 0; + p->bayer_y_invert = 1; +} + +static void +paint_setup_bayer_gbrg (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->ustride = GST_ROUND_UP_4 (p->width); + p->vstride = GST_ROUND_UP_4 (p->width); + p->endptr = p->dest + p->ystride * p->height; + p->bayer_x_invert = 1; + p->bayer_y_invert = 0; +} + +static void +convert_hline_bayer (paintinfo * p, int y) +{ + int i; + guint8 *R = p->yp + y * p->ystride; + guint8 *argb = p->tmpline; + int x_inv = p->bayer_x_invert; + int y_inv = p->bayer_y_invert; + + if ((y ^ y_inv) & 1) { + for (i = 0; i < p->width; i++) { + if ((i ^ x_inv) & 1) { + R[i] = argb[4 * i + 1]; + } else { + R[i] = argb[4 * i + 2]; + } + } + } else { + for (i = 0; i < p->width; i++) { + if ((i ^ x_inv) & 1) { + R[i] = argb[4 * i + 2]; + } else { + R[i] = argb[4 * i + 3]; + } + } + } +} + +static void +paint_setup_GRAY8 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->endptr = dest + p->ystride * p->height; +} + +static void +convert_hline_GRAY8 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + /* FIXME this should use gray, not YUV */ + for (i = 0; i < p->width; i++) { + Y[i] = ayuv[4 * i + 1]; + } +} + +static void +paint_setup_GRAY16 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width * 2); + p->endptr = dest + p->ystride * p->height; +} + +static void +convert_hline_GRAY16 (paintinfo * p, int y) +{ + int i; + guint8 *Y = p->yp + y * p->ystride; + guint8 *ayuv = p->tmpline; + + /* FIXME this should use gray, not YUV */ + for (i = 0; i < p->width; i++) { +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + GST_WRITE_UINT16_LE (Y + i * 2, ayuv[4 * i + 1] << 8); +#else + GST_WRITE_UINT16_BE (Y + i * 2, ayuv[4 * i + 1] << 8); +#endif + } +} diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.h b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.h new file mode 100644 index 0000000..b93b704 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.h @@ -0,0 +1,148 @@ +/* GStreamer + * Copyright (C) <2003> David A. Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 __VIDEO_TEST_SRC_H__ +#define __VIDEO_TEST_SRC_H__ + +#include + +enum { + VTS_YUV, + VTS_RGB, + VTS_GRAY, + VTS_BAYER +}; + +enum { + VTS_BAYER_BGGR, + VTS_BAYER_RGGB, + VTS_BAYER_GRBG, + VTS_BAYER_GBRG +}; + +struct vts_color_struct { + guint8 Y, U, V, A; + guint8 R, G, B; + guint16 gray; +}; + + +typedef struct paintinfo_struct paintinfo; +struct paintinfo_struct +{ + unsigned char *dest; /* pointer to first byte of video data */ + unsigned char *yp, *up, *vp; /* pointers to first byte of each component + * for both packed/planar YUV and RGB */ + unsigned char *ap; /* pointer to first byte of alpha component */ + unsigned char *endptr; /* pointer to byte beyond last video data */ + int ystride; + int ustride; + int vstride; + int width; + int height; + const struct vts_color_struct *colors; + const struct vts_color_struct *color; + /* const struct vts_color_struct *color; */ + void (*paint_hline) (paintinfo * p, int x, int y, int w); + void (*paint_tmpline) (paintinfo * p, int x, int w); + void (*convert_tmpline) (paintinfo * p, int y); + int x_offset; + + int bayer_x_invert; + int bayer_y_invert; + + guint8 *tmpline; + guint8 *tmpline2; + guint8 *tmpline_u8; + + struct vts_color_struct foreground_color; + struct vts_color_struct background_color; +}; + +struct fourcc_list_struct +{ + int type; + const char *fourcc; + const char *name; + int bitspp; + void (*paint_setup) (paintinfo * p, unsigned char *dest); + void (*convert_hline) (paintinfo * p, int y); + int depth; + unsigned int red_mask; + unsigned int green_mask; + unsigned int blue_mask; + unsigned int alpha_mask; +}; + +struct fourcc_list_struct * + paintrect_find_fourcc (int find_fourcc); +struct fourcc_list_struct * + paintrect_find_name (const char *name); +struct fourcc_list_struct * + paintinfo_find_by_structure (const GstStructure *structure); +GstStructure * + paint_get_structure (struct fourcc_list_struct *format); +int gst_video_test_src_get_size (GstVideoTestSrc * v, int w, int h); +void gst_video_test_src_smpte (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_smpte75 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_snow (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_black (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_white (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_red (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_green (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_blue (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_solid (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_blink (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_checkers1 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_checkers2 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_checkers4 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_checkers8 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_circular (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_zoneplate (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_gamut (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_chromazoneplate (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_ball (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_smpte100 (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); +void gst_video_test_src_bar (GstVideoTestSrc * v, + unsigned char *dest, int w, int h); + +extern struct fourcc_list_struct fourcc_list[]; +extern int n_fourccs; + +#endif diff --git a/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.vcproj b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.vcproj new file mode 100644 index 0000000..baff9fe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/videotestsrc/videotestsrc.vcproj @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/gst/volume/.gitignore b/gst-plugins-base-subtitles0.10/gst/volume/.gitignore new file mode 100644 index 0000000..1549b67 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/.gitignore @@ -0,0 +1 @@ +demo diff --git a/gst-plugins-base-subtitles0.10/gst/volume/Makefile.am b/gst-plugins-base-subtitles0.10/gst/volume/Makefile.am new file mode 100644 index 0000000..d750912 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/Makefile.am @@ -0,0 +1,34 @@ +plugin_LTLIBRARIES = libgstvolume.la + +ORC_SOURCE=gstvolumeorc +include $(top_srcdir)/common/orc.mak + +libgstvolume_la_SOURCES = gstvolume.c +nodist_libgstvolume_la_SOURCES = $(ORC_NODIST_SOURCES) +libgstvolume_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(ORC_CFLAGS) +libgstvolume_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvolume_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_CONTROLLER_LIBS) \ + $(GST_LIBS) \ + $(ORC_LIBS) +libgstvolume_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstvolume.h + +Android.mk: Makefile.am $(BUILT_SOURCES) + androgenizer \ + -:PROJECT libgstvolume -:SHARED libgstvolume \ + -:TAGS eng debug \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:SOURCES $(libgstvolume_la_SOURCES) \ + $(nodist_libgstvolume_la_SOURCES) \ + -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstvolume_la_CFLAGS) \ + -:LDFLAGS $(libgstvolume_la_LDFLAGS) \ + $(libgstvolume_la_LIBADD) \ + -ldl \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.c b/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.c new file mode 100644 index 0000000..a592707 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.c @@ -0,0 +1,1048 @@ +/* -*- c-basic-offset: 2 -*- + * vi:si:et:sw=2:sts=8:ts=8:expandtab + * + * GStreamer + * Copyright (C) 1999-2001 Erik Walthinsen + * Copyright (C) 2005 Andy Wingo + * Copyright (C) 2010 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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-volume + * + * The volume element changes the volume of the audio data. + * + * + * Example launch line + * |[ + * gst-launch -v -m audiotestsrc ! volume volume=0.5 ! level ! fakesink silent=TRUE + * ]| This pipeline shows that the level of audiotestsrc has been halved + * (peak values are around -6 dB and RMS around -9 dB) compared to + * the same pipeline without the volume element. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_ORC +#include +#else +#define orc_memset memset +#endif + +#include "gstvolumeorc.h" +#include "gstvolume.h" + +/* some defines for audio processing */ +/* the volume factor is a range from 0.0 to (arbitrary) VOLUME_MAX_DOUBLE = 10.0 + * we map 1.0 to VOLUME_UNITY_INT* + */ +#define VOLUME_UNITY_INT8 32 /* internal int for unity 2^(8-3) */ +#define VOLUME_UNITY_INT8_BIT_SHIFT 5 /* number of bits to shift for unity */ +#define VOLUME_UNITY_INT16 8192 /* internal int for unity 2^(16-3) */ +#define VOLUME_UNITY_INT16_BIT_SHIFT 13 /* number of bits to shift for unity */ +#define VOLUME_UNITY_INT24 2097152 /* internal int for unity 2^(24-3) */ +#define VOLUME_UNITY_INT24_BIT_SHIFT 21 /* number of bits to shift for unity */ +#define VOLUME_UNITY_INT32 134217728 /* internal int for unity 2^(32-5) */ +#define VOLUME_UNITY_INT32_BIT_SHIFT 27 +#define VOLUME_MAX_DOUBLE 10.0 +#define VOLUME_MAX_INT8 G_MAXINT8 +#define VOLUME_MIN_INT8 G_MININT8 +#define VOLUME_MAX_INT16 G_MAXINT16 +#define VOLUME_MIN_INT16 G_MININT16 +#define VOLUME_MAX_INT24 8388607 +#define VOLUME_MIN_INT24 -8388608 +#define VOLUME_MAX_INT32 G_MAXINT32 +#define VOLUME_MIN_INT32 G_MININT32 + +/* number of steps we use for the mixer interface to go from 0.0 to 1.0 */ +# define VOLUME_STEPS 100 + +#define GST_CAT_DEFAULT gst_volume_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +#define DEFAULT_PROP_MUTE FALSE +#define DEFAULT_PROP_VOLUME 1.0 + +enum +{ + PROP_0, + PROP_MUTE, + PROP_VOLUME +}; + +#define ALLOWED_CAPS \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) {32, 64}; " \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 8, " \ + "depth = (int) 8, " \ + "signed = (bool) TRUE; " \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (bool) TRUE; " \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 24, " \ + "depth = (int) 24, " \ + "signed = (bool) TRUE; " \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32, " \ + "depth = (int) 32, " \ + "signed = (bool) TRUE" + +static void gst_volume_interface_init (GstImplementsInterfaceClass * klass); +static void gst_volume_mixer_init (GstMixerClass * iface); + +#define _init_interfaces(type) \ + { \ + static const GInterfaceInfo voliface_info = { \ + (GInterfaceInitFunc) gst_volume_interface_init, \ + NULL, \ + NULL \ + }; \ + static const GInterfaceInfo volmixer_info = { \ + (GInterfaceInitFunc) gst_volume_mixer_init, \ + NULL, \ + NULL \ + }; \ + static const GInterfaceInfo svol_info = { \ + NULL, \ + NULL, \ + NULL \ + }; \ + \ + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, \ + &voliface_info); \ + g_type_add_interface_static (type, GST_TYPE_MIXER, &volmixer_info); \ + g_type_add_interface_static (type, GST_TYPE_STREAM_VOLUME, &svol_info); \ + } + +GST_BOILERPLATE_FULL (GstVolume, gst_volume, GstAudioFilter, + GST_TYPE_AUDIO_FILTER, _init_interfaces); + +static void volume_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void volume_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void volume_before_transform (GstBaseTransform * base, + GstBuffer * buffer); +static GstFlowReturn volume_transform_ip (GstBaseTransform * base, + GstBuffer * outbuf); +static gboolean volume_stop (GstBaseTransform * base); +static gboolean volume_setup (GstAudioFilter * filter, + GstRingBufferSpec * format); + +static void volume_process_double (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_double (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes); +static void volume_process_float (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_float (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes); +static void volume_process_int32 (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_int32_clamp (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_int32_clamp (GstVolume * self, + gpointer bytes, gdouble * volume, guint channels, guint n_bytes); +static void volume_process_int24 (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_int24_clamp (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_int24_clamp (GstVolume * self, + gpointer bytes, gdouble * volume, guint channels, guint n_bytes); +static void volume_process_int16 (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_int16_clamp (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_int16_clamp (GstVolume * self, + gpointer bytes, gdouble * volume, guint channels, guint n_bytes); +static void volume_process_int8 (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_int8_clamp (GstVolume * self, gpointer bytes, + guint n_bytes); +static void volume_process_controlled_int8_clamp (GstVolume * self, + gpointer bytes, gdouble * volume, guint channels, guint n_bytes); + + +/* helper functions */ + +static gboolean +volume_choose_func (GstVolume * self) +{ + self->process = NULL; + self->process_controlled = NULL; + + if (GST_AUDIO_FILTER (self)->format.caps == NULL) + return FALSE; + + switch (GST_AUDIO_FILTER (self)->format.type) { + case GST_BUFTYPE_LINEAR: + switch (GST_AUDIO_FILTER (self)->format.width) { + case 32: + /* only clamp if the gain is greater than 1.0 + */ + if (self->current_vol_i32 > VOLUME_UNITY_INT32) { + self->process = volume_process_int32_clamp; + } else { + self->process = volume_process_int32; + } + self->process_controlled = volume_process_controlled_int32_clamp; + break; + case 24: + /* only clamp if the gain is greater than 1.0 + */ + if (self->current_vol_i24 > VOLUME_UNITY_INT24) { + self->process = volume_process_int24_clamp; + } else { + self->process = volume_process_int24; + } + self->process_controlled = volume_process_controlled_int24_clamp; + break; + case 16: + /* only clamp if the gain is greater than 1.0 + */ + if (self->current_vol_i16 > VOLUME_UNITY_INT16) { + self->process = volume_process_int16_clamp; + } else { + self->process = volume_process_int16; + } + self->process_controlled = volume_process_controlled_int16_clamp; + break; + case 8: + /* only clamp if the gain is greater than 1.0 + */ + if (self->current_vol_i16 > VOLUME_UNITY_INT8) { + self->process = volume_process_int8_clamp; + } else { + self->process = volume_process_int8; + } + self->process_controlled = volume_process_controlled_int8_clamp; + break; + } + break; + case GST_BUFTYPE_FLOAT: + switch (GST_AUDIO_FILTER (self)->format.width) { + case 32: + self->process = volume_process_float; + self->process_controlled = volume_process_controlled_float; + break; + case 64: + self->process = volume_process_double; + self->process_controlled = volume_process_controlled_double; + break; + } + break; + default: + break; + } + + return (self->process != NULL); +} + +static gboolean +volume_update_volume (GstVolume * self, gfloat volume, gboolean mute) +{ + gboolean passthrough; + gboolean res; + GstController *controller; + + GST_DEBUG_OBJECT (self, "configure mute %d, volume %f", mute, volume); + + if (mute) { + self->current_mute = TRUE; + self->current_volume = 0.0; + + self->current_vol_i8 = 0; + self->current_vol_i16 = 0; + self->current_vol_i24 = 0; + self->current_vol_i32 = 0; + + passthrough = FALSE; + } else { + self->current_mute = FALSE; + self->current_volume = volume; + + self->current_vol_i8 = volume * VOLUME_UNITY_INT8; + self->current_vol_i16 = volume * VOLUME_UNITY_INT16; + self->current_vol_i24 = volume * VOLUME_UNITY_INT24; + self->current_vol_i32 = volume * VOLUME_UNITY_INT32; + + passthrough = (self->current_vol_i16 == VOLUME_UNITY_INT16); + } + + /* If a controller is used, never use passthrough mode + * because the property can change from 1.0 to something + * else in the middle of a buffer. + */ + controller = gst_object_get_controller (G_OBJECT (self)); + passthrough = passthrough && (controller == NULL); + + GST_DEBUG_OBJECT (self, "set passthrough %d", passthrough); + + gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (self), passthrough); + + res = self->negotiated = volume_choose_func (self); + + return res; +} + +/* Mixer interface */ + +static gboolean +gst_volume_interface_supported (GstImplementsInterface * iface, GType type) +{ + return (type == GST_TYPE_MIXER || type == GST_TYPE_STREAM_VOLUME); +} + +static void +gst_volume_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = gst_volume_interface_supported; +} + +static const GList * +gst_volume_list_tracks (GstMixer * mixer) +{ + GstVolume *self = GST_VOLUME (mixer); + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (GST_IS_VOLUME (self), NULL); + + return self->tracklist; +} + +static void +gst_volume_set_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes) +{ + GstVolume *self = GST_VOLUME (mixer); + + g_return_if_fail (self != NULL); + g_return_if_fail (GST_IS_VOLUME (self)); + + GST_OBJECT_LOCK (self); + self->volume = (gfloat) volumes[0] / VOLUME_STEPS; + GST_OBJECT_UNLOCK (self); +} + +static void +gst_volume_get_volume (GstMixer * mixer, GstMixerTrack * track, gint * volumes) +{ + GstVolume *self = GST_VOLUME (mixer); + + g_return_if_fail (self != NULL); + g_return_if_fail (GST_IS_VOLUME (self)); + + GST_OBJECT_LOCK (self); + volumes[0] = (gint) self->volume * VOLUME_STEPS; + GST_OBJECT_UNLOCK (self); +} + +static void +gst_volume_set_mute (GstMixer * mixer, GstMixerTrack * track, gboolean mute) +{ + GstVolume *self = GST_VOLUME (mixer); + + g_return_if_fail (self != NULL); + g_return_if_fail (GST_IS_VOLUME (self)); + + GST_OBJECT_LOCK (self); + self->mute = mute; + GST_OBJECT_UNLOCK (self); +} + +static void +gst_volume_mixer_init (GstMixerClass * klass) +{ + GST_MIXER_TYPE (klass) = GST_MIXER_SOFTWARE; + + /* default virtual functions */ + klass->list_tracks = gst_volume_list_tracks; + klass->set_volume = gst_volume_set_volume; + klass->get_volume = gst_volume_get_volume; + klass->set_mute = gst_volume_set_mute; +} + +/* Element class */ + +static void +gst_volume_dispose (GObject * object) +{ + GstVolume *volume = GST_VOLUME (object); + + if (volume->tracklist) { + if (volume->tracklist->data) + g_object_unref (volume->tracklist->data); + g_list_free (volume->tracklist); + volume->tracklist = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_volume_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstAudioFilterClass *filter_class = GST_AUDIO_FILTER_CLASS (g_class); + GstCaps *caps; + + gst_element_class_set_details_simple (element_class, "Volume", + "Filter/Effect/Audio", + "Set volume on audio/raw streams", "Andy Wingo "); + + caps = gst_caps_from_string (ALLOWED_CAPS); + gst_audio_filter_class_add_pad_templates (filter_class, caps); + gst_caps_unref (caps); +} + +static void +gst_volume_class_init (GstVolumeClass * klass) +{ + GObjectClass *gobject_class; + GstBaseTransformClass *trans_class; + GstAudioFilterClass *filter_class; + + gobject_class = (GObjectClass *) klass; + trans_class = (GstBaseTransformClass *) klass; + filter_class = (GstAudioFilterClass *) (klass); + + gobject_class->set_property = volume_set_property; + gobject_class->get_property = volume_get_property; + gobject_class->dispose = gst_volume_dispose; + + g_object_class_install_property (gobject_class, PROP_MUTE, + g_param_spec_boolean ("mute", "Mute", "mute channel", + DEFAULT_PROP_MUTE, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_VOLUME, + g_param_spec_double ("volume", "Volume", "volume factor, 1.0=100%", + 0.0, VOLUME_MAX_DOUBLE, DEFAULT_PROP_VOLUME, + G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)); + + trans_class->before_transform = GST_DEBUG_FUNCPTR (volume_before_transform); + trans_class->transform_ip = GST_DEBUG_FUNCPTR (volume_transform_ip); + trans_class->stop = GST_DEBUG_FUNCPTR (volume_stop); + filter_class->setup = GST_DEBUG_FUNCPTR (volume_setup); +} + +static void +gst_volume_init (GstVolume * self, GstVolumeClass * g_class) +{ + GstMixerTrack *track = NULL; + + self->mute = DEFAULT_PROP_MUTE;; + self->volume = DEFAULT_PROP_VOLUME; + + self->tracklist = NULL; + self->negotiated = FALSE; + + track = g_object_new (GST_TYPE_MIXER_TRACK, NULL); + + if (GST_IS_MIXER_TRACK (track)) { + track->label = g_strdup ("volume"); + track->num_channels = 1; + track->min_volume = 0; + track->max_volume = VOLUME_STEPS; + track->flags = GST_MIXER_TRACK_SOFTWARE; + self->tracklist = g_list_append (self->tracklist, track); + } + + gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (self), TRUE); +} + +static void +volume_process_double (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gdouble *data = (gdouble *) bytes; + guint num_samples = n_bytes / sizeof (gdouble); + + orc_scalarmultiply_f64_ns (data, self->current_volume, num_samples); +} + +static void +volume_process_controlled_double (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gdouble *data = (gdouble *) bytes; + guint num_samples = n_bytes / (sizeof (gdouble) * channels); + guint i, j; + gdouble vol; + + if (channels == 1) { + orc_process_controlled_f64_1ch (data, volume, num_samples); + } else { + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + *data++ *= vol; + } + } + } +} + +static void +volume_process_float (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gfloat *data = (gfloat *) bytes; + guint num_samples = n_bytes / sizeof (gfloat); + + orc_scalarmultiply_f32_ns (data, self->current_volume, num_samples); +} + +static void +volume_process_controlled_float (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gfloat *data = (gfloat *) bytes; + guint num_samples = n_bytes / (sizeof (gfloat) * channels); + guint i, j; + gdouble vol; + + if (channels == 1) { + orc_process_controlled_f32_1ch (data, volume, num_samples); + } else if (channels == 2) { + orc_process_controlled_f32_2ch (data, volume, num_samples); + } else { + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + *data++ *= vol; + } + } + } +} + +static void +volume_process_int32 (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint32 *data = (gint32 *) bytes; + guint num_samples = n_bytes / sizeof (gint); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT32_BIT_SHIFT == 27); + orc_process_int32 (data, self->current_vol_i32, num_samples); +} + +static void +volume_process_int32_clamp (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint32 *data = (gint32 *) bytes; + guint num_samples = n_bytes / sizeof (gint); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT32_BIT_SHIFT == 27); + + orc_process_int32_clamp (data, self->current_vol_i32, num_samples); +} + +static void +volume_process_controlled_int32_clamp (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gint32 *data = (gint32 *) bytes; + guint i, j; + guint num_samples = n_bytes / (sizeof (gint32) * channels); + gdouble vol, val; + + if (channels == 1) { + orc_process_controlled_int32_1ch (data, volume, num_samples); + } else { + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + val = *data * vol; + *data++ = (gint32) CLAMP (val, VOLUME_MIN_INT32, VOLUME_MAX_INT32); + } + } + } +} + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +#define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) ) + +#define write_unaligned_u24(_x,samp) \ +G_STMT_START { \ + *(_x)++ = samp & 0xFF; \ + *(_x)++ = (samp >> 8) & 0xFF; \ + *(_x)++ = (samp >> 16) & 0xFF; \ +} G_STMT_END + +#else /* BIG ENDIAN */ +#define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) ) +#define write_unaligned_u24(_x,samp) \ +G_STMT_START { \ + *(_x)++ = (samp >> 16) & 0xFF; \ + *(_x)++ = (samp >> 8) & 0xFF; \ + *(_x)++ = samp & 0xFF; \ +} G_STMT_END +#endif + +static void +volume_process_int24 (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; /* treat the data as a byte stream */ + guint i, num_samples; + guint32 samp; + gint64 val; + + num_samples = n_bytes / (sizeof (gint8) * 3); + for (i = 0; i < num_samples; i++) { + samp = get_unaligned_i24 (data); + + val = (gint32) samp; + val = + (((gint64) self->current_vol_i24 * + val) >> VOLUME_UNITY_INT24_BIT_SHIFT); + samp = (guint32) val; + + /* write the value back into the stream */ + write_unaligned_u24 (data, samp); + } +} + +static void +volume_process_int24_clamp (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; /* treat the data as a byte stream */ + guint i, num_samples; + guint32 samp; + gint64 val; + + num_samples = n_bytes / (sizeof (gint8) * 3); + for (i = 0; i < num_samples; i++) { + samp = get_unaligned_i24 (data); + + val = (gint32) samp; + val = + (((gint64) self->current_vol_i24 * + val) >> VOLUME_UNITY_INT24_BIT_SHIFT); + samp = (guint32) CLAMP (val, VOLUME_MIN_INT24, VOLUME_MAX_INT24); + + /* write the value back into the stream */ + write_unaligned_u24 (data, samp); + } +} + +static void +volume_process_controlled_int24_clamp (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; /* treat the data as a byte stream */ + guint i, j; + guint num_samples = n_bytes / (sizeof (gint8) * 3 * channels); + gdouble vol, val; + + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + val = get_unaligned_i24 (data) * vol; + val = CLAMP (val, VOLUME_MIN_INT24, VOLUME_MAX_INT24); + write_unaligned_u24 (data, (gint32) val); + } + } +} + +static void +volume_process_int16 (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint16 *data = (gint16 *) bytes; + guint num_samples = n_bytes / sizeof (gint16); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT16_BIT_SHIFT == 13); + + orc_process_int16 (data, self->current_vol_i16, num_samples); +} + +static void +volume_process_int16_clamp (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint16 *data = (gint16 *) bytes; + guint num_samples = n_bytes / sizeof (gint16); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT16_BIT_SHIFT == 13); + + orc_process_int16_clamp (data, self->current_vol_i16, num_samples); +} + +static void +volume_process_controlled_int16_clamp (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gint16 *data = (gint16 *) bytes; + guint i, j; + guint num_samples = n_bytes / (sizeof (gint16) * channels); + gdouble vol, val; + + if (channels == 1) { + orc_process_controlled_int16_1ch (data, volume, num_samples); + } else if (channels == 2) { + orc_process_controlled_int16_2ch (data, volume, num_samples); + } else { + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + val = *data * vol; + *data++ = (gint16) CLAMP (val, VOLUME_MIN_INT16, VOLUME_MAX_INT16); + } + } + } +} + +static void +volume_process_int8 (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; + guint num_samples = n_bytes / sizeof (gint8); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT8_BIT_SHIFT == 5); + + orc_process_int8 (data, self->current_vol_i8, num_samples); +} + +static void +volume_process_int8_clamp (GstVolume * self, gpointer bytes, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; + guint num_samples = n_bytes / sizeof (gint8); + + /* hard coded in volume.orc */ + g_assert (VOLUME_UNITY_INT8_BIT_SHIFT == 5); + + orc_process_int8_clamp (data, self->current_vol_i8, num_samples); +} + +static void +volume_process_controlled_int8_clamp (GstVolume * self, gpointer bytes, + gdouble * volume, guint channels, guint n_bytes) +{ + gint8 *data = (gint8 *) bytes; + guint i, j; + guint num_samples = n_bytes / (sizeof (gint8) * channels); + gdouble val, vol; + + if (channels == 1) { + orc_process_controlled_int8_1ch (data, volume, num_samples); + } else if (channels == 2) { + orc_process_controlled_int8_2ch (data, volume, num_samples); + } else { + for (i = 0; i < num_samples; i++) { + vol = *volume++; + for (j = 0; j < channels; j++) { + val = *data * vol; + *data++ = (gint8) CLAMP (val, VOLUME_MIN_INT8, VOLUME_MAX_INT8); + } + } + } +} + +/* GstBaseTransform vmethod implementations */ + +/* get notified of caps and plug in the correct process function */ +static gboolean +volume_setup (GstAudioFilter * filter, GstRingBufferSpec * format) +{ + gboolean res; + GstVolume *self = GST_VOLUME (filter); + gfloat volume; + gboolean mute; + + GST_OBJECT_LOCK (self); + volume = self->volume; + mute = self->mute; + GST_OBJECT_UNLOCK (self); + + res = volume_update_volume (self, volume, mute); + if (!res) { + GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, + ("Invalid incoming format"), (NULL)); + } + self->negotiated = res; + + return res; +} + +static gboolean +volume_stop (GstBaseTransform * base) +{ + GstVolume *self = GST_VOLUME (base); + + g_free (self->volumes); + self->volumes = NULL; + self->volumes_count = 0; + + g_free (self->mutes); + self->mutes = NULL; + self->mutes_count = 0; + + return GST_CALL_PARENT_WITH_DEFAULT (GST_BASE_TRANSFORM_CLASS, stop, (base), + TRUE); +} + +static void +volume_before_transform (GstBaseTransform * base, GstBuffer * buffer) +{ + GstClockTime timestamp; + GstVolume *self = GST_VOLUME (base); + gfloat volume; + gboolean mute; + + timestamp = GST_BUFFER_TIMESTAMP (buffer); + timestamp = + gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, timestamp); + + GST_DEBUG_OBJECT (base, "sync to %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp)); + + if (GST_CLOCK_TIME_IS_VALID (timestamp)) + gst_object_sync_values (G_OBJECT (self), timestamp); + + /* get latest values */ + GST_OBJECT_LOCK (self); + volume = self->volume; + mute = self->mute; + GST_OBJECT_UNLOCK (self); + + if ((volume != self->current_volume) || (mute != self->current_mute)) { + /* the volume or mute was updated, update our internal state before + * we continue processing. */ + volume_update_volume (self, volume, mute); + } +} + +/* call the plugged-in process function for this instance + * needs to be done with this indirection since volume_transform is + * a class-global method + */ +static GstFlowReturn +volume_transform_ip (GstBaseTransform * base, GstBuffer * outbuf) +{ + GstVolume *self = GST_VOLUME (base); + guint8 *data; + guint size; + GstControlSource *mute_csource, *volume_csource; + + if (G_UNLIKELY (!self->negotiated)) + goto not_negotiated; + + /* don't process data in passthrough-mode */ + if (gst_base_transform_is_passthrough (base) || + GST_BUFFER_FLAG_IS_SET (outbuf, GST_BUFFER_FLAG_GAP)) + return GST_FLOW_OK; + + data = GST_BUFFER_DATA (outbuf); + size = GST_BUFFER_SIZE (outbuf); + + mute_csource = gst_object_get_control_source (G_OBJECT (self), "mute"); + volume_csource = gst_object_get_control_source (G_OBJECT (self), "volume"); + if (mute_csource || (volume_csource && !self->current_mute)) { + gint rate = GST_AUDIO_FILTER_CAST (self)->format.rate; + gint width = GST_AUDIO_FILTER_CAST (self)->format.width / 8; + gint channels = GST_AUDIO_FILTER_CAST (self)->format.channels; + guint nsamples = size / (width * channels); + GstClockTime interval = gst_util_uint64_scale_int (1, GST_SECOND, rate); + GstClockTime ts = GST_BUFFER_TIMESTAMP (outbuf); + + ts = gst_segment_to_stream_time (&base->segment, GST_FORMAT_TIME, ts); + + if (self->mutes_count < nsamples && mute_csource) { + self->mutes = g_realloc (self->mutes, sizeof (gboolean) * nsamples); + self->mutes_count = nsamples; + } + + if (self->volumes_count < nsamples) { + self->volumes = g_realloc (self->volumes, sizeof (gdouble) * nsamples); + self->volumes_count = nsamples; + } + + if (mute_csource) { + GstValueArray va = { "mute", nsamples, interval, (gpointer) self->mutes }; + + if (!gst_control_source_get_value_array (mute_csource, ts, &va)) + goto controller_failure; + + gst_object_unref (mute_csource); + mute_csource = NULL; + } else { + g_free (self->mutes); + self->mutes = NULL; + self->mutes_count = 0; + } + + if (volume_csource) { + GstValueArray va = + { "volume", nsamples, interval, (gpointer) self->volumes }; + + if (!gst_control_source_get_value_array (volume_csource, ts, &va)) + goto controller_failure; + + gst_object_unref (volume_csource); + volume_csource = NULL; + } else { + orc_memset_f64 (self->volumes, self->current_volume, nsamples); + } + + if (mute_csource) { + orc_prepare_volumes (self->volumes, self->mutes, nsamples); + } + + self->process_controlled (self, data, self->volumes, channels, size); + + return GST_FLOW_OK; + } else if (volume_csource) { + gst_object_unref (volume_csource); + } + + if (self->current_volume == 0.0 || self->current_mute) { + orc_memset (data, 0, size); + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP); + } else if (self->current_volume != 1.0) { + self->process (self, data, size); + } + + return GST_FLOW_OK; + + /* ERRORS */ +not_negotiated: + { + GST_ELEMENT_ERROR (self, CORE, NEGOTIATION, + ("No format was negotiated"), (NULL)); + return GST_FLOW_NOT_NEGOTIATED; + } +controller_failure: + { + if (mute_csource) + gst_object_unref (mute_csource); + if (volume_csource) + gst_object_unref (volume_csource); + + GST_ELEMENT_ERROR (self, CORE, FAILED, + ("Failed to get values from controller"), (NULL)); + return GST_FLOW_ERROR; + } +} + +static void +volume_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ + GstVolume *self = GST_VOLUME (object); + + switch (prop_id) { + case PROP_MUTE: + GST_OBJECT_LOCK (self); + self->mute = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (self); + break; + case PROP_VOLUME: + GST_OBJECT_LOCK (self); + self->volume = g_value_get_double (value); + GST_OBJECT_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +volume_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVolume *self = GST_VOLUME (object); + + switch (prop_id) { + case PROP_MUTE: + GST_OBJECT_LOCK (self); + g_value_set_boolean (value, self->mute); + GST_OBJECT_UNLOCK (self); + break; + case PROP_VOLUME: + GST_OBJECT_LOCK (self); + g_value_set_double (value, self->volume); + GST_OBJECT_UNLOCK (self); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_volume_orc_init (); + + /* initialize gst controller library */ + gst_controller_init (NULL, NULL); + + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "volume", 0, "Volume gain"); + + /* ref class from a thread-safe context to work around missing bit of + * thread-safety in GObject */ + g_type_class_ref (GST_TYPE_MIXER_TRACK); + + return gst_element_register (plugin, "volume", GST_RANK_NONE, + GST_TYPE_VOLUME); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "volume", + "plugin for controlling audio volume", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.h b/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.h new file mode 100644 index 0000000..047227d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/gstvolume.h @@ -0,0 +1,88 @@ +/* -*- c-basic-offset: 2 -*- + * vi:si:et:sw=2:sts=8:ts=8:expandtab + * + * GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) 2010 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_VOLUME_H__ +#define __GST_VOLUME_H__ + +#include +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VOLUME \ + (gst_volume_get_type()) +#define GST_VOLUME(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VOLUME,GstVolume)) +#define GST_VOLUME_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VOLUME,GstVolumeClass)) +#define GST_IS_VOLUME(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VOLUME)) +#define GST_IS_VOLUME_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VOLUME)) + +typedef struct _GstVolume GstVolume; +typedef struct _GstVolumeClass GstVolumeClass; + +/** + * GstVolume: + * + * Opaque data structure. + */ +struct _GstVolume { + GstAudioFilter element; + + void (*process)(GstVolume*, gpointer, guint); + void (*process_controlled)(GstVolume*, gpointer, gdouble *, guint, guint); + + gboolean mute; + gfloat volume; + + gboolean current_mute; + gfloat current_volume; + + gint current_vol_i32; + gint current_vol_i24; /* the _i(nt) values get synchronized with the */ + gint current_vol_i16; /* the _i(nt) values get synchronized with the */ + gint current_vol_i8; /* the _i(nt) values get synchronized with the */ + + GList *tracklist; + gboolean negotiated; + + gboolean *mutes; + guint mutes_count; + gdouble *volumes; + guint volumes_count; +}; + +struct _GstVolumeClass { + GstAudioFilterClass parent_class; +}; + +GType gst_volume_get_type (void); + +G_END_DECLS + +#endif /* __GST_VOLUME_H__ */ diff --git a/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.c b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.c new file mode 100644 index 0000000..1028649 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.c @@ -0,0 +1,2721 @@ + +/* autogenerated from gstvolumeorc.orc */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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 + +#ifndef DISABLE_ORC +#include +#endif +void orc_scalarmultiply_f64_ns (double *ORC_RESTRICT d1, double p1, int n); +void orc_scalarmultiply_f32_ns (float *ORC_RESTRICT d1, float p1, int n); +void orc_process_int32 (gint32 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int32_clamp (gint32 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int16 (gint16 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int16_clamp (gint16 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int8 (gint8 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int8_clamp (gint8 * ORC_RESTRICT d1, int p1, int n); +void orc_memset_f64 (gdouble * ORC_RESTRICT d1, double p1, int n); +void orc_prepare_volumes (gdouble * ORC_RESTRICT d1, + const gboolean * ORC_RESTRICT s1, int n); +void orc_process_controlled_f64_1ch (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_f32_1ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_f32_2ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int32_1ch (gint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int16_1ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int16_2ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int8_1ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int8_2ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n); + +void gst_volume_orc_init (void); + + +/* begin Orc C target preamble */ +#define ORC_CLAMP(x,a,b) ((x)<(a) ? (a) : ((x)>(b) ? (b) : (x))) +#define ORC_ABS(a) ((a)<0 ? -(a) : (a)) +#define ORC_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define ORC_MAX(a,b) ((a)>(b) ? (a) : (b)) +#define ORC_SB_MAX 127 +#define ORC_SB_MIN (-1-ORC_SB_MAX) +#define ORC_UB_MAX 255 +#define ORC_UB_MIN 0 +#define ORC_SW_MAX 32767 +#define ORC_SW_MIN (-1-ORC_SW_MAX) +#define ORC_UW_MAX 65535 +#define ORC_UW_MIN 0 +#define ORC_SL_MAX 2147483647 +#define ORC_SL_MIN (-1-ORC_SL_MAX) +#define ORC_UL_MAX 4294967295U +#define ORC_UL_MIN 0 +#define ORC_CLAMP_SB(x) ORC_CLAMP(x,ORC_SB_MIN,ORC_SB_MAX) +#define ORC_CLAMP_UB(x) ORC_CLAMP(x,ORC_UB_MIN,ORC_UB_MAX) +#define ORC_CLAMP_SW(x) ORC_CLAMP(x,ORC_SW_MIN,ORC_SW_MAX) +#define ORC_CLAMP_UW(x) ORC_CLAMP(x,ORC_UW_MIN,ORC_UW_MAX) +#define ORC_CLAMP_SL(x) ORC_CLAMP(x,ORC_SL_MIN,ORC_SL_MAX) +#define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) +#define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) +#define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) +#define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) +#define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) +#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 +#define ORC_RESTRICT __restrict__ +#else +#define ORC_RESTRICT +#endif +#endif +/* end Orc C target preamble */ + + + +/* orc_scalarmultiply_f64_ns */ +#ifdef DISABLE_ORC +void +orc_scalarmultiply_f64_ns (double *ORC_RESTRICT d1, double p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + orc_union64 var34; + + ptr0 = (orc_union64 *) d1; + + /* 1: loadpq */ + var33.f = p1; + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr0[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_scalarmultiply_f64_ns (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + orc_union64 var34; + + ptr0 = (orc_union64 *) ex->arrays[0]; + + /* 1: loadpq */ + var33.i = + (ex->params[24] & 0xffffffff) | ((orc_uint64) (ex->params[24 + + (ORC_VAR_T1 - ORC_VAR_P1)]) << 32); + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr0[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_scalarmultiply_f64_ns; +void +orc_scalarmultiply_f64_ns (double *ORC_RESTRICT d1, double p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_scalarmultiply_f64_ns; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + { + orc_union64 tmp; + tmp.f = p1; + ex->params[ORC_VAR_P1] = tmp.x2[0]; + ex->params[ORC_VAR_T1] = tmp.x2[1]; + } + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_scalarmultiply_f32_ns */ +#ifdef DISABLE_ORC +void +orc_scalarmultiply_f32_ns (float *ORC_RESTRICT d1, float p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) d1; + + /* 1: loadpl */ + var33.f = p1; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 2: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var32.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL (_dest1.i); + } + /* 3: storel */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_scalarmultiply_f32_ns (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var32; + orc_union32 var33; + orc_union32 var34; + + ptr0 = (orc_union32 *) ex->arrays[0]; + + /* 1: loadpl */ + var33.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var32 = ptr0[i]; + /* 2: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var32.i); + _src2.i = ORC_DENORMAL (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL (_dest1.i); + } + /* 3: storel */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_scalarmultiply_f32_ns; +void +orc_scalarmultiply_f32_ns (float *ORC_RESTRICT d1, float p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_scalarmultiply_f32_ns; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + { + orc_union32 tmp; + tmp.f = p1; + ex->params[ORC_VAR_P1] = tmp.i; + } + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int32 */ +#ifdef DISABLE_ORC +void +orc_process_int32 (gint32 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) d1; + + /* 1: loadpl */ + var34.i = p1; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 2: mulslq */ + var36.i = ((orc_int64) var33.i) * ((orc_int64) var34.i); + /* 3: shrsq */ + var37.i = var36.i >> 27; + /* 4: convql */ + var35.i = var37.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int32 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + + /* 1: loadpl */ + var34.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 2: mulslq */ + var36.i = ((orc_int64) var33.i) * ((orc_int64) var34.i); + /* 3: shrsq */ + var37.i = var36.i >> 27; + /* 4: convql */ + var35.i = var37.i; + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int32; +void +orc_process_int32 (gint32 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int32; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int32_clamp */ +#ifdef DISABLE_ORC +void +orc_process_int32_clamp (gint32 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) d1; + + /* 1: loadpl */ + var34.i = p1; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 2: mulslq */ + var36.i = ((orc_int64) var33.i) * ((orc_int64) var34.i); + /* 3: shrsq */ + var37.i = var36.i >> 27; + /* 4: convsssql */ + var35.i = ORC_CLAMP_SL (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int32_clamp (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + orc_union32 var33; + orc_union32 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + + /* 1: loadpl */ + var34.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 2: mulslq */ + var36.i = ((orc_int64) var33.i) * ((orc_int64) var34.i); + /* 3: shrsq */ + var37.i = var36.i >> 27; + /* 4: convsssql */ + var35.i = ORC_CLAMP_SL (var37.i); + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int32_clamp; +void +orc_process_int32_clamp (gint32 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int32_clamp; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int16 */ +#ifdef DISABLE_ORC +void +orc_process_int16 (gint16 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var33; + orc_union16 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) d1; + + /* 1: loadpw */ + var34.i = p1; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr0[i]; + /* 2: mulswl */ + var36.i = var33.i * var34.i; + /* 3: shrsl */ + var37.i = var36.i >> 13; + /* 4: convlw */ + var35.i = var37.i; + /* 5: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int16 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var33; + orc_union16 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) ex->arrays[0]; + + /* 1: loadpw */ + var34.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr0[i]; + /* 2: mulswl */ + var36.i = var33.i * var34.i; + /* 3: shrsl */ + var37.i = var36.i >> 13; + /* 4: convlw */ + var35.i = var37.i; + /* 5: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int16; +void +orc_process_int16 (gint16 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int16; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int16_clamp */ +#ifdef DISABLE_ORC +void +orc_process_int16_clamp (gint16 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var33; + orc_union16 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) d1; + + /* 1: loadpw */ + var34.i = p1; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr0[i]; + /* 2: mulswl */ + var36.i = var33.i * var34.i; + /* 3: shrsl */ + var37.i = var36.i >> 13; + /* 4: convssslw */ + var35.i = ORC_CLAMP_SW (var37.i); + /* 5: storew */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int16_clamp (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + orc_union16 var33; + orc_union16 var34; + orc_union16 var35; + orc_union32 var36; + orc_union32 var37; + + ptr0 = (orc_union16 *) ex->arrays[0]; + + /* 1: loadpw */ + var34.i = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var33 = ptr0[i]; + /* 2: mulswl */ + var36.i = var33.i * var34.i; + /* 3: shrsl */ + var37.i = var36.i >> 13; + /* 4: convssslw */ + var35.i = ORC_CLAMP_SW (var37.i); + /* 5: storew */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int16_clamp; +void +orc_process_int16_clamp (gint16 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int16_clamp; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int8 */ +#ifdef DISABLE_ORC +void +orc_process_int8 (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var33; + orc_int8 var34; + orc_int8 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) d1; + + /* 1: loadpb */ + var34 = p1; + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var33 = ptr0[i]; + /* 2: mulsbw */ + var36.i = var33 * var34; + /* 3: shrsw */ + var37.i = var36.i >> 5; + /* 4: convwb */ + var35 = var37.i; + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int8 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var33; + orc_int8 var34; + orc_int8 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) ex->arrays[0]; + + /* 1: loadpb */ + var34 = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var33 = ptr0[i]; + /* 2: mulsbw */ + var36.i = var33 * var34; + /* 3: shrsw */ + var37.i = var36.i >> 5; + /* 4: convwb */ + var35 = var37.i; + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int8; +void +orc_process_int8 (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int8; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_int8_clamp */ +#ifdef DISABLE_ORC +void +orc_process_int8_clamp (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var33; + orc_int8 var34; + orc_int8 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) d1; + + /* 1: loadpb */ + var34 = p1; + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var33 = ptr0[i]; + /* 2: mulsbw */ + var36.i = var33 * var34; + /* 3: shrsw */ + var37.i = var36.i >> 5; + /* 4: convssswb */ + var35 = ORC_CLAMP_SB (var37.i); + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_int8_clamp (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + orc_int8 var33; + orc_int8 var34; + orc_int8 var35; + orc_union16 var36; + orc_union16 var37; + + ptr0 = (orc_int8 *) ex->arrays[0]; + + /* 1: loadpb */ + var34 = ex->params[24]; + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var33 = ptr0[i]; + /* 2: mulsbw */ + var36.i = var33 * var34; + /* 3: shrsw */ + var37.i = var36.i >> 5; + /* 4: convssswb */ + var35 = ORC_CLAMP_SB (var37.i); + /* 5: storeb */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_int8_clamp; +void +orc_process_int8_clamp (gint8 * ORC_RESTRICT d1, int p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_int8_clamp; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->params[ORC_VAR_P1] = p1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_memset_f64 */ +#ifdef DISABLE_ORC +void +orc_memset_f64 (gdouble * ORC_RESTRICT d1, double p1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) d1; + + /* 0: loadpq */ + var32.f = p1; + + for (i = 0; i < n; i++) { + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +#else +static void +_backup_orc_memset_f64 (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + orc_union64 var32; + orc_union64 var33; + + ptr0 = (orc_union64 *) ex->arrays[0]; + + /* 0: loadpq */ + var32.i = + (ex->params[24] & 0xffffffff) | ((orc_uint64) (ex->params[24 + + (ORC_VAR_T1 - ORC_VAR_P1)]) << 32); + + for (i = 0; i < n; i++) { + /* 1: copyq */ + var33.i = var32.i; + /* 2: storeq */ + ptr0[i] = var33; + } + +} + +static OrcProgram *_orc_program_orc_memset_f64; +void +orc_memset_f64 (gdouble * ORC_RESTRICT d1, double p1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_memset_f64; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + { + orc_union64 tmp; + tmp.f = p1; + ex->params[ORC_VAR_P1] = tmp.x2[0]; + ex->params[ORC_VAR_T1] = tmp.x2[1]; + } + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_prepare_volumes */ +#ifdef DISABLE_ORC +void +orc_prepare_volumes (gdouble * ORC_RESTRICT d1, + const gboolean * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union64 var37; + orc_union64 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union32 *) s1; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x3ff0000000000000); /* 1f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var37.f = var33.i; + /* 3: subd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var34.i); + _src2.i = ORC_DENORMAL_DOUBLE (var37.i); + _dest1.f = _src1.f - _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: loadq */ + var35 = ptr0[i]; + /* 5: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _src2.i = ORC_DENORMAL_DOUBLE (var38.i); + _dest1.f = _src1.f * _src2.f; + var36.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 6: storeq */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_prepare_volumes (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union32 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union64 var37; + orc_union64 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union32 *) ex->arrays[4]; + + /* 2: loadpq */ + var34.i = ORC_UINT64_C (0x3ff0000000000000); /* 1f */ + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr4[i]; + /* 1: convld */ + var37.f = var33.i; + /* 3: subd */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var34.i); + _src2.i = ORC_DENORMAL_DOUBLE (var37.i); + _dest1.f = _src1.f - _src2.f; + var38.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: loadq */ + var35 = ptr0[i]; + /* 5: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _src2.i = ORC_DENORMAL_DOUBLE (var38.i); + _dest1.f = _src1.f * _src2.f; + var36.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 6: storeq */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_prepare_volumes; +void +orc_prepare_volumes (gdouble * ORC_RESTRICT d1, + const gboolean * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_prepare_volumes; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_f64_1ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_f64_1ch (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + orc_union64 var34; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr0[i]; + /* 1: loadq */ + var33 = ptr4[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +#else +static void +_backup_orc_process_controlled_f64_1ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var32; + orc_union64 var33; + orc_union64 var34; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var32 = ptr0[i]; + /* 1: loadq */ + var33 = ptr4[i]; + /* 2: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var32.i); + _src2.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest1.f = _src1.f * _src2.f; + var34.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 3: storeq */ + ptr0[i] = var34; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_f64_1ch; +void +orc_process_controlled_f64_1ch (gdouble * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_f64_1ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_f32_1ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_f32_1ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest.f = _src1.f; + var36.i = ORC_DENORMAL (_dest.i); + } + /* 2: loadl */ + var34 = ptr0[i]; + /* 3: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var34.i); + _src2.i = ORC_DENORMAL (var36.i); + _dest1.f = _src1.f * _src2.f; + var35.i = ORC_DENORMAL (_dest1.i); + } + /* 4: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_controlled_f32_1ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var33; + orc_union32 var34; + orc_union32 var35; + orc_union32 var36; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var33 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var33.i); + _dest.f = _src1.f; + var36.i = ORC_DENORMAL (_dest.i); + } + /* 2: loadl */ + var34 = ptr0[i]; + /* 3: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var34.i); + _src2.i = ORC_DENORMAL (var36.i); + _dest1.f = _src1.f * _src2.f; + var35.i = ORC_DENORMAL (_dest1.i); + } + /* 4: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_f32_1ch; +void +orc_process_controlled_f32_1ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_f32_1ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_f32_2ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_f32_2ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union32 var37; + orc_union64 var38; + + ptr0 = (orc_union64 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest.f = _src1.f; + var37.i = ORC_DENORMAL (_dest.i); + } + /* 2: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var37.i; + _dest.x2[1] = var37.i; + var38.i = _dest.i; + } + /* 3: loadq */ + var35 = ptr0[i]; + /* 4: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.x2[0]); + _src2.i = ORC_DENORMAL (var38.x2[0]); + _dest1.f = _src1.f * _src2.f; + var36.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.x2[1]); + _src2.i = ORC_DENORMAL (var38.x2[1]); + _dest1.f = _src1.f * _src2.f; + var36.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 5: storeq */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_process_controlled_f32_2ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union64 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union64 var34; + orc_union64 var35; + orc_union64 var36; + orc_union32 var37; + orc_union64 var38; + + ptr0 = (orc_union64 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadq */ + var34 = ptr4[i]; + /* 1: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest.f = _src1.f; + var37.i = ORC_DENORMAL (_dest.i); + } + /* 2: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var37.i; + _dest.x2[1] = var37.i; + var38.i = _dest.i; + } + /* 3: loadq */ + var35 = ptr0[i]; + /* 4: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.x2[0]); + _src2.i = ORC_DENORMAL (var38.x2[0]); + _dest1.f = _src1.f * _src2.f; + var36.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var35.x2[1]); + _src2.i = ORC_DENORMAL (var38.x2[1]); + _dest1.f = _src1.f * _src2.f; + var36.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 5: storeq */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_f32_2ch; +void +orc_process_controlled_f32_2ch (gfloat * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_f32_2ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_int32_1ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_int32_1ch (gint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 1: convld */ + var36.f = var33.i; + /* 2: loadq */ + var34 = ptr4[i]; + /* 3: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: convdl */ + { + int tmp; + tmp = var37.f; + if (tmp == 0x80000000 && !(var37.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 5: storel */ + ptr0[i] = var35; + } + +} + +#else +static void +_backup_orc_process_controlled_int32_1ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union32 var33; + orc_union64 var34; + orc_union32 var35; + orc_union64 var36; + orc_union64 var37; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var33 = ptr0[i]; + /* 1: convld */ + var36.f = var33.i; + /* 2: loadq */ + var34 = ptr4[i]; + /* 3: muld */ + { + orc_union64 _src1; + orc_union64 _src2; + orc_union64 _dest1; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _src2.i = ORC_DENORMAL_DOUBLE (var34.i); + _dest1.f = _src1.f * _src2.f; + var37.i = ORC_DENORMAL_DOUBLE (_dest1.i); + } + /* 4: convdl */ + { + int tmp; + tmp = var37.f; + if (tmp == 0x80000000 && !(var37.i & ORC_UINT64_C (0x8000000000000000))) + tmp = 0x7fffffff; + var35.i = tmp; + } + /* 5: storel */ + ptr0[i] = var35; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_int32_1ch; +void +orc_process_controlled_int32_1ch (gint32 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_int32_1ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_int16_1ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_int16_1ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr0[i]; + /* 1: convswl */ + var37.i = var34.i; + /* 2: convlf */ + var38.f = var37.i; + /* 3: loadq */ + var35 = ptr4[i]; + /* 4: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _dest.f = _src1.f; + var39.i = ORC_DENORMAL (_dest.i); + } + /* 5: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var38.i); + _src2.i = ORC_DENORMAL (var39.i); + _dest1.f = _src1.f * _src2.f; + var40.i = ORC_DENORMAL (_dest1.i); + } + /* 6: convfl */ + { + int tmp; + tmp = (int) var40.f; + if (tmp == 0x80000000 && !(var40.i & 0x80000000)) + tmp = 0x7fffffff; + var41.i = tmp; + } + /* 7: convssslw */ + var36.i = ORC_CLAMP_SW (var41.i); + /* 8: storew */ + ptr0[i] = var36; + } + +} + +#else +static void +_backup_orc_process_controlled_int16_1ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union16 var34; + orc_union64 var35; + orc_union16 var36; + orc_union32 var37; + orc_union32 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var34 = ptr0[i]; + /* 1: convswl */ + var37.i = var34.i; + /* 2: convlf */ + var38.f = var37.i; + /* 3: loadq */ + var35 = ptr4[i]; + /* 4: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var35.i); + _dest.f = _src1.f; + var39.i = ORC_DENORMAL (_dest.i); + } + /* 5: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var38.i); + _src2.i = ORC_DENORMAL (var39.i); + _dest1.f = _src1.f * _src2.f; + var40.i = ORC_DENORMAL (_dest1.i); + } + /* 6: convfl */ + { + int tmp; + tmp = (int) var40.f; + if (tmp == 0x80000000 && !(var40.i & 0x80000000)) + tmp = 0x7fffffff; + var41.i = tmp; + } + /* 7: convssslw */ + var36.i = ORC_CLAMP_SW (var41.i); + /* 8: storew */ + ptr0[i] = var36; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_int16_1ch; +void +orc_process_controlled_int16_1ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_int16_1ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_int16_2ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_int16_2ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union32 var35; + orc_union64 var36; + orc_union32 var37; + orc_union64 var38; + orc_union64 var39; + orc_union32 var40; + orc_union64 var41; + orc_union64 var42; + orc_union64 var43; + + ptr0 = (orc_union32 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var35 = ptr0[i]; + /* 1: convswl */ + var38.x2[0] = var35.x2[0]; + var38.x2[1] = var35.x2[1]; + /* 2: convlf */ + var39.x2f[0] = var38.x2[0]; + var39.x2f[1] = var38.x2[1]; + /* 3: loadq */ + var36 = ptr4[i]; + /* 4: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var40.i = ORC_DENORMAL (_dest.i); + } + /* 5: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var40.i; + _dest.x2[1] = var40.i; + var41.i = _dest.i; + } + /* 6: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var41.x2[0]); + _src2.i = ORC_DENORMAL (var39.x2[0]); + _dest1.f = _src1.f * _src2.f; + var42.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var41.x2[1]); + _src2.i = ORC_DENORMAL (var39.x2[1]); + _dest1.f = _src1.f * _src2.f; + var42.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 7: convfl */ + { + int tmp; + tmp = (int) var42.x2f[0]; + if (tmp == 0x80000000 && !(var42.x2[0] & 0x80000000)) + tmp = 0x7fffffff; + var43.x2[0] = tmp; + } + { + int tmp; + tmp = (int) var42.x2f[1]; + if (tmp == 0x80000000 && !(var42.x2[1] & 0x80000000)) + tmp = 0x7fffffff; + var43.x2[1] = tmp; + } + /* 8: convssslw */ + var37.x2[0] = ORC_CLAMP_SW (var43.x2[0]); + var37.x2[1] = ORC_CLAMP_SW (var43.x2[1]); + /* 9: storel */ + ptr0[i] = var37; + } + +} + +#else +static void +_backup_orc_process_controlled_int16_2ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union32 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union32 var35; + orc_union64 var36; + orc_union32 var37; + orc_union64 var38; + orc_union64 var39; + orc_union32 var40; + orc_union64 var41; + orc_union64 var42; + orc_union64 var43; + + ptr0 = (orc_union32 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadl */ + var35 = ptr0[i]; + /* 1: convswl */ + var38.x2[0] = var35.x2[0]; + var38.x2[1] = var35.x2[1]; + /* 2: convlf */ + var39.x2f[0] = var38.x2[0]; + var39.x2f[1] = var38.x2[1]; + /* 3: loadq */ + var36 = ptr4[i]; + /* 4: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var40.i = ORC_DENORMAL (_dest.i); + } + /* 5: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var40.i; + _dest.x2[1] = var40.i; + var41.i = _dest.i; + } + /* 6: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var41.x2[0]); + _src2.i = ORC_DENORMAL (var39.x2[0]); + _dest1.f = _src1.f * _src2.f; + var42.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var41.x2[1]); + _src2.i = ORC_DENORMAL (var39.x2[1]); + _dest1.f = _src1.f * _src2.f; + var42.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 7: convfl */ + { + int tmp; + tmp = (int) var42.x2f[0]; + if (tmp == 0x80000000 && !(var42.x2[0] & 0x80000000)) + tmp = 0x7fffffff; + var43.x2[0] = tmp; + } + { + int tmp; + tmp = (int) var42.x2f[1]; + if (tmp == 0x80000000 && !(var42.x2[1] & 0x80000000)) + tmp = 0x7fffffff; + var43.x2[1] = tmp; + } + /* 8: convssslw */ + var37.x2[0] = ORC_CLAMP_SW (var43.x2[0]); + var37.x2[1] = ORC_CLAMP_SW (var43.x2[1]); + /* 9: storel */ + ptr0[i] = var37; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_int16_2ch; +void +orc_process_controlled_int16_2ch (gint16 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_int16_2ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_int8_1ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_int8_1ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_int8 var35; + orc_union64 var36; + orc_int8 var37; + orc_union16 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union32 var42; + orc_union32 var43; + orc_union16 var44; + + ptr0 = (orc_int8 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var35 = ptr0[i]; + /* 1: convsbw */ + var38.i = var35; + /* 2: convswl */ + var39.i = var38.i; + /* 3: convlf */ + var40.f = var39.i; + /* 4: loadq */ + var36 = ptr4[i]; + /* 5: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var41.i = ORC_DENORMAL (_dest.i); + } + /* 6: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.i); + _src2.i = ORC_DENORMAL (var41.i); + _dest1.f = _src1.f * _src2.f; + var42.i = ORC_DENORMAL (_dest1.i); + } + /* 7: convfl */ + { + int tmp; + tmp = (int) var42.f; + if (tmp == 0x80000000 && !(var42.i & 0x80000000)) + tmp = 0x7fffffff; + var43.i = tmp; + } + /* 8: convlw */ + var44.i = var43.i; + /* 9: convssswb */ + var37 = ORC_CLAMP_SB (var44.i); + /* 10: storeb */ + ptr0[i] = var37; + } + +} + +#else +static void +_backup_orc_process_controlled_int8_1ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_int8 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_int8 var35; + orc_union64 var36; + orc_int8 var37; + orc_union16 var38; + orc_union32 var39; + orc_union32 var40; + orc_union32 var41; + orc_union32 var42; + orc_union32 var43; + orc_union16 var44; + + ptr0 = (orc_int8 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadb */ + var35 = ptr0[i]; + /* 1: convsbw */ + var38.i = var35; + /* 2: convswl */ + var39.i = var38.i; + /* 3: convlf */ + var40.f = var39.i; + /* 4: loadq */ + var36 = ptr4[i]; + /* 5: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var41.i = ORC_DENORMAL (_dest.i); + } + /* 6: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.i); + _src2.i = ORC_DENORMAL (var41.i); + _dest1.f = _src1.f * _src2.f; + var42.i = ORC_DENORMAL (_dest1.i); + } + /* 7: convfl */ + { + int tmp; + tmp = (int) var42.f; + if (tmp == 0x80000000 && !(var42.i & 0x80000000)) + tmp = 0x7fffffff; + var43.i = tmp; + } + /* 8: convlw */ + var44.i = var43.i; + /* 9: convssswb */ + var37 = ORC_CLAMP_SB (var44.i); + /* 10: storeb */ + ptr0[i] = var37; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_int8_1ch; +void +orc_process_controlled_int8_1ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_int8_1ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +/* orc_process_controlled_int8_2ch */ +#ifdef DISABLE_ORC +void +orc_process_controlled_int8_2ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + int i; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union16 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union64 var39; + orc_union64 var40; + orc_union32 var41; + orc_union64 var42; + orc_union64 var43; + orc_union64 var44; + orc_union32 var45; + + ptr0 = (orc_union16 *) d1; + ptr4 = (orc_union64 *) s1; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var35 = ptr0[i]; + /* 1: convsbw */ + var38.x2[0] = var35.x2[0]; + var38.x2[1] = var35.x2[1]; + /* 2: convswl */ + var39.x2[0] = var38.x2[0]; + var39.x2[1] = var38.x2[1]; + /* 3: convlf */ + var40.x2f[0] = var39.x2[0]; + var40.x2f[1] = var39.x2[1]; + /* 4: loadq */ + var36 = ptr4[i]; + /* 5: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var41.i = ORC_DENORMAL (_dest.i); + } + /* 6: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var41.i; + _dest.x2[1] = var41.i; + var42.i = _dest.i; + } + /* 7: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.x2[0]); + _src2.i = ORC_DENORMAL (var42.x2[0]); + _dest1.f = _src1.f * _src2.f; + var43.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.x2[1]); + _src2.i = ORC_DENORMAL (var42.x2[1]); + _dest1.f = _src1.f * _src2.f; + var43.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 8: convfl */ + { + int tmp; + tmp = (int) var43.x2f[0]; + if (tmp == 0x80000000 && !(var43.x2[0] & 0x80000000)) + tmp = 0x7fffffff; + var44.x2[0] = tmp; + } + { + int tmp; + tmp = (int) var43.x2f[1]; + if (tmp == 0x80000000 && !(var43.x2[1] & 0x80000000)) + tmp = 0x7fffffff; + var44.x2[1] = tmp; + } + /* 9: convlw */ + var45.x2[0] = var44.x2[0]; + var45.x2[1] = var44.x2[1]; + /* 10: convssswb */ + var37.x2[0] = ORC_CLAMP_SB (var45.x2[0]); + var37.x2[1] = ORC_CLAMP_SB (var45.x2[1]); + /* 11: storew */ + ptr0[i] = var37; + } + +} + +#else +static void +_backup_orc_process_controlled_int8_2ch (OrcExecutor * ORC_RESTRICT ex) +{ + int i; + int n = ex->n; + orc_union16 *ORC_RESTRICT ptr0; + const orc_union64 *ORC_RESTRICT ptr4; + orc_union16 var35; + orc_union64 var36; + orc_union16 var37; + orc_union32 var38; + orc_union64 var39; + orc_union64 var40; + orc_union32 var41; + orc_union64 var42; + orc_union64 var43; + orc_union64 var44; + orc_union32 var45; + + ptr0 = (orc_union16 *) ex->arrays[0]; + ptr4 = (orc_union64 *) ex->arrays[4]; + + + for (i = 0; i < n; i++) { + /* 0: loadw */ + var35 = ptr0[i]; + /* 1: convsbw */ + var38.x2[0] = var35.x2[0]; + var38.x2[1] = var35.x2[1]; + /* 2: convswl */ + var39.x2[0] = var38.x2[0]; + var39.x2[1] = var38.x2[1]; + /* 3: convlf */ + var40.x2f[0] = var39.x2[0]; + var40.x2f[1] = var39.x2[1]; + /* 4: loadq */ + var36 = ptr4[i]; + /* 5: convdf */ + { + orc_union64 _src1; + orc_union32 _dest; + _src1.i = ORC_DENORMAL_DOUBLE (var36.i); + _dest.f = _src1.f; + var41.i = ORC_DENORMAL (_dest.i); + } + /* 6: mergelq */ + { + orc_union64 _dest; + _dest.x2[0] = var41.i; + _dest.x2[1] = var41.i; + var42.i = _dest.i; + } + /* 7: mulf */ + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.x2[0]); + _src2.i = ORC_DENORMAL (var42.x2[0]); + _dest1.f = _src1.f * _src2.f; + var43.x2[0] = ORC_DENORMAL (_dest1.i); + } + { + orc_union32 _src1; + orc_union32 _src2; + orc_union32 _dest1; + _src1.i = ORC_DENORMAL (var40.x2[1]); + _src2.i = ORC_DENORMAL (var42.x2[1]); + _dest1.f = _src1.f * _src2.f; + var43.x2[1] = ORC_DENORMAL (_dest1.i); + } + /* 8: convfl */ + { + int tmp; + tmp = (int) var43.x2f[0]; + if (tmp == 0x80000000 && !(var43.x2[0] & 0x80000000)) + tmp = 0x7fffffff; + var44.x2[0] = tmp; + } + { + int tmp; + tmp = (int) var43.x2f[1]; + if (tmp == 0x80000000 && !(var43.x2[1] & 0x80000000)) + tmp = 0x7fffffff; + var44.x2[1] = tmp; + } + /* 9: convlw */ + var45.x2[0] = var44.x2[0]; + var45.x2[1] = var44.x2[1]; + /* 10: convssswb */ + var37.x2[0] = ORC_CLAMP_SB (var45.x2[0]); + var37.x2[1] = ORC_CLAMP_SB (var45.x2[1]); + /* 11: storew */ + ptr0[i] = var37; + } + +} + +static OrcProgram *_orc_program_orc_process_controlled_int8_2ch; +void +orc_process_controlled_int8_2ch (gint8 * ORC_RESTRICT d1, + const gdouble * ORC_RESTRICT s1, int n) +{ + OrcExecutor _ex, *ex = &_ex; + OrcProgram *p = _orc_program_orc_process_controlled_int8_2ch; + void (*func) (OrcExecutor *); + + ex->program = p; + + ex->n = n; + ex->arrays[ORC_VAR_D1] = d1; + ex->arrays[ORC_VAR_S1] = (void *) s1; + + func = p->code_exec; + func (ex); +} +#endif + + +void +gst_volume_orc_init (void) +{ +#ifndef DISABLE_ORC + { + /* orc_scalarmultiply_f64_ns */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_scalarmultiply_f64_ns"); + orc_program_set_backup_function (p, _backup_orc_scalarmultiply_f64_ns); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_parameter_double (p, 8, "p1"); + + orc_program_append_2 (p, "muld", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_scalarmultiply_f64_ns = p; + } + { + /* orc_scalarmultiply_f32_ns */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_scalarmultiply_f32_ns"); + orc_program_set_backup_function (p, _backup_orc_scalarmultiply_f32_ns); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_parameter_float (p, 4, "p1"); + + orc_program_append_2 (p, "mulf", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_scalarmultiply_f32_ns = p; + } + { + /* orc_process_int32 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int32"); + orc_program_set_backup_function (p, _backup_orc_process_int32); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_constant (p, 4, 0x0000001b, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "mulslq", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsq", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convql", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int32 = p; + } + { + /* orc_process_int32_clamp */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int32_clamp"); + orc_program_set_backup_function (p, _backup_orc_process_int32_clamp); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_constant (p, 4, 0x0000001b, "c1"); + orc_program_add_parameter (p, 4, "p1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "mulslq", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsq", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convsssql", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int32_clamp = p; + } + { + /* orc_process_int16 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int16"); + orc_program_set_backup_function (p, _backup_orc_process_int16); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_constant (p, 4, 0x0000000d, "c1"); + orc_program_add_parameter (p, 2, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "mulswl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int16 = p; + } + { + /* orc_process_int16_clamp */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int16_clamp"); + orc_program_set_backup_function (p, _backup_orc_process_int16_clamp); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_constant (p, 4, 0x0000000d, "c1"); + orc_program_add_parameter (p, 2, "p1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "mulswl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssslw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int16_clamp = p; + } + { + /* orc_process_int8 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int8"); + orc_program_set_backup_function (p, _backup_orc_process_int8); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_constant (p, 4, 0x00000005, "c1"); + orc_program_add_parameter (p, 1, "p1"); + orc_program_add_temporary (p, 2, "t1"); + + orc_program_append_2 (p, "mulsbw", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convwb", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int8 = p; + } + { + /* orc_process_int8_clamp */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_int8_clamp"); + orc_program_set_backup_function (p, _backup_orc_process_int8_clamp); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_constant (p, 4, 0x00000005, "c1"); + orc_program_add_parameter (p, 1, "p1"); + orc_program_add_temporary (p, 2, "t1"); + + orc_program_append_2 (p, "mulsbw", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_P1, + ORC_VAR_D1); + orc_program_append_2 (p, "shrsw", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_C1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssswb", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_int8_clamp = p; + } + { + /* orc_memset_f64 */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_memset_f64"); + orc_program_set_backup_function (p, _backup_orc_memset_f64); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_parameter_double (p, 8, "p1"); + + orc_program_append_2 (p, "copyq", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_memset_f64 = p; + } + { + /* orc_prepare_volumes */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_prepare_volumes"); + orc_program_set_backup_function (p, _backup_orc_prepare_volumes); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 4, "s1"); + orc_program_add_constant_int64 (p, 8, 0x3ff0000000000000ULL, "c1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "convld", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "subd", 0, ORC_VAR_T1, ORC_VAR_C1, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "muld", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_T1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_prepare_volumes = p; + } + { + /* orc_process_controlled_f64_1ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_f64_1ch"); + orc_program_set_backup_function (p, _backup_orc_process_controlled_f64_1ch); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 8, "s1"); + + orc_program_append_2 (p, "muld", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_S1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_f64_1ch = p; + } + { + /* orc_process_controlled_f32_1ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_f32_1ch"); + orc_program_set_backup_function (p, _backup_orc_process_controlled_f32_1ch); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 0, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_T1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_f32_1ch = p; + } + { + /* orc_process_controlled_f32_2ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_f32_2ch"); + orc_program_set_backup_function (p, _backup_orc_process_controlled_f32_2ch); + orc_program_add_destination (p, 8, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 8, "t2"); + + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mergelq", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 1, ORC_VAR_D1, ORC_VAR_D1, ORC_VAR_T2, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_f32_2ch = p; + } + { + /* orc_process_controlled_int32_1ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_int32_1ch"); + orc_program_set_backup_function (p, + _backup_orc_process_controlled_int32_1ch); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 8, "t1"); + + orc_program_append_2 (p, "convld", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "muld", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_S1, + ORC_VAR_D1); + orc_program_append_2 (p, "convdl", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_int32_1ch = p; + } + { + /* orc_process_controlled_int16_1ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_int16_1ch"); + orc_program_set_backup_function (p, + _backup_orc_process_controlled_int16_1ch); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 4, "t2"); + + orc_program_append_2 (p, "convswl", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T2, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 0, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssslw", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_int16_1ch = p; + } + { + /* orc_process_controlled_int16_2ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_int16_2ch"); + orc_program_set_backup_function (p, + _backup_orc_process_controlled_int16_2ch); + orc_program_add_destination (p, 4, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 8, "t1"); + orc_program_add_temporary (p, 4, "t2"); + orc_program_add_temporary (p, 8, "t3"); + + orc_program_append_2 (p, "convswl", 1, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlf", 1, ORC_VAR_T1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T2, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mergelq", 0, ORC_VAR_T3, ORC_VAR_T2, ORC_VAR_T2, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 1, ORC_VAR_T3, ORC_VAR_T3, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 1, ORC_VAR_T3, ORC_VAR_T3, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssslw", 1, ORC_VAR_D1, ORC_VAR_T3, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_int16_2ch = p; + } + { + /* orc_process_controlled_int8_1ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_int8_1ch"); + orc_program_set_backup_function (p, + _backup_orc_process_controlled_int8_1ch); + orc_program_add_destination (p, 1, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 2, "t1"); + orc_program_add_temporary (p, 4, "t2"); + orc_program_add_temporary (p, 4, "t3"); + + orc_program_append_2 (p, "convsbw", 0, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convswl", 0, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlf", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T3, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_T3, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 0, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 0, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssswb", 0, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_int8_1ch = p; + } + { + /* orc_process_controlled_int8_2ch */ + OrcProgram *p; + + p = orc_program_new (); + orc_program_set_name (p, "orc_process_controlled_int8_2ch"); + orc_program_set_backup_function (p, + _backup_orc_process_controlled_int8_2ch); + orc_program_add_destination (p, 2, "d1"); + orc_program_add_source (p, 8, "s1"); + orc_program_add_temporary (p, 4, "t1"); + orc_program_add_temporary (p, 8, "t2"); + orc_program_add_temporary (p, 8, "t3"); + + orc_program_append_2 (p, "convsbw", 1, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convswl", 1, ORC_VAR_T2, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlf", 1, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convdf", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "mergelq", 0, ORC_VAR_T3, ORC_VAR_T1, ORC_VAR_T1, + ORC_VAR_D1); + orc_program_append_2 (p, "mulf", 1, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_T3, + ORC_VAR_D1); + orc_program_append_2 (p, "convfl", 1, ORC_VAR_T2, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convlw", 1, ORC_VAR_T1, ORC_VAR_T2, ORC_VAR_D1, + ORC_VAR_D1); + orc_program_append_2 (p, "convssswb", 1, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_D1, + ORC_VAR_D1); + + orc_program_compile (p); + + _orc_program_orc_process_controlled_int8_2ch = p; + } +#endif +} diff --git a/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.h b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.h new file mode 100644 index 0000000..45411b8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc-dist.h @@ -0,0 +1,96 @@ + +/* autogenerated from gstvolumeorc.orc */ + +#ifndef _GSTVOLUMEORC_H_ +#define _GSTVOLUMEORC_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +void gst_volume_orc_init (void); + + + +#ifndef _ORC_INTEGER_TYPEDEFS_ +#define _ORC_INTEGER_TYPEDEFS_ +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +#include +typedef int8_t orc_int8; +typedef int16_t orc_int16; +typedef int32_t orc_int32; +typedef int64_t orc_int64; +typedef uint8_t orc_uint8; +typedef uint16_t orc_uint16; +typedef uint32_t orc_uint32; +typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) +#elif defined(_MSC_VER) +typedef signed __int8 orc_int8; +typedef signed __int16 orc_int16; +typedef signed __int32 orc_int32; +typedef signed __int64 orc_int64; +typedef unsigned __int8 orc_uint8; +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 +typedef signed char orc_int8; +typedef short orc_int16; +typedef int orc_int32; +typedef unsigned char orc_uint8; +typedef unsigned short orc_uint16; +typedef unsigned int orc_uint32; +#if INT_MAX == LONG_MAX +typedef long long orc_int64; +typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) +#else +typedef long orc_int64; +typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) +#endif +#endif +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 +#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_scalarmultiply_f64_ns (double * ORC_RESTRICT d1, double p1, int n); +void orc_scalarmultiply_f32_ns (float * ORC_RESTRICT d1, float p1, int n); +void orc_process_int32 (gint32 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int32_clamp (gint32 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int16 (gint16 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int16_clamp (gint16 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int8 (gint8 * ORC_RESTRICT d1, int p1, int n); +void orc_process_int8_clamp (gint8 * ORC_RESTRICT d1, int p1, int n); +void orc_memset_f64 (gdouble * ORC_RESTRICT d1, double p1, int n); +void orc_prepare_volumes (gdouble * ORC_RESTRICT d1, const gboolean * ORC_RESTRICT s1, int n); +void orc_process_controlled_f64_1ch (gdouble * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_f32_1ch (gfloat * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_f32_2ch (gfloat * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int32_1ch (gint32 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int16_1ch (gint16 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int16_2ch (gint16 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int8_1ch (gint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); +void orc_process_controlled_int8_2ch (gint8 * ORC_RESTRICT d1, const gdouble * ORC_RESTRICT s1, int n); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc.orc b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc.orc new file mode 100644 index 0000000..aaea6f5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/gstvolumeorc.orc @@ -0,0 +1,180 @@ + +.init gst_volume_orc_init + +.function orc_scalarmultiply_f64_ns +.dest 8 d1 double +.doubleparam 8 p1 + +muld d1, d1, p1 + +.function orc_scalarmultiply_f32_ns +.dest 4 d1 float +.floatparam 4 p1 + +mulf d1, d1, p1 + +.function orc_process_int32 +.dest 4 d1 gint32 +.param 4 p1 +.temp 8 t1 + +mulslq t1, d1, p1 +shrsq t1, t1, 27 +convql d1, t1 + +.function orc_process_int32_clamp +.dest 4 d1 gint32 +.param 4 p1 +.temp 8 t1 + +mulslq t1, d1, p1 +shrsq t1, t1, 27 +convsssql d1, t1 + +.function orc_process_int16 +.dest 2 d1 gint16 +.param 2 p1 +.temp 4 t1 + +mulswl t1, d1, p1 +shrsl t1, t1, 13 +convlw d1, t1 + + +.function orc_process_int16_clamp +.dest 2 d1 gint16 +.param 2 p1 +.temp 4 t1 + +mulswl t1, d1, p1 +shrsl t1, t1, 13 +convssslw d1, t1 + +.function orc_process_int8 +.dest 1 d1 gint8 +.param 1 p1 +.temp 2 t1 + +mulsbw t1, d1, p1 +shrsw t1, t1, 5 +convwb d1, t1 + + +.function orc_process_int8_clamp +.dest 1 d1 gint8 +.param 1 p1 +.temp 2 t1 + +mulsbw t1, d1, p1 +shrsw t1, t1, 5 +convssswb d1, t1 + +.function orc_memset_f64 +.dest 8 d1 gdouble +.doubleparam 8 p1 + +copyq d1, p1 + +.function orc_prepare_volumes +.dest 8 d1 gdouble +.source 4 s1 gboolean +.temp 8 t1 + +convld t1, s1 +subd t1, 0x3FF0000000000000L, t1 +muld d1, d1, t1 + +.function orc_process_controlled_f64_1ch +.dest 8 d1 gdouble +.source 8 s1 gdouble + +muld d1, d1, s1 + +.function orc_process_controlled_f32_1ch +.dest 4 d1 gfloat +.source 8 s1 gdouble +.temp 4 t1 + +convdf t1, s1 +mulf d1, d1, t1 + +.function orc_process_controlled_f32_2ch +.dest 8 d1 gfloat +.source 8 s1 gdouble +.temp 4 t1 +.temp 8 t2 + +convdf t1, s1 +mergelq t2, t1, t1 +x2 mulf d1, d1, t2 + +.function orc_process_controlled_int32_1ch +.dest 4 d1 gint32 +.source 8 s1 gdouble +.temp 8 t1 + +convld t1, d1 +muld t1, t1, s1 +convdl d1, t1 + +.function orc_process_controlled_int16_1ch +.dest 2 d1 gint16 +.source 8 s1 gdouble +.temp 4 t1 +.temp 4 t2 + +convswl t1, d1 +convlf t1, t1 +convdf t2, s1 +mulf t1, t1, t2 +convfl t1, t1 +convssslw d1, t1 + +.function orc_process_controlled_int16_2ch +.dest 4 d1 gint16 +.source 8 s1 gdouble +.temp 8 t1 +.temp 4 t2 +.temp 8 t3 + +x2 convswl t1, d1 +x2 convlf t1, t1 +convdf t2, s1 +mergelq t3, t2, t2 +x2 mulf t3, t3, t1 +x2 convfl t3, t3 +x2 convssslw d1, t3 + +.function orc_process_controlled_int8_1ch +.dest 1 d1 gint8 +.source 8 s1 gdouble +.temp 2 t1 +.temp 4 t2 +.temp 4 t3 + +convsbw t1, d1 +convswl t2, t1 +convlf t2, t2 +convdf t3, s1 +mulf t2, t2, t3 +convfl t2, t2 +convlw t1, t2 +convssswb d1, t1 + +.function orc_process_controlled_int8_2ch +.dest 2 d1 gint8 +.source 8 s1 gdouble +.temp 4 t1 +.temp 8 t2 +.temp 8 t3 + +x2 convsbw t1, d1 +x2 convswl t2, t1 +x2 convlf t2, t2 +convdf t1, s1 +mergelq t3, t1, t1 +x2 mulf t2, t2, t3 +x2 convfl t2, t2 +x2 convlw t1, t2 +x2 convssswb d1, t1 + diff --git a/gst-plugins-base-subtitles0.10/gst/volume/volume.vcproj b/gst-plugins-base-subtitles0.10/gst/volume/volume.vcproj new file mode 100644 index 0000000..149b8d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/gst/volume/volume.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/.gitignore b/gst-plugins-base-subtitles0.10/pkgconfig/.gitignore new file mode 100644 index 0000000..6fd0ef0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/.gitignore @@ -0,0 +1 @@ +*.pc diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/Makefile.am b/gst-plugins-base-subtitles0.10/pkgconfig/Makefile.am new file mode 100644 index 0000000..8fb2529 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/Makefile.am @@ -0,0 +1,69 @@ +### all of the standard pc files we need to generate +pcverfiles = \ + gstreamer-audio-@GST_MAJORMINOR@.pc \ + gstreamer-app-@GST_MAJORMINOR@.pc \ + gstreamer-cdda-@GST_MAJORMINOR@.pc \ + gstreamer-fft-@GST_MAJORMINOR@.pc \ + gstreamer-floatcast-@GST_MAJORMINOR@.pc \ + gstreamer-interfaces-@GST_MAJORMINOR@.pc \ + gstreamer-netbuffer-@GST_MAJORMINOR@.pc \ + gstreamer-pbutils-@GST_MAJORMINOR@.pc \ + gstreamer-riff-@GST_MAJORMINOR@.pc \ + gstreamer-rtp-@GST_MAJORMINOR@.pc \ + gstreamer-rtsp-@GST_MAJORMINOR@.pc \ + gstreamer-sdp-@GST_MAJORMINOR@.pc \ + gstreamer-tag-@GST_MAJORMINOR@.pc \ + gstreamer-video-@GST_MAJORMINOR@.pc \ + gstreamer-plugins-base-@GST_MAJORMINOR@.pc +pcverfiles_uninstalled = \ + gstreamer-audio-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-app-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-cdda-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-fft-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-floatcast-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-interfaces-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-netbuffer-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-pbutils-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-riff-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-rtp-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-rtsp-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-sdp-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-tag-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-video-@GST_MAJORMINOR@-uninstalled.pc \ + gstreamer-plugins-base-@GST_MAJORMINOR@-uninstalled.pc + +all-local: $(pcverfiles) $(pcverfiles_uninstalled) + +cp_verbose = $(cp_verbose_$(V)) +cp_verbose_ = $(cp_verbose_$(AM_DEFAULT_VERBOSITY)) +cp_verbose_0 = @echo " CP $@"; + +### how to generate versioned .pc files from .pc files in this dir +%-@GST_MAJORMINOR@.pc: %.pc + $(cp_verbose_0)cp $< $@ +%-@GST_MAJORMINOR@-uninstalled.pc: %-uninstalled.pc + $(cp_verbose_0)cp $< $@ + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = $(pcverfiles) + +CLEANFILES = $(pcverfiles) $(pcverfiles_uninstalled) +pcinfiles = \ + gstreamer-audio.pc.in gstreamer-audio-uninstalled.pc.in \ + gstreamer-app.pc.in gstreamer-app-uninstalled.pc.in \ + gstreamer-cdda.pc.in gstreamer-cdda-uninstalled.pc.in \ + gstreamer-fft.pc.in gstreamer-fft-uninstalled.pc.in \ + gstreamer-floatcast.pc.in gstreamer-floatcast-uninstalled.pc.in \ + gstreamer-interfaces.pc.in gstreamer-interfaces-uninstalled.pc.in \ + gstreamer-netbuffer.pc.in gstreamer-netbuffer-uninstalled.pc.in \ + gstreamer-pbutils.pc.in gstreamer-pbutils-uninstalled.pc.in \ + gstreamer-riff.pc.in gstreamer-riff-uninstalled.pc.in \ + gstreamer-rtp.pc.in gstreamer-rtp-uninstalled.pc.in \ + gstreamer-rtsp.pc.in gstreamer-rtsp-uninstalled.pc.in \ + gstreamer-sdp.pc.in gstreamer-sdp-uninstalled.pc.in \ + gstreamer-tag.pc.in gstreamer-tag-uninstalled.pc.in \ + gstreamer-video.pc.in gstreamer-video-uninstalled.pc.in \ + gstreamer-plugins-base.pc.in gstreamer-plugins-base-uninstalled.pc.in + +DISTCLEANFILES = $(pcinfiles:.in=) +EXTRA_DIST = $(pcinfiles) diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app-uninstalled.pc.in new file mode 100644 index 0000000..b989798 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/app +typelibdir=@abs_top_builddir@/gst-libs/gst/app + +Name: GStreamer Application Library, Uninstalled +Description: Helper functions and base classes for application integration, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app.pc.in new file mode 100644 index 0000000..8152eff --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-app.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Application Library +Description: Helper functions and base classes for application integration +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstapp-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio-uninstalled.pc.in new file mode 100644 index 0000000..ce55cf9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/audio +typelibdir=@abs_top_builddir@/gst-libs/gst/audio + +Name: GStreamer Audio Library, Uninstalled +Description: Audio helper functions and base classes, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ gstreamer-interfaces-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio.pc.in new file mode 100644 index 0000000..5743ccf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-audio.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Audio library +Description: Audio helper functions and base classes +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ gstreamer-interfaces-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstaudio-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda-uninstalled.pc.in new file mode 100644 index 0000000..15773e8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/cdda +typelibdir=@abs_top_builddir@/gst-libs/gst/cdda + +Name: GStreamer CDDA Library, Uninstalled +Description: CDDA base classes, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ gstreamer-tag-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/cdda/libgstcdda-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda.pc.in new file mode 100644 index 0000000..86f4a2b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-cdda.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer CDDA Library +Description: CDDA base classes +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ gstreamer-tag-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstcdda-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft-uninstalled.pc.in new file mode 100644 index 0000000..163f3f0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/fft +typelibdir=@abs_top_builddir@/gst-libs/gst/fft + +Name: GStreamer FFT Library, Uninstalled +Description: FFT implementation, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/fft/libgstfft-@GST_MAJORMINOR@.la @LIBM@ +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft.pc.in new file mode 100644 index 0000000..5680a0c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-fft.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer FFT Library +Description: FFT implementation +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstfft-@GST_MAJORMINOR@ @LIBM@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast-uninstalled.pc.in new file mode 100644 index 0000000..a8eacf7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast-uninstalled.pc.in @@ -0,0 +1,14 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs + +Name: GStreamer Floatcast Library, Uninstalled +Description: Platform independent floating point macros, uninstalled +Version: @VERSION@ +Requires: glib-2.0 +Libs: @LIBM@ +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast.pc.in new file mode 100644 index 0000000..c54b098 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-floatcast.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Floatcast Library +Description: Platform independent floating point macros +Requires: glib-2.0 +Version: @VERSION@ +Libs: @LIBM@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces-uninstalled.pc.in new file mode 100644 index 0000000..676a23f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/interfaces +typelibdir=@abs_top_builddir@/gst-libs/gst/interfaces + +Name: GStreamer Interfaces Library, Uninstalled +Description: Interfaces for GStreamer elements, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces.pc.in new file mode 100644 index 0000000..24749be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-interfaces.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Interfaces Library +Description: Interfaces for GStreamer elements +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstinterfaces-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer-uninstalled.pc.in new file mode 100644 index 0000000..941c728 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/netbuffer +typelibdir=@abs_top_builddir@/gst-libs/gst/netbuffer + +Name: GStreamer Network Buffer Library, Uninstalled +Description: Network buffer for use in network sources/sinks, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/netbuffer/libgstnetbuffer-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer.pc.in new file mode 100644 index 0000000..28d7ed2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-netbuffer.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Network Buffer Library +Description: Network buffer for use in network sources/sinks +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstnetbuffer-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils-uninstalled.pc.in new file mode 100644 index 0000000..e08758c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/pbutils +typelibdir=@abs_top_builddir@/gst-libs/gst/pbutils + +Name: GStreamer Base Utils Library, Uninstalled +Description: General utility functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils.pc.in new file mode 100644 index 0000000..e1626a4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-pbutils.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Base Utils Library +Description: General utility functions +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstpbutils-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in new file mode 100644 index 0000000..8a9bea2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +pluginsdir=@abs_top_builddir@ + +Name: GStreamer Base Plugins Libraries, Uninstalled +Description: Streaming media framework, base plugins libraries, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: -L@abs_top_builddir@/gst-libs/gst/audio -L@abs_top_builddir@/gst-libs/gst/cdda -L@abs_top_builddir@/gst-libs/gst/fft -L@abs_top_builddir@/gst-libs/gst/floatcast -L@abs_top_builddir@/gst-libs/gst/interfaces -L@abs_top_builddir@/gst-libs/gst/netbuffer -L@abs_top_builddir@/gst-libs/gst/riff -L@abs_top_builddir@/gst-libs/gst/rtp -L@abs_top_builddir@/gst-libs/gst/rtsp -L@abs_top_builddir@/gst-libs/gst/sdp -L@abs_top_builddir@/gst-libs/gst/tag -L@abs_top_builddir@/gst-libs/gst/pbutils -L@abs_top_builddir@/gst-libs/gst/video -L@abs_top_builddir@/gst-libs/gst/app +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + +libraries=app audio cdda fft floatcast interfaces netbuffer riff rtp rtsp sdp tag pbutils video diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base.pc.in new file mode 100644 index 0000000..4bc6088 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-plugins-base.pc.in @@ -0,0 +1,14 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +pluginsdir=@libdir@/gstreamer-@GST_MAJORMINOR@ + +Name: GStreamer Base Plugins Libraries +Description: Streaming media framework, base plugins libraries +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} +Cflags: -I${includedir} + +libraries=audio cdda fft floatcast interfaces netbuffer riff rtp tag pbutils video diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff-uninstalled.pc.in new file mode 100644 index 0000000..2592ba1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/riff +typelibdir=@abs_top_builddir@/gst-libs/gst/riff + +Name: GStreamer RIFF Library, Uninstalled +Description: RIFF helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/riff/libgstriff-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff.pc.in new file mode 100644 index 0000000..0858276 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-riff.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer RIFF Library +Description: RIFF helper functions +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstriff-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp-uninstalled.pc.in new file mode 100644 index 0000000..96c66cd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/rtp +typelibdir=@abs_top_builddir@/gst-libs/gst/rtp + +Name: GStreamer RTP Library, Uninstalled +Description: RTP base classes and helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/rtp/libgstrtp-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp.pc.in new file mode 100644 index 0000000..ff74a9d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtp.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer RTP Library +Description: RTP base classes and helper functions +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstrtp-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp-uninstalled.pc.in new file mode 100644 index 0000000..53258ec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/rtsp +typelibdir=@abs_top_builddir@/gst-libs/gst/rtsp + +Name: GStreamer RTSP Library, Uninstalled +Description: RTSP base classes and helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-sdp-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/rtsp/libgstrtsp-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp.pc.in new file mode 100644 index 0000000..203e400 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-rtsp.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer RTSP Library +Description: RTSP base classes and helper functions +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-sdp-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstrtsp-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp-uninstalled.pc.in new file mode 100644 index 0000000..bd1d89d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/sdp +typelibdir=@abs_top_builddir@/gst-libs/gst/sdp + +Name: GStreamer SDP Library, Uninstalled +Description: SDP helper functions, uninstalled +Version: @VERSION@ +Requires: glib-2.0 +Libs: @abs_top_builddir@/gst-libs/gst/sdp/libgstsdp-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp.pc.in new file mode 100644 index 0000000..9bb0f40 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-sdp.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer SDP Library +Description: SDP helper functions +Requires: glib-2.0 +Version: @VERSION@ +Libs: -L${libdir} -lgstsdp-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag-uninstalled.pc.in new file mode 100644 index 0000000..b953a4c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/tag +typelibdir=@abs_top_builddir@/gst-libs/gst/tag + +Name: GStreamer Tag Library, Uninstalled +Description: Tag base classes and helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag.pc.in new file mode 100644 index 0000000..a7a564c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-tag.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Tag Library +Description: Tag base classes and helper functions +Requires: gstreamer-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgsttag-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video-uninstalled.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video-uninstalled.pc.in new file mode 100644 index 0000000..450be2b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video-uninstalled.pc.in @@ -0,0 +1,16 @@ +# the standard variables don't make sense for an uninstalled copy +prefix= +exec_prefix= +libdir= +# includedir is builddir because it is used to find gstconfig.h in places +includedir=@abs_top_builddir@/gst-libs +girdir=@abs_top_builddir@/gst-libs/gst/video +typelibdir=@abs_top_builddir@/gst-libs/gst/video + +Name: GStreamer Video Library, Uninstalled +Description: Video base classes and helper functions, uninstalled +Version: @VERSION@ +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Libs: @abs_top_builddir@/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la +Cflags: -I@abs_top_srcdir@/gst-libs -I@abs_top_builddir@/gst-libs + diff --git a/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video.pc.in b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video.pc.in new file mode 100644 index 0000000..59a217d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/pkgconfig/gstreamer-video.pc.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gstreamer-@GST_MAJORMINOR@ +datarootdir=${prefix}/share +datadir=${datarootdir} +girdir=${datadir}/gir-1.0 +typelibdir=${libdir}/girepository-1.0 + +Name: GStreamer Video Library +Description: Video base classes and helper functions +Requires: gstreamer-@GST_MAJORMINOR@ gstreamer-base-@GST_MAJORMINOR@ +Version: @VERSION@ +Libs: -L${libdir} -lgstvideo-@GST_MAJORMINOR@ +Cflags: -I${includedir} + diff --git a/gst-plugins-base-subtitles0.10/po/.gitignore b/gst-plugins-base-subtitles0.10/po/.gitignore new file mode 100644 index 0000000..cada389 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/.gitignore @@ -0,0 +1,17 @@ +*.gmo +remove-potcdate.sed +remove-potcdate.sin +stamp-po +POTFILES +cat-id-tbl.c +gst-plugins-*.pot +Makefile.in.in +Makefile.in.in.orig +Makevars.template +Rules-quot +boldquot.sed +en@boldquot.header +en@quot.header +insert-header.sin +quot.sed +*.pot diff --git a/gst-plugins-base-subtitles0.10/po/LINGUAS b/gst-plugins-base-subtitles0.10/po/LINGUAS new file mode 100644 index 0000000..8e987cc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/LINGUAS @@ -0,0 +1 @@ +af az bg ca cs da de el en_GB es eu fi fr gl hu id it ja lt lv nb nl or pl pt_BR ro ru sk sl sq sr sv tr uk vi zh_CN diff --git a/gst-plugins-base-subtitles0.10/po/Makevars b/gst-plugins-base-subtitles0.10/po/Makevars new file mode 100644 index 0000000..10ed9f6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/Makevars @@ -0,0 +1,47 @@ +# Makefile variables for PO directory in any package using GNU gettext. + +# Usually the message domain is the same as the package name. +DOMAIN = $(GETTEXT_PACKAGE) + +# These two variables depend on the location of this directory. +subdir = po +top_builddir = .. + +# These options get passed to xgettext. +XGETTEXT_OPTIONS = --keyword=_ --keyword=N_ + +# This is the copyright holder that gets inserted into the header of the +# $(DOMAIN).pot file. Set this to the copyright holder of the surrounding +# package. (Note that the msgstr strings, extracted from the package's +# sources, belong to the copyright holder of the package.) Translators are +# expected to transfer the copyright for their translations to this person +# or entity, or to disclaim their copyright. The empty string stands for +# the public domain; in this case the translators are expected to disclaim +# their copyright. +COPYRIGHT_HOLDER = + +# This is the email address or URL to which the translators shall report +# bugs in the untranslated strings: +# - Strings which are not entire sentences, see the maintainer guidelines +# in the GNU gettext documentation, section 'Preparing Strings'. +# - Strings which use unclear terms or require additional context to be +# understood. +# - Strings which make invalid assumptions about notation of date, time or +# money. +# - Pluralisation problems. +# - Incorrect English spelling. +# - Incorrect formatting. +# It can be your email address, or a mailing list address where translators +# can write to without being subscribed, or the URL of a web page through +# which the translators can contact you. +MSGID_BUGS_ADDRESS = http://bugzilla.gnome.org/ + +# This is the list of locale categories, beyond LC_MESSAGES, for which the +# message catalogs shall be used. It is usually empty. +EXTRA_LOCALE_CATEGORIES = + +# Avoid line numbers in *.po, but keep them in *.pot. +MSGMERGE = msgmerge --no-location +MSGMERGE_UPDATE = msgmerge --no-location --update --backup=off +MSGFILTER = msgfilter --no-location + diff --git a/gst-plugins-base-subtitles0.10/po/POTFILES.in b/gst-plugins-base-subtitles0.10/po/POTFILES.in new file mode 100644 index 0000000..d8aa8cc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/POTFILES.in @@ -0,0 +1,23 @@ +ext/alsa/gstalsamixertrack.c +ext/alsa/gstalsasink.c +ext/alsa/gstalsasrc.c +ext/cdparanoia/gstcdparanoiasrc.c +ext/gnomevfs/gstgnomevfssrc.c +ext/gnomevfs/gstgnomevfssink.c +ext/ogg/gstoggdemux.c +gst/playback/gstdecodebin.c +gst/playback/gstdecodebin2.c +gst/playback/gstplaybasebin.c +gst/playback/gstplaybin.c +gst/playback/gstplaysink.c +gst/playback/gsturidecodebin.c +gst/tcp/gsttcp.c +gst/tcp/gsttcpclientsink.c +gst/tcp/gsttcpclientsrc.c +gst-libs/gst/audio/gstbaseaudiosrc.c +gst-libs/gst/tag/gsttagdemux.c +gst-libs/gst/tag/tags.c +gst-libs/gst/cdda/gstcddabasesrc.c +gst-libs/gst/pbutils/descriptions.c +gst-libs/gst/pbutils/missing-plugins.c +sys/v4l/v4l_calls.c diff --git a/gst-plugins-base-subtitles0.10/po/af.po b/gst-plugins-base-subtitles0.10/po/af.po new file mode 100644 index 0000000..8357ae0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/af.po @@ -0,0 +1,734 @@ +# Translation of gstreamer plugin messages to Afrikaans. +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is put in the public domain. +# Petri Jooste , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins 0.7.6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-03-18 14:16+0200\n" +"Last-Translator: Petri Jooste \n" +"Language-Team: Afrikaans \n" +"Language: af\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Treble" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetiseerder" + +msgid "Line-in" +msgstr "Lyn-in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofoon" + +#, fuzzy +msgid "PC Speaker" +msgstr "Luidspreker" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "Kon nie oudio-toestel \"%s\" oopmaak vir skryf nie." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "Kon nie toestel \"%s\" oopmaak vir lees en skryf nie." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +msgid "Could not open CD device for reading." +msgstr "Kon nie CD-toestel oopmaak om te lees nie." + +#, fuzzy +msgid "Could not seek CD." +msgstr "Kon nie vfs-lêer \"%s\" toemaak nie." + +#, fuzzy +msgid "Could not read CD." +msgstr "Kon nie skryf na toestel \"%s\" nie." + +#, fuzzy, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Kon nie vfs-lêer \"%s\" oopmaak vir skryf nie." + +#, fuzzy +msgid "No filename given" +msgstr "Geen lêernaam gespesifiseer." + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Kon nie vfs-lêer \"%s\" toemaak nie." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fout tydens toemaak van lêer \"%s\"." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "Kon nie skryf na lêer \"%s\" nie." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "Toestel \"%s\" is nie 'n vasleggingtoestel nie." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Fout tydens toemaak van lêer \"%s\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "Geen toestel gespesifiseer" + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Toestel \"%s\" bestaan nie." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "OSS-toestel \"%s\" is reeds in gebruik deur 'n ander program." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Kon nie toestel \"%s\" oopmaak vir lees en skryf nie." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Kon nie skryf na lêer \"%s\" nie." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Geen toestel gespesifiseer" + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Kon nie skryf na lêer \"%s\" nie." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Kon nie lêer \"%s\" oopmaak om te lees nie." + +#~ msgid "Device is not open." +#~ msgstr "Toestel is nie oop nie." + +#~ msgid "Device is open." +#~ msgstr "Toestel is oop." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "Kon nie vfs-lêer \"%s\" oopmaak vir lees nie." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "Geen lêernaam gespesifiseer." + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "Kon nie lêer \"%s\" oopmaak om in te skryf nie." + +#~ msgid "No filename specified." +#~ msgstr "Geen lêernaam gespesifiseer." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "Geen of ongeldige klanktoevoer, AVI-stroom sal korrup wees." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "Kon nie beheertoestel \"%s\" oopmaak vir skryf nie." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "Kon nie oudio-toestel \"%s\" konfigureer nie." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "Kon nie klanktoestel \"%s\" verstel na %d Hz nie." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "Kon nie oudio-toestel \"%s\" toemaak nie." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "Kon nie beheertoestel \"%s\" toemaak nie." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "Kon nie video-toestel \"%s\" oopmaak vir skryf nie." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "Kon nie video-toestel \"%s\" toemaak nie." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "Kon nie toegang kry tot toestel \"%s\" nie, kyk na toegangsregte." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "Kon nie toestel \"%s\" oopmaak vir skryf nie." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "Kon nie toestel \"%s\" oopmaak vir lees nie." + +#~ msgid "Volume" +#~ msgstr "Volume" + +#~ msgid "Speaker" +#~ msgstr "Luidspreker" + +#~ msgid "Mixer" +#~ msgstr "Menger" + +#~ msgid "PCM-2" +#~ msgstr "PCM-2" + +#~ msgid "Record" +#~ msgstr "Neem op" + +#~ msgid "In-gain" +#~ msgstr "In-versterking" + +#~ msgid "Out-gain" +#~ msgstr "Uit-versterking" + +#~ msgid "Line-1" +#~ msgstr "Lyn-1" + +#~ msgid "Line-2" +#~ msgstr "Lyn-2" + +#~ msgid "Line-3" +#~ msgstr "Lyn-3" + +#~ msgid "Digital-1" +#~ msgstr "Digitaal-1" + +#~ msgid "Digital-2" +#~ msgstr "Digitaal-2" + +#~ msgid "Digital-3" +#~ msgstr "Digitaal-3" + +#~ msgid "Phone-in" +#~ msgstr "Telefoon-in" + +#~ msgid "Phone-out" +#~ msgstr "Telefoon-uit" + +#~ msgid "Video" +#~ msgstr "Video" + +#~ msgid "Radio" +#~ msgstr "Radio" + +#~ msgid "Monitor" +#~ msgstr "Monitor" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "Kon nie buffers vanaf toestel \"%s\" verkry nie." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "Kon nie genoeg buffers vanaf toestel \"%s\" kry nie." diff --git a/gst-plugins-base-subtitles0.10/po/az.po b/gst-plugins-base-subtitles0.10/po/az.po new file mode 100644 index 0000000..20f23ae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/az.po @@ -0,0 +1,735 @@ +# Translation of 'gst-plugins' messages to Azerbaijani. +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is put in the public domain. +# Mətin Əmirov , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-0.8.0\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-03-19 18:29+0200\n" +"Last-Translator: Metin Amiroff \n" +"Language-Team: Azerbaijani \n" +"Language: az\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.0.2\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Ä°ncə" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sint" + +msgid "Line-in" +msgstr "Xətd-giriş" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +#, fuzzy +msgid "PC Speaker" +msgstr "Spiker" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "\"%s\" audio avadanlığı yazma üçün açıla bilmədi." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "\"%s\" avadanlığı oxuma və yazma üçün açıla bilmədi." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +msgid "Could not open CD device for reading." +msgstr "CD avadanlığı oxuma üçün açıla bilmədi." + +#, fuzzy +msgid "Could not seek CD." +msgstr "\"%s\" vfs faylı bağlana bilmədi." + +#, fuzzy +msgid "Could not read CD." +msgstr "\"%s\" avadanlığına yazıla bilmədi." + +#, fuzzy, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "\"%s\" vfs faylı yazma üçün açıla bilmədi." + +#, fuzzy +msgid "No filename given" +msgstr "Fayl adı verilməyib." + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "\"%s\" vfs faylı bağlana bilmədi." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "\"%s\" faylı bağlana bilmədi." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "\"%s\" faylına yazıla bilmədi." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "\"%s\" avadanlığı capture avadanlığı deyil." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "\"%s\" faylı bağlana bilmədi." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "Avadanlıq bildirilməyib." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "\"%s\" avadanlığı mövcud deyil." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "\"%s\" OSS avadanlığı başqa bir proqram tərəfindən istifadədədir." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "\"%s\" avadanlığı oxuma və yazma üçün açıla bilmədi." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "\"%s\" faylına yazıla bilmədi." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Avadanlıq bildirilməyib." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "\"%s\" faylına yazıla bilmədi." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "\"%s\" faylı oxuma üçün açıla bilmədi." + +#~ msgid "Device is not open." +#~ msgstr "Avadanlıq açıq deyil." + +#~ msgid "Device is open." +#~ msgstr "Avadanlıq açıqdır." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "\"%s\" vfs faylı oxuma üçün açıla bilmədi." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "Fayl adı verilməyib." + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "\"%s\" faylı yazma üçün açıla bilmədi." + +#~ msgid "No filename specified." +#~ msgstr "Fayl adı verilməyib." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "Səhv ya da olmayan audio girişi, AVI yayımı pozulacaqdır." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "\"%s\" idarə avadanlığı yazma üçün açıla bilmədi." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "\"%s\" audio avadanlığı quraşdırıla bilmədi." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "\"%s\" audio avadanlığı %d Hz-ə keçirilə bilmədi." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "\"%s\" audio avadanlığı bağlana bilmədi." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "\"%s\" idarə avadanlığı bağlana bilmədi." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "\"%s\" video avadanlığı yazma üçün açıla bilmədi." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "\"%s\" video avadanlığı bağlana bilmədi." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "\"%s\" avadanlığına yetişə bilmədi, səlahiyyətlərini yoxlayın." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "\"%s\" avadanlığı yazma üçün açıla bilmədi." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "\"%s\" avadanlığı oxuma üçün açıla bilmədi." + +#~ msgid "Volume" +#~ msgstr "Səs" + +#~ msgid "Speaker" +#~ msgstr "Spiker" + +#~ msgid "Mixer" +#~ msgstr "Mikser" + +#~ msgid "PCM-2" +#~ msgstr "PCM-2" + +#~ msgid "Record" +#~ msgstr "Qeyd" + +#~ msgid "In-gain" +#~ msgstr "Giriş-gain" + +#~ msgid "Out-gain" +#~ msgstr "Çıxış-gain" + +#~ msgid "Line-1" +#~ msgstr "Xətd-1" + +#~ msgid "Line-2" +#~ msgstr "Xətd-2" + +#~ msgid "Line-3" +#~ msgstr "Xətd-3" + +#~ msgid "Digital-1" +#~ msgstr "Dijital-1" + +#~ msgid "Digital-2" +#~ msgstr "Dijital-2" + +#~ msgid "Digital-3" +#~ msgstr "Dijital-3" + +#~ msgid "Phone-in" +#~ msgstr "Telefon-girişi" + +#~ msgid "Phone-out" +#~ msgstr "Telefon-çıxışı" + +#~ msgid "Video" +#~ msgstr "Video" + +#~ msgid "Radio" +#~ msgstr "Radio" + +#~ msgid "Monitor" +#~ msgstr "Monitor" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "\"%s\" avadanlığından bufferlər alına bilmədi." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "\"%s\" avadanlığından kifayət qədər bufferlər alına bilmədi." diff --git a/gst-plugins-base-subtitles0.10/po/bg.po b/gst-plugins-base-subtitles0.10/po/bg.po new file mode 100644 index 0000000..0d2b437 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/bg.po @@ -0,0 +1,610 @@ +# Bulgarian translation of gst-plugins-base. +# Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# Alexander Shopov , 2005, 2006, 2007, 2008, 2009, 2010, 2011. +# +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-26 22:31+0300\n" +"Last-Translator: Alexander Shopov \n" +"Language-Team: Bulgarian \n" +"Language: bg\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgid "Master" +msgstr "Главен" + +msgid "Bass" +msgstr "Баси" + +msgid "Treble" +msgstr "Високи" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Синтезатор" + +msgid "Line-in" +msgstr "Вход" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Микрофон" + +msgid "PC Speaker" +msgstr "Високоговорител на PC" + +msgid "Playback" +msgstr "Изпълнение" + +msgid "Capture" +msgstr "Запис" + +msgid "Could not open device for playback in mono mode." +msgstr "Устройството не може да се отвори за изпълнение в моно режим." + +msgid "Could not open device for playback in stereo mode." +msgstr "Устройството не може да се отвори за изпълнение в стерео режим." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Устройството не може да се отвори за изпълнение в %d-канален режим." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Звуковото устройство не може да се отвори за изпълнение, защото се ползва от " +"друго приложение." + +msgid "Could not open audio device for playback." +msgstr "Звуковото устройство не може да се отвори за изпълнение." + +msgid "Could not open device for recording in mono mode." +msgstr "Устройството не може да се отвори за запис в моно режим." + +msgid "Could not open device for recording in stereo mode." +msgstr "Устройството не може да се отвори за изпълнение в стерео режим." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Устройството не може да се отвори за изпълнение в %d-канален режим." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Звуковото устройство не може да се отвори за запис, защото се ползва от " +"друго приложение." + +msgid "Could not open audio device for recording." +msgstr "Звуковото устройство не може да се отвори за запис." + +msgid "Could not open CD device for reading." +msgstr "Устройството за CD-та не може да се отвори за четене." + +msgid "Could not seek CD." +msgstr "По CD-то не може да се търси." + +msgid "Could not read CD." +msgstr "CD-то не може да бъде прочетено." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "" +"Файлът „%s“ от виртуалната файлова система не може да се отвори за запис: %s." + +msgid "No filename given" +msgstr "Не е дадено име на файл" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Файлът „%s“ от виртуалната файлова система не може да се затвори." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Грешка при запис във файла „%s“." + +msgid "Internal data stream error." +msgstr "Вътрешна грешка на потока от данни." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"За да пуснете този поток, се нуждаете от приставка за %s. Такава не е " +"инсталирана." + +msgid "This appears to be a text file" +msgstr "Това изглежда е текстов файл" + +msgid "Could not determine type of stream" +msgstr "Видът на потока не може да бъде определен" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Грешен адрес за субтитри „%s“, субтитрите са изключени." + +msgid "No URI specified to play from." +msgstr "Не е указан адрес за пускане." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Грешен адрес „%s“." + +msgid "RTSP streams cannot be played yet." +msgstr "Потоци с RTSP все още не се поддържат." + +msgid "Could not create \"decodebin\" element." +msgstr "Не може да се създаде елемент „decodebin“." + +msgid "Source element is invalid." +msgstr "Елементът-източник е грешен." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Бе засечен единствено поток със субтитри. Или сте заредили файл със " +"субтитри, или някакъв друг вид текстов файл, или просто видът на " +"мултимедийния файл не е разпознат." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Липсва декодер за обработката на този файл. Ще трябва да инсталирате " +"необходимите приставки." + +msgid "This is not a media file" +msgstr "Това не е медиен файл" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Открит е поток със субтитри, липсва видео поток." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" +"Едновременно липсват елементите-приемници „autovideosink“ и „xvimagesink“." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Елементът „%s“ липсва — проверете инсталацията на GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" +"Едновременно липсват елементите-приемници „autoaudiosink“ и „alsasink“." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Едновременно липсват елементите-приемници „autovideosink“ и „%s“." + +msgid "The autovideosink element is missing." +msgstr "Липсва елементът-приемник „autovideosink“." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Настроеният елемент-приемник за видео %s не работи." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Едновременно не работят елементите-приемници „autovideosink“ и „%s“." + +msgid "The autovideosink element is not working." +msgstr "Елементът-приемник за автоматично видео „autovideosink“ не работи." + +msgid "Custom text sink element is not usable." +msgstr "Потребителският елемент-приемник за текст е неизползваем." + +msgid "No volume control found" +msgstr "Липсва управление на силата на звука" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Едновременно липсват елементите-приемници „autoaudiosink“ и „%s“." + +msgid "The autoaudiosink element is missing." +msgstr "Липсва елементът „autoaudiosink“." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Настроеният елемент-приемник за аудио %s не работи." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Едновременно не работят елементите „autoaudiosink“ и „%s“." + +msgid "The autoaudiosink element is not working." +msgstr "Елементът „autoaudiosink“ не работи." + +msgid "Can't play a text file without video or visualizations." +msgstr "Текстов файл не може да се изпълни без видео или визуализация." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Липсва декодер за вида „%s“." + +msgid "This stream type cannot be played yet." +msgstr "Потоци от този тип все още не могат да бъдат изпълнявани." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Обработката на адреси „%s“ не е реализирана." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Грешка при запис във файла „%s:%d“." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Грешка при запис на заглавните данни gdp във файла „%s:%d“." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Грешка при изпращането на натоварените по gtp данни към „%s:%d“." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Връзката към %s:%d е отказана." + +msgid "Can't record audio fast enough" +msgstr "Звукът не може да бъде записан достатъчно бързо" + +msgid "Failed to read tag: not enough data" +msgstr "Неуспешно прочитано на етикет: липсват достатъчно данни" + +msgid "track ID" +msgstr "идентификатор на песен" + +msgid "MusicBrainz track ID" +msgstr "идентификатор на песен според MusicBrainz" + +msgid "artist ID" +msgstr "идентификатор на изпълнител" + +msgid "MusicBrainz artist ID" +msgstr "идентификатор на изпълнител според MusicBrainz" + +msgid "album ID" +msgstr "идентификатор на албум" + +msgid "MusicBrainz album ID" +msgstr "идентификатор на албум според MusicBrainz" + +msgid "album artist ID" +msgstr "идентификатор на изпълнител в албума" + +msgid "MusicBrainz album artist ID" +msgstr "идентификатор на изпълнител в албума според MusicBrainz" + +msgid "track TRM ID" +msgstr "индустриален идентификатор на песен (TRM)" + +msgid "MusicBrainz TRM ID" +msgstr "индустриален идентификатор на песен според MusicBrainz (TRM)" + +msgid "capturing shutter speed" +msgstr "скорост на затвора" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Скорост на затвора при заснемане в секунди" + +msgid "capturing focal ratio" +msgstr "относителна бленда" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Относителна бленда при заснемане" + +msgid "capturing focal length" +msgstr "фокусно разстояние" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Фокусно разстояние на обектива при заснемане в милиметри" + +msgid "capturing digital zoom ratio" +msgstr "цифрово увеличение" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Цифрово увеличение при заснемане" + +msgid "capturing iso speed" +msgstr "светлочувствителност по ISO" + +msgid "The ISO speed used when capturing an image" +msgstr "Светлочувствителност по ISO при заснемане" + +msgid "capturing exposure program" +msgstr "програма на експозиция" + +msgid "The exposure program used when capturing an image" +msgstr "Програма на експозиция при заснемане" + +msgid "capturing exposure mode" +msgstr "режим на експозиция" + +msgid "The exposure mode used when capturing an image" +msgstr "Режим на експозиция при заснемане" + +msgid "capturing exposure compensation" +msgstr "компенсация на експозицията" + +msgid "The exposure compensation used when capturing an image" +msgstr "Компенсацията на експозицията при заснемане" + +msgid "capturing scene capture type" +msgstr "вид сцена" + +msgid "The scene capture mode used when capturing an image" +msgstr "Вид сцена при заснемане" + +msgid "capturing gain adjustment" +msgstr "корекция с усилване" + +msgid "The overall gain adjustment applied on an image" +msgstr "Общата корекция с усилване при заснемане " + +msgid "capturing white balance" +msgstr "баланс на бялото" + +msgid "The white balance mode set when capturing an image" +msgstr "Режим на баланс на бялото при заснемане" + +msgid "capturing contrast" +msgstr "контраст" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Посоката на обработката за контраст при заснемане" + +msgid "capturing saturation" +msgstr "наситеност" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Посоката на обработката за наситеност при заснемане" + +msgid "capturing sharpness" +msgstr "острота" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Посоката на обработката за острота при заснемане" + +msgid "capturing flash fired" +msgstr "светкавица" + +msgid "If the flash fired while capturing an image" +msgstr "Дали е ползвана светкавица при заснемане" + +msgid "capturing flash mode" +msgstr "режим на светкавица" + +msgid "The selected flash mode while capturing an image" +msgstr "Режимът на светкавица при заснемане" + +msgid "capturing metering mode" +msgstr "режим на заснемане" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Режим на заснемане при определянето на експозиция" + +msgid "capturing source" +msgstr "източник" + +msgid "The source or type of device used for the capture" +msgstr "Видът на устройството-източник при заснемане" + +msgid "image horizontal ppi" +msgstr "точки на инч по хоризонтал" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Целевата разделителна способност на медията по хоризонтал" + +msgid "image vertical ppi" +msgstr "точки на инч по вертикал" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Целевата разделителна способност на медията по вертикал" + +msgid "This CD has no audio tracks" +msgstr "В това CD липсва аудио" + +msgid "ID3 tag" +msgstr "Етикет ID3" + +msgid "APE tag" +msgstr "Етикет APE" + +msgid "ICY internet radio" +msgstr "Радио в Интернет по ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Аудио на Епъл без загуба на качество (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Свободен кодер за аудио без загуба на качество (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Истинско аудио без загуба на качество (TTA)" + +msgid "Windows Media Speech" +msgstr "Говор, формат Windows Media" + +msgid "CYUV Lossless" +msgstr "CYUV без загуба на качество" + +msgid "FFMpeg v1" +msgstr "FFMpeg, версия 1" + +msgid "Lossless MSZH" +msgstr "MSZH без загуба на качество" + +msgid "Uncompressed Gray Image" +msgstr "Некомпресирано изображение с нива на сивото" + +msgid "Run-length encoding" +msgstr "Последователно кодиране RLE" + +msgid "Sami subtitle format" +msgstr "Субтитри, формат Sami" + +msgid "TMPlayer subtitle format" +msgstr "Субтитри, формат TMPlayer" + +msgid "Kate subtitle format" +msgstr "Субтитри, формат Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Некомпресирано видео по равнини YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Некомпресирано видео по равнини YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Некомпресирано, пакетирано видео YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Некомпресирано, пакетирано видео YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Некомпресирано, пакетирано видео YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Некомпресирано, пакетирано видео YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Некомпресирано, пакетирано видео YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Некомпресирано видео по равнини YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Некомпресирано видео по равнини YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Некомпресирано видео с черна и бяла равнини за Y" + +msgid "Uncompressed YUV" +msgstr "Некомпресирано видео YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Некомпресирано, индексирано, %d-битово %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 версия %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Аудио, формат необработен %d-битов PCM" + +msgid "Raw PCM audio" +msgstr "Аудио, формат необработен PCM" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Аудио, необработено, %d-битово, с плаваща запетая" + +msgid "Raw floating-point audio" +msgstr "Аудио, необработено с плаваща запетая" + +msgid "Audio CD source" +msgstr "Елемент-източник — CD" + +msgid "DVD source" +msgstr "Елемент-източник — DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Елемент-източник — RTSP (поточен протокол в реално време)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Елемент-източник — MMS (сървър за медия на Майкрософт)" + +#, c-format +msgid "%s protocol source" +msgstr "Елемент-източник, протокол %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s елемент, разтоварващ видеото от RTP" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s елемент, разтоварващ аудиото от RTP" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s елемент, разтоварващ данни от RTP" + +#, c-format +msgid "%s demuxer" +msgstr "Разделител (демултиплексор) %s" + +#, c-format +msgid "%s decoder" +msgstr "Декодер %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s елемент, товарещ видеото по RTP" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s елемент, товарещ аудиото по RTP" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s елемент, товарещ данни по RTP" + +#, c-format +msgid "%s muxer" +msgstr "Уплътнител (мултиплексор) %s" + +#, c-format +msgid "%s encoder" +msgstr "Кодер %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Елемент на GStreamer %s" + +msgid "Unknown source element" +msgstr "Непознат елемент-източник" + +msgid "Unknown sink element" +msgstr "Непознат елемент-приемник" + +msgid "Unknown element" +msgstr "Непознат елемент" + +msgid "Unknown decoder element" +msgstr "Непознат елемент-декодер" + +msgid "Unknown encoder element" +msgstr "Непознат елемент-кодер" + +msgid "Plugin or element of unknown type" +msgstr "Приставка или елемент от непознат вид" + +msgid "No device specified." +msgstr "Не е указано устройство." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Устройството „%s“ не съществува." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Устройството „%s“ вече се използва." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Устройството „%s“ не може да се отвори за четене и запис." diff --git a/gst-plugins-base-subtitles0.10/po/ca.po b/gst-plugins-base-subtitles0.10/po/ca.po new file mode 100644 index 0000000..7fcab23 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/ca.po @@ -0,0 +1,613 @@ +# Catalan translation of gst-plugins-base. +# Copyright © 2005, 2010 Free Software Foundation, Inc. +# This file is put in the public domain. +# Jordi Mallach , 2005, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-11-04 23:13+0100\n" +"Last-Translator: Jordi Mallach \n" +"Language-Team: Catalan \n" +"Language: ca\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Mestre" + +msgid "Bass" +msgstr "Baixos" + +msgid "Treble" +msgstr "Treble" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetitzador" + +msgid "Line-in" +msgstr "Línia d'entrada" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Micròfon" + +msgid "PC Speaker" +msgstr "Altaveu PC" + +msgid "Playback" +msgstr "Reproducció" + +msgid "Capture" +msgstr "Captura" + +msgid "Could not open device for playback in mono mode." +msgstr "No s'ha pogut obrir el dispositiu per a reproduir en mode mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "No s'ha pogut obrir el dispositiu per a reproduir en mode estèreo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "No s'ha pogut obrir el dispositiu per a reproduir en mode %d-canals." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"No s'ha pogut obrir el dispositiu d'àudio per a reproduir. El dispositiu " +"està en ús per una altra aplicació." + +msgid "Could not open audio device for playback." +msgstr "No s'ha pogut obrir el dispositiu d'àudio per a reproduir." + +msgid "Could not open device for recording in mono mode." +msgstr "No s'ha pogut obrir el dispositiu per a enregistrar en mode mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "No s'ha pogut obrir el dispositiu per a enregistrar en mode estèreo." + +# FIXME Trailing dot. jm +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "No s'ha pogut obrir el dispositiu per a enregistrar en mode %d-canals" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"No s'ha pogut obrir el dispositiu d'àudio per a enregistrar. El dispositiu " +"està en ús per una altra aplicació." + +msgid "Could not open audio device for recording." +msgstr "No s'ha pogut obrir el dispositiu d'àudio per a enregistrar." + +msgid "Could not open CD device for reading." +msgstr "No s'ha pogut obrir el dispositiu del CD per a lectura." + +msgid "Could not seek CD." +msgstr "No s'ha pogut cercar el CD." + +msgid "Could not read CD." +msgstr "No s'ha pogut llegir el CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "No s'ha pogut obrir el fitxer vfs «%s» per a l'escriptura: %s." + +msgid "No filename given" +msgstr "No s'ha donat cap nom de fitxer" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "No s'ha pogut tancar el fitxer vfs «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "S'ha produït un error en escriure al fitxer «%s»." + +msgid "Internal data stream error." +msgstr "S'ha produït un error intern de flux de dades." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Es requereix un connector %s per a reproduir aquest flux, però no és " +"instaŀlat." + +msgid "This appears to be a text file" +msgstr "Açò sembla ser un fitxer de text" + +msgid "Could not determine type of stream" +msgstr "No s'ha pogut determinar el tipus de flux" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "L'URI de subtítols «%s» és invàlida, s'inhabiliten els subtítols." + +msgid "No URI specified to play from." +msgstr "No s'ha especificat cap URL des d'on reproduir." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "L'URI «%s» és invàlid." + +msgid "RTSP streams cannot be played yet." +msgstr "Encara no es poden reproduir els fluxes RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "No s'ha pogut crear l'element «decodebin»." + +msgid "Source element is invalid." +msgstr "L'element font és invàlid." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Només s'ha detectat un flux de subtítols. O bé esteu carregant un fitxer de " +"subtítols o qualsevol altre tipus de fitxer de text, o no s'ha reconegut el " +"fitxer de medi." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"No teniu un decodificador instaŀlat per a gestionar aquest fitxer. És " +"possible que necessiteu instaŀlar els connectors necessaris." + +msgid "This is not a media file" +msgstr "Aquest no és un fitxer de medi" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "S'ha detectat un flux de subtítols, però no un flux de vídeo." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Manquen l'element autovideosink i el xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Manca l'element «%s» - comproveu la vostra instaŀlació del GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Manquen l'element autoaudiosink i l'alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Manquen els elements autovideosink i %s." + +msgid "The autovideosink element is missing." +msgstr "Manca l'element autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "El videosink configurat %s no funciona." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Tant l'element autovideosink com el %s no funcionen." + +msgid "The autovideosink element is not working." +msgstr "L'element autovideosink no funciona." + +msgid "Custom text sink element is not usable." +msgstr "L'element sortida personalitzat de text no es pot emprar." + +msgid "No volume control found" +msgstr "No s'ha trobat un control de volum" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Manquen els elements autoaudiosink i %s." + +msgid "The autoaudiosink element is missing." +msgstr "Manca l'element autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "L'audiosink configurat %s no funciona." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "No funcionen tant l'element autoaudiosink com el %s." + +msgid "The autoaudiosink element is not working." +msgstr "L'element autoaudiosink no funciona." + +msgid "Can't play a text file without video or visualizations." +msgstr "No es pot reproduir un fitxer de text sense vídeo o visualitzacions." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "No hi ha un decodificador disponible per al tipus «%s»." + +msgid "This stream type cannot be played yet." +msgstr "Encara no es pot reproduir aquest tipus de flux." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "No hi ha cap gestor d'URI implementat per a «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "S'ha produït un error en enviar dades a «%s:%d»." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "S'ha produït un error en enviar dades de la capçalera gdp a «%s:%d»." + +# Payload -> càrrega en molts àmbits. jm +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "S'ha produït un error en enviar la càrrega de dades de gdp a «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "S'ha refusat la connexió amb %s:%d." + +msgid "Can't record audio fast enough" +msgstr "No es pot enregistrar l'àudio el suficientment ràpid" + +msgid "Failed to read tag: not enough data" +msgstr "No s'ha pogut llegir l'etiqueta: no hi ha dades suficients" + +msgid "track ID" +msgstr "ID de la pista" + +msgid "MusicBrainz track ID" +msgstr "ID de la pista al MusicBrainz" + +msgid "artist ID" +msgstr "ID de l'artista" + +msgid "MusicBrainz artist ID" +msgstr "ID de l'artista al MusicBrainz" + +msgid "album ID" +msgstr "ID de l'àlbum" + +msgid "MusicBrainz album ID" +msgstr "ID de l'àlbum al MusicBrainz" + +msgid "album artist ID" +msgstr "ID de l'artista de l'àlbum" + +msgid "MusicBrainz album artist ID" +msgstr "ID de l'artista de l'àlbum al MusicBrainz" + +msgid "track TRM ID" +msgstr "ID TRM de la pista" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM al MusicBrainz" + +msgid "capturing shutter speed" +msgstr "velocitat de l'obturador de la captura" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "ppi horitzontal de la imatge" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Densitat horitzontal de píxels del medi (imatge/vídeo), en ppi" + +msgid "image vertical ppi" +msgstr "ppi vertical de la imatge" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Densitat vertical de píxels del medi (imatge/vídeo), en ppi" + +msgid "This CD has no audio tracks" +msgstr "Aquest CD no té pistes d'àudio" + +msgid "ID3 tag" +msgstr "Etiqueta ID3" + +msgid "APE tag" +msgstr "Etiqueta APE" + +msgid "ICY internet radio" +msgstr "Emisora de ràdio per Internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV sense pèrdua" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH sense pèrdua" + +msgid "Uncompressed Gray Image" +msgstr "Imatge en escala de grisos no comprimida" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "Format de subtítols Sami" + +msgid "TMPlayer subtitle format" +msgstr "Format de subtítols TMPlayer" + +msgid "Kate subtitle format" +msgstr "Format de subtítols Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "YUV sense comprimir" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versió %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Àudio en cru de %d-bit" + +msgid "Raw PCM audio" +msgstr "Àudio PCM en cru" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Àudio en cru de %d-bit en coma flotant" + +msgid "Raw floating-point audio" +msgstr "Àudio en cru en coma flotant" + +msgid "Audio CD source" +msgstr "Font de CD d'àudio" + +msgid "DVD source" +msgstr "Font de DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Font del Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Font del protocol Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Font del protocol %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Descarregador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Descarregador d'àudio RTP %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Descarregador RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Demultiplexor %s" + +#, c-format +msgid "%s decoder" +msgstr "Decodificador %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Carregador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Carregador d'àudio RTP %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "Carregador RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Multiplexor %s" + +#, c-format +msgid "%s encoder" +msgstr "Codificador %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Element del GStreamer %s" + +msgid "Unknown source element" +msgstr "L'element de font és desconegut" + +msgid "Unknown sink element" +msgstr "L'element de sortida és desconegut" + +msgid "Unknown element" +msgstr "L'element és desconegut" + +msgid "Unknown decoder element" +msgstr "L'element decodificador és desconegut" + +msgid "Unknown encoder element" +msgstr "L'element codificador és desconegut" + +msgid "Plugin or element of unknown type" +msgstr "El connector o element és de tipus desconegut" + +msgid "No device specified." +msgstr "No s'ha especificat un dispositiu." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "El dispositiu «%s» no existeix." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "El dispositiu «%s» ja és en ús." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "No s'ha pogut obrir el dispositiu «%s» per a llegir i escriure." + +#~ msgid "discid" +#~ msgstr "id del disc" + +#~ msgid "CDDA discid for metadata retrieval" +#~ msgstr "id del disc de CDDA per a l'obtenció de les metadades" diff --git a/gst-plugins-base-subtitles0.10/po/cs.po b/gst-plugins-base-subtitles0.10/po/cs.po new file mode 100644 index 0000000..5e44eac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/cs.po @@ -0,0 +1,613 @@ +# Czech translations of gst-plugins-base. +# Copyright (C) 2007, 2008, 2009, 2010 the author(s) of gst-plugins-base. +# Copyright (C) 2004 Miloslav Trmac . +# This file is put in the public domain. +# Miloslav Trmac , 2004. +# Petr Kovar , 2007, 2008, 2009, 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base-0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-10-31 10:51+0100\n" +"Last-Translator: Petr Kovar \n" +"Language-Team: Czech \n" +"Language: cs\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n" +"X-Generator: Lokalize 1.1\n" + +msgid "Master" +msgstr "Master" + +msgid "Bass" +msgstr "Basy" + +msgid "Treble" +msgstr "Výšky" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Syntezátor" + +msgid "Line-in" +msgstr "Linkový vstup" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC Speaker" + +msgid "Playback" +msgstr "Přehrávání" + +msgid "Capture" +msgstr "Záznam" + +msgid "Could not open device for playback in mono mode." +msgstr "Nezdařilo se otevření zařízení k přehrávání v režimu mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nezdařilo se otevření zařízení k přehrávání v režimu stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Nezdařilo se otevření zařízení k přehrávání v %dkanálovém režimu." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nezdařilo se otevření zvukového zařízení k přehrávání. Zařízení je používáno " +"jinou aplikací." + +msgid "Could not open audio device for playback." +msgstr "Nezdařilo se otevření zvukového zařízení k přehrávání." + +msgid "Could not open device for recording in mono mode." +msgstr "Nezdařilo se otevření zařízení k záznamu v režimu mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Nezdařilo se otevření zařízení k záznamu v režimu stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Nezdařilo se otevření zařízení k záznamu v %dkanálovém režimu" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nezdařilo se otevření zvukového zařízení k záznamu. Zařízení je používáno " +"jinou aplikací." + +msgid "Could not open audio device for recording." +msgstr "Nezdařilo se otevření zvukového zařízení k záznamu." + +msgid "Could not open CD device for reading." +msgstr "Nezdařilo se otevření zařízení CD ke čtení." + +msgid "Could not seek CD." +msgstr "Nezdařilo se nalézt CD." + +msgid "Could not read CD." +msgstr "Nezdařilo se přečíst CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nezdařilo se otevření souboru vfs \"%s\" k zápisu: %s." + +msgid "No filename given" +msgstr "Nezadán název souboru" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nezdařilo se zavření souboru vfs \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Chyba při zápisu do souboru \"%s\"." + +msgid "Internal data stream error." +msgstr "Vnitřní chyba datového proudu." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Zásuvný modul %s je vyžadován k přehrání tohoto proudu, ale není " +"nainstalován." + +msgid "This appears to be a text file" +msgstr "Zdá se, že se jedná o textový soubor" + +msgid "Could not determine type of stream" +msgstr "Nezdařilo se určit typ proudu" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Neplatné URI titulků \"%s\", titulky vypnuty." + +msgid "No URI specified to play from." +msgstr "Nezadáno žádné URI, ze kterého se má přehrávat." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Neplatné URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "Proudy RTSP zatím nemohou být přehrávány." + +msgid "Could not create \"decodebin\" element." +msgstr "Nezdařilo se vytvoření prvku \"decodebin\"." + +msgid "Source element is invalid." +msgstr "Zdrojový prvek je neplatný." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Byl rozpoznán pouze proud titulků. Buď je nahráván pouze soubor titulků nebo " +"nějaký jiný typ textového soubor, popřípadě nebyl rozpoznán multimediální " +"soubor." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"K obsluze tohoto souboru není nainstalován dekodér. Patrně bude nutné " +"nainstalovat nezbytné zásuvné moduly." + +msgid "This is not a media file" +msgstr "Toto není multimediální soubor" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Byl rozpoznán proud titulků, ale nikoliv obrazový proud." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Schází jak prvek autovideosink, tak xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Schází prvek \"%s\" - zkontrolujte prosím instalaci systému GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Schází jak prvek autoaudiosink, tak alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Schází jak prvek autovideosink, tak %s." + +msgid "The autovideosink element is missing." +msgstr "Schází prvek autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Nefunguje prvek videosink %s." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Nefunguje ani prvek autovideosink, ani %s." + +msgid "The autovideosink element is not working." +msgstr "Nefunguje prvek autovideosink." + +msgid "Custom text sink element is not usable." +msgstr "Vlastní prvek kanálu textu není použitelný." + +msgid "No volume control found" +msgstr "Nenalezeno žádné ovládání hlasitosti" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Schází jak prvek autoaudiosink, tak %s." + +msgid "The autoaudiosink element is missing." +msgstr "Schází prvek autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Nefunguje prvek audiosink %s." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Nefunguje ani prvek autoaudiosink, ani %s." + +msgid "The autoaudiosink element is not working." +msgstr "Nefunguje prvek autoaudiosink." + +msgid "Can't play a text file without video or visualizations." +msgstr "Textový soubor nelze přehrát bez videa nebo vizualizací." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "K typu \"%s\" není dostupný dekodér." + +msgid "This stream type cannot be played yet." +msgstr "Tento typ proudu zatím nemůže být přehrán." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "U \"%s\" není prováděna obsluha URI." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Chyba při odesílání dat na \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Chyba při odesílání dat záhlaví gdp na \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Chyba při odesílání zátěžových dat gdp na \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Spojení s %s:%d bylo odmítnuto." + +msgid "Can't record audio fast enough" +msgstr "Zvuk nelze zaznamenat s dostatečnou rychlostí" + +msgid "Failed to read tag: not enough data" +msgstr "Nezdařilo se přečtení značky: nedostatek dat" + +msgid "track ID" +msgstr "ID stopy" + +msgid "MusicBrainz track ID" +msgstr "ID stopy MusicBrainz" + +msgid "artist ID" +msgstr "ID umělce" + +msgid "MusicBrainz artist ID" +msgstr "ID umělce MusicBrainz" + +msgid "album ID" +msgstr "ID alba" + +msgid "MusicBrainz album ID" +msgstr "ID alba MusicBrainz" + +msgid "album artist ID" +msgstr "ID umělce alba" + +msgid "MusicBrainz album artist ID" +msgstr "ID umělce alba MusicBrainz" + +msgid "track TRM ID" +msgstr "ID stopy TRM" + +msgid "MusicBrainz TRM ID" +msgstr "ID stopy TRM MusicBrainz" + +msgid "capturing shutter speed" +msgstr "rychlost závěrky záznamu" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Rychlost závěrky při záznamu obrazu, v sekundách" + +msgid "capturing focal ratio" +msgstr "ohnisková vzdálenost záznamu" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Clonové číslo při záznamu obrazu" + +msgid "capturing focal length" +msgstr "ohnisková vzdálenost záznamu" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Ohnisková vzdálenost čoček při záznamu obrazu, v mm" + +msgid "capturing digital zoom ratio" +msgstr "stupeň digitálního přiblížení záznamu" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Stupeň digitálního přiblížení při záznamu obrazu" + +msgid "capturing iso speed" +msgstr "rychlost ISO záznamu" + +msgid "The ISO speed used when capturing an image" +msgstr "Rychlost ISO při záznamu obrazu" + +msgid "capturing exposure program" +msgstr "program expozice záznamu" + +msgid "The exposure program used when capturing an image" +msgstr "Program expozice při záznamu obrazu" + +msgid "capturing exposure mode" +msgstr "režim expozice záznamu" + +msgid "The exposure mode used when capturing an image" +msgstr "Režim expozice při záznamu obrazu" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "režim expozice záznamu" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "Režim expozice při záznamu obrazu" + +msgid "capturing scene capture type" +msgstr "typ zachycení scény záznamu" + +msgid "The scene capture mode used when capturing an image" +msgstr "Typ zachycení scény při záznamu obrazu" + +msgid "capturing gain adjustment" +msgstr "úprava zesílení záznamu" + +msgid "The overall gain adjustment applied on an image" +msgstr "Úprava zesílení při záznamu obrazu" + +msgid "capturing white balance" +msgstr "vyvážení bílé záznamu" + +msgid "The white balance mode set when capturing an image" +msgstr "Režim vyvážení bílé nastavený při záznamu obrazu" + +msgid "capturing contrast" +msgstr "kontrast záznamu" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Použité zpracování kontrastu při záznamu obrazu" + +msgid "capturing saturation" +msgstr "sytost záznamu" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Použité zpracování sytosti při záznamu obrazu" + +msgid "capturing sharpness" +msgstr "ostrost záznamu" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Použité zpracování ostrosti při záznamu obrazu" + +msgid "capturing flash fired" +msgstr "použití blesku při záznamu" + +msgid "If the flash fired while capturing an image" +msgstr "Zda byl při záznamu obrazu použit blesk" + +msgid "capturing flash mode" +msgstr "režim blesku při záznamu" + +msgid "The selected flash mode while capturing an image" +msgstr "Režim blesku vybraný při záznamu obrazu" + +msgid "capturing metering mode" +msgstr "režim měření při záznamu" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Režim měření expozice při záznamu obrazu" + +msgid "capturing source" +msgstr "zdroj záznamu" + +msgid "The source or type of device used for the capture" +msgstr "Zdroj nebo typ zařízení použitého při záznamu" + +msgid "image horizontal ppi" +msgstr "pixelů na palec vodorovně v obrazu" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Zamýšlená hustota pixelů multimédia (image/video) vodorovně v pixelech na " +"palec" + +msgid "image vertical ppi" +msgstr "pixelů na palec svisle v obrazu" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Zamýšlená hustota pixelů multimédia (image/video) svisle v pixelech na palec" + +msgid "This CD has no audio tracks" +msgstr "Toto CD nemá žádné zvukové stopy" + +msgid "ID3 tag" +msgstr "Značka ID3" + +msgid "APE tag" +msgstr "Značka APE" + +msgid "ICY internet radio" +msgstr "Internetové rádio ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "Bezeztrátový CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Bezeztrátové MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Uncompressed Gray Image" + +msgid "Run-length encoding" +msgstr "RLE (Run-Length Encoding)" + +msgid "Sami subtitle format" +msgstr "Formát titulků Sami" + +msgid "TMPlayer subtitle format" +msgstr "Formát titulků TMPlayer" + +msgid "Kate subtitle format" +msgstr "Formát titulků Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nekomprimovaný planární YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nekomprimovaný planární YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nekomprimovaný zabalený YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nekomprimovaný zabalený YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nekomprimovaný zabalený YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nekomprimovaný zabalený YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nekomprimovaný zabalený YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nekomprimovaný planární YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nekomprimovaný planární YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nekomprimovaná černá a bílá rovina Y" + +msgid "Uncompressed YUV" +msgstr "Nekomprimovaný YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nekomprimovaný paletizovaný %dbitový %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4, verze %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Surový %dbitový zvuk PCM" + +msgid "Raw PCM audio" +msgstr "Surový zvuk PCM" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Surový %dbitový zvuk s pohyblivou desetinnou čárkou" + +msgid "Raw floating-point audio" +msgstr "Surový zvuk s pohyblivou desetinnou čárkou" + +msgid "Audio CD source" +msgstr "Zdroj zvukového CD" + +msgid "DVD source" +msgstr "Zdroj DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Zdroj Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Zdroj protokolu Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Zdroj protokolu %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Depayloader RTP %s, video" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Depayloader RTP %s, audio" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Depayloader RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Demultiplexer %s" + +#, c-format +msgid "%s decoder" +msgstr "Dekodér %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Payloader RTP %s, video" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Payloader RTP %s, audio" + +#, c-format +msgid "%s RTP payloader" +msgstr "Payloader RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Multiplexer %s" + +#, c-format +msgid "%s encoder" +msgstr "Kodér %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Prvek systému GStreamer %s" + +msgid "Unknown source element" +msgstr "Neznámý zdrojový prvek" + +msgid "Unknown sink element" +msgstr "Neznámý kanálový prvek" + +msgid "Unknown element" +msgstr "Neznámý prvek" + +msgid "Unknown decoder element" +msgstr "Neznámý dekodérový prvek" + +msgid "Unknown encoder element" +msgstr "Neznámý kodérový prvek" + +msgid "Plugin or element of unknown type" +msgstr "Zásuvný modul nebo prvek neznámého typu" + +msgid "No device specified." +msgstr "Nezadáno zařízení." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Zařízení \"%s\" neexistuje." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Zařízení \"%s\" je již používáno." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Zařízení \"%s\" se nezdařilo otevřít ke čtení a k zápisu." diff --git a/gst-plugins-base-subtitles0.10/po/da.po b/gst-plugins-base-subtitles0.10/po/da.po new file mode 100644 index 0000000..64fb753 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/da.po @@ -0,0 +1,649 @@ +# Danish translation of gst-plugins-base. +# Copyright (C) 2011 gst, Mogens Jaeger, Joe Hansen. +# This file is distributed under the same license as the gst-plugins-base package. +# +# Mogens Jaeger , 2007. +# Joe Hansen , 2009, 2010, 2011. +# +# capture -> optage +# gain -> forstærkning +# shutter -> lukketid +# +# Hej Torben, de fleste af dem her er vist afklaringen af hvorvidt det er et +# udsagnsord eller navneord. Har du været i koden og kigge? Ville godt nok +# være ked af at rette alle dem her, for sÃ¥ bare at »opdage« at de var gode nok, +# Nu har jeg haft src/gst-plugins-base/tags.c Ã¥ben i en nylig version +# (gst-blugins-base version 0.10.31), og jeg tror ikke strengene bruges, +# mens der sker en aktiv handling. +# I filen ser det sÃ¥ledes ud: +# /* photography tags */ +# gst_tag_register (GST_TAG_CAPTURING_SHUTTER_SPEED, +# GST_TAG_FLAG_META, +# GST_TYPE_FRACTION, +# _("capturing shutter speed"), +# _("Shutter speed used when capturing an image, +# in seconds"), NULL); +# Dette kan du se som en indgang i en tabel over strenge. Den første korte +# streng er navnet pÃ¥ mærket, den anden er en beskrivelse af samme mærke. +# Strengene er altsÃ¥ betegnelser/navneord. +# +# brugt kunne erstattes med der blev brugt (men skal sÃ¥ rettes igennem for alle). +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-30 17:11+0100\n" +"PO-Revision-Date: 2011-04-28 16:38+0100\n" +"Last-Translator: Joe Hansen \n" +"Language-Team: Danish \n" +"Language: da\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Master" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Diskant" + +msgid "PCM" +msgstr "Pcm" + +msgid "Synth" +msgstr "Synthesizer" + +msgid "Line-in" +msgstr "Linie-ind" + +msgid "CD" +msgstr "Cd" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "Pc-højttaler" + +msgid "Playback" +msgstr "Afspilning" + +msgid "Capture" +msgstr "Optage" + +msgid "Could not open device for playback in mono mode." +msgstr "Kunne ikke afspille fra enheden i mono-tilstand." + +msgid "Could not open device for playback in stereo mode." +msgstr "Kunne ikke afspille fra enheden i stereo-tilstand." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Kunne ikke afspille fra enheden i %d-kanals-tilstand." + +# mÃ¥ske bruges af et andet program. +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Kunne ikke Ã¥bne lydenhed til afspilning. Enhed anvendes af et andet program." + +msgid "Could not open audio device for playback." +msgstr "Kunne ikke Ã¥bne lydenhed til afspilning." + +msgid "Could not open device for recording in mono mode." +msgstr "Kunne ikke optage fra enheden i mono-tilstand." + +msgid "Could not open device for recording in stereo mode." +msgstr "Kunne ikke optage fra enheden i stereo-tilstand." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Kunne ikke optage fra enheden i %d-kanals-tilstand." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Kunne ikke Ã¥bne lydenhed til optagelse. Enheden anvendes af et andet program." + +msgid "Could not open audio device for recording." +msgstr "Kunne ikke Ã¥bne lydenhed til optagelse." + +msgid "Could not open CD device for reading." +msgstr "Kunne ikke læse fra cd-enhed." + +msgid "Could not seek CD." +msgstr "Kunne ikke søge pÃ¥ cd." + +msgid "Could not read CD." +msgstr "Kunne ikke læse cd." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Kunne ikke Ã¥bne vfs-filen \"%s\" til skrivning: %s." + +msgid "No filename given" +msgstr "Intet filnavn angivet" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Kunne ikke lukke vfs-filen \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fejl ved skrivning til filen \"%s\"." + +msgid "Internal data stream error." +msgstr "Intern datastrømsfejl." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Et %s plugin er nødvendigt ved afspilning af denne sekvens, men ikke " +"installeret." + +msgid "This appears to be a text file" +msgstr "Denne fremstÃ¥r som en tekstfil" + +msgid "Could not determine type of stream" +msgstr "Kunne ikke afgøre strømtypen" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Defekt undertekst URI \"%s\", undertekster deaktiveret." + +msgid "No URI specified to play from." +msgstr "Ingen angivet URI til afspilning." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Ugyldig URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP sekvenser kan endnu ikke afspilles." + +msgid "Could not create \"decodebin\" element." +msgstr "Kunne ikke danne et \"decodebin\" element." + +msgid "Source element is invalid." +msgstr "Kildeelement er ugyldigt." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Der blev kun fundet en undertekst-sekvens. Enten forsøger du at indlæse en " +"undertekst-fil eller en anden type tekstfil, eller media-filen blev ikke " +"genkendt." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Du har ingen dekoder installeret, der kan hÃ¥ndtere denne fil. Du er nødt til " +"at installere de nødvendige plugins." + +msgid "This is not a media file" +msgstr "Dette er ikke en media-fil" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "En undertekst-sekvens blev fundet, men ingen video-sekvens." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "BÃ¥de autovideosink og xvimagesink elementerne mangler." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "'%s' elementet mangler - check din GStreamer installation." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "BÃ¥de autoaudiosink og alsasink elementerne mangler." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "BÃ¥de autovideosink og %s elementer mangler." + +msgid "The autovideosink element is missing." +msgstr "Elementet autovideosink mangler." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Konfigureret videosink %s virker ikke." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "BÃ¥de autovideosink og %s elementerne virker ikke." + +msgid "The autovideosink element is not working." +msgstr "Elementet autovideosink virker ikke." + +msgid "Custom text sink element is not usable." +msgstr "Brugertilpasset tekstsinkelement er ikke brugbart." + +msgid "No volume control found" +msgstr "Ingen lydstyrkekontrol fundet" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "BÃ¥de autoaudiosink og %s elementerne mangler." + +msgid "The autoaudiosink element is missing." +msgstr "Elementet autoaudiosink mangler." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Konfigureret audiosink %s virker ikke." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "BÃ¥de autoaudiosink og %s elementerne virker ikke." + +msgid "The autoaudiosink element is not working." +msgstr "Elementet autoaudiosink virker ikke." + +msgid "Can't play a text file without video or visualizations." +msgstr "Kan ikke afspille en tekstfil uden video eller visualiseringer." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Ingen dekoder tilgængelig for type '%s'." + +msgid "This stream type cannot be played yet." +msgstr "Denne type lydstrøm kan ikke afspilles endnu." + +# har beholdt »er« +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Ingen URI-hÃ¥ndtering er implementeret for \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Der opstod en fejl under data-overførsel til \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" +"Der opstod en fejl under overførsel af gdp-overskriftsdata til \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Der opstod en fejl under overførsel af gdp-pakkeindhold til \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Opkobling til %s:%d afvist." + +msgid "Can't record audio fast enough" +msgstr "Kan ikke optage lyd hurtigt nok" + +msgid "Failed to read tag: not enough data" +msgstr "Kunne ikke læse mærke: Ikke nok data" + +msgid "track ID" +msgstr "spor-id" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz spor-id" + +msgid "artist ID" +msgstr "kunstner-id" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz kunstner-id" + +msgid "album ID" +msgstr "album-id" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz album-id" + +msgid "album artist ID" +msgstr "albumkunstner-id" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albumkunstner-id" + +msgid "track TRM ID" +msgstr "spor TRM-id" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM-id" + +# nb ikke handling men navneord. +# "optagelukkertid" / "optagerlukkertid" +# Mogens: shutter speed = lukkerhastighed +msgid "capturing shutter speed" +msgstr "optagerlukkertid" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Lukketidshastighed brugt nÃ¥r et billede optages, i sekunder" + +msgid "capturing focal ratio" +msgstr "brændforhold for optager" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Brændforhold (f-nummer) brugt under optagelse af billedet" + +msgid "capturing focal length" +msgstr "brændvidde for optager" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Brændvidde pÃ¥ linse brugt under optagelse af billedet, i mm" + +msgid "capturing digital zoom ratio" +msgstr "digitalt zoomforhold for optager" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Digitalt zoomforhold brugt under optagelse af et billede" + +msgid "capturing iso speed" +msgstr "iso-hastighed for optager" + +msgid "The ISO speed used when capturing an image" +msgstr "ISO-hastigheden brugt under optagelse af et billede" + +msgid "capturing exposure program" +msgstr "belysningsprogram for optagelse" + +msgid "The exposure program used when capturing an image" +msgstr "Belysningsprogrammet brugt under optagelse af et billede" + +msgid "capturing exposure mode" +msgstr "belysningstilstand for optagelse" + +msgid "The exposure mode used when capturing an image" +msgstr "Belysningstilstanden brugt under optagelse af et billede" + +msgid "capturing exposure compensation" +msgstr "belysningskompensation for optagelse" + +msgid "The exposure compensation used when capturing an image" +msgstr "Belysningskompensationen brugt under optagelse af et billede" + +# "optagelsestype for optagelse af scene" / +# "optagelsestype for sceneoptagelse" / +# "sceneoptagelsestype for optager" / +# "optageroptagelsestype for scene" +# De to første rammer vist forlægget mest præcist. +msgid "capturing scene capture type" +msgstr "optagelsestype for optagelse af scene" + +msgid "The scene capture mode used when capturing an image" +msgstr "Sceneoptagelsestilstanden brugt da billedet blev optaget" + +# "justering af optageforstærkning" / +# "justering af optagerforstærkning" +msgid "capturing gain adjustment" +msgstr "justering af optageforstærkning" + +msgid "The overall gain adjustment applied on an image" +msgstr "Den samlede optageforstærkning brugt pÃ¥ et billede" + +msgid "capturing white balance" +msgstr "hvidbalance for optagelse" + +msgid "The white balance mode set when capturing an image" +msgstr "Hvidbalancetilstanden angivet under optagelse af et billede" + +# kontrast for optagelse +msgid "capturing contrast" +msgstr "optagekontrast" + +# Jeg tror "direction" skal oversættes til "indstilling af" +# (sml. "director" ~ "instruction" ~ "instruering" ~ "indstilling" +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Indstilling af kontrastprocessen brugt under optagelse af et billede" + +msgid "capturing saturation" +msgstr "farvemætning for optagelse" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"Indstillingen af farvemætningsprocessen brugt under optagelse af et billede" + +msgid "capturing sharpness" +msgstr "optageskarphed" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "skarphedindstilling brugt under optagelse af et billede" + +msgid "capturing flash fired" +msgstr "optagerblitzen der blev brugt" + +msgid "If the flash fired while capturing an image" +msgstr "Hvorvidt blitzen blev brugt under optagelse af et billede" + +msgid "capturing flash mode" +msgstr "optagererens blitztilstand" + +msgid "The selected flash mode while capturing an image" +msgstr "Den valgte blitztilstand under optagelse af et billede" + +msgid "capturing metering mode" +msgstr "optagerens mÃ¥letilstand" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "MÃ¥letilstanden brugt da optagelsens belysning skulle bestemmes" + +msgid "capturing source" +msgstr "optagekilde" + +msgid "The source or type of device used for the capture" +msgstr "Kilden eller typen af enhed brugt under optagelsen" + +msgid "image horizontal ppi" +msgstr "billedets vandrette billedtæthed (ppi)" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "PÃ¥tænkt vandret billedtæthed for medie (billede/video) i ppi" + +msgid "image vertical ppi" +msgstr "billedets lodrette billedtæthed (ppi)" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "PÃ¥tænkt lodret billedtæthed for medie (billede/video) i ppi" + +msgid "This CD has no audio tracks" +msgstr "Denne cd har ingen lydspor" + +msgid "ID3 tag" +msgstr "ID3-mærke" + +msgid "APE tag" +msgstr "APE-mærke" + +msgid "ICY internet radio" +msgstr "ICY-internetradio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Ukomprimeret grÃ¥tonebillede" + +msgid "Run-length encoding" +msgstr "Kørsels-længde indkodning" + +msgid "Sami subtitle format" +msgstr "Sami undertekstformat" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer undertekstformat" + +msgid "Kate subtitle format" +msgstr "Undertekstformat Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Ukomprimeret plan-YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Ukomprimeret plan-YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Ukomprimeret pakket YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Ukomprimeret pakket YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Ukomprimeret pakket YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Ukomprimeret pakket YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Ukomprimeret pakket YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Ukomprimeret plan-YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Ukomprimeret plan-YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Ukomprimeret sort og hvid Y-plan" + +msgid "Uncompressed YUV" +msgstr "Ukomprimeret YUV" + +# Findes dette ord palettet pÃ¥ dansk ? evt. indekseret +# Ukomprimeret palettet %d-bit %s +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Ukomprimeret indekseret %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 version %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Ufiltreret %d-bit PCM audio" + +msgid "Raw PCM audio" +msgstr "Ufiltreret PCM audio" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Ufiltreret %d-bit flydende-komma audio" + +msgid "Raw floating-point audio" +msgstr "Ufiltreret flydende-komma audio" + +msgid "Audio CD source" +msgstr "Audio cd kilde" + +msgid "DVD source" +msgstr "DVD kilde" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol (RTSP) kilde" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) protokol kilde" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokol kilde" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video RTP-depayloader" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s lyd RTP-depayloader" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP-depayloader" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s afkoder" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video RTP-payloader" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s lyd RTP-payloader" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP-payloader" + +#, c-format +msgid "%s muxer" +msgstr "%s muxer" + +#, c-format +msgid "%s encoder" +msgstr "%s indkoder" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer element %s" + +msgid "Unknown source element" +msgstr "Ukendt kildeelement" + +# sink ? (afløb, kanal) +msgid "Unknown sink element" +msgstr "Ukendt afløbselement" + +msgid "Unknown element" +msgstr "Ukendt element" + +msgid "Unknown decoder element" +msgstr "Ukendt afkodeelement" + +msgid "Unknown encoder element" +msgstr "Ukendt indkodeelement" + +msgid "Plugin or element of unknown type" +msgstr "Plugin eller element af ukendt type" + +msgid "No device specified." +msgstr "Ingen enhed angivet." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Enheden \"%s\" eksisterer ikke." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Enheden \"%s\" er allerede i brug." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Kunne ikke tilgÃ¥ enheden \"%s\"." diff --git a/gst-plugins-base-subtitles0.10/po/de.po b/gst-plugins-base-subtitles0.10/po/de.po new file mode 100644 index 0000000..523c0f0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/de.po @@ -0,0 +1,645 @@ +# German messages for gst-plugins-base 0.10.32.2 +# Copyright © 2006 Karl Eichwalder +# This file is distributed under the same license as the gst-plugins-base package. +# Karl Eichwalder , 2006. +# Mario Blättermann , 2010. +# Christian Kirbach , 2009, 2010, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-30 17:11+0100\n" +"PO-Revision-Date: 2011-04-28 00:04+0200\n" +"Last-Translator: Christian Kirbach \n" +"Language-Team: German \n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Hauptregler" + +msgid "Bass" +msgstr "Bass" + +msgid "Treble" +msgstr "Höhen" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Line-Eingang" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC-Lautsprecher" + +msgid "Playback" +msgstr "Wiedergabe" + +msgid "Capture" +msgstr "Aufnahme" + +msgid "Could not open device for playback in mono mode." +msgstr "Gerät konnte nicht zur Wiedergabe in Mono geöffnet werden." + +msgid "Could not open device for playback in stereo mode." +msgstr "Gerät konnte nicht zur Wiedergabe in Stereo geöffnet werden." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Gerät konnte nicht zur Wiedergabe im %d-Kanalmodus geöffnet werden." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Audio-Gerät konnte nicht zur Wiedergabe geöffnet werden. Es wird durch eine " +"andere Anwendung verwendet." + +msgid "Could not open audio device for playback." +msgstr "Audio-Gerät konnte nicht zur Wiedergabe geöffnet werden." + +msgid "Could not open device for recording in mono mode." +msgstr "Gerät konnte nicht zur Aufnahme in Mono geöffnet werden." + +msgid "Could not open device for recording in stereo mode." +msgstr "Gerät konnte nicht zur Aufnahme in Stereo geöffnet werden." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Gerät konnte nicht zur Aufnahme im %d-Kanalmodus geöffnet werden." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Audio-Gerät konnte nicht zur Aufnahme geöffnet werden. Es wird durch eine " +"andere Anwendung verwendet." + +msgid "Could not open audio device for recording." +msgstr "Audio-Gerät konnte nicht zur Aufnahme geöffnet werden." + +msgid "Could not open CD device for reading." +msgstr "Das CD-Laufwerk konnte nicht zum Lesen geöffnet werden." + +msgid "Could not seek CD." +msgstr "Suchvorgang auf der CD ist fehlgeschlagen." + +msgid "Could not read CD." +msgstr "CD konnte nicht gelesen werden." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "VFS-Datei »%s« konnte nicht zum Schreiben geöffnet werden: %s." + +msgid "No filename given" +msgstr "Kein Dateiname angegeben" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "VFS-Datei »%s« konnte nicht geschlossen werden." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fehler beim Schreiben in die Datei »%s«." + +msgid "Internal data stream error." +msgstr "Interner Fehler im Datenstrom." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Ein Plugin »%s« wird zum Abspielen dieses Datenstroms benötigt, ist aber " +"nicht installiert." + +msgid "This appears to be a text file" +msgstr "Dies scheint eine Textdatei zu sein" + +msgid "Could not determine type of stream" +msgstr "Der Typ des Datenstroms konnte nicht bestimmt werden" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Ungültige Untertitel-URI »%s«, Untertitel werden deaktiviert." + +msgid "No URI specified to play from." +msgstr "Keine Adresse (URI) zum Abspielen angegeben." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Ungültige Adresse (URI) »%s«." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP-Datenströme können noch nicht abgespielt werden." + +msgid "Could not create \"decodebin\" element." +msgstr "Das Element »decodebin« konnte nicht erstellt werden." + +msgid "Source element is invalid." +msgstr "Das Quellelement ist ungültig." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Es wurde nur ein Datenstrom mit Untertiteln erkannt. Entweder laden Sie eine " +"Datei mit Untertiteln oder eine andere Art Textdatei oder die Mediendatei " +"wurde nicht erkannt." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Sie haben keinen Decoder für den Umgang mit dieser Datei installiert. Sie " +"sollten die erforderlichen Plugins installieren." + +msgid "This is not a media file" +msgstr "Dies ist keine Mediendatei" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Ein Datenstrom mit Untertiteln wurde erkannt, aber kein Videostrom." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Beide Elemente »autovideosink« und »xvimagesink« fehlen." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" +"Das Element »%s« fehlt - überprüfen Sie Ihre Installation von GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Beide Elemente »autoaudiosink« und »alsasink« fehlen." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Beide Elemente »autovideosink« und »%s« fehlen." + +msgid "The autovideosink element is missing." +msgstr "Das Element »autovideosink« fehlt." + +# »Senke« hört sich echt scheußlich an. +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Das konfigurierte Videoziel »%s« funktioniert nicht." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Beide Elemente »autovideosink« und »%s« funktionieren nicht." + +msgid "The autovideosink element is not working." +msgstr "Das Element »autovideosink« funktioniert nicht." + +msgid "Custom text sink element is not usable." +msgstr "Das eigene Element des Textziels ist nicht verwendbar." + +msgid "No volume control found" +msgstr "Keine Lautstärkeregelung gefunden" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Beide Elemente »autoaudiosink« und »%s« fehlen." + +msgid "The autoaudiosink element is missing." +msgstr "Das Element »autoaudiosink« fehlt." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Das konfigurierte Audioziel »%s« funktioniert nicht." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Beide Elemente »autoaudiosink« und »%s« funktionieren nicht." + +msgid "The autoaudiosink element is not working." +msgstr "Das Element »autoaudiosink« funktioniert nicht." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Es kann keine Textdatei ohne Video oder Visualisierungen abgespielt werden." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Für den Typ »%s« ist kein Decoder vorhanden." + +msgid "This stream type cannot be played yet." +msgstr "Dieser Datenstrom kann noch nicht abgespielt werden." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Es ist kein URI-Handler für »%s« implementiert." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Fehler beim Senden der Daten nach »%s:%d«." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Fehler beim Senden der GDP-Kopfdaten nach »%s:%d«." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Fehler beim Senden der GDP-Nutzdaten nach »%s:%d«." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Verbindung nach %s:%d wurde verweigert." + +msgid "Can't record audio fast enough" +msgstr "Der Ton kann nicht schnell genug aufgezeichnet werden" + +msgid "Failed to read tag: not enough data" +msgstr "Lesen der Kennzeichnung schlug fehl: Nicht genug Daten" + +msgid "track ID" +msgstr "Titelkennung" + +msgid "MusicBrainz track ID" +msgstr "Titelkennung von MusicBrainz" + +# Hach, hier haben wir ja noch mehr »Interpreten«! +msgid "artist ID" +msgstr "Künstlerkennung" + +msgid "MusicBrainz artist ID" +msgstr "Künstlerkennung von MusicBrainz" + +msgid "album ID" +msgstr "Albenkennung" + +msgid "MusicBrainz album ID" +msgstr "Albenkennung von MusicBrainz" + +msgid "album artist ID" +msgstr "Kennung des Albenkünstlers" + +msgid "MusicBrainz album artist ID" +msgstr "Kennung des Albenkünstlers von MusicBrainz" + +msgid "track TRM ID" +msgstr "TRM-Kennung verfolgen" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz-TRM-Kennung" + +msgid "capturing shutter speed" +msgstr "Belichtungszeit" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Belichtungszeit bei Aufnahme eines Bildes in Sekunden" + +msgid "capturing focal ratio" +msgstr "Blendenwert" + +# F-Nummer kennt bei uns kein Mensch. Oder doch...? +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Der verwendete Blendenwert bei Bildaufnahme" + +msgid "capturing focal length" +msgstr "Brennweite" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Die verwendete Brennweite des Objektivs bei Bildaufnahme in mm" + +msgid "capturing digital zoom ratio" +msgstr "Digitale Vergrößerung" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Die verwendete digitale Vergrößerung bei Bildaufnahme" + +msgid "capturing iso speed" +msgstr "ISO-Empfindlichkeit" + +msgid "The ISO speed used when capturing an image" +msgstr "Die verwendete ISO-Empfindlichkeit bei Bildaufnahme" + +msgid "capturing exposure program" +msgstr "Belichtungsprogramm" + +msgid "The exposure program used when capturing an image" +msgstr "Das verwendete Belichtungsprogramm bei Bildaufnahme" + +msgid "capturing exposure mode" +msgstr "Belichtungsmodus der Aufnahme" + +msgid "The exposure mode used when capturing an image" +msgstr "Der verwendete Belichtungsmodus bei Bildaufnahme" + +msgid "capturing exposure compensation" +msgstr "Belichtungskorrektur der Aufnahme" + +msgid "The exposure compensation used when capturing an image" +msgstr "Der verwendete Belichtungskorrektur bei Bildaufnahme" + +msgid "capturing scene capture type" +msgstr "Motivwahl" + +msgid "The scene capture mode used when capturing an image" +msgstr "Die verwendete Motivwahl bei Bildaufnahme" + +msgid "capturing gain adjustment" +msgstr "Anpassung der Aufnahmebelichtung" + +# »Gain adjustment« kenne ich eigentlich nur bei Audiodateien. Müsste sich hier um eine Anpassung der Belichtungswerte handeln. +msgid "The overall gain adjustment applied on an image" +msgstr "Die auf das Bild angewendete Anpassung der Belichtungswerte" + +msgid "capturing white balance" +msgstr "Weißabgleich" + +msgid "The white balance mode set when capturing an image" +msgstr "Der eingestellte Weißabgleich bei Bildaufnahme" + +msgid "capturing contrast" +msgstr "Kontrast" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Die Einstellung zur angewendeten Kontrastbearbeitung bei Bildaufnahme" + +msgid "capturing saturation" +msgstr "Sättigung" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"Die Einstellung zur angewendeten Sättigungsbearbeitung bei Bildaufnahme" + +msgid "capturing sharpness" +msgstr "Schärfe" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Die Einstellung zur angewendeten Schärfebearbeitung bei Bildaufnahme" + +msgid "capturing flash fired" +msgstr "Blitzauslösung" + +msgid "If the flash fired while capturing an image" +msgstr "Gibt an, ob der Blitz bei der Bildaufnahme ausgelöst wurde" + +msgid "capturing flash mode" +msgstr "Blitzmodus" + +msgid "The selected flash mode while capturing an image" +msgstr "Der gewählte Blitzmodus bei Bildaufnahme" + +msgid "capturing metering mode" +msgstr "Messmethode der Aufnahme" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Die während der Bestimmung der Belichtungszeit eingesetzte Messmethode zur " +"Aufnahme eines Bildes" + +msgid "capturing source" +msgstr "Aufnahmequelle" + +msgid "The source or type of device used for the capture" +msgstr "Die Quelle oder der Gerätetyp, mit dem aufgenommen wird" + +msgid "image horizontal ppi" +msgstr "Horizontale Bildauflösung" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Horizontale Auflösung des Bildes oder Videos in ppi (Pixel pro Zoll)" + +msgid "image vertical ppi" +msgstr "Vertikale Bildauflösung" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Vertikale Auflösung des Bildes oder Videos in ppi (Pixel pro Zoll)" + +msgid "This CD has no audio tracks" +msgstr "Auf dieser CD befinden sich keine Audio-Titel" + +msgid "ID3 tag" +msgstr "ID3-Kennzeichnung" + +msgid "APE tag" +msgstr "APE-Kennzeichnung" + +msgid "ICY internet radio" +msgstr "ICY Internet-Radio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV verlustlos" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "verlustloses MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Unkomprimiertes Graubild" + +msgid "Run-length encoding" +msgstr "RLE-Codierung" + +msgid "Sami subtitle format" +msgstr "Untertitel-Format Sami" + +msgid "TMPlayer subtitle format" +msgstr "Untertitel-Format TMPlayer" + +msgid "Kate subtitle format" +msgstr "Untertitel-Format Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Unkomprimiertes ungepacktes YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Unkomprimiertes ungepacktes YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Unkomprimiertes gepacktes YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Unkomprimiertes gepacktes YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Unkomprimiertes gepacktes YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Unkomprimiertes gepacktes YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Unkomprimiertes gepacktes YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Unkomprimiertes ungepacktes YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Unkomprimiertes ungepacktes YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Unkomprimiertes schwarz-weißes Y-plane" + +msgid "Uncompressed YUV" +msgstr "Unkomprimiertes YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Unkomprimiertes palettiertes %d-Bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Version %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Rohes %d-bit PCM-Audio" + +msgid "Raw PCM audio" +msgstr "Rohes PCM-Audio" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Rohes %d-Bit Gleitkomma-Audio" + +msgid "Raw floating-point audio" +msgstr "Rohes Gleitkomma-Audio" + +msgid "Audio CD source" +msgstr "Musik-CD-Quelle" + +msgid "DVD source" +msgstr "DVD-Quelle" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol (RTSP)-Quelle" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS)-Protokollquelle" + +#, c-format +msgid "%s protocol source" +msgstr "%s Protokollquelle" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s-Video RTP-Payload-Entnahme" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s-Audio RTP-Payload-Entnahme" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s-RTP-Payload-Entnahme" + +#, c-format +msgid "%s demuxer" +msgstr "%s-Demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s-Decoder" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s-Video RTP-Payloader" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s-Audio RTP-Payloader" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s-RTP-Payloader" + +#, c-format +msgid "%s muxer" +msgstr "%s-Multiplexer" + +#, c-format +msgid "%s encoder" +msgstr "%s-Encoder" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer-Element %s" + +msgid "Unknown source element" +msgstr "Unbekanntes Quellelement" + +msgid "Unknown sink element" +msgstr "Unbekanntes Zielelement" + +msgid "Unknown element" +msgstr "Unbekanntes Element" + +msgid "Unknown decoder element" +msgstr "Unbekanntes Decoder-Element" + +msgid "Unknown encoder element" +msgstr "Unbekanntes Encoder-Element" + +msgid "Plugin or element of unknown type" +msgstr "Plugin oder Element unbekannten Typs" + +msgid "No device specified." +msgstr "Kein Gerät angegeben." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Das Gerät »%s« existiert nicht." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Das Gerät »%s« wird bereits verwendet." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Das Gerät »%s« konnte nicht zum Lesen und Schreiben geöffnet werden." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "" +#~ "Es können nicht Untertiteltexte und Kleinbilder zugleich angezeigt werden." + +#~ msgid "No Temp directory specified." +#~ msgstr "Kein temporärer Ordner angegeben." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Temporäre Datei »%s« konnte nicht erstellt werden." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Die Datei »%s« konnte zum Lesen nicht geöffnet werden." + +#~ msgid "Internal data flow error." +#~ msgstr "Interner Fehler im Datenstrom." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Das Element »decodebin2« konnte nicht erstellt werden." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Das Element »queue2« konnte nicht erstellt werden." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Das Element »typefind« konnte nicht erstellt werden." + +#~ msgid "No file name specified." +#~ msgstr "Kein Dateiname angegeben." diff --git a/gst-plugins-base-subtitles0.10/po/el.po b/gst-plugins-base-subtitles0.10/po/el.po new file mode 100644 index 0000000..4a75f7c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/el.po @@ -0,0 +1,625 @@ +# Greek translation for gst-plugins-base. +# This file is put in the public domain. +# +# Simos Xenitellis , 2010. +# Michael Kotsarinis , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-10-27 12:05+0200\n" +"Last-Translator: Michael Kotsarinis \n" +"Language-Team: Greek \n" +"Language: el\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" +"X-Poedit-Language: Greek\n" +"X-Poedit-Country: GREECE\n" + +msgid "Master" +msgstr "Γενικός" + +msgid "Bass" +msgstr "Μπάσα" + +msgid "Treble" +msgstr "Πρίμα" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Συνθεσάιζερ" + +msgid "Line-in" +msgstr "Είσοδος γραμμής" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Μικρόφωνο" + +msgid "PC Speaker" +msgstr "Ηχείο υπολογιστή" + +msgid "Playback" +msgstr "Αναπαραγωγή" + +msgid "Capture" +msgstr "Σύλληψη" + +msgid "Could not open device for playback in mono mode." +msgstr "Αδυναμία ανοίγματος συσκευής για μονοφωνική αναπαραγωγή." + +msgid "Could not open device for playback in stereo mode." +msgstr "Αδυναμία ανοίγματος συσκευής για στερεοφωνική αναπαραγωγή." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Αδυναμία ανοίγματος συσκευής για αναπαραγωγή %d-καναλιών." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Αδυναμία ανοίγματος συσκευής ήχου για αναπαραγωγή. Η συσκευή χρησιμοποιείται " +"από άλλη εφαρμογή." + +msgid "Could not open audio device for playback." +msgstr "Αδυναμία ανοίγματος συσκευής για αναπαραγωγή." + +msgid "Could not open device for recording in mono mode." +msgstr "Αδυναμία ανοίγματος συσκευής για μονοφωνική εγγραφή." + +msgid "Could not open device for recording in stereo mode." +msgstr "Αδυναμία ανοίγματος συσκευής για στερεοφωνική εγγραφή." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Αδυναμία ανοίγματος συσκευής για εγγραφή %d-καναλιών." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Αδυναμία ανοίγματος συσκευής ήχου για εγγραφή. Η συσκευή χρησιμοποιείται από " +"άλλη εφαρμογή." + +msgid "Could not open audio device for recording." +msgstr "Αδυναμία ανοίγματος συσκευής ήχου για εγγραφή." + +msgid "Could not open CD device for reading." +msgstr "Αδυναμία ανοίγματος συσκευής CD για ανάγνωση." + +msgid "Could not seek CD." +msgstr "Αδυναμία αναζήτησης CD." + +msgid "Could not read CD." +msgstr "Αδυναμία ανάγνωσης CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Αδυναμία ανοίγματος αρχείου vfs «%s» για εγγραφή: %s." + +msgid "No filename given" +msgstr "Δεν δόθηκε όνομα αρχείου" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Αδυναμία κλεισίματος αρχείου vfs «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Σφάλμα κατά την εγγραφή στο αρχείο «%s»." + +msgid "Internal data stream error." +msgstr "Σφάλμα εσωτερικής ροής δεδομένων." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Απαιτείται μια πρόσθετη λειτουργία %s για την αναπαραγωγή αυτής της ροής, " +"αλλά δεν έχει εγκατασταθεί." + +msgid "This appears to be a text file" +msgstr "Αυτό φαίνεται να είναι αρχείο κειμένου" + +msgid "Could not determine type of stream" +msgstr "Αδυναμία προσδιορισμού τύπου ροής" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Μη έγκυρο URI υποτίτλων «%s», υπότιτλοι απενεργοποιήθηκαν." + +msgid "No URI specified to play from." +msgstr "Δεν ορίσθηκε URI από το οποίο θα γίνει αναπαραγωγή." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Μη έγκυρο URI «%s»." + +msgid "RTSP streams cannot be played yet." +msgstr "Ροές RTSP δεν μπορούν να αναπαραχθούν ακόμα." + +msgid "Could not create \"decodebin\" element." +msgstr "Αδυναμία δημιουργία στοιχείου «decodebin»." + +msgid "Source element is invalid." +msgstr "Το στοιχείο προέλευσης δεν είναι έγκυρο." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Ανιχνεύθηκε μόνο μια ροή υποτίτλων. Είτε φορτώνετε ένα αρχείο υποτίτλων ή " +"κάποιο άλλο τύπο αρχείου κειμένου, ή το αρχείο πολυμέσων δεν αναγνωρίσθηκε." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Δεν έχετε εγκατεστημένο αποκωδικοποιητή για να χειριστεί αυτό το αρχείο. " +"Μπορεί να χρειάζεται να εγκαταστήσετε τις απαραίτητες πρόσθετες λειτουργίες." + +msgid "This is not a media file" +msgstr "Αυτό δεν είναι αρχείο πολυμέσων" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Ανιχνεύθηκε ροή υποτίτλων αλλά όχι ροή βίντεο." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Λείπουν και τα δύο στοιχεία autovideosink και xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Λείπει το στοιχείο '%s' - ελέγξτε την εγκατάσταση του GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Λείπουν και τα δύο στοιχεία autoaudiosink και alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Λείπουν και τα δύο στοιχεία autoaudiosink και %s." + +msgid "The autovideosink element is missing." +msgstr "Το στοιχείο autovideosink λείπει." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Το διαμορφωμένο videosink %s δεν δουλεύει." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Λείπουν και τα δύο στοιχεία autovideosink και %s." + +msgid "The autovideosink element is not working." +msgstr "Το στοιχείο autovideosink δεν δουλεύει." + +msgid "Custom text sink element is not usable." +msgstr "Το προσαρμοσμένο στοιχείο text sink δεν είναι λειτουργικό." + +msgid "No volume control found" +msgstr "Δεν βρέθηκε ρυθμιστικό έντασης" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Λείπουν και τα δύο στοιχεία autoaudiosink και %s." + +msgid "The autoaudiosink element is missing." +msgstr "Το στοιχείο autoaudiosink λείπει." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Το διαμορφωμένο audiosink %s δεν δουλεύει." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Και τα δύο στοιχεία autoaudiosink και %s δεν δουλεύουν." + +msgid "The autoaudiosink element is not working." +msgstr "Το στοιχείο autoaudiosink δεν δουλεύει." + +msgid "Can't play a text file without video or visualizations." +msgstr "Αδυναμία αναπαραγωγής αρχείου κειμένου χωρίς βίντεο ή οπτικοποίηση." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Δεν υπάρχει διαθέσιμος αποκωδικοποιητής για τον τύπο '%s'." + +msgid "This stream type cannot be played yet." +msgstr "Αυτός ο τύπος ροής δεν μπορεί να αναπαραχθεί ακόμη." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Δεν έχει υλοποιηθεί χειριστής URI για «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Σφάλμα κατά την αποστολή δεδομένων σε «%s:%d»." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Σφάλμα κατά την αποστολή δεδομένων κεφαλίδας gdp σε «%s:%d»." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Σφάλμα κατά την αποστολή δεδομένων φόρτου gdp σε «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Άρνηση σύνδεσης σε %s:%d." + +msgid "Can't record audio fast enough" +msgstr "Αδυναμία εγγραφής ήχου αρκετά γρήγορα" + +msgid "Failed to read tag: not enough data" +msgstr "Αποτυχία ανάγνωσης ετικέτας: δεν υπάρχουν αρκετά δεδομένα" + +msgid "track ID" +msgstr "ID κομματιού" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz ID κομματιού" + +msgid "artist ID" +msgstr "ID καλλιτέχνη" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz ID καλλιτέχνη" + +msgid "album ID" +msgstr "ID άλμπουμ" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz ID άλμπουμ" + +msgid "album artist ID" +msgstr "ID καλλιτενη άλμπουμ" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz ID καλλιτέχνη άλμπουμ" + +msgid "track TRM ID" +msgstr "TRM ID κομματιού" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "ταχύτητα κλείστρου λήψης" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Ταχύτητα κλείστρου κατά τη λήψη μιας εικόνας, σε δευτερόλεπτα" + +msgid "capturing focal ratio" +msgstr "εστιακός λόγος λήψης" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" +"Εστιακός λόγος (f-number ή f-stop) που χρησιμοποιήθηκε κατά τη λήψη της " +"εικόνας" + +msgid "capturing focal length" +msgstr "εστιακό μήκος λήψης" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" +"Το εστιακό μήκος του φακού που χρησιμοποιήθηκε κατά τη λήψη της εικόνας, σε " +"mm" + +msgid "capturing digital zoom ratio" +msgstr "λόγος ψηφιακού ζουμ λήψης" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Ο λόγος ψηφιακού ζουμ που χρησιμοποιήθηκε κατά τη λήψη μιας εικόνας" + +msgid "capturing iso speed" +msgstr "ταχύτητα iso λήψης" + +msgid "The ISO speed used when capturing an image" +msgstr "Η ταχύτητα ISO που χρησιμοποιήθηκε κατά τη λήψη μιας εικόνας" + +msgid "capturing exposure program" +msgstr "πρόγραμμα έκθεσης λήψης" + +msgid "The exposure program used when capturing an image" +msgstr "Το πρόγραμμα έκθεσης που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +msgid "capturing exposure mode" +msgstr "τρόπος έκθεσης λήψης" + +msgid "The exposure mode used when capturing an image" +msgstr "Ο τρόπος έκθεσης που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "τρόπος έκθεσης λήψης" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "Ο τρόπος έκθεσης που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +msgid "capturing scene capture type" +msgstr "τύπος σύλληψης σκηνής της λήψης" + +msgid "The scene capture mode used when capturing an image" +msgstr "Ο τρόπος σύλληψης σκηνής που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +msgid "capturing gain adjustment" +msgstr "προσαρμογή κέρδους λήψης" + +msgid "The overall gain adjustment applied on an image" +msgstr "Η συνολική προσαρμογή κέρδους που εφαρμόσθηκε σε μια εικόνα" + +msgid "capturing white balance" +msgstr "ισορροπία λευκού λήψης" + +msgid "The white balance mode set when capturing an image" +msgstr "Η ισορροπία λευκού που ορίσθηκε κατά τη λήψη μιας εικόνας" + +msgid "capturing contrast" +msgstr "αντίθεση λήψης" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" +"Η κατεύθυνση της επεξεργασίας της αντίθεσης που εφαρμόσθηκε κατά τη λήψη " +"μιας εικόνας" + +msgid "capturing saturation" +msgstr "κορεσμός λήψης" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"Η κατεύθυνση της επεξεργασίας του κορεσμού που εφαρμόσθηκε κατά τη λήψη " +"μιας εικόνας" + +msgid "capturing sharpness" +msgstr "ευκρίνεια λήψης" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" +"Η κατεύθυνση της επεξεργασίας της ευκρίνειας που εφαρμόσθηκε κατά τη λήψη " +"μιας εικόνας" + +msgid "capturing flash fired" +msgstr "ενεργοποίηση φλας στη λήψη" + +msgid "If the flash fired while capturing an image" +msgstr "Αν ενεργοποιήθηκε το φλας κατά τη λήψη μιας εικόνας" + +msgid "capturing flash mode" +msgstr "κατάσταση φλας λήψης" + +msgid "The selected flash mode while capturing an image" +msgstr "Η επιλεγμένη κατάσταση λειτουργίας του φλας κατά τη λήψη μιας εικόνας" + +msgid "capturing metering mode" +msgstr "τρόπος φωτομέτρησης λήψης" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Ο τρόπος φωτομέτρησης που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +msgid "capturing source" +msgstr "πηγή λήψης" + +msgid "The source or type of device used for the capture" +msgstr "" +"Η πηγή ή ο τύπος της συσκευής που χρησιμοποιήθηκε για τη λήψη μιας εικόνας" + +msgid "image horizontal ppi" +msgstr "οριζόντια ppi εικόνας" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Η σκοπούμενη οριζόντια πυκνότητα εικονοστοιχείων (pixel) του μέσου (εικόνα/" +"βίντεο) σε ppi" + +msgid "image vertical ppi" +msgstr "κάθετα ppi εικόνας" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Η σκοπούμενη κάθετη πυκνότητα εικονοστοιχείων (pixel) του μέσου (εικόνα/" +"βίντεο) σε ppi" + +msgid "This CD has no audio tracks" +msgstr "Αυτό το CD δεν έχει ηχητικά κομμάτια" + +msgid "ID3 tag" +msgstr "Ετικέτα ID3" + +msgid "APE tag" +msgstr "Ετικέτα APE" + +msgid "ICY internet radio" +msgstr "Διαδικτυακό ραδιόφωνο ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Μη απωλεστικός ήχος της Apple (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Ελεύθερος μη απωλεστικός κωδικοποιητής ήχου (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Μη απωλεστικός αληθής ήχος (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "Μη απωλεστικός CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Μη απωλεστικός MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Ασυμπίεστη εικόνα κλίμακας του γκρι" + +msgid "Run-length encoding" +msgstr "Κωδικοποίηση Run-length" + +msgid "Sami subtitle format" +msgstr "Μορφή υποτίτλων Sami " + +msgid "TMPlayer subtitle format" +msgstr "Μορφή υποτίτλων TMPlayer" + +msgid "Kate subtitle format" +msgstr "Μορφή υποτίτλων Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Ασυμπίεστο planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Ασυμπίεστο planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Ασυμπίεστο packed YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Ασυμπίεστο packed YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Ασυμπίεστο packed YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Ασυμπίεστο packed YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Ασυμπίεστο packed YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Ασυμπίεστο planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Ασυμπίεστο planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Ασυμπίεστο ασπρόμαυρο Y-plane" + +msgid "Uncompressed YUV" +msgstr "Ασυμπίεστο YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Ασυμπίεστο palettized %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Έκδοση %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Καθαρός %d-bit PCM ήχος" + +msgid "Raw PCM audio" +msgstr "Καθαρός ήχος PCM " + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Καθαρός ήχος %d-bit floating-point" + +msgid "Raw floating-point audio" +msgstr "Καθαρός floating-point ήχος" + +msgid "Audio CD source" +msgstr "Πηγή CD ήχου" + +msgid "DVD source" +msgstr "Πηγή DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Πηγή Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Πηγή πρωτοκόλλου Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Πηγή πρωτοκόλλου %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "RTP depayloader βίντεο %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "RTP depayloader ήχου %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP depayloader" + +#, c-format +msgid "%s demuxer" +msgstr "Αποπλέκτης %s" + +#, c-format +msgid "%s decoder" +msgstr "Αποκωδικοποιητής %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "RTP payloader βίντεο %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "RTP payloader ήχου %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP payloader" + +#, c-format +msgid "%s muxer" +msgstr "Πολυπλέκτης %s" + +#, c-format +msgid "%s encoder" +msgstr "Κωδικοποιητής %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Στοιχείο %s του GStreamer" + +msgid "Unknown source element" +msgstr "Άγνωστο στοιχείο πηγής" + +msgid "Unknown sink element" +msgstr "Άγνωστο στοιχείο απαγωγής" + +msgid "Unknown element" +msgstr "Άγνωστο στοιχείο" + +msgid "Unknown decoder element" +msgstr "Άγνωστο στοιχείο αποκωδικοποιητή" + +msgid "Unknown encoder element" +msgstr "Άγνωστο στοιχείο κωδικοποιητή" + +msgid "Plugin or element of unknown type" +msgstr "Πρόσθετη λειτουργία ή στοιχείο άγνωστου τύπου" + +msgid "No device specified." +msgstr "Δεν ορίσθηκε συσκευή." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Η συσκευή «%s» δεν υπάρχει." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Η συσκευή «%s» χρησιμοποιείται ήδη." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Αδυναμία ανοίγματος συσκευής «%s» για ανάγνωση και εγγραφή." diff --git a/gst-plugins-base-subtitles0.10/po/en_GB.po b/gst-plugins-base-subtitles0.10/po/en_GB.po new file mode 100644 index 0000000..470e344 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/en_GB.po @@ -0,0 +1,740 @@ +# English (British) translation. +# Copyright (C) 2004 Free Software Foundation, Inc. +# Gareth Owen , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins 0.8.1\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-04-26 10:41-0400\n" +"Last-Translator: Gareth Owen \n" +"Language-Team: English (British) \n" +"Language: en_GB\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "Bass" + +msgid "Treble" +msgstr "Treble" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Line-in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Microphone" + +#, fuzzy +msgid "PC Speaker" +msgstr "Speaker" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "Could not open CD device for reading." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "Could not open CD device for reading." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Could not open CD device for reading." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "Could not open audio device \"%s\" for writing." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "Could not open CD device for reading." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "Could not open CD device for reading." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Could not open CD device for reading." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "Could not open device \"%s\" for reading and writing." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "Could not open CD device for reading." + +msgid "Could not open CD device for reading." +msgstr "Could not open CD device for reading." + +#, fuzzy +msgid "Could not seek CD." +msgstr "Could not close vfs file \"%s\"." + +#, fuzzy +msgid "Could not read CD." +msgstr "Could not write to device \"%s\"." + +#, fuzzy, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Could not open vfs file \"%s\" for writing." + +msgid "No filename given" +msgstr "No filename given" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Could not close vfs file \"%s\"." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Error closing file \"%s\"." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "Could not write to file \"%s\"." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "Device \"%s\" is not a capture device." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Error closing file \"%s\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "No device specified." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Device \"%s\" does not exist." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "OSS device \"%s\" is already in use by another program." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Could not open device \"%s\" for reading and writing." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Could not write to file \"%s\"." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "No device specified." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Could not write to file \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Could not open file \"%s\" for reading." + +#~ msgid "Device is not open." +#~ msgstr "Device is not open." + +#~ msgid "Device is open." +#~ msgstr "Device is open." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "Could not open vfs file \"%s\" for reading." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "No filename given" + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "Could not open file \"%s\" for writing." + +#~ msgid "No filename specified." +#~ msgstr "No filename specified." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "No or invalid input audio, AVI stream will be corrupt." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "Could not open control device \"%s\" for writing." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "Could not configure audio device \"%s\"." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "Could not set audio device \"%s\" to %d Hz." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "Could not close audio device \"%s\"." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "Could not close control device \"%s\"." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "Could not open video device \"%s\" for writing." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "Could not close video device \"%s\"." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "Could not access device \"%s\", check its permissions." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "Could not open device \"%s\" for writing." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "Could not open device \"%s\" for reading." + +#, fuzzy +#~ msgid "Your OSS device doesn't support mono or stereo." +#~ msgstr "Your oss device could not be probed correctly" + +#, fuzzy +#~ msgid "Your OSS device could not be probed correctly" +#~ msgstr "Your oss device could not be probed correctly" + +#~ msgid "Volume" +#~ msgstr "Volume" + +#~ msgid "Speaker" +#~ msgstr "Speaker" + +#~ msgid "Mixer" +#~ msgstr "Mixer" + +#~ msgid "PCM-2" +#~ msgstr "PCM-2" + +#~ msgid "Record" +#~ msgstr "Record" + +#~ msgid "In-gain" +#~ msgstr "In-gain" + +#~ msgid "Out-gain" +#~ msgstr "Out-gain" + +#~ msgid "Line-1" +#~ msgstr "Line-1" + +#~ msgid "Line-2" +#~ msgstr "Line-2" + +#~ msgid "Line-3" +#~ msgstr "Line-3" + +#~ msgid "Digital-1" +#~ msgstr "Digital-1" + +#~ msgid "Digital-2" +#~ msgstr "Digital-2" + +#~ msgid "Digital-3" +#~ msgstr "Digital-3" + +#~ msgid "Phone-in" +#~ msgstr "Phone-in" + +#~ msgid "Phone-out" +#~ msgstr "Phone-out" + +#~ msgid "Video" +#~ msgstr "Video" + +#~ msgid "Radio" +#~ msgstr "Radio" + +#~ msgid "Monitor" +#~ msgstr "Monitor" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "Could not get buffers from device \"%s\"." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "Could not get enough buffers from device \"%s\"." diff --git a/gst-plugins-base-subtitles0.10/po/es.po b/gst-plugins-base-subtitles0.10/po/es.po new file mode 100644 index 0000000..2e261e8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/es.po @@ -0,0 +1,637 @@ +# translation of gst-plugins-base-0.10.30.3.po to Español +# spanish translation for gst-plugins-base +# This file is put in the public domain. +# Jorge González González , 2007, 2008, 2009, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-11-02 15:40+0100\n" +"Last-Translator: Jorge González González \n" +"Language-Team: Spanish \n" +"Language: es\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Maestro" + +msgid "Bass" +msgstr "Bajo" + +msgid "Treble" +msgstr "Agudos" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizador" + +msgid "Line-in" +msgstr "Línea de entrada" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Micrófono" + +msgid "PC Speaker" +msgstr "Altavoz del equipo" + +msgid "Playback" +msgstr "Reproducción" + +msgid "Capture" +msgstr "Capturar" + +msgid "Could not open device for playback in mono mode." +msgstr "No se pudo abrir el dispositivo para la reproducir en modo mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "No se pudo abrir el dispositivo para la reproducir en modo estéreo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "No se pudo abrir el dispositivo para reproducir en modo %d-canales." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"No se pudo abrir el dispositivo para la reproducir. Otra aplicación está " +"usando el dispositivo." + +msgid "Could not open audio device for playback." +msgstr "No se pudo abrir el dispositivo para la reproducir." + +msgid "Could not open device for recording in mono mode." +msgstr "No se pudo abrir el dispositivo para grabar en modo mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "No se pudo abrir el dispositivo para grabar en modo estéreo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "No se pudo abrir el dispositivo para grabar en modo %d-canales." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"No se pudo abrir el dispositivo de sonido para grabar. Otra aplicación está " +"usando el dispositivo." + +msgid "Could not open audio device for recording." +msgstr "No se pudo abrir el dispositivo de sonido para grabar." + +msgid "Could not open CD device for reading." +msgstr "No se pudo abrir el dispositivo de CD para leer." + +msgid "Could not seek CD." +msgstr "No se pudo buscar en el CD." + +msgid "Could not read CD." +msgstr "No se pudo leer del D." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "No se pudo abrir el archivo VFS «%s» para escribir: %s." + +msgid "No filename given" +msgstr "No se dio un nombre de archivo" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "No se pudo cerrar el archivo VFS «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Error al escribir al archivo «%s»." + +msgid "Internal data stream error." +msgstr "Error interno de flujo de datos." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Se requiere un complemento de %s para reproducir este medio, pero no está " +"instalado." + +msgid "This appears to be a text file" +msgstr "Esto parece ser un archivo de texto" + +msgid "Could not determine type of stream" +msgstr "No se pudo determinar el tipo de flujo" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI de subtítulos «%s» no válida, se desactivaron los subtítulos." + +msgid "No URI specified to play from." +msgstr "No se especificó una URI para reproducir." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "El URI «%s» no es válido." + +msgid "RTSP streams cannot be played yet." +msgstr "Aún no se pueden reproducir los medios RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "No se pudo crear el elemento «decodebin»." + +msgid "Source element is invalid." +msgstr "El elemento fuente no es válido." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Sólo se detecto un flujo de subtítulos. O bien está cargando un archivo de " +"subtítulos o algún otro tipo de archivo de texto o el archivo multimedia no " +"se pudo reconocer." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"No tiene un decodificador instalado para manejar este archivo. Debe instalar " +"los complementos necesarios." + +msgid "This is not a media file" +msgstr "Este no es un archivo multimedia" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Se detectó un flujo de subtítulos, pero no un flujo de vídeo." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Tanto el elemento autovideosink como xvimagesink faltan." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Falta el elemento «%s»; compruebe su instalación de GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Tanto el elemento autoaudiosink como alsasink faltan." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Tanto el elemento autovideosink como %s faltan." + +msgid "The autovideosink element is missing." +msgstr "Falta el elemento autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "El videosink configurado %s no está funcionando." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Tanto el elemento autovideosink como %s no están funcionando." + +msgid "The autovideosink element is not working." +msgstr "El elemento autovideosink no está funcionando." + +msgid "Custom text sink element is not usable." +msgstr "No se puede usar el elemento sumidero (sink) de texto personalizado." + +msgid "No volume control found" +msgstr "No se encontró ningún control de volumen" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Tanto el elemento autoaudiosink como %s faltan." + +msgid "The autoaudiosink element is missing." +msgstr "Falta el elemento autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "El audiosink configurado %s no está funcionando." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Tanto el elemento autoaudiosink como %s no están funcionando." + +msgid "The autoaudiosink element is not working." +msgstr "El elemento autoaudiosink no está funcionando." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"No se puede reproducir un archivo de texto sin vídeo o visualizaciones." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "No hay un decodificador disponible para el tipo «%s»." + +msgid "This stream type cannot be played yet." +msgstr "Este tipo de flujo no se puede reproducir aún." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "No existe un manejador URI implementado para «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Error al enviar los datos a «%s:%d»." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Error al enviar los datos de la cabecera gdp a «%s:%d»." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Error al enviar la carga de datos de gdp a «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Se rechazó la conexión con %s:%d." + +msgid "Can't record audio fast enough" +msgstr "No se puede grabar el sonido lo suficientemente rápido" + +msgid "Failed to read tag: not enough data" +msgstr "Falló al leer la etiqueta: no hay datos suficientes" + +msgid "track ID" +msgstr "ID de la pista" + +msgid "MusicBrainz track ID" +msgstr "ID de la pista en MusicBrainz" + +msgid "artist ID" +msgstr "ID del artista" + +msgid "MusicBrainz artist ID" +msgstr "ID del artista en MusicBrainz" + +msgid "album ID" +msgstr "ID del álbum" + +msgid "MusicBrainz album ID" +msgstr "ID del álbum en MusicBrainz" + +msgid "album artist ID" +msgstr "ID del álbum del artista" + +msgid "MusicBrainz album artist ID" +msgstr "ID del álbum del artista en MusicBrainz" + +msgid "track TRM ID" +msgstr "ID TRM de la pista" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM en MusicBrainz" + +msgid "capturing shutter speed" +msgstr "velocidad del obturador de la toma" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Velocidad del obturador usada al tomar una imagen, en segundos" + +msgid "capturing focal ratio" +msgstr "tasa focal de la toma" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Tasa focal (número-f) usada al tomar la imagen" + +msgid "capturing focal length" +msgstr "longitud focal de la toma" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Longitud focal de la lente usada al tomar la imagen, en mm" + +msgid "capturing digital zoom ratio" +msgstr "tasa de ampliación digital de la toma" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Tasa de ampliación digital usada al tomar una imagen" + +msgid "capturing iso speed" +msgstr "velocidad ISO de la toma" + +msgid "The ISO speed used when capturing an image" +msgstr "La velocidad de captura ISO usada al tomar una imagen" + +msgid "capturing exposure program" +msgstr "programa de exposición de la toma" + +msgid "The exposure program used when capturing an image" +msgstr "El programa de exposición usado al tomar una imagen" + +msgid "capturing exposure mode" +msgstr "modo de exposición de la toma" + +msgid "The exposure mode used when capturing an image" +msgstr "El modo de exposición usado al tomar una imagen" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "modo de exposición de la toma" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "El modo de exposición usado al tomar una imagen" + +msgid "capturing scene capture type" +msgstr "tipo de escena usado en la toma" + +msgid "The scene capture mode used when capturing an image" +msgstr "El modo de captura usado al tomar una imagen" + +msgid "capturing gain adjustment" +msgstr "ajuste de ganancia de la toma" + +msgid "The overall gain adjustment applied on an image" +msgstr "El ajuste general de ganancia aplicado en una imagen" + +msgid "capturing white balance" +msgstr "balance de blancos de la toma" + +msgid "The white balance mode set when capturing an image" +msgstr "El modo de balance de blancos usado al tomar una imagen" + +msgid "capturing contrast" +msgstr "contraste de la toma" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "La dirección de contraste procesada aplicada al tomar una imagen" + +msgid "capturing saturation" +msgstr "saturación de la toma" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "La dirección de saturación procesada aplicacada al tomar una imagen" + +msgid "capturing sharpness" +msgstr "nitidez de la toma" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "La dirección de nitidez procesada aplicada al tomar una imagen" + +msgid "capturing flash fired" +msgstr "disparo de flash de la toma" + +msgid "If the flash fired while capturing an image" +msgstr "Si el flash se disparó al capturar una imagen" + +msgid "capturing flash mode" +msgstr "modo de flash de la toma" + +msgid "The selected flash mode while capturing an image" +msgstr "El modo de flash seleccionado al tomar una imagen" + +msgid "capturing metering mode" +msgstr "modo de medición de la toma" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"El modo de medición usado al determinado la exposición al tomar una imagen" + +msgid "capturing source" +msgstr "fuente de la toma" + +msgid "The source or type of device used for the capture" +msgstr "El origen o tipo de dispositivo usado para la toma" + +msgid "image horizontal ppi" +msgstr "ppi horizontal de la imagen" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Densidad horizontal de píxeles, en ppi, del medio (imagen o vídeo)" + +msgid "image vertical ppi" +msgstr "ppi vertical de la imagen" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Densidad vertical de píxeles, en ppi, del medio (imagen o vídeo)" + +msgid "This CD has no audio tracks" +msgstr "Este CD no tiene pistas de sonido" + +msgid "ID3 tag" +msgstr "Etiqueta ID3" + +msgid "APE tag" +msgstr "Etiqueta APE" + +msgid "ICY internet radio" +msgstr "Emisora de internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV sin pérdida" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH sin pérdida" + +msgid "Uncompressed Gray Image" +msgstr "Imagen en escala de grises sin comprimir" + +msgid "Run-length encoding" +msgstr "Codificación del tamaño durante la ejecución" + +msgid "Sami subtitle format" +msgstr "Formato de subtítulos Sami" + +msgid "TMPlayer subtitle format" +msgstr "Formato de subtítulos TMPlayer" + +msgid "Kate subtitle format" +msgstr "Formato de subtítulos kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 plano sin comprimir" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YVU 4:2:0 plano sin comprimir" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 empaquetado sin comprimir" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 empaquetado sin comprimir" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU 4:1:0 empaquetado sin comprimir" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 empaquetado sin comprimir" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 empaquetado sin comprimir" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 plano sin comprimir" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 plano sin comprimir" + +msgid "Uncompressed black and white Y-plane" +msgstr "Plano Y en blanco y negro sin comprimir" + +msgid "Uncompressed YUV" +msgstr "YUV sin comprimir" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Paletizado sin comprimir de %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versión %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Audio PCM sin comprimir de %d-bits" + +msgid "Raw PCM audio" +msgstr "Audio PCM sin comprimir" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio sin comprimir de %d-bits en coma flotante" + +msgid "Raw floating-point audio" +msgstr "Audio sin comprimir en coma flotante" + +msgid "Audio CD source" +msgstr "Fuente: CD de audio" + +msgid "DVD source" +msgstr "Fuente: DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Fuente: Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Fuente: Protocolo Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Fuente: Protocolo %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "decodificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "decodificador de sonido RTP %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "decodificador RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "demultiplexor %s" + +#, c-format +msgid "%s decoder" +msgstr "decodificador %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "codificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "codificador de sonido RTP %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "codificador RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "multiplexor %s" + +#, c-format +msgid "%s encoder" +msgstr "codificador %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Elemento %s de GStreamer" + +msgid "Unknown source element" +msgstr "Fuente: Elemento desconocido" + +msgid "Unknown sink element" +msgstr "Elemento sumidero (sink) desconocido" + +msgid "Unknown element" +msgstr "Elemento desconocido" + +msgid "Unknown decoder element" +msgstr "Elemento decodificador desconocido" + +msgid "Unknown encoder element" +msgstr "Elemento codificador desconocido" + +msgid "Plugin or element of unknown type" +msgstr "Complemento o elemento de tipo desconocido" + +msgid "No device specified." +msgstr "No se especificó un dispositivo." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "El dispositivo «%s» no existe." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "El dispositivo «%s» ya se está usando." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "No se pudo abrir el dispositivo «%s» para su lectura y escritura." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "No se pueden mostrar a la vez subtítulos de texto y subimágenes." + +#~ msgid "No Temp directory specified." +#~ msgstr "No se especificó un directorio temporal." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "No se pudo cerrar el archivo temporal «%s»." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "No se pudo abrir el archivo «%s» para leer." + +#~ msgid "Internal data flow error." +#~ msgstr "Error en el flujo de datos interno." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "No se pudo crear el elemento «decodebin2»." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "No se pudo crear el elemento «queue2»." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "No se pudo crear el elemento «typefind»." + +#~ msgid "No file name specified." +#~ msgstr "No se especificó un nombre de archivo." diff --git a/gst-plugins-base-subtitles0.10/po/eu.po b/gst-plugins-base-subtitles0.10/po/eu.po new file mode 100644 index 0000000..1d57a1c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/eu.po @@ -0,0 +1,612 @@ +# translation of gst-plugins-base.master.po to Basque +# Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# +# Iñaki Larrañaga Murgoitio , 2009, 2010. +# Mikel Olasagasti Uranga , 2009, 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base-0.10.26.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-03-25 12:32+0100\n" +"Last-Translator: Mikel Olasagasti Uranga \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Maisua" + +msgid "Bass" +msgstr "Baxua" + +msgid "Treble" +msgstr "Altua" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizadorea" + +msgid "Line-in" +msgstr "Linea-sarrera" + +msgid "CD" +msgstr "CDa" + +msgid "Microphone" +msgstr "Mikrofonoa" + +msgid "PC Speaker" +msgstr "Ordenagailuko bozgorailua" + +msgid "Playback" +msgstr "Erreproduzitzea" + +msgid "Capture" +msgstr "Kapturatzea" + +msgid "Could not open device for playback in mono mode." +msgstr "Ezin izan da gailua ireki mono moduan erreproduzitzeko." + +msgid "Could not open device for playback in stereo mode." +msgstr "Ezin izan da gailua ireki estereo moduan erreproduzitzeko." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Ezin izan da gailua ireki %d kanaleko moduan erreproduzitzeko." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Ezin izan da audioaren gailua ireki erreproduzitzeko. Beste aplikazio batek " +"darabil gailua." + +msgid "Could not open audio device for playback." +msgstr "Ezin izan da audioaren gailua ireki erreproduzitzeko." + +msgid "Could not open device for recording in mono mode." +msgstr "Ezin izan da gailua ireki mono moduan grabatzeko." + +msgid "Could not open device for recording in stereo mode." +msgstr "Ezin izan da gailua ireki estereo moduan grabatzeko." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Ezin izan da gailua ireki %d kanaleko moduan grabatzeko." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Ezin izan da audioaren gailua ireki grabatzeko. Beste aplikazio batek " +"darabil gailua." + +msgid "Could not open audio device for recording." +msgstr "Ezin izan da audioaren gailua ireki grabatzeko." + +msgid "Could not open CD device for reading." +msgstr "Ezin izan da CD gailua ireki irakurtzeko." + +msgid "Could not seek CD." +msgstr "Ezin izan da CDan bilatu." + +msgid "Could not read CD." +msgstr "Ezin izan da CDa irakurri." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Ezin izan da \"%s\" vfs fitxategia ireki idazteko: %s." + +msgid "No filename given" +msgstr "Ez da fitxategi-izenik eman" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Ezin izan da itxi \"%s\" vfs fitxategia." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Errorea gertatu da \"%s\" fitxategian idaztean." + +msgid "Internal data stream error." +msgstr "Datu-korrontearen barne-errorea." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"%s plugina behar da korronte hori erreproduzitzeko, baina ez dago instalatua." + +msgid "This appears to be a text file" +msgstr "Testu-fitxategia dela dirudi" + +msgid "Could not determine type of stream" +msgstr "Ezin izan da korronte mota zehaztu" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" +"Azpitituluen \"%s\" URIa ez da baliozkoa. Azpitituluak desgaitu egin dira." + +msgid "No URI specified to play from." +msgstr "Ez da URIrik zehaztu irakurtzeko." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "\"%s\" URI baliogabea." + +msgid "RTSP streams cannot be played yet." +msgstr "Oraindik ezin dira erreproduzitu RTSP korronteak." + +msgid "Could not create \"decodebin\" element." +msgstr "Ezin izan da sortu \"decodebin\" elementua." + +msgid "Source element is invalid." +msgstr "Iturburuko elementua baliogabea da." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Azpitituluen korrontea soilik detektatu da. Azpitituluen fitxategi bat edo " +"beste testu-fitxategi bat ari zara kargatzen, edo multimedia-fitxategi hori " +"ez da onartzen." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Ez da instalatu fitxategi hori maneiatzeko deskodetzailerik Litekeena da " +"beharrezko pluginak instalatu behar izatea." + +msgid "This is not a media file" +msgstr "Hori ez da multimedia-fitxategi bat" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Azpitituluen korrontea detektatu da, baina ez bideoarena." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Autovideosink eta xvimagesink elementuak, biak, falta dira." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "'%s' elementua falta da. Begiratu GStreamer ondo instalatua dagoen." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Autoaudiosink eta alsasink elementuak, biak, falta dira." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Autovideosink eta %s elementuak, biak, falta dira." + +msgid "The autovideosink element is missing." +msgstr "Autovideosink elementua falta da." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Konfiguratutako %s videosink ez da lanean ari." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Autovideosink eta %s elementuak, biak, ez dira lanean ari." + +msgid "The autovideosink element is not working." +msgstr "Autovideosink elementua ez da lanean ari." + +msgid "Custom text sink element is not usable." +msgstr "Helburuko testu pertsonalizatua ez dago erabilgarri." + +msgid "No volume control found" +msgstr "Ez da bolumenaren kontrolik aurkitu" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Autoaudiosink eta %s elementuak, biak, falta dira." + +msgid "The autoaudiosink element is missing." +msgstr "Autoaudiosink falta da." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Konfiguratutako %s audiosink ez da lanean ari." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Autoaudiosink eta %s elementuak, biak, ez dira lanean ari." + +msgid "The autoaudiosink element is not working." +msgstr "Autoaudiosink elementua ez da lanean ari." + +#, fuzzy +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Ezin da bideo edo bisualizaziorik gabeko testu-fitxategi bat erreproduzitu." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Ez dago deskodetzaile erabilgarririk '%s' motarentzat." + +msgid "This stream type cannot be played yet." +msgstr "Oraindik ezin da erreproduzitu korronte mota hori." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Ez da URI maneiatzailerik ezarri \"%s\"(r)entzat." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Errorea gertatu da datuak \"%s:%d\"(e)ra bidaltzean." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Errorea gertatu da gdp goiburuaren datuak \"%s:%d\"(e)ra bidaltzean." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" +"Errorea gertatu da gdp karga erabilgarriaren datuak \"%s:%d\"(e)ra " +"bidaltzean." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "%s:%d(e)ra konektatzea ukatu da." + +msgid "Can't record audio fast enough" +msgstr "Ezin da behar bezain bizkor grabatu audioa" + +msgid "Failed to read tag: not enough data" +msgstr "Huts egin du etiketa irakurtzean: ez dago nahikoa daturik" + +msgid "track ID" +msgstr "pistaren IDa" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz pistaren IDa" + +msgid "artist ID" +msgstr "interpretearen IDa" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz interpretearen IDa" + +msgid "album ID" +msgstr "albumaren IDa" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz albumaren IDa" + +msgid "album artist ID" +msgstr "albumaren interpretearen IDa" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albumaren interpretearen IDa" + +msgid "track TRM ID" +msgstr "pistaren TRM IDa" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM IDa" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "CD honek ez du audio-pistarik" + +msgid "ID3 tag" +msgstr "ID3 etiketa" + +msgid "APE tag" +msgstr "APE etiketa" + +msgid "ICY internet radio" +msgstr "ICY interneteko irratia" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple-ren galerarik gabeko audioa (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Galerarik gabeko audio-kodek librea (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Galerarik gabeko True audioa (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "Galerarik gabeko CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg 1.b" + +msgid "Lossless MSZH" +msgstr "Galerarik gabeko MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Konprimitu gabeko irudi grisa" + +msgid "Run-length encoding" +msgstr "Run-length kodeketa" + +msgid "Sami subtitle format" +msgstr "Sami azpititulu-formatua" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer azpititulu-formatua" + +msgid "Kate subtitle format" +msgstr "'Kate' azpititulu-formatua" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Konprimitu gabeko YUV 4:2:0 planarra" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Konprimitu gabeko YVU 4:2:0 planarra" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Konprimitu gabeko YUV 4:2:2 paketatua" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Konprimitu gabeko YUV 4:1:0 paketatua" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Konprimitu gabeko YVU 4:1:0 paketatua" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Konprimitu gabeko YUV 4:1:1 paketatua" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Konprimitu gabeko YUV 4:4:4 paketatua" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Konprimitu gabeko YUV 4:2:2 planarra" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Konprimitu gabeko YUV 4:1:1 planarra" + +msgid "Uncompressed black and white Y-plane" +msgstr "Konprimitu gabeko zuri-beltzeko Y-planoa" + +msgid "Uncompressed YUV" +msgstr "Konprimitu gabeko YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Konprimitu gabeko paleta moduko %d biteko %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 %d. bertsioa" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "%d biteko prozesatu gabeko PCM audioa" + +msgid "Raw PCM audio" +msgstr "Prozesatu gabeko PCM audioa" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Koma mugikorreko %d biteko prozesatu gabeko PCM audioa" + +msgid "Raw floating-point audio" +msgstr "Koma mugikorreko prozesatu gabeko audioa" + +msgid "Audio CD source" +msgstr "Audio CDaren iturburua" + +msgid "DVD source" +msgstr "DVD iturburua" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Denbora errealeko transmisio-protokoloaren (RTSP) iturburua" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) protokoloaren iturburua" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokolo-ituruburua" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s bideoaren RTP depayloader-a" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audiooaren RTP depayloader-a" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP depayloader-a" + +#, c-format +msgid "%s demuxer" +msgstr "%s demultiplexadorea" + +#, c-format +msgid "%s decoder" +msgstr "%s deskodetzailea" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s bideoaren RTP payloader-a" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audiooaren RTP payloader-a" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP payloader-a" + +#, c-format +msgid "%s muxer" +msgstr "%s multiplexadorea" + +#, c-format +msgid "%s encoder" +msgstr "%s kodetzailea" + +#, c-format +msgid "GStreamer element %s" +msgstr "%s GStreamer elementua" + +msgid "Unknown source element" +msgstr "Iturburu-elementu ezezaguna" + +msgid "Unknown sink element" +msgstr "Kolektore-elementu ezezaguna" + +msgid "Unknown element" +msgstr "Elementu ezezaguna" + +msgid "Unknown decoder element" +msgstr "Deskodetzailearen elementu ezezaguna" + +msgid "Unknown encoder element" +msgstr "Kodetzailearen elementu ezezaguna" + +msgid "Plugin or element of unknown type" +msgstr "Mota ezezaguneko plugina edo elementua" + +msgid "No device specified." +msgstr "Ez da gailurik zehaztu." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "\"%s\" gailua ez dago." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "\"%s\" gailua erabiltzen ari dira." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Ezin izan da \"%s\" gailua ireki irakurtzeko eta idazteko." diff --git a/gst-plugins-base-subtitles0.10/po/fi.po b/gst-plugins-base-subtitles0.10/po/fi.po new file mode 100644 index 0000000..4dade98 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/fi.po @@ -0,0 +1,643 @@ +# Finnish messages for gst-plugins-base. +# +# This file is distributed under the same license as the gst-plugins-base package. +# Copyright (C) 2008-2010 Tommi Vainikainen, +# Copyright (C) 2007 Ilkka Tuohela. +# +# Tommi Vainikainen , 2008-2010. +# Ilkka Tuohela , 2007. +# +# Suomennos: http://gnome.fi/ +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-12-31 23:21+0200\n" +"Last-Translator: Tommi Vainikainen \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Pääkanava" + +msgid "Bass" +msgstr "Basso" + +msgid "Treble" +msgstr "Ylä-äänet" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Linjatulo" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofoni" + +msgid "PC Speaker" +msgstr "PC-kaiutin" + +msgid "Playback" +msgstr "Toisto" + +msgid "Capture" +msgstr "Nauhoitus" + +msgid "Could not open device for playback in mono mode." +msgstr "Laitetta ei voitu avata toistoa varten monona." + +msgid "Could not open device for playback in stereo mode." +msgstr "Laitetta ei voitu avata toistoa varten stereona." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Laitetta ei voitu avata toistoa varten %d-kanavaisessa tilassa." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Laitetta ei voitu avata toistoa varten. Laitetta käyttää toinen sovellus." + +msgid "Could not open audio device for playback." +msgstr "Laitetta ei voitu avata toistoa varten." + +msgid "Could not open device for recording in mono mode." +msgstr "Laitetta ei voitu avata nauhoitusta varten monona." + +msgid "Could not open device for recording in stereo mode." +msgstr "Laitetta ei voitu avata nauhoitusta varten stereona." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Laitetta ei voitu avata nauhoitusta varten %d-kanavaisessa tilassa." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Äänilaitetta ei voitu avata nauhoitusta varten. Laitetta käyttää toinen " +"sovellus." + +msgid "Could not open audio device for recording." +msgstr "Äänilaitetta ei voitu avat nauhoitusta varten." + +msgid "Could not open CD device for reading." +msgstr "CD-laitetta ei voitu avata luettavaksi." + +msgid "Could not seek CD." +msgstr "CD-levyllä ei voitu siirtyä." + +msgid "Could not read CD." +msgstr "CD-levyä ei voitu lukea." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "VFS-tiedostoa \"%s\" ei voi avata kirjoitettavaksi: %s." + +msgid "No filename given" +msgstr "Tiedostonimeä ei annettu" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "VFS-tiedostoa \"%s\" ei voitu sulkea." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Virhe kirjoitettaessa tiedostoon \"%s\"." + +msgid "Internal data stream error." +msgstr "Sisäisen tietovirran virhe." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Virran toistamiseen tarvitaan %s-liitännäinen, mutta se ei ole asennettu." + +msgid "This appears to be a text file" +msgstr "Tämä näyttää olevan tekstitiedosto" + +msgid "Could not determine type of stream" +msgstr "Virran tyyppiä ei voitu määrittää" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Virheellinen tekstitysten URI \"%s\", tekstitys ei ole käytössä." + +msgid "No URI specified to play from." +msgstr "URIa, josta soitetaan, ei annettu." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Virheellinen URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP-virtoja ei voi vielä soittaa." + +msgid "Could not create \"decodebin\" element." +msgstr "Elementtiä \"decodebin\" ei voitu luoda." + +msgid "Source element is invalid." +msgstr "Lähde-elementti on virheellinen." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Havaittiin vain tekstitysvirta. Joko yrität ladata tekstitystiedostoa tai " +"muuta tekstitiedostoa, tai mediatiedostoa ei voitu tunnistaa." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Tämän tiedoston käsittelyyn ei ole asennettu purkajaa. Voi olla, että sinun " +"täytyy asentaa tarvittavia liitännäisiä." + +msgid "This is not a media file" +msgstr "Tämä ei ole mediatiedosto" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Havaittiin tekstitysvirta, mutta ei videovirtaa." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Sekä autovideosink- ja xvimagesink-elementit puuttuvat." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Puuttuva elementti \"%s\" - tarkista GStreamer-asennuksesi." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Sekä autoaudiosink- että alsasink-elementit puuttuvat." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Sekä autovideosink- ja %s-elementit puuttuvat." + +msgid "The autovideosink element is missing." +msgstr "Autovideosink-elementti puuttuu." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Asetettu videonielu %s ei toimi." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Sekä autovideosink- ja %s-elementit eivät toimi." + +msgid "The autovideosink element is not working." +msgstr "Autovideosink-elementti ei toimi." + +msgid "Custom text sink element is not usable." +msgstr "Räätälöity tekstinieluelementti ei ole käyttökunnossa." + +msgid "No volume control found" +msgstr "Äänenvoimakkuuden hallintaa ei löytynyt" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Sekä autoaudiosink- että %s-elementit puuttuvat." + +msgid "The autoaudiosink element is missing." +msgstr "Autoaudiosink-elementti puuttuu." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Asetettu ääninielu %s ei toimi." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Sekä autoaudiosink- että %s-elementit eivät toimi." + +msgid "The autoaudiosink element is not working." +msgstr "Autoaudiosink-elementti ei toimi." + +msgid "Can't play a text file without video or visualizations." +msgstr "Ei voida toistaa tekstitiedosta ilman videota tai visualisointia." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Purkajaa tyypille \"%s\" ei ole saatavilla." + +msgid "This stream type cannot be played yet." +msgstr "Tätä virtatyyppiä ei voi vielä soittaa." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Protokollalle \"%s\" ei ole määritelty URI-käsittelijää." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Virhe lähetettäessä tietoa kohteeseen \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Virhe lähetettäessä gdp-otsaketietoja kohteeseen \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Virhe lähetettäessä gdp-sisältöä kohteeseen \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Yhteys kohteeseen %s:%d estettiin." + +msgid "Can't record audio fast enough" +msgstr "Ääntä ei voi nauhoittaa tarpeeksi nopeasti" + +msgid "Failed to read tag: not enough data" +msgstr "Tagin lukeminen epäonnistui: ei riittävästi dataa" + +msgid "track ID" +msgstr "kappaletunniste" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz-kappaletunniste" + +msgid "artist ID" +msgstr "esittäjätunniste" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz-esittäjätunniste" + +msgid "album ID" +msgstr "levytunniste" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz-levytunniste" + +msgid "album artist ID" +msgstr "levyn esittäjätunniste" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz levyn esittäjätunniste" + +msgid "track TRM ID" +msgstr "kappaleen TRM-tunniste" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM-tunniste" + +msgid "capturing shutter speed" +msgstr "kuvaamisen suljinnopeus" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Suljinnopeus kuvattaessa, sekunteina" + +msgid "capturing focal ratio" +msgstr "kuvaamisen aukkosuhde" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Aukkosuhde (f-luku) kuvattaessa" + +msgid "capturing focal length" +msgstr "kuvaamisen polttoväli" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Linssin polttoväli kuvattaessa, millimetriä" + +msgid "capturing digital zoom ratio" +msgstr "kuvaamisen digitaalinen zoomaus" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Digitaalinen suurennuskerroin kuvattaessa" + +msgid "capturing iso speed" +msgstr "kuvaamisen ISO-nopeus" + +msgid "The ISO speed used when capturing an image" +msgstr "ISO-nopeus kuvattaessa" + +msgid "capturing exposure program" +msgstr "kuvaamisen valotusohjelma" + +msgid "The exposure program used when capturing an image" +msgstr "Valotusohjelma kuvattaessa" + +msgid "capturing exposure mode" +msgstr "kuvaamisen valotustapa" + +msgid "The exposure mode used when capturing an image" +msgstr "Valotustapa kuvattaessa" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "kuvaamisen valotustapa" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "Valotustapa kuvattaessa" + +msgid "capturing scene capture type" +msgstr "kuvaamisen kuvausmoodi" + +msgid "The scene capture mode used when capturing an image" +msgstr "Kuvausmoodi kuvattaessa" + +msgid "capturing gain adjustment" +msgstr "kuvaamisen kirkkauskorjaus" + +msgid "The overall gain adjustment applied on an image" +msgstr "Yleinen kirkkauskorjaus, joka kuvalle on tehty" + +msgid "capturing white balance" +msgstr "kuvaamisen valkotasapaino" + +msgid "The white balance mode set when capturing an image" +msgstr "Valittu valkotasapainotila kuvattaessa" + +msgid "capturing contrast" +msgstr "kuvaamisen kontrasti" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Käytetty kontrastikäsittelyn suunta kuvattessa" + +msgid "capturing saturation" +msgstr "kuvaamisen saturaatio" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Käytetty saturaatiokäsittelyn suunta kuvattessa" + +msgid "capturing sharpness" +msgstr "kuvaamisen terävyys" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Käytetty terävyyskäsittelyn suunta kuvattessa" + +msgid "capturing flash fired" +msgstr "kuvaamisen salamankäyttö" + +msgid "If the flash fired while capturing an image" +msgstr "Syttyikö salama kuvattaessa" + +msgid "capturing flash mode" +msgstr "kuvaamisen salamamoodi" + +msgid "The selected flash mode while capturing an image" +msgstr "Valittu salamamoodi kuvattessa" + +msgid "capturing metering mode" +msgstr "kuvaamisen mittausmoodi" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Käytetty mittausmoodi päätettäessä valotusta kuvattaessa" + +msgid "capturing source" +msgstr "kuvaamisen lähde" + +msgid "The source or type of device used for the capture" +msgstr "Lähde tai laitetyyppi kuvattaessa" + +msgid "image horizontal ppi" +msgstr "kuvan vaakasuora ppi" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Median (kuva tai video) tarkoitettu vaakasuora pikselitiheys ppi:nä" + +msgid "image vertical ppi" +msgstr "kuvan pystysuora ppi" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Median (kuva tai video) tarkoitettu pystysuora pikselitiheys ppi:nä" + +msgid "This CD has no audio tracks" +msgstr "Tällä CD-levyllä ei ole ääniraitoja" + +msgid "ID3 tag" +msgstr "ID3-tagi" + +msgid "APE tag" +msgstr "APE-tagi" + +msgid "ICY internet radio" +msgstr "ICY-Internet-radio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows-media (puhe)" + +msgid "CYUV Lossless" +msgstr "Häviötön CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Häviötön MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Pakkaamaton harmaakuva" + +msgid "Run-length encoding" +msgstr "RLE-koodaus" + +msgid "Sami subtitle format" +msgstr "Sami-tekstitysmuoto" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer-tekstitysmuoto" + +msgid "Kate subtitle format" +msgstr "Kate-tekstitysmuoto" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Pakkaamaton tasollinen YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Pakkaamaton tasollinen YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Pakkaamaton paketoitu YUV 4:2:0" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Pakkaamaton paketoitu YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Pakkaamaton paketoitu YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Pakkaamaton paketoitu YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Pakkaamaton paketoitu YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Pakkaamaton tasollinen YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Pakkaamaton tasollinen YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Pakkaamaton mustavalkoinen Y-taso" + +msgid "Uncompressed YUV" +msgstr "Pakkaamaton YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Pakkaamaton paletillinen %d-bittinen %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versio %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Raaka %d-bittinen pcm-ääni" + +msgid "Raw PCM audio" +msgstr "Raaka pcm-ääni" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Raaka %d-bittinen liukulukupohjainen ääni" + +msgid "Raw floating-point audio" +msgstr "Raaka liukulukupohjainen ääni" + +msgid "Audio CD source" +msgstr "Ääni-CD-lähde" + +msgid "DVD source" +msgstr "DVD-lähde" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol (RTSP) -lähde" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) -protokollalähde" + +#, c-format +msgid "%s protocol source" +msgstr "%s-protokollalähde" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s-video-RTP-purkaja" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s-ääni-RTP-purkaja" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s-RTP-purkaja" + +#, c-format +msgid "%s demuxer" +msgstr "%s-demukseri" + +#, c-format +msgid "%s decoder" +msgstr "%s-purkaja" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s-video-RTP-pakkain" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s-ääni-RTP-pakkain" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s-RTP-pakkain" + +#, c-format +msgid "%s muxer" +msgstr "%s-mukseri" + +#, c-format +msgid "%s encoder" +msgstr "%s-pakkain" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer-elementti %s" + +msgid "Unknown source element" +msgstr "Tuntematon lähde-elementti" + +msgid "Unknown sink element" +msgstr "Tuntematon nieluelementti" + +msgid "Unknown element" +msgstr "Tuntematon elementti" + +msgid "Unknown decoder element" +msgstr "Tuntematon purkajaelementti" + +msgid "Unknown encoder element" +msgstr "Tuntematon kodekkielementti" + +msgid "Plugin or element of unknown type" +msgstr "Liitännäisen tai elementin tyyppi on tuntematon" + +msgid "No device specified." +msgstr "Laitetta ei ole määritelty." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Laitetta \"%s\" ei ole olemassa." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Laite \"%s\" on jo käytössä." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Laitetta \"%s\" ei voi avata luettavaksi ja kirjoitettavaksi." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Ei voida toistaa sekä tekstitystä että alikuvaa." + +#~ msgid "No Temp directory specified." +#~ msgstr "Tilapäishakemistoa ei ole määritelty." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Tilapäistiedostoa ”%s” ei voitu luoda." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Tiedostoa \"%s\" ei voi avata luettavaksi." + +#~ msgid "Internal data flow error." +#~ msgstr "Sisäisen tietovirran virhe." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Elementtiä \"decodebin2\" ei voitu luoda." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Elementtiä \"queue2\" ei voitu luoda." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Elementtiä \"typefind\" ei voitu luoda." + +#~ msgid "No file name specified." +#~ msgstr "Tiedostonimeä ei annettu." + +#~ msgid "artist sortname" +#~ msgstr "esittäjän järjestysnimi" + +#~ msgid "MusicBrainz artist sortname" +#~ msgstr "MusicBrainz esittäjän järjestysnimi" diff --git a/gst-plugins-base-subtitles0.10/po/fr.po b/gst-plugins-base-subtitles0.10/po/fr.po new file mode 100644 index 0000000..ed86034 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/fr.po @@ -0,0 +1,627 @@ +# Translation of gst-plugins-base to French +# Copyright (C) 2003-2011 GStreamer core team +# This file is distributed under the same license as the gst-plugins-base package. +# +# Nicolas Velin , 2008. +# Claude Paroz , 2008-2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-30 17:11+0100\n" +"PO-Revision-Date: 2011-04-28 09:19+0200\n" +"Last-Translator: Claude Paroz \n" +"Language-Team: French \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n>1;\n" + +msgid "Master" +msgstr "Volume général" + +msgid "Bass" +msgstr "Basses" + +msgid "Treble" +msgstr "Aiguës" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Entrée ligne" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Micro" + +msgid "PC Speaker" +msgstr "Haut-parleur PC" + +msgid "Playback" +msgstr "Lecture" + +msgid "Capture" +msgstr "Enregistrement" + +msgid "Could not open device for playback in mono mode." +msgstr "Impossible d'utiliser le périphérique pour la lecture en mode mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Impossible d'utiliser le périphérique pour la lecture en mode stéréo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "" +"Impossible d'utiliser le périphérique pour la lecture en mode %d canaux." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Impossible d'utiliser le périphérique audio pour la lecture. Celui-ci est " +"occupé par une autre application." + +msgid "Could not open audio device for playback." +msgstr "Impossible d'utiliser le périphérique audio pour la lecture." + +msgid "Could not open device for recording in mono mode." +msgstr "" +"Impossible d'utiliser le périphérique pour l'enregistrement en mode mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "" +"Impossible d'utiliser le périphérique pour l'enregistrement en mode stéréo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "" +"Impossible d'utiliser le périphérique pour l'enregistrement en mode %d " +"canaux." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Impossible d'utiliser le périphérique audio pour l'enregistrement. Celui-ci " +"est occupé par une autre application." + +msgid "Could not open audio device for recording." +msgstr "Impossible d'utiliser le périphérique audio pour l'enregistrement." + +msgid "Could not open CD device for reading." +msgstr "Impossible d'utiliser le lecteur CD pour la lecture." + +msgid "Could not seek CD." +msgstr "Impossible de se positionner sur le CD." + +msgid "Could not read CD." +msgstr "Impossible de lire le CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Impossible d'ouvrir le fichier vfs « %s » en écriture : %s." + +msgid "No filename given" +msgstr "Aucun nom de fichier indiqué" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Impossible de fermer le fichier vfs « %s »." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Erreur lors de l'écriture dans le fichier « %s »." + +msgid "Internal data stream error." +msgstr "Erreur interne de flux de données." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Un greffon %s est requis pour lire ce flux, mais il n'est pas installé." + +msgid "This appears to be a text file" +msgstr "Ce fichier semble être un fichier texte" + +msgid "Could not determine type of stream" +msgstr "Impossible de déterminer le type de flux" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI de sous-titres « %s » non valide, les sous-titres sont désactivés." + +msgid "No URI specified to play from." +msgstr "Aucun URI source indiqué pour la lecture." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "URI « %s » non valide." + +msgid "RTSP streams cannot be played yet." +msgstr "Il n'est pas encore possible de lire les flux RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "Impossible de créer un élément « decodebin »." + +msgid "Source element is invalid." +msgstr "Élément source non valide." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Seul un flux de sous-titres a été détecté. Soit vous essayez d'ouvrir un " +"fichier de sous-titres ou un autre type de fichier texte, soit le fichier " +"multimédia n'a pas été reconnu." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Aucun décodeur n'est installé pour gérer ce fichier. Vous devriez " +"probablement installer des greffons supplémentaires." + +msgid "This is not a media file" +msgstr "Ceci n'est pas un fichier multimédia" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Un flux de sous-titres a été détecté, mais pas de flux vidéo." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Les éléments autovideosink et xvimagesink sont tous deux manquants." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Élément « %s » manquant, contrôlez votre installation de GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Les éléments autoaudiosink et alsasink sont tous deux manquants." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Les éléments autovideosink et %s sont tous deux manquants." + +msgid "The autovideosink element is missing." +msgstr "L'élément autovideosink est manquant." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "L'élément videosink configuré %s ne fonctionne pas." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Les éléments autovideosink et %s ne fonctionnent pas." + +msgid "The autovideosink element is not working." +msgstr "L'élément autovideosink ne fonctionne pas." + +msgid "Custom text sink element is not usable." +msgstr "L'élément sink text personnalisé n'est pas utilisable." + +msgid "No volume control found" +msgstr "Aucun contrôle de volume trouvé" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Les éléments autoaudiosink et %s sont tous deux manquants." + +msgid "The autoaudiosink element is missing." +msgstr "L'élément autoaudiosink est manquant." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "L'élément autoaudiosink configuré %s ne fonctionne pas." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Les éléments autoaudiosink et %s ne fonctionnent pas." + +msgid "The autoaudiosink element is not working." +msgstr "L'élément autoaudiosink ne fonctionne pas." + +msgid "Can't play a text file without video or visualizations." +msgstr "Impossible de lire un fichier texte sans vidéo ou visualisation." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Aucun décodeur n'est disponible pour le type « %s »." + +msgid "This stream type cannot be played yet." +msgstr "Ce type de flux ne peut pas encore être lu." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Aucun gestionnaire d'URI implémenté pour « %s »." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Erreur lors de l'envoi de données vers « %s:%d »." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Erreur lors de l'envoi de données d'en-tête gdp vers « %s:%d »." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Erreur lors de l'envoi de données de charge utile gdp vers « %s:%d »." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Connexion refusée vers %s:%d." + +msgid "Can't record audio fast enough" +msgstr "Impossible d'enregistrer assez rapidement les données audio" + +msgid "Failed to read tag: not enough data" +msgstr "Échec de lecture de l'étiquette : données insuffisantes" + +msgid "track ID" +msgstr "identifiant de piste" + +msgid "MusicBrainz track ID" +msgstr "identifiant de piste MusicBrainz" + +msgid "artist ID" +msgstr "identifiant d'artiste" + +msgid "MusicBrainz artist ID" +msgstr "identifiant d'artiste MusicBrainz" + +msgid "album ID" +msgstr "identifiant d'album" + +msgid "MusicBrainz album ID" +msgstr "identifiant d'album MusicBrainz" + +msgid "album artist ID" +msgstr "identifiant d'artiste de l'album" + +msgid "MusicBrainz album artist ID" +msgstr "identifiant d'artiste de l'album MusicBrainz" + +msgid "track TRM ID" +msgstr "identifiant TRM de piste" + +msgid "MusicBrainz TRM ID" +msgstr "identifiant TRM MusicBrainz" + +msgid "capturing shutter speed" +msgstr "vitesse d'obturation de la capture" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" +"Vitesse d'obturation utilisée lors de la capture de l'image, en secondes" + +# http://www.blog-couleur.com/?Qu-est-ce-que-l-ouverture-en +msgid "capturing focal ratio" +msgstr "ouverture absolue de la capture" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Ouverture absolue (nombre f) utilisée lors de la capture de l'image" + +msgid "capturing focal length" +msgstr "distance focale de la capture" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" +"Distance focale de l'optique utilisée pour la capture de l'image, en mm" + +msgid "capturing digital zoom ratio" +msgstr "valeur du zoom numérique de la capture" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Valeur du zoom numérique utilisé lors de la capture de l'image" + +msgid "capturing iso speed" +msgstr "sensibilité iso de la capture" + +msgid "The ISO speed used when capturing an image" +msgstr "La sensibilité ISO utilisée lors de la capture de l'image" + +msgid "capturing exposure program" +msgstr "programme d'exposition de la capture" + +msgid "The exposure program used when capturing an image" +msgstr "Le programme d'exposition utilisé lors de la capture de l'image" + +msgid "capturing exposure mode" +msgstr "mode d'exposition de la capture" + +msgid "The exposure mode used when capturing an image" +msgstr "Le mode d'exposition utilisé lors de la capture de l'image" + +msgid "capturing exposure compensation" +msgstr "compensation d'exposition de la capture" + +msgid "The exposure compensation used when capturing an image" +msgstr "La compensation d'exposition utilisée lors de la capture de l'image" + +msgid "capturing scene capture type" +msgstr "type de mode scène de la capture" + +msgid "The scene capture mode used when capturing an image" +msgstr "Le mode scène utilisé lors de la capture de l'image" + +msgid "capturing gain adjustment" +msgstr "ajustement de gain de la capture" + +msgid "The overall gain adjustment applied on an image" +msgstr "L'ajustement général de gain appliqué à une image" + +msgid "capturing white balance" +msgstr "balance des blancs de la capture" + +msgid "The white balance mode set when capturing an image" +msgstr "Le mode de balance des blancs défini lors de la capture d'une image" + +msgid "capturing contrast" +msgstr "contraste de la capture" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" +"La direction du traitement de contraste appliqué lors de la capture d'une " +"image" + +msgid "capturing saturation" +msgstr "saturation de la capture" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"La direction du traitement de saturation appliqué lors de la capture d'une " +"image" + +msgid "capturing sharpness" +msgstr "netteté de la capture" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" +"La direction du traitement de netteté appliqué lors de la capture d'une image" + +msgid "capturing flash fired" +msgstr "flash utilisé pour la capture" + +msgid "If the flash fired while capturing an image" +msgstr "Indique si le flash a été utilisé pour capturer une image" + +msgid "capturing flash mode" +msgstr "mode de flash de la capture" + +msgid "The selected flash mode while capturing an image" +msgstr "Le mode de flash sélectionné lors de la capture d'une image" + +msgid "capturing metering mode" +msgstr "mode de msure de la capture" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Le mode de mesure utilisé lors de l'évaluation de l'exposition pour la " +"capture d'une image" + +msgid "capturing source" +msgstr "source de capture" + +msgid "The source or type of device used for the capture" +msgstr "La source ou le type d'appareil utilisé pour la capture" + +msgid "image horizontal ppi" +msgstr "ppp horizontal de l'image" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Densité de pixels horizontale annoncée par le média (image/vidéo), en points " +"par pouce" + +msgid "image vertical ppi" +msgstr "ppp vertical de l'image" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Densité de pixels verticale annoncée par le média (image/vidéo), en points " +"par pouce" + +msgid "This CD has no audio tracks" +msgstr "Ce CD ne contient aucune piste audio" + +msgid "ID3 tag" +msgstr "Étiquette ID3" + +msgid "APE tag" +msgstr "Étiquette APE" + +msgid "ICY internet radio" +msgstr "Radio Internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "ALAC (Apple Lossless Audio)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "FLAC (Free Lossless Audio Codec)" + +msgid "Lossless True Audio (TTA)" +msgstr "TTA (Lossless True Audio)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV sans perte" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH sans perte" + +msgid "Uncompressed Gray Image" +msgstr "Image niveaux de gris non compressée" + +# http://fr.wikipedia.org/wiki/Run-length_encoding +msgid "Run-length encoding" +msgstr "Codage par plages" + +msgid "Sami subtitle format" +msgstr "Format de sous-titres Sami" + +msgid "TMPlayer subtitle format" +msgstr "Format de sous-titres TMPlayer" + +msgid "Kate subtitle format" +msgstr "Format de sous-titres Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV planaire 4:2:0 non compressé" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YVU planaire 4:2:0 non compressé" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV empaqueté 4:2:2 non compressé" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV empaqueté 4:1:0 non compressé" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU empaqueté 4:1:0 non compressé" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV empaqueté 4:1:1 non compressé" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV empaqueté 4:4:4 non compressé" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV planaire 4:2:2 non compressé" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV planaire 4:1:1 non compressé" + +msgid "Uncompressed black and white Y-plane" +msgstr "Plan Y noir et blanc non compressé" + +msgid "Uncompressed YUV" +msgstr "YUV non compressé" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "%2$s %1$d bits en palette non compressé" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "MPEG-4 DivX version %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Audio PCM brut %d bits" + +msgid "Raw PCM audio" +msgstr "Audio PCM brut" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio brut virgule flottante %d bits" + +msgid "Raw floating-point audio" +msgstr "Audio brut virgule flottante" + +msgid "Audio CD source" +msgstr "Source CD audio" + +msgid "DVD source" +msgstr "Source DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Source RTSP (Real Time Streaming Protocol)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Source protocole MMS (Microsoft Media Server)" + +#, c-format +msgid "%s protocol source" +msgstr "Source protocole %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Depayloader RTP vidéo %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Depayloader RTP audio %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Depayloader RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Démultiplexeur %s" + +#, c-format +msgid "%s decoder" +msgstr "Décodeur %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Payloader RTP vidéo %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Payloader RTP audio %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "Payloader RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Multiplexeur %s" + +#, c-format +msgid "%s encoder" +msgstr "Codeur %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Élément GStreamer %s" + +msgid "Unknown source element" +msgstr "Élément source inconnu" + +msgid "Unknown sink element" +msgstr "Élément d'entrée inconnu" + +msgid "Unknown element" +msgstr "Élément inconnu" + +msgid "Unknown decoder element" +msgstr "Élément décodeur inconnu" + +msgid "Unknown encoder element" +msgstr "Élément codeur inconnu" + +msgid "Plugin or element of unknown type" +msgstr "Greffon ou élément de type inconnu" + +msgid "No device specified." +msgstr "Aucun périphérique indiqué." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Le périphérique « %s » n'existe pas." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Le périphérique « %s » est déjà en cours d'utilisation." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Impossible d'ouvrir le périphérique « %s » en lecture et écriture." diff --git a/gst-plugins-base-subtitles0.10/po/gl.po b/gst-plugins-base-subtitles0.10/po/gl.po new file mode 100644 index 0000000..a75661f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/gl.po @@ -0,0 +1,612 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) 2010 Fran Dieguez +# This file is distributed under the same license as the gst-plugins-base package. +# Fran Diéguez , 2010, 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.31.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2011-01-09 21:20+0100\n" +"Last-Translator: Fran Diéguez \n" +"Language-Team: Galician \n" +"Language: gl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n!=1);\n" +"X-Poedit-Language: galego\n" + +msgid "Master" +msgstr "Mestre" + +msgid "Bass" +msgstr "Graves" + +msgid "Treble" +msgstr "Agudos" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizador" + +msgid "Line-in" +msgstr "Liña de entrada" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Micrófono" + +msgid "PC Speaker" +msgstr "Altofalante do PC" + +msgid "Playback" +msgstr "Reproducir" + +msgid "Capture" +msgstr "Capturar" + +msgid "Could not open device for playback in mono mode." +msgstr "Non foi posíbel abrir o dispositivo para a reprodución en modo mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "" +"Non foi posíbel abrir o dispositivo para a reprodución en modo estéreo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Non foi posíbel abrir o dispositivo para reproducir no modo %d-canles." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Non foi posíbel abrir o dispositivo de son para reproducir. Outro aplicativo " +"está usado o dispositivo." + +msgid "Could not open audio device for playback." +msgstr "Non foi posíbel abrir o dispositivo de son para reproducir." + +msgid "Could not open device for recording in mono mode." +msgstr "Non foi posíbel abrir o dispositivo para gravar en modo mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Non foi posíbel abrir o dispositivo para gravar en modo estéreo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Non foi posíbel abrir o dispositivo para gravar en modo %d-canles." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Non foi posíbel abrir o dispositivo de son para gravar. Outro aplicativo " +"está usando o dispositivo." + +msgid "Could not open audio device for recording." +msgstr "Non foi posíbel abrir o dispositivo de son para gravar." + +msgid "Could not open CD device for reading." +msgstr "Non foi posíbel abrir o dispositivo de CD para ler." + +msgid "Could not seek CD." +msgstr "Non foi posíbel buscar no CD." + +msgid "Could not read CD." +msgstr "Non foi posíbel ler o CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Non foi posíbel abrir o ficheiro vfs «%s» para escribir: %s." + +msgid "No filename given" +msgstr "Non se forneceu un nome de ficheiro" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Non foi posíbel pechar o ficheiro vfs «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Produciuse un erro ao escribir no ficheiro «%s»." + +msgid "Internal data stream error." +msgstr "Produciuse un erro no fluxo de datos internos." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Precísase un engadido %s que non está instalado para reproducir este fluxo." + +msgid "This appears to be a text file" +msgstr "Isto parece ser un ficheiro de texto" + +msgid "Could not determine type of stream" +msgstr "Non foi posíbel determinar o tipo de fluxo." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "O URI dos subtítulos «%s» é incorrecto, desactiváronse os subtítulos." + +msgid "No URI specified to play from." +msgstr "Non se especificou un URI para reproducir." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "O URI «%s» é incorrecto." + +msgid "RTSP streams cannot be played yet." +msgstr "Aínda non é posíbel reproducir os fluxos RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "Non foi posíbel crear o elemento \"decodebin\" ." + +msgid "Source element is invalid." +msgstr "O elemento fonte é incorrecto." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Só se detectou un fluxo de subtítulos. Ou ben está cargando un ficheiro de " +"subtítulos ou calquera outro ficheiro de texto ou quizais o ficheiro " +"multimedia non foi recoñecido." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Non ten instalado un decodificador para manexar este ficheiro. É posíbel que " +"precise instalar os engadidos necesarios. " + +msgid "This is not a media file" +msgstr "Este non é un ficheiro multimedia" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Detectouse un fluxo de subtítulos pero non de vídeo." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Faltan os elementos autovideosink e xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Falta o elemento «%s» - comprobe a instalación do GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Faltan os elementos autoaudiosink e alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Faltan os elementos autivideosink e %s." + +msgid "The autovideosink element is missing." +msgstr "Falta o elemento autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "O videosink configurado %s non está funcionando." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Os elementos autovideosink e %s non están funcionando." + +msgid "The autovideosink element is not working." +msgstr "O elemento autovideosink non está funcionando." + +msgid "Custom text sink element is not usable." +msgstr "Non é posíbel usar o elemento sumideiro (sink) de texto personaizado." + +msgid "No volume control found" +msgstr "Non foi posíbel encontrar o control do volume" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Faltan os elementos autoaudiosink e %s." + +msgid "The autoaudiosink element is missing." +msgstr "Falta o elemento autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "O audiosink configurado %s non está funcionando" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Os elementos autoaudiosink e %s non están funcionando." + +msgid "The autoaudiosink element is not working." +msgstr "O elemento autoaudiosink non está funcionando." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Non é posíbel reproducir un ficheiro de texto sen vídeo nin visualizacións." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Non hai dispoñíbel ningún decodificador para o tipo «%s»." + +msgid "This stream type cannot be played yet." +msgstr "Aínda non é posíbel reproducir este tipo de fluxo." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Non hai implementado un manexador de URIs para «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Produciuse un erro mentres se enviaban datos a \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Produciuse un erro ao enviar os datos da cabeceira gdp a \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Produciuse un erro ao enviar a carga de datos de gdp a «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Rexeitouse a conexión a %s:%d." + +msgid "Can't record audio fast enough" +msgstr "Non é posíbel gravar o son cunha velocidade suficiente" + +msgid "Failed to read tag: not enough data" +msgstr "Produciuse un fallo ao ler a etiqueta: non hai datos suficientes" + +msgid "track ID" +msgstr "ID da pista" + +msgid "MusicBrainz track ID" +msgstr "ID da pista en MusicBrainz" + +msgid "artist ID" +msgstr "ID do artista" + +msgid "MusicBrainz artist ID" +msgstr "ID do artista en MusicBrainz" + +msgid "album ID" +msgstr "ID do álbum" + +msgid "MusicBrainz album ID" +msgstr "ID do álbum en MusicBrainz" + +msgid "album artist ID" +msgstr "ID do álbum do artista" + +msgid "MusicBrainz album artist ID" +msgstr "ID do álbum do artista en MusicBrainz" + +msgid "track TRM ID" +msgstr "ID TRM da pista" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM en MusicBrainz" + +msgid "capturing shutter speed" +msgstr "velocidade do obturador da toma" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Velocidade do obturador usada ao tomar unha imaxe, en segundos" + +msgid "capturing focal ratio" +msgstr "taxa focal da toma" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Taxa focal (número-f) usada ao tomar a imaxe" + +msgid "capturing focal length" +msgstr "lonxitude focal da toma" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Lonxitude focal da lente usada ao tomar a imaxe, en mm" + +msgid "capturing digital zoom ratio" +msgstr "taxa de ampliación dixital da toma" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Taxa de ampliación dixital usada ao tomar unha imaxe" + +msgid "capturing iso speed" +msgstr "velocidade ISO da toma" + +msgid "The ISO speed used when capturing an image" +msgstr "A velocidade de captura ISO usada ao tomar unha imaxe" + +msgid "capturing exposure program" +msgstr "programa de exposición da toma" + +msgid "The exposure program used when capturing an image" +msgstr "O programa de exposición usado ao tomar unha imaxe" + +msgid "capturing exposure mode" +msgstr "modo de exposición da toma" + +msgid "The exposure mode used when capturing an image" +msgstr "O modo de exposición usado ao tomar unha imaxe" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "modo de exposición da toma" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "O modo de exposición usado ao tomar unha imaxe" + +msgid "capturing scene capture type" +msgstr "tipo de escena usado na toma" + +msgid "The scene capture mode used when capturing an image" +msgstr "O modo de captura usado ao tomar unha imaxe" + +msgid "capturing gain adjustment" +msgstr "axuste de ganancia da toma" + +msgid "The overall gain adjustment applied on an image" +msgstr "O axuste xeral de ganancia aplicado nunha imaxe" + +msgid "capturing white balance" +msgstr "balance de brancos da toma" + +msgid "The white balance mode set when capturing an image" +msgstr "O modo de balance de brancos usado ao tomar unha imaxe" + +msgid "capturing contrast" +msgstr "contraste da toma" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "A dirección de contraste procesada aplicada ao tomar unha imaxe" + +msgid "capturing saturation" +msgstr "saturación da toma" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "A dirección de saturación procesada aplicada ao tomar unha imaxe" + +msgid "capturing sharpness" +msgstr "nitidez da toma" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "A dirección de nitidez procesada aplicada ao tomar unha imaxe" + +msgid "capturing flash fired" +msgstr "disparo de flash da toma" + +msgid "If the flash fired while capturing an image" +msgstr "Se o flash se disparou ao capturar unha imaxe" + +msgid "capturing flash mode" +msgstr "modo de flash da toma" + +msgid "The selected flash mode while capturing an image" +msgstr "O modo de flash seleccionado ao tomar unha imaxe" + +msgid "capturing metering mode" +msgstr "modo de medición da toma" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"O modo de medición usado ao determinar a exposición ao tomar unha imaxe" + +msgid "capturing source" +msgstr "orixe da toma" + +msgid "The source or type of device used for the capture" +msgstr "A orixe ou tipo de dispositivo usado para a toma" + +msgid "image horizontal ppi" +msgstr "ppi horizontal da imaxe" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Densidade horizontal de píxeles, en ppi, do medio (imaxe ou vídeo)" + +msgid "image vertical ppi" +msgstr "ppi vertical da imaxe" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Densidade vertical de píxeles, en ppi, do medio (imaxe ou vídeo)" + +msgid "This CD has no audio tracks" +msgstr "Este CD non contén pistas de son" + +msgid "ID3 tag" +msgstr "Etiqueta ID3" + +msgid "APE tag" +msgstr "Etiqueta APE" + +msgid "ICY internet radio" +msgstr "Emisora de internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH sen perda" + +msgid "Uncompressed Gray Image" +msgstr "Imaxe en escala de grises sen comprimir" + +msgid "Run-length encoding" +msgstr "Codificación do tamaño durante a execución" + +msgid "Sami subtitle format" +msgstr "Formato de subtítulos Sami" + +msgid "TMPlayer subtitle format" +msgstr "Formato de subtítulos TMPlayer" + +msgid "Kate subtitle format" +msgstr "Formato de subtítulos Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 plano sen comprimir" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YUV 4:2:0 plano sen comprimir" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 empaquetado sen comprimir" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 empaquetado sen comprimir" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YUV 4:1:0 empaquetado sen comprimir" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 empaquetado sen comprimir" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 empaquetado sen comprimir" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 plano sen comprimir" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 plano sen comprimir" + +msgid "Uncompressed black and white Y-plane" +msgstr "Plano Y en branco e negro sen comprimir" + +msgid "Uncompressed YUV" +msgstr "YUV sen comprimir" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Paletizado sen comprimir de %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Versión %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Audio PCM sen comprimir de %d-bits" + +msgid "Raw PCM audio" +msgstr "Audio PCM sen comprimir" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio sen comprimir de %d-bits en coma flotante" + +msgid "Raw floating-point audio" +msgstr "Audio sen comprimir en coma flotante" + +msgid "Audio CD source" +msgstr "Fonte: CD de son" + +msgid "DVD source" +msgstr "Fonte: DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Fonte: Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Fonte: protocolo Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Fonte: Protocolo %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "decodificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "decodificador de son RTP %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "decodificador RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "demultiplexor %s" + +#, c-format +msgid "%s decoder" +msgstr "decodificador %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "codificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "codificador de son RTP %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "codificador RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "multiplexor %s" + +#, c-format +msgid "%s encoder" +msgstr "codificador %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Elemento %s do GStreamer" + +msgid "Unknown source element" +msgstr "Fonte: Elemento descoñecido" + +msgid "Unknown sink element" +msgstr "Elemento sumideiro (sink) descoñecido" + +msgid "Unknown element" +msgstr "Elemento descoñecido" + +msgid "Unknown decoder element" +msgstr "O elemento decodificador é descoñecido" + +msgid "Unknown encoder element" +msgstr "O elemento codificador é descoñecido" + +msgid "Plugin or element of unknown type" +msgstr "Engadido ou elemento de tipo descoñecido" + +msgid "No device specified." +msgstr "Non se especificou un dispositivo." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "O dispositivo «%s» non existe." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "O dispositivo «%s» xa está en uso." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "" +"Non foi posíbel abrir o dispositivo «%s» para a súa lectura e escritura." diff --git a/gst-plugins-base-subtitles0.10/po/hu.po b/gst-plugins-base-subtitles0.10/po/hu.po new file mode 100644 index 0000000..eec9969 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/hu.po @@ -0,0 +1,610 @@ +# Hungarian translation of gst-plugins-base +# This file is distributed under the same license as the gst-plugins-base package. +# Copyright (C) 2004, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +# +# Laszlo Dvornik , 2004. +# Gabor Kelemen , 2006, 2007, 2008, 2009. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-11-03 02:48+0100\n" +"Last-Translator: Gabor Kelemen \n" +"Language-Team: Hungarian \n" +"Language: hu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Rosetta-Export-Date: 2007-03-10 00:18+0000\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Fő hangerő" + +msgid "Bass" +msgstr "Basszus" + +msgid "Treble" +msgstr "Magas" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Szintet." + +msgid "Line-in" +msgstr "Vonalbemenet" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC hangszóró" + +msgid "Playback" +msgstr "Lejátszás" + +msgid "Capture" +msgstr "Felvétel" + +msgid "Could not open device for playback in mono mode." +msgstr "Nem lehet lejátszásra megnyitni az eszközt mono módban." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nem lehet lejátszásra megnyitni az eszközt sztereó módban." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Nem lehet lejátszásra megnyitni az eszközt %d csatornás módban." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nem lehet lejátszásra megnyitni a hangeszközt. Az eszközt másik alkalmazás " +"használja." + +msgid "Could not open audio device for playback." +msgstr "Nem lehet lejátszásra megnyitni a hangeszközt." + +msgid "Could not open device for recording in mono mode." +msgstr "Nem lehet felvételre megnyitni az eszközt mono módban." + +msgid "Could not open device for recording in stereo mode." +msgstr "Nem lehet felvételre megnyitni az eszközt sztereó módban." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Az eszköz nem nyitható meg felvételre %d csatornás módban." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nem lehet felvételre megnyitni a hangeszközt. Az eszközt másik alkalmazás " +"használja." + +msgid "Could not open audio device for recording." +msgstr "Nem lehet felvételre megnyitni a hangeszközt." + +msgid "Could not open CD device for reading." +msgstr "Nem lehet olvasásra megnyitni a CD-eszközt." + +msgid "Could not seek CD." +msgstr "Nem kereshető a CD." + +msgid "Could not read CD." +msgstr "Nem olvasható a CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nem lehet írásra megnyitni a(z) „%s” vfs-fájlt: %s." + +msgid "No filename given" +msgstr "Nincs fájlnév megadva" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nem lehet bezárni a(z) „%s” vfs-fájlt." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Hiba a(z) „%s” fájl írása közben." + +msgid "Internal data stream error." +msgstr "Belső adatfolyam-hiba." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Az adatfolyam lejátszásához egy %s bővítmény szükséges, de az nincs " +"telepítve." + +msgid "This appears to be a text file" +msgstr "Ez egy szövegfájlnak tűnik" + +msgid "Could not determine type of stream" +msgstr "Nem határozható meg az adatfolyam típusa" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Érvénytelen felirat URI: „%s”, a feliratok letiltva." + +msgid "No URI specified to play from." +msgstr "Nincs megadva URI a lejátszáshoz." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Érvénytelen URI: „%s”." + +msgid "RTSP streams cannot be played yet." +msgstr "Az RTSP adatfolyamok még nem játszhatók le." + +msgid "Could not create \"decodebin\" element." +msgstr "Nem hozható létre „decodebin” elem" + +msgid "Source element is invalid." +msgstr "A forráselem érvénytelen." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Csak egy feliratfolyam észlelhető. Vagy egy feliratfájlt vagy más " +"szövegfájlt tölt be, vagy a médiafájl nem ismerhető fel." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Nincs telepítve a fájl kezeléséhez szükséges dekódoló. Lehetséges, hogy " +"telepítenie kell a szükséges bővítményeket." + +msgid "This is not a media file" +msgstr "Ez nem egy médiafájl" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Egy feliratfolyam felismerve, de nincs videofolyam." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Mind az autovideosink, mind az xvimagesink elemek hiányoznak." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "A(z) „%s” elem hiányzik - ellenőrizze a Gstreamer telepítését." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Az autoaudiosink és az alsasink elem is hiányzik." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Az autovideosink és a(z) %s elem is hiányzik." + +msgid "The autovideosink element is missing." +msgstr "Az autovideosink elem hiányzik." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "A beállított %s videosink elem nem működik." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Sem az autovideosink, sem a(z) %s elem nem működik." + +msgid "The autovideosink element is not working." +msgstr "Az autovideosink elem nem működik." + +msgid "Custom text sink element is not usable." +msgstr "Az egyéni szövegnyelő elem nem használható." + +msgid "No volume control found" +msgstr "Nem található hangerőszabályzó" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Az autoaudiosink és a(z) %s elem is hiányzik." + +msgid "The autoaudiosink element is missing." +msgstr "Az autoaudiosink elem hiányzik." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "A beállított %s audiosink elem nem működik." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Sem az autoaudiosink, sem a(z) %s elem nem működik." + +msgid "The autoaudiosink element is not working." +msgstr "Az autoaudiosink elem nem működik." + +msgid "Can't play a text file without video or visualizations." +msgstr "A szövegfájl nem játszható le videó vagy vizualizációk nélkül." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Nem érhető el dekódoló a(z) „%s” típushoz." + +msgid "This stream type cannot be played yet." +msgstr "Ez az adatfolyamtípus még nem játszható le." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nincs URI kezelő megvalósítva a következőhöz: „%s”." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Hiba adatok küldése során a következőnek: „%s:%d”." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Hiba a gdp fejlécadatok küldésekor a következőnek: „%s:%d”." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Hiba a gdp küldeményadatok elküldésekor a következőnek: „%s:%d”." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "A kapcsolat visszautasítva a következőhöz: %s:%d." + +msgid "Can't record audio fast enough" +msgstr "Nem lehet elég gyorsan rögzíteni a hangot" + +msgid "Failed to read tag: not enough data" +msgstr "A címke nem olvasható: nincs elég adat" + +msgid "track ID" +msgstr "számazonosító" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz számazonosító" + +msgid "artist ID" +msgstr "előadó-azonosító" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz előadó-azonosító" + +msgid "album ID" +msgstr "Albumazonosító" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz albumazonosító" + +msgid "album artist ID" +msgstr "Albumelőadó azonosítója" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albumelőadó azonosítója" + +msgid "track TRM ID" +msgstr "szám TRM azonosítója" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz szám TRM azonosítója" + +msgid "capturing shutter speed" +msgstr "felvétel zársebessége" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Kép felvételéhez használt zársebesség másodpercben" + +msgid "capturing focal ratio" +msgstr "felvétel fókuszaránya" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "A kép felvételéhez használt fókuszarány (f-szám)" + +msgid "capturing focal length" +msgstr "felvétel fókusztávolsága" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "A kép felvételéhez használt lencse fókusztávolsága mm-ben" + +msgid "capturing digital zoom ratio" +msgstr "felvétel digitális nagyítási aránya" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "A kép felvételéhez használt digitális nagyítási arány" + +msgid "capturing iso speed" +msgstr "felvétel ISO sebessége" + +msgid "The ISO speed used when capturing an image" +msgstr "A kép felvételéhez használt ISO sebesség" + +msgid "capturing exposure program" +msgstr "felvétel expozíciós programja" + +msgid "The exposure program used when capturing an image" +msgstr "A kép felvételéhez használt expozíciós program" + +msgid "capturing exposure mode" +msgstr "felvétel expozíciós módja" + +msgid "The exposure mode used when capturing an image" +msgstr "A kép felvételéhez használt expozíciós mód" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "felvétel expozíciós módja" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "A kép felvételéhez használt expozíciós mód" + +msgid "capturing scene capture type" +msgstr "felvétel helyszínfelvételi módja" + +msgid "The scene capture mode used when capturing an image" +msgstr "A kép felvételéhez használt helyszínfelvételi mód" + +msgid "capturing gain adjustment" +msgstr "felvétel erősítésmódosítása" + +msgid "The overall gain adjustment applied on an image" +msgstr "A képre alkalmazott általános erősítésmódosítás" + +msgid "capturing white balance" +msgstr "felvétel fehéregyensúlya" + +msgid "The white balance mode set when capturing an image" +msgstr "A kép felvételéhez használt fehéregyensúlymód" + +msgid "capturing contrast" +msgstr "felvétel kontrasztja" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "A kép felvételekor használt kontrasztfeldolgozás iránya" + +msgid "capturing saturation" +msgstr "felvétel telítettsége" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "A kép felvételekor alkalmazott telítettségfeldolgozás iránya" + +msgid "capturing sharpness" +msgstr "felvétel élessége" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "A kép felvételekor alkalmazott élességfeldolgozás iránya" + +msgid "capturing flash fired" +msgstr "felvétel vakuja" + +msgid "If the flash fired while capturing an image" +msgstr "A kép felvételéhez használt vaku" + +msgid "capturing flash mode" +msgstr "felvétel vakumódja" + +msgid "The selected flash mode while capturing an image" +msgstr "A kép felvételéhez használt kijelölt vakumód" + +msgid "capturing metering mode" +msgstr "felvétel mérési módja" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "A kép felvételekor az expozíció meghatározásához használt mérési mód" + +msgid "capturing source" +msgstr "felvétel forrása" + +msgid "The source or type of device used for the capture" +msgstr "A felvételhez használt forrás vagy eszköz típusa" + +msgid "image horizontal ppi" +msgstr "kép vízszintes ppi" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "A média (kép/videó) tervezett vízszintes képpontsűrűsége ppi-ben" + +msgid "image vertical ppi" +msgstr "kép függőleges ppi" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "A média (kép/videó) tervezett függőleges képpontsűrűsége ppi-ben" + +msgid "This CD has no audio tracks" +msgstr "Ez a CD nem rendelkezik hangsávokkal" + +msgid "ID3 tag" +msgstr "ID3 címke" + +msgid "APE tag" +msgstr "APE címke" + +msgid "ICY internet radio" +msgstr "ICY internetrádió" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple veszteségmentes hang (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Szabad veszteségmentes hangkodek (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Veszteségmentes valódi hang (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media beszéd" + +msgid "CYUV Lossless" +msgstr "CYUV veszteségmentes" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Veszteségmentes MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Tömörítetlen szürke kép" + +msgid "Run-length encoding" +msgstr "Műsorhossz-kódolás" + +msgid "Sami subtitle format" +msgstr "Sami feliratformátum" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer feliratformátum" + +msgid "Kate subtitle format" +msgstr "Kate feliratformátum" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Tömörítetlen síkbeli YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Tömörítetlen síkbeli YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Tömörítetlen pakolt YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Tömörítetlen pakolt YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Tömörítetlen pakolt YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Tömörítetlen pakolt YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Tömörítetlen pakolt YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Tömörítetlen síkbeli YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Tömörítetlen síkbeli YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Tömörítetlen fekete-fehér Y-sík" + +msgid "Uncompressed YUV" +msgstr "Tömörítetlen YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Tömörítetlen, palettás %d bites %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 %d. verzió" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Nyers %d bites PCM hang" + +msgid "Raw PCM audio" +msgstr "Nyers PCM hang" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Nyers %d bites lebegőpontos hang" + +msgid "Raw floating-point audio" +msgstr "Nyers lebegőpontos hang" + +msgid "Audio CD source" +msgstr "Hang CD forrás" + +msgid "DVD source" +msgstr "DVD forrás" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Valósidejű adatfolyam-protokoll (RTSP) forrás" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) protokollforrás" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokollforrás" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s videó RTP dekódoló" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s hang RTP dekódoló" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP dekódoló" + +#, c-format +msgid "%s demuxer" +msgstr "%s szétválasztó" + +#, c-format +msgid "%s decoder" +msgstr "%s dekódoló" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s videó RTP kódoló" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s hang RTP kódoló" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP kódoló" + +#, c-format +msgid "%s muxer" +msgstr "%s egyesítő" + +#, c-format +msgid "%s encoder" +msgstr "%s kódoló" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer elem: %s" + +msgid "Unknown source element" +msgstr "Ismeretlen forráselem" + +msgid "Unknown sink element" +msgstr "Ismeretlen nyelőelem" + +msgid "Unknown element" +msgstr "Ismeretlen elem" + +msgid "Unknown decoder element" +msgstr "Ismeretlen dekódolóelem" + +msgid "Unknown encoder element" +msgstr "Ismeretlen kódolóelem" + +msgid "Plugin or element of unknown type" +msgstr "Ismeretlen típusú bővítmény vagy elem" + +msgid "No device specified." +msgstr "Nincs megadva eszköz." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Az eszköz („%s”) nem létezik." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Az eszköz („%s”) már használatban van." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nem lehet olvasásra és írásra megnyitni az eszközt („%s”)." diff --git a/gst-plugins-base-subtitles0.10/po/id.po b/gst-plugins-base-subtitles0.10/po/id.po new file mode 100644 index 0000000..773bd41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/id.po @@ -0,0 +1,628 @@ +# Indonesian translations for gst-plugins-base package. +# This file is put in the public domain. +# Andhika Padmawan , 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.28.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-04-26 22:01+0700\n" +"Last-Translator: Andhika Padmawan \n" +"Language-Team: Indonesian \n" +"Language: id\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Utama" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Treble" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Jalur masuk" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "Pengeras Suara PC" + +msgid "Playback" +msgstr "Putar kembali" + +msgid "Capture" +msgstr "Tangkap" + +msgid "Could not open device for playback in mono mode." +msgstr "Tak dapat membuka divais untuk putar kembali dalam mode mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Tak dapat membuka divais untuk putar kembali dalam mode stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Tak dapat membuka divais untuk putar kembali dalam mode %d-kanal." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Tak dapat membuka divais audio untuk putar kembali. Divais sedang digunakan " +"oleh aplikasi lain." + +msgid "Could not open audio device for playback." +msgstr "Tak dapat membuka divais audio untuk putar kembali." + +msgid "Could not open device for recording in mono mode." +msgstr "Tak dapat membuka divais untuk merekam dalam mode mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Tak dapat membuka divais untuk merekam dalam mode stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Tak dapat membuka divais untuk merekam dalam mode %d-kanal" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Tak dapat membuka divais audio untuk merekam. Divais sedang digunakan oleh " +"aplikasi lain." + +msgid "Could not open audio device for recording." +msgstr "Tak dapat membuka divais audio untuk merekam." + +msgid "Could not open CD device for reading." +msgstr "Tak dapat membuka divais CD untuk dibaca." + +msgid "Could not seek CD." +msgstr "Tak dapat mencari CD." + +msgid "Could not read CD." +msgstr "Tak dapat membaca CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Tak dapat membuka berkas vfs \"%s\" untuk ditulis: %s." + +msgid "No filename given" +msgstr "Tak ada nama berkas yang diberikan" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Tak dapat menutup berkas vfs \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Galat ketika menulis ke berkas \"%s\"." + +msgid "Internal data stream error." +msgstr "Galat arus data internal." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Plugin %s dibutuhkan untuk memutar arus ini, tapi tidak diinstal." + +msgid "This appears to be a text file" +msgstr "Ini kelihatannya merupakan berkas teks" + +msgid "Could not determine type of stream" +msgstr "Tak dapat menentukan tipe arus" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI subjudul \"%s\" tidak sah, subjudul dinonaktifkan." + +msgid "No URI specified to play from." +msgstr "Tak ada URI yang ditentukan untuk diputar." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "URI \"%s\" tidak sah." + +msgid "RTSP streams cannot be played yet." +msgstr "Arus RTSP belum dapat dimainkan." + +msgid "Could not create \"decodebin\" element." +msgstr "Tak dapat membuat elemen \"decodebin\"" + +msgid "Source element is invalid." +msgstr "Elemen sumber tidak sah." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Hanya arus subjudul yang terdeteksi. Mungkin anda memuat berkas subjudul " +"atau tipe lain dari berkas teks, atau berkas media yang tidak dikenal." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Anda tidak memiliki pengawasandi terinstal untuk menangani berkas ini. Anda " +"mungkin harus menginstal plugin yang diperlukan." + +msgid "This is not a media file" +msgstr "Ini bukan berkas media" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Arus subjudul terdeteksi, tapi bukan arus video." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Baik elemen autovideosink maupun xvimagesink hilang." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Elemen '%s' hilang - cek instalasi GStreamer anda." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Baik elemen autoaudiosink maupun alsasink hilang." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Baik elemen autovideosink maupun %s hilang." + +msgid "The autovideosink element is missing." +msgstr "Elemen autovideosink hilang." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Videosink yang dikonfigurasi %s tidak bekerja." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Baik elemen autovideosink maupun %s tidak bekerja." + +msgid "The autovideosink element is not working." +msgstr "Elemen autovideosink tidak bekerja." + +msgid "Custom text sink element is not usable." +msgstr "Elemen teks tenggelam suai tak dapat digunakan." + +msgid "No volume control found" +msgstr "Tak ada kontrol volume yang ditemukan" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Baik elemen autoaudiosink maupun %s hilang." + +msgid "The autoaudiosink element is missing." +msgstr "Elemen autoaudiosink hilang." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Audiosink yang dikonfigurasi %s tidak bekerja." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Baik elemen autoaudiosink maupun %s tidak bekerja." + +msgid "The autoaudiosink element is not working." +msgstr "Elemen autoaudiosink tidak bekerja." + +msgid "Can't play a text file without video or visualizations." +msgstr "Tak dapat memutar berkas teks tanpa video atau visualisasi." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Tak ada pengawasandi yang tersedia untuk tipe '%s'." + +msgid "This stream type cannot be played yet." +msgstr "Tipe arus ini belum dapat dimainkan." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Tak ada penanganan URI yang diimplementasikan untuk \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Galat ketika mengirim data ke \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Galat ketika mengirim data tajuk gdp ke \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Galat ketika mengirim data pemuat gdp ke \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Koneksi ke %s:%d ditolak." + +msgid "Can't record audio fast enough" +msgstr "Tak dapat merekam audio cukup cepat" + +msgid "Failed to read tag: not enough data" +msgstr "Gagal membaca tanda: tak cukup data" + +msgid "track ID" +msgstr "ID jalur" + +msgid "MusicBrainz track ID" +msgstr "ID jalur MusicBrainz" + +msgid "artist ID" +msgstr "ID artis" + +msgid "MusicBrainz artist ID" +msgstr "ID artis MusicBrainz" + +msgid "album ID" +msgstr "ID album" + +msgid "MusicBrainz album ID" +msgstr "ID album MusicBrainz" + +msgid "album artist ID" +msgstr "ID artis album" + +msgid "MusicBrainz album artist ID" +msgstr "ID artis album MusicBrainz" + +msgid "track TRM ID" +msgstr "ID TRM jalur" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM MusicBrainz" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "CD ini tidak memiliki jalur audio" + +msgid "ID3 tag" +msgstr "Tag ID3" + +msgid "APE tag" +msgstr "Tag APE" + +msgid "ICY internet radio" +msgstr "Radio internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Citra Abu-abu Tak Dikompres" + +msgid "Run-length encoding" +msgstr "Penyandian sepanjang-jalan" + +msgid "Sami subtitle format" +msgstr "Format subjudul Sami" + +msgid "TMPlayer subtitle format" +msgstr "Format subjudul TMPlayer" + +msgid "Kate subtitle format" +msgstr "Format subjudul Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 planar tak dikompresi" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YVU 4:2:0 planar tak dikompresi" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 terkemas tak dikompresi" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 terkemas tak dikompresi" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU 4:1:0 terkemas tak dikompresi" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 terkemas tak dikompresi" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 terkemas tak dikompresi" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 planar tak dikompresi" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 planar tak dikompresi" + +msgid "Uncompressed black and white Y-plane" +msgstr "Y-plane hitam dan putih tak dikompresi" + +msgid "Uncompressed YUV" +msgstr "YUV tak dikompresi" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Terpalet dan tak dikompresi dari %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Versi %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Audio PCM %d-bita mentah" + +msgid "Raw PCM audio" +msgstr "Audio PCM mentah" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio titik-apung %d-bita mentah" + +msgid "Raw floating-point audio" +msgstr "Audio titik-apung mentah" + +msgid "Audio CD source" +msgstr "Sumber CD audio" + +msgid "DVD source" +msgstr "Sumber DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Sumber Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Sumber protokol Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "%s sumber protokol" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video RTP depayloader" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audio RTP depayloader" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP depayloader" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s pengawasandi" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video RTP payloader" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audio RTP payloader" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP payloader" + +#, c-format +msgid "%s muxer" +msgstr "%s muxer" + +#, c-format +msgid "%s encoder" +msgstr "%s penyandi" + +#, c-format +msgid "GStreamer element %s" +msgstr "Elemen GStreamer %s" + +msgid "Unknown source element" +msgstr "Elemen sumber tak diketahui" + +msgid "Unknown sink element" +msgstr "Elemen tenggelam tak diketahui" + +msgid "Unknown element" +msgstr "Elemen tak diketahui" + +msgid "Unknown decoder element" +msgstr "Elemen pengawasandi tak diketahui" + +msgid "Unknown encoder element" +msgstr "Elemen penyandi tak diketahui" + +msgid "Plugin or element of unknown type" +msgstr "Plugin atau elemen dari tipe yang tak diketahui" + +msgid "No device specified." +msgstr "Tak ada divais yang ditentukan." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Divais \"%s\" tak ada." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Divais \"%s\" telah digunakan." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Tak dapat membuka divaus \"%s\" untuk dibaca dan ditulis." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Tak dapat menampilkan baik teks subjudul dan subgambar." + +#~ msgid "No Temp directory specified." +#~ msgstr "Tak ada direktori Temp yang ditentukan." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Tak dapat membuat berkas temp \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Tak dapat membuka berkas \"%s\" untuk dibaca." + +#~ msgid "Internal data flow error." +#~ msgstr "Galat arus data internal." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Tak dapat membuat elemen \"decodebin2\"." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Tak dapat membuat elemen \"queue2\"." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Tak dapat membuat elemen \"typefind\"." + +#~ msgid "No file name specified." +#~ msgstr "Tak ada nama berkas yang ditentukan." diff --git a/gst-plugins-base-subtitles0.10/po/it.po b/gst-plugins-base-subtitles0.10/po/it.po new file mode 100644 index 0000000..c48dc83 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/it.po @@ -0,0 +1,629 @@ +# Italian translation for gst-plugins-base package of GStreamer project. +# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 GStreamer team +# This file is distributed under the same license as the gst-plugins-base package. +# Luca Ferretti , 2004, 2005, 2006, 2007, 2008, 2009, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.28.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-04-28 14:27+0200\n" +"Last-Translator: Luca Ferretti \n" +"Language-Team: Italian \n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Principale" + +msgid "Bass" +msgstr "Bassi" + +msgid "Treble" +msgstr "Acuti" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetiz" + +msgid "Line-in" +msgstr "Linea in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Microfono" + +msgid "PC Speaker" +msgstr "Altoparlanti PC" + +msgid "Playback" +msgstr "Riproduzione" + +msgid "Capture" +msgstr "Cattura" + +msgid "Could not open device for playback in mono mode." +msgstr "Impossibile aprire il device per la riproduzione in modalità mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Impossibile aprire il device per la riproduzione in modalità stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "" +"Impossibile aprire il device per la riproduzione in modalità %d-canali." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Impossibile aprire il device audio per la riproduzione. Il device è " +"utilizzato da un'altra applicazione." + +msgid "Could not open audio device for playback." +msgstr "Impossibile aprire il device audio per la riproduzione." + +msgid "Could not open device for recording in mono mode." +msgstr "Impossibile aprire il device per la registrazione in modalità mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Impossibile aprire il device per la registrazione in modalità stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "" +"Impossibile aprire il device per la registrazione in modalità %d-canali." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Impossibile aprire il device audio per la registrazione. Il device è " +"utilizzato da un'altra applicazione." + +msgid "Could not open audio device for recording." +msgstr "Impossibile aprire il device audio per la registrazione." + +msgid "Could not open CD device for reading." +msgstr "Impossibile aprire il device CD in lettura." + +# seek --> posizionamento (come in glib/gio) +msgid "Could not seek CD." +msgstr "Impossibile effettuare il posizionamento nel CD." + +msgid "Could not read CD." +msgstr "Impossibile leggere il CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Impossibile aprire il file vfs «%s» in scrittura: %s." + +msgid "No filename given" +msgstr "Nessun nome di file fornito" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Impossibile chiudere il file vfs «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Errore durante la scrittura sul file «%s»." + +msgid "Internal data stream error." +msgstr "Errore interno nel flusso di dati." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Per riprodurre questo stream è richiesto un plugin %s, che però non risulta " +"installato. " + +msgid "This appears to be a text file" +msgstr "Questo sembra essere un file di testo" + +msgid "Could not determine type of stream" +msgstr "Impossibile determinare il tipo di stream" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI dei sottotitoli «%s» non valido, sottotitoli disabilitati." + +msgid "No URI specified to play from." +msgstr "Non è stato specificato alcun URI da cui riprodurre." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "URI «%s» non valido." + +msgid "RTSP streams cannot be played yet." +msgstr "Non è ancora possibile riprodurre gli stream RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "Impossibile creare l'elemento «decodebin»." + +msgid "Source element is invalid." +msgstr "L'elemento sorgente non è valido." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"È stato rilevato unicamente uno stream di sottotitoli. Ciò significa che si " +"sta caricando un file di sottotitoli o un altro tipo di file di testo, " +"oppure che il file multimediale non è stato riconosciuto." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Non risulta installato alcun decoder in grado di gestire questo file. " +"Potrebbe essere necessario installare gli opportuni plugin." + +msgid "This is not a media file" +msgstr "Questo non è un file multimediale" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "È stato rilevato uno stream di sottotitoli, ma nessuno stream video." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" +"Risultano mancanti entrambi gli elementi «autovideosink» e «xvimagesink»." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" +"Risulta mancante l'elemento «%s» - verificare la propria installazione di " +"GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Risultano mancanti entrambi gli elementi «autoaudiosink» e «alsasink»." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Risultano mancanti entrambi gli elementi «autovideosink» e «%s»." + +msgid "The autovideosink element is missing." +msgstr "Risulta mancante l'elemento «autovideosink»." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "L'elemento videosink «%s» non è operativo." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Entrambi gli elementi «autovideosink» e «%s» non sono operativi." + +msgid "The autovideosink element is not working." +msgstr "L'elemento «autovideosink» non è operativo." + +msgid "Custom text sink element is not usable." +msgstr "L'elemento sink di testo personalizzato non è utilizzabile." + +msgid "No volume control found" +msgstr "Non è stato trovato alcun controllo del volume" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Risultano mancanti entrambi gli elementi «autoaudiosink» e «%s»." + +msgid "The autoaudiosink element is missing." +msgstr "Risulta mancante l'elemento «autoaudiosink»." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "L'elemento audiosink «%s» non è operativo." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Entrambi gli elementi «autoaudiosink» e «%s» non sono operativi." + +msgid "The autoaudiosink element is not working." +msgstr "L'elemento «autoaudiosink» non è operativo." + +msgid "Can't play a text file without video or visualizations." +msgstr "Impossibile riprodurre un file di testo senza video o visualizzazioni." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Nessun decoder disponibile per il tipo «%s»." + +msgid "This stream type cannot be played yet." +msgstr "Non è ancora possibile riprodurre questo tipo di stream." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nessun gestore di URI implementato per «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Errore durante l'invio dei dati a \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Errore durante l'invio di dati header gdp a \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Errore durante l'invio di dati payload gdp a \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Connessione a %s:%d rifiutata." + +# una parafrasi, ma mi pare non perda... -Luca +msgid "Can't record audio fast enough" +msgstr "Impossibile registrare l'audio a velocità adeguata" + +# dati non sufficienti... mah +msgid "Failed to read tag: not enough data" +msgstr "Lettura del tag non riuscita: non abbastanza dati" + +msgid "track ID" +msgstr "ID traccia" + +msgid "MusicBrainz track ID" +msgstr "ID MusicBrainz della traccia" + +msgid "artist ID" +msgstr "ID artista" + +msgid "MusicBrainz artist ID" +msgstr "ID MusicBrainz dell'artista" + +msgid "album ID" +msgstr "ID album" + +msgid "MusicBrainz album ID" +msgstr "ID MusicBrainz dell'album" + +msgid "album artist ID" +msgstr "ID artista dell'album" + +msgid "MusicBrainz album artist ID" +msgstr "ID MusicBrainz dell'artista dell'album" + +msgid "track TRM ID" +msgstr "ID TRM della traccia" + +msgid "MusicBrainz TRM ID" +msgstr "ID MusicBrainz del TRM" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Questo CD non presenta alcuna traccia audio" + +msgid "ID3 tag" +msgstr "Tag ID3" + +msgid "APE tag" +msgstr "Tag APE" + +msgid "ICY internet radio" +msgstr "Radio internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "ALAC (Apple Lossless Audio)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "FLAC (Free Lossless Audio Codec)" + +msgid "Lossless True Audio (TTA)" +msgstr "TTA (Lossless True Audio)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV senza perdita" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH senza perdita" + +# non ho trovato info utili... +# Copiato il messaggio originale solo per arrivare a 100 per cento +msgid "Uncompressed Gray Image" +msgstr "Uncompressed Gray Image" + +# cfr http://en.wikipedia.org/wiki/Run_length_encoding +msgid "Run-length encoding" +msgstr "RLE (Run-Length Encoding)" + +# grazie San Google +msgid "Sami subtitle format" +msgstr "Sottotitoli formato SAMI" + +msgid "TMPlayer subtitle format" +msgstr "Sottotitoli formato TMPlayer" + +msgid "Kate subtitle format" +msgstr "Sottotitoli formato Kate" + +# cfr http://en.wikipedia.org/wiki/YUV +# http://support.microsoft.com/kb/281188/it +# http://support.microsoft.com/kb/294880/it (traduz automatica) :-( +# http://www.benis.it/dvd/agg3.htm +# +# Dal secondo e terzo, evinco YUV compresso o planare sarebbero +# buone abbreviazioni, ma tengo planare/packed + compresso/noncompresso +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 planare non compresso" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YVU 4:2:0 planare non compresso" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 packed non compresso" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 packed non compresso" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU 4:1:0 packed non compresso" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 packed non compresso" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 packed non compresso" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 planare non compresso" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 planare non compresso" + +msgid "Uncompressed black and white Y-plane" +msgstr "Bianco e nero Y-plane non compresso" + +msgid "Uncompressed YUV" +msgstr "YUV non compresso" + +# %s è qualcosa come gli YUV dei precedenti +# +# Non so perché, ma senza X$ non lo dava buono.... +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "%2$s %1$d-bit con tavolozza non compresso" + +# o MPEG-4 DivX ? +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versione %d" + +# o audio grezzo ? +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Audio raw PCM %d-bit" + +msgid "Raw PCM audio" +msgstr "Audio raw PCM" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio raw floating-point %d-bit" + +msgid "Raw floating-point audio" +msgstr "Audio raw floating-point" + +msgid "Audio CD source" +msgstr "Sorgente CD audio" + +msgid "DVD source" +msgstr "Sorgente DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Sorgente RTSP (Real Time Streaming Protocol)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Sorgente protocollo MMS (Microsoft Media Server)" + +#, c-format +msgid "%s protocol source" +msgstr "Sorgente protocollo %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Depayloader RTP %s video" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Depayloader RTP %s audio" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Depayloader RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Demuxer %s" + +#, c-format +msgid "%s decoder" +msgstr "Decoder %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Payloader RTP %s video" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Payloader RTP %s audio" + +#, c-format +msgid "%s RTP payloader" +msgstr "Payloader RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Muxer %s" + +#, c-format +msgid "%s encoder" +msgstr "Encoder %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Elemento GStreamer %s" + +msgid "Unknown source element" +msgstr "Elemento sorgente sconosciuto" + +msgid "Unknown sink element" +msgstr "Elemento sink sconosciuto" + +msgid "Unknown element" +msgstr "Elemento sconosciuto" + +msgid "Unknown decoder element" +msgstr "Elemendo di decodifica sconosciuto" + +msgid "Unknown encoder element" +msgstr "Elemento di codifica sconosciuto" + +msgid "Plugin or element of unknown type" +msgstr "Plugin o elemento di tipo sconosciuto" + +msgid "No device specified." +msgstr "Nessun device specificato." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Il device «%s» non esiste." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Il device «%s» è già in uso." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Impossibile aprire il device «%s» in lettura e scrittura." diff --git a/gst-plugins-base-subtitles0.10/po/ja.po b/gst-plugins-base-subtitles0.10/po/ja.po new file mode 100644 index 0000000..cd68472 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/ja.po @@ -0,0 +1,621 @@ +# Japanese translation of gst-plugins-base +# This file is put in the public domain. +# +# Makoto Kato , 2009-2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-10-25 10:27+0900\n" +"Last-Translator: Makoto Kato \n" +"Language-Team: Japanese \n" +"Language: ja\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 0.2\n" +"Plural-Forms: nplurals=1; plural=0;\n" + +msgid "Master" +msgstr "マスター" + +msgid "Bass" +msgstr "低音" + +msgid "Treble" +msgstr "高音" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "シンセ" + +msgid "Line-in" +msgstr "ライン入力" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "マイクロフォン" + +msgid "PC Speaker" +msgstr "PCスピーカー" + +msgid "Playback" +msgstr "再生" + +msgid "Capture" +msgstr "キャプチャ" + +msgid "Could not open device for playback in mono mode." +msgstr "モノラルモードで再生用にデバイスをオープンできませんでした" + +msgid "Could not open device for playback in stereo mode." +msgstr "ステレオモードで再生用にデバイスをオープンできませんでした" + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "%d チャンネルモードで再生用にデバイスを開くことができませんでした" + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"再生用にオーディオデバイスを開くことができませんでした。デバイスは他のアプリ" +"ケーションで利用されています" + +msgid "Could not open audio device for playback." +msgstr "再生用にオーティオデバイスを開くことができませんでした" + +msgid "Could not open device for recording in mono mode." +msgstr "モノラルモードで録音用にデバイスを開くことができませんでした" + +msgid "Could not open device for recording in stereo mode." +msgstr "ステレオモードで録音用にデバイスを開くことができませんでした" + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "%d チャンネルモードで録音用にデバイスを開くことができませんでした" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"録音用にオーディオデバイスを開くことができませんでした。デバイスは他のアプリ" +"ケーションで利用されています" + +msgid "Could not open audio device for recording." +msgstr "録音用にオーディオデバイスを開くことができませんでした" + +msgid "Could not open CD device for reading." +msgstr "読み込み用に CD デバイスを開くことができませんでした" + +msgid "Could not seek CD." +msgstr "CDをシークすることができませんでした" + +msgid "Could not read CD." +msgstr "CD を読むことができませんでした" + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "書き込み用に vfs ファイル \"%s\" を開くことができませんでした: %s" + +msgid "No filename given" +msgstr "ファイル名が与えられていません" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "vfs ファイル \"%s\" をクローズできませんでした" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "ファイル \"%s\" の書き込み中にエラーが発生しました" + +msgid "Internal data stream error." +msgstr "内部データストリームエラー" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"%s プラグインはこのストリームを再生するのに必要ですが、インストールされていま" +"せん" + +msgid "This appears to be a text file" +msgstr "これはテキストファイルのようです" + +msgid "Could not determine type of stream" +msgstr "ストリームの種類を判別できませんでした" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "不正な字幕 URI \"%s\"。字幕を無効にします。" + +msgid "No URI specified to play from." +msgstr "再生するURIが指定されていません" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "不正な URI \"%s\"" + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP ストリームをまだ再生できません" + +msgid "Could not create \"decodebin\" element." +msgstr "\"decodebin\" エレメントを作成できません。" + +msgid "Source element is invalid." +msgstr "ソースエレメントが不正です。" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"字幕ストリームのみを認識しました。字幕ファイルかテキストファイルをロード中" +"か、メディアファイルが認識されないのかどちらかです。" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"このファイルを扱うことができるデコーダがインストールされていません。必要なプ" +"ラグインをインストールする必要があるかもしれません" + +msgid "This is not a media file" +msgstr "これはメディアファイルではありません" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "字幕のストリームを認識しましたが、動画ストリームがありません" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "autovideosinkとxvimagesinkエレメントの両方が見つかりません。" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" +"エレメント '%s' が見つかりません - GStreamer のインストールが失敗している可能" +"性があります" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "autovideosinkとalsasinkエレメントの両方が見つかりません。" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "autovideosinkと%sエレメントの両方が見つかりません。" + +msgid "The autovideosink element is missing." +msgstr "autovideosinkエレメントが見つかりません。" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "設定された videosink %s が動作していません。" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "autovideosinkと%sエレメントの両方が動作していません。" + +msgid "The autovideosink element is not working." +msgstr "autovideosinkエレメントが動作していません。" + +msgid "Custom text sink element is not usable." +msgstr "カスタムテキストシンクエレメントは使用できません。" + +msgid "No volume control found" +msgstr "ボリュームコントロールが見つかりません" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "autoaudiosinkと%sエレメントの両方が見つかりません。" + +msgid "The autoaudiosink element is missing." +msgstr "autoaudiosinkエレメントが見つかりません。" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "設定された autoaudiosink %s が動作していません。" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "autoaudiosinkと%sエレメントの両方が動作していません。" + +msgid "The autoaudiosink element is not working." +msgstr "autoaudiosinkエレメントが動作していません。" + +msgid "Can't play a text file without video or visualizations." +msgstr "ビデオまたは視覚化なしでテキストファイルを再生できません。" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "タイプ '%s' 用のデコーダーが利用可能ではありません。" + +msgid "This stream type cannot be played yet." +msgstr "このストリームタイプをまだ再生することはできません" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "\"%s\" 用の URI ハンドラの実装はありません" + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "データを \"%s:%d\" へ送信中にエラーが発生しました" + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "gdp ヘッダデータを \"%s:%d\" へ送信中にエラーが発生しました" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "gdp ペイロードデータを \"%s:%d\" へ送信中にエラーが発生しました" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "%s:%d への接続が拒否されました" + +msgid "Can't record audio fast enough" +msgstr "十分に速くオーディオを録音することができません" + +msgid "Failed to read tag: not enough data" +msgstr "タグの読み込みに失敗しました: データが十分にありません" + +msgid "track ID" +msgstr "トラック ID" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz トラック ID" + +msgid "artist ID" +msgstr "アーティスト ID" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz アーティスト ID" + +msgid "album ID" +msgstr "アルバム ID" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz アルバム ID" + +msgid "album artist ID" +msgstr "アルバムアーティスト ID" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz アルバムアーティスト ID" + +msgid "track TRM ID" +msgstr "トラック TRM ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "キャプチャーのシャッタースピード" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "イメージをキャプチャするときに使われるシャッタースピード (秒)" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "キャプチャーの彩度" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "イメージをキャプチャするときのホワイトバランスモードセット" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "キャプチャーのホワイトバランス" + +msgid "The white balance mode set when capturing an image" +msgstr "イメージをキャプチャするときのホワイトバランスモードセット" + +msgid "capturing contrast" +msgstr "キャプチャーのコントラスト" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "キャプチャーの彩度" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "キャプチャーのシャープネス" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "キャプチャーのソース" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "この CD にはオーディオトラックがありません" + +msgid "ID3 tag" +msgstr "ID3 タグ" + +msgid "APE tag" +msgstr "APE タグ" + +msgid "ICY internet radio" +msgstr "ICY インターネットラジオ" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "ロスレス True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV ロスレス" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "ロスレス MSZH" + +msgid "Uncompressed Gray Image" +msgstr "非圧縮グレーイメージ" + +msgid "Run-length encoding" +msgstr "ランレングス符号化" + +msgid "Sami subtitle format" +msgstr "Sami 字幕形式" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer 字幕形式" + +msgid "Kate subtitle format" +msgstr "Kate 字幕形式" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "非圧縮 planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "非圧縮 planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "非圧縮 packed YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "非圧縮 packed YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "非圧縮 packed YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "非圧縮 packed YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "非圧縮 packed YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "非圧縮 planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "非圧縮 planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "非圧縮黒と白Y-plane" + +msgid "Uncompressed YUV" +msgstr "非圧縮 YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "非圧縮 palettized %d ビット %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 バージョン %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Raw %d ビット PCM オーディオ" + +msgid "Raw PCM audio" +msgstr "Raw PCM オーディオ" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Raw %d ビット浮動小数点オーディオ" + +msgid "Raw floating-point audio" +msgstr "Raw 浮動小数点オーディオ" + +msgid "Audio CD source" +msgstr "オーディオ CD ソース" + +msgid "DVD source" +msgstr "DVD ソース" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol (RTSP) ソース" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) プロトコルソース" + +#, c-format +msgid "%s protocol source" +msgstr "%s プロトコルソース" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s ビデオ RTP デペイローダー" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s オーディオ RTP デペイローダー" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP デペイローダー" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s デコーダー" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s ビデオ RTP ペイローダー" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s オーディオ RTP ペイローダー" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP ペイローダー" + +#, c-format +msgid "%s muxer" +msgstr "%s ミキサー" + +#, c-format +msgid "%s encoder" +msgstr "%s エンコーダー" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer エレメント %s" + +msgid "Unknown source element" +msgstr "不明なソースエレメント" + +msgid "Unknown sink element" +msgstr "不明なシンクエレメント" + +msgid "Unknown element" +msgstr "不明なエレメント" + +msgid "Unknown decoder element" +msgstr "不明なデコーダーエレメント" + +msgid "Unknown encoder element" +msgstr "不明なエンコーダーエレメント" + +msgid "Plugin or element of unknown type" +msgstr "不明な種類のプラグインまたはエレメント" + +msgid "No device specified." +msgstr "デバイスが指定されていません。" + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "デバイス \"%s\" は存在しません。" + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "デバイス \"%s\" は既に使われています。" + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "読み込み用と書き込み用にデバイス \"%s\" を開くことができませんでした。" + +#~ msgid "No file name specified." +#~ msgstr "ファイル名が指定されていません" + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "読み込み用にファイル \"%s\" を開くことができませんでした" + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "\"decodebin2\" エレメントを作成できませんでした" + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "\"queue2\" エレメントを作成できませんでした" diff --git a/gst-plugins-base-subtitles0.10/po/lt.po b/gst-plugins-base-subtitles0.10/po/lt.po new file mode 100644 index 0000000..d03994c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/lt.po @@ -0,0 +1,639 @@ +# translation of lt.gst-plugins-base.HEAD.po to Lithuanian +# Copyright (C) 2008 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# +# Gintautas Miliauskas , 2008. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base-0.10.15.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2008-03-07 23:43+0200\n" +"Last-Translator: Gintautas Miliauskas \n" +"Language-Team: Lithuanian \n" +"Language: lt\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.11.4\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n" +"%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Master" +msgstr "Pagrindinis" + +msgid "Bass" +msgstr "Žemi dažniai" + +msgid "Treble" +msgstr "AukÅ¡ti dažniai" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintezatorius" + +msgid "Line-in" +msgstr "Ä®vedimas" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofonas" + +msgid "PC Speaker" +msgstr "PC garsiakalbis" + +msgid "Playback" +msgstr "Grojimas" + +msgid "Capture" +msgstr "Ä®raÅ¡ymas" + +msgid "Could not open device for playback in mono mode." +msgstr "Nepavyko atverti įrenginio monofoniniam grojimui." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nepavyko atverti įrenginio stereofoniniam grojimui." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Nepavyko atverti įrenginio %d kanalų grojimui." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nepavyko atverti audio įrenginio grojimui. Ä®renginys naudojamas kitos " +"programos." + +msgid "Could not open audio device for playback." +msgstr "Nepavyko atverti audio įrenginio grojimui." + +msgid "Could not open device for recording in mono mode." +msgstr "Nepavyko atverti įrenginio monofoniniam įraÅ¡ymui." + +msgid "Could not open device for recording in stereo mode." +msgstr "Nepavyko atverti įrenginio stereofoniniam įraÅ¡ymui." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Nepavyko atverti įrenginio %d kanalų įraÅ¡ymui" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nepavyko atverti audio įrenginio įraÅ¡ymui. Ä®renginys naudojamas kitos " +"programos." + +msgid "Could not open audio device for recording." +msgstr "Nepavyko atverti audio įrenginio įraÅ¡ymui." + +msgid "Could not open CD device for reading." +msgstr "Nepavyko atverti CD įrenginio skaitymui." + +msgid "Could not seek CD." +msgstr "Nepavyko pakeisti pozicijos CD." + +msgid "Could not read CD." +msgstr "Nepavyko perskaityti CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nepavyko atverti vfs failo „%s“ raÅ¡ymui: %s." + +msgid "No filename given" +msgstr "Nenurodytas failo vardas" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nepavyko užverti vfs failo „%s“." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Klaida raÅ¡ant į failą „%s“." + +msgid "Internal data stream error." +msgstr "Vidinė duomenų srauto klaida." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Å iam srautui groti reikalingas %s įskiepis, bet jis nėra įdiegtas." + +msgid "This appears to be a text file" +msgstr "Atrodo, kad Å¡is failas tekstinis" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "Nepavyko sukurti „decodebin“ elemento." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Netaisyklingas titrų URI „%s“, titrai iÅ¡jungti." + +msgid "No URI specified to play from." +msgstr "Nenurodytas URI, iÅ¡ kurio groti." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Netaisyklingas URI „%s“." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP srautai dar negali bÅ«ti rodomi." + +msgid "Could not create \"decodebin\" element." +msgstr "Nepavyko sukurti „decodebin“ elemento." + +msgid "Source element is invalid." +msgstr "Å altinio elementas nekorektiÅ¡kas." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Rastas tik subtitrų srautas. Arba bandote įkelti subtitrų failą ar kitokį " +"tekstinį failą, arba failas nebuvo teisingai atpažintas." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Neturite dekoderio, reikalingo Å¡iam failui rodyti. Gali prireikti įdiegti " +"reikalingus įskiepius." + +msgid "This is not a media file" +msgstr "Tai nėra medijos failas" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Rastas titrų srautas, bet be video srauto." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "TrÅ«ksta elemento „%s“ - patikrinkite GStreamer įdiegimą." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +#, fuzzy, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +#, fuzzy +msgid "The autovideosink element is missing." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +#, fuzzy, c-format +msgid "Configured videosink %s is not working." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +#, fuzzy, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +#, fuzzy +msgid "The autovideosink element is not working." +msgstr "TrÅ«ksta ir autovideosink, ir xvimagesink elementų." + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, fuzzy, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +#, fuzzy +msgid "The autoaudiosink element is missing." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +#, fuzzy, c-format +msgid "Configured audiosink %s is not working." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +#, fuzzy, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +#, fuzzy +msgid "The autoaudiosink element is not working." +msgstr "TrÅ«ksta ir autoaudiosink, ir alsasink elementų." + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Tipui „%s“ dekoderių nerasta." + +msgid "This stream type cannot be played yet." +msgstr "Å is srautas dar negali bÅ«ti rodomas." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nėra URI valdyklės „%s“." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Klaida siunčiant duomenis į „%s:%d“." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Klaida siunčiant gdp antraÅ¡tės duomenis į \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Klaida siunčiant gdp duomenis į „%s:%d“." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Prisijungimas prie %s:%d atmestas." + +msgid "Can't record audio fast enough" +msgstr "Nepakankamai greitai įraÅ¡omas garsas" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "takelio ID" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz takelio ID" + +msgid "artist ID" +msgstr "atlikėjo ID" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz atlikėjo ID" + +msgid "album ID" +msgstr "albumo ID" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz albumo ID" + +msgid "album artist ID" +msgstr "albumo atlikėjo ID" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albumo atlikėjo ID" + +msgid "track TRM ID" +msgstr "takelio TRM ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Å iame CD nėra audio takelių" + +msgid "ID3 tag" +msgstr "ID3 žymė" + +msgid "APE tag" +msgstr "APE žymė" + +msgid "ICY internet radio" +msgstr "ICY interneto radijas" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Nesuspaustas bespalvis paveikslas" + +msgid "Run-length encoding" +msgstr "Eilės ilgio kodavimas (RLE)" + +msgid "Sami subtitle format" +msgstr "Sami titrų formatas" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer titrų formatas" + +#, fuzzy +msgid "Kate subtitle format" +msgstr "Sami titrų formatas" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nekompresuotas planarinis YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nekompresuotas planarinis YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nekompresuotas planarinis YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nekompresuotas planarinis YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nekompresuotas planarinis YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nekompresuotas planarinis YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nekompresuotas planarinis YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nekompresuotas planarinis YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nekompresuotas planarinis YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nekompresuota juodai balta Y plokÅ¡tuma" + +msgid "Uncompressed YUV" +msgstr "Nekompresuotas YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nekompresuotas paletizuotas %d bitų %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versija %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Neapdorotas %d bitų PCM garsas" + +msgid "Raw PCM audio" +msgstr "Neapdorotas PCM garsas" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Neapdorotas %d bitų slankaus kablelio garsas" + +msgid "Raw floating-point audio" +msgstr "Neapdorotas slankaus kablelio garsas" + +msgid "Audio CD source" +msgstr "Audio CD Å¡altinis" + +msgid "DVD source" +msgstr "DVD Å¡altinis" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Realaus laiko srautų protokolo (RTSP) Å¡altinis" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) protokolo Å¡altinis" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokolo Å¡altinis" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video RTP depayloader'is" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audio RTP depayloader'is" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP depayloader'is" + +#, c-format +msgid "%s demuxer" +msgstr "%s demukseris" + +#, c-format +msgid "%s decoder" +msgstr "%s dekoderis" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video RTP payloader'is" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audio RTP payloader'is" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP payloader'is" + +#, c-format +msgid "%s muxer" +msgstr "%s mukseris" + +#, c-format +msgid "%s encoder" +msgstr "%s enkoderis" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer elementas %s" + +msgid "Unknown source element" +msgstr "Nežinomas Å¡altinio elementas" + +msgid "Unknown sink element" +msgstr "Nežinomas paskirties elementas" + +msgid "Unknown element" +msgstr "Nežinomas elementas" + +msgid "Unknown decoder element" +msgstr "Nežinomas dekodavimo elementas" + +msgid "Unknown encoder element" +msgstr "Nežinomas kodavimo elementas" + +msgid "Plugin or element of unknown type" +msgstr "Nežinomo tipo įskiepis ar elementas" + +msgid "No device specified." +msgstr "Nenurodytas įrenginys." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Ä®renginys „%s“ neegzistuoja." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Ä®renginys „%s“ jau naudojamas." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nepavyko atverti įrenginio „%s“ skaitymui ir raÅ¡ymui." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Nepavyko sukurti „decodebin2“ elemento." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Nepavyko sukurti „queue2“ elemento." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Nepavyko sukurti „decodebin“ elemento." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Nenurodytas įrenginys." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Nepavyko užverti vfs failo „%s“." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Nepavyko atverti failo „%s“ raÅ¡ymui." + +#, fuzzy +#~ msgid "Internal data flow error." +#~ msgstr "Vidinė duomenų srauto klaida." + +#~ msgid "No file name specified." +#~ msgstr "Nenurodytas failo vardas." diff --git a/gst-plugins-base-subtitles0.10/po/lv.po b/gst-plugins-base-subtitles0.10/po/lv.po new file mode 100644 index 0000000..539d64f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/lv.po @@ -0,0 +1,626 @@ +# Latvian translation of gst-plugins-base +# This file is put in the public domain. +# +# Arvis Lācis , 2009. +# Rihards PriedÄ«tis , 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.29.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-07-07 10:52+0100\n" +"Last-Translator: Rihards PriedÄ«tis \n" +"Language-Team: Latvian \n" +"Language: lv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Poedit-Language: Latvian\n" +"X-Poedit-Country: LATVIA\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : " +"2);\n" +"X-Generator: Lokalize 1.0\n" + +msgid "Master" +msgstr "Galvenais" + +msgid "Bass" +msgstr "Bass" + +msgid "Treble" +msgstr "Diskants" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintēze" + +msgid "Line-in" +msgstr "Line-in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofons" + +msgid "PC Speaker" +msgstr "Datora skaļrunis" + +msgid "Playback" +msgstr "AtskaņoÅ¡ana" + +msgid "Capture" +msgstr "TverÅ¡ana" + +msgid "Could not open device for playback in mono mode." +msgstr "Nevarēja atvērt ierÄ«ci atskaņoÅ¡anai mono režīmā." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nevarēja atvērt ierÄ«ci atskaņoÅ¡anai stereo režīmā." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Nevarēja atvērt ierÄ«ci atskaņoÅ¡anai %d-kanāla režīmā." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nevarēja atvērt audio ierÄ«ci atskaņoÅ¡anai. IerÄ«ci paÅ¡laik izmanto cita " +"lietotne." + +msgid "Could not open audio device for playback." +msgstr "Nevarēja atvērt audio ierÄ«ci atskaņoÅ¡anai." + +msgid "Could not open device for recording in mono mode." +msgstr "Nevarēja atvērt ierÄ«ci ierakstÄ«Å¡anai mono režīmā." + +msgid "Could not open device for recording in stereo mode." +msgstr "Nevarēja atvērt ierÄ«ci ierakstÄ«Å¡anai stereo režīmā." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Nevarēja atvērt ierÄ«ci ierakstÄ«Å¡anai %d-kanāla režīmā" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nevarēja atvērt audio ierÄ«ci ierakstÄ«Å¡anai. IerÄ«ci paÅ¡laik izmanto cita " +"lietotne." + +msgid "Could not open audio device for recording." +msgstr "Nevarēja atvērt audio ierÄ«ci ierakstÄ«Å¡anai." + +msgid "Could not open CD device for reading." +msgstr "Nevarēja atvērt CD ierÄ«ci lasÄ«Å¡anai." + +msgid "Could not seek CD." +msgstr "Nevarēja meklēt pa CD." + +msgid "Could not read CD." +msgstr "Nevarēja nolasÄ«t CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nevarēja atvērt vfs failu \"%s\" rakstÄ«Å¡anai: %s." + +msgid "No filename given" +msgstr "Nav norādÄ«ts faila nosaukums" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nevarēja aizvērt vfs failu \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Kļūda rakstot failā \"%s\"." + +msgid "Internal data stream error." +msgstr "Iekšējās datu plÅ«smas kļūda." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"NepiecieÅ¡amas %s spraudnis, lai atskaņotu Å¡o plÅ«smu, bet tas nav instalēts." + +msgid "This appears to be a text file" +msgstr "Tiek atpazÄ«ts kā teksta fails" + +msgid "Could not determine type of stream" +msgstr "Nevarēja noteikts straumes tipu" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "NederÄ«gs subtitru URI \"%s\", subtitri izslēgti." + +msgid "No URI specified to play from." +msgstr "Nav norādÄ«ts neviens URI, no kā varētu spēlēt. " + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "NederÄ«gs URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP plÅ«smas pagaidām nevar tikt atskaņotas." + +msgid "Could not create \"decodebin\" element." +msgstr "Nevarēja izveidot \"decodebin\" elementu." + +msgid "Source element is invalid." +msgstr "Avota elements ir nederÄ«gs." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Tika pamanÄ«ta tikai subtitru plÅ«sma. Vai nu jÅ«s ielādējat subtitru failu vai " +"cita veida teksta failu, vai arÄ« mediju fails netika atpazÄ«ts." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Jums nav instalēta atkodētāja, lai apietos ar Å¡o failu. Jums iespējams " +"vajadzētu instalēt nepiecieÅ¡amos spraudņus." + +msgid "This is not a media file" +msgstr "Å is nav mediju fails" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Tika pamanÄ«ta subtitru plÅ«sma, bet ne video plÅ«sma." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "TrÅ«kst gan autovideosink, gan xvimagesink elementi." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "TrÅ«kst elements \"%s\" - pārbaudiet savu GStreamer instalāciju." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "TrÅ«kst gan autoaudiosink, gan alsasink elementi." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "TrÅ«kst gan autovideosink, gan %s elementi." + +msgid "The autovideosink element is missing." +msgstr "TrÅ«kst autovideosink elements." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Konfigurētais videosink %s nestrādā." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Gan autovideosink, gan %s elementi nedarbojas." + +msgid "The autovideosink element is not working." +msgstr "autovideosink elements nedarbojas." + +msgid "Custom text sink element is not usable." +msgstr "Pielāgots teksta iegremdēšanas elements nav lietojams." + +msgid "No volume control found" +msgstr "Netika atrasta neviena skaļuma kontrole" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "TrÅ«kst gan autoaudiosink, gan %s elementi." + +msgid "The autoaudiosink element is missing." +msgstr "TrÅ«kst autoaudiosink elements." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Konfigurētais audiosink %s nestrādā." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Nedarbojas autoaudiosink un %s elementi." + +msgid "The autoaudiosink element is not working." +msgstr "autoaudiosink elements nedarbojas." + +msgid "Can't play a text file without video or visualizations." +msgstr "Nevar atskaņot teksta failu bez video vai vizualizācijas." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Nav pieejams neviens atkodētājs failu veidam \"%s\"." + +msgid "This stream type cannot be played yet." +msgstr "Å Ä« plÅ«sma pagaidām nevar tikt atskaņota." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nav izstrādāts neviens URI apstrādātājs priekÅ¡ \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Radās kļūda nosÅ«tot datus uz \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Radās kļūda nosÅ«tot gdb galvenas datus uz \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Kļūda sÅ«tot gdp iekrāvēja datus uz \"%s:%d\"" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Savienojums ar %s:%d noraidÄ«ts." + +msgid "Can't record audio fast enough" +msgstr "Nevar ierakstÄ«t audio pietiekami ātri" + +msgid "Failed to read tag: not enough data" +msgstr "Neizdevās nolasÄ«t atzÄ«mi: nepietiek datu" + +msgid "track ID" +msgstr "celiņa ID" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz celiņa ID" + +msgid "artist ID" +msgstr "izpildÄ«tāja ID" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz izpildÄ«tāja ID" + +msgid "album ID" +msgstr "albuma ID" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz albuma ID" + +msgid "album artist ID" +msgstr "albuma izpildÄ«tāja ID" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albuma izpildÄ«tāja ID" + +msgid "track TRM ID" +msgstr "celiņa TRM ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Å ajā CD nav neviena audio celiņa" + +msgid "ID3 tag" +msgstr "ID3 atzÄ«me" + +msgid "APE tag" +msgstr "APE atzÄ«me" + +msgid "ICY internet radio" +msgstr "ICY interneta radio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Bez zudumu True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows mediju runa" + +msgid "CYUV Lossless" +msgstr "CYUV bez zudumu" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Bez zudumu MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Neatspiests Pelēks attēls" + +msgid "Run-length encoding" +msgstr "Sērijas garuma kodēšana" + +msgid "Sami subtitle format" +msgstr "Sami subtitru formāts" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer subtitru formāts" + +msgid "Kate subtitle format" +msgstr "Kate subtitru formāts" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nesaspiesta plakne YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nesaspiesta plakne YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nesaspiests pakots YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nesaspiests pakots YUP 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nesaspiests pakots YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nesaspiests pakots YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nesaspiests pakots YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nesaspiesta plakne YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nesaspiesta plakne YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nesaspiests melnbaltais Y-plakne" + +msgid "Uncompressed YUV" +msgstr "Nesaspiests YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nesaspiests paletizēts %d-bitu %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versija %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Jēls %d-bitu PCM audio" + +msgid "Raw PCM audio" +msgstr "Jēls PCM audio" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Jēls %d-bitu plÅ«stošā punkta audio" + +msgid "Raw floating-point audio" +msgstr "Jēls plÅ«stošā punkta audio" + +msgid "Audio CD source" +msgstr "Audio CD avots" + +msgid "DVD source" +msgstr "DVD avots" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Tiešās straumēšanas protokola (RTSP) avots" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Mediju Servera (MMS) protokola avots" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokola avots" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video RTP izkrāvējs" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audio RTP izskrāvējs" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP izkrāvējs" + +#, c-format +msgid "%s demuxer" +msgstr "%s atjaucējs" + +#, c-format +msgid "%s decoder" +msgstr "%s atkodētājs" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video RTP iekrāvējs" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audio RTP iekrāvējs" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP iekrāvējs" + +#, c-format +msgid "%s muxer" +msgstr "%s jaucējs" + +#, c-format +msgid "%s encoder" +msgstr "%s kodētājs" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer elements %s" + +msgid "Unknown source element" +msgstr "Nezināms avota elements" + +msgid "Unknown sink element" +msgstr "Nezināms iegremdēšanas elements" + +msgid "Unknown element" +msgstr "Nezināms elements" + +msgid "Unknown decoder element" +msgstr "Nezināms atkodētāja elements" + +msgid "Unknown encoder element" +msgstr "Nezināms kodētāja elements" + +msgid "Plugin or element of unknown type" +msgstr "Nezināma veida spraudnis vai elements" + +msgid "No device specified." +msgstr "Nav norādÄ«ta ierÄ«ce." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "IerÄ«ce \"%s\" neeksistē." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "IerÄ«ce \"%s\" jau tiek izmantota." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nevarēja atvērt ierÄ«ci \"%s\" lasÄ«Å¡anai vai rakstÄ«Å¡anai." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Nav iespējams izveidot \"decodebin2\" elementu." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Nav iespējams izveidot \"queue2\" elementu." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Nav iespējams izveidot \"typefind\" elementu." + +#~ msgid "Can't play a text subtitles and subpictures." +#~ msgstr "Nevar atskaņot teksta subtitrus un subattēlus." + +#~ msgid "No file name specified." +#~ msgstr "Nav norādÄ«ts faila nosaukums." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Nav iespējams atvērt failu \"%s\" lasÄ«Å¡anai." diff --git a/gst-plugins-base-subtitles0.10/po/nb.po b/gst-plugins-base-subtitles0.10/po/nb.po new file mode 100644 index 0000000..6bc18e5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/nb.po @@ -0,0 +1,600 @@ +# Norwegian bokmaal translation of gst-utils. +# This file is put in the public domain. +# Kjartan Maraas , 2004-2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-10-24 21:44+0200\n" +"Last-Translator: Kjartan Maraas \n" +"Language-Team: Norwegian Bokmaal \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgid "Master" +msgstr "Hovedvolum" + +msgid "Bass" +msgstr "Bass" + +msgid "Treble" +msgstr "Diskant" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Linje inn" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC-høyttaler" + +msgid "Playback" +msgstr "Spill av" + +msgid "Capture" +msgstr "Ta opp" + +msgid "Could not open device for playback in mono mode." +msgstr "Kunne ikke Ã¥pne enheten for avspilling i mono-modus." + +msgid "Could not open device for playback in stereo mode." +msgstr "Kunne ikke Ã¥pne enheten for avspilling i stereo-modus." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +#, fuzzy +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +msgid "Could not open audio device for playback." +msgstr "Kunne ikke Ã¥pne lydenheten for avspilling." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +msgid "Could not open audio device for recording." +msgstr "Kunne ikke Ã¥pne lydenheten for opptak." + +msgid "Could not open CD device for reading." +msgstr "Kunne ikke Ã¥pne CD-enheten for lesing." + +msgid "Could not seek CD." +msgstr "Kunne ikke søke pÃ¥ CD." + +msgid "Could not read CD." +msgstr "Kunne ikke lese CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Kunne ikke Ã¥pne VFS-fil «%s» for skriving: %s." + +msgid "No filename given" +msgstr "Ingen filnavn oppgitt" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Kunne ikke lukke VFS-fil «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Feil under skriving til fil «%s»." + +msgid "Internal data stream error." +msgstr "Intern feil i datastrøm." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Et %s-tillegg kreves for Ã¥ spille av denne strømmen, men det er ikke " +"installert." + +msgid "This appears to be a text file" +msgstr "Dette ser ut som en tekstfil" + +msgid "Could not determine type of stream" +msgstr "Kunne ikke bestemme type strøm." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Ugyldig URI «%s» til undertekst. Undertekst er slÃ¥tt av." + +msgid "No URI specified to play from." +msgstr "Ingen URI for avspilling oppgitt." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Ugyldig URI «%s»." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP-strømmer kan ikke spilles av ennå." + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "Kildeelement er ugyldig." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +msgid "This is not a media file" +msgstr "Dette er ikke en mediefil" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "Fant ikke volumkontroll" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "spor-ID" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "artist-ID" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "album-ID" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Denne CDen har ingen lydspor" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "Ukjent element for koding" + +msgid "Plugin or element of unknown type" +msgstr "Tillegg eller element av ukjent type" + +msgid "No device specified." +msgstr "Ingen enhet oppgitt." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Enhet «%s» eksisterer ikke." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Enhet «%s» er allerede i bruk." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Kunne ikke åpne enhet «%s» for lesing og skriving." diff --git a/gst-plugins-base-subtitles0.10/po/nl.po b/gst-plugins-base-subtitles0.10/po/nl.po new file mode 100644 index 0000000..adec69f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/nl.po @@ -0,0 +1,615 @@ +# translation of gst-plugins-base-0.10.32.2.po to Dutch +# This file is put in the public domain. +# +# Freek de Kruijf , 2007, 2008, 2009, 2010, 2011. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-27 00:12+0200\n" +"Last-Translator: Freek de Kruijf \n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.1\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +msgid "Master" +msgstr "Master" + +msgid "Bass" +msgstr "Lage tonen" + +msgid "Treble" +msgstr "Hoge tonen" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Lijn-in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Microfoon" + +msgid "PC Speaker" +msgstr "PC-luidspreker" + +msgid "Playback" +msgstr "Afspelen" + +msgid "Capture" +msgstr "Opnemen" + +msgid "Could not open device for playback in mono mode." +msgstr "Kan het apparaat niet openen voor afspelen in mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Kan het apparaat niet openen voor afspelen in stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Kan het apparaat niet openen voor afspelen in %d-kanalen." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Kan het audio-apparaat niet openen voor afspelen. Apparaat is in gebruik bij " +"een andere applicatie." + +msgid "Could not open audio device for playback." +msgstr "Kan het audio-apparaat niet openen voor afspelen." + +msgid "Could not open device for recording in mono mode." +msgstr "Kan het apparaat niet openen in mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Kan het apparaat niet openen voor opnemen in stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Kan het apparaat niet openen voor opnemen in %d-kanalen." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Kan het audio-apparaat niet openen voor opnemen. Apparaat is in gebruik bij " +"een andere applicatie." + +msgid "Could not open audio device for recording." +msgstr "Kan het audio-apparaat niet openen voor opnemen." + +msgid "Could not open CD device for reading." +msgstr "Kan het CD-apparaat niet openen om te lezen." + +msgid "Could not seek CD." +msgstr "Kan geen seek doen op CD." + +msgid "Could not read CD." +msgstr "Kan niet lezen van CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Kon het VFS-bestand \"%s\" niet openen om te schrijven: %s." + +msgid "No filename given" +msgstr "Geen bestandsnaam opgegeven" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Kan het VFS-bestand \"%s\" niet sluiten." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fout bij het schrijven naar bestand \"%s\"." + +msgid "Internal data stream error." +msgstr "Interne fout in gegevensstroom." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Een %s plugin is vereist voor het afspelen van deze gegevens, echter deze is " +"niet geïnstalleerd." + +msgid "This appears to be a text file" +msgstr "Dit lijkt een tekstbestand te zijn" + +msgid "Could not determine type of stream" +msgstr "Kan het type stream niet bepalen" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Ongeldige ondertitel-URI \"%s\"; ondertitels zijn uitgezet." + +msgid "No URI specified to play from." +msgstr "Geen URI opgegeven om van af te spelen." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Ongeldige URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP-gegevensstromen zijn nog niet af te spelen." + +msgid "Could not create \"decodebin\" element." +msgstr "Kan \"decodebin\"-element niet aanmaken." + +msgid "Source element is invalid." +msgstr "Bronelement is ongeldig." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Er is alleen een ondertitelgegevensstroom gedetecteerd. Ofwel bent u een " +"ondertitelbestand of een ander type tekstbestand aan het laden, of het " +"mediabestand is niet herkend." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"U hebt geen decoder geïnstalleerd voor dit bestand. U moet mogelijk de " +"noodzakelijke plugins installeren." + +msgid "This is not a media file" +msgstr "Dit is geen mediabestand." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Een ondertitelstroom is gedetecteerd, maar geen videostroom." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "De elementen 'autovideosink' en 'xvimagesink' ontbreken beide." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Ontbrekend element '%s' - controleer de instalatie van uw GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "De elementen 'autoaudiosink' en 'alsasink' ontbreken beide." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "De elementen 'autovideosink' en '%s' ontbreken beide." + +msgid "The autovideosink element is missing." +msgstr "Het element 'autovideosink' ontbreekt." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Het geconfigureerde videosink %s werkt niet." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "De elementen 'autovideosink' en '%s' werken beide niet." + +msgid "The autovideosink element is not working." +msgstr "Het element 'autovideosink' werkt niet." + +msgid "Custom text sink element is not usable." +msgstr "De aangepaste element 'tekst-sink' is niet bruikbaar." + +msgid "No volume control found" +msgstr "Geen volumecontrole gevonden" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "De elementen 'autoaudiosink' en '%s' ontbreken beide." + +msgid "The autoaudiosink element is missing." +msgstr "Het element 'autoaudiosink' ontbreekt." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Het geconfigureerde audiosink %s werkt niet." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "De elementen 'autoaudiosink' en '%s' werken beide niet." + +msgid "The autoaudiosink element is not working." +msgstr "Het element 'autoaudiosink' werkt niet." + +msgid "Can't play a text file without video or visualizations." +msgstr "Kan geen tekstbestand afspelen zonder video of visualisaties." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Geen decoder beschikbaar voor het type '%s'." + +msgid "This stream type cannot be played yet." +msgstr "Deze stroom kan nog niet afgespeeld worden." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Geen URI-handler geïmplementeerd voor \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Fout bij het zenden van gegevens naar \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Fout tijdens het zenden van gdp-headergegevens naar \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Fout tijdens het zenden van gdp-gegevens naar \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Verbinding naar %s:%d is geweigerd." + +msgid "Can't record audio fast enough" +msgstr "Kan geluid niet snel genoeg opslaan" + +msgid "Failed to read tag: not enough data" +msgstr "Lezen van tag is mislukt: niet genoeg gegevens" + +msgid "track ID" +msgstr "track-ID" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz track-ID" + +msgid "artist ID" +msgstr "artiest-ID" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz artiest-ID" + +msgid "album ID" +msgstr "album-ID" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz album-ID" + +msgid "album artist ID" +msgstr "album-artiest-ID" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz album-artiest-ID" + +msgid "track TRM ID" +msgstr "track-TRM-ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM-ID" + +msgid "capturing shutter speed" +msgstr "sluitersnelheid bij het maken" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Gebruikte sluitersnelheid bij het maken van een foto, in seconden" + +msgid "capturing focal ratio" +msgstr "F-nummer bij maken" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Gebruikte F-nummer bij het maken van de foto" + +msgid "capturing focal length" +msgstr "brandpuntsafstand bij maken" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" +"Ge bruikte brandpuntsafstand van de lens bij het maken van de foto, in mm" + +msgid "capturing digital zoom ratio" +msgstr "digitale zoom-verhouding bij het maken" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Gebruikte digitale zoom-verhouding bij het maken van een foto" + +msgid "capturing iso speed" +msgstr "ISO-snelheid bij het maken" + +msgid "The ISO speed used when capturing an image" +msgstr "Gebruikte ISO-snelheid bij het maken van een foto" + +msgid "capturing exposure program" +msgstr "belichtingsprogramma bij het maken" + +msgid "The exposure program used when capturing an image" +msgstr "Gebruikte belichtingsprogramma bij het maken van een foto" + +msgid "capturing exposure mode" +msgstr "belichtingmodus bij het maken" + +msgid "The exposure mode used when capturing an image" +msgstr "Gebruikte belichtingmodus bij het maken van een foto" + +msgid "capturing exposure compensation" +msgstr "belichtingscompensatie bij het maken" + +msgid "The exposure compensation used when capturing an image" +msgstr "Gebruikte belichtingscompensatie bij het maken van een foto" + +msgid "capturing scene capture type" +msgstr "type scene-opname bij het maken" + +msgid "The scene capture mode used when capturing an image" +msgstr "Gebruikte type scene-opname bij het maken van een foto" + +msgid "capturing gain adjustment" +msgstr "aanpassing versterking bij het maken" + +msgid "The overall gain adjustment applied on an image" +msgstr "Gebruikte aanpassing versterking bij het maken van een foto" + +msgid "capturing white balance" +msgstr "witbalans bij het maken" + +msgid "The white balance mode set when capturing an image" +msgstr "Gebruikte witbalans bij het maken van een foto" + +msgid "capturing contrast" +msgstr "contrast bij het maken" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" +"De richting van de contrastbewerking toegepast bij het nemen van een foto" + +msgid "capturing saturation" +msgstr "verzadiging bij het nemen" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"De richting van de bewerking van de verzadiging toegepast bij het nemen van " +"een foto" + +msgid "capturing sharpness" +msgstr "scherpte bij het nemen" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" +"De richting van de scherptebewerking toegepast bij het nemen van een foto" + +msgid "capturing flash fired" +msgstr "flitser gebruikt bij het nemen" + +msgid "If the flash fired while capturing an image" +msgstr "Of de flitser is gebruikt bij het nemen van een foto" + +msgid "capturing flash mode" +msgstr "flitsmodus bij het nemen" + +msgid "The selected flash mode while capturing an image" +msgstr "Geselecteerde flitsmodus bij het nemen van een foto" + +msgid "capturing metering mode" +msgstr "meetmethode bij het nemen" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Gebruikte meetmethode bij het bepalen van de belichting voor het nemen van " +"een foto" + +msgid "capturing source" +msgstr "opnameapparaat bij het nemen" + +msgid "The source or type of device used for the capture" +msgstr "Het gebruikte opnameapparaat of type apparaat voor het nemen" + +msgid "image horizontal ppi" +msgstr "horizontale ppi van afbeelding" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Voorgenomen horizontale pixeldichtheid van medium (afbeelding/video) in ppi" + +msgid "image vertical ppi" +msgstr "verticale ppi van afbeelding" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Voorgenomen verticale pixeldichtheid van medium (afbeelding/video) in ppi" + +msgid "This CD has no audio tracks" +msgstr "Deze CD heeft geen audiotracks" + +msgid "ID3 tag" +msgstr "ID3-tag" + +msgid "APE tag" +msgstr "APE-tag" + +msgid "ICY internet radio" +msgstr "ICY-internetradio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Niet-gecomprimeerde grijze afbeelding" + +msgid "Run-length encoding" +msgstr "Run-length encoding (RLE)" + +msgid "Sami subtitle format" +msgstr "Sami ondertitelformaat" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer ondertitelformaat" + +msgid "Kate subtitle format" +msgstr "Kate ondertitelformaat" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Niet-gecomprimeerde planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Niet-gecomprimeerde planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Niet-gecomprimeerde packed YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Niet-gecomprimeerde packed YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Niet-gecomprimeerde packed YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Niet-gecomprimeerde packed YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Niet-gecomprimeerde packed YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Niet-gecomprimeerde planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Niet-gecomprimeerde planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Niet-gecomprimeerd zwartwit Y-vlak" + +msgid "Uncompressed YUV" +msgstr "Niet-gecomprimeerde YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Niet-gecomprimeerde, gepaletteerde %d-bits %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versie %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Raw %d-bits PCM-audio" + +msgid "Raw PCM audio" +msgstr "Raw PCM-audio" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Raw %d-bits drijvendekomma-audio" + +msgid "Raw floating-point audio" +msgstr "Raw drijvendekomma-audio" + +msgid "Audio CD source" +msgstr "Audio-CD-bron" + +msgid "DVD source" +msgstr "DVD-bron" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol (RTSP)-bron" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server (MMS) protocol-bron" + +#, c-format +msgid "%s protocol source" +msgstr "%s protocol-bron" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video-RTP-depayloader" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audio-RTP-depayloader" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP-depayloader" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s decoder" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video-RTP-payloader" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audio-RTP-payloader" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP-payloader" + +#, c-format +msgid "%s muxer" +msgstr "%s muxer" + +#, c-format +msgid "%s encoder" +msgstr "%s encoder" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer element %s" + +msgid "Unknown source element" +msgstr "Onbekend bronelement" + +msgid "Unknown sink element" +msgstr "Onbekend bestemmingselement" + +msgid "Unknown element" +msgstr "Onbekend element" + +msgid "Unknown decoder element" +msgstr "Onbekend decoder-element" + +msgid "Unknown encoder element" +msgstr "Onbekend encoder-element" + +msgid "Plugin or element of unknown type" +msgstr "Plugin of element van onbekend type" + +msgid "No device specified." +msgstr "Geen apparaat opgegeven." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Apparaat \"%s\" bestaat niet." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Apparaat \"%s\" is al in gebruik." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Kan apparaat \"%s\" niet openen voor lezen en schrijven." diff --git a/gst-plugins-base-subtitles0.10/po/or.po b/gst-plugins-base-subtitles0.10/po/or.po new file mode 100644 index 0000000..eaee60b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/or.po @@ -0,0 +1,757 @@ +# Oriya translation of gst-plugins-0.8.3.pot. +# Copyright (C) 2004, Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-0.8.3 package. +# Gora Mohanty , 2004. +# $Id$ +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-0.8.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-09-27 13:32+0530\n" +"Last-Translator: Gora Mohanty \n" +"Language-Team: Oriya \n" +"Language: or\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "ଅନୁଚ୍ଚ ସ୍ବର" + +msgid "Treble" +msgstr "ଉଚ୍ଚ ସ୍ବର" + +msgid "PCM" +msgstr "ପି.ସି.ଏମ." + +msgid "Synth" +msgstr "ସିନ୍ଥେସାଇଜର" + +msgid "Line-in" +msgstr "ଲାଇନ-ଇନ" + +msgid "CD" +msgstr "ସି.ଡି." + +msgid "Microphone" +msgstr "ମାଇକ୍ରୋଫୋନ୍" + +#, fuzzy +msgid "PC Speaker" +msgstr "ସ୍ବରବର୍ଦ୍ଧକ ୟନ୍ତ୍ର" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "\"%s\" ଧ୍ବନି ଯନ୍ତ୍ର ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "\"%s\" ଯନ୍ତ୍ର ପଢ଼ିବା ଓ ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +msgid "Could not open CD device for reading." +msgstr "ସି.ଡି. ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not seek CD." +msgstr "ଭି.ଏଫ.ଏସ. ଫାଇଲ \"%s\" ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#, fuzzy +msgid "Could not read CD." +msgstr "\"%s\" ଯନ୍ତ୍ରରେ ଲେଖିହେଲା ନାହିଁ." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "ଭି.ଏଫ.ଏସ. ଫାଇଲ \"%s\" ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ: %s." + +msgid "No filename given" +msgstr "କୌଣସି ଫାଇଲନାମ ଦିଆଯାଇ ନାହିଁ" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "ଭି.ଏଫ.ଏସ. ଫାଇଲ \"%s\" ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "\"%s\" ଫାଇଲ ବନ୍ଦ କରିବାରେ ତ୍ରୁଟି." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "\"%s\" ଫାଇଲ ଲେଖିହେଲା ନାହିଁ." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "\"%s\" ଯନ୍ତ୍ର ଗୋଟିଏ ଅନୁଲିପିକାର ନୁହେଁ." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "\"%s\" ଫାଇଲ ବନ୍ଦ କରିବାରେ ତ୍ରୁଟି." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "କୌଣସି ଯନ୍ତ୍ର ଉଲ୍ଲେଖିତ କରାଯାଇ ନାହିଁ." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "\"%s\" ଯନ୍ତ୍ର ଅବସ୍ଥିତ ନାହିଁ." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "\"%s\" ଓ.ଏସ.ଏସ. ଯନ୍ତ୍ର ପୂର୍ବରୁ ଅନ୍ଯ କାରିକା ଦ୍ବାରା ବ୍ଯବହାର କରାଯାଉଛି." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "\"%s\" ଯନ୍ତ୍ର ପଢ଼ିବା ଓ ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "\"%s\" ଫାଇଲ ଲେଖିହେଲା ନାହିଁ." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "କୌଣସି ଯନ୍ତ୍ର ଉଲ୍ଲେଖିତ କରାଯାଇ ନାହିଁ." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "ଭି.ଏଫ.ଏସ. ଫାଇଲ \"%s\" ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "\"%s\" ଫାଇଲ ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +#~ msgid "No file name specified." +#~ msgstr "କୌଣସି ଫାଇଲନାମ ଉଲ୍ଲେଖିତ ହୋଇ ନାହିଁ." + +#~ msgid "Device is not open." +#~ msgstr "ଯନ୍ତ୍ର ଖୋଲାଯାଇ ନାହିଁ." + +#~ msgid "Device is open." +#~ msgstr "ଯନ୍ତ୍ର ଖୋଲାଯାଇଚ୍ଛି." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "ଭି.ଏଫ.ଏସ. ଫାଇଲ \"%s\" ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "କୌଣସି ଫାଇଲନାମ ଦିଆଯାଇ ନାହିଁ" + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "\"%s\" ଫାଇଲ ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "ନିବେଶ ଧ୍ବନି ନାହିଁ ବା ଅବୈଧ ଅଛି. ଏ.ଭି.ଆଇ. ଧାରା ଭ୍ରଷ୍ଟ ହୋଇଯିବ." + +#~ msgid "" +#~ "The %s element could not be found. This element is essential for " +#~ "playback. Please install the right plug-in and verify that it works by " +#~ "running 'gst-inspect %s'" +#~ msgstr "" +#~ "%s ଉପାଦାନ ମିଳିଲା ନାହିଁ. ପୁନଃପ୍ରଦର୍ଶନ ପାଇଁ ଏହି ଉପାଦାନଟି ଆବଶ୍ଯକ. ଦୟା କରି ସଠିକ ପ୍ଲଗ୍ଇନ୍ " +#~ "ସ୍ଥାପିତ କରନ୍ତୁ, ଓ 'gst-inspect %s' ଚଳାଇ ଯାଞ୍ଚ କରନ୍ତୁ କି ଏହା କାର୍ଯ୍ଯକାରୀ ଅଛି" + +#~ msgid "" +#~ "No usable colorspace element could be found.\n" +#~ "Please install one and restart." +#~ msgstr "" +#~ "କୌଣସି ବ୍ଯବହାରଯୋଗ୍ଯ ରଙ୍ଗକ୍ଷେତ୍ର ଉପାଦାନ ମିଳିଲା ନାହିଁ.\n" +#~ "ଦୟା କରି ଗୋଟିଏ ଉପାଦାନ ସ୍ଥାପିତ କରି ପୁନଃପ୍ରାରମ୍ଭ କରନ୍ତୁ." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "\"%s\" ନିୟନ୍ତ୍ରଣ ଯନ୍ତ୍ର ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "\"%s\" ଧ୍ବନି ଯନ୍ତ୍ର ବିନ୍ଯାସ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "\"%s\" ଧ୍ବନି ଯନ୍ତ୍ରକୁ %d ହର୍ଜରେ ବିନ୍ଯାସ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "\"%s\" ଧ୍ବନି ଯନ୍ତ୍ର ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "\"%s\" ନିୟନ୍ତ୍ରଣ ଯନ୍ତ୍ର ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "\"%s\" ଭିଡିଓ ଯନ୍ତ୍ର ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "\"%s\" ଭିଡିଓ ଯନ୍ତ୍ର ବନ୍ଦ କରିହେଲା ନାହିଁ." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "\"%s\" ଯନ୍ତ୍ର ବ୍ଯବହାର କରିହେଲା ନାହିଁ, ତାହାର ଅନୁମତି ଦେଖନ୍ତୁ." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "\"%s\" ଯନ୍ତ୍ର ଲେଖିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "\"%s\" ଯନ୍ତ୍ର ପଢ଼ିବା ପାଇଁ ଖୋଲିହେଲା ନାହିଁ." + +#, fuzzy +#~ msgid "Your OSS device doesn't support mono or stereo." +#~ msgstr "ଆପଣଙ୍କର ଓ.ଏସ.ଏସ. ଯନ୍ତ୍ରର ଠିକ ଭାବରେ ଅନୁସନ୍ଧାନ କରିହେଲା ନାହିଁ." + +#~ msgid "Your OSS device could not be probed correctly" +#~ msgstr "ଆପଣଙ୍କର ଓ.ଏସ.ଏସ. ଯନ୍ତ୍ରର ଠିକ ଭାବରେ ଅନୁସନ୍ଧାନ କରିହେଲା ନାହିଁ." + +#~ msgid "Volume" +#~ msgstr "ପ୍ରବଳତା" + +#~ msgid "Speaker" +#~ msgstr "ସ୍ବରବର୍ଦ୍ଧକ ୟନ୍ତ୍ର" + +#~ msgid "Mixer" +#~ msgstr "ମିଶ୍ରଣ ଯନ୍ତ୍ର" + +#~ msgid "PCM-2" +#~ msgstr "ପି.ସି.ଏମ.-୨" + +#~ msgid "Record" +#~ msgstr "ଅନୁଲିପିକରଣ" + +#~ msgid "In-gain" +#~ msgstr "ନିବେଶ-ବୃଦ୍ଧି" + +#~ msgid "Out-gain" +#~ msgstr "ନିର୍ଗମ-ବୃଦ୍ଧି" + +#~ msgid "Line-1" +#~ msgstr "ଲାଇନ-୧" + +#~ msgid "Line-2" +#~ msgstr "ଲାଇନ-୨" + +#~ msgid "Line-3" +#~ msgstr "ଲାଇନ-୩" + +#~ msgid "Digital-1" +#~ msgstr "ସାଂଖ୍ଯିକ-୧" + +#~ msgid "Digital-2" +#~ msgstr "ସାଂଖ୍ଯିକ-୨" + +#~ msgid "Digital-3" +#~ msgstr "ସାଂଖ୍ଯିକ-୩" + +#~ msgid "Phone-in" +#~ msgstr "ଫୋନ-ନିବେଶ" + +#~ msgid "Phone-out" +#~ msgstr "ଫୋନ-ନିର୍ଗମ" + +#~ msgid "Video" +#~ msgstr "ଭିଡିଓ" + +#~ msgid "Radio" +#~ msgstr "ରେଡିଓ" + +#~ msgid "Monitor" +#~ msgstr "ପ୍ରଦର୍ଶିକା" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "\"%s\" ଯନ୍ତ୍ରରୁ ଅସ୍ଥାୟୀ ସଞ୍ଚୟ ସ୍ଥାନ ଆଣିହେଲା ନାହିଁ." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "\"%s\" ଯନ୍ତ୍ରରୁ ପର୍ଯ୍ଯାପ୍ତ ଅସ୍ଥାୟୀ ସଞ୍ଚୟ ସ୍ଥାନ ଆଣିହେଲା ନାହିଁ." diff --git a/gst-plugins-base-subtitles0.10/po/pl.po b/gst-plugins-base-subtitles0.10/po/pl.po new file mode 100644 index 0000000..75a5526 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/pl.po @@ -0,0 +1,611 @@ +# Polish translation for gst-plugins-base. +# This file is distributed under the same license as the gst-plugins-base package. +# Jakub Bogusz , 2007-2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-26 18:01+0200\n" +"Last-Translator: Jakub Bogusz \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Główny" + +msgid "Bass" +msgstr "Niskie" + +msgid "Treble" +msgstr "Wysokie" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Syntezator" + +msgid "Line-in" +msgstr "Wejście" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "Głośnik PC" + +msgid "Playback" +msgstr "Odtwarzanie" + +msgid "Capture" +msgstr "Nagrywanie" + +msgid "Could not open device for playback in mono mode." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do odtwarzania w trybie mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do odtwarzania w trybie stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do odtwarzania w trybie %d-" +"kanałowym." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do odtwarzania. Urządzenie " +"jest używane przez inną aplikację." + +msgid "Could not open audio device for playback." +msgstr "Nie udało się otworzyć urządzenia dźwiękowego do odtwarzania." + +msgid "Could not open device for recording in mono mode." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do nagrywania w trybie mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do nagrywania w trybie stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do nagrywania w trybie %d-" +"kanałowym." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nie udało się otworzyć urządzenia dźwiękowego do nagrywania. Urządzenie jest " +"używane przez inną aplikację." + +msgid "Could not open audio device for recording." +msgstr "Nie udało się otworzyć urządzenia dźwiękowego do nagrywania." + +msgid "Could not open CD device for reading." +msgstr "Nie udało się otworzyć urządzenia CD do odczytu." + +msgid "Could not seek CD." +msgstr "Nie udało się ustawić położenia na CD." + +msgid "Could not read CD." +msgstr "Nie udał się odczyt CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nie udało się otworzyć pliku vfs \"%s\" do zapisu: %s." + +msgid "No filename given" +msgstr "Nie podano nazwy pliku" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nie udało się zamknąć pliku vfs \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Błąd podczas zapisu do pliku \"%s\"." + +msgid "Internal data stream error." +msgstr "Błąd wewnętrzny strumienia danych." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Wtyczka %s jest wymagana do otworzenia tego strumienia, ale nie jest " +"zainstalowana." + +msgid "This appears to be a text file" +msgstr "To wygląda na plik tekstowy" + +msgid "Could not determine type of stream" +msgstr "Nie udało się określić typu strumienia" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Niepoprawne URI podpisów \"%s\", podpisy wyłączone." + +msgid "No URI specified to play from." +msgstr "Nie podano URI do odtwarzania." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Niepoprawne URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "Strumieni RTSP jeszcze nie można odtwarzać." + +msgid "Could not create \"decodebin\" element." +msgstr "Nie udało się utworzyć elementu \"decodebin\"." + +msgid "Source element is invalid." +msgstr "Element źródłowy jest niepoprawny." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Wykryto tylko strumień podpisów. Albo żądano wczytania pliku podpisów lub " +"innego rodzaju pliku tekstowego, albo nie rozpoznano pliku multimedialnego." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Nie ma zainstalowanego dekodera do obsługi tego pliku. Być może trzeba " +"zainstalować potrzebne wtyczki." + +msgid "This is not a media file" +msgstr "To nie jest plik multimedialny" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Wykryto strumień podpisów, ale brak strumienia obrazu." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Nie ma żadnego z elementów autovideosink i xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Brak elementu '%s' - proszę sprawdzić instalację GStreamera." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Nie ma żadnego z elementów autoaudiosink i alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Nie ma żadnego z elementów autovideosink i %s." + +msgid "The autovideosink element is missing." +msgstr "Nie ma elementu autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Skonfigurowany element videosink %s nie działa." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Żaden z elementów autovideosink i %s nie działa." + +msgid "The autovideosink element is not working." +msgstr "Element autovideosink nie działa." + +msgid "Custom text sink element is not usable." +msgstr "Własny element text sink nie jest użyteczny." + +msgid "No volume control found" +msgstr "Nie znaleziono sterowania głośnością" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Nie ma żadnego z elementów autoaudiosink i %s." + +msgid "The autoaudiosink element is missing." +msgstr "Nie ma elementu autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Skonfigurowany element audiosink %s nie działa." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Żaden z elementów autoaudiosink i %s nie działa." + +msgid "The autoaudiosink element is not working." +msgstr "Element autoaudiosink nie działa." + +msgid "Can't play a text file without video or visualizations." +msgstr "Nie można odtwarzać pliku tekstowego bez obrazu lub wizualizacji." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Brak dostępnego dekodera dla typu '%s'." + +msgid "This stream type cannot be played yet." +msgstr "Tego strumienia jeszcze nie można odtworzyć." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nie ma zaimplementowanej obsługi URI dla \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Błąd podczas wysyłania danych do \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Błąd podczas wysyłania danych nagłówka gdp do \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Błąd podczas wysyłania danych gdp do \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Połączenie z %s:%d odrzucone." + +msgid "Can't record audio fast enough" +msgstr "Nie można zapisywać danych dźwiękowych wystarczająco szybko" + +msgid "Failed to read tag: not enough data" +msgstr "Nie udało się odczytać znacznika: za mało danych" + +msgid "track ID" +msgstr "ID ścieżki" + +msgid "MusicBrainz track ID" +msgstr "ID ścieżki wg MusicBrainz" + +msgid "artist ID" +msgstr "ID artysty" + +msgid "MusicBrainz artist ID" +msgstr "ID artysty wg MusicBrainz" + +msgid "album ID" +msgstr "ID albumu" + +msgid "MusicBrainz album ID" +msgstr "ID albumu wg MusicBrainz" + +msgid "album artist ID" +msgstr "ID artysty albumu ID" + +msgid "MusicBrainz album artist ID" +msgstr "ID artysty albumu wg MusicBrainz" + +msgid "track TRM ID" +msgstr "TRM ID ścieżki" + +msgid "MusicBrainz TRM ID" +msgstr "TRM ID wg MusicBrainz" + +msgid "capturing shutter speed" +msgstr "szybkość migawki" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Szybkość migawki zastosowana przy robieniu zdjęcia, w sekundach" + +msgid "capturing focal ratio" +msgstr "współczynnik przysłony" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Przysłona (liczba f) użyta przy robieniu zdjęcia" + +msgid "capturing focal length" +msgstr "ogniskowa obiektywu" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Długość ogniskowej obiektywu użyta przy robieniu zdjęcia, w mm" + +msgid "capturing digital zoom ratio" +msgstr "współczynnik powiększenia cyfrowego" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Współczynnik powiększenia cyfrowego użytego przy robieniu zdjęcia" + +msgid "capturing iso speed" +msgstr "czyłość ISO" + +msgid "The ISO speed used when capturing an image" +msgstr "Czułość ISO użyta przy robieniu zdjęcia" + +msgid "capturing exposure program" +msgstr "program ekspozycji" + +msgid "The exposure program used when capturing an image" +msgstr "Program ekspozycji użyty przy robieniu zdjęcia" + +msgid "capturing exposure mode" +msgstr "tryb ekspozycji" + +msgid "The exposure mode used when capturing an image" +msgstr "Tryb ekspozycji użyty przy robieniu zdjęcia" + +msgid "capturing exposure compensation" +msgstr "kompensacja ekspozycji" + +msgid "The exposure compensation used when capturing an image" +msgstr "Kompensacja ekspozycji użyta przy robieniu zdjęcia" + +msgid "capturing scene capture type" +msgstr "Tyb sceny zdjęcia" + +msgid "The scene capture mode used when capturing an image" +msgstr "Tryb sceny użyty przy robieniu zdjęcia" + +msgid "capturing gain adjustment" +msgstr "korekcja zdjęcia" + +msgid "The overall gain adjustment applied on an image" +msgstr "Całkowita korekcja zastosowana dla zdjęcia" + +msgid "capturing white balance" +msgstr "balans bieli" + +msgid "The white balance mode set when capturing an image" +msgstr "Tryb balansu bieli ustawiony przy robieniu zdjęcia" + +msgid "capturing contrast" +msgstr "kontrast zdjęcia" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Kierunek korekty kontrastu zastosowanej przy robieniu zdjęcia" + +msgid "capturing saturation" +msgstr "nasycenie zdjęcia" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Kierunek korekty nasycenia zastosowanej przy robieniu zdjęcia" + +msgid "capturing sharpness" +msgstr "ostrość zdjęcia" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Kierunek korekty ostrości zastosowanej przy robieniu zdjęcia" + +msgid "capturing flash fired" +msgstr "użycie flesza" + +msgid "If the flash fired while capturing an image" +msgstr "Czy flesz był uruchomiony przy robieniu zdjęcia" + +msgid "capturing flash mode" +msgstr "tryb flesza" + +msgid "The selected flash mode while capturing an image" +msgstr "Tryb flesza wybrany przy robieniu zdjęcia" + +msgid "capturing metering mode" +msgstr "tryb pomiaru dla zdjęcia" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Tryb pomiaru użyty przy określaniu ekspozycji dla zdjęcia" + +msgid "capturing source" +msgstr "źródło zdjęcia" + +msgid "The source or type of device used for the capture" +msgstr "Źródło lub rodzaj urządzenia użytego do zrobienia zdjęcia" + +msgid "image horizontal ppi" +msgstr "rozdzielczość pozioma" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Rozdzielczość pozioma nośnika w pikselach na cal" + +msgid "image vertical ppi" +msgstr "rozdzielczość pionowa" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Rozdzielczość pionowa nośnika w pikselach na cal" + +msgid "This CD has no audio tracks" +msgstr "Ta płyta CD nie ma ścieżek dźwiękowych" + +msgid "ID3 tag" +msgstr "Znacznik ID3" + +msgid "APE tag" +msgstr "Znacznik APE" + +msgid "ICY internet radio" +msgstr "Radio internetowe ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless (bezstratne CYUV)" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Nieskompresowany obraz w szarości" + +msgid "Run-length encoding" +msgstr "Kodowanie RLE" + +msgid "Sami subtitle format" +msgstr "Format podpisów Sami" + +msgid "TMPlayer subtitle format" +msgstr "Format podpisów TMPlayer" + +msgid "Kate subtitle format" +msgstr "Format podpisów Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nieskompresowany planarny YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nieskompresowany planarny YUV 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nieskompresowany spakowany YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nieskompresowany spakowany YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nieskompresowany spakowany YUV 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nieskompresowany spakowany YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nieskompresowany spakowany YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nieskompresowany planarny YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nieskompresowany planarny YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nieskompresowany czarno-biały plan Y" + +msgid "Uncompressed YUV" +msgstr "Nieskompresowany YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nieskompresowany %d-bitowy %s z paletą" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 w wersji %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Surowe %d-bitowy dźwięk PCM" + +msgid "Raw PCM audio" +msgstr "Surowy dźwięk PCM" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Surowy %d-bitowy dźwięk zmiennoprzecinkowy" + +msgid "Raw floating-point audio" +msgstr "Surowy dźwięk zmiennoprzecinkowy" + +msgid "Audio CD source" +msgstr "Źródło Audio CD" + +msgid "DVD source" +msgstr "Źródło DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Źródło RTSP (Real Time Streaming Protocol)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Źródło protokołu MMS (Microsoft Media Server)" + +#, c-format +msgid "%s protocol source" +msgstr "Źródło protokołu %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Depayloader obrazu RTP %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Depayloader dźwięku RTP %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Depayloader RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Demuxer %s" + +#, c-format +msgid "%s decoder" +msgstr "Dekoder %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Payloader obrazu RTP %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Payloader dźwięku RTP %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "Payloader RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Muxer %s" + +#, c-format +msgid "%s encoder" +msgstr "Koder %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Element GStreamera %s" + +msgid "Unknown source element" +msgstr "Nieznany element źródłowy" + +msgid "Unknown sink element" +msgstr "Nieznany element pochłaniający" + +msgid "Unknown element" +msgstr "Nieznany element" + +msgid "Unknown decoder element" +msgstr "Nieznany element dekodujący" + +msgid "Unknown encoder element" +msgstr "Nieznany element kodujący" + +msgid "Plugin or element of unknown type" +msgstr "Wtyczka lub element nieznanego typu" + +msgid "No device specified." +msgstr "Nie określono urządzenia." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Urządzenie \"%s\" nie istnieje." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Urządzenie \"%s\" jest już używane." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nie udało się otworzyć urządzenia \"%s\" do odczytu i zapisu." diff --git a/gst-plugins-base-subtitles0.10/po/pt_BR.po b/gst-plugins-base-subtitles0.10/po/pt_BR.po new file mode 100644 index 0000000..ed3875f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/pt_BR.po @@ -0,0 +1,645 @@ +# Brazilian Portuguese translation of gst-plugins-base. +# Copyright (C) 2008-2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# Fabrício Godoy , 2008-2011. +# +# PCM -> PCM +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base-0.10.31.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2011-01-08 01:02-0300\n" +"Last-Translator: Fabrício Godoy \n" +"Language-Team: Brazilian Portuguese \n" +"Language: pt_BR\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +msgid "Master" +msgstr "Principal" + +msgid "Bass" +msgstr "Grave" + +msgid "Treble" +msgstr "Agudo" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizador" + +msgid "Line-in" +msgstr "Entrada de linha" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Microfone" + +msgid "PC Speaker" +msgstr "Alto-falante do PC" + +msgid "Playback" +msgstr "Reprodução" + +msgid "Capture" +msgstr "Captura" + +msgid "Could not open device for playback in mono mode." +msgstr "Não foi possível abrir o dispositivo para reprodução em mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Não foi possível abrir o dispositivo para reprodução em estéreo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Não foi possível abrir o dispositivo para reprodução com %d canal(is)." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Não foi possível abrir o dispositivo de áudio para reprodução. O dispositivo " +"está sendo usado por outro aplicativo." + +msgid "Could not open audio device for playback." +msgstr "Não foi possível abrir o dispositivo de áudio para reprodução." + +msgid "Could not open device for recording in mono mode." +msgstr "Não foi possível abrir o dispositivo para gravação em mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Não foi possível abrir o dispositivo para gravação em estéreo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Não foi possível abrir o dispositivo para gravação com %d canal(is)." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Não foi possível abrir o dispositivo de áudio para gravação. O dispositivo " +"está sendo usado por outro aplicativo." + +msgid "Could not open audio device for recording." +msgstr "Não foi possível abrir o dispositivo de áudio para gravação." + +msgid "Could not open CD device for reading." +msgstr "Não foi possível abrir o dispositivo de CD para leitura." + +msgid "Could not seek CD." +msgstr "Não foi possível buscar no CD." + +msgid "Could not read CD." +msgstr "Não foi possível ler o CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Não foi possível abrir o arquivo VFS \"%s\" para escrita: %s." + +msgid "No filename given" +msgstr "Não foi fornecido um nome de arquivo" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Não foi possível fechar o arquivo VFS \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Erro ao gravar no arquivo \"%s\"." + +msgid "Internal data stream error." +msgstr "Erro interno no fluxo de dados." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"O plug-in %s é necessário para reproduzir este fluxo, mas não está instalado." + +msgid "This appears to be a text file" +msgstr "Este parece ser um arquivo de texto" + +msgid "Could not determine type of stream" +msgstr "Não foi possível determinar o tipo de fluxo" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "O URI \"%s\" para legenda é inválido, legendas desabilitadas." + +msgid "No URI specified to play from." +msgstr "Nenhum URI especificado para reprodução." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "O URI \"%s\" é inválido." + +msgid "RTSP streams cannot be played yet." +msgstr "Os fluxos RTSP ainda não podem ser reproduzidos." + +msgid "Could not create \"decodebin\" element." +msgstr "Não foi possível criar o elemento \"decodebin\"." + +msgid "Source element is invalid." +msgstr "O elemente de origem é inválido." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Apenas um fluxo de legendas foi detectado. Ou você está carregando um " +"arquivo de legenda ou algum outro tipo de arquivo de texto, ou o arquivo de " +"mídia não é reconhecido." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Você não tem um decodificador instalado para manipular este arquivo. Você " +"deveria instalar os plug-ins necessários." + +msgid "This is not a media file" +msgstr "Este não é um arquivo de mídia" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Um fluxo de legenda foi detectado, mas nenhum fluxo de vídeo." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Os elementos autovideosink e xvimagesink estão faltando." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" +"O elemento \"%s\" está faltando, verifique a instalação do seu GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Os elementos autoaudiosink e alsasink estão faltando." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Os elementos autovideosink e %s estão faltando." + +msgid "The autovideosink element is missing." +msgstr "O elemento autovideosink está faltando." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "O videosink configurado %s não está funcionando." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Os elementos autovideosink e %s não estão funcionando." + +msgid "The autovideosink element is not working." +msgstr "O elemento autovideosink não está funcionando." + +msgid "Custom text sink element is not usable." +msgstr "O elemento consumidor personalizado de texto não é utilizável." + +msgid "No volume control found" +msgstr "Nenhum controle de volume encontrado" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Os elementos autoaudiosink e %s estão faltando." + +msgid "The autoaudiosink element is missing." +msgstr "O elemento autoaudiosink não está faltando." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "O audiosink configurado %s não está funcionando." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Os elementos autoaudiosink e %s não estão funcionando." + +msgid "The autoaudiosink element is not working." +msgstr "O elemento autoaudiosink não está funcionando." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Não é possível reproduzir um arquivo de texto sem vídeo ou visualização." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Decodificador não disponível para o tipo \"%s\"." + +msgid "This stream type cannot be played yet." +msgstr "Este tipo de fluxo ainda não pode ser reproduzido." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nenhum manipulador para o URI \"%s\" foi implementado." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Erro ao enviar dados para \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Erro ao enviar o cabeçalho de dados GDP para \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Erro ao enviar codificação de dados GDP para \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "A conexão para %s:%d foi recusada." + +msgid "Can't record audio fast enough" +msgstr "Não é possível gravar o áudio rápido suficiente" + +msgid "Failed to read tag: not enough data" +msgstr "Falha ao ler etiqueta: dados insuficientes" + +msgid "track ID" +msgstr "ident. da trilha" + +msgid "MusicBrainz track ID" +msgstr "ident. da trilha no MusicBrainz" + +msgid "artist ID" +msgstr "ident. do artista" + +msgid "MusicBrainz artist ID" +msgstr "ident. do artista no MusicBrainz" + +msgid "album ID" +msgstr "ident. do álbum" + +msgid "MusicBrainz album ID" +msgstr "ident. do álbum no MusicBrainz" + +msgid "album artist ID" +msgstr "ident. do artista do álbum" + +msgid "MusicBrainz album artist ID" +msgstr "ident. do artista do álbum no MusicBrainz" + +msgid "track TRM ID" +msgstr "ident. da trilha TRM" + +msgid "MusicBrainz TRM ID" +msgstr "ident. da trilha TRM no MusicBrainz" + +msgid "capturing shutter speed" +msgstr "velocidade do obturador ao capturar" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Velocidade do obturador usada ao capturar uma imagem, em segundos" + +msgid "capturing focal ratio" +msgstr "taxa focal ao capturar" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Taxa focal usada ao capturar a imagem, f-number" + +msgid "capturing focal length" +msgstr "distância focal ao capturar" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Distância focal das lentes usada ao capturar a imagem, em mm" + +msgid "capturing digital zoom ratio" +msgstr "taxa de zoom digital ao capturar" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Taxa de zoom digital usada ao capturar uma imagem" + +msgid "capturing iso speed" +msgstr "velocidade ISO ao capturar" + +msgid "The ISO speed used when capturing an image" +msgstr "A velocidade ISO usada ao capturar uma imagem" + +msgid "capturing exposure program" +msgstr "programa de exposição ao capturar" + +msgid "The exposure program used when capturing an image" +msgstr "O programa de exposição usado ao capturar uma imagem" + +msgid "capturing exposure mode" +msgstr "modo de exposição ao capturar" + +msgid "The exposure mode used when capturing an image" +msgstr "O modo de exposição usado ao capturar uma imagem" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "modo de exposição ao capturar" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "O modo de exposição usado ao capturar uma imagem" + +msgid "capturing scene capture type" +msgstr "tipo de captura de cena ao capturar" + +msgid "The scene capture mode used when capturing an image" +msgstr "O modo de captura de cena usado ao capturar uma imagem" + +msgid "capturing gain adjustment" +msgstr "ajuste de ganho ao capturar" + +msgid "The overall gain adjustment applied on an image" +msgstr "O ajuste de ganho geral aplicado na imagem" + +msgid "capturing white balance" +msgstr "balanço de branco ao capturar" + +msgid "The white balance mode set when capturing an image" +msgstr "O modo de balanço de branco definido ao capturar uma imagem" + +msgid "capturing contrast" +msgstr "contraste ao capturar" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" +"O procedimento de processamento de contraste aplicado ao capturar uma imagem" + +msgid "capturing saturation" +msgstr "saturação ao capturar" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" +"O procedimento de processamento de saturação aplicado ao capturar uma imagem" + +msgid "capturing sharpness" +msgstr "nitidez ao capturar" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" +"O procedimento de processamento de nitidez aplicado ao capturar uma imagem" + +msgid "capturing flash fired" +msgstr "disparar flash ao capturar" + +msgid "If the flash fired while capturing an image" +msgstr "Define se o flash é disparado ao capturar uma imagem" + +msgid "capturing flash mode" +msgstr "modo de flash ao capturar" + +msgid "The selected flash mode while capturing an image" +msgstr "O modo de flash selecionado ao capturar uma imagem" + +msgid "capturing metering mode" +msgstr "modo de medição de luz ao capturar" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"O modo de medição de luz usado ao determinar a exposição para captura de uma " +"imagem" + +msgid "capturing source" +msgstr "fonte ao capturar" + +msgid "The source or type of device used for the capture" +msgstr "A fonte ou tipo de dispositivo usado para a captura" + +msgid "image horizontal ppi" +msgstr "PPI horizontal da imagem" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Densidade de pixels horizontais desejado para a mídia (imagem/vídeo), em PPI" + +msgid "image vertical ppi" +msgstr "PPI vertical da imagem" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Densidade de pixels verticais desejado para a mídia (imagem/vídeo), em PPI" + +msgid "This CD has no audio tracks" +msgstr "Este CD não tem trilhas de áudio" + +msgid "ID3 tag" +msgstr "Etiqueta ID3" + +msgid "APE tag" +msgstr "Etiqueta APE" + +msgid "ICY internet radio" +msgstr "Rádio on-line ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Áudio Sem Perdas da Apple (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Codec Livre de Áudio Sem Perdas (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Áudio Real Sem Perdas (TTA)" + +msgid "Windows Media Speech" +msgstr "Mídia de Voz do Windows (WMS)" + +msgid "CYUV Lossless" +msgstr "CYUV Sem Perdas" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH Sem Perdas" + +msgid "Uncompressed Gray Image" +msgstr "Imagem Monocromática Sem Compressão" + +msgid "Run-length encoding" +msgstr "Codificação Run-length" + +msgid "Sami subtitle format" +msgstr "Formato de legendas Sami" + +msgid "TMPlayer subtitle format" +msgstr "Formato de legendas TMPlayer" + +msgid "Kate subtitle format" +msgstr "Formato de legendas Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 plano sem compressão" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YVU 4:2:0 plano sem compressão" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 empacotado sem compressão" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 empacotado sem compressão" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU 4:1:0 empacotado sem compressão" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 empacotado sem compressão" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 empacotado sem compressão" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 plano sem compressão" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 plano sem compressão" + +msgid "Uncompressed black and white Y-plane" +msgstr "Plano Y em preto e branco sem compressão" + +msgid "Uncompressed YUV" +msgstr "YUV sem compressão" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "%2$s de %1$d bits com paletas sem compressão" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Versão %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Áudio PCM Raw de %d bits" + +msgid "Raw PCM audio" +msgstr "Áudio PCM Raw" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Áudio Raw de ponto-flutuante de %d bits" + +msgid "Raw floating-point audio" +msgstr "Áudio Raw de ponto-flutuante" + +msgid "Audio CD source" +msgstr "Origem: CD de áudio" + +msgid "DVD source" +msgstr "Origem: DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Origem: Protocolo de Fluxo Contínuo em Tempo Real (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Origem: protocolo do Servidor de Mídia da Microsoft (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Origem: protocolo %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "decodificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "decodificador de áudio RTP %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "decodificador RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "Demultiplexador %s" + +#, c-format +msgid "%s decoder" +msgstr "Decodificador %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "codificador de vídeo RTP %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "codificador de áudio RTP %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "codificador RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "Multiplexador %s" + +#, c-format +msgid "%s encoder" +msgstr "Codificador %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Elemento \"%s\" do GStreamer" + +msgid "Unknown source element" +msgstr "Elemento de origem desconhecida" + +msgid "Unknown sink element" +msgstr "Elemento consumidor desconhecido" + +msgid "Unknown element" +msgstr "Elemento desconhecido" + +msgid "Unknown decoder element" +msgstr "Elemento decodificador desconhecido" + +msgid "Unknown encoder element" +msgstr "Elemento codificador desconhecido" + +msgid "Plugin or element of unknown type" +msgstr "Elemento ou plug-in de tipo desconhecido" + +msgid "No device specified." +msgstr "Nenhum dispositivo especificado." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "O dispositivo \"%s\" não existe." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "O dispositivo \"%s\" já está sendo usado." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Não foi possível abrir o dispositivo \"%s\" para leitura e escrita." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Não foi possível criar o elemento \"decodebin2\"." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Não foi possível criar o elemento \"queue2\"." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Não foi possível criar o elemento \"typefind\"." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Não é possível reproduzir legendas de texto e subimagens." + +#~ msgid "No Temp directory specified." +#~ msgstr "Nenhum diretório temporário especificado." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Não foi possível criar o arquivo temporário \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Não foi possível abrir o arquivo \"%s\" para leitura." + +#~ msgid "Internal data flow error." +#~ msgstr "Erro interno no fluxo de dados." + +#~ msgid "No file name specified." +#~ msgstr "Não foi especificado um nome de arquivo." diff --git a/gst-plugins-base-subtitles0.10/po/ro.po b/gst-plugins-base-subtitles0.10/po/ro.po new file mode 100644 index 0000000..72a0a7e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/ro.po @@ -0,0 +1,606 @@ +# Romanian translation for gst-plugins-base +# This file is distributed under the same license as the gst-plugins-base package. +# Lucian Adrian Grijincu , 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.29.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-08-16 01:21+0300\n" +"Last-Translator: Lucian Adrian Grijincu \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2);;\n" + +msgid "Master" +msgstr "Principal" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Înalte" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Linie intrare" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Microfon" + +msgid "PC Speaker" +msgstr "Difuzor PC" + +msgid "Playback" +msgstr "Redare" + +msgid "Capture" +msgstr "Captură" + +msgid "Could not open device for playback in mono mode." +msgstr "Nu s-a putut deschide dispozitivul pentru redare în modul mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nu s-a putut deschide dispozitivul pentru redare în modul stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Nu s-a putut deschide dispozitivul pentru redare în modul %d-canal." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nu s-a putut deschide dispozitivul audio pentru redare. Dispozitivul este " +"folosit de o altă aplicație." + +msgid "Could not open audio device for playback." +msgstr "Nu s-a putut deschide dispozitivul audio pentru redare." + +msgid "Could not open device for recording in mono mode." +msgstr "Nu s-a putut deschide dispozitivul pentru înregistrare în modul mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "" +"Nu s-a putut deschide dispozitivul pentru înregistrare în modul stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "" +"Nu s-a putut deschide dispozitivul pentru înregistrare în modul %d-canal" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nu s-a putut deschide dispozitivul audio pentru înregistrare. Dispozitivul " +"este folosit de o altă aplicație." + +msgid "Could not open audio device for recording." +msgstr "Nu s-a putut deschide dispozitivul audio pentru înregistrare." + +msgid "Could not open CD device for reading." +msgstr "Nu s-a putut deschide unitatea CD pentru redare." + +msgid "Could not seek CD." +msgstr "Nu s-a putut accesa CD-ul." + +msgid "Could not read CD." +msgstr "Nu s-a putut citi CD-ul." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nu s-a putut deschide fișierul vsf „%s\" pentru scriere: %s." + +msgid "No filename given" +msgstr "Niciun nume de fișier dat." + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nu s-a putut închide fișierul vsf „%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Eroare la scrierea fișierului „%s\"." + +msgid "Internal data stream error." +msgstr "Eroare internă a fluxului de date." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Un modul de extensie %s este necesar pentru a reda acest flux, dar acesta nu " +"este instalat." + +msgid "This appears to be a text file" +msgstr "Acesta pare să fie un fișier text." + +msgid "Could not determine type of stream" +msgstr "Nu s-a putut determina tipul fluxului" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI subtitrare „%s” nevalid, subtitrare dezactivată." + +msgid "No URI specified to play from." +msgstr "Nu s-a specificat URI pentru redare." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "URI „%s” nevalid." + +msgid "RTSP streams cannot be played yet." +msgstr "Fluxurile RTSP nu pot fi redate încă." + +msgid "Could not create \"decodebin\" element." +msgstr "Nu se poate crea elementul „decodebin”." + +msgid "Source element is invalid." +msgstr "Element sursă nevalid." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"A fost detectat doar un flux pentru subtitrare. Fie încărcați un fișier de " +"subtitrare sau un alt tip de fișier text, sau fișierul nu a fost recunoscut." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Nu există instalat un decodor pentru deschiderea acestui fișier. Probabil " +"trebuie să instalați modulele de extensie necesare." + +msgid "This is not a media file" +msgstr "Acesta nu este un fișier media" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "A fost detectat un flux de subtitrare, dar nu există flux video." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Lipsesc ambele elemente autovideosink și xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Element %s lipsă - verificați instalarea GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Lipsesc ambele elemente autoaudiosink și alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Lipsește atât elementul autovideosink cât și %s." + +msgid "The autovideosink element is missing." +msgstr "Elementul autovideosink lipsește." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Videosink-ul configurat %s nu funcționează." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Nu funcționează atât elementul autovideosink cât și %s." + +msgid "The autovideosink element is not working." +msgstr "Elementul autovideosink nu funcționează." + +msgid "Custom text sink element is not usable." +msgstr "Elementul sink de text personalizat nu este utilizabil." + +msgid "No volume control found" +msgstr "Nu s-a găsit niciun control de volum" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Lipsește atât elementul autoaudiosink cât și %s." + +msgid "The autoaudiosink element is missing." +msgstr "Elementul autoaudiosink lipsește." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Audiosink-ul configurat %s nu funcționează." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Nu funcționează atât elementul autoaudiosink cât și %s." + +msgid "The autoaudiosink element is not working." +msgstr "Elementul autoaudiosink nu funcționează." + +msgid "Can't play a text file without video or visualizations." +msgstr "Nu se poate reda un fișier text fără video sau vizualizări." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Niciun decodor disponibil pentru tipul „%s”." + +msgid "This stream type cannot be played yet." +msgstr "Acest tip de flux nu poate fi redat încă." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Nicio rutină de tratare de URI implementată pentru „%s”." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Eroare la trimiterea datelor către „%s:%d”." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Eroare la trimiterea antetului gdp către „%s:%d”." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Eroare la trimiterea conținutului gdp către „%s:%d”." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Conexiunea la %s:%d a fost refuzată." + +msgid "Can't record audio fast enough" +msgstr "Nu se poate înregistra sunetul destul de repede" + +msgid "Failed to read tag: not enough data" +msgstr "Citirea etichetei a eșuat: date insuficiente" + +msgid "track ID" +msgstr "ID pistă" + +msgid "MusicBrainz track ID" +msgstr "ID pistă MusicBrainz" + +msgid "artist ID" +msgstr "ID artist" + +msgid "MusicBrainz artist ID" +msgstr "ID artist MusicBrainz" + +msgid "album ID" +msgstr "ID album" + +msgid "MusicBrainz album ID" +msgstr "ID album MusicBrainz" + +msgid "album artist ID" +msgstr "ID artist album" + +msgid "MusicBrainz album artist ID" +msgstr "ID album artist MusicBrainz" + +msgid "track TRM ID" +msgstr "TRM ID pistă" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM MusicBrainz" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Acest CD nu conține piste audio" + +msgid "ID3 tag" +msgstr "etichetă ID3" + +msgid "APE tag" +msgstr "etichetă APE" + +msgid "ICY internet radio" +msgstr "Radio Internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Audio fără pierdere (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Codec audio liber fără pierdere (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV fără pierdere" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH fără pierdere" + +msgid "Uncompressed Gray Image" +msgstr "Imagine gri necomprimată" + +msgid "Run-length encoding" +msgstr "Codarea run-length" + +msgid "Sami subtitle format" +msgstr "Format subtitrare Sami" + +msgid "TMPlayer subtitle format" +msgstr "Format subtitrare TMPlayer" + +msgid "Kate subtitle format" +msgstr "Format subtitrare Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Planar necomprimat YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Planar necomprimat YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Pachet necomprimat YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Pachet necomprimat YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Pachet necomprimat YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Pachet necomprimat YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Pachet necomprimat YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Planar necomprimat YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Planar necomprimat YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Plan-Y alb și negru necomprimat" + +msgid "Uncompressed YUV" +msgstr "YUV necomprimat" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Paletizat la %d biți necomprimat %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 versiunea %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "PCM audio brut %d biți" + +msgid "Raw PCM audio" +msgstr "PCM audio brut" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Audio în virgulă mobilă brut la %d biți" + +msgid "Raw floating-point audio" +msgstr "Audio în virgulă mobilă brut" + +msgid "Audio CD source" +msgstr "Sursă CD audio" + +msgid "DVD source" +msgstr "Sursă DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Sursă RTSP (protocol pentru flux în timp real)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Sursă protocol Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Sursă protocol %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "Demuxer %s" + +#, c-format +msgid "%s decoder" +msgstr "Decoder %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "Muxer %s" + +#, c-format +msgid "%s encoder" +msgstr "codificator %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Element GStreamer %s" + +msgid "Unknown source element" +msgstr "Element sursă necunoscut" + +msgid "Unknown sink element" +msgstr "Element sink necunoscut" + +msgid "Unknown element" +msgstr "Element necunoscut" + +msgid "Unknown decoder element" +msgstr "Element decodor necunoscut" + +msgid "Unknown encoder element" +msgstr "Element codor necunoscut" + +msgid "Plugin or element of unknown type" +msgstr "Modul de extensie sau element de tip necunoscut" + +msgid "No device specified." +msgstr "Nu s-a specificat niciun dispozitiv." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Dispozitivul „%s” nu există." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Dispozitivul „%s” este deja folosit." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nu s-a putut deschide dispozitivul „%s” pentru citire și scriere." diff --git a/gst-plugins-base-subtitles0.10/po/ru.po b/gst-plugins-base-subtitles0.10/po/ru.po new file mode 100644 index 0000000..9a2e617 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/ru.po @@ -0,0 +1,623 @@ +# Translation for gst-plugins-base messages to Russian +# This file is put in the public domain. +# +# Артём Попов , 2009. +# Pavel Maryanov , 2009. +# Yuri Kozlov , 2010, 2011. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-26 20:30+0400\n" +"Last-Translator: Yuri Kozlov \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Lokalize 1.0\n" +"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Master" +msgstr "Общий" + +msgid "Bass" +msgstr "Низкие" + +msgid "Treble" +msgstr "Высокие" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Синтезатор" + +msgid "Line-in" +msgstr "Линейный вход" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Микрофон" + +msgid "PC Speaker" +msgstr "Внутренний динамик" + +msgid "Playback" +msgstr "Воспроизведение" + +msgid "Capture" +msgstr "Съёмка" + +msgid "Could not open device for playback in mono mode." +msgstr "Не удалось открыть устройство для воспроизведения в режиме моно." + +msgid "Could not open device for playback in stereo mode." +msgstr "Не удалось открыть устройство для воспроизведения в режиме стерео." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "" +"Не удалось открыть устройство для воспроизведения в %d-канальном режиме." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Не удалось открыть устройство для воспроизведения. Устройство используется " +"другим приложением." + +msgid "Could not open audio device for playback." +msgstr "Не удалось открыть устройство для воспроизведения." + +msgid "Could not open device for recording in mono mode." +msgstr "Не удалось открыть устройство для записи в режиме моно." + +msgid "Could not open device for recording in stereo mode." +msgstr "Не удалось открыть устройство для записи в режиме стерео." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Не удалось открыть устройство для записи в %d-канальном режиме." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Не удалось открыть устройство для записи. Устройство используется другим " +"приложением." + +msgid "Could not open audio device for recording." +msgstr "Не удалось открыть устройство для записи." + +msgid "Could not open CD device for reading." +msgstr "Не удалось открыть CD-устройство для чтения." + +msgid "Could not seek CD." +msgstr "Не удалось сменить позицию воспроизведения CD." + +msgid "Could not read CD." +msgstr "Не удалось прочитать диск." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Не удалось открыть vfs-файл «%s» для записи: %s." + +msgid "No filename given" +msgstr "Не указано имя файла" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Не удалось закрыть vfs-файл «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Ошибка записи в файл «%s»." + +msgid "Internal data stream error." +msgstr "Внутренняя ошибка потока данных." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Для воспроизведения этого потока требуется модуль %s, но он не установлен." + +msgid "This appears to be a text file" +msgstr "Этот файл является текстовым" + +msgid "Could not determine type of stream" +msgstr "Не удалось определить тип потока" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Неверный URI субтитров «%s», субтитры выключены." + +msgid "No URI specified to play from." +msgstr "Не указан URI источника воспроизведения." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Неверный URI «%s»." + +msgid "RTSP streams cannot be played yet." +msgstr "Воспроизведение RTSP-потоков в данный момент невозможно." + +msgid "Could not create \"decodebin\" element." +msgstr "Не удалось создать элемент «decodebin»." + +msgid "Source element is invalid." +msgstr "Неверный элемент источника." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Обнаружен только поток субтитров. Либо вы загружаете файл субтитров или иной " +"текстовый файл, либо медиа-файл не распознан." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Не установлен требуемый декодер для обработки этого файла. Возможно, вам " +"следует поставить необходимые модули." + +msgid "This is not a media file" +msgstr "Файл не является медиа-файлом" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Обнаружен только поток субтитров, поток видео не обнаружен." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Отсутствуют элементы autovideosink и xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Отсутствует элемент «%s» — проверьте правильность установки GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Отсутствуют элементы autoaudiosink и alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Отсутствуют элементы autovideosink и %s." + +msgid "The autovideosink element is missing." +msgstr "Отсутствует элемент autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Настроенный videosink %s не работает." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Элементы autovideosink и %s не работают." + +msgid "The autovideosink element is not working." +msgstr "Элемент autovideosink не работает." + +msgid "Custom text sink element is not usable." +msgstr "Входной элемент пользовательского текста не работоспособен." + +msgid "No volume control found" +msgstr "Не найден элемент управления громкостью" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Отсутствуют элементы autoaudiosink и %s." + +msgid "The autoaudiosink element is missing." +msgstr "Отсутствует элемент autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Настроенный audiosink %s не работает." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Элементы autoaudiosink и %s не работают." + +msgid "The autoaudiosink element is not working." +msgstr "Элемент autoaudiosink не работает." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Воспроизведение текстового файла без видео или видеотображения невозможно." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Для типа «%s» недоступен декодер." + +msgid "This stream type cannot be played yet." +msgstr "Воспроизведение этого потока в данный момент невозможно." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Для «%s» не реализован обработчик URI." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Ошибка отправки данных в «%s:%d»." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Ошибка отправки данных заголовка gdp в «%s:%d»." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Ошибка отправки данных gdp в «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "В соединении с %s:%d отказано." + +msgid "Can't record audio fast enough" +msgstr "Невозможна запись аудио с достаточной скоростью" + +msgid "Failed to read tag: not enough data" +msgstr "Не удалось прочитать тег: недостаточно данных" + +msgid "track ID" +msgstr "ID дорожки" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz ID дорожки" + +msgid "artist ID" +msgstr "ID исполнителя" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz ID исполнителя" + +msgid "album ID" +msgstr "ID альбома" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz ID альбома" + +msgid "album artist ID" +msgstr "ID исполнителя альбома" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz ID исполнителя альбома" + +msgid "track TRM ID" +msgstr "ID TRM дорожки" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "выдержка при съёмке" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Выдержка при съёмке изображения, в секундах" + +msgid "capturing focal ratio" +msgstr "диафрагменное число при съёмке" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Диафрагменное число (f) при съёмке изображения" + +msgid "capturing focal length" +msgstr "фокусное расстояние при съёмке" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Фокусное расстояние зеркала при съёмке изображения, в мм" + +msgid "capturing digital zoom ratio" +msgstr "коэффициент цифрового трансфокатора при съёмке" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Коэффициент цифрового трансфокатора при съёмке изображения" + +msgid "capturing iso speed" +msgstr "чувствительность ISO при съёмке" + +msgid "The ISO speed used when capturing an image" +msgstr "Чувствительность ISO при съёмке изображения" + +msgid "capturing exposure program" +msgstr "программа экспозиции при съёмке" + +msgid "The exposure program used when capturing an image" +msgstr "Программа экспозиции при съёмке изображения" + +msgid "capturing exposure mode" +msgstr "режим экспозиции при съёмке" + +msgid "The exposure mode used when capturing an image" +msgstr "Режим экспозиции при съёмке изображения" + +msgid "capturing exposure compensation" +msgstr "компенсация экспозиции при съёмке" + +msgid "The exposure compensation used when capturing an image" +msgstr "Компенсация экспозиции при съёмке изображения" + +msgid "capturing scene capture type" +msgstr "тип сцены при съёмке" + +msgid "The scene capture mode used when capturing an image" +msgstr "Тип сцены при съёмке изображения" + +msgid "capturing gain adjustment" +msgstr "регулировка усиления при съёмке" + +msgid "The overall gain adjustment applied on an image" +msgstr "Итоговая настройка усиления, применяемая к изображению" + +msgid "capturing white balance" +msgstr "баланс белого при съёмке" + +msgid "The white balance mode set when capturing an image" +msgstr "Режим баланса белого при съёмке изображения" + +msgid "capturing contrast" +msgstr "контрастность при съёмке" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Направление обработки контраста при съёмке изображения" + +msgid "capturing saturation" +msgstr "насыщенность при съёмке" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Направление обработки насыщенности при съёмке изображения" + +msgid "capturing sharpness" +msgstr "резкость при съёмке" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Направление обработки резкости при съёмке изображения" + +msgid "capturing flash fired" +msgstr "вспышка при съёмке" + +msgid "If the flash fired while capturing an image" +msgstr "Сработала ли вспышка при съёмке изображения" + +msgid "capturing flash mode" +msgstr "режим вспышки при съёмке" + +msgid "The selected flash mode while capturing an image" +msgstr "Выбранный режим для вспышки при съёмке изображения" + +msgid "capturing metering mode" +msgstr "режим замера при съёмке" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Режим замера, использованный для определения экспозиции при съёмке " +"изображения" + +msgid "capturing source" +msgstr "источник для съёмки" + +msgid "The source or type of device used for the capture" +msgstr "Источник или тип устройства, использованный для съёмки" + +msgid "image horizontal ppi" +msgstr "изображение в ppi по горизонтали" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Горизонтальная плотность носителя (изображение/видео) в ppi" + +msgid "image vertical ppi" +msgstr "изображение в ppi по вертикали" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Вертикальная плотность носителя (изображение/видео) в ppi" + +msgid "This CD has no audio tracks" +msgstr "На CD нет звуковых дорожек" + +msgid "ID3 tag" +msgstr "ID3-тег" + +msgid "APE tag" +msgstr "APE-тег" + +msgid "ICY internet radio" +msgstr "Интернет-радио ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV Lossless" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Lossless MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Несжатое полутоновое изображение" + +msgid "Run-length encoding" +msgstr "RLE-сжатие" + +msgid "Sami subtitle format" +msgstr "Формат субтитров Sami" + +msgid "TMPlayer subtitle format" +msgstr "Формат субтитров TMPlayer" + +msgid "Kate subtitle format" +msgstr "Формат субтитров Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Несжатый планарный YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Несжатый планарный YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Несжатый смешанный YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Несжатый смешанный YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Несжатый смешанный YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Несжатый смешанный YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Несжатый смешанный YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Несжатый планарный YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Несжатый планарный YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Несжатая чёрно-белая Y-плоскость" + +msgid "Uncompressed YUV" +msgstr "Несжатый YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Несжатое %d-битное %s-изображение с палитрой" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Версия %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Несжатое %d-битное PCM-аудио" + +msgid "Raw PCM audio" +msgstr "Несжатое PCM-аудио" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Несжатое %d-битное аудио с плавающей точкой" + +msgid "Raw floating-point audio" +msgstr "Несжатое аудио с плавающей точкой" + +msgid "Audio CD source" +msgstr "Источник аудио-CD" + +msgid "DVD source" +msgstr "Источник DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Источник протокола Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Источник протокола Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Источник протокола %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "RTP-разгрузчик %s-видео" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "RTP-разгрузчик %s-аудио" + +#, c-format +msgid "%s RTP depayloader" +msgstr "RTP-разгрузчик %s" + +#, c-format +msgid "%s demuxer" +msgstr "Демуксер %s" + +#, c-format +msgid "%s decoder" +msgstr "Декодер %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "RTP-нагрузчик %s-видео" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "RTP-нагрузчик %s-аудио" + +#, c-format +msgid "%s RTP payloader" +msgstr "RTP-нагрузчик %s" + +#, c-format +msgid "%s muxer" +msgstr "Муксер %s" + +#, c-format +msgid "%s encoder" +msgstr "Кодировщик %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Элемент GStreamer %s" + +msgid "Unknown source element" +msgstr "Неизвестный элемент-источник" + +msgid "Unknown sink element" +msgstr "Неизвестный элемент-приёмник" + +msgid "Unknown element" +msgstr "Неизвестный элемент" + +msgid "Unknown decoder element" +msgstr "Неизвестный элемент-декодер" + +msgid "Unknown encoder element" +msgstr "Неизвестный элемент-кодировщик" + +msgid "Plugin or element of unknown type" +msgstr "Модуль или элемент неизвестного типа" + +msgid "No device specified." +msgstr "Не указано устройство." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Устройство «%s» не существует." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Устройство «%s» уже используется." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Не удалось открыть устройство «%s» для чтения и записи." + +#~ msgid "No file name specified." +#~ msgstr "Не указано имя файла." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Не удалось открыть файл «%s» для чтения." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Не удалось создать элемент «decodebin2»." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Не удалось создать элемент «queue2»." diff --git a/gst-plugins-base-subtitles0.10/po/sk.po b/gst-plugins-base-subtitles0.10/po/sk.po new file mode 100644 index 0000000..e8896ad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/sk.po @@ -0,0 +1,643 @@ +# Slovak translations for gst-plugins-base. +# This file is put in the public domain. +# +# Peter Tuhársky , 2007, 2008, 2009, 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.30.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-11-08 15:34+0100\n" +"Last-Translator: Peter Tuhársky \n" +"Language-Team: Slovak \n" +"Language: sk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\\n\n" +"X-Generator: KBabel 1.11.4\n" +"X-Poedit-Language: Slovak\n" +"X-Poedit-Country: SLOVAKIA\n" + +msgid "Master" +msgstr "Hlavný" + +msgid "Bass" +msgstr "Basy" + +msgid "Treble" +msgstr "Výšky" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synth" + +msgid "Line-in" +msgstr "Line-in" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofón" + +msgid "PC Speaker" +msgstr "Reproduktor" + +msgid "Playback" +msgstr "Prehrávanie" + +msgid "Capture" +msgstr "Zachytávanie" + +msgid "Could not open device for playback in mono mode." +msgstr "Nepodarilo sa otvoriť zariadenie pre prehrávanie v režime mono." + +msgid "Could not open device for playback in stereo mode." +msgstr "Nepodarilo sa otvoriť zariadenie pre prehrávanie v režime stereo." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "" +"Nepodarilo sa otvoriť zariadenie pre prehrávanie v %d-kanálovom režime." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Nepodarilo sa otvoriť zvukové zariadenie pre prehrávanie. Zariadenie už " +"používa iná aplikácia." + +msgid "Could not open audio device for playback." +msgstr "Nepodarilo sa otvoriť zvukové zariadenie pre prehrávanie." + +msgid "Could not open device for recording in mono mode." +msgstr "Nepodarilo sa otvoriť zariadenie pre nahrávanie v režime mono." + +msgid "Could not open device for recording in stereo mode." +msgstr "Nepodarilo sa otvoriť zariadenie pre nahrávanie v režime stereo." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Nepodarilo sa otvoriť zariadenie pre nahrávanie v %d-kanálovom režime." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Nepodarilo sa otvoriť zvukové zariadenie pre nahrávanie. Zariadenie už " +"používa iná aplikácia." + +msgid "Could not open audio device for recording." +msgstr "Nepodarilo sa otvoriť zvukové zariadenie pre nahrávanie." + +msgid "Could not open CD device for reading." +msgstr "Nepodarilo sa otvoriť zariadenie CD na čítanie." + +msgid "Could not seek CD." +msgstr "Nepodarilo sa nastaviť pozíciu na CD." + +msgid "Could not read CD." +msgstr "Nepodarilo sa čítať CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Nepodarilo sa otvoriť vfs súbor \"%s\" pre zápis: %s." + +msgid "No filename given" +msgstr "Nebol zadaný názov súboru" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Nepodarilo sa zatvoriť súbor \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Chyba pri zápise do súboru \"%s\"." + +msgid "Internal data stream error." +msgstr "Vnútorná chyba prúdu údajov." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"Na prehratie tohto prúdu údajov je vyžadovaný zásuvný modul %s, ktorý nie je " +"nainštalovaný." + +msgid "This appears to be a text file" +msgstr "Tento súbor je asi textový" + +msgid "Could not determine type of stream" +msgstr "Nepodarilo sa zistiť typ prádu údajov" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Chybné URI titulkov \"%s\", titulky zakázané." + +msgid "No URI specified to play from." +msgstr "Nebolo špecifikované žiadne URI, z ktorého by sa dalo prehrávať." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Chybné URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP prúdy sa teraz nedajú prehrávať." + +msgid "Could not create \"decodebin\" element." +msgstr "Nepodarilo sa vytvoriť prvok \"decodebin\"" + +msgid "Source element is invalid." +msgstr "Zdrojový prvok je chybný." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Bol zistený iba prúd titulkov. Buď načítavate titulkový súbor alebo nejaký " +"iný typ textového súboru, alebo ide o neznámy typ mediálneho súboru." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Nemáte nainštalovaný dekodér pre tento typ súboru. Zrejme bude potrebné " +"nainštalovať príslušné zásuvné moduly." + +msgid "This is not a media file" +msgstr "Toto nie je mediálny súbor" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Bol zistený prúd titulkov, ale bez video prúdu údajov." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Chýbajú prvky autovideosink aj xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Chýa prvok '%s' - skontrolujte svoju inštaláciu GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Chýbajú prvky autoaudiosink aj alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Chýbajú prvky autovideosink aj %s." + +msgid "The autovideosink element is missing." +msgstr "Chýba prvok autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Nastavený videosink %s nefunguje." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Nefungujú prvky autovideosink a %s." + +msgid "The autovideosink element is not working." +msgstr "Nefunguje prvok autovideosink." + +msgid "Custom text sink element is not usable." +msgstr "Používateľský textový prvok sink nie je použiteľný." + +msgid "No volume control found" +msgstr "+Ziadny ovl8da4 hlasitosti sa nena3iel" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Chýbajú prvky autoaudiosink aj %s." + +msgid "The autoaudiosink element is missing." +msgstr "Chýba prvok autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Nastavený audiosink %s nefunguje." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Nefungujú prvky autoaudiosink aj %s." + +msgid "The autoaudiosink element is not working." +msgstr "Nefunguje prvok autoaudiosink." + +msgid "Can't play a text file without video or visualizations." +msgstr "Nemôžem prehrať textový súbor bez videa alebo vizualizácií." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Pre typ '%s' nie je k dispozícii dekodér." + +msgid "This stream type cannot be played yet." +msgstr "Tento typ prúdu údajov sa teraz nedá prehrávať." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Pre \"%s\" nie je implementovaná obsluha." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Chyba pri posielaní údajov do \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Chyba pri posielaní hlavičky gdp údajov do \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Chyba pri posielaní gdp záťažových údajov do \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Spojenie s %s:%d bolo odmietnuté." + +msgid "Can't record audio fast enough" +msgstr "Zvuk sa nedá nahrávať dostatočne rýchlo" + +msgid "Failed to read tag: not enough data" +msgstr "Načítanie značky zlyhalo: málo údajov" + +msgid "track ID" +msgstr "ID stopy" + +msgid "MusicBrainz track ID" +msgstr "ID stopy MusicBrainz" + +msgid "artist ID" +msgstr "ID umelca" + +msgid "MusicBrainz artist ID" +msgstr "ID umelca MusicBrainz" + +msgid "album ID" +msgstr "ID albumu" + +msgid "MusicBrainz album ID" +msgstr "ID albumu MusicBrainz" + +msgid "album artist ID" +msgstr "ID umelca albumu" + +msgid "MusicBrainz album artist ID" +msgstr "ID umelca albumu MusicBrainz" + +msgid "track TRM ID" +msgstr "ID TRM stopy" + +msgid "MusicBrainz TRM ID" +msgstr "ID TRM MusicBrainz" + +msgid "capturing shutter speed" +msgstr "zachytávacia rýchlosť uzávierky" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Rýchlosť uzávierky použitá pri zachytávaní obrázku, v sekundách" + +msgid "capturing focal ratio" +msgstr "zachytávacií pomer F" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Pomer (číslo F) použitý pri zachytávaní obrázku" + +msgid "capturing focal length" +msgstr "zachytávacia ohnisková vzdialenosť" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Ohnisková vzdialenosť objektívu pri zachytávaní obrázku, v mm" + +msgid "capturing digital zoom ratio" +msgstr "zachytávací pomer digitálneho priblíženia" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Pomer digitálneho priblíženia použitý pri zachytávaní obrázku" + +msgid "capturing iso speed" +msgstr "zachytávacia rýchlosť ISO" + +msgid "The ISO speed used when capturing an image" +msgstr "Rýchlosť ISO použítá pri zachytávaní obrázku" + +msgid "capturing exposure program" +msgstr "zachytávací program expozície" + +msgid "The exposure program used when capturing an image" +msgstr "Program expozície použitý pri zachytávaní obrázko" + +msgid "capturing exposure mode" +msgstr "zachytávací režim expozície" + +msgid "The exposure mode used when capturing an image" +msgstr "Režim expozície použitý pri zachytávaní obrázku" + +#, fuzzy +msgid "capturing exposure compensation" +msgstr "zachytávací režim expozície" + +#, fuzzy +msgid "The exposure compensation used when capturing an image" +msgstr "Režim expozície použitý pri zachytávaní obrázku" + +msgid "capturing scene capture type" +msgstr "zachytávací typ zachytenia scény" + +msgid "The scene capture mode used when capturing an image" +msgstr "Režim zachytenia scény použitý pri zachytávaní obrázku" + +msgid "capturing gain adjustment" +msgstr "zachytávacie nastavenie zisku" + +msgid "The overall gain adjustment applied on an image" +msgstr "Celkové nastavenie zisku aplikovaného na obrázok" + +msgid "capturing white balance" +msgstr "zachytávacie vyváženie bielej" + +msgid "The white balance mode set when capturing an image" +msgstr "Režim vyváženia bielej nastavený pri zachytávaní obrázku" + +msgid "capturing contrast" +msgstr "zachytávací kontrast" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Smerovanie spracovania kontrastu použitého pri zachytávaní obrázku" + +msgid "capturing saturation" +msgstr "zachytávacia sýtosť" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Smerovanie spracovania sýtosti použitého pri zachytávaní obrázku" + +msgid "capturing sharpness" +msgstr "zachytávacia ostrosť" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Smerovanie spracovania ostrosti použitého pri zachytávaní obrázku" + +msgid "capturing flash fired" +msgstr "zachytávací blesk" + +msgid "If the flash fired while capturing an image" +msgstr "Bol alebo nebol použitý blesk pri zachytávaní obrázku" + +msgid "capturing flash mode" +msgstr "zachytávací režim blesku" + +msgid "The selected flash mode while capturing an image" +msgstr "Vybraný režim blesku pri zachytávaní obrázku" + +msgid "capturing metering mode" +msgstr "zachytávacie meranie blesku" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Režim merania blesku pri zisťovaní expozície pre zachytenie obrázku" + +msgid "capturing source" +msgstr "zachytávací zdroj" + +msgid "The source or type of device used for the capture" +msgstr "Zdroj alebo typ zariadenia použitý na zachytenie" + +msgid "image horizontal ppi" +msgstr "vodorovné ppi obrázku" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Cieľová vodorovná hustota pixlov média (obrázku/videa) v ppi" + +msgid "image vertical ppi" +msgstr "zvislé ppi obrázku" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Cieľová zvislá hustota pixlov média (obrázku/videa) v ppi" + +msgid "This CD has no audio tracks" +msgstr "Toto CD nemá zvukové stopy" + +msgid "ID3 tag" +msgstr "ID3 značka" + +msgid "APE tag" +msgstr "APE značka" + +msgid "ICY internet radio" +msgstr "Internetové rádio ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Bezstratový zvuk Apple (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Slobodný bezstratový zvukový kodek (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Bezstratový verný zvuk (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Reč" + +msgid "CYUV Lossless" +msgstr "Bezstratové CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Bezstratové MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Nekomprimovaný šedotónový obrázok" + +msgid "Run-length encoding" +msgstr "Kódovanie počas prehrávania" + +msgid "Sami subtitle format" +msgstr "Formát titulkov sami" + +msgid "TMPlayer subtitle format" +msgstr "Titulkový formát TMPlayer" + +msgid "Kate subtitle format" +msgstr "Formát titulkov Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nekomprimovaný planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nekomprimovaný planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nekomprimovaný pakovaný YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nekomprimovaný pakovaný YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nekomprimovaný pakovaný YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nekomprimovaný pakovaný YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nekomprimovaný pakovaný YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nekomprimovaný planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nekomprimovaný planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nekomprimovaný čierno-biely Y-plane" + +msgid "Uncompressed YUV" +msgstr "Nekomprimovaný YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nekomprimovaný paletizovaný %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Verzie %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Surový %d-bit PCM zvuk" + +msgid "Raw PCM audio" +msgstr "Surový PCM zvuk" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Surový %d-bit zvuk s pohyblivou desatinnou čiarkou" + +msgid "Raw floating-point audio" +msgstr "Surový zvuk s pohyblivou desatinnou čiarkou" + +msgid "Audio CD source" +msgstr "Zdroj zvukové CD" + +msgid "DVD source" +msgstr "Zdroj DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Zdroj Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Zdroj protokolu Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "zdroj protokolu %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s dekodér" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "%s muxer" + +#, c-format +msgid "%s encoder" +msgstr "%s enkodér" + +#, c-format +msgid "GStreamer element %s" +msgstr "Prvok GStreamera %s" + +msgid "Unknown source element" +msgstr "Neznámy zdrojový prvok" + +msgid "Unknown sink element" +msgstr "Neznámy prvok sink" + +msgid "Unknown element" +msgstr "Neznámy prvok" + +msgid "Unknown decoder element" +msgstr "Neznámy prvok dekodéra" + +msgid "Unknown encoder element" +msgstr "Neznámy prvok enkodéra" + +msgid "Plugin or element of unknown type" +msgstr "Neznámy typ zásuvného modulu alebo prvku" + +msgid "No device specified." +msgstr "Nebolo zadané zariadenie." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Zariadenie \"%s\" neexistuje." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Zariadenie \"%s\" sa už používa." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Nepodarilo sa otvoriť zariadenie \"%s\" pre čítanie a zápis." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Nemôžem zobrazovať naraz textové titulky aj podobrázky." + +#~ msgid "No Temp directory specified." +#~ msgstr "Nebol zadaný dočasný adresár (Temp)." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Nepodarilo sa vytvoriť dočasný súbor \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Nepodarilo sa otvoriť súbor \"%s\" na čítanie." + +#~ msgid "Internal data flow error." +#~ msgstr "Vnútorná chyba prúdu údajov." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Nepodarilo sa vytvoriť prvok \"decodebin2\"." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Nepodarilo sa vytvoriť prvok \"queue2\"." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Nepodarilo sa vytvoriť prvok \"typefind\"" + +#~ msgid "No file name specified." +#~ msgstr "Nebolo zadané meno súboru." + +#~ msgid "artist sortname" +#~ msgstr "katalógové meno umelca" + +#~ msgid "MusicBrainz artist sortname" +#~ msgstr "katalógové meno umelca pre MusicBrainz" diff --git a/gst-plugins-base-subtitles0.10/po/sl.po b/gst-plugins-base-subtitles0.10/po/sl.po new file mode 100644 index 0000000..443f392 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/sl.po @@ -0,0 +1,637 @@ +# Slovenian translation for gst-plugins-base. +# Copyright (C) 2005 - 2011 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# Matej Urbančič , 2010. +# Klemen Košir , 2011. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-26 15:56+0100\n" +"Last-Translator: Klemen Košir \n" +"Language-Team: Slovenian \n" +"Language: sl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 1 : n%100==2 ? 2 : n%100==3 || n" +"%100==4 ? 3 : 0);\n" +"X-Poedit-Language: Slovenian\n" +"X-Poedit-Country: SLOVENIA\n" +"X-Poedit-SourceCharset: utf-8\n" + +msgid "Master" +msgstr "Glavni" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Visoki toni" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizator" + +msgid "Line-in" +msgstr "Analogni vhod" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "Računalniški zvočnik" + +msgid "Playback" +msgstr "Predvajanje" + +msgid "Capture" +msgstr "Zajemanje" + +msgid "Could not open device for playback in mono mode." +msgstr "Naprave ni mogoče odpreti za predvajanje v mono načinu." + +msgid "Could not open device for playback in stereo mode." +msgstr "Naprave ni mogoče odpreti za predvajanje v stereo načinu." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Naprave ni mogoče odpreti za predvajanje v %d-kanalnem načinu." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Zvočne naprave ni mogoče odpreti za predvajanje. Napravo uporablja drug " +"program." + +msgid "Could not open audio device for playback." +msgstr "Zvočne naprave ni mogoče odpreti za predvajanje." + +msgid "Could not open device for recording in mono mode." +msgstr "Naprave ni mogoče odpreti za snemanje v mono načinu." + +msgid "Could not open device for recording in stereo mode." +msgstr "Naprave ni mogoče odpreti za snemanje v stereo načinu." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Naprave ni mogoče odpreti za snemanje v %d-kanalnem načinu." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Zvočne naprave ni mogoče odpreti za snemanje. Napravo uporablja drug program." + +msgid "Could not open audio device for recording." +msgstr "Zvočne naprave ni mogoče odpreti za snemanje." + +msgid "Could not open CD device for reading." +msgstr "Naprave CD ni mogoče odpreti za branje." + +msgid "Could not seek CD." +msgstr "Po CD-ju ni mogoče iskati." + +msgid "Could not read CD." +msgstr "CD-ja ni mogoče prebrati." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "VFS datoteke \"%s\" ni mogoče odpreti za pisanje: %s" + +msgid "No filename given" +msgstr "Ni podanega imena datoteke" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "VFS datoteke \"%s\" ni mogoče zapreti." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Napaka med pisanjem v datoteko \"%s\"." + +msgid "Internal data stream error." +msgstr "Notranja napaka pretoka podatkov." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Za predvajanje tega pretoka je potreben vstavek %s, ki pa ni nameščen." + +msgid "This appears to be a text file" +msgstr "Datoteka je videti kot besedilna datoteka" + +msgid "Could not determine type of stream" +msgstr "Vrste pretoka ni mogoče določiti." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Neveljaven URI podnapisov \"%s\", zato bodo onemogočeni." + +msgid "No URI specified to play from." +msgstr "Ni navedenega naslova URI za predvajanje." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Neveljaven URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "Pretokov RTSP še ni mogoče predvajati." + +msgid "Could not create \"decodebin\" element." +msgstr "Predmeta \"decodebin\" ni mogoče ustvariti." + +msgid "Source element is invalid." +msgstr "Izvorni predmet je neveljaven." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Zaznan je bil le pretok podnapisov. Morda je bila naložena datoteka " +"podnapisov ali katera druga vrsta besedilne datoteke, ali pa predstavnostne " +"datoteke ni mogoče prepoznati." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Za to vrsto datotek ni nameščenega ustreznega odkodirnika. Morda je potrebno " +"namestiti manjkajoče vstavke." + +msgid "This is not a media file" +msgstr "Datoteka ni predstavnostna datoteka" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Zaznan je bil pretok podnapisov, ne pa tudi pretok videa." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Predmeta autovideosink in xvimagesink manjkata." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Predmet '%s' manjka - preverite namestitev paketa GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Predmeta autovideosink in alsasink manjkata." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Predmeta autovideosink in %s manjkata." + +msgid "The autovideosink element is missing." +msgstr "Predmet autovideosink manjka." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Nastavljeni predmet videosink %s ne deluje." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Predmeta autovideosink in %s ne delujeta." + +msgid "The autovideosink element is not working." +msgstr "Predmet autovideosink ne deluje." + +msgid "Custom text sink element is not usable." +msgstr "Predmet ponora besedila po meri ni uporaben." + +msgid "No volume control found" +msgstr "Nadzornika glasnosti ni mogoče najti" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Predmeta autoaudiosink in %s manjkata." + +msgid "The autoaudiosink element is missing." +msgstr "Predmet autoaudiosink manjka." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Nastavljeni predmet autosink %s ne deluje." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Predmeta autovideosink in %s ne delujeta." + +msgid "The autoaudiosink element is not working." +msgstr "Predmet autovideosink ne deluje." + +msgid "Can't play a text file without video or visualizations." +msgstr "Besedilne datoteke ni mogoče predvajati brez videa ali predočenja." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Za vrsto \"%s\" ni ustreznega odkodirnika." + +msgid "This stream type cannot be played yet." +msgstr "Te vrste pretoka še ni mogoče predvajati." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Ni ročnika naslovov URI za \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Napaka med pošiljanjem podatkov na \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Napaka med pošiljanjem podatkov glave GDP na \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Napaka med pošiljanjem podatkov vsebine GDP na \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Povezava s %s:%d zavrnjena." + +msgid "Can't record audio fast enough" +msgstr "Ni mogoče dovolj hitro snemati zvoka" + +msgid "Failed to read tag: not enough data" +msgstr "Oznake ni mogoče prebrati: ni dovolj podatkov" + +msgid "track ID" +msgstr "ID sledi" + +msgid "MusicBrainz track ID" +msgstr "ID sledi MusicBrainz" + +msgid "artist ID" +msgstr "ID izvajalca" + +msgid "MusicBrainz artist ID" +msgstr "ID izvajalca MusicBrainz" + +msgid "album ID" +msgstr "ID albuma" + +msgid "MusicBrainz album ID" +msgstr "ID albuma MusicBrainz" + +msgid "album artist ID" +msgstr "ID izvajalca albuma" + +msgid "MusicBrainz album artist ID" +msgstr "ID izvajalca albuma MusicBrainz" + +msgid "track TRM ID" +msgstr "TRM ID sledi" + +msgid "MusicBrainz TRM ID" +msgstr "TRM ID MusicBrainz" + +msgid "capturing shutter speed" +msgstr "hitrost zaslonke" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Hitrost zaslonke, uporabljene med zajemanjem slike (v sekundah)" + +msgid "capturing focal ratio" +msgstr "goriščno razmerje med zajemanjem" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Goriščno razmerje, uporabljeno med zajemanjem slike" + +msgid "capturing focal length" +msgstr "goriščna razdalja med zajemanjem" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Goriščna razdalja leč, uporabljena med zajemanjem slike" + +msgid "capturing digital zoom ratio" +msgstr "razmerje digitalnega približevanja med zajemanjem" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Razmerje digitalnega približevanja, uporabljeno med zajemanjem slike" + +msgid "capturing iso speed" +msgstr "hitrost ISO zajema" + +msgid "The ISO speed used when capturing an image" +msgstr "Hitrost ISO, uporabljena med zajemanjem slike" + +msgid "capturing exposure program" +msgstr "program osvetlitve zajema" + +msgid "The exposure program used when capturing an image" +msgstr "Program osvetlitve, uporabljen med zajemanjem slike" + +msgid "capturing exposure mode" +msgstr "način osvetlitve zajema" + +msgid "The exposure mode used when capturing an image" +msgstr "Program osvetlitve, uporabljen med zajemanjem slike" + +msgid "capturing exposure compensation" +msgstr "nadomestitev osvetlitve zajema" + +msgid "The exposure compensation used when capturing an image" +msgstr "Nadomestitev osvetlitve, uporabljena med zajemanjem slike" + +msgid "capturing scene capture type" +msgstr "vrsta zajemanja scene med zajemanjem" + +msgid "The scene capture mode used when capturing an image" +msgstr "Način zajemanja scene, uporabljen med zajemanjem slike" + +msgid "capturing gain adjustment" +msgstr "prilagoditev ojačitve med zajemanjem" + +msgid "The overall gain adjustment applied on an image" +msgstr "Skupna prilagoditev ojačitve slike" + +msgid "capturing white balance" +msgstr "ravnotežje bele barve zajema" + +msgid "The white balance mode set when capturing an image" +msgstr "Način ravnotežja bele barve, uporabljen med zajemanjem slike" + +msgid "capturing contrast" +msgstr "kontrast zajema" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Smer kontrasta, uporabljenega med zajemanjem slike" + +msgid "capturing saturation" +msgstr "nasičenost zajema" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Smer nasičenosti, uporabljene med zajemanjem slike" + +msgid "capturing sharpness" +msgstr "ostrina zajema" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Smer ostrine, uporabljene med zajemanjem slike" + +msgid "capturing flash fired" +msgstr "sproženje bliskavice med zajemanjem" + +msgid "If the flash fired while capturing an image" +msgstr "Ali je med zajemanjem slike bliskavica sprožena" + +msgid "capturing flash mode" +msgstr "način bliskavice med zajemanjem" + +msgid "The selected flash mode while capturing an image" +msgstr "Izbrani način bliskavice, uporabljene med zajemanjem slike" + +msgid "capturing metering mode" +msgstr "način umerjanja med zajemanjem" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Način umerjanja, uporabljen med določevanjem osvetljenosti zajemanja slike" + +msgid "capturing source" +msgstr "vir zajema" + +msgid "The source or type of device used for the capture" +msgstr "Vir ali vrsta naprave, uporabljene za zajemanje" + +msgid "image horizontal ppi" +msgstr "vodoravne slikovne točke slike (ppi)" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Gostota vodoravnih slikovnih točk (v ppi)" + +msgid "image vertical ppi" +msgstr "navpične slikovne točke slike (ppi)" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Gostota navpičnih slikovnih točk (v ppi)" + +msgid "This CD has no audio tracks" +msgstr "Ta CD nima zvočnih sledi" + +msgid "ID3 tag" +msgstr "Oznaka ID3" + +msgid "APE tag" +msgstr "Oznaka APE" + +msgid "ICY internet radio" +msgstr "Internetni radio ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Govor Windows Media" + +msgid "CYUV Lossless" +msgstr "Brezizgubni CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Brezizgubni MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Nestisnjena sivinska slika" + +msgid "Run-length encoding" +msgstr "Kodiranje trajanja izvajanja" + +msgid "Sami subtitle format" +msgstr "Oblika podnapisov Sami" + +msgid "TMPlayer subtitle format" +msgstr "Oblika podnapisov TMPlayer" + +msgid "Kate subtitle format" +msgstr "Oblika podnapisov Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Nestisnjen ploskovni YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Nestisnjen ploskovni YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Nestisnjen pakiran YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Nestisnjen pakiran YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Nestisnjen pakiran YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Nestisnjen pakiran YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Nestisnjen pakiran YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Nestisnjen ploskovni YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Nestisnjen ploskovni YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Nestisnjena črno-bela slika Y-ravnine" + +msgid "Uncompressed YUV" +msgstr "Nestisnjen YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Nestisnjen paletni %d-bitni %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 različice %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Surovi %d-bitni zvok PCM" + +msgid "Raw PCM audio" +msgstr "Surovi zvok PCM" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Surovi %d-bitni zvok, določen s plavajočo vejico" + +msgid "Raw floating-point audio" +msgstr "Surovi zvok, določen s plavajočo vejico" + +msgid "Audio CD source" +msgstr "Vir zvočnega CD-ja" + +msgid "DVD source" +msgstr "Vir DVD-ja" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Vir protokola Real Time Streaming Protocol (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Vir protokola Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Vir protokola %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "Razlagalnik video vsebine %s RTP" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "Razlagalnik zvočne vsebine %s RTP" + +#, c-format +msgid "%s RTP depayloader" +msgstr "Razlagalnik vsebine %s RTP" + +#, c-format +msgid "%s demuxer" +msgstr "Odvijalnik %s" + +#, c-format +msgid "%s decoder" +msgstr "Odkodirnik %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "Nalagalnik video vsebine %s RTP" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "Nalagalnik zvočne vsebine %s RTP" + +#, c-format +msgid "%s RTP payloader" +msgstr "Nalagalnik vsebine %s RTP" + +#, c-format +msgid "%s muxer" +msgstr "Zvijalnik %s" + +#, c-format +msgid "%s encoder" +msgstr "Kodirnik %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Predmet GStreamer %s" + +msgid "Unknown source element" +msgstr "Neznan predmet vira" + +msgid "Unknown sink element" +msgstr "Neznan predmet ponora" + +msgid "Unknown element" +msgstr "Neznan predmet" + +msgid "Unknown decoder element" +msgstr "Neznan predmet odkodirnika" + +msgid "Unknown encoder element" +msgstr "Neznan predmet kodirnika" + +msgid "Plugin or element of unknown type" +msgstr "Vstavek ali predmet neznane vrste" + +msgid "No device specified." +msgstr "Ni navedene naprave." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Naprava \"%s\" ne obstaja." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Naprava \"%s\" je že v uporabi." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Naprave \"%s\" ni mogoče odpreti za branje in pisanje." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Ni določenega izvornega pogona" + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Ni mogoče ustvariti datoteke predpomnilnika" + +#, fuzzy +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Ni mogoče odpreti CD naprave za branje." + +#, fuzzy +#~ msgid "Internal data flow error." +#~ msgstr "Notranja napaka pretoka podatkov." + +#, fuzzy +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Elementa filesrc ni mogoče ustvariti" + +#, fuzzy +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Elementa filesrc ni mogoče ustvariti" + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Elementa filesrc ni mogoče ustvariti" diff --git a/gst-plugins-base-subtitles0.10/po/sq.po b/gst-plugins-base-subtitles0.10/po/sq.po new file mode 100644 index 0000000..bad1b7f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/sq.po @@ -0,0 +1,756 @@ +# Përkthimi i mesazheve të gst-plugins në shqip. +# Copyright (C) 2004 Free Software Foundation, Inc. +# Laurent Dhima , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins 0.8.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-08-07 20:29+0200\n" +"Last-Translator: Laurent Dhima \n" +"Language-Team: Albanian \n" +"Language: sq\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Treble" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Sintetizuesi" + +msgid "Line-in" +msgstr "Linja-hyrje" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofoni" + +#, fuzzy +msgid "PC Speaker" +msgstr "Zë folës" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "E pamundur hapja e dispozitivit të zërit \"%s\" për shkrim." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "E pamundur hapja e dispozitivit \"%s\" për lexim dhe shkrim." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +msgid "Could not open CD device for reading." +msgstr "I pamundur hapja e dispozitivit CD për lexim." + +#, fuzzy +msgid "Could not seek CD." +msgstr "E pamundur mbyllja e file vfs \"%s\"." + +#, fuzzy +msgid "Could not read CD." +msgstr "I pamundur shkrimi në dispozitivin \"%s\"." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "E pamundur hapja e file vfs \"%s\" për shkrim: %s." + +msgid "No filename given" +msgstr "Nuk është dhënë asnjë emër file" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "E pamundur mbyllja e file vfs \"%s\"." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Gabim gjatë mbylljes së file \"%s\"." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "I pamundur shkrimi tek file \"%s\"." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "Dispozitivi \"%s\" nuk është një dispozitiv marrje." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Gabim gjatë mbylljes së file \"%s\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "Nuk është përcaktuar asnjë dispozitiv." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Dispozitivi \"%s\" nuk ekziston." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "Dispozitivi OSS \"%s\" është duke u përdorur nga një tjetër program." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "E pamundur hapja e dispozitivit \"%s\" për lexim dhe shkrim." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "I pamundur shkrimi tek file \"%s\"." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Nuk është përcaktuar asnjë dispozitiv." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "I pamundur shkrimi tek file \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "E pamundur hapja e file \"%s\" për lexim." + +#~ msgid "Device is not open." +#~ msgstr "Dispozitivi nuk është hapur." + +#~ msgid "Device is open." +#~ msgstr "Dispozitivi është i hapur." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "E pamundur hapja e file vfs \"%s\" për lexim." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "Nuk është dhënë asnjë emër file" + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "E pamundur hapja e file \"%s\" në shkrim." + +#~ msgid "No filename specified." +#~ msgstr "Nuk është përcaktuar emri i file." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "Input audio i gabuar ose mungon, stream AVI mund të jetë i dëmtuar." + +#~ msgid "" +#~ "The %s element could not be found. This element is essential for " +#~ "playback. Please install the right plug-in and verify that it works by " +#~ "running 'gst-inspect %s'" +#~ msgstr "" +#~ "E pamundur gjetja e elementit %s. Ky element është thelbësor për " +#~ "playback. Ju lutem instaloni plug-in e duhur dhe kontrollo funksionimin " +#~ "duke ekzekutuar 'gst-inspect %s'" + +#~ msgid "" +#~ "No usable colorspace element could be found.\n" +#~ "Please install one and restart." +#~ msgstr "" +#~ "Nuk arrin të gjehet asnjë element ngjyra e hapësirës.\n" +#~ "Ju lutem instaloni një dhe rinisni." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "E pamundur hapja e dispozitivit të kontrollit \"%s\" për shkrim." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "I pamundur konfigurimi i dispozitivit të zërit \"%s\"." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "I pamundur rregullimi i dispozitivit audio \"%s\" në %d Hz." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "E pamundur mbyllja e dispozitivit audio \"%s\"." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "E pamundur mbyllja e dispozitivit të kontrollit \"%s\"." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "E pamundur hapja e dispozitivit video \"%s\" për shkrim." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "E pamundur mbyllja e dispozitivit video \"%s\"." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "" +#~ "E pamundur futja në dispozitivin \"%s\", kontrollo të drejtat e tij." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "E pamundur hapja e dispozitivit \"%s\" për shkrim." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "E pamundur hapja e dispozitivit \"%s\" për lexim." + +#, fuzzy +#~ msgid "Your OSS device doesn't support mono or stereo." +#~ msgstr "Dispozitivi juaj OSS mund të mos provohet korrektësisht" + +#~ msgid "Your OSS device could not be probed correctly" +#~ msgstr "Dispozitivi juaj OSS mund të mos provohet korrektësisht" + +#~ msgid "Volume" +#~ msgstr "Volumi" + +#~ msgid "Speaker" +#~ msgstr "Zë folës" + +#~ msgid "Mixer" +#~ msgstr "Kontrolli i volumit" + +#~ msgid "PCM-2" +#~ msgstr "PCM-2" + +#~ msgid "Record" +#~ msgstr "Regjistrimi" + +#~ msgid "In-gain" +#~ msgstr "In-gain" + +#~ msgid "Out-gain" +#~ msgstr "Out-gain" + +#~ msgid "Line-1" +#~ msgstr "Linja-1" + +#~ msgid "Line-2" +#~ msgstr "Linja-2" + +#~ msgid "Line-3" +#~ msgstr "Linja-3" + +#~ msgid "Digital-1" +#~ msgstr "Dixhitale-1" + +#~ msgid "Digital-2" +#~ msgstr "Dixhitale-2" + +#~ msgid "Digital-3" +#~ msgstr "Dixhitale-3" + +#~ msgid "Phone-in" +#~ msgstr "Phone-hyrja" + +#~ msgid "Phone-out" +#~ msgstr "Phone-dalja" + +#~ msgid "Video" +#~ msgstr "Video" + +#~ msgid "Radio" +#~ msgstr "Radio" + +#~ msgid "Monitor" +#~ msgstr "Ekrani" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "E pamundur marrja e buffers nga dispozitivi \"%s\"." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "E pamundur marrja e buffers të mjaftueshëm nga dispozitivi \"%s\"." diff --git a/gst-plugins-base-subtitles0.10/po/sr.po b/gst-plugins-base-subtitles0.10/po/sr.po new file mode 100644 index 0000000..ea5a7b1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/sr.po @@ -0,0 +1,736 @@ +# Serbian translation of gst-plugins +# Copyright (C) 2004 Free Software Foundation, Inc. +# Danilo Segan , 2004. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins 0.7.6\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2004-03-13 00:18+0100\n" +"Last-Translator: Danilo Segan \n" +"Language-Team: Serbian \n" +"Language: sr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +msgid "Master" +msgstr "" + +msgid "Bass" +msgstr "Бас" + +msgid "Treble" +msgstr "Шум" + +msgid "PCM" +msgstr "ПЦМ" + +msgid "Synth" +msgstr "Синт." + +msgid "Line-in" +msgstr "Ул.лин." + +msgid "CD" +msgstr "ЦД" + +msgid "Microphone" +msgstr "Микрофон" + +#, fuzzy +msgid "PC Speaker" +msgstr "Звучник" + +msgid "Playback" +msgstr "" + +msgid "Capture" +msgstr "" + +#, fuzzy +msgid "Could not open device for playback in mono mode." +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy +msgid "Could not open device for playback in stereo mode." +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Не могу да отворим ЦД уређај ради читања." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" + +#, fuzzy +msgid "Could not open audio device for playback." +msgstr "Не могу да отворим звучни уређај „%s“ ради уписа." + +#, fuzzy +msgid "Could not open device for recording in mono mode." +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy +msgid "Could not open device for recording in stereo mode." +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "Не могу да отворим уређај „%s“ ради читања и уписа." + +#, fuzzy +msgid "Could not open audio device for recording." +msgstr "Не могу да отворим ЦД уређај ради читања." + +msgid "Could not open CD device for reading." +msgstr "Не могу да отворим ЦД уређај ради читања." + +#, fuzzy +msgid "Could not seek CD." +msgstr "Не могу да затворим ВСД датотеку „%s“." + +#, fuzzy +msgid "Could not read CD." +msgstr "Не могу да пишем на видео уређај „%s“." + +#, fuzzy, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Не могу да отворим ВСД датотеку „%s“ ради уписа." + +#, fuzzy +msgid "No filename given" +msgstr "Име датотеке није задато." + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Не могу да затворим ВСД датотеку „%s“." + +#, fuzzy, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Грешка при затварању датотеке „%s“." + +msgid "Internal data stream error." +msgstr "" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" + +msgid "This appears to be a text file" +msgstr "" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "Не могу да пишем у датотеку „%s“." + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "" + +msgid "No URI specified to play from." +msgstr "" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "" + +msgid "RTSP streams cannot be played yet." +msgstr "" + +msgid "Could not create \"decodebin\" element." +msgstr "" + +msgid "Source element is invalid." +msgstr "" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" + +#, fuzzy +msgid "This is not a media file" +msgstr "Уређај „%s“ не представља уређај за снимање." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "" + +msgid "The autovideosink element is missing." +msgstr "" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "" + +msgid "The autovideosink element is not working." +msgstr "" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "" + +msgid "The autoaudiosink element is missing." +msgstr "" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "" + +msgid "The autoaudiosink element is not working." +msgstr "" + +msgid "Can't play a text file without video or visualizations." +msgstr "" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "" + +msgid "This stream type cannot be played yet." +msgstr "" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "" + +#, fuzzy, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Грешка при затварању датотеке „%s“." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "" + +msgid "Can't record audio fast enough" +msgstr "" + +msgid "Failed to read tag: not enough data" +msgstr "" + +msgid "track ID" +msgstr "" + +msgid "MusicBrainz track ID" +msgstr "" + +msgid "artist ID" +msgstr "" + +msgid "MusicBrainz artist ID" +msgstr "" + +msgid "album ID" +msgstr "" + +msgid "MusicBrainz album ID" +msgstr "" + +msgid "album artist ID" +msgstr "" + +msgid "MusicBrainz album artist ID" +msgstr "" + +msgid "track TRM ID" +msgstr "" + +msgid "MusicBrainz TRM ID" +msgstr "" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "" + +msgid "ID3 tag" +msgstr "" + +msgid "APE tag" +msgstr "" + +msgid "ICY internet radio" +msgstr "" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" + +msgid "Lossless True Audio (TTA)" +msgstr "" + +msgid "Windows Media Speech" +msgstr "" + +msgid "CYUV Lossless" +msgstr "" + +msgid "FFMpeg v1" +msgstr "" + +msgid "Lossless MSZH" +msgstr "" + +msgid "Uncompressed Gray Image" +msgstr "" + +msgid "Run-length encoding" +msgstr "" + +msgid "Sami subtitle format" +msgstr "" + +msgid "TMPlayer subtitle format" +msgstr "" + +msgid "Kate subtitle format" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "" + +msgid "Uncompressed black and white Y-plane" +msgstr "" + +msgid "Uncompressed YUV" +msgstr "" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "" + +msgid "Raw PCM audio" +msgstr "" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "" + +msgid "Raw floating-point audio" +msgstr "" + +msgid "Audio CD source" +msgstr "" + +msgid "DVD source" +msgstr "" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" + +#, c-format +msgid "%s protocol source" +msgstr "" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "" + +#, c-format +msgid "%s RTP depayloader" +msgstr "" + +#, c-format +msgid "%s demuxer" +msgstr "" + +#, c-format +msgid "%s decoder" +msgstr "" + +#, c-format +msgid "%s video RTP payloader" +msgstr "" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "" + +#, c-format +msgid "%s RTP payloader" +msgstr "" + +#, c-format +msgid "%s muxer" +msgstr "" + +#, c-format +msgid "%s encoder" +msgstr "" + +#, c-format +msgid "GStreamer element %s" +msgstr "" + +msgid "Unknown source element" +msgstr "" + +msgid "Unknown sink element" +msgstr "" + +msgid "Unknown element" +msgstr "" + +msgid "Unknown decoder element" +msgstr "" + +msgid "Unknown encoder element" +msgstr "" + +msgid "Plugin or element of unknown type" +msgstr "" + +msgid "No device specified." +msgstr "Уређај није наведен." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Не постоји уређај „%s“." + +#, fuzzy, c-format +msgid "Device \"%s\" is already being used." +msgstr "OSS уређај „%s“ већ користи неки програм." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Не могу да отворим уређај „%s“ ради читања и уписа." + +#, fuzzy +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Не могу да пишем у датотеку „%s“." + +#, fuzzy +#~ msgid "No Temp directory specified." +#~ msgstr "Уређај није наведен." + +#, fuzzy +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Не могу да пишем у датотеку „%s“." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Не могу да отворим датотеку „%s“ ради читања." + +#~ msgid "Device is not open." +#~ msgstr "Уређај није отворен." + +#~ msgid "Device is open." +#~ msgstr "Уређај је отворен." + +# Виртуелни Систем Датотека +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "Не могу да отворим ВСД датотеку „%s“ ради читања." + +#, fuzzy +#~ msgid "No filename given." +#~ msgstr "Име датотеке није задато." + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "Не могу да отворим датотеку „%s“ ради уписа." + +#~ msgid "No filename specified." +#~ msgstr "Име датотеке није задато." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "Улазног звука нема или је неисправан, АВИ ток ће бити искварен." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "Не могу да отворим управљачки уређај „%s“ ради уписа." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "Не могу да подесим звучни уређај „%s“." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "Не могу да поставим звучни уређај „%s“ на %d Hz." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "Не могу да отворим радио уређај '%s'" + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "Не могу да затворим управљачки уређај „%s“." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "Не могу да отворим видео уређај „%s“ ради уписа." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "Не могу да затворим видео уређај „%s“." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "Не могу да приступим уређају „%s“, проверите његова овлашћења." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "Не могу да отворим уређај „%s“ ради уписа." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "Не могу да отворим уређај „%s“ ради читања." + +#~ msgid "Volume" +#~ msgstr "Јачина звука" + +#~ msgid "Speaker" +#~ msgstr "Звучник" + +#~ msgid "Mixer" +#~ msgstr "Миксер" + +#~ msgid "PCM-2" +#~ msgstr "ПЦМ-2" + +#~ msgid "Record" +#~ msgstr "Снимање" + +#~ msgid "In-gain" +#~ msgstr "Ул. пој." + +#~ msgid "Out-gain" +#~ msgstr "Из. пој." + +#~ msgid "Line-1" +#~ msgstr "Лин. 1" + +#~ msgid "Line-2" +#~ msgstr "Лин. 2" + +#~ msgid "Line-3" +#~ msgstr "Лин. 3" + +#~ msgid "Digital-1" +#~ msgstr "Диг. 1" + +#~ msgid "Digital-2" +#~ msgstr "Диг. 2" + +#~ msgid "Digital-3" +#~ msgstr "Диг. 3" + +#~ msgid "Phone-in" +#~ msgstr "Тел. ул." + +#~ msgid "Phone-out" +#~ msgstr "Тел. из." + +#~ msgid "Video" +#~ msgstr "Видео" + +#~ msgid "Radio" +#~ msgstr "Радио" + +#~ msgid "Monitor" +#~ msgstr "Праћење" + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "Не могу да примим бафере са уређаја „%s“." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "Не могу да примим довољно бафера са уређаја „%s“." diff --git a/gst-plugins-base-subtitles0.10/po/sv.po b/gst-plugins-base-subtitles0.10/po/sv.po new file mode 100644 index 0000000..58eaf21 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/sv.po @@ -0,0 +1,1776 @@ +# Swedish messages for gst-plugins-base. +# Copyright (C) 2004, 2007, 2008, 2009 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# Christian Rose , 2004. +# Daniel Nylander , 2007, 2008, 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.28.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-06-07 18:17+0100\n" +"Last-Translator: Daniel Nylander \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Övergripande" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Diskant" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synt" + +msgid "Line-in" +msgstr "Linje-in" + +msgid "CD" +msgstr "Cd" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC-högtalare" + +msgid "Playback" +msgstr "Uppspelning" + +msgid "Capture" +msgstr "Fångst" + +msgid "Could not open device for playback in mono mode." +msgstr "Kunde inte öppna enheten för uppspelning i monoläge." + +msgid "Could not open device for playback in stereo mode." +msgstr "Kunde inte öppna enheten för uppspelning i stereoläge." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Kunde inte öppna enheten för uppspelning i %d-kanalsläge." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Kunde inte öppna ljudenheten för uppspelning. Enheten används av ett annat " +"program." + +msgid "Could not open audio device for playback." +msgstr "Kunde inte öppna ljudenheten för uppspelning." + +msgid "Could not open device for recording in mono mode." +msgstr "Kunde inte öppna enheten för inspelning i monoläge." + +msgid "Could not open device for recording in stereo mode." +msgstr "Kunde inte öppna enheten för inspelning i stereoläge." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Kunde inte öppna enheten för inspelning i %d-kanalsläge." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Kunde inte öppna ljudenheten för inspelning. Enheten används av ett annat " +"program." + +msgid "Could not open audio device for recording." +msgstr "Kunde inte öppna ljudenheten för inspelning." + +msgid "Could not open CD device for reading." +msgstr "Kunde inte öppna cd-enheten för läsning." + +msgid "Could not seek CD." +msgstr "Kunde inte söka på cd-skivan." + +msgid "Could not read CD." +msgstr "Kunde inte läsa cd-skivan." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Kunde inte öppna vfs-filen \"%s\" för skrivning: %s." + +msgid "No filename given" +msgstr "Inget filnamn angivet" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Kunde inte stänga vfs-filen \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Fel vid skrivning till filen \"%s\"." + +msgid "Internal data stream error." +msgstr "Internt dataströmfel." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "" +"En %s-insticksmodul krävs för att spela upp den här strömmen men är inte " +"installerad." + +msgid "This appears to be a text file" +msgstr "Den här ser ut att vara en textfil" + +msgid "Could not determine type of stream" +msgstr "Kunde inte fastställa typ av ström" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Ogiltig uri för undertext \"%s\", undertexter inaktiverade." + +msgid "No URI specified to play from." +msgstr "Ingen uri angiven att spela upp från." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Ogiltig uri \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP-strömmar kan inte spelas upp än." + +msgid "Could not create \"decodebin\" element." +msgstr "Kunde inte skapa \"decodebin\"-element." + +msgid "Source element is invalid." +msgstr "Källelementet är ogiltigt." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Endast en undertextström identifierades. Antingen läser du in en " +"undertextfil eller någon annan typ av textfil, eller så kändes inte " +"mediafilen igen." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Du har inte en installerad avkodare som kan hantera den här filen. Du kanske " +"behöver installera de nödvändiga insticksmodulerna." + +msgid "This is not a media file" +msgstr "Det här är inte en mediafil" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "En undertextström identifierades men ingen videoström." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Både autovideosink- och xvimagesink-elementet saknas." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Saknar elementet \"%s\" - kontrollera din GStreamer-installation." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Både autoaudiosink- och alsasink-elementet saknas." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Både autovideosink- och %s-elementet saknas." + +msgid "The autovideosink element is missing." +msgstr "Elementet autovideosink saknas." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Konfigurerat videosink %s fungerar inte." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Det finns både autovideosink- och %s-element som inte fungerar." + +msgid "The autovideosink element is not working." +msgstr "Elementet autovideosink fungerar inte." + +msgid "Custom text sink element is not usable." +msgstr "Anpassat text sink-element är inte användbart." + +msgid "No volume control found" +msgstr "Ingen volymkontroll hittades" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Både autoaudiosink- och %s-elementet saknas." + +msgid "The autoaudiosink element is missing." +msgstr "Elementet autoaudiosink saknas." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Konfigurerat audiosink %s fungerar inte." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Det finns både autoaudiosink- och %s-element som inte fungerar.." + +msgid "The autoaudiosink element is not working." +msgstr "Elementet autoaudiosink fungerar inte." + +msgid "Can't play a text file without video or visualizations." +msgstr "Kan inte spela upp en textfil utan video eller visualiseringar." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Ingen avkodare finns tillgänglig för typen \"%s\"." + +msgid "This stream type cannot be played yet." +msgstr "Den här strömtypen kan inte spelas upp än." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Ingen URI-hanterare implementerad för \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Fel vid sändning av data till \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Fel vid sändning av gdp-huvuddata till \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Fel vid sändning av gdp-paketdata till \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Anslutningen till %s:%d nekades." + +msgid "Can't record audio fast enough" +msgstr "Kan inte spela in ljud tillräckligt snabbt" + +msgid "Failed to read tag: not enough data" +msgstr "Misslyckades med att läsa tagg: inte tillräckligt mycket data" + +msgid "track ID" +msgstr "spår-id" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz spår-id" + +msgid "artist ID" +msgstr "artist-id" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz artist-id" + +msgid "album ID" +msgstr "album-id" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz album-id" + +msgid "album artist ID" +msgstr "albumartist-id" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albumartist-id" + +msgid "track TRM ID" +msgstr "spår TRM-ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM-ID" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Den här cd-skivan saknar ljudspår" + +msgid "ID3 tag" +msgstr "ID3-tagg" + +msgid "APE tag" +msgstr "APE-tagg" + +msgid "ICY internet radio" +msgstr "ICY internetradio" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "Förlustfri CYUV" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Förlustfri MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Okomprimerad gråskalebild" + +msgid "Run-length encoding" +msgstr "Körlängdskodning" + +msgid "Sami subtitle format" +msgstr "Undertextformatet Sami" + +msgid "TMPlayer subtitle format" +msgstr "Undertextformatet TMPlayer" + +msgid "Kate subtitle format" +msgstr "Undertextformatet Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Okomprimerad plan YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Okomprimerad plan YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Okomprimerad paketerad YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Okomprimerad paketerad YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Okomprimerad paketerad YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Okomprimerad paketerad YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Okomprimerad paketerad YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Okomprimerad plan YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Okomprimerad plan YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Okomprimerad svartvitt y-plan" + +msgid "Uncompressed YUV" +msgstr "Okomprimerad YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Okomprimerad palettiserad %d-bitars %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 version %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Rått %d-bitars PCM-ljud" + +msgid "Raw PCM audio" +msgstr "Rått PCM-ljud" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Rått %d-bitars flyttalsljud" + +msgid "Raw floating-point audio" +msgstr "Rått flyttalsljud" + +msgid "Audio CD source" +msgstr "Ljud-cd-källa" + +msgid "DVD source" +msgstr "Dvd-källa" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Real Time Streaming Protocol-källa (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Media Server-protokollkälla (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "%s-protokollkälla" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s RTP-uppackare (video)" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s RTP-uppackare (ljud)" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP-uppackare" + +#, c-format +msgid "%s demuxer" +msgstr "%s-avmultiplexor" + +#, c-format +msgid "%s decoder" +msgstr "%s-avkodare" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s RTP-packare (video)" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s RTP-packare (ljud)" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP-packare" + +#, c-format +msgid "%s muxer" +msgstr "%s-multiplexor" + +#, c-format +msgid "%s encoder" +msgstr "%s-kodare" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer-elementet %s" + +msgid "Unknown source element" +msgstr "Okänt source-element" + +msgid "Unknown sink element" +msgstr "Okänt sink-element" + +msgid "Unknown element" +msgstr "Okänt element" + +msgid "Unknown decoder element" +msgstr "Okänt avkodarelement" + +msgid "Unknown encoder element" +msgstr "Okänt kodarelement" + +msgid "Plugin or element of unknown type" +msgstr "Insticksmodul eller element av okänd typ" + +msgid "No device specified." +msgstr "Ingen enheten angiven." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Enheten \"%s\" finns inte." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Enheten \"%s\" används redan." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Kunde inte öppna enheten \"%s\" för läsning och skrivning." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Kan inte visa både undertexter och underbilder." + +#~ msgid "No Temp directory specified." +#~ msgstr "Ingen temporärkatalog har angivits." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Kunde inte skapa temporärfilen \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Kunde inte öppna filen \"%s\" för läsning." + +#~ msgid "Internal data flow error." +#~ msgstr "Internt dataflödesfel." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Kunde inte skapa \"decodebin2\"-element." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Kunde inte skapa \"queue2\"-element." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Kunde inte skapa \"typefind\"-element." + +#~ msgid "No file name specified." +#~ msgstr "Inget filnamn angivet." + +#~ msgid "artist sortname" +#~ msgstr "artistsorteringsnamn" + +#~ msgid "MusicBrainz artist sortname" +#~ msgstr "MusicBrainz sorteringsnamn för artist" + +#~ msgid "discid" +#~ msgstr "skiv-id" + +#~ msgid "Device is not open." +#~ msgstr "Enheten är inte öppen." + +#~ msgid "Device is open." +#~ msgstr "Enheten är öppen." + +#~ msgid "Could not open vfs file \"%s\" for reading." +#~ msgstr "Kunde inte öppna vfs-filen \"%s\" för läsning." + +#~ msgid "No filename given." +#~ msgstr "Inget filnamn angivet." + +#~ msgid "Could not open file \"%s\" for writing." +#~ msgstr "Kunde inte öppna filen \"%s\" för skrivning." + +#~ msgid "No or invalid input audio, AVI stream will be corrupt." +#~ msgstr "Inget eller ogiltigt inljud. AVI-flödet kommer att skadas." + +#~ msgid "" +#~ "The %s element could not be found. This element is essential for " +#~ "playback. Please install the right plug-in and verify that it works by " +#~ "running 'gst-inspect %s'" +#~ msgstr "" +#~ "Elementet %s kunde inte hittas. Detta element är nödvändigt för " +#~ "uppspelning. Installera rätt insticksmodul och verifiera att den fungerar " +#~ "genom att köra \"gst-inspect %s\"" + +#~ msgid "" +#~ "No usable colorspace element could be found.\n" +#~ "Please install one and restart." +#~ msgstr "" +#~ "Inget användbart namnrymdselement kunde hittas.\n" +#~ "Installera ett och starta om." + +#~ msgid "Could not open audio device \"%s\" for writing." +#~ msgstr "Kunde inte öppna ljudenheten \"%s\" för skrivning." + +#~ msgid "Could not open control device \"%s\" for writing." +#~ msgstr "Kunde inte öppna styrenheten \"%s\" för skrivning." + +#~ msgid "Could not configure audio device \"%s\"." +#~ msgstr "Kunde inte konfigurera ljudenheten \"%s\"." + +#~ msgid "Could not set audio device \"%s\" to %d Hz." +#~ msgstr "Kan inte ställa in ljudenheten \"%s\" till %d Hz." + +#~ msgid "Could not close audio device \"%s\"." +#~ msgstr "Kunde inte stänga ljudenheten \"%s\"." + +#~ msgid "Could not close control device \"%s\"." +#~ msgstr "Kunde inte stänga styrenheten \"%s\"." + +#~ msgid "Could not open video device \"%s\" for writing." +#~ msgstr "Kunde inte öppna videoenheten \"%s\" för skrivning." + +#~ msgid "Could not close video device \"%s\"." +#~ msgstr "Kunde inte stänga vidoeenheten \"%s\"." + +#~ msgid "Could not write to device \"%s\"." +#~ msgstr "Kunde inte skriva till enheten \"%s\"." + +#~ msgid "Could not access device \"%s\", check its permissions." +#~ msgstr "Kunde inte komma åt enheten \"%s\". Kontrollera dess rättigheter." + +#~ msgid "Could not open device \"%s\" for writing." +#~ msgstr "Kunde inte öppna enheten \"%s\" för skrivning." + +#~ msgid "Could not open device \"%s\" for reading." +#~ msgstr "Kunde inte öppna enheten \"%s\" för läsning." + +#~ msgid "Your OSS device doesn't support mono or stereo." +#~ msgstr "Din OSS-enhet saknar stöd för mono eller stereo." + +#~ msgid "Your OSS device could not be probed correctly" +#~ msgstr "Din OSS-enhet kunde inte undersökas korrekt" + +#~ msgid "Volume" +#~ msgstr "Volym" + +#~ msgid "Speaker" +#~ msgstr "Högtalare" + +#~ msgid "Mixer" +#~ msgstr "Mixer" + +#~ msgid "PCM-2" +#~ msgstr "PCM-2" + +#~ msgid "Record" +#~ msgstr "Spela in" + +#~ msgid "In-gain" +#~ msgstr "Införstärkning" + +#~ msgid "Out-gain" +#~ msgstr "Utförstärkning" + +#~ msgid "Line-1" +#~ msgstr "Linje-1" + +#~ msgid "Line-2" +#~ msgstr "Linje-2" + +#~ msgid "Line-3" +#~ msgstr "Linje-3" + +#~ msgid "Digital-1" +#~ msgstr "Digital-1" + +#~ msgid "Digital-2" +#~ msgstr "Digital-2" + +#~ msgid "Digital-3" +#~ msgstr "Digital-3" + +#~ msgid "Phone-in" +#~ msgstr "Tele-in" + +#~ msgid "Phone-out" +#~ msgstr "Tele-ut" + +#~ msgid "Video" +#~ msgstr "Video" + +#~ msgid "Radio" +#~ msgstr "Radio" + +#~ msgid "Monitor" +#~ msgstr "Monitor" + +#~ msgid "Device \"%s\" is not a capture device." +#~ msgstr "Enheten \"%s\" är ingen fångstenhet." + +#~ msgid "Could not get buffers from device \"%s\"." +#~ msgstr "Kunde inte få tag i buffertar från enheten \"%s\"." + +#~ msgid "Could not get enough buffers from device \"%s\"." +#~ msgstr "" +#~ "Kunde inte få tag i tillräckligt många buffertar från enheten \"%s\"." + +#~ msgid "Line" +#~ msgstr "Linje" + +#~ msgid "Digital" +#~ msgstr "Digital" + +#~ msgid "Phone in" +#~ msgstr "Tele in" + +#~ msgid "Phone out" +#~ msgstr "Tele ut" + +#~ msgid "Address of the server to contact for CD queries" +#~ msgstr "Adress till servern som ska kontaktas för cd-frågor" + +#~ msgid "Information to send to server" +#~ msgstr "Information att skicka till server" + +#~ msgid "Port" +#~ msgstr "Port" + +#~ msgid "Server name" +#~ msgstr "Servernamn" + +#~ msgid "Server type" +#~ msgstr "Servertyp" + +#~ msgid "The hostname that will be sent with all queries" +#~ msgstr "Värdnamnet som kommer att skickas med alla frågor" + +#~ msgid "The port that the server is running the database on" +#~ msgstr "Porten som servern kör databasen på" + +#~ msgid "" +#~ "There was an error displaying help: \n" +#~ "%s" +#~ msgstr "" +#~ "Det uppstod ett fel vid visning av hjälp: \n" +#~ "%s" + +#~ msgid "Login Information" +#~ msgstr "Inloggningsinformation" + +#~ msgid "Sen_d no information" +#~ msgstr "Ski_cka ingen information" + +#~ msgid "Send real _information" +#~ msgstr "Skicka verklig _information" + +#~ msgid "Send _other information:" +#~ msgstr "Skicka _annan information:" + +#~ msgid "_Name:" +#~ msgstr "_Namn:" + +#~ msgid "Hostna_me:" +#~ msgstr "Värdna_mn:" + +#~ msgid "Server" +#~ msgstr "Server" + +#~ msgid "Location" +#~ msgstr "Plats" + +#~ msgid "_Update Server List" +#~ msgstr "_Uppdatera serverlistan" + +#~ msgid "Other _server:" +#~ msgstr "Annan _server:" + +#~ msgid "Hos_tname:" +#~ msgstr "Vä_rdnamn:" + +#~ msgid "_Port:" +#~ msgstr "_Port:" + +#~ msgid "CD Database Preferences" +#~ msgstr "Inställningar för cd-databas" + +#~ msgid "Unknown / Unknown" +#~ msgstr "Okänd / Okänd" + +#~ msgid "Unknown" +#~ msgstr "Okänd" + +#~ msgid "Multiple matches..." +#~ msgstr "Flera träffar..." + +#~ msgid "Category" +#~ msgstr "Kategori" + +#~ msgid "Artist and Title" +#~ msgstr "Artist och titel" + +#~ msgid "Unknown track" +#~ msgstr "Okänt spår" + +#~ msgid "CD Database" +#~ msgstr "Cd-databas" + +#~ msgid "Modify your CD database preferences" +#~ msgstr "Ändra dina inställningar för cd-databas" + +#~ msgid "Blues" +#~ msgstr "Blues" + +#~ msgid "Classical Rock" +#~ msgstr "Klassisk rock" + +#~ msgid "Country" +#~ msgstr "Country" + +#~ msgid "Dance" +#~ msgstr "Dance" + +#~ msgid "Disco" +#~ msgstr "Disco" + +#~ msgid "Funk" +#~ msgstr "Funk" + +#~ msgid "Grunge" +#~ msgstr "Grunge" + +#~ msgid "Hip-Hop" +#~ msgstr "Hip-Hop" + +#~ msgid "Jazz" +#~ msgstr "Jazz" + +#~ msgid "Metal" +#~ msgstr "Metal" + +#~ msgid "New Age" +#~ msgstr "New Age" + +#~ msgid "Oldies" +#~ msgstr "Gamla godingar" + +#~ msgid "Other" +#~ msgstr "Annat" + +#~ msgid "Pop" +#~ msgstr "Pop" + +#~ msgid "R&B" +#~ msgstr "R&B" + +#~ msgid "Rap" +#~ msgstr "Rap" + +#~ msgid "Reggae" +#~ msgstr "Reggae" + +#~ msgid "Rock" +#~ msgstr "Rock" + +#~ msgid "Techno" +#~ msgstr "Techno" + +#~ msgid "Industrial" +#~ msgstr "Industrial" + +#~ msgid "Alternative" +#~ msgstr "Alternativmusik" + +#~ msgid "Ska" +#~ msgstr "Ska" + +#~ msgid "Death Metal" +#~ msgstr "Death Metal" + +#~ msgid "Pranks" +#~ msgstr "Pranks" + +#~ msgid "Soundtrack" +#~ msgstr "Filmmusik" + +#~ msgid "Euro-Techno" +#~ msgstr "Euro-Techno" + +#~ msgid "Ambient" +#~ msgstr "Ambient" + +#~ msgid "Trip-Hop" +#~ msgstr "Trip-Hop" + +#~ msgid "Vocal" +#~ msgstr "Vocal" + +#~ msgid "Jazz+Funk" +#~ msgstr "Jazz+Funk" + +#~ msgid "Fusion" +#~ msgstr "Fusion" + +#~ msgid "Trance" +#~ msgstr "Trance" + +#~ msgid "Classical" +#~ msgstr "Klassiskt" + +#~ msgid "Instrumental" +#~ msgstr "Instrumentellt" + +#~ msgid "Acid" +#~ msgstr "Acid" + +#~ msgid "House" +#~ msgstr "House" + +#~ msgid "Game" +#~ msgstr "Spel" + +#~ msgid "Sound Clip" +#~ msgstr "Ljudklipp" + +#~ msgid "Gospel" +#~ msgstr "Gospel" + +#~ msgid "Noise" +#~ msgstr "Brus" + +#~ msgid "Alt" +#~ msgstr "Alt" + +#~ msgid "Soul" +#~ msgstr "Soul" + +#~ msgid "Punk" +#~ msgstr "Punk" + +#~ msgid "Space" +#~ msgstr "Space" + +#~ msgid "Meditative" +#~ msgstr "Meditativt" + +#~ msgid "Instrumental Pop" +#~ msgstr "Instrumentell pop" + +#~ msgid "Instrumental Rock" +#~ msgstr "Instrumentell rock" + +#~ msgid "Ethnic" +#~ msgstr "Folkmusik" + +#~ msgid "Gothic" +#~ msgstr "Gotiskt" + +#~ msgid "Darkwave" +#~ msgstr "Darkwave" + +#~ msgid "Techno-Industrial" +#~ msgstr "Techno-Industrial" + +#~ msgid "Electronic" +#~ msgstr "Electroniskt" + +#~ msgid "Pop-Folk" +#~ msgstr "Pop-Folk" + +#~ msgid "Eurodance" +#~ msgstr "Eurodance" + +#~ msgid "Dream" +#~ msgstr "Dream" + +#~ msgid "Southern Rock" +#~ msgstr "Southern Rock" + +#~ msgid "Comedy" +#~ msgstr "Komedi" + +#~ msgid "Cult" +#~ msgstr "Kult" + +#~ msgid "Gangsta Rap" +#~ msgstr "Gangsta rap" + +#~ msgid "Top 40" +#~ msgstr "Topp 40" + +#~ msgid "Christian Rap" +#~ msgstr "Kristen rap" + +#~ msgid "Pop/Funk" +#~ msgstr "Pop/Funk" + +#~ msgid "Jungle" +#~ msgstr "Jungle" + +#~ msgid "Native American" +#~ msgstr "Amerikansk folkmusik" + +#~ msgid "Cabaret" +#~ msgstr "Kabaré" + +#~ msgid "New Wave" +#~ msgstr "New Wave" + +#~ msgid "Psychedelic" +#~ msgstr "Psykedeliskt" + +#~ msgid "Rave" +#~ msgstr "Rave" + +#~ msgid "Showtunes" +#~ msgstr "Showtunes" + +#~ msgid "Trailer" +#~ msgstr "Trailer" + +#~ msgid "Lo-Fi" +#~ msgstr "Lo-Fi" + +#~ msgid "Tribal" +#~ msgstr "Tribal" + +#~ msgid "Acid Punk" +#~ msgstr "Acid Punk" + +#~ msgid "Acid Jazz" +#~ msgstr "Acid Jazz" + +#~ msgid "Polka" +#~ msgstr "Polka" + +#~ msgid "Retro" +#~ msgstr "Retro" + +#~ msgid "Musical" +#~ msgstr "Musikal" + +#~ msgid "Rock & Roll" +#~ msgstr "Rock & roll" + +#~ msgid "Hard Rock" +#~ msgstr "Hårdrock" + +#~ msgid "Folk" +#~ msgstr "Folk" + +#~ msgid "Folk/Rock" +#~ msgstr "Folk/Rock" + +#~ msgid "National Folk" +#~ msgstr "Nationell folkmusik" + +#~ msgid "Swing" +#~ msgstr "Swing" + +#~ msgid "Fast-Fusion" +#~ msgstr "Fast-Fusion" + +#~ msgid "Bebop" +#~ msgstr "Bebop" + +#~ msgid "Latin" +#~ msgstr "Latinskt" + +#~ msgid "Revival" +#~ msgstr "Uppväckelse" + +#~ msgid "Celtic" +#~ msgstr "Keltiskt" + +#~ msgid "Bluegrass" +#~ msgstr "Bluegrass" + +#~ msgid "Avantgarde" +#~ msgstr "Avantgarde" + +#~ msgid "Gothic Rock" +#~ msgstr "Gotisk rock" + +#~ msgid "Progressive Rock" +#~ msgstr "Progressiv rock" + +#~ msgid "Psychedelic Rock" +#~ msgstr "Psykedelisk rock" + +#~ msgid "Symphonic Rock" +#~ msgstr "Symfonisk rock" + +#~ msgid "Slow Rock" +#~ msgstr "Slow Rock" + +#~ msgid "Big Band" +#~ msgstr "Big Band" + +#~ msgid "Chorus" +#~ msgstr "Kör" + +#~ msgid "Easy Listening" +#~ msgstr "Lättlyssnat" + +#~ msgid "Acoustic" +#~ msgstr "Akustiskt" + +#~ msgid "Humour" +#~ msgstr "Humor" + +#~ msgid "Speech" +#~ msgstr "Tal" + +#~ msgid "Chanson" +#~ msgstr "Chanson" + +#~ msgid "Opera" +#~ msgstr "Opera" + +#~ msgid "Chamber Music" +#~ msgstr "Kammarmusik" + +#~ msgid "Sonata" +#~ msgstr "Sonat" + +#~ msgid "Symphony" +#~ msgstr "Symfoni" + +#~ msgid "Booty Bass" +#~ msgstr "Booty Bass" + +#~ msgid "Primus" +#~ msgstr "Primus" + +#~ msgid "Porn Groove" +#~ msgstr "Porn Groove" + +#~ msgid "Slow Jam" +#~ msgstr "Slow Jam" + +#~ msgid "Club" +#~ msgstr "Klubb" + +#~ msgid "Tango" +#~ msgstr "Tango" + +#~ msgid "Samba" +#~ msgstr "Samba" + +#~ msgid "Folklore" +#~ msgstr "Folklore" + +#~ msgid "Ballad" +#~ msgstr "Ballad" + +#~ msgid "Power Ballad" +#~ msgstr "Power Ballad" + +#~ msgid "Rhythmic Soul" +#~ msgstr "Rhythmic Soul" + +#~ msgid "Freestyle" +#~ msgstr "Freestyle" + +#~ msgid "Duet" +#~ msgstr "Duett" + +#~ msgid "Punk Rock" +#~ msgstr "Punkrock" + +#~ msgid "Drum Solo" +#~ msgstr "Trumsolo" + +#~ msgid "A Cappella" +#~ msgstr "A cappella" + +#~ msgid "Euro-House" +#~ msgstr "Euro-House" + +#~ msgid "Dance Hall" +#~ msgstr "Dance Hall" + +#~ msgid "Goa" +#~ msgstr "Goa" + +#~ msgid "Drum & Bass" +#~ msgstr "Drum & Bass" + +#~ msgid "Club-House" +#~ msgstr "Club-House" + +#~ msgid "Hardcore" +#~ msgstr "Hardcore" + +#~ msgid "Terror" +#~ msgstr "Terror" + +#~ msgid "Indie" +#~ msgstr "Indie" + +#~ msgid "BritPop" +#~ msgstr "BritPop" + +#~ msgid "Negerpunk" +#~ msgstr "Negerpunk" + +#~ msgid "Polsk Punk" +#~ msgstr "Polsk punk" + +#~ msgid "Beat" +#~ msgstr "Beat" + +#~ msgid "Christian Gangsta Rap" +#~ msgstr "Kristen gangsta rap" + +#~ msgid "Heavy Metal" +#~ msgstr "Heavy Metal" + +#~ msgid "Black Metal" +#~ msgstr "Black Metal" + +#~ msgid "Crossover" +#~ msgstr "Crossover" + +#~ msgid "Contemporary Christian" +#~ msgstr "Modern kristen" + +#~ msgid "Christian Rock" +#~ msgstr "Kristen rock" + +#~ msgid "Merengue" +#~ msgstr "Merengue" + +#~ msgid "Salsa" +#~ msgstr "Salsa" + +#~ msgid "Thrash Metal" +#~ msgstr "Thrash Metal" + +#~ msgid "Anime" +#~ msgstr "Anime" + +#~ msgid "JPop" +#~ msgstr "JPop" + +#~ msgid "Synthpop" +#~ msgstr "Synthpop" + +#~ msgid "Nu-Metal" +#~ msgstr "Nu-Metal" + +#~ msgid "Art Rock" +#~ msgstr "Art rock" + +#~ msgid "Editing Disc ID: %s" +#~ msgstr "Redigerar skiv-id: %s" + +#~ msgid "Editing Disc ID: " +#~ msgstr "Redigerar skiv-id: " + +#~ msgid "_Artist:" +#~ msgstr "_Artist:" + +#~ msgid "Disc _Title:" +#~ msgstr "Skiv_titel:" + +#~ msgid "Show advanced disc options" +#~ msgstr "Visa avancerade skivalternativ" + +#~ msgid "Hide advanced disc options" +#~ msgstr "Dölj avancerade skivalternativ" + +#~ msgid "_Disc comments:" +#~ msgstr "_Skivkommentarer:" + +#~ msgid "_Genre:" +#~ msgstr "_Genre:" + +#~ msgid "_Year:" +#~ msgstr "_År:" + +#~ msgid "Title" +#~ msgstr "Titel" + +#~ msgid "Length" +#~ msgstr "Speltid" + +#~ msgid "Show advanced track options" +#~ msgstr "Visa avancerade spåralternativ" + +#~ msgid "Hide advanced track options" +#~ msgstr "Dölj avancerade spåralternativ" + +#~ msgid "_Extra track data:" +#~ msgstr "_Extra spårdata:" + +#~ msgid "Time Line" +#~ msgstr "Tidslinje" + +#~ msgid "Line for displaying the time elapsed for the current track" +#~ msgstr "Linje för visning av den tid som gått tid för aktuellt spår" + +#~ msgid "Info Line" +#~ msgstr "Informationsrad" + +#~ msgid "Line for displaying information" +#~ msgstr "Rad för visning av information" + +#~ msgid "Line for displaying the name of the artist" +#~ msgstr "Rad för visning av namnet på artisten" + +#~ msgid "Album Line" +#~ msgstr "Albumrad" + +#~ msgid "Line for displaying the name of the album" +#~ msgstr "Rad för visning av namnet på albumet" + +#~ msgid "Pause" +#~ msgstr "Paus" + +#~ msgid "Playing %s - %s" +#~ msgstr "Spelar %s - %s" + +#~ msgid "Unknown Artist" +#~ msgstr "Okänd artist" + +#~ msgid "Unknown Album" +#~ msgstr "Okänt album" + +#~ msgid "Playing" +#~ msgstr "Spelar" + +#~ msgid "Paused" +#~ msgstr "Gör paus" + +#~ msgid "CD Player" +#~ msgstr "Cd-spelare" + +#~ msgid "Stopped" +#~ msgstr "Stoppad" + +#~ msgid "Disc error" +#~ msgstr "Skivfel" + +#~ msgid "Data CD" +#~ msgstr "Data-cd" + +#~ msgid "No Cdrom" +#~ msgstr "Ingen cd-rom" + +#~ msgid "Drive Error" +#~ msgstr "Enhetsfel" + +#~ msgid "You do not seem to have permission to access %s." +#~ msgstr "Du verkar inte ha rättighet att komma åt %s." + +#~ msgid "Unknown artist" +#~ msgstr "Okänd artist" + +#~ msgid "Unknown disc" +#~ msgstr "Okänd skiva" + +#~ msgid "%d - Unknown" +#~ msgstr "%d - okänd" + +#~ msgid "P_revious track" +#~ msgstr "F_öregående spår" + +#~ msgid "_Stop" +#~ msgstr "_Stopp" + +#~ msgid "_Play / Pause" +#~ msgstr "S_pela/Paus" + +#~ msgid "_Next track" +#~ msgstr "_Nästa spår" + +#~ msgid "_Eject disc" +#~ msgstr "_Mata ut skiva" + +#~ msgid "_Help" +#~ msgstr "_Hjälp" + +#~ msgid "_About CD player" +#~ msgstr "_Om cd-spelare" + +#~ msgid "Set device" +#~ msgstr "Ställ in enhet" + +#~ msgid "No CD device" +#~ msgstr "Ingen cd-enhet" + +#~ msgid "_Details" +#~ msgstr "_Detaljer" + +#~ msgid "_Set device" +#~ msgstr "_Ställ in enhet" + +#~ msgid "Invalid CD device" +#~ msgstr "Ogiltig cd-enhet" + +#~ msgid "Position" +#~ msgstr "Position" + +#~ msgid "Open track editor" +#~ msgstr "Öppna spårredigerare" + +#~ msgid "Track editor" +#~ msgstr "Spårredigerare" + +#~ msgid "Open preferences" +#~ msgstr "Öppna inställningar" + +#~ msgid "Preferences" +#~ msgstr "Inställningar" + +#~ msgid "Track List" +#~ msgstr "Spårlista" + +#~ msgid "Previous track" +#~ msgstr "Föregående spår" + +#~ msgid "Previous" +#~ msgstr "Föregående" + +#~ msgid "Rewind" +#~ msgstr "Spola tillbaka" + +#~ msgid "Play / Pause" +#~ msgstr "Spela/Paus" + +#~ msgid "Stop" +#~ msgstr "Stopp" + +#~ msgid "Fast forward" +#~ msgstr "Snabbspola" + +#~ msgid "Next track" +#~ msgstr "Nästa spår" + +#~ msgid "Eject CD" +#~ msgstr "Mata ut cd" + +#~ msgid "Eject" +#~ msgstr "Mata ut" + +#~ msgid "CD device to use" +#~ msgstr "Cd-enhet att använda" + +#~ msgid "Only start if there isn't already a CD player application running" +#~ msgstr "Starta endast om det inte finns ett annat cd-spelarprogram som kör" + +#~ msgid "Play the CD on startup" +#~ msgstr "Spela cd-skivan vid uppstart" + +#~ msgid "Cannot create player" +#~ msgstr "Kan inte skapa spelare" + +#~ msgid "Play audio CDs" +#~ msgstr "Spela ljud-cd" + +#~ msgid "CD player theme" +#~ msgstr "Cd-spelartema" + +#~ msgid "Device path" +#~ msgstr "Enhetssökväg" + +#~ msgid "Record sound clips" +#~ msgstr "Spela in ljudklipp" + +#~ msgid "Sound Recorder" +#~ msgstr "Ljudinspelare" + +#~ msgid "About" +#~ msgstr "Om" + +#~ msgid "Close" +#~ msgstr "Stäng" + +#~ msgid "Close this window" +#~ msgstr "Stäng detta fönster" + +#~ msgid "Contents" +#~ msgstr "Innehåll" + +#~ msgid "Create a new sample" +#~ msgstr "Skapa ett nytt ljudklipp" + +#~ msgid "File Information" +#~ msgstr "Filinformation" + +#~ msgid "File _Information" +#~ msgstr "Fil_information" + +#~ msgid "Main toolbar" +#~ msgstr "Huvudverktygsrad" + +#~ msgid "New" +#~ msgstr "Nytt" + +#~ msgid "Open" +#~ msgstr "Öppna" + +#~ msgid "Open a file" +#~ msgstr "Öppna en fil" + +#~ msgid "Play sound" +#~ msgstr "Spela ljud" + +#~ msgid "Quit" +#~ msgstr "Avsluta" + +#~ msgid "Quit the application" +#~ msgstr "Avsluta programmet" + +#~ msgid "Recent _Files" +#~ msgstr "Senaste _filer" + +#~ msgid "Record sound" +#~ msgstr "Spela in ljud" + +#~ msgid "Run Mixer" +#~ msgstr "Kör mixer" + +#~ msgid "Run _Mixer" +#~ msgstr "Kör _mixer" + +#~ msgid "Run the audio mixer" +#~ msgstr "Kör ljudmixern" + +#~ msgid "Save" +#~ msgstr "Spara" + +#~ msgid "Save As" +#~ msgstr "Spara som" + +#~ msgid "Save _As..." +#~ msgstr "Spara so_m..." + +#~ msgid "Save the current file" +#~ msgstr "Spara den aktuella filen" + +#~ msgid "Save the current file with a different name" +#~ msgstr "Spara den aktuella filen med ett annat namn" + +#~ msgid "Show information about the current file" +#~ msgstr "Visa information om den aktuella filen" + +#~ msgid "Show information for Sound Recorder" +#~ msgstr "Visa information för ljudinspelaren" + +#~ msgid "Stop sound" +#~ msgstr "Stoppa ljud" + +#~ msgid "_About" +#~ msgstr "_Om" + +#~ msgid "_Close Window" +#~ msgstr "S_täng fönster" + +#~ msgid "_Contents" +#~ msgstr "_Innehåll" + +#~ msgid "_Control" +#~ msgstr "_Kontroll" + +#~ msgid "_File" +#~ msgstr "_Fil" + +#~ msgid "_New" +#~ msgstr "_Nytt" + +#~ msgid "_Open..." +#~ msgstr "_Öppna..." + +#~ msgid "_Play" +#~ msgstr "_Spela" + +#~ msgid "_Quit" +#~ msgstr "_Avsluta" + +#~ msgid "_Record" +#~ msgstr "Spela _in" + +#~ msgid "_Save" +#~ msgstr "_Spara" + +#~ msgid "hours" +#~ msgstr "timmar" + +#~ msgid "hour" +#~ msgstr "timme" + +#~ msgid "minutes" +#~ msgstr "minuter" + +#~ msgid "minute" +#~ msgstr "minut" + +#~ msgid "seconds" +#~ msgstr "sekunder" + +#~ msgid "second" +#~ msgstr "sekund" + +#~ msgid "Ready" +#~ msgstr "Klar" + +#~ msgid "Save file as" +#~ msgstr "Spara fil som" + +#~ msgid "%s is not installed in the path." +#~ msgstr "%s är inte installerad i sökvägen." + +#~ msgid "There was an error starting %s: %s" +#~ msgstr "Det uppstod ett fel vid start av %s: %s" + +#~ msgid "%s (Has not been saved)" +#~ msgstr "%s (Har inte sparats)" + +#~ msgid "Unknown size" +#~ msgstr "Okänd storlek" + +#~ msgid "%.1f kHz" +#~ msgstr "%.1f kHz" + +#~ msgid "%.0f kb/s" +#~ msgstr "%.0f kb/s" + +#~ msgid "1 (mono)" +#~ msgstr "1 (mono)" + +#~ msgid "2 (stereo)" +#~ msgstr "2 (stereo)" + +#~ msgid "%s Information" +#~ msgstr "Information om %s" + +#~ msgid "Folder:" +#~ msgstr "Mapp:" + +#~ msgid "Filename:" +#~ msgstr "Filnamn:" + +#~ msgid "File size:" +#~ msgstr "Filstorlek:" + +#~ msgid "Audio Information" +#~ msgstr "Ljudinformation" + +#~ msgid "Song length:" +#~ msgstr "Låtlängd:" + +#~ msgid "Number of channels:" +#~ msgstr "Antal kanaler:" + +#~ msgid "Sample rate:" +#~ msgstr "Samplingsfrekvens:" + +#~ msgid "Bit rate:" +#~ msgstr "Bitfrekvens:" + +#~ msgid "Playing..." +#~ msgstr "Spelar upp..." + +#~ msgid "%s.%s - Sound Recorder" +#~ msgstr "%s.%s - Ljudinspelare" + +#~ msgid "Recording..." +#~ msgstr "Spelar in..." + +#~ msgid "Record as" +#~ msgstr "Spela in som" + +#~ msgid "File information" +#~ msgstr "Filinformation" + +#~ msgid "" +#~ msgstr "" + +#~ msgid "Length:" +#~ msgstr "Längd:" + +#~ msgid "Adjust the volume level" +#~ msgstr "Justera nivån på volymen" + +#~ msgid "Volume Control" +#~ msgstr "Volymkontroll" + +#~ msgid "Channel %d of %s Slider" +#~ msgstr "Kanal %d för %s-skjutreglage" + +#~ msgid "%s Slider %d" +#~ msgstr "%s-skjutreglage %d" + +#~ msgid "Lock" +#~ msgstr "Lås" + +#~ msgid "%s Lock" +#~ msgstr "%s-lås" diff --git a/gst-plugins-base-subtitles0.10/po/tr.po b/gst-plugins-base-subtitles0.10/po/tr.po new file mode 100644 index 0000000..82d9d51 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/tr.po @@ -0,0 +1,627 @@ +# translation of gst-plugins-base-0.10.32.2.po to Turkish +# This file is put in the public domain. +# Server Acim , 2010. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-27 11:56+0100\n" +"PO-Revision-Date: 2011-04-26 19:22+0200\n" +"Last-Translator: Server Acim \n" +"Language-Team: Turkish \n" +"Language: tr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "Ana" + +msgid "Bass" +msgstr "Bas" + +msgid "Treble" +msgstr "Tiz" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Synthizer" + +msgid "Line-in" +msgstr "Hat-girişi" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Mikrofon" + +msgid "PC Speaker" +msgstr "PC Hoparlörü" + +msgid "Playback" +msgstr "Çalma" + +msgid "Capture" +msgstr "Yakala" + +msgid "Could not open device for playback in mono mode." +msgstr "Mono kipte çalmak için aygıt açılamıyor." + +msgid "Could not open device for playback in stereo mode." +msgstr "Stereo kipte çalmak için aygıt açılamıyor." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Aygıtı %d- kanal kipinde çalmak için açamıyor." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Aygıtı çalmak için için açamıyor. Aygıt başka bir uygulama tarafından " +"kullanılmakta." + +msgid "Could not open audio device for playback." +msgstr "Aygıtı çalma için açamıyor." + +msgid "Could not open device for recording in mono mode." +msgstr "Mono kipte kaydetmek için aygıtı açamıyor." + +msgid "Could not open device for recording in stereo mode." +msgstr "Stereo kipte kaydetmek için aygıtı açamıyor." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Aygıtı %d- kanal kipinde kaydetmek için açamıyor" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Aygıtı kaydetmek için açamıyor. Aygıt başka bir uygulama tarafından " +"kullanılmakta." + +msgid "Could not open audio device for recording." +msgstr "Kayıt için ses aygıtı açılamıyor." + +msgid "Could not open CD device for reading." +msgstr "Okumak için CD aygıtı açılamıyor." + +msgid "Could not seek CD." +msgstr "CD bulunamıyor." + +msgid "Could not read CD." +msgstr "CD okunamıyor." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Vfs dosyası \"%s\" yazmak için açılamıyor: %s." + +msgid "No filename given" +msgstr "Dosya adı verilmedi" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Vfs dosyası kapatılamıyor \"%s\"." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Dosyaya yazmada hata \"%s\"." + +msgid "Internal data stream error." +msgstr "İç veri akışı hatası." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Bir %s eklenti bu akışı çalmak için gerekli, fakat kurulu değil." + +msgid "This appears to be a text file" +msgstr "Bu bir metin dosyasına benziyor" + +msgid "Could not determine type of stream" +msgstr "Akışın türü belirlenemiyor" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Geçersiz altyazı adresi \"%s\", altyazılar kaldırıldı." + +msgid "No URI specified to play from." +msgstr "Çalmak için bir ağ adresi belirtilmedi." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Geçersiz URI \"%s\"." + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP akışları henüz çalınamıyor." + +msgid "Could not create \"decodebin\" element." +msgstr "\"decodebin\" öğesi oluşturulamıyor." + +msgid "Source element is invalid." +msgstr "Kaynak öğesi geçersiz." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Bir altyazı dosyası algılandı. Siz ya bir altyazı veya başka bir metin " +"dosyası yüklemek üzeresiniz, veya çokluortam dosyası tanınamadı." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Bu yüklü dosyası çözümleyecek bir kod çözücüye sahip değilsiniz. Gerekli " +"eklentileri kurmak zorundasınız." + +msgid "This is not a media file" +msgstr "Bu bir çokluortam dosyası değil." + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Bir altyazı akışı algılanda, ancak vidyo akışı bulunamadı." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Autovideosink ve xvimagesink öğelerininin ikisi de kayıp." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Kayıp öğe '%s' - GStreamer kurulumunu denetleyin." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Autoaudiosink ve alsasink öğelerinin ikisi de kayıp." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Autovideosink ve xvimagesink %s öğelerininin ikisi de kayıp." + +msgid "The autovideosink element is missing." +msgstr "Autovideosink öğelesi kayıp." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Yapılandırılmış olan videosink öğesi %s çalışmıyor." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Autoaudiosink ve xvimagesink %s öğelerinin ikisi de çalışmıyor." + +msgid "The autovideosink element is not working." +msgstr "Autoaudiosink öğesi çalışmıyor." + +msgid "Custom text sink element is not usable." +msgstr "Varsayılan metin gömme öğesi kullanılamaz durumda." + +msgid "No volume control found" +msgstr "Ses denetimi bulunamadı" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Autoaudiosink ve alsasink %s öğelerinin ikisi de kayıp." + +msgid "The autoaudiosink element is missing." +msgstr "Autoaudiosink öğesi kayıp." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Yapılandırılmış olan videosink öğesi %s çalışmıyor." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Autoaudiosink ve %s öğelerinin ikisi de çalışmıyor." + +msgid "The autoaudiosink element is not working." +msgstr "Autoaudiosink öğesi çalışmıyor." + +msgid "Can't play a text file without video or visualizations." +msgstr "Vidyo veya görsellik olmadan metin dosyasını oynatamaz." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Şu tür '%s' için kod çözücü bulunamadı." + +msgid "This stream type cannot be played yet." +msgstr "Bu akış türü henüz çalınamıyor." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Hiç bir URI bağlantısı sağlanmadı \"%s\"." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Dosyayı şuraya gönderirken hata \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Bir gdp başlık verisini şuraya gönderirken hata \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Bir gdp verisini şuraya gönderirken hata \"%s:%d\"." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Şuraya bağlantı %s:%d reddedildi." + +msgid "Can't record audio fast enough" +msgstr "Sesi yeterince hızlı kaydedemiyor" + +msgid "Failed to read tag: not enough data" +msgstr "Etiketi okunamadı: yetersiz veri" + +msgid "track ID" +msgstr "iz BAŞLIĞI" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz iz BAŞLIĞI ID" + +msgid "artist ID" +msgstr "sanatçı BAŞLIĞI" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz sanatçı BAŞLIĞI ID" + +msgid "album ID" +msgstr "albüm BAŞLIĞI" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz albümü BAŞLIĞI" + +msgid "album artist ID" +msgstr "albüm sanatçısı BAŞLIĞI" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz albüm sanatçısı BAŞLIĞI" + +msgid "track TRM ID" +msgstr "iz TRM BAŞLIĞI" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM BAŞLIĞI" + +msgid "capturing shutter speed" +msgstr "objektif hızını yakalıyor" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Saniye bazında, bir resim çekerken kullanılan objektif hızı" + +msgid "capturing focal ratio" +msgstr "odaksal oranı yakalıyor" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "Resim çekerken kullanılan odaksal oran (f-numarası)" + +msgid "capturing focal length" +msgstr "odaksal uzunluğu yakalıyor" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "Mm bazında, resim çekerken kullanılan odaksal uzunluk" + +msgid "capturing digital zoom ratio" +msgstr "sayısal zum oranını yakalıyor" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "Bir resim çekerken kullanılan sayısal yakınlaştırma oranı" + +msgid "capturing iso speed" +msgstr "iso hızını yakalıyor" + +msgid "The ISO speed used when capturing an image" +msgstr "Bir resim çekerken kulllanılan ISO hızı" + +msgid "capturing exposure program" +msgstr "pozlandırma programını yakalıyor" + +msgid "The exposure program used when capturing an image" +msgstr "Bir resim çekerken kullanılan pozlandırma programı" + +msgid "capturing exposure mode" +msgstr "pozlandırma kipini yakalıyor" + +msgid "The exposure mode used when capturing an image" +msgstr "Bir resim çekerken kullanılan pozlandırma kipi" + +msgid "capturing exposure compensation" +msgstr "pozlandırma kipini yakalanıyor" + +msgid "The exposure compensation used when capturing an image" +msgstr "Bir resim çekerken kullanılan pozlandırma kipi" + +msgid "capturing scene capture type" +msgstr "manzara çekme türünü yakalıyor" + +msgid "The scene capture mode used when capturing an image" +msgstr "Bir resim çekerken kullanılan manzara yakalama kipi" + +msgid "capturing gain adjustment" +msgstr "kazanç ayarı yakalanıyor" + +msgid "The overall gain adjustment applied on an image" +msgstr "Bir resime uygulanan kapsamlı kazanç ayarı" + +msgid "capturing white balance" +msgstr "beyaz dengesi yakalanıyor" + +msgid "The white balance mode set when capturing an image" +msgstr "Bir resim çekerken kullanılan beyaz dengesi kipi" + +msgid "capturing contrast" +msgstr "zıtlık yakalanıyor" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Bir resim çekerken uygulanan zıtlık işleminin yönü" + +msgid "capturing saturation" +msgstr "canlılık yakalanıyor" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Bir resim çekerken uygulanan doygunluk işleminin yönü" + +msgid "capturing sharpness" +msgstr "keskinlik yakalanıyor" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Bir resim çekerken uygulanan keskinlik işleminin yönü" + +msgid "capturing flash fired" +msgstr "flaşın yanışı yakalanıyor" + +msgid "If the flash fired while capturing an image" +msgstr "Bir resim çekerken eğer flaş patlamışsa" + +msgid "capturing flash mode" +msgstr "flaş kipi yakalanıyor" + +msgid "The selected flash mode while capturing an image" +msgstr "Bir resim çekerken kullanılan flaş kipi" + +msgid "capturing metering mode" +msgstr "metreleme kipi yakalanıyor" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "Bir resim çekmek için pozlandırmanın metreleme kipi" + +msgid "capturing source" +msgstr "kaynak yakalanıyor" + +msgid "The source or type of device used for the capture" +msgstr "Resim çekerken kullanılan aygıtın kaynak türü" + +msgid "image horizontal ppi" +msgstr "yatay resim ppi değeri" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "Medya (resim/vidyo)'nın ppi değerinden yatay piksel yoğunluğu" + +msgid "image vertical ppi" +msgstr "resim dikey ppi değeri" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "Medya (resim/vidyo)'nun ppi değerinden dikey piksel yoğunluğu" + +msgid "This CD has no audio tracks" +msgstr "Bu CD hiç ses izi içermiyor" + +msgid "ID3 tag" +msgstr "ID3 etiketi" + +msgid "APE tag" +msgstr "APE etiketi" + +msgid "ICY internet radio" +msgstr "ICY internet radyosu" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple Lossless Audio (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Free Lossless Audio Codec (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Hecelemesi" + +msgid "CYUV Lossless" +msgstr "CYUV Kayıpsız" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "Kayıpsız MSZH" + +msgid "Uncompressed Gray Image" +msgstr "Sıkıştırılmamış Gri Resim" + +msgid "Run-length encoding" +msgstr "Çalıştırma-uzunluğu kodlaması" + +msgid "Sami subtitle format" +msgstr "Sami altyazı kipi" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer altyazı kipi" + +msgid "Kate subtitle format" +msgstr "Kate altyazı kipi" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Sıkıştırılmamış planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Sıkıştırılmamış planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Sıkıştırılmamış paket YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Sıkıştırılmamış paket YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Sıkıştırılmamış paket YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Sıkıştırılmamış paket YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Sıkıştırılmamış paket YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Sıkıştırılmamış planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Sıkıştırılmamış planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Sıkıştırılmamış siyah ve beyaz Y" + +msgid "Uncompressed YUV" +msgstr "Sıkıştırılmamış YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Şıkıştırılmamış seviyesi şuna düşürülmüş %d-bit %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Versiyonu %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Ham %d-bit PCM ses" + +msgid "Raw PCM audio" +msgstr "Ham PCM ses" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Ham %d-bit yüzer-noktalı ses" + +msgid "Raw floating-point audio" +msgstr "Ham yüzer-noktalı ses" + +msgid "Audio CD source" +msgstr "Ses CD'si kaynağı" + +msgid "DVD source" +msgstr "DVD kaynağı" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Gerçek Zamanlı Akış Protokolu (RTSP) kaynağı" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft Medya Sunucusu (MMS) protokol kaynağı" + +#, c-format +msgid "%s protocol source" +msgstr "%s protokol kaynağı" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "%s video RTP depayloader" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "%s audio RTP depayloader" + +#, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP depayloader" + +#, c-format +msgid "%s demuxer" +msgstr "%s demuxer" + +#, c-format +msgid "%s decoder" +msgstr "%s kod çözücü" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s video RTP payloader" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s audio RTP payloader" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP payloader" + +#, c-format +msgid "%s muxer" +msgstr "%s muxer" + +#, c-format +msgid "%s encoder" +msgstr "%s kodlayıcı" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer öğesi %s" + +msgid "Unknown source element" +msgstr "Bilinmeyen kaynak öğesi" + +msgid "Unknown sink element" +msgstr "Bilinmeyen gömme öğesi" + +msgid "Unknown element" +msgstr "Bilinmeyen öğe" + +msgid "Unknown decoder element" +msgstr "Bilinmeyen kod çözücü öğesi" + +msgid "Unknown encoder element" +msgstr "Bilinmeyen kodlama öğesi" + +msgid "Plugin or element of unknown type" +msgstr "Bilinmeyen türde eklenti veya öğe" + +msgid "No device specified." +msgstr "Aygıt belirtilmedi." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Aygıt \"%s\" bulunamadı." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Aygıt \"%s\" zaten kullanımda." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Şu aygıtı\"%s\" for okuma veya yazma için açamıyor." + +#~ msgid "Can't display both text subtitles and subpictures." +#~ msgstr "Metin altyazılarını altgörüntülerini oynatamıyor." + +#~ msgid "No Temp directory specified." +#~ msgstr "Geçici Temp dizini belirtilmedi." + +#~ msgid "Could not create temp file \"%s\"." +#~ msgstr "Geçici dosya oluşturulamıyor \"%s\"." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Dosyayı \"%s\" okumak için açamıyor." + +#~ msgid "Internal data flow error." +#~ msgstr "İç veri akışı hatası." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Bir \"decodebin2\" öğesi oluşturamıyor." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Bir \"queue2\" öğesi oluşturamıyor." + +#~ msgid "Could not create \"typefind\" element." +#~ msgstr "Bir \"typefind\" öğesi oluşturamıyor." + +#~ msgid "No file name specified." +#~ msgstr "Dosya adı belirtilmedi." diff --git a/gst-plugins-base-subtitles0.10/po/uk.po b/gst-plugins-base-subtitles0.10/po/uk.po new file mode 100644 index 0000000..11a39c5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/uk.po @@ -0,0 +1,637 @@ +# Ukrainian translation to gst-plugins. +# Copyright (C) 2004 Free Software Foundation, Inc. +# This file is distributed under the same license as the gst-plugins-base package. +# +# Maxim V. Dziumanenko , 2004-2007. +# Yuri Chornoivan , 2010, 2011. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.32.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-30 17:11+0100\n" +"PO-Revision-Date: 2011-04-27 17:49+0300\n" +"Last-Translator: Yuri Chornoivan \n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Lokalize 1.1\n" + +msgid "Master" +msgstr "Головний" + +msgid "Bass" +msgstr "Низькі" + +msgid "Treble" +msgstr "Високі" + +msgid "PCM" +msgstr "КІМ" + +msgid "Synth" +msgstr "Синтезатор" + +msgid "Line-in" +msgstr "Лінійний вхід" + +msgid "CD" +msgstr "Компакт-диск" + +msgid "Microphone" +msgstr "Мікрофон" + +msgid "PC Speaker" +msgstr "Гучномовець" + +msgid "Playback" +msgstr "Відтворення" + +msgid "Capture" +msgstr "Запис" + +msgid "Could not open device for playback in mono mode." +msgstr "Не вдалося відкрити пристрій відтворення у режимі моно." + +msgid "Could not open device for playback in stereo mode." +msgstr "Не вдалося відкрити пристрій відтворення у режимі стерео." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Не вдалося відкрити пристрій відтворення у %d канальному режимі." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Не вдалося відкрити пристрій для відтворення. Пристрій використовується " +"сторонньою програмою." + +msgid "Could not open audio device for playback." +msgstr "Не вдалося відкрити пристрій для відтворення." + +msgid "Could not open device for recording in mono mode." +msgstr "Не вдалося відкрити пристрій запису у режимі моно." + +msgid "Could not open device for recording in stereo mode." +msgstr "Не вдалося відкрити пристрій запису у режимі стерео." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Не вдалося відкрити пристрій запису у %d-канальному режимі." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Не вдалося відкрити пристрій для запису. Пристрій використовується " +"сторонньою програмою." + +msgid "Could not open audio device for recording." +msgstr "Не вдалося відкрити пристрій для запису." + +msgid "Could not open CD device for reading." +msgstr "Не вдалося відкрити пристрій компакт-дисків для читання." + +msgid "Could not seek CD." +msgstr "Не вдалося встановити позицію на CD." + +msgid "Could not read CD." +msgstr "Не вдалося прочитати CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "" +"Не вдалося відкрити файл віртуальної файлової системи «%s» для запису: %s." + +msgid "No filename given" +msgstr "Не вказано файл" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Не вдалося закрити файл віртуальної файлової системи «%s»." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Помилка при записі у файл «%s»." + +msgid "Internal data stream error." +msgstr "Помилка внутрішнього потоку даних." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Для відтворення потоку потрібен модуль %s, але він не встановлений." + +msgid "This appears to be a text file" +msgstr "Файл схожий на текстовий файл" + +msgid "Could not determine type of stream" +msgstr "Не вдалося визначити тип даних потоку" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "Неправильний URI субтитру «%s», субтитри вимкнено." + +msgid "No URI specified to play from." +msgstr "Не вказано URI для відтворення." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "Неправильний URI «%s»." + +msgid "RTSP streams cannot be played yet." +msgstr "Відтворення потоків RTSP поки-що не підтримується." + +msgid "Could not create \"decodebin\" element." +msgstr "Не вдалося створити елемент \"decodebin\"." + +msgid "Source element is invalid." +msgstr "Неправильний вхідний елемент." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Виявлено лише потік субтитрів. Або ви завантажили файл субтитрів чи інший " +"текстовий файл, або носій не розпізнано." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Не встановлено декодер для обробки цього файлу. Можливо потрібно встановити " +"додаткові модулі." + +msgid "This is not a media file" +msgstr "Файл не є мультимедійним" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Виявлено потік субтитрів, але не відеопотік." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Відсутні елементи autovideosink та xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "" +"Відсутній елемент «%s». Перевірте чи встановлено GStreamer належним чином." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Відсутні елементи autoaudiosink та alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Не вказано елементів autovideosink і %s." + +msgid "The autovideosink element is missing." +msgstr "Не вказано елемента autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Налаштований приймач відеоданих, %s, не працює." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Непридатними є обидва елементи: autovideosink і %s." + +msgid "The autovideosink element is not working." +msgstr "Елемент autovideosink є непридатним." + +msgid "Custom text sink element is not usable." +msgstr "" +"Нетиповий елемент приймача текстових даних непридатний до використання." + +msgid "No volume control found" +msgstr "Не знайдено регулятора гучності" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Не вказано обох елементів: autoaudiosink і %s." + +msgid "The autoaudiosink element is missing." +msgstr "Не вказано елемента autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Налаштований приймач звукових даних, %s, не працює." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Елементи autoaudiosink і %s є непридатними." + +msgid "The autoaudiosink element is not working." +msgstr "Елемент autoaudiosink є непридатним." + +msgid "Can't play a text file without video or visualizations." +msgstr "Відтворення текстового файла без відео або візуалізації неможливе." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Для типу '%s' немає доступних декодерів." + +msgid "This stream type cannot be played yet." +msgstr "Цей потік поки-що не може бути відтворений." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Не реалізовано обробник URI для «%s»." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Помилка при надсиланні даних до \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Помилка при надсиланні заголовку gdp даних до \"%s:%d\"." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Помилка при надсиланні даних gdp до «%s:%d»." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "У з'єднанні з %s:%d відмовлено." + +msgid "Can't record audio fast enough" +msgstr "Не вдалося запис аудіоданих з потрібною швидкістю" + +msgid "Failed to read tag: not enough data" +msgstr "Не вдалося прочитати мітку: недостатньо даних" + +msgid "track ID" +msgstr "ідентифікатор доріжки" + +msgid "MusicBrainz track ID" +msgstr "Ідентифікатор доріжки у MusicBrainz" + +msgid "artist ID" +msgstr "ідентифікатор виконавця" + +msgid "MusicBrainz artist ID" +msgstr "Ідентифікатор виконавця у MusicBrainz" + +msgid "album ID" +msgstr "ідентифікатор альбому" + +msgid "MusicBrainz album ID" +msgstr "Ідентифікатор альбому у MusicBrainz" + +msgid "album artist ID" +msgstr "ідентифікатор виконавця альбому" + +msgid "MusicBrainz album artist ID" +msgstr "Ідентифікатор виконавця альбому у MusicBrainz" + +msgid "track TRM ID" +msgstr "ідентифікатор доріжки TRM" + +msgid "MusicBrainz TRM ID" +msgstr "Ідентифікатор доріжки TRM у MusicBrainz" + +msgid "capturing shutter speed" +msgstr "швидкість затвору" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "Швидкість затвору (діафрагми) під час створення зображення, у секундах" + +msgid "capturing focal ratio" +msgstr "фокальний коефіцієнт" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" +"Фокальний коефіцієнт (число діафрагми), використаний під час створення " +"зображення" + +msgid "capturing focal length" +msgstr "фокальна відстань" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" +"Фокальна відстань об’єктива, використаного при створенні зображення, у мм" + +msgid "capturing digital zoom ratio" +msgstr "коефіцієнт цифрового збільшення" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" +"Коефіцієнт цифрового збільшення, використаний під час створення зображення" + +msgid "capturing iso speed" +msgstr "світлочутливість ISO" + +msgid "The ISO speed used when capturing an image" +msgstr "Світлочутливість ISO, використана під час створення зображення" + +msgid "capturing exposure program" +msgstr "програма експозиції" + +msgid "The exposure program used when capturing an image" +msgstr "Програма експозиції, використана під час створення зображення" + +msgid "capturing exposure mode" +msgstr "режим експозиції" + +msgid "The exposure mode used when capturing an image" +msgstr "Режим експозиції, використаний під час створення зображення" + +msgid "capturing exposure compensation" +msgstr "компенсація експозиції під час захоплення" + +msgid "The exposure compensation used when capturing an image" +msgstr "Компенсація часу експозиції, потрібного для захоплення зображення" + +msgid "capturing scene capture type" +msgstr "тип сцени" + +msgid "The scene capture mode used when capturing an image" +msgstr "Режим типу сцени, використаний під час створення зображення" + +msgid "capturing gain adjustment" +msgstr "коригування підсилання" + +msgid "The overall gain adjustment applied on an image" +msgstr "Загальне коригування підсилення, застосоване до зображення" + +msgid "capturing white balance" +msgstr "баланс білого" + +msgid "The white balance mode set when capturing an image" +msgstr "" +"Режим балансування білого кольору, використаний під час створення зображення" + +msgid "capturing contrast" +msgstr "контрастність" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "Напрям обробки контрастності, застосований при створенні зображення" + +msgid "capturing saturation" +msgstr "насиченість" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "Напрям обробки насиченості, застосований при створенні зображення" + +msgid "capturing sharpness" +msgstr "різкість" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "Напрям обробки різкості, застосований при створенні зображення" + +msgid "capturing flash fired" +msgstr "спалах" + +msgid "If the flash fired while capturing an image" +msgstr "Чи було використано спалах при створенні зображення" + +msgid "capturing flash mode" +msgstr "режим спалаху" + +msgid "The selected flash mode while capturing an image" +msgstr "Вибраний режим спалаху під час створення зображення" + +msgid "capturing metering mode" +msgstr "режим вимірювання" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" +"Режим вимірювання, застосований для визначення експозиції створеного " +"зображення" + +msgid "capturing source" +msgstr "джерело" + +msgid "The source or type of device used for the capture" +msgstr "Тип пристрою-джерела зображення" + +msgid "image horizontal ppi" +msgstr "горизонтальна щільність пікселів" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" +"Горизонтальна щільність пікселів на матриці (зображення або відео), у точках " +"на дюйм" + +msgid "image vertical ppi" +msgstr "вертикальна щільність пікселів" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" +"Вертикальна щільність пікселів на матриці (зображення або відео), у точках " +"на дюйм" + +msgid "This CD has no audio tracks" +msgstr "На цьому компакт-диску немає звукових доріжок" + +msgid "ID3 tag" +msgstr "Мітка ID3" + +msgid "APE tag" +msgstr "Мітка APE" + +msgid "ICY internet radio" +msgstr "Інтернет-радіо ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Аудіо без втрат від Apple (ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "Вільний алгоритм аудіо без втрат (FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Lossless True Audio (TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media Speech" + +msgid "CYUV Lossless" +msgstr "CYUV без втрат" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH без втрат" + +msgid "Uncompressed Gray Image" +msgstr "Нестиснене сіре зображення" + +msgid "Run-length encoding" +msgstr "Кодування Run-length" + +msgid "Sami subtitle format" +msgstr "Формат субтитрів Sami" + +msgid "TMPlayer subtitle format" +msgstr "Формат субтитрів TMPlayer" + +msgid "Kate subtitle format" +msgstr "Формат субтитрів Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "Нестиснений планарний YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "Нестиснений планарний YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "Нестиснений пакетний YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "Нестиснений пакетний YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "Нестиснений пакетний YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "Нестиснений пакетний YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "Нестиснений пакетний YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "Нестиснений планарний YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "Нестиснений планарний YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "Нестиснений чорно-білий Y-проекція" + +msgid "Uncompressed YUV" +msgstr "Нестиснений YUV" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "Нестиснений пакетний %d-бітовий %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 версії %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Необроблений %d-бітовий PCM-звук" + +msgid "Raw PCM audio" +msgstr "Необроблений PCM-звук" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Необроблений %d-бітовий звук (дані з плаваючою комою)" + +msgid "Raw floating-point audio" +msgstr "Необроблений звук (дані з плаваючою комою)" + +msgid "Audio CD source" +msgstr "Джерело аудіо-CD" + +msgid "DVD source" +msgstr "Джерело DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "Джерело потокового протоколу реального часу (RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Джерело протоколу Microsoft Media Server (MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Джерело протоколу %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "RTP модуль розпаковування відеоданих %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "RTP модуль розпаковування аудіоданих %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "RTP модуль розпаковування даних %s" + +#, c-format +msgid "%s demuxer" +msgstr "демультиплексор %s" + +#, c-format +msgid "%s decoder" +msgstr "декодер %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "RTP модуль запаковування відеоданих %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "RTP модуль запаковування аудіоданих %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "RTP модуль запаковування даних %s" + +#, c-format +msgid "%s muxer" +msgstr "мультиплексор %s" + +#, c-format +msgid "%s encoder" +msgstr "кодер %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Елемент GStreamer %s" + +msgid "Unknown source element" +msgstr "Невідомий елемент джерела" + +msgid "Unknown sink element" +msgstr "Невідомий елемент приймача" + +msgid "Unknown element" +msgstr "Невідомий елемент" + +msgid "Unknown decoder element" +msgstr "Невідомий елемент декодера" + +msgid "Unknown encoder element" +msgstr "Невідомий елемент кодера" + +msgid "Plugin or element of unknown type" +msgstr "Модуль або елемент невідомого типу" + +msgid "No device specified." +msgstr "Пристрій не вказано." + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Пристрою «%s» не існує." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Пристрій «%s» вже використовується іншою програмою." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Не вдалося відкрити пристрій «%s» для читання чи запису." + +#~ msgid "No file name specified." +#~ msgstr "Не вказано назву файлу." + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "Не вдається відкрити файл \"%s\" для читання." + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "Не вдається створити елемент \"decodebin2\"." + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "Не вдається створити елемент \"queue2\"." + +#~ msgid "artist sortname" +#~ msgstr "категорія виконавця" + +#~ msgid "MusicBrainz artist sortname" +#~ msgstr "Категорія виконавця у MusicBrainz" diff --git a/gst-plugins-base-subtitles0.10/po/vi.po b/gst-plugins-base-subtitles0.10/po/vi.po new file mode 100644 index 0000000..d042bd0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/vi.po @@ -0,0 +1,607 @@ +# Vietnamese Translation for GST Plugins Base. +# This file is distributed under the same license as the gst-plugins-base package. +# Clytie Siddall , 2005-2010. +# +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.28.2\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2010-04-27 22:51+0930\n" +"Last-Translator: Clytie Siddall \n" +"Language-Team: Vietnamese \n" +"Language: vi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: LocFactoryEditor 1.8\n" + +msgid "Master" +msgstr "Chủ" + +msgid "Bass" +msgstr "Trầm" + +msgid "Treble" +msgstr "Cao" + +msgid "PCM" +msgstr "PCM" + +msgid "Synth" +msgstr "Tổng hợp" + +msgid "Line-in" +msgstr "Dây-vào" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "Máy vi âm" + +msgid "PC Speaker" +msgstr "Loa PC" + +msgid "Playback" +msgstr "Phát lại" + +msgid "Capture" +msgstr "Bắt" + +msgid "Could not open device for playback in mono mode." +msgstr "Không thể mở thiết bị để phát lại trong chế độ đơn nguồn." + +msgid "Could not open device for playback in stereo mode." +msgstr "Không thể mở thiết bị để phát lại trong chế độ âm lập thể." + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "Không thể mở thiết bị để phát lại trong chế độ %d kênh." + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "" +"Không thể mở thiết bị âm thanh để phát lại, vì ứng dụng khác đang sử dụng nó." + +msgid "Could not open audio device for playback." +msgstr "Không thể mở thiết bị âm thanh để phát lại." + +msgid "Could not open device for recording in mono mode." +msgstr "Không thể mở thiết bị để thu trong chế độ đơn nguồn." + +msgid "Could not open device for recording in stereo mode." +msgstr "Không thể mở thiết bị để thu trong chế độ âm lập thể." + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "Không thể mở thiết bị để thu trong chế độ %d kênh." + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "" +"Không thể mở thiết bị âm thanh để thu, vì ứng dụng khác đang sử dụng nó." + +msgid "Could not open audio device for recording." +msgstr "Không thể mở thiết bị âm thanh để thu." + +msgid "Could not open CD device for reading." +msgstr "Không thể mở thiết bị đĩa CD để đọc." + +msgid "Could not seek CD." +msgstr "Không thể tìm trên đĩa CD." + +msgid "Could not read CD." +msgstr "Không thể đọc đĩa CD." + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "Không thể mở tập tin VFS « %s » để ghi: %s." + +msgid "No filename given" +msgstr "Chưa nhập tên tập tin" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "Không thể đóng tập tin VFS « %s »." + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "Lỗi khi ghi vào tập tin « %s »." + +msgid "Internal data stream error." +msgstr "Lỗi luồng dữ liệu nội bộ." + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "Cần phần bổ sung %s để phát luồng này nhưng chưa cài đặt." + +msgid "This appears to be a text file" +msgstr "Hình như đây là tập tin văn bản" + +msgid "Could not determine type of stream" +msgstr "Không thể quyết định loại luồng" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "URI phụ đề không hợp lệ « %s » nên tắt khả năng phụ đề." + +msgid "No URI specified to play from." +msgstr "Chưa ghi rõ URI từ đó cần phát." + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "URI không hợp lệ « %s »." + +msgid "RTSP streams cannot be played yet." +msgstr "Chưa có khả năng phát luồng RTSP." + +msgid "Could not create \"decodebin\" element." +msgstr "Không thể tạo phần tử « decodebin »." + +msgid "Source element is invalid." +msgstr "Phần tử nguồn không phải hợp lệ." + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"Chỉ phát hiện luồng phụ đề. Hoặc bạn đang nạp tập tin phụ đề hay tập tin văn " +"bản kiểu khác, hoặc không nhận diện tập tin nhạc/ảnh." + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "" +"Chưa cài đặt bộ giải mã có khả năng quản lý tập tin này. Có thể cần phải cài " +"đặt các phần bổ sung thích hợp." + +msgid "This is not a media file" +msgstr "Đây không phải tập tin nhạc/ảnh" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "Phát hiện luồng phụ đề, không có luồng ảnh động." + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "Thiếu phần tử autovideosink, cũng thiếu phần tử xvimagesink." + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "Thiếu phần tử « %s » — hãy kiểm tra lại cài đặt GStreamer." + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "Thiếu phần tử autoaudiosink, cũng thiếu phần tử alsasink." + +#, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "Thiếu phần tử autovideosink, cũng thiếu phần tử %s." + +msgid "The autovideosink element is missing." +msgstr "Thiếu phần tử autovideosink." + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "Phần tử videosink %s đã cấu hình mà không hoạt động." + +#, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "Cả hai phần tử autovideosink và %s không hoạt động." + +msgid "The autovideosink element is not working." +msgstr "Phần tử autovideosink không hoạt động." + +msgid "Custom text sink element is not usable." +msgstr "Không thể sử dụng yếu tố ổ chìm văn bản riêng." + +msgid "No volume control found" +msgstr "Không tìm thấy điều khiển âm lượng" + +#, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "Thiếu phần tử autoaudiosink, cũng thiếu phần tử %s." + +msgid "The autoaudiosink element is missing." +msgstr "Thiếu phần tử autoaudiosink." + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "Phần tử audiosink %s đã cấu hình mà không hoạt động." + +#, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "Cả hai phần tử autoaudiosink và %s không hoạt động." + +msgid "The autoaudiosink element is not working." +msgstr "Phần tử autoaudiosink không hoạt động." + +msgid "Can't play a text file without video or visualizations." +msgstr "" +"Không thể phát tập tin văn bản mà không có ảnh động hay cách thức hiển thị." + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "Không có bộ giải mã sẵn sàng cho kiểu « %s »." + +msgid "This stream type cannot be played yet." +msgstr "Chưa có khả năng phát kiểu luồng này." + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "Không có bộ quản lý địa chỉ URI được thực hiện cho « %s »." + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "Lỗi khi gởi dữ liệu cho « %s:%d »." + +#, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "Lỗi khi gởi dữ liệu phần đầu GDP cho « %s:%d »." + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "Lỗi khi gởi dữ liệu trọng tải GDP cho « %s:%d »." + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "Kết nối tới « %s:%d » bị từ chối." + +msgid "Can't record audio fast enough" +msgstr "Không thể thu âm thanh một cách đủ nhanh" + +msgid "Failed to read tag: not enough data" +msgstr "Lỗi đọc thẻ: không đủ dữ liệu" + +msgid "track ID" +msgstr "mã rãnh" + +msgid "MusicBrainz track ID" +msgstr "mã rãnh MusicBrainz" + +msgid "artist ID" +msgstr "mã nghệ sĩ" + +msgid "MusicBrainz artist ID" +msgstr "mã nghệ sĩ MusicBrainz" + +msgid "album ID" +msgstr "mã tập nhạc" + +msgid "MusicBrainz album ID" +msgstr "mã tập nhạc MusicBrainz" + +msgid "album artist ID" +msgstr "mã nghệ sĩ tập nhạc" + +msgid "MusicBrainz album artist ID" +msgstr "mã nghệ sĩ tập nhạc MusicBrainz" + +msgid "track TRM ID" +msgstr "mã TRM rãnh" + +msgid "MusicBrainz TRM ID" +msgstr "mã TRM rãnh MusicBrainz" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "Đĩa CD này không có rãnh âm thanh nào" + +msgid "ID3 tag" +msgstr "Thẻ ID3" + +msgid "APE tag" +msgstr "Thẻ APE" + +msgid "ICY internet radio" +msgstr "Thu thanh Internet ICY" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Âm thanh không mất gì của Apple (Apple Lossless Audio: ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "" +"Phương pháp tự do không mất gì nén và truyền nhiều loại dữ liệu âm thanh " +"khác (Free Lossless Audio Codec: FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "Âm thanh đúng không mất gì (Lossless True Audio: TTA)" + +msgid "Windows Media Speech" +msgstr "Tiếng nói của nhạc/ảnh Windows (Windows Media Speech)" + +msgid "CYUV Lossless" +msgstr "CYUV không mất gì (CYUV Lossless)" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "MSZH không mất gì (Lossless MSZH)" + +msgid "Uncompressed Gray Image" +msgstr "Ảnh màu xám không nén" + +msgid "Run-length encoding" +msgstr "Mã hoá độ dài chạy (Run-Length Encoding: RLE)" + +msgid "Sami subtitle format" +msgstr "Định dạng phụ đề Sami" + +msgid "TMPlayer subtitle format" +msgstr "Định dạng phụ đề TMPlayer" + +msgid "Kate subtitle format" +msgstr "Định dạng phụ đề Kate" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "YUV 4:2:0 phẳng không nén" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "YUV 4:2:0 phẳng không nén" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "YUV 4:2:2 đóng gói không nén" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "YUV 4:1:0 đóng gói không nén" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "YVU 4:1:0 đóng gói không nén" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "YUV 4:1:1 đóng gói không nén" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "YUV 4:4:4 đóng gói không nén" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "YUV 4:2:2 phẳng không nén" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "YUV 4:1:1 phẳng không nén" + +msgid "Uncompressed black and white Y-plane" +msgstr "Mặt phẳng Y đen trắng không nén" + +msgid "Uncompressed YUV" +msgstr "YUV không nén" + +#, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "%d-bit %s có bảng chọn không nén" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 Phiên bản %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "Âm thanh PCM %d-bit thô" + +msgid "Raw PCM audio" +msgstr "Âm thanh PCM thô" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "Âm thanh dấu phẩy động %d-bit thô" + +msgid "Raw floating-point audio" +msgstr "Âm thanh dấu phẩy động thô" + +msgid "Audio CD source" +msgstr "Nguồn đĩa CD âm thanh" + +msgid "DVD source" +msgstr "Nguồn đĩa DVD" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "" +"Nguồn Giao thức chạy luồng giờ thật (Real Time Streaming Protocol: RTSP)" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "" +"Nguồn Giao thức trình phục vụ nhạc/ảnh Microsoft (Microsoft Media Server: " +"MMS)" + +#, c-format +msgid "%s protocol source" +msgstr "Nguồn giao thức %s" + +#, c-format +msgid "%s video RTP depayloader" +msgstr "depayloader (bộ trừ trọng tải?) RTP ảnh động %s" + +#, c-format +msgid "%s audio RTP depayloader" +msgstr "depayloader (bộ trừ trọng tải?) RTP âm thanh %s" + +#, c-format +msgid "%s RTP depayloader" +msgstr "depayloader (bộ trừ trọng tải?) RTP %s" + +#, c-format +msgid "%s demuxer" +msgstr "demuxer (bộ chia ra) %s" + +#, c-format +msgid "%s decoder" +msgstr "bộ giải mã %s" + +#, c-format +msgid "%s video RTP payloader" +msgstr "payloader (bộ cộng trọng tải?) RTP ảnh động %s" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "payloader (bộ cộng trọng tải?) RTP âm thanh %s" + +#, c-format +msgid "%s RTP payloader" +msgstr "payloader (bộ cộng trọng tải?) RTP %s" + +#, c-format +msgid "%s muxer" +msgstr "muxer (bộ kết hợp lại) %s" + +#, c-format +msgid "%s encoder" +msgstr "bộ mã hoá %s" + +#, c-format +msgid "GStreamer element %s" +msgstr "Phần tử GStreamer %s" + +msgid "Unknown source element" +msgstr "Không rõ phần tử nguồn" + +msgid "Unknown sink element" +msgstr "Không rõ phần tử ổ chìm" + +msgid "Unknown element" +msgstr "Không rõ phần tử" + +msgid "Unknown decoder element" +msgstr "Không rõ phần tử giải mã" + +msgid "Unknown encoder element" +msgstr "Không rõ phần tử mã hoá" + +msgid "Plugin or element of unknown type" +msgstr "Không rõ kiểu phần bổ sung hay phần tử" + +msgid "No device specified." +msgstr "Chưa ghi rõ thiết bị nào" + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "Không có thiết bị « %s »." + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "Thiết bị « %s » đang được dùng." + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "Không thể mở thiết bị « %s » để đọc và ghi." diff --git a/gst-plugins-base-subtitles0.10/po/zh_CN.po b/gst-plugins-base-subtitles0.10/po/zh_CN.po new file mode 100644 index 0000000..4d16499 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/po/zh_CN.po @@ -0,0 +1,613 @@ +# Chinese (simplified) translation about gst-plugin-base. +# This file is put in the public domain. +# Funda Wang , 2005. +# Ji ZhengYu , 2008. +msgid "" +msgstr "" +"Project-Id-Version: gst-plugins-base 0.10.21.3\n" +"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" +"POT-Creation-Date: 2011-04-16 15:41+0100\n" +"PO-Revision-Date: 2009-01-14 12:41+0800\n" +"Last-Translator: Ji ZhengYu \n" +"Language-Team: Chinese (simplified) \n" +"Language: zh_CN\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" + +msgid "Master" +msgstr "主音量" + +msgid "Bass" +msgstr "低音(Bass)" + +msgid "Treble" +msgstr "高音(Treble)" + +msgid "PCM" +msgstr "波形" + +msgid "Synth" +msgstr "合成器" + +msgid "Line-in" +msgstr "线路输入" + +msgid "CD" +msgstr "CD" + +msgid "Microphone" +msgstr "话筒" + +msgid "PC Speaker" +msgstr "PC 扬声器" + +msgid "Playback" +msgstr "回放" + +msgid "Capture" +msgstr "录音" + +msgid "Could not open device for playback in mono mode." +msgstr "无法在单声道模式打开设备播放。" + +msgid "Could not open device for playback in stereo mode." +msgstr "无法在立体声模式打开设备播放。" + +#, c-format +msgid "Could not open device for playback in %d-channel mode." +msgstr "无法在 %d 声道模式打开设备播放。" + +msgid "" +"Could not open audio device for playback. Device is being used by another " +"application." +msgstr "无法打开音频设备用于回放。目前有另一个程序正在使用该设备。" + +msgid "Could not open audio device for playback." +msgstr "无法打开音频设备播放。" + +msgid "Could not open device for recording in mono mode." +msgstr "无法在单声道模式打开设备录音。" + +msgid "Could not open device for recording in stereo mode." +msgstr "无法在立体声模式打开设备录音。" + +#, c-format +msgid "Could not open device for recording in %d-channel mode" +msgstr "无法在 %d 声道模式打开设备录音。" + +msgid "" +"Could not open audio device for recording. Device is being used by another " +"application." +msgstr "无法打开音频设备用于录音。目前有另一个程序正在使用该设备。" + +msgid "Could not open audio device for recording." +msgstr "无法打开音频设备录音。" + +msgid "Could not open CD device for reading." +msgstr "无法打开 CD 设备读取。" + +msgid "Could not seek CD." +msgstr "无法搜索 CD。" + +msgid "Could not read CD." +msgstr "无法读取 CD。" + +#, c-format +msgid "Could not open vfs file \"%s\" for writing: %s." +msgstr "无法打开 vfs 文件“%s”写入:%s。" + +msgid "No filename given" +msgstr "没有给定文件名" + +#, c-format +msgid "Could not close vfs file \"%s\"." +msgstr "无法关闭 vfs 文件“%s”。" + +#, c-format +msgid "Error while writing to file \"%s\"." +msgstr "写入文件“%s”时出错。" + +msgid "Internal data stream error." +msgstr "内部数据流错误。" + +#, c-format +msgid "A %s plugin is required to play this stream, but not installed." +msgstr "播放此数据流需要 %s 插件,但它未安装。" + +msgid "This appears to be a text file" +msgstr "此文件是个文本文件" + +#, fuzzy +msgid "Could not determine type of stream" +msgstr "无法创建“typefind”组件。" + +#, c-format +msgid "Invalid subtitle URI \"%s\", subtitles disabled." +msgstr "无效的字幕 URI “%s”,不使用字幕。" + +msgid "No URI specified to play from." +msgstr "未指定要播放的 URI。" + +#, c-format +msgid "Invalid URI \"%s\"." +msgstr "无效的 URI“%s”。" + +msgid "RTSP streams cannot be played yet." +msgstr "RTSP 流尚不能播放。" + +msgid "Could not create \"decodebin\" element." +msgstr "无法创建“decodebin”组件。" + +msgid "Source element is invalid." +msgstr "无效的源组件。" + +msgid "" +"Only a subtitle stream was detected. Either you are loading a subtitle file " +"or some other type of text file, or the media file was not recognized." +msgstr "" +"仅检测到字幕流。您可能装入的是字幕文件或者其它类型文本文件,又或者是媒体文件" +"无法识别。" + +msgid "" +"You do not have a decoder installed to handle this file. You might need to " +"install the necessary plugins." +msgstr "您没有安装可处理此文件的解码器。您可能需要安装必要的插件。" + +msgid "This is not a media file" +msgstr "此文件不是媒体文件" + +msgid "A subtitle stream was detected, but no video stream." +msgstr "检测到了字幕流,但无视频流。" + +msgid "Both autovideosink and xvimagesink elements are missing." +msgstr "autovideosink 和 xvimagesink 组件都缺少。" + +#, c-format +msgid "Missing element '%s' - check your GStreamer installation." +msgstr "未找到组件‘%s’-请检查您的 GStreamer 安装情况。" + +msgid "Both autoaudiosink and alsasink elements are missing." +msgstr "autovideosink 和 alsasink 组件都缺少。" + +#, fuzzy, c-format +msgid "Both autovideosink and %s elements are missing." +msgstr "autovideosink 和 xvimagesink 组件都缺少。" + +#, fuzzy +msgid "The autovideosink element is missing." +msgstr "autovideosink 和 xvimagesink 组件都缺少。" + +#, c-format +msgid "Configured videosink %s is not working." +msgstr "" + +#, fuzzy, c-format +msgid "Both autovideosink and %s elements are not working." +msgstr "autovideosink 和 xvimagesink 组件都缺少。" + +#, fuzzy +msgid "The autovideosink element is not working." +msgstr "autovideosink 和 xvimagesink 组件都缺少。" + +msgid "Custom text sink element is not usable." +msgstr "" + +msgid "No volume control found" +msgstr "未找到音量控制" + +#, fuzzy, c-format +msgid "Both autoaudiosink and %s elements are missing." +msgstr "autovideosink 和 alsasink 组件都缺少。" + +#, fuzzy +msgid "The autoaudiosink element is missing." +msgstr "autovideosink 和 alsasink 组件都缺少。" + +#, c-format +msgid "Configured audiosink %s is not working." +msgstr "" + +#, fuzzy, c-format +msgid "Both autoaudiosink and %s elements are not working." +msgstr "autovideosink 和 alsasink 组件都缺少。" + +#, fuzzy +msgid "The autoaudiosink element is not working." +msgstr "autovideosink 和 alsasink 组件都缺少。" + +#, fuzzy +msgid "Can't play a text file without video or visualizations." +msgstr "无法播放不带视频的文本文件。" + +#, c-format +msgid "No decoder available for type '%s'." +msgstr "找不到‘%s’类型可用的解码器。" + +msgid "This stream type cannot be played yet." +msgstr "此类型的数据流尚不能播放。" + +#, c-format +msgid "No URI handler implemented for \"%s\"." +msgstr "“%s”未实现 URI 处理器。" + +#, c-format +msgid "Error while sending data to \"%s:%d\"." +msgstr "发送数据至“%s:%d”时出错。" + +#, fuzzy, c-format +msgid "Error while sending gdp header data to \"%s:%d\"." +msgstr "发送 gdp 头部数据至“%s:%d”时出错。" + +#, c-format +msgid "Error while sending gdp payload data to \"%s:%d\"." +msgstr "发送 gdp 负载数据至“%s:%d”时出错。" + +#, c-format +msgid "Connection to %s:%d refused." +msgstr "拒绝连接至 %s:%d。" + +msgid "Can't record audio fast enough" +msgstr "无法足够快的录音" + +msgid "Failed to read tag: not enough data" +msgstr "无法读取标签: 数据不足" + +msgid "track ID" +msgstr "音轨 ID" + +msgid "MusicBrainz track ID" +msgstr "MusicBrainz 音轨 ID" + +msgid "artist ID" +msgstr "艺人 ID" + +msgid "MusicBrainz artist ID" +msgstr "MusicBrainz 艺人 ID" + +msgid "album ID" +msgstr "专辑 ID" + +msgid "MusicBrainz album ID" +msgstr "MusicBrainz 专辑 ID" + +msgid "album artist ID" +msgstr "音轨艺人 ID" + +msgid "MusicBrainz album artist ID" +msgstr "MusicBrainz 专辑艺人 ID" + +msgid "track TRM ID" +msgstr "音轨 TRM ID" + +msgid "MusicBrainz TRM ID" +msgstr "MusicBrainz TRM ID" + +msgid "capturing shutter speed" +msgstr "" + +msgid "Shutter speed used when capturing an image, in seconds" +msgstr "" + +msgid "capturing focal ratio" +msgstr "" + +msgid "Focal ratio (f-number) used when capturing the image" +msgstr "" + +msgid "capturing focal length" +msgstr "" + +msgid "Focal length of the lens used capturing the image, in mm" +msgstr "" + +msgid "capturing digital zoom ratio" +msgstr "" + +msgid "Digital zoom ratio used when capturing an image" +msgstr "" + +msgid "capturing iso speed" +msgstr "" + +msgid "The ISO speed used when capturing an image" +msgstr "" + +msgid "capturing exposure program" +msgstr "" + +msgid "The exposure program used when capturing an image" +msgstr "" + +msgid "capturing exposure mode" +msgstr "" + +msgid "The exposure mode used when capturing an image" +msgstr "" + +msgid "capturing exposure compensation" +msgstr "" + +msgid "The exposure compensation used when capturing an image" +msgstr "" + +msgid "capturing scene capture type" +msgstr "" + +msgid "The scene capture mode used when capturing an image" +msgstr "" + +msgid "capturing gain adjustment" +msgstr "" + +msgid "The overall gain adjustment applied on an image" +msgstr "" + +msgid "capturing white balance" +msgstr "" + +msgid "The white balance mode set when capturing an image" +msgstr "" + +msgid "capturing contrast" +msgstr "" + +msgid "The direction of contrast processing applied when capturing an image" +msgstr "" + +msgid "capturing saturation" +msgstr "" + +msgid "The direction of saturation processing applied when capturing an image" +msgstr "" + +msgid "capturing sharpness" +msgstr "" + +msgid "The direction of sharpness processing applied when capturing an image" +msgstr "" + +msgid "capturing flash fired" +msgstr "" + +msgid "If the flash fired while capturing an image" +msgstr "" + +msgid "capturing flash mode" +msgstr "" + +msgid "The selected flash mode while capturing an image" +msgstr "" + +msgid "capturing metering mode" +msgstr "" + +msgid "" +"The metering mode used while determining exposure for capturing an image" +msgstr "" + +msgid "capturing source" +msgstr "" + +msgid "The source or type of device used for the capture" +msgstr "" + +msgid "image horizontal ppi" +msgstr "" + +msgid "Media (image/video) intended horizontal pixel density in ppi" +msgstr "" + +msgid "image vertical ppi" +msgstr "" + +msgid "Media (image/video) intended vertical pixel density in ppi" +msgstr "" + +msgid "This CD has no audio tracks" +msgstr "此 CD 无音轨" + +msgid "ID3 tag" +msgstr "ID3 标识" + +msgid "APE tag" +msgstr "APE 标识" + +msgid "ICY internet radio" +msgstr "ICY 网络电台" + +msgid "Apple Lossless Audio (ALAC)" +msgstr "Apple 无损音频(ALAC)" + +msgid "Free Lossless Audio Codec (FLAC)" +msgstr "自由无损音频编码(FLAC)" + +msgid "Lossless True Audio (TTA)" +msgstr "无损高保真音频(TTA)" + +msgid "Windows Media Speech" +msgstr "Windows Media 语音" + +msgid "CYUV Lossless" +msgstr "CYUV 无损" + +msgid "FFMpeg v1" +msgstr "FFMpeg v1" + +msgid "Lossless MSZH" +msgstr "无损 MSZH" + +msgid "Uncompressed Gray Image" +msgstr "未压缩的灰度图像" + +msgid "Run-length encoding" +msgstr "Run-length 编码" + +msgid "Sami subtitle format" +msgstr "Sami 字幕格式" + +msgid "TMPlayer subtitle format" +msgstr "TMPlayer 字幕格式" + +msgid "Kate subtitle format" +msgstr "Kate 字幕格式" + +msgid "Uncompressed planar YUV 4:2:0" +msgstr "未压缩的 planar YUV 4:2:0" + +msgid "Uncompressed planar YVU 4:2:0" +msgstr "未压缩的 planar YVU 4:2:0" + +msgid "Uncompressed packed YUV 4:2:2" +msgstr "未压缩的 packed YUV 4:2:2" + +msgid "Uncompressed packed YUV 4:1:0" +msgstr "未压缩的 packed YUV 4:1:0" + +msgid "Uncompressed packed YVU 4:1:0" +msgstr "未压缩的 packed YVU 4:1:0" + +msgid "Uncompressed packed YUV 4:1:1" +msgstr "未压缩的 packed YUV 4:1:1" + +msgid "Uncompressed packed YUV 4:4:4" +msgstr "未压缩的 packed YUV 4:4:4" + +msgid "Uncompressed planar YUV 4:2:2" +msgstr "未压缩的 planar YUV 4:2:2" + +msgid "Uncompressed planar YUV 4:1:1" +msgstr "未压缩的 planar YUV 4:1:1" + +msgid "Uncompressed black and white Y-plane" +msgstr "未压缩的黑白 Y-plane" + +msgid "Uncompressed YUV" +msgstr "未压缩的 YUV" + +#, fuzzy, c-format +msgid "Uncompressed palettized %d-bit %s" +msgstr "未压缩的 palettized %d-位 %s" + +#, c-format +msgid "DivX MPEG-4 Version %d" +msgstr "DivX MPEG-4 版本 %d" + +#, c-format +msgid "Raw %d-bit PCM audio" +msgstr "原始 %d-位 PCM 音频" + +msgid "Raw PCM audio" +msgstr "原始 PCM 音频" + +#, c-format +msgid "Raw %d-bit floating-point audio" +msgstr "原始 %d-位浮点音频" + +msgid "Raw floating-point audio" +msgstr "原始浮点音频" + +msgid "Audio CD source" +msgstr "音频 CD 源" + +msgid "DVD source" +msgstr "DVD 源" + +msgid "Real Time Streaming Protocol (RTSP) source" +msgstr "实时流协议(RTSP)源" + +msgid "Microsoft Media Server (MMS) protocol source" +msgstr "Microsoft 媒体服务协议(MMS)源" + +#, c-format +msgid "%s protocol source" +msgstr "%s 协议源" + +#, fuzzy, c-format +msgid "%s video RTP depayloader" +msgstr "%s 视频 RTP 去负载器" + +#, fuzzy, c-format +msgid "%s audio RTP depayloader" +msgstr "%s 音频 RTP 去负载器" + +#, fuzzy, c-format +msgid "%s RTP depayloader" +msgstr "%s RTP 去负载器" + +#, c-format +msgid "%s demuxer" +msgstr "%s 多路分配器" + +#, c-format +msgid "%s decoder" +msgstr "%s 解码器" + +#, c-format +msgid "%s video RTP payloader" +msgstr "%s 视频 RTP 负载器" + +#, c-format +msgid "%s audio RTP payloader" +msgstr "%s 音频 RTP 负载器" + +#, c-format +msgid "%s RTP payloader" +msgstr "%s RTP 负载器" + +#, c-format +msgid "%s muxer" +msgstr "%s 混音器" + +#, c-format +msgid "%s encoder" +msgstr "%s 编码器" + +#, c-format +msgid "GStreamer element %s" +msgstr "GStreamer 组件 %s" + +msgid "Unknown source element" +msgstr "未知源组件" + +msgid "Unknown sink element" +msgstr "未知消音组件" + +msgid "Unknown element" +msgstr "未知组件" + +msgid "Unknown decoder element" +msgstr "未知的解码组件" + +msgid "Unknown encoder element" +msgstr "未知的编码组件" + +msgid "Plugin or element of unknown type" +msgstr "未知类型的插件或组件" + +msgid "No device specified." +msgstr "未指定设备。" + +#, c-format +msgid "Device \"%s\" does not exist." +msgstr "设备“%s”不存在。" + +#, c-format +msgid "Device \"%s\" is already being used." +msgstr "设备“%s”目前已被使用了。" + +#, c-format +msgid "Could not open device \"%s\" for reading and writing." +msgstr "无法打开设备“%s”读取。" + +#~ msgid "No file name specified." +#~ msgstr "未给定文件名。" + +#~ msgid "Could not open file \"%s\" for reading." +#~ msgstr "无法打开文件“%s”读取。" + +#~ msgid "Could not create \"decodebin2\" element." +#~ msgstr "无法创建“decodebin”组件。" + +#~ msgid "Could not create \"queue2\" element." +#~ msgstr "无法创建“queue2”组件。" diff --git a/gst-plugins-base-subtitles0.10/sys/Makefile.am b/gst-plugins-base-subtitles0.10/sys/Makefile.am new file mode 100644 index 0000000..8a0309a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/Makefile.am @@ -0,0 +1,29 @@ +if USE_GST_V4L +V4L_DIR=v4l +else +V4L_DIR= +endif + +if USE_X +XIMAGE_DIR=ximage +else +XIMAGE_DIR= +endif + +if USE_XVIDEO +XVIMAGE_DIR=xvimage +else +XVIMAGE_DIR= +endif + +SUBDIRS = \ + $(XIMAGE_DIR) \ + $(XVIMAGE_DIR) \ + $(V4L_DIR) + +DIST_SUBDIRS = \ + v4l \ + ximage \ + xvimage + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/.gitignore b/gst-plugins-base-subtitles0.10/sys/v4l/.gitignore new file mode 100644 index 0000000..bcb497a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/.gitignore @@ -0,0 +1,2 @@ +gstv4lelement-marshal.h +gstv4lelement-marshal.c diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/Makefile.am b/gst-plugins-base-subtitles0.10/sys/v4l/Makefile.am new file mode 100644 index 0000000..5f2b95f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/Makefile.am @@ -0,0 +1,41 @@ +plugin_LTLIBRARIES = libgstvideo4linux.la + +if USE_XVIDEO +xv_source = gstv4lxoverlay.c +xv_libs = $(X_LIBS) $(XVIDEO_LIBS) +else +xv_source = +xv_libs = +endif + +libgstvideo4linux_la_SOURCES = \ + gstv4l.c \ + gstv4lcolorbalance.c \ + gstv4lelement.c \ + gstv4lsrc.c \ + gstv4ltuner.c \ + v4l_calls.c \ + v4lsrc_calls.c $(xv_source) + +# gstv4ljpegsrc.c \ +# gstv4lmjpegsrc.c v4lmjpegsrc_calls.c \ +# gstv4lmjpegsink.c v4lmjpegsink_calls.c + +libgstvideo4linux_la_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) \ + $(GUDEV_CFLAGS) +libgstvideo4linux_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) $(GST_LIBS) $(xv_libs) \ + $(GUDEV_LIBS) +libgstvideo4linux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideo4linux_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstv4lelement.h v4l_calls.h \ + gstv4lsrc.h v4lsrc_calls.h \ + gstv4ljpegsrc.h \ + gstv4lmjpegsrc.h v4lmjpegsrc_calls.h \ + gstv4lmjpegsink.h v4lmjpegsink_calls.h \ + videodev_mjpeg.h \ + gstv4ltuner.h gstv4lxoverlay.h \ + gstv4lcolorbalance.h diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/README b/gst-plugins-base-subtitles0.10/sys/v4l/README new file mode 100644 index 0000000..980e193 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/README @@ -0,0 +1,35 @@ +General Idea: +============= + + _____/ gstv4lsrc.[ch] + _____/ \ v4lsrc_calls.[ch] + / +gstv4lelement.[ch] _/____________/ gstv4lmjpegsrc.[ch] +v4l_calls.[ch] \ \ v4lmjpegsrc_calls.[ch] + \_____ + \_____/ gstv4lmjpegsink.[ch] + \ v4lmjpegsink_calls.[ch] + +I.e., all the files on the right are child classes of +the v4lelement 'parent' on the left. + +* v4lelement handles generic v4l stuff (picture settings, + audio, norm/input setting, open()/close()) +* v4lsrc, v4lmjpegsrc handle the capture specific + functions. Maybe we'd need a v4lmpegsrc too +* v4lmjpegsink handles mjpeg hardware playback of video + +Useful Documentation: +===================== +MJPEG/V4L API : ./videodev_mjpeg.h + +V4L API : /usr/include/linux/videodev.h or + /usr/src/linux/Documentation/video4linux/API.html or + http://linux.bytesex.org/v4l2/API.html + +V4L2 API : /usr/include/linux/videodev2.h or + http://v4l2spec.bytesex.org/ + +BSD/Meteor API: /usr/include/machine/ioctl_meteor.h + +mjpegtools : http://www.sourceforge.net/projects/mjpeg diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/TODO b/gst-plugins-base-subtitles0.10/sys/v4l/TODO new file mode 100644 index 0000000..96616c0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/TODO @@ -0,0 +1,44 @@ +TODO list (short term): +======================= +* v4lsrc/v4lmjpegsrc/v4l2src: fix interlacing (not handled at all...) + +TODO list (long term): +====================== +* v4lmpegsrc (*hint* MPEG card needed *hint*) +* v4l2sink +* BSD-videosrc (bktr) + +Useful Documentation: +===================== +MJPEG/V4L API : ./videodev_mjpeg.h + +V4L API : /usr/include/linux/videodev.h or + /usr/src/linux/Documentation/video4linux/API.html or + http://linux.bytesex.org/v4l2/API.html + +V4L2 API : /usr/include/linux/videodev2.h or + http://v4l2spec.bytesex.org/ + +BSD/Meteor API: /usr/include/machine/ioctl_meteor.h + +mjpegtools : http://www.sourceforge.net/projects/mjpeg + +Capturing: +========== +* sound is the master clock +* it's probably a good idea to create an audiosource element: + - autodetect alsa/oss + - first try alsa, then oss... they work the same internally +* same for videosource: + - autodetect v4l/v4l2 + mjpeg capabilities + - for this, just open device using v4l2element. On success: + + use v4l2 + - on failure: + + use v4lelement and query for MJPEG capabilities + + if that's available, combine caps of v4lmjpegsrc and v4lsrc +* both sources run in their own GstThread with a high priority +* an encoder element takes care of encoding + muxing. A toplevel element + (reverse of spider) is probably a good idea here. How? Don't know... +* format negotiation via filtered caps +* statistics via listening to the frame_{lost,inserted,deleted,captures} + signals and GST_PAD_QUERY_POSITION (gst_pad_query()) diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4l.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4l.c new file mode 100644 index 0000000..aa467c4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4l.c @@ -0,0 +1,67 @@ +/* GStreamer + * + * gstv4l.c: plugin for v4l elements + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gst/gst-i18n-plugin.h" + +#include + +#include "gstv4lelement.h" +#include "gstv4lsrc.h" +/* #include "gstv4ljpegsrc.h" */ +/* #include "gstv4lmjpegsrc.h" */ +/* #include "gstv4lmjpegsink.h" */ + +GST_DEBUG_CATEGORY (v4l_debug); /* used in v4l_calls.c and v4lsrc_calls.c */ + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (v4l_debug, "v4l", 0, "V4L API calls"); + + if (!gst_element_register (plugin, "v4lsrc", GST_RANK_MARGINAL, + GST_TYPE_V4LSRC)) +/* !gst_element_register (plugin, "v4ljpegsrc", */ +/* GST_RANK_NONE, GST_TYPE_V4LJPEGSRC) || */ +/* !gst_element_register (plugin, "v4lmjpegsrc", */ +/* GST_RANK_NONE, GST_TYPE_V4LMJPEGSRC) || */ +/* !gst_element_register (plugin, "v4lmjpegsink", */ +/* GST_RANK_NONE, GST_TYPE_V4LMJPEGSINK)) */ + return FALSE; + +#ifdef ENABLE_NLS + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); +#endif /* ENABLE_NLS */ + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "video4linux", + "elements for Video 4 Linux", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.c new file mode 100644 index 0000000..35745bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.c @@ -0,0 +1,150 @@ +/* GStreamer + * + * gstv4lcolorbalance.c: color balance interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include "gstv4lcolorbalance.h" +#include "gstv4lelement.h" + +static void +gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass * + klass); +static void gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel * + channel); + +static const GList *gst_v4l_color_balance_list_channels (GstColorBalance * + balance); +static void gst_v4l_color_balance_set_value (GstColorBalance * balance, + GstColorBalanceChannel * channel, gint value); +static gint gst_v4l_color_balance_get_value (GstColorBalance * balance, + GstColorBalanceChannel * channel); + +static GstColorBalanceChannelClass *parent_class = NULL; + +GType +gst_v4l_color_balance_channel_get_type (void) +{ + static GType gst_v4l_color_balance_channel_type = 0; + + if (!gst_v4l_color_balance_channel_type) { + static const GTypeInfo v4l_tuner_channel_info = { + sizeof (GstV4lColorBalanceChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l_color_balance_channel_class_init, + NULL, + NULL, + sizeof (GstV4lColorBalanceChannel), + 0, + (GInstanceInitFunc) gst_v4l_color_balance_channel_init, + NULL + }; + + gst_v4l_color_balance_channel_type = + g_type_register_static (GST_TYPE_COLOR_BALANCE_CHANNEL, + "GstV4lColorBalanceChannel", &v4l_tuner_channel_info, 0); + } + + return gst_v4l_color_balance_channel_type; +} + +static void +gst_v4l_color_balance_channel_class_init (GstV4lColorBalanceChannelClass * + klass) +{ + parent_class = g_type_class_peek_parent (klass); +} + +static void +gst_v4l_color_balance_channel_init (GstV4lColorBalanceChannel * channel) +{ + channel->index = 0; +} + +void +gst_v4l_color_balance_interface_init (GstColorBalanceClass * klass) +{ + GST_COLOR_BALANCE_TYPE (klass) = GST_COLOR_BALANCE_HARDWARE; + + /* default virtual functions */ + klass->list_channels = gst_v4l_color_balance_list_channels; + klass->set_value = gst_v4l_color_balance_set_value; + klass->get_value = gst_v4l_color_balance_get_value; +} + +static G_GNUC_UNUSED gboolean +gst_v4l_color_balance_contains_channel (GstV4lElement * v4lelement, + GstV4lColorBalanceChannel * v4lchannel) +{ + const GList *item; + + for (item = v4lelement->colors; item != NULL; item = item->next) + if (item->data == v4lchannel) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l_color_balance_list_channels (GstColorBalance * balance) +{ + return GST_V4LELEMENT (balance)->colors; +} + +static void +gst_v4l_color_balance_set_value (GstColorBalance * balance, + GstColorBalanceChannel * channel, gint value) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (balance); + GstV4lColorBalanceChannel *v4lchannel = + GST_V4L_COLOR_BALANCE_CHANNEL (channel); + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L_IS_OPEN (v4lelement)); + g_return_if_fail (gst_v4l_color_balance_contains_channel (v4lelement, + v4lchannel)); + + gst_v4l_set_picture (v4lelement, v4lchannel->index, value); +} + +static gint +gst_v4l_color_balance_get_value (GstColorBalance * balance, + GstColorBalanceChannel * channel) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (balance); + GstV4lColorBalanceChannel *v4lchannel = + GST_V4L_COLOR_BALANCE_CHANNEL (channel); + gint value; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0); + g_return_val_if_fail (gst_v4l_color_balance_contains_channel (v4lelement, + v4lchannel), 0); + + if (!gst_v4l_get_picture (v4lelement, v4lchannel->index, &value)) + return 0; + + return value; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.h new file mode 100644 index 0000000..7f5c223 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lcolorbalance.h @@ -0,0 +1,59 @@ +/* GStreamer + * + * gstv4lcolorbalance.h: color balance interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4L_COLOR_BALANCE_H__ +#define __GST_V4L_COLOR_BALANCE_H__ + +#include +#include +#include "v4l_calls.h" + +G_BEGIN_DECLS + +#define GST_TYPE_V4L_COLOR_BALANCE_CHANNEL \ + (gst_v4l_color_balance_channel_get_type ()) +#define GST_V4L_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \ + GstV4lColorBalanceChannel)) +#define GST_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, \ + GstV4lColorBalanceChannelClass)) +#define GST_IS_V4L_COLOR_BALANCE_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL)) +#define GST_IS_V4L_COLOR_BALANCE_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_COLOR_BALANCE_CHANNEL)) + +typedef struct _GstV4lColorBalanceChannel { + GstColorBalanceChannel parent; + + GstV4lPictureType index; +} GstV4lColorBalanceChannel; + +typedef struct _GstV4lColorBalanceChannelClass { + GstColorBalanceChannelClass parent; +} GstV4lColorBalanceChannelClass; + +GType gst_v4l_color_balance_channel_get_type (void); + +void gst_v4l_color_balance_interface_init (GstColorBalanceClass *klass); + +#endif /* __GST_V4L_COLOR_BALANCE_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.c new file mode 100644 index 0000000..91776af --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.c @@ -0,0 +1,552 @@ +/* GStreamer + * + * gstv4lelement.c: base class for V4L elements + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#ifdef HAVE_GUDEV +#include +#endif + +#include "v4l_calls.h" +#include "gstv4ltuner.h" +#ifdef HAVE_XVIDEO +#include "gstv4lxoverlay.h" +#endif +#include "gstv4lcolorbalance.h" + + +enum +{ + PROP_0, + PROP_DEVICE, + PROP_DEVICE_NAME, + PROP_FLAGS +}; + +GST_DEBUG_CATEGORY (v4lelement_debug); +#define GST_CAT_DEFAULT v4lelement_debug + +static void gst_v4lelement_init_interfaces (GType type); + +GST_BOILERPLATE_FULL (GstV4lElement, gst_v4lelement, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_v4lelement_init_interfaces); + +static void gst_v4lelement_dispose (GObject * object); +static void gst_v4lelement_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_v4lelement_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +/* element methods */ +static GstStateChangeReturn gst_v4lelement_change_state (GstElement * element, + GstStateChange transition); + +static gboolean +gst_v4l_iface_supported (GstImplementsInterface * iface, GType iface_type) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (iface); + +#ifdef HAVE_XVIDEO + g_assert (iface_type == GST_TYPE_TUNER || + iface_type == GST_TYPE_X_OVERLAY || iface_type == GST_TYPE_COLOR_BALANCE); +#else + g_assert (iface_type == GST_TYPE_TUNER || + iface_type == GST_TYPE_COLOR_BALANCE); +#endif + + if (v4lelement->video_fd == -1) + return FALSE; + +#ifdef HAVE_XVIDEO + if (iface_type == GST_TYPE_X_OVERLAY && !GST_V4L_IS_OVERLAY (v4lelement)) + return FALSE; +#endif + + return TRUE; +} + +static void +gst_v4l_interface_init (GstImplementsInterfaceClass * klass) +{ + /* default virtual functions */ + klass->supported = gst_v4l_iface_supported; +} + +static const GList * +gst_v4l_probe_get_properties (GstPropertyProbe * probe) +{ + GObjectClass *klass = G_OBJECT_GET_CLASS (probe); + static GList *list = NULL; + + if (!list) { + list = g_list_append (NULL, g_object_class_find_property (klass, "device")); + } + + return list; +} + +static gboolean init = FALSE; +static GList *devices = NULL; + +#ifdef HAVE_GUDEV +static gboolean +gst_v4l_class_probe_devices_with_udev (GstV4lElementClass * klass, + gboolean check) +{ + GUdevClient *client = NULL; + GList *item; + + if (!check) { + while (devices) { + gchar *device = devices->data; + devices = g_list_remove (devices, device); + g_free (device); + } + + GST_INFO ("Enumerating video4linux devices from udev"); + client = g_udev_client_new (NULL); + if (!client) { + GST_WARNING ("Failed to initialize gudev client"); + goto finish; + } + + item = g_udev_client_query_by_subsystem (client, "video4linux"); + while (item) { + GUdevDevice *device = item->data; + gchar *devnode = g_strdup (g_udev_device_get_device_file (device)); + gint api = g_udev_device_get_property_as_int (device, "ID_V4L_VERSION"); + GST_INFO ("Found new device: %s, API: %d", devnode, api); + /* Append v4l1 devices only. If api is 0 probably v4l_id has + been stripped out of the current udev installation, append + anyway */ + if (api == 0) { + GST_WARNING + ("Couldn't retrieve ID_V4L_VERSION, silly udev installation?"); + } + if ((api == 1 || api == 0)) { + devices = g_list_append (devices, devnode); + } else { + g_free (devnode); + } + g_object_unref (device); + item = item->next; + } + g_list_free (item); + init = TRUE; + } + +finish: + if (client) { + g_object_unref (client); + } + + klass->devices = devices; + + return init; +} +#endif /* HAVE_GUDEV */ + +static gboolean +gst_v4l_class_probe_devices (GstV4lElementClass * klass, gboolean check) +{ + if (!check) { + const gchar *dev_base[] = { "/dev/video", "/dev/v4l/video", NULL }; + gint base, n, fd; + + while (devices) { + gchar *device = devices->data; + devices = g_list_remove (devices, device); + g_free (device); + } + + /* detect /dev entries */ + for (n = 0; n < 64; n++) { + for (base = 0; dev_base[base] != NULL; base++) { + struct stat s; + gchar *device = g_strdup_printf ("%s%d", dev_base[base], n); + + /* does the /dev/ entry exist at all? */ + if (stat (device, &s) == 0) { + /* yes: is a device attached? */ + if ((fd = open (device, O_RDONLY)) > 0 || errno == EBUSY) { + if (fd > 0) + close (fd); + + devices = g_list_append (devices, device); + break; + } + } + g_free (device); + } + } + + init = TRUE; + } + + klass->devices = devices; + + return init; +} + +static void +gst_v4l_probe_probe_property (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + + switch (prop_id) { + case PROP_DEVICE: +#ifdef HAVE_GUDEV + if (!gst_v4l_class_probe_devices_with_udev (klass, FALSE)) + gst_v4l_class_probe_devices (klass, FALSE); +#else /* !HAVE_GUDEV */ + gst_v4l_class_probe_devices (klass, FALSE); +#endif /* HAVE_GUDEV */ + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } +} + +static gboolean +gst_v4l_probe_needs_probe (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + gboolean ret = FALSE; + + switch (prop_id) { + case PROP_DEVICE: +#ifdef HAVE_GUDEV + ret = !gst_v4l_class_probe_devices_with_udev (klass, FALSE); +#else /* !HAVE_GUDEV */ + ret = !gst_v4l_class_probe_devices (klass, TRUE); +#endif /* HAVE_GUDEV */ + ret = !gst_v4l_class_probe_devices (klass, TRUE); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return ret; +} + +static GValueArray * +gst_v4l_class_list_devices (GstV4lElementClass * klass) +{ + GValueArray *array; + GValue value = { 0 }; + GList *item; + + if (!klass->devices) + return NULL; + + array = g_value_array_new (g_list_length (klass->devices)); + item = klass->devices; + g_value_init (&value, G_TYPE_STRING); + while (item) { + gchar *device = item->data; + + g_value_set_string (&value, device); + g_value_array_append (array, &value); + + item = item->next; + } + g_value_unset (&value); + + return array; +} + +static GValueArray * +gst_v4l_probe_get_values (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_GET_CLASS (probe); + GValueArray *array = NULL; + + switch (prop_id) { + case PROP_DEVICE: + array = gst_v4l_class_list_devices (klass); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return array; +} + +static void +gst_v4l_property_probe_interface_init (GstPropertyProbeInterface * iface) +{ + iface->get_properties = gst_v4l_probe_get_properties; + iface->probe_property = gst_v4l_probe_probe_property; + iface->needs_probe = gst_v4l_probe_needs_probe; + iface->get_values = gst_v4l_probe_get_values; +} + +#define GST_TYPE_V4L_DEVICE_FLAGS (gst_v4l_device_get_type ()) +static GType +gst_v4l_device_get_type (void) +{ + static GType v4l_device_type = 0; + + if (v4l_device_type == 0) { + static const GFlagsValue values[] = { + {VID_TYPE_CAPTURE, "CAPTURE", "Device can capture"}, + {VID_TYPE_TUNER, "TUNER", "Device has a tuner"}, + {VID_TYPE_OVERLAY, "OVERLAY", "Device can do overlay"}, + {VID_TYPE_MPEG_DECODER, "MPEG_DECODER", "Device can decode MPEG"}, + {VID_TYPE_MPEG_ENCODER, "MPEG_ENCODER", "Device can encode MPEG"}, + {VID_TYPE_MJPEG_DECODER, "MJPEG_DECODER", "Device can decode MJPEG"}, + {VID_TYPE_MJPEG_ENCODER, "MJPEG_ENCODER", "Device can encode MJPEG"}, + {0x10000, "AUDIO", "Device handles audio"}, + {0, NULL, NULL} + }; + + v4l_device_type = g_flags_register_static ("GstV4lDeviceTypeFlags", values); + } + + return v4l_device_type; +} + +static void +gst_v4lelement_init_interfaces (GType type) +{ + static const GInterfaceInfo v4liface_info = { + (GInterfaceInitFunc) gst_v4l_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo v4l_tuner_info = { + (GInterfaceInitFunc) gst_v4l_tuner_interface_init, + NULL, + NULL, + }; +#ifdef HAVE_XVIDEO + static const GInterfaceInfo v4l_xoverlay_info = { + (GInterfaceInitFunc) gst_v4l_xoverlay_interface_init, + NULL, + NULL, + }; +#endif + static const GInterfaceInfo v4l_colorbalance_info = { + (GInterfaceInitFunc) gst_v4l_color_balance_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo v4l_propertyprobe_info = { + (GInterfaceInitFunc) gst_v4l_property_probe_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, + GST_TYPE_IMPLEMENTS_INTERFACE, &v4liface_info); + g_type_add_interface_static (type, GST_TYPE_TUNER, &v4l_tuner_info); +#ifdef HAVE_XVIDEO + g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &v4l_xoverlay_info); +#endif + g_type_add_interface_static (type, + GST_TYPE_COLOR_BALANCE, &v4l_colorbalance_info); + g_type_add_interface_static (type, + GST_TYPE_PROPERTY_PROBE, &v4l_propertyprobe_info); +} + + +static void +gst_v4lelement_base_init (gpointer g_class) +{ + GstV4lElementClass *klass = GST_V4LELEMENT_CLASS (g_class); + + klass->devices = NULL; + + GST_DEBUG_CATEGORY_INIT (v4lelement_debug, "v4lelement", 0, + "V4L Base Class debug"); +} + +static void +gst_v4lelement_class_init (GstV4lElementClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + + gobject_class = (GObjectClass *) klass; + element_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_v4lelement_set_property; + gobject_class->get_property = gst_v4lelement_get_property; + gobject_class->dispose = gst_v4lelement_dispose; + + element_class->change_state = gst_v4lelement_change_state; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE, + g_param_spec_string ("device", "Device", "Device location", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Device name", "Name of the device", + NULL, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_FLAGS, + g_param_spec_flags ("flags", "Flags", "Device type flags", + GST_TYPE_V4L_DEVICE_FLAGS, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + +} + + +static void +gst_v4lelement_init (GstV4lElement * v4lelement, GstV4lElementClass * klass) +{ + /* some default values */ + v4lelement->video_fd = -1; + v4lelement->buffer = NULL; + v4lelement->videodev = g_strdup ("/dev/video0"); + + v4lelement->norms = NULL; + v4lelement->channels = NULL; + v4lelement->colors = NULL; + + v4lelement->xwindow_id = 0; +} + + +static void +gst_v4lelement_dispose (GObject * object) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (object); + + if (v4lelement->videodev) { + g_free (v4lelement->videodev); + v4lelement->videodev = NULL; + } + + if (((GObjectClass *) parent_class)->dispose) + ((GObjectClass *) parent_class)->dispose (object); +} + + +static void +gst_v4lelement_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (object); + + switch (prop_id) { + case PROP_DEVICE: + if (v4lelement->videodev) + g_free (v4lelement->videodev); + v4lelement->videodev = g_strdup (g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_v4lelement_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (object); + + switch (prop_id) { + case PROP_DEVICE: + g_value_set_string (value, v4lelement->videodev); + break; + case PROP_DEVICE_NAME:{ + gchar *new = NULL; + + if (GST_V4L_IS_OPEN (v4lelement)) { + new = v4lelement->vcap.name; + } else if (gst_v4l_open (v4lelement)) { + new = v4lelement->vcap.name; + gst_v4l_close (v4lelement); + } + g_value_set_string (value, new); + break; + } + case PROP_FLAGS:{ + guint flags = 0; + + if (GST_V4L_IS_OPEN (v4lelement)) { + flags |= v4lelement->vcap.type & 0x3C0B; + if (v4lelement->vcap.audios) + flags |= 0x10000; + } + g_value_set_flags (value, flags); + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_v4lelement_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstV4lElement *v4lelement = GST_V4LELEMENT (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + /* open the device */ + if (!gst_v4l_open (v4lelement)) + return GST_STATE_CHANGE_FAILURE; +#ifdef HAVE_XVIDEO + gst_v4l_xoverlay_start (v4lelement); +#endif + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + /* close the device */ +#ifdef HAVE_XVIDEO + gst_v4l_xoverlay_stop (v4lelement); +#endif + if (!gst_v4l_close (v4lelement)) + return GST_STATE_CHANGE_FAILURE; + break; + default: + break; + } + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.h new file mode 100644 index 0000000..056873c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lelement.h @@ -0,0 +1,116 @@ +/* GStreamer + * + * gstv4lelement.h: base class for V4L elements + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4LELEMENT_H__ +#define __GST_V4LELEMENT_H__ + +/* Because of some really cool feature in video4linux1, also known as + * 'not including sys/types.h and sys/time.h', we had to include it + * ourselves. In all their intelligence, these people decided to fix + * this in the next version (video4linux2) in such a cool way that it + * breaks all compilations of old stuff... + * The real problem is actually that linux/time.h doesn't use proper + * macro checks before defining types like struct timeval. The proper + * fix here is to either fuck the kernel header (which is what we do + * by defining _LINUX_TIME_H, an innocent little hack) or by fixing it + * upstream, which I'll consider doing later on. If you get compiler + * errors here, check your linux/time.h && sys/time.h header setup. + */ +#include +#define _LINUX_TIME_H +#include + +#include +#include + + +G_BEGIN_DECLS + +#define GST_TYPE_V4LELEMENT \ + (gst_v4lelement_get_type()) +#define GST_V4LELEMENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LELEMENT,GstV4lElement)) +#define GST_V4LELEMENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LELEMENT,GstV4lElementClass)) +#define GST_IS_V4LELEMENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LELEMENT)) +#define GST_IS_V4LELEMENT_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LELEMENT)) +#define GST_V4LELEMENT_GET_CLASS(klass) \ + (G_TYPE_INSTANCE_GET_CLASS ((klass), GST_TYPE_V4LELEMENT, GstV4lElementClass)) + +typedef struct _GstV4lElement GstV4lElement; +typedef struct _GstV4lElementClass GstV4lElementClass; +typedef struct _GstV4lXv GstV4lXv; + +struct _GstV4lElement { + GstPushSrc element; + + /* the video device */ + char *videodev; + + /* the video-device's file descriptor */ + gint video_fd; + + /* the video buffer (mmap()'ed) */ + guint8 *buffer; + + /* the video device's capabilities */ + struct video_capability vcap; + + /* the video device's window properties */ + struct video_window vwin; + + /* some more info about the current input's capabilities */ + struct video_channel vchan; + + /* lists... */ + GList *colors; + GList *norms; + GList *channels; + + /* X-overlay */ + GstV4lXv *xv; + gulong xwindow_id; +}; + +struct _GstV4lElementClass { + GstPushSrcClass parent_class; + + /* probed devices */ + GList *devices; + + /* actions */ + gboolean (*get_attribute) (GstElement *element, + const gchar *attr_name, + int *value); + gboolean (*set_attribute) (GstElement *element, + const gchar *attr_name, + const int value); +}; + +GType gst_v4lelement_get_type(void); + + +G_END_DECLS + +#endif /* __GST_V4LELEMENT_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.c new file mode 100644 index 0000000..724a66f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.c @@ -0,0 +1,293 @@ +/* GStreamer + * + * gstv4ljpegsrc.c: V4L source element for JPEG cameras + * + * Copyright (C) 2004-2005 Jan Schmidt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + e Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "gstv4ljpegsrc.h" +#include "v4lsrc_calls.h" + +GST_DEBUG_CATEGORY_STATIC (v4ljpegsrc_debug); +#define GST_CAT_DEFAULT v4ljpegsrc_debug + +/* init functions */ +static void gst_v4ljpegsrc_base_init (gpointer g_class); +static void gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass); +static void gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc); + +/* buffer functions */ +static GstPadLinkReturn gst_v4ljpegsrc_src_link (GstPad * pad, + const GstCaps * caps); +static GstCaps *gst_v4ljpegsrc_getcaps (GstPad * pad); +static GstData *gst_v4ljpegsrc_get (GstPad * pad); + +static GstElementClass *parent_class = NULL; + +GType +gst_v4ljpegsrc_get_type (void) +{ + static GType v4ljpegsrc_type = 0; + + if (!v4ljpegsrc_type) { + static const GTypeInfo v4ljpegsrc_info = { + sizeof (GstV4lJpegSrcClass), + gst_v4ljpegsrc_base_init, + NULL, + (GClassInitFunc) gst_v4ljpegsrc_class_init, + NULL, + NULL, + sizeof (GstV4lJpegSrc), + 0, + (GInstanceInitFunc) gst_v4ljpegsrc_init, + NULL + }; + + v4ljpegsrc_type = + g_type_register_static (GST_TYPE_V4LSRC, "GstV4lJpegSrc", + &v4ljpegsrc_info, 0); + GST_DEBUG_CATEGORY_INIT (v4ljpegsrc_debug, "v4ljpegsrc", 0, + "V4L JPEG source element"); + } + return v4ljpegsrc_type; +} + +static void +gst_v4ljpegsrc_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "Video (video4linux/raw) Jpeg Source", "Source/Video", + "Reads jpeg frames from a video4linux (eg ov519) device", + "Jan Schmidt "); +} + +static void +gst_v4ljpegsrc_class_init (GstV4lJpegSrcClass * klass) +{ + parent_class = g_type_class_peek_parent (klass); +} + +static void +gst_v4ljpegsrc_init (GstV4lJpegSrc * v4ljpegsrc) +{ + GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc); + GstPad *pad = v4lsrc->srcpad; + + /* + * Stash away and then replace the getcaps and get functions on the src pad + */ + v4ljpegsrc->getfn = GST_RPAD_GETFUNC (pad); + v4ljpegsrc->getcapsfn = GST_RPAD_GETCAPSFUNC (pad); + + gst_pad_set_get_function (v4lsrc->srcpad, gst_v4ljpegsrc_get); + gst_pad_set_getcaps_function (v4lsrc->srcpad, gst_v4ljpegsrc_getcaps); + gst_pad_set_link_function (v4lsrc->srcpad, gst_v4ljpegsrc_src_link); +} + +static GstPadLinkReturn +gst_v4ljpegsrc_src_link (GstPad * pad, const GstCaps * vscapslist) +{ + GstV4lJpegSrc *v4ljpegsrc; + GstV4lSrc *v4lsrc; + gint w, h, palette = -1; + const GValue *fps; + GstStructure *structure; + gboolean was_capturing; + struct video_window *vwin; + + v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad)); + v4lsrc = GST_V4LSRC (v4ljpegsrc); + vwin = &GST_V4LELEMENT (v4lsrc)->vwin; + was_capturing = v4lsrc->is_capturing; + + /* in case the buffers are active (which means that we already + * did capsnego before and didn't clean up), clean up anyways */ + if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))) { + if (was_capturing) { + if (!gst_v4lsrc_capture_stop (v4lsrc)) + return GST_PAD_LINK_REFUSED; + } + if (!gst_v4lsrc_capture_deinit (v4lsrc)) + return GST_PAD_LINK_REFUSED; + } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { + return GST_PAD_LINK_DELAYED; + } + + structure = gst_caps_get_structure (vscapslist, 0); + + gst_structure_get_int (structure, "width", &w); + gst_structure_get_int (structure, "height", &h); + fps = gst_structure_get_value (structure, "framerate"); + + GST_DEBUG_OBJECT (v4ljpegsrc, "linking with %dx%d at %d/%d fps", w, h, + gst_value_get_fraction_numerator (fps), + gst_value_get_fraction_denominator (fps)); + + /* set framerate if it's not already correct */ + if (fps != gst_v4lsrc_get_fps (v4lsrc)) { + int fps_index = fps / 15.0 * 16; + + GST_DEBUG_OBJECT (v4ljpegsrc, "Trying to set fps index %d", fps_index); + /* set bits 16 to 21 to 0 */ + vwin->flags &= (0x3F00 - 1); + /* set bits 16 to 21 to the index */ + vwin->flags |= fps_index << 16; + if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) { + return GST_PAD_LINK_DELAYED; + } + } + + /* + * Try to set the camera to capture RGB24 + */ + palette = VIDEO_PALETTE_RGB24; + v4lsrc->buffer_size = w * h * 3; + + GST_DEBUG_OBJECT (v4ljpegsrc, "trying to set_capture %dx%d, palette %d", + w, h, palette); + /* this only fills in v4lsrc->mmap values */ + if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) { + GST_WARNING_OBJECT (v4ljpegsrc, "could not set_capture %dx%d, palette %d", + w, h, palette); + return GST_PAD_LINK_REFUSED; + } + + /* first try the negotiated settings using try_capture */ + if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) { + GST_DEBUG_OBJECT (v4ljpegsrc, "failed trying palette %d for %dx%d", palette, + w, h); + return GST_PAD_LINK_REFUSED; + } + + if (!gst_v4lsrc_capture_init (v4lsrc)) + return GST_PAD_LINK_REFUSED; + + if (was_capturing || GST_STATE (v4lsrc) == GST_STATE_PLAYING) { + if (!gst_v4lsrc_capture_start (v4lsrc)) + return GST_PAD_LINK_REFUSED; + } + + return GST_PAD_LINK_OK; +} + +static GstCaps * +gst_v4ljpegsrc_getcaps (GstPad * pad) +{ + GstCaps *list; + GstV4lJpegSrc *v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad)); + GstV4lSrc *v4lsrc = GST_V4LSRC (v4ljpegsrc); + struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap; + gfloat fps = 0.0; + + if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { + return gst_caps_new_any (); + } + if (!v4lsrc->autoprobe) { + /* FIXME: query current caps and return those, with _any appended */ + return gst_caps_new_any (); + } + + list = gst_caps_new_simple ("image/jpeg", NULL); + GST_DEBUG_OBJECT (v4ljpegsrc, + "Device reports w: %d-%d, h: %d-%d, fps: %f", + vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, fps); + + if (vcap->minwidth < vcap->maxwidth) { + gst_caps_set_simple (list, "width", GST_TYPE_INT_RANGE, vcap->minwidth, + vcap->maxwidth, NULL); + } else { + gst_caps_set_simple (list, "width", G_TYPE_INT, vcap->minwidth, NULL); + } + if (vcap->minheight < vcap->maxheight) { + gst_caps_set_simple (list, "height", GST_TYPE_INT_RANGE, vcap->minheight, + vcap->maxheight, NULL); + } else { + gst_caps_set_simple (list, "height", G_TYPE_INT, vcap->minheight, NULL); + } + + if (v4lsrc->fps_list) { + GstStructure *structure = gst_caps_get_structure (list, 0); + + gst_structure_set_value (structure, "framerate", v4lsrc->fps_list); + } + GST_DEBUG_OBJECT (v4ljpegsrc, "caps: %" GST_PTR_FORMAT, list); + + return list; +} + +static GstData * +gst_v4ljpegsrc_get (GstPad * pad) +{ + GstV4lJpegSrc *v4ljpegsrc; + GstV4lSrc *v4lsrc; + GstData *data; + GstBuffer *buf; + GstBuffer *outbuf; + int jpeg_size; + + g_return_val_if_fail (pad != NULL, NULL); + v4ljpegsrc = GST_V4LJPEGSRC (gst_pad_get_parent (pad)); + v4lsrc = GST_V4LSRC (v4ljpegsrc); + + /* Fetch from the v4lsrc class get fn. */ + data = v4ljpegsrc->getfn (pad); + + /* If not a buffer, return it unchanged */ + if (!data || (!GST_IS_BUFFER (data))) + return data; + + buf = GST_BUFFER (data); + + /* Confirm that the buffer contains jpeg data */ + + /* + * Create a new subbuffer from the jpeg data + * The first 2 bytes in the buffer are the size of the jpeg data + */ + if (GST_BUFFER_SIZE (buf) > 2) { + jpeg_size = (int) (GST_READ_UINT16_LE (GST_BUFFER_DATA (buf))) * 8; + } else + jpeg_size = 0; + + /* Check that the size is sensible */ + if ((jpeg_size <= 0) || (jpeg_size > GST_BUFFER_SIZE (buf) - 2)) { + GST_ELEMENT_ERROR (v4ljpegsrc, STREAM, FORMAT, (NULL), + ("Invalid non-jpeg frame from camera")); + return NULL; + } + + GST_DEBUG_OBJECT (v4ljpegsrc, "Creating JPEG subbuffer of size %d", + jpeg_size); + outbuf = gst_buffer_create_sub (buf, 2, jpeg_size); + + /* Copy timestamps onto the subbuffer */ + gst_buffer_stamp (outbuf, buf); + + /* Release the main buffer */ + gst_buffer_unref (buf); + + return GST_DATA (outbuf); +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.h new file mode 100644 index 0000000..1d4eab0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ljpegsrc.h @@ -0,0 +1,57 @@ +/* GStreamer + * + * gstv4ljpegsrc.h: V4L video source element for JPEG cameras + * + * Copyright (C) 2001-2005 Jan Schmidt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4LJPEGSRC_H__ +#define __GST_V4LJPEGSRC_H__ + +#include + +G_BEGIN_DECLS +#define GST_TYPE_V4LJPEGSRC \ + (gst_v4ljpegsrc_get_type()) +#define GST_V4LJPEGSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrc)) +#define GST_V4LJPEGSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LJPEGSRC,GstV4lJpegSrcClass)) +#define GST_IS_V4LJPEGSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LJPEGSRC)) +#define GST_IS_V4LJPEGSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LJPEGSRC)) +typedef struct _GstV4lJpegSrc GstV4lJpegSrc; +typedef struct _GstV4lJpegSrcClass GstV4lJpegSrcClass; + +struct _GstV4lJpegSrc +{ + GstV4lSrc v4lsrc; + GstPadGetFunction getfn; + GstPadGetCapsFunction getcapsfn; +}; + +struct _GstV4lJpegSrcClass +{ + GstV4lSrcClass parent_class; +}; + +GType gst_v4ljpegsrc_get_type (void); + +G_END_DECLS +#endif /* __GST_V4LJPEGSRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.c new file mode 100644 index 0000000..3a5cfaa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.c @@ -0,0 +1,431 @@ +/* GStreamer + * + * gstv4lmjpegsink.c: hardware MJPEG video sink plugin + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include "v4lmjpegsink_calls.h" + +GST_DEBUG_CATEGORY_STATIC (v4lmjpegsink_debug); +#define GST_CAT_DEFAULT v4lmjpegsink_debug + +/* v4lmjpegsink signals and args */ +enum +{ + SIGNAL_FRAME_DISPLAYED, + LAST_SIGNAL +}; + +enum +{ + ARG_0, + ARG_NUMBUFS, + ARG_BUFSIZE, + ARG_X_OFFSET, + ARG_Y_OFFSET, + ARG_FRAMES_DISPLAYED, + ARG_FRAME_TIME +}; + + +/* init functions */ +static void gst_v4lmjpegsink_base_init (gpointer g_class); +static void gst_v4lmjpegsink_class_init (GstV4lMjpegSinkClass * klass); +static void gst_v4lmjpegsink_init (GstV4lMjpegSink * v4lmjpegsink); + +/* the chain of buffers */ +static GstPadLinkReturn gst_v4lmjpegsink_sinkconnect (GstPad * pad, + const GstCaps * vscapslist); +static void gst_v4lmjpegsink_chain (GstPad * pad, GstData * _data); + +/* get/set gst object functions */ +static void gst_v4lmjpegsink_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_v4lmjpegsink_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static GstStateChangeReturn gst_v4lmjpegsink_change_state (GstElement * + element); +static void gst_v4lmjpegsink_set_clock (GstElement * element, GstClock * clock); + + +static GstElementClass *parent_class = NULL; +static guint gst_v4lmjpegsink_signals[LAST_SIGNAL] = { 0 }; + + +GType +gst_v4lmjpegsink_get_type (void) +{ + static GType v4lmjpegsink_type = 0; + + if (!v4lmjpegsink_type) { + static const GTypeInfo v4lmjpegsink_info = { + sizeof (GstV4lMjpegSinkClass), + gst_v4lmjpegsink_base_init, + NULL, + (GClassInitFunc) gst_v4lmjpegsink_class_init, + NULL, + NULL, + sizeof (GstV4lMjpegSink), + 0, + (GInstanceInitFunc) gst_v4lmjpegsink_init, + }; + + v4lmjpegsink_type = + g_type_register_static (GST_TYPE_V4LELEMENT, "GstV4lMjpegSink", + &v4lmjpegsink_info, 0); + } + return v4lmjpegsink_type; +} + +static void +gst_v4lmjpegsink_base_init (gpointer g_class) +{ + static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/jpeg, " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ], " "framerate = (fraction) [ 0, MAX ]") + ); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "Video (video4linux/MJPEG) sink", "Sink/Video", + "Writes MJPEG-encoded frames to a zoran MJPEG/video4linux device", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sink_template)); +} + +static void +gst_v4lmjpegsink_class_init (GstV4lMjpegSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUMBUFS, + g_param_spec_int ("num-buffers", "num-buffers", "num-buffers", + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFSIZE, + g_param_spec_int ("buffer-size", "buffer-size", "buffer-size", + G_MININT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_X_OFFSET, + g_param_spec_int ("x-offset", "x-offset", "x-offset", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_Y_OFFSET, + g_param_spec_int ("y-offset", "y-offset", "y-offset", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FRAMES_DISPLAYED, + g_param_spec_int ("frames-displayed", "frames-displayed", + "frames-displayed", G_MININT, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_FRAME_TIME, + g_param_spec_int ("frame-time", "frame-time", "frame-time", G_MININT, + G_MAXINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + GST_DEBUG_CATEGORY_INIT (v4lmjpegsink_debug, "v4lmjpegsink", 0, + "V4L MJPEG sink element"); + gobject_class->set_property = gst_v4lmjpegsink_set_property; + gobject_class->get_property = gst_v4lmjpegsink_get_property; + + gst_v4lmjpegsink_signals[SIGNAL_FRAME_DISPLAYED] = + g_signal_new ("frame-displayed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lMjpegSinkClass, + frame_displayed), NULL, NULL, g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + gstelement_class->change_state = gst_v4lmjpegsink_change_state; + gstelement_class->set_clock = gst_v4lmjpegsink_set_clock; +} + + +static void +gst_v4lmjpegsink_init (GstV4lMjpegSink * v4lmjpegsink) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (v4lmjpegsink); + + v4lmjpegsink->sinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "sink"), "sink"); + gst_element_add_pad (GST_ELEMENT (v4lmjpegsink), v4lmjpegsink->sinkpad); + + gst_pad_set_chain_function (v4lmjpegsink->sinkpad, gst_v4lmjpegsink_chain); + gst_pad_set_link_function (v4lmjpegsink->sinkpad, + gst_v4lmjpegsink_sinkconnect); + + v4lmjpegsink->clock = NULL; + + v4lmjpegsink->width = -1; + v4lmjpegsink->height = -1; + + v4lmjpegsink->x_offset = -1; + v4lmjpegsink->y_offset = -1; + + v4lmjpegsink->numbufs = 64; + v4lmjpegsink->bufsize = 256; + + GST_OBJECT_FLAG_SET (v4lmjpegsink, GST_ELEMENT_THREAD_SUGGESTED); +} + + +static GstPadLinkReturn +gst_v4lmjpegsink_sinkconnect (GstPad * pad, const GstCaps * vscapslist) +{ + GstV4lMjpegSink *v4lmjpegsink; + GstStructure *structure; + + v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad)); + + /* in case the buffers are active (which means that we already + * did capsnego before and didn't clean up), clean up anyways */ + if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsink))) + if (!gst_v4lmjpegsink_playback_deinit (v4lmjpegsink)) + return GST_PAD_LINK_REFUSED; + + structure = gst_caps_get_structure (vscapslist, 0); + + gst_structure_get_int (structure, "width", &v4lmjpegsink->width); + gst_structure_get_int (structure, "height", &v4lmjpegsink->height); + + if (!gst_v4lmjpegsink_set_playback (v4lmjpegsink, v4lmjpegsink->width, v4lmjpegsink->height, v4lmjpegsink->x_offset, v4lmjpegsink->y_offset, GST_V4LELEMENT (v4lmjpegsink)->vchan.norm, 0)) /* TODO: interlacing */ + return GST_PAD_LINK_REFUSED; + + /* set buffer info */ + if (!gst_v4lmjpegsink_set_buffer (v4lmjpegsink, + v4lmjpegsink->numbufs, v4lmjpegsink->bufsize)) + return GST_PAD_LINK_REFUSED; + if (!gst_v4lmjpegsink_playback_init (v4lmjpegsink)) + return GST_PAD_LINK_REFUSED; + + return GST_PAD_LINK_OK; + +} + + +static void +gst_v4lmjpegsink_set_clock (GstElement * element, GstClock * clock) +{ + GstV4lMjpegSink *v4mjpegsink = GST_V4LMJPEGSINK (element); + + v4mjpegsink->clock = clock; +} + + +static void +gst_v4lmjpegsink_chain (GstPad * pad, GstData * _data) +{ + GstBuffer *buf = GST_BUFFER (_data); + GstV4lMjpegSink *v4lmjpegsink; + gint num; + + g_return_if_fail (pad != NULL); + g_return_if_fail (GST_IS_PAD (pad)); + g_return_if_fail (buf != NULL); + + v4lmjpegsink = GST_V4LMJPEGSINK (gst_pad_get_parent (pad)); + + if (v4lmjpegsink->clock) { + GST_DEBUG ("videosink: clock wait: %" G_GUINT64_FORMAT, + GST_BUFFER_TIMESTAMP (buf)); + + gst_element_wait (GST_ELEMENT (v4lmjpegsink), GST_BUFFER_TIMESTAMP (buf)); + } +#if 0 + if (GST_BUFFER_POOL (buf) == v4lmjpegsink->bufferpool) { + num = GPOINTER_TO_INT (GST_BUFFER_POOL_PRIVATE (buf)); + gst_v4lmjpegsink_play_frame (v4lmjpegsink, num); + } else { +#endif + /* check size */ + if (GST_BUFFER_SIZE (buf) > v4lmjpegsink->breq.size) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, WRITE, (NULL), + ("Buffer too big (%d KB), max. buffersize is %ld KB", + GST_BUFFER_SIZE (buf) / 1024, v4lmjpegsink->breq.size / 1024)); + return; + } + + /* put JPEG data to the device */ + gst_v4lmjpegsink_wait_frame (v4lmjpegsink, &num); + memcpy (gst_v4lmjpegsink_get_buffer (v4lmjpegsink, num), + GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); + gst_v4lmjpegsink_play_frame (v4lmjpegsink, num); +#if 0 + } +#endif + + g_signal_emit (G_OBJECT (v4lmjpegsink), + gst_v4lmjpegsink_signals[SIGNAL_FRAME_DISPLAYED], 0); + + gst_buffer_unref (buf); +} + + +#if 0 +static GstBuffer * +gst_v4lmjpegsink_buffer_new (GstBufferPool * pool, + guint64 offset, guint size, gpointer user_data) +{ + GstV4lMjpegSink *v4lmjpegsink = GST_V4LMJPEGSINK (user_data); + GstBuffer *buffer = NULL; + guint8 *data; + gint num; + + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsink))) + return NULL; + if (v4lmjpegsink->breq.size < size) { + GST_DEBUG ("Requested buffer size is too large (%d > %ld)", + size, v4lmjpegsink->breq.size); + return NULL; + } + if (!gst_v4lmjpegsink_wait_frame (v4lmjpegsink, &num)) + return NULL; + data = gst_v4lmjpegsink_get_buffer (v4lmjpegsink, num); + if (!data) + return NULL; + buffer = gst_buffer_new (); + GST_BUFFER_DATA (buffer) = data; + GST_BUFFER_MAXSIZE (buffer) = v4lmjpegsink->breq.size; + GST_BUFFER_SIZE (buffer) = size; + GST_BUFFER_POOL (buffer) = pool; + GST_BUFFER_POOL_PRIVATE (buffer) = GINT_TO_POINTER (num); + + /* with this flag set, we don't need our own buffer_free() function */ + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); + + return buffer; +} +#endif + + +static void +gst_v4lmjpegsink_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstV4lMjpegSink *v4lmjpegsink; + + g_return_if_fail (GST_IS_V4LMJPEGSINK (object)); + + v4lmjpegsink = GST_V4LMJPEGSINK (object); + + switch (prop_id) { + case ARG_NUMBUFS: + v4lmjpegsink->numbufs = g_value_get_int (value); + break; + case ARG_BUFSIZE: + v4lmjpegsink->bufsize = g_value_get_int (value); + break; + case ARG_X_OFFSET: + v4lmjpegsink->x_offset = g_value_get_int (value); + break; + case ARG_Y_OFFSET: + v4lmjpegsink->y_offset = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_v4lmjpegsink_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstV4lMjpegSink *v4lmjpegsink; + + v4lmjpegsink = GST_V4LMJPEGSINK (object); + + switch (prop_id) { + case ARG_FRAMES_DISPLAYED: + g_value_set_int (value, v4lmjpegsink->frames_displayed); + break; + case ARG_FRAME_TIME: + g_value_set_int (value, v4lmjpegsink->frame_time / 1000000); + break; + case ARG_NUMBUFS: + g_value_set_int (value, v4lmjpegsink->numbufs); + break; + case ARG_BUFSIZE: + g_value_set_int (value, v4lmjpegsink->bufsize); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static GstStateChangeReturn +gst_v4lmjpegsink_change_state (GstElement * element, GstStateChange transition) +{ + GstV4lMjpegSink *v4lmjpegsink; + GstStateChangeReturn parent_value; + + g_return_val_if_fail (GST_IS_V4LMJPEGSINK (element), + GST_STATE_CHANGE_FAILURE); + v4lmjpegsink = GST_V4LMJPEGSINK (element); + + /* set up change state */ + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* we used to do buffer setup here, but that's now done + * right after capsnego */ + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + /* start */ + if (!gst_v4lmjpegsink_playback_start (v4lmjpegsink)) + return GST_STATE_CHANGE_FAILURE; + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + /* de-queue all queued buffers */ + if (!gst_v4lmjpegsink_playback_stop (v4lmjpegsink)) + return GST_STATE_CHANGE_FAILURE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* stop playback, unmap all buffers */ + if (!gst_v4lmjpegsink_playback_deinit (v4lmjpegsink)) + return GST_STATE_CHANGE_FAILURE; + break; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) { + parent_value = + GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + } else { + parent_value = GST_STATE_CHANGE_FAILURE; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return parent_value; + + return GST_STATE_CHANGE_SUCCESS; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.h new file mode 100644 index 0000000..e778f53 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsink.h @@ -0,0 +1,97 @@ +/* GStreamer + * + * gstv4lmjpegsink.h: hardware MJPEG video sink element + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4LMJPEGSINK_H__ +#define __GST_V4LMJPEGSINK_H__ + +#include +#include +#include + + +G_BEGIN_DECLS + + +#define GST_TYPE_V4LMJPEGSINK \ + (gst_v4lmjpegsink_get_type()) +#define GST_V4LMJPEGSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSink)) +#define GST_V4LMJPEGSINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSINK,GstV4lMjpegSinkClass)) +#define GST_IS_V4LMJPEGSINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSINK)) +#define GST_IS_V4LMJPEGSINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSINK)) + +typedef struct _GstV4lMjpegSink GstV4lMjpegSink; +typedef struct _GstV4lMjpegSinkClass GstV4lMjpegSinkClass; + +struct _GstV4lMjpegSink { + GstV4lElement v4lelement; + + /* the sink pas */ + GstPad *sinkpad; + + /* frame properties for common players */ + gint frames_displayed; + guint64 frame_time; + + /* system clock object */ + GstClock *clock; + + /* buffer/capture info */ + struct mjpeg_sync bsync; + struct mjpeg_requestbuffers breq; + + /* thread to keep track of synced frames */ + gint8 *isqueued_queued_frames; /* 1 = queued, 0 = unqueued, -1 = error */ + GThread *thread_queued_frames; + GMutex *mutex_queued_frames; + GCond **cond_queued_frames; + gint current_frame; + + /* width/height/norm of the jpeg stream */ + gint width; + gint height; + gint norm; + + /* cache values */ + gint x_offset; + gint y_offset; + + gint numbufs; + gint bufsize; /* in KB */ +}; + +struct _GstV4lMjpegSinkClass { + GstV4lElementClass parent_class; + + /* signals */ + void (*frame_displayed) (GstElement *element); +}; + +GType gst_v4lmjpegsink_get_type(void); + + +G_END_DECLS + +#endif /* __GST_SDLVIDEOSINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.c new file mode 100644 index 0000000..61860a1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.c @@ -0,0 +1,868 @@ +/* GStreamer + * + * gstv4lmjpegsrc.c: hardware MJPEG video source plugin + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include "v4lmjpegsrc_calls.h" + +GST_DEBUG_CATEGORY (v4lmjpegsrc_debug); +#define GST_CAT_DEFAULT v4lmjpegsrc_debug + +/* V4lMjpegSrc signals and args */ +enum +{ + SIGNAL_FRAME_CAPTURE, + SIGNAL_FRAME_DROP, + SIGNAL_FRAME_INSERT, + SIGNAL_FRAME_LOST, + LAST_SIGNAL +}; + +/* arguments */ +enum +{ + ARG_0, +#if 0 + ARG_X_OFFSET, + ARG_Y_OFFSET, + ARG_F_WIDTH, + ARG_F_HEIGHT, + /* normally, we would want to use subframe capture, however, + * for the time being it's easier if we disable it first */ +#endif + ARG_QUALITY, + ARG_NUMBUFS, + ARG_BUFSIZE, + ARG_USE_FIXED_FPS +}; + +GST_FORMATS_FUNCTION (GstPad *, gst_v4lmjpegsrc_get_formats, + GST_FORMAT_TIME, GST_FORMAT_DEFAULT); +GST_QUERY_TYPE_FUNCTION (GstPad *, gst_v4lmjpegsrc_get_query_types, + GST_QUERY_POSITION); + +/* init functions */ +static void gst_v4lmjpegsrc_base_init (gpointer g_class); +static void gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass * klass); +static void gst_v4lmjpegsrc_init (GstV4lMjpegSrc * v4lmjpegsrc); + +/* pad/info functions */ +static gboolean gst_v4lmjpegsrc_src_convert (GstPad * pad, + GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value); +static gboolean gst_v4lmjpegsrc_src_query (GstPad * pad, + GstQueryType type, GstFormat * format, gint64 * value); + +/* buffer functions */ +static GstPadLinkReturn gst_v4lmjpegsrc_srcconnect (GstPad * pad, + const GstCaps * caps); +static GstData *gst_v4lmjpegsrc_get (GstPad * pad); +static GstCaps *gst_v4lmjpegsrc_getcaps (GstPad * pad); + +/* get/set params */ +static void gst_v4lmjpegsrc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_v4lmjpegsrc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +/* set_clock function for A/V sync */ +static void gst_v4lmjpegsrc_set_clock (GstElement * element, GstClock * clock); + +/* state handling */ +static GstStateChangeReturn gst_v4lmjpegsrc_change_state (GstElement * element); + +/* requeue buffer after use */ +static void gst_v4lmjpegsrc_buffer_free (GstBuffer * buffer); + +static GstElementClass *parent_class = NULL; +static guint gst_v4lmjpegsrc_signals[LAST_SIGNAL] = { 0 }; + + +GType +gst_v4lmjpegsrc_get_type (void) +{ + static GType v4lmjpegsrc_type = 0; + + if (!v4lmjpegsrc_type) { + static const GTypeInfo v4lmjpegsrc_info = { + sizeof (GstV4lMjpegSrcClass), + gst_v4lmjpegsrc_base_init, + NULL, + (GClassInitFunc) gst_v4lmjpegsrc_class_init, + NULL, + NULL, + sizeof (GstV4lMjpegSrc), + 0, + (GInstanceInitFunc) gst_v4lmjpegsrc_init, + NULL + }; + + v4lmjpegsrc_type = + g_type_register_static (GST_TYPE_V4LELEMENT, "GstV4lMjpegSrc", + &v4lmjpegsrc_info, 0); + } + return v4lmjpegsrc_type; +} + + +static void +gst_v4lmjpegsrc_base_init (gpointer g_class) +{ + static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/jpeg, " + "width = (int) [ 0, MAX ], " + "height = (int) [ 0, MAX ], " "framerate = (fraction) [ 0, MAX ]") + ); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_sinmple (gstelement_class, + "Video (video4linux/MJPEG) Source", "Source/Video", + "Reads MJPEG-encoded frames from a zoran MJPEG/video4linux device", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&src_template)); +} + +static void +gst_v4lmjpegsrc_class_init (GstV4lMjpegSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + +#if 0 + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_X_OFFSET, + g_param_spec_int ("x-offset", "x_offset", "x_offset", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_Y_OFFSET, + g_param_spec_int ("y-offset", "y_offset", "y_offset", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_F_WIDTH, + g_param_spec_int ("frame-width", "frame_width", "frame_width", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_F_HEIGHT, + g_param_spec_int ("frame-height", "frame_height", "frame_height", + G_MININT, G_MAXINT, 0, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)); +#endif + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_QUALITY, + g_param_spec_int ("quality", "Quality", "JPEG frame quality", + 1, 100, 50, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_NUMBUFS, + g_param_spec_int ("num-buffers", "Num Buffers", "Number of Buffers", + 1, 256, 64, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_BUFSIZE, + g_param_spec_int ("buffer-size", "Buffer Size", "Size of buffers", + 0, 512 * 1024, 128 * 1024, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_USE_FIXED_FPS, + g_param_spec_boolean ("use-fixed-fps", "Use Fixed FPS", + "Drop/Insert frames to reach a certain FPS (TRUE) " + "or adapt FPS to suit the number of grabbed frames", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* signals */ + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_CAPTURE] = + g_signal_new ("frame-capture", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lMjpegSrcClass, frame_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_DROP] = + g_signal_new ("frame-drop", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstV4lMjpegSrcClass, frame_drop), NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_INSERT] = + g_signal_new ("frame-insert", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstV4lMjpegSrcClass, frame_insert), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_LOST] = + g_signal_new ("frame-lost", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstV4lMjpegSrcClass, frame_lost), NULL, NULL, + g_cclosure_marshal_VOID__INT, G_TYPE_NONE, 1, G_TYPE_INT); + + GST_DEBUG_CATEGORY_INIT (v4lmjpegsrc_debug, "v4lmjpegsrc", 0, + "V4L MJPEG source element"); + gobject_class->set_property = gst_v4lmjpegsrc_set_property; + gobject_class->get_property = gst_v4lmjpegsrc_get_property; + + gstelement_class->change_state = gst_v4lmjpegsrc_change_state; + + gstelement_class->set_clock = gst_v4lmjpegsrc_set_clock; +} + + +static void +gst_v4lmjpegsrc_init (GstV4lMjpegSrc * v4lmjpegsrc) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (v4lmjpegsrc); + + GST_OBJECT_FLAG_SET (GST_ELEMENT (v4lmjpegsrc), GST_ELEMENT_THREAD_SUGGESTED); + + v4lmjpegsrc->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "src"), "src"); + gst_element_add_pad (GST_ELEMENT (v4lmjpegsrc), v4lmjpegsrc->srcpad); + + gst_pad_set_get_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_get); + gst_pad_set_getcaps_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_getcaps); + gst_pad_set_link_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_srcconnect); + gst_pad_set_convert_function (v4lmjpegsrc->srcpad, + gst_v4lmjpegsrc_src_convert); + gst_pad_set_formats_function (v4lmjpegsrc->srcpad, + gst_v4lmjpegsrc_get_formats); + gst_pad_set_query_function (v4lmjpegsrc->srcpad, gst_v4lmjpegsrc_src_query); + gst_pad_set_query_type_function (v4lmjpegsrc->srcpad, + gst_v4lmjpegsrc_get_query_types); + +#if 0 + v4lmjpegsrc->frame_width = 0; + v4lmjpegsrc->frame_height = 0; + v4lmjpegsrc->x_offset = -1; + v4lmjpegsrc->y_offset = -1; +#endif + + v4lmjpegsrc->quality = 50; + + v4lmjpegsrc->numbufs = 64; + + /* no clock */ + v4lmjpegsrc->clock = NULL; + + /* fps */ + v4lmjpegsrc->use_fixed_fps = TRUE; + + v4lmjpegsrc->is_capturing = FALSE; +} + + +static gboolean +gst_v4lmjpegsrc_get_fps (GstV4lMjpegSrc * v4lmjpegsrc, GValue * fps) +{ + gint norm; + + g_return_val_if_fail (GST_VALUE_HOLDS_FRACTION (fps), FALSE); + + if (!v4lmjpegsrc->use_fixed_fps && + v4lmjpegsrc->clock != NULL && v4lmjpegsrc->handled > 0) { + /* try to get time from clock master and calculate fps */ + GstClockTime time = + gst_clock_get_time (v4lmjpegsrc->clock) - v4lmjpegsrc->substract_time; + return v4lmjpegsrc->handled * GST_SECOND / time; + } + + /* if that failed ... */ + + if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc))) + return FALSE; + + if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lmjpegsrc), NULL, &norm)) + return FALSE; + + if (norm == VIDEO_MODE_NTSC) + gst_value_set_fraction (fps, 30000, 1001); + else + gst_value_set_fraction (fps, 25, 1); + + return TRUE; +} + +static gboolean +gst_v4lmjpegsrc_src_convert (GstPad * pad, + GstFormat src_format, + gint64 src_value, GstFormat * dest_format, gint64 * dest_value) +{ + GstV4lMjpegSrc *v4lmjpegsrc; + GValue fps = { 0 }; + gboolean result = TRUE; + + v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad)); + + g_value_init (&fps, GST_VALUE_FRACTION); + if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps)) + return FALSE; + + switch (src_format) { + case GST_FORMAT_TIME: + switch (*dest_format) { + case GST_FORMAT_DEFAULT: + *dest_value = gst_util_uint64_scale (src_value, + gst_value_get_fraction_numerator (&fps), + gst_value_get_fraction_denominator (&fps) * GST_SECOND); + break; + default: + result = FALSE; + } + break; + + case GST_FORMAT_DEFAULT: + switch (*dest_format) { + case GST_FORMAT_TIME: + *dest_value = src_value * gst_util_uint64_scale_int (GST_SECOND, + gst_value_get_fraction_denominator (&fps), + gst_value_get_fraction_numerator (&fps)); + break; + default: + result = FALSE; + } + break; + + default: + result = FALSE; + } + + g_value_unset (&fps); + return result; +} + +static gboolean +gst_v4lmjpegsrc_src_query (GstPad * pad, + GstQueryType type, GstFormat * format, gint64 * value) +{ + GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad)); + gboolean res = TRUE; + GValue fps = { 0 }; + + g_value_init (&fps, GST_VALUE_FRACTION); + if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps)) + return FALSE; + + switch (type) { + case GST_QUERY_POSITION: + switch (*format) { + case GST_FORMAT_TIME: + *value = v4lmjpegsrc->handled * gst_util_uint64_scale_int (GST_SECOND, + gst_value_get_fraction_denominator (&fps), + gst_value_get_fraction_numerator (&fps)); + break; + case GST_FORMAT_DEFAULT: + *value = v4lmjpegsrc->handled; + break; + default: + res = FALSE; + break; + } + break; + default: + res = FALSE; + break; + } + + g_value_unset (&fps); + return res; +} + +static inline gulong +calc_bufsize (int hor_dec, int ver_dec) +{ + guint8 div = hor_dec * ver_dec; + guint32 num = (1024 * 512) / (div); + guint32 result = 2; + + num--; + while (num) { + num >>= 1; + result <<= 1; + } + + if (result > (512 * 1024)) + return (512 * 1024); + if (result < 8192) + return 8192; + return result; +} + +static GstPadLinkReturn +gst_v4lmjpegsrc_srcconnect (GstPad * pad, const GstCaps * caps) +{ + GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad)); + gint hor_dec, ver_dec; + gint w, h; + gint max_w = GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxwidth, + max_h = GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxheight; + gulong bufsize; + GstStructure *structure; + gboolean was_capturing; + + /* in case the buffers are active (which means that we already + * did capsnego before and didn't clean up), clean up anyways */ + if ((was_capturing = v4lmjpegsrc->is_capturing)) { + if (!gst_v4lmjpegsrc_capture_stop (v4lmjpegsrc)) + return GST_PAD_LINK_REFUSED; + } + if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc))) { + if (!gst_v4lmjpegsrc_capture_deinit (v4lmjpegsrc)) + return GST_PAD_LINK_REFUSED; + } else if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc))) { + return GST_PAD_LINK_DELAYED; + } + + /* Note: basically, we don't give a damn about the opposite caps here. + * that might seem odd, but it isn't. we know that the opposite caps is + * either NULL or has mime type image/jpeg, and in both cases, we'll set + * our own mime type back and it'll work. Other properties are to be set + * by the src, not by the opposite caps */ + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &w); + gst_structure_get_int (structure, "height", &h); + + /* figure out decimation */ + if (w >= max_w) { + hor_dec = 1; + } else if (w * 2 >= max_w) { + hor_dec = 2; + } else { + hor_dec = 4; + } + if (h >= max_h) { + ver_dec = 1; + } else if (h * 2 >= max_h) { + ver_dec = 2; + } else { + ver_dec = 4; + } + + /* calculate bufsize */ + bufsize = calc_bufsize (hor_dec, ver_dec); + + /* set buffer info */ + if (!gst_v4lmjpegsrc_set_buffer (v4lmjpegsrc, v4lmjpegsrc->numbufs, bufsize)) { + return GST_PAD_LINK_REFUSED; + } + + /* set capture parameters and mmap the buffers */ + if (hor_dec == ver_dec) { + if (!gst_v4lmjpegsrc_set_capture (v4lmjpegsrc, + hor_dec, v4lmjpegsrc->quality)) { + return GST_PAD_LINK_REFUSED; + } + } else { + if (!gst_v4lmjpegsrc_set_capture_m (v4lmjpegsrc, + 0, 0, max_w, max_h, hor_dec, ver_dec, v4lmjpegsrc->quality)) { + return GST_PAD_LINK_REFUSED; + } + } +#if 0 + if (!v4lmjpegsrc->frame_width && !v4lmjpegsrc->frame_height && + v4lmjpegsrc->x_offset < 0 && v4lmjpegsrc->y_offset < 0 && + v4lmjpegsrc->horizontal_decimation == v4lmjpegsrc->vertical_decimation) { + if (!gst_v4lmjpegsrc_set_capture (v4lmjpegsrc, + v4lmjpegsrc->horizontal_decimation, v4lmjpegsrc->quality)) + return GST_PAD_LINK_REFUSED; + } else { + if (!gst_v4lmjpegsrc_set_capture_m (v4lmjpegsrc, + v4lmjpegsrc->x_offset, v4lmjpegsrc->y_offset, + v4lmjpegsrc->frame_width, v4lmjpegsrc->frame_height, + v4lmjpegsrc->horizontal_decimation, + v4lmjpegsrc->vertical_decimation, v4lmjpegsrc->quality)) + return GST_PAD_LINK_REFUSED; + } +#endif + + if (!gst_v4lmjpegsrc_capture_init (v4lmjpegsrc)) + return GST_PAD_LINK_REFUSED; + + if (was_capturing || GST_STATE (v4lmjpegsrc) == GST_STATE_PLAYING) + if (!gst_v4lmjpegsrc_capture_start (v4lmjpegsrc)) + return GST_PAD_LINK_REFUSED; + + return GST_PAD_LINK_OK; +} + + +static GstData * +gst_v4lmjpegsrc_get (GstPad * pad) +{ + GstV4lMjpegSrc *v4lmjpegsrc; + GstBuffer *buf; + gint num; + GValue fps = { 0 }; + GstClockTime duration; + GstClockTime cur_frame_time; + + g_return_val_if_fail (pad != NULL, NULL); + + v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad)); + + if (v4lmjpegsrc->use_fixed_fps) { + g_value_init (&fps, GST_VALUE_FRACTION); + duration = gst_util_uint64_scale_int (GST_SECOND, + gst_value_get_fraction_denominator (&fps), + gst_value_get_fraction_numerator (&fps)); + cur_frame_time = + gst_util_uint64_scale_int (v4lmjpegsrc->handled * GST_SECOND, + gst_value_get_fraction_denominator (&fps), + gst_value_get_fraction_numerator (&fps)); + + + if (!gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps)) { + g_value_unset (&fps); + return NULL; + } + } + + if (v4lmjpegsrc->need_writes > 0) { + /* use last frame */ + num = v4lmjpegsrc->last_frame; + v4lmjpegsrc->need_writes--; + } else if (v4lmjpegsrc->clock && v4lmjpegsrc->use_fixed_fps) { + GstClockTime time; + gboolean have_frame = FALSE; + + do { + /* by default, we use the frame once */ + v4lmjpegsrc->need_writes = 1; + + /* grab a frame from the device */ + if (!gst_v4lmjpegsrc_grab_frame (v4lmjpegsrc, &num, + &v4lmjpegsrc->last_size)) + return NULL; + + v4lmjpegsrc->last_frame = num; + time = GST_TIMEVAL_TO_TIME (v4lmjpegsrc->bsync.timestamp) - + v4lmjpegsrc->substract_time; + + /* first check whether we lost any frames according to the device */ + if (v4lmjpegsrc->last_seq != 0) { + if (v4lmjpegsrc->bsync.seq - v4lmjpegsrc->last_seq > 1) { + v4lmjpegsrc->need_writes = + v4lmjpegsrc->bsync.seq - v4lmjpegsrc->last_seq; + g_signal_emit (G_OBJECT (v4lmjpegsrc), + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_LOST], 0, + v4lmjpegsrc->bsync.seq - v4lmjpegsrc->last_seq - 1); + } + } + v4lmjpegsrc->last_seq = v4lmjpegsrc->bsync.seq; + + /* decide how often we're going to write the frame - set + * v4lmjpegsrc->need_writes to (that-1) and have_frame to TRUE + * if we're going to write it - else, just continue. + * + * time is generally the system or audio clock. Let's + * say that we've written one second of audio, then we want + * to have written one second of video too, within the same + * timeframe. This means that if time - begin_time = X sec, + * we want to have written X*fps frames. If we've written + * more - drop, if we've written less - dup... */ + if (cur_frame_time - time > 1.5 * duration) { + /* yo dude, we've got too many frames here! Drop! DROP! */ + v4lmjpegsrc->need_writes--; /* -= (v4lmjpegsrc->handled - (time / fps)); */ + g_signal_emit (G_OBJECT (v4lmjpegsrc), + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_DROP], 0); + } else if (cur_frame_time - time < -1.5 * duration) { + /* this means we're lagging far behind */ + v4lmjpegsrc->need_writes++; /* += ((time / fps) - v4lmjpegsrc->handled); */ + g_signal_emit (G_OBJECT (v4lmjpegsrc), + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_INSERT], 0); + } + + if (v4lmjpegsrc->need_writes > 0) { + have_frame = TRUE; + v4lmjpegsrc->use_num_times[num] = v4lmjpegsrc->need_writes; + v4lmjpegsrc->need_writes--; + } else { + gst_v4lmjpegsrc_requeue_frame (v4lmjpegsrc, num); + } + } while (!have_frame); + } else { + /* grab a frame from the device */ + if (!gst_v4lmjpegsrc_grab_frame (v4lmjpegsrc, &num, + &v4lmjpegsrc->last_size)) + return NULL; + + v4lmjpegsrc->use_num_times[num] = 1; + } + + buf = gst_buffer_new (); + GST_BUFFER_FREE_DATA_FUNC (buf) = gst_v4lmjpegsrc_buffer_free; + GST_BUFFER_PRIVATE (buf) = v4lmjpegsrc; + GST_BUFFER_DATA (buf) = gst_v4lmjpegsrc_get_buffer (v4lmjpegsrc, num); + GST_BUFFER_SIZE (buf) = v4lmjpegsrc->last_size; + GST_BUFFER_MAXSIZE (buf) = v4lmjpegsrc->breq.size; + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_READONLY); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_DONTFREE); + if (v4lmjpegsrc->use_fixed_fps) + GST_BUFFER_TIMESTAMP (buf) = cur_frame_time; + else /* calculate time based on our own clock */ + GST_BUFFER_TIMESTAMP (buf) = + GST_TIMEVAL_TO_TIME (v4lmjpegsrc->bsync.timestamp) - + v4lmjpegsrc->substract_time; + + v4lmjpegsrc->handled++; + g_signal_emit (G_OBJECT (v4lmjpegsrc), + gst_v4lmjpegsrc_signals[SIGNAL_FRAME_CAPTURE], 0); + + return GST_DATA (buf); +} + + +static GstCaps * +gst_v4lmjpegsrc_getcaps (GstPad * pad) +{ + GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (gst_pad_get_parent (pad)); + struct video_capability *vcap = &GST_V4LELEMENT (v4lmjpegsrc)->vcap; + GstCaps *caps; + GstStructure *str; + gint i; + GValue w = { 0 }, h = { + 0}, w1 = { + 0}, h1 = { + 0}, fps = { + 0}; + + if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc))) { + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + g_value_init (&fps, GST_TYPE_FRACTION); + gst_return_val_if_fail (gst_v4lmjpegsrc_get_fps (v4lmjpegsrc, &fps), NULL); + + caps = gst_caps_new_simple ("image/jpeg", NULL); + str = gst_caps_get_structure (caps, 0); + gst_structure_set_value (str, "framerate", &fps); + g_value_unset (&fps); + + g_value_init (&w, GST_TYPE_LIST); + g_value_init (&h, GST_TYPE_LIST); + g_value_init (&w1, G_TYPE_INT); + g_value_init (&h1, G_TYPE_INT); + for (i = 0; i <= 2; i++) { + g_value_set_int (&w1, vcap->maxwidth / (1 << i)); + g_value_set_int (&h1, vcap->maxheight / (1 << i)); + gst_value_list_append_value (&w, &w1); + gst_value_list_append_value (&h, &h1); + } + g_value_unset (&h1); + g_value_unset (&w1); + gst_structure_set_value (str, "width", &w); + gst_structure_set_value (str, "height", &h); + g_value_unset (&w); + g_value_unset (&h); + + return caps; +} + + +static void +gst_v4lmjpegsrc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstV4lMjpegSrc *v4lmjpegsrc; + + g_return_if_fail (GST_IS_V4LMJPEGSRC (object)); + v4lmjpegsrc = GST_V4LMJPEGSRC (object); + + switch (prop_id) { +#if 0 + case ARG_X_OFFSET: + v4lmjpegsrc->x_offset = g_value_get_int (value); + break; + case ARG_Y_OFFSET: + v4lmjpegsrc->y_offset = g_value_get_int (value); + break; + case ARG_F_WIDTH: + v4lmjpegsrc->frame_width = g_value_get_int (value); + break; + case ARG_F_HEIGHT: + v4lmjpegsrc->frame_height = g_value_get_int (value); + break; +#endif + case ARG_QUALITY: + v4lmjpegsrc->quality = g_value_get_int (value); + break; + case ARG_NUMBUFS: + v4lmjpegsrc->numbufs = g_value_get_int (value); + break; + case ARG_USE_FIXED_FPS: + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc))) { + v4lmjpegsrc->use_fixed_fps = g_value_get_boolean (value); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_v4lmjpegsrc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstV4lMjpegSrc *v4lmjpegsrc; + + g_return_if_fail (GST_IS_V4LMJPEGSRC (object)); + v4lmjpegsrc = GST_V4LMJPEGSRC (object); + + switch (prop_id) { +#if 0 + case ARG_X_OFFSET: + g_value_set_int (value, v4lmjpegsrc->x_offset); + break; + case ARG_Y_OFFSET: + g_value_set_int (value, v4lmjpegsrc->y_offset); + break; + case ARG_F_WIDTH: + g_value_set_int (value, v4lmjpegsrc->frame_width); + break; + case ARG_F_HEIGHT: + g_value_set_int (value, v4lmjpegsrc->frame_height); + break; +#endif + case ARG_QUALITY: + g_value_set_int (value, v4lmjpegsrc->quality); + break; + case ARG_NUMBUFS: + if (GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc))) + g_value_set_int (value, v4lmjpegsrc->breq.count); + else + g_value_set_int (value, v4lmjpegsrc->numbufs); + break; + case ARG_BUFSIZE: + g_value_set_int (value, v4lmjpegsrc->breq.size); + break; + case ARG_USE_FIXED_FPS: + g_value_set_boolean (value, v4lmjpegsrc->use_fixed_fps); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static GstStateChangeReturn +gst_v4lmjpegsrc_change_state (GstElement * element, GstStateChange transition) +{ + GstV4lMjpegSrc *v4lmjpegsrc; + GTimeVal time; + + g_return_val_if_fail (GST_IS_V4LMJPEGSRC (element), GST_STATE_CHANGE_FAILURE); + + v4lmjpegsrc = GST_V4LMJPEGSRC (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* actual buffer set-up used to be done here - but I moved + * it to capsnego itself */ + v4lmjpegsrc->handled = 0; + v4lmjpegsrc->need_writes = 0; + v4lmjpegsrc->last_frame = 0; + v4lmjpegsrc->substract_time = 0; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + /* queue all buffer, start streaming capture */ + if (GST_V4LELEMENT (v4lmjpegsrc)->buffer && + !gst_v4lmjpegsrc_capture_start (v4lmjpegsrc)) + return GST_STATE_CHANGE_FAILURE; + g_get_current_time (&time); + v4lmjpegsrc->substract_time = GST_TIMEVAL_TO_TIME (time) - + v4lmjpegsrc->substract_time; + v4lmjpegsrc->last_seq = 0; + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + g_get_current_time (&time); + v4lmjpegsrc->substract_time = GST_TIMEVAL_TO_TIME (time) - + v4lmjpegsrc->substract_time; + /* de-queue all queued buffers */ + if (v4lmjpegsrc->is_capturing && + !gst_v4lmjpegsrc_capture_stop (v4lmjpegsrc)) + return GST_STATE_CHANGE_FAILURE; + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* stop capturing, unmap all buffers */ + if (GST_V4LELEMENT (v4lmjpegsrc)->buffer && + !gst_v4lmjpegsrc_capture_deinit (v4lmjpegsrc)) + return GST_STATE_CHANGE_FAILURE; + break; + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + return GST_STATE_CHANGE_SUCCESS; +} + + +static void +gst_v4lmjpegsrc_set_clock (GstElement * element, GstClock * clock) +{ + GST_V4LMJPEGSRC (element)->clock = clock; +} + + +#if 0 +static GstBuffer * +gst_v4lmjpegsrc_buffer_new (GstBufferPool * pool, + guint64 offset, guint size, gpointer user_data) +{ + GstBuffer *buffer; + GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (user_data); + + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc))) + return NULL; + + buffer = gst_buffer_new (); + if (!buffer) + return NULL; + + /* TODO: add interlacing info to buffer as metadata */ + GST_BUFFER_MAXSIZE (buffer) = v4lmjpegsrc->breq.size; + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); + + return buffer; +} +#endif + +static void +gst_v4lmjpegsrc_buffer_free (GstBuffer * buf) +{ + GstV4lMjpegSrc *v4lmjpegsrc = GST_V4LMJPEGSRC (GST_BUFFER_PRIVATE (buf)); + int n; + + if (gst_element_get_state (GST_ELEMENT (v4lmjpegsrc)) != GST_STATE_PLAYING) + return; /* we've already cleaned up ourselves */ + + for (n = 0; n < v4lmjpegsrc->breq.count; n++) + if (GST_BUFFER_DATA (buf) == gst_v4lmjpegsrc_get_buffer (v4lmjpegsrc, n)) { + v4lmjpegsrc->use_num_times[n]--; + if (v4lmjpegsrc->use_num_times[n] <= 0) { + gst_v4lmjpegsrc_requeue_frame (v4lmjpegsrc, n); + } + break; + } + + if (n == v4lmjpegsrc->breq.count) + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, (NULL), + ("Couldn't find the buffer")); +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.h new file mode 100644 index 0000000..2e76906 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lmjpegsrc.h @@ -0,0 +1,116 @@ +/* GStreamer + * + * gstv4lmjpegsrc.h: hardware MJPEG video source element + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4LMJPEGSRC_H__ +#define __GST_V4LMJPEGSRC_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_V4LMJPEGSRC \ + (gst_v4lmjpegsrc_get_type()) +#define GST_V4LMJPEGSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrc)) +#define GST_V4LMJPEGSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LMJPEGSRC,GstV4lMjpegSrcClass)) +#define GST_IS_V4LMJPEGSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LMJPEGSRC)) +#define GST_IS_V4LMJPEGSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LMJPEGSRC)) + +typedef struct _GstV4lMjpegSrc GstV4lMjpegSrc; +typedef struct _GstV4lMjpegSrcClass GstV4lMjpegSrcClass; + +struct _GstV4lMjpegSrc { + GstV4lElement v4lelement; + + /* pads */ + GstPad *srcpad; + + /* buffer/capture info */ + struct mjpeg_sync bsync; + struct mjpeg_requestbuffers breq; + + /* num of queued frames and some GThread stuff + * to wait if there's not enough */ + gint8 *frame_queue_state; + GMutex *mutex_queue_state; + GCond *cond_queue_state; + gint num_queued; + gint queue_frame; + + /* True if we want to stop */ + gboolean quit, is_capturing; + + /* A/V sync... frame counter and internal cache */ + gulong handled; + gint last_frame; + gint last_size; + gint need_writes; + gulong last_seq; + + /* clock */ + GstClock *clock; + + /* time to substract from clock time to get back to timestamp */ + GstClockTime substract_time; + + /* how often are we going to use each frame? */ + gint *use_num_times; + + /* how are we going to push buffers? */ + gboolean use_fixed_fps; + + /* end size */ + gint end_width, end_height; + + /* caching values */ +#if 0 + gint x_offset; + gint y_offset; + gint frame_width; + gint frame_height; +#endif + + gint quality; + gint numbufs; +}; + +struct _GstV4lMjpegSrcClass { + GstV4lElementClass parent_class; + + void (*frame_capture) (GObject *object); + void (*frame_drop) (GObject *object); + void (*frame_insert) (GObject *object); + void (*frame_lost) (GObject *object, + gint num_lost); +}; + +GType gst_v4lmjpegsrc_get_type(void); + + +G_END_DECLS + +#endif /* __GST_V4LMJPEGSRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.c new file mode 100644 index 0000000..c0b5f78 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.c @@ -0,0 +1,727 @@ +/* GStreamer + * + * gstv4lsrc.c: BT8x8/V4L source element + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include "v4lsrc_calls.h" +#include + + +GST_DEBUG_CATEGORY_STATIC (v4lsrc_debug); +#define GST_CAT_DEFAULT v4lsrc_debug + + +enum +{ + PROP_0, + PROP_AUTOPROBE, + PROP_AUTOPROBE_FPS, + PROP_COPY_MODE, + PROP_TIMESTAMP_OFFSET +}; + + +GST_BOILERPLATE (GstV4lSrc, gst_v4lsrc, GstV4lElement, GST_TYPE_V4LELEMENT); + +static GstStaticPadTemplate v4l_src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +/* basesrc methods */ +static gboolean gst_v4lsrc_start (GstBaseSrc * src); +static gboolean gst_v4lsrc_stop (GstBaseSrc * src); +static gboolean gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps); +static GstCaps *gst_v4lsrc_get_caps (GstBaseSrc * src); +static GstFlowReturn gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** out); +static gboolean gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query); +static void gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps); + +static void gst_v4lsrc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_v4lsrc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + + +static void +gst_v4lsrc_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "Video (video4linux/raw) Source", "Source/Video", + "Reads raw frames from a video4linux device", + "GStreamer maintainers "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&v4l_src_template)); +} + +static void +gst_v4lsrc_class_init (GstV4lSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseSrcClass *basesrc_class; + GstPushSrcClass *pushsrc_class; + + gobject_class = (GObjectClass *) klass; + basesrc_class = (GstBaseSrcClass *) klass; + pushsrc_class = (GstPushSrcClass *) klass; + + gobject_class->set_property = gst_v4lsrc_set_property; + gobject_class->get_property = gst_v4lsrc_get_property; + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE, + g_param_spec_boolean ("autoprobe", "Autoprobe", + "Whether the device should be probed for all possible features", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_AUTOPROBE_FPS, + g_param_spec_boolean ("autoprobe-fps", "Autoprobe FPS", + "Whether the device should be probed for framerates", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_COPY_MODE, + g_param_spec_boolean ("copy-mode", "Copy mode", + "Whether to send out copies of buffers, or direct pointers to the mmap region", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), + PROP_TIMESTAMP_OFFSET, g_param_spec_int64 ("timestamp-offset", + "Timestamp offset", + "A time offset subtracted from timestamps set on buffers (in ns)", + G_MININT64, G_MAXINT64, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + GST_DEBUG_CATEGORY_INIT (v4lsrc_debug, "v4lsrc", 0, "V4L source element"); + + basesrc_class->get_caps = gst_v4lsrc_get_caps; + basesrc_class->set_caps = gst_v4lsrc_set_caps; + basesrc_class->start = gst_v4lsrc_start; + basesrc_class->stop = gst_v4lsrc_stop; + basesrc_class->fixate = gst_v4lsrc_fixate; + basesrc_class->query = gst_v4lsrc_query; + + pushsrc_class->create = gst_v4lsrc_create; +} + +static void +gst_v4lsrc_init (GstV4lSrc * v4lsrc, GstV4lSrcClass * klass) +{ + v4lsrc->buffer_size = 0; + + /* no colorspaces */ + v4lsrc->colorspaces = NULL; + + v4lsrc->is_capturing = FALSE; + v4lsrc->autoprobe = TRUE; + v4lsrc->autoprobe_fps = TRUE; + v4lsrc->copy_mode = TRUE; + + v4lsrc->timestamp_offset = 0; + + v4lsrc->fps_list = NULL; + + gst_base_src_set_format (GST_BASE_SRC (v4lsrc), GST_FORMAT_TIME); + gst_base_src_set_live (GST_BASE_SRC (v4lsrc), TRUE); +} + +static void +gst_v4lsrc_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstV4lSrc *v4lsrc = GST_V4LSRC (object); + + switch (prop_id) { + case PROP_AUTOPROBE: + g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))); + v4lsrc->autoprobe = g_value_get_boolean (value); + break; + case PROP_AUTOPROBE_FPS: + g_return_if_fail (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc))); + v4lsrc->autoprobe_fps = g_value_get_boolean (value); + break; + case PROP_COPY_MODE: + v4lsrc->copy_mode = g_value_get_boolean (value); + break; + case PROP_TIMESTAMP_OFFSET: + v4lsrc->timestamp_offset = g_value_get_int64 (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + + +static void +gst_v4lsrc_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstV4lSrc *v4lsrc = GST_V4LSRC (object); + + switch (prop_id) { + case PROP_AUTOPROBE: + g_value_set_boolean (value, v4lsrc->autoprobe); + break; + case PROP_AUTOPROBE_FPS: + g_value_set_boolean (value, v4lsrc->autoprobe_fps); + break; + case PROP_COPY_MODE: + g_value_set_boolean (value, v4lsrc->copy_mode); + break; + case PROP_TIMESTAMP_OFFSET: + g_value_set_int64 (value, v4lsrc->timestamp_offset); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* this function is a bit of a last resort */ +static void +gst_v4lsrc_fixate (GstBaseSrc * bsrc, GstCaps * caps) +{ + GstStructure *structure; + int i; + int targetwidth, targetheight; + GstV4lSrc *v4lsrc = GST_V4LSRC (bsrc); + struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap; + struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin; + + if (GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { + GST_DEBUG_OBJECT (v4lsrc, "device reported w: %d-%d, h: %d-%d", + vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight); + targetwidth = vcap->minwidth; + targetheight = vcap->minheight; + /* if we can get the current vwin settings, we use those to fixate */ + if (!gst_v4l_get_capabilities (GST_V4LELEMENT (v4lsrc))) + GST_DEBUG_OBJECT (v4lsrc, "failed getting capabilities"); + else { + targetwidth = vwin->width; + targetheight = vwin->height; + } + } else { + GST_DEBUG_OBJECT (v4lsrc, "device closed, guessing"); + targetwidth = 320; + targetheight = 200; + } + + GST_DEBUG_OBJECT (v4lsrc, "targetting %dx%d", targetwidth, targetheight); + + for (i = 0; i < gst_caps_get_size (caps); ++i) { + const GValue *v; + + structure = gst_caps_get_structure (caps, i); + gst_structure_fixate_field_nearest_int (structure, "width", targetwidth); + gst_structure_fixate_field_nearest_int (structure, "height", targetheight); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", 15, 2); + + v = gst_structure_get_value (structure, "format"); + if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) { + guint32 fourcc; + + g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST); + + fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0)); + gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL); + } + } +} + +static gint all_palettes[] = { + VIDEO_PALETTE_YUV422, + VIDEO_PALETTE_YUV420P, + VIDEO_PALETTE_UYVY, + VIDEO_PALETTE_YUV411P, + VIDEO_PALETTE_YUV422P, + VIDEO_PALETTE_YUV410P, + VIDEO_PALETTE_YUV411, + VIDEO_PALETTE_RGB555, + VIDEO_PALETTE_RGB565, + VIDEO_PALETTE_RGB24, + VIDEO_PALETTE_RGB32, + -1 +}; + +static GstCaps * +gst_v4lsrc_palette_to_caps (int palette) +{ + guint32 fourcc; + GstCaps *caps; + + switch (palette) { + case VIDEO_PALETTE_YUV422: + case VIDEO_PALETTE_YUYV: + fourcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'); + break; + case VIDEO_PALETTE_YUV420P: + fourcc = GST_MAKE_FOURCC ('I', '4', '2', '0'); + break; + case VIDEO_PALETTE_UYVY: + fourcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'); + break; + case VIDEO_PALETTE_YUV411P: + fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B'); + break; + case VIDEO_PALETTE_YUV411: + fourcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P'); + break; + case VIDEO_PALETTE_YUV422P: + fourcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B'); + break; + case VIDEO_PALETTE_YUV410P: + fourcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9'); + break; + case VIDEO_PALETTE_RGB555: + case VIDEO_PALETTE_RGB565: + case VIDEO_PALETTE_RGB24: + case VIDEO_PALETTE_RGB32: + fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' '); + break; + default: + return NULL; + } + + if (fourcc == GST_MAKE_FOURCC ('R', 'G', 'B', ' ')) { + switch (palette) { + case VIDEO_PALETTE_RGB555: + caps = gst_caps_from_string ("video/x-raw-rgb, " + "bpp = (int) 16, " + "depth = (int) 15, " + "endianness = (int) BYTE_ORDER, " + "red_mask = 0x7c00, " "green_mask = 0x03e0, " "blue_mask = 0x001f"); + break; + case VIDEO_PALETTE_RGB565: + caps = gst_caps_from_string ("video/x-raw-rgb, " + "bpp = (int) 16, " + "depth = (int) 16, " + "endianness = (int) BYTE_ORDER, " + "red_mask = 0xf800, " "green_mask = 0x07f0, " "blue_mask = 0x001f"); + break; + case VIDEO_PALETTE_RGB24: + caps = gst_caps_from_string ("video/x-raw-rgb, " + "bpp = (int) 24, " + "depth = (int) 24, " + "endianness = (int) BIG_ENDIAN, " + "red_mask = 0xFF0000, " + "green_mask = 0x00FF00, " "blue_mask = 0x0000FF"); + break; + case VIDEO_PALETTE_RGB32: + caps = gst_caps_from_string ("video/x-raw-rgb, " + "bpp = (int) 32, " + "depth = (int) 24, " + "endianness = (int) BIG_ENDIAN, " + "red_mask = 0xFF000000, " + "green_mask = 0x00FF0000, " "blue_mask = 0x0000FF00"); + break; + default: + g_assert_not_reached (); + return NULL; + } + } else { + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, fourcc, NULL); + } + + return caps; +} + +static GstCaps * +gst_v4lsrc_get_any_caps (void) +{ + gint i; + GstCaps *caps = gst_caps_new_empty (), *one; + + for (i = 0; all_palettes[i] != -1; i++) { + one = gst_v4lsrc_palette_to_caps (all_palettes[i]); + gst_caps_append (caps, one); + } + + return caps; +} + +static GstCaps * +gst_v4lsrc_get_caps (GstBaseSrc * src) +{ + GstCaps *list; + GstV4lSrc *v4lsrc = GST_V4LSRC (src); + struct video_capability *vcap = &GST_V4LELEMENT (v4lsrc)->vcap; + gint width = GST_V4LELEMENT (src)->vcap.minwidth; + gint height = GST_V4LELEMENT (src)->vcap.minheight; + gint i; + gint fps_n, fps_d; + GList *item; + + if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) { + return gst_v4lsrc_get_any_caps (); + } + + if (!v4lsrc->autoprobe) { + /* FIXME: query current caps and return those, with _any appended */ + return gst_v4lsrc_get_any_caps (); + } + + if (!v4lsrc->colorspaces) { + GST_DEBUG_OBJECT (v4lsrc, "Checking supported palettes"); + for (i = 0; all_palettes[i] != -1; i++) { + /* try palette out */ + if (!gst_v4lsrc_try_capture (v4lsrc, width, height, all_palettes[i])) + continue; + GST_DEBUG_OBJECT (v4lsrc, "Added palette %d (%s) to supported list", + all_palettes[i], gst_v4lsrc_palette_name (all_palettes[i])); + v4lsrc->colorspaces = g_list_append (v4lsrc->colorspaces, + GINT_TO_POINTER (all_palettes[i])); + } + GST_DEBUG_OBJECT (v4lsrc, "%d palette(s) supported", + g_list_length (v4lsrc->colorspaces)); + if (v4lsrc->autoprobe_fps) { + GST_DEBUG_OBJECT (v4lsrc, "autoprobing framerates"); + v4lsrc->fps_list = gst_v4lsrc_get_fps_list (v4lsrc); + } + } + + + if (!gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d)) { + fps_n = 0; + fps_d = 1; + } + + list = gst_caps_new_empty (); + for (item = v4lsrc->colorspaces; item != NULL; item = item->next) { + GstCaps *one; + + one = gst_v4lsrc_palette_to_caps (GPOINTER_TO_INT (item->data)); + if (!one) { + GST_WARNING_OBJECT (v4lsrc, "Palette %d gave no caps\n", + GPOINTER_TO_INT (item->data)); + continue; + } + + GST_DEBUG_OBJECT (v4lsrc, + "Device reports w: %d-%d, h: %d-%d, fps: %d/%d for palette %d", + vcap->minwidth, vcap->maxwidth, vcap->minheight, vcap->maxheight, + fps_n, fps_d, GPOINTER_TO_INT (item->data)); + + if (vcap->minwidth < vcap->maxwidth) { + gst_caps_set_simple (one, "width", GST_TYPE_INT_RANGE, vcap->minwidth, + vcap->maxwidth, NULL); + } else { + gst_caps_set_simple (one, "width", G_TYPE_INT, vcap->minwidth, NULL); + } + if (vcap->minheight < vcap->maxheight) { + gst_caps_set_simple (one, "height", GST_TYPE_INT_RANGE, vcap->minheight, + vcap->maxheight, NULL); + } else { + gst_caps_set_simple (one, "height", G_TYPE_INT, vcap->minheight, NULL); + } + + if (v4lsrc->autoprobe_fps) { + GstStructure *structure = gst_caps_get_structure (one, 0); + + if (v4lsrc->fps_list) { + gst_structure_set_value (structure, "framerate", v4lsrc->fps_list); + } else { + gst_structure_set (structure, "framerate", GST_TYPE_FRACTION, + fps_n, fps_d, NULL); + } + } else { + gst_caps_set_simple (one, "framerate", GST_TYPE_FRACTION_RANGE, + 1, 1, 100, 1, NULL); + } + + GST_DEBUG_OBJECT (v4lsrc, "caps: %" GST_PTR_FORMAT, one); + gst_caps_append (list, one); + } + + return list; +} + +static gboolean +gst_v4lsrc_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstV4lSrc *v4lsrc; + guint32 fourcc; + gint bpp, depth, w, h, palette = -1; + const GValue *new_fps; + gint cur_fps_n, cur_fps_d; + GstStructure *structure; + struct video_window *vwin; + + v4lsrc = GST_V4LSRC (src); + vwin = &GST_V4LELEMENT (v4lsrc)->vwin; + + /* if we're not open, punt -- we'll get setcaps'd later via negotiate */ + if (!GST_V4L_IS_OPEN (v4lsrc)) + return FALSE; + + /* make sure we stop capturing and dealloc buffers */ + if (GST_V4L_IS_ACTIVE (v4lsrc)) { + if (!gst_v4lsrc_capture_stop (v4lsrc)) + return FALSE; + if (!gst_v4lsrc_capture_deinit (v4lsrc)) + return FALSE; + } + + /* it's fixed, one struct */ + structure = gst_caps_get_structure (caps, 0); + + if (strcmp (gst_structure_get_name (structure), "video/x-raw-yuv") == 0) + gst_structure_get_fourcc (structure, "format", &fourcc); + else + fourcc = GST_MAKE_FOURCC ('R', 'G', 'B', ' '); + + gst_structure_get_int (structure, "width", &w); + gst_structure_get_int (structure, "height", &h); + new_fps = gst_structure_get_value (structure, "framerate"); + + /* set framerate if it's not already correct */ + if (!gst_v4lsrc_get_fps (v4lsrc, &cur_fps_n, &cur_fps_d)) + return FALSE; + + if (new_fps) { + GST_DEBUG_OBJECT (v4lsrc, "linking with %dx%d at %d/%d fps", w, h, + gst_value_get_fraction_numerator (new_fps), + gst_value_get_fraction_denominator (new_fps)); + + if (gst_value_get_fraction_numerator (new_fps) != cur_fps_n || + gst_value_get_fraction_denominator (new_fps) != cur_fps_d) { + int fps_index = (gst_value_get_fraction_numerator (new_fps) * 16) / + (gst_value_get_fraction_denominator (new_fps) * 15); + + GST_DEBUG_OBJECT (v4lsrc, "Trying to set fps index %d", fps_index); + /* set bits 16 to 21 to 0 */ + vwin->flags &= (0x3F00 - 1); + /* set bits 16 to 21 to the index */ + vwin->flags |= fps_index << 16; + if (!gst_v4l_set_window_properties (GST_V4LELEMENT (v4lsrc))) { + return FALSE; + } + } + } + + switch (fourcc) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + palette = VIDEO_PALETTE_YUV420P; + v4lsrc->buffer_size = ((w + 1) & ~1) * ((h + 1) & ~1) * 1.5; + break; + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + palette = VIDEO_PALETTE_YUV422; + v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; + break; + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + palette = VIDEO_PALETTE_UYVY; + v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'B'): + palette = VIDEO_PALETTE_YUV411P; + v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5; + break; + case GST_MAKE_FOURCC ('Y', '4', '1', 'P'): + palette = VIDEO_PALETTE_YUV411; + v4lsrc->buffer_size = ((w + 3) & ~3) * h * 1.5; + break; + case GST_MAKE_FOURCC ('Y', 'U', 'V', '9'): + palette = VIDEO_PALETTE_YUV410P; + v4lsrc->buffer_size = ((w + 3) & ~3) * ((h + 3) & ~3) * 1.125; + break; + case GST_MAKE_FOURCC ('Y', '4', '2', 'B'): + palette = VIDEO_PALETTE_YUV422P; + v4lsrc->buffer_size = ((w + 1) & ~1) * h * 2; + break; + case GST_MAKE_FOURCC ('R', 'G', 'B', ' '): + gst_structure_get_int (structure, "depth", &depth); + switch (depth) { + case 15: + palette = VIDEO_PALETTE_RGB555; + v4lsrc->buffer_size = w * h * 2; + break; + case 16: + palette = VIDEO_PALETTE_RGB565; + v4lsrc->buffer_size = w * h * 2; + break; + case 24: + gst_structure_get_int (structure, "bpp", &bpp); + switch (bpp) { + case 24: + palette = VIDEO_PALETTE_RGB24; + v4lsrc->buffer_size = w * h * 3; + break; + case 32: + palette = VIDEO_PALETTE_RGB32; + v4lsrc->buffer_size = w * h * 4; + break; + default: + break; + } + break; + default: + break; + } + break; + default: + break; + } + + if (palette == -1) { + GST_WARNING_OBJECT (v4lsrc, "palette for fourcc %" GST_FOURCC_FORMAT + " is -1, refusing link", GST_FOURCC_ARGS (fourcc)); + return FALSE; + } + + GST_DEBUG_OBJECT (v4lsrc, "trying to set_capture %dx%d, palette %d", + w, h, palette); + /* this only fills in v4lsrc->mmap values */ + if (!gst_v4lsrc_set_capture (v4lsrc, w, h, palette)) { + GST_WARNING_OBJECT (v4lsrc, "could not set_capture %dx%d, palette %d", + w, h, palette); + return FALSE; + } + + /* first try the negotiated settings using try_capture */ + if (!gst_v4lsrc_try_capture (v4lsrc, w, h, palette)) { + GST_DEBUG_OBJECT (v4lsrc, "failed trying palette %d for %dx%d", palette, + w, h); + return FALSE; + } + + if (!gst_v4lsrc_capture_init (v4lsrc)) + return FALSE; + + if (!gst_v4lsrc_capture_start (v4lsrc)) + return FALSE; + + return TRUE; +} + +static gboolean +gst_v4lsrc_query (GstBaseSrc * bsrc, GstQuery * query) +{ + GstV4lSrc *v4lsrc; + gboolean res = FALSE; + + v4lsrc = GST_V4LSRC (bsrc); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GstClockTime min_latency, max_latency; + gint fps_n, fps_d; + + /* device must be open */ + if (!GST_V4L_IS_OPEN (v4lsrc)) + goto done; + + /* we must have a framerate */ + if (!(res = gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d))) + goto done; + + /* min latency is the time to capture one frame */ + min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n); + + /* max latency is total duration of the frame buffer */ + max_latency = v4lsrc->mbuf.frames * min_latency; + + GST_DEBUG_OBJECT (bsrc, + "report latency min %" GST_TIME_FORMAT " max %" GST_TIME_FORMAT, + GST_TIME_ARGS (min_latency), GST_TIME_ARGS (max_latency)); + + /* we are always live, the min latency is 1 frame and the max latency is + * the complete buffer of frames. */ + gst_query_set_latency (query, TRUE, min_latency, max_latency); + + res = TRUE; + break; + } + default: + res = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query); + break; + } +done: + return res; +} + +/* start and stop are not symmetric -- start will open the device, but not start + capture. it's setcaps that will start capture, which is called via basesrc's + negotiate method. stop will both stop capture and close the device. + */ +static gboolean +gst_v4lsrc_start (GstBaseSrc * src) +{ + GstV4lSrc *v4lsrc = GST_V4LSRC (src); + + v4lsrc->offset = 0; + + return TRUE; +} + +static gboolean +gst_v4lsrc_stop (GstBaseSrc * src) +{ + GstV4lSrc *v4lsrc = GST_V4LSRC (src); + + if (GST_V4L_IS_ACTIVE (v4lsrc) && !gst_v4lsrc_capture_stop (v4lsrc)) + return FALSE; + + if (GST_V4LELEMENT (v4lsrc)->buffer != NULL) { + if (!gst_v4lsrc_capture_deinit (v4lsrc)) + return FALSE; + } + + g_list_free (v4lsrc->colorspaces); + v4lsrc->colorspaces = NULL; + + if (v4lsrc->fps_list) { + g_value_unset (v4lsrc->fps_list); + g_free (v4lsrc->fps_list); + v4lsrc->fps_list = NULL; + } + + return TRUE; +} + +static GstFlowReturn +gst_v4lsrc_create (GstPushSrc * src, GstBuffer ** buf) +{ + GstV4lSrc *v4lsrc; + gint num; + + v4lsrc = GST_V4LSRC (src); + + /* grab a frame from the device */ + if (!gst_v4lsrc_grab_frame (v4lsrc, &num)) + return GST_FLOW_ERROR; + + *buf = gst_v4lsrc_buffer_new (v4lsrc, num); + + if (v4lsrc->copy_mode) { + GstBuffer *copy = gst_buffer_copy (*buf); + + gst_buffer_unref (*buf); + *buf = copy; + } + + return GST_FLOW_OK; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.h new file mode 100644 index 0000000..fbed86a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lsrc.h @@ -0,0 +1,108 @@ +/* GStreamer + * + * gstv4lsrc.h: BT8x8/V4L video source element + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4LSRC_H__ +#define __GST_V4LSRC_H__ + + +#include + + +G_BEGIN_DECLS + + +#define GST_TYPE_V4LSRC \ + (gst_v4lsrc_get_type()) +#define GST_V4LSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4LSRC,GstV4lSrc)) +#define GST_V4LSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4LSRC,GstV4lSrcClass)) +#define GST_IS_V4LSRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4LSRC)) +#define GST_IS_V4LSRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4LSRC)) + + +typedef struct _GstV4lSrc GstV4lSrc; +typedef struct _GstV4lSrcClass GstV4lSrcClass; + + +enum +{ + QUEUE_STATE_ERROR = -1, + QUEUE_STATE_READY_FOR_QUEUE, /* the frame is ready to be queued for capture */ + QUEUE_STATE_QUEUED, /* the frame is queued for capture */ + QUEUE_STATE_SYNCED /* the frame is captured */ +}; + + +struct _GstV4lSrc +{ + GstV4lElement v4lelement; + + /* pads */ + GstPad *srcpad; + + /* capture/buffer info */ + struct video_mmap mmap; + struct video_mbuf mbuf; + guint buffer_size; + GstClockTime timestamp_sync; + + /* num of queued frames and some GThread stuff + * to wait if there's not enough */ + gint8 *frame_queue_state; + GMutex *mutex_queue_state; + GCond *cond_queue_state; + gint num_queued; + gint sync_frame, queue_frame; + gboolean is_capturing; + GstClockTimeDiff timestamp_offset; + + /* True if we want to stop */ + gboolean quit; + + gint offset; + + /* list of supported colorspaces (as integers) */ + GList *colorspaces; + + gboolean autoprobe; /* probe features on startup ? */ + gboolean autoprobe_fps; /* probe fps on startup ? */ + gboolean copy_mode; + + GValue *fps_list; /* list of fps probed */ +}; + +struct _GstV4lSrcClass +{ + GstV4lElementClass parent_class; +}; + + +GType gst_v4lsrc_get_type (void); + + +G_END_DECLS + + +#endif /* __GST_V4LSRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.c new file mode 100644 index 0000000..8f432b4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.c @@ -0,0 +1,328 @@ +/* GStreamer + * + * gstv4ltuner.c: tuner interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include "gstv4ltuner.h" +#include "gstv4lelement.h" +#include "v4l_calls.h" + +static void gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass); +static void gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel); + +static void gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass); +static void gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm); + +static const GList *gst_v4l_tuner_list_channels (GstTuner * tuner); +static void gst_v4l_tuner_set_channel (GstTuner * tuner, + GstTunerChannel * channel); +static GstTunerChannel *gst_v4l_tuner_get_channel (GstTuner * tuner); + +static const GList *gst_v4l_tuner_list_norms (GstTuner * tuner); +static void gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm); +static GstTunerNorm *gst_v4l_tuner_get_norm (GstTuner * tuner); + +static void gst_v4l_tuner_set_frequency (GstTuner * tuner, + GstTunerChannel * channel, gulong frequency); +static gulong gst_v4l_tuner_get_frequency (GstTuner * tuner, + GstTunerChannel * channel); +static gint gst_v4l_tuner_signal_strength (GstTuner * tuner, + GstTunerChannel * channel); + +static GstTunerNormClass *norm_parent_class = NULL; +static GstTunerChannelClass *channel_parent_class = NULL; + +GType +gst_v4l_tuner_channel_get_type (void) +{ + static GType gst_v4l_tuner_channel_type = 0; + + if (!gst_v4l_tuner_channel_type) { + static const GTypeInfo v4l_tuner_channel_info = { + sizeof (GstV4lTunerChannelClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l_tuner_channel_class_init, + NULL, + NULL, + sizeof (GstV4lTunerChannel), + 0, + (GInstanceInitFunc) gst_v4l_tuner_channel_init, + NULL + }; + + gst_v4l_tuner_channel_type = + g_type_register_static (GST_TYPE_TUNER_CHANNEL, + "GstV4lTunerChannel", &v4l_tuner_channel_info, 0); + } + + return gst_v4l_tuner_channel_type; +} + +static void +gst_v4l_tuner_channel_class_init (GstV4lTunerChannelClass * klass) +{ + channel_parent_class = g_type_class_peek_parent (klass); +} + +static void +gst_v4l_tuner_channel_init (GstV4lTunerChannel * channel) +{ + channel->index = 0; + channel->audio = 0; + channel->tuner = 0; +} + +GType +gst_v4l_tuner_norm_get_type (void) +{ + static GType gst_v4l_tuner_norm_type = 0; + + if (!gst_v4l_tuner_norm_type) { + static const GTypeInfo v4l_tuner_norm_info = { + sizeof (GstV4lTunerNormClass), + NULL, + NULL, + (GClassInitFunc) gst_v4l_tuner_norm_class_init, + NULL, + NULL, + sizeof (GstV4lTunerNorm), + 0, + (GInstanceInitFunc) gst_v4l_tuner_norm_init, + NULL + }; + + gst_v4l_tuner_norm_type = + g_type_register_static (GST_TYPE_TUNER_NORM, + "GstV4lTunerNorm", &v4l_tuner_norm_info, 0); + } + + return gst_v4l_tuner_norm_type; +} + +static void +gst_v4l_tuner_norm_class_init (GstV4lTunerNormClass * klass) +{ + norm_parent_class = g_type_class_peek_parent (klass); +} + +static void +gst_v4l_tuner_norm_init (GstV4lTunerNorm * norm) +{ + norm->index = 0; +} + +void +gst_v4l_tuner_interface_init (GstTunerClass * klass) +{ + /* default virtual functions */ + klass->list_channels = gst_v4l_tuner_list_channels; + klass->set_channel = gst_v4l_tuner_set_channel; + klass->get_channel = gst_v4l_tuner_get_channel; + + klass->list_norms = gst_v4l_tuner_list_norms; + klass->set_norm = gst_v4l_tuner_set_norm; + klass->get_norm = gst_v4l_tuner_get_norm; + + klass->set_frequency = gst_v4l_tuner_set_frequency; + klass->get_frequency = gst_v4l_tuner_get_frequency; + klass->signal_strength = gst_v4l_tuner_signal_strength; +} + +static G_GNUC_UNUSED gboolean +gst_v4l_tuner_contains_channel (GstV4lElement * v4lelement, + GstV4lTunerChannel * v4lchannel) +{ + const GList *item; + + for (item = v4lelement->channels; item != NULL; item = item->next) + if (item->data == v4lchannel) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l_tuner_list_channels (GstTuner * tuner) +{ + return GST_V4LELEMENT (tuner)->channels; +} + +static void +gst_v4l_tuner_set_channel (GstTuner * tuner, GstTunerChannel * channel) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel); + gint norm; + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L_IS_OPEN (v4lelement)); + g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel)); + + gst_v4l_get_chan_norm (v4lelement, NULL, &norm); + gst_v4l_set_chan_norm (v4lelement, v4lchannel->index, norm); +} + +static GstTunerChannel * +gst_v4l_tuner_get_channel (GstTuner * tuner) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GList *item; + gint channel; + + /* assert that we're opened */ + g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL); + + gst_v4l_get_chan_norm (v4lelement, &channel, NULL); + + for (item = v4lelement->channels; item != NULL; item = item->next) { + if (channel == GST_V4L_TUNER_CHANNEL (item->data)->index) + return GST_TUNER_CHANNEL (item->data); + } + + return NULL; +} + +static G_GNUC_UNUSED gboolean +gst_v4l_tuner_contains_norm (GstV4lElement * v4lelement, + GstV4lTunerNorm * v4lnorm) +{ + const GList *item; + + for (item = v4lelement->norms; item != NULL; item = item->next) + if (item->data == v4lnorm) + return TRUE; + + return FALSE; +} + +static const GList * +gst_v4l_tuner_list_norms (GstTuner * tuner) +{ + return GST_V4LELEMENT (tuner)->norms; +} + +static void +gst_v4l_tuner_set_norm (GstTuner * tuner, GstTunerNorm * norm) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GstV4lTunerNorm *v4lnorm = GST_V4L_TUNER_NORM (norm); + gint channel; + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L_IS_OPEN (v4lelement)); + g_return_if_fail (gst_v4l_tuner_contains_norm (v4lelement, v4lnorm)); + + gst_v4l_get_chan_norm (v4lelement, &channel, NULL); + gst_v4l_set_chan_norm (v4lelement, channel, v4lnorm->index); +} + +static GstTunerNorm * +gst_v4l_tuner_get_norm (GstTuner * tuner) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GList *item; + gint norm; + + /* assert that we're opened */ + g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), NULL); + + gst_v4l_get_chan_norm (v4lelement, NULL, &norm); + + for (item = v4lelement->norms; item != NULL; item = item->next) { + if (norm == GST_V4L_TUNER_NORM (item->data)->index) + return GST_TUNER_NORM (item->data); + } + + return NULL; +} + +static void +gst_v4l_tuner_set_frequency (GstTuner * tuner, + GstTunerChannel * channel, gulong frequency) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel); + gint chan; + + /* assert that we're opened and that we're using a known item */ + g_return_if_fail (GST_V4L_IS_OPEN (v4lelement)); + g_return_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY)); + g_return_if_fail (gst_v4l_tuner_contains_channel (v4lelement, v4lchannel)); + + gst_v4l_get_chan_norm (v4lelement, &chan, NULL); + if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) { + gst_v4l_set_frequency (v4lelement, v4lchannel->tuner, frequency); + } +} + +static gulong +gst_v4l_tuner_get_frequency (GstTuner * tuner, GstTunerChannel * channel) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel); + gint chan; + gulong frequency = 0; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement, + v4lchannel), 0); + + gst_v4l_get_chan_norm (v4lelement, &chan, NULL); + if (chan == GST_V4L_TUNER_CHANNEL (channel)->index) { + gst_v4l_get_frequency (v4lelement, v4lchannel->tuner, &frequency); + } + + return frequency; +} + +static gint +gst_v4l_tuner_signal_strength (GstTuner * tuner, GstTunerChannel * channel) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (tuner); + GstV4lTunerChannel *v4lchannel = GST_V4L_TUNER_CHANNEL (channel); + gint chan; + guint signal = 0; + + /* assert that we're opened and that we're using a known item */ + g_return_val_if_fail (GST_V4L_IS_OPEN (v4lelement), 0); + g_return_val_if_fail (GST_TUNER_CHANNEL_HAS_FLAG (channel, + GST_TUNER_CHANNEL_FREQUENCY), 0); + g_return_val_if_fail (gst_v4l_tuner_contains_channel (v4lelement, + v4lchannel), 0); + + gst_v4l_get_chan_norm (v4lelement, &chan, NULL); + if (chan == GST_V4L_TUNER_CHANNEL (channel)->index && + GST_TUNER_CHANNEL_HAS_FLAG (channel, GST_TUNER_CHANNEL_FREQUENCY)) { + gst_v4l_get_signal (v4lelement, v4lchannel->tuner, &signal); + } + + return (gint) signal; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.h new file mode 100644 index 0000000..ca5b93a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4ltuner.h @@ -0,0 +1,84 @@ +/* GStreamer + * + * gstv4ltuner.h: tuner interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4L_TUNER_H__ +#define __GST_V4L_TUNER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_V4L_TUNER_CHANNEL \ + (gst_v4l_tuner_channel_get_type ()) +#define GST_V4L_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_CHANNEL, \ + GstV4lTunerChannel)) +#define GST_V4L_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_CHANNEL, \ + GstV4lTunerChannelClass)) +#define GST_IS_V4L_TUNER_CHANNEL(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_CHANNEL)) +#define GST_IS_V4L_TUNER_CHANNEL_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_CHANNEL)) + +typedef struct _GstV4lTunerChannel { + GstTunerChannel parent; + + gint index; + gint tuner; + gint audio; +} GstV4lTunerChannel; + +typedef struct _GstV4lTunerChannelClass { + GstTunerChannelClass parent; +} GstV4lTunerChannelClass; + +#define GST_TYPE_V4L_TUNER_NORM \ + (gst_v4l_tuner_norm_get_type ()) +#define GST_V4L_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L_TUNER_NORM, \ + GstV4lTunerNorm)) +#define GST_V4L_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_V4L_TUNER_NORM, \ + GstV4lTunerNormClass)) +#define GST_IS_V4L_TUNER_NORM(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4L_TUNER_NORM)) +#define GST_IS_V4L_TUNER_NORM_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_V4L_TUNER_NORM)) + +typedef struct _GstV4lTunerNorm { + GstTunerNorm parent; + + gint index; +} GstV4lTunerNorm; + +typedef struct _GstV4lTunerNormClass { + GstTunerNormClass parent; +} GstV4lTunerNormClass; + +GType gst_v4l_tuner_channel_get_type (void); +GType gst_v4l_tuner_norm_get_type (void); + +void gst_v4l_tuner_interface_init (GstTunerClass *klass); + +#endif /* __GST_V4L_TUNER_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.c b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.c new file mode 100644 index 0000000..5867caf --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.c @@ -0,0 +1,246 @@ +/* GStreamer + * + * gstv4lxoverlay.c: X-based overlay interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include +#include + +#include "gstv4lxoverlay.h" +#include "gstv4lelement.h" +#include "v4l_calls.h" + +GST_DEBUG_CATEGORY_STATIC (v4lxv_debug); +#define GST_CAT_DEFAULT v4lxv_debug + +struct _GstV4lXv +{ + Display *dpy; + gint port, idle_id; + GMutex *mutex; +}; + +static void gst_v4l_xoverlay_set_window_handle (GstXOverlay * overlay, + guintptr xwindow_id); + +void +gst_v4l_xoverlay_interface_init (GstXOverlayClass * klass) +{ + /* default virtual functions */ + klass->set_window_handle = gst_v4l_xoverlay_set_window_handle; + + GST_DEBUG_CATEGORY_INIT (v4lxv_debug, "v4lxv", 0, + "V4L XOverlay interface debugging"); +} + +static void +gst_v4l_xoverlay_open (GstV4lElement * v4lelement) +{ + struct stat s; + GstV4lXv *v4lxv; + const gchar *name = g_getenv ("DISPLAY"); + unsigned int ver, rel, req, ev, err, anum; + int i, id = 0, first_id = 0, min; + XvAdaptorInfo *ai; + Display *dpy; + + /* we need a display, obviously */ + if (!name || !(dpy = XOpenDisplay (name))) { + GST_WARNING ("No $DISPLAY set or failed to open - no overlay"); + return; + } + + /* First let's check that XVideo extension is available */ + if (!XQueryExtension (dpy, "XVideo", &i, &i, &i)) { + GST_WARNING ("Xv extension not available - no overlay"); + XCloseDisplay (dpy); + return; + } + + /* find port that belongs to this device */ + if (XvQueryExtension (dpy, &ver, &rel, &req, &ev, &err) != Success) { + GST_WARNING ("Xv extension not supported - no overlay"); + XCloseDisplay (dpy); + return; + } + if (XvQueryAdaptors (dpy, DefaultRootWindow (dpy), &anum, &ai) != Success) { + GST_WARNING ("Failed to query Xv adaptors"); + XCloseDisplay (dpy); + return; + } + if (fstat (v4lelement->video_fd, &s) < 0) { + GST_ERROR ("Failed to stat() file descriptor: %s", g_strerror (errno)); + XCloseDisplay (dpy); + return; + } + min = s.st_rdev & 0xff; + for (i = 0; i < anum; i++) { + if (!strcmp (ai[i].name, "video4linux")) { + if (first_id == 0) + first_id = ai[i].base_id; + + /* hmm... */ + if (first_id != 0 && ai[i].base_id == first_id + min) + id = ai[i].base_id; + } + } + XvFreeAdaptorInfo (ai); + + if (id == 0) { + GST_WARNING ("Did not find XvPortID for device - no overlay"); + XCloseDisplay (dpy); + return; + } + + v4lxv = g_new0 (GstV4lXv, 1); + v4lxv->dpy = dpy; + v4lxv->port = id; + v4lxv->mutex = g_mutex_new (); + v4lxv->idle_id = 0; + v4lelement->xv = v4lxv; + + if (v4lelement->xwindow_id) { + gst_v4l_xoverlay_set_window_handle (GST_X_OVERLAY (v4lelement), + v4lelement->xwindow_id); + } +} + +static void +gst_v4l_xoverlay_close (GstV4lElement * v4lelement) +{ + GstV4lXv *v4lxv = v4lelement->xv; + + if (!v4lelement->xv) + return; + + if (v4lelement->xwindow_id) { + gst_v4l_xoverlay_set_window_handle (GST_X_OVERLAY (v4lelement), 0); + } + + XCloseDisplay (v4lxv->dpy); + g_mutex_free (v4lxv->mutex); + if (v4lxv->idle_id) + g_source_remove (v4lxv->idle_id); + g_free (v4lxv); + v4lelement->xv = NULL; +} + +void +gst_v4l_xoverlay_start (GstV4lElement * v4lelement) +{ + if (v4lelement->xwindow_id) { + gst_v4l_xoverlay_open (v4lelement); + } +} + +void +gst_v4l_xoverlay_stop (GstV4lElement * v4lelement) +{ + gst_v4l_xoverlay_close (v4lelement); +} + +static gboolean +idle_refresh (gpointer data) +{ + GstV4lElement *v4lelement = GST_V4LELEMENT (data); + GstV4lXv *v4lxv = v4lelement->xv; + XWindowAttributes attr; + + if (v4lxv) { + g_mutex_lock (v4lxv->mutex); + + XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr); + XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id, + DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)), + 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height); + + v4lxv->idle_id = 0; + g_mutex_unlock (v4lxv->mutex); + } + + /* once */ + return FALSE; +} + +static void +gst_v4l_xoverlay_set_window_handle (GstXOverlay * overlay, guintptr id) +{ + XID xwindow_id = id; + GstV4lElement *v4lelement = GST_V4LELEMENT (overlay); + GstV4lXv *v4lxv; + XWindowAttributes attr; + gboolean change = (v4lelement->xwindow_id != xwindow_id); + + GST_LOG_OBJECT (v4lelement, "Changing port to %lx", xwindow_id); + + if (!v4lelement->xv && GST_V4L_IS_OPEN (v4lelement)) + gst_v4l_xoverlay_open (v4lelement); + + v4lxv = v4lelement->xv; + + if (v4lxv) + g_mutex_lock (v4lxv->mutex); + + if (change) { + if (v4lelement->xwindow_id && v4lxv) { + GST_DEBUG_OBJECT (v4lelement, + "Disabling port %lx", v4lelement->xwindow_id); + + XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 0); + XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 0); + XvStopVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id); + } + + v4lelement->xwindow_id = xwindow_id; + } + + if (!v4lxv || xwindow_id == 0) { + if (v4lxv) + g_mutex_unlock (v4lxv->mutex); + return; + } + + if (change) { + GST_DEBUG_OBJECT (v4lelement, "Enabling port %lx", xwindow_id); + + /* draw */ + XvSelectPortNotify (v4lxv->dpy, v4lxv->port, 1); + XvSelectVideoNotify (v4lxv->dpy, v4lelement->xwindow_id, 1); + } + + XGetWindowAttributes (v4lxv->dpy, v4lelement->xwindow_id, &attr); + XvPutVideo (v4lxv->dpy, v4lxv->port, v4lelement->xwindow_id, + DefaultGC (v4lxv->dpy, DefaultScreen (v4lxv->dpy)), + 0, 0, attr.width, attr.height, 0, 0, attr.width, attr.height); + + if (v4lxv->idle_id) + g_source_remove (v4lxv->idle_id); + v4lxv->idle_id = g_idle_add (idle_refresh, v4lelement); + g_mutex_unlock (v4lxv->mutex); +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.h b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.h new file mode 100644 index 0000000..959e5c9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/gstv4lxoverlay.h @@ -0,0 +1,40 @@ +/* GStreamer + * + * gstv4lxoverlay.h: tv mixer interface implementation for V4L + * + * Copyright (C) 2003 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_V4L_X_OVERLAY_H__ +#define __GST_V4L_X_OVERLAY_H__ + +#include +#include + +#include "gstv4lelement.h" + +G_BEGIN_DECLS + +void gst_v4l_xoverlay_interface_init (GstXOverlayClass *klass); + +void gst_v4l_xoverlay_start (GstV4lElement * v4lelement); +void gst_v4l_xoverlay_stop (GstV4lElement * v4lelement); + +G_END_DECLS + +#endif /* __GST_V4L_X_OVERLAY_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.c b/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.c new file mode 100644 index 0000000..b2b7573 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.c @@ -0,0 +1,724 @@ +/* GStreamer + * + * v4l_calls.c: generic V4L calls + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "v4l_calls.h" +#include "gstv4ltuner.h" +#include "gstv4lcolorbalance.h" + +#include "gstv4lsrc.h" +/* #include "gstv4lmjpegsrc.h" */ +/* #include "gstv4lmjpegsink.h" */ + +GST_DEBUG_CATEGORY_EXTERN (v4l_debug); +#define GST_CAT_DEFAULT v4l_debug + +static const char *picture_name[] = { + "Hue", + "Brightness", + "Contrast", + "Saturation", + NULL +}; + +G_GNUC_UNUSED static const char *audio_name[] = { + "Volume", + "Mute", + "Mode", + NULL +}; + +static const char *norm_name[] = { + "PAL", + "NTSC", + "SECAM", + NULL +}; + +/****************************************************** + * gst_v4l_get_capabilities(): + * get the device's capturing capabilities + * sets v4lelement->vcap and v4lelement->vwin + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_capabilities (GstV4lElement * v4lelement) +{ + GST_DEBUG_OBJECT (v4lelement, "getting capabilities"); + GST_V4L_CHECK_OPEN (v4lelement); + + if (ioctl (v4lelement->video_fd, VIDIOCGCAP, &(v4lelement->vcap)) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("error getting capabilities %s of from device %s", + g_strerror (errno), v4lelement->videodev)); + return FALSE; + } + + if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(v4lelement->vwin)) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("error getting window properties %s of from device %s", + g_strerror (errno), v4lelement->videodev)); + return FALSE; + } + + return TRUE; +} + +/****************************************************** + * gst_v4l_set_window_properties(): + * set the device's capturing parameters (vwin) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_set_window_properties (GstV4lElement * v4lelement) +{ + struct video_window vwin; + + GST_DEBUG_OBJECT (v4lelement, "setting window flags 0x%x to device %s", + v4lelement->vwin.flags, v4lelement->videodev); + GST_V4L_CHECK_OPEN (v4lelement); + + if (ioctl (v4lelement->video_fd, VIDIOCSWIN, &(v4lelement->vwin)) < 0) { + GST_DEBUG_OBJECT (v4lelement, + "could not ioctl window properties 0x%x to device %s", + v4lelement->vwin.flags, v4lelement->videodev); + return FALSE; + } + + /* get it again to make sure we have it correctly */ + if (ioctl (v4lelement->video_fd, VIDIOCGWIN, &(vwin)) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("error getting window properties %s of from device %s", + g_strerror (errno), v4lelement->videodev)); + return FALSE; + } + if (vwin.flags != v4lelement->vwin.flags) { + GST_DEBUG_OBJECT (v4lelement, "set 0x%x but got 0x%x back", + v4lelement->vwin.flags, vwin.flags); + return FALSE; + } + + return TRUE; +} + +/****************************************************** + * gst_v4l_open(): + * open the video device (v4lelement->videodev) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_open (GstV4lElement * v4lelement) +{ + int num; + + GST_DEBUG_OBJECT (v4lelement, "opening device %s", v4lelement->videodev); + GST_V4L_CHECK_NOT_OPEN (v4lelement); + GST_V4L_CHECK_NOT_ACTIVE (v4lelement); + + /* be sure we have a device */ + if (!v4lelement->videodev) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND, + (_("No device specified.")), (NULL)); + return FALSE; + } + + /* open the device */ + v4lelement->video_fd = open (v4lelement->videodev, O_RDWR); + if (!GST_V4L_IS_OPEN (v4lelement)) { + if (errno == ENODEV || errno == ENOENT) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, NOT_FOUND, + (_("Device \"%s\" does not exist."), v4lelement->videodev), (NULL)); + return FALSE; + } + if (errno == EBUSY) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, BUSY, + (_("Device \"%s\" is already being used."), v4lelement->videodev), + (NULL)); + return FALSE; + } + GST_ELEMENT_ERROR (v4lelement, RESOURCE, OPEN_READ_WRITE, + (_("Could not open device \"%s\" for reading and writing."), + v4lelement->videodev), GST_ERROR_SYSTEM); + return FALSE; + } + + /* get capabilities */ + if (!gst_v4l_get_capabilities (v4lelement)) { + close (v4lelement->video_fd); + v4lelement->video_fd = -1; + return FALSE; + } + + /* device type check */ + if ((GST_IS_V4LSRC (v4lelement) && + !(v4lelement->vcap.type & VID_TYPE_CAPTURE))) { +/* (GST_IS_V4LMJPEGSRC (v4lelement) && */ +/* !(v4lelement->vcap.type & VID_TYPE_MJPEG_ENCODER)) || */ +/* (GST_IS_V4LMJPEGSINK (v4lelement) && */ +/* !(v4lelement->vcap.type & VID_TYPE_MJPEG_DECODER))) { */ + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Device opened, but wrong type (0x%x)", v4lelement->vcap.type)); + close (v4lelement->video_fd); + v4lelement->video_fd = -1; + return FALSE; + } + + GST_INFO_OBJECT (v4lelement, "Opened device \'%s\' (\'%s\') successfully", + v4lelement->vcap.name, v4lelement->videodev); + + /* norms + inputs, for the tuner interface */ + for (num = 0; norm_name[num] != NULL; num++) { + GstV4lTunerNorm *v4lnorm = g_object_new (GST_TYPE_V4L_TUNER_NORM, + NULL); + GstTunerNorm *norm = GST_TUNER_NORM (v4lnorm); + + norm->label = g_strdup (norm_name[num]); + if (num == 1) + gst_value_set_fraction (&norm->framerate, 30000, 1001); + else + gst_value_set_fraction (&norm->framerate, 25, 1); + + v4lnorm->index = num; + v4lelement->norms = g_list_append (v4lelement->norms, (gpointer) norm); + } + v4lelement->channels = gst_v4l_get_chan_names (v4lelement); + + for (num = 0; picture_name[num] != NULL; num++) { + GstV4lColorBalanceChannel *v4lchannel = + g_object_new (GST_TYPE_V4L_COLOR_BALANCE_CHANNEL, NULL); + GstColorBalanceChannel *channel = GST_COLOR_BALANCE_CHANNEL (v4lchannel); + + channel->label = g_strdup (picture_name[num]); + channel->min_value = 0; + channel->max_value = 65535; + v4lchannel->index = num; + v4lelement->colors = g_list_append (v4lelement->colors, channel); + } + + GST_DEBUG_OBJECT (v4lelement, "Setting default norm/input"); + gst_v4l_set_chan_norm (v4lelement, 0, 0); + + return TRUE; +} + + +/****************************************************** + * gst_v4l_close(): + * close the video device (v4lelement->video_fd) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_close (GstV4lElement * v4lelement) +{ + GST_DEBUG_OBJECT (v4lelement, "closing device"); + GST_V4L_CHECK_OPEN (v4lelement); + GST_V4L_CHECK_NOT_ACTIVE (v4lelement); + + close (v4lelement->video_fd); + v4lelement->video_fd = -1; + + g_list_foreach (v4lelement->channels, (GFunc) g_object_unref, NULL); + g_list_free (v4lelement->channels); + v4lelement->channels = NULL; + + g_list_foreach (v4lelement->norms, (GFunc) g_object_unref, NULL); + g_list_free (v4lelement->norms); + v4lelement->norms = NULL; + + g_list_foreach (v4lelement->colors, (GFunc) g_object_unref, NULL); + g_list_free (v4lelement->colors); + v4lelement->colors = NULL; + + return TRUE; +} + + +/****************************************************** + * gst_v4l_get_num_chans() + * return value: the number of video input channels + ******************************************************/ + +static gint +gst_v4l_get_num_chans (GstV4lElement * v4lelement) +{ + GST_DEBUG_OBJECT (v4lelement, "getting number of channels"); + GST_V4L_CHECK_OPEN (v4lelement); + + return v4lelement->vcap.channels; +} + + +/****************************************************** + * gst_v4l_get_chan_names() + * return value: a GList containing the channel names + ******************************************************/ + +GList * +gst_v4l_get_chan_names (GstV4lElement * v4lelement) +{ + struct video_channel vchan = { 0 }; + GList *list = NULL; + gint i; + + GST_DEBUG_OBJECT (v4lelement, "getting channel names"); + + if (!GST_V4L_IS_OPEN (v4lelement)) + return NULL; + + for (i = 0; i < gst_v4l_get_num_chans (v4lelement); i++) { + GstV4lTunerChannel *v4lchannel; + GstTunerChannel *channel; + + vchan.channel = i; + if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &vchan) < 0) { + /* Skip this channel */ + continue; + } + v4lchannel = g_object_new (GST_TYPE_V4L_TUNER_CHANNEL, NULL); + v4lchannel->index = i; + + channel = GST_TUNER_CHANNEL (v4lchannel); + channel->label = g_strdup (vchan.name); + channel->flags = GST_TUNER_CHANNEL_INPUT; + if (vchan.flags & VIDEO_VC_TUNER) { + struct video_tuner vtun; + gint n; + + for (n = 0; n < vchan.tuners; n++) { + vtun.tuner = n; + if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) + continue; /* no more tuners */ + if (strcmp (vtun.name, vchan.name) != 0) { + continue; /* not this one */ + } + + v4lchannel->tuner = n; + channel->flags |= GST_TUNER_CHANNEL_FREQUENCY; + channel->freq_multiplicator = + 62.5 * ((vtun.flags & VIDEO_TUNER_LOW) ? 1 : 1000); + channel->min_frequency = vtun.rangelow * channel->freq_multiplicator; + channel->max_frequency = vtun.rangehigh * channel->freq_multiplicator; + channel->min_signal = 0; + channel->max_signal = 0xffff; + break; + } + + } + if (vchan.flags & VIDEO_VC_AUDIO) { + struct video_audio vaud; + gint n; + + for (n = 0; n < v4lelement->vcap.audios; n++) { + vaud.audio = n; + if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vaud) < 0) + continue; + if (!strcmp (vaud.name, vchan.name)) { + v4lchannel->audio = n; + channel->flags |= GST_TUNER_CHANNEL_AUDIO; + break; + } + } + } + list = g_list_prepend (list, (gpointer) channel); + } + + return g_list_reverse (list); +} + + +/****************************************************** + * gst_v4l_get_chan_norm(): + * get the currently active video-channel and it's + * norm (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_chan_norm (GstV4lElement * v4lelement, gint * channel, gint * norm) +{ + GST_DEBUG_OBJECT (v4lelement, "getting current channel and norm"); + GST_V4L_CHECK_OPEN (v4lelement); + + if (channel) + *channel = v4lelement->vchan.channel; + if (norm) + *norm = v4lelement->vchan.norm; + + return TRUE; +} + + +/****************************************************** + * gst_v4l_set_chan_norm(): + * set a new active channel and it's norm + * (VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_set_chan_norm (GstV4lElement * v4lelement, gint channel, gint norm) +{ + GST_DEBUG_OBJECT (v4lelement, "setting channel = %d, norm = %d (%s)", + channel, norm, norm_name[norm]); + GST_V4L_CHECK_OPEN (v4lelement); + //GST_V4L_CHECK_NOT_ACTIVE (v4lelement); + + v4lelement->vchan.channel = channel; + v4lelement->vchan.norm = norm; + + if (ioctl (v4lelement->video_fd, VIDIOCSCHAN, &(v4lelement->vchan)) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting the channel/norm settings: %s", g_strerror (errno))); + return FALSE; + } + + if (ioctl (v4lelement->video_fd, VIDIOCGCHAN, &(v4lelement->vchan)) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting the channel/norm settings: %s", g_strerror (errno))); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4l_get_signal(): + * get the current signal + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_signal (GstV4lElement * v4lelement, gint tunernum, guint * signal) +{ + struct video_tuner tuner; + + GST_DEBUG_OBJECT (v4lelement, "getting tuner signal"); + GST_V4L_CHECK_OPEN (v4lelement); + + tuner.tuner = tunernum; + if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &tuner) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting tuner signal: %s", g_strerror (errno))); + return FALSE; + } + + *signal = tuner.signal; + + return TRUE; +} + + +/****************************************************** + * gst_v4l_get_frequency(): + * get the current frequency + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_frequency (GstV4lElement * v4lelement, + gint tunernum, gulong * frequency) +{ + struct video_tuner vtun; + GstTunerChannel *channel; + + GST_DEBUG_OBJECT (v4lelement, "getting tuner frequency"); + GST_V4L_CHECK_OPEN (v4lelement); + + channel = gst_tuner_get_channel (GST_TUNER (v4lelement)); + + /* check that this is the current input */ + vtun.tuner = tunernum; + if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) + return FALSE; + if (strcmp (vtun.name, v4lelement->vchan.name)) + return FALSE; + + if (ioctl (v4lelement->video_fd, VIDIOCGFREQ, frequency) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting tuner frequency: %s", g_strerror (errno))); + return FALSE; + } + + *frequency = *frequency * channel->freq_multiplicator; + + return TRUE; +} + + +/****************************************************** + * gst_v4l_set_frequency(): + * set frequency + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_set_frequency (GstV4lElement * v4lelement, + gint tunernum, gulong frequency) +{ + struct video_tuner vtun; + GstTunerChannel *channel; + + GST_DEBUG_OBJECT (v4lelement, "setting tuner frequency to %lu", frequency); + GST_V4L_CHECK_OPEN (v4lelement); + + channel = gst_tuner_get_channel (GST_TUNER (v4lelement)); + + /* check that this is the current input */ + vtun.tuner = tunernum; + if (ioctl (v4lelement->video_fd, VIDIOCGTUNER, &vtun) < 0) + return FALSE; + if (strcmp (vtun.name, v4lelement->vchan.name)) + return FALSE; + + frequency = frequency / channel->freq_multiplicator; + + if (ioctl (v4lelement->video_fd, VIDIOCSFREQ, &frequency) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting tuner frequency: %s", g_strerror (errno))); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4l_get_picture(): + * get a picture value + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_picture (GstV4lElement * v4lelement, + GstV4lPictureType type, gint * value) +{ + struct video_picture vpic; + + GST_DEBUG_OBJECT (v4lelement, "getting picture property type %d (%s)", type, + picture_name[type]); + GST_V4L_CHECK_OPEN (v4lelement); + + if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting picture parameters: %s", g_strerror (errno))); + return FALSE; + } + + switch (type) { + case V4L_PICTURE_HUE: + *value = vpic.hue; + break; + case V4L_PICTURE_BRIGHTNESS: + *value = vpic.brightness; + break; + case V4L_PICTURE_CONTRAST: + *value = vpic.contrast; + break; + case V4L_PICTURE_SATURATION: + *value = vpic.colour; + break; + default: + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting picture parameters: unknown type %d", type)); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4l_set_picture(): + * set a picture value + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_set_picture (GstV4lElement * v4lelement, + GstV4lPictureType type, gint value) +{ + struct video_picture vpic; + + GST_DEBUG_OBJECT (v4lelement, "setting picture type %d (%s) to value %d", + type, picture_name[type], value); + GST_V4L_CHECK_OPEN (v4lelement); + + if (ioctl (v4lelement->video_fd, VIDIOCGPICT, &vpic) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting picture parameters: %s", g_strerror (errno))); + return FALSE; + } + + switch (type) { + case V4L_PICTURE_HUE: + vpic.hue = value; + break; + case V4L_PICTURE_BRIGHTNESS: + vpic.brightness = value; + break; + case V4L_PICTURE_CONTRAST: + vpic.contrast = value; + break; + case V4L_PICTURE_SATURATION: + vpic.colour = value; + break; + default: + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting picture parameters: unknown type %d", type)); + return FALSE; + } + + if (ioctl (v4lelement->video_fd, VIDIOCSPICT, &vpic) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting picture parameters: %s", g_strerror (errno))); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4l_get_audio(): + * get some audio value + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_get_audio (GstV4lElement * v4lelement, + gint audionum, GstV4lAudioType type, gint * value) +{ + struct video_audio vau; + + GST_DEBUG_OBJECT (v4lelement, "getting audio parameter type %d (%s)", type, + audio_name[type]); + GST_V4L_CHECK_OPEN (v4lelement); + + vau.audio = audionum; + if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting audio parameters: %s", g_strerror (errno))); + return FALSE; + } + + switch (type) { + case V4L_AUDIO_MUTE: + *value = (vau.flags & VIDEO_AUDIO_MUTE); + break; + case V4L_AUDIO_VOLUME: + *value = vau.volume; + break; + case V4L_AUDIO_MODE: + *value = vau.mode; + break; + default: + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting audio parameters: unknown type %d", type)); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4l_set_audio(): + * set some audio value + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4l_set_audio (GstV4lElement * v4lelement, + gint audionum, GstV4lAudioType type, gint value) +{ + struct video_audio vau; + + GST_DEBUG_OBJECT (v4lelement, + "setting audio parameter type %d (%s) to value %d", type, + audio_name[type], value); + GST_V4L_CHECK_OPEN (v4lelement); + + vau.audio = audionum; + if (ioctl (v4lelement->video_fd, VIDIOCGAUDIO, &vau) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error getting audio parameters: %s", g_strerror (errno))); + return FALSE; + } + + switch (type) { + case V4L_AUDIO_MUTE: + if (!(vau.flags & VIDEO_AUDIO_MUTABLE)) { + GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL), + ("Error setting audio mute: (un)setting mute is not supported")); + return FALSE; + } + if (value) + vau.flags |= VIDEO_AUDIO_MUTE; + else + vau.flags &= ~VIDEO_AUDIO_MUTE; + break; + case V4L_AUDIO_VOLUME: + if (!(vau.flags & VIDEO_AUDIO_VOLUME)) { + GST_ELEMENT_ERROR (v4lelement, CORE, NOT_IMPLEMENTED, (NULL), + ("Error setting audio volume: setting volume is not supported")); + return FALSE; + } + vau.volume = value; + break; + case V4L_AUDIO_MODE: + vau.mode = value; + break; + default: + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting audio parameters: unknown type %d", type)); + return FALSE; + } + + if (ioctl (v4lelement->video_fd, VIDIOCSAUDIO, &vau) < 0) { + GST_ELEMENT_ERROR (v4lelement, RESOURCE, SETTINGS, (NULL), + ("Error setting audio parameters: %s", g_strerror (errno))); + return FALSE; + } + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.h b/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.h new file mode 100644 index 0000000..1f1d90a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4l_calls.h @@ -0,0 +1,154 @@ +/* GStreamer + * + * v4l_calls.h: header for generic V4L calls + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __V4L_CALLS_H__ +#define __V4L_CALLS_H__ + +#include "gstv4lelement.h" +#include "gst/gst-i18n-plugin.h" + + +G_BEGIN_DECLS + + +/* simple check whether the device is open */ +#define GST_V4L_IS_OPEN(element) \ + (GST_V4LELEMENT (element)->video_fd > 0) + +/* check whether the device is 'active' */ +#define GST_V4L_IS_ACTIVE(element) \ + (GST_V4LELEMENT (element)->buffer != NULL) + +#define GST_V4L_IS_OVERLAY(element) \ + (GST_V4LELEMENT (element)->vcap.type & VID_TYPE_OVERLAY) + +/* checks whether the current v4lelement has already been open()'ed or not */ +#define GST_V4L_CHECK_OPEN(element) \ + if (!GST_V4L_IS_OPEN (element)) \ + { \ + GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \ + (_("Device is not open.")), (NULL)); \ + return FALSE; \ + } + +/* checks whether the current v4lelement is close()'ed or whether it is still open */ +#define GST_V4L_CHECK_NOT_OPEN(element) \ + if (GST_V4L_IS_OPEN (element)) \ + { \ + GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \ + (_("Device is open.")), (NULL)); \ + return FALSE; \ + } + +/* checks whether the current v4lelement does video overlay */ +#define GST_V4L_CHECK_OVERLAY(element) \ + if (!(element->vcap.type & VID_TYPE_OVERLAY)) \ + { \ + GST_ELEMENT_ERROR (element, RESOURCE, TOO_LAZY, \ + (NULL), ("Device cannot handle overlay")); \ + return FALSE; \ + } + +/* checks whether we're in capture mode or not */ +#define GST_V4L_CHECK_ACTIVE(element) \ + if (!GST_V4L_IS_ACTIVE (element)) \ + { \ + GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \ + (NULL), ("Device is not in streaming mode")); \ + return FALSE; \ + } + +/* checks whether we're out of capture mode or not */ +#define GST_V4L_CHECK_NOT_ACTIVE(element) \ + if (GST_V4L_IS_ACTIVE (element)) \ + { \ + GST_ELEMENT_ERROR (element, RESOURCE, SETTINGS, \ + (NULL), ("Device is in streaming mode")); \ + return FALSE; \ + } + + +typedef enum { + V4L_PICTURE_HUE = 0, + V4L_PICTURE_BRIGHTNESS, + V4L_PICTURE_CONTRAST, + V4L_PICTURE_SATURATION, +} GstV4lPictureType; + +typedef enum { + V4L_AUDIO_VOLUME = 0, + V4L_AUDIO_MUTE, + V4L_AUDIO_MODE, /* stereo, mono, ... (see videodev.h) */ +} GstV4lAudioType; + + +/* open/close the device */ +gboolean gst_v4l_open (GstV4lElement *v4lelement); +gboolean gst_v4l_close (GstV4lElement *v4lelement); + +/* norm control (norm = VIDEO_MODE_{PAL|NTSC|SECAM|AUTO}) */ +gboolean gst_v4l_get_chan_norm (GstV4lElement *v4lelement, + gint *channel, + gint *norm); +gboolean gst_v4l_set_chan_norm (GstV4lElement *v4lelement, + gint channel, + gint norm); +GList *gst_v4l_get_chan_names (GstV4lElement *v4lelement); + +/* frequency control */ +gboolean gst_v4l_get_signal (GstV4lElement *v4lelement, + gint tunernum, + guint *signal); +gboolean gst_v4l_get_frequency (GstV4lElement *v4lelement, + gint tunernum, + gulong *frequency); +gboolean gst_v4l_set_frequency (GstV4lElement *v4lelement, + gint tunernum, + gulong frequency); + +/* picture control */ +gboolean gst_v4l_get_picture (GstV4lElement *v4lelement, + GstV4lPictureType type, + gint *value); +gboolean gst_v4l_set_picture (GstV4lElement *v4lelement, + GstV4lPictureType type, + gint value); + +/* audio control */ +gboolean gst_v4l_get_audio (GstV4lElement *v4lelement, + gint audionum, + GstV4lAudioType type, + gint *value); +gboolean gst_v4l_set_audio (GstV4lElement *v4lelement, + gint audionum, + GstV4lAudioType type, + gint value); + +/* functions that v4lsrc needs */ +gboolean gst_v4l_set_window_properties (GstV4lElement * v4lelement); +gboolean gst_v4l_get_capabilities (GstV4lElement * v4lelement); + + +G_END_DECLS + + +#endif /* __V4L_CALLS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.c b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.c new file mode 100644 index 0000000..416f80e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.c @@ -0,0 +1,525 @@ +/* GStreamer + * + * v4lmjpegsink_calls.c: functions for hardware MJPEG video sink + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "v4lmjpegsink_calls.h" + +/* On some systems MAP_FAILED seems to be missing */ +#ifndef MAP_FAILED +#define MAP_FAILED ( (caddr_t) -1 ) +#endif + +GST_DEBUG_CATEGORY_EXTERN (v4lmjpegsink_debug); +#define GST_CAT_DEFAULT v4lmjpegsink_debug + +/****************************************************** + * gst_v4lmjpegsink_sync_thread() + * thread keeps track of played frames + ******************************************************/ + +static void * +gst_v4lmjpegsink_sync_thread (void *arg) +{ + GstV4lMjpegSink *v4lmjpegsink = GST_V4LMJPEGSINK (arg); + gint frame = 0; /* frame that we're currently syncing on */ + + GST_DEBUG_OBJECT (v4lmjpegsink, "starting sync thread"); + +#if 0 + /* Allow easy shutting down by other processes... */ + pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL); + pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL); +#endif + + while (1) { + g_mutex_lock (v4lmjpegsink->mutex_queued_frames); + if (!v4lmjpegsink->isqueued_queued_frames[frame]) { + g_cond_wait (v4lmjpegsink->cond_queued_frames[frame], + v4lmjpegsink->mutex_queued_frames); + } + if (v4lmjpegsink->isqueued_queued_frames[frame] != 1) { + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + goto end; + } + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + + GST_DEBUG_OBJECT (v4lmjpegsink, "thread-syncing on next frame"); + if (ioctl (GST_V4LELEMENT (v4lmjpegsink)->video_fd, MJPIOC_SYNC, + &(v4lmjpegsink->bsync)) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, SYNC, (NULL), + ("Failed to sync on frame %d: %s", frame, g_strerror (errno))); + g_mutex_lock (v4lmjpegsink->mutex_queued_frames); + v4lmjpegsink->isqueued_queued_frames[frame] = -1; + g_cond_broadcast (v4lmjpegsink->cond_queued_frames[frame]); + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + goto end; + } else { + /* be sure that we're not confusing */ + if (frame != v4lmjpegsink->bsync.frame) { + GST_ELEMENT_ERROR (v4lmjpegsink, CORE, TOO_LAZY, (NULL), + ("Internal error: frame number confusion")); + goto end; + } + g_mutex_lock (v4lmjpegsink->mutex_queued_frames); + v4lmjpegsink->isqueued_queued_frames[frame] = 0; + g_cond_broadcast (v4lmjpegsink->cond_queued_frames[frame]); + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + } + + frame = (frame + 1) % v4lmjpegsink->breq.count; + } + +end: + GST_DEBUG_OBJECT (v4lmjpegsink, "Sync thread got signalled to exit"); + g_thread_exit (NULL); + return NULL; +} + + +/****************************************************** + * gst_v4lmjpegsink_queue_frame() + * queue a frame for playback + * return value: TRUE on success, FALSE on error + ******************************************************/ + +static gboolean +gst_v4lmjpegsink_queue_frame (GstV4lMjpegSink * v4lmjpegsink, gint num) +{ + GST_DEBUG_OBJECT (v4lmjpegsink, "queueing frame %d", num); + + /* queue on this frame */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsink)->video_fd, MJPIOC_QBUF_PLAY, + &num) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, WRITE, (NULL), + ("Failed to queue frame %d: %s", num, g_strerror (errno))); + return FALSE; + } + + g_mutex_lock (v4lmjpegsink->mutex_queued_frames); + v4lmjpegsink->isqueued_queued_frames[num] = 1; + g_cond_broadcast (v4lmjpegsink->cond_queued_frames[num]); + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_sync_frame() + * wait for a frame to be finished playing + * return value: TRUE on success, FALSE on error + ******************************************************/ + +static gboolean +gst_v4lmjpegsink_sync_frame (GstV4lMjpegSink * v4lmjpegsink, gint * num) +{ + GST_DEBUG_OBJECT (v4lmjpegsink, "syncing on next frame"); + + /* calculate next frame */ + v4lmjpegsink->current_frame = + (v4lmjpegsink->current_frame + 1) % v4lmjpegsink->breq.count; + *num = v4lmjpegsink->current_frame; + + g_mutex_lock (v4lmjpegsink->mutex_queued_frames); + if (v4lmjpegsink->isqueued_queued_frames[*num] == 1) { + g_cond_wait (v4lmjpegsink->cond_queued_frames[*num], + v4lmjpegsink->mutex_queued_frames); + } + if (v4lmjpegsink->isqueued_queued_frames[*num] != 0) { + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + return FALSE; + } else + g_mutex_unlock (v4lmjpegsink->mutex_queued_frames); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_set_buffer() + * set buffer options + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_set_buffer (GstV4lMjpegSink * v4lmjpegsink, + gint numbufs, gint bufsize) +{ + GST_DEBUG_OBJECT (v4lmjpegsink, + "setting buffer info to numbufs = %d, bufsize = %d KB", numbufs, bufsize); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + v4lmjpegsink->breq.size = bufsize * 1024; + v4lmjpegsink->breq.count = numbufs; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_set_playback() + * set playback options (video, interlacing, etc.) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_set_playback (GstV4lMjpegSink * v4lmjpegsink, + gint width, + gint height, gint x_offset, gint y_offset, gint norm, gint interlacing) +{ + gint mw, mh; + struct mjpeg_params bparm; + + GST_DEBUG_OBJECT (v4lmjpegsink, + "setting size=%dx%d, X/Y offsets=%d/%d, norm=%d, interlacing=%d\n", + width, height, x_offset, y_offset, norm, interlacing); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + /*GST_V4L_CHECK_NOT_ACTIVE(GST_V4LELEMENT(v4lmjpegsink)); */ + + if (ioctl (GST_V4LELEMENT (v4lmjpegsink)->video_fd, MJPIOC_G_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + bparm.input = 0; + bparm.norm = norm; + bparm.decimation = 0; /* we'll set proper values later on */ + + /* maxwidth is broken on marvel cards */ + mw = GST_V4LELEMENT (v4lmjpegsink)->vcap.maxwidth; + if (mw != 768 && mw != 640) + mw = 720; + mh = (norm == VIDEO_MODE_NTSC ? 480 : 576); + + if (width > mw || height > mh) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Video dimensions (%dx%d) are larger than device max (%dx%d)", + width, height, mw, mh)); + return FALSE; + } + + if (width <= mw / 4) + bparm.HorDcm = 4; + else if (width <= mw / 2) + bparm.HorDcm = 2; + else + bparm.HorDcm = 1; + + /* TODO: add proper interlacing handling */ +#if 0 + if (interlacing != INTERLACING_NOT_INTERLACED) { + bparm.field_per_buff = 2; + bparm.TmpDcm = 1; + + if (height <= mh / 2) + bparm.VerDcm = 2; + else + bparm.VerDcm = 1; + } else +#endif + { + if (height > mh / 2) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Video dimensions (%dx%d) too large for non-interlaced playback (%dx%d)", + width, height, mw, mh / 2)); + return FALSE; + } + + bparm.field_per_buff = 1; + bparm.TmpDcm = 2; + + if (height <= mh / 4) + bparm.VerDcm = 2; + else + bparm.VerDcm = 1; + } + + /* TODO: add proper interlacing handling */ +#if 0 + bparm.odd_even = (interlacing == INTERLACING_TOP_FIRST); +#endif + + bparm.quality = 100; + bparm.img_width = bparm.HorDcm * width; + bparm.img_height = bparm.VerDcm * height / bparm.field_per_buff; + + /* image X/Y offset on device */ + if (x_offset < 0) + bparm.img_x = (mw - bparm.img_width) / 2; + else { + if (x_offset + bparm.img_width > mw) + bparm.img_x = mw - bparm.img_width; + else + bparm.img_x = x_offset; + } + + if (y_offset < 0) + bparm.img_y = (mh / 2 - bparm.img_height) / 2; + else { + if (y_offset + bparm.img_height * 2 > mh) + bparm.img_y = mh / 2 - bparm.img_height; + else + bparm.img_y = y_offset / 2; + } + + if (ioctl (GST_V4LELEMENT (v4lmjpegsink)->video_fd, MJPIOC_S_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_playback_init() + * initialize playback system, set up buffer, etc. + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_playback_init (GstV4lMjpegSink * v4lmjpegsink) +{ + gint n; + + GST_DEBUG_OBJECT (v4lmjpegsink, "initting playback subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + /* Request buffers */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsink)->video_fd, MJPIOC_REQBUFS, + &(v4lmjpegsink->breq)) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + + GST_INFO_OBJECT (v4lmjpegsink, "Got %ld buffers of size %ld KB", + v4lmjpegsink->breq.count, v4lmjpegsink->breq.size / 1024); + + /* Map the buffers */ + GST_V4LELEMENT (v4lmjpegsink)->buffer = mmap (0, + v4lmjpegsink->breq.count * v4lmjpegsink->breq.size, + PROT_READ | PROT_WRITE, MAP_SHARED, + GST_V4LELEMENT (v4lmjpegsink)->video_fd, 0); + if (GST_V4LELEMENT (v4lmjpegsink)->buffer == MAP_FAILED) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Error mapping video buffers: %s", g_strerror (errno))); + GST_V4LELEMENT (v4lmjpegsink)->buffer = NULL; + return FALSE; + } + + /* allocate/init the GThread thingies */ + v4lmjpegsink->mutex_queued_frames = g_mutex_new (); + v4lmjpegsink->isqueued_queued_frames = (gint8 *) + malloc (sizeof (gint8) * v4lmjpegsink->breq.count); + if (!v4lmjpegsink->isqueued_queued_frames) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Failed to create queue tracker: %s", g_strerror (errno))); + return FALSE; + } + v4lmjpegsink->cond_queued_frames = (GCond **) + malloc (sizeof (GCond *) * v4lmjpegsink->breq.count); + if (!v4lmjpegsink->cond_queued_frames) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Failed to create queue condition holders: %s", g_strerror (errno))); + return FALSE; + } + for (n = 0; n < v4lmjpegsink->breq.count; n++) + v4lmjpegsink->cond_queued_frames[n] = g_cond_new (); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_playback_start() + * start playback system + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_playback_start (GstV4lMjpegSink * v4lmjpegsink) +{ + GError *error; + gint n; + + GST_DEBUG_OBJECT (v4lmjpegsink, "starting playback"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + /* mark all buffers as unqueued */ + for (n = 0; n < v4lmjpegsink->breq.count; n++) + v4lmjpegsink->isqueued_queued_frames[n] = 0; + + v4lmjpegsink->current_frame = -1; + + /* create sync() thread */ + v4lmjpegsink->thread_queued_frames = + g_thread_create (gst_v4lmjpegsink_sync_thread, (void *) v4lmjpegsink, + TRUE, &error); + if (!v4lmjpegsink->thread_queued_frames) { + GST_ELEMENT_ERROR (v4lmjpegsink, RESOURCE, TOO_LAZY, (NULL), + ("Failed to create sync thread: %s", error->message)); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_get_buffer() + * get address of a buffer + * return value: buffer's address or NULL + ******************************************************/ + +guint8 * +gst_v4lmjpegsink_get_buffer (GstV4lMjpegSink * v4lmjpegsink, gint num) +{ + /*GST_DEBUG_OBJECT (v4lmjpegsink, gst_v4lmjpegsink_get_buffer(), num = %d", num); */ + + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)) || + !GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsink))) + return NULL; + + if (num < 0 || num >= v4lmjpegsink->breq.count) + return NULL; + + return GST_V4LELEMENT (v4lmjpegsink)->buffer + + (v4lmjpegsink->breq.size * num); +} + + +/****************************************************** + * gst_v4lmjpegsink_play_frame() + * queue a new buffer + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_play_frame (GstV4lMjpegSink * v4lmjpegsink, gint num) +{ + GST_DEBUG_OBJECT (v4lmjpegsink, "playing frame %d", num); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + if (!gst_v4lmjpegsink_queue_frame (v4lmjpegsink, num)) + return FALSE; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_wait_frame() + * wait for buffer to be actually played + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_wait_frame (GstV4lMjpegSink * v4lmjpegsink, gint * num) +{ + GST_DEBUG_OBJECT (v4lmjpegsink, + "waiting for next frame to be finished playing"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + if (!gst_v4lmjpegsink_sync_frame (v4lmjpegsink, num)) + return FALSE; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_playback_stop() + * stop playback system and sync on remaining frames + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_playback_stop (GstV4lMjpegSink * v4lmjpegsink) +{ + gint num; + + GST_DEBUG_OBJECT (v4lmjpegsink, "stopping playback"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + /* mark next buffer as wrong */ + if (!gst_v4lmjpegsink_sync_frame (v4lmjpegsink, &num) || + !gst_v4lmjpegsink_queue_frame (v4lmjpegsink, num)) { + return FALSE; + } + + /* .. and wait for all buffers to be queued on */ + g_thread_join (v4lmjpegsink->thread_queued_frames); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsink_playback_deinit() + * deinitialize the playback system and unmap buffer + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsink_playback_deinit (GstV4lMjpegSink * v4lmjpegsink) +{ + int n; + + GST_DEBUG_OBJECT (v4lmjpegsink, "quitting playback subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsink)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsink)); + + /* free GThread thingies */ + g_mutex_free (v4lmjpegsink->mutex_queued_frames); + for (n = 0; n < v4lmjpegsink->breq.count; n++) + g_cond_free (v4lmjpegsink->cond_queued_frames[n]); + free (v4lmjpegsink->cond_queued_frames); + free (v4lmjpegsink->isqueued_queued_frames); + + /* unmap the buffer */ + munmap (GST_V4LELEMENT (v4lmjpegsink)->buffer, + v4lmjpegsink->breq.size * v4lmjpegsink->breq.count); + GST_V4LELEMENT (v4lmjpegsink)->buffer = NULL; + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.h b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.h new file mode 100644 index 0000000..beebaf4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsink_calls.h @@ -0,0 +1,62 @@ +/* GStreamer + * + * v4lmjpegsink_calls.c: functions for hardware MJPEG video sink + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __V4L_MJPEG_SINK_CALLS_H__ +#define __V4L_MJPEG_SINK_CALLS_H__ + +#include "gstv4lmjpegsink.h" +#include "v4l_calls.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* frame playback on device */ +gboolean gst_v4lmjpegsink_set_buffer (GstV4lMjpegSink *v4lmjpegsink, + gint numbufs, + gint bufsize); +gboolean gst_v4lmjpegsink_set_playback (GstV4lMjpegSink *v4lmjpegsink, + gint width, + gint height, + gint x_offset, + gint y_offset, + gint norm, + gint interlacing); +gboolean gst_v4lmjpegsink_playback_init (GstV4lMjpegSink *v4lmjpegsink); +gboolean gst_v4lmjpegsink_playback_start (GstV4lMjpegSink *v4lmjpegsink); +guint8 * gst_v4lmjpegsink_get_buffer (GstV4lMjpegSink *v4lmjpegsink, + gint num); +gboolean gst_v4lmjpegsink_play_frame (GstV4lMjpegSink *v4lmjpegsink, + gint num); +gboolean gst_v4lmjpegsink_wait_frame (GstV4lMjpegSink *v4lmjpegsink, + gint *num); +gboolean gst_v4lmjpegsink_playback_stop (GstV4lMjpegSink *v4lmjpegsink); +gboolean gst_v4lmjpegsink_playback_deinit (GstV4lMjpegSink *v4lmjpegsink); + + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __V4L_MJPEG_SINK_CALLS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.c b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.c new file mode 100644 index 0000000..60bdfce --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.c @@ -0,0 +1,577 @@ +/* GStreamer + * + * v4lmjpegsrc_calls.c: functions for hardware MJPEG video source + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "v4lmjpegsrc_calls.h" + +/* On some systems MAP_FAILED seems to be missing */ +#ifndef MAP_FAILED +#define MAP_FAILED ( (caddr_t) -1 ) +#endif + +#define MIN_BUFFERS_QUEUED 2 + +GST_DEBUG_CATEGORY_EXTERN (v4lmjpegsrc_debug); +#define GST_CAT_DEFAULT v4lmjpegsrc_debug + +enum +{ + QUEUE_STATE_ERROR = -1, + QUEUE_STATE_READY_FOR_QUEUE, + QUEUE_STATE_QUEUED, + QUEUE_STATE_SYNCED, +}; + +/****************************************************** + * gst_v4lmjpegsrc_queue_frame(): + * queue a frame for capturing + * return value: TRUE on success, FALSE on error + ******************************************************/ + +static gboolean +gst_v4lmjpegsrc_queue_frame (GstV4lMjpegSrc * v4lmjpegsrc, gint num) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "queueing frame %d", num); + + if (v4lmjpegsrc->frame_queue_state[num] != QUEUE_STATE_READY_FOR_QUEUE) { + return FALSE; + } + + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, MJPIOC_QBUF_CAPT, + &num) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, (NULL), + ("Error queueing a buffer (%d): %s", num, g_strerror (errno))); + return FALSE; + } + + v4lmjpegsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED; + v4lmjpegsrc->num_queued++; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_sync_next_frame(): + * sync on the next frame for capturing + * return value: TRUE on success, FALSE on error + ******************************************************/ + +static gboolean +gst_v4lmjpegsrc_sync_next_frame (GstV4lMjpegSrc * v4lmjpegsrc, gint * num) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "syncing on next frame"); + + if (v4lmjpegsrc->num_queued <= 0) { + return FALSE; + } + + while (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, + MJPIOC_SYNC, &(v4lmjpegsrc->bsync)) < 0) { + if (errno != EINTR) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + GST_DEBUG_OBJECT (v4lmjpegsrc, "Sync got interrupted"); + } + + *num = v4lmjpegsrc->bsync.frame; + + v4lmjpegsrc->frame_queue_state[*num] = QUEUE_STATE_SYNCED; + v4lmjpegsrc->num_queued--; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_set_buffer(): + * set buffer parameters (size/count) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_set_buffer (GstV4lMjpegSrc * v4lmjpegsrc, + gint numbufs, gint bufsize) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, + "setting buffer info to numbufs = %d, bufsize = %d KB", numbufs, bufsize); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + v4lmjpegsrc->breq.size = bufsize * 1024; + v4lmjpegsrc->breq.count = numbufs; + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_set_capture(): + * set capture parameters (simple) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_set_capture (GstV4lMjpegSrc * v4lmjpegsrc, + gint decimation, gint quality) +{ + int norm, input, mw; + struct mjpeg_params bparm; + + GST_DEBUG_OBJECT (v4lmjpegsrc, "setting decimation = %d, quality = %d", + decimation, quality); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lmjpegsrc), &input, &norm); + + /* Query params for capture */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, MJPIOC_G_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + bparm.decimation = decimation; + bparm.quality = quality; + bparm.norm = norm; + bparm.input = input; + bparm.APP_len = 0; /* no JPEG markers - TODO: this is definately not right for decimation==1 */ + + mw = GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxwidth; + if (mw != 768 && mw != 640) { + if (decimation == 1) + mw = 720; + else + mw = 704; + } + v4lmjpegsrc->end_width = mw / decimation; + v4lmjpegsrc->end_height = (norm == VIDEO_MODE_NTSC ? 480 : 576) / decimation; + + /* TODO: interlacing */ + + /* Set params for capture */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, MJPIOC_S_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_set_capture_m(): + * set capture parameters (advanced) + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_set_capture_m (GstV4lMjpegSrc * v4lmjpegsrc, + gint x_offset, + gint y_offset, + gint width, gint height, gint h_decimation, gint v_decimation, gint quality) +{ + gint norm, input; + gint maxwidth; + struct mjpeg_params bparm; + + GST_DEBUG_OBJECT (v4lmjpegsrc, "setting x_offset = %d, y_offset = %d, " + "width = %d, height = %d, h_decimation = %d, v_decimation = %d, quality = %d\n", + x_offset, y_offset, width, height, h_decimation, v_decimation, quality); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lmjpegsrc), &input, &norm); + + if (GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxwidth != 768 && + GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxwidth != 640) + maxwidth = 720; + else + maxwidth = GST_V4LELEMENT (v4lmjpegsrc)->vcap.maxwidth; + + /* Query params for capture */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, MJPIOC_G_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + bparm.decimation = 0; + bparm.quality = quality; + bparm.norm = norm; + bparm.input = input; + bparm.APP_len = 0; /* no JPEG markers - TODO: this is definately + * not right for decimation==1 */ + + if (width <= 0) { + if (x_offset < 0) + x_offset = 0; + width = (maxwidth == 720 + && h_decimation != 1) ? 704 : maxwidth - 2 * x_offset; + } else { + if (x_offset < 0) + x_offset = (maxwidth - width) / 2; + } + + if (height <= 0) { + if (y_offset < 0) + y_offset = 0; + height = (norm == VIDEO_MODE_NTSC) ? 480 : 576 - 2 * y_offset; + } else { + if (y_offset < 0) + y_offset = ((norm == VIDEO_MODE_NTSC) ? 480 : 576 - height) / 2; + } + + if (width + x_offset > maxwidth) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, (NULL), + ("Image width+offset (%d) bigger than maximum (%d)", + width + x_offset, maxwidth)); + return FALSE; + } + if ((width % (bparm.HorDcm * 16)) != 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, STREAM, FORMAT, (NULL), + ("Image width (%d) not multiple of %d (required for JPEG)", + width, bparm.HorDcm * 16)); + return FALSE; + } + if (height + y_offset > (norm == VIDEO_MODE_NTSC ? 480 : 576)) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, (NULL), + ("Image height+offset (%d) bigger than maximum (%d)", + height + y_offset, (norm == VIDEO_MODE_NTSC ? 480 : 576))); + return FALSE; + } + /* RJ: Image height must only be a multiple of 8, but geom_height + * is double the field height + */ + if ((height % (bparm.VerDcm * 16)) != 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, STREAM, FORMAT, (NULL), + ("Image height (%d) not multiple of %d (required for JPEG)", + height, bparm.VerDcm * 16)); + return FALSE; + } + + bparm.img_x = x_offset; + bparm.img_width = width; + bparm.img_y = y_offset; + bparm.img_height = height; + bparm.HorDcm = h_decimation; + bparm.VerDcm = (v_decimation == 4) ? 2 : 1; + bparm.TmpDcm = (v_decimation == 1) ? 1 : 2; + bparm.field_per_buff = (v_decimation == 1) ? 2 : 1; + + v4lmjpegsrc->end_width = width / h_decimation; + v4lmjpegsrc->end_width = height / v_decimation; + + /* TODO: interlacing */ + + /* Set params for capture */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, MJPIOC_S_PARAMS, + &bparm) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, SETTINGS, (NULL), + GST_ERROR_SYSTEM); + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_capture_init(): + * initialize the capture system + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_capture_init (GstV4lMjpegSrc * v4lmjpegsrc) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "initting capture subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + /* Request buffers */ + if (ioctl (GST_V4LELEMENT (v4lmjpegsrc)->video_fd, + MJPIOC_REQBUFS, &(v4lmjpegsrc->breq)) < 0) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + + if (v4lmjpegsrc->breq.count < MIN_BUFFERS_QUEUED) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, READ, (NULL), + ("Too little buffers. We got %ld, we want at least %d", + v4lmjpegsrc->breq.count, MIN_BUFFERS_QUEUED)); + return FALSE; + } + + GST_INFO_OBJECT (v4lmjpegsrc, "Got %ld buffers of size %ld KB", + v4lmjpegsrc->breq.count, v4lmjpegsrc->breq.size / 1024); + + /* keep track of queued buffers */ + v4lmjpegsrc->frame_queue_state = (gint8 *) + g_malloc (sizeof (gint8) * v4lmjpegsrc->breq.count); + + /* track how often to use each frame */ + v4lmjpegsrc->use_num_times = (gint *) + g_malloc (sizeof (gint) * v4lmjpegsrc->breq.count); + + /* lock for the frame_state */ + v4lmjpegsrc->mutex_queue_state = g_mutex_new (); + v4lmjpegsrc->cond_queue_state = g_cond_new (); + + /* Map the buffers */ + GST_V4LELEMENT (v4lmjpegsrc)->buffer = mmap (0, + v4lmjpegsrc->breq.count * v4lmjpegsrc->breq.size, + PROT_READ | PROT_WRITE, MAP_SHARED, + GST_V4LELEMENT (v4lmjpegsrc)->video_fd, 0); + if (GST_V4LELEMENT (v4lmjpegsrc)->buffer == MAP_FAILED) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, (NULL), + ("Error mapping video buffers: %s", g_strerror (errno))); + GST_V4LELEMENT (v4lmjpegsrc)->buffer = NULL; + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_capture_start(): + * start streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_capture_start (GstV4lMjpegSrc * v4lmjpegsrc) +{ + int n; + + GST_DEBUG_OBJECT (v4lmjpegsrc, "starting capture"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + g_mutex_lock (v4lmjpegsrc->mutex_queue_state); + + v4lmjpegsrc->quit = FALSE; + v4lmjpegsrc->num_queued = 0; + v4lmjpegsrc->queue_frame = 0; + + /* set all buffers ready to queue , this starts streaming capture */ + for (n = 0; n < v4lmjpegsrc->breq.count; n++) { + v4lmjpegsrc->frame_queue_state[n] = QUEUE_STATE_READY_FOR_QUEUE; + if (!gst_v4lmjpegsrc_queue_frame (v4lmjpegsrc, n)) { + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + gst_v4lmjpegsrc_capture_stop (v4lmjpegsrc); + return FALSE; + } + } + + v4lmjpegsrc->is_capturing = TRUE; + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_grab_frame(): + * grab one frame during streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_grab_frame (GstV4lMjpegSrc * v4lmjpegsrc, + gint * num, gint * size) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "grabbing frame"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + g_mutex_lock (v4lmjpegsrc->mutex_queue_state); + + /* do we have enough frames? */ + while (v4lmjpegsrc->num_queued < MIN_BUFFERS_QUEUED || + v4lmjpegsrc->frame_queue_state[v4lmjpegsrc->queue_frame] == + QUEUE_STATE_READY_FOR_QUEUE) { + while (v4lmjpegsrc->frame_queue_state[v4lmjpegsrc->queue_frame] != + QUEUE_STATE_READY_FOR_QUEUE && !v4lmjpegsrc->quit) { + GST_DEBUG_OBJECT (v4lmjpegsrc, + "Waiting for frames to become available (%d < %d)", + v4lmjpegsrc->num_queued, MIN_BUFFERS_QUEUED); + g_cond_wait (v4lmjpegsrc->cond_queue_state, + v4lmjpegsrc->mutex_queue_state); + } + if (v4lmjpegsrc->quit) { + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + return TRUE; /* it won't get through anyway */ + } + if (!gst_v4lmjpegsrc_queue_frame (v4lmjpegsrc, v4lmjpegsrc->queue_frame)) { + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + return FALSE; + } + v4lmjpegsrc->queue_frame = + (v4lmjpegsrc->queue_frame + 1) % v4lmjpegsrc->breq.count; + } + + /* syncing on the buffer grabs it */ + if (!gst_v4lmjpegsrc_sync_next_frame (v4lmjpegsrc, num)) { + return FALSE; + } + + *size = v4lmjpegsrc->bsync.length; + + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_get_buffer(): + * get the memory address of a single buffer + * return value: TRUE on success, FALSE on error + ******************************************************/ + +guint8 * +gst_v4lmjpegsrc_get_buffer (GstV4lMjpegSrc * v4lmjpegsrc, gint num) +{ + /*DEBUG("gst_v4lmjpegsrc_get_buffer(), num = %d", num); */ + + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)) || + !GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lmjpegsrc))) + return NULL; + + if (num < 0 || num >= v4lmjpegsrc->breq.count) + return NULL; + + return GST_V4LELEMENT (v4lmjpegsrc)->buffer + (v4lmjpegsrc->breq.size * num); +} + + +/****************************************************** + * gst_v4lmjpegsrc_requeue_frame(): + * requeue a frame for capturing + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_requeue_frame (GstV4lMjpegSrc * v4lmjpegsrc, gint num) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "requeueing frame %d", num); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + /* mark frame as 'ready to requeue' */ + g_mutex_lock (v4lmjpegsrc->mutex_queue_state); + + if (v4lmjpegsrc->frame_queue_state[num] != QUEUE_STATE_SYNCED) { + GST_ELEMENT_ERROR (v4lmjpegsrc, RESOURCE, TOO_LAZY, (NULL), + ("Invalid state %d (expected %d), can't requeue", + v4lmjpegsrc->frame_queue_state[num], QUEUE_STATE_SYNCED)); + return FALSE; + } + + v4lmjpegsrc->frame_queue_state[num] = QUEUE_STATE_READY_FOR_QUEUE; + + /* let an optional wait know */ + g_cond_broadcast (v4lmjpegsrc->cond_queue_state); + + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_capture_stop(): + * stop streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_capture_stop (GstV4lMjpegSrc * v4lmjpegsrc) +{ + int n; + + GST_DEBUG_OBJECT (v4lmjpegsrc, "stopping capture"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + g_mutex_lock (v4lmjpegsrc->mutex_queue_state); + + /* make an optional pending wait stop */ + v4lmjpegsrc->quit = TRUE; + g_cond_broadcast (v4lmjpegsrc->cond_queue_state); + + /* sync on remaining frames */ + while (v4lmjpegsrc->num_queued > 0) { + gst_v4lmjpegsrc_sync_next_frame (v4lmjpegsrc, &n); + } + + v4lmjpegsrc->is_capturing = FALSE; + g_mutex_unlock (v4lmjpegsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lmjpegsrc_capture_deinit(): + * deinitialize the capture system + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lmjpegsrc_capture_deinit (GstV4lMjpegSrc * v4lmjpegsrc) +{ + GST_DEBUG_OBJECT (v4lmjpegsrc, "quitting capture subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lmjpegsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lmjpegsrc)); + + /* unmap the buffer */ + munmap (GST_V4LELEMENT (v4lmjpegsrc)->buffer, + v4lmjpegsrc->breq.size * v4lmjpegsrc->breq.count); + GST_V4LELEMENT (v4lmjpegsrc)->buffer = NULL; + + /* free buffer tracker */ + g_mutex_free (v4lmjpegsrc->mutex_queue_state); + g_cond_free (v4lmjpegsrc->cond_queue_state); + g_free (v4lmjpegsrc->frame_queue_state); + g_free (v4lmjpegsrc->use_num_times); + + return TRUE; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.h b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.h new file mode 100644 index 0000000..e873ea0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lmjpegsrc_calls.h @@ -0,0 +1,66 @@ +/* GStreamer + * + * v4lmjpegsrc_calls.h: functions for hardware MJPEG video source + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __V4L_MJPEG_SRC_CALLS_H__ +#define __V4L_MJPEG_SRC_CALLS_H__ + +#include "gstv4lmjpegsrc.h" +#include "v4l_calls.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +/* frame grabbing/capture */ +gboolean gst_v4lmjpegsrc_set_buffer (GstV4lMjpegSrc *v4lmjpegsrc, + gint numbufs, + gint bufsize); +gboolean gst_v4lmjpegsrc_set_capture (GstV4lMjpegSrc *v4lmjpegsrc, + gint decimation, + gint quality); +gboolean gst_v4lmjpegsrc_set_capture_m (GstV4lMjpegSrc *v4lmjpegsrc, + gint x_offset, + gint y_offset, + gint width, + gint height, + gint h_decimation, + gint v_decimation, + gint quality); +gboolean gst_v4lmjpegsrc_capture_init (GstV4lMjpegSrc *v4lmjpegsrc); +gboolean gst_v4lmjpegsrc_capture_start (GstV4lMjpegSrc *v4lmjpegsrc); +gboolean gst_v4lmjpegsrc_grab_frame (GstV4lMjpegSrc *v4lmjpegsrc, + gint *num, + gint *size); +guint8 * gst_v4lmjpegsrc_get_buffer (GstV4lMjpegSrc *v4lmjpegsrc, + gint num); +gboolean gst_v4lmjpegsrc_requeue_frame (GstV4lMjpegSrc *v4lmjpegsrc, + gint num); +gboolean gst_v4lmjpegsrc_capture_stop (GstV4lMjpegSrc *v4lmjpegsrc); +gboolean gst_v4lmjpegsrc_capture_deinit (GstV4lMjpegSrc *v4lmjpegsrc); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __V4L_MJPEG_SRC_CALLS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.c b/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.c new file mode 100644 index 0000000..31bd6de --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.c @@ -0,0 +1,764 @@ +/* GStreamer + * + * v4lsrc_calls.c: generic V4L source functions + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include "v4lsrc_calls.h" +#include + +/* number of buffers to be queued *at least* before syncing */ +#define MIN_BUFFERS_QUEUED 2 + +/* On some systems MAP_FAILED seems to be missing */ +#ifndef MAP_FAILED +#define MAP_FAILED ( (caddr_t) -1 ) +#endif + +GST_DEBUG_CATEGORY_EXTERN (v4l_debug); + +#define GST_CAT_DEFAULT v4l_debug + +#ifndef GST_DISABLE_GST_DEBUG +/* palette names */ +static const char *v4l_palette_name[] = { + "", /* 0 */ + "grayscale", /* VIDEO_PALETTE_GREY */ + "Hi-420", /* VIDEO_PALETTE_HI420 */ + "16-bit RGB (RGB-565)", /* VIDEO_PALETTE_RB565 */ + "24-bit RGB", /* VIDEO_PALETTE_RGB24 */ + "32-bit RGB", /* VIDEO_PALETTE_RGB32 */ + "15-bit RGB (RGB-555)", /* VIDEO_PALETTE_RGB555 */ + "YUV-4:2:2 (packed)", /* VIDEO_PALETTE_YUV422 */ + "YUYV", /* VIDEO_PALETTE_YUYV */ + "UYVY", /* VIDEO_PALETTE_UYVY */ + "YUV-4:2:0 (packed)", /* VIDEO_PALETTE_YUV420 */ + "YUV-4:1:1 (packed)", /* VIDEO_PALETTE_YUV411 */ + "Raw", /* VIDEO_PALETTE_RAW */ + "YUV-4:2:2 (planar)", /* VIDEO_PALETTE_YUV422P */ + "YUV-4:1:1 (planar)", /* VIDEO_PALETTE_YUV411P */ + "YUV-4:2:0 (planar)/I420", /* VIDEO_PALETTE_YUV420P */ + "YUV-4:1:0 (planar)" /* VIDEO_PALETTE_YUV410P */ +}; +#endif + +/****************************************************** + * gst_v4lsrc_queue_frame(): + * queue a frame for capturing + * (ie. instruct the hardware to start capture) + * Requires queue_state lock to be held! + * return value: TRUE on success, FALSE on error + ******************************************************/ + +static gboolean +gst_v4lsrc_queue_frame (GstV4lSrc * v4lsrc, gint num) +{ + GST_LOG_OBJECT (v4lsrc, "queueing frame %d", num); + + if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_READY_FOR_QUEUE) { + return FALSE; + } + + /* instruct the driver to prepare capture using buffer frame num */ + v4lsrc->mmap.frame = num; + if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, + VIDIOCMCAPTURE, &(v4lsrc->mmap)) < 0) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, WRITE, (NULL), + ("Error queueing a buffer (%d): %s", num, g_strerror (errno))); + return FALSE; + } + + v4lsrc->frame_queue_state[num] = QUEUE_STATE_QUEUED; + v4lsrc->num_queued++; + + return TRUE; +} + +/****************************************************** + * gst_v4lsrc_hard_sync_frame(GstV4lSrc *v4lsrc,gint num) + * sync a frame and set the timestamp correctly + * Requires queue_state lock to be held + *****************************************************/ + +static gboolean +gst_v4lsrc_sync_frame (GstV4lSrc * v4lsrc, gint num) +{ + GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d", num); + + if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_QUEUED) { + return FALSE; + } + + while (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &num) < 0) { + /* if the sync() got interrupted, we can retry */ + if (errno != EINTR) { + v4lsrc->frame_queue_state[num] = QUEUE_STATE_ERROR; + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM); + return FALSE; + } + GST_DEBUG_OBJECT (v4lsrc, "Sync got interrupted"); + } + GST_LOG_OBJECT (v4lsrc, "VIOIOCSYNC on frame %d done", num); + + v4lsrc->frame_queue_state[num] = QUEUE_STATE_SYNCED; + v4lsrc->num_queued--; + + return TRUE; +} + +/****************************************************** + * gst_v4lsrc_set_capture(): + * set capture parameters, palette = VIDEO_PALETTE_* + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_set_capture (GstV4lSrc * v4lsrc, + gint width, gint height, gint palette) +{ + GST_DEBUG_OBJECT (v4lsrc, + "capture properties set to %dx%d, palette %d", width, height, palette); + + v4lsrc->mmap.width = width; + v4lsrc->mmap.height = height; + v4lsrc->mmap.format = palette; + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_capture_init(): + * initialize the capture system + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_capture_init (GstV4lSrc * v4lsrc) +{ + GST_DEBUG_OBJECT (v4lsrc, "initting capture subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + /* request the mmap buffer info: + * total size of mmap buffer, number of frames, offsets of frames */ + if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF, + &(v4lsrc->mbuf)) < 0) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL), + ("Error getting buffer information: %s", g_strerror (errno))); + return FALSE; + } + + if (v4lsrc->mbuf.frames < MIN_BUFFERS_QUEUED) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL), + ("Not enough buffers. We got %d, we want at least %d", + v4lsrc->mbuf.frames, MIN_BUFFERS_QUEUED)); + return FALSE; + } + + GST_INFO_OBJECT (v4lsrc, "Got %d buffers (\'%s\') with total size %d KB", + v4lsrc->mbuf.frames, v4l_palette_name[v4lsrc->mmap.format], + v4lsrc->mbuf.size / (v4lsrc->mbuf.frames * 1024)); + + /* keep track of queued buffers */ + v4lsrc->frame_queue_state = (gint8 *) + g_malloc (sizeof (gint8) * v4lsrc->mbuf.frames); + + /* lock for the frame_state */ + v4lsrc->mutex_queue_state = g_mutex_new (); + v4lsrc->cond_queue_state = g_cond_new (); + + /* Map the buffers */ + GST_V4LELEMENT (v4lsrc)->buffer = mmap (NULL, v4lsrc->mbuf.size, + PROT_READ | PROT_WRITE, MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0); + if (GST_V4LELEMENT (v4lsrc)->buffer == MAP_FAILED) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL), + ("Error mapping video buffers: %s", g_strerror (errno))); + GST_V4LELEMENT (v4lsrc)->buffer = NULL; + return FALSE; + } + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_capture_start(): + * start streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_capture_start (GstV4lSrc * v4lsrc) +{ + int n; + + GST_DEBUG_OBJECT (v4lsrc, "starting capture"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + g_mutex_lock (v4lsrc->mutex_queue_state); + + v4lsrc->quit = FALSE; + v4lsrc->num_queued = 0; + v4lsrc->sync_frame = 0; + v4lsrc->queue_frame = 0; + + /* set all buffers ready to queue, and queue captures to the device. + * This starts streaming capture */ + for (n = 0; n < v4lsrc->mbuf.frames; n++) { + v4lsrc->frame_queue_state[n] = QUEUE_STATE_READY_FOR_QUEUE; + if (!gst_v4lsrc_queue_frame (v4lsrc, n)) { + g_mutex_unlock (v4lsrc->mutex_queue_state); + gst_v4lsrc_capture_stop (v4lsrc); + return FALSE; + } + } + + v4lsrc->is_capturing = TRUE; + g_mutex_unlock (v4lsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_grab_frame(): + * capture one frame during streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_grab_frame (GstV4lSrc * v4lsrc, gint * num) +{ + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + GST_LOG_OBJECT (v4lsrc, "grabbing frame"); + + g_mutex_lock (v4lsrc->mutex_queue_state); + + /* do we have enough frames? */ + while (v4lsrc->num_queued < MIN_BUFFERS_QUEUED || + v4lsrc->frame_queue_state[v4lsrc->queue_frame] == + QUEUE_STATE_READY_FOR_QUEUE) { + while (v4lsrc->frame_queue_state[v4lsrc->queue_frame] != + QUEUE_STATE_READY_FOR_QUEUE && !v4lsrc->quit) { + GST_DEBUG_OBJECT (v4lsrc, + "Waiting for frames to become available (queued %d < minimum %d)", + v4lsrc->num_queued, MIN_BUFFERS_QUEUED); + g_cond_wait (v4lsrc->cond_queue_state, v4lsrc->mutex_queue_state); + } + if (v4lsrc->quit) { + g_mutex_unlock (v4lsrc->mutex_queue_state); + return FALSE; + } + if (!gst_v4lsrc_queue_frame (v4lsrc, v4lsrc->queue_frame)) { + g_mutex_unlock (v4lsrc->mutex_queue_state); + return FALSE; + } + v4lsrc->queue_frame = (v4lsrc->queue_frame + 1) % v4lsrc->mbuf.frames; + } + + /* syncing on the buffer grabs it */ + *num = v4lsrc->sync_frame; + if (!gst_v4lsrc_sync_frame (v4lsrc, *num)) { + g_mutex_unlock (v4lsrc->mutex_queue_state); + return FALSE; + } + v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames; + + g_mutex_unlock (v4lsrc->mutex_queue_state); + + GST_LOG_OBJECT (v4lsrc, "grabbed frame %d", *num); + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_get_buffer(): + * get the address of the given frame number in the mmap'd buffer + * return value: the buffer's address or NULL + ******************************************************/ + +guint8 * +gst_v4lsrc_get_buffer (GstV4lSrc * v4lsrc, gint num) +{ + if (!GST_V4L_IS_ACTIVE (GST_V4LELEMENT (v4lsrc)) || + !GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) + return NULL; + + if (num < 0 || num >= v4lsrc->mbuf.frames) + return NULL; + + return GST_V4LELEMENT (v4lsrc)->buffer + v4lsrc->mbuf.offsets[num]; +} + + +/****************************************************** + * gst_v4lsrc_requeue_frame(): + * re-queue a frame after we're done with the buffer + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_requeue_frame (GstV4lSrc * v4lsrc, gint num) +{ + GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + /* mark frame as 'ready to requeue' */ + g_mutex_lock (v4lsrc->mutex_queue_state); + + if (v4lsrc->frame_queue_state[num] != QUEUE_STATE_SYNCED) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, TOO_LAZY, (NULL), + ("Invalid state %d (expected %d), can't requeue", + v4lsrc->frame_queue_state[num], QUEUE_STATE_SYNCED)); + return FALSE; + } + + v4lsrc->frame_queue_state[num] = QUEUE_STATE_READY_FOR_QUEUE; + + /* let an optional wait know */ + g_cond_broadcast (v4lsrc->cond_queue_state); + + g_mutex_unlock (v4lsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_capture_stop(): + * stop streaming capture + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_capture_stop (GstV4lSrc * v4lsrc) +{ + GST_DEBUG_OBJECT (v4lsrc, "stopping capture"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + g_mutex_lock (v4lsrc->mutex_queue_state); + v4lsrc->is_capturing = FALSE; + + /* make an optional pending wait stop */ + v4lsrc->quit = TRUE; + g_cond_broadcast (v4lsrc->cond_queue_state); + + /* sync on remaining frames */ + while (1) { + if (v4lsrc->frame_queue_state[v4lsrc->sync_frame] == QUEUE_STATE_QUEUED) { + gst_v4lsrc_sync_frame (v4lsrc, v4lsrc->sync_frame); + v4lsrc->sync_frame = (v4lsrc->sync_frame + 1) % v4lsrc->mbuf.frames; + } else { + break; + } + } + + g_mutex_unlock (v4lsrc->mutex_queue_state); + + return TRUE; +} + + +/****************************************************** + * gst_v4lsrc_capture_deinit(): + * deinitialize the capture system + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_capture_deinit (GstV4lSrc * v4lsrc) +{ + GST_DEBUG_OBJECT (v4lsrc, "quitting capture subsystem"); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + /* free buffer tracker */ + g_mutex_free (v4lsrc->mutex_queue_state); + v4lsrc->mutex_queue_state = NULL; + g_cond_free (v4lsrc->cond_queue_state); + v4lsrc->cond_queue_state = NULL; + g_free (v4lsrc->frame_queue_state); + v4lsrc->frame_queue_state = NULL; + + /* unmap the buffer */ + if (munmap (GST_V4LELEMENT (v4lsrc)->buffer, v4lsrc->mbuf.size) == -1) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, CLOSE, (NULL), + ("error munmap'ing capture buffer: %s", g_strerror (errno))); + return FALSE; + } + GST_V4LELEMENT (v4lsrc)->buffer = NULL; + + return TRUE; +} + +/****************************************************** + * gst_v4lsrc_try_capture(): + * try out a capture on the device + * This has to be done before initializing the + * actual capture system, to make sure we don't + * mess up anything. So we need to mini-mmap() + * a buffer here, queue and sync on one buffer, + * and unmap it. + * This is ugly, yes, I know - but it's a major + * design flaw of v4l1 that you don't know in + * advance which formats will be supported... + * This is better than "just assuming that it'll + * work"... + * return value: TRUE on success, FALSE on error + ******************************************************/ + +gboolean +gst_v4lsrc_try_capture (GstV4lSrc * v4lsrc, gint width, gint height, + gint palette) +{ + /* so, we need a buffer and some more stuff */ + int frame = 0; + guint8 *buffer; + struct video_mbuf vmbuf; + struct video_mmap vmmap; + + GST_DEBUG_OBJECT (v4lsrc, "try out %dx%d, palette format %d (%s)", + width, height, palette, v4l_palette_name[palette]); + GST_V4L_CHECK_OPEN (GST_V4LELEMENT (v4lsrc)); + GST_V4L_CHECK_NOT_ACTIVE (GST_V4LELEMENT (v4lsrc)); + + /* let's start by requesting a buffer and mmap()'ing it */ + if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCGMBUF, &vmbuf) < 0) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, READ, (NULL), + ("Error getting buffer information: %s", g_strerror (errno))); + return FALSE; + } + /* Map the buffers */ + buffer = mmap (NULL, vmbuf.size, PROT_READ | PROT_WRITE, + MAP_SHARED, GST_V4LELEMENT (v4lsrc)->video_fd, 0); + if (buffer == MAP_FAILED) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, OPEN_READ_WRITE, (NULL), + ("Error mapping our try-out buffer: %s", g_strerror (errno))); + return FALSE; + } + + /* now that we have a buffer, let's try out our format */ + vmmap.width = width; + vmmap.height = height; + vmmap.format = palette; + vmmap.frame = frame; + if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCMCAPTURE, &vmmap) < 0) { + if (errno != EINVAL) /* our format failed! */ + GST_ERROR_OBJECT (v4lsrc, + "Error queueing our try-out buffer: %s", g_strerror (errno)); + munmap (buffer, vmbuf.size); + return FALSE; + } + + if (ioctl (GST_V4LELEMENT (v4lsrc)->video_fd, VIDIOCSYNC, &frame) < 0) { + GST_ELEMENT_ERROR (v4lsrc, RESOURCE, SYNC, (NULL), GST_ERROR_SYSTEM); + munmap (buffer, vmbuf.size); + return FALSE; + } + + munmap (buffer, vmbuf.size); + + /* if we got here, it worked! woohoo, the format is supported! */ + return TRUE; +} + +#ifndef GST_DISABLE_GST_DEBUG +const char * +gst_v4lsrc_palette_name (int i) +{ + return v4l_palette_name[i]; +} +#endif + +gboolean +gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, gint * fps_n, gint * fps_d) +{ + gint norm; + gint fps_index; + struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin; + + /* check if we have vwin window properties giving a framerate, + * as is done for webcams + * See http://www.smcc.demon.nl/webcam/api.html + * which is used for the Philips and qce-ga drivers */ + fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */ + + /* webcams have a non-zero fps_index */ + if (fps_index != 0) { + /* index of 16 corresponds to 15 fps */ + GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)", + fps_index * 15, 16, fps_index * 15.0 / 16); + + if (fps_n) + *fps_n = fps_index * 15; + if (fps_d) + *fps_d = 16; + + return TRUE; + } + + /* removed fps estimation code here */ + + /* if that failed ... */ + + if (!GST_V4L_IS_OPEN (GST_V4LELEMENT (v4lsrc))) + return FALSE; + + if (!gst_v4l_get_chan_norm (GST_V4LELEMENT (v4lsrc), NULL, &norm)) + return FALSE; + + if (norm == VIDEO_MODE_NTSC) { + if (fps_n) + *fps_n = 30000; + if (fps_d) + *fps_d = 1001; + } else { + if (fps_n) + *fps_n = 25; + if (fps_d) + *fps_d = 1; + } + + return TRUE; +} + +/* get a list of possible framerates + * this is only done for webcams; + * other devices return NULL here. + * this function takes a LONG time to execute. + */ +GValue * +gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc) +{ + gint fps_index; + struct video_window *vwin = &GST_V4LELEMENT (v4lsrc)->vwin; + GstV4lElement *v4lelement = GST_V4LELEMENT (v4lsrc); + + /* check if we have vwin window properties giving a framerate, + * as is done for webcams + * See http://www.smcc.demon.nl/webcam/api.html + * which is used for the Philips and qce-ga drivers */ + fps_index = (vwin->flags >> 16) & 0x3F; /* 6 bit index for framerate */ + + /* webcams have a non-zero fps_index */ + if (fps_index == 0) { + GST_DEBUG_OBJECT (v4lsrc, "fps_index is 0, no webcam"); + return NULL; + } + GST_DEBUG_OBJECT (v4lsrc, "fps_index is %d, so webcam", fps_index); + + { + int i; + GValue *list = NULL; + GValue value = { 0 }; + + /* webcam detected, so try all framerates and return a list */ + + list = g_new0 (GValue, 1); + g_value_init (list, GST_TYPE_LIST); + + /* index of 16 corresponds to 15 fps */ + GST_DEBUG_OBJECT (v4lsrc, "device reports fps of %d/%d (%.4f)", + fps_index * 15, 16, fps_index * 15.0 / 16); + for (i = 0; i < 63; ++i) { + /* set bits 16 to 21 to 0 */ + vwin->flags &= (0x3F00 - 1); + /* set bits 16 to 21 to the index */ + vwin->flags |= i << 16; + if (gst_v4l_set_window_properties (v4lelement)) { + /* setting it succeeded. FIXME: get it and check. */ + g_value_init (&value, GST_TYPE_FRACTION); + gst_value_set_fraction (&value, i * 15, 16); + gst_value_list_append_value (list, &value); + g_value_unset (&value); + } + } + /* FIXME: set back the original fps_index */ + vwin->flags &= (0x3F00 - 1); + vwin->flags |= fps_index << 16; + gst_v4l_set_window_properties (v4lelement); + return list; + } +} + +#define GST_TYPE_V4LSRC_BUFFER (gst_v4lsrc_buffer_get_type()) +#define GST_IS_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_V4LSRC_BUFFER)) +#define GST_V4LSRC_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4LSRC_BUFFER, GstV4lSrcBuffer)) + +typedef struct _GstV4lSrcBuffer +{ + GstBuffer buffer; + + GstV4lSrc *v4lsrc; + + gint num; +} GstV4lSrcBuffer; + +static void gst_v4lsrc_buffer_class_init (gpointer g_class, + gpointer class_data); +static void gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class); +static void gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer); + +static GstBufferClass *v4lbuffer_parent_class = NULL; + +static GType +gst_v4lsrc_buffer_get_type (void) +{ + static GType _gst_v4lsrc_buffer_type; + + if (G_UNLIKELY (_gst_v4lsrc_buffer_type == 0)) { + static const GTypeInfo v4lsrc_buffer_info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_v4lsrc_buffer_class_init, + NULL, + NULL, + sizeof (GstV4lSrcBuffer), + 0, + gst_v4lsrc_buffer_init, + NULL + }; + _gst_v4lsrc_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstV4lSrcBuffer", &v4lsrc_buffer_info, 0); + } + return _gst_v4lsrc_buffer_type; +} + +static void +gst_v4lsrc_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + v4lbuffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_v4lsrc_buffer_finalize; +} + +static void +gst_v4lsrc_buffer_init (GTypeInstance * instance, gpointer g_class) +{ + +} + +static void +gst_v4lsrc_buffer_finalize (GstV4lSrcBuffer * v4lsrc_buffer) +{ + GstMiniObjectClass *miniobject_class; + GstV4lSrc *v4lsrc; + gint num; + + v4lsrc = v4lsrc_buffer->v4lsrc; + num = v4lsrc_buffer->num; + + GST_LOG_OBJECT (v4lsrc, "freeing buffer %p for frame %d", v4lsrc_buffer, num); + + /* only requeue if we still have an mmap buffer */ + if (GST_V4LELEMENT (v4lsrc)->buffer) { + GST_LOG_OBJECT (v4lsrc, "requeueing frame %d", num); + gst_v4lsrc_requeue_frame (v4lsrc, num); + } + + gst_object_unref (v4lsrc); + + miniobject_class = (GstMiniObjectClass *) v4lbuffer_parent_class; + miniobject_class->finalize (GST_MINI_OBJECT_CAST (v4lsrc_buffer)); +} + +/* Create a V4lSrc buffer from our mmap'd data area */ +GstBuffer * +gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num) +{ + GstClockTime duration, timestamp, latency; + GstBuffer *buf; + GstClock *clock; + gint fps_n, fps_d; + + GST_DEBUG_OBJECT (v4lsrc, "creating buffer for frame %d", num); + + if (!(gst_v4lsrc_get_fps (v4lsrc, &fps_n, &fps_d))) + return NULL; + + buf = (GstBuffer *) gst_mini_object_new (GST_TYPE_V4LSRC_BUFFER); + + GST_V4LSRC_BUFFER (buf)->num = num; + GST_V4LSRC_BUFFER (buf)->v4lsrc = gst_object_ref (v4lsrc); + + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); + GST_BUFFER_DATA (buf) = gst_v4lsrc_get_buffer (v4lsrc, num); + GST_BUFFER_SIZE (buf) = v4lsrc->buffer_size; + GST_BUFFER_OFFSET (buf) = v4lsrc->offset++; + GST_BUFFER_OFFSET_END (buf) = v4lsrc->offset; + + /* timestamps, LOCK to get clock and base time. */ + GST_OBJECT_LOCK (v4lsrc); + if ((clock = GST_ELEMENT_CLOCK (v4lsrc))) { + /* we have a clock, get base time and ref clock */ + timestamp = GST_ELEMENT_CAST (v4lsrc)->base_time; + gst_object_ref (clock); + } else { + /* no clock, can't set timestamps */ + timestamp = GST_CLOCK_TIME_NONE; + } + GST_OBJECT_UNLOCK (v4lsrc); + + duration = + gst_util_uint64_scale_int (GST_SECOND, fps_d * v4lsrc->offset, fps_n) - + gst_util_uint64_scale_int (GST_SECOND, fps_d * (v4lsrc->offset - 1), + fps_n); + + latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n); + + if (clock) { + /* the time now is the time of the clock minus the base time */ + timestamp = gst_clock_get_time (clock) - timestamp; + gst_object_unref (clock); + + /* adjust timestamp for frame latency (we assume we have a framerate) */ + if (timestamp > latency) + timestamp -= latency; + else + timestamp = 0; + } + + GST_BUFFER_TIMESTAMP (buf) = timestamp; + GST_BUFFER_DURATION (buf) = duration; + + return buf; +} diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.h b/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.h new file mode 100644 index 0000000..18b3525 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/v4lsrc_calls.h @@ -0,0 +1,58 @@ +/* GStreamer + * + * v4lsrc_calls.h: functions for V4L video source + * + * Copyright (C) 2001-2002 Ronald Bultje + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __V4L_SRC_CALLS_H__ +#define __V4L_SRC_CALLS_H__ + +#include "gstv4lsrc.h" +#include "v4l_calls.h" + + +G_BEGIN_DECLS + + +/* frame grabbing/capture (palette = VIDEO_PALETTE_* - see videodev.h) */ +gboolean gst_v4lsrc_set_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette); +gboolean gst_v4lsrc_capture_init (GstV4lSrc *v4lsrc); +gboolean gst_v4lsrc_capture_start (GstV4lSrc *v4lsrc); +gboolean gst_v4lsrc_grab_frame (GstV4lSrc *v4lsrc, gint *num); +guint8 * gst_v4lsrc_get_buffer (GstV4lSrc *v4lsrc, gint num); +gboolean gst_v4lsrc_requeue_frame (GstV4lSrc *v4lsrc, gint num); +gboolean gst_v4lsrc_capture_stop (GstV4lSrc *v4lsrc); +gboolean gst_v4lsrc_capture_deinit (GstV4lSrc *v4lsrc); +gboolean gst_v4lsrc_get_fps (GstV4lSrc * v4lsrc, gint *fps_n, gint *fps_d); +GValue * gst_v4lsrc_get_fps_list (GstV4lSrc * v4lsrc); +GstBuffer *gst_v4lsrc_buffer_new (GstV4lSrc * v4lsrc, gint num); + +/* "the ugliest hack ever, now available at your local mirror" */ +gboolean gst_v4lsrc_try_capture (GstV4lSrc *v4lsrc, gint width, gint height, gint palette); + +/* For debug purposes, share the palette names */ +#ifndef GST_DISABLE_GST_DEBUG +const char *gst_v4lsrc_palette_name (int i); +#endif + + +G_END_DECLS + + +#endif /* __V4L_SRC_CALLS_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/v4l/videodev_mjpeg.h b/gst-plugins-base-subtitles0.10/sys/v4l/videodev_mjpeg.h new file mode 100644 index 0000000..e217fe4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/v4l/videodev_mjpeg.h @@ -0,0 +1,123 @@ +/* These are the MJPEG API extensions for the Video4Linux API, + first introduced by the Iomega Buz driver by Rainer Johanni + +*/ + +#ifndef __VIDEODEV_MJPEG_H__ +#define __VIDEODEV_MJPEG_H__ + +/* This is identical with the mgavideo internal params struct, + please tell me if you change this struct here ! top-field-first */ + + int APPn; /* Number of APP segment to be written, must be 0..15 */ + int APP_len; /* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len; /* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + unsigned long jpeg_markers; /* Which markers should go into the JPEG output. + Unless you exactly know what you do, leave them untouched. + Inluding less markers will make the resulting code + smaller, but there will be fewer applications + which can read it. + The presence of the APP and COM marker is + influenced by APP0_len and COM_len ONLY! */ +#define JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define JPEG_MARKER_APP (1<<7) /* App segment, driver will allways use APP0 */ + + int VFIFO_FB; /* Flag for enabling Video Fifo Feedback. + If this flag is turned on and JPEG decompressing + is going to the screen, the decompress process + is stopped every time the Video Fifo is full. + This enables a smooth decompress to the screen + but the video output signal will get scrambled */ + + /* Misc */ + + char reserved[312]; /* Makes 512 bytes for this structure */ +}; + +struct mjpeg_requestbuffers +{ + unsigned long count; /* Number of buffers for MJPEG grabbing */ + unsigned long size; /* Size PER BUFFER in bytes */ +}; + +struct mjpeg_sync +{ + unsigned long frame; /* Frame (0 - n) for double buffer */ + unsigned long length; /* number of code bytes in buffer (capture only) */ + unsigned long seq; /* frame sequence number */ + struct timeval timestamp; /* timestamp */ +}; + +struct mjpeg_status +{ + int input; /* Input channel, has to be set prior to BUZIOC_G_STATUS */ + int signal; /* Returned: 1 if valid video signal detected */ + int norm; /* Returned: VIDEO_MODE_PAL or VIDEO_MODE_NTSC */ + int color; /* Returned: 1 if color signal detected */ +}; + +/* +Private IOCTL to set up for displaying MJPEG +*/ +#define MJPIOC_G_PARAMS _IOR ('v', BASE_VIDIOCPRIVATE+0, struct mjpeg_params) +#define MJPIOC_S_PARAMS _IOWR('v', BASE_VIDIOCPRIVATE+1, struct mjpeg_params) +#define MJPIOC_REQBUFS _IOWR('v', BASE_VIDIOCPRIVATE+2, struct mjpeg_requestbuffers) +#define MJPIOC_QBUF_CAPT _IOW ('v', BASE_VIDIOCPRIVATE+3, int) +#define MJPIOC_QBUF_PLAY _IOW ('v', BASE_VIDIOCPRIVATE+4, int) +#define MJPIOC_SYNC _IOR ('v', BASE_VIDIOCPRIVATE+5, struct mjpeg_sync) +#define MJPIOC_G_STATUS _IOWR('v', BASE_VIDIOCPRIVATE+6, struct mjpeg_status) + +#endif /* __VIDEODEV_MJPEG_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/ximage/Makefile.am b/gst-plugins-base-subtitles0.10/sys/ximage/Makefile.am new file mode 100644 index 0000000..69f9bbc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/ximage/Makefile.am @@ -0,0 +1,14 @@ +plugin_LTLIBRARIES = libgstximagesink.la + +libgstximagesink_la_SOURCES = ximagesink.c ximage.c +libgstximagesink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) +libgstximagesink_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(X_LIBS) $(XSHM_LIBS) +libgstximagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstximagesink_la_DEPENDENCIES = $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la +libgstximagesink_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = ximagesink.h diff --git a/gst-plugins-base-subtitles0.10/sys/ximage/ximage.c b/gst-plugins-base-subtitles0.10/sys/ximage/ximage.c new file mode 100644 index 0000000..24b7bf2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/ximage/ximage.c @@ -0,0 +1,47 @@ +/* GStreamer + * Copyright (C) <2003> Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ximagesink.h" + +GST_DEBUG_CATEGORY (gst_debug_ximagesink); + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "ximagesink", + GST_RANK_SECONDARY, GST_TYPE_XIMAGESINK)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (gst_debug_ximagesink, "ximagesink", 0, + "ximagesink element"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "ximagesink", + "X11 video output element based on standard Xlib calls", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.c b/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.c new file mode 100644 index 0000000..99ad35b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.c @@ -0,0 +1,2508 @@ +/* GStreamer + * Copyright (C) <2005> Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-ximagesink + * + * XImageSink renders video frames to a drawable (XWindow) on a local or remote + * display. This element can receive a Window ID from the application through + * the XOverlay interface and will then render video frames in this drawable. + * If no Window ID was provided by the application, the element will create its + * own internal window and render into it. + * + * + * Scaling + * + * As standard XImage rendering to a drawable is not scaled, XImageSink will use + * reverse caps negotiation to try to get scaled video frames for the drawable. + * This is accomplished by asking the peer pad if it accepts some different caps + * which in most cases implies that there is a scaling element in the pipeline, + * or that an element generating the video frames can generate them with a + * different geometry. This mechanism is handled during buffer allocations, for + * each allocation request the video sink will check the drawable geometry, look + * at the #GstXImageSink:force-aspect-ratio property, calculate the geometry of + * desired video frames and then check that the peer pad accept those new caps. + * If it does it will then allocate a buffer in video memory with this new + * geometry and return it with the new caps. + * + * + * + * Events + * + * XImageSink creates a thread to handle events coming from the drawable. There + * are several kind of events that can be grouped in 2 big categories: input + * events and window state related events. Input events will be translated to + * navigation events and pushed upstream for other elements to react on them. + * This includes events such as pointer moves, key press/release, clicks etc... + * Other events are used to handle the drawable appearance even when the data + * is not flowing (GST_STATE_PAUSED). That means that even when the element is + * paused, it will receive expose events from the drawable and draw the latest + * frame with correct borders/aspect-ratio. + * + * + * + * Pixel aspect ratio + * + * When changing state to GST_STATE_READY, XImageSink will open a connection to + * the display specified in the #GstXImageSink:display property or the default + * display if nothing specified. Once this connection is open it will inspect + * the display configuration including the physical display geometry and + * then calculate the pixel aspect ratio. When caps negotiation will occur, the + * video sink will set the calculated pixel aspect ratio on the caps to make + * sure that incoming video frames will have the correct pixel aspect ratio for + * this display. Sometimes the calculated pixel aspect ratio can be wrong, it is + * then possible to enforce a specific pixel aspect ratio using the + * #GstXImageSink:pixel-aspect-ratio property. + * + * + * + * Examples + * |[ + * gst-launch -v videotestsrc ! queue ! ximagesink + * ]| A pipeline to test reverse negotiation. When the test video signal appears + * you can resize the window and see that scaled buffers of the desired size are + * going to arrive with a short delay. This illustrates how buffers of desired + * size are allocated along the way. If you take away the queue, scaling will + * happen almost immediately. + * |[ + * gst-launch -v videotestsrc ! navigationtest ! ffmpegcolorspace ! ximagesink + * ]| A pipeline to test navigation events. + * While moving the mouse pointer over the test signal you will see a black box + * following the mouse pointer. If you press the mouse button somewhere on the + * video and release it somewhere else a green box will appear where you pressed + * the button and a red one where you released it. (The navigationtest element + * is part of gst-plugins-good.) + * |[ + * gst-launch -v videotestsrc ! video/x-raw-rgb, pixel-aspect-ratio=(fraction)4/3 ! videoscale ! ximagesink + * ]| This is faking a 4/3 pixel aspect ratio caps on video frames produced by + * videotestsrc, in most cases the pixel aspect ratio of the display will be + * 1/1. This means that videoscale will have to do the scaling to convert + * incoming frames to a size that will match the display pixel aspect ratio + * (from 320x240 to 320x180 in this case). Note that you might have to escape + * some characters for your shell like '\(fraction\)'. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Our interfaces */ +#include +#include + +/* Object header */ +#include "ximagesink.h" + +/* Debugging category */ +#include + +GST_DEBUG_CATEGORY_EXTERN (gst_debug_ximagesink); +#define GST_CAT_DEFAULT gst_debug_ximagesink + +typedef struct +{ + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; +} +MotifWmHints, MwmHints; + +#define MWM_HINTS_DECORATIONS (1L << 1) + +static void gst_ximagesink_reset (GstXImageSink * ximagesink); +static void gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink, + GstXImageBuffer * ximage); +static void gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink); +static void gst_ximagesink_expose (GstXOverlay * overlay); + +static GstStaticPadTemplate gst_ximagesink_sink_template_factory = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") + ); + +enum +{ + PROP_0, + PROP_DISPLAY, + PROP_SYNCHRONOUS, + PROP_PIXEL_ASPECT_RATIO, + PROP_FORCE_ASPECT_RATIO, + PROP_HANDLE_EVENTS, + PROP_HANDLE_EXPOSE, + PROP_WINDOW_WIDTH, + PROP_WINDOW_HEIGHT +}; + +static GstVideoSinkClass *parent_class = NULL; + +/* ============================================================= */ +/* */ +/* Private Methods */ +/* */ +/* ============================================================= */ + +/* ximage buffers */ + +static GstBufferClass *ximage_buffer_parent_class = NULL; + +#define GST_TYPE_XIMAGE_BUFFER (gst_ximage_buffer_get_type()) + +#define GST_IS_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XIMAGE_BUFFER)) +#define GST_XIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBuffer)) +#define GST_XIMAGE_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_XIMAGE_BUFFER, GstXImageBufferClass)) + +/* So some words about GstMiniObject, this is pretty messy... + GstMiniObject does not use the standard finalizing of GObjects, you are + supposed to call gst_buffer_unref that's going to call gst_mini_objec_unref + which will handle its own refcount system and call gst_mini_object_free. + gst_mini_object_free will call the class finalize method which is not the + one from GObject, after calling this finalize method it will free the object + instance for you if the refcount is still 0 so you should not chain up */ +static void +gst_ximage_buffer_finalize (GstXImageBuffer * ximage) +{ + GstXImageSink *ximagesink = NULL; + gboolean recycled = FALSE; + gboolean running; + + g_return_if_fail (ximage != NULL); + + ximagesink = ximage->ximagesink; + if (G_UNLIKELY (ximagesink == NULL)) { + GST_WARNING_OBJECT (ximagesink, "no sink found"); + goto beach; + } + + GST_OBJECT_LOCK (ximagesink); + running = ximagesink->running; + GST_OBJECT_UNLOCK (ximagesink); + + if (running == FALSE) { + /* If the sink is shutting down, need to clear the image */ + GST_DEBUG_OBJECT (ximagesink, + "destroy image %p because the sink is shutting down", ximage); + gst_ximagesink_ximage_destroy (ximagesink, ximage); + } else if ((ximage->width != GST_VIDEO_SINK_WIDTH (ximagesink)) || + (ximage->height != GST_VIDEO_SINK_HEIGHT (ximagesink))) { + /* If our geometry changed we can't reuse that image. */ + GST_DEBUG_OBJECT (ximagesink, + "destroy image %p as its size changed %dx%d vs current %dx%d", + ximage, ximage->width, ximage->height, + GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink)); + gst_ximagesink_ximage_destroy (ximagesink, ximage); + } else { + /* In that case we can reuse the image and add it to our image pool. */ + GST_LOG_OBJECT (ximagesink, "recycling image %p in pool", ximage); + /* need to increment the refcount again to recycle */ + gst_buffer_ref (GST_BUFFER_CAST (ximage)); + g_mutex_lock (ximagesink->pool_lock); + ximagesink->buffer_pool = g_slist_prepend (ximagesink->buffer_pool, ximage); + g_mutex_unlock (ximagesink->pool_lock); + recycled = TRUE; + } + + if (!recycled) + GST_MINI_OBJECT_CLASS (ximage_buffer_parent_class)->finalize + (GST_MINI_OBJECT (ximage)); + +beach: + return; +} + +static void +gst_ximage_buffer_free (GstXImageBuffer * ximage) +{ + /* make sure it is not recycled */ + ximage->width = -1; + ximage->height = -1; + gst_buffer_unref (GST_BUFFER_CAST (ximage)); +} + +static void +gst_ximage_buffer_init (GstXImageBuffer * ximage_buffer, gpointer g_class) +{ +#ifdef HAVE_XSHM + ximage_buffer->SHMInfo.shmaddr = ((void *) -1); + ximage_buffer->SHMInfo.shmid = -1; +#endif +} + +static void +gst_ximage_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + ximage_buffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_ximage_buffer_finalize; +} + +static GType +gst_ximage_buffer_get_type (void) +{ + static GType _gst_ximage_buffer_type; + + if (G_UNLIKELY (_gst_ximage_buffer_type == 0)) { + static const GTypeInfo ximage_buffer_info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_ximage_buffer_class_init, + NULL, + NULL, + sizeof (GstXImageBuffer), + 0, + (GInstanceInitFunc) gst_ximage_buffer_init, + NULL + }; + _gst_ximage_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstXImageBuffer", &ximage_buffer_info, 0); + } + return _gst_ximage_buffer_type; +} + +/* X11 stuff */ + +static gboolean error_caught = FALSE; + +static int +gst_ximagesink_handle_xerror (Display * display, XErrorEvent * xevent) +{ + char error_msg[1024]; + + XGetErrorText (display, xevent->error_code, error_msg, 1024); + GST_DEBUG ("ximagesink triggered an XError. error: %s", error_msg); + error_caught = TRUE; + return 0; +} + +#ifdef HAVE_XSHM /* Check that XShm calls actually work */ + +static gboolean +gst_ximagesink_check_xshm_calls (GstXImageSink * ximagesink, + GstXContext * xcontext) +{ + XImage *ximage; + XShmSegmentInfo SHMInfo; + size_t size; + int (*handler) (Display *, XErrorEvent *); + gboolean result = FALSE; + gboolean did_attach = FALSE; + + g_return_val_if_fail (xcontext != NULL, FALSE); + + /* Sync to ensure any older errors are already processed */ + XSync (xcontext->disp, FALSE); + + /* Set defaults so we don't free these later unnecessarily */ + SHMInfo.shmaddr = ((void *) -1); + SHMInfo.shmid = -1; + + /* Setting an error handler to catch failure */ + error_caught = FALSE; + handler = XSetErrorHandler (gst_ximagesink_handle_xerror); + + /* Trying to create a 1x1 ximage */ + GST_DEBUG ("XShmCreateImage of 1x1"); + + ximage = XShmCreateImage (xcontext->disp, xcontext->visual, + xcontext->depth, ZPixmap, NULL, &SHMInfo, 1, 1); + + /* Might cause an error, sync to ensure it is noticed */ + XSync (xcontext->disp, FALSE); + if (!ximage || error_caught) { + GST_WARNING ("could not XShmCreateImage a 1x1 image"); + goto beach; + } + size = ximage->height * ximage->bytes_per_line; + + SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); + if (SHMInfo.shmid == -1) { + GST_WARNING ("could not get shared memory of %" G_GSIZE_FORMAT " bytes", + size); + goto beach; + } + + SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0); + if (SHMInfo.shmaddr == ((void *) -1)) { + GST_WARNING ("Failed to shmat: %s", g_strerror (errno)); + /* Clean up shm seg */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + goto beach; + } + + ximage->data = SHMInfo.shmaddr; + SHMInfo.readOnly = FALSE; + + if (XShmAttach (xcontext->disp, &SHMInfo) == 0) { + GST_WARNING ("Failed to XShmAttach"); + /* Clean up shm seg */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + goto beach; + } + + /* Sync to ensure we see any errors we caused */ + XSync (xcontext->disp, FALSE); + + /* Delete the shared memory segment as soon as everyone is attached. + * This way, it will be deleted as soon as we detach later, and not + * leaked if we crash. */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + + if (!error_caught) { + did_attach = TRUE; + /* store whether we succeeded in result */ + result = TRUE; + } + +beach: + /* Sync to ensure we swallow any errors we caused and reset error_caught */ + XSync (xcontext->disp, FALSE); + error_caught = FALSE; + XSetErrorHandler (handler); + + if (did_attach) { + XShmDetach (xcontext->disp, &SHMInfo); + XSync (xcontext->disp, FALSE); + } + if (SHMInfo.shmaddr != ((void *) -1)) + shmdt (SHMInfo.shmaddr); + if (ximage) + XDestroyImage (ximage); + return result; +} +#endif /* HAVE_XSHM */ + +/* This function handles GstXImageBuffer creation depending on XShm availability */ +static GstXImageBuffer * +gst_ximagesink_ximage_new (GstXImageSink * ximagesink, GstCaps * caps) +{ + GstXImageBuffer *ximage = NULL; + GstStructure *structure = NULL; + gboolean succeeded = FALSE; + int (*handler) (Display *, XErrorEvent *); + + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL); + + ximage = (GstXImageBuffer *) gst_mini_object_new (GST_TYPE_XIMAGE_BUFFER); + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "width", &ximage->width) || + !gst_structure_get_int (structure, "height", &ximage->height)) { + GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps); + } + + GST_DEBUG_OBJECT (ximagesink, "creating image %p (%dx%d)", ximage, + ximage->width, ximage->height); + + g_mutex_lock (ximagesink->x_lock); + + /* Setting an error handler to catch failure */ + error_caught = FALSE; + handler = XSetErrorHandler (gst_ximagesink_handle_xerror); + +#ifdef HAVE_XSHM + if (ximagesink->xcontext->use_xshm) { + ximage->ximage = XShmCreateImage (ximagesink->xcontext->disp, + ximagesink->xcontext->visual, + ximagesink->xcontext->depth, + ZPixmap, NULL, &ximage->SHMInfo, ximage->width, ximage->height); + if (!ximage->ximage || error_caught) { + g_mutex_unlock (ximagesink->x_lock); + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + /* Push an error */ + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximage->width, ximage->height), + ("could not XShmCreateImage a %dx%d image", + ximage->width, ximage->height)); + goto beach; + } + + /* we have to use the returned bytes_per_line for our shm size */ + ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height; + GST_LOG_OBJECT (ximagesink, + "XShm image size is %" G_GSIZE_FORMAT ", width %d, stride %d", + ximage->size, ximage->width, ximage->ximage->bytes_per_line); + + ximage->SHMInfo.shmid = shmget (IPC_PRIVATE, ximage->size, + IPC_CREAT | 0777); + if (ximage->SHMInfo.shmid == -1) { + g_mutex_unlock (ximagesink->x_lock); + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximage->width, ximage->height), + ("could not get shared memory of %" G_GSIZE_FORMAT " bytes", + ximage->size)); + goto beach; + } + + ximage->SHMInfo.shmaddr = shmat (ximage->SHMInfo.shmid, NULL, 0); + if (ximage->SHMInfo.shmaddr == ((void *) -1)) { + g_mutex_unlock (ximagesink->x_lock); + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximage->width, ximage->height), + ("Failed to shmat: %s", g_strerror (errno))); + /* Clean up the shared memory segment */ + shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL); + goto beach; + } + + ximage->ximage->data = ximage->SHMInfo.shmaddr; + ximage->SHMInfo.readOnly = FALSE; + + if (XShmAttach (ximagesink->xcontext->disp, &ximage->SHMInfo) == 0) { + /* Clean up shm seg */ + shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL); + + g_mutex_unlock (ximagesink->x_lock); + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximage->width, ximage->height), ("Failed to XShmAttach")); + goto beach; + } + + XSync (ximagesink->xcontext->disp, FALSE); + + /* Now that everyone has attached, we can delete the shared memory segment. + * This way, it will be deleted as soon as we detach later, and not + * leaked if we crash. */ + shmctl (ximage->SHMInfo.shmid, IPC_RMID, NULL); + + } else +#endif /* HAVE_XSHM */ + { + guint allocsize; + + ximage->ximage = XCreateImage (ximagesink->xcontext->disp, + ximagesink->xcontext->visual, + ximagesink->xcontext->depth, + ZPixmap, 0, NULL, + ximage->width, ximage->height, ximagesink->xcontext->bpp, 0); + if (!ximage->ximage || error_caught) { + g_mutex_unlock (ximagesink->x_lock); + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + /* Push an error */ + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximage->width, ximage->height), + ("could not XCreateImage a %dx%d image", + ximage->width, ximage->height)); + goto beach; + } + + /* upstream will assume that rowstrides are multiples of 4, but this + * doesn't always seem to be the case with XCreateImage() */ + if ((ximage->ximage->bytes_per_line % 4) != 0) { + GST_WARNING_OBJECT (ximagesink, "returned stride not a multiple of 4 as " + "usually assumed"); + } + + /* we have to use the returned bytes_per_line for our image size */ + ximage->size = ximage->ximage->bytes_per_line * ximage->ximage->height; + + /* alloc a bit more for unexpected strides to avoid crashes upstream. + * FIXME: if we get an unrounded stride, the image will be displayed + * distorted, since all upstream elements assume a rounded stride */ + allocsize = + GST_ROUND_UP_4 (ximage->ximage->bytes_per_line) * + ximage->ximage->height; + ximage->ximage->data = g_malloc (allocsize); + GST_LOG_OBJECT (ximagesink, + "non-XShm image size is %" G_GSIZE_FORMAT " (alloced: %u), width %d, " + "stride %d", ximage->size, allocsize, ximage->width, + ximage->ximage->bytes_per_line); + + XSync (ximagesink->xcontext->disp, FALSE); + } + + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + + succeeded = TRUE; + + GST_BUFFER_DATA (ximage) = (guchar *) ximage->ximage->data; + GST_BUFFER_SIZE (ximage) = ximage->size; + + /* Keep a ref to our sink */ + ximage->ximagesink = gst_object_ref (ximagesink); + + g_mutex_unlock (ximagesink->x_lock); +beach: + if (!succeeded) { + gst_ximage_buffer_free (ximage); + ximage = NULL; + } + + return ximage; +} + +/* This function destroys a GstXImageBuffer handling XShm availability */ +static void +gst_ximagesink_ximage_destroy (GstXImageSink * ximagesink, + GstXImageBuffer * ximage) +{ + g_return_if_fail (ximage != NULL); + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + /* Hold the object lock to ensure the XContext doesn't disappear */ + GST_OBJECT_LOCK (ximagesink); + + /* If the destroyed image is the current one we destroy our reference too */ + if (ximagesink->cur_image == ximage) { + ximagesink->cur_image = NULL; + } + + /* We might have some buffers destroyed after changing state to NULL */ + if (!ximagesink->xcontext) { + GST_DEBUG_OBJECT (ximagesink, "Destroying XImage after XContext"); +#ifdef HAVE_XSHM + if (ximage->SHMInfo.shmaddr != ((void *) -1)) { + shmdt (ximage->SHMInfo.shmaddr); + } +#endif + goto beach; + } + + g_mutex_lock (ximagesink->x_lock); + +#ifdef HAVE_XSHM + if (ximagesink->xcontext->use_xshm) { + if (ximage->SHMInfo.shmaddr != ((void *) -1)) { + XShmDetach (ximagesink->xcontext->disp, &ximage->SHMInfo); + XSync (ximagesink->xcontext->disp, 0); + shmdt (ximage->SHMInfo.shmaddr); + } + if (ximage->ximage) + XDestroyImage (ximage->ximage); + + } else +#endif /* HAVE_XSHM */ + { + if (ximage->ximage) { + XDestroyImage (ximage->ximage); + } + } + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); + +beach: + GST_OBJECT_UNLOCK (ximagesink); + + if (ximage->ximagesink) { + /* Release the ref to our sink */ + ximage->ximagesink = NULL; + gst_object_unref (ximagesink); + } + + return; +} + +/* We are called with the x_lock taken */ +static void +gst_ximagesink_xwindow_draw_borders (GstXImageSink * ximagesink, + GstXWindow * xwindow, GstVideoRectangle rect) +{ + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + g_return_if_fail (xwindow != NULL); + + XSetForeground (ximagesink->xcontext->disp, xwindow->gc, + ximagesink->xcontext->black); + + /* Left border */ + if (rect.x > 0) { + XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc, + 0, 0, rect.x, xwindow->height); + } + + /* Right border */ + if ((rect.x + rect.w) < xwindow->width) { + XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc, + rect.x + rect.w, 0, xwindow->width, xwindow->height); + } + + /* Top border */ + if (rect.y > 0) { + XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc, + 0, 0, xwindow->width, rect.y); + } + + /* Bottom border */ + if ((rect.y + rect.h) < xwindow->height) { + XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc, + 0, rect.y + rect.h, xwindow->width, xwindow->height); + } +} + +/* This function puts a GstXImageBuffer on a GstXImageSink's window */ +static gboolean +gst_ximagesink_ximage_put (GstXImageSink * ximagesink, GstXImageBuffer * ximage) +{ + GstVideoRectangle src, dst, result; + gboolean draw_border = FALSE; + + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE); + + /* We take the flow_lock. If expose is in there we don't want to run + concurrently from the data flow thread */ + g_mutex_lock (ximagesink->flow_lock); + + if (G_UNLIKELY (ximagesink->xwindow == NULL)) { + g_mutex_unlock (ximagesink->flow_lock); + return FALSE; + } + + /* Draw borders when displaying the first frame. After this + draw borders only on expose event or caps change (ximagesink->draw_border = TRUE). */ + if (!ximagesink->cur_image || ximagesink->draw_border) { + draw_border = TRUE; + } + + /* Store a reference to the last image we put, lose the previous one */ + if (ximage && ximagesink->cur_image != ximage) { + if (ximagesink->cur_image) { + GST_LOG_OBJECT (ximagesink, "unreffing %p", ximagesink->cur_image); + gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image)); + } + GST_LOG_OBJECT (ximagesink, "reffing %p as our current image", ximage); + ximagesink->cur_image = + GST_XIMAGE_BUFFER (gst_buffer_ref (GST_BUFFER_CAST (ximage))); + } + + /* Expose sends a NULL image, we take the latest frame */ + if (!ximage) { + draw_border = TRUE; + if (ximagesink->cur_image) { + ximage = ximagesink->cur_image; + } else { + g_mutex_unlock (ximagesink->flow_lock); + return TRUE; + } + } + + src.w = ximage->width; + src.h = ximage->height; + dst.w = ximagesink->xwindow->width; + dst.h = ximagesink->xwindow->height; + + gst_video_sink_center_rect (src, dst, &result, FALSE); + + g_mutex_lock (ximagesink->x_lock); + + if (draw_border) { + gst_ximagesink_xwindow_draw_borders (ximagesink, ximagesink->xwindow, + result); + ximagesink->draw_border = FALSE; + } +#ifdef HAVE_XSHM + if (ximagesink->xcontext->use_xshm) { + GST_LOG_OBJECT (ximagesink, + "XShmPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d", + ximage, 0, 0, result.x, result.y, result.w, result.h, + ximagesink->xwindow->width, ximagesink->xwindow->height); + XShmPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win, + ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y, + result.w, result.h, FALSE); + } else +#endif /* HAVE_XSHM */ + { + GST_LOG_OBJECT (ximagesink, + "XPutImage on %p, src: %d, %d - dest: %d, %d, dim: %dx%d, win %dx%d", + ximage, 0, 0, result.x, result.y, result.w, result.h, + ximagesink->xwindow->width, ximagesink->xwindow->height); + XPutImage (ximagesink->xcontext->disp, ximagesink->xwindow->win, + ximagesink->xwindow->gc, ximage->ximage, 0, 0, result.x, result.y, + result.w, result.h); + } + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); + + g_mutex_unlock (ximagesink->flow_lock); + + return TRUE; +} + +static gboolean +gst_ximagesink_xwindow_decorate (GstXImageSink * ximagesink, + GstXWindow * window) +{ + Atom hints_atom = None; + MotifWmHints *hints; + + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), FALSE); + g_return_val_if_fail (window != NULL, FALSE); + + g_mutex_lock (ximagesink->x_lock); + + hints_atom = XInternAtom (ximagesink->xcontext->disp, "_MOTIF_WM_HINTS", 1); + if (hints_atom == None) { + g_mutex_unlock (ximagesink->x_lock); + return FALSE; + } + + hints = g_malloc0 (sizeof (MotifWmHints)); + + hints->flags |= MWM_HINTS_DECORATIONS; + hints->decorations = 1 << 0; + + XChangeProperty (ximagesink->xcontext->disp, window->win, + hints_atom, hints_atom, 32, PropModeReplace, + (guchar *) hints, sizeof (MotifWmHints) / sizeof (long)); + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); + + g_free (hints); + + return TRUE; +} + +static void +gst_ximagesink_xwindow_set_title (GstXImageSink * ximagesink, + GstXWindow * xwindow, const gchar * media_title) +{ + if (media_title) { + g_free (ximagesink->media_title); + ximagesink->media_title = g_strdup (media_title); + } + if (xwindow) { + /* we have a window */ + if (xwindow->internal) { + XTextProperty xproperty; + const gchar *app_name; + const gchar *title = NULL; + gchar *title_mem = NULL; + + /* set application name as a title */ + app_name = g_get_application_name (); + + if (app_name && ximagesink->media_title) { + title = title_mem = g_strconcat (ximagesink->media_title, " : ", + app_name, NULL); + } else if (app_name) { + title = app_name; + } else if (ximagesink->media_title) { + title = ximagesink->media_title; + } + + if (title) { + if ((XStringListToTextProperty (((char **) &title), 1, + &xproperty)) != 0) { + XSetWMName (ximagesink->xcontext->disp, xwindow->win, &xproperty); + XFree (xproperty.value); + } + + g_free (title_mem); + } + } + } +} + +/* This function handles a GstXWindow creation */ +static GstXWindow * +gst_ximagesink_xwindow_new (GstXImageSink * ximagesink, gint width, gint height) +{ + GstXWindow *xwindow = NULL; + XGCValues values; + + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL); + + xwindow = g_new0 (GstXWindow, 1); + + xwindow->width = width; + xwindow->height = height; + xwindow->internal = TRUE; + + g_mutex_lock (ximagesink->x_lock); + + xwindow->win = XCreateSimpleWindow (ximagesink->xcontext->disp, + ximagesink->xcontext->root, + 0, 0, xwindow->width, xwindow->height, 0, 0, ximagesink->xcontext->black); + + /* We have to do that to prevent X from redrawing the background on + ConfigureNotify. This takes away flickering of video when resizing. */ + XSetWindowBackgroundPixmap (ximagesink->xcontext->disp, xwindow->win, None); + + /* set application name as a title */ + gst_ximagesink_xwindow_set_title (ximagesink, xwindow, NULL); + + if (ximagesink->handle_events) { + Atom wm_delete; + + XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); + + /* Tell the window manager we'd like delete client messages instead of + * being killed */ + wm_delete = XInternAtom (ximagesink->xcontext->disp, + "WM_DELETE_WINDOW", False); + (void) XSetWMProtocols (ximagesink->xcontext->disp, xwindow->win, + &wm_delete, 1); + } + + xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, + 0, &values); + + XMapRaised (ximagesink->xcontext->disp, xwindow->win); + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); + + gst_ximagesink_xwindow_decorate (ximagesink, xwindow); + + gst_x_overlay_got_window_handle (GST_X_OVERLAY (ximagesink), xwindow->win); + + return xwindow; +} + +/* This function destroys a GstXWindow */ +static void +gst_ximagesink_xwindow_destroy (GstXImageSink * ximagesink, + GstXWindow * xwindow) +{ + g_return_if_fail (xwindow != NULL); + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + g_mutex_lock (ximagesink->x_lock); + + /* If we did not create that window we just free the GC and let it live */ + if (xwindow->internal) + XDestroyWindow (ximagesink->xcontext->disp, xwindow->win); + else + XSelectInput (ximagesink->xcontext->disp, xwindow->win, 0); + + XFreeGC (ximagesink->xcontext->disp, xwindow->gc); + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); + + g_free (xwindow); +} + +static void +gst_ximagesink_xwindow_update_geometry (GstXImageSink * ximagesink) +{ + XWindowAttributes attr; + + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + /* Update the window geometry */ + g_mutex_lock (ximagesink->x_lock); + if (G_UNLIKELY (ximagesink->xwindow == NULL)) { + g_mutex_unlock (ximagesink->x_lock); + return; + } + + XGetWindowAttributes (ximagesink->xcontext->disp, + ximagesink->xwindow->win, &attr); + + ximagesink->xwindow->width = attr.width; + ximagesink->xwindow->height = attr.height; + + g_mutex_unlock (ximagesink->x_lock); +} + +static void +gst_ximagesink_xwindow_clear (GstXImageSink * ximagesink, GstXWindow * xwindow) +{ + g_return_if_fail (xwindow != NULL); + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + g_mutex_lock (ximagesink->x_lock); + + XSetForeground (ximagesink->xcontext->disp, xwindow->gc, + ximagesink->xcontext->black); + + XFillRectangle (ximagesink->xcontext->disp, xwindow->win, xwindow->gc, + 0, 0, xwindow->width, xwindow->height); + + XSync (ximagesink->xcontext->disp, FALSE); + + g_mutex_unlock (ximagesink->x_lock); +} + +/* This function handles XEvents that might be in the queue. It generates + GstEvent that will be sent upstream in the pipeline to handle interactivity + and navigation.*/ +static void +gst_ximagesink_handle_xevents (GstXImageSink * ximagesink) +{ + XEvent e; + guint pointer_x = 0, pointer_y = 0; + gboolean pointer_moved = FALSE; + gboolean exposed = FALSE, configured = FALSE; + + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + /* Then we get all pointer motion events, only the last position is + interesting. */ + g_mutex_lock (ximagesink->flow_lock); + g_mutex_lock (ximagesink->x_lock); + while (XCheckWindowEvent (ximagesink->xcontext->disp, + ximagesink->xwindow->win, PointerMotionMask, &e)) { + g_mutex_unlock (ximagesink->x_lock); + g_mutex_unlock (ximagesink->flow_lock); + + switch (e.type) { + case MotionNotify: + pointer_x = e.xmotion.x; + pointer_y = e.xmotion.y; + pointer_moved = TRUE; + break; + default: + break; + } + g_mutex_lock (ximagesink->flow_lock); + g_mutex_lock (ximagesink->x_lock); + } + + if (pointer_moved) { + g_mutex_unlock (ximagesink->x_lock); + g_mutex_unlock (ximagesink->flow_lock); + + GST_DEBUG ("ximagesink pointer moved over window at %d,%d", + pointer_x, pointer_y); + gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink), + "mouse-move", 0, pointer_x, pointer_y); + + g_mutex_lock (ximagesink->flow_lock); + g_mutex_lock (ximagesink->x_lock); + } + + /* We get all remaining events on our window to throw them upstream */ + while (XCheckWindowEvent (ximagesink->xcontext->disp, + ximagesink->xwindow->win, + KeyPressMask | KeyReleaseMask | + ButtonPressMask | ButtonReleaseMask, &e)) { + KeySym keysym; + + /* We lock only for the X function call */ + g_mutex_unlock (ximagesink->x_lock); + g_mutex_unlock (ximagesink->flow_lock); + + switch (e.type) { + case ButtonPress: + /* Mouse button pressed/released over our window. We send upstream + events for interactivity/navigation */ + GST_DEBUG ("ximagesink button %d pressed over window at %d,%d", + e.xbutton.button, e.xbutton.x, e.xbutton.x); + gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink), + "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y); + break; + case ButtonRelease: + GST_DEBUG ("ximagesink button %d release over window at %d,%d", + e.xbutton.button, e.xbutton.x, e.xbutton.x); + gst_navigation_send_mouse_event (GST_NAVIGATION (ximagesink), + "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y); + break; + case KeyPress: + case KeyRelease: + /* Key pressed/released over our window. We send upstream + events for interactivity/navigation */ + GST_DEBUG ("ximagesink key %d pressed over window at %d,%d", + e.xkey.keycode, e.xkey.x, e.xkey.x); + g_mutex_lock (ximagesink->x_lock); + keysym = XKeycodeToKeysym (ximagesink->xcontext->disp, + e.xkey.keycode, 0); + g_mutex_unlock (ximagesink->x_lock); + if (keysym != NoSymbol) { + char *key_str = NULL; + + g_mutex_lock (ximagesink->x_lock); + key_str = XKeysymToString (keysym); + g_mutex_unlock (ximagesink->x_lock); + gst_navigation_send_key_event (GST_NAVIGATION (ximagesink), + e.type == KeyPress ? "key-press" : "key-release", key_str); + + } else { + gst_navigation_send_key_event (GST_NAVIGATION (ximagesink), + e.type == KeyPress ? "key-press" : "key-release", "unknown"); + } + break; + default: + GST_DEBUG_OBJECT (ximagesink, "ximagesink unhandled X event (%d)", + e.type); + } + g_mutex_lock (ximagesink->flow_lock); + g_mutex_lock (ximagesink->x_lock); + } + + while (XCheckWindowEvent (ximagesink->xcontext->disp, + ximagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) { + switch (e.type) { + case Expose: + exposed = TRUE; + break; + case ConfigureNotify: + g_mutex_unlock (ximagesink->x_lock); + gst_ximagesink_xwindow_update_geometry (ximagesink); + g_mutex_lock (ximagesink->x_lock); + configured = TRUE; + break; + default: + break; + } + } + + if (ximagesink->handle_expose && (exposed || configured)) { + g_mutex_unlock (ximagesink->x_lock); + g_mutex_unlock (ximagesink->flow_lock); + + gst_ximagesink_expose (GST_X_OVERLAY (ximagesink)); + + g_mutex_lock (ximagesink->flow_lock); + g_mutex_lock (ximagesink->x_lock); + } + + /* Handle Display events */ + while (XPending (ximagesink->xcontext->disp)) { + XNextEvent (ximagesink->xcontext->disp, &e); + + switch (e.type) { + case ClientMessage:{ + Atom wm_delete; + + wm_delete = XInternAtom (ximagesink->xcontext->disp, + "WM_DELETE_WINDOW", False); + if (wm_delete == (Atom) e.xclient.data.l[0]) { + /* Handle window deletion by posting an error on the bus */ + GST_ELEMENT_ERROR (ximagesink, RESOURCE, NOT_FOUND, + ("Output window was closed"), (NULL)); + + g_mutex_unlock (ximagesink->x_lock); + gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); + ximagesink->xwindow = NULL; + g_mutex_lock (ximagesink->x_lock); + } + break; + } + default: + break; + } + } + + g_mutex_unlock (ximagesink->x_lock); + g_mutex_unlock (ximagesink->flow_lock); +} + +static gpointer +gst_ximagesink_event_thread (GstXImageSink * ximagesink) +{ + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL); + + GST_OBJECT_LOCK (ximagesink); + while (ximagesink->running) { + GST_OBJECT_UNLOCK (ximagesink); + + if (ximagesink->xwindow) { + gst_ximagesink_handle_xevents (ximagesink); + } + /* FIXME: do we want to align this with the framerate or anything else? */ + g_usleep (G_USEC_PER_SEC / 20); + + GST_OBJECT_LOCK (ximagesink); + } + GST_OBJECT_UNLOCK (ximagesink); + + return NULL; +} + +static void +gst_ximagesink_manage_event_thread (GstXImageSink * ximagesink) +{ + GThread *thread = NULL; + + /* don't start the thread too early */ + if (ximagesink->xcontext == NULL) { + return; + } + + GST_OBJECT_LOCK (ximagesink); + if (ximagesink->handle_expose || ximagesink->handle_events) { + if (!ximagesink->event_thread) { + /* Setup our event listening thread */ + GST_DEBUG_OBJECT (ximagesink, "run xevent thread, expose %d, events %d", + ximagesink->handle_expose, ximagesink->handle_events); + ximagesink->running = TRUE; + ximagesink->event_thread = g_thread_create ( + (GThreadFunc) gst_ximagesink_event_thread, ximagesink, TRUE, NULL); + } + } else { + if (ximagesink->event_thread) { + GST_DEBUG_OBJECT (ximagesink, "stop xevent thread, expose %d, events %d", + ximagesink->handle_expose, ximagesink->handle_events); + ximagesink->running = FALSE; + /* grab thread and mark it as NULL */ + thread = ximagesink->event_thread; + ximagesink->event_thread = NULL; + } + } + GST_OBJECT_UNLOCK (ximagesink); + + /* Wait for our event thread to finish */ + if (thread) + g_thread_join (thread); + +} + + +/* This function calculates the pixel aspect ratio based on the properties + * in the xcontext structure and stores it there. */ +static void +gst_ximagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) +{ + static const gint par[][2] = { + {1, 1}, /* regular screen */ + {16, 15}, /* PAL TV */ + {11, 10}, /* 525 line Rec.601 video */ + {54, 59}, /* 625 line Rec.601 video */ + {64, 45}, /* 1280x1024 on 16:9 display */ + {5, 3}, /* 1280x1024 on 4:3 display */ + {4, 3} /* 800x600 on 16:9 display */ + }; + gint i; + gint index; + gdouble ratio; + gdouble delta; + +#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1]))) + + /* first calculate the "real" ratio based on the X values; + * which is the "physical" w/h divided by the w/h in pixels of the display */ + ratio = (gdouble) (xcontext->widthmm * xcontext->height) + / (xcontext->heightmm * xcontext->width); + + /* DirectFB's X in 720x576 reports the physical dimensions wrong, so + * override here */ + if (xcontext->width == 720 && xcontext->height == 576) { + ratio = 4.0 * 576 / (3.0 * 720); + } + GST_DEBUG ("calculated pixel aspect ratio: %f", ratio); + + /* now find the one from par[][2] with the lowest delta to the real one */ + delta = DELTA (0); + index = 0; + + for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) { + gdouble this_delta = DELTA (i); + + if (this_delta < delta) { + index = i; + delta = this_delta; + } + } + + GST_DEBUG ("Decided on index %d (%d/%d)", index, + par[index][0], par[index][1]); + + g_free (xcontext->par); + xcontext->par = g_new0 (GValue, 1); + g_value_init (xcontext->par, GST_TYPE_FRACTION); + gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]); + GST_DEBUG ("set xcontext PAR to %d/%d", + gst_value_get_fraction_numerator (xcontext->par), + gst_value_get_fraction_denominator (xcontext->par)); +} + +/* This function gets the X Display and global info about it. Everything is + stored in our object and will be cleaned when the object is disposed. Note + here that caps for supported format are generated without any window or + image creation */ +static GstXContext * +gst_ximagesink_xcontext_get (GstXImageSink * ximagesink) +{ + GstXContext *xcontext = NULL; + XPixmapFormatValues *px_formats = NULL; + gint nb_formats = 0, i; + + g_return_val_if_fail (GST_IS_XIMAGESINK (ximagesink), NULL); + + xcontext = g_new0 (GstXContext, 1); + + g_mutex_lock (ximagesink->x_lock); + + xcontext->disp = XOpenDisplay (ximagesink->display_name); + + if (!xcontext->disp) { + g_mutex_unlock (ximagesink->x_lock); + g_free (xcontext); + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Could not initialise X output"), ("Could not open display")); + return NULL; + } + + xcontext->screen = DefaultScreenOfDisplay (xcontext->disp); + xcontext->screen_num = DefaultScreen (xcontext->disp); + xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num); + xcontext->root = DefaultRootWindow (xcontext->disp); + xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num); + xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num); + xcontext->depth = DefaultDepthOfScreen (xcontext->screen); + + xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); + xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); + xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num); + xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num); + + GST_DEBUG_OBJECT (ximagesink, "X reports %dx%d pixels and %d mm x %d mm", + xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm); + + gst_ximagesink_calculate_pixel_aspect_ratio (xcontext); + + /* We get supported pixmap formats at supported depth */ + px_formats = XListPixmapFormats (xcontext->disp, &nb_formats); + + if (!px_formats) { + XCloseDisplay (xcontext->disp); + g_mutex_unlock (ximagesink->x_lock); + g_free (xcontext->par); + g_free (xcontext); + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Could not get supported pixmap formats"), (NULL)); + return NULL; + } + + /* We get bpp value corresponding to our running depth */ + for (i = 0; i < nb_formats; i++) { + if (px_formats[i].depth == xcontext->depth) + xcontext->bpp = px_formats[i].bits_per_pixel; + } + + XFree (px_formats); + + xcontext->endianness = + (ImageByteOrder (xcontext->disp) == + LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN; + + /* Search for XShm extension support */ +#ifdef HAVE_XSHM + if (XShmQueryExtension (xcontext->disp) && + gst_ximagesink_check_xshm_calls (ximagesink, xcontext)) { + xcontext->use_xshm = TRUE; + GST_DEBUG ("ximagesink is using XShm extension"); + } else +#endif + { + xcontext->use_xshm = FALSE; + GST_DEBUG ("ximagesink is not using XShm extension"); + } + + /* our caps system handles 24/32bpp RGB as big-endian. */ + if ((xcontext->bpp == 24 || xcontext->bpp == 32) && + xcontext->endianness == G_LITTLE_ENDIAN) { + xcontext->endianness = G_BIG_ENDIAN; + xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask); + xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask); + xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask); + if (xcontext->bpp == 24) { + xcontext->visual->red_mask >>= 8; + xcontext->visual->green_mask >>= 8; + xcontext->visual->blue_mask >>= 8; + } + } + + /* update object's par with calculated one if not set yet */ + if (!ximagesink->par) { + ximagesink->par = g_new0 (GValue, 1); + gst_value_init_and_copy (ximagesink->par, xcontext->par); + GST_DEBUG_OBJECT (ximagesink, "set calculated PAR on object's PAR"); + } + xcontext->caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, xcontext->bpp, + "depth", G_TYPE_INT, xcontext->depth, + "endianness", G_TYPE_INT, xcontext->endianness, + "red_mask", G_TYPE_INT, xcontext->visual->red_mask, + "green_mask", G_TYPE_INT, xcontext->visual->green_mask, + "blue_mask", G_TYPE_INT, xcontext->visual->blue_mask, + "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + if (ximagesink->par) { + int nom, den; + + nom = gst_value_get_fraction_numerator (ximagesink->par); + den = gst_value_get_fraction_denominator (ximagesink->par); + gst_caps_set_simple (xcontext->caps, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } + + g_mutex_unlock (ximagesink->x_lock); + + return xcontext; +} + +/* This function cleans the X context. Closing the Display and unrefing the + caps for supported formats. */ +static void +gst_ximagesink_xcontext_clear (GstXImageSink * ximagesink) +{ + GstXContext *xcontext; + + g_return_if_fail (GST_IS_XIMAGESINK (ximagesink)); + + GST_OBJECT_LOCK (ximagesink); + if (ximagesink->xcontext == NULL) { + GST_OBJECT_UNLOCK (ximagesink); + return; + } + + /* Take the xcontext reference and NULL it while we + * clean it up, so that any buffer-alloced buffers + * arriving after this will be freed correctly */ + xcontext = ximagesink->xcontext; + ximagesink->xcontext = NULL; + + GST_OBJECT_UNLOCK (ximagesink); + + gst_caps_unref (xcontext->caps); + g_free (xcontext->par); + g_free (ximagesink->par); + ximagesink->par = NULL; + + if (xcontext->last_caps) + gst_caps_replace (&xcontext->last_caps, NULL); + + g_mutex_lock (ximagesink->x_lock); + + XCloseDisplay (xcontext->disp); + + g_mutex_unlock (ximagesink->x_lock); + + g_free (xcontext); +} + +static void +gst_ximagesink_bufferpool_clear (GstXImageSink * ximagesink) +{ + + g_mutex_lock (ximagesink->pool_lock); + + while (ximagesink->buffer_pool) { + GstXImageBuffer *ximage = ximagesink->buffer_pool->data; + + ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool, + ximagesink->buffer_pool); + gst_ximage_buffer_free (ximage); + } + + g_mutex_unlock (ximagesink->pool_lock); +} + +/* Element stuff */ + +static GstCaps * +gst_ximagesink_getcaps (GstBaseSink * bsink) +{ + GstXImageSink *ximagesink; + GstCaps *caps; + int i; + + ximagesink = GST_XIMAGESINK (bsink); + + if (ximagesink->xcontext) + return gst_caps_ref (ximagesink->xcontext->caps); + + /* get a template copy and add the pixel aspect ratio */ + caps = + gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SINK + (ximagesink)->sinkpad)); + for (i = 0; i < gst_caps_get_size (caps); ++i) { + GstStructure *structure = gst_caps_get_structure (caps, i); + + if (ximagesink->par) { + int nom, den; + + nom = gst_value_get_fraction_numerator (ximagesink->par); + den = gst_value_get_fraction_denominator (ximagesink->par); + gst_structure_set (structure, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } + } + + return caps; +} + +static gboolean +gst_ximagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) +{ + GstXImageSink *ximagesink; + gboolean ret = TRUE; + GstStructure *structure; + const GValue *par; + gint new_width, new_height; + const GValue *fps; + + ximagesink = GST_XIMAGESINK (bsink); + + if (!ximagesink->xcontext) + return FALSE; + + GST_DEBUG_OBJECT (ximagesink, + "sinkconnect possible caps %" GST_PTR_FORMAT " with given caps %" + GST_PTR_FORMAT, ximagesink->xcontext->caps, caps); + + /* We intersect those caps with our template to make sure they are correct */ + if (!gst_caps_can_intersect (ximagesink->xcontext->caps, caps)) + goto incompatible_caps; + + structure = gst_caps_get_structure (caps, 0); + + ret &= gst_structure_get_int (structure, "width", &new_width); + ret &= gst_structure_get_int (structure, "height", &new_height); + fps = gst_structure_get_value (structure, "framerate"); + ret &= (fps != NULL); + if (!ret) + return FALSE; + + /* if the caps contain pixel-aspect-ratio, they have to match ours, + * otherwise linking should fail */ + par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (par) { + if (ximagesink->par) { + if (gst_value_compare (par, ximagesink->par) != GST_VALUE_EQUAL) { + goto wrong_aspect; + } + } else if (ximagesink->xcontext->par) { + if (gst_value_compare (par, ximagesink->xcontext->par) != GST_VALUE_EQUAL) { + goto wrong_aspect; + } + } + } + + GST_VIDEO_SINK_WIDTH (ximagesink) = new_width; + GST_VIDEO_SINK_HEIGHT (ximagesink) = new_height; + ximagesink->fps_n = gst_value_get_fraction_numerator (fps); + ximagesink->fps_d = gst_value_get_fraction_denominator (fps); + + /* Notify application to set xwindow id now */ + g_mutex_lock (ximagesink->flow_lock); + if (!ximagesink->xwindow) { + g_mutex_unlock (ximagesink->flow_lock); + gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ximagesink)); + } else { + g_mutex_unlock (ximagesink->flow_lock); + } + + /* Creating our window and our image */ + if (GST_VIDEO_SINK_WIDTH (ximagesink) <= 0 || + GST_VIDEO_SINK_HEIGHT (ximagesink) <= 0) { + GST_ELEMENT_ERROR (ximagesink, CORE, NEGOTIATION, (NULL), + ("Invalid image size.")); + return FALSE; + } + + g_mutex_lock (ximagesink->flow_lock); + if (!ximagesink->xwindow) { + ximagesink->xwindow = gst_ximagesink_xwindow_new (ximagesink, + GST_VIDEO_SINK_WIDTH (ximagesink), GST_VIDEO_SINK_HEIGHT (ximagesink)); + } + /* Remember to draw borders for next frame */ + ximagesink->draw_border = TRUE; + g_mutex_unlock (ximagesink->flow_lock); + + /* If our ximage has changed we destroy it, next chain iteration will create + a new one */ + if ((ximagesink->ximage) && + ((GST_VIDEO_SINK_WIDTH (ximagesink) != ximagesink->ximage->width) || + (GST_VIDEO_SINK_HEIGHT (ximagesink) != ximagesink->ximage->height))) { + GST_DEBUG_OBJECT (ximagesink, "our image is not usable anymore, unref %p", + ximagesink->ximage); + gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage)); + ximagesink->ximage = NULL; + } + + return TRUE; + + /* ERRORS */ +incompatible_caps: + { + GST_ERROR_OBJECT (ximagesink, "caps incompatible"); + return FALSE; + } +wrong_aspect: + { + GST_INFO_OBJECT (ximagesink, "pixel aspect ratio does not match"); + return FALSE; + } +} + +static GstStateChangeReturn +gst_ximagesink_change_state (GstElement * element, GstStateChange transition) +{ + GstXImageSink *ximagesink; + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstXContext *xcontext = NULL; + + ximagesink = GST_XIMAGESINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + + /* Initializing the XContext */ + if (ximagesink->xcontext == NULL) { + xcontext = gst_ximagesink_xcontext_get (ximagesink); + if (xcontext == NULL) { + ret = GST_STATE_CHANGE_FAILURE; + goto beach; + } + GST_OBJECT_LOCK (ximagesink); + if (xcontext) + ximagesink->xcontext = xcontext; + GST_OBJECT_UNLOCK (ximagesink); + } + + /* call XSynchronize with the current value of synchronous */ + GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s", + ximagesink->synchronous ? "TRUE" : "FALSE"); + g_mutex_lock (ximagesink->x_lock); + XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous); + g_mutex_unlock (ximagesink->x_lock); + gst_ximagesink_manage_event_thread (ximagesink); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + g_mutex_lock (ximagesink->flow_lock); + if (ximagesink->xwindow) + gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow); + g_mutex_unlock (ximagesink->flow_lock); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + ximagesink->fps_n = 0; + ximagesink->fps_d = 1; + GST_VIDEO_SINK_WIDTH (ximagesink) = 0; + GST_VIDEO_SINK_HEIGHT (ximagesink) = 0; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_ximagesink_reset (ximagesink); + break; + default: + break; + } + +beach: + return ret; +} + +static void +gst_ximagesink_get_times (GstBaseSink * bsink, GstBuffer * buf, + GstClockTime * start, GstClockTime * end) +{ + GstXImageSink *ximagesink; + + ximagesink = GST_XIMAGESINK (bsink); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + *start = GST_BUFFER_TIMESTAMP (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) { + *end = *start + GST_BUFFER_DURATION (buf); + } else { + if (ximagesink->fps_n > 0) { + *end = *start + + gst_util_uint64_scale_int (GST_SECOND, ximagesink->fps_d, + ximagesink->fps_n); + } + } + } +} + +static GstFlowReturn +gst_ximagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) +{ + GstXImageSink *ximagesink; + + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + + ximagesink = GST_XIMAGESINK (vsink); + + /* This shouldn't really happen because state changes will fail + * if the xcontext can't be allocated */ + if (!ximagesink->xcontext) + return GST_FLOW_ERROR; + + /* If this buffer has been allocated using our buffer management we simply + put the ximage which is in the PRIVATE pointer */ + if (GST_IS_XIMAGE_BUFFER (buf)) { + GST_LOG_OBJECT (ximagesink, "buffer from our pool, writing directly"); + if (!gst_ximagesink_ximage_put (ximagesink, GST_XIMAGE_BUFFER (buf))) + goto no_window; + } else { + /* Else we have to copy the data into our private image, */ + /* if we have one... */ + GST_LOG_OBJECT (ximagesink, "normal buffer, copying from it"); + if (!ximagesink->ximage) { + GST_DEBUG_OBJECT (ximagesink, "creating our ximage"); + ximagesink->ximage = gst_ximagesink_ximage_new (ximagesink, + GST_BUFFER_CAPS (buf)); + if (!ximagesink->ximage) + /* The create method should have posted an informative error */ + goto no_ximage; + + if (ximagesink->ximage->size < GST_BUFFER_SIZE (buf)) { + GST_ELEMENT_ERROR (ximagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + ximagesink->ximage->width, ximagesink->ximage->height), + ("XServer allocated buffer size did not match input buffer")); + + gst_ximagesink_ximage_destroy (ximagesink, ximagesink->ximage); + ximagesink->ximage = NULL; + goto no_ximage; + } + } + memcpy (GST_BUFFER_DATA (ximagesink->ximage), GST_BUFFER_DATA (buf), + MIN (GST_BUFFER_SIZE (buf), ximagesink->ximage->size)); + if (!gst_ximagesink_ximage_put (ximagesink, ximagesink->ximage)) + goto no_window; + } + + return GST_FLOW_OK; + + /* ERRORS */ +no_ximage: + { + /* No image available. That's very bad ! */ + GST_WARNING_OBJECT (ximagesink, "could not create image"); + return GST_FLOW_ERROR; + } +no_window: + { + /* No Window available to put our image into */ + GST_WARNING_OBJECT (ximagesink, "could not output image - no window"); + return GST_FLOW_ERROR; + } +} + + +static gboolean +gst_ximagesink_event (GstBaseSink * sink, GstEvent * event) +{ + GstXImageSink *ximagesink = GST_XIMAGESINK (sink); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG:{ + GstTagList *l; + gchar *title = NULL; + + gst_event_parse_tag (event, &l); + gst_tag_list_get_string (l, GST_TAG_TITLE, &title); + + if (title) { + GST_DEBUG_OBJECT (ximagesink, "got tags, title='%s'", title); + gst_ximagesink_xwindow_set_title (ximagesink, ximagesink->xwindow, + title); + + g_free (title); + } + break; + } + default: + break; + } + if (GST_BASE_SINK_CLASS (parent_class)->event) + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); + else + return TRUE; +} + + +/* Buffer management + * + * The buffer_alloc function must either return a buffer with given size and + * caps or create a buffer with different caps attached to the buffer. This + * last option is called reverse negotiation, ie, where the sink suggests a + * different format from the upstream peer. + * + * We try to do reverse negotiation when our geometry changes and we like a + * resized buffer. + */ +static GstFlowReturn +gst_ximagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buf) +{ + GstXImageSink *ximagesink; + GstXImageBuffer *ximage = NULL; + GstStructure *structure = NULL; + GstFlowReturn ret = GST_FLOW_OK; + GstCaps *alloc_caps; + gboolean alloc_unref = FALSE; + gint width, height; + GstVideoRectangle dst, src, result; + gboolean caps_accepted = FALSE; + + ximagesink = GST_XIMAGESINK (bsink); + + if (G_UNLIKELY (!caps)) { + GST_WARNING_OBJECT (ximagesink, "have no caps, doing fallback allocation"); + *buf = NULL; + ret = GST_FLOW_OK; + goto beach; + } + + /* This shouldn't really happen because state changes will fail + * if the xcontext can't be allocated */ + if (!ximagesink->xcontext) + return GST_FLOW_ERROR; + + GST_LOG_OBJECT (ximagesink, + "a buffer of %d bytes was requested with caps %" GST_PTR_FORMAT + " and offset %" G_GUINT64_FORMAT, size, caps, offset); + + /* assume we're going to alloc what was requested, keep track of + * wheter we need to unref or not. When we suggest a new format + * upstream we will create a new caps that we need to unref. */ + alloc_caps = caps; + alloc_unref = FALSE; + + /* get struct to see what is requested */ + structure = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (structure, "width", &width) || + !gst_structure_get_int (structure, "height", &height)) { + GST_WARNING_OBJECT (ximagesink, "invalid caps for buffer allocation %" + GST_PTR_FORMAT, caps); + ret = GST_FLOW_NOT_NEGOTIATED; + goto beach; + } + + src.w = width; + src.h = height; + + /* We take the flow_lock because the window might go away */ + g_mutex_lock (ximagesink->flow_lock); + if (!ximagesink->xwindow) { + g_mutex_unlock (ximagesink->flow_lock); + goto alloc; + } + + /* What is our geometry */ + dst.w = ximagesink->xwindow->width; + dst.h = ximagesink->xwindow->height; + + g_mutex_unlock (ximagesink->flow_lock); + + if (ximagesink->keep_aspect) { + GST_LOG_OBJECT (ximagesink, "enforcing aspect ratio in reverse caps " + "negotiation"); + gst_video_sink_center_rect (src, dst, &result, TRUE); + } else { + GST_LOG_OBJECT (ximagesink, "trying to resize to window geometry " + "ignoring aspect ratio"); + result.x = result.y = 0; + result.w = dst.w; + result.h = dst.h; + } + + /* We would like another geometry */ + if (width != result.w || height != result.h) { + int nom, den; + GstCaps *desired_caps; + GstStructure *desired_struct; + + /* make a copy of the incomming caps to create the new + * suggestion. We can't use make_writable because we might + * then destroy the original caps which we still need when the + * peer does not accept the suggestion. */ + desired_caps = gst_caps_copy (caps); + desired_struct = gst_caps_get_structure (desired_caps, 0); + + GST_DEBUG ("we would love to receive a %dx%d video", result.w, result.h); + gst_structure_set (desired_struct, "width", G_TYPE_INT, result.w, NULL); + gst_structure_set (desired_struct, "height", G_TYPE_INT, result.h, NULL); + + /* PAR property overrides the X calculated one */ + if (ximagesink->par) { + nom = gst_value_get_fraction_numerator (ximagesink->par); + den = gst_value_get_fraction_denominator (ximagesink->par); + gst_structure_set (desired_struct, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } else if (ximagesink->xcontext->par) { + nom = gst_value_get_fraction_numerator (ximagesink->xcontext->par); + den = gst_value_get_fraction_denominator (ximagesink->xcontext->par); + gst_structure_set (desired_struct, "pixel-aspect-ratio", + GST_TYPE_FRACTION, nom, den, NULL); + } + + + /* see if peer accepts our new suggestion, if there is no peer, this + * function returns true. */ + if (!ximagesink->xcontext->last_caps || + !gst_caps_is_equal (desired_caps, ximagesink->xcontext->last_caps)) { + caps_accepted = + gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (ximagesink), + desired_caps); + + /* Suggestion failed, prevent future attempts for the same caps + * to fail as well. */ + if (!caps_accepted) + gst_caps_replace (&ximagesink->xcontext->last_caps, desired_caps); + } + + if (caps_accepted) { + /* we will not alloc a buffer of the new suggested caps. Make sure + * we also unref this new caps after we set it on the buffer. */ + alloc_caps = desired_caps; + alloc_unref = TRUE; + width = result.w; + height = result.h; + GST_DEBUG ("peer pad accepts our desired caps %" GST_PTR_FORMAT, + desired_caps); + } else { + GST_DEBUG ("peer pad does not accept our desired caps %" GST_PTR_FORMAT, + desired_caps); + /* we alloc a buffer with the original incomming caps already in the + * width and height variables */ + gst_caps_unref (desired_caps); + } + } + +alloc: + /* Inspect our buffer pool */ + g_mutex_lock (ximagesink->pool_lock); + while (ximagesink->buffer_pool) { + ximage = (GstXImageBuffer *) ximagesink->buffer_pool->data; + + if (ximage) { + /* Removing from the pool */ + ximagesink->buffer_pool = g_slist_delete_link (ximagesink->buffer_pool, + ximagesink->buffer_pool); + + /* If the ximage is invalid for our need, destroy */ + if ((ximage->width != width) || (ximage->height != height)) { + gst_ximage_buffer_free (ximage); + ximage = NULL; + } else { + /* We found a suitable ximage */ + break; + } + } + } + g_mutex_unlock (ximagesink->pool_lock); + + /* We haven't found anything, creating a new one */ + if (!ximage) { + ximage = gst_ximagesink_ximage_new (ximagesink, alloc_caps); + } + /* Now we should have a ximage, set appropriate caps on it */ + if (ximage) { + /* Make sure the buffer is cleared of any previously used flags */ + GST_MINI_OBJECT_CAST (ximage)->flags = 0; + gst_buffer_set_caps (GST_BUFFER_CAST (ximage), alloc_caps); + } + + /* could be our new reffed suggestion or the original unreffed caps */ + if (alloc_unref) + gst_caps_unref (alloc_caps); + + *buf = GST_BUFFER_CAST (ximage); + +beach: + return ret; +} + +/* Interfaces stuff */ + +static gboolean +gst_ximagesink_interface_supported (GstImplementsInterface * iface, GType type) +{ + g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY); + return TRUE; +} + +static void +gst_ximagesink_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = gst_ximagesink_interface_supported; +} + +static void +gst_ximagesink_navigation_send_event (GstNavigation * navigation, + GstStructure * structure) +{ + GstXImageSink *ximagesink = GST_XIMAGESINK (navigation); + GstEvent *event; + gint x_offset, y_offset; + gdouble x, y; + GstPad *pad = NULL; + + event = gst_event_new_navigation (structure); + + /* We are not converting the pointer coordinates as there's no hardware + scaling done here. The only possible scaling is done by videoscale and + videoscale will have to catch those events and tranform the coordinates + to match the applied scaling. So here we just add the offset if the image + is centered in the window. */ + + /* We take the flow_lock while we look at the window */ + g_mutex_lock (ximagesink->flow_lock); + + if (!ximagesink->xwindow) { + g_mutex_unlock (ximagesink->flow_lock); + return; + } + + x_offset = ximagesink->xwindow->width - GST_VIDEO_SINK_WIDTH (ximagesink); + y_offset = ximagesink->xwindow->height - GST_VIDEO_SINK_HEIGHT (ximagesink); + + g_mutex_unlock (ximagesink->flow_lock); + + if (x_offset > 0 && gst_structure_get_double (structure, "pointer_x", &x)) { + x -= x_offset / 2; + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, x, NULL); + } + if (y_offset > 0 && gst_structure_get_double (structure, "pointer_y", &y)) { + y -= y_offset / 2; + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, y, NULL); + } + + pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (ximagesink)); + + if (GST_IS_PAD (pad) && GST_IS_EVENT (event)) { + gst_pad_send_event (pad, event); + + gst_object_unref (pad); + } +} + +static void +gst_ximagesink_navigation_init (GstNavigationInterface * iface) +{ + iface->send_event = gst_ximagesink_navigation_send_event; +} + +static void +gst_ximagesink_set_window_handle (GstXOverlay * overlay, guintptr id) +{ + XID xwindow_id = id; + GstXImageSink *ximagesink = GST_XIMAGESINK (overlay); + GstXWindow *xwindow = NULL; + XWindowAttributes attr; + + /* We acquire the stream lock while setting this window in the element. + We are basically cleaning tons of stuff replacing the old window, putting + images while we do that would surely crash */ + g_mutex_lock (ximagesink->flow_lock); + + /* If we already use that window return */ + if (ximagesink->xwindow && (xwindow_id == ximagesink->xwindow->win)) { + g_mutex_unlock (ximagesink->flow_lock); + return; + } + + /* If the element has not initialized the X11 context try to do so */ + if (!ximagesink->xcontext && + !(ximagesink->xcontext = gst_ximagesink_xcontext_get (ximagesink))) { + g_mutex_unlock (ximagesink->flow_lock); + /* we have thrown a GST_ELEMENT_ERROR now */ + return; + } + + /* If a window is there already we destroy it */ + if (ximagesink->xwindow) { + gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); + ximagesink->xwindow = NULL; + } + + /* If the xid is 0 we go back to an internal window */ + if (xwindow_id == 0) { + /* If no width/height caps nego did not happen window will be created + during caps nego then */ + if (GST_VIDEO_SINK_WIDTH (ximagesink) && GST_VIDEO_SINK_HEIGHT (ximagesink)) { + xwindow = gst_ximagesink_xwindow_new (ximagesink, + GST_VIDEO_SINK_WIDTH (ximagesink), + GST_VIDEO_SINK_HEIGHT (ximagesink)); + } + } else { + xwindow = g_new0 (GstXWindow, 1); + + xwindow->win = xwindow_id; + + /* We get window geometry, set the event we want to receive, + and create a GC */ + g_mutex_lock (ximagesink->x_lock); + XGetWindowAttributes (ximagesink->xcontext->disp, xwindow->win, &attr); + xwindow->width = attr.width; + xwindow->height = attr.height; + xwindow->internal = FALSE; + if (ximagesink->handle_events) { + XSelectInput (ximagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask); + } + + xwindow->gc = XCreateGC (ximagesink->xcontext->disp, xwindow->win, 0, NULL); + g_mutex_unlock (ximagesink->x_lock); + } + + if (xwindow) + ximagesink->xwindow = xwindow; + + g_mutex_unlock (ximagesink->flow_lock); +} + +static void +gst_ximagesink_expose (GstXOverlay * overlay) +{ + GstXImageSink *ximagesink = GST_XIMAGESINK (overlay); + + gst_ximagesink_xwindow_update_geometry (ximagesink); + gst_ximagesink_ximage_put (ximagesink, NULL); +} + +static void +gst_ximagesink_set_event_handling (GstXOverlay * overlay, + gboolean handle_events) +{ + GstXImageSink *ximagesink = GST_XIMAGESINK (overlay); + + ximagesink->handle_events = handle_events; + + g_mutex_lock (ximagesink->flow_lock); + + if (G_UNLIKELY (!ximagesink->xwindow)) { + g_mutex_unlock (ximagesink->flow_lock); + return; + } + + g_mutex_lock (ximagesink->x_lock); + + if (handle_events) { + if (ximagesink->xwindow->internal) { + XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, + ExposureMask | StructureNotifyMask | PointerMotionMask | + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); + } else { + XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, + ExposureMask | StructureNotifyMask | PointerMotionMask | + KeyPressMask | KeyReleaseMask); + } + } else { + XSelectInput (ximagesink->xcontext->disp, ximagesink->xwindow->win, 0); + } + + g_mutex_unlock (ximagesink->x_lock); + + g_mutex_unlock (ximagesink->flow_lock); +} + +static void +gst_ximagesink_xoverlay_init (GstXOverlayClass * iface) +{ + iface->set_window_handle = gst_ximagesink_set_window_handle; + iface->expose = gst_ximagesink_expose; + iface->handle_events = gst_ximagesink_set_event_handling; +} + +/* =========================================== */ +/* */ +/* Init & Class init */ +/* */ +/* =========================================== */ + +static void +gst_ximagesink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstXImageSink *ximagesink; + + g_return_if_fail (GST_IS_XIMAGESINK (object)); + + ximagesink = GST_XIMAGESINK (object); + + switch (prop_id) { + case PROP_DISPLAY: + ximagesink->display_name = g_strdup (g_value_get_string (value)); + break; + case PROP_SYNCHRONOUS: + ximagesink->synchronous = g_value_get_boolean (value); + if (ximagesink->xcontext) { + GST_DEBUG_OBJECT (ximagesink, "XSynchronize called with %s", + ximagesink->synchronous ? "TRUE" : "FALSE"); + g_mutex_lock (ximagesink->x_lock); + XSynchronize (ximagesink->xcontext->disp, ximagesink->synchronous); + g_mutex_unlock (ximagesink->x_lock); + } + break; + case PROP_FORCE_ASPECT_RATIO: + ximagesink->keep_aspect = g_value_get_boolean (value); + break; + case PROP_PIXEL_ASPECT_RATIO: + { + GValue *tmp; + + tmp = g_new0 (GValue, 1); + g_value_init (tmp, GST_TYPE_FRACTION); + + if (!g_value_transform (value, tmp)) { + GST_WARNING_OBJECT (ximagesink, + "Could not transform string to aspect ratio"); + g_free (tmp); + } else { + GST_DEBUG_OBJECT (ximagesink, "set PAR to %d/%d", + gst_value_get_fraction_numerator (tmp), + gst_value_get_fraction_denominator (tmp)); + g_free (ximagesink->par); + ximagesink->par = tmp; + } + } + break; + case PROP_HANDLE_EVENTS: + gst_ximagesink_set_event_handling (GST_X_OVERLAY (ximagesink), + g_value_get_boolean (value)); + gst_ximagesink_manage_event_thread (ximagesink); + break; + case PROP_HANDLE_EXPOSE: + ximagesink->handle_expose = g_value_get_boolean (value); + gst_ximagesink_manage_event_thread (ximagesink); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ximagesink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstXImageSink *ximagesink; + + g_return_if_fail (GST_IS_XIMAGESINK (object)); + + ximagesink = GST_XIMAGESINK (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, ximagesink->display_name); + break; + case PROP_SYNCHRONOUS: + g_value_set_boolean (value, ximagesink->synchronous); + break; + case PROP_FORCE_ASPECT_RATIO: + g_value_set_boolean (value, ximagesink->keep_aspect); + break; + case PROP_PIXEL_ASPECT_RATIO: + if (ximagesink->par) + g_value_transform (ximagesink->par, value); + break; + case PROP_HANDLE_EVENTS: + g_value_set_boolean (value, ximagesink->handle_events); + break; + case PROP_HANDLE_EXPOSE: + g_value_set_boolean (value, ximagesink->handle_expose); + break; + case PROP_WINDOW_WIDTH: + if (ximagesink->xwindow) + g_value_set_uint64 (value, ximagesink->xwindow->width); + else + g_value_set_uint64 (value, 0); + break; + case PROP_WINDOW_HEIGHT: + if (ximagesink->xwindow) + g_value_set_uint64 (value, ximagesink->xwindow->height); + else + g_value_set_uint64 (value, 0); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_ximagesink_reset (GstXImageSink * ximagesink) +{ + GThread *thread; + + GST_OBJECT_LOCK (ximagesink); + ximagesink->running = FALSE; + /* grab thread and mark it as NULL */ + thread = ximagesink->event_thread; + ximagesink->event_thread = NULL; + GST_OBJECT_UNLOCK (ximagesink); + + /* Wait for our event thread to finish before we clean up our stuff. */ + if (thread) + g_thread_join (thread); + + if (ximagesink->ximage) { + gst_buffer_unref (GST_BUFFER_CAST (ximagesink->ximage)); + ximagesink->ximage = NULL; + } + if (ximagesink->cur_image) { + gst_buffer_unref (GST_BUFFER_CAST (ximagesink->cur_image)); + ximagesink->cur_image = NULL; + } + + gst_ximagesink_bufferpool_clear (ximagesink); + + g_mutex_lock (ximagesink->flow_lock); + if (ximagesink->xwindow) { + gst_ximagesink_xwindow_clear (ximagesink, ximagesink->xwindow); + gst_ximagesink_xwindow_destroy (ximagesink, ximagesink->xwindow); + ximagesink->xwindow = NULL; + } + g_mutex_unlock (ximagesink->flow_lock); + + gst_ximagesink_xcontext_clear (ximagesink); +} + +static void +gst_ximagesink_finalize (GObject * object) +{ + GstXImageSink *ximagesink; + + ximagesink = GST_XIMAGESINK (object); + + gst_ximagesink_reset (ximagesink); + + if (ximagesink->display_name) { + g_free (ximagesink->display_name); + ximagesink->display_name = NULL; + } + if (ximagesink->par) { + g_free (ximagesink->par); + ximagesink->par = NULL; + } + if (ximagesink->x_lock) { + g_mutex_free (ximagesink->x_lock); + ximagesink->x_lock = NULL; + } + if (ximagesink->flow_lock) { + g_mutex_free (ximagesink->flow_lock); + ximagesink->flow_lock = NULL; + } + if (ximagesink->pool_lock) { + g_mutex_free (ximagesink->pool_lock); + ximagesink->pool_lock = NULL; + } + + g_free (ximagesink->media_title); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_ximagesink_init (GstXImageSink * ximagesink) +{ + ximagesink->display_name = NULL; + ximagesink->xcontext = NULL; + ximagesink->xwindow = NULL; + ximagesink->ximage = NULL; + ximagesink->cur_image = NULL; + + ximagesink->event_thread = NULL; + ximagesink->running = FALSE; + + ximagesink->fps_n = 0; + ximagesink->fps_d = 1; + + ximagesink->x_lock = g_mutex_new (); + ximagesink->flow_lock = g_mutex_new (); + + ximagesink->par = NULL; + + ximagesink->pool_lock = g_mutex_new (); + ximagesink->buffer_pool = NULL; + + ximagesink->synchronous = FALSE; + ximagesink->keep_aspect = FALSE; + ximagesink->handle_events = TRUE; + ximagesink->handle_expose = TRUE; +} + +static void +gst_ximagesink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Video sink", "Sink/Video", + "A standard X based videosink", "Julien Moutte "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_ximagesink_sink_template_factory)); +} + +static void +gst_ximagesink_class_init (GstXImageSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + GstVideoSinkClass *videosink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + videosink_class = (GstVideoSinkClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_ximagesink_finalize; + gobject_class->set_property = gst_ximagesink_set_property; + gobject_class->get_property = gst_ximagesink_get_property; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS, + g_param_spec_boolean ("synchronous", "Synchronous", "When enabled, runs " + "the X display in synchronous mode. (used only for debugging)", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, + g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio", + "When enabled, reverse caps negotiation (scaling) will respect " + "original aspect ratio", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO, + g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio", + "The pixel aspect ratio of the device", "1/1", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS, + g_param_spec_boolean ("handle-events", "Handle XEvents", + "When enabled, XEvents will be selected and handled", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE, + g_param_spec_boolean ("handle-expose", "Handle expose", + "When enabled, " + "the current frame will always be drawn in response to X Expose " + "events", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXImageSink:window-width + * + * Actual width of the video window. + * + * Since: 0.10.32 + */ + g_object_class_install_property (gobject_class, PROP_WINDOW_WIDTH, + g_param_spec_uint64 ("window-width", "window-width", + "Width of the window", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXImageSink:window-height + * + * Actual height of the video window. + * + * Since: 0.10.32 + */ + g_object_class_install_property (gobject_class, PROP_WINDOW_HEIGHT, + g_param_spec_uint64 ("window-height", "window-height", + "Height of the window", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = gst_ximagesink_change_state; + + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_getcaps); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_ximagesink_setcaps); + gstbasesink_class->buffer_alloc = + GST_DEBUG_FUNCPTR (gst_ximagesink_buffer_alloc); + gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_ximagesink_get_times); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_ximagesink_event); + + videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_ximagesink_show_frame); +} + +/* ============================================================= */ +/* */ +/* Public Methods */ +/* */ +/* ============================================================= */ + +/* =========================================== */ +/* */ +/* Object typing & Creation */ +/* */ +/* =========================================== */ + +GType +gst_ximagesink_get_type (void) +{ + static GType ximagesink_type = 0; + + if (!ximagesink_type) { + static const GTypeInfo ximagesink_info = { + sizeof (GstXImageSinkClass), + gst_ximagesink_base_init, + NULL, + (GClassInitFunc) gst_ximagesink_class_init, + NULL, + NULL, + sizeof (GstXImageSink), 0, (GInstanceInitFunc) gst_ximagesink_init, + }; + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) gst_ximagesink_interface_init, NULL, NULL, + }; + static const GInterfaceInfo navigation_info = { + (GInterfaceInitFunc) gst_ximagesink_navigation_init, NULL, NULL, + }; + static const GInterfaceInfo overlay_info = { + (GInterfaceInitFunc) gst_ximagesink_xoverlay_init, NULL, NULL, + }; + + ximagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, + "GstXImageSink", &ximagesink_info, 0); + + g_type_add_interface_static (ximagesink_type, GST_TYPE_IMPLEMENTS_INTERFACE, + &iface_info); + g_type_add_interface_static (ximagesink_type, GST_TYPE_NAVIGATION, + &navigation_info); + g_type_add_interface_static (ximagesink_type, GST_TYPE_X_OVERLAY, + &overlay_info); + + /* register type and create class in a more safe place instead of at + * runtime since the type registration and class creation is not + * threadsafe. */ + g_type_class_ref (gst_ximage_buffer_get_type ()); + } + + return ximagesink_type; +} diff --git a/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.h b/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.h new file mode 100644 index 0000000..83e973f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/ximage/ximagesink.h @@ -0,0 +1,234 @@ +/* GStreamer + * Copyright (C) <2005> Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_XIMAGESINK_H__ +#define __GST_XIMAGESINK_H__ + +#include + +#ifdef HAVE_XSHM +#include +#include +#include +#endif /* HAVE_XSHM */ + +#include +#include + +#ifdef HAVE_XSHM +#include +#endif /* HAVE_XSHM */ + +#include +#include + +G_BEGIN_DECLS +#define GST_TYPE_XIMAGESINK \ + (gst_ximagesink_get_type()) +#define GST_XIMAGESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XIMAGESINK, GstXImageSink)) +#define GST_XIMAGESINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XIMAGESINK, GstXImageSinkClass)) +#define GST_IS_XIMAGESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XIMAGESINK)) +#define GST_IS_XIMAGESINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XIMAGESINK)) +typedef struct _GstXContext GstXContext; +typedef struct _GstXWindow GstXWindow; + +typedef struct _GstXImageBuffer GstXImageBuffer; +typedef struct _GstXImageBufferClass GstXImageBufferClass; + +typedef struct _GstXImageSink GstXImageSink; +typedef struct _GstXImageSinkClass GstXImageSinkClass; + +/* + * GstXContext: + * @disp: the X11 Display of this context + * @screen: the default Screen of Display @disp + * @screen_num: the Screen number of @screen + * @visual: the default Visual of Screen @screen + * @root: the root Window of Display @disp + * @white: the value of a white pixel on Screen @screen + * @black: the value of a black pixel on Screen @screen + * @depth: the color depth of Display @disp + * @bpp: the number of bits per pixel on Display @disp + * @endianness: the endianness of image bytes on Display @disp + * @width: the width in pixels of Display @disp + * @height: the height in pixels of Display @disp + * @widthmm: the width in millimeters of Display @disp + * @heightmm: the height in millimeters of Display @disp + * @par: the pixel aspect ratio calculated from @width, @widthmm and @height, + * @heightmm ratio + * @use_xshm: used to known wether of not XShm extension is usable or not even + * if the Extension is present + * @caps: the #GstCaps that Display @disp can accept + * + * Structure used to store various informations collected/calculated for a + * Display. + */ +struct _GstXContext +{ + Display *disp; + + Screen *screen; + gint screen_num; + + Visual *visual; + + Window root; + + gulong white, black; + + gint depth; + gint bpp; + gint endianness; + + gint width, height; + gint widthmm, heightmm; + GValue *par; /* calculated pixel aspect ratio */ + + gboolean use_xshm; + + GstCaps *caps; + GstCaps *last_caps; +}; + +/* + * GstXWindow: + * @win: the Window ID of this X11 window + * @width: the width in pixels of Window @win + * @height: the height in pixels of Window @win + * @internal: used to remember if Window @win was created internally or passed + * through the #GstXOverlay interface + * @gc: the Graphical Context of Window @win + * + * Structure used to store informations about a Window. + */ +struct _GstXWindow +{ + Window win; + gint width, height; + gboolean internal; + GC gc; +}; + +/** + * GstXImageBuffer: + * @ximagesink: a reference to our #GstXImageSink + * @ximage: the XImage of this buffer + * @width: the width in pixels of XImage @ximage + * @height: the height in pixels of XImage @ximage + * @size: the size in bytes of XImage @ximage + * + * Subclass of #GstBuffer containing additional information about an XImage. + */ +struct _GstXImageBuffer +{ + GstBuffer buffer; + + /* Reference to the ximagesink we belong to */ + GstXImageSink *ximagesink; + + XImage *ximage; + +#ifdef HAVE_XSHM + XShmSegmentInfo SHMInfo; +#endif /* HAVE_XSHM */ + + gint width, height; + size_t size; +}; + +/** + * GstXImageSink: + * @display_name: the name of the Display we want to render to + * @xcontext: our instance's #GstXContext + * @xwindow: the #GstXWindow we are rendering to + * @ximage: internal #GstXImage used to store incoming buffers and render when + * not using the buffer_alloc optimization mechanism + * @cur_image: a reference to the last #GstXImage that was put to @xwindow. It + * is used when Expose events are received to redraw the latest video frame + * @event_thread: a thread listening for events on @xwindow and handling them + * @running: used to inform @event_thread if it should run/shutdown + * @fps_n: the framerate fraction numerator + * @fps_d: the framerate fraction denominator + * @x_lock: used to protect X calls as we are not using the XLib in threaded + * mode + * @flow_lock: used to protect data flow routines from external calls such as + * events from @event_thread or methods from the #GstXOverlay interface + * @par: used to override calculated pixel aspect ratio from @xcontext + * @pool_lock: used to protect the buffer pool + * @buffer_pool: a list of #GstXImageBuffer that could be reused at next buffer + * allocation call + * @synchronous: used to store if XSynchronous should be used or not (for + * debugging purpose only) + * @keep_aspect: used to remember if reverse negotiation scaling should respect + * aspect ratio + * @handle_events: used to know if we should handle select XEvents or not + * + * The #GstXImageSink data structure. + */ +struct _GstXImageSink +{ + /* Our element stuff */ + GstVideoSink videosink; + + char *display_name; + + GstXContext *xcontext; + GstXWindow *xwindow; + GstXImageBuffer *ximage; + GstXImageBuffer *cur_image; + + GThread *event_thread; + gboolean running; + + /* Framerate numerator and denominator */ + gint fps_n; + gint fps_d; + + GMutex *x_lock; + GMutex *flow_lock; + + /* object-set pixel aspect ratio */ + GValue *par; + + GMutex *pool_lock; + GSList *buffer_pool; + + gboolean synchronous; + gboolean keep_aspect; + gboolean handle_events; + gboolean handle_expose; + gboolean draw_border; + + /* stream metadata */ + gchar *media_title; +}; + +struct _GstXImageSinkClass +{ + GstVideoSinkClass parent_class; +}; + +GType gst_ximagesink_get_type (void); + +G_END_DECLS +#endif /* __GST_XIMAGESINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/sys/xvimage/Makefile.am b/gst-plugins-base-subtitles0.10/sys/xvimage/Makefile.am new file mode 100644 index 0000000..fbff4d8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/xvimage/Makefile.am @@ -0,0 +1,15 @@ +plugin_LTLIBRARIES = libgstxvimagesink.la + +libgstxvimagesink_la_SOURCES = xvimagesink.c +libgstxvimagesink_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) +libgstxvimagesink_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) \ + $(GST_LIBS) \ + $(X_LIBS) $(XVIDEO_LIBS) $(XSHM_LIBS) $(LIBM) +libgstxvimagesink_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstxvimagesink_la_DEPENDENCIES = $(top_builddir)/gst-libs/gst/video/libgstvideo-$(GST_MAJORMINOR).la +libgstxvimagesink_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = xvimagesink.h diff --git a/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.c b/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.c new file mode 100644 index 0000000..30368d5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.c @@ -0,0 +1,3784 @@ +/* GStreamer + * Copyright (C) <2005> Julien Moutte + * <2009>,<2010> Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-xvimagesink + * + * XvImageSink renders video frames to a drawable (XWindow) on a local display + * using the XVideo extension. Rendering to a remote display is theorically + * possible but i doubt that the XVideo extension is actually available when + * connecting to a remote display. This element can receive a Window ID from the + * application through the XOverlay interface and will then render video frames + * in this drawable. If no Window ID was provided by the application, the + * element will create its own internal window and render into it. + * + * + * Scaling + * + * The XVideo extension, when it's available, handles hardware accelerated + * scaling of video frames. This means that the element will just accept + * incoming video frames no matter their geometry and will then put them to the + * drawable scaling them on the fly. Using the #GstXvImageSink:force-aspect-ratio + * property it is possible to enforce scaling with a constant aspect ratio, + * which means drawing black borders around the video frame. + * + * + * + * Events + * + * XvImageSink creates a thread to handle events coming from the drawable. There + * are several kind of events that can be grouped in 2 big categories: input + * events and window state related events. Input events will be translated to + * navigation events and pushed upstream for other elements to react on them. + * This includes events such as pointer moves, key press/release, clicks etc... + * Other events are used to handle the drawable appearance even when the data + * is not flowing (GST_STATE_PAUSED). That means that even when the element is + * paused, it will receive expose events from the drawable and draw the latest + * frame with correct borders/aspect-ratio. + * + * + * + * Pixel aspect ratio + * + * When changing state to GST_STATE_READY, XvImageSink will open a connection to + * the display specified in the #GstXvImageSink:display property or the + * default display if nothing specified. Once this connection is open it will + * inspect the display configuration including the physical display geometry and + * then calculate the pixel aspect ratio. When receiving video frames with a + * different pixel aspect ratio, XvImageSink will use hardware scaling to + * display the video frames correctly on display's pixel aspect ratio. + * Sometimes the calculated pixel aspect ratio can be wrong, it is + * then possible to enforce a specific pixel aspect ratio using the + * #GstXvImageSink:pixel-aspect-ratio property. + * + * + * + * Examples + * |[ + * gst-launch -v videotestsrc ! xvimagesink + * ]| A pipeline to test hardware scaling. + * When the test video signal appears you can resize the window and see that + * video frames are scaled through hardware (no extra CPU cost). + * |[ + * gst-launch -v videotestsrc ! xvimagesink force-aspect-ratio=true + * ]| Same pipeline with #GstXvImageSink:force-aspect-ratio property set to true + * You can observe the borders drawn around the scaled image respecting aspect + * ratio. + * |[ + * gst-launch -v videotestsrc ! navigationtest ! xvimagesink + * ]| A pipeline to test navigation events. + * While moving the mouse pointer over the test signal you will see a black box + * following the mouse pointer. If you press the mouse button somewhere on the + * video and release it somewhere else a green box will appear where you pressed + * the button and a red one where you released it. (The navigationtest element + * is part of gst-plugins-good.) You can observe here that even if the images + * are scaled through hardware the pointer coordinates are converted back to the + * original video frame geometry so that the box can be drawn to the correct + * position. This also handles borders correctly, limiting coordinates to the + * image area + * |[ + * gst-launch -v videotestsrc ! video/x-raw-yuv, pixel-aspect-ratio=(fraction)4/3 ! xvimagesink + * ]| This is faking a 4/3 pixel aspect ratio caps on video frames produced by + * videotestsrc, in most cases the pixel aspect ratio of the display will be + * 1/1. This means that XvImageSink will have to do the scaling to convert + * incoming frames to a size that will match the display pixel aspect ratio + * (from 320x240 to 320x180 in this case). Note that you might have to escape + * some characters for your shell like '\(fraction\)'. + * |[ + * gst-launch -v videotestsrc ! xvimagesink hue=100 saturation=-100 brightness=100 + * ]| Demonstrates how to use the colorbalance interface. + * + */ + +/* for developers: there are two useful tools : xvinfo and xvattr */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +/* Our interfaces */ +#include +#include +#include +#include +/* Helper functions */ +#include + +/* Object header */ +#include "xvimagesink.h" + +/* Debugging category */ +#include +GST_DEBUG_CATEGORY_STATIC (gst_debug_xvimagesink); +#define GST_CAT_DEFAULT gst_debug_xvimagesink +GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); + +typedef struct +{ + unsigned long flags; + unsigned long functions; + unsigned long decorations; + long input_mode; + unsigned long status; +} +MotifWmHints, MwmHints; + +#define MWM_HINTS_DECORATIONS (1L << 1) + +static void gst_xvimagesink_reset (GstXvImageSink * xvimagesink); + +static GstBufferClass *xvimage_buffer_parent_class = NULL; +static void gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage); + +static void gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * + xvimagesink); +static gint gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink, + GstCaps * caps); +static void gst_xvimagesink_expose (GstXOverlay * overlay); + +/* Default template - initiated with class struct to allow gst-register to work + without X running */ +static GstStaticPadTemplate gst_xvimagesink_sink_template_factory = + GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-rgb, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ]; " + "video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]") + ); + +enum +{ + PROP_0, + PROP_CONTRAST, + PROP_BRIGHTNESS, + PROP_HUE, + PROP_SATURATION, + PROP_DISPLAY, + PROP_SYNCHRONOUS, + PROP_PIXEL_ASPECT_RATIO, + PROP_FORCE_ASPECT_RATIO, + PROP_HANDLE_EVENTS, + PROP_DEVICE, + PROP_DEVICE_NAME, + PROP_HANDLE_EXPOSE, + PROP_DOUBLE_BUFFER, + PROP_AUTOPAINT_COLORKEY, + PROP_COLORKEY, + PROP_DRAW_BORDERS, + PROP_WINDOW_WIDTH, + PROP_WINDOW_HEIGHT +}; + +static GstVideoSinkClass *parent_class = NULL; + +/* ============================================================= */ +/* */ +/* Private Methods */ +/* */ +/* ============================================================= */ + +/* xvimage buffers */ + +#define GST_TYPE_XVIMAGE_BUFFER (gst_xvimage_buffer_get_type()) + +#define GST_IS_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_XVIMAGE_BUFFER)) +#define GST_XVIMAGE_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_XVIMAGE_BUFFER, GstXvImageBuffer)) +#define GST_XVIMAGE_BUFFER_CAST(obj) ((GstXvImageBuffer *)(obj)) + +/* This function destroys a GstXvImage handling XShm availability */ +static void +gst_xvimage_buffer_destroy (GstXvImageBuffer * xvimage) +{ + GstXvImageSink *xvimagesink; + + GST_DEBUG_OBJECT (xvimage, "Destroying buffer"); + + xvimagesink = xvimage->xvimagesink; + if (G_UNLIKELY (xvimagesink == NULL)) + goto no_sink; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + GST_OBJECT_LOCK (xvimagesink); + + /* If the destroyed image is the current one we destroy our reference too */ + if (xvimagesink->cur_image == xvimage) + xvimagesink->cur_image = NULL; + + /* We might have some buffers destroyed after changing state to NULL */ + if (xvimagesink->xcontext == NULL) { + GST_DEBUG_OBJECT (xvimagesink, "Destroying XvImage after Xcontext"); +#ifdef HAVE_XSHM + /* Need to free the shared memory segment even if the x context + * was already cleaned up */ + if (xvimage->SHMInfo.shmaddr != ((void *) -1)) { + shmdt (xvimage->SHMInfo.shmaddr); + } +#endif + goto beach; + } + + g_mutex_lock (xvimagesink->x_lock); + +#ifdef HAVE_XSHM + if (xvimagesink->xcontext->use_xshm) { + if (xvimage->SHMInfo.shmaddr != ((void *) -1)) { + GST_DEBUG_OBJECT (xvimagesink, "XServer ShmDetaching from 0x%x id 0x%lx", + xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg); + XShmDetach (xvimagesink->xcontext->disp, &xvimage->SHMInfo); + XSync (xvimagesink->xcontext->disp, FALSE); + + shmdt (xvimage->SHMInfo.shmaddr); + } + if (xvimage->xvimage) + XFree (xvimage->xvimage); + } else +#endif /* HAVE_XSHM */ + { + if (xvimage->xvimage) { + if (xvimage->xvimage->data) { + g_free (xvimage->xvimage->data); + } + XFree (xvimage->xvimage); + } + } + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); + +beach: + GST_OBJECT_UNLOCK (xvimagesink); + xvimage->xvimagesink = NULL; + gst_object_unref (xvimagesink); + + GST_MINI_OBJECT_CLASS (xvimage_buffer_parent_class)->finalize (GST_MINI_OBJECT + (xvimage)); + + return; + +no_sink: + { + GST_WARNING ("no sink found"); + return; + } +} + +static void +gst_xvimage_buffer_finalize (GstXvImageBuffer * xvimage) +{ + GstXvImageSink *xvimagesink; + gboolean running; + + xvimagesink = xvimage->xvimagesink; + if (G_UNLIKELY (xvimagesink == NULL)) + goto no_sink; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + GST_OBJECT_LOCK (xvimagesink); + running = xvimagesink->running; + GST_OBJECT_UNLOCK (xvimagesink); + + /* If our geometry changed we can't reuse that image. */ + if (running == FALSE) { + GST_LOG_OBJECT (xvimage, "destroy image as sink is shutting down"); + gst_xvimage_buffer_destroy (xvimage); + } else if ((xvimage->width != xvimagesink->video_width) || + (xvimage->height != xvimagesink->video_height)) { + GST_LOG_OBJECT (xvimage, + "destroy image as its size changed %dx%d vs current %dx%d", + xvimage->width, xvimage->height, + xvimagesink->video_width, xvimagesink->video_height); + gst_xvimage_buffer_destroy (xvimage); + } else { + /* In that case we can reuse the image and add it to our image pool. */ + GST_LOG_OBJECT (xvimage, "recycling image in pool"); + /* need to increment the refcount again to recycle */ + gst_buffer_ref (GST_BUFFER_CAST (xvimage)); + g_mutex_lock (xvimagesink->pool_lock); + xvimagesink->image_pool = g_slist_prepend (xvimagesink->image_pool, + xvimage); + g_mutex_unlock (xvimagesink->pool_lock); + } + return; + +no_sink: + { + GST_WARNING ("no sink found"); + return; + } +} + +static void +gst_xvimage_buffer_free (GstXvImageBuffer * xvimage) +{ + /* make sure it is not recycled */ + xvimage->width = -1; + xvimage->height = -1; + gst_buffer_unref (GST_BUFFER (xvimage)); +} + +static void +gst_xvimage_buffer_init (GstXvImageBuffer * xvimage, gpointer g_class) +{ +#ifdef HAVE_XSHM + xvimage->SHMInfo.shmaddr = ((void *) -1); + xvimage->SHMInfo.shmid = -1; +#endif +} + +static void +gst_xvimage_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + xvimage_buffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_xvimage_buffer_finalize; +} + +static GType +gst_xvimage_buffer_get_type (void) +{ + static GType _gst_xvimage_buffer_type; + + if (G_UNLIKELY (_gst_xvimage_buffer_type == 0)) { + static const GTypeInfo xvimage_buffer_info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_xvimage_buffer_class_init, + NULL, + NULL, + sizeof (GstXvImageBuffer), + 0, + (GInstanceInitFunc) gst_xvimage_buffer_init, + NULL + }; + _gst_xvimage_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstXvImageBuffer", &xvimage_buffer_info, 0); + } + return _gst_xvimage_buffer_type; +} + +/* X11 stuff */ + +static gboolean error_caught = FALSE; + +static int +gst_xvimagesink_handle_xerror (Display * display, XErrorEvent * xevent) +{ + char error_msg[1024]; + + XGetErrorText (display, xevent->error_code, error_msg, 1024); + GST_DEBUG ("xvimagesink triggered an XError. error: %s", error_msg); + error_caught = TRUE; + return 0; +} + +#ifdef HAVE_XSHM +/* This function checks that it is actually really possible to create an image + using XShm */ +static gboolean +gst_xvimagesink_check_xshm_calls (GstXContext * xcontext) +{ + XvImage *xvimage; + XShmSegmentInfo SHMInfo; + gint size; + int (*handler) (Display *, XErrorEvent *); + gboolean result = FALSE; + gboolean did_attach = FALSE; + + g_return_val_if_fail (xcontext != NULL, FALSE); + + /* Sync to ensure any older errors are already processed */ + XSync (xcontext->disp, FALSE); + + /* Set defaults so we don't free these later unnecessarily */ + SHMInfo.shmaddr = ((void *) -1); + SHMInfo.shmid = -1; + + /* Setting an error handler to catch failure */ + error_caught = FALSE; + handler = XSetErrorHandler (gst_xvimagesink_handle_xerror); + + /* Trying to create a 1x1 picture */ + GST_DEBUG ("XvShmCreateImage of 1x1"); + xvimage = XvShmCreateImage (xcontext->disp, xcontext->xv_port_id, + xcontext->im_format, NULL, 1, 1, &SHMInfo); + + /* Might cause an error, sync to ensure it is noticed */ + XSync (xcontext->disp, FALSE); + if (!xvimage || error_caught) { + GST_WARNING ("could not XvShmCreateImage a 1x1 image"); + goto beach; + } + size = xvimage->data_size; + + SHMInfo.shmid = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777); + if (SHMInfo.shmid == -1) { + GST_WARNING ("could not get shared memory of %d bytes", size); + goto beach; + } + + SHMInfo.shmaddr = shmat (SHMInfo.shmid, NULL, 0); + if (SHMInfo.shmaddr == ((void *) -1)) { + GST_WARNING ("Failed to shmat: %s", g_strerror (errno)); + /* Clean up the shared memory segment */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + goto beach; + } + + xvimage->data = SHMInfo.shmaddr; + SHMInfo.readOnly = FALSE; + + if (XShmAttach (xcontext->disp, &SHMInfo) == 0) { + GST_WARNING ("Failed to XShmAttach"); + /* Clean up the shared memory segment */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + goto beach; + } + + /* Sync to ensure we see any errors we caused */ + XSync (xcontext->disp, FALSE); + + /* Delete the shared memory segment as soon as everyone is attached. + * This way, it will be deleted as soon as we detach later, and not + * leaked if we crash. */ + shmctl (SHMInfo.shmid, IPC_RMID, NULL); + + if (!error_caught) { + GST_DEBUG ("XServer ShmAttached to 0x%x, id 0x%lx", SHMInfo.shmid, + SHMInfo.shmseg); + + did_attach = TRUE; + /* store whether we succeeded in result */ + result = TRUE; + } else { + GST_WARNING ("MIT-SHM extension check failed at XShmAttach. " + "Not using shared memory."); + } + +beach: + /* Sync to ensure we swallow any errors we caused and reset error_caught */ + XSync (xcontext->disp, FALSE); + + error_caught = FALSE; + XSetErrorHandler (handler); + + if (did_attach) { + GST_DEBUG ("XServer ShmDetaching from 0x%x id 0x%lx", + SHMInfo.shmid, SHMInfo.shmseg); + XShmDetach (xcontext->disp, &SHMInfo); + XSync (xcontext->disp, FALSE); + } + if (SHMInfo.shmaddr != ((void *) -1)) + shmdt (SHMInfo.shmaddr); + if (xvimage) + XFree (xvimage); + return result; +} +#endif /* HAVE_XSHM */ + +/* This function handles GstXvImage creation depending on XShm availability */ +static GstXvImageBuffer * +gst_xvimagesink_xvimage_new (GstXvImageSink * xvimagesink, GstCaps * caps) +{ + GstXvImageBuffer *xvimage = NULL; + GstStructure *structure = NULL; + gboolean succeeded = FALSE; + int (*handler) (Display *, XErrorEvent *); + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + + if (caps == NULL) + return NULL; + + xvimage = (GstXvImageBuffer *) gst_mini_object_new (GST_TYPE_XVIMAGE_BUFFER); + GST_DEBUG_OBJECT (xvimage, "Creating new XvImageBuffer"); + + structure = gst_caps_get_structure (caps, 0); + + if (!gst_structure_get_int (structure, "width", &xvimage->width) || + !gst_structure_get_int (structure, "height", &xvimage->height)) { + GST_WARNING ("failed getting geometry from caps %" GST_PTR_FORMAT, caps); + } + + GST_LOG_OBJECT (xvimagesink, "creating %dx%d", xvimage->width, + xvimage->height); + + xvimage->im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps); + if (xvimage->im_format == -1) { + GST_WARNING_OBJECT (xvimagesink, "failed to get format from caps %" + GST_PTR_FORMAT, caps); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimage->width, xvimage->height), ("Invalid input caps")); + goto beach_unlocked; + } + xvimage->xvimagesink = gst_object_ref (xvimagesink); + + g_mutex_lock (xvimagesink->x_lock); + + /* Setting an error handler to catch failure */ + error_caught = FALSE; + handler = XSetErrorHandler (gst_xvimagesink_handle_xerror); + +#ifdef HAVE_XSHM + if (xvimagesink->xcontext->use_xshm) { + int expected_size; + + xvimage->xvimage = XvShmCreateImage (xvimagesink->xcontext->disp, + xvimagesink->xcontext->xv_port_id, + xvimage->im_format, NULL, + xvimage->width, xvimage->height, &xvimage->SHMInfo); + if (!xvimage->xvimage || error_caught) { + g_mutex_unlock (xvimagesink->x_lock); + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + /* Push an error */ + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimage->width, xvimage->height), + ("could not XvShmCreateImage a %dx%d image", + xvimage->width, xvimage->height)); + goto beach_unlocked; + } + + /* we have to use the returned data_size for our shm size */ + xvimage->size = xvimage->xvimage->data_size; + GST_LOG_OBJECT (xvimagesink, "XShm image size is %" G_GSIZE_FORMAT, + xvimage->size); + + /* calculate the expected size. This is only for sanity checking the + * number we get from X. */ + switch (xvimage->im_format) { + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + { + gint pitches[3]; + gint offsets[3]; + guint plane; + + offsets[0] = 0; + pitches[0] = GST_ROUND_UP_4 (xvimage->width); + offsets[1] = offsets[0] + pitches[0] * GST_ROUND_UP_2 (xvimage->height); + pitches[1] = GST_ROUND_UP_8 (xvimage->width) / 2; + offsets[2] = + offsets[1] + pitches[1] * GST_ROUND_UP_2 (xvimage->height) / 2; + pitches[2] = GST_ROUND_UP_8 (pitches[0]) / 2; + + expected_size = + offsets[2] + pitches[2] * GST_ROUND_UP_2 (xvimage->height) / 2; + + for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) { + GST_DEBUG_OBJECT (xvimagesink, + "Plane %u has a expected pitch of %d bytes, " "offset of %d", + plane, pitches[plane], offsets[plane]); + } + break; + } + case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'): + case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'): + expected_size = xvimage->height * GST_ROUND_UP_4 (xvimage->width * 2); + break; + default: + expected_size = 0; + break; + } + if (expected_size != 0 && xvimage->size != expected_size) { + GST_WARNING_OBJECT (xvimagesink, + "unexpected XShm image size (got %" G_GSIZE_FORMAT ", expected %d)", + xvimage->size, expected_size); + } + + /* Be verbose about our XvImage stride */ + { + guint plane; + + for (plane = 0; plane < xvimage->xvimage->num_planes; plane++) { + GST_DEBUG_OBJECT (xvimagesink, "Plane %u has a pitch of %d bytes, " + "offset of %d", plane, xvimage->xvimage->pitches[plane], + xvimage->xvimage->offsets[plane]); + } + } + + xvimage->SHMInfo.shmid = shmget (IPC_PRIVATE, xvimage->size, + IPC_CREAT | 0777); + if (xvimage->SHMInfo.shmid == -1) { + g_mutex_unlock (xvimagesink->x_lock); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimage->width, xvimage->height), + ("could not get shared memory of %" G_GSIZE_FORMAT " bytes", + xvimage->size)); + goto beach_unlocked; + } + + xvimage->SHMInfo.shmaddr = shmat (xvimage->SHMInfo.shmid, NULL, 0); + if (xvimage->SHMInfo.shmaddr == ((void *) -1)) { + g_mutex_unlock (xvimagesink->x_lock); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimage->width, xvimage->height), + ("Failed to shmat: %s", g_strerror (errno))); + /* Clean up the shared memory segment */ + shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL); + goto beach_unlocked; + } + + xvimage->xvimage->data = xvimage->SHMInfo.shmaddr; + xvimage->SHMInfo.readOnly = FALSE; + + if (XShmAttach (xvimagesink->xcontext->disp, &xvimage->SHMInfo) == 0) { + /* Clean up the shared memory segment */ + shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL); + + g_mutex_unlock (xvimagesink->x_lock); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimage->width, xvimage->height), ("Failed to XShmAttach")); + goto beach_unlocked; + } + + XSync (xvimagesink->xcontext->disp, FALSE); + + /* Delete the shared memory segment as soon as we everyone is attached. + * This way, it will be deleted as soon as we detach later, and not + * leaked if we crash. */ + shmctl (xvimage->SHMInfo.shmid, IPC_RMID, NULL); + + GST_DEBUG_OBJECT (xvimagesink, "XServer ShmAttached to 0x%x, id 0x%lx", + xvimage->SHMInfo.shmid, xvimage->SHMInfo.shmseg); + } else +#endif /* HAVE_XSHM */ + { + xvimage->xvimage = XvCreateImage (xvimagesink->xcontext->disp, + xvimagesink->xcontext->xv_port_id, + xvimage->im_format, NULL, xvimage->width, xvimage->height); + if (!xvimage->xvimage || error_caught) { + g_mutex_unlock (xvimagesink->x_lock); + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + /* Push an error */ + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create outputimage buffer of %dx%d pixels", + xvimage->width, xvimage->height), + ("could not XvCreateImage a %dx%d image", + xvimage->width, xvimage->height)); + goto beach_unlocked; + } + + /* we have to use the returned data_size for our image size */ + xvimage->size = xvimage->xvimage->data_size; + xvimage->xvimage->data = g_malloc (xvimage->size); + + XSync (xvimagesink->xcontext->disp, FALSE); + } + + /* Reset error handler */ + error_caught = FALSE; + XSetErrorHandler (handler); + + succeeded = TRUE; + + GST_BUFFER_DATA (xvimage) = (guchar *) xvimage->xvimage->data; + GST_BUFFER_SIZE (xvimage) = xvimage->size; + + g_mutex_unlock (xvimagesink->x_lock); + +beach_unlocked: + if (!succeeded) { + gst_xvimage_buffer_free (xvimage); + xvimage = NULL; + } + + return xvimage; +} + +/* We are called with the x_lock taken */ +static void +gst_xvimagesink_xwindow_draw_borders (GstXvImageSink * xvimagesink, + GstXWindow * xwindow, GstVideoRectangle rect) +{ + gint t1, t2; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (xwindow != NULL); + + XSetForeground (xvimagesink->xcontext->disp, xwindow->gc, + xvimagesink->xcontext->black); + + /* Left border */ + if (rect.x > xvimagesink->render_rect.x) { + XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, + xvimagesink->render_rect.x, xvimagesink->render_rect.y, + rect.x - xvimagesink->render_rect.x, xvimagesink->render_rect.h); + } + + /* Right border */ + t1 = rect.x + rect.w; + t2 = xvimagesink->render_rect.x + xvimagesink->render_rect.w; + if (t1 < t2) { + XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, + t1, xvimagesink->render_rect.y, t2 - t1, xvimagesink->render_rect.h); + } + + /* Top border */ + if (rect.y > xvimagesink->render_rect.y) { + XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, + xvimagesink->render_rect.x, xvimagesink->render_rect.y, + xvimagesink->render_rect.w, rect.y - xvimagesink->render_rect.y); + } + + /* Bottom border */ + t1 = rect.y + rect.h; + t2 = xvimagesink->render_rect.y + xvimagesink->render_rect.h; + if (t1 < t2) { + XFillRectangle (xvimagesink->xcontext->disp, xwindow->win, xwindow->gc, + xvimagesink->render_rect.x, t1, xvimagesink->render_rect.w, t2 - t1); + } +} + +/* This function puts a GstXvImage on a GstXvImageSink's window. Returns FALSE + * if no window was available */ +static gboolean +gst_xvimagesink_xvimage_put (GstXvImageSink * xvimagesink, + GstXvImageBuffer * xvimage) +{ + GstVideoRectangle result; + gboolean draw_border = FALSE; + + /* We take the flow_lock. If expose is in there we don't want to run + concurrently from the data flow thread */ + g_mutex_lock (xvimagesink->flow_lock); + + if (G_UNLIKELY (xvimagesink->xwindow == NULL)) { + g_mutex_unlock (xvimagesink->flow_lock); + return FALSE; + } + + /* Draw borders when displaying the first frame. After this + draw borders only on expose event or after a size change. */ + if (!xvimagesink->cur_image || xvimagesink->redraw_border) { + draw_border = TRUE; + } + + /* Store a reference to the last image we put, lose the previous one */ + if (xvimage && xvimagesink->cur_image != xvimage) { + if (xvimagesink->cur_image) { + GST_LOG_OBJECT (xvimagesink, "unreffing %p", xvimagesink->cur_image); + gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image)); + } + GST_LOG_OBJECT (xvimagesink, "reffing %p as our current image", xvimage); + xvimagesink->cur_image = + GST_XVIMAGE_BUFFER_CAST (gst_buffer_ref (GST_BUFFER_CAST (xvimage))); + } + + /* Expose sends a NULL image, we take the latest frame */ + if (!xvimage) { + if (xvimagesink->cur_image) { + draw_border = TRUE; + xvimage = xvimagesink->cur_image; + } else { + g_mutex_unlock (xvimagesink->flow_lock); + return TRUE; + } + } + + if (xvimagesink->keep_aspect) { + GstVideoRectangle src, dst; + + /* We use the calculated geometry from _setcaps as a source to respect + source and screen pixel aspect ratios. */ + src.w = GST_VIDEO_SINK_WIDTH (xvimagesink); + src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink); + dst.w = xvimagesink->render_rect.w; + dst.h = xvimagesink->render_rect.h; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + result.x += xvimagesink->render_rect.x; + result.y += xvimagesink->render_rect.y; + } else { + memcpy (&result, &xvimagesink->render_rect, sizeof (GstVideoRectangle)); + } + + g_mutex_lock (xvimagesink->x_lock); + + if (draw_border && xvimagesink->draw_borders) { + gst_xvimagesink_xwindow_draw_borders (xvimagesink, xvimagesink->xwindow, + result); + xvimagesink->redraw_border = FALSE; + } + + /* We scale to the window's geometry */ +#ifdef HAVE_XSHM + if (xvimagesink->xcontext->use_xshm) { + GST_LOG_OBJECT (xvimagesink, + "XvShmPutImage with image %dx%d and window %dx%d, from xvimage %" + GST_PTR_FORMAT, + xvimage->width, xvimage->height, + xvimagesink->render_rect.w, xvimagesink->render_rect.h, xvimage); + + XvShmPutImage (xvimagesink->xcontext->disp, + xvimagesink->xcontext->xv_port_id, + xvimagesink->xwindow->win, + xvimagesink->xwindow->gc, xvimage->xvimage, + xvimagesink->disp_x, xvimagesink->disp_y, + xvimagesink->disp_width, xvimagesink->disp_height, + result.x, result.y, result.w, result.h, FALSE); + } else +#endif /* HAVE_XSHM */ + { + XvPutImage (xvimagesink->xcontext->disp, + xvimagesink->xcontext->xv_port_id, + xvimagesink->xwindow->win, + xvimagesink->xwindow->gc, xvimage->xvimage, + xvimagesink->disp_x, xvimagesink->disp_y, + xvimagesink->disp_width, xvimagesink->disp_height, + result.x, result.y, result.w, result.h); + } + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); + + g_mutex_unlock (xvimagesink->flow_lock); + + return TRUE; +} + +static gboolean +gst_xvimagesink_xwindow_decorate (GstXvImageSink * xvimagesink, + GstXWindow * window) +{ + Atom hints_atom = None; + MotifWmHints *hints; + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), FALSE); + g_return_val_if_fail (window != NULL, FALSE); + + g_mutex_lock (xvimagesink->x_lock); + + hints_atom = XInternAtom (xvimagesink->xcontext->disp, "_MOTIF_WM_HINTS", + True); + if (hints_atom == None) { + g_mutex_unlock (xvimagesink->x_lock); + return FALSE; + } + + hints = g_malloc0 (sizeof (MotifWmHints)); + + hints->flags |= MWM_HINTS_DECORATIONS; + hints->decorations = 1 << 0; + + XChangeProperty (xvimagesink->xcontext->disp, window->win, + hints_atom, hints_atom, 32, PropModeReplace, + (guchar *) hints, sizeof (MotifWmHints) / sizeof (long)); + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); + + g_free (hints); + + return TRUE; +} + +static void +gst_xvimagesink_xwindow_set_title (GstXvImageSink * xvimagesink, + GstXWindow * xwindow, const gchar * media_title) +{ + if (media_title) { + g_free (xvimagesink->media_title); + xvimagesink->media_title = g_strdup (media_title); + } + if (xwindow) { + /* we have a window */ + if (xwindow->internal) { + XTextProperty xproperty; + const gchar *app_name; + const gchar *title = NULL; + gchar *title_mem = NULL; + + /* set application name as a title */ + app_name = g_get_application_name (); + + if (app_name && xvimagesink->media_title) { + title = title_mem = g_strconcat (xvimagesink->media_title, " : ", + app_name, NULL); + } else if (app_name) { + title = app_name; + } else if (xvimagesink->media_title) { + title = xvimagesink->media_title; + } + + if (title) { + if ((XStringListToTextProperty (((char **) &title), 1, + &xproperty)) != 0) { + XSetWMName (xvimagesink->xcontext->disp, xwindow->win, &xproperty); + XFree (xproperty.value); + } + + g_free (title_mem); + } + } + } +} + +/* This function handles a GstXWindow creation + * The width and height are the actual pixel size on the display */ +static GstXWindow * +gst_xvimagesink_xwindow_new (GstXvImageSink * xvimagesink, + gint width, gint height) +{ + GstXWindow *xwindow = NULL; + XGCValues values; + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + + xwindow = g_new0 (GstXWindow, 1); + + xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; + xvimagesink->render_rect.w = width; + xvimagesink->render_rect.h = height; + + xwindow->width = width; + xwindow->height = height; + xwindow->internal = TRUE; + + g_mutex_lock (xvimagesink->x_lock); + + xwindow->win = XCreateSimpleWindow (xvimagesink->xcontext->disp, + xvimagesink->xcontext->root, + 0, 0, width, height, 0, 0, xvimagesink->xcontext->black); + + /* We have to do that to prevent X from redrawing the background on + * ConfigureNotify. This takes away flickering of video when resizing. */ + XSetWindowBackgroundPixmap (xvimagesink->xcontext->disp, xwindow->win, None); + + /* set application name as a title */ + gst_xvimagesink_xwindow_set_title (xvimagesink, xwindow, NULL); + + if (xvimagesink->handle_events) { + Atom wm_delete; + + XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); + + /* Tell the window manager we'd like delete client messages instead of + * being killed */ + wm_delete = XInternAtom (xvimagesink->xcontext->disp, + "WM_DELETE_WINDOW", True); + if (wm_delete != None) { + (void) XSetWMProtocols (xvimagesink->xcontext->disp, xwindow->win, + &wm_delete, 1); + } + } + + xwindow->gc = XCreateGC (xvimagesink->xcontext->disp, + xwindow->win, 0, &values); + + XMapRaised (xvimagesink->xcontext->disp, xwindow->win); + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); + + gst_xvimagesink_xwindow_decorate (xvimagesink, xwindow); + + gst_x_overlay_got_window_handle (GST_X_OVERLAY (xvimagesink), xwindow->win); + + return xwindow; +} + +/* This function destroys a GstXWindow */ +static void +gst_xvimagesink_xwindow_destroy (GstXvImageSink * xvimagesink, + GstXWindow * xwindow) +{ + g_return_if_fail (xwindow != NULL); + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + g_mutex_lock (xvimagesink->x_lock); + + /* If we did not create that window we just free the GC and let it live */ + if (xwindow->internal) + XDestroyWindow (xvimagesink->xcontext->disp, xwindow->win); + else + XSelectInput (xvimagesink->xcontext->disp, xwindow->win, 0); + + XFreeGC (xvimagesink->xcontext->disp, xwindow->gc); + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); + + g_free (xwindow); +} + +static void +gst_xvimagesink_xwindow_update_geometry (GstXvImageSink * xvimagesink) +{ + XWindowAttributes attr; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + /* Update the window geometry */ + g_mutex_lock (xvimagesink->x_lock); + if (G_UNLIKELY (xvimagesink->xwindow == NULL)) { + g_mutex_unlock (xvimagesink->x_lock); + return; + } + + XGetWindowAttributes (xvimagesink->xcontext->disp, + xvimagesink->xwindow->win, &attr); + + xvimagesink->xwindow->width = attr.width; + xvimagesink->xwindow->height = attr.height; + + if (!xvimagesink->have_render_rect) { + xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; + xvimagesink->render_rect.w = attr.width; + xvimagesink->render_rect.h = attr.height; + } + + g_mutex_unlock (xvimagesink->x_lock); +} + +static void +gst_xvimagesink_xwindow_clear (GstXvImageSink * xvimagesink, + GstXWindow * xwindow) +{ + g_return_if_fail (xwindow != NULL); + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + g_mutex_lock (xvimagesink->x_lock); + + XvStopVideo (xvimagesink->xcontext->disp, xvimagesink->xcontext->xv_port_id, + xwindow->win); + + XSync (xvimagesink->xcontext->disp, FALSE); + + g_mutex_unlock (xvimagesink->x_lock); +} + +/* This function commits our internal colorbalance settings to our grabbed Xv + port. If the xcontext is not initialized yet it simply returns */ +static void +gst_xvimagesink_update_colorbalance (GstXvImageSink * xvimagesink) +{ + GList *channels = NULL; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + /* If we haven't initialized the X context we can't update anything */ + if (xvimagesink->xcontext == NULL) + return; + + /* Don't set the attributes if they haven't been changed, to avoid + * rounding errors changing the values */ + if (!xvimagesink->cb_changed) + return; + + /* For each channel of the colorbalance we calculate the correct value + doing range conversion and then set the Xv port attribute to match our + values. */ + channels = xvimagesink->xcontext->channels_list; + + while (channels) { + if (channels->data && GST_IS_COLOR_BALANCE_CHANNEL (channels->data)) { + GstColorBalanceChannel *channel = NULL; + Atom prop_atom; + gint value = 0; + gdouble convert_coef; + + channel = GST_COLOR_BALANCE_CHANNEL (channels->data); + g_object_ref (channel); + + /* Our range conversion coef */ + convert_coef = (channel->max_value - channel->min_value) / 2000.0; + + if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { + value = xvimagesink->hue; + } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { + value = xvimagesink->saturation; + } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { + value = xvimagesink->contrast; + } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { + value = xvimagesink->brightness; + } else { + g_warning ("got an unknown channel %s", channel->label); + g_object_unref (channel); + return; + } + + /* Committing to Xv port */ + g_mutex_lock (xvimagesink->x_lock); + prop_atom = + XInternAtom (xvimagesink->xcontext->disp, channel->label, True); + if (prop_atom != None) { + int xv_value; + xv_value = + floor (0.5 + (value + 1000) * convert_coef + channel->min_value); + XvSetPortAttribute (xvimagesink->xcontext->disp, + xvimagesink->xcontext->xv_port_id, prop_atom, xv_value); + } + g_mutex_unlock (xvimagesink->x_lock); + + g_object_unref (channel); + } + channels = g_list_next (channels); + } +} + +/* This function handles XEvents that might be in the queue. It generates + GstEvent that will be sent upstream in the pipeline to handle interactivity + and navigation. It will also listen for configure events on the window to + trigger caps renegotiation so on the fly software scaling can work. */ +static void +gst_xvimagesink_handle_xevents (GstXvImageSink * xvimagesink) +{ + XEvent e; + guint pointer_x = 0, pointer_y = 0; + gboolean pointer_moved = FALSE; + gboolean exposed = FALSE, configured = FALSE; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + /* Handle Interaction, produces navigation events */ + + /* We get all pointer motion events, only the last position is + interesting. */ + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + while (XCheckWindowEvent (xvimagesink->xcontext->disp, + xvimagesink->xwindow->win, PointerMotionMask, &e)) { + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); + + switch (e.type) { + case MotionNotify: + pointer_x = e.xmotion.x; + pointer_y = e.xmotion.y; + pointer_moved = TRUE; + break; + default: + break; + } + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + } + if (pointer_moved) { + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); + + GST_DEBUG ("xvimagesink pointer moved over window at %d,%d", + pointer_x, pointer_y); + gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink), + "mouse-move", 0, e.xbutton.x, e.xbutton.y); + + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + } + + /* We get all events on our window to throw them upstream */ + while (XCheckWindowEvent (xvimagesink->xcontext->disp, + xvimagesink->xwindow->win, + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask, + &e)) { + KeySym keysym; + + /* We lock only for the X function call */ + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); + + switch (e.type) { + case ButtonPress: + /* Mouse button pressed over our window. We send upstream + events for interactivity/navigation */ + GST_DEBUG ("xvimagesink button %d pressed over window at %d,%d", + e.xbutton.button, e.xbutton.x, e.xbutton.y); + gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink), + "mouse-button-press", e.xbutton.button, e.xbutton.x, e.xbutton.y); + break; + case ButtonRelease: + /* Mouse button released over our window. We send upstream + events for interactivity/navigation */ + GST_DEBUG ("xvimagesink button %d released over window at %d,%d", + e.xbutton.button, e.xbutton.x, e.xbutton.y); + gst_navigation_send_mouse_event (GST_NAVIGATION (xvimagesink), + "mouse-button-release", e.xbutton.button, e.xbutton.x, e.xbutton.y); + break; + case KeyPress: + case KeyRelease: + /* Key pressed/released over our window. We send upstream + events for interactivity/navigation */ + GST_DEBUG ("xvimagesink key %d pressed over window at %d,%d", + e.xkey.keycode, e.xkey.x, e.xkey.y); + g_mutex_lock (xvimagesink->x_lock); + keysym = XKeycodeToKeysym (xvimagesink->xcontext->disp, + e.xkey.keycode, 0); + g_mutex_unlock (xvimagesink->x_lock); + if (keysym != NoSymbol) { + char *key_str = NULL; + + g_mutex_lock (xvimagesink->x_lock); + key_str = XKeysymToString (keysym); + g_mutex_unlock (xvimagesink->x_lock); + gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), + e.type == KeyPress ? "key-press" : "key-release", key_str); + } else { + gst_navigation_send_key_event (GST_NAVIGATION (xvimagesink), + e.type == KeyPress ? "key-press" : "key-release", "unknown"); + } + break; + default: + GST_DEBUG ("xvimagesink unhandled X event (%d)", e.type); + } + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + } + + /* Handle Expose */ + while (XCheckWindowEvent (xvimagesink->xcontext->disp, + xvimagesink->xwindow->win, ExposureMask | StructureNotifyMask, &e)) { + switch (e.type) { + case Expose: + exposed = TRUE; + break; + case ConfigureNotify: + g_mutex_unlock (xvimagesink->x_lock); + gst_xvimagesink_xwindow_update_geometry (xvimagesink); + g_mutex_lock (xvimagesink->x_lock); + configured = TRUE; + break; + default: + break; + } + } + + if (xvimagesink->handle_expose && (exposed || configured)) { + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); + + gst_xvimagesink_expose (GST_X_OVERLAY (xvimagesink)); + + g_mutex_lock (xvimagesink->flow_lock); + g_mutex_lock (xvimagesink->x_lock); + } + + /* Handle Display events */ + while (XPending (xvimagesink->xcontext->disp)) { + XNextEvent (xvimagesink->xcontext->disp, &e); + + switch (e.type) { + case ClientMessage:{ + Atom wm_delete; + + wm_delete = XInternAtom (xvimagesink->xcontext->disp, + "WM_DELETE_WINDOW", True); + if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) { + /* Handle window deletion by posting an error on the bus */ + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, NOT_FOUND, + ("Output window was closed"), (NULL)); + + g_mutex_unlock (xvimagesink->x_lock); + gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + xvimagesink->xwindow = NULL; + g_mutex_lock (xvimagesink->x_lock); + } + break; + } + default: + break; + } + } + + g_mutex_unlock (xvimagesink->x_lock); + g_mutex_unlock (xvimagesink->flow_lock); +} + +static void +gst_lookup_xv_port_from_adaptor (GstXContext * xcontext, + XvAdaptorInfo * adaptors, int adaptor_no) +{ + gint j; + gint res; + + /* Do we support XvImageMask ? */ + if (!(adaptors[adaptor_no].type & XvImageMask)) { + GST_DEBUG ("XV Adaptor %s has no support for XvImageMask", + adaptors[adaptor_no].name); + return; + } + + /* We found such an adaptor, looking for an available port */ + for (j = 0; j < adaptors[adaptor_no].num_ports && !xcontext->xv_port_id; j++) { + /* We try to grab the port */ + res = XvGrabPort (xcontext->disp, adaptors[adaptor_no].base_id + j, 0); + if (Success == res) { + xcontext->xv_port_id = adaptors[adaptor_no].base_id + j; + GST_DEBUG ("XV Adaptor %s with %ld ports", adaptors[adaptor_no].name, + adaptors[adaptor_no].num_ports); + } else { + GST_DEBUG ("GrabPort %d for XV Adaptor %s failed: %d", j, + adaptors[adaptor_no].name, res); + } + } +} + +/* This function generates a caps with all supported format by the first + Xv grabable port we find. We store each one of the supported formats in a + format list and append the format to a newly created caps that we return + If this function does not return NULL because of an error, it also grabs + the port via XvGrabPort */ +static GstCaps * +gst_xvimagesink_get_xv_support (GstXvImageSink * xvimagesink, + GstXContext * xcontext) +{ + gint i; + XvAdaptorInfo *adaptors; + gint nb_formats; + XvImageFormatValues *formats = NULL; + guint nb_encodings; + XvEncodingInfo *encodings = NULL; + gulong max_w = G_MAXINT, max_h = G_MAXINT; + GstCaps *caps = NULL; + GstCaps *rgb_caps = NULL; + + g_return_val_if_fail (xcontext != NULL, NULL); + + /* First let's check that XVideo extension is available */ + if (!XQueryExtension (xcontext->disp, "XVideo", &i, &i, &i)) { + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, + ("Could not initialise Xv output"), + ("XVideo extension is not available")); + return NULL; + } + + /* Then we get adaptors list */ + if (Success != XvQueryAdaptors (xcontext->disp, xcontext->root, + &xcontext->nb_adaptors, &adaptors)) { + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, + ("Could not initialise Xv output"), + ("Failed getting XV adaptors list")); + return NULL; + } + + xcontext->xv_port_id = 0; + + GST_DEBUG ("Found %u XV adaptor(s)", xcontext->nb_adaptors); + + xcontext->adaptors = + (gchar **) g_malloc0 (xcontext->nb_adaptors * sizeof (gchar *)); + + /* Now fill up our adaptor name array */ + for (i = 0; i < xcontext->nb_adaptors; i++) { + xcontext->adaptors[i] = g_strdup (adaptors[i].name); + } + + if (xvimagesink->adaptor_no >= 0 && + xvimagesink->adaptor_no < xcontext->nb_adaptors) { + /* Find xv port from user defined adaptor */ + gst_lookup_xv_port_from_adaptor (xcontext, adaptors, + xvimagesink->adaptor_no); + } + + if (!xcontext->xv_port_id) { + /* Now search for an adaptor that supports XvImageMask */ + for (i = 0; i < xcontext->nb_adaptors && !xcontext->xv_port_id; i++) { + gst_lookup_xv_port_from_adaptor (xcontext, adaptors, i); + xvimagesink->adaptor_no = i; + } + } + + XvFreeAdaptorInfo (adaptors); + + if (!xcontext->xv_port_id) { + xvimagesink->adaptor_no = -1; + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, BUSY, + ("Could not initialise Xv output"), ("No port available")); + return NULL; + } + + /* Set XV_AUTOPAINT_COLORKEY and XV_DOUBLE_BUFFER and XV_COLORKEY */ + { + int count, todo = 3; + XvAttribute *const attr = XvQueryPortAttributes (xcontext->disp, + xcontext->xv_port_id, &count); + static const char autopaint[] = "XV_AUTOPAINT_COLORKEY"; + static const char dbl_buffer[] = "XV_DOUBLE_BUFFER"; + static const char colorkey[] = "XV_COLORKEY"; + + GST_DEBUG_OBJECT (xvimagesink, "Checking %d Xv port attributes", count); + + xvimagesink->have_autopaint_colorkey = FALSE; + xvimagesink->have_double_buffer = FALSE; + xvimagesink->have_colorkey = FALSE; + + for (i = 0; ((i < count) && todo); i++) + if (!strcmp (attr[i].name, autopaint)) { + const Atom atom = XInternAtom (xcontext->disp, autopaint, False); + + /* turn on autopaint colorkey */ + XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, + (xvimagesink->autopaint_colorkey ? 1 : 0)); + todo--; + xvimagesink->have_autopaint_colorkey = TRUE; + } else if (!strcmp (attr[i].name, dbl_buffer)) { + const Atom atom = XInternAtom (xcontext->disp, dbl_buffer, False); + + XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, + (xvimagesink->double_buffer ? 1 : 0)); + todo--; + xvimagesink->have_double_buffer = TRUE; + } else if (!strcmp (attr[i].name, colorkey)) { + /* Set the colorkey, default is something that is dark but hopefully + * won't randomly appear on the screen elsewhere (ie not black or greys) + * can be overridden by setting "colorkey" property + */ + const Atom atom = XInternAtom (xcontext->disp, colorkey, False); + guint32 ckey = 0; + gboolean set_attr = TRUE; + guint cr, cg, cb; + + /* set a colorkey in the right format RGB565/RGB888 + * We only handle these 2 cases, because they're the only types of + * devices we've encountered. If we don't recognise it, leave it alone + */ + cr = (xvimagesink->colorkey >> 16); + cg = (xvimagesink->colorkey >> 8) & 0xFF; + cb = (xvimagesink->colorkey) & 0xFF; + switch (xcontext->depth) { + case 16: /* RGB 565 */ + cr >>= 3; + cg >>= 2; + cb >>= 3; + ckey = (cr << 11) | (cg << 5) | cb; + break; + case 24: + case 32: /* RGB 888 / ARGB 8888 */ + ckey = (cr << 16) | (cg << 8) | cb; + break; + default: + GST_DEBUG_OBJECT (xvimagesink, + "Unknown bit depth %d for Xv Colorkey - not adjusting", + xcontext->depth); + set_attr = FALSE; + break; + } + + if (set_attr) { + ckey = CLAMP (ckey, (guint32) attr[i].min_value, + (guint32) attr[i].max_value); + GST_LOG_OBJECT (xvimagesink, + "Setting color key for display depth %d to 0x%x", + xcontext->depth, ckey); + + XvSetPortAttribute (xcontext->disp, xcontext->xv_port_id, atom, + (gint) ckey); + } + todo--; + xvimagesink->have_colorkey = TRUE; + } + + XFree (attr); + } + + /* Get the list of encodings supported by the adapter and look for the + * XV_IMAGE encoding so we can determine the maximum width and height + * supported */ + XvQueryEncodings (xcontext->disp, xcontext->xv_port_id, &nb_encodings, + &encodings); + + for (i = 0; i < nb_encodings; i++) { + GST_LOG_OBJECT (xvimagesink, + "Encoding %d, name %s, max wxh %lux%lu rate %d/%d", + i, encodings[i].name, encodings[i].width, encodings[i].height, + encodings[i].rate.numerator, encodings[i].rate.denominator); + if (strcmp (encodings[i].name, "XV_IMAGE") == 0) { + max_w = encodings[i].width; + max_h = encodings[i].height; + } + } + + XvFreeEncodingInfo (encodings); + + /* We get all image formats supported by our port */ + formats = XvListImageFormats (xcontext->disp, + xcontext->xv_port_id, &nb_formats); + caps = gst_caps_new_empty (); + for (i = 0; i < nb_formats; i++) { + GstCaps *format_caps = NULL; + gboolean is_rgb_format = FALSE; + + /* We set the image format of the xcontext to an existing one. This + is just some valid image format for making our xshm calls check before + caps negotiation really happens. */ + xcontext->im_format = formats[i].id; + + switch (formats[i].type) { + case XvRGB: + { + XvImageFormatValues *fmt = &(formats[i]); + gint endianness = G_BIG_ENDIAN; + + if (fmt->byte_order == LSBFirst) { + /* our caps system handles 24/32bpp RGB as big-endian. */ + if (fmt->bits_per_pixel == 24 || fmt->bits_per_pixel == 32) { + fmt->red_mask = GUINT32_TO_BE (fmt->red_mask); + fmt->green_mask = GUINT32_TO_BE (fmt->green_mask); + fmt->blue_mask = GUINT32_TO_BE (fmt->blue_mask); + + if (fmt->bits_per_pixel == 24) { + fmt->red_mask >>= 8; + fmt->green_mask >>= 8; + fmt->blue_mask >>= 8; + } + } else + endianness = G_LITTLE_ENDIAN; + } + + format_caps = gst_caps_new_simple ("video/x-raw-rgb", + "endianness", G_TYPE_INT, endianness, + "depth", G_TYPE_INT, fmt->depth, + "bpp", G_TYPE_INT, fmt->bits_per_pixel, + "red_mask", G_TYPE_INT, fmt->red_mask, + "green_mask", G_TYPE_INT, fmt->green_mask, + "blue_mask", G_TYPE_INT, fmt->blue_mask, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + + is_rgb_format = TRUE; + break; + } + case XvYUV: + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[i].id, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + break; + default: + g_assert_not_reached (); + break; + } + + if (format_caps) { + GstXvImageFormat *format = NULL; + + format = g_new0 (GstXvImageFormat, 1); + if (format) { + format->format = formats[i].id; + format->caps = gst_caps_copy (format_caps); + xcontext->formats_list = g_list_append (xcontext->formats_list, format); + } + + if (is_rgb_format) { + if (rgb_caps == NULL) + rgb_caps = format_caps; + else + gst_caps_append (rgb_caps, format_caps); + } else + gst_caps_append (caps, format_caps); + } + } + + /* Collected all caps into either the caps or rgb_caps structures. + * Append rgb_caps on the end of YUV, so that YUV is always preferred */ + if (rgb_caps) + gst_caps_append (caps, rgb_caps); + + if (formats) + XFree (formats); + + GST_DEBUG ("Generated the following caps: %" GST_PTR_FORMAT, caps); + + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0); + GST_ELEMENT_ERROR (xvimagesink, STREAM, WRONG_TYPE, (NULL), + ("No supported format found")); + return NULL; + } + + return caps; +} + +static gpointer +gst_xvimagesink_event_thread (GstXvImageSink * xvimagesink) +{ + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + + GST_OBJECT_LOCK (xvimagesink); + while (xvimagesink->running) { + GST_OBJECT_UNLOCK (xvimagesink); + + if (xvimagesink->xwindow) { + gst_xvimagesink_handle_xevents (xvimagesink); + } + /* FIXME: do we want to align this with the framerate or anything else? */ + g_usleep (G_USEC_PER_SEC / 20); + + GST_OBJECT_LOCK (xvimagesink); + } + GST_OBJECT_UNLOCK (xvimagesink); + + return NULL; +} + +static void +gst_xvimagesink_manage_event_thread (GstXvImageSink * xvimagesink) +{ + GThread *thread = NULL; + + /* don't start the thread too early */ + if (xvimagesink->xcontext == NULL) { + return; + } + + GST_OBJECT_LOCK (xvimagesink); + if (xvimagesink->handle_expose || xvimagesink->handle_events) { + if (!xvimagesink->event_thread) { + /* Setup our event listening thread */ + GST_DEBUG_OBJECT (xvimagesink, "run xevent thread, expose %d, events %d", + xvimagesink->handle_expose, xvimagesink->handle_events); + xvimagesink->running = TRUE; + xvimagesink->event_thread = g_thread_create ( + (GThreadFunc) gst_xvimagesink_event_thread, xvimagesink, TRUE, NULL); + } + } else { + if (xvimagesink->event_thread) { + GST_DEBUG_OBJECT (xvimagesink, "stop xevent thread, expose %d, events %d", + xvimagesink->handle_expose, xvimagesink->handle_events); + xvimagesink->running = FALSE; + /* grab thread and mark it as NULL */ + thread = xvimagesink->event_thread; + xvimagesink->event_thread = NULL; + } + } + GST_OBJECT_UNLOCK (xvimagesink); + + /* Wait for our event thread to finish */ + if (thread) + g_thread_join (thread); + +} + + +/* This function calculates the pixel aspect ratio based on the properties + * in the xcontext structure and stores it there. */ +static void +gst_xvimagesink_calculate_pixel_aspect_ratio (GstXContext * xcontext) +{ + static const gint par[][2] = { + {1, 1}, /* regular screen */ + {16, 15}, /* PAL TV */ + {11, 10}, /* 525 line Rec.601 video */ + {54, 59}, /* 625 line Rec.601 video */ + {64, 45}, /* 1280x1024 on 16:9 display */ + {5, 3}, /* 1280x1024 on 4:3 display */ + {4, 3} /* 800x600 on 16:9 display */ + }; + gint i; + gint index; + gdouble ratio; + gdouble delta; + +#define DELTA(idx) (ABS (ratio - ((gdouble) par[idx][0] / par[idx][1]))) + + /* first calculate the "real" ratio based on the X values; + * which is the "physical" w/h divided by the w/h in pixels of the display */ + ratio = (gdouble) (xcontext->widthmm * xcontext->height) + / (xcontext->heightmm * xcontext->width); + + /* DirectFB's X in 720x576 reports the physical dimensions wrong, so + * override here */ + if (xcontext->width == 720 && xcontext->height == 576) { + ratio = 4.0 * 576 / (3.0 * 720); + } + GST_DEBUG ("calculated pixel aspect ratio: %f", ratio); + /* now find the one from par[][2] with the lowest delta to the real one */ + delta = DELTA (0); + index = 0; + + for (i = 1; i < sizeof (par) / (sizeof (gint) * 2); ++i) { + gdouble this_delta = DELTA (i); + + if (this_delta < delta) { + index = i; + delta = this_delta; + } + } + + GST_DEBUG ("Decided on index %d (%d/%d)", index, + par[index][0], par[index][1]); + + g_free (xcontext->par); + xcontext->par = g_new0 (GValue, 1); + g_value_init (xcontext->par, GST_TYPE_FRACTION); + gst_value_set_fraction (xcontext->par, par[index][0], par[index][1]); + GST_DEBUG ("set xcontext PAR to %d/%d", + gst_value_get_fraction_numerator (xcontext->par), + gst_value_get_fraction_denominator (xcontext->par)); +} + +/* This function gets the X Display and global info about it. Everything is + stored in our object and will be cleaned when the object is disposed. Note + here that caps for supported format are generated without any window or + image creation */ +static GstXContext * +gst_xvimagesink_xcontext_get (GstXvImageSink * xvimagesink) +{ + GstXContext *xcontext = NULL; + XPixmapFormatValues *px_formats = NULL; + gint nb_formats = 0, i, j, N_attr; + XvAttribute *xv_attr; + Atom prop_atom; + const char *channels[4] = { "XV_HUE", "XV_SATURATION", + "XV_BRIGHTNESS", "XV_CONTRAST" + }; + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + + xcontext = g_new0 (GstXContext, 1); + xcontext->im_format = 0; + + g_mutex_lock (xvimagesink->x_lock); + + xcontext->disp = XOpenDisplay (xvimagesink->display_name); + + if (!xcontext->disp) { + g_mutex_unlock (xvimagesink->x_lock); + g_free (xcontext); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Could not initialise Xv output"), ("Could not open display")); + return NULL; + } + + xcontext->screen = DefaultScreenOfDisplay (xcontext->disp); + xcontext->screen_num = DefaultScreen (xcontext->disp); + xcontext->visual = DefaultVisual (xcontext->disp, xcontext->screen_num); + xcontext->root = DefaultRootWindow (xcontext->disp); + xcontext->white = XWhitePixel (xcontext->disp, xcontext->screen_num); + xcontext->black = XBlackPixel (xcontext->disp, xcontext->screen_num); + xcontext->depth = DefaultDepthOfScreen (xcontext->screen); + + xcontext->width = DisplayWidth (xcontext->disp, xcontext->screen_num); + xcontext->height = DisplayHeight (xcontext->disp, xcontext->screen_num); + xcontext->widthmm = DisplayWidthMM (xcontext->disp, xcontext->screen_num); + xcontext->heightmm = DisplayHeightMM (xcontext->disp, xcontext->screen_num); + + GST_DEBUG_OBJECT (xvimagesink, "X reports %dx%d pixels and %d mm x %d mm", + xcontext->width, xcontext->height, xcontext->widthmm, xcontext->heightmm); + + gst_xvimagesink_calculate_pixel_aspect_ratio (xcontext); + /* We get supported pixmap formats at supported depth */ + px_formats = XListPixmapFormats (xcontext->disp, &nb_formats); + + if (!px_formats) { + XCloseDisplay (xcontext->disp); + g_mutex_unlock (xvimagesink->x_lock); + g_free (xcontext->par); + g_free (xcontext); + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, SETTINGS, + ("Could not initialise Xv output"), ("Could not get pixel formats")); + return NULL; + } + + /* We get bpp value corresponding to our running depth */ + for (i = 0; i < nb_formats; i++) { + if (px_formats[i].depth == xcontext->depth) + xcontext->bpp = px_formats[i].bits_per_pixel; + } + + XFree (px_formats); + + xcontext->endianness = + (ImageByteOrder (xcontext->disp) == + LSBFirst) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN; + + /* our caps system handles 24/32bpp RGB as big-endian. */ + if ((xcontext->bpp == 24 || xcontext->bpp == 32) && + xcontext->endianness == G_LITTLE_ENDIAN) { + xcontext->endianness = G_BIG_ENDIAN; + xcontext->visual->red_mask = GUINT32_TO_BE (xcontext->visual->red_mask); + xcontext->visual->green_mask = GUINT32_TO_BE (xcontext->visual->green_mask); + xcontext->visual->blue_mask = GUINT32_TO_BE (xcontext->visual->blue_mask); + if (xcontext->bpp == 24) { + xcontext->visual->red_mask >>= 8; + xcontext->visual->green_mask >>= 8; + xcontext->visual->blue_mask >>= 8; + } + } + + xcontext->caps = gst_xvimagesink_get_xv_support (xvimagesink, xcontext); + + if (!xcontext->caps) { + XCloseDisplay (xcontext->disp); + g_mutex_unlock (xvimagesink->x_lock); + g_free (xcontext->par); + g_free (xcontext); + /* GST_ELEMENT_ERROR is thrown by gst_xvimagesink_get_xv_support */ + return NULL; + } +#ifdef HAVE_XSHM + /* Search for XShm extension support */ + if (XShmQueryExtension (xcontext->disp) && + gst_xvimagesink_check_xshm_calls (xcontext)) { + xcontext->use_xshm = TRUE; + GST_DEBUG ("xvimagesink is using XShm extension"); + } else +#endif /* HAVE_XSHM */ + { + xcontext->use_xshm = FALSE; + GST_DEBUG ("xvimagesink is not using XShm extension"); + } + + xv_attr = XvQueryPortAttributes (xcontext->disp, + xcontext->xv_port_id, &N_attr); + + + /* Generate the channels list */ + for (i = 0; i < (sizeof (channels) / sizeof (char *)); i++) { + XvAttribute *matching_attr = NULL; + + /* Retrieve the property atom if it exists. If it doesn't exist, + * the attribute itself must not either, so we can skip */ + prop_atom = XInternAtom (xcontext->disp, channels[i], True); + if (prop_atom == None) + continue; + + if (xv_attr != NULL) { + for (j = 0; j < N_attr && matching_attr == NULL; ++j) + if (!g_ascii_strcasecmp (channels[i], xv_attr[j].name)) + matching_attr = xv_attr + j; + } + + if (matching_attr) { + GstColorBalanceChannel *channel; + + channel = g_object_new (GST_TYPE_COLOR_BALANCE_CHANNEL, NULL); + channel->label = g_strdup (channels[i]); + channel->min_value = matching_attr ? matching_attr->min_value : -1000; + channel->max_value = matching_attr ? matching_attr->max_value : 1000; + + xcontext->channels_list = g_list_append (xcontext->channels_list, + channel); + + /* If the colorbalance settings have not been touched we get Xv values + as defaults and update our internal variables */ + if (!xvimagesink->cb_changed) { + gint val; + + XvGetPortAttribute (xcontext->disp, xcontext->xv_port_id, + prop_atom, &val); + /* Normalize val to [-1000, 1000] */ + val = floor (0.5 + -1000 + 2000 * (val - channel->min_value) / + (double) (channel->max_value - channel->min_value)); + + if (!g_ascii_strcasecmp (channels[i], "XV_HUE")) + xvimagesink->hue = val; + else if (!g_ascii_strcasecmp (channels[i], "XV_SATURATION")) + xvimagesink->saturation = val; + else if (!g_ascii_strcasecmp (channels[i], "XV_BRIGHTNESS")) + xvimagesink->brightness = val; + else if (!g_ascii_strcasecmp (channels[i], "XV_CONTRAST")) + xvimagesink->contrast = val; + } + } + } + + if (xv_attr) + XFree (xv_attr); + + g_mutex_unlock (xvimagesink->x_lock); + + return xcontext; +} + +/* This function cleans the X context. Closing the Display, releasing the XV + port and unrefing the caps for supported formats. */ +static void +gst_xvimagesink_xcontext_clear (GstXvImageSink * xvimagesink) +{ + GList *formats_list, *channels_list; + GstXContext *xcontext; + gint i = 0; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + GST_OBJECT_LOCK (xvimagesink); + if (xvimagesink->xcontext == NULL) { + GST_OBJECT_UNLOCK (xvimagesink); + return; + } + + /* Take the XContext from the sink and clean it up */ + xcontext = xvimagesink->xcontext; + xvimagesink->xcontext = NULL; + + GST_OBJECT_UNLOCK (xvimagesink); + + + formats_list = xcontext->formats_list; + + while (formats_list) { + GstXvImageFormat *format = formats_list->data; + + gst_caps_unref (format->caps); + g_free (format); + formats_list = g_list_next (formats_list); + } + + if (xcontext->formats_list) + g_list_free (xcontext->formats_list); + + channels_list = xcontext->channels_list; + + while (channels_list) { + GstColorBalanceChannel *channel = channels_list->data; + + g_object_unref (channel); + channels_list = g_list_next (channels_list); + } + + if (xcontext->channels_list) + g_list_free (xcontext->channels_list); + + gst_caps_unref (xcontext->caps); + if (xcontext->last_caps) + gst_caps_replace (&xcontext->last_caps, NULL); + + for (i = 0; i < xcontext->nb_adaptors; i++) { + g_free (xcontext->adaptors[i]); + } + + g_free (xcontext->adaptors); + + g_free (xcontext->par); + + g_mutex_lock (xvimagesink->x_lock); + + GST_DEBUG_OBJECT (xvimagesink, "Closing display and freeing X Context"); + + XvUngrabPort (xcontext->disp, xcontext->xv_port_id, 0); + + XCloseDisplay (xcontext->disp); + + g_mutex_unlock (xvimagesink->x_lock); + + g_free (xcontext); +} + +static void +gst_xvimagesink_imagepool_clear (GstXvImageSink * xvimagesink) +{ + g_mutex_lock (xvimagesink->pool_lock); + + while (xvimagesink->image_pool) { + GstXvImageBuffer *xvimage = xvimagesink->image_pool->data; + + xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool, + xvimagesink->image_pool); + gst_xvimage_buffer_free (xvimage); + } + + g_mutex_unlock (xvimagesink->pool_lock); +} + +/* Element stuff */ + +/* This function tries to get a format matching with a given caps in the + supported list of formats we generated in gst_xvimagesink_get_xv_support */ +static gint +gst_xvimagesink_get_format_from_caps (GstXvImageSink * xvimagesink, + GstCaps * caps) +{ + GList *list = NULL; + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0); + + list = xvimagesink->xcontext->formats_list; + + while (list) { + GstXvImageFormat *format = list->data; + + if (format) { + if (gst_caps_can_intersect (caps, format->caps)) { + return format->format; + } + } + list = g_list_next (list); + } + + return -1; +} + +static GstCaps * +gst_xvimagesink_getcaps (GstBaseSink * bsink) +{ + GstXvImageSink *xvimagesink; + + xvimagesink = GST_XVIMAGESINK (bsink); + + if (xvimagesink->xcontext) + return gst_caps_ref (xvimagesink->xcontext->caps); + + return + gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD + (xvimagesink))); +} + +static gboolean +gst_xvimagesink_setcaps (GstBaseSink * bsink, GstCaps * caps) +{ + GstXvImageSink *xvimagesink; + GstStructure *structure; + guint32 im_format = 0; + gboolean ret; + gint video_width, video_height; + gint disp_x, disp_y; + gint disp_width, disp_height; + gint video_par_n, video_par_d; /* video's PAR */ + gint display_par_n, display_par_d; /* display's PAR */ + const GValue *caps_par; + const GValue *caps_disp_reg; + const GValue *fps; + guint num, den; + + xvimagesink = GST_XVIMAGESINK (bsink); + + GST_DEBUG_OBJECT (xvimagesink, + "In setcaps. Possible caps %" GST_PTR_FORMAT ", setting caps %" + GST_PTR_FORMAT, xvimagesink->xcontext->caps, caps); + + if (!gst_caps_can_intersect (xvimagesink->xcontext->caps, caps)) + goto incompatible_caps; + + structure = gst_caps_get_structure (caps, 0); + ret = gst_structure_get_int (structure, "width", &video_width); + ret &= gst_structure_get_int (structure, "height", &video_height); + fps = gst_structure_get_value (structure, "framerate"); + ret &= (fps != NULL); + + if (!ret) + goto incomplete_caps; + + xvimagesink->fps_n = gst_value_get_fraction_numerator (fps); + xvimagesink->fps_d = gst_value_get_fraction_denominator (fps); + + xvimagesink->video_width = video_width; + xvimagesink->video_height = video_height; + + im_format = gst_xvimagesink_get_format_from_caps (xvimagesink, caps); + if (im_format == -1) + goto invalid_format; + + /* get aspect ratio from caps if it's present, and + * convert video width and height to a display width and height + * using wd / hd = wv / hv * PARv / PARd */ + + /* get video's PAR */ + caps_par = gst_structure_get_value (structure, "pixel-aspect-ratio"); + if (caps_par) { + video_par_n = gst_value_get_fraction_numerator (caps_par); + video_par_d = gst_value_get_fraction_denominator (caps_par); + } else { + video_par_n = 1; + video_par_d = 1; + } + /* get display's PAR */ + if (xvimagesink->par) { + display_par_n = gst_value_get_fraction_numerator (xvimagesink->par); + display_par_d = gst_value_get_fraction_denominator (xvimagesink->par); + } else { + display_par_n = 1; + display_par_d = 1; + } + + /* get the display region */ + caps_disp_reg = gst_structure_get_value (structure, "display-region"); + if (caps_disp_reg) { + disp_x = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 0)); + disp_y = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 1)); + disp_width = g_value_get_int (gst_value_array_get_value (caps_disp_reg, 2)); + disp_height = + g_value_get_int (gst_value_array_get_value (caps_disp_reg, 3)); + } else { + disp_x = disp_y = 0; + disp_width = video_width; + disp_height = video_height; + } + + if (!gst_video_calculate_display_ratio (&num, &den, video_width, + video_height, video_par_n, video_par_d, display_par_n, display_par_d)) + goto no_disp_ratio; + + xvimagesink->disp_x = disp_x; + xvimagesink->disp_y = disp_y; + xvimagesink->disp_width = disp_width; + xvimagesink->disp_height = disp_height; + + GST_DEBUG_OBJECT (xvimagesink, + "video width/height: %dx%d, calculated display ratio: %d/%d", + video_width, video_height, num, den); + + /* now find a width x height that respects this display ratio. + * prefer those that have one of w/h the same as the incoming video + * using wd / hd = num / den */ + + /* start with same height, because of interlaced video */ + /* check hd / den is an integer scale factor, and scale wd with the PAR */ + if (video_height % den == 0) { + GST_DEBUG_OBJECT (xvimagesink, "keeping video height"); + GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint) + gst_util_uint64_scale_int (video_height, num, den); + GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height; + } else if (video_width % num == 0) { + GST_DEBUG_OBJECT (xvimagesink, "keeping video width"); + GST_VIDEO_SINK_WIDTH (xvimagesink) = video_width; + GST_VIDEO_SINK_HEIGHT (xvimagesink) = (guint) + gst_util_uint64_scale_int (video_width, den, num); + } else { + GST_DEBUG_OBJECT (xvimagesink, "approximating while keeping video height"); + GST_VIDEO_SINK_WIDTH (xvimagesink) = (guint) + gst_util_uint64_scale_int (video_height, num, den); + GST_VIDEO_SINK_HEIGHT (xvimagesink) = video_height; + } + GST_DEBUG_OBJECT (xvimagesink, "scaling to %dx%d", + GST_VIDEO_SINK_WIDTH (xvimagesink), GST_VIDEO_SINK_HEIGHT (xvimagesink)); + + /* Notify application to set xwindow id now */ + g_mutex_lock (xvimagesink->flow_lock); + if (!xvimagesink->xwindow) { + g_mutex_unlock (xvimagesink->flow_lock); + gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (xvimagesink)); + } else { + g_mutex_unlock (xvimagesink->flow_lock); + } + + /* Creating our window and our image with the display size in pixels */ + if (GST_VIDEO_SINK_WIDTH (xvimagesink) <= 0 || + GST_VIDEO_SINK_HEIGHT (xvimagesink) <= 0) + goto no_display_size; + + g_mutex_lock (xvimagesink->flow_lock); + if (!xvimagesink->xwindow) { + xvimagesink->xwindow = gst_xvimagesink_xwindow_new (xvimagesink, + GST_VIDEO_SINK_WIDTH (xvimagesink), + GST_VIDEO_SINK_HEIGHT (xvimagesink)); + } + + /* After a resize, we want to redraw the borders in case the new frame size + * doesn't cover the same area */ + xvimagesink->redraw_border = TRUE; + + /* We renew our xvimage only if size or format changed; + * the xvimage is the same size as the video pixel size */ + if ((xvimagesink->xvimage) && + ((im_format != xvimagesink->xvimage->im_format) || + (video_width != xvimagesink->xvimage->width) || + (video_height != xvimagesink->xvimage->height))) { + GST_DEBUG_OBJECT (xvimagesink, + "old format %" GST_FOURCC_FORMAT ", new format %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (xvimagesink->xvimage->im_format), + GST_FOURCC_ARGS (im_format)); + GST_DEBUG_OBJECT (xvimagesink, "renewing xvimage"); + gst_buffer_unref (GST_BUFFER (xvimagesink->xvimage)); + xvimagesink->xvimage = NULL; + } + + g_mutex_unlock (xvimagesink->flow_lock); + + return TRUE; + + /* ERRORS */ +incompatible_caps: + { + GST_ERROR_OBJECT (xvimagesink, "caps incompatible"); + return FALSE; + } +incomplete_caps: + { + GST_DEBUG_OBJECT (xvimagesink, "Failed to retrieve either width, " + "height or framerate from intersected caps"); + return FALSE; + } +invalid_format: + { + GST_DEBUG_OBJECT (xvimagesink, + "Could not locate image format from caps %" GST_PTR_FORMAT, caps); + return FALSE; + } +no_disp_ratio: + { + GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL), + ("Error calculating the output display ratio of the video.")); + return FALSE; + } +no_display_size: + { + GST_ELEMENT_ERROR (xvimagesink, CORE, NEGOTIATION, (NULL), + ("Error calculating the output display ratio of the video.")); + return FALSE; + } +} + +static GstStateChangeReturn +gst_xvimagesink_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstXvImageSink *xvimagesink; + GstXContext *xcontext = NULL; + + xvimagesink = GST_XVIMAGESINK (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + /* Initializing the XContext */ + if (xvimagesink->xcontext == NULL) { + xcontext = gst_xvimagesink_xcontext_get (xvimagesink); + if (xcontext == NULL) + return GST_STATE_CHANGE_FAILURE; + GST_OBJECT_LOCK (xvimagesink); + if (xcontext) + xvimagesink->xcontext = xcontext; + GST_OBJECT_UNLOCK (xvimagesink); + } + + /* update object's par with calculated one if not set yet */ + if (!xvimagesink->par) { + xvimagesink->par = g_new0 (GValue, 1); + gst_value_init_and_copy (xvimagesink->par, xvimagesink->xcontext->par); + GST_DEBUG_OBJECT (xvimagesink, "set calculated PAR on object's PAR"); + } + /* call XSynchronize with the current value of synchronous */ + GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s", + xvimagesink->synchronous ? "TRUE" : "FALSE"); + XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous); + gst_xvimagesink_update_colorbalance (xvimagesink); + gst_xvimagesink_manage_event_thread (xvimagesink); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + g_mutex_lock (xvimagesink->pool_lock); + xvimagesink->pool_invalid = FALSE; + g_mutex_unlock (xvimagesink->pool_lock); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_mutex_lock (xvimagesink->pool_lock); + xvimagesink->pool_invalid = TRUE; + g_mutex_unlock (xvimagesink->pool_lock); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + xvimagesink->fps_n = 0; + xvimagesink->fps_d = 1; + GST_VIDEO_SINK_WIDTH (xvimagesink) = 0; + GST_VIDEO_SINK_HEIGHT (xvimagesink) = 0; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_xvimagesink_reset (xvimagesink); + break; + default: + break; + } + + return ret; +} + +static void +gst_xvimagesink_get_times (GstBaseSink * bsink, GstBuffer * buf, + GstClockTime * start, GstClockTime * end) +{ + GstXvImageSink *xvimagesink; + + xvimagesink = GST_XVIMAGESINK (bsink); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + *start = GST_BUFFER_TIMESTAMP (buf); + if (GST_BUFFER_DURATION_IS_VALID (buf)) { + *end = *start + GST_BUFFER_DURATION (buf); + } else { + if (xvimagesink->fps_n > 0) { + *end = *start + + gst_util_uint64_scale_int (GST_SECOND, xvimagesink->fps_d, + xvimagesink->fps_n); + } + } + } +} + +static GstFlowReturn +gst_xvimagesink_show_frame (GstVideoSink * vsink, GstBuffer * buf) +{ + GstXvImageSink *xvimagesink; + + xvimagesink = GST_XVIMAGESINK (vsink); + + /* If this buffer has been allocated using our buffer management we simply + put the ximage which is in the PRIVATE pointer */ + if (GST_IS_XVIMAGE_BUFFER (buf)) { + GST_LOG_OBJECT (xvimagesink, "fast put of bufferpool buffer %p", buf); + if (!gst_xvimagesink_xvimage_put (xvimagesink, + GST_XVIMAGE_BUFFER_CAST (buf))) + goto no_window; + } else { + GST_CAT_LOG_OBJECT (GST_CAT_PERFORMANCE, xvimagesink, + "slow copy into bufferpool buffer %p", buf); + /* Else we have to copy the data into our private image, */ + /* if we have one... */ + if (!xvimagesink->xvimage) { + GST_DEBUG_OBJECT (xvimagesink, "creating our xvimage"); + + xvimagesink->xvimage = gst_xvimagesink_xvimage_new (xvimagesink, + GST_BUFFER_CAPS (buf)); + + if (!xvimagesink->xvimage) + /* The create method should have posted an informative error */ + goto no_image; + + if (xvimagesink->xvimage->size < GST_BUFFER_SIZE (buf)) { + GST_ELEMENT_ERROR (xvimagesink, RESOURCE, WRITE, + ("Failed to create output image buffer of %dx%d pixels", + xvimagesink->xvimage->width, xvimagesink->xvimage->height), + ("XServer allocated buffer size did not match input buffer")); + + gst_xvimage_buffer_destroy (xvimagesink->xvimage); + xvimagesink->xvimage = NULL; + goto no_image; + } + } + + memcpy (xvimagesink->xvimage->xvimage->data, + GST_BUFFER_DATA (buf), + MIN (GST_BUFFER_SIZE (buf), xvimagesink->xvimage->size)); + + if (!gst_xvimagesink_xvimage_put (xvimagesink, xvimagesink->xvimage)) + goto no_window; + } + + return GST_FLOW_OK; + + /* ERRORS */ +no_image: + { + /* No image available. That's very bad ! */ + GST_WARNING_OBJECT (xvimagesink, "could not create image"); + return GST_FLOW_ERROR; + } +no_window: + { + /* No Window available to put our image into */ + GST_WARNING_OBJECT (xvimagesink, "could not output image - no window"); + return GST_FLOW_ERROR; + } +} + +static gboolean +gst_xvimagesink_event (GstBaseSink * sink, GstEvent * event) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (sink); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG:{ + GstTagList *l; + gchar *title = NULL; + + gst_event_parse_tag (event, &l); + gst_tag_list_get_string (l, GST_TAG_TITLE, &title); + + if (title) { + GST_DEBUG_OBJECT (xvimagesink, "got tags, title='%s'", title); + gst_xvimagesink_xwindow_set_title (xvimagesink, xvimagesink->xwindow, + title); + + g_free (title); + } + break; + } + default: + break; + } + if (GST_BASE_SINK_CLASS (parent_class)->event) + return GST_BASE_SINK_CLASS (parent_class)->event (sink, event); + else + return TRUE; +} + +/* Buffer management */ + +static GstCaps * +gst_xvimage_sink_different_size_suggestion (GstXvImageSink * xvimagesink, + GstCaps * caps) +{ + GstCaps *intersection; + GstCaps *new_caps; + GstStructure *s; + gint width, height; + gint par_n = 1, par_d = 1; + gint dar_n, dar_d; + gint w, h; + + new_caps = gst_caps_copy (caps); + + s = gst_caps_get_structure (new_caps, 0); + + gst_structure_get_int (s, "width", &width); + gst_structure_get_int (s, "height", &height); + gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, &par_d); + + gst_structure_remove_field (s, "width"); + gst_structure_remove_field (s, "height"); + gst_structure_remove_field (s, "pixel-aspect-ratio"); + + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); + gst_caps_unref (new_caps); + + if (gst_caps_is_empty (intersection)) + return intersection; + + s = gst_caps_get_structure (intersection, 0); + + gst_util_fraction_multiply (width, height, par_n, par_d, &dar_n, &dar_d); + + /* xvimagesink supports all PARs */ + + gst_structure_fixate_field_nearest_int (s, "width", width); + gst_structure_fixate_field_nearest_int (s, "height", height); + gst_structure_get_int (s, "width", &w); + gst_structure_get_int (s, "height", &h); + + gst_util_fraction_multiply (h, w, dar_n, dar_d, &par_n, &par_d); + gst_structure_set (s, "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, + NULL); + + return intersection; +} + +static GstFlowReturn +gst_xvimagesink_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buf) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstXvImageSink *xvimagesink; + GstXvImageBuffer *xvimage = NULL; + GstCaps *intersection = NULL; + GstStructure *structure = NULL; + gint width, height, image_format; + + xvimagesink = GST_XVIMAGESINK (bsink); + + if (G_UNLIKELY (!caps)) + goto no_caps; + + g_mutex_lock (xvimagesink->pool_lock); + if (G_UNLIKELY (xvimagesink->pool_invalid)) + goto invalid; + + if (G_LIKELY (xvimagesink->xcontext->last_caps && + gst_caps_is_equal (caps, xvimagesink->xcontext->last_caps))) { + GST_LOG_OBJECT (xvimagesink, + "buffer alloc for same last_caps, reusing caps"); + intersection = gst_caps_ref (caps); + image_format = xvimagesink->xcontext->last_format; + width = xvimagesink->xcontext->last_width; + height = xvimagesink->xcontext->last_height; + + goto reuse_last_caps; + } + + GST_DEBUG_OBJECT (xvimagesink, "buffer alloc requested size %d with caps %" + GST_PTR_FORMAT ", intersecting with our caps %" GST_PTR_FORMAT, size, + caps, xvimagesink->xcontext->caps); + + /* Check the caps against our xcontext */ + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, caps); + + GST_DEBUG_OBJECT (xvimagesink, "intersection in buffer alloc returned %" + GST_PTR_FORMAT, intersection); + + if (gst_caps_is_empty (intersection)) { + GstCaps *new_caps; + + gst_caps_unref (intersection); + + /* So we don't support this kind of buffer, let's define one we'd like */ + new_caps = gst_caps_copy (caps); + + structure = gst_caps_get_structure (new_caps, 0); + if (!gst_structure_has_field (structure, "width") || + !gst_structure_has_field (structure, "height")) { + gst_caps_unref (new_caps); + goto invalid; + } + + /* Try different dimensions */ + intersection = + gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps); + + if (gst_caps_is_empty (intersection)) { + /* Try with different YUV formats first */ + gst_structure_set_name (structure, "video/x-raw-yuv"); + + /* Remove format specific fields */ + gst_structure_remove_field (structure, "format"); + gst_structure_remove_field (structure, "endianness"); + gst_structure_remove_field (structure, "depth"); + gst_structure_remove_field (structure, "bpp"); + gst_structure_remove_field (structure, "red_mask"); + gst_structure_remove_field (structure, "green_mask"); + gst_structure_remove_field (structure, "blue_mask"); + gst_structure_remove_field (structure, "alpha_mask"); + + /* Reuse intersection with Xcontext */ + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); + } + + if (gst_caps_is_empty (intersection)) { + /* Try with different dimensions and YUV formats */ + intersection = + gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps); + } + + if (gst_caps_is_empty (intersection)) { + /* Now try with RGB */ + gst_structure_set_name (structure, "video/x-raw-rgb"); + /* And interset again */ + gst_caps_unref (intersection); + intersection = gst_caps_intersect (xvimagesink->xcontext->caps, new_caps); + } + + if (gst_caps_is_empty (intersection)) { + /* Try with different dimensions and RGB formats */ + intersection = + gst_xvimage_sink_different_size_suggestion (xvimagesink, new_caps); + } + + /* Clean this copy */ + gst_caps_unref (new_caps); + + if (gst_caps_is_empty (intersection)) + goto incompatible; + } + + /* Ensure the returned caps are fixed */ + gst_caps_truncate (intersection); + + GST_DEBUG_OBJECT (xvimagesink, "allocating a buffer with caps %" + GST_PTR_FORMAT, intersection); + if (gst_caps_is_equal (intersection, caps)) { + /* Things work better if we return a buffer with the same caps ptr + * as was asked for when we can */ + gst_caps_replace (&intersection, caps); + } + + /* Get image format from caps */ + image_format = gst_xvimagesink_get_format_from_caps (xvimagesink, + intersection); + + /* Get geometry from caps */ + structure = gst_caps_get_structure (intersection, 0); + if (!gst_structure_get_int (structure, "width", &width) || + !gst_structure_get_int (structure, "height", &height) || + image_format == -1) + goto invalid_caps; + + /* Store our caps and format as the last_caps to avoid expensive + * caps intersection next time */ + gst_caps_replace (&xvimagesink->xcontext->last_caps, intersection); + xvimagesink->xcontext->last_format = image_format; + xvimagesink->xcontext->last_width = width; + xvimagesink->xcontext->last_height = height; + +reuse_last_caps: + + /* Walking through the pool cleaning unusable images and searching for a + suitable one */ + while (xvimagesink->image_pool) { + xvimage = xvimagesink->image_pool->data; + + if (xvimage) { + /* Removing from the pool */ + xvimagesink->image_pool = g_slist_delete_link (xvimagesink->image_pool, + xvimagesink->image_pool); + + /* We check for geometry or image format changes */ + if ((xvimage->width != width) || + (xvimage->height != height) || (xvimage->im_format != image_format)) { + /* This image is unusable. Destroying... */ + gst_xvimage_buffer_free (xvimage); + xvimage = NULL; + } else { + /* We found a suitable image */ + GST_LOG_OBJECT (xvimagesink, "found usable image in pool"); + break; + } + } + } + + if (!xvimage) { + /* We found no suitable image in the pool. Creating... */ + GST_DEBUG_OBJECT (xvimagesink, "no usable image in pool, creating xvimage"); + xvimage = gst_xvimagesink_xvimage_new (xvimagesink, intersection); + } + g_mutex_unlock (xvimagesink->pool_lock); + + if (xvimage) { + /* Make sure the buffer is cleared of any previously used flags */ + GST_MINI_OBJECT_CAST (xvimage)->flags = 0; + gst_buffer_set_caps (GST_BUFFER_CAST (xvimage), intersection); + } + + *buf = GST_BUFFER_CAST (xvimage); + +beach: + if (intersection) { + gst_caps_unref (intersection); + } + + return ret; + + /* ERRORS */ +invalid: + { + GST_DEBUG_OBJECT (xvimagesink, "the pool is flushing"); + ret = GST_FLOW_WRONG_STATE; + g_mutex_unlock (xvimagesink->pool_lock); + goto beach; + } +incompatible: + { + GST_WARNING_OBJECT (xvimagesink, "we were requested a buffer with " + "caps %" GST_PTR_FORMAT ", but our xcontext caps %" GST_PTR_FORMAT + " are completely incompatible with those caps", caps, + xvimagesink->xcontext->caps); + ret = GST_FLOW_NOT_NEGOTIATED; + g_mutex_unlock (xvimagesink->pool_lock); + goto beach; + } +invalid_caps: + { + GST_WARNING_OBJECT (xvimagesink, "invalid caps for buffer allocation %" + GST_PTR_FORMAT, intersection); + ret = GST_FLOW_NOT_NEGOTIATED; + g_mutex_unlock (xvimagesink->pool_lock); + goto beach; + } +no_caps: + { + GST_WARNING_OBJECT (xvimagesink, "have no caps, doing fallback allocation"); + *buf = NULL; + ret = GST_FLOW_OK; + goto beach; + } +} + +/* Interfaces stuff */ + +static gboolean +gst_xvimagesink_interface_supported (GstImplementsInterface * iface, GType type) +{ + g_assert (type == GST_TYPE_NAVIGATION || type == GST_TYPE_X_OVERLAY || + type == GST_TYPE_COLOR_BALANCE || type == GST_TYPE_PROPERTY_PROBE); + return TRUE; +} + +static void +gst_xvimagesink_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = gst_xvimagesink_interface_supported; +} + +static void +gst_xvimagesink_navigation_send_event (GstNavigation * navigation, + GstStructure * structure) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (navigation); + GstPad *peer; + + if ((peer = gst_pad_get_peer (GST_VIDEO_SINK_PAD (xvimagesink)))) { + GstEvent *event; + GstVideoRectangle src, dst, result; + gdouble x, y, xscale = 1.0, yscale = 1.0; + + event = gst_event_new_navigation (structure); + + /* We take the flow_lock while we look at the window */ + g_mutex_lock (xvimagesink->flow_lock); + + if (!xvimagesink->xwindow) { + g_mutex_unlock (xvimagesink->flow_lock); + return; + } + + if (xvimagesink->keep_aspect) { + /* We get the frame position using the calculated geometry from _setcaps + that respect pixel aspect ratios */ + src.w = GST_VIDEO_SINK_WIDTH (xvimagesink); + src.h = GST_VIDEO_SINK_HEIGHT (xvimagesink); + dst.w = xvimagesink->render_rect.w; + dst.h = xvimagesink->render_rect.h; + + gst_video_sink_center_rect (src, dst, &result, TRUE); + result.x += xvimagesink->render_rect.x; + result.y += xvimagesink->render_rect.y; + } else { + memcpy (&result, &xvimagesink->render_rect, sizeof (GstVideoRectangle)); + } + + g_mutex_unlock (xvimagesink->flow_lock); + + /* We calculate scaling using the original video frames geometry to include + pixel aspect ratio scaling. */ + xscale = (gdouble) xvimagesink->video_width / result.w; + yscale = (gdouble) xvimagesink->video_height / result.h; + + /* Converting pointer coordinates to the non scaled geometry */ + if (gst_structure_get_double (structure, "pointer_x", &x)) { + x = MIN (x, result.x + result.w); + x = MAX (x - result.x, 0); + gst_structure_set (structure, "pointer_x", G_TYPE_DOUBLE, + (gdouble) x * xscale, NULL); + } + if (gst_structure_get_double (structure, "pointer_y", &y)) { + y = MIN (y, result.y + result.h); + y = MAX (y - result.y, 0); + gst_structure_set (structure, "pointer_y", G_TYPE_DOUBLE, + (gdouble) y * yscale, NULL); + } + + gst_pad_send_event (peer, event); + gst_object_unref (peer); + } +} + +static void +gst_xvimagesink_navigation_init (GstNavigationInterface * iface) +{ + iface->send_event = gst_xvimagesink_navigation_send_event; +} + +static void +gst_xvimagesink_set_window_handle (GstXOverlay * overlay, guintptr id) +{ + XID xwindow_id = id; + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + GstXWindow *xwindow = NULL; + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + + g_mutex_lock (xvimagesink->flow_lock); + + /* If we already use that window return */ + if (xvimagesink->xwindow && (xwindow_id == xvimagesink->xwindow->win)) { + g_mutex_unlock (xvimagesink->flow_lock); + return; + } + + /* If the element has not initialized the X11 context try to do so */ + if (!xvimagesink->xcontext && + !(xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink))) { + g_mutex_unlock (xvimagesink->flow_lock); + /* we have thrown a GST_ELEMENT_ERROR now */ + return; + } + + gst_xvimagesink_update_colorbalance (xvimagesink); + + /* Clear image pool as the images are unusable anyway */ + gst_xvimagesink_imagepool_clear (xvimagesink); + + /* Clear the xvimage */ + if (xvimagesink->xvimage) { + gst_xvimage_buffer_free (xvimagesink->xvimage); + xvimagesink->xvimage = NULL; + } + + /* If a window is there already we destroy it */ + if (xvimagesink->xwindow) { + gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + xvimagesink->xwindow = NULL; + } + + /* If the xid is 0 we go back to an internal window */ + if (xwindow_id == 0) { + /* If no width/height caps nego did not happen window will be created + during caps nego then */ + if (GST_VIDEO_SINK_WIDTH (xvimagesink) + && GST_VIDEO_SINK_HEIGHT (xvimagesink)) { + xwindow = + gst_xvimagesink_xwindow_new (xvimagesink, + GST_VIDEO_SINK_WIDTH (xvimagesink), + GST_VIDEO_SINK_HEIGHT (xvimagesink)); + } + } else { + XWindowAttributes attr; + + xwindow = g_new0 (GstXWindow, 1); + xwindow->win = xwindow_id; + + /* Set the event we want to receive and create a GC */ + g_mutex_lock (xvimagesink->x_lock); + + XGetWindowAttributes (xvimagesink->xcontext->disp, xwindow->win, &attr); + + xwindow->width = attr.width; + xwindow->height = attr.height; + xwindow->internal = FALSE; + if (!xvimagesink->have_render_rect) { + xvimagesink->render_rect.x = xvimagesink->render_rect.y = 0; + xvimagesink->render_rect.w = attr.width; + xvimagesink->render_rect.h = attr.height; + } + if (xvimagesink->handle_events) { + XSelectInput (xvimagesink->xcontext->disp, xwindow->win, ExposureMask | + StructureNotifyMask | PointerMotionMask | KeyPressMask | + KeyReleaseMask); + } + + xwindow->gc = XCreateGC (xvimagesink->xcontext->disp, + xwindow->win, 0, NULL); + g_mutex_unlock (xvimagesink->x_lock); + } + + if (xwindow) + xvimagesink->xwindow = xwindow; + + g_mutex_unlock (xvimagesink->flow_lock); +} + +static void +gst_xvimagesink_expose (GstXOverlay * overlay) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + + gst_xvimagesink_xwindow_update_geometry (xvimagesink); + gst_xvimagesink_xvimage_put (xvimagesink, NULL); +} + +static void +gst_xvimagesink_set_event_handling (GstXOverlay * overlay, + gboolean handle_events) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + + xvimagesink->handle_events = handle_events; + + g_mutex_lock (xvimagesink->flow_lock); + + if (G_UNLIKELY (!xvimagesink->xwindow)) { + g_mutex_unlock (xvimagesink->flow_lock); + return; + } + + g_mutex_lock (xvimagesink->x_lock); + + if (handle_events) { + if (xvimagesink->xwindow->internal) { + XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, + ExposureMask | StructureNotifyMask | PointerMotionMask | + KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask); + } else { + XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, + ExposureMask | StructureNotifyMask | PointerMotionMask | + KeyPressMask | KeyReleaseMask); + } + } else { + XSelectInput (xvimagesink->xcontext->disp, xvimagesink->xwindow->win, 0); + } + + g_mutex_unlock (xvimagesink->x_lock); + + g_mutex_unlock (xvimagesink->flow_lock); +} + +static void +gst_xvimagesink_set_render_rectangle (GstXOverlay * overlay, gint x, gint y, + gint width, gint height) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (overlay); + + /* FIXME: how about some locking? */ + if (width >= 0 && height >= 0) { + xvimagesink->render_rect.x = x; + xvimagesink->render_rect.y = y; + xvimagesink->render_rect.w = width; + xvimagesink->render_rect.h = height; + xvimagesink->have_render_rect = TRUE; + } else { + xvimagesink->render_rect.x = 0; + xvimagesink->render_rect.y = 0; + xvimagesink->render_rect.w = xvimagesink->xwindow->width; + xvimagesink->render_rect.h = xvimagesink->xwindow->height; + xvimagesink->have_render_rect = FALSE; + } +} + +static void +gst_xvimagesink_xoverlay_init (GstXOverlayClass * iface) +{ + iface->set_window_handle = gst_xvimagesink_set_window_handle; + iface->expose = gst_xvimagesink_expose; + iface->handle_events = gst_xvimagesink_set_event_handling; + iface->set_render_rectangle = gst_xvimagesink_set_render_rectangle; +} + +static const GList * +gst_xvimagesink_colorbalance_list_channels (GstColorBalance * balance) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), NULL); + + if (xvimagesink->xcontext) + return xvimagesink->xcontext->channels_list; + else + return NULL; +} + +static void +gst_xvimagesink_colorbalance_set_value (GstColorBalance * balance, + GstColorBalanceChannel * channel, gint value) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + + g_return_if_fail (GST_IS_XVIMAGESINK (xvimagesink)); + g_return_if_fail (channel->label != NULL); + + xvimagesink->cb_changed = TRUE; + + /* Normalize val to [-1000, 1000] */ + value = floor (0.5 + -1000 + 2000 * (value - channel->min_value) / + (double) (channel->max_value - channel->min_value)); + + if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { + xvimagesink->hue = value; + } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { + xvimagesink->saturation = value; + } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { + xvimagesink->contrast = value; + } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { + xvimagesink->brightness = value; + } else { + g_warning ("got an unknown channel %s", channel->label); + return; + } + + gst_xvimagesink_update_colorbalance (xvimagesink); +} + +static gint +gst_xvimagesink_colorbalance_get_value (GstColorBalance * balance, + GstColorBalanceChannel * channel) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (balance); + gint value = 0; + + g_return_val_if_fail (GST_IS_XVIMAGESINK (xvimagesink), 0); + g_return_val_if_fail (channel->label != NULL, 0); + + if (g_ascii_strcasecmp (channel->label, "XV_HUE") == 0) { + value = xvimagesink->hue; + } else if (g_ascii_strcasecmp (channel->label, "XV_SATURATION") == 0) { + value = xvimagesink->saturation; + } else if (g_ascii_strcasecmp (channel->label, "XV_CONTRAST") == 0) { + value = xvimagesink->contrast; + } else if (g_ascii_strcasecmp (channel->label, "XV_BRIGHTNESS") == 0) { + value = xvimagesink->brightness; + } else { + g_warning ("got an unknown channel %s", channel->label); + } + + /* Normalize val to [channel->min_value, channel->max_value] */ + value = channel->min_value + (channel->max_value - channel->min_value) * + (value + 1000) / 2000; + + return value; +} + +static void +gst_xvimagesink_colorbalance_init (GstColorBalanceClass * iface) +{ + GST_COLOR_BALANCE_TYPE (iface) = GST_COLOR_BALANCE_HARDWARE; + iface->list_channels = gst_xvimagesink_colorbalance_list_channels; + iface->set_value = gst_xvimagesink_colorbalance_set_value; + iface->get_value = gst_xvimagesink_colorbalance_get_value; +} + +static const GList * +gst_xvimagesink_probe_get_properties (GstPropertyProbe * probe) +{ + GObjectClass *klass = G_OBJECT_GET_CLASS (probe); + static GList *list = NULL; + + if (!list) { + list = g_list_append (NULL, g_object_class_find_property (klass, "device")); + list = + g_list_append (list, g_object_class_find_property (klass, + "autopaint-colorkey")); + list = + g_list_append (list, g_object_class_find_property (klass, + "double-buffer")); + list = + g_list_append (list, g_object_class_find_property (klass, "colorkey")); + } + + return list; +} + +static void +gst_xvimagesink_probe_probe_property (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + + switch (prop_id) { + case PROP_DEVICE: + case PROP_AUTOPAINT_COLORKEY: + case PROP_DOUBLE_BUFFER: + case PROP_COLORKEY: + GST_DEBUG_OBJECT (xvimagesink, + "probing device list and get capabilities"); + if (!xvimagesink->xcontext) { + GST_DEBUG_OBJECT (xvimagesink, "generating xcontext"); + xvimagesink->xcontext = gst_xvimagesink_xcontext_get (xvimagesink); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } +} + +static gboolean +gst_xvimagesink_probe_needs_probe (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + gboolean ret = FALSE; + + switch (prop_id) { + case PROP_DEVICE: + case PROP_AUTOPAINT_COLORKEY: + case PROP_DOUBLE_BUFFER: + case PROP_COLORKEY: + if (xvimagesink->xcontext != NULL) { + ret = FALSE; + } else { + ret = TRUE; + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + + return ret; +} + +static GValueArray * +gst_xvimagesink_probe_get_values (GstPropertyProbe * probe, + guint prop_id, const GParamSpec * pspec) +{ + GstXvImageSink *xvimagesink = GST_XVIMAGESINK (probe); + GValueArray *array = NULL; + + if (G_UNLIKELY (!xvimagesink->xcontext)) { + GST_WARNING_OBJECT (xvimagesink, "we don't have any xcontext, can't " + "get values"); + goto beach; + } + + switch (prop_id) { + case PROP_DEVICE: + { + guint i; + GValue value = { 0 }; + + array = g_value_array_new (xvimagesink->xcontext->nb_adaptors); + g_value_init (&value, G_TYPE_STRING); + + for (i = 0; i < xvimagesink->xcontext->nb_adaptors; i++) { + gchar *adaptor_id_s = g_strdup_printf ("%u", i); + + g_value_set_string (&value, adaptor_id_s); + g_value_array_append (array, &value); + g_free (adaptor_id_s); + } + g_value_unset (&value); + break; + } + case PROP_AUTOPAINT_COLORKEY: + if (xvimagesink->have_autopaint_colorkey) { + GValue value = { 0 }; + + array = g_value_array_new (2); + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, FALSE); + g_value_array_append (array, &value); + g_value_set_boolean (&value, TRUE); + g_value_array_append (array, &value); + g_value_unset (&value); + } + break; + case PROP_DOUBLE_BUFFER: + if (xvimagesink->have_double_buffer) { + GValue value = { 0 }; + + array = g_value_array_new (2); + g_value_init (&value, G_TYPE_BOOLEAN); + g_value_set_boolean (&value, FALSE); + g_value_array_append (array, &value); + g_value_set_boolean (&value, TRUE); + g_value_array_append (array, &value); + g_value_unset (&value); + } + break; + case PROP_COLORKEY: + if (xvimagesink->have_colorkey) { + GValue value = { 0 }; + + array = g_value_array_new (1); + g_value_init (&value, GST_TYPE_INT_RANGE); + gst_value_set_int_range (&value, 0, 0xffffff); + g_value_array_append (array, &value); + g_value_unset (&value); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (probe, prop_id, pspec); + break; + } + +beach: + return array; +} + +static void +gst_xvimagesink_property_probe_interface_init (GstPropertyProbeInterface * + iface) +{ + iface->get_properties = gst_xvimagesink_probe_get_properties; + iface->probe_property = gst_xvimagesink_probe_probe_property; + iface->needs_probe = gst_xvimagesink_probe_needs_probe; + iface->get_values = gst_xvimagesink_probe_get_values; +} + +/* =========================================== */ +/* */ +/* Init & Class init */ +/* */ +/* =========================================== */ + +static void +gst_xvimagesink_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstXvImageSink *xvimagesink; + + g_return_if_fail (GST_IS_XVIMAGESINK (object)); + + xvimagesink = GST_XVIMAGESINK (object); + + switch (prop_id) { + case PROP_HUE: + xvimagesink->hue = g_value_get_int (value); + xvimagesink->cb_changed = TRUE; + gst_xvimagesink_update_colorbalance (xvimagesink); + break; + case PROP_CONTRAST: + xvimagesink->contrast = g_value_get_int (value); + xvimagesink->cb_changed = TRUE; + gst_xvimagesink_update_colorbalance (xvimagesink); + break; + case PROP_BRIGHTNESS: + xvimagesink->brightness = g_value_get_int (value); + xvimagesink->cb_changed = TRUE; + gst_xvimagesink_update_colorbalance (xvimagesink); + break; + case PROP_SATURATION: + xvimagesink->saturation = g_value_get_int (value); + xvimagesink->cb_changed = TRUE; + gst_xvimagesink_update_colorbalance (xvimagesink); + break; + case PROP_DISPLAY: + xvimagesink->display_name = g_strdup (g_value_get_string (value)); + break; + case PROP_SYNCHRONOUS: + xvimagesink->synchronous = g_value_get_boolean (value); + if (xvimagesink->xcontext) { + XSynchronize (xvimagesink->xcontext->disp, xvimagesink->synchronous); + GST_DEBUG_OBJECT (xvimagesink, "XSynchronize called with %s", + xvimagesink->synchronous ? "TRUE" : "FALSE"); + } + break; + case PROP_PIXEL_ASPECT_RATIO: + g_free (xvimagesink->par); + xvimagesink->par = g_new0 (GValue, 1); + g_value_init (xvimagesink->par, GST_TYPE_FRACTION); + if (!g_value_transform (value, xvimagesink->par)) { + g_warning ("Could not transform string to aspect ratio"); + gst_value_set_fraction (xvimagesink->par, 1, 1); + } + GST_DEBUG_OBJECT (xvimagesink, "set PAR to %d/%d", + gst_value_get_fraction_numerator (xvimagesink->par), + gst_value_get_fraction_denominator (xvimagesink->par)); + break; + case PROP_FORCE_ASPECT_RATIO: + xvimagesink->keep_aspect = g_value_get_boolean (value); + break; + case PROP_HANDLE_EVENTS: + gst_xvimagesink_set_event_handling (GST_X_OVERLAY (xvimagesink), + g_value_get_boolean (value)); + gst_xvimagesink_manage_event_thread (xvimagesink); + break; + case PROP_DEVICE: + xvimagesink->adaptor_no = atoi (g_value_get_string (value)); + break; + case PROP_HANDLE_EXPOSE: + xvimagesink->handle_expose = g_value_get_boolean (value); + gst_xvimagesink_manage_event_thread (xvimagesink); + break; + case PROP_DOUBLE_BUFFER: + xvimagesink->double_buffer = g_value_get_boolean (value); + break; + case PROP_AUTOPAINT_COLORKEY: + xvimagesink->autopaint_colorkey = g_value_get_boolean (value); + break; + case PROP_COLORKEY: + xvimagesink->colorkey = g_value_get_int (value); + break; + case PROP_DRAW_BORDERS: + xvimagesink->draw_borders = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_xvimagesink_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstXvImageSink *xvimagesink; + + g_return_if_fail (GST_IS_XVIMAGESINK (object)); + + xvimagesink = GST_XVIMAGESINK (object); + + switch (prop_id) { + case PROP_HUE: + g_value_set_int (value, xvimagesink->hue); + break; + case PROP_CONTRAST: + g_value_set_int (value, xvimagesink->contrast); + break; + case PROP_BRIGHTNESS: + g_value_set_int (value, xvimagesink->brightness); + break; + case PROP_SATURATION: + g_value_set_int (value, xvimagesink->saturation); + break; + case PROP_DISPLAY: + g_value_set_string (value, xvimagesink->display_name); + break; + case PROP_SYNCHRONOUS: + g_value_set_boolean (value, xvimagesink->synchronous); + break; + case PROP_PIXEL_ASPECT_RATIO: + if (xvimagesink->par) + g_value_transform (xvimagesink->par, value); + break; + case PROP_FORCE_ASPECT_RATIO: + g_value_set_boolean (value, xvimagesink->keep_aspect); + break; + case PROP_HANDLE_EVENTS: + g_value_set_boolean (value, xvimagesink->handle_events); + break; + case PROP_DEVICE: + { + char *adaptor_no_s = g_strdup_printf ("%u", xvimagesink->adaptor_no); + + g_value_set_string (value, adaptor_no_s); + g_free (adaptor_no_s); + break; + } + case PROP_DEVICE_NAME: + if (xvimagesink->xcontext && xvimagesink->xcontext->adaptors) { + g_value_set_string (value, + xvimagesink->xcontext->adaptors[xvimagesink->adaptor_no]); + } else { + g_value_set_string (value, NULL); + } + break; + case PROP_HANDLE_EXPOSE: + g_value_set_boolean (value, xvimagesink->handle_expose); + break; + case PROP_DOUBLE_BUFFER: + g_value_set_boolean (value, xvimagesink->double_buffer); + break; + case PROP_AUTOPAINT_COLORKEY: + g_value_set_boolean (value, xvimagesink->autopaint_colorkey); + break; + case PROP_COLORKEY: + g_value_set_int (value, xvimagesink->colorkey); + break; + case PROP_DRAW_BORDERS: + g_value_set_boolean (value, xvimagesink->draw_borders); + break; + case PROP_WINDOW_WIDTH: + if (xvimagesink->xwindow) + g_value_set_uint64 (value, xvimagesink->xwindow->width); + else + g_value_set_uint64 (value, 0); + break; + case PROP_WINDOW_HEIGHT: + if (xvimagesink->xwindow) + g_value_set_uint64 (value, xvimagesink->xwindow->height); + else + g_value_set_uint64 (value, 0); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_xvimagesink_reset (GstXvImageSink * xvimagesink) +{ + GThread *thread; + + GST_OBJECT_LOCK (xvimagesink); + xvimagesink->running = FALSE; + /* grab thread and mark it as NULL */ + thread = xvimagesink->event_thread; + xvimagesink->event_thread = NULL; + GST_OBJECT_UNLOCK (xvimagesink); + + /* invalidate the pool, current allocations continue, new buffer_alloc fails + * with wrong_state */ + g_mutex_lock (xvimagesink->pool_lock); + xvimagesink->pool_invalid = TRUE; + g_mutex_unlock (xvimagesink->pool_lock); + + /* Wait for our event thread to finish before we clean up our stuff. */ + if (thread) + g_thread_join (thread); + + if (xvimagesink->cur_image) { + gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->cur_image)); + xvimagesink->cur_image = NULL; + } + if (xvimagesink->xvimage) { + gst_buffer_unref (GST_BUFFER_CAST (xvimagesink->xvimage)); + xvimagesink->xvimage = NULL; + } + + gst_xvimagesink_imagepool_clear (xvimagesink); + + if (xvimagesink->xwindow) { + gst_xvimagesink_xwindow_clear (xvimagesink, xvimagesink->xwindow); + gst_xvimagesink_xwindow_destroy (xvimagesink, xvimagesink->xwindow); + xvimagesink->xwindow = NULL; + } + + xvimagesink->render_rect.x = xvimagesink->render_rect.y = + xvimagesink->render_rect.w = xvimagesink->render_rect.h = 0; + xvimagesink->have_render_rect = FALSE; + + gst_xvimagesink_xcontext_clear (xvimagesink); +} + +/* Finalize is called only once, dispose can be called multiple times. + * We use mutexes and don't reset stuff to NULL here so let's register + * as a finalize. */ +static void +gst_xvimagesink_finalize (GObject * object) +{ + GstXvImageSink *xvimagesink; + + xvimagesink = GST_XVIMAGESINK (object); + + gst_xvimagesink_reset (xvimagesink); + + if (xvimagesink->display_name) { + g_free (xvimagesink->display_name); + xvimagesink->display_name = NULL; + } + + if (xvimagesink->par) { + g_free (xvimagesink->par); + xvimagesink->par = NULL; + } + if (xvimagesink->x_lock) { + g_mutex_free (xvimagesink->x_lock); + xvimagesink->x_lock = NULL; + } + if (xvimagesink->flow_lock) { + g_mutex_free (xvimagesink->flow_lock); + xvimagesink->flow_lock = NULL; + } + if (xvimagesink->pool_lock) { + g_mutex_free (xvimagesink->pool_lock); + xvimagesink->pool_lock = NULL; + } + + g_free (xvimagesink->media_title); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_xvimagesink_init (GstXvImageSink * xvimagesink) +{ + xvimagesink->display_name = NULL; + xvimagesink->adaptor_no = 0; + xvimagesink->xcontext = NULL; + xvimagesink->xwindow = NULL; + xvimagesink->xvimage = NULL; + xvimagesink->cur_image = NULL; + + xvimagesink->hue = xvimagesink->saturation = 0; + xvimagesink->contrast = xvimagesink->brightness = 0; + xvimagesink->cb_changed = FALSE; + + xvimagesink->fps_n = 0; + xvimagesink->fps_d = 0; + xvimagesink->video_width = 0; + xvimagesink->video_height = 0; + + xvimagesink->x_lock = g_mutex_new (); + xvimagesink->flow_lock = g_mutex_new (); + + xvimagesink->image_pool = NULL; + xvimagesink->pool_lock = g_mutex_new (); + + xvimagesink->synchronous = FALSE; + xvimagesink->double_buffer = TRUE; + xvimagesink->running = FALSE; + xvimagesink->keep_aspect = FALSE; + xvimagesink->handle_events = TRUE; + xvimagesink->par = NULL; + xvimagesink->handle_expose = TRUE; + xvimagesink->autopaint_colorkey = TRUE; + + /* on 16bit displays this becomes r,g,b = 1,2,3 + * on 24bit displays this becomes r,g,b = 8,8,16 + * as a port atom value + */ + xvimagesink->colorkey = (8 << 16) | (8 << 8) | 16; + xvimagesink->draw_borders = TRUE; +} + +static void +gst_xvimagesink_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "Video sink", "Sink/Video", + "A Xv based videosink", "Julien Moutte "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_xvimagesink_sink_template_factory)); +} + +static void +gst_xvimagesink_class_init (GstXvImageSinkClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseSinkClass *gstbasesink_class; + GstVideoSinkClass *videosink_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + gstbasesink_class = (GstBaseSinkClass *) klass; + videosink_class = (GstVideoSinkClass *) klass; + + parent_class = g_type_class_peek_parent (klass); + + gobject_class->set_property = gst_xvimagesink_set_property; + gobject_class->get_property = gst_xvimagesink_get_property; + + g_object_class_install_property (gobject_class, PROP_CONTRAST, + g_param_spec_int ("contrast", "Contrast", "The contrast of the video", + -1000, 1000, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_BRIGHTNESS, + g_param_spec_int ("brightness", "Brightness", + "The brightness of the video", -1000, 1000, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HUE, + g_param_spec_int ("hue", "Hue", "The hue of the video", -1000, 1000, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SATURATION, + g_param_spec_int ("saturation", "Saturation", + "The saturation of the video", -1000, 1000, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_SYNCHRONOUS, + g_param_spec_boolean ("synchronous", "Synchronous", + "When enabled, runs " + "the X display in synchronous mode. (used only for debugging)", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PIXEL_ASPECT_RATIO, + g_param_spec_string ("pixel-aspect-ratio", "Pixel Aspect Ratio", + "The pixel aspect ratio of the device", "1/1", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, + g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio", + "When enabled, scaling will respect original aspect ratio", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_HANDLE_EVENTS, + g_param_spec_boolean ("handle-events", "Handle XEvents", + "When enabled, XEvents will be selected and handled", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DEVICE, + g_param_spec_string ("device", "Adaptor number", + "The number of the video adaptor", "0", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DEVICE_NAME, + g_param_spec_string ("device-name", "Adaptor name", + "The name of the video adaptor", NULL, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /** + * GstXvImageSink:handle-expose + * + * When enabled, the current frame will always be drawn in response to X + * Expose. + * + * Since: 0.10.14 + */ + g_object_class_install_property (gobject_class, PROP_HANDLE_EXPOSE, + g_param_spec_boolean ("handle-expose", "Handle expose", + "When enabled, " + "the current frame will always be drawn in response to X Expose " + "events", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXvImageSink:double-buffer + * + * Whether to double-buffer the output. + * + * Since: 0.10.14 + */ + g_object_class_install_property (gobject_class, PROP_DOUBLE_BUFFER, + g_param_spec_boolean ("double-buffer", "Double-buffer", + "Whether to double-buffer the output", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstXvImageSink:autopaint-colorkey + * + * Whether to autofill overlay with colorkey + * + * Since: 0.10.21 + */ + g_object_class_install_property (gobject_class, PROP_AUTOPAINT_COLORKEY, + g_param_spec_boolean ("autopaint-colorkey", "Autofill with colorkey", + "Whether to autofill overlay with colorkey", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstXvImageSink:colorkey + * + * Color to use for the overlay mask. + * + * Since: 0.10.21 + */ + g_object_class_install_property (gobject_class, PROP_COLORKEY, + g_param_spec_int ("colorkey", "Colorkey", + "Color to use for the overlay mask", G_MININT, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXvImageSink:draw-borders + * + * Draw black borders when using GstXvImageSink:force-aspect-ratio to fill + * unused parts of the video area. + * + * Since: 0.10.21 + */ + g_object_class_install_property (gobject_class, PROP_DRAW_BORDERS, + g_param_spec_boolean ("draw-borders", "Colorkey", + "Draw black borders to fill unused area in force-aspect-ratio mode", + TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXvImageSink:window-width + * + * Actual width of the video window. + * + * Since: 0.10.32 + */ + g_object_class_install_property (gobject_class, PROP_WINDOW_WIDTH, + g_param_spec_uint64 ("window-width", "window-width", + "Width of the window", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** + * GstXvImageSink:window-height + * + * Actual height of the video window. + * + * Since: 0.10.32 + */ + g_object_class_install_property (gobject_class, PROP_WINDOW_HEIGHT, + g_param_spec_uint64 ("window-height", "window-height", + "Height of the window", 0, G_MAXUINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + gobject_class->finalize = gst_xvimagesink_finalize; + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_xvimagesink_change_state); + + gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_getcaps); + gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_xvimagesink_setcaps); + gstbasesink_class->buffer_alloc = + GST_DEBUG_FUNCPTR (gst_xvimagesink_buffer_alloc); + gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_xvimagesink_get_times); + gstbasesink_class->event = GST_DEBUG_FUNCPTR (gst_xvimagesink_event); + + videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_xvimagesink_show_frame); +} + +/* ============================================================= */ +/* */ +/* Public Methods */ +/* */ +/* ============================================================= */ + +/* =========================================== */ +/* */ +/* Object typing & Creation */ +/* */ +/* =========================================== */ + +GType +gst_xvimagesink_get_type (void) +{ + static GType xvimagesink_type = 0; + + if (!xvimagesink_type) { + static const GTypeInfo xvimagesink_info = { + sizeof (GstXvImageSinkClass), + gst_xvimagesink_base_init, + NULL, + (GClassInitFunc) gst_xvimagesink_class_init, + NULL, + NULL, + sizeof (GstXvImageSink), + 0, + (GInstanceInitFunc) gst_xvimagesink_init, + }; + static const GInterfaceInfo iface_info = { + (GInterfaceInitFunc) gst_xvimagesink_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo navigation_info = { + (GInterfaceInitFunc) gst_xvimagesink_navigation_init, + NULL, + NULL, + }; + static const GInterfaceInfo overlay_info = { + (GInterfaceInitFunc) gst_xvimagesink_xoverlay_init, + NULL, + NULL, + }; + static const GInterfaceInfo colorbalance_info = { + (GInterfaceInitFunc) gst_xvimagesink_colorbalance_init, + NULL, + NULL, + }; + static const GInterfaceInfo propertyprobe_info = { + (GInterfaceInitFunc) gst_xvimagesink_property_probe_interface_init, + NULL, + NULL, + }; + xvimagesink_type = g_type_register_static (GST_TYPE_VIDEO_SINK, + "GstXvImageSink", &xvimagesink_info, 0); + + g_type_add_interface_static (xvimagesink_type, + GST_TYPE_IMPLEMENTS_INTERFACE, &iface_info); + g_type_add_interface_static (xvimagesink_type, GST_TYPE_NAVIGATION, + &navigation_info); + g_type_add_interface_static (xvimagesink_type, GST_TYPE_X_OVERLAY, + &overlay_info); + g_type_add_interface_static (xvimagesink_type, GST_TYPE_COLOR_BALANCE, + &colorbalance_info); + g_type_add_interface_static (xvimagesink_type, GST_TYPE_PROPERTY_PROBE, + &propertyprobe_info); + + + /* register type and create class in a more safe place instead of at + * runtime since the type registration and class creation is not + * threadsafe. */ + g_type_class_ref (gst_xvimage_buffer_get_type ()); + } + + return xvimagesink_type; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_element_register (plugin, "xvimagesink", + GST_RANK_PRIMARY, GST_TYPE_XVIMAGESINK)) + return FALSE; + + GST_DEBUG_CATEGORY_INIT (gst_debug_xvimagesink, "xvimagesink", 0, + "xvimagesink element"); + GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "xvimagesink", + "XFree86 video output plugin using Xv extension", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.h b/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.h new file mode 100644 index 0000000..0181018 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/sys/xvimage/xvimagesink.h @@ -0,0 +1,303 @@ +/* GStreamer + * Copyright (C) <2005> Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_XVIMAGESINK_H__ +#define __GST_XVIMAGESINK_H__ + +#include + +#ifdef HAVE_XSHM +#include +#include +#include +#endif /* HAVE_XSHM */ + +#include +#include + +#ifdef HAVE_XSHM +#include +#endif /* HAVE_XSHM */ + +#include +#include + +#include +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_XVIMAGESINK \ + (gst_xvimagesink_get_type()) +#define GST_XVIMAGESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_XVIMAGESINK, GstXvImageSink)) +#define GST_XVIMAGESINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_XVIMAGESINK, GstXvImageSinkClass)) +#define GST_IS_XVIMAGESINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_XVIMAGESINK)) +#define GST_IS_XVIMAGESINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_XVIMAGESINK)) + +typedef struct _GstXContext GstXContext; +typedef struct _GstXWindow GstXWindow; +typedef struct _GstXvImageFormat GstXvImageFormat; +typedef struct _GstXvImageBuffer GstXvImageBuffer; +typedef struct _GstXvImageBufferClass GstXvImageBufferClass; + +typedef struct _GstXvImageSink GstXvImageSink; +typedef struct _GstXvImageSinkClass GstXvImageSinkClass; + +/* + * GstXContext: + * @disp: the X11 Display of this context + * @screen: the default Screen of Display @disp + * @screen_num: the Screen number of @screen + * @visual: the default Visual of Screen @screen + * @root: the root Window of Display @disp + * @white: the value of a white pixel on Screen @screen + * @black: the value of a black pixel on Screen @screen + * @depth: the color depth of Display @disp + * @bpp: the number of bits per pixel on Display @disp + * @endianness: the endianness of image bytes on Display @disp + * @width: the width in pixels of Display @disp + * @height: the height in pixels of Display @disp + * @widthmm: the width in millimeters of Display @disp + * @heightmm: the height in millimeters of Display @disp + * @par: the pixel aspect ratio calculated from @width, @widthmm and @height, + * @heightmm ratio + * @use_xshm: used to known wether of not XShm extension is usable or not even + * if the Extension is present + * @xv_port_id: the XVideo port ID + * @im_format: used to store at least a valid format for XShm calls checks + * @formats_list: list of supported image formats on @xv_port_id + * @channels_list: list of #GstColorBalanceChannels + * @caps: the #GstCaps that Display @disp can accept + * + * Structure used to store various informations collected/calculated for a + * Display. + */ +struct _GstXContext { + Display *disp; + + Screen *screen; + gint screen_num; + + Visual *visual; + + Window root; + + gulong white, black; + + gint depth; + gint bpp; + gint endianness; + + gint width, height; + gint widthmm, heightmm; + GValue *par; /* calculated pixel aspect ratio */ + + gboolean use_xshm; + + XvPortID xv_port_id; + guint nb_adaptors; + gchar ** adaptors; + gint im_format; + + GList *formats_list; + GList *channels_list; + + GstCaps *caps; + + /* Optimisation storage for buffer_alloc return */ + GstCaps *last_caps; + gint last_format; + gint last_width; + gint last_height; +}; + +/* + * GstXWindow: + * @win: the Window ID of this X11 window + * @width: the width in pixels of Window @win + * @height: the height in pixels of Window @win + * @internal: used to remember if Window @win was created internally or passed + * through the #GstXOverlay interface + * @gc: the Graphical Context of Window @win + * + * Structure used to store informations about a Window. + */ +struct _GstXWindow { + Window win; + gint width, height; + gboolean internal; + GC gc; +}; + +/** + * GstXvImageFormat: + * @format: the image format + * @caps: generated #GstCaps for this image format + * + * Structure storing image format to #GstCaps association. + */ +struct _GstXvImageFormat { + gint format; + GstCaps *caps; +}; + +/** + * GstXImageBuffer: + * @xvimagesink: a reference to our #GstXvImageSink + * @xvimage: the XvImage of this buffer + * @width: the width in pixels of XvImage @xvimage + * @height: the height in pixels of XvImage @xvimage + * @im_format: the image format of XvImage @xvimage + * @size: the size in bytes of XvImage @xvimage + * + * Subclass of #GstBuffer containing additional information about an XvImage. + */ +struct _GstXvImageBuffer { + GstBuffer buffer; + + /* Reference to the xvimagesink we belong to */ + GstXvImageSink *xvimagesink; + + XvImage *xvimage; + +#ifdef HAVE_XSHM + XShmSegmentInfo SHMInfo; +#endif /* HAVE_XSHM */ + + gint width, height, im_format; + size_t size; +}; + +/** + * GstXvImageSink: + * @display_name: the name of the Display we want to render to + * @xcontext: our instance's #GstXContext + * @xwindow: the #GstXWindow we are rendering to + * @xvimage: internal #GstXvImage used to store incoming buffers and render when + * not using the buffer_alloc optimization mechanism + * @cur_image: a reference to the last #GstXvImage that was put to @xwindow. It + * is used when Expose events are received to redraw the latest video frame + * @event_thread: a thread listening for events on @xwindow and handling them + * @running: used to inform @event_thread if it should run/shutdown + * @fps_n: the framerate fraction numerator + * @fps_d: the framerate fraction denominator + * @x_lock: used to protect X calls as we are not using the XLib in threaded + * mode + * @flow_lock: used to protect data flow routines from external calls such as + * events from @event_thread or methods from the #GstXOverlay interface + * @par: used to override calculated pixel aspect ratio from @xcontext + * @pool_lock: used to protect the buffer pool + * @image_pool: a list of #GstXvImageBuffer that could be reused at next buffer + * allocation call + * @synchronous: used to store if XSynchronous should be used or not (for + * debugging purpose only) + * @keep_aspect: used to remember if reverse negotiation scaling should respect + * aspect ratio + * @handle_events: used to know if we should handle select XEvents or not + * @brightness: used to store the user settings for color balance brightness + * @contrast: used to store the user settings for color balance contrast + * @hue: used to store the user settings for color balance hue + * @saturation: used to store the user settings for color balance saturation + * @cb_changed: used to store if the color balance settings where changed + * @video_width: the width of incoming video frames in pixels + * @video_height: the height of incoming video frames in pixels + * + * The #GstXvImageSink data structure. + */ +struct _GstXvImageSink { + /* Our element stuff */ + GstVideoSink videosink; + + char *display_name; + guint adaptor_no; + + GstXContext *xcontext; + GstXWindow *xwindow; + GstXvImageBuffer *xvimage; + GstXvImageBuffer *cur_image; + + GThread *event_thread; + gboolean running; + + gint fps_n; + gint fps_d; + + GMutex *x_lock; + GMutex *flow_lock; + + /* object-set pixel aspect ratio */ + GValue *par; + + GMutex *pool_lock; + gboolean pool_invalid; + GSList *image_pool; + + gboolean synchronous; + gboolean double_buffer; + gboolean keep_aspect; + gboolean redraw_border; + gboolean handle_events; + gboolean handle_expose; + + gint brightness; + gint contrast; + gint hue; + gint saturation; + gboolean cb_changed; + + /* size of incoming video, used as the size for XvImage */ + guint video_width, video_height; + + /* display sizes, used for clipping the image */ + gint disp_x, disp_y; + gint disp_width, disp_height; + + /* port attributes */ + gboolean autopaint_colorkey; + gint colorkey; + + gboolean draw_borders; + + /* port features */ + gboolean have_autopaint_colorkey; + gboolean have_colorkey; + gboolean have_double_buffer; + + /* stream metadata */ + gchar *media_title; + + /* target video rectagle */ + GstVideoRectangle render_rect; + gboolean have_render_rect; +}; + +struct _GstXvImageSinkClass { + GstVideoSinkClass parent_class; +}; + +GType gst_xvimagesink_get_type(void); + +G_END_DECLS + +#endif /* __GST_XVIMAGESINK_H__ */ diff --git a/gst-plugins-base-subtitles0.10/tests/Makefile.am b/gst-plugins-base-subtitles0.10/tests/Makefile.am new file mode 100644 index 0000000..de36755 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/Makefile.am @@ -0,0 +1,28 @@ +if BUILD_EXAMPLES +SUBDIRS_EXAMPLES = examples +else +SUBDIRS_EXAMPLES = +endif + +if HAVE_GST_CHECK +SUBDIRS_CHECK = check +else +SUBDIRS_CHECK = +endif + +if USE_X +SUBDIRS_ICLES = icles +else +SUBDIRS_ICLES = +endif + +SUBDIRS = \ + $(SUBDIRS_CHECK) \ + $(SUBDIRS_EXAMPLES) \ + $(SUBDIRS_ICLES) + +DIST_SUBDIRS = \ + check \ + examples \ + files \ + icles diff --git a/gst-plugins-base-subtitles0.10/tests/check/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/.gitignore new file mode 100644 index 0000000..9af3130 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/.gitignore @@ -0,0 +1 @@ +test-registry.* diff --git a/gst-plugins-base-subtitles0.10/tests/check/Makefile.am b/gst-plugins-base-subtitles0.10/tests/check/Makefile.am new file mode 100644 index 0000000..8b8782d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/Makefile.am @@ -0,0 +1,529 @@ +include $(top_srcdir)/common/check.mak + +CHECK_REGISTRY = $(top_builddir)/tests/check/test-registry.reg +TEST_FILES_DIRECTORY = $(top_srcdir)/tests/files + +REGISTRY_ENVIRONMENT = \ + GST_REGISTRY=$(CHECK_REGISTRY) + +TESTS_ENVIRONMENT = \ + CK_DEFAULT_TIMEOUT=120 \ + GST_STATE_IGNORE_ELEMENTS="$(STATE_IGNORE_ELEMENTS)" \ + $(REGISTRY_ENVIRONMENT) \ + GST_PLUGIN_SYSTEM_PATH= \ + GST_PLUGIN_PATH=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(GST_PLUGINS_DIR) \ + GST_PLUGIN_LOADING_WHITELIST="gstreamer:gst-plugins-base@$(top_builddir)" + + +# ths core dumps of some machines have PIDs appended +CLEANFILES = core.* test-registry.* + +clean-local: clean-local-check clean-local-orc + +$(CHECK_REGISTRY): + $(TESTS_ENVIRONMENT) + +# elements to ignore for the state tests +STATE_IGNORE_ELEMENTS = cdio cdparanoiasrc libvisual_ alsasrc alsamixer alsasink + +TESTS = $(check_PROGRAMS) + +if USE_ALSA +check_alsa = elements/alsa +else +check_alsa = +endif + +if USE_GNOME_VFS +check_gnomevfs = elements/gnomevfssink +else +check_gnomevfs = +endif + +if USE_GIO +check_gio = pipelines/gio +else +check_gio = +endif + +if USE_LIBVISUAL +check_libvisual = elements/libvisual +else +check_libvisual = +endif + +if USE_OGG +check_ogg = pipelines/oggmux +else +check_ogg = +endif + +if USE_PANGO +check_pango = elements/textoverlay +else +check_pango = +endif + +if USE_VORBIS +check_vorbis = elements/vorbisdec pipelines/vorbisenc pipelines/vorbisdec \ + elements/vorbistag +else +check_vorbis = +endif + +if USE_THEORA +check_theora = pipelines/theoraenc +else +check_theora = +endif + +if USE_VORBIS +if USE_THEORA +check_encodebin = elements/encodebin +else +check_encodebin = +endif +else +check_encodebin = +endif + +if USE_PLUGIN_SUBPARSE +check_subparse = elements/subparse +else +check_subparse = +endif + +if HAVE_ORC +check_orc = orc/adder orc/audioconvert orc/volume orc/videoscale orc/videotestsrc +else +check_orc = +endif + +if HAVE_CXX +cxx_checks = libs/gstlibscpp +else +cxx_checks = +endif + +check_PROGRAMS = \ + $(check_alsa) \ + $(check_gnomevfs) \ + $(check_gio) \ + $(check_ogg) \ + $(check_pango) \ + $(check_vorbis) \ + $(check_theora) \ + elements/adder \ + elements/appsink \ + elements/appsrc \ + elements/audioconvert \ + elements/audiorate \ + elements/audioresample \ + elements/audiotestsrc \ + elements/decodebin \ + elements/decodebin2 \ + $(check_encodebin) \ + elements/ffmpegcolorspace \ + elements/gdpdepay \ + elements/gdppay \ + elements/multifdsink \ + elements/playbin \ + elements/playbin2 \ + $(check_subparse) \ + elements/videorate \ + elements/videoscale \ + elements/videotestsrc \ + elements/volume \ + generic/clock-selection \ + generic/states \ + gst/typefindfunctions \ + libs/libsabi \ + libs/audio \ + libs/cddabasesrc \ + libs/discoverer \ + libs/fft \ + libs/mixer \ + libs/navigation \ + libs/netbuffer \ + libs/pbutils \ + libs/profile \ + libs/rtp \ + libs/rtsp \ + libs/tag \ + libs/video \ + libs/xmpwriter \ + $(cxx_checks) \ + $(check_orc) \ + pipelines/simple-launch-lines \ + pipelines/streamheader \ + pipelines/basetime \ + pipelines/capsfilter-renegotiation + +# TORTURE_TO_FIX = \ +# elements/adder + +# ffmpegcolorspace takes too long, so disabled for now +VALGRIND_TO_FIX = \ + elements/ffmpegcolorspace \ + libs/video + +# these tests don't even pass +noinst_PROGRAMS = $(check_libvisual) + +noinst_HEADERS = \ + libs/struct_i386.h \ + libs/struct_i386_osx.h \ + libs/struct_x86_64.h + +AM_CFLAGS = -I$(top_srcdir)/gst-libs -I$(top_builddir)/gst-libs \ + $(GST_CFLAGS) $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS +AM_CXXFLAGS = -I$(top_srcdir)/gst-libs -I$(top_builddir)/gst-libs \ + $(GST_CXXFLAGS) $(GST_CHECK_CFLAGS) \ + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS +LDADD = $(GST_LIBS) $(GST_CHECK_LIBS) + +# valgrind testing +VALGRIND_TESTS_DISABLE = $(VALGRIND_TO_FIX) + +SUPPRESSIONS = $(top_srcdir)/common/gst.supp $(srcdir)/gst-plugins-base.supp + +libs_libsabi_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_libsabi_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/cdda/libgstcdda-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/fft/libgstfft-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/netbuffer/libgstnetbuffer-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/rtsp/libgstrtsp-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_audio_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_audio_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_cddabasesrc_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_cddabasesrc_LDADD = \ + $(top_builddir)/gst-libs/gst/cdda/libgstcdda-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_discoverer_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) \ + -DGST_TEST_FILE="\"$(abs_top_srcdir)/tests/files/partialframe.mjpeg\"" +libs_discoverer_LDADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +libs_fft_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_fft_LDADD = \ + $(top_builddir)/gst-libs/gst/fft/libgstfft-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_mixer_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_mixer_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_navigation_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_navigation_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +libs_netbuffer_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_netbuffer_LDADD = \ + $(top_builddir)/gst-libs/gst/netbuffer/libgstnetbuffer-@GST_MAJORMINOR@.la \ + $(LDADD) + +libs_rtp_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_rtp_LDADD = \ + $(top_builddir)/gst-libs/gst/rtp/libgstrtp-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +libs_rtsp_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_rtsp_LDADD = \ + $(top_builddir)/gst-libs/gst/rtsp/libgstrtsp-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +libs_tag_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_tag_LDADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +libs_pbutils_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_pbutils_LDADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +libs_profile_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) +libs_profile_LDADD = \ + $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(LDADD) + +libs_xmpwriter_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_xmpwriter_LDADD = \ + $(top_builddir)/gst-libs/gst/tag/libgsttag-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + + +libs_gstlibscpp_SOURCES = libs/gstlibscpp.cc + +elements_appsink_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_appsink_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(LDADD) + +elements_appsrc_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_appsrc_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(LDADD) + +elements_alsa_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_alsa_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(LDADD) + +elements_audioconvert_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_audioconvert_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +elements_audiorate_LDADD = $(LDADD) +elements_audiorate_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(CFLAGS) $(AM_CFLAGS) + +elements_libvisual_LDADD = $(LDADD) +elements_libvisual_CFLAGS = $(CFLAGS) $(AM_CFLAGS) + +elements_gdpdepay_LDADD = $(GST_GDP_LIBS) $(LDADD) +elements_gdppay_LDADD = $(GST_GDP_LIBS) $(LDADD) + +elements_playbin_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_playbin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_playbin2_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_playbin2_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_decodebin_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_decodebin_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_encodebin_LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la $(GST_BASE_LIBS) $(LDADD) +elements_encodebin_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_decodebin2_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_decodebin2_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_subparse_LDADD = $(LDADD) +elements_subparse_CFLAGS = $(CFLAGS) $(AM_CFLAGS) + +elements_audioresample_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_audioresample_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +elements_textoverlay_LDADD = $(GST_BASE_LIBS) $(LDADD) +elements_textoverlay_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) + +elements_volume_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) \ + $(GST_CONTROLLER_LIBS) \ + $(GST_BASE_LIBS) \ + $(LDADD) + +elements_volume_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CONTROLLER_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +elements_vorbisdec_LDADD = \ + $(LDADD) \ + $(VORBIS_LIBS) \ + $(VORBISENC_LIBS) + +elements_vorbisdec_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) \ + $(VORBIS_CFLAGS) \ + $(CFLAGS) + +elements_vorbistag_LDADD = \ + $(LDADD) \ + $(VORBIS_LIBS) \ + $(VORBISENC_LIBS) + +elements_vorbistag_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) \ + $(VORBIS_CFLAGS) \ + $(CFLAGS) + +elements_videoscale_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) +elements_videoscale_LDADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(LDADD) + +gst_typefindfunctions_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) +gst_typefindfunctions_LDADD = $(GST_BASE_LIBS) $(LDADD) + +libs_video_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +libs_video_LDADD = \ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +pipelines_gio_CFLAGS = $(GIO_CFLAGS) $(AM_CFLAGS) +pipelines_gio_LDADD = $(GIO_LIBS) $(LDADD) + +pipelines_vorbisenc_CFLAGS = \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(AM_CFLAGS) + +# this seemingly useless CFLAGS line is here only to avoid +# vorbisdec.$(OBJEXT) by triggering creation of pipelines_vorbisdec.$(OBJEXT) +# instead +pipelines_vorbisdec_CFLAGS = $(AM_CFLAGS) + +pipelines_oggmux_LDADD = $(LDADD) $(OGG_LIBS) +pipelines_oggmux_CFLAGS = $(AM_CFLAGS) $(OGG_CFLAGS) + +pipelines_theoraenc_CFLAGS = $(AM_CFLAGS) $(THEORA_CFLAGS) +pipelines_theoraenc_LDADD = $(LDADD) $(THEORA_LIBS) + +pipelines_simple_launch_lines_CFLAGS = \ + $(GST_BASE_CFLAGS) \ + $(AM_CFLAGS) + +pipelines_simple_launch_lines_LDADD = \ + $(top_builddir)/gst-libs/gst/audio/libgstaudio-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) \ + $(LDADD) + +orc_adder_CFLAGS = $(ORC_CFLAGS) +orc_adder_LDADD = $(ORC_LIBS) -lorc-test-0.4 +nodist_orc_adder_SOURCES = orc/adder.c +orc_audioconvert_CFLAGS = $(ORC_CFLAGS) +orc_audioconvert_LDADD = $(ORC_LIBS) -lorc-test-0.4 +nodist_orc_audioconvert_SOURCES = orc/audioconvert.c +orc_volume_CFLAGS = $(ORC_CFLAGS) +orc_volume_LDADD = $(ORC_LIBS) -lorc-test-0.4 +nodist_orc_volume_SOURCES = orc/volume.c +orc_videoscale_CFLAGS = $(ORC_CFLAGS) +orc_videoscale_LDADD = $(ORC_LIBS) -lorc-test-0.4 +nodist_orc_videoscale_SOURCES = orc/videoscale.c +orc_videotestsrc_CFLAGS = $(ORC_CFLAGS) +orc_videotestsrc_LDADD = $(ORC_LIBS) -lorc-test-0.4 +nodist_orc_videotestsrc_SOURCES = orc/videotestsrc.c + +orc/adder.c: $(top_srcdir)/gst/adder/gstadderorc.orc + $(MKDIR_P) orc/ + $(ORCC) --test -o $@ $< + +orc/audioconvert.c: $(top_srcdir)/gst/audioconvert/gstaudioconvertorc.orc + $(MKDIR_P) orc/ + $(ORCC) --test -o $@ $< + +orc/volume.c: $(top_srcdir)/gst/volume/gstvolumeorc.orc + $(MKDIR_P) orc/ + $(ORCC) --test -o $@ $< + +orc/videoscale.c: $(top_srcdir)/gst/videoscale/gstvideoscaleorc.orc + $(MKDIR_P) orc/ + $(ORCC) --test -o $@ $< + +orc/videotestsrc.c: $(top_srcdir)/gst/videotestsrc/gstvideotestsrcorc.orc + $(MKDIR_P) orc/ + $(ORCC) --test -o $@ $< + + +clean-local-orc: + rm -rf orc + +EXTRA_DIST = gst-plugins-base.supp diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/elements/.gitignore new file mode 100644 index 0000000..20bd96e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/.gitignore @@ -0,0 +1,29 @@ +.dirstamp +adder +alsa +appsink +appsrc +audioconvert +audiorate +audioresample +audiotestsrc +decodebin +decodebin2 +encodebin +gdpdepay +gdppay +gnomevfssink +libvisual +multifdsink +videorate +videotestsrc +volume +vorbisdec +typefindfunctions +textoverlay +ffmpegcolorspace +videoscale +vorbistag +playbin +playbin2 +subparse diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/adder.c b/gst-plugins-base-subtitles0.10/tests/check/elements/adder.c new file mode 100644 index 0000000..eadf31d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/adder.c @@ -0,0 +1,874 @@ +/* GStreamer + * + * unit test for adder + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#ifdef HAVE_VALGRIND +# include +#endif + +#include + +#include +#include + +static GMainLoop *main_loop; + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * bin) +{ + GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT, + GST_MESSAGE_SRC (message), message); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_main_loop_quit (main_loop); + break; + case GST_MESSAGE_WARNING:{ + GError *gerror; + gchar *debug; + + gst_message_parse_warning (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + break; + } + case GST_MESSAGE_ERROR:{ + GError *gerror; + gchar *debug; + + gst_message_parse_error (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + g_main_loop_quit (main_loop); + break; + } + default: + break; + } +} + + +static GstFormat format = GST_FORMAT_UNDEFINED; +static gint64 position = -1; + +static void +test_event_message_received (GstBus * bus, GstMessage * message, + GstPipeline * bin) +{ + GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT, + GST_MESSAGE_SRC (message), message); + + switch (message->type) { + case GST_MESSAGE_SEGMENT_DONE: + gst_message_parse_segment_done (message, &format, &position); + GST_INFO ("received segment_done : %" G_GINT64_FORMAT, position); + g_main_loop_quit (main_loop); + break; + default: + g_assert_not_reached (); + break; + } +} + + +GST_START_TEST (test_event) +{ + GstElement *bin, *src1, *src2, *adder, *sink; + GstBus *bus; + GstEvent *seek_event; + gboolean res; + GstPad *srcpad; + GstStreamConsistency *consist; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + /* FIXME, fakesrc with default setting will produce 0 sized + * buffers and incompatible caps for adder that will make + * adder EOS and error out */ + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "wave", 4, NULL); /* silence */ + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + g_object_set (src2, "wave", 4, NULL); /* silence */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, src2, adder, sink, NULL); + + res = gst_element_link (src1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (src2, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + + format = GST_FORMAT_UNDEFINED; + position = -1; + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::segment-done", + (GCallback) test_event_message_received, bin); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + GST_INFO ("starting test"); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + res = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (bin, seek_event); + fail_unless (res == TRUE, NULL); + + /* run pipeline */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + fail_unless (position == 2 * GST_SECOND, NULL); + + /* cleanup */ + g_main_loop_unref (main_loop); + gst_consistency_checker_free (consist); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + +static guint play_count = 0; +static GstEvent *play_seek_event = NULL; + +static void +test_play_twice_message_received (GstBus * bus, GstMessage * message, + GstPipeline * bin) +{ + gboolean res; + + GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT, + GST_MESSAGE_SRC (message), message); + + switch (message->type) { + case GST_MESSAGE_SEGMENT_DONE: + play_count++; + if (play_count == 1) { + res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_READY); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* prepare playing again */ + res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (GST_ELEMENT (bin), + gst_event_ref (play_seek_event)); + fail_unless (res == TRUE, NULL); + + res = gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + } else { + g_main_loop_quit (main_loop); + } + break; + default: + g_assert_not_reached (); + break; + } +} + + +GST_START_TEST (test_play_twice) +{ + GstElement *bin, *src1, *src2, *adder, *sink; + GstBus *bus; + gboolean res; + GstPad *srcpad; + GstStreamConsistency *consist; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "wave", 4, NULL); /* silence */ + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + g_object_set (src2, "wave", 4, NULL); /* silence */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, src2, adder, sink, NULL); + + res = gst_element_link (src1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (src2, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + + play_count = 0; + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::segment-done", + (GCallback) test_play_twice_message_received, bin); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + GST_INFO ("starting test"); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (bin, gst_event_ref (play_seek_event)); + fail_unless (res == TRUE, NULL); + + GST_INFO ("seeked"); + + /* run pipeline */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + fail_unless (play_count == 2, NULL); + + /* cleanup */ + g_main_loop_unref (main_loop); + gst_consistency_checker_free (consist); + gst_event_ref (play_seek_event); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + +GST_START_TEST (test_play_twice_then_add_and_play_again) +{ + GstElement *bin, *src1, *src2, *src3, *adder, *sink; + GstBus *bus; + gboolean res; + gint i; + GstPad *srcpad; + GstStreamConsistency *consist; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "wave", 4, NULL); /* silence */ + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + g_object_set (src2, "wave", 4, NULL); /* silence */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, src2, adder, sink, NULL); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + res = gst_element_link (src1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (src2, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_SEGMENT | GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::segment-done", + (GCallback) test_play_twice_message_received, bin); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + /* run it twice */ + for (i = 0; i < 2; i++) { + play_count = 0; + + GST_INFO ("starting test-loop %d", i); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (bin, gst_event_ref (play_seek_event)); + fail_unless (res == TRUE, NULL); + + GST_INFO ("seeked"); + + /* run pipeline */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_READY); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + fail_unless (play_count == 2, NULL); + + /* plug another source */ + if (i == 0) { + src3 = gst_element_factory_make ("audiotestsrc", "src3"); + g_object_set (src3, "wave", 4, NULL); /* silence */ + gst_bin_add (GST_BIN (bin), src3); + + res = gst_element_link (src3, adder); + fail_unless (res == TRUE, NULL); + } + + gst_consistency_checker_reset (consist); + } + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + g_main_loop_unref (main_loop); + gst_event_ref (play_seek_event); + gst_consistency_checker_free (consist); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + + +static void +test_live_seeking_eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * bin) +{ + GST_INFO ("bus message from \"%" GST_PTR_FORMAT "\": %" GST_PTR_FORMAT, + GST_MESSAGE_SRC (message), message); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_main_loop_quit (main_loop); + break; + default: + g_assert_not_reached (); + break; + } +} + + +/* test failing seeks on live-sources */ +GST_START_TEST (test_live_seeking) +{ + GstElement *bin, *src1, *src2, *ac1, *ac2, *adder, *sink; + GstBus *bus; + gboolean res; + GstPad *srcpad; + gint i; + GstStreamConsistency *consist; + + GST_INFO ("preparing test"); + main_loop = NULL; + play_seek_event = NULL; + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + /* normal audiosources behave differently than audiotestsrc */ +#if 0 + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "wave", 4, "is-live", TRUE, NULL); /* silence */ +#else + src1 = gst_element_factory_make ("alsasrc", "src1"); + if (!src1) { + GST_INFO ("no audiosrc, skipping"); + goto cleanup; + } + /* Test that the audio source can get to paused, else skip */ + res = gst_element_set_state (src1, GST_STATE_PAUSED); + (void) gst_element_set_state (src1, GST_STATE_NULL); + gst_object_unref (src1); + + if (res == GST_STATE_CHANGE_FAILURE) + goto cleanup; + src1 = gst_element_factory_make ("alsasrc", "src1"); + + /* live sources ignore seeks, force eos after 2 sec (4 buffers half second + * each) - don't use autoaudiosrc, as then we can't set anything here */ + g_object_set (src1, "num-buffers", 4, "blocksize", 44100, NULL); +#endif + ac1 = gst_element_factory_make ("audioconvert", "ac1"); + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + g_object_set (src2, "wave", 4, NULL); /* silence */ + ac2 = gst_element_factory_make ("audioconvert", "ac2"); + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, ac1, src2, ac2, adder, sink, NULL); + + res = gst_element_link (src1, ac1); + fail_unless (res == TRUE, NULL); + res = gst_element_link (ac1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (src2, ac2); + fail_unless (res == TRUE, NULL); + res = gst_element_link (ac2, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + play_seek_event = gst_event_new_seek (1.0, GST_FORMAT_TIME, + GST_SEEK_FLAG_FLUSH, + GST_SEEK_TYPE_SET, (GstClockTime) 0, + GST_SEEK_TYPE_SET, (GstClockTime) 2 * GST_SECOND); + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", + (GCallback) test_live_seeking_eos_message_received, bin); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + GST_INFO ("starting test"); + + /* run it twice */ + for (i = 0; i < 2; i++) { + + GST_INFO ("starting test-loop %d", i); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE); + + /* wait for completion */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + res = gst_element_send_event (bin, gst_event_ref (play_seek_event)); +#if 1 + fail_unless (res == TRUE, NULL); +#else + /* adder is picky, if a single seek fails it totaly fails */ + fail_unless (res == FALSE, NULL); +#endif + + GST_INFO ("seeked"); + + /* run pipeline */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + GST_INFO ("playing"); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + gst_consistency_checker_reset (consist); + } + + /* cleanup */ +cleanup: + GST_INFO ("cleaning up"); + if (main_loop) + g_main_loop_unref (main_loop); + if (play_seek_event) + gst_event_unref (play_seek_event); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + +/* check if adding pads work as expected */ +GST_START_TEST (test_add_pad) +{ + GstElement *bin, *src1, *src2, *adder, *sink; + GstBus *bus; + GstPad *srcpad; + GstStreamConsistency *consist; + gboolean res; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + src1 = gst_element_factory_make ("audiotestsrc", "src1"); + g_object_set (src1, "num-buffers", 4, NULL); + g_object_set (src1, "wave", 4, NULL); /* silence */ + src2 = gst_element_factory_make ("audiotestsrc", "src2"); + /* one buffer less, we connect with 1 buffer of delay */ + g_object_set (src2, "num-buffers", 3, NULL); + g_object_set (src2, "wave", 4, NULL); /* silence */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src1, adder, sink, NULL); + + res = gst_element_link (src1, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::segment-done", (GCallback) message_received, + bin); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + GST_INFO ("starting test"); + + /* prepare playing */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* add other element */ + gst_bin_add_many (GST_BIN (bin), src2, NULL); + + /* now link the second element */ + res = gst_element_link (src2, adder); + fail_unless (res == TRUE, NULL); + + /* set to PAUSED as well */ + res = gst_element_set_state (src2, GST_STATE_PAUSED); + + /* now play all */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + g_main_loop_unref (main_loop); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + +/* check if removing pads work as expected */ +GST_START_TEST (test_remove_pad) +{ + GstElement *bin, *src, *adder, *sink; + GstBus *bus; + GstPad *pad, *srcpad; + gboolean res; + GstStreamConsistency *consist; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + src = gst_element_factory_make ("audiotestsrc", "src"); + g_object_set (src, "num-buffers", 4, NULL); + g_object_set (src, "wave", 4, NULL); + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_bin_add_many (GST_BIN (bin), src, adder, sink, NULL); + + res = gst_element_link (src, adder); + fail_unless (res == TRUE, NULL); + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + /* create an unconnected sinkpad in adder */ + pad = gst_element_get_request_pad (adder, "sink%d"); + fail_if (pad == NULL, NULL); + + srcpad = gst_element_get_static_pad (adder, "src"); + consist = gst_consistency_checker_new (srcpad); + gst_object_unref (srcpad); + + main_loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (bus, "message::segment-done", (GCallback) message_received, + bin); + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + GST_INFO ("starting test"); + + /* prepare playing, this will not preroll as adder is waiting + * on the unconnected sinkpad. */ + res = gst_element_set_state (bin, GST_STATE_PAUSED); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* wait for completion for one second, will return ASYNC */ + res = gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, GST_SECOND); + fail_unless (res == GST_STATE_CHANGE_ASYNC, NULL); + + /* get rid of the pad now, adder should stop waiting on it and + * continue the preroll */ + gst_element_release_request_pad (adder, pad); + gst_object_unref (pad); + + /* wait for completion, should work now */ + res = + gst_element_get_state (GST_ELEMENT (bin), NULL, NULL, + GST_CLOCK_TIME_NONE); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* now play all */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + g_main_loop_run (main_loop); + + res = gst_element_set_state (bin, GST_STATE_NULL); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* cleanup */ + g_main_loop_unref (main_loop); + gst_object_unref (G_OBJECT (bus)); + gst_object_unref (G_OBJECT (bin)); +} + +GST_END_TEST; + + +static GstBuffer *handoff_buffer = NULL; +static void +handoff_buffer_cb (GstElement * fakesink, GstBuffer * buffer, GstPad * pad, + gpointer user_data) +{ + GST_DEBUG ("got buffer %p", buffer); + gst_buffer_replace (&handoff_buffer, buffer); +} + +/* check if clipping works as expected */ +GST_START_TEST (test_clip) +{ + GstElement *bin, *adder, *sink; + GstBus *bus; + GstPad *sinkpad; + gboolean res; + GstFlowReturn ret; + GstEvent *event; + GstBuffer *buffer; + GstCaps *caps; + + GST_INFO ("preparing test"); + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (bin); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + + g_signal_connect (bus, "message::error", (GCallback) message_received, bin); + g_signal_connect (bus, "message::warning", (GCallback) message_received, bin); + g_signal_connect (bus, "message::eos", (GCallback) message_received, bin); + + /* just an adder and a fakesink */ + adder = gst_element_factory_make ("adder", "adder"); + sink = gst_element_factory_make ("fakesink", "sink"); + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "handoff", (GCallback) handoff_buffer_cb, NULL); + gst_bin_add_many (GST_BIN (bin), adder, sink, NULL); + + res = gst_element_link (adder, sink); + fail_unless (res == TRUE, NULL); + + /* set to playing */ + res = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_unless (res != GST_STATE_CHANGE_FAILURE, NULL); + + /* create an unconnected sinkpad in adder, should also automatically activate + * the pad */ + sinkpad = gst_element_get_request_pad (adder, "sink%d"); + fail_if (sinkpad == NULL, NULL); + + /* send segment to adder */ + event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, + GST_SECOND, 2 * GST_SECOND, 0); + gst_pad_send_event (sinkpad, event); + + caps = gst_caps_new_simple ("audio/x-raw-int", + "rate", G_TYPE_INT, 44100, + "channels", G_TYPE_INT, 2, + "endianness", G_TYPE_INT, G_BYTE_ORDER, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + + /* should be clipped and ok */ + buffer = gst_buffer_new_and_alloc (44100); + GST_BUFFER_TIMESTAMP (buffer) = 0; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_set_caps (buffer, caps); + GST_DEBUG ("pushing buffer %p", buffer); + ret = gst_pad_chain (sinkpad, buffer); + fail_unless (ret == GST_FLOW_OK); + fail_unless (handoff_buffer == NULL); + + /* should be partially clipped */ + buffer = gst_buffer_new_and_alloc (44100); + GST_BUFFER_TIMESTAMP (buffer) = 900 * GST_MSECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_set_caps (buffer, caps); + GST_DEBUG ("pushing buffer %p", buffer); + ret = gst_pad_chain (sinkpad, buffer); + fail_unless (ret == GST_FLOW_OK); + fail_unless (handoff_buffer != NULL); + gst_buffer_replace (&handoff_buffer, NULL); + + /* should not be clipped */ + buffer = gst_buffer_new_and_alloc (44100); + GST_BUFFER_TIMESTAMP (buffer) = 1 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_set_caps (buffer, caps); + GST_DEBUG ("pushing buffer %p", buffer); + ret = gst_pad_chain (sinkpad, buffer); + fail_unless (ret == GST_FLOW_OK); + fail_unless (handoff_buffer != NULL); + gst_buffer_replace (&handoff_buffer, NULL); + + /* should be clipped and ok */ + buffer = gst_buffer_new_and_alloc (44100); + GST_BUFFER_TIMESTAMP (buffer) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buffer) = 250 * GST_MSECOND; + gst_buffer_set_caps (buffer, caps); + GST_DEBUG ("pushing buffer %p", buffer); + ret = gst_pad_chain (sinkpad, buffer); + fail_unless (ret == GST_FLOW_OK); + fail_unless (handoff_buffer == NULL); + + +} + +GST_END_TEST; + +static Suite * +adder_suite (void) +{ + Suite *s = suite_create ("adder"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_event); + tcase_add_test (tc_chain, test_play_twice); + tcase_add_test (tc_chain, test_play_twice_then_add_and_play_again); + tcase_add_test (tc_chain, test_live_seeking); + tcase_add_test (tc_chain, test_add_pad); + tcase_add_test (tc_chain, test_remove_pad); + tcase_add_test (tc_chain, test_clip); + + /* Use a longer timeout */ +#ifdef HAVE_VALGRIND + if (RUNNING_ON_VALGRIND) { + tcase_set_timeout (tc_chain, 5 * 60); + } else +#endif + { + /* this is shorter than the default 60 seconds?! (tpm) */ + /* tcase_set_timeout (tc_chain, 6); */ + } + + return s; +} + +GST_CHECK_MAIN (adder); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/alsa.c b/gst-plugins-base-subtitles0.10/tests/check/elements/alsa.c new file mode 100644 index 0000000..ddd95c7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/alsa.c @@ -0,0 +1,134 @@ +/* GStreamer + * + * unit test for alsa elements + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +/* just a simple test that runs device probing on + * an alsasrc, alsasink and alsamixer instance */ + +GST_START_TEST (test_device_property_probe) +{ + const gchar *elements[] = { "alsasink", "alsasrc", "alsamixer" }; + gint n; + + for (n = 0; n < G_N_ELEMENTS (elements); ++n) { + GstPropertyProbe *probe; + GValueArray *arr; + GstElement *element; + gint i; + + element = gst_element_factory_make (elements[n], elements[n]); + fail_unless (element != NULL); + + probe = GST_PROPERTY_PROBE (element); + fail_unless (probe != NULL); + + arr = gst_property_probe_probe_and_get_values_name (probe, "device"); + if (arr) { + for (i = 0; i < arr->n_values; ++i) { + const gchar *device; + GValue *val; + + val = g_value_array_get_nth (arr, i); + fail_unless (val != NULL); + fail_unless (G_VALUE_HOLDS_STRING (val)); + + device = g_value_get_string (val); + fail_unless (device != NULL); + GST_LOG_OBJECT (element, "device[%d] = %s", i, device); + } + g_value_array_free (arr); + } else { + GST_LOG_OBJECT (element, "no devices found"); + } + + gst_object_unref (element); + } +} + +GST_END_TEST; + +GST_START_TEST (test_alsa_mixer_track) +{ + GstStateChangeReturn state_ret; + GstElement *mixer; + GList *tracks, *l; + + mixer = gst_element_factory_make ("alsamixer", "alsamixer"); + fail_unless (mixer != NULL, "Failed to create 'alsamixer' element!"); + + state_ret = gst_element_set_state (mixer, GST_STATE_READY); + if (state_ret != GST_STATE_CHANGE_SUCCESS) { + gst_object_unref (mixer); + return; + } + + GST_LOG ("opened alsamixer"); + fail_unless (GST_IS_MIXER (mixer), "is not a GstMixer?!"); + + tracks = (GList *) gst_mixer_list_tracks (GST_MIXER (mixer)); + for (l = tracks; l != NULL; l = l->next) { + GstMixerTrack *track; + gchar *ulabel = NULL, *label = NULL; + + track = GST_MIXER_TRACK (l->data); + g_object_get (track, "label", &label, "untranslated-label", &ulabel, NULL); + fail_unless (label == NULL || g_utf8_validate (label, -1, NULL)); + if (ulabel != NULL) { + gchar *p; + + for (p = ulabel; p != NULL && *p != '\0'; ++p) { + fail_unless (g_ascii_isprint (*p), + "untranslated label '%s' not printable ASCII", ulabel); + } + } + GST_DEBUG ("%s: %s", GST_STR_NULL (ulabel), GST_STR_NULL (label)); + g_free (label); + g_free (ulabel); + } + + fail_unless_equals_int (gst_element_set_state (mixer, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (mixer); +} + +GST_END_TEST; + +static Suite * +alsa_suite (void) +{ + Suite *s = suite_create ("alsa"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_device_property_probe); + tcase_add_test (tc_chain, test_alsa_mixer_track); + + return s; +} + +GST_CHECK_MAIN (alsa) diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/appsink.c b/gst-plugins-base-subtitles0.10/tests/check/elements/appsink.c new file mode 100644 index 0000000..34982ef --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/appsink.c @@ -0,0 +1,423 @@ +/* GStreamer + * + * Copyright (C) 2009, Axis Communications AB, LUND, SWEDEN + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +gint global_testdata; + +static GstPad *mysrcpad; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gst-check") + ); + +static GstElement * +setup_appsink (void) +{ + GstElement *appsink; + + GST_DEBUG ("setup_appsink"); + appsink = gst_check_setup_element ("appsink"); + mysrcpad = gst_check_setup_src_pad (appsink, &srctemplate, NULL); + + return appsink; +} + +static void +cleanup_appsink (GstElement * appsink) +{ + GST_DEBUG ("cleanup_appsink"); + + gst_check_teardown_src_pad (appsink); + gst_check_teardown_element (appsink); +} + +/* This function does an operation to it's indata argument and returns it. + * The exact operation performed doesn't matter. Currently it multiplies with + * two, but it could do anything. The idea is to use the function to verify + * that the code calling it gets run. */ +static gint +operate_on_data (gint indata) +{ + return indata * 2; +} + +static GstFlowReturn +callback_function (GstAppSink * appsink, gpointer callback_data) +{ + global_testdata = operate_on_data (*((gint *) callback_data)); + + return GST_FLOW_OK; +} + +static void +notify_function (gpointer callback_data) +{ + global_testdata = operate_on_data (*((gint *) callback_data)); +} + +GST_START_TEST (test_non_clients) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + + sink = setup_appsink (); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + gst_caps_unref (caps); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + GST_DEBUG ("cleaning up appsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_appsink (sink); +} + +GST_END_TEST; + +/* Verifies that the handoff callback gets run one time when passing a buffer */ +GST_START_TEST (test_handoff_callback) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + gint testdata; + GstAppSinkCallbacks callbacks = { NULL }; + + sink = setup_appsink (); + + global_testdata = 0; + testdata = 5; /* Arbitrary value */ + + callbacks.new_buffer = callback_function; + + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + gst_caps_unref (caps); + /* Pushing a buffer should run our callback */ + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + testdata = operate_on_data (testdata); + + /* If both test_data & global_testdata have been operated on, we're happy. */ + fail_unless (testdata == global_testdata); + + GST_DEBUG ("cleaning up appsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_appsink (sink); +} + +GST_END_TEST; + +/* Verifies that the notify function gets executed when the sink is destroyed */ +GST_START_TEST (test_notify0) +{ + GstElement *sink; + gint testdata; + GstAppSinkCallbacks callbacks = { NULL }; + + sink = gst_element_factory_make ("appsink", NULL); + + global_testdata = 0; + testdata = 17; /* Arbitrary value */ + + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, + &testdata, (*notify_function)); + + GST_DEBUG ("cleaning up appsink"); + /* Destroying sink should call our notify_function */ + gst_object_unref (sink); + + testdata = operate_on_data (testdata); + + /* If both test_data & global_testdata have been operated on, we're happy. */ + fail_unless (testdata == global_testdata); +} + +GST_END_TEST; + + +/* Verifies that the notify function gets executed when + * gst_app_sink_set_callbacks () gets called */ +GST_START_TEST (test_notify1) +{ + GstElement *sink; + gint testdata; + GstAppSinkCallbacks callbacks = { NULL }; + + sink = gst_element_factory_make ("appsink", NULL); + + global_testdata = 0; + testdata = 42; /* Arbitrary value */ + + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, + &testdata, (*notify_function)); + /* Setting new callbacks should trigger the destroy of the old data */ + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &testdata, NULL); + + testdata = operate_on_data (testdata); + + /* If both test_data & global_testdata have been operated on, we're happy. */ + fail_unless (testdata == global_testdata); + + GST_DEBUG ("cleaning up appsink"); + gst_object_unref (sink); +} + +GST_END_TEST; + +static GstBufferList *mylist; +static GstCaps *mycaps; + +static GstBufferList * +create_buffer_list (void) +{ + GstBufferListIterator *it; + GstBuffer *buffer; + + mylist = gst_buffer_list_new (); + fail_if (mylist == NULL); + + mycaps = gst_caps_from_string ("application/x-gst-check"); + fail_if (mycaps == NULL); + + it = gst_buffer_list_iterate (mylist); + fail_if (it == NULL); + + gst_buffer_list_iterator_add_group (it); + + buffer = gst_buffer_new_and_alloc (sizeof (gint)); + *(gint *) GST_BUFFER_DATA (buffer) = 1; + gst_buffer_set_caps (buffer, mycaps); + gst_buffer_list_iterator_add (it, buffer); + + gst_buffer_list_iterator_add_group (it); + + buffer = gst_buffer_new_and_alloc (sizeof (gint)); + *(gint *) GST_BUFFER_DATA (buffer) = 2; + gst_buffer_set_caps (buffer, mycaps); + gst_buffer_list_iterator_add (it, buffer); + + buffer = gst_buffer_new_and_alloc (sizeof (gint)); + *(gint *) GST_BUFFER_DATA (buffer) = 4; + gst_buffer_set_caps (buffer, mycaps); + gst_buffer_list_iterator_add (it, buffer); + + gst_buffer_list_iterator_free (it); + + return mylist; +} + +static void +check_buffer_list (GstBufferList * list) +{ + GstBufferListIterator *it; + GstBuffer *buf; + GstCaps *caps; + + fail_unless (list == mylist); + fail_unless (gst_buffer_list_n_groups (list) == 2); + + it = gst_buffer_list_iterate (list); + fail_if (it == NULL); + + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_n_buffers (it) == 1); + buf = gst_buffer_list_iterator_next (it); + fail_if (buf == NULL); + fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 1); + caps = gst_buffer_get_caps (buf); + fail_unless (caps == mycaps); + fail_unless (gst_caps_is_equal (caps, mycaps)); + gst_caps_unref (caps); + + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_n_buffers (it) == 2); + buf = gst_buffer_list_iterator_next (it); + fail_if (buf == NULL); + fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 2); + caps = gst_buffer_get_caps (buf); + fail_unless (caps == mycaps); + gst_caps_unref (caps); + + buf = gst_buffer_list_iterator_next (it); + fail_if (buf == NULL); + fail_unless (*(gint *) GST_BUFFER_DATA (buf) == 4); + caps = gst_buffer_get_caps (buf); + fail_unless (caps == mycaps); + gst_caps_unref (caps); + + gst_buffer_list_iterator_free (it); +} + +static GstFlowReturn +callback_function_buffer_list (GstAppSink * appsink, gpointer callback_data) +{ + GstBufferList *list; + + list = gst_app_sink_pull_buffer_list (appsink); + fail_unless (GST_IS_BUFFER_LIST (list)); + + check_buffer_list (list); + + gst_buffer_list_unref (list); + + return GST_FLOW_OK; +} + +GST_START_TEST (test_buffer_list) +{ + GstElement *sink; + GstBufferList *list; + GstAppSinkCallbacks callbacks = { NULL }; + + sink = setup_appsink (); + + callbacks.new_buffer_list = callback_function_buffer_list; + + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, NULL, NULL); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + list = create_buffer_list (); + fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK); + + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_appsink (sink); +} + +GST_END_TEST; + +static GstFlowReturn +callback_function_buffer (GstAppSink * appsink, gpointer p_counter) +{ + GstBuffer *buf; + gint *p_int_counter = p_counter; + + buf = gst_app_sink_pull_buffer (appsink); + fail_unless (GST_IS_BUFFER (buf)); + + /* buffer list has 3 buffers in two groups */ + switch (*p_int_counter) { + case 0: + fail_unless_equals_int (GST_BUFFER_SIZE (buf), sizeof (gint)); + fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 1); + break; + case 1: + fail_unless_equals_int (GST_BUFFER_SIZE (buf), 2 * sizeof (gint)); + fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[0]), 2); + fail_unless_equals_int ((((gint *) GST_BUFFER_DATA (buf))[1]), 4); + break; + default: + g_warn_if_reached (); + break; + } + + gst_buffer_unref (buf); + + *p_int_counter += 1; + + return GST_FLOW_OK; +} + +GST_START_TEST (test_buffer_list_fallback) +{ + GstElement *sink; + GstBufferList *list; + GstAppSinkCallbacks callbacks = { NULL }; + gint counter = 0; + + sink = setup_appsink (); + + callbacks.new_buffer = callback_function_buffer; + + gst_app_sink_set_callbacks (GST_APP_SINK (sink), &callbacks, &counter, NULL); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + list = create_buffer_list (); + fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK); + + fail_unless_equals_int (counter, 2); + + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_appsink (sink); +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_list_fallback_signal) +{ + GstElement *sink; + GstBufferList *list; + gint counter = 0; + + sink = setup_appsink (); + + /* C calling convention to the rescue.. */ + g_signal_connect (sink, "new-buffer", G_CALLBACK (callback_function_buffer), + &counter); + + g_object_set (sink, "emit-signals", TRUE, NULL); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + list = create_buffer_list (); + fail_unless (gst_pad_push_list (mysrcpad, list) == GST_FLOW_OK); + + fail_unless_equals_int (counter, 2); + + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_appsink (sink); +} + +GST_END_TEST; + +static Suite * +appsink_suite (void) +{ + Suite *s = suite_create ("appsink"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_non_clients); + tcase_add_test (tc_chain, test_handoff_callback); + tcase_add_test (tc_chain, test_notify0); + tcase_add_test (tc_chain, test_notify1); + tcase_add_test (tc_chain, test_buffer_list); + tcase_add_test (tc_chain, test_buffer_list_fallback); + tcase_add_test (tc_chain, test_buffer_list_fallback_signal); + + return s; +} + +GST_CHECK_MAIN (appsink); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/appsrc.c b/gst-plugins-base-subtitles0.10/tests/check/elements/appsrc.c new file mode 100644 index 0000000..b888f48 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/appsrc.c @@ -0,0 +1,188 @@ +/* GStreamer + * + * Copyright (C) 2010, Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#define SAMPLE_CAPS "application/x-gst-check-test" + +static GstPad *mysinkpad; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstElement * +setup_appsrc (void) +{ + GstElement *appsrc; + + GST_DEBUG ("setup_appsrc"); + appsrc = gst_check_setup_element ("appsrc"); + mysinkpad = gst_check_setup_sink_pad (appsrc, &sinktemplate, NULL); + + gst_pad_set_active (mysinkpad, TRUE); + + return appsrc; +} + +static void +cleanup_appsrc (GstElement * appsrc) +{ + GST_DEBUG ("cleanup_appsrc"); + + gst_check_teardown_sink_pad (appsrc); + gst_check_teardown_element (appsrc); +} + + +/* + * Pushes 4 buffers into appsrc and checks the caps on them on the output. + * + * Appsrc is configured with caps=null, so the buffers should have the + * same caps that they were pushed with. + * + * The 4 buffers have NULL, SAMPLE_CAPS, NULL, SAMPLE_CAPS caps, + * respectively. + */ +GST_START_TEST (test_appsrc_null_caps) +{ + GstElement *src; + GstBuffer *buffer; + GList *iter; + GstCaps *caps; + + src = setup_appsrc (); + + g_object_set (src, "caps", NULL, NULL); + caps = gst_caps_from_string (SAMPLE_CAPS); + + ASSERT_SET_STATE (src, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + fail_unless (gst_app_src_end_of_stream (GST_APP_SRC (src)) == GST_FLOW_OK); + + /* Give some time to the appsrc loop to push the buffers */ + g_usleep (G_USEC_PER_SEC * 3); + + /* Check the output caps */ + fail_unless (g_list_length (buffers) == 2); + iter = buffers; + buffer = (GstBuffer *) iter->data; + fail_unless (GST_BUFFER_CAPS (buffer) == NULL); + + iter = g_list_next (iter); + buffer = (GstBuffer *) iter->data; + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buffer), caps)); + + ASSERT_SET_STATE (src, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + gst_caps_unref (caps); + cleanup_appsrc (src); +} + +GST_END_TEST; + + +/* + * Pushes 4 buffers into appsrc and checks the caps on them on the output. + * + * Appsrc is configured with caps=SAMPLE_CAPS, so the buffers should have the + * same caps that they were pushed with. + * + * The 4 buffers have NULL, SAMPLE_CAPS, NULL, SAMPLE_CAPS caps, + * respectively. + */ +GST_START_TEST (test_appsrc_non_null_caps) +{ + GstElement *src; + GstBuffer *buffer; + GList *iter; + GstCaps *caps; + + src = setup_appsrc (); + + caps = gst_caps_from_string (SAMPLE_CAPS); + g_object_set (src, "caps", caps, NULL); + + ASSERT_SET_STATE (src, GST_STATE_PLAYING, GST_STATE_CHANGE_SUCCESS); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + fail_unless (gst_app_src_push_buffer (GST_APP_SRC (src), + buffer) == GST_FLOW_OK); + + fail_unless (gst_app_src_end_of_stream (GST_APP_SRC (src)) == GST_FLOW_OK); + + /* Give some time to the appsrc loop to push the buffers */ + g_usleep (G_USEC_PER_SEC * 3); + + /* Check the output caps */ + fail_unless (g_list_length (buffers) == 4); + for (iter = buffers; iter; iter = g_list_next (iter)) { + GstBuffer *buf = (GstBuffer *) iter->data; + + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (buf), caps)); + } + + ASSERT_SET_STATE (src, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + gst_caps_unref (caps); + cleanup_appsrc (src); +} + +GST_END_TEST; + + +static Suite * +appsrc_suite (void) +{ + Suite *s = suite_create ("appsrc"); + TCase *tc_chain = tcase_create ("general"); + + tcase_add_test (tc_chain, test_appsrc_null_caps); + tcase_add_test (tc_chain, test_appsrc_non_null_caps); + + suite_add_tcase (s, tc_chain); + + return s; +} + +GST_CHECK_MAIN (appsrc); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/audioconvert.c b/gst-plugins-base-subtitles0.10/tests/check/elements/audioconvert.c new file mode 100644 index 0000000..b5e292d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/audioconvert.c @@ -0,0 +1,1742 @@ +/* GStreamer + * + * unit test for audioconvert + * + * Copyright (C) <2005> Thomas Vander Stichele + * Copyright (C) <2007> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +/* 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 CONVERT_CAPS_TEMPLATE_STRING \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) { 32, 64 };" \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 32, " \ + "depth = (int) [ 1, 32 ], " \ + "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 24, " \ + "depth = (int) [ 1, 24 ], " \ + "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 16, " \ + "depth = (int) [ 1, 16 ], " \ + "signed = (boolean) { true, false }; " \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, MAX ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) 8, " \ + "depth = (int) [ 1, 8 ], " \ + "signed = (boolean) { true, false } " + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CONVERT_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CONVERT_CAPS_TEMPLATE_STRING) + ); + +/* takes over reference for outcaps */ +static GstElement * +setup_audioconvert (GstCaps * outcaps) +{ + GstElement *audioconvert; + + GST_DEBUG ("setup_audioconvert with caps %" GST_PTR_FORMAT, outcaps); + audioconvert = gst_check_setup_element ("audioconvert"); + g_object_set (G_OBJECT (audioconvert), "dithering", 0, NULL); + g_object_set (G_OBJECT (audioconvert), "noise-shaping", 0, NULL); + mysrcpad = gst_check_setup_src_pad (audioconvert, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (audioconvert, &sinktemplate, NULL); + /* this installs a getcaps func that will always return the caps we set + * later */ + gst_pad_use_fixed_caps (mysinkpad); + gst_pad_set_caps (mysinkpad, outcaps); + gst_caps_unref (outcaps); + outcaps = gst_pad_get_negotiated_caps (mysinkpad); + fail_unless (gst_caps_is_fixed (outcaps)); + gst_caps_unref (outcaps); + + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return audioconvert; +} + +static void +cleanup_audioconvert (GstElement * audioconvert) +{ + GST_DEBUG ("cleanup_audioconvert"); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (audioconvert); + gst_check_teardown_sink_pad (audioconvert); + gst_check_teardown_element (audioconvert); +} + +/* returns a newly allocated caps */ +static GstCaps * +get_int_caps (guint channels, const gchar * endianness, guint width, + guint depth, gboolean signedness) +{ + GstCaps *caps; + gchar *string; + + string = g_strdup_printf ("audio/x-raw-int, " + "rate = (int) 44100, " + "channels = (int) %d, " + "endianness = (int) %s, " + "width = (int) %d, " + "depth = (int) %d, " + "signed = (boolean) %s ", + channels, endianness, width, depth, signedness ? "true" : "false"); + GST_DEBUG ("creating caps from %s", string); + caps = gst_caps_from_string (string); + g_free (string); + fail_unless (caps != NULL); + GST_DEBUG ("returning caps %p", caps); + return caps; +} + +/* returns a newly allocated caps */ +static GstCaps * +get_float_caps (guint channels, const gchar * endianness, guint width) +{ + GstCaps *caps; + gchar *string; + + string = g_strdup_printf ("audio/x-raw-float, " + "rate = (int) 44100, " + "channels = (int) %d, " + "endianness = (int) %s, " + "width = (int) %d ", channels, endianness, width); + GST_DEBUG ("creating caps from %s", string); + caps = gst_caps_from_string (string); + g_free (string); + fail_unless (caps != NULL); + GST_DEBUG ("returning caps %p", caps); + return caps; +} + +/* Copied from vorbis; the particular values used don't matter */ +static GstAudioChannelPosition channelpositions[][6] = { + { /* Mono */ + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}, + { /* Stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Stereo + Centre */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT}, + { /* Quadraphonic */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Stereo + Centre + rear stereo */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { /* Full 5.1 Surround */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, + } +}; + +/* these are a bunch of random positions, they are mostly just + * different from the ones above, don't use elsewhere */ +static GstAudioChannelPosition mixed_up_positions[][6] = { + { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO}, + { + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, + { + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT}, + { + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + }, + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + }, + { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_LFE, + } +}; + +/* we get this when recording from a soundcard with lots of input channels */ +static GstAudioChannelPosition undefined_positions[][15] = { + { + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE}, + { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE} +}; + +static void +set_channel_positions (GstCaps * caps, int channels, + GstAudioChannelPosition * channelpositions) +{ + GValue chanpos = { 0 }; + GValue pos = { 0 }; + GstStructure *structure = gst_caps_get_structure (caps, 0); + int c; + + g_value_init (&chanpos, GST_TYPE_ARRAY); + g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); + + for (c = 0; c < channels; c++) { + g_value_set_enum (&pos, channelpositions[c]); + gst_value_array_append_value (&chanpos, &pos); + } + g_value_unset (&pos); + + gst_structure_set_value (structure, "channel-positions", &chanpos); + g_value_unset (&chanpos); +} + +/* For channels > 2, caps have to have channel positions. This adds some simple + * ones. Only implemented for channels between 1 and 6. + */ +static GstCaps * +get_float_mc_caps (guint channels, const gchar * endianness, guint width, + gboolean mixed_up_layout) +{ + GstCaps *caps = get_float_caps (channels, endianness, width); + + if (channels <= 6) { + if (mixed_up_layout) + set_channel_positions (caps, channels, mixed_up_positions[channels - 1]); + else + set_channel_positions (caps, channels, channelpositions[channels - 1]); + } + + return caps; +} + +static GstCaps * +get_int_mc_caps (guint channels, const gchar * endianness, guint width, + guint depth, gboolean signedness, gboolean mixed_up_layout) +{ + GstCaps *caps = get_int_caps (channels, endianness, width, depth, signedness); + + if (channels <= 6) { + if (mixed_up_layout) + set_channel_positions (caps, channels, mixed_up_positions[channels - 1]); + else + set_channel_positions (caps, channels, channelpositions[channels - 1]); + } + + return caps; +} + +/* eats the refs to the caps */ +static void +verify_convert (const gchar * which, void *in, int inlength, + GstCaps * incaps, void *out, int outlength, GstCaps * outcaps, + GstFlowReturn expected_flow) +{ + GstBuffer *inbuffer, *outbuffer; + GstElement *audioconvert; + + GST_DEBUG ("verifying conversion %s", which); + GST_DEBUG ("incaps: %" GST_PTR_FORMAT, incaps); + GST_DEBUG ("outcaps: %" GST_PTR_FORMAT, outcaps); + ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1); + ASSERT_CAPS_REFCOUNT (outcaps, "outcaps", 1); + audioconvert = setup_audioconvert (outcaps); + ASSERT_CAPS_REFCOUNT (outcaps, "outcaps", 1); + + fail_unless (gst_element_set_state (audioconvert, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("Creating buffer of %d bytes", inlength); + inbuffer = gst_buffer_new_and_alloc (inlength); + memcpy (GST_BUFFER_DATA (inbuffer), in, inlength); + gst_buffer_set_caps (inbuffer, incaps); + ASSERT_CAPS_REFCOUNT (incaps, "incaps", 2); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + GST_DEBUG ("push it"); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), expected_flow); + GST_DEBUG ("pushed it"); + + if (expected_flow != GST_FLOW_OK) + goto done; + + /* ... and puts a new buffer on the global list */ + fail_unless (g_list_length (buffers) == 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), outlength); + + if (memcmp (GST_BUFFER_DATA (outbuffer), out, outlength) != 0) { + g_print ("\nInput data:\n"); + gst_util_dump_mem (in, inlength); + g_print ("\nConverted data:\n"); + gst_util_dump_mem (GST_BUFFER_DATA (outbuffer), outlength); + g_print ("\nExpected data:\n"); + gst_util_dump_mem (out, outlength); + } + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, outlength) == 0, + "failed converting %s", which); + + /* make sure that the channel positions are not lost */ + { + GstStructure *in_s, *out_s; + gint out_chans; + + in_s = gst_caps_get_structure (incaps, 0); + out_s = gst_caps_get_structure (GST_BUFFER_CAPS (outbuffer), 0); + fail_unless (gst_structure_get_int (out_s, "channels", &out_chans)); + + /* positions for 1 and 2 channels are implicit if not provided */ + if (out_chans > 2 && gst_structure_has_field (in_s, "channel-positions")) { + if (!gst_structure_has_field (out_s, "channel-positions")) { + g_error ("Channel layout got lost somewhere:\n\nIns : %s\nOuts: %s\n", + gst_structure_to_string (in_s), gst_structure_to_string (out_s)); + } + } + } + + buffers = g_list_remove (buffers, outbuffer); + gst_buffer_unref (outbuffer); + +done: + fail_unless (gst_element_set_state (audioconvert, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + /* cleanup */ + GST_DEBUG ("cleanup audioconvert"); + cleanup_audioconvert (audioconvert); + GST_DEBUG ("cleanup, unref incaps"); + ASSERT_CAPS_REFCOUNT (incaps, "incaps", 1); + gst_caps_unref (incaps); +} + + +#define RUN_CONVERSION(which, inarray, in_get_caps, outarray, out_get_caps) \ + verify_convert (which, inarray, sizeof (inarray), \ + in_get_caps, outarray, sizeof (outarray), out_get_caps, GST_FLOW_OK) + +#define RUN_CONVERSION_TO_FAIL(which, inarray, in_caps, outarray, out_caps) \ + verify_convert (which, inarray, sizeof (inarray), \ + in_caps, outarray, sizeof (outarray), out_caps, GST_FLOW_NOT_NEGOTIATED) + + +GST_START_TEST (test_int16) +{ + /* stereo to mono */ + { + gint16 in[] = { 16384, -256, 1024, 1024 }; + gint16 out[] = { 8064, 1024 }; + + RUN_CONVERSION ("int16 stereo to mono", + in, get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + } + /* mono to stereo */ + { + gint16 in[] = { 512, 1024 }; + gint16 out[] = { 512, 512, 1024, 1024 }; + + RUN_CONVERSION ("int16 mono to stereo", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE)); + } + /* signed -> unsigned */ + { + gint16 in[] = { 0, -32767, 32767, -32768 }; + guint16 out[] = { 32768, 1, 65535, 0 }; + + RUN_CONVERSION ("int16 signed to unsigned", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE)); + RUN_CONVERSION ("int16 unsigned to signed", + out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE), + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_float32) +{ + /* stereo to mono */ + { + gfloat in[] = { 0.6, -0.0078125, 0.03125, 0.03125 }; + gfloat out[] = { 0.29609375, 0.03125 }; + + RUN_CONVERSION ("float32 stereo to mono", + in, get_float_caps (2, "BYTE_ORDER", 32), + out, get_float_caps (1, "BYTE_ORDER", 32)); + } + /* mono to stereo */ + { + gfloat in[] = { 0.015625, 0.03125 }; + gfloat out[] = { 0.015625, 0.015625, 0.03125, 0.03125 }; + + RUN_CONVERSION ("float32 mono to stereo", + in, get_float_caps (1, "BYTE_ORDER", 32), + out, get_float_caps (2, "BYTE_ORDER", 32)); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_int_conversion) +{ + /* 8 <-> 16 signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gint8 in[] = { 0, 1, 2, 127, -127 }; + gint16 out[] = { 0, 256, 512, 32512, -32512 }; + + RUN_CONVERSION ("int 8bit to 16bit signed", + in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE) + ); + RUN_CONVERSION ("int 16bit signed to 8bit", + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE) + ); + } + /* 16 -> 8 signed */ + { + gint16 in[] = { 0, 127, 128, 256, 256 + 127, 256 + 128 }; + gint8 out[] = { 0, 0, 1, 1, 1, 2 }; + + RUN_CONVERSION ("16 bit to 8 signed", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE) + ); + } + /* 8 unsigned <-> 16 signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + guint8 in[] = { 128, 129, 130, 255, 1 }; + gint16 out[] = { 0, 256, 512, 32512, -32512 }; + GstCaps *incaps, *outcaps; + + /* exploded for easier valgrinding */ + incaps = get_int_caps (1, "BYTE_ORDER", 8, 8, FALSE); + outcaps = get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE); + GST_DEBUG ("incaps: %" GST_PTR_FORMAT, incaps); + GST_DEBUG ("outcaps: %" GST_PTR_FORMAT, outcaps); + RUN_CONVERSION ("8 unsigned to 16 signed", in, incaps, out, outcaps); + RUN_CONVERSION ("16 signed to 8 unsigned", out, get_int_caps (1, + "BYTE_ORDER", 16, 16, TRUE), in, get_int_caps (1, "BYTE_ORDER", 8, + 8, FALSE) + ); + } + /* 8 <-> 24 signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gint8 in[] = { 0, 1, 127 }; + guint8 out[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7f }; + /* out has the bytes in little-endian, so that's how they should be + * interpreted during conversion */ + + RUN_CONVERSION ("8 to 24 signed", in, get_int_caps (1, "BYTE_ORDER", 8, 8, + TRUE), out, get_int_caps (1, "LITTLE_ENDIAN", 24, 24, TRUE) + ); + RUN_CONVERSION ("24 signed to 8", out, get_int_caps (1, "LITTLE_ENDIAN", 24, + 24, TRUE), in, get_int_caps (1, "BYTE_ORDER", 8, 8, TRUE) + ); + } + + /* 16 bit signed <-> unsigned */ + { + gint16 in[] = { 0, 128, -128 }; + guint16 out[] = { 32768, 32896, 32640 }; + RUN_CONVERSION ("16 signed to 16 unsigned", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE) + ); + RUN_CONVERSION ("16 unsigned to 16 signed", + out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE), + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE) + ); + } + + /* 16 bit signed <-> 8 in 16 bit signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gint16 in[] = { 0, 64 << 8, -64 << 8 }; + gint16 out[] = { 0, 64, -64 }; + RUN_CONVERSION ("16 signed to 8 in 16 signed", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 8, TRUE) + ); + RUN_CONVERSION ("8 in 16 signed to 16 signed", + out, get_int_caps (1, "BYTE_ORDER", 16, 8, TRUE), + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE) + ); + } + + /* 16 bit unsigned <-> 8 in 16 bit unsigned */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + guint16 in[] = { 1 << 15, (1 << 15) - (64 << 8), (1 << 15) + (64 << 8) }; + guint16 out[] = { 1 << 7, (1 << 7) - 64, (1 << 7) + 64 }; + RUN_CONVERSION ("16 unsigned to 8 in 16 unsigned", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE), + out, get_int_caps (1, "BYTE_ORDER", 16, 8, FALSE) + ); + RUN_CONVERSION ("8 in 16 unsigned to 16 unsigned", + out, get_int_caps (1, "BYTE_ORDER", 16, 8, FALSE), + in, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE) + ); + } + + /* 32 bit signed -> 16 bit signed for rounding check */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gint32 in[] = { 0, G_MININT32, G_MAXINT32, + (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15), + (32 << 16) + (2 << 15), (32 << 16) - (2 << 15), + (-32 << 16) + (1 << 15), (-32 << 16) - (1 << 15), + (-32 << 16) + (2 << 15), (-32 << 16) - (2 << 15), + (-32 << 16) + }; + gint16 out[] = { 0, G_MININT16, G_MAXINT16, + 32, 33, 32, + 33, 31, + -31, -32, + -31, -33, + -32 + }; + RUN_CONVERSION ("32 signed to 16 signed for rounding", + in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE) + ); + } + + /* 32 bit signed -> 16 bit unsigned for rounding check */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gint32 in[] = { 0, G_MININT32, G_MAXINT32, + (32 << 16), (32 << 16) + (1 << 15), (32 << 16) - (1 << 15), + (32 << 16) + (2 << 15), (32 << 16) - (2 << 15), + (-32 << 16) + (1 << 15), (-32 << 16) - (1 << 15), + (-32 << 16) + (2 << 15), (-32 << 16) - (2 << 15), + (-32 << 16) + }; + guint16 out[] = { (1 << 15), 0, G_MAXUINT16, + (1 << 15) + 32, (1 << 15) + 33, (1 << 15) + 32, + (1 << 15) + 33, (1 << 15) + 31, + (1 << 15) - 31, (1 << 15) - 32, + (1 << 15) - 31, (1 << 15) - 33, + (1 << 15) - 32 + }; + RUN_CONVERSION ("32 signed to 16 unsigned for rounding", + in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, FALSE) + ); + } +} + +GST_END_TEST; + +GST_START_TEST (test_float_conversion) +{ + /* 32 float <-> 16 signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gfloat in_le[] = + { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0), + GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5), GFLOAT_TO_LE (1.1), + GFLOAT_TO_LE (-1.1) + }; + gfloat in_be[] = + { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0), + GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5), GFLOAT_TO_BE (1.1), + GFLOAT_TO_BE (-1.1) + }; + gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 }; + + /* only one direction conversion, the other direction does + * not produce exactly the same as the input due to floating + * point rounding errors etc. */ + RUN_CONVERSION ("32 float le to 16 signed", + in_le, get_float_caps (1, "LITTLE_ENDIAN", 32), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + RUN_CONVERSION ("32 float be to 16 signed", + in_be, get_float_caps (1, "BIG_ENDIAN", 32), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + } + + { + gint16 in[] = { 0, -32768, 16384, -16384 }; + gfloat out[] = { 0.0, -1.0, 0.5, -0.5 }; + + RUN_CONVERSION ("16 signed to 32 float", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_float_caps (1, "BYTE_ORDER", 32)); + } + + /* 64 float <-> 16 signed */ + /* NOTE: if audioconvert was doing dithering we'd have a problem */ + { + gdouble in_le[] = + { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0), + GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5), GDOUBLE_TO_LE (1.1), + GDOUBLE_TO_LE (-1.1) + }; + gdouble in_be[] = + { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0), + GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5), GDOUBLE_TO_BE (1.1), + GDOUBLE_TO_BE (-1.1) + }; + gint16 out[] = { 0, 32767, -32768, 16384, -16384, 32767, -32768 }; + + /* only one direction conversion, the other direction does + * not produce exactly the same as the input due to floating + * point rounding errors etc. */ + RUN_CONVERSION ("64 float LE to 16 signed", + in_le, get_float_caps (1, "LITTLE_ENDIAN", 64), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + RUN_CONVERSION ("64 float BE to 16 signed", + in_be, get_float_caps (1, "BIG_ENDIAN", 64), + out, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE)); + } + { + gint16 in[] = { 0, -32768, 16384, -16384 }; + gdouble out[] = { 0.0, + (gdouble) (-32768L << 16) / 2147483647.0, /* ~ -1.0 */ + (gdouble) (16384L << 16) / 2147483647.0, /* ~ 0.5 */ + (gdouble) (-16384L << 16) / 2147483647.0, /* ~ -0.5 */ + }; + + RUN_CONVERSION ("16 signed to 64 float", + in, get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE), + out, get_float_caps (1, "BYTE_ORDER", 64)); + } + { + gint32 in[] = { 0, (-1L << 31), (1L << 30), (-1L << 30) }; + gdouble out[] = { 0.0, + (gdouble) (-1L << 31) / 2147483647.0, /* ~ -1.0 */ + (gdouble) (1L << 30) / 2147483647.0, /* ~ 0.5 */ + (gdouble) (-1L << 30) / 2147483647.0, /* ~ -0.5 */ + }; + + RUN_CONVERSION ("32 signed to 64 float", + in, get_int_caps (1, "BYTE_ORDER", 32, 32, TRUE), + out, get_float_caps (1, "BYTE_ORDER", 64)); + } + + /* 64-bit float <-> 32-bit float */ + { + gdouble in[] = { 0.0, 1.0, -1.0, 0.5, -0.5 }; + gfloat out[] = { 0.0, 1.0, -1.0, 0.5, -0.5 }; + + RUN_CONVERSION ("64 float to 32 float", + in, get_float_caps (1, "BYTE_ORDER", 64), + out, get_float_caps (1, "BYTE_ORDER", 32)); + + RUN_CONVERSION ("32 float to 64 float", + out, get_float_caps (1, "BYTE_ORDER", 32), + in, get_float_caps (1, "BYTE_ORDER", 64)); + } + + /* 32-bit float little endian <-> big endian */ + { + gfloat le[] = { GFLOAT_TO_LE (0.0), GFLOAT_TO_LE (1.0), GFLOAT_TO_LE (-1.0), + GFLOAT_TO_LE (0.5), GFLOAT_TO_LE (-0.5) + }; + gfloat be[] = { GFLOAT_TO_BE (0.0), GFLOAT_TO_BE (1.0), GFLOAT_TO_BE (-1.0), + GFLOAT_TO_BE (0.5), GFLOAT_TO_BE (-0.5) + }; + + RUN_CONVERSION ("32 float LE to BE", + le, get_float_caps (1, "LITTLE_ENDIAN", 32), + be, get_float_caps (1, "BIG_ENDIAN", 32)); + + RUN_CONVERSION ("32 float BE to LE", + be, get_float_caps (1, "BIG_ENDIAN", 32), + le, get_float_caps (1, "LITTLE_ENDIAN", 32)); + } + + /* 64-bit float little endian <-> big endian */ + { + gdouble le[] = + { GDOUBLE_TO_LE (0.0), GDOUBLE_TO_LE (1.0), GDOUBLE_TO_LE (-1.0), + GDOUBLE_TO_LE (0.5), GDOUBLE_TO_LE (-0.5) + }; + gdouble be[] = + { GDOUBLE_TO_BE (0.0), GDOUBLE_TO_BE (1.0), GDOUBLE_TO_BE (-1.0), + GDOUBLE_TO_BE (0.5), GDOUBLE_TO_BE (-0.5) + }; + + RUN_CONVERSION ("64 float LE to BE", + le, get_float_caps (1, "LITTLE_ENDIAN", 64), + be, get_float_caps (1, "BIG_ENDIAN", 64)); + + RUN_CONVERSION ("64 float BE to LE", + be, get_float_caps (1, "BIG_ENDIAN", 64), + le, get_float_caps (1, "LITTLE_ENDIAN", 64)); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_multichannel_conversion) +{ + { + gfloat in[] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; + gfloat out[] = { 0.0, 0.0 }; + + RUN_CONVERSION ("3 channels to 1", in, get_float_mc_caps (3, + "BYTE_ORDER", 32, FALSE), out, get_float_caps (1, "BYTE_ORDER", + 32)); + RUN_CONVERSION ("1 channels to 3", out, get_float_caps (1, + "BYTE_ORDER", 32), in, get_float_mc_caps (3, "BYTE_ORDER", + 32, TRUE)); + } + + { + gint16 in[] = { 0, 0, 0, 0, 0, 0 }; + gint16 out[] = { 0, 0 }; + + RUN_CONVERSION ("3 channels to 1", in, get_int_mc_caps (3, + "BYTE_ORDER", 16, 16, TRUE, FALSE), out, get_int_caps (1, + "BYTE_ORDER", 16, 16, TRUE)); + RUN_CONVERSION ("1 channels to 3", out, get_int_caps (1, "BYTE_ORDER", 16, + 16, TRUE), in, get_int_mc_caps (3, "BYTE_ORDER", 16, 16, TRUE, + TRUE)); + } + + { + gint16 in[] = { 1, 2 }; + gint16 out[] = { 1, 1, 2, 2 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + GstAudioChannelPosition out_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + set_channel_positions (in_caps, 1, in_layout); + set_channel_positions (out_caps, 2, out_layout); + + RUN_CONVERSION ("1 channels to 2 with standard layout", in, + in_caps, out, out_caps); + } + + { + gint16 in[] = { 1, 2 }; + gint16 out[] = { 1, 1, 2, 2 }; + GstCaps *in_caps = get_int_caps (1, "BYTE_ORDER", 16, 16, TRUE); + GstCaps *out_caps = get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE); + + RUN_CONVERSION ("1 channels to 2 with standard layout and no positions set", + in, gst_caps_copy (in_caps), out, gst_caps_copy (out_caps)); + + RUN_CONVERSION ("2 channels to 1 with standard layout and no positions set", + out, out_caps, in, in_caps); + } + + { + gint16 in[] = { 1, 2 }; + gint16 out[] = { 1, 0, 2, 0 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT }; + GstAudioChannelPosition out_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + set_channel_positions (in_caps, 1, in_layout); + set_channel_positions (out_caps, 2, out_layout); + + RUN_CONVERSION ("1 channels to 2 with non-standard layout", in, + in_caps, out, out_caps); + } + + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 2, 4 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("2 channels to 1 with non-standard layout", in, + in_caps, out, out_caps); + } + + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 2, 4 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("2 channels to 1 with standard layout", in, + in_caps, out, out_caps); + } + + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 3 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER + }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("2 channels to 1 with non-standard layout", in, + in_caps, out, out_caps); + } + + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 3 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT + }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("2 channels to 1 with non-standard layout", in, + in_caps, out, out_caps); + } + { + gint16 in[] = { 4, 5, 4, 2, 2, 1 }; + gint16 out[] = { 3, 3 }; + GstCaps *in_caps = get_int_mc_caps (6, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_caps (2, "BYTE_ORDER", 16, 16, TRUE); + + RUN_CONVERSION ("5.1 to 2 channels", in, in_caps, out, out_caps); + } + { + gint16 in[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + gint16 out[] = { 0, 0 }; + GstCaps *in_caps = get_int_mc_caps (11, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[11] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + }; + + set_channel_positions (in_caps, 11, in_layout); + + RUN_CONVERSION ("11 channels to 2", in, + gst_caps_copy (in_caps), out, gst_caps_copy (out_caps)); + RUN_CONVERSION ("2 channels to 11", out, out_caps, in, in_caps); + } + +} + +GST_END_TEST; + +/* for testing channel remapping with 8 channels */ +static GstAudioChannelPosition n8chan_pos_remap_in[8] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT +}; + +static GstAudioChannelPosition n8chan_pos_remap_out[8] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE +}; + +GST_START_TEST (test_channel_remapping) +{ + /* float */ + { + gfloat in[] = { 0.0, 1.0, -0.5 }; + gfloat out[] = { -0.5, 1.0, 0.0 }; + GstCaps *in_caps = get_float_mc_caps (3, "BYTE_ORDER", 32, FALSE); + GstCaps *out_caps = get_float_mc_caps (3, "BYTE_ORDER", 32, TRUE); + + RUN_CONVERSION ("3 channels layout remapping float", in, in_caps, + out, out_caps); + } + + /* int */ + { + guint16 in[] = { 0, 65535, 0x9999 }; + guint16 out[] = { 0x9999, 65535, 0 }; + GstCaps *in_caps = get_int_mc_caps (3, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (3, "BYTE_ORDER", 16, 16, FALSE, TRUE); + + RUN_CONVERSION ("3 channels layout remapping int", in, in_caps, + out, out_caps); + } + + /* int with 8 channels (= largest number allowed with channel positions) */ + { + guint16 in[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + guint16 out[] = { 4, 0, 1, 6, 7, 2, 3, 5 }; + GstCaps *in_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, FALSE, TRUE); + + set_channel_positions (in_caps, 8, n8chan_pos_remap_in); + set_channel_positions (out_caps, 8, n8chan_pos_remap_out); + + RUN_CONVERSION ("8 channels layout remapping int", in, in_caps, + out, out_caps); + } + + /* int16 to int32 with 8 channels (= largest number allowed with channel positions) */ + { + guint16 in[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; + guint32 out[] = + { 4 << 16, 0, 1 << 16, 6 << 16, 7 << 16, 2 << 16, 3 << 16, 5 << 16 }; + GstCaps *in_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (8, "BYTE_ORDER", 32, 32, FALSE, TRUE); + + set_channel_positions (in_caps, 8, n8chan_pos_remap_in); + set_channel_positions (out_caps, 8, n8chan_pos_remap_out); + + RUN_CONVERSION ("8 channels layout remapping int16 --> int32", in, in_caps, + out, out_caps); + + in_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, FALSE, FALSE); + out_caps = get_int_mc_caps (8, "BYTE_ORDER", 32, 32, FALSE, TRUE); + set_channel_positions (in_caps, 8, n8chan_pos_remap_in); + set_channel_positions (out_caps, 8, n8chan_pos_remap_out); + RUN_CONVERSION ("8 channels layout remapping int16 <-- int32", out, + out_caps, in, in_caps); + } + + /* float to gint16 with 3 channels */ + { + gfloat in[] = { 100.0 / G_MAXINT16, 0.0, -100.0 / G_MAXINT16 }; + gint16 out[] = { -100, 0, 100 }; + GstCaps *in_caps = get_float_mc_caps (3, "BYTE_ORDER", 32, TRUE); + GstCaps *out_caps = get_int_mc_caps (3, "BYTE_ORDER", 16, 16, TRUE, FALSE); + + RUN_CONVERSION ("3 channels layout remapping float32 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 2 channels and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 2, 2, 4 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_LFE + }; + GstAudioChannelPosition out_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 2, out_layout); + + RUN_CONVERSION ("2 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 2 channels and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 2, 1, 4, 3 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT + }; + GstAudioChannelPosition out_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 2, out_layout); + + RUN_CONVERSION ("2 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 2 channels and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 1, 3, 3 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER + }; + GstAudioChannelPosition out_layout[2] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + + set_channel_positions (in_caps, 2, in_layout); + set_channel_positions (out_caps, 2, out_layout); + + RUN_CONVERSION ("2 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 1 channel and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 0, 0, 0, 0 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT }; + + set_channel_positions (in_caps, 1, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("1 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 1 channel and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 2, 3, 4 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER }; + + set_channel_positions (in_caps, 1, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("1 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } + + /* gint16 to gint16 with 1 channel and non-standard layout */ + { + gint16 in[] = { 1, 2, 3, 4 }; + gint16 out[] = { 1, 2, 3, 4 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstAudioChannelPosition in_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_FRONT_MONO }; + GstAudioChannelPosition out_layout[1] = + { GST_AUDIO_CHANNEL_POSITION_REAR_LEFT }; + + set_channel_positions (in_caps, 1, in_layout); + set_channel_positions (out_caps, 1, out_layout); + + RUN_CONVERSION ("1 channels layout remapping int16 --> int16", in, + in_caps, out, out_caps); + } +} + +GST_END_TEST; + +GST_START_TEST (test_caps_negotiation) +{ + GstElement *src, *ac1, *ac2, *ac3, *sink; + GstElement *pipeline; + GstPad *ac3_src; + GstCaps *caps1, *caps2; + + pipeline = gst_pipeline_new ("test"); + + /* create elements */ + src = gst_element_factory_make ("audiotestsrc", "src"); + ac1 = gst_element_factory_make ("audioconvert", "ac1"); + ac2 = gst_element_factory_make ("audioconvert", "ac2"); + ac3 = gst_element_factory_make ("audioconvert", "ac3"); + sink = gst_element_factory_make ("fakesink", "sink"); + ac3_src = gst_element_get_static_pad (ac3, "src"); + + /* test with 2 audioconvert elements */ + gst_bin_add_many (GST_BIN (pipeline), src, ac1, ac3, sink, NULL); + gst_element_link_many (src, ac1, ac3, sink, NULL); + + /* Set to PAUSED and wait for PREROLL */ + fail_if (gst_element_set_state (pipeline, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline to PAUSED"); + fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) != + GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline to PAUSED"); + + caps1 = gst_pad_get_caps (ac3_src); + fail_if (caps1 == NULL, "gst_pad_get_caps returned NULL"); + GST_DEBUG ("Caps size 1 : %d", gst_caps_get_size (caps1)); + + fail_if (gst_element_set_state (pipeline, GST_STATE_READY) == + GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to READY"); + fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) != + GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to READY"); + + /* test with 3 audioconvert elements */ + gst_element_unlink (ac1, ac3); + gst_bin_add (GST_BIN (pipeline), ac2); + gst_element_link_many (ac1, ac2, ac3, NULL); + + fail_if (gst_element_set_state (pipeline, GST_STATE_PAUSED) == + GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to PAUSED"); + fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) != + GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to PAUSED"); + + caps2 = gst_pad_get_caps (ac3_src); + + fail_if (caps2 == NULL, "gst_pad_get_caps returned NULL"); + GST_DEBUG ("Caps size 2 : %d", gst_caps_get_size (caps2)); + fail_unless (gst_caps_get_size (caps1) == gst_caps_get_size (caps2)); + + gst_caps_unref (caps1); + gst_caps_unref (caps2); + + fail_if (gst_element_set_state (pipeline, GST_STATE_NULL) == + GST_STATE_CHANGE_FAILURE, "Failed to set test pipeline back to NULL"); + fail_if (gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE) != + GST_STATE_CHANGE_SUCCESS, "Failed to set test pipeline back to NULL"); + + gst_object_unref (ac3_src); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_convert_undefined_multichannel) +{ + /* (A) CONVERSION FROM 'WORSE' TO 'BETTER' FORMAT */ + + /* 1 channel, NONE positions, int8 => int16 */ + { + guint16 out[] = { 0x2000 }; + guint8 in[] = { 0x20 }; + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 1, undefined_positions[1 - 1]); + set_channel_positions (in_caps, 1, undefined_positions[1 - 1]); + + RUN_CONVERSION ("1 channel, undefined layout, identity conversion, " + "int8 => int16", in, in_caps, out, out_caps); + } + + /* 2 channels, NONE positions, int8 => int16 */ + { + guint16 out[] = { 0x8000, 0x2000 }; + guint8 in[] = { 0x80, 0x20 }; + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 2, undefined_positions[2 - 1]); + set_channel_positions (in_caps, 2, undefined_positions[2 - 1]); + + RUN_CONVERSION ("2 channels, undefined layout, identity conversion, " + "int8 => int16", in, in_caps, out, out_caps); + } + + /* 6 channels, NONE positions, int8 => int16 */ + { + guint16 out[] = { 0x0000, 0x2000, 0x8000, 0x2000, 0x0000, 0xff00 }; + guint8 in[] = { 0x00, 0x20, 0x80, 0x20, 0x00, 0xff }; + GstCaps *out_caps = get_int_mc_caps (6, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *in_caps = get_int_mc_caps (6, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 6, undefined_positions[6 - 1]); + set_channel_positions (in_caps, 6, undefined_positions[6 - 1]); + + RUN_CONVERSION ("6 channels, undefined layout, identity conversion, " + "int8 => int16", in, in_caps, out, out_caps); + } + + /* 9 channels, NONE positions, int8 => int16 */ + { + guint16 out[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000 + }; + guint8 in[] = { 0x00, 0xff, 0x00, 0x20, 0x80, 0x20, 0x00, 0xff, 0x00 }; + GstCaps *out_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *in_caps = get_int_mc_caps (9, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 9, undefined_positions[9 - 1]); + + RUN_CONVERSION ("9 channels, undefined layout, identity conversion, " + "int8 => int16", in, in_caps, out, out_caps); + } + + /* 15 channels, NONE positions, int8 => int16 */ + { + guint16 out[] = + { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, 0x0000, 0xff00, + 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, 0x0000 + }; + guint8 in[] = + { 0x00, 0xff, 0x00, 0x20, 0x80, 0x20, 0x00, 0xff, 0x00, 0xff, 0x00, + 0x20, 0x80, 0x20, 0x00 + }; + GstCaps *out_caps = + get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *in_caps = get_int_mc_caps (15, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 15, undefined_positions[15 - 1]); + set_channel_positions (in_caps, 15, undefined_positions[15 - 1]); + + RUN_CONVERSION ("15 channels, undefined layout, identity conversion, " + "int8 => int16", in, in_caps, out, out_caps); + } + + /* (B) CONVERSION FROM 'BETTER' TO 'WORSE' FORMAT */ + + /* 1 channel, NONE positions, int16 => int8 */ + { + guint16 in[] = { 0x2000 }; + guint8 out[] = { 0x20 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 1, undefined_positions[1 - 1]); + set_channel_positions (in_caps, 1, undefined_positions[1 - 1]); + + RUN_CONVERSION ("1 channel, undefined layout, identity conversion, " + "int16 => int8", in, in_caps, out, out_caps); + } + + /* 2 channels, NONE positions, int16 => int8 */ + { + guint16 in[] = { 0x8000, 0x2000 }; + guint8 out[] = { 0x80, 0x20 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 2, undefined_positions[2 - 1]); + set_channel_positions (in_caps, 2, undefined_positions[2 - 1]); + + RUN_CONVERSION ("2 channels, undefined layout, identity conversion, " + "int16 => int8", in, in_caps, out, out_caps); + } + + /* 6 channels, NONE positions, int16 => int8 */ + { + guint16 in[] = { 0x0000, 0x2000, 0x8000, 0x2000, 0x0000, 0xff00 }; + guint8 out[] = { 0x00, 0x20, 0x80, 0x20, 0x00, 0xff }; + GstCaps *in_caps = get_int_mc_caps (6, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (6, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 6, undefined_positions[6 - 1]); + set_channel_positions (in_caps, 6, undefined_positions[6 - 1]); + + RUN_CONVERSION ("6 channels, undefined layout, identity conversion, " + "int16 => int8", in, in_caps, out, out_caps); + } + + /* 9 channels, NONE positions, int16 => int8 */ + { + guint16 in[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000 + }; + guint8 out[] = { 0x00, 0xff, 0x00, 0x20, 0x80, 0x20, 0x00, 0xff, 0x00 }; + GstCaps *in_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (9, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 9, undefined_positions[9 - 1]); + + RUN_CONVERSION ("9 channels, undefined layout, identity conversion, " + "int16 => int8", in, in_caps, out, out_caps); + } + + /* 15 channels, NONE positions, int16 => int8 */ + { + guint16 in[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000 + }; + guint8 out[] = + { 0x00, 0xff, 0x00, 0x20, 0x80, 0x20, 0x00, 0xff, 0x00, 0xff, 0x00, + 0x20, 0x80, 0x20, 0x00 + }; + GstCaps *in_caps = get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (15, "BYTE_ORDER", 8, 8, FALSE, FALSE); + + set_channel_positions (out_caps, 15, undefined_positions[15 - 1]); + set_channel_positions (in_caps, 15, undefined_positions[15 - 1]); + + RUN_CONVERSION ("15 channels, undefined layout, identity conversion, " + "int16 => int8", in, in_caps, out, out_caps); + } + + + /* (C) NO CONVERSION, SAME FORMAT */ + + /* 1 channel, NONE positions, int16 => int16 */ + { + guint16 in[] = { 0x2000 }; + guint16 out[] = { 0x2000 }; + GstCaps *in_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (1, "BYTE_ORDER", 16, 16, FALSE, FALSE); + + set_channel_positions (out_caps, 1, undefined_positions[1 - 1]); + set_channel_positions (in_caps, 1, undefined_positions[1 - 1]); + + RUN_CONVERSION ("1 channel, undefined layout, identity conversion, " + "int16 => int16", in, in_caps, out, out_caps); + } + + /* 2 channels, NONE positions, int16 => int16 */ + { + guint16 in[] = { 0x8000, 0x2000 }; + guint16 out[] = { 0x8000, 0x2000 }; + GstCaps *in_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, FALSE, FALSE); + + set_channel_positions (out_caps, 2, undefined_positions[2 - 1]); + set_channel_positions (in_caps, 2, undefined_positions[2 - 1]); + + RUN_CONVERSION ("2 channels, undefined layout, identity conversion, " + "int16 => int16", in, in_caps, out, out_caps); + } + + /* 6 channels, NONE positions, int16 => int16 */ + { + guint16 in[] = { 0x0000, 0x2000, 0x8000, 0x2000, 0x0000, 0xff00 }; + guint16 out[] = { 0x0000, 0x2000, 0x8000, 0x2000, 0x0000, 0xff00 }; + GstCaps *in_caps = get_int_mc_caps (6, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (6, "BYTE_ORDER", 16, 16, FALSE, FALSE); + + set_channel_positions (out_caps, 6, undefined_positions[6 - 1]); + set_channel_positions (in_caps, 6, undefined_positions[6 - 1]); + + RUN_CONVERSION ("6 channels, undefined layout, identity conversion, " + "int16 => int16", in, in_caps, out, out_caps); + } + + /* 9 channels, NONE positions, int16 => int16 */ + { + guint16 in[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000 + }; + guint16 out[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000 + }; + GstCaps *in_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + + set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 9, undefined_positions[9 - 1]); + + RUN_CONVERSION ("9 channels, undefined layout, identity conversion, " + "int16 => int16", in, in_caps, out, out_caps); + } + + /* 15 channels, NONE positions, int16 => int16 */ + { + guint16 in[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000 + }; + guint16 out[] = { 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000, 0xff00, 0x0000, 0xff00, 0x0000, 0x2000, 0x8000, 0x2000, + 0x0000 + }; + GstCaps *in_caps = get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = + get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + + set_channel_positions (out_caps, 15, undefined_positions[15 - 1]); + set_channel_positions (in_caps, 15, undefined_positions[15 - 1]); + + RUN_CONVERSION ("15 channels, undefined layout, identity conversion, " + "int16 => int16", in, in_caps, out, out_caps); + } + + + /* (C) int16 => float */ + + /* 9 channels, NONE positions, int16 => float */ + { + guint16 in[] = { 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x0000 + }; + gfloat out[] = { -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0 }; + GstCaps *in_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_float_mc_caps (9, "BYTE_ORDER", 32, FALSE); + + set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 9, undefined_positions[9 - 1]); + + RUN_CONVERSION ("9 channels, undefined layout, identity conversion, " + "int16 => float", in, in_caps, out, out_caps); + } + + /* 15 channels, NONE positions, int16 => float */ + { + guint16 in[] = { 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000 + }; + gfloat out[] = + { -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, + 0.0, -1.0 + }; + GstCaps *in_caps = get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_float_mc_caps (15, "BYTE_ORDER", 32, FALSE); + + set_channel_positions (out_caps, 15, undefined_positions[15 - 1]); + set_channel_positions (in_caps, 15, undefined_positions[15 - 1]); + + RUN_CONVERSION ("15 channels, undefined layout, identity conversion, " + "int16 => float", in, in_caps, out, out_caps); + } + + + /* 9 channels, NONE positions, int16 => float (same as above, but no + * position on output caps to see if audioconvert transforms correctly) */ + { + guint16 in[] = { 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x0000 + }; + gfloat out[] = { -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0 }; + GstCaps *in_caps = get_int_mc_caps (9, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_float_mc_caps (9, "BYTE_ORDER", 32, FALSE); + + //set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 9, undefined_positions[9 - 1]); + + RUN_CONVERSION ("9 channels, undefined layout, identity conversion, " + "int16 => float", in, in_caps, out, out_caps); + } + + /* 15 channels, NONE positions, int16 => float (same as above, but no + * position on output caps to see if audioconvert transforms correctly) */ + { + guint16 in[] = { 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000, 0x8000, 0x0000, 0x8000, 0x0000, 0x8000, 0x8000, 0x8000, + 0x0000 + }; + gfloat out[] = + { -1.0, 0.0, -1.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, 0.0, -1.0, 0.0, 0.0, + 0.0, -1.0 + }; + GstCaps *in_caps = get_int_mc_caps (15, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_float_mc_caps (15, "BYTE_ORDER", 32, FALSE); + + //set_channel_positions (out_caps, 9, undefined_positions[9 - 1]); + set_channel_positions (in_caps, 15, undefined_positions[15 - 1]); + + RUN_CONVERSION ("15 channels, undefined layout, identity conversion, " + "int16 => float", in, in_caps, out, out_caps); + } + + /* 8 channels, NONE positions => 2 channels: should fail, no mixing allowed */ + { + guint16 in[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + gfloat out[] = { -1.0, -1.0 }; + GstCaps *in_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, FALSE, FALSE); + GstCaps *out_caps = get_float_mc_caps (2, "BYTE_ORDER", 32, FALSE); + + set_channel_positions (in_caps, 8, undefined_positions[8 - 1]); + + RUN_CONVERSION_TO_FAIL ("8 channels with layout => 2 channels", + in, in_caps, out, out_caps); + } + + /* 8 channels, with positions => 2 channels (makes sure channel-position + * fields are removed properly in some cases in ::transform_caps, so we + * don't up with caps with 2 channels and 8 channel positions) */ + { + GstAudioChannelPosition layout8ch[] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT + }; + gint16 in[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + gint16 out[] = { 0, 0 }; + GstCaps *in_caps = get_int_mc_caps (8, "BYTE_ORDER", 16, 16, TRUE, FALSE); + GstCaps *out_caps = get_int_mc_caps (2, "BYTE_ORDER", 16, 16, TRUE, FALSE); + + set_channel_positions (in_caps, 8, layout8ch); + + RUN_CONVERSION ("8 channels with layout => 2 channels", + in, in_caps, out, out_caps); + } +} + +GST_END_TEST; + +static Suite * +audioconvert_suite (void) +{ + Suite *s = suite_create ("audioconvert"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_int16); + tcase_add_test (tc_chain, test_float32); + tcase_add_test (tc_chain, test_int_conversion); + tcase_add_test (tc_chain, test_float_conversion); + tcase_add_test (tc_chain, test_multichannel_conversion); + tcase_add_test (tc_chain, test_channel_remapping); + tcase_add_test (tc_chain, test_caps_negotiation); + tcase_add_test (tc_chain, test_convert_undefined_multichannel); + + return s; +} + +GST_CHECK_MAIN (audioconvert); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/audiorate.c b/gst-plugins-base-subtitles0.10/tests/check/elements/audiorate.c new file mode 100644 index 0000000..7845672 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/audiorate.c @@ -0,0 +1,470 @@ +/* GStreamer unit tests for audiorate + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include + +/* helper element to insert additional buffers overlapping with previous ones */ +static gdouble injector_inject_probability = 0.0; + +typedef GstElement TestInjector; +typedef GstElementClass TestInjectorClass; + +GType test_injector_get_type (void); +GST_BOILERPLATE (TestInjector, test_injector, GstElement, GST_TYPE_ELEMENT); + +#define INJECTOR_CAPS \ + "audio/x-raw-float, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 8 ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32;" \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 8 ], " \ + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " \ + "width = (int) { 8, 16, 32 }, " \ + "depth = (int) [ 1, 32 ], " \ + "signed = (boolean) { true, false }" + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (INJECTOR_CAPS)); + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (INJECTOR_CAPS)); + +static void +test_injector_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); +} + +static void +test_injector_class_init (TestInjectorClass * klass) +{ + /* nothing to do here */ +} + +static GstFlowReturn +test_injector_chain (GstPad * pad, GstBuffer * buf) +{ + GstFlowReturn ret; + GstPad *srcpad; + + srcpad = + gst_element_get_static_pad (GST_ELEMENT (GST_PAD_PARENT (pad)), "src"); + + /* since we're increasing timestamp/offsets, push this one first */ + GST_LOG (" passing buffer [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT + "], offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); + + gst_buffer_ref (buf); + + ret = gst_pad_push (srcpad, buf); + + if (g_random_double () < injector_inject_probability) { + GstBuffer *ibuf; + + ibuf = gst_buffer_copy (buf); + + if (GST_BUFFER_OFFSET_IS_VALID (buf) && + GST_BUFFER_OFFSET_END_IS_VALID (buf)) { + guint64 delta; + + delta = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf); + GST_BUFFER_OFFSET (ibuf) += delta / 4; + GST_BUFFER_OFFSET_END (ibuf) += delta / 4; + } else { + GST_BUFFER_OFFSET (ibuf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (ibuf) = GST_BUFFER_OFFSET_NONE; + } + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf) && + GST_BUFFER_DURATION_IS_VALID (buf)) { + GstClockTime delta; + + delta = GST_BUFFER_DURATION (buf); + GST_BUFFER_TIMESTAMP (ibuf) += delta / 4; + } else { + GST_BUFFER_TIMESTAMP (ibuf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (ibuf) = GST_CLOCK_TIME_NONE; + } + + if (GST_BUFFER_TIMESTAMP_IS_VALID (ibuf) || + GST_BUFFER_OFFSET_IS_VALID (ibuf)) { + GST_LOG ("injecting buffer [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT + "], offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (ibuf)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (ibuf) + + GST_BUFFER_DURATION (ibuf)), GST_BUFFER_OFFSET (ibuf), + GST_BUFFER_OFFSET_END (ibuf)); + + if (gst_pad_push (srcpad, ibuf) != GST_FLOW_OK) { + /* ignore return value */ + } + } else { + GST_WARNING ("couldn't inject buffer, no incoming timestamps or offsets"); + gst_buffer_unref (ibuf); + } + } + + gst_buffer_unref (buf); + + return ret; +} + +static void +test_injector_init (TestInjector * injector, TestInjectorClass * klass) +{ + GstPad *pad; + + pad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_chain_function (pad, test_injector_chain); + gst_pad_set_getcaps_function (pad, gst_pad_proxy_getcaps); + gst_pad_set_setcaps_function (pad, gst_pad_proxy_setcaps); + gst_element_add_pad (GST_ELEMENT (injector), pad); + + pad = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_getcaps_function (pad, gst_pad_proxy_getcaps); + gst_pad_set_setcaps_function (pad, gst_pad_proxy_setcaps); + gst_element_add_pad (GST_ELEMENT (injector), pad); +} + +static gboolean +probe_cb (GstPad * pad, GstBuffer * buf, gdouble * drop_probability) +{ + if (g_random_double () < *drop_probability) { + GST_LOG ("dropping buffer [t=%" GST_TIME_FORMAT "-%" GST_TIME_FORMAT "], " + "offset=%" G_GINT64_FORMAT ", offset_end=%" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); + return FALSE; /* drop buffer */ + } + + return TRUE; /* don't drop buffer */ +} + +static void +got_buf (GstElement * fakesink, GstBuffer * buf, GstPad * pad, GList ** p_bufs) +{ + *p_bufs = g_list_append (*p_bufs, gst_buffer_ref (buf)); +} + +static void +do_perfect_stream_test (guint rate, guint width, gdouble drop_probability, + gdouble inject_probability) +{ + GstElement *pipe, *src, *conv, *filter, *injector, *audiorate, *sink; + GstMessage *msg; + GstCaps *caps; + GstPad *srcpad; + GList *l, *bufs = NULL; + GstClockTime next_time = GST_CLOCK_TIME_NONE; + guint64 next_offset = GST_BUFFER_OFFSET_NONE; + + caps = gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, + rate, "width", G_TYPE_INT, width, NULL); + + GST_INFO ("-------- drop=%.0f%% caps = %" GST_PTR_FORMAT " ---------- ", + drop_probability * 100.0, caps); + + g_assert (drop_probability >= 0.0 && drop_probability <= 1.0); + g_assert (inject_probability >= 0.0 && inject_probability <= 1.0); + g_assert (width > 0 && (width % 8) == 0); + + pipe = gst_pipeline_new ("pipeline"); + fail_unless (pipe != NULL); + + src = gst_element_factory_make ("audiotestsrc", "audiotestsrc"); + fail_unless (src != NULL); + + g_object_set (src, "num-buffers", 100, NULL); + + conv = gst_element_factory_make ("audioconvert", "audioconvert"); + fail_unless (conv != NULL); + + filter = gst_element_factory_make ("capsfilter", "capsfilter"); + fail_unless (filter != NULL); + + g_object_set (filter, "caps", caps, NULL); + + injector_inject_probability = inject_probability; + + injector = GST_ELEMENT (g_object_new (test_injector_get_type (), NULL)); + + srcpad = gst_element_get_static_pad (injector, "src"); + fail_unless (srcpad != NULL); + gst_pad_add_buffer_probe (srcpad, G_CALLBACK (probe_cb), &drop_probability); + gst_object_unref (srcpad); + + audiorate = gst_element_factory_make ("audiorate", "audiorate"); + fail_unless (audiorate != NULL); + + sink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (sink != NULL); + + g_object_set (sink, "signal-handoffs", TRUE, NULL); + + g_signal_connect (sink, "handoff", G_CALLBACK (got_buf), &bufs); + + gst_bin_add_many (GST_BIN (pipe), src, conv, filter, injector, audiorate, + sink, NULL); + gst_element_link_many (src, conv, filter, injector, audiorate, sink, NULL); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), + GST_MESSAGE_EOS | GST_MESSAGE_ERROR, -1); + fail_unless_equals_string (GST_MESSAGE_TYPE_NAME (msg), "eos"); + + for (l = bufs; l != NULL; l = l->next) { + GstBuffer *buf = GST_BUFFER (l->data); + guint num_samples; + + fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf)); + fail_unless (GST_BUFFER_DURATION_IS_VALID (buf)); + fail_unless (GST_BUFFER_OFFSET_IS_VALID (buf)); + fail_unless (GST_BUFFER_OFFSET_END_IS_VALID (buf)); + + GST_LOG ("buffer: ts=%" GST_TIME_FORMAT ", end_ts=%" GST_TIME_FORMAT + " off=%" G_GINT64_FORMAT ", end_off=%" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf)), + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET_END (buf)); + + if (GST_CLOCK_TIME_IS_VALID (next_time)) { + fail_unless_equals_uint64 (next_time, GST_BUFFER_TIMESTAMP (buf)); + } + if (next_offset != GST_BUFFER_OFFSET_NONE) { + fail_unless_equals_uint64 (next_offset, GST_BUFFER_OFFSET (buf)); + } + + /* check buffer size for sanity */ + fail_unless_equals_int (GST_BUFFER_SIZE (buf) % (width / 8), 0); + + /* check there is actually as much data as there should be */ + num_samples = GST_BUFFER_OFFSET_END (buf) - GST_BUFFER_OFFSET (buf); + fail_unless_equals_int (GST_BUFFER_SIZE (buf), num_samples * (width / 8)); + + next_time = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf); + next_offset = GST_BUFFER_OFFSET_END (buf); + } + + gst_message_unref (msg); + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + g_list_foreach (bufs, (GFunc) gst_mini_object_unref, NULL); + g_list_free (bufs); + + gst_caps_unref (caps); +} + +static const guint rates[] = { 8000, 11025, 16000, 22050, 32000, 44100, + 48000, 3333, 33333, 66666, 9999 +}; + +GST_START_TEST (test_perfect_stream_drop0) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.0, 0.0); + do_perfect_stream_test (rates[i], 16, 0.0, 0.0); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_drop10) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.10, 0.0); + do_perfect_stream_test (rates[i], 16, 0.10, 0.0); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_drop50) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.50, 0.0); + do_perfect_stream_test (rates[i], 16, 0.50, 0.0); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_drop90) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.90, 0.0); + do_perfect_stream_test (rates[i], 16, 0.90, 0.0); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_inject10) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.0, 0.10); + do_perfect_stream_test (rates[i], 16, 0.0, 0.10); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_inject90) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.0, 0.90); + do_perfect_stream_test (rates[i], 16, 0.0, 0.90); + } +} + +GST_END_TEST; + +GST_START_TEST (test_perfect_stream_drop45_inject25) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (rates); ++i) { + do_perfect_stream_test (rates[i], 8, 0.45, 0.25); + do_perfect_stream_test (rates[i], 16, 0.45, 0.25); + } +} + +GST_END_TEST; + +/* TODO: also do all tests with channels=1 and channels=2 */ + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-float,channels=1,rate=44100,width=32") + ); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-float,channels=1,rate=44100,width=32") + ); + +GST_START_TEST (test_large_discont) +{ + GstElement *audiorate; + GstCaps *caps; + GstPad *srcpad, *sinkpad; + GstBuffer *buf; + + audiorate = gst_check_setup_element ("audiorate"); + caps = gst_caps_new_simple ("audio/x-raw-float", + "channels", G_TYPE_INT, 1, + "rate", G_TYPE_INT, 44100, "width", G_TYPE_INT, 32, NULL); + + srcpad = gst_check_setup_src_pad (audiorate, &srctemplate, caps); + sinkpad = gst_check_setup_sink_pad (audiorate, &sinktemplate, caps); + + gst_pad_set_active (srcpad, TRUE); + gst_pad_set_active (sinkpad, TRUE); + + fail_unless (gst_element_set_state (audiorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "failed to set audiorate playing"); + + buf = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buf, caps); + GST_BUFFER_TIMESTAMP (buf) = 0; + gst_pad_push (srcpad, buf); + + fail_unless_equals_int (g_list_length (buffers), 1); + + buf = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buf, caps); + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + gst_pad_push (srcpad, buf); + /* Now we should have 3 more buffers: the one we injected, plus _two_ filler + * buffers, because the gap is > 1 second (but less than 2 seconds) */ + fail_unless_equals_int (g_list_length (buffers), 4); + + gst_element_set_state (audiorate, GST_STATE_NULL); + gst_caps_unref (caps); + + gst_check_teardown_sink_pad (audiorate); + gst_check_teardown_src_pad (audiorate); + + gst_object_unref (audiorate); +} + +GST_END_TEST; + +static Suite * +audiorate_suite (void) +{ + Suite *s = suite_create ("audiorate"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_perfect_stream_drop0); + tcase_add_test (tc_chain, test_perfect_stream_drop10); + tcase_add_test (tc_chain, test_perfect_stream_drop50); + tcase_add_test (tc_chain, test_perfect_stream_drop90); + tcase_add_test (tc_chain, test_perfect_stream_inject10); + tcase_add_test (tc_chain, test_perfect_stream_inject90); + tcase_add_test (tc_chain, test_perfect_stream_drop45_inject25); + tcase_add_test (tc_chain, test_large_discont); + + return s; +} + +GST_CHECK_MAIN (audiorate); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/audioresample.c b/gst-plugins-base-subtitles0.10/tests/check/elements/audioresample.c new file mode 100644 index 0000000..a8a79a3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/audioresample.c @@ -0,0 +1,926 @@ +/* GStreamer + * + * unit test for audioresample, based on the audioresample unit test + * + * Copyright (C) <2005> Thomas Vander Stichele + * Copyright (C) <2006> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include + +/* For ease of programming we use globals to keep refs for our floating + * src and sink pads we create; otherwise we always have to do get_pad, + * get_peer, and then remove references in every test function */ +static GstPad *mysrcpad, *mysinkpad; + +#define RESAMPLE_CAPS_FLOAT \ + "audio/x-raw-float, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 32, 64 }" + +#define RESAMPLE_CAPS_INT \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (bool) TRUE" + +#define RESAMPLE_CAPS_TEMPLATE_STRING \ + RESAMPLE_CAPS_FLOAT " ; " \ + RESAMPLE_CAPS_INT + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (RESAMPLE_CAPS_TEMPLATE_STRING) + ); + +static GstElement * +setup_audioresample (int channels, int inrate, int outrate, int width, + gboolean fp) +{ + GstElement *audioresample; + GstCaps *caps; + GstStructure *structure; + + GST_DEBUG ("setup_audioresample"); + audioresample = gst_check_setup_element ("audioresample"); + + if (fp) + caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT); + else + caps = gst_caps_from_string (RESAMPLE_CAPS_INT); + structure = gst_caps_get_structure (caps, 0); + gst_structure_set (structure, "channels", G_TYPE_INT, channels, + "rate", G_TYPE_INT, inrate, "width", G_TYPE_INT, width, NULL); + if (!fp) + gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL); + fail_unless (gst_caps_is_fixed (caps)); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PAUSED) == GST_STATE_CHANGE_SUCCESS, + "could not set to paused"); + + mysrcpad = gst_check_setup_src_pad (audioresample, &srctemplate, caps); + gst_pad_set_caps (mysrcpad, caps); + gst_caps_unref (caps); + + if (fp) + caps = gst_caps_from_string (RESAMPLE_CAPS_FLOAT); + else + caps = gst_caps_from_string (RESAMPLE_CAPS_INT); + structure = gst_caps_get_structure (caps, 0); + gst_structure_set (structure, "channels", G_TYPE_INT, channels, + "rate", G_TYPE_INT, outrate, "width", G_TYPE_INT, width, NULL); + if (!fp) + gst_structure_set (structure, "depth", G_TYPE_INT, width, NULL); + fail_unless (gst_caps_is_fixed (caps)); + + mysinkpad = gst_check_setup_sink_pad (audioresample, &sinktemplate, caps); + /* this installs a getcaps func that will always return the caps we set + * later */ + gst_pad_set_caps (mysinkpad, caps); + gst_pad_use_fixed_caps (mysinkpad); + + gst_pad_set_active (mysinkpad, TRUE); + gst_pad_set_active (mysrcpad, TRUE); + + gst_caps_unref (caps); + + return audioresample; +} + +static void +cleanup_audioresample (GstElement * audioresample) +{ + GST_DEBUG ("cleanup_audioresample"); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL"); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (audioresample); + gst_check_teardown_sink_pad (audioresample); + gst_check_teardown_element (audioresample); + gst_check_drop_buffers (); +} + +static void +fail_unless_perfect_stream (void) +{ + guint64 timestamp = 0L, duration = 0L; + guint64 offset = 0L, offset_end = 0L; + + GList *l; + GstBuffer *buffer; + + for (l = buffers; l; l = l->next) { + buffer = GST_BUFFER (l->data); + ASSERT_BUFFER_REFCOUNT (buffer, "buffer", 1); + GST_DEBUG ("buffer timestamp %" G_GUINT64_FORMAT ", duration %" + G_GUINT64_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %" + G_GUINT64_FORMAT, + GST_BUFFER_TIMESTAMP (buffer), + GST_BUFFER_DURATION (buffer), + GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer)); + + fail_unless_equals_uint64 (timestamp, GST_BUFFER_TIMESTAMP (buffer)); + fail_unless_equals_uint64 (offset, GST_BUFFER_OFFSET (buffer)); + duration = GST_BUFFER_DURATION (buffer); + offset_end = GST_BUFFER_OFFSET_END (buffer); + + timestamp += duration; + offset = offset_end; + gst_buffer_unref (buffer); + } + g_list_free (buffers); + buffers = NULL; +} + +/* this tests that the output is a perfect stream if the input is */ +static void +test_perfect_stream_instance (int inrate, int outrate, int samples, + int numbuffers) +{ + GstElement *audioresample; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + guint64 offset = 0; + + int i, j; + gint16 *p; + + audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE); + caps = gst_pad_get_negotiated_caps (mysrcpad); + fail_unless (gst_caps_is_fixed (caps)); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (j = 1; j <= numbuffers; ++j) { + + inbuffer = gst_buffer_new_and_alloc (samples * 4); + GST_BUFFER_DURATION (inbuffer) = GST_FRAMES_TO_CLOCK_TIME (samples, inrate); + GST_BUFFER_TIMESTAMP (inbuffer) = GST_BUFFER_DURATION (inbuffer) * (j - 1); + GST_BUFFER_OFFSET (inbuffer) = offset; + offset += samples; + GST_BUFFER_OFFSET_END (inbuffer) = offset; + + gst_buffer_set_caps (inbuffer, caps); + + p = (gint16 *) GST_BUFFER_DATA (inbuffer); + + /* create a 16 bit signed ramp */ + for (i = 0; i < samples; ++i) { + *p = -32767 + i * (65535 / samples); + ++p; + *p = -32767 + i * (65535 / samples); + ++p; + } + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + fail_unless_equals_int (g_list_length (buffers), j); + } + + /* FIXME: we should make audioresample handle eos by flushing out the last + * samples, which will give us one more, small, buffer */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + + fail_unless_perfect_stream (); + + /* cleanup */ + gst_caps_unref (caps); + cleanup_audioresample (audioresample); +} + + +/* make sure that outgoing buffers are contiguous in timestamp/duration and + * offset/offsetend + */ +GST_START_TEST (test_perfect_stream) +{ + /* integral scalings */ + test_perfect_stream_instance (48000, 24000, 500, 20); + test_perfect_stream_instance (48000, 12000, 500, 20); + test_perfect_stream_instance (12000, 24000, 500, 20); + test_perfect_stream_instance (12000, 48000, 500, 20); + + /* non-integral scalings */ + test_perfect_stream_instance (44100, 8000, 500, 20); + test_perfect_stream_instance (8000, 44100, 500, 20); + + /* wacky scalings */ + test_perfect_stream_instance (12345, 54321, 500, 20); + test_perfect_stream_instance (101, 99, 500, 20); +} + +GST_END_TEST; + +/* this tests that the output is a correct discontinuous stream + * if the input is; ie input drops in time come out the same way */ +static void +test_discont_stream_instance (int inrate, int outrate, int samples, + int numbuffers) +{ + GstElement *audioresample; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + GstClockTime ints; + + int i, j; + gint16 *p; + + GST_DEBUG ("inrate:%d outrate:%d samples:%d numbuffers:%d", + inrate, outrate, samples, numbuffers); + + audioresample = setup_audioresample (2, inrate, outrate, 16, FALSE); + caps = gst_pad_get_negotiated_caps (mysrcpad); + fail_unless (gst_caps_is_fixed (caps)); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + for (j = 1; j <= numbuffers; ++j) { + + inbuffer = gst_buffer_new_and_alloc (samples * 4); + GST_BUFFER_DURATION (inbuffer) = samples * GST_SECOND / inrate; + /* "drop" half the buffers */ + ints = GST_BUFFER_DURATION (inbuffer) * 2 * (j - 1); + GST_BUFFER_TIMESTAMP (inbuffer) = ints; + GST_BUFFER_OFFSET (inbuffer) = (j - 1) * 2 * samples; + GST_BUFFER_OFFSET_END (inbuffer) = j * 2 * samples + samples; + + gst_buffer_set_caps (inbuffer, caps); + + p = (gint16 *) GST_BUFFER_DATA (inbuffer); + + /* create a 16 bit signed ramp */ + for (i = 0; i < samples; ++i) { + *p = -32767 + i * (65535 / samples); + ++p; + *p = -32767 + i * (65535 / samples); + ++p; + } + + GST_DEBUG ("Sending Buffer time:%" G_GUINT64_FORMAT " duration:%" + G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%" + G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (inbuffer), + GST_BUFFER_DURATION (inbuffer), GST_BUFFER_IS_DISCONT (inbuffer), + GST_BUFFER_OFFSET (inbuffer), GST_BUFFER_OFFSET_END (inbuffer)); + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* check if the timestamp of the pushed buffer matches the incoming one */ + outbuffer = g_list_nth_data (buffers, g_list_length (buffers) - 1); + fail_if (outbuffer == NULL); + fail_unless_equals_uint64 (ints, GST_BUFFER_TIMESTAMP (outbuffer)); + GST_DEBUG ("Got Buffer time:%" G_GUINT64_FORMAT " duration:%" + G_GINT64_FORMAT " discont:%d offset:%" G_GUINT64_FORMAT " offset_end:%" + G_GUINT64_FORMAT, GST_BUFFER_TIMESTAMP (outbuffer), + GST_BUFFER_DURATION (outbuffer), GST_BUFFER_IS_DISCONT (outbuffer), + GST_BUFFER_OFFSET (outbuffer), GST_BUFFER_OFFSET_END (outbuffer)); + if (j > 1) { + fail_unless (GST_BUFFER_IS_DISCONT (outbuffer), + "expected discont for buffer #%d", j); + } + } + + /* cleanup */ + gst_caps_unref (caps); + cleanup_audioresample (audioresample); +} + +GST_START_TEST (test_discont_stream) +{ + /* integral scalings */ + test_discont_stream_instance (48000, 24000, 5000, 20); + test_discont_stream_instance (48000, 12000, 5000, 20); + test_discont_stream_instance (12000, 24000, 5000, 20); + test_discont_stream_instance (12000, 48000, 5000, 20); + + /* non-integral scalings */ + test_discont_stream_instance (44100, 8000, 5000, 20); + test_discont_stream_instance (8000, 44100, 5000, 20); + + /* wacky scalings */ + test_discont_stream_instance (12345, 54321, 5000, 20); + test_discont_stream_instance (101, 99, 5000, 20); +} + +GST_END_TEST; + + + +GST_START_TEST (test_reuse) +{ + GstElement *audioresample; + GstEvent *newseg; + GstBuffer *inbuffer; + GstCaps *caps; + + audioresample = setup_audioresample (1, 9343, 48000, 16, FALSE); + caps = gst_pad_get_negotiated_caps (mysrcpad); + fail_unless (gst_caps_is_fixed (caps)); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE); + + inbuffer = gst_buffer_new_and_alloc (9343 * 4); + memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer)); + GST_BUFFER_DURATION (inbuffer) = GST_SECOND; + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_OFFSET (inbuffer) = 0; + gst_buffer_set_caps (inbuffer, caps); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* ... but it ends up being collected on the global buffer list */ + fail_unless_equals_int (g_list_length (buffers), 1); + + /* now reset and try again ... */ + fail_unless (gst_element_set_state (audioresample, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to NULL"); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE); + + inbuffer = gst_buffer_new_and_alloc (9343 * 4); + memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer)); + GST_BUFFER_DURATION (inbuffer) = GST_SECOND; + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_OFFSET (inbuffer) = 0; + gst_buffer_set_caps (inbuffer, caps); + + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* ... it also ends up being collected on the global buffer list. If we + * now have more than 2 buffers, then audioresample probably didn't clean + * up its internal buffer properly and tried to push the remaining samples + * when it got the second NEWSEGMENT event */ + fail_unless_equals_int (g_list_length (buffers), 2); + + cleanup_audioresample (audioresample); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_shutdown) +{ + GstElement *pipeline, *src, *cf1, *ar, *cf2, *sink; + GstCaps *caps; + guint i; + + /* create pipeline, force audioresample to actually resample */ + pipeline = gst_pipeline_new (NULL); + + src = gst_check_setup_element ("audiotestsrc"); + cf1 = gst_check_setup_element ("capsfilter"); + ar = gst_check_setup_element ("audioresample"); + cf2 = gst_check_setup_element ("capsfilter"); + g_object_set (cf2, "name", "capsfilter2", NULL); + sink = gst_check_setup_element ("fakesink"); + + caps = + gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 11025, NULL); + g_object_set (cf1, "caps", caps, NULL); + gst_caps_unref (caps); + + caps = + gst_caps_new_simple ("audio/x-raw-int", "rate", G_TYPE_INT, 48000, NULL); + g_object_set (cf2, "caps", caps, NULL); + gst_caps_unref (caps); + + /* don't want to sync against the clock, the more throughput the better */ + g_object_set (src, "is-live", FALSE, NULL); + g_object_set (sink, "sync", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, cf1, ar, cf2, sink, NULL); + fail_if (!gst_element_link_many (src, cf1, ar, cf2, sink, NULL)); + + /* now, wait until pipeline is running and then shut it down again; repeat */ + for (i = 0; i < 20; ++i) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_get_state (pipeline, NULL, NULL, -1); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + g_usleep (100); + gst_element_set_state (pipeline, GST_STATE_NULL); + } + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static GstFlowReturn +live_switch_alloc_only_48000 (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstStructure *structure; + gint rate; + gint channels; + GstCaps *desired; + + structure = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_get_int (structure, "rate", &rate)); + fail_unless (gst_structure_get_int (structure, "channels", &channels)); + + if (rate < 48000) + return GST_FLOW_NOT_NEGOTIATED; + + desired = gst_caps_copy (caps); + gst_caps_set_simple (desired, "rate", G_TYPE_INT, 48000, NULL); + + *buf = gst_buffer_new_and_alloc (channels * 48000); + gst_buffer_set_caps (*buf, desired); + gst_caps_unref (desired); + + return GST_FLOW_OK; +} + +static GstCaps * +live_switch_get_sink_caps (GstPad * pad) +{ + GstCaps *result; + + result = gst_caps_copy (GST_PAD_CAPS (pad)); + + gst_caps_set_simple (result, + "rate", GST_TYPE_INT_RANGE, 48000, G_MAXINT, NULL); + + return result; +} + +static void +live_switch_push (int rate, GstCaps * caps) +{ + GstBuffer *inbuffer; + GstCaps *desired; + GList *l; + + desired = gst_caps_copy (caps); + gst_caps_set_simple (desired, "rate", G_TYPE_INT, rate, NULL); + gst_pad_set_caps (mysrcpad, desired); + + fail_unless (gst_pad_alloc_buffer_and_set_caps (mysrcpad, + GST_BUFFER_OFFSET_NONE, rate * 4, desired, &inbuffer) == GST_FLOW_OK); + + /* When the basetransform hits the non-configured case it always + * returns a buffer with exactly the same caps as we requested so the actual + * renegotiation (if needed) will be done in the _chain*/ + fail_unless (inbuffer != NULL); + GST_DEBUG ("desired: %" GST_PTR_FORMAT ".... got: %" GST_PTR_FORMAT, + desired, GST_BUFFER_CAPS (inbuffer)); + fail_unless (gst_caps_is_equal (desired, GST_BUFFER_CAPS (inbuffer))); + + memset (GST_BUFFER_DATA (inbuffer), 0, GST_BUFFER_SIZE (inbuffer)); + GST_BUFFER_DURATION (inbuffer) = GST_SECOND; + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_OFFSET (inbuffer) = 0; + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* ... but it ends up being collected on the global buffer list */ + fail_unless_equals_int (g_list_length (buffers), 1); + + for (l = buffers; l; l = l->next) { + GstBuffer *buffer = GST_BUFFER (l->data); + + gst_buffer_unref (buffer); + } + + g_list_free (buffers); + buffers = NULL; + + gst_caps_unref (desired); +} + +GST_START_TEST (test_live_switch) +{ + GstElement *audioresample; + GstEvent *newseg; + GstCaps *caps; + + audioresample = setup_audioresample (4, 48000, 48000, 16, FALSE); + + /* Let the sinkpad act like something that can only handle things of + * rate 48000- and can only allocate buffers for that rate, but if someone + * tries to get a buffer with a rate higher then 48000 tries to renegotiate + * */ + gst_pad_set_bufferalloc_function (mysinkpad, live_switch_alloc_only_48000); + gst_pad_set_getcaps_function (mysinkpad, live_switch_get_sink_caps); + + gst_pad_use_fixed_caps (mysrcpad); + + caps = gst_pad_get_negotiated_caps (mysrcpad); + fail_unless (gst_caps_is_fixed (caps)); + + fail_unless (gst_element_set_state (audioresample, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + newseg = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, 0); + fail_unless (gst_pad_push_event (mysrcpad, newseg) != FALSE); + + /* downstream can provide the requested rate, a buffer alloc will be passed + * on */ + live_switch_push (48000, caps); + + /* Downstream can never accept this rate, buffer alloc isn't passed on */ + live_switch_push (40000, caps); + + /* Downstream can provide the requested rate but will re-negotiate */ + live_switch_push (50000, caps); + + cleanup_audioresample (audioresample); + gst_caps_unref (caps); +} + +GST_END_TEST; + +#ifndef GST_DISABLE_PARSE + +static GMainLoop *loop; +static gint messages = 0; + +static void +element_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + gchar *s; + + s = gst_structure_to_string (gst_message_get_structure (message)); + GST_DEBUG ("Received message: %s", s); + g_free (s); + + messages++; +} + +static void +eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + GST_DEBUG ("Received eos"); + g_main_loop_quit (loop); +} + +static void +test_pipeline (gint width, gboolean fp, gint inrate, gint outrate, gint quality) +{ + GstElement *pipeline; + GstBus *bus; + GError *error = NULL; + gchar *pipe_str; + + pipe_str = + g_strdup_printf + ("audiotestsrc num-buffers=10 ! audioconvert ! audio/x-raw-%s,rate=%d,width=%d,channels=2 ! audioresample quality=%d ! audio/x-raw-%s,rate=%d,width=%d ! identity check-imperfect-timestamp=TRUE ! fakesink", + (fp) ? "float" : "int", inrate, width, quality, (fp) ? "float" : "int", + outrate, width); + + pipeline = gst_parse_launch (pipe_str, &error); + fail_unless (pipeline != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message::element", (GCallback) element_message_cb, + NULL); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* run until we receive EOS */ + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + g_main_loop_unref (loop); + loop = NULL; + + gst_element_set_state (pipeline, GST_STATE_NULL); + + fail_if (messages > 0, "Received imperfect timestamp messages"); + gst_object_unref (pipeline); +} + +GST_START_TEST (test_pipelines) +{ + gint quality; + + /* Test qualities 0, 5 and 10 */ + for (quality = 0; quality < 11; quality += 5) { + GST_DEBUG ("Checking with quality %d", quality); + + test_pipeline (8, FALSE, 44100, 48000, quality); + test_pipeline (8, FALSE, 48000, 44100, quality); + + test_pipeline (16, FALSE, 44100, 48000, quality); + test_pipeline (16, FALSE, 48000, 44100, quality); + + test_pipeline (24, FALSE, 44100, 48000, quality); + test_pipeline (24, FALSE, 48000, 44100, quality); + + test_pipeline (32, FALSE, 44100, 48000, quality); + test_pipeline (32, FALSE, 48000, 44100, quality); + + test_pipeline (32, TRUE, 44100, 48000, quality); + test_pipeline (32, TRUE, 48000, 44100, quality); + + test_pipeline (64, TRUE, 44100, 48000, quality); + test_pipeline (64, TRUE, 48000, 44100, quality); + } +} + +GST_END_TEST; + +GST_START_TEST (test_preference_passthrough) +{ + GstStateChangeReturn ret; + GstElement *pipeline, *src; + GstStructure *s; + GstMessage *msg; + GstCaps *caps; + GstPad *pad; + GstBus *bus; + GError *error = NULL; + gint rate = 0; + + pipeline = gst_parse_launch ("audiotestsrc num-buffers=1 name=src ! " + "audioresample ! audio/x-raw-int,channels=1,width=16,depth=16," + "endianness=BYTE_ORDER,signed=true,rate=8000 ! " + "fakesink can-activate-pull=false", &error); + fail_unless (pipeline != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless_equals_int (ret, GST_STATE_CHANGE_ASYNC); + + /* run until we receive EOS */ + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + msg = gst_bus_timed_pop_filtered (bus, -1, GST_MESSAGE_EOS); + gst_message_unref (msg); + gst_object_unref (bus); + + src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); + fail_unless (src != NULL); + pad = gst_element_get_static_pad (src, "src"); + fail_unless (pad != NULL); + caps = gst_pad_get_negotiated_caps (pad); + GST_LOG ("negotiated audiotestsrc caps: %" GST_PTR_FORMAT, caps); + fail_unless (caps != NULL); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_get_int (s, "rate", &rate)); + /* there's no need to resample, audiotestsrc supports any rate, so make + * sure audioresample provided upstream with the right caps to negotiate + * this correctly */ + fail_unless_equals_int (rate, 8000); + gst_caps_unref (caps); + gst_object_unref (pad); + gst_object_unref (src); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +#endif + +static void +_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + GMainLoop *loop = user_data; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + case GST_MESSAGE_WARNING: + g_assert_not_reached (); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + break; + default: + break; + } +} + +typedef struct +{ + guint64 latency; + GstClockTime in_ts; + + GstClockTime next_out_ts; + guint64 next_out_off; + + guint64 in_buffer_count, out_buffer_count; +} TimestampDriftCtx; + +static void +fakesink_handoff_cb (GstElement * object, GstBuffer * buffer, GstPad * pad, + gpointer user_data) +{ + TimestampDriftCtx *ctx = user_data; + + ctx->out_buffer_count++; + if (ctx->latency == GST_CLOCK_TIME_NONE) { + ctx->latency = 1000 - GST_BUFFER_SIZE (buffer) / 8; + } + + /* Check if we have a perfectly timestampped stream */ + if (ctx->next_out_ts != GST_CLOCK_TIME_NONE) + fail_unless (ctx->next_out_ts == GST_BUFFER_TIMESTAMP (buffer), + "expected timestamp %" GST_TIME_FORMAT " got timestamp %" + GST_TIME_FORMAT, GST_TIME_ARGS (ctx->next_out_ts), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + + /* Check if we have a perfectly offsetted stream */ + fail_unless (GST_BUFFER_OFFSET_END (buffer) == + GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) / 8, + "expected offset end %" G_GUINT64_FORMAT " got offset end %" + G_GUINT64_FORMAT, + GST_BUFFER_OFFSET (buffer) + GST_BUFFER_SIZE (buffer) / 8, + GST_BUFFER_OFFSET_END (buffer)); + if (ctx->next_out_off != GST_BUFFER_OFFSET_NONE) { + fail_unless (GST_BUFFER_OFFSET (buffer) == ctx->next_out_off, + "expected offset %" G_GUINT64_FORMAT " got offset %" G_GUINT64_FORMAT, + ctx->next_out_off, GST_BUFFER_OFFSET (buffer)); + } + + if (ctx->in_buffer_count != ctx->out_buffer_count) { + GST_INFO ("timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + } + + if (ctx->in_ts != GST_CLOCK_TIME_NONE && ctx->in_buffer_count > 1 + && ctx->in_buffer_count == ctx->out_buffer_count) { + fail_unless (GST_BUFFER_TIMESTAMP (buffer) == + ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND, + 4096), + "expected output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT + ") got output timestamp %" GST_TIME_FORMAT " (%" G_GUINT64_FORMAT ")", + GST_TIME_ARGS (ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, + GST_SECOND, 4096)), + ctx->in_ts - gst_util_uint64_scale_round (ctx->latency, GST_SECOND, + 4096), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_BUFFER_TIMESTAMP (buffer)); + } + + ctx->next_out_ts = + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + ctx->next_out_off = GST_BUFFER_OFFSET_END (buffer); +} + +static void +identity_handoff_cb (GstElement * object, GstBuffer * buffer, + gpointer user_data) +{ + TimestampDriftCtx *ctx = user_data; + + ctx->in_ts = GST_BUFFER_TIMESTAMP (buffer); + ctx->in_buffer_count++; +} + +GST_START_TEST (test_timestamp_drift) +{ + TimestampDriftCtx ctx = + { GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE, + GST_BUFFER_OFFSET_NONE, 0, 0 + }; + GstElement *pipeline; + GstElement *audiotestsrc, *capsfilter1, *identity, *audioresample, + *capsfilter2, *fakesink; + GstBus *bus; + GMainLoop *loop; + GstCaps *caps; + + pipeline = gst_pipeline_new ("pipeline"); + fail_unless (pipeline != NULL); + + audiotestsrc = gst_element_factory_make ("audiotestsrc", "src"); + fail_unless (audiotestsrc != NULL); + g_object_set (G_OBJECT (audiotestsrc), "num-buffers", 10000, + "samplesperbuffer", 4000, NULL); + + capsfilter1 = gst_element_factory_make ("capsfilter", "capsfilter1"); + fail_unless (capsfilter1 != NULL); + caps = + gst_caps_from_string + ("audio/x-raw-float, channels=1, width=64, rate=16384"); + g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL); + gst_caps_unref (caps); + + identity = gst_element_factory_make ("identity", "identity"); + fail_unless (identity != NULL); + g_object_set (G_OBJECT (identity), "sync", FALSE, "signal-handoffs", TRUE, + NULL); + g_signal_connect (identity, "handoff", (GCallback) identity_handoff_cb, &ctx); + + audioresample = gst_element_factory_make ("audioresample", "resample"); + fail_unless (audioresample != NULL); + capsfilter2 = gst_element_factory_make ("capsfilter", "capsfilter2"); + fail_unless (capsfilter2 != NULL); + caps = + gst_caps_from_string + ("audio/x-raw-float, channels=1, width=64, rate=4096"); + g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL); + gst_caps_unref (caps); + + fakesink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (fakesink != NULL); + g_object_set (G_OBJECT (fakesink), "sync", FALSE, "async", FALSE, + "signal-handoffs", TRUE, NULL); + g_signal_connect (fakesink, "handoff", (GCallback) fakesink_handoff_cb, &ctx); + + + gst_bin_add_many (GST_BIN (pipeline), audiotestsrc, capsfilter1, identity, + audioresample, capsfilter2, fakesink, NULL); + fail_unless (gst_element_link_many (audiotestsrc, capsfilter1, identity, + audioresample, capsfilter2, fakesink, NULL)); + + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (pipeline); + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message", (GCallback) _message_cb, loop); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + g_main_loop_run (loop); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + g_main_loop_unref (loop); + gst_object_unref (pipeline); + +} GST_END_TEST; + +static Suite * +audioresample_suite (void) +{ + Suite *s = suite_create ("audioresample"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_perfect_stream); + tcase_add_test (tc_chain, test_discont_stream); + tcase_add_test (tc_chain, test_reuse); + tcase_add_test (tc_chain, test_shutdown); + tcase_add_test (tc_chain, test_live_switch); + tcase_add_test (tc_chain, test_timestamp_drift); + +#ifndef GST_DISABLE_PARSE + tcase_set_timeout (tc_chain, 360); + tcase_add_test (tc_chain, test_pipelines); + tcase_add_test (tc_chain, test_preference_passthrough); +#endif + + return s; +} + +GST_CHECK_MAIN (audioresample); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/audiotestsrc.c b/gst-plugins-base-subtitles0.10/tests/check/elements/audiotestsrc.c new file mode 100644 index 0000000..e83dceb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/audiotestsrc.c @@ -0,0 +1,128 @@ +/* GStreamer + * + * unit test for audiotestsrc + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +/* 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 *mysinkpad; + + +#define CAPS_TEMPLATE_STRING \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (bool) TRUE" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CAPS_TEMPLATE_STRING) + ); + +static GstElement * +setup_audiotestsrc (void) +{ + GstElement *audiotestsrc; + + GST_DEBUG ("setup_audiotestsrc"); + audiotestsrc = gst_check_setup_element ("audiotestsrc"); + mysinkpad = gst_check_setup_sink_pad (audiotestsrc, &sinktemplate, NULL); + gst_pad_set_active (mysinkpad, TRUE); + + return audiotestsrc; +} + +static void +cleanup_audiotestsrc (GstElement * audiotestsrc) +{ + GST_DEBUG ("cleanup_audiotestsrc"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (audiotestsrc); + gst_check_teardown_element (audiotestsrc); +} + +GST_START_TEST (test_all_waves) +{ + GstElement *audiotestsrc; + GObjectClass *oclass; + GParamSpec *property; + GEnumValue *values; + guint j = 0; + + audiotestsrc = setup_audiotestsrc (); + oclass = G_OBJECT_GET_CLASS (audiotestsrc); + property = g_object_class_find_property (oclass, "wave"); + fail_unless (G_IS_PARAM_SPEC_ENUM (property)); + values = G_ENUM_CLASS (g_type_class_ref (property->value_type))->values; + + + while (values[j].value_name) { + GST_DEBUG_OBJECT (audiotestsrc, "testing wave %s", values[j].value_name); + + fail_unless (gst_element_set_state (audiotestsrc, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + g_mutex_lock (check_mutex); + while (g_list_length (buffers) < 10) + g_cond_wait (check_cond, check_mutex); + g_mutex_unlock (check_mutex); + + gst_element_set_state (audiotestsrc, GST_STATE_READY); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ++j; + } + + /* cleanup */ + cleanup_audiotestsrc (audiotestsrc); +} + +GST_END_TEST; + +static Suite * +audiotestsrc_suite (void) +{ + Suite *s = suite_create ("audiotestsrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_all_waves); + + return s; +} + +GST_CHECK_MAIN (audiotestsrc); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin.c b/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin.c new file mode 100644 index 0000000..eb6f38a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin.c @@ -0,0 +1,200 @@ +/* GStreamer unit tests for decodebin + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +static const gchar dummytext[] = + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown " + "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick " + "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog " + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy " + "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a " + "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps " + "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox " + "jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown " + "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick " + "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog " + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy " + "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a " + "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps " + "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox "; + +static void +src_handoff_cb (GstElement * src, GstBuffer * buf, GstPad * pad, gpointer data) +{ + GST_BUFFER_DATA (buf) = (guint8 *) dummytext; + GST_BUFFER_SIZE (buf) = sizeof (dummytext); + GST_BUFFER_OFFSET (buf) = 0; + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); +} + +static void +decodebin_new_decoded_pad_cb (GstElement * decodebin, GstPad * pad, + gboolean last, gboolean * p_flag) +{ + /* we should not be reached */ + fail_unless (decodebin == NULL, "new-decoded-pad should not be emitted"); +} + +/* make sure that decodebin errors out instead of creating a new decoded pad + * if the entire stream is a plain text file */ +GST_START_TEST (test_text_plain_streams) +{ + GstElement *pipe, *src, *decodebin; + GstMessage *msg; + + pipe = gst_pipeline_new (NULL); + fail_unless (pipe != NULL, "failed to create pipeline"); + + src = gst_element_factory_make ("fakesrc", "src"); + fail_unless (src != NULL, "Failed to create fakesrc element"); + + g_object_set (src, "signal-handoffs", TRUE, NULL); + g_object_set (src, "num-buffers", 1, NULL); + g_object_set (src, "can-activate-pull", FALSE, NULL); + g_signal_connect (src, "handoff", G_CALLBACK (src_handoff_cb), NULL); + + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + fail_unless (decodebin != NULL, "Failed to create decodebin element"); + + g_signal_connect (decodebin, "new-decoded-pad", + G_CALLBACK (decodebin_new_decoded_pad_cb), NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src)); + fail_unless (gst_bin_add (GST_BIN (pipe), decodebin)); + fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* it should error out at some point */ + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + gst_message_unref (msg); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static void +new_decoded_pad_plug_fakesink_cb (GstElement * decodebin, GstPad * srcpad, + gboolean last, GstElement * pipeline) +{ + GstElement *sink; + GstPad *sinkpad; + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (sink != NULL, "Failed to create fakesink element"); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK); + gst_object_unref (sinkpad); + + gst_element_set_state (sink, GST_STATE_PLAYING); +} + +GST_START_TEST (test_reuse_without_decoders) +{ + GstElement *pipe, *src, *decodebin, *sink; + + pipe = gst_pipeline_new (NULL); + fail_unless (pipe != NULL, "failed to create pipeline"); + + src = gst_element_factory_make ("audiotestsrc", "src"); + fail_unless (src != NULL, "Failed to create audiotestsrc element"); + + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + fail_unless (decodebin != NULL, "Failed to create decodebin element"); + + g_signal_connect (decodebin, "new-decoded-pad", + G_CALLBACK (new_decoded_pad_plug_fakesink_cb), pipe); + + fail_unless (gst_bin_add (GST_BIN (pipe), src)); + fail_unless (gst_bin_add (GST_BIN (pipe), decodebin)); + fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* wait for state change to complete */ + fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + /* there shouldn't be any errors */ + fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL); + + /* reset */ + gst_element_set_state (pipe, GST_STATE_NULL); + + sink = gst_bin_get_by_name (GST_BIN (pipe), "sink"); + gst_bin_remove (GST_BIN (pipe), sink); + gst_object_unref (sink); + + GST_LOG ("second try"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* wait for state change to complete */ + fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + /* there shouldn't be any errors */ + fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static Suite * +decodebin_suite (void) +{ + Suite *s = suite_create ("decodebin"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_text_plain_streams); + tcase_add_test (tc_chain, test_reuse_without_decoders); + + return s; +} + +GST_CHECK_MAIN (decodebin); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin2.c b/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin2.c new file mode 100644 index 0000000..84cf405 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/decodebin2.c @@ -0,0 +1,203 @@ +/* GStreamer unit tests for decodebin2 + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +static const gchar dummytext[] = + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown " + "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick " + "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog " + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy " + "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a " + "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps " + "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox " + "jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown " + "Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick " + "Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog " + "Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a Lazy " + "Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps over a " + "Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox Jumps " + "over a Lazy Frog Quick Brown Fox Jumps over a Lazy Frog Quick Brown Fox "; + +static void +src_handoff_cb (GstElement * src, GstBuffer * buf, GstPad * pad, gpointer data) +{ + GST_BUFFER_DATA (buf) = (guint8 *) dummytext; + GST_BUFFER_SIZE (buf) = sizeof (dummytext); + GST_BUFFER_OFFSET (buf) = 0; + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); +} + +static void +decodebin_new_decoded_pad_cb (GstElement * decodebin, GstPad * pad, + gboolean last, gboolean * p_flag) +{ + /* we should not be reached */ + fail_unless (decodebin == NULL, "new-decoded-pad should not be emitted"); +} + +/* make sure that decodebin errors out instead of creating a new decoded pad + * if the entire stream is a plain text file */ +GST_START_TEST (test_text_plain_streams) +{ + GstElement *pipe, *src, *decodebin; + GstMessage *msg; + + pipe = gst_pipeline_new (NULL); + fail_unless (pipe != NULL, "failed to create pipeline"); + + src = gst_element_factory_make ("fakesrc", "src"); + fail_unless (src != NULL, "Failed to create fakesrc element"); + + g_object_set (src, "signal-handoffs", TRUE, NULL); + g_object_set (src, "num-buffers", 1, NULL); + g_object_set (src, "can-activate-pull", FALSE, NULL); + g_signal_connect (src, "handoff", G_CALLBACK (src_handoff_cb), NULL); + + decodebin = gst_element_factory_make ("decodebin2", "decodebin"); + fail_unless (decodebin != NULL, "Failed to create decodebin element"); + + g_signal_connect (decodebin, "new-decoded-pad", + G_CALLBACK (decodebin_new_decoded_pad_cb), NULL); + + fail_unless (gst_bin_add (GST_BIN (pipe), src)); + fail_unless (gst_bin_add (GST_BIN (pipe), decodebin)); + fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* it should error out at some point */ + msg = gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, -1); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + gst_message_unref (msg); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static void +new_decoded_pad_plug_fakesink_cb (GstElement * decodebin, GstPad * srcpad, + gboolean last, GstElement * pipeline) +{ + GstElement *sink; + GstPad *sinkpad; + + GST_LOG ("Linking fakesink"); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (sink != NULL, "Failed to create fakesink element"); + + gst_bin_add (GST_BIN (pipeline), sink); + + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK); + gst_object_unref (sinkpad); + + gst_element_set_state (sink, GST_STATE_PLAYING); +} + +GST_START_TEST (test_reuse_without_decoders) +{ + GstElement *pipe, *src, *decodebin, *sink; + + pipe = gst_pipeline_new (NULL); + fail_unless (pipe != NULL, "failed to create pipeline"); + + src = gst_element_factory_make ("audiotestsrc", "src"); + fail_unless (src != NULL, "Failed to create audiotestsrc element"); + + decodebin = gst_element_factory_make ("decodebin2", "decodebin"); + fail_unless (decodebin != NULL, "Failed to create decodebin element"); + + g_signal_connect (decodebin, "new-decoded-pad", + G_CALLBACK (new_decoded_pad_plug_fakesink_cb), pipe); + + fail_unless (gst_bin_add (GST_BIN (pipe), src)); + fail_unless (gst_bin_add (GST_BIN (pipe), decodebin)); + fail_unless (gst_element_link (src, decodebin), "can't link src<->decodebin"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* wait for state change to complete */ + fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + /* there shouldn't be any errors */ + fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL); + + /* reset */ + gst_element_set_state (pipe, GST_STATE_READY); + + sink = gst_bin_get_by_name (GST_BIN (pipe), "sink"); + gst_bin_remove (GST_BIN (pipe), sink); + gst_element_set_state (sink, GST_STATE_NULL); + gst_object_unref (sink); + + GST_LOG ("second try"); + + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* it's push-based, so should be async */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* wait for state change to complete */ + fail_unless_equals_int (gst_element_get_state (pipe, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + /* there shouldn't be any errors */ + fail_if (gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, 0) != NULL); + + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); +} + +GST_END_TEST; + +static Suite * +decodebin2_suite (void) +{ + Suite *s = suite_create ("decodebin2"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_text_plain_streams); + tcase_add_test (tc_chain, test_reuse_without_decoders); + + return s; +} + +GST_CHECK_MAIN (decodebin2); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/encodebin.c b/gst-plugins-base-subtitles0.10/tests/check/elements/encodebin.c new file mode 100644 index 0000000..77606cd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/encodebin.c @@ -0,0 +1,902 @@ +/* GStreamer unit test for gstprofile + * + * Copyright (C) <2009> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +/* Helper functions to create profiles */ + +static GstEncodingProfile * +create_ogg_vorbis_profile (guint presence, gchar * preset) +{ + GstEncodingContainerProfile *cprof; + GstCaps *ogg, *vorbis; + + ogg = gst_caps_new_simple ("application/ogg", NULL); + cprof = + gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg, + NULL); + gst_caps_unref (ogg); + + vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL); + fail_unless (gst_encoding_container_profile_add_profile (cprof, + (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, preset, + NULL, presence))); + gst_caps_unref (vorbis); + + return (GstEncodingProfile *) cprof; +} + +static GstEncodingProfile * +create_ogg_theora_vorbis_profile (guint theorapresence, guint vorbispresence) +{ + GstEncodingContainerProfile *prof; + GstCaps *ogg, *vorbis, *theora; + + ogg = gst_caps_new_simple ("application/ogg", NULL); + prof = + gst_encoding_container_profile_new ((gchar *) "myprofile", NULL, ogg, + NULL); + gst_caps_unref (ogg); + + vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL); + fail_unless (gst_encoding_container_profile_add_profile (prof, + (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL, + NULL, vorbispresence))); + gst_caps_unref (vorbis); + + theora = gst_caps_new_simple ("video/x-theora", NULL); + fail_unless (gst_encoding_container_profile_add_profile (prof, + (GstEncodingProfile *) gst_encoding_video_profile_new (theora, NULL, + NULL, theorapresence))); + gst_caps_unref (theora); + + return (GstEncodingProfile *) prof; +} + +static GstEncodingProfile * +create_vorbis_only_profile (void) +{ + GstEncodingProfile *prof; + GstCaps *vorbis; + + vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL); + prof = + (GstEncodingProfile *) gst_encoding_audio_profile_new (vorbis, NULL, NULL, + 0); + gst_caps_unref (vorbis); + + return prof; +} + +GST_START_TEST (test_encodebin_states) +{ + GstElement *ebin; + GstEncodingProfile *prof, *prof2; + GstCaps *ogg; + GstPad *srcpad; + GstPad *target; + + /* Create an encodebin and check that it correctly changes states + * according to whether a profile is set or not */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + + /* At this point, the ghostpad has *NO* target */ + target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad)); + fail_unless (target == NULL); + gst_object_unref (srcpad); + + /* No profile, + * switching to READY should succeed, + * but switching to PAUSED should fail + */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + /* Set a profile on encodebin... */ + ogg = gst_caps_new_simple ("application/ogg", NULL); + prof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *) + "myprofile", NULL, ogg, NULL); + gst_caps_unref (ogg); + + g_object_set (ebin, "profile", prof, NULL); + + /* ... and check the profile has been properly set */ + g_object_get (ebin, "profile", &prof2, NULL); + + fail_unless (gst_encoding_profile_is_equal (prof, prof2)); + + gst_encoding_profile_unref (prof); + gst_encoding_profile_unref (prof2); + + /* Make sure we can go to PAUSED */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* At this point, the source pad *HAS* a target */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + target = gst_ghost_pad_get_target (GST_GHOST_PAD (srcpad)); + fail_unless (target != NULL); + gst_object_unref (target); + gst_object_unref (srcpad); + + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_static) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstPad *srcpad, *sinkpad; + + /* Create an encodebin and check that it properly creates the sink pads + * for a single-stream profile with fixed presence */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* streamprofile that has a forced presence of 1 */ + prof = create_ogg_vorbis_profile (1, NULL); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + gst_object_unref (srcpad); + + /* Check if the audio sink pad was properly created */ + sinkpad = gst_element_get_static_pad (ebin, "audio_0"); + fail_unless (sinkpad != NULL); + gst_object_unref (sinkpad); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_nopreset_static) +{ + GstElement *ebin; + GstEncodingProfile *prof; + + /* Create an encodebin with a bogus preset and check it fails switching states */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* streamprofile that has a forced presence of 1 */ + prof = create_ogg_vorbis_profile (1, (gchar *) "nowaythispresetexists"); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + /* It will go to READY... */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* ... but to not PAUSED */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + gst_element_set_state (ebin, GST_STATE_NULL); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_dynamic) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstPad *srcpad, *sinkpad; + GstCaps *sinkcaps; + + /* Create an encodebin and check that it properly creates the sink pads + * for a single-stream profile with a unfixed presence */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* streamprofile that has non-forced presence */ + prof = create_ogg_vorbis_profile (0, NULL); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + gst_object_unref (srcpad); + + /* Check if the audio sink pad can be requested */ + sinkpad = gst_element_get_request_pad (ebin, "audio_0"); + fail_unless (sinkpad != NULL); + gst_element_release_request_pad (ebin, sinkpad); + gst_object_unref (sinkpad); + sinkpad = NULL; + + /* Check again with the 'request-pad' signal */ + sinkcaps = gst_caps_new_simple ("audio/x-raw-int", NULL); + g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad); + gst_caps_unref (sinkcaps); + fail_unless (sinkpad != NULL); + gst_element_release_request_pad (ebin, sinkpad); + gst_object_unref (sinkpad); + sinkpad = NULL; + + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_multiple_static) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora; + + /* Create an encodebin and check that it properly creates the sink pads */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* First try is with a streamprofile that has a forced presence of 1 */ + prof = create_ogg_theora_vorbis_profile (1, 1); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + gst_object_unref (srcpad); + + /* Check if the audio sink pad was properly created */ + sinkpadvorbis = gst_element_get_static_pad (ebin, "audio_0"); + fail_unless (sinkpadvorbis != NULL); + gst_object_unref (sinkpadvorbis); + + /* Check if the video sink pad was properly created */ + sinkpadtheora = gst_element_get_static_pad (ebin, "video_1"); + fail_unless (sinkpadtheora != NULL); + gst_object_unref (sinkpadtheora); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_multiple_dynamic) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstPad *srcpad, *sinkpadvorbis, *sinkpadtheora; + + /* Create an encodebin and check that it properly creates the sink pads + * for a multiple-stream with unfixed presence */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* multi-stream profile that has non-forced presence */ + prof = create_ogg_theora_vorbis_profile (0, 0); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + gst_object_unref (srcpad); + + /* Check if the audio sink pad was properly created */ + sinkpadvorbis = gst_element_get_request_pad (ebin, "audio_0"); + fail_unless (sinkpadvorbis != NULL); + + /* Check if the video sink pad was properly created */ + sinkpadtheora = gst_element_get_request_pad (ebin, "video_1"); + fail_unless (sinkpadtheora != NULL); + + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadvorbis); + gst_object_unref (sinkpadvorbis); + gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpadtheora); + gst_object_unref (sinkpadtheora); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_sink_pads_dynamic_encoder) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstPad *srcpad, *sinkpad = NULL; + GstCaps *vorbiscaps; + + /* Create an encodebin and check that it properly creates the sink pads + * for a single-stream profile with a unfixed presence */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* streamprofile that has non-forced presence */ + prof = create_ogg_vorbis_profile (0, NULL); + + g_object_set (ebin, "profile", prof, NULL); + + gst_encoding_profile_unref (prof); + + /* Check if the source pad was properly created */ + srcpad = gst_element_get_static_pad (ebin, "src"); + fail_unless (srcpad != NULL); + gst_object_unref (srcpad); + + /* Check if the audio sink pad was properly created */ + vorbiscaps = gst_caps_from_string ("audio/x-vorbis,channels=2,rate=44100"); + g_signal_emit_by_name (ebin, "request-pad", vorbiscaps, &sinkpad); + gst_caps_unref (vorbiscaps); + fail_unless (sinkpad != NULL); + gst_element_release_request_pad (ebin, sinkpad); + gst_object_unref (sinkpad); + + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +GST_START_TEST (test_encodebin_render_audio_static) +{ + GstElement *ebin, *pipeline, *audiotestsrc, *fakesink; + GstEncodingProfile *prof; + GstBus *bus; + gboolean done = FALSE; + + /* Create an encodebin and render 5s of vorbis/ogg */ + + pipeline = gst_pipeline_new ("encodebin-pipeline"); + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 10, NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + + prof = create_ogg_vorbis_profile (1, NULL); + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL); + + fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL)); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *msg; + + /* poll the bus until we get EOS without any errors */ + msg = gst_bus_timed_pop (bus, GST_SECOND / 10); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + fail ("GST_MESSAGE_ERROR"); + break; + case GST_MESSAGE_EOS: + done = TRUE; + break; + default: + break; + } + gst_message_unref (msg); + } + } + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_encodebin_render_audio_only_static) +{ + GstElement *ebin, *pipeline, *audiotestsrc, *fakesink; + GstEncodingProfile *prof; + GstBus *bus; + gboolean done = FALSE; + GstPad *sinkpad; + GstCaps *sinkcaps; + + /* Create an encodebin and render 5s of vorbis only */ + + pipeline = gst_pipeline_new ("encodebin-pipeline"); + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 10, NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + + prof = create_vorbis_only_profile (); + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL); + + fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL)); + + /* Requesting a new pad should fail */ + ASSERT_CRITICAL (gst_element_get_request_pad (ebin, "audio_0")); + + sinkcaps = gst_caps_new_simple ("audio/x-raw-int", NULL); + g_signal_emit_by_name (ebin, "request-pad", sinkcaps, &sinkpad); + gst_caps_unref (sinkcaps); + fail_if (sinkpad != NULL); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *msg; + + /* poll the bus until we get EOS without any errors */ + msg = gst_bus_timed_pop (bus, GST_SECOND / 10); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + fail ("GST_MESSAGE_ERROR"); + break; + case GST_MESSAGE_EOS: + done = TRUE; + break; + default: + break; + } + gst_message_unref (msg); + } + } + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_encodebin_render_audio_dynamic) +{ + GstElement *ebin, *pipeline, *audiotestsrc, *fakesink; + GstEncodingProfile *prof; + GstBus *bus; + GstPad *sinkpad, *srcpad; + gboolean done = FALSE; + + /* Create an encodebin and render 5s of vorbis/ogg */ + + pipeline = gst_pipeline_new ("encodebin-pipeline"); + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 10, NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + + prof = create_ogg_vorbis_profile (0, NULL); + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, ebin, fakesink, NULL); + + srcpad = gst_element_get_static_pad (audiotestsrc, "src"); + fail_unless (srcpad != NULL); + + sinkpad = gst_element_get_request_pad (ebin, "audio_0"); + fail_unless (sinkpad != NULL); + + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad), GST_PAD_LINK_OK); + + gst_object_unref (srcpad); + + fail_unless (gst_element_link (ebin, fakesink)); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *msg; + + /* poll the bus until we get EOS without any errors */ + msg = gst_bus_timed_pop (bus, GST_SECOND / 10); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + fail ("GST_MESSAGE_ERROR"); + break; + case GST_MESSAGE_EOS: + done = TRUE; + break; + default: + break; + } + gst_message_unref (msg); + } + } + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad); + gst_object_unref (sinkpad); + + gst_object_unref (bus); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_encodebin_render_audio_video_static) +{ + GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink; + GstEncodingProfile *prof; + GstBus *bus; + gboolean done = FALSE; + + /* Create an encodebin and render 5s of vorbis/ogg */ + + pipeline = gst_pipeline_new ("encodebin-pipeline"); + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 10, NULL); + videotestsrc = gst_element_factory_make ("videotestsrc", NULL); + g_object_set (videotestsrc, "num-buffers", 5, NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + + prof = create_ogg_theora_vorbis_profile (1, 1); + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin, + fakesink, NULL); + + fail_unless (gst_element_link (videotestsrc, ebin)); + fail_unless (gst_element_link_many (audiotestsrc, ebin, fakesink, NULL)); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *msg; + + /* poll the bus until we get EOS without any errors */ + msg = gst_bus_timed_pop (bus, GST_SECOND / 10); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + fail ("GST_MESSAGE_ERROR"); + break; + case GST_MESSAGE_EOS: + done = TRUE; + break; + default: + break; + } + gst_message_unref (msg); + } + } + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (bus); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_encodebin_render_audio_video_dynamic) +{ + GstElement *ebin, *pipeline, *audiotestsrc, *videotestsrc, *fakesink; + GstEncodingProfile *prof; + GstBus *bus; + gboolean done = FALSE; + GstPad *sinkpad1, *sinkpad2, *srcpad; + + /* Create an encodebin and render 5s of vorbis/ogg */ + + pipeline = gst_pipeline_new ("encodebin-pipeline"); + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 10, NULL); + videotestsrc = gst_element_factory_make ("videotestsrc", NULL); + g_object_set (videotestsrc, "num-buffers", 5, NULL); + fakesink = gst_element_factory_make ("fakesink", NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + + prof = create_ogg_theora_vorbis_profile (0, 0); + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + gst_bin_add_many ((GstBin *) pipeline, audiotestsrc, videotestsrc, ebin, + fakesink, NULL); + + fail_unless (gst_element_link (ebin, fakesink)); + + srcpad = gst_element_get_static_pad (audiotestsrc, "src"); + sinkpad1 = gst_element_get_request_pad (ebin, "audio_0"); + fail_unless (srcpad != NULL); + fail_unless (sinkpad1 != NULL); + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad1), GST_PAD_LINK_OK); + gst_object_unref (srcpad); + + srcpad = gst_element_get_static_pad (videotestsrc, "src"); + sinkpad2 = gst_element_get_request_pad (ebin, "video_1"); + fail_unless_equals_int (gst_pad_link (srcpad, sinkpad2), GST_PAD_LINK_OK); + gst_object_unref (srcpad); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + while (!done) { + GstMessage *msg; + + /* poll the bus until we get EOS without any errors */ + msg = gst_bus_timed_pop (bus, GST_SECOND / 10); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + fail ("GST_MESSAGE_ERROR"); + break; + case GST_MESSAGE_EOS: + done = TRUE; + break; + default: + break; + } + gst_message_unref (msg); + } + } + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad1); + gst_object_unref (sinkpad1); + gst_element_release_request_pad (GST_ELEMENT (ebin), sinkpad2); + gst_object_unref (sinkpad2); + + gst_object_unref (bus); + + gst_object_unref (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_encodebin_impossible_element_combination) +{ + GstElement *ebin; + GstEncodingProfile *prof; + GstCaps *ogg, *x264; + + ebin = gst_element_factory_make ("x264enc", NULL); + if (ebin == NULL) { + GST_DEBUG ("No available h264 encoder, skipping test"); + return; + } + gst_object_unref (ebin); + + /* Make sure that impossible combinations of encoders and muxer + * properly fail. In this case we try putting h264 in ogg. + * + * To properly test we abort early, we use a presence of zero for the + * h264 stream profile. */ + + ebin = gst_element_factory_make ("encodebin", NULL); + + ogg = gst_caps_new_simple ("application/ogg", NULL); + prof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *) + "myprofile", NULL, ogg, NULL); + gst_caps_unref (ogg); + + x264 = gst_caps_new_simple ("video/x-h264", NULL); + fail_unless (gst_encoding_container_profile_add_profile + (GST_ENCODING_CONTAINER_PROFILE (prof), + (GstEncodingProfile *) gst_encoding_video_profile_new (x264, NULL, + NULL, 0))); + gst_caps_unref (x264); + + g_object_set (ebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + + /* It will go to READY... */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + /* ... but to not PAUSED */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + gst_element_set_state (ebin, GST_STATE_NULL); + + gst_object_unref (ebin); +}; + +GST_END_TEST; + +static void +_test_encodebin_reuse (GstEncodingProfile * prof1, GstEncodingProfile * prof2) +{ + GstElement *ebin; + + ebin = gst_element_factory_make ("encodebin", NULL); + + /* Set a profile on encodebin... */ + if (prof1) + g_object_set (ebin, "profile", prof1, NULL); + + /* Make sure we can go to PAUSED */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + if (prof2) + g_object_set (ebin, "profile", prof2, NULL); + + /* Make sure we can go to PLAYING */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + + /* Set back to NULL */ + fail_unless_equals_int (gst_element_set_state (ebin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (ebin); +} + +GST_START_TEST (test_encodebin_reuse) +{ + GstEncodingProfile *prof1; + GstEncodingProfile *prof2; + GstEncodingProfile *prof3; + GstCaps *caps; + + caps = gst_caps_new_simple ("application/ogg", NULL); + prof1 = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *) + "myprofile", NULL, caps, NULL); + gst_caps_unref (caps); + + prof2 = create_ogg_theora_vorbis_profile (1, 1); + prof3 = create_vorbis_only_profile (); + + _test_encodebin_reuse (prof1, NULL); + _test_encodebin_reuse (prof1, prof1); + + _test_encodebin_reuse (prof1, prof2); + + _test_encodebin_reuse (prof2, prof3); + + gst_encoding_profile_unref (prof1); + gst_encoding_profile_unref (prof2); + gst_encoding_profile_unref (prof3); +}; + +GST_END_TEST; + + +static Suite * +encodebin_suite (void) +{ + Suite *s = suite_create ("encodebin element"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_encodebin_states); + tcase_add_test (tc_chain, test_encodebin_sink_pads_static); + tcase_add_test (tc_chain, test_encodebin_sink_pads_nopreset_static); + tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic); + tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_static); + tcase_add_test (tc_chain, test_encodebin_sink_pads_multiple_dynamic); + tcase_add_test (tc_chain, test_encodebin_sink_pads_dynamic_encoder); + tcase_add_test (tc_chain, test_encodebin_render_audio_static); + tcase_add_test (tc_chain, test_encodebin_render_audio_only_static); + tcase_add_test (tc_chain, test_encodebin_render_audio_dynamic); + tcase_add_test (tc_chain, test_encodebin_render_audio_video_static); + tcase_add_test (tc_chain, test_encodebin_render_audio_video_dynamic); + tcase_add_test (tc_chain, test_encodebin_impossible_element_combination); + tcase_add_test (tc_chain, test_encodebin_reuse); + + return s; +} + +GST_CHECK_MAIN (encodebin); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/ffmpegcolorspace.c b/gst-plugins-base-subtitles0.10/tests/check/elements/ffmpegcolorspace.c new file mode 100644 index 0000000..60179c6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/ffmpegcolorspace.c @@ -0,0 +1,439 @@ +/* GStreamer + * + * unit test for ffmpegcolorspace + * + * Copyright (C) <2006> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#ifdef HAVE_VALGRIND +# include +#endif + +#include + +#include + +typedef struct _RGBFormat +{ + const gchar *nick; + guint bpp, depth; + guint32 red_mask, green_mask, blue_mask, alpha_mask; + guint endianness; +} RGBFormat; + +typedef struct _RGBConversion +{ + RGBFormat from_fmt; + RGBFormat to_fmt; + GstCaps *from_caps; + GstCaps *to_caps; +} RGBConversion; + +static GstCaps * +rgb_format_to_caps (RGBFormat * fmt) +{ + GstCaps *caps; + + g_assert (fmt != NULL); + g_assert (fmt->endianness != 0); + + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, fmt->bpp, + "depth", G_TYPE_INT, fmt->depth, + "red_mask", G_TYPE_INT, fmt->red_mask, + "green_mask", G_TYPE_INT, fmt->green_mask, + "blue_mask", G_TYPE_INT, fmt->blue_mask, + "width", G_TYPE_INT, 16, "height", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, fmt->endianness, + "framerate", GST_TYPE_FRACTION, 1, 1, NULL); + + fail_unless (fmt->alpha_mask == 0 || fmt->bpp == 32); + + if (fmt->alpha_mask != 0) { + gst_structure_set (gst_caps_get_structure (caps, 0), + "alpha_mask", G_TYPE_INT, fmt->alpha_mask, NULL); + } + + return caps; +} + +static GList * +create_rgb_conversions (void) +{ + const RGBFormat rgb_formats[] = { + { + "RGBA", 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff, 0}, { + "ARGB", 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000, 0}, { + "BGRA", 32, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff, 0}, { + "ABGR", 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000, 0}, { + "RGBx", 32, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000, 0}, { + "xRGB", 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, { + "BGRx", 32, 24, 0x0000ff00, 0x00ff0000, 0xff000000, 0x00000000, 0}, { + "xBGR", 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, { + "RGB ", 24, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000, 0}, { + "BGR ", 24, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000, 0}, { + "RGB565", 16, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, 0}, { + "xRGB1555", 16, 15, 0x00007c00, 0x000003e0, 0x0000001f, 0x0000000, 0} + }; + const struct + { + guint from_endianness, to_endianness; + } end_arr[4] = { + { + G_LITTLE_ENDIAN, G_LITTLE_ENDIAN}, { + G_BIG_ENDIAN, G_LITTLE_ENDIAN}, { + G_LITTLE_ENDIAN, G_BIG_ENDIAN}, { + G_BIG_ENDIAN, G_BIG_ENDIAN} + }; + GList *conversions = NULL; + guint from_fmt, to_fmt; + + for (from_fmt = 0; from_fmt < G_N_ELEMENTS (rgb_formats); ++from_fmt) { + for (to_fmt = 0; to_fmt < G_N_ELEMENTS (rgb_formats); ++to_fmt) { + guint i; + + for (i = 0; i < 4; ++i) { + RGBConversion *conversion; + + conversion = g_new0 (RGBConversion, 1); + conversion->from_fmt = rgb_formats[from_fmt]; + conversion->to_fmt = rgb_formats[to_fmt]; + conversion->from_fmt.endianness = end_arr[i].from_endianness; + conversion->to_fmt.endianness = end_arr[i].to_endianness; + conversion->from_caps = rgb_format_to_caps (&conversion->from_fmt); + conversion->to_caps = rgb_format_to_caps (&conversion->to_fmt); + conversions = g_list_prepend (conversions, conversion); + } + } + } + + return g_list_reverse (conversions); +} + +static void +rgb_conversion_free (RGBConversion * conv) +{ + gst_caps_unref (conv->from_caps); + gst_caps_unref (conv->to_caps); + memset (conv, 0x99, sizeof (RGBConversion)); + g_free (conv); +} + +static guint32 +right_shift_colour (guint32 mask, guint32 pixel) +{ + if (mask == 0) + return 0; + + pixel = pixel & mask; + while ((mask & 0x01) == 0) { + mask = mask >> 1; + pixel = pixel >> 1; + } + + return pixel; +} + +static guint8 +fix_expected_colour (guint32 col_mask, guint8 col_expected) +{ + guint32 mask; + gint last = g_bit_nth_msf (col_mask, -1); + gint first = g_bit_nth_lsf (col_mask, -1); + + mask = 1 << (last - first + 1); + mask -= 1; + + g_assert (col_expected == 0x00 || col_expected == 0xff); + + /* this only works because we only check for all-bits-set or no-bits-set */ + return col_expected & mask; +} + +static void +check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask, + guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected, + guint8 b_expected, guint endianness, guint bpp, guint depth) +{ + guint32 pixel, red, green, blue, alpha; + + switch (bpp) { + case 32:{ + if (endianness == G_LITTLE_ENDIAN) + pixel = GST_READ_UINT32_LE (pixels); + else + pixel = GST_READ_UINT32_BE (pixels); + break; + } + case 24:{ + if (endianness == G_BIG_ENDIAN) { + pixel = (GST_READ_UINT8 (pixels) << 16) | + (GST_READ_UINT8 (pixels + 1) << 8) | + (GST_READ_UINT8 (pixels + 2) << 0); + } else { + pixel = (GST_READ_UINT8 (pixels + 2) << 16) | + (GST_READ_UINT8 (pixels + 1) << 8) | + (GST_READ_UINT8 (pixels + 0) << 0); + } + break; + } + case 16:{ + if (endianness == G_LITTLE_ENDIAN) + pixel = GST_READ_UINT16_LE (pixels); + else + pixel = GST_READ_UINT16_BE (pixels); + break; + } + default: + g_return_if_reached (); + } + + red = right_shift_colour (r_mask, pixel); + green = right_shift_colour (g_mask, pixel); + blue = right_shift_colour (b_mask, pixel); + alpha = right_shift_colour (a_mask, pixel); + + /* can't enable this by default, valgrind will complain about accessing + * uninitialised memory for the depth=24,bpp=32 formats ... */ + /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x", + pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */ + + /* fix up the mask (for rgb15/16) */ + if (bpp == 16) { + r_expected = fix_expected_colour (r_mask, r_expected); + g_expected = fix_expected_colour (g_mask, g_expected); + b_expected = fix_expected_colour (b_mask, b_expected); + } + + fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x " + "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x Pixel: 0x%08x", r_expected, red, + pixels[0], pixels[1], pixels[2], pixels[3], pixel); + fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x " + "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x Pixel: 0x%08x", g_expected, green, + pixels[0], pixels[1], pixels[2], pixels[3], pixel); + fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x " + "Bytes: 0x%02x 0x%02x 0x%02x 0x%02x Pixel: 0x%08x", b_expected, blue, + pixels[0], pixels[1], pixels[2], pixels[3], pixel); + +// FIXME: fix alpha check +// fail_unless (a_mask == 0 || alpha != 0); /* better than nothing */ +} + +static void +got_buf_cb (GstElement * sink, GstBuffer * new_buf, GstPad * pad, + GstBuffer ** p_old_buf) +{ + gst_buffer_replace (p_old_buf, new_buf); +} + +/* Note: lots of this code here is also in the videotestsrc.c unit test */ +GST_START_TEST (test_rgb_to_rgb) +{ + const struct + { + const gchar *pattern_name; + gint pattern_enum; + guint8 r_expected; + guint8 g_expected; + guint8 b_expected; + } test_patterns[] = { + { + "white", 3, 0xff, 0xff, 0xff}, { + "red", 4, 0xff, 0x00, 0x00}, { + "green", 5, 0x00, 0xff, 0x00}, { + "blue", 6, 0x00, 0x00, 0xff}, { + "black", 2, 0x00, 0x00, 0x00} + }; + GstElement *pipeline, *src, *filter1, *csp, *filter2, *sink; + const GstCaps *template_caps; + GstBuffer *buf = NULL; + GstPad *srcpad; + GList *conversions, *l; + gint p; + + /* test check function */ + fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22); + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("videotestsrc"); + filter1 = gst_check_setup_element ("capsfilter"); + csp = gst_check_setup_element ("ffmpegcolorspace"); + filter2 = gst_element_factory_make ("capsfilter", "to_filter"); + sink = gst_check_setup_element ("fakesink"); + + gst_bin_add_many (GST_BIN (pipeline), src, filter1, csp, filter2, sink, NULL); + + fail_unless (gst_element_link (src, filter1)); + fail_unless (gst_element_link (filter1, csp)); + fail_unless (gst_element_link (csp, filter2)); + fail_unless (gst_element_link (filter2, sink)); + + srcpad = gst_element_get_static_pad (src, "src"); + template_caps = gst_pad_get_pad_template_caps (srcpad); + gst_object_unref (srcpad); + + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &buf); + + GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps); + + conversions = create_rgb_conversions (); + + for (l = conversions; l != NULL; l = l->next) { + RGBConversion *conv = (RGBConversion *) l->data; + + /* does videotestsrc support the from_caps? */ + if (!gst_caps_is_subset (conv->from_caps, template_caps)) { + GST_DEBUG ("videotestsrc doesn't support from_caps %" GST_PTR_FORMAT, + conv->from_caps); + continue; + } + + /* caps are supported, let's run some tests then ... */ + for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) { + GstStateChangeReturn state_ret; + RGBFormat *from = &conv->from_fmt; + RGBFormat *to = &conv->to_fmt; + + /* trick compiler into thinking from is used, might throw warning + * otherwise if the debugging system is disabled */ + fail_unless (from != NULL); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL); + + GST_INFO ("%5s %u/%u %08x %08x %08x %08x %u => " + "%5s %u/%u %08x %08x %08x %08x %u, pattern=%s", + from->nick, from->bpp, from->depth, from->red_mask, + from->green_mask, from->blue_mask, from->alpha_mask, + from->endianness, to->nick, to->bpp, to->depth, to->red_mask, + to->green_mask, to->blue_mask, to->alpha_mask, to->endianness, + test_patterns[p].pattern_name); + + /* now get videotestsrc to produce a buffer with the given caps */ + g_object_set (filter1, "caps", conv->from_caps, NULL); + + /* ... and force ffmpegcolorspace to convert to our target caps */ + g_object_set (filter2, "caps", conv->to_caps, NULL); + + state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (state_ret == GST_STATE_CHANGE_FAILURE) { + GstMessage *msg; + GError *err = NULL; + + msg = gst_bus_poll (GST_ELEMENT_BUS (pipeline), GST_MESSAGE_ERROR, 0); + fail_if (msg == NULL, "expected ERROR message on the bus"); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + if (msg->src == GST_OBJECT_CAST (src) && + err->code == GST_STREAM_ERROR_FORMAT) { + GST_DEBUG ("ffmpegcolorspace does not support this conversion"); + gst_message_unref (msg); + g_error_free (err); + continue; + } + fail_unless (state_ret != GST_STATE_CHANGE_FAILURE, + "pipeline _set_state() to PAUSED failed: %s", err->message); + } + + state_ret = gst_element_get_state (pipeline, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS, + "pipeline failed going to PAUSED state"); + + state_ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + fail_unless (buf != NULL); + + /* check buffer caps */ + { + GstStructure *s; + gint v; + + fail_unless (GST_BUFFER_CAPS (buf) != NULL); + s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + fail_unless (gst_structure_get_int (s, "bpp", &v)); + fail_unless_equals_int (v, to->bpp); + fail_unless (gst_structure_get_int (s, "depth", &v)); + fail_unless_equals_int (v, to->depth); + fail_unless (gst_structure_get_int (s, "red_mask", &v)); + fail_unless_equals_int (v, to->red_mask); + fail_unless (gst_structure_get_int (s, "green_mask", &v)); + fail_unless_equals_int (v, to->green_mask); + fail_unless (gst_structure_get_int (s, "blue_mask", &v)); + fail_unless_equals_int (v, to->blue_mask); + /* there mustn't be an alpha_mask if there's no alpha component */ + if (to->depth == 32) { + fail_unless (gst_structure_get_int (s, "alpha_mask", &v)); + fail_unless_equals_int (v, to->alpha_mask); + } else { + fail_unless (gst_structure_get_value (s, "alpha_mask") == NULL); + } + } + + /* now check the top-left pixel */ + check_rgb_buf (GST_BUFFER_DATA (buf), to->red_mask, + to->green_mask, to->blue_mask, to->alpha_mask, + test_patterns[p].r_expected, test_patterns[p].g_expected, + test_patterns[p].b_expected, to->endianness, to->bpp, to->depth); + + gst_buffer_unref (buf); + buf = NULL; + } + } + + g_list_foreach (conversions, (GFunc) rgb_conversion_free, NULL); + g_list_free (conversions); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +ffmpegcolorspace_suite (void) +{ + Suite *s = suite_create ("ffmpegcolorspace"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + +#ifdef HAVE_VALGRIND + if (RUNNING_ON_VALGRIND) { + /* otherwise valgrind errors out when liboil probes CPU extensions + * during which it causes SIGILLs etc. to be fired */ + g_setenv ("OIL_CPU_FLAGS", "0", 0); + /* test_rgb_formats takes a bit longer, so increase timeout */ + tcase_set_timeout (tc_chain, 10 * 60); + } +#endif + + /* FIXME: add tests for YUV <=> YUV and YUV <=> RGB */ + tcase_add_test (tc_chain, test_rgb_to_rgb); + + return s; +} + +GST_CHECK_MAIN (ffmpegcolorspace); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/gdpdepay.c b/gst-plugins-base-subtitles0.10/tests/check/elements/gdpdepay.c new file mode 100644 index 0000000..3ee83c8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/gdpdepay.c @@ -0,0 +1,413 @@ +/* GStreamer + * + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "config.h" +#include +#include + +#include +#include + +/* 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, *myshsinkpad; + +#define AUDIO_CAPS_TEMPLATE_STRING \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 8 ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) {8, 16}, " \ + "depth = (int) {8, 16}, " \ + "signed = (boolean) true" + +#define AUDIO_CAPS_STRING \ + "audio/x-raw-int, " \ + "rate = (int) 1000, " \ + "channels = (int) 2, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) true" + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (AUDIO_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gdp") + ); + +/* takes over reference for outcaps */ +static GstElement * +setup_gdpdepay (void) +{ + GstElement *gdpdepay; + + GST_DEBUG ("setup_gdpdepay"); + gdpdepay = gst_check_setup_element ("gdpdepay"); + mysrcpad = gst_check_setup_src_pad (gdpdepay, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (gdpdepay, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return gdpdepay; +} + +static void +cleanup_gdpdepay (GstElement * gdpdepay) +{ + GST_DEBUG ("cleanup_gdpdepay"); + + gst_pad_set_active (mysrcpad, FALSE); + if (mysinkpad) + gst_pad_set_active (mysinkpad, FALSE); + if (myshsinkpad) + gst_pad_set_active (myshsinkpad, FALSE); + gst_check_teardown_src_pad (gdpdepay); + gst_check_teardown_sink_pad (gdpdepay); + gst_check_teardown_element (gdpdepay); + mysinkpad = NULL; + myshsinkpad = NULL; +} + +static void +gdpdepay_push_per_byte (const gchar * reason, guint8 * bytes, guint length) +{ + int i; + GstBuffer *inbuffer; + + for (i = 0; i < length; ++i) { + inbuffer = gst_buffer_new_and_alloc (1); + GST_BUFFER_DATA (inbuffer)[0] = bytes[i]; + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK, + "%s: failed pushing byte buffer", reason); + } +} + +GST_START_TEST (test_audio_per_byte) +{ + GstCaps *caps; + GstPad *srcpad; + GstElement *gdpdepay; + GstBuffer *buffer, *outbuffer; + guint8 *header, *payload; + guint len; + GstDPPacketizer *pk; + + pk = gst_dp_packetizer_new (GST_DP_VERSION_1_0); + + gdpdepay = setup_gdpdepay (); + srcpad = gst_element_get_static_pad (gdpdepay, "src"); + + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + caps = gst_pad_get_caps (srcpad); + fail_unless (gst_caps_is_any (caps)); + gst_caps_unref (caps); + fail_if (gst_pad_get_negotiated_caps (srcpad)); + + /* create caps and buffer packets and push them */ + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + fail_unless (pk->packet_from_caps (caps, 0, &len, &header, &payload)); + gst_caps_unref (caps); + gdpdepay_push_per_byte ("caps header", header, len); + fail_unless_equals_int (g_list_length (buffers), 0); + gdpdepay_push_per_byte ("caps payload", payload, + gst_dp_header_payload_length (header)); + fail_unless_equals_int (g_list_length (buffers), 0); + caps = gst_pad_get_caps (srcpad); + fail_if (gst_caps_is_any (caps)); + gst_caps_unref (caps); + + g_free (header); + g_free (payload); + + buffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buffer), "f00d", 4); + GST_BUFFER_TIMESTAMP (buffer) = GST_SECOND; + GST_BUFFER_DURATION (buffer) = GST_SECOND / 10; + fail_unless (pk->header_from_buffer (buffer, 0, &len, &header)); + gdpdepay_push_per_byte ("buffer header", header, len); + fail_unless_equals_int (g_list_length (buffers), 0); + gdpdepay_push_per_byte ("buffer payload", GST_BUFFER_DATA (buffer), + gst_dp_header_payload_length (header)); + g_free (header); + gst_buffer_unref (buffer); + + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (outbuffer), GST_SECOND); + fail_unless_equals_uint64 (GST_BUFFER_DURATION (outbuffer), GST_SECOND / 10); + + buffers = g_list_remove (buffers, outbuffer); + gst_buffer_unref (outbuffer); + + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + ASSERT_OBJECT_REFCOUNT (gdpdepay, "gdpdepay", 1); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + gst_object_unref (srcpad); + cleanup_gdpdepay (gdpdepay); + + gst_dp_packetizer_free (pk); +} + +GST_END_TEST; + +GST_START_TEST (test_audio_in_one_buffer) +{ + GstCaps *caps; + GstPad *srcpad; + GstElement *gdpdepay; + GstBuffer *buffer, *inbuffer; + guint8 *caps_header, *caps_payload, *buf_header; + guint header_len, payload_len; + guint i; + GstDPPacketizer *pk; + + pk = gst_dp_packetizer_new (GST_DP_VERSION_1_0); + + gdpdepay = setup_gdpdepay (); + srcpad = gst_element_get_static_pad (gdpdepay, "src"); + + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + /* make sure no caps are set yet */ + caps = gst_pad_get_caps (srcpad); + fail_unless (gst_caps_is_any (caps)); + gst_caps_unref (caps); + fail_if (gst_pad_get_negotiated_caps (srcpad)); + + /* create caps and buffer packets and push them as one buffer */ + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + fail_unless (pk->packet_from_caps (caps, 0, &header_len, &caps_header, + &caps_payload)); + + buffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buffer), "f00d", 4); + fail_unless (pk->header_from_buffer (buffer, 0, &header_len, &buf_header)); + + payload_len = gst_dp_header_payload_length (caps_header); + + inbuffer = gst_buffer_new_and_alloc (2 * GST_DP_HEADER_LENGTH + + payload_len + GST_BUFFER_SIZE (buffer)); + memcpy (GST_BUFFER_DATA (inbuffer), caps_header, GST_DP_HEADER_LENGTH); + i = GST_DP_HEADER_LENGTH; + memcpy (GST_BUFFER_DATA (inbuffer) + i, caps_payload, payload_len); + i += payload_len; + memcpy (GST_BUFFER_DATA (inbuffer) + i, buf_header, GST_DP_HEADER_LENGTH); + i += GST_DP_HEADER_LENGTH; + memcpy (GST_BUFFER_DATA (inbuffer) + i, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + + gst_caps_unref (caps); + gst_buffer_unref (buffer); + + g_free (caps_header); + g_free (caps_payload); + g_free (buf_header); + + /* now push it */ + gst_pad_push (mysrcpad, inbuffer); + + /* the buffer is still queued */ + fail_unless_equals_int (g_list_length (buffers), 1); + + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_object_unref (srcpad); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdpdepay, "gdpdepay", 1); + cleanup_gdpdepay (gdpdepay); + + gst_dp_packetizer_free (pk); +} + +GST_END_TEST; + +static GstStaticPadTemplate shsinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gst-test-streamheader") + ); + +static GstElement * +setup_gdpdepay_streamheader (void) +{ + GstElement *gdpdepay; + + GST_DEBUG ("setup_gdpdepay"); + gdpdepay = gst_check_setup_element ("gdpdepay"); + mysrcpad = gst_check_setup_src_pad (gdpdepay, &srctemplate, NULL); + myshsinkpad = gst_check_setup_sink_pad (gdpdepay, &shsinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (myshsinkpad, TRUE); + + return gdpdepay; +} + +/* this tests deserialization of a GDP stream where the serialized caps + * have a streamheader set */ +GST_START_TEST (test_streamheader) +{ + GstCaps *caps, *padcaps; + GstPad *srcpad; + GstElement *gdpdepay; + GstBuffer *buffer, *inbuffer, *outbuffer, *shbuffer; + guint8 *caps_header, *caps_payload, *buf_header; + guint header_len, payload_len; + guint i; + GstStructure *structure; + GValue array = { 0 }; + GValue value = { 0 }; + GstDPPacketizer *pk; + + pk = gst_dp_packetizer_new (GST_DP_VERSION_1_0); + + gdpdepay = setup_gdpdepay_streamheader (); + srcpad = gst_element_get_static_pad (gdpdepay, "src"); + ASSERT_OBJECT_REFCOUNT (gdpdepay, "gdpdepay", 1); + + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + /* make sure no caps are set yet */ + caps = gst_pad_get_caps (srcpad); + fail_unless (gst_caps_is_any (caps)); + gst_caps_unref (caps); + fail_if (gst_pad_get_negotiated_caps (srcpad)); + + /* create a streamheader buffer and the caps containing it */ + caps = gst_caps_from_string ("application/x-gst-test-streamheader"); + structure = gst_caps_get_structure (caps, 0); + buffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buffer), "f00d", 4); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS); + g_value_init (&array, GST_TYPE_ARRAY); + g_value_init (&value, GST_TYPE_BUFFER); + shbuffer = gst_buffer_copy (buffer); + gst_value_set_buffer (&value, shbuffer); + gst_buffer_unref (shbuffer); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + + gst_buffer_set_caps (buffer, caps); + + /* create GDP packets for the caps and the buffer, and put them in one + * GDP buffer */ + fail_unless (pk->packet_from_caps (caps, 0, &header_len, &caps_header, + &caps_payload)); + + fail_unless (pk->header_from_buffer (buffer, 0, &header_len, &buf_header)); + + payload_len = gst_dp_header_payload_length (caps_header); + + inbuffer = gst_buffer_new_and_alloc (2 * GST_DP_HEADER_LENGTH + + payload_len + GST_BUFFER_SIZE (buffer)); + memcpy (GST_BUFFER_DATA (inbuffer), caps_header, GST_DP_HEADER_LENGTH); + i = GST_DP_HEADER_LENGTH; + memcpy (GST_BUFFER_DATA (inbuffer) + i, caps_payload, payload_len); + i += payload_len; + memcpy (GST_BUFFER_DATA (inbuffer) + i, buf_header, GST_DP_HEADER_LENGTH); + i += GST_DP_HEADER_LENGTH; + memcpy (GST_BUFFER_DATA (inbuffer) + i, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + + gst_caps_unref (caps); + gst_buffer_unref (buffer); + + g_free (caps_header); + g_free (caps_payload); + g_free (buf_header); + + /* now push it */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_pad_push (mysrcpad, inbuffer); + + /* our only output buffer is the streamheader buffer */ + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + fail_unless (GST_BUFFER_FLAG_IS_SET (outbuffer, GST_BUFFER_FLAG_IN_CAPS)); + + padcaps = gst_pad_get_negotiated_caps (myshsinkpad); + caps = gst_buffer_get_caps (outbuffer); + fail_if (caps == NULL); + fail_if (padcaps == NULL); + GST_DEBUG ("caps: %" GST_PTR_FORMAT ", padcaps: %" GST_PTR_FORMAT, caps, + padcaps); + fail_unless (gst_caps_is_equal (padcaps, caps)); + + /* FIXME: get streamheader, compare data with buffer */ + gst_buffer_unref (outbuffer); + gst_caps_unref (padcaps); + gst_caps_unref (caps); + + /* clean up */ + fail_unless (gst_element_set_state (gdpdepay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_object_unref (srcpad); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdpdepay, "gdpdepay", 1); + cleanup_gdpdepay (gdpdepay); + + gst_dp_packetizer_free (pk); +} + +GST_END_TEST; + +static Suite * +gdpdepay_suite (void) +{ + Suite *s = suite_create ("gdpdepay"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_audio_per_byte); + tcase_add_test (tc_chain, test_audio_in_one_buffer); + tcase_add_test (tc_chain, test_streamheader); + + return s; +} + +GST_CHECK_MAIN (gdpdepay); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/gdppay.c b/gst-plugins-base-subtitles0.10/tests/check/elements/gdppay.c new file mode 100644 index 0000000..13117a6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/gdppay.c @@ -0,0 +1,566 @@ +/* GStreamer + * + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include + +/* 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, *myshsrcpad, *mysinkpad; + +#define AUDIO_CAPS_TEMPLATE_STRING \ + "audio/x-raw-int, " \ + "rate = (int) [ 1, MAX ], " \ + "channels = (int) [ 1, 8 ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) {8, 16}, " \ + "depth = (int) {8, 16}, " \ + "signed = (boolean) true" + +#define AUDIO_CAPS_STRING \ + "audio/x-raw-int, " \ + "rate = (int) 1000, " \ + "channels = (int) 2, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (boolean) true" + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gdp") + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (AUDIO_CAPS_TEMPLATE_STRING) + ); + +/* takes over reference for outcaps */ +static GstElement * +setup_gdppay (void) +{ + GstElement *gdppay; + + GST_DEBUG ("setup_gdppay"); + gdppay = gst_check_setup_element ("gdppay"); + mysrcpad = gst_check_setup_src_pad (gdppay, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (gdppay, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return gdppay; +} + +static void +cleanup_gdppay (GstElement * gdppay) +{ + GST_DEBUG ("cleanup_gdppay"); + + if (mysrcpad) + gst_pad_set_active (mysrcpad, FALSE); + if (myshsrcpad) + gst_pad_set_active (myshsrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (gdppay); + gst_check_teardown_sink_pad (gdppay); + gst_check_teardown_element (gdppay); + mysrcpad = NULL; + myshsrcpad = NULL; +} + +GST_START_TEST (test_audio) +{ + GstCaps *caps; + GstElement *gdppay; + GstBuffer *inbuffer, *outbuffer; + GstEvent *event; + gchar *caps_string; + gint length; + + gdppay = setup_gdppay (); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("new segment"); + event = + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, GST_SECOND, 0); + fail_unless (gst_pad_push_event (mysrcpad, event)); + + /* no buffer should be pushed yet, waiting for caps */ + fail_unless_equals_int (g_list_length (buffers), 0); + + GST_DEBUG ("first buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + gst_buffer_set_caps (inbuffer, caps); + caps_string = gst_caps_to_string (caps); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* we should have three buffers now */ + fail_unless_equals_int (g_list_length (buffers), 3); + + /* first buffer is the serialized new_segment event; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + gst_buffer_unref (outbuffer); + + /* second buffer is the serialized caps; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + length = GST_DP_HEADER_LENGTH + (strlen (caps_string) + 1); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* the third buffer is the GDP buffer for our pushed buffer */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* second buffer */ + GST_DEBUG ("second buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (inbuffer, caps); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + + /* the third output buffer is data */ + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* a third buffer without caps set explicitly; should work */ + GST_DEBUG ("Creating third buffer, no caps set"); + inbuffer = gst_buffer_new_and_alloc (4); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + + /* the fourth output buffer is data */ + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_caps_unref (caps); + g_free (caps_string); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdppay, "gdppay", 1); + cleanup_gdppay (gdppay); +} + +GST_END_TEST; + +static GstStaticPadTemplate shsrctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gst-test-streamheader") + ); + + +static GstElement * +setup_gdppay_streamheader (void) +{ + GstElement *gdppay; + + GST_DEBUG ("setup_gdppay"); + gdppay = gst_check_setup_element ("gdppay"); + myshsrcpad = gst_check_setup_src_pad (gdppay, &shsrctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (gdppay, &sinktemplate, NULL); + gst_pad_set_active (myshsrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return gdppay; +} + +/* this test serializes a stream that already has a streamheader of its own. + * the streamheader should then be serialized and put on the GDP stream's + * streamheader */ +GST_START_TEST (test_streamheader) +{ + GstCaps *caps, *sinkcaps; + GstElement *gdppay; + GstBuffer *inbuffer, *outbuffer, *shbuffer; + GstEvent *event; + gchar *caps_string; + gint length; + GstStructure *structure; + GValue array = { 0 }; + GValue value = { 0 }; + const GValue *sh; + GArray *shbuffers; + + + gdppay = setup_gdppay_streamheader (); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("new segment"); + event = + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, GST_SECOND, 0); + fail_unless (gst_pad_push_event (myshsrcpad, event)); + + /* no buffer should be pushed yet, still waiting for caps */ + fail_unless_equals_int (g_list_length (buffers), 0); + + GST_DEBUG ("first buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), "head", 4); + caps = gst_caps_from_string ("application/x-gst-test-streamheader"); + structure = gst_caps_get_structure (caps, 0); + GST_BUFFER_FLAG_SET (inbuffer, GST_BUFFER_FLAG_IN_CAPS); + g_value_init (&array, GST_TYPE_ARRAY); + g_value_init (&value, GST_TYPE_BUFFER); + shbuffer = gst_buffer_copy (inbuffer); + gst_value_set_buffer (&value, shbuffer); + gst_buffer_unref (shbuffer); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + caps_string = gst_caps_to_string (caps); + + gst_buffer_set_caps (inbuffer, caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (myshsrcpad, inbuffer) == GST_FLOW_OK); + + /* we should have three buffers now */ + fail_unless_equals_int (g_list_length (buffers), 3); + + /* our sink pad should now have GDP caps with a streamheader that includes + * GDP wrappings of our streamheader */ + sinkcaps = gst_pad_get_negotiated_caps (mysinkpad); + structure = gst_caps_get_structure (sinkcaps, 0); + fail_unless_equals_string ((gchar *) gst_structure_get_name (structure), + "application/x-gdp"); + fail_unless (gst_structure_has_field (structure, "streamheader")); + sh = gst_structure_get_value (structure, "streamheader"); + fail_unless (G_VALUE_TYPE (sh) == GST_TYPE_ARRAY); + shbuffers = g_value_peek_pointer (sh); + /* a serialized new_segment, a serialized caps, and serialization of our + * incoming streamheader */ + fail_unless_equals_int (shbuffers->len, 3); + + gst_caps_unref (sinkcaps); + + /* first buffer is the serialized new_segment event; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + gst_buffer_unref (outbuffer); + + /* second buffer is the serialized caps; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + length = GST_DP_HEADER_LENGTH + (strlen (caps_string) + 1); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* the third buffer is the GDP buffer for our pushed buffer */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* second buffer */ + GST_DEBUG ("second buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (inbuffer, caps); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (myshsrcpad, inbuffer) == GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + + /* the third output buffer is data */ + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* a third buffer without caps set explicitly; should work */ + GST_DEBUG ("Creating third buffer, no caps set"); + inbuffer = gst_buffer_new_and_alloc (4); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (myshsrcpad, inbuffer) == GST_FLOW_OK); + + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + + /* the fourth output buffer is data */ + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_caps_unref (caps); + g_free (caps_string); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdppay, "gdppay", 1); + cleanup_gdppay (gdppay); +} + +GST_END_TEST; + + +GST_START_TEST (test_first_no_caps) +{ + GstElement *gdppay; + GstBuffer *inbuffer; + + gdppay = setup_gdppay (); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("first buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing should trigger an error */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_NOT_NEGOTIATED); + + fail_unless_equals_int (g_list_length (buffers), 0); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdppay, "gdppay", 1); + cleanup_gdppay (gdppay); +} + +GST_END_TEST; + +/* element should still work if no new_segment is sent before the first + * buffer */ +GST_START_TEST (test_first_no_new_segment) +{ + GstElement *gdppay; + GstBuffer *inbuffer; + GstCaps *caps; + + gdppay = setup_gdppay (); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("first buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* we should have three buffers now; + * one for an "invented" new segment, one for GDP caps, and one with our + * buffer */ + fail_unless_equals_int (g_list_length (buffers), 3); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdppay, "gdppay", 1); + cleanup_gdppay (gdppay); +} + +GST_END_TEST; + +GST_START_TEST (test_crc) +{ + GstCaps *caps; + GstElement *gdppay; + GstBuffer *inbuffer, *outbuffer; + GstEvent *event; + gchar *caps_string; + gint length; + guint16 crc_calculated, crc_read; + + gdppay = setup_gdppay (); + g_object_set (gdppay, "crc-header", TRUE, NULL); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + GST_DEBUG ("new segment"); + event = + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, GST_SECOND, 0); + fail_unless (gst_pad_push_event (mysrcpad, event)); + + /* no buffer should be pushed yet, waiting for caps */ + fail_unless_equals_int (g_list_length (buffers), 0); + + GST_DEBUG ("first buffer"); + inbuffer = gst_buffer_new_and_alloc (4); + caps = gst_caps_from_string (AUDIO_CAPS_STRING); + gst_buffer_set_caps (inbuffer, caps); + caps_string = gst_caps_to_string (caps); + + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* we should have three buffers now */ + fail_unless_equals_int (g_list_length (buffers), 3); + + /* first buffer is the serialized new_segment event; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + + /* verify the header checksum */ + /* CRC's start at 58 in the header */ + crc_calculated = gst_dp_crc (GST_BUFFER_DATA (outbuffer), 58); + crc_read = GST_READ_UINT16_BE (GST_BUFFER_DATA (outbuffer) + 58); + fail_unless_equals_int (crc_calculated, crc_read); + + /* change a byte in the header and verify that the checksum now fails */ + GST_BUFFER_DATA (outbuffer)[0] = 0xff; + crc_calculated = gst_dp_crc (GST_BUFFER_DATA (outbuffer), 58); + fail_if (crc_calculated == crc_read, + "Introducing a byte error in the header should make the checksum fail"); + + gst_buffer_unref (outbuffer); + + /* second buffer is the serialized caps; + * the element also holds a ref to it */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 2); + length = GST_DP_HEADER_LENGTH + (strlen (caps_string) + 1); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + /* the third buffer is the GDP buffer for our pushed buffer */ + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + buffers = g_list_remove (buffers, outbuffer); + ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1); + length = GST_DP_HEADER_LENGTH + 4; + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), length); + gst_buffer_unref (outbuffer); + + fail_unless (gst_element_set_state (gdppay, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); + + gst_caps_unref (caps); + g_free (caps_string); + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_OBJECT_REFCOUNT (gdppay, "gdppay", 1); + cleanup_gdppay (gdppay); +} + +GST_END_TEST; + + +static Suite * +gdppay_suite (void) +{ + Suite *s = suite_create ("gdppay"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_audio); + tcase_add_test (tc_chain, test_first_no_caps); + tcase_add_test (tc_chain, test_first_no_new_segment); + tcase_add_test (tc_chain, test_streamheader); + tcase_add_test (tc_chain, test_crc); + + return s; +} + +GST_CHECK_MAIN (gdppay); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/gnomevfssink.c b/gst-plugins-base-subtitles0.10/tests/check/elements/gnomevfssink.c new file mode 100644 index 0000000..f0cf64d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/gnomevfssink.c @@ -0,0 +1,319 @@ +/* GStreamer unit test for the gnomevfssink element + * + * Copyright (C) 2006 Thomas Vander Stichele + * Copyright (C) 2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +#ifdef HAVE_UNISTD_H +#include /* for close() */ +#endif + +#include + +static GstPad *mysrcpad; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstElement * +setup_gnomevfssink (void) +{ + GstElement *gnomevfssink; + + GST_DEBUG ("setup_gnomevfssink"); + gnomevfssink = gst_check_setup_element ("gnomevfssink"); + mysrcpad = gst_check_setup_src_pad (gnomevfssink, &srctemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + return gnomevfssink; +} + +static void +cleanup_gnomevfssink (GstElement * gnomevfssink) +{ + gst_pad_set_active (mysrcpad, FALSE); + gst_check_teardown_src_pad (gnomevfssink); + gst_check_teardown_element (gnomevfssink); +} + +#if 0 +/* this queries via the element vfunc, which is currently not implemented */ +#define CHECK_QUERY_POSITION(gnomevfssink,format,position) \ + G_STMT_START { \ + GstFormat fmt = format; \ + gint64 pos; \ + fail_unless (gst_element_query_position (gnomevfssink, &fmt, &pos)); \ + fail_unless_equals_int (pos, position); \ + } G_STMT_END +#else +#define CHECK_QUERY_POSITION(gnomevfssink,format,position) \ + G_STMT_START { \ + GstFormat fmt = format; \ + GstPad *pad; \ + gint64 pos; \ + pad = gst_element_get_static_pad (gnomevfssink, "sink"); \ + fail_unless (gst_pad_query_position (pad, &fmt, &pos)); \ + fail_unless_equals_int (pos, position); \ + gst_object_unref (pad); \ + } G_STMT_END +#endif + +#define PUSH_BYTES(num_bytes) \ + G_STMT_START { \ + GstBuffer *buf = gst_buffer_new_and_alloc(num_bytes); \ + GRand *rand = g_rand_new_with_seed (num_bytes); \ + guint i; \ + for (i = 0; i < num_bytes; ++i) \ + GST_BUFFER_DATA(buf)[i] = (g_rand_int (rand) >> 24) & 0xff; \ + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); \ + g_rand_free (rand); \ + } G_STMT_END + +/* TODO: we don't check that the data is actually written to the right + * position after a seek */ +GST_START_TEST (test_seeking) +{ + const gchar *tmpdir; + GstElement *gnomevfssink; + gchar *tmp_fn; + gint fd; + + tmpdir = g_get_tmp_dir (); + if (tmpdir == NULL) + return; + + /* this is just silly, but gcc warns if we try to use tpmnam() */ + tmp_fn = + g_build_filename (tmpdir, "gstreamer-gnomevfssink-test-XXXXXX", NULL); + fd = g_mkstemp (tmp_fn); + if (fd < 0) { + GST_ERROR ("can't create temp file %s: %s", tmp_fn, g_strerror (errno)); + g_free (tmp_fn); + return; + } + /* don't want the file, just a filename (hence silly, see above) */ + close (fd); + g_remove (tmp_fn); + + gnomevfssink = setup_gnomevfssink (); + + GST_LOG ("using temp file '%s'", tmp_fn); + g_object_set (gnomevfssink, "location", tmp_fn, NULL); + + fail_unless_equals_int (gst_element_set_state (gnomevfssink, + GST_STATE_PLAYING), GST_STATE_CHANGE_ASYNC); + +#if 0 + /* Test that gnomevfssink is seekable with a file fd */ + /* gnomevfssink doesn't implement seekable query at the moment */ + GstQuery *seeking_query; + gboolean seekable; + + fail_unless ((seeking_query = gst_query_new_seeking (GST_FORMAT_BYTES)) + != NULL); + fail_unless (gst_element_query (gnomevfssink, seeking_query) == TRUE); + gst_query_parse_seeking (seeking_query, NULL, &seekable, NULL, NULL); + fail_unless (seekable == TRUE); + gst_query_unref (seeking_query); +#endif + + fail_unless (gst_pad_push_event (mysrcpad, + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0))); + + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 0); + + /* push buffer with size 0 and NULL data */ + PUSH_BYTES (0); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 0); + + PUSH_BYTES (1); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 1); + + PUSH_BYTES (99); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 100); + + PUSH_BYTES (8800); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8900); + + if (gst_pad_push_event (mysrcpad, + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_BYTES, 8800, -1, + 0))) { + GST_LOG ("seek ok"); + /* make sure that that new position is reported immediately */ + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8800); + PUSH_BYTES (1); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 8801); + PUSH_BYTES (9256); + CHECK_QUERY_POSITION (gnomevfssink, GST_FORMAT_BYTES, 18057); + } else { + GST_INFO ("seeking not supported for tempfile?!"); + } + + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + fail_unless_equals_int (gst_element_set_state (gnomevfssink, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + /* cleanup */ + cleanup_gnomevfssink (gnomevfssink); + + /* check that we wrote data to the right position after the seek */ + { + gchar *data = NULL; + gsize len; + + fail_unless (g_file_get_contents (tmp_fn, &data, &len, NULL), + "Failed to read in newly-created file '%s'", tmp_fn); + fail_unless_equals_int (len, 18057); + { + /* we wrote 9256 bytes at position 8801 */ + GRand *rand = g_rand_new_with_seed (9256); + guint i; + + for (i = 0; i < 9256; ++i) { + guint8 byte_written = *(((guint8 *) data) + 8801 + i); + + fail_unless_equals_int (byte_written, g_rand_int (rand) >> 24); + } + g_rand_free (rand); + } + g_free (data); + } + + /* remove file */ + g_remove (tmp_fn); + g_free (tmp_fn); +} + +GST_END_TEST; + +GST_START_TEST (test_coverage) +{ + GstElement *gnomevfssink; + gchar *location; + GstBus *bus; + GstMessage *message; + + gnomevfssink = setup_gnomevfssink (); + bus = gst_bus_new (); + + gst_element_set_bus (gnomevfssink, bus); + + g_object_set (gnomevfssink, "location", "/i/do/not/exist", NULL); + g_object_get (gnomevfssink, "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + + fail_unless_equals_int (gst_element_set_state (gnomevfssink, + GST_STATE_PLAYING), GST_STATE_CHANGE_FAILURE); + + /* a state change and an error */ + fail_if ((message = gst_bus_pop (bus)) == NULL); + fail_unless_message_error (message, RESOURCE, OPEN_WRITE); + gst_message_unref (message); + + g_object_set (gnomevfssink, "location", NULL, NULL); + g_object_get (gnomevfssink, "location", &location, NULL); + fail_if (location); + + /* cleanup */ + gst_element_set_bus (gnomevfssink, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_gnomevfssink (gnomevfssink); +} + +GST_END_TEST; + +GST_START_TEST (test_uri_interface) +{ + GstElement *gnomevfssink; + gchar *location; + GstBus *bus; + + gnomevfssink = setup_gnomevfssink (); + bus = gst_bus_new (); + + gst_element_set_bus (gnomevfssink, bus); + + g_object_set (G_OBJECT (gnomevfssink), "location", "/i/do/not/exist", NULL); + g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); + fail_unless_equals_string (location, "/i/do/not/exist"); + g_free (location); + + location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); + fail_unless_equals_string (location, "file://%2Fi%2Fdo%2Fnot%2Fexist"); + + /* should accept file:///foo/bar URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), + "file:///foo/bar")); + location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); + fail_unless_equals_string (location, "file://%2Ffoo%2Fbar"); + g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); + fail_unless_equals_string (location, "/foo/bar"); + g_free (location); + + /* should accept file://localhost/foo/bar URIs */ + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), + "file://localhost/foo/baz")); + location = (gchar *) gst_uri_handler_get_uri (GST_URI_HANDLER (gnomevfssink)); + fail_unless_equals_string (location, "file://%2Ffoo%2Fbaz"); + g_object_get (G_OBJECT (gnomevfssink), "location", &location, NULL); + fail_unless_equals_string (location, "/foo/baz"); + g_free (location); + + /* should fail with other hostnames */ + fail_if (gst_uri_handler_set_uri (GST_URI_HANDLER (gnomevfssink), + "file://hostname/foo/foo")); + + /* cleanup */ + gst_element_set_bus (gnomevfssink, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_gnomevfssink (gnomevfssink); +} + +GST_END_TEST; + +static Suite * +gnomevfssink_suite (void) +{ + Suite *s = suite_create ("gnomevfssink"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + /* FIXME: these two tests fail right now because of uri/location stuff */ + if (0) { + tcase_add_test (tc_chain, test_coverage); + tcase_add_test (tc_chain, test_uri_interface); + } + tcase_add_test (tc_chain, test_seeking); + + return s; +} + +GST_CHECK_MAIN (gnomevfssink); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/libvisual.c b/gst-plugins-base-subtitles0.10/tests/check/elements/libvisual.c new file mode 100644 index 0000000..0f95006 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/libvisual.c @@ -0,0 +1,118 @@ +/* GStreamer unit test for libvisual plugin + * + * Copyright (C) 2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +static gboolean +filter_func (GstPluginFeature * feature, gpointer user_data) +{ + return (g_str_has_prefix (GST_PLUGIN_FEATURE_NAME (feature), "libvisual_")); +} + +static void +test_shutdown_for_factory (const gchar * factory_name) +{ + GstElement *pipeline, *src, *q, *ac, *vis, *cf, *q2, *sink; + GstCaps *caps; + guint i; + + pipeline = gst_pipeline_new (NULL); + + src = gst_check_setup_element ("audiotestsrc"); + q = gst_check_setup_element ("queue"); + ac = gst_check_setup_element ("audioconvert"); + + GST_INFO ("Using %s", factory_name); + vis = gst_check_setup_element (factory_name); + + cf = gst_check_setup_element ("capsfilter"); + caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, 320, + "height", G_TYPE_INT, 240, "framerate", GST_TYPE_FRACTION, 15, 1, NULL); + g_object_set (cf, "caps", caps, NULL); + gst_caps_unref (caps); + + q2 = gst_check_setup_element ("queue"); + gst_object_set_name (GST_OBJECT (q2), "queue2"); + sink = gst_check_setup_element ("fakesink"); + + /* don't want to sync against the clock, the more throughput the better */ + g_object_set (src, "is-live", FALSE, NULL); + g_object_set (sink, "sync", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, q, ac, vis, cf, q2, sink, NULL); + fail_if (!gst_element_link_many (src, q, ac, vis, cf, q2, sink, NULL)); + + /* now, wait until pipeline is running and then shut it down again; repeat; + * this makes sure we can shut down cleanly while stuff is going on in the + * chain function */ + for (i = 0; i < 50; ++i) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_get_state (pipeline, NULL, NULL, -1); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + g_usleep (100); + gst_element_set_state (pipeline, GST_STATE_NULL); + } + + gst_object_unref (pipeline); +} + +GST_START_TEST (test_shutdown) +{ + const gchar *factory_to_test; + + factory_to_test = g_getenv ("LIBVISUAL_UNIT_TEST_FACTORY"); + + if (factory_to_test == NULL) { + GList *list, *l; + + list = gst_default_registry_feature_filter (filter_func, FALSE, NULL); + if (list == NULL) { + g_print ("No libvisual plugins installed.\n"); + return; + } + for (l = list; l != NULL; l = l->next) { + test_shutdown_for_factory (GST_PLUGIN_FEATURE_NAME (l->data)); + } + gst_plugin_feature_list_free (list); + } else { + test_shutdown_for_factory (factory_to_test); + } +} + +GST_END_TEST; + +static Suite * +libvisual_suite (void) +{ + Suite *s = suite_create ("libvisual"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + /* set one manually, since we're currently built as uninst program with + * the default timeout of 3 seconds, which is way too short */ + tcase_set_timeout (tc_chain, 30); + + tcase_add_test (tc_chain, test_shutdown); + + return s; +} + +GST_CHECK_MAIN (libvisual); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/multifdsink.c b/gst-plugins-base-subtitles0.10/tests/check/elements/multifdsink.c new file mode 100644 index 0000000..4eb6e9e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/multifdsink.c @@ -0,0 +1,867 @@ +/* GStreamer + * + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#ifdef HAVE_FIONREAD_IN_SYS_FILIO +#include +#endif + +#include + +static GstPad *mysrcpad; + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-gst-check") + ); + +static GstElement * +setup_multifdsink (void) +{ + GstElement *multifdsink; + + GST_DEBUG ("setup_multifdsink"); + multifdsink = gst_check_setup_element ("multifdsink"); + mysrcpad = gst_check_setup_src_pad (multifdsink, &srctemplate, NULL); + + return multifdsink; +} + +static void +cleanup_multifdsink (GstElement * multifdsink) +{ + GST_DEBUG ("cleanup_multifdsink"); + + gst_check_teardown_src_pad (multifdsink); + gst_check_teardown_element (multifdsink); +} + +static void +wait_bytes_served (GstElement * sink, guint64 bytes) +{ + guint64 bytes_served = 0; + + while (bytes_served != bytes) { + g_object_get (sink, "bytes-served", &bytes_served, NULL); + } +} + +/* FIXME: possibly racy, since if it would write, we may not get it + * immediately ? */ +#define fail_if_can_read(msg,fd) \ +G_STMT_START { \ + long avail; \ +\ + fail_if (ioctl (fd, FIONREAD, &avail) < 0, "%s: could not ioctl", msg); \ + fail_if (avail > 0, "%s: has bytes available to read"); \ +} G_STMT_END; + + +GST_START_TEST (test_no_clients) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + + sink = setup_multifdsink (); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + gst_caps_unref (caps); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); +} + +GST_END_TEST; + +GST_START_TEST (test_add_client) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + int pfd[2]; + gchar data[4]; + + sink = setup_multifdsink (); + + fail_if (pipe (pfd) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + /* add the client */ + g_signal_emit_by_name (sink, "add", pfd[1]); + + caps = gst_caps_from_string ("application/x-gst-check"); + GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps); + buffer = gst_buffer_new_and_alloc (4); + gst_buffer_set_caps (buffer, caps); + ASSERT_CAPS_REFCOUNT (caps, "caps", 2); + memcpy (GST_BUFFER_DATA (buffer), "dead", 4); + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + + GST_DEBUG ("reading"); + fail_if (read (pfd[0], data, 4) < 4); + fail_unless (strncmp (data, "dead", 4) == 0); + wait_bytes_served (sink, 4); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +#define fail_unless_read(msg,fd,size,ref) \ +G_STMT_START { \ + char data[size + 1]; \ + int nbytes; \ +\ + GST_DEBUG ("%s: reading %d bytes", msg, size); \ + nbytes = read (fd, data, size); \ + data[size] = 0; \ + GST_DEBUG ("%s: read %d bytes", msg, nbytes); \ + fail_if (nbytes < size); \ + fail_unless (memcmp (data, ref, size) == 0, \ + "data read '%s' differs from '%s'", data, ref); \ +} G_STMT_END; + +/* from the given two data buffers, create two streamheader buffers and + * some caps that match it, and store them in the given pointers + * returns one ref to each of the buffers and the caps */ +static void +gst_multifdsink_create_streamheader (const gchar * data1, + const gchar * data2, GstBuffer ** hbuf1, GstBuffer ** hbuf2, + GstCaps ** caps) +{ + GstBuffer *buf; + GValue array = { 0 }; + GValue value = { 0 }; + GstStructure *structure; + guint size1 = strlen (data1); + guint size2 = strlen (data2); + + fail_if (hbuf1 == NULL); + fail_if (hbuf2 == NULL); + fail_if (caps == NULL); + + /* create caps with streamheader, set the caps, and push the IN_CAPS + * buffers */ + *hbuf1 = gst_buffer_new_and_alloc (size1); + GST_BUFFER_FLAG_SET (*hbuf1, GST_BUFFER_FLAG_IN_CAPS); + memcpy (GST_BUFFER_DATA (*hbuf1), data1, size1); + *hbuf2 = gst_buffer_new_and_alloc (size2); + GST_BUFFER_FLAG_SET (*hbuf2, GST_BUFFER_FLAG_IN_CAPS); + memcpy (GST_BUFFER_DATA (*hbuf2), data2, size2); + + g_value_init (&array, GST_TYPE_ARRAY); + + g_value_init (&value, GST_TYPE_BUFFER); + /* we take a copy, set it on the array (which refs it), then unref our copy */ + buf = gst_buffer_copy (*hbuf1); + gst_value_set_buffer (&value, buf); + ASSERT_BUFFER_REFCOUNT (buf, "copied buffer", 2); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_copy (*hbuf2); + gst_value_set_buffer (&value, buf); + ASSERT_BUFFER_REFCOUNT (buf, "copied buffer", 2); + gst_buffer_unref (buf); + gst_value_array_append_value (&array, &value); + g_value_unset (&value); + + *caps = gst_caps_from_string ("application/x-gst-check"); + structure = gst_caps_get_structure (*caps, 0); + + gst_structure_set_value (structure, "streamheader", &array); + g_value_unset (&array); + ASSERT_CAPS_REFCOUNT (*caps, "streamheader caps", 1); + + /* set our streamheadery caps on the buffers */ + gst_buffer_set_caps (*hbuf1, *caps); + gst_buffer_set_caps (*hbuf2, *caps); + ASSERT_CAPS_REFCOUNT (*caps, "streamheader caps", 3); + + /* we want to keep them around for the tests */ + gst_buffer_ref (*hbuf1); + gst_buffer_ref (*hbuf2); + + GST_DEBUG ("created streamheader caps %p %" GST_PTR_FORMAT, *caps, *caps); +} + + +/* this test: + * - adds a first client + * - sets streamheader caps on the pad + * - pushes the IN_CAPS buffers + * - pushes a buffer + * - verifies that the client received all the data correctly, and did not + * get multiple copies of the streamheader + * - adds a second client + * - verifies that this second client receives the streamheader caps too, plus + * - the new buffer + */ +GST_START_TEST (test_streamheader) +{ + GstElement *sink; + GstBuffer *hbuf1, *hbuf2, *buf; + GstCaps *caps; + int pfd1[2], pfd2[2]; + + sink = setup_multifdsink (); + + fail_if (pipe (pfd1) == -1); + fail_if (pipe (pfd2) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + /* add the first client */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + + /* create caps with streamheader, set the caps, and push the IN_CAPS + * buffers */ + gst_multifdsink_create_streamheader ("babe", "deadbeef", &hbuf1, &hbuf2, + &caps); + fail_unless (gst_pad_set_caps (mysrcpad, caps)); + /* one is ours, two on the buffers, and one now on the pad */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 4); + + fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK); + fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK); + + //FIXME: + //fail_if_can_read ("first client", pfd1[0]); + + /* push a non-IN_CAPS buffer, this should trigger the client receiving the + * first three buffers */ + buf = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buf), "f00d", 4); + gst_pad_push (mysrcpad, buf); + + fail_unless_read ("first client", pfd1[0], 4, "babe"); + fail_unless_read ("first client", pfd1[0], 8, "deadbeef"); + fail_unless_read ("first client", pfd1[0], 4, "f00d"); + wait_bytes_served (sink, 16); + + /* now add the second client */ + g_signal_emit_by_name (sink, "add", pfd2[1]); + //FIXME: + //fail_if_can_read ("second client", pfd2[0]); + + /* now push another buffer, which will trigger streamheader for second + * client */ + buf = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buf), "deaf", 4); + gst_pad_push (mysrcpad, buf); + + fail_unless_read ("first client", pfd1[0], 4, "deaf"); + + fail_unless_read ("second client", pfd2[0], 4, "babe"); + fail_unless_read ("second client", pfd2[0], 8, "deadbeef"); + /* we missed the f00d buffer */ + fail_unless_read ("second client", pfd2[0], 4, "deaf"); + wait_bytes_served (sink, 36); + + GST_DEBUG ("cleaning up multifdsink"); + + g_signal_emit_by_name (sink, "remove", pfd1[1]); + g_signal_emit_by_name (sink, "remove", pfd2[1]); + + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 1); + ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 1); + gst_buffer_unref (hbuf1); + gst_buffer_unref (hbuf2); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* this tests changing of streamheaders + * - set streamheader caps on the pad + * - pushes the IN_CAPS buffers + * - pushes a buffer + * - add a first client + * - verifies that this first client receives the first streamheader caps, + * plus a new buffer + * - change streamheader caps + * - verify that the first client receives the new streamheader buffers as well + */ +GST_START_TEST (test_change_streamheader) +{ + GstElement *sink; + GstBuffer *hbuf1, *hbuf2, *buf; + GstCaps *caps; + int pfd1[2], pfd2[2]; + + sink = setup_multifdsink (); + + fail_if (pipe (pfd1) == -1); + fail_if (pipe (pfd2) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + /* create caps with streamheader, set the caps, and push the IN_CAPS + * buffers */ + gst_multifdsink_create_streamheader ("first", "header", &hbuf1, &hbuf2, + &caps); + fail_unless (gst_pad_set_caps (mysrcpad, caps)); + /* one is ours, two on the buffers, and one now on the pad */ + ASSERT_CAPS_REFCOUNT (caps, "caps", 4); + + /* one to hold for the test and one to give away */ + ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2); + ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2); + + fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK); + fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK); + + /* add the first client */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + + /* verify this hasn't triggered a write yet */ + /* FIXME: possibly racy, since if it would write, we may not get it + * immediately ? */ + //fail_if_can_read ("first client, no buffer", pfd1[0]); + + /* now push a buffer and read */ + buf = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (buf), "f00d", 4); + gst_pad_push (mysrcpad, buf); + + fail_unless_read ("change: first client", pfd1[0], 5, "first"); + fail_unless_read ("change: first client", pfd1[0], 6, "header"); + fail_unless_read ("change: first client", pfd1[0], 4, "f00d"); + //wait_bytes_served (sink, 16); + + /* now add the second client */ + g_signal_emit_by_name (sink, "add", pfd2[1]); + //fail_if_can_read ("second client, no buffer", pfd2[0]); + + /* change the streamheader */ + + /* before we change, multifdsink still has a list of the old streamheaders */ + ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2); + ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2); + gst_buffer_unref (hbuf1); + gst_buffer_unref (hbuf2); + + /* drop our ref to the previous caps */ + gst_caps_unref (caps); + + gst_multifdsink_create_streamheader ("second", "header", &hbuf1, &hbuf2, + &caps); + fail_unless (gst_pad_set_caps (mysrcpad, caps)); + /* one to hold for the test and one to give away */ + ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 2); + ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 2); + + fail_unless (gst_pad_push (mysrcpad, hbuf1) == GST_FLOW_OK); + fail_unless (gst_pad_push (mysrcpad, hbuf2) == GST_FLOW_OK); + + /* verify neither client has new data available to read */ + //fail_if_can_read ("first client, changed streamheader", pfd1[0]); + //fail_if_can_read ("second client, changed streamheader", pfd2[0]); + + /* now push another buffer, which will trigger streamheader for second + * client, but should also send new streamheaders to first client */ + buf = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (buf), "deadbabe", 8); + gst_pad_push (mysrcpad, buf); + + fail_unless_read ("first client", pfd1[0], 6, "second"); + fail_unless_read ("first client", pfd1[0], 6, "header"); + fail_unless_read ("first client", pfd1[0], 8, "deadbabe"); + + /* new streamheader data */ + fail_unless_read ("second client", pfd2[0], 6, "second"); + fail_unless_read ("second client", pfd2[0], 6, "header"); + /* we missed the f00d buffer */ + fail_unless_read ("second client", pfd2[0], 8, "deadbabe"); + //wait_bytes_served (sink, 36); + + GST_DEBUG ("cleaning up multifdsink"); + g_signal_emit_by_name (sink, "remove", pfd1[1]); + g_signal_emit_by_name (sink, "remove", pfd2[1]); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + + /* setting to NULL should have cleared the streamheader */ + ASSERT_BUFFER_REFCOUNT (hbuf1, "hbuf1", 1); + ASSERT_BUFFER_REFCOUNT (hbuf2, "hbuf2", 1); + gst_buffer_unref (hbuf1); + gst_buffer_unref (hbuf2); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* keep 100 bytes and burst 80 bytes to clients */ +GST_START_TEST (test_burst_client_bytes) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + int pfd1[2]; + int pfd2[2]; + int pfd3[2]; + gchar data[16]; + gint i; + guint buffers_queued; + + sink = setup_multifdsink (); + /* make sure we keep at least 100 bytes at all times */ + g_object_set (sink, "bytes-min", 100, NULL); + g_object_set (sink, "sync-method", 3, NULL); /* 3 = burst */ + g_object_set (sink, "burst-unit", 3, NULL); /* 3 = bytes */ + g_object_set (sink, "burst-value", (guint64) 80, NULL); + + fail_if (pipe (pfd1) == -1); + fail_if (pipe (pfd2) == -1); + fail_if (pipe (pfd3) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps); + + /* push buffers in, 9 * 16 bytes = 144 bytes */ + for (i = 0; i < 9; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* check that at least 7 buffers (112 bytes) are in the queue */ + g_object_get (sink, "buffers-queued", &buffers_queued, NULL); + fail_if (buffers_queued != 7); + + /* now add the clients */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + g_signal_emit_by_name (sink, "add_full", pfd2[1], 3, + 3, (guint64) 50, 3, (guint64) 200); + g_signal_emit_by_name (sink, "add_full", pfd3[1], 3, + 3, (guint64) 50, 3, (guint64) 50); + + /* push last buffer to make client fds ready for reading */ + for (i = 9; i < 10; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* now we should only read the last 5 buffers (5 * 16 = 80 bytes) */ + GST_DEBUG ("Reading from client 1"); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000005", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000006", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* second client only bursts 50 bytes = 4 buffers (we get 4 buffers since + * the max alows it) */ + GST_DEBUG ("Reading from client 2"); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000006", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* third client only bursts 50 bytes = 4 buffers, we can't send + * more than 50 bytes so we only get 3 buffers (48 bytes). */ + GST_DEBUG ("Reading from client 3"); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* keep 100 bytes and burst 80 bytes to clients */ +GST_START_TEST (test_burst_client_bytes_keyframe) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + int pfd1[2]; + int pfd2[2]; + int pfd3[2]; + gchar data[16]; + gint i; + guint buffers_queued; + + sink = setup_multifdsink (); + /* make sure we keep at least 100 bytes at all times */ + g_object_set (sink, "bytes-min", 100, NULL); + g_object_set (sink, "sync-method", 4, NULL); /* 3 = burst_keyframe */ + g_object_set (sink, "burst-unit", 3, NULL); /* 3 = bytes */ + g_object_set (sink, "burst-value", (guint64) 80, NULL); + + fail_if (pipe (pfd1) == -1); + fail_if (pipe (pfd2) == -1); + fail_if (pipe (pfd3) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps); + + /* push buffers in, 9 * 16 bytes = 144 bytes */ + for (i = 0; i < 9; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + + /* mark most buffers as delta */ + if (i != 0 && i != 4 && i != 8) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* check that at least 7 buffers (112 bytes) are in the queue */ + g_object_get (sink, "buffers-queued", &buffers_queued, NULL); + fail_if (buffers_queued != 7); + + /* now add the clients */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + g_signal_emit_by_name (sink, "add_full", pfd2[1], 4, + 3, (guint64) 50, 3, (guint64) 90); + g_signal_emit_by_name (sink, "add_full", pfd3[1], 4, + 3, (guint64) 50, 3, (guint64) 50); + + /* push last buffer to make client fds ready for reading */ + for (i = 9; i < 10; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* now we should only read the last 6 buffers (min 5 * 16 = 80 bytes), + * keyframe at buffer 4 */ + GST_DEBUG ("Reading from client 1"); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000004", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000005", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000006", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* second client only bursts 50 bytes = 4 buffers, there is + * no keyframe above min and below max, so get one below min */ + GST_DEBUG ("Reading from client 2"); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* third client only bursts 50 bytes = 4 buffers, we can't send + * more than 50 bytes so we only get 2 buffers (32 bytes). */ + GST_DEBUG ("Reading from client 3"); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* keep 100 bytes and burst 80 bytes to clients */ +GST_START_TEST (test_burst_client_bytes_with_keyframe) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + int pfd1[2]; + int pfd2[2]; + int pfd3[2]; + gchar data[16]; + gint i; + guint buffers_queued; + + sink = setup_multifdsink (); + /* make sure we keep at least 100 bytes at all times */ + g_object_set (sink, "bytes-min", 100, NULL); + g_object_set (sink, "sync-method", 5, NULL); /* 3 = burst_with_keyframe */ + g_object_set (sink, "burst-unit", 3, NULL); /* 3 = bytes */ + g_object_set (sink, "burst-value", (guint64) 80, NULL); + + fail_if (pipe (pfd1) == -1); + fail_if (pipe (pfd2) == -1); + fail_if (pipe (pfd3) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps); + + /* push buffers in, 9 * 16 bytes = 144 bytes */ + for (i = 0; i < 9; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + + /* mark most buffers as delta */ + if (i != 0 && i != 4 && i != 8) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* check that at least 7 buffers (112 bytes) are in the queue */ + g_object_get (sink, "buffers-queued", &buffers_queued, NULL); + fail_if (buffers_queued != 7); + + /* now add the clients */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + g_signal_emit_by_name (sink, "add_full", pfd2[1], 5, + 3, (guint64) 50, 3, (guint64) 90); + g_signal_emit_by_name (sink, "add_full", pfd3[1], 5, + 3, (guint64) 50, 3, (guint64) 50); + + /* push last buffer to make client fds ready for reading */ + for (i = 9; i < 10; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* now we should only read the last 6 buffers (min 5 * 16 = 80 bytes), + * keyframe at buffer 4 */ + GST_DEBUG ("Reading from client 1"); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000004", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000005", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000006", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* second client only bursts 50 bytes = 4 buffers, there is + * no keyframe above min and below max, so send min */ + GST_DEBUG ("Reading from client 2"); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000006", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd2[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + /* third client only bursts 50 bytes = 4 buffers, we can't send + * more than 50 bytes so we only get 3 buffers (48 bytes). */ + GST_DEBUG ("Reading from client 3"); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000007", 16) == 0); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000008", 16) == 0); + fail_if (read (pfd3[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000009", 16) == 0); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* Check that we can get data when multifdsink is configured in next-keyframe + * mode */ +GST_START_TEST (test_client_next_keyframe) +{ + GstElement *sink; + GstBuffer *buffer; + GstCaps *caps; + int pfd1[2]; + gchar data[16]; + gint i; + + sink = setup_multifdsink (); + g_object_set (sink, "sync-method", 1, NULL); /* 1 = next-keyframe */ + + fail_if (pipe (pfd1) == -1); + + ASSERT_SET_STATE (sink, GST_STATE_PLAYING, GST_STATE_CHANGE_ASYNC); + + caps = gst_caps_from_string ("application/x-gst-check"); + GST_DEBUG ("Created test caps %p %" GST_PTR_FORMAT, caps, caps); + + /* now add our client */ + g_signal_emit_by_name (sink, "add", pfd1[1]); + + /* push buffers in: keyframe, then non-keyframe */ + for (i = 0; i < 2; i++) { + gchar *data; + + buffer = gst_buffer_new_and_alloc (16); + gst_buffer_set_caps (buffer, caps); + + /* copy some id */ + data = (gchar *) GST_BUFFER_DATA (buffer); + g_snprintf (data, 16, "deadbee%08x", i); + if (i > 0) + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + fail_unless (gst_pad_push (mysrcpad, buffer) == GST_FLOW_OK); + } + + /* now we should be able to read some data */ + GST_DEBUG ("Reading from client 1"); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000000", 16) == 0); + fail_if (read (pfd1[0], data, 16) < 16); + fail_unless (strncmp (data, "deadbee00000001", 16) == 0); + + GST_DEBUG ("cleaning up multifdsink"); + ASSERT_SET_STATE (sink, GST_STATE_NULL, GST_STATE_CHANGE_SUCCESS); + cleanup_multifdsink (sink); + + ASSERT_CAPS_REFCOUNT (caps, "caps", 1); + gst_caps_unref (caps); +} + +GST_END_TEST; + +/* FIXME: add test simulating chained oggs where: + * sync-method is burst-on-connect + * (when multifdsink actually does burst-on-connect based on byte size, not + "last keyframe" which any frame for audio :)) + * an old client still needs to read from before the new streamheaders + * a new client gets the new streamheaders + */ +static Suite * +multifdsink_suite (void) +{ + Suite *s = suite_create ("multifdsink"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_no_clients); + tcase_add_test (tc_chain, test_add_client); + tcase_add_test (tc_chain, test_streamheader); + tcase_add_test (tc_chain, test_change_streamheader); + tcase_add_test (tc_chain, test_burst_client_bytes); + tcase_add_test (tc_chain, test_burst_client_bytes_keyframe); + tcase_add_test (tc_chain, test_burst_client_bytes_with_keyframe); + tcase_add_test (tc_chain, test_client_next_keyframe); + + return s; +} + +GST_CHECK_MAIN (multifdsink); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/playbin.c b/gst-plugins-base-subtitles0.10/tests/check/elements/playbin.c new file mode 100644 index 0000000..08aace6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/playbin.c @@ -0,0 +1,650 @@ +/* GStreamer unit tests for playbin + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include + +#ifndef GST_DISABLE_REGISTRY + +static GType gst_red_video_src_get_type (void); +static GType gst_codec_src_get_type (void); + +#define DEFINE_TEST(func) \ + static void func (void); \ + \ + GST_START_TEST(func ## _decodebin1) \ + { g_unsetenv("USE_DECODEBIN2"); func(); } \ + GST_END_TEST; \ + \ + GST_START_TEST(func ## _decodebin2) \ + { g_setenv("USE_DECODEBIN2", "1", TRUE); func(); } \ + GST_END_TEST; + +DEFINE_TEST (test_sink_usage_video_only_stream); + +/* make sure the audio sink is not touched for video-only streams */ +static void +test_sink_usage_video_only_stream (void) +{ + GstElement *playbin, *fakevideosink, *fakeaudiosink; + GstState cur_state, pending_state; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin", "playbin"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakevideosink = gst_element_factory_make ("fakesink", "fakevideosink"); + fail_unless (fakevideosink != NULL, "Failed to create fakevideosink element"); + + fakeaudiosink = gst_element_factory_make ("fakesink", "fakeaudiosink"); + fail_unless (fakeaudiosink != NULL, "Failed to create fakeaudiosink element"); + + /* video-only stream, audiosink will error out in null => ready if used */ + g_object_set (fakeaudiosink, "state-error", 1, NULL); + + g_object_set (playbin, "video-sink", fakevideosink, NULL); + g_object_set (playbin, "audio-sink", fakeaudiosink, NULL); + + g_object_set (playbin, "uri", "redvideo://", NULL); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + fail_unless_equals_int (gst_element_get_state (fakeaudiosink, &cur_state, + &pending_state, 0), GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (cur_state, GST_STATE_NULL); + fail_unless_equals_int (pending_state, GST_STATE_VOID_PENDING); + + { + GValueArray *stream_info = NULL; + + g_object_get (playbin, "stream-info-value-array", &stream_info, NULL); + fail_unless (stream_info != NULL); + fail_unless_equals_int (stream_info->n_values, 1); + g_value_array_free (stream_info); + } + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +/* this tests async error handling when setting up the subbin */ +DEFINE_TEST (test_suburi_error_unknowntype); + +static void +test_suburi_error_unknowntype (void) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin", "playbin"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* suburi file format unknown: playbin should just ignore the suburi and + * preroll normally (if /dev/zero does not exist, this test should behave + * the same as test_suburi_error_invalidfile() */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "file:///dev/zero", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +DEFINE_TEST (test_suburi_error_invalidfile); + +static void +test_suburi_error_invalidfile (void) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin", "playbin"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* suburi file does not exist: playbin should just ignore the suburi and + * preroll normally */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "file:///foo/bar/803129999/32x9ax1", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +DEFINE_TEST (test_suburi_error_wrongproto); + +static void +test_suburi_error_wrongproto (void) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin", "playbin"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* wrong protocol for suburi: playbin should just ignore the suburi and + * preroll normally */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "nosuchproto://foo.bar:80", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +static GstElement * +create_playbin (const gchar * uri) +{ + GstElement *playbin, *fakesink1, *fakesink2; + + playbin = gst_element_factory_make ("playbin", "playbin"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink1 = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink1 != NULL, "Failed to create fakesink element #1"); + + fakesink2 = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink2 != NULL, "Failed to create fakesink element #2"); + + /* make them behave like normal sinks, even if not needed for the test */ + g_object_set (fakesink1, "sync", TRUE, NULL); + g_object_set (fakesink2, "sync", TRUE, NULL); + + g_object_set (playbin, "video-sink", fakesink1, NULL); + g_object_set (playbin, "audio-sink", fakesink2, NULL); + + g_object_set (playbin, "uri", uri, NULL); + + return playbin; +} + +DEFINE_TEST (test_missing_urisource_handler); + +static void +test_missing_urisource_handler (void) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + + playbin = create_playbin ("chocchipcookie://withahint.of/cinnamon"); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + /* there should be at least a missing-plugin message on the bus now and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), + "chocchipcookie"); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a CORE MISSING_PLUGIN one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code); + g_error_free (err); + gst_message_unref (msg); + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +DEFINE_TEST (test_missing_suburisource_handler); + +static void +test_missing_suburisource_handler (void) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + + playbin = create_playbin ("file:///does/not/exis.t"); + + g_object_set (playbin, "suburi", "cookie://withahint.of/cinnamon", NULL); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + /* there should be at least a missing-plugin message on the bus now and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "cookie"); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a CORE MISSING_PLUGIN one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code); + g_error_free (err); + gst_message_unref (msg); + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +DEFINE_TEST (test_missing_primary_decoder); + +static void +test_missing_primary_decoder (void) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + gchar *use_decodebin2 = getenv ("USE_DECODEBIN2"); + gboolean decodebin2 = use_decodebin2 != NULL && *use_decodebin2 == '1'; + + fail_unless (gst_element_register (NULL, "codecsrc", GST_RANK_PRIMARY, + gst_codec_src_get_type ())); + + playbin = create_playbin ("codec://"); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* there should soon be at least a missing-plugin message on the bus and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a STREAM CODEC_NOT_FOUND one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + if (decodebin2) { + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_RESOURCE_ERROR_MISSING_PLUGIN", err->code); + } else { + fail_unless (err->domain == GST_STREAM_ERROR, + "error has wrong error domain " "%s instead of stream-error-quark", + g_quark_to_string (err->domain)); + fail_unless (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND, + "error has wrong " + "code %u instead of GST_STREAM_ERROR_CODEC_NOT_FOUND", err->code); + } + g_error_free (err); + gst_message_unref (msg); + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +/*** redvideo:// source ***/ + +static GstURIType +gst_red_video_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_red_video_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "redvideo", NULL }; + + return protocols; +} + +static const gchar * +gst_red_video_src_uri_get_uri (GstURIHandler * handler) +{ + return "redvideo://"; +} + +static gboolean +gst_red_video_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + return (uri != NULL && g_str_has_prefix (uri, "redvideo:")); +} + +static void +gst_red_video_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_red_video_src_uri_get_type; + iface->get_protocols = gst_red_video_src_uri_get_protocols; + iface->get_uri = gst_red_video_src_uri_get_uri; + iface->set_uri = gst_red_video_src_uri_set_uri; +} + +static void +gst_red_video_src_init_type (GType type) +{ + static const GInterfaceInfo uri_hdlr_info = { + gst_red_video_src_uri_handler_init, NULL, NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info); +} + +typedef GstPushSrc GstRedVideoSrc; +typedef GstPushSrcClass GstRedVideoSrcClass; + +GST_BOILERPLATE_FULL (GstRedVideoSrc, gst_red_video_src, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_red_video_src_init_type); + +static void +gst_red_video_src_base_init (gpointer klass) +{ + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, format=(fourcc)I420") + ); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "Red Video Src", "Source/Video", "yep", "me"); +} + +static GstFlowReturn +gst_red_video_src_create (GstPushSrc * src, GstBuffer ** p_buf) +{ + GstBuffer *buf; + GstCaps *caps; + guint8 *data; + guint w = 64, h = 64; + guint size; + + size = w * h * 3 / 2; + buf = gst_buffer_new_and_alloc (size); + data = GST_BUFFER_DATA (buf); + memset (data, 76, w * h); + memset (data + (w * h), 85, (w * h) / 4); + memset (data + (w * h) + ((w * h) / 4), 255, (w * h) / 4); + + caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC ('I', '4', '2', '0'), "width", G_TYPE_INT, w, "height", + G_TYPE_INT, h, "framerate", GST_TYPE_FRACTION, 1, 1, NULL); + gst_buffer_set_caps (buf, caps); + gst_caps_unref (caps); + + *p_buf = buf; + return GST_FLOW_OK; +} + +static void +gst_red_video_src_class_init (GstRedVideoSrcClass * klass) +{ + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + + pushsrc_class->create = gst_red_video_src_create; +} + +static void +gst_red_video_src_init (GstRedVideoSrc * src, GstRedVideoSrcClass * klass) +{ +} + +/*** codec:// source ***/ + +static GstURIType +gst_codec_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_codec_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "codec", NULL }; + + return protocols; +} + +static const gchar * +gst_codec_src_uri_get_uri (GstURIHandler * handler) +{ + return "codec://"; +} + +static gboolean +gst_codec_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + return (uri != NULL && g_str_has_prefix (uri, "codec:")); +} + +static void +gst_codec_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_codec_src_uri_get_type; + iface->get_protocols = gst_codec_src_uri_get_protocols; + iface->get_uri = gst_codec_src_uri_get_uri; + iface->set_uri = gst_codec_src_uri_set_uri; +} + +static void +gst_codec_src_init_type (GType type) +{ + static const GInterfaceInfo uri_hdlr_info = { + gst_codec_src_uri_handler_init, NULL, NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info); +} + +#undef parent_class +#define parent_class codec_src_parent_class + +typedef GstPushSrc GstCodecSrc; +typedef GstPushSrcClass GstCodecSrcClass; + +GST_BOILERPLATE_FULL (GstCodecSrc, gst_codec_src, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_codec_src_init_type); + +static void +gst_codec_src_base_init (gpointer klass) +{ + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-codec") + ); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "Codec Src", "Source/Video", "yep", "me"); +} + +static GstFlowReturn +gst_codec_src_create (GstPushSrc * src, GstBuffer ** p_buf) +{ + GstBuffer *buf; + GstCaps *caps; + + buf = gst_buffer_new_and_alloc (20); + memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf)); + + caps = gst_caps_new_simple ("application/x-codec", NULL); + gst_buffer_set_caps (buf, caps); + gst_caps_unref (caps); + + *p_buf = buf; + return GST_FLOW_OK; +} + +static void +gst_codec_src_class_init (GstCodecSrcClass * klass) +{ + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + + pushsrc_class->create = gst_codec_src_create; +} + +static void +gst_codec_src_init (GstCodecSrc * src, GstCodecSrcClass * klass) +{ +} + +#endif /* GST_DISABLE_REGISTRY */ + + +static Suite * +playbin_suite (void) +{ + Suite *s = suite_create ("playbin"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + +#ifndef GST_DISABLE_REGISTRY + /* with the old decodebin */ + tcase_add_test (tc_chain, test_sink_usage_video_only_stream_decodebin1); + tcase_add_test (tc_chain, test_suburi_error_wrongproto_decodebin1); + tcase_add_test (tc_chain, test_suburi_error_invalidfile_decodebin1); + tcase_add_test (tc_chain, test_suburi_error_unknowntype_decodebin1); + tcase_add_test (tc_chain, test_missing_urisource_handler_decodebin1); + tcase_add_test (tc_chain, test_missing_suburisource_handler_decodebin1); + tcase_add_test (tc_chain, test_missing_primary_decoder_decodebin1); + + /* and again with decodebin2 */ + tcase_add_test (tc_chain, test_missing_primary_decoder_decodebin2); + tcase_add_test (tc_chain, test_sink_usage_video_only_stream_decodebin2); + tcase_add_test (tc_chain, test_suburi_error_wrongproto_decodebin2); + tcase_add_test (tc_chain, test_suburi_error_invalidfile_decodebin2); + tcase_add_test (tc_chain, test_suburi_error_unknowntype_decodebin2); + tcase_add_test (tc_chain, test_missing_urisource_handler_decodebin2); + tcase_add_test (tc_chain, test_missing_suburisource_handler_decodebin2); + + /* one day we might also want to have the following checks: + * tcase_add_test (tc_chain, test_missing_secondary_decoder_one_fatal); + * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_fatal); + * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_with_preroll); + */ +#endif + + return s; +} + +GST_CHECK_MAIN (playbin); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/playbin2.c b/gst-plugins-base-subtitles0.10/tests/check/elements/playbin2.c new file mode 100644 index 0000000..aef9272 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/playbin2.c @@ -0,0 +1,754 @@ +/* GStreamer unit tests for playbin2 + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include +#include + +#ifndef GST_DISABLE_REGISTRY + +static GType gst_red_video_src_get_type (void); +static GType gst_codec_src_get_type (void); + +/* make sure the audio sink is not touched for video-only streams */ +GST_START_TEST (test_sink_usage_video_only_stream) +{ + GstElement *playbin, *fakevideosink, *fakeaudiosink; + GstState cur_state, pending_state; + GstElement *source; + GstBuffer *last_frame; + gint nstreams; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakevideosink = gst_element_factory_make ("fakesink", "fakevideosink"); + fail_unless (fakevideosink != NULL, "Failed to create fakevideosink element"); + + fakeaudiosink = gst_element_factory_make ("fakesink", "fakeaudiosink"); + fail_unless (fakeaudiosink != NULL, "Failed to create fakeaudiosink element"); + + /* video-only stream, audiosink will error out in null => ready if used */ + g_object_set (fakeaudiosink, "state-error", 1, NULL); + + g_object_set (playbin, "video-sink", fakevideosink, NULL); + g_object_set (playbin, "audio-sink", fakeaudiosink, NULL); + + g_object_set (playbin, "uri", "redvideo://", NULL); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + fail_unless_equals_int (gst_element_get_state (fakeaudiosink, &cur_state, + &pending_state, 0), GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (cur_state, GST_STATE_NULL); + fail_unless_equals_int (pending_state, GST_STATE_VOID_PENDING); + + g_object_get (playbin, "n-video", &nstreams, NULL); + fail_unless_equals_int (nstreams, 1); + + g_object_get (playbin, "n-audio", &nstreams, NULL); + fail_unless_equals_int (nstreams, 0); + + g_object_get (playbin, "n-text", &nstreams, NULL); + fail_unless_equals_int (nstreams, 0); + + g_object_get (playbin, "source", &source, NULL); + fail_unless (G_TYPE_FROM_INSTANCE (source) == gst_red_video_src_get_type ()); + gst_object_unref (source); + + g_object_get (playbin, "frame", &last_frame, NULL); + fail_unless (GST_IS_BUFFER (last_frame)); + gst_buffer_unref (last_frame); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +/* this tests async error handling when setting up the subbin */ +GST_START_TEST (test_suburi_error_unknowntype) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* suburi file format unknown: playbin should just ignore the suburi and + * preroll normally (if /dev/zero does not exist, this test should behave + * the same as test_suburi_error_invalidfile() */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "file:///dev/zero", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +GST_START_TEST (test_suburi_error_invalidfile) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* suburi file does not exist: playbin should just ignore the suburi and + * preroll normally */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "file:///foo/bar/803129999/32x9ax1", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +GST_START_TEST (test_suburi_error_wrongproto) +{ + GstElement *playbin, *fakesink; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + fail_unless (fakesink != NULL, "Failed to create fakesink element"); + ASSERT_OBJECT_REFCOUNT (fakesink, "fakesink after creation", 1); + + g_object_set (playbin, "video-sink", fakesink, NULL); + + /* wrong protocol for suburi: playbin should just ignore the suburi and + * preroll normally */ + g_object_set (playbin, "uri", "redvideo://", NULL); + g_object_set (playbin, "suburi", "nosuchproto://foo.bar:80", NULL); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, -1), + GST_STATE_CHANGE_SUCCESS); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +static GstElement * +create_playbin (const gchar * uri) +{ + GstElement *playbin, *fakesink1, *fakesink2; + + playbin = gst_element_factory_make ("playbin2", "playbin2"); + fail_unless (playbin != NULL, "Failed to create playbin element"); + + fakesink1 = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink1 != NULL, "Failed to create fakesink element #1"); + + fakesink2 = gst_element_factory_make ("fakesink", NULL); + fail_unless (fakesink2 != NULL, "Failed to create fakesink element #2"); + + /* make them behave like normal sinks, even if not needed for the test */ + g_object_set (fakesink1, "sync", TRUE, NULL); + g_object_set (fakesink2, "sync", TRUE, NULL); + + g_object_set (playbin, "video-sink", fakesink1, NULL); + g_object_set (playbin, "audio-sink", fakesink2, NULL); + + g_object_set (playbin, "uri", uri, NULL); + + return playbin; +} + +GST_START_TEST (test_missing_urisource_handler) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + + playbin = create_playbin ("chocchipcookie://withahint.of/cinnamon"); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + /* there should be at least a missing-plugin message on the bus now and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), + "chocchipcookie"); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a CORE MISSING_PLUGIN one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code); + g_error_free (err); + gst_message_unref (msg); + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +GST_START_TEST (test_missing_suburisource_handler) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + + playbin = create_playbin ("file:///does/not/exis.t"); + + g_object_set (playbin, "suburi", "cookie://withahint.of/cinnamon", NULL); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_FAILURE); + + /* there should be at least a missing-plugin message on the bus now and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "cookie"); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_WARNING, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_WARNING); + + /* make sure the *warning* is a CORE MISSING_PLUGIN one */ + gst_message_parse_warning (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code); + g_error_free (err); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a RESOURCE NOT_FOUND one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_RESOURCE_ERROR, + "error has wrong error domain " "%s instead of resource-error-quark", + g_quark_to_string (err->domain)); + fail_unless (err->code == GST_RESOURCE_ERROR_NOT_FOUND, + "error has wrong " "code %u instead of GST_RESOURCE_ERROR_NOT_FOUND", + err->code); + g_error_free (err); + gst_message_unref (msg); + + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +GST_START_TEST (test_missing_primary_decoder) +{ + GstStructure *s; + GstMessage *msg; + GstElement *playbin; + GError *err = NULL; + GstBus *bus; + + fail_unless (gst_element_register (NULL, "codecsrc", GST_RANK_PRIMARY, + gst_codec_src_get_type ())); + + playbin = create_playbin ("codec://"); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_READY), + GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + + /* there should soon be at least a missing-plugin message on the bus and an + * error message; the missing-plugin message should be first */ + bus = gst_element_get_bus (playbin); + + msg = gst_bus_poll (bus, GST_MESSAGE_ELEMENT | GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_WARNING, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_WARNING); + + /* make sure the *warning* is a STREAM CODEC_NOT_FOUND one */ + gst_message_parse_warning (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_STREAM_ERROR, "error has wrong error domain " + "%s instead of stream-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_STREAM_ERROR_CODEC_NOT_FOUND, "error has wrong " + "code %u instead of GST_STREAM_ERROR_CODEC_NOT_FOUND", err->code); + g_error_free (err); + gst_message_unref (msg); + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, -1); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ERROR); + + /* make sure the error is a CORE MISSING_PLUGIN one */ + gst_message_parse_error (msg, &err, NULL); + fail_unless (err != NULL); + fail_unless (err->domain == GST_CORE_ERROR, "error has wrong error domain " + "%s instead of core-error-quark", g_quark_to_string (err->domain)); + fail_unless (err->code == GST_CORE_ERROR_MISSING_PLUGIN, "error has wrong " + "code %u instead of GST_CORE_ERROR_MISSING_PLUGIN", err->code); + g_error_free (err); + gst_message_unref (msg); + + gst_object_unref (bus); + + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); +} + +GST_END_TEST; + +GST_START_TEST (test_refcount) +{ + GstElement *playbin, *audiosink, *videosink, *vis; + + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + + playbin = gst_element_factory_make ("playbin2", NULL); + audiosink = gst_element_factory_make ("fakesink", "myaudiosink"); + videosink = gst_element_factory_make ("fakesink", "myvideosink"); + vis = gst_element_factory_make ("identity", "myvis"); + + /* ref because we need them after we unref playbin2 */ + gst_object_ref (audiosink); + gst_object_ref (videosink); + gst_object_ref (vis); + + /* Sinks have floating ref only, setting the properties takes ownership. */ + g_object_set (playbin, + "audio-sink", audiosink, + "video-sink", videosink, + "vis-plugin", vis, "flags", 0x01 | 0x02 | 0x08, NULL); + + g_object_set (playbin, "uri", "redvideo://", NULL); + //"uri", "file:///home/wim/data/cdda.ogg", NULL); + + ASSERT_OBJECT_REFCOUNT (playbin, "playbin", 1); + + /* we have two refs now, one from ourselves and one from playbin2 */ + ASSERT_OBJECT_REFCOUNT (audiosink, "myaudiosink", 2); + ASSERT_OBJECT_REFCOUNT (videosink, "myvideosink", 2); + ASSERT_OBJECT_REFCOUNT (vis, "myvis", 2); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, + GST_CLOCK_TIME_NONE), GST_STATE_CHANGE_SUCCESS); + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + ASSERT_OBJECT_REFCOUNT (playbin, "playbin", 1); + /* refcount of our elements is undefined, playbin2 might keep additional refs + * because it cached the elements in bins */ + gst_object_unref (playbin); + + /* now we are back to our refs */ + ASSERT_OBJECT_REFCOUNT (audiosink, "myaudiosink", 1); + ASSERT_OBJECT_REFCOUNT (videosink, "myvideosink", 1); + ASSERT_OBJECT_REFCOUNT (vis, "myvis", 1); + + gst_object_unref (audiosink); + gst_object_unref (videosink); + gst_object_unref (vis); +} + +GST_END_TEST; + +static void +source_setup (GstElement * playbin, GstElement * source, GstElement ** p_src) +{ + GST_LOG ("source-setup called, source = %s", G_OBJECT_TYPE_NAME (source)); + *p_src = gst_object_ref (source); + GST_LOG ("here"); +} + +GST_START_TEST (test_source_setup) +{ + GstElement *playbin, *videosink; + GstElement *src = NULL; + + if (!gst_default_registry_check_feature_version ("redvideosrc", 0, 10, 0)) { + fail_unless (gst_element_register (NULL, "redvideosrc", GST_RANK_PRIMARY, + gst_red_video_src_get_type ())); + } + + playbin = gst_element_factory_make ("playbin2", NULL); + g_object_set (playbin, "uri", "redvideo://", NULL); + + videosink = gst_element_factory_make ("fakesink", "myvideosink"); + g_object_set (playbin, "video-sink", videosink, NULL); + + g_signal_connect (playbin, "source-setup", G_CALLBACK (source_setup), &src); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_PAUSED), + GST_STATE_CHANGE_ASYNC); + fail_unless_equals_int (gst_element_get_state (playbin, NULL, NULL, + GST_CLOCK_TIME_NONE), GST_STATE_CHANGE_SUCCESS); + + fail_unless (src != NULL); + fail_unless (G_OBJECT_TYPE (src) == gst_red_video_src_get_type ()); + + fail_unless_equals_int (gst_element_set_state (playbin, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (playbin); + gst_object_unref (src); +} + +GST_END_TEST; + +/*** redvideo:// source ***/ + +static GstURIType +gst_red_video_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_red_video_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "redvideo", NULL }; + + return protocols; +} + +static const gchar * +gst_red_video_src_uri_get_uri (GstURIHandler * handler) +{ + return "redvideo://"; +} + +static gboolean +gst_red_video_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + return (uri != NULL && g_str_has_prefix (uri, "redvideo:")); +} + +static void +gst_red_video_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_red_video_src_uri_get_type; + iface->get_protocols = gst_red_video_src_uri_get_protocols; + iface->get_uri = gst_red_video_src_uri_get_uri; + iface->set_uri = gst_red_video_src_uri_set_uri; +} + +static void +gst_red_video_src_init_type (GType type) +{ + static const GInterfaceInfo uri_hdlr_info = { + gst_red_video_src_uri_handler_init, NULL, NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info); +} + +typedef GstPushSrc GstRedVideoSrc; +typedef GstPushSrcClass GstRedVideoSrcClass; + +GST_BOILERPLATE_FULL (GstRedVideoSrc, gst_red_video_src, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_red_video_src_init_type); + +static void +gst_red_video_src_base_init (gpointer klass) +{ + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, format=(fourcc)I420") + ); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "Red Video Src", "Source/Video", "yep", "me"); +} + +static GstFlowReturn +gst_red_video_src_create (GstPushSrc * src, GstBuffer ** p_buf) +{ + GstBuffer *buf; + GstCaps *caps; + guint8 *data; + guint w = 64, h = 64; + guint size; + + size = w * h * 3 / 2; + buf = gst_buffer_new_and_alloc (size); + data = GST_BUFFER_DATA (buf); + memset (data, 76, w * h); + memset (data + (w * h), 85, (w * h) / 4); + memset (data + (w * h) + ((w * h) / 4), 255, (w * h) / 4); + + caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC ('I', '4', '2', '0'), "width", G_TYPE_INT, w, "height", + G_TYPE_INT, h, "framerate", GST_TYPE_FRACTION, 1, 1, NULL); + gst_buffer_set_caps (buf, caps); + gst_caps_unref (caps); + + *p_buf = buf; + return GST_FLOW_OK; +} + +static void +gst_red_video_src_class_init (GstRedVideoSrcClass * klass) +{ + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + + pushsrc_class->create = gst_red_video_src_create; +} + +static void +gst_red_video_src_init (GstRedVideoSrc * src, GstRedVideoSrcClass * klass) +{ +} + +/*** codec:// source ***/ + +static GstURIType +gst_codec_src_uri_get_type (void) +{ + return GST_URI_SRC; +} + +static gchar ** +gst_codec_src_uri_get_protocols (void) +{ + static gchar *protocols[] = { (char *) "codec", NULL }; + + return protocols; +} + +static const gchar * +gst_codec_src_uri_get_uri (GstURIHandler * handler) +{ + return "codec://"; +} + +static gboolean +gst_codec_src_uri_set_uri (GstURIHandler * handler, const gchar * uri) +{ + return (uri != NULL && g_str_has_prefix (uri, "codec:")); +} + +static void +gst_codec_src_uri_handler_init (gpointer g_iface, gpointer iface_data) +{ + GstURIHandlerInterface *iface = (GstURIHandlerInterface *) g_iface; + + iface->get_type = gst_codec_src_uri_get_type; + iface->get_protocols = gst_codec_src_uri_get_protocols; + iface->get_uri = gst_codec_src_uri_get_uri; + iface->set_uri = gst_codec_src_uri_set_uri; +} + +static void +gst_codec_src_init_type (GType type) +{ + static const GInterfaceInfo uri_hdlr_info = { + gst_codec_src_uri_handler_init, NULL, NULL + }; + + g_type_add_interface_static (type, GST_TYPE_URI_HANDLER, &uri_hdlr_info); +} + +#undef parent_class +#define parent_class codec_src_parent_class + +typedef GstPushSrc GstCodecSrc; +typedef GstPushSrcClass GstCodecSrcClass; + +GST_BOILERPLATE_FULL (GstCodecSrc, gst_codec_src, GstPushSrc, + GST_TYPE_PUSH_SRC, gst_codec_src_init_type); + +static void +gst_codec_src_base_init (gpointer klass) +{ + static GstStaticPadTemplate src_templ = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-codec") + ); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_templ)); + gst_element_class_set_details_simple (element_class, + "Codec Src", "Source/Video", "yep", "me"); +} + +static GstFlowReturn +gst_codec_src_create (GstPushSrc * src, GstBuffer ** p_buf) +{ + GstBuffer *buf; + GstCaps *caps; + + buf = gst_buffer_new_and_alloc (20); + memset (GST_BUFFER_DATA (buf), 0, GST_BUFFER_SIZE (buf)); + + caps = gst_caps_new_simple ("application/x-codec", NULL); + gst_buffer_set_caps (buf, caps); + gst_caps_unref (caps); + + *p_buf = buf; + return GST_FLOW_OK; +} + +static void +gst_codec_src_class_init (GstCodecSrcClass * klass) +{ + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + + pushsrc_class->create = gst_codec_src_create; +} + +static void +gst_codec_src_init (GstCodecSrc * src, GstCodecSrcClass * klass) +{ +} + +#endif /* GST_DISABLE_REGISTRY */ + + +static Suite * +playbin2_suite (void) +{ + Suite *s = suite_create ("playbin2"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + +#ifndef GST_DISABLE_REGISTRY + tcase_add_test (tc_chain, test_sink_usage_video_only_stream); + tcase_add_test (tc_chain, test_suburi_error_wrongproto); + tcase_add_test (tc_chain, test_suburi_error_invalidfile); + tcase_add_test (tc_chain, test_suburi_error_unknowntype); + tcase_add_test (tc_chain, test_missing_urisource_handler); + tcase_add_test (tc_chain, test_missing_suburisource_handler); + tcase_add_test (tc_chain, test_missing_primary_decoder); + tcase_add_test (tc_chain, test_refcount); + tcase_add_test (tc_chain, test_source_setup); + + /* one day we might also want to have the following checks: + * tcase_add_test (tc_chain, test_missing_secondary_decoder_one_fatal); + * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_fatal); + * tcase_add_test (tc_chain, test_missing_secondary_decoder_two_with_preroll); + */ +#endif + + return s; +} + +GST_CHECK_MAIN (playbin2); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/subparse.c b/gst-plugins-base-subtitles0.10/tests/check/elements/subparse.c new file mode 100644 index 0000000..884140b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/subparse.c @@ -0,0 +1,719 @@ +/* GStreamer unit tests for subparse + * Copyright (C) 2006-2008 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include + +#include + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/plain; text/x-pango-markup") + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("ANY") + ); + +static GstElement *subparse; +static GstPad *mysrcpad, *mysinkpad; + +static GstBuffer * +buffer_from_static_string (const gchar * s) +{ + GstBuffer *buf; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) s; + GST_BUFFER_SIZE (buf) = strlen (s); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_READONLY); + + return buf; +} + +typedef struct +{ + const gchar *in; + GstClockTime from_ts; + GstClockTime to_ts; + const gchar *out; +} SubParseInputChunk; + +static SubParseInputChunk srt_input[] = { + { + "1\n00:00:01,000 --> 00:00:02,000\nOne\n\n", + 1 * GST_SECOND, 2 * GST_SECOND, "One"}, { + "2\n00:00:02,000 --> 00:00:03,000\nTwo\n\n", + 2 * GST_SECOND, 3 * GST_SECOND, "Two"}, { + "3\n00:00:03,000 --> 00:00:04,000\nThree\n\n", + 3 * GST_SECOND, 4 * GST_SECOND, "Three"}, { + "4\n00:00:04,000 --> 00:00:05,000\nFour\n\n", + 4 * GST_SECOND, 5 * GST_SECOND, "Four"}, { + "5\n00:00:05,000 --> 00:00:06,000\nFive\n\n", + 5 * GST_SECOND, 6 * GST_SECOND, "Five"}, { + /* markup should be preserved */ + "6\n00:00:06,000 --> 00:00:07,000\nSix\n\n", + 6 * GST_SECOND, 7 * GST_SECOND, "Six"}, { + /* open markup tags should be closed */ + "7\n00:00:07,000 --> 00:00:08,000\nSeven\n\n", + 7 * GST_SECOND, 8 * GST_SECOND, "Seven"}, { + /* open markup tags should be closed (II) */ + "8\n00:00:08,000 --> 00:00:09,000\nEight\n\n", + 8 * GST_SECOND, 9 * GST_SECOND, "Eight"}, { + /* broken markup should be fixed */ + "9\n00:00:09,000 --> 00:00:10,000\n\n\n", + 9 * GST_SECOND, 10 * GST_SECOND, ""}, { + "10\n00:00:10,000 --> 00:00:11,000\n\n\n", + 10 * GST_SECOND, 11 * GST_SECOND, ""}, { + "11\n00:00:11,000 --> 00:00:12,000\nxyz\n\n", + 11 * GST_SECOND, 12 * GST_SECOND, "xyz"}, { + "12\n00:00:12,000 --> 00:00:13,000\nxyz\n\n", + 12 * GST_SECOND, 13 * GST_SECOND, "xyz"}, { + /* skip a few chunk numbers here, the numbers shouldn't matter */ + "24\n00:01:00,000 --> 00:02:00,000\nYep, still here\n\n", + 60 * GST_SECOND, 120 * GST_SECOND, "Yep, still here"}, { + /* make sure stuff is escaped properly, but allowed markup stays intact */ + "25\n00:03:00,000 --> 00:04:00,000\ngave Rock & Roll to\n\n", + 180 * GST_SECOND, 240 * GST_SECOND, "gave Rock & Roll to"}, { + "26\n00:04:00,000 --> 00:05:00,000\nRock & Roll\n\n", + 240 * GST_SECOND, 300 * GST_SECOND, "Rock & Roll"}, { + "27\n00:06:00,000 --> 00:08:00,000\nRock & Roll\n\n", + 360 * GST_SECOND, 480 * GST_SECOND, "Rock & Roll"}, { + "28\n00:10:00,000 --> 00:11:00,000\n" + "This is in blue but <5\n\n", + 600 * GST_SECOND, 660 * GST_SECOND, "This is in blue but <5"} +}; + +/* starts with chunk number 0 (not exactly according to spec) */ +static SubParseInputChunk srt_input0[] = { + { + "0\n00:00:01,000 --> 00:00:02,000\nOne\n\n", + 1 * GST_SECOND, 2 * GST_SECOND, "One"}, { + "1\n00:00:02,000 --> 00:00:03,000\nTwo\n\n", + 2 * GST_SECOND, 3 * GST_SECOND, "Two"}, { + "2\n00:00:03,000 --> 00:00:04,000\nThree\n\n", + 3 * GST_SECOND, 4 * GST_SECOND, "Three"} +}; + +/* has spaces instead of doubled zeroes (not exactly according to spec) */ +static SubParseInputChunk srt_input1[] = { + { + "1\n 0: 0:26, 26 --> 0: 0:28, 17\nI cant see.\n\n", + 26 * GST_SECOND + 26 * GST_MSECOND, + 28 * GST_SECOND + 17 * GST_MSECOND, "I cant see."}, + { + "2\n 0: 0:30, 30 --> 0: 0:33, 22\nI really cant see.\n\n", + 30 * GST_SECOND + 30 * GST_MSECOND, + 33 * GST_SECOND + 22 * GST_MSECOND, "I really cant see."}, + { + "3\n 0: 0:40, 40 --> 0: 0:44, 44\nI still cant see anything.\n\n", + 40 * GST_SECOND + 40 * GST_MSECOND, + 44 * GST_SECOND + 44 * GST_MSECOND, "I still cant see anything."} +}; + +/* has UTF-8 BOM at the start */ +static SubParseInputChunk srt_input2[] = { + { + "\xef\xbb\xbf" "1\n00:00:00,000 --> 00:00:03,50\nJust testing.\n\n", + 0, 3 * GST_SECOND + 50 * GST_MSECOND, "Just testing."} +}; + +/* starts with chunk number 0 and has less than three digits after the comma + * and a few extra spaces before the arrow or at the end of the line */ +static SubParseInputChunk srt_input3[] = { + { + "0\n00:00:01,0 --> 00:00:02,0\nOne\n\n", + 1000 * GST_MSECOND, 2000 * GST_MSECOND, "One"}, { + "1\n00:00:02,5 --> 00:00:03, 5 \nTwo\n\n", + 2500 * GST_MSECOND, 3005 * GST_MSECOND, "Two"}, { + "2\n00:00:03, 9 --> 00:00:04,0 \nThree\n\n", + 3090 * GST_MSECOND, 4000 * GST_MSECOND, "Three"} +}; + +static void +setup_subparse (void) +{ + subparse = gst_check_setup_element ("subparse"); + + mysrcpad = gst_check_setup_src_pad (subparse, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (subparse, &sinktemplate, NULL); + + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + fail_unless_equals_int (gst_element_set_state (subparse, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); +} + +static void +teardown_subparse (void) +{ + GST_DEBUG ("cleaning up"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (subparse); + gst_check_teardown_src_pad (subparse); + gst_check_teardown_element (subparse); + subparse = NULL; + mysrcpad = NULL; + mysinkpad = NULL; +} + +static void +test_srt_do_test (SubParseInputChunk * input, guint start_idx, guint num) +{ + guint n; + + GST_LOG ("srt test: start_idx = %u, num = %u", start_idx, num); + + setup_subparse (); + + for (n = start_idx; n < start_idx + num; ++n) { + GstBuffer *buf; + + buf = buffer_from_static_string (input[n].in); + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); + } + + gst_pad_push_event (mysrcpad, gst_event_new_eos ()); + + fail_unless_equals_int (g_list_length (buffers), num); + + for (n = start_idx; n < start_idx + num; ++n) { + const GstStructure *buffer_caps_struct; + GstBuffer *buf; + gchar *out; + guint out_size; + + buf = g_list_nth_data (buffers, n - start_idx); + fail_unless (buf != NULL); + fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL); + fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts); + fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf), + input[n].to_ts - input[n].from_ts); + out = (gchar *) GST_BUFFER_DATA (buf); + out_size = GST_BUFFER_SIZE (buf); + /* shouldn't have trailing newline characters */ + fail_if (out_size > 0 && out[out_size - 1] == '\n'); + /* shouldn't include NUL-terminator in data size */ + fail_if (out_size > 0 && out[out_size - 1] == '\0'); + /* but should still have a NUL-terminator behind the declared data */ + fail_unless_equals_int (out[out_size], '\0'); + /* make sure out string matches expected string */ + fail_unless_equals_string (out, input[n].out); + /* check caps */ + fail_unless (GST_BUFFER_CAPS (buf) != NULL); + buffer_caps_struct = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + fail_unless_equals_string (gst_structure_get_name (buffer_caps_struct), + "text/x-pango-markup"); + } + + teardown_subparse (); +} + +GST_START_TEST (test_srt) +{ + test_srt_do_test (srt_input, 0, G_N_ELEMENTS (srt_input)); + + /* make sure everything works fine if we don't start with chunk 1 */ + test_srt_do_test (srt_input, 1, G_N_ELEMENTS (srt_input) - 1); + test_srt_do_test (srt_input, 2, G_N_ELEMENTS (srt_input) - 2); + test_srt_do_test (srt_input, 3, G_N_ELEMENTS (srt_input) - 3); + test_srt_do_test (srt_input, 4, G_N_ELEMENTS (srt_input) - 4); + + /* try with empty input, immediate EOS */ + test_srt_do_test (srt_input, 5, G_N_ELEMENTS (srt_input) - 5); + + /* try with chunk number 0 (which is not exactly according to spec) */ + test_srt_do_test (srt_input0, 0, G_N_ELEMENTS (srt_input0)); + + /* try with spaces instead of doubled zeroes (which is not exactly according to spec) */ + test_srt_do_test (srt_input1, 0, G_N_ELEMENTS (srt_input1)); + + /* try with UTF-8 BOM at the start */ + test_srt_do_test (srt_input1, 0, G_N_ELEMENTS (srt_input2)); + + /* try with fewer than three post-comma digits, and some extra spaces */ + test_srt_do_test (srt_input3, 0, G_N_ELEMENTS (srt_input3)); +} + +GST_END_TEST; + +static void +do_test (SubParseInputChunk * input, guint num, const gchar * media_type) +{ + guint n; + + setup_subparse (); + + for (n = 0; n < num; ++n) { + GstBuffer *buf; + + buf = buffer_from_static_string (input[n].in); + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_OK); + } + + gst_pad_push_event (mysrcpad, gst_event_new_eos ()); + + fail_unless_equals_int (g_list_length (buffers), num); + + for (n = 0; n < num; ++n) { + const GstStructure *buffer_caps_struct; + GstBuffer *buf; + gchar *out; + guint out_size; + + buf = g_list_nth_data (buffers, n); + fail_unless (buf != NULL); + + /* check timestamp */ + fail_unless (GST_BUFFER_TIMESTAMP_IS_VALID (buf), NULL); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (buf), input[n].from_ts); + + /* might not be able to put a duration on the last buffer */ + if (input[n].to_ts != GST_CLOCK_TIME_NONE) { + /* check duration */ + fail_unless (GST_BUFFER_DURATION_IS_VALID (buf), NULL); + fail_unless_equals_uint64 (GST_BUFFER_DURATION (buf), + input[n].to_ts - input[n].from_ts); + } + + out = (gchar *) GST_BUFFER_DATA (buf); + out_size = GST_BUFFER_SIZE (buf); + /* shouldn't have trailing newline characters */ + fail_if (out_size > 0 && out[out_size - 1] == '\n'); + /* shouldn't include NUL-terminator in data size */ + fail_if (out_size > 0 && out[out_size - 1] == '\0'); + /* but should still have a NUL-terminator behind the declared data */ + fail_unless_equals_int (out[out_size], '\0'); + /* make sure out string matches expected string */ + fail_unless_equals_string (out, input[n].out); + /* check caps */ + fail_unless (GST_BUFFER_CAPS (buf) != NULL); + buffer_caps_struct = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + fail_unless_equals_string (gst_structure_get_name (buffer_caps_struct), + media_type); + } + + teardown_subparse (); +} + +static void +test_tmplayer_do_test (SubParseInputChunk * input, guint num) +{ + do_test (input, num, "text/plain"); +} + +static void +test_microdvd_do_test (SubParseInputChunk * input, guint num) +{ + do_test (input, num, "text/x-pango-markup"); +} + +GST_START_TEST (test_tmplayer_multiline) +{ + static SubParseInputChunk tmplayer_multiline_input[] = { + { + "00:00:10,1=This is the Earth at a time\n" + "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_multiline_input, + G_N_ELEMENTS (tmplayer_multiline_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_multiline_with_bogus_lines) +{ + static SubParseInputChunk tmplayer_multiline_b_input[] = { + { + "00:00:10,1=This is the Earth at a time\n" + "Yooboo wabahablablahuguug bogus line hello test 1-2-3-4\n" + "00:00:10,2=when the dinosaurs roamed...\n" "00:00:13,1=\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "00:00:14,1=a lush and fertile planet.\n" "00:00:16,1=\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_multiline_b_input, + G_N_ELEMENTS (tmplayer_multiline_b_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_style1) +{ + static SubParseInputChunk tmplayer_style1_input[] = { + { + "00:00:10:This is the Earth at a time|when the dinosaurs roamed...\n" + "00:00:13:\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "00:00:14:a lush and fertile planet.\n" "00:00:16:\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_style1_input, + G_N_ELEMENTS (tmplayer_style1_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_style2) +{ + static SubParseInputChunk tmplayer_style2_input[] = { + { + "00:00:10=This is the Earth at a time|when the dinosaurs roamed...\n" + "00:00:13=\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "00:00:14=a lush and fertile planet.\n" "00:00:16=\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_style2_input, + G_N_ELEMENTS (tmplayer_style2_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_style3) +{ + static SubParseInputChunk tmplayer_style3_input[] = { + { + "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n" + "0:00:13:\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "0:00:14:a lush and fertile planet.\n" "0:00:16:\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_style3_input, + G_N_ELEMENTS (tmplayer_style3_input)); +} + +GST_END_TEST; + +/* also tests the max_duration stuff (see second-last chunk which is supposed + * to be clipped to 5s duration) */ +GST_START_TEST (test_tmplayer_style3b) +{ + static SubParseInputChunk tmplayer_style3b_input[] = { + { + "0:00:10:This is the Earth at a time|when the dinosaurs roamed...\n", + 10 * GST_SECOND, 14 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "0:00:14:a lush and fertile planet.\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."}, { + "0:00:16:And they liked it a lot.\n", + 16 * GST_SECOND, (16 + 5) * GST_SECOND, "And they liked it a lot."}, { + "0:00:30:Last line.", + 30 * GST_SECOND, GST_CLOCK_TIME_NONE, "Last line."} + }; + + test_tmplayer_do_test (tmplayer_style3b_input, + G_N_ELEMENTS (tmplayer_style3b_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_style4) +{ + static SubParseInputChunk tmplayer_style4_input[] = { + { + "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n" + "0:00:13=\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "0:00:14=a lush and fertile planet.\n" "0:00:16=\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_style4_input, + G_N_ELEMENTS (tmplayer_style4_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_tmplayer_style4_with_bogus_lines) +{ + static SubParseInputChunk tmplayer_style4b_input[] = { + { + "0:00:10=This is the Earth at a time|when the dinosaurs roamed...\n" + "# This is a bogus line with a comment and should just be skipped\n" + "0:00:13=\n", + 10 * GST_SECOND, 13 * GST_SECOND, + "This is the Earth at a time\nwhen the dinosaurs roamed..."}, { + "0:00:14=a lush and fertile planet.\n" + " \n" + "0:00:16=\n", + 14 * GST_SECOND, 16 * GST_SECOND, + "a lush and fertile planet."} + }; + + test_tmplayer_do_test (tmplayer_style4b_input, + G_N_ELEMENTS (tmplayer_style4b_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_microdvd_with_italics) +{ + static SubParseInputChunk microdvd_italics[] = { + { + "{1}{1}25.000 movie info: XVID 608x256 25.0fps 699.0 MB|" + "/SubEdit b.4060(http://subedit.com.pl)/\n" + "{100}{200}/italics/|not italics\n", + 4 * GST_SECOND, 8 * GST_SECOND, + "italics\n" "not italics"} + }; + + test_microdvd_do_test (microdvd_italics, G_N_ELEMENTS (microdvd_italics)); +} + +GST_END_TEST; + +GST_START_TEST (test_microdvd_with_fps) +{ + static SubParseInputChunk microdvd_input[] = { + { + "{1}{1}12.500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n", + 8 * GST_SECOND, 16 * GST_SECOND, + "- Hi, Eddie.\n- Hiya, Scotty."}, { + "{1250}{1350}- Cold enough for you?|- Well, I'm only faintly alive. " + "It's 25 below\n", + 100 * GST_SECOND, 108 * GST_SECOND, + "- Cold enough for you?\n" + "- Well, I'm only faintly alive. It's 25 below"} + }; + + test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input)); + + /* and the same with ',' instead of '.' as floating point divider */ + microdvd_input[0].in = + "{1}{1}12,500\n{100}{200}- Hi, Eddie.|- Hiya, Scotty.\n"; + test_microdvd_do_test (microdvd_input, G_N_ELEMENTS (microdvd_input)); +} + +GST_END_TEST; + +GST_START_TEST (test_mpl2) +{ + SubParseInputChunk mpl2_input[] = { + { + "[123][456] This is the Earth at a time|when the dinosaurs roamed\n", + (123 * GST_SECOND) / 10, (456 * GST_SECOND) / 10, + "This is the Earth at a time\nwhen the dinosaurs roamed"}, { + "[1234][5678]a lush and fertile planet.\n", + (1234 * GST_SECOND) / 10, (5678 * GST_SECOND) / 10, + "a lush and fertile planet."}, { + "[12345][27890] /Italic|Normal\n", + (12345 * GST_SECOND) / 10, (27890 * GST_SECOND) / 10, + "Italic\nNormal"}, { + "[32345][37890]/Italic|/Italic\n", + (32345 * GST_SECOND) / 10, (37890 * GST_SECOND) / 10, + "Italic\nItalic"}, { + "[42345][47890] Normal|/Italic", + (42345 * GST_SECOND) / 10, (47890 * GST_SECOND) / 10, + "Normal\nItalic"} + }; + + do_test (mpl2_input, G_N_ELEMENTS (mpl2_input), "text/x-pango-markup"); +} + +GST_END_TEST; + +GST_START_TEST (test_subviewer) +{ + SubParseInputChunk subviewer_input[] = { + { + "[INFORMATION]\n" + "[TITLE]xxxxxxxxxx\n" + "[AUTHOR]xxxxxxxx\n" + "[SOURCE]xxxxxxxxxxxxxxxx\n" + "[FILEPATH]\n" + "[DELAY]0\n" + "[COMMENT]\n" + "[END INFORMATION]\n" + "[SUBTITLE]\n" + "[COLF]&HFFFFFF,[STYLE]bd,[SIZE]18,[FONT]Arial\n" + "00:00:41.00,00:00:44.40\n" + "The Age of Gods was closing.\n" + "Eternity had come to an end.\n" + "\n", 41 * GST_SECOND, 44 * GST_SECOND + 40 * GST_MSECOND, + "The Age of Gods was closing.\nEternity had come to an end."}, { + "00:00:55.00,00:00:58.40\n" + "The heavens shook as the armies\n" + "of Falis, God of Light...\n\n", 55 * GST_SECOND, + 58 * GST_SECOND + 40 * GST_MSECOND, + "The heavens shook as the armies\nof Falis, God of Light..."} + }; + + do_test (subviewer_input, G_N_ELEMENTS (subviewer_input), "text/plain"); +} + +GST_END_TEST; + +GST_START_TEST (test_subviewer2) +{ + SubParseInputChunk subviewer2_input[] = { + { + "[INFORMATION]\n" + "[TITLE]xxxxxxxxxx\n" + "[AUTHOR]xxxxxxxxxx\n" + "[SOURCE]xxxxxxxxxx\n" + "[PRG]\n" + "[FILEPATH]\n" + "[DELAY]0\n" + "[CD TRACK]0\n" + "[COMMENT]\n" + "[END INFORMATION]\n" + "[SUBTITLE]\n" + "[COLF]&H00FFFF,[STYLE]no,[SIZE]12,[FONT]Courier New\n" + "00:00:07.00,00:00:11.91\n" + "THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n\n", + 7 * GST_SECOND, 11 * GST_SECOND + 91 * GST_MSECOND, + "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, { + "00:00:12.48,00:00:15.17\n" + "AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n\n", + 12 * GST_SECOND + 48 * GST_MSECOND, + 15 * GST_SECOND + 17 * GST_MSECOND, + "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"} + }; + + do_test (subviewer2_input, G_N_ELEMENTS (subviewer2_input), "text/plain"); +} + +GST_END_TEST; + +GST_START_TEST (test_dks) +{ + SubParseInputChunk dks_input[] = { + { + "[00:00:07]THERE IS A PLACE ON EARTH WHERE IT[br]IS STILL THE MORNING OF LIFE...\n[00:00:12]\n", + 7 * GST_SECOND, 12 * GST_SECOND, + "THERE IS A PLACE ON EARTH WHERE IT\nIS STILL THE MORNING OF LIFE..."}, { + "[00:00:13]AND THE GREAT HERDS RUN FREE.[br]SO WHAT?!\n[00:00:15]\n", + 13 * GST_SECOND, 15 * GST_SECOND, + "AND THE GREAT HERDS RUN FREE.\nSO WHAT?!"} + }; + + do_test (dks_input, G_N_ELEMENTS (dks_input), "text/plain"); +} + +GST_END_TEST; + +#ifndef GST_DISABLE_XML +GST_START_TEST (test_sami) +{ + SubParseInputChunk sami_input[] = { + {"\n" + "\n" + " Subtitle\n" + " \n" + "\n" + "\n" + " \n" + "

\n" + " This is a comment.
\n" + " This is a second comment.\n", + 1000 * GST_MSECOND, 2000 * GST_MSECOND, + "This is a comment.\nThis is a second comment."}, + {" \n" + "

\n" + " This is a third comment.
\n" + " This is a fourth comment.\n" "\n" "\n", + 2000 * GST_MSECOND, GST_CLOCK_TIME_NONE, + "This is a third comment.\nThis is a fourth comment."} + }; + + do_test (sami_input, G_N_ELEMENTS (sami_input), "text/x-pango-markup"); +} + +GST_END_TEST; +#endif + +/* TODO: + * - add/modify tests so that lines aren't dogfed to the parsers in complete + * lines or sets of complete lines, but rather in random chunks + */ + +static Suite * +subparse_suite (void) +{ + Suite *s = suite_create ("subparse"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_srt); + tcase_add_test (tc_chain, test_tmplayer_multiline); + tcase_add_test (tc_chain, test_tmplayer_multiline_with_bogus_lines); + tcase_add_test (tc_chain, test_tmplayer_style1); + tcase_add_test (tc_chain, test_tmplayer_style2); + tcase_add_test (tc_chain, test_tmplayer_style3); + tcase_add_test (tc_chain, test_tmplayer_style3b); + tcase_add_test (tc_chain, test_tmplayer_style4); + tcase_add_test (tc_chain, test_tmplayer_style4_with_bogus_lines); + tcase_add_test (tc_chain, test_microdvd_with_fps); + tcase_add_test (tc_chain, test_microdvd_with_italics); + tcase_add_test (tc_chain, test_mpl2); + tcase_add_test (tc_chain, test_subviewer); + tcase_add_test (tc_chain, test_subviewer2); + tcase_add_test (tc_chain, test_dks); +#ifndef GST_DISABLE_XML + tcase_add_test (tc_chain, test_sami); +#endif + return s; +} + +GST_CHECK_MAIN (subparse); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/textoverlay.c b/gst-plugins-base-subtitles0.10/tests/check/elements/textoverlay.c new file mode 100644 index 0000000..3c970b2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/textoverlay.c @@ -0,0 +1,751 @@ +/* GStreamer unit tests for textoverlay + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#define I420_Y_ROWSTRIDE(width) (GST_ROUND_UP_4(width)) +#define I420_U_ROWSTRIDE(width) (GST_ROUND_UP_8(width)/2) +#define I420_V_ROWSTRIDE(width) ((GST_ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2) + +#define I420_Y_OFFSET(w,h) (0) +#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*GST_ROUND_UP_2(h))) +#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*GST_ROUND_UP_2(h)/2)) + +#define WIDTH 240 +#define HEIGHT 120 + +/* 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 *myvideosrcpad, *mytextsrcpad, *mysinkpad; + +#define VIDEO_CAPS_STRING \ + "video/x-raw-yuv, " \ + "format = (fourcc) I420, " \ + "framerate = (fraction) 1/1, " \ + "width = (int) 240, " \ + "height = (int) 120" + +#define VIDEO_CAPS_TEMPLATE_STRING \ + "video/x-raw-yuv, " \ + "format = (fourcc) I420" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate text_srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("text/plain") + ); + +static GstStaticPadTemplate video_srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING) + ); + +/* much like gst_check_setup_src_pad(), but with possibility to give a hint + * which sink template of the element to use, if there are multiple ones */ +static GstPad * +notgst_check_setup_src_pad2 (GstElement * element, + GstStaticPadTemplate * template, GstCaps * caps, + const gchar * sink_template_name) +{ + GstPad *srcpad, *sinkpad; + + if (sink_template_name == NULL) + sink_template_name = "sink"; + + /* sending pad */ + srcpad = gst_pad_new_from_static_template (template, "src"); + GST_DEBUG_OBJECT (element, "setting up sending pad %p", srcpad); + fail_if (srcpad == NULL, "Could not create a srcpad"); + ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); + + if (!(sinkpad = gst_element_get_static_pad (element, sink_template_name))) + sinkpad = gst_element_get_request_pad (element, sink_template_name); + fail_if (sinkpad == NULL, "Could not get sink pad from %s", + GST_ELEMENT_NAME (element)); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); + if (caps) + fail_unless (gst_pad_set_caps (srcpad, caps)); + 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 */ + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1); + + return srcpad; +} + +static void +notgst_check_teardown_src_pad2 (GstElement * element, + const gchar * sink_template_name) +{ + GstPad *srcpad, *sinkpad; + + if (sink_template_name == NULL) + sink_template_name = "sink"; + + /* clean up floating src pad */ + if (!(sinkpad = gst_element_get_static_pad (element, sink_template_name))) + sinkpad = gst_element_get_request_pad (element, sink_template_name); + ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2); + srcpad = gst_pad_get_peer (sinkpad); + + gst_pad_unlink (srcpad, sinkpad); + + /* caps could have been set, make sure they get unset */ + gst_pad_set_caps (srcpad, NULL); + + /* pad refs held by both creator and this function (through _get) */ + ASSERT_OBJECT_REFCOUNT (sinkpad, "element sinkpad", 2); + gst_object_unref (sinkpad); + /* one more ref is held by element itself */ + + /* pad refs held by both creator and this function (through _get_peer) */ + ASSERT_OBJECT_REFCOUNT (srcpad, "check srcpad", 2); + gst_object_unref (srcpad); + gst_object_unref (srcpad); +} + +static GstElement * +setup_textoverlay (gboolean video_only_no_text) +{ + GstElement *textoverlay; + + GST_DEBUG ("setup_textoverlay"); + textoverlay = gst_check_setup_element ("textoverlay"); + mysinkpad = gst_check_setup_sink_pad (textoverlay, &sinktemplate, NULL); + myvideosrcpad = + notgst_check_setup_src_pad2 (textoverlay, &video_srctemplate, NULL, + "video_sink"); + + if (!video_only_no_text) { + mytextsrcpad = + notgst_check_setup_src_pad2 (textoverlay, &text_srctemplate, NULL, + "text_sink"); + gst_pad_set_active (mytextsrcpad, TRUE); + } else { + mytextsrcpad = NULL; + } + + gst_pad_set_active (myvideosrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return textoverlay; +} + +static gboolean +buffer_is_all_black (GstBuffer * buf) +{ + GstStructure *s; + gint x, y, w, h; + + fail_unless (buf != NULL); + fail_unless (GST_BUFFER_CAPS (buf) != NULL); + s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + fail_unless (s != NULL); + fail_unless (gst_structure_get_int (s, "width", &w)); + fail_unless (gst_structure_get_int (s, "height", &h)); + + for (y = 0; y < h; ++y) { + guint8 *data = GST_BUFFER_DATA (buf) + (y * GST_ROUND_UP_4 (w)); + + for (x = 0; x < w; ++x) { + if (data[x] != 0x00) { + GST_LOG ("non-black pixel at (x,y) %d,%d", x, y); + return FALSE; + } + } + } + + return TRUE; +} + +static GstBuffer * +create_black_buffer (const gchar * caps_string) +{ + GstStructure *s; + GstBuffer *buffer; + GstCaps *caps; + gint w, h, size; + + fail_unless (caps_string != NULL); + + caps = gst_caps_from_string (caps_string); + fail_unless (caps != NULL); + fail_unless (gst_caps_is_fixed (caps)); + + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_get_int (s, "width", &w)); + fail_unless (gst_structure_get_int (s, "height", &h)); + + GST_LOG ("creating buffer (%dx%d)", w, h); + size = I420_SIZE (w, h); + buffer = gst_buffer_new_and_alloc (size); + /* we're only checking the Y plane later, so just zero it all out, + * even if it's not the blackest black there is */ + memset (GST_BUFFER_DATA (buffer), 0, size); + + gst_buffer_set_caps (buffer, caps); + gst_caps_unref (caps); + + /* double check to make sure it's been created right */ + fail_unless (buffer_is_all_black (buffer)); + + return buffer; +} + +static GstBuffer * +create_text_buffer (const gchar * txt, GstClockTime ts, GstClockTime duration) +{ + GstBuffer *buffer; + GstCaps *caps; + guint txt_len; + + fail_unless (txt != NULL); + + txt_len = strlen (txt); + + buffer = gst_buffer_new_and_alloc (txt_len); + memcpy (GST_BUFFER_DATA (buffer), txt, txt_len); + + GST_BUFFER_TIMESTAMP (buffer) = ts; + GST_BUFFER_DURATION (buffer) = duration; + + caps = gst_caps_new_simple ("text/plain", NULL); + gst_buffer_set_caps (buffer, caps); + gst_caps_unref (caps); + + return buffer; +} + +static void +cleanup_textoverlay (GstElement * textoverlay) +{ + GST_DEBUG ("cleanup_textoverlay"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + gst_element_set_state (textoverlay, GST_STATE_NULL); + gst_element_get_state (textoverlay, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_pad_set_active (myvideosrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + notgst_check_teardown_src_pad2 (textoverlay, "video_sink"); + if (mytextsrcpad) { + notgst_check_teardown_src_pad2 (textoverlay, "text_sink"); + } + gst_check_teardown_sink_pad (textoverlay); + gst_check_teardown_element (textoverlay); +} + +GST_START_TEST (test_video_passthrough) +{ + GstElement *textoverlay; + GstBuffer *inbuffer; + + textoverlay = setup_textoverlay (TRUE); + fail_unless (gst_element_set_state (textoverlay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = create_black_buffer (VIDEO_CAPS_STRING); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* ========== (1) video buffer without timestamp => should be dropped ==== */ + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* should have been discarded as out-of-segment since it has no timestamp */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* ========== (2) buffer with 0 timestamp => simple passthrough ========== */ + + /* now try again, this time with timestamp (segment defaults to 0 start) */ + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_DURATION (inbuffer) = GST_CLOCK_TIME_NONE; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* text pad is not linked, timestamp is in segment, no static text to + * render, should have gone through right away without modification */ + fail_unless_equals_int (g_list_length (buffers), 1); + fail_unless (GST_BUFFER_CAST (buffers->data) == inbuffer); + fail_unless (buffer_is_all_black (inbuffer)); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* and clean up */ + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* ========== (3) buffer with 0 timestamp and no duration, with the + * segment starting from 1sec => should be discarded */ + + gst_pad_push_event (myvideosrcpad, + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 1 * GST_SECOND, + -1, 0)); + + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_DURATION (inbuffer) = GST_CLOCK_TIME_NONE; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* should have been discarded as out-of-segment */ + fail_unless_equals_int (g_list_length (buffers), 0); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* ========== (4) buffer with 0 timestamp and small defined duration, with + * segment starting from 1sec => should be discarded */ + + gst_pad_push_event (myvideosrcpad, + gst_event_new_new_segment (FALSE, 1.0, 1 * GST_FORMAT_TIME, GST_SECOND, + -1, 0)); + + GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 10; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* should have been discareded as out-of-segment since it has no timestamp */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* ========== (5) buffer partially overlapping into the segment => should + * be pushed through, but with adjusted stamp values */ + + gst_pad_push_event (myvideosrcpad, + gst_event_new_new_segment (FALSE, 1.0, 1 * GST_FORMAT_TIME, GST_SECOND, + -1, 0)); + + GST_BUFFER_TIMESTAMP (inbuffer) = GST_SECOND / 4; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* should be the parent for a new subbuffer for the stamp fix-up */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_unless (GST_BUFFER_CAST (buffers->data) != inbuffer); + fail_unless (GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (buffers->data)) == + GST_SECOND); + fail_unless (GST_BUFFER_DURATION (GST_BUFFER_CAST (buffers->data)) == + (GST_SECOND / 4)); + fail_unless (buffer_is_all_black (GST_BUFFER_CAST (buffers->data))); + /* and clean up */ + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* cleanup */ + cleanup_textoverlay (textoverlay); + gst_buffer_unref (inbuffer); +} + +GST_END_TEST; + +GST_START_TEST (test_video_render_static_text) +{ + GstElement *textoverlay; + GstBuffer *inbuffer; + + textoverlay = setup_textoverlay (TRUE); + + /* set static text to render */ + g_object_set (textoverlay, "text", "XLX", NULL); + + fail_unless (gst_element_set_state (textoverlay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = create_black_buffer (VIDEO_CAPS_STRING); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 10; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* should have been dropped in favour of a new writable buffer */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_unless (GST_BUFFER_CAST (buffers->data) != inbuffer); + + /* there should be text rendered */ + fail_unless (buffer_is_all_black (GST_BUFFER_CAST (buffers->data)) == FALSE); + + fail_unless (GST_BUFFER_TIMESTAMP (GST_BUFFER_CAST (buffers->data)) == 0); + fail_unless (GST_BUFFER_DURATION (GST_BUFFER_CAST (buffers->data)) == + (GST_SECOND / 10)); + + /* and clean up */ + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* cleanup */ + cleanup_textoverlay (textoverlay); + gst_buffer_unref (inbuffer); +} + +GST_END_TEST; + +static gpointer +test_video_waits_for_text_send_text_newsegment_thread (gpointer data) +{ + g_usleep (1 * G_USEC_PER_SEC); + + /* send an update newsegment; the video buffer should now be pushed through + * even though there is no text buffer queued at the moment */ + GST_INFO ("Sending newsegment update on text pad"); + gst_pad_push_event (mytextsrcpad, + gst_event_new_new_segment (TRUE, 1.0, GST_FORMAT_TIME, + 35 * GST_SECOND, -1, 35 * GST_SECOND)); + + return NULL; +} + +static gpointer +test_video_waits_for_text_shutdown_element (gpointer data) +{ + g_usleep (1 * G_USEC_PER_SEC); + + GST_INFO ("Trying to shut down textoverlay element ..."); + /* set to NULL state to make sure we can shut it down while it's + * blocking in the video chain function waiting for a text buffer */ + gst_element_set_state (GST_ELEMENT (data), GST_STATE_NULL); + GST_INFO ("Done."); + + return NULL; +} + +GST_START_TEST (test_video_waits_for_text) +{ + GstElement *textoverlay; + GstBuffer *inbuffer, *tbuf; + GThread *thread; + + textoverlay = setup_textoverlay (FALSE); + + fail_unless (gst_element_set_state (textoverlay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + tbuf = create_text_buffer ("XLX", 1 * GST_SECOND, 5 * GST_SECOND); + gst_buffer_ref (tbuf); + ASSERT_BUFFER_REFCOUNT (tbuf, "tbuf", 2); + + GST_LOG ("pushing text buffer"); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + /* it should be stuck in textoverlay until it gets a text buffer or a + * newsegment event that indicates it's not needed any longer */ + fail_unless_equals_int (g_list_length (buffers), 0); + + inbuffer = create_black_buffer (VIDEO_CAPS_STRING); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 2; + + /* take additional ref to keep it alive */ + gst_buffer_ref (inbuffer); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 2); + + /* pushing gives away one of the two references we have ... */ + GST_LOG ("pushing video buffer 1"); + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* video buffer should have gone through untainted, since the text is later */ + fail_unless_equals_int (g_list_length (buffers), 1); + + /* text should still be stuck in textoverlay */ + ASSERT_BUFFER_REFCOUNT (tbuf, "tbuf", 2); + + /* there should be no text rendered */ + fail_unless (buffer_is_all_black (GST_BUFFER_CAST (buffers->data))); + + /* now, another video buffer */ + inbuffer = gst_buffer_make_metadata_writable (inbuffer); + GST_BUFFER_TIMESTAMP (inbuffer) = GST_SECOND; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 2; + + /* pushing gives away one of the two references we have ... */ + GST_LOG ("pushing video buffer 2"); + gst_buffer_ref (inbuffer); + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* video buffer should have gone right away, with text rendered on it */ + fail_unless_equals_int (g_list_length (buffers), 2); + + /* text should still be stuck in textoverlay */ + ASSERT_BUFFER_REFCOUNT (tbuf, "tbuf", 2); + + /* there should be text rendered */ + fail_unless (buffer_is_all_black (GST_BUFFER_CAST (buffers->next->data)) == + FALSE); + + /* a third video buffer */ + inbuffer = gst_buffer_make_metadata_writable (inbuffer); + GST_BUFFER_TIMESTAMP (inbuffer) = 30 * GST_SECOND; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND / 2; + + /* video buffer #3: should not go through, it should discard the current + * text buffer as too old and then wait for the next text buffer (or a + * newsegment event to arrive); we spawn a background thread to send such + * a newsegment event after a second or so so we get back control */ + thread = + g_thread_create (test_video_waits_for_text_send_text_newsegment_thread, + NULL, FALSE, NULL); + fail_unless (thread != NULL); + + GST_LOG ("pushing video buffer 3"); + gst_buffer_ref (inbuffer); + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_OK); + + /* but the text should no longer be stuck in textoverlay */ + ASSERT_BUFFER_REFCOUNT (tbuf, "tbuf", 1); + + /* video buffer should have gone through after newsegment event */ + fail_unless_equals_int (g_list_length (buffers), 3); + + /* ... and there should not be any text rendered on it */ + fail_unless (buffer_is_all_black (GST_BUFFER_CAST (buffers->next-> + next->data))); + + /* a fourth video buffer */ + inbuffer = gst_buffer_make_metadata_writable (inbuffer); + GST_BUFFER_TIMESTAMP (inbuffer) = 35 * GST_SECOND; + GST_BUFFER_DURATION (inbuffer) = GST_SECOND; + + /* video buffer #4: should not go through, it should wait for the next + * text buffer (or a newsegment event) to arrive; we spawn a background + * thread to shut down the element while it's waiting to make sure that + * works ok */ + thread = g_thread_create (test_video_waits_for_text_shutdown_element, + textoverlay, FALSE, NULL); + fail_unless (thread != NULL); + + GST_LOG ("pushing video buffer 4"); + gst_buffer_ref (inbuffer); + fail_unless (gst_pad_push (myvideosrcpad, inbuffer) == GST_FLOW_WRONG_STATE); + + /* and clean up */ + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* cleanup */ + cleanup_textoverlay (textoverlay); + gst_buffer_unref (inbuffer); + + /* give up our ref, textoverlay should've cleared its queued buffer by now */ + ASSERT_BUFFER_REFCOUNT (tbuf, "tbuf", 1); + gst_buffer_unref (tbuf); +} + +GST_END_TEST; + +static gpointer +test_render_continuity_push_video_buffers_thread (gpointer data) +{ + /* push video buffers at 1fps */ + guint frame_count = 0; + + do { + GstBuffer *vbuf; + + vbuf = create_black_buffer (VIDEO_CAPS_STRING); + ASSERT_BUFFER_REFCOUNT (vbuf, "vbuf", 1); + + GST_BUFFER_TIMESTAMP (vbuf) = frame_count * GST_SECOND; + GST_BUFFER_DURATION (vbuf) = GST_SECOND; + + /* pushing gives away one of the two references we have ... */ + GST_LOG ("pushing video buffer %u @ %" GST_TIME_FORMAT, frame_count, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (vbuf))); + fail_unless (gst_pad_push (myvideosrcpad, vbuf) == GST_FLOW_OK); + + ++frame_count; + } while (frame_count < 15); + + return NULL; +} + + +GST_START_TEST (test_render_continuity) +{ + GThread *thread; + GstElement *textoverlay; + GstBuffer *tbuf; + + textoverlay = setup_textoverlay (FALSE); + + fail_unless (gst_element_set_state (textoverlay, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + thread = g_thread_create (test_render_continuity_push_video_buffers_thread, + NULL, FALSE, NULL); + fail_unless (thread != NULL); + + tbuf = create_text_buffer ("XLX", 2 * GST_SECOND, GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + tbuf = create_text_buffer ("XLX", 3 * GST_SECOND, 2 * GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + tbuf = create_text_buffer ("XLX", 7 * GST_SECOND, GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + tbuf = create_text_buffer ("XLX", 8 * GST_SECOND, GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + tbuf = create_text_buffer ("XLX", 9 * GST_SECOND, GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + tbuf = create_text_buffer ("XLX", 10 * GST_SECOND, 30 * GST_SECOND); + GST_LOG ("pushing text buffer @ %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (tbuf))); + fail_unless (gst_pad_push (mytextsrcpad, tbuf) == GST_FLOW_OK); + + GST_LOG ("give the other thread some time to push through the remaining" + "video buffers"); + g_usleep (G_USEC_PER_SEC); + GST_LOG ("done"); + + /* we should have 15 buffers each with one second length now */ + fail_unless_equals_int (g_list_length (buffers), 15); + + /* buffers 0 + 1 should be black */ + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, 0)))); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, 1)))); + + /* buffers 2 - 4 should have text */ + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 2))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 3))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 4))) == FALSE); + + /* buffers 5 + 6 should be black */ + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, 5)))); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, 6)))); + + /* buffers 7 - last should have text */ + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 7))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 8))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 9))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 10))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 11))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 12))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 13))) == FALSE); + fail_unless (buffer_is_all_black (GST_BUFFER (g_list_nth_data (buffers, + 14))) == FALSE); + + /* and clean up */ + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + /* cleanup */ + cleanup_textoverlay (textoverlay); +} + +GST_END_TEST; + +static Suite * +textoverlay_suite (void) +{ + Suite *s = suite_create ("textoverlay"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_video_passthrough); + tcase_add_test (tc_chain, test_video_render_static_text); + tcase_add_test (tc_chain, test_render_continuity); + tcase_add_test (tc_chain, test_video_waits_for_text); + + return s; +} + +GST_CHECK_MAIN (textoverlay); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/videorate.c b/gst-plugins-base-subtitles0.10/tests/check/elements/videorate.c new file mode 100644 index 0000000..69eb3c6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/videorate.c @@ -0,0 +1,797 @@ +/* GStreamer + * + * unit test for videorate + * + * Copyright (C) 2006 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +/* 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 VIDEO_CAPS_TEMPLATE_STRING \ + "video/x-raw-yuv" + +#define VIDEO_CAPS_STRING \ + "video/x-raw-yuv, " \ + "width = (int) 320, " \ + "height = (int) 240, " \ + "framerate = (fraction) 25/1 , " \ + "format = (fourcc) I420" + +#define VIDEO_CAPS_NO_FRAMERATE_STRING \ + "video/x-raw-yuv, " \ + "width = (int) 320, " \ + "height = (int) 240, " \ + "format = (fourcc) I420" + +#define VIDEO_CAPS_NEWSIZE_STRING \ + "video/x-raw-yuv, " \ + "width = (int) 240, " \ + "height = (int) 120, " \ + "framerate = (fraction) 25/1 , " \ + "format = (fourcc) I420" + +#define VIDEO_CAPS_UNUSUAL_FRAMERATE \ + "video/x-raw-yuv, " \ + "width = (int) 240, " \ + "height = (int) 120, " \ + "framerate = (fraction) 999/7 , " \ + "format = (fourcc) I420, " \ + "color-matrix=(string)sdtv" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate downstreamsinktemplate = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VIDEO_CAPS_STRING) + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VIDEO_CAPS_TEMPLATE_STRING) + ); + +static void +assert_videorate_stats (GstElement * videorate, const gchar * reason, + guint64 xin, guint64 xout, guint64 xdropped, guint64 xduplicated) +{ + guint64 in, out, dropped, duplicated; + + g_object_get (videorate, "in", &in, "out", &out, "drop", &dropped, + "duplicate", &duplicated, NULL); +#define _assert_equals_uint64(a, b) \ +G_STMT_START { \ + guint64 first = a; \ + guint64 second = b; \ + fail_unless(first == second, \ + "%s: '" #a "' (%" G_GUINT64_FORMAT ") is not equal to " \ + "expected '" #a"' (%" G_GUINT64_FORMAT ")", reason, first, second); \ +} G_STMT_END; + + + _assert_equals_uint64 (in, xin); + _assert_equals_uint64 (out, xout); + _assert_equals_uint64 (dropped, xdropped); + _assert_equals_uint64 (duplicated, xduplicated); +} + +static GstElement * +setup_videorate_full (GstStaticPadTemplate * srctemplate, + GstStaticPadTemplate * sinktemplate) +{ + GstElement *videorate; + + GST_DEBUG ("setup_videorate"); + videorate = gst_check_setup_element ("videorate"); + mysrcpad = gst_check_setup_src_pad (videorate, srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (videorate, sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return videorate; +} + +static GstElement * +setup_videorate (void) +{ + return setup_videorate_full (&srctemplate, &sinktemplate); +} + +static void +cleanup_videorate (GstElement * videorate) +{ + GST_DEBUG ("cleanup_videorate"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + gst_element_set_state (videorate, GST_STATE_NULL); + gst_element_get_state (videorate, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (videorate); + gst_check_teardown_sink_pad (videorate); + gst_check_teardown_element (videorate); +} + +GST_START_TEST (test_one) +{ + GstElement *videorate; + GstBuffer *inbuffer; + GstCaps *caps; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memset (GST_BUFFER_DATA (inbuffer), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (inbuffer, caps); + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* cleanup */ + cleanup_videorate (videorate); +} + +GST_END_TEST; + +GST_START_TEST (test_more) +{ + GstElement *videorate; + GstBuffer *first, *second, *third, *outbuffer; + GList *l; + GstCaps *caps; + GRand *rand; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + assert_videorate_stats (videorate, "creation", 0, 0, 0, 0); + + rand = g_rand_new (); + + /* first buffer */ + first = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (first) = 0; + /* it shouldn't matter what the offsets are, videorate produces perfect + streams */ + GST_BUFFER_OFFSET (first) = g_rand_int (rand); + GST_BUFFER_OFFSET_END (first) = g_rand_int (rand); + memset (GST_BUFFER_DATA (first), 1, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (first, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (first, "first", 1); + gst_buffer_ref (first); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, first) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (first, "first", 2); + fail_unless_equals_int (g_list_length (buffers), 0); + assert_videorate_stats (videorate, "first buffer", 1, 0, 0, 0); + + /* second buffer; inbetween second and third output frame's timestamp */ + second = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (second) = GST_SECOND * 3 / 50; + GST_BUFFER_OFFSET (first) = g_rand_int (rand); + GST_BUFFER_OFFSET_END (first) = g_rand_int (rand); + memset (GST_BUFFER_DATA (second), 2, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (second, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (second, "second", 1); + gst_buffer_ref (second); + + /* pushing gives away one of my references ... */ + fail_unless (gst_pad_push (mysrcpad, second) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (second, "second", 2); + + /* ... and the first one is pushed out, with timestamp 0 */ + fail_unless_equals_int (g_list_length (buffers), 1); + assert_videorate_stats (videorate, "second buffer", 2, 1, 0, 0); + ASSERT_BUFFER_REFCOUNT (first, "first", 2); + + outbuffer = buffers->data; + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (outbuffer), 0); + + /* third buffer */ + third = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (third) = GST_SECOND * 12 / 50; + GST_BUFFER_OFFSET (first) = g_rand_int (rand); + GST_BUFFER_OFFSET_END (first) = g_rand_int (rand); + memset (GST_BUFFER_DATA (third), 3, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (third, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (third, "third", 1); + gst_buffer_ref (third); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, third) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (third, "third", 2); + + /* submitting the third buffer has triggered flushing of three more frames */ + assert_videorate_stats (videorate, "third buffer", 3, 4, 0, 2); + + /* check timestamp and source correctness */ + l = buffers; + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (l->data), 0); + fail_unless_equals_int (GST_BUFFER_DATA (l->data)[0], 1); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET (l->data), 0); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (l->data), 1); + + l = g_list_next (l); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (l->data), GST_SECOND / 25); + fail_unless_equals_int (GST_BUFFER_DATA (l->data)[0], 2); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET (l->data), 1); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (l->data), 2); + + l = g_list_next (l); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (l->data), + GST_SECOND * 2 / 25); + fail_unless_equals_int (GST_BUFFER_DATA (l->data)[0], 2); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET (l->data), 2); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (l->data), 3); + + l = g_list_next (l); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (l->data), + GST_SECOND * 3 / 25); + fail_unless_equals_int (GST_BUFFER_DATA (l->data)[0], 2); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET (l->data), 3); + fail_unless_equals_uint64 (GST_BUFFER_OFFSET_END (l->data), 4); + + fail_unless_equals_int (g_list_length (buffers), 4); + /* one held by us, three held by each output frame taken from the second */ + ASSERT_BUFFER_REFCOUNT (second, "second", 4); + + /* now send EOS */ + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ())); + + /* submitting eos should flush out two more frames for tick 8 and 10 */ + /* FIXME: right now it only flushes out one, so out is 5 instead of 6 ! */ + assert_videorate_stats (videorate, "eos", 3, 5, 0, 2); + fail_unless_equals_int (g_list_length (buffers), 5); + + /* cleanup */ + g_rand_free (rand); + gst_buffer_unref (first); + gst_buffer_unref (second); + gst_buffer_unref (third); + cleanup_videorate (videorate); +} + +GST_END_TEST; + +/* frames at 1, 0, 2 -> second one should be ignored */ +GST_START_TEST (test_wrong_order_from_zero) +{ + GstElement *videorate; + GstBuffer *first, *second, *third, *outbuffer; + GstCaps *caps; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + assert_videorate_stats (videorate, "start", 0, 0, 0, 0); + + /* first buffer */ + first = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (first) = GST_SECOND; + memset (GST_BUFFER_DATA (first), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (first, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (first, "first", 1); + gst_buffer_ref (first); + + GST_DEBUG ("pushing first buffer"); + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, first) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (first, "first", 2); + fail_unless_equals_int (g_list_length (buffers), 0); + assert_videorate_stats (videorate, "first", 1, 0, 0, 0); + + /* second buffer */ + second = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (second) = 0; + memset (GST_BUFFER_DATA (second), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (second, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (second, "second", 1); + gst_buffer_ref (second); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, second) == GST_FLOW_OK); + /* ... and it is now dropped because it is too old */ + ASSERT_BUFFER_REFCOUNT (second, "second", 1); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* ... and the first one is still there */ + assert_videorate_stats (videorate, "second", 2, 0, 1, 0); + ASSERT_BUFFER_REFCOUNT (first, "first", 2); + + /* third buffer */ + third = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (third) = 2 * GST_SECOND; + memset (GST_BUFFER_DATA (third), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (third, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (third, "third", 1); + gst_buffer_ref (third); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, third) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (third, "third", 2); + + /* and now the first one should be pushed once and dupped 24 + 13 times, to + * reach the half point between 1 s (first) and 2 s (third) */ + fail_unless_equals_int (g_list_length (buffers), 38); + ASSERT_BUFFER_REFCOUNT (first, "first", 39); + ASSERT_BUFFER_REFCOUNT (second, "second", 1); + ASSERT_BUFFER_REFCOUNT (third, "third", 2); + assert_videorate_stats (videorate, "third", 3, 38, 1, 37); + + /* verify last buffer */ + outbuffer = g_list_last (buffers)->data; + fail_unless (GST_IS_BUFFER (outbuffer)); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (outbuffer), + GST_SECOND * 37 / 25); + + /* cleanup */ + gst_buffer_unref (first); + gst_buffer_unref (second); + gst_buffer_unref (third); + cleanup_videorate (videorate); +} + +GST_END_TEST; + +/* send frames with 0, 1, 2, 0 seconds */ +GST_START_TEST (test_wrong_order) +{ + GstElement *videorate; + GstBuffer *first, *second, *third, *fourth, *outbuffer; + GstCaps *caps; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + assert_videorate_stats (videorate, "start", 0, 0, 0, 0); + + /* first buffer */ + first = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (first) = 0; + memset (GST_BUFFER_DATA (first), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (first, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (first, "first", 1); + gst_buffer_ref (first); + + GST_DEBUG ("pushing first buffer"); + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, first) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (first, "first", 2); + fail_unless_equals_int (g_list_length (buffers), 0); + assert_videorate_stats (videorate, "first", 1, 0, 0, 0); + + /* second buffer */ + second = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (second) = GST_SECOND; + memset (GST_BUFFER_DATA (second), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (second, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (second, "second", 1); + gst_buffer_ref (second); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, second) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (second, "second", 2); + /* and it created 13 output buffers as copies of the first frame */ + fail_unless_equals_int (g_list_length (buffers), 13); + assert_videorate_stats (videorate, "second", 2, 13, 0, 12); + ASSERT_BUFFER_REFCOUNT (first, "first", 14); + + /* third buffer */ + third = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (third) = 2 * GST_SECOND; + memset (GST_BUFFER_DATA (third), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (third, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (third, "third", 1); + gst_buffer_ref (third); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, third) == GST_FLOW_OK); + /* ... and it is now stuck inside videorate */ + ASSERT_BUFFER_REFCOUNT (third, "third", 2); + + /* submitting a frame with 2 seconds triggers output of 25 more frames */ + fail_unless_equals_int (g_list_length (buffers), 38); + ASSERT_BUFFER_REFCOUNT (first, "first", 14); + ASSERT_BUFFER_REFCOUNT (second, "second", 26); + /* three frames submitted; two of them output as is, and 36 duplicated */ + assert_videorate_stats (videorate, "third", 3, 38, 0, 36); + + /* fourth buffer */ + fourth = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (fourth) = 0; + memset (GST_BUFFER_DATA (fourth), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (fourth, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (fourth, "fourth", 1); + gst_buffer_ref (fourth); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, fourth) == GST_FLOW_OK); + /* ... and it is dropped */ + ASSERT_BUFFER_REFCOUNT (fourth, "fourth", 1); + + fail_unless_equals_int (g_list_length (buffers), 38); + ASSERT_BUFFER_REFCOUNT (first, "first", 14); + ASSERT_BUFFER_REFCOUNT (second, "second", 26); + assert_videorate_stats (videorate, "fourth", 4, 38, 1, 36); + + /* verify last buffer */ + outbuffer = g_list_last (buffers)->data; + fail_unless (GST_IS_BUFFER (outbuffer)); + fail_unless_equals_uint64 (GST_BUFFER_TIMESTAMP (outbuffer), + GST_SECOND * 37 / 25); + + + /* cleanup */ + gst_buffer_unref (first); + gst_buffer_unref (second); + gst_buffer_unref (third); + gst_buffer_unref (fourth); + cleanup_videorate (videorate); +} + +GST_END_TEST; + + +/* if no framerate is negotiated, we should not be able to push a buffer */ +GST_START_TEST (test_no_framerate) +{ + GstElement *videorate; + GstBuffer *inbuffer; + GstCaps *caps; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memset (GST_BUFFER_DATA (inbuffer), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_NO_FRAMERATE_STRING); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* take a ref so we can later check refcount */ + gst_buffer_ref (inbuffer); + + /* no framerate is negotiated so pushing should fail */ + fail_if (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* cleanup */ + cleanup_videorate (videorate); +} + +GST_END_TEST; + +/* This test outputs 2 buffers of same dimensions (320x240), then 1 buffer of + * differing dimensions (240x120), and then another buffer of previous + * dimensions (320x240) and checks that the 3 buffers output as a result have + * correct caps (first 2 with 320x240 and 3rd with 240x120). + */ +GST_START_TEST (test_changing_size) +{ + GstElement *videorate; + GstBuffer *first; + GstBuffer *second; + GstBuffer *third; + GstBuffer *fourth; + GstBuffer *fifth; + GstBuffer *outbuf; + GstEvent *newsegment; + GstCaps *caps, *caps_newsize; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + newsegment = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, -1, + 0); + fail_unless (gst_pad_push_event (mysrcpad, newsegment) == TRUE); + + first = gst_buffer_new_and_alloc (4); + memset (GST_BUFFER_DATA (first), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + GST_BUFFER_TIMESTAMP (first) = 0; + gst_buffer_set_caps (first, caps); + + GST_DEBUG ("pushing first buffer"); + fail_unless (gst_pad_push (mysrcpad, first) == GST_FLOW_OK); + + /* second buffer */ + second = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (second) = GST_SECOND / 25; + memset (GST_BUFFER_DATA (second), 0, 4); + gst_buffer_set_caps (second, caps); + + fail_unless (gst_pad_push (mysrcpad, second) == GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + outbuf = buffers->data; + /* first buffer should be output here */ + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (outbuf), caps)); + fail_unless (GST_BUFFER_TIMESTAMP (outbuf) == 0); + + /* third buffer with new size */ + third = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (third) = 2 * GST_SECOND / 25; + memset (GST_BUFFER_DATA (third), 0, 4); + caps_newsize = gst_caps_from_string (VIDEO_CAPS_NEWSIZE_STRING); + gst_buffer_set_caps (third, caps_newsize); + + fail_unless (gst_pad_push (mysrcpad, third) == GST_FLOW_OK); + /* new caps flushed the internal state, no new output yet */ + fail_unless_equals_int (g_list_length (buffers), 1); + outbuf = g_list_last (buffers)->data; + /* first buffer should be output here */ + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (outbuf), caps)); + fail_unless (GST_BUFFER_TIMESTAMP (outbuf) == 0); + + /* fourth buffer with original size */ + fourth = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (fourth) = 3 * GST_SECOND / 25; + memset (GST_BUFFER_DATA (fourth), 0, 4); + gst_buffer_set_caps (fourth, caps); + + fail_unless (gst_pad_push (mysrcpad, fourth) == GST_FLOW_OK); + fail_unless_equals_int (g_list_length (buffers), 1); + + /* fifth buffer with original size */ + fifth = gst_buffer_new_and_alloc (4); + GST_BUFFER_TIMESTAMP (fifth) = 4 * GST_SECOND / 25; + memset (GST_BUFFER_DATA (fifth), 0, 4); + gst_buffer_set_caps (fifth, caps); + + fail_unless (gst_pad_push (mysrcpad, fifth) == GST_FLOW_OK); + /* all four missing buffers here, dups of fourth buffer */ + fail_unless_equals_int (g_list_length (buffers), 4); + outbuf = g_list_last (buffers)->data; + /* third buffer should be output here */ + fail_unless (GST_BUFFER_TIMESTAMP (outbuf) == 3 * GST_SECOND / 25); + fail_unless (gst_caps_is_equal (GST_BUFFER_CAPS (outbuf), caps)); + + gst_caps_unref (caps); + gst_caps_unref (caps_newsize); + cleanup_videorate (videorate); +} + +GST_END_TEST; + +GST_START_TEST (test_non_ok_flow) +{ + GstElement *videorate; + GstClockTime ts; + GstBuffer *buf; + GstCaps *caps; + + videorate = setup_videorate (); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + buf = gst_buffer_new_and_alloc (4); + memset (GST_BUFFER_DATA (buf), 0, 4); + caps = gst_caps_from_string (VIDEO_CAPS_STRING); + gst_buffer_set_caps (buf, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (buf, "inbuffer", 1); + + /* push a few 'normal' buffers */ + for (ts = 0; ts < 100 * GST_SECOND; ts += GST_SECOND / 33) { + GstBuffer *inbuf; + + inbuf = gst_buffer_copy (buf); + GST_BUFFER_TIMESTAMP (inbuf) = ts; + + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuf), GST_FLOW_OK); + } + + /* we should have buffers according to the output framerate of 25/1 */ + fail_unless_equals_int (g_list_length (buffers), 100 * 25); + + /* now deactivate pad so we get a WRONG_STATE flow return */ + gst_pad_set_active (mysinkpad, FALSE); + + /* push buffer on deactivated pad */ + fail_unless (gst_buffer_is_metadata_writable (buf)); + GST_BUFFER_TIMESTAMP (buf) = ts; + + /* pushing gives away our reference */ + fail_unless_equals_int (gst_pad_push (mysrcpad, buf), GST_FLOW_WRONG_STATE); + + /* cleanup */ + cleanup_videorate (videorate); +} + +GST_END_TEST; + +GST_START_TEST (test_upstream_caps_nego) +{ + GstElement *videorate; + GstPad *videorate_pad; + GstCaps *expected_caps; + GstCaps *caps; + GstStructure *structure; + + videorate = setup_videorate_full (&srctemplate, &downstreamsinktemplate); + fail_unless (gst_element_set_state (videorate, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + videorate_pad = gst_element_get_static_pad (videorate, "sink"); + caps = gst_pad_get_caps (videorate_pad); + + /* assemble the expected caps */ + structure = gst_structure_from_string (VIDEO_CAPS_STRING, NULL); + expected_caps = gst_caps_new_empty (); + gst_caps_append_structure (expected_caps, structure); + structure = gst_structure_copy (structure); + gst_structure_set (structure, "framerate", GST_TYPE_FRACTION_RANGE, + 0, 1, G_MAXINT, 1, NULL); + gst_caps_append_structure (expected_caps, structure); + + fail_unless (gst_caps_is_equal (expected_caps, caps)); + gst_caps_unref (caps); + gst_caps_unref (expected_caps); + gst_object_unref (videorate_pad); + + /* cleanup */ + cleanup_videorate (videorate); +} + +GST_END_TEST; + + +GST_START_TEST (test_selected_caps) +{ + GstElement *videorate; + GstElement *pipeline; + GstBus *bus; + GstMessage *msg; + + pipeline = gst_parse_launch ("videotestsrc num-buffers=1" + " ! identity ! videorate name=videorate0 ! " VIDEO_CAPS_UNUSUAL_FRAMERATE + " ! fakesink", NULL); + fail_if (pipeline == NULL); + videorate = gst_bin_get_by_name (GST_BIN (pipeline), "videorate0"); + fail_if (videorate == NULL); + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + + fail_if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE, + "could not set to playing"); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_if (msg == NULL || GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + + /* make sure upstream nego works right and videotestsrc has selected the + * caps we want downstream of videorate */ + { + GstStructure *s; + const GValue *val; + GstCaps *caps = NULL; + GstPad *videorate_pad; + + videorate_pad = gst_element_get_static_pad (videorate, "sink"); + g_object_get (videorate_pad, "caps", &caps, NULL); + fail_unless (caps != NULL); + + GST_DEBUG ("negotiated caps: %" GST_PTR_FORMAT, caps); + + s = gst_caps_get_structure (caps, 0); + val = gst_structure_get_value (s, "framerate"); + fail_unless (val != NULL, "no framerate field in negotiated caps"); + fail_unless (GST_VALUE_HOLDS_FRACTION (val)); + fail_unless_equals_int (gst_value_get_fraction_numerator (val), 999); + fail_unless_equals_int (gst_value_get_fraction_denominator (val), 7); + + gst_caps_unref (caps); + gst_object_unref (videorate_pad); + } + + /* cleanup */ + gst_object_unref (bus); + gst_message_unref (msg); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (videorate); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +videorate_suite (void) +{ + Suite *s = suite_create ("videorate"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_one); + tcase_add_test (tc_chain, test_more); + tcase_add_test (tc_chain, test_wrong_order_from_zero); + tcase_add_test (tc_chain, test_wrong_order); + tcase_add_test (tc_chain, test_no_framerate); + tcase_add_test (tc_chain, test_changing_size); + tcase_add_test (tc_chain, test_non_ok_flow); + tcase_add_test (tc_chain, test_upstream_caps_nego); + tcase_add_test (tc_chain, test_selected_caps); + + return s; +} + +GST_CHECK_MAIN (videorate) diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/videoscale.c b/gst-plugins-base-subtitles0.10/tests/check/elements/videoscale.c new file mode 100644 index 0000000..276261f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/videoscale.c @@ -0,0 +1,866 @@ +/* GStreamer + * + * unit test for videoscale + * + * Copyright (C) <2009,2010> Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include + +/* kids, don't do this at home, skipping checks is *BAD* */ +#define LINK_CHECK_FLAGS GST_PAD_LINK_CHECK_NOTHING + +static GstCaps ** +videoscale_get_allowed_caps (void) +{ + GstElement *scale = gst_element_factory_make ("videoscale", "scale"); + GstPadTemplate *templ; + GstCaps *caps, **ret; + GstStructure *s; + gint i, n; + + templ = + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (scale), + "sink"); + fail_unless (templ != NULL); + + caps = gst_pad_template_get_caps (templ); + + n = gst_caps_get_size (caps); + ret = g_new0 (GstCaps *, n + 1); + + for (i = 0; i < n; i++) { + s = gst_caps_get_structure (caps, i); + ret[i] = gst_caps_new_empty (); + gst_caps_append_structure (ret[i], gst_structure_copy (s)); + } + + gst_object_unref (scale); + + return ret; +} + +static void +on_sink_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad, + gpointer user_data) +{ + guint *n_buffers = user_data; + + *n_buffers = *n_buffers + 1; +} + +static gboolean +caps_are_64bpp (const GstCaps * caps) +{ + GstVideoFormat fmt; + GstCaps *fmt_caps; + + /* need fixed caps for _parse_caps */ + fmt_caps = gst_caps_copy (caps); + gst_structure_remove_field (gst_caps_get_structure (fmt_caps, 0), "width"); + gst_structure_remove_field (gst_caps_get_structure (fmt_caps, 0), "height"); + gst_structure_remove_field (gst_caps_get_structure (fmt_caps, 0), + "framerate"); + + fail_unless (gst_video_format_parse_caps (fmt_caps, &fmt, NULL, NULL)); + gst_caps_unref (fmt_caps); + return (fmt == GST_VIDEO_FORMAT_ARGB64 || fmt == GST_VIDEO_FORMAT_AYUV64); +} + +static void +run_test (const GstCaps * caps, gint src_width, gint src_height, + gint dest_width, gint dest_height, gint method, + GCallback src_handoff, gpointer src_handoff_user_data, + GCallback sink_handoff, gpointer sink_handoff_user_data) +{ + GstElement *pipeline; + GstElement *src, *ffmpegcolorspace, *capsfilter1, *identity, *scale, + *capsfilter2, *sink; + GstMessage *msg; + GstBus *bus; + GstCaps *copy; + guint n_buffers = 0; + + /* skip formats that ffmpegcolorspace can't handle */ + if (caps_are_64bpp (caps)) + return; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fail_unless (pipeline != NULL); + + src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (src != NULL); + g_object_set (G_OBJECT (src), "num-buffers", 1, NULL); + + ffmpegcolorspace = gst_element_factory_make ("ffmpegcolorspace", "csp"); + fail_unless (ffmpegcolorspace != NULL); + + capsfilter1 = gst_element_factory_make ("capsfilter", "filter1"); + fail_unless (capsfilter1 != NULL); + copy = gst_caps_copy (caps); + gst_caps_set_simple (copy, "width", G_TYPE_INT, src_width, "height", + G_TYPE_INT, src_height, "framerate", GST_TYPE_FRACTION, 30, 1, NULL); + g_object_set (G_OBJECT (capsfilter1), "caps", copy, NULL); + gst_caps_unref (copy); + + identity = gst_element_factory_make ("identity", "identity"); + fail_unless (identity != NULL); + if (src_handoff) { + g_object_set (G_OBJECT (identity), "signal-handoffs", TRUE, NULL); + g_signal_connect (identity, "handoff", G_CALLBACK (src_handoff), + src_handoff_user_data); + } + + scale = gst_element_factory_make ("videoscale", "scale"); + fail_unless (scale != NULL); + g_object_set (G_OBJECT (scale), "method", method, NULL); + + capsfilter2 = gst_element_factory_make ("capsfilter", "filter2"); + fail_unless (capsfilter2 != NULL); + copy = gst_caps_copy (caps); + gst_caps_set_simple (copy, "width", G_TYPE_INT, dest_width, "height", + G_TYPE_INT, dest_height, NULL); + g_object_set (G_OBJECT (capsfilter2), "caps", copy, NULL); + gst_caps_unref (copy); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (sink != NULL); + g_object_set (G_OBJECT (sink), "signal-handoffs", TRUE, "async", FALSE, NULL); + g_signal_connect (sink, "handoff", G_CALLBACK (on_sink_handoff), &n_buffers); + if (sink_handoff) { + g_signal_connect (sink, "handoff", G_CALLBACK (sink_handoff), + sink_handoff_user_data); + } + + gst_bin_add_many (GST_BIN (pipeline), src, ffmpegcolorspace, capsfilter1, + identity, scale, capsfilter2, sink, NULL); + + fail_unless (gst_element_link_pads_full (src, "src", ffmpegcolorspace, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (ffmpegcolorspace, "src", capsfilter1, + "sink", LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (capsfilter1, "src", identity, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (identity, "src", scale, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink", + LINK_CHECK_FLAGS)); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR | GST_MESSAGE_WARNING); + + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (n_buffers == 1); + + gst_object_unref (pipeline); + gst_message_unref (msg); + gst_object_unref (bus); +} + +static void +on_sink_handoff_passthrough (GstElement * element, GstBuffer * buffer, + GstPad * pad, gpointer user_data) +{ + GList **list = user_data; + + *list = g_list_prepend (*list, gst_buffer_ref (buffer)); +} + +static void +on_src_handoff_passthrough (GstElement * element, GstBuffer * buffer, + gpointer user_data) +{ + GList **list = user_data; + + *list = g_list_prepend (*list, gst_buffer_ref (buffer)); +} + +GST_START_TEST (test_passthrough) +{ + GList *l1, *l2, *src_buffers = NULL, *sink_buffers = NULL; + GstCaps **allowed_caps = NULL, **p; + gint method; + static const gint src_width = 640, src_height = 480; + static const gint dest_width = 640, dest_height = 480; + + p = allowed_caps = videoscale_get_allowed_caps (); + + while (*p) { + GstCaps *caps = *p; + + for (method = 0; method < 3; method++) { + /* skip formats that ffmpegcolorspace can't handle */ + if (caps_are_64bpp (caps)) + continue; + + GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'" + " from %dx%u to %dx%d with method %d", caps, src_width, src_height, + dest_width, dest_height, method); + run_test (caps, src_width, src_height, + dest_width, dest_height, method, + G_CALLBACK (on_src_handoff_passthrough), &src_buffers, + G_CALLBACK (on_sink_handoff_passthrough), &sink_buffers); + + fail_unless (src_buffers && sink_buffers); + fail_unless_equals_int (g_list_length (src_buffers), + g_list_length (sink_buffers)); + + for (l1 = src_buffers, l2 = sink_buffers; l1 && l2; + l1 = l1->next, l2 = l2->next) { + GstBuffer *a = l1->data; + GstBuffer *b = l2->data; + + fail_unless_equals_int (GST_BUFFER_SIZE (a), GST_BUFFER_SIZE (b)); + fail_unless (GST_BUFFER_DATA (a) == GST_BUFFER_DATA (b)); + + gst_buffer_unref (a); + gst_buffer_unref (b); + } + g_list_free (src_buffers); + src_buffers = NULL; + g_list_free (sink_buffers); + sink_buffers = NULL; + } + + gst_caps_unref (caps); + p++; + } + g_free (allowed_caps); +} + +GST_END_TEST; + +#define CREATE_TEST(name,method,src_width,src_height,dest_width,dest_height) \ +GST_START_TEST (name) \ +{ \ + GstCaps **allowed_caps = NULL, **p; \ + \ + p = allowed_caps = videoscale_get_allowed_caps (); \ + \ + while (*p) { \ + GstCaps *caps = *p; \ + \ + GST_DEBUG ("Running test for caps '%" GST_PTR_FORMAT "'" \ + " from %dx%u to %dx%d with method %d", caps, src_width, src_height, \ + dest_width, dest_height, method); \ + run_test (caps, src_width, src_height, \ + dest_width, dest_height, method, \ + NULL, NULL, NULL, NULL); \ + gst_caps_unref (caps); \ + p++; \ + } \ + g_free (allowed_caps); \ +} \ +\ +GST_END_TEST; + +CREATE_TEST (test_downscale_640x480_320x240_method_0, 0, 640, 480, 320, 240); +CREATE_TEST (test_downscale_640x480_320x240_method_1, 1, 640, 480, 320, 240); +CREATE_TEST (test_downscale_640x480_320x240_method_2, 2, 640, 480, 320, 240); +CREATE_TEST (test_upscale_320x240_640x480_method_0, 0, 320, 240, 640, 480); +CREATE_TEST (test_upscale_320x240_640x480_method_1, 1, 320, 240, 640, 480); +CREATE_TEST (test_upscale_320x240_640x480_method_2, 2, 320, 240, 640, 480); +CREATE_TEST (test_downscale_640x480_1x1_method_0, 0, 640, 480, 1, 1); +CREATE_TEST (test_downscale_640x480_1x1_method_1, 1, 640, 480, 1, 1); +CREATE_TEST (test_downscale_640x480_1x1_method_2, 2, 640, 480, 1, 1); +CREATE_TEST (test_upscale_1x1_640x480_method_0, 0, 1, 1, 640, 480); +CREATE_TEST (test_upscale_1x1_640x480_method_1, 1, 1, 1, 640, 480); +CREATE_TEST (test_upscale_1x1_640x480_method_2, 2, 1, 1, 640, 480); +CREATE_TEST (test_downscale_641x481_111x30_method_0, 0, 641, 481, 111, 30); +CREATE_TEST (test_downscale_641x481_111x30_method_1, 1, 641, 481, 111, 30); +CREATE_TEST (test_downscale_641x481_111x30_method_2, 2, 641, 481, 111, 30); +CREATE_TEST (test_upscale_111x30_641x481_method_0, 0, 111, 30, 641, 481); +CREATE_TEST (test_upscale_111x30_641x481_method_1, 1, 111, 30, 641, 481); +CREATE_TEST (test_upscale_111x30_641x481_method_2, 2, 111, 30, 641, 481); +CREATE_TEST (test_downscale_641x481_30x111_method_0, 0, 641, 481, 30, 111); +CREATE_TEST (test_downscale_641x481_30x111_method_1, 1, 641, 481, 30, 111); +CREATE_TEST (test_downscale_641x481_30x111_method_2, 2, 641, 481, 30, 111); +CREATE_TEST (test_upscale_30x111_641x481_method_0, 0, 30, 111, 641, 481); +CREATE_TEST (test_upscale_30x111_641x481_method_1, 1, 30, 111, 641, 481); +CREATE_TEST (test_upscale_30x111_641x481_method_2, 2, 30, 111, 641, 481); +CREATE_TEST (test_downscale_640x480_320x1_method_0, 0, 640, 480, 320, 1); +CREATE_TEST (test_downscale_640x480_320x1_method_1, 1, 640, 480, 320, 1); +CREATE_TEST (test_downscale_640x480_320x1_method_2, 2, 640, 480, 320, 1); +CREATE_TEST (test_upscale_320x1_640x480_method_0, 0, 320, 1, 640, 480); +CREATE_TEST (test_upscale_320x1_640x480_method_1, 1, 320, 1, 640, 480); +CREATE_TEST (test_upscale_320x1_640x480_method_2, 2, 320, 1, 640, 480); +CREATE_TEST (test_downscale_640x480_1x240_method_0, 0, 640, 480, 1, 240); +CREATE_TEST (test_downscale_640x480_1x240_method_1, 1, 640, 480, 1, 240); +CREATE_TEST (test_downscale_640x480_1x240_method_2, 2, 640, 480, 1, 240); +CREATE_TEST (test_upscale_1x240_640x480_method_0, 0, 1, 240, 640, 480); +CREATE_TEST (test_upscale_1x240_640x480_method_1, 1, 1, 240, 640, 480); +CREATE_TEST (test_upscale_1x240_640x480_method_2, 2, 1, 240, 640, 480); + +typedef struct +{ + gint width, height; + gint par_n, par_d; + gboolean ok; + GMainLoop *loop; +} TestNegotiationData; + +static void +_test_negotiation_message (GstBus * bus, GstMessage * message, + TestNegotiationData * data) +{ + GError *err = NULL; + gchar *debug; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (message, &err, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), err, debug); + g_error_free (err); + g_free (debug); + g_assert_not_reached (); + break; + case GST_MESSAGE_WARNING: + gst_message_parse_warning (message, &err, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), err, debug); + g_error_free (err); + g_free (debug); + g_assert_not_reached (); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (data->loop); + break; + default: + break; + } +} + +static void +_test_negotiation_notify_caps (GObject * src, GParamSpec * pspec, + TestNegotiationData * data) +{ + GstCaps *caps; + GstStructure *s; + gint width, height; + gint par_n = 0, par_d = 0; + + g_object_get (src, "caps", &caps, NULL); + if (caps == NULL) + return; + + s = gst_caps_get_structure (caps, 0); + + fail_unless (gst_structure_get_int (s, "width", &width)); + fail_unless (gst_structure_get_int (s, "height", &height)); + fail_unless (gst_structure_get_fraction (s, "pixel-aspect-ratio", &par_n, + &par_d) || (data->par_n == 1 && data->par_d == 1)); + + gst_caps_unref (caps); + + fail_unless_equals_int (width, data->width); + fail_unless_equals_int (height, data->height); + if (par_n != 0 || par_d != 0) { + fail_unless_equals_int (par_n, data->par_n); + fail_unless_equals_int (par_d, data->par_d); + } + + data->ok = (width == data->width) && (height == data->height) + && (par_n == data->par_n) && (par_d == data->par_d); + + g_main_loop_quit (data->loop); +} + +static void +_test_negotiation (const gchar * src_templ, const gchar * sink_templ, + gint width, gint height, gint par_n, gint par_d) +{ + GstElement *pipeline; + GstElement *src, *capsfilter1, *scale, *capsfilter2, *sink; + GstBus *bus; + GMainLoop *loop; + GstCaps *caps; + TestNegotiationData data = { 0, 0, 0, 0, FALSE, NULL }; + GstPad *pad; + + GST_DEBUG ("Running test for src templ caps '%s' and sink templ caps '%s'", + src_templ, sink_templ); + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fail_unless (pipeline != NULL); + + src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (src != NULL); + g_object_set (G_OBJECT (src), "num-buffers", 1, NULL); + + capsfilter1 = gst_element_factory_make ("capsfilter", "filter1"); + fail_unless (capsfilter1 != NULL); + caps = gst_caps_from_string (src_templ); + fail_unless (caps != NULL); + g_object_set (G_OBJECT (capsfilter1), "caps", caps, NULL); + gst_caps_unref (caps); + + scale = gst_element_factory_make ("videoscale", "scale"); + fail_unless (scale != NULL); + + capsfilter2 = gst_element_factory_make ("capsfilter", "filter2"); + fail_unless (capsfilter2 != NULL); + caps = gst_caps_from_string (sink_templ); + fail_unless (caps != NULL); + g_object_set (G_OBJECT (capsfilter2), "caps", caps, NULL); + gst_caps_unref (caps); + + pad = gst_element_get_static_pad (capsfilter2, "sink"); + fail_unless (pad != NULL); + g_signal_connect (pad, "notify::caps", + G_CALLBACK (_test_negotiation_notify_caps), &data); + gst_object_unref (pad); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (sink != NULL); + g_object_set (sink, "async", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2, + sink, NULL); + + fail_unless (gst_element_link_pads_full (src, "src", capsfilter1, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (capsfilter1, "src", scale, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (scale, "src", capsfilter2, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (capsfilter2, "src", sink, "sink", + LINK_CHECK_FLAGS)); + + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL); + gst_bus_add_signal_watch (bus); + + data.loop = loop; + data.width = width; + data.height = height; + data.par_n = par_n; + data.par_d = par_d; + data.ok = FALSE; + + g_signal_connect (bus, "message", G_CALLBACK (_test_negotiation_message), + &data); + + gst_object_unref (bus); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + g_main_loop_run (loop); + + fail_unless (data.ok == TRUE); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (pipeline); + g_main_loop_unref (loop); +} + +GST_START_TEST (test_negotiation) +{ + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=720,height=576,pixel-aspect-ratio=16/15", + "video/x-raw-yuv,format=(fourcc)AYUV,width=768,height=576", + 768, 576, 1, 1); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=320,height=240", + "video/x-raw-yuv,format=(fourcc)AYUV,width=640,height=320", + 640, 320, 2, 3); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=320,height=240", + "video/x-raw-yuv,format=(fourcc)AYUV,width=640,height=320,pixel-aspect-ratio=[0/1, 1/1]", + 640, 320, 2, 3); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1", + "video/x-raw-yuv,format=(fourcc)AYUV,width=[1, 2048],height=[1, 2048],pixel-aspect-ratio=1/1", + 1536, 2048, 1, 1); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=1920,height=2560,pixel-aspect-ratio=1/1", + "video/x-raw-yuv,format=(fourcc)AYUV,width=[1, 2048],height=[1, 2048]", + 1920, 2048, 4, 5); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=1920,height=2560", + "video/x-raw-yuv,format=(fourcc)AYUV,width=[1, 2048],height=[1, 2048]", + 1920, 2048, 4, 5); + + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=1920,height=2560", + "video/x-raw-yuv,format=(fourcc)AYUV,width=1200,height=[1, 2048],pixel-aspect-ratio=1/1", + 1200, 1600, 1, 1); + + /* Doesn't keep DAR but must be possible! */ + _test_negotiation + ("video/x-raw-yuv,format=(fourcc)AYUV,width=320,height=240,pixel-aspect-ratio=1/1", + "video/x-raw-yuv,format=(fourcc)AYUV,width=200,height=200,pixel-aspect-ratio=1/2", + 200, 200, 1, 2); +} + +GST_END_TEST; + +#define GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK \ + (gst_test_reverse_negotiation_sink_get_type()) +#define GST_TEST_REVERSE_NEGOTIATION_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSink)) +#define GST_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK,GstTestReverseNegotiationSinkClass)) +#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK)) +#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK)) +#define GST_TEST_REVERSE_NEGOTIATION_SINK_CAST(obj) ((GstTestReverseNegotiationSink *)obj) + +typedef struct _GstTestReverseNegotiationSink GstTestReverseNegotiationSink; +typedef struct _GstTestReverseNegotiationSinkClass + GstTestReverseNegotiationSinkClass; +struct _GstTestReverseNegotiationSink +{ + GstBaseSink element; + gint nbuffers; +}; + +struct _GstTestReverseNegotiationSinkClass +{ + GstBaseSinkClass parent_class; +}; + +GType gst_test_reverse_negotiation_sink_get_type (void); + +GST_BOILERPLATE (GstTestReverseNegotiationSink, + gst_test_reverse_negotiation_sink, GstBaseSink, GST_TYPE_BASE_SINK); + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB)); + +static GstFlowReturn +gst_test_reverse_negotiation_sink_buffer_alloc (GstBaseSink * bsink, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstTestReverseNegotiationSink *sink = + GST_TEST_REVERSE_NEGOTIATION_SINK (bsink); + GstVideoFormat fmt; + gint width, height; + + fail_unless (gst_video_format_parse_caps (caps, &fmt, &width, &height)); + + if (sink->nbuffers < 2) { + *buf = + gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width, + height)); + gst_buffer_set_caps (*buf, caps); + } else { + gint fps_n, fps_d; + + fail_unless (gst_video_parse_caps_framerate (caps, &fps_n, &fps_d)); + + width = 512; + height = 128; + *buf = + gst_buffer_new_and_alloc (gst_video_format_get_size (fmt, width, + height)); + caps = gst_video_format_new_caps (fmt, width, height, fps_n, fps_d, 1, 1); + gst_buffer_set_caps (*buf, caps); + gst_caps_unref (caps); + } + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_test_reverse_negotiation_sink_render (GstBaseSink * bsink, + GstBuffer * buffer) +{ + GstTestReverseNegotiationSink *sink = + GST_TEST_REVERSE_NEGOTIATION_SINK (bsink); + GstCaps *caps = gst_buffer_get_caps (buffer); + GstVideoFormat fmt; + gint width, height; + + fail_unless (caps != NULL); + fail_unless (gst_video_format_parse_caps (caps, &fmt, &width, &height)); + + sink->nbuffers++; + + /* The third buffer is still in the old size + * because the ffmpegcolorspaces can't convert + * the frame sizes + */ + if (sink->nbuffers > 3) { + fail_unless_equals_int (width, 512); + fail_unless_equals_int (height, 128); + } + + gst_caps_unref (caps); + + return GST_FLOW_OK; +} + +static void +gst_test_reverse_negotiation_sink_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "Test Reverse Negotiation Sink", + "Sink", + "Some test sink", "Sebastian Dröge "); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); +} + +static void +gst_test_reverse_negotiation_sink_class_init (GstTestReverseNegotiationSinkClass + * klass) +{ + GstBaseSinkClass *gstbase_sink_class; + + gstbase_sink_class = GST_BASE_SINK_CLASS (klass); + + gstbase_sink_class->buffer_alloc = + GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_buffer_alloc); + gstbase_sink_class->render = + GST_DEBUG_FUNCPTR (gst_test_reverse_negotiation_sink_render); +} + +static void +gst_test_reverse_negotiation_sink_init (GstTestReverseNegotiationSink * sink, + GstTestReverseNegotiationSinkClass * g_class) +{ + sink->nbuffers = 0; +} + +static void +_test_reverse_negotiation_message (GstBus * bus, GstMessage * message, + GMainLoop * loop) +{ + GError *err = NULL; + gchar *debug; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + gst_message_parse_error (message, &err, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), err, debug); + g_error_free (err); + g_free (debug); + g_assert_not_reached (); + break; + case GST_MESSAGE_WARNING: + gst_message_parse_warning (message, &err, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), err, debug); + g_error_free (err); + g_free (debug); + g_assert_not_reached (); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + break; + default: + break; + } +} + +GST_START_TEST (test_reverse_negotiation) +{ + GstElement *pipeline; + GstElement *src, *csp1, *scale, *csp2, *sink; + GstBus *bus; + GMainLoop *loop; + + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + fail_unless (pipeline != NULL); + + src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (src != NULL); + g_object_set (G_OBJECT (src), "num-buffers", 8, NULL); + + csp1 = gst_element_factory_make ("ffmpegcolorspace", "csp1"); + fail_unless (csp1 != NULL); + + scale = gst_element_factory_make ("videoscale", "scale"); + fail_unless (scale != NULL); + + csp2 = gst_element_factory_make ("ffmpegcolorspace", "csp2"); + fail_unless (csp2 != NULL); + + sink = g_object_new (GST_TYPE_TEST_REVERSE_NEGOTIATION_SINK, NULL); + fail_unless (sink != NULL); + g_object_set (sink, "async", FALSE, NULL); + + gst_bin_add_many (GST_BIN (pipeline), src, csp1, scale, csp2, sink, NULL); + + fail_unless (gst_element_link_pads_full (src, "src", csp1, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (csp1, "src", scale, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (scale, "src", csp2, "sink", + LINK_CHECK_FLAGS)); + fail_unless (gst_element_link_pads_full (csp2, "src", sink, "sink", + LINK_CHECK_FLAGS)); + + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL); + gst_bus_add_signal_watch (bus); + + g_signal_connect (bus, "message", + G_CALLBACK (_test_reverse_negotiation_message), loop); + + gst_object_unref (bus); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS); + + g_main_loop_run (loop); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + gst_object_unref (pipeline); + g_main_loop_unref (loop); +} + +GST_END_TEST; + +GST_START_TEST (test_basetransform_negotiation) +{ + GstElement *pipeline, *src, *sink, *scale, *capsfilter1, *capsfilter2; + GstMessage *msg; + GstCaps *caps; + + pipeline = gst_pipeline_new (NULL); + src = gst_element_factory_make ("videotestsrc", NULL); + capsfilter1 = gst_element_factory_make ("capsfilter", NULL); + scale = gst_element_factory_make ("videoscale", NULL); + capsfilter2 = gst_element_factory_make ("capsfilter", NULL); + sink = gst_element_factory_make ("fakesink", NULL); + fail_unless (pipeline && src && capsfilter1 && scale && capsfilter2 && sink); + + g_object_set (src, "num-buffers", 3, NULL); + + caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), "width", G_TYPE_INT, 352, + "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); + g_object_set (capsfilter1, "caps", caps, NULL); + gst_caps_unref (caps); + + /* same caps, just different pixel-aspect-ratio */ + caps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'), "width", G_TYPE_INT, 352, + "height", G_TYPE_INT, 288, "framerate", GST_TYPE_FRACTION, 30, 1, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 12, 11, NULL); + g_object_set (capsfilter2, "caps", caps, NULL); + gst_caps_unref (caps); + + gst_bin_add_many (GST_BIN (pipeline), src, capsfilter1, scale, capsfilter2, + sink, NULL); + fail_unless (gst_element_link_many (src, capsfilter1, scale, capsfilter2, + sink, NULL)); + + fail_unless_equals_int (gst_element_set_state (pipeline, GST_STATE_PLAYING), + GST_STATE_CHANGE_ASYNC); + + msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), -1, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_EOS); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +videoscale_suite (void) +{ + Suite *s = suite_create ("videoscale"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_set_timeout (tc_chain, 180); + tcase_add_test (tc_chain, test_passthrough); + tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_0); + tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_1); + tcase_add_test (tc_chain, test_downscale_640x480_320x240_method_2); + tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_0); + tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_1); + tcase_add_test (tc_chain, test_upscale_320x240_640x480_method_2); + tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_0); + tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_1); + tcase_add_test (tc_chain, test_downscale_640x480_1x1_method_2); + tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_0); + tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_1); + tcase_add_test (tc_chain, test_upscale_1x1_640x480_method_2); + tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_0); + tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_1); + tcase_add_test (tc_chain, test_downscale_641x481_111x30_method_2); + tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_0); + tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_1); + tcase_add_test (tc_chain, test_upscale_111x30_641x481_method_2); + tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_0); + tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_1); + tcase_add_test (tc_chain, test_downscale_641x481_30x111_method_2); + tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_0); + tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_1); + tcase_add_test (tc_chain, test_upscale_30x111_641x481_method_2); + tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_0); + tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_1); + tcase_add_test (tc_chain, test_downscale_640x480_320x1_method_2); + tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_0); + tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_1); + tcase_add_test (tc_chain, test_upscale_320x1_640x480_method_2); + tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_0); + tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_1); + tcase_add_test (tc_chain, test_downscale_640x480_1x240_method_2); + tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_0); + tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_1); + tcase_add_test (tc_chain, test_upscale_1x240_640x480_method_2); + tcase_add_test (tc_chain, test_negotiation); + tcase_add_test (tc_chain, test_reverse_negotiation); + tcase_add_test (tc_chain, test_basetransform_negotiation); + + GST_ERROR ("FIXME: test 64-bpp formats as well"); + return s; +} + +GST_CHECK_MAIN (videoscale); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/videotestsrc.c b/gst-plugins-base-subtitles0.10/tests/check/elements/videotestsrc.c new file mode 100644 index 0000000..635ca32 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/videotestsrc.c @@ -0,0 +1,428 @@ +/* GStreamer + * + * unit test for videotestsrc + * + * Copyright (C) <2005> Thomas Vander Stichele + * Copyright (C) <2006> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#ifdef HAVE_VALGRIND +# include +#endif + +#include + +#include + +/* 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 *mysinkpad; + + +#define CAPS_TEMPLATE_STRING \ + "video/x-raw-yuv, " \ + "format = (fourcc) UYVY, " \ + "width = (int) [ 1, MAX ], " \ + "height = (int) [ 1, MAX ], " \ + "framerate = (fraction) [ 0/1, MAX ]" + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (CAPS_TEMPLATE_STRING) + ); + +static GstElement * +setup_videotestsrc (void) +{ + GstElement *videotestsrc; + + GST_DEBUG ("setup_videotestsrc"); + videotestsrc = gst_check_setup_element ("videotestsrc"); + mysinkpad = gst_check_setup_sink_pad (videotestsrc, &sinktemplate, NULL); + gst_pad_set_active (mysinkpad, TRUE); + + return videotestsrc; +} + +static void +cleanup_videotestsrc (GstElement * videotestsrc) +{ + GST_DEBUG ("cleanup_videotestsrc"); + + gst_check_drop_buffers (); + + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_sink_pad (videotestsrc); + gst_check_teardown_element (videotestsrc); +} + +GST_START_TEST (test_all_patterns) +{ + GstElement *videotestsrc; + GObjectClass *oclass; + GParamSpec *property; + GEnumValue *values; + guint j = 0; + + videotestsrc = setup_videotestsrc (); + oclass = G_OBJECT_GET_CLASS (videotestsrc); + property = g_object_class_find_property (oclass, "pattern"); + fail_unless (G_IS_PARAM_SPEC_ENUM (property)); + values = G_ENUM_CLASS (g_type_class_ref (property->value_type))->values; + + while (values[j].value_name) { + GST_DEBUG_OBJECT (videotestsrc, "testing pattern %s", values[j].value_name); + + g_object_set (videotestsrc, "pattern", j, NULL); + + fail_unless (gst_element_set_state (videotestsrc, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + g_mutex_lock (check_mutex); + while (g_list_length (buffers) < 10) { + GST_DEBUG_OBJECT (videotestsrc, "Waiting for more buffers"); + g_cond_wait (check_cond, check_mutex); + } + g_mutex_unlock (check_mutex); + + gst_element_set_state (videotestsrc, GST_STATE_READY); + + gst_check_drop_buffers (); + ++j; + } + + /* cleanup */ + cleanup_videotestsrc (videotestsrc); +} + +GST_END_TEST; + +static guint32 +right_shift_colour (guint32 mask, guint32 pixel) +{ + if (mask == 0) + return 0; + + pixel = pixel & mask; + while ((mask & 0x01) == 0) { + mask = mask >> 1; + pixel = pixel >> 1; + } + + return pixel; +} + +static guint8 +fix_expected_colour (guint32 col_mask, guint8 col_expected) +{ + guint32 mask; + gint last = g_bit_nth_msf (col_mask, -1); + gint first = g_bit_nth_lsf (col_mask, -1); + + mask = 1 << (last - first + 1); + mask -= 1; + + g_assert (col_expected == 0x00 || col_expected == 0xff); + + /* this only works because we only check for all-bits-set or no-bits-set */ + return col_expected & mask; +} + +static void +check_rgb_buf (const guint8 * pixels, guint32 r_mask, guint32 g_mask, + guint32 b_mask, guint32 a_mask, guint8 r_expected, guint8 g_expected, + guint8 b_expected, guint endianness, guint bpp, guint depth) +{ + guint32 pixel, red, green, blue, alpha; + + switch (bpp) { + case 32:{ + if (endianness == G_LITTLE_ENDIAN) + pixel = GST_READ_UINT32_LE (pixels); + else + pixel = GST_READ_UINT32_BE (pixels); + break; + } + case 24:{ + if (endianness == G_BIG_ENDIAN) { + pixel = (GST_READ_UINT8 (pixels) << 16) | + (GST_READ_UINT8 (pixels + 1) << 8) | + (GST_READ_UINT8 (pixels + 2) << 0); + } else { + pixel = (GST_READ_UINT8 (pixels + 2) << 16) | + (GST_READ_UINT8 (pixels + 1) << 8) | + (GST_READ_UINT8 (pixels + 0) << 0); + } + break; + } + case 16:{ + if (endianness == G_LITTLE_ENDIAN) + pixel = GST_READ_UINT16_LE (pixels); + else + pixel = GST_READ_UINT16_BE (pixels); + break; + } + default: + g_return_if_reached (); + } + + red = right_shift_colour (r_mask, pixel); + green = right_shift_colour (g_mask, pixel); + blue = right_shift_colour (b_mask, pixel); + alpha = right_shift_colour (a_mask, pixel); + + /* can't enable this by default, valgrind will complain about accessing + * uninitialised memory for the depth=24,bpp=32 formats ... */ + /* GST_LOG ("pixels: 0x%02x 0x%02x 0x%02x 0x%02x => pixel = 0x%08x", + pixels[0], (guint) pixels[1], pixels[2], pixels[3], pixel); */ + + /* fix up the mask (for rgb15/16) */ + if (bpp == 16) { + r_expected = fix_expected_colour (r_mask, r_expected); + g_expected = fix_expected_colour (g_mask, g_expected); + b_expected = fix_expected_colour (b_mask, b_expected); + } + + fail_unless (red == r_expected, "RED: expected 0x%02x, found 0x%02x", + r_expected, red); + fail_unless (green == g_expected, "GREEN: expected 0x%02x, found 0x%02x", + g_expected, green); + fail_unless (blue == b_expected, "BLUE: expected 0x%02x, found 0x%02x", + b_expected, blue); + + fail_unless (a_mask == 0 || alpha != 0); /* better than nothing */ +} + +static void +got_buf_cb (GstElement * sink, GstBuffer * new_buf, GstPad * pad, + GstBuffer ** p_old_buf) +{ + gst_buffer_replace (p_old_buf, new_buf); +} + +/* tests the positioning of pixels within the various RGB pixel layouts */ +GST_START_TEST (test_rgb_formats) +{ + const struct + { + const gchar *pattern_name; + gint pattern_enum; + guint8 r_expected; + guint8 g_expected; + guint8 b_expected; + } test_patterns[] = { + { + "white", 3, 0xff, 0xff, 0xff}, { + "red", 4, 0xff, 0x00, 0x00}, { + "green", 5, 0x00, 0xff, 0x00}, { + "blue", 6, 0x00, 0x00, 0xff}, { + "black", 2, 0x00, 0x00, 0x00} + }; + const struct + { + const gchar *nick; + guint bpp, depth; + guint32 red_mask, green_mask, blue_mask, alpha_mask; + } rgb_formats[] = { + { + "RGBA", 32, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff}, { + "ARGB", 32, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000}, { + "BGRA", 32, 32, 0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff}, { + "ABGR", 32, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000}, { + "RGBx", 32, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x00000000}, { + "xRGB", 32, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, { + "BGRx", 32, 24, 0x0000ff00, 0x00ff0000, 0xff000000, 0x00000000}, { + "xBGR", 32, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}, { + "RGB ", 24, 24, 0x00ff0000, 0x0000ff00, 0x000000ff, 0x00000000}, { + "BGR ", 24, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000}, { + "RGB565", 16, 16, 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000}, { + "xRGB1555", 16, 15, 0x00007c00, 0x000003e0, 0x0000001f, 0x0000000} + }; + GstElement *pipeline, *src, *filter, *sink; + const GstCaps *template_caps; + GstBuffer *buf = NULL; + GstPad *srcpad; + gint p, i, e; + + /* test check function */ + fail_unless (right_shift_colour (0x00ff0000, 0x11223344) == 0x22); + + pipeline = gst_pipeline_new ("pipeline"); + src = gst_check_setup_element ("videotestsrc"); + filter = gst_check_setup_element ("capsfilter"); + sink = gst_check_setup_element ("fakesink"); + + gst_bin_add_many (GST_BIN (pipeline), src, filter, sink, NULL); + + fail_unless (gst_element_link (src, filter)); + fail_unless (gst_element_link (filter, sink)); + + srcpad = gst_element_get_static_pad (src, "src"); + template_caps = gst_pad_get_pad_template_caps (srcpad); + gst_object_unref (srcpad); + + g_object_set (sink, "signal-handoffs", TRUE, NULL); + g_signal_connect (sink, "preroll-handoff", G_CALLBACK (got_buf_cb), &buf); + + GST_LOG ("videotestsrc src template caps: %" GST_PTR_FORMAT, template_caps); + + for (i = 0; i < G_N_ELEMENTS (rgb_formats); ++i) { + for (e = 0; e < 2; ++e) { + guint endianness; + GstCaps *caps; + + if (e == 0) { + endianness = G_BYTE_ORDER; + } else { + endianness = + (G_BYTE_ORDER == G_BIG_ENDIAN) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN; + } + + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, rgb_formats[i].bpp, + "depth", G_TYPE_INT, rgb_formats[i].depth, + "red_mask", G_TYPE_INT, rgb_formats[i].red_mask, + "green_mask", G_TYPE_INT, rgb_formats[i].green_mask, + "blue_mask", G_TYPE_INT, rgb_formats[i].blue_mask, + "width", G_TYPE_INT, 16, "height", G_TYPE_INT, 16, + "endianness", G_TYPE_INT, endianness, + "framerate", GST_TYPE_FRACTION, 1, 1, NULL); + + fail_unless (rgb_formats[i].alpha_mask == 0 || rgb_formats[i].bpp == 32); + + if (rgb_formats[i].alpha_mask != 0) { + gst_structure_set (gst_caps_get_structure (caps, 0), + "alpha_mask", G_TYPE_INT, rgb_formats[i].alpha_mask, NULL); + } + + if (gst_caps_is_subset (caps, template_caps)) { + + /* caps are supported, let's run some tests then ... */ + for (p = 0; p < G_N_ELEMENTS (test_patterns); ++p) { + GstStateChangeReturn state_ret; + + g_object_set (src, "pattern", test_patterns[p].pattern_enum, NULL); + + GST_INFO ("%5s %u/%u %08x %08x %08x %08x %u, pattern=%s", + rgb_formats[i].nick, rgb_formats[i].bpp, rgb_formats[i].depth, + rgb_formats[i].red_mask, rgb_formats[i].green_mask, + rgb_formats[i].blue_mask, rgb_formats[i].alpha_mask, endianness, + test_patterns[p].pattern_name); + + /* now get videotestsrc to produce a buffer with the given caps */ + g_object_set (filter, "caps", caps, NULL); + + state_ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + fail_unless (state_ret != GST_STATE_CHANGE_FAILURE, + "pipeline _set_state() to PAUSED failed"); + state_ret = gst_element_get_state (pipeline, NULL, NULL, -1); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS, + "pipeline failed going to PAUSED state"); + + state_ret = gst_element_set_state (pipeline, GST_STATE_NULL); + fail_unless (state_ret == GST_STATE_CHANGE_SUCCESS); + + fail_unless (buf != NULL); + + /* check buffer caps */ + { + GstStructure *s; + gint v; + + fail_unless (GST_BUFFER_CAPS (buf) != NULL); + + s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + fail_unless (gst_structure_get_int (s, "bpp", &v)); + fail_unless_equals_int (v, rgb_formats[i].bpp); + fail_unless (gst_structure_get_int (s, "depth", &v)); + fail_unless_equals_int (v, rgb_formats[i].depth); + fail_unless (gst_structure_get_int (s, "red_mask", &v)); + fail_unless_equals_int (v, rgb_formats[i].red_mask); + fail_unless (gst_structure_get_int (s, "green_mask", &v)); + fail_unless_equals_int (v, rgb_formats[i].green_mask); + fail_unless (gst_structure_get_int (s, "blue_mask", &v)); + fail_unless_equals_int (v, rgb_formats[i].blue_mask); + /* there mustn't be an alpha_mask if there's no alpha component */ + if (rgb_formats[i].depth == 32) { + fail_unless (gst_structure_get_int (s, "alpha_mask", &v)); + fail_unless_equals_int (v, rgb_formats[i].alpha_mask); + } else { + fail_unless (gst_structure_get_value (s, "alpha_mask") == NULL); + } + } + + + /* now check the first pixel */ + check_rgb_buf (GST_BUFFER_DATA (buf), rgb_formats[i].red_mask, + rgb_formats[i].green_mask, rgb_formats[i].blue_mask, + rgb_formats[i].alpha_mask, test_patterns[p].r_expected, + test_patterns[p].g_expected, test_patterns[p].b_expected, + endianness, rgb_formats[i].bpp, rgb_formats[i].depth); + + gst_buffer_unref (buf); + buf = NULL; + } + + } else { + GST_INFO ("videotestsrc doesn't support format %" GST_PTR_FORMAT, caps); + } + + gst_caps_unref (caps); + } + } + + gst_object_unref (pipeline); +} + +GST_END_TEST; + + +/* FIXME: add tests for YUV formats */ + +static Suite * +videotestsrc_suite (void) +{ + Suite *s = suite_create ("videotestsrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + +#ifdef HAVE_VALGRIND + if (RUNNING_ON_VALGRIND) { + /* otherwise valgrind errors out when liboil probes CPU extensions + * during which it causes SIGILLs etc. to be fired */ + g_setenv ("OIL_CPU_FLAGS", "0", 0); + /* test_rgb_formats takes a bit longer, so increase timeout */ + tcase_set_timeout (tc_chain, 5 * 60); + } +#endif + + tcase_add_test (tc_chain, test_all_patterns); + tcase_add_test (tc_chain, test_rgb_formats); + + return s; +} + +GST_CHECK_MAIN (videotestsrc); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/volume.c b/gst-plugins-base-subtitles0.10/tests/check/elements/volume.c new file mode 100644 index 0000000..d59a96f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/volume.c @@ -0,0 +1,1525 @@ +/* GStreamer + * + * unit test for volume + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include +#include + +/* 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 VOLUME_CAPS_TEMPLATE_STRING \ + "audio/x-raw-int, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 8, 16, 24, 32 }, " \ + "depth = (int) { 8, 16, 24, 32 }, " \ + "signed = (bool) TRUE; " \ + "audio/x-raw-float, " \ + "channels = (int) [ 1, MAX ], " \ + "rate = (int) [ 1, MAX ], " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) { 32, 64 }" \ + +#define VOLUME_CAPS_STRING_S8 \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 8, " \ + "depth = (int) 8, " \ + "signed = (bool) TRUE" + +#define VOLUME_CAPS_STRING_S16 \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (bool) TRUE" + +#define VOLUME_CAPS_STRING_S24 \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 24, " \ + "depth = (int) 24, " \ + "signed = (bool) TRUE" + +#define VOLUME_CAPS_STRING_S32 \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32, " \ + "depth = (int) 32, " \ + "signed = (bool) TRUE" + +#define VOLUME_CAPS_STRING_F32 \ + "audio/x-raw-float, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 32" + +#define VOLUME_CAPS_STRING_F64 \ + "audio/x-raw-float, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 64" + +#define VOLUME_WRONG_CAPS_STRING \ + "audio/x-raw-int, " \ + "channels = (int) 1, " \ + "rate = (int) 44100, " \ + "endianness = (int) BYTE_ORDER, " \ + "width = (int) 16, " \ + "depth = (int) 16, " \ + "signed = (bool) FALSE" + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING) + ); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (VOLUME_CAPS_TEMPLATE_STRING) + ); + +static GstElement * +setup_volume (void) +{ + GstElement *volume; + + GST_DEBUG ("setup_volume"); + volume = gst_check_setup_element ("volume"); + mysrcpad = gst_check_setup_src_pad (volume, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (volume, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return volume; +} + +static void +cleanup_volume (GstElement * volume) +{ + GST_DEBUG ("cleanup_volume"); + + g_list_foreach (buffers, (GFunc) gst_mini_object_unref, NULL); + g_list_free (buffers); + buffers = NULL; + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (volume); + gst_check_teardown_sink_pad (volume); + gst_check_teardown_element (volume); +} + +GST_START_TEST (test_get_set) +{ + GstElement *volume = gst_element_factory_make ("volume", NULL); + gdouble val; + + fail_unless (volume != NULL); + g_object_get (G_OBJECT (volume), "volume", &val, NULL); + fail_unless (val == 1.0); + fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume), + GST_STREAM_VOLUME_FORMAT_LINEAR)); + + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + g_object_get (G_OBJECT (volume), "volume", &val, NULL); + fail_unless (val == 0.5); + fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume), + GST_STREAM_VOLUME_FORMAT_LINEAR)); + + gst_stream_volume_set_volume (GST_STREAM_VOLUME (volume), + GST_STREAM_VOLUME_FORMAT_LINEAR, 1.0); + g_object_get (G_OBJECT (volume), "volume", &val, NULL); + fail_unless (val == 1.0); + fail_unless (val == gst_stream_volume_get_volume (GST_STREAM_VOLUME (volume), + GST_STREAM_VOLUME_FORMAT_LINEAR)); + + gst_object_unref (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_unity_s8) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint8 in[2] = { 64, -16 }; + gint8 *res; + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (2); + memcpy (GST_BUFFER_DATA (inbuffer), in, 2); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint8 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_s8) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint8 in[2] = { 64, -16 }; + gint8 out[2] = { 32, -8 }; + gint8 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (2); + memcpy (GST_BUFFER_DATA (inbuffer), in, 2); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint8 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_s8) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint8 in[2] = { 64, -16 }; + gint8 out[2] = { 127, -32 }; /* notice the clamped sample */ + gint8 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (2); + memcpy (GST_BUFFER_DATA (inbuffer), in, 2); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint8 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_mute_s8) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint8 in[2] = { 64, -16 }; + gint8 out[2] = { 0, 0 }; + gint8 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (2); + memcpy (GST_BUFFER_DATA (inbuffer), in, 2); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 2) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S8); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint8 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 2) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_unity_s16) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 *res; + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_s16) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 out[2] = { 8192, -128 }; + gint16 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_s16) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 out[2] = { 32767, -512 }; /* notice the clamped sample */ + gint16 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + + +GST_START_TEST (test_mute_s16) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 out[2] = { 0, 0 }; + gint16 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 4) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) +#define get_unaligned_i24(_x) ( (((guint8*)_x)[0]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[2]) << 16) ) +#define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = samp & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = (samp >> 16) & 0xFF; } while (0) +#else /* BIG ENDIAN */ +#define get_unaligned_i24(_x) ( (((guint8*)_x)[2]) | ((((guint8*)_x)[1]) << 8) | ((((gint8*)_x)[0]) << 16) ) +#define write_unaligned_u24(_x,samp) do { (((guint8*)_x)[0]) = (samp >> 16) & 0xFF; (((guint8*)_x)[1]) = (samp >> 8) & 0xFF; (((guint8*)_x)[2]) = samp & 0xFF; } while (0) +#endif + +GST_START_TEST (test_unity_s24) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint32 in_32[2] = { 4194304, -4096 }; + guint8 in[6]; + guint8 *res; + gint32 res_32[2]; + + + write_unaligned_u24 (in, in_32[0]); + write_unaligned_u24 (in + 3, in_32[1]); + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (6); + memcpy (GST_BUFFER_DATA (inbuffer), in, 6); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = GST_BUFFER_DATA (outbuffer); + + res_32[0] = get_unaligned_i24 (res); + res_32[1] = get_unaligned_i24 ((res + 3)); + + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in_32[0], in_32[1], res_32[0], + res_32[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_s24) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in_32[2] = { 4194304, -4096 }; + guint8 in[6]; + guint8 *res; + gint32 res_32[2]; + gint32 out_32[2] = { 2097152, -2048 }; + + write_unaligned_u24 (in, in_32[0]); + write_unaligned_u24 (in + 3, in_32[1]); + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (6); + memcpy (GST_BUFFER_DATA (inbuffer), in, 6); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = GST_BUFFER_DATA (outbuffer); + + res_32[0] = get_unaligned_i24 (res); + res_32[1] = get_unaligned_i24 ((res + 3)); + + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1], + res_32[0], res_32[1]); + fail_unless (memcmp (res_32, out_32, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_s24) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in_32[2] = { 4194304, -4096 }; + guint8 in[6]; + guint8 *res; + gint32 res_32[2]; + gint32 out_32[2] = { 8388607, -8192 }; /* notice the clamped sample */ + + write_unaligned_u24 (in, in_32[0]); + write_unaligned_u24 (in + 3, in_32[1]); + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (6); + memcpy (GST_BUFFER_DATA (inbuffer), in, 6); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = GST_BUFFER_DATA (outbuffer); + + res_32[0] = get_unaligned_i24 (res); + res_32[1] = get_unaligned_i24 ((res + 3)); + + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1], + res_32[0], res_32[1]); + fail_unless (memcmp (res_32, out_32, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + + +GST_START_TEST (test_mute_s24) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in_32[2] = { 4194304, -4096 }; + guint8 in[6]; + guint8 *res; + gint32 res_32[2]; + gint32 out_32[2] = { 0, 0 }; /* notice the clamped sample */ + + write_unaligned_u24 (in, in_32[0]); + write_unaligned_u24 (in + 3, in_32[1]); + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (6); + memcpy (GST_BUFFER_DATA (inbuffer), in, 6); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 6) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S24); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + + res = GST_BUFFER_DATA (outbuffer); + + res_32[0] = get_unaligned_i24 (res); + res_32[1] = get_unaligned_i24 ((res + 3)); + + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out_32[0], out_32[1], + res_32[0], res_32[1]); + fail_unless (memcmp (res_32, out_32, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_unity_s32) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint32 in[2] = { 1073741824, -65536 }; + gint32 *res; + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint32 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_s32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in[2] = { 1073741824, -65536 }; + gint32 out[2] = { 536870912, -32768 }; + gint32 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint32 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_s32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in[2] = { 1073741824, -65536 }; + gint32 out[2] = { 2147483647, -131072 }; /* notice the clamped sample */ + gint32 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint32 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + + +GST_START_TEST (test_mute_s32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gint32 in[2] = { 1073741824, -65536 }; + gint32 out[2] = { 0, 0 }; + gint32 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint32 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", out[0], out[1], res[0], + res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), out, 8) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_unity_f32) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gfloat in[2] = { 0.75, -0.25 }; + gfloat *res; + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gfloat *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", in[0], in[1], res[0], + res[1]); + fail_unless_equals_float (res[0], in[0]); + fail_unless_equals_float (res[1], in[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_f32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gfloat in[2] = { 0.75, -0.25 }; + gfloat out[2] = { 0.375, -0.125 }; + gfloat *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gfloat *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_f32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gfloat in[2] = { 0.75, -0.25 }; + gfloat out[2] = { 1.5, -0.5 }; /* nothing is clamped */ + gfloat *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gfloat *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + + +GST_START_TEST (test_mute_f32) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gfloat in[2] = { 0.75, -0.25 }; + gfloat out[2] = { 0, 0 }; + gfloat *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (8); + memcpy (GST_BUFFER_DATA (inbuffer), in, 8); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 8) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F32); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gfloat *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_unity_f64) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gdouble in[2] = { 0.75, -0.25 }; + gdouble *res; + + volume = setup_volume (); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (16); + memcpy (GST_BUFFER_DATA (inbuffer), in, 16); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gdouble *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", in[0], in[1], res[0], + res[1]); + fail_unless_equals_float (res[0], in[0]); + fail_unless_equals_float (res[1], in[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_half_f64) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gdouble in[2] = { 0.75, -0.25 }; + gdouble out[2] = { 0.375, -0.125 }; + gdouble *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 0.5, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (16); + memcpy (GST_BUFFER_DATA (inbuffer), in, 16); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gdouble *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_double_f64) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gdouble in[2] = { 0.75, -0.25 }; + gdouble out[2] = { 1.5, -0.5 }; /* nothing is clamped */ + gdouble *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 2.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (16); + memcpy (GST_BUFFER_DATA (inbuffer), in, 16); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gdouble *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + + +GST_START_TEST (test_mute_f64) +{ + GstElement *volume; + GstBuffer *inbuffer; + GstBuffer *outbuffer; + GstCaps *caps; + gdouble in[2] = { 0.75, -0.25 }; + gdouble out[2] = { 0, 0 }; + gdouble *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "mute", TRUE, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (16); + memcpy (GST_BUFFER_DATA (inbuffer), in, 16); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 16) == 0); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_F64); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + /* FIXME: reffing the inbuffer should make the transformation not be + * inplace + gst_buffer_ref (inbuffer); + */ + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being modified inplace and + * collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gdouble *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+1.4f %+1.4f real %+1.4f %+1.4f", out[0], out[1], + res[0], res[1]); + fail_unless_equals_float (res[0], out[0]); + fail_unless_equals_float (res[1], out[1]); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_wrong_caps) +{ + GstElement *volume; + GstBuffer *inbuffer; + gint16 in[2] = { 16384, -256 }; + GstBus *bus; + GstMessage *message; + GstCaps *caps; + + volume = setup_volume (); + bus = gst_bus_new (); + + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + caps = gst_caps_from_string (VOLUME_WRONG_CAPS_STRING); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_ref (inbuffer); + + /* set a bus here so we avoid getting state change messages */ + gst_element_set_bus (volume, bus); + + /* pushing gives an error because it can't negotiate with wrong caps */ + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), + GST_FLOW_NOT_NEGOTIATED); + /* ... and the buffer would have been lost if we didn't ref it ourselves */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless_equals_int (g_list_length (buffers), 0); + + /* volume_set_caps should not have been called since basetransform caught + * the negotiation problem */ + fail_if ((message = gst_bus_pop (bus)) != NULL); + + /* cleanup */ + gst_element_set_bus (volume, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_passthrough) +{ + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 *res; + + volume = setup_volume (); + g_object_set (G_OBJECT (volume), "volume", 1.0, NULL); + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + + /* cleanup */ + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_controller_usability) +{ + GstInterpolationControlSource *csource; + GstController *c; + GstElement *volume; + GValue value = { 0, }; + + /* note: the volume element should init the controller library for us */ + volume = setup_volume (); + + c = gst_controller_new (G_OBJECT (volume), "volume", NULL); + + fail_unless (GST_IS_CONTROLLER (c)); + + /* this shouldn't crash, whether this mode is implemented or not */ + csource = gst_interpolation_control_source_new (); + gst_interpolation_control_source_set_interpolation_mode (csource, + GST_INTERPOLATE_CUBIC); + gst_controller_set_control_source (c, "volume", GST_CONTROL_SOURCE (csource)); + g_object_unref (csource); + + g_value_init (&value, G_TYPE_DOUBLE); + g_value_set_double (&value, 0.0); + gst_interpolation_control_source_set (csource, 0 * GST_SECOND, &value); + g_value_set_double (&value, 1.0); + gst_interpolation_control_source_set (csource, 5 * GST_SECOND, &value); + g_value_set_double (&value, 0.0); + gst_interpolation_control_source_set (csource, 10 * GST_SECOND, &value); + g_value_unset (&value); + + g_object_unref (c); + + cleanup_volume (volume); +} + +GST_END_TEST; + +GST_START_TEST (test_controller_processing) +{ + GstInterpolationControlSource *csource; + GstController *c; + GstElement *volume; + GstBuffer *inbuffer, *outbuffer; + GstCaps *caps; + gint16 in[2] = { 16384, -256 }; + gint16 *res; + + volume = setup_volume (); + + c = gst_controller_new (G_OBJECT (volume), "volume", NULL); + + fail_unless (GST_IS_CONTROLLER (c)); + + csource = gst_interpolation_control_source_new (); + gst_interpolation_control_source_set_interpolation_mode (csource, + GST_INTERPOLATE_CUBIC); + gst_controller_set_control_source (c, "volume", GST_CONTROL_SOURCE (csource)); + g_object_unref (csource); + + fail_unless (gst_element_set_state (volume, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (4); + memcpy (GST_BUFFER_DATA (inbuffer), in, 4); + caps = gst_caps_from_string (VOLUME_CAPS_STRING_S16); + gst_buffer_set_caps (inbuffer, caps); + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + gst_caps_unref (caps); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... but it ends up being collected on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless_equals_int (g_list_length (buffers), 1); + fail_if ((outbuffer = (GstBuffer *) buffers->data) == NULL); + fail_unless (inbuffer == outbuffer); + res = (gint16 *) GST_BUFFER_DATA (outbuffer); + GST_INFO ("expected %+5d %+5d real %+5d %+5d", in[0], in[1], res[0], res[1]); + fail_unless (memcmp (GST_BUFFER_DATA (inbuffer), in, 4) == 0); + + g_object_unref (c); + + cleanup_volume (volume); +} + +GST_END_TEST; + +static Suite * +volume_suite (void) +{ + Suite *s = suite_create ("volume"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_get_set); + tcase_add_test (tc_chain, test_unity_s8); + tcase_add_test (tc_chain, test_half_s8); + tcase_add_test (tc_chain, test_double_s8); + tcase_add_test (tc_chain, test_mute_s8); + tcase_add_test (tc_chain, test_unity_s16); + tcase_add_test (tc_chain, test_half_s16); + tcase_add_test (tc_chain, test_double_s16); + tcase_add_test (tc_chain, test_mute_s16); + tcase_add_test (tc_chain, test_unity_s24); + tcase_add_test (tc_chain, test_half_s24); + tcase_add_test (tc_chain, test_double_s24); + tcase_add_test (tc_chain, test_mute_s24); + tcase_add_test (tc_chain, test_unity_s32); + tcase_add_test (tc_chain, test_half_s32); + tcase_add_test (tc_chain, test_double_s32); + tcase_add_test (tc_chain, test_mute_s32); + tcase_add_test (tc_chain, test_unity_f32); + tcase_add_test (tc_chain, test_half_f32); + tcase_add_test (tc_chain, test_double_f32); + tcase_add_test (tc_chain, test_mute_f32); + tcase_add_test (tc_chain, test_unity_f64); + tcase_add_test (tc_chain, test_half_f64); + tcase_add_test (tc_chain, test_double_f64); + tcase_add_test (tc_chain, test_mute_f64); + tcase_add_test (tc_chain, test_wrong_caps); + tcase_add_test (tc_chain, test_passthrough); + tcase_add_test (tc_chain, test_controller_usability); + tcase_add_test (tc_chain, test_controller_processing); + + return s; +} + +GST_CHECK_MAIN (volume) diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/vorbisdec.c b/gst-plugins-base-subtitles0.10/tests/check/elements/vorbisdec.c new file mode 100644 index 0000000..29e3cd5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/vorbisdec.c @@ -0,0 +1,339 @@ +/* GStreamer + * + * unit test for vorbisdec + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include +#include + +/* 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; + +/* a valid first header packet */ +static guchar identification_header[30] = { + 1, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 0, 0, 0, 0, /* vorbis_version */ + 2, /* audio_channels */ + 0x44, 0xac, 0, 0, /* sample_rate */ + 0xff, 0xff, 0xff, 0xff, /* bitrate_maximum */ + 0x00, 0xee, 0x02, 0x00, /* bitrate_nominal */ + 0xff, 0xff, 0xff, 0xff, /* bitrate_minimum */ + 0xb8, /* blocksize_0, blocksize_1 */ + 0x01, /* framing_flag */ +}; + +static guchar comment_header[] = { + 3, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 2, 0, 0, 0, /* vendor_length */ + 'm', 'e', + 1, 0, 0, 0, /* user_comment_list_length */ + 9, 0, 0, 0, /* length comment[0] */ + 'A', 'R', 'T', 'I', 'S', 'T', '=', 'm', 'e', + 0x01, /* framing bit */ +}; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstElement * +setup_vorbisdec (void) +{ + GstElement *vorbisdec; + + GST_DEBUG ("setup_vorbisdec"); + vorbisdec = gst_check_setup_element ("vorbisdec"); + mysrcpad = gst_check_setup_src_pad (vorbisdec, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (vorbisdec, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return vorbisdec; +} + +static void +cleanup_vorbisdec (GstElement * vorbisdec) +{ + GST_DEBUG ("cleanup_vorbisdec"); + gst_element_set_state (vorbisdec, GST_STATE_NULL); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (vorbisdec); + gst_check_teardown_sink_pad (vorbisdec); + gst_check_teardown_element (vorbisdec); +} + +GST_START_TEST (test_empty_identification_header) +{ + GstElement *vorbisdec; + GstBuffer *inbuffer; + GstBus *bus; + GstMessage *message; + + vorbisdec = setup_vorbisdec (); + bus = gst_bus_new (); + + fail_unless (gst_element_set_state (vorbisdec, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + + inbuffer = gst_buffer_new_and_alloc (0); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + + /* set a bus here so we avoid getting state change messages */ + gst_element_set_bus (vorbisdec, bus); + + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_ERROR); + /* ... but it ends up being collected on the global buffer list */ + fail_unless_equals_int (g_list_length (buffers), 0); + + fail_if ((message = gst_bus_pop (bus)) == NULL); + fail_unless_message_error (message, STREAM, DECODE); + gst_message_unref (message); + gst_element_set_bus (vorbisdec, NULL); + + /* cleanup */ + gst_object_unref (GST_OBJECT (bus)); + cleanup_vorbisdec (vorbisdec); +} + +GST_END_TEST; + +/* FIXME: also tests comment header */ +GST_START_TEST (test_identification_header) +{ + GstElement *vorbisdec; + GstBuffer *inbuffer; + GstBus *bus; + GstMessage *message; + GstTagList *tag_list; + gchar *artist; + + vorbisdec = setup_vorbisdec (); + fail_unless (gst_element_set_state (vorbisdec, + GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, + "could not set to playing"); + bus = gst_bus_new (); + + inbuffer = gst_buffer_new_and_alloc (30); + memcpy (GST_BUFFER_DATA (inbuffer), identification_header, 30); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_ref (inbuffer); + + gst_element_set_bus (vorbisdec, bus); + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... and nothing ends up on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless (g_list_length (buffers) == 0); + fail_if ((message = gst_bus_pop (bus)) != NULL); + + inbuffer = gst_buffer_new_and_alloc (sizeof (comment_header)); + memcpy (GST_BUFFER_DATA (inbuffer), comment_header, sizeof (comment_header)); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_ref (inbuffer); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... and nothing ends up on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless (g_list_length (buffers) == 0); + /* there's a tag message waiting */ + fail_if ((message = gst_bus_pop (bus)) == NULL); + gst_message_parse_tag (message, &tag_list); + fail_unless_equals_int (gst_tag_list_get_tag_size (tag_list, GST_TAG_ARTIST), + 1); + fail_unless (gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist)); + fail_unless_equals_string (artist, "me"); + g_free (artist); + fail_unless_equals_int (gst_tag_list_get_tag_size (tag_list, "album"), 0); + gst_tag_list_free (tag_list); + gst_message_unref (message); + + /* cleanup */ + gst_bus_set_flushing (bus, TRUE); + gst_element_set_bus (vorbisdec, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_vorbisdec (vorbisdec); +} + +GST_END_TEST; + +static vorbis_comment vc; +static vorbis_dsp_state vd; +static vorbis_info vi; +static vorbis_block vb; + +static GstBuffer * +_create_codebook_header_buffer (void) +{ + GstBuffer *buffer; + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_info_init (&vi); + vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5); + vorbis_encode_setup_init (&vi); + vorbis_analysis_init (&vd, &vi); + vorbis_block_init (&vd, &vb); + vorbis_comment_init (&vc); + vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code); + + buffer = gst_buffer_new_and_alloc (header_code.bytes); + memcpy (GST_BUFFER_DATA (buffer), header_code.packet, header_code.bytes); + + return buffer; +} + +static GstBuffer * +_create_audio_buffer (void) +{ + GstBuffer *buffer; + ogg_packet packet; + float **vorbis_buffer; + gint i; + + vorbis_buffer = vorbis_analysis_buffer (&vd, 44100); + for (i = 0; i < 44100 * 1; ++i) + vorbis_buffer[0][i] = 0.0; + vorbis_analysis_wrote (&vd, 44100); + vorbis_analysis_blockout (&vd, &vb); + vorbis_analysis (&vb, NULL); + vorbis_bitrate_addblock (&vb); + vorbis_bitrate_flushpacket (&vd, &packet); + buffer = gst_buffer_new_and_alloc (packet.bytes); + memcpy (GST_BUFFER_DATA (buffer), packet.packet, packet.bytes); + + vorbis_comment_clear (&vc); + vorbis_block_clear (&vb); + vorbis_dsp_clear (&vd); + vorbis_info_clear (&vi); + + return buffer; +} + +GST_START_TEST (test_empty_vorbis_packet) +{ + GstElement *vorbisdec; + GstBuffer *inbuffer; + GstMessage *message; + GstBus *bus; + + vorbisdec = setup_vorbisdec (); + fail_unless_equals_int (gst_element_set_state (vorbisdec, GST_STATE_PLAYING), + GST_STATE_CHANGE_SUCCESS); + + bus = gst_bus_new (); + + inbuffer = gst_buffer_new_and_alloc (30); + memcpy (GST_BUFFER_DATA (inbuffer), identification_header, 30); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_ref (inbuffer); + + gst_element_set_bus (vorbisdec, bus); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... and nothing ends up on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless (g_list_length (buffers) == 0); + fail_if ((message = gst_bus_pop (bus)) != NULL); + + inbuffer = gst_buffer_new_and_alloc (sizeof (comment_header)); + memcpy (GST_BUFFER_DATA (inbuffer), comment_header, sizeof (comment_header)); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_ref (inbuffer); + + /* pushing gives away my reference ... */ + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + /* ... and nothing ends up on the global buffer list */ + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless (g_list_length (buffers) == 0); + + /* send minimal codebook header and audio packers */ + inbuffer = _create_codebook_header_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* now send an empty vorbis packet, which should just be skipped */ + inbuffer = gst_buffer_new_and_alloc (0); + gst_buffer_ref (inbuffer); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + fail_unless (g_list_length (buffers) == 0); + + /* create and push an encoded audio packet */ + inbuffer = _create_audio_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* now send another empty vorbis packet, which should just be skipped */ + inbuffer = gst_buffer_new_and_alloc (0); + gst_buffer_ref (inbuffer); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + gst_buffer_unref (inbuffer); + + /* make sure there's no error on the bus */ + message = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0); + fail_if (message != NULL); + + /* cleanup */ + gst_bus_set_flushing (bus, TRUE); + gst_element_set_bus (vorbisdec, NULL); + gst_object_unref (GST_OBJECT (bus)); + cleanup_vorbisdec (vorbisdec); +} + +GST_END_TEST; + +static Suite * +vorbisdec_suite (void) +{ + Suite *s = suite_create ("vorbisdec"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_empty_identification_header); + tcase_add_test (tc_chain, test_identification_header); + tcase_add_test (tc_chain, test_empty_vorbis_packet); + + return s; +} + +GST_CHECK_MAIN (vorbisdec); diff --git a/gst-plugins-base-subtitles0.10/tests/check/elements/vorbistag.c b/gst-plugins-base-subtitles0.10/tests/check/elements/vorbistag.c new file mode 100644 index 0000000..4b20d6d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/elements/vorbistag.c @@ -0,0 +1,409 @@ +/* GStreamer + * + * unit test for vorbisdec + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include + +#include +#include + +/* a valid first header packet */ +static guchar identification_header[30] = { + 1, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 0, 0, 0, 0, /* vorbis_version */ + 2, /* audio_channels */ + 0x44, 0xac, 0, 0, /* sample_rate */ + 0xff, 0xff, 0xff, 0xff, /* bitrate_maximum */ + 0x00, 0xee, 0x02, 0x00, /* bitrate_nominal */ + 0xff, 0xff, 0xff, 0xff, /* bitrate_minimum */ + 0xb8, /* blocksize_0, blocksize_1 */ + 0x01 /* framing_flag */ +}; + +static guchar artist_comment_header[] = { + 3, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 2, 0, 0, 0, /* vendor_length */ + 'm', 'e', + 1, 0, 0, 0, /* user_comment_list_length */ + 9, 0, 0, 0, /* length comment[0] */ + 'A', 'R', 'T', 'I', 'S', 'T', '=', 'm', 'e', + 0x01, /* framing bit */ +}; + +static guchar title_comment_header[] = { + 3, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 2, 0, 0, 0, /* vendor_length */ + 'm', 'e', + 1, 0, 0, 0, /* user_comment_list_length */ + 12, 0, 0, 0, /* length comment[0] */ + 'T', 'I', 'T', 'L', 'E', '=', 'f', 'o', 'o', 'b', 'a', 'r', + 0x01, /* framing bit */ +}; + +static guchar empty_comment_header[] = { + 3, /* packet_type */ + 'v', 'o', 'r', 'b', 'i', 's', + 2, 0, 0, 0, /* vendor_length */ + 'm', 'e', + 0, 0, 0, 0, /* user_comment_list_length */ + 0x01, /* framing bit */ +}; + + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstPad *mysrcpad, *mysinkpad; +static GAsyncQueue *pending_buffers; +static gulong id; + + +static GstElement * +setup_vorbistag (void) +{ + GstElement *vorbistag; + + GST_DEBUG ("setup_vorbistag"); + vorbistag = gst_check_setup_element ("vorbistag"); + mysrcpad = gst_check_setup_src_pad (vorbistag, &srctemplate, NULL); + mysinkpad = gst_check_setup_sink_pad (vorbistag, &sinktemplate, NULL); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + return vorbistag; +} + +static void +cleanup_vorbistag (GstElement * vorbistag) +{ + GST_DEBUG ("cleanup_vorbistag"); + gst_element_set_state (vorbistag, GST_STATE_NULL); + + gst_pad_set_active (mysrcpad, FALSE); + gst_pad_set_active (mysinkpad, FALSE); + gst_check_teardown_src_pad (vorbistag); + gst_check_teardown_sink_pad (vorbistag); + gst_check_teardown_element (vorbistag); +} + + +static gboolean +buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused) +{ + g_async_queue_push (pending_buffers, gst_buffer_ref (buffer)); + return TRUE; +} + +static void +start_pipeline (GstElement * element) +{ + id = gst_pad_add_buffer_probe (mysinkpad, G_CALLBACK (buffer_probe), NULL); + + pending_buffers = g_async_queue_new (); + gst_element_set_state (element, GST_STATE_PLAYING); +} + +static GstBuffer * +get_buffer (void) +{ + return GST_BUFFER (g_async_queue_pop (pending_buffers)); +} + +static void +stop_pipeline (GstElement * element) +{ + GstBuffer *buf; + + while ((buf = g_async_queue_try_pop (pending_buffers))) + gst_buffer_unref (buf); + + gst_pad_remove_buffer_probe (mysinkpad, (guint) id); + id = 0; + + gst_element_set_state (element, GST_STATE_NULL); + + while ((buf = g_async_queue_try_pop (pending_buffers))) + gst_buffer_unref (buf); + + g_async_queue_unref (pending_buffers); + pending_buffers = NULL; +} + +static vorbis_comment vc; +static vorbis_dsp_state vd; +static vorbis_info vi; +static vorbis_block vb; + +static GstBuffer * +_create_codebook_header_buffer (void) +{ + GstBuffer *buffer; + ogg_packet header; + ogg_packet header_comm; + ogg_packet header_code; + + vorbis_info_init (&vi); + vorbis_encode_setup_vbr (&vi, 1, 44000, 0.5); + vorbis_encode_setup_init (&vi); + vorbis_analysis_init (&vd, &vi); + vorbis_block_init (&vd, &vb); + vorbis_comment_init (&vc); + vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code); + + buffer = gst_buffer_new_and_alloc (header_code.bytes); + memcpy (GST_BUFFER_DATA (buffer), header_code.packet, header_code.bytes); + + return buffer; +} + +static GstBuffer * +_create_audio_buffer (void) +{ + GstBuffer *buffer; + ogg_packet packet; + float **vorbis_buffer; + + vorbis_buffer = vorbis_analysis_buffer (&vd, 0); + vorbis_analysis_wrote (&vd, 0); + vorbis_analysis_blockout (&vd, &vb); + vorbis_analysis (&vb, NULL); + vorbis_bitrate_addblock (&vb); + vorbis_bitrate_flushpacket (&vd, &packet); + buffer = gst_buffer_new_and_alloc (packet.bytes); + memcpy (GST_BUFFER_DATA (buffer), packet.packet, packet.bytes); + + vorbis_comment_clear (&vc); + vorbis_block_clear (&vb); + vorbis_dsp_clear (&vd); + vorbis_info_clear (&vi); + + return buffer; +} + + +GST_START_TEST (test_empty_tags_set) +{ + GstTagList *tags; + GstElement *vorbistag; + GstBuffer *inbuffer, *outbuffer; + + vorbistag = setup_vorbistag (); + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL); + gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags, + GST_TAG_MERGE_REPLACE); + gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag), + GST_TAG_MERGE_KEEP_ALL); + gst_tag_list_free (tags); + + start_pipeline (vorbistag); + + /* send identification header */ + inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header)); + memcpy (GST_BUFFER_DATA (inbuffer), identification_header, + sizeof (identification_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send empty comment buffer */ + inbuffer = gst_buffer_new_and_alloc (sizeof (empty_comment_header)); + memcpy (GST_BUFFER_DATA (inbuffer), empty_comment_header, + sizeof (empty_comment_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send minimal codebook header and audio packers */ + inbuffer = _create_codebook_header_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + inbuffer = _create_audio_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + + /* check identification header is unchanged */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (identification_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + identification_header, sizeof (identification_header)), 0); + gst_buffer_unref (outbuffer); + + /* check comment header is correct */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (title_comment_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + title_comment_header, sizeof (title_comment_header)), 0); + gst_buffer_unref (outbuffer); + + stop_pipeline (vorbistag); + cleanup_vorbistag (vorbistag); +} + +GST_END_TEST; + + +GST_START_TEST (test_filled_tags_unset) +{ + GstTagList *tags; + GstElement *vorbistag; + GstBuffer *inbuffer, *outbuffer; + + vorbistag = setup_vorbistag (); + + tags = gst_tag_list_new (); + gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags, + GST_TAG_MERGE_REPLACE); + gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag), + GST_TAG_MERGE_KEEP_ALL); + gst_tag_list_free (tags); + + start_pipeline (vorbistag); + + /* send identification header */ + inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header)); + memcpy (GST_BUFFER_DATA (inbuffer), identification_header, + sizeof (identification_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send empty comment buffer */ + inbuffer = gst_buffer_new_and_alloc (sizeof (title_comment_header)); + memcpy (GST_BUFFER_DATA (inbuffer), title_comment_header, + sizeof (title_comment_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send minimal codebook header and audio packers */ + inbuffer = _create_codebook_header_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + inbuffer = _create_audio_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + + /* check identification header is unchanged */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (identification_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + identification_header, sizeof (identification_header)), 0); + gst_buffer_unref (outbuffer); + + /* check comment header is correct */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (empty_comment_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + empty_comment_header, sizeof (empty_comment_header)), 0); + gst_buffer_unref (outbuffer); + + stop_pipeline (vorbistag); + cleanup_vorbistag (vorbistag); +} + +GST_END_TEST; + + +GST_START_TEST (test_filled_tags_change) +{ + GstTagList *tags; + GstElement *vorbistag; + GstBuffer *inbuffer, *outbuffer; + + vorbistag = setup_vorbistag (); + + tags = gst_tag_list_new (); + gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, "foobar", NULL); + gst_tag_setter_merge_tags (GST_TAG_SETTER (vorbistag), tags, + GST_TAG_MERGE_REPLACE); + gst_tag_setter_set_tag_merge_mode (GST_TAG_SETTER (vorbistag), + GST_TAG_MERGE_KEEP_ALL); + gst_tag_list_free (tags); + + start_pipeline (vorbistag); + + /* send identification header */ + inbuffer = gst_buffer_new_and_alloc (sizeof (identification_header)); + memcpy (GST_BUFFER_DATA (inbuffer), identification_header, + sizeof (identification_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send empty comment buffer */ + inbuffer = gst_buffer_new_and_alloc (sizeof (artist_comment_header)); + memcpy (GST_BUFFER_DATA (inbuffer), artist_comment_header, + sizeof (artist_comment_header)); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + /* send minimal codebook header and audio packers */ + inbuffer = _create_codebook_header_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + inbuffer = _create_audio_buffer (); + fail_unless_equals_int (gst_pad_push (mysrcpad, inbuffer), GST_FLOW_OK); + + + /* check identification header is unchanged */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (identification_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + identification_header, sizeof (identification_header)), 0); + gst_buffer_unref (outbuffer); + + /* check comment header is correct */ + outbuffer = get_buffer (); + fail_unless_equals_int (GST_BUFFER_SIZE (outbuffer), + sizeof (title_comment_header)); + fail_unless_equals_int (memcmp (GST_BUFFER_DATA (outbuffer), + title_comment_header, sizeof (title_comment_header)), 0); + gst_buffer_unref (outbuffer); + + stop_pipeline (vorbistag); + cleanup_vorbistag (vorbistag); +} + +GST_END_TEST; + + + +static Suite * +vorbistag_suite (void) +{ + Suite *s = suite_create ("vorbistag"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_empty_tags_set); + tcase_add_test (tc_chain, test_filled_tags_unset); + tcase_add_test (tc_chain, test_filled_tags_change); + + return s; +} + +GST_CHECK_MAIN (vorbistag) diff --git a/gst-plugins-base-subtitles0.10/tests/check/generic/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/generic/.gitignore new file mode 100644 index 0000000..0d69de1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/generic/.gitignore @@ -0,0 +1,3 @@ +.dirstamp +clock-selection +states diff --git a/gst-plugins-base-subtitles0.10/tests/check/generic/clock-selection.c b/gst-plugins-base-subtitles0.10/tests/check/generic/clock-selection.c new file mode 100644 index 0000000..8e332f8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/generic/clock-selection.c @@ -0,0 +1,72 @@ +/* GStreamer + * + * unit test for clock selection + * + * Copyright (C) <2005> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +GST_START_TEST (test_add) +{ + GstElement *pipeline; + GstStateChangeReturn ret; + + pipeline = gst_pipeline_new ("pipeline"); + fail_unless (pipeline != NULL, "could not create pipeline"); + + ret = gst_element_set_state (pipeline, GST_STATE_READY); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS, "could not set to READY"); + + /* cleanup */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +GST_END_TEST; + +static Suite * +volume_suite (void) +{ + Suite *s = suite_create ("clocks"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_add); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = volume_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/gst-plugins-base-subtitles0.10/tests/check/generic/states.c b/gst-plugins-base-subtitles0.10/tests/check/generic/states.c new file mode 100644 index 0000000..4db8a1b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/generic/states.c @@ -0,0 +1,222 @@ +/* GStreamer + * + * unit test for state changes on all elements + * + * Copyright (C) <2005> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +static GList *elements = NULL; + +static void +setup (void) +{ + GList *features, *f; + GList *plugins, *p; + gchar **ignorelist = NULL; + const gchar *STATE_IGNORE_ELEMENTS = NULL; + + GST_DEBUG ("getting elements for package %s", PACKAGE); + STATE_IGNORE_ELEMENTS = g_getenv ("GST_STATE_IGNORE_ELEMENTS"); + if (!g_getenv ("GST_NO_STATE_IGNORE_ELEMENTS") && STATE_IGNORE_ELEMENTS) { + GST_DEBUG ("Will ignore element factories: '%s'", STATE_IGNORE_ELEMENTS); + ignorelist = g_strsplit (STATE_IGNORE_ELEMENTS, " ", 0); + } + + plugins = gst_registry_get_plugin_list (gst_registry_get_default ()); + + for (p = plugins; p; p = p->next) { + GstPlugin *plugin = p->data; + + if (strcmp (gst_plugin_get_source (plugin), PACKAGE) != 0) + continue; + + features = + gst_registry_get_feature_list_by_plugin (gst_registry_get_default (), + gst_plugin_get_name (plugin)); + + for (f = features; f; f = f->next) { + GstPluginFeature *feature = f->data; + const gchar *name = gst_plugin_feature_get_name (feature); + gboolean ignore = FALSE; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + continue; + + if (ignorelist) { + gchar **s; + + for (s = ignorelist; s && *s; ++s) { + if (g_str_has_prefix (name, *s)) { + GST_DEBUG ("ignoring element %s", name); + ignore = TRUE; + } + } + if (ignore) + continue; + } + + GST_DEBUG ("adding element %s", name); + elements = g_list_prepend (elements, (gpointer) g_strdup (name)); + } + gst_plugin_feature_list_free (features); + } + gst_plugin_list_free (plugins); + g_strfreev (ignorelist); +} + +static void +teardown (void) +{ + GList *e; + + for (e = elements; e; e = e->next) { + g_free (e->data); + } + g_list_free (elements); + elements = NULL; +} + + +GST_START_TEST (test_state_changes_up_and_down_seq) +{ + GstElement *element; + GList *e; + + for (e = elements; e; e = e->next) { + const gchar *name = e->data; + + GST_DEBUG ("testing element %s", name); + element = gst_element_factory_make (name, name); + fail_if (element == NULL, "Could not make element from factory %s", name); + + if (GST_IS_PIPELINE (element)) { + GST_DEBUG ("element %s is a pipeline", name); + } + + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_PLAYING); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_NULL); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_PLAYING); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (element)); + } +} + +GST_END_TEST; + +GST_START_TEST (test_state_changes_up_seq) +{ + GstElement *element; + GList *e; + + for (e = elements; e; e = e->next) { + const gchar *name = e->data; + + GST_DEBUG ("testing element %s", name); + element = gst_element_factory_make (name, name); + fail_if (element == NULL, "Could not make element from factory %s", name); + + if (GST_IS_PIPELINE (element)) { + GST_DEBUG ("element %s is a pipeline", name); + } + + gst_element_set_state (element, GST_STATE_READY); + + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_PLAYING); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (element)); + } +} + +GST_END_TEST; + +GST_START_TEST (test_state_changes_down_seq) +{ + GstElement *element; + GList *e; + + for (e = elements; e; e = e->next) { + const gchar *name = e->data; + + GST_DEBUG ("testing element %s", name); + element = gst_element_factory_make (name, name); + fail_if (element == NULL, "Could not make element from factory %s", name); + + if (GST_IS_PIPELINE (element)) { + GST_DEBUG ("element %s is a pipeline", name); + } + + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_PLAYING); + + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_PLAYING); + + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_PLAYING); + + gst_element_set_state (element, GST_STATE_PAUSED); + gst_element_set_state (element, GST_STATE_READY); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (GST_OBJECT (element)); + } +} + +GST_END_TEST; + + +static Suite * +states_suite (void) +{ + Suite *s = suite_create ("states"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_checked_fixture (tc_chain, setup, teardown); + tcase_add_test (tc_chain, test_state_changes_up_and_down_seq); + tcase_add_test (tc_chain, test_state_changes_up_seq); + tcase_add_test (tc_chain, test_state_changes_down_seq); + + return s; +} + +GST_CHECK_MAIN (states); diff --git a/gst-plugins-base-subtitles0.10/tests/check/gst-plugins-base.supp b/gst-plugins-base-subtitles0.10/tests/check/gst-plugins-base.supp new file mode 100644 index 0000000..0d0705d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/gst-plugins-base.supp @@ -0,0 +1,389 @@ +# A suppression for an old bug in libtheora (fixed in more recent versions, +# but some of our buildslaves still have this) +{ + + Memcheck:Leak + fun:realloc + fun:oggpackB_write + fun:EncodeData + obj:/usr/lib/libtheora.so* + fun:theora_encode_YUVin +} + +# Suppression for pango on ubuntu edgy/x86 and textoverlay test +{ + + Memcheck:Param + access(pathname) + fun:access + fun:pango_config_key_get + fun:pango_find_map +} + +{ + + Memcheck:Leak + fun:realloc + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + fun:g_type_create_instance + fun:g_object_constructor + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + fun:get_default_vfs + fun:g_once_impl + fun:g_vfs_get_default +} + +{ + + Memcheck:Leak + fun:malloc + obj:* + obj:* + obj:* + obj:* + fun:g_type_create_instance + fun:g_object_constructor + fun:g_object_newv + fun:g_object_new_valist + fun:g_object_new + fun:get_default_vfs + fun:g_once_impl + fun:g_vfs_get_default +} + +{ + + Memcheck:Cond + obj:/usr/lib/libasound.so.* + fun:snd_pcm_hw_params_set_buffer_time_near +} + +{ + + Memcheck:Cond + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:snd_pcm_hw_params_set_buffer_time_near +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:gst_alsa_device_property_probe_get_values +} + +{ + + Memcheck:Leak + fun:calloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:snd_config_hook_load + obj:* + obj:/usr/lib/libasound.so.* + fun:snd_config_searcha_hooks + fun:snd_config_searchva_hooks + obj:/usr/lib/libasound.so.* + fun:snd_config_search_definition + obj:/usr/lib/libasound.so.* + fun:gst_alsa_device_property_probe_get_values +} + +{ + + Memcheck:Leak + fun:calloc + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:/usr/lib/libasound.so.* + fun:snd_config_searcha_hooks + fun:snd_config_searchva_hooks + obj:/usr/lib/libasound.so.* + fun:snd_config_search_definition + obj:/usr/lib/libasound.so.* + fun:gst_alsa_device_property_probe_get_values +} + +{ + + Memcheck:Leak + fun:calloc + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:/usr/lib/libasound.so.* + fun:snd_config_searcha_hooks + fun:snd_config_searchva_hooks + obj:/usr/lib/libasound.so.* + fun:snd_config_search_definition + obj:/usr/lib/libasound.so.* + fun:gst_alsa_device_property_probe_get_values +} + +{ + + Memcheck:Leak + fun:calloc + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:* + obj:/usr/lib/libasound.so.* + fun:snd_config_searcha_hooks + fun:snd_config_searchva_hooks + obj:/usr/lib/libasound.so.* + fun:snd_config_search_definition + obj:/usr/lib/libasound.so.* + fun:gst_alsa_device_property_probe_get_values +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:snd_hctl_open + fun:snd_mixer_attach +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_proplist_sets + fun:pa_context_new_with_proplist + fun:pa_context_new + obj:/usr/lib/alsa-lib/libasound_module_pcm_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_pcm_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:snd_config_hook_load + obj:/usr/lib/alsa-lib/libasound_module_ctl_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_proplist_sets + fun:pa_context_new_with_proplist + fun:pa_context_new + obj:/usr/lib/alsa-lib/libasound_module_ctl_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_ctl_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_ctl_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_ctl_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:snd_config_hook_load + obj:/usr/lib/alsa-lib/libasound_module_pcm_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_pcm_pulse.so +} + +{ + + Memcheck:Leak + fun:calloc + fun:pa_xmalloc0 + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + obj:/usr/lib/libpulse.so.* + fun:pa_mainloop_dispatch + obj:/usr/lib/alsa-lib/libasound_module_pcm_pulse.so +} + +{ + + Memcheck:Leak + fun:malloc + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + obj:/usr/lib/libasound.so.* + fun:gst_alsasrc_open +} + +{ + + Memcheck:Leak + fun:*alloc + ... + fun:FcConfigParseAndLoad +} + +{ + + Memcheck:Leak + fun:realloc + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + fun:FcDefaultSubstitute +} + +{ + + Memcheck:Leak + fun:realloc + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + fun:FcConfigSubstituteWithPat +} + +{ + + Memcheck:Leak + fun:realloc + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + obj:/usr/lib/libfontconfig.so.* + fun:FcFontRenderPrepare +} diff --git a/gst-plugins-base-subtitles0.10/tests/check/gst/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/gst/.gitignore new file mode 100644 index 0000000..b469041 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/gst/.gitignore @@ -0,0 +1,2 @@ +typefindfunctions +.dirstamp diff --git a/gst-plugins-base-subtitles0.10/tests/check/gst/typefindfunctions.c b/gst-plugins-base-subtitles0.10/tests/check/gst/typefindfunctions.c new file mode 100644 index 0000000..c53c671 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/gst/typefindfunctions.c @@ -0,0 +1,391 @@ +/* GStreamer unit tests for the -base typefind functions + * + * Copyright (C) 2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +GST_START_TEST (test_quicktime_mpeg4video) +{ + /* quicktime redirect file which starts with what could also be interpreted + * as an MPEG-4 video object layer start code */ + const guint8 qt_redirect_396042[] = + { 0x00, 0x00, 0x01, 0x22, 0x6d, 0x6f, 0x6f, 0x76, 0x00, 0x00, 0x01, 0x1a, + 0x72, 0x6d, 0x72, 0x61, 0x00, 0x00, 0x00, 0x86, 0x72, 0x6d, 0x64, 0x61, + 0x00, 0x00, 0x00, 0x54, 0x72, 0x64, 0x72, 0x66, 0x00, 0x00, 0x00, 0x00, + 0x75, 0x72, 0x6c, 0x20, 0x00, 0x00, 0x00, 0x40, 0x68, 0x74, 0x74, 0x70, + 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x71, 0x74, + 0x76, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6a, 0x61, 0x6e, 0x2f, 0x6a, + 0x34, 0x37, 0x64, 0x35, 0x32, 0x6f, 0x6f, 0x2f, 0x71, 0x74, 0x37, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x2e, 0x6d, 0x6f, 0x76, 0x00, + 0x00, 0x00, 0x00, 0x10, 0x72, 0x6d, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0xf0, 0x00, 0x00, 0x00, 0x1a, 0x72, 0x6d, 0x76, 0x63, + 0x00, 0x00, 0x00, 0x00, 0x71, 0x74, 0x69, 0x6d, 0x06, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x72, 0x6d, + 0x64, 0x61, 0x00, 0x00, 0x00, 0x5a, 0x72, 0x64, 0x72, 0x66, 0x00, 0x00, + 0x00, 0x00, 0x75, 0x72, 0x6c, 0x20, 0x00, 0x00, 0x00, 0x46, 0x68, 0x74, + 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, + 0x71, 0x74, 0x76, 0x2e, 0x61, 0x70, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x6a, 0x61, 0x6e, + 0x2f, 0x6a, 0x34, 0x37, 0x64, 0x35, 0x32, 0x6f, 0x6f, 0x2f, 0x38, 0x38, + 0x34, 0x38, 0x31, 0x32, 0x35, 0x5f, 0x32, 0x5f, 0x33, 0x35, 0x30, 0x5f, + 0x72, 0x65, 0x66, 0x2e, 0x6d, 0x6f, 0x76, 0x00, 0x00, 0x00, 0x00, 0x10, + 0x72, 0x6d, 0x64, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0xf0, + 0x00, 0x00, 0x00, 0x1a, 0x72, 0x6d, 0x76, 0x63, 0x00, 0x00, 0x00, 0x00, + 0x71, 0x74, 0x69, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00 + }; + GstTypeFindProbability prob; + const gchar *type; + GstBuffer *buf; + GstCaps *caps = NULL; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) qt_redirect_396042; + GST_BUFFER_SIZE (buf) = sizeof (qt_redirect_396042); + GST_BUFFER_OFFSET (buf) = 0; + + caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); + fail_unless (caps != NULL); + GST_LOG ("Found type: %" GST_PTR_FORMAT, caps); + + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "video/quicktime"); + fail_unless (prob > GST_TYPE_FIND_MINIMUM && prob <= GST_TYPE_FIND_MAXIMUM); + + gst_buffer_unref (buf); + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_broken_flac_in_ogg) +{ + const guint8 flac_id_packet[4] = { 'f', 'L', 'a', 'C' }; + GstTypeFindProbability prob; + const gchar *type; + GstBuffer *buf; + GstCaps *caps = NULL; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) flac_id_packet; + GST_BUFFER_SIZE (buf) = sizeof (flac_id_packet); + GST_BUFFER_OFFSET (buf) = 0; + + caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); + fail_unless (caps != NULL); + GST_LOG ("Found type: %" GST_PTR_FORMAT, caps); + + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "audio/x-flac"); + fail_unless (prob > GST_TYPE_FIND_MINIMUM && prob <= GST_TYPE_FIND_MAXIMUM); + + gst_buffer_unref (buf); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static GstCaps * +typefind_test_file (const gchar * filename) +{ + GstBuffer *buf; + GError *err = NULL; + GstCaps *caps = NULL; + gchar *path, *data = NULL; + gsize data_len; + + path = g_build_filename (GST_TEST_FILES_PATH, filename, NULL); + GST_LOG ("reading file '%s'", path); + if (!g_file_get_contents (path, &data, &data_len, &err)) { + g_error ("error loading test file: %s", err->message); + } + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) data; + GST_BUFFER_SIZE (buf) = data_len; + GST_BUFFER_OFFSET (buf) = 0; + + caps = gst_type_find_helper_for_buffer (NULL, buf, NULL); + fail_unless (caps != NULL); + GST_LOG ("Found type: %" GST_PTR_FORMAT, caps); + + gst_buffer_unref (buf); + g_free (data); + g_free (path); + + return caps; +} + +GST_START_TEST (test_jpeg_not_ac3) +{ + const gchar *type; + GstCaps *caps = NULL; + + caps = typefind_test_file ("partialframe.mjpeg"); + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "image/jpeg"); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_mpegts) +{ + GstStructure *s; + gboolean systemstream = FALSE; + GstCaps *caps = NULL; + gint packetsize = -1; + + caps = typefind_test_file ("623663.mts"); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_has_name (s, "video/mpegts")); + fail_unless (gst_structure_has_field (s, "systemstream")); + fail_unless (gst_structure_get_boolean (s, "systemstream", &systemstream)); + fail_unless_equals_int (systemstream, TRUE); + fail_unless (gst_structure_has_field (s, "packetsize")); + fail_unless (gst_structure_get_int (s, "packetsize", &packetsize)); + fail_unless_equals_int (packetsize, 192); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +struct ac3_frmsize +{ + unsigned frmsizecod; + unsigned frmsize; +}; + +static void +make_ac3_packet (guint8 * data, guint bytesize, guint bsid) +{ + /* Actually not a fully valid packet; if the typefinder starts to + * check e.g. the CRCs, this test needs to be improved as well. */ + const guint8 ac3_header[] = { + 0x0b, 0x77, /* syncword */ + 0x00, 0x00, /* crc1 */ + 0x00, /* fscod 0xc0, frmsizecod 0x3f */ + 0x00 /* bsid 0xf8, bsmod 0x07 */ + }; + const struct ac3_frmsize frmsize[] = { + {17, 256}, {26, 640} /* small subset of supported sizes */ + }; + guint wordsize = bytesize >> 1, frmsizecod = 0; + int i; + + fail_unless ((bytesize & 0x01) == 0); + fail_unless (bytesize >= sizeof (ac3_header)); + + for (i = 0; i < G_N_ELEMENTS (frmsize); i++) { + if (frmsize[i].frmsize == wordsize) { + frmsizecod = frmsize[i].frmsizecod; + break; + } + } + + fail_unless (frmsizecod); + + memcpy (data, ac3_header, sizeof (ac3_header)); + data[4] = (data[4] & ~0x3f) | (frmsizecod & 0x3f); + data[5] = (bsid & 0x1f) << 3; + memset (data + 6, 0, bytesize - 6); +} + +GST_START_TEST (test_ac3) +{ + GstTypeFindProbability prob; + const gchar *type; + GstBuffer *buf; + GstCaps *caps = NULL; + guint bsid; + + for (bsid = 0; bsid < 32; bsid++) { + buf = gst_buffer_new_and_alloc ((256 + 640) * 2); + make_ac3_packet (GST_BUFFER_DATA (buf), 256 * 2, bsid); + make_ac3_packet (GST_BUFFER_DATA (buf) + 256 * 2, 640 * 2, bsid); + + caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); + if (bsid <= 8) { + fail_unless (caps != NULL); + GST_LOG ("Found type for BSID %u: %" GST_PTR_FORMAT, bsid, caps); + + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "audio/x-ac3"); + fail_unless (prob > GST_TYPE_FIND_MINIMUM + && prob <= GST_TYPE_FIND_MAXIMUM); + gst_caps_unref (caps); + } else { + fail_unless (caps == NULL); + } + + gst_buffer_unref (buf); + } +} + +GST_END_TEST; + +static void +make_eac3_packet (guint8 * data, guint bytesize, guint bsid) +{ + /* Actually not a fully valid packet; if the typefinder starts to + * check e.g. the CRCs, this test needs to be improved as well. */ + const guint8 eac3_header[] = { + 0x0b, 0x77, /* syncword */ + 0x00, /* strmtyp 0xc0, substreamid 0x38, + * frmsize 0x07 (3 high bits) */ + 0x00, /* frmsize (low bits -> 11 total) */ + 0x00, /* fscod 0xc0, fscod2/numblocks 0x30, + * acmod 0x0e, lfeon 0x01 */ + 0x00 /* bsid 0xf8, dialnorm 0x07 (3 high bits) */ + }; + guint wordsize = bytesize >> 1; + + fail_unless ((bytesize & 0x01) == 0); + fail_unless (bytesize >= sizeof (eac3_header)); + + memcpy (data, eac3_header, sizeof (eac3_header)); + data[2] = (data[2] & ~0x07) | ((((wordsize - 1) & 0x700) >> 8) & 0xff); + data[3] = (wordsize - 1) & 0xff; + data[5] = (bsid & 0x1f) << 3; + memset (data + 6, 0, bytesize - 6); +} + +GST_START_TEST (test_eac3) +{ + GstTypeFindProbability prob; + const gchar *type; + GstBuffer *buf; + GstCaps *caps = NULL; + guint bsid; + + for (bsid = 0; bsid <= 32; bsid++) { + buf = gst_buffer_new_and_alloc (558 + 384); + make_eac3_packet (GST_BUFFER_DATA (buf), 558, bsid); + make_eac3_packet (GST_BUFFER_DATA (buf) + 558, 384, bsid); + + caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); + if (bsid > 10 && bsid <= 16) { + /* Only BSIs 11..16 are valid for Annex E */ + fail_unless (caps != NULL); + GST_LOG ("Found type for BSID %u: %" GST_PTR_FORMAT, bsid, caps); + + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "audio/x-eac3"); + fail_unless (prob > GST_TYPE_FIND_MINIMUM + && prob <= GST_TYPE_FIND_MAXIMUM); + gst_caps_unref (caps); + } else { + /* Invalid E-AC-3 BSID, must not be detected as anything: */ + fail_unless (caps == NULL); + } + + gst_buffer_unref (buf); + } +} + +GST_END_TEST; + +#define TEST_RANDOM_DATA_SIZE (4*1024) + +/* typefind random data, to make sure all typefinders are called */ +GST_START_TEST (test_random_data) +{ + GstTypeFindProbability prob; + const gchar *seed_env; + GstBuffer *buf; + GstCaps *caps; + guint32 seed; + guint8 *data; + gint i; + + seed_env = g_getenv ("GST_TYPEFIND_TEST_SEED"); + if (seed_env != NULL) + seed = atoi (seed_env); + else + seed = (guint32) time (NULL); + + g_random_set_seed (seed); + + data = g_malloc (TEST_RANDOM_DATA_SIZE); + for (i = 0; i < TEST_RANDOM_DATA_SIZE; ++i) + data[i] = g_random_int () & 0xff; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) data; + GST_BUFFER_SIZE (buf) = TEST_RANDOM_DATA_SIZE; + GST_BUFFER_OFFSET (buf) = 0; + + caps = gst_type_find_helper_for_buffer (NULL, buf, &prob); + GST_INFO ("caps: %" GST_PTR_FORMAT ", probability=%u", caps, prob); + /* for now we just print an error log message */ + if (caps != NULL /* && prob >= GST_TYPE_FIND_LIKELY */ ) { + GST_ERROR ("typefinder thinks random data is %" GST_PTR_FORMAT ", with a " + "probability of %u (seed was %u)", caps, prob, seed); + gst_caps_unref (caps); + } + + gst_buffer_unref (buf); + g_free (data); +} + +GST_END_TEST; + +GST_START_TEST (test_hls_m3u8) +{ + const gchar *type; + GstCaps *caps = NULL; + + caps = typefind_test_file ("hls.m3u8"); + type = gst_structure_get_name (gst_caps_get_structure (caps, 0)); + fail_unless_equals_string (type, "application/x-hls"); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +static Suite * +typefindfunctions_suite (void) +{ + Suite *s = suite_create ("typefindfunctions"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_quicktime_mpeg4video); + tcase_add_test (tc_chain, test_broken_flac_in_ogg); + tcase_add_test (tc_chain, test_jpeg_not_ac3); + tcase_add_test (tc_chain, test_mpegts); + tcase_add_test (tc_chain, test_ac3); + tcase_add_test (tc_chain, test_eac3); + tcase_add_test (tc_chain, test_random_data); + tcase_add_test (tc_chain, test_hls_m3u8); + + return s; +} + +GST_CHECK_MAIN (typefindfunctions); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/libs/.gitignore new file mode 100644 index 0000000..4972a9a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/.gitignore @@ -0,0 +1,18 @@ +.dirstamp +audio +cddabasesrc +discoverer +fft +gstlibscpp +libsabi +mixer +navigation +netbuffer +pbutils +profile +rtp +rtsp +tag +utils +video +xmpwriter diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/audio.c b/gst-plugins-base-subtitles0.10/tests/check/libs/audio.c new file mode 100644 index 0000000..f5fab57 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/audio.c @@ -0,0 +1,559 @@ +/* GStreamer + * + * unit tests for audio support library + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +static gboolean +structure_contains_channel_positions (const GstStructure * s) +{ + return (gst_structure_get_value (s, "channel-positions") != NULL); +} + +#if 0 +static gboolean +fixed_caps_have_channel_positions (const GstCaps * caps) +{ + GstStructure *s; + + fail_unless (caps != NULL); + + s = gst_caps_get_structure (caps, 0); + fail_unless (s != NULL); + + return structure_contains_channel_positions (s); +} +#endif + +GST_START_TEST (test_multichannel_checks) +{ + GstAudioChannelPosition pos_2_mixed[2] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + GST_AUDIO_CHANNEL_POSITION_NONE + }; + GstAudioChannelPosition pos_2_none[2] = { + GST_AUDIO_CHANNEL_POSITION_NONE, + GST_AUDIO_CHANNEL_POSITION_NONE + }; + GstAudioChannelPosition pos_2_flr[2] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + GstAudioChannelPosition pos_2_frr[2] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT + }; + GstStructure *s; + + s = gst_structure_new ("audio/x-raw-int", "channels", G_TYPE_INT, 2, NULL); + + /* check if the audio channel position checks work */ + fail_if (gst_audio_check_channel_positions (pos_2_mixed, 2)); + fail_unless (gst_audio_check_channel_positions (pos_2_none, 2)); + fail_unless (gst_audio_check_channel_positions (pos_2_flr, 2)); + fail_if (gst_audio_check_channel_positions (pos_2_frr, 2)); + + /* this should not work and issue a warning: FRONT_MONO + NONE */ + _gst_check_expecting_log = TRUE; + gst_audio_set_channel_positions (s, pos_2_mixed); + _gst_check_expecting_log = FALSE; + fail_if (structure_contains_channel_positions (s)); + + /* this should work: NONE + NONE */ + gst_audio_set_channel_positions (s, pos_2_none); + fail_unless (structure_contains_channel_positions (s)); + gst_structure_remove_field (s, "channel-positions"); + + /* this should also work: FRONT_LEFT + FRONT_RIGHT */ + gst_audio_set_channel_positions (s, pos_2_flr); + fail_unless (structure_contains_channel_positions (s)); + gst_structure_remove_field (s, "channel-positions"); + + /* this should not work and issue a warning: FRONT_RIGHT twice */ + _gst_check_expecting_log = TRUE; + gst_audio_set_channel_positions (s, pos_2_frr); + _gst_check_expecting_log = FALSE; + +/* FIXME: did I misunderstand _set_structure_channel_positions_list? */ +#if 0 + /* this should not work and issue a warning: FRONT_RIGHT twice */ + _gst_check_expecting_log = TRUE; + gst_audio_set_structure_channel_positions_list (s, pos_2_frr, 2); + _gst_check_expecting_log = FALSE; + + /* this should not work and issue a warning: FRONT_MONO + NONE */ + _gst_check_expecting_log = TRUE; + gst_audio_set_structure_channel_positions_list (s, pos_2_mixed, 2); + _gst_check_expecting_log = FALSE; + + /* this should not work either (channel count mismatch) */ + _gst_check_expecting_log = TRUE; + gst_audio_set_structure_channel_positions_list (s, pos_2_none, 44); + _gst_check_expecting_log = FALSE; + fail_if (structure_contains_channel_positions (s)); +#endif + + gst_structure_free (s); +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_clipping_time) +{ + GstSegment s; + + GstBuffer *buf; + + GstBuffer *ret; + + guint8 *data; + + /* Clip start and end */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 4 * GST_SECOND, + 8 * GST_SECOND, 4 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 800); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 400); + + gst_buffer_unref (ret); + + /* Clip only start */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 4 * GST_SECOND, + 12 * GST_SECOND, 4 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 1200); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 800); + + gst_buffer_unref (ret); + + /* Clip only stop */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 2 * GST_SECOND, + 10 * GST_SECOND, 2 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 2 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 200); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 1000); + fail_unless (GST_BUFFER_DATA (ret) == data); + fail_unless (GST_BUFFER_SIZE (ret) == 800); + + gst_buffer_unref (ret); + + /* Buffer outside segment */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 12 * GST_SECOND, + 20 * GST_SECOND, 12 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret == NULL); + + /* Clip start and end but don't touch duration and offset_end */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 4 * GST_SECOND, + 8 * GST_SECOND, 4 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == GST_CLOCK_TIME_NONE); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == GST_BUFFER_OFFSET_NONE); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 400); + + gst_buffer_unref (ret); + + /* If the buffer has no timestamp it should assert() + * FIXME: check if return value is the same as the input buffer. + * probably can't be done because the assert() does a SIGABRT. + */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_TIME); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_TIME, 0 * GST_SECOND, + 10 * GST_SECOND, 0 * GST_SECOND); + + GST_BUFFER_TIMESTAMP (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret == buf); + + gst_buffer_unref (buf); + + /* If the format is not TIME or DEFAULT it should assert() + * FIXME: check if return value is the same as the input buffer. + * probably can't be done because the assert() does a SIGABRT. + */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_PERCENT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_PERCENT, 0, 10, 0); + + GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 0; + GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + + ASSERT_CRITICAL (ret = gst_audio_buffer_clip (buf, &s, 100, 1)); + + gst_buffer_unref (buf); + +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_clipping_samples) +{ + GstSegment s; + + GstBuffer *buf; + + GstBuffer *ret; + + guint8 *data; + + /* Clip start and end */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, + 800, 400); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 800); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 400); + + gst_buffer_unref (ret); + + /* Clip only start */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, + 1200, 400); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 1200); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 800); + + gst_buffer_unref (ret); + + /* Clip only stop */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 200, + 1000, 200); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 2 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == 8 * GST_SECOND); + fail_unless (GST_BUFFER_OFFSET (ret) == 200); + fail_unless (GST_BUFFER_OFFSET_END (ret) == 1000); + fail_unless (GST_BUFFER_DATA (ret) == data); + fail_unless (GST_BUFFER_SIZE (ret) == 800); + + gst_buffer_unref (ret); + + /* Buffer outside segment */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 1200, + 2000, 1200); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = 10 * GST_SECOND; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = 1200; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret == NULL); + + /* Clip start and end but don't touch duration and offset_end */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 400, + 800, 400); + + GST_BUFFER_TIMESTAMP (buf) = 2 * GST_SECOND; + GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buf) = 200; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + + ret = gst_audio_buffer_clip (buf, &s, 100, 1); + fail_unless (ret != NULL); + + fail_unless (GST_BUFFER_TIMESTAMP (ret) == 4 * GST_SECOND); + fail_unless (GST_BUFFER_DURATION (ret) == GST_CLOCK_TIME_NONE); + fail_unless (GST_BUFFER_OFFSET (ret) == 400); + fail_unless (GST_BUFFER_OFFSET_END (ret) == GST_BUFFER_OFFSET_NONE); + fail_unless (GST_BUFFER_DATA (ret) == data + 200); + fail_unless (GST_BUFFER_SIZE (ret) == 400); + + gst_buffer_unref (ret); + + /* If the buffer has no offset it should assert() + * FIXME: check if return value is the same as the input buffer. + * probably can't be done because the assert() does a SIGABRT. + */ + buf = gst_buffer_new (); + data = (guint8 *) g_malloc (1000); + GST_BUFFER_SIZE (buf) = 1000; + GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data; + + gst_segment_init (&s, GST_FORMAT_DEFAULT); + gst_segment_set_newsegment (&s, FALSE, 1.0, GST_FORMAT_DEFAULT, 0, 10, 0); + + GST_BUFFER_TIMESTAMP (buf) = 0 * GST_SECOND; + GST_BUFFER_DURATION (buf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE; + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE; + + ASSERT_CRITICAL (ret = gst_audio_buffer_clip (buf, &s, 100, 1)); + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +static void +init_value_to_channel_layout (GValue * val, GstAudioChannelPosition pos1, + GstAudioChannelPosition pos2) +{ + GValue pos = { 0, }; + + g_value_init (val, GST_TYPE_ARRAY); + g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); + g_value_set_enum (&pos, pos1); + gst_value_array_append_value (val, &pos); + g_value_set_enum (&pos, pos2); + gst_value_array_append_value (val, &pos); + g_value_unset (&pos); +} + +GST_START_TEST (test_channel_layout_value_intersect) +{ + GValue layout = { 0, }; + GValue list = { 0, }; + GValue res = { 0, }; + + g_value_init (&list, GST_TYPE_LIST); + init_value_to_channel_layout (&layout, GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT); + gst_value_list_append_value (&list, &layout); + g_value_unset (&layout); + init_value_to_channel_layout (&layout, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT); + gst_value_list_append_value (&list, &layout); + g_value_unset (&layout); + + init_value_to_channel_layout (&layout, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT); + + /* we should get the second layout in the list, as it matches the input */ + fail_unless (gst_value_intersect (&res, &layout, &list)); + g_value_unset (&layout); + fail_unless (GST_VALUE_HOLDS_ARRAY (&res)); + fail_unless_equals_int (gst_value_array_get_size (&res), 2); + fail_unless_equals_int (g_value_get_enum (gst_value_array_get_value (&res, + 0)), GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT); + fail_unless_equals_int (g_value_get_enum (gst_value_array_get_value (&res, + 1)), GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT); + g_value_unset (&res); + + /* this (with rear position) should not yield any results */ + init_value_to_channel_layout (&layout, GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT); + fail_if (gst_value_intersect (&res, &layout, &list)); + g_value_unset (&layout); + + g_value_unset (&list); +} + +GST_END_TEST; + +static Suite * +audio_suite (void) +{ + Suite *s = suite_create ("audio support library"); + + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_multichannel_checks); + tcase_add_test (tc_chain, test_buffer_clipping_time); + tcase_add_test (tc_chain, test_buffer_clipping_samples); + tcase_add_test (tc_chain, test_channel_layout_value_intersect); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = audio_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/gst-plugins-base-subtitles0.10/tests/check/libs/cddabasesrc.c b/gst-plugins-base-subtitles0.10/tests/check/libs/cddabasesrc.c new file mode 100644 index 0000000..8747c9a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/cddabasesrc.c @@ -0,0 +1,515 @@ +/* GStreamer + * + * unit test for cddabasesrc + * + * Copyright (C) <2005> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* TODO: + * - test different modes (when seeking to tracks in track mode, buffer + * timestamps should start from 0, when seeking to tracks in disc mode, + * buffer timestamps should increment, etc.) + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include + +#include +#include + +#define CD_FRAMESIZE_RAW 2352 + +#define GST_TYPE_CD_FOO_SRC (gst_cd_foo_src_get_type()) +#define GST_CD_FOO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CD_FOO_SRC,GstCdFooSrc)) +#define GST_CD_FOO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CD_FOO_SRC,GstCdFooSrcClass)) +#define GST_IS_CD_FOO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CD_FOO_SRC)) +#define GST_IS_CD_FOO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CD_FOO_SRC)) +#define GST_CD_FOO_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CDDA_BASAE_SRC, GstCdFooSrcClass)) + +typedef struct _GstCdFooSrc GstCdFooSrc; +typedef struct _GstCdFooSrcClass GstCdFooSrcClass; + + +/* Neue Heimat (CD 2) */ +static GstCddaBaseSrcTrack nh_cd2_tracks[] = { + {TRUE, 1, 0, 20664, NULL,}, + {TRUE, 2, 20665, 52377, NULL,}, + {TRUE, 3, 52378, 84100, NULL,}, + {TRUE, 4, 84101, 105401, NULL,}, + {TRUE, 5, 105402, 123060, NULL,}, + {TRUE, 6, 123061, 146497, NULL,}, + {TRUE, 7, 146498, 175693, NULL,}, + {TRUE, 8, 175694, 203272, NULL,}, + {TRUE, 9, 203273, 217909, NULL,}, + {TRUE, 10, 217910, 240938, NULL,}, + {TRUE, 11, 240939, 256169, NULL,}, + {TRUE, 12, 256170, 282237, NULL,}, + {TRUE, 13, 282238, 307606, NULL,}, + {TRUE, 14, 307607, 337245, NULL,} +}; + +/* Offspring - Smash */ +static GstCddaBaseSrcTrack offspring_tracks[] = { + {TRUE, 1, 0, 1924, NULL,}, + {TRUE, 2, 1925, 12947, NULL,}, + {TRUE, 3, 12948, 29739, NULL,}, + {TRUE, 4, 29740, 47202, NULL,}, + {TRUE, 5, 47203, 63134, NULL,}, + {TRUE, 6, 63135, 77954, NULL,}, + {TRUE, 7, 77955, 92789, NULL,}, + {TRUE, 8, 92790, 112127, NULL,}, + {TRUE, 9, 112128, 124372, NULL,}, + {TRUE, 10, 124373, 133574, NULL,}, + {TRUE, 11, 133575, 143484, NULL,}, + {TRUE, 12, 143485, 149279, NULL,}, + {TRUE, 13, 149280, 162357, NULL,}, + {TRUE, 14, 162358, 210372, NULL,} +}; + +/* this matches the sample TOC from the DiscIDCalculation + * page in the Musicbrainz wiki. It's a tricky one because + * it's got a data track as well. */ +static GstCddaBaseSrcTrack mb_sample_tracks[] = { + {TRUE, 1, 0, 18640, NULL,}, + {TRUE, 2, 18641, 34666, NULL,}, + {TRUE, 3, 34667, 56349, NULL,}, + {TRUE, 4, 56350, 77005, NULL,}, + {TRUE, 5, 77006, 106093, NULL,}, + {TRUE, 6, 106094, 125728, NULL,}, + {TRUE, 7, 125729, 149784, NULL,}, + {TRUE, 8, 149785, 168884, NULL,}, + {TRUE, 9, 168885, 185909, NULL,}, + {TRUE, 10, 185910, 205828, NULL,}, + {TRUE, 11, 205829, 230141, NULL,}, + {TRUE, 12, 230142, 246658, NULL,}, + {TRUE, 13, 246659, 265613, NULL,}, + {TRUE, 14, 265614, 289478, NULL,}, + {FALSE, 15, 289479, 325731, NULL,} +}; + +/* Nicola Conte - Other Directions (also + * tricky due to the extra data track) */ +static GstCddaBaseSrcTrack nconte_odir_tracks[] = { + {TRUE, 1, 0, 17852, NULL,}, + {TRUE, 2, 17853, 39956, NULL,}, + {TRUE, 3, 39957, 68449, NULL,}, + {TRUE, 4, 68450, 88725, NULL,}, + {TRUE, 5, 88726, 106413, NULL,}, + {TRUE, 6, 106414, 131966, NULL,}, + {TRUE, 7, 131967, 152372, NULL,}, + {TRUE, 8, 152373, 168602, NULL,}, + {TRUE, 9, 168603, 190348, NULL,}, + {TRUE, 10, 190349, 209044, NULL,}, + {TRUE, 11, 209045, 235586, NULL,}, + {TRUE, 12, 235587, 253830, NULL,}, + {TRUE, 13, 253831, 272213, NULL,}, + {FALSE, 14, 272214, 332849, NULL,} +}; + +/* Pink Martini - Sympathique (11 track version) */ +static GstCddaBaseSrcTrack pm_symp_tracks[] = { + {TRUE, 1, 0, 21667, NULL,}, + {TRUE, 2, 21668, 49576, NULL,}, + {TRUE, 3, 49577, 62397, NULL,}, + {TRUE, 4, 62398, 81087, NULL,}, + {TRUE, 5, 81088, 106595, NULL,}, + {TRUE, 6, 106596, 122012, NULL,}, + {TRUE, 7, 122013, 138469, NULL,}, + {TRUE, 8, 138470, 157306, NULL,}, + {TRUE, 9, 157307, 179635, NULL,}, + {TRUE, 10, 179636, 203673, NULL,}, + {TRUE, 11, 203674, 213645, NULL,} +}; + +#define NUM_TEST_DISCS 5 + +struct _test_disc +{ + GstCddaBaseSrcTrack *tracks; + guint num_tracks; + guint32 cddb_discid; + const gchar *musicbrainz_discid; +}; + +/* FIXME: now we just need to find out how to treat + * data tracks for the cddb id calculation .... */ +static struct _test_disc test_discs[NUM_TEST_DISCS] = { + {nh_cd2_tracks, G_N_ELEMENTS (nh_cd2_tracks), 0xae11900e, + NULL}, + {mb_sample_tracks, G_N_ELEMENTS (mb_sample_tracks), 0x00000000, + "MUtMmKN402WPj3_VFsgUelxpc8U-"}, + {offspring_tracks, G_N_ELEMENTS (offspring_tracks), 0xc20af40e, + "ahg7JUcfR3vCYBphSDIogOOWrr0-"}, + {nconte_odir_tracks, G_N_ELEMENTS (nconte_odir_tracks), 0x00000000, + /* hKx_PejjG47X161ND_Sh0HyqaS0- according to libmusicbrainz, but that's + * wrong according to the wiki docs (or not?) (neither discid is listed) */ + "fboaOQtfqwENv8WyXa9tRyvyUbQ-"}, + {pm_symp_tracks, G_N_ELEMENTS (pm_symp_tracks), 0xa00b200b, + "iP0DOLdr4vt_IfKSIXoRUR.q_Wc-"} +}; + +struct _GstCdFooSrc +{ + GstCddaBaseSrc cddabasesrc; + + struct _test_disc *cur_test; + guint cur_disc; +}; + +struct _GstCdFooSrcClass +{ + GstCddaBaseSrcClass parent_class; +}; + +GType gst_cd_foo_src_get_type (void); +GST_BOILERPLATE (GstCdFooSrc, gst_cd_foo_src, GstCddaBaseSrc, + GST_TYPE_CDDA_BASE_SRC); + +static GstBuffer *gst_cd_foo_src_read_sector (GstCddaBaseSrc * src, + gint sector); +static gboolean gst_cd_foo_src_open (GstCddaBaseSrc * src, + const gchar * device); +static void gst_cd_foo_src_close (GstCddaBaseSrc * src); + +static void +gst_cd_foo_src_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, + "CD Audio (cdda) Source, FooBar", "Source/File", + "Read audio from CD", "Foo Bar "); +} + +static void +gst_cd_foo_src_init (GstCdFooSrc * src, GstCdFooSrcClass * klass) +{ + src->cur_disc = 0; +} + +static void +gst_cd_foo_src_class_init (GstCdFooSrcClass * klass) +{ + GstCddaBaseSrcClass *cddabasesrc_class = GST_CDDA_BASE_SRC_CLASS (klass); + + cddabasesrc_class->open = gst_cd_foo_src_open; + cddabasesrc_class->close = gst_cd_foo_src_close; + cddabasesrc_class->read_sector = gst_cd_foo_src_read_sector; +} + +static gboolean +gst_cd_foo_src_open (GstCddaBaseSrc * cddabasesrc, const gchar * device) +{ + GstCddaBaseSrcTrack *tracks; + GstCdFooSrc *src; + gint i; + + src = GST_CD_FOO_SRC (cddabasesrc); + + /* if this fails, the test is wrong */ + g_assert (src->cur_disc < NUM_TEST_DISCS); + + src->cur_test = &test_discs[src->cur_disc]; + + /* add tracks */ + tracks = src->cur_test->tracks; + for (i = 0; i < src->cur_test->num_tracks; ++i) { + gst_cdda_base_src_add_track (GST_CDDA_BASE_SRC (src), &tracks[i]); + } + + return TRUE; +} + +static void +gst_cd_foo_src_close (GstCddaBaseSrc * cddabasesrc) +{ + GstCdFooSrc *src = GST_CD_FOO_SRC (cddabasesrc); + + if (src->cur_test->cddb_discid != 0) { + g_assert (cddabasesrc->discid == src->cur_test->cddb_discid); + } + + if (src->cur_test->musicbrainz_discid != NULL) { + g_assert (g_str_equal (cddabasesrc->mb_discid, + src->cur_test->musicbrainz_discid)); + } +} + +static GstBuffer * +gst_cd_foo_src_read_sector (GstCddaBaseSrc * cddabasesrc, gint sector) +{ + GstBuffer *buf; + + buf = gst_buffer_new_and_alloc (CD_FRAMESIZE_RAW); + memset (GST_BUFFER_DATA (buf), 0, CD_FRAMESIZE_RAW); + + return buf; +} + +static inline gboolean +tag_list_has_tag (GstTagList * list, const gchar * tag, GType type) +{ + const GValue *val = gst_tag_list_get_value_index (list, tag, 0); + + if (val == NULL) { + GST_LOG ("no tag '%s' in taglist %" GST_PTR_FORMAT, tag, list); + return FALSE; + } + + if (!G_VALUE_HOLDS (val, type)) { + GST_LOG ("tag '%s' in taglist %" GST_PTR_FORMAT " is not of type %s", + tag, list, g_type_name (type)); + return FALSE; + } + + return TRUE; +} + +static void +test_uri_parse (const gchar * uri, const gchar * device, gint track) +{ + GstElement *foosrc; + gchar *set_device = NULL; + gint set_track = 0; + + foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc"); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), uri) == TRUE, + "couldn't set uri %s", uri); + g_object_get (foosrc, "device", &set_device, "track", &set_track, NULL); + fail_unless (set_device != NULL); + fail_unless (strcmp (set_device, device) == 0, + "device set was %s, expected %s", set_device, device); + fail_unless (set_track == track, "track set was %d, expected %d", set_track, + track); + g_free (set_device); + gst_object_unref (foosrc); +} + +GST_START_TEST (test_discid_calculations) +{ + GstElement *foosrc, *pipeline, *sink; + gint i; + + fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY, + GST_TYPE_CD_FOO_SRC)); + + pipeline = gst_pipeline_new ("pipeline"); + + sink = gst_element_factory_make ("fakesink", "sink"); + fail_unless (sink != NULL, "couldn't create fakesink"); + + foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc"); + fail_unless (foosrc != NULL, "couldn't create cdfoosrc"); + + gst_bin_add (GST_BIN (pipeline), foosrc); + gst_bin_add (GST_BIN (pipeline), sink); + fail_unless (gst_element_link (foosrc, sink)); + + for (i = 0; i < G_N_ELEMENTS (test_discs); ++i) { + GstTagList *tags = NULL; + GstMessage *msg; + + GST_LOG ("Testing disc layout %u ...", i); + GST_CD_FOO_SRC (foosrc)->cur_disc = i; + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + msg = + gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), + GST_CLOCK_TIME_NONE, GST_MESSAGE_TAG); + gst_message_parse_tag (msg, &tags); + fail_unless (tags != NULL); + fail_unless (tag_list_has_tag (tags, "track-count", G_TYPE_UINT)); + fail_unless (tag_list_has_tag (tags, "track-number", G_TYPE_UINT)); + fail_unless (tag_list_has_tag (tags, "duration", G_TYPE_UINT64)); + fail_unless (tag_list_has_tag (tags, "discid", G_TYPE_STRING)); + fail_unless (tag_list_has_tag (tags, "discid-full", G_TYPE_STRING)); + fail_unless (tag_list_has_tag (tags, "musicbrainz-discid", G_TYPE_STRING)); + fail_unless (tag_list_has_tag (tags, "musicbrainz-discid-full", + G_TYPE_STRING)); + gst_tag_list_free (tags); + gst_message_unref (msg); + + msg = + gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipeline), + GST_CLOCK_TIME_NONE, GST_MESSAGE_ASYNC_DONE); + gst_message_unref (msg); + + gst_element_set_state (pipeline, GST_STATE_NULL); + } + + gst_object_unref (pipeline); + + gst_task_cleanup_all (); +} + +GST_END_TEST; + +GST_START_TEST (test_buffer_timestamps) +{ + GstElement *foosrc, *pipeline, *fakesink; + GstClockTime prev_ts, prev_duration, ts; + GstPad *sinkpad; + gint i; + + fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY, + GST_TYPE_CD_FOO_SRC)); + + pipeline = gst_pipeline_new ("pipeline"); + foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + gst_bin_add_many (GST_BIN (pipeline), foosrc, fakesink, NULL); + fail_unless (gst_element_link (foosrc, fakesink)); + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + + GST_CD_FOO_SRC (foosrc)->cur_disc = 0; + + gst_buffer_straw_start_pipeline (pipeline, sinkpad); + + prev_ts = GST_CLOCK_TIME_NONE; + prev_duration = GST_CLOCK_TIME_NONE; + + for (i = 0; i < 100; ++i) { + GstBuffer *buf; + + buf = gst_buffer_straw_get_buffer (pipeline, sinkpad); + GST_LOG ("buffer, ts=%" GST_TIME_FORMAT ", dur=%" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf))); + ts = GST_BUFFER_TIMESTAMP (buf); + fail_unless (GST_CLOCK_TIME_IS_VALID (ts)); + fail_unless (GST_BUFFER_DURATION_IS_VALID (buf)); + if (i > 0) { + fail_unless (GST_CLOCK_TIME_IS_VALID (prev_ts)); + fail_unless (GST_CLOCK_TIME_IS_VALID (prev_duration)); + fail_unless ((prev_ts + prev_duration) == ts); + } + prev_ts = ts; + prev_duration = GST_BUFFER_DURATION (buf); + gst_buffer_unref (buf); + } + + gst_buffer_straw_stop_pipeline (pipeline, sinkpad); + + gst_task_cleanup_all (); + gst_object_unref (pipeline); + gst_object_unref (sinkpad); +} + +GST_END_TEST; + +GST_START_TEST (test_uri_parsing) +{ + GstElement *foosrc; + + fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY, + GST_TYPE_CD_FOO_SRC)); + + /* wrong protocol */ + foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc"); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "x://") == FALSE); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "cddaq://") == FALSE); + + /* cdda://track */ + test_uri_parse ("cdda://", "/dev/cdrom", 1); + test_uri_parse ("cdda://2", "/dev/cdrom", 2); + test_uri_parse ("cdda://47", "/dev/cdrom", 47); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "cdda://-1") == FALSE); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "cdda://what") == FALSE); + + /* cdda://device#track */ + test_uri_parse ("cdda:///dev/hdb#1", "/dev/hdb", 1); + test_uri_parse ("cdda://anything#8", "anything", 8); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "cdda:///dev/hdb#nonsense") == FALSE); + fail_unless (gst_uri_handler_set_uri (GST_URI_HANDLER (foosrc), + "cdda:///dev/hdb#-2") == FALSE); + + /* cdda://track#device (device should be ignored - FIXME 0.11) */ + test_uri_parse ("cdda://8#/dev/hdb", "/dev/cdrom", 8); + + gst_object_unref (foosrc); +} + +GST_END_TEST; + +GST_START_TEST (test_properties) +{ + GstElement *foosrc; + gchar *device; + guint track; + + fail_unless (gst_element_register (NULL, "cdfoosrc", GST_RANK_SECONDARY, + GST_TYPE_CD_FOO_SRC)); + + foosrc = gst_element_factory_make ("cdfoosrc", "cdfoosrc"); + + g_object_set (foosrc, "device", "/dev/cdrom", NULL); + g_object_get (foosrc, "device", &device, "track", &track, NULL); + fail_unless (g_str_equal (device, "/dev/cdrom")); + fail_unless_equals_int (track, 1); + g_free (device); + + g_object_set (foosrc, "device", "/dev/cdrom1", "track", 17, NULL); + g_object_get (foosrc, "device", &device, "track", &track, NULL); + fail_unless (g_str_equal (device, "/dev/cdrom1")); + fail_unless_equals_int (track, 17); + g_free (device); + + g_object_set (foosrc, "track", 17, "device", "/dev/cdrom1", NULL); + g_object_get (foosrc, "device", &device, "track", &track, NULL); + fail_unless (g_str_equal (device, "/dev/cdrom1")); + fail_unless_equals_int (track, 17); + g_free (device); + + g_object_set (foosrc, "track", 12, NULL); + g_object_get (foosrc, "device", &device, "track", &track, NULL); + fail_unless (g_str_equal (device, "/dev/cdrom1")); + fail_unless_equals_int (track, 12); + g_free (device); + + gst_object_unref (foosrc); +} + +GST_END_TEST; + +static Suite * +cddabasesrc_suite (void) +{ + Suite *s = suite_create ("cddabasesrc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_discid_calculations); + tcase_add_test (tc_chain, test_buffer_timestamps); + tcase_add_test (tc_chain, test_uri_parsing); + tcase_add_test (tc_chain, test_properties); + + return s; +} + +GST_CHECK_MAIN (cddabasesrc) diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/discoverer.c b/gst-plugins-base-subtitles0.10/tests/check/libs/discoverer.c new file mode 100644 index 0000000..2d20576 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/discoverer.c @@ -0,0 +1,94 @@ +/* GStreamer unit tests for discoverer + * + * Copyright (C) 2011 Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +#include +#include +#include + + +GST_START_TEST (test_disco_init) +{ + GError *err = NULL; + GstDiscoverer *dc; + + dc = gst_discoverer_new (GST_SECOND, &err); + fail_unless (dc != NULL); + fail_unless (err == NULL); + + g_object_unref (dc); +} + +GST_END_TEST; + +GST_START_TEST (test_disco_sync) +{ + GError *err = NULL; + GstDiscoverer *dc; + GstDiscovererInfo *info; + GstDiscovererResult result; + gchar *uri; + + dc = gst_discoverer_new (GST_SECOND, &err); + fail_unless (dc != NULL); + fail_unless (err == NULL); + + /* GST_TEST_FILE comes from makefile CFLAGS */ + GST_INFO ("discovering file '%s'", GST_TEST_FILE); + uri = g_filename_to_uri (GST_TEST_FILE, NULL, &err); + fail_unless (err == NULL); + GST_INFO ("discovering uri '%s'", uri); + + info = gst_discoverer_discover_uri (dc, uri, &err); + result = gst_discoverer_info_get_result (info); + GST_INFO ("result: %d", result); + gst_discoverer_info_unref (info); + g_free (uri); + + if (err) { + /* we won't have the codec for the jpeg */ + g_error_free (err); + } + + g_object_unref (dc); +} + +GST_END_TEST; + + +static Suite * +discoverer_suite (void) +{ + Suite *s = suite_create ("discoverer"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_disco_init); + tcase_add_test (tc_chain, test_disco_sync); + return s; +} + +GST_CHECK_MAIN (discoverer); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/fft.c b/gst-plugins-base-subtitles0.10/tests/check/libs/fft.c new file mode 100644 index 0000000..bcaf967 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/fft.c @@ -0,0 +1,563 @@ +/* GStreamer + * + * unit test for FFT library + * + * Copyright (C) 2007 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include +#include +#include + +GST_START_TEST (test_next_fast_length) +{ + fail_unless_equals_int (gst_fft_next_fast_length (13), 16); + fail_unless_equals_int (gst_fft_next_fast_length (30), 30); + fail_unless_equals_int (gst_fft_next_fast_length (31), 32); + fail_unless_equals_int (gst_fft_next_fast_length (1), 2); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_0hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = G_MAXINT16; + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_11025hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0; + in[i + 1] = G_MAXINT16; + in[i + 2] = 0; + in[i + 3] = G_MININT16; + } + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s16_22050hz) +{ + gint i; + gint16 *in; + GstFFTS16Complex *out; + GstFFTS16 *ctx; + + in = g_new (gint16, 2048); + out = g_new (GstFFTS16Complex, 1025); + ctx = gst_fft_s16_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = G_MAXINT16; + in[i + 1] = G_MININT16; + } + + gst_fft_s16_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s16_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 32767.0 * 32767.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -55.0); + } + + gst_fft_s16_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_0hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 2147483647; + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_11025hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0; + in[i + 1] = G_MAXINT32; + in[i + 2] = 0; + in[i + 3] = G_MININT32; + } + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_s32_22050hz) +{ + gint i; + gint32 *in; + GstFFTS32Complex *out; + GstFFTS32 *ctx; + + in = g_new (gint32, 2048); + out = g_new (GstFFTS32Complex, 1025); + ctx = gst_fft_s32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = G_MAXINT32; + in[i + 1] = G_MININT32; + } + + gst_fft_s32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_s32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2147483647.0 * 2147483647.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_s32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_0hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 1.0; + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_11025hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0.0; + in[i + 1] = 1.0; + in[i + 2] = 0.0; + in[i + 3] = -1.0; + } + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f32_22050hz) +{ + gint i; + gfloat *in; + GstFFTF32Complex *out; + GstFFTF32 *ctx; + + in = g_new (gfloat, 2048); + out = g_new (GstFFTF32Complex, 1025); + ctx = gst_fft_f32_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = 1.0; + in[i + 1] = -1.0; + } + + gst_fft_f32_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f32_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f32_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_0hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i++) + in[i] = 1.0; + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i < 2) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_11025hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i += 4) { + in[i] = 0.0; + in[i + 1] = 1.0; + in[i + 2] = 0.0; + in[i + 3] = -1.0; + } + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (abs (512 - i) < 2) + fail_unless (mag > -20.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +GST_START_TEST (test_f64_22050hz) +{ + gint i; + gdouble *in; + GstFFTF64Complex *out; + GstFFTF64 *ctx; + + in = g_new (gdouble, 2048); + out = g_new (GstFFTF64Complex, 1025); + ctx = gst_fft_f64_new (2048, FALSE); + + for (i = 0; i < 2048; i += 2) { + in[i] = 1.0; + in[i + 1] = -1.0; + } + + gst_fft_f64_window (ctx, in, GST_FFT_WINDOW_HAMMING); + gst_fft_f64_fft (ctx, in, out); + + for (i = 0; i < 1025; i++) { + gdouble mag; + + mag = (gdouble) out[i].r * (gdouble) out[i].r; + mag += (gdouble) out[i].i * (gdouble) out[i].i; + mag /= 2048.0 * 2048.0; + mag = 10.0 * log10 (mag); + + if (i > 1022) + fail_unless (mag > -15.0); + else + fail_unless (mag < -60.0); + } + + gst_fft_f64_free (ctx); + g_free (in); + g_free (out); +} + +GST_END_TEST; + +static Suite * +fft_suite (void) +{ + Suite *s = suite_create ("fft library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_next_fast_length); + tcase_add_test (tc_chain, test_s16_0hz); + tcase_add_test (tc_chain, test_s16_11025hz); + tcase_add_test (tc_chain, test_s16_22050hz); + tcase_add_test (tc_chain, test_s32_0hz); + tcase_add_test (tc_chain, test_s32_11025hz); + tcase_add_test (tc_chain, test_s32_22050hz); + tcase_add_test (tc_chain, test_f32_0hz); + tcase_add_test (tc_chain, test_f32_11025hz); + tcase_add_test (tc_chain, test_f32_22050hz); + tcase_add_test (tc_chain, test_f64_0hz); + tcase_add_test (tc_chain, test_f64_11025hz); + tcase_add_test (tc_chain, test_f64_22050hz); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = fft_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/gst-plugins-base-subtitles0.10/tests/check/libs/gstlibscpp.cc b/gst-plugins-base-subtitles0.10/tests/check/libs/gstlibscpp.cc new file mode 100644 index 0000000..aa80624 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/gstlibscpp.cc @@ -0,0 +1,139 @@ +/* GStreamer + * Copyright (C) 2011 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* we mostly just want to make sure that our library headers don't + * contain anything a C++ compiler might not like */ +GST_START_TEST (test_nothing) +{ + gst_init (NULL, NULL); +} + +GST_END_TEST; + +static Suite * +libscpp_suite (void) +{ + Suite *s = suite_create ("GstLibsCpp"); + TCase *tc_chain = tcase_create ("C++ libs header tests"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_nothing); + + return s; +} + +GST_CHECK_MAIN (libscpp); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/libsabi.c b/gst-plugins-base-subtitles0.10/tests/check/libs/libsabi.c new file mode 100644 index 0000000..e2111ba --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/libsabi.c @@ -0,0 +1,122 @@ +/* GStreamer + * Copyright (C) 2005 Wim Taymans + * 2011 Stefan Kost + * + * libsabi.c: Unit test for ABI compatibility + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* initial version of the file was generated using: + * grep -A1 "" ../../docs/libs/gst-plugins-base-libs-decl.txt | \ + * grep "" | grep -v "Private" | sort | \ + * sed -e 's/\(.*\)<\/NAME>/\ {\"\1\", sizeof (\1), 0\},/' + * + * it needs a bit of editing to remove opaque structs + */ + +#ifdef HAVE_CPU_I386 +# ifdef __APPLE__ +# include "struct_i386_osx.h" +# define HAVE_ABI_SIZES TRUE +# else +# include "struct_i386.h" +# define HAVE_ABI_SIZES TRUE +# endif +#else +#ifdef HAVE_CPU_X86_64 +#include "struct_x86_64.h" +#define HAVE_ABI_SIZES TRUE +#else +/* in case someone wants to generate a new arch */ +#include "struct_i386.h" +#define HAVE_ABI_SIZES FALSE +#endif +#endif + +GST_START_TEST (test_ABI) +{ + gst_check_abi_list (list, HAVE_ABI_SIZES); +} + +GST_END_TEST; + +static Suite * +libsabi_suite (void) +{ + Suite *s = suite_create ("LibsABI"); + TCase *tc_chain = tcase_create ("size check"); + + tcase_set_timeout (tc_chain, 0); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_ABI); + return s; +} + +GST_CHECK_MAIN (libsabi); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/mixer.c b/gst-plugins-base-subtitles0.10/tests/check/libs/mixer.c new file mode 100644 index 0000000..2dfd284 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/mixer.c @@ -0,0 +1,243 @@ +/* GStreamer + * + * unit tests for audio support library + * + * Copyright (C) 2007 Jan Schmidt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include + +#define TEST_ELEMENT_TYPE (test_element_get_type()) + +typedef struct TestElement TestElement; +typedef struct TestElementClass TestElementClass; + +struct TestElement +{ + GstElement parent; +}; + +struct TestElementClass +{ + GstElementClass parent_class; +}; + +GType test_element_get_type (void); + +static void init_interface (GType type); +static void gst_implements_interface_init (GstImplementsInterfaceClass * klass); + +GST_BOILERPLATE_FULL (TestElement, test_element, GstElement, GST_TYPE_ELEMENT, + init_interface); + +static void +test_element_mixer_interface_init (GstMixerClass * klass) +{ + /* Not actually implementing any interfaces for this test atm */ +} + +static void +init_interface (GType type) +{ + static const GInterfaceInfo mixer_iface_info = { + (GInterfaceInitFunc) test_element_mixer_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_MIXER, &mixer_iface_info); +} + +static void +test_element_base_init (gpointer klass) +{ +} + +static void +test_element_class_init (TestElementClass * klass) +{ +} + +static gboolean +test_element_interface_supported (GstImplementsInterface * ifacE, + GType interface_type) +{ + if (interface_type == GST_TYPE_MIXER) + return TRUE; + + return FALSE; +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = test_element_interface_supported; +} + +static void +test_element_init (TestElement * this, TestElementClass * klass) +{ +} + +GST_START_TEST (test_messages) +{ + /* Create an empty GstElement that has a GstMixer interface and then + * send some notifications and validate them */ + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstBus *bus = gst_bus_new (); + GstMixerTrack *mtrack = g_object_new (GST_TYPE_MIXER_TRACK, NULL); + GstMixerOptions *mopts = g_object_new (GST_TYPE_MIXER_OPTIONS, NULL); + GstMixerTrack *t; + GstMixerOptions *o; + gint vols_in[2] = { 50, 75 }; + gboolean mute, record; + gint *vols_out; + gint n_chans, i; + const gchar *val; + GstMessage *message; + + mtrack->num_channels = 2; + mtrack->flags = GST_MIXER_TRACK_MUTE | GST_MIXER_TRACK_RECORD; + + gst_element_set_bus (test_element, bus); + + /* Test mute-toggled */ + gst_mixer_mute_toggled (GST_MIXER (test_element), mtrack, TRUE); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_MUTE_TOGGLED); + /* Test that we can pass NULL args */ + gst_mixer_message_parse_mute_toggled (message, NULL, NULL); + /* Test the parsing */ + gst_mixer_message_parse_mute_toggled (message, &t, &mute); + fail_unless (t == mtrack); + fail_unless (mute == TRUE); + gst_message_unref (message); + + /* Test record-toggled */ + gst_mixer_record_toggled (GST_MIXER (test_element), mtrack, TRUE); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_RECORD_TOGGLED); + gst_mixer_message_parse_record_toggled (message, NULL, NULL); + gst_mixer_message_parse_record_toggled (message, &t, &record); + fail_unless (t == mtrack); + fail_unless (record == TRUE); + gst_message_unref (message); + + /* Test volume-changed */ + gst_mixer_volume_changed (GST_MIXER (test_element), mtrack, vols_in); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_VOLUME_CHANGED); + gst_mixer_message_parse_volume_changed (message, NULL, NULL, NULL); + gst_mixer_message_parse_volume_changed (message, NULL, NULL, &n_chans); + fail_unless (n_chans == 2); + gst_mixer_message_parse_volume_changed (message, &t, &vols_out, &n_chans); + fail_unless (mtrack == t); + for (i = 0; i < n_chans; i++) + fail_unless (vols_out[i] == vols_in[i]); + + gst_message_unref (message); + g_free (vols_out); + + /* Test option-changed */ + gst_mixer_option_changed (GST_MIXER (test_element), mopts, "TESTING"); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_OPTION_CHANGED); + gst_mixer_message_parse_option_changed (message, NULL, NULL); + gst_mixer_message_parse_option_changed (message, &o, &val); + fail_unless (o == mopts); + fail_unless (g_str_equal (val, "TESTING")); + gst_message_unref (message); + + /* Test options-list-changed */ + gst_mixer_options_list_changed (GST_MIXER (test_element), mopts); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED); + gst_mixer_message_parse_options_list_changed (message, &o); + fail_unless (o == mopts); + gst_message_unref (message); + + /* Test mixer-changed */ + gst_mixer_mixer_changed (GST_MIXER (test_element)); + message = gst_bus_poll (bus, GST_MESSAGE_ELEMENT, GST_CLOCK_TIME_NONE); + fail_if (message == NULL); + fail_unless (gst_mixer_message_get_type (message) == + GST_MIXER_MESSAGE_MIXER_CHANGED); + gst_message_unref (message); + + gst_object_unref (mtrack); + gst_object_unref (mopts); + gst_object_unref (bus); + gst_object_unref (test_element); +} + +GST_END_TEST; + +static Suite * +mixer_suite (void) +{ + Suite *s = suite_create ("mixer interface"); + TCase *tc_chain = tcase_create ("notifications"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_messages); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = mixer_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/gst-plugins-base-subtitles0.10/tests/check/libs/navigation.c b/gst-plugins-base-subtitles0.10/tests/check/libs/navigation.c new file mode 100644 index 0000000..e3928d1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/navigation.c @@ -0,0 +1,353 @@ +/* GStreamer + * + * unit tests for the navigation interface library + * + * Copyright (C) 2009 Jan Schmidt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include + +#define TEST_ELEMENT_TYPE (test_element_get_type()) + +typedef struct TestElement TestElement; +typedef struct TestElementClass TestElementClass; + +struct TestElement +{ + GstElement parent; + + GstNavigationEventType sent_type; + const gchar *sent_key; + gdouble sent_x, sent_y; + gint sent_button; + GstNavigationCommand sent_command; +}; + +struct TestElementClass +{ + GstElementClass parent_class; +}; + +GType test_element_get_type (void); + +static void init_interface (GType type); +static void gst_implements_interface_init (GstImplementsInterfaceClass * klass); +static void nav_send_event (GstNavigation * navigation, + GstStructure * structure); + +GST_BOILERPLATE_FULL (TestElement, test_element, GstElement, GST_TYPE_ELEMENT, + init_interface); + +static void +test_element_navigation_interface_init (GstNavigationInterface * klass) +{ + klass->send_event = nav_send_event; +} + +static void +init_interface (GType type) +{ + static const GInterfaceInfo navigation_iface_info = { + (GInterfaceInitFunc) test_element_navigation_interface_init, + NULL, + NULL, + }; + static const GInterfaceInfo implements_iface_info = { + (GInterfaceInitFunc) gst_implements_interface_init, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE, + &implements_iface_info); + g_type_add_interface_static (type, GST_TYPE_NAVIGATION, + &navigation_iface_info); +} + +static void +test_element_base_init (gpointer klass) +{ +} + +static void +test_element_class_init (TestElementClass * klass) +{ +} + +static gboolean +test_element_interface_supported (GstImplementsInterface * ifacE, + GType interface_type) +{ + if (interface_type == GST_TYPE_NAVIGATION) + return TRUE; + + return FALSE; +} + +static void +gst_implements_interface_init (GstImplementsInterfaceClass * klass) +{ + klass->supported = test_element_interface_supported; +} + +static void +test_element_init (TestElement * this, TestElementClass * klass) +{ +} + +static void +nav_send_event (GstNavigation * navigation, GstStructure * structure) +{ + GstEvent *event = gst_event_new_navigation (structure); + GstNavigationEventType etype = gst_navigation_event_get_type (event); + TestElement *self = (TestElement *) (navigation); + + fail_if (etype == GST_NAVIGATION_EVENT_INVALID, + "Received navigation event could not be parsed"); + fail_unless (etype == self->sent_type, + "Received navigation event did not match sent"); + + switch (etype) { + case GST_NAVIGATION_EVENT_KEY_PRESS: + case GST_NAVIGATION_EVENT_KEY_RELEASE:{ + const gchar *key; + fail_unless (gst_navigation_event_parse_key_event (event, &key)); + fail_unless (strcmp (key, self->sent_key) == 0); + break; + } + case GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS: + case GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE:{ + gint button; + gdouble x, y; + fail_unless (gst_navigation_event_parse_mouse_button_event (event, + &button, &x, &y)); + fail_unless (button == self->sent_button); + fail_unless (x == self->sent_x); + fail_unless (y == self->sent_y); + break; + } + case GST_NAVIGATION_EVENT_MOUSE_MOVE:{ + gdouble x, y; + fail_unless (gst_navigation_event_parse_mouse_move_event (event, &x, &y)); + fail_unless (x == self->sent_x); + fail_unless (y == self->sent_y); + break; + } + case GST_NAVIGATION_EVENT_COMMAND:{ + GstNavigationCommand cmd; + fail_unless (gst_navigation_event_parse_command (event, &cmd)); + fail_unless (cmd == self->sent_command); + } + default: + break; + } + + gst_event_unref (event); +} + +GST_START_TEST (test_events) +{ + /* Create an empty GstElement that has a GstNavigation interface and then + * send some navigation events and validate them */ + TestElement *test_element = + (TestElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstNavigationCommand cmds[] = { + GST_NAVIGATION_COMMAND_MENU1, GST_NAVIGATION_COMMAND_MENU2, + GST_NAVIGATION_COMMAND_MENU3, GST_NAVIGATION_COMMAND_MENU4, + GST_NAVIGATION_COMMAND_MENU5, GST_NAVIGATION_COMMAND_MENU6, + GST_NAVIGATION_COMMAND_MENU7, GST_NAVIGATION_COMMAND_LEFT, + GST_NAVIGATION_COMMAND_RIGHT, GST_NAVIGATION_COMMAND_UP, + GST_NAVIGATION_COMMAND_DOWN, GST_NAVIGATION_COMMAND_ACTIVATE, + GST_NAVIGATION_COMMAND_PREV_ANGLE, GST_NAVIGATION_COMMAND_NEXT_ANGLE + }; + gint i; + + test_element->sent_type = GST_NAVIGATION_EVENT_KEY_PRESS; + test_element->sent_key = "1"; + gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-press", + "1"); + + test_element->sent_type = GST_NAVIGATION_EVENT_KEY_RELEASE; + test_element->sent_key = "2"; + gst_navigation_send_key_event (GST_NAVIGATION (test_element), "key-release", + "2"); + + test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_MOVE; + test_element->sent_x = 50; + test_element->sent_y = 100; + gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), "mouse-move", + 0, 50, 100); + + test_element->sent_type = GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS; + test_element->sent_x = 10; + test_element->sent_y = 20; + test_element->sent_button = 1; + gst_navigation_send_mouse_event (GST_NAVIGATION (test_element), + "mouse-button-press", 1, 10, 20); + + for (i = 0; i < G_N_ELEMENTS (cmds); i++) { + test_element->sent_type = GST_NAVIGATION_EVENT_COMMAND; + test_element->sent_command = cmds[i]; + gst_navigation_send_command (GST_NAVIGATION (test_element), cmds[i]); + } + + gst_object_unref (test_element); +} + +GST_END_TEST; + +GST_START_TEST (test_messages) +{ + GstMessage *m; + /* GST_NAVIGATION_MESSAGE_MOUSE_OVER */ + { + gboolean active; + m = gst_navigation_message_new_mouse_over (NULL, TRUE); + fail_if (m == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_MOUSE_OVER); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_parse_mouse_over (m, &active)); + fail_unless (active == TRUE); + gst_message_unref (m); + + m = gst_navigation_message_new_mouse_over (NULL, FALSE); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_MOUSE_OVER); + fail_unless (gst_navigation_message_parse_mouse_over (m, &active)); + fail_unless (active == FALSE); + gst_message_unref (m); + } + + /* GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED */ + { + m = gst_navigation_message_new_commands_changed (NULL); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED); + gst_message_unref (m); + } + + /* GST_NAVIGATION_MESSAGE_ANGLES_CHANGED */ + { + guint angle, angles; + m = gst_navigation_message_new_angles_changed (NULL, 1, 5); + fail_if (m == NULL); + fail_unless (GST_MESSAGE_SRC (m) == NULL); + fail_unless (gst_navigation_message_get_type (m) == + GST_NAVIGATION_MESSAGE_ANGLES_CHANGED); + fail_unless (gst_navigation_message_parse_angles_changed (m, &angle, + &angles)); + fail_unless (angle == 1); + fail_unless (angles == 5); + gst_message_unref (m); + } +} + +GST_END_TEST; + +GST_START_TEST (test_queries) +{ + GstQuery *q; + + /* GST_NAVIGATION_QUERY_COMMANDS */ + { + guint n; + GstNavigationCommand cmd; + + q = gst_navigation_query_new_commands (); + fail_unless (q != NULL); + fail_unless (gst_navigation_query_get_type (q) == + GST_NAVIGATION_QUERY_COMMANDS); + gst_navigation_query_set_commands (q, 3, GST_NAVIGATION_COMMAND_LEFT, + GST_NAVIGATION_COMMAND_MENU1, GST_NAVIGATION_COMMAND_MENU5); + fail_unless (gst_navigation_query_parse_commands_length (q, &n)); + fail_unless (n == 3); + fail_unless (gst_navigation_query_parse_commands_nth (q, 1, &cmd)); + fail_unless (cmd == GST_NAVIGATION_COMMAND_MENU1); + + fail_unless (gst_navigation_query_parse_commands_length (q, NULL)); + fail_unless (gst_navigation_query_parse_commands_nth (q, 2, NULL)); + + gst_query_unref (q); + } + + /* GST_NAVIGATION_QUERY_ANGLES */ + { + guint angle, angles; + q = gst_navigation_query_new_angles (); + fail_unless (q != NULL); + fail_unless (gst_navigation_query_get_type (q) == + GST_NAVIGATION_QUERY_ANGLES); + gst_navigation_query_set_angles (q, 4, 8); + fail_unless (gst_navigation_query_parse_angles (q, &angle, &angles)); + fail_unless (angle == 4); + fail_unless (angles == 8); + + fail_unless (gst_navigation_query_parse_angles (q, NULL, &angles)); + fail_unless (gst_navigation_query_parse_angles (q, &angle, NULL)); + fail_unless (gst_navigation_query_parse_angles (q, NULL, NULL)); + + gst_query_unref (q); + } + +} + +GST_END_TEST; + +static Suite * +navigation_suite (void) +{ + Suite *s = suite_create ("navigation interface"); + TCase *tc_chain = tcase_create ("notifications"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_events); + tcase_add_test (tc_chain, test_messages); + tcase_add_test (tc_chain, test_queries); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = navigation_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/gst-plugins-base-subtitles0.10/tests/check/libs/netbuffer.c b/gst-plugins-base-subtitles0.10/tests/check/libs/netbuffer.c new file mode 100644 index 0000000..3236a0f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/netbuffer.c @@ -0,0 +1,96 @@ +/* GStreamer unit tests for libgstnetbuffer + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +#define DATA_STRING "Yoho this is a string" + +GST_START_TEST (test_netbuffer_copy) +{ + GstNetBuffer *netbuf, *copy; + guint8 ipv6_addr[16] = { 0xff, 0x11, 0xee, 0x22, 0xdd, 0x33, 0xcc, + 0x44, 0xbb, 0x55, 0xaa, 0x66, 0x00, 0x77, 0x99, 0x88 + }; + guint8 ipv6_copy[16]; + guint32 ipv4_copy, ipv4_addr = 0xfe12dc34; + guint16 ipv6_port = 3490; + guint16 ipv4_port = 5678; + guint16 port; + + netbuf = gst_netbuffer_new (); + fail_unless (netbuf != NULL, "failed to create net buffer"); + + gst_netaddress_set_ip4_address (&netbuf->from, ipv4_addr, ipv4_port); + gst_netaddress_set_ip6_address (&netbuf->to, ipv6_addr, ipv6_port); + + GST_BUFFER_DATA (netbuf) = (guint8 *) DATA_STRING; + GST_BUFFER_SIZE (netbuf) = strlen (DATA_STRING); + GST_BUFFER_FLAG_SET (netbuf, GST_BUFFER_FLAG_DISCONT); + GST_BUFFER_FLAG_SET (netbuf, GST_BUFFER_FLAG_READONLY); + + copy = (GstNetBuffer *) gst_buffer_copy (GST_BUFFER_CAST (netbuf)); + fail_unless (copy != NULL, "failed to copy net buffer"); + fail_unless (GST_IS_NETBUFFER (copy), "copied buffer is not a GstNetBuffer!"); + + fail_unless_equals_int (GST_MINI_OBJECT_REFCOUNT_VALUE (copy), 1); + + fail_unless_equals_int (GST_BUFFER_SIZE (copy), GST_BUFFER_SIZE (netbuf)); + fail_unless (memcmp (GST_BUFFER_DATA (copy), GST_BUFFER_DATA (netbuf), + GST_BUFFER_SIZE (copy)) == 0); + + fail_if (GST_BUFFER_FLAG_IS_SET (copy, GST_BUFFER_FLAG_READONLY)); + fail_unless (GST_BUFFER_FLAG_IS_SET (copy, GST_BUFFER_FLAG_DISCONT)); + + fail_unless (gst_netaddress_get_ip4_address (©->from, &ipv4_copy, &port)); + fail_unless (ipv4_copy == ipv4_addr, + "Copied buffer has wrong IPV4 from address"); + fail_unless (port == ipv4_port, "Copied buffer has wrong IPV4 from port"); + + fail_unless (gst_netaddress_get_ip6_address (©->to, ipv6_copy, &port)); + fail_unless (memcmp (ipv6_copy, ipv6_addr, 16) == 0, + "Copied buffer has wrong IPv6 destination address"); + fail_unless (port == ipv6_port, + "Copied buffer has wrong IPv6 destination port"); + + gst_buffer_unref (GST_BUFFER_CAST (netbuf)); + gst_buffer_unref (GST_BUFFER_CAST (copy)); +} + +GST_END_TEST; + +static Suite * +netbuffer_suite (void) +{ + Suite *s = suite_create ("netbuffer"); + TCase *tc_chain = tcase_create ("netbuffer"); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_netbuffer_copy); + + return s; +} + +GST_CHECK_MAIN (netbuffer); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/pbutils.c b/gst-plugins-base-subtitles0.10/tests/check/libs/pbutils.c new file mode 100644 index 0000000..144d9a6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/pbutils.c @@ -0,0 +1,750 @@ +/* GStreamer unit tests for libgstpbutils + * + * Copyright (C) 2006 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif + +#include +#include + +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include /* for chmod() and getpid () */ +#endif + +#ifdef HAVE_SYS_STAT_H +#include /* for chmod() */ +#endif + +#ifdef HAVE_UNISTD_H +#include /* for unlink() */ +#endif + +static void +missing_msg_check_getters (GstMessage * msg) +{ + gchar *str; + + str = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (str != NULL); + fail_unless (*str != '\0'); + fail_unless (g_str_has_prefix (str, "gstreamer|")); + g_free (str); + + str = gst_missing_plugin_message_get_description (msg); + fail_unless (str != NULL); + fail_unless (*str != '\0'); + g_free (str); +} + +GST_START_TEST (test_pb_utils_post_missing_messages) +{ + GstElement *pipeline; + GstStructure *s; + GstMessage *msg; + GstCaps *caps; + GstBus *bus; + + gst_pb_utils_init (); + + pipeline = gst_pipeline_new ("pipeline"); + bus = gst_element_get_bus (pipeline); + + /* first, test common assertion failure cases */ + ASSERT_CRITICAL (msg = gst_missing_uri_source_message_new (NULL, "http")); + ASSERT_CRITICAL (gst_missing_uri_source_message_new (pipeline, NULL)); + + ASSERT_CRITICAL (gst_missing_uri_sink_message_new (NULL, "http")); + ASSERT_CRITICAL (gst_missing_uri_sink_message_new (pipeline, NULL)); + + ASSERT_CRITICAL (gst_missing_element_message_new (NULL, "rgbfyltr")); + ASSERT_CRITICAL (gst_missing_element_message_new (pipeline, NULL)); + + caps = gst_caps_new_simple ("audio/x-dontexist", NULL); + + ASSERT_CRITICAL (gst_missing_decoder_message_new (NULL, caps)); + ASSERT_CRITICAL (gst_missing_decoder_message_new (pipeline, NULL)); + + ASSERT_CRITICAL (gst_missing_encoder_message_new (NULL, caps)); + ASSERT_CRITICAL (gst_missing_encoder_message_new (pipeline, NULL)); + + gst_caps_unref (caps); + + /* URI source (with existing protocol) */ + msg = gst_missing_uri_source_message_new (pipeline, "http"); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "http"); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* URI sink (with existing protocol) */ + msg = gst_missing_uri_sink_message_new (pipeline, "smb"); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisink"); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "smb"); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* URI source (with bogus protocol) */ + msg = gst_missing_uri_source_message_new (pipeline, "chchck"); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisource"); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "chchck"); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* URI sink (with bogus protocol) */ + msg = gst_missing_uri_sink_message_new (pipeline, "chchck"); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "urisink"); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "chchck"); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* element */ + msg = gst_missing_element_message_new (pipeline, "foobar"); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "element"); + fail_unless (gst_structure_has_field_typed (s, "detail", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "detail"), "foobar"); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* create bogus caps that don't exist */ + caps = gst_caps_new_simple ("do/x-not", "exist", G_TYPE_BOOLEAN, FALSE, NULL); + + /* decoder (with unknown caps) */ + msg = gst_missing_decoder_message_new (pipeline, caps); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* encoder (with unknown caps) */ + msg = gst_missing_encoder_message_new (pipeline, caps); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "encoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + gst_caps_unref (caps); + + /* create caps that exist */ + caps = gst_caps_new_simple ("video/x-matroska", NULL); + /* decoder (with known caps) */ + msg = gst_missing_decoder_message_new (pipeline, caps); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "decoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + fail_unless (gst_structure_has_field_typed (s, "name", G_TYPE_STRING)); + fail_unless (gst_structure_get_string (s, "name") != NULL); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + /* encoder (with known caps) */ + msg = gst_missing_encoder_message_new (pipeline, caps); + fail_unless (msg != NULL); + fail_unless_equals_int (GST_MESSAGE_TYPE (msg), GST_MESSAGE_ELEMENT); + fail_unless (msg->structure != NULL); + s = msg->structure; + fail_unless (gst_structure_has_name (s, "missing-plugin")); + fail_unless (gst_structure_has_field_typed (s, "type", G_TYPE_STRING)); + fail_unless_equals_string (gst_structure_get_string (s, "type"), "encoder"); + fail_unless (gst_structure_has_field_typed (s, "detail", GST_TYPE_CAPS)); + fail_unless (gst_structure_has_field_typed (s, "name", G_TYPE_STRING)); + fail_unless (gst_structure_get_string (s, "name") != NULL); + missing_msg_check_getters (msg); + gst_message_unref (msg); + + gst_caps_unref (caps); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (bus); +} + +GST_END_TEST; + +GST_START_TEST (test_pb_utils_init) +{ + /* should be fine to call multiple times */ + gst_pb_utils_init (); + gst_pb_utils_init (); + gst_pb_utils_init (); + gst_pb_utils_init (); +} + +GST_END_TEST; + +static const gchar *caps_strings[] = { + /* formats with static descriptions */ + "application/ogg", "application/vnd.rn-realmedia", "video/x-fli", + "video/x-flv", "video/x-matroska", "video/x-ms-asf", "video/x-msvideo", + "video/x-quicktime", "video/quicktime", "audio/x-ac3", "audio/ac3", + "audio/x-private-ac3", "audio/x-private1-ac3", "audio/x-adpcm", + "audio/aiff", "audio/x-alaw", "audio/amr", "audio/AMR", "audio/AMR-WB", + "audio/iLBC-sh", "audio/ms-gsm", "audio/qcelp", "audio/x-adpcm", + "audio/x-aiff", "audio/x-alac", "audio/x-amr-nb-sh", "audio/x-amr-wb-sh", + "audio/x-au", "audio/x-cinepak", "audio/x-dpcm", "audio/x-dts", + "audio/x-dv", "audio/x-flac", "audio/x-gsm", "audio/x-iec958", + "audio/x-iLBC", "audio/x-ircam", "audio/x-lpcm", "audio/x-private1-lpcm", + "audio/x-m4a", "audio/x-mod", "audio/x-mulaw", "audio/x-musepack", + "audio/x-nist", "audio/x-nsf", "audio/x-paris", "audio/x-qdm2", + "audio/x-ralf-mpeg4-generic", "audio/x-sds", "audio/x-shorten", + "audio/x-sid", "audio/x-sipro", "audio/x-spc", "audio/x-speex", + "audio/x-svx", "audio/x-tta", "audio/x-ttafile", + "audio/x-vnd.sony.atrac3", "audio/x-vorbis", "audio/x-voc", "audio/x-w64", + "audio/x-wav", "audio/x-wavpack", "audio/x-wavpack-correction", + "audio/x-wms", "audio/x-voxware", "video/sp5x", "video/vivo", + "video/x-3ivx", "video/x-4xm", "video/x-apple-video", "video/x-camtasia", + "video/x-cdxa", "video/x-cinepak", "video/x-cirrus-logic-accupak", + "video/x-compressed-yuv", "video/x-dirac", "video/x-dvd-subpicture", + "video/x-ffv", "video/x-flash-screen", "video/x-flash-video", + "video/x-h261", "video/x-huffyuv", "video/x-intel-h263", "video/x-jpeg", + "video/x-mjpeg", "video/x-mjpeg-b", "video/mpegts", "video/x-mng", + "video/x-mszh", "video/x-msvideocodec", "video/x-mve", "video/x-nut", + "video/x-nuv", "video/x-qdrw", "video/x-raw-gray", "video/x-smc", + "video/x-smoke", "video/x-tarkin", "video/x-theora", "video/x-rle", + "video/x-ultimotion", "video/x-vcd", "video/x-vmnc", "video/x-vp3", + "video/x-vp5", "video/x-vp6", "video/x-vp6-flash", "video/x-vp7", + "video/x-xvid", "video/x-zlib", "image/bmp", "image/x-bmp", + "image/x-MS-bmp", "image/gif", "image/jpeg", "image/jng", "image/png", + "image/pbm", "image/ppm", "image/svg+xml", "image/tiff", + "image/x-cmu-raster", "image/x-icon", "image/x-xcf", "image/x-pixmap", + "image/x-xpixmap", "image/x-quicktime", "image/x-sun-raster", + "image/x-tga", "video/x-dv", "video/x-dv", + /* some RTP formats */ + "application/x-rtp, media=(string)video, encoding-name=(string)TimVCodec", + "application/x-rtp, media=(string)audio, encoding-name=(string)TimACodec", + "application/x-rtp, media=(string)application, encoding-name=(string)TimMux", + "application/x-rtp, media=(string)woohoo, encoding-name=(string)TPM", + /* incomplete RTP formats */ + "application/x-rtp, media=(string)woohoo", + "application/x-rtp, encoding-name=(string)TPM", + "application/x-rtp, media=(string)woohoo", + /* formats with dynamic descriptions */ + "audio/x-adpcm", + "audio/x-adpcm, layout=(string)dvi", + "audio/x-adpcm, layout=(string)swf", + "audio/x-adpcm, layout=(string)microsoft", + "audio/x-adpcm, layout=(string)quicktime", + "audio/mpeg, mpegversion=(int)4", + "audio/mpeg, mpegversion=(int)1, layer=(int)1", + "audio/mpeg, mpegversion=(int)1, layer=(int)2", + "audio/mpeg, mpegversion=(int)1, layer=(int)3", + "audio/mpeg, mpegversion=(int)1, layer=(int)99", + "audio/mpeg, mpegversion=(int)99", + "video/mpeg, mpegversion=(int)2, systemstream=(boolean)TRUE", + "video/mpeg, systemstream=(boolean)FALSE", + "video/mpeg, mpegversion=(int)2", + "video/mpeg, mpegversion=(int)1, systemstream=(boolean)FALSE", + "video/mpeg, mpegversion=(int)2, systemstream=(boolean)FALSE", + "video/mpeg, mpegversion=(int)4, systemstream=(boolean)FALSE", + "video/mpeg, mpegversion=(int)99, systemstream=(boolean)TRUE", + "video/mpeg, mpegversion=(int)99, systemstream=(boolean)FALSE", + "video/mpeg", + "video/x-indeo, indeoversion=(int)3", + "video/x-indeo, indeoversion=(int)5", + "video/x-indeo", + "video/x-wmv, wmvversion=(int)1", + "video/x-wmv, wmvversion=(int)2", + "video/x-wmv, wmvversion=(int)3", + "video/x-wmv, wmvversion=(int)99", + "video/x-wmv", + "audio/x-wma, wmaversion=(int)1", + "audio/x-wma, wmaversion=(int)2", + "audio/x-wma, wmaversion=(int)3", + "audio/x-wma, wmaversion=(int)99", + "audio/x-wma", + "video/x-divx, divxversion=(int)3", + "video/x-divx, divxversion=(int)4", + "video/x-divx, divxversion=(int)5", + "video/x-divx, divxversion=(int)99", + "video/x-divx", + "video/x-svq, svqversion=(int)1", + "video/x-svq, svqversion=(int)3", + "video/x-svq, svqversion=(int)99", + "video/x-svq", + "video/x-h264, variant=(string)itu", + "video/x-h264, variant=(string)videosoft", + "video/x-h264, variant=(string)foobar", + "video/x-h264", + "video/x-h263, variant=(string)itu", + "video/x-h263, variant=(string)lead", + "video/x-h263, variant=(string)microsoft", + "video/x-h263, variant=(string)vdolive", + "video/x-h263, variant=(string)vivo", + "video/x-h263, variant=(string)xirlink", + "video/x-h263, variant=(string)foobar", + "video/x-h263", + "video/x-msmpeg, msmpegversion=(int)41", + "video/x-msmpeg, msmpegversion=(int)42", + "video/x-msmpeg, msmpegversion=(int)43", + "video/x-msmpeg, msmpegversion=(int)99", + "video/x-msmpeg", + "video/x-pn-realvideo, rmversion=(int)1", + "video/x-pn-realvideo, rmversion=(int)2", + "video/x-pn-realvideo, rmversion=(int)3", + "video/x-pn-realvideo, rmversion=(int)4", + "video/x-pn-realvideo, rmversion=(int)99", + "video/x-pn-realvideo", + "audio/x-pn-realaudio, raversion=(int)1", + "audio/x-pn-realaudio, raversion=(int)2", + "audio/x-pn-realaudio, raversion=(int)99", + "audio/x-pn-realaudio", + "audio/x-mace, maceversion=(int)3", + "audio/x-mace, maceversion=(int)6", + "audio/x-mace, maceversion=(int)99", + "audio/x-mace", + "video/x-truemotion, trueversion=(int)1", + "video/x-truemotion, trueversion=(int)2", + "video/x-truemotion, trueversion=(int)99", + "video/x-truemotion", + "video/x-asus, asusversion=(int)1", + "video/x-asus, asusversion=(int)2", + "video/x-asus, asusversion=(int)99", + "video/x-asus", + "video/x-xan, wcversion=(int)1", + "video/x-xan, wcversion=(int)99", + "video/x-xan", + "video/x-ati-vcr, vcrversion=(int)1", + "video/x-ati-vcr, vcrversion=(int)2", + "video/x-ati-vcr, vcrversion=(int)99", + "video/x-ati-vcr", + /* raw audio */ + "audio/x-raw-int, endianness=(int)1234, signed=(boolean)true, width=(int)16, depth=(int)16, rate=(int)44100, channels=(int)2", + "audio/x-raw-float, rate=(int)22050, channels=(int)2, endianness=(int)1234, width=(int)32", + /* raw video */ + "video/x-raw-rgb, bpp=(int)16, endianness=(int)1234, depth=(int)16, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)320, height=(int)240, framerate=(fraction)30/1, pixel-aspect-ratio=(fraction)1/1", + "video/x-raw-yuv, format=(fourcc)YUY2, width=(int)320, height=(int)240, framerate=(fraction)30/1", + /* and a made-up format */ + "video/x-tpm" +}; + +GST_START_TEST (test_pb_utils_get_codec_description) +{ + gint i; + + gst_pb_utils_init (); + + for (i = 0; i < G_N_ELEMENTS (caps_strings); ++i) { + GstCaps *caps; + gchar *desc; + + caps = gst_caps_from_string (caps_strings[i]); + fail_unless (caps != NULL, "could not create caps from string '%s'", + caps_strings[i]); + GST_LOG ("Caps %s:", caps_strings[i]); + desc = gst_pb_utils_get_codec_description (caps); + fail_unless (desc != NULL); + GST_LOG (" - codec : %s", desc); + g_free (desc); + desc = gst_pb_utils_get_decoder_description (caps); + fail_unless (desc != NULL); + GST_LOG (" - decoder : %s", desc); + g_free (desc); + desc = gst_pb_utils_get_encoder_description (caps); + fail_unless (desc != NULL); + GST_LOG (" - encoder : %s", desc); + g_free (desc); + gst_caps_unref (caps); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_pb_utils_taglist_add_codec_info) +{ + GstTagList *list; + GstCaps *caps; + + gst_pb_utils_init (); + list = gst_tag_list_new (); + caps = gst_caps_new_simple ("video/x-theora", NULL); + ASSERT_CRITICAL (fail_if + (gst_pb_utils_add_codec_description_to_tag_list (NULL, + GST_TAG_VIDEO_CODEC, caps))); + ASSERT_CRITICAL (fail_if + (gst_pb_utils_add_codec_description_to_tag_list (list, NULL, caps))); + ASSERT_CRITICAL (fail_if + (gst_pb_utils_add_codec_description_to_tag_list (list, "asdfa", caps))); + ASSERT_CRITICAL (fail_if + (gst_pb_utils_add_codec_description_to_tag_list (list, + GST_TAG_IMAGE, caps))); + ASSERT_CRITICAL (fail_if + (gst_pb_utils_add_codec_description_to_tag_list (list, + GST_TAG_VIDEO_CODEC, NULL))); + /* FIXME: do something here */ + fail_unless (gst_pb_utils_add_codec_description_to_tag_list (list, + GST_TAG_VIDEO_CODEC, caps)); + fail_if (gst_tag_list_is_empty (list)); + gst_tag_list_free (list); + gst_caps_unref (caps); +} + +GST_END_TEST; + +static gint marker; + +static void +result_cb (GstInstallPluginsReturn result, gpointer user_data) +{ + GST_LOG ("result = %u, user_data = %p", result, user_data); + + fail_unless (user_data == (gpointer) & marker); + + marker = result; +} + +#define SCRIPT_NO_XID \ + "#!/bin/sh\n" \ + "if test x$1 != xdetail1; then exit 21; fi;\n" \ + "if test x$2 != xdetail2; then exit 22; fi;\n" \ + "exit 1\n" + +#define SCRIPT_WITH_XID \ + "#!/bin/sh\n" \ + "if test x$1 != 'x--transient-for=42'; then exit 21; fi;\n" \ + "if test x$2 != xdetail1; then exit 22; fi;\n" \ + "if test x$3 != xdetail2; then exit 23; fi;\n" \ + "exit 0\n" + +/* make sure our script gets called with the right parameters */ +static void +test_pb_utils_install_plugins_do_callout (gchar ** details, + GstInstallPluginsContext * ctx, const gchar * script, + GstInstallPluginsReturn expected_result) +{ +#ifdef G_OS_UNIX + GstInstallPluginsReturn ret; + GError *err = NULL; + gchar *path; + + path = g_strdup_printf ("%s/gst-plugins-base-unit-test-helper.%s.%lu", + g_get_tmp_dir (), (g_get_user_name ())? g_get_user_name () : "nobody", + (gulong) getpid ()); + + if (!g_file_set_contents (path, script, -1, &err)) { + GST_DEBUG ("Failed to write test script to %s: %s", path, err->message); + g_error_free (err); + goto done; + } + + if (chmod (path, S_IRUSR | S_IWUSR | S_IXUSR) != 0) { + GST_DEBUG ("Could not set mode u+rwx on '%s'", path); + goto done; + } + + /* test gst_install_plugins_supported() I */ + g_setenv ("GST_INSTALL_PLUGINS_HELPER", "/i/do/not/ex.ist!", 1); + fail_if (gst_install_plugins_supported ()); + + GST_LOG ("setting GST_INSTALL_PLUGINS_HELPER to '%s'", path); + g_setenv ("GST_INSTALL_PLUGINS_HELPER", path, 1); + + /* test gst_install_plugins_supported() II */ + fail_unless (gst_install_plugins_supported ()); + + /* test sync callout */ + ret = gst_install_plugins_sync (details, ctx); + fail_unless (ret == GST_INSTALL_PLUGINS_HELPER_MISSING || + ret == expected_result, + "gst_install_plugins_sync() failed with unexpected ret %d, which is " + "neither HELPER_MISSING nor %d", ret, expected_result); + + /* test async callout */ + marker = -333; + ret = gst_install_plugins_async (details, ctx, result_cb, + (gpointer) & marker); + fail_unless (ret == GST_INSTALL_PLUGINS_HELPER_MISSING || + ret == GST_INSTALL_PLUGINS_STARTED_OK, + "gst_install_plugins_async() failed with unexpected ret %d", ret); + if (ret == GST_INSTALL_PLUGINS_STARTED_OK) { + while (marker == -333) { + g_usleep (500); + g_main_context_iteration (NULL, FALSE); + } + /* and check that the callback was called with the expected code */ + fail_unless_equals_int (marker, expected_result); + } + +done: + + unlink (path); + g_free (path); +#endif /* G_OS_UNIX */ +} + +GST_START_TEST (test_pb_utils_install_plugins) +{ + GstInstallPluginsContext *ctx; + GstInstallPluginsReturn ret; + gchar *details[] = { (char *) "detail1", (char *) "detail2", NULL }; + gchar *details_multi[] = + { (char *) "detail1", (char *) "detail1", (char *) "detail2", NULL }; + + ctx = gst_install_plugins_context_new (); + + ASSERT_CRITICAL (ret = gst_install_plugins_sync (NULL, ctx)); + ASSERT_CRITICAL (ret = + gst_install_plugins_async (NULL, ctx, result_cb, (gpointer) & marker)); + ASSERT_CRITICAL (ret = + gst_install_plugins_async (details, ctx, NULL, (gpointer) & marker)); + + /* make sure the functions return the right error code if the helper does + * not exist */ + g_setenv ("GST_INSTALL_PLUGINS_HELPER", "/does/not/ex/is.t", 1); + ret = gst_install_plugins_sync (details, NULL); + fail_unless_equals_int (ret, GST_INSTALL_PLUGINS_HELPER_MISSING); + + marker = -333; + ret = + gst_install_plugins_async (details, NULL, result_cb, (gpointer) & marker); + fail_unless_equals_int (ret, GST_INSTALL_PLUGINS_HELPER_MISSING); + /* and check that the callback wasn't called */ + fail_unless_equals_int (marker, -333); + + /* now make sure our scripts are actually called as expected (if possible) */ + test_pb_utils_install_plugins_do_callout (details, NULL, SCRIPT_NO_XID, + GST_INSTALL_PLUGINS_NOT_FOUND); + + /* and again with context */ + gst_install_plugins_context_set_xid (ctx, 42); + test_pb_utils_install_plugins_do_callout (details, ctx, SCRIPT_WITH_XID, + GST_INSTALL_PLUGINS_SUCCESS); + + /* and make sure that duplicate detail strings get dropped */ + test_pb_utils_install_plugins_do_callout (details_multi, NULL, SCRIPT_NO_XID, + GST_INSTALL_PLUGINS_NOT_FOUND); + + /* and the same again with context */ + gst_install_plugins_context_set_xid (ctx, 42); + test_pb_utils_install_plugins_do_callout (details_multi, ctx, SCRIPT_WITH_XID, + GST_INSTALL_PLUGINS_SUCCESS); + + /* and free the context now that we don't need it any longer */ + gst_install_plugins_context_free (ctx); + + /* completely silly test to check gst_install_plugins_return_get_name() + * is somewhat well-behaved */ + { + gint i; + + for (i = -99; i < 16738; ++i) { + const gchar *s; + + s = gst_install_plugins_return_get_name ((GstInstallPluginsReturn) i); + fail_unless (s != NULL); + /* GST_LOG ("%5d = %s", i, s); */ + } + } +} + +GST_END_TEST; + +GST_START_TEST (test_pb_utils_installer_details) +{ + GstMessage *msg; + GstElement *el; + GstCaps *caps; + gchar *detail1, *detail2; + + el = gst_pipeline_new ("dummy-element"); + + /* uri source */ + detail1 = gst_missing_uri_source_installer_detail_new ("http"); + fail_unless (detail1 != NULL); + fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|")); + fail_unless (g_str_has_suffix (detail1, "|urisource-http")); + msg = gst_missing_uri_source_message_new (el, "http"); + fail_unless (msg != NULL); + detail2 = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (detail2 != NULL); + gst_message_unref (msg); + fail_unless_equals_string (detail1, detail2); + g_free (detail1); + g_free (detail2); + + /* uri sink */ + detail1 = gst_missing_uri_sink_installer_detail_new ("http"); + fail_unless (detail1 != NULL); + fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|")); + fail_unless (g_str_has_suffix (detail1, "|urisink-http")); + msg = gst_missing_uri_sink_message_new (el, "http"); + fail_unless (msg != NULL); + detail2 = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (detail2 != NULL); + gst_message_unref (msg); + fail_unless_equals_string (detail1, detail2); + g_free (detail1); + g_free (detail2); + + /* element */ + detail1 = gst_missing_element_installer_detail_new ("deinterlace"); + fail_unless (detail1 != NULL); + fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|")); + fail_unless (g_str_has_suffix (detail1, "|element-deinterlace")); + msg = gst_missing_element_message_new (el, "deinterlace"); + fail_unless (msg != NULL); + detail2 = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (detail2 != NULL); + gst_message_unref (msg); + fail_unless_equals_string (detail1, detail2); + g_free (detail1); + g_free (detail2); + + /* decoder */ + caps = gst_caps_new_simple ("audio/x-spiffy", "spiffyversion", G_TYPE_INT, + 2, "channels", G_TYPE_INT, 6, NULL); + detail1 = gst_missing_decoder_installer_detail_new (caps); + fail_unless (detail1 != NULL); + fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|")); + fail_unless (g_str_has_suffix (detail1, + "|decoder-audio/x-spiffy, spiffyversion=(int)2")); + msg = gst_missing_decoder_message_new (el, caps); + fail_unless (msg != NULL); + detail2 = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (detail2 != NULL); + gst_message_unref (msg); + gst_caps_unref (caps); + fail_unless_equals_string (detail1, detail2); + g_free (detail1); + g_free (detail2); + + /* encoder */ + caps = gst_caps_new_simple ("audio/x-spiffy", "spiffyversion", G_TYPE_INT, + 2, "channels", G_TYPE_INT, 6, NULL); + detail1 = gst_missing_encoder_installer_detail_new (caps); + fail_unless (g_str_has_prefix (detail1, "gstreamer|0.10|")); + fail_unless (g_str_has_suffix (detail1, + "|encoder-audio/x-spiffy, spiffyversion=(int)2")); + fail_unless (detail1 != NULL); + msg = gst_missing_encoder_message_new (el, caps); + fail_unless (msg != NULL); + detail2 = gst_missing_plugin_message_get_installer_detail (msg); + fail_unless (detail2 != NULL); + gst_message_unref (msg); + gst_caps_unref (caps); + fail_unless_equals_string (detail1, detail2); + g_free (detail1); + g_free (detail2); + + gst_object_unref (el); +} + +GST_END_TEST; + +GST_START_TEST (test_pb_utils_versions) +{ + gchar *s; + guint maj, min, mic, nano; + + gst_plugins_base_version (NULL, NULL, NULL, NULL); + gst_plugins_base_version (&maj, &min, &mic, &nano); + fail_unless_equals_int (maj, GST_PLUGINS_BASE_VERSION_MAJOR); + fail_unless_equals_int (min, GST_PLUGINS_BASE_VERSION_MINOR); + fail_unless_equals_int (mic, GST_PLUGINS_BASE_VERSION_MICRO); + fail_unless_equals_int (nano, GST_PLUGINS_BASE_VERSION_NANO); + + s = gst_plugins_base_version_string (); + if (GST_PLUGINS_BASE_VERSION_NANO == 0) { + fail_if (strstr (s, "GIT") || strstr (s, "git") || strstr (s, "prerel")); + } + if (GST_PLUGINS_BASE_VERSION_NANO == 1) { + fail_unless (strstr (s, "GIT") || strstr (s, "git")); + } + if (GST_PLUGINS_BASE_VERSION_NANO >= 2) { + fail_unless (strstr (s, "Prerelease") || strstr (s, "prerelease")); + } + g_free (s); +} + +GST_END_TEST; + +static Suite * +libgstpbutils_suite (void) +{ + Suite *s = suite_create ("pbutils library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_pb_utils_init); + tcase_add_test (tc_chain, test_pb_utils_post_missing_messages); + tcase_add_test (tc_chain, test_pb_utils_taglist_add_codec_info); + tcase_add_test (tc_chain, test_pb_utils_get_codec_description); + tcase_add_test (tc_chain, test_pb_utils_install_plugins); + tcase_add_test (tc_chain, test_pb_utils_installer_details); + tcase_add_test (tc_chain, test_pb_utils_versions); + return s; +} + +GST_CHECK_MAIN (libgstpbutils); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/profile.c b/gst-plugins-base-subtitles0.10/tests/check/libs/profile.c new file mode 100644 index 0000000..285a58e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/profile.c @@ -0,0 +1,621 @@ +/* GStreamer unit test for gstprofile + * + * Copyright (C) <2009> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 */ +#include +#include +#include +#include + +#include +#include + +#define CHECK_PROFILE(profile, name, description, format, preset, presence, restriction) \ + { \ + fail_if(profile == NULL); \ + fail_unless_equals_string (gst_encoding_profile_get_name (profile), name); \ + fail_unless_equals_string (gst_encoding_profile_get_description (profile), description); \ + fail_unless (gst_caps_is_equal (gst_encoding_profile_get_format (profile), format)); \ + fail_unless_equals_string (gst_encoding_profile_get_preset (profile), preset); \ + fail_unless_equals_int (gst_encoding_profile_get_presence (profile), presence); \ + fail_unless (gst_caps_is_equal (gst_encoding_profile_get_restriction (profile), restriction)); \ + } + +GST_START_TEST (test_profile_creation) +{ + GstEncodingProfile *encprof; + GstEncodingAudioProfile *audioprof; + GstEncodingVideoProfile *videoprof; + GstCaps *ogg, *vorbis, *theora; + GstCaps *test1, *test2; + + ogg = gst_caps_new_simple ("application/ogg", NULL); + vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL); + theora = gst_caps_new_simple ("video/x-theora", NULL); + + encprof = (GstEncodingProfile *) gst_encoding_container_profile_new ((gchar *) + "ogg-theora-vorbis", "dumb-profile", ogg, (gchar *) "dumb-preset"); + CHECK_PROFILE (encprof, "ogg-theora-vorbis", "dumb-profile", ogg, + "dumb-preset", 0, NULL); + + audioprof = gst_encoding_audio_profile_new (vorbis, (gchar *) "HQ", NULL, 0); + CHECK_PROFILE ((GstEncodingProfile *) audioprof, NULL, NULL, vorbis, "HQ", 0, + NULL); + + videoprof = gst_encoding_video_profile_new (theora, (gchar *) "HQ", NULL, 0); + CHECK_PROFILE ((GstEncodingProfile *) videoprof, NULL, NULL, theora, "HQ", + 0, NULL); + + fail_unless (gst_encoding_container_profile_add_profile ( + (GstEncodingContainerProfile *) encprof, + (GstEncodingProfile *) audioprof)); + fail_unless (gst_encoding_container_profile_add_profile ( + (GstEncodingContainerProfile *) encprof, + (GstEncodingProfile *) videoprof)); + + /* Test caps */ + test1 = gst_caps_from_string ("video/x-theora; audio/x-vorbis"); + test2 = gst_encoding_profile_get_input_caps (encprof); + fail_unless (gst_caps_is_equal (test1, test2)); + gst_caps_unref (test1); + gst_caps_unref (test2); + + gst_encoding_profile_unref (encprof); + gst_caps_unref (ogg); + gst_caps_unref (theora); + gst_caps_unref (vorbis); +} + +GST_END_TEST; + + +GST_START_TEST (test_profile_input_caps) +{ + GstEncodingProfile *sprof; + GstCaps *vorbis; + GstCaps *out, *restriction, *test1; + + vorbis = gst_caps_new_simple ("audio/x-vorbis", NULL); + + /* Simple case, no restriction */ + sprof = (GstEncodingProfile *) + gst_encoding_audio_profile_new (vorbis, NULL, NULL, 0); + fail_if (sprof == NULL); + + out = gst_encoding_profile_get_input_caps (sprof); + fail_if (out == NULL); + fail_unless (gst_caps_is_equal (out, vorbis)); + gst_caps_unref (out); + gst_encoding_profile_unref (sprof); + + /* One simple restriction */ + restriction = gst_caps_from_string ("audio/x-raw-int,channels=2,rate=44100"); + test1 = gst_caps_from_string ("audio/x-vorbis,channels=2,rate=44100"); + fail_if (restriction == NULL); + + sprof = (GstEncodingProfile *) + gst_encoding_audio_profile_new (vorbis, NULL, restriction, 0); + fail_if (sprof == NULL); + + out = gst_encoding_profile_get_input_caps (sprof); + fail_if (out == NULL); + GST_DEBUG ("got caps %" GST_PTR_FORMAT, out); + fail_unless (gst_caps_is_equal (out, test1)); + gst_caps_unref (out); + gst_caps_unref (restriction); + gst_caps_unref (test1); + gst_encoding_profile_unref (sprof); + + gst_caps_unref (vorbis); +} + +GST_END_TEST; + + +GST_START_TEST (test_target_naming) +{ + GstEncodingTarget *target; + + /* NULL values */ + ASSERT_CRITICAL (target = gst_encoding_target_new (NULL, NULL, NULL, NULL)); + fail_if (target != NULL); + ASSERT_CRITICAL (target = + gst_encoding_target_new ("donkey", NULL, NULL, NULL)); + fail_if (target != NULL); + ASSERT_CRITICAL (target = + gst_encoding_target_new (NULL, "donkey", NULL, NULL)); + fail_if (target != NULL); + ASSERT_CRITICAL (target = + gst_encoding_target_new (NULL, NULL, "donkey", NULL)); + fail_if (target != NULL); + + /* Name and Category validation */ + + /* empty non-NULL strings */ + fail_if (gst_encoding_target_new ("", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "", "description", NULL) != NULL); + + /* don't start with a lower case ASCII character */ + fail_if (gst_encoding_target_new ("A", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("3", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("-", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("!", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new (" ", "valid", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "A", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "3", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "-", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "!", "description", NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", " ", "description", NULL) != NULL); + + /* Starting with anything else is valid */ + target = gst_encoding_target_new ("a", "valid", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + target = gst_encoding_target_new ("z", "valid", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + target = gst_encoding_target_new ("valid", "a", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + target = gst_encoding_target_new ("valid", "z", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + + /* only inner valid characters are lower-case ASCII letters *OR* digits *OR* hyphens */ + fail_if (gst_encoding_target_new ("aA", "valid", "description", + NULL) != NULL); + fail_if (gst_encoding_target_new ("a!", "valid", "description", + NULL) != NULL); + fail_if (gst_encoding_target_new ("space donkeys", "valid", "description", + NULL) != NULL); + fail_if (gst_encoding_target_new ("howaboutùnicode", "valid", "description", + NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "aA", "description", + NULL) != NULL); + fail_if (gst_encoding_target_new ("valid", "a!", "description", + NULL) != NULL); + + target = + gst_encoding_target_new ("donkey-4-ever", "valid", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + target = + gst_encoding_target_new ("valid", "donkey-4-ever", "description", NULL); + fail_if (target == NULL); + gst_encoding_target_unref (target); + +} + +GST_END_TEST; + +static GstEncodingTarget * +create_saveload_target (const gchar * targetname) +{ + GstEncodingTarget *target; + GstEncodingProfile *profile, *sprof; + GstCaps *caps, *caps2; + + GST_DEBUG ("Creating target"); + + target = gst_encoding_target_new (targetname, "herding", + "Plenty of pony glitter profiles", NULL); + caps = gst_caps_from_string ("animal/x-pony"); + profile = + (GstEncodingProfile *) gst_encoding_container_profile_new ("pony", + "I don't want a description !", caps, NULL); + gst_caps_unref (caps); + gst_encoding_target_add_profile (target, profile); + + caps = gst_caps_from_string ("audio/x-pony-song,pretty=True"); + caps2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100"); + sprof = + (GstEncodingProfile *) gst_encoding_audio_profile_new (caps, NULL, caps2, + 1); + gst_encoding_container_profile_add_profile ((GstEncodingContainerProfile *) + profile, sprof); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + caps = gst_caps_from_string ("video/x-glitter,sparkling=True"); + caps2 = + gst_caps_from_string + ("video/x-raw-yuv,width=640,height=480,framerate=15/1"); + sprof = (GstEncodingProfile *) + gst_encoding_video_profile_new (caps, "seriously glittery", caps2, 0); + gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile *) + sprof, TRUE); + gst_encoding_container_profile_add_profile ((GstEncodingContainerProfile *) + profile, sprof); + gst_caps_unref (caps); + gst_caps_unref (caps2); + + return target; +} + +GST_START_TEST (test_target_profile) +{ + GstEncodingTarget *target; + GstEncodingProfile *prof; + + target = create_saveload_target ("myponytarget"); + + /* NULL isn't a valid profile name */ + ASSERT_CRITICAL (gst_encoding_target_get_profile (target, NULL)); + + /* try finding a profile that doesn't exist */ + fail_if (gst_encoding_target_get_profile (target, + "no-really-does-not-exist")); + + /* try finding a profile that exists */ + prof = gst_encoding_target_get_profile (target, "pony"); + fail_if (prof == NULL); + + gst_encoding_profile_unref (prof); + gst_encoding_target_unref (target); +} + +GST_END_TEST; + +GST_START_TEST (test_saving_profile) +{ + GstEncodingTarget *orig, *loaded = NULL; + GstEncodingProfile *proforig, *profloaded; + gchar *profile_file_name; + + /* Create and store a target */ + orig = create_saveload_target ("myponytarget2"); + GST_DEBUG ("Saving target 'myponytarget2'"); + fail_unless (gst_encoding_target_save (orig, NULL)); + + /* Check we can load it */ + profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", "myponytarget2.gep", NULL); + GST_DEBUG ("Loading target from '%s'", profile_file_name); + loaded = gst_encoding_target_load_from_file (profile_file_name, NULL); + fail_unless (loaded != NULL); + g_free (profile_file_name); + + GST_DEBUG ("Checking targets are equal"); + /* Check targets are identical */ + /* 1. at the target level */ + fail_unless_equals_string (gst_encoding_target_get_name (orig), + gst_encoding_target_get_name (loaded)); + fail_unless_equals_string (gst_encoding_target_get_category (orig), + gst_encoding_target_get_category (loaded)); + fail_unless_equals_string (gst_encoding_target_get_description (orig), + gst_encoding_target_get_description (loaded)); + fail_unless_equals_int (g_list_length ((GList *) + gst_encoding_target_get_profiles (loaded)), 1); + + /* 2. at the profile level */ + profloaded = + (GstEncodingProfile *) gst_encoding_target_get_profiles (loaded)->data; + proforig = + (GstEncodingProfile *) gst_encoding_target_get_profiles (orig)->data; + + fail_unless_equals_int (G_TYPE_FROM_INSTANCE (profloaded), + G_TYPE_FROM_INSTANCE (proforig)); + GST_DEBUG ("Comparing loaded:%p to original:%p", profloaded, proforig); + fail_unless (gst_encoding_profile_is_equal (profloaded, proforig)); + + gst_encoding_target_unref (orig); + gst_encoding_target_unref (loaded); +} + +GST_END_TEST; + +static void +test_individual_target (GstEncodingTarget * target) +{ + GstEncodingProfile *prof; + GstCaps *tmpcaps, *tmpcaps2; + GstEncodingProfile *sprof1, *sprof2; + + GST_DEBUG ("Checking the target properties"); + /* Check the target */ + fail_unless_equals_string (gst_encoding_target_get_name (target), + "myponytarget"); + fail_unless_equals_string (gst_encoding_target_get_category (target), + "herding"); + fail_unless_equals_string (gst_encoding_target_get_description (target), + "Plenty of pony glitter profiles"); + + GST_DEBUG ("Checking the number of profiles the target contains"); + fail_unless_equals_int (g_list_length ((GList *) + gst_encoding_target_get_profiles (target)), 1); + + + GST_DEBUG ("Checking the container profile"); + /* Check the profile */ + prof = (GstEncodingProfile *) gst_encoding_target_get_profiles (target)->data; + tmpcaps = gst_caps_from_string ("animal/x-pony"); + CHECK_PROFILE (prof, "pony", "I don't want a description !", tmpcaps, NULL, 0, + 0); + gst_caps_unref (tmpcaps); + + GST_DEBUG ("Checking the container profile has 2 stream profiles"); + /* Check the stream profiles */ + fail_unless_equals_int (g_list_length ((GList *) + gst_encoding_container_profile_get_profiles ( + (GstEncodingContainerProfile *) prof)), 2); + + GST_DEBUG ("Checking the container profile has the audio/x-pony-song stream"); + tmpcaps = gst_caps_from_string ("audio/x-pony-song,pretty=True"); + tmpcaps2 = gst_caps_from_string ("audio/x-raw-int,channels=1,rate=44100"); + sprof1 = + (GstEncodingProfile *) gst_encoding_audio_profile_new (tmpcaps, NULL, + tmpcaps2, 1); + fail_unless (gst_encoding_container_profile_contains_profile ( + (GstEncodingContainerProfile *) prof, sprof1)); + gst_encoding_profile_unref (sprof1); + gst_caps_unref (tmpcaps); + gst_caps_unref (tmpcaps2); + + GST_DEBUG ("Checking the container profile has the video//x-glitter stream"); + tmpcaps = gst_caps_from_string ("video/x-glitter,sparkling=True"); + tmpcaps2 = + gst_caps_from_string + ("video/x-raw-yuv,width=640,height=480,framerate=15/1"); + sprof2 = (GstEncodingProfile *) + gst_encoding_video_profile_new (tmpcaps, "seriously glittery", tmpcaps2, + 0); + gst_encoding_video_profile_set_variableframerate ((GstEncodingVideoProfile *) + sprof2, TRUE); + fail_unless (gst_encoding_container_profile_contains_profile ( + (GstEncodingContainerProfile *) prof, sprof2)); + gst_encoding_profile_unref (sprof2); + gst_caps_unref (tmpcaps); + gst_caps_unref (tmpcaps2); +} + +GST_START_TEST (test_loading_profile) +{ + GstEncodingTarget *target; + gchar *profile_file_name; + GstEncodingProfile *profile; + GstCaps *tmpcaps; + GValue strvalue = { 0, }; + GValue miniobjectvalue = { 0, }; + + /* Test loading using short method and all arguments */ + target = gst_encoding_target_load ("myponytarget", "herding", NULL); + fail_unless (target != NULL); + test_individual_target (target); + gst_encoding_target_unref (target); + + /* Test loading using short method and no category */ + target = gst_encoding_target_load ("myponytarget", NULL, NULL); + fail_unless (target != NULL); + test_individual_target (target); + gst_encoding_target_unref (target); + + /* Test loading using fully specified path */ + profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", "myponytarget.gep", NULL); + + GST_DEBUG ("Loading target from '%s'", profile_file_name); + target = gst_encoding_target_load_from_file (profile_file_name, NULL); + g_free (profile_file_name); + fail_unless (target != NULL); + test_individual_target (target); + gst_encoding_target_unref (target); + + /* Test getting the profiles directly + * First without category */ + profile = gst_encoding_profile_find ("myponytarget", "pony", NULL); + fail_unless (profile != NULL); + tmpcaps = gst_caps_from_string ("animal/x-pony"); + CHECK_PROFILE (profile, "pony", "I don't want a description !", tmpcaps, NULL, + 0, 0); + gst_caps_unref (tmpcaps); + gst_encoding_profile_unref (profile); + + /* Then with a specific category */ + profile = gst_encoding_profile_find ("myponytarget", "pony", "herding"); + fail_unless (profile != NULL); + tmpcaps = gst_caps_from_string ("animal/x-pony"); + CHECK_PROFILE (profile, "pony", "I don't want a description !", tmpcaps, NULL, + 0, 0); + gst_caps_unref (tmpcaps); + gst_encoding_profile_unref (profile); + + /* For my next trick, I will need the assistance of a GValue */ + g_value_init (&strvalue, G_TYPE_STRING); + g_value_init (&miniobjectvalue, GST_TYPE_ENCODING_PROFILE); + g_value_set_static_string (&strvalue, "myponytarget/pony"); + fail_unless (g_value_transform (&strvalue, &miniobjectvalue)); + profile = (GstEncodingProfile *) gst_value_dup_mini_object (&miniobjectvalue); + fail_if (profile == NULL); + g_value_unset (&strvalue); + g_value_unset (&miniobjectvalue); + tmpcaps = gst_caps_from_string ("animal/x-pony"); + CHECK_PROFILE (profile, "pony", "I don't want a description !", tmpcaps, NULL, + 0, 0); + gst_caps_unref (tmpcaps); + gst_encoding_profile_unref (profile); + + /* Let's go crazy for error detection */ + fail_if (gst_encoding_profile_find ("myponytarget", "whales", NULL)); + fail_if (gst_encoding_profile_find ("myponytarget", "whales", "herding")); + fail_if (gst_encoding_profile_find ("myponytarget", "", NULL)); + fail_if (gst_encoding_profile_find ("", "pony", NULL)); +} + +GST_END_TEST; + +GST_START_TEST (test_target_list) +{ + GList *categories; + GList *targets; + GList *tmp; + + /* Make sure we get our test category in the available categories */ + categories = gst_encoding_list_available_categories (); + fail_if (categories == NULL); + fail_if (g_list_find_custom (categories, "herding", + (GCompareFunc) g_strcmp0) == NULL); + g_list_foreach (categories, (GFunc) g_free, NULL); + g_list_free (categories); + + /* Try getting all available targets with a specified category */ + targets = gst_encoding_list_all_targets ("herding"); + fail_if (targets == NULL); + for (tmp = targets; tmp; tmp = tmp->next) { + GstEncodingTarget *target = (GstEncodingTarget *) tmp->data; + if (!g_strcmp0 (gst_encoding_target_get_name (target), "myponytarget")) + break; + } + /* If tmp is NULL, it means we iterated the whole list without finding + * our target */ + fail_if (tmp == NULL); + g_list_foreach (targets, (GFunc) gst_mini_object_unref, NULL); + g_list_free (targets); + + /* Try getting all available targets without a specified category */ + targets = gst_encoding_list_all_targets (NULL); + fail_if (targets == NULL); + for (tmp = targets; tmp; tmp = tmp->next) { + GstEncodingTarget *target = (GstEncodingTarget *) tmp->data; + if (!g_strcmp0 (gst_encoding_target_get_name (target), "myponytarget")) + break; + } + /* If tmp is NULL, it means we iterated the whole list without finding + * our target */ + fail_if (tmp == NULL); + g_list_foreach (targets, (GFunc) gst_mini_object_unref, NULL); + g_list_free (targets); +} + +GST_END_TEST; + + +static const gchar *profile_string = "\ +[GStreamer Encoding Target]\n\ +name=myponytarget\n\ +category=herding\n\ +description=Plenty of pony glitter profiles\n\ +\n\ +[profile-pony1]\n\ +name=pony\n\ +type=container\n\ +description=I don't want a description !\n\ +format=animal/x-pony\n\ +\n\ +[streamprofile-pony11]\n\ +parent=pony\n\ +type=audio\n\ +format=audio/x-pony-song,pretty=True\n\ +restriction=audio/x-raw-int,channels=1,rate=44100\n\ +presence=1\n\ +\n\ +[streamprofile-pony12]\n\ +parent=pony\n\ +type=video\n\ +preset=seriously glittery\n\ +format=video/x-glitter,sparkling=True\n\ +restriction=video/x-raw-yuv,width=640,height=480,framerate=15/1\n\ +presence=0\n\ +variableframerate=true\n\ +"; + +static void +remove_profile_file (void) +{ + gchar *profile_file_name; + + profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", "myponytarget.gep", NULL); + g_unlink (profile_file_name); + g_free (profile_file_name); + profile_file_name = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", "myponytarget2.gep", NULL); + g_unlink (profile_file_name); + g_free (profile_file_name); +} + +static void +create_profile_file (void) +{ + gchar *profile_file_name; + gchar *profile_dir; + GError *error = NULL; + + profile_dir = + g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", NULL); + profile_file_name = + g_build_filename (g_get_home_dir (), ".gstreamer-0.10", + "encoding-profiles", "herding", "myponytarget.gep", NULL); + g_mkdir_with_parents (profile_dir, S_IRUSR | S_IWUSR | S_IXUSR); + if (!g_file_set_contents (profile_file_name, profile_string, + strlen (profile_string), &error)) + GST_WARNING ("Couldn't write contents to file : %s", error->message); + g_free (profile_dir); + g_free (profile_file_name); +} + +static void +test_setup (void) +{ + create_profile_file (); +} + +static void +test_teardown (void) +{ + remove_profile_file (); +} + + +static Suite * +profile_suite (void) +{ + Suite *s = suite_create ("profile support library"); + TCase *tc_chain = tcase_create ("general"); + gboolean can_write; + gchar *gst_dir; + + /* cehck if we can create profiles */ + gst_dir = g_build_filename (g_get_home_dir (), ".gstreamer-0.10", NULL); + can_write = (g_access (gst_dir, R_OK | W_OK | X_OK) == 0); + g_free (gst_dir); + + suite_add_tcase (s, tc_chain); + + tcase_add_test (tc_chain, test_profile_creation); + tcase_add_test (tc_chain, test_profile_input_caps); + tcase_add_test (tc_chain, test_target_naming); + tcase_add_test (tc_chain, test_target_profile); + if (can_write) { + tcase_add_test (tc_chain, test_loading_profile); + tcase_add_test (tc_chain, test_saving_profile); + tcase_add_test (tc_chain, test_target_list); + } + + tcase_add_unchecked_fixture (tc_chain, test_setup, test_teardown); + + return s; +} + +GST_CHECK_MAIN (profile); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/rtp.c b/gst-plugins-base-subtitles0.10/tests/check/libs/rtp.c new file mode 100644 index 0000000..defd6b6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/rtp.c @@ -0,0 +1,767 @@ +/* GStreamer unit tests for the RTP support library + * + * Copyright (C) 2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +#define RTP_HEADER_LEN 12 + +GST_START_TEST (test_rtp_buffer) +{ + GstBuffer *buf; + guint8 *data; + + /* check GstRTPHeader structure alignment and packing */ + buf = gst_rtp_buffer_new_allocate (16, 4, 0); + fail_unless (buf != NULL); + fail_unless_equals_int (GST_BUFFER_SIZE (buf), RTP_HEADER_LEN + 16 + 4); + data = GST_BUFFER_DATA (buf); + + /* check defaults */ + fail_unless_equals_int (gst_rtp_buffer_get_version (buf), 2); + fail_unless (gst_rtp_buffer_get_padding (buf) == FALSE); + fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE); + fail_unless_equals_int (gst_rtp_buffer_get_csrc_count (buf), 0); + fail_unless (gst_rtp_buffer_get_marker (buf) == FALSE); + fail_unless (gst_rtp_buffer_get_payload_type (buf) == 0); + fail_unless_equals_int (GST_READ_UINT16_BE (data), 0x8000); + + /* check version in bitfield */ + gst_rtp_buffer_set_version (buf, 3); + fail_unless_equals_int (gst_rtp_buffer_get_version (buf), 3); + fail_unless_equals_int ((data[0] & 0xC0) >> 6, 3); + gst_rtp_buffer_set_version (buf, 2); + fail_unless_equals_int (gst_rtp_buffer_get_version (buf), 2); + fail_unless_equals_int ((data[0] & 0xC0) >> 6, 2); + + /* check padding bit */ + gst_rtp_buffer_set_padding (buf, TRUE); + fail_unless (gst_rtp_buffer_get_padding (buf) == TRUE); + fail_unless_equals_int ((data[0] & 0x20) >> 5, 1); + gst_rtp_buffer_set_padding (buf, FALSE); + fail_unless (gst_rtp_buffer_get_padding (buf) == FALSE); + fail_unless_equals_int ((data[0] & 0x20) >> 5, 0); + + /* check marker bit */ + gst_rtp_buffer_set_marker (buf, TRUE); + fail_unless (gst_rtp_buffer_get_marker (buf) == TRUE); + fail_unless_equals_int ((data[1] & 0x80) >> 7, 1); + gst_rtp_buffer_set_marker (buf, FALSE); + fail_unless (gst_rtp_buffer_get_marker (buf) == FALSE); + fail_unless_equals_int ((data[1] & 0x80) >> 7, 0); + + /* check sequence offset */ + gst_rtp_buffer_set_seq (buf, 0xF2C9); + fail_unless_equals_int (gst_rtp_buffer_get_seq (buf), 0xF2C9); + fail_unless_equals_int (GST_READ_UINT16_BE (data + 2), 0xF2C9); + gst_rtp_buffer_set_seq (buf, 0); + fail_unless_equals_int (gst_rtp_buffer_get_seq (buf), 0); + fail_unless_equals_int (GST_READ_UINT16_BE (data + 2), 0); + + /* check timestamp offset */ + gst_rtp_buffer_set_timestamp (buf, 432191); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 4), 432191); + fail_unless_equals_int (gst_rtp_buffer_get_timestamp (buf), 432191); + gst_rtp_buffer_set_timestamp (buf, 0); + fail_unless_equals_int (gst_rtp_buffer_get_timestamp (buf), 0); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 4), 0); + + /* check ssrc offset */ + gst_rtp_buffer_set_ssrc (buf, 0xf04043C2); + fail_unless_equals_int (gst_rtp_buffer_get_ssrc (buf), (gint) 0xf04043c2); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 4 + 4), (gint) 0xf04043c2); + gst_rtp_buffer_set_ssrc (buf, 0); + fail_unless_equals_int (gst_rtp_buffer_get_ssrc (buf), 0); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 4 + 4), 0); + + /* check csrc bits */ + fail_unless_equals_int (gst_rtp_buffer_get_csrc_count (buf), 0); + ASSERT_CRITICAL (gst_rtp_buffer_get_csrc (buf, 0)); + fail_unless_equals_int (data[0] & 0xf, 0); + gst_buffer_unref (buf); + + /* and again, this time with CSRCs */ + buf = gst_rtp_buffer_new_allocate (16, 4, 3); + fail_unless (buf != NULL); + fail_unless_equals_int (GST_BUFFER_SIZE (buf), + RTP_HEADER_LEN + 16 + 4 + 4 * 3); + + data = GST_BUFFER_DATA (buf); + + fail_unless_equals_int (gst_rtp_buffer_get_csrc_count (buf), 3); + ASSERT_CRITICAL (gst_rtp_buffer_get_csrc (buf, 3)); + fail_unless_equals_int (data[0] & 0xf, 3); + fail_unless_equals_int (gst_rtp_buffer_get_csrc (buf, 0), 0); + fail_unless_equals_int (gst_rtp_buffer_get_csrc (buf, 1), 0); + fail_unless_equals_int (gst_rtp_buffer_get_csrc (buf, 2), 0); + + data += RTP_HEADER_LEN; /* skip the other header stuff */ + gst_rtp_buffer_set_csrc (buf, 0, 0xf7c0); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 0 * 4), 0xf7c0); + gst_rtp_buffer_set_csrc (buf, 1, 0xf7c1); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 1 * 4), 0xf7c1); + gst_rtp_buffer_set_csrc (buf, 2, 0xf7c2); + fail_unless_equals_int (GST_READ_UINT32_BE (data + 2 * 4), 0xf7c2); + ASSERT_CRITICAL (gst_rtp_buffer_set_csrc (buf, 3, 0xf123)); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_rtp_buffer_validate_corrupt) +{ + GstBuffer *buf; + guint8 corrupt_rtp_packet[58] = { + 0x90, 0x7a, 0xbf, 0x28, 0x3a, 0x8a, 0x0a, 0xf4, 0x69, 0x6b, 0x76, 0xc0, + 0x21, 0xe0, 0xe0, 0x60, 0x81, 0x10, 0x84, 0x30, 0x21, 0x52, 0x06, 0xc2, + 0xb8, 0x30, 0x10, 0x4c, 0x08, 0x62, 0x67, 0xc2, 0x6e, 0x1a, 0x53, 0x3f, + 0xaf, 0xd6, 0x1b, 0x29, 0x40, 0xe0, 0xa5, 0x83, 0x01, 0x4b, 0x04, 0x02, + 0xb0, 0x97, 0x63, 0x08, 0x10, 0x4b, 0x43, 0x85, 0x37, 0x2c + }; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = corrupt_rtp_packet; + GST_BUFFER_SIZE (buf) = sizeof (corrupt_rtp_packet); + fail_if (gst_rtp_buffer_validate (buf)); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_rtp_buffer_list) +{ + GstBuffer *rtp_header; + GstBuffer *rtp_payload; + GstBufferList *list = NULL; + GstBufferListIterator *it; + guint i; + + list = gst_buffer_list_new (); + it = gst_buffer_list_iterate (list); + + /* Creating a list of two RTP packages */ + + /* Create first group to hold the rtp header and the payload */ + gst_buffer_list_iterator_add_group (it); + rtp_header = gst_rtp_buffer_new_allocate (0, 0, 0); + gst_buffer_list_iterator_add (it, rtp_header); + rtp_payload = gst_buffer_new_and_alloc (42); + gst_buffer_list_iterator_add (it, rtp_payload); + + /* Create second group to hold an rtp header and a payload */ + gst_buffer_list_iterator_add_group (it); + rtp_header = gst_rtp_buffer_new_allocate (0, 0, 0); + gst_buffer_list_iterator_add (it, rtp_header); + rtp_payload = gst_buffer_new_and_alloc (42); + gst_buffer_list_iterator_add (it, rtp_payload); + + gst_buffer_list_iterator_free (it); + + /* Test SEQ number */ + i = gst_rtp_buffer_list_set_seq (list, 1024); + fail_if (1026 != i); + fail_if (!gst_rtp_buffer_list_validate (list)); + + /* Timestamp */ + gst_rtp_buffer_list_set_timestamp (list, 432191); + fail_unless_equals_int (gst_rtp_buffer_list_get_timestamp (list), 432191); + + /* SSRC */ + gst_rtp_buffer_list_set_ssrc (list, 0xf04043C2); + fail_unless_equals_int (gst_rtp_buffer_list_get_ssrc (list), + (gint) 0xf04043c2); + + /* Payload type */ + gst_rtp_buffer_list_set_payload_type (list, 127); + fail_unless_equals_int (gst_rtp_buffer_list_get_payload_type (list), 127); + + gst_buffer_list_unref (list); +} + +GST_END_TEST; + +GST_START_TEST (test_rtp_buffer_set_extension_data) +{ + GstBuffer *buf; + guint8 *data; + guint16 bits; + guint size; + guint8 misc_data[4] = { 1, 2, 3, 4 }; + gpointer pointer; + guint8 appbits; + + /* check GstRTPHeader structure alignment and packing */ + buf = gst_rtp_buffer_new_allocate (4, 0, 0); + data = GST_BUFFER_DATA (buf); + + /* should be impossible to set the extension data */ + ASSERT_WARNING (fail_unless (gst_rtp_buffer_set_extension_data (buf, 0, + 4) == FALSE)); + fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE); + + /* should be possible to set the extension data */ + fail_unless (gst_rtp_buffer_set_extension_data (buf, 270, 0) == TRUE); + fail_unless (gst_rtp_buffer_get_extension (buf) == TRUE); + gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size); + fail_unless (bits == 270); + fail_unless (size == 0); + fail_unless (pointer == GST_BUFFER_DATA (buf) + 16); + pointer = gst_rtp_buffer_get_payload (buf); + fail_unless (pointer == GST_BUFFER_DATA (buf) + 16); + gst_buffer_unref (buf); + + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + data = GST_BUFFER_DATA (buf); + fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE); + fail_unless (gst_rtp_buffer_set_extension_data (buf, 333, 2) == TRUE); + fail_unless (gst_rtp_buffer_get_extension (buf) == TRUE); + gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size); + fail_unless (bits == 333); + fail_unless (size == 2); + fail_unless (pointer == GST_BUFFER_DATA (buf) + 16); + pointer = gst_rtp_buffer_get_payload (buf); + fail_unless (pointer == GST_BUFFER_DATA (buf) + 24); + gst_buffer_unref (buf); + + /* Test header extensions with a one byte header */ + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE); + + fail_unless (gst_rtp_buffer_add_extension_onebyte_header (buf, 5, + misc_data, 2) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size)); + fail_unless (bits == 0xBEDE); + fail_unless (size == 1); + data = (guint8 *) pointer; + fail_unless (data[0] == ((5 << 4) | 1)); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 2, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + + fail_unless (gst_rtp_buffer_add_extension_onebyte_header (buf, 5, + misc_data, 4) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 2, + 1, &pointer, &size) == FALSE); + + fail_unless (gst_rtp_buffer_add_extension_onebyte_header (buf, 6, + misc_data, 2) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 3, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 2, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 6, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_onebyte_header (buf, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + gst_buffer_unref (buf); + + /* Test header extensions with a two bytes header */ + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + fail_unless (gst_rtp_buffer_get_extension (buf) == FALSE); + + fail_unless (gst_rtp_buffer_add_extension_twobytes_header (buf, 0, 5, + misc_data, 2) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size)); + fail_unless (bits == 0x100 << 4); + fail_unless (size == 1); + data = (guint8 *) pointer; + fail_unless (data[0] == 5); + fail_unless (data[1] == 2); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 2, + 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + + fail_unless (gst_rtp_buffer_add_extension_twobytes_header (buf, 0, 5, + misc_data, 4) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 2, + 0, &pointer, &size) == FALSE); + + fail_unless (gst_rtp_buffer_add_extension_twobytes_header (buf, 0, 6, + misc_data, 2) == TRUE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 2, + 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 6, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_get_extension_twobytes_header (buf, &appbits, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +GST_START_TEST (test_rtp_buffer_list_set_extension) +{ + GstBufferList *list; + GstBuffer *buf; + guint8 *data; + guint16 bits; + guint size; + guint8 misc_data[4] = { 1, 2, 3, 4 }; + gpointer pointer; + guint8 appbits; + GstBufferListIterator *it; + + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + list = gst_rtp_buffer_list_from_buffer (buf); + gst_buffer_unref (buf); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + buf = gst_buffer_list_iterator_next (it); + fail_unless (buf != NULL); + fail_unless (GST_BUFFER_SIZE (buf) == 12); + buf = gst_buffer_list_iterator_next (it); + fail_unless (buf != NULL); + fail_unless (GST_BUFFER_SIZE (buf) == 20); + gst_buffer_list_iterator_free (it); + + /* Test header extensions with a one byte header */ + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 2, + 1, &pointer, &size) == FALSE); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_onebyte_header (it, 5, + misc_data, 2) == TRUE); + gst_buffer_list_iterator_free (it); + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + buf = gst_buffer_list_iterator_next (it); + fail_unless (gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size)); + fail_unless (bits == 0xBEDE); + fail_unless (size == 1); + data = (guint8 *) pointer; + fail_unless (data[0] == ((5 << 4) | 1)); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 2, + 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_onebyte_header (it, 5, + misc_data, 4) == TRUE); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 2, + 0, &pointer, &size) == FALSE); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_onebyte_header (it, 6, + misc_data, 2) == TRUE); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 2, + 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 6, + 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_onebyte_header (list, 0, 5, + 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + gst_buffer_list_unref (list); + + + /* Test header extensions with a two bytes header */ + buf = gst_rtp_buffer_new_allocate (20, 0, 0); + list = gst_rtp_buffer_list_from_buffer (buf); + gst_buffer_unref (buf); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_twobytes_header (it, 0, 5, + misc_data, 2) == TRUE); + gst_buffer_list_iterator_free (it); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + buf = gst_buffer_list_iterator_next (it); + fail_unless (gst_rtp_buffer_get_extension_data (buf, &bits, &pointer, &size)); + fail_unless (bits == 0x100 << 4); + fail_unless (size == 1); + data = (guint8 *) pointer; + fail_unless (data[0] == 5); + fail_unless (data[1] == 2); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 2, 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_twobytes_header (it, 0, 5, + misc_data, 4) == TRUE); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 2, 0, &pointer, &size) == FALSE); + + it = gst_buffer_list_iterate (list); + fail_unless (gst_buffer_list_iterator_next_group (it)); + fail_unless (gst_buffer_list_iterator_next (it) != NULL); + fail_unless (gst_rtp_buffer_list_add_extension_twobytes_header (it, 0, 6, + misc_data, 2) == TRUE); + gst_buffer_list_iterator_free (it); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 1, &pointer, &size) == TRUE); + fail_unless (size == 4); + fail_unless (memcmp (pointer, misc_data, 4) == 0); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 2, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 2, 0, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 6, 1, &pointer, &size) == FALSE); + fail_unless (gst_rtp_buffer_list_get_extension_twobytes_header (list, 0, + &appbits, 5, 0, &pointer, &size) == TRUE); + fail_unless (size == 2); + fail_unless (memcmp (pointer, misc_data, 2) == 0); + + gst_buffer_list_unref (list); +} + +GST_END_TEST; + +GST_START_TEST (test_rtp_seqnum_compare) +{ +#define ASSERT_COMP(a,b,c) fail_unless (gst_rtp_buffer_compare_seqnum ((guint16)a,(guint16)b) == c); + ASSERT_COMP (0xfffe, 0xfffd, -1); + ASSERT_COMP (0xffff, 0xfffe, -1); + ASSERT_COMP (0x0000, 0xffff, -1); + ASSERT_COMP (0x0001, 0x0000, -1); + ASSERT_COMP (0x0002, 0x0001, -1); + + ASSERT_COMP (0xffff, 0xfffd, -2); + ASSERT_COMP (0x0000, 0xfffd, -3); + ASSERT_COMP (0x0001, 0xfffd, -4); + ASSERT_COMP (0x0002, 0xfffd, -5); + + ASSERT_COMP (0x7ffe, 0x7ffd, -1); + ASSERT_COMP (0x7fff, 0x7ffe, -1); + ASSERT_COMP (0x8000, 0x7fff, -1); + ASSERT_COMP (0x8001, 0x8000, -1); + ASSERT_COMP (0x8002, 0x8001, -1); + + ASSERT_COMP (0x7fff, 0x7ffd, -2); + ASSERT_COMP (0x8000, 0x7ffd, -3); + ASSERT_COMP (0x8001, 0x7ffd, -4); + ASSERT_COMP (0x8002, 0x7ffd, -5); + + ASSERT_COMP (0x7ffd, 0xffff, -0x7ffe); + ASSERT_COMP (0x7ffe, 0x0000, -0x7ffe); + ASSERT_COMP (0x7fff, 0x0001, -0x7ffe); + ASSERT_COMP (0x7fff, 0x0000, -0x7fff); + ASSERT_COMP (0x8000, 0x0001, -0x7fff); + ASSERT_COMP (0x8001, 0x0002, -0x7fff); + + ASSERT_COMP (0xfffd, 0x7ffe, -0x7fff); + ASSERT_COMP (0xfffe, 0x7fff, -0x7fff); + ASSERT_COMP (0xffff, 0x8000, -0x7fff); + ASSERT_COMP (0x0000, 0x8001, -0x7fff); + ASSERT_COMP (0x0001, 0x8002, -0x7fff); + + ASSERT_COMP (0xfffe, 0x7ffe, -0x8000); + ASSERT_COMP (0xffff, 0x7fff, -0x8000); + ASSERT_COMP (0x0000, 0x8000, -0x8000); + ASSERT_COMP (0x0001, 0x8001, -0x8000); + + ASSERT_COMP (0x7ffe, 0xfffe, -0x8000); + ASSERT_COMP (0x7fff, 0xffff, -0x8000); + ASSERT_COMP (0x8000, 0x0000, -0x8000); + ASSERT_COMP (0x8001, 0x0001, -0x8000); + + ASSERT_COMP (0x0001, 0x0002, 1); + ASSERT_COMP (0x0000, 0x0001, 1); + ASSERT_COMP (0xffff, 0x0000, 1); + ASSERT_COMP (0xfffe, 0xffff, 1); + ASSERT_COMP (0xfffd, 0xfffe, 1); + + ASSERT_COMP (0x0000, 0x0002, 2); + ASSERT_COMP (0xffff, 0x0002, 3); + ASSERT_COMP (0xfffe, 0x0002, 4); + ASSERT_COMP (0xfffd, 0x0002, 5); + + ASSERT_COMP (0x8001, 0x8002, 1); + ASSERT_COMP (0x8000, 0x8001, 1); + ASSERT_COMP (0x7fff, 0x8000, 1); + ASSERT_COMP (0x7ffe, 0x7fff, 1); + ASSERT_COMP (0x7ffd, 0x7ffe, 1); + + ASSERT_COMP (0x8000, 0x8002, 2); + ASSERT_COMP (0x7fff, 0x8002, 3); + ASSERT_COMP (0x7ffe, 0x8002, 4); + ASSERT_COMP (0x7ffd, 0x8002, 5); + + ASSERT_COMP (0xfffe, 0x7ffd, 0x7fff); + ASSERT_COMP (0xffff, 0x7ffe, 0x7fff); + ASSERT_COMP (0x0000, 0x7fff, 0x7fff); + ASSERT_COMP (0x0001, 0x8000, 0x7fff); + ASSERT_COMP (0x0002, 0x8001, 0x7fff); + + ASSERT_COMP (0x7ffe, 0xfffd, 0x7fff); + ASSERT_COMP (0x7fff, 0xfffe, 0x7fff); + ASSERT_COMP (0x8000, 0xffff, 0x7fff); + ASSERT_COMP (0x8001, 0x0000, 0x7fff); + ASSERT_COMP (0x8002, 0x0001, 0x7fff); +#undef ASSERT_COMP +} + +GST_END_TEST; + +GST_START_TEST (test_rtcp_buffer) +{ + GstBuffer *buf; + GstRTCPPacket packet; + guint8 *data; + + buf = gst_rtcp_buffer_new (1400); + fail_unless (buf != NULL); + fail_unless_equals_int (GST_BUFFER_SIZE (buf), 1400); + data = GST_BUFFER_DATA (buf); + + fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == FALSE); + fail_unless (gst_rtcp_buffer_get_packet_count (buf) == 0); + fail_unless (gst_rtcp_buffer_validate (buf) == FALSE); + + /* add an SR packet */ + fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_SR, + &packet) == TRUE); + + fail_unless (gst_rtcp_packet_get_padding (&packet) == 0); + fail_unless (gst_rtcp_packet_get_count (&packet) == 0); + fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SR); + fail_unless (gst_rtcp_packet_get_length (&packet) == 6); + + gst_rtcp_packet_sr_set_sender_info (&packet, 0x44556677, + G_GUINT64_CONSTANT (1), 0x11111111, 101, 123456); + { + guint32 ssrc; + guint64 ntptime; + guint32 rtptime; + guint32 packet_count; + guint32 octet_count; + + gst_rtcp_packet_sr_get_sender_info (&packet, &ssrc, &ntptime, &rtptime, + &packet_count, &octet_count); + + fail_unless (ssrc == 0x44556677); + fail_unless (ntptime == G_GUINT64_CONSTANT (1)); + fail_unless (rtptime == 0x11111111); + fail_unless (packet_count == 101); + fail_unless (octet_count == 123456); + } + + /* go to first packet, this should be the packet we just added */ + fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == TRUE); + + fail_unless (gst_rtcp_packet_get_padding (&packet) == 0); + fail_unless (gst_rtcp_packet_get_count (&packet) == 0); + fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SR); + fail_unless (gst_rtcp_packet_get_length (&packet) == 6); + + fail_unless (gst_rtcp_packet_move_to_next (&packet) == FALSE); + + /* add some SDES */ + fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_SDES, + &packet) == TRUE); + fail_unless (gst_rtcp_packet_sdes_add_item (&packet, 0xff658743) == TRUE); + fail_unless (gst_rtcp_packet_sdes_add_entry (&packet, GST_RTCP_SDES_CNAME, + sizeof ("test@foo.bar"), (guint8 *) "test@foo.bar") == TRUE); + + /* add some BYE */ + fail_unless (gst_rtcp_buffer_add_packet (buf, GST_RTCP_TYPE_BYE, + &packet) == TRUE); + fail_unless (gst_rtcp_packet_bye_add_ssrc (&packet, 0x5613212f) == TRUE); + fail_unless (gst_rtcp_packet_bye_add_ssrc (&packet, 0x00112233) == TRUE); + fail_unless (gst_rtcp_packet_bye_get_ssrc_count (&packet) == 2); + + fail_unless (gst_rtcp_packet_get_padding (&packet) == 0); + fail_unless (gst_rtcp_packet_get_count (&packet) == 2); + fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_BYE); + fail_unless (gst_rtcp_packet_get_length (&packet) == 2); + + /* move to SDES */ + fail_unless (gst_rtcp_buffer_get_first_packet (buf, &packet) == TRUE); + fail_unless (gst_rtcp_packet_move_to_next (&packet) == TRUE); + + fail_unless (gst_rtcp_packet_get_padding (&packet) == 0); + fail_unless (gst_rtcp_packet_get_count (&packet) == 1); + fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_SDES); + fail_unless (gst_rtcp_packet_get_length (&packet) == 5); + + /* remove the SDES */ + fail_unless (gst_rtcp_packet_remove (&packet) == TRUE); + + /* we are now at the BYE packet */ + fail_unless (gst_rtcp_packet_get_padding (&packet) == 0); + fail_unless (gst_rtcp_packet_get_count (&packet) == 2); + fail_unless (gst_rtcp_packet_get_type (&packet) == GST_RTCP_TYPE_BYE); + fail_unless (gst_rtcp_packet_get_length (&packet) == 2); + + /* close and validate */ + gst_rtcp_buffer_end (buf); + fail_unless (gst_rtcp_buffer_validate (buf) == TRUE); + gst_buffer_unref (buf); +} + +GST_END_TEST; + +static Suite * +rtp_suite (void) +{ + Suite *s = suite_create ("rtp support library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_rtp_buffer); + tcase_add_test (tc_chain, test_rtp_buffer_validate_corrupt); + tcase_add_test (tc_chain, test_rtp_buffer_set_extension_data); + tcase_add_test (tc_chain, test_rtp_buffer_list_set_extension); + tcase_add_test (tc_chain, test_rtp_seqnum_compare); + + tcase_add_test (tc_chain, test_rtcp_buffer); + + tcase_add_test (tc_chain, test_rtp_buffer_list); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = rtp_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/gst-plugins-base-subtitles0.10/tests/check/libs/rtsp.c b/gst-plugins-base-subtitles0.10/tests/check/libs/rtsp.c new file mode 100644 index 0000000..377f277 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/rtsp.c @@ -0,0 +1,153 @@ +/* GStreamer unit tests for the RTSP support library + * + * Copyright (C) 2010 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +GST_START_TEST (test_rtsp_url_basic) +{ + GstRTSPUrl *url = NULL; + GstRTSPResult res; + + res = gst_rtsp_url_parse ("rtsp://localhost/foo/bar", &url); + fail_unless (res == GST_RTSP_OK); + fail_unless (url != NULL); + fail_unless (url->transports & GST_RTSP_LOWER_TRANS_TCP); + fail_unless (url->transports & GST_RTSP_LOWER_TRANS_UDP); + fail_unless (url->transports & GST_RTSP_LOWER_TRANS_UDP_MCAST); + fail_unless (url->family == GST_RTSP_FAM_INET); + fail_unless (!url->user); + fail_unless (!url->passwd); + fail_unless (!strcmp (url->host, "localhost")); + /* fail_unless (url->port == GST_RTSP_DEFAULT_PORT); */ + fail_unless (!strcmp (url->abspath, "/foo/bar")); + fail_unless (!url->query); + + gst_rtsp_url_free (url); +} + +GST_END_TEST; + +GST_START_TEST (test_rtsp_url_components_1) +{ + GstRTSPUrl *url = NULL; + GstRTSPResult res; + gchar **comps = NULL; + + res = gst_rtsp_url_parse ("rtsp://localhost/foo/bar", &url); + fail_unless (res == GST_RTSP_OK); + fail_unless (url != NULL); + + comps = gst_rtsp_url_decode_path_components (url); + fail_unless (comps != NULL); + fail_unless (g_strv_length (comps) == 3); + fail_unless (!strcmp (comps[0], "")); + fail_unless (!strcmp (comps[1], "foo")); + fail_unless (!strcmp (comps[2], "bar")); + + g_strfreev (comps); + gst_rtsp_url_free (url); +} + +GST_END_TEST; + +GST_START_TEST (test_rtsp_url_components_2) +{ + GstRTSPUrl *url = NULL; + GstRTSPResult res; + gchar **comps = NULL; + + res = gst_rtsp_url_parse ("rtsp://localhost/foo%2Fbar/qux%20baz", &url); + fail_unless (res == GST_RTSP_OK); + fail_unless (url != NULL); + + comps = gst_rtsp_url_decode_path_components (url); + fail_unless (comps != NULL); + fail_unless (g_strv_length (comps) == 3); + fail_unless (!strcmp (comps[0], "")); + fail_unless (!strcmp (comps[1], "foo/bar")); + fail_unless (!strcmp (comps[2], "qux baz")); + + g_strfreev (comps); + gst_rtsp_url_free (url); +} + +GST_END_TEST; + +GST_START_TEST (test_rtsp_url_components_3) +{ + GstRTSPUrl *url = NULL; + GstRTSPResult res; + gchar **comps = NULL; + + res = gst_rtsp_url_parse ("rtsp://localhost/foo%00bar/qux%20baz", &url); + fail_unless (res == GST_RTSP_OK); + fail_unless (url != NULL); + + comps = gst_rtsp_url_decode_path_components (url); + fail_unless (comps != NULL); + fail_unless (g_strv_length (comps) == 3); + fail_unless (!strcmp (comps[0], "")); + fail_unless (!strcmp (comps[1], "foo%00bar")); + fail_unless (!strcmp (comps[2], "qux baz")); + + g_strfreev (comps); + gst_rtsp_url_free (url); +} + +GST_END_TEST; + +static Suite * +rtsp_suite (void) +{ + Suite *s = suite_create ("rtsp support library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_rtsp_url_basic); + tcase_add_test (tc_chain, test_rtsp_url_components_1); + tcase_add_test (tc_chain, test_rtsp_url_components_2); + tcase_add_test (tc_chain, test_rtsp_url_components_3); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = rtsp_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/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386.h b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386.h new file mode 100644 index 0000000..6f504ad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386.h @@ -0,0 +1,100 @@ + +GstCheckABIStruct list[] = { + {"GstAppBufferClass", sizeof (GstAppBufferClass), 16}, + {"GstAppBuffer", sizeof (GstAppBuffer), 88}, + {"GstAppSinkCallbacks", sizeof (GstAppSinkCallbacks), 28}, + {"GstAppSinkClass", sizeof (GstAppSinkClass), 404}, + {"GstAppSink", sizeof (GstAppSink), 404}, + {"GstAppSrcCallbacks", sizeof (GstAppSrcCallbacks), 28}, + {"GstAppSrcClass", sizeof (GstAppSrcClass), 412}, + {"GstAppSrc", sizeof (GstAppSrc), 396}, + {"GstAudioClockClass", sizeof (GstAudioClockClass), 192}, + {"GstAudioClock", sizeof (GstAudioClock), 228}, + {"GstAudioFilterClass", sizeof (GstAudioFilterClass), 396}, + {"GstAudioFilter", sizeof (GstAudioFilter), 480}, + {"GstAudioSinkClass", sizeof (GstAudioSinkClass), 432}, + {"GstAudioSink", sizeof (GstAudioSink), 456}, + {"GstAudioSrcClass", sizeof (GstAudioSrcClass), 460}, + {"GstAudioSrc", sizeof (GstAudioSrc), 460}, + {"GstBaseAudioSinkClass", sizeof (GstBaseAudioSinkClass), 388}, + {"GstBaseAudioSink", sizeof (GstBaseAudioSink), 436}, + {"GstBaseAudioSrcClass", sizeof (GstBaseAudioSrcClass), 416}, + {"GstBaseAudioSrc", sizeof (GstBaseAudioSrc), 440}, + {"GstBaseRTPAudioPayloadClass", sizeof (GstBaseRTPAudioPayloadClass), 288}, + {"GstBaseRTPAudioPayload", sizeof (GstBaseRTPAudioPayload), 364}, + {"GstBaseRTPDepayloadClass", sizeof (GstBaseRTPDepayloadClass), 280}, + {"GstBaseRTPDepayload", sizeof (GstBaseRTPDepayload), 304}, + {"GstBaseRTPPayloadClass", sizeof (GstBaseRTPPayloadClass), 272}, + {"GstBaseRTPPayload", sizeof (GstBaseRTPPayload), 324}, + {"GstCddaBaseSrcClass", sizeof (GstCddaBaseSrcClass), 432}, + {"GstCddaBaseSrc", sizeof (GstCddaBaseSrc), 508}, + {"GstCddaBaseSrcTrack", sizeof (GstCddaBaseSrcTrack), 36}, + {"GstColorBalanceChannelClass", sizeof (GstColorBalanceChannelClass), 88}, + {"GstColorBalanceChannel", sizeof (GstColorBalanceChannel), 24}, + {"GstColorBalanceClass", sizeof (GstColorBalanceClass), 44}, + {"GstDiscovererClass", sizeof (GstDiscovererClass), 96}, + {"GstDiscoverer", sizeof (GstDiscoverer), 32}, + {"GstFFTF32Complex", sizeof (GstFFTF32Complex), 8}, + {"GstFFTF32", sizeof (GstFFTF32), 28}, + {"GstFFTF64Complex", sizeof (GstFFTF64Complex), 16}, + {"GstFFTF64", sizeof (GstFFTF64), 28}, + {"GstFFTS16Complex", sizeof (GstFFTS16Complex), 4}, + {"GstFFTS16", sizeof (GstFFTS16), 28}, + {"GstFFTS32Complex", sizeof (GstFFTS32Complex), 8}, + {"GstFFTS32", sizeof (GstFFTS32), 28}, + {"GstMixerClass", sizeof (GstMixerClass), 72}, + {"GstMixerOptionsClass", sizeof (GstMixerOptionsClass), 100}, + {"GstMixerOptions", sizeof (GstMixerOptions), 52}, + {"GstMixerTrackClass", sizeof (GstMixerTrackClass), 84}, + {"GstMixerTrack", sizeof (GstMixerTrack), 32}, + {"GstNavigationInterface", sizeof (GstNavigationInterface), 28}, + {"GstNetAddress", sizeof (GstNetAddress), 40}, + {"GstNetBufferClass", sizeof (GstNetBufferClass), 32}, + {"GstNetBuffer", sizeof (GstNetBuffer), 176}, + {"GstPropertyProbeInterface", sizeof (GstPropertyProbeInterface), 44}, + {"gst_riff_acid", sizeof (gst_riff_acid), 24}, + {"gst_riff_dmlh", sizeof (gst_riff_dmlh), 4}, + {"gst_riff_index_entry", sizeof (gst_riff_index_entry), 16}, + {"gst_riff_strf_auds", sizeof (gst_riff_strf_auds), 16}, + {"gst_riff_strf_iavs", sizeof (gst_riff_strf_iavs), 32}, + {"gst_riff_strf_vids", sizeof (gst_riff_strf_vids), 40}, + {"gst_riff_strh", sizeof (gst_riff_strh), 48}, + {"GstRingBufferClass", sizeof (GstRingBufferClass), 172}, + {"GstRingBuffer", sizeof (GstRingBuffer), 220}, + {"GstRingBufferSpec", sizeof (GstRingBufferSpec), 112}, + {"GstRTCPPacket", sizeof (GstRTCPPacket), 36}, + {"GstRTPPayloadInfo", sizeof (GstRTPPayloadInfo), 24}, + {"GstRTSPExtensionInterface", sizeof (GstRTSPExtensionInterface), 60}, + {"GstRTSPMessage", sizeof (GstRTSPMessage), 28}, + {"GstRTSPRange", sizeof (GstRTSPRange), 8}, + {"GstRTSPTime", sizeof (GstRTSPTime), 12}, + {"GstRTSPTimeRange", sizeof (GstRTSPTimeRange), 28}, + {"GstRTSPTransport", sizeof (GstRTSPTransport), 76}, + {"GstRTSPUrl", sizeof (GstRTSPUrl), 32}, + {"GstRTSPWatchFuncs", sizeof (GstRTSPWatchFuncs), 40}, + {"GstSDPAttribute", sizeof (GstSDPAttribute), 8}, + {"GstSDPBandwidth", sizeof (GstSDPBandwidth), 8}, + {"GstSDPConnection", sizeof (GstSDPConnection), 20}, + {"GstSDPKey", sizeof (GstSDPKey), 8}, + {"GstSDPMedia", sizeof (GstSDPMedia), 44}, + {"GstSDPMessage", sizeof (GstSDPMessage), 96}, + {"GstSDPOrigin", sizeof (GstSDPOrigin), 24}, + {"GstSDPTime", sizeof (GstSDPTime), 12}, + {"GstSDPZone", sizeof (GstSDPZone), 8}, + {"GstStreamVolumeInterface", sizeof (GstStreamVolumeInterface), 24}, + {"GstTagDemuxClass", sizeof (GstTagDemuxClass), 284}, + {"GstTagDemux", sizeof (GstTagDemux), 148}, + {"GstTunerChannelClass", sizeof (GstTunerChannelClass), 92}, + {"GstTunerChannel", sizeof (GstTunerChannel), 40}, + {"GstTunerClass", sizeof (GstTunerClass), 76}, + {"GstTunerNormClass", sizeof (GstTunerNormClass), 84}, + {"GstTunerNorm", sizeof (GstTunerNorm), 36}, + {"GstVideoFilterClass", sizeof (GstVideoFilterClass), 376}, + {"GstVideoFilter", sizeof (GstVideoFilter), 356}, + {"GstVideoOrientationInterface", sizeof (GstVideoOrientationInterface), 56}, + {"GstVideoRectangle", sizeof (GstVideoRectangle), 16}, + {"GstVideoSinkClass", sizeof (GstVideoSinkClass), 384}, + {"GstVideoSink", sizeof (GstVideoSink), 408}, + {"GstXOverlayClass", sizeof (GstXOverlayClass), 32}, + {NULL, 0, 0} +}; diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386_osx.h b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386_osx.h new file mode 100644 index 0000000..1714aec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_i386_osx.h @@ -0,0 +1,100 @@ + +GstCheckABIStruct list[] = { + {"GstAppBufferClass", sizeof (GstAppBufferClass), 16}, + {"GstAppBuffer", sizeof (GstAppBuffer), 88}, + {"GstAppSinkCallbacks", sizeof (GstAppSinkCallbacks), 28}, + {"GstAppSinkClass", sizeof (GstAppSinkClass), 404}, + {"GstAppSink", sizeof (GstAppSink), 404}, + {"GstAppSrcCallbacks", sizeof (GstAppSrcCallbacks), 28}, + {"GstAppSrcClass", sizeof (GstAppSrcClass), 412}, + {"GstAppSrc", sizeof (GstAppSrc), 396}, + {"GstAudioClockClass", sizeof (GstAudioClockClass), 192}, + {"GstAudioClock", sizeof (GstAudioClock), 228}, + {"GstAudioFilterClass", sizeof (GstAudioFilterClass), 396}, + {"GstAudioFilter", sizeof (GstAudioFilter), 480}, + {"GstAudioSinkClass", sizeof (GstAudioSinkClass), 432}, + {"GstAudioSink", sizeof (GstAudioSink), 456}, + {"GstAudioSrcClass", sizeof (GstAudioSrcClass), 460}, + {"GstAudioSrc", sizeof (GstAudioSrc), 460}, + {"GstBaseAudioSinkClass", sizeof (GstBaseAudioSinkClass), 388}, + {"GstBaseAudioSink", sizeof (GstBaseAudioSink), 436}, + {"GstBaseAudioSrcClass", sizeof (GstBaseAudioSrcClass), 416}, + {"GstBaseAudioSrc", sizeof (GstBaseAudioSrc), 440}, + {"GstBaseRTPAudioPayloadClass", sizeof (GstBaseRTPAudioPayloadClass), 288}, + {"GstBaseRTPAudioPayload", sizeof (GstBaseRTPAudioPayload), 364}, + {"GstBaseRTPDepayloadClass", sizeof (GstBaseRTPDepayloadClass), 280}, + {"GstBaseRTPDepayload", sizeof (GstBaseRTPDepayload), 324}, + {"GstBaseRTPPayloadClass", sizeof (GstBaseRTPPayloadClass), 272}, + {"GstBaseRTPPayload", sizeof (GstBaseRTPPayload), 324}, + {"GstCddaBaseSrcClass", sizeof (GstCddaBaseSrcClass), 432}, + {"GstCddaBaseSrc", sizeof (GstCddaBaseSrc), 508}, + {"GstCddaBaseSrcTrack", sizeof (GstCddaBaseSrcTrack), 36}, + {"GstColorBalanceChannelClass", sizeof (GstColorBalanceChannelClass), 88}, + {"GstColorBalanceChannel", sizeof (GstColorBalanceChannel), 24}, + {"GstColorBalanceClass", sizeof (GstColorBalanceClass), 44}, + {"GstDiscovererClass", sizeof (GstDiscovererClass), 96}, + {"GstDiscoverer", sizeof (GstDiscoverer), 32}, + {"GstFFTF32Complex", sizeof (GstFFTF32Complex), 8}, + {"GstFFTF32", sizeof (GstFFTF32), 28}, + {"GstFFTF64Complex", sizeof (GstFFTF64Complex), 16}, + {"GstFFTF64", sizeof (GstFFTF64), 28}, + {"GstFFTS16Complex", sizeof (GstFFTS16Complex), 4}, + {"GstFFTS16", sizeof (GstFFTS16), 28}, + {"GstFFTS32Complex", sizeof (GstFFTS32Complex), 8}, + {"GstFFTS32", sizeof (GstFFTS32), 28}, + {"GstMixerClass", sizeof (GstMixerClass), 72}, + {"GstMixerOptionsClass", sizeof (GstMixerOptionsClass), 100}, + {"GstMixerOptions", sizeof (GstMixerOptions), 52}, + {"GstMixerTrackClass", sizeof (GstMixerTrackClass), 84}, + {"GstMixerTrack", sizeof (GstMixerTrack), 32}, + {"GstNavigationInterface", sizeof (GstNavigationInterface), 28}, + {"GstNetAddress", sizeof (GstNetAddress), 40}, + {"GstNetBufferClass", sizeof (GstNetBufferClass), 32}, + {"GstNetBuffer", sizeof (GstNetBuffer), 176}, + {"GstPropertyProbeInterface", sizeof (GstPropertyProbeInterface), 44}, + {"gst_riff_acid", sizeof (gst_riff_acid), 24}, + {"gst_riff_dmlh", sizeof (gst_riff_dmlh), 4}, + {"gst_riff_index_entry", sizeof (gst_riff_index_entry), 16}, + {"gst_riff_strf_auds", sizeof (gst_riff_strf_auds), 16}, + {"gst_riff_strf_iavs", sizeof (gst_riff_strf_iavs), 32}, + {"gst_riff_strf_vids", sizeof (gst_riff_strf_vids), 40}, + {"gst_riff_strh", sizeof (gst_riff_strh), 48}, + {"GstRingBufferClass", sizeof (GstRingBufferClass), 172}, + {"GstRingBuffer", sizeof (GstRingBuffer), 220}, + {"GstRingBufferSpec", sizeof (GstRingBufferSpec), 112}, + {"GstRTCPPacket", sizeof (GstRTCPPacket), 36}, + {"GstRTPPayloadInfo", sizeof (GstRTPPayloadInfo), 24}, + {"GstRTSPExtensionInterface", sizeof (GstRTSPExtensionInterface), 60}, + {"GstRTSPMessage", sizeof (GstRTSPMessage), 28}, + {"GstRTSPRange", sizeof (GstRTSPRange), 8}, + {"GstRTSPTime", sizeof (GstRTSPTime), 12}, + {"GstRTSPTimeRange", sizeof (GstRTSPTimeRange), 28}, + {"GstRTSPTransport", sizeof (GstRTSPTransport), 76}, + {"GstRTSPUrl", sizeof (GstRTSPUrl), 32}, + {"GstRTSPWatchFuncs", sizeof (GstRTSPWatchFuncs), 40}, + {"GstSDPAttribute", sizeof (GstSDPAttribute), 8}, + {"GstSDPBandwidth", sizeof (GstSDPBandwidth), 8}, + {"GstSDPConnection", sizeof (GstSDPConnection), 20}, + {"GstSDPKey", sizeof (GstSDPKey), 8}, + {"GstSDPMedia", sizeof (GstSDPMedia), 44}, + {"GstSDPMessage", sizeof (GstSDPMessage), 96}, + {"GstSDPOrigin", sizeof (GstSDPOrigin), 24}, + {"GstSDPTime", sizeof (GstSDPTime), 12}, + {"GstSDPZone", sizeof (GstSDPZone), 8}, + {"GstStreamVolumeInterface", sizeof (GstStreamVolumeInterface), 24}, + {"GstTagDemuxClass", sizeof (GstTagDemuxClass), 284}, + {"GstTagDemux", sizeof (GstTagDemux), 148}, + {"GstTunerChannelClass", sizeof (GstTunerChannelClass), 92}, + {"GstTunerChannel", sizeof (GstTunerChannel), 40}, + {"GstTunerClass", sizeof (GstTunerClass), 76}, + {"GstTunerNormClass", sizeof (GstTunerNormClass), 84}, + {"GstTunerNorm", sizeof (GstTunerNorm), 36}, + {"GstVideoFilterClass", sizeof (GstVideoFilterClass), 376}, + {"GstVideoFilter", sizeof (GstVideoFilter), 356}, + {"GstVideoOrientationInterface", sizeof (GstVideoOrientationInterface), 56}, + {"GstVideoRectangle", sizeof (GstVideoRectangle), 16}, + {"GstVideoSinkClass", sizeof (GstVideoSinkClass), 384}, + {"GstVideoSink", sizeof (GstVideoSink), 408}, + {"GstXOverlayClass", sizeof (GstXOverlayClass), 32}, + {NULL, 0, 0} +}; diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/struct_x86_64.h b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_x86_64.h new file mode 100644 index 0000000..3029e56 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/struct_x86_64.h @@ -0,0 +1,100 @@ + +GstCheckABIStruct list[] = { + {"GstAppBufferClass", sizeof (GstAppBufferClass), 32}, + {"GstAppBuffer", sizeof (GstAppBuffer), 136}, + {"GstAppSinkCallbacks", sizeof (GstAppSinkCallbacks), 56}, + {"GstAppSinkClass", sizeof (GstAppSinkClass), 800}, + {"GstAppSink", sizeof (GstAppSink), 640}, + {"GstAppSrcCallbacks", sizeof (GstAppSrcCallbacks), 56}, + {"GstAppSrcClass", sizeof (GstAppSrcClass), 816}, + {"GstAppSrc", sizeof (GstAppSrc), 640}, + {"GstAudioClockClass", sizeof (GstAudioClockClass), 384}, + {"GstAudioClock", sizeof (GstAudioClock), 344}, + {"GstAudioFilterClass", sizeof (GstAudioFilterClass), 784}, + {"GstAudioFilter", sizeof (GstAudioFilter), 744}, + {"GstAudioSinkClass", sizeof (GstAudioSinkClass), 856}, + {"GstAudioSink", sizeof (GstAudioSink), 720}, + {"GstAudioSrcClass", sizeof (GstAudioSrcClass), 912}, + {"GstAudioSrc", sizeof (GstAudioSrc), 744}, + {"GstBaseAudioSinkClass", sizeof (GstBaseAudioSinkClass), 768}, + {"GstBaseAudioSink", sizeof (GstBaseAudioSink), 680}, + {"GstBaseAudioSrcClass", sizeof (GstBaseAudioSrcClass), 824}, + {"GstBaseAudioSrc", sizeof (GstBaseAudioSrc), 704}, + {"GstBaseRTPAudioPayloadClass", sizeof (GstBaseRTPAudioPayloadClass), 568}, + {"GstBaseRTPAudioPayload", sizeof (GstBaseRTPAudioPayload), 544}, + {"GstBaseRTPDepayloadClass", sizeof (GstBaseRTPDepayloadClass), 552}, + {"GstBaseRTPDepayload", sizeof (GstBaseRTPDepayload), 488}, + {"GstBaseRTPPayloadClass", sizeof (GstBaseRTPPayloadClass), 536}, + {"GstBaseRTPPayload", sizeof (GstBaseRTPPayload), 480}, + {"GstCddaBaseSrcClass", sizeof (GstCddaBaseSrcClass), 856}, + {"GstCddaBaseSrc", sizeof (GstCddaBaseSrc), 792}, + {"GstCddaBaseSrcTrack", sizeof (GstCddaBaseSrcTrack), 48}, + {"GstColorBalanceChannelClass", sizeof (GstColorBalanceChannelClass), 176}, + {"GstColorBalanceChannel", sizeof (GstColorBalanceChannel), 40}, + {"GstColorBalanceClass", sizeof (GstColorBalanceClass), 88}, + {"GstDiscovererClass", sizeof (GstDiscovererClass), 192}, + {"GstDiscoverer", sizeof (GstDiscoverer), 64}, + {"GstFFTF32Complex", sizeof (GstFFTF32Complex), 8}, + {"GstFFTF32", sizeof (GstFFTF32), 48}, + {"GstFFTF64Complex", sizeof (GstFFTF64Complex), 16}, + {"GstFFTF64", sizeof (GstFFTF64), 48}, + {"GstFFTS16Complex", sizeof (GstFFTS16Complex), 4}, + {"GstFFTS16", sizeof (GstFFTS16), 48}, + {"GstFFTS32Complex", sizeof (GstFFTS32Complex), 8}, + {"GstFFTS32", sizeof (GstFFTS32), 48}, + {"GstMixerClass", sizeof (GstMixerClass), 144}, + {"GstMixerOptionsClass", sizeof (GstMixerOptionsClass), 200}, + {"GstMixerOptions", sizeof (GstMixerOptions), 88}, + {"GstMixerTrackClass", sizeof (GstMixerTrackClass), 168}, + {"GstMixerTrack", sizeof (GstMixerTrack), 48}, + {"GstNavigationInterface", sizeof (GstNavigationInterface), 56}, + {"GstNetAddress", sizeof (GstNetAddress), 56}, + {"GstNetBufferClass", sizeof (GstNetBufferClass), 64}, + {"GstNetBuffer", sizeof (GstNetBuffer), 264}, + {"GstPropertyProbeInterface", sizeof (GstPropertyProbeInterface), 88}, + {"gst_riff_acid", sizeof (gst_riff_acid), 24}, + {"gst_riff_dmlh", sizeof (gst_riff_dmlh), 4}, + {"gst_riff_index_entry", sizeof (gst_riff_index_entry), 16}, + {"gst_riff_strf_auds", sizeof (gst_riff_strf_auds), 16}, + {"gst_riff_strf_iavs", sizeof (gst_riff_strf_iavs), 32}, + {"gst_riff_strf_vids", sizeof (gst_riff_strf_vids), 40}, + {"gst_riff_strh", sizeof (gst_riff_strh), 48}, + {"GstRingBufferClass", sizeof (GstRingBufferClass), 344}, + {"GstRingBuffer", sizeof (GstRingBuffer), 328}, + {"GstRingBufferSpec", sizeof (GstRingBufferSpec), 136}, + {"GstRTCPPacket", sizeof (GstRTCPPacket), 40}, + {"GstRTPPayloadInfo", sizeof (GstRTPPayloadInfo), 48}, + {"GstRTSPExtensionInterface", sizeof (GstRTSPExtensionInterface), 120}, + {"GstRTSPMessage", sizeof (GstRTSPMessage), 56}, + {"GstRTSPRange", sizeof (GstRTSPRange), 8}, + {"GstRTSPTime", sizeof (GstRTSPTime), 16}, + {"GstRTSPTimeRange", sizeof (GstRTSPTimeRange), 40}, + {"GstRTSPTransport", sizeof (GstRTSPTransport), 88}, + {"GstRTSPUrl", sizeof (GstRTSPUrl), 56}, + {"GstRTSPWatchFuncs", sizeof (GstRTSPWatchFuncs), 80}, + {"GstSDPAttribute", sizeof (GstSDPAttribute), 16}, + {"GstSDPBandwidth", sizeof (GstSDPBandwidth), 16}, + {"GstSDPConnection", sizeof (GstSDPConnection), 32}, + {"GstSDPKey", sizeof (GstSDPKey), 16}, + {"GstSDPMedia", sizeof (GstSDPMedia), 80}, + {"GstSDPMessage", sizeof (GstSDPMessage), 184}, + {"GstSDPOrigin", sizeof (GstSDPOrigin), 48}, + {"GstSDPTime", sizeof (GstSDPTime), 24}, + {"GstSDPZone", sizeof (GstSDPZone), 16}, + {"GstStreamVolumeInterface", sizeof (GstStreamVolumeInterface), 48}, + {"GstTagDemuxClass", sizeof (GstTagDemuxClass), 552}, + {"GstTagDemux", sizeof (GstTagDemux), 272}, + {"GstTunerChannelClass", sizeof (GstTunerChannelClass), 184}, + {"GstTunerChannel", sizeof (GstTunerChannel), 64}, + {"GstTunerClass", sizeof (GstTunerClass), 152}, + {"GstTunerNormClass", sizeof (GstTunerNormClass), 168}, + {"GstTunerNorm", sizeof (GstTunerNorm), 56}, + {"GstVideoFilterClass", sizeof (GstVideoFilterClass), 744}, + {"GstVideoFilter", sizeof (GstVideoFilter), 584}, + {"GstVideoOrientationInterface", sizeof (GstVideoOrientationInterface), 112}, + {"GstVideoRectangle", sizeof (GstVideoRectangle), 16}, + {"GstVideoSinkClass", sizeof (GstVideoSinkClass), 760}, + {"GstVideoSink", sizeof (GstVideoSink), 640}, + {"GstXOverlayClass", sizeof (GstXOverlayClass), 64}, + {NULL, 0, 0} +}; diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/tag.c b/gst-plugins-base-subtitles0.10/tests/check/libs/tag.c new file mode 100644 index 0000000..c963ce5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/tag.c @@ -0,0 +1,1656 @@ +/* GStreamer + * + * unit tests for the tag support library + * + * Copyright (C) 2006-2009 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +GST_START_TEST (test_parse_extended_comment) +{ + gchar *key, *val, *lang; + + /* first check the g_return_val_if_fail conditions */ + ASSERT_CRITICAL (gst_tag_parse_extended_comment (NULL, NULL, NULL, NULL, + FALSE)); + ASSERT_CRITICAL (gst_tag_parse_extended_comment ("\377\000", NULL, NULL, NULL, + FALSE)); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("a=b", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key != NULL); + fail_unless (lang == NULL); + fail_unless (val != NULL); + fail_unless_equals_string (key, "a"); + fail_unless_equals_string (val, "b"); + g_free (key); + g_free (lang); + g_free (val); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("a[l]=b", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key != NULL); + fail_unless (lang != NULL); + fail_unless (val != NULL); + fail_unless_equals_string (key, "a"); + fail_unless_equals_string (lang, "l"); + fail_unless_equals_string (val, "b"); + g_free (key); + g_free (lang); + g_free (val); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("foo=bar", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key != NULL); + fail_unless (lang == NULL); + fail_unless (val != NULL); + fail_unless_equals_string (key, "foo"); + fail_unless_equals_string (val, "bar"); + g_free (key); + g_free (lang); + g_free (val); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key != NULL); + fail_unless (lang != NULL); + fail_unless (val != NULL); + fail_unless_equals_string (key, "foo"); + fail_unless_equals_string (lang, "fr"); + fail_unless_equals_string (val, "bar"); + g_free (key); + g_free (lang); + g_free (val); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("foo=[fr]bar", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key != NULL); + fail_unless (lang == NULL); + fail_unless (val != NULL); + fail_unless_equals_string (key, "foo"); + fail_unless_equals_string (val, "[fr]bar"); + g_free (key); + g_free (lang); + g_free (val); + + /* test NULL for output locations */ + fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL, + FALSE) == TRUE); + + /* test strict mode (key must be specified) */ + fail_unless (gst_tag_parse_extended_comment ("foo[fr]=bar", NULL, NULL, NULL, + TRUE) == TRUE); + fail_unless (gst_tag_parse_extended_comment ("foo=bar", NULL, NULL, NULL, + TRUE) == TRUE); + fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL, + TRUE) == FALSE); + + /* test non-strict mode (if there's no key, that's fine too) */ + fail_unless (gst_tag_parse_extended_comment ("foobar", NULL, NULL, NULL, + FALSE) == TRUE); + fail_unless (gst_tag_parse_extended_comment ("[fr]bar", NULL, NULL, NULL, + FALSE) == TRUE); + + key = val = lang = NULL; + fail_unless (gst_tag_parse_extended_comment ("[fr]bar", &key, &lang, &val, + FALSE) == TRUE); + fail_unless (key == NULL); + fail_unless (lang == NULL); + fail_unless (val != NULL); + fail_unless_equals_string (val, "[fr]bar"); + g_free (key); + g_free (lang); + g_free (val); +} + +GST_END_TEST; + +#define ASSERT_TAG_LIST_HAS_STRING(list,field,string) \ + { \ + gboolean got_match = FALSE; \ + guint i, size; \ + \ + fail_unless (gst_tag_list_get_tag_size (list,field) > 0); \ + size = gst_tag_list_get_tag_size (list,field); \ + for (i = 0; i < size; ++i) { \ + gchar *___s = NULL; \ + \ + fail_unless (gst_tag_list_get_string_index (list, field, i, &___s)); \ + fail_unless (___s != NULL); \ + if (g_str_equal (___s, string)) { \ + got_match = TRUE; \ + g_free (___s); \ + break; \ + } \ + g_free (___s); \ + } \ + fail_unless (got_match); \ + } + +#define ASSERT_TAG_LIST_HAS_UINT(list,field,num) \ + { \ + guint ___n; \ + \ + fail_unless (gst_tag_list_get_tag_size (list,field) > 0); \ + fail_unless (gst_tag_list_get_tag_size (list,field) == 1); \ + fail_unless (gst_tag_list_get_uint_index (list, field, 0, &___n)); \ + fail_unless_equals_int (___n, num); \ + } + +#define MATCH_DOUBLE(p1, p2) ((p1 < p2 + 1e-6) && (p2 < p1 + 1e-6)) +#define ASSERT_TAG_LIST_HAS_DOUBLE(list,field,d) \ + { \ + gdouble ___d; \ + \ + fail_unless (gst_tag_list_get_tag_size (list,field) > 0); \ + fail_unless (gst_tag_list_get_tag_size (list,field) == 1); \ + fail_unless (gst_tag_list_get_double_index (list, field, 0, &___d)); \ + fail_unless (MATCH_DOUBLE (d, ___d), \ + "%f does not match expected %f", ___d, d); \ + } + +GST_START_TEST (test_musicbrainz_tag_registration) +{ + GstTagList *list; + + gst_tag_register_musicbrainz_tags (); + + list = gst_tag_list_new (); + + /* musicbrainz tags aren't registered yet */ + gst_vorbis_tag_add (list, "MUSICBRAINZ_TRACKID", "123456"); + gst_vorbis_tag_add (list, "MUSICBRAINZ_ARTISTID", "234567"); + gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMID", "345678"); + gst_vorbis_tag_add (list, "MUSICBRAINZ_ALBUMARTISTID", "4567890"); + gst_vorbis_tag_add (list, "MUSICBRAINZ_TRMID", "5678901"); + /* MUSICBRAINZ_SORTNAME = GST_TAG_ARTIST_SORTNAME now */ + gst_vorbis_tag_add (list, "MUSICBRAINZ_SORTNAME", "Five, 678901"); + + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRACKID, "123456"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ARTISTID, "234567"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMID, "345678"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_ALBUMARTISTID, + "4567890"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_MUSICBRAINZ_TRMID, "5678901"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST_SORTNAME, "Five, 678901"); + + gst_tag_list_free (list); +} + +GST_END_TEST; + +/* is there an easier way to compare two structures / tagslists? */ +static gboolean +taglists_are_equal (const GstTagList * list_1, const GstTagList * list_2) +{ + GstCaps *c_list_1 = gst_caps_new_empty (); + GstCaps *c_list_2 = gst_caps_new_empty (); + gboolean ret; + + gst_caps_append_structure (c_list_1, + gst_structure_copy ((GstStructure *) list_1)); + gst_caps_append_structure (c_list_2, + gst_structure_copy ((GstStructure *) list_2)); + + ret = gst_caps_is_equal (c_list_2, c_list_1); + + gst_caps_unref (c_list_1); + gst_caps_unref (c_list_2); + + return ret; +} + +GST_START_TEST (test_vorbis_tags) +{ + GstTagList *list; + + list = gst_tag_list_new (); + + /* NULL pointers aren't allowed */ + ASSERT_CRITICAL (gst_vorbis_tag_add (NULL, "key", "value")); + ASSERT_CRITICAL (gst_vorbis_tag_add (list, NULL, "value")); + ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", NULL)); + + /* must be UTF-8 */ + ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key", "v\377lue")); + ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k\377y", "value")); + + /* key can't have a '=' in it */ + ASSERT_CRITICAL (gst_vorbis_tag_add (list, "k=y", "value")); + ASSERT_CRITICAL (gst_vorbis_tag_add (list, "key=", "value")); + + /* should be allowed in values though */ + gst_vorbis_tag_add (list, "keeey", "va=ue"); + + /* add some tags */ + gst_vorbis_tag_add (list, "TITLE", "Too"); + gst_vorbis_tag_add (list, "ALBUM", "Aoo"); + gst_vorbis_tag_add (list, "ARTIST", "Alboo"); + gst_vorbis_tag_add (list, "PERFORMER", "Perfoo"); + gst_vorbis_tag_add (list, "COPYRIGHT", "Copyfoo"); + gst_vorbis_tag_add (list, "DESCRIPTION", "Descoo"); + gst_vorbis_tag_add (list, "LICENSE", "Licoo"); + gst_vorbis_tag_add (list, "LICENSE", + "http://creativecommons.org/licenses/by/3.0/"); + gst_vorbis_tag_add (list, "LOCATION", "Bristol, UK"); + gst_vorbis_tag_add (list, "ORGANIZATION", "Orgoo"); + gst_vorbis_tag_add (list, "GENRE", "Goo"); + gst_vorbis_tag_add (list, "CONTACT", "Coo"); + gst_vorbis_tag_add (list, "COMMENT", "Stroodle is good"); + gst_vorbis_tag_add (list, "COMMENT", "Peroxysulfid stroodles the brain"); + + gst_vorbis_tag_add (list, "TRACKNUMBER", "5"); + gst_vorbis_tag_add (list, "TRACKTOTAL", "77"); + gst_vorbis_tag_add (list, "DISCNUMBER", "1"); + gst_vorbis_tag_add (list, "DISCTOTAL", "2"); + gst_vorbis_tag_add (list, "DATE", "1954-12-31"); + + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_TITLE, "Too"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ALBUM, "Aoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "Alboo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_PERFORMER, "Perfoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COPYRIGHT, "Copyfoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_DESCRIPTION, "Descoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE, "Licoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LICENSE_URI, + "http://creativecommons.org/licenses/by/3.0/"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GEO_LOCATION_NAME, "Bristol, UK"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ORGANIZATION, "Orgoo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_GENRE, "Goo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_CONTACT, "Coo"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT, + "Peroxysulfid stroodles the brain"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_COMMENT, "Stroodle is good"); + ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_NUMBER, 5); + ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_TRACK_COUNT, 77); + ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_NUMBER, 1); + ASSERT_TAG_LIST_HAS_UINT (list, GST_TAG_ALBUM_VOLUME_COUNT, 2); + + { + GDate *date = NULL; + + fail_unless (gst_tag_list_get_date (list, GST_TAG_DATE, &date)); + fail_unless (date != NULL); + fail_unless (g_date_get_day (date) == 31); + fail_unless (g_date_get_month (date) == G_DATE_DECEMBER); + fail_unless (g_date_get_year (date) == 1954); + + g_date_free (date); + } + + /* unknown vorbis comments should go into a GST_TAG_EXTENDED_COMMENT */ + gst_vorbis_tag_add (list, "CoEdSub_ID", "98172AF-973-10-B"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT, + "CoEdSub_ID=98172AF-973-10-B"); + gst_vorbis_tag_add (list, "RuBuWuHash", "1337BA42F91"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_EXTENDED_COMMENT, + "RuBuWuHash=1337BA42F91"); + + gst_vorbis_tag_add (list, "REPLAYGAIN_REFERENCE_LOUDNESS", "89."); + ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_REFERENCE_LEVEL, 89.); + gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_GAIN", "+12.36"); + ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_GAIN, +12.36); + gst_vorbis_tag_add (list, "REPLAYGAIN_TRACK_PEAK", "0.96349"); + ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_TRACK_PEAK, 0.96349); + gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_GAIN", "+10.12"); + ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_GAIN, +10.12); + /* now check that we can parse floating point numbers with any separator + * (',' or '.') regardless of the current locale */ + gst_vorbis_tag_add (list, "REPLAYGAIN_ALBUM_PEAK", "0,98107"); + ASSERT_TAG_LIST_HAS_DOUBLE (list, GST_TAG_ALBUM_PEAK, 0.98107); + gst_vorbis_tag_add (list, "LICENSE", "http://foo.com/license-1.html"); + + /* make sure we can convert back and forth without loss */ + { + GstTagList *new_list, *even_newer_list; + GstBuffer *buf, *buf2; + gchar *vendor_id = NULL; + + buf = gst_tag_list_to_vorbiscomment_buffer (list, + (const guint8 *) "\003vorbis", 7, "libgstunittest"); + fail_unless (buf != NULL); + new_list = gst_tag_list_from_vorbiscomment_buffer (buf, + (const guint8 *) "\003vorbis", 7, &vendor_id); + fail_unless (new_list != NULL); + fail_unless (vendor_id != NULL); + g_free (vendor_id); + vendor_id = NULL; + + GST_LOG ("new_list = %" GST_PTR_FORMAT, new_list); + fail_unless (taglists_are_equal (list, new_list)); + + buf2 = gst_tag_list_to_vorbiscomment_buffer (new_list, + (const guint8 *) "\003vorbis", 7, "libgstunittest"); + fail_unless (buf2 != NULL); + even_newer_list = gst_tag_list_from_vorbiscomment_buffer (buf2, + (const guint8 *) "\003vorbis", 7, &vendor_id); + fail_unless (even_newer_list != NULL); + fail_unless (vendor_id != NULL); + g_free (vendor_id); + vendor_id = NULL; + + GST_LOG ("even_newer_list = %" GST_PTR_FORMAT, even_newer_list); + fail_unless (taglists_are_equal (new_list, even_newer_list)); + + gst_tag_list_free (new_list); + gst_tag_list_free (even_newer_list); + gst_buffer_unref (buf); + gst_buffer_unref (buf2); + } + + /* there can only be one language per taglist ... */ + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "fr"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr"); + + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "[fr]"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr"); + + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "French [fr]"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "fr"); + + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "[eng] English"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng"); + + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "eng"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng"); + + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "[eng]"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "eng"); + + /* free-form *sigh* */ + gst_tag_list_free (list); + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "LANGUAGE", "English"); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_LANGUAGE_CODE, "English"); + + /* now, while we still have a taglist, test _to_vorbiscomment_buffer() */ + { + GstBuffer *buf1, *buf2; + + ASSERT_CRITICAL (gst_tag_list_to_vorbiscomment_buffer (NULL, + (const guint8 *) "x", 1, "x")); + + buf1 = gst_tag_list_to_vorbiscomment_buffer (list, NULL, 0, NULL); + fail_unless (buf1 != NULL); + + buf2 = gst_tag_list_to_vorbiscomment_buffer (list, + (const guint8 *) "foo", 3, NULL); + fail_unless (buf2 != NULL); + + fail_unless (memcmp (GST_BUFFER_DATA (buf1), GST_BUFFER_DATA (buf2) + 3, + GST_BUFFER_SIZE (buf1)) == 0); + + gst_buffer_unref (buf1); + gst_buffer_unref (buf2); + } + + gst_tag_list_free (list); + + /* make sure gst_tag_list_from_vorbiscomment_buffer() works with an + * empty ID (for Speex) */ + { + const guint8 speex_comments_buf1[] = { 0x03, 0x00, 0x00, 0x00, 'f', 'o', + 'o', 0x00, 0x00, 0x00, 0x00 + }; + GstBuffer *buf; + gchar *vendor = NULL; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) speex_comments_buf1; + GST_BUFFER_SIZE (buf) = sizeof (speex_comments_buf1); + + /* make sure it doesn't memcmp over the end of the buffer */ + fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf, + (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39, + &vendor) == NULL); + fail_unless (vendor == NULL); + + /* make sure it bails out if the ID doesn't match */ + fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf, + (guint8 *) "short", 4, &vendor) == NULL); + fail_unless (vendor == NULL); + + /* now read properly */ + list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, &vendor); + fail_unless (vendor != NULL); + fail_unless_equals_string (vendor, "foo"); + fail_unless (list != NULL); + fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0); + g_free (vendor); + gst_tag_list_free (list); + + /* now again without vendor */ + list = gst_tag_list_from_vorbiscomment_buffer (buf, NULL, 0, NULL); + fail_unless (list != NULL); + fail_unless (gst_structure_n_fields ((GstStructure *) list) == 0); + gst_tag_list_free (list); + + gst_buffer_unref (buf); + } + + /* the same with an ID */ + { + const guint8 vorbis_comments_buf[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', + 0x03, 0x00, 0x00, 0x00, 'f', 'o', 'o', 0x01, 0x00, 0x00, 0x00, + strlen ("ARTIST=foo bar"), 0x00, 0x00, 0x00, 'A', 'R', 'T', 'I', 'S', + 'T', '=', 'f', 'o', 'o', ' ', 'b', 'a', 'r' + }; + GstBuffer *buf; + gchar *vendor = NULL; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) vorbis_comments_buf; + GST_BUFFER_SIZE (buf) = sizeof (vorbis_comments_buf); + + /* make sure it doesn't memcmp over the end of the buffer */ + fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf, + (const guint8 *) "averylongstringbrownfoxjumpoverthefence", 39, + &vendor) == NULL); + fail_unless (vendor == NULL); + + /* make sure it bails out if the ID doesn't match */ + fail_unless (gst_tag_list_from_vorbiscomment_buffer (buf, + (guint8 *) "short", 4, &vendor) == NULL); + fail_unless (vendor == NULL); + + /* now read properly */ + list = gst_tag_list_from_vorbiscomment_buffer (buf, + (guint8 *) "\003vorbis", 7, &vendor); + fail_unless (vendor != NULL); + fail_unless_equals_string (vendor, "foo"); + fail_unless (list != NULL); + fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar"); + g_free (vendor); + gst_tag_list_free (list); + + /* now again without vendor */ + list = gst_tag_list_from_vorbiscomment_buffer (buf, + (guint8 *) "\003vorbis", 7, NULL); + fail_unless (list != NULL); + fail_unless (gst_structure_n_fields ((GstStructure *) list) == 1); + ASSERT_TAG_LIST_HAS_STRING (list, GST_TAG_ARTIST, "foo bar"); + gst_tag_list_free (list); + + gst_buffer_unref (buf); + } + + /* check date with time */ + { + GDate *date = NULL; + + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "DATE", "2006-09-25 22:02:38"); + + fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date)); + fail_unless (date != NULL); + fail_unless (g_date_get_day (date) == 25); + fail_unless (g_date_get_month (date) == G_DATE_SEPTEMBER); + fail_unless (g_date_get_year (date) == 2006); + + g_date_free (date); + gst_tag_list_free (list); + } + + /* check date with month/day of 00-00 */ + { + GDate *date = NULL; + + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "DATE", "1992-00-00"); + + fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date)); + fail_unless (date != NULL); + fail_unless (g_date_get_year (date) == 1992); + + g_date_free (date); + gst_tag_list_free (list); + } + + /* check date with valid month, but day of 00 */ + { + GDate *date = NULL; + + list = gst_tag_list_new (); + gst_vorbis_tag_add (list, "DATE", "1992-05-00"); + + fail_unless (gst_tag_list_get_date_index (list, GST_TAG_DATE, 0, &date)); + fail_unless (date != NULL); + fail_unless (g_date_get_year (date) == 1992); + fail_unless (g_date_get_month (date) == G_DATE_MAY); + + g_date_free (date); + gst_tag_list_free (list); + } +} + +GST_END_TEST; + +GST_START_TEST (test_id3_tags) +{ + guint i; + + fail_unless (gst_tag_id3_genre_count () > 0); + + for (i = 0; i < gst_tag_id3_genre_count (); ++i) { + const gchar *genre; + + genre = gst_tag_id3_genre_get (i); + fail_unless (genre != NULL); + } + + { + /* TODO: GstTagList *gst_tag_list_new_from_id3v1 (const guint8 *data) */ + } + + /* gst_tag_from_id3_tag */ + fail_unless (gst_tag_from_id3_tag ("TALB") != NULL); + ASSERT_CRITICAL (gst_tag_from_id3_tag (NULL)); + fail_unless (gst_tag_from_id3_tag ("R2D2") == NULL); + fail_unless_equals_string (gst_tag_from_id3_tag ("WCOP"), + GST_TAG_COPYRIGHT_URI); + + /* gst_tag_from_id3_user_tag */ + ASSERT_CRITICAL (gst_tag_from_id3_user_tag (NULL, "foo")); + ASSERT_CRITICAL (gst_tag_from_id3_user_tag ("foo", NULL)); + fail_unless (gst_tag_from_id3_user_tag ("R2D2", "R2D2") == NULL); + + /* gst_tag_to_id3_tag */ + ASSERT_CRITICAL (gst_tag_to_id3_tag (NULL)); + fail_unless (gst_tag_to_id3_tag ("R2D2") == NULL); + fail_unless (gst_tag_to_id3_tag (GST_TAG_ARTIST) != NULL); + fail_unless_equals_string (gst_tag_to_id3_tag (GST_TAG_COPYRIGHT_URI), + "WCOP"); + + fail_unless (GST_TYPE_TAG_IMAGE_TYPE != 0); + fail_unless (g_type_name (GST_TYPE_TAG_IMAGE_TYPE) != NULL); +} + +GST_END_TEST; + + +GST_START_TEST (test_id3v1_utf8_tag) +{ + const guint8 id3v1[128] = { + /* marker */ + 'T', 'A', 'G', + /* title (30 bytes) */ + 'D', 0xc3, 0xad, 'v', 'k', 'a', ' ', 's', + ' ', 'p', 'e', 'r', 'l', 'a', 'm', 'i', + ' ', 'v', 'e', ' ', 'v', 'l', 'a', 's', + 'e', 'c', 'h', 0, 0, 0, + /* artist (30 bytes) */ + 'A', 'l', 'e', 0xc5, 0xa1, ' ', 'B', 'r', 'i', 'c', 'h', 't', 'a', + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* album (30 bytes) */ + 'B', 'e', 's', 't', ' ', 'o', 'f', ' ', '(', 'P', 'r', 'o', 's', 't', + 0xc4, 0x9b, ' ', 0xc3, 0xba, 0xc5, 0xbe, 'a', 's', 'n', 0xc3, 0xbd, ')', + 0, 0, 0, + /* year (4 bytes) */ + '2', '0', '0', '0', + /* comment (28 bytes) */ + '-', '-', '-', ' ', 0xc4, 0x8d, 'e', 's', 'k', 0xc3, 0xa9, ' ', 'p', + 0xc3, 0xad, 's', 'n', 'i', 0xc4, 0x8d, 'k', 'y', ' ', '-', '-', '-', + 0, 0, + /* track number */ + 0, 0, + /* genre */ + 0x11 + }; + GstTagList *tags; + GDate *d; + gchar *s; + + /* set this, to make sure UTF-8 strings are really interpreted properly + * as UTF-8, regardless of the locale set */ + g_setenv ("GST_ID3V1_TAG_ENCODING", "WINDOWS-1250", TRUE); + + tags = gst_tag_list_new_from_id3v1 (id3v1); + fail_unless (tags != NULL); + + GST_LOG ("Got tags: %" GST_PTR_FORMAT, tags); + + s = NULL; + fail_unless (gst_tag_list_get_string (tags, GST_TAG_TITLE, &s)); + fail_unless (s != NULL); + fail_unless_equals_string (s, "Dívka s perlami ve vlasech"); + g_free (s); + + s = NULL; + fail_unless (gst_tag_list_get_string (tags, GST_TAG_ARTIST, &s)); + fail_unless (s != NULL); + fail_unless_equals_string (s, "AleÅ¡ Brichta"); + g_free (s); + + s = NULL; + fail_unless (gst_tag_list_get_string (tags, GST_TAG_ALBUM, &s)); + fail_unless (s != NULL); + fail_unless_equals_string (s, "Best of (Prostě úžasný)"); + g_free (s); + + d = NULL; + fail_unless (gst_tag_list_get_date (tags, GST_TAG_DATE, &d)); + fail_unless (d != NULL); + fail_unless_equals_int (g_date_get_year (d), 2000); + g_date_free (d); + d = NULL; + + gst_tag_list_free (tags); + + g_unsetenv ("GST_ID3V1_TAG_ENCODING"); +} + +GST_END_TEST; + +GST_START_TEST (test_language_utils) +{ + gchar **lang_codes, **c; + +#define ASSERT_STRINGS_EQUAL fail_unless_equals_string + + lang_codes = gst_tag_get_language_codes (); + fail_unless (lang_codes != NULL); + fail_unless (*lang_codes != NULL); + + for (c = lang_codes; c != NULL && *c != NULL; ++c) { + const gchar *lang_name, *c1, *c2t, *c2b; + + lang_name = gst_tag_get_language_name (*c); + fail_unless (lang_name != NULL); + fail_unless (g_utf8_validate (lang_name, -1, NULL)); + + c1 = gst_tag_get_language_code_iso_639_1 (*c); + fail_unless (c1 != NULL); + fail_unless (g_utf8_validate (c1, -1, NULL)); + + c2t = gst_tag_get_language_code_iso_639_2T (*c); + fail_unless (c2t != NULL); + fail_unless (g_utf8_validate (c2t, -1, NULL)); + + c2b = gst_tag_get_language_code_iso_639_2B (*c); + fail_unless (c2b != NULL); + fail_unless (g_utf8_validate (c2b, -1, NULL)); + + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (*c), *c); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2t), *c); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 (c2b), *c); + + GST_DEBUG ("[%s] %s %s %s : %s\n", *c, c1, c2t, c2b, lang_name); + + } + g_strfreev (lang_codes); + + fail_unless (gst_tag_get_language_name ("de") != NULL); + fail_unless (gst_tag_get_language_name ("deu") != NULL); + fail_unless (gst_tag_get_language_name ("ger") != NULL); + fail_unless_equals_string (gst_tag_get_language_name ("deu"), + gst_tag_get_language_name ("ger")); + fail_unless_equals_string (gst_tag_get_language_name ("de"), + gst_tag_get_language_name ("ger")); + fail_unless (gst_tag_get_language_name ("de") != + gst_tag_get_language_name ("fr")); + + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("deu"), "de"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("de"), "de"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code ("ger"), "de"); + + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("deu"), "de"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("de"), "de"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_1 ("ger"), "de"); + + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("de"), "deu"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("deu"), "deu"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2T ("ger"), "deu"); + + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("de"), "ger"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("deu"), "ger"); + ASSERT_STRINGS_EQUAL (gst_tag_get_language_code_iso_639_2B ("ger"), "ger"); +} + +GST_END_TEST; + +GST_START_TEST (test_xmp_formatting) +{ + GstTagList *list; + GstBuffer *buf; + const gchar *text; + guint len; + + /* test data */ + list = gst_tag_list_new_full (GST_TAG_TITLE, "test title", + GST_TAG_DESCRIPTION, "test decription", + GST_TAG_KEYWORDS, "keyword1", GST_TAG_KEYWORDS, "keyword2", NULL); + + buf = gst_tag_list_to_xmp_buffer (list, FALSE); + fail_unless (buf != NULL); + + text = (const gchar *) GST_BUFFER_DATA (buf); + len = GST_BUFFER_SIZE (buf); + + /* check the content */ + fail_unless (g_strrstr_len (text, len, "test title<") != NULL); + fail_unless (g_strrstr_len (text, len, ">test decription<") != NULL); + fail_unless (g_strrstr_len (text, len, ">keyword1<") != NULL); + fail_unless (g_strrstr_len (text, len, ">keyword2<") != NULL); + fail_unless (g_strrstr_len (text, len, "" + "" + ""; + const gchar *xmp_footer = + "" "" "\n"; + struct + { + const gchar *xmp_data; + gint result_size; + gint result_test; + } test_data[] = { + { + "", -1, -1}, { + "", 0, -1}, { + "", 0, -1}, { + "", 0, -1}, { + "test", + 1, 0}, { + "", + 1, 0}, { + NULL, -1, -1} + }; + + /* test data */ + buf = gst_buffer_new (); + + i = 0; + while (test_data[i].xmp_data) { + GST_DEBUG ("trying test-data %u", i); + + text = g_strconcat (xmp_header, test_data[i].xmp_data, xmp_footer, NULL); + GST_BUFFER_DATA (buf) = (guint8 *) text; + GST_BUFFER_SIZE (buf) = strlen (text) + 1; + + + list = gst_tag_list_from_xmp_buffer (buf); + if (test_data[i].result_size >= 0) { + fail_unless (list != NULL); + + result_size = gst_structure_n_fields ((GstStructure *) list); + fail_unless (result_size == test_data[i].result_size); + + /* check the taglist content */ + switch (test_data[i].result_test) { + case 0: + ASSERT_TAG_LIST_HAS_STRING (list, "description", "test"); + break; + default: + break; + } + } + if (list) + gst_tag_list_free (list); + + g_free (text); + i++; + } + + gst_buffer_unref (buf); +} + +GST_END_TEST; + +static void +tag_list_equals (GstTagList * taglist, GstTagList * taglist2) +{ + const gchar *name_sent, *name_recv; + const GValue *value_sent, *value_recv; + gboolean found; + gint comparison; + gint n_recv; + gint n_sent; + gint i, j; + + /* verify tags */ + fail_unless (taglist2 != NULL); + n_recv = gst_structure_n_fields (taglist2); + n_sent = gst_structure_n_fields (taglist); + fail_unless (n_recv == n_sent); + fail_unless (n_sent > 0); + + /* FIXME: compare taglist values */ + for (i = 0; i < n_sent; i++) { + name_sent = gst_structure_nth_field_name (taglist, i); + value_sent = gst_structure_get_value (taglist, name_sent); + found = FALSE; + for (j = 0; j < n_recv; j++) { + name_recv = gst_structure_nth_field_name (taglist2, j); + if (!strcmp (name_sent, name_recv)) { + value_recv = gst_structure_get_value (taglist2, 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); + } + if (comparison != GST_VALUE_EQUAL && + G_VALUE_HOLDS (value_sent, G_TYPE_DOUBLE)) { + gdouble vs; + gdouble vr; + + /* add some tolerance for doubles */ + vs = g_value_get_double (value_sent); + vr = g_value_get_double (value_recv); + if (vr >= vs - 0.001 && vr <= vs + 0.001) + comparison = GST_VALUE_EQUAL; + } + 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); + } +} + +static void +do_xmp_tag_serialization_deserialization (GstTagList * taglist) +{ + GstTagList *taglist2; + GstBuffer *buf; + + buf = gst_tag_list_to_xmp_buffer (taglist, TRUE); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + + tag_list_equals (taglist, taglist2); + + gst_buffer_unref (buf); + gst_tag_list_free (taglist2); +} + +static void +do_simple_xmp_tag_serialization_deserialization (const gchar * gsttag, + GValue * value) +{ + GstTagList *taglist = gst_tag_list_new (); + + gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value); + + do_xmp_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); +} + +GST_START_TEST (test_xmp_tags_serialization_deserialization) +{ + GValue value = { 0 }; + GDate *date; + GstDateTime *datetime; + + gst_tag_register_musicbrainz_tags (); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, "my string"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY, + &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY, + &value); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_SUBLOCATION, &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MANUFACTURER, + &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DEVICE_MODEL, + &value); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME, + &value); + + g_value_set_static_string (&value, "rotate-0"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-0"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-180"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-180"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-270"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-90"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-90"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-270"); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + + g_value_unset (&value); + g_value_init (&value, G_TYPE_DOUBLE); + + g_value_set_double (&value, 0.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LATITUDE, &value); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + g_value_set_double (&value, 10.5); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LATITUDE, &value); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + g_value_set_double (&value, -32.375); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LATITUDE, &value); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + + g_value_set_double (&value, 0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + g_value_set_double (&value, 100); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + g_value_set_double (&value, 500.25); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + g_value_set_double (&value, -12.75); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + + g_value_set_double (&value, 0.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + g_value_set_double (&value, 10.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + g_value_set_double (&value, 786.125); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + g_value_set_double (&value, -2.5); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + + g_value_set_double (&value, 0.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value); + g_value_set_double (&value, 180.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value); + g_value_set_double (&value, 359.99); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value); + + g_value_set_double (&value, 0.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value); + g_value_set_double (&value, 90.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value); + g_value_set_double (&value, 359.99); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value); + + g_value_set_double (&value, 0.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_set_double (&value, 1.0); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_set_double (&value, -2.5); + do_simple_xmp_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_DATE); + date = g_date_new_dmy (22, 3, 2010); + gst_value_set_date (&value, date); + g_date_free (date); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_UINT); + g_value_set_uint (&value, 0); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value); + g_value_set_uint (&value, 100); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value); + g_value_set_uint (&value, 22); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_USER_RATING, &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_DATE_TIME); + datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000125); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.000001); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new (0, 2010, 6, 22, 12, 5, 10.123456); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new (-3, 2010, 6, 22, 12, 5, 10.123456); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new (5, 2010, 6, 22, 12, 5, 10.123456); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + datetime = gst_date_time_new_local_time (2010, 12, 2, 12, 5, 10.000043); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_xmp_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + g_value_unset (&value); +} + +GST_END_TEST; + + +GST_START_TEST (test_xmp_compound_tags) +{ + GstTagList *taglist = gst_tag_list_new (); + + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_KEYWORDS, "k1", + GST_TAG_KEYWORDS, "k2", GST_TAG_TITLE, "title", GST_TAG_KEYWORDS, "k3", + NULL); + + do_xmp_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_exif_parsing) +{ + GstTagList *taglist; + GstBuffer *buf; + GstByteWriter writer; + const gchar *str; + + gst_byte_writer_init (&writer); + + /* write the IFD */ + /* 1 entry */ + gst_byte_writer_put_uint16_le (&writer, 1); + + /* copyright tag */ + /* tag id */ + gst_byte_writer_put_uint16_le (&writer, 0x8298); + /* tag type */ + gst_byte_writer_put_uint16_le (&writer, 0x2); + /* count */ + gst_byte_writer_put_uint32_le (&writer, strlen ("my copyright") + 1); + /* offset */ + gst_byte_writer_put_uint32_le (&writer, 8 + 14); + + /* data */ + gst_byte_writer_put_string (&writer, "my copyright"); + + buf = gst_byte_writer_reset_and_get_buffer (&writer); + + taglist = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 8); + + fail_unless (gst_structure_n_fields (taglist) == 1); + fail_unless (gst_structure_has_field_typed (taglist, GST_TAG_COPYRIGHT, + G_TYPE_STRING)); + str = gst_structure_get_string (taglist, GST_TAG_COPYRIGHT); + fail_unless (strcmp (str, "my copyright") == 0); + + gst_tag_list_free (taglist); + gst_buffer_unref (buf); +} + +GST_END_TEST; + + +static void +do_exif_tag_serialization_deserialization (GstTagList * taglist) +{ + GstTagList *taglist2; + GstBuffer *buf; + + /* LE */ + buf = gst_tag_list_to_exif_buffer (taglist, G_LITTLE_ENDIAN, 0); + taglist2 = gst_tag_list_from_exif_buffer (buf, G_LITTLE_ENDIAN, 0); + gst_buffer_unref (buf); + + tag_list_equals (taglist, taglist2); + gst_tag_list_free (taglist2); + + /* BE */ + buf = gst_tag_list_to_exif_buffer (taglist, G_BIG_ENDIAN, 0); + taglist2 = gst_tag_list_from_exif_buffer (buf, G_BIG_ENDIAN, 0); + gst_buffer_unref (buf); + + tag_list_equals (taglist, taglist2); + gst_tag_list_free (taglist2); + + /* APP1 */ + buf = gst_tag_list_to_exif_buffer_with_tiff_header (taglist); + taglist2 = gst_tag_list_from_exif_buffer_with_tiff_header (buf); + gst_buffer_unref (buf); + + tag_list_equals (taglist, taglist2); + gst_tag_list_free (taglist2); +} + +static void +do_simple_exif_tag_serialization_deserialization (const gchar * gsttag, + GValue * value) +{ + GstTagList *taglist = gst_tag_list_new (); + + gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value); + + do_exif_tag_serialization_deserialization (taglist); + + gst_tag_list_free (taglist); +} + +/* + * Adds tags from multiple ifd tables and tries serializing them + */ +GST_START_TEST (test_exif_multiple_tags) +{ + GstTagList *taglist; + GstDateTime *datetime; + GValue value = { 0 }; + + gst_tag_register_musicbrainz_tags (); + + taglist = gst_tag_list_new_full (GST_TAG_ARTIST, "artist", + GST_TAG_DEVICE_MANUFACTURER, "make", + GST_TAG_DEVICE_MODEL, "model", GST_TAG_GEO_LOCATION_LATITUDE, 45.5, + GST_TAG_GEO_LOCATION_LONGITUDE, -10.25, + GST_TAG_IMAGE_HORIZONTAL_PPI, 300.0, + GST_TAG_IMAGE_VERTICAL_PPI, 300.0, NULL); + + g_value_init (&value, GST_TYPE_DATE_TIME); + datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, GST_TAG_DATE_TIME, + &value); + g_value_unset (&value); + + do_exif_tag_serialization_deserialization (taglist); + + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_exif_tags_serialization_deserialization) +{ + GValue value = { 0 }; + GstDateTime *datetime = NULL; + GstBuffer *buf = NULL; + gint i; + GstTagList *taglist; + + gst_tag_register_musicbrainz_tags (); + + g_value_init (&value, G_TYPE_STRING); + g_value_set_static_string (&value, "my string"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value); + g_value_set_static_string (&value, "ty"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_ARTIST, &value); + g_value_set_static_string (&value, "Company Software 1.2b (info)"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_NAME, + &value); + + /* image orientation tests */ + g_value_set_static_string (&value, "rotate-0"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-0"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-180"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-180"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-270"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-90"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "flip-rotate-90"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + g_value_set_static_string (&value, "rotate-270"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_IMAGE_ORIENTATION, + &value); + + /* exposure program */ + g_value_set_static_string (&value, "undefined"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "manual"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "normal"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "aperture-priority"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "shutter-priority"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "creative"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "action"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "portrait"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + g_value_set_static_string (&value, "landscape"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_PROGRAM, &value); + + /* exposure mode */ + g_value_set_static_string (&value, "auto-exposure"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_MODE, &value); + g_value_set_static_string (&value, "manual-exposure"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_MODE, &value); + g_value_set_static_string (&value, "auto-bracket"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_MODE, &value); + + /* scene capture type */ + g_value_set_static_string (&value, "standard"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value); + g_value_set_static_string (&value, "portrait"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value); + g_value_set_static_string (&value, "landscape"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value); + g_value_set_static_string (&value, "night-scene"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SCENE_CAPTURE_TYPE, &value); + + g_value_set_static_string (&value, "none"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value); + g_value_set_static_string (&value, "high-gain-up"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value); + g_value_set_static_string (&value, "low-gain-up"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value); + g_value_set_static_string (&value, "high-gain-down"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value); + g_value_set_static_string (&value, "low-gain-down"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_GAIN_ADJUSTMENT, &value); + + g_value_set_static_string (&value, "auto"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_WHITE_BALANCE, &value); + g_value_set_static_string (&value, "manual"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_WHITE_BALANCE, &value); + + g_value_set_static_string (&value, "normal"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST, + &value); + g_value_set_static_string (&value, "hard"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST, + &value); + g_value_set_static_string (&value, "soft"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_CONTRAST, + &value); + + g_value_set_static_string (&value, "normal"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); + g_value_set_static_string (&value, "low-saturation"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); + g_value_set_static_string (&value, "high-saturation"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SATURATION, &value); + + g_value_set_static_string (&value, "normal"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS, + &value); + g_value_set_static_string (&value, "hard"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS, + &value); + g_value_set_static_string (&value, "soft"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SHARPNESS, + &value); + + g_value_set_static_string (&value, "unknown"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "average"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "center-weighted-average"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "spot"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "multi-spot"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "pattern"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "partial"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + g_value_set_static_string (&value, "other"); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_METERING_MODE, &value); + + g_value_set_static_string (&value, "dsc"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE, + &value); + g_value_set_static_string (&value, "other"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE, + &value); + g_value_set_static_string (&value, "transparent-scanner"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE, + &value); + g_value_set_static_string (&value, "reflex-scanner"); + do_simple_exif_tag_serialization_deserialization (GST_TAG_CAPTURING_SOURCE, + &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_DOUBLE); + g_value_set_double (&value, 30.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LATITUDE, &value); + g_value_set_double (&value, -12.125); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LATITUDE, &value); + g_value_set_double (&value, 0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + g_value_set_double (&value, 65.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + g_value_set_double (&value, -0.75); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_LONGITUDE, &value); + + g_value_set_double (&value, 0.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value); + g_value_set_double (&value, 180.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, &value); + g_value_set_double (&value, 0.12345); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value); + g_value_set_double (&value, 359.9); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, &value); + + g_value_set_double (&value, 0.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + g_value_set_double (&value, 321.456); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + g_value_set_double (&value, -12.56); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_ELEVATION, &value); + + g_value_set_double (&value, 0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + g_value_set_double (&value, 100 / 3.6); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value); + + g_value_set_double (&value, 0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value); + g_value_set_double (&value, 50.25); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_GEO_LOCATION_HORIZONTAL_ERROR, &value); + + g_value_set_double (&value, 0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value); + g_value_set_double (&value, 2.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value); + g_value_set_double (&value, 8.75); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_DIGITAL_ZOOM_RATIO, &value); + + g_value_set_double (&value, 20.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_FOCAL_LENGTH, &value); + g_value_set_double (&value, 5.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_FOCAL_LENGTH, &value); + + g_value_set_double (&value, 16); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_FOCAL_RATIO, &value); + g_value_set_double (&value, 2.7); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_FOCAL_LENGTH, &value); + + g_value_set_double (&value, 96.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_HORIZONTAL_PPI, &value); + g_value_set_double (&value, 300.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_HORIZONTAL_PPI, &value); + g_value_set_double (&value, 87.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_VERTICAL_PPI, &value); + g_value_set_double (&value, 600.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_IMAGE_VERTICAL_PPI, &value); + + g_value_set_double (&value, 0.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_set_double (&value, 1.0); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_set_double (&value, -2.5); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, &value); + g_value_unset (&value); + + g_value_init (&value, G_TYPE_INT); + g_value_set_int (&value, 400); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_ISO_SPEED, &value); + g_value_set_int (&value, 1600); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_ISO_SPEED, &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_DATE_TIME); + datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10); + g_value_set_boxed (&value, datetime); + gst_date_time_unref (datetime); + do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_new_and_alloc (1024); + for (i = 0; i < 1024; i++) + GST_BUFFER_DATA (buf)[i] = i % 255; + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA, + &value); + g_value_unset (&value); + + g_value_init (&value, GST_TYPE_FRACTION); + gst_value_set_fraction (&value, 1, 1); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SHUTTER_SPEED, &value); + gst_value_set_fraction (&value, 1, 30); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SHUTTER_SPEED, &value); + gst_value_set_fraction (&value, 1, 200); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SHUTTER_SPEED, &value); + gst_value_set_fraction (&value, 1, 8000); + do_simple_exif_tag_serialization_deserialization + (GST_TAG_CAPTURING_SHUTTER_SPEED, &value); + g_value_unset (&value); + + /* flash is a little bit more tricky, because 2 tags are merged into 1 in + * exif */ + taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, FALSE, + GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL); + do_exif_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); + + taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, TRUE, + GST_TAG_CAPTURING_FLASH_MODE, "auto", NULL); + do_exif_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); + + taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, FALSE, + GST_TAG_CAPTURING_FLASH_MODE, "never", NULL); + do_exif_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); + + taglist = gst_tag_list_new_full (GST_TAG_CAPTURING_FLASH_FIRED, TRUE, + GST_TAG_CAPTURING_FLASH_MODE, "always", NULL); + do_exif_tag_serialization_deserialization (taglist); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + +static Suite * +tag_suite (void) +{ + Suite *s = suite_create ("tag support library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_musicbrainz_tag_registration); + tcase_add_test (tc_chain, test_parse_extended_comment); + tcase_add_test (tc_chain, test_vorbis_tags); + tcase_add_test (tc_chain, test_id3_tags); + tcase_add_test (tc_chain, test_id3v1_utf8_tag); + tcase_add_test (tc_chain, test_language_utils); + tcase_add_test (tc_chain, test_xmp_formatting); + tcase_add_test (tc_chain, test_xmp_parsing); + tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization); + tcase_add_test (tc_chain, test_xmp_compound_tags); + tcase_add_test (tc_chain, test_exif_parsing); + tcase_add_test (tc_chain, test_exif_tags_serialization_deserialization); + tcase_add_test (tc_chain, test_exif_multiple_tags); + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = tag_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/gst-plugins-base-subtitles0.10/tests/check/libs/video.c b/gst-plugins-base-subtitles0.10/tests/check/libs/video.c new file mode 100644 index 0000000..05b840c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/video.c @@ -0,0 +1,770 @@ +/* GStreamer unit test for video + * + * Copyright (C) <2003> David A. Schleef + * Copyright (C) <2006> Jan Schmidt + * Copyright (C) <2008> Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#include +#include + +/* These are from the current/old videotestsrc; we check our new public API + * in libgstvideo against the old one to make sure the sizes and offsets + * end up the same */ + +typedef struct paintinfo_struct paintinfo; +struct paintinfo_struct +{ + unsigned char *dest; /* pointer to first byte of video data */ + unsigned char *yp, *up, *vp; /* pointers to first byte of each component + * for both packed/planar YUV and RGB */ + unsigned char *ap; /* pointer to first byte of alpha component */ + unsigned char *endptr; /* pointer to byte beyond last video data */ + int ystride; + int ustride; + int vstride; + int width; + int height; +}; + +struct fourcc_list_struct +{ + const char *fourcc; + const char *name; + int bitspp; + void (*paint_setup) (paintinfo * p, unsigned char *dest); +}; + +static void paint_setup_I420 (paintinfo * p, unsigned char *dest); +static void paint_setup_YV12 (paintinfo * p, unsigned char *dest); +static void paint_setup_YUY2 (paintinfo * p, unsigned char *dest); +static void paint_setup_UYVY (paintinfo * p, unsigned char *dest); +static void paint_setup_YVYU (paintinfo * p, unsigned char *dest); +static void paint_setup_IYU2 (paintinfo * p, unsigned char *dest); +static void paint_setup_Y41B (paintinfo * p, unsigned char *dest); +static void paint_setup_Y42B (paintinfo * p, unsigned char *dest); +static void paint_setup_Y800 (paintinfo * p, unsigned char *dest); +static void paint_setup_AYUV (paintinfo * p, unsigned char *dest); + +#if 0 +static void paint_setup_IMC1 (paintinfo * p, unsigned char *dest); +static void paint_setup_IMC2 (paintinfo * p, unsigned char *dest); +static void paint_setup_IMC3 (paintinfo * p, unsigned char *dest); +static void paint_setup_IMC4 (paintinfo * p, unsigned char *dest); +#endif +static void paint_setup_YUV9 (paintinfo * p, unsigned char *dest); +static void paint_setup_YVU9 (paintinfo * p, unsigned char *dest); + +int fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h); + +struct fourcc_list_struct fourcc_list[] = { +/* packed */ + {"YUY2", "YUY2", 16, paint_setup_YUY2}, + {"UYVY", "UYVY", 16, paint_setup_UYVY}, + {"Y422", "Y422", 16, paint_setup_UYVY}, + {"UYNV", "UYNV", 16, paint_setup_UYVY}, /* FIXME: UYNV? */ + {"YVYU", "YVYU", 16, paint_setup_YVYU}, + {"AYUV", "AYUV", 32, paint_setup_AYUV}, + + /* interlaced */ + /*{ "IUYV", "IUY2", 16, paint_setup_YVYU }, */ + + /* inverted */ + /*{ "cyuv", "cyuv", 16, paint_setup_YVYU }, */ + + /*{ "Y41P", "Y41P", 12, paint_setup_YVYU }, */ + + /* interlaced */ + /*{ "IY41", "IY41", 12, paint_setup_YVYU }, */ + + /*{ "Y211", "Y211", 8, paint_setup_YVYU }, */ + + /*{ "Y41T", "Y41T", 12, paint_setup_YVYU }, */ + /*{ "Y42P", "Y42P", 16, paint_setup_YVYU }, */ + /*{ "CLJR", "CLJR", 8, paint_setup_YVYU }, */ + /*{ "IYU1", "IYU1", 12, paint_setup_YVYU }, */ + {"IYU2", "IYU2", 24, paint_setup_IYU2}, + +/* planar */ + /* YVU9 */ + {"YVU9", "YVU9", 9, paint_setup_YVU9}, + /* YUV9 */ + {"YUV9", "YUV9", 9, paint_setup_YUV9}, + /* IF09 */ + /* YV12 */ + {"YV12", "YV12", 12, paint_setup_YV12}, + /* I420 */ + {"I420", "I420", 12, paint_setup_I420}, + /* NV12 */ + /* NV21 */ +#if 0 + /* IMC1 */ + {"IMC1", "IMC1", 16, paint_setup_IMC1}, + /* IMC2 */ + {"IMC2", "IMC2", 12, paint_setup_IMC2}, + /* IMC3 */ + {"IMC3", "IMC3", 16, paint_setup_IMC3}, + /* IMC4 */ + {"IMC4", "IMC4", 12, paint_setup_IMC4}, +#endif + /* CLPL */ + /* Y41B */ + {"Y41B", "Y41B", 12, paint_setup_Y41B}, + /* Y42B */ + {"Y42B", "Y42B", 16, paint_setup_Y42B}, + /* Y800 grayscale */ + {"Y800", "Y800", 8, paint_setup_Y800} +}; + +/* returns the size in bytes for one video frame of the given dimensions + * given the fourcc */ +int +fourcc_get_size (struct fourcc_list_struct *fourcc, int w, int h) +{ + paintinfo pi = { NULL, }; + paintinfo *p = π + + p->width = w; + p->height = h; + + fourcc->paint_setup (p, NULL); + + return (unsigned long) p->endptr; +} + +static void +paint_setup_I420 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->ustride = GST_ROUND_UP_8 (p->width) / 2; + p->vp = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2; + p->vstride = GST_ROUND_UP_8 (p->ystride) / 2; + p->endptr = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2; +} + +static void +paint_setup_YV12 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->vp = p->yp + p->ystride * GST_ROUND_UP_2 (p->height); + p->vstride = GST_ROUND_UP_8 (p->ystride) / 2; + p->up = p->vp + p->vstride * GST_ROUND_UP_2 (p->height) / 2; + p->ustride = GST_ROUND_UP_8 (p->ystride) / 2; + p->endptr = p->up + p->ustride * GST_ROUND_UP_2 (p->height) / 2; +} + +static void +paint_setup_AYUV (paintinfo * p, unsigned char *dest) +{ + p->ap = dest; + p->yp = dest + 1; + p->up = dest + 2; + p->vp = dest + 3; + p->ystride = p->width * 4; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_YUY2 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + 1; + p->vp = dest + 3; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_UYVY (paintinfo * p, unsigned char *dest) +{ + p->yp = dest + 1; + p->up = dest; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_YVYU (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + 3; + p->vp = dest + 1; + p->ystride = GST_ROUND_UP_2 (p->width) * 2; + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_IYU2 (paintinfo * p, unsigned char *dest) +{ + /* untested */ + p->yp = dest + 1; + p->up = dest + 0; + p->vp = dest + 2; + p->ystride = GST_ROUND_UP_4 (p->width * 3); + p->endptr = dest + p->ystride * p->height; +} + +static void +paint_setup_Y41B (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->ustride = GST_ROUND_UP_16 (p->width) / 4; + p->vp = p->up + p->ustride * p->height; + p->vstride = GST_ROUND_UP_16 (p->width) / 4; + p->endptr = p->vp + p->vstride * p->height; +} + +static void +paint_setup_Y42B (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->ustride = GST_ROUND_UP_8 (p->width) / 2; + p->vp = p->up + p->ustride * p->height; + p->vstride = GST_ROUND_UP_8 (p->width) / 2; + p->endptr = p->vp + p->vstride * p->height; +} + +static void +paint_setup_Y800 (paintinfo * p, unsigned char *dest) +{ + /* untested */ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->endptr = dest + p->ystride * p->height; +} + +#if 0 +static void +paint_setup_IMC1 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + p->width * p->height; + p->vp = dest + p->width * p->height + p->width * p->height / 2; +} + +static void +paint_setup_IMC2 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->vp = dest + p->width * p->height; + p->up = dest + p->width * p->height + p->width / 2; +} + +static void +paint_setup_IMC3 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->up = dest + p->width * p->height + p->width * p->height / 2; + p->vp = dest + p->width * p->height; +} + +static void +paint_setup_IMC4 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->vp = dest + p->width * p->height + p->width / 2; + p->up = dest + p->width * p->height; +} +#endif + +static void +paint_setup_YVU9 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->vp = p->yp + p->ystride * p->height; + p->vstride = GST_ROUND_UP_4 (p->ystride / 4); + p->up = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4); + p->ustride = GST_ROUND_UP_4 (p->ystride / 4); + p->endptr = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4); +} + +static void +paint_setup_YUV9 (paintinfo * p, unsigned char *dest) +{ + p->yp = dest; + p->ystride = GST_ROUND_UP_4 (p->width); + p->up = p->yp + p->ystride * p->height; + p->ustride = GST_ROUND_UP_4 (p->ystride / 4); + p->vp = p->up + p->ustride * (GST_ROUND_UP_4 (p->height) / 4); + p->vstride = GST_ROUND_UP_4 (p->ystride / 4); + p->endptr = p->vp + p->vstride * (GST_ROUND_UP_4 (p->height) / 4); +} + +#define gst_video_format_is_packed video_format_is_packed +static gboolean +video_format_is_packed (GstVideoFormat fmt) +{ + switch (fmt) { + case GST_VIDEO_FORMAT_I420: + case GST_VIDEO_FORMAT_YV12: + case GST_VIDEO_FORMAT_Y41B: + case GST_VIDEO_FORMAT_Y42B: + case GST_VIDEO_FORMAT_Y800: + case GST_VIDEO_FORMAT_YUV9: + case GST_VIDEO_FORMAT_YVU9: + return FALSE; + case GST_VIDEO_FORMAT_IYU1: + case GST_VIDEO_FORMAT_YUY2: + case GST_VIDEO_FORMAT_YVYU: + case GST_VIDEO_FORMAT_UYVY: + case GST_VIDEO_FORMAT_AYUV: + case GST_VIDEO_FORMAT_RGBx: + case GST_VIDEO_FORMAT_BGRx: + case GST_VIDEO_FORMAT_xRGB: + case GST_VIDEO_FORMAT_xBGR: + case GST_VIDEO_FORMAT_RGBA: + case GST_VIDEO_FORMAT_BGRA: + case GST_VIDEO_FORMAT_ARGB: + case GST_VIDEO_FORMAT_ABGR: + case GST_VIDEO_FORMAT_RGB: + case GST_VIDEO_FORMAT_BGR: + case GST_VIDEO_FORMAT_RGB8_PALETTED: + return TRUE; + default: + g_return_val_if_reached (FALSE); + } + return FALSE; +} + +GST_START_TEST (test_video_formats) +{ + guint i; + + for (i = 0; i < G_N_ELEMENTS (fourcc_list); ++i) { + GstVideoFormat fmt; + const gchar *s; + guint32 fourcc; + guint w, h; + + s = fourcc_list[i].fourcc; + fourcc = GST_MAKE_FOURCC (s[0], s[1], s[2], s[3]); + fmt = gst_video_format_from_fourcc (fourcc); + + if (fmt == GST_VIDEO_FORMAT_UNKNOWN) + continue; + + GST_INFO ("Fourcc %s, packed=%d", fourcc_list[i].fourcc, + gst_video_format_is_packed (fmt)); + + fail_unless (gst_video_format_is_yuv (fmt)); + + /* use any non-NULL pointer so we can compare against NULL */ + { + paintinfo paintinfo = { 0, }; + fourcc_list[i].paint_setup (&paintinfo, (unsigned char *) s); + if (paintinfo.ap != NULL) { + fail_unless (gst_video_format_has_alpha (fmt)); + } else { + fail_if (gst_video_format_has_alpha (fmt)); + } + } + + for (w = 1; w <= 65; ++w) { + for (h = 1; h <= 65; ++h) { + paintinfo paintinfo = { 0, }; + guint off0, off1, off2, off3; + guint size; + + GST_LOG ("%s, %dx%d", fourcc_list[i].fourcc, w, h); + + paintinfo.width = w; + paintinfo.height = h; + fourcc_list[i].paint_setup (&paintinfo, NULL); + fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 0, w), + paintinfo.ystride); + if (!gst_video_format_is_packed (fmt) + && !gst_video_format_is_gray (fmt)) { + /* planar */ + fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 1, w), + paintinfo.ustride); + fail_unless_equals_int (gst_video_format_get_row_stride (fmt, 2, w), + paintinfo.vstride); + /* check component_width * height against offsets/size somehow? */ + } + + size = gst_video_format_get_size (fmt, w, h); + off0 = gst_video_format_get_component_offset (fmt, 0, w, h); + off1 = gst_video_format_get_component_offset (fmt, 1, w, h); + off2 = gst_video_format_get_component_offset (fmt, 2, w, h); + + fail_unless_equals_int (size, (unsigned long) paintinfo.endptr); + fail_unless_equals_int (off0, (unsigned long) paintinfo.yp); + fail_unless_equals_int (off1, (unsigned long) paintinfo.up); + fail_unless_equals_int (off2, (unsigned long) paintinfo.vp); + + /* should be 0 if there's no alpha component */ + off3 = gst_video_format_get_component_offset (fmt, 3, w, h); + fail_unless_equals_int (off3, (unsigned long) paintinfo.ap); + + /* some gstvideo checks ... (FIXME: fails for Y41B and Y42B; not sure + * if the check or the _get_component_size implementation is wrong) */ + if (fmt != GST_VIDEO_FORMAT_Y41B && fmt != GST_VIDEO_FORMAT_Y42B + && fmt != GST_VIDEO_FORMAT_Y800) { + guint cs0, cs1, cs2, cs3; + + cs0 = gst_video_format_get_component_width (fmt, 0, w) * + gst_video_format_get_component_height (fmt, 0, h); + cs1 = gst_video_format_get_component_width (fmt, 1, w) * + gst_video_format_get_component_height (fmt, 1, h); + cs2 = gst_video_format_get_component_width (fmt, 2, w) * + gst_video_format_get_component_height (fmt, 2, h); + + /* GST_LOG ("cs0=%d,cs1=%d,cs2=%d,off0=%d,off1=%d,off2=%d,size=%d", + cs0, cs1, cs2, off0, off1, off2, size); */ + + if (!gst_video_format_is_packed (fmt)) + fail_unless (cs0 <= off1); + + if (gst_video_format_has_alpha (fmt)) { + cs3 = gst_video_format_get_component_width (fmt, 3, w) * + gst_video_format_get_component_height (fmt, 3, h); + fail_unless (cs3 < size); + /* U/V/alpha shouldn't take up more space than the Y component */ + fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); + fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); + fail_if (cs3 > cs0, "cs3 (%d) should be <= cs0 (%d)", cs3, cs0); + + /* all components together shouldn't take up more space than size */ + fail_unless (cs0 + cs1 + cs2 + cs3 <= size); + } else { + /* U/V shouldn't take up more space than the Y component */ + fail_if (cs1 > cs0, "cs1 (%d) should be <= cs0 (%d)", cs1, cs0); + fail_if (cs2 > cs0, "cs2 (%d) should be <= cs0 (%d)", cs2, cs0); + + /* all components together shouldn't take up more space than size */ + fail_unless (cs0 + cs1 + cs2 <= size, + "cs0 (%d) + cs1 (%d) + cs2 (%d) should be <= size (%d)", + cs0, cs1, cs2, size); + } + } + } + } + } +} + +GST_END_TEST; + +GST_START_TEST (test_video_formats_rgb) +{ + gint width, height, framerate_n, framerate_d, par_n, par_d; + GstCaps *caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_RGB, 800, 600, 0, 1, 1, 1); + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + + fail_unless (gst_structure_get_int (structure, "width", &width)); + fail_unless (gst_structure_get_int (structure, "height", &height)); + fail_unless (gst_structure_get_fraction (structure, "framerate", &framerate_n, + &framerate_d)); + fail_unless (gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_n, &par_d)); + + fail_unless (width == 800); + fail_unless (height == 600); + fail_unless (framerate_n == 0); + fail_unless (framerate_d == 1); + fail_unless (par_n == 1); + fail_unless (par_d == 1); + + gst_caps_unref (caps); +} + +GST_END_TEST; + +GST_START_TEST (test_video_template_caps) +{ + GstCaps *caps = gst_video_format_new_template_caps (GST_VIDEO_FORMAT_RGB); + gst_caps_unref (caps); +} + +GST_END_TEST; + + +GST_START_TEST (test_dar_calc) +{ + guint display_ratio_n, display_ratio_d; + + /* Ensure that various Display Ratio calculations are correctly done */ + /* video 768x576, par 16/15, display par 16/15 = 4/3 */ + fail_unless (gst_video_calculate_display_ratio (&display_ratio_n, + &display_ratio_d, 768, 576, 16, 15, 16, 15)); + fail_unless (display_ratio_n == 4 && display_ratio_d == 3); + + /* video 720x480, par 32/27, display par 1/1 = 16/9 */ + fail_unless (gst_video_calculate_display_ratio (&display_ratio_n, + &display_ratio_d, 720, 480, 32, 27, 1, 1)); + fail_unless (display_ratio_n == 16 && display_ratio_d == 9); + + /* video 360x288, par 533333/500000, display par 16/15 = + * dar 1599999/1600000 */ + fail_unless (gst_video_calculate_display_ratio (&display_ratio_n, + &display_ratio_d, 360, 288, 533333, 500000, 16, 15)); + fail_unless (display_ratio_n == 1599999 && display_ratio_d == 1280000); +} + +GST_END_TEST; + +GST_START_TEST (test_parse_caps_rgb) +{ + struct + { + const gchar *tmpl_caps_string; + GstVideoFormat fmt; + } formats[] = { + /* 24 bit */ + { + GST_VIDEO_CAPS_RGB, GST_VIDEO_FORMAT_RGB}, { + GST_VIDEO_CAPS_BGR, GST_VIDEO_FORMAT_BGR}, + /* 32 bit (no alpha) */ + { + GST_VIDEO_CAPS_RGBx, GST_VIDEO_FORMAT_RGBx}, { + GST_VIDEO_CAPS_xRGB, GST_VIDEO_FORMAT_xRGB}, { + GST_VIDEO_CAPS_BGRx, GST_VIDEO_FORMAT_BGRx}, { + GST_VIDEO_CAPS_xBGR, GST_VIDEO_FORMAT_xBGR}, + /* 32 bit (with alpha) */ + { + GST_VIDEO_CAPS_RGBA, GST_VIDEO_FORMAT_RGBA}, { + GST_VIDEO_CAPS_ARGB, GST_VIDEO_FORMAT_ARGB}, { + GST_VIDEO_CAPS_BGRA, GST_VIDEO_FORMAT_BGRA}, { + GST_VIDEO_CAPS_ABGR, GST_VIDEO_FORMAT_ABGR} + }; + gint i; + + for (i = 0; i < G_N_ELEMENTS (formats); ++i) { + GstVideoFormat fmt = GST_VIDEO_FORMAT_UNKNOWN; + GstCaps *caps, *caps2; + int w = -1, h = -1; + + caps = gst_caps_from_string (formats[i].tmpl_caps_string); + gst_caps_set_simple (caps, "width", G_TYPE_INT, 2 * (i + 1), "height", + G_TYPE_INT, i + 1, "framerate", GST_TYPE_FRACTION, 15, 1, + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL); + g_assert (gst_caps_is_fixed (caps)); + + GST_DEBUG ("testing caps: %" GST_PTR_FORMAT, caps); + + fail_unless (gst_video_format_parse_caps (caps, &fmt, &w, &h)); + fail_unless_equals_int (fmt, formats[i].fmt); + fail_unless_equals_int (w, 2 * (i + 1)); + fail_unless_equals_int (h, i + 1); + + /* make sure they're serialised back correctly */ + caps2 = gst_video_format_new_caps (fmt, w, h, 15, 1, 1, 1); + fail_unless (caps != NULL); + fail_unless (gst_caps_is_equal (caps, caps2)); + + gst_caps_unref (caps); + gst_caps_unref (caps2); + } +} + +GST_END_TEST; + +GST_START_TEST (test_events) +{ + GstEvent *e; + gboolean in_still; + + e = gst_video_event_new_still_frame (TRUE); + fail_if (e == NULL, "Failed to create still frame event"); + fail_unless (gst_video_event_parse_still_frame (e, &in_still), + "Failed to parse still frame event"); + fail_unless (gst_video_event_parse_still_frame (e, NULL), + "Failed to parse still frame event w/ in_still == NULL"); + fail_unless (in_still == TRUE); + gst_event_unref (e); + + e = gst_video_event_new_still_frame (FALSE); + fail_if (e == NULL, "Failed to create still frame event"); + fail_unless (gst_video_event_parse_still_frame (e, &in_still), + "Failed to parse still frame event"); + fail_unless (gst_video_event_parse_still_frame (e, NULL), + "Failed to parse still frame event w/ in_still == NULL"); + fail_unless (in_still == FALSE); + gst_event_unref (e); +} + +GST_END_TEST; + +GST_START_TEST (test_convert_frame) +{ + GstCaps *from_caps, *to_caps; + GstBuffer *from_buffer, *to_buffer; + GError *error = NULL; + gint i; + guint8 *data; + + from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4); + data = GST_BUFFER_DATA (from_buffer); + + for (i = 0; i < 640 * 480; i++) { + data[4 * i + 0] = 0; /* x */ + data[4 * i + 1] = 255; /* R */ + data[4 * i + 2] = 0; /* G */ + data[4 * i + 3] = 0; /* B */ + } + from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB, + 640, 480, 25, 1, 1, 1); + gst_buffer_set_caps (from_buffer, from_caps); + + to_caps = + gst_caps_from_string + ("something/that, does=(string)not, exist=(boolean)FALSE"); + + to_buffer = + gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE, + &error); + fail_if (to_buffer != NULL); + fail_unless (error != NULL); + g_error_free (error); + error = NULL; + + gst_caps_unref (to_caps); + to_caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2); + to_buffer = + gst_video_convert_frame (from_buffer, to_caps, GST_CLOCK_TIME_NONE, + &error); + fail_unless (to_buffer != NULL); + fail_unless (gst_caps_can_intersect (to_caps, GST_BUFFER_CAPS (to_buffer))); + fail_unless (error == NULL); + + gst_buffer_unref (from_buffer); + gst_caps_unref (from_caps); + gst_buffer_unref (to_buffer); + gst_caps_unref (to_caps); +} + +GST_END_TEST; + +typedef struct +{ + GMainLoop *loop; + GstBuffer *buffer; + GError *error; +} ConvertFrameContext; + +static void +convert_frame_async_callback (GstBuffer * buf, GError * err, + ConvertFrameContext * cf_data) +{ + cf_data->buffer = buf; + cf_data->error = err; + + g_main_loop_quit (cf_data->loop); +} + +GST_START_TEST (test_convert_frame_async) +{ + GstCaps *from_caps, *to_caps; + GstBuffer *from_buffer; + gint i; + guint8 *data; + GMainLoop *loop; + ConvertFrameContext cf_data = { NULL, NULL, NULL }; + + from_buffer = gst_buffer_new_and_alloc (640 * 480 * 4); + data = GST_BUFFER_DATA (from_buffer); + + for (i = 0; i < 640 * 480; i++) { + data[4 * i + 0] = 0; /* x */ + data[4 * i + 1] = 255; /* R */ + data[4 * i + 2] = 0; /* G */ + data[4 * i + 3] = 0; /* B */ + } + from_caps = gst_video_format_new_caps (GST_VIDEO_FORMAT_xRGB, + 640, 480, 25, 1, 1, 1); + gst_buffer_set_caps (from_buffer, from_caps); + + to_caps = + gst_caps_from_string + ("something/that, does=(string)not, exist=(boolean)FALSE"); + + loop = cf_data.loop = g_main_loop_new (NULL, FALSE); + + gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE, + (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data, + NULL); + + g_main_loop_run (loop); + + fail_if (cf_data.buffer != NULL); + fail_unless (cf_data.error != NULL); + g_error_free (cf_data.error); + cf_data.error = NULL; + + gst_caps_unref (to_caps); + to_caps = + gst_video_format_new_caps (GST_VIDEO_FORMAT_I420, 240, 320, 25, 1, 1, 2); + gst_video_convert_frame_async (from_buffer, to_caps, GST_CLOCK_TIME_NONE, + (GstVideoConvertFrameCallback) convert_frame_async_callback, &cf_data, + NULL); + g_main_loop_run (loop); + fail_unless (cf_data.buffer != NULL); + fail_unless (gst_caps_can_intersect (to_caps, + GST_BUFFER_CAPS (cf_data.buffer))); + fail_unless (cf_data.error == NULL); + + gst_buffer_unref (from_buffer); + gst_caps_unref (from_caps); + gst_buffer_unref (cf_data.buffer); + gst_caps_unref (to_caps); + + g_main_loop_unref (loop); +} + +GST_END_TEST; + +static Suite * +video_suite (void) +{ + Suite *s = suite_create ("video support library"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_video_formats); + tcase_add_test (tc_chain, test_video_formats_rgb); + tcase_add_test (tc_chain, test_video_template_caps); + tcase_add_test (tc_chain, test_dar_calc); + tcase_add_test (tc_chain, test_parse_caps_rgb); + tcase_add_test (tc_chain, test_events); + tcase_add_test (tc_chain, test_convert_frame); + tcase_add_test (tc_chain, test_convert_frame_async); + + return s; +} + +GST_CHECK_MAIN (video); diff --git a/gst-plugins-base-subtitles0.10/tests/check/libs/xmpwriter.c b/gst-plugins-base-subtitles0.10/tests/check/libs/xmpwriter.c new file mode 100644 index 0000000..99b84ae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/libs/xmpwriter.c @@ -0,0 +1,275 @@ +/* GStreamer + * + * unit tests for xmp config library + * + * Copyright (C) 2011 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +#include + +#define TEST_ELEMENT_TYPE (test_element_get_type()) + +typedef struct TestElement TestElement; +typedef struct TestElementClass TestElementClass; + +struct TestElement +{ + GstElement parent; +}; + +struct TestElementClass +{ + GstElementClass parent_class; +}; + +GType test_element_get_type (void); + +static void init_interface (GType type); + +GST_BOILERPLATE_FULL (TestElement, test_element, GstElement, GST_TYPE_ELEMENT, + init_interface); + +static void +init_interface (GType type) +{ + static const GInterfaceInfo tagxmpwriter_info = { + NULL, + NULL, + NULL, + }; + + g_type_add_interface_static (type, GST_TYPE_TAG_XMP_WRITER, + &tagxmpwriter_info); +} + +static void +test_element_base_init (gpointer klass) +{ +} + +static void +test_element_class_init (TestElementClass * klass) +{ +} + +static void +test_element_init (TestElement * this, TestElementClass * klass) +{ +} + +static void +tag_list_equals (GstTagList * taglist, GstTagList * taglist2) +{ + const gchar *name_sent, *name_recv; + const GValue *value_sent, *value_recv; + gboolean found; + gint comparison; + gint n_recv; + gint n_sent; + gint i, j; + + /* verify tags */ + fail_unless (taglist2 != NULL); + n_recv = gst_structure_n_fields (taglist2); + n_sent = gst_structure_n_fields (taglist); + fail_unless (n_recv == n_sent); + fail_unless (n_sent > 0); + + /* FIXME: compare taglist values */ + for (i = 0; i < n_sent; i++) { + name_sent = gst_structure_nth_field_name (taglist, i); + value_sent = gst_structure_get_value (taglist, name_sent); + found = FALSE; + for (j = 0; j < n_recv; j++) { + name_recv = gst_structure_nth_field_name (taglist2, j); + if (!strcmp (name_sent, name_recv)) { + value_recv = gst_structure_get_value (taglist2, 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); + } + if (comparison != GST_VALUE_EQUAL && + G_VALUE_HOLDS (value_sent, G_TYPE_DOUBLE)) { + gdouble vs; + gdouble vr; + + /* add some tolerance for doubles */ + vs = g_value_get_double (value_sent); + vr = g_value_get_double (value_recv); + if (vr >= vs - 0.001 && vr <= vs + 0.001) + comparison = GST_VALUE_EQUAL; + } + 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); + } +} + +static gboolean +gst_buffer_equals (GstBuffer * buf_a, GstBuffer * buf_b) +{ + if (GST_BUFFER_SIZE (buf_a) != GST_BUFFER_SIZE (buf_b)) + return FALSE; + + return memcmp (GST_BUFFER_DATA (buf_a), GST_BUFFER_DATA (buf_b), + GST_BUFFER_SIZE (buf_a)) == 0; +} + +static GstTagList * +create_taglist (void) +{ + return gst_tag_list_new_full (GST_TAG_ARTIST, "artist", + GST_TAG_TITLE, "title", GST_TAG_COPYRIGHT, "copyright", NULL); +} + +GST_START_TEST (test_no_xmp) +{ + GstTagList *taglist = create_taglist (); + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + + gst_tag_xmp_writer_remove_all_schemas (GST_TAG_XMP_WRITER (test_element)); + + fail_unless (gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE) == NULL); + + gst_object_unref (test_element); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_default) +{ + GstTagList *taglist = create_taglist (); + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstBuffer *buf; + GstBuffer *buf2; + + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + buf2 = gst_tag_list_to_xmp_buffer (taglist, TRUE); + fail_unless (gst_buffer_equals (buf, buf2)); + + gst_object_unref (test_element); + gst_buffer_unref (buf); + gst_buffer_unref (buf2); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +GST_START_TEST (test_disable) +{ + GstTagList *taglist; + GstTagList *taglist2; + GstElement *test_element = + (GstElement *) g_object_new (TEST_ELEMENT_TYPE, NULL); + GstBuffer *buf; + const gchar *str; + + taglist = gst_tag_list_new_full (GST_TAG_ARTIST, "artist", NULL); + + /* add a tag that is mapped on xmp schema (as of Mar, 21th 2011) */ + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_USER_RATING, 5, + NULL); + + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + tag_list_equals (taglist, taglist2); + gst_tag_list_free (taglist2); + gst_buffer_unref (buf); + + gst_tag_xmp_writer_remove_schema (GST_TAG_XMP_WRITER (test_element), "xap"); + buf = + gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER + (test_element), taglist, TRUE); + taglist2 = gst_tag_list_from_xmp_buffer (buf); + + /* artist should be there, but rating shouldn't */ + fail_unless (gst_tag_list_peek_string_index (taglist2, GST_TAG_ARTIST, 0, + &str)); + fail_unless (gst_tag_list_get_value_index (taglist2, GST_TAG_USER_RATING, + 0) == NULL); + + gst_tag_list_free (taglist2); + gst_buffer_unref (buf); + + gst_object_unref (test_element); + gst_tag_list_free (taglist); +} + +GST_END_TEST; + + +static Suite * +xmp_config_suite (void) +{ + Suite *s = suite_create ("xmpconfig interface"); + TCase *tc_chain = tcase_create ("configuration"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_no_xmp); + tcase_add_test (tc_chain, test_default); + tcase_add_test (tc_chain, test_disable); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = xmp_config_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/.gitignore b/gst-plugins-base-subtitles0.10/tests/check/pipelines/.gitignore new file mode 100644 index 0000000..7a5eb34 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/.gitignore @@ -0,0 +1,10 @@ +.dirstamp +basetime +capsfilter-renegotiation +gio +simple-launch-lines +theoraenc +vorbisdec +vorbisenc +oggmux +streamheader diff --git a/gst-plugins-base-subtitles0.10/tests/check/pipelines/basetime.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/basetime.c new file mode 100644 index 0000000..2b84f9d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/basetime.c @@ -0,0 +1,158 @@ +/* GStreamer + * + * unit test for audiotestsrc basetime handling + * + * Copyright (C) 2009 Maemo Multimedia + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#ifndef GST_DISABLE_PARSE + +static GstClockTime old_ts = GST_CLOCK_TIME_NONE; + +static gboolean +break_mainloop (gpointer data) +{ + GMainLoop *loop; + + loop = (GMainLoop *) data; + g_main_loop_quit (loop); + + return FALSE; +} + +static gboolean +buffer_probe_cb (GstPad * pad, GstBuffer * buffer) +{ + if (old_ts != GST_CLOCK_TIME_NONE) { + fail_unless (GST_BUFFER_TIMESTAMP (buffer) != old_ts, + "Two buffers had same timestamp"); + } + old_ts = GST_BUFFER_TIMESTAMP (buffer); + + return TRUE; +} + +GST_START_TEST (test_basetime_calculation) +{ + GstElement *p1, *bin; + GstElement *asrc, *asink; + GstPad *pad; + GMainLoop *loop; + + /* Don't run with osxaudiosrc . This is because libcheck runs the actual + * test in a forked process and causes havoc with osx's API. */ + if (G_UNLIKELY (!g_ascii_strcasecmp (DEFAULT_AUDIOSRC, "osxaudiosrc"))) + return; + + loop = g_main_loop_new (NULL, FALSE); + + /* The "main" pipeline */ + p1 = gst_parse_launch ("fakesrc ! fakesink", NULL); + fail_if (p1 == NULL); + + /* Create a sub-bin that is activated only in "certain situations" */ + asrc = gst_element_factory_make (DEFAULT_AUDIOSRC, NULL); + if (asrc == NULL) { + GST_WARNING ("Cannot run test. test audio source %s not available", + DEFAULT_AUDIOSRC); + gst_element_set_state (p1, GST_STATE_NULL); + gst_object_unref (p1); + return; + } + asink = gst_element_factory_make ("fakesink", NULL); + + bin = gst_bin_new ("audiobin"); + gst_bin_add_many (GST_BIN (bin), asrc, asink, NULL); + gst_element_link (asrc, asink); + + gst_bin_add (GST_BIN (p1), bin); + gst_element_set_state (p1, GST_STATE_READY); + + pad = gst_element_get_static_pad (asink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of sink"); + + gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe_cb), NULL); + gst_element_set_locked_state (bin, TRUE); + + /* Run main pipeline first */ + gst_element_set_state (p1, GST_STATE_PLAYING); + g_timeout_add (2 * 1000, break_mainloop, loop); + g_main_loop_run (loop); + + /* Now activate the audio pipeline */ + gst_element_set_locked_state (bin, FALSE); + gst_element_set_state (p1, GST_STATE_PAUSED); + + /* Normally our custom audiobin would send this message */ + gst_element_post_message (asrc, + gst_message_new_clock_provide (GST_OBJECT (asrc), NULL, TRUE)); + + /* At this point a new clock is selected */ + gst_element_set_state (p1, GST_STATE_PLAYING); + + g_timeout_add (2 * 1000, break_mainloop, loop); + g_main_loop_run (loop); + + gst_object_unref (pad); + gst_element_set_state (p1, GST_STATE_NULL); + gst_object_unref (p1); +} + +GST_END_TEST; + +#endif /* #ifndef GST_DISABLE_PARSE */ + +static Suite * +baseaudiosrc_suite (void) +{ + Suite *s = suite_create ("baseaudiosrc"); + TCase *tc_chain = tcase_create ("general"); + + /* timeout 6 sec */ + tcase_set_timeout (tc_chain, 6); + suite_add_tcase (s, tc_chain); + +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_basetime_calculation); +#endif + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = baseaudiosrc_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/capsfilter-renegotiation.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/capsfilter-renegotiation.c new file mode 100644 index 0000000..f18a713 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/capsfilter-renegotiation.c @@ -0,0 +1,172 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * capsfilter-renegotiation.c: Unit test for capsfilter caps renegotiation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Ideally this would be in core, but using videotestsrc makes it easier */ + +#include + +#define FIRST_CAPS "video/x-raw-yuv,width=(int)480,height=(int)320" +#define SECOND_CAPS "video/x-raw-yuv,width=(int)120,height=(int)100" +#define THIRD_CAPS "video/x-raw-yuv,width=(int)[10,50],height=(int)[100,200]" +#define FOURTH_CAPS "video/x-raw-rgb,width=(int)300,height=(int)[25,75];" \ + "video/x-raw-yuv,width=(int)[30,40]," \ + "height=(int)[100,200],format=(fourcc)YUY2" + +int buffer_count = 0; +GstCaps *current_caps = NULL; +int caps_change = 0; + +static gboolean +buffer_probe (GstPad * pad, GstMiniObject * obj, gpointer data) +{ + GstBuffer *buffer; + GstCaps *buffer_caps; + GstElement *capsfilter = GST_ELEMENT (data); + GstCaps *caps = NULL; + + buffer = GST_BUFFER (obj); + + /* increment the buffer count and check if it is time to change the caps */ + buffer_count++; + if (buffer_count == 50) { + /* change the caps to another one */ + caps = gst_caps_from_string (SECOND_CAPS); + } else if (buffer_count == 100) { + /* change the caps to another one, this time unfixed */ + caps = gst_caps_from_string (THIRD_CAPS); + } else if (buffer_count == 150) { + /* change the caps to another one, + * this time unfixed with multiple entries */ + caps = gst_caps_from_string (FOURTH_CAPS); + } + /* set the caps */ + if (caps) { + g_object_set (capsfilter, "caps", caps, NULL); + gst_caps_unref (caps); + } + + /* now check if the buffer caps has changed since last check */ + buffer_caps = GST_BUFFER_CAPS (buffer); + if (current_caps == NULL && buffer_caps != NULL) { + /* probably the first caps, this is a change */ + current_caps = gst_caps_copy (buffer_caps); + caps_change++; + } else if (current_caps != NULL) { + if (buffer_caps == NULL) { + /* caps was set to NULL, we consider this a change */ + gst_caps_unref (current_caps); + current_caps = NULL; + caps_change++; + } else { + if (!gst_caps_is_equal (current_caps, buffer_caps)) { + /* a caps change */ + gst_caps_unref (current_caps); + current_caps = gst_caps_copy (buffer_caps); + caps_change++; + } + } + } + + return TRUE; +} + +GST_START_TEST (test_capsfilter_renegotiation) +{ + GstElement *capsfilter; + GstElement *sink; + GstElement *pipeline; + GstBus *bus; + GstMessage *msg; + GstPad *pad; + + caps_change = 0; + buffer_count = 0; + if (current_caps) + gst_caps_unref (current_caps); + current_caps = NULL; + + pipeline = gst_parse_launch ("videotestsrc num-buffers=200 ! capsfilter " + "caps=\"" FIRST_CAPS "\" name=cf ! fakesink name=sink", NULL); + g_assert (pipeline); + + capsfilter = gst_bin_get_by_name (GST_BIN (pipeline), "cf"); + g_assert (capsfilter); + + sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); + g_assert (sink); + + pad = gst_element_get_static_pad (sink, "sink"); + gst_pad_add_buffer_probe (pad, (GCallback) buffer_probe, capsfilter); + gst_object_unref (pad); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + + g_assert (gst_element_set_state (pipeline, GST_STATE_PLAYING) != + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + + g_assert (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + g_assert (caps_change == 4); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + if (current_caps) + gst_caps_unref (current_caps); + gst_message_unref (msg); + g_object_unref (bus); + g_object_unref (G_OBJECT (pipeline)); +} + +GST_END_TEST; + +static Suite * +capsfilter_renegotiation_suite (void) +{ + Suite *s = suite_create ("CapsfilterRenegotiation"); + TCase *tc_chain = tcase_create ("linear"); + + /* 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_capsfilter_renegotiation); + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = capsfilter_renegotiation_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/gio.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/gio.c new file mode 100644 index 0000000..ee14110 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/gio.c @@ -0,0 +1,181 @@ +/* GStreamer + * + * unit test for GIO + * + * Copyright (C) 2007 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +static gboolean got_eos = FALSE; + +static gboolean +message_handler (GstBus * bus, GstMessage * msg, gpointer data) +{ + GMainLoop *loop = (GMainLoop *) data; + + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_EOS: + got_eos = TRUE; + g_main_loop_quit (loop); + break; + case GST_MESSAGE_ERROR:{ + gchar *debug; + GError *err; + + gst_message_parse_error (msg, &err, &debug); + g_free (debug); + + /* Will abort the check */ + g_warning ("Error: %s\n", err->message); + g_error_free (err); + + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + +GST_START_TEST (test_memory_stream) +{ + GMainLoop *loop; + GstElement *bin; + GstElement *src, *sink; + GstBus *bus; + GMemoryInputStream *input; + GMemoryOutputStream *output; + guint8 *in_data; + guint8 *out_data; + gint i; + GstFormat fmt = GST_FORMAT_BYTES; + gint64 duration; + guint bus_watch = 0; + + got_eos = FALSE; + + in_data = g_new (guint8, 512); + out_data = g_new (guint8, 512); + for (i = 0; i < 512; i++) + in_data[i] = i % 256; + + input = + G_MEMORY_INPUT_STREAM (g_memory_input_stream_new_from_data (in_data, 512, + (GDestroyNotify) g_free)); + + output = G_MEMORY_OUTPUT_STREAM (g_memory_output_stream_new (out_data, 512, + (GReallocFunc) g_realloc, (GDestroyNotify) g_free)); + out_data = NULL; + + loop = g_main_loop_new (NULL, FALSE); + + bin = gst_pipeline_new ("bin"); + + src = gst_element_factory_make ("giostreamsrc", "src"); + fail_unless (src != NULL); + g_object_set (G_OBJECT (src), "stream", input, NULL); + + sink = gst_element_factory_make ("giostreamsink", "sink"); + fail_unless (sink != NULL); + g_object_set (G_OBJECT (sink), "stream", output, NULL); + + gst_bin_add_many (GST_BIN (bin), src, sink, NULL); + + fail_unless (gst_element_link_many (src, sink, NULL)); + + bus = gst_element_get_bus (bin); + bus_watch = gst_bus_add_watch (bus, message_handler, loop); + gst_object_unref (bus); + + gst_element_set_state (bin, GST_STATE_PAUSED); + gst_element_get_state (bin, NULL, NULL, -1); + + fail_unless (gst_element_query_duration (bin, &fmt, &duration)); + fail_unless_equals_int (duration, 512); + + gst_element_set_state (bin, GST_STATE_PLAYING); + + g_main_loop_run (loop); + + gst_element_set_state (bin, GST_STATE_NULL); + + fail_unless (got_eos); + got_eos = FALSE; + + out_data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output)); + + for (i = 0; i < 512; i++) + fail_unless_equals_int (in_data[i], out_data[i]); + + gst_element_set_state (bin, GST_STATE_PAUSED); + gst_element_get_state (bin, NULL, NULL, -1); + + fail_unless (gst_element_query_duration (bin, &fmt, &duration)); + fail_unless_equals_int (duration, 512); + + gst_element_set_state (bin, GST_STATE_PLAYING); + + g_main_loop_run (loop); + + gst_element_set_state (bin, GST_STATE_NULL); + gst_object_unref (bin); + + fail_unless (got_eos); + + g_object_unref (input); + g_object_unref (output); + + g_main_loop_unref (loop); + g_source_remove (bus_watch); +} + +GST_END_TEST; + +static Suite * +gio_testsuite (void) +{ + Suite *s = suite_create ("gio"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_memory_stream); + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = gio_testsuite (); + 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/gst-plugins-base-subtitles0.10/tests/check/pipelines/oggmux.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/oggmux.c new file mode 100644 index 0000000..81056ca --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/oggmux.c @@ -0,0 +1,432 @@ +/* GStreamer + * + * unit tests for oggmux + * + * Copyright (C) 2006 James Livingston + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + + +typedef enum +{ + CODEC_UNKNOWN, + CODEC_VORBIS, + CODEC_THEORA, + CODEC_SPEEX, +} ChainCodec; + +typedef struct +{ + gboolean eos; + gulong serialno; + gint64 last_granule; + ChainCodec codec; +} ChainState; + +#if (defined (HAVE_THEORA) || defined (HAVE_VORBIS)) +static ogg_sync_state oggsync; +static GHashTable *eos_chain_states; +static gulong probe_id; + +static ChainCodec +get_page_codec (ogg_page * page) +{ + ChainCodec codec = CODEC_UNKNOWN; + ogg_stream_state state; + ogg_packet packet; + + ogg_stream_init (&state, ogg_page_serialno (page)); + if (ogg_stream_pagein (&state, page) == 0) { + if (ogg_stream_packetpeek (&state, &packet) > 0) { + if (strncmp ((char *) &packet.packet[1], "vorbis", + strlen ("vorbis")) == 0) + codec = CODEC_VORBIS; + else if (strncmp ((char *) &packet.packet[1], "theora", + strlen ("theora")) == 0) + codec = CODEC_THEORA; + else if (strncmp ((char *) &packet.packet[0], "Speex ", + strlen ("Speex ")) == 0) + codec = CODEC_SPEEX; + } + } + ogg_stream_clear (&state); + + return codec; +} + +static void +fail_if_audio (gpointer key, ChainState * state, gpointer data) +{ + fail_if (state->codec == CODEC_VORBIS, + "vorbis BOS occurred before theora BOS"); + fail_if (state->codec == CODEC_SPEEX, "speex BOS occurred before theora BOS"); +} + +static ChainState * +validate_ogg_page (ogg_page * page) +{ + gulong serialno; + gint64 granule; + ChainState *state; + + serialno = ogg_page_serialno (page); + granule = ogg_page_granulepos (page); + state = g_hash_table_lookup (eos_chain_states, GINT_TO_POINTER (serialno)); + + fail_if (ogg_page_packets (page) == 0 && granule != -1, + "Must have granulepos -1 when page has no packets, has %" G_GINT64_FORMAT, + granule); + + if (ogg_page_bos (page)) { + fail_unless (state == NULL, "Extraneous BOS flag on chain %u", serialno); + + state = g_new0 (ChainState, 1); + g_hash_table_insert (eos_chain_states, GINT_TO_POINTER (serialno), state); + state->serialno = serialno; + state->last_granule = granule; + state->codec = get_page_codec (page); + + /* check for things like BOS ordering, etc */ + switch (state->codec) { + case CODEC_THEORA: + /* check we have no vorbis/speex chains yet */ + g_hash_table_foreach (eos_chain_states, (GHFunc) fail_if_audio, NULL); + break; + case CODEC_VORBIS: + case CODEC_SPEEX: + /* no checks (yet) */ + break; + case CODEC_UNKNOWN: + default: + break; + } + } else if (ogg_page_eos (page)) { + fail_unless (state != NULL, "Missing BOS flag on chain %u", serialno); + state->eos = TRUE; + } else { + fail_unless (state != NULL, "Missing BOS flag on chain %u", serialno); + fail_unless (!state->eos, "Data after EOS flag on chain %u", serialno); + } + + if (granule != -1) { + fail_unless (granule >= state->last_granule, + "Granulepos out-of-order for chain %u: old=%" G_GINT64_FORMAT ", new=" + G_GINT64_FORMAT, serialno, state->last_granule, granule); + state->last_granule = granule; + } + + return state; +} + +static void +is_video (gpointer key, ChainState * state, gpointer data) +{ + if (state->codec == CODEC_THEORA) + *((gboolean *) data) = TRUE; +} + +static gboolean +check_chain_final_state (gpointer key, ChainState * state, gpointer data) +{ + fail_unless (state->eos, "missing EOS flag on chain %u", state->serialno); + + /* return TRUE to empty the chain table */ + return TRUE; +} + +static gboolean +eos_buffer_probe (GstPad * pad, GstBuffer * buffer, gpointer unused) +{ + gint ret; + gint size; + guint8 *data; + gchar *oggbuffer; + ChainState *state = NULL; + gboolean has_video = FALSE; + + size = GST_BUFFER_SIZE (buffer); + data = GST_BUFFER_DATA (buffer); + + oggbuffer = ogg_sync_buffer (&oggsync, size); + memcpy (oggbuffer, data, size); + ogg_sync_wrote (&oggsync, size); + + do { + ogg_page page; + + ret = ogg_sync_pageout (&oggsync, &page); + if (ret > 0) + state = validate_ogg_page (&page); + } + while (ret != 0); + + if (state) { + /* Now, we can do buffer-level checks... + * If we have video somewhere, then we should have DELTA_UNIT set on all + * non-header (not IN_CAPS), non-video buffers + */ + g_hash_table_foreach (eos_chain_states, (GHFunc) is_video, &has_video); + if (has_video && state->codec != CODEC_THEORA) { + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) + fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, + GST_BUFFER_FLAG_DELTA_UNIT), + "Non-video buffer doesn't have DELTA_UNIT in stream with video"); + } + } + + return TRUE; +} + +static void +start_pipeline (GstElement * bin, GstPad * pad) +{ + GstStateChangeReturn ret; + + ogg_sync_init (&oggsync); + + eos_chain_states = + g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + probe_id = + gst_pad_add_buffer_probe (pad, G_CALLBACK (eos_buffer_probe), NULL); + + ret = gst_element_set_state (bin, GST_STATE_PLAYING); + fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not start test pipeline"); + if (ret == GST_STATE_CHANGE_ASYNC) { + ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not start test pipeline"); + } +} + +static void +stop_pipeline (GstElement * bin, GstPad * pad) +{ + GstStateChangeReturn ret; + + ret = gst_element_set_state (bin, GST_STATE_NULL); + fail_if (ret == GST_STATE_CHANGE_FAILURE, "Could not stop test pipeline"); + if (ret == GST_STATE_CHANGE_ASYNC) { + ret = gst_element_get_state (bin, NULL, NULL, GST_CLOCK_TIME_NONE); + fail_if (ret != GST_STATE_CHANGE_SUCCESS, "Could not stop test pipeline"); + } + + gst_pad_remove_buffer_probe (pad, (guint) probe_id); + ogg_sync_clear (&oggsync); + + /* check end conditions, such as EOS flags */ + g_hash_table_foreach_remove (eos_chain_states, + (GHRFunc) check_chain_final_state, NULL); +} + +static gboolean +eos_watch (GstBus * bus, GstMessage * message, GMainLoop * loop) +{ + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_EOS) { + g_main_loop_quit (loop); + } + return TRUE; +} + +static void +test_pipeline (const char *pipeline) +{ + GstElement *bin, *sink; + GstPad *pad, *sinkpad; + GstBus *bus; + GError *error = NULL; + GMainLoop *loop; + GstPadLinkReturn linkret; + guint bus_watch = 0; + + bin = gst_parse_launch (pipeline, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + pad = gst_bin_find_unlinked_pad (GST_BIN (bin), GST_PAD_SRC); + fail_unless (pad != NULL, "Could not locate free src pad"); + + /* connect the fake sink */ + sink = gst_element_factory_make ("fakesink", "fake_sink"); + fail_unless (sink != NULL, "Could create fakesink"); + fail_unless (gst_bin_add (GST_BIN (bin), sink), "Could not insert fakesink"); + sinkpad = gst_element_get_static_pad (sink, "sink"); + fail_unless (sinkpad != NULL, "Could not get fakesink src pad"); + + linkret = gst_pad_link (pad, sinkpad); + fail_unless (GST_PAD_LINK_SUCCESSFUL (linkret), + "Could not link to fake sink"); + gst_object_unref (sinkpad); + + /* run until we receive EOS */ + loop = g_main_loop_new (NULL, FALSE); + bus = gst_element_get_bus (bin); + bus_watch = gst_bus_add_watch (bus, (GstBusFunc) eos_watch, loop); + gst_object_unref (bus); + + start_pipeline (bin, pad); + g_main_loop_run (loop); + + /* we're EOS now; make sure oggmux out caps have stream headers on them */ + { + GstStructure *s; + GstCaps *muxcaps; + + muxcaps = gst_pad_get_negotiated_caps (sinkpad); + fail_unless (muxcaps != NULL); + s = gst_caps_get_structure (muxcaps, 0); + fail_unless (gst_structure_has_name (s, "application/ogg")); + fail_unless (gst_structure_has_field (s, "streamheader")); + fail_unless (gst_structure_has_field_typed (s, "streamheader", + GST_TYPE_ARRAY)); + gst_caps_unref (muxcaps); + } + + stop_pipeline (bin, pad); + + /* clean up */ + g_main_loop_unref (loop); + g_source_remove (bus_watch); + gst_object_unref (pad); + gst_object_unref (bin); +} +#endif + +#ifdef HAVE_VORBIS +GST_START_TEST (test_vorbis) +{ + test_pipeline + ("audiotestsrc num-buffers=5 ! audioconvert ! vorbisenc ! oggmux"); +} + +GST_END_TEST; + +GST_START_TEST (test_vorbis_oggmux_unlinked) +{ + GstElement *pipe; + GstMessage *msg; + + pipe = gst_parse_launch ("audiotestsrc ! vorbisenc ! oggmux", NULL); + if (pipe == NULL) { + g_printerr ("Skipping test 'test_vorbis_oggmux_unlinked'"); + return; + } + /* no sink, no async state change */ + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_PAUSED), + GST_STATE_CHANGE_SUCCESS); + /* we expect an error (without any criticals/warnings) */ + msg = gst_bus_timed_pop_filtered (GST_ELEMENT_BUS (pipe), -1, + GST_MESSAGE_ERROR); + gst_message_unref (msg); + fail_unless_equals_int (gst_element_set_state (pipe, GST_STATE_NULL), + GST_STATE_CHANGE_SUCCESS); + gst_object_unref (pipe); +} + +GST_END_TEST; +#endif + +#ifdef HAVE_THEORA +GST_START_TEST (test_theora) +{ + test_pipeline + ("videotestsrc num-buffers=5 ! ffmpegcolorspace ! theoraenc ! oggmux"); +} + +GST_END_TEST; +#endif + +#if (defined (HAVE_THEORA) && defined (HAVE_VORBIS)) +GST_START_TEST (test_theora_vorbis) +{ + test_pipeline + ("videotestsrc num-buffers=10 ! ffmpegcolorspace ! theoraenc ! queue ! oggmux name=mux " + "audiotestsrc num-buffers=2 ! audioconvert ! vorbisenc ! queue ! mux."); +} + +GST_END_TEST; + +GST_START_TEST (test_vorbis_theora) +{ + test_pipeline + ("videotestsrc num-buffers=2 ! ffmpegcolorspace ! theoraenc ! queue ! oggmux name=mux " + "audiotestsrc num-buffers=10 ! audioconvert ! vorbisenc ! queue ! mux."); +} + +GST_END_TEST; +#endif + +GST_START_TEST (test_simple_cleanup) +{ + GstElement *oggmux; + + oggmux = gst_element_factory_make ("oggmux", NULL); + gst_object_unref (oggmux); +} + +GST_END_TEST; + +GST_START_TEST (test_request_pad_cleanup) +{ + GstElement *oggmux; + GstPad *pad; + + oggmux = gst_element_factory_make ("oggmux", NULL); + pad = gst_element_get_request_pad (oggmux, "sink_%d"); + fail_unless (pad != NULL); + gst_object_unref (pad); + pad = gst_element_get_request_pad (oggmux, "sink_%d"); + fail_unless (pad != NULL); + gst_object_unref (pad); + gst_object_unref (oggmux); +} + +GST_END_TEST; + +static Suite * +oggmux_suite (void) +{ + Suite *s = suite_create ("oggmux"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); +#ifdef HAVE_VORBIS + tcase_add_test (tc_chain, test_vorbis); + tcase_add_test (tc_chain, test_vorbis_oggmux_unlinked); +#endif + +#ifdef HAVE_THEORA + tcase_add_test (tc_chain, test_theora); +#endif + +#if (defined (HAVE_THEORA) && defined (HAVE_VORBIS)) + tcase_add_test (tc_chain, test_vorbis_theora); + tcase_add_test (tc_chain, test_theora_vorbis); +#endif + + tcase_add_test (tc_chain, test_simple_cleanup); + tcase_add_test (tc_chain, test_request_pad_cleanup); + return s; +} + +GST_CHECK_MAIN (oggmux); diff --git a/gst-plugins-base-subtitles0.10/tests/check/pipelines/simple-launch-lines.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/simple-launch-lines.c new file mode 100644 index 0000000..ab636d9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/simple-launch-lines.c @@ -0,0 +1,240 @@ +/* GStreamer + * Copyright (C) 2005 Andy Wingo + * + * simple_launch_lines.c: Unit test for simple pipelines + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#ifndef GST_DISABLE_PARSE + +static GstElement * +setup_pipeline (const gchar * pipe_descr) +{ + GstElement *pipeline; + + GST_LOG ("pipeline: %s", pipe_descr); + pipeline = gst_parse_launch (pipe_descr, NULL); + g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL); + return pipeline; +} + +/* + * run_pipeline: + * @pipe: the pipeline to run + * @desc: the description for use in messages + * @events: is a mask of expected events + * @tevent: is the expected terminal event. + * + * the poll call will time out after half a second. + */ +static void +run_pipeline (GstElement * pipe, const gchar * descr, + GstMessageType events, GstMessageType tevent) +{ + GstBus *bus; + GstMessage *message; + GstMessageType revent; + GstStateChangeReturn ret; + + g_assert (pipe); + bus = gst_element_get_bus (pipe); + g_assert (bus); + + fail_if (gst_element_set_state (pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE, "Could not set pipeline %s to playing", descr); + ret = gst_element_get_state (pipe, NULL, NULL, 10 * GST_SECOND); + if (ret == GST_STATE_CHANGE_ASYNC) { + g_critical ("Pipeline '%s' failed to go to PLAYING fast enough", descr); + goto done; + } else if (ret != GST_STATE_CHANGE_SUCCESS) { + g_critical ("Pipeline '%s' failed to go into PLAYING state", descr); + goto done; + } + + while (1) { + message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 2); + + + /* always have to pop the message before getting back into poll */ + if (message) { + revent = GST_MESSAGE_TYPE (message); + gst_message_unref (message); + } else { + revent = GST_MESSAGE_UNKNOWN; + } + + if (revent == tevent) { + break; + } else if (revent == GST_MESSAGE_UNKNOWN) { + g_critical ("Unexpected timeout in gst_bus_poll, looking for %d: %s", + tevent, descr); + break; + } else if (revent & events) { + continue; + } + g_critical + ("Unexpected message received of type %d, '%s', looking for %d: %s", + revent, gst_message_type_get_name (revent), tevent, descr); + } + +done: + fail_if (gst_element_set_state (pipe, GST_STATE_NULL) == + GST_STATE_CHANGE_FAILURE, "Could not set pipeline %s to NULL", descr); + gst_element_get_state (pipe, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (pipe); + + gst_bus_set_flushing (bus, TRUE); + gst_object_unref (bus); +} + +GST_START_TEST (test_element_negotiation) +{ + const gchar *s; + + /* Ensures that filtering buffers with unknown caps down to fixed-caps + * will apply those caps to the buffers. + * see http://bugzilla.gnome.org/show_bug.cgi?id=315126 */ + s = "fakesrc num-buffers=2 ! " + "audio/x-raw-int,width=16,depth=16,rate=22050,channels=1," + "signed=(boolean)true,endianness=1234 ! " + "audioconvert ! audio/x-raw-int,width=16,depth=16,rate=22050,channels=1 " + "! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + +#ifdef HAVE_LIBVISUAL + s = "audiotestsrc num-buffers=30 ! tee name=t ! alsasink t. ! audioconvert ! " + "libvisual_lv_scope ! ffmpegcolorspace ! xvimagesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); +#endif +} + +GST_END_TEST; + +GST_START_TEST (test_basetransform_based) +{ + /* Each of these tests is to check whether various basetransform based + * elements can select output caps when not allowed to do passthrough + * and going to a generic sink such as fakesink or filesink */ + const gchar *s; + + /* Check that videoscale can pick a height given only a width */ + s = "videotestsrc num-buffers=2 ! " + "video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! " + "videoscale ! video/x-raw-yuv,width=640 ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + + /* Test that ffmpegcolorspace can pick an output format that isn't + * passthrough without completely specified output caps */ + s = "videotestsrc num-buffers=2 ! " + "video/x-raw-yuv,format=(fourcc)I420,width=320,height=240 ! " + "ffmpegcolorspace ! video/x-raw-rgb ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + + /* Check that audioresample can pick a samplerate to use from a + * range that doesn't include the input */ + s = "audiotestsrc num-buffers=2 ! " + "audio/x-raw-int,width=16,depth=16,rate=8000 ! " + "audioresample ! audio/x-raw-int,rate=[16000,48000] ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + + /* Check that audioconvert can pick a depth to use, given a width */ + s = "audiotestsrc num-buffers=30 ! audio/x-raw-int,width=16,depth=16 ! " + "audioconvert ! " "audio/x-raw-int,width=32 ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + + /* Check that videoscale doesn't claim to be able to transform input in + * formats it can't handle for a given scaling method; ffmpegcolorspace + * should then make sure a format that can be handled is chosen (4-tap + * scaling is not implemented for RGB and packed yuv currently) */ + s = "videotestsrc num-buffers=2 ! video/x-raw-rgb,width=64,height=64 ! " + "ffmpegcolorspace ! videoscale method=4-tap ! ffmpegcolorspace ! " + "video/x-raw-rgb,width=32,height=32,framerate=(fraction)30/1," + "pixel-aspect-ratio=(fraction)1/1,bpp=(int)24,depth=(int)24," + "red_mask=(int)16711680,green_mask=(int)65280,blue_mask=(int)255," + "endianness=(int)4321 ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + s = "videotestsrc num-buffers=2 ! video/x-raw-yuv,format=(fourcc)AYUV," + "width=64,height=64 ! ffmpegcolorspace ! videoscale method=4-tap ! " + "ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)AYUV,width=32," + "height=32 ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); + /* make sure nothing funny happens in passthrough mode (we don't check that + * passthrough mode is chosen though) */ + s = "videotestsrc num-buffers=2 ! video/x-raw-yuv,format=(fourcc)I420," + "width=64,height=64 ! ffmpegcolorspace ! videoscale method=4-tap ! " + "ffmpegcolorspace ! video/x-raw-yuv,format=(fourcc)I420,width=32," + "height=32 ! fakesink"; + run_pipeline (setup_pipeline (s), s, + GST_MESSAGE_ANY & ~(GST_MESSAGE_ERROR | GST_MESSAGE_WARNING), + GST_MESSAGE_UNKNOWN); +} + +GST_END_TEST; + +#endif /* #ifndef GST_DISABLE_PARSE */ +static Suite * +simple_launch_lines_suite (void) +{ + Suite *s = suite_create ("Pipelines"); + TCase *tc_chain = tcase_create ("linear"); + + /* time out after 60s, not the default 3 */ + tcase_set_timeout (tc_chain, 60); + + suite_add_tcase (s, tc_chain); +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_element_negotiation); + tcase_add_test (tc_chain, test_basetransform_based); +#endif + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = simple_launch_lines_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/streamheader.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/streamheader.c new file mode 100644 index 0000000..c3872ad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/streamheader.c @@ -0,0 +1,256 @@ +/* GStreamer + * + * unit test for streamheader handling + * + * Copyright (C) 2007 Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +#ifndef GST_DISABLE_PARSE + +/* this tests a gdp-serialized tag from audiotestsrc being sent only once + * to clients of multifdsink */ + +static int n_tags = 0; + +static gboolean +tag_event_probe_cb (GstPad * pad, GstEvent * event, GMainLoop * loop) +{ + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG: + { + ++n_tags; + fail_if (n_tags > 1, "More than 1 tag received"); + break; + } + case GST_EVENT_EOS: + { + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + +GST_START_TEST (test_multifdsink_gdp_tag) +{ + GstElement *p1, *p2; + GstElement *src, *sink, *depay; + GstPad *pad; + GMainLoop *loop; + int pfd[2]; + + loop = g_main_loop_new (NULL, FALSE); + + p1 = gst_parse_launch ("audiotestsrc num-buffers=10 ! gdppay" + " ! multifdsink name=p1sink", NULL); + fail_if (p1 == NULL); + p2 = gst_parse_launch ("fdsrc name=p2src ! gdpdepay name=depay" + " ! fakesink name=p2sink signal-handoffs=True", NULL); + fail_if (p2 == NULL); + + fail_if (pipe (pfd) == -1); + + + gst_element_set_state (p1, GST_STATE_READY); + + sink = gst_bin_get_by_name (GST_BIN (p1), "p1sink"); + g_signal_emit_by_name (sink, "add", pfd[1], NULL); + gst_object_unref (sink); + + src = gst_bin_get_by_name (GST_BIN (p2), "p2src"); + g_object_set (G_OBJECT (src), "fd", pfd[0], NULL); + gst_object_unref (src); + + depay = gst_bin_get_by_name (GST_BIN (p2), "depay"); + fail_if (depay == NULL); + + pad = gst_element_get_static_pad (depay, "src"); + fail_unless (pad != NULL, "Could not get pad out of depay"); + gst_object_unref (depay); + + gst_pad_add_event_probe (pad, G_CALLBACK (tag_event_probe_cb), loop); + + gst_element_set_state (p1, GST_STATE_PLAYING); + gst_element_set_state (p2, GST_STATE_PLAYING); + + g_main_loop_run (loop); + + assert_equals_int (n_tags, 1); + + gst_element_set_state (p1, GST_STATE_NULL); + gst_object_unref (p1); + gst_element_set_state (p2, GST_STATE_NULL); + gst_object_unref (p2); +} + +GST_END_TEST; + +#ifdef HAVE_VORBIS +/* this tests gdp-serialized Vorbis header pages being sent only once + * to clients of multifdsink; the gdp depayloader should deserialize + * exactly three in_caps buffers for the three header packets */ + +static int n_in_caps = 0; + +static gboolean +buffer_probe_cb (GstPad * pad, GstBuffer * buffer) +{ + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS)) { + GstCaps *caps; + GstStructure *s; + const GValue *sh; + GArray *buffers; + GstBuffer *buf; + int i; + gboolean found = FALSE; + + n_in_caps++; + + caps = gst_buffer_get_caps (buffer); + s = gst_caps_get_structure (caps, 0); + fail_unless (gst_structure_has_field (s, "streamheader")); + sh = gst_structure_get_value (s, "streamheader"); + buffers = g_value_peek_pointer (sh); + assert_equals_int (buffers->len, 3); + + + for (i = 0; i < 3; ++i) { + GValue *val; + + val = &g_array_index (buffers, GValue, i); + buf = g_value_peek_pointer (val); + fail_unless (GST_IS_BUFFER (buf)); + if (GST_BUFFER_SIZE (buf) == GST_BUFFER_SIZE (buffer)) { + if (memcmp (GST_BUFFER_DATA (buf), GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)) == 0) { + found = TRUE; + } + } + } + fail_unless (found, "Did not find incoming IN_CAPS buffer %p on caps", + buffer); + + gst_caps_unref (caps); + } + + return TRUE; +} + +GST_START_TEST (test_multifdsink_gdp_vorbisenc) +{ + GstElement *p1, *p2; + GstElement *src, *sink, *depay; + GstPad *pad; + GMainLoop *loop; + int pfd[2]; + + loop = g_main_loop_new (NULL, FALSE); + + p1 = gst_parse_launch ("audiotestsrc num-buffers=10 ! audioconvert " + " ! vorbisenc ! gdppay ! multifdsink name=p1sink", NULL); + fail_if (p1 == NULL); + p2 = gst_parse_launch ("fdsrc name=p2src ! gdpdepay name=depay" + " ! fakesink name=p2sink signal-handoffs=True", NULL); + fail_if (p2 == NULL); + + fail_if (pipe (pfd) == -1); + + + gst_element_set_state (p1, GST_STATE_READY); + + sink = gst_bin_get_by_name (GST_BIN (p1), "p1sink"); + g_signal_emit_by_name (sink, "add", pfd[1], NULL); + gst_object_unref (sink); + + src = gst_bin_get_by_name (GST_BIN (p2), "p2src"); + g_object_set (G_OBJECT (src), "fd", pfd[0], NULL); + gst_object_unref (src); + + depay = gst_bin_get_by_name (GST_BIN (p2), "depay"); + fail_if (depay == NULL); + + pad = gst_element_get_static_pad (depay, "src"); + fail_unless (pad != NULL, "Could not get pad out of depay"); + gst_object_unref (depay); + + gst_pad_add_event_probe (pad, G_CALLBACK (tag_event_probe_cb), loop); + gst_pad_add_buffer_probe (pad, G_CALLBACK (buffer_probe_cb), NULL); + + gst_element_set_state (p1, GST_STATE_PLAYING); + gst_element_set_state (p2, GST_STATE_PLAYING); + + g_main_loop_run (loop); + + assert_equals_int (n_in_caps, 3); + + gst_element_set_state (p1, GST_STATE_NULL); + gst_object_unref (p1); + gst_element_set_state (p2, GST_STATE_NULL); + gst_object_unref (p2); +} + +GST_END_TEST; +#endif /* HAVE_VORBIS */ + +#endif /* #ifndef GST_DISABLE_PARSE */ + +static Suite * +streamheader_suite (void) +{ + Suite *s = suite_create ("streamheader"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_multifdsink_gdp_tag); +#ifdef HAVE_VORBIS + tcase_add_test (tc_chain, test_multifdsink_gdp_vorbisenc); +#endif +#endif + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = streamheader_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/theoraenc.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/theoraenc.c new file mode 100644 index 0000000..ddc37d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/theoraenc.c @@ -0,0 +1,463 @@ +/* GStreamer + * + * unit test for theoraenc + * + * Copyright (C) 2006 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +#ifndef GST_DISABLE_PARSE + +#define TIMESTAMP_OFFSET G_GINT64_CONSTANT(3249870963) +#define FRAMERATE 10 + +/* I know all of these have a shift of 6 bits */ +#define GRANULEPOS_SHIFT 6 + + +#define check_buffer_is_header(buffer,is_header) \ + fail_unless (GST_BUFFER_FLAG_IS_SET (buffer, \ + GST_BUFFER_FLAG_IN_CAPS) == is_header, \ + "GST_BUFFER_IN_CAPS is set to %d but expected %d", \ + GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_IN_CAPS), is_header) + +#define check_buffer_timestamp(buffer,timestamp) \ + fail_unless (GST_BUFFER_TIMESTAMP (buffer) == timestamp, \ + "expected timestamp %" GST_TIME_FORMAT \ + ", but got timestamp %" GST_TIME_FORMAT, \ + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))) + +#define check_buffer_duration(buffer,duration) \ + fail_unless (GST_BUFFER_DURATION (buffer) == duration, \ + "expected duration %" GST_TIME_FORMAT \ + ", but got duration %" GST_TIME_FORMAT, \ + GST_TIME_ARGS (duration), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))) + +static gboolean old_libtheora; + +static void +check_libtheora (void) +{ + old_libtheora = (theora_version_number () <= 0x00030200); +} + +static void +check_buffer_granulepos (GstBuffer * buffer, gint64 granulepos) +{ + GstClockTime clocktime; + int framecount; + + /* With old versions of libtheora, the granulepos represented the + * start time, not end time. Adapt for that. */ + if (old_libtheora) { + if (granulepos >> GRANULEPOS_SHIFT) + granulepos -= 1 << GRANULEPOS_SHIFT; + else if (granulepos) + granulepos -= 1; + } + + fail_unless (GST_BUFFER_OFFSET_END (buffer) == granulepos, + "expected granulepos %" G_GUINT64_FORMAT + ", but got granulepos %" G_GUINT64_FORMAT, + granulepos, GST_BUFFER_OFFSET_END (buffer)); + + /* contrary to what we record as TIMESTAMP, we can use OFFSET to check + * the granulepos correctly here */ + framecount = GST_BUFFER_OFFSET_END (buffer); + framecount = granulepos >> GRANULEPOS_SHIFT; + framecount += granulepos & ((1 << GRANULEPOS_SHIFT) - 1); + clocktime = gst_util_uint64_scale (framecount, GST_SECOND, FRAMERATE); + + fail_unless (clocktime == GST_BUFFER_OFFSET (buffer), + "expected OFFSET set to clocktime %" GST_TIME_FORMAT + ", but got %" GST_TIME_FORMAT, + GST_TIME_ARGS (clocktime), GST_TIME_ARGS (GST_BUFFER_OFFSET (buffer))); +} + +/* this check is here to check that the granulepos we derive from the + timestamp is about correct. This is "about correct" because you can't + precisely go from timestamp to granulepos due to the downward-rounding + characteristics of gst_util_uint64_scale, so you check if granulepos is + equal to the number, or the number plus one. */ +/* should be from_endtime, but theora's granulepos mapping is "special" */ +static void +check_buffer_granulepos_from_starttime (GstBuffer * buffer, + GstClockTime starttime) +{ + gint64 granulepos, expected, framecount; + + granulepos = GST_BUFFER_OFFSET_END (buffer); + /* Now convert to 'granulepos for start time', depending on libtheora + * version */ + if (!old_libtheora) { + if (granulepos & ((1 << GRANULEPOS_SHIFT) - 1)) + granulepos -= 1; + else if (granulepos) + granulepos -= 1 << GRANULEPOS_SHIFT; + } + + framecount = granulepos >> GRANULEPOS_SHIFT; + framecount += granulepos & ((1 << GRANULEPOS_SHIFT) - 1); + expected = gst_util_uint64_scale (starttime, FRAMERATE, GST_SECOND); + + fail_unless (framecount == expected || framecount == expected + 1, + "expected frame count %" G_GUINT64_FORMAT + " or %" G_GUINT64_FORMAT + ", but got frame count %" G_GUINT64_FORMAT, + expected, expected + 1, framecount); +} + +GST_START_TEST (test_granulepos_offset) +{ + GstElement *bin; + GstPad *pad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + + pipe_str = g_strdup_printf ("videotestsrc timestamp-offset=%" G_GUINT64_FORMAT + " num-buffers=10 ! video/x-raw-yuv,format=(fourcc)I420,framerate=10/1" + " ! theoraenc ! fakesink name=fs0", TIMESTAMP_OFFSET); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fs0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + gst_buffer_straw_start_pipeline (bin, pad); + + /* header packets should have timestamp == NONE, granulepos 0, IN_CAPS */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + { + GstClockTime next_timestamp; + gint64 last_granulepos; + + /* first buffer should have timestamp of TIMESTAMP_OFFSET, granulepos to + * match the timestamp of the end of the last sample in the output buffer. + * Note that one cannot go timestamp->granulepos->timestamp and get the + * same value due to loss of precision with granulepos. theoraenc does + * take care to timestamp correctly based on the offset of the input data + * however, so it does do sub-granulepos timestamping. */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + last_granulepos = GST_BUFFER_OFFSET_END (buffer); + check_buffer_timestamp (buffer, TIMESTAMP_OFFSET); + /* don't really have a good way of checking duration... */ + check_buffer_granulepos_from_starttime (buffer, TIMESTAMP_OFFSET); + check_buffer_is_header (buffer, FALSE); + + next_timestamp = TIMESTAMP_OFFSET + GST_BUFFER_DURATION (buffer); + + gst_buffer_unref (buffer); + + /* check continuity with the next buffer */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, next_timestamp); + check_buffer_duration (buffer, + gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND, + FRAMERATE) + - gst_util_uint64_scale (last_granulepos, GST_SECOND, FRAMERATE)); + check_buffer_granulepos_from_starttime (buffer, next_timestamp); + check_buffer_is_header (buffer, FALSE); + + gst_buffer_unref (buffer); + } + + gst_buffer_straw_stop_pipeline (bin, pad); + + gst_object_unref (pad); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_continuity) +{ + GstElement *bin; + GstPad *pad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + + pipe_str = g_strdup_printf ("videotestsrc num-buffers=10" + " ! video/x-raw-yuv,format=(fourcc)I420,framerate=10/1" + " ! theoraenc ! fakesink name=fs0"); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fs0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + gst_buffer_straw_start_pipeline (bin, pad); + + /* header packets should have timestamp == NONE, granulepos 0 */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + { + GstClockTime next_timestamp; + gint64 last_granulepos; + + /* first buffer should have timestamp of TIMESTAMP_OFFSET, granulepos to + * match the timestamp of the end of the last sample in the output buffer. + * Note that one cannot go timestamp->granulepos->timestamp and get the + * same value due to loss of precision with granulepos. theoraenc does + * take care to timestamp correctly based on the offset of the input data + * however, so it does do sub-granulepos timestamping. */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + last_granulepos = GST_BUFFER_OFFSET_END (buffer); + check_buffer_timestamp (buffer, 0); + /* plain division because I know the answer is exact */ + check_buffer_duration (buffer, GST_SECOND / 10); + check_buffer_granulepos (buffer, 1 << GRANULEPOS_SHIFT); + check_buffer_is_header (buffer, FALSE); + + next_timestamp = GST_BUFFER_DURATION (buffer); + + gst_buffer_unref (buffer); + + /* check continuity with the next buffer */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, next_timestamp); + check_buffer_duration (buffer, GST_SECOND / 10); + check_buffer_granulepos (buffer, (1 << GRANULEPOS_SHIFT) | 1); + check_buffer_is_header (buffer, FALSE); + + gst_buffer_unref (buffer); + } + + gst_buffer_straw_stop_pipeline (bin, pad); + + gst_object_unref (pad); + gst_object_unref (bin); +} + +GST_END_TEST; + +static gboolean +drop_second_data_buffer (GstPad * droppad, GstBuffer * buffer, gpointer unused) +{ + return !(GST_BUFFER_OFFSET (buffer) == 1); +} + +GST_START_TEST (test_discontinuity) +{ + GstElement *bin; + GstPad *pad, *droppad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + guint drop_id; + + pipe_str = g_strdup_printf ("videotestsrc num-buffers=10" + " ! video/x-raw-yuv,format=(fourcc)I420,framerate=10/1" + " ! theoraenc ! fakesink name=fs0"); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* the plan: same as test_continuity, but dropping a buffer and seeing if + theoraenc correctly notes the discontinuity */ + + /* get the pad to use to drop buffers */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "theoraenc0"); + + fail_unless (sink != NULL, "Could not get theoraenc out of bin"); + droppad = gst_element_get_static_pad (sink, "sink"); + fail_unless (droppad != NULL, "Could not get pad out of theoraenc"); + gst_object_unref (sink); + } + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fs0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + drop_id = gst_pad_add_buffer_probe (droppad, + G_CALLBACK (drop_second_data_buffer), NULL); + gst_buffer_straw_start_pipeline (bin, pad); + + /* header packets should have timestamp == NONE, granulepos 0 */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + check_buffer_is_header (buffer, TRUE); + gst_buffer_unref (buffer); + + { + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, 0); + /* plain division because I know the answer is exact */ + check_buffer_duration (buffer, GST_SECOND / 10); + check_buffer_granulepos (buffer, 1 << GRANULEPOS_SHIFT); + check_buffer_is_header (buffer, FALSE); + fail_if (GST_BUFFER_IS_DISCONT (buffer), "expected continuous buffer yo"); + gst_buffer_unref (buffer); + + /* check discontinuity with the next buffer */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_duration (buffer, GST_SECOND / 10); + /* After a discont, we'll always get a keyframe, so this one should be + * 3< + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#ifndef GST_DISABLE_PARSE + +static GMainLoop *loop; +static gint messages = 0; + +static void +element_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + gchar *s; + + s = gst_structure_to_string (gst_message_get_structure (message)); + GST_DEBUG ("Received message: %s", s); + g_free (s); + + messages++; +} + +static void +eos_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + GST_DEBUG ("Received eos"); + g_main_loop_quit (loop); +} + +GST_START_TEST (test_timestamps) +{ + GstElement *pipeline; + gchar *pipe_str; + GstBus *bus; + GError *error = NULL; + + pipe_str = g_strdup_printf ("audiotestsrc num-buffers=100" + " ! audio/x-raw-int,rate=44100 ! audioconvert ! vorbisenc ! vorbisdec" + " ! identity check-imperfect-timestamp=TRUE ! fakesink"); + + pipeline = gst_parse_launch (pipe_str, &error); + fail_unless (pipeline != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + bus = gst_element_get_bus (pipeline); + fail_if (bus == NULL); + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message::element", (GCallback) element_message_cb, + NULL); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_cb, NULL); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* run until we receive EOS */ + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + fail_if (messages > 0, "Received imperfect timestamp messages"); + gst_object_unref (pipeline); +} + +GST_END_TEST; +#endif /* #ifndef GST_DISABLE_PARSE */ + +static Suite * +vorbisenc_suite (void) +{ + Suite *s = suite_create ("vorbisenc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_timestamps); +#endif + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = vorbisenc_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/gst-plugins-base-subtitles0.10/tests/check/pipelines/vorbisenc.c b/gst-plugins-base-subtitles0.10/tests/check/pipelines/vorbisenc.c new file mode 100644 index 0000000..b207dff --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/pipelines/vorbisenc.c @@ -0,0 +1,410 @@ +/* GStreamer + * + * unit test for vorbisenc + * + * Copyright (C) 2006 Andy Wingo + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#ifndef GST_DISABLE_PARSE + +#define TIMESTAMP_OFFSET G_GINT64_CONSTANT(3249870963) + +static void +check_buffer_timestamp (GstBuffer * buffer, GstClockTime timestamp) +{ + fail_unless (GST_BUFFER_TIMESTAMP (buffer) == timestamp, + "expected timestamp %" GST_TIME_FORMAT + ", but got timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); +} + +static void +check_buffer_duration (GstBuffer * buffer, GstClockTime duration) +{ + fail_unless (GST_BUFFER_DURATION (buffer) == duration, + "expected duration %" GST_TIME_FORMAT + ", but got duration %" GST_TIME_FORMAT, + GST_TIME_ARGS (duration), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); +} + +static void +check_buffer_granulepos (GstBuffer * buffer, gint64 granulepos) +{ + GstClockTime clocktime; + + fail_unless (GST_BUFFER_OFFSET_END (buffer) == granulepos, + "expected granulepos %" G_GUINT64_FORMAT + ", but got granulepos %" G_GUINT64_FORMAT, + granulepos, GST_BUFFER_OFFSET_END (buffer)); + + /* contrary to what we record as TIMESTAMP, we can use OFFSET to check + * the granulepos correctly here */ + clocktime = gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), 44100, + GST_SECOND); + + fail_unless (clocktime == GST_BUFFER_OFFSET (buffer), + "expected OFFSET set to clocktime %" GST_TIME_FORMAT + ", but got %" GST_TIME_FORMAT, + GST_TIME_ARGS (clocktime), GST_TIME_ARGS (GST_BUFFER_OFFSET (buffer))); +} + +/* this check is here to check that the granulepos we derive from the timestamp + is about correct. This is "about correct" because you can't precisely go from + timestamp to granulepos due to the downward-rounding characteristics of + gst_util_uint64_scale, so you check if granulepos is equal to the number, or + the number plus one. */ +static void +check_buffer_granulepos_from_endtime (GstBuffer * buffer, GstClockTime endtime) +{ + gint64 granulepos, expected; + + granulepos = GST_BUFFER_OFFSET_END (buffer); + expected = gst_util_uint64_scale (endtime, 44100, GST_SECOND); + + fail_unless (granulepos == expected || granulepos == expected + 1, + "expected granulepos %" G_GUINT64_FORMAT + " or %" G_GUINT64_FORMAT + ", but got granulepos %" G_GUINT64_FORMAT, + expected, expected + 1, granulepos); +} + +GST_START_TEST (test_granulepos_offset) +{ + GstElement *bin; + GstPad *pad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + + pipe_str = g_strdup_printf ("audiotestsrc timestamp-offset=%" G_GUINT64_FORMAT + " ! audio/x-raw-int,rate=44100" + " ! audioconvert ! vorbisenc ! fakesink", TIMESTAMP_OFFSET); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fakesink0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + gst_buffer_straw_start_pipeline (bin, pad); + + /* header packets should have timestamp == NONE, granulepos 0 */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + GST_DEBUG ("Got buffer in test"); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + GST_DEBUG ("Unreffed buffer in test"); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + { + GstClockTime next_timestamp; + gint64 last_granulepos = 0; + + /* first buffer should have timestamp of TIMESTAMP_OFFSET, granulepos to + * match the timestamp of the end of the last sample in the output buffer. + * Note that one cannot go timestamp->granulepos->timestamp and get the same + * value due to loss of precision with granulepos. vorbisenc does take care + * to timestamp correctly based on the offset of the input data however, so + * it does do sub-granulepos timestamping. */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + last_granulepos = GST_BUFFER_OFFSET_END (buffer); + check_buffer_timestamp (buffer, TIMESTAMP_OFFSET); + /* don't really have a good way of checking duration... */ + check_buffer_granulepos_from_endtime (buffer, + TIMESTAMP_OFFSET + GST_BUFFER_DURATION (buffer)); + + next_timestamp = TIMESTAMP_OFFSET + GST_BUFFER_DURATION (buffer); + + gst_buffer_unref (buffer); + + /* check continuity with the next buffer */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, next_timestamp); + check_buffer_duration (buffer, + gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND, + 44100) + - gst_util_uint64_scale (last_granulepos, GST_SECOND, 44100)); + check_buffer_granulepos_from_endtime (buffer, + next_timestamp + GST_BUFFER_DURATION (buffer)); + + gst_buffer_unref (buffer); + } + + gst_buffer_straw_stop_pipeline (bin, pad); + + gst_object_unref (pad); + gst_object_unref (bin); +} + +GST_END_TEST; + +GST_START_TEST (test_timestamps) +{ + GstElement *bin; + GstPad *pad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + + pipe_str = g_strdup_printf ("audiotestsrc" + " ! audio/x-raw-int,rate=44100 ! audioconvert ! vorbisenc ! fakesink"); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fakesink0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + gst_buffer_straw_start_pipeline (bin, pad); + + /* check header packets */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + { + GstClockTime next_timestamp; + gint64 last_granulepos; + + /* first buffer has timestamp 0 */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + last_granulepos = GST_BUFFER_OFFSET_END (buffer); + check_buffer_timestamp (buffer, 0); + /* don't really have a good way of checking duration... */ + check_buffer_granulepos_from_endtime (buffer, GST_BUFFER_DURATION (buffer)); + + next_timestamp = GST_BUFFER_DURATION (buffer); + + gst_buffer_unref (buffer); + + /* check continuity with the next buffer */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, next_timestamp); + check_buffer_duration (buffer, + gst_util_uint64_scale (GST_BUFFER_OFFSET_END (buffer), GST_SECOND, + 44100) + - gst_util_uint64_scale (last_granulepos, GST_SECOND, 44100)); + check_buffer_granulepos_from_endtime (buffer, + next_timestamp + GST_BUFFER_DURATION (buffer)); + + gst_buffer_unref (buffer); + } + + gst_buffer_straw_stop_pipeline (bin, pad); + + gst_object_unref (pad); + gst_object_unref (bin); +} + +GST_END_TEST; + +static gboolean +drop_second_data_buffer (GstPad * droppad, GstBuffer * buffer, gpointer unused) +{ + return !(GST_BUFFER_OFFSET (buffer) == 1024); +} + +GST_START_TEST (test_discontinuity) +{ + GstElement *bin; + GstPad *pad, *droppad; + gchar *pipe_str; + GstBuffer *buffer; + GError *error = NULL; + guint drop_id; + + pipe_str = g_strdup_printf ("audiotestsrc samplesperbuffer=1024" + " ! audio/x-raw-int,rate=44100" " ! audioconvert ! vorbisenc ! fakesink"); + + bin = gst_parse_launch (pipe_str, &error); + fail_unless (bin != NULL, "Error parsing pipeline: %s", + error ? error->message : "(invalid error)"); + g_free (pipe_str); + + /* the plan: same as test_timestamps, but dropping a buffer and seeing if + vorbisenc correctly notes the discontinuity */ + + /* get the pad to use to drop buffers */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "vorbisenc0"); + + fail_unless (sink != NULL, "Could not get vorbisenc out of bin"); + droppad = gst_element_get_static_pad (sink, "sink"); + fail_unless (droppad != NULL, "Could not get pad out of vorbisenc"); + gst_object_unref (sink); + } + + /* get the pad */ + { + GstElement *sink = gst_bin_get_by_name (GST_BIN (bin), "fakesink0"); + + fail_unless (sink != NULL, "Could not get fakesink out of bin"); + pad = gst_element_get_static_pad (sink, "sink"); + fail_unless (pad != NULL, "Could not get pad out of fakesink"); + gst_object_unref (sink); + } + + drop_id = gst_pad_add_buffer_probe (droppad, + G_CALLBACK (drop_second_data_buffer), NULL); + gst_buffer_straw_start_pipeline (bin, pad); + + /* check header packets */ + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + buffer = gst_buffer_straw_get_buffer (bin, pad); + check_buffer_timestamp (buffer, GST_CLOCK_TIME_NONE); + check_buffer_duration (buffer, GST_CLOCK_TIME_NONE); + check_buffer_granulepos (buffer, 0); + gst_buffer_unref (buffer); + + /* two phases: continuous granulepos values up to 1024, then a first + discontinuous granulepos whose granulepos corresponds to a gap ending at + 2048. */ + { + GstClockTime next_timestamp = 0; + gint64 last_granulepos = 0; + + while (last_granulepos < 1024) { + buffer = gst_buffer_straw_get_buffer (bin, pad); + last_granulepos = GST_BUFFER_OFFSET_END (buffer); + check_buffer_timestamp (buffer, next_timestamp); + fail_if (GST_BUFFER_IS_DISCONT (buffer), "expected continuous buffer"); + next_timestamp += GST_BUFFER_DURATION (buffer); + gst_buffer_unref (buffer); + } + + fail_unless (last_granulepos == 1024, + "unexpected granulepos: %" G_GUINT64_FORMAT, last_granulepos); + } + + { + buffer = gst_buffer_straw_get_buffer (bin, pad); + /* The first buffer after the discontinuity will produce zero output + * samples (because of the overlap/add), so it won't increment the + * granulepos, which should be 2048 after the discontinuity. + */ + fail_unless (GST_BUFFER_OFFSET_END (buffer) == 2048, + "expected granulepos after gap: %" G_GUINT64_FORMAT, + GST_BUFFER_OFFSET_END (buffer)); + fail_unless (GST_BUFFER_IS_DISCONT (buffer), + "expected discontinuous buffer"); + gst_buffer_unref (buffer); + } + + gst_buffer_straw_stop_pipeline (bin, pad); + gst_pad_remove_buffer_probe (droppad, drop_id); + + gst_object_unref (droppad); + gst_object_unref (pad); + gst_object_unref (bin); +} + +GST_END_TEST; + +#endif /* #ifndef GST_DISABLE_PARSE */ + +static Suite * +vorbisenc_suite (void) +{ + Suite *s = suite_create ("vorbisenc"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); +#ifndef GST_DISABLE_PARSE + tcase_add_test (tc_chain, test_granulepos_offset); + tcase_add_test (tc_chain, test_timestamps); + tcase_add_test (tc_chain, test_discontinuity); +#endif + + return s; +} + +int +main (int argc, char **argv) +{ + int nf; + + Suite *s = vorbisenc_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/gst-plugins-base-subtitles0.10/tests/check/tests.xml b/gst-plugins-base-subtitles0.10/tests/check/tests.xml new file mode 100644 index 0000000..4d06d6f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/check/tests.xml @@ -0,0 +1,160 @@ + + + + + + /usr/share/gstreamer0.10-plugins-base-tests/alsa + + + /usr/share/gstreamer0.10-plugins-base-tests/gio + + + /usr/share/gstreamer0.10-plugins-base-tests/oggmux + + + /usr/share/gstreamer0.10-plugins-base-tests/textoverlay + + + /usr/share/gstreamer0.10-plugins-base-tests/adder + + + /usr/share/gstreamer0.10-plugins-base-tests/appsink + + + /usr/share/gstreamer0.10-plugins-base-tests/appsrc + + + /usr/share/gstreamer0.10-plugins-base-tests/audioconvert + + + /usr/share/gstreamer0.10-plugins-base-tests/audiorate + + + /usr/share/gstreamer0.10-plugins-base-tests/audioresample + + + /usr/share/gstreamer0.10-plugins-base-tests/audiotestsrc + + + /usr/share/gstreamer0.10-plugins-base-tests/decodebin + + + /usr/share/gstreamer0.10-plugins-base-tests/decodebin2 + + + /usr/share/gstreamer0.10-plugins-base-tests/encodebin + + + /usr/share/gstreamer0.10-plugins-base-tests/ffmpegcolorspace2 + + + /usr/share/gstreamer0.10-plugins-base-tests/gdpdepay + + + /usr/share/gstreamer0.10-plugins-base-tests/gdppay + + + /usr/share/gstreamer0.10-plugins-base-tests/multifdsink + + + /usr/share/gstreamer0.10-plugins-base-tests/playbin + + + /usr/share/gstreamer0.10-plugins-base-tests/playbin2 + + + /usr/share/gstreamer0.10-plugins-base-tests/subparse + + + /usr/share/gstreamer0.10-plugins-base-tests/videorate + + + /usr/share/gstreamer0.10-plugins-base-tests/videoscale + + + /usr/share/gstreamer0.10-plugins-base-tests/videotestsrc + + + /usr/share/gstreamer0.10-plugins-base-tests/volume + + + /usr/share/gstreamer0.10-plugins-base-tests/clock-selection + + + /usr/share/gstreamer0.10-plugins-base-tests/states + + + /usr/share/gstreamer0.10-plugins-base-tests/typefindfunctions + + + /usr/share/gstreamer0.10-plugins-base-tests/audio + + + /usr/share/gstreamer0.10-plugins-base-tests/cddabasesrc + + + /usr/share/gstreamer0.10-plugins-base-tests/fft + + + /usr/share/gstreamer0.10-plugins-base-tests/mixer + + + /usr/share/gstreamer0.10-plugins-base-tests/navigation + + + /usr/share/gstreamer0.10-plugins-base-tests/netbuffer + + + /usr/share/gstreamer0.10-plugins-base-tests/pbutils + + + /usr/share/gstreamer0.10-plugins-base-tests/profile + + + /usr/share/gstreamer0.10-plugins-base-tests/rtp + + + /usr/share/gstreamer0.10-plugins-base-tests/rtsp + + + /usr/share/gstreamer0.10-plugins-base-tests/tag + + + /usr/share/gstreamer0.10-plugins-base-tests/video + + + /usr/share/gstreamer0.10-plugins-base-tests/orc/adder + + + /usr/share/gstreamer0.10-plugins-base-tests/orc/audioconvert + + + /usr/share/gstreamer0.10-plugins-base-tests/orc/videoscale + + + /usr/share/gstreamer0.10-plugins-base-tests/orc/volume + + + /usr/share/gstreamer0.10-plugins-base-tests/orc/videotestsrc + + + /usr/share/gstreamer0.10-plugins-base-tests/simple-launch-lines + + + /usr/share/gstreamer0.10-plugins-base-tests/streamheader + + + /usr/share/gstreamer0.10-plugins-base-tests/basetime + + + /usr/share/gstreamer0.10-plugins-base-tests/capsfilter-renegotiation + + + true + true + + + + + + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/Makefile.am new file mode 100644 index 0000000..48c38a5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/Makefile.am @@ -0,0 +1,15 @@ +if HAVE_FT2 +FT2_SUBDIRS = seek snapshot +else +FT2_SUBDIRS = +endif + +if USE_GIO +GIO_SUBDIRS = gio +endif + +SUBDIRS = app dynamic $(FT2_SUBDIRS) $(GIO_SUBDIRS) overlay playrec volume v4l encoding + +DIST_SUBDIRS = app dynamic gio overlay seek snapshot playrec volume v4l encoding + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/app/.gitignore new file mode 100644 index 0000000..8a2c761 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/.gitignore @@ -0,0 +1,6 @@ +appsrc_ex +appsrc-ra +appsrc-seekable +appsrc-stream +appsrc-stream2 +appsink-src diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/app/Makefile.am new file mode 100644 index 0000000..4f17ad7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/Makefile.am @@ -0,0 +1,32 @@ + +noinst_PROGRAMS = appsrc_ex appsrc-stream appsrc-stream2 appsrc-ra \ + appsrc-seekable appsink-src + +appsrc_ex_SOURCES = appsrc_ex.c +appsrc_ex_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsrc_ex_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) + +appsrc_stream_SOURCES = appsrc-stream.c +appsrc_stream_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsrc_stream_LDADD = $(GST_BASE_LIBS) $(GST_LIBS) + +appsrc_stream2_SOURCES = appsrc-stream2.c +appsrc_stream2_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsrc_stream2_LDADD = $(GST_BASE_LIBS) $(GST_LIBS) + +appsrc_ra_SOURCES = appsrc-ra.c +appsrc_ra_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsrc_ra_LDADD = $(GST_BASE_LIBS) $(GST_LIBS) + +appsrc_seekable_SOURCES = appsrc-seekable.c +appsrc_seekable_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsrc_seekable_LDADD = $(GST_BASE_LIBS) $(GST_LIBS) + +appsink_src_SOURCES = appsink-src.c +appsink_src_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +appsink_src_LDADD = \ + $(top_builddir)/gst-libs/gst/app/libgstapp-@GST_MAJORMINOR@.la \ + $(GST_BASE_LIBS) $(GST_LIBS) + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsink-src.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsink-src.c new file mode 100644 index 0000000..a92dfb5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsink-src.c @@ -0,0 +1,192 @@ +#include + +#include + +#include +#include +#include + +/* these are the caps we are going to pass through the appsink and appsrc */ +const gchar *audio_caps = + "audio/x-raw-int,channels=1,rate=8000,signed=(boolean)true,width=16,depth=16,endianness=1234"; + +typedef struct +{ + GMainLoop *loop; + GstElement *source; + GstElement *sink; +} ProgramData; + +/* called when the appsink notifies us that there is a new buffer ready for + * processing */ +static void +on_new_buffer_from_source (GstElement * elt, ProgramData * data) +{ + guint size; + gpointer raw_buffer; + GstBuffer *app_buffer, *buffer; + GstElement *source; + + /* get the buffer from appsink */ + buffer = gst_app_sink_pull_buffer (GST_APP_SINK (elt)); + + /* turn it into an app buffer, it's not really needed, we could simply push + * the retrieved buffer from appsink into appsrc just fine. */ + size = GST_BUFFER_SIZE (buffer); + g_print ("Pushing a buffer of size %d\n", size); + raw_buffer = g_malloc0 (size); + memcpy (raw_buffer, GST_BUFFER_DATA (buffer), size); + app_buffer = gst_app_buffer_new (raw_buffer, size, g_free, raw_buffer); + + /* newer basesrc will set caps for use automatically but it does not really + * hurt to set it on the buffer again */ + gst_buffer_set_caps (app_buffer, GST_BUFFER_CAPS (buffer)); + + /* we don't need the appsink buffer anymore */ + gst_buffer_unref (buffer); + + /* get source an push new buffer */ + source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); + gst_app_src_push_buffer (GST_APP_SRC (source), app_buffer); +} + +/* called when we get a GstMessage from the source pipeline when we get EOS, we + * notify the appsrc of it. */ +static gboolean +on_source_message (GstBus * bus, GstMessage * message, ProgramData * data) +{ + GstElement *source; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + g_print ("The source got dry\n"); + source = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); + gst_app_src_end_of_stream (GST_APP_SRC (source)); + break; + case GST_MESSAGE_ERROR: + g_print ("Received error\n"); + g_main_loop_quit (data->loop); + break; + default: + break; + } + return TRUE; +} + +/* called when we get a GstMessage from the sink pipeline when we get EOS, we + * exit the mainloop and this testapp. */ +static gboolean +on_sink_message (GstBus * bus, GstMessage * message, ProgramData * data) +{ + /* nil */ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + g_print ("Finished playback\n"); + g_main_loop_quit (data->loop); + break; + case GST_MESSAGE_ERROR: + g_print ("Received error\n"); + g_main_loop_quit (data->loop); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + gchar *filename = NULL; + ProgramData *data = NULL; + gchar *string = NULL; + GstBus *bus = NULL; + GstElement *testsink = NULL; + GstElement *testsource = NULL; + + gst_init (&argc, &argv); + + if (argc == 2) + filename = g_strdup (argv[1]); + else + filename = g_strdup ("/usr/share/sounds/ekiga/ring.wav"); + + data = g_new0 (ProgramData, 1); + + data->loop = g_main_loop_new (NULL, FALSE); + + /* setting up source pipeline, we read from a file and convert to our desired + * caps. */ + string = + g_strdup_printf + ("filesrc location=\"%s\" ! wavparse ! audioconvert ! audioresample ! appsink caps=\"%s\" name=testsink", + filename, audio_caps); + g_free (filename); + data->source = gst_parse_launch (string, NULL); + g_free (string); + + if (data->source == NULL) { + g_print ("Bad source\n"); + return -1; + } + + /* to be notified of messages from this pipeline, mostly EOS */ + bus = gst_element_get_bus (data->source); + gst_bus_add_watch (bus, (GstBusFunc) on_source_message, data); + gst_object_unref (bus); + + /* we use appsink in push mode, it sends us a signal when data is available + * and we pull out the data in the signal callback. We want the appsink to + * push as fast as it can, hence the sync=false */ + testsink = gst_bin_get_by_name (GST_BIN (data->source), "testsink"); + g_object_set (G_OBJECT (testsink), "emit-signals", TRUE, "sync", FALSE, NULL); + g_signal_connect (testsink, "new-buffer", + G_CALLBACK (on_new_buffer_from_source), data); + gst_object_unref (testsink); + + /* setting up sink pipeline, we push audio data into this pipeline that will + * then play it back using the default audio sink. We have no blocking + * behaviour on the src which means that we will push the entire file into + * memory. */ + string = + g_strdup_printf ("appsrc name=testsource caps=\"%s\" ! autoaudiosink", + audio_caps); + data->sink = gst_parse_launch (string, NULL); + g_free (string); + + if (data->sink == NULL) { + g_print ("Bad sink\n"); + return -1; + } + + testsource = gst_bin_get_by_name (GST_BIN (data->sink), "testsource"); + /* configure for time-based format */ + g_object_set (testsource, "format", GST_FORMAT_TIME, NULL); + /* uncomment the next line to block when appsrc has buffered enough */ + /* g_object_set (testsource, "block", TRUE, NULL); */ + gst_object_unref (testsource); + + bus = gst_element_get_bus (data->sink); + gst_bus_add_watch (bus, (GstBusFunc) on_sink_message, data); + gst_object_unref (bus); + + /* launching things */ + gst_element_set_state (data->sink, GST_STATE_PLAYING); + gst_element_set_state (data->source, GST_STATE_PLAYING); + + /* let's run !, this loop will quit when the sink pipeline goes EOS or when an + * error occurs in the source or sink pipelines. */ + g_print ("Let's run!\n"); + g_main_loop_run (data->loop); + g_print ("Going out\n"); + + gst_element_set_state (data->source, GST_STATE_NULL); + gst_element_set_state (data->sink, GST_STATE_NULL); + + gst_object_unref (data->source); + gst_object_unref (data->sink); + g_main_loop_unref (data->loop); + g_free (data); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-ra.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-ra.c new file mode 100644 index 0000000..af5d7a7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-ra.c @@ -0,0 +1,224 @@ +/* GStreamer + * + * appsrc-ra.c: example for using appsrc in random-access mode. + * + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +GST_DEBUG_CATEGORY (appsrc_playbin_debug); +#define GST_CAT_DEFAULT appsrc_playbin_debug + +/* + * an example application of using appsrc in random-access mode. When the + * appsrc requests data with the need-data signal, we retrieve a buffer of the + * requested size and push it to appsrc. + * + * This is a good example how one would deal with a local file resource. + * + * Appsrc in random-access mode needs seeking support and we must thus connect + * to the seek signal to perform any seeks when requested. + * + * In random-access mode we must set the size of the source material. + */ +typedef struct _App App; + +struct _App +{ + GstElement *playbin; + GstElement *appsrc; + + GMainLoop *loop; + + GMappedFile *file; + guint8 *data; + gsize length; + guint64 offset; +}; + +App s_app; + +/* This method is called by the need-data signal callback, we feed data into the + * appsrc with the requested size. + */ +static void +feed_data (GstElement * appsrc, guint size, App * app) +{ + GstBuffer *buffer; + GstFlowReturn ret; + + buffer = gst_buffer_new (); + + if (app->offset >= app->length) { + /* we are EOS, send end-of-stream */ + g_signal_emit_by_name (app->appsrc, "end-of-stream", &ret); + return; + } + + /* read the amount of data, we are allowed to return less if we are EOS */ + if (app->offset + size > app->length) + size = app->length - app->offset; + + GST_BUFFER_DATA (buffer) = app->data + app->offset; + GST_BUFFER_SIZE (buffer) = size; + /* we need to set an offset for random access */ + GST_BUFFER_OFFSET (buffer) = app->offset; + GST_BUFFER_OFFSET_END (buffer) = app->offset + size; + + GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, + app->offset, size); + g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); + gst_buffer_unref (buffer); + + app->offset += size; + + return; +} + +/* called when appsrc wants us to return data from a new position with the next + * call to push-buffer. */ +static gboolean +seek_data (GstElement * appsrc, guint64 position, App * app) +{ + GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); + app->offset = position; + + return TRUE; +} + +/* this callback is called when playbin2 has constructed a source object to read + * from. Since we provided the appsrc:// uri to playbin2, this will be the + * appsrc that we must handle. We set up some signals to push data into appsrc + * and one to perform a seek. */ +static void +found_source (GObject * object, GObject * orig, GParamSpec * pspec, App * app) +{ + /* get a handle to the appsrc */ + g_object_get (orig, pspec->name, &app->appsrc, NULL); + + GST_DEBUG ("got appsrc %p", app->appsrc); + + /* we can set the length in appsrc. This allows some elements to estimate the + * total duration of the stream. It's a good idea to set the property when you + * can but it's not required. */ + g_object_set (app->appsrc, "size", (gint64) app->length, NULL); + gst_util_set_object_arg (G_OBJECT (app->appsrc), "stream-type", + "random-access"); + + /* configure the appsrc, we will push a buffer to appsrc when it needs more + * data */ + g_signal_connect (app->appsrc, "need-data", G_CALLBACK (feed_data), app); + g_signal_connect (app->appsrc, "seek-data", G_CALLBACK (seek_data), app); +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, App * app) +{ + GST_DEBUG ("got message %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + g_error ("received error"); + g_main_loop_quit (app->loop); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (app->loop); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + GError *error = NULL; + GstBus *bus; + + gst_init (&argc, &argv); + + GST_DEBUG_CATEGORY_INIT (appsrc_playbin_debug, "appsrc-playbin", 0, + "appsrc playbin example"); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* try to open the file as an mmapped file */ + app->file = g_mapped_file_new (argv[1], FALSE, &error); + if (error) { + g_print ("failed to open file: %s\n", error->message); + g_error_free (error); + return -2; + } + /* get some vitals, this will be used to read data from the mmapped file and + * feed it to appsrc. */ + app->length = g_mapped_file_get_length (app->file); + app->data = (guint8 *) g_mapped_file_get_contents (app->file); + app->offset = 0; + + /* create a mainloop to get messages */ + app->loop = g_main_loop_new (NULL, TRUE); + + app->playbin = gst_element_factory_make ("playbin2", NULL); + g_assert (app->playbin); + + bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin)); + + /* add watch for messages */ + gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); + + /* set to read from appsrc */ + g_object_set (app->playbin, "uri", "appsrc://", NULL); + + /* get notification when the source is created so that we get a handle to it + * and can configure it */ + g_signal_connect (app->playbin, "deep-notify::source", + (GCallback) found_source, app); + + /* go to playing and wait in a mainloop. */ + gst_element_set_state (app->playbin, GST_STATE_PLAYING); + + /* this mainloop is stopped when we receive an error or EOS */ + g_main_loop_run (app->loop); + + GST_DEBUG ("stopping"); + + gst_element_set_state (app->playbin, GST_STATE_NULL); + + /* free the file */ + g_mapped_file_unref (app->file); + + gst_object_unref (bus); + g_main_loop_unref (app->loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-seekable.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-seekable.c new file mode 100644 index 0000000..9421f9b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-seekable.c @@ -0,0 +1,229 @@ +/* GStreamer + * + * appsrc-seekable.c: example for using appsrc in seekable mode. + * + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +GST_DEBUG_CATEGORY (appsrc_playbin_debug); +#define GST_CAT_DEFAULT appsrc_playbin_debug + +/* + * an example application of using appsrc in seekable mode. When the + * appsrc requests data with the need-data signal, we retrieve a buffer and + * push it to appsrc. We can also use the method as demonstrated in + * appsrc-stream.c, ie. pushing buffers when we can. + * + * This is a good example how one would deal with a remote http server that + * supports range requests. + * + * Appsrc in seekable mode needs seeking support and we must thus connect + * to the seek signal to perform any seeks when requested. + * + * In seekable mode we should set the size of the source material. + */ +typedef struct _App App; + +struct _App +{ + GstElement *playbin; + GstElement *appsrc; + + GMainLoop *loop; + + GMappedFile *file; + guint8 *data; + gsize length; + guint64 offset; +}; + +App s_app; + +#define CHUNK_SIZE 4096 + +/* This method is called by the need-data signal callback, we feed data into the + * appsrc with an arbitrary size. + */ +static void +feed_data (GstElement * appsrc, guint size, App * app) +{ + GstBuffer *buffer; + guint len; + GstFlowReturn ret; + + buffer = gst_buffer_new (); + + if (app->offset >= app->length) { + /* we are EOS, send end-of-stream */ + g_signal_emit_by_name (app->appsrc, "end-of-stream", &ret); + return; + } + + /* read any amount of data, we are allowed to return less if we are EOS */ + len = CHUNK_SIZE; + if (app->offset + len > app->length) + len = app->length - app->offset; + + GST_BUFFER_DATA (buffer) = app->data + app->offset; + GST_BUFFER_SIZE (buffer) = len; + + GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, + app->offset, len); + g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); + gst_buffer_unref (buffer); + + app->offset += len; + + return; +} + +/* called when appsrc wants us to return data from a new position with the next + * call to push-buffer. */ +static gboolean +seek_data (GstElement * appsrc, guint64 position, App * app) +{ + GST_DEBUG ("seek to offset %" G_GUINT64_FORMAT, position); + app->offset = position; + + return TRUE; +} + +/* this callback is called when playbin2 has constructed a source object to read + * from. Since we provided the appsrc:// uri to playbin2, this will be the + * appsrc that we must handle. We set up some signals to push data into appsrc + * and one to perform a seek. */ +static void +found_source (GObject * object, GObject * orig, GParamSpec * pspec, App * app) +{ + /* get a handle to the appsrc */ + g_object_get (orig, pspec->name, &app->appsrc, NULL); + + GST_DEBUG ("got appsrc %p", app->appsrc); + + /* we can set the length in appsrc. This allows some elements to estimate the + * total duration of the stream. It's a good idea to set the property when you + * can but it's not required. */ + g_object_set (app->appsrc, "size", (gint64) app->length, NULL); + /* we are seekable in push mode, this means that the element usually pushes + * out buffers of an undefined size and that seeks happen only occasionally + * and only by request of the user. */ + gst_util_set_object_arg (G_OBJECT (app->appsrc), "stream-type", "seekable"); + + /* configure the appsrc, we will push a buffer to appsrc when it needs more + * data */ + g_signal_connect (app->appsrc, "need-data", G_CALLBACK (feed_data), app); + g_signal_connect (app->appsrc, "seek-data", G_CALLBACK (seek_data), app); +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, App * app) +{ + GST_DEBUG ("got message %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + g_error ("received error"); + g_main_loop_quit (app->loop); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (app->loop); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + GError *error = NULL; + GstBus *bus; + + gst_init (&argc, &argv); + + GST_DEBUG_CATEGORY_INIT (appsrc_playbin_debug, "appsrc-playbin", 0, + "appsrc playbin example"); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* try to open the file as an mmapped file */ + app->file = g_mapped_file_new (argv[1], FALSE, &error); + if (error) { + g_print ("failed to open file: %s\n", error->message); + g_error_free (error); + return -2; + } + /* get some vitals, this will be used to read data from the mmapped file and + * feed it to appsrc. */ + app->length = g_mapped_file_get_length (app->file); + app->data = (guint8 *) g_mapped_file_get_contents (app->file); + app->offset = 0; + + /* create a mainloop to get messages */ + app->loop = g_main_loop_new (NULL, TRUE); + + app->playbin = gst_element_factory_make ("playbin2", NULL); + g_assert (app->playbin); + + bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin)); + + /* add watch for messages */ + gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); + + /* set to read from appsrc */ + g_object_set (app->playbin, "uri", "appsrc://", NULL); + + /* get notification when the source is created so that we get a handle to it + * and can configure it */ + g_signal_connect (app->playbin, "deep-notify::source", + (GCallback) found_source, app); + + /* go to playing and wait in a mainloop. */ + gst_element_set_state (app->playbin, GST_STATE_PLAYING); + + /* this mainloop is stopped when we receive an error or EOS */ + g_main_loop_run (app->loop); + + GST_DEBUG ("stopping"); + + gst_element_set_state (app->playbin, GST_STATE_NULL); + + /* free the file */ + g_mapped_file_unref (app->file); + + gst_object_unref (bus); + g_main_loop_unref (app->loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream.c new file mode 100644 index 0000000..d14e143 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream.c @@ -0,0 +1,249 @@ +/* GStreamer + * + * appsrc-stream.c: example for using appsrc in streaming mode. + * + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +GST_DEBUG_CATEGORY (appsrc_playbin_debug); +#define GST_CAT_DEFAULT appsrc_playbin_debug + +/* + * an example application of using appsrc in streaming push mode. We simply push + * buffers into appsrc. The size of the buffers we push can be any size we + * choose. + * + * This example is very close to how one would deal with a streaming webserver + * that does not support range requests or does not report the total file size. + * + * Some optimisations are done so that we don't push too much data. We connect + * to the need-data and enough-data signals to start/stop sending buffers. + * + * Appsrc in streaming mode (the default) does not support seeking so we don't + * have to handle any seek callbacks. + * + * Some formats are able to estimate the duration of the media file based on the + * file length (mp3, mpeg,..), others report an unknown length (ogg,..). + */ +typedef struct _App App; + +struct _App +{ + GstElement *playbin; + GstElement *appsrc; + + GMainLoop *loop; + guint sourceid; + + GMappedFile *file; + guint8 *data; + gsize length; + guint64 offset; +}; + +App s_app; + +#define CHUNK_SIZE 4096 + +/* This method is called by the idle GSource in the mainloop. We feed CHUNK_SIZE + * bytes into appsrc. + * The ide handler is added to the mainloop when appsrc requests us to start + * sending data (need-data signal) and is removed when appsrc has enough data + * (enough-data signal). + */ +static gboolean +read_data (App * app) +{ + GstBuffer *buffer; + guint len; + GstFlowReturn ret; + + buffer = gst_buffer_new (); + + if (app->offset >= app->length) { + /* we are EOS, send end-of-stream and remove the source */ + g_signal_emit_by_name (app->appsrc, "end-of-stream", &ret); + return FALSE; + } + + /* read the next chunk */ + len = CHUNK_SIZE; + if (app->offset + len > app->length) + len = app->length - app->offset; + + GST_BUFFER_DATA (buffer) = app->data + app->offset; + GST_BUFFER_SIZE (buffer) = len; + + GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, + app->offset, len); + g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); + gst_buffer_unref (buffer); + if (ret != GST_FLOW_OK) { + /* some error, stop sending data */ + return FALSE; + } + + app->offset += len; + + return TRUE; +} + +/* This signal callback is called when appsrc needs data, we add an idle handler + * to the mainloop to start pushing data into the appsrc */ +static void +start_feed (GstElement * playbin, guint size, App * app) +{ + if (app->sourceid == 0) { + GST_DEBUG ("start feeding"); + app->sourceid = g_idle_add ((GSourceFunc) read_data, app); + } +} + +/* This callback is called when appsrc has enough data and we can stop sending. + * We remove the idle handler from the mainloop */ +static void +stop_feed (GstElement * playbin, App * app) +{ + if (app->sourceid != 0) { + GST_DEBUG ("stop feeding"); + g_source_remove (app->sourceid); + app->sourceid = 0; + } +} + +/* this callback is called when playbin2 has constructed a source object to read + * from. Since we provided the appsrc:// uri to playbin2, this will be the + * appsrc that we must handle. We set up some signals to start and stop pushing + * data into appsrc */ +static void +found_source (GObject * object, GObject * orig, GParamSpec * pspec, App * app) +{ + /* get a handle to the appsrc */ + g_object_get (orig, pspec->name, &app->appsrc, NULL); + + GST_DEBUG ("got appsrc %p", app->appsrc); + + /* we can set the length in appsrc. This allows some elements to estimate the + * total duration of the stream. It's a good idea to set the property when you + * can but it's not required. */ + g_object_set (app->appsrc, "size", (gint64) app->length, NULL); + + /* configure the appsrc, we will push data into the appsrc from the + * mainloop. */ + g_signal_connect (app->appsrc, "need-data", G_CALLBACK (start_feed), app); + g_signal_connect (app->appsrc, "enough-data", G_CALLBACK (stop_feed), app); +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, App * app) +{ + GST_DEBUG ("got message %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + g_error ("received error"); + g_main_loop_quit (app->loop); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (app->loop); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + GError *error = NULL; + GstBus *bus; + + gst_init (&argc, &argv); + + GST_DEBUG_CATEGORY_INIT (appsrc_playbin_debug, "appsrc-playbin", 0, + "appsrc playbin example"); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* try to open the file as an mmapped file */ + app->file = g_mapped_file_new (argv[1], FALSE, &error); + if (error) { + g_print ("failed to open file: %s\n", error->message); + g_error_free (error); + return -2; + } + /* get some vitals, this will be used to read data from the mmapped file and + * feed it to appsrc. */ + app->length = g_mapped_file_get_length (app->file); + app->data = (guint8 *) g_mapped_file_get_contents (app->file); + app->offset = 0; + + /* create a mainloop to get messages and to handle the idle handler that will + * feed data to appsrc. */ + app->loop = g_main_loop_new (NULL, TRUE); + + app->playbin = gst_element_factory_make ("playbin2", NULL); + g_assert (app->playbin); + + bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin)); + + /* add watch for messages */ + gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); + + /* set to read from appsrc */ + g_object_set (app->playbin, "uri", "appsrc://", NULL); + + /* get notification when the source is created so that we get a handle to it + * and can configure it */ + g_signal_connect (app->playbin, "deep-notify::source", + (GCallback) found_source, app); + + /* go to playing and wait in a mainloop. */ + gst_element_set_state (app->playbin, GST_STATE_PLAYING); + + /* this mainloop is stopped when we receive an error or EOS */ + g_main_loop_run (app->loop); + + GST_DEBUG ("stopping"); + + gst_element_set_state (app->playbin, GST_STATE_NULL); + + /* free the file */ + g_mapped_file_unref (app->file); + + gst_object_unref (bus); + g_main_loop_unref (app->loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream2.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream2.c new file mode 100644 index 0000000..a80e4d1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc-stream2.c @@ -0,0 +1,219 @@ +/* GStreamer + * + * appsrc-stream2.c: example for using appsrc in streaming mode. + * + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +GST_DEBUG_CATEGORY (appsrc_playbin_debug); +#define GST_CAT_DEFAULT appsrc_playbin_debug + +/* + * an example application of using appsrc in streaming pull mode. When the + * appsrc request data with the need-data signal, we retrieve a buffer of an + * arbitrary size and push it to appsrc. + * + * This example keeps the internal buffer queue of appsrc to a minimal size, + * only feeding data to appsrc when needed. + * + * This is a good example how one would deal with a live resource, such as a udp + * socket where one would feed the most recently acquired buffer to appsrc. + * + * Usually one would timestamp the buffers with the running_time of the + * pipeline or configure the appsrc to do timestamping by setting the + * do-timestamp property to TRUE. + * + * Appsrc in streaming mode (the default) does not support seeking so we don't + * have to handle any seek callbacks. + * + * Some formats are able to estimate the duration of the media file based on the + * file length (mp3, mpeg,..), others report an unknown length (ogg,..). + */ +typedef struct _App App; + +struct _App +{ + GstElement *playbin; + GstElement *appsrc; + + GMainLoop *loop; + + GMappedFile *file; + guint8 *data; + gsize length; + guint64 offset; +}; + +App s_app; + +#define CHUNK_SIZE 4096 + +/* This method is called by the need-data signal callback, we feed data into the + * appsrc. + */ +static void +feed_data (GstElement * appsrc, guint size, App * app) +{ + GstBuffer *buffer; + guint len; + GstFlowReturn ret; + + buffer = gst_buffer_new (); + + if (app->offset >= app->length) { + /* we are EOS, send end-of-stream */ + g_signal_emit_by_name (app->appsrc, "end-of-stream", &ret); + return; + } + + /* read the next chunk */ + len = CHUNK_SIZE; + if (app->offset + len > app->length) + len = app->length - app->offset; + + GST_BUFFER_DATA (buffer) = app->data + app->offset; + GST_BUFFER_SIZE (buffer) = len; + + GST_DEBUG ("feed buffer %p, offset %" G_GUINT64_FORMAT "-%u", buffer, + app->offset, len); + g_signal_emit_by_name (app->appsrc, "push-buffer", buffer, &ret); + gst_buffer_unref (buffer); + + app->offset += len; + + return; +} + +/* this callback is called when playbin2 has constructed a source object to read + * from. Since we provided the appsrc:// uri to playbin2, this will be the + * appsrc that we must handle. We set up a signals to push data into appsrc. */ +static void +found_source (GObject * object, GObject * orig, GParamSpec * pspec, App * app) +{ + /* get a handle to the appsrc */ + g_object_get (orig, pspec->name, &app->appsrc, NULL); + + GST_DEBUG ("got appsrc %p", app->appsrc); + + /* we can set the length in appsrc. This allows some elements to estimate the + * total duration of the stream. It's a good idea to set the property when you + * can but it's not required. */ + g_object_set (app->appsrc, "size", (gint64) app->length, NULL); + + /* configure the appsrc, we will push a buffer to appsrc when it needs more + * data */ + g_signal_connect (app->appsrc, "need-data", G_CALLBACK (feed_data), app); +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, App * app) +{ + GST_DEBUG ("got message %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + g_error ("received error"); + g_main_loop_quit (app->loop); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (app->loop); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + GError *error = NULL; + GstBus *bus; + + gst_init (&argc, &argv); + + GST_DEBUG_CATEGORY_INIT (appsrc_playbin_debug, "appsrc-playbin", 0, + "appsrc playbin example"); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* try to open the file as an mmapped file */ + app->file = g_mapped_file_new (argv[1], FALSE, &error); + if (error) { + g_print ("failed to open file: %s\n", error->message); + g_error_free (error); + return -2; + } + /* get some vitals, this will be used to read data from the mmapped file and + * feed it to appsrc. */ + app->length = g_mapped_file_get_length (app->file); + app->data = (guint8 *) g_mapped_file_get_contents (app->file); + app->offset = 0; + + /* create a mainloop to get messages */ + app->loop = g_main_loop_new (NULL, TRUE); + + app->playbin = gst_element_factory_make ("playbin2", NULL); + g_assert (app->playbin); + + bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin)); + + /* add watch for messages */ + gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); + + /* set to read from appsrc */ + g_object_set (app->playbin, "uri", "appsrc://", NULL); + + /* get notification when the source is created so that we get a handle to it + * and can configure it */ + g_signal_connect (app->playbin, "deep-notify::source", + (GCallback) found_source, app); + + /* go to playing and wait in a mainloop. */ + gst_element_set_state (app->playbin, GST_STATE_PLAYING); + + /* this mainloop is stopped when we receive an error or EOS */ + g_main_loop_run (app->loop); + + GST_DEBUG ("stopping"); + + gst_element_set_state (app->playbin, GST_STATE_NULL); + + /* free the file */ + g_mapped_file_unref (app->file); + + gst_object_unref (bus); + g_main_loop_unref (app->loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc_ex.c b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc_ex.c new file mode 100644 index 0000000..c7aa4b6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/app/appsrc_ex.c @@ -0,0 +1,95 @@ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include +#include + + +typedef struct _App App; +struct _App +{ + GstElement *pipe; + GstElement *src; + GstElement *id; + GstElement *sink; +}; + +App s_app; + +static void dont_eat_my_chicken_wings (void *priv); + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + int i; + + gst_init (&argc, &argv); + + app->pipe = gst_pipeline_new (NULL); + g_assert (app->pipe); + + app->src = gst_element_factory_make ("appsrc", NULL); + g_assert (app->src); + gst_bin_add (GST_BIN (app->pipe), app->src); + + app->id = gst_element_factory_make ("identity", NULL); + g_assert (app->id); + gst_bin_add (GST_BIN (app->pipe), app->id); + + app->sink = gst_element_factory_make ("appsink", NULL); + g_assert (app->sink); + gst_bin_add (GST_BIN (app->pipe), app->sink); + + gst_element_link (app->src, app->id); + gst_element_link (app->id, app->sink); + + gst_element_set_state (app->pipe, GST_STATE_PLAYING); + + for (i = 0; i < 10; i++) { + GstBuffer *buf; + void *data; + + data = malloc (100); + memset (data, i, 100); + + buf = gst_app_buffer_new (data, 100, dont_eat_my_chicken_wings, data); + printf ("%d: creating buffer for pointer %p, %p\n", i, data, buf); + gst_app_src_push_buffer (GST_APP_SRC (app->src), buf); + } + + /* push EOS */ + gst_app_src_end_of_stream (GST_APP_SRC (app->src)); + + /* _is_eos() does not block and returns TRUE if there is not currently an EOS + * to be retrieved */ + while (!gst_app_sink_is_eos (GST_APP_SINK (app->sink))) { + GstBuffer *buf; + + /* pull the next item, this can return NULL when there is no more data and + * EOS has been received */ + buf = gst_app_sink_pull_buffer (GST_APP_SINK (app->sink)); + printf ("retrieved buffer %p\n", buf); + if (buf) + gst_buffer_unref (buf); + } + gst_element_set_state (app->pipe, GST_STATE_NULL); + + return 0; +} + +static void +dont_eat_my_chicken_wings (void *priv) +{ + printf ("freeing buffer for pointer %p\n", priv); + free (priv); +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/.gitignore new file mode 100644 index 0000000..99b7654 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/.gitignore @@ -0,0 +1,5 @@ +addstream +codec-select +sprinkle +sprinkle2 +sprinkle3 diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/Makefile.am new file mode 100644 index 0000000..6cdb8ff --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/Makefile.am @@ -0,0 +1,21 @@ +noinst_PROGRAMS = addstream codec-select sprinkle sprinkle2 sprinkle3 + +addstream_SOURCES = addstream.c +addstream_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE +addstream_LDADD = $(GST_LIBS) + +codec_select_SOURCES = codec-select.c +codec_select_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE +codec_select_LDADD = $(GST_LIBS) + +sprinkle_SOURCES = sprinkle.c +sprinkle_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE +sprinkle_LDADD = $(GST_LIBS) + +sprinkle2_SOURCES = sprinkle2.c +sprinkle2_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE +sprinkle2_LDADD = $(GST_LIBS) + +sprinkle3_SOURCES = sprinkle3.c +sprinkle3_CFLAGS = $(GST_CFLAGS) -D_GNU_SOURCE +sprinkle3_LDADD = $(GST_LIBS) diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/addstream.c b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/addstream.c new file mode 100644 index 0000000..66ad0be --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/addstream.c @@ -0,0 +1,253 @@ +/* GStreamer + * + * addstream.c: sample application to dynamically add streams to a running + * pipeline + * + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +static GstElement *pipeline; +static GstClock *theclock; +static GMainLoop *loop; +static GstElement *bin1, *bin2, *bin3, *bin4, *bin5; + +/* start a bin with the given description */ +static GstElement * +create_stream (const gchar * descr) +{ + GstElement *bin; + GError *error = NULL; + + bin = gst_parse_launch (descr, &error); + if (error) { + g_print ("pipeline could not be constructed: %s\n", error->message); + g_error_free (error); + return NULL; + } + + /* add the bin to the pipeline now, this will set the current base_time of the + * pipeline on the new bin. */ + gst_bin_add (GST_BIN_CAST (pipeline), bin); + + return bin; +} + +static gboolean +pause_play_stream (GstElement * bin, gint seconds) +{ + gboolean punch_in; + GstStateChangeReturn ret; + GstClockTime now, base_time, running_time; + + /* get current running time, we need this value to continue playback of + * non-live pipelines. */ + now = gst_clock_get_time (theclock); + base_time = gst_element_get_base_time (bin); + + running_time = now - base_time; + + /* set the new bin to PAUSED, the parent bin will notice (because of the ASYNC + * message and will perform latency calculations again when going to PLAYING + * later. */ + ret = gst_element_set_state (bin, GST_STATE_PAUSED); + + switch (ret) { + case GST_STATE_CHANGE_NO_PREROLL: + /* live source, timestamps are running_time of the pipeline clock. */ + punch_in = FALSE; + break; + case GST_STATE_CHANGE_SUCCESS: + /* success, no async state changes, same as async, timestamps start + * from 0 */ + case GST_STATE_CHANGE_ASYNC: + /* no live source, bin will preroll. We have to punch it in because in + * this situation timestamps start from 0. */ + punch_in = TRUE; + break; + default: + case GST_STATE_CHANGE_FAILURE: + return FALSE; + } + + if (seconds) + g_usleep (seconds * G_USEC_PER_SEC); + + if (punch_in) { + /* new bin has to be aligned with previous running_time. We do this by taking + * the current absolute clock time and calculating the base time that would + * give the previous running_time. We set this base_time on the bin before + * setting it to PLAYING. */ + now = gst_clock_get_time (theclock); + base_time = now - running_time; + + gst_element_set_base_time (bin, base_time); + } + + /* now set the pipeline to PLAYING */ + gst_element_set_state (bin, GST_STATE_PLAYING); + + return TRUE; +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static void +eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * pipeline) +{ + message_received (bus, message, pipeline); + g_main_loop_quit (loop); +} + +static gboolean +perform_step (gpointer pstep) +{ + gint step = GPOINTER_TO_INT (pstep); + + switch (step) { + case 0: + /* live stream locks on to running_time, pipeline configures latency. */ + g_print ("creating bin1\n"); + bin1 = + create_stream + ("( v4l2src ! ffmpegcolorspace ! timeoverlay ! queue ! xvimagesink name=v4llive )"); + pause_play_stream (bin1, 0); + g_timeout_add (1000, (GSourceFunc) perform_step, GINT_TO_POINTER (1)); + break; + case 1: + /* live stream locks on to running_time, pipeline reconfigures latency + * together with the previously added bin so that they run synchronized. */ + g_print ("creating bin2\n"); + bin2 = create_stream ("( alsasrc ! queue ! alsasink name=alsalive )"); + pause_play_stream (bin2, 0); + g_timeout_add (1000, (GSourceFunc) perform_step, GINT_TO_POINTER (2)); + break; + case 2: + /* non-live stream, need base_time to align with current running live sources. */ + g_print ("creating bin3\n"); + bin3 = create_stream ("( audiotestsrc ! alsasink name=atnonlive )"); + pause_play_stream (bin3, 0); + g_timeout_add (1000, (GSourceFunc) perform_step, GINT_TO_POINTER (3)); + break; + case 3: + g_print ("creating bin4\n"); + bin4 = + create_stream + ("( videotestsrc ! timeoverlay ! ffmpegcolorspace ! ximagesink name=vtnonlive )"); + pause_play_stream (bin4, 0); + g_timeout_add (1000, (GSourceFunc) perform_step, GINT_TO_POINTER (4)); + break; + case 4: + /* live stream locks on to running_time */ + g_print ("creating bin5\n"); + bin5 = + create_stream + ("( videotestsrc is-live=1 ! timeoverlay ! ffmpegcolorspace ! ximagesink name=vtlive )"); + pause_play_stream (bin5, 0); + g_timeout_add (1000, (GSourceFunc) perform_step, GINT_TO_POINTER (5)); + break; + case 5: + /* pause the fist live stream for 2 seconds */ + g_print ("PAUSE bin1 for 2 seconds\n"); + pause_play_stream (bin1, 2); + /* pause the non-live stream for 2 seconds */ + g_print ("PAUSE bin4 for 2 seconds\n"); + pause_play_stream (bin4, 2); + /* pause the pseudo live stream for 2 seconds */ + g_print ("PAUSE bin5 for 2 seconds\n"); + pause_play_stream (bin5, 2); + g_print ("Waiting 5 seconds\n"); + g_timeout_add (5000, (GSourceFunc) perform_step, GINT_TO_POINTER (6)); + break; + case 6: + g_print ("quiting\n"); + g_main_loop_quit (loop); + break; + default: + break; + } + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); + + /* setup message handling */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_received, + pipeline); + + /* we set the pipeline to PLAYING, this will distribute a default clock and + * start running. no preroll is needed */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* get the clock now. Since we never set the pipeline to PAUSED again, the + * clock will not change, even when we add new clock providers later. */ + theclock = gst_element_get_clock (pipeline); + + /* start our actions while we are in the mainloop so that we can catch errors + * and other messages. */ + g_idle_add ((GSourceFunc) perform_step, GINT_TO_POINTER (0)); + /* go to main loop */ + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (bus); + gst_object_unref (pipeline); + gst_object_unref (theclock); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/codec-select.c b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/codec-select.c new file mode 100644 index 0000000..2d8f9fa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/codec-select.c @@ -0,0 +1,298 @@ +/* GStreamer + * + * codec-select.c: sample application to dynamically select a codec + * + * Copyright (C) <2008> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * This example sets up a pipeline to 'encode' an audiotestsrc into 3 different + * formats. The format can be selected dynamically at runtime. + * + * Each of the encoders require the audio in a specific different format. + * + * This example uses identity as the encoder and enforces the caps on identity + * with a capsfilter. + * + * This is a good example of input and output selector and how these elements + * preserve segment and timing information while switching between streams. + */ + +#include +#include + +/* Create an encoder element. + * We make a bin containing: + * + * audioresample ! ! identity + * + * The sinkpad of audioresample and source pad of identity are ghosted on the + * bin. + */ +static GstElement * +make_encoder (const GstCaps * caps) +{ + GstElement *result; + GstElement *audioresample; + GstElement *capsfilter; + GstElement *identity; + GstPad *pad; + + /* create result bin */ + result = gst_bin_new (NULL); + g_assert (result); + + /* create elements */ + audioresample = gst_element_factory_make ("audioresample", NULL); + g_assert (audioresample); + + capsfilter = gst_element_factory_make ("capsfilter", NULL); + g_assert (capsfilter); + g_object_set (capsfilter, "caps", caps, NULL); + + identity = gst_element_factory_make ("identity", NULL); + g_assert (identity); + g_object_set (identity, "silent", TRUE, NULL); + + /* add elements to result bin */ + gst_bin_add (GST_BIN (result), audioresample); + gst_bin_add (GST_BIN (result), capsfilter); + gst_bin_add (GST_BIN (result), identity); + + /* link elements */ + gst_element_link_pads (audioresample, "src", capsfilter, "sink"); + gst_element_link_pads (capsfilter, "src", identity, "sink"); + + /* ghost src and sink pads */ + pad = gst_element_get_static_pad (audioresample, "sink"); + gst_element_add_pad (result, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (identity, "src"); + gst_element_add_pad (result, gst_ghost_pad_new ("src", pad)); + gst_object_unref (pad); + + return result; +} + +/* + * We generate: + * + * audiotestsrc ! ! output-selector ! [enc1 .. enc3] ! input-selector + * select-all = true ! fakesink + * + * makes sure we only produce one format from the audiotestsrc. + * + * Each encX element consists of: + * + * audioresample ! ! identity ! + * + * This way we can simply switch encoders without having to renegotiate. + */ +static GstElement * +make_pipeline (void) +{ + GstElement *result; + GstElement *audiotestsrc; + GstElement *audiocaps; + GstElement *outputselect; + GstElement *inputselect; + GstElement *sink; + GstCaps *caps; + GstCaps *capslist[3]; + gint i; + + /* create result pipeline */ + result = gst_pipeline_new (NULL); + g_assert (result); + + /* create various elements */ + audiotestsrc = gst_element_factory_make ("audiotestsrc", NULL); + g_object_set (audiotestsrc, "num-buffers", 1000, NULL); + g_assert (audiotestsrc); + + audiocaps = gst_element_factory_make ("capsfilter", NULL); + g_assert (audiocaps); + + caps = + gst_caps_from_string + ("audio/x-raw-int,signed=true,width=16,depth=16,rate=48000,channels=1"); + g_object_set (audiocaps, "caps", caps, NULL); + gst_caps_unref (caps); + + outputselect = gst_element_factory_make ("output-selector", "select"); + g_assert (outputselect); + + inputselect = gst_element_factory_make ("input-selector", NULL); + g_assert (inputselect); + g_object_set (inputselect, "select-all", TRUE, NULL); + + sink = gst_element_factory_make ("fakesink", NULL); + g_object_set (sink, "sync", TRUE, NULL); + g_object_set (sink, "silent", TRUE, NULL); + g_assert (sink); + + /* add elements */ + gst_bin_add (GST_BIN (result), audiotestsrc); + gst_bin_add (GST_BIN (result), audiocaps); + gst_bin_add (GST_BIN (result), outputselect); + gst_bin_add (GST_BIN (result), inputselect); + gst_bin_add (GST_BIN (result), sink); + + /* link elements */ + gst_element_link_pads (audiotestsrc, "src", audiocaps, "sink"); + gst_element_link_pads (audiocaps, "src", outputselect, "sink"); + gst_element_link_pads (inputselect, "src", sink, "sink"); + + /* make caps */ + capslist[0] = + gst_caps_from_string + ("audio/x-raw-int,signed=true,width=16,depth=16,rate=48000,channels=1"); + capslist[1] = + gst_caps_from_string + ("audio/x-raw-int,signed=true,width=16,depth=16,rate=16000,channels=1"); + capslist[2] = + gst_caps_from_string + ("audio/x-raw-int,signed=true,width=16,depth=16,rate=8000,channels=1"); + + /* create encoder elements */ + for (i = 0; i < 3; i++) { + GstElement *encoder; + GstPad *srcpad, *sinkpad; + + encoder = make_encoder (capslist[i]); + g_assert (encoder); + + gst_bin_add (GST_BIN (result), encoder); + + srcpad = gst_element_get_request_pad (outputselect, "src%d"); + sinkpad = gst_element_get_static_pad (encoder, "sink"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + srcpad = gst_element_get_static_pad (encoder, "src"); + sinkpad = gst_element_get_request_pad (inputselect, "sink%d"); + gst_pad_link (srcpad, sinkpad); + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + } + + return result; +} + +static gboolean +do_switch (GstElement * pipeline) +{ + gint rand; + GstElement *select; + gchar *name; + GstPad *pad; + + rand = g_random_int_range (0, 3); + + g_print ("switching to %d\n", rand); + + /* find the selector */ + select = gst_bin_get_by_name (GST_BIN (pipeline), "select"); + + /* get the named pad */ + name = g_strdup_printf ("src%d", rand); + pad = gst_element_get_static_pad (select, name); + g_free (name); + + /* set the active pad */ + g_object_set (select, "active-pad", pad, NULL); + + return TRUE; +} + +static gboolean +my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + GstElement *sender = (GstElement *) GST_MESSAGE_SRC (message); + const gchar *name = gst_element_get_name (sender); + GMainLoop *loop = (GMainLoop *) data; + + g_print ("Got %s message from %s\n", GST_MESSAGE_TYPE_NAME (message), name); + + switch (GST_MESSAGE_TYPE (message)) { + + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s (%s)\n", err->message, debug); + g_error_free (err); + g_free (debug); + + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + g_main_loop_quit (loop); + break; + default: + /* unhandled message */ + break; + } + + return TRUE; +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline; + GstBus *bus; + GMainLoop *loop; + + /* init GStreamer */ + gst_init (&argc, &argv); + loop = g_main_loop_new (NULL, FALSE); + + /* set up */ + pipeline = make_pipeline (); + + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, my_bus_callback, loop); + gst_object_unref (bus); + + g_print ("Starting pipeline\n"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* add a timeout to cycle between the formats */ + g_timeout_add (1000, (GSourceFunc) do_switch, pipeline); + + /* now run */ + g_main_loop_run (loop); + + g_print ("Nulling pipeline\n"); + + /* also clean up */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle.c b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle.c new file mode 100644 index 0000000..1b75840 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle.c @@ -0,0 +1,264 @@ +/* GStreamer + * + * sprinkle.c: sample application to dynamically mix tones with adder + * + * Copyright (C) <2009> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Produces a sweeping sprinkle of tones by dynamically adding and removing + * elements to adder. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstElement *pipeline, *adder; +static GMainLoop *loop; + +typedef struct +{ + GstElement *element; + GstPad *srcpad; + GstPad *sinkpad; + gdouble freq; +} SourceInfo; + +/* dynamically add the source to the pipeline and link it to a new pad on + * adder */ +static SourceInfo * +add_source (gdouble freq) +{ + SourceInfo *info; + + info = g_new0 (SourceInfo, 1); + info->freq = freq; + + /* make source with unique name */ + info->element = gst_element_factory_make ("audiotestsrc", NULL); + + g_object_set (info->element, "freq", freq, NULL); + + /* add to the bin */ + gst_bin_add (GST_BIN (pipeline), info->element); + + /* get pad from the element */ + info->srcpad = gst_element_get_static_pad (info->element, "src"); + + /* get new pad from adder, adder will now wait for data on this pad */ + info->sinkpad = gst_element_get_request_pad (adder, "sink%d"); + + /* link pad to adder */ + gst_pad_link (info->srcpad, info->sinkpad); + + /* and play the element */ + gst_element_set_state (info->element, GST_STATE_PLAYING); + + g_print ("added freq %f\n", info->freq); + + return info; +} + +/* remove the source from the pipeline after removing it from adder */ +static void +remove_source (SourceInfo * info) +{ + g_print ("remove freq %f\n", info->freq); + + /* lock the state so that we can put it to NULL without the parent messing + * with our state */ + gst_element_set_locked_state (info->element, TRUE); + + /* first stop the source. Remember that this might block when in the PAUSED + * state. Alternatively one could send EOS to the source, install an event + * probe and schedule a state change/unlink/release from the mainthread. + * Note that changing the state of a source makes it emit an EOS, which can + * make adder go EOS. */ + gst_element_set_state (info->element, GST_STATE_NULL); + + /* unlink from adder */ + gst_pad_unlink (info->srcpad, info->sinkpad); + gst_object_unref (info->srcpad); + + /* remove from the bin */ + gst_bin_remove (GST_BIN (pipeline), info->element); + + /* give back the pad */ + gst_element_release_request_pad (adder, info->sinkpad); + gst_object_unref (info->sinkpad); + + g_free (info); +} + +/* we'll keep the state of the sources in this structure. We keep 3 sources + * alive */ +typedef struct +{ + guint count; + SourceInfo *infos[3]; +} SprinkleState; + +static SprinkleState * +create_state (void) +{ + SprinkleState *state; + + state = g_new0 (SprinkleState, 1); + + return state; +} + +static void +free_state (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + for (i = 0; i < 3; i++) { + info = state->infos[i]; + if (info) + remove_source (info); + } + + g_free (state); +} + +static gboolean +do_sprinkle (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + /* first remove the oldest info */ + info = state->infos[2]; + + if (info) + remove_source (info); + + /* move sources */ + for (i = 2; i > 0; i--) { + state->infos[i] = state->infos[i - 1]; + } + + /* add new source, stop adding sources after 10 rounds. */ + if (state->count < 10) { + state->infos[0] = add_source ((state->count * 100) + 200); + state->count++; + } else { + state->infos[0] = NULL; + } + return TRUE; +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static void +eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * pipeline) +{ + message_received (bus, message, pipeline); + g_main_loop_quit (loop); +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + GstElement *filter, *convert, *sink; + GstCaps *caps; + gboolean res; + SprinkleState *state; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); + + /* add the fixed part to the pipeline. Remember that we need a capsfilter + * after adder so that multiple sources are not racing to negotiate + * a format */ + adder = gst_element_factory_make ("adder", "adder"); + filter = gst_element_factory_make ("capsfilter", "filter"); + convert = gst_element_factory_make ("audioconvert", "convert"); + sink = gst_element_factory_make ("autoaudiosink", "sink"); + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, 1, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 44100, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + gst_bin_add_many (GST_BIN (pipeline), adder, filter, convert, sink, NULL); + + res = gst_element_link_many (adder, filter, convert, sink, NULL); + g_assert (res); + + /* setup message handling */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_received, + pipeline); + + /* we set the pipeline to PLAYING, the pipeline will not yet preroll because + * there is no source providing data for it yet */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* and add the function that modifies the pipeline every 100ms */ + state = create_state (); + g_timeout_add (100, (GSourceFunc) do_sprinkle, state); + + /* go to main loop */ + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + free_state (state); + gst_object_unref (bus); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle2.c b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle2.c new file mode 100644 index 0000000..abab47c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle2.c @@ -0,0 +1,288 @@ +/* GStreamer + * + * sprinkle.c: sample application to dynamically mix tones with adder + * + * Copyright (C) <2009> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Produces a sweeping sprinkle of tones by dynamically adding and removing + * elements to adder. + * + * gcc `pkg-config --cflags --libs gstreamer-0.10` sprinkle2.c -osprinkle2 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstElement *pipeline, *adder; +static GMainLoop *loop; + +typedef struct +{ + GstElement *src, *fx; + GstPad *src_srcpad; + GstPad *fx_sinkpad, *fx_srcpad; + GstPad *adder_sinkpad; + gdouble freq; + gfloat pos; +} SourceInfo; + +/* dynamically add the source to the pipeline and link it to a new pad on + * adder */ +static SourceInfo * +add_source (gdouble freq, gfloat pos) +{ + SourceInfo *info; + + info = g_new0 (SourceInfo, 1); + info->freq = freq; + info->pos = pos; + + /* make source with unique name */ + info->src = gst_element_factory_make ("audiotestsrc", NULL); + info->fx = gst_element_factory_make ("audiopanorama", NULL); + + g_object_set (info->src, "freq", freq, "volume", (gdouble) 0.35, NULL); + g_object_set (info->fx, "panorama", pos, NULL); + + /* add to the bin */ + gst_bin_add (GST_BIN (pipeline), info->src); + gst_bin_add (GST_BIN (pipeline), info->fx); + + /* get pads from the elements */ + info->src_srcpad = gst_element_get_static_pad (info->src, "src"); + info->fx_srcpad = gst_element_get_static_pad (info->fx, "src"); + info->fx_sinkpad = gst_element_get_static_pad (info->fx, "sink"); + + /* get new pad from adder, adder will now wait for data on this pad */ + info->adder_sinkpad = gst_element_get_request_pad (adder, "sink%d"); + + /* link src to fx and fx to adder */ + gst_pad_link (info->fx_srcpad, info->adder_sinkpad); + gst_pad_link (info->src_srcpad, info->fx_sinkpad); + + /* and play the elements, change the state from sink to source */ + gst_element_set_state (info->fx, GST_STATE_PLAYING); + gst_element_set_state (info->src, GST_STATE_PLAYING); + + g_print ("added freq %5.0f, pos %3.1f\n", info->freq, info->pos); + + return info; +} + +/* remove the source from the pipeline after removing it from adder */ +static void +remove_source (SourceInfo * info) +{ + g_print ("remove freq %5.0f, pos %3.1f\n", info->freq, info->pos); + + /* lock the state so that we can put it to NULL without the parent messing + * with our state */ + gst_element_set_locked_state (info->src, TRUE); + gst_element_set_locked_state (info->fx, TRUE); + + /* first stop the source. Remember that this might block when in the PAUSED + * state. Alternatively one could send EOS to the source, install an event + * probe and schedule a state change/unlink/release from the mainthread. */ + gst_element_set_state (info->fx, GST_STATE_NULL); + /* NOTE that the source emits EOS when shutting down but the EOS will not + * reach the adder sinkpad because the effect is in the NULL state. We will + * send an EOS to adder later. */ + gst_element_set_state (info->src, GST_STATE_NULL); + + /* unlink from adder */ + gst_pad_unlink (info->src_srcpad, info->fx_sinkpad); + gst_pad_unlink (info->fx_srcpad, info->adder_sinkpad); + gst_object_unref (info->src_srcpad); + gst_object_unref (info->fx_srcpad); + gst_object_unref (info->fx_sinkpad); + + /* remove from the bin */ + gst_bin_remove (GST_BIN (pipeline), info->src); + gst_bin_remove (GST_BIN (pipeline), info->fx); + + /* send EOS to the sinkpad to make adder EOS when needed */ + gst_pad_send_event (info->adder_sinkpad, gst_event_new_eos ()); + + /* give back the pad */ + gst_element_release_request_pad (adder, info->adder_sinkpad); + gst_object_unref (info->adder_sinkpad); + + g_free (info); +} + +/* we'll keep the state of the sources in this structure. We keep 3 sources + * alive */ +typedef struct +{ + guint count; + SourceInfo *infos[3]; +} SprinkleState; + +static SprinkleState * +create_state (void) +{ + SprinkleState *state; + + state = g_new0 (SprinkleState, 1); + + return state; +} + +static void +free_state (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + for (i = 0; i < 3; i++) { + info = state->infos[i]; + if (info) + remove_source (info); + } + + g_free (state); +} + +static gboolean +do_sprinkle (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + /* first remove the oldest info */ + info = state->infos[2]; + + if (info) + remove_source (info); + + /* move sources */ + for (i = 2; i > 0; i--) { + state->infos[i] = state->infos[i - 1]; + } + + /* add new source, stop adding sources after 10 rounds. */ + if (state->count < 20) { + state->infos[0] = add_source ( + (gdouble) ((state->count * 100) + 200), + ((gfloat) (state->count % 5) / 2.0 - 1.0)); + state->count++; + } else { + state->infos[0] = NULL; + } + return TRUE; +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static void +eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * pipeline) +{ + message_received (bus, message, pipeline); + g_main_loop_quit (loop); +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + GstElement *filter, *convert, *sink; + GstCaps *caps; + gboolean res; + SprinkleState *state; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); + + /* add the fixed part to the pipeline. Remember that we need a capsfilter + * after adder so that multiple sources are not racing to negotiate + * a format */ + adder = gst_element_factory_make ("adder", "adder"); + filter = gst_element_factory_make ("capsfilter", "filter"); + convert = gst_element_factory_make ("audioconvert", "convert"); + sink = gst_element_factory_make ("autoaudiosink", "sink"); + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, 2, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 44100, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + gst_bin_add_many (GST_BIN (pipeline), adder, filter, convert, sink, NULL); + + res = gst_element_link_many (adder, filter, convert, sink, NULL); + g_assert (res); + + /* setup message handling */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_received, + pipeline); + + /* we set the pipeline to PLAYING, the pipeline will not yet preroll because + * there is no source providing data for it yet */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* and add the function that modifies the pipeline every 100ms */ + state = create_state (); + g_timeout_add (100, (GSourceFunc) do_sprinkle, state); + + /* go to main loop */ + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + free_state (state); + gst_object_unref (bus); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle3.c b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle3.c new file mode 100644 index 0000000..5983c33 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/dynamic/sprinkle3.c @@ -0,0 +1,301 @@ +/* GStreamer + * + * sprinkle.c: sample application to dynamically mix tones with adder + * + * Copyright (C) <2009> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * Produces a sweeping sprinkle of tones by dynamically adding and removing + * elements to adder. + * + * gcc `pkg-config --cflags --libs gstreamer-0.10` sprinkle3.c -osprinkle3 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +static GstElement *pipeline, *adder; +static GMainLoop *loop; + +typedef struct +{ + GstElement *bin, *src, *fx; + GstPad *src_srcpad; + GstPad *fx_sinkpad, *fx_srcpad; + GstPad *adder_sinkpad; + GstPad *bin_srcpad; + gdouble freq; + gfloat pos; +} SourceInfo; + +/* dynamically add the source to the pipeline and link it to a new pad on + * adder */ +static SourceInfo * +add_source (gdouble freq, gfloat pos) +{ + SourceInfo *info; + + info = g_new0 (SourceInfo, 1); + info->freq = freq; + info->pos = pos; + + /* make source with unique name */ + info->bin = gst_element_factory_make ("bin", NULL); + info->src = gst_element_factory_make ("audiotestsrc", NULL); + info->fx = gst_element_factory_make ("audiopanorama", NULL); + + g_object_set (info->src, "freq", freq, "volume", (gdouble) 0.35, NULL); + g_object_set (info->fx, "panorama", pos, NULL); + + /* add to the bin */ + gst_bin_add (GST_BIN (info->bin), info->src); + gst_bin_add (GST_BIN (info->bin), info->fx); + + /* get pads from the elements */ + info->src_srcpad = gst_element_get_static_pad (info->src, "src"); + info->fx_srcpad = gst_element_get_static_pad (info->fx, "src"); + info->fx_sinkpad = gst_element_get_static_pad (info->fx, "sink"); + + /* create and add a pad for the bin */ + info->bin_srcpad = gst_ghost_pad_new ("src", info->fx_srcpad); + gst_element_add_pad (info->bin, info->bin_srcpad); + + /* get new pad from adder, adder will now wait for data on this pad */ + info->adder_sinkpad = gst_element_get_request_pad (adder, "sink%d"); + + /* link inside the bin */ + gst_pad_link (info->src_srcpad, info->fx_sinkpad); + + /* add bin to pipeline */ + gst_bin_add (GST_BIN (pipeline), info->bin); + + /* link bin to adder */ + gst_pad_link (info->bin_srcpad, info->adder_sinkpad); + + /* and play the elements */ + gst_element_set_state (info->bin, GST_STATE_PLAYING); + + g_print ("added freq %5.0f, pos %3.1f\n", info->freq, info->pos); + + return info; +} + +/* remove the source from the pipeline after removing it from adder */ +static void +remove_source (SourceInfo * info) +{ + g_print ("remove freq %5.0f, pos %3.1f\n", info->freq, info->pos); + + /* lock the state so that we can put it to NULL without the parent messing + * with our state */ + gst_element_set_locked_state (info->bin, TRUE); + + /* first stop the source. Remember that this might block when in the PAUSED + * state. Alternatively one could send EOS to the source, install an event + * probe and schedule a state change/unlink/release from the mainthread. */ + /* NOTE that the source inside the bin will emit EOS but it will not reach + * adder because the element after the source is shut down first. We will send + * EOS later */ + gst_element_set_state (info->bin, GST_STATE_NULL); + + /* unlink bin from adder */ + gst_pad_unlink (info->bin_srcpad, info->adder_sinkpad); + + /* release pads */ + gst_object_unref (info->src_srcpad); + gst_object_unref (info->fx_srcpad); + gst_object_unref (info->fx_sinkpad); + + /* remove from the bin */ + gst_bin_remove (GST_BIN (pipeline), info->bin); + + /* send EOS to the sinkpad to make adder EOS when needed */ + gst_pad_send_event (info->adder_sinkpad, gst_event_new_eos ()); + + /* give back the pad */ + gst_element_release_request_pad (adder, info->adder_sinkpad); + gst_object_unref (info->adder_sinkpad); + + g_free (info); +} + +/* we'll keep the state of the sources in this structure. We keep 3 sources + * alive */ +typedef struct +{ + guint count; + SourceInfo *infos[3]; +} SprinkleState; + +static SprinkleState * +create_state (void) +{ + SprinkleState *state; + + state = g_new0 (SprinkleState, 1); + + return state; +} + +static void +free_state (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + for (i = 0; i < 3; i++) { + info = state->infos[i]; + if (info) + remove_source (info); + } + + g_free (state); +} + +static gboolean +do_sprinkle (SprinkleState * state) +{ + SourceInfo *info; + gint i; + + /* first remove the oldest info */ + info = state->infos[2]; + + if (info) + remove_source (info); + + /* move sources */ + for (i = 2; i > 0; i--) { + state->infos[i] = state->infos[i - 1]; + } + + /* add new source, stop adding sources after 10 rounds. */ + if (state->count < 20) { + state->infos[0] = add_source ( + (gdouble) ((state->count * 100) + 200), + ((gfloat) (state->count % 5) / 2.0 - 1.0)); + state->count++; + } else { + state->infos[0] = NULL; + } + + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (pipeline), + /*GST_DEBUG_GRAPH_SHOW_ALL, */ + GST_DEBUG_GRAPH_SHOW_CAPS_DETAILS | GST_DEBUG_GRAPH_SHOW_STATES, + "sprinkle3"); + return TRUE; +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static void +eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * pipeline) +{ + message_received (bus, message, pipeline); + g_main_loop_quit (loop); +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + GstElement *filter, *convert, *sink; + GstCaps *caps; + gboolean res; + SprinkleState *state; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); + + /* add the fixed part to the pipeline. Remember that we need a capsfilter + * after adder so that multiple sources are not racing to negotiate + * a format */ + adder = gst_element_factory_make ("adder", "adder"); + filter = gst_element_factory_make ("capsfilter", "filter"); + convert = gst_element_factory_make ("audioconvert", "convert"); + sink = gst_element_factory_make ("autoaudiosink", "sink"); + + caps = gst_caps_new_simple ("audio/x-raw-int", + "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, + "channels", G_TYPE_INT, 2, + "width", G_TYPE_INT, 16, + "depth", G_TYPE_INT, 16, + "rate", G_TYPE_INT, 44100, "signed", G_TYPE_BOOLEAN, TRUE, NULL); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + gst_bin_add_many (GST_BIN (pipeline), adder, filter, convert, sink, NULL); + + res = gst_element_link_many (adder, filter, convert, sink, NULL); + g_assert (res); + + /* setup message handling */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_received, + pipeline); + + /* we set the pipeline to PLAYING, the pipeline will not yet preroll because + * there is no source providing data for it yet */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* and add the function that modifies the pipeline every 100ms */ + state = create_state (); + g_timeout_add (100, (GSourceFunc) do_sprinkle, state); + + /* go to main loop */ + g_main_loop_run (loop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + free_state (state); + gst_object_unref (bus); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/encoding/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/encoding/.gitignore new file mode 100644 index 0000000..c684c2e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/encoding/.gitignore @@ -0,0 +1 @@ +encoding diff --git a/gst-plugins-base-subtitles0.10/tests/examples/encoding/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/encoding/Makefile.am new file mode 100644 index 0000000..2bcc902 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/encoding/Makefile.am @@ -0,0 +1,12 @@ +examples = encoding + +encoding_SOURCES = gstcapslist.c encoding.c +EXTRA_DIST = gstcapslist.h + +noinst_PROGRAMS = $(examples) + +LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la \ + $(GST_LIBS) +AM_CFLAGS = -I$(top_builddir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/examples/encoding/encoding.c b/gst-plugins-base-subtitles0.10/tests/examples/encoding/encoding.c new file mode 100644 index 0000000..89674ce --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/encoding/encoding.c @@ -0,0 +1,512 @@ +/* Example application for using GstProfile and encodebin + * Copyright (C) 2009 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include +#include +#include +#include "gstcapslist.h" + +static gboolean silent = FALSE; + +static void +list_codecs (void) +{ + GstCaps *l; + GstCaps *caps; + guint i, len; + + caps = gst_caps_new_empty (); + + g_print ("Available container formats:\n"); + l = gst_caps_list_container_formats (GST_RANK_NONE); + len = gst_caps_get_size (l); + for (i = 0; i < len; i++) { + GstStructure *st = gst_caps_steal_structure (l, 0); + gchar *tmpstr, *desc; + + gst_caps_append_structure (caps, st); + + tmpstr = gst_caps_to_string (caps); + desc = gst_pb_utils_get_codec_description (caps); + g_print (" %s - %s\n", desc, tmpstr); + g_free (tmpstr); + if (desc) + g_free (desc); + gst_caps_remove_structure (caps, 0); + } + g_print ("\n"); + gst_caps_unref (l); + + g_print ("Available video codecs:\n"); + l = gst_caps_list_video_encoding_formats (GST_RANK_NONE); + len = gst_caps_get_size (l); + for (i = 0; i < len; i++) { + GstStructure *st = gst_caps_steal_structure (l, 0); + gchar *tmpstr, *desc; + + gst_caps_append_structure (caps, st); + + tmpstr = gst_caps_to_string (caps); + desc = gst_pb_utils_get_codec_description (caps); + g_print (" %s - %s\n", desc, tmpstr); + g_free (tmpstr); + if (desc) + g_free (desc); + gst_caps_remove_structure (caps, 0); + } + g_print ("\n"); + gst_caps_unref (l); + + g_print ("Available audio codecs:\n"); + l = gst_caps_list_audio_encoding_formats (GST_RANK_NONE); + len = gst_caps_get_size (l); + for (i = 0; i < len; i++) { + GstStructure *st = gst_caps_steal_structure (l, 0); + gchar *tmpstr, *desc; + + gst_caps_append_structure (caps, st); + + tmpstr = gst_caps_to_string (caps); + desc = gst_pb_utils_get_codec_description (caps); + g_print (" %s - %s\n", desc, tmpstr); + g_free (tmpstr); + if (desc) + g_free (desc); + gst_caps_remove_structure (caps, 0); + } + g_print ("\n"); + gst_caps_unref (l); + + gst_caps_unref (caps); +} + +static gchar * +generate_filename (const GstCaps * container, const GstCaps * vcodec, + const GstCaps * acodec) +{ + gchar *a, *b, *c; + gchar *res = NULL; + guint i; + + a = gst_pb_utils_get_codec_description (container); + b = gst_pb_utils_get_codec_description (vcodec); + c = gst_pb_utils_get_codec_description (acodec); + + if (!a) + a = g_strdup_printf ("%.10s", + g_uri_escape_string (gst_caps_to_string (container), NULL, FALSE)); + if (!b) + b = g_strdup_printf ("%.10s", + g_uri_escape_string (gst_caps_to_string (vcodec), NULL, FALSE)); + if (!c) + c = g_strdup_printf ("%.10s", + g_uri_escape_string (gst_caps_to_string (acodec), NULL, FALSE)); + + for (i = 0; i < 256 && res == NULL; i++) { + res = g_strdup_printf ("%s-%s-%s-%d.file", a, b, c, i); + if (g_file_test (res, G_FILE_TEST_EXISTS)) { + g_free (res); + res = NULL; + } + } + /* Make sure file doesn't already exist */ + + g_free (a); + g_free (b); + g_free (c); + + return res; +} + +static GstEncodingProfile * +create_profile (GstCaps * cf, GstCaps * vf, GstCaps * af) +{ + GstEncodingContainerProfile *cprof = NULL; + + cprof = + gst_encoding_container_profile_new ((gchar *) "test-application-profile", + NULL, cf, NULL); + + if (vf) + gst_encoding_container_profile_add_profile (cprof, + (GstEncodingProfile *) gst_encoding_video_profile_new (vf, + NULL, NULL, 0)); + if (af) + gst_encoding_container_profile_add_profile (cprof, (GstEncodingProfile *) + gst_encoding_audio_profile_new (af, NULL, NULL, 0)); + + /* Let's print out some info */ + if (!silent) { + gchar *desc = gst_pb_utils_get_codec_description (cf); + gchar *cd = gst_caps_to_string (cf); + g_print ("Encoding parameters\n"); + g_print (" Container format : %s (%s)\n", desc, cd); + g_free (desc); + g_free (cd); + if (vf) { + desc = gst_pb_utils_get_codec_description (vf); + cd = gst_caps_to_string (vf); + g_print (" Video format : %s (%s)\n", desc, cd); + g_free (desc); + g_free (cd); + } + if (af) { + desc = gst_pb_utils_get_codec_description (af); + cd = gst_caps_to_string (af); + g_print (" Audio format : %s (%s)\n", desc, cd); + g_free (desc); + g_free (cd); + } + } + + return (GstEncodingProfile *) cprof; +} + +static GstEncodingProfile * +create_profile_from_string (gchar * format, gchar * vformat, gchar * aformat) +{ + GstEncodingProfile *prof = NULL; + GstCaps *cf = NULL, *vf = NULL, *af = NULL; + + if (format) + cf = gst_caps_from_string (format); + if (vformat) + vf = gst_caps_from_string (vformat); + if (aformat) + af = gst_caps_from_string (aformat); + + if (G_UNLIKELY ((vformat && (vf == NULL)) || (aformat && (af == NULL)))) + goto beach; + + prof = create_profile (cf, vf, af); + +beach: + if (cf) + gst_caps_unref (cf); + if (vf) + gst_caps_unref (vf); + if (af) + gst_caps_unref (af); + + return prof; +} + +static void +pad_added_cb (GstElement * uridecodebin, GstPad * pad, GstElement * encodebin) +{ + GstPad *sinkpad; + + sinkpad = gst_element_get_compatible_pad (encodebin, pad, NULL); + + if (sinkpad == NULL) { + GstCaps *caps; + + /* Ask encodebin for a compatible pad */ + caps = gst_pad_get_caps (pad); + g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad); + if (caps) + gst_caps_unref (caps); + } + if (sinkpad == NULL) { + g_print ("Couldn't get an encoding channel for pad %s:%s\n", + GST_DEBUG_PAD_NAME (pad)); + return; + } + + if (G_UNLIKELY (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) { + g_print ("Couldn't link pads\n"); + } + + return; +} + +static gboolean +autoplug_continue_cb (GstElement * uridecodebin, GstPad * somepad, + GstCaps * caps, GstElement * encodebin) +{ + GstPad *sinkpad; + + g_signal_emit_by_name (encodebin, "request-pad", caps, &sinkpad); + + if (sinkpad == NULL) + return TRUE; + + return FALSE; +} + +static void +bus_message_cb (GstBus * bus, GstMessage * message, GMainLoop * mainloop) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + g_print ("ERROR\n"); + gst_bus_set_flushing (bus, TRUE); + g_main_loop_quit (mainloop); + break; + case GST_MESSAGE_EOS: + g_print ("Done\n"); + g_main_loop_quit (mainloop); + break; + default: + break; + } +} + +static void +transcode_file (gchar * uri, gchar * outputuri, GstEncodingProfile * prof) +{ + GstElement *pipeline; + GstElement *src; + GstElement *ebin; + GstElement *sink; + GstBus *bus; + GstCaps *profilecaps, *rescaps; + GMainLoop *mainloop; + + g_print (" Input URI : %s\n", uri); + g_print (" Output URI : %s\n", outputuri); + + sink = gst_element_make_from_uri (GST_URI_SINK, outputuri, "sink"); + if (G_UNLIKELY (sink == NULL)) { + g_print ("Can't create output sink, most likely invalid output URI !\n"); + return; + } + + src = gst_element_factory_make ("uridecodebin", NULL); + if (G_UNLIKELY (src == NULL)) { + g_print ("Can't create uridecodebin for input URI, aborting!\n"); + return; + } + + /* Figure out the streams that can be passed as-is to encodebin */ + g_object_get (src, "caps", &rescaps, NULL); + rescaps = gst_caps_copy (rescaps); + profilecaps = gst_encoding_profile_get_input_caps (prof); + gst_caps_append (rescaps, profilecaps); + + /* Set properties */ + g_object_set (src, "uri", uri, "caps", rescaps, NULL); + + ebin = gst_element_factory_make ("encodebin", NULL); + g_object_set (ebin, "profile", prof, NULL); + + g_signal_connect (src, "autoplug-continue", G_CALLBACK (autoplug_continue_cb), + ebin); + g_signal_connect (src, "pad-added", G_CALLBACK (pad_added_cb), ebin); + + pipeline = gst_pipeline_new ("encoding-pipeline"); + + gst_bin_add_many (GST_BIN (pipeline), src, ebin, sink, NULL); + + gst_element_link (ebin, sink); + + mainloop = g_main_loop_new (NULL, FALSE); + + bus = gst_pipeline_get_bus ((GstPipeline *) pipeline); + gst_bus_add_signal_watch (bus); + g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop); + + if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { + g_print ("Failed to start the encoding\n"); + return; + } + + g_main_loop_run (mainloop); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +static gchar * +ensure_uri (gchar * location) +{ + gchar *res; + gchar *path; + + if (gst_uri_is_valid (location)) + return g_strdup (location); + + if (!g_path_is_absolute (location)) { + gchar *cur_dir; + cur_dir = g_get_current_dir (); + path = g_build_filename (cur_dir, location, NULL); + g_free (cur_dir); + } else + path = g_strdup (location); + + res = g_filename_to_uri (path, NULL, NULL); + g_free (path); + + return res; +} + +int +main (int argc, char **argv) +{ + GError *err = NULL; + gchar *outputuri = NULL; + gchar *format = NULL; + gchar *aformat = NULL; + gchar *vformat = NULL; + gboolean allmissing = FALSE; + gboolean listcodecs = FALSE; + GOptionEntry options[] = { + {"silent", 's', 0, G_OPTION_ARG_NONE, &silent, + "Don't output the information structure", NULL}, + {"outputuri", 'o', 0, G_OPTION_ARG_STRING, &outputuri, + "URI to encode to", "URI (://)"}, + {"format", 'f', 0, G_OPTION_ARG_STRING, &format, + "Container format", ""}, + {"vformat", 'v', 0, G_OPTION_ARG_STRING, &vformat, + "Video format", ""}, + {"aformat", 'a', 0, G_OPTION_ARG_STRING, &aformat, + "Audio format", ""}, + {"allmissing", 'm', 0, G_OPTION_ARG_NONE, &allmissing, + "encode to all matching format/codec that aren't specified", NULL}, + {"list-codecs", 'l', 0, G_OPTION_ARG_NONE, &listcodecs, + "list all available codecs and container formats", NULL}, + {NULL} + }; + GOptionContext *ctx; + GstEncodingProfile *prof; + gchar *inputuri; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new ("- encode URIs with GstProfile and encodebin"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + if (listcodecs) { + list_codecs (); + g_option_context_free (ctx); + exit (0); + } + + if (outputuri == NULL || argc != 2) { + g_print ("%s", g_option_context_get_help (ctx, TRUE, NULL)); + g_option_context_free (ctx); + exit (-1); + } + + g_option_context_free (ctx); + + /* Fixup outputuri to be a URI */ + inputuri = ensure_uri (argv[1]); + outputuri = ensure_uri (outputuri); + + if (allmissing) { + GList *muxers; + GstCaps *formats = NULL; + GstCaps *vformats = NULL; + GstCaps *aformats = NULL; + guint f, v, a, flen, vlen, alen; + + if (!format) + formats = gst_caps_list_container_formats (GST_RANK_NONE); + else + formats = gst_caps_from_string (format); + + if (!vformat) + vformats = gst_caps_list_video_encoding_formats (GST_RANK_NONE); + else + vformats = gst_caps_from_string (vformat); + + if (!aformat) + aformats = gst_caps_list_audio_encoding_formats (GST_RANK_NONE); + else + aformats = gst_caps_from_string (aformat); + muxers = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER, + GST_RANK_NONE); + + flen = gst_caps_get_size (formats); + + for (f = 0; f < flen; f++) { + GstCaps *container = + gst_caps_new_full (gst_caps_steal_structure (formats, 0), NULL); + GstCaps *compatv = + gst_caps_list_compatible_codecs (container, vformats, muxers); + GstCaps *compata = + gst_caps_list_compatible_codecs (container, aformats, muxers); + + vlen = gst_caps_get_size (compatv); + alen = gst_caps_get_size (compata); + + + for (v = 0; v < vlen; v++) { + GstCaps *vcodec = + gst_caps_new_full (gst_structure_copy (gst_caps_get_structure + (compatv, v)), NULL); + for (a = 0; a < alen; a++) { + GstCaps *acodec = + gst_caps_new_full (gst_structure_copy (gst_caps_get_structure + (compata, a)), NULL); + + prof = + create_profile ((GstCaps *) container, (GstCaps *) vcodec, + (GstCaps *) acodec); + if (G_UNLIKELY (prof == NULL)) { + g_print ("Wrong arguments\n"); + break; + } + outputuri = + ensure_uri (generate_filename (container, vcodec, acodec)); + transcode_file (inputuri, outputuri, prof); + gst_encoding_profile_unref (prof); + + gst_caps_unref (acodec); + } + gst_caps_unref (vcodec); + } + gst_caps_unref (container); + } + + } else { + + /* Create the profile */ + prof = create_profile_from_string (format, vformat, aformat); + if (G_UNLIKELY (prof == NULL)) { + g_print ("Encoding arguments are not valid !\n"); + return 1; + } + + /* Trancode file */ + transcode_file (inputuri, outputuri, prof); + + /* cleanup */ + gst_encoding_profile_unref (prof); + + } + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.c b/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.c new file mode 100644 index 0000000..aed5821 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.c @@ -0,0 +1,285 @@ +/* GStreamer + * Copyright (C) <2010> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "gstcapslist.h" + +/* + * Caps listing convenience functions + */ + +static gboolean +remove_range_foreach (GQuark field_id, const GValue * value, GstStructure * st) +{ + GType ftype = G_VALUE_TYPE (value); + /* const gchar *fname; */ + + if (ftype == GST_TYPE_INT_RANGE || ftype == GST_TYPE_DOUBLE_RANGE || + ftype == GST_TYPE_FRACTION_RANGE) { + gst_structure_remove_field (st, g_quark_to_string (field_id)); + return FALSE; + } + + /* fname = g_quark_to_string (field_id); */ + /* if (strstr (fname, "framerate") || strstr (fname, "pixel-aspect-ratio") || */ + /* strstr (fname, "rate")) { */ + /* gst_structure_remove_field (st, g_quark_to_string (field_id)); */ + /* return FALSE; */ + /* } */ + + return TRUE; +} + +static void +clear_caps (GstCaps * caps, GstCaps * rescaps) +{ + GstCaps *res; + GstStructure *st; + guint i; + + res = gst_caps_make_writable (caps); + + GST_DEBUG ("incoming caps %" GST_PTR_FORMAT, res); + + /* Remove width/height/framerate/depth/width fields */ + for (i = gst_caps_get_size (res); i; i--) { + st = gst_caps_get_structure (res, i - 1); + + /* Remove range fields */ + while (!gst_structure_foreach (st, + (GstStructureForeachFunc) remove_range_foreach, st)); + } + + GST_DEBUG ("stripped %" GST_PTR_FORMAT, res); + + /* And append to list without duplicates */ + while ((st = gst_caps_steal_structure (res, 0))) { + /* Skip fake codecs/containers */ + if (gst_structure_has_name (st, "audio/x-raw-int") || + gst_structure_has_name (st, "audio/x-raw-float") || + gst_structure_has_name (st, "video/x-raw-yuv") || + gst_structure_has_name (st, "video/x-raw-rgb") || + gst_structure_has_name (st, "unknown/unknown")) { + gst_structure_free (st); + continue; + } + + gst_caps_append_structure (rescaps, st); + } + + gst_caps_unref (res); +} + +static GstCaps * +get_all_caps (GList * elements, GstPadDirection direction) +{ + GstCaps *res = NULL, *res2; + GList *tmp; + + res = gst_caps_new_empty (); + + for (tmp = elements; tmp; tmp = tmp->next) { + GstElementFactory *factory = (GstElementFactory *) tmp->data; + const GList *templates; + GList *walk; + + templates = gst_element_factory_get_static_pad_templates (factory); + for (walk = (GList *) templates; walk; walk = g_list_next (walk)) { + GstStaticPadTemplate *templ = walk->data; + if (templ->direction == direction) + clear_caps (gst_static_caps_get (&templ->static_caps), res); + } + } + + res2 = gst_caps_normalize (res); + gst_caps_unref (res); + return res2; +} + +/** + * gst_caps_list_container_formats: + * @minrank: The minimum #GstRank + * + * Returns a #GstCaps corresponding to all the container formats + * one can mux to on this system. + * + * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it. + */ +GstCaps * +gst_caps_list_container_formats (GstRank minrank) +{ + GstCaps *res; + GList *muxers; + + muxers = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER, + minrank); + res = get_all_caps (muxers, GST_PAD_SRC); + gst_plugin_feature_list_free (muxers); + + return res; +} + +static GstCaps * +gst_caps_list_encoding_formats (GstRank minrank) +{ + GstCaps *res; + GList *encoders; + + encoders = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_ENCODER, + minrank); + res = get_all_caps (encoders, GST_PAD_SRC); + gst_plugin_feature_list_free (encoders); + + return res; +} + +/** + * gst_caps_list_video_encoding_formats: + * @minrank: The minimum #GstRank + * + * Returns a #GstCaps corresponding to all the video or image formats one + * can encode to on this system. + * + * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it. + */ +GstCaps * +gst_caps_list_video_encoding_formats (GstRank minrank) +{ + GstCaps *res; + GList *encoders; + + encoders = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER, minrank); + res = get_all_caps (encoders, GST_PAD_SRC); + gst_plugin_feature_list_free (encoders); + + return res; +} + + +/** + * gst_caps_list_audio_encoding_formats: + * @minrank: The minimum #GstRank + * + * Returns a #GstCaps corresponding to all the audio formats one + * can encode to on this system. + * + * Returns: A #GstCaps. Unref with %gst_caps_unref when done with it. + */ +GstCaps * +gst_caps_list_audio_encoding_formats (GstRank minrank) +{ + GstCaps *res; + GList *encoders; + + encoders = + gst_element_factory_list_get_elements + (GST_ELEMENT_FACTORY_TYPE_AUDIO_ENCODER, minrank); + res = get_all_caps (encoders, GST_PAD_SRC); + gst_plugin_feature_list_free (encoders); + + return res; +} + +/** + * gst_caps_list_compatible_codecs: + * @containerformat: A #GstCaps corresponding to a container format + * @codecformats: An optional #GstCaps of codec formats + * @muxers: An optional #GList of muxer #GstElementFactory. + * + * Returns an array of #GstCaps corresponding to the audio/video/text formats + * one can encode to and that can be muxed in the provided @containerformat. + * + * If specified, only the #GstCaps contained in @codecformats will be checked + * against, else all compatible audio/video formats will be returned. + * + * If specified, only the #GstElementFactory contained in @muxers will be checked, + * else all available muxers on the system will be checked. + * + * Returns: A #GstCaps containing all compatible formats. Unref with %gst_caps_unref + * when done. + */ +GstCaps * +gst_caps_list_compatible_codecs (const GstCaps * containerformat, + GstCaps * codecformats, GList * muxers) +{ + const GList *templates; + GstElementFactory *factory; + GList *walk; + GstCaps *res = NULL; + GstCaps *tmpcaps; + GList *tmp; + gboolean hadmuxers = (muxers != NULL); + gboolean hadcodecs = (codecformats != NULL); + + GST_DEBUG ("containerformat: %" GST_PTR_FORMAT, containerformat); + GST_DEBUG ("codecformats: %" GST_PTR_FORMAT, codecformats); + + if (!hadmuxers) + muxers = + gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_MUXER, + GST_RANK_NONE); + if (!hadcodecs) + codecformats = gst_caps_list_encoding_formats (GST_RANK_NONE); + + /* Get the highest rank muxer matching containerformat */ + tmp = + gst_element_factory_list_filter (muxers, containerformat, GST_PAD_SRC, + TRUE); + if (G_UNLIKELY (tmp == NULL)) + goto beach; + + factory = (GstElementFactory *) tmp->data; + + GST_DEBUG ("Trying with factory %s", + gst_element_factory_get_longname (factory)); + + /* Match all muxer sink pad templates against the available codec formats */ + templates = gst_element_factory_get_static_pad_templates (factory); + gst_plugin_feature_list_free (tmp); + + tmpcaps = gst_caps_new_empty (); + + for (walk = (GList *) templates; walk; walk = walk->next) { + GstStaticPadTemplate *templ = walk->data; + + if (templ->direction == GST_PAD_SINK) { + GstCaps *templ_caps; + + templ_caps = gst_static_caps_get (&templ->static_caps); + gst_caps_append (tmpcaps, gst_caps_copy (templ_caps)); + } + } + + res = gst_caps_intersect (tmpcaps, codecformats); + gst_caps_unref (tmpcaps); + +beach: + if (!hadmuxers) + gst_plugin_feature_list_free (muxers); + if (!hadcodecs) + gst_caps_unref (codecformats); + + tmpcaps = gst_caps_normalize (res); + gst_caps_unref (res); + + return tmpcaps; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.h b/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.h new file mode 100644 index 0000000..fa0ed83 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/encoding/gstcapslist.h @@ -0,0 +1,35 @@ +/* GStreamer + * Copyright (C) <2010> Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +GstCaps *gst_caps_list_compatible_codecs (const GstCaps *containerformat, + GstCaps *codecformats, + GList *muxers); + +GstCaps *gst_caps_list_compatible_containers (GstCaps *mediaformat, + GList *containerformats); + + +GstCaps *gst_caps_list_container_formats (GstRank minrank); + +GstCaps *gst_caps_list_video_encoding_formats (GstRank minrank); + +GstCaps *gst_caps_list_audio_encoding_formats (GstRank minrank); + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/gio/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/gio/.gitignore new file mode 100644 index 0000000..673c078 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/gio/.gitignore @@ -0,0 +1 @@ +giosrc-mounting diff --git a/gst-plugins-base-subtitles0.10/tests/examples/gio/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/gio/Makefile.am new file mode 100644 index 0000000..c4306f8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/gio/Makefile.am @@ -0,0 +1,8 @@ +if HAVE_GTK +if USE_GIO +noinst_PROGRAMS = giosrc-mounting +giosrc_mounting_SOURCES = giosrc-mounting.c +giosrc_mounting_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) $(GIO_CFLAGS) +giosrc_mounting_LDADD = $(GST_LIBS) $(GTK_LIBS) $(GIO_LIBS) +endif +endif diff --git a/gst-plugins-base-subtitles0.10/tests/examples/gio/giosrc-mounting.c b/gst-plugins-base-subtitles0.10/tests/examples/gio/giosrc-mounting.c new file mode 100644 index 0000000..0a8e202 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/gio/giosrc-mounting.c @@ -0,0 +1,127 @@ +/* GStreamer + * + * Copyright (C) 2009 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +static GstElement *pipeline = NULL; + +static void +mount_cb (GObject * obj, GAsyncResult * res, gpointer user_data) +{ + gboolean ret; + GError *err = NULL; + + ret = g_file_mount_enclosing_volume_finish (G_FILE (obj), res, &err); + + if (ret) { + g_print ("mounted successfully\n"); + gst_bus_set_flushing ((GstBus *) user_data, FALSE); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } else { + g_print ("mounting failed: %s\n", err->message); + g_clear_error (&err); + gtk_main_quit (); + } +} + +static gboolean +message_handler (GstBus * bus, GstMessage * message, gpointer user_data) +{ + + switch (message->type) { + case GST_MESSAGE_ELEMENT:{ + const GstStructure *s = gst_message_get_structure (message); + const gchar *name = gst_structure_get_name (s); + + if (strcmp (name, "not-mounted") == 0) { + GMountOperation *mop = gtk_mount_operation_new (NULL); + GFile *file = + G_FILE (g_value_get_object (gst_structure_get_value + (message->structure, "file"))); + + g_print ("not-mounted\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_bus_set_flushing (bus, TRUE); + + g_file_mount_enclosing_volume (file, G_MOUNT_MOUNT_NONE, + mop, NULL, mount_cb, bus); + + g_object_unref (mop); + } + break; + } + + case GST_MESSAGE_EOS: + g_print ("EOS\n"); + gtk_main_quit (); + break; + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + + gst_message_parse_error (message, &err, NULL); + g_print ("error: %s\n", err->message); + g_clear_error (&err); + + gtk_main_quit (); + break; + } + default: + break; + } + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + gint watch_id; + + if (argc != 2) { + g_print ("usage: giosrc-mounting URI\n"); + return -1; + } + + gst_init (NULL, NULL); + gtk_init (NULL, NULL); + + pipeline = gst_element_factory_make ("playbin2", NULL); + g_assert (pipeline); + g_object_set (G_OBJECT (pipeline), "uri", argv[1], NULL); + + bus = gst_element_get_bus (pipeline); + watch_id = gst_bus_add_watch (bus, message_handler, NULL); + gst_object_unref (bus); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + gtk_main (); + + g_source_remove (watch_id); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/overlay/.gitignore new file mode 100644 index 0000000..c8795e7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/.gitignore @@ -0,0 +1,5 @@ +gtk-xoverlay +qt-xoverlay +qtgv-xoverlay +moc_*.cpp + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/overlay/Makefile.am new file mode 100644 index 0000000..55dbb02 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/Makefile.am @@ -0,0 +1,47 @@ +EXAMPLES = + +if USE_X + +if HAVE_GTK_X11 +EXAMPLES += gtk-xoverlay + +gtk_xoverlay_SOURCES = gtk-xoverlay.c +gtk_xoverlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) $(GTK_CFLAGS) +gtk_xoverlay_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) $(GTK_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la +endif + +if HAVE_QT +EXAMPLES += qt-xoverlay + +qt_xoverlay_SOURCES = qt-xoverlay.cpp +qt_xoverlay_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CXXFLAGS) $(X_CFLAGS) $(QT_CFLAGS) +qt_xoverlay_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) $(QT_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la + +endif + +if HAVE_QT_GV +EXAMPLES += qtgv-xoverlay + +qtgv_xoverlay_SOURCES = qtgv-xoverlay.cpp qtgv-xoverlay.h +qtgv_xoverlay_CXXFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CXXFLAGS) $(X_CFLAGS) $(QT_CFLAGS) +qtgv_xoverlay_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) $(QT_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la + +# qt moc support, according to http://qtnode.net/wiki/Qt_with_autotools + +nodist_qtgv_xoverlay_SOURCES = moc_qtgv-xoverlay.cpp + +moc_%.cpp:%.h + $(AM_V_GEN)$(QT4_MOC) $< -o $@ + +EXTRA_DIST = $(nodist_qtgv_xoverlay_SOURCES:moc_%.cpp=%.h) +CLEANFILES = $(nodist_qtgv_xoverlay_SOURCES) + +endif + +endif + +noinst_PROGRAMS = $(EXAMPLES) + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/gtk-xoverlay.c b/gst-plugins-base-subtitles0.10/tests/examples/overlay/gtk-xoverlay.c new file mode 100644 index 0000000..c05685c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/gtk-xoverlay.c @@ -0,0 +1,149 @@ +/* GStreamer + * Copyright (C) <2010> Stefan Kost + * + * gtk-xoverlay: demonstrate overlay handling using gtk + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +#include +#include + +#include + +static void +window_closed (GtkWidget * widget, GdkEvent * event, gpointer user_data) +{ + GstElement *pipeline = user_data; + + gtk_widget_hide (widget); + gst_element_set_state (pipeline, GST_STATE_NULL); + gtk_main_quit (); +} + +/* slightly convoluted way to find a working video sink that's not a bin, + * one could use autovideosink from gst-plugins-good instead + */ +static GstElement * +find_video_sink (void) +{ + GstStateChangeReturn sret; + GstElement *sink; + + if ((sink = gst_element_factory_make ("xvimagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + + if ((sink = gst_element_factory_make ("ximagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + + if (strcmp (DEFAULT_VIDEOSINK, "xvimagesink") == 0 || + strcmp (DEFAULT_VIDEOSINK, "ximagesink") == 0) + return NULL; + + if ((sink = gst_element_factory_make (DEFAULT_VIDEOSINK, NULL))) { + if (GST_IS_BIN (sink)) { + gst_object_unref (sink); + return NULL; + } + + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + return NULL; +} + +int +main (int argc, char **argv) +{ + GdkWindow *video_window_xwindow; + GtkWidget *window, *video_window; + GstElement *pipeline, *src, *sink; + gulong embed_xid; + GstStateChangeReturn sret; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + /* prepare the pipeline */ + + pipeline = gst_pipeline_new ("xvoverlay"); + src = gst_element_factory_make ("videotestsrc", NULL); + sink = find_video_sink (); + + if (sink == NULL) + g_error ("Couldn't find a working video sink."); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + + /* prepare the ui */ + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (window), "delete-event", + G_CALLBACK (window_closed), (gpointer) pipeline); + gtk_window_set_default_size (GTK_WINDOW (window), 320, 240); + gtk_window_set_title (GTK_WINDOW (window), "GstXOverlay Gtk+ demo"); + + video_window = gtk_drawing_area_new (); + gtk_widget_set_double_buffered (video_window, FALSE); + gtk_container_add (GTK_CONTAINER (window), video_window); + gtk_container_set_border_width (GTK_CONTAINER (window), 16); + + gtk_widget_show_all (window); + gtk_widget_realize (window); + + video_window_xwindow = gtk_widget_get_window (video_window); + embed_xid = GDK_WINDOW_XID (video_window_xwindow); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid); + + /* run the pipeline */ + + sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (sret == GST_STATE_CHANGE_FAILURE) + gst_element_set_state (pipeline, GST_STATE_NULL); + else + gtk_main (); + + gst_object_unref (pipeline); + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/qt-xoverlay.cpp b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qt-xoverlay.cpp new file mode 100644 index 0000000..aa483a7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qt-xoverlay.cpp @@ -0,0 +1,130 @@ +/* GStreamer + * Copyright (C) <2010> Stefan Kost + * + * qt-xoverlay: demonstrate overlay handling using qt + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +#include +#include +#include + +/* slightly convoluted way to find a working video sink that's not a bin, + * one could use autovideosink from gst-plugins-good instead + */ +static GstElement * +find_video_sink (void) +{ + GstStateChangeReturn sret; + GstElement *sink; + + if ((sink = gst_element_factory_make ("xvimagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + + if ((sink = gst_element_factory_make ("ximagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + + if (strcmp (DEFAULT_VIDEOSINK, "xvimagesink") == 0 || + strcmp (DEFAULT_VIDEOSINK, "ximagesink") == 0) + return NULL; + + if ((sink = gst_element_factory_make (DEFAULT_VIDEOSINK, NULL))) { + if (GST_IS_BIN (sink)) { + gst_object_unref (sink); + return NULL; + } + + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_SUCCESS) + return sink; + + gst_element_set_state (sink, GST_STATE_NULL); + } + gst_object_unref (sink); + return NULL; +} + +int main(int argc, char *argv[]) +{ + if (!g_thread_supported ()) + g_thread_init (NULL); + + gst_init (&argc, &argv); + QApplication app(argc, argv); + app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ())); + + /* prepare the pipeline */ + + GstElement *pipeline = gst_pipeline_new ("xvoverlay"); + GstElement *src = gst_element_factory_make ("videotestsrc", NULL); + GstElement *sink = find_video_sink (); + + if (sink == NULL) + g_error ("Couldn't find a working video sink."); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + + /* prepare the ui */ + + QWidget window; + window.resize(320, 240); + window.setWindowTitle("GstXOverlay Qt demo"); + window.show(); + + WId xwinid = window.winId(); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid); + + /* run the pipeline */ + + GstStateChangeReturn sret = gst_element_set_state (pipeline, + GST_STATE_PLAYING); + if (sret == GST_STATE_CHANGE_FAILURE) { + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + /* Exit application */ + QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); + } + + int ret = app.exec(); + + window.hide(); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.cpp b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.cpp new file mode 100644 index 0000000..58af85b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.cpp @@ -0,0 +1,128 @@ +/* GStreamer + * Copyright (C) <2010> Alexander Bokovoy + * + * qtgv-xoverlay: demonstrate overlay handling using qt graphics view + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 "qtgv-xoverlay.h" + +#include +#include + +#include + +SinkPipeline::SinkPipeline(QGraphicsView *parent) : QObject(parent) +{ + GstStateChangeReturn sret; + + pipeline = gst_pipeline_new ("xvoverlay"); + src = gst_element_factory_make ("videotestsrc", NULL); + + if ((sink = gst_element_factory_make ("xvimagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret != GST_STATE_CHANGE_SUCCESS) { + gst_element_set_state (sink, GST_STATE_NULL); + gst_object_unref (sink); + + if ((sink = gst_element_factory_make ("ximagesink", NULL))) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret != GST_STATE_CHANGE_SUCCESS) { + gst_element_set_state (sink, GST_STATE_NULL); + gst_object_unref (sink); + + if (strcmp (DEFAULT_VIDEOSINK, "xvimagesink") != 0 && + strcmp (DEFAULT_VIDEOSINK, "ximagesink") != 0) { + + if ((sink = gst_element_factory_make (DEFAULT_VIDEOSINK, NULL))) { + if (!GST_IS_BIN (sink)) { + sret = gst_element_set_state (sink, GST_STATE_READY); + if (sret != GST_STATE_CHANGE_SUCCESS) { + gst_element_set_state (sink, GST_STATE_NULL); + gst_object_unref (sink); + sink = NULL; + } + } else { + gst_object_unref (sink); + sink = NULL; + } + } + } + } + } + } + } + + if (sink == NULL) + g_error ("Couldn't find a working video sink."); + + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + xwinid = parent->winId(); +} + +SinkPipeline::~SinkPipeline() +{ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); +} + +void SinkPipeline::startPipeline() +{ + GstStateChangeReturn sret; + + /* we know what the video sink is in this case (xvimagesink), so we can + * just set it directly here now (instead of waiting for a prepare-xwindow-id + * element message in a sync bus handler and setting it there) */ + + gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), xwinid); + + sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (sret == GST_STATE_CHANGE_FAILURE) { + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + /* Exit application */ + QTimer::singleShot(0, QApplication::activeWindow(), SLOT(quit())); + } +} + +int main( int argc, char **argv ) +{ + QApplication app(argc, argv); + + QGraphicsScene scene; + scene.setSceneRect( -100.0, -100.0, 200.0, 200.0 ); + + QGraphicsView view( &scene ); + view.resize(320, 240); + view.setWindowTitle("GstXOverlay Qt GraphicsView demo"); + view.show(); + + gst_init (&argc, &argv); + SinkPipeline pipeline(&view); + pipeline.startPipeline(); + + int ret = app.exec(); + + view.hide(); + + return ret; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.h b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.h new file mode 100644 index 0000000..091fff8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/overlay/qtgv-xoverlay.h @@ -0,0 +1,45 @@ +/* GStreamer + * Copyright (C) <2010> Alexander Bokovoy + * + * qtgv-xoverlay: demonstrate overlay handling using qt graphics view + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 QTGV_XOVERLAY_H +#define QTGV_XOVERLAY_H + +#include +#include + + +class SinkPipeline : public QObject +{ + Q_OBJECT +public: + SinkPipeline(QGraphicsView *parent = 0); + ~SinkPipeline(); + + void startPipeline(); + +private: + GstElement *pipeline; + GstElement *sink; + GstElement *src; + WId xwinid; +}; + +#endif // QTGV_XOVERLAY_H diff --git a/gst-plugins-base-subtitles0.10/tests/examples/playrec/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/playrec/.gitignore new file mode 100644 index 0000000..ad309aa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/playrec/.gitignore @@ -0,0 +1 @@ +playrec diff --git a/gst-plugins-base-subtitles0.10/tests/examples/playrec/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/playrec/Makefile.am new file mode 100644 index 0000000..f7548b5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/playrec/Makefile.am @@ -0,0 +1,4 @@ +noinst_PROGRAMS = playrec +playrec_SOURCES = playrec.c +playrec_CFLAGS = $(GST_CFLAGS) +playrec_LDADD = $(GST_LIBS) diff --git a/gst-plugins-base-subtitles0.10/tests/examples/playrec/playrec.c b/gst-plugins-base-subtitles0.10/tests/examples/playrec/playrec.c new file mode 100644 index 0000000..352f65a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/playrec/playrec.c @@ -0,0 +1,166 @@ +/* GStreamer + * + * Copyright (C) 2010 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* An example of synchronized playback and recording. + * The trick is to wait for the playback pipeline to preroll before starting + * playback and recording. + */ +#include + +#include + +/* Define to run the asynchronous version. This requires 0.10.31 of the + * GStreamer core. The async version has the benefit that it doesn't block the + * main thread but it produces slightly less clear code. */ +#define ASYNC_VERSION + +static GMainLoop *loop; +static GstElement *pipeline = NULL; +static GstElement *play_bin, *play_source, *play_sink; +static GstElement *rec_bin, *rec_source, *rec_sink; + +static gboolean +message_handler (GstBus * bus, GstMessage * message, gpointer user_data) +{ + + switch (GST_MESSAGE_TYPE (message)) { +#ifdef ASYNC_VERSION + case GST_MESSAGE_ELEMENT:{ + const GstStructure *str; + + str = gst_message_get_structure (message); + + if (gst_structure_has_name (str, "GstBinForwarded")) { + GstMessage *orig; + + /* unwrap the element message */ + gst_structure_get (str, "message", GST_TYPE_MESSAGE, &orig, NULL); + g_assert (orig); + + switch (GST_MESSAGE_TYPE (orig)) { + case GST_MESSAGE_ASYNC_DONE: + g_print ("ASYNC done %s\n", GST_MESSAGE_SRC_NAME (orig)); + if (GST_MESSAGE_SRC (orig) == GST_OBJECT_CAST (play_bin)) { + g_print + ("prerolled, starting synchronized playback and recording\n"); + /* returns ASYNC because the sink linked to the live source is not + * prerolled */ + g_assert (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_ASYNC); + } + break; + default: + break; + } + } + break; + } +#endif + case GST_MESSAGE_EOS: + g_print ("EOS\n"); + g_main_loop_quit (loop); + break; + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + + gst_message_parse_error (message, &err, NULL); + g_print ("error: %s\n", err->message); + g_clear_error (&err); + + g_main_loop_quit (loop); + break; + } + default: + break; + } + + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GstBus *bus; + gint watch_id; + + gst_init (NULL, NULL); + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); +#ifdef ASYNC_VERSION + /* this enables messages of individual elements inside the pipeline */ + g_object_set (pipeline, "message-forward", TRUE, NULL); +#endif + + /* make a bin with the playback elements this is a non-live pipeline */ + play_bin = gst_bin_new ("play_bin"); + play_source = gst_element_factory_make ("audiotestsrc", "play_source"); + play_sink = gst_element_factory_make ("autoaudiosink", "play_sink"); + + gst_bin_add (GST_BIN (play_bin), play_source); + gst_bin_add (GST_BIN (play_bin), play_sink); + + gst_element_link (play_source, play_sink); + + /* make bin with the record elements, this is a live pipeline */ + rec_bin = gst_bin_new ("rec_bin"); + rec_source = gst_element_factory_make ("autoaudiosrc", "rec_source"); + rec_sink = gst_element_factory_make ("fakesink", "rec_sink"); + + gst_bin_add (GST_BIN (rec_bin), rec_source); + gst_bin_add (GST_BIN (rec_bin), rec_sink); + + gst_element_link (rec_source, rec_sink); + + gst_bin_add (GST_BIN (pipeline), play_bin); + gst_bin_add (GST_BIN (pipeline), rec_bin); + + bus = gst_element_get_bus (pipeline); + watch_id = gst_bus_add_watch (bus, message_handler, NULL); + gst_object_unref (bus); + + g_print ("going to PAUSED\n"); + /* returns NO_PREROLL because we have a live element */ + g_assert (gst_element_set_state (pipeline, + GST_STATE_PAUSED) == GST_STATE_CHANGE_NO_PREROLL); + + g_print ("waiting for playback preroll\n"); +#ifndef ASYNC_VERSION + /* sync wait for preroll on the playback bin and then go to PLAYING */ + g_assert (gst_element_get_state (play_bin, NULL, NULL, + GST_CLOCK_TIME_NONE) == GST_STATE_CHANGE_SUCCESS); + g_print ("prerolled, starting synchronized playback and recording\n"); + /* returns ASYNC because the sink linked to the live source is not + * prerolled */ + g_assert (gst_element_set_state (pipeline, + GST_STATE_PLAYING) == GST_STATE_CHANGE_ASYNC); +#endif + + g_main_loop_run (loop); + + g_source_remove (watch_id); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + g_main_loop_unref (loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/seek/.gitignore new file mode 100644 index 0000000..6315cd3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/.gitignore @@ -0,0 +1,5 @@ +jsseek +scrubby +seek +stepping +stepping2 diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/seek/Makefile.am new file mode 100644 index 0000000..ae34780 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/Makefile.am @@ -0,0 +1,17 @@ +if HAVE_GTK_X11 +if HAVE_LINUX_JOYSTICK_HEADERS +GTK_EXAMPLES=seek scrubby jsseek +else +GTK_EXAMPLES=seek scrubby +endif +endif + +examples = $(GTK_EXAMPLES) stepping stepping2 + +noinst_PROGRAMS = $(examples) + +LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_LIBS) $(GTK_LIBS) $(LIBM) + +AM_CFLAGS = -I$(top_builddir)/gst-libs $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/jsseek.c b/gst-plugins-base-subtitles0.10/tests/examples/seek/jsseek.c new file mode 100644 index 0000000..ec74cc8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/jsseek.c @@ -0,0 +1,3056 @@ +/* GStreamer + * + * seek.c: seeking sample application + * + * Copyright (C) 2005 Wim Taymans + * 2006 Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include +#include + +#ifdef HAVE_X +#include +#endif +#include + +GST_DEBUG_CATEGORY_STATIC (seek_debug); +#define GST_CAT_DEFAULT (seek_debug) + +#if (!GTK_CHECK_VERSION(2, 23, 0) || GTK_CHECK_VERSION(2, 90, 0)) && !GTK_CHECK_VERSION(2, 91, 1) +#define gtk_combo_box_text_new gtk_combo_box_new_text +#define gtk_combo_box_text_append_text gtk_combo_box_append_text +#define gtk_combo_box_text_remove gtk_combo_box_remove_text +#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX +#endif + +#if !GTK_CHECK_VERSION (2, 17, 7) +static void +gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a) +{ + *a = w->allocation; +} +#endif + +/* configuration */ + +//#define SOURCE "filesrc" +#define SOURCE "gnomevfssrc" + +#define ASINK "alsasink" +//#define ASINK "osssink" + +#define VSINK "xvimagesink" +//#define VSINK "sdlvideosink" +//#define VSINK "ximagesink" +//#define VSINK "aasink" +//#define VSINK "cacasink" + +#define FILL_INTERVAL 100 +//#define UPDATE_INTERVAL 500 +//#define UPDATE_INTERVAL 100 +//#define UPDATE_INTERVAL 10 +#define UPDATE_INTERVAL 40 + +/* number of milliseconds to play for after a seek */ +#define SCRUB_TIME 100 + +/* timeout for gst_element_get_state() after a seek */ +#define SEEK_TIMEOUT 40 * GST_MSECOND + +#define DEFAULT_VIDEO_HEIGHT 300 + +/* the state to go to when stop is pressed */ +#define STOP_STATE GST_STATE_READY + + +static GList *seekable_pads = NULL; +static GList *rate_pads = NULL; +static GList *seekable_elements = NULL; + +static gboolean accurate_seek = FALSE; +static gboolean keyframe_seek = FALSE; +static gboolean loop_seek = FALSE; +static gboolean flush_seek = TRUE; +static gboolean scrub = TRUE; +static gboolean play_scrub = FALSE; +static gboolean skip_seek = FALSE; +static gdouble rate = 1.0; + +static GstElement *pipeline; +static gint pipeline_type; +static const gchar *pipeline_spec; +static gint64 position = -1; +static gint64 duration = -1; +static GtkAdjustment *adjustment; +static GtkWidget *hscale, *statusbar; +static guint status_id = 0; +static gboolean stats = FALSE; +static gboolean elem_seek = FALSE; +static gboolean verbose = FALSE; +static gchar *js_device = NULL; + +static gboolean is_live = FALSE; +static gboolean buffering = FALSE; +static GstBufferingMode mode; +static gint64 buffering_left; +static GstState state = GST_STATE_NULL; +static guint update_id = 0; +static guint seek_timeout_id = 0; +static gulong changed_id; +static guint fill_id = 0; + +static gint n_video = 0, n_audio = 0, n_text = 0; +static gboolean need_streams = TRUE; +static GtkWidget *video_combo, *audio_combo, *text_combo, *vis_combo; +static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox; +static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton; +static GtkWidget *skip_checkbox, *video_window, *download_checkbox; +static GtkWidget *buffer_checkbox, *rate_spinbutton; + +static GStaticMutex state_mutex = G_STATIC_MUTEX_INIT; + +static GtkWidget *format_combo, *step_amount_spinbutton, *step_rate_spinbutton; +static GtkWidget *shuttle_checkbox, *step_button; +static GtkWidget *shuttle_hscale; +static GtkAdjustment *shuttle_adjustment; + +static GList *paths = NULL, *l = NULL; + +gint js_fd; + +/* we keep an array of the visualisation entries so that we can easily switch + * with the combo box index. */ +typedef struct +{ + GstElementFactory *factory; +} VisEntry; + +static GArray *vis_entries; + +static void clear_streams (GstElement * pipeline); +static void volume_notify_cb (GstElement * pipeline, GParamSpec * arg, + gpointer user_dat); + +/* pipeline construction */ + +typedef struct +{ + const gchar *padname; + GstPad *target; + GstElement *bin; +} +dyn_link; + +static GstElement * +gst_element_factory_make_or_warn (const gchar * type, const gchar * name) +{ + GstElement *element = gst_element_factory_make (type, name); + + if (!element) { + g_warning ("Failed to create element %s of type %s", name, type); + } + + return element; +} + +static void +dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) +{ + gchar *padname; + dyn_link *connect = (dyn_link *) data; + + padname = gst_pad_get_name (newpad); + + if (connect->padname == NULL || !strcmp (padname, connect->padname)) { + if (connect->bin) + gst_bin_add (GST_BIN (pipeline), connect->bin); + gst_pad_link (newpad, connect->target); + + //seekable_pads = g_list_prepend (seekable_pads, newpad); + rate_pads = g_list_prepend (rate_pads, newpad); + } + g_free (padname); +} + +static void +setup_dynamic_link (GstElement * element, const gchar * padname, + GstPad * target, GstElement * bin) +{ + dyn_link *connect; + + connect = g_new0 (dyn_link, 1); + connect->padname = g_strdup (padname); + connect->target = target; + connect->bin = bin; + + g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link), + connect); +} + +static GstElement * +make_mod_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("modplug", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_dv_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *demux, *decoder, *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (pipeline), a_queue); + gst_bin_add (GST_BIN (pipeline), audiosink); + gst_bin_add (GST_BIN (pipeline), v_queue); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), videosink); + + gst_element_link (src, demux); + gst_element_link (a_queue, audiosink); + gst_element_link (v_queue, decoder); + gst_element_link (decoder, videosink); + + setup_dynamic_link (demux, "video", gst_element_get_static_pad (v_queue, + "sink"), NULL); + setup_dynamic_link (demux, "audio", gst_element_get_static_pad (a_queue, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + + return pipeline; +} + +static GstElement * +make_wav_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("wavparse", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + + setup_dynamic_link (decoder, "src", gst_element_get_static_pad (audiosink, + "sink"), NULL); + + seekable_elements = g_list_prepend (seekable_elements, audiosink); + + /* force element seeking on this pipeline */ + elem_seek = TRUE; + + return pipeline; +} + +static GstElement * +make_flac_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("flacdec", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_sid_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("siddec", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_parse_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *parser, *fakesink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + parser = gst_element_factory_make_or_warn ("mpegparse", "parse"); + fakesink = gst_element_factory_make_or_warn ("fakesink", "sink"); + g_object_set (G_OBJECT (fakesink), "silent", TRUE, NULL); + g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), parser); + gst_bin_add (GST_BIN (pipeline), fakesink); + + gst_element_link (src, parser); + gst_element_link (parser, fakesink); + + seekable = gst_element_get_static_pad (parser, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (parser, "sink")); + + return pipeline; +} + +static GstElement * +make_vorbis_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin; + GstElement *src, *demux, *decoder, *convert, *audiosink; + GstPad *pad, *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + decoder = gst_element_factory_make_or_warn ("vorbisdec", "decoder"); + convert = gst_element_factory_make_or_warn ("audioconvert", "convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + audio_bin = gst_bin_new ("a_decoder_bin"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (audio_bin), decoder); + gst_bin_add (GST_BIN (audio_bin), convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + gst_bin_add (GST_BIN (pipeline), audio_bin); + + gst_element_link (src, demux); + gst_element_link (decoder, convert); + gst_element_link (convert, audiosink); + + pad = gst_element_get_static_pad (decoder, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_theora_pipeline (const gchar * location) +{ + GstElement *pipeline, *video_bin; + GstElement *src, *demux, *decoder, *convert, *videosink; + GstPad *pad, *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + decoder = gst_element_factory_make_or_warn ("theoradec", "decoder"); + convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert"); + videosink = gst_element_factory_make_or_warn (VSINK, "sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (video_bin), decoder); + gst_bin_add (GST_BIN (video_bin), convert); + gst_bin_add (GST_BIN (video_bin), videosink); + gst_bin_add (GST_BIN (pipeline), video_bin); + + gst_element_link (src, demux); + gst_element_link (decoder, convert); + gst_element_link (convert, videosink); + + pad = gst_element_get_static_pad (decoder, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_vorbis_theora_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue, *v_scale; + GstPad *seekable; + GstPad *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec"); + a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_queue, a_decoder); + gst_element_link (a_decoder, a_convert); + gst_element_link (a_convert, audiosink); + + pad = gst_element_get_static_pad (a_queue, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec"); + v_convert = + gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert"); + v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_convert); + gst_bin_add (GST_BIN (video_bin), v_scale); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link_many (v_queue, v_decoder, v_convert, v_scale, videosink, + NULL); + + pad = gst_element_get_static_pad (v_queue, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (a_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_avi_msmpeg4v3_mp3_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable, *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("avidemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_queue, a_decoder); + gst_element_link (a_decoder, a_convert); + gst_element_link (a_convert, audiosink); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + pad = gst_element_get_static_pad (a_queue, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec"); + v_convert = + gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_convert); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + pad = gst_element_get_static_pad (v_queue, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (a_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mp3_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *parser, *decoder, *audiosink, *queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + parser = gst_element_factory_make_or_warn ("mp3parse", "parse"); + decoder = gst_element_factory_make_or_warn ("mad", "dec"); + queue = gst_element_factory_make_or_warn ("queue", "queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + + seekable_elements = g_list_prepend (seekable_elements, audiosink); + + g_object_set (G_OBJECT (src), "location", location, NULL); + //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), parser); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), queue); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, parser); + gst_element_link (parser, decoder); + gst_element_link (decoder, queue); + gst_element_link (queue, audiosink); + + seekable = gst_element_get_static_pad (queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_avi_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink; + GstElement *a_queue = NULL, *v_queue = NULL; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("avidemux", "demux"); + seekable_elements = g_list_prepend (seekable_elements, demux); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + gst_element_set_state (audio_bin, GST_STATE_PAUSED); + + setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder, + "sink"), audio_bin); + + seekable = gst_element_get_static_pad (a_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + gst_element_link (v_decoder, v_queue); + gst_element_link (v_queue, videosink); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_set_state (video_bin, GST_STATE_PAUSED); + + setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder, + "sink"), video_bin); + + seekable = gst_element_get_static_pad (v_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mpeg_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable; + GstPad *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux"); + demux = gst_element_factory_make_or_warn ("flupsdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + pad = gst_element_get_static_pad (a_decoder, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, "audio_c0", gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_filter); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link (v_decoder, v_queue); + gst_element_link (v_queue, v_filter); + gst_element_link (v_filter, videosink); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + pad = gst_element_get_static_pad (v_decoder, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, "video_e0", gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (v_filter, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mpegnt_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter; + GstElement *audiosink, *videosink; + GstElement *a_queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("mpegdemux", "demux"); + //g_object_set (G_OBJECT (demux), "sync", TRUE, NULL); + + seekable_elements = g_list_prepend (seekable_elements, demux); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL); + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder, + "sink"), audio_bin); + + seekable = gst_element_get_static_pad (a_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec"); + v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + gst_element_link_many (v_decoder, v_filter, videosink, NULL); + + gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL); + + setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder, + "sink"), video_bin); + + seekable = gst_element_get_static_pad (v_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static void +playerbin_set_uri (GstElement * player, const gchar * location) +{ + gchar *uri; + + /* Add "file://" prefix for convenience */ + if (g_str_has_prefix (location, "/")) { + uri = g_strconcat ("file://", location, NULL); + g_object_set (G_OBJECT (player), "uri", uri, NULL); + g_free (uri); + } else { + g_object_set (G_OBJECT (player), "uri", location, NULL); + } +} + +static GstElement * +construct_playerbin (const gchar * name, const gchar * location) +{ + GstElement *player; + + player = gst_element_factory_make (name, "player"); + g_assert (player); + + playerbin_set_uri (player, location); + + seekable_elements = g_list_prepend (seekable_elements, player); + + /* force element seeking on this pipeline */ + elem_seek = TRUE; + + return player; +} + +static GstElement * +make_playerbin_pipeline (const gchar * location) +{ + return construct_playerbin ("playbin", location); +} + +static GstElement * +make_playerbin2_pipeline (const gchar * location) +{ + GstElement *pipeline = construct_playerbin ("playbin2", location); + + /* FIXME: this is not triggered, playbin2 is not forwarding it from the sink */ + g_signal_connect (pipeline, "notify::volume", G_CALLBACK (volume_notify_cb), + NULL); + return pipeline; +} + +#ifndef GST_DISABLE_PARSE +static GstElement * +make_parselaunch_pipeline (const gchar * description) +{ + GstElement *pipeline; + GError *error = NULL; + + pipeline = gst_parse_launch (description, &error); + + seekable_elements = g_list_prepend (seekable_elements, pipeline); + + elem_seek = TRUE; + + return pipeline; +} +#endif + +typedef struct +{ + const gchar *name; + GstElement *(*func) (const gchar * location); +} +Pipeline; + +static Pipeline pipelines[] = { + {"mp3", make_mp3_pipeline}, + {"avi", make_avi_pipeline}, + {"mpeg1", make_mpeg_pipeline}, + {"mpegparse", make_parse_pipeline}, + {"vorbis", make_vorbis_pipeline}, + {"theora", make_theora_pipeline}, + {"ogg/v/t", make_vorbis_theora_pipeline}, + {"avi/msmpeg4v3/mp3", make_avi_msmpeg4v3_mp3_pipeline}, + {"sid", make_sid_pipeline}, + {"flac", make_flac_pipeline}, + {"wav", make_wav_pipeline}, + {"mod", make_mod_pipeline}, + {"dv", make_dv_pipeline}, + {"mpeg1nothreads", make_mpegnt_pipeline}, + {"playerbin", make_playerbin_pipeline}, +#ifndef GST_DISABLE_PARSE + {"parse-launch", make_parselaunch_pipeline}, +#endif + {"playerbin2", make_playerbin2_pipeline}, + {NULL, NULL}, +}; + +#define NUM_TYPES ((sizeof (pipelines) / sizeof (Pipeline)) - 1) + +/* ui callbacks and helpers */ + +static gchar * +format_value (GtkScale * scale, gdouble value) +{ + gint64 real; + gint64 seconds; + gint64 subseconds; + + real = value * duration / 100; + seconds = (gint64) real / GST_SECOND; + subseconds = (gint64) real / (GST_SECOND / 100); + + return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02" + G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100); +} + + +static gchar * +shuttle_format_value (GtkScale * scale, gdouble value) +{ + return g_strdup_printf ("%0.*g", gtk_scale_get_digits (scale), value); +} + +typedef struct +{ + const gchar *name; + const GstFormat format; +} +seek_format; + +static seek_format seek_formats[] = { + {"tim", GST_FORMAT_TIME}, + {"byt", GST_FORMAT_BYTES}, + {"buf", GST_FORMAT_BUFFERS}, + {"def", GST_FORMAT_DEFAULT}, + {NULL, 0}, +}; + +G_GNUC_UNUSED static void +query_rates (void) +{ + GList *walk = rate_pads; + + while (walk) { + GstPad *pad = GST_PAD (walk->data); + gint i = 0; + + g_print ("rate/sec %8.8s: ", GST_PAD_NAME (pad)); + while (seek_formats[i].name) { + gint64 value; + GstFormat format; + + format = seek_formats[i].format; + + if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format, + &value)) { + g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value); + } else { + g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*"); + } + + i++; + } + g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad)); + + walk = g_list_next (walk); + } +} + +G_GNUC_UNUSED static void +query_positions_elems (void) +{ + GList *walk = seekable_elements; + + while (walk) { + GstElement *element = GST_ELEMENT (walk->data); + gint i = 0; + + g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element)); + while (seek_formats[i].name) { + gint64 position, total; + GstFormat format; + + format = seek_formats[i].format; + + if (gst_element_query_position (element, &format, &position) && + gst_element_query_duration (element, &format, &total)) { + g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ", + seek_formats[i].name, position, total); + } else { + g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*", + "*NA*"); + } + i++; + } + g_print (" %s\n", GST_ELEMENT_NAME (element)); + + walk = g_list_next (walk); + } +} + +G_GNUC_UNUSED static void +query_positions_pads (void) +{ + GList *walk = seekable_pads; + + while (walk) { + GstPad *pad = GST_PAD (walk->data); + gint i = 0; + + g_print ("positions %8.8s: ", GST_PAD_NAME (pad)); + while (seek_formats[i].name) { + GstFormat format; + gint64 position, total; + + format = seek_formats[i].format; + + if (gst_pad_query_position (pad, &format, &position) && + gst_pad_query_duration (pad, &format, &total)) { + g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ", + seek_formats[i].name, position, total); + } else { + g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*", + "*NA*"); + } + + i++; + } + g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad)); + + walk = g_list_next (walk); + } +} + +static gboolean start_seek (GtkWidget * widget, GdkEventButton * event, + gpointer user_data); +static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event, + gpointer user_data); +static void seek_cb (GtkWidget * widget); + +static void +set_scale (gdouble value) +{ + g_signal_handlers_block_by_func (hscale, (void *) start_seek, + (void *) pipeline); + g_signal_handlers_block_by_func (hscale, (void *) stop_seek, + (void *) pipeline); + g_signal_handlers_block_by_func (hscale, (void *) seek_cb, (void *) pipeline); + gtk_adjustment_set_value (adjustment, value); + g_signal_handlers_unblock_by_func (hscale, (void *) start_seek, + (void *) pipeline); + g_signal_handlers_unblock_by_func (hscale, (void *) stop_seek, + (void *) pipeline); + g_signal_handlers_unblock_by_func (hscale, (void *) seek_cb, + (void *) pipeline); + gtk_widget_queue_draw (hscale); +} + +static gboolean +update_fill (gpointer data) +{ + if (elem_seek) { + if (seekable_elements) { + GstElement *element = GST_ELEMENT (seekable_elements->data); + GstQuery *query; + + query = gst_query_new_buffering (GST_FORMAT_PERCENT); + if (gst_element_query (element, query)) { + gint64 start, stop, buffering_total; + GstFormat format; + gdouble fill; + gboolean busy; + gint percent; + GstBufferingMode mode; + gint avg_in, avg_out; + gint64 buffering_left; + + gst_query_parse_buffering_percent (query, &busy, &percent); + gst_query_parse_buffering_range (query, &format, &start, &stop, + &buffering_total); + gst_query_parse_buffering_stats (query, &mode, &avg_in, &avg_out, + &buffering_left); + + /* note that we could start the playback when buffering_left < remaining + * playback time */ + GST_DEBUG ("buffering total %" G_GINT64_FORMAT " ms, left %" + G_GINT64_FORMAT " ms", buffering_total, buffering_left); + GST_DEBUG ("start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, + start, stop); + + if (stop != -1) + fill = 100.0 * stop / GST_FORMAT_PERCENT_MAX; + else + fill = 100.0; + + gtk_range_set_fill_level (GTK_RANGE (hscale), fill); + } + gst_query_unref (query); + } + } + return TRUE; +} + +static gboolean +update_scale (gpointer data) +{ + GstFormat format = GST_FORMAT_TIME; + + //position = 0; + //duration = 0; + + if (elem_seek) { + if (seekable_elements) { + GstElement *element = GST_ELEMENT (seekable_elements->data); + + gst_element_query_position (element, &format, &position); + gst_element_query_duration (element, &format, &duration); + } + } else { + if (seekable_pads) { + GstPad *pad = GST_PAD (seekable_pads->data); + + gst_pad_query_position (pad, &format, &position); + gst_pad_query_duration (pad, &format, &duration); + } + } + + if (stats) { + if (elem_seek) { + query_positions_elems (); + } else { + query_positions_pads (); + } + query_rates (); + } + + if (position >= duration) + duration = position; + + if (duration > 0) { + set_scale (position * 100.0 / duration); + } + + /* FIXME: see make_playerbin2_pipeline() and volume_notify_cb() */ + if (pipeline_type == 16) { + g_object_notify (G_OBJECT (pipeline), "volume"); + } + + return TRUE; +} + +static void do_seek (GtkWidget * widget); +static void connect_bus_signals (GstElement * pipeline); +static void set_update_scale (gboolean active); +static void set_update_fill (gboolean active); + +static gboolean +end_scrub (GtkWidget * widget) +{ + GST_DEBUG ("end scrub, PAUSE"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + seek_timeout_id = 0; + + return FALSE; +} + +static gboolean +send_event (GstEvent * event) +{ + gboolean res = FALSE; + + if (!elem_seek) { + GList *walk = seekable_pads; + + while (walk) { + GstPad *seekable = GST_PAD (walk->data); + + GST_DEBUG ("send event on pad %s:%s", GST_DEBUG_PAD_NAME (seekable)); + + gst_event_ref (event); + res = gst_pad_send_event (seekable, event); + + walk = g_list_next (walk); + } + } else { + GList *walk = seekable_elements; + + while (walk) { + GstElement *seekable = GST_ELEMENT (walk->data); + + GST_DEBUG ("send event on element %s", GST_ELEMENT_NAME (seekable)); + + gst_event_ref (event); + res = gst_element_send_event (seekable, event); + + walk = g_list_next (walk); + } + } + gst_event_unref (event); + return res; +} + +static void +do_seek (GtkWidget * widget) +{ + gint64 real; + gboolean res = FALSE; + GstEvent *s_event; + GstSeekFlags flags; + + real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100; + + flags = 0; + if (flush_seek) + flags |= GST_SEEK_FLAG_FLUSH; + if (accurate_seek) + flags |= GST_SEEK_FLAG_ACCURATE; + if (keyframe_seek) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + if (rate >= 0) { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, real, GST_SEEK_TYPE_SET, + GST_CLOCK_TIME_NONE); + GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (real), GST_TIME_ARGS (duration)); + } else { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, real); + GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (0), GST_TIME_ARGS (real)); + } + + res = send_event (s_event); + + if (res) { + if (flush_seek) { + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT); + } else { + set_update_scale (TRUE); + } + } else { + g_print ("seek failed\n"); + set_update_scale (TRUE); + } +} + +static void +seek_cb (GtkWidget * widget) +{ + /* If the timer hasn't expired yet, then the pipeline is running */ + if (play_scrub && seek_timeout_id != 0) { + GST_DEBUG ("do scrub seek, PAUSED"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + + GST_DEBUG ("do seek"); + do_seek (widget); + + if (play_scrub) { + GST_DEBUG ("do scrub seek, PLAYING"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + if (seek_timeout_id == 0) { + seek_timeout_id = + g_timeout_add (SCRUB_TIME, (GSourceFunc) end_scrub, widget); + } + } +} + +static void +set_update_fill (gboolean active) +{ + GST_DEBUG ("fill scale is %d", active); + + if (active) { + if (fill_id == 0) { + fill_id = + g_timeout_add (FILL_INTERVAL, (GSourceFunc) update_fill, pipeline); + } + } else { + if (fill_id) { + g_source_remove (fill_id); + fill_id = 0; + } + } +} + +static void +set_update_scale (gboolean active) +{ + + GST_DEBUG ("update scale is %d", active); + + if (active) { + if (update_id == 0) { + update_id = + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, pipeline); + } + } else { + if (update_id) { + g_source_remove (update_id); + update_id = 0; + } + } +} + +static gboolean +start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + set_update_scale (FALSE); + + if (state == GST_STATE_PLAYING && flush_seek && scrub) { + GST_DEBUG ("start scrub seek, PAUSE"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + + if (changed_id == 0 && flush_seek && scrub) { + changed_id = + g_signal_connect (hscale, "value_changed", G_CALLBACK (seek_cb), + pipeline); + } + + return FALSE; +} + +static gboolean +stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + if (changed_id) { + g_signal_handler_disconnect (hscale, changed_id); + changed_id = 0; + } + + if (!flush_seek || !scrub) { + GST_DEBUG ("do final seek"); + do_seek (widget); + } + + if (seek_timeout_id != 0) { + g_source_remove (seek_timeout_id); + seek_timeout_id = 0; + /* Still scrubbing, so the pipeline is playing, see if we need PAUSED + * instead. */ + if (state == GST_STATE_PAUSED) { + GST_DEBUG ("stop scrub seek, PAUSED"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + } else { + if (state == GST_STATE_PLAYING) { + GST_DEBUG ("stop scrub seek, PLAYING"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } + } + + return FALSE; +} + +static void +play_cb (GtkButton * button, gpointer data) +{ + GstStateChangeReturn ret; + + if (state != GST_STATE_PLAYING) { + g_print ("PLAY pipeline\n"); + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + goto failed; + case GST_STATE_CHANGE_NO_PREROLL: + is_live = TRUE; + break; + default: + break; + } + state = GST_STATE_PLAYING; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Playing"); + } + + return; + +failed: + { + g_print ("PLAY failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Play failed"); + } +} + +static void +pause_cb (GtkButton * button, gpointer data) +{ + g_static_mutex_lock (&state_mutex); + if (state != GST_STATE_PAUSED) { + GstStateChangeReturn ret; + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + g_print ("PAUSE pipeline\n"); + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + goto failed; + case GST_STATE_CHANGE_NO_PREROLL: + is_live = TRUE; + break; + default: + break; + } + + state = GST_STATE_PAUSED; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Paused"); + } + g_static_mutex_unlock (&state_mutex); + + return; + +failed: + { + g_static_mutex_unlock (&state_mutex); + g_print ("PAUSE failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Pause failed"); + } +} + +static void +stop_cb (GtkButton * button, gpointer data) +{ + if (state != STOP_STATE) { + GstStateChangeReturn ret; + + g_print ("READY pipeline\n"); + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + + g_static_mutex_lock (&state_mutex); + ret = gst_element_set_state (pipeline, STOP_STATE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto failed; + + state = STOP_STATE; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped"); + + is_live = FALSE; + buffering = FALSE; + set_update_scale (FALSE); + set_scale (0.0); + set_update_fill (FALSE); + + if (pipeline_type == 16) + clear_streams (pipeline); + g_static_mutex_unlock (&state_mutex); + +#if 0 + /* if one uses parse_launch, play, stop and play again it fails as all the + * pads after the demuxer can't be reconnected + */ + if (!strcmp (pipelines[pipeline_type].name, "parse-launch")) { + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + g_list_free (seekable_elements); + seekable_elements = NULL; + g_list_free (seekable_pads); + seekable_pads = NULL; + g_list_free (rate_pads); + rate_pads = NULL; + + pipeline = pipelines[pipeline_type].func (pipeline_spec); + g_assert (pipeline); + gst_element_set_state (pipeline, STOP_STATE); + connect_bus_signals (pipeline); + } +#endif + } + return; + +failed: + { + g_static_mutex_unlock (&state_mutex); + g_print ("STOP failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stop failed"); + } +} + +static void +accurate_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + accurate_seek = gtk_toggle_button_get_active (button); +} + +static void +key_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + keyframe_seek = gtk_toggle_button_get_active (button); +} + +static void +loop_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + loop_seek = gtk_toggle_button_get_active (button); + if (state == GST_STATE_PLAYING) { + do_seek (hscale); + } +} + +static void +flush_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + flush_seek = gtk_toggle_button_get_active (button); +} + +static void +scrub_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + scrub = gtk_toggle_button_get_active (button); +} + +static void +play_scrub_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + play_scrub = gtk_toggle_button_get_active (button); +} + +static void +skip_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + skip_seek = gtk_toggle_button_get_active (button); + if (state == GST_STATE_PLAYING) { + do_seek (hscale); + } +} + +static void +rate_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline) +{ + gboolean res = FALSE; + GstEvent *s_event; + GstSeekFlags flags; + + rate = gtk_spin_button_get_value (button); + + GST_DEBUG ("rate changed to %lf", rate); + + flags = 0; + if (flush_seek) + flags |= GST_SEEK_FLAG_FLUSH; + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (accurate_seek) + flags |= GST_SEEK_FLAG_ACCURATE; + if (keyframe_seek) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + if (rate >= 0.0) { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, position, + GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); + } else { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, position); + } + + res = send_event (s_event); + + if (res) { + if (flush_seek) { + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT); + } + } else + g_print ("seek failed\n"); +} + +static void +update_flag (GstPipeline * pipeline, gint num, gboolean state) +{ + gint flags; + + g_object_get (pipeline, "flags", &flags, NULL); + if (state) + flags |= (1 << num); + else + flags &= ~(1 << num); + g_object_set (pipeline, "flags", flags, NULL); +} + +static void +vis_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 3, state); + gtk_widget_set_sensitive (vis_combo, state); +} + +static void +audio_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 1, state); + gtk_widget_set_sensitive (audio_combo, state); +} + +static void +video_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 0, state); + gtk_widget_set_sensitive (video_combo, state); +} + +static void +text_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 2, state); + gtk_widget_set_sensitive (text_combo, state); +} + +static void +mute_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean mute; + + mute = gtk_toggle_button_get_active (button); + g_object_set (pipeline, "mute", mute, NULL); +} + +static void +download_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 7, state); +} + +static void +buffer_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 8, state); +} + +static void +clear_streams (GstElement * pipeline) +{ + gint i; + + /* remove previous info */ + for (i = 0; i < n_video; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (video_combo), 0); + for (i = 0; i < n_audio; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (audio_combo), 0); + for (i = 0; i < n_text; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (text_combo), 0); + + n_audio = n_video = n_text = 0; + gtk_widget_set_sensitive (video_combo, FALSE); + gtk_widget_set_sensitive (audio_combo, FALSE); + gtk_widget_set_sensitive (text_combo, FALSE); + + need_streams = TRUE; +} + +static void +update_streams (GstPipeline * pipeline) +{ + gint i; + + if (pipeline_type == 16 && need_streams) { + GstTagList *tags; + gchar *name, *str; + gint active_idx; + gboolean state; + + /* remove previous info */ + clear_streams (GST_ELEMENT_CAST (pipeline)); + + /* here we get and update the different streams detected by playbin2 */ + g_object_get (pipeline, "n-video", &n_video, NULL); + g_object_get (pipeline, "n-audio", &n_audio, NULL); + g_object_get (pipeline, "n-text", &n_text, NULL); + + g_print ("video %d, audio %d, text %d\n", n_video, n_audio, n_text); + + active_idx = 0; + for (i = 0; i < n_video; i++) { + g_signal_emit_by_name (pipeline, "get-video-tags", i, &tags); + if (tags) { + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("video %d: %s\n", i, str); + g_free (str); + } + /* find good name for the label */ + name = g_strdup_printf ("video %d", i + 1); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (video_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (video_checkbox)); + gtk_widget_set_sensitive (video_combo, state && n_video > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (video_combo), active_idx); + + active_idx = 0; + for (i = 0; i < n_audio; i++) { + g_signal_emit_by_name (pipeline, "get-audio-tags", i, &tags); + if (tags) { + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("audio %d: %s\n", i, str); + g_free (str); + } + /* find good name for the label */ + name = g_strdup_printf ("audio %d", i + 1); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (audio_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (audio_checkbox)); + gtk_widget_set_sensitive (audio_combo, state && n_audio > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (audio_combo), active_idx); + + active_idx = 0; + for (i = 0; i < n_text; i++) { + g_signal_emit_by_name (pipeline, "get-text-tags", i, &tags); + + name = NULL; + if (tags) { + const GValue *value; + + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("text %d: %s\n", i, str); + g_free (str); + + /* get the language code if we can */ + value = gst_tag_list_get_value_index (tags, GST_TAG_LANGUAGE_CODE, 0); + if (value && G_VALUE_HOLDS_STRING (value)) { + name = g_strdup_printf ("text %s", g_value_get_string (value)); + } + } + /* find good name for the label if we didn't use a tag */ + if (name == NULL) + name = g_strdup_printf ("text %d", i + 1); + + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (text_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (text_checkbox)); + gtk_widget_set_sensitive (text_combo, state && n_text > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (text_combo), active_idx); + + need_streams = FALSE; + } +} + +static void +video_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current video track %d\n", active); + g_object_set (pipeline, "current-video", active, NULL); +} + +static void +audio_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current audio track %d\n", active); + g_object_set (pipeline, "current-audio", active, NULL); +} + +static void +text_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current text track %d\n", active); + g_object_set (pipeline, "current-text", active, NULL); +} + +static gboolean +filter_features (GstPluginFeature * feature, gpointer data) +{ + GstElementFactory *f; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + f = GST_ELEMENT_FACTORY (feature); + if (!g_strrstr (gst_element_factory_get_klass (f), "Visualization")) + return FALSE; + + return TRUE; +} + +static void +init_visualization_features (void) +{ + GList *list, *walk; + + vis_entries = g_array_new (FALSE, FALSE, sizeof (VisEntry)); + + list = gst_registry_feature_filter (gst_registry_get_default (), + filter_features, FALSE, NULL); + + for (walk = list; walk; walk = g_list_next (walk)) { + VisEntry entry; + const gchar *name; + + entry.factory = GST_ELEMENT_FACTORY (walk->data); + name = gst_element_factory_get_longname (entry.factory); + + g_array_append_val (vis_entries, entry); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (vis_combo), name); + } + gtk_combo_box_set_active (GTK_COMBO_BOX (vis_combo), 0); +} + +static void +vis_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + guint index; + VisEntry *entry; + GstElement *element; + + /* get the selected index and get the factory for this index */ + index = gtk_combo_box_get_active (GTK_COMBO_BOX (vis_combo)); + if (vis_entries->len > 0) { + entry = &g_array_index (vis_entries, VisEntry, index); + + /* create an instance of the element from the factory */ + element = gst_element_factory_create (entry->factory, NULL); + if (!element) + return; + + /* set vis plugin for playbin2 */ + g_object_set (pipeline, "vis-plugin", element, NULL); + } +} + +static void +volume_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline) +{ + gdouble volume; + + volume = gtk_spin_button_get_value (button); + + g_object_set (pipeline, "volume", volume, NULL); +} + +static void +volume_notify_cb (GstElement * pipeline, GParamSpec * arg, gpointer user_dat) +{ + gdouble cur_volume, new_volume; + + g_object_get (pipeline, "volume", &new_volume, NULL); + cur_volume = gtk_spin_button_get_value (GTK_SPIN_BUTTON (volume_spinbutton)); + if (fabs (cur_volume - new_volume) > 0.001) { + g_signal_handlers_block_by_func (volume_spinbutton, + volume_spinbutton_changed_cb, pipeline); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (volume_spinbutton), new_volume); + g_signal_handlers_unblock_by_func (volume_spinbutton, + volume_spinbutton_changed_cb, pipeline); + } +} + +static void +shot_cb (GtkButton * button, gpointer data) +{ + GstBuffer *buffer; + GstCaps *caps; + + /* convert to our desired format (RGB24) */ + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24, + /* Note: we don't ask for a specific width/height here, so that + * videoscale can adjust dimensions from a non-1/1 pixel aspect + * ratio to a 1/1 pixel-aspect-ratio */ + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "red_mask", G_TYPE_INT, 0xff0000, + "green_mask", G_TYPE_INT, 0x00ff00, + "blue_mask", G_TYPE_INT, 0x0000ff, NULL); + + /* convert the latest frame to the requested format */ + g_signal_emit_by_name (pipeline, "convert-frame", caps, &buffer); + gst_caps_unref (caps); + + if (buffer) { + GstCaps *caps; + GstStructure *s; + gboolean res; + gint width, height; + GdkPixbuf *pixbuf; + GError *error = NULL; + + /* get the snapshot buffer format now. We set the caps on the appsink so + * that it can only be an rgb buffer. The only thing we have not specified + * on the caps is the height, which is dependant on the pixel-aspect-ratio + * of the source material */ + caps = GST_BUFFER_CAPS (buffer); + if (!caps) { + g_warning ("could not get snapshot format\n"); + goto done; + } + s = gst_caps_get_structure (caps, 0); + + /* we need to get the final caps on the buffer to get the size */ + res = gst_structure_get_int (s, "width", &width); + res |= gst_structure_get_int (s, "height", &height); + if (!res) { + g_warning ("could not get snapshot dimension\n"); + goto done; + } + + /* create pixmap from buffer and save, gstreamer video buffers have a stride + * that is rounded up to the nearest multiple of 4 */ + pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buffer), + GDK_COLORSPACE_RGB, FALSE, 8, width, height, + GST_ROUND_UP_4 (width * 3), NULL, NULL); + + /* save the pixbuf */ + gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL); + + done: + gst_buffer_unref (buffer); + } +} + +/* called when the Step button is pressed */ +static void +step_cb (GtkButton * button, gpointer data) +{ + GstEvent *event; + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush, res; + gint active; + + active = gtk_combo_box_get_active (GTK_COMBO_BOX (format_combo)); + amount = + gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON + (step_amount_spinbutton)); + rate = gtk_spin_button_get_value (GTK_SPIN_BUTTON (step_rate_spinbutton)); + flush = TRUE; + + switch (active) { + case 0: + format = GST_FORMAT_BUFFERS; + break; + case 1: + format = GST_FORMAT_TIME; + amount *= GST_MSECOND; + break; + default: + format = GST_FORMAT_UNDEFINED; + break; + } + + event = gst_event_new_step (format, amount, rate, flush, FALSE); + + res = send_event (event); + + if (!res) { + g_print ("Sending step event failed\n"); + } +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static gboolean shuttling = FALSE; +static gdouble shuttle_rate = 0.0; +static gdouble play_rate = 1.0; + +static void +do_shuttle (GstElement * element) +{ + guint64 duration; + + if (shuttling) + duration = 40 * GST_MSECOND; + else + duration = -1; + + gst_element_send_event (element, + gst_event_new_step (GST_FORMAT_TIME, duration, shuttle_rate, FALSE, + FALSE)); +} + +static void +msg_sync_step_done (GstBus * bus, GstMessage * message, GstElement * element) +{ + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush; + gboolean intermediate; + guint64 duration; + gboolean eos; + + gst_message_parse_step_done (message, &format, &amount, &rate, &flush, + &intermediate, &duration, &eos); + + if (eos) { + g_print ("stepped till EOS\n"); + return; + } + + if (g_static_mutex_trylock (&state_mutex)) { + if (shuttling) + do_shuttle (element); + g_static_mutex_unlock (&state_mutex); + } else { + /* ignore step messages that come while we are doing a state change */ + g_print ("state change is busy\n"); + } +} + +static void +shuttle_toggled (GtkToggleButton * button, GstElement * element) +{ + gboolean active; + + active = gtk_toggle_button_get_active (button); + + if (active != shuttling) { + shuttling = active; + g_print ("shuttling %s\n", shuttling ? "active" : "inactive"); + if (active) { + shuttle_rate = 0.0; + play_rate = 1.0; + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } + } +} + +static void +shuttle_rate_switch (GstElement * element) +{ + GstSeekFlags flags; + GstEvent *s_event; + gboolean res; + + if (state == GST_STATE_PLAYING) { + /* pause when we need to */ + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } + + if (play_rate == 1.0) + play_rate = -1.0; + else + play_rate = 1.0; + + g_print ("rate changed to %lf %" GST_TIME_FORMAT "\n", play_rate, + GST_TIME_ARGS (position)); + + flags = GST_SEEK_FLAG_FLUSH; + flags |= GST_SEEK_FLAG_ACCURATE; + + if (play_rate >= 0.0) { + s_event = gst_event_new_seek (play_rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, position, + GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); + } else { + s_event = gst_event_new_seek (play_rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, position); + } + res = send_event (s_event); + if (res) { + gst_element_get_state (element, NULL, NULL, SEEK_TIMEOUT); + } else { + g_print ("seek failed\n"); + } +} + +static void +shuttle_value_changed (GtkRange * range, GstElement * element) +{ + gdouble rate; + + rate = gtk_adjustment_get_value (shuttle_adjustment); + + if (rate == 0.0) { + g_print ("rate 0.0, pause\n"); + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } else { + g_print ("rate changed %0.3g\n", rate); + + if ((rate < 0.0 && play_rate > 0.0) || (rate > 0.0 && play_rate < 0.0)) { + shuttle_rate_switch (element); + } + + shuttle_rate = ABS (rate); + if (state != GST_STATE_PLAYING) { + do_shuttle (element); + play_cb (NULL, NULL); + } + } +} + +static void +msg_async_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + GST_DEBUG ("async done"); + /* when we get ASYNC_DONE we can query position, duration and other + * properties */ + update_scale (pipeline); + + /* update the available streams */ + update_streams (pipeline); +} + +static void +msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + + /* We only care about state changed on the pipeline */ + if (s && GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) { + GstState old, new, pending; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + /* When state of the pipeline changes to paused or playing we start updating scale */ + if (new == GST_STATE_PLAYING) { + set_update_scale (TRUE); + } else { + set_update_scale (FALSE); + } + } +} + +static void +msg_segment_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + GstEvent *s_event; + GstSeekFlags flags; + gboolean res; + GstFormat format; + + GST_DEBUG ("position is %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + gst_message_parse_segment_done (message, &format, &position); + GST_DEBUG ("end of segment at %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + + flags = 0; + /* in the segment-done callback we never flush as this would not make sense + * for seamless playback. */ + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, duration); + + GST_DEBUG ("restart loop with rate %lf to 0 / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (duration)); + + res = send_event (s_event); + if (!res) + g_print ("segment seek failed\n"); +} + +/* in stream buffering mode we PAUSE the pipeline until we receive a 100% + * message */ +static void +do_stream_buffering (gint percent) +{ + gchar *bufstr; + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + bufstr = g_strdup_printf ("Buffering...%d", percent); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, bufstr); + g_free (bufstr); + + if (percent == 100) { + /* a 100% message means buffering is done */ + buffering = FALSE; + /* if the desired state is playing, go back */ + if (state == GST_STATE_PLAYING) { + /* no state management needed for live pipelines */ + if (!is_live) { + fprintf (stderr, "Done buffering, setting pipeline to PLAYING ...\n"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Playing"); + } + } else { + /* buffering busy */ + if (buffering == FALSE && state == GST_STATE_PLAYING) { + /* we were not buffering but PLAYING, PAUSE the pipeline. */ + if (!is_live) { + fprintf (stderr, "Buffering, setting pipeline to PAUSED ...\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + } + buffering = TRUE; + } +} + +static void +do_download_buffering (gint percent) +{ + if (!buffering && percent < 100) { + gchar *bufstr; + + buffering = TRUE; + + bufstr = g_strdup_printf ("Downloading..."); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, bufstr); + g_free (bufstr); + + /* once we get a buffering message, we'll do the fill update */ + set_update_fill (TRUE); + + if (state == GST_STATE_PLAYING && !is_live) { + fprintf (stderr, "Downloading, setting pipeline to PAUSED ...\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + /* user has to manually start the playback */ + state = GST_STATE_PAUSED; + } + } +} + +static void +msg_buffering (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + gint percent; + + gst_message_parse_buffering (message, &percent); + + /* get more stats */ + gst_message_parse_buffering_stats (message, &mode, NULL, NULL, + &buffering_left); + + switch (mode) { + case GST_BUFFERING_DOWNLOAD: + do_download_buffering (percent); + break; + case GST_BUFFERING_LIVE: + case GST_BUFFERING_TIMESHIFT: + case GST_BUFFERING_STREAM: + do_stream_buffering (percent); + break; + } +} + +static void +msg_clock_lost (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + g_print ("clock lost! PAUSE and PLAY to select a new clock\n"); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_PLAYING); +} + +#ifdef HAVE_X + +static gulong embed_xid = 0; + +/* We set the xid here in response to the prepare-xwindow-id message via a + * bus sync handler because we don't know the actual videosink used from the + * start (as we don't know the pipeline, or bin elements such as autovideosink + * or gconfvideosink may be used which create the actual videosink only once + * the pipeline is started) */ +static GstBusSyncReply +bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + if ((GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name (message->structure, "prepare-xwindow-id")) { + GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message)); + + g_print ("got prepare-xwindow-id, setting XID %lu\n", embed_xid); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "force-aspect-ratio")) { + g_object_set (element, "force-aspect-ratio", TRUE, NULL); + } + + /* Should have been initialised from main thread before (can't use + * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will + * be called from a streaming thread and GDK_WINDOW_XID maps to more than + * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that + * shouldn't be done from a non-GUI thread without explicit locking). */ + g_assert (embed_xid != 0); + + gst_x_overlay_set_window_handle (GST_X_OVERLAY (element), embed_xid); + } + return GST_BUS_PASS; +} +#endif + +static gboolean +handle_expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data) +{ + if (state < GST_STATE_PAUSED) { + GtkAllocation allocation; + GdkWindow *window = gtk_widget_get_window (widget); + cairo_t *cr; + + gtk_widget_get_allocation (widget, &allocation); + cr = gdk_cairo_create (window); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); + cairo_fill (cr); + cairo_destroy (cr); + } + return FALSE; +} + +static void +realize_cb (GtkWidget * widget, gpointer data) +{ +#if GTK_CHECK_VERSION(2,18,0) + { + GdkWindow *window = gtk_widget_get_window (widget); + + /* This is here just for pedagogical purposes, GDK_WINDOW_XID will call it + * as well */ + if (!gdk_window_ensure_native (window)) + g_error ("Couldn't create native window needed for GstXOverlay!"); + } +#endif + +#ifdef HAVE_X + { + GdkWindow *window = gtk_widget_get_window (video_window); + + embed_xid = GDK_WINDOW_XID (window); + g_print ("Window realize: video window XID = %lu\n", embed_xid); + } +#endif +} + +static void +msg_eos (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + message_received (bus, message, data); + + /* Set new uri for playerbins and continue playback */ + if (l && (pipeline_type == 14 || pipeline_type == 16)) { + stop_cb (NULL, NULL); + l = g_list_next (l); + if (l) { + playerbin_set_uri (GST_ELEMENT (data), l->data); + play_cb (NULL, NULL); + } + } +} + +static void +msg_step_done (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + if (!shuttling) + message_received (bus, message, data); +} + +static void +connect_bus_signals (GstElement * pipeline) +{ + GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + +#ifdef HAVE_X + /* handle prepare-xwindow-id element message synchronously */ + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, + pipeline); +#endif + + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + gst_bus_enable_sync_message_emission (bus); + + g_signal_connect (bus, "message::state-changed", + (GCallback) msg_state_changed, pipeline); + g_signal_connect (bus, "message::segment-done", (GCallback) msg_segment_done, + pipeline); + g_signal_connect (bus, "message::async-done", (GCallback) msg_async_done, + pipeline); + + g_signal_connect (bus, "message::new-clock", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::clock-lost", (GCallback) msg_clock_lost, + pipeline); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) msg_eos, pipeline); + g_signal_connect (bus, "message::tag", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::element", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::segment-done", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::buffering", (GCallback) msg_buffering, + pipeline); +// g_signal_connect (bus, "message::step-done", (GCallback) msg_step_done, +// pipeline); + g_signal_connect (bus, "message::step-start", (GCallback) msg_step_done, + pipeline); + g_signal_connect (bus, "sync-message::step-done", + (GCallback) msg_sync_step_done, pipeline); + + gst_object_unref (bus); +} + +/* Return GList of paths described in location string */ +static GList * +handle_wildcards (const gchar * location) +{ + GList *res = NULL; + gchar *path = g_path_get_dirname (location); + gchar *pattern = g_path_get_basename (location); + GPatternSpec *pspec = g_pattern_spec_new (pattern); + GDir *dir = g_dir_open (path, 0, NULL); + const gchar *name; + + g_print ("matching %s from %s\n", pattern, path); + + if (!dir) { + g_print ("opening directory %s failed\n", path); + goto out; + } + + while ((name = g_dir_read_name (dir)) != NULL) { + if (g_pattern_match_string (pspec, name)) { + res = g_list_append (res, g_strjoin ("/", path, name, NULL)); + g_print (" found clip %s\n", name); + } + } + + g_dir_close (dir); +out: + g_pattern_spec_free (pspec); + g_free (pattern); + g_free (path); + + return res; +} + +static void +delete_event_cb (void) +{ + stop_cb (NULL, NULL); + gtk_main_quit (); +} + +static void +print_usage (int argc, char **argv) +{ + gint i; + + g_print ("usage: %s \n", argv[0]); + g_print (" possible types:\n"); + + for (i = 0; i < NUM_TYPES; i++) { + g_print (" %d = %s\n", i, pipelines[i].name); + } +} + +static gboolean +read_joystick (GIOChannel * source, GIOCondition condition, gpointer user_data) +{ + gchar buf[sizeof (struct js_event)]; + struct js_event *js = (struct js_event *) buf; + GError *err = NULL; + gsize bytes_read = 0; + GIOStatus result; + + result = + g_io_channel_read_chars (source, buf, sizeof (struct js_event), + &bytes_read, &err); + if (err) { + g_print ("error reading from joystick: %s", err->message); + g_error_free (err); + return FALSE; + } else if (bytes_read != sizeof (struct js_event)) { + g_print ("error reading joystick, read %u bytes of %u\n", + (guint) bytes_read, (guint) sizeof (struct js_event)); + return TRUE; + } else if (result != G_IO_STATUS_NORMAL) { + g_print ("reading from joystick returned status %d", result); + } + + switch (js->type & ~JS_EVENT_INIT) { + case JS_EVENT_AXIS: + if (js->number == 0) { + gdouble new_rate = (gdouble) (js->value) / 3000; + g_print ("Got: %d (rate %g)\n", js->value, new_rate); + if (shuttling) + gtk_adjustment_set_value (shuttle_adjustment, new_rate); + } + break; + } + + return TRUE; +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *hbox, *vbox, *panel, *expander, *pb2vbox, *boxes, + *flagtable, *boxes2, *step; + GtkWidget *play_button, *pause_button, *stop_button, *shot_button; + GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox; + GtkWidget *scrub_checkbox, *play_scrub_checkbox; + GtkWidget *rate_label, *volume_label; + GOptionEntry options[] = { + {"stats", 's', 0, G_OPTION_ARG_NONE, &stats, + "Show pad stats", NULL}, + {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek, + "Seek on elements instead of pads", NULL}, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Verbose properties", NULL}, + {"joystick", 'j', 0, G_OPTION_ARG_STRING, &js_device, + "Joystick device to use", NULL}, + {NULL} + }; + GOptionContext *ctx; + GError *err = NULL; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new ("- test seeking in gsteamer"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + g_option_context_add_group (ctx, gtk_get_option_group (TRUE)); + + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + GST_DEBUG_CATEGORY_INIT (seek_debug, "seek", 0, "seek example"); + + if (argc != 3) { + print_usage (argc, argv); + exit (-1); + } + + pipeline_type = atoi (argv[1]); + + if (pipeline_type < 0 || pipeline_type >= NUM_TYPES) { + print_usage (argc, argv); + exit (-1); + } + + pipeline_spec = argv[2]; + + if (js_device == NULL) + js_device = g_strdup ("/dev/input/js0"); + + js_fd = g_open (js_device, O_RDONLY, 0); + if (js_fd < 0) { + g_print ("Failed to open joystick device %s\n", js_device); + exit (-1); + } + + if (g_strrstr (pipeline_spec, "*") != NULL || + g_strrstr (pipeline_spec, "?") != NULL) { + paths = handle_wildcards (pipeline_spec); + } else { + paths = g_list_prepend (paths, g_strdup (pipeline_spec)); + } + + if (!paths) { + g_print ("opening %s failed\n", pipeline_spec); + exit (-1); + } + + l = paths; + + pipeline = pipelines[pipeline_type].func ((gchar *) l->data); + g_assert (pipeline); + + /* initialize gui elements ... */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + video_window = gtk_drawing_area_new (); + g_signal_connect (video_window, "expose-event", + G_CALLBACK (handle_expose_cb), NULL); + g_signal_connect (video_window, "realize", G_CALLBACK (realize_cb), NULL); + gtk_widget_set_double_buffered (video_window, FALSE); + + statusbar = gtk_statusbar_new (); + status_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "seek"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped"); + hbox = gtk_hbox_new (FALSE, 0); + vbox = gtk_vbox_new (FALSE, 0); + flagtable = gtk_table_new (4, 2, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); + + /* media controls */ + play_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY); + pause_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PAUSE); + stop_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_STOP); + + /* seek flags */ + accurate_checkbox = gtk_check_button_new_with_label ("Accurate Seek"); + key_checkbox = gtk_check_button_new_with_label ("Key-unit Seek"); + loop_checkbox = gtk_check_button_new_with_label ("Loop"); + flush_checkbox = gtk_check_button_new_with_label ("Flush"); + scrub_checkbox = gtk_check_button_new_with_label ("Scrub"); + play_scrub_checkbox = gtk_check_button_new_with_label ("Play Scrub"); + skip_checkbox = gtk_check_button_new_with_label ("Play Skip"); + rate_spinbutton = gtk_spin_button_new_with_range (-100, 100, 0.1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (rate_spinbutton), 3); + rate_label = gtk_label_new ("Rate"); + + gtk_widget_set_tooltip_text (accurate_checkbox, + "accurate position is requested, this might be considerably slower for some formats"); + gtk_widget_set_tooltip_text (key_checkbox, + "seek to the nearest keyframe. This might be faster but less accurate"); + gtk_widget_set_tooltip_text (loop_checkbox, "loop playback"); + gtk_widget_set_tooltip_text (flush_checkbox, "flush pipeline after seeking"); + gtk_widget_set_tooltip_text (rate_spinbutton, "define the playback rate, " + "negative value trigger reverse playback"); + gtk_widget_set_tooltip_text (scrub_checkbox, "show images while seeking"); + gtk_widget_set_tooltip_text (play_scrub_checkbox, "play video while seeking"); + gtk_widget_set_tooltip_text (skip_checkbox, + "Skip frames while playing at high frame rates"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flush_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scrub_checkbox), TRUE); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (rate_spinbutton), rate); + + /* step expander */ + { + GtkWidget *hbox; + + step = gtk_expander_new ("step options"); + hbox = gtk_hbox_new (FALSE, 0); + + format_combo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (format_combo), + "frames"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (format_combo), + "time (ms)"); + gtk_combo_box_set_active (GTK_COMBO_BOX (format_combo), 0); + gtk_box_pack_start (GTK_BOX (hbox), format_combo, FALSE, FALSE, 2); + + step_amount_spinbutton = gtk_spin_button_new_with_range (1, 1000, 1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_amount_spinbutton), 0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_amount_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (hbox), step_amount_spinbutton, FALSE, FALSE, + 2); + + step_rate_spinbutton = gtk_spin_button_new_with_range (0.0, 100, 0.1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_rate_spinbutton), 3); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_rate_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (hbox), step_rate_spinbutton, FALSE, FALSE, 2); + + step_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_FORWARD); + gtk_button_set_label (GTK_BUTTON (step_button), "Step"); + gtk_box_pack_start (GTK_BOX (hbox), step_button, FALSE, FALSE, 2); + + g_signal_connect (G_OBJECT (step_button), "clicked", G_CALLBACK (step_cb), + pipeline); + + /* shuttle scale */ + shuttle_checkbox = gtk_check_button_new_with_label ("Shuttle"); + gtk_box_pack_start (GTK_BOX (hbox), shuttle_checkbox, FALSE, FALSE, 2); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (shuttle_checkbox), FALSE); + g_signal_connect (shuttle_checkbox, "toggled", G_CALLBACK (shuttle_toggled), + pipeline); + + shuttle_adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, -3.00, 4.0, 0.1, 1.0, 1.0)); + shuttle_hscale = gtk_hscale_new (shuttle_adjustment); + gtk_scale_set_digits (GTK_SCALE (shuttle_hscale), 2); + gtk_scale_set_value_pos (GTK_SCALE (shuttle_hscale), GTK_POS_TOP); + g_signal_connect (shuttle_hscale, "value_changed", + G_CALLBACK (shuttle_value_changed), pipeline); + g_signal_connect (shuttle_hscale, "format_value", + G_CALLBACK (shuttle_format_value), pipeline); + + gtk_box_pack_start (GTK_BOX (hbox), shuttle_hscale, TRUE, TRUE, 2); + + gtk_container_add (GTK_CONTAINER (step), hbox); + } + + /* seek bar */ + adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0)); + hscale = gtk_hscale_new (adjustment); + gtk_scale_set_digits (GTK_SCALE (hscale), 2); + gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_RIGHT); + gtk_range_set_show_fill_level (GTK_RANGE (hscale), TRUE); + gtk_range_set_fill_level (GTK_RANGE (hscale), 100.0); + + g_signal_connect (hscale, "button_press_event", G_CALLBACK (start_seek), + pipeline); + g_signal_connect (hscale, "button_release_event", G_CALLBACK (stop_seek), + pipeline); + g_signal_connect (hscale, "format_value", G_CALLBACK (format_value), + pipeline); + + if (pipeline_type == 16) { + /* the playbin2 panel controls for the video/audio/subtitle tracks */ + panel = gtk_hbox_new (FALSE, 0); + video_combo = gtk_combo_box_text_new (); + audio_combo = gtk_combo_box_text_new (); + text_combo = gtk_combo_box_text_new (); + gtk_widget_set_sensitive (video_combo, FALSE); + gtk_widget_set_sensitive (audio_combo, FALSE); + gtk_widget_set_sensitive (text_combo, FALSE); + gtk_box_pack_start (GTK_BOX (panel), video_combo, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (panel), audio_combo, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (panel), text_combo, TRUE, TRUE, 2); + g_signal_connect (G_OBJECT (video_combo), "changed", + G_CALLBACK (video_combo_cb), pipeline); + g_signal_connect (G_OBJECT (audio_combo), "changed", + G_CALLBACK (audio_combo_cb), pipeline); + g_signal_connect (G_OBJECT (text_combo), "changed", + G_CALLBACK (text_combo_cb), pipeline); + /* playbin2 panel for flag checkboxes and volume/mute */ + boxes = gtk_hbox_new (FALSE, 0); + vis_checkbox = gtk_check_button_new_with_label ("Vis"); + video_checkbox = gtk_check_button_new_with_label ("Video"); + audio_checkbox = gtk_check_button_new_with_label ("Audio"); + text_checkbox = gtk_check_button_new_with_label ("Text"); + mute_checkbox = gtk_check_button_new_with_label ("Mute"); + download_checkbox = gtk_check_button_new_with_label ("Download"); + buffer_checkbox = gtk_check_button_new_with_label ("Buffer"); + volume_label = gtk_label_new ("Volume"); + volume_spinbutton = gtk_spin_button_new_with_range (0, 10.0, 0.1); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (volume_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (boxes), video_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), audio_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), text_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), vis_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), mute_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), download_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), buffer_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), volume_label, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), volume_spinbutton, TRUE, TRUE, 2); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vis_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (audio_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (video_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (download_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (buffer_checkbox), FALSE); + g_signal_connect (G_OBJECT (vis_checkbox), "toggled", + G_CALLBACK (vis_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (audio_checkbox), "toggled", + G_CALLBACK (audio_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (video_checkbox), "toggled", + G_CALLBACK (video_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (text_checkbox), "toggled", + G_CALLBACK (text_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (mute_checkbox), "toggled", + G_CALLBACK (mute_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (download_checkbox), "toggled", + G_CALLBACK (download_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (buffer_checkbox), "toggled", + G_CALLBACK (buffer_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (volume_spinbutton), "value_changed", + G_CALLBACK (volume_spinbutton_changed_cb), pipeline); + /* playbin2 panel for snapshot */ + boxes2 = gtk_hbox_new (FALSE, 0); + shot_button = gtk_button_new_from_stock (GTK_STOCK_SAVE); + gtk_widget_set_tooltip_text (shot_button, + "save a screenshot .png in the current directory"); + g_signal_connect (G_OBJECT (shot_button), "clicked", G_CALLBACK (shot_cb), + pipeline); + vis_combo = gtk_combo_box_text_new (); + g_signal_connect (G_OBJECT (vis_combo), "changed", + G_CALLBACK (vis_combo_cb), pipeline); + gtk_widget_set_sensitive (vis_combo, FALSE); + gtk_box_pack_start (GTK_BOX (boxes2), shot_button, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes2), vis_combo, TRUE, TRUE, 2); + + /* fill the vis combo box and the array of factories */ + init_visualization_features (); + } else { + panel = boxes = boxes2 = NULL; + } + + /* do the packing stuff ... */ + gtk_window_set_default_size (GTK_WINDOW (window), 250, 96); + /* FIXME: can we avoid this for audio only? */ + gtk_widget_set_size_request (GTK_WIDGET (video_window), -1, + DEFAULT_VIDEO_HEIGHT); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_box_pack_start (GTK_BOX (vbox), video_window, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), flagtable, FALSE, FALSE, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), accurate_checkbox, 0, 1, 0, + 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), flush_checkbox, 1, 2, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), loop_checkbox, 2, 3, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), key_checkbox, 0, 1, 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), scrub_checkbox, 1, 2, 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), play_scrub_checkbox, 2, 3, + 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), skip_checkbox, 3, 4, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_label, 4, 5, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 4, 5, 1, + 2); + if (panel && boxes && boxes2) { + expander = gtk_expander_new ("playbin2 options"); + pb2vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (pb2vbox), panel, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (pb2vbox), boxes, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (pb2vbox), boxes2, FALSE, FALSE, 2); + gtk_container_add (GTK_CONTAINER (expander), pb2vbox); + gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 2); + } + gtk_box_pack_start (GTK_BOX (vbox), step, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hscale, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2); + + /* connect things ... */ + g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), + pipeline); + g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), + pipeline); + g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), + pipeline); + g_signal_connect (G_OBJECT (accurate_checkbox), "toggled", + G_CALLBACK (accurate_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (key_checkbox), "toggled", + G_CALLBACK (key_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (loop_checkbox), "toggled", + G_CALLBACK (loop_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (flush_checkbox), "toggled", + G_CALLBACK (flush_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (scrub_checkbox), "toggled", + G_CALLBACK (scrub_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (play_scrub_checkbox), "toggled", + G_CALLBACK (play_scrub_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (skip_checkbox), "toggled", + G_CALLBACK (skip_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (rate_spinbutton), "value_changed", + G_CALLBACK (rate_spinbutton_changed_cb), pipeline); + + g_signal_connect (G_OBJECT (window), "delete-event", delete_event_cb, NULL); + + /* show the gui. */ + gtk_widget_show_all (window); + + /* realize window now so that the video window gets created and we can + * obtain its XID before the pipeline is started up and the videosink + * asks for the XID of the window to render onto */ + gtk_widget_realize (window); + + /* we should have the XID now */ + g_assert (embed_xid != 0); + + if (verbose) { + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + } + + { + GIOChannel *js_watch = g_io_channel_unix_new (js_fd); + g_io_channel_set_encoding (js_watch, NULL, NULL); + g_io_add_watch (js_watch, G_IO_IN, read_joystick, NULL); + } + + connect_bus_signals (pipeline); + gtk_main (); + + g_print ("NULL pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + + g_print ("free pipeline\n"); + gst_object_unref (pipeline); + + g_list_foreach (paths, (GFunc) g_free, NULL); + g_list_free (paths); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/scrubby.c b/gst-plugins-base-subtitles0.10/tests/examples/seek/scrubby.c new file mode 100644 index 0000000..c9a02f4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/scrubby.c @@ -0,0 +1,568 @@ +#include +#include +#include +#include +#include + +GST_DEBUG_CATEGORY_STATIC (scrubby_debug); +#define GST_CAT_DEFAULT (scrubby_debug) + +static GstElement *pipeline; +static gint64 position; +static gint64 duration; +static GtkAdjustment *adjustment; +static GtkWidget *hscale; +static GtkAdjustment *sadjustment; +static GtkWidget *shscale; +static gboolean verbose = FALSE; + +static guint bus_watch = 0; +static guint update_id = 0; +static guint changed_id = 0; +static guint schanged_id = 0; + +//#define SOURCE "filesrc" +#define SOURCE "gnomevfssrc" +#define ASINK "alsasink" +//#define ASINK "osssink" +#define VSINK "xvimagesink" +//#define VSINK "ximagesink" +//#define VSINK "aasink" +//#define VSINK "cacasink" + +#define RANGE_PREC 10000 +#define SEGMENT_LEN 100 +#define UPDATE_INTERVAL 500 + +static gdouble prev_range = -1.0; +static GstClockTime prev_time = GST_CLOCK_TIME_NONE; +static gdouble cur_range; +static GstClockTime cur_time; +static GstClockTimeDiff diff; +static gdouble cur_speed = 1.0; + +typedef struct +{ + const gchar *padname; + GstPad *target; + GstElement *bin; +} +dyn_link; + +static GstElement * +gst_element_factory_make_or_warn (const gchar * type, const gchar * name) +{ + GstElement *element = gst_element_factory_make (type, name); + + if (!element) { + g_warning ("Failed to create element %s of type %s", name, type); + } + + return element; +} + +static void +dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) +{ + dyn_link *connect = (dyn_link *) data; + + if (connect->padname == NULL || + !strcmp (gst_pad_get_name (newpad), connect->padname)) { + if (connect->bin) + gst_bin_add (GST_BIN (pipeline), connect->bin); + gst_pad_link (newpad, connect->target); + } +} + +static void +setup_dynamic_link (GstElement * element, const gchar * padname, + GstPad * target, GstElement * bin) +{ + dyn_link *connect; + + connect = g_new0 (dyn_link, 1); + connect->padname = g_strdup (padname); + connect->target = target; + connect->bin = bin; + + g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link), + connect); +} + +static GstElement * +make_wav_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("wavparse", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + + setup_dynamic_link (decoder, "src", gst_element_get_static_pad (audiosink, + "sink"), NULL); + + return pipeline; +} + +static GstElement * +make_playerbin_pipeline (const gchar * location) +{ + GstElement *player; + + player = gst_element_factory_make ("playbin", "player"); + g_assert (player); + + g_object_set (G_OBJECT (player), "uri", location, NULL); + + return player; +} + +static gchar * +format_value (GtkScale * scale, gdouble value) +{ + gint64 real; + gint64 seconds; + gint64 subseconds; + + real = value * duration / RANGE_PREC; + seconds = (gint64) real / GST_SECOND; + subseconds = (gint64) real / (GST_SECOND / RANGE_PREC); + + return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02" + G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100); +} + +static gboolean +update_scale (gpointer data) +{ + GstFormat format; + + position = 0; + duration = 0; + + format = GST_FORMAT_TIME; + + gst_element_query_position (pipeline, &format, &position); + gst_element_query_duration (pipeline, &format, &duration); + + if (position >= duration) + duration = position; + + if (duration > 0) { + gtk_adjustment_set_value (adjustment, + position * (gdouble) RANGE_PREC / duration); + gtk_widget_queue_draw (hscale); + } + + return TRUE; +} + +static void +speed_cb (GtkWidget * widget) +{ + GstEvent *s_event; + gboolean res; + + GST_DEBUG ("speed change"); + cur_speed = gtk_range_get_value (GTK_RANGE (widget)); + + if (cur_speed == 0.0) + return; + + s_event = gst_event_new_seek (cur_speed, + GST_FORMAT_TIME, 0, GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1); + + res = gst_element_send_event (pipeline, s_event); + if (!res) + g_print ("speed change failed\n"); +} + +static gboolean do_seek (GtkWidget * widget, gboolean flush, gboolean segment); + +static void +seek_cb (GtkWidget * widget) +{ + if (changed_id) { + GST_DEBUG ("seek because of slider move"); + + if (do_seek (widget, TRUE, TRUE)) { + g_source_remove (changed_id); + changed_id = 0; + } + } +} + +static gboolean +do_seek (GtkWidget * widget, gboolean flush, gboolean segment) +{ + gint64 start, stop; + gboolean res = FALSE; + GstEvent *s_event; + gdouble rate; + GTimeVal tv; + gboolean valid; + gdouble new_range; + + if (segment) + new_range = gtk_range_get_value (GTK_RANGE (widget)); + else { + new_range = (gdouble) RANGE_PREC; + cur_time = -1; + } + + valid = prev_time != -1; + + GST_DEBUG ("flush %d, segment %d, valid %d", flush, segment, valid); + + if (new_range == cur_range) + return FALSE; + + prev_time = cur_time; + prev_range = cur_range; + + cur_range = new_range; + + g_get_current_time (&tv); + cur_time = GST_TIMEVAL_TO_TIME (tv); + + if (!valid) + return FALSE; + + GST_DEBUG ("cur: %lf, %" GST_TIME_FORMAT, cur_range, + GST_TIME_ARGS (cur_time)); + GST_DEBUG ("prev: %lf, %" GST_TIME_FORMAT, prev_range, + GST_TIME_ARGS (prev_time)); + + diff = cur_time - prev_time; + + GST_DEBUG ("diff: %" GST_TIME_FORMAT, GST_TIME_ARGS (diff)); + + start = prev_range * duration / RANGE_PREC; + /* play 50 milliseconds */ + stop = segment ? cur_range * duration / RANGE_PREC : duration; + + if (start == stop) + return FALSE; + + if (segment) + rate = (stop - start) / (gdouble) diff; + else + rate = cur_speed; + + if (start > stop) { + gint64 tmp; + + tmp = start; + start = stop; + stop = tmp; + } + + if (rate == 0.0) + return TRUE; + + GST_DEBUG ("seek to %" GST_TIME_FORMAT " -- %" GST_TIME_FORMAT ", rate %lf" + " on element %s", + GST_TIME_ARGS (start), GST_TIME_ARGS (stop), rate, + GST_ELEMENT_NAME (pipeline)); + + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, + (flush ? GST_SEEK_FLAG_FLUSH : 0) | + (segment ? GST_SEEK_FLAG_SEGMENT : 0), + GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_SET, stop); + + res = gst_element_send_event (pipeline, s_event); + if (!res) + g_print ("seek failed\n"); + + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + + return TRUE; +} + +static gboolean +start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + if (update_id) { + g_source_remove (update_id); + update_id = 0; + } + + if (changed_id == 0) { + changed_id = + g_signal_connect (hscale, "value_changed", G_CALLBACK (seek_cb), + pipeline); + } + + GST_DEBUG ("start seek"); + + return FALSE; +} + +static gboolean +stop_seek (GtkWidget * widget, gpointer user_data) +{ + update_id = + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, pipeline); + + GST_DEBUG ("stop seek"); + + if (changed_id) { + g_source_remove (changed_id); + changed_id = 0; + } + + do_seek (hscale, FALSE, FALSE); + + return FALSE; +} + +static void +play_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_PLAYING) { + g_print ("PLAY pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + update_id = + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, pipeline); + } +} + +static void +pause_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_PAUSED) { + g_print ("PAUSE pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + g_source_remove (update_id); + } +} + +static void +stop_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_READY) { + g_print ("READY pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_READY); + /* position and speed return to their default values */ + gtk_adjustment_set_value (adjustment, 0.0); + gtk_adjustment_set_value (sadjustment, 1.0); + g_source_remove (update_id); + } +} + +static void +print_message (GstMessage * message) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("Got Message from element \"%s\"\n", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message)))); + + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } +} + +static gboolean +bus_message (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_EOS: + g_print ("EOS\n"); + break; + case GST_MESSAGE_ERROR: + case GST_MESSAGE_WARNING: + print_message (message); + break; + case GST_MESSAGE_SEGMENT_START: + break; + case GST_MESSAGE_SEGMENT_DONE: + GST_DEBUG ("segment_done, doing next seek"); + if (!do_seek (hscale, FALSE, update_id == 0)) { + if (changed_id == 0) { + changed_id = + g_signal_connect (hscale, "value_changed", G_CALLBACK (seek_cb), + pipeline); + } + } + break; + default: + break; + } + + return TRUE; +} + +typedef struct +{ + const gchar *name; + GstElement *(*func) (const gchar * location); +} +Pipeline; + +static Pipeline pipelines[] = { + {"wav", make_wav_pipeline}, + {"playerbin", make_playerbin_pipeline}, + {NULL, NULL}, +}; + +#define NUM_TYPES ((sizeof (pipelines) / sizeof (Pipeline)) - 1) + +static void +print_usage (int argc, char **argv) +{ + gint i; + + g_print ("usage: %s \n", argv[0]); + g_print (" possible types:\n"); + + for (i = 0; i < NUM_TYPES; i++) { + g_print (" %d = %s\n", i, pipelines[i].name); + } +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *hbox, *vbox, *play_button, *pause_button, *stop_button; + GstBus *bus; + GOptionEntry options[] = { + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Verbose properties", NULL}, + {NULL} + }; + gint type; + GOptionContext *ctx; + GError *err = NULL; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new ("seek"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + GST_DEBUG_CATEGORY_INIT (scrubby_debug, "scrubby", 0, "scrubby example"); + + gtk_init (&argc, &argv); + + if (argc != 3) { + print_usage (argc, argv); + exit (-1); + } + + type = atoi (argv[1]); + + if (type < 0 || type >= NUM_TYPES) { + print_usage (argc, argv); + exit (-1); + } + + pipeline = pipelines[type].func (argv[2]); + g_assert (pipeline); + + /* initialize gui elements ... */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + hbox = gtk_hbox_new (FALSE, 0); + vbox = gtk_vbox_new (FALSE, 0); + play_button = gtk_button_new_with_label ("play"); + pause_button = gtk_button_new_with_label ("pause"); + stop_button = gtk_button_new_with_label ("stop"); + + adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, (gdouble) RANGE_PREC, 0.1, + 1.0, 1.0)); + hscale = gtk_hscale_new (adjustment); + gtk_scale_set_digits (GTK_SCALE (hscale), 2); + + sadjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (1.0, 0.0, 5.0, 0.1, 1.0, 0.0)); + shscale = gtk_hscale_new (sadjustment); + gtk_scale_set_digits (GTK_SCALE (shscale), 2); + + schanged_id = + g_signal_connect (shscale, "value_changed", G_CALLBACK (speed_cb), + pipeline); + + g_signal_connect (hscale, "button_press_event", G_CALLBACK (start_seek), + pipeline); + g_signal_connect (hscale, "button_release_event", G_CALLBACK (stop_seek), + pipeline); + g_signal_connect (hscale, "format_value", G_CALLBACK (format_value), + pipeline); + + /* do the packing stuff ... */ + gtk_window_set_default_size (GTK_WINDOW (window), 96, 96); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox), shscale, TRUE, TRUE, 2); + + /* connect things ... */ + g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), + pipeline); + g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), + pipeline); + g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), + pipeline); + g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL); + + /* show the gui. */ + gtk_widget_show_all (window); + + if (verbose) { + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + } + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + g_assert (bus); + + bus_watch = gst_bus_add_watch_full (bus, + G_PRIORITY_HIGH, bus_message, pipeline, NULL); + + gtk_main (); + + g_print ("NULL pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + + g_print ("free pipeline\n"); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/seek.c b/gst-plugins-base-subtitles0.10/tests/examples/seek/seek.c new file mode 100644 index 0000000..8bf0818 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/seek.c @@ -0,0 +1,2996 @@ +/* GStreamer + * + * seek.c: seeking sample application + * + * Copyright (C) 2005 Wim Taymans + * 2006 Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include +#include +#include + +#ifdef HAVE_X +#include +#endif +#include + +#if (!GTK_CHECK_VERSION(2, 23, 0) || GTK_CHECK_VERSION(2, 90, 0)) && !GTK_CHECK_VERSION(2, 91, 1) +#define gtk_combo_box_text_new gtk_combo_box_new_text +#define gtk_combo_box_text_append_text gtk_combo_box_append_text +#define gtk_combo_box_text_remove gtk_combo_box_remove_text +#define GTK_COMBO_BOX_TEXT GTK_COMBO_BOX +#endif + +GST_DEBUG_CATEGORY_STATIC (seek_debug); +#define GST_CAT_DEFAULT (seek_debug) + +#if !GTK_CHECK_VERSION (2, 17, 7) +static void +gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a) +{ + *a = w->allocation; +} +#endif + +/* configuration */ + +//#define SOURCE "filesrc" +#define SOURCE "gnomevfssrc" + +#define ASINK "alsasink" +//#define ASINK "osssink" + +#define VSINK "xvimagesink" +//#define VSINK "sdlvideosink" +//#define VSINK "ximagesink" +//#define VSINK "aasink" +//#define VSINK "cacasink" + +#define FILL_INTERVAL 100 +//#define UPDATE_INTERVAL 500 +//#define UPDATE_INTERVAL 100 +#define UPDATE_INTERVAL 40 + +/* number of milliseconds to play for after a seek */ +#define SCRUB_TIME 100 + +/* timeout for gst_element_get_state() after a seek */ +#define SEEK_TIMEOUT 40 * GST_MSECOND + +#define DEFAULT_VIDEO_HEIGHT 300 + +/* the state to go to when stop is pressed */ +#define STOP_STATE GST_STATE_READY + +#define N_GRAD 1000.0 + +static GList *seekable_pads = NULL; +static GList *rate_pads = NULL; +static GList *seekable_elements = NULL; + +static gboolean accurate_seek = FALSE; +static gboolean keyframe_seek = FALSE; +static gboolean loop_seek = FALSE; +static gboolean flush_seek = TRUE; +static gboolean scrub = TRUE; +static gboolean play_scrub = FALSE; +static gboolean skip_seek = FALSE; +static gdouble rate = 1.0; + +static GstElement *pipeline; +static gint pipeline_type; +static const gchar *pipeline_spec; +static gint64 position = -1; +static gint64 duration = -1; +static GtkAdjustment *adjustment; +static GtkWidget *hscale, *statusbar; +static guint status_id = 0; +static gboolean stats = FALSE; +static gboolean elem_seek = FALSE; +static gboolean verbose = FALSE; + +static gboolean is_live = FALSE; +static gboolean buffering = FALSE; +static GstBufferingMode mode; +static gint64 buffering_left; +static GstState state = GST_STATE_NULL; +static guint update_id = 0; +static guint seek_timeout_id = 0; +static gulong changed_id; +static guint fill_id = 0; + +static gint n_video = 0, n_audio = 0, n_text = 0; +static gboolean need_streams = TRUE; +static GtkWidget *video_combo, *audio_combo, *text_combo, *vis_combo; +static GtkWidget *vis_checkbox, *video_checkbox, *audio_checkbox; +static GtkWidget *text_checkbox, *mute_checkbox, *volume_spinbutton; +static GtkWidget *skip_checkbox, *video_window, *download_checkbox; +static GtkWidget *buffer_checkbox, *rate_spinbutton; + +static GStaticMutex state_mutex = G_STATIC_MUTEX_INIT; + +static GtkWidget *format_combo, *step_amount_spinbutton, *step_rate_spinbutton; +static GtkWidget *shuttle_checkbox, *step_button; +static GtkWidget *shuttle_hscale; +static GtkAdjustment *shuttle_adjustment; + +static GList *paths = NULL, *l = NULL; + +/* we keep an array of the visualisation entries so that we can easily switch + * with the combo box index. */ +typedef struct +{ + GstElementFactory *factory; +} VisEntry; + +static GArray *vis_entries; + +static void clear_streams (GstElement * pipeline); +static void volume_notify_cb (GstElement * pipeline, GParamSpec * arg, + gpointer user_dat); + +/* pipeline construction */ + +typedef struct +{ + const gchar *padname; + GstPad *target; + GstElement *bin; +} +dyn_link; + +static GstElement * +gst_element_factory_make_or_warn (const gchar * type, const gchar * name) +{ + GstElement *element = gst_element_factory_make (type, name); + + if (!element) { + g_warning ("Failed to create element %s of type %s", name, type); + } + + return element; +} + +static void +dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) +{ + gchar *padname; + dyn_link *connect = (dyn_link *) data; + + padname = gst_pad_get_name (newpad); + + if (connect->padname == NULL || !strcmp (padname, connect->padname)) { + if (connect->bin) + gst_bin_add (GST_BIN (pipeline), connect->bin); + gst_pad_link (newpad, connect->target); + + //seekable_pads = g_list_prepend (seekable_pads, newpad); + rate_pads = g_list_prepend (rate_pads, newpad); + } + g_free (padname); +} + +static void +setup_dynamic_link (GstElement * element, const gchar * padname, + GstPad * target, GstElement * bin) +{ + dyn_link *connect; + + connect = g_new0 (dyn_link, 1); + connect->padname = g_strdup (padname); + connect->target = target; + connect->bin = bin; + + g_signal_connect (G_OBJECT (element), "pad-added", G_CALLBACK (dynamic_link), + connect); +} + +static GstElement * +make_mod_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("modplug", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_dv_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *demux, *decoder, *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("dvdemux", "demuxer"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + decoder = gst_element_factory_make_or_warn ("ffdec_dvvideo", "decoder"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn ("alsasink", "a_sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (pipeline), a_queue); + gst_bin_add (GST_BIN (pipeline), audiosink); + gst_bin_add (GST_BIN (pipeline), v_queue); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), videosink); + + gst_element_link (src, demux); + gst_element_link (a_queue, audiosink); + gst_element_link (v_queue, decoder); + gst_element_link (decoder, videosink); + + setup_dynamic_link (demux, "video", gst_element_get_static_pad (v_queue, + "sink"), NULL); + setup_dynamic_link (demux, "audio", gst_element_get_static_pad (a_queue, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + + return pipeline; +} + +static GstElement * +make_wav_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("wavparse", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + + setup_dynamic_link (decoder, "src", gst_element_get_static_pad (audiosink, + "sink"), NULL); + + seekable_elements = g_list_prepend (seekable_elements, audiosink); + + /* force element seeking on this pipeline */ + elem_seek = TRUE; + + return pipeline; +} + +static GstElement * +make_flac_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("flacdec", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_sid_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *decoder, *audiosink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + decoder = gst_element_factory_make_or_warn ("siddec", "decoder"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + //g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, decoder); + gst_element_link (decoder, audiosink); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_parse_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *parser, *fakesink; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + parser = gst_element_factory_make_or_warn ("mpegparse", "parse"); + fakesink = gst_element_factory_make_or_warn ("fakesink", "sink"); + g_object_set (G_OBJECT (fakesink), "silent", TRUE, NULL); + g_object_set (G_OBJECT (fakesink), "sync", TRUE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), parser); + gst_bin_add (GST_BIN (pipeline), fakesink); + + gst_element_link (src, parser); + gst_element_link (parser, fakesink); + + seekable = gst_element_get_static_pad (parser, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (parser, "sink")); + + return pipeline; +} + +static GstElement * +make_vorbis_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin; + GstElement *src, *demux, *decoder, *convert, *audiosink; + GstPad *pad, *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + decoder = gst_element_factory_make_or_warn ("vorbisdec", "decoder"); + convert = gst_element_factory_make_or_warn ("audioconvert", "convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + g_object_set (G_OBJECT (audiosink), "sync", TRUE, NULL); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + audio_bin = gst_bin_new ("a_decoder_bin"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (audio_bin), decoder); + gst_bin_add (GST_BIN (audio_bin), convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + gst_bin_add (GST_BIN (pipeline), audio_bin); + + gst_element_link (src, demux); + gst_element_link (decoder, convert); + gst_element_link (convert, audiosink); + + pad = gst_element_get_static_pad (decoder, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_theora_pipeline (const gchar * location) +{ + GstElement *pipeline, *video_bin; + GstElement *src, *demux, *decoder, *convert, *videosink; + GstPad *pad, *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + decoder = gst_element_factory_make_or_warn ("theoradec", "decoder"); + convert = gst_element_factory_make_or_warn ("ffmpegcolorspace", "convert"); + videosink = gst_element_factory_make_or_warn (VSINK, "sink"); + + g_object_set (G_OBJECT (src), "location", location, NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_bin_add (GST_BIN (video_bin), decoder); + gst_bin_add (GST_BIN (video_bin), convert); + gst_bin_add (GST_BIN (video_bin), videosink); + gst_bin_add (GST_BIN (pipeline), video_bin); + + gst_element_link (src, demux); + gst_element_link (decoder, convert); + gst_element_link (convert, videosink); + + pad = gst_element_get_static_pad (decoder, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_vorbis_theora_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue, *v_scale; + GstPad *seekable; + GstPad *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("oggdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + a_decoder = gst_element_factory_make_or_warn ("vorbisdec", "a_dec"); + a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_queue, a_decoder); + gst_element_link (a_decoder, a_convert); + gst_element_link (a_convert, audiosink); + + pad = gst_element_get_static_pad (a_queue, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_decoder = gst_element_factory_make_or_warn ("theoradec", "v_dec"); + v_convert = + gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert"); + v_scale = gst_element_factory_make_or_warn ("videoscale", "v_scale"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_convert); + gst_bin_add (GST_BIN (video_bin), v_scale); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link_many (v_queue, v_decoder, v_convert, v_scale, videosink, + NULL); + + pad = gst_element_get_static_pad (v_queue, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (a_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_avi_msmpeg4v3_mp3_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *a_convert, *v_decoder, *v_convert; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable, *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("avidemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_convert = gst_element_factory_make_or_warn ("audioconvert", "a_convert"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_convert); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_queue, a_decoder); + gst_element_link (a_decoder, a_convert); + gst_element_link (a_convert, audiosink); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + pad = gst_element_get_static_pad (a_queue, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_decoder = gst_element_factory_make_or_warn ("ffdec_msmpeg4", "v_dec"); + v_convert = + gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_convert"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_convert); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link_many (v_queue, v_decoder, v_convert, videosink, NULL); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + pad = gst_element_get_static_pad (v_queue, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, NULL, gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (a_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mp3_pipeline (const gchar * location) +{ + GstElement *pipeline; + GstElement *src, *parser, *decoder, *audiosink, *queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + parser = gst_element_factory_make_or_warn ("mp3parse", "parse"); + decoder = gst_element_factory_make_or_warn ("mad", "dec"); + queue = gst_element_factory_make_or_warn ("queue", "queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "sink"); + + seekable_elements = g_list_prepend (seekable_elements, audiosink); + + g_object_set (G_OBJECT (src), "location", location, NULL); + //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), parser); + gst_bin_add (GST_BIN (pipeline), decoder); + gst_bin_add (GST_BIN (pipeline), queue); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link (src, parser); + gst_element_link (parser, decoder); + gst_element_link (decoder, queue); + gst_element_link (queue, audiosink); + + seekable = gst_element_get_static_pad (queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (decoder, "sink")); + + return pipeline; +} + +static GstElement * +make_avi_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *audiosink, *videosink; + GstElement *a_queue = NULL, *v_queue = NULL; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("avidemux", "demux"); + seekable_elements = g_list_prepend (seekable_elements, demux); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + gst_element_set_state (audio_bin, GST_STATE_PAUSED); + + setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder, + "sink"), audio_bin); + + seekable = gst_element_get_static_pad (a_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("ffmpegdecall", "v_dec"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + gst_element_link (v_decoder, v_queue); + gst_element_link (v_queue, videosink); + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_set_state (video_bin, GST_STATE_PAUSED); + + setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder, + "sink"), video_bin); + + seekable = gst_element_get_static_pad (v_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mpeg_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter; + GstElement *audiosink, *videosink; + GstElement *a_queue, *v_queue; + GstPad *seekable; + GstPad *pad; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + //demux = gst_element_factory_make_or_warn ("mpegdemux", "demux"); + demux = gst_element_factory_make_or_warn ("flupsdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + + gst_bin_add (GST_BIN (pipeline), audio_bin); + + pad = gst_element_get_static_pad (a_decoder, "sink"); + gst_element_add_pad (audio_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, "audio_c0", gst_element_get_static_pad (audio_bin, + "sink"), NULL); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec"); + v_queue = gst_element_factory_make_or_warn ("queue", "v_queue"); + v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + + gst_bin_add (GST_BIN (video_bin), v_decoder); + gst_bin_add (GST_BIN (video_bin), v_queue); + gst_bin_add (GST_BIN (video_bin), v_filter); + gst_bin_add (GST_BIN (video_bin), videosink); + + gst_element_link (v_decoder, v_queue); + gst_element_link (v_queue, v_filter); + gst_element_link (v_filter, videosink); + + gst_bin_add (GST_BIN (pipeline), video_bin); + + pad = gst_element_get_static_pad (v_decoder, "sink"); + gst_element_add_pad (video_bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + setup_dynamic_link (demux, "video_e0", gst_element_get_static_pad (video_bin, + "sink"), NULL); + + seekable = gst_element_get_static_pad (v_filter, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static GstElement * +make_mpegnt_pipeline (const gchar * location) +{ + GstElement *pipeline, *audio_bin, *video_bin; + GstElement *src, *demux, *a_decoder, *v_decoder, *v_filter; + GstElement *audiosink, *videosink; + GstElement *a_queue; + GstPad *seekable; + + pipeline = gst_pipeline_new ("app"); + + src = gst_element_factory_make_or_warn (SOURCE, "src"); + g_object_set (G_OBJECT (src), "location", location, NULL); + + demux = gst_element_factory_make_or_warn ("mpegdemux", "demux"); + //g_object_set (G_OBJECT (demux), "sync", TRUE, NULL); + + seekable_elements = g_list_prepend (seekable_elements, demux); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + gst_element_link (src, demux); + + audio_bin = gst_bin_new ("a_decoder_bin"); + a_decoder = gst_element_factory_make_or_warn ("mad", "a_dec"); + a_queue = gst_element_factory_make_or_warn ("queue", "a_queue"); + audiosink = gst_element_factory_make_or_warn (ASINK, "a_sink"); + //g_object_set (G_OBJECT (audiosink), "fragment", 0x00180008, NULL); + g_object_set (G_OBJECT (audiosink), "sync", FALSE, NULL); + gst_element_link (a_decoder, a_queue); + gst_element_link (a_queue, audiosink); + gst_bin_add (GST_BIN (audio_bin), a_decoder); + gst_bin_add (GST_BIN (audio_bin), a_queue); + gst_bin_add (GST_BIN (audio_bin), audiosink); + + setup_dynamic_link (demux, "audio_00", gst_element_get_static_pad (a_decoder, + "sink"), audio_bin); + + seekable = gst_element_get_static_pad (a_queue, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (a_decoder, + "sink")); + + video_bin = gst_bin_new ("v_decoder_bin"); + v_decoder = gst_element_factory_make_or_warn ("mpeg2dec", "v_dec"); + v_filter = gst_element_factory_make_or_warn ("ffmpegcolorspace", "v_filter"); + videosink = gst_element_factory_make_or_warn (VSINK, "v_sink"); + gst_element_link_many (v_decoder, v_filter, videosink, NULL); + + gst_bin_add_many (GST_BIN (video_bin), v_decoder, v_filter, videosink, NULL); + + setup_dynamic_link (demux, "video_00", gst_element_get_static_pad (v_decoder, + "sink"), video_bin); + + seekable = gst_element_get_static_pad (v_decoder, "src"); + seekable_pads = g_list_prepend (seekable_pads, seekable); + rate_pads = g_list_prepend (rate_pads, seekable); + rate_pads = + g_list_prepend (rate_pads, gst_element_get_static_pad (v_decoder, + "sink")); + + return pipeline; +} + +static void +playerbin_set_uri (GstElement * player, const gchar * location) +{ + gchar *uri; + + /* Add "file://" prefix for convenience */ + if (g_str_has_prefix (location, "/")) { + uri = g_strconcat ("file://", location, NULL); + g_object_set (G_OBJECT (player), "uri", uri, NULL); + g_free (uri); + } else { + g_object_set (G_OBJECT (player), "uri", location, NULL); + } +} + +static GstElement * +construct_playerbin (const gchar * name, const gchar * location) +{ + GstElement *player; + + player = gst_element_factory_make (name, "player"); + g_assert (player); + + playerbin_set_uri (player, location); + + seekable_elements = g_list_prepend (seekable_elements, player); + + /* force element seeking on this pipeline */ + elem_seek = TRUE; + + return player; +} + +static GstElement * +make_playerbin_pipeline (const gchar * location) +{ + return construct_playerbin ("playbin", location); +} + +static GstElement * +make_playerbin2_pipeline (const gchar * location) +{ + GstElement *pipeline = construct_playerbin ("playbin2", location); + + /* FIXME: this is not triggered, playbin2 is not forwarding it from the sink */ + g_signal_connect (pipeline, "notify::volume", G_CALLBACK (volume_notify_cb), + NULL); + return pipeline; +} + +#ifndef GST_DISABLE_PARSE +static GstElement * +make_parselaunch_pipeline (const gchar * description) +{ + GstElement *pipeline; + GError *error = NULL; + + pipeline = gst_parse_launch (description, &error); + + seekable_elements = g_list_prepend (seekable_elements, pipeline); + + elem_seek = TRUE; + + return pipeline; +} +#endif + +typedef struct +{ + const gchar *name; + GstElement *(*func) (const gchar * location); +} +Pipeline; + +static Pipeline pipelines[] = { + {"mp3", make_mp3_pipeline}, + {"avi", make_avi_pipeline}, + {"mpeg1", make_mpeg_pipeline}, + {"mpegparse", make_parse_pipeline}, + {"vorbis", make_vorbis_pipeline}, + {"theora", make_theora_pipeline}, + {"ogg/v/t", make_vorbis_theora_pipeline}, + {"avi/msmpeg4v3/mp3", make_avi_msmpeg4v3_mp3_pipeline}, + {"sid", make_sid_pipeline}, + {"flac", make_flac_pipeline}, + {"wav", make_wav_pipeline}, + {"mod", make_mod_pipeline}, + {"dv", make_dv_pipeline}, + {"mpeg1nothreads", make_mpegnt_pipeline}, + {"playerbin", make_playerbin_pipeline}, +#ifndef GST_DISABLE_PARSE + {"parse-launch", make_parselaunch_pipeline}, +#endif + {"playerbin2", make_playerbin2_pipeline}, + {NULL, NULL}, +}; + +#define NUM_TYPES ((sizeof (pipelines) / sizeof (Pipeline)) - 1) + +/* ui callbacks and helpers */ + +static gchar * +format_value (GtkScale * scale, gdouble value) +{ + gint64 real; + gint64 seconds; + gint64 subseconds; + + real = value * duration / N_GRAD; + seconds = (gint64) real / GST_SECOND; + subseconds = (gint64) real / (GST_SECOND / N_GRAD); + + return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02" + G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100); +} + + +static gchar * +shuttle_format_value (GtkScale * scale, gdouble value) +{ + return g_strdup_printf ("%0.*g", gtk_scale_get_digits (scale), value); +} + +typedef struct +{ + const gchar *name; + const GstFormat format; +} +seek_format; + +static seek_format seek_formats[] = { + {"tim", GST_FORMAT_TIME}, + {"byt", GST_FORMAT_BYTES}, + {"buf", GST_FORMAT_BUFFERS}, + {"def", GST_FORMAT_DEFAULT}, + {NULL, 0}, +}; + +G_GNUC_UNUSED static void +query_rates (void) +{ + GList *walk = rate_pads; + + while (walk) { + GstPad *pad = GST_PAD (walk->data); + gint i = 0; + + g_print ("rate/sec %8.8s: ", GST_PAD_NAME (pad)); + while (seek_formats[i].name) { + gint64 value; + GstFormat format; + + format = seek_formats[i].format; + + if (gst_pad_query_convert (pad, GST_FORMAT_TIME, GST_SECOND, &format, + &value)) { + g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value); + } else { + g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*"); + } + + i++; + } + g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad)); + + walk = g_list_next (walk); + } +} + +G_GNUC_UNUSED static void +query_positions_elems (void) +{ + GList *walk = seekable_elements; + + while (walk) { + GstElement *element = GST_ELEMENT (walk->data); + gint i = 0; + + g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element)); + while (seek_formats[i].name) { + gint64 position, total; + GstFormat format; + + format = seek_formats[i].format; + + if (gst_element_query_position (element, &format, &position) && + gst_element_query_duration (element, &format, &total)) { + g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ", + seek_formats[i].name, position, total); + } else { + g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*", + "*NA*"); + } + i++; + } + g_print (" %s\n", GST_ELEMENT_NAME (element)); + + walk = g_list_next (walk); + } +} + +G_GNUC_UNUSED static void +query_positions_pads (void) +{ + GList *walk = seekable_pads; + + while (walk) { + GstPad *pad = GST_PAD (walk->data); + gint i = 0; + + g_print ("positions %8.8s: ", GST_PAD_NAME (pad)); + while (seek_formats[i].name) { + GstFormat format; + gint64 position, total; + + format = seek_formats[i].format; + + if (gst_pad_query_position (pad, &format, &position) && + gst_pad_query_duration (pad, &format, &total)) { + g_print ("%s %13" G_GINT64_FORMAT " / %13" G_GINT64_FORMAT " | ", + seek_formats[i].name, position, total); + } else { + g_print ("%s %13.13s / %13.13s | ", seek_formats[i].name, "*NA*", + "*NA*"); + } + + i++; + } + g_print (" %s:%s\n", GST_DEBUG_PAD_NAME (pad)); + + walk = g_list_next (walk); + } +} + +static gboolean start_seek (GtkWidget * widget, GdkEventButton * event, + gpointer user_data); +static gboolean stop_seek (GtkWidget * widget, GdkEventButton * event, + gpointer user_data); +static void seek_cb (GtkWidget * widget); + +static void +set_scale (gdouble value) +{ + g_signal_handlers_block_by_func (hscale, (void *) start_seek, + (void *) pipeline); + g_signal_handlers_block_by_func (hscale, (void *) stop_seek, + (void *) pipeline); + g_signal_handlers_block_by_func (hscale, (void *) seek_cb, (void *) pipeline); + gtk_adjustment_set_value (adjustment, value); + g_signal_handlers_unblock_by_func (hscale, (void *) start_seek, + (void *) pipeline); + g_signal_handlers_unblock_by_func (hscale, (void *) stop_seek, + (void *) pipeline); + g_signal_handlers_unblock_by_func (hscale, (void *) seek_cb, + (void *) pipeline); + gtk_widget_queue_draw (hscale); +} + +static gboolean +update_fill (gpointer data) +{ + if (elem_seek) { + if (seekable_elements) { + GstElement *element = GST_ELEMENT (seekable_elements->data); + GstQuery *query; + + query = gst_query_new_buffering (GST_FORMAT_PERCENT); + if (gst_element_query (element, query)) { + gint64 start, stop, buffering_total; + GstFormat format; + gdouble fill; + gboolean busy; + gint percent; + GstBufferingMode mode; + gint avg_in, avg_out; + gint64 buffering_left; + + gst_query_parse_buffering_percent (query, &busy, &percent); + gst_query_parse_buffering_range (query, &format, &start, &stop, + &buffering_total); + gst_query_parse_buffering_stats (query, &mode, &avg_in, &avg_out, + &buffering_left); + + /* note that we could start the playback when buffering_left < remaining + * playback time */ + GST_DEBUG ("buffering total %" G_GINT64_FORMAT " ms, left %" + G_GINT64_FORMAT " ms", buffering_total, buffering_left); + GST_DEBUG ("start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT, + start, stop); + + if (stop != -1) + fill = N_GRAD * stop / GST_FORMAT_PERCENT_MAX; + else + fill = N_GRAD; + + gtk_range_set_fill_level (GTK_RANGE (hscale), fill); + } + gst_query_unref (query); + } + } + return TRUE; +} + +static gboolean +update_scale (gpointer data) +{ + GstFormat format = GST_FORMAT_TIME; + + //position = 0; + //duration = 0; + + if (elem_seek) { + if (seekable_elements) { + GstElement *element = GST_ELEMENT (seekable_elements->data); + + gst_element_query_position (element, &format, &position); + gst_element_query_duration (element, &format, &duration); + } + } else { + if (seekable_pads) { + GstPad *pad = GST_PAD (seekable_pads->data); + + gst_pad_query_position (pad, &format, &position); + gst_pad_query_duration (pad, &format, &duration); + } + } + + if (stats) { + if (elem_seek) { + query_positions_elems (); + } else { + query_positions_pads (); + } + query_rates (); + } + + if (position >= duration) + duration = position; + + if (duration > 0) { + set_scale (position * N_GRAD / duration); + } + + /* FIXME: see make_playerbin2_pipeline() and volume_notify_cb() */ + if (pipeline_type == 16) { + g_object_notify (G_OBJECT (pipeline), "volume"); + } + + return TRUE; +} + +static void do_seek (GtkWidget * widget); +static void connect_bus_signals (GstElement * pipeline); +static void set_update_scale (gboolean active); +static void set_update_fill (gboolean active); + +static gboolean +end_scrub (GtkWidget * widget) +{ + GST_DEBUG ("end scrub, PAUSE"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + seek_timeout_id = 0; + + return FALSE; +} + +static gboolean +send_event (GstEvent * event) +{ + gboolean res = FALSE; + + if (!elem_seek) { + GList *walk = seekable_pads; + + while (walk) { + GstPad *seekable = GST_PAD (walk->data); + + GST_DEBUG ("send event on pad %s:%s", GST_DEBUG_PAD_NAME (seekable)); + + gst_event_ref (event); + res = gst_pad_send_event (seekable, event); + + walk = g_list_next (walk); + } + } else { + GList *walk = seekable_elements; + + while (walk) { + GstElement *seekable = GST_ELEMENT (walk->data); + + GST_DEBUG ("send event on element %s", GST_ELEMENT_NAME (seekable)); + + gst_event_ref (event); + res = gst_element_send_event (seekable, event); + + walk = g_list_next (walk); + } + } + gst_event_unref (event); + return res; +} + +static void +do_seek (GtkWidget * widget) +{ + gint64 real; + gboolean res = FALSE; + GstEvent *s_event; + GstSeekFlags flags; + + real = gtk_range_get_value (GTK_RANGE (widget)) * duration / N_GRAD; + + GST_DEBUG ("value=%f, real=%" G_GINT64_FORMAT, + gtk_range_get_value (GTK_RANGE (widget)), real); + + flags = 0; + if (flush_seek) + flags |= GST_SEEK_FLAG_FLUSH; + if (accurate_seek) + flags |= GST_SEEK_FLAG_ACCURATE; + if (keyframe_seek) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + if (rate >= 0) { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, real, GST_SEEK_TYPE_SET, + GST_CLOCK_TIME_NONE); + GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (real), GST_TIME_ARGS (duration)); + } else { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, real); + GST_DEBUG ("seek with rate %lf to %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (0), GST_TIME_ARGS (real)); + } + + res = send_event (s_event); + + if (res) { + if (flush_seek) { + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT); + } else { + set_update_scale (TRUE); + } + } else { + g_print ("seek failed\n"); + set_update_scale (TRUE); + } +} + +static void +seek_cb (GtkWidget * widget) +{ + /* If the timer hasn't expired yet, then the pipeline is running */ + if (play_scrub && seek_timeout_id != 0) { + GST_DEBUG ("do scrub seek, PAUSED"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + + GST_DEBUG ("do seek"); + do_seek (widget); + + if (play_scrub) { + GST_DEBUG ("do scrub seek, PLAYING"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + if (seek_timeout_id == 0) { + seek_timeout_id = + g_timeout_add (SCRUB_TIME, (GSourceFunc) end_scrub, widget); + } + } +} + +static void +set_update_fill (gboolean active) +{ + GST_DEBUG ("fill scale is %d", active); + + if (active) { + if (fill_id == 0) { + fill_id = + g_timeout_add (FILL_INTERVAL, (GSourceFunc) update_fill, pipeline); + } + } else { + if (fill_id) { + g_source_remove (fill_id); + fill_id = 0; + } + } +} + +static void +set_update_scale (gboolean active) +{ + + GST_DEBUG ("update scale is %d", active); + + if (active) { + if (update_id == 0) { + update_id = + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, pipeline); + } + } else { + if (update_id) { + g_source_remove (update_id); + update_id = 0; + } + } +} + +static gboolean +start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + if (event->type != GDK_BUTTON_PRESS) + return FALSE; + + set_update_scale (FALSE); + + if (state == GST_STATE_PLAYING && flush_seek && scrub) { + GST_DEBUG ("start scrub seek, PAUSE"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + + if (changed_id == 0 && flush_seek && scrub) { + changed_id = + g_signal_connect (hscale, "value_changed", G_CALLBACK (seek_cb), + pipeline); + } + + return FALSE; +} + +static gboolean +stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + if (changed_id) { + g_signal_handler_disconnect (hscale, changed_id); + changed_id = 0; + } + + if (!flush_seek || !scrub) { + GST_DEBUG ("do final seek"); + do_seek (widget); + } + + if (seek_timeout_id != 0) { + g_source_remove (seek_timeout_id); + seek_timeout_id = 0; + /* Still scrubbing, so the pipeline is playing, see if we need PAUSED + * instead. */ + if (state == GST_STATE_PAUSED) { + GST_DEBUG ("stop scrub seek, PAUSED"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + } else { + if (state == GST_STATE_PLAYING) { + GST_DEBUG ("stop scrub seek, PLAYING"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } + } + + return FALSE; +} + +static void +play_cb (GtkButton * button, gpointer data) +{ + GstStateChangeReturn ret; + + if (state != GST_STATE_PLAYING) { + g_print ("PLAY pipeline\n"); + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + goto failed; + case GST_STATE_CHANGE_NO_PREROLL: + is_live = TRUE; + break; + default: + break; + } + state = GST_STATE_PLAYING; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Playing"); + } + + return; + +failed: + { + g_print ("PLAY failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Play failed"); + } +} + +static void +pause_cb (GtkButton * button, gpointer data) +{ + g_static_mutex_lock (&state_mutex); + if (state != GST_STATE_PAUSED) { + GstStateChangeReturn ret; + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + g_print ("PAUSE pipeline\n"); + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + goto failed; + case GST_STATE_CHANGE_NO_PREROLL: + is_live = TRUE; + break; + default: + break; + } + + state = GST_STATE_PAUSED; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Paused"); + } + g_static_mutex_unlock (&state_mutex); + + return; + +failed: + { + g_static_mutex_unlock (&state_mutex); + g_print ("PAUSE failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Pause failed"); + } +} + +static void +stop_cb (GtkButton * button, gpointer data) +{ + if (state != STOP_STATE) { + GstStateChangeReturn ret; + + g_print ("READY pipeline\n"); + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + + g_static_mutex_lock (&state_mutex); + ret = gst_element_set_state (pipeline, STOP_STATE); + if (ret == GST_STATE_CHANGE_FAILURE) + goto failed; + + state = STOP_STATE; + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped"); + + is_live = FALSE; + buffering = FALSE; + set_update_scale (FALSE); + set_scale (0.0); + set_update_fill (FALSE); + + if (pipeline_type == 16) + clear_streams (pipeline); + g_static_mutex_unlock (&state_mutex); + +#if 0 + /* if one uses parse_launch, play, stop and play again it fails as all the + * pads after the demuxer can't be reconnected + */ + if (!strcmp (pipelines[pipeline_type].name, "parse-launch")) { + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + g_list_free (seekable_elements); + seekable_elements = NULL; + g_list_free (seekable_pads); + seekable_pads = NULL; + g_list_free (rate_pads); + rate_pads = NULL; + + pipeline = pipelines[pipeline_type].func (pipeline_spec); + g_assert (pipeline); + gst_element_set_state (pipeline, STOP_STATE); + connect_bus_signals (pipeline); + } +#endif + } + return; + +failed: + { + g_static_mutex_unlock (&state_mutex); + g_print ("STOP failed\n"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stop failed"); + } +} + +static void +accurate_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + accurate_seek = gtk_toggle_button_get_active (button); +} + +static void +key_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + keyframe_seek = gtk_toggle_button_get_active (button); +} + +static void +loop_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + loop_seek = gtk_toggle_button_get_active (button); + if (state == GST_STATE_PLAYING) { + do_seek (hscale); + } +} + +static void +flush_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + flush_seek = gtk_toggle_button_get_active (button); +} + +static void +scrub_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + scrub = gtk_toggle_button_get_active (button); +} + +static void +play_scrub_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + play_scrub = gtk_toggle_button_get_active (button); +} + +static void +skip_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + skip_seek = gtk_toggle_button_get_active (button); + if (state == GST_STATE_PLAYING) { + do_seek (hscale); + } +} + +static void +rate_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline) +{ + gboolean res = FALSE; + GstEvent *s_event; + GstSeekFlags flags; + + rate = gtk_spin_button_get_value (button); + + GST_DEBUG ("rate changed to %lf", rate); + + flags = 0; + if (flush_seek) + flags |= GST_SEEK_FLAG_FLUSH; + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (accurate_seek) + flags |= GST_SEEK_FLAG_ACCURATE; + if (keyframe_seek) + flags |= GST_SEEK_FLAG_KEY_UNIT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + if (rate >= 0.0) { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, position, + GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); + } else { + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, position); + } + + res = send_event (s_event); + + if (res) { + if (flush_seek) { + gst_element_get_state (GST_ELEMENT (pipeline), NULL, NULL, SEEK_TIMEOUT); + } + } else + g_print ("seek failed\n"); +} + +static void +update_flag (GstPipeline * pipeline, gint num, gboolean state) +{ + gint flags; + + g_object_get (pipeline, "flags", &flags, NULL); + if (state) + flags |= (1 << num); + else + flags &= ~(1 << num); + g_object_set (pipeline, "flags", flags, NULL); +} + +static void +vis_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 3, state); + gtk_widget_set_sensitive (vis_combo, state); +} + +static void +audio_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 1, state); + gtk_widget_set_sensitive (audio_combo, state); +} + +static void +video_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 0, state); + gtk_widget_set_sensitive (video_combo, state); +} + +static void +text_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 2, state); + gtk_widget_set_sensitive (text_combo, state); +} + +static void +mute_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean mute; + + mute = gtk_toggle_button_get_active (button); + g_object_set (pipeline, "mute", mute, NULL); +} + +static void +download_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 7, state); +} + +static void +buffer_toggle_cb (GtkToggleButton * button, GstPipeline * pipeline) +{ + gboolean state; + + state = gtk_toggle_button_get_active (button); + update_flag (pipeline, 8, state); +} + +static void +clear_streams (GstElement * pipeline) +{ + gint i; + + /* remove previous info */ + for (i = 0; i < n_video; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (video_combo), 0); + for (i = 0; i < n_audio; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (audio_combo), 0); + for (i = 0; i < n_text; i++) + gtk_combo_box_text_remove (GTK_COMBO_BOX_TEXT (text_combo), 0); + + n_audio = n_video = n_text = 0; + gtk_widget_set_sensitive (video_combo, FALSE); + gtk_widget_set_sensitive (audio_combo, FALSE); + gtk_widget_set_sensitive (text_combo, FALSE); + + need_streams = TRUE; +} + +static void +update_streams (GstPipeline * pipeline) +{ + gint i; + + if (pipeline_type == 16 && need_streams) { + GstTagList *tags; + gchar *name, *str; + gint active_idx; + gboolean state; + + /* remove previous info */ + clear_streams (GST_ELEMENT_CAST (pipeline)); + + /* here we get and update the different streams detected by playbin2 */ + g_object_get (pipeline, "n-video", &n_video, NULL); + g_object_get (pipeline, "n-audio", &n_audio, NULL); + g_object_get (pipeline, "n-text", &n_text, NULL); + + g_print ("video %d, audio %d, text %d\n", n_video, n_audio, n_text); + + active_idx = 0; + for (i = 0; i < n_video; i++) { + g_signal_emit_by_name (pipeline, "get-video-tags", i, &tags); + if (tags) { + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("video %d: %s\n", i, str); + g_free (str); + } + /* find good name for the label */ + name = g_strdup_printf ("video %d", i + 1); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (video_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (video_checkbox)); + gtk_widget_set_sensitive (video_combo, state && n_video > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (video_combo), active_idx); + + active_idx = 0; + for (i = 0; i < n_audio; i++) { + g_signal_emit_by_name (pipeline, "get-audio-tags", i, &tags); + if (tags) { + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("audio %d: %s\n", i, str); + g_free (str); + } + /* find good name for the label */ + name = g_strdup_printf ("audio %d", i + 1); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (audio_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (audio_checkbox)); + gtk_widget_set_sensitive (audio_combo, state && n_audio > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (audio_combo), active_idx); + + active_idx = 0; + for (i = 0; i < n_text; i++) { + g_signal_emit_by_name (pipeline, "get-text-tags", i, &tags); + + name = NULL; + if (tags) { + const GValue *value; + + str = gst_structure_to_string ((GstStructure *) tags); + g_print ("text %d: %s\n", i, str); + g_free (str); + + /* get the language code if we can */ + value = gst_tag_list_get_value_index (tags, GST_TAG_LANGUAGE_CODE, 0); + if (value && G_VALUE_HOLDS_STRING (value)) { + name = g_strdup_printf ("text %s", g_value_get_string (value)); + } + } + /* find good name for the label if we didn't use a tag */ + if (name == NULL) + name = g_strdup_printf ("text %d", i + 1); + + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (text_combo), name); + g_free (name); + } + state = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (text_checkbox)); + gtk_widget_set_sensitive (text_combo, state && n_text > 0); + gtk_combo_box_set_active (GTK_COMBO_BOX (text_combo), active_idx); + + need_streams = FALSE; + } +} + +static void +video_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current video track %d\n", active); + g_object_set (pipeline, "current-video", active, NULL); +} + +static void +audio_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current audio track %d\n", active); + g_object_set (pipeline, "current-audio", active, NULL); +} + +static void +text_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + gint active; + + active = gtk_combo_box_get_active (combo); + + g_print ("setting current text track %d\n", active); + g_object_set (pipeline, "current-text", active, NULL); +} + +static gboolean +filter_features (GstPluginFeature * feature, gpointer data) +{ + GstElementFactory *f; + + if (!GST_IS_ELEMENT_FACTORY (feature)) + return FALSE; + f = GST_ELEMENT_FACTORY (feature); + if (!g_strrstr (gst_element_factory_get_klass (f), "Visualization")) + return FALSE; + + return TRUE; +} + +static void +init_visualization_features (void) +{ + GList *list, *walk; + + vis_entries = g_array_new (FALSE, FALSE, sizeof (VisEntry)); + + list = gst_registry_feature_filter (gst_registry_get_default (), + filter_features, FALSE, NULL); + + for (walk = list; walk; walk = g_list_next (walk)) { + VisEntry entry; + const gchar *name; + + entry.factory = GST_ELEMENT_FACTORY (walk->data); + name = gst_element_factory_get_longname (entry.factory); + + g_array_append_val (vis_entries, entry); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (vis_combo), name); + } + gtk_combo_box_set_active (GTK_COMBO_BOX (vis_combo), 0); +} + +static void +vis_combo_cb (GtkComboBox * combo, GstPipeline * pipeline) +{ + guint index; + VisEntry *entry; + GstElement *element; + + /* get the selected index and get the factory for this index */ + index = gtk_combo_box_get_active (GTK_COMBO_BOX (vis_combo)); + if (vis_entries->len > 0) { + entry = &g_array_index (vis_entries, VisEntry, index); + + /* create an instance of the element from the factory */ + element = gst_element_factory_create (entry->factory, NULL); + if (!element) + return; + + /* set vis plugin for playbin2 */ + g_object_set (pipeline, "vis-plugin", element, NULL); + } +} + +static void +volume_spinbutton_changed_cb (GtkSpinButton * button, GstPipeline * pipeline) +{ + gdouble volume; + + volume = gtk_spin_button_get_value (button); + + g_object_set (pipeline, "volume", volume, NULL); +} + +static void +volume_notify_cb (GstElement * pipeline, GParamSpec * arg, gpointer user_dat) +{ + gdouble cur_volume, new_volume; + + g_object_get (pipeline, "volume", &new_volume, NULL); + cur_volume = gtk_spin_button_get_value (GTK_SPIN_BUTTON (volume_spinbutton)); + if (fabs (cur_volume - new_volume) > 0.001) { + g_signal_handlers_block_by_func (volume_spinbutton, + volume_spinbutton_changed_cb, pipeline); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (volume_spinbutton), new_volume); + g_signal_handlers_unblock_by_func (volume_spinbutton, + volume_spinbutton_changed_cb, pipeline); + } +} + +static void +shot_cb (GtkButton * button, gpointer data) +{ + GstBuffer *buffer; + GstCaps *caps; + + /* convert to our desired format (RGB24) */ + caps = gst_caps_new_simple ("video/x-raw-rgb", + "bpp", G_TYPE_INT, 24, "depth", G_TYPE_INT, 24, + /* Note: we don't ask for a specific width/height here, so that + * videoscale can adjust dimensions from a non-1/1 pixel aspect + * ratio to a 1/1 pixel-aspect-ratio */ + "pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, + "endianness", G_TYPE_INT, G_BIG_ENDIAN, + "red_mask", G_TYPE_INT, 0xff0000, + "green_mask", G_TYPE_INT, 0x00ff00, + "blue_mask", G_TYPE_INT, 0x0000ff, NULL); + + /* convert the latest frame to the requested format */ + g_signal_emit_by_name (pipeline, "convert-frame", caps, &buffer); + gst_caps_unref (caps); + + if (buffer) { + GstCaps *caps; + GstStructure *s; + gboolean res; + gint width, height; + GdkPixbuf *pixbuf; + GError *error = NULL; + + /* get the snapshot buffer format now. We set the caps on the appsink so + * that it can only be an rgb buffer. The only thing we have not specified + * on the caps is the height, which is dependant on the pixel-aspect-ratio + * of the source material */ + caps = GST_BUFFER_CAPS (buffer); + if (!caps) { + g_warning ("could not get snapshot format\n"); + goto done; + } + s = gst_caps_get_structure (caps, 0); + + /* we need to get the final caps on the buffer to get the size */ + res = gst_structure_get_int (s, "width", &width); + res |= gst_structure_get_int (s, "height", &height); + if (!res) { + g_warning ("could not get snapshot dimension\n"); + goto done; + } + + /* create pixmap from buffer and save, gstreamer video buffers have a stride + * that is rounded up to the nearest multiple of 4 */ + pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buffer), + GDK_COLORSPACE_RGB, FALSE, 8, width, height, + GST_ROUND_UP_4 (width * 3), NULL, NULL); + + /* save the pixbuf */ + gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL); + + done: + gst_buffer_unref (buffer); + } +} + +/* called when the Step button is pressed */ +static void +step_cb (GtkButton * button, gpointer data) +{ + GstEvent *event; + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush, res; + gint active; + + active = gtk_combo_box_get_active (GTK_COMBO_BOX (format_combo)); + amount = + gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON + (step_amount_spinbutton)); + rate = gtk_spin_button_get_value (GTK_SPIN_BUTTON (step_rate_spinbutton)); + flush = TRUE; + + switch (active) { + case 0: + format = GST_FORMAT_BUFFERS; + break; + case 1: + format = GST_FORMAT_TIME; + amount *= GST_MSECOND; + break; + default: + format = GST_FORMAT_UNDEFINED; + break; + } + + event = gst_event_new_step (format, amount, rate, flush, FALSE); + + res = send_event (event); + + if (!res) { + g_print ("Sending step event failed\n"); + } +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static gboolean shuttling = FALSE; +static gdouble shuttle_rate = 0.0; +static gdouble play_rate = 1.0; + +static void +do_shuttle (GstElement * element) +{ + guint64 duration; + + if (shuttling) + duration = 40 * GST_MSECOND; + else + duration = -1; + + gst_element_send_event (element, + gst_event_new_step (GST_FORMAT_TIME, duration, shuttle_rate, FALSE, + FALSE)); +} + +static void +msg_sync_step_done (GstBus * bus, GstMessage * message, GstElement * element) +{ + GstFormat format; + guint64 amount; + gdouble rate; + gboolean flush; + gboolean intermediate; + guint64 duration; + gboolean eos; + + gst_message_parse_step_done (message, &format, &amount, &rate, &flush, + &intermediate, &duration, &eos); + + if (eos) { + g_print ("stepped till EOS\n"); + return; + } + + if (g_static_mutex_trylock (&state_mutex)) { + if (shuttling) + do_shuttle (element); + g_static_mutex_unlock (&state_mutex); + } else { + /* ignore step messages that come while we are doing a state change */ + g_print ("state change is busy\n"); + } +} + +static void +shuttle_toggled (GtkToggleButton * button, GstElement * element) +{ + gboolean active; + + active = gtk_toggle_button_get_active (button); + + if (active != shuttling) { + shuttling = active; + g_print ("shuttling %s\n", shuttling ? "active" : "inactive"); + if (active) { + shuttle_rate = 0.0; + play_rate = 1.0; + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } + } +} + +static void +shuttle_rate_switch (GstElement * element) +{ + GstSeekFlags flags; + GstEvent *s_event; + gboolean res; + + if (state == GST_STATE_PLAYING) { + /* pause when we need to */ + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } + + if (play_rate == 1.0) + play_rate = -1.0; + else + play_rate = 1.0; + + g_print ("rate changed to %lf %" GST_TIME_FORMAT "\n", play_rate, + GST_TIME_ARGS (position)); + + flags = GST_SEEK_FLAG_FLUSH; + flags |= GST_SEEK_FLAG_ACCURATE; + + if (play_rate >= 0.0) { + s_event = gst_event_new_seek (play_rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, position, + GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE); + } else { + s_event = gst_event_new_seek (play_rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, position); + } + res = send_event (s_event); + if (res) { + gst_element_get_state (element, NULL, NULL, SEEK_TIMEOUT); + } else { + g_print ("seek failed\n"); + } +} + +static void +shuttle_value_changed (GtkRange * range, GstElement * element) +{ + gdouble rate; + + rate = gtk_adjustment_get_value (shuttle_adjustment); + + if (rate == 0.0) { + g_print ("rate 0.0, pause\n"); + pause_cb (NULL, NULL); + gst_element_get_state (element, NULL, NULL, -1); + } else { + g_print ("rate changed %0.3g\n", rate); + + if ((rate < 0.0 && play_rate > 0.0) || (rate > 0.0 && play_rate < 0.0)) { + shuttle_rate_switch (element); + } + + shuttle_rate = ABS (rate); + if (state != GST_STATE_PLAYING) { + do_shuttle (element); + play_cb (NULL, NULL); + } + } +} + +static void +msg_async_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + GST_DEBUG ("async done"); + /* when we get ASYNC_DONE we can query position, duration and other + * properties */ + update_scale (pipeline); + + /* update the available streams */ + update_streams (pipeline); +} + +static void +msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + + /* We only care about state changed on the pipeline */ + if (s && GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) { + GstState old, new, pending; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + /* When state of the pipeline changes to paused or playing we start updating scale */ + if (new == GST_STATE_PLAYING) { + set_update_scale (TRUE); + } else { + set_update_scale (FALSE); + } + } +} + +static void +msg_segment_done (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + GstEvent *s_event; + GstSeekFlags flags; + gboolean res; + GstFormat format; + + GST_DEBUG ("position is %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + gst_message_parse_segment_done (message, &format, &position); + GST_DEBUG ("end of segment at %" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + + flags = 0; + /* in the segment-done callback we never flush as this would not make sense + * for seamless playback. */ + if (loop_seek) + flags |= GST_SEEK_FLAG_SEGMENT; + if (skip_seek) + flags |= GST_SEEK_FLAG_SKIP; + + s_event = gst_event_new_seek (rate, + GST_FORMAT_TIME, flags, GST_SEEK_TYPE_SET, G_GINT64_CONSTANT (0), + GST_SEEK_TYPE_SET, duration); + + GST_DEBUG ("restart loop with rate %lf to 0 / %" GST_TIME_FORMAT, + rate, GST_TIME_ARGS (duration)); + + res = send_event (s_event); + if (!res) + g_print ("segment seek failed\n"); +} + +/* in stream buffering mode we PAUSE the pipeline until we receive a 100% + * message */ +static void +do_stream_buffering (gint percent) +{ + gchar *bufstr; + + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + bufstr = g_strdup_printf ("Buffering...%d", percent); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, bufstr); + g_free (bufstr); + + if (percent == 100) { + /* a 100% message means buffering is done */ + buffering = FALSE; + /* if the desired state is playing, go back */ + if (state == GST_STATE_PLAYING) { + /* no state management needed for live pipelines */ + if (!is_live) { + fprintf (stderr, "Done buffering, setting pipeline to PLAYING ...\n"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } + gtk_statusbar_pop (GTK_STATUSBAR (statusbar), status_id); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Playing"); + } + } else { + /* buffering busy */ + if (buffering == FALSE && state == GST_STATE_PLAYING) { + /* we were not buffering but PLAYING, PAUSE the pipeline. */ + if (!is_live) { + fprintf (stderr, "Buffering, setting pipeline to PAUSED ...\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + } + } + buffering = TRUE; + } +} + +static void +do_download_buffering (gint percent) +{ + if (!buffering && percent < 100) { + gchar *bufstr; + + buffering = TRUE; + + bufstr = g_strdup_printf ("Downloading..."); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, bufstr); + g_free (bufstr); + + /* once we get a buffering message, we'll do the fill update */ + set_update_fill (TRUE); + + if (state == GST_STATE_PLAYING && !is_live) { + fprintf (stderr, "Downloading, setting pipeline to PAUSED ...\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + /* user has to manually start the playback */ + state = GST_STATE_PAUSED; + } + } +} + +static void +msg_buffering (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + gint percent; + + gst_message_parse_buffering (message, &percent); + + /* get more stats */ + gst_message_parse_buffering_stats (message, &mode, NULL, NULL, + &buffering_left); + + switch (mode) { + case GST_BUFFERING_DOWNLOAD: + do_download_buffering (percent); + break; + case GST_BUFFERING_LIVE: + is_live = TRUE; + case GST_BUFFERING_TIMESHIFT: + case GST_BUFFERING_STREAM: + do_stream_buffering (percent); + break; + } +} + +static void +msg_clock_lost (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + g_print ("clock lost! PAUSE and PLAY to select a new clock\n"); + if (state == GST_STATE_PLAYING) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } +} + +#ifdef HAVE_X + +static gulong embed_xid = 0; + +/* We set the xid here in response to the prepare-xwindow-id message via a + * bus sync handler because we don't know the actual videosink used from the + * start (as we don't know the pipeline, or bin elements such as autovideosink + * or gconfvideosink may be used which create the actual videosink only once + * the pipeline is started) */ +static GstBusSyncReply +bus_sync_handler (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + if ((GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name (message->structure, "prepare-xwindow-id")) { + GstElement *element = GST_ELEMENT (GST_MESSAGE_SRC (message)); + + g_print ("got prepare-xwindow-id, setting XID %lu\n", embed_xid); + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (element), + "force-aspect-ratio")) { + g_object_set (element, "force-aspect-ratio", TRUE, NULL); + } + + /* Should have been initialised from main thread before (can't use + * GDK_WINDOW_XID here with Gtk+ >= 2.18, because the sync handler will + * be called from a streaming thread and GDK_WINDOW_XID maps to more than + * a simple structure lookup with Gtk+ >= 2.18, where 'more' is stuff that + * shouldn't be done from a non-GUI thread without explicit locking). */ + g_assert (embed_xid != 0); + + gst_x_overlay_set_window_handle (GST_X_OVERLAY (element), embed_xid); + } + return GST_BUS_PASS; +} +#endif + +static gboolean +handle_expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data) +{ + if (state < GST_STATE_PAUSED) { + GtkAllocation allocation; + GdkWindow *window = gtk_widget_get_window (widget); + cairo_t *cr; + + gtk_widget_get_allocation (widget, &allocation); + cr = gdk_cairo_create (window); + cairo_set_source_rgb (cr, 0, 0, 0); + cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); + cairo_fill (cr); + cairo_destroy (cr); + } + return FALSE; +} + +static void +realize_cb (GtkWidget * widget, gpointer data) +{ +#if GTK_CHECK_VERSION(2,18,0) + { + GdkWindow *window = gtk_widget_get_window (widget); + + /* This is here just for pedagogical purposes, GDK_WINDOW_XID will call it + * as well */ + if (!gdk_window_ensure_native (window)) + g_error ("Couldn't create native window needed for GstXOverlay!"); + } +#endif + +#ifdef HAVE_X + { + GdkWindow *window = gtk_widget_get_window (video_window); + + embed_xid = GDK_WINDOW_XID (window); + g_print ("Window realize: video window XID = %lu\n", embed_xid); + } +#endif +} + +static void +msg_eos (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + message_received (bus, message, data); + + /* Set new uri for playerbins and continue playback */ + if (l && (pipeline_type == 14 || pipeline_type == 16)) { + stop_cb (NULL, NULL); + l = g_list_next (l); + if (l) { + playerbin_set_uri (GST_ELEMENT (data), l->data); + play_cb (NULL, NULL); + } + } +} + +static void +msg_step_done (GstBus * bus, GstMessage * message, GstPipeline * data) +{ + if (!shuttling) + message_received (bus, message, data); +} + +static void +connect_bus_signals (GstElement * pipeline) +{ + GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + +#ifdef HAVE_X + /* handle prepare-xwindow-id element message synchronously */ + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) bus_sync_handler, + pipeline); +#endif + + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + gst_bus_enable_sync_message_emission (bus); + + g_signal_connect (bus, "message::state-changed", + (GCallback) msg_state_changed, pipeline); + g_signal_connect (bus, "message::segment-done", (GCallback) msg_segment_done, + pipeline); + g_signal_connect (bus, "message::async-done", (GCallback) msg_async_done, + pipeline); + + g_signal_connect (bus, "message::new-clock", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::clock-lost", (GCallback) msg_clock_lost, + pipeline); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) msg_eos, pipeline); + g_signal_connect (bus, "message::tag", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::element", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::segment-done", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::buffering", (GCallback) msg_buffering, + pipeline); +// g_signal_connect (bus, "message::step-done", (GCallback) msg_step_done, +// pipeline); + g_signal_connect (bus, "message::step-start", (GCallback) msg_step_done, + pipeline); + g_signal_connect (bus, "sync-message::step-done", + (GCallback) msg_sync_step_done, pipeline); + + gst_object_unref (bus); +} + +/* Return GList of paths described in location string */ +static GList * +handle_wildcards (const gchar * location) +{ + GList *res = NULL; + gchar *path = g_path_get_dirname (location); + gchar *pattern = g_path_get_basename (location); + GPatternSpec *pspec = g_pattern_spec_new (pattern); + GDir *dir = g_dir_open (path, 0, NULL); + const gchar *name; + + g_print ("matching %s from %s\n", pattern, path); + + if (!dir) { + g_print ("opening directory %s failed\n", path); + goto out; + } + + while ((name = g_dir_read_name (dir)) != NULL) { + if (g_pattern_match_string (pspec, name)) { + res = g_list_append (res, g_strjoin ("/", path, name, NULL)); + g_print (" found clip %s\n", name); + } + } + + g_dir_close (dir); +out: + g_pattern_spec_free (pspec); + g_free (pattern); + g_free (path); + + return res; +} + +static void +delete_event_cb (void) +{ + stop_cb (NULL, NULL); + gtk_main_quit (); +} + +static void +print_usage (int argc, char **argv) +{ + gint i; + + g_print ("usage: %s \n", argv[0]); + g_print (" possible types:\n"); + + for (i = 0; i < NUM_TYPES; i++) { + g_print (" %d = %s\n", i, pipelines[i].name); + } +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *hbox, *vbox, *panel, *expander, *pb2vbox, *boxes, + *flagtable, *boxes2, *step; + GtkWidget *play_button, *pause_button, *stop_button, *shot_button; + GtkWidget *accurate_checkbox, *key_checkbox, *loop_checkbox, *flush_checkbox; + GtkWidget *scrub_checkbox, *play_scrub_checkbox; + GtkWidget *rate_label, *volume_label; + GOptionEntry options[] = { + {"stats", 's', 0, G_OPTION_ARG_NONE, &stats, + "Show pad stats", NULL}, + {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek, + "Seek on elements instead of pads", NULL}, + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Verbose properties", NULL}, + {NULL} + }; + GOptionContext *ctx; + GError *err = NULL; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new ("- test seeking in gsteamer"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + g_option_context_add_group (ctx, gtk_get_option_group (TRUE)); + + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + GST_DEBUG_CATEGORY_INIT (seek_debug, "seek", 0, "seek example"); + + if (argc != 3) { + print_usage (argc, argv); + exit (-1); + } + + pipeline_type = atoi (argv[1]); + + if (pipeline_type < 0 || pipeline_type >= NUM_TYPES) { + print_usage (argc, argv); + exit (-1); + } + + pipeline_spec = argv[2]; + + if (g_path_is_absolute (pipeline_spec) && + (g_strrstr (pipeline_spec, "*") != NULL || + g_strrstr (pipeline_spec, "?") != NULL)) { + paths = handle_wildcards (pipeline_spec); + } else { + paths = g_list_prepend (paths, g_strdup (pipeline_spec)); + } + + if (!paths) { + g_print ("opening %s failed\n", pipeline_spec); + exit (-1); + } + + l = paths; + + pipeline = pipelines[pipeline_type].func ((gchar *) l->data); + g_assert (pipeline); + + /* initialize gui elements ... */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + video_window = gtk_drawing_area_new (); + g_signal_connect (video_window, "expose-event", + G_CALLBACK (handle_expose_cb), NULL); + g_signal_connect (video_window, "realize", G_CALLBACK (realize_cb), NULL); + gtk_widget_set_double_buffered (video_window, FALSE); + + statusbar = gtk_statusbar_new (); + status_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "seek"); + gtk_statusbar_push (GTK_STATUSBAR (statusbar), status_id, "Stopped"); + hbox = gtk_hbox_new (FALSE, 0); + vbox = gtk_vbox_new (FALSE, 0); + flagtable = gtk_table_new (4, 2, FALSE); + gtk_container_set_border_width (GTK_CONTAINER (vbox), 3); + + /* media controls */ + play_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PLAY); + pause_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_PAUSE); + stop_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_STOP); + + /* seek flags */ + accurate_checkbox = gtk_check_button_new_with_label ("Accurate Seek"); + key_checkbox = gtk_check_button_new_with_label ("Key-unit Seek"); + loop_checkbox = gtk_check_button_new_with_label ("Loop"); + flush_checkbox = gtk_check_button_new_with_label ("Flush"); + scrub_checkbox = gtk_check_button_new_with_label ("Scrub"); + play_scrub_checkbox = gtk_check_button_new_with_label ("Play Scrub"); + skip_checkbox = gtk_check_button_new_with_label ("Play Skip"); + rate_spinbutton = gtk_spin_button_new_with_range (-100, 100, 0.1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (rate_spinbutton), 3); + rate_label = gtk_label_new ("Rate"); + + gtk_widget_set_tooltip_text (accurate_checkbox, + "accurate position is requested, this might be considerably slower for some formats"); + gtk_widget_set_tooltip_text (key_checkbox, + "seek to the nearest keyframe. This might be faster but less accurate"); + gtk_widget_set_tooltip_text (loop_checkbox, "loop playback"); + gtk_widget_set_tooltip_text (flush_checkbox, "flush pipeline after seeking"); + gtk_widget_set_tooltip_text (rate_spinbutton, "define the playback rate, " + "negative value trigger reverse playback"); + gtk_widget_set_tooltip_text (scrub_checkbox, "show images while seeking"); + gtk_widget_set_tooltip_text (play_scrub_checkbox, "play video while seeking"); + gtk_widget_set_tooltip_text (skip_checkbox, + "Skip frames while playing at high frame rates"); + + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (flush_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (scrub_checkbox), TRUE); + + gtk_spin_button_set_value (GTK_SPIN_BUTTON (rate_spinbutton), rate); + + /* step expander */ + { + GtkWidget *hbox; + + step = gtk_expander_new ("step options"); + hbox = gtk_hbox_new (FALSE, 0); + + format_combo = gtk_combo_box_text_new (); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (format_combo), + "frames"); + gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (format_combo), + "time (ms)"); + gtk_combo_box_set_active (GTK_COMBO_BOX (format_combo), 0); + gtk_box_pack_start (GTK_BOX (hbox), format_combo, FALSE, FALSE, 2); + + step_amount_spinbutton = gtk_spin_button_new_with_range (1, 1000, 1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_amount_spinbutton), 0); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_amount_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (hbox), step_amount_spinbutton, FALSE, FALSE, + 2); + + step_rate_spinbutton = gtk_spin_button_new_with_range (0.0, 100, 0.1); + gtk_spin_button_set_digits (GTK_SPIN_BUTTON (step_rate_spinbutton), 3); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (step_rate_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (hbox), step_rate_spinbutton, FALSE, FALSE, 2); + + step_button = gtk_button_new_from_stock (GTK_STOCK_MEDIA_FORWARD); + gtk_button_set_label (GTK_BUTTON (step_button), "Step"); + gtk_box_pack_start (GTK_BOX (hbox), step_button, FALSE, FALSE, 2); + + g_signal_connect (G_OBJECT (step_button), "clicked", G_CALLBACK (step_cb), + pipeline); + + /* shuttle scale */ + shuttle_checkbox = gtk_check_button_new_with_label ("Shuttle"); + gtk_box_pack_start (GTK_BOX (hbox), shuttle_checkbox, FALSE, FALSE, 2); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (shuttle_checkbox), FALSE); + g_signal_connect (shuttle_checkbox, "toggled", G_CALLBACK (shuttle_toggled), + pipeline); + + shuttle_adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, -3.00, 4.0, 0.1, 1.0, 1.0)); + shuttle_hscale = gtk_hscale_new (shuttle_adjustment); + gtk_scale_set_digits (GTK_SCALE (shuttle_hscale), 2); + gtk_scale_set_value_pos (GTK_SCALE (shuttle_hscale), GTK_POS_TOP); + g_signal_connect (shuttle_hscale, "value_changed", + G_CALLBACK (shuttle_value_changed), pipeline); + g_signal_connect (shuttle_hscale, "format_value", + G_CALLBACK (shuttle_format_value), pipeline); + + gtk_box_pack_start (GTK_BOX (hbox), shuttle_hscale, TRUE, TRUE, 2); + + gtk_container_add (GTK_CONTAINER (step), hbox); + } + + /* seek bar */ + adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, N_GRAD, 0.1, 1.0, 1.0)); + hscale = gtk_hscale_new (adjustment); + gtk_scale_set_digits (GTK_SCALE (hscale), 2); + gtk_scale_set_value_pos (GTK_SCALE (hscale), GTK_POS_RIGHT); + gtk_range_set_show_fill_level (GTK_RANGE (hscale), TRUE); + gtk_range_set_fill_level (GTK_RANGE (hscale), N_GRAD); + + g_signal_connect (hscale, "button_press_event", G_CALLBACK (start_seek), + pipeline); + g_signal_connect (hscale, "button_release_event", G_CALLBACK (stop_seek), + pipeline); + g_signal_connect (hscale, "format_value", G_CALLBACK (format_value), + pipeline); + + if (pipeline_type == 16) { + /* the playbin2 panel controls for the video/audio/subtitle tracks */ + panel = gtk_hbox_new (FALSE, 0); + video_combo = gtk_combo_box_text_new (); + audio_combo = gtk_combo_box_text_new (); + text_combo = gtk_combo_box_text_new (); + gtk_widget_set_sensitive (video_combo, FALSE); + gtk_widget_set_sensitive (audio_combo, FALSE); + gtk_widget_set_sensitive (text_combo, FALSE); + gtk_box_pack_start (GTK_BOX (panel), video_combo, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (panel), audio_combo, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (panel), text_combo, TRUE, TRUE, 2); + g_signal_connect (G_OBJECT (video_combo), "changed", + G_CALLBACK (video_combo_cb), pipeline); + g_signal_connect (G_OBJECT (audio_combo), "changed", + G_CALLBACK (audio_combo_cb), pipeline); + g_signal_connect (G_OBJECT (text_combo), "changed", + G_CALLBACK (text_combo_cb), pipeline); + /* playbin2 panel for flag checkboxes and volume/mute */ + boxes = gtk_hbox_new (FALSE, 0); + vis_checkbox = gtk_check_button_new_with_label ("Vis"); + video_checkbox = gtk_check_button_new_with_label ("Video"); + audio_checkbox = gtk_check_button_new_with_label ("Audio"); + text_checkbox = gtk_check_button_new_with_label ("Text"); + mute_checkbox = gtk_check_button_new_with_label ("Mute"); + download_checkbox = gtk_check_button_new_with_label ("Download"); + buffer_checkbox = gtk_check_button_new_with_label ("Buffer"); + volume_label = gtk_label_new ("Volume"); + volume_spinbutton = gtk_spin_button_new_with_range (0, 10.0, 0.1); + gtk_spin_button_set_value (GTK_SPIN_BUTTON (volume_spinbutton), 1.0); + gtk_box_pack_start (GTK_BOX (boxes), video_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), audio_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), text_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), vis_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), mute_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), download_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), buffer_checkbox, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), volume_label, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes), volume_spinbutton, TRUE, TRUE, 2); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (vis_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (audio_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (video_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (text_checkbox), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mute_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (download_checkbox), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (buffer_checkbox), FALSE); + g_signal_connect (G_OBJECT (vis_checkbox), "toggled", + G_CALLBACK (vis_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (audio_checkbox), "toggled", + G_CALLBACK (audio_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (video_checkbox), "toggled", + G_CALLBACK (video_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (text_checkbox), "toggled", + G_CALLBACK (text_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (mute_checkbox), "toggled", + G_CALLBACK (mute_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (download_checkbox), "toggled", + G_CALLBACK (download_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (buffer_checkbox), "toggled", + G_CALLBACK (buffer_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (volume_spinbutton), "value_changed", + G_CALLBACK (volume_spinbutton_changed_cb), pipeline); + /* playbin2 panel for snapshot */ + boxes2 = gtk_hbox_new (FALSE, 0); + shot_button = gtk_button_new_from_stock (GTK_STOCK_SAVE); + gtk_widget_set_tooltip_text (shot_button, + "save a screenshot .png in the current directory"); + g_signal_connect (G_OBJECT (shot_button), "clicked", G_CALLBACK (shot_cb), + pipeline); + vis_combo = gtk_combo_box_text_new (); + g_signal_connect (G_OBJECT (vis_combo), "changed", + G_CALLBACK (vis_combo_cb), pipeline); + gtk_widget_set_sensitive (vis_combo, FALSE); + gtk_box_pack_start (GTK_BOX (boxes2), shot_button, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (boxes2), vis_combo, TRUE, TRUE, 2); + + /* fill the vis combo box and the array of factories */ + init_visualization_features (); + } else { + panel = boxes = boxes2 = NULL; + } + + /* do the packing stuff ... */ + gtk_window_set_default_size (GTK_WINDOW (window), 250, 96); + /* FIXME: can we avoid this for audio only? */ + gtk_widget_set_size_request (GTK_WIDGET (video_window), -1, + DEFAULT_VIDEO_HEIGHT); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_box_pack_start (GTK_BOX (vbox), video_window, TRUE, TRUE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), flagtable, FALSE, FALSE, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), accurate_checkbox, 0, 1, 0, + 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), flush_checkbox, 1, 2, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), loop_checkbox, 2, 3, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), key_checkbox, 0, 1, 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), scrub_checkbox, 1, 2, 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), play_scrub_checkbox, 2, 3, + 1, 2); + gtk_table_attach_defaults (GTK_TABLE (flagtable), skip_checkbox, 3, 4, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_label, 4, 5, 0, 1); + gtk_table_attach_defaults (GTK_TABLE (flagtable), rate_spinbutton, 4, 5, 1, + 2); + if (panel && boxes && boxes2) { + expander = gtk_expander_new ("playbin2 options"); + pb2vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (pb2vbox), panel, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (pb2vbox), boxes, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (pb2vbox), boxes2, FALSE, FALSE, 2); + gtk_container_add (GTK_CONTAINER (expander), pb2vbox); + gtk_box_pack_start (GTK_BOX (vbox), expander, FALSE, FALSE, 2); + } + gtk_box_pack_start (GTK_BOX (vbox), step, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hscale, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 2); + + /* connect things ... */ + g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), + pipeline); + g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), + pipeline); + g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), + pipeline); + g_signal_connect (G_OBJECT (accurate_checkbox), "toggled", + G_CALLBACK (accurate_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (key_checkbox), "toggled", + G_CALLBACK (key_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (loop_checkbox), "toggled", + G_CALLBACK (loop_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (flush_checkbox), "toggled", + G_CALLBACK (flush_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (scrub_checkbox), "toggled", + G_CALLBACK (scrub_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (play_scrub_checkbox), "toggled", + G_CALLBACK (play_scrub_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (skip_checkbox), "toggled", + G_CALLBACK (skip_toggle_cb), pipeline); + g_signal_connect (G_OBJECT (rate_spinbutton), "value_changed", + G_CALLBACK (rate_spinbutton_changed_cb), pipeline); + + g_signal_connect (G_OBJECT (window), "delete-event", delete_event_cb, NULL); + + /* show the gui. */ + gtk_widget_show_all (window); + + /* realize window now so that the video window gets created and we can + * obtain its XID before the pipeline is started up and the videosink + * asks for the XID of the window to render onto */ + gtk_widget_realize (window); + +#ifdef HAVE_X + /* we should have the XID now */ + g_assert (embed_xid != 0); +#endif + + if (verbose) { + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + } + + connect_bus_signals (pipeline); + gtk_main (); + + g_print ("NULL pipeline\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + + g_print ("free pipeline\n"); + gst_object_unref (pipeline); + + g_list_foreach (paths, (GFunc) g_free, NULL); + g_list_free (paths); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping.c b/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping.c new file mode 100644 index 0000000..6f6997f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping.c @@ -0,0 +1,124 @@ +/* GStreamer + * + * stepping.c: stepping sample application + * + * Copyright (C) 2009 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +static GMainLoop *loop; + +static gdouble period = 0.0; + +static gboolean +do_step (GstElement * bin) +{ + gdouble length; + + length = sin (period); + + period += M_PI / 40; + + length += 1.1; + length *= 100 * GST_MSECOND; + + gst_element_send_event (bin, + gst_event_new_step (GST_FORMAT_TIME, length, 1.0, TRUE, FALSE)); + + return FALSE; +} + +static gboolean +handle_message (GstBus * bus, GstMessage * message, gpointer data) +{ + GstElement *bin = GST_ELEMENT_CAST (data); + + switch (message->type) { + case GST_MESSAGE_EOS: + g_message ("got EOS"); + g_main_loop_quit (loop); + break; + case GST_MESSAGE_WARNING: + case GST_MESSAGE_ERROR: + { + GError *gerror; + gchar *debug; + + if (message->type == GST_MESSAGE_ERROR) + gst_message_parse_error (message, &gerror, &debug); + else + gst_message_parse_warning (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_ASYNC_DONE: + g_timeout_add (40, (GSourceFunc) do_step, bin); + break; + default: + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + GstElement *bin; + GstBus *bus; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* create a new bin to hold the elements */ + bin = gst_element_factory_make ("playbin2", "bin"); + g_assert (bin); + g_object_set (bin, "uri", argv[1], NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (bin)); + gst_bus_add_watch (bus, handle_message, bin); + + /* go to the PAUSED state and wait for preroll */ + g_message ("prerolling first frame"); + gst_element_set_state (bin, GST_STATE_PAUSED); + gst_element_get_state (bin, NULL, NULL, -1); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + g_message ("finished"); + + /* stop the bin */ + gst_element_set_state (bin, GST_STATE_NULL); + + g_main_loop_unref (loop); + gst_object_unref (bus); + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping2.c b/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping2.c new file mode 100644 index 0000000..8cea180 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/seek/stepping2.c @@ -0,0 +1,142 @@ +/* GStreamer + * + * stepping.c: stepping sample application + * + * Copyright (C) 2009 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +static GMainLoop *loop; + +static gdouble period = 0.0; + +static void +do_step (GstElement * bin) +{ + gdouble rate; + + rate = sin (period); + + period += M_PI / 150; + + rate += 1.2; + + gst_element_send_event (bin, + gst_event_new_step (GST_FORMAT_TIME, 40 * GST_MSECOND, rate, FALSE, + FALSE)); +} + +static void +handle_sync_message (GstBus * bus, GstMessage * message, gpointer data) +{ + GstElement *bin; + + bin = GST_ELEMENT_CAST (data); + + switch (message->type) { + case GST_MESSAGE_STEP_DONE: + do_step (bin); + break; + default: + break; + } +} + +static void +handle_message (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (message->type) { + case GST_MESSAGE_EOS: + g_message ("got EOS"); + g_main_loop_quit (loop); + break; + case GST_MESSAGE_WARNING: + case GST_MESSAGE_ERROR: + { + GError *gerror; + gchar *debug; + + if (message->type == GST_MESSAGE_ERROR) + gst_message_parse_error (message, &gerror, &debug); + else + gst_message_parse_warning (message, &gerror, &debug); + + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + if (message->type == GST_MESSAGE_ERROR) + g_main_loop_quit (loop); + break; + } + default: + break; + } +} + +int +main (int argc, char *argv[]) +{ + GstElement *bin; + GstBus *bus; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* create a new bin to hold the elements */ + bin = gst_element_factory_make ("playbin2", "bin"); + g_assert (bin); + g_object_set (bin, "uri", argv[1], NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (bin)); + gst_bus_add_signal_watch (bus); + gst_bus_enable_sync_message_emission (bus); + + g_signal_connect (bus, "message", (GCallback) handle_message, bin); + g_signal_connect (bus, "sync-message", (GCallback) handle_sync_message, bin); + + /* go to the PAUSED state and wait for preroll */ + g_message ("prerolling first frame"); + gst_element_set_state (bin, GST_STATE_PAUSED); + gst_element_get_state (bin, NULL, NULL, -1); + + /* queue step */ + do_step (bin); + + gst_element_set_state (bin, GST_STATE_PLAYING); + + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + g_message ("finished"); + + /* stop the bin */ + gst_element_set_state (bin, GST_STATE_NULL); + + g_main_loop_unref (loop); + gst_object_unref (bus); + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/snapshot/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/.gitignore new file mode 100644 index 0000000..a701b4c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/.gitignore @@ -0,0 +1,2 @@ +snapshot +snapshot.png diff --git a/gst-plugins-base-subtitles0.10/tests/examples/snapshot/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/Makefile.am new file mode 100644 index 0000000..16830ee --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/Makefile.am @@ -0,0 +1,10 @@ +if HAVE_GTK +GTK_EXAMPLES=snapshot +endif + +examples = $(GTK_EXAMPLES) + +noinst_PROGRAMS = $(examples) + +LIBS = $(GST_LIBS) $(GTK_LIBS) +AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/examples/snapshot/snapshot.c b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/snapshot.c new file mode 100644 index 0000000..14f2809 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/snapshot/snapshot.c @@ -0,0 +1,151 @@ +/* GStreamer snapshot example + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include + +#define CAPS "video/x-raw-rgb,width=160,pixel-aspect-ratio=1/1,bpp=(int)24,depth=(int)24,endianness=(int)4321,red_mask=(int)0xff0000, green_mask=(int)0x00ff00, blue_mask=(int)0x0000ff" + +int +main (int argc, char *argv[]) +{ + GstElement *pipeline, *sink; + gint width, height; + GstBuffer *buffer; + gchar *descr; + GError *error = NULL; + GdkPixbuf *pixbuf; + gint64 duration, position; + GstFormat format; + GstStateChangeReturn ret; + gboolean res; + + gst_init (&argc, &argv); + + if (argc != 2) { + g_print ("usage: %s \n Writes snapshot.png in the current directory\n", + argv[0]); + exit (-1); + } + + /* create a new pipeline */ + descr = + g_strdup_printf ("uridecodebin uri=%s ! ffmpegcolorspace ! videoscale ! " + " appsink name=sink caps=\"" CAPS "\"", argv[1]); + pipeline = gst_parse_launch (descr, &error); + + if (error != NULL) { + g_print ("could not construct pipeline: %s\n", error->message); + g_error_free (error); + exit (-1); + } + + /* get sink */ + sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); + + /* set to PAUSED to make the first frame arrive in the sink */ + ret = gst_element_set_state (pipeline, GST_STATE_PAUSED); + switch (ret) { + case GST_STATE_CHANGE_FAILURE: + g_print ("failed to play the file\n"); + exit (-1); + case GST_STATE_CHANGE_NO_PREROLL: + /* for live sources, we need to set the pipeline to PLAYING before we can + * receive a buffer. We don't do that yet */ + g_print ("live sources not supported yet\n"); + exit (-1); + default: + break; + } + /* This can block for up to 5 seconds. If your machine is really overloaded, + * it might time out before the pipeline prerolled and we generate an error. A + * better way is to run a mainloop and catch errors there. */ + ret = gst_element_get_state (pipeline, NULL, NULL, 5 * GST_SECOND); + if (ret == GST_STATE_CHANGE_FAILURE) { + g_print ("failed to play the file\n"); + exit (-1); + } + + /* get the duration */ + format = GST_FORMAT_TIME; + gst_element_query_duration (pipeline, &format, &duration); + + if (duration != -1) + /* we have a duration, seek to 5% */ + position = duration * 5 / 100; + else + /* no duration, seek to 1 second, this could EOS */ + position = 1 * GST_SECOND; + + /* seek to the a position in the file. Most files have a black first frame so + * by seeking to somewhere else we have a bigger chance of getting something + * more interesting. An optimisation would be to detect black images and then + * seek a little more */ + gst_element_seek_simple (pipeline, GST_FORMAT_TIME, + GST_SEEK_FLAG_KEY_UNIT | GST_SEEK_FLAG_FLUSH, position); + + /* get the preroll buffer from appsink, this block untils appsink really + * prerolls */ + g_signal_emit_by_name (sink, "pull-preroll", &buffer, NULL); + + /* if we have a buffer now, convert it to a pixbuf. It's possible that we + * don't have a buffer because we went EOS right away or had an error. */ + if (buffer) { + GstCaps *caps; + GstStructure *s; + + /* get the snapshot buffer format now. We set the caps on the appsink so + * that it can only be an rgb buffer. The only thing we have not specified + * on the caps is the height, which is dependant on the pixel-aspect-ratio + * of the source material */ + caps = GST_BUFFER_CAPS (buffer); + if (!caps) { + g_print ("could not get snapshot format\n"); + exit (-1); + } + s = gst_caps_get_structure (caps, 0); + + /* we need to get the final caps on the buffer to get the size */ + res = gst_structure_get_int (s, "width", &width); + res |= gst_structure_get_int (s, "height", &height); + if (!res) { + g_print ("could not get snapshot dimension\n"); + exit (-1); + } + + /* create pixmap from buffer and save, gstreamer video buffers have a stride + * that is rounded up to the nearest multiple of 4 */ + pixbuf = gdk_pixbuf_new_from_data (GST_BUFFER_DATA (buffer), + GDK_COLORSPACE_RGB, FALSE, 8, width, height, + GST_ROUND_UP_4 (width * 3), NULL, NULL); + + /* save the pixbuf */ + gdk_pixbuf_save (pixbuf, "snapshot.png", "png", &error, NULL); + } else { + g_print ("could not make snapshot\n"); + } + + /* cleanup and exit */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/v4l/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/v4l/.gitignore new file mode 100644 index 0000000..da0c4eb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/v4l/.gitignore @@ -0,0 +1 @@ +probe diff --git a/gst-plugins-base-subtitles0.10/tests/examples/v4l/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/v4l/Makefile.am new file mode 100644 index 0000000..6132cdc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/v4l/Makefile.am @@ -0,0 +1,10 @@ +noinst_PROGRAMS = probe + +probe_SOURCES = probe.c +probe_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) +probe_LDFLAGS = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) \ + $(GST_BASE_LIBS) $(GST_LIBS) + diff --git a/gst-plugins-base-subtitles0.10/tests/examples/v4l/probe.c b/gst-plugins-base-subtitles0.10/tests/examples/v4l/probe.c new file mode 100644 index 0000000..435aeac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/v4l/probe.c @@ -0,0 +1,85 @@ +/* GStreamer + * Copyright (C) 2009 Filippo Argiolas + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +int +main (int argc, char *argv[]) +{ + GstElement *src, *sink; + GstElement *bin; + GstPropertyProbe *probe = NULL; + const GParamSpec *pspec = NULL; + GValueArray *array = NULL; + gint i, ret; + GValue *value; + const gchar *device; + gchar *name; + guint flags; + + gst_init (&argc, &argv); + + bin = gst_pipeline_new ("pipeline"); + g_assert (bin); + + src = gst_element_factory_make ("v4lsrc", "v4l_source"); + g_assert (src); + sink = gst_element_factory_make ("fakesink", "fake_sink"); + g_assert (sink); + + /* add objects to the main pipeline */ + gst_bin_add_many (GST_BIN (bin), src, sink, NULL); + /* link the elements */ + gst_element_link_many (src, sink, NULL); + + /* probe devices */ + g_print ("Probing devices with propertyprobe...\n"); + probe = GST_PROPERTY_PROBE (src); + pspec = gst_property_probe_get_property (probe, "device"); + array = gst_property_probe_probe_and_get_values (probe, pspec); + + if (!array) { + g_print ("No device found\n"); + exit (1); + } + + for (i = 0; i < array->n_values; i++) { + value = g_value_array_get_nth (array, i); + device = g_value_get_string (value); + g_print ("Device: %s\n", device); + g_object_set_property (G_OBJECT (src), "device", value); + gst_element_set_state (bin, GST_STATE_READY); + ret = gst_element_get_state (bin, NULL, NULL, 10 * GST_SECOND); + if (ret != GST_STATE_CHANGE_SUCCESS) { + g_print ("Couldn't set STATE_READY\n"); + continue; + } + g_object_get (G_OBJECT (src), "device-name", &name, NULL); + g_print ("Name: %s\n", name); + g_free (name); + g_object_get (G_OBJECT (src), "flags", &flags, NULL); + g_print ("Flags: 0x%08X\n", flags); + gst_element_set_state (bin, GST_STATE_NULL); + g_print ("\n"); + } + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/examples/volume/.gitignore b/gst-plugins-base-subtitles0.10/tests/examples/volume/.gitignore new file mode 100644 index 0000000..4833bbb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/volume/.gitignore @@ -0,0 +1 @@ +volume diff --git a/gst-plugins-base-subtitles0.10/tests/examples/volume/Makefile.am b/gst-plugins-base-subtitles0.10/tests/examples/volume/Makefile.am new file mode 100644 index 0000000..7b2f067 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/volume/Makefile.am @@ -0,0 +1,6 @@ +if HAVE_GTK +noinst_PROGRAMS = volume +volume_SOURCES = volume.c +volume_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) -D_GNU_SOURCE +volume_LDADD = $(GST_LIBS) $(GTK_LIBS) $(LIBM) +endif diff --git a/gst-plugins-base-subtitles0.10/tests/examples/volume/volume.c b/gst-plugins-base-subtitles0.10/tests/examples/volume/volume.c new file mode 100644 index 0000000..59e4981 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/examples/volume/volume.c @@ -0,0 +1,172 @@ +/* GStreamer + * + * volume.c: sample application to change the volume of a pipeline + * + * Copyright (C) <2004> Thomas Vander Stichele + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include + +/* global pointer for the scale widget */ +GtkWidget *elapsed; +GtkWidget *scale; + +#ifndef M_LN10 +#define M_LN10 (log(10.0)) +#endif + +static void +value_changed_callback (GtkWidget * widget, GstElement * volume) +{ + gdouble value; + gdouble level; + + value = gtk_range_get_value (GTK_RANGE (widget)); + level = exp (value / 20.0 * M_LN10); + g_print ("Value: %f dB, level: %f\n", value, level); + g_object_set (volume, "volume", level, NULL); +} + +static void +setup_gui (GstElement * volume) +{ + GtkWidget *window; + GtkWidget *vbox; + GtkWidget *label, *hbox; + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (window, "destroy", gtk_main_quit, NULL); + + vbox = gtk_vbox_new (TRUE, 0); + gtk_container_add (GTK_CONTAINER (window), vbox); + + /* elapsed widget */ + hbox = gtk_hbox_new (TRUE, 0); + label = gtk_label_new ("Elapsed"); + elapsed = gtk_label_new ("0.000"); + gtk_container_add (GTK_CONTAINER (hbox), label); + gtk_container_add (GTK_CONTAINER (hbox), elapsed); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + + /* volume */ + hbox = gtk_hbox_new (TRUE, 0); + label = gtk_label_new ("volume"); + gtk_container_add (GTK_CONTAINER (hbox), label); + scale = gtk_hscale_new_with_range (-90.0, 10.0, 0.2); + gtk_range_set_value (GTK_RANGE (scale), 0.0); + gtk_widget_set_size_request (scale, 100, -1); + gtk_container_add (GTK_CONTAINER (hbox), scale); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + g_signal_connect (scale, "value-changed", + G_CALLBACK (value_changed_callback), volume); + + gtk_widget_show_all (GTK_WIDGET (window)); +} + +static void +message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + g_print ("message from \"%s\" (%s): ", + GST_STR_NULL (GST_ELEMENT_NAME (GST_MESSAGE_SRC (message))), + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + if (s) { + gchar *sstr; + + sstr = gst_structure_to_string (s); + g_print ("%s\n", sstr); + g_free (sstr); + } else { + g_print ("no message details\n"); + } +} + +static void +eos_message_received (GstBus * bus, GstMessage * message, + GstPipeline * pipeline) +{ + message_received (bus, message, pipeline); + gtk_main_quit (); +} + +int +main (int argc, char *argv[]) +{ + + GstElement *pipeline = NULL; + +#ifndef GST_DISABLE_PARSE + GError *error = NULL; +#endif + GstElement *volume; + GstBus *bus; + +#ifdef GST_DISABLE_PARSE + g_print ("GStreamer was built without pipeline parsing capabilities.\n"); + g_print + ("Please rebuild GStreamer with pipeline parsing capabilities activated to use this example.\n"); + return 1; +#else + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + pipeline = gst_parse_launchv ((const gchar **) &argv[1], &error); + if (error) { + g_print ("pipeline could not be constructed: %s\n", error->message); + g_print ("Please give a complete pipeline with a 'volume' element.\n"); + g_print ("Example: audiotestsrc ! volume ! %s\n", DEFAULT_AUDIOSINK); + g_error_free (error); + return 1; + } +#endif + volume = gst_bin_get_by_name (GST_BIN (pipeline), "volume0"); + if (volume == NULL) { + g_print ("Please give a pipeline with a 'volume' element in it\n"); + return 1; + } + + /* setup message handling */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::error", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::warning", (GCallback) message_received, + pipeline); + g_signal_connect (bus, "message::eos", (GCallback) eos_message_received, + pipeline); + + /* setup GUI */ + setup_gui (volume); + + /* go to main loop */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + gtk_main (); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/files/623663.mts b/gst-plugins-base-subtitles0.10/tests/files/623663.mts new file mode 100644 index 0000000000000000000000000000000000000000..482ddf7f74e9347a9b128959d8b840bf1df717d8 GIT binary patch literal 4000 zcmdUxc{r5YAHdIGn3>2-go&GB4A(7Dq%38ODOKIc8pbH3lRe9k$a=XqZM#EZ?uAYgt0LLiA0v!L2I#EVHo%gc%aoB)GF ztpy-OGZUr|tmRG3v~-zbVme}=b9Gk#U)&}@WQLfNm9Zd7fQO(pevAjIdW`-J2_T{Y zMx93d7x})oG$6?k&9MkV32cyb>#Fki`u}KoK*CqS{=@FCQ~ybQ60rZcb?d*Cx-NYF zo7V05TWxRt$A9I#)$t$A@9*&dt7&=IpH1u5ABKS$?2pX4^@m~7`;R}`A(8XnyRRQD z4+6wBV1H!Rtv{@1isk`0`0It}1AtkL*$I$WggAgCUt0SYLcW*82pl>zXgyK`AIf?!3NjG=A!^X^18PT z)y@X3AVR<*@e;TL_<$B61O-BXRaIiHgTujIz>Dj~^kH#2BK;C@a}tji0aJ)-0RBHC zLShXXF55+#9$D|$&Z}BJ>9-4CR8h!)e3pjUe zYu%DGf)$j~rHLFbN-N3|w>$MxS;}|-MmFt@Hjvt2B)JW7IMw-M)t)Iq`I9KEm8fFt z6k2V)vRbg+8@KUSioR3bN-J7Ua)8x11@p_atSn5oy#|pxdDfa&JPv1phTOEo#5mCw zzW*oGxu>5zYOZ?PLgEd#j}#x7Mlkn-(scoP;@6gGb3R9NxU z`ue>dWnGJl+5P#y^|afjpNQlIFg`R=r!`GQV@8-KFO5jvwbZ!w_3W<|PAx>)9c{my zHVZGjIFvKcrOwOm9q~S8&#vt3alC>%YE6ZNr+3F8bp=>}3hG$wkLMP1!$lrZ2YK1} zIcX|jwI{;-vKf(0swVz@45Q5Hw3w}fWt)GJCsn+9p5K%%->usDD3;!<$$itfqh?QX zp2-K*lE;y3i;bmMr%LbK$PE7KbsxFd)ZV{4h9vn4Qqmu<)Uk5r#dp1M$Wf`E2Wiv6 zsIL4!XK?<#^QleG_r)E0a4?nWMtg00jh|_gSf1{1tK6Ty^X?7ady)H7h(ua8G3)-x zi_E7@{19=u?Lxi$xz4gW^?5{J@9BjT+E;S#8)OtDppU=HzN6X=Slt>h|K?-#Gx5(I ziTNQtk&}wvY9dL^Tq*R#FnXR7FU?(1seG^a#63zoHSqA3-CT?OH2wD1Lyyr7lI_SS zr4&naUC_+ANUP`W4flo&AtyCyow*JU`(T1q|5bKMq@d~A$4uls-J5Ny9UK9kxy;&T zuUqVL(P_5vEVb3=FCkIl78u^D#JokR){)Y)HnJXqL~Z#d>}Ovzxi0hc;Xq^Y6?@q@ zibG6L=fQ2un+dCgEZT7so`LCG24MBo!TfR!Sy>$gw+m}b)JD&1;5R5{*v-=?Hf&l&F#( z#7mkgdViPC$*ouCR|GS*F0`19F29Q-VD6#c#6RbaW76#)h*XC z&TPk3(lw}ka`3{O4HQ8?mXo`u8kvBlc9DjcuU(b%x6^1wLMlZnBu>rv!(+g|5~ zq3rZIFO2!*K+S;sUpd@mi_N1Ed+$W_5+traH9yXz?%%VzTnJd7mtcN{WNNTUpCd60 zT}$vnEH)qVmfRZN_V8;=&dCH$`$U%iWr@QD^?s^{9IOKNZMrnj)$QsaSKt6G?Qb+7J^N|~~NGu9p$n03jz$K5_#q9WP|1s&azJk92lPS$$ literal 0 HcmV?d00001 diff --git a/gst-plugins-base-subtitles0.10/tests/files/Makefile.am b/gst-plugins-base-subtitles0.10/tests/files/Makefile.am new file mode 100644 index 0000000..ca997a2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/files/Makefile.am @@ -0,0 +1,4 @@ +EXTRA_DIST = \ + 623663.mts \ + hls.m3u8 \ + partialframe.mjpeg diff --git a/gst-plugins-base-subtitles0.10/tests/files/hls.m3u8 b/gst-plugins-base-subtitles0.10/tests/files/hls.m3u8 new file mode 100644 index 0000000..3acce06 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/files/hls.m3u8 @@ -0,0 +1,15 @@ +#EXTM3U +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=246221 +0240/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=38872 +0064/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=153059 +0150/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=455394 +0440/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=650356 +0640/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=861738 +0840/prog_index.m3u8 +#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1258987 +1240/prog_index.m3u8 diff --git a/gst-plugins-base-subtitles0.10/tests/files/partialframe.mjpeg b/gst-plugins-base-subtitles0.10/tests/files/partialframe.mjpeg new file mode 100644 index 0000000000000000000000000000000000000000..fe8621e1f5ebc8990dd2d11b061fc922c39c1327 GIT binary patch literal 1600 zcma)yeKga19LK-ES*Dw0Qq3t^HI1o`DbHL}nP<0jEvqXkSstbtS%v1Qhg)mS5+z0+ z8k3}CT-CTLdG3kH!pb(Sj4sWM%I-SncJ8@<-TOM9_xXH2uk+UQYox%?o#c&&0DzWD zwHeU71~{OF8bzag`~UV*ts;K&S~|5E)<&fn1aJT}5|9a?{{ajJLE3>}-}&eIroZ#A z%J=GjZcP(F>VZ$NCpyq707F7LNJujP^mQQZqk{x)U=HTiGxN{~dns%J1BzlDrHJ`r zo=%NfW`@{Ul34318BnSBRKW*1i#`&QmNdApVs(iZW)u(jfSt8j@$!I!Hj{RfT* zBB-y)cSXNthONAi(Kd6_QITE1RrpY&uHO+=Jv>5uhnr+f&dj9{Yo8gGf5AU13hK^gb<-wxd8xx~*JMWj8Z-^GA z*r_$()PT(I*4iZ*uoiS!M(rrd)Q&~Vf>>YdSe}HU6e81OHR;nJ8fDBrt(-NUZV?0|s2+E8APcy`i6?zhuyiJIgk8u|38v1%)31pZ*#m&pVJ z{+d+lV4m|Ir~TN$t9i6F&HWIR_CsPSzLDo`He=#|5%ll^srRRu$CN1(b!R)D;pMru zLpM~|Ln3C&RXioLJZAxenw6!%Czl6LkH$#TPM}agma3=J71Sd5zN-Y1lG6%C zSnPaO!pjCLi-+d78F$3PQ&VF`QHOlVC8gl+5yx;!0P9f@B(wg;Q9ITFN{P z!?qX}$>K0jc3sfXSWzn{Q%lXCS6pcx6Zu%?xOF8uavJM2lJjS3j~R;?n9W z!R3`lV5MvV1{^`5r~3FdeukzuvWmxo@K!h@ku&Z->^2h#!ja0f^Hy|L3B^8X&}w#% z2K+decLpygJJ{w?_3`=c5Dnl|(%vy*KryFrFWYuSyMZ2>m4nXefhWp2a18alBJjcZ zg=0o$E(O)`C1`oK7K*{rZ$}-BrQM zq3QRHLPa#Aqmf#c@a)-euJV%u>m?~->#O5RWc7}EuJ;yRiHYN51lCxdPqgk>aaTAf zwZs?^ELpr%)@(-8b(t#s>&H9(vDe2hYQVzl{x@Ef`IAF;Pw+_=*>#~7P`^tZ5}A!W z5wmm$4>gJ!L7?;TScvwdv@{1B7aM%-Nh`wqq&I2}f`dqje1mI=Y-=r!(g5>>!jK<# zX9eaJsMZ$GTCEqWtM_)%Btlio;(DjMB@P>)<``bRNi!5ToYD2F%Ne%}dmMQtxsyih zr4ilRnwpjQ6g$C-b24t9s=DJ^VPEcQ<5ly<$@eFAyJ4B4fP3&|^W4q+Fv(SaF4}%u zfvLed6I`S@F5!7$JP!b&-ZjnODK1m>6Cd*JM(p8hb4ho;9*in`Tvg1TCP~zDxpX(XZAFNSo|i(Mdxn1h(!%d{8bwb! b9k%h@^e%|A3@4w9m@-gEx^?yT*M|QE7_!0H literal 0 HcmV?d00001 diff --git a/gst-plugins-base-subtitles0.10/tests/icles/.gitignore b/gst-plugins-base-subtitles0.10/tests/icles/.gitignore new file mode 100644 index 0000000..bd175b1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/.gitignore @@ -0,0 +1,12 @@ +audio-trickplay +input-selector-test +output-selector-test +playbin-text +position-formats +stress-playbin +stress-xoverlay +test-textoverlay +test-scale +test-box +test-colorkey +test-xoverlay diff --git a/gst-plugins-base-subtitles0.10/tests/icles/Makefile.am b/gst-plugins-base-subtitles0.10/tests/icles/Makefile.am new file mode 100644 index 0000000..d7a3236 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/Makefile.am @@ -0,0 +1,82 @@ +SUBDIRS = playback +DIST_SUBDIRS = playback + +if USE_X +X_TESTS = stress-xoverlay + +stress_xoverlay_SOURCES = stress-xoverlay.c +stress_xoverlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) +stress_xoverlay_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la + +if HAVE_GTK_X11 +X_TESTS += test-colorkey test-xoverlay + +test_colorkey_SOURCES = test-colorkey.c +test_colorkey_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) $(GTK_CFLAGS) +test_colorkey_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) $(GTK_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la + +test_xoverlay_SOURCES = test-xoverlay.c +test_xoverlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(X_CFLAGS) $(GTK_CFLAGS) +test_xoverlay_LDADD = $(GST_LIBS) $(X_LIBS) $(LIBM) $(GTK_LIBS) \ + $(top_builddir)/gst-libs/gst/interfaces/libgstinterfaces-$(GST_MAJORMINOR).la +endif + +output_selector_test_SOURCES = output-selector-test.c +output_selector_test_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +output_selector_test_LDADD = $(GST_LIBS) +output_selector_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +input_selector_test_SOURCES = input-selector-test.c +input_selector_test_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +input_selector_test_LDADD = $(GST_LIBS) +input_selector_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) + +X_TESTS += output-selector-test input-selector-test + +else +X_TESTS = +endif + +if USE_PANGO +PANGO_TESTS = test-textoverlay + +test_textoverlay_SOURCES = test-textoverlay.c +test_textoverlay_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +test_textoverlay_LDADD = $(GST_LIBS) $(LIBM) + +else +PANGO_TESTS = +endif + +audio_trickplay_SOURCES = audio-trickplay.c +audio_trickplay_CFLAGS = $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) +audio_trickplay_LDADD = $(GST_CONTROLLER_LIBS) $(GST_LIBS) $(LIBM) + +playbin_text_SOURCES = playbin-text.c +playbin_text_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +playbin_text_LDADD = $(GST_LIBS) $(LIBM) + +position_formats_SOURCES = position-formats.c +position_formats_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +position_formats_LDADD = $(GST_LIBS) $(LIBM) + +stress_playbin_SOURCES = stress-playbin.c +stress_playbin_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +stress_playbin_LDADD = $(GST_LIBS) $(LIBM) + +test_scale_SOURCES = test-scale.c +test_scale_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +test_scale_LDADD = $(GST_LIBS) $(LIBM) + +test_box_SOURCES = test-box.c +test_box_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +test_box_LDADD = $(GST_LIBS) $(LIBM) + +noinst_PROGRAMS = $(X_TESTS) $(PANGO_TESTS) \ + audio-trickplay playbin-text position-formats stress-playbin \ + test-scale test-box diff --git a/gst-plugins-base-subtitles0.10/tests/icles/audio-trickplay.c b/gst-plugins-base-subtitles0.10/tests/icles/audio-trickplay.c new file mode 100644 index 0000000..7da0be4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/audio-trickplay.c @@ -0,0 +1,264 @@ +/* + * audio-trickplay.c + * + * Builds a pipeline with two audiotestsources mixed with adder. Assigns + * controller patterns to the audio generators and test various trick modes. + * + * There are currently several issues: + * - adder only work with flushing seeks + * - there is a gap of almost 4 seconds before backwards playback + * - it is "waiting for free space" + * - using sync=false on the sink does not help (but has some other weird effects) + * - using fakesink shows same behaviour + * + * GST_DEBUG_NO_COLOR=1 GST_DEBUG="*:2,default:3,*sink*:4,*ring*:4,*pulse*:5" ./audio-trickplay 2>log.txt + * GST_DEBUG_NO_COLOR=1 GST_DEBUG="*:2,default:3,*sink*:4,*ring*:4,*pulse*:5" ./audio-trickplay -a -f 2>log-af.txt + */ + +#include +#include +#include + +static void +check_position (GstElement * elem, GstQuery * pos, const gchar * info) +{ + if (gst_element_query (elem, pos)) { + gint64 play_pos; + gst_query_parse_position (pos, NULL, &play_pos); + GST_INFO ("pos : %" GST_TIME_FORMAT " %s", GST_TIME_ARGS (play_pos), info); + } else { + GST_WARNING ("position query failed"); + } +} + +static gboolean +print_buffer_ts (GstPad * pad, GstBuffer * buffer, gpointer user_data) +{ + GST_DEBUG_OBJECT (pad, " ts: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + return TRUE; +} + +gint +main (gint argc, gchar ** argv) +{ + gint res = 1; + GstElement *src, *mix = NULL, *sink; + GstElement *bin; + GstController *ctrl; + GstInterpolationControlSource *csource1, *csource2; + GstClock *clock; + GstClockID clock_id; + GstClockReturn wait_ret; + GValue vol = { 0, }; + GstEvent *pos_seek, *rate_seek1, *rate_seek2; + GstQuery *pos; + GstSeekFlags flags; + GstPad *src_pad; + /* options */ + gboolean use_adder = FALSE; + gboolean use_flush = FALSE; + gboolean be_quiet = FALSE; + + gst_init (&argc, &argv); + gst_controller_init (&argc, &argv); + + if (argc) { + gint arg; + for (arg = 0; arg < argc; arg++) { + if (!strcmp (argv[arg], "-a")) + use_adder = TRUE; + else if (!strcmp (argv[arg], "-f")) + use_flush = TRUE; + else if (!strcmp (argv[arg], "-q")) + be_quiet = TRUE; + } + } + + /* build pipeline */ + bin = gst_pipeline_new ("pipeline"); + clock = gst_pipeline_get_clock (GST_PIPELINE (bin)); + src = gst_element_factory_make ("audiotestsrc", NULL); + if (!src) { + GST_WARNING ("need audiotestsrc from gst-plugins-base"); + goto Error; + } + if (use_adder) { + mix = gst_element_factory_make ("adder", NULL); + if (!mix) { + GST_WARNING ("need adder from gst-plugins-base"); + goto Error; + } + } + sink = gst_element_factory_make ((be_quiet ? "fakesink" : "autoaudiosink"), + NULL); + if (!sink) { + GST_WARNING ("need autoaudiosink from gst-plugins-base"); + goto Error; + } + + if (use_adder) { + gst_bin_add_many (GST_BIN (bin), src, mix, sink, NULL); + if (!gst_element_link_many (src, mix, sink, NULL)) { + GST_WARNING ("can't link elements"); + goto Error; + } + } else { + gst_bin_add_many (GST_BIN (bin), src, sink, NULL); + if (!gst_element_link_many (src, sink, NULL)) { + GST_WARNING ("can't link elements"); + goto Error; + } + } + + /* use 10 buffers per second */ + g_object_set (src, "samplesperbuffer", 44100 / 10, NULL); + + if (be_quiet) { + g_object_set (sink, "sync", TRUE, NULL); + } + + src_pad = gst_element_get_static_pad (src, "src"); + gst_pad_add_buffer_probe (src_pad, G_CALLBACK (print_buffer_ts), NULL); + gst_object_unref (src_pad); + + /* add a controller to the source */ + if (!(ctrl = gst_controller_new (G_OBJECT (src), "freq", "volume", NULL))) { + GST_WARNING ("can't control source element"); + goto Error; + } + + csource1 = gst_interpolation_control_source_new (); + csource2 = gst_interpolation_control_source_new (); + + gst_controller_set_control_source (ctrl, "volume", + GST_CONTROL_SOURCE (csource1)); + gst_controller_set_control_source (ctrl, "freq", + GST_CONTROL_SOURCE (csource2)); + + /* Set interpolation mode */ + + gst_interpolation_control_source_set_interpolation_mode (csource1, + GST_INTERPOLATE_LINEAR); + gst_interpolation_control_source_set_interpolation_mode (csource2, + GST_INTERPOLATE_LINEAR); + + /* set control values */ + g_value_init (&vol, G_TYPE_DOUBLE); + g_value_set_double (&vol, 0.0); + gst_interpolation_control_source_set (csource1, 0 * GST_SECOND, &vol); + g_value_set_double (&vol, 1.0); + gst_interpolation_control_source_set (csource1, 5 * GST_SECOND, &vol); + + g_object_unref (csource1); + + g_value_set_double (&vol, 220.0); + gst_interpolation_control_source_set (csource2, 0 * GST_SECOND, &vol); + g_value_set_double (&vol, 3520.0); + gst_interpolation_control_source_set (csource2, 2 * GST_SECOND, &vol); + g_value_set_double (&vol, 440.0); + gst_interpolation_control_source_set (csource2, 6 * GST_SECOND, &vol); + + g_object_unref (csource2); + + /* prepare events */ + flags = use_flush ? GST_SEEK_FLAG_FLUSH : GST_SEEK_FLAG_NONE; + pos_seek = gst_event_new_seek (1.0, GST_FORMAT_TIME, flags, + GST_SEEK_TYPE_SET, 3 * GST_SECOND, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + rate_seek1 = gst_event_new_seek (0.5, GST_FORMAT_TIME, flags, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + rate_seek2 = gst_event_new_seek (-1.0, GST_FORMAT_TIME, flags, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE, + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); + + /* prepare queries */ + pos = gst_query_new_position (GST_FORMAT_TIME); + + + /* run the show */ + if (gst_element_set_state (bin, GST_STATE_PAUSED) != GST_STATE_CHANGE_FAILURE) { + + /* run for 5 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (5 * GST_SECOND)); + + if (gst_element_set_state (bin, + GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { + check_position (bin, pos, "start"); + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + } + gst_clock_id_unref (clock_id); + + check_position (bin, pos, "before seek to new pos"); + + /* seek to 3:00 sec (back 2 sec) */ + if (!gst_element_send_event (sink, pos_seek)) { + GST_WARNING ("element failed to seek to new position"); + } + + check_position (bin, pos, "after seek to new pos"); + + /* run for 2 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (2 * GST_SECOND)); + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_clock_id_unref (clock_id); + + check_position (bin, pos, "before slow down rate change"); + + /* change playback rate to 0.5 */ + if (!gst_element_send_event (sink, rate_seek1)) { + GST_WARNING ("element failed to change playback rate"); + } + + check_position (bin, pos, "after slow down rate change"); + + /* run for 4 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (4 * GST_SECOND)); + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_clock_id_unref (clock_id); + + check_position (bin, pos, "before reverse rate change"); + + /* change playback rate to -1.0 */ + if (!gst_element_send_event (sink, rate_seek2)) { + GST_WARNING ("element failed to change playback rate"); + } + + check_position (bin, pos, "after reverse rate change"); + + /* run for 7 seconds */ + clock_id = + gst_clock_new_single_shot_id (clock, + gst_clock_get_time (clock) + (7 * GST_SECOND)); + if ((wait_ret = gst_clock_id_wait (clock_id, NULL)) != GST_CLOCK_OK) { + GST_WARNING ("clock_id_wait returned: %d", wait_ret); + } + gst_clock_id_unref (clock_id); + + check_position (bin, pos, "done"); + + gst_element_set_state (bin, GST_STATE_NULL); + } + + /* cleanup */ + gst_query_unref (pos); + g_object_unref (G_OBJECT (ctrl)); + gst_object_unref (G_OBJECT (clock)); + gst_object_unref (G_OBJECT (bin)); + res = 0; +Error: + return (res); +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/input-selector-test.c b/gst-plugins-base-subtitles0.10/tests/icles/input-selector-test.c new file mode 100644 index 0000000..4742c03 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/input-selector-test.c @@ -0,0 +1,162 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + + +#include + +static GMainLoop *loop = NULL; + +static gboolean +my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s\n", err->message); + g_error_free (err); + g_free (debug); + + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + g_main_loop_quit (loop); + break; + default: + /* unhandled message */ + break; + } + + /* we want to be notified again the next time there is a message + * on the bus, so returning TRUE (FALSE means we want to stop watching + * for messages on the bus and our callback should not be called again) + */ + return TRUE; +} + + + +static gboolean +switch_timer (GstElement * video_switch) +{ + gint nb_sources; + GstPad *active_pad, *new_pad; + gchar *active_name; + + g_message ("switching"); + g_object_get (G_OBJECT (video_switch), "n-pads", &nb_sources, NULL); + g_object_get (G_OBJECT (video_switch), "active-pad", &active_pad, NULL); + + active_name = gst_pad_get_name (active_pad); + if (strcmp (active_name, "sink0") == 0) { + new_pad = gst_element_get_static_pad (video_switch, "sink1"); + } else { + new_pad = gst_element_get_static_pad (video_switch, "sink0"); + } + g_object_set (G_OBJECT (video_switch), "active-pad", new_pad, NULL); + g_free (active_name); + gst_object_unref (new_pad); + + g_message ("current number of sources : %d, active source %s", + nb_sources, gst_pad_get_name (active_pad)); + + return (GST_STATE (GST_ELEMENT (video_switch)) == GST_STATE_PLAYING); +} + +static void +last_message_received (GObject * segment) +{ + gchar *last_message; + + g_object_get (segment, "last_message", &last_message, NULL); + g_print ("last-message: %s\n", last_message); + g_free (last_message); +} + +int +main (int argc, char *argv[]) +{ + GstElement *pipeline, *src1, *src2, *video_switch, *video_sink, *segment; + GstElement *sink1_sync, *sink2_sync, *capsfilter; + GstBus *bus; + + /* Initing GStreamer library */ + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + pipeline = gst_pipeline_new ("pipeline"); + src1 = gst_element_factory_make ("videotestsrc", "src1"); + g_object_set (G_OBJECT (src1), "pattern", 0, NULL); + src2 = gst_element_factory_make ("videotestsrc", "src2"); + g_object_set (G_OBJECT (src2), "pattern", 1, NULL); + capsfilter = gst_element_factory_make ("capsfilter", "caps0"); + g_object_set (G_OBJECT (capsfilter), "caps", + gst_caps_from_string ("video/x-raw-rgb,width=640,height=480"), NULL); + video_switch = gst_element_factory_make ("input-selector", "video_switch"); + segment = gst_element_factory_make ("identity", "identity-segment"); + g_object_set (G_OBJECT (segment), "silent", TRUE, NULL); + g_signal_connect (G_OBJECT (segment), "notify::last-message", + G_CALLBACK (last_message_received), segment); + g_object_set (G_OBJECT (segment), "single-segment", TRUE, NULL); + video_sink = gst_element_factory_make ("ximagesink", "video_sink"); + g_object_set (G_OBJECT (video_sink), "sync", FALSE, NULL); + sink1_sync = gst_element_factory_make ("identity", "sink0_sync"); + g_object_set (G_OBJECT (sink1_sync), "sync", TRUE, NULL); + sink2_sync = gst_element_factory_make ("identity", "sink1_sync"); + g_object_set (G_OBJECT (sink2_sync), "sync", TRUE, NULL); + gst_bin_add_many (GST_BIN (pipeline), src1, src2, segment, video_switch, + video_sink, sink1_sync, sink2_sync, capsfilter, NULL); + gst_element_link (src1, sink1_sync); + gst_element_link (sink1_sync, video_switch); + gst_element_link (src2, capsfilter); + gst_element_link (capsfilter, sink2_sync); + gst_element_link (sink2_sync, video_switch); + gst_element_link (video_switch, segment); + gst_element_link (segment, /*scaler); + gst_element_link (scaler, */ video_sink); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, my_bus_callback, NULL); + gst_object_unref (bus); + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + + g_timeout_add (200, (GSourceFunc) switch_timer, video_switch); + + g_main_loop_run (loop); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); + + /* unref */ + gst_object_unref (GST_OBJECT (pipeline)); + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/output-selector-test.c b/gst-plugins-base-subtitles0.10/tests/icles/output-selector-test.c new file mode 100644 index 0000000..24ad283 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/output-selector-test.c @@ -0,0 +1,173 @@ +#include + +#define SWITCH_TIMEOUT 1000 +#define NUM_VIDEO_BUFFERS 500 + +static GMainLoop *loop; + +/* Output selector src pads */ +static GstPad *osel_src1 = NULL; +static GstPad *osel_src2 = NULL; + +static gboolean +my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s\n", err->message); + g_error_free (err); + g_free (debug); + + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + g_main_loop_quit (loop); + break; + default: + /* unhandled message */ + break; + } + /* we want to be notified again the next time there is a message + * on the bus, so returning TRUE (FALSE means we want to stop watching + * for messages on the bus and our callback should not be called again) + */ + return TRUE; +} + +static gboolean +switch_cb (gpointer user_data) +{ + GstElement *sel = GST_ELEMENT (user_data); + GstPad *old_pad, *new_pad = NULL; + + g_object_get (G_OBJECT (sel), "active-pad", &old_pad, NULL); + + if (old_pad == osel_src1) + new_pad = osel_src2; + else + new_pad = osel_src1; + + g_object_set (G_OBJECT (sel), "active-pad", new_pad, NULL); + + g_print ("switched from %s:%s to %s:%s\n", GST_DEBUG_PAD_NAME (old_pad), + GST_DEBUG_PAD_NAME (new_pad)); + + gst_object_unref (old_pad); + + return TRUE; + +} + +static void +on_bin_element_added (GstBin * bin, GstElement * element, gpointer user_data) +{ + g_object_set (G_OBJECT (element), "sync", FALSE, "async", FALSE, NULL); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *src, *toverlay, *osel, *sink1, *sink2, *c1, *c2, *c0; + GstPad *sinkpad; + GstBus *bus; + + /* init GStreamer */ + gst_init (&argc, &argv); + loop = g_main_loop_new (NULL, FALSE); + + /* create elements */ + pipeline = gst_element_factory_make ("pipeline", "pipeline"); + src = gst_element_factory_make ("videotestsrc", "src"); + c0 = gst_element_factory_make ("ffmpegcolorspace", NULL); + toverlay = gst_element_factory_make ("timeoverlay", "timeoverlay"); + osel = gst_element_factory_make ("output-selector", "osel"); + c1 = gst_element_factory_make ("ffmpegcolorspace", NULL); + c2 = gst_element_factory_make ("ffmpegcolorspace", NULL); + sink1 = gst_element_factory_make ("autovideosink", "sink1"); + sink2 = gst_element_factory_make ("autovideosink", "sink2"); + + if (!pipeline || !src || !c0 || !toverlay || !osel || !c1 || !c2 || !sink1 || + !sink2) { + g_print ("missing element\n"); + return -1; + } + + /* add them to bin */ + gst_bin_add_many (GST_BIN (pipeline), src, c0, toverlay, osel, c1, sink1, c2, + sink2, NULL); + + /* set properties */ + g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); + g_object_set (G_OBJECT (src), "do-timestamp", TRUE, NULL); + g_object_set (G_OBJECT (src), "num-buffers", NUM_VIDEO_BUFFERS, NULL); + g_object_set (G_OBJECT (osel), "resend-latest", TRUE, NULL); + + /* handle deferred properties */ + g_signal_connect (G_OBJECT (sink1), "element-added", + G_CALLBACK (on_bin_element_added), NULL); + g_signal_connect (G_OBJECT (sink2), "element-added", + G_CALLBACK (on_bin_element_added), NULL); + + /* link src ! timeoverlay ! osel */ + if (!gst_element_link_many (src, c0, toverlay, osel, NULL)) { + g_print ("linking failed\n"); + return -1; + } + + /* link output 1 */ + sinkpad = gst_element_get_static_pad (c1, "sink"); + osel_src1 = gst_element_get_request_pad (osel, "src%d"); + if (gst_pad_link (osel_src1, sinkpad) != GST_PAD_LINK_OK) { + g_print ("linking output 1 converter failed\n"); + return -1; + } + gst_object_unref (sinkpad); + + if (!gst_element_link (c1, sink1)) { + g_print ("linking output 1 failed\n"); + return -1; + } + + /* link output 2 */ + sinkpad = gst_element_get_static_pad (c2, "sink"); + osel_src2 = gst_element_get_request_pad (osel, "src%d"); + if (gst_pad_link (osel_src2, sinkpad) != GST_PAD_LINK_OK) { + g_print ("linking output 2 converter failed\n"); + return -1; + } + gst_object_unref (sinkpad); + + if (!gst_element_link (c2, sink2)) { + g_print ("linking output 2 failed\n"); + return -1; + } + + /* add switch callback */ + g_timeout_add (SWITCH_TIMEOUT, switch_cb, osel); + + /* change to playing */ + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, my_bus_callback, loop); + gst_object_unref (bus); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* now run */ + g_main_loop_run (loop); + + /* also clean up */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_element_release_request_pad (osel, osel_src1); + gst_element_release_request_pad (osel, osel_src2); + gst_object_unref (GST_OBJECT (pipeline)); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/.gitignore b/gst-plugins-base-subtitles0.10/tests/icles/playback/.gitignore new file mode 100644 index 0000000..4fdb026 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/.gitignore @@ -0,0 +1,8 @@ +decodetest +test +test2 +test3 +test4 +test5 +test6 +test7 diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/Makefile.am b/gst-plugins-base-subtitles0.10/tests/icles/playback/Makefile.am new file mode 100644 index 0000000..b1d7f94 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/Makefile.am @@ -0,0 +1,26 @@ +noinst_PROGRAMS = test decodetest test2 test3 test4 test5 test6 test7 + +test_LDADD = $(GST_LIBS) +test_CFLAGS = $(GST_CFLAGS) + +test2_LDADD = $(GST_LIBS) +test2_CFLAGS = $(GST_CFLAGS) + +test3_LDADD = $(GST_LIBS) +test3_CFLAGS = $(GST_CFLAGS) + +test4_LDADD = $(GST_LIBS) +test4_CFLAGS = $(GST_CFLAGS) + +test5_LDADD = $(GST_LIBS) +test5_CFLAGS = $(GST_CFLAGS) + +test6_LDADD = $(GST_LIBS) +test6_CFLAGS = $(GST_CFLAGS) + +test7_LDADD = $(GST_LIBS) +test7_CFLAGS = $(GST_CFLAGS) + +decodetest_LDADD = $(GST_LIBS) +decodetest_CFLAGS = $(GST_CFLAGS) + diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/decodetest.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/decodetest.c new file mode 100644 index 0000000..dd81c6b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/decodetest.c @@ -0,0 +1,169 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +static void +warning_cb (GstBus * bus, GstMessage * msg, gpointer foo) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_warning (msg, &err, &dbg); + + g_printerr ("WARNING: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_error_free (err); + g_free (dbg); +} + +static void +error_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_error (msg, &err, &dbg); + + g_printerr ("ERROR: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_main_loop_quit (main_loop); + + g_error_free (err); + g_free (dbg); +} + +static void +eos_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + g_print ("EOS\n"); + g_main_loop_quit (main_loop); +} + +static void +state_cb (GstBus * bus, GstMessage * msg, GstElement * pipeline) +{ + if (msg->src == GST_OBJECT (pipeline)) { + GstState old_state, new_state, pending_state; + + gst_message_parse_state_changed (msg, &old_state, &new_state, + &pending_state); + if (new_state == GST_STATE_PLAYING) { + g_print ("Decoding ...\n"); + } + } +} + +static void +new_decoded_pad_cb (GstElement * decodebin, GstPad * pad, gboolean last, + GstElement * pipeline) +{ + GstPadLinkReturn ret; + GstElement *fakesink; + GstPad *fakesink_pad; + + fakesink = gst_element_factory_make ("fakesink", NULL); + fakesink_pad = gst_element_get_static_pad (fakesink, "sink"); + + gst_bin_add (GST_BIN (pipeline), fakesink); + + /* this doesn't really seem right, but it makes things work for me */ + gst_element_set_state (fakesink, GST_STATE_PLAYING); + + ret = gst_pad_link (pad, fakesink_pad); + if (!GST_PAD_LINK_SUCCESSFUL (ret)) { + g_printerr ("Failed to link %s:%s to %s:%s (ret = %d)\n", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (fakesink_pad), ret); + } else { + g_printerr ("Linked %s:%s to %s:%s\n", GST_DEBUG_PAD_NAME (pad), + GST_DEBUG_PAD_NAME (fakesink_pad)); + } + + gst_object_unref (fakesink_pad); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *decoder; + GstElement *source; + GstElement *pipeline; + GstStateChangeReturn res; + GMainLoop *loop; + GstBus *bus; + + gst_init (&argc, &argv); + + if (argc != 2) { + g_printerr ("Decode file from start to end.\n"); + g_printerr ("Usage: %s URI\n\n", argv[0]); + return 1; + } + + loop = g_main_loop_new (NULL, TRUE); + + pipeline = gst_pipeline_new ("pipeline"); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch (bus); + + g_signal_connect (bus, "message::eos", G_CALLBACK (eos_cb), loop); + g_signal_connect (bus, "message::error", G_CALLBACK (error_cb), loop); + g_signal_connect (bus, "message::warning", G_CALLBACK (warning_cb), NULL); + g_signal_connect (bus, "message::state-changed", G_CALLBACK (state_cb), + pipeline); + + source = gst_element_factory_make ("gnomevfssrc", "source"); + g_assert (source); + + if (argv[1] && strstr (argv[1], "://") != NULL) { + g_object_set (G_OBJECT (source), "location", argv[1], NULL); + } else if (argv[1]) { + gchar *uri = g_strdup_printf ("file://%s", argv[1]); + + g_object_set (G_OBJECT (source), "location", uri, NULL); + g_free (uri); + } + + decoder = gst_element_factory_make ("decodebin", "decoder"); + g_assert (decoder); + + gst_bin_add (GST_BIN (pipeline), source); + gst_bin_add (GST_BIN (pipeline), decoder); + + gst_element_link_pads (source, "src", decoder, "sink"); + + g_signal_connect (decoder, "new-decoded-pad", + G_CALLBACK (new_decoded_pad_cb), pipeline); + + res = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not play\n"); + return -1; + } + + g_main_loop_run (loop); + + /* tidy up */ + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (bus); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test.c new file mode 100644 index 0000000..3c944ec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test.c @@ -0,0 +1,193 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +static GMainLoop *loop; + +static GstElement * +gen_video_element (void) +{ + GstElement *element; + GstElement *conv; + GstElement *sink; + GstPad *pad; + + element = gst_bin_new ("vbin"); + conv = gst_element_factory_make ("ffmpegcolorspace", "conv"); + sink = gst_element_factory_make (DEFAULT_VIDEOSINK, "sink"); + + gst_bin_add (GST_BIN (element), conv); + gst_bin_add (GST_BIN (element), sink); + gst_element_link_pads (conv, "src", sink, "sink"); + + pad = gst_element_get_static_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + return element; +} + +static GstElement * +gen_audio_element (void) +{ + GstElement *element; + GstElement *conv; + GstElement *sink; + GstPad *pad; + + element = gst_bin_new ("abin"); + conv = gst_element_factory_make ("audioconvert", "conv"); + sink = gst_element_factory_make (DEFAULT_AUDIOSINK, "sink"); + + gst_bin_add (GST_BIN (element), conv); + gst_bin_add (GST_BIN (element), sink); + gst_element_link_pads (conv, "src", sink, "sink"); + + pad = gst_element_get_static_pad (conv, "sink"); + gst_element_add_pad (element, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (pad); + + return element; +} + +static void +cb_newpad (GstElement * decodebin, GstPad * pad, gboolean last, gpointer data) +{ + GstCaps *caps; + GstStructure *str; + GstPad *sinkpad; + GstElement *sink; + GstElement *pipeline; + const gchar *name; + GstStateChangeReturn ret; + GstPadLinkReturn lret; + + /* check media type */ + caps = gst_pad_get_caps (pad); + str = gst_caps_get_structure (caps, 0); + + name = gst_structure_get_name (str); + g_print ("name: %s\n", name); + + if (g_strrstr (name, "audio")) { + sink = gen_audio_element (); + } else if (g_strrstr (name, "video")) { + sink = gen_video_element (); + } else { + sink = NULL; + } + gst_caps_unref (caps); + + if (sink) { + pipeline = GST_ELEMENT_CAST (data); + + /* add new sink to the pipeline */ + gst_bin_add (GST_BIN_CAST (pipeline), sink); + + /* set the new sink tp PAUSED as well */ + ret = gst_element_set_state (sink, GST_STATE_PAUSED); + if (ret == GST_STATE_CHANGE_FAILURE) + goto state_error; + + /* get the ghostpad of the sink bin */ + sinkpad = gst_element_get_static_pad (sink, "sink"); + + /* link'n'play */ + lret = gst_pad_link (pad, sinkpad); + if (lret != GST_PAD_LINK_OK) + goto link_failed; + + gst_object_unref (sinkpad); + } + return; + + /* ERRORS */ +state_error: + { + gst_bin_remove (GST_BIN_CAST (pipeline), sink); + g_warning ("could not change state of new sink (%d)", ret); + return; + } +link_failed: + { + g_warning ("could not link pad and sink (%d)", lret); + return; + } +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *filesrc, *decodebin; + GstStateChangeReturn res; + + gst_init (&argc, &argv); + + pipeline = gst_pipeline_new ("pipeline"); + + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_assert (filesrc); + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + g_assert (decodebin); + + g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad", + G_CALLBACK (cb_newpad), pipeline); + + gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL); + gst_element_link (filesrc, decodebin); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + + /* set to paused, decodebin will autoplug and signal new_pad callbacks */ + res = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not pause\n"); + return -1; + } + /* wait for paused to complete */ + res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not pause\n"); + return -1; + } + + /* play, now all the sinks are added to the pipeline and are prerolled and + * ready to play. */ + res = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not play\n"); + return -1; + } + + /* go in the mainloop now */ + loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test2.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test2.c new file mode 100644 index 0000000..86f3c4c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test2.c @@ -0,0 +1,43 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *player; + GstStateChangeReturn res; + + gst_init (&argc, &argv); + + player = gst_element_factory_make ("playbin", "player"); + g_assert (player); + + g_object_set (G_OBJECT (player), "uri", argv[1], NULL); + + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_main_loop_run (g_main_loop_new (NULL, TRUE)); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test3.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test3.c new file mode 100644 index 0000000..dd08f7c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test3.c @@ -0,0 +1,128 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#define UPDATE_INTERVAL 500 + +static gboolean +update_scale (GstElement * element) +{ + gint64 duration = -1; + gint64 position = -1; + GstFormat format = GST_FORMAT_TIME; + gchar dur_str[32], pos_str[32]; + + if (gst_element_query_position (element, &format, &position) && + position != -1) { + g_snprintf (pos_str, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + } else { + g_snprintf (pos_str, 32, "-:--:--.---------"); + } + + if (gst_element_query_duration (element, &format, &duration) && + duration != -1) { + g_snprintf (dur_str, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + } else { + g_snprintf (dur_str, 32, "-:--:--.---------"); + } + + g_print ("%s / %s\n", pos_str, dur_str); + + return TRUE; +} + +static void +warning_cb (GstBus * bus, GstMessage * msg, gpointer foo) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_warning (msg, &err, &dbg); + + g_printerr ("WARNING: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_error_free (err); + g_free (dbg); +} + +static void +error_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_error (msg, &err, &dbg); + + g_printerr ("ERROR: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_main_loop_quit (main_loop); + + g_error_free (err); + g_free (dbg); +} + +static void +eos_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + g_print ("EOS\n"); + g_main_loop_quit (main_loop); +} + + +gint +main (gint argc, gchar * argv[]) +{ + GstStateChangeReturn res; + GstElement *player; + GMainLoop *loop; + GstBus *bus; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + player = gst_element_factory_make ("playbin", "player"); + g_assert (player); + + bus = gst_pipeline_get_bus (GST_PIPELINE (player)); + gst_bus_add_signal_watch (bus); + + g_signal_connect (bus, "message::eos", G_CALLBACK (eos_cb), loop); + g_signal_connect (bus, "message::error", G_CALLBACK (error_cb), loop); + g_signal_connect (bus, "message::warning", G_CALLBACK (warning_cb), NULL); + + g_object_set (G_OBJECT (player), "uri", argv[1], NULL); + + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not play\n"); + return -1; + } + + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, player); + + g_main_loop_run (loop); + + /* tidy up */ + gst_element_set_state (player, GST_STATE_NULL); + gst_object_unref (player); + gst_object_unref (bus); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test4.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test4.c new file mode 100644 index 0000000..c2bb7c9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test4.c @@ -0,0 +1,99 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STDLIB_H +#include /* exit() */ +#endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#include + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *player; + GstStateChangeReturn res; + + gst_init (&argc, &argv); + + player = gst_element_factory_make ("playbin", "player"); + g_assert (player); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + g_object_set (G_OBJECT (player), "uri", argv[1], NULL); + + g_print ("play...\n"); + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_print ("sleep 2...\n"); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("pause...\n"); + res = gst_element_set_state (player, GST_STATE_PAUSED); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_print ("sleep 2...\n"); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("play...\n"); + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_print ("sleep 2...\n"); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("ready...\n"); + res = gst_element_set_state (player, GST_STATE_READY); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_print ("sleep 2...\n"); + g_usleep (2 * G_USEC_PER_SEC); + + g_print ("play...\n"); + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res != GST_STATE_CHANGE_SUCCESS) { + g_print ("could not play\n"); + return -1; + } + + g_main_loop_run (g_main_loop_new (NULL, TRUE)); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test5.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test5.c new file mode 100644 index 0000000..715b4bb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test5.c @@ -0,0 +1,132 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif +#ifdef HAVE_STDLIB_H +#include /* exit */ +#endif +#include + +static GMainLoop *loop; + +static void +new_pad (GstElement * element, GstPad * pad, gboolean last, GstElement * sink) +{ + g_print ("New pad...\n"); +} + +static void +no_more_pads (GstElement * element) +{ + g_print ("No more pads...\n"); + g_main_loop_quit (loop); +} + +static gboolean +start_finding (GstElement * pipeline) +{ + GstStateChangeReturn res; + + g_print ("finding caps...\n"); + res = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not pause\n"); + exit (-1); + } + return FALSE; +} + +static void +dump_element_stats (GstElement * element) +{ + GstIterator *it; + gpointer data; + + it = gst_element_iterate_src_pads (element); + while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) { + GstPad *pad = GST_PAD (data); + GstCaps *caps; + gchar *str; + GstQuery *query; + + g_print ("stream %s:\n", GST_OBJECT_NAME (pad)); + + caps = gst_pad_get_caps (pad); + str = gst_caps_to_string (caps); + g_print (" caps: %s\n", str); + g_free (str); + gst_caps_unref (caps); + + query = gst_query_new_duration (GST_FORMAT_TIME); + if (gst_pad_query (pad, query)) { + gint64 duration; + + gst_query_parse_duration (query, NULL, &duration); + + g_print (" duration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (duration)); + } + gst_query_unref (query); + + gst_object_unref (pad); + } + gst_iterator_free (it); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *filesrc, *decodebin; + + gst_init (&argc, &argv); + + pipeline = gst_pipeline_new ("pipeline"); + + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_assert (filesrc); + + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + g_assert (decodebin); + + g_signal_connect (G_OBJECT (decodebin), "new-decoded-pad", + G_CALLBACK (new_pad), NULL); + g_signal_connect (G_OBJECT (decodebin), "no-more-pads", + G_CALLBACK (no_more_pads), NULL); + + gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL); + gst_element_link (filesrc, decodebin); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + + /* event based programming approach */ + loop = g_main_loop_new (NULL, TRUE); + g_idle_add ((GSourceFunc) start_finding, pipeline); + g_main_loop_run (loop); + + dump_element_stats (decodebin); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test6.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test6.c new file mode 100644 index 0000000..17e50f9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test6.c @@ -0,0 +1,164 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#endif +#ifdef HAVE_STDLIB_H +#include /* exit */ +#endif +#include + +static void +new_decoded_pad_cb (GstElement * decodebin, GstPad * new_pad, gboolean last, + GstElement * pipeline) +{ + GstElement *fakesink; + GstPad *sinkpad; + + fakesink = gst_element_factory_make ("fakesink", NULL); + gst_bin_add (GST_BIN (pipeline), fakesink); + + sinkpad = gst_element_get_static_pad (fakesink, "sink"); + if (GST_PAD_LINK_FAILED (gst_pad_link (new_pad, sinkpad))) { + g_warning ("Failed to link %s:%s to %s:%s", GST_DEBUG_PAD_NAME (new_pad), + GST_DEBUG_PAD_NAME (sinkpad)); + gst_bin_remove (GST_BIN (pipeline), fakesink); + } else { + gst_element_set_state (fakesink, GST_STATE_PAUSED); + } +} + +static void +show_error (const gchar * errmsg, GstBus * bus) +{ + GstMessage *msg; + GError *err = NULL; + gchar *dbg = NULL; + + msg = gst_bus_poll (bus, GST_MESSAGE_ERROR, 0); + if (msg) { + g_assert (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + + gst_message_parse_error (msg, &err, &dbg); + } + + g_print ("ERROR: %s\n", errmsg); + g_print (" %s\n", (err) ? err->message : ""); + if (dbg) { + g_print ("\ndebug: %s\n\n", dbg); + g_free (dbg); + } + + if (err) + g_error_free (err); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline, *filesrc, *decodebin; + GstStateChangeReturn res; + GstIterator *it; + GstBus *bus; + gpointer data; + + gst_init (&argc, &argv); + + pipeline = gst_pipeline_new ("pipeline"); + + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_assert (filesrc); + + decodebin = gst_element_factory_make ("decodebin", "decodebin"); + g_assert (decodebin); + + gst_bin_add_many (GST_BIN (pipeline), filesrc, decodebin, NULL); + gst_element_link (filesrc, decodebin); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + if (!g_str_has_prefix (argv[1], "file://")) { + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + } else { + g_object_set (G_OBJECT (filesrc), "location", argv[1] + 7, NULL); + } + + /* we've got to connect fakesinks to newly decoded pads to make sure + * buffers have actually been flowing over those pads and caps have + * been set on them. decodebin might insert internal queues and + * without fakesinks it's pot-luck what caps we get from the pad, because + * it depends on whether the queues have started pushing buffers yet or not. + * With fakesinks we make sure that the pipeline doesn't go to PAUSED state + * before each fakesink has a buffer queued. */ + g_signal_connect (decodebin, "new-decoded-pad", + G_CALLBACK (new_decoded_pad_cb), pipeline); + + bus = gst_element_get_bus (pipeline); + + g_print ("pause..\n"); + res = gst_element_set_state (pipeline, GST_STATE_PAUSED); + if (res == GST_STATE_CHANGE_FAILURE) { + show_error ("Could not go to PAUSED state", bus); + exit (-1); + } + g_print ("waiting..\n"); + res = gst_element_get_state (pipeline, NULL, NULL, GST_CLOCK_TIME_NONE); + if (res != GST_STATE_CHANGE_SUCCESS) { + show_error ("Failed to complete state change to PAUSED", bus); + exit (-1); + } + g_print ("stats..\n"); + + it = gst_element_iterate_src_pads (decodebin); + while (gst_iterator_next (it, &data) == GST_ITERATOR_OK) { + GstPad *pad = GST_PAD (data); + GstCaps *caps; + gchar *str; + GstQuery *query; + + g_print ("stream %s:\n", GST_OBJECT_NAME (pad)); + + caps = gst_pad_get_caps (pad); + str = gst_caps_to_string (caps); + g_print (" caps: %s\n", str); + g_free (str); + gst_caps_unref (caps); + + query = gst_query_new_duration (GST_FORMAT_TIME); + if (gst_pad_query (pad, query)) { + gint64 duration; + + gst_query_parse_duration (query, NULL, &duration); + + g_print (" duration: %" GST_TIME_FORMAT "\n", GST_TIME_ARGS (duration)); + } + gst_query_unref (query); + + gst_object_unref (pad); + } + gst_iterator_free (it); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playback/test7.c b/gst-plugins-base-subtitles0.10/tests/icles/playback/test7.c new file mode 100644 index 0000000..530229b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playback/test7.c @@ -0,0 +1,179 @@ +/* GStreamer + * Copyright (C) <2007> Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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_STDLIB_H +#include /* exit() */ +#endif +#include + +#define UPDATE_INTERVAL 500 + +static int arg_count; +static int max_count; + +static gboolean +update_scale (GstElement * element) +{ + gint64 duration = -1; + gint64 position = -1; + GstFormat format = GST_FORMAT_TIME; + gchar dur_str[32], pos_str[32]; + + if (gst_element_query_position (element, &format, &position) && + position != -1) { + g_snprintf (pos_str, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (position)); + } else { + g_snprintf (pos_str, 32, "-:--:--.---------"); + } + + if (gst_element_query_duration (element, &format, &duration) && + duration != -1) { + g_snprintf (dur_str, 32, "%" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + } else { + g_snprintf (dur_str, 32, "-:--:--.---------"); + } + + g_print ("%s / %s\n", pos_str, dur_str); + + return TRUE; +} + +static void +warning_cb (GstBus * bus, GstMessage * msg, gpointer foo) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_warning (msg, &err, &dbg); + + g_printerr ("WARNING: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_error_free (err); + g_free (dbg); +} + +static void +error_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + GError *err = NULL; + gchar *dbg = NULL; + + gst_message_parse_error (msg, &err, &dbg); + + g_printerr ("ERROR: %s (%s)\n", err->message, (dbg) ? dbg : "no details"); + + g_main_loop_quit (main_loop); + + g_error_free (err); + g_free (dbg); +} + +static void +eos_cb (GstBus * bus, GstMessage * msg, GMainLoop * main_loop) +{ + g_print ("EOS\n"); + g_main_loop_quit (main_loop); +} + +static void +new_clock_cb (GstBus * bus, GstMessage * msg, gpointer nothing) +{ + GstClock *clock; + + gst_message_parse_new_clock (msg, &clock); + g_print ("NEW CLOCK: %s\n", GST_OBJECT_NAME (clock)); +} + +static void +clock_lost_cb (GstBus * bus, GstMessage * msg, GstElement * playbin) +{ + GstClock *clock; + + gst_message_parse_clock_lost (msg, &clock); + g_print ("CLOCK LOST: %s\n", GST_OBJECT_NAME (clock)); + + gst_element_set_state (playbin, GST_STATE_PAUSED); + gst_element_set_state (playbin, GST_STATE_PLAYING); +} + +static void +about_to_finish_cb (GstElement * element, gchar * uri[]) +{ + if (arg_count < max_count) { + g_object_set (G_OBJECT (element), "uri", uri[arg_count], NULL); + arg_count++; + } +} + +gint +main (gint argc, gchar * argv[]) +{ + GstStateChangeReturn res; + GstElement *player; + GMainLoop *loop; + GstBus *bus; + + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, TRUE); + + if (argc < 2) { + g_print ("usage: %s [ ... ]\n", argv[0]); + exit (-1); + } + + player = gst_element_factory_make ("playbin2", "player"); + g_assert (player); + + bus = gst_pipeline_get_bus (GST_PIPELINE (player)); + gst_bus_add_signal_watch (bus); + + g_signal_connect (bus, "message::eos", G_CALLBACK (eos_cb), loop); + g_signal_connect (bus, "message::error", G_CALLBACK (error_cb), loop); + g_signal_connect (bus, "message::warning", G_CALLBACK (warning_cb), NULL); + g_signal_connect (bus, "message::new-clock", G_CALLBACK (new_clock_cb), NULL); + g_signal_connect (bus, "message::clock-lost", G_CALLBACK (clock_lost_cb), + player); + + g_object_set (G_OBJECT (player), "uri", argv[1], NULL); + + arg_count = 2; + max_count = argc; + g_signal_connect (player, "about-to-finish", G_CALLBACK (about_to_finish_cb), + argv); + + res = gst_element_set_state (player, GST_STATE_PLAYING); + if (res == GST_STATE_CHANGE_FAILURE) { + g_print ("could not play\n"); + return -1; + } + + g_timeout_add (UPDATE_INTERVAL, (GSourceFunc) update_scale, player); + + g_main_loop_run (loop); + + /* tidy up */ + gst_element_set_state (player, GST_STATE_NULL); + gst_object_unref (player); + gst_object_unref (bus); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/playbin-text.c b/gst-plugins-base-subtitles0.10/tests/icles/playbin-text.c new file mode 100644 index 0000000..8fc3107 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/playbin-text.c @@ -0,0 +1,178 @@ +/* GStreamer + * + * Copyright (C) 2009 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include +#include +#include + +typedef struct _App App; + +struct _App +{ + GstElement *playbin; + GstElement *textsink; + + GMainLoop *loop; +}; + +static App s_app; + +static gboolean +bus_message (GstBus * bus, GstMessage * message, App * app) +{ + GST_DEBUG ("got message %s", + gst_message_type_get_name (GST_MESSAGE_TYPE (message))); + + switch (GST_MESSAGE_TYPE (message)) { + 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 (app->loop); + break; + } + case GST_MESSAGE_WARNING: + { + GError *gerror; + gchar *debug; + + gst_message_parse_warning (message, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug); + g_error_free (gerror); + g_free (debug); + + g_main_loop_quit (app->loop); + break; + } + case GST_MESSAGE_EOS: + g_message ("received EOS"); + g_main_loop_quit (app->loop); + break; + default: + break; + } + return TRUE; +} + +static void +have_subtitle (GstElement * appsink, App * app) +{ + GstBuffer *buffer; + + /* get the buffer, we can also wakeup the mainloop to get the subtitle from + * appsink in the mainloop */ + g_signal_emit_by_name (appsink, "pull-buffer", &buffer); + + if (buffer) { + guint8 *data; + guint size; + GstFormat format; + gint64 position; + GstClock *clock; + GstClockTime base_time, running_time; + + format = GST_FORMAT_TIME; + gst_element_query_position (appsink, &format, &position); + + clock = gst_element_get_clock (appsink); + base_time = gst_element_get_base_time (appsink); + + running_time = gst_clock_get_time (clock) - base_time; + + gst_object_unref (clock); + + g_message ("received a subtitle at position %" GST_TIME_FORMAT + ", running_time %" GST_TIME_FORMAT, GST_TIME_ARGS (position), + GST_TIME_ARGS (running_time)); + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + gst_util_dump_mem (data, size); + } +} + +int +main (int argc, char *argv[]) +{ + App *app = &s_app; + GstBus *bus; + GstCaps *subcaps; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + /* create a mainloop to get messages */ + app->loop = g_main_loop_new (NULL, TRUE); + + app->playbin = gst_element_factory_make ("playbin2", NULL); + g_assert (app->playbin); + + /* set appsink to get the subtitles */ + app->textsink = gst_element_factory_make ("appsink", "subtitle_sink"); + g_object_set (G_OBJECT (app->textsink), "emit-signals", TRUE, NULL); + g_object_set (G_OBJECT (app->textsink), "ts-offset", 0 * GST_SECOND, NULL); + g_signal_connect (app->textsink, "new-buffer", G_CALLBACK (have_subtitle), + app); + subcaps = gst_caps_from_string ("text/x-pango-markup; text/plain"); + g_object_set (G_OBJECT (app->textsink), "caps", subcaps, NULL); + gst_caps_unref (subcaps); + + g_object_set (G_OBJECT (app->playbin), "text-sink", app->textsink, NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (app->playbin)); + + /* add watch for messages */ + gst_bus_add_watch (bus, (GstBusFunc) bus_message, app); + + /* set to read from appsrc */ + g_object_set (app->playbin, "uri", argv[1], NULL); + + /* go to playing and wait in a mainloop. */ + gst_element_set_state (app->playbin, GST_STATE_PLAYING); + + /* this mainloop is stopped when we receive an error or EOS */ + g_main_loop_run (app->loop); + + g_message ("stopping"); + + gst_element_set_state (app->playbin, GST_STATE_NULL); + + gst_object_unref (bus); + g_main_loop_unref (app->loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/position-formats.c b/gst-plugins-base-subtitles0.10/tests/icles/position-formats.c new file mode 100644 index 0000000..5ca815e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/position-formats.c @@ -0,0 +1,149 @@ +/* + * position-formats.c + * + * we mostly use GST_FORMAT_TIME in queries and seeks. Test the other ones to + * know what works and what not. + */ + +#include + +#include + +static gboolean +bus_message (GstBus * bus, GstMessage * message, gpointer user_data) +{ + GMainLoop *loop = (GMainLoop *) user_data; + + switch (GST_MESSAGE_TYPE (message)) { + 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_WARNING: + { + GError *gerror; + gchar *debug; + + gst_message_parse_warning (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_EOS: + g_main_loop_quit (loop); + break; + default: + break; + } + return TRUE; +} + +static void +print_value (gboolean res, GstFormat fmt, gint64 val) +{ + if (res) { + switch (fmt) { + case GST_FORMAT_TIME: + printf ("%" GST_TIME_FORMAT, GST_TIME_ARGS (val)); + break; + case GST_FORMAT_PERCENT: + printf ("%8.4lf%%", (gdouble) val / GST_FORMAT_PERCENT_SCALE); + break; + case GST_FORMAT_DEFAULT: + case GST_FORMAT_BYTES: + case GST_FORMAT_BUFFERS: + default: + printf ("%" G_GINT64_FORMAT, val); + break; + } + } else { + printf ("-"); + } +} + +static gboolean +run_queries (gpointer user_data) +{ + GstElement *bin = (GstElement *) user_data; + GstFormat i, fmt; + gint64 pos, dur; + gboolean pres, dres; + + for (i = GST_FORMAT_DEFAULT; i <= GST_FORMAT_PERCENT; i++) { + fmt = i; + pres = gst_element_query_position (bin, &fmt, &pos); + fmt = i; + dres = gst_element_query_duration (bin, &fmt, &dur); + printf ("%-8s : ", gst_format_get_name (i)); + print_value (pres, fmt, pos); + printf (" / "); + print_value (dres, fmt, dur); + printf ("\n"); + } + printf ("\n"); + + return TRUE; +} + +gint +main (gint argc, gchar ** argv) +{ + gint res = 1; + GstElement *bin; + GstBus *bus; + GMainLoop *loop; + const gchar *uri; + + gst_init (&argc, &argv); + + if (argc < 2) { + printf ("Usage: %s \n", argv[0]); + goto Error; + } + uri = argv[1]; + + /* build pipeline */ + bin = gst_element_factory_make ("playbin2", NULL); + if (!bin) { + GST_WARNING ("need playbin2 from gst-plugins-base"); + goto Error; + } + + g_object_set (bin, "uri", uri, NULL); + + loop = g_main_loop_new (NULL, TRUE); + + /* add watch for messages */ + bus = gst_pipeline_get_bus (GST_PIPELINE (bin)); + gst_bus_add_watch (bus, (GstBusFunc) bus_message, (gpointer) loop); + gst_object_unref (bus); + + /* add timeout for queries */ + g_timeout_add (1000, (GSourceFunc) run_queries, (gpointer) bin); + + /* run the show */ + if (gst_element_set_state (bin, + GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) { + g_main_loop_run (loop); + gst_element_set_state (bin, GST_STATE_NULL); + } + + /* cleanup */ + g_main_loop_unref (loop); + gst_object_unref (G_OBJECT (bin)); + res = 0; +Error: + return (res); +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/stress-playbin.c b/gst-plugins-base-subtitles0.10/tests/icles/stress-playbin.c new file mode 100644 index 0000000..3b90710 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/stress-playbin.c @@ -0,0 +1,157 @@ +#include +#include +#include + +#define TEST_RUNTIME 120.0 /* how long to run the test, in seconds */ + +static void +play_file (const gchar * bin, const gint delay, const gchar * uri) +{ + GstStateChangeReturn sret; + GstMessage *msg; + GstElement *play; + guint wait_nanosecs; + + play = gst_element_factory_make (bin, "playbin"); + + g_object_set (play, "uri", uri, NULL); + g_printerr ("Playing %s\n", uri); + sret = gst_element_set_state (play, GST_STATE_PLAYING); + if (sret != GST_STATE_CHANGE_ASYNC && sret != GST_STATE_CHANGE_SUCCESS) { + g_printerr ("ERROR: state change failed, sret=%d\n", sret); + goto next; + } + + wait_nanosecs = g_random_int_range (0, GST_MSECOND * delay); + msg = gst_bus_poll (GST_ELEMENT_BUS (play), + GST_MESSAGE_ERROR | GST_MESSAGE_EOS, wait_nanosecs); + if (msg) { + switch (GST_MESSAGE_TYPE (msg)) { + case GST_MESSAGE_ERROR: + { + GError *gerror; + gchar *debug; + + gst_message_parse_error (msg, &gerror, &debug); + gst_object_default_error (GST_MESSAGE_SRC (msg), gerror, debug); + g_error_free (gerror); + g_free (debug); + break; + } + case GST_MESSAGE_EOS: + g_printerr ("Got EOS\n"); + break; + default: + g_printerr ("Got unexpected %s messge\n", GST_MESSAGE_TYPE_NAME (msg)); + break; + } + gst_message_unref (msg); + goto next; + } + + /* on to the next one */ + g_print ("."); + +next: + gst_element_set_state (play, GST_STATE_NULL); + gst_object_unref (play); +} + +static void +check_arg (GPtrArray * files, const gchar * arg) +{ + GDir *dir; + + if ((dir = g_dir_open (arg, 0, NULL))) { + const gchar *entry; + + while ((entry = g_dir_read_name (dir))) { + gchar *path; + + path = g_strconcat (arg, G_DIR_SEPARATOR_S, entry, NULL); + check_arg (files, path); + g_free (path); + } + + g_dir_close (dir); + return; + } else if (g_file_test (arg, G_FILE_TEST_EXISTS)) { + /* hack: technically an URI is not just file:// + path, but it'll do here */ + g_ptr_array_add (files, g_strdup_printf ("file://%s", arg)); + } +} + +int +main (int argc, char **argv) +{ + GPtrArray *files; + gchar **args = NULL; + guint num, i; + GError *err = NULL; + gchar *bin = NULL; + gint run = 100; + GOptionContext *ctx; + GOptionEntry options[] = { + {"bin", '\000', 0, G_OPTION_ARG_STRING, &bin, "playbin factory name", NULL}, + {"runtime", '\000', 0, G_OPTION_ARG_INT, &run, "maximum play time (ms)", + NULL}, + {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &args, NULL}, + {NULL} + }; + GTimer *timer; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new ("FILES OR DIRECTORIES WITH AUDIO FILES"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", GST_STR_NULL (err->message)); + exit (1); + } + g_option_context_free (ctx); + + if (!bin) + bin = g_strdup ("playbin"); + + if (strcmp (bin, "playbin") && strcmp (bin, "playbin2")) { + g_print ("Please provide a valid playbin argument; playbin | playbin2"); + return 1; + } + if (args == NULL || *args == NULL) { + g_print ("Please provide one or more directories with audio files\n\n"); + return 1; + } + + files = g_ptr_array_new (); + + num = g_strv_length (args); + for (i = 0; i < num; ++i) { + if (g_path_is_absolute (args[i])) { + check_arg (files, args[i]); + } else { + g_warning ("Argument '%s' is not an absolute file path", args[i]); + } + } + + if (files->len == 0) { + g_print ("Did not find any files\n\n"); + return 1; + } + + timer = g_timer_new (); + + while (g_timer_elapsed (timer, NULL) < TEST_RUNTIME) { + gint32 idx; + + idx = g_random_int_range (0, files->len); + play_file (bin, run, (const gchar *) g_ptr_array_index (files, idx)); + } + + g_strfreev (args); + g_free (bin); + g_timer_destroy (timer); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/stress-xoverlay.c b/gst-plugins-base-subtitles0.10/tests/icles/stress-xoverlay.c new file mode 100644 index 0000000..9cfb308 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/stress-xoverlay.c @@ -0,0 +1,247 @@ +/* GStreamer + * Copyright (C) <2005> Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include + +#include +#include + +static GMainLoop *loop; + +static Display *disp; +static Window root, win = 0; +static GC gc; +static gint width = 320, height = 240, x = 0, y = 0; +static gint disp_width, disp_height; + +static inline long +myclock (void) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return (tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + +static void +open_display (void) +{ + gint screen_num; + + disp = XOpenDisplay (NULL); + root = DefaultRootWindow (disp); + screen_num = DefaultScreen (disp); + disp_width = DisplayWidth (disp, screen_num); + disp_height = DisplayHeight (disp, screen_num); +} + +static void +close_display (void) +{ + XCloseDisplay (disp); +} + +static gboolean +resize_window (GstPipeline * pipeline) +{ + width = (sin (myclock () / 300.0) * 200) + 640; + height = (sin (myclock () / 300.0) * 200) + 480; + + XResizeWindow (disp, win, width, height); + + XSync (disp, FALSE); + + return TRUE; +} + +static gboolean +move_window (GstPipeline * pipeline) +{ + x += 5; + y = disp_height - height + (sin (myclock () / 300.0) * height); + if (x > disp_width) + x = 0; + + XMoveWindow (disp, win, x, y); + + XSync (disp, FALSE); + + return TRUE; +} + +static gboolean +toggle_events (GstXOverlay * ov) +{ + static gboolean events_toggled; + + gst_x_overlay_handle_events (ov, events_toggled); + + if (events_toggled) { + g_print ("Events are handled\n"); + events_toggled = FALSE; + } else { + g_print ("Events are NOT handled\n"); + events_toggled = TRUE; + } + + return TRUE; +} + +static gboolean +cycle_window (GstXOverlay * ov) +{ + XGCValues values; + Window old_win = win; + GC old_gc = gc; + + win = XCreateSimpleWindow (disp, root, 0, 0, width, height, 0, 0, 0); + + XSetWindowBackgroundPixmap (disp, win, None); + + gc = XCreateGC (disp, win, 0, &values); + + XMapRaised (disp, win); + + XSync (disp, FALSE); + + gst_x_overlay_set_window_handle (ov, win); + + if (old_win) { + XDestroyWindow (disp, old_win); + XFreeGC (disp, old_gc); + XSync (disp, FALSE); + } + + return TRUE; +} + +static GstBusSyncReply +create_window (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + GstXOverlay *ov = NULL; + + s = gst_message_get_structure (message); + if (s == NULL || !gst_structure_has_name (s, "prepare-xwindow-id")) { + return GST_BUS_PASS; + } + + ov = GST_X_OVERLAY (GST_MESSAGE_SRC (message)); + + g_print ("Creating our own window\n"); + + cycle_window (ov); + + g_timeout_add (50, (GSourceFunc) resize_window, pipeline); + g_timeout_add (50, (GSourceFunc) move_window, pipeline); + g_timeout_add (100, (GSourceFunc) cycle_window, ov); + g_timeout_add (2000, (GSourceFunc) toggle_events, ov); + + gst_message_unref (message); + return GST_BUS_DROP; +} + +#if 0 +static gboolean +terminate_playback (GstElement * pipeline) +{ + g_print ("Terminating playback\n"); + g_main_loop_quit (loop); + return FALSE; +} +#endif + +static gboolean +pause_playback (GstElement * pipeline) +{ + g_print ("Pausing playback\n"); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + return FALSE; +} + +static gboolean +start_playback (GstElement * pipeline) +{ + g_print ("Starting playback\n"); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + return FALSE; +} + +int +main (int argc, char **argv) +{ + GstElement *pipeline; + GstBus *bus; + +#ifndef GST_DISABLE_PARSE + GError *error = NULL; +#endif + + gst_init (&argc, &argv); + + if (argc != 2) { + g_print ("Usage: %s \"pipeline description with launch format\"\n", + argv[0]); + g_print ("The pipeline should contain an element implementing XOverlay.\n"); + g_print ("Example: %s \"videotestsrc ! ximagesink\"\n", argv[0]); + return -1; + } +#ifdef GST_DISABLE_PARSE + g_print ("GStreamer was built without pipeline parsing capabilities.\n"); + g_print + ("Please rebuild GStreamer with pipeline parsing capabilities activated to use this example.\n"); + return 1; +#else + pipeline = gst_parse_launch (argv[1], &error); + if (error) { + g_print ("Error while parsing pipeline description: %s\n", error->message); + return -1; + } +#endif + + loop = g_main_loop_new (NULL, FALSE); + + open_display (); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_set_sync_handler (bus, (GstBusSyncHandler) create_window, pipeline); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + /* We want to get out after */ + //g_timeout_add (500000, (GSourceFunc) terminate_playback, pipeline); + g_timeout_add (10000, (GSourceFunc) pause_playback, pipeline); + g_timeout_add (20000, (GSourceFunc) start_playback, pipeline); + + g_main_loop_run (loop); + + close_display (); + + g_main_loop_unref (loop); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/test-box.c b/gst-plugins-base-subtitles0.10/tests/icles/test-box.c new file mode 100644 index 0000000..6d04e56 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/test-box.c @@ -0,0 +1,144 @@ +/* GStreamer interactive videoscale test + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +#define CAPS " capsfilter caps=\"video/x-raw-yuv, format=(fourcc)I420, width=(int)640, height=(int)480\" " + +static GstElement * +make_pipeline (gint type) +{ + GstElement *result; + gchar *pstr; + + switch (type) { + case 0: + pstr = + g_strdup_printf ("videotestsrc ! " CAPS + " ! videobox name=box ! videoscale ! " CAPS + " ! ffmpegcolorspace ! ximagesink"); + break; + default: + return NULL; + } + + result = gst_parse_launch_full (pstr, NULL, GST_PARSE_FLAG_NONE, NULL); + g_print ("created test %d: \"%s\"\n", type, pstr); + g_free (pstr); + + return result; +} + +#define MAX_ROUND 100 + +int +main (int argc, char **argv) +{ + GstElement *pipe, *filter; + gint left, right; + gint top, bottom; + gint rdir, ldir; + gint tdir, bdir; + gint round, type, stop; + + gst_init (&argc, &argv); + + type = 0; + stop = -1; + + if (argc > 1) { + type = atoi (argv[1]); + stop = type + 1; + } + + while (TRUE) { + GstMessage *message; + + pipe = make_pipeline (type); + if (pipe == NULL) + break; + + filter = gst_bin_get_by_name (GST_BIN (pipe), "box"); + g_assert (filter); + + /* start with no borders or cropping */ + left = right = top = bottom = 0; + rdir = ldir = tdir = bdir = -10; + + for (round = 0; round < MAX_ROUND; round++) { + g_print ("box to %dx%d %dx%d (%d/%d) \r", left, right, top, bottom, + round, MAX_ROUND); + + g_object_set (filter, "left", left, "right", right, "top", top, "bottom", + bottom, NULL); + + if (round == 0) + gst_element_set_state (pipe, GST_STATE_PLAYING); + + left += ldir; + if (left >= 40) + ldir = -10; + else if (left < -30) + ldir = 10; + + right += rdir; + if (right >= 30) + rdir = -10; + else if (right < -20) + rdir = 10; + + top += tdir; + if (top >= 20) + tdir = -10; + else if (top < -30) + tdir = 10; + + bottom += bdir; + if (bottom >= 60) + bdir = -10; + else if (bottom < -40) + bdir = 10; + + message = + gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, + 50 * GST_MSECOND); + if (message) { + g_print ("got error \n"); + + gst_message_unref (message); + } + } + g_print ("test %d done \n", type); + + gst_object_unref (filter); + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + type++; + if (type == stop) + break; + } + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/test-colorkey.c b/gst-plugins-base-subtitles0.10/tests/icles/test-colorkey.c new file mode 100644 index 0000000..947363c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/test-colorkey.c @@ -0,0 +1,284 @@ +/* GStreamer + * Copyright (C) <2008> Stefan Kost + * + * test-colorkey: test manual colorkey handling + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +#include +#include +#include + +#include +#include +#include + +#if !GTK_CHECK_VERSION (2, 17, 7) +static void +gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a) +{ + *a = w->allocation; +} +#endif + +static GtkWidget *video_window = NULL; +static GstElement *sink = NULL; +static gulong embed_xid = 0; +static GdkColor trans_color; +static gboolean trans_color_set = FALSE; + +static void +redraw_overlay (GtkWidget * widget) +{ + GtkAllocation allocation; + GdkWindow *window = gtk_widget_get_window (widget); + cairo_t *cr; + + cr = gdk_cairo_create (window); + gtk_widget_get_allocation (widget, &allocation); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_rectangle (cr, 0, 0, allocation.width, allocation.height); + cairo_fill (cr); + + if (trans_color_set) { + guint x, y; + guint h = allocation.height * 0.75; + + gdk_cairo_set_source_color (cr, &trans_color); + cairo_rectangle (cr, 0, 0, allocation.width, h); + cairo_fill (cr); + + for (y = h; y < allocation.height; y++) { + for (x = 0; x < allocation.width; x++) { + if (((x & 1) || (y & 1)) && (x & 1) != (y & 1)) { + cairo_move_to (cr, x, y); + cairo_paint (cr); + } + } + } + } +} + +static gboolean +handle_resize_cb (GtkWidget * widget, GdkEventConfigure * event, gpointer data) +{ + redraw_overlay (widget); + return FALSE; +} + +static gboolean +handle_expose_cb (GtkWidget * widget, GdkEventExpose * event, gpointer data) +{ + redraw_overlay (widget); + return FALSE; +} + +static void +realize_cb (GtkWidget * widget, gpointer data) +{ +#if GTK_CHECK_VERSION(2,18,0) + { + GdkWindow *window = gtk_widget_get_window (widget); + + /* This is here just for pedagogical purposes, GDK_WINDOW_XID will call it + * as well */ + if (!gdk_window_ensure_native (window)) + g_error ("Couldn't create native window needed for GstXOverlay!"); + } +#endif + + { + GdkWindow *window = gtk_widget_get_window (video_window); + + embed_xid = GDK_WINDOW_XID (window); + g_print ("Window realize: video window XID = %lu\n", embed_xid); + } +} + +static void +msg_state_changed (GstBus * bus, GstMessage * message, GstPipeline * pipeline) +{ + const GstStructure *s; + + s = gst_message_get_structure (message); + + /* We only care about state changed on the pipeline */ + if (s && GST_MESSAGE_SRC (message) == GST_OBJECT_CAST (pipeline)) { + GstState old, new, pending; + gint color; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + /* When state of the pipeline changes to paused or playing we start updating scale */ + switch (GST_STATE_TRANSITION (old, new)) { + case GST_STATE_CHANGE_READY_TO_PAUSED:{ + g_object_get (G_OBJECT (sink), "colorkey", &color, NULL); + if (color != -1) { + trans_color.red = (color & 0xff0000) >> 8; + trans_color.green = (color & 0xff00); + trans_color.blue = (color & 0xff) << 8; + trans_color_set = TRUE; + } else { + trans_color_set = FALSE; + } + handle_resize_cb (video_window, NULL, NULL); + break; + } + default: + break; + } + } +} + +static void +window_closed (GtkWidget * widget, GdkEvent * event, gpointer user_data) +{ + GstElement *pipeline = user_data; + + g_print ("stopping\n"); + gtk_widget_hide (widget); + gst_element_set_state (pipeline, GST_STATE_NULL); + gtk_main_quit (); +} + +static gboolean +start_pipeline (gpointer user_data) +{ + GstElement *pipeline = GST_ELEMENT (user_data); + GstStateChangeReturn sret; + + sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (sret == GST_STATE_CHANGE_FAILURE) { + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gtk_main_quit (); + } + return FALSE; +} + +int +main (int argc, char **argv) +{ + GtkWidget *window; + GstElement *pipeline, *src; + GstBus *bus; + GstStateChangeReturn sret; + GstPropertyProbe *probe; + GValueArray *arr; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + /* prepare the pipeline */ + + pipeline = gst_pipeline_new ("xvoverlay"); + src = gst_element_factory_make ("videotestsrc", NULL); + sink = gst_element_factory_make ("xvimagesink", NULL); + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + +#define COLOR_GRAY 0x7F7F7F + + g_object_set (G_OBJECT (sink), "autopaint-colorkey", FALSE, + "force-aspect-ratio", TRUE, "draw-borders", FALSE, + "colorkey", COLOR_GRAY, NULL); + + /* check xvimagesink capabilities */ + sret = gst_element_set_state (pipeline, GST_STATE_READY); + if (sret == GST_STATE_CHANGE_FAILURE) { + g_printerr ("Can't set pipeline to READY\n"); + gst_object_unref (pipeline); + return -1; + } + + probe = GST_PROPERTY_PROBE (sink); + if (!probe) { + g_printerr ("Can't probe sink\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return -1; + } + arr = + gst_property_probe_probe_and_get_values_name (probe, + "autopaint-colorkey"); + if (!arr || !arr->n_values) { + g_printerr ("Can't disable autopaint-colorkey property\n"); + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + return -1; + } + if (arr) + g_value_array_free (arr); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_signal_watch_full (bus, G_PRIORITY_HIGH); + g_signal_connect (bus, "message::state-changed", + G_CALLBACK (msg_state_changed), pipeline); + gst_object_unref (bus); + + /* prepare the ui */ + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (window), "delete-event", + G_CALLBACK (window_closed), (gpointer) pipeline); + gtk_window_set_default_size (GTK_WINDOW (window), 320, 240); + + video_window = gtk_drawing_area_new (); + g_signal_connect (G_OBJECT (video_window), "configure-event", + G_CALLBACK (handle_resize_cb), NULL); + g_signal_connect (G_OBJECT (video_window), "expose-event", + G_CALLBACK (handle_expose_cb), NULL); + g_signal_connect (video_window, "realize", G_CALLBACK (realize_cb), NULL); + gtk_widget_set_double_buffered (video_window, FALSE); + gtk_container_add (GTK_CONTAINER (window), video_window); + + /* show the gui and play */ + + gtk_widget_show_all (window); + + /* realize window now so that the video window gets created and we can + * obtain its XID before the pipeline is started up and the videosink + * asks for the XID of the window to render onto */ + gtk_widget_realize (window); + + /* we should have the XID now */ + g_assert (embed_xid != 0); + + /* we know what the video sink is in this case (xvimagesink), so we can + * just set it directly here now (instead of waiting for a prepare-xwindow-id + * element message in a sync bus handler and setting it there) */ + g_print ("setting XID %lu\n", embed_xid); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid); + + g_idle_add (start_pipeline, pipeline); + gtk_main (); + + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/test-scale.c b/gst-plugins-base-subtitles0.10/tests/icles/test-scale.c new file mode 100644 index 0000000..6d13119 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/test-scale.c @@ -0,0 +1,164 @@ +/* GStreamer interactive videoscale test + * Copyright (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +#include + +static GstElement * +make_pipeline (gint type) +{ + GstElement *result; + gchar *pstr; + + switch (type) { + case 0: + pstr = g_strdup_printf ("videotestsrc ! capsfilter name=filter ! " + "ximagesink"); + break; + case 1: + pstr = g_strdup_printf ("videotestsrc ! queue ! capsfilter name=filter ! " + "ximagesink"); + break; + case 2: + pstr = g_strdup_printf ("videotestsrc peer-alloc=0 ! videoscale ! " + "capsfilter name=filter ! " "ximagesink"); + break; + case 3: + pstr = + g_strdup_printf ("videotestsrc peer-alloc=0 ! queue ! videoscale ! " + "capsfilter name=filter ! " "ximagesink"); + break; + case 4: + pstr = + g_strdup_printf ("videotestsrc peer-alloc=0 ! videoscale ! queue ! " + "capsfilter name=filter ! " "ximagesink"); + break; + case 5: + pstr = g_strdup_printf ("videotestsrc peer-alloc=0 ! " + "capsfilter name=filter ! " "ximagesink"); + break; + case 6: + pstr = g_strdup_printf ("videotestsrc ! videoscale ! " + "capsfilter name=filter ! " "ximagesink"); + break; + case 7: + pstr = g_strdup_printf ("v4l2src ! ffmpegcolorspace ! videoscale ! " + "capsfilter name=filter ! " "ximagesink"); + break; + default: + return NULL; + } + + result = gst_parse_launch_full (pstr, NULL, GST_PARSE_FLAG_NONE, NULL); + g_print ("created test %d: \"%s\"\n", type, pstr); + g_free (pstr); + + return result; +} + +#define MAX_ROUND 100 + +int +main (int argc, char **argv) +{ + GstElement *pipe, *filter; + GstCaps *caps; + gint width, height; + gint xdir, ydir; + gint round, type, stop; + + gst_init (&argc, &argv); + + type = 0; + stop = -1; + + if (argc > 1) { + type = atoi (argv[1]); + stop = type + 1; + } + + while (TRUE) { + GstMessage *message; + + pipe = make_pipeline (type); + if (pipe == NULL) + break; + + filter = gst_bin_get_by_name (GST_BIN (pipe), "filter"); + g_assert (filter); + + width = 320; + height = 240; + xdir = ydir = -10; + + for (round = 0; round < MAX_ROUND; round++) { + gchar *capsstr; + g_print ("resize to %dx%d (%d/%d) \r", width, height, round, MAX_ROUND); + + /* we prefer our fixed width and height but allow other dimensions to pass + * as well */ + capsstr = + g_strdup_printf ("video/x-raw-rgb, width=(int)%d, height=(int)%d;" + "video/x-raw-rgb", width, height); + caps = gst_caps_from_string (capsstr); + g_free (capsstr); + g_object_set (filter, "caps", caps, NULL); + gst_caps_unref (caps); + + if (round == 0) + gst_element_set_state (pipe, GST_STATE_PLAYING); + + width += xdir; + if (width >= 320) + xdir = -10; + else if (width < 200) + xdir = 10; + + height += ydir; + if (height >= 240) + ydir = -10; + else if (height < 150) + ydir = 10; + + message = + gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, + 50 * GST_MSECOND); + if (message) { + g_print ("got error \n"); + + gst_message_unref (message); + } + } + g_print ("test %d done \n", type); + + gst_object_unref (filter); + gst_element_set_state (pipe, GST_STATE_NULL); + gst_object_unref (pipe); + + type++; + if (type == stop) + break; + } + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/test-textoverlay.c b/gst-plugins-base-subtitles0.10/tests/icles/test-textoverlay.c new file mode 100644 index 0000000..8d989a8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/test-textoverlay.c @@ -0,0 +1,125 @@ +/* GStreamer interactive textoverlay test + * Copyright (C) 2007 Tim-Philipp Müller + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +static void +set_enum_property_by_name (gpointer object, const gchar * prop, + const gchar * value) +{ + GParamSpec *pspec; + GValue val = { 0, }; + GEnumClass *eclass; + GEnumValue *eval; + + pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (object), prop); + g_return_if_fail (pspec != NULL); + + g_value_init (&val, pspec->value_type); + g_object_get_property (G_OBJECT (object), prop, &val); + eclass = G_ENUM_CLASS (g_type_class_peek (G_VALUE_TYPE (&val))); + g_return_if_fail (eclass != NULL); + eval = g_enum_get_value_by_name (eclass, value); + if (eval == NULL) + eval = g_enum_get_value_by_nick (eclass, value); + g_return_if_fail (eval != NULL); + g_value_set_enum (&val, eval->value); + g_object_set_property (G_OBJECT (object), prop, &val); + g_value_unset (&val); +} + +static void +show_text (GstElement * textoverlay, const gchar * txt, const gchar * valign, + const gchar * halign, const gchar * line_align) +{ + GstElement *pipe; + + g_object_set (textoverlay, "text", txt, NULL); + + set_enum_property_by_name (textoverlay, "valignment", valign); + set_enum_property_by_name (textoverlay, "halignment", halign); + set_enum_property_by_name (textoverlay, "line-alignment", line_align); + + pipe = textoverlay; + while (GST_ELEMENT_PARENT (pipe)) + pipe = GST_ELEMENT_PARENT (pipe); + + gst_element_set_state (pipe, GST_STATE_PLAYING); + gst_bus_poll (GST_ELEMENT_BUS (pipe), GST_MESSAGE_ERROR, GST_SECOND); + gst_element_set_state (pipe, GST_STATE_NULL); +} + +static void +test_textoverlay (int width, int height) +{ + const gchar *valigns[] = { /* "baseline", */ "bottom", "top" }; + const gchar *haligns[] = { "left", "center", "right" }; + const gchar *linealigns[] = { "left", "center", "right" }; + GstElement *pipe, *toverlay; + gchar *pstr; + gint a, b, c; + + pstr = g_strdup_printf ("videotestsrc pattern=blue ! " + "video/x-raw-yuv,width=%d,height=%d ! t.video_sink " + "textoverlay name=t font-desc=\"Sans Serif, 20\" ! " + " ffmpegcolorspace ! videoscale ! autovideosink", width, height); + + pipe = gst_parse_launch_full (pstr, NULL, GST_PARSE_FLAG_NONE, NULL); + g_assert (pipe); + + toverlay = gst_bin_get_by_name (GST_BIN (pipe), "t"); + g_assert (toverlay); + + g_object_set (toverlay, "xpad", 3, "ypad", 3, NULL); + + for (a = 0; a < G_N_ELEMENTS (valigns); ++a) { + for (b = 0; b < G_N_ELEMENTS (haligns); ++b) { + for (c = 0; c < G_N_ELEMENTS (linealigns); ++c) { + gchar *s; + + s = g_strdup_printf ("line-alignment = %s\n" + "<----- halignment = %s ----->\nvalignment = %s", + linealigns[c], haligns[b], valigns[a]); + show_text (toverlay, s, valigns[a], haligns[b], linealigns[c]); + g_free (s); + } + } + } + + g_free (pstr); +} + +int +main (int argc, char **argv) +{ + gst_init (&argc, &argv); + + test_textoverlay (640, 480); + + g_print ("Now with odd width/height ...\n"); + test_textoverlay (639, 479); + + /* test_textoverlay (796, 256); */ + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/icles/test-xoverlay.c b/gst-plugins-base-subtitles0.10/tests/icles/test-xoverlay.c new file mode 100644 index 0000000..c129b41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/icles/test-xoverlay.c @@ -0,0 +1,247 @@ +/* GStreamer + * Copyright (C) <2008> Stefan Kost + * + * test-xoverlay: test xoverlay custom event handling and subregions + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if !GTK_CHECK_VERSION (2, 17, 7) +static void +gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a) +{ + *a = w->allocation; +} +#endif + +static struct +{ + gint w, h; + GstXOverlay *overlay; + GtkWidget *widget; + gdouble a, p; + GstVideoRectangle rect; + gboolean running; +} anim_state; + +static gboolean verbose = FALSE; + +static gboolean +animate_render_rect (gpointer user_data) +{ + if (anim_state.running) { + GstVideoRectangle *r = &anim_state.rect; + gdouble s = sin (3.0 * anim_state.a); + gdouble c = cos (2.0 * anim_state.a); + + anim_state.a += anim_state.p; + if (anim_state.a > (M_PI + M_PI)) + anim_state.a -= (M_PI + M_PI); + + r->w = anim_state.w / 2; + r->x = (r->w - (r->w / 2)) + c * (r->w / 2); + r->h = anim_state.h / 2; + r->y = (r->h - (r->h / 2)) + s * (r->h / 2); + + gst_x_overlay_set_render_rectangle (anim_state.overlay, r->x, r->y, + r->w, r->h); + gtk_widget_queue_draw (anim_state.widget); + } + return TRUE; +} + +static gboolean +handle_resize_cb (GtkWidget * widget, GdkEventConfigure * event, + gpointer user_data) +{ + GtkAllocation allocation; + + gtk_widget_get_allocation (widget, &allocation); + + if (verbose) { + g_print ("resize(%p): %dx%d\n", widget, allocation.width, + allocation.height); + } + anim_state.w = allocation.width; + anim_state.h = allocation.height; + animate_render_rect (NULL); + + return FALSE; +} + +static gboolean +handle_expose_cb (GtkWidget * widget, GdkEventExpose * event, + gpointer user_data) +{ + GstVideoRectangle *r = &anim_state.rect; + GtkAllocation allocation; + GdkWindow *window; + GtkStyle *style; + cairo_t *cr; + + style = gtk_widget_get_style (widget); + window = gtk_widget_get_window (widget); + gtk_widget_get_allocation (widget, &allocation); + cr = gdk_cairo_create (window); + + gdk_cairo_set_source_color (cr, &style->bg[GTK_STATE_NORMAL]); + + /* we should only redraw outside of the video rect! */ + cairo_rectangle (cr, 0, event->area.y, r->x, event->area.height); + cairo_rectangle (cr, r->x + r->w, event->area.y, + allocation.width - (r->x + r->w), event->area.height); + + cairo_rectangle (cr, event->area.x, 0, event->area.width, r->y); + cairo_rectangle (cr, event->area.x, r->y + r->h, + event->area.width, allocation.height - (r->y + r->h)); + + cairo_fill (cr); + + cairo_destroy (cr); + + if (verbose) { + g_print ("expose(%p)\n", widget); + } + gst_x_overlay_expose (anim_state.overlay); + return FALSE; +} + +static void +window_closed (GtkWidget * widget, GdkEvent * event, gpointer user_data) +{ + GstElement *pipeline = user_data; + + if (verbose) { + g_print ("stopping\n"); + } + anim_state.running = FALSE; + gtk_widget_hide (widget); + gst_element_set_state (pipeline, GST_STATE_NULL); + gtk_main_quit (); +} + +gint +main (gint argc, gchar ** argv) +{ + GdkWindow *video_window_xwindow; + GtkWidget *window, *video_window; + GstElement *pipeline, *src, *sink; + GstStateChangeReturn sret; + gulong embed_xid = 0; + gboolean force_aspect = FALSE, draw_borders = FALSE; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + if (argc) { + gint arg; + for (arg = 0; arg < argc; arg++) { + if (!strcmp (argv[arg], "-a")) + force_aspect = TRUE; + else if (!strcmp (argv[arg], "-b")) + draw_borders = TRUE; + else if (!strcmp (argv[arg], "-v")) + verbose = TRUE; + } + } + + /* prepare the pipeline */ + + pipeline = gst_pipeline_new ("xvoverlay"); + src = gst_element_factory_make ("videotestsrc", NULL); + sink = gst_element_factory_make ("xvimagesink", NULL); + gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); + gst_element_link (src, sink); + + g_object_set (G_OBJECT (sink), "handle-events", FALSE, + "force-aspect-ratio", force_aspect, "draw-borders", draw_borders, NULL); + + /* prepare the ui */ + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (window), "delete-event", + G_CALLBACK (window_closed), (gpointer) pipeline); + gtk_window_set_default_size (GTK_WINDOW (window), 320, 240); + + video_window = gtk_drawing_area_new (); + gtk_widget_set_double_buffered (video_window, FALSE); + gtk_container_add (GTK_CONTAINER (window), video_window); + + /* show the gui and play */ + gtk_widget_show_all (window); + + /* realize window now so that the video window gets created and we can + * obtain its XID before the pipeline is started up and the videosink + * asks for the XID of the window to render onto */ + gtk_widget_realize (window); + + video_window_xwindow = gtk_widget_get_window (video_window); + embed_xid = GDK_WINDOW_XID (video_window_xwindow); + if (verbose) { + g_print ("Window realize: got XID %lu\n", embed_xid); + } + + /* we know what the video sink is in this case (xvimagesink), so we can + * just set it directly here now (instead of waiting for a prepare-xwindow-id + * element message in a sync bus handler and setting it there) */ + gst_x_overlay_set_window_handle (GST_X_OVERLAY (sink), embed_xid); + + anim_state.overlay = GST_X_OVERLAY (sink); + anim_state.widget = video_window; + anim_state.w = 320; + anim_state.h = 240; + anim_state.a = 0.0; + anim_state.p = (M_PI + M_PI) / 200.0; + + handle_resize_cb (video_window, NULL, sink); + g_signal_connect (video_window, "configure-event", + G_CALLBACK (handle_resize_cb), NULL); + g_signal_connect (video_window, "expose-event", + G_CALLBACK (handle_expose_cb), NULL); + + g_timeout_add (50, (GSourceFunc) animate_render_rect, NULL); + + /* run the pipeline */ + sret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + if (sret == GST_STATE_CHANGE_FAILURE) + gst_element_set_state (pipeline, GST_STATE_NULL); + else { + anim_state.running = TRUE; + gtk_main (); + } + + gst_object_unref (pipeline); + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/Makefile.am new file mode 100644 index 0000000..c376eaa --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/Makefile.am @@ -0,0 +1,26 @@ +if USE_ALSA +ALSA_DIR=alsa +else +ALSA_DIR= +endif + +# if HAVE_GTK +# EMBED_DIR=embed +# else +# EMBED_DIR= +# endif + +SUBDIRS = \ + $(ALSA_DIR) #seeking +DIST_SUBDIRS = \ + alsa + +GST_PLUGIN_PATH=$(shell cd $(top_builddir) && pwd) + +#$(TESTS): +# @echo -e '\nrunning gst-register...\n' +# $(GST_TOOLS_DIR)/gst-register --gst-plugin-path=$(GST_PLUGIN_PATH) + +#TESTS=$(GST_TOOLS_DIR)/gst-compprep + +.PHONY: $(TESTS) diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/Makefile.am new file mode 100644 index 0000000..b443119 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/Makefile.am @@ -0,0 +1,15 @@ +if HAVE_FT2 +FT2_SUBDIRS=seeking +else +FT2_SUBDIRS= +endif + +# if HAVE_GTK +# GTK_SUBDIRS=dynparams $(FT2_SUBDIRS) +# else +GTK_SUBDIRS= +# endif + +SUBDIRS=$(GTK_SUBDIRS) +#DIST_SUBDIRS=capsfilter seeking indexing switch +DIST_SUBDIRS=seeking diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/Makefile.am new file mode 100644 index 0000000..f8562fe --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/Makefile.am @@ -0,0 +1,6 @@ +noinst_PROGRAMS = capsfilter1 + +LDADD = $(GST_LIBS) +AM_CFLAGS = $(GST_CFLAGS) + + diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/capsfilter1.c b/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/capsfilter1.c new file mode 100644 index 0000000..a59f728 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/capsfilter/capsfilter1.c @@ -0,0 +1,87 @@ +#include +#include + +/* This app uses a filter to connect colorspace and videosink + * so that only RGB data can pass the connection, colorspace will use + * a converter to convert the I420 data to RGB. Without a filter, this + * connection would use the I420 format (assuming Xv is enabled) */ + +static void +new_pad_func (GstElement * element, GstPad * newpad, gpointer data) +{ + GstElement *pipeline = (GstElement *) data; + GstElement *queue = gst_bin_get_by_name (GST_BIN (pipeline), "queue"); + + if (!strcmp (gst_pad_get_name (newpad), "video_00")) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_pad_link (newpad, gst_element_get_pad (queue, "sink")); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + } +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline; + GstElement *filesrc; + GstElement *demux; + GstElement *thread; + GstElement *queue; + GstElement *mpeg2dec; + GstElement *colorspace; + GstElement *videosink; + gboolean res; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return (-1); + } + + pipeline = gst_pipeline_new ("main_pipeline"); + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_return_val_if_fail (filesrc, -1); + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + demux = gst_element_factory_make ("mpegdemux", "demux"); + g_return_val_if_fail (demux, -1); + g_signal_connect (G_OBJECT (demux), "new_pad", G_CALLBACK (new_pad_func), + pipeline); + + thread = gst_thread_new ("thread"); + queue = gst_element_factory_make ("queue", "queue"); + mpeg2dec = gst_element_factory_make ("mpeg2dec", "mpeg2dec"); + g_return_val_if_fail (mpeg2dec, -1); + colorspace = gst_element_factory_make ("ffmpegcolorspace", "colorspace"); + g_return_val_if_fail (colorspace, -1); + videosink = gst_element_factory_make (DEFAULT_VIDEOSINK, "videosink"); + g_return_val_if_fail (videosink, -1); + + gst_bin_add (GST_BIN (pipeline), filesrc); + gst_bin_add (GST_BIN (pipeline), demux); + + gst_bin_add (GST_BIN (thread), queue); + gst_bin_add (GST_BIN (thread), mpeg2dec); + gst_bin_add (GST_BIN (thread), colorspace); + gst_bin_add (GST_BIN (thread), videosink); + gst_bin_add (GST_BIN (pipeline), thread); + + gst_element_link_pads (filesrc, "src", demux, "sink"); + gst_element_link_pads (queue, "src", mpeg2dec, "sink"); + gst_element_link_pads (mpeg2dec, "src", colorspace, "sink"); + /* force RGB data passing between colorspace and videosink */ + res = gst_element_link_pads_filtered (colorspace, "src", videosink, "sink", + gst_caps_new_simple ("video/x-raw-rgb", NULL)); + if (!res) { + g_print ("could not connect colorspace and videosink\n"); + return -1; + } + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + while (gst_bin_iterate (GST_BIN (pipeline))); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/gob/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/gob/Makefile.am new file mode 100644 index 0000000..7abde4d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/gob/Makefile.am @@ -0,0 +1,19 @@ + +plugin_LTLIBRARIES = libgstidentity2.la + +GOB_FILES_ID = gst-identity2.c gst-identity2.h gst-identity2-private.h + +BUILT_SOURCES = \ + $(GOB_FILES_ID) + +libgstidentity2_la_SOURCES = gst-identity2.gob $(GOB_FILES_ID) +libgstidentity2_la_CFLAGS = $(GST_CFLAGS) +libgstidentity2_la_LIBADD = + +%.c %.h %-private.h: %.gob + gob $< + +CLEANFILES = $(GOB_FILES_ID) + +dist-hook: + cd $(distdir); rm -f $(CLEANFILES) diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/gob/gst-identity2.gob b/gst-plugins-base-subtitles0.10/tests/old/examples/gob/gst-identity2.gob new file mode 100644 index 0000000..2c58f06 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/gob/gst-identity2.gob @@ -0,0 +1,139 @@ + +%header{ +#include +#include "gst-identity2.h" +#include "gst-identity2-private.h" +%} + +class Gst:Identity2 from Gst:Element { + + /* plugin init */ + private gboolean + plugin_init (GModule *module, GstPlugin *plugin) + { + static GstElementDetails identity2_details = + GST_ELEMENT_DETAILS ( + "GOB Identity", + "Filter/Effect", + "Does nothing", + "Wim Taymans "); + GstElementFactory *factory; + + factory = gst_elementfactory_new ("identity2", TYPE_SELF, + &identity2_details); + g_return_val_if_fail (factory != NULL, FALSE); + + gst_plugin_add_feature (plugin, &(factory->feature)); + + return TRUE; + } + + /* pads FIXME gob oculd be improved here */ + private GstPad *sinkpad = + { + gst_pad_new ("sink", GST_PAD_SINK); + gst_element_add_pad (GST_ELEMENT (o), o->_priv->sinkpad); + gst_pad_set_chain_function (o->_priv->sinkpad, chain); + gst_pad_set_bufferpool_function (o->_priv->sinkpad, get_bufferpool); + //gst_pad_set_negotiate_function (o->_priv->sinkpad, negotiate_sink); + }; + private GstPad *srcpad = + { + gst_pad_new ("src", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (o), o->_priv->srcpad); + //gst_pad_set_negotiate_function (o->_priv->srcpad, negotiate_src); + }; + + /* arguments */ + /* + private gboolean loop_based = FALSE; argument BOOL loop_based + get { + ARG = self->_priv->loop_based; + } + set { + self->_priv->loop_based = ARG; + if (self->_priv->loop_based) { + gst_element_set_loop_function (GST_ELEMENT (self), loop); + gst_pad_set_chain_function (self->_priv->sinkpad, NULL); + } + else { + gst_pad_set_chain_function (self->_priv->sinkpad, chain); + gst_element_set_loop_function (GST_ELEMENT (self), NULL); + } + };*/ + private guint sleep_time = 0; argument UINT sleep_time link; + private gboolean silent = FALSE; argument BOOL silent link; + + /* signals */ + private signal last NONE(NONE) void handoff(self); + + /* core code here */ + private GstBufferPool* + get_bufferpool (GstPad *pad (check null)) + { + Self *self = SELF (gst_pad_get_parent (pad)); + + return gst_pad_get_bufferpool (self->_priv->srcpad); + } + + /* private GstPadNegotiateReturn + negotiate_src (GstPad *pad, GstCaps **caps, gpointer *data) + { + Self *self = SELF (gst_pad_get_parent (pad)); + + return gst_pad_negotiate_proxy (pad, self->_priv->sinkpad, caps); + } + + private GstPadNegotiateReturn + negotiate_sink (GstPad *pad, GstCaps **caps, gpointer *data) + { + Self *self = SELF (gst_pad_get_parent (pad)); + + return gst_pad_negotiate_proxy (pad, self->_priv->srcpad, caps); + } */ + + private void + chain (GstPad *pad (check null), GstBuffer *buf (check null)) + { + Self *self; + + self = SELF (gst_pad_get_parent (pad)); + + if (!self->_priv->silent) + g_print("identity2: chain ******* (%s:%s)i \n",GST_DEBUG_PAD_NAME(pad)); + + handoff (self); + gst_pad_push (self->_priv->srcpad, buf); + + if (self->_priv->sleep_time) + usleep (self->_priv->sleep_time); + } + + /*private void + loop (GstElement *element (check null)) + { + Self *self = SELF (element); + GstBuffer *buf; + + do { + buf = gst_pad_pull (self->_priv->sinkpad); + g_print("identity2: loop ******* (%s:%s)i \n",GST_DEBUG_PAD_NAME(self->_priv->sinkpad)); + + handoff (self); + gst_pad_push (self->_priv->srcpad, buf); + + if (self->_priv->sleep_time) + usleep (self->_priv->sleep_time); + + } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element)); + }*/ +} + +%{ +GstPluginDesc plugin_desc = { + GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "identity2", + gst_identity2_plugin_init +}; +%} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/.gitignore b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/.gitignore new file mode 100644 index 0000000..5ce0947 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/.gitignore @@ -0,0 +1 @@ +indexmpeg diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/Makefile.am new file mode 100644 index 0000000..022bfc8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/Makefile.am @@ -0,0 +1,7 @@ +examples = indexmpeg + +noinst_PROGRAMS = $(examples) + +# we have nothing but apps here, we can do this safely +LIBS = $(GST_LIBS) $(GTK_LIBS) +AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/indexmpeg.c b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/indexmpeg.c new file mode 100644 index 0000000..a670ad8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/indexing/indexmpeg.c @@ -0,0 +1,321 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include + +static gboolean verbose = FALSE; +static gboolean quiet = FALSE; + +static void +entry_added (GstIndex * index, GstIndexEntry * entry) +{ + switch (entry->type) { + case GST_INDEX_ENTRY_ID: + g_print ("id %d describes writer %s\n", entry->id, + GST_INDEX_ID_DESCRIPTION (entry)); + break; + case GST_INDEX_ENTRY_FORMAT: + g_print ("%d: registered format %d for %s\n", entry->id, + GST_INDEX_FORMAT_FORMAT (entry), GST_INDEX_FORMAT_KEY (entry)); + break; + case GST_INDEX_ENTRY_ASSOCIATION: + { + gint i; + + g_print ("%p, %d: %08x ", entry, entry->id, + GST_INDEX_ASSOC_FLAGS (entry)); + for (i = 0; i < GST_INDEX_NASSOCS (entry); i++) { + g_print ("%d %" G_GINT64_FORMAT " ", GST_INDEX_ASSOC_FORMAT (entry, i), + GST_INDEX_ASSOC_VALUE (entry, i)); + } + g_print ("\n"); + break; + } + default: + break; + } +} + +typedef struct +{ + const gchar *padname; + GstPad *target; + GstElement *bin; + GstElement *pipeline; + GstIndex *index; +} +dyn_link; + +static void +dynamic_link (GstPadTemplate * templ, GstPad * newpad, gpointer data) +{ + dyn_link *link = (dyn_link *) data; + + if (!strcmp (gst_pad_get_name (newpad), link->padname)) { + gst_element_set_state (link->pipeline, GST_STATE_PAUSED); + gst_bin_add (GST_BIN (link->pipeline), link->bin); + gst_pad_link (newpad, link->target); + gst_element_set_index (link->bin, link->index); + gst_element_set_state (link->pipeline, GST_STATE_PLAYING); + } +} + +static void +setup_dynamic_linking (GstElement * pipeline, + GstElement * element, + const gchar * padname, GstPad * target, GstElement * bin, GstIndex * index) +{ + dyn_link *link; + + link = g_new0 (dyn_link, 1); + link->padname = g_strdup (padname); + link->target = target; + link->bin = bin; + link->pipeline = pipeline; + link->index = index; + + g_signal_connect (G_OBJECT (element), "new_pad", G_CALLBACK (dynamic_link), + link); +} + +static GstElement * +make_mpeg_systems_pipeline (const gchar * path, GstIndex * index) +{ + GstElement *pipeline; + GstElement *src, *demux; + + pipeline = gst_pipeline_new ("pipeline"); + + src = gst_element_factory_make ("filesrc", "src"); + g_object_set (G_OBJECT (src), "location", path, NULL); + + demux = gst_element_factory_make ("mpegdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + + if (index) { + gst_element_set_index (pipeline, index); + } + + gst_element_link_pads (src, "src", demux, "sink"); + + return pipeline; +} + +static GstElement * +make_mpeg_decoder_pipeline (const gchar * path, GstIndex * index) +{ + GstElement *pipeline; + GstElement *src, *demux; + GstElement *video_bin, *audio_bin; + GstElement *video_decoder, *audio_decoder; + + pipeline = gst_pipeline_new ("pipeline"); + + src = gst_element_factory_make ("filesrc", "src"); + g_object_set (G_OBJECT (src), "location", path, NULL); + + demux = gst_element_factory_make ("mpegdemux", "demux"); + + gst_bin_add (GST_BIN (pipeline), src); + gst_bin_add (GST_BIN (pipeline), demux); + + gst_element_link_pads (src, "src", demux, "sink"); + + video_bin = gst_bin_new ("video_bin"); + video_decoder = gst_element_factory_make ("mpeg2dec", "video_decoder"); + + gst_bin_add (GST_BIN (video_bin), video_decoder); + + setup_dynamic_linking (pipeline, demux, "video_00", + gst_element_get_pad (video_decoder, "sink"), video_bin, index); + + audio_bin = gst_bin_new ("audio_bin"); + audio_decoder = gst_element_factory_make ("mad", "audio_decoder"); + + setup_dynamic_linking (pipeline, demux, "audio_00", + gst_element_get_pad (audio_decoder, "sink"), audio_bin, index); + + gst_bin_add (GST_BIN (audio_bin), audio_decoder); + + if (index) { + gst_element_set_index (pipeline, index); + } + + return pipeline; +} + +static void +print_progress (GstPad * pad) +{ + gint i = 0; + gchar status[53]; + GstFormat format; + gboolean res; + gint64 value; + gint percent = 0; + + status[0] = '|'; + + format = GST_FORMAT_PERCENT; + res = gst_pad_query (pad, GST_QUERY_POSITION, &format, &value); + if (res) { + percent = value / (2 * GST_FORMAT_PERCENT_SCALE); + } + + for (i = 0; i < percent; i++) { + status[i + 1] = '='; + } + for (i = percent; i < 50; i++) { + status[i + 1] = ' '; + } + status[51] = '|'; + status[52] = 0; + + g_print ("%s\r", status); +} + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline; + GstElement *src; + GstPad *pad; + GstIndex *index; + gint count = 0; + GstEvent *event; + gboolean res; + GstElement *sink; + struct poptOption options[] = { + {"verbose", 'v', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &verbose, 0, + "Print index entries", NULL}, + {"quiet", 'q', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &quiet, 0, + "don't print progress bar", NULL}, + POPT_TABLEEND + }; + + if (!gst_init_check_with_popt_table (&argc, &argv, options) || argc < 3) { + g_print ("usage: %s [-v] \n" + " type can be: 0 mpeg_systems\n" + " 1 mpeg_decoder\n" + " -v : report added index entries\n" + " -q : don't print progress\n", argv[0]); + return -1; + } + + /* create index that elements can fill */ + index = gst_index_factory_make ("memindex"); + if (index) { + if (verbose) + g_signal_connect (G_OBJECT (index), "entry_added", + G_CALLBACK (entry_added), NULL); + + g_object_set (G_OBJECT (index), "resolver", 1, NULL); + } + + /* construct pipeline */ + switch (atoi (argv[1])) { + case 0: + pipeline = make_mpeg_systems_pipeline (argv[2], index); + break; + case 1: + pipeline = make_mpeg_decoder_pipeline (argv[2], index); + break; + default: + g_print ("unknown type %d\n", atoi (argv[1])); + return -1; + } + + /* setup some default info/error handlers */ + g_signal_connect (G_OBJECT (pipeline), "deep_notify", + G_CALLBACK (gst_element_default_deep_notify), NULL); + g_signal_connect (G_OBJECT (pipeline), "error", + G_CALLBACK (gst_element_default_error), NULL); + + /* get a pad to perform progress reporting on */ + src = gst_bin_get_by_name (GST_BIN (pipeline), "src"); + pad = gst_element_get_pad (src, "src"); + + /* prepare for iteration */ + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + g_print ("indexing %s...\n", argv[2]); + /* run through the complete stream to let it generate an index */ + while (gst_bin_iterate (GST_BIN (pipeline))) { + if (!quiet && (count % 1000 == 0)) { + print_progress (pad); + } + count++; + } + g_print ("\n"); + + /* bring to ready to restart the pipeline */ + gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + if (index) + GST_OBJECT_FLAG_UNSET (index, GST_INDEX_WRITABLE); + + src = gst_bin_get_by_name (GST_BIN (pipeline), "video_decoder"); + + { + gint id; + GstIndexEntry *entry; + gint64 result; + gint total_tm; + + gst_index_get_writer_id (index, GST_OBJECT (src), &id); + + entry = gst_index_get_assoc_entry (index, id, GST_INDEX_LOOKUP_BEFORE, 0, + GST_FORMAT_TIME, G_MAXINT64); + g_assert (entry); + gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &result); + total_tm = result * 60 / GST_SECOND; + g_print ("total time = %.2fs\n", total_tm / 60.0); + } + + pad = gst_element_get_pad (src, "src"); + sink = gst_element_factory_make ("fakesink", "sink"); + gst_element_link_pads (src, "src", sink, "sink"); + gst_bin_add (GST_BIN (pipeline), sink); + + g_print ("seeking %s...\n", argv[2]); + event = gst_event_new_seek (GST_FORMAT_TIME | + GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, 5 * GST_SECOND); + + res = gst_pad_send_event (pad, event); + if (!res) { + g_warning ("seek failed"); + } + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + count = 0; + while (gst_bin_iterate (GST_BIN (pipeline))) { + if (!quiet && (count % 1000 == 0)) { + print_progress (pad); + } + count++; + } + + gst_element_set_state (pipeline, GST_STATE_NULL); + + return 1; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/seek/.gitignore b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/.gitignore new file mode 100644 index 0000000..fcb1d20 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/.gitignore @@ -0,0 +1,6 @@ +cdparanoia +cdplayer +seek +spider_seek +vorbisfile + diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/seek/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/Makefile.am new file mode 100644 index 0000000..b53022b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/Makefile.am @@ -0,0 +1,7 @@ +examples = seek scrubby #cdplayer cdparanoia + +noinst_PROGRAMS = $(examples) + +# we have nothing but apps here, we can do this safely +LIBS = $(GST_LIBS) $(GTK_LIBS) +AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdparanoia.c b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdparanoia.c new file mode 100644 index 0000000..f5b8c32 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdparanoia.c @@ -0,0 +1,215 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +static void +get_position_info (GstElement * cdparanoia) +{ + GstFormat track_format; + const GstFormat *formats; + GstPad *pad; + + track_format = gst_format_get_by_nick ("track"); + g_assert (track_format != 0); + + pad = gst_element_get_pad (cdparanoia, "src"); + formats = gst_pad_get_formats (pad); + + while (*formats) { + const GstFormatDefinition *definition; + GstFormat format; + gint64 position; + gboolean res; + + definition = gst_format_get_details (*formats); + + format = *formats; + res = gst_pad_query (pad, GST_QUERY_POSITION, &format, &position); + + if (format == GST_FORMAT_TIME) { + position /= GST_SECOND; + g_print ("%s: %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT, + definition->nick, position / 60, position % 60); + } else { + g_print ("%s: %" G_GINT64_FORMAT, definition->nick, position); + } + + formats++; + if (*formats) { + g_print (", "); + } + } + g_print ("\r"); +} + +static void +get_track_info (GstElement * cdparanoia) +{ + GstFormat track_format; + gint64 total_tracks = 0, total_time = 0; + GstPad *pad; + const GstFormat *formats; + gint i; + gint64 time_count = 0; + + track_format = gst_format_get_by_nick ("track"); + g_assert (track_format != 0); + + pad = gst_element_get_pad (cdparanoia, "src"); + formats = gst_pad_get_formats (pad); + + /* we loop over all supported formats and report the total + * number of them */ + while (*formats) { + const GstFormatDefinition *definition; + gint64 total; + GstFormat format; + gboolean res; + + definition = gst_format_get_details (*formats); + + format = *formats; + res = gst_pad_query (pad, GST_QUERY_TOTAL, &format, &total); + if (res) { + if (format == GST_FORMAT_TIME) { + total /= GST_SECOND; + g_print ("%s total: %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "\n", + definition->nick, total / 60, total % 60); + } else + g_print ("%s total: %" G_GINT64_FORMAT "\n", definition->nick, total); + + if (format == track_format) + total_tracks = total; + else if (format == GST_FORMAT_TIME) + total_time = total; + } else + g_print ("failed to get %s total\n", definition->nick); + + formats++; + } + + /* then we loop over all the tracks to get more info. + * since pad_convert always works from 0, the time from track 1 needs + * to be substracted from track 2 */ + for (i = 0; i <= total_tracks; i++) { + gint64 time; + gboolean res; + + if (i < total_tracks) { + GstFormat format; + + format = GST_FORMAT_TIME; + res = gst_pad_convert (pad, track_format, i, &format, &time); + time /= GST_SECOND; + } else { + time = total_time; + res = TRUE; + } + + if (res) { + /* for the first track (i==0) we wait until we have the + * time of the next track */ + if (i > 0) { + gint64 length = time - time_count; + + g_print ("track %d: %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT + " -> %" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ", length: %" + G_GINT64_FORMAT ":%02" G_GINT64_FORMAT "\n", + i - 1, + time_count / 60, time_count % 60, + time / 60, time % 60, length / 60, length % 60); + } + } else { + g_print ("could not get time for track %d\n", i); + } + + time_count = time; + } +} + +int +main (int argc, char **argv) +{ + GstElement *pipeline; + GstElement *cdparanoia; + GstElement *audiosink; + GstPad *pad; + GstFormat track_format; + GstEvent *event; + gint count; + gboolean res; + + gst_init (&argc, &argv); + + pipeline = gst_pipeline_new ("pipeline"); + + cdparanoia = gst_element_factory_make ("cdparanoia", "cdparanoia"); + g_assert (cdparanoia); + g_object_set (G_OBJECT (cdparanoia), "paranoia_mode", 0, NULL); + + audiosink = gst_element_factory_make (DEFAULT_AUDIOSINK, DEFAULT_AUDIOSINK); + g_assert (audiosink); + + gst_bin_add (GST_BIN (pipeline), cdparanoia); + gst_bin_add (GST_BIN (pipeline), audiosink); + + gst_element_link_pads (cdparanoia, "src", audiosink, "sink"); + + g_signal_connect (G_OBJECT (pipeline), "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + /* now we go into probe mode */ + get_track_info (cdparanoia); + + track_format = gst_format_get_by_nick ("track"); + g_assert (track_format != 0); + + pad = gst_element_get_pad (cdparanoia, "src"); + g_assert (pad); + + g_print ("playing from track 3\n"); + /* seek to track3 */ + event = gst_event_new_seek (track_format | + GST_SEEK_METHOD_SET | GST_SEEK_FLAG_FLUSH, 3); + + res = gst_pad_send_event (pad, event); + if (!res) + g_warning ("seek failed"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + count = 0; + while (count++ < 500) { + get_position_info (cdparanoia); + g_usleep (G_USEC_PER_SEC / 2); + } + gst_element_set_state (pipeline, GST_STATE_PAUSED); + + g_print ("\nplaying from second 25 to second 29\n"); + /* seek to some seconds */ + event = gst_event_new_segment_seek (GST_FORMAT_TIME | + GST_SEEK_METHOD_SET | + GST_SEEK_FLAG_FLUSH, 25 * GST_SECOND, 29 * GST_SECOND); + res = gst_pad_send_event (pad, event); + if (!res) + g_warning ("seek failed"); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + count = 0; + while (count++ < 500) { + get_position_info (cdparanoia); + g_usleep (G_USEC_PER_SEC / 2); + } + g_print ("\n"); + + /* shutdown everything again */ + gst_element_set_state (pipeline, GST_STATE_NULL); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdplayer.c b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdplayer.c new file mode 100644 index 0000000..6305d50 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/cdplayer.c @@ -0,0 +1,292 @@ +#include +#include +#include +#include +#include + +static GList *seekable_elements = NULL; + +static GstElement *pipeline; +static GtkAdjustment *adjustment; +static gboolean stats = FALSE; +static guint64 duration; + +static guint update_id; + +#define UPDATE_INTERVAL 500 + +static GstElement * +make_cdaudio_pipeline (void) +{ + GstElement *cdaudio; + + cdaudio = gst_element_factory_make ("cdaudio", "cdaudio"); + g_assert (cdaudio != NULL); + + seekable_elements = g_list_prepend (seekable_elements, cdaudio); + + return cdaudio; +} + +static gchar * +format_value (GtkScale * scale, gdouble value) +{ + gint64 real; + gint64 seconds; + gint64 subseconds; + + real = value * duration / 100; + seconds = (gint64) real / GST_SECOND; + subseconds = (gint64) real / (GST_SECOND / 100); + + return g_strdup_printf ("%02" G_GINT64_FORMAT ":%02" G_GINT64_FORMAT ":%02" + G_GINT64_FORMAT, seconds / 60, seconds % 60, subseconds % 100); +} + +typedef struct +{ + const gchar *name; + const GstFormat format; +} +seek_format; + +static seek_format seek_formats[] = { + {"tim", GST_FORMAT_TIME}, + {"byt", GST_FORMAT_BYTES}, + {"buf", GST_FORMAT_BUFFERS}, + {"def", GST_FORMAT_DEFAULT}, + {NULL, 0}, +}; + + +G_GNUC_UNUSED static void +query_durations () +{ + GList *walk = seekable_elements; + + while (walk) { + GstElement *element = GST_ELEMENT (walk->data); + gint i = 0; + + g_print ("durations %8.8s: ", GST_ELEMENT_NAME (element)); + while (seek_formats[i].name) { + gboolean res; + gint64 value; + GstFormat format; + + format = seek_formats[i].format; + res = gst_element_query (element, GST_QUERY_TOTAL, &format, &value); + if (res) { + g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value); + } else { + g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*"); + } + i++; + } + g_print (" %s\n", GST_ELEMENT_NAME (element)); + walk = g_list_next (walk); + } +} + +G_GNUC_UNUSED static void +query_positions () +{ + GList *walk = seekable_elements; + + while (walk) { + GstElement *element = GST_ELEMENT (walk->data); + gint i = 0; + + g_print ("positions %8.8s: ", GST_ELEMENT_NAME (element)); + while (seek_formats[i].name) { + gboolean res; + gint64 value; + GstFormat format; + + format = seek_formats[i].format; + res = gst_element_query (element, GST_QUERY_POSITION, &format, &value); + if (res) { + g_print ("%s %13" G_GINT64_FORMAT " | ", seek_formats[i].name, value); + } else { + g_print ("%s %13.13s | ", seek_formats[i].name, "*NA*"); + } + i++; + } + g_print (" %s\n", GST_ELEMENT_NAME (element)); + walk = g_list_next (walk); + } +} + +static gboolean +update_scale (gpointer data) +{ + GstClock *clock; + guint64 position = 0; + GstFormat format = GST_FORMAT_TIME; + + duration = 0; + clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline)); + + if (seekable_elements) { + GstElement *element = GST_ELEMENT (seekable_elements->data); + + gst_element_query (element, GST_QUERY_TOTAL, &format, &duration); + gst_element_query (element, GST_QUERY_POSITION, &format, &position); + } + + if (stats) { + if (clock) + g_print ("clock: %13" G_GUINT64_FORMAT " (%s)\n", + position, gst_object_get_name (GST_OBJECT (clock))); + query_durations (); + query_positions (); + } + if (duration > 0) { + gtk_adjustment_set_value (adjustment, position * 100.0 / duration); + } + + return TRUE; +} + +static gboolean +start_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + g_timeout_remove (update_id); + + return FALSE; +} + +static gboolean +stop_seek (GtkWidget * widget, GdkEventButton * event, gpointer user_data) +{ + gint64 real = gtk_range_get_value (GTK_RANGE (widget)) * duration / 100; + gboolean res; + GstEvent *s_event; + GList *walk = seekable_elements; + + while (walk) { + GstElement *seekable = GST_ELEMENT (walk->data); + + g_print ("seek to %" G_GINT64_FORMAT " on element %s\n", real, + GST_ELEMENT_NAME (seekable)); + s_event = + gst_event_new_seek (GST_FORMAT_TIME | GST_SEEK_METHOD_SET | + GST_SEEK_FLAG_FLUSH, real); + + res = gst_element_send_event (seekable, s_event); + + walk = g_list_next (walk); + } + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + update_id = + g_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline); + + return FALSE; +} + +static void +play_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_PLAYING) { + gst_element_set_state (pipeline, GST_STATE_PLAYING); + update_id = + g_timeout_add (UPDATE_INTERVAL, (GtkFunction) update_scale, pipeline); + } +} + +static void +pause_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_PAUSED) { + gst_element_set_state (pipeline, GST_STATE_PAUSED); + g_timeout_remove (update_id); + } +} + +static void +stop_cb (GtkButton * button, gpointer data) +{ + GstState state; + + gst_element_get_state (pipeline, &state, NULL, GST_CLOCK_TIME_NONE); + if (state != GST_STATE_READY) { + gst_element_set_state (pipeline, GST_STATE_READY); + g_timeout_remove (update_id); + } +} + +int +main (int argc, char **argv) +{ + GtkWidget *window, *hbox, *vbox, + *play_button, *pause_button, *stop_button, *hscale; + struct poptOption options[] = { + {"stats", 's', POPT_ARG_NONE | POPT_ARGFLAG_STRIP, &stats, 0, + "Show element stats", NULL}, + POPT_TABLEEND + }; + + gst_init_with_popt_table (&argc, &argv, options); + gtk_init (&argc, &argv); + + pipeline = make_cdaudio_pipeline (); + + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_object_default_deep_notify), NULL); + + /* initialize gui elements ... */ + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + hbox = gtk_hbox_new (FALSE, 0); + vbox = gtk_vbox_new (FALSE, 0); + play_button = gtk_button_new_with_label ("play"); + pause_button = gtk_button_new_with_label ("pause"); + stop_button = gtk_button_new_with_label ("stop"); + + adjustment = + GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.00, 100.0, 0.1, 1.0, 1.0)); + hscale = gtk_hscale_new (adjustment); + gtk_scale_set_digits (GTK_SCALE (hscale), 2); + gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_CONTINUOUS); + + g_signal_connect (GTK_OBJECT (hscale), + "button_press_event", G_CALLBACK (start_seek), pipeline); + g_signal_connect (GTK_OBJECT (hscale), + "button_release_event", G_CALLBACK (stop_seek), pipeline); + g_signal_connect (GTK_OBJECT (hscale), + "format_value", G_CALLBACK (format_value), pipeline); + + /* do the packing stuff ... */ + gtk_window_set_default_size (GTK_WINDOW (window), 96, 96); + gtk_container_add (GTK_CONTAINER (window), vbox); + gtk_container_add (GTK_CONTAINER (vbox), hbox); + gtk_box_pack_start (GTK_BOX (hbox), play_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), pause_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (hbox), stop_button, FALSE, FALSE, 2); + gtk_box_pack_start (GTK_BOX (vbox), hscale, TRUE, TRUE, 2); + + /* connect things ... */ + g_signal_connect (G_OBJECT (play_button), "clicked", G_CALLBACK (play_cb), + pipeline); + g_signal_connect (G_OBJECT (pause_button), "clicked", G_CALLBACK (pause_cb), + pipeline); + g_signal_connect (G_OBJECT (stop_button), "clicked", G_CALLBACK (stop_cb), + pipeline); + g_signal_connect (G_OBJECT (window), "delete_event", gtk_main_quit, NULL); + + /* show the gui. */ + gtk_widget_show_all (window); + + gtk_main (); + + gst_element_set_state (pipeline, GST_STATE_NULL); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/seek/chained.c b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/chained.c new file mode 100644 index 0000000..bf23e05 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/seek/chained.c @@ -0,0 +1,107 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +static GstElement *bin; + +static void +unlinked (GstPad * pad, GstPad * peerpad, GstElement * pipeline) +{ + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_bin_remove (GST_BIN (pipeline), bin); + gst_element_set_state (bin, GST_STATE_READY); + gst_element_set_state (pipeline, GST_STATE_PLAYING); +} + +static void +new_pad (GstElement * elem, GstPad * newpad, GstElement * pipeline) +{ + GstScheduler *sched; + GstClock *clock; + + g_print ("new pad %s\n", gst_pad_get_name (newpad)); + + gst_element_set_state (pipeline, GST_STATE_PAUSED); + gst_bin_add (GST_BIN (pipeline), bin); + + sched = gst_element_get_scheduler (GST_ELEMENT (pipeline)); + clock = gst_scheduler_get_clock (sched); + gst_scheduler_set_clock (sched, clock); + + gst_pad_link (newpad, gst_element_get_pad (bin, "sink")); + + g_signal_connect (G_OBJECT (newpad), "unlinked", G_CALLBACK (unlinked), + pipeline); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); +} + +int +main (int argc, char **argv) +{ + GstElement *pipeline; + GstElement *filesrc; + GstElement *oggdemux; + GstElement *vorbisdec; + GstElement *audioconvert; + GstElement *audiosink; + + gst_init (&argc, &argv); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + return (-1); + } + + pipeline = gst_pipeline_new ("pipeline"); + + filesrc = gst_element_factory_make ("filesrc", "filesrc"); + g_assert (filesrc); + g_object_set (G_OBJECT (filesrc), "location", argv[1], NULL); + + oggdemux = gst_element_factory_make ("oggdemux", "oggdemux"); + g_assert (oggdemux); + + gst_bin_add (GST_BIN (pipeline), filesrc); + gst_bin_add (GST_BIN (pipeline), oggdemux); + + gst_element_link_pads (filesrc, "src", oggdemux, "sink"); + + g_signal_connect (G_OBJECT (oggdemux), "new_pad", G_CALLBACK (new_pad), + pipeline); + + bin = gst_bin_new ("bin"); + vorbisdec = gst_element_factory_make ("vorbisdec", "vorbisdec"); + g_assert (vorbisdec); + audioconvert = gst_element_factory_make ("audioconvert", "audioconvert"); + g_assert (audioconvert); + audiosink = gst_element_factory_make (DEFAULT_AUDIOSINK, DEFAULT_AUDIOSINK); + g_assert (audiosink); + gst_bin_add (GST_BIN (bin), vorbisdec); + gst_bin_add (GST_BIN (bin), audioconvert); + gst_bin_add (GST_BIN (bin), audiosink); + + gst_element_link_pads (vorbisdec, "src", audioconvert, "sink"); + gst_element_link_pads (audioconvert, "src", audiosink, "sink"); + + gst_element_add_ghost_pad (bin, gst_element_get_pad (vorbisdec, "sink"), + "sink"); + + g_object_ref (G_OBJECT (bin)); + + g_signal_connect (pipeline, "deep_notify", + G_CALLBACK (gst_element_default_deep_notify), NULL); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + while (gst_bin_iterate (GST_BIN (pipeline))) + /* nop */ ; + + /* stop probe */ + gst_element_set_state (pipeline, GST_STATE_NULL); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/stats/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/stats/Makefile.am new file mode 100644 index 0000000..0f7d81c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/stats/Makefile.am @@ -0,0 +1,6 @@ +noinst_PROGRAMS = mp2ogg + +LDADD = $(GST_LIBS) +AM_CFLAGS = $(GST_CFLAGS) + + diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/stats/mp2ogg.c b/gst-plugins-base-subtitles0.10/tests/old/examples/stats/mp2ogg.c new file mode 100644 index 0000000..fc56d5b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/stats/mp2ogg.c @@ -0,0 +1,102 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +/* This example app demonstartes the use of pad query and convert to + * get useful statistics about a plugin. In this case we monitor the + * compression status of mpeg audio to ogg vorbis transcoding. + */ + +gint +main (gint argc, gchar * argv[]) +{ + GstElement *pipeline; + GError *error = NULL; + gchar *description; + GstElement *encoder, *decoder; + GstPad *dec_sink, *enc_src; + + gst_init (&argc, &argv); + + if (argc < 3) { + g_print ("usage: %s \n", argv[0]); + return -1; + } + + description = g_strdup_printf ("filesrc location=\"%s\" ! mad name=decoder ! " + "vorbisenc name=encoder ! filesink location=\"%s\"", argv[1], argv[2]); + + pipeline = GST_ELEMENT (gst_parse_launch (description, &error)); + if (!pipeline) { + if (error) + g_print ("ERROR: pipeline could not be constructed: %s\n", + error->message); + else + g_print ("ERROR: pipeline could not be constructed\n"); + return -1; + } + + decoder = gst_bin_get_by_name (GST_BIN (pipeline), "decoder"); + encoder = gst_bin_get_by_name (GST_BIN (pipeline), "encoder"); + + dec_sink = gst_element_get_pad (decoder, "sink"); + enc_src = gst_element_get_pad (encoder, "src"); + + if (gst_element_set_state (pipeline, + GST_STATE_PLAYING) != GST_STATE_CHANGE_SUCCESS) { + g_print ("pipeline doesn't want to play\n"); + return -1; + } + + while (gst_bin_iterate (GST_BIN (pipeline))) { + gint64 position; + gint64 duration; + gint64 bitrate_enc, bitrate_dec; + GstFormat format; + + format = GST_FORMAT_TIME; + /* get the position */ + gst_pad_query (enc_src, GST_QUERY_POSITION, &format, &position); + + /* get the total duration */ + gst_pad_query (enc_src, GST_QUERY_TOTAL, &format, &duration); + + format = GST_FORMAT_BYTES; + /* see how many bytes are genereated per 8 seconds (== bitrate) */ + gst_pad_convert (enc_src, GST_FORMAT_TIME, 8 * GST_SECOND, + &format, &bitrate_enc); + + gst_pad_convert (dec_sink, GST_FORMAT_TIME, 8 * GST_SECOND, + &format, &bitrate_dec); + + g_print ("[%2dm %.2ds] of [%2dm %.2ds], " + "src avg bitrate: %" G_GINT64_FORMAT ", dest avg birate: %" + G_GINT64_FORMAT ", ratio [%02.2f] \r", + (gint) (position / (GST_SECOND * 60)), + (gint) (position / (GST_SECOND)) % 60, + (gint) (duration / (GST_SECOND * 60)), + (gint) (duration / (GST_SECOND)) % 60, bitrate_dec, bitrate_enc, + (gfloat) bitrate_dec / bitrate_enc); + } + + g_print ("\n"); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/switch/.gitignore b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/.gitignore new file mode 100644 index 0000000..7893c43 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/.gitignore @@ -0,0 +1 @@ +switcher diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/switch/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/Makefile.am new file mode 100644 index 0000000..bd7aaf6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/Makefile.am @@ -0,0 +1,7 @@ + +noinst_PROGRAMS = switcher + +switcher_SOURCES = switcher.c +switcher_CFLAGS = $(GST_CFLAGS) +switcher_LDADD = $(GST_LIBS) + diff --git a/gst-plugins-base-subtitles0.10/tests/old/examples/switch/switcher.c b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/switcher.c new file mode 100644 index 0000000..8d463c2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/examples/switch/switcher.c @@ -0,0 +1,104 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 + +static GMainLoop *loop = NULL; + + + +static void +got_eos (GstElement * pipeline) +{ + g_main_loop_quit (loop); +} + +static gboolean +idle_iterate (GstElement * pipeline) +{ + gst_bin_iterate (GST_BIN (pipeline)); + return (GST_STATE (GST_ELEMENT (pipeline)) == GST_STATE_PLAYING); +} + +static gboolean +switch_timer (GstElement * video_switch) +{ + gint nb_sources, active_source; + + g_object_get (G_OBJECT (video_switch), "nb_sources", &nb_sources, NULL); + g_object_get (G_OBJECT (video_switch), "active_source", &active_source, NULL); + + active_source++; + + if (active_source > nb_sources - 1) + active_source = 0; + + g_object_set (G_OBJECT (video_switch), "active_source", active_source, NULL); + + g_message ("current number of sources : %d, active source %d", + nb_sources, active_source); + + return (GST_STATE (GST_ELEMENT (video_switch)) == GST_STATE_PLAYING); +} + +int +main (int argc, char *argv[]) +{ + GstElement *pipeline, *src1, *src2, *video_switch, *video_sink; + + /* Initing GStreamer library */ + gst_init (&argc, &argv); + + loop = g_main_loop_new (NULL, FALSE); + + pipeline = gst_pipeline_new ("pipeline"); + src1 = gst_element_factory_make ("videotestsrc", "src1"); + g_object_set (G_OBJECT (src1), "pattern", 0, NULL); + src2 = gst_element_factory_make ("videotestsrc", "src2"); + g_object_set (G_OBJECT (src2), "pattern", 1, NULL); + video_switch = gst_element_factory_make ("switch", "video_switch"); + video_sink = gst_element_factory_make (DEFAULT_VIDEOSINK, "video_sink"); + + gst_bin_add_many (GST_BIN (pipeline), src1, src2, video_switch, + video_sink, NULL); + + gst_element_link (src1, video_switch); + gst_element_link (src2, video_switch); + gst_element_link (video_switch, video_sink); + + g_signal_connect (G_OBJECT (pipeline), "eos", G_CALLBACK (got_eos), NULL); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); + + g_idle_add ((GSourceFunc) idle_iterate, pipeline); + g_timeout_add (2000, (GSourceFunc) switch_timer, video_switch); + + g_main_loop_run (loop); + + gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); + + /* unref */ + gst_object_unref (pipeline); + + exit (0); +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/.gitignore b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/.gitignore new file mode 100644 index 0000000..abf7b41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/.gitignore @@ -0,0 +1,3 @@ +formats +srcstate +state diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/Makefile.am new file mode 100644 index 0000000..6557bc5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/Makefile.am @@ -0,0 +1,13 @@ +testprogs = formats state srcstate + +noinst_PROGRAMS = $(testprogs) + +formats_SOURCES = formats.c sinesrc.c sinesrc.h +state_SOURCES = state.c sinesrc.c sinesrc.h +srcstate_SOURCES =srcstate.c + +# we have nothing but apps here, we can do this safely +LIBS = $(GST_LIBS) +AM_CFLAGS = $(GST_CFLAGS) + +noinst_HEADERS = sinesrc.h diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/formats.c b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/formats.c new file mode 100644 index 0000000..e6ca8f1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/formats.c @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2003 Benjamin Otte + * + * formats.c: Tests the different formats on alsasink + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "sinesrc.h" + +GstElement *pipeline; +gint channels = 1; +gboolean sign = FALSE; +gint endianness = G_LITTLE_ENDIAN; +gint depth = 8; +gint width = 8; + +#define NUMBER_OF_INT_TESTS 28 +#define NUMBER_OF_FLOAT_TESTS 2 +#define NUMBER_OF_LAW_TESTS 2 + +gint last = 0; +gint counter = 0; + +static void create_pipeline (void); + + +static void +pre_get_func (SineSrc * src) +{ + counter++; +}; + +static void +create_pipeline (void) +{ + GstElement *src; + SineSrc *sinesrc; + GstElement *alsasink; + + pipeline = gst_pipeline_new ("pipeline"); + src = sinesrc_new (); + alsasink = gst_element_factory_make ("alsasink", "alsasink"); + + gst_bin_add_many (GST_BIN (pipeline), src, alsasink, NULL); + gst_element_link (src, alsasink); + + /* prepare our sinesrc */ + sinesrc = (SineSrc *) src; + sinesrc->pre_get_func = pre_get_func; + sinesrc->newcaps = TRUE; + /* int tests */ + if (last < NUMBER_OF_INT_TESTS) { + sinesrc->type = SINE_SRC_INT; + sinesrc->sign = ((last % 2) == 0) ? TRUE : FALSE; + sinesrc->endianness = + ((last / 2) % 2 == 0) ? G_LITTLE_ENDIAN : G_BIG_ENDIAN; + switch ((last / 4) % 8) { + case 0: + sinesrc->depth = 8; + sinesrc->width = 8; + break; + case 1: + sinesrc->depth = 16; + sinesrc->width = 16; + break; + case 2: + sinesrc->depth = 24; + sinesrc->width = 32; + break; + case 3: + sinesrc->depth = 32; + sinesrc->width = 32; + break; + /* nomore tests below until i know what 24bit width means to alsa wrt endianness */ + case 4: + sinesrc->depth = 24; + sinesrc->width = 24; + break; + case 5: + sinesrc->depth = 20; + sinesrc->width = 24; + break; + case 6: + sinesrc->depth = 18; + sinesrc->width = 24; + break; + case 7: + /* not used yet */ + sinesrc->depth = 8; + sinesrc->width = 8; + break; + default: + g_assert_not_reached (); + } + + g_print ("Setting format to: format: \"int\"\n" + " sign: %s\n" + " endianness: %d\n" + " width: %d\n" + " depth: %d\n", + sinesrc->sign ? "TRUE" : "FALSE", sinesrc->endianness, + sinesrc->width, sinesrc->depth); + } else if (last < NUMBER_OF_INT_TESTS + NUMBER_OF_FLOAT_TESTS) { + gint temp = last - NUMBER_OF_INT_TESTS; + + sinesrc->type = SINE_SRC_FLOAT; + switch (temp) { + case 0: + sinesrc->width = 32; + break; + case 1: + sinesrc->width = 64; + break; + default: + g_assert_not_reached (); + } + g_print ("Setting format to float width %d\n", sinesrc->width); + } else if (last < + NUMBER_OF_INT_TESTS + NUMBER_OF_FLOAT_TESTS + NUMBER_OF_LAW_TESTS) { + gint temp = last - NUMBER_OF_INT_TESTS - NUMBER_OF_FLOAT_TESTS; + GstElement *law; + + sinesrc->type = SINE_SRC_INT; + sinesrc->sign = TRUE; + sinesrc->endianness = G_BYTE_ORDER; + sinesrc->depth = 16; + sinesrc->width = 16; + + if (temp == 0) { + law = gst_element_factory_make ("mulawenc", "mulaw"); + } else { + law = gst_element_factory_make ("alawenc", "alaw"); + } + g_assert (law); + gst_element_unlink (src, alsasink); + gst_bin_add (GST_BIN (pipeline), law); + gst_element_link_many (src, law, alsasink, NULL); + if (temp == 0) { + g_print ("Setting format to: format: \"MU law\"\n"); + } else { + g_print ("Setting format to: format: \"A law\"\n"); + } + } else { + g_print ("All formats work like a charm.\n"); + exit (0); + } + gst_element_set_state (pipeline, GST_STATE_PLAYING); +} + +gint +main (gint argc, gchar * argv[]) +{ + gst_init (&argc, &argv); + + g_print ("\n" + "This test will test the various formats ALSA and GStreamer support.\n" + "You will hear a short sine tone on your default ALSA soundcard for every\n" + "format tested. They should all sound the same (incl. volume).\n" "\n"); + create_pipeline (); + + while (pipeline) { + gst_bin_iterate (GST_BIN (pipeline)); + if ((counter / 200) > last) { + last = counter / 200; + gst_object_unref (pipeline); + create_pipeline (); + } + } + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.c b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.c new file mode 100644 index 0000000..a42db71 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.c @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2003 Benjamin Otte + * + * sinesrc.c: An elemnt emitting a sine src in lots of different formats + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "sinesrc.h" +#include +#include /* memcpy */ + +#define SAMPLES_PER_WAVE 200 + +static GstStaticPadTemplate sinesrc_src_factory = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("audio/x-raw-int, " + "endianness = (int) { LITTLE_ENDIAN, BIG_ENDIAN }, " + "signed = (boolean) { FALSE, TRUE }, " + "width = (int) [8, 32], " + "depth = (int) [8, 32], " + "rate = (int) [8000, 192000], " + "channels = (int) [1, 16];" + "audio/x-raw-float, " + "endianness = (int) BYTE_ORDER, " + "width = (int) {32, 64}, " + "rate = (int) [8000, 192000], " "channels = (int) [1, 16]") + ); + +static GstElementClass *parent_class = NULL; + +static void sinesrc_init (SineSrc * src); +static void sinesrc_class_init (SineSrcClass * klass); + +static GstData *sinesrc_get (GstPad * pad); +static GstStateChangeReturn sinesrc_change_state (GstElement * element, + GstStateChange transition); + + +GType +sinesrc_get_type (void) +{ + static GType sinesrc_type = 0; + + if (!sinesrc_type) { + static const GTypeInfo sinesrc_info = { + sizeof (SineSrcClass), NULL, NULL, + (GClassInitFunc) sinesrc_class_init, NULL, NULL, + sizeof (SineSrc), 0, + (GInstanceInitFunc) sinesrc_init, + }; + + sinesrc_type = g_type_register_static (GST_TYPE_ELEMENT, "SineSrc", + &sinesrc_info, 0); + } + return sinesrc_type; +} + +static void +sinesrc_class_init (SineSrcClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + element_class->change_state = sinesrc_change_state; + + parent_class = g_type_class_peek_parent (klass); +} + +static void +sinesrc_init (SineSrc * src) +{ + src->src = + gst_pad_new_from_template (gst_static_pad_template_get + (&sinesrc_src_factory), "src"); + gst_element_add_pad (GST_ELEMENT (src), src->src); + gst_pad_set_get_function (src->src, sinesrc_get); + + src->width = 16; + src->depth = 16; + src->sign = TRUE; + src->endianness = G_BYTE_ORDER; + src->rate = 44100; + src->channels = 1; + src->type = SINE_SRC_INT; + src->newcaps = TRUE; + + src->pre_get_func = NULL; + + GST_OBJECT (src)->name = "sinesrc"; +} + +static void +sinesrc_force_caps (SineSrc * src) +{ + GstCaps *caps; + + if (!src->newcaps) + return; + + src->newcaps = FALSE; + + switch (src->type) { + case SINE_SRC_INT: + caps = gst_caps_new_simple ("audio/x-raw-int", + "signed", G_TYPE_BOOLEAN, src->sign, + "depth", G_TYPE_INT, src->depth, NULL); + if (src->width > 8) + gst_caps_set_simple (caps, + "endianness", G_TYPE_INT, src->endianness, NULL); + break; + case SINE_SRC_FLOAT: + g_assert (src->width == 32 || src->width == 64); + caps = gst_caps_new_simple ("audio/x-raw-float", + "endianness", G_TYPE_INT, src->endianness, NULL); + break; + default: + caps = NULL; + g_assert_not_reached (); + } + gst_caps_set_simple (caps, + "width", G_TYPE_INT, src->width, + "rate", G_TYPE_INT, src->rate, + "channels", G_TYPE_INT, src->channels, NULL); + + if (gst_pad_try_set_caps (src->src, caps) != GST_PAD_LINK_OK) + g_assert_not_reached (); +} + +/* always return 1 wave + * there are 200 waves in 1 second, so the frequency is samplerate/200 + */ +static guint8 +UIDENTITY (guint8 x) +{ + return x; +}; + +static gint8 +IDENTITY (gint8 x) +{ + return x; +}; + +#define POPULATE(format, be_func, le_func) G_STMT_START {\ + format val = (format) int_value;\ + format *p = data;\ + switch (src->endianness) {\ + case G_LITTLE_ENDIAN:\ + val = le_func (val);\ + break;\ + case G_BIG_ENDIAN:\ + val = be_func (val);\ + break;\ + default: \ + g_assert_not_reached ();\ + };\ + for (j = 0; j < src->channels; j++) {\ + *p = val;\ + p ++;\ + }\ + data = p;\ +} G_STMT_END + +static GstData * +sinesrc_get (GstPad * pad) +{ + GstBuffer *buf; + SineSrc *src; + + void *data; + gint i, j; + gdouble value; + + g_return_val_if_fail (pad != NULL, NULL); + src = SINESRC (gst_pad_get_parent (pad)); + + if (src->pre_get_func) + src->pre_get_func (src); + + buf = gst_buffer_new_and_alloc ((src->width / 8) * src->channels * + SAMPLES_PER_WAVE); + g_assert (buf); + data = GST_BUFFER_DATA (buf); + g_assert (data); + + for (i = 0; i < SAMPLES_PER_WAVE; i++) { + value = sin (i * 2 * M_PI / SAMPLES_PER_WAVE); + switch (src->type) { + case SINE_SRC_INT:{ + gint64 int_value = + (value + (src->sign ? 0 : 1)) * (((guint64) 1) << (src->depth - 1)); + if (int_value == + (1 + (src->sign ? 0 : 1)) * (((guint64) 1) << (src->depth - 1))) + int_value--; + switch (src->width) { + case 8: + if (src->sign) + POPULATE (gint8, IDENTITY, IDENTITY); + else + POPULATE (guint8, UIDENTITY, UIDENTITY); + break; + case 16: + if (src->sign) + POPULATE (gint16, GINT16_TO_BE, GINT16_TO_LE); + else + POPULATE (guint16, GUINT16_TO_BE, GUINT16_TO_LE); + break; + case 24: + if (src->sign) { + gpointer p; + gint32 val = (gint32) int_value; + + switch (src->endianness) { + case G_LITTLE_ENDIAN: + val = GINT32_TO_LE (val); + break; + case G_BIG_ENDIAN: + val = GINT32_TO_BE (val); + break; + default: + g_assert_not_reached (); + }; + p = &val; + if (src->endianness == G_BIG_ENDIAN) + p++; + for (j = 0; j < src->channels; j++) { + memcpy (data, p, 3); + data += 3; + } + } else { + gpointer p; + guint32 val = (guint32) int_value; + + switch (src->endianness) { + case G_LITTLE_ENDIAN: + val = GUINT32_TO_LE (val); + break; + case G_BIG_ENDIAN: + val = GUINT32_TO_BE (val); + break; + default: + g_assert_not_reached (); + }; + p = &val; + if (src->endianness == G_BIG_ENDIAN) + p++; + for (j = 0; j < src->channels; j++) { + memcpy (data, p, 3); + data += 3; + } + } + break; + case 32: + if (src->sign) + POPULATE (gint32, GINT32_TO_BE, GINT32_TO_LE); + else + POPULATE (guint32, GUINT32_TO_BE, GUINT32_TO_LE); + break; + default: + g_assert_not_reached (); + } + break; + } + case SINE_SRC_FLOAT: + if (src->width == 32) { + gfloat *p = (gfloat *) data; + gfloat fval = (gfloat) value; + + for (j = 0; j < src->channels; j++) { + *p = fval; + p++; + } + data = p; + break; + } + if (src->width == 64) { + gdouble *p = (gdouble *) data; + + for (j = 0; j < src->channels; j++) { + *p = value; + p++; + } + data = p; + break; + } + g_assert_not_reached (); + default: + g_assert_not_reached (); + } + } + + if (src->newcaps) { + sinesrc_force_caps (src); + } + return GST_DATA (buf); +} + +GstElement * +sinesrc_new (void) +{ + return GST_ELEMENT (g_object_new (TYPE_SINESRC, NULL)); +} + +void +sinesrc_set_pre_get_func (SineSrc * src, PreGetFunc func) +{ + src->pre_get_func = func; +} + +static GstStateChangeReturn +sinesrc_change_state (GstElement * element, GstStateChange transition) +{ + SineSrc *sinesrc; + + g_return_val_if_fail (element != NULL, FALSE); + sinesrc = SINESRC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_READY_TO_PAUSED: + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + sinesrc->newcaps = TRUE; + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + g_assert_not_reached (); + } + + if (GST_ELEMENT_CLASS (parent_class)->change_state) + return GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + return GST_STATE_CHANGE_SUCCESS; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.h b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.h new file mode 100644 index 0000000..057428d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/sinesrc.h @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2003 Benjamin Otte + * + * sinesrc.h: Header file for sinesrc.c + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef __SINESRC_H__ +#define __SINESRC_H__ + + +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define TYPE_SINESRC \ + (sinesrc_get_type()) +#define SINESRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),TYPE_SINESRC,SineSrc)) +#define SINESRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),TYPE_SINESRC,SineSrcClass)) +#define IS_SINESRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),TYPE_SINESRC)) +#define IS_SINESRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),TYPE_SINESRC)) + +typedef struct _SineSrc SineSrc; +typedef struct _SineSrcClass SineSrcClass; + +typedef void (*PreGetFunc) (SineSrc *src); + +typedef enum { + SINE_SRC_INT, + SINE_SRC_FLOAT +} SineSrcAudio; + +struct _SineSrc { + GstElement element; + + /* pads */ + GstPad *src; + + /* audio parameters */ + SineSrcAudio type; + gint width; /* int + float */ + gint depth; /* int */ + gboolean sign; /* int */ + gint endianness; /* int */ + + gint rate; + gint channels; /* interleaved */ + + gboolean newcaps; + + /* freaky stuff for testing */ + PreGetFunc pre_get_func; +}; + +struct _SineSrcClass { + GstElementClass parent_class; +}; + +GType sinesrc_get_type (void); +GstElement * sinesrc_new (void); + +void sinesrc_set_pre_get_func (SineSrc *src, PreGetFunc func); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __GST_SINESRC_H__ */ diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/srcstate.c b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/srcstate.c new file mode 100644 index 0000000..4ae536d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/srcstate.c @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2003 Benjamin Otte + * + * srcstate.c: Tests alsasrc for state changes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include + +GstElement *pipeline; + +static void +set_state (GstState state) +{ + GstState old_state = gst_element_get_state (pipeline); + + g_print ("Setting state from %s to %s...", + gst_element_state_get_name (old_state), + gst_element_state_get_name (state)); + + if (!gst_element_set_state (pipeline, state)) { + g_print (" ERROR\n"); + exit (-1); + } + + if (state == GST_STATE_PLAYING) { + gint i; + + g_print (" DONE - iterating a bit..."); + for (i = 0; i < 5; i++) { + if (!gst_bin_iterate (GST_BIN (pipeline))) { + g_print (" ERROR in iteration %d\n", i); + exit (-2); + } + } + } + g_print (" DONE\n"); +} + +static void +create_pipeline (void) +{ + GstElement *alsasrc; + GstElement *fakesink; + + pipeline = gst_pipeline_new ("pipeline"); + alsasrc = gst_element_factory_make ("alsasrc", "alsasrc"); + fakesink = gst_element_factory_make ("fakesink", "fakesink"); + + gst_bin_add_many (GST_BIN (pipeline), alsasrc, fakesink, NULL); + gst_element_link (alsasrc, fakesink); + +} + +gint +main (gint argc, gchar * argv[]) +{ + gst_init (&argc, &argv); + + g_print ("\n" "This test will check if state changes work on the alsasrc.\n"); + create_pipeline (); + + /* simulate some state changes here */ + set_state (GST_STATE_READY); + set_state (GST_STATE_NULL); + set_state (GST_STATE_READY); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PAUSED); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_PAUSED); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_READY); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PLAYING); + + g_print ("The alsa plugin mastered another test.\n"); + + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/state.c b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/state.c new file mode 100644 index 0000000..9cbd8ac --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/alsa/state.c @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2003 Benjamin Otte + * + * state.c: Tests alsasink for state changes + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "sinesrc.h" + +GstElement *pipeline; + +static void +set_state (GstState state) +{ + GstState old_state = gst_element_get_state (pipeline); + + g_print ("Setting state from %s to %s...", + gst_element_state_get_name (old_state), + gst_element_state_get_name (state)); + + if (!gst_element_set_state (pipeline, state)) { + g_print (" ERROR\n"); + exit (-1); + } + + if (state == GST_STATE_PLAYING) { + gint i; + + g_print (" DONE - iterating a bit..."); + for (i = 0; i < 400; i++) { + if (!gst_bin_iterate (GST_BIN (pipeline))) { + g_print (" ERROR in iteration %d\n", i); + exit (-2); + } + } + } + g_print (" DONE\n"); +} + +static void +create_pipeline (void) +{ + GstElement *src; + SineSrc *sinesrc; + GstElement *alsasink; + + pipeline = gst_pipeline_new ("pipeline"); + src = sinesrc_new (); + alsasink = gst_element_factory_make ("alsasink", "alsasink"); + + gst_bin_add_many (GST_BIN (pipeline), src, alsasink, NULL); + gst_element_link (src, alsasink); + + /* prepare our sinesrc */ + sinesrc = (SineSrc *) src; + sinesrc->newcaps = TRUE; + sinesrc->type = SINE_SRC_INT; + sinesrc->sign = TRUE; + sinesrc->endianness = G_BYTE_ORDER; + sinesrc->depth = 16; + sinesrc->width = 16; +} + +gint +main (gint argc, gchar * argv[]) +{ + gst_init (&argc, &argv); + + g_print ("\n" + "This test will check if state changes work on the alsasink.\n" + "You will hear some short sine tones on your default ALSA soundcard,\n" + "but they are not important in this test.\n" "\n"); + create_pipeline (); + + /* simulate some state changes here */ + set_state (GST_STATE_READY); + set_state (GST_STATE_NULL); + set_state (GST_STATE_READY); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PAUSED); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_PAUSED); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_READY); + set_state (GST_STATE_PLAYING); + set_state (GST_STATE_NULL); + set_state (GST_STATE_PLAYING); + + g_print ("The alsa plugin mastered another test.\n"); + + gst_object_unref (pipeline); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/Makefile.am b/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/Makefile.am new file mode 100644 index 0000000..2ffdc76 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/Makefile.am @@ -0,0 +1,7 @@ + +noinst_PROGRAMS = embed + +# we have nothing but apps here, we can do this safely +LIBS = $(GST_LIBS) $(GTK_LIBS) \ + $(top_builddir)/gst-libs/gst/libgstinterfaces-$(GST_MAJORMINOR).la +AM_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/embed.c b/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/embed.c new file mode 100644 index 0000000..ed4a93c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/embed/embed.c @@ -0,0 +1,54 @@ +/* + * Sample app for element embedding. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +static void +cb_expose (GtkWidget * w, GdkEventExpose * ev, GstElement * e) +{ + if (GST_IS_X_OVERLAY (e) && + !GTK_WIDGET_NO_WINDOW (w) && GTK_WIDGET_REALIZED (w)) { + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (e), + GDK_WINDOW_XWINDOW (w->window)); + } +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *window, *content; + GstElement *testsrc, *csp, *videosink, *pipeline; + + gtk_init (&argc, &argv); + gst_init (&argc, &argv); + + pipeline = gst_element_factory_make ("pipeline", NULL); + testsrc = gst_element_factory_make ("videotestsrc", NULL); + csp = gst_element_factory_make ("ffmpegcolorspace", NULL); + videosink = gst_element_factory_make (DEFAULT_VIDEOSINK, NULL); + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_default_size (GTK_WINDOW (window), 640, 480); + gtk_window_set_title (GTK_WINDOW (window), "My application"); + content = gtk_event_box_new (); + gtk_container_add (GTK_CONTAINER (window), content); + g_signal_connect (content, "expose-event", G_CALLBACK (cb_expose), videosink); + gtk_widget_show_all (window); + + gst_bin_add_many (GST_BIN (pipeline), testsrc, csp, videosink, NULL); + gst_element_link_many (testsrc, csp, videosink, NULL); + + g_idle_add ((GSourceFunc) gst_bin_iterate, pipeline); + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + gtk_main (); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tests/old/testsuite/gst-lint b/gst-plugins-base-subtitles0.10/tests/old/testsuite/gst-lint new file mode 100755 index 0000000..a924f05 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tests/old/testsuite/gst-lint @@ -0,0 +1,571 @@ +#!/usr/bin/perl -w +# vi: set ts=4: +# + +# +# GStreamer developers: please add comments on any tests you think +# are dumb or have too many false positives. +# + +# +# Future ideas: +# - spell check comments +# - check each function for at least one assertion (?) +# - check parameters that init/set/get have consistent types +# - check for gst_caps_set() without check for writeability +# - check .so files for stray symbols +# + +# +# Random "other" testing ideas +# - load each plugin individually +# + +sub check_copyright(); +sub check_license(); +sub check_buffer_alloc(); +sub check_bad_includes(); +sub check_begin_decls(); +sub check_c99_comments(); +sub check_carriage_returns(); +sub check_printf_lld(); +sub check_glibisms(); +sub check_indentation(); +sub check_no_ignore(); +sub check_deprecated(); +sub check_config_h(); +sub check_varargs_functions(); +sub check_debugging(); +sub check_old_typefind(); +sub check_bad_casts(); +sub check_old_plugin(); +sub check_signal_new(); +sub check_gnuc_const(); +sub check_caps(); +sub check_lib_deprecated(); +sub check_typo(); +sub check_explicit_caps(); +sub check_signals(); +sub check_gettext(); +sub check_padtemplate(); +sub check_parent_class(); + +sub m_check_plugindir(); +sub m_check_interfaces(); + +open FIND, "find . -name \"*.[ch]\" -print|"; + +foreach $filename () { + chomp $filename; + open FILE, "$filename"; + @lines = ; + close FILE; + + print "I: $filename\n"; + + # important stuff + check_bad_includes(); + check_printf_lld(); + check_no_ignore(); + check_deprecated(); + check_config_h(); + check_old_typefind(); + check_old_plugin(); + check_caps(); + check_lib_deprecated(); + check_typo(); + check_glibisms(); + check_explicit_caps(); + check_signals(); + check_gettext(); + check_padtemplate(); + check_parent_class(); + + # less important stuff + check_license(); + +if (0) { + check_copyright(); + + check_gnuc_const(); + check_begin_decls(); + check_buffer_alloc(); + check_c99_comments(); + check_carriage_returns(); + #check_indentation(); + check_varargs_functions(); + check_debugging(); + check_bad_casts(); + check_signal_new(); +} +} + +open FIND, "find . -name \"Makefile.am\" -print|"; + +foreach $filename () { + chomp $filename; + open FILE, "$filename"; + @lines = ; + close FILE; + + print "I: $filename\n"; + + m_check_plugindir(); + m_check_interfaces(); +} + +# +# Every source file must have a copyright block +# +sub check_copyright() +{ + if (! grep { /copyright/i; } @lines) { + print "E: no copyright block\n"; + } +} + +# +# Every source file should have a license statement +# +sub check_license() +{ + if (grep { /Lesser General Public License/; } @lines) { + print "I: license is LGPL\n"; + } elsif (grep { /Library General Public License/; } @lines) { + print "I: license is LGPL\n"; + print "W: copyright header uses \"Library\" LGPL\n"; + } elsif (grep { /General Public License/; } @lines) { + print "I: license is GPL\n"; + } else { + print "E: unknown license or no copyright block\n"; + } +} + +# +# Suggest usage of gst_buffer_new_and_alloc() +# +sub check_buffer_alloc() +{ + my $n = 0; + my $lineno = 1; + + foreach $line (@lines){ + if($line =~ /gst_buffer_new/){ + $n=5; + } + if($n>0 && $line =~ /malloc/){ + print "W: ($lineno) gst_buffer_new() followed by malloc(), suggest gst_buffer_new_and_alloc()\n"; + return; + } + $n--; + $lineno++; + } +} + +sub check_bad_includes() +{ + # + # malloc.h is non-standard (and probably not what is indended) + # + if (grep { /^#include\s+/; } @lines) { + print "E: bad header: malloc.h\n" + } +} + +sub check_begin_decls() +{ + # + # Prefer "G_BEGIN_DECLS" to 'extern "C" {' + # + if($filename =~ /\.h$/){ + if (grep { /extern\s*\"C\"\s*/; } @lines) { + print "W: extern \"C\" { should be changed to G_BEGIN_DECLS,G_END_DECLS\n"; + }elsif (!grep { /G_BEGIN_DECLS/; } @lines) { + print "E: header doesn't use G_BEGIN_DECLS\n"; + } + } +} + +# +# Prefer c89-style comments +# +sub check_c99_comments() +{ + if (grep { /\/\//; } @lines) { + print "W: //-style comments should be converted to /* */\n" + } +} + +# +# DOS end-of-line characters are just wrong +# +sub check_carriage_returns() +{ + if (grep { /\r/; } @lines) { + print "E: source has carriage returns (DOS-style files)\n" + } +} + +# +# Many uses of %lld are wrong. This could have a lot of false-positives +# +sub check_printf_lld() +{ + if (grep { /\".*\%\d*ll[du].*\"/; } @lines) { + print "W: Possible \%lld or \%llu in printf format\n" + } +} + +# +# Glib functions are preferred +# +sub check_glibisms() +{ + if (grep { /\bcalloc\s*\(/; } @lines) { + print "E: use g_malloc0() instead of calloc()\n" + } + if (grep { /\bfree\s*\(/; } @lines) { + print "E: use g_free() instead of free()\n" + } + if (grep { /\bmalloc\s*\(/; } @lines) { + print "E: use g_malloc() instead of malloc()\n" + } + if (grep { /\bprintf\s*\(/; } @lines) { + print "E: use g_print() instead of printf()\n" + } + if (grep { /\brealloc\s*\(/; } @lines) { + print "E: use g_realloc() instead of realloc()\n" + } + if (grep { /^#include\s+/; } @lines) { + print "E: ctype.h functions are not locale-independent and don't work in UTF-8 locales. Use g_ascii_is*()\n" + } +} + +# +# I don't think that indentation necessarily needs to be fixed, since +# it causes problems with patching and cvs annotate. +# +# This takes forever and isn't very useful +# +sub check_indentation() +{ + my $changed_lines; + my $percent; + + `indent -br -bad -cbi0 -cli2 -bls -l80 -ut -ce $filename -o .check_plugin.tmp`; + $changed_lines = `diff $filename .check_plugin.tmp | grep '^>' | wc -l`; + `rm -f .check_plugin.tmp`; + + $percent = int(100 * $changed_lines / $#lines); + + if($percent < 10){ + print "I: indent changed $percent % of the lines\n"; + }elsif($percent <20){ + print "W: indent changed $percent % of the lines\n"; + }else{ + print "E: indent changed $percent % of the lines\n"; + } +} + + +# +# Check (roughly) for functions whose value should not be ignored +# +sub check_no_ignore() +{ + if (grep { /^\s+gst_buffer_merge\s*\(/; } @lines) { + print "E: return value of gst_buffer_merge () possibly ignored\n"; + } + if (grep { /^\s+malloc\s*\(/; } @lines) { + print "E: return value of malloc() possibly ignored\n"; + } + if (grep { /^\s+gst_buffer_new\s*\(/; } @lines) { + print "E: return value of gst_buffer_new() possibly ignored\n"; + } +} + +# +# Check for some deprecated stuff (that _shouldn't_ be around anymore) +# +sub check_deprecated() +{ + # + # Check for old GST_DEBUG() usage + # (none found) + # + if (grep { /GST_DEBUG\s*\(\s+\d/; } @lines) { + print "E: old-style GST_DEBUG()\n"; + } + if (grep { /GST_INFO\s*\(\s+\d/; } @lines) { + print "E: old-style GST_DEBUG()\n"; + } + if (grep { /GstEventFlags/; } @lines) { + print "W: who uses GstEventFlags\n"; + } + if (grep { /g_type_class_ref/ } @lines) { + print "W: g_type_class_ref should be changed to g_type_class_peek_parent\n"; + } + +} + +# +# Every .c file should include config.h before any other headers +# No .h file should include config.h +# +sub check_config_h() +{ + if($filename =~ /\.c$/){ + # + # config.h should be wrapped + # + my @includes = grep { /^#include/; } @lines; + + if (!grep { /^#include\s+["<]config.h[">]/; } @includes) { + print "E: #include missing\n"; + }else{ + if (!($includes[0] =~ /^#include\s+["<]config.h[">]/)){ + print "E: #include is not first include\n"; + } + if(!grep { /^#ifdef HAVE_CONFIG_H/; } @lines) { + print "E: #include not surrounded by #ifdef HAVE_CONFIG_H\n"; + } + } + } + + if($filename =~ /\.h$/){ + if (grep { /^#include\s+["<]config.h[">]/; } @lines) { + print "E: headers should not #include \n"; + } + } + +} + +# +# Check for functions that take varargs to make sure they are +# named correctly +# +sub check_varargs_functions() +{ + if($filename =~ /\.h$/){ + if (grep { /varargs/; } @lines) { + print "I: has varargs\n"; + } + } +} + +# +# Debugging checks +# +sub check_debugging() +{ + if (grep { /\Wg_print\W/ || /\Wprintf\W/ && /\Wfprintf\W/; } @lines) { + print "W: friendly libraries don't print to stdio or stderr\n"; + } + + if (grep { /GST_DEBUG.*\\n"/; } @lines) { + print "W: possible newline in GST_DEBUG()\n"; + } + +} + +# +# check for plugindir= +# +sub m_check_plugindir() +{ + if (grep { /plugindir\s*=/; } @lines) { + print "E: plugindir= is no longer necessary\n"; + } +} + +# +# check for old typefinding code +# +sub check_old_typefind() +{ + if (grep { /GstTypeDefinition/ || /GstTypeFactory/ } @lines) { + print "E: old typefind interface has been removed\n"; + } +} + +# +# check for casts that we've deemed incorrect (fix the prototype) +# +sub check_bad_casts() +{ + if (grep { /GBaseInitFunc/ || /GBaseFinalizeFunc/ || + /GClassInitFunc/ || /GClassFinalizeFunc/ || + /GInstanceInitFunc/ || /GInterfaceInitFunc/ || + /GInterfaceFinalizeFunc/ } @lines) { + print "W: bad casts (fix prototype)\n"; + } + if (grep { /\(\s*Gst[A-Z][A-Za-z]*\s*\*\s*\)/ } @lines ) { + print "W: use GST_XXX() instead of (GstXxx *)\n"; + } + +} + +# +# check for old plugin code +# +sub check_old_plugin() +{ + if (grep { /plugin_init.*GModule.*GstPlugin/ } @lines) { + print "E: old plugin interface detected\n"; + } + if (grep { /GstPluginDesc.*plugin_desc/ } @lines) { + print "W: should use GST_PLUGIN_DEFINE() instead of GstPluginDesc\n"; + } +} + +# +# Check for calls to g_signal_new() with a callback type of G_TYPE_POINTER +# +sub check_signal_new() +{ + my $n = 0; + my $lineno = 1; + + foreach $line (@lines){ + if($line =~ /g_signal_new/){ + $n=5; + } + if($n>0 && $line =~ /G_TYPE_POINTER/){ + print "W: ($lineno) g_signal_new() with callback type of G_TYPE_POINTER. Register and use a boxed type instead.\n"; + return; + } + $n--; + $lineno++; + } +} + +# +# Check that libgstinterfaces is in LDADD +# +sub m_check_interfaces() +{ + if (grep { /libgstinterfaces.la/ } @lines) { + if (! grep { /libgstinterfaces_la/ } @lines) { + if (! grep { /_LDADD.*libgstinterfaces.la/ } @lines) { + print "E: libgstinterfaces.la not in LDADD\n"; + } + } + } +} + +# +# Check that get_type() functions return G_CONST_RETURN GType +# +sub check_gnuc_const() +{ + my $n = 0; + my $lineno = 1; + + foreach $line (@lines){ + if($line =~ /GType.*get_type.*/ && + !($line =~ /GType.*get_type.*G_GNUC_CONST/)) { + + print "E: get_type function does not have G_GNUC_CONST attribute\n"; + } + } +} + +# +# Check caps usage +# +sub check_caps() +{ + if (grep { /gst_pad_get_caps/ } @lines) { + print "E: elements should not call gst_pad_get_caps(), use gst_pad_get_allowed_caps()\n"; + } +} + +# +# Check for use of deprecated functions +# +sub check_lib_deprecated() +{ + if (grep { /bzero/ } @lines) { + print "E: change bzero() to memset()\n"; + } +} + +# +# Check for typos +# +sub check_typo() +{ + if (grep { /;\s*;\s*$/ } @lines) { + print "W: typo? \";;\"\n"; + } +} + +# +# set_explicit_caps() should preceed pad_add() +# +sub check_explicit_caps() +{ + my $n = 0; + my $lineno = 1; + + foreach $line (@lines){ + if($line =~ /gst_element_add_pad/){ + $n=10; + } + if($n>0 && $line =~ /gst_pad_set_explicit_caps/){ + print "W: ($lineno) explicit caps should be set before adding pad\n"; + return; + } + $n--; + $lineno++; + } +} + +# +# Check for - in signal names +# +sub check_signals() +{ + if (grep { /g_signal_new.*\".*-.*\"/; } @lines) { + print "E: g_signal_new() with a signal name with a - in it (we prefer _)\n" + } +} + +# +# Check for things that gettext gets wrong +# +sub check_gettext() +{ + if (grep { /\b_\(.*G_GU?INT64_FORMAT/ || + /\b_\(.*GST_TIME_FORMAT/ || + /\b_\(.*GST_FOURCC_FORMAT/ } @lines) { + print "E: gettext doesn't handle format strings that are defines\n" + } +} + +# +# Check that pad templates are statically scoped +# +sub check_padtemplate() +{ + foreach $line (@lines){ + if ($line =~ /GstStaticPadTemplate/ && !($line =~ /static/)) { + print "W: pad template definitions should be static\n"; + return; + } + } +} + +# +# Check that parent_class is statically scoped +# +sub check_parent_class() +{ + foreach $line (@lines){ + if ($line =~ /Gst.*\*\s*parent_class/ && !($line =~ /static/)) { + print "E: parent_class definitions should be static\n"; + return; + } + } +} + diff --git a/gst-plugins-base-subtitles0.10/tools/.gitignore b/gst-plugins-base-subtitles0.10/tools/.gitignore new file mode 100644 index 0000000..af30ade --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/.gitignore @@ -0,0 +1,5 @@ +gst-launch-ext-?.* +gst-visualise-?.* +gst-launch-ext-?.*.1 +gst-visualise-?.*.1 +gst-discoverer-* diff --git a/gst-plugins-base-subtitles0.10/tools/Makefile.am b/gst-plugins-base-subtitles0.10/tools/Makefile.am new file mode 100644 index 0000000..647b634 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/Makefile.am @@ -0,0 +1,49 @@ +bin_SCRIPTS = \ + gst-visualise-@GST_MAJORMINOR@ + +man_MANS = \ + gst-visualise-@GST_MAJORMINOR@.1 + +bin_PROGRAMS = \ + gst-discoverer-@GST_MAJORMINOR@ + +gst_discoverer_@GST_MAJORMINOR@_SOURCES = gst-discoverer.c + +CLEANFILES = $(man_MANS) $(bin_SCRIPTS) $(bin_PROGRAMS) + +EXTRA_DIST = \ + gst-visualise-m.m gst-visualise.1.in + + +LDADD = $(top_builddir)/gst-libs/gst/pbutils/libgstpbutils-@GST_MAJORMINOR@.la\ + $(top_builddir)/gst-libs/gst/video/libgstvideo-@GST_MAJORMINOR@.la\ + $(GST_BASE_LIBS) $(GST_LIBS) + +AM_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) + +# generate versioned scripts from templates +%-@GST_MAJORMINOR@: %-m.m + $(AM_V_GEN)sed -e s,\@GST_MAJORMINOR\@,@GST_MAJORMINOR@,g $< > $@ && \ + chmod +x $@ + +# generate man pages +%-@GST_MAJORMINOR@.1: %.1.in + $(AM_V_GEN)sed \ + -e s,gst-visualise,gst-visualise-@GST_MAJORMINOR@,g \ + $< >$@ + +all: all-am chmod + +chmod: $(bin_SCRIPTS) + @chmod +x $^ + +Android.mk: Makefile.am + androgenizer -:PROJECT gst-discoverer \ + -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \ + -:EXECUTABLE gst-discoverer -:TAGS eng debug \ + -:SOURCES $(gst_discoverer_@GST_MAJORMINOR@_SOURCES) \ + -:CFLAGS $(DEFS) $(AM_CFLAGS) \ + -:LDFLAGS -lgstpbutils-@GST_MAJORMINOR@ -lgstvideo-@GST_MAJORMINOR@ \ + $(GST_BASE_LIBS) $(GST_LIBS) \ + -:PASSTHROUGH LOCAL_ARM_MODE:=arm \ + > $@ diff --git a/gst-plugins-base-subtitles0.10/tools/README.filterstamp b/gst-plugins-base-subtitles0.10/tools/README.filterstamp new file mode 100644 index 0000000..a7b3d21 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/README.filterstamp @@ -0,0 +1,24 @@ +filterstamp.sh is a script to copy a filter and change filenames and all +occurrences of the old name to the new name. + +This is used for writing new audio filters. The best one to copy for now is +passthrough; it works on raw/audio int or float data. + +If your new filter is called StereoPan, for example, then do this : + +cd gst +../tools/filterstamp.sh Passthrough StereoPan +cd stereopan +make + +(Please note the upper- and lower-case !) + +You should also add a line to configure.ac to make sure the Makefiles are built +correctly. Just search for "passthrough" and add corresponding "stereopan" (or +whatever your plugin is) lines. + +Register it, then try it out. It shouldn't do anything ! + +Now edit the filter.func in the new directory; this file contains the body +of the main processing loop. + diff --git a/gst-plugins-base-subtitles0.10/tools/filterstamp.sh b/gst-plugins-base-subtitles0.10/tools/filterstamp.sh new file mode 100755 index 0000000..56b3d8d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/filterstamp.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +# copies from gstreamer filter boilerplate +# to new filter +# changing file names and function references + +# thomas@apestaart.org + +# modified 23 aug 2001 apwingo@eos.ncsu.edu: +# conform better to gtk naming conventions (GstFoo->gst_foo in functions, etc) + +if [ "$1" = "" ] +then + echo "please specify the filter to copy FROM (e.g. Passthrough)" + exit +fi + +if [ "$2" = "" ] +then + echo "please specify the filter to copy TO (e.g. NewFilter)" + exit +fi + +FROM=$1 +TO=$2 +FROM_LC=`echo $FROM | tr [A-Z] [a-z]` +TO_LC=`echo $TO | tr [A-Z] [a-z]` +FROM_UC=`echo $FROM | tr [a-z] [A-Z]` +TO_UC=`echo $TO | tr [a-z] [A-Z]` +FROM_LC_UNDERSCORE=`echo $FROM | perl -n -p -e 's/([a-z])([A-Z])/$1_$2/g; tr/A-Z/a-z/'` +TO_LC_UNDERSCORE=`echo $TO | perl -n -p -e 's/([a-z])([A-Z])/$1_$2/g; tr/A-Z/a-z/'` + +echo "Copying filter boilerplate $FROM to new filter $TO..." + +if [ ! -d $FROM_LC ] +then + echo "Filter directory $FROM_LC does not exist !" + exit +fi + +if [ -d $TO_LC ] +then + echo "Filter directory $TO_LC already exists !" + exit +fi + +cp -r $FROM_LC $TO_LC + +cd $TO_LC + +for a in *$FROM_LC*; do mv $a `echo $a | sed s/$FROM_LC/$TO_LC/g`; done + +perl -i -p -e "s/$FROM/$TO/g" * +perl -i -p -e "s/${FROM_LC_UNDERSCORE}_/${TO_LC_UNDERSCORE}_/g" * +perl -i -p -e "s/$FROM_LC/$TO_LC/g" * +perl -i -p -e "s/$FROM_UC/$TO_UC/g" * + diff --git a/gst-plugins-base-subtitles0.10/tools/gst-discoverer.c b/gst-plugins-base-subtitles0.10/tools/gst-discoverer.c new file mode 100644 index 0000000..00d2d0f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/gst-discoverer.c @@ -0,0 +1,499 @@ +/* GStreamer + * Copyright (C) 2009 Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * 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 +#include +#include +#include + +static gboolean async = FALSE; +static gboolean silent = FALSE; +static gboolean verbose = FALSE; + +typedef struct +{ + GstDiscoverer *dc; + int argc; + char **argv; +} PrivStruct; + +#define my_g_string_append_printf(str, format, ...) \ + g_string_append_printf (str, "%*s" format, 2*depth, " ", ##__VA_ARGS__) + +static gchar * +gst_stream_audio_information_to_string (GstDiscovererStreamInfo * info, + gint depth) +{ + GstDiscovererAudioInfo *audio_info; + GString *s; + gchar *tmp; + int len = 400; + const GstTagList *tags; + GstCaps *caps; + + g_return_val_if_fail (info != NULL, NULL); + + s = g_string_sized_new (len); + + my_g_string_append_printf (s, "Codec:\n"); + caps = gst_discoverer_stream_info_get_caps (info); + tmp = gst_caps_to_string (caps); + gst_caps_unref (caps); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + + my_g_string_append_printf (s, "Additional info:\n"); + if (gst_discoverer_stream_info_get_misc (info)) { + tmp = gst_structure_to_string (gst_discoverer_stream_info_get_misc (info)); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + } else { + my_g_string_append_printf (s, " None\n"); + } + + audio_info = (GstDiscovererAudioInfo *) info; + my_g_string_append_printf (s, "Channels: %u\n", + gst_discoverer_audio_info_get_channels (audio_info)); + my_g_string_append_printf (s, "Sample rate: %u\n", + gst_discoverer_audio_info_get_sample_rate (audio_info)); + my_g_string_append_printf (s, "Depth: %u\n", + gst_discoverer_audio_info_get_depth (audio_info)); + + my_g_string_append_printf (s, "Bitrate: %u\n", + gst_discoverer_audio_info_get_bitrate (audio_info)); + my_g_string_append_printf (s, "Max bitrate: %u\n", + gst_discoverer_audio_info_get_max_bitrate (audio_info)); + + my_g_string_append_printf (s, "Tags:\n"); + tags = gst_discoverer_stream_info_get_tags (info); + if (tags) { + tmp = gst_structure_to_string ((GstStructure *) tags); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + } else { + my_g_string_append_printf (s, " None\n"); + } + if (verbose) + my_g_string_append_printf (s, "\n"); + + return g_string_free (s, FALSE); +} + +static gchar * +gst_stream_video_information_to_string (GstDiscovererStreamInfo * info, + gint depth) +{ + GstDiscovererVideoInfo *video_info; + GString *s; + gchar *tmp; + int len = 500; + const GstStructure *misc; + const GstTagList *tags; + GstCaps *caps; + + g_return_val_if_fail (info != NULL, NULL); + + s = g_string_sized_new (len); + + my_g_string_append_printf (s, "Codec:\n"); + caps = gst_discoverer_stream_info_get_caps (info); + tmp = gst_caps_to_string (caps); + gst_caps_unref (caps); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + + my_g_string_append_printf (s, "Additional info:\n"); + misc = gst_discoverer_stream_info_get_misc (info); + if (misc) { + tmp = gst_structure_to_string (misc); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + } else { + my_g_string_append_printf (s, " None\n"); + } + + video_info = (GstDiscovererVideoInfo *) info; + my_g_string_append_printf (s, "Width: %u\n", + gst_discoverer_video_info_get_width (video_info)); + my_g_string_append_printf (s, "Height: %u\n", + gst_discoverer_video_info_get_height (video_info)); + my_g_string_append_printf (s, "Depth: %u\n", + gst_discoverer_video_info_get_depth (video_info)); + + my_g_string_append_printf (s, "Frame rate: %u/%u\n", + gst_discoverer_video_info_get_framerate_num (video_info), + gst_discoverer_video_info_get_framerate_denom (video_info)); + + my_g_string_append_printf (s, "Pixel aspect ratio: %u/%u\n", + gst_discoverer_video_info_get_par_num (video_info), + gst_discoverer_video_info_get_par_denom (video_info)); + + my_g_string_append_printf (s, "Interlaced: %s\n", + gst_discoverer_video_info_is_interlaced (video_info) ? "true" : "false"); + + my_g_string_append_printf (s, "Bitrate: %u\n", + gst_discoverer_video_info_get_bitrate (video_info)); + my_g_string_append_printf (s, "Max bitrate: %u\n", + gst_discoverer_video_info_get_max_bitrate (video_info)); + + my_g_string_append_printf (s, "Tags:\n"); + tags = gst_discoverer_stream_info_get_tags (info); + if (tags) { + tmp = gst_structure_to_string ((GstStructure *) tags); + my_g_string_append_printf (s, " %s\n", tmp); + g_free (tmp); + } else { + my_g_string_append_printf (s, " None\n"); + } + if (verbose) + my_g_string_append_printf (s, "\n"); + + return g_string_free (s, FALSE); +} + +static void +print_stream_info (GstDiscovererStreamInfo * info, void *depth) +{ + gchar *desc = NULL; + GstCaps *caps; + + caps = gst_discoverer_stream_info_get_caps (info); + + if (caps) { + if (gst_caps_is_fixed (caps) && !verbose) + desc = gst_pb_utils_get_codec_description (caps); + else + desc = gst_caps_to_string (caps); + gst_caps_unref (caps); + } + + g_print ("%*s%s: %s\n", 2 * GPOINTER_TO_INT (depth), " ", + gst_discoverer_stream_info_get_stream_type_nick (info), desc); + + if (desc) { + g_free (desc); + desc = NULL; + } + + if (verbose) { + if (GST_IS_DISCOVERER_AUDIO_INFO (info)) + desc = + gst_stream_audio_information_to_string (info, + GPOINTER_TO_INT (depth) + 1); + else if (GST_IS_DISCOVERER_VIDEO_INFO (info)) + desc = + gst_stream_video_information_to_string (info, + GPOINTER_TO_INT (depth) + 1); + if (desc) { + g_print ("%s", desc); + g_free (desc); + } + } +} + +static void +print_topology (GstDiscovererStreamInfo * info, gint depth) +{ + GstDiscovererStreamInfo *next; + + if (!info) + return; + + print_stream_info (info, GINT_TO_POINTER (depth)); + + next = gst_discoverer_stream_info_get_next (info); + if (next) { + print_topology (next, depth + 1); + gst_discoverer_stream_info_unref (next); + } else if (GST_IS_DISCOVERER_CONTAINER_INFO (info)) { + GList *tmp, *streams; + + streams = + gst_discoverer_container_info_get_streams (GST_DISCOVERER_CONTAINER_INFO + (info)); + for (tmp = streams; tmp; tmp = tmp->next) { + GstDiscovererStreamInfo *tmpinf = (GstDiscovererStreamInfo *) tmp->data; + print_topology (tmpinf, depth + 1); + } + gst_discoverer_stream_info_list_free (streams); + } +} + +static gboolean +print_tag_each (GQuark field_id, const GValue * value, gpointer user_data) +{ + gint tab = GPOINTER_TO_INT (user_data); + gchar *ser; + + if (G_VALUE_HOLDS_STRING (value)) + ser = g_value_dup_string (value); + else if (GST_VALUE_HOLDS_BUFFER (value)) { + GstBuffer *buf = gst_value_get_buffer (value); + ser = g_strdup_printf ("", GST_BUFFER_SIZE (buf)); + } else + ser = gst_value_serialize (value); + + g_print ("%*s%s: %s\n", tab, " ", + gst_tag_get_nick (g_quark_to_string (field_id)), ser); + g_free (ser); + + return TRUE; +} + +static void +print_properties (GstDiscovererInfo * info, gint tab) +{ + const GstTagList *tags; + + g_print ("%*sDuration: %" GST_TIME_FORMAT "\n", tab + 1, " ", + GST_TIME_ARGS (gst_discoverer_info_get_duration (info))); + g_print ("%*sSeekable: %s\n", tab + 1, " ", + (gst_discoverer_info_get_seekable (info) ? "yes" : "no")); + if ((tags = gst_discoverer_info_get_tags (info))) { + g_print ("%*sTags: \n", tab + 1, " "); + gst_structure_foreach ((const GstStructure *) tags, print_tag_each, + GINT_TO_POINTER (tab + 5)); + } +} + +static void +print_info (GstDiscovererInfo * info, GError * err) +{ + GstDiscovererResult result = gst_discoverer_info_get_result (info); + GstDiscovererStreamInfo *sinfo; + + g_print ("Done discovering %s\n", gst_discoverer_info_get_uri (info)); + switch (result) { + case GST_DISCOVERER_OK: + { + break; + } + case GST_DISCOVERER_URI_INVALID: + { + g_print ("URI is not valid\n"); + break; + } + case GST_DISCOVERER_ERROR: + { + g_print ("An error was encountered while discovering the file\n"); + g_print (" %s\n", err->message); + break; + } + case GST_DISCOVERER_TIMEOUT: + { + g_print ("Analyzing URI timed out\n"); + break; + } + case GST_DISCOVERER_BUSY: + { + g_print ("Discoverer was busy\n"); + break; + } + case GST_DISCOVERER_MISSING_PLUGINS: + { + g_print ("Missing plugins\n"); + if (verbose) { + gchar *tmp = + gst_structure_to_string (gst_discoverer_info_get_misc (info)); + g_print (" (%s)\n", tmp); + g_free (tmp); + } + break; + } + } + + if ((sinfo = gst_discoverer_info_get_stream_info (info))) { + g_print ("\nTopology:\n"); + print_topology (sinfo, 1); + g_print ("\nProperties:\n"); + print_properties (info, 1); + gst_discoverer_stream_info_unref (sinfo); + } + + g_print ("\n"); +} + +static void +process_file (GstDiscoverer * dc, const gchar * filename) +{ + GError *err = NULL; + GDir *dir; + gchar *uri, *path; + GstDiscovererInfo *info; + GstStructure *st = NULL; + + if (!gst_uri_is_valid (filename)) { + /* Recurse into directories */ + if ((dir = g_dir_open (filename, 0, NULL))) { + const gchar *entry; + + while ((entry = g_dir_read_name (dir))) { + gchar *path; + path = g_strconcat (filename, G_DIR_SEPARATOR_S, entry, NULL); + process_file (dc, path); + g_free (path); + } + + g_dir_close (dir); + return; + } + + if (!g_path_is_absolute (filename)) { + gchar *cur_dir; + + cur_dir = g_get_current_dir (); + path = g_build_filename (cur_dir, filename, NULL); + g_free (cur_dir); + } else { + path = g_strdup (filename); + } + + uri = g_filename_to_uri (path, NULL, &err); + g_free (path); + path = NULL; + + if (err) { + g_warning ("Couldn't convert filename to URI: %s\n", err->message); + g_error_free (err); + return; + } + } else { + uri = g_strdup (filename); + } + + if (async == FALSE) { + g_print ("Analyzing %s\n", uri); + info = gst_discoverer_discover_uri (dc, uri, &err); + print_info (info, err); + gst_discoverer_info_unref (info); + if (st) + gst_structure_free (st); + } else { + gst_discoverer_discover_uri_async (dc, uri); + } + + g_free (uri); +} + +static void +_new_discovered_uri (GstDiscoverer * dc, GstDiscovererInfo * info, GError * err) +{ + print_info (info, err); +} + +static gboolean +_run_async (PrivStruct * ps) +{ + gint i; + + for (i = 1; i < ps->argc; i++) + process_file (ps->dc, ps->argv[i]); + + return FALSE; +} + +static void +_discoverer_finished (GstDiscoverer * dc, GMainLoop * ml) +{ + g_main_loop_quit (ml); +} + +int +main (int argc, char **argv) +{ + GError *err = NULL; + GstDiscoverer *dc; + gint timeout = 10; + GOptionEntry options[] = { + {"async", 'a', 0, G_OPTION_ARG_NONE, &async, + "Run asynchronously", NULL}, + {"silent", 's', 0, G_OPTION_ARG_NONE, &silent, + "Don't output the information structure", NULL}, + {"timeout", 't', 0, G_OPTION_ARG_INT, &timeout, + "Specify timeout (in seconds, default 10)", "T"}, + /* {"elem", 'e', 0, G_OPTION_ARG_NONE, &elem_seek, */ + /* "Seek on elements instead of pads", NULL}, */ + {"verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, + "Verbose properties", NULL}, + {NULL} + }; + GOptionContext *ctx; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = + g_option_context_new + ("- discover files synchronously with GstDiscoverer"); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + g_option_context_free (ctx); + + if (argc < 2) { + g_print ("usage: %s \n", argv[0]); + exit (-1); + } + + dc = gst_discoverer_new (timeout * GST_SECOND, &err); + if (G_UNLIKELY (dc == NULL)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + + if (async == FALSE) { + gint i; + for (i = 1; i < argc; i++) + process_file (dc, argv[i]); + } else { + PrivStruct *ps = g_new0 (PrivStruct, 1); + GMainLoop *ml = g_main_loop_new (NULL, FALSE); + + ps->dc = dc; + ps->argc = argc; + ps->argv = argv; + + /* adding uris will be started when the mainloop runs */ + g_idle_add ((GSourceFunc) _run_async, ps); + + /* connect signals */ + g_signal_connect (dc, "discovered", G_CALLBACK (_new_discovered_uri), NULL); + g_signal_connect (dc, "finished", G_CALLBACK (_discoverer_finished), ml); + + gst_discoverer_start (dc); + /* run mainloop */ + g_main_loop_run (ml); + + gst_discoverer_stop (dc); + g_free (ps); + g_main_loop_unref (ml); + } + g_object_unref (dc); + + return 0; +} diff --git a/gst-plugins-base-subtitles0.10/tools/gst-launch-ext.1.in b/gst-plugins-base-subtitles0.10/tools/gst-launch-ext.1.in new file mode 100644 index 0000000..ada7380 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/gst-launch-ext.1.in @@ -0,0 +1,42 @@ +.TH "GStreamer" "1" "February 2002" "" "" +.SH "NAME" +gst\-launch\-ext \- Run a predefined GStreamer pipeline +.SH "SYNOPSIS" +\fBgst\-launch\-ext\fR \fIfilename [filename...]\fR +.SH "DESCRIPTION" +.LP +\fIgst\-launch\-ext\fP is a tool that is used to run a basic predefined +\fIGStreamer\fP pipeline. This application is only used as a quick test to +ensure proper working of codecs and GStreamer. It doesn't handle more advanced +features like synchronisation. + +All supported formats in GStreamer should be playable by simply typing: + + gst\-launch\-ext filename + +It will also print out the pipeline it uses, so you can customize it using +cut and paste. + +.SH "CONFIGURATION" +.LP +\fIgst\-launch\-ext\fP can be configured by creating a .gst file in your +home directory. This is a perl-style configuration file and can override +the defaults for audio and video output sinks. + +Here is an example .gst file that implements the same defaults as hard-coded +in the script : + +AUDIOSINK = osssink +VIDEOSINK = ffmpegcolorspace ! xvimagesink + +You can change osssink to esdsink or alsasink (if you have +the plug-in), and you can change xvimagesink to ximagesink, aasink +or sdlvideosink. + +Other plug-ins might be used as well if GStreamer has them. + +.SH "SEE ALSO" +.BR gst\-inspect (1), +.BR gst\-launch (1), +.SH "AUTHOR" +The GStreamer team at http://gstreamer.net/ diff --git a/gst-plugins-base-subtitles0.10/tools/gst-visualise.1.in b/gst-plugins-base-subtitles0.10/tools/gst-visualise.1.in new file mode 100644 index 0000000..5b5a1fc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/tools/gst-visualise.1.in @@ -0,0 +1,32 @@ +.TH "GStreamer" "1" "February 2002" "" "" +.SH "NAME" +gst\-visualise \- Run a GStreamer pipeline to display an audio visualisation +.SH "SYNOPSIS" +\fBgst\-visualise\fR \fI[visualiser]\fR +.SH "DESCRIPTION" +.LP +\fIgst\-visualise\fP is a tool that is used to run a basic \fIGStreamer\fP pipeline, to display a graphical visualisation of an audio stream. + +By default, the audio stream is read from ESD (the Enlightened Sound Daemon), +but this can be changed by setting the AUDIOSRC parameter in ~/.gst. For +example, you might set "AUDIOSRC=osssrc" to display a visualisation of the +sound input to your soundcard. + +You can select a visualiser by providing a parameter naming the visualiser. +For example: + + gst\-visualise synaesthesia + +will use the synaesthesia plugin. If no visualiser is named, the VISUALIZER +property in ~/.gst will be used. If this is not specified either, the goom +visualiser will be used. + +The videosink to use to display the visualisation will be read from the +VIDEOSINK parameter in ~/.gst, defaulting to sdlvideosink. + +.SH "SEE ALSO" +.BR gst\-launch\-ext (1), +.BR gst\-inspect (1), +.BR gst\-launch (1), +.SH "AUTHOR" +The GStreamer team at http://gstreamer.net/ diff --git a/gst-plugins-base-subtitles0.10/win32/MANIFEST b/gst-plugins-base-subtitles0.10/win32/MANIFEST new file mode 100644 index 0000000..f075b82 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/MANIFEST @@ -0,0 +1,84 @@ +win32/MANIFEST +win32/common/_stdint.h +win32/common/config.h +win32/common/gstrtsp-enumtypes.c +win32/common/gstrtsp-enumtypes.h +win32/common/interfaces-enumtypes.c +win32/common/interfaces-enumtypes.h +win32/common/libgstapp.def +win32/common/libgstaudio.def +win32/common/libgstcdda.def +win32/common/libgstinterfaces.def +win32/common/libgstnetbuffer.def +win32/common/libgstpbutils.def +win32/common/libgstriff.def +win32/common/libgstrtp.def +win32/common/libgstrtsp.def +win32/common/libgstsdp.def +win32/common/libgsttag.def +win32/common/libgstvideo.def +win32/common/audio-enumtypes.c +win32/common/audio-enumtypes.h +win32/common/pbutils-enumtypes.c +win32/common/pbutils-enumtypes.h +win32/common/video-enumtypes.c +win32/common/video-enumtypes.h +win32/vs6/gst_plugins_base.dsw +win32/vs6/grammar.dsp +win32/vs6/libgstadder.dsp +win32/vs6/libgstaudio.dsp +win32/vs6/libgstaudioconvert.dsp +win32/vs6/libgstaudiorate.dsp +win32/vs6/libgstaudioresample.dsp +win32/vs6/libgstaudioscale.dsp +win32/vs6/libgstaudiotestsrc.dsp +win32/vs6/libgstcdda.dsp +win32/vs6/libgstdecodebin2.dsp +win32/vs6/libgstdecodebin.dsp +win32/vs6/libgstffmpegcolorspace.dsp +win32/vs6/libgstfft.dsp +win32/vs6/libgstgdp.dsp +win32/vs6/libgstinterfaces.dsp +win32/vs6/libgstnetbuffer.dsp +win32/vs6/libgstogg.dsp +win32/vs6/libgstpbutils.dsp +win32/vs6/libgstplaybin.dsp +win32/vs6/libgstriff.dsp +win32/vs6/libgstrtp.dsp +win32/vs6/libgstrtsp.dsp +win32/vs6/libgstsdp.dsp +win32/vs6/libgstsinesrc.dsp +win32/vs6/libgstsubparse.dsp +win32/vs6/libgsttag.dsp +win32/vs6/libgsttheora.dsp +win32/vs6/libgsttypefindfunctions.dsp +win32/vs6/libgstvideo.dsp +win32/vs6/libgstvideorate.dsp +win32/vs6/libgstvideoscale.dsp +win32/vs6/libgstvideotestsrc.dsp +win32/vs6/libgstvolume.dsp +win32/vs6/libgstvorbis.dsp +win32/vs8/gst-plugins-base.sln +win32/vs8/libgstadder.vcproj +win32/vs8/libgstaudio.vcproj +win32/vs8/libgstaudioconvert.vcproj +win32/vs8/libgstaudiorate.vcproj +win32/vs8/libgstaudioresample.vcproj +win32/vs8/libgstaudiotestsrc.vcproj +win32/vs8/libgstdecodebin.vcproj +win32/vs8/libgstffmpegcolorspace.vcproj +win32/vs8/libgstinterfaces.vcproj +win32/vs8/libgstogg.vcproj +win32/vs8/libgstplaybin.vcproj +win32/vs8/libgstriff.vcproj +win32/vs8/libgstsubparse.vcproj +win32/vs8/libgsttag.vcproj +win32/vs8/libgsttcp.vcproj +win32/vs8/libgsttheora.vcproj +win32/vs8/libgsttypefind.vcproj +win32/vs8/libgstvideo.vcproj +win32/vs8/libgstvideorate.vcproj +win32/vs8/libgstvideoscale.vcproj +win32/vs8/libgstvideotestsrc.vcproj +win32/vs8/libgstvolume.vcproj +win32/vs8/libgstvorbis.vcproj diff --git a/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.c new file mode 100644 index 0000000..61af357 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.c @@ -0,0 +1,173 @@ + + + +#include "audio-enumtypes.h" + +#include "multichannel.h" +#include "gstringbuffer.h" + +/* enumerations from "multichannel.h" */ +GType +gst_audio_channel_position_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_AUDIO_CHANNEL_POSITION_INVALID, "GST_AUDIO_CHANNEL_POSITION_INVALID", + "invalid"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO", "front-mono"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT", "front-left"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT", "front-right"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + "GST_AUDIO_CHANNEL_POSITION_REAR_CENTER", "rear-center"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + "GST_AUDIO_CHANNEL_POSITION_REAR_LEFT", "rear-left"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT", "rear-right"}, + {GST_AUDIO_CHANNEL_POSITION_LFE, "GST_AUDIO_CHANNEL_POSITION_LFE", "lfe"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER", "front-center"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER", + "front-left-of-center"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER", + "front-right-of-center"}, + {GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + "GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT", "side-left"}, + {GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT", "side-right"}, + {GST_AUDIO_CHANNEL_POSITION_NONE, "GST_AUDIO_CHANNEL_POSITION_NONE", + "none"}, + {GST_AUDIO_CHANNEL_POSITION_NUM, "GST_AUDIO_CHANNEL_POSITION_NUM", "num"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstAudioChannelPosition", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "gstringbuffer.h" */ +GType +gst_ring_buffer_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RING_BUFFER_STATE_STOPPED, "GST_RING_BUFFER_STATE_STOPPED", + "stopped"}, + {GST_RING_BUFFER_STATE_PAUSED, "GST_RING_BUFFER_STATE_PAUSED", "paused"}, + {GST_RING_BUFFER_STATE_STARTED, "GST_RING_BUFFER_STATE_STARTED", + "started"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstRingBufferState", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_ring_buffer_seg_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_SEGSTATE_INVALID, "GST_SEGSTATE_INVALID", "invalid"}, + {GST_SEGSTATE_EMPTY, "GST_SEGSTATE_EMPTY", "empty"}, + {GST_SEGSTATE_FILLED, "GST_SEGSTATE_FILLED", "filled"}, + {GST_SEGSTATE_PARTIAL, "GST_SEGSTATE_PARTIAL", "partial"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstRingBufferSegState", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_buffer_format_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_BUFTYPE_LINEAR, "GST_BUFTYPE_LINEAR", "linear"}, + {GST_BUFTYPE_FLOAT, "GST_BUFTYPE_FLOAT", "float"}, + {GST_BUFTYPE_MU_LAW, "GST_BUFTYPE_MU_LAW", "mu-law"}, + {GST_BUFTYPE_A_LAW, "GST_BUFTYPE_A_LAW", "a-law"}, + {GST_BUFTYPE_IMA_ADPCM, "GST_BUFTYPE_IMA_ADPCM", "ima-adpcm"}, + {GST_BUFTYPE_MPEG, "GST_BUFTYPE_MPEG", "mpeg"}, + {GST_BUFTYPE_GSM, "GST_BUFTYPE_GSM", "gsm"}, + {GST_BUFTYPE_IEC958, "GST_BUFTYPE_IEC958", "iec958"}, + {GST_BUFTYPE_AC3, "GST_BUFTYPE_AC3", "ac3"}, + {GST_BUFTYPE_EAC3, "GST_BUFTYPE_EAC3", "eac3"}, + {GST_BUFTYPE_DTS, "GST_BUFTYPE_DTS", "dts"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstBufferFormatType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_buffer_format_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_UNKNOWN, "GST_UNKNOWN", "unknown"}, + {GST_S8, "GST_S8", "s8"}, + {GST_U8, "GST_U8", "u8"}, + {GST_S16_LE, "GST_S16_LE", "s16-le"}, + {GST_S16_BE, "GST_S16_BE", "s16-be"}, + {GST_U16_LE, "GST_U16_LE", "u16-le"}, + {GST_U16_BE, "GST_U16_BE", "u16-be"}, + {GST_S24_LE, "GST_S24_LE", "s24-le"}, + {GST_S24_BE, "GST_S24_BE", "s24-be"}, + {GST_U24_LE, "GST_U24_LE", "u24-le"}, + {GST_U24_BE, "GST_U24_BE", "u24-be"}, + {GST_S32_LE, "GST_S32_LE", "s32-le"}, + {GST_S32_BE, "GST_S32_BE", "s32-be"}, + {GST_U32_LE, "GST_U32_LE", "u32-le"}, + {GST_U32_BE, "GST_U32_BE", "u32-be"}, + {GST_S24_3LE, "GST_S24_3LE", "s24-3le"}, + {GST_S24_3BE, "GST_S24_3BE", "s24-3be"}, + {GST_U24_3LE, "GST_U24_3LE", "u24-3le"}, + {GST_U24_3BE, "GST_U24_3BE", "u24-3be"}, + {GST_S20_3LE, "GST_S20_3LE", "s20-3le"}, + {GST_S20_3BE, "GST_S20_3BE", "s20-3be"}, + {GST_U20_3LE, "GST_U20_3LE", "u20-3le"}, + {GST_U20_3BE, "GST_U20_3BE", "u20-3be"}, + {GST_S18_3LE, "GST_S18_3LE", "s18-3le"}, + {GST_S18_3BE, "GST_S18_3BE", "s18-3be"}, + {GST_U18_3LE, "GST_U18_3LE", "u18-3le"}, + {GST_U18_3BE, "GST_U18_3BE", "u18-3be"}, + {GST_FLOAT32_LE, "GST_FLOAT32_LE", "float32-le"}, + {GST_FLOAT32_BE, "GST_FLOAT32_BE", "float32-be"}, + {GST_FLOAT64_LE, "GST_FLOAT64_LE", "float64-le"}, + {GST_FLOAT64_BE, "GST_FLOAT64_BE", "float64-be"}, + {GST_MU_LAW, "GST_MU_LAW", "mu-law"}, + {GST_A_LAW, "GST_A_LAW", "a-law"}, + {GST_IMA_ADPCM, "GST_IMA_ADPCM", "ima-adpcm"}, + {GST_MPEG, "GST_MPEG", "mpeg"}, + {GST_GSM, "GST_GSM", "gsm"}, + {GST_IEC958, "GST_IEC958", "iec958"}, + {GST_AC3, "GST_AC3", "ac3"}, + {GST_EAC3, "GST_EAC3", "eac3"}, + {GST_DTS, "GST_DTS", "dts"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstBufferFormat", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} diff --git a/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.h new file mode 100644 index 0000000..bc0db46 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/audio-enumtypes.h @@ -0,0 +1,29 @@ + + + +#ifndef __GST_AUDIO_ENUM_TYPES_H__ +#define __GST_AUDIO_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "multichannel.h" */ +GType gst_audio_channel_position_get_type (void); +#define GST_TYPE_AUDIO_CHANNEL_POSITION (gst_audio_channel_position_get_type()) + +/* enumerations from "gstringbuffer.h" */ +GType gst_ring_buffer_state_get_type (void); +#define GST_TYPE_RING_BUFFER_STATE (gst_ring_buffer_state_get_type()) +GType gst_ring_buffer_seg_state_get_type (void); +#define GST_TYPE_RING_BUFFER_SEG_STATE (gst_ring_buffer_seg_state_get_type()) +GType gst_buffer_format_type_get_type (void); +#define GST_TYPE_BUFFER_FORMAT_TYPE (gst_buffer_format_type_get_type()) +GType gst_buffer_format_get_type (void); +#define GST_TYPE_BUFFER_FORMAT (gst_buffer_format_get_type()) +G_END_DECLS + +#endif /* __GST_AUDIO_ENUM_TYPES_H__ */ + + + diff --git a/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.c new file mode 100644 index 0000000..15a0c4b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.c @@ -0,0 +1,389 @@ + + + +#include "gstrtsp-enumtypes.h" + +#include "gstrtspdefs.h" + +/* enumerations from "gstrtspdefs.h" */ +GType +gst_rtsp_result_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_OK, "GST_RTSP_OK", "ok"}, + {GST_RTSP_ERROR, "GST_RTSP_ERROR", "error"}, + {GST_RTSP_EINVAL, "GST_RTSP_EINVAL", "einval"}, + {GST_RTSP_EINTR, "GST_RTSP_EINTR", "eintr"}, + {GST_RTSP_ENOMEM, "GST_RTSP_ENOMEM", "enomem"}, + {GST_RTSP_ERESOLV, "GST_RTSP_ERESOLV", "eresolv"}, + {GST_RTSP_ENOTIMPL, "GST_RTSP_ENOTIMPL", "enotimpl"}, + {GST_RTSP_ESYS, "GST_RTSP_ESYS", "esys"}, + {GST_RTSP_EPARSE, "GST_RTSP_EPARSE", "eparse"}, + {GST_RTSP_EWSASTART, "GST_RTSP_EWSASTART", "ewsastart"}, + {GST_RTSP_EWSAVERSION, "GST_RTSP_EWSAVERSION", "ewsaversion"}, + {GST_RTSP_EEOF, "GST_RTSP_EEOF", "eeof"}, + {GST_RTSP_ENET, "GST_RTSP_ENET", "enet"}, + {GST_RTSP_ENOTIP, "GST_RTSP_ENOTIP", "enotip"}, + {GST_RTSP_ETIMEOUT, "GST_RTSP_ETIMEOUT", "etimeout"}, + {GST_RTSP_ETGET, "GST_RTSP_ETGET", "etget"}, + {GST_RTSP_ETPOST, "GST_RTSP_ETPOST", "etpost"}, + {GST_RTSP_ELAST, "GST_RTSP_ELAST", "elast"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstRTSPResult", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_event_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GFlagsValue values[] = { + {GST_RTSP_EV_READ, "GST_RTSP_EV_READ", "read"}, + {GST_RTSP_EV_WRITE, "GST_RTSP_EV_WRITE", "write"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_flags_register_static ("GstRTSPEvent", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_family_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_FAM_NONE, "GST_RTSP_FAM_NONE", "none"}, + {GST_RTSP_FAM_INET, "GST_RTSP_FAM_INET", "inet"}, + {GST_RTSP_FAM_INET6, "GST_RTSP_FAM_INET6", "inet6"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstRTSPFamily", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_state_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_STATE_INVALID, "GST_RTSP_STATE_INVALID", "invalid"}, + {GST_RTSP_STATE_INIT, "GST_RTSP_STATE_INIT", "init"}, + {GST_RTSP_STATE_READY, "GST_RTSP_STATE_READY", "ready"}, + {GST_RTSP_STATE_SEEKING, "GST_RTSP_STATE_SEEKING", "seeking"}, + {GST_RTSP_STATE_PLAYING, "GST_RTSP_STATE_PLAYING", "playing"}, + {GST_RTSP_STATE_RECORDING, "GST_RTSP_STATE_RECORDING", "recording"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstRTSPState", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_version_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_VERSION_INVALID, "GST_RTSP_VERSION_INVALID", "invalid"}, + {GST_RTSP_VERSION_1_0, "GST_RTSP_VERSION_1_0", "1-0"}, + {GST_RTSP_VERSION_1_1, "GST_RTSP_VERSION_1_1", "1-1"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstRTSPVersion", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_method_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GFlagsValue values[] = { + {GST_RTSP_INVALID, "GST_RTSP_INVALID", "invalid"}, + {GST_RTSP_DESCRIBE, "GST_RTSP_DESCRIBE", "describe"}, + {GST_RTSP_ANNOUNCE, "GST_RTSP_ANNOUNCE", "announce"}, + {GST_RTSP_GET_PARAMETER, "GST_RTSP_GET_PARAMETER", "get-parameter"}, + {GST_RTSP_OPTIONS, "GST_RTSP_OPTIONS", "options"}, + {GST_RTSP_PAUSE, "GST_RTSP_PAUSE", "pause"}, + {GST_RTSP_PLAY, "GST_RTSP_PLAY", "play"}, + {GST_RTSP_RECORD, "GST_RTSP_RECORD", "record"}, + {GST_RTSP_REDIRECT, "GST_RTSP_REDIRECT", "redirect"}, + {GST_RTSP_SETUP, "GST_RTSP_SETUP", "setup"}, + {GST_RTSP_SET_PARAMETER, "GST_RTSP_SET_PARAMETER", "set-parameter"}, + {GST_RTSP_TEARDOWN, "GST_RTSP_TEARDOWN", "teardown"}, + {GST_RTSP_GET, "GST_RTSP_GET", "get"}, + {GST_RTSP_POST, "GST_RTSP_POST", "post"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_flags_register_static ("GstRTSPMethod", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_auth_method_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_AUTH_NONE, "GST_RTSP_AUTH_NONE", "none"}, + {GST_RTSP_AUTH_BASIC, "GST_RTSP_AUTH_BASIC", "basic"}, + {GST_RTSP_AUTH_DIGEST, "GST_RTSP_AUTH_DIGEST", "digest"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstRTSPAuthMethod", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_header_field_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_HDR_INVALID, "GST_RTSP_HDR_INVALID", "invalid"}, + {GST_RTSP_HDR_ACCEPT, "GST_RTSP_HDR_ACCEPT", "accept"}, + {GST_RTSP_HDR_ACCEPT_ENCODING, "GST_RTSP_HDR_ACCEPT_ENCODING", + "accept-encoding"}, + {GST_RTSP_HDR_ACCEPT_LANGUAGE, "GST_RTSP_HDR_ACCEPT_LANGUAGE", + "accept-language"}, + {GST_RTSP_HDR_ALLOW, "GST_RTSP_HDR_ALLOW", "allow"}, + {GST_RTSP_HDR_AUTHORIZATION, "GST_RTSP_HDR_AUTHORIZATION", + "authorization"}, + {GST_RTSP_HDR_BANDWIDTH, "GST_RTSP_HDR_BANDWIDTH", "bandwidth"}, + {GST_RTSP_HDR_BLOCKSIZE, "GST_RTSP_HDR_BLOCKSIZE", "blocksize"}, + {GST_RTSP_HDR_CACHE_CONTROL, "GST_RTSP_HDR_CACHE_CONTROL", + "cache-control"}, + {GST_RTSP_HDR_CONFERENCE, "GST_RTSP_HDR_CONFERENCE", "conference"}, + {GST_RTSP_HDR_CONNECTION, "GST_RTSP_HDR_CONNECTION", "connection"}, + {GST_RTSP_HDR_CONTENT_BASE, "GST_RTSP_HDR_CONTENT_BASE", "content-base"}, + {GST_RTSP_HDR_CONTENT_ENCODING, "GST_RTSP_HDR_CONTENT_ENCODING", + "content-encoding"}, + {GST_RTSP_HDR_CONTENT_LANGUAGE, "GST_RTSP_HDR_CONTENT_LANGUAGE", + "content-language"}, + {GST_RTSP_HDR_CONTENT_LENGTH, "GST_RTSP_HDR_CONTENT_LENGTH", + "content-length"}, + {GST_RTSP_HDR_CONTENT_LOCATION, "GST_RTSP_HDR_CONTENT_LOCATION", + "content-location"}, + {GST_RTSP_HDR_CONTENT_TYPE, "GST_RTSP_HDR_CONTENT_TYPE", "content-type"}, + {GST_RTSP_HDR_CSEQ, "GST_RTSP_HDR_CSEQ", "cseq"}, + {GST_RTSP_HDR_DATE, "GST_RTSP_HDR_DATE", "date"}, + {GST_RTSP_HDR_EXPIRES, "GST_RTSP_HDR_EXPIRES", "expires"}, + {GST_RTSP_HDR_FROM, "GST_RTSP_HDR_FROM", "from"}, + {GST_RTSP_HDR_IF_MODIFIED_SINCE, "GST_RTSP_HDR_IF_MODIFIED_SINCE", + "if-modified-since"}, + {GST_RTSP_HDR_LAST_MODIFIED, "GST_RTSP_HDR_LAST_MODIFIED", + "last-modified"}, + {GST_RTSP_HDR_PROXY_AUTHENTICATE, "GST_RTSP_HDR_PROXY_AUTHENTICATE", + "proxy-authenticate"}, + {GST_RTSP_HDR_PROXY_REQUIRE, "GST_RTSP_HDR_PROXY_REQUIRE", + "proxy-require"}, + {GST_RTSP_HDR_PUBLIC, "GST_RTSP_HDR_PUBLIC", "public"}, + {GST_RTSP_HDR_RANGE, "GST_RTSP_HDR_RANGE", "range"}, + {GST_RTSP_HDR_REFERER, "GST_RTSP_HDR_REFERER", "referer"}, + {GST_RTSP_HDR_REQUIRE, "GST_RTSP_HDR_REQUIRE", "require"}, + {GST_RTSP_HDR_RETRY_AFTER, "GST_RTSP_HDR_RETRY_AFTER", "retry-after"}, + {GST_RTSP_HDR_RTP_INFO, "GST_RTSP_HDR_RTP_INFO", "rtp-info"}, + {GST_RTSP_HDR_SCALE, "GST_RTSP_HDR_SCALE", "scale"}, + {GST_RTSP_HDR_SESSION, "GST_RTSP_HDR_SESSION", "session"}, + {GST_RTSP_HDR_SERVER, "GST_RTSP_HDR_SERVER", "server"}, + {GST_RTSP_HDR_SPEED, "GST_RTSP_HDR_SPEED", "speed"}, + {GST_RTSP_HDR_TRANSPORT, "GST_RTSP_HDR_TRANSPORT", "transport"}, + {GST_RTSP_HDR_UNSUPPORTED, "GST_RTSP_HDR_UNSUPPORTED", "unsupported"}, + {GST_RTSP_HDR_USER_AGENT, "GST_RTSP_HDR_USER_AGENT", "user-agent"}, + {GST_RTSP_HDR_VIA, "GST_RTSP_HDR_VIA", "via"}, + {GST_RTSP_HDR_WWW_AUTHENTICATE, "GST_RTSP_HDR_WWW_AUTHENTICATE", + "www-authenticate"}, + {GST_RTSP_HDR_CLIENT_CHALLENGE, "GST_RTSP_HDR_CLIENT_CHALLENGE", + "client-challenge"}, + {GST_RTSP_HDR_REAL_CHALLENGE1, "GST_RTSP_HDR_REAL_CHALLENGE1", + "real-challenge1"}, + {GST_RTSP_HDR_REAL_CHALLENGE2, "GST_RTSP_HDR_REAL_CHALLENGE2", + "real-challenge2"}, + {GST_RTSP_HDR_REAL_CHALLENGE3, "GST_RTSP_HDR_REAL_CHALLENGE3", + "real-challenge3"}, + {GST_RTSP_HDR_SUBSCRIBE, "GST_RTSP_HDR_SUBSCRIBE", "subscribe"}, + {GST_RTSP_HDR_ALERT, "GST_RTSP_HDR_ALERT", "alert"}, + {GST_RTSP_HDR_CLIENT_ID, "GST_RTSP_HDR_CLIENT_ID", "client-id"}, + {GST_RTSP_HDR_COMPANY_ID, "GST_RTSP_HDR_COMPANY_ID", "company-id"}, + {GST_RTSP_HDR_GUID, "GST_RTSP_HDR_GUID", "guid"}, + {GST_RTSP_HDR_REGION_DATA, "GST_RTSP_HDR_REGION_DATA", "region-data"}, + {GST_RTSP_HDR_MAX_ASM_WIDTH, "GST_RTSP_HDR_MAX_ASM_WIDTH", + "max-asm-width"}, + {GST_RTSP_HDR_LANGUAGE, "GST_RTSP_HDR_LANGUAGE", "language"}, + {GST_RTSP_HDR_PLAYER_START_TIME, "GST_RTSP_HDR_PLAYER_START_TIME", + "player-start-time"}, + {GST_RTSP_HDR_LOCATION, "GST_RTSP_HDR_LOCATION", "location"}, + {GST_RTSP_HDR_ETAG, "GST_RTSP_HDR_ETAG", "etag"}, + {GST_RTSP_HDR_IF_MATCH, "GST_RTSP_HDR_IF_MATCH", "if-match"}, + {GST_RTSP_HDR_ACCEPT_CHARSET, "GST_RTSP_HDR_ACCEPT_CHARSET", + "accept-charset"}, + {GST_RTSP_HDR_SUPPORTED, "GST_RTSP_HDR_SUPPORTED", "supported"}, + {GST_RTSP_HDR_VARY, "GST_RTSP_HDR_VARY", "vary"}, + {GST_RTSP_HDR_X_ACCELERATE_STREAMING, + "GST_RTSP_HDR_X_ACCELERATE_STREAMING", "x-accelerate-streaming"}, + {GST_RTSP_HDR_X_ACCEPT_AUTHENT, "GST_RTSP_HDR_X_ACCEPT_AUTHENT", + "x-accept-authent"}, + {GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT, + "GST_RTSP_HDR_X_ACCEPT_PROXY_AUTHENT", "x-accept-proxy-authent"}, + {GST_RTSP_HDR_X_BROADCAST_ID, "GST_RTSP_HDR_X_BROADCAST_ID", + "x-broadcast-id"}, + {GST_RTSP_HDR_X_BURST_STREAMING, "GST_RTSP_HDR_X_BURST_STREAMING", + "x-burst-streaming"}, + {GST_RTSP_HDR_X_NOTICE, "GST_RTSP_HDR_X_NOTICE", "x-notice"}, + {GST_RTSP_HDR_X_PLAYER_LAG_TIME, "GST_RTSP_HDR_X_PLAYER_LAG_TIME", + "x-player-lag-time"}, + {GST_RTSP_HDR_X_PLAYLIST, "GST_RTSP_HDR_X_PLAYLIST", "x-playlist"}, + {GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE, + "GST_RTSP_HDR_X_PLAYLIST_CHANGE_NOTICE", + "x-playlist-change-notice"}, + {GST_RTSP_HDR_X_PLAYLIST_GEN_ID, "GST_RTSP_HDR_X_PLAYLIST_GEN_ID", + "x-playlist-gen-id"}, + {GST_RTSP_HDR_X_PLAYLIST_SEEK_ID, "GST_RTSP_HDR_X_PLAYLIST_SEEK_ID", + "x-playlist-seek-id"}, + {GST_RTSP_HDR_X_PROXY_CLIENT_AGENT, "GST_RTSP_HDR_X_PROXY_CLIENT_AGENT", + "x-proxy-client-agent"}, + {GST_RTSP_HDR_X_PROXY_CLIENT_VERB, "GST_RTSP_HDR_X_PROXY_CLIENT_VERB", + "x-proxy-client-verb"}, + {GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE, + "GST_RTSP_HDR_X_RECEDING_PLAYLISTCHANGE", + "x-receding-playlistchange"}, + {GST_RTSP_HDR_X_RTP_INFO, "GST_RTSP_HDR_X_RTP_INFO", "x-rtp-info"}, + {GST_RTSP_HDR_X_STARTUPPROFILE, "GST_RTSP_HDR_X_STARTUPPROFILE", + "x-startupprofile"}, + {GST_RTSP_HDR_TIMESTAMP, "GST_RTSP_HDR_TIMESTAMP", "timestamp"}, + {GST_RTSP_HDR_AUTHENTICATION_INFO, "GST_RTSP_HDR_AUTHENTICATION_INFO", + "authentication-info"}, + {GST_RTSP_HDR_HOST, "GST_RTSP_HDR_HOST", "host"}, + {GST_RTSP_HDR_PRAGMA, "GST_RTSP_HDR_PRAGMA", "pragma"}, + {GST_RTSP_HDR_X_SERVER_IP_ADDRESS, "GST_RTSP_HDR_X_SERVER_IP_ADDRESS", + "x-server-ip-address"}, + {GST_RTSP_HDR_X_SESSIONCOOKIE, "GST_RTSP_HDR_X_SESSIONCOOKIE", + "x-sessioncookie"}, + {GST_RTSP_HDR_LAST, "GST_RTSP_HDR_LAST", "last"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstRTSPHeaderField", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_rtsp_status_code_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_RTSP_STS_INVALID, "GST_RTSP_STS_INVALID", "invalid"}, + {GST_RTSP_STS_CONTINUE, "GST_RTSP_STS_CONTINUE", "continue"}, + {GST_RTSP_STS_OK, "GST_RTSP_STS_OK", "ok"}, + {GST_RTSP_STS_CREATED, "GST_RTSP_STS_CREATED", "created"}, + {GST_RTSP_STS_LOW_ON_STORAGE, "GST_RTSP_STS_LOW_ON_STORAGE", + "low-on-storage"}, + {GST_RTSP_STS_MULTIPLE_CHOICES, "GST_RTSP_STS_MULTIPLE_CHOICES", + "multiple-choices"}, + {GST_RTSP_STS_MOVED_PERMANENTLY, "GST_RTSP_STS_MOVED_PERMANENTLY", + "moved-permanently"}, + {GST_RTSP_STS_MOVE_TEMPORARILY, "GST_RTSP_STS_MOVE_TEMPORARILY", + "move-temporarily"}, + {GST_RTSP_STS_SEE_OTHER, "GST_RTSP_STS_SEE_OTHER", "see-other"}, + {GST_RTSP_STS_NOT_MODIFIED, "GST_RTSP_STS_NOT_MODIFIED", "not-modified"}, + {GST_RTSP_STS_USE_PROXY, "GST_RTSP_STS_USE_PROXY", "use-proxy"}, + {GST_RTSP_STS_BAD_REQUEST, "GST_RTSP_STS_BAD_REQUEST", "bad-request"}, + {GST_RTSP_STS_UNAUTHORIZED, "GST_RTSP_STS_UNAUTHORIZED", "unauthorized"}, + {GST_RTSP_STS_PAYMENT_REQUIRED, "GST_RTSP_STS_PAYMENT_REQUIRED", + "payment-required"}, + {GST_RTSP_STS_FORBIDDEN, "GST_RTSP_STS_FORBIDDEN", "forbidden"}, + {GST_RTSP_STS_NOT_FOUND, "GST_RTSP_STS_NOT_FOUND", "not-found"}, + {GST_RTSP_STS_METHOD_NOT_ALLOWED, "GST_RTSP_STS_METHOD_NOT_ALLOWED", + "method-not-allowed"}, + {GST_RTSP_STS_NOT_ACCEPTABLE, "GST_RTSP_STS_NOT_ACCEPTABLE", + "not-acceptable"}, + {GST_RTSP_STS_PROXY_AUTH_REQUIRED, "GST_RTSP_STS_PROXY_AUTH_REQUIRED", + "proxy-auth-required"}, + {GST_RTSP_STS_REQUEST_TIMEOUT, "GST_RTSP_STS_REQUEST_TIMEOUT", + "request-timeout"}, + {GST_RTSP_STS_GONE, "GST_RTSP_STS_GONE", "gone"}, + {GST_RTSP_STS_LENGTH_REQUIRED, "GST_RTSP_STS_LENGTH_REQUIRED", + "length-required"}, + {GST_RTSP_STS_PRECONDITION_FAILED, "GST_RTSP_STS_PRECONDITION_FAILED", + "precondition-failed"}, + {GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE, + "GST_RTSP_STS_REQUEST_ENTITY_TOO_LARGE", + "request-entity-too-large"}, + {GST_RTSP_STS_REQUEST_URI_TOO_LARGE, "GST_RTSP_STS_REQUEST_URI_TOO_LARGE", + "request-uri-too-large"}, + {GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE, + "GST_RTSP_STS_UNSUPPORTED_MEDIA_TYPE", "unsupported-media-type"}, + {GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD, + "GST_RTSP_STS_PARAMETER_NOT_UNDERSTOOD", + "parameter-not-understood"}, + {GST_RTSP_STS_CONFERENCE_NOT_FOUND, "GST_RTSP_STS_CONFERENCE_NOT_FOUND", + "conference-not-found"}, + {GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH, "GST_RTSP_STS_NOT_ENOUGH_BANDWIDTH", + "not-enough-bandwidth"}, + {GST_RTSP_STS_SESSION_NOT_FOUND, "GST_RTSP_STS_SESSION_NOT_FOUND", + "session-not-found"}, + {GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE, + "GST_RTSP_STS_METHOD_NOT_VALID_IN_THIS_STATE", + "method-not-valid-in-this-state"}, + {GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE, + "GST_RTSP_STS_HEADER_FIELD_NOT_VALID_FOR_RESOURCE", + "header-field-not-valid-for-resource"}, + {GST_RTSP_STS_INVALID_RANGE, "GST_RTSP_STS_INVALID_RANGE", + "invalid-range"}, + {GST_RTSP_STS_PARAMETER_IS_READONLY, "GST_RTSP_STS_PARAMETER_IS_READONLY", + "parameter-is-readonly"}, + {GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED, + "GST_RTSP_STS_AGGREGATE_OPERATION_NOT_ALLOWED", + "aggregate-operation-not-allowed"}, + {GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED, + "GST_RTSP_STS_ONLY_AGGREGATE_OPERATION_ALLOWED", + "only-aggregate-operation-allowed"}, + {GST_RTSP_STS_UNSUPPORTED_TRANSPORT, "GST_RTSP_STS_UNSUPPORTED_TRANSPORT", + "unsupported-transport"}, + {GST_RTSP_STS_DESTINATION_UNREACHABLE, + "GST_RTSP_STS_DESTINATION_UNREACHABLE", "destination-unreachable"}, + {GST_RTSP_STS_INTERNAL_SERVER_ERROR, "GST_RTSP_STS_INTERNAL_SERVER_ERROR", + "internal-server-error"}, + {GST_RTSP_STS_NOT_IMPLEMENTED, "GST_RTSP_STS_NOT_IMPLEMENTED", + "not-implemented"}, + {GST_RTSP_STS_BAD_GATEWAY, "GST_RTSP_STS_BAD_GATEWAY", "bad-gateway"}, + {GST_RTSP_STS_SERVICE_UNAVAILABLE, "GST_RTSP_STS_SERVICE_UNAVAILABLE", + "service-unavailable"}, + {GST_RTSP_STS_GATEWAY_TIMEOUT, "GST_RTSP_STS_GATEWAY_TIMEOUT", + "gateway-timeout"}, + {GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED, + "GST_RTSP_STS_RTSP_VERSION_NOT_SUPPORTED", + "rtsp-version-not-supported"}, + {GST_RTSP_STS_OPTION_NOT_SUPPORTED, "GST_RTSP_STS_OPTION_NOT_SUPPORTED", + "option-not-supported"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstRTSPStatusCode", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} diff --git a/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.h new file mode 100644 index 0000000..3254324 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/gstrtsp-enumtypes.h @@ -0,0 +1,35 @@ + + + +#ifndef __gst_rtsp_ENUM_TYPES_H__ +#define __gst_rtsp_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "gstrtspdefs.h" */ +GType gst_rtsp_result_get_type (void); +#define GST_TYPE_RTSP_RESULT (gst_rtsp_result_get_type()) +GType gst_rtsp_event_get_type (void); +#define GST_TYPE_RTSP_EVENT (gst_rtsp_event_get_type()) +GType gst_rtsp_family_get_type (void); +#define GST_TYPE_RTSP_FAMILY (gst_rtsp_family_get_type()) +GType gst_rtsp_state_get_type (void); +#define GST_TYPE_RTSP_STATE (gst_rtsp_state_get_type()) +GType gst_rtsp_version_get_type (void); +#define GST_TYPE_RTSP_VERSION (gst_rtsp_version_get_type()) +GType gst_rtsp_method_get_type (void); +#define GST_TYPE_RTSP_METHOD (gst_rtsp_method_get_type()) +GType gst_rtsp_auth_method_get_type (void); +#define GST_TYPE_RTSP_AUTH_METHOD (gst_rtsp_auth_method_get_type()) +GType gst_rtsp_header_field_get_type (void); +#define GST_TYPE_RTSP_HEADER_FIELD (gst_rtsp_header_field_get_type()) +GType gst_rtsp_status_code_get_type (void); +#define GST_TYPE_RTSP_STATUS_CODE (gst_rtsp_status_code_get_type()) +G_END_DECLS + +#endif /* __gst_rtsp_ENUM_TYPES_H__ */ + + + diff --git a/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.c new file mode 100644 index 0000000..9cb315d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.c @@ -0,0 +1,274 @@ + + + +#include "interfaces-enumtypes.h" + +#include "colorbalance.h" +#include "colorbalancechannel.h" +#include "mixer.h" +#include "mixeroptions.h" +#include "mixertrack.h" +#include "navigation.h" +#include "propertyprobe.h" +#include "streamvolume.h" +#include "tuner.h" +#include "tunernorm.h" +#include "tunerchannel.h" +#include "videoorientation.h" +#include "xoverlay.h" + +/* enumerations from "colorbalance.h" */ +GType +gst_color_balance_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_COLOR_BALANCE_HARDWARE, "GST_COLOR_BALANCE_HARDWARE", "hardware"}, + {GST_COLOR_BALANCE_SOFTWARE, "GST_COLOR_BALANCE_SOFTWARE", "software"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstColorBalanceType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "mixer.h" */ +GType +gst_mixer_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_MIXER_HARDWARE, "GST_MIXER_HARDWARE", "hardware"}, + {GST_MIXER_SOFTWARE, "GST_MIXER_SOFTWARE", "software"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstMixerType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_mixer_message_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_MIXER_MESSAGE_INVALID, "GST_MIXER_MESSAGE_INVALID", "invalid"}, + {GST_MIXER_MESSAGE_MUTE_TOGGLED, "GST_MIXER_MESSAGE_MUTE_TOGGLED", + "mute-toggled"}, + {GST_MIXER_MESSAGE_RECORD_TOGGLED, "GST_MIXER_MESSAGE_RECORD_TOGGLED", + "record-toggled"}, + {GST_MIXER_MESSAGE_VOLUME_CHANGED, "GST_MIXER_MESSAGE_VOLUME_CHANGED", + "volume-changed"}, + {GST_MIXER_MESSAGE_OPTION_CHANGED, "GST_MIXER_MESSAGE_OPTION_CHANGED", + "option-changed"}, + {GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED, + "GST_MIXER_MESSAGE_OPTIONS_LIST_CHANGED", "options-list-changed"}, + {GST_MIXER_MESSAGE_MIXER_CHANGED, "GST_MIXER_MESSAGE_MIXER_CHANGED", + "mixer-changed"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstMixerMessageType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_mixer_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GFlagsValue values[] = { + {GST_MIXER_FLAG_NONE, "GST_MIXER_FLAG_NONE", "none"}, + {GST_MIXER_FLAG_AUTO_NOTIFICATIONS, "GST_MIXER_FLAG_AUTO_NOTIFICATIONS", + "auto-notifications"}, + {GST_MIXER_FLAG_HAS_WHITELIST, "GST_MIXER_FLAG_HAS_WHITELIST", + "has-whitelist"}, + {GST_MIXER_FLAG_GROUPING, "GST_MIXER_FLAG_GROUPING", "grouping"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_flags_register_static ("GstMixerFlags", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "mixertrack.h" */ +GType +gst_mixer_track_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GFlagsValue values[] = { + {GST_MIXER_TRACK_INPUT, "GST_MIXER_TRACK_INPUT", "input"}, + {GST_MIXER_TRACK_OUTPUT, "GST_MIXER_TRACK_OUTPUT", "output"}, + {GST_MIXER_TRACK_MUTE, "GST_MIXER_TRACK_MUTE", "mute"}, + {GST_MIXER_TRACK_RECORD, "GST_MIXER_TRACK_RECORD", "record"}, + {GST_MIXER_TRACK_MASTER, "GST_MIXER_TRACK_MASTER", "master"}, + {GST_MIXER_TRACK_SOFTWARE, "GST_MIXER_TRACK_SOFTWARE", "software"}, + {GST_MIXER_TRACK_NO_RECORD, "GST_MIXER_TRACK_NO_RECORD", "no-record"}, + {GST_MIXER_TRACK_NO_MUTE, "GST_MIXER_TRACK_NO_MUTE", "no-mute"}, + {GST_MIXER_TRACK_WHITELIST, "GST_MIXER_TRACK_WHITELIST", "whitelist"}, + {GST_MIXER_TRACK_READONLY, "GST_MIXER_TRACK_READONLY", "readonly"}, + {GST_MIXER_TRACK_WRITEONLY, "GST_MIXER_TRACK_WRITEONLY", "writeonly"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_flags_register_static ("GstMixerTrackFlags", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "navigation.h" */ +GType +gst_navigation_command_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_NAVIGATION_COMMAND_INVALID, "GST_NAVIGATION_COMMAND_INVALID", + "invalid"}, + {GST_NAVIGATION_COMMAND_MENU1, "GST_NAVIGATION_COMMAND_MENU1", "menu1"}, + {GST_NAVIGATION_COMMAND_MENU2, "GST_NAVIGATION_COMMAND_MENU2", "menu2"}, + {GST_NAVIGATION_COMMAND_MENU3, "GST_NAVIGATION_COMMAND_MENU3", "menu3"}, + {GST_NAVIGATION_COMMAND_MENU4, "GST_NAVIGATION_COMMAND_MENU4", "menu4"}, + {GST_NAVIGATION_COMMAND_MENU5, "GST_NAVIGATION_COMMAND_MENU5", "menu5"}, + {GST_NAVIGATION_COMMAND_MENU6, "GST_NAVIGATION_COMMAND_MENU6", "menu6"}, + {GST_NAVIGATION_COMMAND_MENU7, "GST_NAVIGATION_COMMAND_MENU7", "menu7"}, + {GST_NAVIGATION_COMMAND_LEFT, "GST_NAVIGATION_COMMAND_LEFT", "left"}, + {GST_NAVIGATION_COMMAND_RIGHT, "GST_NAVIGATION_COMMAND_RIGHT", "right"}, + {GST_NAVIGATION_COMMAND_UP, "GST_NAVIGATION_COMMAND_UP", "up"}, + {GST_NAVIGATION_COMMAND_DOWN, "GST_NAVIGATION_COMMAND_DOWN", "down"}, + {GST_NAVIGATION_COMMAND_ACTIVATE, "GST_NAVIGATION_COMMAND_ACTIVATE", + "activate"}, + {GST_NAVIGATION_COMMAND_PREV_ANGLE, "GST_NAVIGATION_COMMAND_PREV_ANGLE", + "prev-angle"}, + {GST_NAVIGATION_COMMAND_NEXT_ANGLE, "GST_NAVIGATION_COMMAND_NEXT_ANGLE", + "next-angle"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstNavigationCommand", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_navigation_query_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_NAVIGATION_QUERY_INVALID, "GST_NAVIGATION_QUERY_INVALID", "invalid"}, + {GST_NAVIGATION_QUERY_COMMANDS, "GST_NAVIGATION_QUERY_COMMANDS", + "commands"}, + {GST_NAVIGATION_QUERY_ANGLES, "GST_NAVIGATION_QUERY_ANGLES", "angles"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstNavigationQueryType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_navigation_message_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_NAVIGATION_MESSAGE_INVALID, "GST_NAVIGATION_MESSAGE_INVALID", + "invalid"}, + {GST_NAVIGATION_MESSAGE_MOUSE_OVER, "GST_NAVIGATION_MESSAGE_MOUSE_OVER", + "mouse-over"}, + {GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED, + "GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED", "commands-changed"}, + {GST_NAVIGATION_MESSAGE_ANGLES_CHANGED, + "GST_NAVIGATION_MESSAGE_ANGLES_CHANGED", "angles-changed"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstNavigationMessageType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +GType +gst_navigation_event_type_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_NAVIGATION_EVENT_INVALID, "GST_NAVIGATION_EVENT_INVALID", "invalid"}, + {GST_NAVIGATION_EVENT_KEY_PRESS, "GST_NAVIGATION_EVENT_KEY_PRESS", + "key-press"}, + {GST_NAVIGATION_EVENT_KEY_RELEASE, "GST_NAVIGATION_EVENT_KEY_RELEASE", + "key-release"}, + {GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS, + "GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS", "mouse-button-press"}, + {GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE, + "GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE", + "mouse-button-release"}, + {GST_NAVIGATION_EVENT_MOUSE_MOVE, "GST_NAVIGATION_EVENT_MOUSE_MOVE", + "mouse-move"}, + {GST_NAVIGATION_EVENT_COMMAND, "GST_NAVIGATION_EVENT_COMMAND", "command"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstNavigationEventType", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "streamvolume.h" */ +GType +gst_stream_volume_format_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_STREAM_VOLUME_FORMAT_LINEAR, "GST_STREAM_VOLUME_FORMAT_LINEAR", + "linear"}, + {GST_STREAM_VOLUME_FORMAT_CUBIC, "GST_STREAM_VOLUME_FORMAT_CUBIC", + "cubic"}, + {GST_STREAM_VOLUME_FORMAT_DB, "GST_STREAM_VOLUME_FORMAT_DB", "db"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstStreamVolumeFormat", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "tunerchannel.h" */ +GType +gst_tuner_channel_flags_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GFlagsValue values[] = { + {GST_TUNER_CHANNEL_INPUT, "GST_TUNER_CHANNEL_INPUT", "input"}, + {GST_TUNER_CHANNEL_OUTPUT, "GST_TUNER_CHANNEL_OUTPUT", "output"}, + {GST_TUNER_CHANNEL_FREQUENCY, "GST_TUNER_CHANNEL_FREQUENCY", "frequency"}, + {GST_TUNER_CHANNEL_AUDIO, "GST_TUNER_CHANNEL_AUDIO", "audio"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_flags_register_static ("GstTunerChannelFlags", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} diff --git a/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.h new file mode 100644 index 0000000..77fd7eb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/interfaces-enumtypes.h @@ -0,0 +1,49 @@ + + + +#ifndef __GST_INTERFACES_ENUM_TYPES_H__ +#define __GST_INTERFACES_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "colorbalance.h" */ +GType gst_color_balance_type_get_type (void); +#define GST_TYPE_COLOR_BALANCE_TYPE (gst_color_balance_type_get_type()) + +/* enumerations from "mixer.h" */ +GType gst_mixer_type_get_type (void); +#define GST_TYPE_MIXER_TYPE (gst_mixer_type_get_type()) +GType gst_mixer_message_type_get_type (void); +#define GST_TYPE_MIXER_MESSAGE_TYPE (gst_mixer_message_type_get_type()) +GType gst_mixer_flags_get_type (void); +#define GST_TYPE_MIXER_FLAGS (gst_mixer_flags_get_type()) + +/* enumerations from "mixertrack.h" */ +GType gst_mixer_track_flags_get_type (void); +#define GST_TYPE_MIXER_TRACK_FLAGS (gst_mixer_track_flags_get_type()) + +/* enumerations from "navigation.h" */ +GType gst_navigation_command_get_type (void); +#define GST_TYPE_NAVIGATION_COMMAND (gst_navigation_command_get_type()) +GType gst_navigation_query_type_get_type (void); +#define GST_TYPE_NAVIGATION_QUERY_TYPE (gst_navigation_query_type_get_type()) +GType gst_navigation_message_type_get_type (void); +#define GST_TYPE_NAVIGATION_MESSAGE_TYPE (gst_navigation_message_type_get_type()) +GType gst_navigation_event_type_get_type (void); +#define GST_TYPE_NAVIGATION_EVENT_TYPE (gst_navigation_event_type_get_type()) + +/* enumerations from "streamvolume.h" */ +GType gst_stream_volume_format_get_type (void); +#define GST_TYPE_STREAM_VOLUME_FORMAT (gst_stream_volume_format_get_type()) + +/* enumerations from "tunerchannel.h" */ +GType gst_tuner_channel_flags_get_type (void); +#define GST_TYPE_TUNER_CHANNEL_FLAGS (gst_tuner_channel_flags_get_type()) +G_END_DECLS + +#endif /* __GST_INTERFACES_ENUM_TYPES_H__ */ + + + diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstapp.def b/gst-plugins-base-subtitles0.10/win32/common/libgstapp.def new file mode 100644 index 0000000..892d680 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstapp.def @@ -0,0 +1,34 @@ +EXPORTS + gst_app_buffer_get_type + gst_app_buffer_new + gst_app_sink_get_caps + gst_app_sink_get_drop + gst_app_sink_get_emit_signals + gst_app_sink_get_max_buffers + gst_app_sink_get_type + gst_app_sink_is_eos + gst_app_sink_pull_buffer + gst_app_sink_pull_buffer_list + gst_app_sink_pull_preroll + gst_app_sink_set_callbacks + gst_app_sink_set_caps + gst_app_sink_set_drop + gst_app_sink_set_emit_signals + gst_app_sink_set_max_buffers + gst_app_src_end_of_stream + gst_app_src_get_caps + gst_app_src_get_emit_signals + gst_app_src_get_latency + gst_app_src_get_max_bytes + gst_app_src_get_size + gst_app_src_get_stream_type + gst_app_src_get_type + gst_app_src_push_buffer + gst_app_src_set_callbacks + gst_app_src_set_caps + gst_app_src_set_emit_signals + gst_app_src_set_latency + gst_app_src_set_max_bytes + gst_app_src_set_size + gst_app_src_set_stream_type + gst_app_stream_type_get_type diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstaudio.def b/gst-plugins-base-subtitles0.10/win32/common/libgstaudio.def new file mode 100644 index 0000000..f234847 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstaudio.def @@ -0,0 +1,75 @@ +EXPORTS + gst_audio_buffer_clip + gst_audio_channel_position_get_type + gst_audio_check_channel_positions + gst_audio_clock_adjust + gst_audio_clock_get_time + gst_audio_clock_get_type + gst_audio_clock_invalidate + gst_audio_clock_new + gst_audio_clock_new_full + gst_audio_clock_reset + gst_audio_default_registry_mixer_filter + gst_audio_duration_from_pad_buffer + gst_audio_filter_class_add_pad_templates + gst_audio_filter_get_type + gst_audio_fixate_channel_positions + gst_audio_frame_byte_size + gst_audio_frame_length + gst_audio_get_channel_positions + gst_audio_is_buffer_framed + gst_audio_set_caps_channel_positions_list + gst_audio_set_channel_positions + gst_audio_set_structure_channel_positions_list + gst_audio_sink_get_type + gst_audio_src_get_type + gst_audio_structure_set_int + gst_base_audio_sink_create_ringbuffer + gst_base_audio_sink_get_drift_tolerance + gst_base_audio_sink_get_provide_clock + gst_base_audio_sink_get_slave_method + gst_base_audio_sink_get_type + gst_base_audio_sink_set_drift_tolerance + gst_base_audio_sink_set_provide_clock + gst_base_audio_sink_set_slave_method + gst_base_audio_sink_slave_method_get_type + gst_base_audio_src_create_ringbuffer + gst_base_audio_src_get_provide_clock + gst_base_audio_src_get_slave_method + gst_base_audio_src_get_type + gst_base_audio_src_set_provide_clock + gst_base_audio_src_set_slave_method + gst_base_audio_src_slave_method_get_type + gst_buffer_format_get_type + gst_buffer_format_type_get_type + gst_ring_buffer_acquire + gst_ring_buffer_activate + gst_ring_buffer_advance + gst_ring_buffer_clear + gst_ring_buffer_clear_all + gst_ring_buffer_close_device + gst_ring_buffer_commit + gst_ring_buffer_commit_full + gst_ring_buffer_convert + gst_ring_buffer_debug_spec_buff + gst_ring_buffer_debug_spec_caps + gst_ring_buffer_delay + gst_ring_buffer_device_is_open + gst_ring_buffer_get_type + gst_ring_buffer_is_acquired + gst_ring_buffer_is_active + gst_ring_buffer_may_start + gst_ring_buffer_open_device + gst_ring_buffer_parse_caps + gst_ring_buffer_pause + gst_ring_buffer_prepare_read + gst_ring_buffer_read + gst_ring_buffer_release + gst_ring_buffer_samples_done + gst_ring_buffer_seg_state_get_type + gst_ring_buffer_set_callback + gst_ring_buffer_set_flushing + gst_ring_buffer_set_sample + gst_ring_buffer_start + gst_ring_buffer_state_get_type + gst_ring_buffer_stop diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstcdda.def b/gst-plugins-base-subtitles0.10/win32/common/libgstcdda.def new file mode 100644 index 0000000..736f61c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstcdda.def @@ -0,0 +1,4 @@ +EXPORTS + gst_cdda_base_src_add_track + gst_cdda_base_src_get_type + gst_cdda_base_src_mode_get_type diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstinterfaces.def b/gst-plugins-base-subtitles0.10/win32/common/libgstinterfaces.def new file mode 100644 index 0000000..2f45637 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstinterfaces.def @@ -0,0 +1,122 @@ +EXPORTS + gst_color_balance_channel_get_type + gst_color_balance_get_balance_type + gst_color_balance_get_type + gst_color_balance_get_value + gst_color_balance_list_channels + gst_color_balance_set_value + gst_color_balance_type_get_type + gst_color_balance_value_changed + gst_mixer_flags_get_type + gst_mixer_get_mixer_flags + gst_mixer_get_mixer_type + gst_mixer_get_option + gst_mixer_get_type + gst_mixer_get_volume + gst_mixer_list_tracks + gst_mixer_message_get_type + gst_mixer_message_parse_mute_toggled + gst_mixer_message_parse_option_changed + gst_mixer_message_parse_options_list_changed + gst_mixer_message_parse_record_toggled + gst_mixer_message_parse_volume_changed + gst_mixer_message_type_get_type + gst_mixer_mixer_changed + gst_mixer_mute_toggled + gst_mixer_option_changed + gst_mixer_options_get_type + gst_mixer_options_get_values + gst_mixer_options_list_changed + gst_mixer_record_toggled + gst_mixer_set_mute + gst_mixer_set_option + gst_mixer_set_record + gst_mixer_set_volume + gst_mixer_track_flags_get_type + gst_mixer_track_get_type + gst_mixer_type_get_type + gst_mixer_volume_changed + gst_navigation_command_get_type + gst_navigation_event_get_type + gst_navigation_event_parse_command + gst_navigation_event_parse_key_event + gst_navigation_event_parse_mouse_button_event + gst_navigation_event_parse_mouse_move_event + gst_navigation_event_type_get_type + gst_navigation_get_type + gst_navigation_message_get_type + gst_navigation_message_new_angles_changed + gst_navigation_message_new_commands_changed + gst_navigation_message_new_mouse_over + gst_navigation_message_parse_angles_changed + gst_navigation_message_parse_mouse_over + gst_navigation_message_type_get_type + gst_navigation_query_get_type + gst_navigation_query_new_angles + gst_navigation_query_new_commands + gst_navigation_query_parse_angles + gst_navigation_query_parse_commands_length + gst_navigation_query_parse_commands_nth + gst_navigation_query_set_angles + gst_navigation_query_set_commands + gst_navigation_query_set_commandsv + gst_navigation_query_type_get_type + gst_navigation_send_command + gst_navigation_send_event + gst_navigation_send_key_event + gst_navigation_send_mouse_event + gst_property_probe_get_properties + gst_property_probe_get_property + gst_property_probe_get_type + gst_property_probe_get_values + gst_property_probe_get_values_name + gst_property_probe_needs_probe + gst_property_probe_needs_probe_name + gst_property_probe_probe_and_get_values + gst_property_probe_probe_and_get_values_name + gst_property_probe_probe_property + gst_property_probe_probe_property_name + gst_stream_volume_convert_volume + gst_stream_volume_format_get_type + gst_stream_volume_get_mute + gst_stream_volume_get_type + gst_stream_volume_get_volume + gst_stream_volume_set_mute + gst_stream_volume_set_volume + gst_tuner_channel_changed + gst_tuner_channel_flags_get_type + gst_tuner_channel_get_type + gst_tuner_find_channel_by_name + gst_tuner_find_norm_by_name + gst_tuner_frequency_changed + gst_tuner_get_channel + gst_tuner_get_frequency + gst_tuner_get_norm + gst_tuner_get_type + gst_tuner_list_channels + gst_tuner_list_norms + gst_tuner_norm_changed + gst_tuner_norm_get_type + gst_tuner_set_channel + gst_tuner_set_frequency + gst_tuner_set_norm + gst_tuner_signal_changed + gst_tuner_signal_strength + gst_video_orientation_get_hcenter + gst_video_orientation_get_hflip + gst_video_orientation_get_type + gst_video_orientation_get_vcenter + gst_video_orientation_get_vflip + gst_video_orientation_set_hcenter + gst_video_orientation_set_hflip + gst_video_orientation_set_vcenter + gst_video_orientation_set_vflip + gst_x_overlay_expose + gst_x_overlay_get_type + gst_x_overlay_got_window_handle + gst_x_overlay_got_xwindow_id + gst_x_overlay_handle_events + gst_x_overlay_prepare_xwindow_id + gst_x_overlay_set_render_rectangle + gst_x_overlay_set_window_handle + gst_x_overlay_set_xwindow_id diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstnetbuffer.def b/gst-plugins-base-subtitles0.10/win32/common/libgstnetbuffer.def new file mode 100644 index 0000000..bd6f8c7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstnetbuffer.def @@ -0,0 +1,12 @@ +EXPORTS + gst_netaddress_equal + gst_netaddress_get_address_bytes + gst_netaddress_get_ip4_address + gst_netaddress_get_ip6_address + gst_netaddress_get_net_type + gst_netaddress_set_address_bytes + gst_netaddress_set_ip4_address + gst_netaddress_set_ip6_address + gst_netaddress_to_string + gst_netbuffer_get_type + gst_netbuffer_new diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstpbutils.def b/gst-plugins-base-subtitles0.10/win32/common/libgstpbutils.def new file mode 100644 index 0000000..083e294 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstpbutils.def @@ -0,0 +1,137 @@ +EXPORTS + gst_codec_utils_aac_caps_set_level_and_profile + gst_codec_utils_aac_get_level + gst_codec_utils_aac_get_profile + gst_codec_utils_aac_get_sample_rate_from_index + gst_codec_utils_h264_caps_set_level_and_profile + gst_codec_utils_h264_get_level + gst_codec_utils_h264_get_profile + gst_codec_utils_mpeg4video_caps_set_level_and_profile + gst_codec_utils_mpeg4video_get_level + gst_codec_utils_mpeg4video_get_profile + gst_discoverer_audio_info_get_bitrate + gst_discoverer_audio_info_get_channels + gst_discoverer_audio_info_get_depth + gst_discoverer_audio_info_get_max_bitrate + gst_discoverer_audio_info_get_sample_rate + gst_discoverer_audio_info_get_type + gst_discoverer_container_info_get_streams + gst_discoverer_container_info_get_type + gst_discoverer_discover_uri + gst_discoverer_discover_uri_async + gst_discoverer_get_type + gst_discoverer_info_copy + gst_discoverer_info_get_audio_streams + gst_discoverer_info_get_container_streams + gst_discoverer_info_get_duration + gst_discoverer_info_get_misc + gst_discoverer_info_get_result + gst_discoverer_info_get_seekable + gst_discoverer_info_get_stream_info + gst_discoverer_info_get_stream_list + gst_discoverer_info_get_streams + gst_discoverer_info_get_tags + gst_discoverer_info_get_type + gst_discoverer_info_get_uri + gst_discoverer_info_get_video_streams + gst_discoverer_new + gst_discoverer_result_get_type + gst_discoverer_start + gst_discoverer_stop + gst_discoverer_stream_info_get_caps + gst_discoverer_stream_info_get_misc + gst_discoverer_stream_info_get_next + gst_discoverer_stream_info_get_previous + gst_discoverer_stream_info_get_stream_type_nick + gst_discoverer_stream_info_get_tags + gst_discoverer_stream_info_get_type + gst_discoverer_stream_info_list_free + gst_discoverer_video_info_get_bitrate + gst_discoverer_video_info_get_depth + gst_discoverer_video_info_get_framerate_denom + gst_discoverer_video_info_get_framerate_num + gst_discoverer_video_info_get_height + gst_discoverer_video_info_get_max_bitrate + gst_discoverer_video_info_get_par_denom + gst_discoverer_video_info_get_par_num + gst_discoverer_video_info_get_type + gst_discoverer_video_info_get_width + gst_discoverer_video_info_is_image + gst_discoverer_video_info_is_interlaced + gst_encoding_audio_profile_get_type + gst_encoding_audio_profile_new + gst_encoding_container_profile_add_profile + gst_encoding_container_profile_contains_profile + gst_encoding_container_profile_get_profiles + gst_encoding_container_profile_get_type + gst_encoding_container_profile_new + gst_encoding_list_all_targets + gst_encoding_list_available_categories + gst_encoding_profile_find + gst_encoding_profile_get_description + gst_encoding_profile_get_format + gst_encoding_profile_get_input_caps + gst_encoding_profile_get_name + gst_encoding_profile_get_presence + gst_encoding_profile_get_preset + gst_encoding_profile_get_restriction + gst_encoding_profile_get_type + gst_encoding_profile_get_type_nick + gst_encoding_profile_is_equal + gst_encoding_profile_set_description + gst_encoding_profile_set_format + gst_encoding_profile_set_name + gst_encoding_profile_set_presence + gst_encoding_profile_set_preset + gst_encoding_profile_set_restriction + gst_encoding_target_add_profile + gst_encoding_target_get_category + gst_encoding_target_get_description + gst_encoding_target_get_name + gst_encoding_target_get_profile + gst_encoding_target_get_profiles + gst_encoding_target_get_type + gst_encoding_target_load + gst_encoding_target_load_from_file + gst_encoding_target_new + gst_encoding_target_save + gst_encoding_target_save_to_file + gst_encoding_video_profile_get_pass + gst_encoding_video_profile_get_type + gst_encoding_video_profile_get_variableframerate + gst_encoding_video_profile_new + gst_encoding_video_profile_set_pass + gst_encoding_video_profile_set_variableframerate + gst_install_plugins_async + gst_install_plugins_context_free + gst_install_plugins_context_get_type + gst_install_plugins_context_new + gst_install_plugins_context_set_xid + gst_install_plugins_installation_in_progress + gst_install_plugins_return_get_name + gst_install_plugins_return_get_type + gst_install_plugins_supported + gst_install_plugins_sync + gst_is_missing_plugin_message + gst_missing_decoder_installer_detail_new + gst_missing_decoder_message_new + gst_missing_element_installer_detail_new + gst_missing_element_message_new + gst_missing_encoder_installer_detail_new + gst_missing_encoder_message_new + gst_missing_plugin_message_get_description + gst_missing_plugin_message_get_installer_detail + gst_missing_uri_sink_installer_detail_new + gst_missing_uri_sink_message_new + gst_missing_uri_source_installer_detail_new + gst_missing_uri_source_message_new + gst_pb_utils_add_codec_description_to_tag_list + gst_pb_utils_get_codec_description + gst_pb_utils_get_decoder_description + gst_pb_utils_get_element_description + gst_pb_utils_get_encoder_description + gst_pb_utils_get_sink_description + gst_pb_utils_get_source_description + gst_pb_utils_init + gst_plugins_base_version + gst_plugins_base_version_string diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstriff.def b/gst-plugins-base-subtitles0.10/win32/common/libgstriff.def new file mode 100644 index 0000000..e566107 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstriff.def @@ -0,0 +1,16 @@ +EXPORTS + gst_riff_create_audio_caps + gst_riff_create_audio_template_caps + gst_riff_create_iavs_caps + gst_riff_create_iavs_template_caps + gst_riff_create_video_caps + gst_riff_create_video_template_caps + gst_riff_init + gst_riff_parse_chunk + gst_riff_parse_file_header + gst_riff_parse_info + gst_riff_parse_strf_auds + gst_riff_parse_strf_iavs + gst_riff_parse_strf_vids + gst_riff_parse_strh + gst_riff_read_chunk diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstrtp.def b/gst-plugins-base-subtitles0.10/win32/common/libgstrtp.def new file mode 100644 index 0000000..41c9660 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstrtp.def @@ -0,0 +1,136 @@ +EXPORTS + gst_base_rtp_audio_payload_flush + gst_base_rtp_audio_payload_get_adapter + gst_base_rtp_audio_payload_get_type + gst_base_rtp_audio_payload_push + gst_base_rtp_audio_payload_set_frame_based + gst_base_rtp_audio_payload_set_frame_options + gst_base_rtp_audio_payload_set_sample_based + gst_base_rtp_audio_payload_set_sample_options + gst_base_rtp_audio_payload_set_samplebits_options + gst_base_rtp_depayload_get_type + gst_base_rtp_depayload_push + gst_base_rtp_depayload_push_list + gst_base_rtp_depayload_push_ts + gst_basertppayload_get_type + gst_basertppayload_is_filled + gst_basertppayload_push + gst_basertppayload_push_list + gst_basertppayload_set_options + gst_basertppayload_set_outcaps + gst_rtcp_buffer_add_packet + gst_rtcp_buffer_end + gst_rtcp_buffer_get_first_packet + gst_rtcp_buffer_get_packet_count + gst_rtcp_buffer_new + gst_rtcp_buffer_new_copy_data + gst_rtcp_buffer_new_take_data + gst_rtcp_buffer_validate + gst_rtcp_buffer_validate_data + gst_rtcp_ntp_to_unix + gst_rtcp_packet_add_rb + gst_rtcp_packet_bye_add_ssrc + gst_rtcp_packet_bye_add_ssrcs + gst_rtcp_packet_bye_get_nth_ssrc + gst_rtcp_packet_bye_get_reason + gst_rtcp_packet_bye_get_reason_len + gst_rtcp_packet_bye_get_ssrc_count + gst_rtcp_packet_bye_set_reason + gst_rtcp_packet_fb_get_fci + gst_rtcp_packet_fb_get_fci_length + gst_rtcp_packet_fb_get_media_ssrc + gst_rtcp_packet_fb_get_sender_ssrc + gst_rtcp_packet_fb_get_type + gst_rtcp_packet_fb_set_fci_length + gst_rtcp_packet_fb_set_media_ssrc + gst_rtcp_packet_fb_set_sender_ssrc + gst_rtcp_packet_fb_set_type + gst_rtcp_packet_get_count + gst_rtcp_packet_get_length + gst_rtcp_packet_get_padding + gst_rtcp_packet_get_rb + gst_rtcp_packet_get_rb_count + gst_rtcp_packet_get_type + gst_rtcp_packet_move_to_next + gst_rtcp_packet_remove + gst_rtcp_packet_rr_get_ssrc + gst_rtcp_packet_rr_set_ssrc + gst_rtcp_packet_sdes_add_entry + gst_rtcp_packet_sdes_add_item + gst_rtcp_packet_sdes_copy_entry + gst_rtcp_packet_sdes_first_entry + gst_rtcp_packet_sdes_first_item + gst_rtcp_packet_sdes_get_entry + gst_rtcp_packet_sdes_get_item_count + gst_rtcp_packet_sdes_get_ssrc + gst_rtcp_packet_sdes_next_entry + gst_rtcp_packet_sdes_next_item + gst_rtcp_packet_set_rb + gst_rtcp_packet_sr_get_sender_info + gst_rtcp_packet_sr_set_sender_info + gst_rtcp_sdes_name_to_type + gst_rtcp_sdes_type_to_name + gst_rtcp_unix_to_ntp + gst_rtp_buffer_add_extension_onebyte_header + gst_rtp_buffer_add_extension_twobytes_header + gst_rtp_buffer_allocate_data + gst_rtp_buffer_calc_header_len + gst_rtp_buffer_calc_packet_len + gst_rtp_buffer_calc_payload_len + gst_rtp_buffer_compare_seqnum + gst_rtp_buffer_default_clock_rate + gst_rtp_buffer_ext_timestamp + gst_rtp_buffer_get_csrc + gst_rtp_buffer_get_csrc_count + gst_rtp_buffer_get_extension + gst_rtp_buffer_get_extension_data + gst_rtp_buffer_get_extension_onebyte_header + gst_rtp_buffer_get_extension_twobytes_header + gst_rtp_buffer_get_header_len + gst_rtp_buffer_get_marker + gst_rtp_buffer_get_packet_len + gst_rtp_buffer_get_padding + gst_rtp_buffer_get_payload + gst_rtp_buffer_get_payload_buffer + gst_rtp_buffer_get_payload_len + gst_rtp_buffer_get_payload_subbuffer + gst_rtp_buffer_get_payload_type + gst_rtp_buffer_get_seq + gst_rtp_buffer_get_ssrc + gst_rtp_buffer_get_timestamp + gst_rtp_buffer_get_version + gst_rtp_buffer_list_add_extension_onebyte_header + gst_rtp_buffer_list_add_extension_twobytes_header + gst_rtp_buffer_list_from_buffer + gst_rtp_buffer_list_get_extension_onebyte_header + gst_rtp_buffer_list_get_extension_twobytes_header + gst_rtp_buffer_list_get_payload_len + gst_rtp_buffer_list_get_payload_type + gst_rtp_buffer_list_get_seq + gst_rtp_buffer_list_get_ssrc + gst_rtp_buffer_list_get_timestamp + gst_rtp_buffer_list_set_payload_type + gst_rtp_buffer_list_set_seq + gst_rtp_buffer_list_set_ssrc + gst_rtp_buffer_list_set_timestamp + gst_rtp_buffer_list_validate + gst_rtp_buffer_new_allocate + gst_rtp_buffer_new_allocate_len + gst_rtp_buffer_new_copy_data + gst_rtp_buffer_new_take_data + gst_rtp_buffer_pad_to + gst_rtp_buffer_set_csrc + gst_rtp_buffer_set_extension + gst_rtp_buffer_set_extension_data + gst_rtp_buffer_set_marker + gst_rtp_buffer_set_packet_len + gst_rtp_buffer_set_padding + gst_rtp_buffer_set_payload_type + gst_rtp_buffer_set_seq + gst_rtp_buffer_set_ssrc + gst_rtp_buffer_set_timestamp + gst_rtp_buffer_set_version + gst_rtp_buffer_validate + gst_rtp_buffer_validate_data + gst_rtp_payload_info_for_name + gst_rtp_payload_info_for_pt diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstrtsp.def b/gst-plugins-base-subtitles0.10/win32/common/libgstrtsp.def new file mode 100644 index 0000000..5327c5b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstrtsp.def @@ -0,0 +1,112 @@ +EXPORTS + gst_rtsp_auth_method_get_type + gst_rtsp_base64_decode_ip + gst_rtsp_base64_encode + gst_rtsp_connection_accept + gst_rtsp_connection_clear_auth_params + gst_rtsp_connection_close + gst_rtsp_connection_connect + gst_rtsp_connection_create + gst_rtsp_connection_create_from_fd + gst_rtsp_connection_do_tunnel + gst_rtsp_connection_flush + gst_rtsp_connection_free + gst_rtsp_connection_get_ip + gst_rtsp_connection_get_readfd + gst_rtsp_connection_get_tunnelid + gst_rtsp_connection_get_url + gst_rtsp_connection_get_writefd + gst_rtsp_connection_is_tunneled + gst_rtsp_connection_next_timeout + gst_rtsp_connection_poll + gst_rtsp_connection_read + gst_rtsp_connection_receive + gst_rtsp_connection_reset_timeout + gst_rtsp_connection_send + gst_rtsp_connection_set_auth + gst_rtsp_connection_set_auth_param + gst_rtsp_connection_set_http_mode + gst_rtsp_connection_set_ip + gst_rtsp_connection_set_proxy + gst_rtsp_connection_set_qos_dscp + gst_rtsp_connection_set_tunneled + gst_rtsp_connection_write + gst_rtsp_event_get_type + gst_rtsp_extension_after_send + gst_rtsp_extension_before_send + gst_rtsp_extension_configure_stream + gst_rtsp_extension_detect_server + gst_rtsp_extension_get_transports + gst_rtsp_extension_get_type + gst_rtsp_extension_parse_sdp + gst_rtsp_extension_receive_request + gst_rtsp_extension_send + gst_rtsp_extension_setup_media + gst_rtsp_extension_stream_select + gst_rtsp_family_get_type + gst_rtsp_find_header_field + gst_rtsp_find_method + gst_rtsp_header_allow_multiple + gst_rtsp_header_as_text + gst_rtsp_header_field_get_type + gst_rtsp_lower_trans_get_type + gst_rtsp_message_add_header + gst_rtsp_message_append_headers + gst_rtsp_message_dump + gst_rtsp_message_free + gst_rtsp_message_get_body + gst_rtsp_message_get_header + gst_rtsp_message_get_type + gst_rtsp_message_init + gst_rtsp_message_init_data + gst_rtsp_message_init_request + gst_rtsp_message_init_response + gst_rtsp_message_new + gst_rtsp_message_new_data + gst_rtsp_message_new_request + gst_rtsp_message_new_response + gst_rtsp_message_parse_data + gst_rtsp_message_parse_request + gst_rtsp_message_parse_response + gst_rtsp_message_remove_header + gst_rtsp_message_set_body + gst_rtsp_message_steal_body + gst_rtsp_message_take_body + gst_rtsp_message_take_header + gst_rtsp_message_unset + gst_rtsp_method_as_text + gst_rtsp_method_get_type + gst_rtsp_options_as_text + gst_rtsp_range_free + gst_rtsp_range_parse + gst_rtsp_range_to_string + gst_rtsp_result_get_type + gst_rtsp_state_get_type + gst_rtsp_status_as_text + gst_rtsp_status_code_get_type + gst_rtsp_strresult + gst_rtsp_transport_as_text + gst_rtsp_transport_free + gst_rtsp_transport_get_manager + gst_rtsp_transport_get_mime + gst_rtsp_transport_init + gst_rtsp_transport_new + gst_rtsp_transport_parse + gst_rtsp_url_copy + gst_rtsp_url_decode_path_components + gst_rtsp_url_free + gst_rtsp_url_get_port + gst_rtsp_url_get_request_uri + gst_rtsp_url_get_type + gst_rtsp_url_parse + gst_rtsp_url_set_port + gst_rtsp_version_as_text + gst_rtsp_version_get_type + gst_rtsp_watch_attach + gst_rtsp_watch_new + gst_rtsp_watch_queue_data + gst_rtsp_watch_queue_message + gst_rtsp_watch_reset + gst_rtsp_watch_send_message + gst_rtsp_watch_unref + gst_rtsp_watch_write_data diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstsdp.def b/gst-plugins-base-subtitles0.10/win32/common/libgstsdp.def new file mode 100644 index 0000000..186e4ff --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstsdp.def @@ -0,0 +1,78 @@ +EXPORTS + gst_sdp_address_is_multicast + gst_sdp_media_add_attribute + gst_sdp_media_add_bandwidth + gst_sdp_media_add_connection + gst_sdp_media_add_format + gst_sdp_media_as_text + gst_sdp_media_attributes_len + gst_sdp_media_bandwidths_len + gst_sdp_media_connections_len + gst_sdp_media_formats_len + gst_sdp_media_free + gst_sdp_media_get_attribute + gst_sdp_media_get_attribute_val + gst_sdp_media_get_attribute_val_n + gst_sdp_media_get_bandwidth + gst_sdp_media_get_connection + gst_sdp_media_get_format + gst_sdp_media_get_information + gst_sdp_media_get_key + gst_sdp_media_get_media + gst_sdp_media_get_num_ports + gst_sdp_media_get_port + gst_sdp_media_get_proto + gst_sdp_media_init + gst_sdp_media_new + gst_sdp_media_set_information + gst_sdp_media_set_key + gst_sdp_media_set_media + gst_sdp_media_set_port_info + gst_sdp_media_set_proto + gst_sdp_media_uninit + gst_sdp_message_add_attribute + gst_sdp_message_add_bandwidth + gst_sdp_message_add_email + gst_sdp_message_add_media + gst_sdp_message_add_phone + gst_sdp_message_add_time + gst_sdp_message_add_zone + gst_sdp_message_as_text + gst_sdp_message_as_uri + gst_sdp_message_attributes_len + gst_sdp_message_bandwidths_len + gst_sdp_message_dump + gst_sdp_message_emails_len + gst_sdp_message_free + gst_sdp_message_get_attribute + gst_sdp_message_get_attribute_val + gst_sdp_message_get_attribute_val_n + gst_sdp_message_get_bandwidth + gst_sdp_message_get_connection + gst_sdp_message_get_email + gst_sdp_message_get_information + gst_sdp_message_get_key + gst_sdp_message_get_media + gst_sdp_message_get_origin + gst_sdp_message_get_phone + gst_sdp_message_get_session_name + gst_sdp_message_get_time + gst_sdp_message_get_uri + gst_sdp_message_get_version + gst_sdp_message_get_zone + gst_sdp_message_init + gst_sdp_message_medias_len + gst_sdp_message_new + gst_sdp_message_parse_buffer + gst_sdp_message_parse_uri + gst_sdp_message_phones_len + gst_sdp_message_set_connection + gst_sdp_message_set_information + gst_sdp_message_set_key + gst_sdp_message_set_origin + gst_sdp_message_set_session_name + gst_sdp_message_set_uri + gst_sdp_message_set_version + gst_sdp_message_times_len + gst_sdp_message_uninit + gst_sdp_message_zones_len diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgsttag.def b/gst-plugins-base-subtitles0.10/win32/common/libgsttag.def new file mode 100644 index 0000000..bab6bbd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgsttag.def @@ -0,0 +1,41 @@ +EXPORTS + gst_tag_demux_get_type + gst_tag_demux_result_get_type + gst_tag_freeform_string_to_utf8 + gst_tag_from_id3_tag + gst_tag_from_id3_user_tag + gst_tag_from_vorbis_tag + gst_tag_get_language_code_iso_639_1 + gst_tag_get_language_code_iso_639_2B + gst_tag_get_language_code_iso_639_2T + gst_tag_get_language_codes + gst_tag_get_language_name + gst_tag_id3_genre_count + gst_tag_id3_genre_get + gst_tag_image_data_to_image_buffer + gst_tag_image_type_get_type + gst_tag_list_add_id3_image + gst_tag_list_from_exif_buffer + gst_tag_list_from_exif_buffer_with_tiff_header + gst_tag_list_from_vorbiscomment_buffer + gst_tag_list_from_xmp_buffer + gst_tag_list_new_from_id3v1 + gst_tag_list_to_exif_buffer + gst_tag_list_to_exif_buffer_with_tiff_header + gst_tag_list_to_vorbiscomment_buffer + gst_tag_list_to_xmp_buffer + gst_tag_list_to_xmp_buffer_full + gst_tag_parse_extended_comment + gst_tag_register_musicbrainz_tags + gst_tag_to_id3_tag + gst_tag_to_vorbis_comments + gst_tag_to_vorbis_tag + gst_tag_xmp_list_schemas + gst_tag_xmp_writer_add_all_schemas + gst_tag_xmp_writer_add_schema + gst_tag_xmp_writer_get_type + gst_tag_xmp_writer_has_schema + gst_tag_xmp_writer_remove_all_schemas + gst_tag_xmp_writer_remove_schema + gst_tag_xmp_writer_tag_list_to_xmp_buffer + gst_vorbis_tag_add diff --git a/gst-plugins-base-subtitles0.10/win32/common/libgstvideo.def b/gst-plugins-base-subtitles0.10/win32/common/libgstvideo.def new file mode 100644 index 0000000..0f09b80 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/libgstvideo.def @@ -0,0 +1,36 @@ +EXPORTS + gst_video_calculate_display_ratio + gst_video_convert_frame + gst_video_convert_frame_async + gst_video_event_new_still_frame + gst_video_event_parse_still_frame + gst_video_filter_get_type + gst_video_format_convert + gst_video_format_from_fourcc + gst_video_format_get_component_depth + gst_video_format_get_component_height + gst_video_format_get_component_offset + gst_video_format_get_component_width + gst_video_format_get_pixel_stride + gst_video_format_get_row_stride + gst_video_format_get_size + gst_video_format_get_type + gst_video_format_has_alpha + gst_video_format_is_gray + gst_video_format_is_rgb + gst_video_format_is_yuv + gst_video_format_new_caps + gst_video_format_new_caps_interlaced + gst_video_format_new_template_caps + gst_video_format_parse_caps + gst_video_format_parse_caps_interlaced + gst_video_format_to_fourcc + gst_video_frame_rate + gst_video_get_size + gst_video_parse_caps_chroma_site + gst_video_parse_caps_color_matrix + gst_video_parse_caps_framerate + gst_video_parse_caps_palette + gst_video_parse_caps_pixel_aspect_ratio + gst_video_sink_center_rect + gst_video_sink_get_type diff --git a/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.c new file mode 100644 index 0000000..d8a64d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.c @@ -0,0 +1,53 @@ + +/* Generated data (by glib-mkenums) */ + +#include "multichannel-enumtypes.h" + +#include "multichannel.h" + +/* enumerations from "multichannel.h" */ +GType +gst_audio_channel_position_get_type (void) +{ + static GType etype = 0; + + if (etype == 0) { + static const GEnumValue values[] = { + {GST_AUDIO_CHANNEL_POSITION_INVALID, "GST_AUDIO_CHANNEL_POSITION_INVALID", + "invalid"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, + "GST_AUDIO_CHANNEL_POSITION_FRONT_MONO", "front-mono"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT", "front-left"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT", "front-right"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + "GST_AUDIO_CHANNEL_POSITION_REAR_CENTER", "rear-center"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + "GST_AUDIO_CHANNEL_POSITION_REAR_LEFT", "rear-left"}, + {GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT", "rear-right"}, + {GST_AUDIO_CHANNEL_POSITION_LFE, "GST_AUDIO_CHANNEL_POSITION_LFE", "lfe"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER", "front-center"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER", + "front-left-of-center"}, + {GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + "GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER", + "front-right-of-center"}, + {GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + "GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT", "side-left"}, + {GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + "GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT", "side-right"}, + {GST_AUDIO_CHANNEL_POSITION_NONE, "GST_AUDIO_CHANNEL_POSITION_NONE", + "none"}, + {GST_AUDIO_CHANNEL_POSITION_NUM, "GST_AUDIO_CHANNEL_POSITION_NUM", "num"}, + {0, NULL, NULL} + }; + etype = g_enum_register_static ("GstAudioChannelPosition", values); + } + return etype; +} + +/* Generated data ends here */ diff --git a/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.h new file mode 100644 index 0000000..f3cc6bd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/multichannel-enumtypes.h @@ -0,0 +1,19 @@ + +/* Generated data (by glib-mkenums) */ + +#ifndef __GST_AUDIO_ENUM_TYPES_H__ +#define __GST_AUDIO_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "multichannel.h" */ +GType gst_audio_channel_position_get_type (void); +#define GST_TYPE_AUDIO_CHANNEL_POSITION (gst_audio_channel_position_get_type()) +G_END_DECLS + +#endif /* __GST_AUDIO_ENUM_TYPES_H__ */ + +/* Generated data ends here */ + diff --git a/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.c new file mode 100644 index 0000000..2652ec0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.c @@ -0,0 +1,70 @@ + + + +#include "pbutils-enumtypes.h" + +#include "pbutils.h" +#include "codec-utils.h" +#include "descriptions.h" +#include "encoding-profile.h" +#include "encoding-target.h" +#include "install-plugins.h" +#include "missing-plugins.h" +#include "gstdiscoverer.h" + +/* enumerations from "install-plugins.h" */ +GType +gst_install_plugins_return_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_INSTALL_PLUGINS_SUCCESS, "GST_INSTALL_PLUGINS_SUCCESS", "success"}, + {GST_INSTALL_PLUGINS_NOT_FOUND, "GST_INSTALL_PLUGINS_NOT_FOUND", + "not-found"}, + {GST_INSTALL_PLUGINS_ERROR, "GST_INSTALL_PLUGINS_ERROR", "error"}, + {GST_INSTALL_PLUGINS_PARTIAL_SUCCESS, + "GST_INSTALL_PLUGINS_PARTIAL_SUCCESS", "partial-success"}, + {GST_INSTALL_PLUGINS_USER_ABORT, "GST_INSTALL_PLUGINS_USER_ABORT", + "user-abort"}, + {GST_INSTALL_PLUGINS_CRASHED, "GST_INSTALL_PLUGINS_CRASHED", "crashed"}, + {GST_INSTALL_PLUGINS_INVALID, "GST_INSTALL_PLUGINS_INVALID", "invalid"}, + {GST_INSTALL_PLUGINS_STARTED_OK, "GST_INSTALL_PLUGINS_STARTED_OK", + "started-ok"}, + {GST_INSTALL_PLUGINS_INTERNAL_FAILURE, + "GST_INSTALL_PLUGINS_INTERNAL_FAILURE", "internal-failure"}, + {GST_INSTALL_PLUGINS_HELPER_MISSING, "GST_INSTALL_PLUGINS_HELPER_MISSING", + "helper-missing"}, + {GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS, + "GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS", "install-in-progress"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstInstallPluginsReturn", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} + +/* enumerations from "gstdiscoverer.h" */ +GType +gst_discoverer_result_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_DISCOVERER_OK, "GST_DISCOVERER_OK", "ok"}, + {GST_DISCOVERER_URI_INVALID, "GST_DISCOVERER_URI_INVALID", "uri-invalid"}, + {GST_DISCOVERER_ERROR, "GST_DISCOVERER_ERROR", "error"}, + {GST_DISCOVERER_TIMEOUT, "GST_DISCOVERER_TIMEOUT", "timeout"}, + {GST_DISCOVERER_BUSY, "GST_DISCOVERER_BUSY", "busy"}, + {GST_DISCOVERER_MISSING_PLUGINS, "GST_DISCOVERER_MISSING_PLUGINS", + "missing-plugins"}, + {0, NULL, NULL} + }; + GType g_define_type_id = + g_enum_register_static ("GstDiscovererResult", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} diff --git a/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.h new file mode 100644 index 0000000..30dadfd --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/pbutils-enumtypes.h @@ -0,0 +1,23 @@ + + + +#ifndef __PB_UTILS_ENUM_TYPES_H__ +#define __PB_UTILS_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "install-plugins.h" */ +GType gst_install_plugins_return_get_type (void); +#define GST_TYPE_INSTALL_PLUGINS_RETURN (gst_install_plugins_return_get_type()) + +/* enumerations from "gstdiscoverer.h" */ +GType gst_discoverer_result_get_type (void); +#define GST_TYPE_DISCOVERER_RESULT (gst_discoverer_result_get_type()) +G_END_DECLS + +#endif /* __PB_UTILS_ENUM_TYPES_H__ */ + + + diff --git a/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.c b/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.c new file mode 100644 index 0000000..caa2aef --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.c @@ -0,0 +1,65 @@ + + + +#include "video-enumtypes.h" + +#include "video.h" + +/* enumerations from "video.h" */ +GType +gst_video_format_get_type (void) +{ + static volatile gsize g_define_type_id__volatile = 0; + if (g_once_init_enter (&g_define_type_id__volatile)) { + static const GEnumValue values[] = { + {GST_VIDEO_FORMAT_UNKNOWN, "GST_VIDEO_FORMAT_UNKNOWN", "unknown"}, + {GST_VIDEO_FORMAT_I420, "GST_VIDEO_FORMAT_I420", "i420"}, + {GST_VIDEO_FORMAT_YV12, "GST_VIDEO_FORMAT_YV12", "yv12"}, + {GST_VIDEO_FORMAT_YUY2, "GST_VIDEO_FORMAT_YUY2", "yuy2"}, + {GST_VIDEO_FORMAT_UYVY, "GST_VIDEO_FORMAT_UYVY", "uyvy"}, + {GST_VIDEO_FORMAT_AYUV, "GST_VIDEO_FORMAT_AYUV", "ayuv"}, + {GST_VIDEO_FORMAT_RGBx, "GST_VIDEO_FORMAT_RGBx", "rgbx"}, + {GST_VIDEO_FORMAT_BGRx, "GST_VIDEO_FORMAT_BGRx", "bgrx"}, + {GST_VIDEO_FORMAT_xRGB, "GST_VIDEO_FORMAT_xRGB", "xrgb"}, + {GST_VIDEO_FORMAT_xBGR, "GST_VIDEO_FORMAT_xBGR", "xbgr"}, + {GST_VIDEO_FORMAT_RGBA, "GST_VIDEO_FORMAT_RGBA", "rgba"}, + {GST_VIDEO_FORMAT_BGRA, "GST_VIDEO_FORMAT_BGRA", "bgra"}, + {GST_VIDEO_FORMAT_ARGB, "GST_VIDEO_FORMAT_ARGB", "argb"}, + {GST_VIDEO_FORMAT_ABGR, "GST_VIDEO_FORMAT_ABGR", "abgr"}, + {GST_VIDEO_FORMAT_RGB, "GST_VIDEO_FORMAT_RGB", "rgb"}, + {GST_VIDEO_FORMAT_BGR, "GST_VIDEO_FORMAT_BGR", "bgr"}, + {GST_VIDEO_FORMAT_Y41B, "GST_VIDEO_FORMAT_Y41B", "y41b"}, + {GST_VIDEO_FORMAT_Y42B, "GST_VIDEO_FORMAT_Y42B", "y42b"}, + {GST_VIDEO_FORMAT_YVYU, "GST_VIDEO_FORMAT_YVYU", "yvyu"}, + {GST_VIDEO_FORMAT_Y444, "GST_VIDEO_FORMAT_Y444", "y444"}, + {GST_VIDEO_FORMAT_v210, "GST_VIDEO_FORMAT_v210", "v210"}, + {GST_VIDEO_FORMAT_v216, "GST_VIDEO_FORMAT_v216", "v216"}, + {GST_VIDEO_FORMAT_NV12, "GST_VIDEO_FORMAT_NV12", "nv12"}, + {GST_VIDEO_FORMAT_NV21, "GST_VIDEO_FORMAT_NV21", "nv21"}, + {GST_VIDEO_FORMAT_GRAY8, "GST_VIDEO_FORMAT_GRAY8", "gray8"}, + {GST_VIDEO_FORMAT_GRAY16_BE, "GST_VIDEO_FORMAT_GRAY16_BE", "gray16-be"}, + {GST_VIDEO_FORMAT_GRAY16_LE, "GST_VIDEO_FORMAT_GRAY16_LE", "gray16-le"}, + {GST_VIDEO_FORMAT_v308, "GST_VIDEO_FORMAT_v308", "v308"}, + {GST_VIDEO_FORMAT_Y800, "GST_VIDEO_FORMAT_Y800", "y800"}, + {GST_VIDEO_FORMAT_Y16, "GST_VIDEO_FORMAT_Y16", "y16"}, + {GST_VIDEO_FORMAT_RGB16, "GST_VIDEO_FORMAT_RGB16", "rgb16"}, + {GST_VIDEO_FORMAT_BGR16, "GST_VIDEO_FORMAT_BGR16", "bgr16"}, + {GST_VIDEO_FORMAT_RGB15, "GST_VIDEO_FORMAT_RGB15", "rgb15"}, + {GST_VIDEO_FORMAT_BGR15, "GST_VIDEO_FORMAT_BGR15", "bgr15"}, + {GST_VIDEO_FORMAT_UYVP, "GST_VIDEO_FORMAT_UYVP", "uyvp"}, + {GST_VIDEO_FORMAT_A420, "GST_VIDEO_FORMAT_A420", "a420"}, + {GST_VIDEO_FORMAT_RGB8_PALETTED, "GST_VIDEO_FORMAT_RGB8_PALETTED", + "rgb8-paletted"}, + {GST_VIDEO_FORMAT_YUV9, "GST_VIDEO_FORMAT_YUV9", "yuv9"}, + {GST_VIDEO_FORMAT_YVU9, "GST_VIDEO_FORMAT_YVU9", "yvu9"}, + {GST_VIDEO_FORMAT_IYU1, "GST_VIDEO_FORMAT_IYU1", "iyu1"}, + {GST_VIDEO_FORMAT_ARGB64, "GST_VIDEO_FORMAT_ARGB64", "argb64"}, + {GST_VIDEO_FORMAT_AYUV64, "GST_VIDEO_FORMAT_AYUV64", "ayuv64"}, + {GST_VIDEO_FORMAT_r210, "GST_VIDEO_FORMAT_r210", "r210"}, + {0, NULL, NULL} + }; + GType g_define_type_id = g_enum_register_static ("GstVideoFormat", values); + g_once_init_leave (&g_define_type_id__volatile, g_define_type_id); + } + return g_define_type_id__volatile; +} diff --git a/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.h b/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.h new file mode 100644 index 0000000..a247abc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/common/video-enumtypes.h @@ -0,0 +1,19 @@ + + + +#ifndef __GST_VIDEO_ENUM_TYPES_H__ +#define __GST_VIDEO_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/* enumerations from "video.h" */ +GType gst_video_format_get_type (void); +#define GST_TYPE_VIDEO_FORMAT (gst_video_format_get_type()) +G_END_DECLS + +#endif /* __GST_VIDEO_ENUM_TYPES_H__ */ + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/grammar.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/grammar.dsp new file mode 100644 index 0000000..4d67df1 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/grammar.dsp @@ -0,0 +1,424 @@ +# Microsoft Developer Studio Project File - Name="grammar" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Generic Project" 0x010a + +CFG=grammar - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "grammar.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "grammar.mak" CFG="grammar - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "grammar - Win32 Release" (based on "Win32 (x86) Generic Project") +!MESSAGE "grammar - Win32 Debug" (based on "Win32 (x86) Generic Project") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +MTL=midl.exe + +!IF "$(CFG)" == "grammar - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" + +!ENDIF + +# Begin Target + +# Name "grammar - Win32 Release" +# Name "grammar - Win32 Debug" +# Begin Source File + +SOURCE="..\..\gst\playback\gstplay-marshal.list" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\..\gst\playback\gstplay-marshal.list" + +BuildCmds= \ + echo #include "glib-object.h" > gstplay-marshal.c.tmp \ + echo #include "gstplay-marshal.h" >> gstplay-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_play_marshal ..\..\gst\playback\gstplay-marshal.list >> gstplay-marshal.c.tmp \ + move gstplay-marshal.c.tmp ..\..\gst\playback\gstplay-marshal.c \ + echo #include "gst/gstconfig.h" > gstplay-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_play_marshal ..\..\gst\playback\gstplay-marshal.list >> gstplay-marshal.h.tmp \ + move gstplay-marshal.h.tmp ..\..\gst\playback\gstplay-marshal.h + +"..\..\gst\playback\gstplay-marshal.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst\playback\gstplay-marshal.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\..\gst\playback\gstplay-marshal.list" + +BuildCmds= \ + echo #include "glib-object.h" > gstplay-marshal.c.tmp \ + echo #include "gstplay-marshal.h" >> gstplay-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_play_marshal ..\..\gst\playback\gstplay-marshal.list >> gstplay-marshal.c.tmp \ + move gstplay-marshal.c.tmp ..\..\gst\playback\gstplay-marshal.c \ + echo #include "gst/gstconfig.h" > gstplay-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_play_marshal ..\..\gst\playback\gstplay-marshal.list >> gstplay-marshal.h.tmp \ + move gstplay-marshal.h.tmp ..\..\gst\playback\gstplay-marshal.h + +"..\..\gst\playback\gstplay-marshal.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst\playback\gstplay-marshal.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\..\gst\tcp\gsttcp-marshal.list" +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\..\gst\tcp\gsttcp-marshal.list" + +BuildCmds= \ + echo #include "glib-object.h" > gsttcp-marshal.c.tmp \ + echo #include "gsttcp-marshal.h" >> gsttcp-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_tcp_marshal ..\..\gst\tcp\gsttcp-marshal.list >> gsttcp-marshal.c.tmp \ + move gsttcp-marshal.c.tmp ..\..\gst\tcp\gsttcp-marshal.c \ + echo #include "gst/gstconfig.h" > gsttcp-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_tcp_marshal ..\..\gst\tcp\gsttcp-marshal.list >> gsttcp-marshal.h.tmp \ + move gsttcp-marshal.h.tmp ..\..\gst\tcp\gsttcp-marshal.h + + +"..\..\gst\tcp\gsttcp-marshal.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst\tcp\gsttcp-marshal.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\..\gst\tcp\gsttcp-marshal.list" + +BuildCmds= \ + echo #include "glib-object.h" > gsttcp-marshal.c.tmp \ + echo #include "gsttcp-marshal.h" >> gsttcp-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_tcp_marshal ..\..\gst\tcp\gsttcp-marshal.list >> gsttcp-marshal.c.tmp \ + move gsttcp-marshal.c.tmp ..\..\gst\tcp\gsttcp-marshal.c \ + echo #include "gst/gstconfig.h" > gsttcp-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_tcp_marshal ..\..\gst\tcp\gsttcp-marshal.list >> gsttcp-marshal.h.tmp \ + move gsttcp-marshal.h.tmp ..\..\gst\tcp\gsttcp-marshal.h + + +"..\..\gst\tcp\gsttcp-marshal.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst\tcp\gsttcp-marshal.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\common\interfaces-enumtypes.c" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\common\interfaces-enumtypes.c" + +BuildCmds= \ + copy ..\common\interfaces-enumtypes.h ..\..\gst-libs\gst\interfaces \ + copy ..\common\interfaces-enumtypes.c ..\..\gst-libs\gst\interfaces + + +"..\..\gst-libs\gst\interfaces\interfaces-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\interfaces\interfaces-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\common\interfaces-enumtypes.c" + +BuildCmds= \ + copy ..\common\interfaces-enumtypes.h ..\..\gst-libs\gst\interfaces \ + copy ..\common\interfaces-enumtypes.c ..\..\gst-libs\gst\interfaces + + +"..\..\gst-libs\gst\interfaces\interfaces-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\interfaces\interfaces-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\interfaces-marshal.list" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\..\gst-libs\gst\interfaces\interfaces-marshal.list" + +BuildCmds= \ + echo #include "interfaces-marshal.h" > interfaces-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_interfaces_marshal ..\..\gst-libs\gst\interfaces\interfaces-marshal.list >> interfaces-marshal.c.tmp \ + move interfaces-marshal.c.tmp ..\..\gst-libs\gst\interfaces\interfaces-marshal.c \ + echo #include "gst/gstconfig.h" > interfaces-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_interfaces_marshal ..\..\gst-libs\gst\interfaces\interfaces-marshal.list >> interfaces-marshal.h.tmp \ + move interfaces-marshal.h.tmp ..\..\gst-libs\gst\interfaces\interfaces-marshal.h + + +"..\..\gst-libs\gst\interfaces\interfaces-marshal.list.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\interfaces\interfaces-marshal.list.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\..\gst-libs\gst\interfaces\interfaces-marshal.list" + +BuildCmds= \ + echo #include "interfaces-marshal.h" > interfaces-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_interfaces_marshal ..\..\gst-libs\gst\interfaces\interfaces-marshal.list >> interfaces-marshal.c.tmp \ + move interfaces-marshal.c.tmp ..\..\gst-libs\gst\interfaces\interfaces-marshal.c \ + echo #include "gst/gstconfig.h" > interfaces-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_interfaces_marshal ..\..\gst-libs\gst\interfaces\interfaces-marshal.list >> interfaces-marshal.h.tmp \ + move interfaces-marshal.h.tmp ..\..\gst-libs\gst\interfaces\interfaces-marshal.h + + +"..\..\gst-libs\gst\interfaces\interfaces-marshal.list.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\interfaces\interfaces-marshal.list.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\common\audio-enumtypes.c" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\common\audio-enumtypes.c" + +BuildCmds= \ + copy ..\common\audio-enumtypes.h ..\..\gst-libs\gst\audio \ + copy ..\common\audio-enumtypes.c ..\..\gst-libs\gst\audio + + +"..\..\gst-libs\gst\audio\audio-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\audio\audio-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\common\audio-enumtypes.c" + +BuildCmds= \ + copy ..\common\audio-enumtypes.h ..\..\gst-libs\gst\audio \ + copy ..\common\audio-enumtypes.c ..\..\gst-libs\gst\audio + + +"..\..\gst-libs\gst\audio\audio-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\audio\audio-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\rtsp-marshal.list" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\..\gst-libs\gst\rtsp\rtsp-marshal.list" + +BuildCmds= \ + echo #include "rtsp-marshal.h" > rtsp-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_rtsp_marshal ..\..\gst-libs\gst\rtsp\rtsp-marshal.list >> rtsp-marshal.c.tmp \ + move rtsp-marshal.c.tmp ..\..\gst-libs\gst\rtsp\rtsp-marshal.c \ + echo #include "gst/gstconfig.h" > rtsp-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_rtsp_marshal ..\..\gst-libs\gst\rtsp\rtsp-marshal.list >> rtsp-marshal.h.tmp \ + move rtsp-marshal.h.tmp ..\..\gst-libs\gst\rtsp\rtsp-marshal.h + + +"..\..\gst-libs\gst\rtsp\rtsp-marshal.list.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\rtsp\rtsp-marshal.list.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\..\gst-libs\gst\rtsp\rtsp-marshal.list" + +BuildCmds= \ + echo #include "rtsp-marshal.h" > rtsp-marshal.c.tmp \ + glib-genmarshal --body --prefix=gst_rtsp_marshal ..\..\gst-libs\gst\rtsp\rtsp-marshal.list >> rtsp-marshal.c.tmp \ + move rtsp-marshal.c.tmp ..\..\gst-libs\gst\rtsp\rtsp-marshal.c \ + echo #include "gst/gstconfig.h" > rtsp-marshal.h.tmp \ + glib-genmarshal --header --prefix=gst_rtsp_marshal ..\..\gst-libs\gst\rtsp\rtsp-marshal.list >> rtsp-marshal.h.tmp \ + move rtsp-marshal.h.tmp ..\..\gst-libs\gst\rtsp\rtsp-marshal.h + + +"..\..\gst-libs\gst\rtsp\rtsp-marshal.list.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +..\..\gst-libs\gst\rtsp\rtsp-marshal.list.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\common\gstrtsp-enumtypes.c" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\common\gstrtsp-enumtypes.c" + +BuildCmds= \ + copy ..\common\gstrtsp-enumtypes.h ..\..\gst-libs\gst\rtsp \ + copy ..\common\gstrtsp-enumtypes.c ..\..\gst-libs\gst\rtsp + + +"..\..\gst-libs\gst\rtsp\gstrtsp-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\rtsp\gstrtsp-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\common\gstrtsp-enumtypes.c" + +BuildCmds= \ + copy ..\common\gstrtsp-enumtypes.h ..\..\gst-libs\gst\rtsp \ + copy ..\common\gstrtsp-enumtypes.c ..\..\gst-libs\gst\rtsp + + +"..\..\gst-libs\gst\rtsp\gstrtsp-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\rtsp\gstrtsp-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE="..\common\pbutils-enumtypes.c" + +!IF "$(CFG)" == "grammar - Win32 Release" + +# Begin Custom Build +InputPath="..\common\pbutils-enumtypes.c" + +BuildCmds= \ + copy ..\common\pbutils-enumtypes.h ..\..\gst-libs\gst\pbutils \ + copy ..\common\pbutils-enumtypes.c ..\..\gst-libs\gst\pbutils + + +"..\..\gst-libs\gst\pbutils\pbutils-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\pbutils\pbutils-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ELSEIF "$(CFG)" == "grammar - Win32 Debug" + +# Begin Custom Build +InputPath="..\common\pbutils-enumtypes.c" + +BuildCmds= \ + copy ..\common\pbutils-enumtypes.h ..\..\gst-libs\gst\pbutils \ + copy ..\common\pbutils-enumtypes.c ..\..\gst-libs\gst\pbutils + + +"..\..\gst-libs\gst\pbutils\pbutils-enumtypes.c" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"..\..\gst-libs\gst\pbutils\pbutils-enumtypes.h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/gst_plugins_base.dsw b/gst-plugins-base-subtitles0.10/win32/vs6/gst_plugins_base.dsw new file mode 100644 index 0000000..ab6bfad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/gst_plugins_base.dsw @@ -0,0 +1,440 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "grammar"=".\grammar.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstadder"=".\libgstadder.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstaudio"=".\libgstaudio.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name grammar + End Project Dependency + Begin Project Dependency + Project_Dep_Name libgstinterfaces + End Project Dependency +}}} + +############################################################################### + +Project: "libgstaudioconvert"=".\libgstaudioconvert.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstaudiorate"=".\libgstaudiorate.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstaudioresample"=".\libgstaudioresample.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstaudiotestsrc"=".\libgstaudiotestsrc.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstcdda"=".\libgstcdda.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libgsttag + End Project Dependency +}}} + +############################################################################### + +Project: "libgstdecodebin"=".\libgstdecodebin.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name grammar + End Project Dependency + Begin Project Dependency + Project_Dep_Name libgstpbutils + End Project Dependency +}}} + +############################################################################### + +Project: "libgstdecodebin2"=".\libgstdecodebin2.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstffmpegcolorspace"=".\libgstffmpegcolorspace.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstfft"=".\libgstfft.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstgdp"=".\libgstgdp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstinterfaces"=".\libgstinterfaces.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name grammar + End Project Dependency +}}} + +############################################################################### + +Project: "libgstnetbuffer"=".\libgstnetbuffer.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstogg"=".\libgstogg.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libgstriff + End Project Dependency +}}} + +############################################################################### + +Project: "libgstpbutils"=".\libgstpbutils.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstplaybin"=".\libgstplaybin.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name grammar + End Project Dependency + Begin Project Dependency + Project_Dep_Name libgstpbutils + End Project Dependency +}}} + +############################################################################### + +Project: "libgstriff"=".\libgstriff.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstrtp"=".\libgstrtp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstrtsp"=".\libgstrtsp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name grammar + End Project Dependency +}}} + +############################################################################### + +Project: "libgstsdp"=".\libgstsdp.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstsubparse"=".\libgstsubparse.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgsttag"=".\libgsttag.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgsttheora"=".\libgsttheora.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libgsttag + End Project Dependency +}}} + +############################################################################### + +Project: "libgsttypefindfunctions"=".\libgsttypefindfunctions.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvideo"=".\libgstvideo.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvideorate"=".\libgstvideorate.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvideoscale"=".\libgstvideoscale.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvideotestsrc"=".\libgstvideotestsrc.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvolume"=".\libgstvolume.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "libgstvorbis"=".\libgstvorbis.dsp" - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name libgstaudio + End Project Dependency + Begin Project Dependency + Project_Dep_Name libgsttag + End Project Dependency +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstadder.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstadder.dsp new file mode 100644 index 0000000..3616c30 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstadder.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="libgstadder" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstadder - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstadder.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstadder.mak" CFG="libgstadder - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstadder - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstadder - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstadder - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTADDER_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTADDER_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstadder.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstadder - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTADDER_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTADDER_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstadder.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstadder - Win32 Release" +# Name "libgstadder - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\adder\gstadder.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\adder\gstadder.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudio.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudio.dsp new file mode 100644 index 0000000..bfd0a8a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudio.dsp @@ -0,0 +1,207 @@ +# Microsoft Developer Studio Project File - Name="libgstaudio" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudio - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudio.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudio.mak" CFG="libgstaudio - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudio - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudio - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudio - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIO_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "./" /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/audio" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIO_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib /nologo /dll /machine:I386 /out:"Release/libgstaudio-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudio-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudio - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIO_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/audio" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIO_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstinterfaces-0.10.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstaudio-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudio-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudio - Win32 Release" +# Name "libgstaudio - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\audio.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudioclock.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiofilter.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiofiltertemplate.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiosink.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiosrc.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstbaseaudiosink.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstbaseaudiosrc.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstringbuffer.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstaudio.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\mixerutils.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\audio-enumtypes.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\multichannel.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\audio.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudioclock.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiofilter.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiosink.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstaudiosrc.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstbaseaudiosink.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstbaseaudiosrc.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\gstringbuffer.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\audio-enumtypes.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\audio\multichannel.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioconvert.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioconvert.dsp new file mode 100644 index 0000000..132c297 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioconvert.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="libgstaudioconvert" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudioconvert - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioconvert.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioconvert.mak" CFG="libgstaudioconvert - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudioconvert - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudioconvert - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudioconvert - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOCONVERT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOCONVERT_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstaudio-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudioconvert.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudioconvert - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOCONVERT_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOCONVERT_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstaudio-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudioconvert.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudioconvert - Win32 Release" +# Name "libgstaudioconvert - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\audioconvert\audioconvert.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\gstaudioconvert.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\gstaudioquantize.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\gstchannelmix.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\plugin.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\audioconvert\audioconvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\gstaudioconvert.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\gstchannelmix.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioconvert\plugin.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiorate.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiorate.dsp new file mode 100644 index 0000000..4487b11 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiorate.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="libgstaudiorate" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudiorate - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudiorate.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudiorate.mak" CFG="libgstaudiorate - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudiorate - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudiorate - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudiorate - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORATE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORATE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudiorate.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudiorate - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORATE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORATE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudiorate.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudiorate - Win32 Release" +# Name "libgstaudiorate - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\audiorate\gstaudiorate.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioresample.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioresample.dsp new file mode 100644 index 0000000..a1ca5b0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioresample.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="libgstaudioresample" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudioresample - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioresample.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioresample.mak" CFG="libgstaudioresample - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudioresample - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudioresample - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudioresample - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORESAMPLE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst/audioresample" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORESAMPLE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib liboil-0.3-0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudioresample.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudioresample - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORESAMPLE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst/audioresample" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIORESAMPLE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib liboil-0.3-0.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudioresample.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudioresample - Win32 Release" +# Name "libgstaudioresample - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\audioresample\buffer.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\functable.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\gstaudioresample.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\resample.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\resample_chunk.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\resample_functable.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\resample_ref.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\audioresample\buffer.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\debug.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\functable.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\gstaudioresample.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioresample\resample.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioscale.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioscale.dsp new file mode 100644 index 0000000..f6148cc --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudioscale.dsp @@ -0,0 +1,125 @@ +# Microsoft Developer Studio Project File - Name="libgstaudioscale" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudioscale - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioscale.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudioscale.mak" CFG="libgstaudioscale - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudioscale - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudioscale - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudioscale - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOSCALE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOSCALE_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudioscale.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudioscale - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOSCALE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOSCALE_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudioscale.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudioscale - Win32 Release" +# Name "libgstaudioscale - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\audioscale\gstaudioscale.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\audioscale\gstaudioscale.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\audioscale\private.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiotestsrc.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiotestsrc.dsp new file mode 100644 index 0000000..ed291b3 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstaudiotestsrc.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="libgstaudiotestsrc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstaudiotestsrc - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstaudiotestsrc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstaudiotestsrc.mak" CFG="libgstaudiotestsrc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstaudiotestsrc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstaudiotestsrc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstaudiotestsrc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOTESTSRC_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOTESTSRC_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstcontroller-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstaudiotestsrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstaudiotestsrc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOTESTSRC_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTAUDIOTESTSRC_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgstcontroller-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./" +# Begin Special Build Tool +TargetPath=.\Debug\libgstaudiotestsrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstaudiotestsrc - Win32 Release" +# Name "libgstaudiotestsrc - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\audiotestsrc\gstaudiotestsrc.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\audiotestsrc\gstaudiotestsrc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstcdda.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstcdda.dsp new file mode 100644 index 0000000..744b444 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstcdda.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="libgstcdda" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstcdda - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstcdda.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstcdda.mak" CFG="libgstcdda - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstcdda - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstcdda - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstcdda - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTCDDA_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTCDDA_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib /nologo /dll /machine:I386 /out:"Release/libgstcdda-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstcdda-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstcdda - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTCDDA_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTCDDA_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstcdda-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstcdda-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstcdda - Win32 Release" +# Name "libgstcdda - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\base64.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\gstcddabasesrc.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstcdda.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\sha1.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\base64.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\gstcddabasesrc.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\cdda\sha1.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin.dsp new file mode 100644 index 0000000..bccea4f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="libgstdecodebin" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstdecodebin - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstdecodebin.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstdecodebin.mak" CFG="libgstdecodebin - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstdecodebin - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstdecodebin - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstdecodebin - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstdecodebin.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstdecodebin - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstdecodebin.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstdecodebin - Win32 Release" +# Name "libgstdecodebin - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\playback\gstdecodebin.c +# End Source File +# Begin Source File + +SOURCE="..\..\gst\playback\gstplay-marshal.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin2.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin2.dsp new file mode 100644 index 0000000..72b2d17 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdecodebin2.dsp @@ -0,0 +1,135 @@ +# Microsoft Developer Studio Project File - Name="libgstdecodebin2" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstdecodebin2 - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstdecodebin2.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstdecodebin2.mak" CFG="libgstdecodebin2 - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstdecodebin2 - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstdecodebin2 - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstdecodebin2 - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN2_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN2_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstdecodebin2.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstdecodebin2 - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN2_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDECODEBIN2_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstdecodebin2.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstdecodebin2 - Win32 Release" +# Name "libgstdecodebin2 - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\playback\gstdecodebin2.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstfactorylists.c +# End Source File +# Begin Source File + +SOURCE="..\..\gst\playback\gstplay-enum.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst\playback\gstplay-marshal.c" +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gsturidecodebin.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstdirectsound.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdirectsound.dsp new file mode 100644 index 0000000..c205b32 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstdirectsound.dsp @@ -0,0 +1,125 @@ +# Microsoft Developer Studio Project File - Name="libgstdirectsound" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstdirectsound - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstdirectsound.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstdirectsound.mak" CFG="libgstdirectsound - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstdirectsound - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstdirectsound - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstdirectsound - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttagedit-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gobject-2.0.lib vorbis.lib ogg.lib dsound.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstdirectsound.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstdirectsound - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTDIRECTSOUND_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttagedit-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gobject-2.0.lib vorbis.lib ogg.lib dsound.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstdirectsound.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstdirectsound - Win32 Release" +# Name "libgstdirectsound - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\libgstdirectsound\gstdirectsoundplugin.c +# End Source File +# Begin Source File + +SOURCE=..\libgstdirectsound\gstdirectsoundsink.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\libgstdirectsound\gstdirectsoundsink.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstffmpegcolorspace.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstffmpegcolorspace.dsp new file mode 100644 index 0000000..ad7cd40 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstffmpegcolorspace.dsp @@ -0,0 +1,163 @@ +# Microsoft Developer Studio Project File - Name="libgstffmpegcolorspace" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstffmpegcolorspace - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstffmpegcolorspace.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstffmpegcolorspace.mak" CFG="libgstffmpegcolorspace - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstffmpegcolorspace - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstffmpegcolorspace - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstffmpegcolorspace - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFMPEGCOLORSPACE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst/ffmpegcolorspace" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFMPEGCOLORSPACE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstffmpegcolorspace.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstffmpegcolorspace - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFMPEGCOLORSPACE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst/ffmpegcolorspace" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFMPEGCOLORSPACE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstffmpegcolorspace.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstffmpegcolorspace - Win32 Release" +# Name "libgstffmpegcolorspace - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\dsputil.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\gstffmpeg.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\gstffmpegcodecmap.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\gstffmpegcolorspace.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\imgconvert.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\mem.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\utils.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\avcodec.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\dsputil.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\gstffmpegcodecmap.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\gstffmpegcolorspace.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\imgconvert_template.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstfft.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstfft.dsp new file mode 100644 index 0000000..82e213f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstfft.dsp @@ -0,0 +1,167 @@ +# Microsoft Developer Studio Project File - Name="libgstfft" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstfft - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstfft.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstfft.mak" CFG="libgstfft - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstfft - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstfft - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstfft - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/interfaces" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFT_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstfft-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstfft-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstfft - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFT_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/interfaces" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTFFT_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstfft-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstfft-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstfft - Win32 Release" +# Name "libgstfft - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\gstfft.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\gstfftf32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\gstfftf64.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\gstffts16.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\gstffts32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fft_f32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fft_f64.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fft_s16.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fft_s32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fftr_f32.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fftr_f64.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fftr_s16.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\fft\kiss_fftr_s32.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstgdp.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstgdp.dsp new file mode 100644 index 0000000..fb375ee --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstgdp.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="libgstgdp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstgdp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstgdp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstgdp.mak" CFG="libgstgdp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstgdp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstgdp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstgdp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTGDP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTGDP_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstcontroller-0.10.lib libgstinterfaces-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstdataprotocol-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstgdp.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstgdp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTGDP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTGDP_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstcontroller-0.10.lib libgstinterfaces-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstdataprotocol-0.10.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstgdp.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstgdp - Win32 Release" +# Name "libgstgdp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\gdp\gstgdp.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\gdp\gstgdpdepay.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\gdp\gstgdppay.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstinterfaces.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstinterfaces.dsp new file mode 100644 index 0000000..5b5596a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstinterfaces.dsp @@ -0,0 +1,223 @@ +# Microsoft Developer Studio Project File - Name="libgstinterfaces" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstinterfaces - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstinterfaces.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstinterfaces.mak" CFG="libgstinterfaces - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstinterfaces - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstinterfaces - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstinterfaces - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTINTERFACES_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/interfaces" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTINTERFACES_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstinterfaces-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstinterfaces-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstinterfaces - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTINTERFACES_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/interfaces" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTINTERFACES_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstinterfaces-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstinterfaces-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstinterfaces - Win32 Release" +# Name "libgstinterfaces - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\colorbalance.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\colorbalancechannel.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\interfaces-enumtypes.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\interfaces-marshal.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstinterfaces.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixer.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixeroptions.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixertrack.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\navigation.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\propertyprobe.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tuner.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tunerchannel.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tunernorm.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\videoorientation.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\xoverlay.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\colorbalance.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\colorbalancechannel.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\interfaces.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixer.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixeroptions.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\mixertrack.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\navigation.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\propertyprobe.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tuner.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tunerchannel.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\tunernorm.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\interfaces\xoverlay.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstnetbuffer.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstnetbuffer.dsp new file mode 100644 index 0000000..3111069 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstnetbuffer.dsp @@ -0,0 +1,127 @@ +# Microsoft Developer Studio Project File - Name="libgstnetbuffer" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstnetbuffer - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstnetbuffer.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstnetbuffer.mak" CFG="libgstnetbuffer - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstnetbuffer - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstnetbuffer - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstnetbuffer - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTNETBUFFER_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTNETBUFFER_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstnetbuffer-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstnetbuffer-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstnetbuffer - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTNETBUFFER_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTNETBUFFER_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstnetbuffer-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstnetbuffer-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstnetbuffer - Win32 Release" +# Name "libgstnetbuffer - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\netbuffer\gstnetbuffer.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstnetbuffer.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\net\gstnetbuffer.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstogg.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstogg.dsp new file mode 100644 index 0000000..289097c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstogg.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="libgstogg" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstogg - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstogg.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstogg.mak" CFG="libgstogg - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstogg - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstogg - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstogg - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTOGG_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTOGG_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib glib-2.0.lib gobject-2.0.lib ogg.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstogg.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstogg - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTOGG_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTOGG_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib glib-2.0D.lib gobject-2.0D.lib ogg.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstogg.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstogg - Win32 Release" +# Name "libgstogg - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\ext\ogg\gstogg.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\ogg\gstoggaviparse.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\ogg\gstoggdemux.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\ogg\gstoggmux.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\ogg\gstoggparse.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\ogg\gstogmparse.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstpbutils.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstpbutils.dsp new file mode 100644 index 0000000..0e944b5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstpbutils.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="libgstpbutils" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstpbutils - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstpbutils.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstpbutils.mak" CFG="libgstpbutils - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstpbutils - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstpbutils - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstpbutils - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPBUTILS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPBUTILS_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstpbutils-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstpbutils-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstpbutils - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPBUTILS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPBUTILS_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstpbutils-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstpbutils-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstpbutils - Win32 Release" +# Name "libgstpbutils - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\pbutils\descriptions.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\pbutils\install-plugins.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstpbutils.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\pbutils\missing-plugins.c" +# End Source File +# Begin Source File + +SOURCE="..\common\pbutils-enumtypes.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\pbutils\pbutils.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstplaybin.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstplaybin.dsp new file mode 100644 index 0000000..722fc0a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstplaybin.dsp @@ -0,0 +1,151 @@ +# Microsoft Developer Studio Project File - Name="libgstplaybin" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstplaybin - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstplaybin.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstplaybin.mak" CFG="libgstplaybin - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstplaybin - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstplaybin - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstplaybin - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPLAYBIN_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPLAYBIN_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstplaybin.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstplaybin - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPLAYBIN_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTPLAYBIN_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstpbutils-0.10.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstplaybin.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstplaybin - Win32 Release" +# Name "libgstplaybin - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\playback\gstfactorylists.c +# End Source File +# Begin Source File + +SOURCE="..\..\gst\playback\gstplay-enum.c" +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstplayback.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstplaybasebin.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstplaybin.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstplaybin2.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gstplaysink.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gststreaminfo.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\playback\gststreamselector.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstriff.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstriff.dsp new file mode 100644 index 0000000..0b227ad --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstriff.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="libgstriff" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstriff - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstriff.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstriff.mak" CFG="libgstriff - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstriff - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstriff - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstriff - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRIFF_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRIFF_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstaudio-0.10.lib libgsttag-0.10.lib /nologo /dll /machine:I386 /out:"Release/libgstriff-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstriff-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstriff - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRIFF_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRIFF_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib libgstaudio-0.10.lib libgsttag-0.10.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstriff-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstriff-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstriff - Win32 Release" +# Name "libgstriff - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\common\libgstriff.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff-media.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff-read.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff-ids.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff-media.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\riff\riff-read.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtp.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtp.dsp new file mode 100644 index 0000000..0cfe87b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtp.dsp @@ -0,0 +1,155 @@ +# Microsoft Developer Studio Project File - Name="libgstrtp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstrtp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstrtp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstrtp.mak" CFG="libgstrtp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstrtp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstrtp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstrtp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTP_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstrtp-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstrtp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstrtp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTP_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstrtp-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstrtp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstrtp - Win32 Release" +# Name "libgstrtp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstbasertpaudiopayload.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstbasertpdepayload.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstbasertppayload.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstrtcpbuffer.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstrtpbuffer.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstrtppayloads.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstrtp.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstbasertpdepayload.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstbasertppayload.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtp\gstrtpbuffer.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtsp.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtsp.dsp new file mode 100644 index 0000000..d8fd438 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstrtsp.dsp @@ -0,0 +1,195 @@ +# Microsoft Developer Studio Project File - Name="libgstrtsp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstrtsp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstrtsp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstrtsp.mak" CFG="libgstrtsp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstrtsp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstrtsp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstrtsp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTSP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/rtsp" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTSP_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib Ws2_32.lib /nologo /dll /machine:I386 /out:"Release/libgstrtsp-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstrtsp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstrtsp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTSP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/rtsp" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTRTSP_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib Ws2_32.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstrtsp-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstrtsp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstrtsp - Win32 Release" +# Name "libgstrtsp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\common\gstrtsp-enumtypes.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtsp.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspbase64.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspconnection.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspdefs.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspextension.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspmessage.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtsprange.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtsptransport.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspurl.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstrtsp.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\rtsp-marshal.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspbase64.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspconnection.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspdefs.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspextension.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspmessage.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtsprange.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtsptransport.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\rtsp\gstrtspurl.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstsdp.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsdp.dsp new file mode 100644 index 0000000..0b76921 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsdp.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="libgstsdp" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstsdp - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstsdp.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstsdp.mak" CFG="libgstsdp - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstsdp - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstsdp - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstsdp - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSDP_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/rtsp" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSDP_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstreamer-0.10.lib libgstbase-0.10.lib Ws2_32.lib /nologo /dll /machine:I386 /out:"Release/libgstsdp-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstsdp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstsdp - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSDP_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /I "../../gst-libs/gst/rtsp" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSDP_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstreamer-0.10.lib libgstbase-0.10.lib Ws2_32.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstsdp-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstsdp-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstsdp - Win32 Release" +# Name "libgstsdp - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\sdp\gstsdpmessage.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstsdp.def +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstsinesrc.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsinesrc.dsp new file mode 100644 index 0000000..52386ed --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsinesrc.dsp @@ -0,0 +1,121 @@ +# Microsoft Developer Studio Project File - Name="libgstsinesrc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstsinesrc - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstsinesrc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstsinesrc.mak" CFG="libgstsinesrc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstsinesrc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstsinesrc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstsinesrc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSINESRC_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSINESRC_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstsinesrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstsinesrc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSINESRC_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSINESRC_EXPORTS" /D "HAVE_CONFIG_H" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstsinesrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstsinesrc - Win32 Release" +# Name "libgstsinesrc - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\sine\gstsinesrc.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\sine\gstsinesrc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstsubparse.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsubparse.dsp new file mode 100644 index 0000000..aac5e13 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstsubparse.dsp @@ -0,0 +1,123 @@ +# Microsoft Developer Studio Project File - Name="libgstsubparse" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstsubparse - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstsubparse.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstsubparse.mak" CFG="libgstsubparse - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstsubparse - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstsubparse - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstsubparse - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSUBPARSE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../../../gstreamer/win32/common" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSUBPARSE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstsubparse.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstsubparse - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSUBPARSE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTSUBPARSE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstsubparse.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstsubparse - Win32 Release" +# Name "libgstsubparse - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\subparse\gstsubparse.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\subparse\gstsubparse.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgsttag.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttag.dsp new file mode 100644 index 0000000..7e68ec6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttag.dsp @@ -0,0 +1,139 @@ +# Microsoft Developer Studio Project File - Name="libgsttag" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgsttag - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgsttag.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgsttag.mak" CFG="libgsttag - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgsttag - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgsttag - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgsttag - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTAGEDIT_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTAGEDIT_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgsttag-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgsttag-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgsttag - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTAGEDIT_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTAGEDIT_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgsttag-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgsttag-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgsttag - Win32 Release" +# Name "libgsttag - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\tag\gstid3tag.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\tag\gsttagdemux.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\tag\gstvorbistag.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgsttag.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\tag\tags.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Source File + +SOURCE=..\..\gst\ffmpegcolorspace\avcodec.h +# End Source File +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgsttheora.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttheora.dsp new file mode 100644 index 0000000..b36eed5 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttheora.dsp @@ -0,0 +1,131 @@ +# Microsoft Developer Studio Project File - Name="libgsttheora" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgsttheora - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgsttheora.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgsttheora.mak" CFG="libgsttheora - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgsttheora - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgsttheora - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgsttheora - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTHEORA_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTHEORA_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib theora_static.lib ogg.lib libgsttag-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgsttheora.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgsttheora - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTHEORA_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTHEORA_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgsttag-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib theora_static.lib ogg.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgsttheora.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgsttheora - Win32 Release" +# Name "libgsttheora - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\ext\theora\theora.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\theora\theoradec.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\theora\theoraenc.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\theora\theoraparse.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgsttypefindfunctions.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttypefindfunctions.dsp new file mode 100644 index 0000000..043d9de --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgsttypefindfunctions.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="libgsttypefindfunctions" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgsttypefindfunctions - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgsttypefindfunctions.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgsttypefindfunctions.mak" CFG="libgsttypefindfunctions - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgsttypefindfunctions - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgsttypefindfunctions - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgsttypefindfunctions - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTYPEFINDFUNCTIONS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTYPEFINDFUNCTIONS_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgsttypefindfunctions.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgsttypefindfunctions - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTYPEFINDFUNCTIONS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTTYPEFINDFUNCTIONS_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgsttypefindfunctions.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgsttypefindfunctions - Win32 Release" +# Name "libgsttypefindfunctions - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\typefind\gsttypefindfunctions.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideo.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideo.dsp new file mode 100644 index 0000000..2560e15 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideo.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="libgstvideo" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvideo - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvideo.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvideo.mak" CFG="libgstvideo - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvideo - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvideo - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvideo - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEO_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEO_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /out:"Release/libgstvideo-0.10.dll" /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvideo-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\bin +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvideo - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEO_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEO_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /out:"Debug/libgstvideo-0.10.dll" /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvideo-0.10.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\bin +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvideo - Win32 Release" +# Name "libgstvideo - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\gstvideofilter.c" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\gstvideosink.c" +# End Source File +# Begin Source File + +SOURCE=..\common\libgstvideo.def +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\video.c" +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\gstvideofilter.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\video.h" +# End Source File +# Begin Source File + +SOURCE="..\..\gst-libs\gst\video\videosink.h" +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideorate.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideorate.dsp new file mode 100644 index 0000000..17f3e42 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideorate.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="libgstvideorate" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvideorate - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvideorate.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvideorate.mak" CFG="libgstvideorate - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvideorate - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvideorate - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvideorate - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEORATE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEORATE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvideorate.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvideorate - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEORATE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEORATE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvideorate.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvideorate - Win32 Release" +# Name "libgstvideorate - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\videorate\gstvideorate.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideoscale.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideoscale.dsp new file mode 100644 index 0000000..ac69f82 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideoscale.dsp @@ -0,0 +1,143 @@ +# Microsoft Developer Studio Project File - Name="libgstvideoscale" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvideoscale - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvideoscale.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvideoscale.mak" CFG="libgstvideoscale - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvideoscale - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvideoscale - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvideoscale - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOSCALE_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOSCALE_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstvideo-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib liboil-0.3-0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvideoscale.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvideoscale - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOSCALE_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOSCALE_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstvideo-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib liboil-0.3-0.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvideoscale.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvideoscale - Win32 Release" +# Name "libgstvideoscale - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\videoscale\gstvideoscale.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videoscale\vs_4tap.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videoscale\vs_image.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videoscale\vs_scanline.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\videoscale\gstvideoscale.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videoscale\vs_image.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videoscale\vs_scanline.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideotestsrc.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideotestsrc.dsp new file mode 100644 index 0000000..cb4947d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvideotestsrc.dsp @@ -0,0 +1,131 @@ +# Microsoft Developer Studio Project File - Name="libgstvideotestsrc" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvideotestsrc - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvideotestsrc.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvideotestsrc.mak" CFG="libgstvideotestsrc - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvideotestsrc - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvideotestsrc - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvideotestsrc - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOTESTSRC_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../.." /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOTESTSRC_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0.lib gobject-2.0.lib liboil-0.3-0.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvideotestsrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvideotestsrc - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOTESTSRC_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer/win32" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVIDEOTESTSRC_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib glib-2.0D.lib gobject-2.0D.lib liboil-0.3-0.lib /nologo /dll /profile /debug /machine:I386 /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvideotestsrc.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvideotestsrc - Win32 Release" +# Name "libgstvideotestsrc - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\videotestsrc\gstvideotestsrc.c +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videotestsrc\videotestsrc.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\gst\videotestsrc\gstvideotestsrc.h +# End Source File +# Begin Source File + +SOURCE=..\..\gst\videotestsrc\videotestsrc.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvolume.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvolume.dsp new file mode 100644 index 0000000..7f6a0ef --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvolume.dsp @@ -0,0 +1,119 @@ +# Microsoft Developer Studio Project File - Name="libgstvolume" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvolume - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvolume.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvolume.mak" CFG="libgstvolume - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvolume - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvolume - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvolume - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVOLUME_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVOLUME_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 glib-2.0.lib gobject-2.0.lib libgstcontroller-0.10.lib libgstinterfaces-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib liboil-0.3-0.lib libgstaudio-0.10.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvolume.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvolume - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVOLUME_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVOLUME_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 glib-2.0D.lib gobject-2.0D.lib libgstcontroller-0.10.lib libgstinterfaces-0.10.lib libgstreamer-0.10.lib libgstbase-0.10.lib liboil-0.3-0.lib libgstaudio-0.10.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvolume.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvolume - Win32 Release" +# Name "libgstvolume - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\gst\volume\gstvolume.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs6/libgstvorbis.dsp b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvorbis.dsp new file mode 100644 index 0000000..954038e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs6/libgstvorbis.dsp @@ -0,0 +1,147 @@ +# Microsoft Developer Studio Project File - Name="libgstvorbis" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=libgstvorbis - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "libgstvorbis.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "libgstvorbis.mak" CFG="libgstvorbis - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "libgstvorbis - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "libgstvorbis - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "libgstvorbis - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVORBIS_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MD /W3 /O2 /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVORBIS_EXPORTS" /D "HAVE_CONFIG_H" /FD /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "NDEBUG" +# ADD RSC /l 0x40c /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib libgstaudio-0.10.lib glib-2.0.lib gobject-2.0.lib vorbis.lib ogg.lib /nologo /dll /machine:I386 /libpath:"../../../gstreamer/win32/vs6/release" /libpath:"./release" +# Begin Special Build Tool +TargetPath=.\Release\libgstvorbis.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\lib\gstreamer-0.10 +# End Special Build Tool + +!ELSEIF "$(CFG)" == "libgstvorbis - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVORBIS_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MDd /W3 /Gm /ZI /Od /I "../../gst-libs" /I "../../../gstreamer" /I "../common" /I "../../../gstreamer/libs" /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "LIBGSTVORBIS_EXPORTS" /D "HAVE_CONFIG_H" /FD /GZ /c +# SUBTRACT CPP /YX +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x40c /d "_DEBUG" +# ADD RSC /l 0x40c /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 libgstreamer-0.10.lib libgstbase-0.10.lib libgsttag-0.10.lib libgstaudio-0.10.lib glib-2.0D.lib gobject-2.0D.lib vorbis.lib ogg.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"../../../gstreamer/win32/vs6/debug" /libpath:"./debug" +# Begin Special Build Tool +TargetPath=.\Debug\libgstvorbis.dll +SOURCE="$(InputPath)" +PostBuild_Cmds=copy /Y $(TargetPath) c:\gstreamer\debug\lib\gstreamer-0.10 +# End Special Build Tool + +!ENDIF + +# Begin Target + +# Name "libgstvorbis - Win32 Release" +# Name "libgstvorbis - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbis.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisdec.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisenc.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisparse.c +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbistag.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisdec.h +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisenc.h +# End Source File +# Begin Source File + +SOURCE=..\..\ext\vorbis\vorbisparse.h +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/gst-plugins-base.sln b/gst-plugins-base-subtitles0.10/win32/vs7/gst-plugins-base.sln new file mode 100644 index 0000000..cd048c2 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/gst-plugins-base.sln @@ -0,0 +1,199 @@ +Microsoft Visual Studio Solution File, Format Version 8.00 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstriff", "libgstriff.vcproj", "{3D36330F-1F68-44F6-A712-803E819A3DCD}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudio", "libgstaudio.vcproj", "{BD17F145-422C-4EC0-A756-C7675A5626B2}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstadder", "libgstadder.vcproj", "{E54E1872-C90A-4FF8-A4F4-27C3F8750D44}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudioconvert", "libgstaudioconvert.vcproj", "{EA99F8DE-660D-42E9-B14D-08F34FA45AD1}" + ProjectSection(ProjectDependencies) = postProject + {BD17F145-422C-4EC0-A756-C7675A5626B2} = {BD17F145-422C-4EC0-A756-C7675A5626B2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudiorate", "libgstaudiorate.vcproj", "{C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudioresample", "libgstaudioresample.vcproj", "{0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudiotestsrc", "libgstaudiotestsrc.vcproj", "{B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstffmpegcolorspace", "libgstffmpegcolorspace.vcproj", "{BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstplaybin", "libgstplaybin.vcproj", "{7B296C12-D728-4CD8-8CF7-B8D7A433F85C}" + ProjectSection(ProjectDependencies) = postProject + {F7558C2A-C1BC-453C-8FDE-84F33DB73915} = {F7558C2A-C1BC-453C-8FDE-84F33DB73915} + {80270384-C551-471F-86C2-D80FE61D9883} = {80270384-C551-471F-86C2-D80FE61D9883} + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1} = {EA99F8DE-660D-42E9-B14D-08F34FA45AD1} + {0969BEF1-77F5-468F-9497-8470FDEC615A} = {0969BEF1-77F5-468F-9497-8470FDEC615A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttypefind", "libgsttypefind.vcproj", "{F7558C2A-C1BC-453C-8FDE-84F33DB73915}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideorate", "libgstvideorate.vcproj", "{84F3B76C-4733-4032-B51E-F8E71022AFE6}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideoscale", "libgstvideoscale.vcproj", "{557CB36F-7F92-4B43-973D-05C6BF0A6414}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideotestsrc", "libgstvideotestsrc.vcproj", "{7586DFA1-F847-4BEF-9105-724DD9F12C2A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvolume", "libgstvolume.vcproj", "{80270384-C551-471F-86C2-D80FE61D9883}" + ProjectSection(ProjectDependencies) = postProject + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4} = {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstdecodebin", "libgstdecodebin.vcproj", "{0969BEF1-77F5-468F-9497-8470FDEC615A}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstinterfaces", "libgstinterfaces.vcproj", "{CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstsubparse", "libgstsubparse.vcproj", "{C41E324E-03FD-4483-92B1-B50F6E3B6B82}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttcp", "libgsttcp.vcproj", "{40412A73-43D3-4F1F-9078-DBD76705767D}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvorbis", "libgstvorbis.vcproj", "{4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}" + ProjectSection(ProjectDependencies) = postProject + {BD17F145-422C-4EC0-A756-C7675A5626B2} = {BD17F145-422C-4EC0-A756-C7675A5626B2} + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} = {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstogg", "libgstogg.vcproj", "{51E1F9C4-091E-43A0-97C1-E1B68700A5AF}" + ProjectSection(ProjectDependencies) = postProject + {3D36330F-1F68-44F6-A712-803E819A3DCD} = {3D36330F-1F68-44F6-A712-803E819A3DCD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttheora", "libgsttheora.vcproj", "{AB7AD55A-A521-42F2-A953-623E5F059C1A}" + ProjectSection(ProjectDependencies) = postProject + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} = {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttag", "libgsttag.vcproj", "{626AF6BD-0AAB-4019-929A-2DB5CAD0419E}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideo", "libgstvideo.vcproj", "{1975AEE8-05C5-42DE-8A8B-620168F9C1C9}" + ProjectSection(ProjectDependencies) = postProject + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfiguration) = preSolution + Debug = Debug + Release = Release + EndGlobalSection + GlobalSection(ProjectConfiguration) = postSolution + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Debug.ActiveCfg = Debug|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Debug.Build.0 = Debug|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Release.ActiveCfg = Release|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Release.Build.0 = Release|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Debug.ActiveCfg = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Debug.Build.0 = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Release.ActiveCfg = Release|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Release.Build.0 = Release|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Debug.ActiveCfg = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Debug.Build.0 = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Release.ActiveCfg = Release|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Release.Build.0 = Release|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Debug.ActiveCfg = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Debug.Build.0 = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Release.ActiveCfg = Release|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Release.Build.0 = Release|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Debug.ActiveCfg = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Debug.Build.0 = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Release.ActiveCfg = Release|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Release.Build.0 = Release|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Debug.ActiveCfg = Debug|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Release.ActiveCfg = Release|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Debug.ActiveCfg = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Debug.Build.0 = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Release.ActiveCfg = Release|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Release.Build.0 = Release|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Debug.ActiveCfg = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Debug.Build.0 = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Release.ActiveCfg = Release|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Release.Build.0 = Release|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Debug.ActiveCfg = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Debug.Build.0 = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Release.ActiveCfg = Release|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Release.Build.0 = Release|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Debug.ActiveCfg = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Debug.Build.0 = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Release.ActiveCfg = Release|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Release.Build.0 = Release|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Debug.ActiveCfg = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Debug.Build.0 = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Release.ActiveCfg = Release|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Release.Build.0 = Release|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Debug.ActiveCfg = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Debug.Build.0 = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Release.ActiveCfg = Release|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Release.Build.0 = Release|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Debug.ActiveCfg = Debug|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Release.ActiveCfg = Release|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Debug.ActiveCfg = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Debug.Build.0 = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Release.ActiveCfg = Release|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Release.Build.0 = Release|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Debug.ActiveCfg = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Debug.Build.0 = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Release.ActiveCfg = Release|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Release.Build.0 = Release|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Debug.ActiveCfg = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Debug.Build.0 = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Release.ActiveCfg = Release|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Release.Build.0 = Release|Win32 + {C41E324E-03FD-4483-92B1-B50F6E3B6B82}.Debug.ActiveCfg = Debug|Win32 + {C41E324E-03FD-4483-92B1-B50F6E3B6B82}.Release.ActiveCfg = Release|Win32 + {40412A73-43D3-4F1F-9078-DBD76705767D}.Debug.ActiveCfg = Debug|Win32 + {40412A73-43D3-4F1F-9078-DBD76705767D}.Release.ActiveCfg = Release|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Debug.ActiveCfg = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Debug.Build.0 = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Release.ActiveCfg = Release|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Release.Build.0 = Release|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Debug.ActiveCfg = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Debug.Build.0 = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Release.ActiveCfg = Release|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Release.Build.0 = Release|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Debug.ActiveCfg = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Debug.Build.0 = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Release.ActiveCfg = Release|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Release.Build.0 = Release|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Debug.ActiveCfg = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Debug.Build.0 = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Release.ActiveCfg = Release|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Release.Build.0 = Release|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Debug.ActiveCfg = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Debug.Build.0 = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Release.ActiveCfg = Release|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Release.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + EndGlobalSection + GlobalSection(ExtensibilityAddIns) = postSolution + EndGlobalSection +EndGlobal diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstadder.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstadder.vcproj new file mode 100644 index 0000000..1d964a4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstadder.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudio.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudio.vcproj new file mode 100644 index 0000000..29e46c7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudio.vcproj @@ -0,0 +1,183 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioconvert.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioconvert.vcproj new file mode 100644 index 0000000..e630792 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioconvert.vcproj @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiorate.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiorate.vcproj new file mode 100644 index 0000000..27d93ab --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiorate.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioresample.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioresample.vcproj new file mode 100644 index 0000000..d07964f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudioresample.vcproj @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiotestsrc.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiotestsrc.vcproj new file mode 100644 index 0000000..a04af46 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstaudiotestsrc.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstdecodebin.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstdecodebin.vcproj new file mode 100644 index 0000000..ba64bce --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstdecodebin.vcproj @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstffmpegcolorspace.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstffmpegcolorspace.vcproj new file mode 100644 index 0000000..5b53b22 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstffmpegcolorspace.vcproj @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstinterfaces.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstinterfaces.vcproj new file mode 100644 index 0000000..cc2b9ff --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstinterfaces.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstogg.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstogg.vcproj new file mode 100644 index 0000000..bfd0cd9 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstogg.vcproj @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstplaybin.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstplaybin.vcproj new file mode 100644 index 0000000..753c8eb --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstplaybin.vcproj @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstriff.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstriff.vcproj new file mode 100644 index 0000000..4bf5a25 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstriff.vcproj @@ -0,0 +1,153 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstsubparse.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstsubparse.vcproj new file mode 100644 index 0000000..bce4752 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstsubparse.vcproj @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgsttag.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttag.vcproj new file mode 100644 index 0000000..32925d4 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttag.vcproj @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgsttcp.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttcp.vcproj new file mode 100644 index 0000000..2c9d3c8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttcp.vcproj @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgsttheora.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttheora.vcproj new file mode 100644 index 0000000..506c765 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttheora.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgsttypefind.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttypefind.vcproj new file mode 100644 index 0000000..41eafae --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgsttypefind.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideo.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideo.vcproj new file mode 100644 index 0000000..f7484d0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideo.vcproj @@ -0,0 +1,150 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideorate.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideorate.vcproj new file mode 100644 index 0000000..21fda00 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideorate.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideoscale.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideoscale.vcproj new file mode 100644 index 0000000..1838c8b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideoscale.vcproj @@ -0,0 +1,148 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideotestsrc.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideotestsrc.vcproj new file mode 100644 index 0000000..7f30c06 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvideotestsrc.vcproj @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvolume.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvolume.vcproj new file mode 100644 index 0000000..cf75202 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvolume.vcproj @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs7/libgstvorbis.vcproj b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvorbis.vcproj new file mode 100644 index 0000000..f7089a0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs7/libgstvorbis.vcproj @@ -0,0 +1,151 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/gst-plugins-base.sln b/gst-plugins-base-subtitles0.10/win32/vs8/gst-plugins-base.sln new file mode 100644 index 0000000..e7a593d --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/gst-plugins-base.sln @@ -0,0 +1,177 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual C++ Express 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstriff", "libgstriff.vcproj", "{3D36330F-1F68-44F6-A712-803E819A3DCD}" + ProjectSection(ProjectDependencies) = postProject + {BD17F145-422C-4EC0-A756-C7675A5626B2} = {BD17F145-422C-4EC0-A756-C7675A5626B2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudio", "libgstaudio.vcproj", "{BD17F145-422C-4EC0-A756-C7675A5626B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstadder", "libgstadder.vcproj", "{E54E1872-C90A-4FF8-A4F4-27C3F8750D44}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudioconvert", "libgstaudioconvert.vcproj", "{EA99F8DE-660D-42E9-B14D-08F34FA45AD1}" + ProjectSection(ProjectDependencies) = postProject + {BD17F145-422C-4EC0-A756-C7675A5626B2} = {BD17F145-422C-4EC0-A756-C7675A5626B2} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudiorate", "libgstaudiorate.vcproj", "{C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudioresample", "libgstaudioresample.vcproj", "{0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstaudiotestsrc", "libgstaudiotestsrc.vcproj", "{B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstffmpegcolorspace", "libgstffmpegcolorspace.vcproj", "{BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstplaybin", "libgstplaybin.vcproj", "{7B296C12-D728-4CD8-8CF7-B8D7A433F85C}" + ProjectSection(ProjectDependencies) = postProject + {F7558C2A-C1BC-453C-8FDE-84F33DB73915} = {F7558C2A-C1BC-453C-8FDE-84F33DB73915} + {80270384-C551-471F-86C2-D80FE61D9883} = {80270384-C551-471F-86C2-D80FE61D9883} + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1} = {EA99F8DE-660D-42E9-B14D-08F34FA45AD1} + {0969BEF1-77F5-468F-9497-8470FDEC615A} = {0969BEF1-77F5-468F-9497-8470FDEC615A} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttypefind", "libgsttypefind.vcproj", "{F7558C2A-C1BC-453C-8FDE-84F33DB73915}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideorate", "libgstvideorate.vcproj", "{84F3B76C-4733-4032-B51E-F8E71022AFE6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideoscale", "libgstvideoscale.vcproj", "{557CB36F-7F92-4B43-973D-05C6BF0A6414}" + ProjectSection(ProjectDependencies) = postProject + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9} = {1975AEE8-05C5-42DE-8A8B-620168F9C1C9} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideotestsrc", "libgstvideotestsrc.vcproj", "{7586DFA1-F847-4BEF-9105-724DD9F12C2A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvolume", "libgstvolume.vcproj", "{80270384-C551-471F-86C2-D80FE61D9883}" + ProjectSection(ProjectDependencies) = postProject + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4} = {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstdecodebin", "libgstdecodebin.vcproj", "{0969BEF1-77F5-468F-9497-8470FDEC615A}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstinterfaces", "libgstinterfaces.vcproj", "{CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstsubparse", "libgstsubparse.vcproj", "{C41E324E-03FD-4483-92B1-B50F6E3B6B82}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttcp", "libgsttcp.vcproj", "{40412A73-43D3-4F1F-9078-DBD76705767D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvorbis", "libgstvorbis.vcproj", "{4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}" + ProjectSection(ProjectDependencies) = postProject + {BD17F145-422C-4EC0-A756-C7675A5626B2} = {BD17F145-422C-4EC0-A756-C7675A5626B2} + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} = {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstogg", "libgstogg.vcproj", "{51E1F9C4-091E-43A0-97C1-E1B68700A5AF}" + ProjectSection(ProjectDependencies) = postProject + {3D36330F-1F68-44F6-A712-803E819A3DCD} = {3D36330F-1F68-44F6-A712-803E819A3DCD} + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} = {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttheora", "libgsttheora.vcproj", "{AB7AD55A-A521-42F2-A953-623E5F059C1A}" + ProjectSection(ProjectDependencies) = postProject + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} = {626AF6BD-0AAB-4019-929A-2DB5CAD0419E} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgsttag", "libgsttag.vcproj", "{626AF6BD-0AAB-4019-929A-2DB5CAD0419E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libgstvideo", "libgstvideo.vcproj", "{1975AEE8-05C5-42DE-8A8B-620168F9C1C9}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Debug|Win32.Build.0 = Debug|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Release|Win32.ActiveCfg = Debug|Win32 + {3D36330F-1F68-44F6-A712-803E819A3DCD}.Release|Win32.Build.0 = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Debug|Win32.ActiveCfg = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Debug|Win32.Build.0 = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Release|Win32.ActiveCfg = Debug|Win32 + {BD17F145-422C-4EC0-A756-C7675A5626B2}.Release|Win32.Build.0 = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Debug|Win32.ActiveCfg = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Debug|Win32.Build.0 = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Release|Win32.ActiveCfg = Debug|Win32 + {E54E1872-C90A-4FF8-A4F4-27C3F8750D44}.Release|Win32.Build.0 = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Debug|Win32.ActiveCfg = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Debug|Win32.Build.0 = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Release|Win32.ActiveCfg = Debug|Win32 + {EA99F8DE-660D-42E9-B14D-08F34FA45AD1}.Release|Win32.Build.0 = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Debug|Win32.ActiveCfg = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Debug|Win32.Build.0 = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Release|Win32.ActiveCfg = Debug|Win32 + {C51F9363-7DC1-40F7-84D3-C9D4FD67A3CA}.Release|Win32.Build.0 = Debug|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Debug|Win32.ActiveCfg = Debug|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Debug|Win32.Build.0 = Debug|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Release|Win32.ActiveCfg = Debug|Win32 + {0EE3173E-FCD3-4EC6-A28F-5AE5CE7196AC}.Release|Win32.Build.0 = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Debug|Win32.ActiveCfg = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Debug|Win32.Build.0 = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Release|Win32.ActiveCfg = Debug|Win32 + {B5CDFF9E-28E0-4915-8C3E-95EDAE2D9DE3}.Release|Win32.Build.0 = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Debug|Win32.ActiveCfg = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Debug|Win32.Build.0 = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Release|Win32.ActiveCfg = Debug|Win32 + {BE2600A9-5BEB-42D9-8F13-FD38FCF5B801}.Release|Win32.Build.0 = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Debug|Win32.ActiveCfg = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Debug|Win32.Build.0 = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Release|Win32.ActiveCfg = Debug|Win32 + {7B296C12-D728-4CD8-8CF7-B8D7A433F85C}.Release|Win32.Build.0 = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Debug|Win32.ActiveCfg = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Debug|Win32.Build.0 = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Release|Win32.ActiveCfg = Debug|Win32 + {F7558C2A-C1BC-453C-8FDE-84F33DB73915}.Release|Win32.Build.0 = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Debug|Win32.ActiveCfg = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Debug|Win32.Build.0 = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Release|Win32.ActiveCfg = Debug|Win32 + {84F3B76C-4733-4032-B51E-F8E71022AFE6}.Release|Win32.Build.0 = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Debug|Win32.ActiveCfg = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Debug|Win32.Build.0 = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Release|Win32.ActiveCfg = Debug|Win32 + {557CB36F-7F92-4B43-973D-05C6BF0A6414}.Release|Win32.Build.0 = Debug|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Debug|Win32.Build.0 = Debug|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Release|Win32.ActiveCfg = Debug|Win32 + {7586DFA1-F847-4BEF-9105-724DD9F12C2A}.Release|Win32.Build.0 = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Debug|Win32.ActiveCfg = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Debug|Win32.Build.0 = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Release|Win32.ActiveCfg = Debug|Win32 + {80270384-C551-471F-86C2-D80FE61D9883}.Release|Win32.Build.0 = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Debug|Win32.ActiveCfg = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Debug|Win32.Build.0 = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Release|Win32.ActiveCfg = Debug|Win32 + {0969BEF1-77F5-468F-9497-8470FDEC615A}.Release|Win32.Build.0 = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Debug|Win32.ActiveCfg = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Debug|Win32.Build.0 = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Release|Win32.ActiveCfg = Debug|Win32 + {CF1687EC-9097-4A86-B7FB-C1ECF9E27EA4}.Release|Win32.Build.0 = Debug|Win32 + {C41E324E-03FD-4483-92B1-B50F6E3B6B82}.Debug|Win32.ActiveCfg = Debug|Win32 + {C41E324E-03FD-4483-92B1-B50F6E3B6B82}.Release|Win32.ActiveCfg = Debug|Win32 + {40412A73-43D3-4F1F-9078-DBD76705767D}.Debug|Win32.ActiveCfg = Debug|Win32 + {40412A73-43D3-4F1F-9078-DBD76705767D}.Release|Win32.ActiveCfg = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Debug|Win32.ActiveCfg = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Debug|Win32.Build.0 = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Release|Win32.ActiveCfg = Debug|Win32 + {4F2E05FD-F87C-4325-8C2A-C1EEA21A483F}.Release|Win32.Build.0 = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Debug|Win32.ActiveCfg = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Debug|Win32.Build.0 = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Release|Win32.ActiveCfg = Debug|Win32 + {51E1F9C4-091E-43A0-97C1-E1B68700A5AF}.Release|Win32.Build.0 = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Debug|Win32.ActiveCfg = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Debug|Win32.Build.0 = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Release|Win32.ActiveCfg = Debug|Win32 + {AB7AD55A-A521-42F2-A953-623E5F059C1A}.Release|Win32.Build.0 = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Debug|Win32.ActiveCfg = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Debug|Win32.Build.0 = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Release|Win32.ActiveCfg = Debug|Win32 + {626AF6BD-0AAB-4019-929A-2DB5CAD0419E}.Release|Win32.Build.0 = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Debug|Win32.ActiveCfg = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Debug|Win32.Build.0 = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Release|Win32.ActiveCfg = Debug|Win32 + {1975AEE8-05C5-42DE-8A8B-620168F9C1C9}.Release|Win32.Build.0 = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstadder.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstadder.vcproj new file mode 100644 index 0000000..e582576 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstadder.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudio.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudio.vcproj new file mode 100644 index 0000000..6d320b0 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudio.vcproj @@ -0,0 +1,254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioconvert.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioconvert.vcproj new file mode 100644 index 0000000..037311c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioconvert.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiorate.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiorate.vcproj new file mode 100644 index 0000000..ac6acd7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiorate.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioresample.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioresample.vcproj new file mode 100644 index 0000000..0f9c62e --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudioresample.vcproj @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiotestsrc.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiotestsrc.vcproj new file mode 100644 index 0000000..9bcf568 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstaudiotestsrc.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstdecodebin.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstdecodebin.vcproj new file mode 100644 index 0000000..7f5332f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstdecodebin.vcproj @@ -0,0 +1,212 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstffmpegcolorspace.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstffmpegcolorspace.vcproj new file mode 100644 index 0000000..add0dc7 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstffmpegcolorspace.vcproj @@ -0,0 +1,230 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstinterfaces.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstinterfaces.vcproj new file mode 100644 index 0000000..10e8816 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstinterfaces.vcproj @@ -0,0 +1,264 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstogg.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstogg.vcproj new file mode 100644 index 0000000..f6b169b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstogg.vcproj @@ -0,0 +1,226 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstplaybin.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstplaybin.vcproj new file mode 100644 index 0000000..d490bf6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstplaybin.vcproj @@ -0,0 +1,224 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstriff.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstriff.vcproj new file mode 100644 index 0000000..232da11 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstriff.vcproj @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstsubparse.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstsubparse.vcproj new file mode 100644 index 0000000..3bc1c4f --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstsubparse.vcproj @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgsttag.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttag.vcproj new file mode 100644 index 0000000..878b10c --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttag.vcproj @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgsttcp.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttcp.vcproj new file mode 100644 index 0000000..6600730 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttcp.vcproj @@ -0,0 +1,232 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgsttheora.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttheora.vcproj new file mode 100644 index 0000000..c0b7dec --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttheora.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgsttypefind.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttypefind.vcproj new file mode 100644 index 0000000..1c19e41 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgsttypefind.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideo.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideo.vcproj new file mode 100644 index 0000000..4fa89d6 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideo.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideorate.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideorate.vcproj new file mode 100644 index 0000000..8bec130 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideorate.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideoscale.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideoscale.vcproj new file mode 100644 index 0000000..8f9477b --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideoscale.vcproj @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideotestsrc.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideotestsrc.vcproj new file mode 100644 index 0000000..b9d6d8a --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvideotestsrc.vcproj @@ -0,0 +1,210 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvolume.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvolume.vcproj new file mode 100644 index 0000000..02f6828 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvolume.vcproj @@ -0,0 +1,206 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gst-plugins-base-subtitles0.10/win32/vs8/libgstvorbis.vcproj b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvorbis.vcproj new file mode 100644 index 0000000..92c38f8 --- /dev/null +++ b/gst-plugins-base-subtitles0.10/win32/vs8/libgstvorbis.vcproj @@ -0,0 +1,222 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- 1.7.9.5